src/render/software/SDL_rotate.c
author Sam Lantinga
Fri, 19 Jun 2015 23:20:43 -0700
changeset 9762 5c4a85c5b648
parent 8696 6bb798ddf205
child 9763 c2ba8ab27c1a
permissions -rw-r--r--
Fixed bug 1550 - SDL_RenderCopy/CopyEx in software should optionally render 8bit alpha

Adam M.

There are three problems in the code that I see.
1. SW_RenderCopyEx enables a color key on surface_scaled even if the source surface didn't have a color key.
2. SW_RenderCopyEx doesn't copy blend mode, color mod, or alpha mod from src to surface_scaled.
3. When SDL_BlitScaled(src, srcrect, surface_scaled, &tmp_rect) is called, it blends the src pixels into surface_scaled instead of overwriting them (if src has blending, etc. enabled).

I've attached a patch that 1) fixes the three problems that I mentioned, 2) adds the requested performance improvement of using the regular blit function if no rotation or flipping is needed, 3) avoids cloning the source surface if no stretching is required, and simplifies the rotation code slightly.
gabomdq@6320
     1
/*
gabomdq@6320
     2
gabomdq@6320
     3
SDL_rotate.c: rotates 32bit or 8bit surfaces
gabomdq@6320
     4
gabomdq@6320
     5
Shamelessly stolen from SDL_gfx by Andreas Schiffler. Original copyright follows:
gabomdq@6320
     6
gabomdq@6320
     7
Copyright (C) 2001-2011  Andreas Schiffler
gabomdq@6320
     8
gabomdq@6320
     9
This software is provided 'as-is', without any express or implied
gabomdq@6320
    10
warranty. In no event will the authors be held liable for any damages
gabomdq@6320
    11
arising from the use of this software.
gabomdq@6320
    12
gabomdq@6320
    13
Permission is granted to anyone to use this software for any purpose,
gabomdq@6320
    14
including commercial applications, and to alter it and redistribute it
gabomdq@6320
    15
freely, subject to the following restrictions:
gabomdq@6320
    16
gabomdq@6320
    17
   1. The origin of this software must not be misrepresented; you must not
gabomdq@6320
    18
   claim that you wrote the original software. If you use this software
gabomdq@6320
    19
   in a product, an acknowledgment in the product documentation would be
gabomdq@6320
    20
   appreciated but is not required.
gabomdq@6320
    21
gabomdq@6320
    22
   2. Altered source versions must be plainly marked as such, and must not be
gabomdq@6320
    23
   misrepresented as being the original software.
gabomdq@6320
    24
gabomdq@6320
    25
   3. This notice may not be removed or altered from any source
gabomdq@6320
    26
   distribution.
gabomdq@6320
    27
gabomdq@6320
    28
Andreas Schiffler -- aschiffler at ferzkopp dot net
gabomdq@6320
    29
gabomdq@6320
    30
*/
icculus@8093
    31
#include "../../SDL_internal.h"
gabomdq@6320
    32
slouken@7828
    33
#if defined(__WIN32__)
slouken@7828
    34
#include "../../core/windows/SDL_windows.h"
gabomdq@6320
    35
#endif
gabomdq@6320
    36
gabomdq@6320
    37
#include <stdlib.h>
gabomdq@6320
    38
#include <string.h>
gabomdq@6320
    39
gabomdq@6320
    40
#include "SDL.h"
gabomdq@6320
    41
#include "SDL_rotate.h"
gabomdq@6320
    42
gabomdq@6320
    43
/* ---- Internally used structures */
gabomdq@6320
    44
gabomdq@7678
    45
/* !
gabomdq@6320
    46
\brief A 32 bit RGBA pixel.
gabomdq@6320
    47
*/
gabomdq@6320
    48
typedef struct tColorRGBA {
gabomdq@6320
    49
    Uint8 r;
gabomdq@6320
    50
    Uint8 g;
gabomdq@6320
    51
    Uint8 b;
gabomdq@6320
    52
    Uint8 a;
gabomdq@6320
    53
} tColorRGBA;
gabomdq@6320
    54
gabomdq@7678
    55
