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
31 #include "wine/test.h"
33 static const WCHAR tahomaW
[] = {'T','a','h','o','m','a',0};
34 static const WCHAR enusW
[] = {'e','n','-','u','s',0};
36 static DWRITE_SCRIPT_ANALYSIS g_sa
;
37 static DWRITE_SCRIPT_ANALYSIS g_control_sa
;
39 /* test IDWriteTextAnalysisSink */
40 static HRESULT WINAPI
analysissink_QueryInterface(IDWriteTextAnalysisSink
*iface
, REFIID riid
, void **obj
)
42 if (IsEqualIID(riid
, &IID_IDWriteTextAnalysisSink
) || IsEqualIID(riid
, &IID_IUnknown
))
52 static ULONG WINAPI
analysissink_AddRef(IDWriteTextAnalysisSink
*iface
)
57 static ULONG WINAPI
analysissink_Release(IDWriteTextAnalysisSink
*iface
)
62 static HRESULT WINAPI
analysissink_SetScriptAnalysis(IDWriteTextAnalysisSink
*iface
,
63 UINT32 position
, UINT32 length
, DWRITE_SCRIPT_ANALYSIS
const* sa
)
69 static HRESULT WINAPI
analysissink_SetLineBreakpoints(IDWriteTextAnalysisSink
*iface
,
70 UINT32 position
, UINT32 length
, DWRITE_LINE_BREAKPOINT
const* breakpoints
)
72 ok(0, "unexpected call\n");
76 static HRESULT WINAPI
analysissink_SetBidiLevel(IDWriteTextAnalysisSink
*iface
,
77 UINT32 position
, UINT32 length
, UINT8 explicitLevel
, UINT8 resolvedLevel
)
79 ok(0, "unexpected\n");
83 static HRESULT WINAPI
analysissink_SetNumberSubstitution(IDWriteTextAnalysisSink
*iface
,
84 UINT32 position
, UINT32 length
, IDWriteNumberSubstitution
* substitution
)
86 ok(0, "unexpected\n");
90 static IDWriteTextAnalysisSinkVtbl analysissinkvtbl
= {
91 analysissink_QueryInterface
,
94 analysissink_SetScriptAnalysis
,
95 analysissink_SetLineBreakpoints
,
96 analysissink_SetBidiLevel
,
97 analysissink_SetNumberSubstitution
100 static IDWriteTextAnalysisSink analysissink
= { &analysissinkvtbl
};
102 /* test IDWriteTextAnalysisSource */
103 static HRESULT WINAPI
analysissource_QueryInterface(IDWriteTextAnalysisSource
*iface
,
104 REFIID riid
, void **obj
)
106 if (IsEqualIID(riid
, &IID_IDWriteTextAnalysisSource
) || IsEqualIID(riid
, &IID_IUnknown
)) {
108 IDWriteTextAnalysisSource_AddRef(iface
);
111 return E_NOINTERFACE
;
114 static ULONG WINAPI
analysissource_AddRef(IDWriteTextAnalysisSource
*iface
)
119 static ULONG WINAPI
analysissource_Release(IDWriteTextAnalysisSource
*iface
)
124 static const WCHAR
*g_source
;
126 static HRESULT WINAPI
analysissource_GetTextAtPosition(IDWriteTextAnalysisSource
*iface
,
127 UINT32 position
, WCHAR
const** text
, UINT32
* text_len
)
129 if (position
>= lstrlenW(g_source
))
136 *text
= &g_source
[position
];
137 *text_len
= lstrlenW(g_source
) - position
;
143 static HRESULT WINAPI
analysissource_GetTextBeforePosition(IDWriteTextAnalysisSource
*iface
,
144 UINT32 position
, WCHAR
const** text
, UINT32
* text_len
)
146 ok(0, "unexpected\n");
150 static DWRITE_READING_DIRECTION WINAPI
analysissource_GetParagraphReadingDirection(
151 IDWriteTextAnalysisSource
*iface
)
153 ok(0, "unexpected\n");
154 return DWRITE_READING_DIRECTION_RIGHT_TO_LEFT
;
157 static HRESULT WINAPI
analysissource_GetLocaleName(IDWriteTextAnalysisSource
*iface
,
158 UINT32 position
, UINT32
* text_len
, WCHAR
const** locale
)
165 static HRESULT WINAPI
analysissource_GetNumberSubstitution(IDWriteTextAnalysisSource
*iface
,
166 UINT32 position
, UINT32
* text_len
, IDWriteNumberSubstitution
**substitution
)
168 ok(0, "unexpected\n");
172 static IDWriteTextAnalysisSourceVtbl analysissourcevtbl
= {
173 analysissource_QueryInterface
,
174 analysissource_AddRef
,
175 analysissource_Release
,
176 analysissource_GetTextAtPosition
,
177 analysissource_GetTextBeforePosition
,
178 analysissource_GetParagraphReadingDirection
,
179 analysissource_GetLocaleName
,
180 analysissource_GetNumberSubstitution
183 static IDWriteTextAnalysisSource analysissource
= { &analysissourcevtbl
};
185 static IDWriteFactory
*create_factory(void)
187 IDWriteFactory
*factory
;
188 HRESULT hr
= DWriteCreateFactory(DWRITE_FACTORY_TYPE_ISOLATED
, &IID_IDWriteFactory
, (IUnknown
**)&factory
);
189 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
193 /* obvious limitation is that only last script data is returned, so this
194 helper is suitable for single script strings only */
195 static void get_script_analysis(const WCHAR
*str
, UINT32 len
, DWRITE_SCRIPT_ANALYSIS
*sa
)
197 IDWriteTextAnalyzer
*analyzer
;
198 IDWriteFactory
*factory
;
203 factory
= create_factory();
204 hr
= IDWriteFactory_CreateTextAnalyzer(factory
, &analyzer
);
205 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
207 hr
= IDWriteTextAnalyzer_AnalyzeScript(analyzer
, &analysissource
, 0, len
, &analysissink
);
208 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
211 IDWriteFactory_Release(factory
);
214 #define EXPECT_REF(obj,ref) _expect_ref((IUnknown*)obj, ref, __LINE__)
215 static void _expect_ref(IUnknown
* obj
, ULONG ref
, int line
)
217 ULONG rc
= IUnknown_AddRef(obj
);
218 IUnknown_Release(obj
);
219 ok_(__FILE__
,line
)(rc
-1 == ref
, "expected refcount %d, got %d\n", ref
, rc
-1);
222 enum drawcall_modifiers_kind
{
229 DRAW_STRIKETHROUGH
= 2,
232 DRAW_TOTAL_KINDS
= 5,
233 DRAW_KINDS_MASK
= 0xff
236 static const char *get_draw_kind_name(unsigned short kind
)
238 static const char *kind_names
[] = {
247 "STRIKETHROUGH|EFFECT",
251 if ((kind
& DRAW_KINDS_MASK
) > DRAW_LAST_KIND
)
253 return (kind
& DRAW_EFFECT
) ? kind_names
[(kind
& DRAW_KINDS_MASK
) + DRAW_TOTAL_KINDS
] :
257 struct drawcall_entry
{
258 enum drawcall_kind kind
;
259 WCHAR string
[10]; /* only meaningful for DrawGlyphRun() */
262 struct drawcall_sequence
266 struct drawcall_entry
*sequence
;
269 struct drawtestcontext
{
277 #define NUM_CALL_SEQUENCES 1
278 #define RENDERER_ID 0
279 static struct drawcall_sequence
*sequences
[NUM_CALL_SEQUENCES
];
280 static struct drawcall_sequence
*expected_seq
[1];
282 static void add_call(struct drawcall_sequence
**seq
, int sequence_index
, const struct drawcall_entry
*call
)
284 struct drawcall_sequence
*call_seq
= seq
[sequence_index
];
286 if (!call_seq
->sequence
) {
288 call_seq
->sequence
= HeapAlloc(GetProcessHeap(), 0, call_seq
->size
* sizeof (struct drawcall_entry
));
291 if (call_seq
->count
== call_seq
->size
) {
293 call_seq
->sequence
= HeapReAlloc(GetProcessHeap(), 0,
295 call_seq
->size
* sizeof (struct drawcall_entry
));
298 assert(call_seq
->sequence
);
299 call_seq
->sequence
[call_seq
->count
++] = *call
;
302 static inline void flush_sequence(struct drawcall_sequence
**seg
, int sequence_index
)
304 struct drawcall_sequence
*call_seq
= seg
[sequence_index
];
306 HeapFree(GetProcessHeap(), 0, call_seq
->sequence
);
307 call_seq
->sequence
= NULL
;
308 call_seq
->count
= call_seq
->size
= 0;
311 static inline void flush_sequences(struct drawcall_sequence
**seq
, int n
)
314 for (i
= 0; i
< n
; i
++)
315 flush_sequence(seq
, i
);
318 static void init_call_sequences(struct drawcall_sequence
**seq
, int n
)
322 for (i
= 0; i
< n
; i
++)
323 seq
[i
] = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(struct drawcall_sequence
));
326 static void ok_sequence_(struct drawcall_sequence
**seq
, int sequence_index
,
327 const struct drawcall_entry
*expected
, const char *context
, BOOL todo
,
328 const char *file
, int line
)
330 static const struct drawcall_entry end_of_sequence
= { DRAW_LAST_KIND
};
331 struct drawcall_sequence
*call_seq
= seq
[sequence_index
];
332 const struct drawcall_entry
*actual
, *sequence
;
335 add_call(seq
, sequence_index
, &end_of_sequence
);
337 sequence
= call_seq
->sequence
;
340 while (expected
->kind
!= DRAW_LAST_KIND
&& actual
->kind
!= DRAW_LAST_KIND
) {
341 if (expected
->kind
!= actual
->kind
) {
345 ok_(file
, line
) (0, "%s: call %s was expected, but got call %s instead\n",
346 context
, get_draw_kind_name(expected
->kind
), get_draw_kind_name(actual
->kind
));
348 flush_sequence(seq
, sequence_index
);
352 ok_(file
, line
) (0, "%s: call %s was expected, but got call %s instead\n",
353 context
, get_draw_kind_name(expected
->kind
), get_draw_kind_name(actual
->kind
));
355 else if ((expected
->kind
& DRAW_KINDS_MASK
) == DRAW_GLYPHRUN
) {
356 int cmp
= lstrcmpW(expected
->string
, actual
->string
);
357 if (cmp
!= 0 && todo
) {
360 ok_(file
, line
) (0, "%s: glyphrun string %s was expected, but got %s instead\n",
361 context
, wine_dbgstr_w(expected
->string
), wine_dbgstr_w(actual
->string
));
364 ok_(file
, line
) (cmp
== 0, "%s: glyphrun string %s was expected, but got %s instead\n",
365 context
, wine_dbgstr_w(expected
->string
), wine_dbgstr_w(actual
->string
));
373 if (expected
->kind
!= DRAW_LAST_KIND
|| actual
->kind
!= DRAW_LAST_KIND
) {
375 ok_(file
, line
) (0, "%s: the call sequence is not complete: expected %s - actual %s\n",
376 context
, get_draw_kind_name(expected
->kind
), get_draw_kind_name(actual
->kind
));
380 else if (expected
->kind
!= DRAW_LAST_KIND
|| actual
->kind
!= DRAW_LAST_KIND
)
381 ok_(file
, line
) (0, "%s: the call sequence is not complete: expected %s - actual %s\n",
382 context
, get_draw_kind_name(expected
->kind
), get_draw_kind_name(actual
->kind
));
384 if (todo
&& !failcount
) /* succeeded yet marked todo */
386 ok_(file
, line
)(1, "%s: marked \"todo_wine\" but succeeds\n", context
);
388 flush_sequence(seq
, sequence_index
);
391 #define ok_sequence(seq, index, exp, contx, todo) \
392 ok_sequence_(seq, index, (exp), (contx), (todo), __FILE__, __LINE__)
394 static HRESULT WINAPI
testrenderer_QI(IDWriteTextRenderer
*iface
, REFIID riid
, void **obj
)
396 if (IsEqualIID(riid
, &IID_IDWriteTextRenderer
) ||
397 IsEqualIID(riid
, &IID_IDWritePixelSnapping
) ||
398 IsEqualIID(riid
, &IID_IUnknown
)
406 /* IDWriteTextRenderer1 overrides drawing calls, ignore for now */
407 if (IsEqualIID(riid
, &IID_IDWriteTextRenderer1
))
408 return E_NOINTERFACE
;
410 ok(0, "unexpected QI %s\n", wine_dbgstr_guid(riid
));
411 return E_NOINTERFACE
;
414 static ULONG WINAPI
testrenderer_AddRef(IDWriteTextRenderer
*iface
)
419 static ULONG WINAPI
testrenderer_Release(IDWriteTextRenderer
*iface
)
424 struct renderer_context
{
426 BOOL use_gdi_natural
;
427 BOOL snapping_disabled
;
434 static HRESULT WINAPI
testrenderer_IsPixelSnappingDisabled(IDWriteTextRenderer
*iface
,
435 void *context
, BOOL
*disabled
)
437 struct renderer_context
*ctxt
= (struct renderer_context
*)context
;
439 *disabled
= ctxt
->snapping_disabled
;
445 static HRESULT WINAPI
testrenderer_GetCurrentTransform(IDWriteTextRenderer
*iface
,
446 void *context
, DWRITE_MATRIX
*m
)
448 struct renderer_context
*ctxt
= (struct renderer_context
*)context
;
449 ok(!ctxt
->snapping_disabled
, "expected enabled snapping\n");
454 static HRESULT WINAPI
testrenderer_GetPixelsPerDip(IDWriteTextRenderer
*iface
,
455 void *context
, FLOAT
*pixels_per_dip
)
457 struct renderer_context
*ctxt
= (struct renderer_context
*)context
;
458 *pixels_per_dip
= ctxt
->ppdip
;
462 #define TEST_MEASURING_MODE(ctxt, mode) test_measuring_mode(ctxt, mode, __LINE__)
463 static void test_measuring_mode(const struct renderer_context
*ctxt
, DWRITE_MEASURING_MODE mode
, int line
)
465 if (ctxt
->gdicompat
) {
466 if (ctxt
->use_gdi_natural
)
467 ok_(__FILE__
, line
)(mode
== DWRITE_MEASURING_MODE_GDI_NATURAL
, "got %d\n", mode
);
469 ok_(__FILE__
, line
)(mode
== DWRITE_MEASURING_MODE_GDI_CLASSIC
, "got %d\n", mode
);
472 ok_(__FILE__
, line
)(mode
== DWRITE_MEASURING_MODE_NATURAL
, "got %d\n", mode
);
475 static HRESULT WINAPI
testrenderer_DrawGlyphRun(IDWriteTextRenderer
*iface
,
477 FLOAT baselineOriginX
,
478 FLOAT baselineOriginY
,
479 DWRITE_MEASURING_MODE mode
,
480 DWRITE_GLYPH_RUN
const *run
,
481 DWRITE_GLYPH_RUN_DESCRIPTION
const *descr
,
484 struct renderer_context
*ctxt
= (struct renderer_context
*)context
;
485 struct drawcall_entry entry
;
486 DWRITE_SCRIPT_ANALYSIS sa
;
489 TEST_MEASURING_MODE(ctxt
, mode
);
490 ctxt
->originX
= baselineOriginX
;
491 ctxt
->originY
= baselineOriginY
;
494 ok(descr
->stringLength
< sizeof(entry
.string
)/sizeof(WCHAR
), "string is too long\n");
495 if (descr
->stringLength
&& descr
->stringLength
< sizeof(entry
.string
)/sizeof(WCHAR
)) {
496 memcpy(entry
.string
, descr
->string
, descr
->stringLength
*sizeof(WCHAR
));
497 entry
.string
[descr
->stringLength
] = 0;
502 /* see what's reported for control codes runs */
503 get_script_analysis(descr
->string
, descr
->stringLength
, &sa
);
504 if (sa
.script
== g_control_sa
.script
) {
505 /* glyphs are not reported at all for control code runs */
506 ok(run
->glyphCount
== 0, "got %u\n", run
->glyphCount
);
507 ok(run
->glyphAdvances
!= NULL
, "advances array %p\n", run
->glyphAdvances
);
508 ok(run
->glyphOffsets
!= NULL
, "offsets array %p\n", run
->glyphOffsets
);
509 ok(run
->fontFace
!= NULL
, "got %p\n", run
->fontFace
);
510 /* text positions are still valid */
511 ok(descr
->string
!= NULL
, "got string %p\n", descr
->string
);
512 ok(descr
->stringLength
> 0, "got string length %u\n", descr
->stringLength
);
513 ok(descr
->clusterMap
!= NULL
, "clustermap %p\n", descr
->clusterMap
);
516 entry
.kind
= DRAW_GLYPHRUN
;
518 entry
.kind
|= DRAW_EFFECT
;
519 add_call(sequences
, RENDERER_ID
, &entry
);
523 static HRESULT WINAPI
testrenderer_DrawUnderline(IDWriteTextRenderer
*iface
,
525 FLOAT baselineOriginX
,
526 FLOAT baselineOriginY
,
527 DWRITE_UNDERLINE
const* underline
,
530 struct renderer_context
*ctxt
= (struct renderer_context
*)context
;
531 struct drawcall_entry entry
;
534 TEST_MEASURING_MODE(ctxt
, underline
->measuringMode
);
536 entry
.kind
= DRAW_UNDERLINE
;
538 entry
.kind
|= DRAW_EFFECT
;
539 add_call(sequences
, RENDERER_ID
, &entry
);
543 static HRESULT WINAPI
testrenderer_DrawStrikethrough(IDWriteTextRenderer
*iface
,
545 FLOAT baselineOriginX
,
546 FLOAT baselineOriginY
,
547 DWRITE_STRIKETHROUGH
const* strikethrough
,
550 struct renderer_context
*ctxt
= (struct renderer_context
*)context
;
551 struct drawcall_entry entry
;
554 TEST_MEASURING_MODE(ctxt
, strikethrough
->measuringMode
);
556 entry
.kind
= DRAW_STRIKETHROUGH
;
558 entry
.kind
|= DRAW_EFFECT
;
559 add_call(sequences
, RENDERER_ID
, &entry
);
563 static HRESULT WINAPI
testrenderer_DrawInlineObject(IDWriteTextRenderer
*iface
,
567 IDWriteInlineObject
*object
,
572 struct drawcall_entry entry
;
573 entry
.kind
= DRAW_INLINE
;
575 entry
.kind
|= DRAW_EFFECT
;
576 add_call(sequences
, RENDERER_ID
, &entry
);
580 static const IDWriteTextRendererVtbl testrenderervtbl
= {
583 testrenderer_Release
,
584 testrenderer_IsPixelSnappingDisabled
,
585 testrenderer_GetCurrentTransform
,
586 testrenderer_GetPixelsPerDip
,
587 testrenderer_DrawGlyphRun
,
588 testrenderer_DrawUnderline
,
589 testrenderer_DrawStrikethrough
,
590 testrenderer_DrawInlineObject
593 static IDWriteTextRenderer testrenderer
= { &testrenderervtbl
};
595 /* test IDWriteInlineObject */
596 static HRESULT WINAPI
testinlineobj_QI(IDWriteInlineObject
*iface
, REFIID riid
, void **obj
)
598 if (IsEqualIID(riid
, &IID_IDWriteInlineObject
) || IsEqualIID(riid
, &IID_IUnknown
)) {
600 IDWriteInlineObject_AddRef(iface
);
605 return E_NOINTERFACE
;
608 static ULONG WINAPI
testinlineobj_AddRef(IDWriteInlineObject
*iface
)
613 static ULONG WINAPI
testinlineobj_Release(IDWriteInlineObject
*iface
)
618 static HRESULT WINAPI
testinlineobj_Draw(IDWriteInlineObject
*iface
,
619 void* client_drawingontext
, IDWriteTextRenderer
* renderer
,
620 FLOAT originX
, FLOAT originY
, BOOL is_sideways
, BOOL is_rtl
, IUnknown
*drawing_effect
)
622 ok(0, "unexpected call\n");
626 static HRESULT WINAPI
testinlineobj_GetMetrics(IDWriteInlineObject
*iface
, DWRITE_INLINE_OBJECT_METRICS
*metrics
)
628 metrics
->width
= 123.0;
632 static HRESULT WINAPI
testinlineobj_GetOverhangMetrics(IDWriteInlineObject
*iface
, DWRITE_OVERHANG_METRICS
*overhangs
)
634 ok(0, "unexpected call\n");
638 static HRESULT WINAPI
testinlineobj_GetBreakConditions(IDWriteInlineObject
*iface
, DWRITE_BREAK_CONDITION
*before
,
639 DWRITE_BREAK_CONDITION
*after
)
641 *before
= *after
= DWRITE_BREAK_CONDITION_MUST_BREAK
;
645 static HRESULT WINAPI
testinlineobj2_GetBreakConditions(IDWriteInlineObject
*iface
, DWRITE_BREAK_CONDITION
*before
,
646 DWRITE_BREAK_CONDITION
*after
)
648 *before
= *after
= DWRITE_BREAK_CONDITION_MAY_NOT_BREAK
;
652 static IDWriteInlineObjectVtbl testinlineobjvtbl
= {
654 testinlineobj_AddRef
,
655 testinlineobj_Release
,
657 testinlineobj_GetMetrics
,
658 testinlineobj_GetOverhangMetrics
,
659 testinlineobj_GetBreakConditions
662 static IDWriteInlineObjectVtbl testinlineobjvtbl2
= {
664 testinlineobj_AddRef
,
665 testinlineobj_Release
,
667 testinlineobj_GetMetrics
,
668 testinlineobj_GetOverhangMetrics
,
669 testinlineobj2_GetBreakConditions
672 static IDWriteInlineObject testinlineobj
= { &testinlineobjvtbl
};
673 static IDWriteInlineObject testinlineobj2
= { &testinlineobjvtbl
};
674 static IDWriteInlineObject testinlineobj3
= { &testinlineobjvtbl2
};
676 static HRESULT WINAPI
testeffect_QI(IUnknown
*iface
, REFIID riid
, void **obj
)
678 if (IsEqualIID(riid
, &IID_IUnknown
)) {
680 IUnknown_AddRef(iface
);
685 return E_NOINTERFACE
;
688 static ULONG WINAPI
testeffect_AddRef(IUnknown
*iface
)
693 static ULONG WINAPI
testeffect_Release(IUnknown
*iface
)
698 static const IUnknownVtbl testeffectvtbl
= {
704 static IUnknown testeffect
= { &testeffectvtbl
};
706 static void test_CreateTextLayout(void)
708 static const WCHAR strW
[] = {'s','t','r','i','n','g',0};
709 IDWriteTextLayout2
*layout2
;
710 IDWriteTextLayout
*layout
;
711 IDWriteTextFormat
*format
;
712 IDWriteFactory
*factory
;
715 factory
= create_factory();
717 hr
= IDWriteFactory_CreateTextLayout(factory
, NULL
, 0, NULL
, 0.0, 0.0, &layout
);
718 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
720 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 6, NULL
, 0.0, 0.0, &layout
);
721 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
723 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 6, NULL
, 1.0, 0.0, &layout
);
724 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
726 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 6, NULL
, 0.0, 1.0, &layout
);
727 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
729 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 6, NULL
, 1000.0, 1000.0, &layout
);
730 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
732 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
733 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
734 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
736 EXPECT_REF(format
, 1);
737 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 6, format
, 1000.0, 1000.0, &layout
);
738 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
739 EXPECT_REF(format
, 1);
741 hr
= IDWriteTextLayout_QueryInterface(layout
, &IID_IDWriteTextLayout2
, (void**)&layout2
);
743 IDWriteTextLayout1
*layout1
;
744 IDWriteTextFormat1
*format1
;
745 IDWriteTextFormat
*format
;
747 hr
= IDWriteTextLayout2_QueryInterface(layout2
, &IID_IDWriteTextLayout1
, (void**)&layout1
);
748 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
749 IDWriteTextLayout1_Release(layout1
);
751 EXPECT_REF(layout2
, 2);
752 hr
= IDWriteTextLayout2_QueryInterface(layout2
, &IID_IDWriteTextFormat1
, (void**)&format1
);
753 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
754 EXPECT_REF(layout2
, 3);
756 hr
= IDWriteTextLayout2_QueryInterface(layout2
, &IID_IDWriteTextFormat
, (void**)&format
);
757 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
758 ok(format
== (IDWriteTextFormat
*)format1
, "got %p, %p\n", format
, format1
);
759 ok(format
!= (IDWriteTextFormat
*)layout2
, "got %p, %p\n", format
, layout2
);
760 EXPECT_REF(layout2
, 4);
762 hr
= IDWriteTextFormat_QueryInterface(format
, &IID_IDWriteTextLayout1
, (void**)&layout1
);
763 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
764 IDWriteTextLayout1_Release(layout1
);
766 IDWriteTextFormat1_Release(format1
);
767 IDWriteTextFormat_Release(format
);
769 hr
= IDWriteTextLayout_QueryInterface(layout
, &IID_IDWriteTextFormat1
, (void**)&format1
);
770 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
771 EXPECT_REF(layout2
, 3);
773 hr
= IDWriteTextLayout_QueryInterface(layout
, &IID_IDWriteTextFormat
, (void**)&format
);
774 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
775 ok(format
== (IDWriteTextFormat
*)format1
, "got %p, %p\n", format
, format1
);
776 EXPECT_REF(layout2
, 4);
778 IDWriteTextFormat1_Release(format1
);
779 IDWriteTextFormat_Release(format
);
780 IDWriteTextLayout2_Release(layout2
);
783 win_skip("IDWriteTextLayout2 is not supported.\n");
785 IDWriteTextLayout_Release(layout
);
786 IDWriteTextFormat_Release(format
);
787 IDWriteFactory_Release(factory
);
790 static DWRITE_MATRIX layoutcreate_transforms
[] = {
791 { 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 },
792 { 1.0, 0.0, 0.0, 1.0, 0.3, 0.2 },
793 { 1.0, 0.0, 0.0, 1.0,-0.3,-0.2 },
795 { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 },
796 { 1.0, 0.0, 0.0, 0.0, 0.0, 0.0 },
797 { 1.0, 2.0, 0.5, 1.0, 0.0, 0.0 },
800 static void test_CreateGdiCompatibleTextLayout(void)
802 static const WCHAR strW
[] = {'s','t','r','i','n','g',0};
803 IDWriteTextLayout
*layout
;
804 IDWriteTextFormat
*format
;
805 IDWriteFactory
*factory
;
810 factory
= create_factory();
812 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, NULL
, 0, NULL
, 0.0, 0.0, 0.0, NULL
, FALSE
, &layout
);
813 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
815 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, strW
, 6, NULL
, 0.0, 0.0, 0.0, NULL
, FALSE
, &layout
);
816 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
818 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, strW
, 6, NULL
, 1.0, 0.0, 0.0, NULL
, FALSE
, &layout
);
819 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
821 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, strW
, 6, NULL
, 1.0, 0.0, 1.0, NULL
, FALSE
, &layout
);
822 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
824 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, strW
, 6, NULL
, 1000.0, 1000.0, 1.0, NULL
, FALSE
, &layout
);
825 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
827 /* create with text format */
828 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
829 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
830 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
831 EXPECT_REF(format
, 1);
833 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, strW
, 6, format
, 100.0, 100.0, 1.0, NULL
, FALSE
, &layout
);
834 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
835 EXPECT_REF(format
, 1);
836 EXPECT_REF(layout
, 1);
838 IDWriteTextLayout_AddRef(layout
);
839 EXPECT_REF(format
, 1);
840 EXPECT_REF(layout
, 2);
841 IDWriteTextLayout_Release(layout
);
842 IDWriteTextLayout_Release(layout
);
844 /* zero length string is okay */
845 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, strW
, 0, format
, 100.0, 100.0, 1.0, NULL
, FALSE
, &layout
);
846 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
848 dimension
= IDWriteTextLayout_GetMaxWidth(layout
);
849 ok(dimension
== 100.0, "got %f\n", dimension
);
851 dimension
= IDWriteTextLayout_GetMaxHeight(layout
);
852 ok(dimension
== 100.0, "got %f\n", dimension
);
854 IDWriteTextLayout_Release(layout
);
856 /* negative, zero ppdip */
857 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, strW
, 1, format
, 100.0, 100.0, -1.0, NULL
, FALSE
, &layout
);
858 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
859 IDWriteTextLayout_Release(layout
);
861 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, strW
, 1, format
, 100.0, 100.0, 0.0, NULL
, FALSE
, &layout
);
862 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
863 IDWriteTextLayout_Release(layout
);
866 for (i
= 0; i
< sizeof(layoutcreate_transforms
)/sizeof(layoutcreate_transforms
[0]); i
++) {
867 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, strW
, 1, format
, 100.0, 100.0, 1.0,
868 &layoutcreate_transforms
[i
], FALSE
, &layout
);
869 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
870 IDWriteTextLayout_Release(layout
);
873 IDWriteTextFormat_Release(format
);
874 IDWriteFactory_Release(factory
);
877 static void test_CreateTextFormat(void)
879 IDWriteFontCollection
*collection
, *syscoll
;
880 DWRITE_PARAGRAPH_ALIGNMENT paralign
;
881 DWRITE_READING_DIRECTION readdir
;
882 DWRITE_WORD_WRAPPING wrapping
;
883 DWRITE_TEXT_ALIGNMENT align
;
884 DWRITE_FLOW_DIRECTION flow
;
885 DWRITE_LINE_SPACING_METHOD method
;
886 DWRITE_TRIMMING trimming
;
887 IDWriteTextFormat
*format
;
888 FLOAT spacing
, baseline
;
889 IDWriteInlineObject
*trimmingsign
;
890 IDWriteFactory
*factory
;
893 factory
= create_factory();
895 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
896 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
897 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
899 if (0) /* crashes on native */
900 hr
= IDWriteTextFormat_GetFontCollection(format
, NULL
);
903 hr
= IDWriteTextFormat_GetFontCollection(format
, &collection
);
904 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
905 ok(collection
!= NULL
, "got %p\n", collection
);
907 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &syscoll
, FALSE
);
908 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
909 ok(collection
== syscoll
, "got %p, was %p\n", syscoll
, collection
);
910 IDWriteFontCollection_Release(syscoll
);
911 IDWriteFontCollection_Release(collection
);
913 /* default format properties */
914 align
= IDWriteTextFormat_GetTextAlignment(format
);
915 ok(align
== DWRITE_TEXT_ALIGNMENT_LEADING
, "got %d\n", align
);
917 paralign
= IDWriteTextFormat_GetParagraphAlignment(format
);
918 ok(paralign
== DWRITE_PARAGRAPH_ALIGNMENT_NEAR
, "got %d\n", paralign
);
920 wrapping
= IDWriteTextFormat_GetWordWrapping(format
);
921 ok(wrapping
== DWRITE_WORD_WRAPPING_WRAP
, "got %d\n", wrapping
);
923 readdir
= IDWriteTextFormat_GetReadingDirection(format
);
924 ok(readdir
== DWRITE_READING_DIRECTION_LEFT_TO_RIGHT
, "got %d\n", readdir
);
926 flow
= IDWriteTextFormat_GetFlowDirection(format
);
927 ok(flow
== DWRITE_FLOW_DIRECTION_TOP_TO_BOTTOM
, "got %d\n", flow
);
929 hr
= IDWriteTextFormat_GetLineSpacing(format
, &method
, &spacing
, &baseline
);
930 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
931 ok(spacing
== 0.0, "got %f\n", spacing
);
932 ok(baseline
== 0.0, "got %f\n", baseline
);
933 ok(method
== DWRITE_LINE_SPACING_METHOD_DEFAULT
, "got %d\n", method
);
935 trimming
.granularity
= DWRITE_TRIMMING_GRANULARITY_WORD
;
936 trimming
.delimiter
= 10;
937 trimming
.delimiterCount
= 10;
938 trimmingsign
= (void*)0xdeadbeef;
939 hr
= IDWriteTextFormat_GetTrimming(format
, &trimming
, &trimmingsign
);
940 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
941 ok(trimming
.granularity
== DWRITE_TRIMMING_GRANULARITY_NONE
, "got %d\n", trimming
.granularity
);
942 ok(trimming
.delimiter
== 0, "got %d\n", trimming
.delimiter
);
943 ok(trimming
.delimiterCount
== 0, "got %d\n", trimming
.delimiterCount
);
944 ok(trimmingsign
== NULL
, "got %p\n", trimmingsign
);
947 hr
= IDWriteTextFormat_SetTextAlignment(format
, DWRITE_TEXT_ALIGNMENT_LEADING
);
948 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
950 hr
= IDWriteTextFormat_SetTextAlignment(format
, DWRITE_TEXT_ALIGNMENT_JUSTIFIED
+1);
951 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
953 hr
= IDWriteTextFormat_SetParagraphAlignment(format
, DWRITE_PARAGRAPH_ALIGNMENT_NEAR
);
954 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
956 hr
= IDWriteTextFormat_SetParagraphAlignment(format
, DWRITE_PARAGRAPH_ALIGNMENT_CENTER
+1);
957 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
959 hr
= IDWriteTextFormat_SetWordWrapping(format
, DWRITE_WORD_WRAPPING_WRAP
);
960 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
962 hr
= IDWriteTextFormat_SetWordWrapping(format
, DWRITE_WORD_WRAPPING_CHARACTER
+1);
963 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
965 hr
= IDWriteTextFormat_SetReadingDirection(format
, DWRITE_READING_DIRECTION_LEFT_TO_RIGHT
);
966 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
968 hr
= IDWriteTextFormat_SetFlowDirection(format
, DWRITE_FLOW_DIRECTION_TOP_TO_BOTTOM
);
969 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
971 hr
= IDWriteTextFormat_SetLineSpacing(format
, DWRITE_LINE_SPACING_METHOD_DEFAULT
, 0.0, 0.0);
972 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
974 hr
= IDWriteTextFormat_SetLineSpacing(format
, DWRITE_LINE_SPACING_METHOD_DEFAULT
, 0.0, -10.0);
975 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
977 hr
= IDWriteTextFormat_SetLineSpacing(format
, DWRITE_LINE_SPACING_METHOD_DEFAULT
, -10.0, 0.0);
978 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
980 hr
= IDWriteTextFormat_SetLineSpacing(format
, DWRITE_LINE_SPACING_METHOD_PROPORTIONAL
+1, 0.0, 0.0);
981 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
983 hr
= IDWriteTextFormat_SetTrimming(format
, &trimming
, NULL
);
984 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
986 IDWriteTextFormat_Release(format
);
987 IDWriteFactory_Release(factory
);
990 static void test_GetLocaleName(void)
992 static const WCHAR strW
[] = {'s','t','r','i','n','g',0};
993 static const WCHAR ruW
[] = {'r','u',0};
994 IDWriteTextLayout
*layout
;
995 IDWriteTextFormat
*format
, *format2
;
996 IDWriteFactory
*factory
;
1001 factory
= create_factory();
1003 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
1004 DWRITE_FONT_STRETCH_NORMAL
, 10.0, ruW
, &format
);
1005 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1007 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, strW
, 0, format
, 100.0, 100.0, 1.0, NULL
, FALSE
, &layout
);
1008 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1010 hr
= IDWriteTextLayout_QueryInterface(layout
, &IID_IDWriteTextFormat
, (void**)&format2
);
1011 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1013 len
= IDWriteTextFormat_GetLocaleNameLength(format2
);
1014 ok(len
== 2, "got %u\n", len
);
1015 len
= IDWriteTextFormat_GetLocaleNameLength(format
);
1016 ok(len
== 2, "got %u\n", len
);
1017 hr
= IDWriteTextFormat_GetLocaleName(format2
, buff
, len
);
1018 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
1019 hr
= IDWriteTextFormat_GetLocaleName(format2
, buff
, len
+1);
1020 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1021 ok(!lstrcmpW(buff
, ruW
), "got %s\n", wine_dbgstr_w(buff
));
1022 hr
= IDWriteTextFormat_GetLocaleName(format
, buff
, len
);
1023 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
1024 hr
= IDWriteTextFormat_GetLocaleName(format
, buff
, len
+1);
1025 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1026 ok(!lstrcmpW(buff
, ruW
), "got %s\n", wine_dbgstr_w(buff
));
1028 IDWriteTextLayout_Release(layout
);
1029 IDWriteTextFormat_Release(format
);
1030 IDWriteTextFormat_Release(format2
);
1031 IDWriteFactory_Release(factory
);
1034 static const struct drawcall_entry drawellipsis_seq
[] = {
1035 { DRAW_GLYPHRUN
, {0x2026, 0} },
1039 static void test_CreateEllipsisTrimmingSign(void)
1041 DWRITE_INLINE_OBJECT_METRICS metrics
;
1042 DWRITE_BREAK_CONDITION before
, after
;
1043 IDWriteTextFormat
*format
;
1044 IDWriteInlineObject
*sign
;
1045 IDWriteFactory
*factory
;
1049 factory
= create_factory();
1051 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
1052 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
1053 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1055 EXPECT_REF(format
, 1);
1056 hr
= IDWriteFactory_CreateEllipsisTrimmingSign(factory
, format
, &sign
);
1057 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1058 EXPECT_REF(format
, 1);
1060 hr
= IDWriteInlineObject_QueryInterface(sign
, &IID_IDWriteTextLayout
, (void**)&unk
);
1061 ok(hr
== E_NOINTERFACE
, "got 0x%08x\n", hr
);
1063 if (0) {/* crashes on native */
1064 hr
= IDWriteInlineObject_GetBreakConditions(sign
, NULL
, NULL
);
1065 hr
= IDWriteInlineObject_GetMetrics(sign
, NULL
);
1067 metrics
.width
= 0.0;
1068 metrics
.height
= 123.0;
1069 metrics
.baseline
= 123.0;
1070 metrics
.supportsSideways
= TRUE
;
1071 hr
= IDWriteInlineObject_GetMetrics(sign
, &metrics
);
1072 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1074 ok(metrics
.width
> 0.0, "got %.2f\n", metrics
.width
);
1075 ok(metrics
.height
== 0.0, "got %.2f\n", metrics
.height
);
1076 ok(metrics
.baseline
== 0.0, "got %.2f\n", metrics
.baseline
);
1077 ok(!metrics
.supportsSideways
, "got %d\n", metrics
.supportsSideways
);
1079 before
= after
= DWRITE_BREAK_CONDITION_CAN_BREAK
;
1080 hr
= IDWriteInlineObject_GetBreakConditions(sign
, &before
, &after
);
1081 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1082 ok(before
== DWRITE_BREAK_CONDITION_NEUTRAL
, "got %d\n", before
);
1083 ok(after
== DWRITE_BREAK_CONDITION_NEUTRAL
, "got %d\n", after
);
1086 flush_sequence(sequences
, RENDERER_ID
);
1087 hr
= IDWriteInlineObject_Draw(sign
, NULL
, &testrenderer
, 0.0, 0.0, FALSE
, FALSE
, NULL
);
1088 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1089 ok_sequence(sequences
, RENDERER_ID
, drawellipsis_seq
, "ellipsis sign draw test", FALSE
);
1090 IDWriteInlineObject_Release(sign
);
1092 /* non-orthogonal flow/reading combination */
1093 hr
= IDWriteTextFormat_SetReadingDirection(format
, DWRITE_READING_DIRECTION_LEFT_TO_RIGHT
);
1094 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1096 hr
= IDWriteTextFormat_SetFlowDirection(format
, DWRITE_FLOW_DIRECTION_LEFT_TO_RIGHT
);
1097 ok(hr
== S_OK
|| broken(hr
== E_INVALIDARG
) /* vista, win7 */, "got 0x%08x\n", hr
);
1099 hr
= IDWriteFactory_CreateEllipsisTrimmingSign(factory
, format
, &sign
);
1100 ok(hr
== DWRITE_E_FLOWDIRECTIONCONFLICTS
, "got 0x%08x\n", hr
);
1103 IDWriteTextFormat_Release(format
);
1104 IDWriteFactory_Release(factory
);
1107 static void test_fontweight(void)
1109 static const WCHAR strW
[] = {'s','t','r','i','n','g',0};
1110 static const WCHAR ruW
[] = {'r','u',0};
1111 IDWriteTextFormat
*format
, *fmt2
;
1112 IDWriteTextLayout
*layout
;
1113 DWRITE_FONT_WEIGHT weight
;
1114 DWRITE_TEXT_RANGE range
;
1115 IDWriteFactory
*factory
;
1119 factory
= create_factory();
1121 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_BOLD
, DWRITE_FONT_STYLE_NORMAL
,
1122 DWRITE_FONT_STRETCH_NORMAL
, 10.0, ruW
, &format
);
1123 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1125 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, strW
, 6, format
, 100.0, 100.0, 1.0, NULL
, FALSE
, &layout
);
1126 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1128 hr
= IDWriteTextLayout_QueryInterface(layout
, &IID_IDWriteTextFormat
, (void**)&fmt2
);
1129 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1131 weight
= IDWriteTextFormat_GetFontWeight(fmt2
);
1132 ok(weight
== DWRITE_FONT_WEIGHT_BOLD
, "got %u\n", weight
);
1134 range
.startPosition
= range
.length
= 0;
1135 hr
= IDWriteTextLayout_GetFontWeight(layout
, 0, &weight
, &range
);
1136 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1137 ok(range
.startPosition
== 0 && range
.length
== ~0u, "got %u, %u\n", range
.startPosition
, range
.length
);
1139 range
.startPosition
= 0;
1141 hr
= IDWriteTextLayout_SetFontWeight(layout
, DWRITE_FONT_WEIGHT_NORMAL
, range
);
1142 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1144 range
.startPosition
= range
.length
= 0;
1145 hr
= IDWriteTextLayout_GetFontWeight(layout
, 0, &weight
, &range
);
1146 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1147 ok(range
.startPosition
== 0 && range
.length
== 6, "got %u, %u\n", range
.startPosition
, range
.length
);
1149 /* IDWriteTextFormat methods output doesn't reflect layout changes */
1150 weight
= IDWriteTextFormat_GetFontWeight(fmt2
);
1151 ok(weight
== DWRITE_FONT_WEIGHT_BOLD
, "got %u\n", weight
);
1154 weight
= DWRITE_FONT_WEIGHT_BOLD
;
1155 hr
= IDWriteTextLayout_GetFontWeight(layout
, 0, &weight
, &range
);
1156 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1157 ok(weight
== DWRITE_FONT_WEIGHT_NORMAL
, "got %d\n", weight
);
1158 ok(range
.length
== 6, "got %d\n", range
.length
);
1160 size
= IDWriteTextLayout_GetMaxWidth(layout
);
1161 ok(size
== 100.0, "got %.2f\n", size
);
1163 hr
= IDWriteTextLayout_SetMaxWidth(layout
, 0.0);
1164 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1166 size
= IDWriteTextLayout_GetMaxWidth(layout
);
1167 ok(size
== 0.0, "got %.2f\n", size
);
1169 hr
= IDWriteTextLayout_SetMaxWidth(layout
, -1.0);
1170 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1172 size
= IDWriteTextLayout_GetMaxWidth(layout
);
1173 ok(size
== 0.0, "got %.2f\n", size
);
1175 hr
= IDWriteTextLayout_SetMaxWidth(layout
, 100.0);
1176 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1178 size
= IDWriteTextLayout_GetMaxWidth(layout
);
1179 ok(size
== 100.0, "got %.2f\n", size
);
1181 size
= IDWriteTextLayout_GetMaxHeight(layout
);
1182 ok(size
== 100.0, "got %.2f\n", size
);
1184 hr
= IDWriteTextLayout_SetMaxHeight(layout
, 0.0);
1185 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1187 size
= IDWriteTextLayout_GetMaxHeight(layout
);
1188 ok(size
== 0.0, "got %.2f\n", size
);
1190 hr
= IDWriteTextLayout_SetMaxHeight(layout
, -1.0);
1191 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1193 size
= IDWriteTextLayout_GetMaxHeight(layout
);
1194 ok(size
== 0.0, "got %.2f\n", size
);
1196 hr
= IDWriteTextLayout_SetMaxHeight(layout
, 100.0);
1197 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1199 size
= IDWriteTextLayout_GetMaxHeight(layout
);
1200 ok(size
== 100.0, "got %.2f\n", size
);
1202 IDWriteTextLayout_Release(layout
);
1203 IDWriteTextFormat_Release(fmt2
);
1204 IDWriteTextFormat_Release(format
);
1205 IDWriteFactory_Release(factory
);
1208 static void test_SetInlineObject(void)
1210 static const WCHAR strW
[] = {'s','t','r','i','n','g',0};
1211 static const WCHAR ruW
[] = {'r','u',0};
1213 IDWriteInlineObject
*inlineobj
, *inlineobj2
, *inlinetest
;
1214 IDWriteTextFormat
*format
;
1215 IDWriteTextLayout
*layout
;
1216 DWRITE_TEXT_RANGE range
, r2
;
1217 IDWriteFactory
*factory
;
1220 factory
= create_factory();
1222 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_BOLD
, DWRITE_FONT_STYLE_NORMAL
,
1223 DWRITE_FONT_STRETCH_NORMAL
, 10.0, ruW
, &format
);
1224 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1226 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, strW
, 6, format
, 100.0, 100.0, 1.0, NULL
, FALSE
, &layout
);
1227 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1229 hr
= IDWriteFactory_CreateEllipsisTrimmingSign(factory
, format
, &inlineobj
);
1230 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1232 hr
= IDWriteFactory_CreateEllipsisTrimmingSign(factory
, format
, &inlineobj2
);
1233 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1235 EXPECT_REF(inlineobj
, 1);
1236 EXPECT_REF(inlineobj2
, 1);
1238 inlinetest
= (void*)0x1;
1239 hr
= IDWriteTextLayout_GetInlineObject(layout
, 0, &inlinetest
, NULL
);
1240 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1241 ok(inlinetest
== NULL
, "got %p\n", inlinetest
);
1243 range
.startPosition
= 0;
1245 hr
= IDWriteTextLayout_SetInlineObject(layout
, inlineobj
, range
);
1246 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1248 EXPECT_REF(inlineobj
, 2);
1250 inlinetest
= (void*)0x1;
1251 hr
= IDWriteTextLayout_GetInlineObject(layout
, 2, &inlinetest
, NULL
);
1252 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1253 ok(inlinetest
== NULL
, "got %p\n", inlinetest
);
1256 r2
.startPosition
= r2
.length
= 100;
1257 hr
= IDWriteTextLayout_GetInlineObject(layout
, 0, &inlinetest
, &r2
);
1258 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1259 ok(inlinetest
== inlineobj
, "got %p\n", inlinetest
);
1260 ok(r2
.startPosition
== 0 && r2
.length
== 2, "got %d, %d\n", r2
.startPosition
, r2
.length
);
1261 IDWriteInlineObject_Release(inlinetest
);
1263 EXPECT_REF(inlineobj
, 2);
1265 /* get from somewhere inside a range */
1267 r2
.startPosition
= r2
.length
= 100;
1268 hr
= IDWriteTextLayout_GetInlineObject(layout
, 1, &inlinetest
, &r2
);
1269 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1270 ok(inlinetest
== inlineobj
, "got %p\n", inlinetest
);
1271 ok(r2
.startPosition
== 0 && r2
.length
== 2, "got %d, %d\n", r2
.startPosition
, r2
.length
);
1272 IDWriteInlineObject_Release(inlinetest
);
1274 EXPECT_REF(inlineobj
, 2);
1276 range
.startPosition
= 1;
1278 hr
= IDWriteTextLayout_SetInlineObject(layout
, inlineobj2
, range
);
1279 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1282 r2
.startPosition
= r2
.length
= 100;
1283 hr
= IDWriteTextLayout_GetInlineObject(layout
, 1, &inlinetest
, &r2
);
1284 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1285 ok(inlinetest
== inlineobj2
, "got %p\n", inlinetest
);
1286 ok(r2
.startPosition
== 1 && r2
.length
== 1, "got %d, %d\n", r2
.startPosition
, r2
.length
);
1287 IDWriteInlineObject_Release(inlinetest
);
1289 EXPECT_REF(inlineobj
, 2);
1290 EXPECT_REF(inlineobj2
, 2);
1293 r2
.startPosition
= r2
.length
= 100;
1294 hr
= IDWriteTextLayout_GetInlineObject(layout
, 0, &inlinetest
, &r2
);
1295 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1296 ok(inlinetest
== inlineobj
, "got %p\n", inlinetest
);
1297 ok(r2
.startPosition
== 0 && r2
.length
== 1, "got %d, %d\n", r2
.startPosition
, r2
.length
);
1298 IDWriteInlineObject_Release(inlinetest
);
1300 EXPECT_REF(inlineobj
, 2);
1302 range
.startPosition
= 1;
1304 hr
= IDWriteTextLayout_SetInlineObject(layout
, inlineobj
, range
);
1305 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1307 r2
.startPosition
= r2
.length
= 100;
1308 hr
= IDWriteTextLayout_GetInlineObject(layout
, 0, &inlinetest
, &r2
);
1309 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1310 ok(inlinetest
== inlineobj
, "got %p\n", inlinetest
);
1311 ok(r2
.startPosition
== 0 && r2
.length
== 2, "got %d, %d\n", r2
.startPosition
, r2
.length
);
1312 IDWriteInlineObject_Release(inlinetest
);
1314 EXPECT_REF(inlineobj
, 2);
1316 range
.startPosition
= 1;
1318 hr
= IDWriteTextLayout_SetInlineObject(layout
, inlineobj
, range
);
1319 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1321 EXPECT_REF(inlineobj
, 2);
1323 r2
.startPosition
= r2
.length
= 100;
1324 hr
= IDWriteTextLayout_GetInlineObject(layout
, 0, &inlinetest
, &r2
);
1325 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1326 ok(inlinetest
== inlineobj
, "got %p\n", inlinetest
);
1327 ok(r2
.startPosition
== 0 && r2
.length
== 3, "got %d, %d\n", r2
.startPosition
, r2
.length
);
1328 IDWriteInlineObject_Release(inlinetest
);
1330 EXPECT_REF(inlineobj
, 2);
1331 EXPECT_REF(inlineobj2
, 1);
1333 IDWriteTextLayout_Release(layout
);
1335 EXPECT_REF(inlineobj
, 1);
1337 IDWriteInlineObject_Release(inlineobj
);
1338 IDWriteInlineObject_Release(inlineobj2
);
1339 IDWriteTextFormat_Release(format
);
1340 IDWriteFactory_Release(factory
);
1343 /* drawing calls sequence doesn't depend on run order, instead all runs are
1344 drawn first, inline objects next and then underline/strikes */
1345 static const struct drawcall_entry draw_seq
[] = {
1346 { DRAW_GLYPHRUN
, {'s',0} },
1347 { DRAW_GLYPHRUN
, {'r','i',0} },
1348 { DRAW_GLYPHRUN
|DRAW_EFFECT
, {'n',0} },
1349 { DRAW_GLYPHRUN
, {'g',0} },
1352 { DRAW_STRIKETHROUGH
},
1356 static const struct drawcall_entry draw_seq2
[] = {
1357 { DRAW_GLYPHRUN
, {'s',0} },
1358 { DRAW_GLYPHRUN
, {'t',0} },
1359 { DRAW_GLYPHRUN
, {'r',0} },
1360 { DRAW_GLYPHRUN
, {'i',0} },
1361 { DRAW_GLYPHRUN
, {'n',0} },
1362 { DRAW_GLYPHRUN
, {'g',0} },
1366 static const struct drawcall_entry draw_seq3
[] = {
1368 { DRAW_GLYPHRUN
, {'a','b',0} },
1372 static const struct drawcall_entry draw_seq4
[] = {
1373 { DRAW_GLYPHRUN
, {'s','t','r',0} },
1374 { DRAW_GLYPHRUN
, {'i','n','g',0} },
1375 { DRAW_STRIKETHROUGH
},
1379 static const struct drawcall_entry draw_seq5
[] = {
1380 { DRAW_GLYPHRUN
, {'s','t',0} },
1381 { DRAW_GLYPHRUN
, {'r','i',0} },
1382 { DRAW_GLYPHRUN
, {'n','g',0} },
1383 { DRAW_STRIKETHROUGH
},
1387 static const struct drawcall_entry empty_seq
[] = {
1391 static const struct drawcall_entry draw_single_run_seq
[] = {
1392 { DRAW_GLYPHRUN
, {'s','t','r','i','n','g',0} },
1396 static void test_Draw(void)
1398 static const WCHAR strW
[] = {'s','t','r','i','n','g',0};
1399 static const WCHAR str2W
[] = {0x202a,0x202c,'a','b',0};
1400 static const WCHAR ruW
[] = {'r','u',0};
1401 IDWriteInlineObject
*inlineobj
;
1402 struct renderer_context ctxt
;
1403 IDWriteTextFormat
*format
;
1404 IDWriteTextLayout
*layout
;
1405 DWRITE_TEXT_RANGE range
;
1406 IDWriteFactory
*factory
;
1407 DWRITE_TEXT_METRICS tm
;
1411 factory
= create_factory();
1413 ctxt
.gdicompat
= FALSE
;
1414 ctxt
.use_gdi_natural
= FALSE
;
1415 ctxt
.snapping_disabled
= TRUE
;
1417 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_BOLD
, DWRITE_FONT_STYLE_NORMAL
,
1418 DWRITE_FONT_STRETCH_NORMAL
, 10.0, ruW
, &format
);
1419 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1421 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 6, format
, 100.0, 100.0, &layout
);
1422 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1424 hr
= IDWriteFactory_CreateEllipsisTrimmingSign(factory
, format
, &inlineobj
);
1425 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1427 range
.startPosition
= 5;
1429 hr
= IDWriteTextLayout_SetStrikethrough(layout
, TRUE
, range
);
1430 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1432 range
.startPosition
= 1;
1434 hr
= IDWriteTextLayout_SetInlineObject(layout
, inlineobj
, range
);
1435 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1437 range
.startPosition
= 4;
1439 hr
= IDWriteTextLayout_SetDrawingEffect(layout
, (IUnknown
*)inlineobj
, range
);
1440 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1442 range
.startPosition
= 0;
1444 hr
= IDWriteTextLayout_SetUnderline(layout
, TRUE
, range
);
1445 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1447 flush_sequence(sequences
, RENDERER_ID
);
1448 hr
= IDWriteTextLayout_Draw(layout
, &ctxt
, &testrenderer
, 0.0, 0.0);
1449 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1450 ok_sequence(sequences
, RENDERER_ID
, draw_seq
, "draw test", TRUE
);
1451 IDWriteTextLayout_Release(layout
);
1453 /* with reduced width DrawGlyphRun() is called for every line */
1454 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 6, format
, 5.0, 100.0, &layout
);
1455 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1456 flush_sequence(sequences
, RENDERER_ID
);
1457 hr
= IDWriteTextLayout_Draw(layout
, &ctxt
, &testrenderer
, 0.0, 0.0);
1458 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1459 ok_sequence(sequences
, RENDERER_ID
, draw_seq2
, "draw test 2", TRUE
);
1460 IDWriteTextLayout_Release(layout
);
1462 /* string with control characters */
1463 hr
= IDWriteFactory_CreateTextLayout(factory
, str2W
, 4, format
, 500.0, 100.0, &layout
);
1464 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1465 flush_sequence(sequences
, RENDERER_ID
);
1466 hr
= IDWriteTextLayout_Draw(layout
, &ctxt
, &testrenderer
, 0.0, 0.0);
1467 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1468 ok_sequence(sequences
, RENDERER_ID
, draw_seq3
, "draw test 3", TRUE
);
1469 IDWriteTextLayout_Release(layout
);
1471 /* strikethrough splits ranges from renderer point of view, but doesn't break
1473 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 6, format
, 500.0, 100.0, &layout
);
1474 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1475 flush_sequence(sequences
, RENDERER_ID
);
1477 range
.startPosition
= 0;
1479 hr
= IDWriteTextLayout_SetStrikethrough(layout
, TRUE
, range
);
1480 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1482 hr
= IDWriteTextLayout_Draw(layout
, &ctxt
, &testrenderer
, 0.0, 0.0);
1483 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1484 ok_sequence(sequences
, RENDERER_ID
, draw_seq4
, "draw test 4", FALSE
);
1485 IDWriteTextLayout_Release(layout
);
1487 /* strikethrough somewhere in the middle */
1488 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 6, format
, 500.0, 100.0, &layout
);
1489 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1490 flush_sequence(sequences
, RENDERER_ID
);
1492 range
.startPosition
= 2;
1494 hr
= IDWriteTextLayout_SetStrikethrough(layout
, TRUE
, range
);
1495 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1497 hr
= IDWriteTextLayout_Draw(layout
, &ctxt
, &testrenderer
, 0.0, 0.0);
1498 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1499 ok_sequence(sequences
, RENDERER_ID
, draw_seq5
, "draw test 5", FALSE
);
1500 IDWriteTextLayout_Release(layout
);
1503 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 0, format
, 500.0, 100.0, &layout
);
1504 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1506 flush_sequence(sequences
, RENDERER_ID
);
1507 hr
= IDWriteTextLayout_Draw(layout
, &ctxt
, &testrenderer
, 0.0, 0.0);
1508 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1509 ok_sequence(sequences
, RENDERER_ID
, empty_seq
, "draw test 6", FALSE
);
1510 IDWriteTextLayout_Release(layout
);
1512 ctxt
.gdicompat
= TRUE
;
1513 ctxt
.use_gdi_natural
= TRUE
;
1515 /* different parameter combinations with gdi-compatible layout */
1516 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, strW
, 6, format
, 100.0, 100.0, 1.0, NULL
, TRUE
, &layout
);
1517 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1518 flush_sequence(sequences
, RENDERER_ID
);
1519 hr
= IDWriteTextLayout_Draw(layout
, &ctxt
, &testrenderer
, 0.0, 0.0);
1520 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1521 ok_sequence(sequences
, RENDERER_ID
, draw_single_run_seq
, "draw test 7", FALSE
);
1523 /* text alignment keeps pixel-aligned origin */
1524 hr
= IDWriteTextLayout_GetMetrics(layout
, &tm
);
1525 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1526 ok(tm
.width
== floorf(tm
.width
), "got %f\n", tm
.width
);
1528 hr
= IDWriteTextLayout_SetMaxWidth(layout
, tm
.width
+ 3.0);
1529 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1530 hr
= IDWriteTextLayout_SetTextAlignment(layout
, DWRITE_TEXT_ALIGNMENT_CENTER
);
1531 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1533 ctxt
.originX
= ctxt
.originY
= 0.0;
1534 flush_sequence(sequences
, RENDERER_ID
);
1535 hr
= IDWriteTextLayout_Draw(layout
, &ctxt
, &testrenderer
, 0.0, 0.0);
1536 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1537 ok_sequence(sequences
, RENDERER_ID
, draw_single_run_seq
, "draw test 7", FALSE
);
1538 ok(ctxt
.originX
!= 0.0 && ctxt
.originX
== floorf(ctxt
.originX
), "got %f\n", ctxt
.originX
);
1540 IDWriteTextLayout_Release(layout
);
1542 ctxt
.gdicompat
= TRUE
;
1543 ctxt
.use_gdi_natural
= FALSE
;
1545 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, strW
, 6, format
, 100.0, 100.0, 1.0, NULL
, FALSE
, &layout
);
1546 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1547 flush_sequence(sequences
, RENDERER_ID
);
1548 hr
= IDWriteTextLayout_Draw(layout
, &ctxt
, &testrenderer
, 0.0, 0.0);
1549 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1550 ok_sequence(sequences
, RENDERER_ID
, draw_single_run_seq
, "draw test 8", FALSE
);
1551 IDWriteTextLayout_Release(layout
);
1553 ctxt
.gdicompat
= TRUE
;
1554 ctxt
.use_gdi_natural
= TRUE
;
1556 m
.m11
= m
.m22
= 2.0;
1557 m
.m12
= m
.m21
= m
.dx
= m
.dy
= 0.0;
1558 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, strW
, 6, format
, 100.0, 100.0, 1.0, &m
, TRUE
, &layout
);
1559 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1560 flush_sequence(sequences
, RENDERER_ID
);
1561 hr
= IDWriteTextLayout_Draw(layout
, &ctxt
, &testrenderer
, 0.0, 0.0);
1562 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1563 ok_sequence(sequences
, RENDERER_ID
, draw_single_run_seq
, "draw test 9", FALSE
);
1564 IDWriteTextLayout_Release(layout
);
1566 ctxt
.gdicompat
= TRUE
;
1567 ctxt
.use_gdi_natural
= FALSE
;
1569 m
.m11
= m
.m22
= 2.0;
1570 m
.m12
= m
.m21
= m
.dx
= m
.dy
= 0.0;
1571 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, strW
, 6, format
, 100.0, 100.0, 1.0, &m
, FALSE
, &layout
);
1572 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1573 flush_sequence(sequences
, RENDERER_ID
);
1574 hr
= IDWriteTextLayout_Draw(layout
, &ctxt
, &testrenderer
, 0.0, 0.0);
1575 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1576 ok_sequence(sequences
, RENDERER_ID
, draw_single_run_seq
, "draw test 10", FALSE
);
1577 IDWriteTextLayout_Release(layout
);
1579 IDWriteInlineObject_Release(inlineobj
);
1580 IDWriteTextFormat_Release(format
);
1581 IDWriteFactory_Release(factory
);
1584 static void test_typography(void)
1586 DWRITE_FONT_FEATURE feature
;
1587 IDWriteTypography
*typography
;
1588 IDWriteFactory
*factory
;
1592 factory
= create_factory();
1594 hr
= IDWriteFactory_CreateTypography(factory
, &typography
);
1595 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1597 feature
.nameTag
= DWRITE_FONT_FEATURE_TAG_KERNING
;
1598 feature
.parameter
= 1;
1599 hr
= IDWriteTypography_AddFontFeature(typography
, feature
);
1600 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1602 count
= IDWriteTypography_GetFontFeatureCount(typography
);
1603 ok(count
== 1, "got %u\n", count
);
1605 /* duplicated features work just fine */
1606 feature
.nameTag
= DWRITE_FONT_FEATURE_TAG_KERNING
;
1607 feature
.parameter
= 0;
1608 hr
= IDWriteTypography_AddFontFeature(typography
, feature
);
1609 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1611 count
= IDWriteTypography_GetFontFeatureCount(typography
);
1612 ok(count
== 2, "got %u\n", count
);
1614 memset(&feature
, 0xcc, sizeof(feature
));
1615 hr
= IDWriteTypography_GetFontFeature(typography
, 0, &feature
);
1616 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1617 ok(feature
.nameTag
== DWRITE_FONT_FEATURE_TAG_KERNING
, "got tag %x\n", feature
.nameTag
);
1618 ok(feature
.parameter
== 1, "got %u\n", feature
.parameter
);
1620 memset(&feature
, 0xcc, sizeof(feature
));
1621 hr
= IDWriteTypography_GetFontFeature(typography
, 1, &feature
);
1622 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1623 ok(feature
.nameTag
== DWRITE_FONT_FEATURE_TAG_KERNING
, "got tag %x\n", feature
.nameTag
);
1624 ok(feature
.parameter
== 0, "got %u\n", feature
.parameter
);
1626 hr
= IDWriteTypography_GetFontFeature(typography
, 2, &feature
);
1627 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1629 /* duplicated with same parameter value */
1630 feature
.nameTag
= DWRITE_FONT_FEATURE_TAG_KERNING
;
1631 feature
.parameter
= 0;
1632 hr
= IDWriteTypography_AddFontFeature(typography
, feature
);
1633 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1635 count
= IDWriteTypography_GetFontFeatureCount(typography
);
1636 ok(count
== 3, "got %u\n", count
);
1638 memset(&feature
, 0xcc, sizeof(feature
));
1639 hr
= IDWriteTypography_GetFontFeature(typography
, 2, &feature
);
1640 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1641 ok(feature
.nameTag
== DWRITE_FONT_FEATURE_TAG_KERNING
, "got tag %x\n", feature
.nameTag
);
1642 ok(feature
.parameter
== 0, "got %u\n", feature
.parameter
);
1644 IDWriteTypography_Release(typography
);
1645 IDWriteFactory_Release(factory
);
1648 static void test_GetClusterMetrics(void)
1650 static const WCHAR str5W
[] = {'a','\r','b','\n','c','\n','\r','d','\r','\n','e',0xb,'f',0xc,
1651 'g',0x0085,'h',0x2028,'i',0x2029,0};
1652 static const WCHAR str3W
[] = {0x2066,')',')',0x661,'(',0x627,')',0};
1653 static const WCHAR str2W
[] = {0x202a,0x202c,'a',0};
1654 static const WCHAR strW
[] = {'a','b','c','d',0};
1655 static const WCHAR str4W
[] = {'a',' ',0};
1656 DWRITE_INLINE_OBJECT_METRICS inline_metrics
;
1657 DWRITE_CLUSTER_METRICS metrics
[20];
1658 IDWriteTextLayout1
*layout1
;
1659 IDWriteInlineObject
*trimm
;
1660 IDWriteTextFormat
*format
;
1661 IDWriteTextLayout
*layout
;
1662 DWRITE_TEXT_RANGE range
;
1663 IDWriteFactory
*factory
;
1667 factory
= create_factory();
1669 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
1670 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
1671 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1673 hr
= IDWriteFactory_CreateTextLayout(factory
, str3W
, 7, format
, 1000.0, 1000.0, &layout
);
1674 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1675 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, NULL
, 0, &count
);
1676 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
1677 ok(count
== 7, "got %u\n", count
);
1678 IDWriteTextLayout_Release(layout
);
1680 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 1000.0, 1000.0, &layout
);
1681 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1684 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, NULL
, 0, &count
);
1685 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
1686 ok(count
== 4, "got %u\n", count
);
1688 /* check every cluster width */
1690 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, metrics
, sizeof(metrics
)/sizeof(metrics
[0]), &count
);
1691 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1692 ok(count
== 4, "got %u\n", count
);
1693 for (i
= 0; i
< count
; i
++) {
1694 ok(metrics
[i
].width
> 0.0, "%u: got width %.2f\n", i
, metrics
[i
].width
);
1695 ok(metrics
[i
].length
== 1, "%u: got length %u\n", i
, metrics
[i
].length
);
1698 /* apply spacing and check widths again */
1699 if (IDWriteTextLayout_QueryInterface(layout
, &IID_IDWriteTextLayout1
, (void**)&layout1
) == S_OK
) {
1700 DWRITE_CLUSTER_METRICS metrics2
[4];
1701 FLOAT leading
, trailing
, min_advance
;
1702 DWRITE_TEXT_RANGE r
;
1704 leading
= trailing
= min_advance
= 2.0;
1705 hr
= IDWriteTextLayout1_GetCharacterSpacing(layout1
, 500, &leading
, &trailing
,
1707 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1708 ok(leading
== 0.0 && trailing
== 0.0 && min_advance
== 0.0,
1709 "got %.2f, %.2f, %.2f\n", leading
, trailing
, min_advance
);
1710 ok(r
.startPosition
== 0 && r
.length
== ~0u, "got %u, %u\n", r
.startPosition
, r
.length
);
1712 leading
= trailing
= min_advance
= 2.0;
1713 hr
= IDWriteTextLayout1_GetCharacterSpacing(layout1
, 0, &leading
, &trailing
,
1714 &min_advance
, NULL
);
1715 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1716 ok(leading
== 0.0 && trailing
== 0.0 && min_advance
== 0.0,
1717 "got %.2f, %.2f, %.2f\n", leading
, trailing
, min_advance
);
1719 r
.startPosition
= 0;
1721 hr
= IDWriteTextLayout1_SetCharacterSpacing(layout1
, 10.0, 15.0, 0.0, r
);
1722 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1725 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, metrics2
, sizeof(metrics2
)/sizeof(metrics2
[0]), &count
);
1726 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1727 ok(count
== 4, "got %u\n", count
);
1728 for (i
= 0; i
< count
; i
++) {
1730 ok(metrics2
[i
].width
> metrics
[i
].width
, "%u: got width %.2f, was %.2f\n", i
, metrics2
[i
].width
,
1732 ok(metrics2
[i
].length
== 1, "%u: got length %u\n", i
, metrics2
[i
].length
);
1735 /* back to defaults */
1736 r
.startPosition
= 0;
1738 hr
= IDWriteTextLayout1_SetCharacterSpacing(layout1
, 0.0, 0.0, 0.0, r
);
1739 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1741 /* negative advance limit */
1742 r
.startPosition
= 0;
1744 hr
= IDWriteTextLayout1_SetCharacterSpacing(layout1
, 0.0, 0.0, -10.0, r
);
1745 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1747 IDWriteTextLayout1_Release(layout1
);
1750 win_skip("IDWriteTextLayout1 is not supported, cluster spacing test skipped.\n");
1752 hr
= IDWriteFactory_CreateEllipsisTrimmingSign(factory
, format
, &trimm
);
1753 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1755 range
.startPosition
= 0;
1757 hr
= IDWriteTextLayout_SetInlineObject(layout
, trimm
, range
);
1758 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1760 /* inline object takes a separate cluster, replaced codepoints number doesn't matter */
1762 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, NULL
, 0, &count
);
1763 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
1764 ok(count
== 3, "got %u\n", count
);
1767 memset(&metrics
, 0, sizeof(metrics
));
1768 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, metrics
, 1, &count
);
1769 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
1770 ok(count
== 3, "got %u\n", count
);
1771 ok(metrics
[0].length
== 2, "got %u\n", metrics
[0].length
);
1773 hr
= IDWriteInlineObject_GetMetrics(trimm
, &inline_metrics
);
1774 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1776 ok(inline_metrics
.width
> 0.0 && inline_metrics
.width
== metrics
[0].width
, "got %.2f, expected %.2f\n",
1777 inline_metrics
.width
, metrics
[0].width
);
1779 IDWriteTextLayout_Release(layout
);
1781 /* text with non-visual control codes */
1782 hr
= IDWriteFactory_CreateTextLayout(factory
, str2W
, 3, format
, 1000.0, 1000.0, &layout
);
1783 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1785 /* bidi control codes take a separate cluster */
1787 memset(metrics
, 0, sizeof(metrics
));
1788 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, metrics
, 3, &count
);
1789 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1790 ok(count
== 3, "got %u\n", count
);
1792 ok(metrics
[0].width
== 0.0, "got %.2f\n", metrics
[0].width
);
1793 ok(metrics
[0].length
== 1, "got %d\n", metrics
[0].length
);
1794 ok(metrics
[0].canWrapLineAfter
== 0, "got %d\n", metrics
[0].canWrapLineAfter
);
1795 ok(metrics
[0].isWhitespace
== 0, "got %d\n", metrics
[0].isWhitespace
);
1796 ok(metrics
[0].isNewline
== 0, "got %d\n", metrics
[0].isNewline
);
1797 ok(metrics
[0].isSoftHyphen
== 0, "got %d\n", metrics
[0].isSoftHyphen
);
1798 ok(metrics
[0].isRightToLeft
== 0, "got %d\n", metrics
[0].isRightToLeft
);
1800 ok(metrics
[1].width
== 0.0, "got %.2f\n", metrics
[1].width
);
1801 ok(metrics
[1].length
== 1, "got %d\n", metrics
[1].length
);
1802 ok(metrics
[1].canWrapLineAfter
== 0, "got %d\n", metrics
[1].canWrapLineAfter
);
1803 ok(metrics
[1].isWhitespace
== 0, "got %d\n", metrics
[1].isWhitespace
);
1804 ok(metrics
[1].isNewline
== 0, "got %d\n", metrics
[1].isNewline
);
1805 ok(metrics
[1].isSoftHyphen
== 0, "got %d\n", metrics
[1].isSoftHyphen
);
1806 ok(metrics
[1].isRightToLeft
== 0, "got %d\n", metrics
[1].isRightToLeft
);
1808 ok(metrics
[2].width
> 0.0, "got %.2f\n", metrics
[2].width
);
1809 ok(metrics
[2].length
== 1, "got %d\n", metrics
[2].length
);
1810 ok(metrics
[2].canWrapLineAfter
== 1, "got %d\n", metrics
[2].canWrapLineAfter
);
1811 ok(metrics
[2].isWhitespace
== 0, "got %d\n", metrics
[2].isWhitespace
);
1812 ok(metrics
[2].isNewline
== 0, "got %d\n", metrics
[2].isNewline
);
1813 ok(metrics
[2].isSoftHyphen
== 0, "got %d\n", metrics
[2].isSoftHyphen
);
1814 ok(metrics
[2].isRightToLeft
== 0, "got %d\n", metrics
[2].isRightToLeft
);
1816 IDWriteTextLayout_Release(layout
);
1818 /* single inline object that fails to report its metrics */
1819 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 1000.0, 1000.0, &layout
);
1820 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1822 range
.startPosition
= 0;
1824 hr
= IDWriteTextLayout_SetInlineObject(layout
, &testinlineobj
, range
);
1825 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1828 memset(metrics
, 0, sizeof(metrics
));
1829 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, metrics
, 3, &count
);
1830 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1831 ok(count
== 1, "got %u\n", count
);
1833 /* object sets a width to 123.0, but returns failure from GetMetrics() */
1834 ok(metrics
[0].width
== 0.0, "got %.2f\n", metrics
[0].width
);
1835 ok(metrics
[0].length
== 4, "got %d\n", metrics
[0].length
);
1836 ok(metrics
[0].canWrapLineAfter
== 1, "got %d\n", metrics
[0].canWrapLineAfter
);
1837 ok(metrics
[0].isWhitespace
== 0, "got %d\n", metrics
[0].isWhitespace
);
1838 ok(metrics
[0].isNewline
== 0, "got %d\n", metrics
[0].isNewline
);
1839 ok(metrics
[0].isSoftHyphen
== 0, "got %d\n", metrics
[0].isSoftHyphen
);
1840 ok(metrics
[0].isRightToLeft
== 0, "got %d\n", metrics
[0].isRightToLeft
);
1842 /* now set two inline object for [0,1] and [2,3], both fail to report break conditions */
1843 range
.startPosition
= 2;
1845 hr
= IDWriteTextLayout_SetInlineObject(layout
, &testinlineobj2
, range
);
1846 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1849 memset(metrics
, 0, sizeof(metrics
));
1850 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, metrics
, 3, &count
);
1851 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1852 ok(count
== 2, "got %u\n", count
);
1854 ok(metrics
[0].width
== 0.0, "got %.2f\n", metrics
[0].width
);
1855 ok(metrics
[0].length
== 2, "got %d\n", metrics
[0].length
);
1856 ok(metrics
[0].canWrapLineAfter
== 0, "got %d\n", metrics
[0].canWrapLineAfter
);
1857 ok(metrics
[0].isWhitespace
== 0, "got %d\n", metrics
[0].isWhitespace
);
1858 ok(metrics
[0].isNewline
== 0, "got %d\n", metrics
[0].isNewline
);
1859 ok(metrics
[0].isSoftHyphen
== 0, "got %d\n", metrics
[0].isSoftHyphen
);
1860 ok(metrics
[0].isRightToLeft
== 0, "got %d\n", metrics
[0].isRightToLeft
);
1862 ok(metrics
[1].width
== 0.0, "got %.2f\n", metrics
[1].width
);
1863 ok(metrics
[1].length
== 2, "got %d\n", metrics
[1].length
);
1864 ok(metrics
[1].canWrapLineAfter
== 1, "got %d\n", metrics
[1].canWrapLineAfter
);
1865 ok(metrics
[1].isWhitespace
== 0, "got %d\n", metrics
[1].isWhitespace
);
1866 ok(metrics
[1].isNewline
== 0, "got %d\n", metrics
[1].isNewline
);
1867 ok(metrics
[1].isSoftHyphen
== 0, "got %d\n", metrics
[1].isSoftHyphen
);
1868 ok(metrics
[1].isRightToLeft
== 0, "got %d\n", metrics
[1].isRightToLeft
);
1870 IDWriteTextLayout_Release(layout
);
1872 /* zero length string */
1873 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 0, format
, 1000.0, 1000.0, &layout
);
1874 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1877 memset(metrics
, 0, sizeof(metrics
));
1878 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, metrics
, 3, &count
);
1879 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1880 ok(count
== 0, "got %u\n", count
);
1881 IDWriteTextLayout_Release(layout
);
1884 hr
= IDWriteFactory_CreateTextLayout(factory
, str4W
, 2, format
, 1000.0, 1000.0, &layout
);
1885 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1888 memset(metrics
, 0, sizeof(metrics
));
1889 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, metrics
, 2, &count
);
1890 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1891 ok(count
== 2, "got %u\n", count
);
1892 ok(metrics
[0].isWhitespace
== 0, "got %d\n", metrics
[0].isWhitespace
);
1893 ok(metrics
[1].isWhitespace
== 1, "got %d\n", metrics
[1].isWhitespace
);
1894 ok(metrics
[1].canWrapLineAfter
== 1, "got %d\n", metrics
[1].canWrapLineAfter
);
1895 IDWriteTextLayout_Release(layout
);
1897 /* layout is fully covered by inline object with after condition DWRITE_BREAK_CONDITION_MAY_NOT_BREAK */
1898 hr
= IDWriteFactory_CreateTextLayout(factory
, str4W
, 2, format
, 1000.0, 1000.0, &layout
);
1899 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1901 range
.startPosition
= 0;
1903 hr
= IDWriteTextLayout_SetInlineObject(layout
, &testinlineobj3
, range
);
1904 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1907 memset(metrics
, 0, sizeof(metrics
));
1908 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, metrics
, 2, &count
);
1909 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1910 ok(count
== 1, "got %u\n", count
);
1911 ok(metrics
[0].canWrapLineAfter
== 1, "got %d\n", metrics
[0].canWrapLineAfter
);
1913 IDWriteTextLayout_Release(layout
);
1915 /* compare natural cluster width with gdi layout */
1916 hr
= IDWriteFactory_CreateTextLayout(factory
, str4W
, 1, format
, 100.0, 100.0, &layout
);
1917 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1920 memset(metrics
, 0, sizeof(metrics
));
1921 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, metrics
, 1, &count
);
1922 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1923 ok(count
== 1, "got %u\n", count
);
1924 ok(metrics
[0].width
!= floorf(metrics
[0].width
), "got %f\n", metrics
[0].width
);
1926 IDWriteTextLayout_Release(layout
);
1928 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, str4W
, 1, format
, 100.0, 100.0, 1.0, NULL
, FALSE
, &layout
);
1929 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1932 memset(metrics
, 0, sizeof(metrics
));
1933 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, metrics
, 1, &count
);
1934 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1935 ok(count
== 1, "got %u\n", count
);
1936 ok(metrics
[0].width
== floorf(metrics
[0].width
), "got %f\n", metrics
[0].width
);
1938 IDWriteTextLayout_Release(layout
);
1940 /* isNewline tests */
1941 hr
= IDWriteFactory_CreateTextLayout(factory
, str5W
, 20, format
, 100.0, 200.0, &layout
);
1942 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1945 memset(metrics
, 0, sizeof(metrics
));
1946 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, metrics
, 20, &count
);
1947 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1948 ok(count
== 20, "got %u\n", count
);
1951 ok(metrics
[1].isNewline
== 1, "got %d\n", metrics
[1].isNewline
);
1952 ok(metrics
[3].isNewline
== 1, "got %d\n", metrics
[3].isNewline
);
1953 ok(metrics
[5].isNewline
== 1, "got %d\n", metrics
[5].isNewline
);
1954 ok(metrics
[6].isNewline
== 1, "got %d\n", metrics
[6].isNewline
);
1955 ok(metrics
[9].isNewline
== 1, "got %d\n", metrics
[9].isNewline
);
1956 ok(metrics
[11].isNewline
== 1, "got %d\n", metrics
[11].isNewline
);
1957 ok(metrics
[13].isNewline
== 1, "got %d\n", metrics
[13].isNewline
);
1958 ok(metrics
[15].isNewline
== 1, "got %d\n", metrics
[15].isNewline
);
1959 ok(metrics
[17].isNewline
== 1, "got %d\n", metrics
[17].isNewline
);
1960 ok(metrics
[19].isNewline
== 1, "got %d\n", metrics
[19].isNewline
);
1962 ok(metrics
[0].isNewline
== 0, "got %d\n", metrics
[0].isNewline
);
1963 ok(metrics
[2].isNewline
== 0, "got %d\n", metrics
[2].isNewline
);
1964 ok(metrics
[4].isNewline
== 0, "got %d\n", metrics
[4].isNewline
);
1965 ok(metrics
[7].isNewline
== 0, "got %d\n", metrics
[7].isNewline
);
1966 ok(metrics
[8].isNewline
== 0, "got %d\n", metrics
[8].isNewline
);
1967 ok(metrics
[10].isNewline
== 0, "got %d\n", metrics
[10].isNewline
);
1968 ok(metrics
[12].isNewline
== 0, "got %d\n", metrics
[12].isNewline
);
1969 ok(metrics
[14].isNewline
== 0, "got %d\n", metrics
[14].isNewline
);
1970 ok(metrics
[16].isNewline
== 0, "got %d\n", metrics
[16].isNewline
);
1971 ok(metrics
[18].isNewline
== 0, "got %d\n", metrics
[18].isNewline
);
1973 for (i
= 0; i
< count
; i
++)
1974 ok(metrics
[i
].length
== 1, "%d: got %d\n", i
, metrics
[i
].length
);
1976 IDWriteTextLayout_Release(layout
);
1978 IDWriteInlineObject_Release(trimm
);
1979 IDWriteTextFormat_Release(format
);
1980 IDWriteFactory_Release(factory
);
1983 static void test_SetLocaleName(void)
1985 static const WCHAR eNuSW
[] = {'e','N','-','u','S',0};
1986 static const WCHAR strW
[] = {'a','b','c','d',0};
1987 WCHAR buffW
[LOCALE_NAME_MAX_LENGTH
+sizeof(strW
)/sizeof(WCHAR
)];
1988 IDWriteTextFormat
*format
;
1989 IDWriteTextLayout
*layout
;
1990 DWRITE_TEXT_RANGE range
;
1991 IDWriteFactory
*factory
;
1994 factory
= create_factory();
1996 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
1997 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
1998 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2000 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 1000.0, 1000.0, &layout
);
2001 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2003 range
.startPosition
= 0;
2005 hr
= IDWriteTextLayout_SetLocaleName(layout
, enusW
, range
);
2006 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2008 hr
= IDWriteTextLayout_SetLocaleName(layout
, NULL
, range
);
2009 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
2011 /* invalid locale name is allowed */
2012 hr
= IDWriteTextLayout_SetLocaleName(layout
, strW
, range
);
2013 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2015 hr
= IDWriteTextLayout_GetLocaleName(layout
, 0, NULL
, 0, NULL
);
2016 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
2018 if (0) /* crashes on native */
2019 hr
= IDWriteTextLayout_GetLocaleName(layout
, 0, NULL
, 1, NULL
);
2023 hr
= IDWriteTextLayout_GetLocaleName(layout
, 0, buffW
, sizeof(buffW
)/sizeof(WCHAR
), &range
);
2024 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2025 ok(!lstrcmpW(buffW
, strW
), "got %s\n", wine_dbgstr_w(buffW
));
2026 ok(range
.startPosition
== 0 && range
.length
== 1, "got %u,%u\n", range
.startPosition
, range
.length
);
2028 /* get with a shorter buffer */
2030 hr
= IDWriteTextLayout_GetLocaleName(layout
, 0, buffW
, 1, NULL
);
2031 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
2032 ok(buffW
[0] == 0, "got %x\n", buffW
[0]);
2034 /* name is too long */
2035 lstrcpyW(buffW
, strW
);
2036 while (lstrlenW(buffW
) <= LOCALE_NAME_MAX_LENGTH
)
2037 lstrcatW(buffW
, strW
);
2039 range
.startPosition
= 0;
2041 hr
= IDWriteTextLayout_SetLocaleName(layout
, buffW
, range
);
2042 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
2045 hr
= IDWriteTextLayout_GetLocaleName(layout
, 0, buffW
, sizeof(buffW
)/sizeof(WCHAR
), NULL
);
2046 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2047 ok(!lstrcmpW(buffW
, strW
), "got %s\n", wine_dbgstr_w(buffW
));
2049 /* set initial locale name for whole text, except with a different casing */
2050 range
.startPosition
= 0;
2052 hr
= IDWriteTextLayout_SetLocaleName(layout
, eNuSW
, range
);
2053 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2057 hr
= IDWriteTextLayout_GetLocaleName(layout
, 0, buffW
, sizeof(buffW
)/sizeof(WCHAR
), &range
);
2058 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2060 ok(!lstrcmpW(buffW
, enusW
), "got %s\n", wine_dbgstr_w(buffW
));
2061 ok((range
.startPosition
== 0 && range
.length
== ~0u) ||
2062 broken(range
.startPosition
== 0 && range
.length
== 4) /* vista/win7 */, "got %u,%u\n", range
.startPosition
, range
.length
);
2064 /* check what's returned for positions after the text */
2067 hr
= IDWriteTextLayout_GetLocaleName(layout
, 100, buffW
, sizeof(buffW
)/sizeof(WCHAR
), &range
);
2068 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2070 ok(!lstrcmpW(buffW
, enusW
), "got %s\n", wine_dbgstr_w(buffW
));
2071 ok((range
.startPosition
== 0 && range
.length
== ~0u) ||
2072 broken(range
.startPosition
== 4 && range
.length
== ~0u-4) /* vista/win7 */, "got %u,%u\n", range
.startPosition
, range
.length
);
2074 IDWriteTextLayout_Release(layout
);
2075 IDWriteTextFormat_Release(format
);
2076 IDWriteFactory_Release(factory
);
2079 static void test_SetPairKerning(void)
2081 static const WCHAR strW
[] = {'a','e',0x0300,'d',0}; /* accent grave */
2082 DWRITE_CLUSTER_METRICS clusters
[4];
2083 IDWriteTextLayout1
*layout1
;
2084 IDWriteTextFormat
*format
;
2085 IDWriteTextLayout
*layout
;
2086 DWRITE_TEXT_RANGE range
;
2087 IDWriteFactory
*factory
;
2092 factory
= create_factory();
2094 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
2095 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
2096 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2098 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 1000.0, 1000.0, &layout
);
2099 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2100 IDWriteTextFormat_Release(format
);
2102 hr
= IDWriteTextLayout_QueryInterface(layout
, &IID_IDWriteTextLayout1
, (void**)&layout1
);
2103 IDWriteTextLayout_Release(layout
);
2106 win_skip("SetPairKerning() is not supported.\n");
2107 IDWriteFactory_Release(factory
);
2111 if (0) { /* crashes on native */
2112 hr
= IDWriteTextLayout1_GetPairKerning(layout1
, 0, NULL
, NULL
);
2113 hr
= IDWriteTextLayout1_GetPairKerning(layout1
, 0, NULL
, &range
);
2116 hr
= IDWriteTextLayout1_GetPairKerning(layout1
, 0, &kerning
, NULL
);
2117 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2119 range
.startPosition
= 0;
2122 hr
= IDWriteTextLayout1_GetPairKerning(layout1
, 0, &kerning
, &range
);
2123 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2124 ok(!kerning
, "got %d\n", kerning
);
2125 ok(range
.length
== ~0u, "got %u\n", range
.length
);
2128 hr
= IDWriteTextLayout1_GetClusterMetrics(layout1
, clusters
, 4, &count
);
2129 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2131 ok(count
== 3, "got %u\n", count
);
2133 ok(clusters
[0].length
== 1, "got %u\n", clusters
[0].length
);
2134 ok(clusters
[1].length
== 2, "got %u\n", clusters
[1].length
);
2135 ok(clusters
[2].length
== 1, "got %u\n", clusters
[2].length
);
2137 /* pair kerning flag participates in itemization - combining characters
2139 range
.startPosition
= 0;
2141 hr
= IDWriteTextLayout1_SetPairKerning(layout1
, 2, range
);
2142 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2145 hr
= IDWriteTextLayout1_GetPairKerning(layout1
, 0, &kerning
, &range
);
2146 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2147 ok(kerning
== TRUE
, "got %d\n", kerning
);
2150 hr
= IDWriteTextLayout1_GetClusterMetrics(layout1
, clusters
, 4, &count
);
2151 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2152 ok(count
== 4, "got %u\n", count
);
2153 ok(clusters
[0].length
== 1, "got %u\n", clusters
[0].length
);
2154 ok(clusters
[1].length
== 1, "got %u\n", clusters
[1].length
);
2155 ok(clusters
[2].length
== 1, "got %u\n", clusters
[2].length
);
2156 ok(clusters
[3].length
== 1, "got %u\n", clusters
[3].length
);
2158 IDWriteTextLayout1_Release(layout1
);
2159 IDWriteFactory_Release(factory
);
2162 static void test_SetVerticalGlyphOrientation(void)
2164 static const WCHAR strW
[] = {'a','b','c','d',0};
2165 DWRITE_VERTICAL_GLYPH_ORIENTATION orientation
;
2166 IDWriteTextLayout2
*layout2
;
2167 IDWriteTextFormat
*format
;
2168 IDWriteTextLayout
*layout
;
2169 IDWriteFactory
*factory
;
2172 factory
= create_factory();
2174 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
2175 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
2176 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2178 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 1000.0, 1000.0, &layout
);
2179 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2180 IDWriteTextFormat_Release(format
);
2182 hr
= IDWriteTextLayout_QueryInterface(layout
, &IID_IDWriteTextLayout2
, (void**)&layout2
);
2183 IDWriteTextLayout_Release(layout
);
2186 win_skip("SetVerticalGlyphOrientation() is not supported.\n");
2187 IDWriteFactory_Release(factory
);
2191 orientation
= IDWriteTextLayout2_GetVerticalGlyphOrientation(layout2
);
2192 ok(orientation
== DWRITE_VERTICAL_GLYPH_ORIENTATION_DEFAULT
, "got %d\n", orientation
);
2194 hr
= IDWriteTextLayout2_SetVerticalGlyphOrientation(layout2
, DWRITE_VERTICAL_GLYPH_ORIENTATION_STACKED
+1);
2195 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
2197 IDWriteTextLayout2_Release(layout2
);
2198 IDWriteFactory_Release(factory
);
2201 static void test_fallback(void)
2203 static const WCHAR strW
[] = {'a','b','c','d',0};
2204 IDWriteFontFallback
*fallback
, *fallback2
;
2205 IDWriteTextLayout2
*layout2
;
2206 IDWriteTextFormat1
*format1
;
2207 IDWriteTextFormat
*format
;
2208 IDWriteTextLayout
*layout
;
2209 IDWriteFactory2
*factory2
;
2210 IDWriteFactory
*factory
;
2213 factory
= create_factory();
2215 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
2216 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
2217 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2219 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 1000.0, 1000.0, &layout
);
2220 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2221 IDWriteTextFormat_Release(format
);
2223 hr
= IDWriteTextLayout_QueryInterface(layout
, &IID_IDWriteTextLayout2
, (void**)&layout2
);
2224 IDWriteTextLayout_Release(layout
);
2227 win_skip("GetFontFallback() is not supported.\n");
2228 IDWriteFactory_Release(factory
);
2232 if (0) /* crashes on native */
2233 hr
= IDWriteTextLayout2_GetFontFallback(layout2
, NULL
);
2235 fallback
= (void*)0xdeadbeef;
2236 hr
= IDWriteTextLayout2_GetFontFallback(layout2
, &fallback
);
2237 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2238 ok(fallback
== NULL
, "got %p\n", fallback
);
2240 hr
= IDWriteTextLayout2_QueryInterface(layout2
, &IID_IDWriteTextFormat1
, (void**)&format1
);
2241 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2243 fallback
= (void*)0xdeadbeef;
2244 hr
= IDWriteTextFormat1_GetFontFallback(format1
, &fallback
);
2245 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2246 ok(fallback
== NULL
, "got %p\n", fallback
);
2248 hr
= IDWriteFactory_QueryInterface(factory
, &IID_IDWriteFactory2
, (void**)&factory2
);
2249 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2252 hr
= IDWriteFactory2_GetSystemFontFallback(factory2
, &fallback
);
2254 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2256 ok(fallback
!= NULL
, "got %p\n", fallback
);
2258 hr
= IDWriteTextFormat1_SetFontFallback(format1
, fallback
);
2259 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2261 fallback2
= (void*)0xdeadbeef;
2262 hr
= IDWriteTextLayout2_GetFontFallback(layout2
, &fallback2
);
2263 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2264 ok(fallback2
== fallback
, "got %p\n", fallback2
);
2266 hr
= IDWriteTextLayout2_SetFontFallback(layout2
, NULL
);
2267 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2269 fallback2
= (void*)0xdeadbeef;
2270 hr
= IDWriteTextFormat1_GetFontFallback(format1
, &fallback2
);
2271 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2272 ok(fallback2
== NULL
, "got %p\n", fallback2
);
2274 IDWriteFontFallback_Release(fallback
);
2276 IDWriteTextFormat1_Release(format1
);
2277 IDWriteTextLayout2_Release(layout2
);
2278 IDWriteFactory_Release(factory
);
2281 static void test_DetermineMinWidth(void)
2283 static const WCHAR strW
[] = {'a','b','c','d',0};
2284 IDWriteTextFormat
*format
;
2285 IDWriteTextLayout
*layout
;
2286 IDWriteFactory
*factory
;
2290 factory
= create_factory();
2292 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
2293 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
2294 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2296 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, lstrlenW(strW
), format
, 1000.0, 1000.0, &layout
);
2297 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2299 hr
= IDWriteTextLayout_DetermineMinWidth(layout
, NULL
);
2300 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
2303 hr
= IDWriteTextLayout_DetermineMinWidth(layout
, &minwidth
);
2304 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2305 ok(minwidth
> 0.0, "got %.2f\n", minwidth
);
2307 IDWriteTextLayout_Release(layout
);
2308 IDWriteTextFormat_Release(format
);
2309 IDWriteFactory_Release(factory
);
2312 static void test_SetFontSize(void)
2314 static const WCHAR strW
[] = {'a','b','c','d',0};
2315 IDWriteTextFormat
*format
;
2316 IDWriteTextLayout
*layout
;
2317 IDWriteFactory
*factory
;
2318 DWRITE_TEXT_RANGE r
;
2322 factory
= create_factory();
2324 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
2325 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
2326 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2328 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 1000.0, 1000.0, &layout
);
2329 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2331 /* negative/zero size */
2332 r
.startPosition
= 1;
2334 hr
= IDWriteTextLayout_SetFontSize(layout
, -15.0, r
);
2335 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
2337 hr
= IDWriteTextLayout_SetFontSize(layout
, 0.0, r
);
2338 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
2340 r
.startPosition
= 1;
2343 hr
= IDWriteTextLayout_GetFontSize(layout
, 0, &size
, &r
);
2344 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2345 ok(r
.startPosition
== 0 && r
.length
== ~0u, "got %u, %u\n", r
.startPosition
, r
.length
);
2346 ok(size
== 10.0, "got %.2f\n", size
);
2348 r
.startPosition
= 1;
2350 hr
= IDWriteTextLayout_SetFontSize(layout
, 15.0, r
);
2351 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2353 /* zero length range */
2354 r
.startPosition
= 1;
2356 hr
= IDWriteTextLayout_SetFontSize(layout
, 123.0, r
);
2357 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2360 hr
= IDWriteTextLayout_GetFontSize(layout
, 1, &size
, &r
);
2361 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2362 ok(size
== 15.0, "got %.2f\n", size
);
2364 r
.startPosition
= 0;
2366 hr
= IDWriteTextLayout_SetFontSize(layout
, 15.0, r
);
2367 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2370 hr
= IDWriteTextLayout_GetFontSize(layout
, 1, &size
, &r
);
2371 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2372 ok(size
== 15.0, "got %.2f\n", size
);
2375 hr
= IDWriteTextLayout_GetFontSize(layout
, 0, &size
, &r
);
2376 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2377 ok(r
.startPosition
== 0 && r
.length
== 4, "got %u, %u\n", r
.startPosition
, r
.length
);
2378 ok(size
== 15.0, "got %.2f\n", size
);
2381 r
.startPosition
= r
.length
= 0;
2382 hr
= IDWriteTextLayout_GetFontSize(layout
, 20, &size
, &r
);
2383 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2384 ok(r
.startPosition
== 4 && r
.length
== ~0u-4, "got %u, %u\n", r
.startPosition
, r
.length
);
2385 ok(size
== 10.0, "got %.2f\n", size
);
2387 r
.startPosition
= 100;
2389 hr
= IDWriteTextLayout_SetFontSize(layout
, 25.0, r
);
2390 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2393 r
.startPosition
= r
.length
= 0;
2394 hr
= IDWriteTextLayout_GetFontSize(layout
, 100, &size
, &r
);
2395 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2396 ok(r
.startPosition
== 100 && r
.length
== 4, "got %u, %u\n", r
.startPosition
, r
.length
);
2397 ok(size
== 25.0, "got %.2f\n", size
);
2399 IDWriteTextLayout_Release(layout
);
2400 IDWriteTextFormat_Release(format
);
2401 IDWriteFactory_Release(factory
);
2404 static void test_SetFontFamilyName(void)
2406 static const WCHAR taHomaW
[] = {'T','a','H','o','m','a',0};
2407 static const WCHAR arialW
[] = {'A','r','i','a','l',0};
2408 static const WCHAR strW
[] = {'a','b','c','d',0};
2409 IDWriteTextFormat
*format
;
2410 IDWriteTextLayout
*layout
;
2411 IDWriteFactory
*factory
;
2412 DWRITE_TEXT_RANGE r
;
2416 factory
= create_factory();
2418 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
2419 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
2420 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2422 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 1000.0, 1000.0, &layout
);
2423 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2426 r
.startPosition
= 1;
2428 hr
= IDWriteTextLayout_SetFontFamilyName(layout
, NULL
, r
);
2429 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
2431 r
.startPosition
= 1;
2434 hr
= IDWriteTextLayout_GetFontFamilyName(layout
, 1, nameW
, sizeof(nameW
)/sizeof(WCHAR
), &r
);
2435 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2436 ok(r
.startPosition
== 0 && r
.length
== ~0u, "got %u, %u\n", r
.startPosition
, r
.length
);
2438 /* set name only different in casing */
2439 r
.startPosition
= 1;
2441 hr
= IDWriteTextLayout_SetFontFamilyName(layout
, taHomaW
, r
);
2442 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2444 /* zero length range */
2445 r
.startPosition
= 1;
2447 hr
= IDWriteTextLayout_SetFontFamilyName(layout
, arialW
, r
);
2448 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2450 r
.startPosition
= 0;
2453 hr
= IDWriteTextLayout_GetFontFamilyName(layout
, 1, nameW
, sizeof(nameW
)/sizeof(WCHAR
), &r
);
2454 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2455 ok(!lstrcmpW(nameW
, taHomaW
), "got %s\n", wine_dbgstr_w(nameW
));
2456 ok(r
.startPosition
== 1 && r
.length
== 1, "got %u, %u\n", r
.startPosition
, r
.length
);
2458 r
.startPosition
= 1;
2460 hr
= IDWriteTextLayout_SetFontFamilyName(layout
, arialW
, r
);
2461 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2463 r
.startPosition
= 1;
2465 hr
= IDWriteTextLayout_GetFontFamilyName(layout
, 1, nameW
, sizeof(nameW
)/sizeof(WCHAR
), &r
);
2466 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2467 ok(r
.startPosition
== 1 && r
.length
== 1, "got %u, %u\n", r
.startPosition
, r
.length
);
2469 r
.startPosition
= 0;
2471 hr
= IDWriteTextLayout_SetFontFamilyName(layout
, arialW
, r
);
2472 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2475 hr
= IDWriteTextLayout_GetFontFamilyName(layout
, 1, nameW
, sizeof(nameW
)/sizeof(WCHAR
), &r
);
2476 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2477 ok(r
.startPosition
== 0 && r
.length
== 4, "got %u, %u\n", r
.startPosition
, r
.length
);
2478 ok(!lstrcmpW(nameW
, arialW
), "got name %s\n", wine_dbgstr_w(nameW
));
2480 IDWriteTextLayout_Release(layout
);
2481 IDWriteTextFormat_Release(format
);
2482 IDWriteFactory_Release(factory
);
2485 static void test_SetFontStyle(void)
2487 static const WCHAR strW
[] = {'a','b','c','d',0};
2488 IDWriteTextFormat
*format
;
2489 IDWriteTextLayout
*layout
;
2490 IDWriteFactory
*factory
;
2491 DWRITE_FONT_STYLE style
;
2492 DWRITE_TEXT_RANGE r
;
2495 factory
= create_factory();
2497 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
2498 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
2499 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2501 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 1000.0, 1000.0, &layout
);
2502 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2504 /* invalid style value */
2505 r
.startPosition
= 1;
2507 hr
= IDWriteTextLayout_SetFontStyle(layout
, DWRITE_FONT_STYLE_ITALIC
+1, r
);
2508 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
2510 r
.startPosition
= 1;
2512 hr
= IDWriteTextLayout_GetFontStyle(layout
, 0, &style
, &r
);
2513 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2514 ok(r
.startPosition
== 0 && r
.length
== ~0u, "got %u, %u\n", r
.startPosition
, r
.length
);
2515 ok(style
== DWRITE_FONT_STYLE_NORMAL
, "got %d\n", style
);
2517 r
.startPosition
= 1;
2519 hr
= IDWriteTextLayout_SetFontStyle(layout
, DWRITE_FONT_STYLE_ITALIC
, r
);
2520 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2522 /* zero length range */
2523 r
.startPosition
= 1;
2525 hr
= IDWriteTextLayout_SetFontStyle(layout
, DWRITE_FONT_STYLE_NORMAL
, r
);
2526 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2528 style
= DWRITE_FONT_STYLE_NORMAL
;
2529 hr
= IDWriteTextLayout_GetFontStyle(layout
, 1, &style
, &r
);
2530 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2531 ok(style
== DWRITE_FONT_STYLE_ITALIC
, "got %d\n", style
);
2533 r
.startPosition
= 0;
2535 hr
= IDWriteTextLayout_SetFontStyle(layout
, DWRITE_FONT_STYLE_OBLIQUE
, r
);
2536 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2538 style
= DWRITE_FONT_STYLE_ITALIC
;
2539 hr
= IDWriteTextLayout_GetFontStyle(layout
, 1, &style
, &r
);
2540 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2541 ok(style
== DWRITE_FONT_STYLE_OBLIQUE
, "got %d\n", style
);
2543 style
= DWRITE_FONT_STYLE_ITALIC
;
2544 hr
= IDWriteTextLayout_GetFontStyle(layout
, 0, &style
, &r
);
2545 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2546 ok(r
.startPosition
== 0 && r
.length
== 4, "got %u, %u\n", r
.startPosition
, r
.length
);
2547 ok(style
== DWRITE_FONT_STYLE_OBLIQUE
, "got %d\n", style
);
2549 style
= DWRITE_FONT_STYLE_ITALIC
;
2550 r
.startPosition
= r
.length
= 0;
2551 hr
= IDWriteTextLayout_GetFontStyle(layout
, 20, &style
, &r
);
2552 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2553 ok(r
.startPosition
== 4 && r
.length
== ~0u-4, "got %u, %u\n", r
.startPosition
, r
.length
);
2554 ok(style
== DWRITE_FONT_STYLE_NORMAL
, "got %d\n", style
);
2556 r
.startPosition
= 100;
2558 hr
= IDWriteTextLayout_SetFontStyle(layout
, DWRITE_FONT_STYLE_OBLIQUE
, r
);
2559 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2561 style
= DWRITE_FONT_STYLE_NORMAL
;
2562 r
.startPosition
= r
.length
= 0;
2563 hr
= IDWriteTextLayout_GetFontStyle(layout
, 100, &style
, &r
);
2564 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2565 ok(r
.startPosition
== 100 && r
.length
== 4, "got %u, %u\n", r
.startPosition
, r
.length
);
2566 ok(style
== DWRITE_FONT_STYLE_OBLIQUE
, "got %d\n", style
);
2568 IDWriteTextLayout_Release(layout
);
2569 IDWriteTextFormat_Release(format
);
2570 IDWriteFactory_Release(factory
);
2573 static void test_SetFontStretch(void)
2575 static const WCHAR strW
[] = {'a','b','c','d',0};
2576 DWRITE_FONT_STRETCH stretch
;
2577 IDWriteTextFormat
*format
;
2578 IDWriteTextLayout
*layout
;
2579 IDWriteFactory
*factory
;
2580 DWRITE_TEXT_RANGE r
;
2583 factory
= create_factory();
2585 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
2586 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
2587 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2589 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 1000.0, 1000.0, &layout
);
2590 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2592 /* invalid stretch value */
2593 r
.startPosition
= 1;
2595 hr
= IDWriteTextLayout_SetFontStretch(layout
, DWRITE_FONT_STRETCH_ULTRA_EXPANDED
+1, r
);
2596 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
2598 r
.startPosition
= 1;
2600 stretch
= DWRITE_FONT_STRETCH_UNDEFINED
;
2601 hr
= IDWriteTextLayout_GetFontStretch(layout
, 0, &stretch
, &r
);
2602 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2603 ok(r
.startPosition
== 0 && r
.length
== ~0u, "got %u, %u\n", r
.startPosition
, r
.length
);
2604 ok(stretch
== DWRITE_FONT_STRETCH_NORMAL
, "got %d\n", stretch
);
2606 r
.startPosition
= 1;
2608 hr
= IDWriteTextLayout_SetFontStretch(layout
, DWRITE_FONT_STRETCH_CONDENSED
, r
);
2609 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2611 /* zero length range */
2612 r
.startPosition
= 1;
2614 hr
= IDWriteTextLayout_SetFontStretch(layout
, DWRITE_FONT_STRETCH_NORMAL
, r
);
2615 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2617 stretch
= DWRITE_FONT_STRETCH_UNDEFINED
;
2618 hr
= IDWriteTextLayout_GetFontStretch(layout
, 1, &stretch
, &r
);
2619 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2620 ok(stretch
== DWRITE_FONT_STRETCH_CONDENSED
, "got %d\n", stretch
);
2622 r
.startPosition
= 0;
2624 hr
= IDWriteTextLayout_SetFontStretch(layout
, DWRITE_FONT_STRETCH_EXPANDED
, r
);
2625 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2627 stretch
= DWRITE_FONT_STRETCH_UNDEFINED
;
2628 hr
= IDWriteTextLayout_GetFontStretch(layout
, 1, &stretch
, &r
);
2629 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2630 ok(stretch
== DWRITE_FONT_STRETCH_EXPANDED
, "got %d\n", stretch
);
2632 stretch
= DWRITE_FONT_STRETCH_UNDEFINED
;
2633 hr
= IDWriteTextLayout_GetFontStretch(layout
, 0, &stretch
, &r
);
2634 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2635 ok(r
.startPosition
== 0 && r
.length
== 4, "got %u, %u\n", r
.startPosition
, r
.length
);
2636 ok(stretch
== DWRITE_FONT_STRETCH_EXPANDED
, "got %d\n", stretch
);
2638 stretch
= DWRITE_FONT_STRETCH_UNDEFINED
;
2639 r
.startPosition
= r
.length
= 0;
2640 hr
= IDWriteTextLayout_GetFontStretch(layout
, 20, &stretch
, &r
);
2641 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2642 ok(r
.startPosition
== 4 && r
.length
== ~0u-4, "got %u, %u\n", r
.startPosition
, r
.length
);
2643 ok(stretch
== DWRITE_FONT_STRETCH_NORMAL
, "got %d\n", stretch
);
2645 r
.startPosition
= 100;
2647 hr
= IDWriteTextLayout_SetFontStretch(layout
, DWRITE_FONT_STRETCH_EXPANDED
, r
);
2648 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2650 stretch
= DWRITE_FONT_STRETCH_UNDEFINED
;
2651 r
.startPosition
= r
.length
= 0;
2652 hr
= IDWriteTextLayout_GetFontStretch(layout
, 100, &stretch
, &r
);
2653 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2654 ok(r
.startPosition
== 100 && r
.length
== 4, "got %u, %u\n", r
.startPosition
, r
.length
);
2655 ok(stretch
== DWRITE_FONT_STRETCH_EXPANDED
, "got %d\n", stretch
);
2657 /* trying to set undefined value */
2658 r
.startPosition
= 0;
2660 hr
= IDWriteTextLayout_SetFontStretch(layout
, DWRITE_FONT_STRETCH_UNDEFINED
, r
);
2661 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
2663 IDWriteTextLayout_Release(layout
);
2664 IDWriteTextFormat_Release(format
);
2665 IDWriteFactory_Release(factory
);
2668 static void test_SetStrikethrough(void)
2670 static const WCHAR strW
[] = {'a','b','c','d',0};
2671 IDWriteTextFormat
*format
;
2672 IDWriteTextLayout
*layout
;
2673 IDWriteFactory
*factory
;
2674 DWRITE_TEXT_RANGE r
;
2678 factory
= create_factory();
2680 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
2681 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
2682 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2684 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 1000.0, 1000.0, &layout
);
2685 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2687 r
.startPosition
= 1;
2690 hr
= IDWriteTextLayout_GetStrikethrough(layout
, 0, &value
, &r
);
2691 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2692 ok(r
.startPosition
== 0 && r
.length
== ~0u, "got %u, %u\n", r
.startPosition
, r
.length
);
2693 ok(value
== FALSE
, "got %d\n", value
);
2695 r
.startPosition
= 1;
2697 hr
= IDWriteTextLayout_SetStrikethrough(layout
, TRUE
, r
);
2698 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2701 hr
= IDWriteTextLayout_GetStrikethrough(layout
, 1, &value
, &r
);
2702 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2703 ok(value
== TRUE
, "got %d\n", value
);
2704 ok(r
.startPosition
== 1 && r
.length
== 1, "got %u, %u\n", r
.startPosition
, r
.length
);
2707 r
.startPosition
= r
.length
= 0;
2708 hr
= IDWriteTextLayout_GetStrikethrough(layout
, 20, &value
, &r
);
2709 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2710 ok(r
.startPosition
== 2 && r
.length
== ~0u-2, "got %u, %u\n", r
.startPosition
, r
.length
);
2711 ok(value
== FALSE
, "got %d\n", value
);
2713 r
.startPosition
= 100;
2715 hr
= IDWriteTextLayout_SetStrikethrough(layout
, TRUE
, r
);
2716 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2719 r
.startPosition
= r
.length
= 0;
2720 hr
= IDWriteTextLayout_GetStrikethrough(layout
, 100, &value
, &r
);
2721 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2722 ok(r
.startPosition
== 100 && r
.length
== 4, "got %u, %u\n", r
.startPosition
, r
.length
);
2723 ok(value
== TRUE
, "got %d\n", value
);
2725 IDWriteTextLayout_Release(layout
);
2726 IDWriteTextFormat_Release(format
);
2727 IDWriteFactory_Release(factory
);
2730 static void test_GetMetrics(void)
2732 static const WCHAR str2W
[] = {0x2066,')',')',0x661,'(',0x627,')',0};
2733 static const WCHAR strW
[] = {'a','b','c','d',0};
2734 static const WCHAR str3W
[] = {'a',0};
2735 DWRITE_CLUSTER_METRICS clusters
[4];
2736 DWRITE_TEXT_METRICS metrics
;
2737 IDWriteTextFormat
*format
;
2738 IDWriteTextLayout
*layout
;
2739 IDWriteFactory
*factory
;
2744 factory
= create_factory();
2746 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
2747 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
2748 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2750 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 500.0, 1000.0, &layout
);
2751 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2754 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, clusters
, 4, &count
);
2755 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2756 ok(count
== 4, "got %u\n", count
);
2757 for (i
= 0, width
= 0.0; i
< count
; i
++)
2758 width
+= clusters
[i
].width
;
2760 memset(&metrics
, 0xcc, sizeof(metrics
));
2761 hr
= IDWriteTextLayout_GetMetrics(layout
, &metrics
);
2762 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2763 ok(metrics
.left
== 0.0, "got %.2f\n", metrics
.left
);
2764 ok(metrics
.top
== 0.0, "got %.2f\n", metrics
.top
);
2765 ok(metrics
.width
== width
, "got %.2f, expected %.2f\n", metrics
.width
, width
);
2766 ok(metrics
.widthIncludingTrailingWhitespace
== width
, "got %.2f, expected %.2f\n",
2767 metrics
.widthIncludingTrailingWhitespace
, width
);
2768 ok(metrics
.height
> 0.0, "got %.2f\n", metrics
.height
);
2769 ok(metrics
.layoutWidth
== 500.0, "got %.2f\n", metrics
.layoutWidth
);
2770 ok(metrics
.layoutHeight
== 1000.0, "got %.2f\n", metrics
.layoutHeight
);
2771 ok(metrics
.maxBidiReorderingDepth
== 1, "got %u\n", metrics
.maxBidiReorderingDepth
);
2772 ok(metrics
.lineCount
== 1, "got %u\n", metrics
.lineCount
);
2774 IDWriteTextLayout_Release(layout
);
2776 /* a string with more complex bidi sequence */
2777 hr
= IDWriteFactory_CreateTextLayout(factory
, str2W
, 7, format
, 500.0, 1000.0, &layout
);
2778 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2780 memset(&metrics
, 0xcc, sizeof(metrics
));
2781 metrics
.maxBidiReorderingDepth
= 0;
2782 hr
= IDWriteTextLayout_GetMetrics(layout
, &metrics
);
2783 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2784 ok(metrics
.left
== 0.0, "got %.2f\n", metrics
.left
);
2785 ok(metrics
.top
== 0.0, "got %.2f\n", metrics
.top
);
2786 ok(metrics
.width
> 0.0, "got %.2f\n", metrics
.width
);
2787 ok(metrics
.widthIncludingTrailingWhitespace
> 0.0, "got %.2f\n", metrics
.widthIncludingTrailingWhitespace
);
2788 ok(metrics
.height
> 0.0, "got %.2f\n", metrics
.height
);
2789 ok(metrics
.layoutWidth
== 500.0, "got %.2f\n", metrics
.layoutWidth
);
2790 ok(metrics
.layoutHeight
== 1000.0, "got %.2f\n", metrics
.layoutHeight
);
2792 ok(metrics
.maxBidiReorderingDepth
> 1, "got %u\n", metrics
.maxBidiReorderingDepth
);
2793 ok(metrics
.lineCount
== 1, "got %u\n", metrics
.lineCount
);
2795 IDWriteTextLayout_Release(layout
);
2797 /* single cluster layout */
2798 hr
= IDWriteFactory_CreateTextLayout(factory
, str3W
, 1, format
, 500.0, 1000.0, &layout
);
2799 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2802 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, clusters
, 1, &count
);
2803 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2804 ok(count
== 1, "got %u\n", count
);
2806 memset(&metrics
, 0xcc, sizeof(metrics
));
2807 hr
= IDWriteTextLayout_GetMetrics(layout
, &metrics
);
2808 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2809 ok(metrics
.left
== 0.0, "got %.2f\n", metrics
.left
);
2810 ok(metrics
.top
== 0.0, "got %.2f\n", metrics
.top
);
2811 ok(metrics
.width
== clusters
[0].width
, "got %.2f, expected %.2f\n", metrics
.width
, clusters
[0].width
);
2812 ok(metrics
.widthIncludingTrailingWhitespace
== clusters
[0].width
, "got %.2f\n", metrics
.widthIncludingTrailingWhitespace
);
2813 ok(metrics
.height
> 0.0, "got %.2f\n", metrics
.height
);
2814 ok(metrics
.layoutWidth
== 500.0, "got %.2f\n", metrics
.layoutWidth
);
2815 ok(metrics
.layoutHeight
== 1000.0, "got %.2f\n", metrics
.layoutHeight
);
2816 ok(metrics
.maxBidiReorderingDepth
== 1, "got %u\n", metrics
.maxBidiReorderingDepth
);
2817 ok(metrics
.lineCount
== 1, "got %u\n", metrics
.lineCount
);
2818 IDWriteTextLayout_Release(layout
);
2820 IDWriteTextFormat_Release(format
);
2821 IDWriteFactory_Release(factory
);
2824 static void test_SetFlowDirection(void)
2826 static const WCHAR strW
[] = {'a','b','c','d',0};
2827 DWRITE_READING_DIRECTION reading
;
2828 DWRITE_FLOW_DIRECTION flow
;
2829 IDWriteTextFormat
*format
;
2830 IDWriteTextLayout
*layout
;
2831 IDWriteFactory
*factory
;
2834 factory
= create_factory();
2836 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
2837 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
2838 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2840 flow
= IDWriteTextFormat_GetFlowDirection(format
);
2841 ok(flow
== DWRITE_FLOW_DIRECTION_TOP_TO_BOTTOM
, "got %d\n", flow
);
2843 reading
= IDWriteTextFormat_GetReadingDirection(format
);
2844 ok(reading
== DWRITE_READING_DIRECTION_LEFT_TO_RIGHT
, "got %d\n", reading
);
2846 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 500.0, 1000.0, &layout
);
2847 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2848 IDWriteTextLayout_Release(layout
);
2850 hr
= IDWriteTextFormat_SetFlowDirection(format
, DWRITE_FLOW_DIRECTION_LEFT_TO_RIGHT
);
2851 ok(hr
== S_OK
|| broken(hr
== E_INVALIDARG
) /* vista,win7 */, "got 0x%08x\n", hr
);
2853 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 500.0, 1000.0, &layout
);
2854 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2855 IDWriteTextLayout_Release(layout
);
2857 hr
= IDWriteTextFormat_SetReadingDirection(format
, DWRITE_READING_DIRECTION_TOP_TO_BOTTOM
);
2858 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2860 hr
= IDWriteTextFormat_SetFlowDirection(format
, DWRITE_FLOW_DIRECTION_TOP_TO_BOTTOM
);
2861 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2863 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 500.0, 1000.0, &layout
);
2864 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2865 IDWriteTextLayout_Release(layout
);
2868 win_skip("DWRITE_FLOW_DIRECTION_LEFT_TO_RIGHT is not supported\n");
2870 IDWriteTextFormat_Release(format
);
2871 IDWriteFactory_Release(factory
);
2874 static const struct drawcall_entry draweffect_seq
[] = {
2875 { DRAW_GLYPHRUN
|DRAW_EFFECT
, {'a','e',0x0300,0} },
2876 { DRAW_GLYPHRUN
, {'d',0} },
2880 static const struct drawcall_entry draweffect2_seq
[] = {
2881 { DRAW_GLYPHRUN
|DRAW_EFFECT
, {'a','e',0} },
2882 { DRAW_GLYPHRUN
, {'c','d',0} },
2886 static const struct drawcall_entry draweffect3_seq
[] = {
2887 { DRAW_INLINE
|DRAW_EFFECT
},
2891 static const struct drawcall_entry draweffect4_seq
[] = {
2896 static void test_SetDrawingEffect(void)
2898 static const WCHAR strW
[] = {'a','e',0x0300,'d',0}; /* accent grave */
2899 static const WCHAR str2W
[] = {'a','e','c','d',0};
2900 IDWriteInlineObject
*sign
;
2901 IDWriteTextFormat
*format
;
2902 IDWriteTextLayout
*layout
;
2903 IDWriteFactory
*factory
;
2904 DWRITE_TEXT_RANGE r
;
2908 factory
= create_factory();
2910 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
2911 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
2912 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2914 /* string with combining mark */
2915 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 500.0, 1000.0, &layout
);
2916 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2918 /* set effect past the end of text */
2919 r
.startPosition
= 100;
2921 hr
= IDWriteTextLayout_SetDrawingEffect(layout
, &testeffect
, r
);
2922 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2924 r
.startPosition
= r
.length
= 0;
2925 hr
= IDWriteTextLayout_GetDrawingEffect(layout
, 101, &unk
, &r
);
2926 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2927 ok(r
.startPosition
== 100 && r
.length
== 10, "got %u, %u\n", r
.startPosition
, r
.length
);
2929 r
.startPosition
= r
.length
= 0;
2930 unk
= (void*)0xdeadbeef;
2931 hr
= IDWriteTextLayout_GetDrawingEffect(layout
, 1000, &unk
, &r
);
2932 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2933 ok(r
.startPosition
== 110 && r
.length
== ~0u-110, "got %u, %u\n", r
.startPosition
, r
.length
);
2934 ok(unk
== NULL
, "got %p\n", unk
);
2936 /* effect is applied to clusters, not individual text positions */
2937 r
.startPosition
= 0;
2939 hr
= IDWriteTextLayout_SetDrawingEffect(layout
, &testeffect
, r
);
2940 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2942 flush_sequence(sequences
, RENDERER_ID
);
2943 hr
= IDWriteTextLayout_Draw(layout
, NULL
, &testrenderer
, 0.0, 0.0);
2944 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2945 ok_sequence(sequences
, RENDERER_ID
, draweffect_seq
, "effect draw test", TRUE
);
2946 IDWriteTextLayout_Release(layout
);
2949 hr
= IDWriteFactory_CreateTextLayout(factory
, str2W
, 4, format
, 500.0, 1000.0, &layout
);
2950 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2952 r
.startPosition
= 0;
2954 hr
= IDWriteTextLayout_SetDrawingEffect(layout
, &testeffect
, r
);
2955 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2957 flush_sequence(sequences
, RENDERER_ID
);
2958 hr
= IDWriteTextLayout_Draw(layout
, NULL
, &testrenderer
, 0.0, 0.0);
2959 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2960 ok_sequence(sequences
, RENDERER_ID
, draweffect2_seq
, "effect draw test 2", TRUE
);
2961 IDWriteTextLayout_Release(layout
);
2963 /* Inline object - effect set for same range */
2964 hr
= IDWriteFactory_CreateEllipsisTrimmingSign(factory
, format
, &sign
);
2965 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2967 hr
= IDWriteFactory_CreateTextLayout(factory
, str2W
, 4, format
, 500.0, 1000.0, &layout
);
2968 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2970 r
.startPosition
= 0;
2972 hr
= IDWriteTextLayout_SetInlineObject(layout
, sign
, r
);
2973 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2975 hr
= IDWriteTextLayout_SetDrawingEffect(layout
, &testeffect
, r
);
2976 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2978 flush_sequence(sequences
, RENDERER_ID
);
2979 hr
= IDWriteTextLayout_Draw(layout
, NULL
, &testrenderer
, 0.0, 0.0);
2980 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2981 ok_sequence(sequences
, RENDERER_ID
, draweffect3_seq
, "effect draw test 3", FALSE
);
2983 /* now set effect somewhere inside a range replaced by inline object */
2984 hr
= IDWriteTextLayout_SetDrawingEffect(layout
, NULL
, r
);
2985 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2987 r
.startPosition
= 1;
2989 hr
= IDWriteTextLayout_SetDrawingEffect(layout
, &testeffect
, r
);
2990 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2992 /* no effect is reported in this case */
2993 flush_sequence(sequences
, RENDERER_ID
);
2994 hr
= IDWriteTextLayout_Draw(layout
, NULL
, &testrenderer
, 0.0, 0.0);
2995 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2996 ok_sequence(sequences
, RENDERER_ID
, draweffect4_seq
, "effect draw test 4", FALSE
);
2998 r
.startPosition
= 0;
3000 hr
= IDWriteTextLayout_SetDrawingEffect(layout
, NULL
, r
);
3001 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3003 r
.startPosition
= 0;
3005 hr
= IDWriteTextLayout_SetDrawingEffect(layout
, &testeffect
, r
);
3006 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3008 /* first range position is all that matters for inline ranges */
3009 flush_sequence(sequences
, RENDERER_ID
);
3010 hr
= IDWriteTextLayout_Draw(layout
, NULL
, &testrenderer
, 0.0, 0.0);
3011 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3012 ok_sequence(sequences
, RENDERER_ID
, draweffect3_seq
, "effect draw test 5", FALSE
);
3014 IDWriteTextLayout_Release(layout
);
3016 IDWriteInlineObject_Release(sign
);
3017 IDWriteTextFormat_Release(format
);
3018 IDWriteFactory_Release(factory
);
3021 static IDWriteFontFace
*get_fontface_from_format(IDWriteTextFormat
*format
)
3023 IDWriteFontCollection
*collection
;
3024 IDWriteFontFamily
*family
;
3025 IDWriteFontFace
*fontface
;
3032 hr
= IDWriteTextFormat_GetFontCollection(format
, &collection
);
3033 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3035 hr
= IDWriteTextFormat_GetFontFamilyName(format
, nameW
, sizeof(nameW
)/sizeof(WCHAR
));
3036 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3038 hr
= IDWriteFontCollection_FindFamilyName(collection
, nameW
, &index
, &exists
);
3039 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3041 hr
= IDWriteFontCollection_GetFontFamily(collection
, index
, &family
);
3042 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3043 IDWriteFontCollection_Release(collection
);
3045 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
,
3046 IDWriteTextFormat_GetFontWeight(format
),
3047 IDWriteTextFormat_GetFontStretch(format
),
3048 IDWriteTextFormat_GetFontStyle(format
),
3050 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3052 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
3053 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3055 IDWriteFont_Release(font
);
3056 IDWriteFontFamily_Release(family
);
3061 static void test_GetLineMetrics(void)
3063 static const WCHAR str3W
[] = {'a','\r','b','\n','c','\n','\r','d','\r','\n',0};
3064 static const WCHAR strW
[] = {'a','b','c','d',' ',0};
3065 static const WCHAR str2W
[] = {'a','b','\r','c','d',0};
3066 DWRITE_FONT_METRICS fontmetrics
;
3067 DWRITE_LINE_METRICS metrics
[6];
3068 IDWriteTextFormat
*format
;
3069 IDWriteTextLayout
*layout
;
3070 IDWriteFontFace
*fontface
;
3071 IDWriteFactory
*factory
;
3075 factory
= create_factory();
3077 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
3078 DWRITE_FONT_STRETCH_NORMAL
, 2048.0, enusW
, &format
);
3079 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3081 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 5, format
, 30000.0, 1000.0, &layout
);
3082 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3085 hr
= IDWriteTextLayout_GetLineMetrics(layout
, metrics
, 0, &count
);
3086 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
3087 ok(count
== 1, "got count %u\n", count
);
3089 memset(metrics
, 0, sizeof(metrics
));
3090 hr
= IDWriteTextLayout_GetLineMetrics(layout
, metrics
, 1, &count
);
3091 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3092 ok(metrics
[0].length
== 5, "got %u\n", metrics
[0].length
);
3093 ok(metrics
[0].trailingWhitespaceLength
== 1, "got %u\n", metrics
[0].trailingWhitespaceLength
);
3095 ok(metrics
[0].newlineLength
== 0, "got %u\n", metrics
[0].newlineLength
);
3096 ok(metrics
[0].isTrimmed
== FALSE
, "got %d\n", metrics
[0].isTrimmed
);
3098 /* Tahoma doesn't provide BASE table, so baseline is calculated from font metrics */
3099 fontface
= get_fontface_from_format(format
);
3100 ok(fontface
!= NULL
, "got %p\n", fontface
);
3101 IDWriteFontFace_GetMetrics(fontface
, &fontmetrics
);
3103 ok(metrics
[0].baseline
== fontmetrics
.ascent
, "got %.2f, expected %d\n", metrics
[0].baseline
,
3104 fontmetrics
.ascent
);
3105 ok(metrics
[0].height
== fontmetrics
.ascent
+ fontmetrics
.descent
, "got %.2f, expected %d\n",
3106 metrics
[0].height
, fontmetrics
.ascent
+ fontmetrics
.descent
);
3107 IDWriteTextLayout_Release(layout
);
3110 hr
= IDWriteFactory_CreateTextLayout(factory
, str2W
, 5, format
, 10000.0, 1000.0, &layout
);
3111 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3113 memset(metrics
, 0, sizeof(metrics
));
3115 hr
= IDWriteTextLayout_GetLineMetrics(layout
, metrics
, 2, &count
);
3116 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3118 ok(count
== 2, "got %u\n", count
);
3119 /* baseline is relative to a line, and is not accumulated */
3120 ok(metrics
[0].baseline
== metrics
[1].baseline
, "got %.2f, %.2f\n", metrics
[0].baseline
,
3121 metrics
[1].baseline
);
3123 IDWriteTextLayout_Release(layout
);
3124 IDWriteTextFormat_Release(format
);
3127 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
3128 DWRITE_FONT_STRETCH_NORMAL
, 12.0, enusW
, &format
);
3129 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3131 hr
= IDWriteFactory_CreateTextLayout(factory
, str3W
, 10, format
, 100.0, 300.0, &layout
);
3132 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3134 memset(metrics
, 0xcc, sizeof(metrics
));
3135 hr
= IDWriteTextLayout_GetLineMetrics(layout
, metrics
, 6, &count
);
3136 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3138 ok(count
== 6, "got %u\n", count
);
3141 ok(metrics
[0].length
== 2, "got %u\n", metrics
[0].length
);
3142 ok(metrics
[1].length
== 2, "got %u\n", metrics
[1].length
);
3143 ok(metrics
[2].length
== 2, "got %u\n", metrics
[2].length
);
3144 ok(metrics
[3].length
== 1, "got %u\n", metrics
[3].length
);
3145 ok(metrics
[4].length
== 3, "got %u\n", metrics
[4].length
);
3146 ok(metrics
[5].length
== 0, "got %u\n", metrics
[5].length
);
3150 ok(metrics
[0].newlineLength
== 1, "got %u\n", metrics
[0].newlineLength
);
3151 ok(metrics
[1].newlineLength
== 1, "got %u\n", metrics
[1].newlineLength
);
3152 ok(metrics
[2].newlineLength
== 1, "got %u\n", metrics
[2].newlineLength
);
3153 ok(metrics
[3].newlineLength
== 1, "got %u\n", metrics
[3].newlineLength
);
3154 ok(metrics
[4].newlineLength
== 2, "got %u\n", metrics
[4].newlineLength
);
3155 ok(metrics
[5].newlineLength
== 0, "got %u\n", metrics
[5].newlineLength
);
3157 IDWriteTextLayout_Release(layout
);
3158 IDWriteTextFormat_Release(format
);
3159 IDWriteFontFace_Release(fontface
);
3160 IDWriteFactory_Release(factory
);
3163 static void test_SetTextAlignment(void)
3165 static const WCHAR str2W
[] = {'a','a','a','a','a',0};
3166 static const WCHAR strW
[] = {'a',0};
3167 DWRITE_CLUSTER_METRICS clusters
[1];
3168 DWRITE_TEXT_METRICS metrics
;
3169 IDWriteTextFormat1
*format1
;
3170 IDWriteTextFormat
*format
;
3171 IDWriteTextLayout
*layout
;
3172 IDWriteFactory
*factory
;
3173 DWRITE_TEXT_ALIGNMENT v
;
3177 factory
= create_factory();
3179 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
3180 DWRITE_FONT_STRETCH_NORMAL
, 12.0, enusW
, &format
);
3181 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3183 v
= IDWriteTextFormat_GetTextAlignment(format
);
3184 ok(v
== DWRITE_TEXT_ALIGNMENT_LEADING
, "got %d\n", v
);
3186 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 1, format
, 500.0, 100.0, &layout
);
3187 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3189 v
= IDWriteTextLayout_GetTextAlignment(layout
);
3190 ok(v
== DWRITE_TEXT_ALIGNMENT_LEADING
, "got %d\n", v
);
3192 hr
= IDWriteTextLayout_SetTextAlignment(layout
, DWRITE_TEXT_ALIGNMENT_TRAILING
);
3193 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3195 hr
= IDWriteTextLayout_SetTextAlignment(layout
, DWRITE_TEXT_ALIGNMENT_TRAILING
);
3196 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3198 v
= IDWriteTextFormat_GetTextAlignment(format
);
3199 ok(v
== DWRITE_TEXT_ALIGNMENT_LEADING
, "got %d\n", v
);
3201 v
= IDWriteTextLayout_GetTextAlignment(layout
);
3202 ok(v
== DWRITE_TEXT_ALIGNMENT_TRAILING
, "got %d\n", v
);
3204 hr
= IDWriteTextLayout_QueryInterface(layout
, &IID_IDWriteTextFormat1
, (void**)&format1
);
3206 hr
= IDWriteTextFormat1_SetTextAlignment(format1
, DWRITE_TEXT_ALIGNMENT_CENTER
);
3207 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3209 v
= IDWriteTextFormat_GetTextAlignment(format
);
3210 ok(v
== DWRITE_TEXT_ALIGNMENT_LEADING
, "got %d\n", v
);
3212 v
= IDWriteTextLayout_GetTextAlignment(layout
);
3213 ok(v
== DWRITE_TEXT_ALIGNMENT_CENTER
, "got %d\n", v
);
3215 v
= IDWriteTextFormat1_GetTextAlignment(format1
);
3216 ok(v
== DWRITE_TEXT_ALIGNMENT_CENTER
, "got %d\n", v
);
3218 IDWriteTextFormat1_Release(format1
);
3221 win_skip("IDWriteTextFormat1 is not supported\n");
3224 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, clusters
, 1, &count
);
3225 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3226 ok(count
== 1, "got %u\n", count
);
3228 /* maxwidth is 500, leading alignment */
3229 hr
= IDWriteTextLayout_SetTextAlignment(layout
, DWRITE_TEXT_ALIGNMENT_LEADING
);
3230 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3232 hr
= IDWriteTextLayout_GetMetrics(layout
, &metrics
);
3233 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3235 ok(metrics
.left
== 0.0, "got %.2f\n", metrics
.left
);
3236 ok(metrics
.width
== clusters
[0].width
, "got %.2f\n", metrics
.width
);
3237 ok(metrics
.layoutWidth
== 500.0, "got %.2f\n", metrics
.layoutWidth
);
3238 ok(metrics
.lineCount
== 1, "got %d\n", metrics
.lineCount
);
3240 /* maxwidth is 500, trailing alignment */
3241 hr
= IDWriteTextLayout_SetTextAlignment(layout
, DWRITE_TEXT_ALIGNMENT_TRAILING
);
3242 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3244 hr
= IDWriteTextLayout_GetMetrics(layout
, &metrics
);
3245 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3247 ok(metrics
.left
== metrics
.layoutWidth
- metrics
.width
, "got %.2f\n", metrics
.left
);
3248 ok(metrics
.width
== clusters
[0].width
, "got %.2f\n", metrics
.width
);
3249 ok(metrics
.layoutWidth
== 500.0, "got %.2f\n", metrics
.layoutWidth
);
3250 ok(metrics
.lineCount
== 1, "got %d\n", metrics
.lineCount
);
3251 IDWriteTextLayout_Release(layout
);
3253 /* initially created with trailing alignment */
3254 hr
= IDWriteTextFormat_SetTextAlignment(format
, DWRITE_TEXT_ALIGNMENT_TRAILING
);
3255 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3257 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 1, format
, 500.0, 100.0, &layout
);
3258 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3260 hr
= IDWriteTextLayout_GetMetrics(layout
, &metrics
);
3261 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3263 ok(metrics
.left
== metrics
.layoutWidth
- metrics
.width
, "got %.2f\n", metrics
.left
);
3264 ok(metrics
.width
== clusters
[0].width
, "got %.2f\n", metrics
.width
);
3265 ok(metrics
.layoutWidth
== 500.0, "got %.2f\n", metrics
.layoutWidth
);
3266 ok(metrics
.lineCount
== 1, "got %d\n", metrics
.lineCount
);
3267 IDWriteTextLayout_Release(layout
);
3269 /* max width less than total run width, trailing alignment */
3270 hr
= IDWriteTextFormat_SetWordWrapping(format
, DWRITE_WORD_WRAPPING_NO_WRAP
);
3271 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3273 hr
= IDWriteFactory_CreateTextLayout(factory
, str2W
, 5, format
, 2*clusters
[0].width
, 100.0, &layout
);
3274 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3275 hr
= IDWriteTextLayout_GetMetrics(layout
, &metrics
);
3276 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3277 ok(metrics
.left
== metrics
.layoutWidth
- metrics
.width
, "got %.2f\n", metrics
.left
);
3279 ok(metrics
.width
== 5*clusters
[0].width
, "got %.2f\n", metrics
.width
);
3280 ok(metrics
.lineCount
== 1, "got %d\n", metrics
.lineCount
);
3281 IDWriteTextLayout_Release(layout
);
3283 /* maxwidth is 500, centered */
3284 hr
= IDWriteTextFormat_SetTextAlignment(format
, DWRITE_TEXT_ALIGNMENT_CENTER
);
3285 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3287 hr
= IDWriteFactory_CreateTextLayout(factory
, str2W
, 5, format
, 500.0, 100.0, &layout
);
3288 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3290 hr
= IDWriteTextLayout_GetMetrics(layout
, &metrics
);
3291 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3292 ok(metrics
.left
== (metrics
.layoutWidth
- metrics
.width
) / 2.0, "got %.2f\n", metrics
.left
);
3293 ok(metrics
.width
== 5*clusters
[0].width
, "got %.2f\n", metrics
.width
);
3294 ok(metrics
.lineCount
== 1, "got %d\n", metrics
.lineCount
);
3296 IDWriteTextLayout_Release(layout
);
3298 IDWriteTextFormat_Release(format
);
3299 IDWriteFactory_Release(factory
);
3302 static void test_SetParagraphAlignment(void)
3304 static const WCHAR strW
[] = {'a',0};
3305 DWRITE_TEXT_METRICS metrics
;
3306 IDWriteTextFormat
*format
;
3307 IDWriteTextLayout
*layout
;
3308 IDWriteFactory
*factory
;
3309 DWRITE_PARAGRAPH_ALIGNMENT v
;
3310 DWRITE_LINE_METRICS lines
[1];
3314 factory
= create_factory();
3316 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
3317 DWRITE_FONT_STRETCH_NORMAL
, 12.0, enusW
, &format
);
3318 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3320 v
= IDWriteTextFormat_GetParagraphAlignment(format
);
3321 ok(v
== DWRITE_PARAGRAPH_ALIGNMENT_NEAR
, "got %d\n", v
);
3323 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 1, format
, 500.0, 100.0, &layout
);
3324 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3326 v
= IDWriteTextLayout_GetParagraphAlignment(layout
);
3327 ok(v
== DWRITE_PARAGRAPH_ALIGNMENT_NEAR
, "got %d\n", v
);
3329 hr
= IDWriteTextLayout_SetParagraphAlignment(layout
, DWRITE_PARAGRAPH_ALIGNMENT_FAR
);
3330 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3332 hr
= IDWriteTextLayout_SetParagraphAlignment(layout
, DWRITE_PARAGRAPH_ALIGNMENT_FAR
);
3333 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3335 v
= IDWriteTextFormat_GetParagraphAlignment(format
);
3336 ok(v
== DWRITE_PARAGRAPH_ALIGNMENT_NEAR
, "got %d\n", v
);
3338 v
= IDWriteTextLayout_GetParagraphAlignment(layout
);
3339 ok(v
== DWRITE_PARAGRAPH_ALIGNMENT_FAR
, "got %d\n", v
);
3341 hr
= IDWriteTextLayout_SetParagraphAlignment(layout
, DWRITE_PARAGRAPH_ALIGNMENT_CENTER
);
3342 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3344 v
= IDWriteTextLayout_GetParagraphAlignment(layout
);
3345 ok(v
== DWRITE_PARAGRAPH_ALIGNMENT_CENTER
, "got %d\n", v
);
3348 hr
= IDWriteTextLayout_GetLineMetrics(layout
, lines
, 1, &count
);
3349 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3350 ok(count
== 1, "got %u\n", count
);
3352 /* maxheight is 100, near alignment */
3353 hr
= IDWriteTextLayout_SetParagraphAlignment(layout
, DWRITE_PARAGRAPH_ALIGNMENT_NEAR
);
3354 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3356 hr
= IDWriteTextLayout_GetMetrics(layout
, &metrics
);
3357 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3359 ok(metrics
.top
== 0.0, "got %.2f\n", metrics
.top
);
3360 ok(metrics
.height
== lines
[0].height
, "got %.2f\n", metrics
.height
);
3361 ok(metrics
.layoutHeight
== 100.0, "got %.2f\n", metrics
.layoutHeight
);
3362 ok(metrics
.lineCount
== 1, "got %d\n", metrics
.lineCount
);
3364 /* maxwidth is 100, far alignment */
3365 hr
= IDWriteTextLayout_SetParagraphAlignment(layout
, DWRITE_PARAGRAPH_ALIGNMENT_FAR
);
3366 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3368 hr
= IDWriteTextLayout_GetMetrics(layout
, &metrics
);
3369 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3371 ok(metrics
.top
== metrics
.layoutHeight
- metrics
.height
, "got %.2f\n", metrics
.top
);
3372 ok(metrics
.height
== lines
[0].height
, "got %.2f\n", metrics
.height
);
3373 ok(metrics
.layoutHeight
== 100.0, "got %.2f\n", metrics
.layoutHeight
);
3374 ok(metrics
.lineCount
== 1, "got %d\n", metrics
.lineCount
);
3375 IDWriteTextLayout_Release(layout
);
3377 /* initially created with centered alignment */
3378 hr
= IDWriteTextFormat_SetParagraphAlignment(format
, DWRITE_PARAGRAPH_ALIGNMENT_CENTER
);
3379 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3381 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 1, format
, 500.0, 100.0, &layout
);
3382 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3384 hr
= IDWriteTextLayout_GetMetrics(layout
, &metrics
);
3385 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3387 ok(metrics
.top
== (metrics
.layoutHeight
- lines
[0].height
) / 2, "got %.2f\n", metrics
.top
);
3388 ok(metrics
.height
== lines
[0].height
, "got %.2f\n", metrics
.height
);
3389 ok(metrics
.lineCount
== 1, "got %d\n", metrics
.lineCount
);
3390 IDWriteTextLayout_Release(layout
);
3392 IDWriteTextFormat_Release(format
);
3393 IDWriteFactory_Release(factory
);
3396 static void test_SetReadingDirection(void)
3398 static const WCHAR strW
[] = {'a',0};
3399 DWRITE_CLUSTER_METRICS clusters
[1];
3400 DWRITE_TEXT_METRICS metrics
;
3401 IDWriteTextFormat
*format
;
3402 IDWriteTextLayout
*layout
;
3403 IDWriteFactory
*factory
;
3404 DWRITE_READING_DIRECTION v
;
3405 DWRITE_LINE_METRICS lines
[1];
3409 factory
= create_factory();
3411 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
3412 DWRITE_FONT_STRETCH_NORMAL
, 12.0, enusW
, &format
);
3413 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3415 v
= IDWriteTextFormat_GetReadingDirection(format
);
3416 ok(v
== DWRITE_READING_DIRECTION_LEFT_TO_RIGHT
, "got %d\n", v
);
3418 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 1, format
, 500.0, 100.0, &layout
);
3419 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3421 v
= IDWriteTextLayout_GetReadingDirection(layout
);
3422 ok(v
== DWRITE_READING_DIRECTION_LEFT_TO_RIGHT
, "got %d\n", v
);
3424 v
= IDWriteTextFormat_GetReadingDirection(format
);
3425 ok(v
== DWRITE_READING_DIRECTION_LEFT_TO_RIGHT
, "got %d\n", v
);
3427 hr
= IDWriteTextLayout_SetReadingDirection(layout
, DWRITE_READING_DIRECTION_RIGHT_TO_LEFT
);
3428 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3431 hr
= IDWriteTextLayout_GetLineMetrics(layout
, lines
, 1, &count
);
3432 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3433 ok(count
== 1, "got %u\n", count
);
3436 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, clusters
, 1, &count
);
3437 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3438 ok(count
== 1, "got %u\n", count
);
3440 /* leading alignment, RTL */
3441 hr
= IDWriteTextLayout_GetMetrics(layout
, &metrics
);
3442 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3444 ok(metrics
.left
== metrics
.layoutWidth
- clusters
[0].width
, "got %.2f\n", metrics
.left
);
3445 ok(metrics
.top
== 0.0, "got %.2f\n", metrics
.top
);
3446 ok(metrics
.width
== clusters
[0].width
, "got %.2f\n", metrics
.width
);
3447 ok(metrics
.height
== lines
[0].height
, "got %.2f\n", metrics
.height
);
3448 ok(metrics
.layoutWidth
== 500.0, "got %.2f\n", metrics
.layoutWidth
);
3449 ok(metrics
.layoutHeight
== 100.0, "got %.2f\n", metrics
.layoutHeight
);
3450 ok(metrics
.lineCount
== 1, "got %d\n", metrics
.lineCount
);
3452 /* trailing alignment, RTL */
3453 hr
= IDWriteTextLayout_SetTextAlignment(layout
, DWRITE_TEXT_ALIGNMENT_TRAILING
);
3454 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3456 hr
= IDWriteTextLayout_GetMetrics(layout
, &metrics
);
3457 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3459 ok(metrics
.left
== 0.0, "got %.2f\n", metrics
.left
);
3460 ok(metrics
.top
== 0.0, "got %.2f\n", metrics
.top
);
3461 ok(metrics
.width
== clusters
[0].width
, "got %.2f\n", metrics
.width
);
3462 ok(metrics
.height
== lines
[0].height
, "got %.2f\n", metrics
.height
);
3463 ok(metrics
.layoutWidth
== 500.0, "got %.2f\n", metrics
.layoutWidth
);
3464 ok(metrics
.layoutHeight
== 100.0, "got %.2f\n", metrics
.layoutHeight
);
3465 ok(metrics
.lineCount
== 1, "got %d\n", metrics
.lineCount
);
3467 /* centered alignment, RTL */
3468 hr
= IDWriteTextLayout_SetTextAlignment(layout
, DWRITE_TEXT_ALIGNMENT_CENTER
);
3469 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3471 hr
= IDWriteTextLayout_GetMetrics(layout
, &metrics
);
3472 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3474 ok(metrics
.left
== (metrics
.layoutWidth
- clusters
[0].width
) / 2.0, "got %.2f\n", metrics
.left
);
3475 ok(metrics
.top
== 0.0, "got %.2f\n", metrics
.top
);
3476 ok(metrics
.width
== clusters
[0].width
, "got %.2f\n", metrics
.width
);
3477 ok(metrics
.height
== lines
[0].height
, "got %.2f\n", metrics
.height
);
3478 ok(metrics
.layoutWidth
== 500.0, "got %.2f\n", metrics
.layoutWidth
);
3479 ok(metrics
.layoutHeight
== 100.0, "got %.2f\n", metrics
.layoutHeight
);
3480 ok(metrics
.lineCount
== 1, "got %d\n", metrics
.lineCount
);
3482 IDWriteTextLayout_Release(layout
);
3484 IDWriteTextFormat_Release(format
);
3485 IDWriteFactory_Release(factory
);
3488 static inline FLOAT
get_scaled_font_metric(UINT32 metric
, FLOAT emSize
, const DWRITE_FONT_METRICS
*metrics
)
3490 return (FLOAT
)metric
* emSize
/ (FLOAT
)metrics
->designUnitsPerEm
;
3493 static FLOAT
snap_coord(const DWRITE_MATRIX
*m
, FLOAT ppdip
, FLOAT coord
)
3495 FLOAT vec
[2], det
, vec2
[2];
3498 /* has to be a diagonal matrix */
3499 if ((ppdip
<= 0.0) ||
3500 (m
->m11
* m
->m22
!= 0.0 && (m
->m12
!= 0.0 || m
->m21
!= 0.0)) ||
3501 (m
->m12
* m
->m21
!= 0.0 && (m
->m11
!= 0.0 || m
->m22
!= 0.0)))
3504 det
= m
->m11
* m
->m22
- m
->m12
* m
->m21
;
3505 transform
= fabsf(det
) > 1e-10;
3508 /* apply transform */
3510 vec
[1] = coord
* ppdip
;
3512 vec2
[0] = m
->m11
* vec
[0] + m
->m21
* vec
[1] + m
->dx
;
3513 vec2
[1] = m
->m12
* vec
[0] + m
->m22
* vec
[1] + m
->dy
;
3516 vec2
[0] = floorf(vec2
[0] + 0.5f
);
3517 vec2
[1] = floorf(vec2
[1] + 0.5f
);
3519 /* apply inverted transform */
3520 vec
[1] = (-m
->m12
* vec2
[0] + m
->m11
* vec2
[1] - (m
->m11
* m
->dy
- m
->m12
* m
->dx
)) / det
;
3524 vec
[1] = floorf(coord
* ppdip
+ 0.5f
) / ppdip
;
3528 static inline BOOL
float_eq(FLOAT left
, FLOAT right
)
3530 int x
= *(int *)&left
;
3531 int y
= *(int *)&right
;
3538 return abs(x
- y
) <= 16;
3541 struct snapping_test
{
3546 static struct snapping_test snapping_tests
[] = {
3547 { { 0.0, 1.0, 2.0, 0.0, 0.2, 0.3 }, 1.0 },
3548 { { 0.0, 1.0, 2.0, 0.0, 0.0, 0.0 }, 1.0 },
3549 { { 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 }, 1.0 }, /* identity transform */
3550 { { 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 }, 0.9 },
3551 { { 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 }, -1.0 },
3552 { { 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 }, 0.0 },
3553 { { 1.0, 0.0, 0.0, 1.0, 0.0, 0.3 }, 1.0 }, /* simple Y shift */
3554 { { 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 }, 10.0 }, /* identity, 10 ppdip */
3555 { { 1.0, 0.0, 0.0, 10.0, 0.0, 0.0 }, 10.0 },
3556 { { 0.0, 1.0, 1.0, 0.0, 0.2, 0.6 }, 1.0 },
3557 { { 0.0, 2.0, 2.0, 0.0, 0.2, 0.6 }, 1.0 },
3558 { { 0.0, 0.5, -0.5, 0.0, 0.2, 0.6 }, 1.0 },
3559 { { 1.0, 2.0, 0.0, 1.0, 0.2, 0.6 }, 1.0 },
3560 { { 1.0, 1.0, 0.0, 1.0, 0.2, 0.6 }, 1.0 },
3561 { { 0.5, 0.5, -0.5, 0.5, 0.2, 0.6 }, 1.0 }, /* 45 degrees rotation */
3562 { { 0.5, 0.5, -0.5, 0.5, 0.0, 0.0 }, 100.0 }, /* 45 degrees rotation */
3563 { { 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 }, 100.0 },
3564 { { 0.0, 1.0, -1.0, 0.0, 0.2, 0.6 }, 1.0 }, /* 90 degrees rotation */
3565 { { -1.0, 0.0, 0.0, -1.0, 0.2, 0.6 }, 1.0 }, /* 180 degrees rotation */
3566 { { 0.0, -1.0, 1.0, 0.0, 0.2, 0.6 }, 1.0 }, /* 270 degrees rotation */
3567 { { 1.0, 0.0, 0.0, 1.0,-0.1, 0.2 }, 1.0 },
3568 { { 0.0, 1.0, -1.0, 0.0,-0.2,-0.3 }, 1.0 }, /* 90 degrees rotation */
3569 { { -1.0, 0.0, 0.0, -1.0,-0.3,-1.6 }, 1.0 }, /* 180 degrees rotation */
3570 { { 0.0, -1.0, 1.0, 0.0,-0.7, 0.6 }, 10.0 }, /* 270 degrees rotation */
3571 { { 0.0, 2.0, 1.0, 0.0, 0.2, 0.6 }, 1.0 },
3572 { { 0.0, 0.0, 1.0, 0.0, 0.0, 0.0 }, 1.0 },
3573 { { 3.0, 0.0, 0.0, 5.0, 0.2,-0.3 }, 10.0 },
3574 { { 0.0, -3.0, 5.0, 0.0,-0.1, 0.7 }, 10.0 },
3577 static DWRITE_MATRIX compattransforms
[] = {
3578 { 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 },
3579 { 1.0, 0.0, 0.0, 1.0, 0.2, 0.3 },
3580 { 2.0, 0.0, 0.0, 2.0, 0.2, 0.3 },
3581 { 2.0, 1.0, 2.0, 2.0, 0.2, 0.3 },
3584 static void test_pixelsnapping(void)
3586 static const WCHAR strW
[] = {'a',0};
3587 IDWriteTextLayout
*layout
, *layout2
;
3588 struct renderer_context ctxt
;
3589 DWRITE_FONT_METRICS metrics
;
3590 IDWriteTextFormat
*format
;
3591 IDWriteFontFace
*fontface
;
3592 IDWriteFactory
*factory
;
3593 FLOAT baseline
, originX
;
3597 factory
= create_factory();
3599 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
3600 DWRITE_FONT_STRETCH_NORMAL
, 12.0, enusW
, &format
);
3601 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3603 fontface
= get_fontface_from_format(format
);
3604 IDWriteFontFace_GetMetrics(fontface
, &metrics
);
3606 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 1, format
, 500.0, 100.0, &layout
);
3607 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3609 /* disabled snapping */
3610 ctxt
.snapping_disabled
= TRUE
;
3611 ctxt
.gdicompat
= FALSE
;
3612 ctxt
.use_gdi_natural
= FALSE
;
3614 memset(&ctxt
.m
, 0, sizeof(ctxt
.m
));
3615 ctxt
.m
.m11
= ctxt
.m
.m22
= 1.0;
3618 hr
= IDWriteTextLayout_Draw(layout
, &ctxt
, &testrenderer
, originX
, 0.0);
3619 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3621 baseline
= get_scaled_font_metric(metrics
.ascent
, 12.0, &metrics
);
3622 ok(ctxt
.originX
== originX
, "got %f, originX %f\n", ctxt
.originX
, originX
);
3623 ok(ctxt
.originY
== baseline
, "got %f, baseline %f\n", ctxt
.originY
, baseline
);
3624 ok(floor(baseline
) != baseline
, "got %f\n", baseline
);
3626 ctxt
.snapping_disabled
= FALSE
;
3628 for (i
= 0; i
< sizeof(snapping_tests
)/sizeof(snapping_tests
[0]); i
++) {
3629 struct snapping_test
*ptr
= &snapping_tests
[i
];
3633 ctxt
.ppdip
= ptr
->ppdip
;
3634 ctxt
.originX
= 678.9;
3635 ctxt
.originY
= 678.9;
3637 expectedY
= snap_coord(&ctxt
.m
, ctxt
.ppdip
, baseline
);
3638 hr
= IDWriteTextLayout_Draw(layout
, &ctxt
, &testrenderer
, originX
, 0.0);
3639 ok(hr
== S_OK
, "%d: got 0x%08x\n", i
, hr
);
3640 ok(ctxt
.originX
== originX
, "%d: got %f, originX %f\n", i
, ctxt
.originX
, originX
);
3641 ok(float_eq(ctxt
.originY
, expectedY
), "%d: got %f, expected %f, baseline %f\n",
3642 i
, ctxt
.originY
, expectedY
, baseline
);
3644 /* gdicompat layout transform doesn't affect snapping */
3645 for (j
= 0; j
< sizeof(compattransforms
)/sizeof(compattransforms
[0]); j
++) {
3646 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, strW
, 1, format
, 500.0, 100.0,
3647 1.0, &compattransforms
[j
], FALSE
, &layout2
);
3648 ok(hr
== S_OK
, "%d: got 0x%08x\n", i
, hr
);
3650 expectedY
= snap_coord(&ctxt
.m
, ctxt
.ppdip
, baseline
);
3651 hr
= IDWriteTextLayout_Draw(layout
, &ctxt
, &testrenderer
, originX
, 0.0);
3652 ok(hr
== S_OK
, "%d: got 0x%08x\n", i
, hr
);
3653 ok(ctxt
.originX
== originX
, "%d: got %f, originX %f\n", i
, ctxt
.originX
, originX
);
3654 ok(float_eq(ctxt
.originY
, expectedY
), "%d: got %f, expected %f, baseline %f\n",
3655 i
, ctxt
.originY
, expectedY
, baseline
);
3657 IDWriteTextLayout_Release(layout2
);
3661 IDWriteTextLayout_Release(layout
);
3662 IDWriteTextFormat_Release(format
);
3663 IDWriteFontFace_Release(fontface
);
3664 IDWriteFactory_Release(factory
);
3667 static void test_SetWordWrapping(void)
3669 static const WCHAR strW
[] = {'a',0};
3670 IDWriteTextFormat
*format
;
3671 IDWriteTextLayout
*layout
;
3672 IDWriteFactory
*factory
;
3673 DWRITE_WORD_WRAPPING v
;
3676 factory
= create_factory();
3678 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
3679 DWRITE_FONT_STRETCH_NORMAL
, 12.0, enusW
, &format
);
3680 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3682 v
= IDWriteTextFormat_GetWordWrapping(format
);
3683 ok(v
== DWRITE_WORD_WRAPPING_WRAP
, "got %d\n", v
);
3685 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 1, format
, 500.0, 100.0, &layout
);
3686 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3688 v
= IDWriteTextLayout_GetWordWrapping(layout
);
3689 ok(v
== DWRITE_WORD_WRAPPING_WRAP
, "got %d\n", v
);
3691 hr
= IDWriteTextLayout_SetWordWrapping(layout
, DWRITE_WORD_WRAPPING_NO_WRAP
);
3692 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3694 hr
= IDWriteTextLayout_SetWordWrapping(layout
, DWRITE_WORD_WRAPPING_NO_WRAP
);
3695 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3697 v
= IDWriteTextFormat_GetWordWrapping(format
);
3698 ok(v
== DWRITE_WORD_WRAPPING_WRAP
, "got %d\n", v
);
3700 IDWriteTextLayout_Release(layout
);
3701 IDWriteTextFormat_Release(format
);
3702 IDWriteFactory_Release(factory
);
3705 /* Collection dedicated to fallback testing */
3707 static const WCHAR g_blahfontW
[] = {'B','l','a','h',0};
3708 static HRESULT WINAPI
fontcollection_QI(IDWriteFontCollection
*iface
, REFIID riid
, void **obj
)
3710 if (IsEqualIID(riid
, &IID_IDWriteFontCollection
) || IsEqualIID(riid
, &IID_IUnknown
)) {
3712 IDWriteFontCollection_AddRef(iface
);
3717 return E_NOINTERFACE
;
3720 static ULONG WINAPI
fontcollection_AddRef(IDWriteFontCollection
*iface
)
3725 static ULONG WINAPI
fontcollection_Release(IDWriteFontCollection
*iface
)
3730 static UINT32 WINAPI
fontcollection_GetFontFamilyCount(IDWriteFontCollection
*iface
)
3732 ok(0, "unexpected call\n");
3736 static HRESULT WINAPI
fontcollection_GetFontFamily(IDWriteFontCollection
*iface
, UINT32 index
, IDWriteFontFamily
**family
)
3738 if (index
== 123456) {
3739 IDWriteFactory
*factory
= create_factory();
3740 IDWriteFontCollection
*syscollection
;
3744 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &syscollection
, FALSE
);
3745 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3747 hr
= IDWriteFontCollection_FindFamilyName(syscollection
, tahomaW
, &index
, &exists
);
3748 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3750 hr
= IDWriteFontCollection_GetFontFamily(syscollection
, index
, family
);
3751 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3753 IDWriteFontCollection_Release(syscollection
);
3754 IDWriteFactory_Release(factory
);
3757 ok(0, "unexpected call\n");
3761 static HRESULT WINAPI
fontcollection_FindFamilyName(IDWriteFontCollection
*iface
, WCHAR
const *name
, UINT32
*index
, BOOL
*exists
)
3763 if (!lstrcmpW(name
, g_blahfontW
)) {
3768 ok(0, "unexpected call, name %s\n", wine_dbgstr_w(name
));
3772 static HRESULT WINAPI
fontcollection_GetFontFromFontFace(IDWriteFontCollection
*iface
, IDWriteFontFace
*face
, IDWriteFont
**font
)
3774 ok(0, "unexpected call\n");
3778 static const IDWriteFontCollectionVtbl fallbackcollectionvtbl
= {
3780 fontcollection_AddRef
,
3781 fontcollection_Release
,
3782 fontcollection_GetFontFamilyCount
,
3783 fontcollection_GetFontFamily
,
3784 fontcollection_FindFamilyName
,
3785 fontcollection_GetFontFromFontFace
3788 static IDWriteFontCollection fallbackcollection
= { &fallbackcollectionvtbl
};
3790 static void test_MapCharacters(void)
3792 static const WCHAR strW
[] = {'a','b','c',0};
3793 static const WCHAR str2W
[] = {'a',0x3058,'b',0};
3794 IDWriteLocalizedStrings
*strings
;
3795 IDWriteFontFallback
*fallback
;
3796 IDWriteFactory2
*factory2
;
3797 IDWriteFactory
*factory
;
3798 UINT32 mappedlength
;
3805 factory
= create_factory();
3807 hr
= IDWriteFactory_QueryInterface(factory
, &IID_IDWriteFactory2
, (void**)&factory2
);
3808 IDWriteFactory_Release(factory
);
3810 win_skip("MapCharacters() is not supported\n");
3815 hr
= IDWriteFactory2_GetSystemFontFallback(factory2
, &fallback
);
3817 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3819 ok(fallback
!= NULL
, "got %p\n", fallback
);
3823 font
= (void*)0xdeadbeef;
3824 hr
= IDWriteFontFallback_MapCharacters(fallback
, NULL
, 0, 0, NULL
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
,
3825 DWRITE_FONT_STYLE_NORMAL
, DWRITE_FONT_STRETCH_NORMAL
, &mappedlength
, &font
, &scale
);
3826 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
3827 ok(mappedlength
== 0, "got %u\n", mappedlength
);
3828 ok(scale
== 1.0f
, "got %f\n", scale
);
3829 ok(font
== NULL
, "got %p\n", font
);
3831 /* zero length source */
3835 font
= (void*)0xdeadbeef;
3836 hr
= IDWriteFontFallback_MapCharacters(fallback
, &analysissource
, 0, 0, NULL
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
,
3837 DWRITE_FONT_STYLE_NORMAL
, DWRITE_FONT_STRETCH_NORMAL
, &mappedlength
, &font
, &scale
);
3838 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3839 ok(mappedlength
== 0, "got %u\n", mappedlength
);
3840 ok(scale
== 1.0f
, "got %f\n", scale
);
3841 ok(font
== NULL
, "got %p\n", font
);
3847 hr
= IDWriteFontFallback_MapCharacters(fallback
, &analysissource
, 0, 1, NULL
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
,
3848 DWRITE_FONT_STYLE_NORMAL
, DWRITE_FONT_STRETCH_NORMAL
, &mappedlength
, &font
, &scale
);
3849 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3850 ok(mappedlength
== 1, "got %u\n", mappedlength
);
3851 ok(scale
== 1.0f
, "got %f\n", scale
);
3852 ok(font
!= NULL
, "got %p\n", font
);
3853 IDWriteFont_Release(font
);
3855 /* same latin text, full length */
3860 hr
= IDWriteFontFallback_MapCharacters(fallback
, &analysissource
, 0, 3, NULL
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
,
3861 DWRITE_FONT_STYLE_NORMAL
, DWRITE_FONT_STRETCH_NORMAL
, &mappedlength
, &font
, &scale
);
3862 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3863 ok(mappedlength
== 3, "got %u\n", mappedlength
);
3864 ok(scale
== 1.0f
, "got %f\n", scale
);
3865 ok(font
!= NULL
, "got %p\n", font
);
3866 IDWriteFont_Release(font
);
3868 /* string 'a\x3058b' */
3873 hr
= IDWriteFontFallback_MapCharacters(fallback
, &analysissource
, 0, 3, NULL
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
,
3874 DWRITE_FONT_STYLE_NORMAL
, DWRITE_FONT_STRETCH_NORMAL
, &mappedlength
, &font
, &scale
);
3875 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3876 ok(mappedlength
== 1, "got %u\n", mappedlength
);
3877 ok(scale
== 1.0f
, "got %f\n", scale
);
3878 ok(font
!= NULL
, "got %p\n", font
);
3879 IDWriteFont_Release(font
);
3885 hr
= IDWriteFontFallback_MapCharacters(fallback
, &analysissource
, 1, 2, NULL
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
,
3886 DWRITE_FONT_STYLE_NORMAL
, DWRITE_FONT_STRETCH_NORMAL
, &mappedlength
, &font
, &scale
);
3887 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3888 ok(mappedlength
== 1, "got %u\n", mappedlength
);
3889 ok(scale
== 1.0f
, "got %f\n", scale
);
3890 ok(font
!= NULL
, "got %p\n", font
);
3892 /* font returned for Hiragana character, check if it supports Latin too */
3894 hr
= IDWriteFont_HasCharacter(font
, 'b', &exists
);
3895 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3896 ok(exists
, "got %d\n", exists
);
3898 IDWriteFont_Release(font
);
3900 /* Try with explicit collection, Tahoma will be forced. */
3906 hr
= IDWriteFontFallback_MapCharacters(fallback
, &analysissource
, 0, 3, &fallbackcollection
, g_blahfontW
, DWRITE_FONT_WEIGHT_NORMAL
,
3907 DWRITE_FONT_STYLE_NORMAL
, DWRITE_FONT_STRETCH_NORMAL
, &mappedlength
, &font
, &scale
);
3908 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3909 ok(mappedlength
== 1, "got %u\n", mappedlength
);
3910 ok(scale
== 1.0f
, "got %f\n", scale
);
3911 ok(font
!= NULL
, "got %p\n", font
);
3914 hr
= IDWriteFont_GetInformationalStrings(font
, DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES
, &strings
, &exists
);
3915 ok(hr
== S_OK
&& exists
, "got 0x%08x, exists %d\n", hr
, exists
);
3916 hr
= IDWriteLocalizedStrings_GetString(strings
, 0, buffW
, sizeof(buffW
)/sizeof(WCHAR
));
3917 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3918 ok(!lstrcmpW(buffW
, tahomaW
), "%s\n", wine_dbgstr_w(buffW
));
3919 IDWriteLocalizedStrings_Release(strings
);
3921 IDWriteFont_Release(font
);
3923 /* 2. Hiragana character, force Tahoma font does not support Japanese */
3928 hr
= IDWriteFontFallback_MapCharacters(fallback
, &analysissource
, 1, 1, &fallbackcollection
, g_blahfontW
, DWRITE_FONT_WEIGHT_NORMAL
,
3929 DWRITE_FONT_STYLE_NORMAL
, DWRITE_FONT_STRETCH_NORMAL
, &mappedlength
, &font
, &scale
);
3930 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3931 ok(mappedlength
== 1, "got %u\n", mappedlength
);
3932 ok(scale
== 1.0f
, "got %f\n", scale
);
3933 ok(font
!= NULL
, "got %p\n", font
);
3936 hr
= IDWriteFont_GetInformationalStrings(font
, DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES
, &strings
, &exists
);
3937 ok(hr
== S_OK
&& exists
, "got 0x%08x, exists %d\n", hr
, exists
);
3938 hr
= IDWriteLocalizedStrings_GetString(strings
, 0, buffW
, sizeof(buffW
)/sizeof(WCHAR
));
3939 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3940 ok(lstrcmpW(buffW
, tahomaW
), "%s\n", wine_dbgstr_w(buffW
));
3941 IDWriteLocalizedStrings_Release(strings
);
3943 IDWriteFont_Release(font
);
3944 IDWriteFontFallback_Release(fallback
);
3946 IDWriteFactory2_Release(factory2
);
3949 static void test_FontFallbackBuilder(void)
3951 static const WCHAR localeW
[] = {'l','o','c','a','l','e',0};
3952 static const WCHAR strW
[] = {'A',0};
3953 IDWriteFontFallbackBuilder
*builder
;
3954 IDWriteFontFallback
*fallback
;
3955 DWRITE_UNICODE_RANGE range
;
3956 IDWriteFactory2
*factory2
;
3957 IDWriteFactory
*factory
;
3958 const WCHAR
*familyW
;
3959 UINT32 mappedlength
;
3964 factory
= create_factory();
3966 hr
= IDWriteFactory_QueryInterface(factory
, &IID_IDWriteFactory2
, (void**)&factory2
);
3967 IDWriteFactory_Release(factory
);
3970 hr
= IDWriteFactory2_CreateFontFallbackBuilder(factory2
, &builder
);
3973 skip("IDWriteFontFallbackBuilder is not supported\n");
3977 hr
= IDWriteFontFallbackBuilder_CreateFontFallback(builder
, &fallback
);
3978 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3980 hr
= IDWriteFontFallbackBuilder_AddMapping(builder
, NULL
, 0, NULL
, 0, NULL
, NULL
, NULL
, 0.0f
);
3981 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
3985 hr
= IDWriteFontFallbackBuilder_AddMapping(builder
, &range
, 0, NULL
, 0, NULL
, NULL
, NULL
, 0.0f
);
3986 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
3988 hr
= IDWriteFontFallbackBuilder_AddMapping(builder
, &range
, 0, NULL
, 0, NULL
, NULL
, NULL
, 1.0f
);
3989 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
3991 /* negative scaling factor */
3992 range
.first
= range
.last
= 0;
3993 familyW
= g_blahfontW
;
3994 hr
= IDWriteFontFallbackBuilder_AddMapping(builder
, &range
, 1, &familyW
, 1, NULL
, NULL
, NULL
, -1.0f
);
3995 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
3998 range
.first
= range
.last
= 0;
3999 familyW
= g_blahfontW
;
4000 hr
= IDWriteFontFallbackBuilder_AddMapping(builder
, &range
, 1, &familyW
, 1, NULL
, NULL
, NULL
, 1.0f
);
4001 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4003 range
.first
= range
.last
= 0;
4004 hr
= IDWriteFontFallbackBuilder_AddMapping(builder
, &range
, 1, &familyW
, 1, NULL
, NULL
, NULL
, 2.0f
);
4005 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4007 range
.first
= range
.last
= 'A';
4008 hr
= IDWriteFontFallbackBuilder_AddMapping(builder
, &range
, 1, &familyW
, 1, NULL
, NULL
, NULL
, 3.0f
);
4009 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4013 hr
= IDWriteFontFallbackBuilder_AddMapping(builder
, &range
, 1, &familyW
, 1, NULL
, NULL
, NULL
, 4.0f
);
4014 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4016 if (0) /* crashes on native */
4017 hr
= IDWriteFontFallbackBuilder_CreateFontFallback(builder
, NULL
);
4019 hr
= IDWriteFontFallbackBuilder_CreateFontFallback(builder
, &fallback
);
4020 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4022 /* fallback font missing from system collection */
4026 font
= (void*)0xdeadbeef;
4027 hr
= IDWriteFontFallback_MapCharacters(fallback
, &analysissource
, 0, 1, NULL
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
,
4028 DWRITE_FONT_STYLE_NORMAL
, DWRITE_FONT_STRETCH_NORMAL
, &mappedlength
, &font
, &scale
);
4029 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4030 ok(mappedlength
== 1, "got %u\n", mappedlength
);
4031 ok(scale
== 1.0f
, "got %f\n", scale
);
4032 ok(font
== NULL
, "got %p\n", font
);
4034 IDWriteFontFallback_Release(fallback
);
4036 /* remap with custom collection */
4037 range
.first
= range
.last
= 'A';
4038 hr
= IDWriteFontFallbackBuilder_AddMapping(builder
, &range
, 1, &familyW
, 1, &fallbackcollection
, NULL
, NULL
, 5.0f
);
4039 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4041 hr
= IDWriteFontFallbackBuilder_CreateFontFallback(builder
, &fallback
);
4042 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4048 hr
= IDWriteFontFallback_MapCharacters(fallback
, &analysissource
, 0, 1, NULL
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
,
4049 DWRITE_FONT_STYLE_NORMAL
, DWRITE_FONT_STRETCH_NORMAL
, &mappedlength
, &font
, &scale
);
4050 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4051 ok(mappedlength
== 1, "got %u\n", mappedlength
);
4052 ok(scale
== 5.0f
, "got %f\n", scale
);
4053 ok(font
!= NULL
, "got %p\n", font
);
4054 IDWriteFont_Release(font
);
4056 IDWriteFontFallback_Release(fallback
);
4060 hr
= IDWriteFontFallbackBuilder_AddMapping(builder
, &range
, 1, &familyW
, 1, &fallbackcollection
, NULL
, NULL
, 6.0f
);
4061 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4063 hr
= IDWriteFontFallbackBuilder_CreateFontFallback(builder
, &fallback
);
4064 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4070 hr
= IDWriteFontFallback_MapCharacters(fallback
, &analysissource
, 0, 1, NULL
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
,
4071 DWRITE_FONT_STYLE_NORMAL
, DWRITE_FONT_STRETCH_NORMAL
, &mappedlength
, &font
, &scale
);
4072 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4073 ok(mappedlength
== 1, "got %u\n", mappedlength
);
4074 ok(scale
== 5.0f
, "got %f\n", scale
);
4075 ok(font
!= NULL
, "got %p\n", font
);
4076 IDWriteFont_Release(font
);
4078 IDWriteFontFallback_Release(fallback
);
4080 /* explicit locale */
4083 hr
= IDWriteFontFallbackBuilder_AddMapping(builder
, &range
, 1, &familyW
, 1, &fallbackcollection
, localeW
, NULL
, 6.0f
);
4084 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4086 hr
= IDWriteFontFallbackBuilder_CreateFontFallback(builder
, &fallback
);
4087 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4093 hr
= IDWriteFontFallback_MapCharacters(fallback
, &analysissource
, 0, 1, NULL
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
,
4094 DWRITE_FONT_STYLE_NORMAL
, DWRITE_FONT_STRETCH_NORMAL
, &mappedlength
, &font
, &scale
);
4095 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4096 ok(mappedlength
== 1, "got %u\n", mappedlength
);
4097 ok(scale
== 5.0f
, "got %f\n", scale
);
4098 ok(font
!= NULL
, "got %p\n", font
);
4099 IDWriteFont_Release(font
);
4101 IDWriteFontFallbackBuilder_Release(builder
);
4102 IDWriteFactory2_Release(factory2
);
4105 static void test_SetTypography(void)
4107 static const WCHAR strW
[] = {'a','f','i','b',0};
4108 IDWriteTypography
*typography
, *typography2
;
4109 IDWriteTextFormat
*format
;
4110 IDWriteTextLayout
*layout
;
4111 DWRITE_TEXT_RANGE range
;
4112 IDWriteFactory
*factory
;
4115 factory
= create_factory();
4117 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
4118 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
4119 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4121 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 1000.0, 1000.0, &layout
);
4122 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4123 IDWriteTextFormat_Release(format
);
4125 hr
= IDWriteFactory_CreateTypography(factory
, &typography
);
4126 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4128 EXPECT_REF(typography
, 1);
4129 range
.startPosition
= 0;
4131 hr
= IDWriteTextLayout_SetTypography(layout
, typography
, range
);
4132 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4133 EXPECT_REF(typography
, 2);
4135 hr
= IDWriteTextLayout_GetTypography(layout
, 0, &typography2
, NULL
);
4136 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4137 ok(typography2
== typography
, "got %p, expected %p\n", typography2
, typography
);
4138 IDWriteTypography_Release(typography2
);
4139 IDWriteTypography_Release(typography
);
4141 hr
= IDWriteFactory_CreateTypography(factory
, &typography2
);
4142 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4144 range
.startPosition
= 0;
4146 hr
= IDWriteTextLayout_SetTypography(layout
, typography2
, range
);
4147 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4148 EXPECT_REF(typography2
, 2);
4149 IDWriteTypography_Release(typography2
);
4151 hr
= IDWriteTextLayout_GetTypography(layout
, 0, &typography
, &range
);
4152 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4153 ok(range
.length
== 1, "got %u\n", range
.length
);
4155 IDWriteTypography_Release(typography
);
4157 IDWriteTextLayout_Release(layout
);
4158 IDWriteFactory_Release(factory
);
4161 static void test_SetLastLineWrapping(void)
4163 static const WCHAR strW
[] = {'a',0};
4164 IDWriteTextLayout2
*layout2
;
4165 IDWriteTextFormat1
*format1
;
4166 IDWriteTextLayout
*layout
;
4167 IDWriteTextFormat
*format
;
4168 IDWriteFactory
*factory
;
4172 factory
= create_factory();
4174 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
4175 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
4176 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4178 hr
= IDWriteTextFormat_QueryInterface(format
, &IID_IDWriteTextFormat1
, (void**)&format1
);
4179 IDWriteTextFormat_Release(format
);
4181 win_skip("SetLastLineWrapping() is not supported\n");
4182 IDWriteFactory_Release(factory
);
4186 ret
= IDWriteTextFormat1_GetLastLineWrapping(format1
);
4187 ok(ret
, "got %d\n", ret
);
4189 hr
= IDWriteTextFormat1_SetLastLineWrapping(format1
, FALSE
);
4190 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4192 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 1, (IDWriteTextFormat
*)format1
, 1000.0, 1000.0, &layout
);
4193 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4195 hr
= IDWriteTextLayout_QueryInterface(layout
, &IID_IDWriteTextLayout2
, (void**)&layout2
);
4196 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4197 IDWriteTextLayout_Release(layout
);
4199 ret
= IDWriteTextLayout2_GetLastLineWrapping(layout2
);
4200 ok(!ret
, "got %d\n", ret
);
4202 hr
= IDWriteTextLayout2_SetLastLineWrapping(layout2
, TRUE
);
4203 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4205 IDWriteFactory_Release(factory
);
4208 static void test_SetOpticalAlignment(void)
4210 static const WCHAR strW
[] = {'a',0};
4211 DWRITE_OPTICAL_ALIGNMENT alignment
;
4212 IDWriteTextLayout2
*layout2
;
4213 IDWriteTextFormat1
*format1
;
4214 IDWriteTextLayout
*layout
;
4215 IDWriteTextFormat
*format
;
4216 IDWriteFactory
*factory
;
4219 factory
= create_factory();
4221 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
4222 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
4223 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4225 hr
= IDWriteTextFormat_QueryInterface(format
, &IID_IDWriteTextFormat1
, (void**)&format1
);
4226 IDWriteTextFormat_Release(format
);
4228 win_skip("SetOpticalAlignment() is not supported\n");
4229 IDWriteFactory_Release(factory
);
4233 alignment
= IDWriteTextFormat1_GetOpticalAlignment(format1
);
4234 ok(alignment
== DWRITE_OPTICAL_ALIGNMENT_NONE
, "got %d\n", alignment
);
4236 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 1, (IDWriteTextFormat
*)format1
, 1000.0, 1000.0, &layout
);
4237 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4239 hr
= IDWriteTextLayout_QueryInterface(layout
, &IID_IDWriteTextLayout2
, (void**)&layout2
);
4240 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4241 IDWriteTextLayout_Release(layout
);
4242 IDWriteTextFormat1_Release(format1
);
4244 alignment
= IDWriteTextLayout2_GetOpticalAlignment(layout2
);
4245 ok(alignment
== DWRITE_OPTICAL_ALIGNMENT_NONE
, "got %d\n", alignment
);
4247 hr
= IDWriteTextLayout2_QueryInterface(layout2
, &IID_IDWriteTextFormat1
, (void**)&format1
);
4248 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4250 alignment
= IDWriteTextFormat1_GetOpticalAlignment(format1
);
4251 ok(alignment
== DWRITE_OPTICAL_ALIGNMENT_NONE
, "got %d\n", alignment
);
4253 hr
= IDWriteTextLayout2_SetOpticalAlignment(layout2
, DWRITE_OPTICAL_ALIGNMENT_NO_SIDE_BEARINGS
);
4254 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4256 hr
= IDWriteTextLayout2_SetOpticalAlignment(layout2
, DWRITE_OPTICAL_ALIGNMENT_NO_SIDE_BEARINGS
+1);
4257 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
4259 alignment
= IDWriteTextFormat1_GetOpticalAlignment(format1
);
4260 ok(alignment
== DWRITE_OPTICAL_ALIGNMENT_NO_SIDE_BEARINGS
, "got %d\n", alignment
);
4262 hr
= IDWriteTextFormat1_SetOpticalAlignment(format1
, DWRITE_OPTICAL_ALIGNMENT_NONE
);
4263 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4265 hr
= IDWriteTextFormat1_SetOpticalAlignment(format1
, DWRITE_OPTICAL_ALIGNMENT_NO_SIDE_BEARINGS
+1);
4266 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
4268 alignment
= IDWriteTextLayout2_GetOpticalAlignment(layout2
);
4269 ok(alignment
== DWRITE_OPTICAL_ALIGNMENT_NONE
, "got %d\n", alignment
);
4271 IDWriteTextLayout2_Release(layout2
);
4272 IDWriteTextFormat1_Release(format1
);
4273 IDWriteFactory_Release(factory
);
4276 static const struct drawcall_entry drawunderline_seq
[] = {
4277 { DRAW_GLYPHRUN
, {'a','e',0x0300,0} }, /* reported runs can't mix different underline values */
4278 { DRAW_GLYPHRUN
, {'d',0} },
4283 static void test_SetUnderline(void)
4285 static const WCHAR strW
[] = {'a','e',0x0300,'d',0}; /* accent grave */
4286 DWRITE_CLUSTER_METRICS clusters
[4];
4287 IDWriteTextFormat
*format
;
4288 IDWriteTextLayout
*layout
;
4289 DWRITE_TEXT_RANGE range
;
4290 IDWriteFactory
*factory
;
4294 factory
= create_factory();
4296 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
4297 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
4298 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4300 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 1000.0, 1000.0, &layout
);
4301 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4302 IDWriteTextFormat_Release(format
);
4305 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, clusters
, sizeof(clusters
)/sizeof(clusters
[0]), &count
);
4306 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4308 ok(count
== 3, "got %u\n", count
);
4310 range
.startPosition
= 0;
4312 hr
= IDWriteTextLayout_SetUnderline(layout
, TRUE
, range
);
4313 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4316 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, clusters
, sizeof(clusters
)/sizeof(clusters
[0]), &count
);
4317 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4319 ok(count
== 3, "got %u\n", count
);
4321 flush_sequence(sequences
, RENDERER_ID
);
4322 hr
= IDWriteTextLayout_Draw(layout
, NULL
, &testrenderer
, 0.0, 0.0);
4323 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4324 ok_sequence(sequences
, RENDERER_ID
, drawunderline_seq
, "draw underline test", TRUE
);
4326 IDWriteTextLayout_Release(layout
);
4327 IDWriteFactory_Release(factory
);
4332 static const WCHAR ctrlstrW
[] = {0x202a,0};
4333 IDWriteFactory
*factory
;
4335 if (!(factory
= create_factory())) {
4336 win_skip("failed to create factory\n");
4340 /* actual script ids are not fixed */
4341 get_script_analysis(ctrlstrW
, 1, &g_control_sa
);
4343 init_call_sequences(sequences
, NUM_CALL_SEQUENCES
);
4344 init_call_sequences(expected_seq
, 1);
4346 test_CreateTextLayout();
4347 test_CreateGdiCompatibleTextLayout();
4348 test_CreateTextFormat();
4349 test_GetLocaleName();
4350 test_CreateEllipsisTrimmingSign();
4352 test_SetInlineObject();
4355 test_GetClusterMetrics();
4356 test_SetLocaleName();
4357 test_SetPairKerning();
4358 test_SetVerticalGlyphOrientation();
4360 test_DetermineMinWidth();
4362 test_SetFontFamilyName();
4363 test_SetFontStyle();
4364 test_SetFontStretch();
4365 test_SetStrikethrough();
4367 test_SetFlowDirection();
4368 test_SetDrawingEffect();
4369 test_GetLineMetrics();
4370 test_SetTextAlignment();
4371 test_SetParagraphAlignment();
4372 test_SetReadingDirection();
4373 test_pixelsnapping();
4374 test_SetWordWrapping();
4375 test_MapCharacters();
4376 test_FontFallbackBuilder();
4377 test_SetTypography();
4378 test_SetLastLineWrapping();
4379 test_SetOpticalAlignment();
4380 test_SetUnderline();
4382 IDWriteFactory_Release(factory
);