[PATCH 1/2] dwrite: Rework Analyze() to make it easier to extend

Nikolay Sivov nsivov at codeweavers.com
Thu Feb 4 18:09:43 CST 2016


Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
 dlls/dwrite/opentype.c | 107 +++++++++++++++++++++++++++++++++++++------------
 1 file changed, 82 insertions(+), 25 deletions(-)

diff --git a/dlls/dwrite/opentype.c b/dlls/dwrite/opentype.c
index 5898fb4..a7c0aee 100644
--- a/dlls/dwrite/opentype.c
+++ b/dlls/dwrite/opentype.c
@@ -715,50 +715,107 @@ BOOL is_face_type_supported(DWRITE_FONT_FACE_TYPE type)
            (type == DWRITE_FONT_FACE_TYPE_RAW_CFF);
 }
 
-HRESULT opentype_analyze_font(IDWriteFontFileStream *stream, UINT32* font_count, DWRITE_FONT_FILE_TYPE *file_type, DWRITE_FONT_FACE_TYPE *face_type, BOOL *supported)
+typedef HRESULT (*dwrite_fontfile_analyzer)(IDWriteFontFileStream *stream, UINT32 *font_count, DWRITE_FONT_FILE_TYPE *file_type,
+    DWRITE_FONT_FACE_TYPE *face_type);
+
+static HRESULT opentype_ttc_analyzer(IDWriteFontFileStream *stream, UINT32 *font_count, DWRITE_FONT_FILE_TYPE *file_type,
+    DWRITE_FONT_FACE_TYPE *face_type)
 {
-    /* TODO: Do font validation */
-    DWRITE_FONT_FACE_TYPE face;
-    const void *font_data;
-    const char* tag;
+    static const DWORD ttctag = MS_TTCF_TAG;
+    const TTC_Header_V1 *header;
     void *context;
     HRESULT hr;
 
-    hr = IDWriteFontFileStream_ReadFileFragment(stream, &font_data, 0, sizeof(TTC_Header_V1), &context);
+    hr = IDWriteFontFileStream_ReadFileFragment(stream, (const void**)&header, 0, sizeof(header), &context);
     if (FAILED(hr))
         return hr;
 
-    tag = font_data;
-    *file_type = DWRITE_FONT_FILE_TYPE_UNKNOWN;
-    face = DWRITE_FONT_FACE_TYPE_UNKNOWN;
-    *font_count = 0;
-
-    if (DWRITE_MAKE_OPENTYPE_TAG(tag[0], tag[1], tag[2], tag[3]) == MS_TTCF_TAG)
-    {
-        const TTC_Header_V1 *header = font_data;
+    if (!memcmp(header->TTCTag, &ttctag, sizeof(ttctag))) {
         *font_count = GET_BE_DWORD(header->numFonts);
         *file_type = DWRITE_FONT_FILE_TYPE_TRUETYPE_COLLECTION;
-        face = DWRITE_FONT_FACE_TYPE_TRUETYPE_COLLECTION;
+        *face_type = DWRITE_FONT_FACE_TYPE_TRUETYPE_COLLECTION;
     }
-    else if (GET_BE_DWORD(*(DWORD*)font_data) == 0x10000)
-    {
+
+    IDWriteFontFileStream_ReleaseFileFragment(stream, context);
+
+    return *file_type != DWRITE_FONT_FILE_TYPE_UNKNOWN ? S_OK : S_FALSE;
+}
+
+static HRESULT opentype_ttf_analyzer(IDWriteFontFileStream *stream, UINT32 *font_count, DWRITE_FONT_FILE_TYPE *file_type,
+    DWRITE_FONT_FACE_TYPE *face_type)
+{
+    const DWORD *header;
+    void *context;
+    HRESULT hr;
+
+    hr = IDWriteFontFileStream_ReadFileFragment(stream, (const void**)&header, 0, sizeof(*header), &context);
+    if (FAILED(hr))
+        return hr;
+
+    if (GET_BE_DWORD(*header) == 0x10000) {
         *font_count = 1;
         *file_type = DWRITE_FONT_FILE_TYPE_TRUETYPE;
-        face = DWRITE_FONT_FACE_TYPE_TRUETYPE;
+        *face_type = DWRITE_FONT_FACE_TYPE_TRUETYPE;
     }
-    else if (DWRITE_MAKE_OPENTYPE_TAG(tag[0], tag[1], tag[2], tag[3]) == MS_OTTO_TAG)
-    {
+
+    IDWriteFontFileStream_ReleaseFileFragment(stream, context);
+
+    return *file_type != DWRITE_FONT_FILE_TYPE_UNKNOWN ? S_OK : S_FALSE;
+}
+
+static HRESULT opentype_otf_analyzer(IDWriteFontFileStream *stream, UINT32 *font_count, DWRITE_FONT_FILE_TYPE *file_type,
+    DWRITE_FONT_FACE_TYPE *face_type)
+{
+    const DWORD *header;
+    void *context;
+    HRESULT hr;
+
+    hr = IDWriteFontFileStream_ReadFileFragment(stream, (const void**)&header, 0, sizeof(*header), &context);
+    if (FAILED(hr))
+        return hr;
+
+    if (GET_BE_DWORD(*header) == MS_OTTO_TAG) {
         *font_count = 1;
         *file_type = DWRITE_FONT_FILE_TYPE_CFF;
-        face = DWRITE_FONT_FACE_TYPE_CFF;
+        *face_type = DWRITE_FONT_FACE_TYPE_CFF;
     }
 
-    if (face_type)
-        *face_type = face;
+    IDWriteFontFileStream_ReleaseFileFragment(stream, context);
 
-    *supported = is_face_type_supported(face);
+    return *file_type != DWRITE_FONT_FILE_TYPE_UNKNOWN ? S_OK : S_FALSE;
+}
 
-    IDWriteFontFileStream_ReleaseFileFragment(stream, context);
+HRESULT opentype_analyze_font(IDWriteFontFileStream *stream, UINT32* font_count, DWRITE_FONT_FILE_TYPE *file_type, DWRITE_FONT_FACE_TYPE *face_type, BOOL *supported)
+{
+    static dwrite_fontfile_analyzer fontfile_analyzers[] = {
+        opentype_ttf_analyzer,
+        opentype_otf_analyzer,
+        opentype_ttc_analyzer,
+        NULL
+    };
+    dwrite_fontfile_analyzer *analyzer = fontfile_analyzers;
+    DWRITE_FONT_FACE_TYPE face;
+    HRESULT hr;
+
+    if (!face_type)
+        face_type = &face;
+
+    *file_type = DWRITE_FONT_FILE_TYPE_UNKNOWN;
+    *face_type = DWRITE_FONT_FACE_TYPE_UNKNOWN;
+    *font_count = 0;
+
+    while (*analyzer) {
+        hr = (*analyzer)(stream, font_count, file_type, face_type);
+        if (FAILED(hr))
+            return hr;
+
+        if (hr == S_OK)
+            break;
+
+        analyzer++;
+    }
+
+    *supported = is_face_type_supported(*face_type);
     return S_OK;
 }
 
-- 
2.7.0




More information about the wine-patches mailing list