From 2b6355fbaae1d1e5dc30a8dadab1a055aa38af55 Mon Sep 17 00:00:00 2001
From: "Erich E. Hoover" <erich.e.hoover@wine-staging.com>
Date: Wed, 2 Sep 2015 17:21:15 -0600
Subject: wineps.drv: Add glyph names for PostScript Format 1 glyphs.

Required for generating searchable PDFs from a PostScript document.
---
 dlls/wineps.drv/download.c | 327 ++++++++++++++++++++++++++++++++++++++++++++-
 dlls/wineps.drv/psdrv.h    |   2 +-
 dlls/wineps.drv/type42.c   |   2 +-
 3 files changed, 323 insertions(+), 8 deletions(-)

diff --git a/dlls/wineps.drv/download.c b/dlls/wineps.drv/download.c
index e5b57f7..6f6a307 100644
--- a/dlls/wineps.drv/download.c
+++ b/dlls/wineps.drv/download.c
@@ -342,7 +342,7 @@ BOOL PSDRV_WriteSetDownloadFont(PHYSDEV dev, BOOL vertical)
 
         if(pdl->type == Type42) {
             char g_name[MAX_G_NAME + 1];
-            get_glyph_name(dev->hdc, 0, g_name);
+            get_glyph_name(dev, 0, g_name);
             T42_download_glyph(dev, pdl, 0, g_name);
         }
     }
@@ -359,11 +359,326 @@ BOOL PSDRV_WriteSetDownloadFont(PHYSDEV dev, BOOL vertical)
     return TRUE;
 }
 
