[PATCH] dwrite: Reuse streams when initializing font data and creating faces

Nikolay Sivov nsivov at codeweavers.com
Wed Oct 18 06:53:06 CDT 2017


Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
 dlls/dwrite/dwrite_private.h |   3 +-
 dlls/dwrite/font.c           | 126 +++++++++++++++++++------------------------
 dlls/dwrite/main.c           |  31 +++++++----
 dlls/dwrite/opentype.c       |   7 +--
 4 files changed, 83 insertions(+), 84 deletions(-)

diff --git a/dlls/dwrite/dwrite_private.h b/dlls/dwrite/dwrite_private.h
index 6c3088b044..457d863d7b 100644
--- a/dlls/dwrite/dwrite_private.h
+++ b/dlls/dwrite/dwrite_private.h
@@ -151,6 +151,7 @@ struct fontface_desc
     IDWriteFactory5 *factory;
     DWRITE_FONT_FACE_TYPE face_type;
     IDWriteFontFile * const *files;
+    IDWriteFontFileStream *stream;
     UINT32 files_number;
     UINT32 index;
     DWRITE_FONT_SIMULATIONS simulations;
@@ -228,7 +229,7 @@ struct file_stream_desc {
     UINT32 face_index;
 };
 
-extern HRESULT opentype_analyze_font(IDWriteFontFileStream*,UINT32*,DWRITE_FONT_FILE_TYPE*,DWRITE_FONT_FACE_TYPE*,BOOL*) DECLSPEC_HIDDEN;
+extern HRESULT opentype_analyze_font(IDWriteFontFileStream*,BOOL*,DWRITE_FONT_FILE_TYPE*,DWRITE_FONT_FACE_TYPE*,UINT32*) DECLSPEC_HIDDEN;
 extern HRESULT opentype_get_font_table(struct file_stream_desc*,UINT32,const void**,void**,UINT32*,BOOL*) DECLSPEC_HIDDEN;
 extern HRESULT opentype_cmap_get_unicode_ranges(void*,UINT32,DWRITE_UNICODE_RANGE*,UINT32*) DECLSPEC_HIDDEN;
 extern void opentype_get_font_properties(struct file_stream_desc*,struct dwrite_font_props*) DECLSPEC_HIDDEN;
diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c
index cab220a826..c545f09c0a 100644
--- a/dlls/dwrite/font.c
+++ b/dlls/dwrite/font.c
@@ -217,7 +217,7 @@ struct dwrite_fontface {
     IDWriteFontFace4 IDWriteFontFace4_iface;
     LONG ref;
 
-    IDWriteFontFileStream **streams;
+    IDWriteFontFileStream *stream;
     IDWriteFontFile **files;
     UINT32 file_count;
     UINT32 index;
@@ -515,12 +515,11 @@ static ULONG WINAPI dwritefontface_Release(IDWriteFontFace4 *iface)
         if (This->colr.context)
             IDWriteFontFace4_ReleaseFontTable(iface, This->colr.context);
         for (i = 0; i < This->file_count; i++) {
-            if (This->streams[i])
-                IDWriteFontFileStream_Release(This->streams[i]);
             if (This->files[i])
                 IDWriteFontFile_Release(This->files[i]);
         }
-        heap_free(This->streams);
+        if (This->stream)
+            IDWriteFontFileStream_Release(This->stream);
         heap_free(This->files);
 
         for (i = 0; i < sizeof(This->glyphs)/sizeof(This->glyphs[0]); i++)
@@ -665,7 +664,7 @@ static HRESULT WINAPI dwritefontface_TryGetFontTable(IDWriteFontFace4 *iface, UI
 
     TRACE("(%p)->(%s %p %p %p %p)\n", This, debugstr_tag(table_tag), table_data, table_size, context, exists);
 
-    stream_desc.stream = This->streams[0];
+    stream_desc.stream = This->stream;
     stream_desc.face_type = This->type;
     stream_desc.face_index = This->index;
     return opentype_get_font_table(&stream_desc, table_tag, table_data, context, table_size, exists);
@@ -677,7 +676,7 @@ static void WINAPI dwritefontface_ReleaseFontTable(IDWriteFontFace4 *iface, void
 
     TRACE("(%p)->(%p)\n", This, table_context);
 
-    IDWriteFontFileStream_ReleaseFileFragment(This->streams[0], table_context);
+    IDWriteFontFileStream_ReleaseFileFragment(This->stream, table_context);
 }
 
 static HRESULT WINAPI dwritefontface_GetGlyphRunOutline(IDWriteFontFace4 *iface, FLOAT emSize,
@@ -1395,6 +1394,9 @@ static HRESULT get_fontface_from_font(struct dwrite_font *font, IDWriteFontFace4
     if (hr == S_OK)
         return hr;
 
+    if (FAILED(hr = get_filestream_from_file(data->file, &desc.stream)))
+        return hr;
+
     desc.factory = font->family->collection->factory;
     desc.face_type = data->face_type;
     desc.files = &data->file;
@@ -1402,7 +1404,10 @@ static HRESULT get_fontface_from_font(struct dwrite_font *font, IDWriteFontFace4
     desc.index = data->face_index;
     desc.simulations = data->simulations;
     desc.font_data = data;
-    return create_fontface(&desc, cached_list, fontface);
+    hr = create_fontface(&desc, cached_list, fontface);
+
+    IDWriteFontFileStream_Release(desc.stream);
+    return hr;
 }
 
 static HRESULT WINAPI dwritefont_QueryInterface(IDWriteFont3 *iface, REFIID riid, void **obj)
@@ -3322,26 +3327,21 @@ static BOOL font_apply_differentiation_rules(struct dwrite_font_data *font, WCHA
     return TRUE;
 }
 
-static HRESULT init_font_data(const struct fontface_desc *desc, IDWriteLocalizedStrings **family_name, struct dwrite_font_data **ret)
+static HRESULT init_font_data(const struct fontface_desc *desc, IDWriteLocalizedStrings **family_name,
+        struct dwrite_font_data **ret)
 {
     struct file_stream_desc stream_desc;
     struct dwrite_font_props props;
     struct dwrite_font_data *data;
-    IDWriteFontFileStream *stream;
     WCHAR familyW[255], faceW[255];
     HRESULT hr;
 
     *ret = NULL;
+
     data = heap_alloc_zero(sizeof(*data));
     if (!data)
         return E_OUTOFMEMORY;
 
-    hr = get_filestream_from_file(desc->files[0], &stream);
-    if (FAILED(hr)) {
-        heap_free(data);
-        return hr;
-    }
-
     data->ref = 1;
     data->file = desc->files[0];
     data->face_index = desc->index;
@@ -3351,7 +3351,7 @@ static HRESULT init_font_data(const struct fontface_desc *desc, IDWriteLocalized
     data->oblique_sim_tested = 0;
     IDWriteFontFile_AddRef(data->file);
 
-    stream_desc.stream = stream;
+    stream_desc.stream = desc->stream;
     stream_desc.face_type = desc->face_type;
     stream_desc.face_index = desc->index;
     opentype_get_font_properties(&stream_desc, &props);
@@ -3360,7 +3360,6 @@ static HRESULT init_font_data(const struct fontface_desc *desc, IDWriteLocalized
 
     /* get family name from font file */
     hr = opentype_get_font_familyname(&stream_desc, family_name);
-    IDWriteFontFileStream_Release(stream);
     if (FAILED(hr)) {
         WARN("unable to get family name from font\n");
         release_font_data(data);
@@ -3700,6 +3699,7 @@ HRESULT create_font_collection(IDWriteFactory5 *factory, IDWriteFontFileEnumerat
         DWRITE_FONT_FACE_TYPE face_type;
         DWRITE_FONT_FILE_TYPE file_type;
         BOOL supported, same = FALSE;
+        IDWriteFontFileStream *stream;
         IDWriteFontFile *file;
         UINT32 face_count;
 
@@ -3723,10 +3723,16 @@ HRESULT create_font_collection(IDWriteFactory5 *factory, IDWriteFontFileEnumerat
             continue;
         }
 
-        /* failed font files are skipped */
-        hr = IDWriteFontFile_Analyze(file, &supported, &file_type, &face_type, &face_count);
+        if (FAILED(get_filestream_from_file(file, &stream))) {
+            IDWriteFontFile_Release(file);
+            continue;
+        }
+
+        /* Unsupported formats are skipped. */
+        hr = opentype_analyze_font(stream, &supported, &file_type, &face_type, &face_count);
         if (FAILED(hr) || !supported || face_count == 0) {
-            TRACE("unsupported font (%p, 0x%08x, %d, %u)\n", file, hr, supported, face_count);
+            TRACE("Unsupported font (%p, 0x%08x, %d, %u)\n", file, hr, supported, face_count);
+            IDWriteFontFileStream_Release(stream);
             IDWriteFontFile_Release(file);
             hr = S_OK;
             continue;
@@ -3747,6 +3753,7 @@ HRESULT create_font_collection(IDWriteFactory5 *factory, IDWriteFontFileEnumerat
             desc.factory = factory;
             desc.face_type = face_type;
             desc.files = &file;
+            desc.stream = stream;
             desc.files_number = 1;
             desc.index = i;
             desc.simulations = DWRITE_FONT_SIMULATIONS_NONE;
@@ -4031,24 +4038,31 @@ static HRESULT eudc_collection_add_family(IDWriteFactory5 *factory, struct dwrit
 {
     static const WCHAR defaultfontW[] = {'S','y','s','t','e','m','D','e','f','a','u','l','t','E','U','D','C','F','o','n','t',0};
     static const WCHAR emptyW[] = {0};
+    struct dwrite_fontfamily_data *family_data;
     IDWriteLocalizedStrings *names;
     DWRITE_FONT_FACE_TYPE face_type;
     DWRITE_FONT_FILE_TYPE file_type;
-    BOOL supported;
-    UINT32 face_count, i;
+    IDWriteFontFileStream *stream;
     IDWriteFontFile *file;
+    UINT32 face_count, i;
+    BOOL supported;
     HRESULT hr;
-    struct dwrite_fontfamily_data *family_data;
 
     /* create font file from this path */
     hr = create_local_file_reference(factory, pathW, &file);
     if (FAILED(hr))
         return S_FALSE;
 
-    /* failed font files are skipped */
-    hr = IDWriteFontFile_Analyze(file, &supported, &file_type, &face_type, &face_count);
+    if (FAILED(get_filestream_from_file(file, &stream))) {
+        IDWriteFontFile_Release(file);
+        return S_FALSE;
+    }
+
+    /* Unsupported formats are skipped. */
+    hr = opentype_analyze_font(stream, &supported, &file_type, &face_type, &face_count);
     if (FAILED(hr) || !supported || face_count == 0) {
-        TRACE("unsupported font (%p, 0x%08x, %d, %u)\n", file, hr, supported, face_count);
+        TRACE("Unsupported font (%p, 0x%08x, %d, %u)\n", file, hr, supported, face_count);
+        IDWriteFontFileStream_Release(stream);
         IDWriteFontFile_Release(file);
         return S_FALSE;
     }
@@ -4080,6 +4094,7 @@ static HRESULT eudc_collection_add_family(IDWriteFactory5 *factory, struct dwrit
         desc.face_type = face_type;
         desc.index = i;
         desc.files = &file;
+        desc.stream = stream;
         desc.files_number = 1;
         desc.simulations = DWRITE_FONT_SIMULATIONS_NONE;
         desc.font_data = NULL;
@@ -4100,6 +4115,7 @@ static HRESULT eudc_collection_add_family(IDWriteFactory5 *factory, struct dwrit
     hr = fontcollection_add_family(collection, family_data);
     if (FAILED(hr))
         release_fontfamily_data(family_data);
+    IDWriteFontFileStream_Release(stream);
     IDWriteFontFile_Release(file);
 
     return hr;
@@ -4243,26 +4259,26 @@ static HRESULT WINAPI dwritefontfile_GetLoader(IDWriteFontFile *iface, IDWriteFo
     return S_OK;
 }
 
-static HRESULT WINAPI dwritefontfile_Analyze(IDWriteFontFile *iface, BOOL *isSupportedFontType, DWRITE_FONT_FILE_TYPE *fontFileType,
-    DWRITE_FONT_FACE_TYPE *fontFaceType, UINT32 *numberOfFaces)
+static HRESULT WINAPI dwritefontfile_Analyze(IDWriteFontFile *iface, BOOL *is_supported, DWRITE_FONT_FILE_TYPE *file_type,
+    DWRITE_FONT_FACE_TYPE *face_type, UINT32 *face_count)
 {
     struct dwrite_fontfile *This = impl_from_IDWriteFontFile(iface);
     IDWriteFontFileStream *stream;
     HRESULT hr;
 
-    TRACE("(%p)->(%p, %p, %p, %p)\n", This, isSupportedFontType, fontFileType, fontFaceType, numberOfFaces);
+    TRACE("(%p)->(%p, %p, %p, %p)\n", This, is_supported, file_type, face_type, face_count);
 
-    *isSupportedFontType = FALSE;
-    *fontFileType = DWRITE_FONT_FILE_TYPE_UNKNOWN;
-    if (fontFaceType)
-        *fontFaceType = DWRITE_FONT_FACE_TYPE_UNKNOWN;
-    *numberOfFaces = 0;
+    *is_supported = FALSE;
+    *file_type = DWRITE_FONT_FILE_TYPE_UNKNOWN;
+    if (face_type)
+        *face_type = DWRITE_FONT_FACE_TYPE_UNKNOWN;
+    *face_count = 0;
 
     hr = IDWriteFontFileLoader_CreateStreamFromKey(This->loader, This->reference_key, This->key_size, &stream);
     if (FAILED(hr))
         return hr;
 
-    hr = opentype_analyze_font(stream, numberOfFaces, fontFileType, fontFaceType, isSupportedFontType);
+    hr = opentype_analyze_font(stream, is_supported, file_type, face_type, face_count);
 
     /* TODO: Further Analysis */
     IDWriteFontFileStream_Release(stream);
@@ -4308,30 +4324,6 @@ HRESULT create_font_file(IDWriteFontFileLoader *loader, const void *reference_ke
     return S_OK;
 }
 
-static HRESULT get_stream_from_file(IDWriteFontFile *file, IDWriteFontFileStream **stream)
-{
-    IDWriteFontFileLoader *loader;
-    UINT32 key_size;
-    const void *key;
-    HRESULT hr;
-
-    *stream = NULL;
-    hr = IDWriteFontFile_GetLoader(file, &loader);
-    if (FAILED(hr))
-        return hr;
-
-    hr = IDWriteFontFile_GetReferenceKey(file, &key, &key_size);
-    if (FAILED(hr)) {
-        IDWriteFontFileLoader_Release(loader);
-        return hr;
-    }
-
-    hr = IDWriteFontFileLoader_CreateStreamFromKey(loader, key, key_size, stream);
-    IDWriteFontFileLoader_Release(loader);
-
-    return hr;
-}
-
 HRESULT create_fontface(const struct fontface_desc *desc, struct list *cached_list, IDWriteFontFace4 **ret)
 {
     struct file_stream_desc stream_desc;
@@ -4347,11 +4339,7 @@ HRESULT create_fontface(const struct fontface_desc *desc, struct list *cached_li
         return E_OUTOFMEMORY;
 
     fontface->files = heap_alloc_zero(sizeof(*fontface->files) * desc->files_number);
-    fontface->streams = heap_alloc_zero(sizeof(*fontface->streams) * desc->files_number);
-
-    if (!fontface->files || !fontface->streams) {
-        heap_free(fontface->files);
-        heap_free(fontface->streams);
+    if (!fontface->files) {
         heap_free(fontface);
         return E_OUTOFMEMORY;
     }
@@ -4370,17 +4358,13 @@ HRESULT create_fontface(const struct fontface_desc *desc, struct list *cached_li
     IDWriteFactory5_AddRef(fontface->factory = desc->factory);
 
     for (i = 0; i < fontface->file_count; i++) {
-        hr = get_stream_from_file(desc->files[i], &fontface->streams[i]);
-        if (FAILED(hr)) {
-            IDWriteFontFace4_Release(&fontface->IDWriteFontFace4_iface);
-            return hr;
-        }
-
         fontface->files[i] = desc->files[i];
         IDWriteFontFile_AddRef(fontface->files[i]);
     }
+    fontface->stream = desc->stream;
+    IDWriteFontFileStream_AddRef(fontface->stream);
 
-    stream_desc.stream = fontface->streams[0];
+    stream_desc.stream = fontface->stream;
     stream_desc.face_type = desc->face_type;
     stream_desc.face_index = desc->index;
     opentype_get_font_metrics(&stream_desc, &fontface->metrics, &fontface->caret);
diff --git a/dlls/dwrite/main.c b/dlls/dwrite/main.c
index 7237a0ee88..c4d2a5f5e7 100644
--- a/dlls/dwrite/main.c
+++ b/dlls/dwrite/main.c
@@ -943,10 +943,11 @@ static HRESULT WINAPI dwritefactory_CreateFontFace(IDWriteFactory5 *iface, DWRIT
     struct dwritefactory *This = impl_from_IDWriteFactory5(iface);
     DWRITE_FONT_FILE_TYPE file_type;
     DWRITE_FONT_FACE_TYPE face_type;
+    IDWriteFontFileStream *stream;
     struct fontface_desc desc;
     struct list *fontfaces;
     BOOL is_supported;
-    UINT32 count;
+    UINT32 face_count;
     HRESULT hr;
 
     TRACE("(%p)->(%d %u %p %u 0x%x %p)\n", This, req_facetype, files_number, font_files, index,
@@ -963,32 +964,44 @@ static HRESULT WINAPI dwritefactory_CreateFontFace(IDWriteFactory5 *iface, DWRIT
     if (!is_simulation_valid(simulations))
         return E_INVALIDARG;
 
+    if (FAILED(hr = get_filestream_from_file(*font_files, &stream)))
+        return hr;
+
     /* check actual file/face type */
     is_supported = FALSE;
     face_type = DWRITE_FONT_FACE_TYPE_UNKNOWN;
-    hr = IDWriteFontFile_Analyze(*font_files, &is_supported, &file_type, &face_type, &count);
+    hr = opentype_analyze_font(stream, &is_supported, &file_type, &face_type, &face_count);
     if (FAILED(hr))
-        return hr;
+        goto failed;
 
-    if (!is_supported)
-        return E_FAIL;
+    if (!is_supported) {
+        hr = E_FAIL;
+        goto failed;
+    }
 
-    if (face_type != req_facetype)
-        return DWRITE_E_FILEFORMAT;
+    if (face_type != req_facetype) {
+        hr = DWRITE_E_FILEFORMAT;
+        goto failed;
+    }
 
     hr = factory_get_cached_fontface(iface, font_files, index, simulations, &fontfaces,
             &IID_IDWriteFontFace, (void **)fontface);
     if (hr != S_FALSE)
-        return hr;
+        goto failed;
 
     desc.factory = iface;
     desc.face_type = req_facetype;
     desc.files = font_files;
+    desc.stream = stream;
     desc.files_number = files_number;
     desc.index = index;
     desc.simulations = simulations;
     desc.font_data = NULL;
-    return create_fontface(&desc, fontfaces, (IDWriteFontFace4 **)fontface);
+    hr = create_fontface(&desc, fontfaces, (IDWriteFontFace4 **)fontface);
+
+failed:
+    IDWriteFontFileStream_Release(stream);
+    return hr;
 }
 
 static HRESULT WINAPI dwritefactory_CreateRenderingParams(IDWriteFactory5 *iface, IDWriteRenderingParams **params)
diff --git a/dlls/dwrite/opentype.c b/dlls/dwrite/opentype.c
index e3bf483dba..4f570f586c 100644
--- a/dlls/dwrite/opentype.c
+++ b/dlls/dwrite/opentype.c
@@ -1029,7 +1029,8 @@ static HRESULT opentype_type1_analyzer(IDWriteFontFileStream *stream, UINT32 *fo
     return *file_type != DWRITE_FONT_FILE_TYPE_UNKNOWN ? S_OK : S_FALSE;
 }
 
-HRESULT opentype_analyze_font(IDWriteFontFileStream *stream, UINT32* font_count, DWRITE_FONT_FILE_TYPE *file_type, DWRITE_FONT_FACE_TYPE *face_type, BOOL *supported)
+HRESULT opentype_analyze_font(IDWriteFontFileStream *stream, BOOL *supported, DWRITE_FONT_FILE_TYPE *file_type,
+        DWRITE_FONT_FACE_TYPE *face_type, UINT32 *face_count)
 {
     static dwrite_fontfile_analyzer fontfile_analyzers[] = {
         opentype_ttf_analyzer,
@@ -1047,10 +1048,10 @@ HRESULT opentype_analyze_font(IDWriteFontFileStream *stream, UINT32* font_count,
 
     *file_type = DWRITE_FONT_FILE_TYPE_UNKNOWN;
     *face_type = DWRITE_FONT_FACE_TYPE_UNKNOWN;
-    *font_count = 0;
+    *face_count = 0;
 
     while (*analyzer) {
-        hr = (*analyzer)(stream, font_count, file_type, face_type);
+        hr = (*analyzer)(stream, face_count, file_type, face_type);
         if (FAILED(hr))
             return hr;
 
-- 
2.14.2




More information about the wine-patches mailing list