/* !
gabomdq@6320
    56
\brief A 8bit Y/palette pixel.
gabomdq@6320
    57
*/
gabomdq@6320
    58
typedef struct tColorY {
gabomdq@6320
    59
    Uint8 y;
gabomdq@6320
    60
} tColorY;
gabomdq@6320
    61
gabomdq@7678
    62
/* !
gabomdq@6320
    63
\brief Returns maximum of two numbers a and b.
gabomdq@6320
    64
*/
gabomdq@6320
    65
#define MAX(a,b)    (((a) > (b)) ? (a) : (b))
gabomdq@6320
    66
gabomdq@7678
    67
/* !
gabomdq@6320
    68
\brief Number of guard rows added to destination surfaces.
gabomdq@6320
    69
gabomdq@6320
    70
This is a simple but effective workaround for observed issues.
gabomdq@6320
    71
These rows allocate extra memory and are then hidden from the surface.
gabomdq@6320
    72
Rows are added to the end of destination surfaces when they are allocated.
gabomdq@6320
    73
This catches any potential overflows which seem to happen with
gabomdq@6320
    74
just the right src image dimensions and scale/rotation and can lead
gabomdq@6320
    75
to a situation where the program can segfault.
gabomdq@6320
    76
*/
gabomdq@6320
    77
#define GUARD_ROWS (2)
gabomdq@6320
    78
gabomdq@7678
    79
/* !
gabomdq@6320
    80
\brief Lower limit of absolute zoom factor or rotation degrees.
gabomdq@6320
    81
*/
gabomdq@6320
    82
#define VALUE_LIMIT 0.001
gabomdq@6320
    83
gabomdq@7678
    84
/* !
gabomdq@6320
    85
\brief Returns colorkey info for a surface
gabomdq@6320
    86
*/
slouken@7859
    87
static Uint32
slouken@7859
    88
_colorkey(SDL_Surface *src)
gabomdq@6320
    89
{
gabomdq@6320
    90
    Uint32 key = 0;
gabomdq@6320
    91
    SDL_GetColorKey(src, &key);
gabomdq@6320
    92
    return key;
gabomdq@6320
    93
}
gabomdq@6320
    94
gabomdq@6320
    95
gabomdq@7678
    96
/* !
gabomdq@6320
    97
\brief Internal target surface sizing function for rotations with trig result return.
gabomdq@6320
    98
gabomdq@6320
    99
\param width The source surface width.
gabomdq@6320
   100
\param height The source surface height.
gabomdq@6320
   101
\param angle The angle to rotate in degrees.
gabomdq@6320
   102
\param dstwidth The calculated width of the destination surface.
gabomdq@6320
   103
\param dstheight The calculated height of the destination surface.
gabomdq@6320
   104
\param cangle The sine of the angle
gabomdq@6320
   105
\param sangle The cosine of the angle
gabomdq@6320
   106
gabomdq@6320
   107
*/
slouken@7859
   108
void
slouken@7859
   109
SDLgfx_rotozoomSurfaceSizeTrig(int width, int height, double angle,
slouken@7859
   110
                               int *dstwidth, int *dstheight,
slouken@7859
   111
                               double *cangle, double *sangle)
