WINEPS: Unicode encodings for PostScript fonts
Ian Pilcher
ian.pilcher at home.com
Tue May 8 05:22:26 CDT 2001
No TrueType support yet, but this patch makes the driver build Unicode-
style encodings for the PostScript fonts it uses. (Actually, most fonts
end up using the pre-defined Adobe Glyph List encoding.)
As an added bonus, knowing the Unicode value for each glyph will allow
the driver to determine if it is part of the "Windows ANSI" character
set. This will allow the driver to compute the 'WinAscent' and
'WinDescent' metrics for PostScript fonts, which should allow it to
scale them much more accurately.
There is one semi-ugly const->non-const typecasts in afm.c:
SortFontMetrics. The only way to get rid of it (and not get a
compiler warning) is to make the Adobe Glyph List encoding (not the
glyph name strings) in agl.c non-const, which moves them out of read-
only memory; pick your poison.
Modified files:
dlls/wineps: afm.c agl.c glyphlist.c psdrv.h
Log message:
Ian Pilcher
WINEPS: Unicode encodings for PostScript fonts
--
========================================================================
Ian Pilcher ian.pilcher at home.com
========================================================================
-------------- next part --------------
--- ../wine-20010507cvs/dlls/wineps/afm.c Fri May 4 10:06:55 2001
+++ dlls/wineps/afm.c Tue May 8 05:04:35 2001
@@ -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 @@
* 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 @@
}
/*******************************************************************************
- * 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 @@
HeapFree(PSDRV_Heap, 0, afm);
}
-
/***********************************************************
*
* PSDRV_AFMGetCharMetrics
@@ -191,6 +193,55 @@
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 @@
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_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 @@
if (PSDRV_ReadAFMDir (value) == FALSE)
return FALSE;
- PSDRV_DumpGlyphList();
+ PSDRV_IndexGlyphList();
+ if (SortFontMetrics() == FALSE)
+ return FALSE;
PSDRV_DumpFontList();
return TRUE;
}
-
--- ../wine-20010507cvs/dlls/wineps/agl.c Fri Apr 20 13:30:38 2001
+++ dlls/wineps/agl.c Tue May 8 05:00:04 2001
@@ -3179,4 +3179,4 @@
{ 0xfb4b, PSDRV_AGLGlyphNames + 515 } /* afii57700 */
};
-const UNICODEVECTOR PSDRV_AdobeGlyphList = { 1051, encoding };
+UNICODEVECTOR PSDRV_AdobeGlyphList = { 1051, encoding };
--- ../wine-20010507cvs/dlls/wineps/glyphlist.c Mon Apr 23 13:12:45 2001
+++ dlls/wineps/glyphlist.c Tue May 8 04:10:57 2001
@@ -158,7 +158,7 @@
* 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 @@
}
/*******************************************************************************
- * 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);
+ }
}
--- ../wine-20010507cvs/dlls/wineps/psdrv.h Fri May 4 10:06:55 2001
+++ dlls/wineps/psdrv.h Tue May 8 04:59:56 2001
@@ -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 @@
} 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 @@
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 @@
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
More information about the wine-patches
mailing list