-void get_glyph_name(HDC hdc, WORD index, char *name)
+void get_standard_glyph_name(WORD index, char *name)
 {
-  /* FIXME */
+    /* These PostScript Format 1 glyph names are stored by glyph index, do not reorder them. */
+    const char *glyph_table[] = {
+        ".notdef",
+        ".null",
+        "nonmarkingreturn",
+        "space",
+        "exclam",
+        "quotedbl",
+        "numbersign",
+        "dollar",
+        "percent",
+        "ampersand",
+        "quotesingle",
+        "parenleft",
+        "parenright",
+        "asterisk",
+        "plus",
+        "comma",
+        "hyphen",
+        "period",
+        "slash",
+        "zero",
+        "one",
+        "two",
+        "three",
+        "four",
+        "five",
+        "six",
+        "seven",
+        "eight",
+        "nine",
+        "colon",
+        "semicolon",
+        "less",
+        "equal",
+        "greater",
+        "question",
+        "at",
+        "A",
+        "B",
+        "C",
+        "D",
+        "E",
+        "F",
+        "G",
+        "H",
+        "I",
+        "J",
+        "K",
+        "L",
+        "M",
+        "N",
+        "O",
+        "P",
+        "Q",
+        "R",
+        "S",
+        "T",
+        "U",
+        "V",
+        "W",
+        "X",
+        "Y",
+        "Z",
+        "bracketleft",
+        "backslash",
+        "bracketright",
+        "asciicircum",
+        "underscore",
+        "grave",
+        "a",
+        "b",
+        "c",
+        "d",
+        "e",
+        "f",
+        "g",
+        "h",
+        "i",
+        "j",
+        "k",
+        "l",
+        "m",
+        "n",
+        "o",
+        "p",
+        "q",
+        "r",
+        "s",
+        "t",
+        "u",
+        "v",
+        "w",
+        "x",
+        "y",
+        "z",
+        "braceleft",
+        "bar",
+        "braceright",
+        "asciitilde",
+        "Adieresis",
+        "Aring",
+        "Ccedilla",
+        "Eacute",
+        "Ntilde",
+        "Odieresis",
+        "Udieresis",
+        "aacute",
+        "agrave",
+        "acircumflex",
+        "adieresis",
+        "atilde",
+        "aring",
+        "ccedilla",
+        "eacute",
+        "egrave",
+        "ecircumflex",
+        "edieresis",
+        "iacute",
+        "igrave",
+        "icircumflex",
+        "idieresis",
+        "ntilde",
+        "oacute",
+        "ograve",
+        "ocircumflex",
+        "odieresis",
+        "otilde",
+        "uacute",
+        "ugrave",
+        "ucircumflex",
+        "udieresis",
+        "dagger",
+        "degree",
+        "cent",
+        "sterling",
+        "section",
+        "bullet",
+        "paragraph",
+        "germandbls",
+        "registered",
+        "copyright",
+        "trademark",
+        "acute",
+        "dieresis",
+        "notequal",
+        "AE",
+        "Oslash",
+        "infinity",
+        "plusminus",
+        "lessequal",
+        "greaterequal",
+        "yen",
+        "mu",
+        "partialdiff",
+        "summation",
+        "product",
+        "pi",
+        "integral",
+        "ordfeminine",
+        "ordmasculine",
+        "Omega",
+        "ae",
+        "oslash",
+        "questiondown",
+        "exclamdown",
+        "logicalnot",
+        "radical",
+        "florin",
+        "approxequal",
+        "Delta",
+        "guillemotleft",
+        "guillemotright",
+        "ellipsis",
+        "nonbreakingspace",
+        "Agrave",
+        "Atilde",
+        "Otilde",
+        "OE",
+        "oe",
+        "endash",
+        "emdash",
+        "quotedblleft",
+        "quotedblright",
+        "quoteleft",
+        "quoteright",
+        "divide",
+        "lozenge",
+        "ydieresis",
+        "Ydieresis",
+        "fraction",
+        "currency",
+        "guilsinglleft",
+        "guilsinglright",
+        "fi",
+        "fl",
+        "daggerdbl",
+        "periodcentered",
+        "quotesinglbase",
+        "quotedblbase",
+        "perthousand",
+        "Acircumflex",
+        "Ecircumflex",
+        "Aacute",
+        "Edieresis",
+        "Egrave",
+        "Iacute",
+        "Icircumflex",
+        "Idieresis",
+        "Igrave",
+        "Oacute",
+        "Ocircumflex",
+        "apple",
+        "Ograve",
+        "Uacute",
+        "Ucircumflex",
+        "Ugrave",
+        "dotlessi",
+        "circumflex",
+        "tilde",
+        "macron",
+        "breve",
+        "dotaccent",
+        "ring",
+        "cedilla",
+        "hungarumlaut",
+        "ogonek",
+        "caron",
+        "Lslash",
+        "lslash",
+        "Scaron",
+        "scaron",
+        "Zcaron",
+        "zcaron",
+        "brokenbar",
+        "Eth",
+        "eth",
+        "Yacute",
+        "yacute",
+        "Thorn",
+        "thorn",
+        "minus",
+        "multiply",
+        "onesuperior",
+        "twosuperior",
+        "threesuperior",
+        "onehalf",
+        "onequarter",
+        "threequarters",
+        "franc",
+        "Gbreve",
+        "gbreve",
+        "Idotaccent",
+        "Scedilla",
+        "scedilla",
+        "Cacute",
+        "cacute",
+        "Ccaron",
+        "ccaron",
+        "dcroat"
+    };
+    strcpy(name, glyph_table[index]);
+}
+
+void get_glyph_name(PHYSDEV dev, WORD index, char *name)
+{
+    struct
+    {
+        DWORD format;
+        DWORD italicAngle;
+        SHORT underlinePosition;
+        SHORT underlineThickness;
+        DWORD isFixedPitch;
+        DWORD minMemType42;
+        DWORD maxMemType42;
+        DWORD minMemType1;
+        DWORD maxMemType1;
+    } *post_header;
+    BYTE *post = NULL;
+    DWORD size;
+
+    /* set a fallback name that is just 'g<index>' */
     sprintf(name, "g%04x", index);
-    return;
+
+    /* attempt to obtain the glyph name from the 'post' table */
+    size = GetFontData(dev->hdc, MS_MAKE_TAG('p','o','s','t'), 0, NULL, 0);
+    if(size == 0 || size == GDI_ERROR)
+        goto cleanup;
+    post = HeapAlloc(GetProcessHeap(), 0, size);
+    if(!post)
+        goto cleanup;
+    size = GetFontData(dev->hdc, MS_MAKE_TAG('p','o','s','t'), 0, post, size);
+    if(size == 0 || size == GDI_ERROR)
+        goto cleanup;
+    post_header = (typeof(post_header))(post);
+    /* note: only interested in the format for obtaining glyph names */
+    post_header->format = GET_BE_DWORD(&post_header->format);
+
+    /* now that we know the format of the 'post' table we can get the glyph name */
+    if(post_header->format == MAKELONG(0, 1))
+    {
+        if(index < 258)
+            get_standard_glyph_name(index, name);
+        else
+            WARN("Font uses PostScript Format 1, but non-standard glyph (%d) requested.\n", index);
+    }
+    else if(post_header->format == MAKELONG(0, 2))
+    {
+        if(index < 258)
+            get_standard_glyph_name(index, name);
+        else
+            FIXME("PostScript Format 2 custom glyph names are currently unsupported.\n");
+    }
+    else
+        FIXME("Only standard PostScript Format 1 glyph names are currently supported.\n");
+
+cleanup:
+    HeapFree(GetProcessHeap(), 0, post);
 }
 
 /****************************************************************************
@@ -383,7 +698,7 @@ BOOL PSDRV_WriteDownloadGlyphShow(PHYSDEV dev, const WORD *glyphs,
     switch(physDev->font.fontinfo.Download->type) {
     case Type42:
     for(i = 0; i < count; i++) {
-        get_glyph_name(dev->hdc, glyphs[i], g_name);
+        get_glyph_name(dev, glyphs[i], g_name);
 	T42_download_glyph(dev, physDev->font.fontinfo.Download, glyphs[i], g_name);
 	PSDRV_WriteGlyphShow(dev, g_name);
     }
@@ -391,7 +706,7 @@ BOOL PSDRV_WriteDownloadGlyphShow(PHYSDEV dev, const WORD *glyphs,
 
     case Type1:
     for(i = 0; i < count; i++) {
-        get_glyph_name(dev->hdc, glyphs[i], g_name);
+        get_glyph_name(dev, glyphs[i], g_name);
 	T1_download_glyph(dev, physDev->font.fontinfo.Download, glyphs[i], g_name);
 	PSDRV_WriteGlyphShow(dev, g_name);
     }
diff --git a/dlls/wineps.drv/psdrv.h b/dlls/wineps.drv/psdrv.h
index 75c062a..ab25eea 100644
--- a/dlls/wineps.drv/psdrv.h
+++ b/dlls/wineps.drv/psdrv.h
@@ -555,7 +555,7 @@ extern BOOL PSDRV_EmptyDownloadList(PHYSDEV dev, BOOL write_undef) DECLSPEC_HIDD
 extern DWORD write_spool( PHYSDEV dev, const void *data, DWORD num ) DECLSPEC_HIDDEN;
 
 #define MAX_G_NAME 31 /* max length of PS glyph name */