gabomdq@6320
   112
{
gabomdq@6320
   113
    double x, y, cx, cy, sx, sy;
gabomdq@6320
   114
    double radangle;
gabomdq@6320
   115
    int dstwidthhalf, dstheighthalf;
gabomdq@6320
   116
gabomdq@6320
   117
    /*
gabomdq@6320
   118
    * Determine destination width and height by rotating a centered source box
gabomdq@6320
   119
    */
gabomdq@6320
   120
    radangle = angle * (M_PI / 180.0);
gabomdq@6320
   121
    *sangle = SDL_sin(radangle);
gabomdq@6320
   122
    *cangle = SDL_cos(radangle);
gabomdq@6320
   123
    x = (double)(width / 2);
gabomdq@6320
   124
    y = (double)(height / 2);
gabomdq@6320
   125
    cx = *cangle * x;
gabomdq@6320
   126
    cy = *cangle * y;
gabomdq@6320
   127
    sx = *sangle * x;
gabomdq@6320
   128
    sy = *sangle * y;
gabomdq@6320
   129
gabomdq@6320
   130
    dstwidthhalf = MAX((int)
gabomdq@6320
   131
        SDL_ceil(MAX(MAX(MAX(SDL_fabs(cx + sy), SDL_fabs(cx - sy)), SDL_fabs(-cx + sy)), SDL_fabs(-cx - sy))), 1);
gabomdq@6320
   132
    dstheighthalf = MAX((int)
gabomdq@6320
   133
        SDL_ceil(MAX(MAX(MAX(SDL_fabs(sx + cy), SDL_fabs(sx - cy)), SDL_fabs(-sx + cy)), SDL_fabs(-sx - cy))), 1);
gabomdq@6320
   134
    *dstwidth = 2 * dstwidthhalf;
gabomdq@6320
   135
    *dstheight = 2 * dstheighthalf;
gabomdq@6320
   136
}
gabomdq@6320
   137
gabomdq@6320
   138
gabomdq@7678
   139
/* !
gabomdq@6320
   140
\brief Internal 32 bit rotozoomer with optional anti-aliasing.
gabomdq@6320
   141
gabomdq@6320
   142
Rotates and zooms 32 bit RGBA/ABGR 'src' surface to 'dst' surface based on the control
gabomdq@6320
   143
parameters by scanning the destination surface and applying optionally anti-aliasing
gabomdq@6320
   144
by bilinear interpolation.
gabomdq@6320
   145
Assumes src and dst surfaces are of 32 bit depth.
gabomdq@6320
   146
Assumes dst surface was allocated with the correct dimensions.
gabomdq@6320
   147
gabomdq@6320
   148
\param src Source surface.
gabomdq@6320
   149
\param dst Destination surface.
gabomdq@6320
   150
\param cx Horizontal center coordinate.
gabomdq@6320
   151
\param cy Vertical center coordinate.
gabomdq@6320
   152
\param isin Integer version of sine of angle.
gabomdq@6320
   153
\param icos Integer version of cosine of angle.
gabomdq@6320
   154
\param flipx Flag indicating horizontal mirroring should be applied.
gabomdq@6320
   155
\param flipy Flag indicating vertical mirroring should be applied.
gabomdq@6320
   156
\param smooth Flag indicating anti-aliasing should be used.
gabomdq@6320
   157
*/
slouken@7859
   158
static void
slouken@7859
   159
