[PATCH 1/4] dwrite: Return some of font properties from IDWriteFontFace3 methods

Nikolay Sivov nsivov at codeweavers.com
Tue Jul 5 04:55:53 CDT 2016


Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
 dlls/dwrite/bidi.c           |   1 -
 dlls/dwrite/dwrite_private.h |  17 ++++-
 dlls/dwrite/font.c           | 144 +++++++++++++++++++++++++++++++------------
 dlls/dwrite/layout.c         |   1 -
 dlls/dwrite/main.c           | 142 ++++++++++++++++++++++++++----------------
 dlls/dwrite/tests/font.c     |  63 +++++++++++++++++--
 6 files changed, 264 insertions(+), 104 deletions(-)

diff --git a/dlls/dwrite/bidi.c b/dlls/dwrite/bidi.c
index 32c4075..3a7367e 100644
--- a/dlls/dwrite/bidi.c
+++ b/dlls/dwrite/bidi.c
@@ -46,7 +46,6 @@
 #include "windef.h"
 #include "winbase.h"
 #include "wine/debug.h"
-#include "wine/list.h"
 
 #include "dwrite_private.h"
 
diff --git a/dlls/dwrite/dwrite_private.h b/dlls/dwrite/dwrite_private.h
index 61409c8..3309f3f 100644
--- a/dlls/dwrite/dwrite_private.h
+++ b/dlls/dwrite/dwrite_private.h
@@ -20,6 +20,7 @@
 #include "d2d1.h"
 
 #include "wine/debug.h"
+#include "wine/list.h"
 #include "wine/unicode.h"
 
 static const DWRITE_MATRIX identity =
@@ -151,6 +152,17 @@ struct glyphrunanalysis_desc
     FLOAT ppdip;
 };
 
