226 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			226 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			C
		
	
	
	
| /*
 | |
|  * SDL_zoom_template - surface scaling
 | |
|  * 
 | |
|  * Copyright (c) 2009 Citrix Systems, Inc.
 | |
|  *
 | |
|  * Derived from: SDL_rotozoom,  LGPL (c) A. Schiffler from the SDL_gfx library.
 | |
|  * Modifications by Stefano Stabellini.
 | |
|  *
 | |
|  * This work is licensed under the terms of the GNU GPL version 2.
 | |
|  * See the COPYING file in the top-level directory.
 | |
|  *
 | |
|  */
 | |
| 
 | |
| #if BPP == 16
 | |
| #define SDL_TYPE Uint16
 | |
| #elif BPP == 32
 | |
| #define SDL_TYPE Uint32
 | |
| #else
 | |
| #error unsupport depth
 | |
| #endif
 | |
| 
 | |
| /*  
 | |
|  *  Simple helper functions to make the code looks nicer
 | |
|  *
 | |
|  *  Assume spf = source SDL_PixelFormat
 | |
|  *         dpf = dest SDL_PixelFormat
 | |
|  *
 | |
|  */
 | |
| #define getRed(color)   (((color) & spf->Rmask) >> spf->Rshift)
 | |
| #define getGreen(color) (((color) & spf->Gmask) >> spf->Gshift)
 | |
| #define getBlue(color)  (((color) & spf->Bmask) >> spf->Bshift)
 | |
| #define getAlpha(color) (((color) & spf->Amask) >> spf->Ashift)
 | |
| 
 | |
| #define setRed(r, pcolor) do { \
 | |
|     *pcolor = ((*pcolor) & (~(dpf->Rmask))) + \
 | |
|               (((r) & (dpf->Rmask >> dpf->Rshift)) << dpf->Rshift); \
 | |
| } while (0);
 | |
| 
 | |
| #define setGreen(g, pcolor) do { \
 | |
|     *pcolor = ((*pcolor) & (~(dpf->Gmask))) + \
 | |
|               (((g) & (dpf->Gmask >> dpf->Gshift)) << dpf->Gshift); \
 | |
| } while (0);
 | |
| 
 | |
| #define setBlue(b, pcolor) do { \
 | |
|     *pcolor = ((*pcolor) & (~(dpf->Bmask))) + \
 | |
|               (((b) & (dpf->Bmask >> dpf->Bshift)) << dpf->Bshift); \
 | |
| } while (0);
 | |
| 
 | |
| #define setAlpha(a, pcolor) do { \
 | |
|     *pcolor = ((*pcolor) & (~(dpf->Amask))) + \
 | |
|               (((a) & (dpf->Amask >> dpf->Ashift)) << dpf->Ashift); \
 | |
| } while (0);
 | |
| 
 | |
| static int glue(sdl_zoom_rgb, BPP)(SDL_Surface *src, SDL_Surface *dst, int smooth,
 | |
|                                    SDL_Rect *dst_rect)
 | |