_transformSurfaceRGBA(SDL_Surface * src, SDL_Surface * dst, int cx, int cy, int isin, int icos, int flipx, int flipy, int smooth)
gabomdq@6320
   160
{
gabomdq@6320
   161
    int x, y, t1, t2, dx, dy, xd, yd, sdx, sdy, ax, ay, ex, ey, sw, sh;
gabomdq@6320
   162
    tColorRGBA c00, c01, c10, c11, cswap;
gabomdq@6320
   163
    tColorRGBA *pc, *sp;
gabomdq@6320
   164
    int gap;
gabomdq@6320
   165
gabomdq@6320
   166
    /*
gabomdq@6320
   167
    * Variable setup
gabomdq@6320
   168
    */
gabomdq@6320
   169
    xd = ((src->w - dst->w) << 15);
gabomdq@6320
   170
    yd = ((src->h - dst->h) << 15);
gabomdq@6320
   171
    ax = (cx << 16) - (icos * cx);
gabomdq@6320
   172
    ay = (cy << 16) - (isin * cx);
gabomdq@6320
   173
    sw = src->w - 1;
gabomdq@6320
   174
    sh = src->h - 1;
gabomdq@6320
   175
    pc = (tColorRGBA*) dst->pixels;
gabomdq@6320
   176
    gap = dst->pitch - dst->w * 4;
gabomdq@6320
   177
gabomdq@6320
   178
    /*
gabomdq@6320
   179
    * Switch between interpolating and non-interpolating code
gabomdq@6320
   180
    */
gabomdq@6320
   181
    if (smooth) {
gabomdq@6320
   182
        for (y = 0; y < dst->h; y++) {
gabomdq@6320
   183
            dy = cy - y;
gabomdq@6320
   184
            sdx = (ax + (isin * dy)) + xd;
gabomdq@6320
   185
            sdy = (ay - (icos * dy)) + yd;
gabomdq@6320
   186
            for (x = 0; x < dst->w; x++) {
gabomdq@6320
   187
                dx = (sdx >> 16);
gabomdq@6320
   188
                dy = (sdy >> 16);
gabomdq@6320
   189
                if (flipx) dx = sw - dx;
gabomdq@6320
   190
                if (flipy) dy = sh - dy;
slouken@9762
   191
                if ((unsigned)dx < (unsigned)sw && (unsigned)dy < (unsigned)sh) {
slouken@9762
   192
                    sp = (tColorRGBA *) ((Uint8 *) src->pixels + src->pitch * dy) + dx;
gabomdq@6320
   193
                    c00 = *sp;
gabomdq@6320
   194
                    sp += 1;
gabomdq@6320
   195
                    c01 = *sp;
gabomdq@6320
   196
                    sp += (src->pitch/4);
gabomdq@6320
   197
                    c11 = *sp;
gabomdq@6320
   198
                    sp -= 1;
gabomdq@6320
   199
                    c10 = *sp;
gabomdq@6320
   200
                    if (flipx) {
gabomdq@6320
   201
                        cswap = c00; c00=c01; c01=cswap;
gabomdq@6320
   202
                        cswap = c10; c10=c11; c11=cswap;
gabomdq@6320
   203
                    }
gabomdq@6320
   204
                    if (flipy) {
gabomdq@6320
   205
                        cswap = c00; c00=c10; c10=cswap;
gabomdq@6320
   206
                        cswap = c01; c01=c11; c11=cswap;
gabomdq@6320
   207
                    }
gabomdq@6320
   208
                    /*
gabomdq@6320
   209
                    * Interpolate colors
gabomdq@6320
   210
                    */
gabomdq@6320
   211
                    ex = (sdx & 0xffff);
gabomdq@6320
   212
                    ey = (sdy & 0xffff);
gabomdq@6320
   213
                    t1 = ((((c01.r - c00.r) * ex) >> 16) + c00.r) & 0xff;
gabomdq@6320
   214
                    t2 = ((((c11.r - c10.r) * ex) >> 16) + c10.r) & 0xff;
gabomdq@6320
   215
                    pc->r = (((t2 - t1) * ey) >> 16) + t1;
gabomdq@6320
   216
                    t1 = ((((c01.g - c00.g) * ex) >> 16) + c00.g) & 0xff;
gabomdq@6320
   217
                    t2 = ((((c11.g - c10.g) * ex) >> 16) + c10.g) & 0xff;
gabomdq@6320
   218
                    pc->g = (((t2 - t1) * ey) >> 16) + t1;
gabomdq@6320
   219
                    t1 = ((((c01.b - c00.b) * ex) >> 16) + c00.b) & 0xff;
gabomdq@6320
   220
                    t2 = ((((c11.b - c10.b) * ex) >> 16) + c10.b) & 0xff;
gabomdq@6320
   221
                    pc->b = (((t2 - t1) * ey) >> 16) + t1;
gabomdq@6320
   222
                    t1 = ((((c01.a - c00.a) * ex) >> 16) + c00.a) & 0xff;
gabomdq@6320
   223
                    t2 = ((((c11.a - c10.a) * ex) >> 16) + c10.a) & 0xff;
gabomdq@6320
   224
                    pc->a = (((t2 - t1) * ey) >> 16) + t1;
gabomdq@6320
   225
                }
gabomdq@6320
   226
                sdx += icos;
gabomdq@6320
   227
                sdy += isin;
gabomdq@6320
   228
                pc++;
gabomdq@6320
   229
            }
gabomdq@6320
   230
            pc = (tColorRGBA *) ((Uint8 *) pc + gap);
gabomdq@6320
   231
        }
gabomdq@6320
   232
    } else {
gabomdq@6320
   233
        for (y = 0; y < dst->h; y++) {
gabomdq@6320
   234
            dy = cy - y;
gabomdq@6320
   235
            sdx = (ax + (isin * dy)) + xd;
gabomdq@6320
   236
            sdy = (ay - (icos * dy)) + yd;
gabomdq@6320
   237
            for (x = 0; x < dst->w; x++) {
slouken@9762
   238
                dx = (sdx >> 16);
slouken@9762
   239
                dy = (sdy >> 16);
slouken@9762
   240
                if ((unsigned)dx < (unsigned)src->w && (unsigned)dy < (unsigned)src->h) {
slouken@9762
   241
                    if(flipx) dx = sw - dx;
slouken@9762
   242
                    if(flipy) dy = sh - dy;
slouken@9762
   243
                    *pc = *((tColorRGBA *)((Uint8 *)src->pixels + src->pitch * dy) + dx);
gabomdq@6320
   244
                }
gabomdq@6320
   245
                sdx += icos;
gabomdq@6320
   246
                sdy += isin;
gabomdq@6320
   247
                pc++;
gabomdq@6320
   248
            }
gabomdq@6320
   249
            pc = (tColorRGBA *) ((Uint8 *) pc + gap);
gabomdq@6320
   250
        }
gabomdq@6320
   251
    }
gabomdq@6320
   252
}
gabomdq@6320
   253