+struct fontface_desc
+{
+    IDWriteFactory3 *factory;
+    DWRITE_FONT_FACE_TYPE face_type;
+    IDWriteFontFile * const *files;
+    UINT32 files_number;
+    UINT32 index;
+    DWRITE_FONT_SIMULATIONS simulations;
+    struct dwrite_font_data *font_data; /* could be NULL when face is created directly with IDWriteFactory::CreateFontFace() */
+};
+
 extern HRESULT convert_fontface_to_logfont(IDWriteFontFace*, LOGFONTW*) DECLSPEC_HIDDEN;
 extern HRESULT create_numbersubstitution(DWRITE_NUMBER_SUBSTITUTION_METHOD,const WCHAR *locale,BOOL,IDWriteNumberSubstitution**) DECLSPEC_HIDDEN;
 extern HRESULT create_textformat(const WCHAR*,IDWriteFontCollection*,DWRITE_FONT_WEIGHT,DWRITE_FONT_STYLE,DWRITE_FONT_STRETCH,
@@ -168,7 +180,7 @@ extern HRESULT get_eudc_fontcollection(IDWriteFactory3*,IDWriteFontCollection**)
 extern HRESULT get_textanalyzer(IDWriteTextAnalyzer**) DECLSPEC_HIDDEN;
 extern HRESULT create_font_file(IDWriteFontFileLoader *loader, const void *reference_key, UINT32 key_size, IDWriteFontFile **font_file) DECLSPEC_HIDDEN;
 extern HRESULT create_localfontfileloader(IDWriteLocalFontFileLoader** iface) DECLSPEC_HIDDEN;
-extern HRESULT create_fontface(DWRITE_FONT_FACE_TYPE,UINT32,IDWriteFontFile* const*,UINT32,DWRITE_FONT_SIMULATIONS,IDWriteFontFace3**) DECLSPEC_HIDDEN;
+extern HRESULT create_fontface(const struct fontface_desc*,IDWriteFontFace3**) DECLSPEC_HIDDEN;
 extern HRESULT create_font_collection(IDWriteFactory3*,IDWriteFontFileEnumerator*,BOOL,IDWriteFontCollection**) DECLSPEC_HIDDEN;
 extern HRESULT create_glyphrunanalysis(const struct glyphrunanalysis_desc*,IDWriteGlyphRunAnalysis**) DECLSPEC_HIDDEN;
 extern BOOL    is_system_collection(IDWriteFontCollection*) DECLSPEC_HIDDEN;
@@ -185,6 +197,9 @@ extern HRESULT create_matching_font(IDWriteFontCollection*,const WCHAR*,DWRITE_F
     IDWriteFont**) DECLSPEC_HIDDEN;
 extern HRESULT create_fontfacereference(IDWriteFactory3*,IDWriteFontFile*,UINT32,DWRITE_FONT_SIMULATIONS,
     IDWriteFontFaceReference**) DECLSPEC_HIDDEN;
+extern HRESULT factory_get_cached_fontface(IDWriteFactory3*,IDWriteFontFile*const*,UINT32,DWRITE_FONT_SIMULATIONS,IDWriteFontFace**,
+    struct list**) DECLSPEC_HIDDEN;
+extern void    factory_cache_fontface(struct list*,IDWriteFontFace3*) DECLSPEC_HIDDEN;
 
 /* Opentype font table functions */
 struct dwrite_font_props {
diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c
index b625f7a..c99c5c3 100644
--- a/dlls/dwrite/font.c
+++ b/dlls/dwrite/font.c
@@ -23,7 +23,6 @@
 
 #define COBJMACROS
 
-#include "wine/list.h"
 #include "dwrite_private.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(dwrite);
@@ -230,6 +229,11 @@ struct dwrite_fontface {
     struct dwrite_fonttable cpal;
     struct dwrite_fonttable colr;
     DWRITE_GLYPH_METRICS *glyphs[GLYPH_MAX/GLYPH_BLOCK_SIZE];
+
+    DWRITE_FONT_STYLE style;
+    DWRITE_FONT_STRETCH stretch;
+    DWRITE_FONT_WEIGHT weight;
+    DWRITE_PANOSE panose;
 };
 
 struct dwrite_fontfile {
@@ -1068,28 +1072,29 @@ static HRESULT WINAPI dwritefontface3_GetFontFaceReference(IDWriteFontFace3 *ifa
 static void WINAPI dwritefontface3_GetPanose(IDWriteFontFace3 *iface, DWRITE_PANOSE *panose)
 {
     struct dwrite_fontface *This = impl_from_IDWriteFontFace3(iface);
-    FIXME("(%p)->(%p): stub\n", This, panose);
+    TRACE("(%p)->(%p)\n", This, panose);
+    *panose = This->panose;
 }
 
 static DWRITE_FONT_WEIGHT WINAPI dwritefontface3_GetWeight(IDWriteFontFace3 *iface)
 {
     struct dwrite_fontface *This = impl_from_IDWriteFontFace3(iface);
-    FIXME("(%p): stub\n", This);
-    return DWRITE_FONT_WEIGHT_NORMAL;
+    TRACE("(%p)\n", This);
+    return This->weight;
 }
 
 static DWRITE_FONT_STRETCH WINAPI dwritefontface3_GetStretch(IDWriteFontFace3 *iface)
 {
     struct dwrite_fontface *This = impl_from_IDWriteFontFace3(iface);
-    FIXME("(%p): stub\n", This);
-    return DWRITE_FONT_STRETCH_NORMAL;
+    TRACE("(%p)\n", This);
+    return This->stretch;
 }
 
 static DWRITE_FONT_STYLE WINAPI dwritefontface3_GetStyle(IDWriteFontFace3 *iface)
 {
     struct dwrite_fontface *This = impl_from_IDWriteFontFace3(iface);
-    FIXME("(%p): stub\n", This);
-    return DWRITE_FONT_STYLE_NORMAL;
+    TRACE("(%p)\n", This);
+    return This->style;
 }
 
 static HRESULT WINAPI dwritefontface3_GetFamilyNames(IDWriteFontFace3 *iface, IDWriteLocalizedStrings **names)
@@ -1275,20 +1280,31 @@ static const IDWriteFontFace3Vtbl dwritefontfacevtbl = {
 static HRESULT get_fontface_from_font(struct dwrite_font *font, IDWriteFontFace3 **fontface)
 {
     struct dwrite_font_data *data = font->data;
-    IDWriteFontFace *face;
+    struct fontface_desc desc;
+    struct list *cached_list;
     HRESULT hr;
 
     *fontface = NULL;
 
-    hr = IDWriteFactory3_CreateFontFace(data->factory, data->face_type, 1, &data->file,
-            data->face_index, font->data->simulations, &face);
+    hr = factory_get_cached_fontface(data->factory, &data->file, data->face_index,
+        font->data->simulations, (IDWriteFontFace**)fontface, &cached_list);
+    if (hr != S_FALSE)
+        return hr;
+
+    desc.factory = data->factory;
+    desc.face_type = data->face_type;
+    desc.files = &data->file;
+    desc.files_number = 1;
+    desc.index = data->face_index;
+    desc.simulations = data->simulations;
+    desc.font_data = data;
+    hr = create_fontface(&desc, fontface);
     if (FAILED(hr))
         return hr;
 
-    hr = IDWriteFontFace_QueryInterface(face, &IID_IDWriteFontFace3, (void**)fontface);
-    IDWriteFontFace_Release(face);
+    factory_cache_fontface(cached_list, *fontface);
 
-    return hr;
+    return S_OK;
 }
 
 static HRESULT WINAPI dwritefont_QueryInterface(IDWriteFont3 *iface, REFIID riid, void **obj)
@@ -3136,8 +3152,7 @@ static BOOL font_apply_differentiation_rules(struct dwrite_font_data *font, WCHA
     return TRUE;
 }
 
-static HRESULT init_font_data(IDWriteFactory3 *factory, IDWriteFontFile *file, DWRITE_FONT_FACE_TYPE face_type, UINT32 face_index,
-    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;
@@ -3151,26 +3166,26 @@ static HRESULT init_font_data(IDWriteFactory3 *factory, IDWriteFontFile *file, D
     if (!data)
         return E_OUTOFMEMORY;
 
-    hr = get_filestream_from_file(file, &stream);
+    hr = get_filestream_from_file(desc->files[0], &stream);
     if (FAILED(hr)) {
         heap_free(data);
         return hr;
     }
 
     data->ref = 1;
-    data->factory = factory;
-    data->file = file;
-    data->face_index = face_index;
-    data->face_type = face_type;
+    data->factory = desc->factory;
+    data->file = desc->files[0];
+    data->face_index = desc->index;
+    data->face_type = desc->face_type;
     data->simulations = DWRITE_FONT_SIMULATIONS_NONE;
     data->bold_sim_tested = 0;
     data->oblique_sim_tested = 0;
-    IDWriteFontFile_AddRef(file);
-    IDWriteFactory3_AddRef(factory);
+    IDWriteFontFile_AddRef(data->file);
+    IDWriteFactory3_AddRef(data->factory);
 
     stream_desc.stream = stream;
-    stream_desc.face_type = face_type;
-    stream_desc.face_index = face_index;
+    stream_desc.face_type = desc->face_type;
+    stream_desc.face_index = desc->index;
     opentype_get_font_properties(&stream_desc, &props);
     opentype_get_font_metrics(&stream_desc, &data->metrics, NULL);
     opentype_get_font_facename(&stream_desc, &data->names);
@@ -3550,11 +3565,20 @@ HRESULT create_font_collection(IDWriteFactory3 *factory, IDWriteFontFileEnumerat
         for (i = 0; i < face_count; i++) {
             IDWriteLocalizedStrings *family_name = NULL;
             struct dwrite_font_data *font_data;
+            struct fontface_desc desc;
             WCHAR familyW[255];
             UINT32 index;
 
+            desc.factory = factory;
+            desc.face_type = face_type;
+            desc.files = &file;
+            desc.files_number = 1;
+            desc.index = i;
+            desc.simulations = DWRITE_FONT_SIMULATIONS_NONE;
+            desc.font_data = NULL;
+
             /* alloc and init new font data structure */
-            hr = init_font_data(factory, file, face_type, i, &family_name, &font_data);
+            hr = init_font_data(&desc, &family_name, &font_data);
             if (FAILED(hr)) {
                 /* move to next one */
                 hr = S_OK;
@@ -3855,9 +3879,18 @@ static HRESULT eudc_collection_add_family(IDWriteFactory3 *factory, struct dwrit
     /* fill with faces */
     for (i = 0; i < face_count; i++) {
         struct dwrite_font_data *font_data;
+        struct fontface_desc desc;
 
         /* alloc and init new font data structure */
-        hr = init_font_data(factory, file, face_type, i, &names, &font_data);
+        desc.factory = factory;
+        desc.face_type = face_type;
+        desc.index = i;
+        desc.files = &file;
+        desc.files_number = 1;
+        desc.simulations = DWRITE_FONT_SIMULATIONS_NONE;
+        desc.font_data = NULL;
+
+        hr = init_font_data(&desc, &names, &font_data);
         if (FAILED(hr))
             continue;
 
@@ -4092,8 +4125,7 @@ static HRESULT get_stream_from_file(IDWriteFontFile *file, IDWriteFontFileStream
     return hr;
 }
 
-HRESULT create_fontface(DWRITE_FONT_FACE_TYPE facetype, UINT32 files_number, IDWriteFontFile* const* font_files, UINT32 index,
-    DWRITE_FONT_SIMULATIONS simulations, IDWriteFontFace3 **ret)
+HRESULT create_fontface(const struct fontface_desc *desc, IDWriteFontFace3 **ret)
 {
     struct file_stream_desc stream_desc;
     struct dwrite_fontface *fontface;
@@ -4106,8 +4138,8 @@ HRESULT create_fontface(DWRITE_FONT_FACE_TYPE facetype, UINT32 files_number, IDW
     if (!fontface)
         return E_OUTOFMEMORY;
 
-    fontface->files = heap_alloc_zero(sizeof(*fontface->files) * files_number);
-    fontface->streams = heap_alloc_zero(sizeof(*fontface->streams) * files_number);
+    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);
@@ -4118,8 +4150,8 @@ HRESULT create_fontface(DWRITE_FONT_FACE_TYPE facetype, UINT32 files_number, IDW
 
     fontface->IDWriteFontFace3_iface.lpVtbl = &dwritefontfacevtbl;
     fontface->ref = 1;
-    fontface->type = facetype;
-    fontface->file_count = files_number;
+    fontface->type = desc->face_type;
+    fontface->file_count = desc->files_number;
     memset(&fontface->cmap, 0, sizeof(fontface->cmap));
     memset(&fontface->vdmx, 0, sizeof(fontface->vdmx));
     memset(&fontface->gasp, 0, sizeof(fontface->gasp));
@@ -4130,26 +4162,26 @@ HRESULT create_fontface(DWRITE_FONT_FACE_TYPE facetype, UINT32 files_number, IDW
     fontface->gasp.exists = TRUE;
     fontface->cpal.exists = TRUE;
     fontface->colr.exists = TRUE;
-    fontface->index = index;
-    fontface->simulations = simulations;
+    fontface->index = desc->index;
+    fontface->simulations = desc->simulations;
     memset(fontface->glyphs, 0, sizeof(fontface->glyphs));
 
     for (i = 0; i < fontface->file_count; i++) {
-        hr = get_stream_from_file(font_files[i], &fontface->streams[i]);
+        hr = get_stream_from_file(desc->files[i], &fontface->streams[i]);
         if (FAILED(hr)) {
             IDWriteFontFace3_Release(&fontface->IDWriteFontFace3_iface);
             return hr;
         }
 
-        fontface->files[i] = font_files[i];
-        IDWriteFontFile_AddRef(font_files[i]);
+        fontface->files[i] = desc->files[i];
+        IDWriteFontFile_AddRef(fontface->files[i]);
     }
 
     stream_desc.stream = fontface->streams[0];
-    stream_desc.face_type = facetype;
-    stream_desc.face_index = index;
+    stream_desc.face_type = desc->face_type;
+    stream_desc.face_index = desc->index;
     opentype_get_font_metrics(&stream_desc, &fontface->metrics, &fontface->caret);
-    if (simulations & DWRITE_FONT_SIMULATIONS_OBLIQUE) {
+    if (desc->simulations & DWRITE_FONT_SIMULATIONS_OBLIQUE) {
         /* TODO: test what happens if caret is already slanted */
         if (fontface->caret.slopeRise == 1) {
             fontface->caret.slopeRise = fontface->metrics.designUnitsPerEm;
@@ -4160,6 +4192,36 @@ HRESULT create_fontface(DWRITE_FONT_FACE_TYPE facetype, UINT32 files_number, IDW
     fontface->has_kerning_pairs = freetype_has_kerning_pairs(&fontface->IDWriteFontFace3_iface);
     fontface->is_monospaced = freetype_is_monospaced(&fontface->IDWriteFontFace3_iface);
 
+    /* Font properties are reused from font object when 'normal' face creation path is used:
+       collection -> family -> matching font -> fontface.
+
+       If face is created directly from factory we have to go through properties resolution.
+    */
+    if (desc->font_data) {
+        fontface->weight = desc->font_data->weight;
+        fontface->style = desc->font_data->style;
+        fontface->stretch = desc->font_data->stretch;
+        fontface->panose = desc->font_data->panose;
+    }
+    else {
+        IDWriteLocalizedStrings *names;
+        struct dwrite_font_data *data;
+
+        hr = init_font_data(desc, &names, &data);
+        if (FAILED(hr)) {
+            IDWriteFontFace3_Release(&fontface->IDWriteFontFace3_iface);
+            return hr;
+        }
+
+        fontface->weight = data->weight;
+        fontface->style = data->style;
+        fontface->stretch = data->stretch;
+        fontface->panose = data->panose;
+
+        IDWriteLocalizedStrings_Release(names);
+        release_font_data(data);
+    }
+
     *ret = &fontface->IDWriteFontFace3_iface;
     return S_OK;
 }
diff --git a/dlls/dwrite/layout.c b/dlls/dwrite/layout.c
index 6d3d8b7..fd72875 100644
--- a/dlls/dwrite/layout.c
+++ b/dlls/dwrite/layout.c
@@ -28,7 +28,6 @@
 #include "wingdi.h"
 #include "dwrite_private.h"
 #include "scripts.h"
-#include "wine/list.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(dwrite);
 
diff --git a/dlls/dwrite/main.c b/dlls/dwrite/main.c
index 9b1c50f..fc69be4 100644
--- a/dlls/dwrite/main.c
+++ b/dlls/dwrite/main.c
@@ -30,7 +30,6 @@
 
 #include "dwrite_private.h"
 #include "wine/debug.h"
-#include "wine/list.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(dwrite);
 
@@ -509,7 +508,7 @@ struct collectionloader
 struct fontfacecached
 {
     struct list entry;
-    IDWriteFontFace *fontface;
+    IDWriteFontFace3 *fontface;
 };
 
 struct fileloader
@@ -545,7 +544,7 @@ static void release_fontface_cache(struct list *fontfaces)
     struct fontfacecached *fontface, *fontface2;
     LIST_FOR_EACH_ENTRY_SAFE(fontface, fontface2, fontfaces, struct fontfacecached, entry) {
         list_remove(&fontface->entry);
-        IDWriteFontFace_Release(fontface->fontface);
+        IDWriteFontFace3_Release(fontface->fontface);
         heap_free(fontface);
     }
 }
@@ -807,47 +806,19 @@ static HRESULT WINAPI dwritefactory_CreateCustomFontFileReference(IDWriteFactory
     return create_font_file(loader, reference_key, key_size, font_file);
 }
 
-static HRESULT WINAPI dwritefactory_CreateFontFace(IDWriteFactory3 *iface,
-    DWRITE_FONT_FACE_TYPE req_facetype, UINT32 files_number, IDWriteFontFile* const* font_files,
-    UINT32 index, DWRITE_FONT_SIMULATIONS simulations, IDWriteFontFace **font_face)
+HRESULT factory_get_cached_fontface(IDWriteFactory3 *iface, IDWriteFontFile * const *font_files,
+    UINT32 index, DWRITE_FONT_SIMULATIONS simulations, IDWriteFontFace **font_face, struct list **cached_list)
 {
-    struct dwritefactory *This = impl_from_IDWriteFactory3(iface);
-    DWRITE_FONT_FILE_TYPE file_type;
-    DWRITE_FONT_FACE_TYPE face_type;
-    IDWriteFontFileLoader *loader;
+    struct dwritefactory *factory = impl_from_IDWriteFactory3(iface);
     struct fontfacecached *cached;
+    IDWriteFontFileLoader *loader;
     struct list *fontfaces;
-    IDWriteFontFace3 *face;
-    UINT32 key_size, count;
-    BOOL is_supported;
+    UINT32 key_size;
     const void *key;
     HRESULT hr;
 
-    TRACE("(%p)->(%d %u %p %u 0x%x %p)\n", This, req_facetype, files_number, font_files, index, simulations, font_face);
-
     *font_face = NULL;
-
-    if (!is_face_type_supported(req_facetype))
-        return E_INVALIDARG;
-
-    if (req_facetype != DWRITE_FONT_FACE_TYPE_TRUETYPE_COLLECTION && index)
-        return E_INVALIDARG;
-
-    if (!is_simulation_valid(simulations))
-        return E_INVALIDARG;
-
-    /* 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);
-    if (FAILED(hr))
-        return hr;
-
-    if (!is_supported)
-        return E_FAIL;
-
-    if (face_type != req_facetype)
-        return DWRITE_E_FILEFORMAT;
+    *cached_list = NULL;
 
     hr = IDWriteFontFile_GetReferenceKey(*font_files, &key, &key_size);
     if (FAILED(hr))
@@ -857,18 +828,20 @@ static HRESULT WINAPI dwritefactory_CreateFontFace(IDWriteFactory3 *iface,
     if (FAILED(hr))
         return hr;
 
-    if (loader == (IDWriteFontFileLoader*)This->localfontfileloader) {
-        fontfaces = &This->localfontfaces;
+    if (loader == (IDWriteFontFileLoader*)factory->localfontfileloader) {
+        fontfaces = &factory->localfontfaces;
         IDWriteFontFileLoader_Release(loader);
     }
     else {
-        struct fileloader *fileloader = factory_get_file_loader(This, loader);
+        struct fileloader *fileloader = factory_get_file_loader(factory, loader);
         IDWriteFontFileLoader_Release(loader);
         if (!fileloader)
             return E_INVALIDARG;
         fontfaces = &fileloader->fontfaces;
     }
 
+    *cached_list = fontfaces;
+
     /* search through cache list */
     LIST_FOR_EACH_ENTRY(cached, fontfaces, struct fontfacecached, entry) {
         UINT32 cached_key_size, count = 1, cached_face_index;
@@ -876,14 +849,14 @@ static HRESULT WINAPI dwritefactory_CreateFontFace(IDWriteFactory3 *iface,
         const void *cached_key;
         IDWriteFontFile *file;
 
-        cached_face_index = IDWriteFontFace_GetIndex(cached->fontface);
-        cached_simulations = IDWriteFontFace_GetSimulations(cached->fontface);
+        cached_face_index = IDWriteFontFace3_GetIndex(cached->fontface);
+        cached_simulations = IDWriteFontFace3_GetSimulations(cached->fontface);
 
         /* skip earlier */
         if (cached_face_index != index || cached_simulations != simulations)
             continue;
 
-        hr = IDWriteFontFace_GetFiles(cached->fontface, &count, &file);
+        hr = IDWriteFontFace3_GetFiles(cached->fontface, &count, &file);
         if (FAILED(hr))
             return hr;
 
@@ -894,27 +867,88 @@ static HRESULT WINAPI dwritefactory_CreateFontFace(IDWriteFactory3 *iface,
 
         if (cached_key_size == key_size && !memcmp(cached_key, key, key_size)) {
             TRACE("returning cached fontface %p\n", cached->fontface);
-            *font_face = cached->fontface;
-            IDWriteFontFace_AddRef(*font_face);
+            *font_face = (IDWriteFontFace*)cached->fontface;
             return S_OK;
         }
     }
 
-    hr = create_fontface(req_facetype, files_number, font_files, index, simulations, &face);
-    if (FAILED(hr))
-        return hr;
+    return S_FALSE;
+}
+
+void factory_cache_fontface(struct list *fontfaces, IDWriteFontFace3 *fontface)
+{
+    struct fontfacecached *cached;
 
     /* new cache entry */
     cached = heap_alloc(sizeof(*cached));
-    if (!cached) {
-        IDWriteFontFace3_Release(face);
-        return E_OUTOFMEMORY;
-    }
+    if (!cached)
+        return;
 
-    cached->fontface = (IDWriteFontFace*)face;
+    cached->fontface = fontface;
     list_add_tail(fontfaces, &cached->entry);
+}
+
+static HRESULT WINAPI dwritefactory_CreateFontFace(IDWriteFactory3 *iface,
+    DWRITE_FONT_FACE_TYPE req_facetype, UINT32 files_number, IDWriteFontFile* const* font_files,
+    UINT32 index, DWRITE_FONT_SIMULATIONS simulations, IDWriteFontFace **font_face)
+{
+    struct dwritefactory *This = impl_from_IDWriteFactory3(iface);
+    DWRITE_FONT_FILE_TYPE file_type;
+    DWRITE_FONT_FACE_TYPE face_type;
+    struct fontface_desc desc;
+    struct list *fontfaces;
+    IDWriteFontFace3 *face;
+    BOOL is_supported;
+    UINT32 count;
+    HRESULT hr;
+
+    TRACE("(%p)->(%d %u %p %u 0x%x %p)\n", This, req_facetype, files_number, font_files, index, simulations, font_face);
+
+    *font_face = NULL;
+
+    if (!is_face_type_supported(req_facetype))
+        return E_INVALIDARG;
+
+    if (req_facetype != DWRITE_FONT_FACE_TYPE_TRUETYPE_COLLECTION && index)
+        return E_INVALIDARG;
+
+    if (!is_simulation_valid(simulations))
+        return E_INVALIDARG;
+
+    /* 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);
+    if (FAILED(hr))
+        return hr;
+
+    if (!is_supported)
+        return E_FAIL;
+
+    if (face_type != req_facetype)
+        return DWRITE_E_FILEFORMAT;
+
+    hr = factory_get_cached_fontface(iface, font_files, index, simulations, font_face, &fontfaces);
+    if (hr == S_OK)
+        IDWriteFontFace_AddRef(*font_face);
+
+    if (hr != S_FALSE)
+        return hr;
+
+    desc.factory = iface;
+    desc.face_type = req_facetype;
+    desc.files = font_files;
+    desc.files_number = files_number;
+    desc.index = index;
+    desc.simulations = simulations;
+    desc.font_data = NULL;
+    hr = create_fontface(&desc, &face);
+    if (FAILED(hr))
+        return hr;
+
+    factory_cache_fontface(fontfaces, face);
 
-    *font_face = cached->fontface;
+    *font_face = (IDWriteFontFace*)face;
     IDWriteFontFace_AddRef(*font_face);
 
     return S_OK;
diff --git a/dlls/dwrite/tests/font.c b/dlls/dwrite/tests/font.c
index 163b481..e211712 100644
--- a/dlls/dwrite/tests/font.c
+++ b/dlls/dwrite/tests/font.c
@@ -600,19 +600,20 @@ static ULONG WINAPI resourcefontfileloader_Release(IDWriteFontFileLoader *iface)
     return 1;
 }
 
-static HRESULT WINAPI resourcefontfileloader_CreateStreamFromKey(IDWriteFontFileLoader *iface, const void *fontFileReferenceKey, UINT32 fontFileReferenceKeySize, IDWriteFontFileStream **fontFileStream)
+static HRESULT WINAPI resourcefontfileloader_CreateStreamFromKey(IDWriteFontFileLoader *iface, const void *ref_key, UINT32 key_size,
+    IDWriteFontFileStream **stream)
 {
     LPVOID data;
     DWORD size;
     HGLOBAL mem;
 
-    mem = LoadResource(GetModuleHandleA(NULL), *(HRSRC*)fontFileReferenceKey);
+    mem = LoadResource(GetModuleHandleA(NULL), *(HRSRC*)ref_key);
     ok(mem != NULL, "Failed to lock font resource\n");
     if (mem)
     {
-        size = SizeofResource(GetModuleHandleA(NULL), *(HRSRC*)fontFileReferenceKey);
+        size = SizeofResource(GetModuleHandleA(NULL), *(HRSRC*)ref_key);
         data = LockResource(mem);
-        return create_fontdatastream(data, size, fontFileStream);
+        return create_fontdatastream(data, size, stream);
     }
     return E_FAIL;
 }
@@ -2452,7 +2453,8 @@ static ULONG WINAPI fontfileloader_Release(IDWriteFontFileLoader *iface)
     return 1;
 }
 
-static HRESULT WINAPI fontfileloader_CreateStreamFromKey(IDWriteFontFileLoader *iface, const void *fontFileReferenceKey, UINT32 fontFileReferenceKeySize, IDWriteFontFileStream **fontFileStream)
+static HRESULT WINAPI fontfileloader_CreateStreamFromKey(IDWriteFontFileLoader *iface, const void *ref_key, UINT32 key_size,
+    IDWriteFontFileStream **stream)
 {
     return 0x8faecafe;
 }
@@ -4476,7 +4478,6 @@ struct VDMX_vTable
     SHORT yMin;
 };
 
-
 static const struct VDMX_group *find_vdmx_group(const struct VDMX_Header *hdr)
 {
     WORD num_ratios, i, group_offset = 0;
@@ -4813,6 +4814,8 @@ static void test_GetPanose(void)
     hr = IDWriteFont_QueryInterface(font, &IID_IDWriteFont1, (void**)&font1);
     IDWriteFont_Release(font);
     if (hr == S_OK) {
+        IDWriteFontFace3 *fontface3;
+        IDWriteFontFace *fontface;
         DWRITE_PANOSE panose;
 
     if (0) /* crashes on native */
@@ -4841,6 +4844,20 @@ static void test_GetPanose(void)
         ok(panose.text.xHeight == DWRITE_PANOSE_XHEIGHT_CONSTANT_LARGE,
             "got %u\n", panose.text.xHeight);
 
+        hr = IDWriteFont1_CreateFontFace(font1, &fontface);
+        ok(hr == S_OK, "got 0x%08x\n", hr);
+
+        hr = IDWriteFontFace_QueryInterface(fontface, &IID_IDWriteFontFace3, (void**)&fontface3);
+        IDWriteFontFace_Release(fontface);
+        if (hr == S_OK) {
+            DWRITE_PANOSE panose2;
+
+            IDWriteFontFace3_GetPanose(fontface3, &panose2);
+            ok(!memcmp(&panose, &panose2, sizeof(panose)), "wrong panose data\n");
+
+            IDWriteFontFace3_Release(fontface3);
+        }
+
         IDWriteFont1_Release(font1);
     }
     else
@@ -6250,6 +6267,39 @@ static void test_GetFontSignature(void)
     IDWriteFactory_Release(factory);
 }
 
+static void test_font_properties(void)
+{
+    IDWriteFontFace3 *fontface3;
+    IDWriteFontFace *fontface;
+    IDWriteFactory *factory;
+    DWRITE_FONT_STYLE style;
+    IDWriteFont *font;
+    HRESULT hr;
+
+    factory = create_factory();
+
+    /* this creates simulated font */
+    font = get_tahoma_instance(factory, DWRITE_FONT_STYLE_ITALIC);
+
+    style = IDWriteFont_GetStyle(font);
+    ok(style == DWRITE_FONT_STYLE_OBLIQUE, "got %u\n", style);
+
+    hr = IDWriteFont_CreateFontFace(font, &fontface);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+
+    hr = IDWriteFontFace_QueryInterface(fontface, &IID_IDWriteFontFace3, (void**)&fontface3);
+    IDWriteFontFace_Release(fontface);
+    if (hr == S_OK) {
+        style = IDWriteFontFace3_GetStyle(fontface3);
+        ok(style == DWRITE_FONT_STYLE_OBLIQUE, "got %u\n", style);
+
+        IDWriteFontFace3_Release(fontface3);
+    }
+
+    IDWriteFont_Release(font);
+    IDWriteFactory_Release(factory);
+}
+
 START_TEST(font)
 {
     IDWriteFactory *factory;
@@ -6306,6 +6356,7 @@ START_TEST(font)
     test_HasCharacter();
     test_CreateFontFaceReference();
     test_GetFontSignature();
+    test_font_properties();
 
     IDWriteFactory_Release(factory);
 }
-- 
2.8.1




More information about the wine-patches mailing list