Split SDL_BlitScaled into SDL_UpperBlitScaled and SDL_LowerBlitScaled.
authorKen Rogoway <ken@rogoway.com>
Sun, 13 Mar 2011 22:38:41 -0500
changeset 54992b8e6d1e3817
parent 5498 ef1db08c40ac
child 5501 f48c1e0ca9ae
Split SDL_BlitScaled into SDL_UpperBlitScaled and SDL_LowerBlitScaled.
Fixed issue when calling SDL_BlitScaled() directly with src or dst rectangles that were out of bounds.
include/SDL_surface.h
src/video/SDL_surface.c
     1.1 --- a/include/SDL_surface.h	Tue Mar 15 23:26:22 2011 -0700
     1.2 +++ b/include/SDL_surface.h	Sun Mar 13 22:38:41 2011 -0500
     1.3 @@ -466,15 +466,23 @@
     1.4                                              SDL_Surface * dst,
     1.5                                              const SDL_Rect * dstrect);
     1.6  
     1.7 +#define SDL_BlitScaled SDL_UpperBlitScaled
     1.8 +
     1.9  /**
    1.10 - *  \brief Perform a fast, low quality, stretch blit between two surfaces of the
    1.11 - *         different pixel formats.
    1.12 - *  
    1.13 - *  \note This function calls SDL_SoftStretch or SDL_LowerBlit.
    1.14 + *  This is the public scaled blit function, SDL_BlitScaled(), and it performs
    1.15 + *  rectangle validation and clipping before passing it to SDL_LowerBlitScaled()
    1.16   */
    1.17 -extern DECLSPEC int SDLCALL SDL_BlitScaled
    1.18 +extern DECLSPEC int SDLCALL SDL_UpperBlitScaled
    1.19      (SDL_Surface * src, const SDL_Rect * srcrect,
    1.20 -    SDL_Surface * dst, const SDL_Rect * dstrect);
    1.21 +    SDL_Surface * dst, SDL_Rect * dstrect);
    1.22 +
    1.23 +/**
    1.24 + *  This is a semi-private blit function and it performs low-level surface
    1.25 + *  scaled blitting only.
    1.26 + */
    1.27 +extern DECLSPEC int SDLCALL SDL_LowerBlitScaled
    1.28 +    (SDL_Surface * src, SDL_Rect * srcrect,
    1.29 +    SDL_Surface * dst, SDL_Rect * dstrect);
    1.30  
    1.31  
    1.32  /* Ends C function definitions when using C++ */
     2.1 --- a/src/video/SDL_surface.c	Tue Mar 15 23:26:22 2011 -0700
     2.2 +++ b/src/video/SDL_surface.c	Sun Mar 13 22:38:41 2011 -0500
     2.3 @@ -602,12 +602,101 @@
     2.4      return 0;
     2.5  }
     2.6  
     2.7 -/*
     2.8 - * Scale and blit a surface 
     2.9 -*/
    2.10  int
    2.11 -SDL_BlitScaled(SDL_Surface * src, const SDL_Rect * srcrect,
    2.12 -               SDL_Surface * dst, const SDL_Rect * dstrect)
    2.13 +SDL_UpperBlitScaled(SDL_Surface * src, const SDL_Rect * srcrect,
    2.14 +              SDL_Surface * dst, SDL_Rect * dstrect)
    2.15 +{
    2.16 +    SDL_Rect final_src, final_dst, fulldst;
    2.17 +
    2.18 +    /* Make sure the surfaces aren't locked */
    2.19 +    if (!src || !dst) {
    2.20 +        SDL_SetError("SDL_UpperBlitScaled: passed a NULL surface");
    2.21 +        return (-1);
    2.22 +    }
    2.23 +    if (src->locked || dst->locked) {
    2.24 +        SDL_SetError("Surfaces must not be locked during blit");
    2.25 +        return (-1);
    2.26 +    }
    2.27 +
    2.28 +    /* If the destination rectangle is NULL, use the entire dest surface */
    2.29 +    if (dstrect == NULL) {
    2.30 +        fulldst.x = fulldst.y = 0;
    2.31 +        dstrect = &fulldst;
    2.32 +    }
    2.33 +
    2.34 +    /* clip the source rectangle to the source surface */
    2.35 +    if (srcrect) {
    2.36 +        int maxw, maxh;
    2.37 +
    2.38 +        final_src.x = srcrect->x;
    2.39 +        final_src.w = srcrect->w;
    2.40 +        if (final_src.x < 0) {
    2.41 +            final_src.w += final_src.x;
    2.42 +            final_src.x = 0;
    2.43 +        }
    2.44 +        maxw = src->w - final_src.x;
    2.45 +        if (maxw < final_src.w)
    2.46 +            final_src.w = maxw;
    2.47 +
    2.48 +        final_src.y = srcrect->y;
    2.49 +        final_src.h = srcrect->h;
    2.50 +        if (final_src.y < 0) {
    2.51 +            final_src.h += final_src.y;
    2.52 +            final_src.y = 0;
    2.53 +        }
    2.54 +        maxh = src->h - final_src.y;
    2.55 +        if (maxh < final_src.h)
    2.56 +            final_src.h = maxh;
    2.57 +
    2.58 +    } else {
    2.59 +        final_src.x = final_src.y = 0;
    2.60 +        final_src.w = src->w;
    2.61 +        final_src.h = src->h;
    2.62 +    }
    2.63 +
    2.64 +    /* clip the destination rectangle against the clip rectangle */
    2.65 +    if (dstrect) {
    2.66 +        int maxw, maxh;
    2.67 +
    2.68 +        final_dst.x = dstrect->x;
    2.69 +        final_dst.w = dstrect->w;
    2.70 +        if (final_dst.x < 0) {
    2.71 +            final_dst.w += final_dst.x;
    2.72 +            final_dst.x = 0;
    2.73 +        }
    2.74 +        maxw = dst->w - final_dst.x;
    2.75 +        if (maxw < final_dst.w)
    2.76 +            final_dst.w = maxw;
    2.77 +
    2.78 +        final_dst.y = dstrect->y;
    2.79 +        final_dst.h = dstrect->h;
    2.80 +        if (final_dst.y < 0) {
    2.81 +            final_dst.h += final_dst.y;
    2.82 +            final_dst.y = 0;
    2.83 +        }
    2.84 +        maxh = dst->h - final_dst.y;
    2.85 +        if (maxh < final_dst.h)
    2.86 +            final_dst.h = maxh;
    2.87 +    } else {
    2.88 +        final_dst.x = final_dst.y = 0;
    2.89 +        final_dst.w = dst->w;
    2.90 +        final_dst.h = dst->h;
    2.91 +    }
    2.92 +
    2.93 +    if (final_dst.w > 0 && final_dst.h > 0) {
    2.94 +        return SDL_LowerBlitScaled(src, &final_src, dst, &final_dst);
    2.95 +    }
    2.96 +
    2.97 +    return 0;
    2.98 +}
    2.99 +
   2.100 +/**
   2.101 + *  This is a semi-private blit function and it performs low-level surface
   2.102 + *  scaled blitting only.
   2.103 + */
   2.104 +int
   2.105 +SDL_LowerBlitScaled(SDL_Surface * src, SDL_Rect * srcrect,
   2.106 +                SDL_Surface * dst, SDL_Rect * dstrect)
   2.107  {
   2.108      /* Save off the original dst width, height */
   2.109      int dstW = dstrect->w;
   2.110 @@ -618,11 +707,6 @@
   2.111      /* Clip the dst surface to the dstrect */
   2.112      SDL_SetClipRect( dst, &final_dst );
   2.113  
   2.114 -    /* If the dest was clipped to a zero sized rect then exit */
   2.115 -    if ( dst->clip_rect.w <= 0 || dst->clip_rect.h <= 0 ) {
   2.116 -        return -1;
   2.117 -    }
   2.118 -
   2.119      /* Did the dst width change? */
   2.120      if ( dstW != dst->clip_rect.w ) {
   2.121          /* scale the src width appropriately */