int SDL_UpperBlitScaled(SDL_Surface * src, const SDL_Rect * srcrect, SDL_Surface * dst, SDL_Rect * dstrect) { SDL_Rect final_src, final_dst, fulldst; /* Make sure the surfaces aren't locked */ if (!src || !dst) { return SDL_SetError("SDL_UpperBlitScaled: passed a NULL surface"); } if (src->locked || dst->locked) { return SDL_SetError("Surfaces must not be locked during blit"); } /* If the destination rectangle is NULL, use the entire dest surface */ if (dstrect == NULL) { fulldst.x = fulldst.y = 0; fulldst.w = dst->w; fulldst.h = dst->h; dstrect = &fulldst; } /* clip the source rectangle to the source surface */ if (srcrect) { int maxw, maxh; final_src.x = srcrect->x; final_src.w = srcrect->w; if (final_src.x < 0) { final_src.w += final_src.x; final_src.x = 0; } maxw = src->w - final_src.x; if (maxw < final_src.w) final_src.w = maxw; final_src.y = srcrect->y; final_src.h = srcrect->h; if (final_src.y < 0) { final_src.h += final_src.y; final_src.y = 0; } maxh = src->h - final_src.y; if (maxh < final_src.h) final_src.h = maxh; } else { final_src.x = final_src.y = 0; final_src.w = src->w; final_src.h = src->h; } /* clip the destination rectangle against the clip rectangle */ if (dstrect) { int maxw, maxh; final_dst.x = dstrect->x; final_dst.w = dstrect->w; if (final_dst.x < 0) { final_dst.w += final_dst.x; final_dst.x = 0; } maxw = dst->w - final_dst.x; if (maxw < final_dst.w) final_dst.w = maxw; final_dst.y = dstrect->y; final_dst.h = dstrect->h; if (final_dst.y < 0) { final_dst.h += final_dst.y; final_dst.y = 0; } maxh = dst->h - final_dst.y; if (maxh < final_dst.h) final_dst.h = maxh; } else { final_dst.x = final_dst.y = 0; final_dst.w = dst->w; final_dst.h = dst->h; } if (final_dst.w > 0 && final_dst.h > 0) { return SDL_LowerBlitScaled(src, &final_src, dst, &final_dst); } return 0; }
int SDL_UpperBlitScaled(SDL_Surface * src, const SDL_Rect * srcrect, SDL_Surface * dst, SDL_Rect * dstrect) { double src_x0, src_y0, src_x1, src_y1; double dst_x0, dst_y0, dst_x1, dst_y1; SDL_Rect final_src, final_dst; double scaling_w, scaling_h; int src_w, src_h; int dst_w, dst_h; /* Make sure the surfaces aren't locked */ if (!src || !dst) { return SDL_SetError("SDL_UpperBlitScaled: passed a NULL surface"); } if (src->locked || dst->locked) { return SDL_SetError("Surfaces must not be locked during blit"); } if (NULL == srcrect) { src_w = src->w; src_h = src->h; } else { src_w = srcrect->w; src_h = srcrect->h; } if (NULL == dstrect) { dst_w = dst->w; dst_h = dst->h; } else { dst_w = dstrect->w; dst_h = dstrect->h; } if (dst_w == src_w && dst_h == src_h) { /* No scaling, defer to regular blit */ return SDL_BlitSurface(src, srcrect, dst, dstrect); } scaling_w = (double)dst_w / src_w; scaling_h = (double)dst_h / src_h; if (NULL == dstrect) { dst_x0 = 0; dst_y0 = 0; dst_x1 = dst_w - 1; dst_y1 = dst_h - 1; } else { dst_x0 = dstrect->x; dst_y0 = dstrect->y; dst_x1 = dst_x0 + dst_w - 1; dst_y1 = dst_y0 + dst_h - 1; } if (NULL == srcrect) { src_x0 = 0; src_y0 = 0; src_x1 = src_w - 1; src_y1 = src_h - 1; } else { src_x0 = srcrect->x; src_y0 = srcrect->y; src_x1 = src_x0 + src_w - 1; src_y1 = src_y0 + src_h - 1; /* Clip source rectangle to the source surface */ if (src_x0 < 0) { dst_x0 -= src_x0 * scaling_w; src_x0 = 0; } if (src_x1 >= src->w) { dst_x1 -= (src_x1 - src->w + 1) * scaling_w; src_x1 = src->w - 1; } if (src_y0 < 0) { dst_y0 -= src_y0 * scaling_h; src_y0 = 0; } if (src_y1 >= src->h) { dst_y1 -= (src_y1 - src->h + 1) * scaling_h; src_y1 = src->h - 1; } } /* Clip destination rectangle to the clip rectangle */ /* Translate to clip space for easier calculations */ dst_x0 -= dst->clip_rect.x; dst_x1 -= dst->clip_rect.x; dst_y0 -= dst->clip_rect.y; dst_y1 -= dst->clip_rect.y; if (dst_x0 < 0) { src_x0 -= dst_x0 / scaling_w; dst_x0 = 0; } if (dst_x1 >= dst->clip_rect.w) { src_x1 -= (dst_x1 - dst->clip_rect.w + 1) / scaling_w; dst_x1 = dst->clip_rect.w - 1; } if (dst_y0 < 0) { src_y0 -= dst_y0 / scaling_h; dst_y0 = 0; } if (dst_y1 >= dst->clip_rect.h) { src_y1 -= (dst_y1 - dst->clip_rect.h + 1) / scaling_h; dst_y1 = dst->clip_rect.h - 1; } /* Translate back to surface coordinates */ dst_x0 += dst->clip_rect.x; dst_x1 += dst->clip_rect.x; dst_y0 += dst->clip_rect.y; dst_y1 += dst->clip_rect.y; final_src.x = (int)SDL_floor(src_x0 + 0.5); final_src.y = (int)SDL_floor(src_y0 + 0.5); final_src.w = (int)SDL_floor(src_x1 - src_x0 + 1.5); final_src.h = (int)SDL_floor(src_y1 - src_y0 + 1.5); final_dst.x = (int)SDL_floor(dst_x0 + 0.5); final_dst.y = (int)SDL_floor(dst_y0 + 0.5); final_dst.w = (int)SDL_floor(dst_x1 - dst_x0 + 1.5); final_dst.h = (int)SDL_floor(dst_y1 - dst_y0 + 1.5); if (final_dst.w < 0) final_dst.w = 0; if (final_dst.h < 0) final_dst.h = 0; if (dstrect) *dstrect = final_dst; if (final_dst.w == 0 || final_dst.h == 0 || final_src.w <= 0 || final_src.h <= 0) { /* No-op. */ return 0; } return SDL_LowerBlitScaled(src, &final_src, dst, &final_dst); }