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:
@@ -1,4 +1,7 @@
|
|||||||
Changes towards version 0.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
|
- Added --keepaspectratio to keep correct aspect ratio when using
|
||||||
custom resolutions in OpenGL mode - Mika
|
custom resolutions in OpenGL mode - Mika
|
||||||
- Add /var/tmp as possible location for temporary files. Don't try
|
- Add /var/tmp as possible location for temporary files. Don't try
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
#include "battle.h"
|
#include "battle.h"
|
||||||
|
|
||||||
#include "controls.h"
|
#include "controls.h"
|
||||||
|
#include "options.h"
|
||||||
#include "init.h"
|
#include "init.h"
|
||||||
#include "intel.h"
|
#include "intel.h"
|
||||||
#ifdef NETPLAY
|
#ifdef NETPLAY
|
||||||
@@ -422,6 +423,9 @@ Battle (void)
|
|||||||
battle_counter[0] = CountLinks (&race_q[0]);
|
battle_counter[0] = CountLinks (&race_q[0]);
|
||||||
battle_counter[1] = CountLinks (&race_q[1]);
|
battle_counter[1] = CountLinks (&race_q[1]);
|
||||||
|
|
||||||
|
if (optMeleeScale != TFB_SCALE_STEP)
|
||||||
|
SetGraphicScaleMode (optMeleeScale);
|
||||||
|
|
||||||
setupBattleInputOrder ();
|
setupBattleInputOrder ();
|
||||||
#ifdef NETPLAY
|
#ifdef NETPLAY
|
||||||
initBattleInputBuffers ();
|
initBattleInputBuffers ();
|
||||||
|
|||||||
@@ -585,20 +585,23 @@ DoPresentation (void *pIS)
|
|||||||
int cargs;
|
int cargs;
|
||||||
int draw_what;
|
int draw_what;
|
||||||
int index, x, y, scale, angle;
|
int index, x, y, scale, angle;
|
||||||
|
int scale_mode;
|
||||||
char ImgName[16];
|
char ImgName[16];
|
||||||
int OldScale;
|
int old_scale, old_mode;
|
||||||
STAMP s;
|
STAMP s;
|
||||||
|
|
||||||
if (1 == sscanf (pStr, "%15s", ImgName)
|
if (1 == sscanf (pStr, "%15s", ImgName)
|
||||||
&& strcmp (strupr (ImgName), "SIS") == 0)
|
&& strcmp (strupr (ImgName), "SIS") == 0)
|
||||||
{
|
{
|
||||||
draw_what = PRES_DRAW_SIS;
|
draw_what = PRES_DRAW_SIS;
|
||||||
|
scale_mode = TFB_SCALE_NEAREST;
|
||||||
cargs = sscanf (pStr, "%*s %d %d %d %d",
|
cargs = sscanf (pStr, "%*s %d %d %d %d",
|
||||||
&x, &y, &scale, &angle) + 1;
|
&x, &y, &scale, &angle) + 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
draw_what = PRES_DRAW_INDEX;
|
draw_what = PRES_DRAW_INDEX;
|
||||||
|
scale_mode = TFB_SCALE_BILINEAR;
|
||||||
cargs = sscanf (pStr, "%d %d %d %d %d",
|
cargs = sscanf (pStr, "%d %d %d %d %d",
|
||||||
&index, &x, &y, &scale, &angle);
|
&index, &x, &y, &scale, &angle);
|
||||||
}
|
}
|
||||||
@@ -646,11 +649,12 @@ DoPresentation (void *pIS)
|
|||||||
s.origin.y = y;
|
s.origin.y = y;
|
||||||
if (!pPIS->Batched)
|
if (!pPIS->Batched)
|
||||||
LockMutex (GraphicsLock);
|
LockMutex (GraphicsLock);
|
||||||
OldScale = GetGraphicScale ();
|
old_mode = SetGraphicScaleMode (scale_mode);
|
||||||
SetGraphicScale (scale);
|
old_scale = SetGraphicScale (scale);
|
||||||
SetContextClipping (TRUE);
|
SetContextClipping (TRUE);
|
||||||
DrawStamp (&s);
|
DrawStamp (&s);
|
||||||
SetGraphicScale (OldScale);
|
SetGraphicScale (old_scale);
|
||||||
|
SetGraphicScaleMode (old_mode);
|
||||||
if (!pPIS->Batched)
|
if (!pPIS->Batched)
|
||||||
UnlockMutex (GraphicsLock);
|
UnlockMutex (GraphicsLock);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,6 +34,9 @@ int ScreenColorDepth;
|
|||||||
int GraphicsDriver;
|
int GraphicsDriver;
|
||||||
int TFB_DEBUG_HALT = 0;
|
int TFB_DEBUG_HALT = 0;
|
||||||
|
|
||||||
|
static int gscale = GSCALE_IDENTITY;
|
||||||
|
static int gscale_mode = TFB_SCALE_NEAREST;
|
||||||
|
|
||||||
// Status: Ignored (only used in fmv.c)
|
// Status: Ignored (only used in fmv.c)
|
||||||
void
|
void
|
||||||
SetGraphicUseOtherExtra (int other) //Could this possibly be more cryptic?!? :)
|
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);
|
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;
|
||||||
|
}
|
||||||
|
|||||||
@@ -67,15 +67,22 @@ int TFB_InitGraphics (int driver, int flags, int width, int height);
|
|||||||
void TFB_UninitGraphics (void);
|
void TFB_UninitGraphics (void);
|
||||||
void TFB_ProcessEvents (void);
|
void TFB_ProcessEvents (void);
|
||||||
|
|
||||||
// 3DO Graphics Stuff
|
|
||||||
|
|
||||||
#define GSCALE_IDENTITY 256
|
#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 LoadIntoExtraScreen (RECT *r);
|
||||||
void DrawFromExtraScreen (RECT *r);
|
void DrawFromExtraScreen (RECT *r);
|
||||||
void SetGraphicGrabOther (int grab_other);
|
void SetGraphicGrabOther (int grab_other);
|
||||||
void SetGraphicScale (int scale);
|
int SetGraphicScale (int scale);
|
||||||
int GetGraphicScale (void);
|
int GetGraphicScale (void);
|
||||||
|
int SetGraphicScaleMode (int mode /* enum SCALE */);
|
||||||
|
int GetGraphicScaleMode (void);
|
||||||
void SetGraphicUseOtherExtra (int other);
|
void SetGraphicUseOtherExtra (int other);
|
||||||
void SetTransitionSource (RECT *pRect);
|
void SetTransitionSource (RECT *pRect);
|
||||||
void ScreenTransition (int transition, RECT *pRect);
|
void ScreenTransition (int transition, RECT *pRect);
|
||||||
|
|||||||
@@ -22,20 +22,6 @@
|
|||||||
#include "graphics/tfb_draw.h"
|
#include "graphics/tfb_draw.h"
|
||||||
#include "libs/log.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
|
static void
|
||||||
read_screen (RECT *lpRect, FRAME DstFramePtr)
|
read_screen (RECT *lpRect, FRAME DstFramePtr)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -191,7 +191,6 @@ FRAME stretch_frame (FRAME FramePtr, int neww, int newh, int destroy)
|
|||||||
CREATE_FLAGS flags;
|
CREATE_FLAGS flags;
|
||||||
TFB_Image *tfbImg;
|
TFB_Image *tfbImg;
|
||||||
TFB_Canvas src, dst;
|
TFB_Canvas src, dst;
|
||||||
EXTENT ext;
|
|
||||||
|
|
||||||
flags = GetFrameParentDrawable (FramePtr)->Flags;
|
flags = GetFrameParentDrawable (FramePtr)->Flags;
|
||||||
NewFrame = CaptureDrawable (
|
NewFrame = CaptureDrawable (
|
||||||
@@ -200,9 +199,7 @@ FRAME stretch_frame (FRAME FramePtr, int neww, int newh, int destroy)
|
|||||||
LockMutex (tfbImg->mutex);
|
LockMutex (tfbImg->mutex);
|
||||||
src = tfbImg->NormalImg;
|
src = tfbImg->NormalImg;
|
||||||
dst = NewFrame->image->NormalImg;
|
dst = NewFrame->image->NormalImg;
|
||||||
ext.width = neww;
|
TFB_DrawCanvas_Rescale_Nearest (src, dst, -1, NULL, NULL, NULL);
|
||||||
ext.height = newh;
|
|
||||||
TFB_DrawCanvas_Rescale_Nearest (src, dst, ext);
|
|
||||||
UnlockMutex (tfbImg->mutex);
|
UnlockMutex (tfbImg->mutex);
|
||||||
if (destroy)
|
if (destroy)
|
||||||
DestroyDrawable (ReleaseDrawable (FramePtr));
|
DestroyDrawable (ReleaseDrawable (FramePtr));
|
||||||
|
|||||||
@@ -105,18 +105,18 @@ TFB_DrawCanvas_Image (TFB_Image *img, int x, int y, int scale,
|
|||||||
|
|
||||||
if (scale != 0 && scale != GSCALE_IDENTITY)
|
if (scale != 0 && scale != GSCALE_IDENTITY)
|
||||||
{
|
{
|
||||||
int type;
|
int type = GetGraphicScaleMode ();
|
||||||
if (optMeleeScale == TFB_SCALE_TRILINEAR && img->MipmapImg)
|
|
||||||
|
if (type == TFB_SCALE_TRILINEAR && img->MipmapImg)
|
||||||
{
|
{
|
||||||
type = TFB_SCALE_TRILINEAR;
|
|
||||||
// only set the new palette if it changed
|
// only set the new palette if it changed
|
||||||
if (((SDL_Surface *)img->MipmapImg)->format->palette
|
if (((SDL_Surface *)img->MipmapImg)->format->palette
|
||||||
&& cmap && img->colormap_version != cmap->version)
|
&& cmap && img->colormap_version != cmap->version)
|
||||||
SDL_SetColors (img->MipmapImg, (SDL_Color*)palette, 0, 256);
|
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);
|
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_Rect srcRect, targetRect, *pSrcRect;
|
||||||
SDL_Surface *surf;
|
SDL_Surface *surf;
|
||||||
int i;
|
int i;
|
||||||
SDL_Color pal[256];
|
bool force_fill = false;
|
||||||
EXTENT prevextent = img->extent;
|
|
||||||
|
|
||||||
if (img == 0)
|
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)
|
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;
|
surf = img->ScaledImg;
|
||||||
srcRect.x = 0;
|
srcRect.x = 0;
|
||||||
srcRect.y = 0;
|
srcRect.y = 0;
|
||||||
@@ -270,6 +278,14 @@ TFB_DrawCanvas_FilledImage (TFB_Image *img, int x, int y, int scale, int r, int
|
|||||||
}
|
}
|
||||||
else
|
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;
|
surf = img->NormalImg;
|
||||||
pSrcRect = NULL;
|
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)
|
if (surf->format->palette)
|
||||||
{ // set palette for fill-stamp
|
{ // 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++)
|
for (i = 0; i < 256; i++)
|
||||||
{
|
{
|
||||||
pal[i].r = r;
|
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
|
{ // fill the non-transparent parts of the image with fillcolor
|
||||||
SDL_Surface *src = img->NormalImg;
|
SDL_Surface *src = img->NormalImg;
|
||||||
SDL_Surface *newfill = img->FilledImg;
|
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
|
// prepare the filled image
|
||||||
if (!newfill)
|
if (!newfill)
|
||||||
{
|
{
|
||||||
newfill = SDL_CreateRGBSurface (SDL_SWSURFACE,
|
newfill = SDL_CreateRGBSurface (SDL_SWSURFACE,
|
||||||
src->w, src->h,
|
surf->w, surf->h,
|
||||||
surf->format->BitsPerPixel,
|
surf->format->BitsPerPixel,
|
||||||
surf->format->Rmask,
|
surf->format->Rmask,
|
||||||
surf->format->Gmask,
|
surf->format->Gmask,
|
||||||
surf->format->Bmask,
|
surf->format->Bmask,
|
||||||
surf->format->Amask);
|
surf->format->Amask);
|
||||||
force = TRUE;
|
force_fill = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (force ||
|
if (force_fill ||
|
||||||
prevextent.height != img->extent.height ||
|
|
||||||
prevextent.width != img->extent.width ||
|
|
||||||
img->last_fill.r != r ||
|
img->last_fill.r != r ||
|
||||||
img->last_fill.g != g ||
|
img->last_fill.g != g ||
|
||||||
img->last_fill.b != b)
|
img->last_fill.b != b)
|
||||||
{ // image or fillcolor changed - regenerate
|
{ // 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);
|
SDL_MapRGBA (newfill->format, r, g, b, 0), newfill);
|
||||||
// important to keep alpha=0 in fillcolor
|
// important to keep alpha=0 in fillcolor
|
||||||
// -- we process alpha ourselves
|
// -- we process alpha ourselves
|
||||||
}
|
|
||||||
|
|
||||||
// cache filled image if possible
|
// cache filled image if possible
|
||||||
img->last_fill.r = r;
|
img->last_fill.r = r;
|
||||||
img->last_fill.g = g;
|
img->last_fill.g = g;
|
||||||
img->last_fill.b = b;
|
img->last_fill.b = b;
|
||||||
img->FilledImg = newfill;
|
}
|
||||||
|
|
||||||
|
img->FilledImg = newfill;
|
||||||
surf = newfill;
|
surf = newfill;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -486,16 +513,23 @@ TFB_DrawCanvas_New_ScaleTarget (TFB_Canvas canvas, TFB_Canvas oldcanvas, int typ
|
|||||||
{
|
{
|
||||||
SDL_Surface *src = (SDL_Surface *)canvas;
|
SDL_Surface *src = (SDL_Surface *)canvas;
|
||||||
SDL_Surface *old = (SDL_Surface *)oldcanvas;
|
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 (type == TFB_SCALE_NEAREST)
|
|
||||||
{
|
|
||||||
if (old && type != last_type)
|
if (old && type != last_type)
|
||||||
{
|
{
|
||||||
TFB_DrawCanvas_Delete (old);
|
TFB_DrawCanvas_Delete (old);
|
||||||
old = NULL;
|
old = NULL;
|
||||||
}
|
}
|
||||||
if (!old)
|
if (old)
|
||||||
|
return old; /* can just reuse the old one */
|
||||||
|
|
||||||
|
if (type == TFB_SCALE_NEAREST)
|
||||||
{
|
{
|
||||||
newsurf = SDL_CreateRGBSurface (SDL_SWSURFACE, src->w,
|
newsurf = SDL_CreateRGBSurface (SDL_SWSURFACE, src->w,
|
||||||
src->h,
|
src->h,
|
||||||
@@ -504,30 +538,16 @@ TFB_DrawCanvas_New_ScaleTarget (TFB_Canvas canvas, TFB_Canvas oldcanvas, int typ
|
|||||||
src->format->Gmask,
|
src->format->Gmask,
|
||||||
src->format->Bmask,
|
src->format->Bmask,
|
||||||
src->format->Amask);
|
src->format->Amask);
|
||||||
if (src->format->palette)
|
TFB_DrawCanvas_CopyTransparencyInfo (src, newsurf);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (old && type != last_type)
|
// The scaled image may in fact be larger by 1 pixel than the source
|
||||||
{
|
// because of hotspot alignment and fractional edge pixels
|
||||||
TFB_DrawCanvas_Delete (old);
|
|
||||||
old = NULL;
|
|
||||||
}
|
|
||||||
if (!old)
|
|
||||||
{
|
|
||||||
if (SDL_Screen->format->BitsPerPixel == 32)
|
if (SDL_Screen->format->BitsPerPixel == 32)
|
||||||
newsurf = TFB_DrawCanvas_New_ForScreen (src->w, src->h, TRUE);
|
newsurf = TFB_DrawCanvas_New_ForScreen (src->w + 1, src->h + 1, TRUE);
|
||||||
else
|
else
|
||||||
newsurf = TFB_DrawCanvas_New_TrueColor (src->w, src->h, TRUE);
|
newsurf = TFB_DrawCanvas_New_TrueColor (src->w + 1, src->h + 1, TRUE);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return newsurf;
|
return newsurf;
|
||||||
@@ -556,14 +576,7 @@ TFB_DrawCanvas_New_RotationTarget (TFB_Canvas src_canvas, int angle)
|
|||||||
SDL_GetError());
|
SDL_GetError());
|
||||||
exit (EXIT_FAILURE);
|
exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
if (src->format->palette)
|
TFB_DrawCanvas_CopyTransparencyInfo (src, newsurf);
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 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
|
BOOLEAN
|
||||||
TFB_DrawCanvas_GetTransparentColor (TFB_Canvas canvas, int *r, int *g, int *b)
|
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
|
void
|
||||||
TFB_DrawCanvas_GetScaledExtent (TFB_Canvas src_canvas, HOT_SPOT src_hs,
|
TFB_DrawCanvas_GetScaledExtent (TFB_Canvas src_canvas, HOT_SPOT* src_hs,
|
||||||
TFB_Canvas src_mipmap, HOT_SPOT mm_hs,
|
TFB_Canvas src_mipmap, HOT_SPOT* mm_hs,
|
||||||
int scale, EXTENT *size, HOT_SPOT *hs)
|
int scale, int type, EXTENT *size, HOT_SPOT *hs)
|
||||||
{
|
{
|
||||||
SDL_Surface *src = (SDL_Surface *)src_canvas;
|
SDL_Surface *src = (SDL_Surface *)src_canvas;
|
||||||
|
sint32 x, y, w, h;
|
||||||
|
int frac;
|
||||||
|
|
||||||
if (!src_mipmap)
|
if (!src_mipmap)
|
||||||
{
|
{
|
||||||
size->width = src->w * scale / GSCALE_IDENTITY;
|
w = src->w * scale;
|
||||||
size->height = src->h * scale / GSCALE_IDENTITY;
|
h = src->h * scale;
|
||||||
|
x = src_hs->x * scale;
|
||||||
hs->x = src_hs.x * scale / GSCALE_IDENTITY;
|
y = src_hs->y * scale;
|
||||||
hs->y = src_hs.y * scale / GSCALE_IDENTITY;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// interpolates extents between src and mipmap to get smoother
|
// interpolates extents between src and mipmap to get smoother
|
||||||
// transition when surface changes
|
// transition when surface changes
|
||||||
SDL_Surface *mipmap = (SDL_Surface *)src_mipmap;
|
SDL_Surface *mipmap = (SDL_Surface *)src_mipmap;
|
||||||
|
int ratio = scale * 2 - GSCALE_IDENTITY;
|
||||||
|
|
||||||
float ratio = (scale / (float)GSCALE_IDENTITY) * 2.0f - 1.0f;
|
assert (scale >= GSCALE_IDENTITY / 2);
|
||||||
if (ratio < 0.0f)
|
|
||||||
ratio = 0.0f;
|
|
||||||
else if (ratio > 1.0f)
|
|
||||||
ratio = 1.0f;
|
|
||||||
|
|
||||||
size->width = (int)((src->w - mipmap->w) * ratio + mipmap->w + 0.5);
|
w = mipmap->w * GSCALE_IDENTITY + (src->w - mipmap->w) * ratio;
|
||||||
size->height = (int)((src->h - mipmap->h) * ratio + mipmap->h + 0.5);
|
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);
|
// Seems it is better to use mipmap hotspot because some
|
||||||
hs->y = (int)((src_hs.y - mm_hs.y) * ratio + mm_hs.y + 0.5);
|
// 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)
|
if (!size->width && src->w)
|
||||||
size->width = 1;
|
size->width = 1;
|
||||||
if (!size->height && src->h)
|
if (!size->height && src->h)
|
||||||
@@ -756,57 +817,48 @@ TFB_DrawCanvas_GetExtent (TFB_Canvas canvas, EXTENT *size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
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 *src = (SDL_Surface *)src_canvas;
|
||||||
SDL_Surface *dst = (SDL_Surface *)dest_canvas;
|
SDL_Surface *dst = (SDL_Surface *)dst_canvas;
|
||||||
int x, y, sx, sy, *csax, *csay, csx, csy;
|
int x, y;
|
||||||
int saspace[NNS_MAX_DIMS];
|
int fsx = 0, fsy = 0; // source fractional dx and dy increments
|
||||||
int *sax, *say;
|
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"
|
TFB_DrawCanvas_GetScaledExtent (src, src_hs, NULL, NULL, scale,
|
||||||
" an image to unreasonable size! Failing.");
|
TFB_SCALE_NEAREST, size, dst_hs);
|
||||||
return;
|
|
||||||
|
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"
|
" image to size %d %d when dest_canvas has only"
|
||||||
" dimensions of %d %d! Failing.",
|
" dimensions of %d %d! Failing.",
|
||||||
size.width, size.height, dst->w, dst->h);
|
w, h, dst->w, dst->h);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
sx = sy = 0;
|
if (w > 1)
|
||||||
if (size.width > 1)
|
fsx = ((src->w - 1) << 16) / (w - 1);
|
||||||
sx = ((src->w - 1) << 16) / (size.width - 1);
|
if (h > 1)
|
||||||
if (size.height > 1)
|
fsy = ((src->h - 1) << 16) / (h - 1);
|
||||||
sy = ((src->h - 1) << 16) / (size.height - 1);
|
// We start with a value in 0..0.5 range to shift the bigger
|
||||||
|
// jumps towards the center of the image
|
||||||
sax = saspace;
|
ssx = 0x6000;
|
||||||
say = saspace + size.width;
|
ssy = 0x6000;
|
||||||
/*
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
SDL_LockSurface (src);
|
SDL_LockSurface (src);
|
||||||
SDL_LockSurface (dst);
|
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)
|
if (src->format->BytesPerPixel == 1 && dst->format->BytesPerPixel == 1)
|
||||||
{
|
{
|
||||||
Uint8 *sp, *csp, *dp, *cdp;
|
Uint8 *sp, *csp, *dp, *cdp;
|
||||||
|
int sx, sy; // source fractional x and y positions
|
||||||
|
|
||||||
sp = csp = (Uint8 *) src->pixels;
|
sp = csp = (Uint8 *) src->pixels;
|
||||||
dp = cdp = (Uint8 *) dst->pixels;
|
dp = cdp = (Uint8 *) dst->pixels;
|
||||||
|
|
||||||
csay = say;
|
for (y = 0, sy = ssy; y < h; ++y)
|
||||||
for (y = 0; y < size.height; ++y) {
|
{
|
||||||
csp += (*csay) * src->pitch;
|
csp += (sy >> 16) * src->pitch;
|
||||||
sp = csp;
|
sp = csp;
|
||||||
dp = cdp;
|
dp = cdp;
|
||||||
csax = sax;
|
for (x = 0, sx = ssx; x < w; ++x)
|
||||||
for (x = 0; x < size.width; ++x) {
|
{
|
||||||
sp += *csax;
|
sp += (sx >> 16);
|
||||||
*dp = *sp;
|
*dp = *sp;
|
||||||
++csax;
|
sx &= 0xffff;
|
||||||
|
sx += fsx;
|
||||||
++dp;
|
++dp;
|
||||||
}
|
}
|
||||||
++csay;
|
sy &= 0xffff;
|
||||||
|
sy += fsy;
|
||||||
cdp += dst->pitch;
|
cdp += dst->pitch;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (src->format->BytesPerPixel == 4 && dst->format->BytesPerPixel == 4)
|
else if (src->format->BytesPerPixel == 4 && dst->format->BytesPerPixel == 4)
|
||||||
{
|
{
|
||||||
Uint32 *sp, *csp, *dp, *cdp;
|
Uint32 *sp, *csp, *dp, *cdp;
|
||||||
|
int sx, sy; // source fractional x and y positions
|
||||||
int sgap, dgap;
|
int sgap, dgap;
|
||||||
|
|
||||||
sgap = src->pitch >> 2;
|
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;
|
sp = csp = (Uint32 *) src->pixels;
|
||||||
dp = cdp = (Uint32 *) dst->pixels;
|
dp = cdp = (Uint32 *) dst->pixels;
|
||||||
|
|
||||||
csay = say;
|
for (y = 0, sy = ssy; y < h; ++y)
|
||||||
for (y = 0; y < size.height; ++y) {
|
{
|
||||||
csp += (*csay) * sgap;
|
csp += (sy >> 16) * sgap;
|
||||||
sp = csp;
|
sp = csp;
|
||||||
dp = cdp;
|
dp = cdp;
|
||||||
csax = sax;
|
for (x = 0, sx = ssx; x < w; ++x)
|
||||||
for (x = 0; x < size.width; ++x) {
|
{
|
||||||
sp += *csax;
|
sp += (sx >> 16);
|
||||||
*dp = *sp;
|
*dp = *sp;
|
||||||
++csax;
|
sx &= 0xffff;
|
||||||
|
sx += fsx;
|
||||||
++dp;
|
++dp;
|
||||||
}
|
}
|
||||||
++csay;
|
sy &= 0xffff;
|
||||||
|
sy += fsy;
|
||||||
cdp += dgap;
|
cdp += dgap;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -913,7 +971,7 @@ blend_ratio_2 (Uint8 c1, Uint8 c2, int ratio)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline Uint32
|
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)
|
Uint32 mask, Uint32 key)
|
||||||
{
|
{
|
||||||
pixel_t p;
|
pixel_t p;
|
||||||
@@ -956,29 +1014,41 @@ tri_get_pixel (void* ppix, SDL_PixelFormat *fmt, SDL_Color *pal,
|
|||||||
return p.value;
|
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
|
void
|
||||||
TFB_DrawCanvas_Rescale_Trilinear (TFB_Canvas src_canvas,
|
TFB_DrawCanvas_Rescale_Trilinear (TFB_Canvas src_canvas, TFB_Canvas src_mipmap,
|
||||||
TFB_Canvas dest_canvas, TFB_Canvas src_mipmap, EXTENT size)
|
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 *src = (SDL_Surface *)src_canvas;
|
||||||
SDL_Surface *dst = (SDL_Surface *)dest_canvas;
|
SDL_Surface *dst = (SDL_Surface *)dst_canvas;
|
||||||
SDL_Surface *mipmap = (SDL_Surface *)src_mipmap;
|
SDL_Surface *mm = (SDL_Surface *)src_mipmap;
|
||||||
SDL_PixelFormat *srcfmt = src->format;
|
SDL_PixelFormat *srcfmt = src->format;
|
||||||
SDL_PixelFormat *mmfmt = mipmap->format;
|
SDL_PixelFormat *mmfmt = mm->format;
|
||||||
SDL_PixelFormat *dstfmt = dst->format;
|
SDL_PixelFormat *dstfmt = dst->format;
|
||||||
SDL_Color *srcpal = srcfmt->palette? srcfmt->palette->colors : 0;
|
SDL_Color *srcpal = srcfmt->palette? srcfmt->palette->colors : 0;
|
||||||
SDL_Color *mmpal = mmfmt->palette ? mmfmt->palette->colors : 0;
|
SDL_Color *mmpal = mmfmt->palette ? mmfmt->palette->colors : 0;
|
||||||
const int sbpp = srcfmt->BytesPerPixel;
|
const int sbpp = srcfmt->BytesPerPixel;
|
||||||
const int mmbpp = mmfmt->BytesPerPixel;
|
const int mmbpp = mmfmt->BytesPerPixel;
|
||||||
const int slen = src->pitch;
|
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 dst_has_alpha = (dstfmt->Amask != 0);
|
||||||
const int transparent = (dst->flags & SDL_SRCCOLORKEY) ?
|
const int transparent = (dst->flags & SDL_SRCCOLORKEY) ?
|
||||||
dstfmt->colorkey : 0;
|
dstfmt->colorkey : 0;
|
||||||
const int w = size.width, h = size.height;
|
|
||||||
const int alpha_threshold = dst_has_alpha ? 0 : 127;
|
const int alpha_threshold = dst_has_alpha ? 0 : 127;
|
||||||
// src v. mipmap importance factor
|
// src v. mipmap importance factor
|
||||||
int ratio;
|
int ratio = scale * 2 - GSCALE_IDENTITY;
|
||||||
// source masks and keys
|
// source masks and keys
|
||||||
Uint32 mk0 = 0, ck0 = ~0, mk1 = 0, ck1 = ~0;
|
Uint32 mk0 = 0, ck0 = ~0, mk1 = 0, ck1 = ~0;
|
||||||
// source fractional x and y positions
|
// 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;
|
int fsx0 = 0, fsy0 = 0, fsx1 = 0, fsy1 = 0;
|
||||||
// source fractional x and y starting points
|
// source fractional x and y starting points
|
||||||
int ssx0 = 0, ssy0 = 0, ssx1 = 0, ssy1 = 0;
|
int ssx0 = 0, ssy0 = 0, ssx1 = 0, ssy1 = 0;
|
||||||
int x, y;
|
int x, y, w, h;
|
||||||
|
|
||||||
|
if (scale > 0)
|
||||||
|
{
|
||||||
|
int fw, fh;
|
||||||
|
|
||||||
|
// Use (scale / GSCALE_IDENTITY) sizing factor
|
||||||
|
TFB_DrawCanvas_GetScaledExtent (src, src_hs, mm, mm_hs, scale,
|
||||||
|
TFB_SCALE_TRILINEAR, size, dst_hs);
|
||||||
|
|
||||||
|
w = size->width;
|
||||||
|
h = size->height;
|
||||||
|
|
||||||
|
fw = mm->w * GSCALE_IDENTITY + (src->w - mm->w) * ratio;
|
||||||
|
fh = mm->h * GSCALE_IDENTITY + (src->h - mm->h) * ratio;
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
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;
|
fsx0 = (src->w << 16) / w;
|
||||||
fsy0 = (src->h << 16) / h;
|
fsy0 = (src->h << 16) / h;
|
||||||
|
|
||||||
if (w > 1)
|
fsx1 = (mm->w << 16) / w;
|
||||||
fsx1 = ((mipmap->w - 1) << 16) / (w - 1);
|
fsy1 = (mm->h << 16) / h;
|
||||||
if (h > 1)
|
|
||||||
fsy1 = ((mipmap->h - 1) << 16) / (h - 1);
|
|
||||||
|
|
||||||
// give equal importance to both edges
|
// give equal importance to both edges
|
||||||
ssx0 = (((src->w - 1) << 16) - fsx0 * (w - 1)) >> 1;
|
ssx0 = (((src->w - 1) << 16) - fsx0 * (w - 1)) >> 1;
|
||||||
ssy0 = (((src->h - 1) << 16) - fsy0 * (h - 1)) >> 1;
|
ssy0 = (((src->h - 1) << 16) - fsy0 * (h - 1)) >> 1;
|
||||||
|
|
||||||
ssx1 = (((mipmap->w - 1) << 16) - fsx1 * (w - 1)) >> 1;
|
ssx1 = (((mm->w - 1) << 16) - fsx1 * (w - 1)) >> 1;
|
||||||
ssy1 = (((mipmap->h - 1) << 16) - fsy1 * (h - 1)) >> 1;
|
ssy1 = (((mm->h - 1) << 16) - fsy1 * (h - 1)) >> 1;
|
||||||
|
}
|
||||||
|
|
||||||
// src v. mipmap importance factor
|
if (w > dst->w || h > dst->h)
|
||||||
ratio = (w << 9) / src->w - 256;
|
|
||||||
if (ratio < 0)
|
|
||||||
ratio = 0;
|
|
||||||
if (ratio > 256)
|
|
||||||
ratio = 256;
|
|
||||||
|
|
||||||
if (size.width > dst->w || size.height > dst->h)
|
|
||||||
{
|
{
|
||||||
log_add (log_Warning, "TFB_DrawCanvas_Rescale_Trilinear: "
|
log_add (log_Warning, "TFB_DrawCanvas_Rescale_Trilinear: "
|
||||||
"Tried to scale image to size %d %d when dest_canvas"
|
"Tried to scale image to size %d %d when dest_canvas"
|
||||||
" has only dimensions of %d %d! Failing.",
|
" has only dimensions of %d %d! Failing.",
|
||||||
size.width, size.height, dst->w, dst->h);
|
w, h, dst->w, dst->h);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1048,7 +1149,7 @@ TFB_DrawCanvas_Rescale_Trilinear (TFB_Canvas src_canvas,
|
|||||||
mk1 = mmfmt->Amask;
|
mk1 = mmfmt->Amask;
|
||||||
ck1 = 0;
|
ck1 = 0;
|
||||||
}
|
}
|
||||||
else if (mipmap->flags & SDL_SRCCOLORKEY)
|
else if (mm->flags & SDL_SRCCOLORKEY)
|
||||||
{ // colorkey transparency
|
{ // colorkey transparency
|
||||||
mk1 = ~mmfmt->Amask;
|
mk1 = ~mmfmt->Amask;
|
||||||
ck1 = mmfmt->colorkey & mk1;
|
ck1 = mmfmt->colorkey & mk1;
|
||||||
@@ -1056,15 +1157,17 @@ TFB_DrawCanvas_Rescale_Trilinear (TFB_Canvas src_canvas,
|
|||||||
|
|
||||||
SDL_LockSurface(src);
|
SDL_LockSurface(src);
|
||||||
SDL_LockSurface(dst);
|
SDL_LockSurface(dst);
|
||||||
SDL_LockSurface(mipmap);
|
SDL_LockSurface(mm);
|
||||||
|
|
||||||
for (y = 0, sy0 = ssy0, sy1 = ssy1;
|
for (y = 0, sy0 = ssy0, sy1 = ssy1;
|
||||||
y < h;
|
y < h;
|
||||||
++y, sy0 += fsy0, sy1 += fsy1)
|
++y, sy0 += fsy0, sy1 += fsy1)
|
||||||
{
|
{
|
||||||
Uint32 *dst_p = (Uint32 *) ((Uint8*)dst->pixels + y * dst->pitch);
|
Uint32 *dst_p = (Uint32 *) ((Uint8*)dst->pixels + y * dst->pitch);
|
||||||
Uint8 *src_a0 = (Uint8*)src->pixels + (sy0 >> 16) * slen;
|
const int py0 = (sy0 >> 16);
|
||||||
Uint8 *src_a1 = (Uint8*)mipmap->pixels + (sy1 >> 16) * mmlen;
|
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
|
// retrieve the fractional portions of y
|
||||||
const Uint8 v0 = (sy0 >> 8) & 0xff;
|
const Uint8 v0 = (sy0 >> 8) & 0xff;
|
||||||
const Uint8 v1 = (sy1 >> 8) & 0xff;
|
const Uint8 v1 = (sy1 >> 8) & 0xff;
|
||||||
@@ -1074,8 +1177,10 @@ TFB_DrawCanvas_Rescale_Trilinear (TFB_Canvas src_canvas,
|
|||||||
x < w;
|
x < w;
|
||||||
++x, ++dst_p, sx0 += fsx0, sx1 += fsx1)
|
++x, ++dst_p, sx0 += fsx0, sx1 += fsx1)
|
||||||
{
|
{
|
||||||
Uint8 *src_p0 = src_a0 + (sx0 >> 16) * sbpp;
|
const int px0 = (sx0 >> 16);
|
||||||
Uint8 *src_p1 = src_a1 + (sx1 >> 16) * mmbpp;
|
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
|
// retrieve the fractional portions of x
|
||||||
const Uint8 u0 = (sx0 >> 8) & 0xff;
|
const Uint8 u0 = (sx0 >> 8) & 0xff;
|
||||||
const Uint8 u1 = (sx1 >> 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[1] = btable[u0][255 - v0];
|
||||||
w0[2] = btable[255 - u0][v0];
|
w0[2] = btable[255 - u0][v0];
|
||||||
w0[3] = btable[u0][v0];
|
w0[3] = btable[u0][v0];
|
||||||
|
|
||||||
w1[0] = btable[255 - u1][255 - v1];
|
w1[0] = btable[255 - u1][255 - v1];
|
||||||
w1[1] = btable[u1][255 - v1];
|
w1[1] = btable[u1][255 - v1];
|
||||||
w1[2] = btable[255 - u1][v1];
|
w1[2] = btable[255 - u1][v1];
|
||||||
w1[3] = btable[u1][v1];
|
w1[3] = btable[u1][v1];
|
||||||
|
|
||||||
// collect interesting pixels from src image
|
// Collect interesting pixels from src image
|
||||||
p0[0].value = tri_get_pixel (src_p0, srcfmt, srcpal, mk0, ck0);
|
// 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)
|
||||||
|
{
|
||||||
|
Uint8 *src_p = src_a0 + px0 * sbpp;
|
||||||
|
|
||||||
if ((sx0 >> 16) <= src->w - 2)
|
p0[0].value = scale_read_pixel (src_p, srcfmt,
|
||||||
{
|
srcpal, mk0, ck0);
|
||||||
p0[1].value = tri_get_pixel (src_p0 + sbpp,
|
p0[1].value = scale_read_pixel (src_p + sbpp, srcfmt,
|
||||||
srcfmt, srcpal, mk0, ck0);
|
srcpal, mk0, ck0);
|
||||||
|
p0[2].value = scale_read_pixel (src_p + slen, srcfmt,
|
||||||
if ((sy0 >> 16) <= src->h - 2)
|
srcpal, mk0, ck0);
|
||||||
{
|
p0[3].value = scale_read_pixel (src_p + sbpp + slen, srcfmt,
|
||||||
p0[2].value = tri_get_pixel (src_p0 + slen,
|
srcpal, mk0, ck0);
|
||||||
srcfmt, srcpal, mk0, ck0);
|
|
||||||
p0[3].value = tri_get_pixel (src_p0 + slen + sbpp,
|
|
||||||
srcfmt, srcpal, mk0, ck0);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
p0[2].value = p0[0].value;
|
p0[0].value = scale_get_pixel (src, mk0, ck0, px0, py0);
|
||||||
p0[3].value = p0[1].value;
|
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,
|
||||||
else
|
px0 + 1, py0 + 1);
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// collect interesting pixels from mipmap image
|
// Collect interesting pixels from mipmap image
|
||||||
p1[0].value = tri_get_pixel (src_p1, mmfmt, mmpal, mk1, ck1);
|
if (px1 >= 0 && px1 + 1 < mm->w && py1 >= 0 && py1 + 1 < mm->h)
|
||||||
|
{
|
||||||
|
Uint8 *mm_p = src_a1 + px1 * mmbpp;
|
||||||
|
|
||||||
if ((sx1 >> 16) <= mipmap->w - 2)
|
p1[0].value = scale_read_pixel (mm_p, mmfmt,
|
||||||
{
|
mmpal, mk1, ck1);
|
||||||
p1[1].value = tri_get_pixel (src_p1 + mmbpp,
|
p1[1].value = scale_read_pixel (mm_p + mmbpp, mmfmt,
|
||||||
mmfmt, mmpal, mk1, ck1);
|
mmpal, mk1, ck1);
|
||||||
|
p1[2].value = scale_read_pixel (mm_p + mmlen, mmfmt,
|
||||||
if ((sy1 >> 16) <= mipmap->h - 2)
|
mmpal, mk1, ck1);
|
||||||
{
|
p1[3].value = scale_read_pixel (mm_p + mmbpp + mmlen, mmfmt,
|
||||||
p1[2].value = tri_get_pixel (src_p1 + mmlen,
|
mmpal, mk1, ck1);
|
||||||
mmfmt, mmpal, mk1, ck1);
|
|
||||||
p1[3].value = tri_get_pixel (src_p1 + mmlen + mmbpp,
|
|
||||||
mmfmt, mmpal, mk1, ck1);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
p1[2].value = p1[0].value;
|
p1[0].value = scale_get_pixel (mm, mk1, ck1, px1, py1);
|
||||||
p1[3].value = p1[1].value;
|
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,
|
||||||
else
|
px1 + 1, py1 + 1);
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
p0[4].c.a = dot_product_8_4 (p0, 3, w0);
|
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.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);
|
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 =
|
*dst_p =
|
||||||
(p0[4].c.r << dstfmt->Rshift) |
|
(p0[4].c.r << dstfmt->Rshift) |
|
||||||
(p0[4].c.g << dstfmt->Gshift) |
|
(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(dst);
|
||||||
SDL_UnlockSurface(src);
|
SDL_UnlockSurface(src);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -292,6 +292,7 @@ TFB_DrawImage_New (TFB_Canvas canvas)
|
|||||||
img->MipmapHs = NullHs;
|
img->MipmapHs = NullHs;
|
||||||
img->last_scale_hs = NullHs;
|
img->last_scale_hs = NullHs;
|
||||||
img->last_scale_type = -1;
|
img->last_scale_type = -1;
|
||||||
|
img->last_scale = 0;
|
||||||
TFB_DrawCanvas_GetExtent (canvas, &img->extent);
|
TFB_DrawCanvas_GetExtent (canvas, &img->extent);
|
||||||
|
|
||||||
img->Palette = TFB_DrawCanvas_ExtractPalette (canvas);
|
img->Palette = TFB_DrawCanvas_ExtractPalette (canvas);
|
||||||
@@ -322,6 +323,7 @@ TFB_DrawImage_CreateForScreen (int w, int h, BOOLEAN withalpha)
|
|||||||
img->MipmapHs = NullHs;
|
img->MipmapHs = NullHs;
|
||||||
img->last_scale_hs = NullHs;
|
img->last_scale_hs = NullHs;
|
||||||
img->last_scale_type = -1;
|
img->last_scale_type = -1;
|
||||||
|
img->last_scale = 0;
|
||||||
img->Palette = NULL;
|
img->Palette = NULL;
|
||||||
img->extent.width = w;
|
img->extent.width = w;
|
||||||
img->extent.height = h;
|
img->extent.height = h;
|
||||||
@@ -389,28 +391,29 @@ TFB_DrawImage_Delete (TFB_Image *image)
|
|||||||
void
|
void
|
||||||
TFB_DrawImage_FixScaling (TFB_Image *image, int target, int type)
|
TFB_DrawImage_FixScaling (TFB_Image *image, int target, int type)
|
||||||
{
|
{
|
||||||
EXTENT old = image->extent;
|
if (image->dirty || !image->ScaledImg ||
|
||||||
HOT_SPOT oldhs = image->last_scale_hs;
|
target != image->last_scale ||
|
||||||
TFB_DrawCanvas_GetScaledExtent (image->NormalImg, image->NormalHs,
|
type != image->last_scale_type)
|
||||||
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))
|
|
||||||
{
|
{
|
||||||
image->dirty = FALSE;
|
image->dirty = FALSE;
|
||||||
image->ScaledImg = TFB_DrawCanvas_New_ScaleTarget (image->NormalImg,
|
image->ScaledImg = TFB_DrawCanvas_New_ScaleTarget (image->NormalImg,
|
||||||
image->ScaledImg, type, image->last_scale_type);
|
image->ScaledImg, type, image->last_scale_type);
|
||||||
image->last_scale_type = type;
|
|
||||||
|
|
||||||
if (type == TFB_SCALE_NEAREST)
|
if (type == TFB_SCALE_NEAREST)
|
||||||
TFB_DrawCanvas_Rescale_Nearest (image->NormalImg,
|
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
|
else
|
||||||
TFB_DrawCanvas_Rescale_Trilinear (image->NormalImg,
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,12 +32,6 @@ typedef enum {
|
|||||||
TFB_GFX_NUMSCREENS
|
TFB_GFX_NUMSCREENS
|
||||||
} SCREEN;
|
} SCREEN;
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
TFB_SCALE_STEP, /* not really a scaler */
|
|
||||||
TFB_SCALE_NEAREST,
|
|
||||||
TFB_SCALE_TRILINEAR
|
|
||||||
} SCALE;
|
|
||||||
|
|
||||||
typedef struct tfb_palette
|
typedef struct tfb_palette
|
||||||
{
|
{
|
||||||
UBYTE r;
|
UBYTE r;
|
||||||
@@ -61,6 +55,7 @@ typedef struct tfb_image
|
|||||||
HOT_SPOT NormalHs;
|
HOT_SPOT NormalHs;
|
||||||
HOT_SPOT MipmapHs;
|
HOT_SPOT MipmapHs;
|
||||||
HOT_SPOT last_scale_hs;
|
HOT_SPOT last_scale_hs;
|
||||||
|
int last_scale;
|
||||||
int last_scale_type;
|
int last_scale_type;
|
||||||
TFB_Palette last_fill;
|
TFB_Palette last_fill;
|
||||||
EXTENT extent;
|
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_New_RotationTarget (TFB_Canvas src, int angle);
|
||||||
TFB_Canvas TFB_DrawCanvas_ToScreenFormat (TFB_Canvas canvas);
|
TFB_Canvas TFB_DrawCanvas_ToScreenFormat (TFB_Canvas canvas);
|
||||||
BOOLEAN TFB_DrawCanvas_IsPaletted (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_Nearest (TFB_Canvas src, TFB_Canvas dst,
|
||||||
void TFB_DrawCanvas_Rescale_Trilinear (TFB_Canvas src, TFB_Canvas dst, TFB_Canvas mipmap, EXTENT size);
|
int scale, HOT_SPOT* src_hs, EXTENT* size, HOT_SPOT* dst_hs);
|
||||||
void TFB_DrawCanvas_GetScaledExtent (TFB_Canvas src_canvas, HOT_SPOT src_hs,
|
void TFB_DrawCanvas_Rescale_Bilinear (TFB_Canvas src, TFB_Canvas dst,
|
||||||
TFB_Canvas src_mipmap, HOT_SPOT mm_hs,
|
int scale, HOT_SPOT* src_hs, EXTENT* size, HOT_SPOT* dst_hs);
|
||||||
int scale, EXTENT *size, HOT_SPOT *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_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_GetRotatedExtent (TFB_Canvas src, int angle, EXTENT *size);
|
||||||
void TFB_DrawCanvas_GetExtent (TFB_Canvas canvas, 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);
|
void TFB_DrawCanvas_SetTransparentIndex (TFB_Canvas canvas, int i, BOOLEAN rleaccel);
|
||||||
BOOLEAN TFB_DrawCanvas_GetTransparentColor (TFB_Canvas canvas, int *r, int *g, int *b);
|
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_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_Initialize (void);
|
||||||
void TFB_DrawCanvas_GetScreenFormat (TFB_PixelFormat *fmt);
|
void TFB_DrawCanvas_GetScreenFormat (TFB_PixelFormat *fmt);
|
||||||
void* TFB_DrawCanvas_GetLine (TFB_Canvas canvas, int line);
|
void* TFB_DrawCanvas_GetLine (TFB_Canvas canvas, int line);
|
||||||
|
|||||||
@@ -54,7 +54,8 @@ RotatePlanet (int x, int dx, int dy, COUNT scale_amt, UBYTE zoom_from,
|
|||||||
{
|
{
|
||||||
STAMP s;
|
STAMP s;
|
||||||
FRAME pFrame[2];
|
FRAME pFrame[2];
|
||||||
COUNT i, num_frames, old_scale;
|
COUNT i, num_frames;
|
||||||
|
int old_scale, old_mode;
|
||||||
RECT *rp = NULL;
|
RECT *rp = NULL;
|
||||||
CONTEXT OldContext;
|
CONTEXT OldContext;
|
||||||
PLANET_ORBIT *Orbit = &pSolarSysState->Orbit;
|
PLANET_ORBIT *Orbit = &pSolarSysState->Orbit;
|
||||||
@@ -97,14 +98,15 @@ RotatePlanet (int x, int dx, int dy, COUNT scale_amt, UBYTE zoom_from,
|
|||||||
RepairBackRect (rp);
|
RepairBackRect (rp);
|
||||||
s.origin.x = dx;
|
s.origin.x = dx;
|
||||||
s.origin.y = dy;
|
s.origin.y = dy;
|
||||||
old_scale = GetGraphicScale ();
|
old_mode = SetGraphicScaleMode (TFB_SCALE_BILINEAR);
|
||||||
SetGraphicScale (scale_amt);
|
old_scale = SetGraphicScale (scale_amt);
|
||||||
for (i = 0; i < num_frames; i++)
|
for (i = 0; i < num_frames; i++)
|
||||||
{
|
{
|
||||||
s.frame = pFrame[i];
|
s.frame = pFrame[i];
|
||||||
DrawStamp (&s);
|
DrawStamp (&s);
|
||||||
}
|
}
|
||||||
SetGraphicScale (old_scale);
|
SetGraphicScale (old_scale);
|
||||||
|
SetGraphicScaleMode (old_mode);
|
||||||
UnbatchGraphics ();
|
UnbatchGraphics ();
|
||||||
SetContext (OldContext);
|
SetContext (OldContext);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1077,8 +1077,8 @@ GetGlobalOptions (GLOBALOPTS *opts)
|
|||||||
opts->shield = (optWhichShield == OPT_3DO) ? OPTVAL_3DO : OPTVAL_PC;
|
opts->shield = (optWhichShield == OPT_3DO) ? OPTVAL_3DO : OPTVAL_PC;
|
||||||
opts->fps = (GfxFlags & TFB_GFXFLAGS_SHOWFPS) ?
|
opts->fps = (GfxFlags & TFB_GFXFLAGS_SHOWFPS) ?
|
||||||
OPTVAL_ENABLED : OPTVAL_DISABLED;
|
OPTVAL_ENABLED : OPTVAL_DISABLED;
|
||||||
opts->meleezoom = (optMeleeScale == TFB_SCALE_TRILINEAR) ?
|
opts->meleezoom = (optMeleeScale == TFB_SCALE_STEP) ?
|
||||||
OPTVAL_3DO : OPTVAL_PC;
|
OPTVAL_PC : OPTVAL_3DO;
|
||||||
opts->stereo = optStereoSFX ? OPTVAL_ENABLED : OPTVAL_DISABLED;
|
opts->stereo = optStereoSFX ? OPTVAL_ENABLED : OPTVAL_DISABLED;
|
||||||
/* These values are read in, but won't change during a run. */
|
/* These values are read in, but won't change during a run. */
|
||||||
opts->music = (optWhichMusic == OPT_3DO) ? OPTVAL_3DO : OPTVAL_PC;
|
opts->music = (optWhichMusic == OPT_3DO) ? OPTVAL_3DO : OPTVAL_PC;
|
||||||
|
|||||||
+2
-1
@@ -396,7 +396,6 @@ main (int argc, char *argv[])
|
|||||||
return optionsResult;
|
return optionsResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* TODO: Once threading is gone, these become local variables
|
/* TODO: Once threading is gone, these become local variables
|
||||||
again. In the meantime, they must be global so that
|
again. In the meantime, they must be global so that
|
||||||
initAudio (in StarCon2Main) can see them. initAudio needed
|
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;
|
options->meleeScale = TFB_SCALE_TRILINEAR;
|
||||||
else if (!strcmp (optarg, "step") || !strcmp (optarg, "pc"))
|
else if (!strcmp (optarg, "step") || !strcmp (optarg, "pc"))
|
||||||
options->meleeScale = TFB_SCALE_STEP;
|
options->meleeScale = TFB_SCALE_STEP;
|
||||||
|
else if (!strcmp (optarg, "bilinear"))
|
||||||
|
options->meleeScale = TFB_SCALE_BILINEAR;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
InvalidArgument (optarg, "--meleezoom or -b");
|
InvalidArgument (optarg, "--meleezoom or -b");
|
||||||
|
|||||||
Reference in New Issue
Block a user