[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