gabomdq@7678
   254
/* !
gabomdq@6320
   255
gabomdq@6320
   256
\brief Rotates and zooms 8 bit palette/Y 'src' surface to 'dst' surface without smoothing.
gabomdq@6320
   257
gabomdq@6320
   258
Rotates and zooms 8 bit RGBA/ABGR 'src' surface to 'dst' surface based on the control
gabomdq@6320
   259
parameters by scanning the destination surface.
gabomdq@6320
   260
Assumes src and dst surfaces are of 8 bit depth.
gabomdq@6320
   261
Assumes dst surface was allocated with the correct dimensions.
gabomdq@6320
   262
gabomdq@6320
   263
\param src Source surface.
gabomdq@6320
   264
\param dst Destination surface.
gabomdq@6320
   265
\param cx Horizontal center coordinate.
gabomdq@6320
   266
\param cy Vertical center coordinate.
gabomdq@6320
   267
\param isin Integer version of sine of angle.
gabomdq@6320
   268
\param icos Integer version of cosine of angle.
gabomdq@6320
   269
\param flipx Flag indicating horizontal mirroring should be applied.
gabomdq@6320
   270
\param flipy Flag indicating vertical mirroring should be applied.
gabomdq@6320
   271
*/
slouken@7859
   272
static void
slouken@7859
   273
transformSurfaceY(SDL_Surface * src, SDL_Surface * dst, int cx, int cy, int isin, int icos, int flipx, int flipy)
gabomdq@6320
   274
{
icculus@6389
   275
    int x, y, dx, dy, xd, yd, sdx, sdy, ax, ay;
slouken@9762
   276
    tColorY *pc;
gabomdq@6320
   277
    int gap;
gabomdq@6320
   278
gabomdq@6320
   279
    /*
gabomdq@6320
   280
    * Variable setup
gabomdq@6320
   281
    */
gabomdq@6320
   282
    xd = ((src->w - dst->w) << 15);
gabomdq@6320
   283
    yd = ((src->h - dst->h) << 15);
gabomdq@6320
   284
    ax = (cx << 16) - (icos * cx);
gabomdq@6320
   285
    ay = (cy << 16) - (isin * cx);
gabomdq@6320
   286
    pc = (tColorY*) dst->pixels;
gabomdq@6320
   287
    gap = dst->pitch - dst->w;
gabomdq@6320
   288
    /*
gabomdq@6320
   289
    * Clear surface to colorkey
gabomdq@6320
   290
    */
gabomdq@6320
   291
    SDL_memset(pc, (int)(_colorkey(src) & 0xff), dst->pitch * dst->h);
gabomdq@6320
   292
    /*
gabomdq@6320
   293
    * Iterate through destination surface
gabomdq@6320
   294
    */
gabomdq@6320
   295
    for (y = 0; y < dst->h; y++) {
gabomdq@6320
   296
        dy = cy - y;
gabomdq@6320
   297
        sdx = (ax + (isin * dy)) + xd;
gabomdq@6320
   298
        sdy = (ay - (icos * dy)) + yd;
gabomdq@6320
   299
        for (x = 0; x < dst->w; x++) {
slouken@9762
   300
            dx = (sdx >> 16);
slouken@9762
   301
            dy = (sdy >> 16);
slouken@9762
   302
            if ((unsigned)dx < (unsigned)src->w && (unsigned)dy < (unsigned)src->h) {
slouken@9762
   303
                if (flipx) dx = (src->w-1)-dx;
slouken@9762
   304
                if (flipy) dy = (src->h-1)-dy;
slouken@9762
   305
                *pc = *((tColorY *)src->pixels + src->pitch * dy + dx);
gabomdq@6320
   306
            }
gabomdq@6320
   307
            sdx += icos;
gabomdq@6320
   308
            sdy += isin;
gabomdq@6320
   309
            pc++;
gabomdq@6320
   310
        }
gabomdq@6320
   311
        pc += gap;
gabomdq@6320
   312
    }
gabomdq@6320
   313
}
gabomdq@6320
   314
