root / sdl_zoom_template.h @ 16415335
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
|