From e9d4725326ab8d9d3be50c2f4d75606abded2363 Mon Sep 17 00:00:00 2001 From: Nikolay Sivov Date: Fri, 25 Dec 2015 15:57:57 +0300 Subject: [PATCH] dwrite: Store per-range typography property. Signed-off-by: Nikolay Sivov Signed-off-by: Alexandre Julliard --- dlls/dwrite/layout.c | 101 +++++++++++++++++++++++++++++++-------------- dlls/dwrite/tests/layout.c | 57 +++++++++++++++++++++++++ 2 files changed, 126 insertions(+), 32 deletions(-) diff --git a/dlls/dwrite/layout.c b/dlls/dwrite/layout.c index 22c36a3c5d1..66998b6a58c 100644 --- a/dlls/dwrite/layout.c +++ b/dlls/dwrite/layout.c @@ -74,7 +74,8 @@ enum layout_range_attr_kind { LAYOUT_RANGE_ATTR_FONTCOLL, LAYOUT_RANGE_ATTR_LOCALE, LAYOUT_RANGE_ATTR_FONTFAMILY, - LAYOUT_RANGE_ATTR_SPACING + LAYOUT_RANGE_ATTR_SPACING, + LAYOUT_RANGE_ATTR_TYPOGRAPHY }; struct layout_range_attr_value { @@ -93,6 +94,7 @@ struct layout_range_attr_value { const WCHAR *locale; const WCHAR *fontfamily; FLOAT spacing[3]; /* in arguments order - leading, trailing, advance */ + IDWriteTypography *typography; } u; }; @@ -100,7 +102,8 @@ enum layout_range_kind { LAYOUT_RANGE_REGULAR, LAYOUT_RANGE_STRIKETHROUGH, LAYOUT_RANGE_EFFECT, - LAYOUT_RANGE_SPACING + LAYOUT_RANGE_SPACING, + LAYOUT_RANGE_TYPOGRAPHY }; struct layout_range_header { @@ -128,9 +131,9 @@ struct layout_range_bool { BOOL value; }; -struct layout_range_effect { +struct layout_range_iface { struct layout_range_header h; - IUnknown *effect; + IUnknown *iface; }; struct layout_range_spacing { @@ -229,6 +232,7 @@ struct dwrite_textlayout { UINT32 len; struct dwrite_textformat_data format; struct list strike_ranges; + struct list typographies; struct list effects; struct list spacing; struct list ranges; @@ -961,7 +965,7 @@ static struct layout_range_header *get_layout_range_header_by_pos(struct list *r static inline IUnknown *layout_get_effect_from_pos(struct dwrite_textlayout *layout, UINT32 pos) { struct layout_range_header *h = get_layout_range_header_by_pos(&layout->effects, pos); - return ((struct layout_range_effect*)h)->effect; + return ((struct layout_range_iface*)h)->iface; } static inline BOOL layout_is_erun_rtl(const struct layout_effective_run *erun) @@ -1557,7 +1561,7 @@ static HRESULT layout_compute_effective_runs(struct dwrite_textlayout *layout) static BOOL is_same_layout_attrvalue(struct layout_range_header const *h, enum layout_range_attr_kind attr, struct layout_range_attr_value *value) { struct layout_range_spacing const *range_spacing = (struct layout_range_spacing*)h; - struct layout_range_effect const *range_effect = (struct layout_range_effect*)h; + struct layout_range_iface const *range_iface = (struct layout_range_iface*)h; struct layout_range_bool const *range_bool = (struct layout_range_bool*)h; struct layout_range const *range = (struct layout_range*)h; @@ -1573,7 +1577,7 @@ static BOOL is_same_layout_attrvalue(struct layout_range_header const *h, enum l case LAYOUT_RANGE_ATTR_INLINE: return range->object == value->u.object; case LAYOUT_RANGE_ATTR_EFFECT: - return range_effect->effect == value->u.effect; + return range_iface->iface == value->u.effect; case LAYOUT_RANGE_ATTR_UNDERLINE: return range->underline == value->u.underline; case LAYOUT_RANGE_ATTR_STRIKETHROUGH: @@ -1590,6 +1594,8 @@ static BOOL is_same_layout_attrvalue(struct layout_range_header const *h, enum l return range_spacing->leading == value->u.spacing[0] && range_spacing->trailing == value->u.spacing[1] && range_spacing->min_advance == value->u.spacing[2]; + case LAYOUT_RANGE_ATTR_TYPOGRAPHY: + return range_iface->iface == (IUnknown*)value->u.typography; default: ; } @@ -1623,10 +1629,11 @@ static inline BOOL is_same_layout_attributes(struct layout_range_header const *h return left->value == right->value; } case LAYOUT_RANGE_EFFECT: + case LAYOUT_RANGE_TYPOGRAPHY: { - struct layout_range_effect const *left = (struct layout_range_effect const*)hleft; - struct layout_range_effect const *right = (struct layout_range_effect const*)hright; - return left->effect == right->effect; + struct layout_range_iface const *left = (struct layout_range_iface const*)hleft; + struct layout_range_iface const *right = (struct layout_range_iface const*)hright; + return left->iface == right->iface; } case LAYOUT_RANGE_SPACING: { @@ -1696,13 +1703,14 @@ static struct layout_range_header *alloc_layout_range(struct dwrite_textlayout * break; } case LAYOUT_RANGE_EFFECT: + case LAYOUT_RANGE_TYPOGRAPHY: { - struct layout_range_effect *range; + struct layout_range_iface *range; range = heap_alloc(sizeof(*range)); if (!range) return NULL; - range->effect = NULL; + range->iface = NULL; h = &range->h; break; } @@ -1767,13 +1775,14 @@ static struct layout_range_header *alloc_layout_range_from(struct layout_range_h break; } case LAYOUT_RANGE_EFFECT: + case LAYOUT_RANGE_TYPOGRAPHY: { - struct layout_range_effect *effect = heap_alloc(sizeof(*effect)); + struct layout_range_iface *effect = heap_alloc(sizeof(*effect)); if (!effect) return NULL; - *effect = *(struct layout_range_effect*)h; - if (effect->effect) - IUnknown_AddRef(effect->effect); + *effect = *(struct layout_range_iface*)h; + if (effect->iface) + IUnknown_AddRef(effect->iface); ret = &effect->h; break; } @@ -1814,10 +1823,11 @@ static void free_layout_range(struct layout_range_header *h) break; } case LAYOUT_RANGE_EFFECT: + case LAYOUT_RANGE_TYPOGRAPHY: { - struct layout_range_effect *effect = (struct layout_range_effect*)h; - if (effect->effect) - IUnknown_Release(effect->effect); + struct layout_range_iface *range = (struct layout_range_iface*)h; + if (range->iface) + IUnknown_Release(range->iface); break; } default: @@ -1850,6 +1860,11 @@ static void free_layout_ranges_list(struct dwrite_textlayout *layout) list_remove(&cur->entry); free_layout_range(cur); } + + LIST_FOR_EACH_ENTRY_SAFE(cur, cur2, &layout->typographies, struct layout_range_header, entry) { + list_remove(&cur->entry); + free_layout_range(cur); + } } static struct layout_range_header *find_outer_range(struct list *ranges, const DWRITE_TEXT_RANGE *range) @@ -1900,7 +1915,7 @@ static inline BOOL set_layout_range_iface_attr(IUnknown **dest, IUnknown *value) static BOOL set_layout_range_attrval(struct layout_range_header *h, enum layout_range_attr_kind attr, struct layout_range_attr_value *value) { struct layout_range_spacing *dest_spacing = (struct layout_range_spacing*)h; - struct layout_range_effect *dest_effect = (struct layout_range_effect*)h; + struct layout_range_iface *dest_iface = (struct layout_range_iface*)h; struct layout_range_bool *dest_bool = (struct layout_range_bool*)h; struct layout_range *dest = (struct layout_range*)h; @@ -1927,7 +1942,7 @@ static BOOL set_layout_range_attrval(struct layout_range_header *h, enum layout_ changed = set_layout_range_iface_attr((IUnknown**)&dest->object, (IUnknown*)value->u.object); break; case LAYOUT_RANGE_ATTR_EFFECT: - changed = set_layout_range_iface_attr((IUnknown**)&dest_effect->effect, (IUnknown*)value->u.effect); + changed = set_layout_range_iface_attr((IUnknown**)&dest_iface->iface, (IUnknown*)value->u.effect); break; case LAYOUT_RANGE_ATTR_UNDERLINE: changed = dest->underline != value->u.underline; @@ -1964,6 +1979,9 @@ static BOOL set_layout_range_attrval(struct layout_range_header *h, enum layout_ dest_spacing->trailing = value->u.spacing[1]; dest_spacing->min_advance = value->u.spacing[2]; break; + case LAYOUT_RANGE_ATTR_TYPOGRAPHY: + changed = set_layout_range_iface_attr((IUnknown**)&dest_iface->iface, (IUnknown*)value->u.typography); + break; default: ; } @@ -2019,6 +2037,9 @@ static HRESULT set_layout_range_attr(struct dwrite_textlayout *layout, enum layo case LAYOUT_RANGE_ATTR_SPACING: ranges = &layout->spacing; break; + case LAYOUT_RANGE_ATTR_TYPOGRAPHY: + ranges = &layout->typographies; + break; default: FIXME("unknown attr kind %d\n", attr); return E_FAIL; @@ -2576,8 +2597,13 @@ static HRESULT WINAPI dwritetextlayout_SetInlineObject(IDWriteTextLayout2 *iface static HRESULT WINAPI dwritetextlayout_SetTypography(IDWriteTextLayout2 *iface, IDWriteTypography* typography, DWRITE_TEXT_RANGE range) { struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface); - FIXME("(%p)->(%p %s): stub\n", This, typography, debugstr_range(&range)); - return E_NOTIMPL; + struct layout_range_attr_value value; + + TRACE("(%p)->(%p %s)\n", This, typography, debugstr_range(&range)); + + value.range = range; + value.u.typography = typography; + return set_layout_range_attr(This, LAYOUT_RANGE_ATTR_TYPOGRAPHY, &value); } static HRESULT WINAPI dwritetextlayout_SetLocaleName(IDWriteTextLayout2 *iface, WCHAR const* locale, DWRITE_TEXT_RANGE range) @@ -2735,12 +2761,12 @@ static HRESULT WINAPI dwritetextlayout_GetDrawingEffect(IDWriteTextLayout2 *ifac UINT32 position, IUnknown **effect, DWRITE_TEXT_RANGE *r) { struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface); - struct layout_range_effect *range; + struct layout_range_iface *range; TRACE("(%p)->(%u %p %p)\n", This, position, effect, r); - range = (struct layout_range_effect*)get_layout_range_header_by_pos(&This->effects, position); - *effect = range->effect; + range = (struct layout_range_iface*)get_layout_range_header_by_pos(&This->effects, position); + *effect = range->iface; if (*effect) IUnknown_AddRef(*effect); @@ -2767,11 +2793,19 @@ static HRESULT WINAPI dwritetextlayout_GetInlineObject(IDWriteTextLayout2 *iface } static HRESULT WINAPI dwritetextlayout_GetTypography(IDWriteTextLayout2 *iface, - UINT32 position, IDWriteTypography** typography, DWRITE_TEXT_RANGE *range) + UINT32 position, IDWriteTypography** typography, DWRITE_TEXT_RANGE *r) { struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface); - FIXME("(%p)->(%u %p %p): stub\n", This, position, typography, range); - return E_NOTIMPL; + struct layout_range_iface *range; + + TRACE("(%p)->(%u %p %p)\n", This, position, typography, r); + + range = (struct layout_range_iface*)get_layout_range_header_by_pos(&This->typographies, position); + *typography = (IDWriteTypography*)range->iface; + if (*typography) + IDWriteTypography_AddRef(*typography); + + return return_range(&range->h, r); } static HRESULT WINAPI dwritetextlayout_layout_GetLocaleNameLength(IDWriteTextLayout2 *iface, @@ -3921,8 +3955,8 @@ static HRESULT layout_format_from_textformat(struct dwrite_textlayout *layout, I static HRESULT init_textlayout(const WCHAR *str, UINT32 len, IDWriteTextFormat *format, FLOAT maxwidth, FLOAT maxheight, struct dwrite_textlayout *layout) { - struct layout_range_header *range, *strike, *effect, *spacing; - DWRITE_TEXT_RANGE r = { 0, ~0u }; + struct layout_range_header *range, *strike, *effect, *spacing, *typography; + static const DWRITE_TEXT_RANGE r = { 0, ~0u }; HRESULT hr; layout->IDWriteTextLayout2_iface.lpVtbl = &dwritetextlayoutvtbl; @@ -3948,6 +3982,7 @@ static HRESULT init_textlayout(const WCHAR *str, UINT32 len, IDWriteTextFormat * list_init(&layout->strike_ranges); list_init(&layout->effects); list_init(&layout->spacing); + list_init(&layout->typographies); memset(&layout->format, 0, sizeof(layout->format)); memset(&layout->metrics, 0, sizeof(layout->metrics)); layout->metrics.layoutWidth = maxwidth; @@ -3971,7 +4006,8 @@ static HRESULT init_textlayout(const WCHAR *str, UINT32 len, IDWriteTextFormat * strike = alloc_layout_range(layout, &r, LAYOUT_RANGE_STRIKETHROUGH); effect = alloc_layout_range(layout, &r, LAYOUT_RANGE_EFFECT); spacing = alloc_layout_range(layout, &r, LAYOUT_RANGE_SPACING); - if (!range || !strike || !effect || !spacing) { + typography = alloc_layout_range(layout, &r, LAYOUT_RANGE_TYPOGRAPHY); + if (!range || !strike || !effect || !spacing || !typography) { free_layout_range(range); free_layout_range(strike); free_layout_range(effect); @@ -3984,6 +4020,7 @@ static HRESULT init_textlayout(const WCHAR *str, UINT32 len, IDWriteTextFormat * list_add_head(&layout->strike_ranges, &strike->entry); list_add_head(&layout->effects, &effect->entry); list_add_head(&layout->spacing, &spacing->entry); + list_add_head(&layout->typographies, &typography->entry); return S_OK; fail: diff --git a/dlls/dwrite/tests/layout.c b/dlls/dwrite/tests/layout.c index 5e38a07db62..186e25720b6 100644 --- a/dlls/dwrite/tests/layout.c +++ b/dlls/dwrite/tests/layout.c @@ -4074,6 +4074,62 @@ if (0) /* crashes on native */ IDWriteFactory2_Release(factory2); } +static void test_SetTypography(void) +{ + static const WCHAR strW[] = {'a','f','i','b',0}; + IDWriteTypography *typography, *typography2; + IDWriteTextFormat *format; + IDWriteTextLayout *layout; + DWRITE_TEXT_RANGE range; + IDWriteFactory *factory; + HRESULT hr; + + factory = create_factory(); + + hr = IDWriteFactory_CreateTextFormat(factory, tahomaW, NULL, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL, + DWRITE_FONT_STRETCH_NORMAL, 10.0, enusW, &format); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = IDWriteFactory_CreateTextLayout(factory, strW, 4, format, 1000.0, 1000.0, &layout); + ok(hr == S_OK, "got 0x%08x\n", hr); + IDWriteTextFormat_Release(format); + + hr = IDWriteFactory_CreateTypography(factory, &typography); + ok(hr == S_OK, "got 0x%08x\n", hr); + + EXPECT_REF(typography, 1); + range.startPosition = 0; + range.length = 2; + hr = IDWriteTextLayout_SetTypography(layout, typography, range); + ok(hr == S_OK, "got 0x%08x\n", hr); + EXPECT_REF(typography, 2); + + hr = IDWriteTextLayout_GetTypography(layout, 0, &typography2, NULL); + ok(hr == S_OK, "got 0x%08x\n", hr); + ok(typography2 == typography, "got %p, expected %p\n", typography2, typography); + IDWriteTypography_Release(typography2); + IDWriteTypography_Release(typography); + + hr = IDWriteFactory_CreateTypography(factory, &typography2); + ok(hr == S_OK, "got 0x%08x\n", hr); + + range.startPosition = 0; + range.length = 1; + hr = IDWriteTextLayout_SetTypography(layout, typography2, range); + ok(hr == S_OK, "got 0x%08x\n", hr); + EXPECT_REF(typography2, 2); + IDWriteTypography_Release(typography2); + + hr = IDWriteTextLayout_GetTypography(layout, 0, &typography, &range); + ok(hr == S_OK, "got 0x%08x\n", hr); + ok(range.length == 1, "got %u\n", range.length); + + IDWriteTypography_Release(typography); + + IDWriteTextLayout_Release(layout); + IDWriteFactory_Release(factory); +} + START_TEST(layout) { static const WCHAR ctrlstrW[] = {0x202a,0}; @@ -4121,6 +4177,7 @@ START_TEST(layout) test_SetWordWrapping(); test_MapCharacters(); test_FontFallbackBuilder(); + test_SetTypography(); IDWriteFactory_Release(factory); } -- 2.11.4.GIT