Unicode encodings for PostScript fonts.

This commit is contained in:
Ian Pilcher 2001-05-09 17:11:59 +00:00 committed by Alexandre Julliard
parent 0c63012b6d
commit 657c4afaec
4 changed files with 227 additions and 31 deletions

View File

@ -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 */
@ -55,9 +57,10 @@ inline static BOOL CheckMetrics(const AFMMETRICS *metrics)
}
/*******************************************************************************
* FreeAFM
* 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
@ -410,6 +461,12 @@ static AFM *PSDRV_AFMParse(char const *file)
afm->FullAscender = afm->Ascender;
if(afm->Weight == 0)
afm->Weight = FW_NORMAL;
if (BuildEncoding(afm) == FALSE)
{
FreeAFM(afm);
return NULL;
}
return afm;
}
@ -554,18 +611,141 @@ static void PSDRV_ReencodeCharWidths(AFM *afm)
*/
static void PSDRV_DumpFontList(void)
{
FONTFAMILY *family;
AFMLISTENTRY *afmle;
FONTFAMILY *family;
AFMLISTENTRY *afmle;
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;
}

View File

@ -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 };

View File

@ -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);
}
}

View File

@ -15,23 +15,23 @@
#include "winspool.h"
typedef struct {
INT index;
LPCSTR sz;
INT index;
LPCSTR sz;
} GLYPHNAME;
typedef struct {
LONG UV;
const GLYPHNAME *name;
LONG UV;
GLYPHNAME *name;
} UNICODEGLYPH;
typedef struct {
INT size;
const UNICODEGLYPH *glyphs;
INT size;
const UNICODEGLYPH *glyphs;
} UNICODEVECTOR;
extern const INT PSDRV_AGLGlyphNamesSize;
extern GLYPHNAME PSDRV_AGLGlyphNames[];
extern const UNICODEVECTOR PSDRV_AdobeGlyphList;
extern const INT PSDRV_AGLGlyphNamesSize;
extern GLYPHNAME PSDRV_AGLGlyphNames[];
extern UNICODEVECTOR PSDRV_AdobeGlyphList;
typedef struct {
float llx, lly, urx, ury;
@ -44,13 +44,23 @@ typedef struct _tagAFMLIGS {
} AFMLIGS;
typedef struct _tagAFMMETRICS {
int C; /* character */
float WX;
const GLYPHNAME *N; /* name */
AFMBBOX B;
AFMLIGS *L; /* Ligatures */
int C; /* character */
LONG UV;
float WX;
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