diff --git a/dlls/dwrite/analyzer.c b/dlls/dwrite/analyzer.c index 0f88fd9ac03..5bb9a2c9cb5 100644 --- a/dlls/dwrite/analyzer.c +++ b/dlls/dwrite/analyzer.c @@ -182,6 +182,11 @@ const char *debugstr_sa_script(UINT16 script) return script < Script_LastId ? debugstr_an((char*)&dwritescripts_properties[script].props.isoScriptCode, 4): "not defined"; } +struct dwrite_fontfallback { + IDWriteFontFallback IDWriteFontFallback_iface; + IDWriteFactory2 *factory; +}; + struct dwrite_numbersubstitution { IDWriteNumberSubstitution IDWriteNumberSubstitution_iface; LONG ref; @@ -196,6 +201,11 @@ static inline struct dwrite_numbersubstitution *impl_from_IDWriteNumberSubstitut return CONTAINING_RECORD(iface, struct dwrite_numbersubstitution, IDWriteNumberSubstitution_iface); } +static inline struct dwrite_fontfallback *impl_from_IDWriteFontFallback(IDWriteFontFallback *iface) +{ + return CONTAINING_RECORD(iface, struct dwrite_fontfallback, IDWriteFontFallback_iface); +} + static inline UINT32 decode_surrogate_pair(const WCHAR *str, UINT32 index, UINT32 end) { if (index < end-1 && IS_SURROGATE_PAIR(str[index], str[index+1])) { @@ -1677,3 +1687,77 @@ HRESULT create_numbersubstitution(DWRITE_NUMBER_SUBSTITUTION_METHOD method, cons *ret = &substitution->IDWriteNumberSubstitution_iface; return S_OK; } + +/* IDWriteFontFallback */ +static HRESULT WINAPI fontfallback_QueryInterface(IDWriteFontFallback *iface, REFIID riid, void **obj) +{ + struct dwrite_fontfallback *fallback = impl_from_IDWriteFontFallback(iface); + + TRACE("(%p)->(%s %p)\n", fallback, debugstr_guid(riid), obj); + + if (IsEqualIID(riid, &IID_IDWriteFontFallback) || IsEqualIID(riid, &IID_IUnknown)) { + *obj = iface; + IDWriteFontFallback_AddRef(iface); + return S_OK; + } + + *obj = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI fontfallback_AddRef(IDWriteFontFallback *iface) +{ + struct dwrite_fontfallback *fallback = impl_from_IDWriteFontFallback(iface); + TRACE("(%p)\n", fallback); + return IDWriteFactory2_AddRef(fallback->factory); +} + +static ULONG WINAPI fontfallback_Release(IDWriteFontFallback *iface) +{ + struct dwrite_fontfallback *fallback = impl_from_IDWriteFontFallback(iface); + TRACE("(%p)\n", fallback); + return IDWriteFactory2_Release(fallback->factory); +} + +static HRESULT WINAPI fontfallback_MapCharacters(IDWriteFontFallback *iface, IDWriteTextAnalysisSource *source, + UINT32 position, UINT32 length, IDWriteFontCollection *basecollection, const WCHAR *basefamily, + DWRITE_FONT_WEIGHT weight, DWRITE_FONT_STYLE style, DWRITE_FONT_STRETCH stretch, UINT32 *mapped_length, + IDWriteFont **mapped_font, FLOAT *scale) +{ + struct dwrite_fontfallback *fallback = impl_from_IDWriteFontFallback(iface); + + FIXME("(%p)->(%p %u %u %p, %s, %u, %u, %u, %p, %p, %p): stub\n", fallback, source, position, length, + basecollection, debugstr_w(basefamily), weight, style, stretch, mapped_length, mapped_font, scale); + + return E_NOTIMPL; +} + +static const IDWriteFontFallbackVtbl fontfallbackvtbl = { + fontfallback_QueryInterface, + fontfallback_AddRef, + fontfallback_Release, + fontfallback_MapCharacters +}; + +HRESULT create_system_fontfallback(IDWriteFactory2 *factory, IDWriteFontFallback **ret) +{ + struct dwrite_fontfallback *fallback; + + *ret = NULL; + + fallback = heap_alloc(sizeof(*fallback)); + if (!fallback) + return E_OUTOFMEMORY; + + fallback->IDWriteFontFallback_iface.lpVtbl = &fontfallbackvtbl; + fallback->factory = factory; + + *ret = &fallback->IDWriteFontFallback_iface; + return S_OK; +} + +void release_system_fontfallback(IDWriteFontFallback *iface) +{ + struct dwrite_fontfallback *fallback = impl_from_IDWriteFontFallback(iface); + heap_free(fallback); +} diff --git a/dlls/dwrite/dwrite_private.h b/dlls/dwrite/dwrite_private.h index 874f0bbbeb5..9f0171b5900 100644 --- a/dlls/dwrite/dwrite_private.h +++ b/dlls/dwrite/dwrite_private.h @@ -142,6 +142,8 @@ extern HRESULT get_family_names_from_stream(IDWriteFontFileStream*,UINT32,DWRITE extern HRESULT create_colorglyphenum(FLOAT,FLOAT,const DWRITE_GLYPH_RUN*,const DWRITE_GLYPH_RUN_DESCRIPTION*,DWRITE_MEASURING_MODE, const DWRITE_MATRIX*,UINT32,IDWriteColorGlyphRunEnumerator**) DECLSPEC_HIDDEN; extern BOOL lb_is_newline_char(WCHAR) DECLSPEC_HIDDEN; +extern HRESULT create_system_fontfallback(IDWriteFactory2*,IDWriteFontFallback**) DECLSPEC_HIDDEN; +extern void release_system_fontfallback(IDWriteFontFallback*) DECLSPEC_HIDDEN; /* Opentype font table functions */ struct dwrite_font_props { diff --git a/dlls/dwrite/main.c b/dlls/dwrite/main.c index e1aed0cacad..588549819cc 100644 --- a/dlls/dwrite/main.c +++ b/dlls/dwrite/main.c @@ -512,6 +512,7 @@ struct dwritefactory { IDWriteFontCollection *system_collection; IDWriteFontCollection *eudc_collection; IDWriteGdiInterop *gdiinterop; + IDWriteFontFallback *fallback; IDWriteLocalFontFileLoader* localfontfileloader; struct list localfontfaces; @@ -525,6 +526,12 @@ static inline struct dwritefactory *impl_from_IDWriteFactory2(IDWriteFactory2 *i return CONTAINING_RECORD(iface, struct dwritefactory, IDWriteFactory2_iface); } +void notify_factory_fallback_removed(IDWriteFactory2 *iface) +{ + struct dwritefactory *factory = impl_from_IDWriteFactory2(iface); + factory->fallback = NULL; +} + static void release_fontface_cache(struct list *fontfaces) { struct fontfacecached *fontface, *fontface2; @@ -567,6 +574,8 @@ static void release_dwritefactory(struct dwritefactory *factory) IDWriteFontCollection_Release(factory->eudc_collection); if (factory->gdiinterop) release_gdiinterop(factory->gdiinterop); + if (factory->fallback) + release_system_fontfallback(factory->fallback); heap_free(factory); } @@ -1148,8 +1157,20 @@ static HRESULT WINAPI dwritefactory1_CreateCustomRenderingParams(IDWriteFactory2 static HRESULT WINAPI dwritefactory2_GetSystemFontFallback(IDWriteFactory2 *iface, IDWriteFontFallback **fallback) { struct dwritefactory *This = impl_from_IDWriteFactory2(iface); - FIXME("(%p)->(%p): stub\n", This, fallback); - return E_NOTIMPL; + + TRACE("(%p)->(%p)\n", This, fallback); + + *fallback = NULL; + + if (!This->fallback) { + HRESULT hr = create_system_fontfallback(iface, &This->fallback); + if (FAILED(hr)) + return hr; + } + + *fallback = This->fallback; + IDWriteFontFallback_AddRef(*fallback); + return S_OK; } static HRESULT WINAPI dwritefactory2_CreateFontFallbackBuilder(IDWriteFactory2 *iface, IDWriteFontFallbackBuilder **fallbackbuilder) @@ -1282,6 +1303,7 @@ static void init_dwritefactory(struct dwritefactory *factory, DWRITE_FACTORY_TYP factory->system_collection = NULL; factory->eudc_collection = NULL; factory->gdiinterop = NULL; + factory->fallback = NULL; list_init(&factory->collection_loaders); list_init(&factory->file_loaders); diff --git a/dlls/dwrite/tests/layout.c b/dlls/dwrite/tests/layout.c index 89a63053aa6..4df6e002472 100644 --- a/dlls/dwrite/tests/layout.c +++ b/dlls/dwrite/tests/layout.c @@ -2383,9 +2383,7 @@ if (0) /* crashes on native */ fallback = NULL; hr = IDWriteFactory2_GetSystemFontFallback(factory2, &fallback); -todo_wine ok(hr == S_OK, "got 0x%08x\n", hr); -if (hr == S_OK) { ok(fallback != NULL, "got %p\n", fallback); hr = IDWriteTextFormat1_SetFontFallback(format1, fallback); @@ -2405,7 +2403,6 @@ if (hr == S_OK) { ok(fallback2 == NULL, "got %p\n", fallback2); IDWriteFontFallback_Release(fallback); -} IDWriteTextFormat1_Release(format1); IDWriteTextLayout2_Release(layout2); IDWriteFactory_Release(factory); @@ -4248,9 +4245,7 @@ static void test_MapCharacters(void) fallback = NULL; hr = IDWriteFactory2_GetSystemFontFallback(factory2, &fallback); -todo_wine ok(hr == S_OK, "got 0x%08x\n", hr); -if (hr == S_OK) { ok(fallback != NULL, "got %p\n", fallback); mappedlength = 1; @@ -4258,11 +4253,12 @@ if (hr == S_OK) { font = (void*)0xdeadbeef; hr = IDWriteFontFallback_MapCharacters(fallback, NULL, 0, 0, NULL, NULL, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL, DWRITE_FONT_STRETCH_NORMAL, &mappedlength, &font, &scale); +todo_wine { ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); ok(mappedlength == 0, "got %u\n", mappedlength); ok(scale == 1.0f, "got %f\n", scale); ok(font == NULL, "got %p\n", font); - +} /* zero length source */ g_source = strW; mappedlength = 1; @@ -4270,21 +4266,25 @@ if (hr == S_OK) { font = (void*)0xdeadbeef; hr = IDWriteFontFallback_MapCharacters(fallback, &analysissource, 0, 0, NULL, NULL, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL, DWRITE_FONT_STRETCH_NORMAL, &mappedlength, &font, &scale); +todo_wine { ok(hr == S_OK, "got 0x%08x\n", hr); ok(mappedlength == 0, "got %u\n", mappedlength); ok(scale == 1.0f, "got %f\n", scale); ok(font == NULL, "got %p\n", font); - +} g_source = strW; mappedlength = 0; scale = 0.0f; font = NULL; hr = IDWriteFontFallback_MapCharacters(fallback, &analysissource, 0, 1, NULL, NULL, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL, DWRITE_FONT_STRETCH_NORMAL, &mappedlength, &font, &scale); +todo_wine { ok(hr == S_OK, "got 0x%08x\n", hr); ok(mappedlength == 1, "got %u\n", mappedlength); ok(scale == 1.0f, "got %f\n", scale); ok(font != NULL, "got %p\n", font); +} +if (font) IDWriteFont_Release(font); /* same latin text, full length */ @@ -4294,10 +4294,13 @@ if (hr == S_OK) { font = NULL; hr = IDWriteFontFallback_MapCharacters(fallback, &analysissource, 0, 3, NULL, NULL, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL, DWRITE_FONT_STRETCH_NORMAL, &mappedlength, &font, &scale); +todo_wine { ok(hr == S_OK, "got 0x%08x\n", hr); ok(mappedlength == 3, "got %u\n", mappedlength); ok(scale == 1.0f, "got %f\n", scale); ok(font != NULL, "got %p\n", font); +} +if (font) IDWriteFont_Release(font); /* string 'a\x3058b' */ @@ -4307,10 +4310,13 @@ if (hr == S_OK) { font = NULL; hr = IDWriteFontFallback_MapCharacters(fallback, &analysissource, 0, 3, NULL, NULL, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL, DWRITE_FONT_STRETCH_NORMAL, &mappedlength, &font, &scale); +todo_wine { ok(hr == S_OK, "got 0x%08x\n", hr); ok(mappedlength == 1, "got %u\n", mappedlength); ok(scale == 1.0f, "got %f\n", scale); ok(font != NULL, "got %p\n", font); +} +if (font) IDWriteFont_Release(font); g_source = str2W; @@ -4319,11 +4325,13 @@ if (hr == S_OK) { font = NULL; hr = IDWriteFontFallback_MapCharacters(fallback, &analysissource, 1, 2, NULL, NULL, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL, DWRITE_FONT_STRETCH_NORMAL, &mappedlength, &font, &scale); +todo_wine { ok(hr == S_OK, "got 0x%08x\n", hr); ok(mappedlength == 1, "got %u\n", mappedlength); ok(scale == 1.0f, "got %f\n", scale); ok(font != NULL, "got %p\n", font); - +} +if (font) { /* font returned for Hiragana character, check if it supports Latin too */ exists = FALSE; hr = IDWriteFont_HasCharacter(font, 'b', &exists); @@ -4331,7 +4339,7 @@ if (hr == S_OK) { ok(exists, "got %d\n", exists); IDWriteFont_Release(font); - +} /* Try with explicit collection, Tahoma will be forced. */ /* 1. Latin part */ g_source = str2W; @@ -4340,11 +4348,14 @@ if (hr == S_OK) { font = NULL; hr = IDWriteFontFallback_MapCharacters(fallback, &analysissource, 0, 3, &fallbackcollection, g_blahfontW, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL, DWRITE_FONT_STRETCH_NORMAL, &mappedlength, &font, &scale); +todo_wine { ok(hr == S_OK, "got 0x%08x\n", hr); ok(mappedlength == 1, "got %u\n", mappedlength); ok(scale == 1.0f, "got %f\n", scale); ok(font != NULL, "got %p\n", font); +} +if (font) { exists = FALSE; hr = IDWriteFont_GetInformationalStrings(font, DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES, &strings, &exists); ok(hr == S_OK && exists, "got 0x%08x, exists %d\n", hr, exists); @@ -4354,7 +4365,7 @@ if (hr == S_OK) { IDWriteLocalizedStrings_Release(strings); IDWriteFont_Release(font); - +} /* 2. Hiragana character, force Tahoma font does not support Japanese */ g_source = str2W; mappedlength = 0; @@ -4362,11 +4373,14 @@ if (hr == S_OK) { font = NULL; hr = IDWriteFontFallback_MapCharacters(fallback, &analysissource, 1, 1, &fallbackcollection, g_blahfontW, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL, DWRITE_FONT_STRETCH_NORMAL, &mappedlength, &font, &scale); +todo_wine { ok(hr == S_OK, "got 0x%08x\n", hr); ok(mappedlength == 1, "got %u\n", mappedlength); ok(scale == 1.0f, "got %f\n", scale); ok(font != NULL, "got %p\n", font); +} +if (font) { exists = FALSE; hr = IDWriteFont_GetInformationalStrings(font, DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES, &strings, &exists); ok(hr == S_OK && exists, "got 0x%08x, exists %d\n", hr, exists); @@ -4376,8 +4390,8 @@ if (hr == S_OK) { IDWriteLocalizedStrings_Release(strings); IDWriteFont_Release(font); - IDWriteFontFallback_Release(fallback); } + IDWriteFontFallback_Release(fallback); IDWriteFactory2_Release(factory2); }