gabomdq@6320
   315
gabomdq@7678
   316
/* !
gabomdq@6320
   317
\brief Rotates and zooms a surface with different horizontal and vertival scaling factors and optional anti-aliasing.
gabomdq@6320
   318
gabomdq@6320
   319
Rotates a 32bit or 8bit 'src' surface to newly created 'dst' surface.
gabomdq@6320
   320
'angle' is the rotation in degrees, 'centerx' and 'centery' the rotation center. If 'smooth' is set
gabomdq@6320
   321
then the destination 32bit surface is anti-aliased. If the surface is not 8bit
gabomdq@6320
   322
or 32bit RGBA/ABGR it will be converted into a 32bit RGBA format on the fly.
gabomdq@6320
   323
gabomdq@6320
   324
\param src The surface to rotozoom.
gabomdq@6320
   325
\param angle The angle to rotate in degrees.
gabomdq@6320
   326
\param centerx The horizontal coordinate of the center of rotation
gabomdq@6320
   327
\param zoomy The vertical coordinate of the center of rotation
gabomdq@6320
   328
\param smooth Antialiasing flag; set to SMOOTHING_ON to enable.
gabomdq@6320
   329
\param flipx Set to 1 to flip the image horizontally
gabomdq@6320
   330
\param flipy Set to 1 to flip the image vertically
gabomdq@6320
   331
\param dstwidth The destination surface width
gabomdq@6320
   332
\param dstheight The destination surface height
gabomdq@6320
   333
\param cangle The angle cosine
gabomdq@6320
   334
\param sangle The angle sine
gabomdq@6320
   335
\return The new rotated surface.
gabomdq@6320
   336
gabomdq@6320
   337
*/
gabomdq@6320
   338
slouken@7859
   339
SDL_Surface *
slouken@7859
   340
