Unicode encodings for PostScript fonts.
This commit is contained in:
parent
0c63012b6d
commit
657c4afaec
|
@ -7,6 +7,7 @@
|
|||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h> /* qsort() & bsearch() */
|
||||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
#include <dirent.h>
|
||||
|
@ -28,12 +29,13 @@ FONTFAMILY *PSDRV_AFMFontList = NULL;
|
|||
* CheckMetrics
|
||||
*
|
||||
* Check an AFMMETRICS structure to make sure all elements have been properly
|
||||
* filled in.
|
||||
* filled in. (Don't check UV or L.)
|
||||
*
|
||||
*/
|
||||
static const AFMMETRICS badMetrics =
|
||||
{
|
||||
INT_MIN, /* C */
|
||||
INT_MIN, /* UV */
|
||||
FLT_MAX, /* WX */
|
||||
NULL, /* N */
|
||||
{ FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX }, /* B */
|
||||
|
@ -57,7 +59,8 @@ inline static BOOL CheckMetrics(const AFMMETRICS *metrics)
|
|||
/*******************************************************************************
|
||||
* FreeAFM
|
||||
*
|
||||
* Free an AFM structure and any subsidiary objects that have been allocated
|
||||
* Free an AFM structure and any subsidiary objects that have been allocated.
|
||||
* AFM must have been allocated with HEAP_ZERO_MEMORY.
|
||||
*
|
||||
*/
|
||||
static void FreeAFM(AFM *afm)
|
||||
|
@ -76,7 +79,6 @@ static void FreeAFM(AFM *afm)
|
|||
HeapFree(PSDRV_Heap, 0, afm);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************
|
||||
*
|
||||
* PSDRV_AFMGetCharMetrics
|
||||
|
@ -191,6 +193,55 @@ static BOOL PSDRV_AFMGetCharMetrics(AFM *afm, FILE *fp)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* BuildEncoding
|
||||
*
|
||||
* Builds a custom encoding vector if necessary. Leaves vector in the same
|
||||
* order as the afm->Metrics array; see SortFontMetrics().
|
||||
*
|
||||
*/
|
||||
static BOOL BuildEncoding(AFM *afm)
|
||||
{
|
||||
UNICODEVECTOR *uv;
|
||||
UNICODEGLYPH *ug;
|
||||
int i;
|
||||
|
||||
if (strcmp(afm->EncodingScheme, "FontSpecific") != 0)
|
||||
{
|
||||
afm->Encoding = &PSDRV_AdobeGlyphList;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
uv = HeapAlloc(PSDRV_Heap, 0, sizeof(UNICODEVECTOR) +
|
||||
afm->NumofMetrics * sizeof(UNICODEGLYPH));
|
||||
if (uv == NULL)
|
||||
return FALSE;
|
||||
|
||||
afm->Encoding = uv;
|
||||
ug = (UNICODEGLYPH *)(uv + 1);
|
||||
uv->glyphs = ug;
|
||||
uv->size = afm->NumofMetrics;
|
||||
|
||||
for (i = 0; i < afm->NumofMetrics; ++i)
|
||||
{
|
||||
ug[i].name = afm->Metrics[i].N;
|
||||
|
||||
if (afm->Metrics[i].C < 0) /* unencoded glyph */
|
||||
{
|
||||
WARN("Glyph '%s' in font '%s' has no encoding\n", ug[i].name->sz,
|
||||
afm->FullName);
|
||||
ug[i].UV = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
ug[i].UV = afm->Metrics[i].C | 0xf000; /* private use area? */
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************
|
||||
*
|
||||
* PSDRV_AFMParse
|
||||
|
@ -411,6 +462,12 @@ static AFM *PSDRV_AFMParse(char const *file)
|
|||
if(afm->Weight == 0)
|
||||
afm->Weight = FW_NORMAL;
|
||||
|
||||
if (BuildEncoding(afm) == FALSE)
|
||||
{
|
||||
FreeAFM(afm);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return afm;
|
||||
}
|
||||
|
||||
|
@ -559,13 +616,136 @@ static void PSDRV_DumpFontList(void)
|
|||
|
||||
for(family = PSDRV_AFMFontList; family; family = family->next) {
|
||||
TRACE("Family '%s'\n", family->FamilyName);
|
||||
for(afmle = family->afmlist; afmle; afmle = afmle->next) {
|
||||
TRACE("\tFontName '%s'\n", afmle->afm->FontName);
|
||||
for(afmle = family->afmlist; afmle; afmle = afmle->next)
|
||||
{
|
||||
INT i;
|
||||
|
||||
TRACE("\tFontName '%s' (%i glyphs):\n", afmle->afm->FontName,
|
||||
afmle->afm->NumofMetrics);
|
||||
|
||||
for (i = 0; i < afmle->afm->NumofMetrics; ++i)
|
||||
{
|
||||
TRACE("\t\tU+%.4lX; C %i; N '%s'\n", afmle->afm->Metrics[i].UV,
|
||||
afmle->afm->Metrics[i].C, afmle->afm->Metrics[i].N->sz);
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* SortFontMetrics
|
||||
*
|
||||
* Initializes the UV member of each glyph's AFMMETRICS and sorts each font's
|
||||
* Metrics by Unicode Value.
|
||||
*
|
||||
*/
|
||||
static int UnicodeGlyphByNameIndex(const UNICODEGLYPH *a, const UNICODEGLYPH *b)
|
||||
{
|
||||
return a->name->index - b->name->index;
|
||||
}
|
||||
|
||||
static int UnicodeGlyphByUV(const UNICODEGLYPH *a, const UNICODEGLYPH *b)
|
||||
{
|
||||
return a->UV - b->UV;
|
||||
}
|
||||
|
||||
static int AFMMetricsByUV(const AFMMETRICS *a, const AFMMETRICS *b)
|
||||
{
|
||||
return a->UV - b->UV;
|
||||
}
|
||||
|
||||
static BOOL SortFontMetrics()
|
||||
{
|
||||
UNICODEGLYPH *aglCopy = NULL;
|
||||
FONTFAMILY *family = PSDRV_AFMFontList;
|
||||
|
||||
while (family != NULL)
|
||||
{
|
||||
AFMLISTENTRY *afmle = family->afmlist;
|
||||
|
||||
while (afmle != NULL)
|
||||
{
|
||||
AFM *afm = afmle->afm; /* should always be valid */
|
||||
INT i;
|
||||
|
||||
if (afm->Encoding == &PSDRV_AdobeGlyphList)
|
||||
{
|
||||
if (aglCopy == NULL) /* do this once, if necessary */
|
||||
{
|
||||
aglCopy = HeapAlloc(PSDRV_Heap, 0,
|
||||
PSDRV_AdobeGlyphList.size * sizeof(UNICODEGLYPH));
|
||||
if (aglCopy == NULL)
|
||||
return FALSE;
|
||||
|
||||
memcpy(aglCopy, PSDRV_AdobeGlyphList.glyphs,
|
||||
PSDRV_AdobeGlyphList.size * sizeof(UNICODEGLYPH));
|
||||
|
||||
qsort(aglCopy, PSDRV_AdobeGlyphList.size,
|
||||
sizeof(UNICODEGLYPH),
|
||||
(__compar_fn_t)UnicodeGlyphByNameIndex);
|
||||
}
|
||||
|
||||
for (i = 0; i < afm->NumofMetrics; ++i)
|
||||
{
|
||||
UNICODEGLYPH ug, *pug;
|
||||
|
||||
ug.name = afm->Metrics[i].N;
|
||||
ug.UV = -1;
|
||||
|
||||
pug = bsearch(&ug, aglCopy, PSDRV_AdobeGlyphList.size,
|
||||
sizeof(UNICODEGLYPH),
|
||||
(__compar_fn_t)UnicodeGlyphByNameIndex);
|
||||
if (pug == NULL)
|
||||
{
|
||||
WARN("Glyph '%s' in font '%s' does not have a UV\n",
|
||||
ug.name->sz, afm->FullName);
|
||||
afm->Metrics[i].UV = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
afm->Metrics[i].UV = pug->UV;
|
||||
}
|
||||
}
|
||||
}
|
||||
else /* FontSpecific encoding or TrueType font */
|
||||
{
|
||||
for (i = 0; i < afm->NumofMetrics; ++i)
|
||||
afm->Metrics[i].UV = afm->Encoding->glyphs[i].UV;
|
||||
|
||||
/* typecast avoids compiler warning */
|
||||
qsort((void *)(afm->Encoding->glyphs), afm->Encoding->size,
|
||||
sizeof(UNICODEGLYPH), (__compar_fn_t)UnicodeGlyphByUV);
|
||||
|
||||
for (i = 0; i < afm->Encoding->size; ++i)
|
||||
if (afm->Encoding->glyphs[i].UV >= 0)
|
||||
break;
|
||||
|
||||
afm->Encoding->size -= i; /* Ignore unencoded glyphs */
|
||||
afm->Encoding->glyphs += i; /* from now on */
|
||||
}
|
||||
|
||||
qsort(afm->Metrics, afm->NumofMetrics, sizeof(AFMMETRICS),
|
||||
(__compar_fn_t)AFMMetricsByUV);
|
||||
|
||||
for (i = 0; i < afm->NumofMetrics; ++i)
|
||||
if (afm->Metrics[i].UV >= 0)
|
||||
break;
|
||||
|
||||
afm->NumofMetrics -= i; /* Ignore unencoded glyphs here too */
|
||||
afm->Metrics += i;
|
||||
|
||||
afmle = afmle->next;
|
||||
}
|
||||
|
||||
family = family->next;
|
||||
}
|
||||
|
||||
if (aglCopy != NULL)
|
||||
HeapFree(PSDRV_Heap, 0, aglCopy);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/***********************************************************
|
||||
*
|
||||
|
@ -658,8 +838,9 @@ BOOL PSDRV_GetFontMetrics(void)
|
|||
if (PSDRV_ReadAFMDir (value) == FALSE)
|
||||
return FALSE;
|
||||
|
||||
PSDRV_DumpGlyphList();
|
||||
PSDRV_IndexGlyphList();
|
||||
if (SortFontMetrics() == FALSE)
|
||||
return FALSE;
|
||||
PSDRV_DumpFontList();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
|
@ -3179,4 +3179,4 @@ static const UNICODEGLYPH encoding[1051] =
|
|||
{ 0xfb4b, PSDRV_AGLGlyphNames + 515 } /* afii57700 */
|
||||
};
|
||||
|
||||
const UNICODEVECTOR PSDRV_AdobeGlyphList = { 1051, encoding };
|
||||
UNICODEVECTOR PSDRV_AdobeGlyphList = { 1051, encoding };
|
||||
|
|
|
@ -158,7 +158,7 @@ static INT GlyphListSearch(LPCSTR szName, INT loIndex, INT hiIndex)
|
|||
* necessary, and returns a pointer to it (NULL if unable to add it)
|
||||
*
|
||||
*/
|
||||
const GLYPHNAME *PSDRV_GlyphName(LPCSTR szName)
|
||||
GLYPHNAME *PSDRV_GlyphName(LPCSTR szName)
|
||||
{
|
||||
INT index;
|
||||
|
||||
|
@ -172,17 +172,20 @@ const GLYPHNAME *PSDRV_GlyphName(LPCSTR szName)
|
|||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* PSDRV_DumpGlyphList
|
||||
* PSDRV_IndexGlyphList
|
||||
*
|
||||
* Print contents of glyph list for debugging purposes
|
||||
* Initializes index member of all GLYPHNAME structures
|
||||
*
|
||||
*/
|
||||
VOID PSDRV_DumpGlyphList()
|
||||
VOID PSDRV_IndexGlyphList()
|
||||
{
|
||||
INT i;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ typedef struct {
|
|||
|
||||
typedef struct {
|
||||
LONG UV;
|
||||
const GLYPHNAME *name;
|
||||
GLYPHNAME *name;
|
||||
} UNICODEGLYPH;
|
||||
|
||||
typedef struct {
|
||||
|
@ -31,7 +31,7 @@ typedef struct {
|
|||
|
||||
extern const INT PSDRV_AGLGlyphNamesSize;
|
||||
extern GLYPHNAME PSDRV_AGLGlyphNames[];
|
||||
extern const UNICODEVECTOR PSDRV_AdobeGlyphList;
|
||||
extern UNICODEVECTOR PSDRV_AdobeGlyphList;
|
||||
|
||||
typedef struct {
|
||||
float llx, lly, urx, ury;
|
||||
|
@ -45,12 +45,22 @@ typedef struct _tagAFMLIGS {
|
|||
|
||||
typedef struct _tagAFMMETRICS {
|
||||
int C; /* character */
|
||||
LONG UV;
|
||||
float WX;
|
||||
const GLYPHNAME *N; /* name */
|
||||
GLYPHNAME *N; /* name */
|
||||
AFMBBOX B;
|
||||
AFMLIGS *L; /* Ligatures */
|
||||
} AFMMETRICS;
|
||||
|
||||
typedef struct {
|
||||
USHORT usUnitsPerEm; /* 1000 for Type 1 fonts */
|
||||
SHORT sTypoAscender; /* AFM Ascender */
|
||||
SHORT sTypoDescender; /* AFM Descender */
|
||||
SHORT sTypoLineGap; /* guess for Type 1 fonts */
|
||||
USHORT usWinAscent;
|
||||
USHORT usWinDescent;
|
||||
} WINMETRICS;
|
||||
|
||||
typedef struct _tagAFM {
|
||||
char *FontName;
|
||||
char *FullName;
|
||||
|
@ -67,9 +77,11 @@ typedef struct _tagAFM {
|
|||
float Ascender;
|
||||
float Descender;
|
||||
float FullAscender; /* Ascent of Aring character */
|
||||
WINMETRICS WinMetrics;
|
||||
float CharWidths[256];
|
||||
int NumofMetrics;
|
||||
AFMMETRICS *Metrics;
|
||||
UNICODEVECTOR *Encoding;
|
||||
} AFM; /* CharWidths is a shortcut to the WX values of numbered glyphs */
|
||||
|
||||
/* Note no 'next' in AFM. Use AFMLISTENTRY as a container. This allow more than
|
||||
|
@ -401,8 +413,8 @@ extern DWORD PSDRV_DeviceCapabilities(LPSTR lpszDriver, LPCSTR lpszDevice,
|
|||
LPDEVMODEA lpdm);
|
||||
VOID PSDRV_DrawLine( DC *dc );
|
||||
INT PSDRV_GlyphListInit();
|
||||
const GLYPHNAME *PSDRV_GlyphName(LPCSTR szName);
|
||||
VOID PSDRV_DumpGlyphList();
|
||||
GLYPHNAME *PSDRV_GlyphName(LPCSTR szName);
|
||||
VOID PSDRV_IndexGlyphList();
|
||||
|
||||
#endif
|
||||
|
||||
|
|
Loading…
Reference in New Issue