Gfxlib cleanup: move ani and font loading functions out of SDL domain; SDL-specific bits split off into TFB_Canvas functions
git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@3469 8092fc87-c524-0410-9efc-e669fe64eaf9
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
uqm_SUBDIRS="sdl"
|
||||
uqm_CFILES="boxint.c clipline.c cmap.c context.c drawable.c filegfx.c
|
||||
bbox.c dcqueue.c
|
||||
bbox.c dcqueue.c gfxload.c
|
||||
font.c frame.c gfx_common.c intersec.c loaddisp.c
|
||||
pixmap.c resgfx.c tfb_draw.c tfb_prim.c widgets.c"
|
||||
|
||||
@@ -0,0 +1,603 @@
|
||||
//Copyright Paul Reiche, Fred Ford. 1992-2002
|
||||
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "options.h"
|
||||
#include "port.h"
|
||||
#include "libs/uio.h"
|
||||
#include "libs/reslib.h"
|
||||
// for _cur_resfile_name
|
||||
#include "libs/log.h"
|
||||
#include "libs/memlib.h"
|
||||
#include "libs/graphics/tfb_draw.h"
|
||||
#include "libs/graphics/drawable.h"
|
||||
#include "libs/graphics/font.h"
|
||||
|
||||
|
||||
typedef struct anidata
|
||||
{
|
||||
int transparent_color;
|
||||
int colormap_index;
|
||||
int hotspot_x;
|
||||
int hotspot_y;
|
||||
} AniData;
|
||||
|
||||
extern uio_Repository *repository;
|
||||
static uio_AutoMount *autoMount[] = { NULL };
|
||||
|
||||
static void
|
||||
process_image (FRAME FramePtr, TFB_Canvas img[], AniData *ani, int cel_ct)
|
||||
{
|
||||
TFB_Image *tfbimg;
|
||||
int hx, hy;
|
||||
|
||||
FramePtr->Type = ROM_DRAWABLE;
|
||||
FramePtr->Index = cel_ct;
|
||||
|
||||
// handle transparency cases
|
||||
if (TFB_DrawCanvas_IsPaletted (img[cel_ct]))
|
||||
{ // indexed color image
|
||||
if (ani[cel_ct].transparent_color >= 0)
|
||||
{
|
||||
TFB_DrawCanvas_SetTransparentIndex (img[cel_ct],
|
||||
ani[cel_ct].transparent_color, FALSE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // special transparency cases for truecolor images
|
||||
if (ani[cel_ct].transparent_color == 0)
|
||||
{ // make RGB=0,0,0 transparent
|
||||
Color color = {0, 0, 0, 0};
|
||||
TFB_DrawCanvas_SetTransparentColor (img[cel_ct], color, FALSE);
|
||||
}
|
||||
}
|
||||
if (ani[cel_ct].transparent_color == -1)
|
||||
{ // enforce -1 to mean 'no transparency'
|
||||
TFB_DrawCanvas_SetTransparentIndex (img[cel_ct], -1, FALSE);
|
||||
// set transparent_color == -2 to use PNG tRNS transparency
|
||||
}
|
||||
|
||||
hx = ani[cel_ct].hotspot_x;
|
||||
hy = ani[cel_ct].hotspot_y;
|
||||
|
||||
FramePtr->image = TFB_DrawImage_New (img[cel_ct]);
|
||||
|
||||
tfbimg = FramePtr->image;
|
||||
tfbimg->colormap_index = ani[cel_ct].colormap_index;
|
||||
img[cel_ct] = tfbimg->NormalImg;
|
||||
|
||||
FramePtr->HotSpot = MAKE_HOT_SPOT (hx, hy);
|
||||
SetFrameBounds (FramePtr, tfbimg->extent.width, tfbimg->extent.height);
|
||||
|
||||
#ifdef CLIPDEBUG
|
||||
{
|
||||
/* for debugging clipping:
|
||||
draws white (or most matching color from palette) pixels to
|
||||
every corner of the image
|
||||
*/
|
||||
Color color = {0xff, 0xff, 0xff, 0xff};
|
||||
RECT r = {{0, 0}, {1, 1}};
|
||||
if (tfbimg->extent.width > 2 && tfbimg->extent.height > 2)
|
||||
{
|
||||
TFB_DrawImage_Rect (&r, color, tfbimg);
|
||||
r.corner.x = tfbimg->extent.width - 1;
|
||||
TFB_DrawImage_Rect (&r, color, tfbimg);
|
||||
r.corner.y = tfbimg->extent.height - 1;
|
||||
TFB_DrawImage_Rect (&r, color, tfbimg);
|
||||
r.corner.x = 0;
|
||||
TFB_DrawImage_Rect (&r, color, tfbimg);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
processFontChar (TFB_Char* CharPtr, TFB_Canvas canvas)
|
||||
{
|
||||
BYTE* newdata;
|
||||
size_t dpitch;
|
||||
|
||||
TFB_DrawCanvas_GetExtent (canvas, &CharPtr->extent);
|
||||
|
||||
// Currently, each font char has its own separate data
|
||||
// but that can change to common mem area
|
||||
dpitch = CharPtr->extent.width;
|
||||
newdata = HMalloc (dpitch * CharPtr->extent.height * sizeof (BYTE));
|
||||
TFB_DrawCanvas_GetFontCharData (canvas, newdata, dpitch);
|
||||
|
||||
CharPtr->data = newdata;
|
||||
CharPtr->pitch = dpitch;
|
||||
CharPtr->disp.width = CharPtr->extent.width + 1;
|
||||
CharPtr->disp.height = CharPtr->extent.height + 1;
|
||||
// XXX: why the +1?
|
||||
// I brought it into this function from the only calling
|
||||
// function, but I don't know why it was there in the first
|
||||
// place.
|
||||
// XXX: the +1 appears to be for character and line spacing
|
||||
// text_blt just adds the frame width to move to the next char
|
||||
|
||||
{
|
||||
// This tunes the font positioning to be about what it should
|
||||
// TODO: prolly needs a little tweaking still
|
||||
|
||||
int tune_amount = 0;
|
||||
|
||||
if (CharPtr->extent.height == 8)
|
||||
tune_amount = -1;
|
||||
else if (CharPtr->extent.height == 9)
|
||||
tune_amount = -2;
|
||||
else if (CharPtr->extent.height > 9)
|
||||
tune_amount = -3;
|
||||
|
||||
CharPtr->HotSpot = MAKE_HOT_SPOT (0,
|
||||
CharPtr->extent.height + tune_amount);
|
||||
}
|
||||
}
|
||||
|
||||
void *
|
||||
_GetCelData (uio_Stream *fp, DWORD length)
|
||||
{
|
||||
int cel_total, cel_index, n;
|
||||
DWORD opos;
|
||||
char CurrentLine[1024], filename[PATH_MAX];
|
||||
TFB_Canvas *img;
|
||||
AniData *ani;
|
||||
DRAWABLE Drawable;
|
||||
uio_MountHandle *aniMount = 0;
|
||||
uio_DirHandle *aniDir = 0;
|
||||
uio_Stream *aniFile = 0;
|
||||
|
||||
opos = uio_ftell (fp);
|
||||
|
||||
{
|
||||
char *s1, *s2;
|
||||
char aniDirName[PATH_MAX];
|
||||
const char *aniFileName;
|
||||
uint8 buf[4] = { 0, 0, 0, 0 };
|
||||
uint32 header;
|
||||
|
||||
if (_cur_resfile_name == 0
|
||||
|| (((s2 = 0), (s1 = strrchr (_cur_resfile_name, '/')) == 0)
|
||||
&& (s2 = strrchr (_cur_resfile_name, '\\')) == 0))
|
||||
{
|
||||
n = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (s2 > s1)
|
||||
s1 = s2;
|
||||
n = s1 - _cur_resfile_name + 1;
|
||||
}
|
||||
|
||||
uio_fread(buf, 4, 1, fp);
|
||||
header = buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
|
||||
if (_cur_resfile_name && header == 0x04034b50)
|
||||
{
|
||||
// zipped ani file
|
||||
if (n)
|
||||
{
|
||||
strncpy (aniDirName, _cur_resfile_name, n - 1);
|
||||
aniDirName[n - 1] = 0;
|
||||
aniFileName = _cur_resfile_name + n;
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy(aniDirName, ".");
|
||||
aniFileName = _cur_resfile_name;
|
||||
}
|
||||
aniDir = uio_openDir (repository, aniDirName, 0);
|
||||
aniMount = uio_mountDir (repository, aniDirName, uio_FSTYPE_ZIP,
|
||||
aniDir, aniFileName, "/", autoMount,
|
||||
uio_MOUNT_RDONLY | uio_MOUNT_TOP,
|
||||
NULL);
|
||||
aniFile = uio_fopen (aniDir, aniFileName, "r");
|
||||
opos = 0;
|
||||
n = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// unpacked ani file
|
||||
strncpy (filename, _cur_resfile_name, n);
|
||||
aniFile = fp;
|
||||
aniDir = contentDir;
|
||||
}
|
||||
}
|
||||
|
||||
cel_total = 0;
|
||||
uio_fseek (aniFile, opos, SEEK_SET);
|
||||
while (uio_fgets (CurrentLine, sizeof (CurrentLine), aniFile))
|
||||
{
|
||||
++cel_total;
|
||||
}
|
||||
|
||||
img = HMalloc (sizeof (TFB_Canvas) * cel_total);
|
||||
ani = HMalloc (sizeof (AniData) * cel_total);
|
||||
if (!img || !ani)
|
||||
{
|
||||
log_add (log_Warning, "Couldn't allocate space for '%s'", _cur_resfile_name);
|
||||
if (aniMount)
|
||||
{
|
||||
uio_fclose(aniFile);
|
||||
uio_closeDir(aniDir);
|
||||
uio_unmountDir(aniMount);
|
||||
}
|
||||
HFree (img);
|
||||
HFree (ani);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cel_index = 0;
|
||||
uio_fseek (aniFile, opos, SEEK_SET);
|
||||
while (uio_fgets (CurrentLine, sizeof (CurrentLine), aniFile) && cel_index < cel_total)
|
||||
{
|
||||
sscanf (CurrentLine, "%s %d %d %d %d", &filename[n],
|
||||
&ani[cel_index].transparent_color, &ani[cel_index].colormap_index,
|
||||
&ani[cel_index].hotspot_x, &ani[cel_index].hotspot_y);
|
||||
|
||||
img[cel_index] = TFB_DrawCanvas_LoadFromFile (aniDir, filename);
|
||||
if (img[cel_index] == NULL)
|
||||
{
|
||||
const char *err;
|
||||
|
||||
err = TFB_DrawCanvas_GetError ();
|
||||
log_add (log_Warning, "_GetCelData: Unable to load image!");
|
||||
if (err != NULL)
|
||||
log_add (log_Warning, "Gfx Driver reports: %s", err);
|
||||
}
|
||||
else
|
||||
{
|
||||
++cel_index;
|
||||
}
|
||||
|
||||
if ((int)uio_ftell (aniFile) - (int)opos >= (int)length)
|
||||
break;
|
||||
}
|
||||
|
||||
Drawable = NULL;
|
||||
if (cel_index && (Drawable = AllocDrawable (cel_index)))
|
||||
{
|
||||
if (!Drawable)
|
||||
{
|
||||
while (cel_index--)
|
||||
TFB_DrawCanvas_Delete (img[cel_index]);
|
||||
|
||||
HFree (Drawable);
|
||||
Drawable = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
FRAME FramePtr;
|
||||
|
||||
Drawable->Flags = WANT_PIXMAP;
|
||||
Drawable->MaxIndex = cel_index - 1;
|
||||
|
||||
FramePtr = &Drawable->Frame[cel_index];
|
||||
while (--FramePtr, cel_index--)
|
||||
process_image (FramePtr, img, ani, cel_index);
|
||||
}
|
||||
}
|
||||
|
||||
if (Drawable == NULL)
|
||||
log_add (log_Warning, "Couldn't get cel data for '%s'",
|
||||
_cur_resfile_name);
|
||||
|
||||
if (aniMount)
|
||||
{
|
||||
uio_fclose(aniFile);
|
||||
uio_closeDir(aniDir);
|
||||
uio_unmountDir(aniMount);
|
||||
}
|
||||
|
||||
HFree (img);
|
||||
HFree (ani);
|
||||
return Drawable;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
_ReleaseCelData (void *handle)
|
||||
{
|
||||
DRAWABLE DrawablePtr;
|
||||
int cel_ct;
|
||||
FRAME FramePtr = NULL;
|
||||
|
||||
if ((DrawablePtr = handle) == 0)
|
||||
return (FALSE);
|
||||
|
||||
cel_ct = DrawablePtr->MaxIndex + 1;
|
||||
|
||||
if (DrawablePtr->Frame)
|
||||
{
|
||||
FramePtr = DrawablePtr->Frame;
|
||||
if (FramePtr->Type == SCREEN_DRAWABLE)
|
||||
{
|
||||
FramePtr = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
HFree (handle);
|
||||
if (FramePtr)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < cel_ct; i++)
|
||||
{
|
||||
TFB_Image *img = FramePtr[i].image;
|
||||
if (img)
|
||||
{
|
||||
FramePtr[i].image = NULL;
|
||||
TFB_DrawScreen_DeleteImage (img);
|
||||
}
|
||||
}
|
||||
HFree (FramePtr);
|
||||
}
|
||||
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
typedef struct BuildCharDesc
|
||||
{
|
||||
TFB_Canvas canvas;
|
||||
UniChar index;
|
||||
} BuildCharDesc;
|
||||
|
||||
int
|
||||
compareBCDIndex (const BuildCharDesc *bcd1, const BuildCharDesc *bcd2)
|
||||
{
|
||||
return (int) bcd1->index - (int) bcd2->index;
|
||||
}
|
||||
|
||||
void *
|
||||
_GetFontData (uio_Stream *fp, DWORD length)
|
||||
{
|
||||
COUNT numDirEntries;
|
||||
DIRENTRY fontDir = NULL;
|
||||
BuildCharDesc *bcds = NULL;
|
||||
size_t numBCDs = 0;
|
||||
int dirEntryI;
|
||||
uio_DirHandle *fontDirHandle = NULL;
|
||||
uio_MountHandle *fontMount = NULL;
|
||||
FONT fontPtr = NULL;
|
||||
|
||||
if (_cur_resfile_name == 0)
|
||||
goto err;
|
||||
|
||||
if (fp != (uio_Stream*)~0)
|
||||
{
|
||||
// font is zipped instead of being in a directory
|
||||
|
||||
char *s1, *s2;
|
||||
int n;
|
||||
const char *fontZipName;
|
||||
char fontDirName[PATH_MAX];
|
||||
|
||||
if ((((s2 = 0), (s1 = strrchr (_cur_resfile_name, '/')) == 0)
|
||||
&& (s2 = strrchr (_cur_resfile_name, '\\')) == 0))
|
||||
{
|
||||
strcpy(fontDirName, ".");
|
||||
fontZipName = _cur_resfile_name;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (s2 > s1)
|
||||
s1 = s2;
|
||||
n = s1 - _cur_resfile_name + 1;
|
||||
strncpy (fontDirName, _cur_resfile_name, n - 1);
|
||||
fontDirName[n - 1] = 0;
|
||||
fontZipName = _cur_resfile_name + n;
|
||||
}
|
||||
|
||||
fontDirHandle = uio_openDir (repository, fontDirName, 0);
|
||||
fontMount = uio_mountDir (repository, _cur_resfile_name, uio_FSTYPE_ZIP,
|
||||
fontDirHandle, fontZipName, "/", autoMount,
|
||||
uio_MOUNT_RDONLY | uio_MOUNT_TOP,
|
||||
NULL);
|
||||
uio_closeDir (fontDirHandle);
|
||||
}
|
||||
|
||||
fontDir = CaptureDirEntryTable (LoadDirEntryTable (contentDir,
|
||||
_cur_resfile_name, ".", match_MATCH_SUBSTRING));
|
||||
if (fontDir == 0)
|
||||
goto err;
|
||||
numDirEntries = GetDirEntryTableCount (fontDir);
|
||||
|
||||
fontDirHandle = uio_openDirRelative (contentDir, _cur_resfile_name, 0);
|
||||
if (fontDirHandle == NULL)
|
||||
goto err;
|
||||
|
||||
bcds = HMalloc (numDirEntries * sizeof (BuildCharDesc));
|
||||
if (bcds == NULL)
|
||||
goto err;
|
||||
|
||||
// Load the surfaces for all dir Entries
|
||||
for (dirEntryI = 0; dirEntryI < numDirEntries; dirEntryI++)
|
||||
{
|
||||
char *char_name;
|
||||
unsigned int charIndex;
|
||||
TFB_Canvas canvas;
|
||||
EXTENT size;
|
||||
|
||||
char_name = GetDirEntryAddress (SetAbsDirEntryTableIndex (
|
||||
fontDir, dirEntryI));
|
||||
if (sscanf (char_name, "%x.", &charIndex) != 1)
|
||||
continue;
|
||||
|
||||
if (charIndex > 0xffff)
|
||||
continue;
|
||||
|
||||
canvas = TFB_DrawCanvas_LoadFromFile (fontDirHandle, char_name);
|
||||
if (canvas == NULL)
|
||||
continue;
|
||||
|
||||
TFB_DrawCanvas_GetExtent (canvas, &size);
|
||||
if (size.width == 0 || size.height == 0)
|
||||
{
|
||||
TFB_DrawCanvas_Delete (canvas);
|
||||
continue;
|
||||
}
|
||||
|
||||
bcds[numBCDs].canvas = canvas;
|
||||
bcds[numBCDs].index = charIndex;
|
||||
numBCDs++;
|
||||
}
|
||||
uio_closeDir (fontDirHandle);
|
||||
DestroyDirEntryTable (ReleaseDirEntryTable (fontDir));
|
||||
if (fontMount != 0)
|
||||
uio_unmountDir(fontMount);
|
||||
|
||||
#if 0
|
||||
if (numBCDs == 0)
|
||||
goto err;
|
||||
#endif
|
||||
|
||||
// sort on the character index
|
||||
qsort (bcds, numBCDs, sizeof (BuildCharDesc),
|
||||
(int (*)(const void *, const void *)) compareBCDIndex);
|
||||
|
||||
fontPtr = AllocFont (0);
|
||||
if (fontPtr == NULL)
|
||||
goto err;
|
||||
|
||||
fontPtr->Leading = 0;
|
||||
fontPtr->LeadingWidth = 0;
|
||||
|
||||
{
|
||||
size_t startBCD = 0;
|
||||
UniChar pageStart;
|
||||
FONT_PAGE **pageEndPtr = &fontPtr->fontPages;
|
||||
while (startBCD < numBCDs)
|
||||
{
|
||||
// Process one character page.
|
||||
size_t endBCD;
|
||||
pageStart = bcds[startBCD].index & CHARACTER_PAGE_MASK;
|
||||
|
||||
endBCD = startBCD;
|
||||
while (endBCD < numBCDs &&
|
||||
(bcds[endBCD].index & CHARACTER_PAGE_MASK) == pageStart)
|
||||
endBCD++;
|
||||
|
||||
{
|
||||
size_t bcdI;
|
||||
int numChars = bcds[endBCD - 1].index + 1
|
||||
- bcds[startBCD].index;
|
||||
FONT_PAGE *page = AllocFontPage (numChars);
|
||||
page->pageStart = pageStart;
|
||||
page->firstChar = bcds[startBCD].index;
|
||||
page->numChars = numChars;
|
||||
*pageEndPtr = page;
|
||||
pageEndPtr = &page->next;
|
||||
|
||||
for (bcdI = startBCD; bcdI < endBCD; bcdI++)
|
||||
{
|
||||
// Process one character.
|
||||
BuildCharDesc *bcd = &bcds[bcdI];
|
||||
TFB_Char *destChar =
|
||||
&page->charDesc[bcd->index - page->firstChar];
|
||||
|
||||
if (destChar->data != NULL)
|
||||
{
|
||||
// There's already an image for this character.
|
||||
log_add (log_Debug, "Duplicate image for character %d "
|
||||
"for font %s.", (int) bcd->index,
|
||||
_cur_resfile_name);
|
||||
TFB_DrawCanvas_Delete (bcd->canvas);
|
||||
continue;
|
||||
}
|
||||
|
||||
processFontChar (destChar, bcd->canvas);
|
||||
TFB_DrawCanvas_Delete (bcd->canvas);
|
||||
|
||||
if (destChar->disp.height > fontPtr->Leading)
|
||||
fontPtr->Leading = destChar->disp.height;
|
||||
if (destChar->disp.width > fontPtr->LeadingWidth)
|
||||
fontPtr->LeadingWidth = destChar->disp.width;
|
||||
}
|
||||
}
|
||||
|
||||
startBCD = endBCD;
|
||||
}
|
||||
*pageEndPtr = NULL;
|
||||
}
|
||||
|
||||
fontPtr->Leading++;
|
||||
|
||||
HFree (bcds);
|
||||
|
||||
(void) fp; /* Satisfying compiler (unused parameter) */
|
||||
(void) length; /* Satisfying compiler (unused parameter) */
|
||||
return fontPtr;
|
||||
|
||||
err:
|
||||
if (fontPtr != 0)
|
||||
HFree (fontPtr);
|
||||
|
||||
if (bcds != NULL)
|
||||
{
|
||||
size_t bcdI;
|
||||
for (bcdI = 0; bcdI < numBCDs; bcdI++)
|
||||
TFB_DrawCanvas_Delete (bcds[bcdI].canvas);
|
||||
HFree (bcds);
|
||||
}
|
||||
|
||||
if (fontDirHandle != NULL)
|
||||
uio_closeDir (fontDirHandle);
|
||||
|
||||
if (fontDir != 0)
|
||||
DestroyDirEntryTable (ReleaseDirEntryTable (fontDir));
|
||||
|
||||
if (fontMount != 0)
|
||||
uio_unmountDir(fontMount);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
_ReleaseFontData (void *handle)
|
||||
{
|
||||
FONT font = (FONT) handle;
|
||||
if (font == NULL)
|
||||
return FALSE;
|
||||
|
||||
{
|
||||
FONT_PAGE *page;
|
||||
FONT_PAGE *nextPage;
|
||||
|
||||
for (page = font->fontPages; page != NULL; page = nextPage)
|
||||
{
|
||||
size_t charI;
|
||||
for (charI = 0; charI < page->numChars; charI++)
|
||||
{
|
||||
TFB_Char *c = &page->charDesc[charI];
|
||||
|
||||
if (c->data == NULL)
|
||||
continue;
|
||||
|
||||
// XXX: fix this if fonts get per-page data
|
||||
// rather than per-char
|
||||
TFB_DrawScreen_DeleteData (c->data);
|
||||
}
|
||||
|
||||
nextPage = page->next;
|
||||
FreeFontPage (page);
|
||||
}
|
||||
}
|
||||
|
||||
HFree (font);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -18,172 +18,13 @@
|
||||
|
||||
#ifdef GFXMODULE_SDL
|
||||
|
||||
#ifdef WIN32
|
||||
#include <io.h>
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "options.h"
|
||||
#include "port.h"
|
||||
#include "libs/gfxlib.h"
|
||||
#include "libs/graphics/tfb_draw.h"
|
||||
#include "sdl_common.h"
|
||||
#include "sdluio.h"
|
||||
#include "libs/file.h"
|
||||
#include "libs/reslib.h"
|
||||
#include "libs/log.h"
|
||||
#include "libs/memlib.h"
|
||||
#include "../font.h"
|
||||
#include "primitives.h"
|
||||
|
||||
|
||||
typedef struct anidata
|
||||
{
|
||||
int transparent_color;
|
||||
int colormap_index;
|
||||
int hotspot_x;
|
||||
int hotspot_y;
|
||||
} AniData;
|
||||
|
||||
extern uio_Repository *repository;
|
||||
static uio_AutoMount *autoMount[] = { NULL };
|
||||
|
||||
static void
|
||||
process_image (FRAME FramePtr, SDL_Surface *img[], AniData *ani, int cel_ct)
|
||||
{
|
||||
TFB_Image *tfbimg;
|
||||
int hx, hy;
|
||||
|
||||
FramePtr->Type = ROM_DRAWABLE;
|
||||
FramePtr->Index = cel_ct;
|
||||
|
||||
// handle transparency cases
|
||||
if (img[cel_ct]->format->palette)
|
||||
{ // indexed color image
|
||||
if (ani[cel_ct].transparent_color >= 0)
|
||||
SDL_SetColorKey (img[cel_ct], SDL_SRCCOLORKEY,
|
||||
ani[cel_ct].transparent_color);
|
||||
}
|
||||
else if (img[cel_ct]->format->BitsPerPixel > 8)
|
||||
{ // special transparency cases for truecolor images
|
||||
if (ani[cel_ct].transparent_color == 0)
|
||||
// make RGB=0,0,0 transparent
|
||||
SDL_SetColorKey (img[cel_ct], SDL_SRCCOLORKEY,
|
||||
SDL_MapRGBA (img[cel_ct]->format, 0, 0, 0, 0));
|
||||
}
|
||||
if (ani[cel_ct].transparent_color == -1)
|
||||
{ // enforce -1 to mean 'no transparency'
|
||||
SDL_SetColorKey (img[cel_ct], 0, 0);
|
||||
// set transparent_color == -2 to use PNG tRNS transparency
|
||||
}
|
||||
|
||||
hx = ani[cel_ct].hotspot_x;
|
||||
hy = ani[cel_ct].hotspot_y;
|
||||
|
||||
FramePtr->image = TFB_DrawImage_New (img[cel_ct]);
|
||||
|
||||
tfbimg = FramePtr->image;
|
||||
tfbimg->colormap_index = ani[cel_ct].colormap_index;
|
||||
img[cel_ct] = (SDL_Surface *)tfbimg->NormalImg;
|
||||
|
||||
FramePtr->HotSpot = MAKE_HOT_SPOT (hx, hy);
|
||||
SetFrameBounds (FramePtr, img[cel_ct]->w, img[cel_ct]->h);
|
||||
|
||||
#ifdef CLIPDEBUG
|
||||
{
|
||||
/* for debugging clipping:
|
||||
draws white (or most matching color from palette) pixels to
|
||||
every corner of the image
|
||||
*/
|
||||
Uint32 color = SDL_MapRGB (img[cel_ct]->format, 255, 255, 255);
|
||||
SDL_Rect r = {0, 0, 1, 1};
|
||||
if (img[cel_ct]->w > 2 && img[cel_ct]->h > 2)
|
||||
{
|
||||
SDL_FillRect (img[cel_ct], &r, color);
|
||||
r.x = img[cel_ct]->w - 1;
|
||||
SDL_FillRect (img[cel_ct], &r, color);
|
||||
r.y = img[cel_ct]->h - 1;
|
||||
SDL_FillRect (img[cel_ct], &r, color);
|
||||
r.x = 0;
|
||||
SDL_FillRect (img[cel_ct], &r, color);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
processFontChar (TFB_Char* CharPtr, SDL_Surface *surf)
|
||||
{
|
||||
int x,y;
|
||||
Uint8 r,g,b,a;
|
||||
Uint32 p;
|
||||
SDL_PixelFormat* srcfmt = surf->format;
|
||||
GetPixelFn getpix;
|
||||
BYTE* newdata;
|
||||
Uint32 dpitch;
|
||||
|
||||
// Currently, each font char has its own separate data
|
||||
// but that can change to common mem area
|
||||
newdata = HMalloc (surf->w * surf->h * sizeof(BYTE));
|
||||
dpitch = surf->w;
|
||||
|
||||
SDL_LockSurface (surf);
|
||||
|
||||
getpix = getpixel_for (surf);
|
||||
|
||||
// produce an alpha-only image in internal BYTE[] format
|
||||
// from the SDL surface
|
||||
for (y = 0; y < surf->h; ++y)
|
||||
{
|
||||
BYTE* dst = newdata + dpitch * y;
|
||||
|
||||
for (x = 0; x < surf->w; ++x, ++dst)
|
||||
{
|
||||
p = getpix (surf, x, y);
|
||||
SDL_GetRGBA (p, srcfmt, &r, &g, &b, &a);
|
||||
|
||||
if (!srcfmt->Amask)
|
||||
{ // produce alpha from intensity (Y component)
|
||||
// using a fast approximation
|
||||
// contributions to Y are: R=2, G=4, B=1
|
||||
a = (((int)r << 1) + ((int)g << 2) + b) / 7;
|
||||
}
|
||||
|
||||
*dst = a;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_UnlockSurface (surf);
|
||||
|
||||
CharPtr->data = newdata;
|
||||
CharPtr->pitch = dpitch;
|
||||
CharPtr->extent.width = surf->w;
|
||||
CharPtr->extent.height = surf->h;
|
||||
CharPtr->disp.width = surf->w + 1;
|
||||
CharPtr->disp.height = surf->h + 1;
|
||||
// XXX: why the +1?
|
||||
// I brought it into this function from the only calling
|
||||
// function, but I don't know why it was there in the first
|
||||
// place.
|
||||
// XXX: the +1 appears to be for character and line spacing
|
||||
// text_blt just adds the frame width to move to the next char
|
||||
|
||||
{
|
||||
// This tunes the font positioning to be about what it should
|
||||
// TODO: prolly needs a little tweaking still
|
||||
|
||||
int tune_amount = 0;
|
||||
|
||||
if (CharPtr->extent.height == 8)
|
||||
tune_amount = -1;
|
||||
else if (CharPtr->extent.height == 9)
|
||||
tune_amount = -2;
|
||||
else if (CharPtr->extent.height > 9)
|
||||
tune_amount = -3;
|
||||
|
||||
CharPtr->HotSpot = MAKE_HOT_SPOT (0,
|
||||
CharPtr->extent.height + tune_amount);
|
||||
}
|
||||
}
|
||||
|
||||
// stretch_frame
|
||||
// create a new frame of size neww x newh, and blit a scaled version FramePtr
|
||||
// into it.
|
||||
@@ -373,458 +214,4 @@ Uint32 frame_mapRGBA (FRAME FramePtr,Uint8 r, Uint8 g, Uint8 b, Uint8 a)
|
||||
return (SDL_MapRGBA (img->format, r, g, b, a));
|
||||
}
|
||||
|
||||
void *
|
||||
_GetCelData (uio_Stream *fp, DWORD length)
|
||||
{
|
||||
int cel_total, cel_index, n;
|
||||
DWORD opos;
|
||||
char CurrentLine[1024], filename[PATH_MAX];
|
||||
SDL_Surface **img;
|
||||
AniData *ani;
|
||||
DRAWABLE Drawable;
|
||||
uio_MountHandle *aniMount = 0;
|
||||
uio_DirHandle *aniDir = 0;
|
||||
uio_Stream *aniFile = 0;
|
||||
|
||||
opos = uio_ftell (fp);
|
||||
|
||||
{
|
||||
char *s1, *s2;
|
||||
char aniDirName[PATH_MAX];
|
||||
const char *aniFileName;
|
||||
uint8 buf[4] = { 0, 0, 0, 0 };
|
||||
uint32 header;
|
||||
|
||||
if (_cur_resfile_name == 0
|
||||
|| (((s2 = 0), (s1 = strrchr (_cur_resfile_name, '/')) == 0)
|
||||
&& (s2 = strrchr (_cur_resfile_name, '\\')) == 0))
|
||||
{
|
||||
n = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (s2 > s1)
|
||||
s1 = s2;
|
||||
n = s1 - _cur_resfile_name + 1;
|
||||
}
|
||||
|
||||
uio_fread(buf, 4, 1, fp);
|
||||
header = buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
|
||||
if (_cur_resfile_name && header == 0x04034b50)
|
||||
{
|
||||
// zipped ani file
|
||||
if (n)
|
||||
{
|
||||
strncpy (aniDirName, _cur_resfile_name, n - 1);
|
||||
aniDirName[n - 1] = 0;
|
||||
aniFileName = _cur_resfile_name + n;
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy(aniDirName, ".");
|
||||
aniFileName = _cur_resfile_name;
|
||||
}
|
||||
aniDir = uio_openDir (repository, aniDirName, 0);
|
||||
aniMount = uio_mountDir (repository, aniDirName, uio_FSTYPE_ZIP,
|
||||
aniDir, aniFileName, "/", autoMount,
|
||||
uio_MOUNT_RDONLY | uio_MOUNT_TOP,
|
||||
NULL);
|
||||
aniFile = uio_fopen (aniDir, aniFileName, "r");
|
||||
opos = 0;
|
||||
n = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// unpacked ani file
|
||||
strncpy (filename, _cur_resfile_name, n);
|
||||
aniFile = fp;
|
||||
aniDir = contentDir;
|
||||
}
|
||||
}
|
||||
|
||||
cel_total = 0;
|
||||
uio_fseek (aniFile, opos, SEEK_SET);
|
||||
while (uio_fgets (CurrentLine, sizeof (CurrentLine), aniFile))
|
||||
{
|
||||
++cel_total;
|
||||
}
|
||||
|
||||
img = HMalloc (sizeof (SDL_Surface *) * cel_total);
|
||||
ani = HMalloc (sizeof (AniData) * cel_total);
|
||||
if (!img || !ani)
|
||||
{
|
||||
log_add (log_Warning, "Couldn't allocate space for '%s'", _cur_resfile_name);
|
||||
if (aniMount)
|
||||
{
|
||||
uio_fclose(aniFile);
|
||||
uio_closeDir(aniDir);
|
||||
uio_unmountDir(aniMount);
|
||||
}
|
||||
HFree (img);
|
||||
HFree (ani);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cel_index = 0;
|
||||
uio_fseek (aniFile, opos, SEEK_SET);
|
||||
while (uio_fgets (CurrentLine, sizeof (CurrentLine), aniFile) && cel_index < cel_total)
|
||||
{
|
||||
sscanf (CurrentLine, "%s %d %d %d %d", &filename[n],
|
||||
&ani[cel_index].transparent_color, &ani[cel_index].colormap_index,
|
||||
&ani[cel_index].hotspot_x, &ani[cel_index].hotspot_y);
|
||||
|
||||
img[cel_index] = sdluio_loadImage (aniDir, filename);
|
||||
if (img[cel_index] == NULL)
|
||||
{
|
||||
const char *err;
|
||||
|
||||
err = SDL_GetError();
|
||||
log_add (log_Warning, "_GetCelData: Unable to load image!");
|
||||
if (err != NULL)
|
||||
log_add (log_Warning, "SDL reports: %s", err);
|
||||
SDL_FreeSurface (img[cel_index]);
|
||||
}
|
||||
else if (img[cel_index]->w < 0 || img[cel_index]->h < 0 ||
|
||||
img[cel_index]->format->BitsPerPixel < 8)
|
||||
{
|
||||
log_add (log_Warning, "_GetCelData: Bad file!");
|
||||
SDL_FreeSurface (img[cel_index]);
|
||||
}
|
||||
else
|
||||
{
|
||||
++cel_index;
|
||||
}
|
||||
|
||||
if ((int)uio_ftell (aniFile) - (int)opos >= (int)length)
|
||||
break;
|
||||
}
|
||||
|
||||
Drawable = NULL;
|
||||
if (cel_index && (Drawable = AllocDrawable (cel_index)))
|
||||
{
|
||||
if (!Drawable)
|
||||
{
|
||||
while (cel_index--)
|
||||
SDL_FreeSurface (img[cel_index]);
|
||||
|
||||
HFree (Drawable);
|
||||
Drawable = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
FRAME FramePtr;
|
||||
|
||||
Drawable->Flags = WANT_PIXMAP;
|
||||
Drawable->MaxIndex = cel_index - 1;
|
||||
|
||||
FramePtr = &Drawable->Frame[cel_index];
|
||||
while (--FramePtr, cel_index--)
|
||||
process_image (FramePtr, img, ani, cel_index);
|
||||
}
|
||||
}
|
||||
|
||||
if (Drawable == NULL)
|
||||
log_add (log_Warning, "Couldn't get cel data for '%s'",
|
||||
_cur_resfile_name);
|
||||
|
||||
if (aniMount)
|
||||
{
|
||||
uio_fclose(aniFile);
|
||||
uio_closeDir(aniDir);
|
||||
uio_unmountDir(aniMount);
|
||||
}
|
||||
|
||||
HFree (img);
|
||||
HFree (ani);
|
||||
return Drawable;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
_ReleaseCelData (void *handle)
|
||||
{
|
||||
DRAWABLE DrawablePtr;
|
||||
int cel_ct;
|
||||
FRAME FramePtr = NULL;
|
||||
|
||||
if ((DrawablePtr = handle) == 0)
|
||||
return (FALSE);
|
||||
|
||||
cel_ct = DrawablePtr->MaxIndex + 1;
|
||||
|
||||
if (DrawablePtr->Frame)
|
||||
{
|
||||
FramePtr = DrawablePtr->Frame;
|
||||
if (FramePtr->Type == SCREEN_DRAWABLE)
|
||||
{
|
||||
FramePtr = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
HFree (handle);
|
||||
if (FramePtr)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < cel_ct; i++)
|
||||
{
|
||||
TFB_Image *img = FramePtr[i].image;
|
||||
if (img)
|
||||
{
|
||||
FramePtr[i].image = NULL;
|
||||
TFB_DrawScreen_DeleteImage (img);
|
||||
}
|
||||
}
|
||||
HFree (FramePtr);
|
||||
}
|
||||
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
typedef struct BuildCharDesc {
|
||||
SDL_Surface *surface;
|
||||
UniChar index;
|
||||
} BuildCharDesc;
|
||||
|
||||
int
|
||||
compareBCDIndex(const BuildCharDesc *bcd1, const BuildCharDesc *bcd2) {
|
||||
return (int) bcd1->index - (int) bcd2->index;
|
||||
}
|
||||
|
||||
void *
|
||||
_GetFontData (uio_Stream *fp, DWORD length)
|
||||
{
|
||||
COUNT numDirEntries;
|
||||
DIRENTRY fontDir = NULL;
|
||||
BuildCharDesc *bcds = NULL;
|
||||
size_t numBCDs = 0;
|
||||
int dirEntryI;
|
||||
uio_DirHandle *fontDirHandle = NULL;
|
||||
uio_MountHandle *fontMount = NULL;
|
||||
FONT fontPtr = NULL;
|
||||
|
||||
if (_cur_resfile_name == 0)
|
||||
goto err;
|
||||
|
||||
if (fp != (uio_Stream*)~0)
|
||||
{
|
||||
// font is zipped instead of being in a directory
|
||||
|
||||
char *s1, *s2;
|
||||
int n;
|
||||
const char *fontZipName;
|
||||
char fontDirName[PATH_MAX];
|
||||
|
||||
if ((((s2 = 0), (s1 = strrchr (_cur_resfile_name, '/')) == 0)
|
||||
&& (s2 = strrchr (_cur_resfile_name, '\\')) == 0))
|
||||
{
|
||||
strcpy(fontDirName, ".");
|
||||
fontZipName = _cur_resfile_name;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (s2 > s1)
|
||||
s1 = s2;
|
||||
n = s1 - _cur_resfile_name + 1;
|
||||
strncpy (fontDirName, _cur_resfile_name, n - 1);
|
||||
fontDirName[n - 1] = 0;
|
||||
fontZipName = _cur_resfile_name + n;
|
||||
}
|
||||
|
||||
fontDirHandle = uio_openDir (repository, fontDirName, 0);
|
||||
fontMount = uio_mountDir (repository, _cur_resfile_name, uio_FSTYPE_ZIP,
|
||||
fontDirHandle, fontZipName, "/", autoMount,
|
||||
uio_MOUNT_RDONLY | uio_MOUNT_TOP,
|
||||
NULL);
|
||||
uio_closeDir (fontDirHandle);
|
||||
}
|
||||
|
||||
fontDir = CaptureDirEntryTable (LoadDirEntryTable (contentDir,
|
||||
_cur_resfile_name, ".", match_MATCH_SUBSTRING));
|
||||
if (fontDir == 0)
|
||||
goto err;
|
||||
numDirEntries = GetDirEntryTableCount (fontDir);
|
||||
|
||||
fontDirHandle = uio_openDirRelative (contentDir, _cur_resfile_name, 0);
|
||||
if (fontDirHandle == NULL)
|
||||
goto err;
|
||||
|
||||
bcds = HMalloc (numDirEntries * sizeof (BuildCharDesc));
|
||||
if (bcds == NULL)
|
||||
goto err;
|
||||
|
||||
// Load the surfaces for all dir Entries
|
||||
for (dirEntryI = 0; dirEntryI < numDirEntries; dirEntryI++)
|
||||
{
|
||||
char *char_name;
|
||||
unsigned int charIndex;
|
||||
SDL_Surface *surface;
|
||||
|
||||
char_name = GetDirEntryAddress (SetAbsDirEntryTableIndex (
|
||||
fontDir, dirEntryI));
|
||||
if (sscanf (char_name, "%x.", &charIndex) != 1)
|
||||
continue;
|
||||
|
||||
if (charIndex > 0xffff)
|
||||
continue;
|
||||
|
||||
surface = sdluio_loadImage (fontDirHandle, char_name);
|
||||
if (surface == NULL)
|
||||
continue;
|
||||
|
||||
if (surface->w == 0 || surface->h == 0 ||
|
||||
surface->format->BitsPerPixel < 8) {
|
||||
SDL_FreeSurface (surface);
|
||||
continue;
|
||||
}
|
||||
|
||||
bcds[numBCDs].surface = surface;
|
||||
bcds[numBCDs].index = charIndex;
|
||||
numBCDs++;
|
||||
}
|
||||
uio_closeDir (fontDirHandle);
|
||||
DestroyDirEntryTable (ReleaseDirEntryTable (fontDir));
|
||||
if (fontMount != 0)
|
||||
uio_unmountDir(fontMount);
|
||||
|
||||
#if 0
|
||||
if (numBCDs == 0)
|
||||
goto err;
|
||||
#endif
|
||||
|
||||
// sort on the character index
|
||||
qsort (bcds, numBCDs, sizeof (BuildCharDesc),
|
||||
(int (*)(const void *, const void *)) compareBCDIndex);
|
||||
|
||||
fontPtr = AllocFont (0);
|
||||
if (fontPtr == NULL)
|
||||
goto err;
|
||||
|
||||
fontPtr->Leading = 0;
|
||||
fontPtr->LeadingWidth = 0;
|
||||
|
||||
{
|
||||
size_t startBCD = 0;
|
||||
UniChar pageStart;
|
||||
FONT_PAGE **pageEndPtr = &fontPtr->fontPages;
|
||||
while (startBCD < numBCDs)
|
||||
{
|
||||
// Process one character page.
|
||||
size_t endBCD;
|
||||
pageStart = bcds[startBCD].index & CHARACTER_PAGE_MASK;
|
||||
|
||||
endBCD = startBCD;
|
||||
while (endBCD < numBCDs &&
|
||||
(bcds[endBCD].index & CHARACTER_PAGE_MASK) == pageStart)
|
||||
endBCD++;
|
||||
|
||||
{
|
||||
size_t bcdI;
|
||||
int numChars = bcds[endBCD - 1].index + 1
|
||||
- bcds[startBCD].index;
|
||||
FONT_PAGE *page = AllocFontPage (numChars);
|
||||
page->pageStart = pageStart;
|
||||
page->firstChar = bcds[startBCD].index;
|
||||
page->numChars = numChars;
|
||||
*pageEndPtr = page;
|
||||
pageEndPtr = &page->next;
|
||||
|
||||
for (bcdI = startBCD; bcdI < endBCD; bcdI++)
|
||||
{
|
||||
// Process one character.
|
||||
BuildCharDesc *bcd = &bcds[bcdI];
|
||||
TFB_Char *destChar =
|
||||
&page->charDesc[bcd->index - page->firstChar];
|
||||
|
||||
if (destChar->data != NULL)
|
||||
{
|
||||
// There's already an image for this character.
|
||||
log_add (log_Debug, "Duplicate image for character %d "
|
||||
"for font %s.", (int) bcd->index,
|
||||
_cur_resfile_name);
|
||||
SDL_FreeSurface (bcd->surface);
|
||||
continue;
|
||||
}
|
||||
|
||||
processFontChar (destChar, bcd->surface);
|
||||
SDL_FreeSurface (bcd->surface);
|
||||
|
||||
if (destChar->disp.height > fontPtr->Leading)
|
||||
fontPtr->Leading = destChar->disp.height;
|
||||
if (destChar->disp.width > fontPtr->LeadingWidth)
|
||||
fontPtr->LeadingWidth = destChar->disp.width;
|
||||
}
|
||||
}
|
||||
|
||||
startBCD = endBCD;
|
||||
}
|
||||
*pageEndPtr = NULL;
|
||||
}
|
||||
|
||||
fontPtr->Leading++;
|
||||
|
||||
HFree (bcds);
|
||||
|
||||
(void) fp; /* Satisfying compiler (unused parameter) */
|
||||
(void) length; /* Satisfying compiler (unused parameter) */
|
||||
return fontPtr;
|
||||
|
||||
err:
|
||||
if (fontPtr != 0)
|
||||
HFree (fontPtr);
|
||||
|
||||
if (bcds != NULL)
|
||||
{
|
||||
size_t bcdI;
|
||||
for (bcdI = 0; bcdI < numBCDs; bcdI++)
|
||||
SDL_FreeSurface (bcds[bcdI].surface);
|
||||
HFree (bcds);
|
||||
}
|
||||
|
||||
if (fontDirHandle != NULL)
|
||||
uio_closeDir (fontDirHandle);
|
||||
|
||||
if (fontDir != 0)
|
||||
DestroyDirEntryTable (ReleaseDirEntryTable (fontDir));
|
||||
|
||||
if (fontMount != 0)
|
||||
uio_unmountDir(fontMount);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
_ReleaseFontData (void *handle)
|
||||
{
|
||||
FONT font = (FONT) handle;
|
||||
if (font == NULL)
|
||||
return FALSE;
|
||||
|
||||
{
|
||||
FONT_PAGE *page;
|
||||
FONT_PAGE *nextPage;
|
||||
|
||||
for (page = font->fontPages; page != NULL; page = nextPage)
|
||||
{
|
||||
size_t charI;
|
||||
for (charI = 0; charI < page->numChars; charI++)
|
||||
{
|
||||
TFB_Char *c = &page->charDesc[charI];
|
||||
|
||||
if (c->data == NULL)
|
||||
continue;
|
||||
|
||||
// XXX: fix this if fonts get per-page data
|
||||
// rather than per-char
|
||||
TFB_DrawScreen_DeleteData (c->data);
|
||||
}
|
||||
|
||||
nextPage = page->next;
|
||||
FreeFontPage (page);
|
||||
}
|
||||
}
|
||||
|
||||
HFree (font);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "libs/memlib.h"
|
||||
#include "primitives.h"
|
||||
#include "palette.h"
|
||||
#include "sdluio.h"
|
||||
#include "rotozoom.h"
|
||||
#include "options.h"
|
||||
#include "types.h"
|
||||
@@ -43,6 +44,15 @@ TFB_DrawCanvas_Initialize (void)
|
||||
// need error correction here
|
||||
}
|
||||
|
||||
const char *
|
||||
TFB_DrawCanvas_GetError (void)
|
||||
{
|
||||
const char *err = SDL_GetError ();
|
||||
// TODO: Should we call SDL_ClearError() here so that it is not
|
||||
// returned again later?
|
||||
return err;
|
||||
}
|
||||
|
||||
void
|
||||
TFB_DrawCanvas_Line (int x1, int y1, int x2, int y2, Color color,
|
||||
TFB_Canvas target)
|
||||
@@ -590,6 +600,23 @@ TFB_DrawCanvas_New_RotationTarget (TFB_Canvas src_canvas, int angle)
|
||||
return newsurf;
|
||||
}
|
||||
|
||||
TFB_Canvas
|
||||
TFB_DrawCanvas_LoadFromFile (void *dir, const char *fileName)
|
||||
{
|
||||
SDL_Surface *surf = sdluio_loadImage (dir, fileName);
|
||||
if (!surf)
|
||||
return NULL;
|
||||
|
||||
if (surf->format->BitsPerPixel < 8)
|
||||
{
|
||||
SDL_SetError ("unsupported image format (min 8bpp)");
|
||||
SDL_FreeSurface (surf);
|
||||
surf = NULL;
|
||||
}
|
||||
|
||||
return surf;
|
||||
}
|
||||
|
||||
void
|
||||
TFB_DrawCanvas_Delete (TFB_Canvas canvas)
|
||||
{
|
||||
@@ -603,7 +630,51 @@ TFB_DrawCanvas_Delete (TFB_Canvas canvas)
|
||||
{
|
||||
SDL_FreeSurface (canvas);
|
||||
}
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
TFB_DrawCanvas_GetFontCharData (TFB_Canvas canvas, BYTE *outData,
|
||||
unsigned dataPitch)
|
||||
{
|
||||
SDL_Surface *surf = canvas;
|
||||
int x, y;
|
||||
Uint8 r, g, b, a;
|
||||
Uint32 p;
|
||||
SDL_PixelFormat *fmt = surf->format;
|
||||
GetPixelFn getpix;
|
||||
|
||||
if (!surf || !outData)
|
||||
return FALSE;
|
||||
|
||||
SDL_LockSurface (surf);
|
||||
|
||||
getpix = getpixel_for (surf);
|
||||
|
||||
// produce an alpha-only image in internal BYTE[] format
|
||||
// from the SDL surface
|
||||
for (y = 0; y < surf->h; ++y)
|
||||
{
|
||||
BYTE *dst = outData + dataPitch * y;
|
||||
|
||||
for (x = 0; x < surf->w; ++x, ++dst)
|
||||
{
|
||||
p = getpix (surf, x, y);
|
||||
SDL_GetRGBA (p, fmt, &r, &g, &b, &a);
|
||||
|
||||
if (!fmt->Amask)
|
||||
{ // produce alpha from intensity (Y component)
|
||||
// using a fast approximation
|
||||
// contributions to Y are: R=2, G=4, B=1
|
||||
a = ((r * 2) + (g * 4) + b) / 7;
|
||||
}
|
||||
|
||||
*dst = a;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_UnlockSurface (surf);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
Color *
|
||||
@@ -1617,10 +1688,14 @@ TFB_DrawCanvas_GetPixel (TFB_Canvas canvas, int x, int y)
|
||||
return c;
|
||||
}
|
||||
|
||||
SDL_LockSurface (surf);
|
||||
|
||||
getpixel = getpixel_for(surf);
|
||||
pixel = (*getpixel)(surf, x, y);
|
||||
SDL_GetRGBA (pixel, surf->format, &c.r, &c.g, &c.b, &c.a);
|
||||
|
||||
SDL_UnlockSurface (surf);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
@@ -1726,6 +1801,7 @@ BOOLEAN
|
||||
TFB_DrawCanvas_Intersect (TFB_Canvas canvas1, POINT c1org,
|
||||
TFB_Canvas canvas2, POINT c2org, const RECT *interRect)
|
||||
{
|
||||
BOOLEAN ret = FALSE;
|
||||
SDL_Surface *surf1 = canvas1;
|
||||
SDL_Surface *surf2 = canvas2;
|
||||
int x, y;
|
||||
@@ -1733,6 +1809,9 @@ TFB_DrawCanvas_Intersect (TFB_Canvas canvas1, POINT c1org,
|
||||
Uint32 s1mask, s2mask;
|
||||
GetPixelFn getpixel1, getpixel2;
|
||||
|
||||
SDL_LockSurface (surf1);
|
||||
SDL_LockSurface (surf2);
|
||||
|
||||
getpixel1 = getpixel_for (surf1);
|
||||
getpixel2 = getpixel_for (surf2);
|
||||
|
||||
@@ -1774,10 +1853,15 @@ TFB_DrawCanvas_Intersect (TFB_Canvas canvas1, POINT c1org,
|
||||
Uint32 p2 = getpixel2 (surf2, x + c2org.x, y + c2org.y) & s2mask;
|
||||
|
||||
if (p1 != s1key && p2 != s2key)
|
||||
return TRUE; // pixel collision
|
||||
{ // pixel collision
|
||||
ret = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// no pixel collision
|
||||
return FALSE;
|
||||
SDL_UnlockSurface (surf2);
|
||||
SDL_UnlockSurface (surf1);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -118,6 +118,7 @@ void TFB_DrawImage_FilledImage (TFB_Image *img, int x, int y, int scale,
|
||||
void TFB_DrawImage_FontChar (TFB_Char *, TFB_Image *backing, int x, int y,
|
||||
TFB_Image *target);
|
||||
|
||||
TFB_Canvas TFB_DrawCanvas_LoadFromFile (void *dir, const char *fileName);
|
||||
TFB_Canvas TFB_DrawCanvas_New_TrueColor (int w, int h, BOOLEAN hasalpha);
|
||||
TFB_Canvas TFB_DrawCanvas_New_ForScreen (int w, int h, BOOLEAN withalpha);
|
||||
TFB_Canvas TFB_DrawCanvas_New_Paletted (int w, int h, Color palette[256],
|
||||
@@ -157,6 +158,8 @@ void TFB_DrawCanvas_FontChar (TFB_Char *, TFB_Image *backing, int x, int y,
|
||||
void TFB_DrawCanvas_CopyRect (TFB_Canvas source, const RECT *srcRect,
|
||||
TFB_Canvas target, POINT dstPt);
|
||||
|
||||
BOOLEAN TFB_DrawCanvas_GetFontCharData (TFB_Canvas canvas, BYTE *outData,
|
||||
unsigned dataPitch);
|
||||
Color *TFB_DrawCanvas_ExtractPalette (TFB_Canvas canvas);
|
||||
void TFB_DrawCanvas_SetPalette (TFB_Canvas target, Color palette[256]);
|
||||
int TFB_DrawCanvas_GetTransparentIndex (TFB_Canvas canvas);
|
||||
@@ -177,6 +180,8 @@ Color TFB_DrawCanvas_GetPixel (TFB_Canvas canvas, int x, int y);
|
||||
BOOLEAN TFB_DrawCanvas_Intersect (TFB_Canvas canvas1, POINT c1org,
|
||||
TFB_Canvas canvas2, POINT c2org, const RECT *interRect);
|
||||
|
||||
const char *TFB_DrawCanvas_GetError (void);
|
||||
|
||||
TFB_Canvas TFB_GetScreenCanvas (SCREEN screen);
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user