Statistics
| Branch: | Revision:

root / ui / sdl_zoom_template.h @ 7fee199c

History | View | Annotate | Download (7 kB)

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

    
54
static 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