diff --git a/debian/changelog b/debian/changelog index 528c210..3f59aea 100644 --- a/debian/changelog +++ b/debian/changelog @@ -3,6 +3,8 @@ instead (1.3.2) unstable; urgency=low * bug fix (dates in save slots); * bug fix (dbg fixes); * small bug fixes; + * s60 build; + * SDL 1.3 ready; -- Peter Kosyh Mon, 14 Feb 2011 16:24:00 +0300 diff --git a/src/sdl-instead/SDL_gfxBlitFunc.c b/src/sdl-instead/SDL_gfxBlitFunc.c index be3c445..e976da3 100644 --- a/src/sdl-instead/SDL_gfxBlitFunc.c +++ b/src/sdl-instead/SDL_gfxBlitFunc.c @@ -1,454 +1,505 @@ /* - SDL_gfxBlitFunc: custom blitters (part of SDL_gfx library) +SDL_gfxBlitFunc: custom blitters (part of SDL_gfx library) + +LGPL (c) A. Schiffler - LGPL (c) A. Schiffler - */ - #include "SDL_gfxBlitFunc.h" -/* -------- Alpha adjustment table, modified transfer function -------- */ +/*! +\brief Alpha adjustment table for custom blitter. -unsigned int GFX_ALPHA_ADJUST[256] = { - 0, /* 0 */ - 15, /* 1 */ - 22, /* 2 */ - 27, /* 3 */ - 31, /* 4 */ - 35, /* 5 */ - 39, /* 6 */ - 42, /* 7 */ - 45, /* 8 */ - 47, /* 9 */ - 50, /* 10 */ - 52, /* 11 */ - 55, /* 12 */ - 57, /* 13 */ - 59, /* 14 */ - 61, /* 15 */ - 63, /* 16 */ - 65, /* 17 */ - 67, /* 18 */ - 69, /* 19 */ - 71, /* 20 */ - 73, /* 21 */ - 74, /* 22 */ - 76, /* 23 */ - 78, /* 24 */ - 79, /* 25 */ - 81, /* 26 */ - 82, /* 27 */ - 84, /* 28 */ - 85, /* 29 */ - 87, /* 30 */ - 88, /* 31 */ - 90, /* 32 */ - 91, /* 33 */ - 93, /* 34 */ - 94, /* 35 */ - 95, /* 36 */ - 97, /* 37 */ - 98, /* 38 */ - 99, /* 39 */ - 100, /* 40 */ - 102, /* 41 */ - 103, /* 42 */ - 104, /* 43 */ - 105, /* 44 */ - 107, /* 45 */ - 108, /* 46 */ - 109, /* 47 */ - 110, /* 48 */ - 111, /* 49 */ - 112, /* 50 */ - 114, /* 51 */ - 115, /* 52 */ - 116, /* 53 */ - 117, /* 54 */ - 118, /* 55 */ - 119, /* 56 */ - 120, /* 57 */ - 121, /* 58 */ - 122, /* 59 */ - 123, /* 60 */ - 124, /* 61 */ - 125, /* 62 */ - 126, /* 63 */ - 127, /* 64 */ - 128, /* 65 */ - 129, /* 66 */ - 130, /* 67 */ - 131, /* 68 */ - 132, /* 69 */ - 133, /* 70 */ - 134, /* 71 */ - 135, /* 72 */ - 136, /* 73 */ - 137, /* 74 */ - 138, /* 75 */ - 139, /* 76 */ - 140, /* 77 */ - 141, /* 78 */ - 141, /* 79 */ - 142, /* 80 */ - 143, /* 81 */ - 144, /* 82 */ - 145, /* 83 */ - 146, /* 84 */ - 147, /* 85 */ - 148, /* 86 */ - 148, /* 87 */ - 149, /* 88 */ - 150, /* 89 */ - 151, /* 90 */ - 152, /* 91 */ - 153, /* 92 */ - 153, /* 93 */ - 154, /* 94 */ - 155, /* 95 */ - 156, /* 96 */ - 157, /* 97 */ - 158, /* 98 */ - 158, /* 99 */ - 159, /* 100 */ - 160, /* 101 */ - 161, /* 102 */ - 162, /* 103 */ - 162, /* 104 */ - 163, /* 105 */ - 164, /* 106 */ - 165, /* 107 */ - 165, /* 108 */ - 166, /* 109 */ - 167, /* 110 */ - 168, /* 111 */ - 168, /* 112 */ - 169, /* 113 */ - 170, /* 114 */ - 171, /* 115 */ - 171, /* 116 */ - 172, /* 117 */ - 173, /* 118 */ - 174, /* 119 */ - 174, /* 120 */ - 175, /* 121 */ - 176, /* 122 */ - 177, /* 123 */ - 177, /* 124 */ - 178, /* 125 */ - 179, /* 126 */ - 179, /* 127 */ - 180, /* 128 */ - 181, /* 129 */ - 182, /* 130 */ - 182, /* 131 */ - 183, /* 132 */ - 184, /* 133 */ - 184, /* 134 */ - 185, /* 135 */ - 186, /* 136 */ - 186, /* 137 */ - 187, /* 138 */ - 188, /* 139 */ - 188, /* 140 */ - 189, /* 141 */ - 190, /* 142 */ - 190, /* 143 */ - 191, /* 144 */ - 192, /* 145 */ - 192, /* 146 */ - 193, /* 147 */ - 194, /* 148 */ - 194, /* 149 */ - 195, /* 150 */ - 196, /* 151 */ - 196, /* 152 */ - 197, /* 153 */ - 198, /* 154 */ - 198, /* 155 */ - 199, /* 156 */ - 200, /* 157 */ - 200, /* 158 */ - 201, /* 159 */ - 201, /* 160 */ - 202, /* 161 */ - 203, /* 162 */ - 203, /* 163 */ - 204, /* 164 */ - 205, /* 165 */ - 205, /* 166 */ - 206, /* 167 */ - 206, /* 168 */ - 207, /* 169 */ - 208, /* 170 */ - 208, /* 171 */ - 209, /* 172 */ - 210, /* 173 */ - 210, /* 174 */ - 211, /* 175 */ - 211, /* 176 */ - 212, /* 177 */ - 213, /* 178 */ - 213, /* 179 */ - 214, /* 180 */ - 214, /* 181 */ - 215, /* 182 */ - 216, /* 183 */ - 216, /* 184 */ - 217, /* 185 */ - 217, /* 186 */ - 218, /* 187 */ - 218, /* 188 */ - 219, /* 189 */ - 220, /* 190 */ - 220, /* 191 */ - 221, /* 192 */ - 221, /* 193 */ - 222, /* 194 */ - 222, /* 195 */ - 223, /* 196 */ - 224, /* 197 */ - 224, /* 198 */ - 225, /* 199 */ - 225, /* 200 */ - 226, /* 201 */ - 226, /* 202 */ - 227, /* 203 */ - 228, /* 204 */ - 228, /* 205 */ - 229, /* 206 */ - 229, /* 207 */ - 230, /* 208 */ - 230, /* 209 */ - 231, /* 210 */ - 231, /* 211 */ - 232, /* 212 */ - 233, /* 213 */ - 233, /* 214 */ - 234, /* 215 */ - 234, /* 216 */ - 235, /* 217 */ - 235, /* 218 */ - 236, /* 219 */ - 236, /* 220 */ - 237, /* 221 */ - 237, /* 222 */ - 238, /* 223 */ - 238, /* 224 */ - 239, /* 225 */ - 240, /* 226 */ - 240, /* 227 */ - 241, /* 228 */ - 241, /* 229 */ - 242, /* 230 */ - 242, /* 231 */ - 243, /* 232 */ - 243, /* 233 */ - 244, /* 234 */ - 244, /* 235 */ - 245, /* 236 */ - 245, /* 237 */ - 246, /* 238 */ - 246, /* 239 */ - 247, /* 240 */ - 247, /* 241 */ - 248, /* 242 */ - 248, /* 243 */ - 249, /* 244 */ - 249, /* 245 */ - 250, /* 246 */ - 250, /* 247 */ - 251, /* 248 */ - 251, /* 249 */ - 252, /* 250 */ - 252, /* 251 */ - 253, /* 252 */ - 253, /* 253 */ - 254, /* 254 */ - 255 /* 255 */ - }; +The table provides values for a modified, non-linear +transfer function which maintain brightness. +*/ +static unsigned int GFX_ALPHA_ADJUST_ARRAY[256] = { + 0, /* 0 */ + 15, /* 1 */ + 22, /* 2 */ + 27, /* 3 */ + 31, /* 4 */ + 35, /* 5 */ + 39, /* 6 */ + 42, /* 7 */ + 45, /* 8 */ + 47, /* 9 */ + 50, /* 10 */ + 52, /* 11 */ + 55, /* 12 */ + 57, /* 13 */ + 59, /* 14 */ + 61, /* 15 */ + 63, /* 16 */ + 65, /* 17 */ + 67, /* 18 */ + 69, /* 19 */ + 71, /* 20 */ + 73, /* 21 */ + 74, /* 22 */ + 76, /* 23 */ + 78, /* 24 */ + 79, /* 25 */ + 81, /* 26 */ + 82, /* 27 */ + 84, /* 28 */ + 85, /* 29 */ + 87, /* 30 */ + 88, /* 31 */ + 90, /* 32 */ + 91, /* 33 */ + 93, /* 34 */ + 94, /* 35 */ + 95, /* 36 */ + 97, /* 37 */ + 98, /* 38 */ + 99, /* 39 */ + 100, /* 40 */ + 102, /* 41 */ + 103, /* 42 */ + 104, /* 43 */ + 105, /* 44 */ + 107, /* 45 */ + 108, /* 46 */ + 109, /* 47 */ + 110, /* 48 */ + 111, /* 49 */ + 112, /* 50 */ + 114, /* 51 */ + 115, /* 52 */ + 116, /* 53 */ + 117, /* 54 */ + 118, /* 55 */ + 119, /* 56 */ + 120, /* 57 */ + 121, /* 58 */ + 122, /* 59 */ + 123, /* 60 */ + 124, /* 61 */ + 125, /* 62 */ + 126, /* 63 */ + 127, /* 64 */ + 128, /* 65 */ + 129, /* 66 */ + 130, /* 67 */ + 131, /* 68 */ + 132, /* 69 */ + 133, /* 70 */ + 134, /* 71 */ + 135, /* 72 */ + 136, /* 73 */ + 137, /* 74 */ + 138, /* 75 */ + 139, /* 76 */ + 140, /* 77 */ + 141, /* 78 */ + 141, /* 79 */ + 142, /* 80 */ + 143, /* 81 */ + 144, /* 82 */ + 145, /* 83 */ + 146, /* 84 */ + 147, /* 85 */ + 148, /* 86 */ + 148, /* 87 */ + 149, /* 88 */ + 150, /* 89 */ + 151, /* 90 */ + 152, /* 91 */ + 153, /* 92 */ + 153, /* 93 */ + 154, /* 94 */ + 155, /* 95 */ + 156, /* 96 */ + 157, /* 97 */ + 158, /* 98 */ + 158, /* 99 */ + 159, /* 100 */ + 160, /* 101 */ + 161, /* 102 */ + 162, /* 103 */ + 162, /* 104 */ + 163, /* 105 */ + 164, /* 106 */ + 165, /* 107 */ + 165, /* 108 */ + 166, /* 109 */ + 167, /* 110 */ + 168, /* 111 */ + 168, /* 112 */ + 169, /* 113 */ + 170, /* 114 */ + 171, /* 115 */ + 171, /* 116 */ + 172, /* 117 */ + 173, /* 118 */ + 174, /* 119 */ + 174, /* 120 */ + 175, /* 121 */ + 176, /* 122 */ + 177, /* 123 */ + 177, /* 124 */ + 178, /* 125 */ + 179, /* 126 */ + 179, /* 127 */ + 180, /* 128 */ + 181, /* 129 */ + 182, /* 130 */ + 182, /* 131 */ + 183, /* 132 */ + 184, /* 133 */ + 184, /* 134 */ + 185, /* 135 */ + 186, /* 136 */ + 186, /* 137 */ + 187, /* 138 */ + 188, /* 139 */ + 188, /* 140 */ + 189, /* 141 */ + 190, /* 142 */ + 190, /* 143 */ + 191, /* 144 */ + 192, /* 145 */ + 192, /* 146 */ + 193, /* 147 */ + 194, /* 148 */ + 194, /* 149 */ + 195, /* 150 */ + 196, /* 151 */ + 196, /* 152 */ + 197, /* 153 */ + 198, /* 154 */ + 198, /* 155 */ + 199, /* 156 */ + 200, /* 157 */ + 200, /* 158 */ + 201, /* 159 */ + 201, /* 160 */ + 202, /* 161 */ + 203, /* 162 */ + 203, /* 163 */ + 204, /* 164 */ + 205, /* 165 */ + 205, /* 166 */ + 206, /* 167 */ + 206, /* 168 */ + 207, /* 169 */ + 208, /* 170 */ + 208, /* 171 */ + 209, /* 172 */ + 210, /* 173 */ + 210, /* 174 */ + 211, /* 175 */ + 211, /* 176 */ + 212, /* 177 */ + 213, /* 178 */ + 213, /* 179 */ + 214, /* 180 */ + 214, /* 181 */ + 215, /* 182 */ + 216, /* 183 */ + 216, /* 184 */ + 217, /* 185 */ + 217, /* 186 */ + 218, /* 187 */ + 218, /* 188 */ + 219, /* 189 */ + 220, /* 190 */ + 220, /* 191 */ + 221, /* 192 */ + 221, /* 193 */ + 222, /* 194 */ + 222, /* 195 */ + 223, /* 196 */ + 224, /* 197 */ + 224, /* 198 */ + 225, /* 199 */ + 225, /* 200 */ + 226, /* 201 */ + 226, /* 202 */ + 227, /* 203 */ + 228, /* 204 */ + 228, /* 205 */ + 229, /* 206 */ + 229, /* 207 */ + 230, /* 208 */ + 230, /* 209 */ + 231, /* 210 */ + 231, /* 211 */ + 232, /* 212 */ + 233, /* 213 */ + 233, /* 214 */ + 234, /* 215 */ + 234, /* 216 */ + 235, /* 217 */ + 235, /* 218 */ + 236, /* 219 */ + 236, /* 220 */ + 237, /* 221 */ + 237, /* 222 */ + 238, /* 223 */ + 238, /* 224 */ + 239, /* 225 */ + 240, /* 226 */ + 240, /* 227 */ + 241, /* 228 */ + 241, /* 229 */ + 242, /* 230 */ + 242, /* 231 */ + 243, /* 232 */ + 243, /* 233 */ + 244, /* 234 */ + 244, /* 235 */ + 245, /* 236 */ + 245, /* 237 */ + 246, /* 238 */ + 246, /* 239 */ + 247, /* 240 */ + 247, /* 241 */ + 248, /* 242 */ + 248, /* 243 */ + 249, /* 244 */ + 249, /* 245 */ + 250, /* 246 */ + 250, /* 247 */ + 251, /* 248 */ + 251, /* 249 */ + 252, /* 250 */ + 252, /* 251 */ + 253, /* 252 */ + 253, /* 253 */ + 254, /* 254 */ + 255 /* 255 */ +}; -/* --- */ +/*! +\brief Internal blitter using adjusted destination alpha during RGBA->RGBA blits. -/* Special blitter for correct destination Alpha during RGBA->RGBA blits */ +Performs the blit based on the 'info' structure and applies the transfer function +to the destination 'a' values. -void SDL_gfxBlitBlitterRGBA(SDL_gfxBlitInfo * info) +\param info The blit info to use. +*/ +void _SDL_gfxBlitBlitterRGBA(SDL_gfxBlitInfo * info) { - int width = info->d_width; - int height = info->d_height; - Uint8 *src = info->s_pixels; - int srcskip = info->s_skip; - Uint8 *dst = info->d_pixels; - int dstskip = info->d_skip; - SDL_PixelFormat *srcfmt = info->src; - SDL_PixelFormat *dstfmt = info->dst; - int srcbpp = srcfmt->BytesPerPixel; - int dstbpp = dstfmt->BytesPerPixel; + int width = info->d_width; + int height = info->d_height; + Uint8 *src = info->s_pixels; + int srcskip = info->s_skip; + Uint8 *dst = info->d_pixels; + int dstskip = info->d_skip; + SDL_PixelFormat *srcfmt = info->src; + SDL_PixelFormat *dstfmt = info->dst; + int srcbpp = srcfmt->BytesPerPixel; + int dstbpp = dstfmt->BytesPerPixel; - while (height--) { - GFX_DUFFS_LOOP4( { - Uint32 pixel; - unsigned sR; - unsigned sG; - unsigned sB; - unsigned sA; - unsigned dR; - unsigned dG; - unsigned dB; - unsigned dA; - unsigned sAA; - GFX_DISEMBLE_RGBA(src, srcbpp, srcfmt, pixel, sR, sG, sB, sA); - GFX_DISEMBLE_RGBA(dst, dstbpp, dstfmt, pixel, dR, dG, dB, dA); - sAA=GFX_ALPHA_ADJUST[sA & 255]; - GFX_ALPHA_BLEND(sR, sG, sB, sAA, dR, dG, dB); - dA |= sAA; - GFX_ASSEMBLE_RGBA(dst, dstbpp, dstfmt, dR, dG, dB, dA); - src += srcbpp; dst += dstbpp; - }, width); - src += srcskip; - dst += dstskip; - } + while (height--) { + GFX_DUFFS_LOOP4( { + Uint32 pixel; + unsigned sR; + unsigned sG; + unsigned sB; + unsigned sA; + unsigned dR; + unsigned dG; + unsigned dB; + unsigned dA; + unsigned sAA; + GFX_DISEMBLE_RGBA(src, srcbpp, srcfmt, pixel, sR, sG, sB, sA); + GFX_DISEMBLE_RGBA(dst, dstbpp, dstfmt, pixel, dR, dG, dB, dA); + sAA=GFX_ALPHA_ADJUST_ARRAY[sA & 255]; + GFX_ALPHA_BLEND(sR, sG, sB, sAA, dR, dG, dB); + dA |= sAA; + GFX_ASSEMBLE_RGBA(dst, dstbpp, dstfmt, dR, dG, dB, dA); + src += srcbpp; dst += dstbpp; + }, width); + src += srcskip; + dst += dstskip; + } } -int SDL_gfxBlitRGBACall(SDL_Surface * src, SDL_Rect * srcrect, SDL_Surface * dst, SDL_Rect * dstrect) +/*! +\brief Internal blitter setup wrapper for RGBA->RGBA blits. + +Sets up the blitter info based on the 'src' and 'dst' surfaces and rectangles. + +\param src The source surface. +\param srcrect The source rectangle. +\param dst The destination surface. +\param dstrect The destination rectangle. + +\returns Returns 1 if blit was performed, 0 otherwise. +*/ +int _SDL_gfxBlitRGBACall(SDL_Surface * src, SDL_Rect * srcrect, SDL_Surface * dst, SDL_Rect * dstrect) { - /* - * Set up source and destination buffer pointers, then blit - */ - if (srcrect->w && srcrect->h) { - SDL_gfxBlitInfo info; + /* + * Set up source and destination buffer pointers, then blit + */ + if (srcrect->w && srcrect->h) { + SDL_gfxBlitInfo info; - /* - * Set up the blit information - */ - info.s_pixels = (Uint8 *) src->pixels + src->offset + (Uint16) srcrect->y * src->pitch + (Uint16) srcrect->x * src->format->BytesPerPixel; - info.s_width = srcrect->w; - info.s_height = srcrect->h; - info.s_skip = src->pitch - info.s_width * src->format->BytesPerPixel; - info.d_pixels = (Uint8 *) dst->pixels + dst->offset + (Uint16) dstrect->y * dst->pitch + (Uint16) dstrect->x * dst->format->BytesPerPixel; - info.d_width = dstrect->w; - info.d_height = dstrect->h; - info.d_skip = dst->pitch - info.d_width * dst->format->BytesPerPixel; - info.aux_data = NULL; - info.src = src->format; - info.table = NULL; - info.dst = dst->format; + /* + * Set up the blit information + */ +#if (SDL_MINOR_VERSION == 3) + info.s_pixels = (Uint8 *) src->pixels + (Uint16) srcrect->y * src->pitch + (Uint16) srcrect->x * src->format->BytesPerPixel; +#else + info.s_pixels = (Uint8 *) src->pixels + src->offset + (Uint16) srcrect->y * src->pitch + (Uint16) srcrect->x * src->format->BytesPerPixel; +#endif + info.s_width = srcrect->w; + info.s_height = srcrect->h; + info.s_skip = src->pitch - info.s_width * src->format->BytesPerPixel; +#if (SDL_MINOR_VERSION == 3) + info.d_pixels = (Uint8 *) dst->pixels + (Uint16) dstrect->y * dst->pitch + (Uint16) dstrect->x * dst->format->BytesPerPixel; +#else + info.d_pixels = (Uint8 *) dst->pixels + dst->offset + (Uint16) dstrect->y * dst->pitch + (Uint16) dstrect->x * dst->format->BytesPerPixel; +#endif + info.d_width = dstrect->w; + info.d_height = dstrect->h; + info.d_skip = dst->pitch - info.d_width * dst->format->BytesPerPixel; + info.aux_data = NULL; + info.src = src->format; + info.table = NULL; + info.dst = dst->format; - /* - * Run the actual software blitter - */ - SDL_gfxBlitBlitterRGBA(&info); - } + /* + * Run the actual software blitter + */ + _SDL_gfxBlitBlitterRGBA(&info); + return 1; + } - return (0); + return (0); } +/*! +\brief Blitter for RGBA->RGBA blits with alpha adjustment. +Verifies the input 'src' and 'dst' surfaces and rectangles and performs blit. +The destination clip rectangle is honored. + +\param src The source surface. +\param srcrect The source rectangle. +\param dst The destination surface. +\param dstrect The destination rectangle. + +\returns Returns 1 if blit was performed, 0 otherwise, or -1 if an error occured. +*/ int SDL_gfxBlitRGBA(SDL_Surface * src, SDL_Rect * srcrect, SDL_Surface * dst, SDL_Rect * dstrect) { - SDL_Rect sr, dr; - int srcx, srcy, w, h; + SDL_Rect sr, dr; + int srcx, srcy, w, h; - /* - * Make sure the surfaces aren't locked - */ - if (!src || !dst) { - SDL_SetError("SDL_UpperBlit: passed a NULL surface"); - return (-1); - } - if (src->locked || dst->locked) { - SDL_SetError("Surfaces must not be locked during blit"); - return (-1); - } + /* + * Make sure the surfaces aren't locked + */ + if (!src || !dst) { + SDL_SetError("SDL_UpperBlit: passed a NULL surface"); + return (-1); + } + if (src->locked || dst->locked) { + SDL_SetError("Surfaces must not be locked during blit"); + return (-1); + } - /* - * If the destination rectangle is NULL, use the entire dest surface - */ - if (dstrect == NULL) { - dr.x = dr.y = 0; - dr.w = dst->w; - dr.h = dst->h; - } else { - dr = *dstrect; - } + /* + * If the destination rectangle is NULL, use the entire dest surface + */ + if (dstrect == NULL) { + dr.x = dr.y = 0; + dr.w = dst->w; + dr.h = dst->h; + } else { + dr = *dstrect; + } - /* - * Clip the source rectangle to the source surface - */ - if (srcrect) { - int maxw, maxh; + /* + * Clip the source rectangle to the source surface + */ + if (srcrect) { + int maxw, maxh; - srcx = srcrect->x; - w = srcrect->w; - if (srcx < 0) { - w += srcx; - dr.x -= srcx; - srcx = 0; - } - maxw = src->w - srcx; - if (maxw < w) - w = maxw; + srcx = srcrect->x; + w = srcrect->w; + if (srcx < 0) { + w += srcx; + dr.x -= srcx; + srcx = 0; + } + maxw = src->w - srcx; + if (maxw < w) + w = maxw; - srcy = srcrect->y; - h = srcrect->h; - if (srcy < 0) { - h += srcy; - dr.y -= srcy; - srcy = 0; - } - maxh = src->h - srcy; - if (maxh < h) - h = maxh; + srcy = srcrect->y; + h = srcrect->h; + if (srcy < 0) { + h += srcy; + dr.y -= srcy; + srcy = 0; + } + maxh = src->h - srcy; + if (maxh < h) + h = maxh; - } else { - srcx = srcy = 0; - w = src->w; - h = src->h; - } + } else { + srcx = srcy = 0; + w = src->w; + h = src->h; + } - /* - * Clip the destination rectangle against the clip rectangle - */ - { - SDL_Rect *clip = &dst->clip_rect; - int dx, dy; + /* + * Clip the destination rectangle against the clip rectangle + */ + { + SDL_Rect *clip = &dst->clip_rect; + int dx, dy; - dx = clip->x - dr.x; - if (dx > 0) { - w -= dx; - dr.x += dx; - srcx += dx; - } - dx = dr.x + w - clip->x - clip->w; - if (dx > 0) - w -= dx; + dx = clip->x - dr.x; + if (dx > 0) { + w -= dx; + dr.x += dx; + srcx += dx; + } + dx = dr.x + w - clip->x - clip->w; + if (dx > 0) + w -= dx; - dy = clip->y - dr.y; - if (dy > 0) { - h -= dy; - dr.y += dy; - srcy += dy; - } - dy = dr.y + h - clip->y - clip->h; - if (dy > 0) - h -= dy; - } + dy = clip->y - dr.y; + if (dy > 0) { + h -= dy; + dr.y += dy; + srcy += dy; + } + dy = dr.y + h - clip->y - clip->h; + if (dy > 0) + h -= dy; + } - if (w > 0 && h > 0) { - sr.x = srcx; - sr.y = srcy; - sr.w = dr.w = w; - sr.h = dr.h = h; - return (SDL_gfxBlitRGBACall(src, &sr, dst, &dr)); - } - return 0; + if (w > 0 && h > 0) { + sr.x = srcx; + sr.y = srcy; + sr.w = dr.w = w; + sr.h = dr.h = h; + return (_SDL_gfxBlitRGBACall(src, &sr, dst, &dr)); + } + + return 0; } -/* Helper function that sets the alpha channel in a 32bit surface */ +/*! +\brief Sets the alpha channel in a 32 bit surface. +Helper function that sets the alpha channel in a 32 bit surface +to a constant value. +Only 32 bit surfaces can be used with this function. + +\param src Pointer to the target surface to change. +\param a The alpha value to set. + +\return Returns 1 if alpha was changed, 0 otherwise. +*/ int SDL_gfxSetAlpha(SDL_Surface *src, Uint8 a) { #if SDL_BYTEORDER == SDL_BIG_ENDIAN @@ -457,25 +508,69 @@ int SDL_gfxSetAlpha(SDL_Surface *src, Uint8 a) Uint16 alpha_offset = 3; #endif Uint16 i, j; - + /* Check if we have a 32bit surface */ if ( (src) && (src->format) && (src->format->BytesPerPixel==4) ) { - /* Lock and process */ - if ( SDL_LockSurface(src) == 0 ) { - Uint8 *pixels = (Uint8 *)src->pixels; - Uint16 row_skip = (src->pitch - (4*src->w)); - pixels += alpha_offset; - for ( i=0; ih; i++ ) { - for ( j=0; jw; j++ ) { - *pixels = a; - pixels += 4; - } - pixels += row_skip; - } - SDL_UnlockSurface(src); - } - return 1; - } else { - return 0; - } + /* Lock and process */ + if ( SDL_LockSurface(src) == 0 ) { + Uint8 *pixels = (Uint8 *)src->pixels; + Uint16 row_skip = (src->pitch - (4*src->w)); + pixels += alpha_offset; + for ( i=0; ih; i++ ) { + for ( j=0; jw; j++ ) { + *pixels = a; + pixels += 4; + } + pixels += row_skip; + } + SDL_UnlockSurface(src); + } + return 1; + } else { + return 0; + } +} + +/*! +\brief Multiply the alpha channel in a 32bit surface. + +Helper function that multiplies the alpha channel in a 32 bit surface +with a constant value. The final alpha is always scaled to the range +0-255 (i.e. the factor is a/256). +Only 32 bit surfaces can be used with this function. + +\param src Pointer to the target surface to change. +\param a The alpha value to multiply with. + +\return Returns 1 if alpha was changed, 0 otherwise. +*/ +int SDL_gfxMultiplyAlpha(SDL_Surface *src, Uint8 a) +{ +#if SDL_BYTEORDER == SDL_BIG_ENDIAN + Uint16 alpha_offset = 0; +#else + Uint16 alpha_offset = 3; +#endif + Uint16 i, j; + + /* Check if we have a 32bit surface */ + if ( (src) && (src->format) && (src->format->BytesPerPixel==4) && (a!=255) ) { + /* Lock and process */ + if ( SDL_LockSurface(src) == 0 ) { + Uint8 *pixels = (Uint8 *)src->pixels; + Uint16 row_skip = (src->pitch - (4*src->w)); + pixels += alpha_offset; + for ( i=0; ih; i++ ) { + for ( j=0; jw; j++ ) { + *pixels = (Uint8)(((int)(*pixels)*a)>>8); + pixels += 4; + } + pixels += row_skip; + } + SDL_UnlockSurface(src); + } + return 1; + } + + return 0; } diff --git a/src/sdl-instead/SDL_gfxBlitFunc.h b/src/sdl-instead/SDL_gfxBlitFunc.h index 527b051..2690de1 100644 --- a/src/sdl-instead/SDL_gfxBlitFunc.h +++ b/src/sdl-instead/SDL_gfxBlitFunc.h @@ -1,9 +1,9 @@ /* - SDL_gfxBlitFunc: custom blitters (part of SDL_gfx library) +SDL_gfxBlitFunc: custom blitters (part of SDL_gfx library) + +LGPL (c) A. Schiffler - LGPL (c) A. Schiffler - */ #ifndef _SDL_gfxBlitFunc_h @@ -20,87 +20,123 @@ extern "C" { #include #include -int SDL_gfxBlitRGBA(SDL_Surface * src, SDL_Rect * srcrect, SDL_Surface * dst, SDL_Rect * dstrect); + /* ---- Function Prototypes */ -int SDL_gfxSetAlpha(SDL_Surface * src, Uint8 a); +#if defined(WIN32) || defined(WIN64) +# if defined(DLL_EXPORT) && !defined(LIBSDL_GFX_DLL_IMPORT) +# define SDL_GFXBLITFUNC_SCOPE __declspec(dllexport) +# else +# ifdef LIBSDL_GFX_DLL_IMPORT +# define SDL_GFXBLITFUNC_SCOPE __declspec(dllimport) +# endif +# endif +#endif +#ifndef SDL_GFXBLITFUNC_SCOPE +# define SDL_GFXBLITFUNC_SCOPE extern +#endif -/* -------- Macros */ + SDL_GFXBLITFUNC_SCOPE int SDL_gfxBlitRGBA(SDL_Surface * src, SDL_Rect * srcrect, SDL_Surface * dst, SDL_Rect * dstrect); -/* Define SDL macros locally as a substitute for a #include "SDL_blit.h", */ + SDL_GFXBLITFUNC_SCOPE int SDL_gfxSetAlpha(SDL_Surface * src, Uint8 a); -/* which doesn't work since the include file doesn't get installed. */ + SDL_GFXBLITFUNC_SCOPE int SDL_gfxMultiplyAlpha(SDL_Surface * src, Uint8 a); -/* The structure passed to the low level blit functions */ - typedef struct { - Uint8 *s_pixels; - int s_width; - int s_height; - int s_skip; - Uint8 *d_pixels; - int d_width; - int d_height; - int d_skip; - void *aux_data; - SDL_PixelFormat *src; - Uint8 *table; - SDL_PixelFormat *dst; - } SDL_gfxBlitInfo; + /* -------- Macros */ + /* Define SDL macros locally as a substitute for an #include "SDL_blit.h", */ + /* which doesn't work since the include file doesn't get installed. */ + +/*! +\brief The structure passed to the low level blit functions. +*/ + typedef struct { + Uint8 *s_pixels; + int s_width; + int s_height; + int s_skip; + Uint8 *d_pixels; + int d_width; + int d_height; + int d_skip; + void *aux_data; + SDL_PixelFormat *src; + Uint8 *table; + SDL_PixelFormat *dst; + } SDL_gfxBlitInfo; + +/*! +\brief Unwrap RGBA values from a pixel using mask, shift and loss for surface. +*/ #define GFX_RGBA_FROM_PIXEL(pixel, fmt, r, g, b, a) \ -{ \ + { \ r = ((pixel&fmt->Rmask)>>fmt->Rshift)<Rloss; \ g = ((pixel&fmt->Gmask)>>fmt->Gshift)<Gloss; \ b = ((pixel&fmt->Bmask)>>fmt->Bshift)<Bloss; \ a = ((pixel&fmt->Amask)>>fmt->Ashift)<Aloss; \ -} + } +/*! +\brief Disassemble buffer pointer into a pixel and separate RGBA values. +*/ #define GFX_DISEMBLE_RGBA(buf, bpp, fmt, pixel, r, g, b, a) \ -do { \ + do { \ pixel = *((Uint32 *)(buf)); \ GFX_RGBA_FROM_PIXEL(pixel, fmt, r, g, b, a); \ pixel &= ~fmt->Amask; \ -} while(0) + } while(0) +/*! +\brief Wrap a pixel from RGBA values using mask, shift and loss for surface. +*/ #define GFX_PIXEL_FROM_RGBA(pixel, fmt, r, g, b, a) \ -{ \ + { \ pixel = ((r>>fmt->Rloss)<Rshift)| \ - ((g>>fmt->Gloss)<Gshift)| \ - ((b>>fmt->Bloss)<Bshift)| \ - ((a<Aloss)<Ashift); \ -} + ((g>>fmt->Gloss)<Gshift)| \ + ((b>>fmt->Bloss)<Bshift)| \ + ((a<Aloss)<Ashift); \ + } +/*! +\brief Assemble pixel into buffer pointer from separate RGBA values. +*/ #define GFX_ASSEMBLE_RGBA(buf, bpp, fmt, r, g, b, a) \ -{ \ - Uint32 pixel; \ - \ - GFX_PIXEL_FROM_RGBA(pixel, fmt, r, g, b, a); \ - *((Uint32 *)(buf)) = pixel; \ -} + { \ + Uint32 pixel; \ + \ + GFX_PIXEL_FROM_RGBA(pixel, fmt, r, g, b, a); \ + *((Uint32 *)(buf)) = pixel; \ + } -/* Blend the RGB values of two pixels based on a source alpha value */ +/*! +\brief Blend the RGB values of two pixels based on a source alpha value. +*/ #define GFX_ALPHA_BLEND(sR, sG, sB, A, dR, dG, dB) \ -do { \ + do { \ dR = (((sR-dR)*(A))/255)+dR; \ dG = (((sG-dG)*(A))/255)+dG; \ dB = (((sB-dB)*(A))/255)+dB; \ -} while(0) + } while(0) -/* This is a very useful loop for optimizing blitters */ +/*! +\brief 4-times unrolled DUFFs loop. -/* 4-times unrolled loop */ +This is a very useful loop for optimizing blitters. +*/ #define GFX_DUFFS_LOOP4(pixel_copy_increment, width) \ -{ int n = (width+3)/4; \ + { int n = (width+3)/4; \ switch (width & 3) { \ case 0: do { pixel_copy_increment; \ case 3: pixel_copy_increment; \ case 2: pixel_copy_increment; \ case 1: pixel_copy_increment; \ - } while ( --n > 0 ); \ + } while ( --n > 0 ); \ } \ -} + } -/* Ends C function definitions when using C++ */ + + + /* Ends C function definitions when using C++ */ #ifdef __cplusplus } #endif diff --git a/src/sdl-instead/SDL_rotozoom.c b/src/sdl-instead/SDL_rotozoom.c index 1abf7f4..5a20279 100644 --- a/src/sdl-instead/SDL_rotozoom.c +++ b/src/sdl-instead/SDL_rotozoom.c @@ -1,1356 +1,1638 @@ -/* - - SDL_rotozoom.c - rotozoomer for 32bit or 8bit surfaces - - LGPL (c) A. Schiffler +/* + +SDL_rotozoom.c - rotozoomer, zoomer and shrinker for 32bit or 8bit surfaces + +LGPL (c) A. Schiffler + +*/ + +#ifdef WIN32 +#include +#endif + +#include +#include + +#include "SDL_rotozoom.h" + +/* ---- Internally used structures */ +/*! +\brief A 32 bit RGBA pixel. */ +typedef struct tColorRGBA { + Uint8 r; + Uint8 g; + Uint8 b; + Uint8 a; +} tColorRGBA; -#ifdef WIN32 -#include -#endif - -#include -#include - -#include "SDL_rotozoom.h" - -#define MAX(a,b) (((a) > (b)) ? (a) : (b)) - - -/* - - 32bit integer-factor averaging Shrinker - - Shrinks 32bit RGBA/ABGR 'src' surface to 'dst' surface. - +/*! +\brief A 8bit Y/palette pixel. */ - -int shrinkSurfaceRGBA(SDL_Surface * src, SDL_Surface * dst, int factorx, int factory) -{ - int x, y, dx, dy, sgap, dgap, ra, ga, ba, aa; - int n_average; - tColorRGBA *sp, *osp, *oosp; - tColorRGBA *dp; - - /* - * Averaging integer shrink - */ - - /* Precalculate division factor */ - n_average = factorx*factory; - - /* - * Scan destination - */ - sp = (tColorRGBA *) src->pixels; - sgap = src->pitch - src->w * 4; - - dp = (tColorRGBA *) dst->pixels; - dgap = dst->pitch - dst->w * 4; - - for (y = 0; y < dst->h; y++) { - - osp=sp; - for (x = 0; x < dst->w; x++) { - - /* Trace out source box and accumulate */ - oosp=sp; - ra=ga=ba=aa=0; - for (dy=0; dy < factory; dy++) { - for (dx=0; dx < factorx; dx++) { - ra += sp->r; - ga += sp->g; - ba += sp->b; - aa += sp->a; - - sp++; - } - /* src dx loop */ - sp = (tColorRGBA *)((Uint8*)sp + (src->pitch - 4*factorx)); // next y - } - /* src dy loop */ - - /* next box-x */ - sp = (tColorRGBA *)((Uint8*)oosp + 4*factorx); - - /* Store result in destination */ - dp->r = ra/n_average; - dp->g = ga/n_average; - dp->b = ba/n_average; - dp->a = aa/n_average; - - /* - * Advance destination pointer - */ - dp++; - } - /* dst x loop */ - - /* next box-y */ - sp = (tColorRGBA *)((Uint8*)osp + src->pitch*factory); - - /* - * Advance destination pointers - */ - dp = (tColorRGBA *) ((Uint8 *) dp + dgap); - } - /* dst y loop */ - - return (0); -} - -/* - - 8bit integer-factor averaging Shrinker - - Shrinks 8bit Y 'src' surface to 'dst' surface. - -*/ - -int shrinkSurfaceY(SDL_Surface * src, SDL_Surface * dst, int factorx, int factory) -{ - int x, y, dx, dy, sgap, dgap, a; - int n_average; - Uint8 *sp, *osp, *oosp; - Uint8 *dp; - - /* - * Averaging integer shrink - */ - - /* Precalculate division factor */ - n_average = factorx*factory; - - /* - * Scan destination - */ - sp = (Uint8 *) src->pixels; - sgap = src->pitch - src->w; - - dp = (Uint8 *) dst->pixels; - dgap = dst->pitch - dst->w; - - for (y = 0; y < dst->h; y++) { - - osp=sp; - for (x = 0; x < dst->w; x++) { - - /* Trace out source box and accumulate */ - oosp=sp; - a=0; - for (dy=0; dy < factory; dy++) { - for (dx=0; dx < factorx; dx++) { - a += (*sp); - /* next x */ - sp++; - } - /* end src dx loop */ - /* next y */ - sp = (Uint8 *)((Uint8*)sp + (src->pitch - factorx)); - } - /* end src dy loop */ - - /* next box-x */ - sp = (Uint8 *)((Uint8*)oosp + factorx); - - /* Store result in destination */ - *dp = a/n_average; - - /* - * Advance destination pointer - */ - dp++; - } - /* end dst x loop */ - - /* next box-y */ - sp = (Uint8 *)((Uint8*)osp + src->pitch*factory); - - /* - * Advance destination pointers - */ - dp = (Uint8 *)((Uint8 *)dp + dgap); - } - /* end dst y loop */ - - return (0); -} - -/* - - 32bit Zoomer with optional anti-aliasing by bilinear interpolation. - - Zoomes 32bit RGBA/ABGR 'src' surface to 'dst' surface. - -*/ - -int zoomSurfaceRGBA(SDL_Surface * src, SDL_Surface * dst, int flipx, int flipy, int smooth) -{ - int x, y, sx, sy, *sax, *say, *csax, *csay, csx, csy, ex, ey, t1, t2, sstep, lx, ly; - tColorRGBA *c00, *c01, *c10, *c11, *cswap; - tColorRGBA *sp, *csp, *dp; - int dgap; - - /* - * Variable setup - */ - if (smooth) { - /* - * For interpolation: assume source dimension is one pixel - */ - /* - * smaller to avoid overflow on right and bottom edge. - */ - sx = (int) (65536.0 * (float) (src->w - 1) / (float) dst->w); - sy = (int) (65536.0 * (float) (src->h - 1) / (float) dst->h); - } else { - sx = (int) (65536.0 * (float) src->w / (float) dst->w); - sy = (int) (65536.0 * (float) src->h / (float) dst->h); - } - - /* - * Allocate memory for row increments - */ - if ((sax = (int *) malloc((dst->w + 1) * sizeof(Uint32))) == NULL) { - return (-1); - } - if ((say = (int *) malloc((dst->h + 1) * sizeof(Uint32))) == NULL) { - free(sax); - return (-1); - } - - /* - * Precalculate row increments - */ - sp = csp = (tColorRGBA *) src->pixels; - dp = (tColorRGBA *) dst->pixels; - - if (flipx) csp += (src->w-1); - if (flipy) csp += (src->pitch*(src->h-1)); - - csx = 0; - csax = sax; - for (x = 0; x <= dst->w; x++) { - *csax = csx; - csax++; - csx &= 0xffff; - csx += sx; - } - csy = 0; - csay = say; - for (y = 0; y <= dst->h; y++) { - *csay = csy; - csay++; - csy &= 0xffff; - csy += sy; - } - - dgap = dst->pitch - dst->w * 4; - - /* - * Switch between interpolating and non-interpolating code - */ - if (smooth) { - - /* - * Interpolating Zoom - */ - - /* - * Scan destination - */ - ly = 0; - csay = say; - for (y = 0; y < dst->h; y++) { - /* - * Setup color source pointers - */ - c00 = csp; - c01 = csp; - c01++; - c10 = (tColorRGBA *) ((Uint8 *) csp + src->pitch); - c11 = c10; - c11++; - csax = sax; - if (flipx) { - cswap = c00; c00=c01; c01=cswap; - cswap = c10; c10=c11; c11=cswap; - } - if (flipy) { - cswap = c00; c00=c10; c10=cswap; - cswap = c01; c01=c11; c11=cswap; - } - lx = 0; - for (x = 0; x < dst->w; x++) { - /* - * Interpolate colors - */ - ex = (*csax & 0xffff); - ey = (*csay & 0xffff); - t1 = ((((c01->r - c00->r) * ex) >> 16) + c00->r) & 0xff; - t2 = ((((c11->r - c10->r) * ex) >> 16) + c10->r) & 0xff; - dp->r = (((t2 - t1) * ey) >> 16) + t1; - t1 = ((((c01->g - c00->g) * ex) >> 16) + c00->g) & 0xff; - t2 = ((((c11->g - c10->g) * ex) >> 16) + c10->g) & 0xff; - dp->g = (((t2 - t1) * ey) >> 16) + t1; - t1 = ((((c01->b - c00->b) * ex) >> 16) + c00->b) & 0xff; - t2 = ((((c11->b - c10->b) * ex) >> 16) + c10->b) & 0xff; - dp->b = (((t2 - t1) * ey) >> 16) + t1; - t1 = ((((c01->a - c00->a) * ex) >> 16) + c00->a) & 0xff; - t2 = ((((c11->a - c10->a) * ex) >> 16) + c10->a) & 0xff; - dp->a = (((t2 - t1) * ey) >> 16) + t1; - - /* - * Advance source pointers - */ - csax++; - sstep = (*csax >> 16); - lx += sstep; - if (lx >= src->w) sstep = 0; - if (flipx) sstep = -sstep; - c00 += sstep; - c01 += sstep; - c10 += sstep; - c11 += sstep; - /* - * Advance destination pointer - */ - dp++; - } - /* - * Advance source pointer - */ - csay++; - sstep = (*csay >> 16); - ly += sstep; - if (ly >= src->h) sstep = 0; - sstep *= src->pitch; - if (flipy) sstep = -sstep; - csp = (tColorRGBA *) ((Uint8 *) csp + sstep); - - /* - * Advance destination pointers - */ - dp = (tColorRGBA *) ((Uint8 *) dp + dgap); - } - } else { - - /* - * Non-Interpolating Zoom - */ - - csay = say; - for (y = 0; y < dst->h; y++) { - sp = csp; - csax = sax; - for (x = 0; x < dst->w; x++) { - /* - * Draw - */ - *dp = *sp; - /* - * Advance source pointers - */ - csax++; - sstep = (*csax >> 16); - if (flipx) sstep = -sstep; - sp += sstep; - /* - * Advance destination pointer - */ - dp++; - } - /* - * Advance source pointer - */ - csay++; - sstep = (*csay >> 16) * src->pitch; - if (flipy) sstep = -sstep; - csp = (tColorRGBA *) ((Uint8 *) csp + sstep); - - /* - * Advance destination pointers - */ - dp = (tColorRGBA *) ((Uint8 *) dp + dgap); - } - } - - /* - * Remove temp arrays - */ - free(sax); - free(say); - - return (0); -} - -/* - - 8bit Zoomer without smoothing. - - Zoomes 8bit palette/Y 'src' surface to 'dst' surface. - -*/ - -int zoomSurfaceY(SDL_Surface * src, SDL_Surface * dst, int flipx, int flipy) -{ - Uint32 x, y, sx, sy, *sax, *say, *csax, *csay, csx, csy, sstep; - Uint8 *sp, *dp, *csp; - int dgap; - - /* - * Variable setup - */ - sx = (Uint32) (65536.0 * (float) src->w / (float) dst->w); - sy = (Uint32) (65536.0 * (float) src->h / (float) dst->h); - - - /* - * Allocate memory for row increments - */ - if ((sax = (Uint32 *) malloc((dst->w + 1) * sizeof(Uint32))) == NULL) { - return (-1); - } - if ((say = (Uint32 *) malloc((dst->h + 1) * sizeof(Uint32))) == NULL) { - free(sax); - return (-1); - } - - /* - * Pointer setup - */ - sp = csp = (Uint8 *) src->pixels; - dp = (Uint8 *) dst->pixels; - dgap = dst->pitch - dst->w; - - if (flipx) csp += (src->w-1); - if (flipy) csp = ( (Uint8*)csp + src->pitch*(src->h-1) ); - - /* - * Precalculate row increments - */ - csx = 0; - csax = sax; - for (x = 0; x <= dst->w; x++) { - *csax = csx; - csax++; - csx &= 0xffff; - csx += sx; - } - csy = 0; - csay = say; - for (y = 0; y <= dst->h; y++) { - *csay = csy; - csay++; - csy &= 0xffff; - csy += sy; - } - - - /* - * Draw - */ - csay = say; - for (y = 0; y < dst->h; y++) { - csax = sax; - sp = csp; - for (x = 0; x < dst->w; x++) { - /* - * Draw - */ - *dp = *sp; - /* - * Advance source pointers - */ - csax++; - sstep = (*csax >> 16); - if (flipx) sstep = -sstep; - sp += sstep; - /* - * Advance destination pointer - */ - dp++; - } - /* - * Advance source pointer (for row) - */ - csay++; - sstep = (*csay >> 16) * src->pitch; - if (flipy) sstep = -sstep; - csp = ((Uint8 *) csp + sstep); - - /* - * Advance destination pointers - */ - dp += dgap; - } - - /* - * Remove temp arrays - */ - free(sax); - free(say); - - return (0); -} - -/* - - 32bit Rotozoomer with optional anti-aliasing by bilinear interpolation. - - Rotates and zoomes 32bit RGBA/ABGR 'src' surface to 'dst' surface. - -*/ - -void transformSurfaceRGBA(SDL_Surface * src, SDL_Surface * dst, int cx, int cy, int isin, int icos, int flipx, int flipy, int smooth) -{ - int x, y, t1, t2, dx, dy, xd, yd, sdx, sdy, ax, ay, ex, ey, sw, sh; - tColorRGBA c00, c01, c10, c11, cswap; - tColorRGBA *pc, *sp; - int gap; - - /* - * Variable setup - */ - xd = ((src->w - dst->w) << 15); - yd = ((src->h - dst->h) << 15); - ax = (cx << 16) - (icos * cx); - ay = (cy << 16) - (isin * cx); - sw = src->w - 1; - sh = src->h - 1; - pc = dst->pixels; - gap = dst->pitch - dst->w * 4; - - /* - * Switch between interpolating and non-interpolating code - */ - if (smooth) { - for (y = 0; y < dst->h; y++) { - dy = cy - y; - sdx = (ax + (isin * dy)) + xd; - sdy = (ay - (icos * dy)) + yd; - for (x = 0; x < dst->w; x++) { - dx = (sdx >> 16); - dy = (sdy >> 16); - if ((dx > -1) && (dy > -1) && (dx < src->w) && (dy < src->h)) { - if (flipx) dx = sw - dx; - if (flipy) dy = sh - dy; - sp = (tColorRGBA *) ((Uint8 *) src->pixels + src->pitch * dy); - sp += dx; - c00 = *sp; - sp += 1; - c01 = *sp; - sp = (tColorRGBA *) ((Uint8 *) sp + src->pitch); - c11 = *sp; - sp -= 1; - c10 = *sp; - if (flipx) { - cswap = c00; c00=c01; c01=cswap; - cswap = c10; c10=c11; c11=cswap; - } - if (flipy) { - cswap = c00; c00=c10; c10=cswap; - cswap = c01; c01=c11; c11=cswap; - } - /* - * Interpolate colors - */ - ex = (sdx & 0xffff); - ey = (sdy & 0xffff); - t1 = ((((c01.r - c00.r) * ex) >> 16) + c00.r) & 0xff; - t2 = ((((c11.r - c10.r) * ex) >> 16) + c10.r) & 0xff; - pc->r = (((t2 - t1) * ey) >> 16) + t1; - t1 = ((((c01.g - c00.g) * ex) >> 16) + c00.g) & 0xff; - t2 = ((((c11.g - c10.g) * ex) >> 16) + c10.g) & 0xff; - pc->g = (((t2 - t1) * ey) >> 16) + t1; - t1 = ((((c01.b - c00.b) * ex) >> 16) + c00.b) & 0xff; - t2 = ((((c11.b - c10.b) * ex) >> 16) + c10.b) & 0xff; - pc->b = (((t2 - t1) * ey) >> 16) + t1; - t1 = ((((c01.a - c00.a) * ex) >> 16) + c00.a) & 0xff; - t2 = ((((c11.a - c10.a) * ex) >> 16) + c10.a) & 0xff; - pc->a = (((t2 - t1) * ey) >> 16) + t1; - } - sdx += icos; - sdy += isin; - pc++; - } - pc = (tColorRGBA *) ((Uint8 *) pc + gap); - } - } else { - for (y = 0; y < dst->h; y++) { - dy = cy - y; - sdx = (ax + (isin * dy)) + xd; - sdy = (ay - (icos * dy)) + yd; - for (x = 0; x < dst->w; x++) { - dx = (short) (sdx >> 16); - dy = (short) (sdy >> 16); - if (flipx) dx = (src->w-1)-dx; - if (flipy) dy = (src->h-1)-dy; - if ((dx >= 0) && (dy >= 0) && (dx < src->w) && (dy < src->h)) { - sp = (tColorRGBA *) ((Uint8 *) src->pixels + src->pitch * dy); - sp += dx; - *pc = *sp; - } - sdx += icos; - sdy += isin; - pc++; - } - pc = (tColorRGBA *) ((Uint8 *) pc + gap); - } - } -} - -/* - - 8bit Rotozoomer without smoothing - - Rotates and zoomes 8bit palette/Y 'src' surface to 'dst' surface. - -*/ - -void transformSurfaceY(SDL_Surface * src, SDL_Surface * dst, int cx, int cy, int isin, int icos, int flipx, int flipy) -{ - int x, y, dx, dy, xd, yd, sdx, sdy, ax, ay, sw, sh; - tColorY *pc, *sp; - int gap; - - /* - * Variable setup - */ - xd = ((src->w - dst->w) << 15); - yd = ((src->h - dst->h) << 15); - ax = (cx << 16) - (icos * cx); - ay = (cy << 16) - (isin * cx); - sw = src->w - 1; - sh = src->h - 1; - pc = dst->pixels; - gap = dst->pitch - dst->w; - /* - * Clear surface to colorkey - */ - memset(pc, (unsigned char) (src->format->colorkey & 0xff), dst->pitch * dst->h); - /* - * Iterate through destination surface - */ - for (y = 0; y < dst->h; y++) { - dy = cy - y; - sdx = (ax + (isin * dy)) + xd; - sdy = (ay - (icos * dy)) + yd; - for (x = 0; x < dst->w; x++) { - dx = (short) (sdx >> 16); - dy = (short) (sdy >> 16); - if (flipx) dx = (src->w-1)-dx; - if (flipy) dy = (src->h-1)-dy; - if ((dx >= 0) && (dy >= 0) && (dx < src->w) && (dy < src->h)) { - sp = (tColorY *) (src->pixels); - sp += (src->pitch * dy + dx); - *pc = *sp; - } - sdx += icos; - sdy += isin; - pc++; - } - pc += gap; - } -} - -/* - - 32bit specialized 90degree rotator - - Rotates and zooms 'src' surface to 'dst' surface in 90degree increments. - - (contributed by Jeff Schiller) - -*/ -SDL_Surface* rotateSurface90Degrees(SDL_Surface* pSurf, int numClockwiseTurns) -{ - int row, col, newWidth, newHeight; - SDL_Surface* pSurfOut; - - /* Has to be a valid surface pointer and only 32-bit surfaces (for now) */ - if (!pSurf || pSurf->format->BitsPerPixel != 32) { return NULL; } - - /* normalize numClockwiseTurns */ - while(numClockwiseTurns < 0) { numClockwiseTurns += 4; } - numClockwiseTurns = (numClockwiseTurns % 4); - - /* if it's even, our new width will be the same as the source surface */ - newWidth = (numClockwiseTurns % 2) ? (pSurf->h) : (pSurf->w); - newHeight = (numClockwiseTurns % 2) ? (pSurf->w) : (pSurf->h); - pSurfOut = SDL_CreateRGBSurface( pSurf->flags, newWidth, newHeight, pSurf->format->BitsPerPixel, - pSurf->format->Rmask, - pSurf->format->Gmask, - pSurf->format->Bmask, - pSurf->format->Amask); - if(!pSurfOut) { - return NULL; - } - - if(numClockwiseTurns != 0) { - SDL_LockSurface(pSurf); - SDL_LockSurface(pSurfOut); - switch(numClockwiseTurns) { - - /* rotate clockwise */ - case 1: /* rotated 90 degrees clockwise */ - { - Uint32* srcBuf = NULL; - Uint32* dstBuf = NULL; - - for (row = 0; row < pSurf->h; ++row) { - srcBuf = (Uint32*)(pSurf->pixels) + (row*pSurf->pitch/4); - dstBuf = (Uint32*)(pSurfOut->pixels) + (pSurfOut->w - row - 1); - for (col = 0; col < pSurf->w; ++col) { - *dstBuf = *srcBuf; - ++srcBuf; - dstBuf += pSurfOut->pitch/4; - } - /* end for(col) */ - } - /* end for(row) */ - } - break; - - case 2: /* rotated 180 degrees clockwise */ - { - Uint32* srcBuf = NULL; - Uint32* dstBuf = NULL; - - for(row = 0; row < pSurf->h; ++row) { - srcBuf = (Uint32*)(pSurf->pixels) + (row*pSurf->pitch/4); - dstBuf = (Uint32*)(pSurfOut->pixels) + ((pSurfOut->h - row - 1)*pSurfOut->pitch/4) + (pSurfOut->w - 1); - for(col = 0; col < pSurf->w; ++col) { - *dstBuf = *srcBuf; - ++srcBuf; - --dstBuf; - } - } - } - break; - - case 3: - { - Uint32* srcBuf = NULL; - Uint32* dstBuf = NULL; - - for(row = 0; row < pSurf->h; ++row) { - srcBuf = (Uint32*)(pSurf->pixels) + (row*pSurf->pitch/4); - dstBuf = (Uint32*)(pSurfOut->pixels) + row + ((pSurfOut->h - 1)*pSurfOut->pitch/4); - for(col = 0; col < pSurf->w; ++col) { - *dstBuf = *srcBuf; - ++srcBuf; - dstBuf -= pSurfOut->pitch/4; - } - } - } - break; - } - /* end switch */ - - SDL_UnlockSurface(pSurf); - SDL_UnlockSurface(pSurfOut); - } - /* end if numClockwiseTurns > 0 */ - else { - /* simply copy surface to output */ - if(SDL_BlitSurface(pSurf, NULL, pSurfOut, NULL)) { - return NULL; - } - } - return pSurfOut; -} - -/* - - rotozoomSurface() - - Rotates and zoomes a 32bit or 8bit 'src' surface to newly created 'dst' surface. - 'angle' is the rotation in degrees. 'zoom' a scaling factor. If 'smooth' is 1 - then the destination 32bit surface is anti-aliased. If the surface is not 8bit - or 32bit RGBA/ABGR it will be converted into a 32bit RGBA format on the fly. - -*/ - -#define VALUE_LIMIT 0.001 - -/* Local rotozoom-size function with trig result return */ - -void rotozoomSurfaceSizeTrig(int width, int height, double angle, double zoomx, double zoomy, int *dstwidth, int *dstheight, - double *canglezoom, double *sanglezoom) -{ - double x, y, cx, cy, sx, sy; - double radangle; - int dstwidthhalf, dstheighthalf; - - /* - * Determine destination width and height by rotating a centered source box - */ - radangle = angle * (M_PI / 180.0); - *sanglezoom = sin(radangle); - *canglezoom = cos(radangle); - *sanglezoom *= zoomx; - *canglezoom *= zoomx; - x = width / 2; - y = height / 2; - cx = *canglezoom * x; - cy = *canglezoom * y; - sx = *sanglezoom * x; - sy = *sanglezoom * y; - - dstwidthhalf = MAX((int) - ceil(MAX(MAX(MAX(fabs(cx + sy), fabs(cx - sy)), fabs(-cx + sy)), fabs(-cx - sy))), 1); - dstheighthalf = MAX((int) - ceil(MAX(MAX(MAX(fabs(sx + cy), fabs(sx - cy)), fabs(-sx + cy)), fabs(-sx - cy))), 1); - *dstwidth = 2 * dstwidthhalf; - *dstheight = 2 * dstheighthalf; -} - - -/* Publically available rotozoom-size function */ - -void rotozoomSurfaceSizeXY(int width, int height, double angle, double zoomx, double zoomy, int *dstwidth, int *dstheight) -{ - double dummy_sanglezoom, dummy_canglezoom; - - rotozoomSurfaceSizeTrig(width, height, angle, zoomx, zoomy, dstwidth, dstheight, &dummy_sanglezoom, &dummy_canglezoom); -} - -/* Publically available rotozoom-size function */ - -void rotozoomSurfaceSize(int width, int height, double angle, double zoom, int *dstwidth, int *dstheight) -{ - double dummy_sanglezoom, dummy_canglezoom; - - rotozoomSurfaceSizeTrig(width, height, angle, zoom, zoom, dstwidth, dstheight, &dummy_sanglezoom, &dummy_canglezoom); -} - -/* Publically available rotozoom function */ - -SDL_Surface *rotozoomSurface(SDL_Surface * src, double angle, double zoom, int smooth) -{ - return rotozoomSurfaceXY(src, angle, zoom, zoom, smooth); -} - -/* Publically available rotozoom function */ - -SDL_Surface *rotozoomSurfaceXY(SDL_Surface * src, double angle, double zoomx, double zoomy, int smooth) -{ - SDL_Surface *rz_src; - SDL_Surface *rz_dst; - double zoominv; - double sanglezoom, canglezoom, sanglezoominv, canglezoominv; - int dstwidthhalf, dstwidth, dstheighthalf, dstheight; - int is32bit; - int i, src_converted; - int flipx,flipy; - Uint8 r,g,b; - Uint32 colorkey; - int colorKeyAvailable = 0; - - /* - * Sanity check - */ - if (src == NULL) - return (NULL); - - if( src->flags & SDL_SRCCOLORKEY ) - { - colorkey = src->format->colorkey; - SDL_GetRGB(colorkey, src->format, &r, &g, &b); - colorKeyAvailable = 1; - } - /* - * Determine if source surface is 32bit or 8bit - */ - is32bit = (src->format->BitsPerPixel == 32); - if ((is32bit) || (src->format->BitsPerPixel == 8)) { - /* - * Use source surface 'as is' - */ - rz_src = src; - src_converted = 0; - } else { - /* - * New source surface is 32bit with a defined RGBA ordering - */ - rz_src = - SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32, -#if SDL_BYTEORDER == SDL_LIL_ENDIAN - 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 -#else - 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff -#endif - ); - if(colorKeyAvailable) - SDL_SetColorKey(src, 0, 0); - - SDL_BlitSurface(src, NULL, rz_src, NULL); - - if(colorKeyAvailable) - SDL_SetColorKey(src, SDL_SRCCOLORKEY, colorkey); - src_converted = 1; - is32bit = 1; - } - - /* - * Sanity check zoom factor - */ - flipx = (zoomx<0.0); - if (flipx) zoomx=-zoomx; - flipy = (zoomy<0.0); - if (flipy) zoomy=-zoomy; - if (zoomx < VALUE_LIMIT) zoomx = VALUE_LIMIT; - if (zoomy < VALUE_LIMIT) zoomy = VALUE_LIMIT; - zoominv = 65536.0 / (zoomx * zoomx); - - /* - * Check if we have a rotozoom or just a zoom - */ - if (fabs(angle) > VALUE_LIMIT) { - - /* - * Angle!=0: full rotozoom - */ - /* - * ----------------------- - */ - - /* Determine target size */ - rotozoomSurfaceSizeTrig(rz_src->w, rz_src->h, angle, zoomx, zoomy, &dstwidth, &dstheight, &canglezoom, &sanglezoom); - - /* - * Calculate target factors from sin/cos and zoom - */ - sanglezoominv = sanglezoom; - canglezoominv = canglezoom; - sanglezoominv *= zoominv; - canglezoominv *= zoominv; - - /* Calculate half size */ - dstwidthhalf = dstwidth / 2; - dstheighthalf = dstheight / 2; - - /* - * Alloc space to completely contain the rotated surface - */ - rz_dst = NULL; - if (is32bit) { - /* - * Target surface is 32bit with source RGBA/ABGR ordering - */ - rz_dst = - SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight, 32, - rz_src->format->Rmask, rz_src->format->Gmask, - rz_src->format->Bmask, rz_src->format->Amask); - } else { - /* - * Target surface is 8bit - */ - rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight, 8, 0, 0, 0, 0); - } - - if (colorKeyAvailable == 1){ - colorkey = SDL_MapRGB(rz_dst->format, r, g, b); - - SDL_FillRect(rz_dst, NULL, colorkey ); - } - - /* - * Lock source surface - */ - SDL_LockSurface(rz_src); - /* - * Check which kind of surface we have - */ - if (is32bit) { - /* - * Call the 32bit transformation routine to do the rotation (using alpha) - */ - transformSurfaceRGBA(rz_src, rz_dst, dstwidthhalf, dstheighthalf, - (int) (sanglezoominv), (int) (canglezoominv), - flipx, flipy, - smooth); - /* - * Turn on source-alpha support - */ - SDL_SetAlpha(rz_dst, SDL_SRCALPHA, 255); - } else { - /* - * Copy palette and colorkey info - */ - for (i = 0; i < rz_src->format->palette->ncolors; i++) { - rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i]; - } - rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors; - /* - * Call the 8bit transformation routine to do the rotation - */ - transformSurfaceY(rz_src, rz_dst, dstwidthhalf, dstheighthalf, - (int) (sanglezoominv), (int) (canglezoominv), - flipx, flipy); - SDL_SetColorKey(rz_dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, rz_src->format->colorkey); - } - /* - * Unlock source surface - */ - SDL_UnlockSurface(rz_src); - - } else { - - /* - * Angle=0: Just a zoom - */ - /* - * -------------------- - */ - - /* - * Calculate target size - */ - zoomSurfaceSize(rz_src->w, rz_src->h, zoomx, zoomy, &dstwidth, &dstheight); - - /* - * Alloc space to completely contain the zoomed surface - */ - rz_dst = NULL; - if (is32bit) { - /* - * Target surface is 32bit with source RGBA/ABGR ordering - */ - rz_dst = - SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight, 32, - rz_src->format->Rmask, rz_src->format->Gmask, - rz_src->format->Bmask, rz_src->format->Amask); - } else { - /* - * Target surface is 8bit - */ - rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight, 8, 0, 0, 0, 0); - } - - if (colorKeyAvailable == 1){ - colorkey = SDL_MapRGB(rz_dst->format, r, g, b); - - SDL_FillRect(rz_dst, NULL, colorkey ); - } - - /* - * Lock source surface - */ - SDL_LockSurface(rz_src); - /* - * Check which kind of surface we have - */ - if (is32bit) { - /* - * Call the 32bit transformation routine to do the zooming (using alpha) - */ - zoomSurfaceRGBA(rz_src, rz_dst, flipx, flipy, smooth); - /* - * Turn on source-alpha support - */ - SDL_SetAlpha(rz_dst, SDL_SRCALPHA, 255); - } else { - /* - * Copy palette and colorkey info - */ - for (i = 0; i < rz_src->format->palette->ncolors; i++) { - rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i]; - } - rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors; - /* - * Call the 8bit transformation routine to do the zooming - */ - zoomSurfaceY(rz_src, rz_dst, flipx, flipy); - SDL_SetColorKey(rz_dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, rz_src->format->colorkey); - } - /* - * Unlock source surface - */ - SDL_UnlockSurface(rz_src); - } - - /* - * Cleanup temp surface - */ - if (src_converted) { - SDL_FreeSurface(rz_src); - } - - /* - * Return destination surface - */ - return (rz_dst); -} - -/* - - zoomSurface() - - Zoomes a 32bit or 8bit 'src' surface to newly created 'dst' surface. - 'zoomx' and 'zoomy' are scaling factors for width and height. If 'smooth' is 1 - then the destination 32bit surface is anti-aliased. If the surface is not 8bit - or 32bit RGBA/ABGR it will be converted into a 32bit RGBA format on the fly. - -*/ - -#define VALUE_LIMIT 0.001 - -void zoomSurfaceSize(int width, int height, double zoomx, double zoomy, int *dstwidth, int *dstheight) -{ - /* - * Sanity check zoom factors - */ - if (zoomx < VALUE_LIMIT) { - zoomx = VALUE_LIMIT; - } - if (zoomy < VALUE_LIMIT) { - zoomy = VALUE_LIMIT; - } - - /* - * Calculate target size - */ - *dstwidth = (int) ((double) width * zoomx); - *dstheight = (int) ((double) height * zoomy); - if (*dstwidth < 1) { - *dstwidth = 1; - } - if (*dstheight < 1) { - *dstheight = 1; - } -} - -SDL_Surface *zoomSurface(SDL_Surface * src, double zoomx, double zoomy, int smooth) -{ - SDL_Surface *rz_src; - SDL_Surface *rz_dst; - int dstwidth, dstheight; - int is32bit; - int i, src_converted; - int flipx, flipy; - /* - * Sanity check - */ - if (src == NULL) - return (NULL); - - /* - * Determine if source surface is 32bit or 8bit - */ - is32bit = (src->format->BitsPerPixel == 32); - if ((is32bit) || (src->format->BitsPerPixel == 8)) { - /* - * Use source surface 'as is' - */ - rz_src = src; - src_converted = 0; - } else { - /* - * New source surface is 32bit with a defined RGBA ordering - */ - rz_src = - SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32, -#if SDL_BYTEORDER == SDL_LIL_ENDIAN - 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 -#else - 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff -#endif - ); - SDL_BlitSurface(src, NULL, rz_src, NULL); - src_converted = 1; - is32bit = 1; - } - - flipx = (zoomx<0.0); - if (flipx) zoomx = -zoomx; - flipy = (zoomy<0.0); - if (flipy) zoomy = -zoomy; - - /* Get size if target */ - zoomSurfaceSize(rz_src->w, rz_src->h, zoomx, zoomy, &dstwidth, &dstheight); - - /* - * Alloc space to completely contain the zoomed surface - */ - rz_dst = NULL; - if (is32bit) { - /* - * Target surface is 32bit with source RGBA/ABGR ordering - */ - rz_dst = - SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight, 32, - rz_src->format->Rmask, rz_src->format->Gmask, - rz_src->format->Bmask, rz_src->format->Amask); - } else { - /* - * Target surface is 8bit - */ - rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight, 8, 0, 0, 0, 0); - } - - /* - * Lock source surface - */ - SDL_LockSurface(rz_src); - /* - * Check which kind of surface we have - */ - if (is32bit) { - /* - * Call the 32bit transformation routine to do the zooming (using alpha) - */ - zoomSurfaceRGBA(rz_src, rz_dst, flipx, flipy, smooth); - /* - * Turn on source-alpha support - */ - SDL_SetAlpha(rz_dst, SDL_SRCALPHA, 255); - } else { - /* - * Copy palette and colorkey info - */ - for (i = 0; i < rz_src->format->palette->ncolors; i++) { - rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i]; - } - rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors; - /* - * Call the 8bit transformation routine to do the zooming - */ - zoomSurfaceY(rz_src, rz_dst, flipx, flipy); - if (rz_src->flags & SDL_SRCCOLORKEY) - SDL_SetColorKey(rz_dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, rz_src->format->colorkey); - } - /* - * Unlock source surface - */ - SDL_UnlockSurface(rz_src); - - /* - * Cleanup temp surface - */ - if (src_converted) { - SDL_FreeSurface(rz_src); - } - - /* - * Return destination surface - */ - return (rz_dst); -} - -SDL_Surface *shrinkSurface(SDL_Surface * src, int factorx, int factory) -{ - SDL_Surface *rz_src; - SDL_Surface *rz_dst; - int dstwidth, dstheight; - int is32bit; - int i, src_converted; - - /* - * Sanity check - */ - if (src == NULL) - return (NULL); - - /* - * Determine if source surface is 32bit or 8bit - */ - is32bit = (src->format->BitsPerPixel == 32); - if ((is32bit) || (src->format->BitsPerPixel == 8)) { - /* - * Use source surface 'as is' - */ - rz_src = src; - src_converted = 0; - } else { - /* - * New source surface is 32bit with a defined RGBA ordering - */ - rz_src = - SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32, -#if SDL_BYTEORDER == SDL_LIL_ENDIAN - 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 -#else - 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff -#endif - ); - SDL_BlitSurface(src, NULL, rz_src, NULL); - src_converted = 1; - is32bit = 1; - } - - /* Get size for target */ - dstwidth=rz_src->w/factorx; - while (dstwidth*factorx>rz_src->w) { dstwidth--; } - dstheight=rz_src->h/factory; - while (dstheight*factory>rz_src->h) { dstheight--; } - - /* - * Alloc space to completely contain the shrunken surface - */ - rz_dst = NULL; - if (is32bit) { - /* - * Target surface is 32bit with source RGBA/ABGR ordering - */ - rz_dst = - SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight, 32, - rz_src->format->Rmask, rz_src->format->Gmask, - rz_src->format->Bmask, rz_src->format->Amask); - } else { - /* - * Target surface is 8bit - */ - rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight, 8, 0, 0, 0, 0); - } - - /* - * Lock source surface - */ - SDL_LockSurface(rz_src); - /* - * Check which kind of surface we have - */ - if (is32bit) { - /* - * Call the 32bit transformation routine to do the shrinking (using alpha) - */ - shrinkSurfaceRGBA(rz_src, rz_dst, factorx, factory); - /* - * Turn on source-alpha support - */ - SDL_SetAlpha(rz_dst, SDL_SRCALPHA, 255); - } else { - /* - * Copy palette and colorkey info - */ - for (i = 0; i < rz_src->format->palette->ncolors; i++) { - rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i]; - } - rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors; - /* - * Call the 8bit transformation routine to do the shrinking - */ - shrinkSurfaceY(rz_src, rz_dst, factorx, factory); - if (rz_src->flags & SDL_SRCCOLORKEY) - SDL_SetColorKey(rz_dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, rz_src->format->colorkey); - } - /* - * Unlock source surface - */ - SDL_UnlockSurface(rz_src); - - /* - * Cleanup temp surface - */ - if (src_converted) { - SDL_FreeSurface(rz_src); - } - - /* - * Return destination surface - */ - return (rz_dst); -} +typedef struct tColorY { + Uint8 y; +} tColorY; + +/*! +\brief Returns maximum of two numbers a and b. +*/ +#define MAX(a,b) (((a) > (b)) ? (a) : (b)) + +/*! +\brief Number of guard rows added to destination surfaces. + +This is a simple but effective workaround for observed issues. +These rows allocate extra memory and are then hidden from the surface. +Rows are added to the end of destination surfaces when they are allocated. +This catches any potential overflows which seem to happen with +just the right src image dimensions and scale/rotation and can lead +to a situation where the program can segfault. +*/ +#define GUARD_ROWS (2) + +/*! +\brief Lower limit of absolute zoom factor or rotation degrees. +*/ +#define VALUE_LIMIT 0.001 + +/*! +\brief Returns colorkey info for a surface +*/ +Uint32 _colorkey(SDL_Surface *src) +{ + Uint32 key = 0; +#if (SDL_MINOR_VERSION == 3) + SDL_GetColorKey(src, &key); +#else + if (src) + { + key = src->format->colorkey; + } +#endif + return key; +} + + +/*! +\brief Internal 32 bit integer-factor averaging Shrinker. + +Shrinks 32 bit RGBA/ABGR 'src' surface to 'dst' surface. +Averages color and alpha values values of src pixels to calculate dst pixels. +Assumes src and dst surfaces are of 32 bit depth. +Assumes dst surface was allocated with the correct dimensions. + +\param src The surface to shrink (input). +\param dst The shrunken surface (output). +\param factorx The horizontal shrinking ratio. +\param factory The vertical shrinking ratio. + +\return 0 for success or -1 for error. +*/ +int _shrinkSurfaceRGBA(SDL_Surface * src, SDL_Surface * dst, int factorx, int factory) +{ + int x, y, dx, dy, sgap, dgap, ra, ga, ba, aa; + int n_average; + tColorRGBA *sp, *osp, *oosp; + tColorRGBA *dp; + + /* + * Averaging integer shrink + */ + + /* Precalculate division factor */ + n_average = factorx*factory; + + /* + * Scan destination + */ + sp = (tColorRGBA *) src->pixels; + sgap = src->pitch - src->w * 4; + + dp = (tColorRGBA *) dst->pixels; + dgap = dst->pitch - dst->w * 4; + + for (y = 0; y < dst->h; y++) { + + osp=sp; + for (x = 0; x < dst->w; x++) { + + /* Trace out source box and accumulate */ + oosp=sp; + ra=ga=ba=aa=0; + for (dy=0; dy < factory; dy++) { + for (dx=0; dx < factorx; dx++) { + ra += sp->r; + ga += sp->g; + ba += sp->b; + aa += sp->a; + + sp++; + } + /* src dx loop */ + sp = (tColorRGBA *)((Uint8*)sp + (src->pitch - 4*factorx)); // next y + } + /* src dy loop */ + + /* next box-x */ + sp = (tColorRGBA *)((Uint8*)oosp + 4*factorx); + + /* Store result in destination */ + dp->r = ra/n_average; + dp->g = ga/n_average; + dp->b = ba/n_average; + dp->a = aa/n_average; + + /* + * Advance destination pointer + */ + dp++; + } + /* dst x loop */ + + /* next box-y */ + sp = (tColorRGBA *)((Uint8*)osp + src->pitch*factory); + + /* + * Advance destination pointers + */ + dp = (tColorRGBA *) ((Uint8 *) dp + dgap); + } + /* dst y loop */ + + return (0); +} + +/*! +\brief Internal 8 bit integer-factor averaging shrinker. + +Shrinks 8bit Y 'src' surface to 'dst' surface. +Averages color (brightness) values values of src pixels to calculate dst pixels. +Assumes src and dst surfaces are of 8 bit depth. +Assumes dst surface was allocated with the correct dimensions. + +\param src The surface to shrink (input). +\param dst The shrunken surface (output). +\param factorx The horizontal shrinking ratio. +\param factory The vertical shrinking ratio. + +\return 0 for success or -1 for error. +*/ +int _shrinkSurfaceY(SDL_Surface * src, SDL_Surface * dst, int factorx, int factory) +{ + int x, y, dx, dy, sgap, dgap, a; + int n_average; + Uint8 *sp, *osp, *oosp; + Uint8 *dp; + + /* + * Averaging integer shrink + */ + + /* Precalculate division factor */ + n_average = factorx*factory; + + /* + * Scan destination + */ + sp = (Uint8 *) src->pixels; + sgap = src->pitch - src->w; + + dp = (Uint8 *) dst->pixels; + dgap = dst->pitch - dst->w; + + for (y = 0; y < dst->h; y++) { + + osp=sp; + for (x = 0; x < dst->w; x++) { + + /* Trace out source box and accumulate */ + oosp=sp; + a=0; + for (dy=0; dy < factory; dy++) { + for (dx=0; dx < factorx; dx++) { + a += (*sp); + /* next x */ + sp++; + } + /* end src dx loop */ + /* next y */ + sp = (Uint8 *)((Uint8*)sp + (src->pitch - factorx)); + } + /* end src dy loop */ + + /* next box-x */ + sp = (Uint8 *)((Uint8*)oosp + factorx); + + /* Store result in destination */ + *dp = a/n_average; + + /* + * Advance destination pointer + */ + dp++; + } + /* end dst x loop */ + + /* next box-y */ + sp = (Uint8 *)((Uint8*)osp + src->pitch*factory); + + /* + * Advance destination pointers + */ + dp = (Uint8 *)((Uint8 *)dp + dgap); + } + /* end dst y loop */ + + return (0); +} + +/*! +\brief Internal 32 bit Zoomer with optional anti-aliasing by bilinear interpolation. + +Zooms 32 bit RGBA/ABGR 'src' surface to 'dst' surface. +Assumes src and dst surfaces are of 32 bit depth. +Assumes dst surface was allocated with the correct dimensions. + +\param src The surface to zoom (input). +\param dst The zoomed surface (output). +\param flipx Flag indicating if the image should be horizontally flipped. +\param flipy Flag indicating if the image should be vertically flipped. +\param smooth Antialiasing flag; set to SMOOTHING_ON to enable. + +\return 0 for success or -1 for error. +*/ +int _zoomSurfaceRGBA(SDL_Surface * src, SDL_Surface * dst, int flipx, int flipy, int smooth) +{ + int x, y, sx, sy, *sax, *say, *csax, *csay, csx, csy, ex, ey, t1, t2, sstep, lx, ly; + tColorRGBA *c00, *c01, *c10, *c11, *cswap; + tColorRGBA *sp, *csp, *dp; + int dgap; + + /* + * Variable setup + */ + if (smooth) { + /* + * For interpolation: assume source dimension is one pixel + * smaller to avoid overflow on right and bottom edge. + */ + sx = (int) (65536.0 * (float) (src->w - 1) / (float) dst->w); + sy = (int) (65536.0 * (float) (src->h - 1) / (float) dst->h); + } else { + sx = (int) (65536.0 * (float) src->w / (float) dst->w); + sy = (int) (65536.0 * (float) src->h / (float) dst->h); + } + + /* + * Allocate memory for row increments + */ + if ((sax = (int *) malloc((dst->w + 1) * sizeof(Uint32))) == NULL) { + return (-1); + } + if ((say = (int *) malloc((dst->h + 1) * sizeof(Uint32))) == NULL) { + free(sax); + return (-1); + } + + /* + * Precalculate row increments + */ + sp = csp = (tColorRGBA *) src->pixels; + dp = (tColorRGBA *) dst->pixels; + + if (flipx) csp += (src->w-1); + if (flipy) csp += ((src->pitch/4)*(src->h-1)); + + csx = 0; + csax = sax; + for (x = 0; x <= dst->w; x++) { + *csax = csx; + csax++; + csx &= 0xffff; + csx += sx; + } + csy = 0; + csay = say; + for (y = 0; y <= dst->h; y++) { + *csay = csy; + csay++; + csy &= 0xffff; + csy += sy; + } + + dgap = dst->pitch - dst->w * 4; + + /* + * Switch between interpolating and non-interpolating code + */ + if (smooth) { + + /* + * Interpolating Zoom + */ + + /* + * Scan destination + */ + csay = say; + ly = 0; + for (y = 0; y < dst->h; y++) { + /* + * Setup color source pointers + */ + c00 = csp; + c01 = csp; + c01++; + c10 = csp; + c10 += src->pitch/4; + c11 = c10; + c11++; + if (flipx) { + cswap = c00; c00=c01; c01=cswap; + cswap = c10; c10=c11; c11=cswap; + } + if (flipy) { + cswap = c00; c00=c10; c10=cswap; + cswap = c01; c01=c11; c11=cswap; + } + + csax = sax; + lx = 0; + for (x = 0; x < dst->w; x++) { + /* + * Draw and interpolate colors + */ + ex = (*csax & 0xffff); + ey = (*csay & 0xffff); + t1 = ((((c01->r - c00->r) * ex) >> 16) + c00->r) & 0xff; + t2 = ((((c11->r - c10->r) * ex) >> 16) + c10->r) & 0xff; + dp->r = (((t2 - t1) * ey) >> 16) + t1; + t1 = ((((c01->g - c00->g) * ex) >> 16) + c00->g) & 0xff; + t2 = ((((c11->g - c10->g) * ex) >> 16) + c10->g) & 0xff; + dp->g = (((t2 - t1) * ey) >> 16) + t1; + t1 = ((((c01->b - c00->b) * ex) >> 16) + c00->b) & 0xff; + t2 = ((((c11->b - c10->b) * ex) >> 16) + c10->b) & 0xff; + dp->b = (((t2 - t1) * ey) >> 16) + t1; + t1 = ((((c01->a - c00->a) * ex) >> 16) + c00->a) & 0xff; + t2 = ((((c11->a - c10->a) * ex) >> 16) + c10->a) & 0xff; + dp->a = (((t2 - t1) * ey) >> 16) + t1; + + /* + * Advance source pointers + */ + csax++; + if (*csax > 0) + { + sstep = (*csax >> 16); + lx += sstep; + if (flipx) sstep = -sstep; + if (lx <= src->w) + { + c00 += sstep; + c01 += sstep; + c10 += sstep; + c11 += sstep; + } + } + + /* + * Advance destination pointer + */ + dp++; + } + + /* + * Advance source pointer + */ + csay++; + if (*csay > 0) + { + sstep = (*csay >> 16); + ly += sstep; + if (flipy) sstep = -sstep; + if (ly < src->h) + { + csp += (sstep * (src->pitch/4)); + } + } + + /* + * Advance destination pointers + */ + dp = (tColorRGBA *) ((Uint8 *) dp + dgap); + } + } else { + + /* + * Non-Interpolating Zoom + */ + csay = say; + for (y = 0; y < dst->h; y++) { + sp = csp; + csax = sax; + for (x = 0; x < dst->w; x++) { + /* + * Draw + */ + *dp = *sp; + /* + * Advance source pointers + */ + csax++; + if (*csax > 0) + { + sstep = (*csax >> 16); + if (flipx) sstep = -sstep; + sp += sstep; + } + /* + * Advance destination pointer + */ + dp++; + } + /* + * Advance source pointer + */ + csay++; + if (*csay > 0) + { + sstep = (*csay >> 16) * (src->pitch/4); + if (flipy) sstep = -sstep; + csp += sstep; + } + + /* + * Advance destination pointers + */ + dp = (tColorRGBA *) ((Uint8 *) dp + dgap); + } + } + + /* + * Remove temp arrays + */ + free(sax); + free(say); + + return (0); +} + +/*! + +\brief Internal 8 bit Zoomer without smoothing. + +Zooms 8bit palette/Y 'src' surface to 'dst' surface. +Assumes src and dst surfaces are of 8 bit depth. +Assumes dst surface was allocated with the correct dimensions. + +\param src The surface to zoom (input). +\param dst The zoomed surface (output). +\param flipx Flag indicating if the image should be horizontally flipped. +\param flipy Flag indicating if the image should be vertically flipped. + +\return 0 for success or -1 for error. +*/ +int _zoomSurfaceY(SDL_Surface * src, SDL_Surface * dst, int flipx, int flipy) +{ + int x, y; + Uint32 *sax, *say, *csax, *csay; + int csx, csy; + Uint8 *sp, *dp, *csp; + int dgap; + + /* + * Allocate memory for row increments + */ + if ((sax = (Uint32 *) malloc((dst->w + 1) * sizeof(Uint32))) == NULL) { + return (-1); + } + if ((say = (Uint32 *) malloc((dst->h + 1) * sizeof(Uint32))) == NULL) { + free(sax); + return (-1); + } + + /* + * Pointer setup + */ + sp = csp = (Uint8 *) src->pixels; + dp = (Uint8 *) dst->pixels; + dgap = dst->pitch - dst->w; + + if (flipx) csp += (src->w-1); + if (flipy) csp = ( (Uint8*)csp + src->pitch*(src->h-1) ); + + /* + * Precalculate row increments + */ + csx = 0; + csax = sax; + for (x = 0; x < dst->w; x++) { + csx += src->w; + *csax = 0; + while (csx >= dst->w) { + csx -= dst->w; + (*csax)++; + } + csax++; + } + csy = 0; + csay = say; + for (y = 0; y < dst->h; y++) { + csy += src->h; + *csay = 0; + while (csy >= dst->h) { + csy -= dst->h; + (*csay)++; + } + csay++; + } + + /* + * Draw + */ + csay = say; + for (y = 0; y < dst->h; y++) { + csax = sax; + sp = csp; + for (x = 0; x < dst->w; x++) { + /* + * Draw + */ + *dp = *sp; + /* + * Advance source pointers + */ + sp += (*csax) * (flipx ? -1 : 1); + csax++; + /* + * Advance destination pointer + */ + dp++; + } + /* + * Advance source pointer (for row) + */ + csp += ((*csay) * src->pitch) * (flipy ? -1 : 1); + csay++; + + /* + * Advance destination pointers + */ + dp += dgap; + } + + /* + * Remove temp arrays + */ + free(sax); + free(say); + + return (0); +} + +/*! +\brief Internal 32 bit rotozoomer with optional anti-aliasing. + +Rotates and zooms 32 bit RGBA/ABGR 'src' surface to 'dst' surface based on the control +parameters by scanning the destination surface and applying optionally anti-aliasing +by bilinear interpolation. +Assumes src and dst surfaces are of 32 bit depth. +Assumes dst surface was allocated with the correct dimensions. + +\param src Source surface. +\param dst Destination surface. +\param cx Horizontal center coordinate. +\param cy Vertical center coordinate. +\param isin Integer version of sine of angle. +\param icos Integer version of cosine of angle. +\param flipx Flag indicating horizontal mirroring should be applied. +\param flipy Flag indicating vertical mirroring should be applied. +\param smooth Flag indicating anti-aliasing should be used. +*/ +void _transformSurfaceRGBA(SDL_Surface * src, SDL_Surface * dst, int cx, int cy, int isin, int icos, int flipx, int flipy, int smooth) +{ + int x, y, t1, t2, dx, dy, xd, yd, sdx, sdy, ax, ay, ex, ey, sw, sh; + tColorRGBA c00, c01, c10, c11, cswap; + tColorRGBA *pc, *sp; + int gap; + + /* + * Variable setup + */ + xd = ((src->w - dst->w) << 15); + yd = ((src->h - dst->h) << 15); + ax = (cx << 16) - (icos * cx); + ay = (cy << 16) - (isin * cx); + sw = src->w - 1; + sh = src->h - 1; + pc = (tColorRGBA*) dst->pixels; + gap = dst->pitch - dst->w * 4; + + /* + * Switch between interpolating and non-interpolating code + */ + if (smooth) { + for (y = 0; y < dst->h; y++) { + dy = cy - y; + sdx = (ax + (isin * dy)) + xd; + sdy = (ay - (icos * dy)) + yd; + for (x = 0; x < dst->w; x++) { + dx = (sdx >> 16); + dy = (sdy >> 16); + if (flipx) dx = sw - dx; + if (flipy) dy = sh - dy; + if ((dx > -1) && (dy > -1) && (dx < (src->w-1)) && (dy < (src->h-1))) { + sp = (tColorRGBA *)src->pixels;; + sp += ((src->pitch/4) * dy); + sp += dx; + c00 = *sp; + sp += 1; + c01 = *sp; + sp += (src->pitch/4); + c11 = *sp; + sp -= 1; + c10 = *sp; + if (flipx) { + cswap = c00; c00=c01; c01=cswap; + cswap = c10; c10=c11; c11=cswap; + } + if (flipy) { + cswap = c00; c00=c10; c10=cswap; + cswap = c01; c01=c11; c11=cswap; + } + /* + * Interpolate colors + */ + ex = (sdx & 0xffff); + ey = (sdy & 0xffff); + t1 = ((((c01.r - c00.r) * ex) >> 16) + c00.r) & 0xff; + t2 = ((((c11.r - c10.r) * ex) >> 16) + c10.r) & 0xff; + pc->r = (((t2 - t1) * ey) >> 16) + t1; + t1 = ((((c01.g - c00.g) * ex) >> 16) + c00.g) & 0xff; + t2 = ((((c11.g - c10.g) * ex) >> 16) + c10.g) & 0xff; + pc->g = (((t2 - t1) * ey) >> 16) + t1; + t1 = ((((c01.b - c00.b) * ex) >> 16) + c00.b) & 0xff; + t2 = ((((c11.b - c10.b) * ex) >> 16) + c10.b) & 0xff; + pc->b = (((t2 - t1) * ey) >> 16) + t1; + t1 = ((((c01.a - c00.a) * ex) >> 16) + c00.a) & 0xff; + t2 = ((((c11.a - c10.a) * ex) >> 16) + c10.a) & 0xff; + pc->a = (((t2 - t1) * ey) >> 16) + t1; + } + sdx += icos; + sdy += isin; + pc++; + } + pc = (tColorRGBA *) ((Uint8 *) pc + gap); + } + } else { + for (y = 0; y < dst->h; y++) { + dy = cy - y; + sdx = (ax + (isin * dy)) + xd; + sdy = (ay - (icos * dy)) + yd; + for (x = 0; x < dst->w; x++) { + dx = (short) (sdx >> 16); + dy = (short) (sdy >> 16); + if (flipx) dx = (src->w-1)-dx; + if (flipy) dy = (src->h-1)-dy; + if ((dx >= 0) && (dy >= 0) && (dx < src->w) && (dy < src->h)) { + sp = (tColorRGBA *) ((Uint8 *) src->pixels + src->pitch * dy); + sp += dx; + *pc = *sp; + } + sdx += icos; + sdy += isin; + pc++; + } + pc = (tColorRGBA *) ((Uint8 *) pc + gap); + } + } +} + +/*! + +\brief Rotates and zooms 8 bit palette/Y 'src' surface to 'dst' surface without smoothing. + +Rotates and zooms 8 bit RGBA/ABGR 'src' surface to 'dst' surface based on the control +parameters by scanning the destination surface. +Assumes src and dst surfaces are of 8 bit depth. +Assumes dst surface was allocated with the correct dimensions. + +\param src Source surface. +\param dst Destination surface. +\param cx Horizontal center coordinate. +\param cy Vertical center coordinate. +\param isin Integer version of sine of angle. +\param icos Integer version of cosine of angle. +\param flipx Flag indicating horizontal mirroring should be applied. +\param flipy Flag indicating vertical mirroring should be applied. +*/ +void transformSurfaceY(SDL_Surface * src, SDL_Surface * dst, int cx, int cy, int isin, int icos, int flipx, int flipy) +{ + int x, y, dx, dy, xd, yd, sdx, sdy, ax, ay, sw, sh; + tColorY *pc, *sp; + int gap; + + /* + * Variable setup + */ + xd = ((src->w - dst->w) << 15); + yd = ((src->h - dst->h) << 15); + ax = (cx << 16) - (icos * cx); + ay = (cy << 16) - (isin * cx); + sw = src->w - 1; + sh = src->h - 1; + pc = (tColorY*) dst->pixels; + gap = dst->pitch - dst->w; + /* + * Clear surface to colorkey + */ + memset(pc, (unsigned char) (_colorkey(src) & 0xff), dst->pitch * dst->h); + /* + * Iterate through destination surface + */ + for (y = 0; y < dst->h; y++) { + dy = cy - y; + sdx = (ax + (isin * dy)) + xd; + sdy = (ay - (icos * dy)) + yd; + for (x = 0; x < dst->w; x++) { + dx = (short) (sdx >> 16); + dy = (short) (sdy >> 16); + if (flipx) dx = (src->w-1)-dx; + if (flipy) dy = (src->h-1)-dy; + if ((dx >= 0) && (dy >= 0) && (dx < src->w) && (dy < src->h)) { + sp = (tColorY *) (src->pixels); + sp += (src->pitch * dy + dx); + *pc = *sp; + } + sdx += icos; + sdy += isin; + pc++; + } + pc += gap; + } +} + +/*! +\brief Rotates a 32 bit surface in increments of 90 degrees. + +Specialized 90 degree rotator which rotates a 'src' surface in 90 degree +increments clockwise returning a new surface. Faster than rotozoomer since +not scanning or interpolation takes place. Input surface must be 32 bit. +(code contributed by J. Schiller, improved by C. Allport and A. Schiffler) + +\param src Source surface to rotate. +\param numClockwiseTurns Number of clockwise 90 degree turns to apply to the source. + +\returns The new, rotated surface; or NULL for surfaces with incorrect input format. +*/ +SDL_Surface* rotateSurface90Degrees(SDL_Surface* src, int numClockwiseTurns) +{ + int row, col, newWidth, newHeight; + int bpp, src_ipr, dst_ipr; + SDL_Surface* dst; + Uint32* srcBuf; + Uint32* dstBuf; + + /* Has to be a valid surface pointer and only 32-bit surfaces (for now) */ + if (!src || src->format->BitsPerPixel != 32) { return NULL; } + + /* normalize numClockwiseTurns */ + while(numClockwiseTurns < 0) { numClockwiseTurns += 4; } + numClockwiseTurns = (numClockwiseTurns % 4); + + /* if it's even, our new width will be the same as the source surface */ + newWidth = (numClockwiseTurns % 2) ? (src->h) : (src->w); + newHeight = (numClockwiseTurns % 2) ? (src->w) : (src->h); + dst = SDL_CreateRGBSurface( src->flags, newWidth, newHeight, src->format->BitsPerPixel, + src->format->Rmask, + src->format->Gmask, + src->format->Bmask, + src->format->Amask); + if(!dst) { + return NULL; + } + + if (SDL_MUSTLOCK(dst)) { + SDL_LockSurface(dst); + } + if (SDL_MUSTLOCK(dst)) { + SDL_LockSurface(dst); + } + + /* Calculate int-per-row */ + bpp = src->format->BitsPerPixel / 8; + src_ipr = src->pitch / bpp; + dst_ipr = dst->pitch / bpp; + + switch(numClockwiseTurns) { + case 0: /* Make a copy of the surface */ + { + /* Unfortunately SDL_BlitSurface cannot be used to make a copy of the surface + since it does not preserve alpha. */ + + if (src->pitch == dst->pitch) { + /* If the pitch is the same for both surfaces, the memory can be copied all at once. */ + memcpy(dst->pixels, src->pixels, (src->h * src->pitch)); + } + else + { + /* If the pitch differs, copy each row separately */ + srcBuf = (Uint32*)(src->pixels); + dstBuf = (Uint32*)(dst->pixels); + for (row = 0; row < src->h; row++) { + memcpy(dstBuf, srcBuf, dst->w * bpp); + srcBuf += src_ipr; + dstBuf += dst_ipr; + } /* end for(col) */ + } /* end for(row) */ + } + break; + + /* rotate clockwise */ + case 1: /* rotated 90 degrees clockwise */ + { + for (row = 0; row < src->h; ++row) { + srcBuf = (Uint32*)(src->pixels) + (row * src_ipr); + dstBuf = (Uint32*)(dst->pixels) + (dst->w - row - 1); + for (col = 0; col < src->w; ++col) { + *dstBuf = *srcBuf; + ++srcBuf; + dstBuf += dst_ipr; + } + /* end for(col) */ + } + /* end for(row) */ + } + break; + + case 2: /* rotated 180 degrees clockwise */ + { + for (row = 0; row < src->h; ++row) { + srcBuf = (Uint32*)(src->pixels) + (row * src_ipr); + dstBuf = (Uint32*)(dst->pixels) + ((dst->h - row - 1) * dst_ipr) + (dst->w - 1); + for (col = 0; col < src->w; ++col) { + *dstBuf = *srcBuf; + ++srcBuf; + --dstBuf; + } + } + } + break; + + case 3: + { + for (row = 0; row < src->h; ++row) { + srcBuf = (Uint32*)(src->pixels) + (row * src_ipr); + dstBuf = (Uint32*)(dst->pixels) + row + ((dst->h - 1) * dst_ipr); + for (col = 0; col < src->w; ++col) { + *dstBuf = *srcBuf; + ++srcBuf; + dstBuf -= dst_ipr; + } + } + } + break; + } + /* end switch */ + + if (SDL_MUSTLOCK(src)) { + SDL_UnlockSurface(src); + } + if (SDL_MUSTLOCK(dst)) { + SDL_UnlockSurface(dst); + } + + return dst; +} + + +/*! +\brief Internal target surface sizing function for rotozooms with trig result return. + +\param width The source surface width. +\param height The source surface height. +\param angle The angle to rotate in degrees. +\param zoomx The horizontal scaling factor. +\param zoomy The vertical scaling factor. +\param dstwidth The calculated width of the destination surface. +\param dstheight The calculated height of the destination surface. +\param canglezoom The sine of the angle adjusted by the zoom factor. +\param sanglezoom The cosine of the angle adjusted by the zoom factor. + +*/ +void _rotozoomSurfaceSizeTrig(int width, int height, double angle, double zoomx, double zoomy, + int *dstwidth, int *dstheight, + double *canglezoom, double *sanglezoom) +{ + double x, y, cx, cy, sx, sy; + double radangle; + int dstwidthhalf, dstheighthalf; + + /* + * Determine destination width and height by rotating a centered source box + */ + radangle = angle * (M_PI / 180.0); + *sanglezoom = sin(radangle); + *canglezoom = cos(radangle); + *sanglezoom *= zoomx; + *canglezoom *= zoomx; + x = width / 2; + y = height / 2; + cx = *canglezoom * x; + cy = *canglezoom * y; + sx = *sanglezoom * x; + sy = *sanglezoom * y; + + dstwidthhalf = MAX((int) + ceil(MAX(MAX(MAX(fabs(cx + sy), fabs(cx - sy)), fabs(-cx + sy)), fabs(-cx - sy))), 1); + dstheighthalf = MAX((int) + ceil(MAX(MAX(MAX(fabs(sx + cy), fabs(sx - cy)), fabs(-sx + cy)), fabs(-sx - cy))), 1); + *dstwidth = 2 * dstwidthhalf; + *dstheight = 2 * dstheighthalf; +} + +/*! +\brief Returns the size of the resulting target surface for a rotozoomSurfaceXY() call. + +\param width The source surface width. +\param height The source surface height. +\param angle The angle to rotate in degrees. +\param zoomx The horizontal scaling factor. +\param zoomy The vertical scaling factor. +\param dstwidth The calculated width of the rotozoomed destination surface. +\param dstheight The calculated height of the rotozoomed destination surface. +*/ +void rotozoomSurfaceSizeXY(int width, int height, double angle, double zoomx, double zoomy, int *dstwidth, int *dstheight) +{ + double dummy_sanglezoom, dummy_canglezoom; + + _rotozoomSurfaceSizeTrig(width, height, angle, zoomx, zoomy, dstwidth, dstheight, &dummy_sanglezoom, &dummy_canglezoom); +} + +/*! +\brief Returns the size of the resulting target surface for a rotozoomSurface() call. + +\param width The source surface width. +\param height The source surface height. +\param angle The angle to rotate in degrees. +\param zoom The scaling factor. +\param dstwidth The calculated width of the rotozoomed destination surface. +\param dstheight The calculated height of the rotozoomed destination surface. +*/ +void rotozoomSurfaceSize(int width, int height, double angle, double zoom, int *dstwidth, int *dstheight) +{ + double dummy_sanglezoom, dummy_canglezoom; + + _rotozoomSurfaceSizeTrig(width, height, angle, zoom, zoom, dstwidth, dstheight, &dummy_sanglezoom, &dummy_canglezoom); +} + +/*! +\brief Rotates and zooms a surface and optional anti-aliasing. + +Rotates and zoomes a 32bit or 8bit 'src' surface to newly created 'dst' surface. +'angle' is the rotation in degrees and 'zoom' a scaling factor. If 'smooth' is set +then the destination 32bit surface is anti-aliased. If the surface is not 8bit +or 32bit RGBA/ABGR it will be converted into a 32bit RGBA format on the fly. + +\param src The surface to rotozoom. +\param angle The angle to rotate in degrees. +\param zoom The scaling factor. +\param smooth Antialiasing flag; set to SMOOTHING_ON to enable. + +\return The new rotozoomed surface. +*/ +SDL_Surface *rotozoomSurface(SDL_Surface * src, double angle, double zoom, int smooth) +{ + return rotozoomSurfaceXY(src, angle, zoom, zoom, smooth); +} + +/*! +\brief Rotates and zooms a surface with different horizontal and vertival scaling factors and optional anti-aliasing. + +Rotates and zooms a 32bit or 8bit 'src' surface to newly created 'dst' surface. +'angle' is the rotation in degrees, 'zoomx and 'zoomy' scaling factors. If 'smooth' is set +then the destination 32bit surface is anti-aliased. If the surface is not 8bit +or 32bit RGBA/ABGR it will be converted into a 32bit RGBA format on the fly. + +\param src The surface to rotozoom. +\param angle The angle to rotate in degrees. +\param zoomx The horizontal scaling factor. +\param zoomy The vertical scaling factor. +\param smooth Antialiasing flag; set to SMOOTHING_ON to enable. + +\return The new rotozoomed surface. +*/ +SDL_Surface *rotozoomSurfaceXY(SDL_Surface * src, double angle, double zoomx, double zoomy, int smooth) +{ + SDL_Surface *rz_src; + SDL_Surface *rz_dst; + double zoominv; + double sanglezoom, canglezoom, sanglezoominv, canglezoominv; + int dstwidthhalf, dstwidth, dstheighthalf, dstheight; + int is32bit; + int i, src_converted; + int flipx,flipy; + Uint8 r,g,b; + Uint32 colorkey = 0; + int colorKeyAvailable = 0; + + /* + * Sanity check + */ + if (src == NULL) + return (NULL); + + if (src->flags & SDL_SRCCOLORKEY) + { + colorkey = _colorkey(src); + SDL_GetRGB(colorkey, src->format, &r, &g, &b); + colorKeyAvailable = 1; + } + /* + * Determine if source surface is 32bit or 8bit + */ + is32bit = (src->format->BitsPerPixel == 32); + if ((is32bit) || (src->format->BitsPerPixel == 8)) { + /* + * Use source surface 'as is' + */ + rz_src = src; + src_converted = 0; + } else { + /* + * New source surface is 32bit with a defined RGBA ordering + */ + rz_src = + SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32, +#if SDL_BYTEORDER == SDL_LIL_ENDIAN + 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 +#else + 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff +#endif + ); + if(colorKeyAvailable) + SDL_SetColorKey(src, 0, 0); + + SDL_BlitSurface(src, NULL, rz_src, NULL); + + if(colorKeyAvailable) + SDL_SetColorKey(src, SDL_SRCCOLORKEY, colorkey); + src_converted = 1; + is32bit = 1; + } + + /* + * Sanity check zoom factor + */ + flipx = (zoomx<0.0); + if (flipx) zoomx=-zoomx; + flipy = (zoomy<0.0); + if (flipy) zoomy=-zoomy; + if (zoomx < VALUE_LIMIT) zoomx = VALUE_LIMIT; + if (zoomy < VALUE_LIMIT) zoomy = VALUE_LIMIT; + zoominv = 65536.0 / (zoomx * zoomx); + + /* + * Check if we have a rotozoom or just a zoom + */ + if (fabs(angle) > VALUE_LIMIT) { + + /* + * Angle!=0: full rotozoom + */ + /* + * ----------------------- + */ + + /* Determine target size */ + _rotozoomSurfaceSizeTrig(rz_src->w, rz_src->h, angle, zoomx, zoomy, &dstwidth, &dstheight, &canglezoom, &sanglezoom); + + /* + * Calculate target factors from sin/cos and zoom + */ + sanglezoominv = sanglezoom; + canglezoominv = canglezoom; + sanglezoominv *= zoominv; + canglezoominv *= zoominv; + + /* Calculate half size */ + dstwidthhalf = dstwidth / 2; + dstheighthalf = dstheight / 2; + + /* + * Alloc space to completely contain the rotated surface + */ + rz_dst = NULL; + if (is32bit) { + /* + * Target surface is 32bit with source RGBA/ABGR ordering + */ + rz_dst = + SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 32, + rz_src->format->Rmask, rz_src->format->Gmask, + rz_src->format->Bmask, rz_src->format->Amask); + } else { + /* + * Target surface is 8bit + */ + rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 8, 0, 0, 0, 0); + } + + /* Check target */ + if (rz_dst == NULL) + return NULL; + + /* Adjust for guard rows */ + rz_dst->h = dstheight; + + if (colorKeyAvailable == 1){ + colorkey = SDL_MapRGB(rz_dst->format, r, g, b); + + SDL_FillRect(rz_dst, NULL, colorkey ); + } + + /* + * Lock source surface + */ + if (SDL_MUSTLOCK(rz_src)) { + SDL_LockSurface(rz_src); + } + + /* + * Check which kind of surface we have + */ + if (is32bit) { + /* + * Call the 32bit transformation routine to do the rotation (using alpha) + */ + _transformSurfaceRGBA(rz_src, rz_dst, dstwidthhalf, dstheighthalf, + (int) (sanglezoominv), (int) (canglezoominv), + flipx, flipy, + smooth); + /* + * Turn on source-alpha support + */ + SDL_SetAlpha(rz_dst, SDL_SRCALPHA, 255); + SDL_SetColorKey(rz_dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, _colorkey(rz_src)); + } else { + /* + * Copy palette and colorkey info + */ + for (i = 0; i < rz_src->format->palette->ncolors; i++) { + rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i]; + } + rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors; + /* + * Call the 8bit transformation routine to do the rotation + */ + transformSurfaceY(rz_src, rz_dst, dstwidthhalf, dstheighthalf, + (int) (sanglezoominv), (int) (canglezoominv), + flipx, flipy); + SDL_SetColorKey(rz_dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, _colorkey(rz_src)); + } + /* + * Unlock source surface + */ + if (SDL_MUSTLOCK(rz_src)) { + SDL_UnlockSurface(rz_src); + } + + } else { + + /* + * Angle=0: Just a zoom + */ + /* + * -------------------- + */ + + /* + * Calculate target size + */ + zoomSurfaceSize(rz_src->w, rz_src->h, zoomx, zoomy, &dstwidth, &dstheight); + + /* + * Alloc space to completely contain the zoomed surface + */ + rz_dst = NULL; + if (is32bit) { + /* + * Target surface is 32bit with source RGBA/ABGR ordering + */ + rz_dst = + SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 32, + rz_src->format->Rmask, rz_src->format->Gmask, + rz_src->format->Bmask, rz_src->format->Amask); + } else { + /* + * Target surface is 8bit + */ + rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 8, 0, 0, 0, 0); + } + + /* Check target */ + if (rz_dst == NULL) + return NULL; + + /* Adjust for guard rows */ + rz_dst->h = dstheight; + + if (colorKeyAvailable == 1){ + colorkey = SDL_MapRGB(rz_dst->format, r, g, b); + + SDL_FillRect(rz_dst, NULL, colorkey ); + } + + /* + * Lock source surface + */ + if (SDL_MUSTLOCK(rz_src)) { + SDL_LockSurface(rz_src); + } + + /* + * Check which kind of surface we have + */ + if (is32bit) { + /* + * Call the 32bit transformation routine to do the zooming (using alpha) + */ + _zoomSurfaceRGBA(rz_src, rz_dst, flipx, flipy, smooth); + + /* + * Turn on source-alpha support + */ + SDL_SetAlpha(rz_dst, SDL_SRCALPHA, 255); + SDL_SetColorKey(rz_dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, _colorkey(rz_src)); + } else { + /* + * Copy palette and colorkey info + */ + for (i = 0; i < rz_src->format->palette->ncolors; i++) { + rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i]; + } + rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors; + + /* + * Call the 8bit transformation routine to do the zooming + */ + _zoomSurfaceY(rz_src, rz_dst, flipx, flipy); + SDL_SetColorKey(rz_dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, _colorkey(rz_src)); + } + + /* + * Unlock source surface + */ + if (SDL_MUSTLOCK(rz_src)) { + SDL_UnlockSurface(rz_src); + } + } + + /* + * Cleanup temp surface + */ + if (src_converted) { + SDL_FreeSurface(rz_src); + } + + /* + * Return destination surface + */ + return (rz_dst); +} + +/*! +\brief Calculates the size of the target surface for a zoomSurface() call. + +The minimum size of the target surface is 1. The input factors can be positive or negative. + +\param width The width of the source surface to zoom. +\param height The height of the source surface to zoom. +\param zoomx The horizontal zoom factor. +\param zoomy The vertical zoom factor. +\param dstwidth Pointer to an integer to store the calculated width of the zoomed target surface. +\param dstheight Pointer to an integer to store the calculated height of the zoomed target surface. +*/ +void zoomSurfaceSize(int width, int height, double zoomx, double zoomy, int *dstwidth, int *dstheight) +{ + /* + * Make zoom factors positive + */ + int flipx, flipy; + flipx = (zoomx<0.0); + if (flipx) zoomx = -zoomx; + flipy = (zoomy<0.0); + if (flipy) zoomy = -zoomy; + + /* + * Sanity check zoom factors + */ + if (zoomx < VALUE_LIMIT) { + zoomx = VALUE_LIMIT; + } + if (zoomy < VALUE_LIMIT) { + zoomy = VALUE_LIMIT; + } + + /* + * Calculate target size + */ + *dstwidth = (int) ((double) width * zoomx); + *dstheight = (int) ((double) height * zoomy); + if (*dstwidth < 1) { + *dstwidth = 1; + } + if (*dstheight < 1) { + *dstheight = 1; + } +} + +/*! +\brief Zoom a surface by independent horizontal and vertical factors with optional smoothing. + +Zooms a 32bit or 8bit 'src' surface to newly created 'dst' surface. +'zoomx' and 'zoomy' are scaling factors for width and height. If 'smooth' is on +then the destination 32bit surface is anti-aliased. If the surface is not 8bit +or 32bit RGBA/ABGR it will be converted into a 32bit RGBA format on the fly. +If zoom factors are negative, the image is flipped on the axes. + +\param src The surface to zoom. +\param zoomx The horizontal zoom factor. +\param zoomy The vertical zoom factor. +\param smooth Antialiasing flag; set to SMOOTHING_ON to enable. + +\return The new, zoomed surface. +*/ +SDL_Surface *zoomSurface(SDL_Surface * src, double zoomx, double zoomy, int smooth) +{ + SDL_Surface *rz_src; + SDL_Surface *rz_dst; + int dstwidth, dstheight; + int is32bit; + int i, src_converted; + int flipx, flipy; + + /* + * Sanity check + */ + if (src == NULL) + return (NULL); + + /* + * Determine if source surface is 32bit or 8bit + */ + is32bit = (src->format->BitsPerPixel == 32); + if ((is32bit) || (src->format->BitsPerPixel == 8)) { + /* + * Use source surface 'as is' + */ + rz_src = src; + src_converted = 0; + } else { + /* + * New source surface is 32bit with a defined RGBA ordering + */ + rz_src = + SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32, +#if SDL_BYTEORDER == SDL_LIL_ENDIAN + 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 +#else + 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff +#endif + ); + SDL_BlitSurface(src, NULL, rz_src, NULL); + src_converted = 1; + is32bit = 1; + } + + flipx = (zoomx<0.0); + if (flipx) zoomx = -zoomx; + flipy = (zoomy<0.0); + if (flipy) zoomy = -zoomy; + + /* Get size if target */ + zoomSurfaceSize(rz_src->w, rz_src->h, zoomx, zoomy, &dstwidth, &dstheight); + + /* + * Alloc space to completely contain the zoomed surface + */ + rz_dst = NULL; + if (is32bit) { + /* + * Target surface is 32bit with source RGBA/ABGR ordering + */ + rz_dst = + SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 32, + rz_src->format->Rmask, rz_src->format->Gmask, + rz_src->format->Bmask, rz_src->format->Amask); + } else { + /* + * Target surface is 8bit + */ + rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 8, 0, 0, 0, 0); + } + + /* Check target */ + if (rz_dst == NULL) + return NULL; + + /* Adjust for guard rows */ + rz_dst->h = dstheight; + + /* + * Lock source surface + */ + if (SDL_MUSTLOCK(rz_src)) { + SDL_LockSurface(rz_src); + } + + /* + * Check which kind of surface we have + */ + if (is32bit) { + /* + * Call the 32bit transformation routine to do the zooming (using alpha) + */ + _zoomSurfaceRGBA(rz_src, rz_dst, flipx, flipy, smooth); + /* + * Turn on source-alpha support + */ + SDL_SetAlpha(rz_dst, SDL_SRCALPHA, 255); + } else { + /* + * Copy palette and colorkey info + */ + for (i = 0; i < rz_src->format->palette->ncolors; i++) { + rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i]; + } + rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors; + /* + * Call the 8bit transformation routine to do the zooming + */ + _zoomSurfaceY(rz_src, rz_dst, flipx, flipy); + SDL_SetColorKey(rz_dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, _colorkey(rz_src)); + } + /* + * Unlock source surface + */ + if (SDL_MUSTLOCK(rz_src)) { + SDL_UnlockSurface(rz_src); + } + + /* + * Cleanup temp surface + */ + if (src_converted) { + SDL_FreeSurface(rz_src); + } + + /* + * Return destination surface + */ + return (rz_dst); +} + +/*! +\brief Shrink a surface by an integer ratio using averaging. + +Shrinks a 32bit or 8bit 'src' surface to a newly created 'dst' surface. +'factorx' and 'factory' are the shrinking ratios (i.e. 2=1/2 the size, +3=1/3 the size, etc.) The destination surface is antialiased by averaging +the source box RGBA or Y information. If the surface is not 8bit +or 32bit RGBA/ABGR it will be converted into a 32bit RGBA format on the fly. +The input surface is not modified. The output surface is newly allocated. + +\param src The surface to shrink. +\param factorx The horizontal shrinking ratio. +\param factory The vertical shrinking ratio. + +\return The new, shrunken surface. +*/ +SDL_Surface *shrinkSurface(SDL_Surface *src, int factorx, int factory) +{ + SDL_Surface *rz_src; + SDL_Surface *rz_dst; + int dstwidth, dstheight; + int is32bit; + int i, src_converted; + + /* + * Sanity check + */ + if (src == NULL) + return (NULL); + + /* + * Determine if source surface is 32bit or 8bit + */ + is32bit = (src->format->BitsPerPixel == 32); + if ((is32bit) || (src->format->BitsPerPixel == 8)) { + /* + * Use source surface 'as is' + */ + rz_src = src; + src_converted = 0; + } else { + /* + * New source surface is 32bit with a defined RGBA ordering + */ + rz_src = + SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32, +#if SDL_BYTEORDER == SDL_LIL_ENDIAN + 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 +#else + 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff +#endif + ); + SDL_BlitSurface(src, NULL, rz_src, NULL); + src_converted = 1; + is32bit = 1; + } + + /* Get size for target */ + dstwidth=rz_src->w/factorx; + while (dstwidth*factorx>rz_src->w) { dstwidth--; } + dstheight=rz_src->h/factory; + while (dstheight*factory>rz_src->h) { dstheight--; } + + /* + * Alloc space to completely contain the shrunken surface + * (with added guard rows) + */ + rz_dst = NULL; + if (is32bit) { + /* + * Target surface is 32bit with source RGBA/ABGR ordering + */ + rz_dst = + SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 32, + rz_src->format->Rmask, rz_src->format->Gmask, + rz_src->format->Bmask, rz_src->format->Amask); + } else { + /* + * Target surface is 8bit + */ + rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 8, 0, 0, 0, 0); + } + + /* Check target */ + if (rz_dst == NULL) + return NULL; + + /* Adjust for guard rows */ + rz_dst->h = dstheight; + + /* + * Lock source surface + */ + if (SDL_MUSTLOCK(rz_src)) { + SDL_LockSurface(rz_src); + } + + /* + * Check which kind of surface we have + */ + if (is32bit) { + /* + * Call the 32bit transformation routine to do the shrinking (using alpha) + */ + _shrinkSurfaceRGBA(rz_src, rz_dst, factorx, factory); + /* + * Turn on source-alpha support + */ + SDL_SetAlpha(rz_dst, SDL_SRCALPHA, 255); + } else { + /* + * Copy palette and colorkey info + */ + for (i = 0; i < rz_src->format->palette->ncolors; i++) { + rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i]; + } + rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors; + /* + * Call the 8bit transformation routine to do the shrinking + */ + _shrinkSurfaceY(rz_src, rz_dst, factorx, factory); + SDL_SetColorKey(rz_dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, _colorkey(rz_src)); + } + + /* + * Unlock source surface + */ + if (SDL_MUSTLOCK(rz_src)) { + SDL_UnlockSurface(rz_src); + } + + /* + * Cleanup temp surface + */ + if (src_converted) { + SDL_FreeSurface(rz_src); + } + + /* + * Return destination surface + */ + return (rz_dst); +} diff --git a/src/sdl-instead/SDL_rotozoom.h b/src/sdl-instead/SDL_rotozoom.h index 9773866..0fce281 100644 --- a/src/sdl-instead/SDL_rotozoom.h +++ b/src/sdl-instead/SDL_rotozoom.h @@ -1,9 +1,9 @@ /* - SDL_rotozoom - rotozoomer +SDL_rotozoom - rotozoomer - LGPL (c) A. Schiffler +LGPL (c) A. Schiffler */ @@ -23,93 +23,79 @@ extern "C" { #include "SDL.h" -/* ---- Defines */ + /* ---- Defines */ + /*! + \brief Disable anti-aliasing (no smoothing). + */ #define SMOOTHING_OFF 0 + + /*! + \brief Enable anti-aliasing (smoothing). + */ #define SMOOTHING_ON 1 -/* ---- Structures */ + /* ---- Function Prototypes */ - typedef struct tColorRGBA { - Uint8 r; - Uint8 g; - Uint8 b; - Uint8 a; - } tColorRGBA; +#if defined(WIN32) || defined(WIN64) +# if defined(DLL_EXPORT) && !defined(LIBSDL_GFX_DLL_IMPORT) +# define SDL_ROTOZOOM_SCOPE __declspec(dllexport) +# else +# ifdef LIBSDL_GFX_DLL_IMPORT +# define SDL_ROTOZOOM_SCOPE __declspec(dllimport) +# endif +# endif +#endif +#ifndef SDL_ROTOZOOM_SCOPE +# define SDL_ROTOZOOM_SCOPE extern +#endif - typedef struct tColorY { - Uint8 y; - } tColorY; + /* + + Rotozoom functions + + */ + + SDL_ROTOZOOM_SCOPE SDL_Surface *rotozoomSurface(SDL_Surface * src, double angle, double zoom, int smooth); + + SDL_ROTOZOOM_SCOPE SDL_Surface *rotozoomSurfaceXY + (SDL_Surface * src, double angle, double zoomx, double zoomy, int smooth); -/* ---- Prototypes */ + SDL_ROTOZOOM_SCOPE void rotozoomSurfaceSize(int width, int height, double angle, double zoom, int *dstwidth, + int *dstheight); -#define DLLINTERFACE + SDL_ROTOZOOM_SCOPE void rotozoomSurfaceSizeXY + (int width, int height, double angle, double zoomx, double zoomy, + int *dstwidth, int *dstheight); -/* - - rotozoomSurface() + /* - Rotates and zoomes a 32bit or 8bit 'src' surface to newly created 'dst' surface. - 'angle' is the rotation in degrees. 'zoom' a scaling factor. If 'smooth' is 1 - then the destination 32bit surface is anti-aliased. If the surface is not 8bit - or 32bit RGBA/ABGR it will be converted into a 32bit RGBA format on the fly. + Zooming functions -*/ + */ - DLLINTERFACE SDL_Surface *rotozoomSurface(SDL_Surface * src, double angle, double zoom, int smooth); + SDL_ROTOZOOM_SCOPE SDL_Surface *zoomSurface(SDL_Surface * src, double zoomx, double zoomy, int smooth); - DLLINTERFACE SDL_Surface *rotozoomSurfaceXY - (SDL_Surface * src, double angle, double zoomx, double zoomy, int smooth); + SDL_ROTOZOOM_SCOPE void zoomSurfaceSize(int width, int height, double zoomx, double zoomy, int *dstwidth, int *dstheight); -/* Returns the size of the target surface for a rotozoomSurface() call */ + /* - DLLINTERFACE void rotozoomSurfaceSize(int width, int height, double angle, double zoom, int *dstwidth, - int *dstheight); + Shrinking functions - DLLINTERFACE void rotozoomSurfaceSizeXY - (int width, int height, double angle, double zoomx, double zoomy, - int *dstwidth, int *dstheight); + */ -/* - - zoomSurface() + SDL_ROTOZOOM_SCOPE SDL_Surface *shrinkSurface(SDL_Surface * src, int factorx, int factory); - Zoomes a 32bit or 8bit 'src' surface to newly created 'dst' surface. - 'zoomx' and 'zoomy' are scaling factors for width and height. If 'smooth' is 1 - then the destination 32bit surface is anti-aliased. If the surface is not 8bit - or 32bit RGBA/ABGR it will be converted into a 32bit RGBA format on the fly. + /* -*/ + Specialized rotation functions - DLLINTERFACE SDL_Surface *zoomSurface(SDL_Surface * src, double zoomx, double zoomy, int smooth); + */ -/* Returns the size of the target surface for a zoomSurface() call */ + SDL_ROTOZOOM_SCOPE SDL_Surface* rotateSurface90Degrees(SDL_Surface* src, int numClockwiseTurns); - DLLINTERFACE void zoomSurfaceSize(int width, int height, double zoomx, double zoomy, int *dstwidth, int *dstheight); - - -/* - shrinkSurface() - - Shrinks a 32bit or 8bit 'src' surface ti a newly created 'dst' surface. - 'factorx' and 'factory' are the shrinking ratios (i.e. 2=1/2 the size, - 3=1/3 the size, etc.) The destination surface is antialiased by averaging - the source box RGBA or Y information. If the surface is not 8bit - or 32bit RGBA/ABGR it will be converted into a 32bit RGBA format on the fly. -*/ - - DLLINTERFACE SDL_Surface *shrinkSurface(SDL_Surface * src, int factorx, int factory); - -/* - - Other functions - -*/ - - DLLINTERFACE SDL_Surface* rotateSurface90Degrees(SDL_Surface* pSurf, int numClockwiseTurns); - -/* Ends C function definitions when using C++ */ + /* Ends C function definitions when using C++ */ #ifdef __cplusplus } #endif diff --git a/src/sdl-instead/game.c b/src/sdl-instead/game.c index ac5ff82..5f5845c 100644 --- a/src/sdl-instead/game.c +++ b/src/sdl-instead/game.c @@ -644,8 +644,7 @@ int game_change_hz(int hz) } unsigned int timer_counter = 0; - -gtimer_t timer_han = NULL; +gtimer_t timer_han = NULL_TIMER; static void anigif_do(void *data) { @@ -832,7 +831,7 @@ void game_release_theme(void) void game_done(int err) { gfx_del_timer(timer_han); - timer_han = NULL; + timer_han = NULL_TIMER; if (opt_autosave && curgame_dir && !err) game_save(0); @@ -1681,7 +1680,7 @@ inv: } { /* highlight new scene, to avoid flickering */ int x, y; - gfx_cursor(&x, &y, NULL, NULL); + gfx_cursor(&x, &y); game_highlight(x, y, 1); } game_cursor(CURSOR_DRAW); @@ -2085,7 +2084,7 @@ void game_cursor(int on) int oh = h; if (on != CURSOR_DRAW) { - gfx_cursor(&xc, &yc, NULL, NULL); + gfx_cursor(&xc, &yc); xc -= game_theme.cur_x; yc -= game_theme.cur_y; } @@ -2096,7 +2095,7 @@ void game_cursor(int on) grab = gfx_grab_screen(xc, yc, w, h); if (mouse_focus()) gfx_draw(cur, xc, yc); - + if (on != CURSOR_DRAW) { gfx_update(xc, yc, w, h); gfx_update(ox, oy, ow, oh); @@ -2218,7 +2217,7 @@ static void select_frame(int prev) struct el *elem = NULL; int x, y, w, h; - gfx_cursor(&x, &y, NULL, NULL); + gfx_cursor(&x, &y); elem = look_obj(x, y); @@ -2338,7 +2337,7 @@ static int select_ref(int prev, int last) int x, y; struct el *elem = NULL; xref_t xref = NULL; - gfx_cursor(&x, &y, NULL, NULL); + gfx_cursor(&x, &y); xref = look_xref(x, y, &elem); @@ -2379,7 +2378,7 @@ static void game_scroll_up(int count) { int xm, ym; struct el *o; - gfx_cursor(&xm, &ym, NULL, NULL); + gfx_cursor(&xm, &ym); o = look_obj(xm, ym); if (o && (o->id == el_scene || o->id == el_inv)) { scroll_up(o->id, count); @@ -2390,7 +2389,7 @@ static void game_scroll_down(int count) { int xm, ym; struct el *o; - gfx_cursor(&xm, &ym, NULL, NULL); + gfx_cursor(&xm, &ym); o = look_obj(xm, ym); if (o && (o->id == el_scene || o->id == el_inv)) { scroll_down(o->id, count); @@ -2401,7 +2400,7 @@ static int game_scroll_pup(void) { int xm, ym; struct el *o; - gfx_cursor(&xm, &ym, NULL, NULL); + gfx_cursor(&xm, &ym); o = look_obj(xm, ym); if (o && (o->id == el_scene || o->id == el_inv)) { return scroll_pup(o->id); @@ -2413,7 +2412,7 @@ static int game_scroll_pdown(void) { int xm, ym; struct el *o; - gfx_cursor(&xm, &ym, NULL, NULL); + gfx_cursor(&xm, &ym); o = look_obj(xm, ym); if (o && (o->id == el_scene || o->id == el_inv)) { return scroll_pdown(o->id); @@ -2423,8 +2422,6 @@ static int game_scroll_pdown(void) static int is_key(struct inp_event *ev, const char *name) { - if (!ev->sym) - return -1; return strcmp(ev->sym, name); } @@ -2713,7 +2710,7 @@ int game_loop(void) || !is_key(&ev, ".") #endif )) { - gfx_cursor(&x, &y, NULL, NULL); + gfx_cursor(&x, &y); game_highlight(-1, -1, 0); /* reset */ game_click(x, y, 0, 0); @@ -2840,7 +2837,7 @@ int game_loop(void) game_highlight(x, y, 1); else { int x, y; - gfx_cursor(&x, &y, NULL, NULL); + gfx_cursor(&x, &y); game_highlight(x, y, 1); } game_cursor(CURSOR_ON); diff --git a/src/sdl-instead/graphics.c b/src/sdl-instead/graphics.c index 1d48f21..4809fcf 100644 --- a/src/sdl-instead/graphics.c +++ b/src/sdl-instead/graphics.c @@ -588,7 +588,10 @@ img_t gfx_alpha_img(img_t src, int alpha) else img = gfx_new(Surf(src)->w, Surf(src)->h); if (!img) - return NULL; + return NULL; +#if SDL_VERSION_ATLEAST(1,3,0) + SDL_SetAlpha(img, SDL_SRCALPHA, 255); +#endif ptr = (Uint32*)img->pixels; size = img->w * img->h; while (size --) { @@ -604,7 +607,11 @@ img_t gfx_alpha_img(img_t src, int alpha) void gfx_set_alpha(img_t src, int alpha) { +#if SDL_VERSION_ATLEAST(1,3,0) + SDL_SetAlpha((SDL_Surface *)src, SDL_SRCALPHA, alpha); +#else SDL_SetAlpha((SDL_Surface *)src, SDL_SRCALPHA | SDL_RLEACCEL, alpha); +#endif } img_t gfx_combine(img_t src, img_t dst) @@ -769,7 +776,11 @@ static img_t _gfx_load_image(char *filename) rwop = SDL_RWFromFile(filename, "rb"); if (rwop) { if (IMG_isBMP(rwop)) +#if SDL_VERSION_ATLEAST(1,3,0) + SDL_SetAlpha(img, 0, SDL_ALPHA_OPAQUE); +#else SDL_SetAlpha(img, SDL_RLEACCEL, SDL_ALPHA_OPAQUE); +#endif SDL_RWclose(rwop); } } @@ -3596,22 +3607,16 @@ void txt_layout_real_size(layout_t lay, int *pw, int *ph) *ph = h; } -void gfx_cursor(int *xp, int *yp, int *w, int *h) +void gfx_cursor(int *xp, int *yp) { int x, y; - SDL_Cursor *c = SDL_GetCursor(); - if (!c) - return; SDL_GetMouseState(&x, &y); - if (w) - *w = c->area.w - c->hot_x; - if (h) - *h = c->area.h - c->hot_y; if (xp) *xp = x; if (yp) *yp = y; } + void gfx_warp_cursor(int x, int y) { SDL_WarpMouse(x, y); @@ -3685,7 +3690,11 @@ void gfx_done(void) gtimer_t gfx_add_timer(int delay, int (*fn)(int, void*), void *aux) { +#if SDL_VERSION_ATLEAST(1,3,0) + return (gtimer_t)SDL_AddTimer(delay, (SDL_TimerCallback)fn, aux); +#else return (gtimer_t)SDL_AddTimer(delay, (SDL_NewTimerCallback)fn, aux); +#endif } void gfx_del_timer(gtimer_t han) diff --git a/src/sdl-instead/graphics.h b/src/sdl-instead/graphics.h index 34fe32c..095641f 100644 --- a/src/sdl-instead/graphics.h +++ b/src/sdl-instead/graphics.h @@ -1,6 +1,6 @@ #ifndef __GRAPHICS_H__ #define __GRAPHICS_H__ - +#include /* #define GFX_CACHE_SIZE 64 #define GFX_MAX_CACHED_W 256 #define GFX_MAX_CACHED_H 256 @@ -8,7 +8,13 @@ #define LINK_CACHE_SIZE 64 */ +#if SDL_VERSION_ATLEAST(1,3,0) +typedef int gtimer_t; +#define NULL_TIMER 0 +#else typedef void* gtimer_t; +#define NULL_TIMER NULL +#endif typedef void* img_t; typedef void* fnt_t; typedef void* layout_t; @@ -81,7 +87,7 @@ extern img_t gfx_display_alpha(img_t src); extern img_t gfx_scale(img_t src, float xscale, float yscale); extern void gfx_draw_bg(img_t p, int x, int y, int width, int height); extern void gfx_draw_from(img_t p, int x, int y, int xx, int yy, int width, int height); -extern void gfx_cursor(int *xp, int *yp, int *w, int *h); +extern void gfx_cursor(int *xp, int *yp); extern void gfx_warp_cursor(int x, int y); extern void gfx_change_screen(img_t src, int steps); extern int gfx_fading(void); diff --git a/src/sdl-instead/input.c b/src/sdl-instead/input.c index 08f5b67..d89ce9e 100644 --- a/src/sdl-instead/input.c +++ b/src/sdl-instead/input.c @@ -67,10 +67,9 @@ int input(struct inp_event *inp, int wait) rc = SDL_PollEvent(&event); if (!rc) return 0; - inp->sym = NULL; + inp->sym[0] = 0; inp->type = 0; inp->count = 1; - switch(event.type){ case SDL_ACTIVEEVENT: if (event.active.state & SDL_APPACTIVE) { @@ -88,7 +87,11 @@ int input(struct inp_event *inp, int wait) mouse_cursor(1); /* is it hack?*/ } } +#if SDL_VERSION_ATLEAST(1,3,0) + if (SDL_PeepEvents(&peek, 1, SDL_PEEKEVENT, SDL_ACTIVEEVENT, SDL_ACTIVEEVENT) > 0) +#else if (SDL_PeepEvents(&peek, 1, SDL_PEEKEVENT, SDL_EVENTMASK(SDL_ACTIVEEVENT)) > 0) +#endif return AGAIN; /* to avoid flickering */ return 0; case SDL_USEREVENT: { @@ -102,19 +105,27 @@ int input(struct inp_event *inp, int wait) case SDL_KEYDOWN: //A key has been pressed inp->type = KEY_DOWN; inp->code = event.key.keysym.scancode; - inp->sym = SDL_GetKeyName(event.key.keysym.sym); + strncpy(inp->sym, SDL_GetKeyName(event.key.keysym.sym), sizeof(inp->sym)); + inp->sym[sizeof(inp->sym) - 1] = 0; + tolow(inp->sym); break; case SDL_KEYUP: inp->type = KEY_UP; inp->code = event.key.keysym.scancode; - inp->sym = SDL_GetKeyName(event.key.keysym.sym); + strncpy(inp->sym, SDL_GetKeyName(event.key.keysym.sym), sizeof(inp->sym)); + inp->sym[sizeof(inp->sym) - 1] = 0; + tolow(inp->sym); break; case SDL_MOUSEMOTION: m_focus = 1; /* ahhh */ inp->type = MOUSE_MOTION; inp->x = event.button.x; inp->y = event.button.y; +#if SDL_VERSION_ATLEAST(1,3,0) + while (SDL_PeepEvents(&peek, 1, SDL_GETEVENT, SDL_MOUSEMOTION, SDL_MOUSEMOTION) > 0) { +#else while (SDL_PeepEvents(&peek, 1, SDL_GETEVENT, SDL_EVENTMASK (SDL_MOUSEMOTION)) > 0) { +#endif inp->x = peek.button.x; inp->y = peek.button.y; } @@ -139,7 +150,11 @@ int input(struct inp_event *inp, int wait) inp->type = MOUSE_WHEEL_UP; else if (event.button.button == 5) inp->type = MOUSE_WHEEL_DOWN; +#if SDL_VERSION_ATLEAST(1,3,0) + while (SDL_PeepEvents(&peek, 1, SDL_GETEVENT, SDL_MOUSEBUTTONDOWN, SDL_MOUSEBUTTONDOWN) > 0) { +#else while (SDL_PeepEvents(&peek, 1, SDL_GETEVENT, SDL_EVENTMASK (SDL_MOUSEBUTTONDOWN)) > 0) { +#endif if (!((event.button.button == 4 && inp->type == MOUSE_WHEEL_UP) || (event.button.button == 5 && diff --git a/src/sdl-instead/input.h b/src/sdl-instead/input.h index 9b7e52b..11ab78e 100644 --- a/src/sdl-instead/input.h +++ b/src/sdl-instead/input.h @@ -14,7 +14,7 @@ struct inp_event { int type; int code; - char *sym; + char sym[64]; int x; int y; int count; diff --git a/src/sdl-instead/instead.c b/src/sdl-instead/instead.c index 9dae920..9858678 100644 --- a/src/sdl-instead/instead.c +++ b/src/sdl-instead/instead.c @@ -7,7 +7,7 @@ /* the Lua interpreter */ -static gtimer_t instead_timer = NULL; +static gtimer_t instead_timer = NULL_TIMER; static int instead_timer_nr = 0; char *fromgame(const char *s); @@ -29,7 +29,7 @@ static int report (lua_State *L, int status) lua_pop(L, 1); status = -1; gfx_del_timer(instead_timer); /* to avoid error loops */ - instead_timer = NULL; + instead_timer = NULL_TIMER; } return status; } @@ -491,7 +491,7 @@ static int luaB_set_timer(lua_State *L) { const char *delay = luaL_optstring(L, 1, NULL); int d; gfx_del_timer(instead_timer); - instead_timer = NULL; + instead_timer = NULL_TIMER; if (!delay) d = 0; else @@ -613,7 +613,7 @@ int instead_init(void) void instead_done(void) { gfx_del_timer(instead_timer); - instead_timer = NULL; + instead_timer = NULL_TIMER; #ifdef _HAVE_ICONV if (fromcp) free(fromcp); diff --git a/src/sdl-instead/sound.c b/src/sdl-instead/sound.c index d5b40a9..e1116ab 100644 --- a/src/sdl-instead/sound.c +++ b/src/sdl-instead/sound.c @@ -18,7 +18,7 @@ static mus_t mus; static char *next_mus = NULL; static int next_fadein = 0; static int next_loop = -1; -static SDL_TimerID timer_id = NULL; +static SDL_TimerID timer_id = NULL_TIMER; static int sound_on = 0; @@ -42,7 +42,7 @@ static void mus_callback(void *aux) next_mus = NULL; } SDL_RemoveTimer(timer_id); - timer_id = NULL; + timer_id = NULL_TIMER; } static Uint32 callback(Uint32 interval, void *aux) @@ -273,7 +273,7 @@ void snd_done(void) Mix_HaltChannel(-1); Mix_HaltMusic(); - timer_id = NULL; + timer_id = NULL_TIMER; if (mus) snd_free_mus(mus); mus = NULL;