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

Dmitry Timoshkov dmitry at codeweavers.com
Wed Nov 24 12:11:07 CST 2010


From: Jeremy White <jwhite at codeweavers.com>

---
 dlls/gdi32/freetype.c |  238 +++++++++++++++++++++++++++++++++++++------------
 1 files changed, 182 insertions(+), 56 deletions(-)

diff --git a/dlls/gdi32/freetype.c b/dlls/gdi32/freetype.c
index 7c4b2e2..37a7de32 100644
--- a/dlls/gdi32/freetype.c
+++ b/dlls/gdi32/freetype.c
@@ -370,7 +370,7 @@ typedef struct {
 
 #include "pshpack1.h"
 
-static const struct
+static const struct dos
 {
     WORD e_magic;      /* 00: MZ Header signature */
     WORD unused[29];
@@ -907,6 +907,172 @@ static inline BOOL is_win9x(void)
 {
     return GetVersion() & 0x80000000;
 }
+
+static struct font_mapping *map_font_file( const char *name )
+{
+    struct font_mapping *mapping;
+    struct stat st;
+    int fd;
+
+    if ((fd = open( name, O_RDONLY )) == -1) return NULL;
+    if (fstat( fd, &st ) == -1) goto error;
+
+    LIST_FOR_EACH_ENTRY( mapping, &mappings_list, struct font_mapping, entry )
+    {
+        if (mapping->dev == st.st_dev && mapping->ino == st.st_ino)
+        {
+            mapping->refcount++;
+            close( fd );
+            return mapping;
+        }
+    }
+    if (!(mapping = HeapAlloc( GetProcessHeap(), 0, sizeof(*mapping) )))
+        goto error;
+
+    mapping->data = mmap( NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0 );
+    close( fd );
+
+    if (mapping->data == MAP_FAILED)
+    {
+        HeapFree( GetProcessHeap(), 0, mapping );
+        return NULL;
+    }
+    mapping->refcount = 1;
+    mapping->dev = st.st_dev;
+    mapping->ino = st.st_ino;
+    mapping->size = st.st_size;
+    list_add_tail( &mappings_list, &mapping->entry );
+    return mapping;
+
+error:
+    close( fd );
+    return NULL;
+}
+
+static void unmap_font_file( struct font_mapping *mapping )
+{
+    if (!--mapping->refcount)
+    {
+        list_remove( &mapping->entry );
+        munmap( mapping->data, mapping->size );
+        HeapFree( GetProcessHeap(), 0, mapping );
+    }
+}
+
+static char *get_scalable_resource_name(const char *file, void *data, DWORD size)
+{
+    struct font_mapping *mapping = NULL;
+    char *data_ptr;
+    DWORD data_size;
+    struct dos *dos;
+    IMAGE_OS2_HEADER *os2;
+    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;
+
+    if (file)
+    {
+        if (!(mapping = map_font_file(file)))
+        {
+            WARN("failed to map %s\n", debugstr_a(file));
+            return NULL;
+        }
+        data_ptr = mapping->data;
+        data_size = mapping->size;
+        size = data_size;
+    }
+    else
+    {
+        data_ptr = data;
+        data_size = size;
+    }
+
+    if (data_size < sizeof(dos))
+        goto errexit;
+
+    dos = (struct dos *)data_ptr;
+    if (dos->e_magic != IMAGE_DOS_SIGNATURE)
+        goto errexit;
+
+    if (dos->e_lfanew + sizeof(os2) > data_size)
+        goto errexit;
+
+    os2 = (IMAGE_OS2_HEADER *)(data_ptr + dos->e_lfanew);
+    if (os2->ne_magic != IMAGE_OS2_SIGNATURE)
+        goto errexit;
+
+    resource_shift = os2->ne_align;
+
+    if (os2->ne_rsrctab >= os2->ne_restab)
+        goto errexit;
+
+    if (dos->e_lfanew + os2->ne_rsrctab + 2 > data_size)
+        goto errexit;
+
+    type = (NE_TYPEINFO *)(data_ptr + dos->e_lfanew + os2->ne_rsrctab + 2);
+
+    data_size -= (char *)type - data_ptr;
+
+    while (data_size >= sizeof(*type) + sizeof(*name))
+    {
+        data_size -= sizeof(*type) + sizeof(*name);
+
+        if (!type->type_id) break;
+
+        name = (NE_NAMEINFO *)(type + 1);
+
+        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;
+        }
+
+        type = (NE_TYPEINFO *)(name + 1);
+    }
+
+    data_size = size;
+
+    if (!fontdir_off || !fontpath_off)
+        goto errexit;
+
+    fd = (struct fontdir *)(data_ptr + fontdir_off);
+    if (fontdir_off + fd->dfSize > data_size)
+        goto errexit;
+
+    if (fontpath_off + fontpath_len > data_size)
+        goto errexit;
+
+    fot_path = data_ptr + fontpath_off;
+
+    len = MultiByteToWideChar(CP_ACP, 0, fot_path, fontpath_len, NULL, 0);
+    wide_path = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR));
+    MultiByteToWideChar(CP_ACP, 0, fot_path, fontpath_len, wide_path, len);
+    wide_path[len] = 0;
+
+    ret = wine_get_unix_file_name(wide_path);
+
+errexit:
+    if (mapping) unmap_font_file(mapping);
+    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 +1624,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, flist, 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);
@@ -3109,57 +3286,6 @@ static LONG calc_ppem_for_height(FT_Face ft_face, LONG height)
     return ppem;
 }
 
-static struct font_mapping *map_font_file( const char *name )
-{
-    struct font_mapping *mapping;
-    struct stat st;
-    int fd;
-
-    if ((fd = open( name, O_RDONLY )) == -1) return NULL;
-    if (fstat( fd, &st ) == -1) goto error;
-
-    LIST_FOR_EACH_ENTRY( mapping, &mappings_list, struct font_mapping, entry )
-    {
-        if (mapping->dev == st.st_dev && mapping->ino == st.st_ino)
-        {
-            mapping->refcount++;
-            close( fd );
-            return mapping;
-        }
-    }
-    if (!(mapping = HeapAlloc( GetProcessHeap(), 0, sizeof(*mapping) )))
-        goto error;
-
-    mapping->data = mmap( NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0 );
-    close( fd );
-
-    if (mapping->data == MAP_FAILED)
-    {
-        HeapFree( GetProcessHeap(), 0, mapping );
-        return NULL;
-    }
-    mapping->refcount = 1;
-    mapping->dev = st.st_dev;
-    mapping->ino = st.st_ino;
-    mapping->size = st.st_size;
-    list_add_tail( &mappings_list, &mapping->entry );
-    return mapping;
-
-error:
-    close( fd );
-    return NULL;
-}
-
-static void unmap_font_file( struct font_mapping *mapping )
-{
-    if (!--mapping->refcount)
-    {
-        list_remove( &mapping->entry );
-        munmap( mapping->data, mapping->size );
-        HeapFree( GetProcessHeap(), 0, mapping );
-    }
-}
-
 static LONG load_VDMX(GdiFont*, LONG);
 
 static FT_Face OpenFontFace(GdiFont *font, Face *face, LONG width, LONG height)
-- 
1.7.3.2




More information about the wine-patches mailing list