196 lines
4.9 KiB
C
196 lines
4.9 KiB
C
/*******************************************************************************
|
|
*
|
|
* Functions and data structures used to maintain a single list of glyph
|
|
* names. The list is sorted alphabetically and each name appears only
|
|
* once. After all font information has been read, the 'index' field of
|
|
* each GLYPHNAME structure is initialized, so future sorts/searches can
|
|
* be done without comparing strings.
|
|
*
|
|
*/
|
|
|
|
#include <string.h>
|
|
#include "psdrv.h"
|
|
#include "debugtools.h"
|
|
|
|
DEFAULT_DEBUG_CHANNEL(psdrv);
|
|
|
|
#define GLYPHLIST_ALLOCSIZE 1024
|
|
|
|
static GLYPHNAME **glyphList = NULL;
|
|
static INT glyphListSize = 0;
|
|
static BOOL glyphNamesIndexed = TRUE;
|
|
|
|
/*******************************************************************************
|
|
* PSDRV_GlyphListInit
|
|
*
|
|
* Allocates initial block of memory for the glyph list and copies pointers to
|
|
* the AGL glyph names into it; returns 0 on success, 1 on failure
|
|
*
|
|
*/
|
|
INT PSDRV_GlyphListInit()
|
|
{
|
|
INT i;
|
|
|
|
/*
|
|
* Compute the smallest multiple of GLYPHLIST_ALLOCSIZE that is
|
|
* greater than or equal to PSDRV_AGLGlyphNamesSize
|
|
*
|
|
*/
|
|
glyphListSize = PSDRV_AGLGlyphNamesSize;
|
|
i = ((glyphListSize + GLYPHLIST_ALLOCSIZE - 1) / GLYPHLIST_ALLOCSIZE) *
|
|
GLYPHLIST_ALLOCSIZE;
|
|
|
|
TRACE("glyphList will initially hold %i glyph names\n", i);
|
|
|
|
glyphList = (GLYPHNAME **) HeapAlloc(PSDRV_Heap, 0,
|
|
i * sizeof(GLYPHNAME *));
|
|
if (glyphList == NULL)
|
|
{
|
|
ERR("Failed to allocate %i bytes of memory\n", i * sizeof(GLYPHNAME *));
|
|
return 1;
|
|
}
|
|
|
|
for (i = 0; i < glyphListSize; ++i)
|
|
glyphList[i] = PSDRV_AGLGlyphNames + i;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* GlyphListInsert
|
|
*
|
|
* Inserts a copy of the glyph name into the list at the index, growing the
|
|
* list if necessary; returns index on success (-1 on failure)
|
|
*
|
|
*/
|
|
inline static INT GlyphListInsert(LPCSTR szName, INT index)
|
|
{
|
|
GLYPHNAME *g;
|
|
|
|
g = HeapAlloc(PSDRV_Heap, 0, sizeof(GLYPHNAME) + strlen(szName) + 1);
|
|
if (g == NULL)
|
|
{
|
|
ERR("Failed to allocate %i bytes of memory\n",
|
|
sizeof(GLYPHNAME) + strlen(szName) + 1);
|
|
return -1;
|
|
}
|
|
|
|
g->index = -1;
|
|
g->sz = (LPSTR)(g + 1);
|
|
strcpy((LPSTR)g->sz, szName);
|
|
|
|
if (glyphListSize % GLYPHLIST_ALLOCSIZE == 0) /* grow the list? */
|
|
{
|
|
GLYPHNAME **newGlyphList;
|
|
|
|
newGlyphList = (GLYPHNAME **) HeapReAlloc(PSDRV_Heap, 0, glyphList,
|
|
(glyphListSize + GLYPHLIST_ALLOCSIZE) * sizeof(GLYPHNAME *));
|
|
if (newGlyphList == NULL)
|
|
{
|
|
ERR("Failed to allocate %i bytes of memory\n", (glyphListSize +
|
|
GLYPHLIST_ALLOCSIZE) * sizeof (GLYPHNAME *));
|
|
HeapFree(PSDRV_Heap, 0, g);
|
|
return -1;
|
|
}
|
|
|
|
glyphList = newGlyphList;
|
|
|
|
TRACE("glyphList will now hold %i glyph names\n",
|
|
glyphListSize + GLYPHLIST_ALLOCSIZE);
|
|
}
|
|
|
|
if (index < glyphListSize)
|
|
{
|
|
memmove(glyphList + (index + 1), glyphList + index,
|
|
(glyphListSize - index) * sizeof(GLYPHNAME *));
|
|
}
|
|
|
|
glyphList[index] = g;
|
|
++glyphListSize;
|
|
glyphNamesIndexed = FALSE;
|
|
|
|
TRACE("Added '%s' at glyphList[%i] (glyphListSize now %i)\n",
|
|
glyphList[index]->sz, index, glyphListSize);
|
|
|
|
return index;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* GlyphListSearch
|
|
*
|
|
* Searches the specified portion of the list for the glyph name and inserts it
|
|
* in the list if necessary; returns the index at which the name (now) resides
|
|
* (-1 if unable to insert it)
|
|
*
|
|
*/
|
|
static INT GlyphListSearch(LPCSTR szName, INT loIndex, INT hiIndex)
|
|
{
|
|
INT midIndex, cmpResult;
|
|
|
|
while (1)
|
|
{
|
|
if (loIndex > hiIndex)
|
|
return GlyphListInsert(szName, loIndex);
|
|
|
|
midIndex = (loIndex + hiIndex) >> 1;
|
|
|
|
cmpResult = strcmp(szName, glyphList[midIndex]->sz);
|
|
|
|
if (cmpResult == 0)
|
|
{
|
|
TRACE("Found '%s' at glyphList[%i]\n", glyphList[midIndex]->sz,
|
|
midIndex);
|
|
return midIndex;
|
|
}
|
|
|
|
if (cmpResult < 0)
|
|
hiIndex = midIndex - 1;
|
|
else
|
|
loIndex = midIndex + 1;
|
|
}
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* PSDRV_GlyphName
|
|
*
|
|
* Searches the glyph name list for the provided name, adds it to the list if
|
|
* necessary, and returns a pointer to it (NULL if unable to add it)
|
|
*
|
|
*/
|
|
const GLYPHNAME *PSDRV_GlyphName(LPCSTR szName)
|
|
{
|
|
INT index;
|
|
|
|
TRACE("'%s'\n", szName);
|
|
|
|
index = GlyphListSearch(szName, 0, glyphListSize - 1);
|
|
if (index < 0)
|
|
return NULL;
|
|
|
|
return glyphList[index];
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* PSDRV_IndexGlyphList
|
|
*
|
|
* Initializes index member of all GLYPHNAME structures
|
|
*
|
|
*/
|
|
VOID PSDRV_IndexGlyphList()
|
|
{
|
|
INT i;
|
|
|
|
if (glyphNamesIndexed == TRUE)
|
|
return;
|
|
|
|
TRACE("%i glyph names:\n", glyphListSize);
|
|
|
|
for (i = 0; i < glyphListSize; ++i)
|
|
{
|
|
glyphList[i]->index = i;
|
|
TRACE(" glyphList[%i] -> '%s'\n", i, glyphList[i]->sz);
|
|
}
|
|
|
|
glyphNamesIndexed = TRUE;
|
|
}
|