[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