qemu/sdl_zoom_template.h
<<
>>
Prefs
   1/*
   2 * SDL_zoom_template - surface scaling
   3 * 
   4 * Copyright (c) 2009 Citrix Systems, Inc.
   5 *
   6 * Derived from: SDL_rotozoom,  LGPL (c) A. Schiffler from the SDL_gfx library.
   7 * Modifications by Stefano Stabellini.
   8 *
   9 * This work is licensed under the terms of the GNU GPL version 2.
  10 * See the COPYING file in the top-level directory.
  11 *
  12 */
  13
  14#if BPP == 16
  15#define SDL_TYPE Uint16
  16#elif BPP == 32
  17#define SDL_TYPE Uint32
  18#else
  19#error unsupport depth
  20#endif
  21
  22/*  
  23 *  Simple helper functions to make the code looks nicer
  24 *
  25 *  Assume spf = source SDL_PixelFormat
  26 *         dpf = dest SDL_PixelFormat
  27 *
  28 */
  29#define getRed(color)   (((color) & spf->Rmask) >> spf->Rshift)
  30#define getGreen(color) (((color) & spf->Gmask) >> spf->Gshift)
  31#define getBlue(color)  (((color) & spf->Bmask) >> spf->Bshift)
  32#define getAlpha(color) (((color) & spf->Amask) >> spf->Ashift)
  33
  34#define setRed(r, pcolor) do { \
  35    *pcolor = ((*pcolor) & (~(dpf->Rmask))) + \
  36              (((r) & (dpf->Rmask >> dpf->Rshift)) << dpf->Rshift); \
  37} while (0);
  38
  39#define setGreen(g, pcolor) do { \
  40    *pcolor = ((*pcolor) & (~(dpf->Gmask))) + \
  41              (((g) & (dpf->Gmask >> dpf->Gshift)) << dpf->Gshift); \
  42} while (0);
  43
  44#define setBlue(b, pcolor) do { \
  45    *pcolor = ((*pcolor) & (~(dpf->Bmask))) + \
  46              (((b) & (dpf->Bmask >> dpf->Bshift)) << dpf->Bshift); \
  47} while (0);
  48
  49#define setAlpha(a, pcolor) do { \
  50    *pcolor = ((*pcolor) & (~(dpf->Amask))) + \
  51              (((a) & (dpf->Amask >> dpf->Ashift)) << dpf->Ashift); \
  52} while (0);
  53
  54static int glue(sdl_zoom_rgb, BPP)(SDL_Surface *src, SDL_Surface *dst, int smooth,
  55                                   SDL_Rect *dst_rect)
  56{
  57    int x, y, sx, sy, *sax, *say, *csax, *csay, csx, csy, ex, ey, t1, t2, sstep, sstep_jump;
  58    SDL_TYPE *c00, *c01, *c10, *c11, *sp, *csp, *dp;
  59    int d_gap;
  60    SDL_PixelFormat *spf = src->format;
  61    SDL_PixelFormat *dpf = dst->format;
  62
  63    if (smooth) { 
  64        /* For interpolation: assume source dimension is one pixel.
  65         * Smaller here to avoid overflow on right and bottom edge.
  66         */
  67        sx = (int) (65536.0 * (float) (src->w - 1) / (float) dst->w);
  68        sy = (int) (65536.0 * (float) (src->h - 1) / (float) dst->h);
  69    } else {
  70        sx = (int) (65536.0 * (float) src->w / (float) dst->w);
  71        sy = (int) (65536.0 * (float) src->h / (float) dst->h);
  72    }
  73
  74    if ((sax = (int *) malloc((dst->w + 1) * sizeof(Uint32))) == NULL) {
  75        return (-1);
  76    }
  77    if ((say = (int *) malloc((dst->h + 1) * sizeof(Uint32))) == NULL) {
  78        free(sax);
  79        return (-1);
  80    }
  81
  82    sp = csp = (SDL_TYPE *) src->pixels;
  83    dp = (SDL_TYPE *) (dst->pixels + dst_rect->y * dst->pitch +
  84                       dst_rect->x * dst->format->BytesPerPixel);
  85
  86    csx = 0;
  87    csax = sax;
  88    for (x = 0; x <= dst->w; x++) {
  89        *csax = csx;
  90        csax++;
  91        csx &= 0xffff;
  92        csx += sx;
  93    }
  94    csy = 0;
  95    csay = say;
  96    for (y = 0; y <= dst->h; y++) {
  97        *csay = csy;
  98        csay++;
  99        csy &= 0xffff;
 100        csy += sy;
 101    }
 102
 103    d_gap = dst->pitch - dst_rect->w * dst->format->BytesPerPixel;
 104
 105    if (smooth) {
 106        csay = say;
 107        for (y = 0; y < dst_rect->y; y++) {
 108            csay++;
 109            sstep = (*csay >> 16) * src->pitch;
 110            csp = (SDL_TYPE *) ((Uint8 *) csp + sstep);
 111        }
 112
 113        /* Calculate sstep_jump */
 114        csax = sax; 
 115        sstep_jump = 0;
 116        for (x = 0; x < dst_rect->x; x++) {
 117            csax++; 
 118            sstep = (*csax >> 16);
 119            sstep_jump += sstep;
 120        }
 121
 122        for (y = 0; y < dst_rect->h ; y++) {
 123            /* Setup colour source pointers */
 124            c00 = csp + sstep_jump;
 125            c01 = c00 + 1;
 126            c10 = (SDL_TYPE *) ((Uint8 *) csp + src->pitch) + sstep_jump;
 127            c11 = c10 + 1;
 128            csax = sax + dst_rect->x; 
 129
 130            for (x = 0; x < dst_rect->w; x++) {
 131
 132                /* Interpolate colours */
 133                ex = (*csax & 0xffff);
 134                ey = (*csay & 0xffff);
 135                t1 = ((((getRed(*c01) - getRed(*c00)) * ex) >> 16) +
 136                     getRed(*c00)) & (dpf->Rmask >> dpf->Rshift);
 137                t2 = ((((getRed(*c11) - getRed(*c10)) * ex) >> 16) +
 138                     getRed(*c10)) & (dpf->Rmask >> dpf->Rshift);
 139                setRed((((t2 - t1) * ey) >> 16) + t1, dp);
 140                t1 = ((((getGreen(*c01) - getGreen(*c00)) * ex) >> 16) +
 141                     getGreen(*c00)) & (dpf->Gmask >> dpf->Gshift);
 142                t2 = ((((getGreen(*c11) - getGreen(*c10)) * ex) >> 16) +
 143                     getGreen(*c10)) & (dpf->Gmask >> dpf->Gshift);
 144                setGreen((((t2 - t1) * ey) >> 16) + t1, dp);
 145                t1 = ((((getBlue(*c01) - getBlue(*c00)) * ex) >> 16) +
 146                     getBlue(*c00)) & (dpf->Bmask >> dpf->Bshift);
 147                t2 = ((((getBlue(*c11) - getBlue(*c10)) * ex) >> 16) +
 148                     getBlue(*c10)) & (dpf->Bmask >> dpf->Bshift);
 149                setBlue((((t2 - t1) * ey) >> 16) + t1, dp);
 150                t1 = ((((getAlpha(*c01) - getAlpha(*c00)) * ex) >> 16) +
 151                     getAlpha(*c00)) & (dpf->Amask >> dpf->Ashift);
 152                t2 = ((((getAlpha(*c11) - getAlpha(*c10)) * ex) >> 16) +
 153                     getAlpha(*c10)) & (dpf->Amask >> dpf->Ashift);
 154                setAlpha((((t2 - t1) * ey) >> 16) + t1, dp); 
 155
 156                /* Advance source pointers */
 157                csax++; 
 158                sstep = (*csax >> 16);
 159                c00 += sstep;
 160                c01 += sstep;
 161                c10 += sstep;
 162                c11 += sstep;
 163                /* Advance destination pointer */
 164                dp++;
 165            }
 166            /* Advance source pointer */
 167            csay++;
 168            csp = (SDL_TYPE *) ((Uint8 *) csp + (*csay >> 16) * src->pitch);
 169            /* Advance destination pointers */
 170            dp = (SDL_TYPE *) ((Uint8 *) dp + d_gap);
 171        }
 172
 173
 174    } else {
 175        csay = say;
 176
 177        for (y = 0; y < dst_rect->y; y++) {
 178            csay++;
 179            sstep = (*csay >> 16) * src->pitch;
 180            csp = (SDL_TYPE *) ((Uint8 *) csp + sstep);
 181        }
 182
 183        /* Calculate sstep_jump */
 184        csax = sax; 
 185        sstep_jump = 0;
 186        for (x = 0; x < dst_rect->x; x++) {
 187            csax++; 
 188            sstep = (*csax >> 16);
 189            sstep_jump += sstep;
 190        }
 191
 192        for (y = 0 ; y < dst_rect->h ; y++) {
 193            sp = csp + sstep_jump;
 194            csax = sax + dst_rect->x;
 195
 196            for (x = 0; x < dst_rect->w; x++) {
 197
 198                /* Draw */
 199                *dp = *sp;
 200
 201                /* Advance source pointers */
 202                csax++;
 203                sstep = (*csax >> 16);
 204                sp += sstep;
 205
 206                /* Advance destination pointer */
 207                dp++;
 208            }
 209            /* Advance source pointers */
 210            csay++;
 211            sstep = (*csay >> 16) * src->pitch;
 212            csp = (SDL_TYPE *) ((Uint8 *) csp + sstep);
 213
 214            /* Advance destination pointer */
 215            dp = (SDL_TYPE *) ((Uint8 *) dp + d_gap);
 216        }
 217    }
 218
 219    free(sax);
 220    free(say);
 221    return (0);
 222}
 223
 224#undef SDL_TYPE
 225
 226