Statistics
| Branch: | Revision:

root / ui / sdl_zoom_template.h @ e4ebcc1a

History | View | Annotate | Download (7 kB)

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