Unicode support for fonts.
git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@1546 8092fc87-c524-0410-9efc-e669fe64eaf9
This commit is contained in:
@@ -324,8 +324,21 @@ _text_blt (PRECT pClipRect, PRIMITIVEPTR PrimPtr)
|
||||
|
||||
static inline FRAME_DESC *
|
||||
getCharFrame (FONT_DESC *fontPtr, wchar_t ch) {
|
||||
if (ch > MAX_CHARS)
|
||||
wchar_t pageStart = ch & 0xff00;
|
||||
|
||||
FONT_PAGE *page = fontPtr->fontPages;
|
||||
for (;;)
|
||||
{
|
||||
if (page == NULL)
|
||||
return NULL;
|
||||
return &fontPtr->CharDesc[ch - FIRST_CHAR];
|
||||
|
||||
if (page->pageStart == pageStart)
|
||||
break;
|
||||
|
||||
page = page->next;
|
||||
}
|
||||
|
||||
return &page->charDesc[ch - page->firstChar];
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -19,19 +19,39 @@
|
||||
#ifndef _FONT_H
|
||||
#define _FONT_H
|
||||
|
||||
#define FIRST_CHAR (UNICODE)' '
|
||||
// keep MAX_CHARS under 256 for now
|
||||
#define MAX_CHARS 255
|
||||
// MAX_CHARS gets cast to UNICODE in a few places and is used in math
|
||||
// UNICODE is defined to BYTE, all strings attached
|
||||
#define MAX_DELTAS 100
|
||||
|
||||
typedef struct FontPage
|
||||
{
|
||||
struct FontPage *next;
|
||||
wchar_t pageStart;
|
||||
wchar_t firstChar;
|
||||
size_t numChars;
|
||||
FRAME_DESC *charDesc;
|
||||
} FONT_PAGE;
|
||||
typedef FONT_PAGE *PFONT_PAGE;
|
||||
|
||||
static inline FONT_PAGE *
|
||||
AllocFontPage (int numChars)
|
||||
{
|
||||
FONT_PAGE *result = HMalloc (sizeof (FONT_PAGE));
|
||||
result->charDesc = HCalloc (numChars * sizeof *result->charDesc);
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline void
|
||||
FreeFontPage (FONT_PAGE *page)
|
||||
{
|
||||
HFree (page->charDesc);
|
||||
HFree (page);
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
FONT_REF FontRef;
|
||||
|
||||
BYTE Leading;
|
||||
FRAME_DESC CharDesc[MAX_CHARS];
|
||||
FONT_PAGE *fontPages;
|
||||
} FONT_DESC;
|
||||
typedef FONT_DESC *PFONT_DESC;
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "sdluio.h"
|
||||
#include "libs/file.h"
|
||||
#include "libs/reslib.h"
|
||||
#include "../font.h"
|
||||
#include "primitives.h"
|
||||
|
||||
|
||||
@@ -105,9 +106,8 @@ process_image (FRAMEPTR FramePtr, SDL_Surface *img[], AniData *ani, int cel_ct)
|
||||
}
|
||||
|
||||
static void
|
||||
process_font (FRAMEPTR FramePtr, SDL_Surface *img[], int cel_ct)
|
||||
processFontChar (FRAMEPTR FramePtr, SDL_Surface *surf, int charInd)
|
||||
{
|
||||
int hx, hy;
|
||||
int x,y;
|
||||
Uint8 r,g,b,a;
|
||||
Uint32 p;
|
||||
@@ -117,26 +117,25 @@ process_font (FRAMEPTR FramePtr, SDL_Surface *img[], int cel_ct)
|
||||
PutPixelFn putpix;
|
||||
|
||||
TYPE_SET (FramePtr->TypeIndexAndFlags, WANT_PIXMAP << FTYPE_SHIFT);
|
||||
INDEX_SET (FramePtr->TypeIndexAndFlags, cel_ct);
|
||||
INDEX_SET (FramePtr->TypeIndexAndFlags, charInd);
|
||||
// XXX: Is this still relevant?
|
||||
|
||||
hx = hy = 0;
|
||||
|
||||
SDL_LockSurface (img[cel_ct]);
|
||||
SDL_LockSurface (surf);
|
||||
|
||||
// convert 32-bit png font to indexed
|
||||
|
||||
new_surf = SDL_CreateRGBSurface (SDL_SWSURFACE, img[cel_ct]->w, img[cel_ct]->h,
|
||||
new_surf = SDL_CreateRGBSurface (SDL_SWSURFACE, surf->w, surf->h,
|
||||
8, 0, 0, 0, 0);
|
||||
|
||||
getpix = getpixel_for (img[cel_ct]);
|
||||
getpix = getpixel_for (surf);
|
||||
putpix = putpixel_for (new_surf);
|
||||
|
||||
for (y = 0; y < img[cel_ct]->h; ++y)
|
||||
for (y = 0; y < surf->h; ++y)
|
||||
{
|
||||
for (x = 0; x < img[cel_ct]->w; ++x)
|
||||
for (x = 0; x < surf->w; ++x)
|
||||
{
|
||||
p = getpix (img[cel_ct], x, y);
|
||||
SDL_GetRGBA (p, img[cel_ct]->format, &r, &g, &b, &a);
|
||||
p = getpix (surf, x, y);
|
||||
SDL_GetRGBA (p, surf->format, &r, &g, &b, &a);
|
||||
|
||||
if (r == 0 && g == 0 && b == 0)
|
||||
putpix (new_surf, x, y, 0);
|
||||
@@ -145,7 +144,9 @@ process_font (FRAMEPTR FramePtr, SDL_Surface *img[], int cel_ct)
|
||||
}
|
||||
}
|
||||
|
||||
colors[0].r = colors[0].g = colors[0].b = 0;
|
||||
colors[0].r = 0;
|
||||
colors[0].g = 0;
|
||||
colors[0].b = 0;
|
||||
for (x = 1; x < 256; ++x)
|
||||
{
|
||||
colors[x].r = 255;
|
||||
@@ -156,20 +157,38 @@ process_font (FRAMEPTR FramePtr, SDL_Surface *img[], int cel_ct)
|
||||
SDL_SetColors (new_surf, colors, 0, 256);
|
||||
SDL_SetColorKey (new_surf, SDL_SRCCOLORKEY, 0);
|
||||
|
||||
SDL_UnlockSurface (img[cel_ct]);
|
||||
SDL_FreeSurface (img[cel_ct]);
|
||||
SDL_UnlockSurface (surf);
|
||||
SDL_FreeSurface (surf);
|
||||
|
||||
img[cel_ct] = new_surf;
|
||||
FramePtr->image = TFB_DrawImage_New (new_surf);
|
||||
surf = FramePtr->image->NormalImg;
|
||||
|
||||
FramePtr->image = TFB_DrawImage_New (img[cel_ct]);
|
||||
img[cel_ct] = FramePtr->image->NormalImg;
|
||||
SetFrameBounds (FramePtr, surf->w + 1, 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.
|
||||
|
||||
FramePtr->HotSpot = MAKE_HOT_SPOT (hx, hy);
|
||||
SetFrameBounds (FramePtr, img[cel_ct]->w, img[cel_ct]->h);
|
||||
{
|
||||
// This tunes the font positioning to be about what it should
|
||||
// TODO: prolly needs a little tweaking still
|
||||
|
||||
int tune_amount = 0;
|
||||
|
||||
if (surf->h == 8)
|
||||
tune_amount = -1;
|
||||
else if (surf->h == 9)
|
||||
tune_amount = -2;
|
||||
else if (surf->h > 9)
|
||||
tune_amount = -3;
|
||||
|
||||
FramePtr->HotSpot = MAKE_HOT_SPOT (0, surf->h + tune_amount);
|
||||
}
|
||||
}
|
||||
|
||||
//stretch_frame
|
||||
// create a new frame of size neww x newh, and blit a scaled version FramePtr into it
|
||||
// stretch_frame
|
||||
// create a new frame of size neww x newh, and blit a scaled version FramePtr
|
||||
// into it.
|
||||
// destroy the old frame if 'destroy' is 1
|
||||
FRAMEPTR stretch_frame (FRAMEPTR FramePtr, int neww, int newh, int destroy)
|
||||
{
|
||||
@@ -181,8 +200,7 @@ FRAMEPTR stretch_frame (FRAMEPTR FramePtr, int neww, int newh, int destroy)
|
||||
type = (UBYTE)TYPE_GET (GetFrameParentDrawable (FramePtr)
|
||||
->FlagsAndIndex) >> FTYPE_SHIFT;
|
||||
NewFrame = CaptureDrawable (
|
||||
CreateDrawable (type, (SIZE)neww, (SIZE)newh, 1)
|
||||
);
|
||||
CreateDrawable (type, (SIZE)neww, (SIZE)newh, 1));
|
||||
tfbImg = FramePtr->image;
|
||||
LockMutex (tfbImg->mutex);
|
||||
src = tfbImg->NormalImg;
|
||||
@@ -222,7 +240,8 @@ void process_rgb_bmp (FRAMEPTR FramePtr, Uint32 *rgba, int maxx, int maxy)
|
||||
UnlockMutex (tfbImg->mutex);
|
||||
}
|
||||
|
||||
void fill_frame_rgb (FRAMEPTR FramePtr, Uint32 color, int x0, int y0, int x, int y)
|
||||
void fill_frame_rgb (FRAMEPTR FramePtr, Uint32 color, int x0, int y0,
|
||||
int x, int y)
|
||||
{
|
||||
SDL_Surface *img;
|
||||
TFB_Image *tfbImg;
|
||||
@@ -570,143 +589,219 @@ _ReleaseCelData (MEM_HANDLE handle)
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
typedef struct BuildCharDesc {
|
||||
SDL_Surface *surface;
|
||||
wchar_t index;
|
||||
} BuildCharDesc;
|
||||
|
||||
int
|
||||
compareBCDIndex(const BuildCharDesc *bcd1, const BuildCharDesc *bcd2) {
|
||||
return (int) bcd1->index - (int) bcd2->index;
|
||||
}
|
||||
|
||||
MEM_HANDLE
|
||||
_GetFontData (uio_Stream *fp, DWORD length)
|
||||
{
|
||||
DWORD cel_ct;
|
||||
COUNT num_entries;
|
||||
FONT_REF FontRef;
|
||||
DIRENTRY FontDir;
|
||||
BOOLEAN found_chars;
|
||||
#define MAX_CELS 256
|
||||
SDL_Surface *img[MAX_CELS] = { 0 };
|
||||
char pattern[PATH_MAX];
|
||||
COUNT numDirEntries;
|
||||
FONT_REF fontRef = 0;
|
||||
DIRENTRY fontDir = 0;
|
||||
BuildCharDesc *bcds = NULL;
|
||||
size_t numBCDs = 0;
|
||||
int dirEntryI;
|
||||
uio_DirHandle *fontDirHandle = NULL;
|
||||
FONTPTR fontPtr;
|
||||
|
||||
if (_cur_resfile_name == 0)
|
||||
return (0);
|
||||
goto err;
|
||||
|
||||
found_chars = FALSE;
|
||||
FontDir = CaptureDirEntryTable (LoadDirEntryTable (contentDir,
|
||||
_cur_resfile_name, ".", match_MATCH_SUBSTRING,
|
||||
&num_entries));
|
||||
while (num_entries--)
|
||||
fontDir = CaptureDirEntryTable (LoadDirEntryTable (contentDir,
|
||||
_cur_resfile_name, ".", match_MATCH_SUBSTRING, &numDirEntries));
|
||||
if (fontDir == 0)
|
||||
goto err;
|
||||
|
||||
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, "%u.", &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 0
|
||||
if (numBCDs == 0)
|
||||
goto err;
|
||||
#endif
|
||||
|
||||
// sort on the character index
|
||||
qsort (bcds, numBCDs, sizeof (BuildCharDesc),
|
||||
(int (*)(const void *, const void *)) compareBCDIndex);
|
||||
|
||||
fontRef = AllocFont (0);
|
||||
if (fontRef == 0)
|
||||
goto err;
|
||||
|
||||
fontPtr = LockFont (fontRef);
|
||||
if (fontPtr == NULL)
|
||||
goto err;
|
||||
|
||||
fontPtr->FontRef = fontRef;
|
||||
fontPtr->Leading = 0;
|
||||
|
||||
char_name = GetDirEntryAddress (SetAbsDirEntryTableIndex (FontDir, num_entries));
|
||||
if (sscanf (char_name, "%u.", (unsigned int*) &cel_ct) == 1
|
||||
&& cel_ct >= FIRST_CHAR
|
||||
&& img[cel_ct -= FIRST_CHAR] == 0
|
||||
&& sprintf (pattern, "%s/%s", _cur_resfile_name, char_name)
|
||||
&& (img[cel_ct] = sdluio_loadImage (contentDir, pattern)))
|
||||
{
|
||||
if (img[cel_ct]->w > 0
|
||||
&& img[cel_ct]->h > 0
|
||||
&& img[cel_ct]->format->BitsPerPixel >= 8)
|
||||
found_chars = TRUE;
|
||||
else
|
||||
size_t startBCD = 0;
|
||||
int pageStart;
|
||||
FONT_PAGE **pageEndPtr = &fontPtr->fontPages;
|
||||
while (startBCD < numBCDs)
|
||||
{
|
||||
SDL_FreeSurface (img[cel_ct]);
|
||||
img[cel_ct] = 0;
|
||||
}
|
||||
}
|
||||
// Process one character page.
|
||||
size_t endBCD;
|
||||
pageStart = bcds[startBCD].index & 0xff00;
|
||||
|
||||
}
|
||||
DestroyDirEntryTable (ReleaseDirEntryTable (FontDir));
|
||||
endBCD = startBCD;
|
||||
while (endBCD < numBCDs &&
|
||||
(bcds[endBCD].index & 0xff00) == pageStart)
|
||||
endBCD++;
|
||||
|
||||
FontRef = 0;
|
||||
if (found_chars && (FontRef = AllocFont (0)))
|
||||
{
|
||||
FONTPTR FontPtr;
|
||||
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;
|
||||
|
||||
cel_ct = MAX_CELS; // MAX_CHARS;
|
||||
if ((FontPtr = LockFont (FontRef)) == 0)
|
||||
for (bcdI = startBCD; bcdI < endBCD; bcdI++)
|
||||
{
|
||||
while (cel_ct--)
|
||||
// Process one character.
|
||||
BuildCharDesc *bcd = &bcds[bcdI];
|
||||
FRAME_DESC *destFrame =
|
||||
&page->charDesc[bcd->index - page->firstChar];
|
||||
|
||||
if (destFrame->image != NULL)
|
||||
{
|
||||
if (img[cel_ct])
|
||||
SDL_FreeSurface (img[cel_ct]);
|
||||
// There's already an image for this character.
|
||||
#ifdef DEBUG
|
||||
fprintf (stderr, "Duplicate image for characted %d "
|
||||
"for font %s.\n", (int) bcd->index,
|
||||
_cur_resfile_name);
|
||||
#endif
|
||||
SDL_FreeSurface (bcd->surface);
|
||||
continue;
|
||||
}
|
||||
|
||||
mem_release (FontRef);
|
||||
FontRef = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
FRAMEPTR FramePtr;
|
||||
processFontChar (destFrame, bcd->surface,
|
||||
bcd->index - page->firstChar);
|
||||
// bcd->surface is handed over to destFrame.
|
||||
// Don't access it through bcd->surface any more.
|
||||
// It may be freed from within ProcessFontChar().
|
||||
|
||||
FontPtr->FontRef = FontRef;
|
||||
FontPtr->Leading = 0;
|
||||
FramePtr = &FontPtr->CharDesc[cel_ct];
|
||||
while (--FramePtr, cel_ct--)
|
||||
{
|
||||
if (img[cel_ct])
|
||||
{
|
||||
process_font (FramePtr, img, cel_ct);
|
||||
SetFrameBounds (FramePtr, GetFrameWidth (FramePtr) + 1, GetFrameHeight (FramePtr) + 1);
|
||||
|
||||
if (img[0])
|
||||
{
|
||||
// This tunes the font positioning to be about what it should
|
||||
// TODO: prolly needs a little tweaking still
|
||||
|
||||
int tune_amount = 0;
|
||||
|
||||
if (img[0]->h == 8)
|
||||
tune_amount = -1;
|
||||
else if (img[0]->h == 9)
|
||||
tune_amount = -2;
|
||||
else if (img[0]->h > 9)
|
||||
tune_amount = -3;
|
||||
|
||||
FramePtr->HotSpot = MAKE_HOT_SPOT (0, img[0]->h + tune_amount);
|
||||
}
|
||||
|
||||
if (GetFrameHeight (FramePtr) > FontPtr->Leading)
|
||||
FontPtr->Leading = GetFrameHeight (FramePtr);
|
||||
if (GetFrameHeight (destFrame) > fontPtr->Leading)
|
||||
fontPtr->Leading = GetFrameHeight (destFrame);
|
||||
}
|
||||
}
|
||||
++FontPtr->Leading;
|
||||
|
||||
UnlockFont (FontRef);
|
||||
startBCD = endBCD;
|
||||
}
|
||||
*pageEndPtr = NULL;
|
||||
}
|
||||
|
||||
fontPtr->Leading++;
|
||||
UnlockFont (fontRef);
|
||||
|
||||
HFree (bcds);
|
||||
|
||||
(void) fp; /* Satisfying compiler (unused parameter) */
|
||||
(void) length; /* Satisfying compiler (unused parameter) */
|
||||
return (FontRef);
|
||||
return fontRef;
|
||||
|
||||
err:
|
||||
if (fontRef != 0)
|
||||
mem_release (fontRef);
|
||||
|
||||
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));
|
||||
return 0;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
_ReleaseFontData (MEM_HANDLE handle)
|
||||
{
|
||||
FONTPTR FontPtr;
|
||||
|
||||
if ((FontPtr = LockFont (handle)) == 0)
|
||||
return (FALSE);
|
||||
FONTPTR font = LockFont (handle);
|
||||
if (font == NULL)
|
||||
return FALSE;
|
||||
|
||||
{
|
||||
int cel_ct;
|
||||
FRAMEPTR FramePtr;
|
||||
FONT_PAGE *page;
|
||||
FONT_PAGE *nextPage;
|
||||
|
||||
cel_ct = MAX_CHARS;
|
||||
|
||||
FramePtr = &FontPtr->CharDesc[cel_ct];
|
||||
while (--FramePtr, cel_ct--)
|
||||
for (page = font->fontPages; page != NULL; page = nextPage)
|
||||
{
|
||||
TFB_Image *img = FramePtr->image;
|
||||
if (img)
|
||||
size_t charI;
|
||||
for (charI = 0; charI < page->numChars; charI++)
|
||||
{
|
||||
FramePtr->image = NULL;
|
||||
FRAME_DESC *frame = &page->charDesc[charI];
|
||||
|
||||
TFB_DrawScreen_DeleteImage (img);
|
||||
if (frame->image == NULL)
|
||||
continue;
|
||||
|
||||
TFB_DrawScreen_DeleteImage (frame->image);
|
||||
}
|
||||
|
||||
nextPage = page->next;
|
||||
FreeFontPage (page);
|
||||
}
|
||||
}
|
||||
|
||||
UnlockFont (handle);
|
||||
mem_release (handle);
|
||||
|
||||
return (TRUE);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// _request_drawable was in libs/graphics/drawable.c before modularization
|
||||
|
||||
Reference in New Issue
Block a user