SDLgfx_rotateSurface(SDL_Surface * src, double angle, int centerx, int centery, int smooth, int flipx, int flipy, int dstwidth, int dstheight, double cangle, double sangle)
gabomdq@6320
   341
{
gabomdq@6320
   342
    SDL_Surface *rz_src;
gabomdq@6320
   343
    SDL_Surface *rz_dst;
gabomdq@6320
   344
    int is32bit;
gabomdq@6320
   345
    int i, src_converted;
gabomdq@6320
   346
    Uint8 r,g,b;
gabomdq@6320
   347
    Uint32 colorkey = 0;
gabomdq@6320
   348
    int colorKeyAvailable = 0;
gabomdq@6320
   349
    double sangleinv, cangleinv;
gabomdq@6320
   350
gabomdq@6320
   351
    /*
gabomdq@6320
   352
    * Sanity check
gabomdq@6320
   353
    */
gabomdq@6320
   354
    if (src == NULL)
gabomdq@6320
   355
        return (NULL);
gabomdq@6320
   356
gabomdq@7678
   357
    if (src->flags & SDL_TRUE/* SDL_SRCCOLORKEY */)
gabomdq@6320
   358
    {
gabomdq@6320
   359
        colorkey = _colorkey(src);
gabomdq@6320
   360
        SDL_GetRGB(colorkey, src->format, &r, &g, &b);
gabomdq@6320
   361
        colorKeyAvailable = 1;
gabomdq@6320
   362
    }
gabomdq@6320
   363
    /*
gabomdq@6320
   364
    * Determine if source surface is 32bit or 8bit
gabomdq@6320
   365
    */
gabomdq@6320
   366
    is32bit = (src->format->BitsPerPixel == 32);
gabomdq@6320
   367
    if ((is32bit) || (src->format->BitsPerPixel == 8)) {
gabomdq@6320
   368
        /*
gabomdq@6320
   369
        * Use source surface 'as is'
gabomdq@6320
   370
        */
gabomdq@6320
   371
        rz_src = src;
gabomdq@6320
   372
        src_converted = 0;
gabomdq@6320
   373
    } else {
gabomdq@6320
   374
        /*
gabomdq@6320
   375
        * New source surface is 32bit with a defined RGBA ordering
gabomdq@6320
   376
        */
gabomdq@6320
   377
        rz_src =
gabomdq@6320
   378
            SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32,
gabomdq@6320
   379
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
gabomdq@6320
   380
            0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000
gabomdq@6320
   381
#else
gabomdq@6320
   382
            0xff000000,  0x00ff0000, 0x0000ff00, 0x000000ff
gabomdq@6320
   383
#endif
gabomdq@6320
   384
            );
gabomdq@6320
   385
        if(colorKeyAvailable)
gabomdq@6320
   386
            SDL_SetColorKey(src, 0, 0);
gabomdq@6320
   387
gabomdq@6320
   388
        SDL_BlitSurface(src, NULL, rz_src, NULL);
gabomdq@6320
   389
gabomdq@6320
   390
        if(colorKeyAvailable)
gabomdq@7678
   391
            SDL_SetColorKey(src, SDL_TRUE /* SDL_SRCCOLORKEY */, colorkey);
gabomdq@6320
   392
        src_converted = 1;
gabomdq@6320
   393
        is32bit = 1;
gabomdq@6320
   394
    }
gabomdq@6320
   395
gabomdq@6320
   396
gabomdq@6320
   397
    /* Determine target size */
gabomdq@7678
   398
    /* _rotozoomSurfaceSizeTrig(rz_src->w, rz_src->h, angle, &dstwidth, &dstheight, &cangle, &sangle); */
gabomdq@6320
   399
gabomdq@6320
   400
    /*
gabomdq@6320
   401
    * Calculate target factors from sin/cos and zoom
gabomdq@6320
   402
    */
gabomdq@6320
   403
    sangleinv = sangle*65536.0;
gabomdq@6320
   404
    cangleinv = cangle*65536.0;
gabomdq@6320
   405
gabomdq@6320
   406
    /*
gabomdq@6320
   407
    * Alloc space to completely contain the rotated surface
gabomdq@6320
   408
    */
gabomdq@6320
   409
    rz_dst = NULL;
gabomdq@6320
   410
    if (is32bit) {
gabomdq@6320
   411
        /*
gabomdq@6320
   412
        * Target surface is 32bit with source RGBA/ABGR ordering
gabomdq@6320
   413
        */
gabomdq@6320
   414
        rz_dst =
gabomdq@6320
   415
            SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 32,
gabomdq@6320
   416
            rz_src->format->Rmask, rz_src->format->Gmask,
gabomdq@6320
   417
            rz_src->format->Bmask, rz_src->format->Amask);
gabomdq@6320
   418
    } else {
gabomdq@6320
   419
        /*
gabomdq@6320
   420
        * Target surface is 8bit
gabomdq@6320
   421
        */
gabomdq@6320
   422
        rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 8, 0, 0, 0, 0);
gabomdq@6320
   423
    }
gabomdq@6320
   424
gabomdq@6320
   425
    /* Check target */
gabomdq@6320
   426
    if (rz_dst == NULL)
