Page Menu
Home
Phabricator (Chris)
Search
Configure Global Search
Log In
Files
F126040
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Authored By
Unknown
Size
24 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/util/sdl/sprig/SPG_rotation.c b/util/sdl/sprig/SPG_rotation.c
index 5f681cba..00b1ae87 100644
--- a/util/sdl/sprig/SPG_rotation.c
+++ b/util/sdl/sprig/SPG_rotation.c
@@ -1,737 +1,751 @@
/*
SPriG - SDL Primitive Generator
by Jonathan Dearborn
Based on SGE: SDL Graphics Extension r030809
by Anders Lindström
*/
/*********************************************************************
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
*********************************************************************/
#include "sprig.h"
#include "sprig_common.h"
#include <math.h>
#ifdef SPG_USE_FAST_MATH
#define sqrt fastsqrt
// Fast sqrt for IEEE floating point. From Wikipedia.
float fastsqrt(float value)
{
union
{
int tmp;
float val;
} u;
u.val = value;
u.tmp -= 1<<23; /* Remove last bit so 1.0 gives 1.0 */
/* tmp is now an approximation to logbase2(val) */
u.tmp >>= 1; /* divide by 2 */
u.tmp += 1<<29; /* add 64 to exponent: (e+127)/2 =(e/2)+63, */
/* that represents (e/2)-64 but we want e/2 */
return u.val;
}
#endif
extern SPG_bool spg_useerrors;
extern SPG_bool spg_usedegrees;
extern SPG_bool spg_makedirtyrects;
extern SPG_DirtyTable* spg_dirtytable_front;
void spg_pixelX(SDL_Surface *dest,Sint16 x,Sint16 y,Uint32 color);
SDL_Rect spg_transform_tmap(SDL_Surface *src, SDL_Surface *dst, float angle, float xscale, float yscale, Uint16 qx, Uint16 qy);
//==================================================================================
// Helper function to SPG_TransformX()
// Returns the bounding box
//==================================================================================
void spg_calcrect(SDL_Surface *src, SDL_Surface *dst, float theta, float xscale, float yscale, Uint16 px, Uint16 py, Uint16 qx, Uint16 qy, Sint16 *xmin, Sint16 *ymin, Sint16 *xmax, Sint16 *ymax)
{
Sint16 x, y, rx, ry;
// Clip to src surface
Sint16 sxmin = SPG_CLIP_XMIN(src);
Sint16 sxmax = SPG_CLIP_XMAX(src);
Sint16 symin = SPG_CLIP_YMIN(src);
Sint16 symax = SPG_CLIP_YMAX(src);
Sint16 sx[]={sxmin, sxmax, sxmin, sxmax};
Sint16 sy[]={symin, symax, symax, symin};
// We don't really need fixed-point here
// but why not?
Sint32 const istx = (Sint32)((sin(theta)*xscale) * 8192.0); /* Inverse transform */
Sint32 const ictx = (Sint32)((cos(theta)*xscale) * 8192.2);
Sint32 const isty = (Sint32)((sin(theta)*yscale) * 8192.0);
Sint32 const icty = (Sint32)((cos(theta)*yscale) * 8192.2);
int i;
//Calculate the four corner points
for(i=0; i<4; i++){
rx = sx[i] - px;
ry = sy[i] - py;
x = (Sint16)(((ictx*rx - isty*ry) >> 13) + qx);
y = (Sint16)(((icty*ry + istx*rx) >> 13) + qy);
if(i==0){
*xmax = *xmin = x;
*ymax = *ymin = y;
}else{
if(x>*xmax)
*xmax=x;
else if(x<*xmin)
*xmin=x;
if(y>*ymax)
*ymax=y;
else if(y<*ymin)
*ymin=y;
}
}
//Better safe than sorry...
*xmin -= 1;
*ymin -= 1;
*xmax += 1;
*ymax += 1;
//Clip to dst surface
if( !dst )
return;
if( *xmin < SPG_CLIP_XMIN(dst) )
*xmin = SPG_CLIP_XMIN(dst);
if( *xmax > SPG_CLIP_XMAX(dst) )
*xmax = SPG_CLIP_XMAX(dst);
if( *ymin < SPG_CLIP_YMIN(dst) )
*ymin = SPG_CLIP_YMIN(dst);
if( *ymax > SPG_CLIP_YMAX(dst) )
*ymax = SPG_CLIP_YMAX(dst);
}
/*==================================================================================
** Rotate by angle about pivot (px,py) scale by scale and place at
** position (qx,qy).
**
** Transformation matrix application (rotated coords "R"):
**
** / rx \ / cos(theta) sin(theta) \ / dx \
** | | = | | | |
** \ ry / \ -sin(theta) cos(theta) / \ dy /
**
** => rx = cos(theta) dx + sin(theta) dy
** ry = cos(theta) dy - sin(theta) dx
** but represented as a fixed-point float using integer math
**
** Developed with the help from Terry Hancock (hancock@earthlink.net)
**
**==================================================================================*/
// First we need some macros to handle different bpp
// I'm sorry about this...
#define TRANSFORM(UintXX, DIV) \
Sint32 const src_pitch=src->pitch/DIV; \
Sint32 const dst_pitch=dst->pitch/DIV; \
UintXX const *src_row = (UintXX *)src->pixels; \
UintXX *dst_row; \
Uint32 col;\
\
for (y=ymin; y<=ymax; y++){ /* Changed from y<ymax to y<=ymax Edge fix 7-13-08*/\
dy = y - qy; \
\
sx = (Sint32)(ctdx + stx*dy + mx); /* Compute source anchor points */ \
sy = (Sint32)(cty*dy - stdx + my); \
\
/* Calculate pointer to dst surface */ \
dst_row = (UintXX *)dst->pixels + y*dst_pitch; \
\
for (x=xmin; x<=xmax; x++){ /* Changed from x<xmax to x<=xmax Edge fix 7-13-08*/\
rx=(Sint16)(sx >> 13); /* Convert from fixed-point */ \
ry=(Sint16)(sy >> 13)+1; /* Added +1 Edge fix 7-13-08*/\
/* Make sure the source pixel is actually in the source image. */ \
if( (rx>=sxmin) && (rx<=sxmax) && (ry>=symin) && (ry<=symax) ) /* Changed from (rx<=sxmax) to (rx<=sxmax+1) Edge fix 7-13-08*. Reverted this change on 7/3/2010 - Jon Rafkind */\
{\
col = *(src_row+ry*src_pitch+rx);\
- if(!(flags & SPG_TCOLORKEY && src->flags & SDL_SRCCOLORKEY && col == src->format->colorkey))\
+ if(!(flags & SPG_TCOLORKEY && src->flags & SDL_SRCCOLORKEY && col == colorkey))\
*(dst_row + x) = (UintXX)(col);\
}\
sx += ctx; /* Incremental transformations */ \
sy -= sty; \
} \
}
#define TRANSFORM_GENERIC \
Uint8 R, G, B, A; \
\
for (y=ymin; y<=ymax; y++){ /* Changed from y<ymax to y<=ymax Edge fix 7-13-08*/\
dy = y - qy; \
\
sx = (Sint32)(ctdx + stx*dy + mx); /* Compute source anchor points */ \
sy = (Sint32)(cty*dy - stdx + my); \
\
for (x=xmin; x<=xmax; x++){ /* Changed from x<xmax to x<=xmax Edge fix 7-13-08*/\
rx=(Sint16)(sx >> 13); /* Convert from fixed-point */ \
ry=(Sint16)(sy >> 13)+1; /* Added +1 Edge fix 7-13-08*/\
\
/* Make sure the source pixel is actually in the source image. */ \
if( (rx>=sxmin) && (rx<=sxmax+1) && (ry>=symin) && (ry<=symax) ){ /* Changed from (rx<=sxmax) to (rx<=sxmax+1) Edge fix 7-13-08*/\
SPG_GetRGBA(SPG_GetPixel(src,rx,ry), src->format, &R, &G, &B, &A);\
- if(!(flags & SPG_TCOLORKEY && src->flags & SDL_SRCCOLORKEY && SDL_MapRGB(src->format, R, G, B) == src->format->colorkey))\
+ if(!(flags & SPG_TCOLORKEY && src->flags & SDL_SRCCOLORKEY && SDL_MapRGB(src->format, R, G, B) == colorkey))\
spg_pixelX(dst,x,y,SPG_MapRGBA(dst->format, R, G, B, A)); \
\
} \
sx += ctx; /* Incremental transformations */ \
sy -= sty; \
} \
}
// Interpolated transform
#define TRANSFORM_AA(UintXX, DIV) \
Sint32 const src_pitch=src->pitch/DIV; \
Sint32 const dst_pitch=dst->pitch/DIV; \
UintXX const *src_row = (UintXX *)src->pixels; \
UintXX *dst_row; \
UintXX c1, c2, c3, c4;\
Uint32 R, G, B, A=0; \
UintXX Rmask = src->format->Rmask, Gmask = src->format->Gmask, Bmask = src->format->Bmask, Amask = src->format->Amask;\
Uint32 wx, wy;\
Uint32 p1, p2, p3, p4;\
\
/*
* Interpolation:
* We calculate the distances from our point to the four nearest pixels, d1..d4.
* d(a,b) = sqrt(a�+b�) ~= 0.707(a+b) (Pythagoras (Taylor) expanded around (0.5;0.5))
*
* 1 wx 2
* *-|-* (+ = our point at (x,y))
* | | | (* = the four nearest pixels)
* wy --+ | wx = float(x) - int(x)
* | | wy = float(y) - int(y)
* *---*
* 3 4
* d1 = d(wx,wy) d2 = d(1-wx,wy) d3 = d(wx,1-wy) d4 = d(1-wx,1-wy)
* We now want to weight each pixels importance - it's vicinity to our point:
* w1=d4 w2=d3 w3=d2 w4=d1 (Yes it works... just think a bit about it)
*
* If the pixels have the colors c1..c4 then our point should have the color
* c = (w1*c1 + w2*c2 + w3*c3 + w4*c4)/(w1+w2+w3+w4) (the weighted average)
* but w1+w2+w3+w4 = 4*0.707 so we might as well write it as
* c = p1*c1 + p2*c2 + p3*c3 + p4*c4 where p1..p4 = (w1..w4)/(4*0.707)
*
* But p1..p4 are fixed point so we can just divide the fixed point constant!
* 8192/(4*0.71) = 2897 and we can skip 0.71 too (the division will cancel it everywhere)
* 8192/4 = 2048
*
* 020102: I changed the fixed-point representation for the variables in the weighted average
* to 24.7 to avoid problems with 32bit colors. Everything else is still 18.13. This
* does however not solve the problem with 32bit RGBA colors...
*/\
\
Sint32 const one = 2048>>6; /* 1 in Fixed-point */ \
Sint32 const two = 2*2048>>6; /* 2 in Fixed-point */ \
\
for (y=ymin; y<ymax; y++){ \
dy = y - qy; \
\
sx = (Sint32)(ctdx + stx*dy + mx); /* Compute source anchor points */ \
sy = (Sint32)(cty*dy - stdx + my); \
\
/* Calculate pointer to dst surface */ \
dst_row = (UintXX *)dst->pixels + y*dst_pitch; \
\
for (x=xmin; x<xmax; x++){ \
rx=(Sint16)(sx >> 13); /* Convert from fixed-point */ \
ry=(Sint16)(sy >> 13); \
\
/* Make sure the source pixel is actually in the source image. */ \
- if((rx>=sxmin) && (rx+1<=sxmax) && (ry>=symin) && (ry+1<=symax) && !((flags & SPG_TCOLORKEY) && (src->flags & SDL_SRCCOLORKEY) && *(src_row+ry*src_pitch+rx) == src->format->colorkey) ){ \
+ if((rx>=sxmin) && (rx+1<=sxmax) && (ry>=symin) && (ry+1<=symax) && !((flags & SPG_TCOLORKEY) && (src->flags & SDL_SRCCOLORKEY) && *(src_row+ry*src_pitch+rx) == colorkey) ){ \
wx = (sx & 0x00001FFF) >>8; /* (float(x) - int(x)) / 4 */ \
wy = (sy & 0x00001FFF) >>8;\
\
p4 = wx+wy;\
p3 = one-wx+wy;\
p2 = wx+one-wy;\
p1 = two-wx-wy;\
\
c1 = *(src_row + ry*src_pitch + rx);\
c2 = *(src_row + ry*src_pitch + rx+1);\
c3 = *(src_row + (ry+1)*src_pitch + rx);\
c4 = *(src_row + (ry+1)*src_pitch + rx+1);\
\
/* Calculate the average */\
R = ((p1*(c1 & Rmask) + p2*(c2 & Rmask) + p3*(c3 & Rmask) + p4*(c4 & Rmask))>>7) & Rmask;\
G = ((p1*(c1 & Gmask) + p2*(c2 & Gmask) + p3*(c3 & Gmask) + p4*(c4 & Gmask))>>7) & Gmask;\
B = ((p1*(c1 & Bmask) + p2*(c2 & Bmask) + p3*(c3 & Bmask) + p4*(c4 & Bmask))>>7) & Bmask;\
if(Amask)\
A = (SDL_ALPHA_OPAQUE - ((p1*(c1 & Amask) + p2*(c2 & Amask) + p3*(c3 & Amask) + p4*(c4 & Amask))>>7)) & Amask;\
\
*(dst_row + x) = R | G | B | A;\
} \
sx += ctx; /* Incremental transformations */ \
sy -= sty; \
} \
}
#define TRANSFORM_GENERIC_AA \
Uint8 R, G, B, A, R1, G1, B1, A1=0, R2, G2, B2, A2=0, R3, G3, B3, A3=0, R4, G4, B4, A4=0; \
Sint32 wx, wy, p1, p2, p3, p4;\
\
Sint32 const one = 2048; /* 1 in Fixed-point */ \
Sint32 const two = 2*2048; /* 2 in Fixed-point */ \
\
for (y=ymin; y<ymax; y++){ \
dy = y - qy; \
\
sx = (Sint32)(ctdx + stx*dy + mx); /* Compute source anchor points */ \
sy = (Sint32)(cty*dy - stdx + my); \
\
for (x=xmin; x<xmax; x++){ \
rx=(Sint16)(sx >> 13); /* Convert from fixed-point */ \
ry=(Sint16)(sy >> 13); \
\
/* Make sure the source pixel is actually in the source image. */ \
if( (rx>=sxmin) && (rx+1<=sxmax) && (ry>=symin) && (ry+1<=symax)){ \
wx = (sx & 0x00001FFF) >> 2; /* (float(x) - int(x)) / 4 */ \
wy = (sy & 0x00001FFF) >> 2;\
\
p4 = wx+wy;\
p3 = one-wx+wy;\
p2 = wx+one-wy;\
p1 = two-wx-wy;\
\
SPG_GetRGBA(SPG_GetPixel(src,rx, ry), src->format, &R1, &G1, &B1, &A1);\
SPG_GetRGBA(SPG_GetPixel(src,rx+1,ry), src->format, &R2, &G2, &B2, &A2);\
SPG_GetRGBA(SPG_GetPixel(src,rx, ry+1), src->format, &R3, &G3, &B3, &A3);\
SPG_GetRGBA(SPG_GetPixel(src,rx+1,ry+1), src->format, &R4, &G4, &B4, &A4);\
\
/* Calculate the average */\
R = (p1*R1 + p2*R2 + p3*R3 + p4*R4)>>13;\
G = (p1*G1 + p2*G2 + p3*G3 + p4*G4)>>13;\
B = (p1*B1 + p2*B2 + p3*B3 + p4*B4)>>13;\
A = (p1*A1 + p2*A2 + p3*A3 + p4*A4)>>13;\
- if(!(flags & SPG_TCOLORKEY && src->flags & SDL_SRCCOLORKEY && SDL_MapRGB(src->format, R, G, B) == src->format->colorkey))\
+ if(!(flags & SPG_TCOLORKEY && src->flags & SDL_SRCCOLORKEY && SDL_MapRGB(src->format, R, G, B) == colorkey))\
spg_pixelX(dst,x,y,SPG_MapRGBA(dst->format, R, G, B, A)); \
\
} \
sx += ctx; /* Incremental transformations */ \
sy -= sty; \
} \
}
// We get better performance if AA and normal rendering is separated into two functions (better optimization).
// SPG_TransformX() is used as a wrapper.
SDL_Rect SPG_transformNorm(SDL_Surface *src, SDL_Surface *dst, float angle, float xscale, float yscale ,Uint16 px, Uint16 py, Uint16 qx, Uint16 qy, Uint8 flags)
{
Sint32 dy, sx, sy;
Sint16 x, y, rx, ry;
SDL_Rect r;
+#ifdef PS3
+ /* Hack for the ps3 because it doesn't have src->format->colorkey.
+ * we know that paintown always uses 255,0,255 for the colorkey
+ * so we just hack it in here.
+ */
+ int colorkey = SDL_MapRGB(src->format, 255, 0, 255);
+#else
+ int colorkey = src->format->colorkey;
+#endif
+
r.x = r.y = r.w = r.h = 0;
+
if(spg_usedegrees)
angle *= RADPERDEG; /* Convert to radians. */
// Here we use 18.13 fixed point integer math
// Sint32 should have 31 usable bits and one for sign
// 2^13 = 8192
// Check scales
//Sint32 maxint = (Sint32)(pow(2, sizeof(Sint32)*8 - 1 - 13)); // 2^(31-13)
Sint32 maxint = 262144; // 2^(31-13)
if( xscale == 0 || yscale == 0)
{
return r;
}
if( 8192.0f/xscale > maxint )
xscale = 8192.0f/maxint;
else if( 8192.0f/xscale < -maxint )
xscale = -8192.0f/maxint;
if( 8192.0f/yscale > maxint )
yscale = 8192.0f/maxint;
else if( 8192.0f/yscale < -maxint )
yscale = -8192.0f/maxint;
// Fixed-point equivalents
Sint32 const stx = (Sint32)((sin(angle)/xscale) * 8192.0);
Sint32 const ctx = (Sint32)((cos(angle)/xscale) * 8192.0);
Sint32 const sty = (Sint32)((sin(angle)/yscale) * 8192.0);
Sint32 const cty = (Sint32)((cos(angle)/yscale) * 8192.0);
Sint32 const mx = (Sint32)(px*8192.0);
Sint32 const my = (Sint32)(py*8192.0);
// Compute a bounding rectangle
Sint16 xmin=0, xmax=dst->w, ymin=0, ymax=dst->h;
spg_calcrect(src, dst, angle, xscale, yscale, px, py, qx, qy, &xmin,&ymin, &xmax,&ymax);
// Clip to src surface
Sint16 sxmin = SPG_CLIP_XMIN(src);
Sint16 sxmax = SPG_CLIP_XMAX(src);
Sint16 symin = SPG_CLIP_YMIN(src);
Sint16 symax = SPG_CLIP_YMAX(src);
// Some terms in the transform are constant
Sint32 const dx = xmin - qx;
Sint32 const ctdx = ctx*dx;
Sint32 const stdx = sty*dx;
// Lock surfaces... hopfully less than two needs locking!
if ( spg_lock(src) < 0 )
{
if(spg_useerrors)
SPG_Error("SPG_Transform could not lock surface");
return r;
}
if ( spg_lock(dst) < 0 )
{
if(spg_useerrors)
SPG_Error("SPG_Transform could not lock surface");
spg_unlock(src);
return r;
}
-#ifndef PS3
// Use the correct bpp
if( src->format->BytesPerPixel == dst->format->BytesPerPixel && src->format->BytesPerPixel != 3 && !(flags & SPG_TSAFE)){
+
switch( src->format->BytesPerPixel ){
case 1: { /* Assuming 8-bpp */
TRANSFORM(Uint8, 1)
}
break;
case 2: { /* Probably 15-bpp or 16-bpp */
TRANSFORM(Uint16, 2)
}
break;
case 4: { /* Probably 32-bpp */
TRANSFORM(Uint32, 4)
}
break;
}
- }else{
+ } else {
TRANSFORM_GENERIC
}
-#endif
spg_unlock(src);
spg_unlock(dst);
//Return the bounding rectangle
r.x=xmin; r.y=ymin; r.w=xmax-xmin+1; r.h=ymax-ymin+1;
return r;
}
SDL_Rect SPG_transformAA(SDL_Surface *src, SDL_Surface *dst, float angle, float xscale, float yscale ,Uint16 px, Uint16 py, Uint16 qx, Uint16 qy, Uint8 flags)
{
Sint32 dy, sx, sy;
Sint16 x, y, rx, ry;
SDL_Rect r;
+#ifdef PS3
+ int colorkey = SDL_MapRGB(src->format, 255, 0, 255);
+#else
+ int colorkey = src->format->colorkey;
+#endif
+
r.x = r.y = r.w = r.h = 0;
if(spg_usedegrees)
angle *= RADPERDEG; /* Convert to radians. */
// Here we use 18.13 fixed point integer math
// Sint32 should have 31 usable bits and one for sign
// 2^13 = 8192
// Check scales
//Sint32 maxint = (Sint32)(pow(2, sizeof(Sint32)*8 - 1 - 13)); // 2^(31-13)
Sint32 maxint = 262144; // 2^(31-13)
if( xscale == 0 || yscale == 0)
{
return r;
}
if( 8192.0/xscale > maxint )
xscale = (float)(8192.0/maxint);
else if( 8192.0/xscale < -maxint )
xscale = (float)(-8192.0/maxint);
if( 8192.0/yscale > maxint )
yscale = (float)(8192.0/maxint);
else if( 8192.0/yscale < -maxint )
yscale = (float)(-8192.0/maxint);
// Fixed-point equivalents
Sint32 const stx = (Sint32)((sin(angle)/xscale) * 8192.0);
Sint32 const ctx = (Sint32)((cos(angle)/xscale) * 8192.0);
Sint32 const sty = (Sint32)((sin(angle)/yscale) * 8192.0);
Sint32 const cty = (Sint32)((cos(angle)/yscale) * 8192.0);
Sint32 const mx = (Sint32)(px*8192.0);
Sint32 const my = (Sint32)(py*8192.0);
// Compute a bounding rectangle
Sint16 xmin=0, xmax=dst->w, ymin=0, ymax=dst->h;
spg_calcrect(src, dst, angle, xscale, yscale, px, py, qx, qy, &xmin,&ymin, &xmax,&ymax);
// Clip to src surface
Sint16 sxmin = SPG_CLIP_XMIN(src);
Sint16 sxmax = SPG_CLIP_XMAX(src);
Sint16 symin = SPG_CLIP_YMIN(src);
Sint16 symax = SPG_CLIP_YMAX(src);
// Some terms in the transform are constant
Sint32 const dx = xmin - qx;
Sint32 const ctdx = ctx*dx;
Sint32 const stdx = sty*dx;
// Lock surfaces... hopfully less than two needs locking!
if ( spg_lock(src) < 0 )
{
if(spg_useerrors)
SPG_Error("SPG_Transform could not lock surface");
return r;
}
if ( spg_lock(dst) < 0 )
{
if(spg_useerrors)
SPG_Error("SPG_Transform could not lock surface");
spg_unlock(src);
return r;
}
-#ifndef PS3
// Use the correct bpp
if( src->format->BytesPerPixel == dst->format->BytesPerPixel && src->format->BytesPerPixel != 3 && !(flags & SPG_TSAFE) ){
switch( src->format->BytesPerPixel ){
case 1: { /* Assuming 8-bpp */
TRANSFORM_AA(Uint8, 1)
//TRANSFORM_GENERIC_AA
}
break;
case 2: { /* Probably 15-bpp or 16-bpp */
TRANSFORM_AA(Uint16, 2)
}
break;
case 4: { /* Probably 32-bpp */
TRANSFORM_AA(Uint32, 4)
}
break;
}
}else{
TRANSFORM_GENERIC_AA
}
-#endif
// Unlock surfaces
spg_unlock(src);
spg_unlock(dst);
//Return the bounding rectangle
r.x=xmin; r.y=ymin; r.w=xmax-xmin+1; r.h=ymax-ymin+1;
return r;
}
SDL_Rect SPG_TransformX(SDL_Surface *src, SDL_Surface *dst, float angle, float xscale, float yscale, Uint16 pivotX, Uint16 pivotY, Uint16 destX, Uint16 destY, Uint8 flags)
{
destY++; // Hacky fix for missing edges 7/13/08
SDL_Rect rect;
if(flags & SPG_TTMAP)
rect = spg_transform_tmap(src, dst, angle, xscale, yscale, destX, destY);
else{
if(flags & SPG_TAA)
rect = SPG_transformAA(src, dst, angle, xscale, yscale, pivotX, pivotY, destX, destY, flags);
else
rect = SPG_transformNorm(src, dst, angle, xscale, yscale, pivotX, pivotY, destX, destY, flags);
}
if(spg_makedirtyrects)
{
// Clip it to the screen
SPG_DirtyClip(dst, &rect);
SPG_DirtyAddTo(spg_dirtytable_front, &rect);
}
return rect;
}
//==================================================================================
// Same as SPG_TransformX() but returns a surface with the result
//==================================================================================
SDL_Surface* SPG_Transform(SDL_Surface *src, Uint32 bgColor, float angle, float xscale, float yscale, Uint8 flags)
{
float theta = angle;
if(spg_usedegrees)
theta *= RADPERDEG; /* Convert to radians. */
// Compute a bounding rectangle
Sint16 xmin=0, xmax=0, ymin=0, ymax=0;
spg_calcrect(src, NULL, theta, xscale, yscale, 0, 0, 0, 0, &xmin,&ymin, &xmax,&ymax);
Sint16 w = xmax-xmin+1;
Sint16 h = ymax-ymin+1;
Sint16 qx = -xmin;
Sint16 qy = -ymin;
SDL_Surface *dest;
dest = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, src->format->BitsPerPixel, src->format->Rmask, src->format->Gmask, src->format->Bmask, src->format->Amask);
if(dest == NULL)
{
if(spg_useerrors)
SPG_Error("SPG_Transform could not allocate enough memory");
return NULL;
}
// Copy flag settings (passes on colorkey and alpha blending)
dest->flags = src->flags;
#ifndef PS3
dest->format->alpha = src->format->alpha;
dest->format->colorkey = src->format->colorkey;
#endif
SPG_Fill(dest,bgColor); //Set background color
SPG_TransformX(src, dest, angle, xscale, yscale, 0, 0, qx, qy, flags);
return dest;
}
//==================================================================================
// Rotate using texture mapping
//==================================================================================
SDL_Rect spg_transform_tmap(SDL_Surface *src, SDL_Surface *dst, float angle, float xscale, float yscale, Uint16 qx, Uint16 qy)
{
float a=(SPG_CLIP_XMAX(src) - SPG_CLIP_XMIN(src))/2.0f;
float b=(SPG_CLIP_YMAX(src) - SPG_CLIP_YMIN(src))/2.0f;
float cosv, sinv;
//Get an exact value if possible
if(angle == 0.0f || angle == 360.0f){
cosv=1; sinv=0;
}
else if(angle == 90.0f){
cosv=0; sinv=1;
}
else if(angle == 180.0f){
cosv=-1; sinv=0;
}
else if(angle == 270.0f){
cosv=0; sinv=-1;
}
else{ //Oh well
if(spg_usedegrees)
angle *= RADPERDEG; /* Convert to radians. */
cosv=cos(angle); sinv=sin(angle);
}
//Precalculate as much as possible
float acosv=a*cosv*xscale, bcosv=b*cosv*yscale;
float asinv=a*sinv*xscale, bsinv=b*sinv*yscale;
/* Do the math */
Sint16 xt[4],yt[4];
xt[0] = (Sint16)((-acosv+bsinv)+qx);
yt[0] = (Sint16)((-asinv-bcosv)+qy);
xt[1] = (Sint16)((acosv+bsinv)+qx);
yt[1] = (Sint16)((asinv-bcosv)+qy);
xt[2] = (Sint16)((-acosv-bsinv)+qx);
yt[2] = (Sint16)((-asinv+bcosv)+qy);
xt[3] = (Sint16)((acosv-bsinv)+qx);
yt[3] = (Sint16)((asinv+bcosv)+qy);
//Use a texture mapped rectangle
SPG_QuadTex(dst,xt[0],yt[0],xt[1],yt[1],xt[2],yt[2],xt[3],yt[3],src, SPG_CLIP_XMIN(src),SPG_CLIP_YMIN(src), SPG_CLIP_XMAX(src),SPG_CLIP_YMIN(src), SPG_CLIP_XMIN(src),SPG_CLIP_YMAX(src), SPG_CLIP_XMAX(src),SPG_CLIP_YMAX(src));
//Or maybe two trigons...
//SPG_TexturedTrigon(dest,xt[0],yt[0],xt[1],yt[1],xt[2],yt[2],src, SPG_CLIP_XMIN(src),SPG_CLIP_YMIN(src), SPG_CLIP_XMAX(src),SPG_CLIP_YMIN(src), SPG_CLIP_XMIN(src),SPG_CLIP_YMAX(src));
//SPG_TexturedTrigon(dest,xt[3],yt[3],xt[1],yt[1],xt[2],yt[2],src, SPG_CLIP_XMAX(src),SPG_CLIP_YMAX(src), SPG_CLIP_XMAX(src),SPG_CLIP_YMIN(src), SPG_CLIP_XMIN(src),SPG_CLIP_YMAX(src));
//For debug
//SPG_Trigon(dest,xt[0],yt[0],xt[1],yt[1],xt[2],yt[2],SDL_MapRGB(dest->format,255,0,0));
//SPG_Trigon(dest,xt[3],yt[3],xt[1],yt[1],xt[2],yt[2],SDL_MapRGB(dest->format,0,255,0));
Sint16 xmax=xt[0], xmin=xt[0];
xmax= (xmax>xt[1])? xmax : xt[1];
xmin= (xmin<xt[1])? xmin : xt[1];
xmax= (xmax>xt[2])? xmax : xt[2];
xmin= (xmin<xt[2])? xmin : xt[2];
xmax= (xmax>xt[3])? xmax : xt[3];
xmin= (xmin<xt[3])? xmin : xt[3];
Sint16 ymax=yt[0], ymin=yt[0];
ymax= (ymax>yt[1])? ymax : yt[1];
ymin= (ymin<yt[1])? ymin : yt[1];
ymax= (ymax>yt[2])? ymax : yt[2];
ymin= (ymin<yt[2])? ymin : yt[2];
ymax= (ymax>yt[3])? ymax : yt[3];
ymin= (ymin<yt[3])? ymin : yt[3];
SDL_Rect r;
r.x=xmin; r.y=ymin; r.w=xmax-xmin+1; r.h=ymax-ymin+1;
return r;
}
SDL_Surface* SPG_Rotate(SDL_Surface *src, float angle, Uint32 bgColor)
{
SDL_Surface *dest;
/* Create the destination surface*/
int max = (int)( sqrt( (src->h*src->h/2 + src->w*src->w/2) + 1 ) );
dest=SDL_AllocSurface(SDL_SWSURFACE, max, max, src->format->BitsPerPixel, src->format->Rmask, src->format->Gmask, src->format->Bmask, src->format->Amask );
if(!dest)
{SPG_Error("SPG_Rotate could not allocate enough memory");return NULL;}
SDL_FillRect(dest, NULL, bgColor);
SPG_TransformX(src, dest, angle, 1.0f, 1.0f, src->w/2, src->h/2, dest->w/2, dest->h/2, 0);
return dest;
}
SDL_Surface* SPG_RotateAA(SDL_Surface *src, float angle, Uint32 bgColor)
{
SDL_Surface *dest;
/* Create the destination surface*/
int max = (int)( sqrt( (src->h*src->h/2 + src->w*src->w/2) + 1 ) );
dest=SDL_AllocSurface(SDL_SWSURFACE, max, max, src->format->BitsPerPixel, src->format->Rmask, src->format->Gmask, src->format->Bmask, src->format->Amask );
if(!dest)
{SPG_Error("SPG_RotateAA could not allocate enough memory"); return NULL;}
SDL_FillRect(dest, NULL, bgColor);
SPG_TransformX(src, dest, angle, 1.0f, 1.0f, src->w/2, src->h/2, dest->w/2, dest->h/2, SPG_TAA);
return dest;
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Thu, Jun 11, 10:28 AM (3 w, 5 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
68412
Default Alt Text
(24 KB)
Attached To
Mode
R75 R-Tech1
Attached
Detach File
Event Timeline