| {
 | |
|     int x, y, sx, sy, *sax, *say, *csax, *csay, csx, csy, ex, ey, t1, t2, sstep, sstep_jump;
 | |
|     SDL_TYPE *c00, *c01, *c10, *c11, *sp, *csp, *dp;
 | |
|     int d_gap;
 | |
|     SDL_PixelFormat *spf = src->format;
 | |
|     SDL_PixelFormat *dpf = dst->format;
 | |
| 
 | |
|     if (smooth) { 
 | |
|         /* For interpolation: assume source dimension is one pixel.
 | |
|          * Smaller here to avoid overflow on right and bottom edge.
 | |
|          */
 | |
|         sx = (int) (65536.0 * (float) (src->w - 1) / (float) dst->w);
 | |
|         sy = (int) (65536.0 * (float) (src->h - 1) / (float) dst->h);
 | |
|     } else {
 | |
|         sx = (int) (65536.0 * (float) src->w / (float) dst->w);
 | |
|         sy = (int) (65536.0 * (float) src->h / (float) dst->h);
 | |
|     }
 | |
| 
 | |
|     if ((sax = (int *) malloc((dst->w + 1) * sizeof(Uint32))) == NULL) {
 | |
|         return (-1);
 | |
|     }
 | |
|     if ((say = (int *) malloc((dst->h + 1) * sizeof(Uint32))) == NULL) {
 | |
|         free(sax);
 | |
|         return (-1);
 | |
|     }
 | |
| 
 | |
|     sp = csp = (SDL_TYPE *) src->pixels;
 | |
|     dp = (SDL_TYPE *) (dst->pixels + dst_rect->y * dst->pitch +
 | |
|                        dst_rect->x * dst->format->BytesPerPixel);
 | |
| 
 | |
|     csx = 0;
 | |
|     csax = sax;
 | |
|     for (x = 0; x <= dst->w; x++) {
 | |
|         *csax = csx;
 | |
|         csax++;
 | |
|         csx &= 0xffff;
 | |
|         csx += sx;
 | |
|     }
 | |
|     csy = 0;
 | |
|     csay = say;
 | |
|     for (y = 0; y <= dst->h; y++) {
 | |
|         *csay = csy;
 | |
|         csay++;
 | |
|         csy &= 0xffff;
 | |
|         csy += sy;
 | |
|     }
 | |
| 
 | |
|     d_gap = dst->pitch - dst_rect->w * dst->format->BytesPerPixel;
 | |
| 
 | |
|     if (smooth) {
 | |
|         csay = say;
 | |
|         for (y = 0; y < dst_rect->y; y++) {
 | |
|             csay++;
 | |
|             sstep = (*csay >> 16) * src->pitch;
 | |
|             csp = (SDL_TYPE *) ((Uint8 *) csp + sstep);
 | |
|         }
 | |
| 
 | |
|         /* Calculate sstep_jump */
 | |
|         csax = sax; 
 | |
|         sstep_jump = 0;
 | |
|         for (x = 0; x < dst_rect->x; x++) {
 | |
|             csax++; 
 | |
|             sstep = (*csax >> 16);
 | |
|             sstep_jump += sstep;
 | |
|         }
 | |
| 
 | |
|         for (y = 0; y < dst_rect->h ; y++) {
 | |
|             /* Setup colour source pointers */
 | |
|             c00 = csp + sstep_jump;
 | |
|             c01 = c00 + 1;
 | |
|             c10 = (SDL_TYPE *) ((Uint8 *) csp + src->pitch) + sstep_jump;
 | |
|             c11 = c10 + 1;
 | |
|             csax = sax + dst_rect->x; 
 | |
| 
 | |
|             for (x = 0; x < dst_rect->w; x++) {
 | |
| 
 | |
|                 /* Interpolate colours */
 | |
|                 ex = (*csax & 0xffff);
 | |
|                 ey = (*csay & 0xffff);
 | |
|                 t1 = ((((getRed(*c01) - getRed(*c00)) * ex) >> 16) +
 | |
|                      getRed(*c00)) & (dpf->Rmask >> dpf->Rshift);
 | |
|                 t2 = ((((getRed(*c11) - getRed(*c10)) * ex) >> 16) +
 | |
|                      getRed(*c10)) & (dpf->Rmask >> dpf->Rshift);
 | |
|                 setRed((((t2 - t1) * ey) >> 16) + t1, dp);
 | |
|                 t1 = ((((getGreen(*c01) - getGreen(*c00)) * ex) >> 16) +
 | |
|                      getGreen(*c00)) & (dpf->Gmask >> dpf->Gshift);
 | |
|                 t2 = ((((getGreen(*c11) - getGreen(*c10)) * ex) >> 16) +
 | |
|                      getGreen(*c10)) & (dpf->Gmask >> dpf->Gshift);
 | |
|                 setGreen((((t2 - t1) * ey) >> 16) + t1, dp);
 | |
|                 t1 = ((((getBlue(*c01) - getBlue(*c00)) * ex) >> 16) +
 | |
|                      getBlue(*c00)) & (dpf->Bmask >> dpf->Bshift);
 | |
|                 t2 = ((((getBlue(*c11) - getBlue(*c10)) * ex) >> 16) +
 | |
|                      getBlue(*c10)) & (dpf->Bmask >> dpf->Bshift);
 | |
|                 setBlue((((t2 - t1) * ey) >> 16) + t1, dp);
 | |
|                 t1 = ((((getAlpha(*c01) - getAlpha(*c00)) * ex) >> 16) +
 | |
|                      getAlpha(*c00)) & (dpf->Amask >> dpf->Ashift);
 | |
|                 t2 = ((((getAlpha(*c11) - getAlpha(*c10)) * ex) >> 16) +
 | |
|                      getAlpha(*c10)) & (dpf->Amask >> dpf->Ashift);
 | |
|                 setAlpha((((t2 - t1) * ey) >> 16) + t1, dp); 
 | |
| 
 | |
|                 /* Advance source pointers */
 | |
|                 csax++; 
 | |
|                 sstep = (*csax >> 16);
 | |
|                 c00 += sstep;
 | |
|                 c01 += sstep;
 | |
|                 c10 += sstep;
 | |
|                 c11 += sstep;
 | |
|                 /* Advance destination pointer */
 | |
|                 dp++;
 | |
|             }
 | |
|             /* Advance source pointer */
 | |
|             csay++;
 | |
|             csp = (SDL_TYPE *) ((Uint8 *) csp + (*csay >> 16) * src->pitch);
 | |
|             /* Advance destination pointers */
 | |
|             dp = (SDL_TYPE *) ((Uint8 *) dp + d_gap);
 | |
|         }
 | |
| 
 | |
| 
 | |
|     } else {
 | |
|         csay = say;
 | |
| 
 | |
|         for (y = 0; y < dst_rect->y; y++) {
 | |
|             csay++;
 | |
|             sstep = (*csay >> 16) * src->pitch;
 | |
|             csp = (SDL_TYPE *) ((Uint8 *) csp + sstep);
 | |
|         }
 | |
| 
 | |
|         /* Calculate sstep_jump */
 | |
|         csax = sax; 
 | |
|         sstep_jump = 0;
 | |
|         for (x = 0; x < dst_rect->x; x++) {
 | |
|             csax++; 
 | |
|             sstep = (*csax >> 16);
 | |
|             sstep_jump += sstep;
 | |
|         }
 | |
| 
 | |
|         for (y = 0 ; y < dst_rect->h ; y++) {
 | |
|             sp = csp + sstep_jump;
 | |
|             csax = sax + dst_rect->x;
 | |
| 
 | |
|             for (x = 0; x < dst_rect->w; x++) {
 | |
| 
 | |
|                 /* Draw */
 | |
|                 *dp = *sp;
 | |
| 
 | |
|                 /* Advance source pointers */
 | |
|                 csax++;
 | |
|                 sstep = (*csax >> 16);
 | |
|                 sp += sstep;
 | |
| 
 | |
|                 /* Advance destination pointer */
 | |
|                 dp++;
 | |
|             }
 | |
|             /* Advance source pointers */
 | |
|             csay++;
 | |
|             sstep = (*csay >> 16) * src->pitch;
 | |
|             csp = (SDL_TYPE *) ((Uint8 *) csp + sstep);
 | |
| 
 | |
|             /* Advance destination pointer */
 | |
|             dp = (SDL_TYPE *) ((Uint8 *) dp + d_gap);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     free(sax);
 | |
|     free(say);
 | |
|     return (0);
 | |
| }
 | |
| 
 | |
| #undef SDL_TYPE
 | |
| 
 |