2 * Text layout/format tests
4 * Copyright 2012, 2014-2015 Nikolay Sivov for CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
29 #include "wine/test.h"
31 static const WCHAR tahomaW
[] = {'T','a','h','o','m','a',0};
32 static const WCHAR enusW
[] = {'e','n','-','u','s',0};
34 static DWRITE_SCRIPT_ANALYSIS g_sa
;
35 static DWRITE_SCRIPT_ANALYSIS g_control_sa
;
37 /* test IDWriteTextAnalysisSink */
38 static HRESULT WINAPI
analysissink_QueryInterface(IDWriteTextAnalysisSink
*iface
, REFIID riid
, void **obj
)
40 if (IsEqualIID(riid
, &IID_IDWriteTextAnalysisSink
) || IsEqualIID(riid
, &IID_IUnknown
))
50 static ULONG WINAPI
analysissink_AddRef(IDWriteTextAnalysisSink
*iface
)
55 static ULONG WINAPI
analysissink_Release(IDWriteTextAnalysisSink
*iface
)
60 static HRESULT WINAPI
analysissink_SetScriptAnalysis(IDWriteTextAnalysisSink
*iface
,
61 UINT32 position
, UINT32 length
, DWRITE_SCRIPT_ANALYSIS
const* sa
)
67 static HRESULT WINAPI
analysissink_SetLineBreakpoints(IDWriteTextAnalysisSink
*iface
,
68 UINT32 position
, UINT32 length
, DWRITE_LINE_BREAKPOINT
const* breakpoints
)
70 ok(0, "unexpected call\n");
74 static HRESULT WINAPI
analysissink_SetBidiLevel(IDWriteTextAnalysisSink
*iface
,
75 UINT32 position
, UINT32 length
, UINT8 explicitLevel
, UINT8 resolvedLevel
)
77 ok(0, "unexpected\n");
81 static HRESULT WINAPI
analysissink_SetNumberSubstitution(IDWriteTextAnalysisSink
*iface
,
82 UINT32 position
, UINT32 length
, IDWriteNumberSubstitution
* substitution
)
84 ok(0, "unexpected\n");
88 static IDWriteTextAnalysisSinkVtbl analysissinkvtbl
= {
89 analysissink_QueryInterface
,
92 analysissink_SetScriptAnalysis
,
93 analysissink_SetLineBreakpoints
,
94 analysissink_SetBidiLevel
,
95 analysissink_SetNumberSubstitution
98 static IDWriteTextAnalysisSink analysissink
= { &analysissinkvtbl
};
100 /* test IDWriteTextAnalysisSource */
101 static HRESULT WINAPI
analysissource_QueryInterface(IDWriteTextAnalysisSource
*iface
,
102 REFIID riid
, void **obj
)
104 ok(0, "QueryInterface not expected\n");
108 static ULONG WINAPI
analysissource_AddRef(IDWriteTextAnalysisSource
*iface
)
110 ok(0, "AddRef not expected\n");
114 static ULONG WINAPI
analysissource_Release(IDWriteTextAnalysisSource
*iface
)
116 ok(0, "Release not expected\n");
120 static const WCHAR
*g_source
;
122 static HRESULT WINAPI
analysissource_GetTextAtPosition(IDWriteTextAnalysisSource
*iface
,
123 UINT32 position
, WCHAR
const** text
, UINT32
* text_len
)
125 if (position
>= lstrlenW(g_source
))
132 *text
= &g_source
[position
];
133 *text_len
= lstrlenW(g_source
) - position
;
139 static HRESULT WINAPI
analysissource_GetTextBeforePosition(IDWriteTextAnalysisSource
*iface
,
140 UINT32 position
, WCHAR
const** text
, UINT32
* text_len
)
142 ok(0, "unexpected\n");
146 static DWRITE_READING_DIRECTION WINAPI
analysissource_GetParagraphReadingDirection(
147 IDWriteTextAnalysisSource
*iface
)
149 ok(0, "unexpected\n");
150 return DWRITE_READING_DIRECTION_RIGHT_TO_LEFT
;
153 static HRESULT WINAPI
analysissource_GetLocaleName(IDWriteTextAnalysisSource
*iface
,
154 UINT32 position
, UINT32
* text_len
, WCHAR
const** locale
)
161 static HRESULT WINAPI
analysissource_GetNumberSubstitution(IDWriteTextAnalysisSource
*iface
,
162 UINT32 position
, UINT32
* text_len
, IDWriteNumberSubstitution
**substitution
)
164 ok(0, "unexpected\n");
168 static IDWriteTextAnalysisSourceVtbl analysissourcevtbl
= {
169 analysissource_QueryInterface
,
170 analysissource_AddRef
,
171 analysissource_Release
,
172 analysissource_GetTextAtPosition
,
173 analysissource_GetTextBeforePosition
,
174 analysissource_GetParagraphReadingDirection
,
175 analysissource_GetLocaleName
,
176 analysissource_GetNumberSubstitution
179 static IDWriteTextAnalysisSource analysissource
= { &analysissourcevtbl
};
181 static IDWriteFactory
*create_factory(void)
183 IDWriteFactory
*factory
;
184 HRESULT hr
= DWriteCreateFactory(DWRITE_FACTORY_TYPE_ISOLATED
, &IID_IDWriteFactory
, (IUnknown
**)&factory
);
185 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
189 /* obvious limitation is that only last script data is returned, so this
190 helper is suitable for single script strings only */
191 static void get_script_analysis(const WCHAR
*str
, UINT32 len
, DWRITE_SCRIPT_ANALYSIS
*sa
)
193 IDWriteTextAnalyzer
*analyzer
;
194 IDWriteFactory
*factory
;
199 factory
= create_factory();
200 hr
= IDWriteFactory_CreateTextAnalyzer(factory
, &analyzer
);
201 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
203 hr
= IDWriteTextAnalyzer_AnalyzeScript(analyzer
, &analysissource
, 0, len
, &analysissink
);
204 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
207 IDWriteFactory_Release(factory
);
210 #define EXPECT_REF(obj,ref) _expect_ref((IUnknown*)obj, ref, __LINE__)
211 static void _expect_ref(IUnknown
* obj
, ULONG ref
, int line
)
213 ULONG rc
= IUnknown_AddRef(obj
);
214 IUnknown_Release(obj
);
215 ok_(__FILE__
,line
)(rc
-1 == ref
, "expected refcount %d, got %d\n", ref
, rc
-1);
218 enum drawcall_modifiers_kind
{
225 DRAW_STRIKETHROUGH
= 2,
228 DRAW_TOTAL_KINDS
= 5,
229 DRAW_KINDS_MASK
= 0xff
232 static const char *get_draw_kind_name(unsigned short kind
)
234 static const char *kind_names
[] = {
243 "STRIKETHROUGH|EFFECT",
247 if ((kind
& DRAW_KINDS_MASK
) > DRAW_LAST_KIND
)
249 return (kind
& DRAW_EFFECT
) ? kind_names
[(kind
& DRAW_KINDS_MASK
) + DRAW_TOTAL_KINDS
] :
253 struct drawcall_entry
{
254 enum drawcall_kind kind
;
255 WCHAR string
[10]; /* only meaningful for DrawGlyphRun() */
258 struct drawcall_sequence
262 struct drawcall_entry
*sequence
;
265 struct drawtestcontext
{
273 #define NUM_CALL_SEQUENCES 1
274 #define RENDERER_ID 0
275 static struct drawcall_sequence
*sequences
[NUM_CALL_SEQUENCES
];
276 static struct drawcall_sequence
*expected_seq
[1];
278 static void add_call(struct drawcall_sequence
**seq
, int sequence_index
, const struct drawcall_entry
*call
)
280 struct drawcall_sequence
*call_seq
= seq
[sequence_index
];
282 if (!call_seq
->sequence
) {
284 call_seq
->sequence
= HeapAlloc(GetProcessHeap(), 0, call_seq
->size
* sizeof (struct drawcall_entry
));
287 if (call_seq
->count
== call_seq
->size
) {
289 call_seq
->sequence
= HeapReAlloc(GetProcessHeap(), 0,
291 call_seq
->size
* sizeof (struct drawcall_entry
));
294 assert(call_seq
->sequence
);
295 call_seq
->sequence
[call_seq
->count
++] = *call
;
298 static inline void flush_sequence(struct drawcall_sequence
**seg
, int sequence_index
)
300 struct drawcall_sequence
*call_seq
= seg
[sequence_index
];
302 HeapFree(GetProcessHeap(), 0, call_seq
->sequence
);
303 call_seq
->sequence
= NULL
;
304 call_seq
->count
= call_seq
->size
= 0;
307 static inline void flush_sequences(struct drawcall_sequence
**seq
, int n
)
310 for (i
= 0; i
< n
; i
++)
311 flush_sequence(seq
, i
);
314 static void init_call_sequences(struct drawcall_sequence
**seq
, int n
)
318 for (i
= 0; i
< n
; i
++)
319 seq
[i
] = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(struct drawcall_sequence
));
322 static void ok_sequence_(struct drawcall_sequence
**seq
, int sequence_index
,
323 const struct drawcall_entry
*expected
, const char *context
, BOOL todo
,
324 const char *file
, int line
)
326 static const struct drawcall_entry end_of_sequence
= { DRAW_LAST_KIND
};
327 struct drawcall_sequence
*call_seq
= seq
[sequence_index
];
328 const struct drawcall_entry
*actual
, *sequence
;
331 add_call(seq
, sequence_index
, &end_of_sequence
);
333 sequence
= call_seq
->sequence
;
336 while (expected
->kind
!= DRAW_LAST_KIND
&& actual
->kind
!= DRAW_LAST_KIND
) {
337 if (expected
->kind
!= actual
->kind
) {
341 ok_(file
, line
) (0, "%s: call %s was expected, but got call %s instead\n",
342 context
, get_draw_kind_name(expected
->kind
), get_draw_kind_name(actual
->kind
));
344 flush_sequence(seq
, sequence_index
);
348 ok_(file
, line
) (0, "%s: call %s was expected, but got call %s instead\n",
349 context
, get_draw_kind_name(expected
->kind
), get_draw_kind_name(actual
->kind
));
351 else if ((expected
->kind
& DRAW_KINDS_MASK
) == DRAW_GLYPHRUN
) {
352 int cmp
= lstrcmpW(expected
->string
, actual
->string
);
353 if (cmp
!= 0 && todo
) {
356 ok_(file
, line
) (0, "%s: glyphrun string %s was expected, but got %s instead\n",
357 context
, wine_dbgstr_w(expected
->string
), wine_dbgstr_w(actual
->string
));
360 ok_(file
, line
) (cmp
== 0, "%s: glyphrun string %s was expected, but got %s instead\n",
361 context
, wine_dbgstr_w(expected
->string
), wine_dbgstr_w(actual
->string
));
369 if (expected
->kind
!= DRAW_LAST_KIND
|| actual
->kind
!= DRAW_LAST_KIND
) {
371 ok_(file
, line
) (0, "%s: the call sequence is not complete: expected %s - actual %s\n",
372 context
, get_draw_kind_name(expected
->kind
), get_draw_kind_name(actual
->kind
));
376 else if (expected
->kind
!= DRAW_LAST_KIND
|| actual
->kind
!= DRAW_LAST_KIND
)
377 ok_(file
, line
) (0, "%s: the call sequence is not complete: expected %s - actual %s\n",
378 context
, get_draw_kind_name(expected
->kind
), get_draw_kind_name(actual
->kind
));
380 if (todo
&& !failcount
) /* succeeded yet marked todo */
382 ok_(file
, line
)(1, "%s: marked \"todo_wine\" but succeeds\n", context
);
384 flush_sequence(seq
, sequence_index
);
387 #define ok_sequence(seq, index, exp, contx, todo) \
388 ok_sequence_(seq, index, (exp), (contx), (todo), __FILE__, __LINE__)
390 static HRESULT WINAPI
testrenderer_QI(IDWriteTextRenderer
*iface
, REFIID riid
, void **obj
)
392 if (IsEqualIID(riid
, &IID_IDWriteTextRenderer
) ||
393 IsEqualIID(riid
, &IID_IDWritePixelSnapping
) ||
394 IsEqualIID(riid
, &IID_IUnknown
)
402 /* IDWriteTextRenderer1 overrides drawing calls, ignore for now */
403 if (IsEqualIID(riid
, &IID_IDWriteTextRenderer1
))
404 return E_NOINTERFACE
;
406 ok(0, "unexpected QI %s\n", wine_dbgstr_guid(riid
));
407 return E_NOINTERFACE
;
410 static ULONG WINAPI
testrenderer_AddRef(IDWriteTextRenderer
*iface
)
415 static ULONG WINAPI
testrenderer_Release(IDWriteTextRenderer
*iface
)
420 static HRESULT WINAPI
testrenderer_IsPixelSnappingDisabled(IDWriteTextRenderer
*iface
,
421 void *client_drawingcontext
, BOOL
*disabled
)
427 static HRESULT WINAPI
testrenderer_GetCurrentTransform(IDWriteTextRenderer
*iface
,
428 void *client_drawingcontext
, DWRITE_MATRIX
*transform
)
430 ok(0, "unexpected call\n");
434 static HRESULT WINAPI
testrenderer_GetPixelsPerDip(IDWriteTextRenderer
*iface
,
435 void *client_drawingcontext
, FLOAT
*pixels_per_dip
)
437 ok(0, "unexpected call\n");
441 static HRESULT WINAPI
testrenderer_DrawGlyphRun(IDWriteTextRenderer
*iface
,
442 void* client_drawingcontext
,
443 FLOAT baselineOriginX
,
444 FLOAT baselineOriginY
,
445 DWRITE_MEASURING_MODE mode
,
446 DWRITE_GLYPH_RUN
const *run
,
447 DWRITE_GLYPH_RUN_DESCRIPTION
const *descr
,
450 struct drawcall_entry entry
;
451 DWRITE_SCRIPT_ANALYSIS sa
;
453 ok(descr
->stringLength
< sizeof(entry
.string
)/sizeof(WCHAR
), "string is too long\n");
454 if (descr
->stringLength
&& descr
->stringLength
< sizeof(entry
.string
)/sizeof(WCHAR
)) {
455 memcpy(entry
.string
, descr
->string
, descr
->stringLength
*sizeof(WCHAR
));
456 entry
.string
[descr
->stringLength
] = 0;
461 /* see what's reported for control codes runs */
462 get_script_analysis(descr
->string
, descr
->stringLength
, &sa
);
463 if (sa
.script
== g_control_sa
.script
) {
464 /* glyphs are not reported at all for control code runs */
465 ok(run
->glyphCount
== 0, "got %u\n", run
->glyphCount
);
466 ok(run
->glyphAdvances
!= NULL
, "advances array %p\n", run
->glyphAdvances
);
467 ok(run
->glyphOffsets
!= NULL
, "offsets array %p\n", run
->glyphOffsets
);
468 ok(run
->fontFace
!= NULL
, "got %p\n", run
->fontFace
);
469 /* text positions are still valid */
470 ok(descr
->string
!= NULL
, "got string %p\n", descr
->string
);
471 ok(descr
->stringLength
> 0, "got string length %u\n", descr
->stringLength
);
472 ok(descr
->clusterMap
!= NULL
, "clustermap %p\n", descr
->clusterMap
);
475 entry
.kind
= DRAW_GLYPHRUN
;
477 entry
.kind
|= DRAW_EFFECT
;
478 add_call(sequences
, RENDERER_ID
, &entry
);
482 static HRESULT WINAPI
testrenderer_DrawUnderline(IDWriteTextRenderer
*iface
,
483 void *client_drawingcontext
,
484 FLOAT baselineOriginX
,
485 FLOAT baselineOriginY
,
486 DWRITE_UNDERLINE
const* underline
,
489 struct drawcall_entry entry
;
490 entry
.kind
= DRAW_UNDERLINE
;
492 entry
.kind
|= DRAW_EFFECT
;
493 add_call(sequences
, RENDERER_ID
, &entry
);
497 static HRESULT WINAPI
testrenderer_DrawStrikethrough(IDWriteTextRenderer
*iface
,
498 void *client_drawingcontext
,
499 FLOAT baselineOriginX
,
500 FLOAT baselineOriginY
,
501 DWRITE_STRIKETHROUGH
const* strikethrough
,
504 struct drawcall_entry entry
;
505 entry
.kind
= DRAW_STRIKETHROUGH
;
507 entry
.kind
|= DRAW_EFFECT
;
508 add_call(sequences
, RENDERER_ID
, &entry
);
512 static HRESULT WINAPI
testrenderer_DrawInlineObject(IDWriteTextRenderer
*iface
,
513 void *client_drawingcontext
,
516 IDWriteInlineObject
*object
,
521 struct drawcall_entry entry
;
522 entry
.kind
= DRAW_INLINE
;
524 entry
.kind
|= DRAW_EFFECT
;
525 add_call(sequences
, RENDERER_ID
, &entry
);
529 static const IDWriteTextRendererVtbl testrenderervtbl
= {
532 testrenderer_Release
,
533 testrenderer_IsPixelSnappingDisabled
,
534 testrenderer_GetCurrentTransform
,
535 testrenderer_GetPixelsPerDip
,
536 testrenderer_DrawGlyphRun
,
537 testrenderer_DrawUnderline
,
538 testrenderer_DrawStrikethrough
,
539 testrenderer_DrawInlineObject
542 static IDWriteTextRenderer testrenderer
= { &testrenderervtbl
};
544 /* test IDWriteInlineObject */
545 static HRESULT WINAPI
testinlineobj_QI(IDWriteInlineObject
*iface
, REFIID riid
, void **obj
)
547 if (IsEqualIID(riid
, &IID_IDWriteInlineObject
) || IsEqualIID(riid
, &IID_IUnknown
)) {
549 IDWriteInlineObject_AddRef(iface
);
554 return E_NOINTERFACE
;
557 static ULONG WINAPI
testinlineobj_AddRef(IDWriteInlineObject
*iface
)
562 static ULONG WINAPI
testinlineobj_Release(IDWriteInlineObject
*iface
)
567 static HRESULT WINAPI
testinlineobj_Draw(IDWriteInlineObject
*iface
,
568 void* client_drawingontext
, IDWriteTextRenderer
* renderer
,
569 FLOAT originX
, FLOAT originY
, BOOL is_sideways
, BOOL is_rtl
, IUnknown
*drawing_effect
)
571 ok(0, "unexpected call\n");
575 static HRESULT WINAPI
testinlineobj_GetMetrics(IDWriteInlineObject
*iface
, DWRITE_INLINE_OBJECT_METRICS
*metrics
)
577 metrics
->width
= 123.0;
581 static HRESULT WINAPI
testinlineobj_GetOverhangMetrics(IDWriteInlineObject
*iface
, DWRITE_OVERHANG_METRICS
*overhangs
)
583 ok(0, "unexpected call\n");
587 static HRESULT WINAPI
testinlineobj_GetBreakConditions(IDWriteInlineObject
*iface
, DWRITE_BREAK_CONDITION
*before
,
588 DWRITE_BREAK_CONDITION
*after
)
590 *before
= *after
= DWRITE_BREAK_CONDITION_MUST_BREAK
;
594 static HRESULT WINAPI
testinlineobj2_GetBreakConditions(IDWriteInlineObject
*iface
, DWRITE_BREAK_CONDITION
*before
,
595 DWRITE_BREAK_CONDITION
*after
)
597 *before
= *after
= DWRITE_BREAK_CONDITION_MAY_NOT_BREAK
;
601 static IDWriteInlineObjectVtbl testinlineobjvtbl
= {
603 testinlineobj_AddRef
,
604 testinlineobj_Release
,
606 testinlineobj_GetMetrics
,
607 testinlineobj_GetOverhangMetrics
,
608 testinlineobj_GetBreakConditions
611 static IDWriteInlineObjectVtbl testinlineobjvtbl2
= {
613 testinlineobj_AddRef
,
614 testinlineobj_Release
,
616 testinlineobj_GetMetrics
,
617 testinlineobj_GetOverhangMetrics
,
618 testinlineobj2_GetBreakConditions
621 static IDWriteInlineObject testinlineobj
= { &testinlineobjvtbl
};
622 static IDWriteInlineObject testinlineobj2
= { &testinlineobjvtbl
};
623 static IDWriteInlineObject testinlineobj3
= { &testinlineobjvtbl2
};
625 static HRESULT WINAPI
testeffect_QI(IUnknown
*iface
, REFIID riid
, void **obj
)
627 if (IsEqualIID(riid
, &IID_IUnknown
)) {
629 IUnknown_AddRef(iface
);
634 return E_NOINTERFACE
;
637 static ULONG WINAPI
testeffect_AddRef(IUnknown
*iface
)
642 static ULONG WINAPI
testeffect_Release(IUnknown
*iface
)
647 static const IUnknownVtbl testeffectvtbl
= {
653 static IUnknown testeffect
= { &testeffectvtbl
};
655 static void test_CreateTextLayout(void)
657 static const WCHAR strW
[] = {'s','t','r','i','n','g',0};
658 IDWriteTextLayout2
*layout2
;
659 IDWriteTextLayout
*layout
;
660 IDWriteTextFormat
*format
;
661 IDWriteFactory
*factory
;
664 factory
= create_factory();
666 hr
= IDWriteFactory_CreateTextLayout(factory
, NULL
, 0, NULL
, 0.0, 0.0, &layout
);
667 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
669 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 6, NULL
, 0.0, 0.0, &layout
);
670 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
672 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 6, NULL
, 1.0, 0.0, &layout
);
673 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
675 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 6, NULL
, 0.0, 1.0, &layout
);
676 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
678 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 6, NULL
, 1000.0, 1000.0, &layout
);
679 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
681 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
682 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
683 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
685 EXPECT_REF(format
, 1);
686 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 6, format
, 1000.0, 1000.0, &layout
);
687 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
688 EXPECT_REF(format
, 1);
690 hr
= IDWriteTextLayout_QueryInterface(layout
, &IID_IDWriteTextLayout2
, (void**)&layout2
);
692 IDWriteTextLayout1
*layout1
;
693 IDWriteTextFormat1
*format1
;
694 IDWriteTextFormat
*format
;
696 hr
= IDWriteTextLayout2_QueryInterface(layout2
, &IID_IDWriteTextLayout1
, (void**)&layout1
);
697 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
698 IDWriteTextLayout1_Release(layout1
);
700 EXPECT_REF(layout2
, 2);
701 hr
= IDWriteTextLayout2_QueryInterface(layout2
, &IID_IDWriteTextFormat1
, (void**)&format1
);
702 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
703 EXPECT_REF(layout2
, 3);
705 hr
= IDWriteTextLayout2_QueryInterface(layout2
, &IID_IDWriteTextFormat
, (void**)&format
);
706 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
707 ok(format
== (IDWriteTextFormat
*)format1
, "got %p, %p\n", format
, format1
);
708 ok(format
!= (IDWriteTextFormat
*)layout2
, "got %p, %p\n", format
, layout2
);
709 EXPECT_REF(layout2
, 4);
711 hr
= IDWriteTextFormat_QueryInterface(format
, &IID_IDWriteTextLayout1
, (void**)&layout1
);
712 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
713 IDWriteTextLayout1_Release(layout1
);
715 IDWriteTextFormat1_Release(format1
);
716 IDWriteTextFormat_Release(format
);
718 hr
= IDWriteTextLayout_QueryInterface(layout
, &IID_IDWriteTextFormat1
, (void**)&format1
);
719 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
720 EXPECT_REF(layout2
, 3);
722 hr
= IDWriteTextLayout_QueryInterface(layout
, &IID_IDWriteTextFormat
, (void**)&format
);
723 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
724 ok(format
== (IDWriteTextFormat
*)format1
, "got %p, %p\n", format
, format1
);
725 EXPECT_REF(layout2
, 4);
727 IDWriteTextFormat1_Release(format1
);
728 IDWriteTextFormat_Release(format
);
729 IDWriteTextLayout2_Release(layout2
);
732 win_skip("IDWriteTextLayout2 is not supported.\n");
734 IDWriteTextLayout_Release(layout
);
735 IDWriteTextFormat_Release(format
);
736 IDWriteFactory_Release(factory
);
739 static void test_CreateGdiCompatibleTextLayout(void)
741 static const WCHAR strW
[] = {'s','t','r','i','n','g',0};
742 IDWriteTextLayout
*layout
;
743 IDWriteTextFormat
*format
;
744 IDWriteFactory
*factory
;
748 factory
= create_factory();
750 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, NULL
, 0, NULL
, 0.0, 0.0, 0.0, NULL
, FALSE
, &layout
);
751 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
753 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, strW
, 6, NULL
, 0.0, 0.0, 0.0, NULL
, FALSE
, &layout
);
754 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
756 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, strW
, 6, NULL
, 1.0, 0.0, 0.0, NULL
, FALSE
, &layout
);
757 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
759 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, strW
, 6, NULL
, 1.0, 0.0, 1.0, NULL
, FALSE
, &layout
);
760 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
762 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, strW
, 6, NULL
, 1000.0, 1000.0, 1.0, NULL
, FALSE
, &layout
);
763 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
765 /* create with text format */
766 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
767 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
768 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
769 EXPECT_REF(format
, 1);
771 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, strW
, 6, format
, 100.0, 100.0, 1.0, NULL
, FALSE
, &layout
);
772 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
773 EXPECT_REF(format
, 1);
774 EXPECT_REF(layout
, 1);
776 IDWriteTextLayout_AddRef(layout
);
777 EXPECT_REF(format
, 1);
778 EXPECT_REF(layout
, 2);
779 IDWriteTextLayout_Release(layout
);
780 IDWriteTextLayout_Release(layout
);
782 /* zero length string is okay */
783 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, strW
, 0, format
, 100.0, 100.0, 1.0, NULL
, FALSE
, &layout
);
784 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
786 dimension
= IDWriteTextLayout_GetMaxWidth(layout
);
787 ok(dimension
== 100.0, "got %f\n", dimension
);
789 dimension
= IDWriteTextLayout_GetMaxHeight(layout
);
790 ok(dimension
== 100.0, "got %f\n", dimension
);
792 IDWriteTextLayout_Release(layout
);
793 IDWriteTextFormat_Release(format
);
794 IDWriteFactory_Release(factory
);
797 static void test_CreateTextFormat(void)
799 IDWriteFontCollection
*collection
, *syscoll
;
800 DWRITE_PARAGRAPH_ALIGNMENT paralign
;
801 DWRITE_READING_DIRECTION readdir
;
802 DWRITE_WORD_WRAPPING wrapping
;
803 DWRITE_TEXT_ALIGNMENT align
;
804 DWRITE_FLOW_DIRECTION flow
;
805 DWRITE_LINE_SPACING_METHOD method
;
806 DWRITE_TRIMMING trimming
;
807 IDWriteTextFormat
*format
;
808 FLOAT spacing
, baseline
;
809 IDWriteInlineObject
*trimmingsign
;
810 IDWriteFactory
*factory
;
813 factory
= create_factory();
815 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
816 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
817 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
819 if (0) /* crashes on native */
820 hr
= IDWriteTextFormat_GetFontCollection(format
, NULL
);
823 hr
= IDWriteTextFormat_GetFontCollection(format
, &collection
);
824 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
825 ok(collection
!= NULL
, "got %p\n", collection
);
827 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &syscoll
, FALSE
);
828 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
829 ok(collection
== syscoll
, "got %p, was %p\n", syscoll
, collection
);
830 IDWriteFontCollection_Release(syscoll
);
831 IDWriteFontCollection_Release(collection
);
833 /* default format properties */
834 align
= IDWriteTextFormat_GetTextAlignment(format
);
835 ok(align
== DWRITE_TEXT_ALIGNMENT_LEADING
, "got %d\n", align
);
837 paralign
= IDWriteTextFormat_GetParagraphAlignment(format
);
838 ok(paralign
== DWRITE_PARAGRAPH_ALIGNMENT_NEAR
, "got %d\n", paralign
);
840 wrapping
= IDWriteTextFormat_GetWordWrapping(format
);
841 ok(wrapping
== DWRITE_WORD_WRAPPING_WRAP
, "got %d\n", wrapping
);
843 readdir
= IDWriteTextFormat_GetReadingDirection(format
);
844 ok(readdir
== DWRITE_READING_DIRECTION_LEFT_TO_RIGHT
, "got %d\n", readdir
);
846 flow
= IDWriteTextFormat_GetFlowDirection(format
);
847 ok(flow
== DWRITE_FLOW_DIRECTION_TOP_TO_BOTTOM
, "got %d\n", flow
);
849 hr
= IDWriteTextFormat_GetLineSpacing(format
, &method
, &spacing
, &baseline
);
850 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
851 ok(spacing
== 0.0, "got %f\n", spacing
);
852 ok(baseline
== 0.0, "got %f\n", baseline
);
853 ok(method
== DWRITE_LINE_SPACING_METHOD_DEFAULT
, "got %d\n", method
);
855 trimming
.granularity
= DWRITE_TRIMMING_GRANULARITY_WORD
;
856 trimming
.delimiter
= 10;
857 trimming
.delimiterCount
= 10;
858 trimmingsign
= (void*)0xdeadbeef;
859 hr
= IDWriteTextFormat_GetTrimming(format
, &trimming
, &trimmingsign
);
860 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
861 ok(trimming
.granularity
== DWRITE_TRIMMING_GRANULARITY_NONE
, "got %d\n", trimming
.granularity
);
862 ok(trimming
.delimiter
== 0, "got %d\n", trimming
.delimiter
);
863 ok(trimming
.delimiterCount
== 0, "got %d\n", trimming
.delimiterCount
);
864 ok(trimmingsign
== NULL
, "got %p\n", trimmingsign
);
867 hr
= IDWriteTextFormat_SetTextAlignment(format
, DWRITE_TEXT_ALIGNMENT_LEADING
);
868 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
870 hr
= IDWriteTextFormat_SetTextAlignment(format
, DWRITE_TEXT_ALIGNMENT_JUSTIFIED
+1);
871 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
873 hr
= IDWriteTextFormat_SetParagraphAlignment(format
, DWRITE_PARAGRAPH_ALIGNMENT_NEAR
);
874 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
876 hr
= IDWriteTextFormat_SetParagraphAlignment(format
, DWRITE_PARAGRAPH_ALIGNMENT_CENTER
+1);
877 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
879 hr
= IDWriteTextFormat_SetWordWrapping(format
, DWRITE_WORD_WRAPPING_WRAP
);
880 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
882 hr
= IDWriteTextFormat_SetWordWrapping(format
, DWRITE_WORD_WRAPPING_CHARACTER
+1);
883 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
885 hr
= IDWriteTextFormat_SetReadingDirection(format
, DWRITE_READING_DIRECTION_LEFT_TO_RIGHT
);
886 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
888 hr
= IDWriteTextFormat_SetFlowDirection(format
, DWRITE_FLOW_DIRECTION_TOP_TO_BOTTOM
);
889 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
891 hr
= IDWriteTextFormat_SetLineSpacing(format
, DWRITE_LINE_SPACING_METHOD_DEFAULT
, 0.0, 0.0);
892 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
894 hr
= IDWriteTextFormat_SetLineSpacing(format
, DWRITE_LINE_SPACING_METHOD_DEFAULT
, 0.0, -10.0);
895 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
897 hr
= IDWriteTextFormat_SetLineSpacing(format
, DWRITE_LINE_SPACING_METHOD_DEFAULT
, -10.0, 0.0);
898 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
900 hr
= IDWriteTextFormat_SetLineSpacing(format
, DWRITE_LINE_SPACING_METHOD_UNIFORM
+1, 0.0, 0.0);
901 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
903 hr
= IDWriteTextFormat_SetTrimming(format
, &trimming
, NULL
);
904 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
906 IDWriteTextFormat_Release(format
);
907 IDWriteFactory_Release(factory
);
910 static void test_GetLocaleName(void)
912 static const WCHAR strW
[] = {'s','t','r','i','n','g',0};
913 static const WCHAR ruW
[] = {'r','u',0};
914 IDWriteTextLayout
*layout
;
915 IDWriteTextFormat
*format
, *format2
;
916 IDWriteFactory
*factory
;
921 factory
= create_factory();
923 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
924 DWRITE_FONT_STRETCH_NORMAL
, 10.0, ruW
, &format
);
925 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
927 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, strW
, 0, format
, 100.0, 100.0, 1.0, NULL
, FALSE
, &layout
);
928 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
930 hr
= IDWriteTextLayout_QueryInterface(layout
, &IID_IDWriteTextFormat
, (void**)&format2
);
931 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
933 len
= IDWriteTextFormat_GetLocaleNameLength(format2
);
934 ok(len
== 2, "got %u\n", len
);
935 len
= IDWriteTextFormat_GetLocaleNameLength(format
);
936 ok(len
== 2, "got %u\n", len
);
937 hr
= IDWriteTextFormat_GetLocaleName(format2
, buff
, len
);
938 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
939 hr
= IDWriteTextFormat_GetLocaleName(format2
, buff
, len
+1);
940 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
941 ok(!lstrcmpW(buff
, ruW
), "got %s\n", wine_dbgstr_w(buff
));
942 hr
= IDWriteTextFormat_GetLocaleName(format
, buff
, len
);
943 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
944 hr
= IDWriteTextFormat_GetLocaleName(format
, buff
, len
+1);
945 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
946 ok(!lstrcmpW(buff
, ruW
), "got %s\n", wine_dbgstr_w(buff
));
948 IDWriteTextLayout_Release(layout
);
949 IDWriteTextFormat_Release(format
);
950 IDWriteTextFormat_Release(format2
);
951 IDWriteFactory_Release(factory
);
954 static const struct drawcall_entry drawellipsis_seq
[] = {
955 { DRAW_GLYPHRUN
, {0x2026, 0} },
959 static void test_CreateEllipsisTrimmingSign(void)
961 DWRITE_BREAK_CONDITION before
, after
;
962 IDWriteTextFormat
*format
;
963 IDWriteInlineObject
*sign
;
964 IDWriteFactory
*factory
;
968 factory
= create_factory();
970 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
971 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
972 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
974 EXPECT_REF(format
, 1);
975 hr
= IDWriteFactory_CreateEllipsisTrimmingSign(factory
, format
, &sign
);
976 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
977 EXPECT_REF(format
, 1);
979 hr
= IDWriteInlineObject_QueryInterface(sign
, &IID_IDWriteTextLayout
, (void**)&unk
);
980 ok(hr
== E_NOINTERFACE
, "got 0x%08x\n", hr
);
982 if (0) /* crashes on native */
983 hr
= IDWriteInlineObject_GetBreakConditions(sign
, NULL
, NULL
);
985 before
= after
= DWRITE_BREAK_CONDITION_CAN_BREAK
;
986 hr
= IDWriteInlineObject_GetBreakConditions(sign
, &before
, &after
);
987 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
988 ok(before
== DWRITE_BREAK_CONDITION_NEUTRAL
, "got %d\n", before
);
989 ok(after
== DWRITE_BREAK_CONDITION_NEUTRAL
, "got %d\n", after
);
992 flush_sequence(sequences
, RENDERER_ID
);
993 hr
= IDWriteInlineObject_Draw(sign
, NULL
, &testrenderer
, 0.0, 0.0, FALSE
, FALSE
, NULL
);
994 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
995 ok_sequence(sequences
, RENDERER_ID
, drawellipsis_seq
, "ellipsis sign draw test", FALSE
);
996 IDWriteInlineObject_Release(sign
);
998 /* non-orthogonal flow/reading combination */
999 hr
= IDWriteTextFormat_SetReadingDirection(format
, DWRITE_READING_DIRECTION_LEFT_TO_RIGHT
);
1000 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1002 hr
= IDWriteTextFormat_SetFlowDirection(format
, DWRITE_FLOW_DIRECTION_LEFT_TO_RIGHT
);
1003 ok(hr
== S_OK
|| broken(hr
== E_INVALIDARG
) /* vista, win7 */, "got 0x%08x\n", hr
);
1005 hr
= IDWriteFactory_CreateEllipsisTrimmingSign(factory
, format
, &sign
);
1006 ok(hr
== DWRITE_E_FLOWDIRECTIONCONFLICTS
, "got 0x%08x\n", hr
);
1009 IDWriteTextFormat_Release(format
);
1010 IDWriteFactory_Release(factory
);
1013 static void test_fontweight(void)
1015 static const WCHAR strW
[] = {'s','t','r','i','n','g',0};
1016 static const WCHAR ruW
[] = {'r','u',0};
1017 IDWriteTextFormat
*format
, *fmt2
;
1018 IDWriteTextLayout
*layout
;
1019 DWRITE_FONT_WEIGHT weight
;
1020 DWRITE_TEXT_RANGE range
;
1021 IDWriteFactory
*factory
;
1025 factory
= create_factory();
1027 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_BOLD
, DWRITE_FONT_STYLE_NORMAL
,
1028 DWRITE_FONT_STRETCH_NORMAL
, 10.0, ruW
, &format
);
1029 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1031 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, strW
, 6, format
, 100.0, 100.0, 1.0, NULL
, FALSE
, &layout
);
1032 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1034 hr
= IDWriteTextLayout_QueryInterface(layout
, &IID_IDWriteTextFormat
, (void**)&fmt2
);
1035 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1037 weight
= IDWriteTextFormat_GetFontWeight(fmt2
);
1038 ok(weight
== DWRITE_FONT_WEIGHT_BOLD
, "got %u\n", weight
);
1040 range
.startPosition
= range
.length
= 0;
1041 hr
= IDWriteTextLayout_GetFontWeight(layout
, 0, &weight
, &range
);
1042 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1043 ok(range
.startPosition
== 0 && range
.length
== ~0u, "got %u, %u\n", range
.startPosition
, range
.length
);
1045 range
.startPosition
= 0;
1047 hr
= IDWriteTextLayout_SetFontWeight(layout
, DWRITE_FONT_WEIGHT_NORMAL
, range
);
1048 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1050 range
.startPosition
= range
.length
= 0;
1051 hr
= IDWriteTextLayout_GetFontWeight(layout
, 0, &weight
, &range
);
1052 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1053 ok(range
.startPosition
== 0 && range
.length
== 6, "got %u, %u\n", range
.startPosition
, range
.length
);
1055 /* IDWriteTextFormat methods output doesn't reflect layout changes */
1056 weight
= IDWriteTextFormat_GetFontWeight(fmt2
);
1057 ok(weight
== DWRITE_FONT_WEIGHT_BOLD
, "got %u\n", weight
);
1060 weight
= DWRITE_FONT_WEIGHT_BOLD
;
1061 hr
= IDWriteTextLayout_GetFontWeight(layout
, 0, &weight
, &range
);
1062 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1063 ok(weight
== DWRITE_FONT_WEIGHT_NORMAL
, "got %d\n", weight
);
1064 ok(range
.length
== 6, "got %d\n", range
.length
);
1066 size
= IDWriteTextLayout_GetMaxWidth(layout
);
1067 ok(size
== 100.0, "got %.2f\n", size
);
1069 hr
= IDWriteTextLayout_SetMaxWidth(layout
, 0.0);
1070 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1072 size
= IDWriteTextLayout_GetMaxWidth(layout
);
1073 ok(size
== 0.0, "got %.2f\n", size
);
1075 hr
= IDWriteTextLayout_SetMaxWidth(layout
, -1.0);
1076 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1078 size
= IDWriteTextLayout_GetMaxWidth(layout
);
1079 ok(size
== 0.0, "got %.2f\n", size
);
1081 hr
= IDWriteTextLayout_SetMaxWidth(layout
, 100.0);
1082 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1084 size
= IDWriteTextLayout_GetMaxWidth(layout
);
1085 ok(size
== 100.0, "got %.2f\n", size
);
1087 size
= IDWriteTextLayout_GetMaxHeight(layout
);
1088 ok(size
== 100.0, "got %.2f\n", size
);
1090 hr
= IDWriteTextLayout_SetMaxHeight(layout
, 0.0);
1091 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1093 size
= IDWriteTextLayout_GetMaxHeight(layout
);
1094 ok(size
== 0.0, "got %.2f\n", size
);
1096 hr
= IDWriteTextLayout_SetMaxHeight(layout
, -1.0);
1097 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1099 size
= IDWriteTextLayout_GetMaxHeight(layout
);
1100 ok(size
== 0.0, "got %.2f\n", size
);
1102 hr
= IDWriteTextLayout_SetMaxHeight(layout
, 100.0);
1103 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1105 size
= IDWriteTextLayout_GetMaxHeight(layout
);
1106 ok(size
== 100.0, "got %.2f\n", size
);
1108 IDWriteTextLayout_Release(layout
);
1109 IDWriteTextFormat_Release(fmt2
);
1110 IDWriteTextFormat_Release(format
);
1111 IDWriteFactory_Release(factory
);
1114 static void test_SetInlineObject(void)
1116 static const WCHAR strW
[] = {'s','t','r','i','n','g',0};
1117 static const WCHAR ruW
[] = {'r','u',0};
1119 IDWriteInlineObject
*inlineobj
, *inlineobj2
, *inlinetest
;
1120 IDWriteTextFormat
*format
;
1121 IDWriteTextLayout
*layout
;
1122 DWRITE_TEXT_RANGE range
, r2
;
1123 IDWriteFactory
*factory
;
1126 factory
= create_factory();
1128 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_BOLD
, DWRITE_FONT_STYLE_NORMAL
,
1129 DWRITE_FONT_STRETCH_NORMAL
, 10.0, ruW
, &format
);
1130 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1132 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, strW
, 6, format
, 100.0, 100.0, 1.0, NULL
, FALSE
, &layout
);
1133 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1135 hr
= IDWriteFactory_CreateEllipsisTrimmingSign(factory
, format
, &inlineobj
);
1136 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1138 hr
= IDWriteFactory_CreateEllipsisTrimmingSign(factory
, format
, &inlineobj2
);
1139 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1141 EXPECT_REF(inlineobj
, 1);
1142 EXPECT_REF(inlineobj2
, 1);
1144 inlinetest
= (void*)0x1;
1145 hr
= IDWriteTextLayout_GetInlineObject(layout
, 0, &inlinetest
, NULL
);
1146 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1147 ok(inlinetest
== NULL
, "got %p\n", inlinetest
);
1149 range
.startPosition
= 0;
1151 hr
= IDWriteTextLayout_SetInlineObject(layout
, inlineobj
, range
);
1152 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1154 EXPECT_REF(inlineobj
, 2);
1156 inlinetest
= (void*)0x1;
1157 hr
= IDWriteTextLayout_GetInlineObject(layout
, 2, &inlinetest
, NULL
);
1158 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1159 ok(inlinetest
== NULL
, "got %p\n", inlinetest
);
1162 r2
.startPosition
= r2
.length
= 100;
1163 hr
= IDWriteTextLayout_GetInlineObject(layout
, 0, &inlinetest
, &r2
);
1164 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1165 ok(inlinetest
== inlineobj
, "got %p\n", inlinetest
);
1166 ok(r2
.startPosition
== 0 && r2
.length
== 2, "got %d, %d\n", r2
.startPosition
, r2
.length
);
1167 IDWriteInlineObject_Release(inlinetest
);
1169 EXPECT_REF(inlineobj
, 2);
1171 /* get from somewhere inside a range */
1173 r2
.startPosition
= r2
.length
= 100;
1174 hr
= IDWriteTextLayout_GetInlineObject(layout
, 1, &inlinetest
, &r2
);
1175 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1176 ok(inlinetest
== inlineobj
, "got %p\n", inlinetest
);
1177 ok(r2
.startPosition
== 0 && r2
.length
== 2, "got %d, %d\n", r2
.startPosition
, r2
.length
);
1178 IDWriteInlineObject_Release(inlinetest
);
1180 EXPECT_REF(inlineobj
, 2);
1182 range
.startPosition
= 1;
1184 hr
= IDWriteTextLayout_SetInlineObject(layout
, inlineobj2
, range
);
1185 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1188 r2
.startPosition
= r2
.length
= 100;
1189 hr
= IDWriteTextLayout_GetInlineObject(layout
, 1, &inlinetest
, &r2
);
1190 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1191 ok(inlinetest
== inlineobj2
, "got %p\n", inlinetest
);
1192 ok(r2
.startPosition
== 1 && r2
.length
== 1, "got %d, %d\n", r2
.startPosition
, r2
.length
);
1193 IDWriteInlineObject_Release(inlinetest
);
1195 EXPECT_REF(inlineobj
, 2);
1196 EXPECT_REF(inlineobj2
, 2);
1199 r2
.startPosition
= r2
.length
= 100;
1200 hr
= IDWriteTextLayout_GetInlineObject(layout
, 0, &inlinetest
, &r2
);
1201 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1202 ok(inlinetest
== inlineobj
, "got %p\n", inlinetest
);
1203 ok(r2
.startPosition
== 0 && r2
.length
== 1, "got %d, %d\n", r2
.startPosition
, r2
.length
);
1204 IDWriteInlineObject_Release(inlinetest
);
1206 EXPECT_REF(inlineobj
, 2);
1208 range
.startPosition
= 1;
1210 hr
= IDWriteTextLayout_SetInlineObject(layout
, inlineobj
, range
);
1211 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1213 r2
.startPosition
= r2
.length
= 100;
1214 hr
= IDWriteTextLayout_GetInlineObject(layout
, 0, &inlinetest
, &r2
);
1215 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1216 ok(inlinetest
== inlineobj
, "got %p\n", inlinetest
);
1217 ok(r2
.startPosition
== 0 && r2
.length
== 2, "got %d, %d\n", r2
.startPosition
, r2
.length
);
1218 IDWriteInlineObject_Release(inlinetest
);
1220 EXPECT_REF(inlineobj
, 2);
1222 range
.startPosition
= 1;
1224 hr
= IDWriteTextLayout_SetInlineObject(layout
, inlineobj
, range
);
1225 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1227 EXPECT_REF(inlineobj
, 2);
1229 r2
.startPosition
= r2
.length
= 100;
1230 hr
= IDWriteTextLayout_GetInlineObject(layout
, 0, &inlinetest
, &r2
);
1231 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1232 ok(inlinetest
== inlineobj
, "got %p\n", inlinetest
);
1233 ok(r2
.startPosition
== 0 && r2
.length
== 3, "got %d, %d\n", r2
.startPosition
, r2
.length
);
1234 IDWriteInlineObject_Release(inlinetest
);
1236 EXPECT_REF(inlineobj
, 2);
1237 EXPECT_REF(inlineobj2
, 1);
1239 IDWriteTextLayout_Release(layout
);
1241 EXPECT_REF(inlineobj
, 1);
1243 IDWriteInlineObject_Release(inlineobj
);
1244 IDWriteInlineObject_Release(inlineobj2
);
1245 IDWriteTextFormat_Release(format
);
1246 IDWriteFactory_Release(factory
);
1249 /* drawing calls sequence doesn't depend on run order, instead all runs are
1250 drawn first, inline objects next and then underline/strikes */
1251 static const struct drawcall_entry draw_seq
[] = {
1252 { DRAW_GLYPHRUN
, {'s',0} },
1253 { DRAW_GLYPHRUN
, {'r','i',0} },
1254 { DRAW_GLYPHRUN
|DRAW_EFFECT
, {'n',0} },
1255 { DRAW_GLYPHRUN
, {'g',0} },
1258 { DRAW_STRIKETHROUGH
},
1262 static const struct drawcall_entry draw_seq2
[] = {
1263 { DRAW_GLYPHRUN
, {'s',0} },
1264 { DRAW_GLYPHRUN
, {'t',0} },
1265 { DRAW_GLYPHRUN
, {'r',0} },
1266 { DRAW_GLYPHRUN
, {'i',0} },
1267 { DRAW_GLYPHRUN
, {'n',0} },
1268 { DRAW_GLYPHRUN
, {'g',0} },
1272 static const struct drawcall_entry draw_seq3
[] = {
1274 { DRAW_GLYPHRUN
, {'a','b',0} },
1278 static const struct drawcall_entry draw_seq4
[] = {
1279 { DRAW_GLYPHRUN
, {'s','t','r',0} },
1280 { DRAW_GLYPHRUN
, {'i','n','g',0} },
1281 { DRAW_STRIKETHROUGH
},
1285 static const struct drawcall_entry draw_seq5
[] = {
1286 { DRAW_GLYPHRUN
, {'s','t',0} },
1287 { DRAW_GLYPHRUN
, {'r','i',0} },
1288 { DRAW_GLYPHRUN
, {'n','g',0} },
1289 { DRAW_STRIKETHROUGH
},
1293 static const struct drawcall_entry empty_seq
[] = {
1297 static const struct drawcall_entry draw_single_run_seq
[] = {
1298 { DRAW_GLYPHRUN
, {'s','t','r','i','n','g',0} },
1302 static void test_Draw(void)
1304 static const WCHAR strW
[] = {'s','t','r','i','n','g',0};
1305 static const WCHAR str2W
[] = {0x202a,0x202c,'a','b',0};
1306 static const WCHAR ruW
[] = {'r','u',0};
1307 IDWriteInlineObject
*inlineobj
;
1308 IDWriteTextFormat
*format
;
1309 IDWriteTextLayout
*layout
;
1310 DWRITE_TEXT_RANGE range
;
1311 IDWriteFactory
*factory
;
1315 factory
= create_factory();
1317 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_BOLD
, DWRITE_FONT_STYLE_NORMAL
,
1318 DWRITE_FONT_STRETCH_NORMAL
, 10.0, ruW
, &format
);
1319 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1321 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 6, format
, 100.0, 100.0, &layout
);
1322 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1324 hr
= IDWriteFactory_CreateEllipsisTrimmingSign(factory
, format
, &inlineobj
);
1325 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1327 range
.startPosition
= 5;
1329 hr
= IDWriteTextLayout_SetStrikethrough(layout
, TRUE
, range
);
1330 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1332 range
.startPosition
= 1;
1334 hr
= IDWriteTextLayout_SetInlineObject(layout
, inlineobj
, range
);
1335 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1337 range
.startPosition
= 4;
1339 hr
= IDWriteTextLayout_SetDrawingEffect(layout
, (IUnknown
*)inlineobj
, range
);
1340 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1342 range
.startPosition
= 0;
1344 hr
= IDWriteTextLayout_SetUnderline(layout
, TRUE
, range
);
1345 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1347 flush_sequence(sequences
, RENDERER_ID
);
1348 hr
= IDWriteTextLayout_Draw(layout
, NULL
, &testrenderer
, 0.0, 0.0);
1349 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1350 ok_sequence(sequences
, RENDERER_ID
, draw_seq
, "draw test", TRUE
);
1351 IDWriteTextLayout_Release(layout
);
1353 /* with reduced width DrawGlyphRun() is called for every line */
1354 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 6, format
, 5.0, 100.0, &layout
);
1355 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1356 flush_sequence(sequences
, RENDERER_ID
);
1357 hr
= IDWriteTextLayout_Draw(layout
, NULL
, &testrenderer
, 0.0, 0.0);
1358 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1359 ok_sequence(sequences
, RENDERER_ID
, draw_seq2
, "draw test 2", TRUE
);
1360 IDWriteTextLayout_Release(layout
);
1362 /* string with control characters */
1363 hr
= IDWriteFactory_CreateTextLayout(factory
, str2W
, 4, format
, 500.0, 100.0, &layout
);
1364 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1365 flush_sequence(sequences
, RENDERER_ID
);
1366 hr
= IDWriteTextLayout_Draw(layout
, NULL
, &testrenderer
, 0.0, 0.0);
1367 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1368 ok_sequence(sequences
, RENDERER_ID
, draw_seq3
, "draw test 3", TRUE
);
1369 IDWriteTextLayout_Release(layout
);
1371 /* strikethrough splits ranges from renderer point of view, but doesn't break
1373 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 6, format
, 500.0, 100.0, &layout
);
1374 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1375 flush_sequence(sequences
, RENDERER_ID
);
1377 range
.startPosition
= 0;
1379 hr
= IDWriteTextLayout_SetStrikethrough(layout
, TRUE
, range
);
1380 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1382 hr
= IDWriteTextLayout_Draw(layout
, NULL
, &testrenderer
, 0.0, 0.0);
1383 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1384 ok_sequence(sequences
, RENDERER_ID
, draw_seq4
, "draw test 4", FALSE
);
1385 IDWriteTextLayout_Release(layout
);
1387 /* strikethrough somewhere in the middle */
1388 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 6, format
, 500.0, 100.0, &layout
);
1389 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1390 flush_sequence(sequences
, RENDERER_ID
);
1392 range
.startPosition
= 2;
1394 hr
= IDWriteTextLayout_SetStrikethrough(layout
, TRUE
, range
);
1395 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1397 hr
= IDWriteTextLayout_Draw(layout
, NULL
, &testrenderer
, 0.0, 0.0);
1398 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1399 ok_sequence(sequences
, RENDERER_ID
, draw_seq5
, "draw test 5", FALSE
);
1400 IDWriteTextLayout_Release(layout
);
1403 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 0, format
, 500.0, 100.0, &layout
);
1404 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1406 flush_sequence(sequences
, RENDERER_ID
);
1407 hr
= IDWriteTextLayout_Draw(layout
, NULL
, &testrenderer
, 0.0, 0.0);
1408 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1409 ok_sequence(sequences
, RENDERER_ID
, empty_seq
, "draw test 6", FALSE
);
1410 IDWriteTextLayout_Release(layout
);
1412 /* different parameter combinations with gdi-compatible layout */
1413 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, strW
, 6, format
, 100.0, 100.0, 1.0, NULL
, TRUE
, &layout
);
1414 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1415 flush_sequence(sequences
, RENDERER_ID
);
1416 hr
= IDWriteTextLayout_Draw(layout
, NULL
, &testrenderer
, 0.0, 0.0);
1417 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1418 ok_sequence(sequences
, RENDERER_ID
, draw_single_run_seq
, "draw test 7", FALSE
);
1419 IDWriteTextLayout_Release(layout
);
1421 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, strW
, 6, format
, 100.0, 100.0, 1.0, NULL
, FALSE
, &layout
);
1422 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1423 flush_sequence(sequences
, RENDERER_ID
);
1424 hr
= IDWriteTextLayout_Draw(layout
, NULL
, &testrenderer
, 0.0, 0.0);
1425 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1426 ok_sequence(sequences
, RENDERER_ID
, draw_single_run_seq
, "draw test 8", FALSE
);
1427 IDWriteTextLayout_Release(layout
);
1429 m
.m11
= m
.m22
= 2.0;
1430 m
.m12
= m
.m21
= m
.dx
= m
.dy
= 0.0;
1431 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, strW
, 6, format
, 100.0, 100.0, 1.0, &m
, TRUE
, &layout
);
1432 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1433 flush_sequence(sequences
, RENDERER_ID
);
1434 hr
= IDWriteTextLayout_Draw(layout
, NULL
, &testrenderer
, 0.0, 0.0);
1435 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1436 ok_sequence(sequences
, RENDERER_ID
, draw_single_run_seq
, "draw test 9", FALSE
);
1437 IDWriteTextLayout_Release(layout
);
1439 m
.m11
= m
.m22
= 2.0;
1440 m
.m12
= m
.m21
= m
.dx
= m
.dy
= 0.0;
1441 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, strW
, 6, format
, 100.0, 100.0, 1.0, &m
, FALSE
, &layout
);
1442 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1443 flush_sequence(sequences
, RENDERER_ID
);
1444 hr
= IDWriteTextLayout_Draw(layout
, NULL
, &testrenderer
, 0.0, 0.0);
1445 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1446 ok_sequence(sequences
, RENDERER_ID
, draw_single_run_seq
, "draw test 10", FALSE
);
1447 IDWriteTextLayout_Release(layout
);
1449 IDWriteTextFormat_Release(format
);
1450 IDWriteFactory_Release(factory
);
1453 static void test_typography(void)
1455 DWRITE_FONT_FEATURE feature
;
1456 IDWriteTypography
*typography
;
1457 IDWriteFactory
*factory
;
1461 factory
= create_factory();
1463 hr
= IDWriteFactory_CreateTypography(factory
, &typography
);
1464 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1466 feature
.nameTag
= DWRITE_FONT_FEATURE_TAG_KERNING
;
1467 feature
.parameter
= 1;
1468 hr
= IDWriteTypography_AddFontFeature(typography
, feature
);
1469 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1471 count
= IDWriteTypography_GetFontFeatureCount(typography
);
1472 ok(count
== 1, "got %u\n", count
);
1474 /* duplicated features work just fine */
1475 feature
.nameTag
= DWRITE_FONT_FEATURE_TAG_KERNING
;
1476 feature
.parameter
= 0;
1477 hr
= IDWriteTypography_AddFontFeature(typography
, feature
);
1478 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1480 count
= IDWriteTypography_GetFontFeatureCount(typography
);
1481 ok(count
== 2, "got %u\n", count
);
1483 memset(&feature
, 0, sizeof(feature
));
1484 hr
= IDWriteTypography_GetFontFeature(typography
, 0, &feature
);
1485 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1486 ok(feature
.nameTag
== DWRITE_FONT_FEATURE_TAG_KERNING
, "got tag %x\n", feature
.nameTag
);
1487 ok(feature
.parameter
== 1, "got %u\n", feature
.parameter
);
1489 memset(&feature
, 0, sizeof(feature
));
1490 hr
= IDWriteTypography_GetFontFeature(typography
, 1, &feature
);
1491 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1492 ok(feature
.nameTag
== DWRITE_FONT_FEATURE_TAG_KERNING
, "got tag %x\n", feature
.nameTag
);
1493 ok(feature
.parameter
== 0, "got %u\n", feature
.parameter
);
1495 hr
= IDWriteTypography_GetFontFeature(typography
, 2, &feature
);
1496 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1498 IDWriteTypography_Release(typography
);
1499 IDWriteFactory_Release(factory
);
1502 static void test_GetClusterMetrics(void)
1504 static const WCHAR str3W
[] = {0x2066,')',')',0x661,'(',0x627,')',0};
1505 static const WCHAR str2W
[] = {0x202a,0x202c,'a',0};
1506 static const WCHAR strW
[] = {'a','b','c','d',0};
1507 static const WCHAR str4W
[] = {'a',' ',0};
1508 DWRITE_INLINE_OBJECT_METRICS inline_metrics
;
1509 DWRITE_CLUSTER_METRICS metrics
[4];
1510 IDWriteTextLayout1
*layout1
;
1511 IDWriteInlineObject
*trimm
;
1512 IDWriteTextFormat
*format
;
1513 IDWriteTextLayout
*layout
;
1514 DWRITE_TEXT_RANGE range
;
1515 IDWriteFactory
*factory
;
1519 factory
= create_factory();
1521 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
1522 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
1523 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1525 hr
= IDWriteFactory_CreateTextLayout(factory
, str3W
, 7, format
, 1000.0, 1000.0, &layout
);
1526 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1527 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, NULL
, 0, &count
);
1528 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
1529 ok(count
== 7, "got %u\n", count
);
1530 IDWriteTextLayout_Release(layout
);
1532 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 1000.0, 1000.0, &layout
);
1533 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1536 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, NULL
, 0, &count
);
1537 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
1538 ok(count
== 4, "got %u\n", count
);
1540 /* check every cluster width */
1542 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, metrics
, sizeof(metrics
)/sizeof(metrics
[0]), &count
);
1543 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1544 ok(count
== 4, "got %u\n", count
);
1545 for (i
= 0; i
< count
; i
++) {
1546 ok(metrics
[i
].width
> 0.0, "%u: got width %.2f\n", i
, metrics
[i
].width
);
1547 ok(metrics
[i
].length
== 1, "%u: got length %u\n", i
, metrics
[i
].length
);
1550 /* apply spacing and check widths again */
1551 if (IDWriteTextLayout_QueryInterface(layout
, &IID_IDWriteTextLayout1
, (void**)&layout1
) == S_OK
) {
1552 DWRITE_CLUSTER_METRICS metrics2
[4];
1553 FLOAT leading
, trailing
, min_advance
;
1554 DWRITE_TEXT_RANGE r
;
1556 leading
= trailing
= min_advance
= 2.0;
1557 hr
= IDWriteTextLayout1_GetCharacterSpacing(layout1
, 500, &leading
, &trailing
,
1559 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1560 ok(leading
== 0.0 && trailing
== 0.0 && min_advance
== 0.0,
1561 "got %.2f, %.2f, %.2f\n", leading
, trailing
, min_advance
);
1562 ok(r
.startPosition
== 0 && r
.length
== ~0u, "got %u, %u\n", r
.startPosition
, r
.length
);
1564 leading
= trailing
= min_advance
= 2.0;
1565 hr
= IDWriteTextLayout1_GetCharacterSpacing(layout1
, 0, &leading
, &trailing
,
1566 &min_advance
, NULL
);
1567 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1568 ok(leading
== 0.0 && trailing
== 0.0 && min_advance
== 0.0,
1569 "got %.2f, %.2f, %.2f\n", leading
, trailing
, min_advance
);
1571 r
.startPosition
= 0;
1573 hr
= IDWriteTextLayout1_SetCharacterSpacing(layout1
, 10.0, 15.0, 0.0, r
);
1574 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1577 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, metrics2
, sizeof(metrics2
)/sizeof(metrics2
[0]), &count
);
1578 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1579 ok(count
== 4, "got %u\n", count
);
1580 for (i
= 0; i
< count
; i
++) {
1582 ok(metrics2
[i
].width
> metrics
[i
].width
, "%u: got width %.2f, was %.2f\n", i
, metrics2
[i
].width
,
1584 ok(metrics2
[i
].length
== 1, "%u: got length %u\n", i
, metrics2
[i
].length
);
1587 /* back to defaults */
1588 r
.startPosition
= 0;
1590 hr
= IDWriteTextLayout1_SetCharacterSpacing(layout1
, 0.0, 0.0, 0.0, r
);
1591 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1593 /* negative advance limit */
1594 r
.startPosition
= 0;
1596 hr
= IDWriteTextLayout1_SetCharacterSpacing(layout1
, 0.0, 0.0, -10.0, r
);
1597 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1599 IDWriteTextLayout1_Release(layout1
);
1602 win_skip("IDWriteTextLayout1 is not supported, cluster spacing test skipped.\n");
1604 hr
= IDWriteFactory_CreateEllipsisTrimmingSign(factory
, format
, &trimm
);
1605 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1607 range
.startPosition
= 0;
1609 hr
= IDWriteTextLayout_SetInlineObject(layout
, trimm
, range
);
1610 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1612 /* inline object takes a separate cluster, replaced codepoints number doesn't matter */
1614 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, NULL
, 0, &count
);
1615 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
1616 ok(count
== 3, "got %u\n", count
);
1619 memset(&metrics
, 0, sizeof(metrics
));
1620 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, metrics
, 1, &count
);
1621 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
1622 ok(count
== 3, "got %u\n", count
);
1623 ok(metrics
[0].length
== 2, "got %u\n", metrics
[0].length
);
1625 hr
= IDWriteInlineObject_GetMetrics(trimm
, &inline_metrics
);
1626 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1628 ok(inline_metrics
.width
> 0.0 && inline_metrics
.width
== metrics
[0].width
, "got %.2f, expected %.2f\n",
1629 inline_metrics
.width
, metrics
[0].width
);
1631 IDWriteTextLayout_Release(layout
);
1633 /* text with non-visual control codes */
1634 hr
= IDWriteFactory_CreateTextLayout(factory
, str2W
, 3, format
, 1000.0, 1000.0, &layout
);
1635 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1637 /* bidi control codes take a separate cluster */
1639 memset(metrics
, 0, sizeof(metrics
));
1640 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, metrics
, 3, &count
);
1641 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1642 ok(count
== 3, "got %u\n", count
);
1644 ok(metrics
[0].width
== 0.0, "got %.2f\n", metrics
[0].width
);
1645 ok(metrics
[0].length
== 1, "got %d\n", metrics
[0].length
);
1646 ok(metrics
[0].canWrapLineAfter
== 0, "got %d\n", metrics
[0].canWrapLineAfter
);
1647 ok(metrics
[0].isWhitespace
== 0, "got %d\n", metrics
[0].isWhitespace
);
1648 ok(metrics
[0].isNewline
== 0, "got %d\n", metrics
[0].isNewline
);
1649 ok(metrics
[0].isSoftHyphen
== 0, "got %d\n", metrics
[0].isSoftHyphen
);
1650 ok(metrics
[0].isRightToLeft
== 0, "got %d\n", metrics
[0].isRightToLeft
);
1652 ok(metrics
[1].width
== 0.0, "got %.2f\n", metrics
[1].width
);
1653 ok(metrics
[1].length
== 1, "got %d\n", metrics
[1].length
);
1654 ok(metrics
[1].canWrapLineAfter
== 0, "got %d\n", metrics
[1].canWrapLineAfter
);
1655 ok(metrics
[1].isWhitespace
== 0, "got %d\n", metrics
[1].isWhitespace
);
1656 ok(metrics
[1].isNewline
== 0, "got %d\n", metrics
[1].isNewline
);
1657 ok(metrics
[1].isSoftHyphen
== 0, "got %d\n", metrics
[1].isSoftHyphen
);
1658 ok(metrics
[1].isRightToLeft
== 0, "got %d\n", metrics
[1].isRightToLeft
);
1660 ok(metrics
[2].width
> 0.0, "got %.2f\n", metrics
[2].width
);
1661 ok(metrics
[2].length
== 1, "got %d\n", metrics
[2].length
);
1662 ok(metrics
[2].canWrapLineAfter
== 1, "got %d\n", metrics
[2].canWrapLineAfter
);
1663 ok(metrics
[2].isWhitespace
== 0, "got %d\n", metrics
[2].isWhitespace
);
1664 ok(metrics
[2].isNewline
== 0, "got %d\n", metrics
[2].isNewline
);
1665 ok(metrics
[2].isSoftHyphen
== 0, "got %d\n", metrics
[2].isSoftHyphen
);
1666 ok(metrics
[2].isRightToLeft
== 0, "got %d\n", metrics
[2].isRightToLeft
);
1668 IDWriteTextLayout_Release(layout
);
1670 /* single inline object that fails to report its metrics */
1671 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 1000.0, 1000.0, &layout
);
1672 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1674 range
.startPosition
= 0;
1676 hr
= IDWriteTextLayout_SetInlineObject(layout
, &testinlineobj
, range
);
1677 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1680 memset(metrics
, 0, sizeof(metrics
));
1681 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, metrics
, 3, &count
);
1682 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1683 ok(count
== 1, "got %u\n", count
);
1685 /* object sets a width to 123.0, but returns failure from GetMetrics() */
1686 ok(metrics
[0].width
== 0.0, "got %.2f\n", metrics
[0].width
);
1687 ok(metrics
[0].length
== 4, "got %d\n", metrics
[0].length
);
1688 ok(metrics
[0].canWrapLineAfter
== 1, "got %d\n", metrics
[0].canWrapLineAfter
);
1689 ok(metrics
[0].isWhitespace
== 0, "got %d\n", metrics
[0].isWhitespace
);
1690 ok(metrics
[0].isNewline
== 0, "got %d\n", metrics
[0].isNewline
);
1691 ok(metrics
[0].isSoftHyphen
== 0, "got %d\n", metrics
[0].isSoftHyphen
);
1692 ok(metrics
[0].isRightToLeft
== 0, "got %d\n", metrics
[0].isRightToLeft
);
1694 /* now set two inline object for [0,1] and [2,3], both fail to report break conditions */
1695 range
.startPosition
= 2;
1697 hr
= IDWriteTextLayout_SetInlineObject(layout
, &testinlineobj2
, range
);
1698 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1701 memset(metrics
, 0, sizeof(metrics
));
1702 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, metrics
, 3, &count
);
1703 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1704 ok(count
== 2, "got %u\n", count
);
1706 ok(metrics
[0].width
== 0.0, "got %.2f\n", metrics
[0].width
);
1707 ok(metrics
[0].length
== 2, "got %d\n", metrics
[0].length
);
1708 ok(metrics
[0].canWrapLineAfter
== 0, "got %d\n", metrics
[0].canWrapLineAfter
);
1709 ok(metrics
[0].isWhitespace
== 0, "got %d\n", metrics
[0].isWhitespace
);
1710 ok(metrics
[0].isNewline
== 0, "got %d\n", metrics
[0].isNewline
);
1711 ok(metrics
[0].isSoftHyphen
== 0, "got %d\n", metrics
[0].isSoftHyphen
);
1712 ok(metrics
[0].isRightToLeft
== 0, "got %d\n", metrics
[0].isRightToLeft
);
1714 ok(metrics
[1].width
== 0.0, "got %.2f\n", metrics
[1].width
);
1715 ok(metrics
[1].length
== 2, "got %d\n", metrics
[1].length
);
1716 ok(metrics
[1].canWrapLineAfter
== 1, "got %d\n", metrics
[1].canWrapLineAfter
);
1717 ok(metrics
[1].isWhitespace
== 0, "got %d\n", metrics
[1].isWhitespace
);
1718 ok(metrics
[1].isNewline
== 0, "got %d\n", metrics
[1].isNewline
);
1719 ok(metrics
[1].isSoftHyphen
== 0, "got %d\n", metrics
[1].isSoftHyphen
);
1720 ok(metrics
[1].isRightToLeft
== 0, "got %d\n", metrics
[1].isRightToLeft
);
1722 IDWriteTextLayout_Release(layout
);
1724 /* zero length string */
1725 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 0, format
, 1000.0, 1000.0, &layout
);
1726 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1729 memset(metrics
, 0, sizeof(metrics
));
1730 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, metrics
, 3, &count
);
1731 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1732 ok(count
== 0, "got %u\n", count
);
1733 IDWriteTextLayout_Release(layout
);
1736 hr
= IDWriteFactory_CreateTextLayout(factory
, str4W
, 2, format
, 1000.0, 1000.0, &layout
);
1737 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1740 memset(metrics
, 0, sizeof(metrics
));
1741 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, metrics
, 2, &count
);
1742 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1743 ok(count
== 2, "got %u\n", count
);
1744 ok(metrics
[0].isWhitespace
== 0, "got %d\n", metrics
[0].isWhitespace
);
1745 ok(metrics
[1].isWhitespace
== 1, "got %d\n", metrics
[1].isWhitespace
);
1746 ok(metrics
[1].canWrapLineAfter
== 1, "got %d\n", metrics
[1].canWrapLineAfter
);
1747 IDWriteTextLayout_Release(layout
);
1749 /* layout is fully covered by inline object with after condition DWRITE_BREAK_CONDITION_MAY_NOT_BREAK */
1750 hr
= IDWriteFactory_CreateTextLayout(factory
, str4W
, 2, format
, 1000.0, 1000.0, &layout
);
1751 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1753 range
.startPosition
= 0;
1755 hr
= IDWriteTextLayout_SetInlineObject(layout
, &testinlineobj3
, range
);
1756 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1759 memset(metrics
, 0, sizeof(metrics
));
1760 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, metrics
, 2, &count
);
1761 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1762 ok(count
== 1, "got %u\n", count
);
1763 ok(metrics
[0].canWrapLineAfter
== 1, "got %d\n", metrics
[0].canWrapLineAfter
);
1765 IDWriteTextLayout_Release(layout
);
1767 IDWriteInlineObject_Release(trimm
);
1768 IDWriteTextFormat_Release(format
);
1769 IDWriteFactory_Release(factory
);
1772 static void test_SetLocaleName(void)
1774 static const WCHAR strW
[] = {'a','b','c','d',0};
1775 WCHAR buffW
[LOCALE_NAME_MAX_LENGTH
+sizeof(strW
)/sizeof(WCHAR
)];
1776 IDWriteTextFormat
*format
;
1777 IDWriteTextLayout
*layout
;
1778 DWRITE_TEXT_RANGE range
;
1779 IDWriteFactory
*factory
;
1782 factory
= create_factory();
1784 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
1785 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
1786 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1788 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 1000.0, 1000.0, &layout
);
1789 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1791 range
.startPosition
= 0;
1793 hr
= IDWriteTextLayout_SetLocaleName(layout
, enusW
, range
);
1794 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1796 hr
= IDWriteTextLayout_SetLocaleName(layout
, NULL
, range
);
1797 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1799 /* invalid locale name is allowed */
1800 hr
= IDWriteTextLayout_SetLocaleName(layout
, strW
, range
);
1801 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1803 hr
= IDWriteTextLayout_GetLocaleName(layout
, 0, NULL
, 0, NULL
);
1804 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1806 if (0) /* crashes on native */
1807 hr
= IDWriteTextLayout_GetLocaleName(layout
, 0, NULL
, 1, NULL
);
1810 hr
= IDWriteTextLayout_GetLocaleName(layout
, 0, buffW
, sizeof(buffW
)/sizeof(WCHAR
), NULL
);
1811 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1812 ok(!lstrcmpW(buffW
, strW
), "got %s\n", wine_dbgstr_w(buffW
));
1814 /* get with a shorter buffer */
1816 hr
= IDWriteTextLayout_GetLocaleName(layout
, 0, buffW
, 1, NULL
);
1817 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
1818 ok(buffW
[0] == 0, "got %x\n", buffW
[0]);
1820 /* name is too long */
1821 lstrcpyW(buffW
, strW
);
1822 while (lstrlenW(buffW
) <= LOCALE_NAME_MAX_LENGTH
)
1823 lstrcatW(buffW
, strW
);
1825 range
.startPosition
= 0;
1827 hr
= IDWriteTextLayout_SetLocaleName(layout
, buffW
, range
);
1828 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1831 hr
= IDWriteTextLayout_GetLocaleName(layout
, 0, buffW
, sizeof(buffW
)/sizeof(WCHAR
), NULL
);
1832 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1833 ok(!lstrcmpW(buffW
, strW
), "got %s\n", wine_dbgstr_w(buffW
));
1835 IDWriteTextLayout_Release(layout
);
1836 IDWriteTextFormat_Release(format
);
1837 IDWriteFactory_Release(factory
);
1840 static void test_SetPairKerning(void)
1842 static const WCHAR strW
[] = {'a','e',0x0300,'d',0}; /* accent grave */
1843 DWRITE_CLUSTER_METRICS clusters
[4];
1844 IDWriteTextLayout1
*layout1
;
1845 IDWriteTextFormat
*format
;
1846 IDWriteTextLayout
*layout
;
1847 DWRITE_TEXT_RANGE range
;
1848 IDWriteFactory
*factory
;
1853 factory
= create_factory();
1855 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
1856 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
1857 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1859 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 1000.0, 1000.0, &layout
);
1860 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1861 IDWriteTextFormat_Release(format
);
1863 hr
= IDWriteTextLayout_QueryInterface(layout
, &IID_IDWriteTextLayout1
, (void**)&layout1
);
1864 IDWriteTextLayout_Release(layout
);
1867 win_skip("SetPairKerning() is not supported.\n");
1868 IDWriteFactory_Release(factory
);
1872 if (0) { /* crashes on native */
1873 hr
= IDWriteTextLayout1_GetPairKerning(layout1
, 0, NULL
, NULL
);
1874 hr
= IDWriteTextLayout1_GetPairKerning(layout1
, 0, NULL
, &range
);
1877 hr
= IDWriteTextLayout1_GetPairKerning(layout1
, 0, &kerning
, NULL
);
1878 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1880 range
.startPosition
= 0;
1883 hr
= IDWriteTextLayout1_GetPairKerning(layout1
, 0, &kerning
, &range
);
1884 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1885 ok(!kerning
, "got %d\n", kerning
);
1886 ok(range
.length
== ~0u, "got %u\n", range
.length
);
1889 hr
= IDWriteTextLayout1_GetClusterMetrics(layout1
, clusters
, 4, &count
);
1890 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1892 ok(count
== 3, "got %u\n", count
);
1894 ok(clusters
[0].length
== 1, "got %u\n", clusters
[0].length
);
1895 ok(clusters
[1].length
== 2, "got %u\n", clusters
[1].length
);
1896 ok(clusters
[2].length
== 1, "got %u\n", clusters
[2].length
);
1898 /* pair kerning flag participates in itemization - combining characters
1900 range
.startPosition
= 0;
1902 hr
= IDWriteTextLayout1_SetPairKerning(layout1
, 2, range
);
1903 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1906 hr
= IDWriteTextLayout1_GetPairKerning(layout1
, 0, &kerning
, &range
);
1907 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1908 ok(kerning
== TRUE
, "got %d\n", kerning
);
1911 hr
= IDWriteTextLayout1_GetClusterMetrics(layout1
, clusters
, 4, &count
);
1912 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1913 ok(count
== 4, "got %u\n", count
);
1914 ok(clusters
[0].length
== 1, "got %u\n", clusters
[0].length
);
1915 ok(clusters
[1].length
== 1, "got %u\n", clusters
[1].length
);
1916 ok(clusters
[2].length
== 1, "got %u\n", clusters
[2].length
);
1917 ok(clusters
[3].length
== 1, "got %u\n", clusters
[3].length
);
1919 IDWriteTextLayout1_Release(layout1
);
1920 IDWriteFactory_Release(factory
);
1923 static void test_SetVerticalGlyphOrientation(void)
1925 static const WCHAR strW
[] = {'a','b','c','d',0};
1926 DWRITE_VERTICAL_GLYPH_ORIENTATION orientation
;
1927 IDWriteTextLayout2
*layout2
;
1928 IDWriteTextFormat
*format
;
1929 IDWriteTextLayout
*layout
;
1930 IDWriteFactory
*factory
;
1933 factory
= create_factory();
1935 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
1936 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
1937 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1939 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 1000.0, 1000.0, &layout
);
1940 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1941 IDWriteTextFormat_Release(format
);
1943 hr
= IDWriteTextLayout_QueryInterface(layout
, &IID_IDWriteTextLayout2
, (void**)&layout2
);
1944 IDWriteTextLayout_Release(layout
);
1947 win_skip("SetVerticalGlyphOrientation() is not supported.\n");
1948 IDWriteFactory_Release(factory
);
1952 orientation
= IDWriteTextLayout2_GetVerticalGlyphOrientation(layout2
);
1953 ok(orientation
== DWRITE_VERTICAL_GLYPH_ORIENTATION_DEFAULT
, "got %d\n", orientation
);
1955 hr
= IDWriteTextLayout2_SetVerticalGlyphOrientation(layout2
, DWRITE_VERTICAL_GLYPH_ORIENTATION_STACKED
+1);
1956 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1958 IDWriteTextLayout2_Release(layout2
);
1959 IDWriteFactory_Release(factory
);
1962 static void test_fallback(void)
1964 static const WCHAR strW
[] = {'a','b','c','d',0};
1965 IDWriteFontFallback
*fallback
, *fallback2
;
1966 IDWriteTextLayout2
*layout2
;
1967 IDWriteTextFormat1
*format1
;
1968 IDWriteTextFormat
*format
;
1969 IDWriteTextLayout
*layout
;
1970 IDWriteFactory2
*factory2
;
1971 IDWriteFactory
*factory
;
1974 factory
= create_factory();
1976 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
1977 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
1978 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1980 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 1000.0, 1000.0, &layout
);
1981 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1982 IDWriteTextFormat_Release(format
);
1984 hr
= IDWriteTextLayout_QueryInterface(layout
, &IID_IDWriteTextLayout2
, (void**)&layout2
);
1985 IDWriteTextLayout_Release(layout
);
1988 win_skip("GetFontFallback() is not supported.\n");
1989 IDWriteFactory_Release(factory
);
1993 if (0) /* crashes on native */
1994 hr
= IDWriteTextLayout2_GetFontFallback(layout2
, NULL
);
1996 fallback
= (void*)0xdeadbeef;
1997 hr
= IDWriteTextLayout2_GetFontFallback(layout2
, &fallback
);
1998 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1999 ok(fallback
== NULL
, "got %p\n", fallback
);
2001 hr
= IDWriteTextLayout2_QueryInterface(layout2
, &IID_IDWriteTextFormat1
, (void**)&format1
);
2002 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2004 fallback
= (void*)0xdeadbeef;
2005 hr
= IDWriteTextFormat1_GetFontFallback(format1
, &fallback
);
2006 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2007 ok(fallback
== NULL
, "got %p\n", fallback
);
2009 hr
= IDWriteFactory_QueryInterface(factory
, &IID_IDWriteFactory2
, (void**)&factory2
);
2010 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2013 hr
= IDWriteFactory2_GetSystemFontFallback(factory2
, &fallback
);
2015 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2017 ok(fallback
!= NULL
, "got %p\n", fallback
);
2019 hr
= IDWriteTextFormat1_SetFontFallback(format1
, fallback
);
2020 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2022 fallback2
= (void*)0xdeadbeef;
2023 hr
= IDWriteTextLayout2_GetFontFallback(layout2
, &fallback2
);
2024 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2025 ok(fallback2
== fallback
, "got %p\n", fallback2
);
2027 hr
= IDWriteTextLayout2_SetFontFallback(layout2
, NULL
);
2028 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2030 fallback2
= (void*)0xdeadbeef;
2031 hr
= IDWriteTextFormat1_GetFontFallback(format1
, &fallback2
);
2032 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2033 ok(fallback2
== NULL
, "got %p\n", fallback2
);
2035 IDWriteFontFallback_Release(fallback
);
2037 IDWriteTextFormat1_Release(format1
);
2038 IDWriteTextLayout2_Release(layout2
);
2039 IDWriteFactory_Release(factory
);
2042 static void test_DetermineMinWidth(void)
2044 static const WCHAR strW
[] = {'a','b','c','d',0};
2045 IDWriteTextFormat
*format
;
2046 IDWriteTextLayout
*layout
;
2047 IDWriteFactory
*factory
;
2051 factory
= create_factory();
2053 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
2054 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
2055 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2057 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, lstrlenW(strW
), format
, 1000.0, 1000.0, &layout
);
2058 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2060 hr
= IDWriteTextLayout_DetermineMinWidth(layout
, NULL
);
2061 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
2064 hr
= IDWriteTextLayout_DetermineMinWidth(layout
, &minwidth
);
2065 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2066 ok(minwidth
> 0.0, "got %.2f\n", minwidth
);
2068 IDWriteTextLayout_Release(layout
);
2069 IDWriteTextFormat_Release(format
);
2070 IDWriteFactory_Release(factory
);
2073 static void test_SetFontSize(void)
2075 static const WCHAR strW
[] = {'a','b','c','d',0};
2076 IDWriteTextFormat
*format
;
2077 IDWriteTextLayout
*layout
;
2078 IDWriteFactory
*factory
;
2079 DWRITE_TEXT_RANGE r
;
2083 factory
= create_factory();
2085 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
2086 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
2087 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2089 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 1000.0, 1000.0, &layout
);
2090 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2092 /* negative/zero size */
2093 r
.startPosition
= 1;
2095 hr
= IDWriteTextLayout_SetFontSize(layout
, -15.0, r
);
2096 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
2098 hr
= IDWriteTextLayout_SetFontSize(layout
, 0.0, r
);
2099 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
2101 r
.startPosition
= 1;
2104 hr
= IDWriteTextLayout_GetFontSize(layout
, 0, &size
, &r
);
2105 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2106 ok(r
.startPosition
== 0 && r
.length
== ~0u, "got %u, %u\n", r
.startPosition
, r
.length
);
2107 ok(size
== 10.0, "got %.2f\n", size
);
2109 r
.startPosition
= 1;
2111 hr
= IDWriteTextLayout_SetFontSize(layout
, 15.0, r
);
2112 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2114 /* zero length range */
2115 r
.startPosition
= 1;
2117 hr
= IDWriteTextLayout_SetFontSize(layout
, 123.0, r
);
2118 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2121 hr
= IDWriteTextLayout_GetFontSize(layout
, 1, &size
, &r
);
2122 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2123 ok(size
== 15.0, "got %.2f\n", size
);
2125 r
.startPosition
= 0;
2127 hr
= IDWriteTextLayout_SetFontSize(layout
, 15.0, r
);
2128 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2131 hr
= IDWriteTextLayout_GetFontSize(layout
, 1, &size
, &r
);
2132 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2133 ok(size
== 15.0, "got %.2f\n", size
);
2136 hr
= IDWriteTextLayout_GetFontSize(layout
, 0, &size
, &r
);
2137 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2138 ok(r
.startPosition
== 0 && r
.length
== 4, "got %u, %u\n", r
.startPosition
, r
.length
);
2139 ok(size
== 15.0, "got %.2f\n", size
);
2142 r
.startPosition
= r
.length
= 0;
2143 hr
= IDWriteTextLayout_GetFontSize(layout
, 20, &size
, &r
);
2144 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2145 ok(r
.startPosition
== 4 && r
.length
== ~0u-4, "got %u, %u\n", r
.startPosition
, r
.length
);
2146 ok(size
== 10.0, "got %.2f\n", size
);
2148 r
.startPosition
= 100;
2150 hr
= IDWriteTextLayout_SetFontSize(layout
, 25.0, r
);
2151 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2154 r
.startPosition
= r
.length
= 0;
2155 hr
= IDWriteTextLayout_GetFontSize(layout
, 100, &size
, &r
);
2156 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2157 ok(r
.startPosition
== 100 && r
.length
== 4, "got %u, %u\n", r
.startPosition
, r
.length
);
2158 ok(size
== 25.0, "got %.2f\n", size
);
2160 IDWriteTextLayout_Release(layout
);
2161 IDWriteTextFormat_Release(format
);
2162 IDWriteFactory_Release(factory
);
2165 static void test_SetFontFamilyName(void)
2167 static const WCHAR taHomaW
[] = {'T','a','H','o','m','a',0};
2168 static const WCHAR arialW
[] = {'A','r','i','a','l',0};
2169 static const WCHAR strW
[] = {'a','b','c','d',0};
2170 IDWriteTextFormat
*format
;
2171 IDWriteTextLayout
*layout
;
2172 IDWriteFactory
*factory
;
2173 DWRITE_TEXT_RANGE r
;
2177 factory
= create_factory();
2179 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
2180 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
2181 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2183 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 1000.0, 1000.0, &layout
);
2184 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2187 r
.startPosition
= 1;
2189 hr
= IDWriteTextLayout_SetFontFamilyName(layout
, NULL
, r
);
2190 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
2192 r
.startPosition
= 1;
2195 hr
= IDWriteTextLayout_GetFontFamilyName(layout
, 1, nameW
, sizeof(nameW
)/sizeof(WCHAR
), &r
);
2196 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2197 ok(r
.startPosition
== 0 && r
.length
== ~0u, "got %u, %u\n", r
.startPosition
, r
.length
);
2199 /* set name only different in casing */
2200 r
.startPosition
= 1;
2202 hr
= IDWriteTextLayout_SetFontFamilyName(layout
, taHomaW
, r
);
2203 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2205 /* zero length range */
2206 r
.startPosition
= 1;
2208 hr
= IDWriteTextLayout_SetFontFamilyName(layout
, arialW
, r
);
2209 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2211 r
.startPosition
= 0;
2214 hr
= IDWriteTextLayout_GetFontFamilyName(layout
, 1, nameW
, sizeof(nameW
)/sizeof(WCHAR
), &r
);
2215 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2216 ok(!lstrcmpW(nameW
, taHomaW
), "got %s\n", wine_dbgstr_w(nameW
));
2217 ok(r
.startPosition
== 1 && r
.length
== 1, "got %u, %u\n", r
.startPosition
, r
.length
);
2219 r
.startPosition
= 1;
2221 hr
= IDWriteTextLayout_SetFontFamilyName(layout
, arialW
, r
);
2222 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2224 r
.startPosition
= 1;
2226 hr
= IDWriteTextLayout_GetFontFamilyName(layout
, 1, nameW
, sizeof(nameW
)/sizeof(WCHAR
), &r
);
2227 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2228 ok(r
.startPosition
== 1 && r
.length
== 1, "got %u, %u\n", r
.startPosition
, r
.length
);
2230 r
.startPosition
= 0;
2232 hr
= IDWriteTextLayout_SetFontFamilyName(layout
, arialW
, r
);
2233 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2236 hr
= IDWriteTextLayout_GetFontFamilyName(layout
, 1, nameW
, sizeof(nameW
)/sizeof(WCHAR
), &r
);
2237 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2238 ok(r
.startPosition
== 0 && r
.length
== 4, "got %u, %u\n", r
.startPosition
, r
.length
);
2239 ok(!lstrcmpW(nameW
, arialW
), "got name %s\n", wine_dbgstr_w(nameW
));
2241 IDWriteTextLayout_Release(layout
);
2242 IDWriteTextFormat_Release(format
);
2243 IDWriteFactory_Release(factory
);
2246 static void test_SetFontStyle(void)
2248 static const WCHAR strW
[] = {'a','b','c','d',0};
2249 IDWriteTextFormat
*format
;
2250 IDWriteTextLayout
*layout
;
2251 IDWriteFactory
*factory
;
2252 DWRITE_FONT_STYLE style
;
2253 DWRITE_TEXT_RANGE r
;
2256 factory
= create_factory();
2258 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
2259 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
2260 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2262 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 1000.0, 1000.0, &layout
);
2263 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2265 /* invalid style value */
2266 r
.startPosition
= 1;
2268 hr
= IDWriteTextLayout_SetFontStyle(layout
, DWRITE_FONT_STYLE_ITALIC
+1, r
);
2269 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
2271 r
.startPosition
= 1;
2273 hr
= IDWriteTextLayout_GetFontStyle(layout
, 0, &style
, &r
);
2274 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2275 ok(r
.startPosition
== 0 && r
.length
== ~0u, "got %u, %u\n", r
.startPosition
, r
.length
);
2276 ok(style
== DWRITE_FONT_STYLE_NORMAL
, "got %d\n", style
);
2278 r
.startPosition
= 1;
2280 hr
= IDWriteTextLayout_SetFontStyle(layout
, DWRITE_FONT_STYLE_ITALIC
, r
);
2281 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2283 /* zero length range */
2284 r
.startPosition
= 1;
2286 hr
= IDWriteTextLayout_SetFontStyle(layout
, DWRITE_FONT_STYLE_NORMAL
, r
);
2287 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2289 style
= DWRITE_FONT_STYLE_NORMAL
;
2290 hr
= IDWriteTextLayout_GetFontStyle(layout
, 1, &style
, &r
);
2291 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2292 ok(style
== DWRITE_FONT_STYLE_ITALIC
, "got %d\n", style
);
2294 r
.startPosition
= 0;
2296 hr
= IDWriteTextLayout_SetFontStyle(layout
, DWRITE_FONT_STYLE_OBLIQUE
, r
);
2297 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2299 style
= DWRITE_FONT_STYLE_ITALIC
;
2300 hr
= IDWriteTextLayout_GetFontStyle(layout
, 1, &style
, &r
);
2301 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2302 ok(style
== DWRITE_FONT_STYLE_OBLIQUE
, "got %d\n", style
);
2304 style
= DWRITE_FONT_STYLE_ITALIC
;
2305 hr
= IDWriteTextLayout_GetFontStyle(layout
, 0, &style
, &r
);
2306 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2307 ok(r
.startPosition
== 0 && r
.length
== 4, "got %u, %u\n", r
.startPosition
, r
.length
);
2308 ok(style
== DWRITE_FONT_STYLE_OBLIQUE
, "got %d\n", style
);
2310 style
= DWRITE_FONT_STYLE_ITALIC
;
2311 r
.startPosition
= r
.length
= 0;
2312 hr
= IDWriteTextLayout_GetFontStyle(layout
, 20, &style
, &r
);
2313 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2314 ok(r
.startPosition
== 4 && r
.length
== ~0u-4, "got %u, %u\n", r
.startPosition
, r
.length
);
2315 ok(style
== DWRITE_FONT_STYLE_NORMAL
, "got %d\n", style
);
2317 r
.startPosition
= 100;
2319 hr
= IDWriteTextLayout_SetFontStyle(layout
, DWRITE_FONT_STYLE_OBLIQUE
, r
);
2320 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2322 style
= DWRITE_FONT_STYLE_NORMAL
;
2323 r
.startPosition
= r
.length
= 0;
2324 hr
= IDWriteTextLayout_GetFontStyle(layout
, 100, &style
, &r
);
2325 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2326 ok(r
.startPosition
== 100 && r
.length
== 4, "got %u, %u\n", r
.startPosition
, r
.length
);
2327 ok(style
== DWRITE_FONT_STYLE_OBLIQUE
, "got %d\n", style
);
2329 IDWriteTextLayout_Release(layout
);
2330 IDWriteTextFormat_Release(format
);
2331 IDWriteFactory_Release(factory
);
2334 static void test_SetFontStretch(void)
2336 static const WCHAR strW
[] = {'a','b','c','d',0};
2337 DWRITE_FONT_STRETCH stretch
;
2338 IDWriteTextFormat
*format
;
2339 IDWriteTextLayout
*layout
;
2340 IDWriteFactory
*factory
;
2341 DWRITE_TEXT_RANGE r
;
2344 factory
= create_factory();
2346 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
2347 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
2348 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2350 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 1000.0, 1000.0, &layout
);
2351 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2353 /* invalid stretch value */
2354 r
.startPosition
= 1;
2356 hr
= IDWriteTextLayout_SetFontStretch(layout
, DWRITE_FONT_STRETCH_ULTRA_EXPANDED
+1, r
);
2357 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
2359 r
.startPosition
= 1;
2361 stretch
= DWRITE_FONT_STRETCH_UNDEFINED
;
2362 hr
= IDWriteTextLayout_GetFontStretch(layout
, 0, &stretch
, &r
);
2363 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2364 ok(r
.startPosition
== 0 && r
.length
== ~0u, "got %u, %u\n", r
.startPosition
, r
.length
);
2365 ok(stretch
== DWRITE_FONT_STRETCH_NORMAL
, "got %d\n", stretch
);
2367 r
.startPosition
= 1;
2369 hr
= IDWriteTextLayout_SetFontStretch(layout
, DWRITE_FONT_STRETCH_CONDENSED
, r
);
2370 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2372 /* zero length range */
2373 r
.startPosition
= 1;
2375 hr
= IDWriteTextLayout_SetFontStretch(layout
, DWRITE_FONT_STRETCH_NORMAL
, r
);
2376 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2378 stretch
= DWRITE_FONT_STRETCH_UNDEFINED
;
2379 hr
= IDWriteTextLayout_GetFontStretch(layout
, 1, &stretch
, &r
);
2380 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2381 ok(stretch
== DWRITE_FONT_STRETCH_CONDENSED
, "got %d\n", stretch
);
2383 r
.startPosition
= 0;
2385 hr
= IDWriteTextLayout_SetFontStretch(layout
, DWRITE_FONT_STRETCH_EXPANDED
, r
);
2386 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2388 stretch
= DWRITE_FONT_STRETCH_UNDEFINED
;
2389 hr
= IDWriteTextLayout_GetFontStretch(layout
, 1, &stretch
, &r
);
2390 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2391 ok(stretch
== DWRITE_FONT_STRETCH_EXPANDED
, "got %d\n", stretch
);
2393 stretch
= DWRITE_FONT_STRETCH_UNDEFINED
;
2394 hr
= IDWriteTextLayout_GetFontStretch(layout
, 0, &stretch
, &r
);
2395 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2396 ok(r
.startPosition
== 0 && r
.length
== 4, "got %u, %u\n", r
.startPosition
, r
.length
);
2397 ok(stretch
== DWRITE_FONT_STRETCH_EXPANDED
, "got %d\n", stretch
);
2399 stretch
= DWRITE_FONT_STRETCH_UNDEFINED
;
2400 r
.startPosition
= r
.length
= 0;
2401 hr
= IDWriteTextLayout_GetFontStretch(layout
, 20, &stretch
, &r
);
2402 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2403 ok(r
.startPosition
== 4 && r
.length
== ~0u-4, "got %u, %u\n", r
.startPosition
, r
.length
);
2404 ok(stretch
== DWRITE_FONT_STRETCH_NORMAL
, "got %d\n", stretch
);
2406 r
.startPosition
= 100;
2408 hr
= IDWriteTextLayout_SetFontStretch(layout
, DWRITE_FONT_STRETCH_EXPANDED
, r
);
2409 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2411 stretch
= DWRITE_FONT_STRETCH_UNDEFINED
;
2412 r
.startPosition
= r
.length
= 0;
2413 hr
= IDWriteTextLayout_GetFontStretch(layout
, 100, &stretch
, &r
);
2414 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2415 ok(r
.startPosition
== 100 && r
.length
== 4, "got %u, %u\n", r
.startPosition
, r
.length
);
2416 ok(stretch
== DWRITE_FONT_STRETCH_EXPANDED
, "got %d\n", stretch
);
2418 /* trying to set undefined value */
2419 r
.startPosition
= 0;
2421 hr
= IDWriteTextLayout_SetFontStretch(layout
, DWRITE_FONT_STRETCH_UNDEFINED
, r
);
2422 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
2424 IDWriteTextLayout_Release(layout
);
2425 IDWriteTextFormat_Release(format
);
2426 IDWriteFactory_Release(factory
);
2429 static void test_SetStrikethrough(void)
2431 static const WCHAR strW
[] = {'a','b','c','d',0};
2432 IDWriteTextFormat
*format
;
2433 IDWriteTextLayout
*layout
;
2434 IDWriteFactory
*factory
;
2435 DWRITE_TEXT_RANGE r
;
2439 factory
= create_factory();
2441 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
2442 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
2443 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2445 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 1000.0, 1000.0, &layout
);
2446 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2448 r
.startPosition
= 1;
2451 hr
= IDWriteTextLayout_GetStrikethrough(layout
, 0, &value
, &r
);
2452 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2453 ok(r
.startPosition
== 0 && r
.length
== ~0u, "got %u, %u\n", r
.startPosition
, r
.length
);
2454 ok(value
== FALSE
, "got %d\n", value
);
2456 r
.startPosition
= 1;
2458 hr
= IDWriteTextLayout_SetStrikethrough(layout
, TRUE
, r
);
2459 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2462 hr
= IDWriteTextLayout_GetStrikethrough(layout
, 1, &value
, &r
);
2463 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2464 ok(value
== TRUE
, "got %d\n", value
);
2465 ok(r
.startPosition
== 1 && r
.length
== 1, "got %u, %u\n", r
.startPosition
, r
.length
);
2468 r
.startPosition
= r
.length
= 0;
2469 hr
= IDWriteTextLayout_GetStrikethrough(layout
, 20, &value
, &r
);
2470 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2471 ok(r
.startPosition
== 2 && r
.length
== ~0u-2, "got %u, %u\n", r
.startPosition
, r
.length
);
2472 ok(value
== FALSE
, "got %d\n", value
);
2474 r
.startPosition
= 100;
2476 hr
= IDWriteTextLayout_SetStrikethrough(layout
, TRUE
, r
);
2477 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2480 r
.startPosition
= r
.length
= 0;
2481 hr
= IDWriteTextLayout_GetStrikethrough(layout
, 100, &value
, &r
);
2482 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2483 ok(r
.startPosition
== 100 && r
.length
== 4, "got %u, %u\n", r
.startPosition
, r
.length
);
2484 ok(value
== TRUE
, "got %d\n", value
);
2486 IDWriteTextLayout_Release(layout
);
2487 IDWriteTextFormat_Release(format
);
2488 IDWriteFactory_Release(factory
);
2491 static void test_GetMetrics(void)
2493 static const WCHAR str2W
[] = {0x2066,')',')',0x661,'(',0x627,')',0};
2494 static const WCHAR strW
[] = {'a','b','c','d',0};
2495 static const WCHAR str3W
[] = {'a',0};
2496 DWRITE_CLUSTER_METRICS clusters
[4];
2497 DWRITE_TEXT_METRICS metrics
;
2498 IDWriteTextFormat
*format
;
2499 IDWriteTextLayout
*layout
;
2500 IDWriteFactory
*factory
;
2505 factory
= create_factory();
2507 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
2508 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
2509 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2511 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 500.0, 1000.0, &layout
);
2512 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2515 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, clusters
, 4, &count
);
2516 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2517 ok(count
== 4, "got %u\n", count
);
2518 for (i
= 0, width
= 0.0; i
< count
; i
++)
2519 width
+= clusters
[i
].width
;
2521 memset(&metrics
, 0xcc, sizeof(metrics
));
2522 hr
= IDWriteTextLayout_GetMetrics(layout
, &metrics
);
2523 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2524 ok(metrics
.left
== 0.0, "got %.2f\n", metrics
.left
);
2525 ok(metrics
.top
== 0.0, "got %.2f\n", metrics
.top
);
2526 ok(metrics
.width
== width
, "got %.2f, expected %.2f\n", metrics
.width
, width
);
2527 ok(metrics
.widthIncludingTrailingWhitespace
== width
, "got %.2f, expected %.2f\n",
2528 metrics
.widthIncludingTrailingWhitespace
, width
);
2529 ok(metrics
.height
> 0.0, "got %.2f\n", metrics
.height
);
2530 ok(metrics
.layoutWidth
== 500.0, "got %.2f\n", metrics
.layoutWidth
);
2531 ok(metrics
.layoutHeight
== 1000.0, "got %.2f\n", metrics
.layoutHeight
);
2532 ok(metrics
.maxBidiReorderingDepth
== 1, "got %u\n", metrics
.maxBidiReorderingDepth
);
2533 ok(metrics
.lineCount
== 1, "got %u\n", metrics
.lineCount
);
2535 IDWriteTextLayout_Release(layout
);
2537 /* a string with more complex bidi sequence */
2538 hr
= IDWriteFactory_CreateTextLayout(factory
, str2W
, 7, format
, 500.0, 1000.0, &layout
);
2539 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2541 memset(&metrics
, 0xcc, sizeof(metrics
));
2542 metrics
.maxBidiReorderingDepth
= 0;
2543 hr
= IDWriteTextLayout_GetMetrics(layout
, &metrics
);
2544 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2545 ok(metrics
.left
== 0.0, "got %.2f\n", metrics
.left
);
2546 ok(metrics
.top
== 0.0, "got %.2f\n", metrics
.top
);
2547 ok(metrics
.width
> 0.0, "got %.2f\n", metrics
.width
);
2548 ok(metrics
.widthIncludingTrailingWhitespace
> 0.0, "got %.2f\n", metrics
.widthIncludingTrailingWhitespace
);
2549 ok(metrics
.height
> 0.0, "got %.2f\n", metrics
.height
);
2550 ok(metrics
.layoutWidth
== 500.0, "got %.2f\n", metrics
.layoutWidth
);
2551 ok(metrics
.layoutHeight
== 1000.0, "got %.2f\n", metrics
.layoutHeight
);
2553 ok(metrics
.maxBidiReorderingDepth
> 1, "got %u\n", metrics
.maxBidiReorderingDepth
);
2554 ok(metrics
.lineCount
== 1, "got %u\n", metrics
.lineCount
);
2556 IDWriteTextLayout_Release(layout
);
2558 /* single cluster layout */
2559 hr
= IDWriteFactory_CreateTextLayout(factory
, str3W
, 1, format
, 500.0, 1000.0, &layout
);
2560 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2563 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, clusters
, 1, &count
);
2564 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2565 ok(count
== 1, "got %u\n", count
);
2567 memset(&metrics
, 0xcc, sizeof(metrics
));
2568 hr
= IDWriteTextLayout_GetMetrics(layout
, &metrics
);
2569 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2570 ok(metrics
.left
== 0.0, "got %.2f\n", metrics
.left
);
2571 ok(metrics
.top
== 0.0, "got %.2f\n", metrics
.top
);
2572 ok(metrics
.width
== clusters
[0].width
, "got %.2f, expected %.2f\n", metrics
.width
, clusters
[0].width
);
2573 ok(metrics
.widthIncludingTrailingWhitespace
== clusters
[0].width
, "got %.2f\n", metrics
.widthIncludingTrailingWhitespace
);
2574 ok(metrics
.height
> 0.0, "got %.2f\n", metrics
.height
);
2575 ok(metrics
.layoutWidth
== 500.0, "got %.2f\n", metrics
.layoutWidth
);
2576 ok(metrics
.layoutHeight
== 1000.0, "got %.2f\n", metrics
.layoutHeight
);
2577 ok(metrics
.maxBidiReorderingDepth
== 1, "got %u\n", metrics
.maxBidiReorderingDepth
);
2578 ok(metrics
.lineCount
== 1, "got %u\n", metrics
.lineCount
);
2579 IDWriteTextLayout_Release(layout
);
2581 IDWriteTextFormat_Release(format
);
2582 IDWriteFactory_Release(factory
);
2585 static void test_SetFlowDirection(void)
2587 static const WCHAR strW
[] = {'a','b','c','d',0};
2588 DWRITE_READING_DIRECTION reading
;
2589 DWRITE_FLOW_DIRECTION flow
;
2590 IDWriteTextFormat
*format
;
2591 IDWriteTextLayout
*layout
;
2592 IDWriteFactory
*factory
;
2595 factory
= create_factory();
2597 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
2598 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
2599 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2601 flow
= IDWriteTextFormat_GetFlowDirection(format
);
2602 ok(flow
== DWRITE_FLOW_DIRECTION_TOP_TO_BOTTOM
, "got %d\n", flow
);
2604 reading
= IDWriteTextFormat_GetReadingDirection(format
);
2605 ok(reading
== DWRITE_READING_DIRECTION_LEFT_TO_RIGHT
, "got %d\n", reading
);
2607 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 500.0, 1000.0, &layout
);
2608 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2609 IDWriteTextLayout_Release(layout
);
2611 hr
= IDWriteTextFormat_SetFlowDirection(format
, DWRITE_FLOW_DIRECTION_LEFT_TO_RIGHT
);
2612 ok(hr
== S_OK
|| broken(hr
== E_INVALIDARG
) /* vista,win7 */, "got 0x%08x\n", hr
);
2614 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 500.0, 1000.0, &layout
);
2615 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2616 IDWriteTextLayout_Release(layout
);
2618 hr
= IDWriteTextFormat_SetReadingDirection(format
, DWRITE_READING_DIRECTION_TOP_TO_BOTTOM
);
2619 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2621 hr
= IDWriteTextFormat_SetFlowDirection(format
, DWRITE_FLOW_DIRECTION_TOP_TO_BOTTOM
);
2622 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2624 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 500.0, 1000.0, &layout
);
2625 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2626 IDWriteTextLayout_Release(layout
);
2629 win_skip("DWRITE_FLOW_DIRECTION_LEFT_TO_RIGHT is not supported\n");
2631 IDWriteTextFormat_Release(format
);
2632 IDWriteFactory_Release(factory
);
2635 static const struct drawcall_entry draweffect_seq
[] = {
2636 { DRAW_GLYPHRUN
|DRAW_EFFECT
, {'a','e',0x0300,0} },
2637 { DRAW_GLYPHRUN
, {'d',0} },
2641 static const struct drawcall_entry draweffect2_seq
[] = {
2642 { DRAW_GLYPHRUN
|DRAW_EFFECT
, {'a','e',0} },
2643 { DRAW_GLYPHRUN
, {'c','d',0} },
2647 static const struct drawcall_entry draweffect3_seq
[] = {
2648 { DRAW_INLINE
|DRAW_EFFECT
},
2652 static const struct drawcall_entry draweffect4_seq
[] = {
2657 static void test_SetDrawingEffect(void)
2659 static const WCHAR strW
[] = {'a','e',0x0300,'d',0}; /* accent grave */
2660 static const WCHAR str2W
[] = {'a','e','c','d',0};
2661 IDWriteInlineObject
*sign
;
2662 IDWriteTextFormat
*format
;
2663 IDWriteTextLayout
*layout
;
2664 IDWriteFactory
*factory
;
2665 DWRITE_TEXT_RANGE r
;
2669 factory
= create_factory();
2671 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
2672 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
2673 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2675 /* string with combining mark */
2676 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 500.0, 1000.0, &layout
);
2677 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2679 /* set effect past the end of text */
2680 r
.startPosition
= 100;
2682 hr
= IDWriteTextLayout_SetDrawingEffect(layout
, &testeffect
, r
);
2683 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2685 r
.startPosition
= r
.length
= 0;
2686 hr
= IDWriteTextLayout_GetDrawingEffect(layout
, 101, &unk
, &r
);
2687 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2688 ok(r
.startPosition
== 100 && r
.length
== 10, "got %u, %u\n", r
.startPosition
, r
.length
);
2690 r
.startPosition
= r
.length
= 0;
2691 unk
= (void*)0xdeadbeef;
2692 hr
= IDWriteTextLayout_GetDrawingEffect(layout
, 1000, &unk
, &r
);
2693 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2694 ok(r
.startPosition
== 110 && r
.length
== ~0u-110, "got %u, %u\n", r
.startPosition
, r
.length
);
2695 ok(unk
== NULL
, "got %p\n", unk
);
2697 /* effect is applied to clusters, not individual text positions */
2698 r
.startPosition
= 0;
2700 hr
= IDWriteTextLayout_SetDrawingEffect(layout
, &testeffect
, r
);
2701 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2703 flush_sequence(sequences
, RENDERER_ID
);
2704 hr
= IDWriteTextLayout_Draw(layout
, NULL
, &testrenderer
, 0.0, 0.0);
2705 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2706 ok_sequence(sequences
, RENDERER_ID
, draweffect_seq
, "effect draw test", TRUE
);
2707 IDWriteTextLayout_Release(layout
);
2710 hr
= IDWriteFactory_CreateTextLayout(factory
, str2W
, 4, format
, 500.0, 1000.0, &layout
);
2711 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2713 r
.startPosition
= 0;
2715 hr
= IDWriteTextLayout_SetDrawingEffect(layout
, &testeffect
, r
);
2716 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2718 flush_sequence(sequences
, RENDERER_ID
);
2719 hr
= IDWriteTextLayout_Draw(layout
, NULL
, &testrenderer
, 0.0, 0.0);
2720 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2721 ok_sequence(sequences
, RENDERER_ID
, draweffect2_seq
, "effect draw test 2", TRUE
);
2722 IDWriteTextLayout_Release(layout
);
2724 /* Inline object - effect set for same range */
2725 hr
= IDWriteFactory_CreateEllipsisTrimmingSign(factory
, format
, &sign
);
2726 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2728 hr
= IDWriteFactory_CreateTextLayout(factory
, str2W
, 4, format
, 500.0, 1000.0, &layout
);
2729 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2731 r
.startPosition
= 0;
2733 hr
= IDWriteTextLayout_SetInlineObject(layout
, sign
, r
);
2734 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2736 hr
= IDWriteTextLayout_SetDrawingEffect(layout
, &testeffect
, r
);
2737 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2739 flush_sequence(sequences
, RENDERER_ID
);
2740 hr
= IDWriteTextLayout_Draw(layout
, NULL
, &testrenderer
, 0.0, 0.0);
2741 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2742 ok_sequence(sequences
, RENDERER_ID
, draweffect3_seq
, "effect draw test 3", FALSE
);
2744 /* now set effect somewhere inside a range replaced by inline object */
2745 hr
= IDWriteTextLayout_SetDrawingEffect(layout
, NULL
, r
);
2746 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2748 r
.startPosition
= 1;
2750 hr
= IDWriteTextLayout_SetDrawingEffect(layout
, &testeffect
, r
);
2751 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2753 /* no effect is reported in this case */
2754 flush_sequence(sequences
, RENDERER_ID
);
2755 hr
= IDWriteTextLayout_Draw(layout
, NULL
, &testrenderer
, 0.0, 0.0);
2756 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2757 ok_sequence(sequences
, RENDERER_ID
, draweffect4_seq
, "effect draw test 4", FALSE
);
2759 r
.startPosition
= 0;
2761 hr
= IDWriteTextLayout_SetDrawingEffect(layout
, NULL
, r
);
2762 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2764 r
.startPosition
= 0;
2766 hr
= IDWriteTextLayout_SetDrawingEffect(layout
, &testeffect
, r
);
2767 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2769 /* first range position is all that matters for inline ranges */
2770 flush_sequence(sequences
, RENDERER_ID
);
2771 hr
= IDWriteTextLayout_Draw(layout
, NULL
, &testrenderer
, 0.0, 0.0);
2772 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2773 ok_sequence(sequences
, RENDERER_ID
, draweffect3_seq
, "effect draw test 5", FALSE
);
2775 IDWriteTextLayout_Release(layout
);
2777 IDWriteInlineObject_Release(sign
);
2778 IDWriteTextFormat_Release(format
);
2779 IDWriteFactory_Release(factory
);
2782 static IDWriteFontFace
*get_fontface_from_format(IDWriteTextFormat
*format
)
2784 IDWriteFontCollection
*collection
;
2785 IDWriteFontFamily
*family
;
2786 IDWriteFontFace
*fontface
;
2793 hr
= IDWriteTextFormat_GetFontCollection(format
, &collection
);
2794 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2796 hr
= IDWriteTextFormat_GetFontFamilyName(format
, nameW
, sizeof(nameW
)/sizeof(WCHAR
));
2797 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2799 hr
= IDWriteFontCollection_FindFamilyName(collection
, nameW
, &index
, &exists
);
2800 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2802 hr
= IDWriteFontCollection_GetFontFamily(collection
, index
, &family
);
2803 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2804 IDWriteFontCollection_Release(collection
);
2806 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
,
2807 IDWriteTextFormat_GetFontWeight(format
),
2808 IDWriteTextFormat_GetFontStretch(format
),
2809 IDWriteTextFormat_GetFontStyle(format
),
2811 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2813 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
2814 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2816 IDWriteFont_Release(font
);
2817 IDWriteFontFamily_Release(family
);
2822 static void test_GetLineMetrics(void)
2824 static const WCHAR strW
[] = {'a','b','c','d',' ',0};
2825 static const WCHAR str2W
[] = {'a','b','\r','c','d',0};
2826 DWRITE_FONT_METRICS fontmetrics
;
2827 DWRITE_LINE_METRICS metrics
[2];
2828 IDWriteTextFormat
*format
;
2829 IDWriteTextLayout
*layout
;
2830 IDWriteFontFace
*fontface
;
2831 IDWriteFactory
*factory
;
2835 factory
= create_factory();
2837 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
2838 DWRITE_FONT_STRETCH_NORMAL
, 2048.0, enusW
, &format
);
2839 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2841 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 5, format
, 30000.0, 1000.0, &layout
);
2842 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2845 hr
= IDWriteTextLayout_GetLineMetrics(layout
, metrics
, 0, &count
);
2846 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
2847 ok(count
== 1, "got count %u\n", count
);
2849 memset(metrics
, 0, sizeof(metrics
));
2850 hr
= IDWriteTextLayout_GetLineMetrics(layout
, metrics
, 1, &count
);
2851 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2852 ok(metrics
[0].length
== 5, "got %u\n", metrics
[0].length
);
2853 ok(metrics
[0].trailingWhitespaceLength
== 1, "got %u\n", metrics
[0].trailingWhitespaceLength
);
2855 ok(metrics
[0].newlineLength
== 0, "got %u\n", metrics
[0].newlineLength
);
2856 ok(metrics
[0].isTrimmed
== FALSE
, "got %d\n", metrics
[0].isTrimmed
);
2858 /* Tahoma doesn't provide BASE table, so baseline is calculated from font metrics */
2859 fontface
= get_fontface_from_format(format
);
2860 ok(fontface
!= NULL
, "got %p\n", fontface
);
2861 IDWriteFontFace_GetMetrics(fontface
, &fontmetrics
);
2863 ok(metrics
[0].baseline
== fontmetrics
.ascent
, "got %.2f, expected %d\n", metrics
[0].baseline
,
2864 fontmetrics
.ascent
);
2865 ok(metrics
[0].height
== fontmetrics
.ascent
+ fontmetrics
.descent
, "got %.2f, expected %d\n",
2866 metrics
[0].height
, fontmetrics
.ascent
+ fontmetrics
.descent
);
2867 IDWriteTextLayout_Release(layout
);
2870 hr
= IDWriteFactory_CreateTextLayout(factory
, str2W
, 5, format
, 10000.0, 1000.0, &layout
);
2871 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2873 memset(metrics
, 0, sizeof(metrics
));
2875 hr
= IDWriteTextLayout_GetLineMetrics(layout
, metrics
, 2, &count
);
2876 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2878 ok(count
== 2, "got %u\n", count
);
2879 /* baseline is relative to a line, and is not accumulated */
2880 ok(metrics
[0].baseline
== metrics
[1].baseline
, "got %.2f, %.2f\n", metrics
[0].baseline
,
2881 metrics
[1].baseline
);
2883 IDWriteTextLayout_Release(layout
);
2885 IDWriteFontFace_Release(fontface
);
2886 IDWriteTextFormat_Release(format
);
2887 IDWriteFactory_Release(factory
);
2890 static void test_SetTextAlignment(void)
2892 static const WCHAR str2W
[] = {'a','a','a','a','a',0};
2893 static const WCHAR strW
[] = {'a',0};
2894 DWRITE_CLUSTER_METRICS clusters
[1];
2895 DWRITE_TEXT_METRICS metrics
;
2896 IDWriteTextFormat1
*format1
;
2897 IDWriteTextFormat
*format
;
2898 IDWriteTextLayout
*layout
;
2899 IDWriteFactory
*factory
;
2900 DWRITE_TEXT_ALIGNMENT v
;
2904 factory
= create_factory();
2906 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
2907 DWRITE_FONT_STRETCH_NORMAL
, 12.0, enusW
, &format
);
2908 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2910 v
= IDWriteTextFormat_GetTextAlignment(format
);
2911 ok(v
== DWRITE_TEXT_ALIGNMENT_LEADING
, "got %d\n", v
);
2913 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 1, format
, 500.0, 100.0, &layout
);
2914 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2916 v
= IDWriteTextLayout_GetTextAlignment(layout
);
2917 ok(v
== DWRITE_TEXT_ALIGNMENT_LEADING
, "got %d\n", v
);
2919 hr
= IDWriteTextLayout_SetTextAlignment(layout
, DWRITE_TEXT_ALIGNMENT_TRAILING
);
2920 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2922 hr
= IDWriteTextLayout_SetTextAlignment(layout
, DWRITE_TEXT_ALIGNMENT_TRAILING
);
2923 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2925 v
= IDWriteTextFormat_GetTextAlignment(format
);
2926 ok(v
== DWRITE_TEXT_ALIGNMENT_LEADING
, "got %d\n", v
);
2928 v
= IDWriteTextLayout_GetTextAlignment(layout
);
2929 ok(v
== DWRITE_TEXT_ALIGNMENT_TRAILING
, "got %d\n", v
);
2931 hr
= IDWriteTextLayout_QueryInterface(layout
, &IID_IDWriteTextFormat1
, (void**)&format1
);
2933 hr
= IDWriteTextFormat1_SetTextAlignment(format1
, DWRITE_TEXT_ALIGNMENT_CENTER
);
2934 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2936 v
= IDWriteTextFormat_GetTextAlignment(format
);
2937 ok(v
== DWRITE_TEXT_ALIGNMENT_LEADING
, "got %d\n", v
);
2939 v
= IDWriteTextLayout_GetTextAlignment(layout
);
2940 ok(v
== DWRITE_TEXT_ALIGNMENT_CENTER
, "got %d\n", v
);
2942 v
= IDWriteTextFormat1_GetTextAlignment(format1
);
2943 ok(v
== DWRITE_TEXT_ALIGNMENT_CENTER
, "got %d\n", v
);
2945 IDWriteTextFormat1_Release(format1
);
2948 win_skip("IDWriteTextFormat1 is not supported\n");
2951 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, clusters
, 1, &count
);
2952 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2953 ok(count
== 1, "got %u\n", count
);
2955 /* maxwidth is 500, leading alignment */
2956 hr
= IDWriteTextLayout_SetTextAlignment(layout
, DWRITE_TEXT_ALIGNMENT_LEADING
);
2957 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2959 hr
= IDWriteTextLayout_GetMetrics(layout
, &metrics
);
2960 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2962 ok(metrics
.left
== 0.0, "got %.2f\n", metrics
.left
);
2963 ok(metrics
.width
== clusters
[0].width
, "got %.2f\n", metrics
.width
);
2964 ok(metrics
.layoutWidth
== 500.0, "got %.2f\n", metrics
.layoutWidth
);
2965 ok(metrics
.lineCount
== 1, "got %d\n", metrics
.lineCount
);
2967 /* maxwidth is 500, trailing alignment */
2968 hr
= IDWriteTextLayout_SetTextAlignment(layout
, DWRITE_TEXT_ALIGNMENT_TRAILING
);
2969 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2971 hr
= IDWriteTextLayout_GetMetrics(layout
, &metrics
);
2972 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2974 ok(metrics
.left
== metrics
.layoutWidth
- metrics
.width
, "got %.2f\n", metrics
.left
);
2975 ok(metrics
.width
== clusters
[0].width
, "got %.2f\n", metrics
.width
);
2976 ok(metrics
.layoutWidth
== 500.0, "got %.2f\n", metrics
.layoutWidth
);
2977 ok(metrics
.lineCount
== 1, "got %d\n", metrics
.lineCount
);
2978 IDWriteTextLayout_Release(layout
);
2980 /* initially created with trailing alignment */
2981 hr
= IDWriteTextFormat_SetTextAlignment(format
, DWRITE_TEXT_ALIGNMENT_TRAILING
);
2982 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2984 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 1, format
, 500.0, 100.0, &layout
);
2985 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2987 hr
= IDWriteTextLayout_GetMetrics(layout
, &metrics
);
2988 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2990 ok(metrics
.left
== metrics
.layoutWidth
- metrics
.width
, "got %.2f\n", metrics
.left
);
2991 ok(metrics
.width
== clusters
[0].width
, "got %.2f\n", metrics
.width
);
2992 ok(metrics
.layoutWidth
== 500.0, "got %.2f\n", metrics
.layoutWidth
);
2993 ok(metrics
.lineCount
== 1, "got %d\n", metrics
.lineCount
);
2994 IDWriteTextLayout_Release(layout
);
2996 /* max width less than total run width, trailing alignment */
2997 hr
= IDWriteTextFormat_SetWordWrapping(format
, DWRITE_WORD_WRAPPING_NO_WRAP
);
2998 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3000 hr
= IDWriteFactory_CreateTextLayout(factory
, str2W
, 5, format
, 2*clusters
[0].width
, 100.0, &layout
);
3001 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3002 hr
= IDWriteTextLayout_GetMetrics(layout
, &metrics
);
3003 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3004 ok(metrics
.left
== metrics
.layoutWidth
- metrics
.width
, "got %.2f\n", metrics
.left
);
3006 ok(metrics
.width
== 5*clusters
[0].width
, "got %.2f\n", metrics
.width
);
3007 ok(metrics
.lineCount
== 1, "got %d\n", metrics
.lineCount
);
3008 IDWriteTextLayout_Release(layout
);
3010 /* maxwidth is 500, centered */
3011 hr
= IDWriteTextFormat_SetTextAlignment(format
, DWRITE_TEXT_ALIGNMENT_CENTER
);
3012 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3014 hr
= IDWriteFactory_CreateTextLayout(factory
, str2W
, 5, format
, 500.0, 100.0, &layout
);
3015 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3017 hr
= IDWriteTextLayout_GetMetrics(layout
, &metrics
);
3018 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3019 ok(metrics
.left
== (metrics
.layoutWidth
- metrics
.width
) / 2.0, "got %.2f\n", metrics
.left
);
3020 ok(metrics
.width
== 5*clusters
[0].width
, "got %.2f\n", metrics
.width
);
3021 ok(metrics
.lineCount
== 1, "got %d\n", metrics
.lineCount
);
3023 IDWriteTextLayout_Release(layout
);
3025 IDWriteTextFormat_Release(format
);
3026 IDWriteFactory_Release(factory
);
3029 static void test_SetParagraphAlignment(void)
3031 static const WCHAR strW
[] = {'a',0};
3032 DWRITE_TEXT_METRICS metrics
;
3033 IDWriteTextFormat
*format
;
3034 IDWriteTextLayout
*layout
;
3035 IDWriteFactory
*factory
;
3036 DWRITE_PARAGRAPH_ALIGNMENT v
;
3037 DWRITE_LINE_METRICS lines
[1];
3041 factory
= create_factory();
3043 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
3044 DWRITE_FONT_STRETCH_NORMAL
, 12.0, enusW
, &format
);
3045 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3047 v
= IDWriteTextFormat_GetParagraphAlignment(format
);
3048 ok(v
== DWRITE_PARAGRAPH_ALIGNMENT_NEAR
, "got %d\n", v
);
3050 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 1, format
, 500.0, 100.0, &layout
);
3051 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3053 v
= IDWriteTextLayout_GetParagraphAlignment(layout
);
3054 ok(v
== DWRITE_PARAGRAPH_ALIGNMENT_NEAR
, "got %d\n", v
);
3056 hr
= IDWriteTextLayout_SetParagraphAlignment(layout
, DWRITE_PARAGRAPH_ALIGNMENT_FAR
);
3057 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3059 hr
= IDWriteTextLayout_SetParagraphAlignment(layout
, DWRITE_PARAGRAPH_ALIGNMENT_FAR
);
3060 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3062 v
= IDWriteTextFormat_GetParagraphAlignment(format
);
3063 ok(v
== DWRITE_PARAGRAPH_ALIGNMENT_NEAR
, "got %d\n", v
);
3065 v
= IDWriteTextLayout_GetParagraphAlignment(layout
);
3066 ok(v
== DWRITE_PARAGRAPH_ALIGNMENT_FAR
, "got %d\n", v
);
3068 hr
= IDWriteTextLayout_SetParagraphAlignment(layout
, DWRITE_PARAGRAPH_ALIGNMENT_CENTER
);
3069 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3071 v
= IDWriteTextLayout_GetParagraphAlignment(layout
);
3072 ok(v
== DWRITE_PARAGRAPH_ALIGNMENT_CENTER
, "got %d\n", v
);
3075 hr
= IDWriteTextLayout_GetLineMetrics(layout
, lines
, 1, &count
);
3076 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3077 ok(count
== 1, "got %u\n", count
);
3079 /* maxheight is 100, near alignment */
3080 hr
= IDWriteTextLayout_SetParagraphAlignment(layout
, DWRITE_PARAGRAPH_ALIGNMENT_NEAR
);
3081 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3083 hr
= IDWriteTextLayout_GetMetrics(layout
, &metrics
);
3084 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3086 ok(metrics
.top
== 0.0, "got %.2f\n", metrics
.top
);
3087 ok(metrics
.height
== lines
[0].height
, "got %.2f\n", metrics
.height
);
3088 ok(metrics
.layoutHeight
== 100.0, "got %.2f\n", metrics
.layoutHeight
);
3089 ok(metrics
.lineCount
== 1, "got %d\n", metrics
.lineCount
);
3091 /* maxwidth is 100, far alignment */
3092 hr
= IDWriteTextLayout_SetParagraphAlignment(layout
, DWRITE_PARAGRAPH_ALIGNMENT_FAR
);
3093 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3095 hr
= IDWriteTextLayout_GetMetrics(layout
, &metrics
);
3096 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3098 ok(metrics
.top
== metrics
.layoutHeight
- metrics
.height
, "got %.2f\n", metrics
.top
);
3099 ok(metrics
.height
== lines
[0].height
, "got %.2f\n", metrics
.height
);
3100 ok(metrics
.layoutHeight
== 100.0, "got %.2f\n", metrics
.layoutHeight
);
3101 ok(metrics
.lineCount
== 1, "got %d\n", metrics
.lineCount
);
3102 IDWriteTextLayout_Release(layout
);
3104 /* initially created with centered alignment */
3105 hr
= IDWriteTextFormat_SetParagraphAlignment(format
, DWRITE_PARAGRAPH_ALIGNMENT_CENTER
);
3106 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3108 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 1, format
, 500.0, 100.0, &layout
);
3109 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3111 hr
= IDWriteTextLayout_GetMetrics(layout
, &metrics
);
3112 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3114 ok(metrics
.top
== (metrics
.layoutHeight
- lines
[0].height
) / 2, "got %.2f\n", metrics
.top
);
3115 ok(metrics
.height
== lines
[0].height
, "got %.2f\n", metrics
.height
);
3116 ok(metrics
.lineCount
== 1, "got %d\n", metrics
.lineCount
);
3117 IDWriteTextLayout_Release(layout
);
3119 IDWriteTextFormat_Release(format
);
3120 IDWriteFactory_Release(factory
);
3125 static const WCHAR ctrlstrW
[] = {0x202a,0};
3126 IDWriteFactory
*factory
;
3128 if (!(factory
= create_factory())) {
3129 win_skip("failed to create factory\n");
3133 /* actual script ids are not fixed */
3134 get_script_analysis(ctrlstrW
, 1, &g_control_sa
);
3136 init_call_sequences(sequences
, NUM_CALL_SEQUENCES
);
3137 init_call_sequences(expected_seq
, 1);
3139 test_CreateTextLayout();
3140 test_CreateGdiCompatibleTextLayout();
3141 test_CreateTextFormat();
3142 test_GetLocaleName();
3143 test_CreateEllipsisTrimmingSign();
3145 test_SetInlineObject();
3148 test_GetClusterMetrics();
3149 test_SetLocaleName();
3150 test_SetPairKerning();
3151 test_SetVerticalGlyphOrientation();
3153 test_DetermineMinWidth();
3155 test_SetFontFamilyName();
3156 test_SetFontStyle();
3157 test_SetFontStretch();
3158 test_SetStrikethrough();
3160 test_SetFlowDirection();
3161 test_SetDrawingEffect();
3162 test_GetLineMetrics();
3163 test_SetTextAlignment();
3164 test_SetParagraphAlignment();
3166 IDWriteFactory_Release(factory
);