[3/5] gdi32: Add the ability to load a scalable font resource.

Dmitry Timoshkov dmitry at codeweavers.com
Sun Nov 14 05:05:46 CST 2010


From: Jeremy White <jwhite at codeweavers.com>

---
 dlls/gdi32/freetype.c |  129 +++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 124 insertions(+), 5 deletions(-)

diff --git a/dlls/gdi32/freetype.c b/dlls/gdi32/freetype.c
index 544d955..fdefadc 100644
--- a/dlls/gdi32/freetype.c
+++ b/dlls/gdi32/freetype.c
@@ -368,7 +368,7 @@ typedef struct {
 #define NE_SEGFLAGS_MOVEABLE    0x0010
 #define NE_SEGFLAGS_PRELOAD     0x0040
 
-static const struct
+static const struct dos
 {
     WORD e_magic;      /* 00: MZ Header signature */
     WORD unused[29];
@@ -907,6 +907,114 @@ static inline BOOL is_win9x(void)
 {
     return GetVersion() & 0x80000000;
 }
+
+static char *get_scalable_resource_name(const char *file, void *font_data_ptr, DWORD font_data_size)
+{
+    struct dos dos;
+    IMAGE_OS2_HEADER os2;
+    HANDLE hfile;
+    NE_TYPEINFO type;
+    NE_NAMEINFO name;
+    WORD resource_shift;
+    DWORD fontdir_off = 0, fontpath_off = 0, fontdir_len, fontpath_len;
+    LPSTR fot_path = NULL;
+    LPWSTR wide_path = NULL;
+    char *ret = NULL;
+    int len;
+    struct fontdir fd;
+
+    /* FIXME */
+    if (!file) return NULL;
+
+    hfile = CreateFileA(file, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+    if (hfile == INVALID_HANDLE_VALUE)
+    {
+        TRACE("Could not open %s for reading\n", file);
+        return NULL;
+    }
+
+    if (!ReadFile(hfile, &dos, sizeof(dos), NULL, NULL))
+        goto errexit;
+
+    if (dos.e_magic != IMAGE_DOS_SIGNATURE)
+        goto errexit;
+
+    if (SetFilePointer(hfile, dos.e_lfanew, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
+        goto errexit;
+
+    if (!ReadFile(hfile, &os2, sizeof(os2), NULL, NULL))
+        goto errexit;
+
+    if (os2.ne_magic != IMAGE_OS2_SIGNATURE)
+        goto errexit;
+
+    resource_shift = os2.ne_align;
+
+    if (os2.ne_rsrctab >= os2.ne_restab)
+        goto errexit;
+
+    if (SetFilePointer(hfile, dos.e_lfanew + os2.ne_rsrctab + 2, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
+        goto errexit;
+
+    while (ReadFile(hfile, &type, sizeof(type), NULL, NULL))
+    {
+        if (!type.type_id) break;
+
+        if (!ReadFile(hfile, &name, sizeof(name), NULL, NULL))
+            goto errexit;
+
+        switch (type.type_id)
+        {
+        case NE_RSCTYPE_FONTDIR:
+            fontdir_off = name.offset << resource_shift;
+            fontdir_len = name.length << resource_shift;
+            break;
+
+        case NE_RSCTYPE_SCALABLE_FONTPATH:
+            fontpath_off = name.offset << resource_shift;
+            fontpath_len = name.length << resource_shift;
+            break;
+        }
+    }
+
+    if (!fontdir_off || !fontpath_off)
+        goto errexit;
+
+    if (SetFilePointer(hfile, fontdir_off, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
+        goto errexit;
+
+    memset(&fd, 0, sizeof(fd));
+    if (fontdir_len > sizeof(fd)) fontdir_len = sizeof(fd);
+    if (!ReadFile(hfile, &fd, fontdir_len, NULL, NULL))
+        goto errexit;
+
+    if (SetFilePointer(hfile, fontpath_off, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
+        goto errexit;
+
+    fot_path = HeapAlloc(GetProcessHeap(), 0, fontpath_len);
+    if (!fot_path)
+        goto errexit;
+
+    if (!ReadFile(hfile, fot_path, fontpath_len, NULL, NULL))
+        goto errexit;
+
+    len = MultiByteToWideChar(CP_ACP, 0, fot_path, -1, NULL, 0);
+    wide_path = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
+    MultiByteToWideChar(CP_ACP, 0, fot_path, -1, wide_path, len);
+
+    ret = wine_get_unix_file_name(wide_path);
+
+errexit:
+    CloseHandle(hfile);
+
+    HeapFree(GetProcessHeap(), 0, fot_path);
+    HeapFree(GetProcessHeap(), 0, wide_path);
+
+    TRACE("-> %s\n", ret);
+
+    return ret;
+}
+
 /* 
    This function builds an FT_Fixed from a double. It fails if the absolute
    value of the float number is greater than 32768.
@@ -1458,10 +1566,21 @@ static int load_font(const char *file, void *font_data_ptr, DWORD font_data_size
             err = pFT_New_Memory_Face(library, font_data_ptr, font_data_size, face_index, &ft_face);
         }
 
-	if(err != 0) {
-	    WARN("Unable to load font %s/%p err = %x\n", debugstr_a(file), font_data_ptr, err);
-	    return 0;
-	}
+        if (err != 0)
+        {
+            char *scalable_rsrc_name;
+
+            scalable_rsrc_name = get_scalable_resource_name(file, font_data_ptr, font_data_size);
+            if (scalable_rsrc_name)
+            {
+                int ret = load_font(scalable_rsrc_name, NULL, 0, font_list, flags);
+                HeapFree(GetProcessHeap(), 0, scalable_rsrc_name);
+                return ret;
+            }
+
+            WARN("Unable to load font %s/%p err = %x\n", debugstr_a(file), font_data_ptr, err);
+            return 0;
+        }
 
 	if(!FT_IS_SFNT(ft_face) && (FT_IS_SCALABLE(ft_face) || !(flags & ADDFONT_FORCE_BITMAP))) { /* for now we'll accept TT/OT or bitmap fonts*/
 	    WARN("Ignoring font %s/%p\n", debugstr_a(file), font_data_ptr);
-- 
1.7.0.6




More information about the wine-patches mailing list