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:
@@ -471,6 +471,10 @@ SOURCE=..\..\src\libs\graphics\gfxintrn.h
|
|||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\src\libs\graphics\gfxload.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
SOURCE=..\..\src\libs\graphics\intersec.c
|
SOURCE=..\..\src\libs\graphics\intersec.c
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
uqm_SUBDIRS="sdl"
|
uqm_SUBDIRS="sdl"
|
||||||
uqm_CFILES="boxint.c clipline.c cmap.c context.c drawable.c filegfx.c
|
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
|
font.c frame.c gfx_common.c intersec.c loaddisp.c
|
||||||
pixmap.c resgfx.c tfb_draw.c tfb_prim.c widgets.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 GFXMODULE_SDL
|
||||||
|
|
||||||
#ifdef WIN32
|
|
||||||
#include <io.h>
|
|
||||||
#endif
|
|
||||||
#include <fcntl.h>
|
|
||||||
|
|
||||||
#include "options.h"
|
|
||||||
#include "port.h"
|
#include "port.h"
|
||||||
|
#include "libs/gfxlib.h"
|
||||||
|
#include "libs/graphics/tfb_draw.h"
|
||||||
#include "sdl_common.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"
|
#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
|
// stretch_frame
|
||||||
// create a new frame of size neww x newh, and blit a scaled version FramePtr
|
// create a new frame of size neww x newh, and blit a scaled version FramePtr
|
||||||
// into it.
|
// 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));
|
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
|
#endif
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
#include "libs/memlib.h"
|
#include "libs/memlib.h"
|
||||||
#include "primitives.h"
|
#include "primitives.h"
|
||||||
#include "palette.h"
|
#include "palette.h"
|
||||||
|
#include "sdluio.h"
|
||||||
#include "rotozoom.h"
|
#include "rotozoom.h"
|
||||||
#include "options.h"
|
#include "options.h"
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
@@ -43,6 +44,15 @@ TFB_DrawCanvas_Initialize (void)
|
|||||||
// need error correction here
|
// 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
|
void
|
||||||
TFB_DrawCanvas_Line (int x1, int y1, int x2, int y2, Color color,
|
TFB_DrawCanvas_Line (int x1, int y1, int x2, int y2, Color color,
|
||||||
TFB_Canvas target)
|
TFB_Canvas target)
|
||||||
@@ -590,6 +600,23 @@ TFB_DrawCanvas_New_RotationTarget (TFB_Canvas src_canvas, int angle)
|
|||||||
return newsurf;
|
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
|
void
|
||||||
TFB_DrawCanvas_Delete (TFB_Canvas canvas)
|
TFB_DrawCanvas_Delete (TFB_Canvas canvas)
|
||||||
{
|
{
|
||||||
@@ -603,7 +630,51 @@ TFB_DrawCanvas_Delete (TFB_Canvas canvas)
|
|||||||
{
|
{
|
||||||
SDL_FreeSurface (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 *
|
Color *
|
||||||
@@ -1617,10 +1688,14 @@ TFB_DrawCanvas_GetPixel (TFB_Canvas canvas, int x, int y)
|
|||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SDL_LockSurface (surf);
|
||||||
|
|
||||||
getpixel = getpixel_for(surf);
|
getpixel = getpixel_for(surf);
|
||||||
pixel = (*getpixel)(surf, x, y);
|
pixel = (*getpixel)(surf, x, y);
|
||||||
SDL_GetRGBA (pixel, surf->format, &c.r, &c.g, &c.b, &c.a);
|
SDL_GetRGBA (pixel, surf->format, &c.r, &c.g, &c.b, &c.a);
|
||||||
|
|
||||||
|
SDL_UnlockSurface (surf);
|
||||||
|
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1726,6 +1801,7 @@ BOOLEAN
|
|||||||
TFB_DrawCanvas_Intersect (TFB_Canvas canvas1, POINT c1org,
|
TFB_DrawCanvas_Intersect (TFB_Canvas canvas1, POINT c1org,
|
||||||
TFB_Canvas canvas2, POINT c2org, const RECT *interRect)
|
TFB_Canvas canvas2, POINT c2org, const RECT *interRect)
|
||||||
{
|
{
|
||||||
|
BOOLEAN ret = FALSE;
|
||||||
SDL_Surface *surf1 = canvas1;
|
SDL_Surface *surf1 = canvas1;
|
||||||
SDL_Surface *surf2 = canvas2;
|
SDL_Surface *surf2 = canvas2;
|
||||||
int x, y;
|
int x, y;
|
||||||
@@ -1733,6 +1809,9 @@ TFB_DrawCanvas_Intersect (TFB_Canvas canvas1, POINT c1org,
|
|||||||
Uint32 s1mask, s2mask;
|
Uint32 s1mask, s2mask;
|
||||||
GetPixelFn getpixel1, getpixel2;
|
GetPixelFn getpixel1, getpixel2;
|
||||||
|
|
||||||
|
SDL_LockSurface (surf1);
|
||||||
|
SDL_LockSurface (surf2);
|
||||||
|
|
||||||
getpixel1 = getpixel_for (surf1);
|
getpixel1 = getpixel_for (surf1);
|
||||||
getpixel2 = getpixel_for (surf2);
|
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;
|
Uint32 p2 = getpixel2 (surf2, x + c2org.x, y + c2org.y) & s2mask;
|
||||||
|
|
||||||
if (p1 != s1key && p2 != s2key)
|
if (p1 != s1key && p2 != s2key)
|
||||||
return TRUE; // pixel collision
|
{ // pixel collision
|
||||||
|
ret = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// no pixel collision
|
SDL_UnlockSurface (surf2);
|
||||||
return FALSE;
|
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,
|
void TFB_DrawImage_FontChar (TFB_Char *, TFB_Image *backing, int x, int y,
|
||||||
TFB_Image *target);
|
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_TrueColor (int w, int h, BOOLEAN hasalpha);
|
||||||
TFB_Canvas TFB_DrawCanvas_New_ForScreen (int w, int h, BOOLEAN withalpha);
|
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],
|
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,
|
void TFB_DrawCanvas_CopyRect (TFB_Canvas source, const RECT *srcRect,
|
||||||
TFB_Canvas target, POINT dstPt);
|
TFB_Canvas target, POINT dstPt);
|
||||||
|
|
||||||
|
BOOLEAN TFB_DrawCanvas_GetFontCharData (TFB_Canvas canvas, BYTE *outData,
|
||||||
|
unsigned dataPitch);
|
||||||
Color *TFB_DrawCanvas_ExtractPalette (TFB_Canvas canvas);
|
Color *TFB_DrawCanvas_ExtractPalette (TFB_Canvas canvas);
|
||||||
void TFB_DrawCanvas_SetPalette (TFB_Canvas target, Color palette[256]);
|
void TFB_DrawCanvas_SetPalette (TFB_Canvas target, Color palette[256]);
|
||||||
int TFB_DrawCanvas_GetTransparentIndex (TFB_Canvas canvas);
|
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,
|
BOOLEAN TFB_DrawCanvas_Intersect (TFB_Canvas canvas1, POINT c1org,
|
||||||
TFB_Canvas canvas2, POINT c2org, const RECT *interRect);
|
TFB_Canvas canvas2, POINT c2org, const RECT *interRect);
|
||||||
|
|
||||||
|
const char *TFB_DrawCanvas_GetError (void);
|
||||||
|
|
||||||
TFB_Canvas TFB_GetScreenCanvas (SCREEN screen);
|
TFB_Canvas TFB_GetScreenCanvas (SCREEN screen);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user