Mercurial > otakunoraifu
comparison window/SDL_rotozoom.cc @ 0:223b71206888
Initial import
author | thib |
---|---|
date | Fri, 01 Aug 2008 16:32:45 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:223b71206888 |
---|---|
1 /* | |
2 | |
3 SDL_rotozoom.c - rotozoomer for 32bit or 8bit surfaces | |
4 | |
5 LGPL (c) A. Schiffler | |
6 | |
7 */ | |
8 | |
9 #ifdef WIN32 | |
10 #include <windows.h> | |
11 #endif | |
12 | |
13 #include <stdlib.h> | |
14 #include <string.h> | |
15 | |
16 #include "SDL_rotozoom.h" | |
17 | |
18 #define MAX(a,b) (((a) > (b)) ? (a) : (b)) | |
19 | |
20 /* | |
21 | |
22 32bit Zoomer with optional anti-aliasing by bilinear interpolation. | |
23 | |
24 Zoomes 32bit RGBA/ABGR 'src' surface to 'dst' surface. | |
25 | |
26 */ | |
27 | |
28 int zoomSurfaceRGBA(SDL_Surface * src, SDL_Surface * dst, int smooth) | |
29 { | |
30 int x, y, sx, sy, *sax, *say, *csax, *csay, csx, csy, ex, ey, t1, t2, sstep; | |
31 tColorRGBA *c00, *c01, *c10, *c11; | |
32 tColorRGBA *sp, *csp, *dp; | |
33 int sgap, dgap; | |
34 | |
35 /* | |
36 * Variable setup | |
37 */ | |
38 if (smooth) { | |
39 /* | |
40 * For interpolation: assume source dimension is one pixel | |
41 */ | |
42 /* | |
43 * smaller to avoid overflow on right and bottom edge. | |
44 */ | |
45 sx = (int) (65536.0 * (float) (src->w - 1) / (float) dst->w); | |
46 sy = (int) (65536.0 * (float) (src->h - 1) / (float) dst->h); | |
47 } else { | |
48 sx = (int) (65536.0 * (float) src->w / (float) dst->w); | |
49 sy = (int) (65536.0 * (float) src->h / (float) dst->h); | |
50 } | |
51 | |
52 /* | |
53 * Allocate memory for row increments | |
54 */ | |
55 if ((sax = (int *) malloc((dst->w + 1) * sizeof(Uint32))) == NULL) { | |
56 return (-1); | |
57 } | |
58 if ((say = (int *) malloc((dst->h + 1) * sizeof(Uint32))) == NULL) { | |
59 free(sax); | |
60 return (-1); | |
61 } | |
62 | |
63 /* | |
64 * Precalculate row increments | |
65 */ | |
66 csx = 0; | |
67 csax = sax; | |
68 for (x = 0; x <= dst->w; x++) { | |
69 *csax = csx; | |
70 csax++; | |
71 csx &= 0xffff; | |
72 csx += sx; | |
73 } | |
74 csy = 0; | |
75 csay = say; | |
76 for (y = 0; y <= dst->h; y++) { | |
77 *csay = csy; | |
78 csay++; | |
79 csy &= 0xffff; | |
80 csy += sy; | |
81 } | |
82 | |
83 /* | |
84 * Pointer setup | |
85 */ | |
86 sp = csp = (tColorRGBA *) src->pixels; | |
87 dp = (tColorRGBA *) dst->pixels; | |
88 sgap = src->pitch - src->w * 4; | |
89 dgap = dst->pitch - dst->w * 4; | |
90 | |
91 /* | |
92 * Switch between interpolating and non-interpolating code | |
93 */ | |
94 if (smooth) { | |
95 | |
96 /* | |
97 * Interpolating Zoom | |
98 */ | |
99 | |
100 /* | |
101 * Scan destination | |
102 */ | |
103 csay = say; | |
104 for (y = 0; y < dst->h; y++) { | |
105 /* | |
106 * Setup color source pointers | |
107 */ | |
108 c00 = csp; | |
109 c01 = csp; | |
110 c01++; | |
111 c10 = (tColorRGBA *) ((Uint8 *) csp + src->pitch); | |
112 c11 = c10; | |
113 c11++; | |
114 csax = sax; | |
115 for (x = 0; x < dst->w; x++) { | |
116 | |
117 /* | |
118 * Interpolate colors | |
119 */ | |
120 ex = (*csax & 0xffff); | |
121 ey = (*csay & 0xffff); | |
122 t1 = ((((c01->r - c00->r) * ex) >> 16) + c00->r) & 0xff; | |
123 t2 = ((((c11->r - c10->r) * ex) >> 16) + c10->r) & 0xff; | |
124 dp->r = (((t2 - t1) * ey) >> 16) + t1; | |
125 t1 = ((((c01->g - c00->g) * ex) >> 16) + c00->g) & 0xff; | |
126 t2 = ((((c11->g - c10->g) * ex) >> 16) + c10->g) & 0xff; | |
127 dp->g = (((t2 - t1) * ey) >> 16) + t1; | |
128 t1 = ((((c01->b - c00->b) * ex) >> 16) + c00->b) & 0xff; | |
129 t2 = ((((c11->b - c10->b) * ex) >> 16) + c10->b) & 0xff; | |
130 dp->b = (((t2 - t1) * ey) >> 16) + t1; | |
131 t1 = ((((c01->a - c00->a) * ex) >> 16) + c00->a) & 0xff; | |
132 t2 = ((((c11->a - c10->a) * ex) >> 16) + c10->a) & 0xff; | |
133 dp->a = (((t2 - t1) * ey) >> 16) + t1; | |
134 | |
135 /* | |
136 * Advance source pointers | |
137 */ | |
138 csax++; | |
139 sstep = (*csax >> 16); | |
140 c00 += sstep; | |
141 c01 += sstep; | |
142 c10 += sstep; | |
143 c11 += sstep; | |
144 /* | |
145 * Advance destination pointer | |
146 */ | |
147 dp++; | |
148 } | |
149 /* | |
150 * Advance source pointer | |
151 */ | |
152 csay++; | |
153 csp = (tColorRGBA *) ((Uint8 *) csp + (*csay >> 16) * src->pitch); | |
154 /* | |
155 * Advance destination pointers | |
156 */ | |
157 dp = (tColorRGBA *) ((Uint8 *) dp + dgap); | |
158 } | |
159 | |
160 } else { | |
161 | |
162 /* | |
163 * Non-Interpolating Zoom | |
164 */ | |
165 | |
166 csay = say; | |
167 for (y = 0; y < dst->h; y++) { | |
168 sp = csp; | |
169 csax = sax; | |
170 for (x = 0; x < dst->w; x++) { | |
171 /* | |
172 * Draw | |
173 */ | |
174 *dp = *sp; | |
175 /* | |
176 * Advance source pointers | |
177 */ | |
178 csax++; | |
179 sp += (*csax >> 16); | |
180 /* | |
181 * Advance destination pointer | |
182 */ | |
183 dp++; | |
184 } | |
185 /* | |
186 * Advance source pointer | |
187 */ | |
188 csay++; | |
189 csp = (tColorRGBA *) ((Uint8 *) csp + (*csay >> 16) * src->pitch); | |
190 /* | |
191 * Advance destination pointers | |
192 */ | |
193 dp = (tColorRGBA *) ((Uint8 *) dp + dgap); | |
194 } | |
195 | |
196 } | |
197 | |
198 /* | |
199 * Remove temp arrays | |
200 */ | |
201 free(sax); | |
202 free(say); | |
203 | |
204 return (0); | |
205 } | |
206 | |
207 /* | |
208 | |
209 8bit Zoomer without smoothing. | |
210 | |
211 Zoomes 8bit palette/Y 'src' surface to 'dst' surface. | |
212 | |
213 */ | |
214 | |
215 int zoomSurfaceY(SDL_Surface * src, SDL_Surface * dst) | |
216 { | |
217 Uint32 x, y, sx, sy, *sax, *say, *csax, *csay, csx, csy; | |
218 Uint8 *sp, *dp, *csp; | |
219 int dgap; | |
220 | |
221 /* | |
222 * Variable setup | |
223 */ | |
224 sx = (Uint32) (65536.0 * (float) src->w / (float) dst->w); | |
225 sy = (Uint32) (65536.0 * (float) src->h / (float) dst->h); | |
226 | |
227 /* | |
228 * Allocate memory for row increments | |
229 */ | |
230 if ((sax = (Uint32 *) malloc(dst->w * sizeof(Uint32))) == NULL) { | |
231 return (-1); | |
232 } | |
233 if ((say = (Uint32 *) malloc(dst->h * sizeof(Uint32))) == NULL) { | |
234 if (sax != NULL) { | |
235 free(sax); | |
236 } | |
237 return (-1); | |
238 } | |
239 | |
240 /* | |
241 * Precalculate row increments | |
242 */ | |
243 csx = 0; | |
244 csax = sax; | |
245 for (x = 0; x < dst->w; x++) { | |
246 csx += sx; | |
247 *csax = (csx >> 16); | |
248 csx &= 0xffff; | |
249 csax++; | |
250 } | |
251 csy = 0; | |
252 csay = say; | |
253 for (y = 0; y < dst->h; y++) { | |
254 csy += sy; | |
255 *csay = (csy >> 16); | |
256 csy &= 0xffff; | |
257 csay++; | |
258 } | |
259 | |
260 csx = 0; | |
261 csax = sax; | |
262 for (x = 0; x < dst->w; x++) { | |
263 csx += (*csax); | |
264 csax++; | |
265 } | |
266 csy = 0; | |
267 csay = say; | |
268 for (y = 0; y < dst->h; y++) { | |
269 csy += (*csay); | |
270 csay++; | |
271 } | |
272 | |
273 /* | |
274 * Pointer setup | |
275 */ | |
276 sp = csp = (Uint8 *) src->pixels; | |
277 dp = (Uint8 *) dst->pixels; | |
278 dgap = dst->pitch - dst->w; | |
279 | |
280 /* | |
281 * Draw | |
282 */ | |
283 csay = say; | |
284 for (y = 0; y < dst->h; y++) { | |
285 csax = sax; | |
286 sp = csp; | |
287 for (x = 0; x < dst->w; x++) { | |
288 /* | |
289 * Draw | |
290 */ | |
291 *dp = *sp; | |
292 /* | |
293 * Advance source pointers | |
294 */ | |
295 sp += (*csax); | |
296 csax++; | |
297 /* | |
298 * Advance destination pointer | |
299 */ | |
300 dp++; | |
301 } | |
302 /* | |
303 * Advance source pointer (for row) | |
304 */ | |
305 csp += ((*csay) * src->pitch); | |
306 csay++; | |
307 /* | |
308 * Advance destination pointers | |
309 */ | |
310 dp += dgap; | |
311 } | |
312 | |
313 /* | |
314 * Remove temp arrays | |
315 */ | |
316 free(sax); | |
317 free(say); | |
318 | |
319 return (0); | |
320 } | |
321 | |
322 /* | |
323 | |
324 32bit Rotozoomer with optional anti-aliasing by bilinear interpolation. | |
325 | |
326 Rotates and zoomes 32bit RGBA/ABGR 'src' surface to 'dst' surface. | |
327 | |
328 */ | |
329 | |
330 void transformSurfaceRGBA(SDL_Surface * src, SDL_Surface * dst, int cx, int cy, int isin, int icos, int smooth) | |
331 { | |
332 int x, y, t1, t2, dx, dy, xd, yd, sdx, sdy, ax, ay, ex, ey, sw, sh; | |
333 tColorRGBA c00, c01, c10, c11; | |
334 tColorRGBA *pc, *sp, *spb; | |
335 int gap; | |
336 | |
337 /* | |
338 * Variable setup | |
339 */ | |
340 xd = ((src->w - dst->w) << 15); | |
341 yd = ((src->h - dst->h) << 15); | |
342 ax = (cx << 16) - (icos * cx); | |
343 ay = (cy << 16) - (isin * cx); | |
344 sw = src->w - 1; | |
345 sh = src->h - 1; | |
346 pc = (tColorRGBA*)(dst->pixels); | |
347 gap = dst->pitch - dst->w * 4; | |
348 | |
349 /* | |
350 * Switch between interpolating and non-interpolating code | |
351 */ | |
352 if (smooth) { | |
353 for (y = 0; y < dst->h; y++) { | |
354 dy = cy - y; | |
355 sdx = (ax + (isin * dy)) + xd; | |
356 sdy = (ay - (icos * dy)) + yd; | |
357 for (x = 0; x < dst->w; x++) { | |
358 dx = (sdx >> 16); | |
359 dy = (sdy >> 16); | |
360 if ((dx >= -1) && (dy >= -1) && (dx < src->w) && (dy < src->h)) { | |
361 if ((dx >= 0) && (dy >= 0) && (dx < sw) && (dy < sh)) { | |
362 sp = (tColorRGBA *) ((Uint8 *) src->pixels + src->pitch * dy); | |
363 sp += dx; | |
364 c00 = *sp; | |
365 sp += 1; | |
366 c01 = *sp; | |
367 sp = (tColorRGBA *) ((Uint8 *) sp + src->pitch); | |
368 sp -= 1; | |
369 c10 = *sp; | |
370 sp += 1; | |
371 c11 = *sp; | |
372 } else if ((dx == sw) && (dy == sh)) { | |
373 sp = (tColorRGBA *) ((Uint8 *) src->pixels + src->pitch * dy); | |
374 sp += dx; | |
375 c00 = *sp; | |
376 c01 = *sp; | |
377 c10 = *sp; | |
378 c11 = *sp; | |
379 } else if ((dx == -1) && (dy == -1)) { | |
380 sp = (tColorRGBA *) (src->pixels); | |
381 c00 = *sp; | |
382 c01 = *sp; | |
383 c10 = *sp; | |
384 c11 = *sp; | |
385 } else if ((dx == -1) && (dy == sh)) { | |
386 sp = (tColorRGBA *) (src->pixels); | |
387 sp = (tColorRGBA *) ((Uint8 *) src->pixels + src->pitch * dy); | |
388 c00 = *sp; | |
389 c01 = *sp; | |
390 c10 = *sp; | |
391 c11 = *sp; | |
392 } else if ((dx == sw) && (dy == -1)) { | |
393 sp = (tColorRGBA *) (src->pixels); | |
394 sp += dx; | |
395 c00 = *sp; | |
396 c01 = *sp; | |
397 c10 = *sp; | |
398 c11 = *sp; | |
399 } else if (dx == -1) { | |
400 sp = (tColorRGBA *) ((Uint8 *) src->pixels + src->pitch * dy); | |
401 c00 = *sp; | |
402 c01 = *sp; | |
403 c10 = *sp; | |
404 sp = (tColorRGBA *) ((Uint8 *) sp + src->pitch); | |
405 c11 = *sp; | |
406 } else if (dy == -1) { | |
407 sp = (tColorRGBA *) (src->pixels); | |
408 sp += dx; | |
409 c00 = *sp; | |
410 c01 = *sp; | |
411 c10 = *sp; | |
412 sp += 1; | |
413 c11 = *sp; | |
414 } else if (dx == sw) { | |
415 sp = (tColorRGBA *) ((Uint8 *) src->pixels + src->pitch * dy); | |
416 sp += dx; | |
417 c00 = *sp; | |
418 c01 = *sp; | |
419 sp = (tColorRGBA *) ((Uint8 *) sp + src->pitch); | |
420 c10 = *sp; | |
421 c11 = *sp; | |
422 } else if (dy == sh) { | |
423 sp = (tColorRGBA *) ((Uint8 *) src->pixels + src->pitch * dy); | |
424 sp += dx; | |
425 c00 = *sp; | |
426 sp += 1; | |
427 c01 = *sp; | |
428 c10 = *sp; | |
429 c11 = *sp; | |
430 } | |
431 /* | |
432 * Interpolate colors | |
433 */ | |
434 ex = (sdx & 0xffff); | |
435 ey = (sdy & 0xffff); | |
436 t1 = ((((c01.r - c00.r) * ex) >> 16) + c00.r) & 0xff; | |
437 t2 = ((((c11.r - c10.r) * ex) >> 16) + c10.r) & 0xff; | |
438 pc->r = (((t2 - t1) * ey) >> 16) + t1; | |
439 t1 = ((((c01.g - c00.g) * ex) >> 16) + c00.g) & 0xff; | |
440 t2 = ((((c11.g - c10.g) * ex) >> 16) + c10.g) & 0xff; | |
441 pc->g = (((t2 - t1) * ey) >> 16) + t1; | |
442 t1 = ((((c01.b - c00.b) * ex) >> 16) + c00.b) & 0xff; | |
443 t2 = ((((c11.b - c10.b) * ex) >> 16) + c10.b) & 0xff; | |
444 pc->b = (((t2 - t1) * ey) >> 16) + t1; | |
445 t1 = ((((c01.a - c00.a) * ex) >> 16) + c00.a) & 0xff; | |
446 t2 = ((((c11.a - c10.a) * ex) >> 16) + c10.a) & 0xff; | |
447 pc->a = (((t2 - t1) * ey) >> 16) + t1; | |
448 } | |
449 sdx += icos; | |
450 sdy += isin; | |
451 pc++; | |
452 } | |
453 pc = (tColorRGBA *) ((Uint8 *) pc + gap); | |
454 } | |
455 } else { | |
456 for (y = 0; y < dst->h; y++) { | |
457 dy = cy - y; | |
458 sdx = (ax + (isin * dy)) + xd; | |
459 sdy = (ay - (icos * dy)) + yd; | |
460 for (x = 0; x < dst->w; x++) { | |
461 dx = (short) (sdx >> 16); | |
462 dy = (short) (sdy >> 16); | |
463 if ((dx >= 0) && (dy >= 0) && (dx < src->w) && (dy < src->h)) { | |
464 sp = (tColorRGBA *) ((Uint8 *) src->pixels + src->pitch * dy); | |
465 sp += dx; | |
466 *pc = *sp; | |
467 } | |
468 sdx += icos; | |
469 sdy += isin; | |
470 pc++; | |
471 } | |
472 pc = (tColorRGBA *) ((Uint8 *) pc + gap); | |
473 } | |
474 } | |
475 } | |
476 | |
477 /* | |
478 | |
479 8bit Rotozoomer without smoothing | |
480 | |
481 Rotates and zoomes 8bit palette/Y 'src' surface to 'dst' surface. | |
482 | |
483 */ | |
484 | |
485 void transformSurfaceY(SDL_Surface * src, SDL_Surface * dst, int cx, int cy, int isin, int icos) | |
486 { | |
487 int x, y, dx, dy, xd, yd, sdx, sdy, ax, ay, sw, sh; | |
488 tColorY *pc, *sp; | |
489 int gap; | |
490 | |
491 /* | |
492 * Variable setup | |
493 */ | |
494 xd = ((src->w - dst->w) << 15); | |
495 yd = ((src->h - dst->h) << 15); | |
496 ax = (cx << 16) - (icos * cx); | |
497 ay = (cy << 16) - (isin * cx); | |
498 sw = src->w - 1; | |
499 sh = src->h - 1; | |
500 pc = (tColorY*)(dst->pixels); | |
501 gap = dst->pitch - dst->w; | |
502 /* | |
503 * Clear surface to colorkey | |
504 */ | |
505 memset(pc, (unsigned char) (src->format->colorkey & 0xff), dst->pitch * dst->h); | |
506 /* | |
507 * Iterate through destination surface | |
508 */ | |
509 for (y = 0; y < dst->h; y++) { | |
510 dy = cy - y; | |
511 sdx = (ax + (isin * dy)) + xd; | |
512 sdy = (ay - (icos * dy)) + yd; | |
513 for (x = 0; x < dst->w; x++) { | |
514 dx = (short) (sdx >> 16); | |
515 dy = (short) (sdy >> 16); | |
516 if ((dx >= 0) && (dy >= 0) && (dx < src->w) && (dy < src->h)) { | |
517 sp = (tColorY *) (src->pixels); | |
518 sp += (src->pitch * dy + dx); | |
519 *pc = *sp; | |
520 } | |
521 sdx += icos; | |
522 sdy += isin; | |
523 pc++; | |
524 } | |
525 pc += gap; | |
526 } | |
527 } | |
528 | |
529 /* | |
530 | |
531 rotozoomSurface() | |
532 | |
533 Rotates and zoomes a 32bit or 8bit 'src' surface to newly created 'dst' surface. | |
534 'angle' is the rotation in degrees. 'zoom' a scaling factor. If 'smooth' is 1 | |
535 then the destination 32bit surface is anti-aliased. If the surface is not 8bit | |
536 or 32bit RGBA/ABGR it will be converted into a 32bit RGBA format on the fly. | |
537 | |
538 */ | |
539 | |
540 #define VALUE_LIMIT 0.001 | |
541 | |
542 | |
543 /* Local rotozoom-size function with trig result return */ | |
544 | |
545 void rotozoomSurfaceSizeTrig(int width, int height, double angle, double zoom, int *dstwidth, int *dstheight, | |
546 double *canglezoom, double *sanglezoom) | |
547 { | |
548 double x, y, cx, cy, sx, sy; | |
549 double radangle; | |
550 int dstwidthhalf, dstheighthalf; | |
551 | |
552 /* | |
553 * Determine destination width and height by rotating a centered source box | |
554 */ | |
555 radangle = angle * (M_PI / 180.0); | |
556 *sanglezoom = sin(radangle); | |
557 *canglezoom = cos(radangle); | |
558 *sanglezoom *= zoom; | |
559 *canglezoom *= zoom; | |
560 x = width / 2; | |
561 y = height / 2; | |
562 cx = *canglezoom * x; | |
563 cy = *canglezoom * y; | |
564 sx = *sanglezoom * x; | |
565 sy = *sanglezoom * y; | |
566 dstwidthhalf = MAX((int) | |
567 ceil(MAX(MAX(MAX(fabs(cx + sy), fabs(cx - sy)), fabs(-cx + sy)), fabs(-cx - sy))), 1); | |
568 dstheighthalf = MAX((int) | |
569 ceil(MAX(MAX(MAX(fabs(sx + cy), fabs(sx - cy)), fabs(-sx + cy)), fabs(-sx - cy))), 1); | |
570 *dstwidth = 2 * dstwidthhalf; | |
571 *dstheight = 2 * dstheighthalf; | |
572 } | |
573 | |
574 | |
575 /* Publically available rotozoom-size function */ | |
576 | |
577 void rotozoomSurfaceSize(int width, int height, double angle, double zoom, int *dstwidth, int *dstheight) | |
578 { | |
579 double dummy_sanglezoom, dummy_canglezoom; | |
580 | |
581 rotozoomSurfaceSizeTrig(width, height, angle, zoom, dstwidth, dstheight, &dummy_sanglezoom, &dummy_canglezoom); | |
582 } | |
583 | |
584 | |
585 /* Publically available rotozoom function */ | |
586 | |
587 SDL_Surface *rotozoomSurface(SDL_Surface * src, double angle, double zoom, int smooth) | |
588 { | |
589 SDL_Surface *rz_src; | |
590 SDL_Surface *rz_dst; | |
591 double zoominv; | |
592 double sanglezoom, canglezoom, sanglezoominv, canglezoominv; | |
593 int dstwidthhalf, dstwidth, dstheighthalf, dstheight; | |
594 double x, y, cx, cy, sx, sy; | |
595 int is32bit; | |
596 int i, src_converted; | |
597 | |
598 /* | |
599 * Sanity check | |
600 */ | |
601 if (src == NULL) | |
602 return (NULL); | |
603 | |
604 /* | |
605 * Determine if source surface is 32bit or 8bit | |
606 */ | |
607 is32bit = (src->format->BitsPerPixel == 32); | |
608 if ((is32bit) || (src->format->BitsPerPixel == 8)) { | |
609 /* | |
610 * Use source surface 'as is' | |
611 */ | |
612 rz_src = src; | |
613 src_converted = 0; | |
614 } else { | |
615 /* | |
616 * New source surface is 32bit with a defined RGBA ordering | |
617 */ | |
618 rz_src = | |
619 SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000); | |
620 SDL_BlitSurface(src, NULL, rz_src, NULL); | |
621 src_converted = 1; | |
622 is32bit = 1; | |
623 } | |
624 | |
625 /* | |
626 * Sanity check zoom factor | |
627 */ | |
628 if (zoom < VALUE_LIMIT) { | |
629 zoom = VALUE_LIMIT; | |
630 } | |
631 zoominv = 65536.0 / (zoom * zoom); | |
632 | |
633 /* | |
634 * Check if we have a rotozoom or just a zoom | |
635 */ | |
636 if (fabs(angle) > VALUE_LIMIT) { | |
637 | |
638 /* | |
639 * Angle!=0: full rotozoom | |
640 */ | |
641 /* | |
642 * ----------------------- | |
643 */ | |
644 | |
645 /* Determine target size */ | |
646 rotozoomSurfaceSizeTrig(rz_src->w, rz_src->h, angle, zoom, &dstwidth, &dstheight, &canglezoom, &sanglezoom); | |
647 | |
648 /* | |
649 * Calculate target factors from sin/cos and zoom | |
650 */ | |
651 sanglezoominv = sanglezoom; | |
652 canglezoominv = canglezoom; | |
653 sanglezoominv *= zoominv; | |
654 canglezoominv *= zoominv; | |
655 | |
656 /* Calculate half size */ | |
657 dstwidthhalf = dstwidth / 2; | |
658 dstheighthalf = dstheight / 2; | |
659 | |
660 /* | |
661 * Alloc space to completely contain the rotated surface | |
662 */ | |
663 rz_dst = NULL; | |
664 if (is32bit) { | |
665 /* | |
666 * Target surface is 32bit with source RGBA/ABGR ordering | |
667 */ | |
668 rz_dst = | |
669 SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight, 32, | |
670 rz_src->format->Rmask, rz_src->format->Gmask, | |
671 rz_src->format->Bmask, rz_src->format->Amask); | |
672 } else { | |
673 /* | |
674 * Target surface is 8bit | |
675 */ | |
676 rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight, 8, 0, 0, 0, 0); | |
677 } | |
678 | |
679 /* | |
680 * Lock source surface | |
681 */ | |
682 SDL_LockSurface(rz_src); | |
683 /* | |
684 * Check which kind of surface we have | |
685 */ | |
686 if (is32bit) { | |
687 /* | |
688 * Call the 32bit transformation routine to do the rotation (using alpha) | |
689 */ | |
690 transformSurfaceRGBA(rz_src, rz_dst, dstwidthhalf, dstheighthalf, | |
691 (int) (sanglezoominv), (int) (canglezoominv), smooth); | |
692 /* | |
693 * Turn on source-alpha support | |
694 */ | |
695 SDL_SetAlpha(rz_dst, SDL_SRCALPHA, 255); | |
696 } else { | |
697 /* | |
698 * Copy palette and colorkey info | |
699 */ | |
700 for (i = 0; i < rz_src->format->palette->ncolors; i++) { | |
701 rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i]; | |
702 } | |
703 rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors; | |
704 /* | |
705 * Call the 8bit transformation routine to do the rotation | |
706 */ | |
707 transformSurfaceY(rz_src, rz_dst, dstwidthhalf, dstheighthalf, | |
708 (int) (sanglezoominv), (int) (canglezoominv)); | |
709 SDL_SetColorKey(rz_dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, rz_src->format->colorkey); | |
710 } | |
711 /* | |
712 * Unlock source surface | |
713 */ | |
714 SDL_UnlockSurface(rz_src); | |
715 | |
716 } else { | |
717 | |
718 /* | |
719 * Angle=0: Just a zoom | |
720 */ | |
721 /* | |
722 * -------------------- | |
723 */ | |
724 | |
725 /* | |
726 * Calculate target size | |
727 */ | |
728 zoomSurfaceSize(rz_src->w, rz_src->h, zoom, zoom, &dstwidth, &dstheight); | |
729 | |
730 /* | |
731 * Alloc space to completely contain the zoomed surface | |
732 */ | |
733 rz_dst = NULL; | |
734 if (is32bit) { | |
735 /* | |
736 * Target surface is 32bit with source RGBA/ABGR ordering | |
737 */ | |
738 rz_dst = | |
739 SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight, 32, | |
740 rz_src->format->Rmask, rz_src->format->Gmask, | |
741 rz_src->format->Bmask, rz_src->format->Amask); | |
742 } else { | |
743 /* | |
744 * Target surface is 8bit | |
745 */ | |
746 rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight, 8, 0, 0, 0, 0); | |
747 } | |
748 | |
749 /* | |
750 * Lock source surface | |
751 */ | |
752 SDL_LockSurface(rz_src); | |
753 /* | |
754 * Check which kind of surface we have | |
755 */ | |
756 if (is32bit) { | |
757 /* | |
758 * Call the 32bit transformation routine to do the zooming (using alpha) | |
759 */ | |
760 zoomSurfaceRGBA(rz_src, rz_dst, smooth); | |
761 /* | |
762 * Turn on source-alpha support | |
763 */ | |
764 SDL_SetAlpha(rz_dst, SDL_SRCALPHA, 255); | |
765 } else { | |
766 /* | |
767 * Copy palette and colorkey info | |
768 */ | |
769 for (i = 0; i < rz_src->format->palette->ncolors; i++) { | |
770 rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i]; | |
771 } | |
772 rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors; | |
773 /* | |
774 * Call the 8bit transformation routine to do the zooming | |
775 */ | |
776 zoomSurfaceY(rz_src, rz_dst); | |
777 SDL_SetColorKey(rz_dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, rz_src->format->colorkey); | |
778 } | |
779 /* | |
780 * Unlock source surface | |
781 */ | |
782 SDL_UnlockSurface(rz_src); | |
783 } | |
784 | |
785 /* | |
786 * Cleanup temp surface | |
787 */ | |
788 if (src_converted) { | |
789 SDL_FreeSurface(rz_src); | |
790 } | |
791 | |
792 /* | |
793 * Return destination surface | |
794 */ | |
795 return (rz_dst); | |
796 } | |
797 | |
798 /* | |
799 | |
800 zoomSurface() | |
801 | |
802 Zoomes a 32bit or 8bit 'src' surface to newly created 'dst' surface. | |
803 'zoomx' and 'zoomy' are scaling factors for width and height. If 'smooth' is 1 | |
804 then the destination 32bit surface is anti-aliased. If the surface is not 8bit | |
805 or 32bit RGBA/ABGR it will be converted into a 32bit RGBA format on the fly. | |
806 | |
807 */ | |
808 | |
809 #define VALUE_LIMIT 0.001 | |
810 | |
811 void zoomSurfaceSize(int width, int height, double zoomx, double zoomy, int *dstwidth, int *dstheight) | |
812 { | |
813 /* | |
814 * Sanity check zoom factors | |
815 */ | |
816 if (zoomx < VALUE_LIMIT) { | |
817 zoomx = VALUE_LIMIT; | |
818 } | |
819 if (zoomy < VALUE_LIMIT) { | |
820 zoomy = VALUE_LIMIT; | |
821 } | |
822 | |
823 /* | |
824 * Calculate target size | |
825 */ | |
826 *dstwidth = (int) ((double) width * zoomx); | |
827 *dstheight = (int) ((double) height * zoomy); | |
828 if (*dstwidth < 1) { | |
829 *dstwidth = 1; | |
830 } | |
831 if (*dstheight < 1) { | |
832 *dstheight = 1; | |
833 } | |
834 } | |
835 | |
836 SDL_Surface *zoomSurface(SDL_Surface * src, double zoomx, double zoomy, int smooth) | |
837 { | |
838 SDL_Surface *rz_src; | |
839 SDL_Surface *rz_dst; | |
840 int dstwidth, dstheight; | |
841 int is32bit; | |
842 int i, src_converted; | |
843 | |
844 /* | |
845 * Sanity check | |
846 */ | |
847 if (src == NULL) | |
848 return (NULL); | |
849 | |
850 /* | |
851 * Determine if source surface is 32bit or 8bit | |
852 */ | |
853 is32bit = (src->format->BitsPerPixel == 32); | |
854 if ((is32bit) || (src->format->BitsPerPixel == 8)) { | |
855 /* | |
856 * Use source surface 'as is' | |
857 */ | |
858 rz_src = src; | |
859 src_converted = 0; | |
860 } else { | |
861 /* | |
862 * New source surface is 32bit with a defined RGBA ordering | |
863 */ | |
864 rz_src = | |
865 SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000); | |
866 SDL_BlitSurface(src, NULL, rz_src, NULL); | |
867 src_converted = 1; | |
868 is32bit = 1; | |
869 } | |
870 | |
871 /* Get size if target */ | |
872 zoomSurfaceSize(rz_src->w, rz_src->h, zoomx, zoomy, &dstwidth, &dstheight); | |
873 | |
874 /* | |
875 * Alloc space to completely contain the zoomed surface | |
876 */ | |
877 rz_dst = NULL; | |
878 if (is32bit) { | |
879 /* | |
880 * Target surface is 32bit with source RGBA/ABGR ordering | |
881 */ | |
882 rz_dst = | |
883 SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight, 32, | |
884 rz_src->format->Rmask, rz_src->format->Gmask, | |
885 rz_src->format->Bmask, rz_src->format->Amask); | |
886 } else { | |
887 /* | |
888 * Target surface is 8bit | |
889 */ | |
890 rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight, 8, 0, 0, 0, 0); | |
891 } | |
892 | |
893 /* | |
894 * Lock source surface | |
895 */ | |
896 SDL_LockSurface(rz_src); | |
897 /* | |
898 * Check which kind of surface we have | |
899 */ | |
900 if (is32bit) { | |
901 /* | |
902 * Call the 32bit transformation routine to do the zooming (using alpha) | |
903 */ | |
904 zoomSurfaceRGBA(rz_src, rz_dst, smooth); | |
905 /* | |
906 * Turn on source-alpha support | |
907 */ | |
908 SDL_SetAlpha(rz_dst, SDL_SRCALPHA, 255); | |
909 } else { | |
910 /* | |
911 * Copy palette and colorkey info | |
912 */ | |
913 for (i = 0; i < rz_src->format->palette->ncolors; i++) { | |
914 rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i]; | |
915 } | |
916 rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors; | |
917 /* | |
918 * Call the 8bit transformation routine to do the zooming | |
919 */ | |
920 zoomSurfaceY(rz_src, rz_dst); | |
921 SDL_SetColorKey(rz_dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, rz_src->format->colorkey); | |
922 } | |
923 /* | |
924 * Unlock source surface | |
925 */ | |
926 SDL_UnlockSurface(rz_src); | |
927 | |
928 /* | |
929 * Cleanup temp surface | |
930 */ | |
931 if (src_converted) { | |
932 SDL_FreeSurface(rz_src); | |
933 } | |
934 | |
935 /* | |
936 * Return destination surface | |
937 */ | |
938 return (rz_dst); | |
939 } |