Image scaling wrt hotspot; re-added bilinear; minor gfx refactoring

git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@2827 8092fc87-c524-0410-9efc-e669fe64eaf9
This commit is contained in:
avolkov
2007-08-01 03:25:08 +00:00
parent 2dcea171b5
commit 8669bbaf99
13 changed files with 604 additions and 291 deletions
+3
View File
@@ -1,4 +1,7 @@
Changes towards version 0.7:
- Scaling images with respect to their hotspots: stabilizes compound
Melee objects; re-added bilinear Melee scaler; zooming planet uses
bilinear; fixes bug #685 - Alex
- Added --keepaspectratio to keep correct aspect ratio when using
custom resolutions in OpenGL mode - Mika
- Add /var/tmp as possible location for temporary files. Don't try
+4
View File
@@ -19,6 +19,7 @@
#include "battle.h"
#include "controls.h"
#include "options.h"
#include "init.h"
#include "intel.h"
#ifdef NETPLAY
@@ -422,6 +423,9 @@ Battle (void)
battle_counter[0] = CountLinks (&race_q[0]);
battle_counter[1] = CountLinks (&race_q[1]);
if (optMeleeScale != TFB_SCALE_STEP)
SetGraphicScaleMode (optMeleeScale);
setupBattleInputOrder ();
#ifdef NETPLAY
initBattleInputBuffers ();
+8 -4
View File
@@ -585,20 +585,23 @@ DoPresentation (void *pIS)
int cargs;
int draw_what;
int index, x, y, scale, angle;
int scale_mode;
char ImgName[16];
int OldScale;
int old_scale, old_mode;
STAMP s;
if (1 == sscanf (pStr, "%15s", ImgName)
&& strcmp (strupr (ImgName), "SIS") == 0)
{
draw_what = PRES_DRAW_SIS;
scale_mode = TFB_SCALE_NEAREST;
cargs = sscanf (pStr, "%*s %d %d %d %d",
&x, &y, &scale, &angle) + 1;
}
else
{
draw_what = PRES_DRAW_INDEX;
scale_mode = TFB_SCALE_BILINEAR;
cargs = sscanf (pStr, "%d %d %d %d %d",
&index, &x, &y, &scale, &angle);
}
@@ -646,11 +649,12 @@ DoPresentation (void *pIS)
s.origin.y = y;
if (!pPIS->Batched)
LockMutex (GraphicsLock);
OldScale = GetGraphicScale ();
SetGraphicScale (scale);
old_mode = SetGraphicScaleMode (scale_mode);
old_scale = SetGraphicScale (scale);
SetContextClipping (TRUE);
DrawStamp (&s);
SetGraphicScale (OldScale);
SetGraphicScale (old_scale);
SetGraphicScaleMode (old_mode);
if (!pPIS->Batched)
UnlockMutex (GraphicsLock);
}
@@ -34,6 +34,9 @@ int ScreenColorDepth;
int GraphicsDriver;
int TFB_DEBUG_HALT = 0;
static int gscale = GSCALE_IDENTITY;
static int gscale_mode = TFB_SCALE_NEAREST;
// Status: Ignored (only used in fmv.c)
void
SetGraphicUseOtherExtra (int other) //Could this possibly be more cryptic?!? :)
@@ -62,3 +65,31 @@ LoadIntoExtraScreen (RECT *r)
TFB_DrawScreen_Copy(r, TFB_SCREEN_MAIN, TFB_SCREEN_EXTRA);
}
int
SetGraphicScale (int scale)
{
int old_scale = gscale;
gscale = (scale ? scale : GSCALE_IDENTITY);
return old_scale;
}
int
GetGraphicScale (void)
{
return gscale;
}
int
SetGraphicScaleMode (int mode)
{
int old_mode = gscale_mode;
assert (mode >= TFB_SCALE_NEAREST && mode <= TFB_SCALE_TRILINEAR);
gscale_mode = mode;
return old_mode;
}
int
GetGraphicScaleMode (void)
{
return gscale_mode;
}
+11 -4
View File
@@ -67,15 +67,22 @@ int TFB_InitGraphics (int driver, int flags, int width, int height);
void TFB_UninitGraphics (void);
void TFB_ProcessEvents (void);
// 3DO Graphics Stuff
#define GSCALE_IDENTITY 256
typedef enum {
TFB_SCALE_STEP, /* not really a scaler */
TFB_SCALE_NEAREST,
TFB_SCALE_BILINEAR,
TFB_SCALE_TRILINEAR
} SCALE;
void LoadIntoExtraScreen (RECT *r);
void DrawFromExtraScreen (RECT *r);
void SetGraphicGrabOther (int grab_other);
void SetGraphicScale (int scale);
int GetGraphicScale (void);
int SetGraphicScale (int scale);
int GetGraphicScale (void);
int SetGraphicScaleMode (int mode /* enum SCALE */);
int GetGraphicScaleMode (void);
void SetGraphicUseOtherExtra (int other);
void SetTransitionSource (RECT *pRect);
void ScreenTransition (int transition, RECT *pRect);
@@ -22,20 +22,6 @@
#include "graphics/tfb_draw.h"
#include "libs/log.h"
static int gscale = GSCALE_IDENTITY;
void
SetGraphicScale (int scale)
{
gscale = (scale ? scale : GSCALE_IDENTITY);
}
int
GetGraphicScale ()
{
return gscale;
}
static void
read_screen (RECT *lpRect, FRAME DstFramePtr)
{
@@ -191,7 +191,6 @@ FRAME stretch_frame (FRAME FramePtr, int neww, int newh, int destroy)
CREATE_FLAGS flags;
TFB_Image *tfbImg;
TFB_Canvas src, dst;
EXTENT ext;
flags = GetFrameParentDrawable (FramePtr)->Flags;
NewFrame = CaptureDrawable (
@@ -200,9 +199,7 @@ FRAME stretch_frame (FRAME FramePtr, int neww, int newh, int destroy)
LockMutex (tfbImg->mutex);
src = tfbImg->NormalImg;
dst = NewFrame->image->NormalImg;
ext.width = neww;
ext.height = newh;
TFB_DrawCanvas_Rescale_Nearest (src, dst, ext);
TFB_DrawCanvas_Rescale_Nearest (src, dst, -1, NULL, NULL, NULL);
UnlockMutex (tfbImg->mutex);
if (destroy)
DestroyDrawable (ReleaseDrawable (FramePtr));
+505 -231
View File
@@ -105,18 +105,18 @@ TFB_DrawCanvas_Image (TFB_Image *img, int x, int y, int scale,
if (scale != 0 && scale != GSCALE_IDENTITY)
{
int type;
if (optMeleeScale == TFB_SCALE_TRILINEAR && img->MipmapImg)
int type = GetGraphicScaleMode ();
if (type == TFB_SCALE_TRILINEAR && img->MipmapImg)
{
type = TFB_SCALE_TRILINEAR;
// only set the new palette if it changed
if (((SDL_Surface *)img->MipmapImg)->format->palette
&& cmap && img->colormap_version != cmap->version)
SDL_SetColors (img->MipmapImg, (SDL_Color*)palette, 0, 256);
}
else
else if (type == TFB_SCALE_TRILINEAR && !img->MipmapImg)
{
type = TFB_SCALE_NEAREST;
type = TFB_SCALE_BILINEAR;
}
TFB_DrawImage_FixScaling (img, scale, type);
@@ -244,8 +244,7 @@ TFB_DrawCanvas_FilledImage (TFB_Image *img, int x, int y, int scale, int r, int
SDL_Rect srcRect, targetRect, *pSrcRect;
SDL_Surface *surf;
int i;
SDL_Color pal[256];
EXTENT prevextent = img->extent;
bool force_fill = false;
if (img == 0)
{
@@ -257,7 +256,16 @@ TFB_DrawCanvas_FilledImage (TFB_Image *img, int x, int y, int scale, int r, int
if (scale != 0 && scale != GSCALE_IDENTITY)
{
TFB_DrawImage_FixScaling (img, scale, TFB_SCALE_NEAREST);
int type = GetGraphicScaleMode ();
if (type == TFB_SCALE_TRILINEAR)
type = TFB_SCALE_BILINEAR;
// no point in trilinear for filled images
if (scale != img->last_scale || type != img->last_scale_type)
force_fill = true;
TFB_DrawImage_FixScaling (img, scale, type);
surf = img->ScaledImg;
srcRect.x = 0;
srcRect.y = 0;
@@ -270,6 +278,14 @@ TFB_DrawCanvas_FilledImage (TFB_Image *img, int x, int y, int scale, int r, int
}
else
{
if (img->last_scale != 0)
{
// Make sure we remember that the last fill was from
// an unscaled image
force_fill = true;
img->last_scale = 0;
}
surf = img->NormalImg;
pSrcRect = NULL;
@@ -279,6 +295,14 @@ TFB_DrawCanvas_FilledImage (TFB_Image *img, int x, int y, int scale, int r, int
if (surf->format->palette)
{ // set palette for fill-stamp
// Calling SDL_SetColors() results in an expensive src -> dst
// color-mapping operation for an SDL blit, following the call.
// We want to avoid that as much as possible.
// TODO: generate a 32bpp filled image?
SDL_Color pal[256];
for (i = 0; i < 256; i++)
{
pal[i].r = r;
@@ -293,40 +317,43 @@ TFB_DrawCanvas_FilledImage (TFB_Image *img, int x, int y, int scale, int r, int
{ // fill the non-transparent parts of the image with fillcolor
SDL_Surface *src = img->NormalImg;
SDL_Surface *newfill = img->FilledImg;
BOOLEAN force = FALSE;
if (newfill && (newfill->w < surf->w || newfill->h < surf->h))
{
TFB_DrawCanvas_Delete (newfill);
newfill = NULL;
}
// prepare the filled image
if (!newfill)
{
newfill = SDL_CreateRGBSurface (SDL_SWSURFACE,
src->w, src->h,
surf->w, surf->h,
surf->format->BitsPerPixel,
surf->format->Rmask,
surf->format->Gmask,
surf->format->Bmask,
surf->format->Amask);
force = TRUE;
force_fill = true;
}
if (force ||
prevextent.height != img->extent.height ||
prevextent.width != img->extent.width ||
if (force_fill ||
img->last_fill.r != r ||
img->last_fill.g != g ||
img->last_fill.b != b)
{ // image or fillcolor changed - regenerate
TFB_DrawCanvas_Fill (surf, img->extent.width, img->extent.height,
TFB_DrawCanvas_Fill (surf, surf->w, surf->h,
SDL_MapRGBA (newfill->format, r, g, b, 0), newfill);
// important to keep alpha=0 in fillcolor
// -- we process alpha ourselves
// cache filled image if possible
img->last_fill.r = r;
img->last_fill.g = g;
img->last_fill.b = b;
}
// cache filled image if possible
img->last_fill.r = r;
img->last_fill.g = g;
img->last_fill.b = b;
img->FilledImg = newfill;
surf = newfill;
}
@@ -486,48 +513,41 @@ TFB_DrawCanvas_New_ScaleTarget (TFB_Canvas canvas, TFB_Canvas oldcanvas, int typ
{
SDL_Surface *src = (SDL_Surface *)canvas;
SDL_Surface *old = (SDL_Surface *)oldcanvas;
SDL_Surface *newsurf = old;
SDL_Surface *newsurf = NULL;
// For the purposes of this function, bilinear == trilinear
if (type == TFB_SCALE_TRILINEAR)
type = TFB_SCALE_BILINEAR;
if (last_type == TFB_SCALE_TRILINEAR)
last_type = TFB_SCALE_BILINEAR;
if (old && type != last_type)
{
TFB_DrawCanvas_Delete (old);
old = NULL;
}
if (old)
return old; /* can just reuse the old one */
if (type == TFB_SCALE_NEAREST)
{
if (old && type != last_type)
{
TFB_DrawCanvas_Delete (old);
old = NULL;
}
if (!old)
{
newsurf = SDL_CreateRGBSurface (SDL_SWSURFACE, src->w,
src->h,
src->format->BitsPerPixel,
src->format->Rmask,
src->format->Gmask,
src->format->Bmask,
src->format->Amask);
if (src->format->palette)
TFB_DrawCanvas_SetTransparentIndex (newsurf, TFB_DrawCanvas_GetTransparentIndex (src), FALSE);
else
{
int r, g, b;
if (TFB_DrawCanvas_GetTransparentColor (src, &r, &g, &b))
TFB_DrawCanvas_SetTransparentColor (newsurf, r, g, b, FALSE);
}
}
newsurf = SDL_CreateRGBSurface (SDL_SWSURFACE, src->w,
src->h,
src->format->BitsPerPixel,
src->format->Rmask,
src->format->Gmask,
src->format->Bmask,
src->format->Amask);
TFB_DrawCanvas_CopyTransparencyInfo (src, newsurf);
}
else
{
if (old && type != last_type)
{
TFB_DrawCanvas_Delete (old);
old = NULL;
}
if (!old)
{
if (SDL_Screen->format->BitsPerPixel == 32)
newsurf = TFB_DrawCanvas_New_ForScreen (src->w, src->h, TRUE);
else
newsurf = TFB_DrawCanvas_New_TrueColor (src->w, src->h, TRUE);
}
// The scaled image may in fact be larger by 1 pixel than the source
// because of hotspot alignment and fractional edge pixels
if (SDL_Screen->format->BitsPerPixel == 32)
newsurf = TFB_DrawCanvas_New_ForScreen (src->w + 1, src->h + 1, TRUE);
else
newsurf = TFB_DrawCanvas_New_TrueColor (src->w + 1, src->h + 1, TRUE);
}
return newsurf;
@@ -556,14 +576,7 @@ TFB_DrawCanvas_New_RotationTarget (TFB_Canvas src_canvas, int angle)
SDL_GetError());
exit (EXIT_FAILURE);
}
if (src->format->palette)
TFB_DrawCanvas_SetTransparentIndex (newsurf, TFB_DrawCanvas_GetTransparentIndex (src), FALSE);
else
{
int r, g, b;
if (TFB_DrawCanvas_GetTransparentColor (src, &r, &g, &b))
TFB_DrawCanvas_SetTransparentColor (newsurf, r, g, b, FALSE);
}
TFB_DrawCanvas_CopyTransparencyInfo (src, newsurf);
return newsurf;
}
@@ -672,6 +685,25 @@ TFB_DrawCanvas_SetTransparentIndex (TFB_Canvas canvas, int index, BOOLEAN rleacc
}
}
void
TFB_DrawCanvas_CopyTransparencyInfo (TFB_Canvas src_canvas, TFB_Canvas dst_canvas)
{
SDL_Surface* src = (SDL_Surface*)src_canvas;
if (src->format->palette)
{
int index;
index = TFB_DrawCanvas_GetTransparentIndex (src_canvas);
TFB_DrawCanvas_SetTransparentIndex (dst_canvas, index, FALSE);
}
else
{
int r, g, b;
if (TFB_DrawCanvas_GetTransparentColor (src_canvas, &r, &g, &b))
TFB_DrawCanvas_SetTransparentColor (dst_canvas, r, g, b, FALSE);
}
}
BOOLEAN
TFB_DrawCanvas_GetTransparentColor (TFB_Canvas canvas, int *r, int *g, int *b)
{
@@ -707,39 +739,68 @@ TFB_DrawCanvas_SetTransparentColor (TFB_Canvas canvas, int r, int g, int b, BOOL
}
void
TFB_DrawCanvas_GetScaledExtent (TFB_Canvas src_canvas, HOT_SPOT src_hs,
TFB_Canvas src_mipmap, HOT_SPOT mm_hs,
int scale, EXTENT *size, HOT_SPOT *hs)
TFB_DrawCanvas_GetScaledExtent (TFB_Canvas src_canvas, HOT_SPOT* src_hs,
TFB_Canvas src_mipmap, HOT_SPOT* mm_hs,
int scale, int type, EXTENT *size, HOT_SPOT *hs)
{
SDL_Surface *src = (SDL_Surface *)src_canvas;
sint32 x, y, w, h;
int frac;
if (!src_mipmap)
{
size->width = src->w * scale / GSCALE_IDENTITY;
size->height = src->h * scale / GSCALE_IDENTITY;
hs->x = src_hs.x * scale / GSCALE_IDENTITY;
hs->y = src_hs.y * scale / GSCALE_IDENTITY;
w = src->w * scale;
h = src->h * scale;
x = src_hs->x * scale;
y = src_hs->y * scale;
}
else
{
// interpolates extents between src and mipmap to get smoother
// transition when surface changes
SDL_Surface *mipmap = (SDL_Surface *)src_mipmap;
int ratio = scale * 2 - GSCALE_IDENTITY;
float ratio = (scale / (float)GSCALE_IDENTITY) * 2.0f - 1.0f;
if (ratio < 0.0f)
ratio = 0.0f;
else if (ratio > 1.0f)
ratio = 1.0f;
assert (scale >= GSCALE_IDENTITY / 2);
size->width = (int)((src->w - mipmap->w) * ratio + mipmap->w + 0.5);
size->height = (int)((src->h - mipmap->h) * ratio + mipmap->h + 0.5);
w = mipmap->w * GSCALE_IDENTITY + (src->w - mipmap->w) * ratio;
h = mipmap->h * GSCALE_IDENTITY + (src->h - mipmap->h) * ratio;
hs->x = (int)((src_hs.x - mm_hs.x) * ratio + mm_hs.x + 0.5);
hs->y = (int)((src_hs.y - mm_hs.y) * ratio + mm_hs.y + 0.5);
// Seems it is better to use mipmap hotspot because some
// source and mipmap images have the same dimensions!
x = mm_hs->x * GSCALE_IDENTITY + (src_hs->x - mm_hs->x) * ratio;
y = mm_hs->y * GSCALE_IDENTITY + (src_hs->y - mm_hs->y) * ratio;
}
if (type != TFB_SCALE_NEAREST)
{
// align hotspot on an whole pixel
if (x & (GSCALE_IDENTITY - 1))
{
frac = GSCALE_IDENTITY - (x & (GSCALE_IDENTITY - 1));
x += frac;
w += frac;
}
if (y & (GSCALE_IDENTITY - 1))
{
frac = GSCALE_IDENTITY - (y & (GSCALE_IDENTITY - 1));
y += frac;
h += frac;
}
// pad the extent to accomodate fractional edge pixels
w += (GSCALE_IDENTITY - 1);
h += (GSCALE_IDENTITY - 1);
}
size->width = w / GSCALE_IDENTITY;
size->height = h / GSCALE_IDENTITY;
hs->x = x / GSCALE_IDENTITY;
hs->y = y / GSCALE_IDENTITY;
// Scaled image can be larger than the source by 1 pixel
// because of hotspot alignment and fractional edge pixels
assert (size->width <= src->w + 1 && size->height <= src->h + 1);
if (!size->width && src->w)
size->width = 1;
if (!size->height && src->h)
@@ -756,57 +817,48 @@ TFB_DrawCanvas_GetExtent (TFB_Canvas canvas, EXTENT *size)
}
void
TFB_DrawCanvas_Rescale_Nearest (TFB_Canvas src_canvas, TFB_Canvas dest_canvas, EXTENT size)
TFB_DrawCanvas_Rescale_Nearest (TFB_Canvas src_canvas, TFB_Canvas dst_canvas,
int scale, HOT_SPOT* src_hs, EXTENT* size, HOT_SPOT* dst_hs)
{
#define NNS_MAX_DIMS 600
SDL_Surface *src = (SDL_Surface *)src_canvas;
SDL_Surface *dst = (SDL_Surface *)dest_canvas;
int x, y, sx, sy, *csax, *csay, csx, csy;
int saspace[NNS_MAX_DIMS];
int *sax, *say;
SDL_Surface *dst = (SDL_Surface *)dst_canvas;
int x, y;
int fsx = 0, fsy = 0; // source fractional dx and dy increments
int ssx = 0, ssy = 0; // source fractional x and y starting points
int w, h;
if (size.width + size.height > NNS_MAX_DIMS)
if (scale > 0)
{
log_add (log_Warning, "TFB_DrawCanvas_Scale: Tried to zoom"
" an image to unreasonable size! Failing.");
return;
TFB_DrawCanvas_GetScaledExtent (src, src_hs, NULL, NULL, scale,
TFB_SCALE_NEAREST, size, dst_hs);
w = size->width;
h = size->height;
}
if (size.width > dst->w || size.height > dst->h)
else
{
log_add (log_Warning, "TFB_DrawCanvas_Scale: Tried to scale"
// Just go with the dst surface dimensions
w = dst->w;
h = dst->h;
}
if (w > dst->w || h > dst->h)
{
log_add (log_Warning, "TFB_DrawCanvas_Rescale_Nearest: Tried to scale"
" image to size %d %d when dest_canvas has only"
" dimensions of %d %d! Failing.",
size.width, size.height, dst->w, dst->h);
w, h, dst->w, dst->h);
return;
}
sx = sy = 0;
if (size.width > 1)
sx = ((src->w - 1) << 16) / (size.width - 1);
if (size.height > 1)
sy = ((src->h - 1) << 16) / (size.height - 1);
sax = saspace;
say = saspace + size.width;
/*
* Precalculate row increments
* We start with a value in 0..0.5 range to shift the bigger
* jumps towards the center of the image
*/
csax = sax;
for (x = 0, csx = 0x6000; x < size.width; x++) {
*csax = csx >> 16;
csax++;
csx &= 0xffff;
csx += sx;
}
csay = say;
for (y = 0, csy = 0x6000; y < size.height; y++) {
*csay = csy >> 16;
csay++;
csy &= 0xffff;
csy += sy;
}
if (w > 1)
fsx = ((src->w - 1) << 16) / (w - 1);
if (h > 1)
fsy = ((src->h - 1) << 16) / (h - 1);
// We start with a value in 0..0.5 range to shift the bigger
// jumps towards the center of the image
ssx = 0x6000;
ssy = 0x6000;
SDL_LockSurface (src);
SDL_LockSurface (dst);
@@ -814,29 +866,33 @@ TFB_DrawCanvas_Rescale_Nearest (TFB_Canvas src_canvas, TFB_Canvas dest_canvas, E
if (src->format->BytesPerPixel == 1 && dst->format->BytesPerPixel == 1)
{
Uint8 *sp, *csp, *dp, *cdp;
int sx, sy; // source fractional x and y positions
sp = csp = (Uint8 *) src->pixels;
dp = cdp = (Uint8 *) dst->pixels;
csay = say;
for (y = 0; y < size.height; ++y) {
csp += (*csay) * src->pitch;
for (y = 0, sy = ssy; y < h; ++y)
{
csp += (sy >> 16) * src->pitch;
sp = csp;
dp = cdp;
csax = sax;
for (x = 0; x < size.width; ++x) {
sp += *csax;
for (x = 0, sx = ssx; x < w; ++x)
{
sp += (sx >> 16);
*dp = *sp;
++csax;
sx &= 0xffff;
sx += fsx;
++dp;
}
++csay;
sy &= 0xffff;
sy += fsy;
cdp += dst->pitch;
}
}
else if (src->format->BytesPerPixel == 4 && dst->format->BytesPerPixel == 4)
{
Uint32 *sp, *csp, *dp, *cdp;
int sx, sy; // source fractional x and y positions
int sgap, dgap;
sgap = src->pitch >> 2;
@@ -845,19 +901,21 @@ TFB_DrawCanvas_Rescale_Nearest (TFB_Canvas src_canvas, TFB_Canvas dest_canvas, E
sp = csp = (Uint32 *) src->pixels;
dp = cdp = (Uint32 *) dst->pixels;
csay = say;
for (y = 0; y < size.height; ++y) {
csp += (*csay) * sgap;
for (y = 0, sy = ssy; y < h; ++y)
{
csp += (sy >> 16) * sgap;
sp = csp;
dp = cdp;
csax = sax;
for (x = 0; x < size.width; ++x) {
sp += *csax;
for (x = 0, sx = ssx; x < w; ++x)
{
sp += (sx >> 16);
*dp = *sp;
++csax;
sx &= 0xffff;
sx += fsx;
++dp;
}
++csay;
sy &= 0xffff;
sy += fsy;
cdp += dgap;
}
}
@@ -913,7 +971,7 @@ blend_ratio_2 (Uint8 c1, Uint8 c2, int ratio)
}
static inline Uint32
tri_get_pixel (void* ppix, SDL_PixelFormat *fmt, SDL_Color *pal,
scale_read_pixel (void* ppix, SDL_PixelFormat *fmt, SDL_Color *pal,
Uint32 mask, Uint32 key)
{
pixel_t p;
@@ -956,29 +1014,41 @@ tri_get_pixel (void* ppix, SDL_PixelFormat *fmt, SDL_Color *pal,
return p.value;
}
static inline Uint32
scale_get_pixel (SDL_Surface *src, Uint32 mask, Uint32 key, int x, int y)
{
SDL_Color *pal = src->format->palette? src->format->palette->colors : 0;
if (x < 0 || x >= src->w || y < 0 || y >= src->h)
return 0;
return scale_read_pixel ((Uint8*)src->pixels + y * src->pitch +
x * src->format->BytesPerPixel, src->format, pal, mask, key);
}
void
TFB_DrawCanvas_Rescale_Trilinear (TFB_Canvas src_canvas,
TFB_Canvas dest_canvas, TFB_Canvas src_mipmap, EXTENT size)
TFB_DrawCanvas_Rescale_Trilinear (TFB_Canvas src_canvas, TFB_Canvas src_mipmap,
TFB_Canvas dst_canvas, int scale, HOT_SPOT* src_hs, HOT_SPOT* mm_hs,
EXTENT* size, HOT_SPOT* dst_hs)
{
SDL_Surface *src = (SDL_Surface *)src_canvas;
SDL_Surface *dst = (SDL_Surface *)dest_canvas;
SDL_Surface *mipmap = (SDL_Surface *)src_mipmap;
SDL_Surface *dst = (SDL_Surface *)dst_canvas;
SDL_Surface *mm = (SDL_Surface *)src_mipmap;
SDL_PixelFormat *srcfmt = src->format;
SDL_PixelFormat *mmfmt = mipmap->format;
SDL_PixelFormat *mmfmt = mm->format;
SDL_PixelFormat *dstfmt = dst->format;
SDL_Color *srcpal = srcfmt->palette? srcfmt->palette->colors : 0;
SDL_Color *mmpal = mmfmt->palette ? mmfmt->palette->colors : 0;
const int sbpp = srcfmt->BytesPerPixel;
const int mmbpp = mmfmt->BytesPerPixel;
const int slen = src->pitch;
const int mmlen = mipmap->pitch;
const int mmlen = mm->pitch;
const int dst_has_alpha = (dstfmt->Amask != 0);
const int transparent = (dst->flags & SDL_SRCCOLORKEY) ?
dstfmt->colorkey : 0;
const int w = size.width, h = size.height;
const int alpha_threshold = dst_has_alpha ? 0 : 127;
// src v. mipmap importance factor
int ratio;
int ratio = scale * 2 - GSCALE_IDENTITY;
// source masks and keys
Uint32 mk0 = 0, ck0 = ~0, mk1 = 0, ck1 = ~0;
// source fractional x and y positions
@@ -987,36 +1057,67 @@ TFB_DrawCanvas_Rescale_Trilinear (TFB_Canvas src_canvas,
int fsx0 = 0, fsy0 = 0, fsx1 = 0, fsy1 = 0;
// source fractional x and y starting points
int ssx0 = 0, ssy0 = 0, ssx1 = 0, ssy1 = 0;
int x, y;
int x, y, w, h;
fsx0 = (src->w << 16) / w;
fsy0 = (src->h << 16) / h;
if (scale > 0)
{
int fw, fh;
if (w > 1)
fsx1 = ((mipmap->w - 1) << 16) / (w - 1);
if (h > 1)
fsy1 = ((mipmap->h - 1) << 16) / (h - 1);
// Use (scale / GSCALE_IDENTITY) sizing factor
TFB_DrawCanvas_GetScaledExtent (src, src_hs, mm, mm_hs, scale,
TFB_SCALE_TRILINEAR, size, dst_hs);
// give equal importance to both edges
ssx0 = (((src->w - 1) << 16) - fsx0 * (w - 1)) >> 1;
ssy0 = (((src->h - 1) << 16) - fsy0 * (h - 1)) >> 1;
w = size->width;
h = size->height;
ssx1 = (((mipmap->w - 1) << 16) - fsx1 * (w - 1)) >> 1;
ssy1 = (((mipmap->h - 1) << 16) - fsy1 * (h - 1)) >> 1;
fw = mm->w * GSCALE_IDENTITY + (src->w - mm->w) * ratio;
fh = mm->h * GSCALE_IDENTITY + (src->h - mm->h) * ratio;
// src v. mipmap importance factor
ratio = (w << 9) / src->w - 256;
if (ratio < 0)
ratio = 0;
if (ratio > 256)
ratio = 256;
// This limits the effective source dimensions to 2048x2048,
// and we also lose 4 bits of precision out of 16 (no problem)
fsx0 = (src->w << 20) / fw;
fsx0 <<= 4;
fsy0 = (src->h << 20) / fh;
fsy0 <<= 4;
if (size.width > dst->w || size.height > dst->h)
fsx1 = (mm->w << 20) / fw;
fsx1 <<= 4;
fsy1 = (mm->h << 20) / fh;
fsy1 <<= 4;
// position the hotspots directly over each other
ssx0 = (src_hs->x << 16) - fsx0 * dst_hs->x;
ssy0 = (src_hs->y << 16) - fsy0 * dst_hs->y;
ssx1 = (mm_hs->x << 16) - fsx1 * dst_hs->x;
ssy1 = (mm_hs->y << 16) - fsy1 * dst_hs->y;
}
else
{
// Just go with the dst surface dimensions
w = dst->w;
h = dst->h;
fsx0 = (src->w << 16) / w;
fsy0 = (src->h << 16) / h;
fsx1 = (mm->w << 16) / w;
fsy1 = (mm->h << 16) / h;
// give equal importance to both edges
ssx0 = (((src->w - 1) << 16) - fsx0 * (w - 1)) >> 1;
ssy0 = (((src->h - 1) << 16) - fsy0 * (h - 1)) >> 1;
ssx1 = (((mm->w - 1) << 16) - fsx1 * (w - 1)) >> 1;
ssy1 = (((mm->h - 1) << 16) - fsy1 * (h - 1)) >> 1;
}
if (w > dst->w || h > dst->h)
{
log_add (log_Warning, "TFB_DrawCanvas_Rescale_Trilinear: "
"Tried to scale image to size %d %d when dest_canvas"
" has only dimensions of %d %d! Failing.",
size.width, size.height, dst->w, dst->h);
w, h, dst->w, dst->h);
return;
}
@@ -1048,7 +1149,7 @@ TFB_DrawCanvas_Rescale_Trilinear (TFB_Canvas src_canvas,
mk1 = mmfmt->Amask;
ck1 = 0;
}
else if (mipmap->flags & SDL_SRCCOLORKEY)
else if (mm->flags & SDL_SRCCOLORKEY)
{ // colorkey transparency
mk1 = ~mmfmt->Amask;
ck1 = mmfmt->colorkey & mk1;
@@ -1056,15 +1157,17 @@ TFB_DrawCanvas_Rescale_Trilinear (TFB_Canvas src_canvas,
SDL_LockSurface(src);
SDL_LockSurface(dst);
SDL_LockSurface(mipmap);
SDL_LockSurface(mm);
for (y = 0, sy0 = ssy0, sy1 = ssy1;
y < h;
++y, sy0 += fsy0, sy1 += fsy1)
{
Uint32 *dst_p = (Uint32 *) ((Uint8*)dst->pixels + y * dst->pitch);
Uint8 *src_a0 = (Uint8*)src->pixels + (sy0 >> 16) * slen;
Uint8 *src_a1 = (Uint8*)mipmap->pixels + (sy1 >> 16) * mmlen;
const int py0 = (sy0 >> 16);
const int py1 = (sy1 >> 16);
Uint8 *src_a0 = (Uint8*)src->pixels + py0 * slen;
Uint8 *src_a1 = (Uint8*)mm->pixels + py1 * mmlen;
// retrieve the fractional portions of y
const Uint8 v0 = (sy0 >> 8) & 0xff;
const Uint8 v1 = (sy1 >> 8) & 0xff;
@@ -1074,8 +1177,10 @@ TFB_DrawCanvas_Rescale_Trilinear (TFB_Canvas src_canvas,
x < w;
++x, ++dst_p, sx0 += fsx0, sx1 += fsx1)
{
Uint8 *src_p0 = src_a0 + (sx0 >> 16) * sbpp;
Uint8 *src_p1 = src_a1 + (sx1 >> 16) * mmbpp;
const int px0 = (sx0 >> 16);
const int px1 = (sx1 >> 16);
Uint8 *src_p0 = src_a0 + px0 * sbpp;
Uint8 *src_p1 = src_a1 + px1 * mmbpp;
// retrieve the fractional portions of x
const Uint8 u0 = (sx0 >> 8) & 0xff;
const Uint8 u1 = (sx1 >> 8) & 0xff;
@@ -1092,81 +1197,58 @@ TFB_DrawCanvas_Rescale_Trilinear (TFB_Canvas src_canvas,
w0[1] = btable[u0][255 - v0];
w0[2] = btable[255 - u0][v0];
w0[3] = btable[u0][v0];
w1[0] = btable[255 - u1][255 - v1];
w1[1] = btable[u1][255 - v1];
w1[2] = btable[255 - u1][v1];
w1[3] = btable[u1][v1];
// collect interesting pixels from src image
p0[0].value = tri_get_pixel (src_p0, srcfmt, srcpal, mk0, ck0);
if ((sx0 >> 16) <= src->w - 2)
// Collect interesting pixels from src image
// Optimization: speed is criticial on larger images;
// most pixel reads fall completely inside the image
if (px0 >= 0 && px0 + 1 < src->w && py0 >= 0 && py0 + 1 < src->h)
{
p0[1].value = tri_get_pixel (src_p0 + sbpp,
srcfmt, srcpal, mk0, ck0);
Uint8 *src_p = src_a0 + px0 * sbpp;
if ((sy0 >> 16) <= src->h - 2)
{
p0[2].value = tri_get_pixel (src_p0 + slen,
srcfmt, srcpal, mk0, ck0);
p0[3].value = tri_get_pixel (src_p0 + slen + sbpp,
srcfmt, srcpal, mk0, ck0);
}
else
{
p0[2].value = p0[0].value;
p0[3].value = p0[1].value;
}
p0[0].value = scale_read_pixel (src_p, srcfmt,
srcpal, mk0, ck0);
p0[1].value = scale_read_pixel (src_p + sbpp, srcfmt,
srcpal, mk0, ck0);
p0[2].value = scale_read_pixel (src_p + slen, srcfmt,
srcpal, mk0, ck0);
p0[3].value = scale_read_pixel (src_p + sbpp + slen, srcfmt,
srcpal, mk0, ck0);
}
else
{
p0[1].value = p0[0].value;
if ((sy0 >> 16) <= src->h - 2)
{
p0[2].value = tri_get_pixel (src_p0 + slen,
srcfmt, srcpal, mk0, ck0);
}
else
{
p0[2].value = p0[0].value;
}
p0[3].value = p0[2].value;
p0[0].value = scale_get_pixel (src, mk0, ck0, px0, py0);
p0[1].value = scale_get_pixel (src, mk0, ck0, px0 + 1, py0);
p0[2].value = scale_get_pixel (src, mk0, ck0, px0, py0 + 1);
p0[3].value = scale_get_pixel (src, mk0, ck0,
px0 + 1, py0 + 1);
}
// collect interesting pixels from mipmap image
p1[0].value = tri_get_pixel (src_p1, mmfmt, mmpal, mk1, ck1);
if ((sx1 >> 16) <= mipmap->w - 2)
// Collect interesting pixels from mipmap image
if (px1 >= 0 && px1 + 1 < mm->w && py1 >= 0 && py1 + 1 < mm->h)
{
p1[1].value = tri_get_pixel (src_p1 + mmbpp,
mmfmt, mmpal, mk1, ck1);
Uint8 *mm_p = src_a1 + px1 * mmbpp;
if ((sy1 >> 16) <= mipmap->h - 2)
{
p1[2].value = tri_get_pixel (src_p1 + mmlen,
mmfmt, mmpal, mk1, ck1);
p1[3].value = tri_get_pixel (src_p1 + mmlen + mmbpp,
mmfmt, mmpal, mk1, ck1);
}
else
{
p1[2].value = p1[0].value;
p1[3].value = p1[1].value;
}
p1[0].value = scale_read_pixel (mm_p, mmfmt,
mmpal, mk1, ck1);
p1[1].value = scale_read_pixel (mm_p + mmbpp, mmfmt,
mmpal, mk1, ck1);
p1[2].value = scale_read_pixel (mm_p + mmlen, mmfmt,
mmpal, mk1, ck1);
p1[3].value = scale_read_pixel (mm_p + mmbpp + mmlen, mmfmt,
mmpal, mk1, ck1);
}
else
{
p1[1].value = p1[0].value;
if ((sy1 >> 16) <= mipmap->h - 2)
{
p1[2].value = tri_get_pixel (src_p1 + mmlen,
mmfmt, mmpal, mk1, ck1);
}
else
{
p1[2].value = p1[0].value;
}
p1[3].value = p1[2].value;
p1[0].value = scale_get_pixel (mm, mk1, ck1, px1, py1);
p1[1].value = scale_get_pixel (mm, mk1, ck1, px1 + 1, py1);
p1[2].value = scale_get_pixel (mm, mk1, ck1, px1, py1 + 1);
p1[3].value = scale_get_pixel (mm, mk1, ck1,
px1 + 1, py1 + 1);
}
p0[4].c.a = dot_product_8_4 (p0, 3, w0);
@@ -1192,6 +1274,9 @@ TFB_DrawCanvas_Rescale_Trilinear (TFB_Canvas src_canvas,
p0[4].c.g = blend_ratio_2 (p0[4].c.g, p1[4].c.g, ratio);
p0[4].c.b = blend_ratio_2 (p0[4].c.b, p1[4].c.b, ratio);
// TODO: we should handle alpha-blending here, but we do
// not know the destination color for blending!
*dst_p =
(p0[4].c.r << dstfmt->Rshift) |
(p0[4].c.g << dstfmt->Gshift) |
@@ -1251,7 +1336,196 @@ TFB_DrawCanvas_Rescale_Trilinear (TFB_Canvas src_canvas,
}
}
SDL_UnlockSurface(mipmap);
SDL_UnlockSurface(mm);
SDL_UnlockSurface(dst);
SDL_UnlockSurface(src);
}
void
TFB_DrawCanvas_Rescale_Bilinear (TFB_Canvas src_canvas, TFB_Canvas dst_canvas,
int scale, HOT_SPOT* src_hs, EXTENT* size, HOT_SPOT* dst_hs)
{
SDL_Surface *src = (SDL_Surface *)src_canvas;
SDL_Surface *dst = (SDL_Surface *)dst_canvas;
SDL_PixelFormat *srcfmt = src->format;
SDL_PixelFormat *dstfmt = dst->format;
SDL_Color *srcpal = srcfmt->palette? srcfmt->palette->colors : 0;
const int sbpp = srcfmt->BytesPerPixel;
const int slen = src->pitch;
const int dst_has_alpha = (dstfmt->Amask != 0);
const int transparent = (dst->flags & SDL_SRCCOLORKEY) ?
dstfmt->colorkey : 0;
const int alpha_threshold = dst_has_alpha ? 0 : 127;
// source masks and keys
Uint32 mk = 0, ck = ~0;
// source fractional x and y positions
int sx, sy;
// source fractional dx and dy increments
int fsx = 0, fsy = 0;
// source fractional x and y starting points
int ssx = 0, ssy = 0;
int x, y, w, h;
if (scale > 0)
{
// Use (scale / GSCALE_IDENTITY) sizing factor
TFB_DrawCanvas_GetScaledExtent (src, src_hs, NULL, NULL, scale,
TFB_SCALE_BILINEAR, size, dst_hs);
w = size->width;
h = size->height;
fsx = (GSCALE_IDENTITY << 16) / scale;
fsy = (GSCALE_IDENTITY << 16) / scale;
// position the hotspots directly over each other
ssx = (src_hs->x << 16) - fsx * dst_hs->x;
ssy = (src_hs->y << 16) - fsy * dst_hs->y;
}
else
{
// Just go with the dst surface dimensions
w = dst->w;
h = dst->h;
fsx = (src->w << 16) / w;
fsy = (src->h << 16) / h;
// give equal importance to both edges
ssx = (((src->w - 1) << 16) - fsx * (w - 1)) >> 1;
ssy = (((src->h - 1) << 16) - fsy * (h - 1)) >> 1;
}
if (w > dst->w || h > dst->h)
{
log_add (log_Warning, "TFB_DrawCanvas_Rescale_Bilinear: "
"Tried to scale image to size %d %d when dest_canvas"
" has only dimensions of %d %d! Failing.",
w, h, dst->w, dst->h);
return;
}
if ((srcfmt->BytesPerPixel != 1 && srcfmt->BytesPerPixel != 4) ||
(dst->format->BytesPerPixel != 4))
{
log_add (log_Warning, "TFB_DrawCanvas_Rescale_Bilinear: "
"Tried to deal with unknown BPP: %d -> %d",
srcfmt->BitsPerPixel, dst->format->BitsPerPixel);
return;
}
// use colorkeys where appropriate
if (srcfmt->Amask)
{ // alpha transparency
mk = srcfmt->Amask;
ck = 0;
}
else if (src->flags & SDL_SRCCOLORKEY)
{ // colorkey transparency
mk = ~srcfmt->Amask;
ck = srcfmt->colorkey & mk;
}
SDL_LockSurface(src);
SDL_LockSurface(dst);
for (y = 0, sy = ssy; y < h; ++y, sy += fsy)
{
Uint32 *dst_p = (Uint32 *) ((Uint8*)dst->pixels + y * dst->pitch);
const int py = (sy >> 16);
Uint8 *src_a = (Uint8*)src->pixels + py * slen;
// retrieve the fractional portions of y
const Uint8 v = (sy >> 8) & 0xff;
Uint8 weight[4]; // pixel weight vectors
for (x = 0, sx = ssx; x < w; ++x, ++dst_p, sx += fsx)
{
const int px = (sx >> 16);
// retrieve the fractional portions of x
const Uint8 u = (sx >> 8) & 0xff;
// pixels are examined and numbered in pattern
// 0 1
// 2 3
// the ideal pixel (4) is somewhere between these four
// and is calculated from these using weight vector (weight)
// with a dot product
pixel_t p[5];
weight[0] = btable[255 - u][255 - v];
weight[1] = btable[u][255 - v];
weight[2] = btable[255 - u][v];
weight[3] = btable[u][v];
// Collect interesting pixels from src image
// Optimization: speed is criticial on larger images;
// most pixel reads fall completely inside the image
if (px >= 0 && px + 1 < src->w && py >= 0 && py + 1 < src->h)
{
Uint8 *src_p = src_a + px * sbpp;
p[0].value = scale_read_pixel (src_p, srcfmt, srcpal, mk, ck);
p[1].value = scale_read_pixel (src_p + sbpp, srcfmt,
srcpal, mk, ck);
p[2].value = scale_read_pixel (src_p + slen, srcfmt,
srcpal, mk, ck);
p[3].value = scale_read_pixel (src_p + sbpp + slen, srcfmt,
srcpal, mk, ck);
}
else
{
p[0].value = scale_get_pixel (src, mk, ck, px, py);
p[1].value = scale_get_pixel (src, mk, ck, px + 1, py);
p[2].value = scale_get_pixel (src, mk, ck, px, py + 1);
p[3].value = scale_get_pixel (src, mk, ck, px + 1, py + 1);
}
p[4].c.a = dot_product_8_4 (p, 3, weight);
if (p[4].c.a <= alpha_threshold)
{
*dst_p = transparent;
}
else if (!dst_has_alpha)
{ // RGB surface handling
p[4].c.r = dot_product_8_4 (p, 0, weight);
p[4].c.g = dot_product_8_4 (p, 1, weight);
p[4].c.b = dot_product_8_4 (p, 2, weight);
// TODO: we should handle alpha-blending here, but we do
// not know the destination color for blending!
*dst_p =
(p[4].c.r << dstfmt->Rshift) |
(p[4].c.g << dstfmt->Gshift) |
(p[4].c.b << dstfmt->Bshift);
}
else
{ // RGBA surface handling
// we do not want to blend with non-present pixels
// (pixels that have alpha == 0) as these will
// skew the result and make resulting alpha useless
int i;
for (i = 0; i < 4; ++i)
if (p[i].c.a == 0)
weight[i] = 0;
p[4].c.r = weight_product_8_4 (p, 0, weight);
p[4].c.g = weight_product_8_4 (p, 1, weight);
p[4].c.b = weight_product_8_4 (p, 2, weight);
// error-correct alpha to fully opaque to remove
// the often unwanted and unnecessary blending
if (p[4].c.a > 0xf8)
p[4].c.a = 0xff;
*dst_p =
(p[4].c.r << dstfmt->Rshift) |
(p[4].c.g << dstfmt->Gshift) |
(p[4].c.b << dstfmt->Bshift) |
(p[4].c.a << dstfmt->Ashift);
}
}
}
SDL_UnlockSurface(dst);
SDL_UnlockSurface(src);
}
+17 -14
View File
@@ -292,6 +292,7 @@ TFB_DrawImage_New (TFB_Canvas canvas)
img->MipmapHs = NullHs;
img->last_scale_hs = NullHs;
img->last_scale_type = -1;
img->last_scale = 0;
TFB_DrawCanvas_GetExtent (canvas, &img->extent);
img->Palette = TFB_DrawCanvas_ExtractPalette (canvas);
@@ -322,6 +323,7 @@ TFB_DrawImage_CreateForScreen (int w, int h, BOOLEAN withalpha)
img->MipmapHs = NullHs;
img->last_scale_hs = NullHs;
img->last_scale_type = -1;
img->last_scale = 0;
img->Palette = NULL;
img->extent.width = w;
img->extent.height = h;
@@ -389,28 +391,29 @@ TFB_DrawImage_Delete (TFB_Image *image)
void
TFB_DrawImage_FixScaling (TFB_Image *image, int target, int type)
{
EXTENT old = image->extent;
HOT_SPOT oldhs = image->last_scale_hs;
TFB_DrawCanvas_GetScaledExtent (image->NormalImg, image->NormalHs,
image->MipmapImg, image->MipmapHs, target,
&image->extent, &image->last_scale_hs);
if ((old.width != image->extent.width) ||
(old.height != image->extent.height) || image->dirty ||
!image->ScaledImg || type != image->last_scale_type ||
(oldhs.x != image->last_scale_hs.x) ||
(oldhs.y != image->last_scale_hs.y))
if (image->dirty || !image->ScaledImg ||
target != image->last_scale ||
type != image->last_scale_type)
{
image->dirty = FALSE;
image->ScaledImg = TFB_DrawCanvas_New_ScaleTarget (image->NormalImg,
image->ScaledImg, type, image->last_scale_type);
image->last_scale_type = type;
if (type == TFB_SCALE_NEAREST)
TFB_DrawCanvas_Rescale_Nearest (image->NormalImg,
image->ScaledImg, image->extent);
image->ScaledImg, target, &image->NormalHs,
&image->extent, &image->last_scale_hs);
else if (type == TFB_SCALE_BILINEAR)
TFB_DrawCanvas_Rescale_Bilinear (image->NormalImg,
image->ScaledImg, target, &image->NormalHs,
&image->extent, &image->last_scale_hs);
else
TFB_DrawCanvas_Rescale_Trilinear (image->NormalImg,
image->ScaledImg, image->MipmapImg, image->extent);
image->MipmapImg, image->ScaledImg, target,
&image->NormalHs, &image->MipmapHs,
&image->extent, &image->last_scale_hs);
image->last_scale_type = type;
image->last_scale = target;
}
}
+12 -11
View File
@@ -32,12 +32,6 @@ typedef enum {
TFB_GFX_NUMSCREENS
} SCREEN;
typedef enum {
TFB_SCALE_STEP, /* not really a scaler */
TFB_SCALE_NEAREST,
TFB_SCALE_TRILINEAR
} SCALE;
typedef struct tfb_palette
{
UBYTE r;
@@ -61,6 +55,7 @@ typedef struct tfb_image
HOT_SPOT NormalHs;
HOT_SPOT MipmapHs;
HOT_SPOT last_scale_hs;
int last_scale;
int last_scale_type;
TFB_Palette last_fill;
EXTENT extent;
@@ -125,11 +120,16 @@ TFB_Canvas TFB_DrawCanvas_New_ScaleTarget (TFB_Canvas canvas, TFB_Canvas oldcanv
TFB_Canvas TFB_DrawCanvas_New_RotationTarget (TFB_Canvas src, int angle);
TFB_Canvas TFB_DrawCanvas_ToScreenFormat (TFB_Canvas canvas);
BOOLEAN TFB_DrawCanvas_IsPaletted (TFB_Canvas canvas);
void TFB_DrawCanvas_Rescale_Nearest (TFB_Canvas src, TFB_Canvas dst, EXTENT size);
void TFB_DrawCanvas_Rescale_Trilinear (TFB_Canvas src, TFB_Canvas dst, TFB_Canvas mipmap, EXTENT size);
void TFB_DrawCanvas_GetScaledExtent (TFB_Canvas src_canvas, HOT_SPOT src_hs,
TFB_Canvas src_mipmap, HOT_SPOT mm_hs,
int scale, EXTENT *size, HOT_SPOT *hs);
void TFB_DrawCanvas_Rescale_Nearest (TFB_Canvas src, TFB_Canvas dst,
int scale, HOT_SPOT* src_hs, EXTENT* size, HOT_SPOT* dst_hs);
void TFB_DrawCanvas_Rescale_Bilinear (TFB_Canvas src, TFB_Canvas dst,
int scale, HOT_SPOT* src_hs, EXTENT* size, HOT_SPOT* dst_hs);
void TFB_DrawCanvas_Rescale_Trilinear (TFB_Canvas src, TFB_Canvas mipmap,
TFB_Canvas dst, int scale, HOT_SPOT* src_hs, HOT_SPOT* mm_hs,
EXTENT* size, HOT_SPOT* dst_hs);
void TFB_DrawCanvas_GetScaledExtent (TFB_Canvas src_canvas, HOT_SPOT* src_hs,
TFB_Canvas src_mipmap, HOT_SPOT* mm_hs,
int scale, int type, EXTENT *size, HOT_SPOT *hs);
void TFB_DrawCanvas_Rotate (TFB_Canvas src, TFB_Canvas dst, int angle, EXTENT size);
void TFB_DrawCanvas_GetRotatedExtent (TFB_Canvas src, int angle, EXTENT *size);
void TFB_DrawCanvas_GetExtent (TFB_Canvas canvas, EXTENT *size);
@@ -148,6 +148,7 @@ int TFB_DrawCanvas_GetTransparentIndex (TFB_Canvas canvas);
void TFB_DrawCanvas_SetTransparentIndex (TFB_Canvas canvas, int i, BOOLEAN rleaccel);
BOOLEAN TFB_DrawCanvas_GetTransparentColor (TFB_Canvas canvas, int *r, int *g, int *b);
void TFB_DrawCanvas_SetTransparentColor (TFB_Canvas canvas, int r, int g, int b, BOOLEAN rleaccel);
void TFB_DrawCanvas_CopyTransparencyInfo (TFB_Canvas src, TFB_Canvas dst);
void TFB_DrawCanvas_Initialize (void);
void TFB_DrawCanvas_GetScreenFormat (TFB_PixelFormat *fmt);
void* TFB_DrawCanvas_GetLine (TFB_Canvas canvas, int line);
+5 -3
View File
@@ -54,7 +54,8 @@ RotatePlanet (int x, int dx, int dy, COUNT scale_amt, UBYTE zoom_from,
{
STAMP s;
FRAME pFrame[2];
COUNT i, num_frames, old_scale;
COUNT i, num_frames;
int old_scale, old_mode;
RECT *rp = NULL;
CONTEXT OldContext;
PLANET_ORBIT *Orbit = &pSolarSysState->Orbit;
@@ -97,14 +98,15 @@ RotatePlanet (int x, int dx, int dy, COUNT scale_amt, UBYTE zoom_from,
RepairBackRect (rp);
s.origin.x = dx;
s.origin.y = dy;
old_scale = GetGraphicScale ();
SetGraphicScale (scale_amt);
old_mode = SetGraphicScaleMode (TFB_SCALE_BILINEAR);
old_scale = SetGraphicScale (scale_amt);
for (i = 0; i < num_frames; i++)
{
s.frame = pFrame[i];
DrawStamp (&s);
}
SetGraphicScale (old_scale);
SetGraphicScaleMode (old_mode);
UnbatchGraphics ();
SetContext (OldContext);
}
+2 -2
View File
@@ -1077,8 +1077,8 @@ GetGlobalOptions (GLOBALOPTS *opts)
opts->shield = (optWhichShield == OPT_3DO) ? OPTVAL_3DO : OPTVAL_PC;
opts->fps = (GfxFlags & TFB_GFXFLAGS_SHOWFPS) ?
OPTVAL_ENABLED : OPTVAL_DISABLED;
opts->meleezoom = (optMeleeScale == TFB_SCALE_TRILINEAR) ?
OPTVAL_3DO : OPTVAL_PC;
opts->meleezoom = (optMeleeScale == TFB_SCALE_STEP) ?
OPTVAL_PC : OPTVAL_3DO;
opts->stereo = optStereoSFX ? OPTVAL_ENABLED : OPTVAL_DISABLED;
/* These values are read in, but won't change during a run. */
opts->music = (optWhichMusic == OPT_3DO) ? OPTVAL_3DO : OPTVAL_PC;
+2 -1
View File
@@ -396,7 +396,6 @@ main (int argc, char *argv[])
return optionsResult;
}
/* TODO: Once threading is gone, these become local variables
again. In the meantime, they must be global so that
initAudio (in StarCon2Main) can see them. initAudio needed
@@ -660,6 +659,8 @@ parseOptions (int argc, char *argv[], struct options_struct *options)
options->meleeScale = TFB_SCALE_TRILINEAR;
else if (!strcmp (optarg, "step") || !strcmp (optarg, "pc"))
options->meleeScale = TFB_SCALE_STEP;
else if (!strcmp (optarg, "bilinear"))
options->meleeScale = TFB_SCALE_BILINEAR;
else
{
InvalidArgument (optarg, "--meleezoom or -b");