[PATCH 5/7] Add a helper function to write a NE file given a FONTDIR16 and path name.

Jeremy White jwhite at codeweavers.com
Wed Apr 23 23:26:52 CDT 2008


---
 dlls/gdi32/font.c |  220 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 220 insertions(+), 0 deletions(-)

diff --git a/dlls/gdi32/font.c b/dlls/gdi32/font.c
index e59b7d5..61aae1d 100644
--- a/dlls/gdi32/font.c
+++ b/dlls/gdi32/font.c
@@ -2359,6 +2359,226 @@ DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
 }


+/*****************************************************************************
+ * FONT_WriteScalableFont
+ *  Write out a .fot file
+ *  The format for this file is not specified, so we create an NE format file
+ * that is similar to one created by Windows XP.
+ */
+static int FONT_WriteScalableFont(LPCWSTR output_name, FONTDIR16 *fontdir, LPCSTR ttf_file)
+{
+    HANDLE h;
+    IMAGE_DOS_HEADER dos;
+    char dos_stub[64];
+    IMAGE_OS2_HEADER ne;
+    NE_TYPEINFO types[2];
+    NE_NAMEINFO names[2];
+    WORD resource_shift = 4;
+    char fontdir_string[] = "FONTDIR";
+    char buffer[4096];
+    char *bufp;
+    char shortname[128];
+    char fontres[256];
+    char *sp;
+    int extlen;
+    int i;
+    int rc = 0;
+    int ne_offset;
+    int type_0_offset;
+    int fontdir_len;
+    int write_len;
+    char *fp;
+
+    TRACE("(%s,%s,%s):\n",
+          debugstr_w(output_name), fontdir->szDeviceName + 1, ttf_file);
+
+    h = CreateFileW(output_name, FILE_SHARE_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+    if (h == INVALID_HANDLE_VALUE)
+    {
+        TRACE("Error:  could not open %s for writing\n", debugstr_w(output_name));
+        return 1;
+    }
+
+    /* Get an 8.3 name to be used in the name tables */
+    if (GetShortPathNameA(ttf_file, shortname, sizeof(shortname)) == 0)
+        strcpy(shortname, ttf_file);
+    for (sp = shortname + strlen(shortname) - 1; *sp != '/' && *sp != '\\' && sp >= shortname; )
+        sp--;
+    sp++;
+    if (strstr(sp, "."))
+        extlen = strstr(sp, ".") - sp;
+    else
+        extlen = strlen(sp);
+
+    fontdir_len = sizeof(*fontdir);
+
+    /* Make a DOS header.  Modern programs ignore most values in the dos header */
+    memset(&dos, '\0', sizeof(dos));
+    memset(dos_stub, '\0', sizeof(dos_stub));
+    dos.e_magic = IMAGE_DOS_SIGNATURE;
+    dos.e_lfarlc = sizeof(dos);
+    dos.e_lfanew = sizeof(dos) + sizeof(dos_stub);
+
+    memset(&ne, '\0', sizeof(ne));
+    ne.ne_magic = IMAGE_OS2_SIGNATURE;
+    ne.ne_ver = 5;
+    ne.ne_rev = 1;
+
+    ne.ne_flags =  NE_FFLAGS_LIBMODULE;
+    ne.ne_align =  0x4;    /* 16 byte alignment */
+    ne.ne_cres =   2;      /* # of resource segments */
+    ne.ne_exetyp = NE_OSFLAGS_WINDOWS;
+    ne.ne_expver = 0x400;
+
+    memset(types, '\0', sizeof(types));
+    memset(names, '\0', sizeof(names));
+
+    types[0].type_id = NE_RSCTYPE_FONTDIR;
+    types[0].count = 1;
+    names[0].length = fontdir_len >> resource_shift;
+    names[0].flags = NE_SEGFLAGS_PRELOAD | NE_SEGFLAGS_MOVEABLE;
+    names[0].id = 0; /* To be computed and rewritten later */
+
+
+    types[1].type_id = NE_RSCTYPE_SCALABLE_FONTPATH;
+    types[1].count = 1;
+    names[1].length = (strlen(ttf_file) + 1 + 15) >> resource_shift;
+    names[1].flags = NE_SEGFLAGS_PRELOAD | NE_SEGFLAGS_MOVEABLE;
+    names[1].id = 1 | 0x8000;
+
+    memset(buffer, 0, sizeof(buffer));
+    bufp = buffer;
+
+#define ADD_DATA(p, s)  { memcpy(bufp, (p), (s)); bufp += (s); }
+#define ADD_BYTE(b)     { *((BYTE *)(bufp)) = (b); bufp += sizeof(BYTE); }
+#define ADD_WORD(w)     { *((WORD *)(bufp)) = (w); bufp += sizeof(WORD); }
+#define ADD_DWORD(dw)   { *((DWORD *)(bufp)) = (dw); bufp += sizeof(DWORD); }
+#define CURRENT_OFFSET  (bufp - buffer)
+
+    ADD_DATA(&dos, sizeof(dos));
+    ADD_DATA(&dos_stub, sizeof(dos_stub));
+
+    ne_offset = CURRENT_OFFSET;
+
+    ADD_DATA(&ne, sizeof(ne));
+
+    /* Segment table */
+    ne.ne_cseg = 0;
+    ne.ne_segtab = CURRENT_OFFSET - ne_offset;
+    ADD_WORD(0);
+    ADD_WORD(0);
+    ADD_WORD(0);
+    ADD_WORD(0);
+
+    /* Begin resource table */
+    ne.ne_rsrctab = CURRENT_OFFSET - ne_offset;
+    ADD_DATA(&resource_shift, sizeof(resource_shift));
+
+    type_0_offset = CURRENT_OFFSET;
+
+    for (i = 0; i < 2; i++)
+    {
+        ADD_DATA(&types[i], sizeof(types[i]));
+        ADD_DATA(&names[i], sizeof(names[i]));
+    }
+
+    ADD_WORD(0);   /* End the list of type/names with a 0 id */
+
+    /* The id field of the first name points to the offset of the resource name */
+    names[0].id = CURRENT_OFFSET - ne.ne_rsrctab - ne_offset;
+
+    ADD_BYTE(strlen(fontdir_string));
+    ADD_DATA(fontdir_string, strlen(fontdir_string));
+    /* End resource table */
+
+
+    /* Resident name table */
+    ne.ne_restab = CURRENT_OFFSET - ne_offset;
+    ADD_BYTE(extlen);
+    ADD_DATA(sp, extlen);
+    ADD_WORD(0);
+    ADD_BYTE(0);
+
+    /* Module reference table */
+    ne.ne_cmod = 0;
+    ne.ne_modtab = CURRENT_OFFSET - ne_offset;
+    ADD_WORD(0);
+
+    /* Imported name table */
+    ne.ne_imptab = CURRENT_OFFSET - ne_offset;
+    ADD_BYTE(strlen(sp));
+    ADD_DATA(sp, strlen(sp));
+
+    /* Entry table */
+    ne.ne_enttab = CURRENT_OFFSET - ne_offset;
+    ne.ne_cbenttab = 1;
+    ADD_BYTE(0);
+
+    /* Nonresident name table */
+    ne.ne_nrestab = CURRENT_OFFSET;
+    memset(fontres, 0, sizeof(fontres));
+    strcpy(fontres, "FONTRES:");
+    fp = fontdir->szDeviceName + 1;
+    fp += strlen(fp) + 1;
+    strcat(fontres, fp);
+    ADD_BYTE(strlen(fontres));
+    ADD_DATA(fontres, strlen(fontres));
+    ADD_WORD(0);
+    ADD_BYTE(0);
+    ne.ne_cbnrestab = CURRENT_OFFSET - ne.ne_nrestab;
+
+    /* Skip ahead to paragraph boundary */
+    if (CURRENT_OFFSET % 16)
+        bufp += 16 - (CURRENT_OFFSET % 16);
+
+    /* Resource 0 - FONTDIR */
+    names[0].offset = CURRENT_OFFSET >> resource_shift;
+    ADD_DWORD(1);
+    ADD_DATA(fontdir,  fontdir_len);
+
+    /* Skip ahead to paragraph boundary */
+    if (CURRENT_OFFSET % 16)
+        bufp += 16 - (CURRENT_OFFSET % 16);
+
+    /* Resource 1 - Scalable font path */
+    names[1].offset = CURRENT_OFFSET >> resource_shift;
+    ADD_DATA(ttf_file, strlen(ttf_file) + 1);
+
+    /* Skip ahead to paragraph boundary */
+    if (CURRENT_OFFSET % 16)
+        bufp += 16 - (CURRENT_OFFSET % 16);
+
+    write_len = CURRENT_OFFSET;
+
+    /* Copy back in the updated ne */
+    memcpy(buffer + ne_offset, &ne, sizeof(ne));
+
+    /* Copy back in updated types + names */
+    bufp = buffer + type_0_offset;
+
+    for (i = 0; i < 2; i++)
+    {
+        ADD_DATA(&types[i], sizeof(types[i]));
+        ADD_DATA(&names[i], sizeof(names[i]));
+    }
+
+    if (!WriteFile(h, buffer, write_len, NULL, NULL))
+    {
+        TRACE("Error:  could not write %d bytes\n", bufp - buffer);
+        rc = 1;
+    }
+
+#undef ADD_DATA
+#undef ADD_BYTE
+#undef ADD_WORD
+#undef ADD_DWORD
+#undef CURRENT_OFFSET
+
+    CloseHandle(h);
+    return rc;
+}
+
+
 /***********************************************************************
  *           CreateScalableFontResourceA   (GDI32.@)
  */



More information about the wine-patches mailing list