dwrite: Fix the way drawing effects are reported for inline objects.

This commit is contained in:
Nikolay Sivov 2015-06-15 01:15:25 +03:00 committed by Alexandre Julliard
parent 6655b0c93a
commit b7fb00e9aa
2 changed files with 321 additions and 54 deletions

View File

@ -95,7 +95,8 @@ struct layout_range_attr_value {
enum layout_range_kind {
LAYOUT_RANGE_REGULAR,
LAYOUT_RANGE_STRIKETHROUGH
LAYOUT_RANGE_STRIKETHROUGH,
LAYOUT_RANGE_EFFECT
};
struct layout_range_header {
@ -111,7 +112,6 @@ struct layout_range {
FLOAT fontsize;
DWRITE_FONT_STRETCH stretch;
IDWriteInlineObject *object;
IUnknown *effect;
BOOL underline;
BOOL pair_kerning;
IDWriteFontCollection *collection;
@ -124,6 +124,11 @@ struct layout_range_bool {
BOOL value;
};
struct layout_range_effect {
struct layout_range_header h;
IUnknown *effect;
};
enum layout_run_kind {
LAYOUT_RUN_REGULAR,
LAYOUT_RUN_INLINE
@ -153,7 +158,6 @@ struct layout_run {
struct inline_object_run object;
struct regular_layout_run regular;
} u;
IUnknown *effect;
};
struct layout_effective_run {
@ -170,6 +174,7 @@ struct layout_effective_run {
struct layout_effective_inline {
struct list entry;
IDWriteInlineObject *object;
IUnknown *effect;
FLOAT origin_x;
FLOAT origin_y;
BOOL is_sideways;
@ -207,6 +212,7 @@ struct dwrite_textlayout {
FLOAT maxwidth;
FLOAT maxheight;
struct list strike_ranges;
struct list effects;
struct list ranges;
struct list runs;
/* lists ready to use by Draw() */
@ -601,7 +607,6 @@ static HRESULT layout_compute_runs(struct dwrite_textlayout *layout)
r->u.object.object = range->object;
r->u.object.length = get_clipped_range_length(layout, range);
r->effect = range->effect;
list_add_tail(&layout->runs, &r->entry);
continue;
}
@ -661,7 +666,6 @@ static HRESULT layout_compute_runs(struct dwrite_textlayout *layout)
}
range = get_layout_range_by_pos(layout, run->descr.textPosition);
r->effect = range->effect;
hr = IDWriteFontCollection_FindFamilyName(range->collection, range->fontfamily, &index, &exists);
if (FAILED(hr) || !exists) {
@ -844,6 +848,25 @@ static inline FLOAT get_cluster_range_width(struct dwrite_textlayout *layout, UI
return width;
}
static struct layout_range_header *get_layout_range_header_by_pos(struct list *ranges, UINT32 pos)
{
struct layout_range_header *cur;
LIST_FOR_EACH_ENTRY(cur, ranges, struct layout_range_header, entry) {
DWRITE_TEXT_RANGE *r = &cur->range;
if (r->startPosition <= pos && pos < r->startPosition + r->length)
return cur;
}
return NULL;
}
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;
}
/* Effective run is built from consecutive clusters of a single nominal run, 'first_cluster' is 0 based cluster index,
'cluster_count' indicates how many clusters to add, including first one. */
static HRESULT layout_add_effective_run(struct dwrite_textlayout *layout, const struct layout_run *r, UINT32 first_cluster,
@ -867,6 +890,10 @@ static HRESULT layout_add_effective_run(struct dwrite_textlayout *layout, const
different ranges which differ in reading direction). */
inlineobject->is_sideways = FALSE;
inlineobject->is_rtl = FALSE;
/* effect assigned from start position and on is used for inline objects */
inlineobject->effect = layout_get_effect_from_pos(layout, layout->clusters[first_cluster].position);
list_add_tail(&layout->inlineobjects, &inlineobject->entry);
return S_OK;
}
@ -970,19 +997,6 @@ static HRESULT layout_set_line_metrics(struct dwrite_textlayout *layout, DWRITE_
return S_OK;
}
static struct layout_range_header *get_layout_range_header_by_pos(struct list *ranges, UINT32 pos)
{
struct layout_range_header *cur;
LIST_FOR_EACH_ENTRY(cur, ranges, struct layout_range_header, entry) {
DWRITE_TEXT_RANGE *r = &cur->range;
if (r->startPosition <= pos && pos < r->startPosition + r->length)
return cur;
}
return NULL;
}
static inline BOOL layout_get_strikethrough_from_pos(struct dwrite_textlayout *layout, UINT32 pos)
{
struct layout_range_header *h = get_layout_range_header_by_pos(&layout->strike_ranges, pos);
@ -1090,6 +1104,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_effect const *range_effect = (struct layout_range_effect*)h;
struct layout_range_bool const *range_bool = (struct layout_range_bool*)h;
struct layout_range const *range = (struct layout_range*)h;
@ -1105,7 +1120,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 == value->u.effect;
return range_effect->effect == value->u.effect;
case LAYOUT_RANGE_ATTR_UNDERLINE:
return range->underline == value->u.underline;
case LAYOUT_RANGE_ATTR_STRIKETHROUGH:
@ -1138,7 +1153,6 @@ static inline BOOL is_same_layout_attributes(struct layout_range_header const *h
left->stretch == right->stretch &&
left->fontsize == right->fontsize &&
left->object == right->object &&
left->effect == right->effect &&
left->underline == right->underline &&
left->pair_kerning == right->pair_kerning &&
left->collection == right->collection &&
@ -1151,6 +1165,12 @@ static inline BOOL is_same_layout_attributes(struct layout_range_header const *h
struct layout_range_bool const *right = (struct layout_range_bool const*)hright;
return left->value == right->value;
}
case LAYOUT_RANGE_EFFECT:
{
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;
}
default:
FIXME("unknown range kind %d\n", hleft->kind);
return FALSE;
@ -1182,7 +1202,6 @@ static struct layout_range_header *alloc_layout_range(struct dwrite_textlayout *
range->stretch = layout->format.stretch;
range->fontsize = layout->format.fontsize;
range->object = NULL;
range->effect = NULL;
range->underline = FALSE;
range->pair_kerning = FALSE;
@ -1211,6 +1230,17 @@ static struct layout_range_header *alloc_layout_range(struct dwrite_textlayout *
h = &range->h;
break;
}
case LAYOUT_RANGE_EFFECT:
{
struct layout_range_effect *range;
range = heap_alloc(sizeof(*range));
if (!range) return NULL;
range->effect = NULL;
h = &range->h;
break;
}
default:
FIXME("unknown range kind %d\n", kind);
return NULL;
@ -1244,8 +1274,6 @@ static struct layout_range_header *alloc_layout_range_from(struct layout_range_h
/* update refcounts */
if (range->object)
IDWriteInlineObject_AddRef(range->object);
if (range->effect)
IUnknown_AddRef(range->effect);
if (range->collection)
IDWriteFontCollection_AddRef(range->collection);
ret = &range->h;
@ -1260,6 +1288,17 @@ static struct layout_range_header *alloc_layout_range_from(struct layout_range_h
ret = &strike->h;
break;
}
case LAYOUT_RANGE_EFFECT:
{
struct layout_range_effect *effect = heap_alloc(sizeof(*effect));
if (!effect) return NULL;
*effect = *(struct layout_range_effect*)h;
if (effect->effect)
IUnknown_AddRef(effect->effect);
ret = &effect->h;
break;
}
default:
FIXME("unknown range kind %d\n", h->kind);
return NULL;
@ -1274,16 +1313,28 @@ static void free_layout_range(struct layout_range_header *h)
if (!h)
return;
if (h->kind == LAYOUT_RANGE_REGULAR) {
switch (h->kind)
{
case LAYOUT_RANGE_REGULAR:
{
struct layout_range *range = (struct layout_range*)h;
if (range->object)
IDWriteInlineObject_Release(range->object);
if (range->effect)
IUnknown_Release(range->effect);
if (range->collection)
IDWriteFontCollection_Release(range->collection);
heap_free(range->fontfamily);
break;
}
case LAYOUT_RANGE_EFFECT:
{
struct layout_range_effect *effect = (struct layout_range_effect*)h;
if (effect->effect)
IUnknown_Release(effect->effect);
break;
}
default:
;
}
heap_free(h);
@ -1302,6 +1353,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->effects, 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)
@ -1351,6 +1407,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_effect *dest_effect = (struct layout_range_effect*)h;
struct layout_range_bool *dest_bool = (struct layout_range_bool*)h;
struct layout_range *dest = (struct layout_range*)h;
@ -1377,7 +1434,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, (IUnknown*)value->u.effect);
changed = set_layout_range_iface_attr((IUnknown**)&dest_effect->effect, (IUnknown*)value->u.effect);
break;
case LAYOUT_RANGE_ATTR_UNDERLINE:
changed = dest->underline != value->u.underline;
@ -1444,7 +1501,6 @@ static HRESULT set_layout_range_attr(struct dwrite_textlayout *layout, enum layo
case LAYOUT_RANGE_ATTR_STYLE:
case LAYOUT_RANGE_ATTR_STRETCH:
case LAYOUT_RANGE_ATTR_FONTSIZE:
case LAYOUT_RANGE_ATTR_EFFECT:
case LAYOUT_RANGE_ATTR_INLINE:
case LAYOUT_RANGE_ATTR_UNDERLINE:
case LAYOUT_RANGE_ATTR_PAIR_KERNING:
@ -1456,6 +1512,9 @@ static HRESULT set_layout_range_attr(struct dwrite_textlayout *layout, enum layo
case LAYOUT_RANGE_ATTR_STRIKETHROUGH:
ranges = &layout->strike_ranges;
break;
case LAYOUT_RANGE_ATTR_EFFECT:
ranges = &layout->effects;
break;
default:
FIXME("unknown attr kind %d\n", attr);
return E_FAIL;
@ -2191,14 +2250,11 @@ 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 *range;
struct layout_range_effect *range;
TRACE("(%p)->(%u %p %p)\n", This, position, effect, r);
if (position >= This->len)
return S_OK;
range = get_layout_range_by_pos(This, position);
range = (struct layout_range_effect*)get_layout_range_header_by_pos(&This->effects, position);
*effect = range->effect;
if (*effect)
IUnknown_AddRef(*effect);
@ -2297,7 +2353,7 @@ static HRESULT WINAPI dwritetextlayout_Draw(IDWriteTextLayout2 *iface,
DWRITE_MEASURING_MODE_NATURAL,
&glyph_run,
&descr,
run->run->effect);
NULL);
}
/* 2. Inline objects */
@ -2309,7 +2365,7 @@ static HRESULT WINAPI dwritetextlayout_Draw(IDWriteTextLayout2 *iface,
inlineobject->object,
inlineobject->is_sideways,
inlineobject->is_rtl,
run->run->effect);
inlineobject->effect);
}
/* TODO: 3. Underlines */
@ -2321,7 +2377,7 @@ static HRESULT WINAPI dwritetextlayout_Draw(IDWriteTextLayout2 *iface,
s->run->origin_x,
s->run->origin_y,
&s->s,
s->run->run->effect);
NULL);
}
return S_OK;
@ -3254,7 +3310,7 @@ 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;
struct layout_range_header *range, *strike, *effect;
DWRITE_TEXT_RANGE r = { 0, ~0u };
HRESULT hr;
@ -3282,6 +3338,7 @@ static HRESULT init_textlayout(const WCHAR *str, UINT32 len, IDWriteTextFormat *
list_init(&layout->runs);
list_init(&layout->ranges);
list_init(&layout->strike_ranges);
list_init(&layout->effects);
memset(&layout->format, 0, sizeof(layout->format));
layout->gdicompatible = FALSE;
@ -3301,15 +3358,18 @@ static HRESULT init_textlayout(const WCHAR *str, UINT32 len, IDWriteTextFormat *
range = alloc_layout_range(layout, &r, LAYOUT_RANGE_REGULAR);
strike = alloc_layout_range(layout, &r, LAYOUT_RANGE_STRIKETHROUGH);
if (!range || !strike) {
effect = alloc_layout_range(layout, &r, LAYOUT_RANGE_EFFECT);
if (!range || !strike || !effect) {
free_layout_range(range);
free_layout_range(strike);
free_layout_range(effect);
hr = E_OUTOFMEMORY;
goto fail;
}
list_add_head(&layout->ranges, &range->entry);
list_add_head(&layout->strike_ranges, &strike->entry);
list_add_head(&layout->effects, &effect->entry);
return S_OK;
fail:

View File

@ -215,18 +215,39 @@ static void _expect_ref(IUnknown* obj, ULONG ref, int line)
ok_(__FILE__,line)(rc-1 == ref, "expected refcount %d, got %d\n", ref, rc-1);
}
enum drawcall_kind {
DRAW_GLYPHRUN = 0,
DRAW_UNDERLINE,
DRAW_STRIKETHROUGH,
DRAW_INLINE,
DRAW_LAST_KIND
enum drawcall_modifiers_kind {
DRAW_EFFECT = 0x1000
};
static const char *get_draw_kind_name(enum drawcall_kind kind)
enum drawcall_kind {
DRAW_GLYPHRUN = 0,
DRAW_UNDERLINE = 1,
DRAW_STRIKETHROUGH = 2,
DRAW_INLINE = 3,
DRAW_LAST_KIND = 4,
DRAW_TOTAL_KINDS = 5,
DRAW_KINDS_MASK = 0xff
};
static const char *get_draw_kind_name(unsigned short kind)
{
static const char *kind_names[] = { "GLYPH_RUN", "UNDERLINE", "STRIKETHROUGH", "INLINE", "END_OF_SEQ" };
return kind > DRAW_LAST_KIND ? "unknown" : kind_names[kind];
static const char *kind_names[] = {
"GLYPH_RUN",
"UNDERLINE",
"STRIKETHROUGH",
"INLINE",
"END_OF_SEQ",
"GLYPH_RUN|EFFECT",
"UNDERLINE|EFFECT",
"STRIKETHROUGH|EFFECT",
"INLINE|EFFECT",
"END_OF_SEQ"
};
if ((kind & DRAW_KINDS_MASK) > DRAW_LAST_KIND)
return "unknown";
return (kind & DRAW_EFFECT) ? kind_names[(kind & DRAW_KINDS_MASK) + DRAW_TOTAL_KINDS] :
kind_names[kind];
}
struct drawcall_entry {
@ -242,7 +263,7 @@ struct drawcall_sequence
};
struct drawtestcontext {
enum drawcall_kind kind;
unsigned short kind;
BOOL todo;
int *failcount;
const char *file;
@ -327,7 +348,7 @@ static void ok_sequence_(struct drawcall_sequence **seq, int sequence_index,
ok_(file, line) (0, "%s: call %s was expected, but got call %s instead\n",
context, get_draw_kind_name(expected->kind), get_draw_kind_name(actual->kind));
}
else if (expected->kind == DRAW_GLYPHRUN) {
else if ((expected->kind & DRAW_KINDS_MASK) == DRAW_GLYPHRUN) {
int cmp = lstrcmpW(expected->string, actual->string);
if (cmp != 0 && todo) {
failcount++;
@ -424,7 +445,7 @@ static HRESULT WINAPI testrenderer_DrawGlyphRun(IDWriteTextRenderer *iface,
DWRITE_MEASURING_MODE mode,
DWRITE_GLYPH_RUN const *run,
DWRITE_GLYPH_RUN_DESCRIPTION const *descr,
IUnknown *drawing_effect)
IUnknown *effect)
{
struct drawcall_entry entry;
DWRITE_SCRIPT_ANALYSIS sa;
@ -452,6 +473,8 @@ static HRESULT WINAPI testrenderer_DrawGlyphRun(IDWriteTextRenderer *iface,
}
entry.kind = DRAW_GLYPHRUN;
if (effect)
entry.kind |= DRAW_EFFECT;
add_call(sequences, RENDERER_ID, &entry);
return S_OK;
}
@ -461,10 +484,12 @@ static HRESULT WINAPI testrenderer_DrawUnderline(IDWriteTextRenderer *iface,
FLOAT baselineOriginX,
FLOAT baselineOriginY,
DWRITE_UNDERLINE const* underline,
IUnknown *drawing_effect)
IUnknown *effect)
{
struct drawcall_entry entry;
entry.kind = DRAW_UNDERLINE;
if (effect)
entry.kind |= DRAW_EFFECT;
add_call(sequences, RENDERER_ID, &entry);
return S_OK;
}
@ -474,10 +499,12 @@ static HRESULT WINAPI testrenderer_DrawStrikethrough(IDWriteTextRenderer *iface,
FLOAT baselineOriginX,
FLOAT baselineOriginY,
DWRITE_STRIKETHROUGH const* strikethrough,
IUnknown *drawing_effect)
IUnknown *effect)
{
struct drawcall_entry entry;
entry.kind = DRAW_STRIKETHROUGH;
if (effect)
entry.kind |= DRAW_EFFECT;
add_call(sequences, RENDERER_ID, &entry);
return S_OK;
}
@ -489,10 +516,12 @@ static HRESULT WINAPI testrenderer_DrawInlineObject(IDWriteTextRenderer *iface,
IDWriteInlineObject *object,
BOOL is_sideways,
BOOL is_rtl,
IUnknown *drawing_effect)
IUnknown *effect)
{
struct drawcall_entry entry;
entry.kind = DRAW_INLINE;
if (effect)
entry.kind |= DRAW_EFFECT;
add_call(sequences, RENDERER_ID, &entry);
return S_OK;
}
@ -575,6 +604,36 @@ static IDWriteInlineObjectVtbl testinlineobjvtbl = {
static IDWriteInlineObject testinlineobj = { &testinlineobjvtbl };
static IDWriteInlineObject testinlineobj2 = { &testinlineobjvtbl };
static HRESULT WINAPI testeffect_QI(IUnknown *iface, REFIID riid, void **obj)
{
if (IsEqualIID(riid, &IID_IUnknown)) {
*obj = iface;
IUnknown_AddRef(iface);
return S_OK;
}
*obj = NULL;
return E_NOINTERFACE;
}
static ULONG WINAPI testeffect_AddRef(IUnknown *iface)
{
return 2;
}
static ULONG WINAPI testeffect_Release(IUnknown *iface)
{
return 1;
}
static const IUnknownVtbl testeffectvtbl = {
testeffect_QI,
testeffect_AddRef,
testeffect_Release
};
static IUnknown testeffect = { &testeffectvtbl };
static void test_CreateTextLayout(void)
{
static const WCHAR strW[] = {'s','t','r','i','n','g',0};
@ -1156,7 +1215,7 @@ static void test_SetInlineObject(void)
static const struct drawcall_entry draw_seq[] = {
{ DRAW_GLYPHRUN, {'s',0} },
{ DRAW_GLYPHRUN, {'r','i',0} },
{ DRAW_GLYPHRUN, {'n',0} },
{ DRAW_GLYPHRUN|DRAW_EFFECT, {'n',0} },
{ DRAW_GLYPHRUN, {'g',0} },
{ DRAW_INLINE },
{ DRAW_UNDERLINE },
@ -2438,6 +2497,153 @@ static void test_SetFlowDirection(void)
IDWriteFactory_Release(factory);
}
static const struct drawcall_entry draweffect_seq[] = {
{ DRAW_GLYPHRUN|DRAW_EFFECT, {'a','e',0x0300,0} },
{ DRAW_GLYPHRUN, {'d',0} },
{ DRAW_LAST_KIND }
};
static const struct drawcall_entry draweffect2_seq[] = {
{ DRAW_GLYPHRUN|DRAW_EFFECT, {'a','e',0} },
{ DRAW_GLYPHRUN, {'c','d',0} },
{ DRAW_LAST_KIND }
};
static const struct drawcall_entry draweffect3_seq[] = {
{ DRAW_INLINE|DRAW_EFFECT },
{ DRAW_LAST_KIND }
};
static const struct drawcall_entry draweffect4_seq[] = {
{ DRAW_INLINE },
{ DRAW_LAST_KIND }
};
static void test_SetDrawingEffect(void)
{
static const WCHAR strW[] = {'a','e',0x0300,'d',0}; /* accent grave */
static const WCHAR str2W[] = {'a','e','c','d',0};
IDWriteInlineObject *sign;
IDWriteTextFormat *format;
IDWriteTextLayout *layout;
IDWriteFactory *factory;
DWRITE_TEXT_RANGE r;
IUnknown *unk;
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);
/* string with combining mark */
hr = IDWriteFactory_CreateTextLayout(factory, strW, 4, format, 500.0, 1000.0, &layout);
ok(hr == S_OK, "got 0x%08x\n", hr);
/* set effect past the end of text */
r.startPosition = 100;
r.length = 10;
hr = IDWriteTextLayout_SetDrawingEffect(layout, &testeffect, r);
ok(hr == S_OK, "got 0x%08x\n", hr);
r.startPosition = r.length = 0;
hr = IDWriteTextLayout_GetDrawingEffect(layout, 101, &unk, &r);
ok(hr == S_OK, "got 0x%08x\n", hr);
ok(r.startPosition == 100 && r.length == 10, "got %u, %u\n", r.startPosition, r.length);
r.startPosition = r.length = 0;
unk = (void*)0xdeadbeef;
hr = IDWriteTextLayout_GetDrawingEffect(layout, 1000, &unk, &r);
ok(hr == S_OK, "got 0x%08x\n", hr);
ok(r.startPosition == 110 && r.length == ~0u-110, "got %u, %u\n", r.startPosition, r.length);
ok(unk == NULL, "got %p\n", unk);
/* effect is applied to clusters, not individual text positions */
r.startPosition = 0;
r.length = 2;
hr = IDWriteTextLayout_SetDrawingEffect(layout, &testeffect, r);
ok(hr == S_OK, "got 0x%08x\n", hr);
flush_sequence(sequences, RENDERER_ID);
hr = IDWriteTextLayout_Draw(layout, NULL, &testrenderer, 0.0, 0.0);
ok(hr == S_OK, "got 0x%08x\n", hr);
ok_sequence(sequences, RENDERER_ID, draweffect_seq, "effect draw test", TRUE);
IDWriteTextLayout_Release(layout);
/* simple string */
hr = IDWriteFactory_CreateTextLayout(factory, str2W, 4, format, 500.0, 1000.0, &layout);
ok(hr == S_OK, "got 0x%08x\n", hr);
r.startPosition = 0;
r.length = 2;
hr = IDWriteTextLayout_SetDrawingEffect(layout, &testeffect, r);
ok(hr == S_OK, "got 0x%08x\n", hr);
flush_sequence(sequences, RENDERER_ID);
hr = IDWriteTextLayout_Draw(layout, NULL, &testrenderer, 0.0, 0.0);
ok(hr == S_OK, "got 0x%08x\n", hr);
ok_sequence(sequences, RENDERER_ID, draweffect2_seq, "effect draw test 2", TRUE);
IDWriteTextLayout_Release(layout);
/* Inline object - effect set for same range */
hr = IDWriteFactory_CreateEllipsisTrimmingSign(factory, format, &sign);
ok(hr == S_OK, "got 0x%08x\n", hr);
hr = IDWriteFactory_CreateTextLayout(factory, str2W, 4, format, 500.0, 1000.0, &layout);
ok(hr == S_OK, "got 0x%08x\n", hr);
r.startPosition = 0;
r.length = 4;
hr = IDWriteTextLayout_SetInlineObject(layout, sign, r);
ok(hr == S_OK, "got 0x%08x\n", hr);
hr = IDWriteTextLayout_SetDrawingEffect(layout, &testeffect, r);
ok(hr == S_OK, "got 0x%08x\n", hr);
flush_sequence(sequences, RENDERER_ID);
hr = IDWriteTextLayout_Draw(layout, NULL, &testrenderer, 0.0, 0.0);
ok(hr == S_OK, "got 0x%08x\n", hr);
ok_sequence(sequences, RENDERER_ID, draweffect3_seq, "effect draw test 3", FALSE);
/* now set effect somewhere inside a range replaced by inline object */
hr = IDWriteTextLayout_SetDrawingEffect(layout, NULL, r);
ok(hr == S_OK, "got 0x%08x\n", hr);
r.startPosition = 1;
r.length = 1;
hr = IDWriteTextLayout_SetDrawingEffect(layout, &testeffect, r);
ok(hr == S_OK, "got 0x%08x\n", hr);
/* no effect is reported in this case */
flush_sequence(sequences, RENDERER_ID);
hr = IDWriteTextLayout_Draw(layout, NULL, &testrenderer, 0.0, 0.0);
ok(hr == S_OK, "got 0x%08x\n", hr);
ok_sequence(sequences, RENDERER_ID, draweffect4_seq, "effect draw test 4", FALSE);
r.startPosition = 0;
r.length = 4;
hr = IDWriteTextLayout_SetDrawingEffect(layout, NULL, r);
ok(hr == S_OK, "got 0x%08x\n", hr);
r.startPosition = 0;
r.length = 1;
hr = IDWriteTextLayout_SetDrawingEffect(layout, &testeffect, r);
ok(hr == S_OK, "got 0x%08x\n", hr);
/* first range position is all that matters for inline ranges */
flush_sequence(sequences, RENDERER_ID);
hr = IDWriteTextLayout_Draw(layout, NULL, &testrenderer, 0.0, 0.0);
ok(hr == S_OK, "got 0x%08x\n", hr);
ok_sequence(sequences, RENDERER_ID, draweffect3_seq, "effect draw test 5", FALSE);
IDWriteTextLayout_Release(layout);
IDWriteInlineObject_Release(sign);
IDWriteTextFormat_Release(format);
IDWriteFactory_Release(factory);
}
START_TEST(layout)
{
static const WCHAR ctrlstrW[] = {0x202a,0};
@ -2476,6 +2682,7 @@ START_TEST(layout)
test_SetStrikethrough();
test_GetMetrics();
test_SetFlowDirection();
test_SetDrawingEffect();
IDWriteFactory_Release(factory);
}