Huw Davies : gdi32: Add support for loading scalable font resources.

Alexandre Julliard julliard at winehq.org
Fri Mar 30 11:27:06 CDT 2012


Module: wine
Branch: master
Commit: 88a2620b149b3fa82b20cca2aff3b2088026456e
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=88a2620b149b3fa82b20cca2aff3b2088026456e

Author: Huw Davies <huw at codeweavers.com>
Date:   Fri Mar 30 12:38:04 2012 +0100

gdi32: Add support for loading scalable font resources.

---

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

diff --git a/dlls/gdi32/font.c b/dlls/gdi32/font.c
index 1abb6ae..230d421 100644
--- a/dlls/gdi32/font.c
+++ b/dlls/gdi32/font.c
@@ -3446,12 +3446,85 @@ static BOOL CALLBACK load_enumed_resource(HMODULE hModule, LPCWSTR type, LPWSTR
     return TRUE;
 }
 
+static void *map_file( const WCHAR *filename, LARGE_INTEGER *size )
+{
+    HANDLE file, mapping;
+    void *ptr;
+
+    file = CreateFileW( filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
+    if (file == INVALID_HANDLE_VALUE) return NULL;
+
+    GetFileSizeEx( file, size );
+    mapping = CreateFileMappingW( file, NULL, PAGE_READONLY, 0, 0, NULL );
+    CloseHandle( file );
+    if (mapping == NULL) return NULL;
+
+    ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 0 );
+    CloseHandle( mapping );
+
+    return ptr;
+}
+
+static WCHAR *get_scalable_filename( const WCHAR *res )
+{
+    LARGE_INTEGER size;
+    BYTE *ptr = map_file( res, &size );
+    const IMAGE_DOS_HEADER *dos;
+    const IMAGE_OS2_HEADER *ne;
+    WCHAR *name = NULL;
+    WORD rsrc_off, align, type_id, count;
+    DWORD res_off, res_len, i;
+    int len;
+
+    if (!ptr) return NULL;
+
+    if (size.u.HighPart) goto fail;
+    if (size.u.LowPart < sizeof( *dos )) goto fail;
+    dos = (const IMAGE_DOS_HEADER *)ptr;
+    if (dos->e_magic != IMAGE_DOS_SIGNATURE) goto fail;
+    if (size.u.LowPart < dos->e_lfanew + sizeof( *ne )) goto fail;
+    ne = (const IMAGE_OS2_HEADER *)(ptr + dos->e_lfanew);
+    rsrc_off = dos->e_lfanew + ne->ne_rsrctab;
+    if (size.u.LowPart < rsrc_off + 10) goto fail;
+    align = *(WORD *)(ptr + rsrc_off);
+    rsrc_off += 2;
+    type_id = *(WORD *)(ptr + rsrc_off);
+    while (type_id && type_id != 0x80cc)
+    {
+        count = *(WORD *)(ptr + rsrc_off + 2);
+        rsrc_off += 8 + count * 12;
+        if (size.u.LowPart < rsrc_off + 8) goto fail;
+        type_id = *(WORD *)(ptr + rsrc_off);
+    }
+    if (!type_id) goto fail;
+    count = *(WORD *)(ptr + rsrc_off + 2);
+    if (size.u.LowPart < rsrc_off + 8 + count * 12) goto fail;
+
+    res_off = *(WORD *)(ptr + rsrc_off + 8) << align;
+    res_len = *(WORD *)(ptr + rsrc_off + 10) << align;
+    if (size.u.LowPart < res_off + res_len) goto fail;
+
+    for (i = 0; i < res_len; i++)
+        if (ptr[ res_off + i ] == 0) break;
+    if (i == res_len) goto fail;
+
+    len = MultiByteToWideChar( CP_ACP, 0, (char *)ptr + res_off, -1, NULL, 0 );
+    name = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
+    if (name) MultiByteToWideChar( CP_ACP, 0, (char *)ptr + res_off, -1, name, len );
+
+fail:
+    UnmapViewOfFile( ptr );
+    return name;
+}
+
 /***********************************************************************
  *           AddFontResourceExW    (GDI32.@)
  */
 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
 {
     int ret = WineEngAddFontResourceEx(str, fl, pdv);
+    WCHAR *filename;
+
     if (ret == 0)
     {
         /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
@@ -3467,6 +3540,11 @@ INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
                 ret = num_resources;
             FreeLibrary(hModule);
         }
+        else if ((filename = get_scalable_filename( str )) != NULL)
+        {
+            ret = WineEngAddFontResourceEx( filename, fl, pdv );
+            HeapFree( GetProcessHeap(), 0, filename );
+        }
     }
     return ret;
 }




More information about the wine-cvs mailing list