Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/dwrite/tests/font.c | 165 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 159 insertions(+), 6 deletions(-)
diff --git a/dlls/dwrite/tests/font.c b/dlls/dwrite/tests/font.c index d7ced109a2f..24ad30bc845 100644 --- a/dlls/dwrite/tests/font.c +++ b/dlls/dwrite/tests/font.c @@ -124,7 +124,7 @@ static void _expect_ref_broken(IUnknown* obj, ULONG ref, ULONG brokenref, int li
static BOOL (WINAPI *pGetFontRealizationInfo)(HDC hdc, void *);
-static const WCHAR test_fontfile[] = {'w','i','n','e','_','t','e','s','t','_','f','o','n','t','.','t','t','f',0}; +static const WCHAR test_fontfile[] = L"wine_test_font.ttf";
/* PANOSE is 10 bytes in size, need to pack the structure properly */ #include "pshpack2.h" @@ -9363,10 +9363,15 @@ static void test_AnalyzeContainerType(void)
static void test_fontsetbuilder(void) { + IDWriteFontFaceReference *ref, *ref2, *ref3; IDWriteFontCollection1 *collection; + IDWriteFontSetBuilder1 *builder1; IDWriteFontSetBuilder *builder; IDWriteFactory3 *factory; - UINT32 count, i, ref; + UINT32 count, i, refcount; + IDWriteFontSet *fontset; + IDWriteFontFile *file; + WCHAR *path; HRESULT hr;
factory = create_factory_iid(&IID_IDWriteFactory3); @@ -9380,6 +9385,40 @@ static void test_fontsetbuilder(void) hr = IDWriteFactory3_CreateFontSetBuilder(factory, &builder); ok(hr == S_OK, "Failed to create font set builder, hr %#x.\n", hr); EXPECT_REF(factory, 2); + + if (SUCCEEDED(hr = IDWriteFontSetBuilder_QueryInterface(builder, &IID_IDWriteFontSetBuilder1, (void **)&builder1))) + { + path = create_testfontfile(test_fontfile); + + hr = IDWriteFactory3_CreateFontFileReference(factory, path, NULL, &file); + ok(hr == S_OK, "Unexpected hr %#x.\n",hr); + + hr = IDWriteFontSetBuilder1_AddFontFile(builder1, file); + todo_wine + ok(hr == S_OK, "Unexpected hr %#x.\n",hr); + + hr = IDWriteFontSetBuilder1_AddFontFile(builder1, file); + todo_wine + ok(hr == S_OK, "Unexpected hr %#x.\n",hr); + + hr = IDWriteFontSetBuilder1_CreateFontSet(builder1, &fontset); + todo_wine + ok(hr == S_OK, "Unexpected hr %#x.\n",hr); + + if (SUCCEEDED(hr)) + { + /* No attempt to eliminate duplicates. */ + count = IDWriteFontSet_GetFontCount(fontset); + ok(count == 2, "Unexpected font count %u.\n", count); + + IDWriteFontSet_Release(fontset); + } + + IDWriteFontFile_Release(file); + IDWriteFontSetBuilder1_Release(builder1); + } + else + win_skip("IDWriteFontSetBuilder1 is not available.\n"); IDWriteFontSetBuilder_Release(builder);
hr = IDWriteFactory3_GetSystemFontCollection(factory, FALSE, &collection, FALSE); @@ -9395,8 +9434,8 @@ static void test_fontsetbuilder(void) ok(hr == S_OK, "Failed to get family, hr %#x.\n", hr);
fontcount = IDWriteFontFamily1_GetFontCount(family); - for (j = 0; j < fontcount; j++) { - IDWriteFontFaceReference *ref, *ref2; + for (j = 0; j < fontcount; ++j) + { IDWriteFontSet *fontset; UINT32 setcount, id;
@@ -9428,6 +9467,12 @@ static void test_fontsetbuilder(void) hr = IDWriteFontSet_GetFontFaceReference(fontset, 0, &ref2); ok(hr == S_OK, "Failed to get font face reference, hr %#x.\n", hr); ok(ref2 != ref, "Unexpected reference.\n"); + + hr = IDWriteFontSet_GetFontFaceReference(fontset, 0, &ref3); + ok(hr == S_OK, "Failed to get font face reference, hr %#x.\n", hr); + ok(ref2 != ref3, "Unexpected reference.\n"); + + IDWriteFontFaceReference_Release(ref3); IDWriteFontFaceReference_Release(ref2);
for (id = DWRITE_FONT_PROPERTY_ID_FAMILY_NAME; id < DWRITE_FONT_PROPERTY_ID_TOTAL; ++id) @@ -9499,8 +9544,8 @@ static void test_fontsetbuilder(void)
IDWriteFontCollection1_Release(collection);
- ref = IDWriteFactory3_Release(factory); - ok(ref == 0, "factory not released, %u\n", ref); + refcount = IDWriteFactory3_Release(factory); + ok(!refcount, "Factory not released, %u.\n", refcount); }
static void test_font_resource(void) @@ -9805,6 +9850,112 @@ static void test_GetVerticalGlyphVariants(void) ok(!refcount, "Factory not released, refcount %u.\n", refcount); }
+static HANDLE get_collection_expiration_event(IDWriteFontCollection *collection) +{ + IDWriteFontCollection3 *collection3; + HANDLE event; + HRESULT hr; + + hr = IDWriteFontCollection_QueryInterface(collection, &IID_IDWriteFontCollection3, (void **)&collection3); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + event = IDWriteFontCollection3_GetExpirationEvent(collection3); + IDWriteFontCollection3_Release(collection3); + + return event; +} + +static void test_expiration_event(void) +{ + IDWriteFontCollection *collection, *collection2; + IDWriteFontCollection3 *collection3; + IDWriteFactory *factory, *factory2; + unsigned int refcount; + HANDLE event, event2; + HRESULT hr; + + factory = create_factory(); + + hr = IDWriteFactory_GetSystemFontCollection(factory, &collection, FALSE); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + hr = IDWriteFontCollection_QueryInterface(collection, &IID_IDWriteFontCollection3, (void **)&collection3); + if (FAILED(hr)) + { + win_skip("Expiration events are not supported.\n"); + IDWriteFontCollection_Release(collection); + IDWriteFactory_Release(factory); + return; + } + IDWriteFontCollection3_Release(collection3); + + event = get_collection_expiration_event(collection); +todo_wine + ok(!!event, "Unexpected event handle.\n"); + + /* Compare handles with another isolated factory. */ + factory2 = create_factory(); + + hr = IDWriteFactory_GetSystemFontCollection(factory2, &collection2, FALSE); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + event2 = get_collection_expiration_event(collection2); +todo_wine { + ok(!!event2, "Unexpected event handle.\n"); + ok(event != event2, "Unexpected event handle.\n"); +} + IDWriteFontCollection_Release(collection2); + + IDWriteFontCollection_Release(collection); + + refcount = IDWriteFactory_Release(factory2); + ok(!refcount, "Unexpected factory refcount %u.\n", refcount); + refcount = IDWriteFactory_Release(factory); + ok(!refcount, "Unexpected factory refcount %u.\n", refcount); +} + +static void test_family_font_set(void) +{ + IDWriteFontCollection *collection; + IDWriteFontFamily2 *family2; + IDWriteFontFamily *family; + IDWriteFactory *factory; + unsigned int refcount; + IDWriteFontSet1 *fontset, *fontset2; + HRESULT hr; + + factory = create_factory(); + + hr = IDWriteFactory_GetSystemFontCollection(factory, &collection, FALSE); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + hr = IDWriteFontCollection_GetFontFamily(collection, 0, &family); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + if (SUCCEEDED(IDWriteFontFamily_QueryInterface(family, &IID_IDWriteFontFamily2, (void **)&family2))) + { + hr = IDWriteFontFamily2_GetFontSet(family2, &fontset); + todo_wine + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + hr = IDWriteFontFamily2_GetFontSet(family2, &fontset2); + todo_wine + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + if (SUCCEEDED(hr)) + { + ok(fontset != fontset2, "Unexpected fontset instance.\n"); + IDWriteFontSet1_Release(fontset2); + IDWriteFontSet1_Release(fontset); + } + IDWriteFontFamily2_Release(family2); + } + else + win_skip("IDWriteFontFamily2 is not supported.\n"); + + IDWriteFontFamily_Release(family); + IDWriteFontCollection_Release(collection); + + refcount = IDWriteFactory_Release(factory); + ok(!refcount, "Unexpected factory refcount %u.\n", refcount); +} + START_TEST(font) { IDWriteFactory *factory; @@ -9875,6 +10026,8 @@ START_TEST(font) test_font_resource(); test_IsColorFont(); test_GetVerticalGlyphVariants(); + test_expiration_event(); + test_family_font_set();
IDWriteFactory_Release(factory); }
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/dwrite/font.c | 93 +++++++++++++++++++++++++++++++++++++--- dlls/dwrite/tests/font.c | 3 -- 2 files changed, 87 insertions(+), 9 deletions(-)
diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c index ac8f5c0a7bb..bbd73f734de 100644 --- a/dlls/dwrite/font.c +++ b/dlls/dwrite/font.c @@ -250,11 +250,22 @@ struct dwrite_fontresource IDWriteFactory7 *factory; };
+struct dwrite_fontset_entry +{ + IDWriteFontFile *file; + unsigned int face_index; + unsigned int simulations; +}; + struct dwrite_fontset_builder { IDWriteFontSetBuilder2 IDWriteFontSetBuilder2_iface; LONG refcount; IDWriteFactory7 *factory; + + struct dwrite_fontset_entry *entries; + size_t count; + size_t capacity; };
static void dwrite_grab_font_table(void *context, UINT32 table, const BYTE **data, UINT32 *size, void **data_context) @@ -7103,18 +7114,65 @@ static ULONG WINAPI dwritefontsetbuilder_Release(IDWriteFontSetBuilder2 *iface) { struct dwrite_fontset_builder *builder = impl_from_IDWriteFontSetBuilder2(iface); ULONG refcount = InterlockedDecrement(&builder->refcount); + size_t i;
TRACE("%p, refcount %u.\n", iface, refcount);
if (!refcount) { IDWriteFactory7_Release(builder->factory); + for (i = 0; i < builder->count; ++i) + IDWriteFontFile_Release(builder->entries[i].file); + heap_free(builder->entries); heap_free(builder); }
return refcount; }
+static HRESULT fontset_builder_add_entry(struct dwrite_fontset_builder *builder, IDWriteFontFile *file, + unsigned int face_index, unsigned int simulations) +{ + struct dwrite_fontset_entry *entry; + + if (!dwrite_array_reserve((void **)&builder->entries, &builder->capacity, builder->count + 1, + sizeof(*builder->entries))) + { + return E_OUTOFMEMORY; + } + + entry = &builder->entries[builder->count++]; + entry->file = file; + IDWriteFontFile_AddRef(entry->file); + entry->face_index = face_index; + entry->simulations = simulations; + + return S_OK; +} + +static HRESULT fontset_builder_add_file(struct dwrite_fontset_builder *builder, IDWriteFontFile *file) +{ + DWRITE_FONT_FILE_TYPE filetype; + DWRITE_FONT_FACE_TYPE facetype; + unsigned int i, face_count; + BOOL supported = FALSE; + HRESULT hr; + + if (FAILED(hr = IDWriteFontFile_Analyze(file, &supported, &filetype, &facetype, &face_count))) + return hr; + + if (!supported) + return DWRITE_E_FILEFORMAT; + + for (i = 0; i < face_count; ++i) + { + if (FAILED(hr = fontset_builder_add_entry(builder, file, i, DWRITE_FONT_SIMULATIONS_NONE))) + break; + } + + return hr; +} + static HRESULT WINAPI dwritefontsetbuilder_AddFontFaceReference_(IDWriteFontSetBuilder2 *iface, IDWriteFontFaceReference *ref, DWRITE_FONT_PROPERTY const *props, UINT32 prop_count) { @@ -7126,9 +7184,21 @@ static HRESULT WINAPI dwritefontsetbuilder_AddFontFaceReference_(IDWriteFontSetB static HRESULT WINAPI dwritefontsetbuilder_AddFontFaceReference(IDWriteFontSetBuilder2 *iface, IDWriteFontFaceReference *ref) { - FIXME("%p, %p.\n", iface, ref); + struct dwrite_fontset_builder *builder = impl_from_IDWriteFontSetBuilder2(iface); + unsigned int face_index, simulations; + IDWriteFontFile *file; + HRESULT hr;
- return E_NOTIMPL; + TRACE("%p, %p.\n", iface, ref); + + if (FAILED(hr = IDWriteFontFaceReference_GetFontFile(ref, &file))) return hr; + + face_index = IDWriteFontFaceReference_GetFontFaceIndex(ref); + simulations = IDWriteFontFaceReference_GetSimulations(ref); + hr = fontset_builder_add_entry(builder, file, face_index, simulations); + IDWriteFontFile_Release(file); + + return hr; }
static HRESULT WINAPI dwritefontsetbuilder_AddFontSet(IDWriteFontSetBuilder2 *iface, IDWriteFontSet *fontset) @@ -7147,9 +7217,11 @@ static HRESULT WINAPI dwritefontsetbuilder_CreateFontSet(IDWriteFontSetBuilder2
static HRESULT WINAPI dwritefontsetbuilder1_AddFontFile(IDWriteFontSetBuilder2 *iface, IDWriteFontFile *file) { - FIXME("%p, %p.\n", iface, file); + struct dwrite_fontset_builder *builder = impl_from_IDWriteFontSetBuilder2(iface);
- return E_NOTIMPL; + TRACE("%p, %p.\n", iface, file); + + return fontset_builder_add_file(builder, file); }
static HRESULT WINAPI dwritefontsetbuilder2_AddFont(IDWriteFontSetBuilder2 *iface, IDWriteFontFile *file, @@ -7165,9 +7237,18 @@ static HRESULT WINAPI dwritefontsetbuilder2_AddFont(IDWriteFontSetBuilder2 *ifac
static HRESULT WINAPI dwritefontsetbuilder2_AddFontFile(IDWriteFontSetBuilder2 *iface, const WCHAR *filepath) { - FIXME("%p, %s.\n", iface, debugstr_w(filepath)); + struct dwrite_fontset_builder *builder = impl_from_IDWriteFontSetBuilder2(iface); + IDWriteFontFile *file; + HRESULT hr;
- return E_NOTIMPL; + TRACE("%p, %s.\n", iface, debugstr_w(filepath)); + + if (FAILED(hr = IDWriteFactory7_CreateFontFileReference(builder->factory, filepath, NULL, &file))) + return hr; + + hr = fontset_builder_add_file(builder, file); + IDWriteFontFile_Release(file); + return hr; }
static const IDWriteFontSetBuilder2Vtbl fontsetbuildervtbl = diff --git a/dlls/dwrite/tests/font.c b/dlls/dwrite/tests/font.c index 24ad30bc845..c377f20556b 100644 --- a/dlls/dwrite/tests/font.c +++ b/dlls/dwrite/tests/font.c @@ -9394,11 +9394,9 @@ static void test_fontsetbuilder(void) ok(hr == S_OK, "Unexpected hr %#x.\n",hr);
hr = IDWriteFontSetBuilder1_AddFontFile(builder1, file); - todo_wine ok(hr == S_OK, "Unexpected hr %#x.\n",hr);
hr = IDWriteFontSetBuilder1_AddFontFile(builder1, file); - todo_wine ok(hr == S_OK, "Unexpected hr %#x.\n",hr);
hr = IDWriteFontSetBuilder1_CreateFontSet(builder1, &fontset); @@ -9451,7 +9449,6 @@ static void test_fontsetbuilder(void)
EXPECT_REF(ref, 1); hr = IDWriteFontSetBuilder_AddFontFaceReference(builder, ref); - todo_wine ok(hr == S_OK, "Failed to add fontface reference, hr %#x.\n", hr); EXPECT_REF(ref, 1);