gabomdq@6320
   427
        return NULL;
gabomdq@6320
   428
gabomdq@6320
   429
    /* Adjust for guard rows */
gabomdq@6320
   430
    rz_dst->h = dstheight;
gabomdq@6320
   431
gabomdq@6320
   432
    if (colorKeyAvailable == 1){
gabomdq@6320
   433
        colorkey = SDL_MapRGB(rz_dst->format, r, g, b);
gabomdq@6320
   434
gabomdq@6320
   435
        SDL_FillRect(rz_dst, NULL, colorkey );
gabomdq@6320
   436
    }
gabomdq@6320
   437
gabomdq@6320
   438
    /*
gabomdq@6320
   439
    * Lock source surface
gabomdq@6320
   440
    */
gabomdq@6320
   441
    if (SDL_MUSTLOCK(rz_src)) {
gabomdq@6320
   442
        SDL_LockSurface(rz_src);
gabomdq@6320
   443
    }
gabomdq@6320
   444
gabomdq@6320
   445
    /*
gabomdq@6320
   446
    * Check which kind of surface we have
gabomdq@6320
   447
    */
gabomdq@6320
   448
    if (is32bit) {
gabomdq@6320
   449
        /*
gabomdq@6320
   450
        * Call the 32bit transformation routine to do the rotation (using alpha)
gabomdq@6320
   451
        */
gabomdq@6320
   452
        _transformSurfaceRGBA(rz_src, rz_dst, centerx, centery,
gabomdq@6320
   453
            (int) (sangleinv), (int) (cangleinv),
gabomdq@6320
   454
            flipx, flipy,
gabomdq@6320
   455
            smooth);
gabomdq@6320
   456
        /*
gabomdq@6320
   457
        * Turn on source-alpha support
gabomdq@6320
   458
        */
gabomdq@7678
   459
        /* SDL_SetAlpha(rz_dst, SDL_SRCALPHA, 255); */
gabomdq@7678
   460
        SDL_SetColorKey(rz_dst, /* SDL_SRCCOLORKEY */ SDL_TRUE | SDL_RLEACCEL, _colorkey(rz_src));
gabomdq@6320
   461
    } else {
gabomdq@6320
   462
        /*
gabomdq@6320
   463
        * Copy palette and colorkey info
gabomdq@6320
   464
        */
gabomdq@6320
   465
        for (i = 0; i < rz_src->format->palette->ncolors; i++) {
gabomdq@6320
   466
            rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i];
gabomdq@6320
   467
        }
gabomdq@6320
   468
        rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors;
gabomdq@6320
   469
        /*
gabomdq@6320
   470
        * Call the 8bit transformation routine to do the rotation
gabomdq@6320
   471
        */
gabomdq@6320
   472
        transformSurfaceY(rz_src, rz_dst, centerx, centery,
gabomdq@6320
   473
            (int) (sangleinv), (int) (cangleinv),
gabomdq@6320
   474
            flipx, flipy);
gabomdq@7678
   475
        SDL_SetColorKey(rz_dst, /* SDL_SRCCOLORKEY */ SDL_TRUE | SDL_RLEACCEL, _colorkey(rz_src));
gabomdq@6320
   476
    }
gabomdq@6320
   477
    /*
gabomdq@6320
   478
    * Unlock source surface
gabomdq@6320
   479
    */
gabomdq@6320
   480
    if (SDL_MUSTLOCK(rz_src)) {
gabomdq@6320
   481
        SDL_UnlockSurface(rz_src);
gabomdq@6320
   482
    }
gabomdq@6320
   483
gabomdq@6320
   484
    /*
gabomdq@6320
   485
    * Cleanup temp surface
gabomdq@6320
   486
    */
gabomdq@6320
   487
    if (src_converted) {
gabomdq@6320
   488
        SDL_FreeSurface(rz_src);
gabomdq@6320
   489
    }
gabomdq@6320
   490
gabomdq@6320
   491
    /*
gabomdq@6320
   492
    * Return destination surface
gabomdq@6320
   493
    */
gabomdq@6320
   494
    return (rz_dst);
gabomdq@6320
   495
}