dwrite: Store per-range typography property.

Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Nikolay Sivov 2015-12-25 15:57:57 +03:00 committed by Alexandre Julliard
parent f845cca0dc
commit e9d4725326
2 changed files with 126 additions and 32 deletions

View File

@ -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:

View File

@ -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);
}