Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/dwrite/dwrite_private.h | 2 + dlls/dwrite/font.c | 117 +++++++++++++++++++++++++++++++++++ dlls/dwrite/main.c | 11 ++-- dlls/dwrite/tests/font.c | 28 +++------ 4 files changed, 134 insertions(+), 24 deletions(-)
diff --git a/dlls/dwrite/dwrite_private.h b/dlls/dwrite/dwrite_private.h index 35cf5add34b..60e8b87f499 100644 --- a/dlls/dwrite/dwrite_private.h +++ b/dlls/dwrite/dwrite_private.h @@ -347,6 +347,8 @@ extern HRESULT create_font_resource(IDWriteFactory7 *factory, IDWriteFontFile *f extern HRESULT create_fontset_builder(IDWriteFactory7 *factory, IDWriteFontSetBuilder2 **ret) DECLSPEC_HIDDEN; extern HRESULT compute_glyph_origins(DWRITE_GLYPH_RUN const *run, DWRITE_MEASURING_MODE measuring_mode, D2D1_POINT_2F baseline_origin, DWRITE_MATRIX const *transform, D2D1_POINT_2F *origins) DECLSPEC_HIDDEN; +extern HRESULT create_font_collection_from_set(IDWriteFactory7 *factory, IDWriteFontSet *set, + DWRITE_FONT_FAMILY_MODEL family_model, REFGUID riid, void **ret) DECLSPEC_HIDDEN;
struct dwrite_fontface;
diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c index e32b2d0f4cb..23dad8970b8 100644 --- a/dlls/dwrite/font.c +++ b/dlls/dwrite/font.c @@ -624,6 +624,8 @@ static struct dwrite_fontset *impl_from_IDWriteFontSet3(IDWriteFontSet3 *iface) return CONTAINING_RECORD(iface, struct dwrite_fontset, IDWriteFontSet3_iface); }
+static struct dwrite_fontset *unsafe_impl_from_IDWriteFontSet(IDWriteFontSet *iface); + static HRESULT get_cached_glyph_metrics(struct dwrite_fontface *fontface, UINT16 glyph, DWRITE_GLYPH_METRICS *metrics) { static const DWRITE_GLYPH_METRICS nil; @@ -4791,6 +4793,113 @@ HRESULT create_font_collection(IDWriteFactory7 *factory, IDWriteFontFileEnumerat return hr; }
+static HRESULT collection_add_font_entry(struct dwrite_fontcollection *collection, const struct fontface_desc *desc) +{ + struct dwrite_font_data *font_data; + WCHAR familyW[255]; + UINT32 index; + HRESULT hr; + + if (FAILED(hr = init_font_data(desc, collection->family_model, &font_data))) + return hr; + + fontstrings_get_en_string(font_data->family_names, familyW, ARRAY_SIZE(familyW)); + + /* ignore dot named faces */ + if (familyW[0] == '.') + { + WARN("Ignoring face %s\n", debugstr_w(familyW)); + release_font_data(font_data); + return S_OK; + } + + index = collection_find_family(collection, familyW); + if (index != ~0u) + hr = fontfamily_add_font(collection->family_data[index], font_data); + else + { + struct dwrite_fontfamily_data *family_data; + + /* Create and initialize new family */ + hr = init_fontfamily_data(font_data->family_names, &family_data); + if (hr == S_OK) + { + /* add font to family, family - to collection */ + hr = fontfamily_add_font(family_data, font_data); + if (hr == S_OK) + hr = fontcollection_add_family(collection, family_data); + + if (FAILED(hr)) + release_fontfamily_data(family_data); + } + } + + if (FAILED(hr)) + release_font_data(font_data); + + return hr; +} + +HRESULT create_font_collection_from_set(IDWriteFactory7 *factory, IDWriteFontSet *fontset, + DWRITE_FONT_FAMILY_MODEL family_model, REFGUID riid, void **ret) +{ + struct dwrite_fontset *set = unsafe_impl_from_IDWriteFontSet(fontset); + struct dwrite_fontcollection *collection; + HRESULT hr = S_OK; + size_t i; + + *ret = NULL; + + if (!(collection = calloc(1, sizeof(*collection)))) + return E_OUTOFMEMORY; + + if (FAILED(hr = init_font_collection(collection, factory, family_model, FALSE))) + { + free(collection); + return hr; + } + + for (i = 0; i < set->count; ++i) + { + const struct dwrite_fontset_entry *entry = set->entries[i]; + IDWriteFontFileStream *stream; + struct fontface_desc desc; + + if (FAILED(get_filestream_from_file(entry->desc.file, &stream))) + { + WARN("Failed to get file stream.\n"); + continue; + } + + desc.factory = factory; + desc.face_type = entry->desc.face_type; + desc.file = entry->desc.file; + desc.stream = stream; + desc.index = entry->desc.face_index; + desc.simulations = entry->desc.simulations; + desc.font_data = NULL; + + if (FAILED(hr = collection_add_font_entry(collection, &desc))) + WARN("Failed to add font collection element, hr %#lx.\n", hr); + + IDWriteFontFileStream_Release(stream); + } + + if (family_model == DWRITE_FONT_FAMILY_MODEL_WEIGHT_STRETCH_STYLE) + { + for (i = 0; i < collection->count; ++i) + { + fontfamily_add_bold_simulated_face(collection->family_data[i]); + fontfamily_add_oblique_simulated_face(collection->family_data[i]); + } + } + + hr = IDWriteFontCollection3_QueryInterface(&collection->IDWriteFontCollection3_iface, riid, ret); + IDWriteFontCollection3_Release(&collection->IDWriteFontCollection3_iface); + + return hr; +} + struct system_fontfile_enumerator { IDWriteFontFileEnumerator IDWriteFontFileEnumerator_iface; @@ -7908,6 +8017,14 @@ static const IDWriteFontSet3Vtbl fontsetvtbl = dwritefontset3_GetFontSourceName, };
+static struct dwrite_fontset *unsafe_impl_from_IDWriteFontSet(IDWriteFontSet *iface) +{ + if (!iface) + return NULL; + assert(iface->lpVtbl == (IDWriteFontSetVtbl *)&fontsetvtbl); + return CONTAINING_RECORD(iface, struct dwrite_fontset, IDWriteFontSet3_iface); +} + static HRESULT fontset_create_entry(IDWriteFontFile *file, DWRITE_FONT_FACE_TYPE face_type, unsigned int face_index, unsigned int simulations, struct dwrite_fontset_entry **ret) { diff --git a/dlls/dwrite/main.c b/dlls/dwrite/main.c index 82dc34a0cdc..4d7d6a7eab0 100644 --- a/dlls/dwrite/main.c +++ b/dlls/dwrite/main.c @@ -1670,11 +1670,12 @@ static HRESULT WINAPI dwritefactory3_CreateFontSetBuilder(IDWriteFactory7 *iface }
static HRESULT WINAPI dwritefactory3_CreateFontCollectionFromFontSet(IDWriteFactory7 *iface, IDWriteFontSet *fontset, - IDWriteFontCollection1 **collection) + IDWriteFontCollection1 **collection) { - FIXME("%p, %p, %p: stub\n", iface, fontset, collection); + TRACE("%p, %p, %p.\n", iface, fontset, collection);
- return E_NOTIMPL; + return create_font_collection_from_set(iface, fontset, DWRITE_FONT_FAMILY_MODEL_WEIGHT_STRETCH_STYLE, + &IID_IDWriteFontCollection1, (void **)collection); }
static HRESULT WINAPI dwritefactory3_GetSystemFontCollection(IDWriteFactory7 *iface, BOOL include_downloadable, @@ -1856,9 +1857,9 @@ static HRESULT WINAPI dwritefactory6_GetSystemFontCollection(IDWriteFactory7 *if static HRESULT WINAPI dwritefactory6_CreateFontCollectionFromFontSet(IDWriteFactory7 *iface, IDWriteFontSet *fontset, DWRITE_FONT_FAMILY_MODEL family_model, IDWriteFontCollection2 **collection) { - FIXME("%p, %p, %d, %p.\n", iface, fontset, family_model, collection); + TRACE("%p, %p, %d, %p.\n", iface, fontset, family_model, collection);
- return E_NOTIMPL; + return create_font_collection_from_set(iface, fontset, family_model, &IID_IDWriteFontCollection2, (void **)collection); }
static HRESULT WINAPI dwritefactory6_CreateFontSetBuilder(IDWriteFactory7 *iface, IDWriteFontSetBuilder2 **builder) diff --git a/dlls/dwrite/tests/font.c b/dlls/dwrite/tests/font.c index 3d4c4caad98..2ca1a5f9c81 100644 --- a/dlls/dwrite/tests/font.c +++ b/dlls/dwrite/tests/font.c @@ -9656,14 +9656,10 @@ static void test_fontsetbuilder(void) hr = IDWriteFontSetBuilder1_CreateFontSet(builder1, &fontset); ok(hr == S_OK, "Unexpected hr %#lx.\n",hr); hr = IDWriteFactory3_CreateFontCollectionFromFontSet(factory, fontset, &collection); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n",hr); - if (SUCCEEDED(hr)) - { - count = IDWriteFontCollection1_GetFontFamilyCount(collection); - ok(count == 1, "Unexpected family count %u.\n", count); - IDWriteFontCollection1_Release(collection); - } + count = IDWriteFontCollection1_GetFontFamilyCount(collection); + ok(count == 1, "Unexpected family count %u.\n", count); + IDWriteFontCollection1_Release(collection); IDWriteFontSet_Release(fontset);
hr = IDWriteFontSetBuilder1_AddFontFile(builder1, file); @@ -9673,15 +9669,11 @@ static void test_fontsetbuilder(void) ok(hr == S_OK, "Unexpected hr %#lx.\n",hr);
hr = IDWriteFactory3_CreateFontCollectionFromFontSet(factory, fontset, &collection); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n",hr); - if (SUCCEEDED(hr)) - { - check_familymodel(collection, DWRITE_FONT_FAMILY_MODEL_WEIGHT_STRETCH_STYLE); - count = IDWriteFontCollection1_GetFontFamilyCount(collection); - ok(count == 1, "Unexpected family count %u.\n", count); - IDWriteFontCollection1_Release(collection); - } + check_familymodel(collection, DWRITE_FONT_FAMILY_MODEL_WEIGHT_STRETCH_STYLE); + count = IDWriteFontCollection1_GetFontFamilyCount(collection); + ok(count == 1, "Unexpected family count %u.\n", count); + IDWriteFontCollection1_Release(collection);
/* No attempt to eliminate duplicates. */ count = IDWriteFontSet_GetFontCount(fontset); @@ -10405,22 +10397,20 @@ static void test_CreateFontCollectionFromFontSet(void) ok(hr == S_OK, "Unexpected hr %#lx.\n",hr);
hr = IDWriteFactory5_CreateFontCollectionFromFontSet(factory, fontset, &collection); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n",hr);
-if (SUCCEEDED(hr)) -{ count = IDWriteFontCollection1_GetFontFamilyCount(collection); + todo_wine ok(count == 2, "Unexpected family count %u.\n", count);
/* Explicit fontset properties are prioritized and not replaced by actual properties from a file. */ exists = FALSE; hr = IDWriteFontCollection1_FindFamilyName(collection, L"Another Font", &index, &exists); ok(hr == S_OK, "Unexpected hr %#lx.\n",hr); + todo_wine ok(!!exists, "Unexpected return value %d.\n", exists);
IDWriteFontCollection1_Release(collection); -} IDWriteFontSet_Release(fontset);
IDWriteFontSetBuilder1_Release(builder);