Aric Stewart : dwrite: Implement TryGetFontTable and ReleaseFontTable.

Alexandre Julliard julliard at wine.codeweavers.com
Wed Aug 20 14:30:35 CDT 2014


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

Author: Aric Stewart <aric at codeweavers.com>
Date:   Sat Aug 16 20:42:24 2014 -0500

dwrite: Implement TryGetFontTable and ReleaseFontTable.

---

 dlls/dwrite/dwrite_private.h |  1 +
 dlls/dwrite/font.c           | 65 ++++++++++++++++++++++++++++++--
 dlls/dwrite/opentype.c       | 88 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 151 insertions(+), 3 deletions(-)

diff --git a/dlls/dwrite/dwrite_private.h b/dlls/dwrite/dwrite_private.h
index f56b6f0..a64e632 100644
--- a/dlls/dwrite/dwrite_private.h
+++ b/dlls/dwrite/dwrite_private.h
@@ -94,3 +94,4 @@ extern HRESULT font_create_fontface(IDWriteFactory *iface, DWRITE_FONT_FACE_TYPE
 
 /* Opentype font table functions */
 extern HRESULT analyze_opentype_font(const void* font_data, UINT32* font_count, DWRITE_FONT_FILE_TYPE *file_type, DWRITE_FONT_FACE_TYPE *face_type, BOOL *supported) DECLSPEC_HIDDEN;
+extern HRESULT find_font_table(IDWriteFontFileStream *stream, UINT32 font_index, UINT32 tag, const void** table_data, void** table_context, UINT32 *table_size, BOOL* found) DECLSPEC_HIDDEN;
diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c
index 8c82d08..0683dd5 100644
--- a/dlls/dwrite/font.c
+++ b/dlls/dwrite/font.c
@@ -156,6 +156,14 @@ struct dwrite_font {
     WCHAR *facename;
 };
 
+#define DWRITE_FONTTABLE_MAGIC 0xededfafa
+
+struct dwrite_fonttable {
+    UINT32 magic;
+    LPVOID context;
+    UINT32 file_index;
+};
+
 struct dwrite_fontface {
     IDWriteFontFace IDWriteFontFace_iface;
     LONG ref;
@@ -384,14 +392,65 @@ static HRESULT WINAPI dwritefontface_TryGetFontTable(IDWriteFontFace *iface, UIN
     const void **table_data, UINT32 *table_size, void **context, BOOL *exists)
 {
     struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
-    FIXME("(%p)->(%u %p %p %p %p): stub\n", This, table_tag, table_data, table_size, context, exists);
-    return E_NOTIMPL;
+    if (This->is_system)
+    {
+        FIXME("(%p)->(%u %p %p %p %p): stub\n", This, table_tag, table_data, table_size, context, exists);
+        return E_NOTIMPL;
+    }
+    else
+    {
+        HRESULT hr = S_OK;
+        int i;
+        struct dwrite_fonttable *table;
+
+        TRACE("(%p)->(%u %p %p %p %p)\n", This, table_tag, table_data, table_size, context, exists);
+
+        table = heap_alloc(sizeof(struct dwrite_fonttable));
+        table->magic = DWRITE_FONTTABLE_MAGIC;
+        if (!table)
+            return E_OUTOFMEMORY;
+
+        *exists = FALSE;
+        for (i = 0; i < This->file_count && !(*exists); i++)
+        {
+            IDWriteFontFileStream *stream;
+            hr = _dwritefontfile_GetFontFileStream(This->files[i], &stream);
+            if (FAILED(hr))
+                continue;
+            table->file_index = i;
+
+            hr = find_font_table(stream, This->index, table_tag, table_data, &table->context, table_size, exists);
+
+            IDWriteFontFileStream_Release(stream);
+        }
+        if (FAILED(hr) && !*exists)
+            heap_free(table);
+        else
+            *context = (LPVOID)table;
+        return hr;
+    }
 }
 
 static void WINAPI dwritefontface_ReleaseFontTable(IDWriteFontFace *iface, void *table_context)
 {
     struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
-    FIXME("(%p)->(%p): stub\n", This, table_context);
+    struct dwrite_fonttable *table = (struct dwrite_fonttable *)table_context;
+    IDWriteFontFileStream *stream;
+    HRESULT hr;
+    TRACE("(%p)->(%p)\n", This, table_context);
+
+    if (table->magic != DWRITE_FONTTABLE_MAGIC)
+    {
+        TRACE("Invalid table magic\n");
+        return;
+    }
+
+    hr = _dwritefontfile_GetFontFileStream(This->files[table->file_index], &stream);
+    if (FAILED(hr))
+        return;
+    IDWriteFontFileStream_ReleaseFileFragment(stream, table->context);
+    IDWriteFontFileStream_Release(stream);
+    heap_free(table);
 }
 
 static HRESULT WINAPI dwritefontface_GetGlyphRunOutline(IDWriteFontFace *iface, FLOAT emSize,
diff --git a/dlls/dwrite/opentype.c b/dlls/dwrite/opentype.c
index 538db98..6c90a96 100644
--- a/dlls/dwrite/opentype.c
+++ b/dlls/dwrite/opentype.c
@@ -47,6 +47,21 @@ typedef struct {
     DWORD OffsetTable[1];
 } TTC_Header_V1;
 
+typedef struct {
+    DWORD version;
+    WORD numTables;
+    WORD searchRange;
+    WORD entrySelector;
+    WORD rangeShift;
+} TTC_SFNT_V1;
+
+typedef struct {
+    CHAR tag[4];
+    DWORD checkSum;
+    DWORD offset;
+    DWORD length;
+} TT_TableRecord;
+
 HRESULT analyze_opentype_font(const void* font_data, UINT32* font_count, DWRITE_FONT_FILE_TYPE *file_type, DWRITE_FONT_FACE_TYPE *face_type, BOOL *supported)
 {
     /* TODO: Do font validation */
@@ -81,3 +96,76 @@ HRESULT analyze_opentype_font(const void* font_data, UINT32* font_count, DWRITE_
     }
     return S_OK;
 }
+
+HRESULT find_font_table(IDWriteFontFileStream *stream, UINT32 font_index, UINT32 tag, const void** table_data, void** table_context, UINT32 *table_size, BOOL* found)
+{
+    const CHAR *first_data;
+    void *first_context;
+    HRESULT hr;
+    TTC_SFNT_V1 *font_header = NULL;
+    void *sfnt_context;
+    TT_TableRecord *table_record = NULL;
+    void *table_record_context;
+    int i;
+    int table_count;
+    int table_offset = 0;
+
+    *found = FALSE;
+
+    hr = IDWriteFontFileStream_ReadFileFragment(stream, (const void**)&first_data, 0, 4, &first_context);
+    if (SUCCEEDED(hr))
+    {
+        if (DWRITE_MAKE_OPENTYPE_TAG(first_data[0], first_data[1], first_data[2], first_data[3]) == MS_TTCF_TAG)
+        {
+            const TTC_Header_V1 *ttc_header;
+            void * ttc_context;
+            hr = IDWriteFontFileStream_ReadFileFragment(stream, (const void**)&ttc_header, 0, sizeof(*ttc_header), &ttc_context);
+            if (SUCCEEDED(hr))
+            {
+                table_offset = GET_BE_DWORD(ttc_header->OffsetTable[0]);
+                if (font_index >= GET_BE_DWORD(ttc_header->numFonts))
+                    hr = E_INVALIDARG;
+                else
+                    hr = IDWriteFontFileStream_ReadFileFragment(stream, (const void**)&font_header, table_offset, sizeof(*font_header), &sfnt_context);
+                IDWriteFontFileStream_ReleaseFileFragment(stream, ttc_context);
+            }
+        }
+        else
+        {
+            if (font_index > 0)
+                hr = E_INVALIDARG;
+            else
+                hr = IDWriteFontFileStream_ReadFileFragment(stream, (const void**)&font_header, 0, sizeof(*font_header), &sfnt_context);
+        }
+        IDWriteFontFileStream_ReleaseFileFragment(stream, first_context);
+    }
+    if (FAILED(hr))
+        return hr;
+
+    table_count = GET_BE_WORD(font_header->numTables);
+    table_offset += sizeof(*font_header);
+    for (i = 0; i < table_count; i++)
+    {
+        hr = IDWriteFontFileStream_ReadFileFragment(stream, (const void**)&table_record, table_offset, sizeof(*table_record), &table_record_context);
+        if (FAILED(hr))
+            break;
+        if (DWRITE_MAKE_OPENTYPE_TAG(table_record->tag[0], table_record->tag[1], table_record->tag[2], table_record->tag[3]) == tag)
+            break;
+        IDWriteFontFileStream_ReleaseFileFragment(stream, table_record_context);
+        table_offset += sizeof(*table_record);
+    }
+
+    IDWriteFontFileStream_ReleaseFileFragment(stream, sfnt_context);
+    if (SUCCEEDED(hr) && i < table_count)
+    {
+        int offset = GET_BE_DWORD(table_record->offset);
+        int length = GET_BE_DWORD(table_record->length);
+        IDWriteFontFileStream_ReleaseFileFragment(stream, table_record_context);
+
+        *found = TRUE;
+        *table_size = length;
+        hr = IDWriteFontFileStream_ReadFileFragment(stream, table_data, offset, length, table_context);
+    }
+
+    return hr;
+}




More information about the wine-cvs mailing list