| /* |
| * 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 |
| |