-extern void get_glyph_name(HDC hdc, WORD index, char *name) DECLSPEC_HIDDEN;
+extern void get_glyph_name(PHYSDEV hdc, WORD index, char *name) DECLSPEC_HIDDEN;
 
 extern TYPE1 *T1_download_header(PHYSDEV dev, char *ps_name,
                                  RECT *bbox, UINT emsize) DECLSPEC_HIDDEN;
diff --git a/dlls/wineps.drv/type42.c b/dlls/wineps.drv/type42.c
index c0cda50..7c8fbe7 100644
--- a/dlls/wineps.drv/type42.c
+++ b/dlls/wineps.drv/type42.c
@@ -326,7 +326,7 @@ BOOL T42_download_glyph(PHYSDEV dev, DOWNLOAD *pdl, DWORD index,
 	    sg_index = GET_BE_WORD(sg_start + 2);
 
 	    TRACE("Sending subglyph %04x for glyph %04x\n", sg_index, index);
-	    get_glyph_name(dev->hdc, sg_index, sg_name);
+	    get_glyph_name(dev, sg_index, sg_name);
 	    T42_download_glyph(dev, pdl, sg_index, sg_name);
 	    sg_start += 4;
 	    if(sg_flags & ARG_1_AND_2_ARE_WORDS)
-- 
1.9.1

