2 * Text layout/format tests
4 * Copyright 2012, 2014-2016 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
30 #include "wine/test.h"
32 static const WCHAR tahomaW
[] = {'T','a','h','o','m','a',0};
33 static const WCHAR enusW
[] = {'e','n','-','u','s',0};
35 static DWRITE_SCRIPT_ANALYSIS g_sa
;
37 /* test IDWriteTextAnalysisSink */
38 static HRESULT WINAPI
analysissink_QueryInterface(IDWriteTextAnalysisSink
*iface
, REFIID riid
, void **obj
)
40 if (IsEqualIID(riid
, &IID_IDWriteTextAnalysisSink
) || IsEqualIID(riid
, &IID_IUnknown
))
50 static ULONG WINAPI
analysissink_AddRef(IDWriteTextAnalysisSink
*iface
)
55 static ULONG WINAPI
analysissink_Release(IDWriteTextAnalysisSink
*iface
)
60 static HRESULT WINAPI
analysissink_SetScriptAnalysis(IDWriteTextAnalysisSink
*iface
,
61 UINT32 position
, UINT32 length
, DWRITE_SCRIPT_ANALYSIS
const* sa
)
67 static HRESULT WINAPI
analysissink_SetLineBreakpoints(IDWriteTextAnalysisSink
*iface
,
68 UINT32 position
, UINT32 length
, DWRITE_LINE_BREAKPOINT
const* breakpoints
)
70 ok(0, "unexpected call\n");
74 static HRESULT WINAPI
analysissink_SetBidiLevel(IDWriteTextAnalysisSink
*iface
,
75 UINT32 position
, UINT32 length
, UINT8 explicitLevel
, UINT8 resolvedLevel
)
77 ok(0, "unexpected\n");
81 static HRESULT WINAPI
analysissink_SetNumberSubstitution(IDWriteTextAnalysisSink
*iface
,
82 UINT32 position
, UINT32 length
, IDWriteNumberSubstitution
* substitution
)
84 ok(0, "unexpected\n");
88 static IDWriteTextAnalysisSinkVtbl analysissinkvtbl
= {
89 analysissink_QueryInterface
,
92 analysissink_SetScriptAnalysis
,
93 analysissink_SetLineBreakpoints
,
94 analysissink_SetBidiLevel
,
95 analysissink_SetNumberSubstitution
98 static IDWriteTextAnalysisSink analysissink
= { &analysissinkvtbl
};
100 /* test IDWriteTextAnalysisSource */
101 static HRESULT WINAPI
analysissource_QueryInterface(IDWriteTextAnalysisSource
*iface
,
102 REFIID riid
, void **obj
)
104 if (IsEqualIID(riid
, &IID_IDWriteTextAnalysisSource
) || IsEqualIID(riid
, &IID_IUnknown
)) {
106 IDWriteTextAnalysisSource_AddRef(iface
);
109 return E_NOINTERFACE
;
112 static ULONG WINAPI
analysissource_AddRef(IDWriteTextAnalysisSource
*iface
)
117 static ULONG WINAPI
analysissource_Release(IDWriteTextAnalysisSource
*iface
)
122 static const WCHAR
*g_source
;
124 static HRESULT WINAPI
analysissource_GetTextAtPosition(IDWriteTextAnalysisSource
*iface
,
125 UINT32 position
, WCHAR
const** text
, UINT32
* text_len
)
127 if (position
>= lstrlenW(g_source
))
134 *text
= &g_source
[position
];
135 *text_len
= lstrlenW(g_source
) - position
;
141 static HRESULT WINAPI
analysissource_GetTextBeforePosition(IDWriteTextAnalysisSource
*iface
,
142 UINT32 position
, WCHAR
const** text
, UINT32
* text_len
)
144 ok(0, "unexpected\n");
148 static DWRITE_READING_DIRECTION WINAPI
analysissource_GetParagraphReadingDirection(
149 IDWriteTextAnalysisSource
*iface
)
151 ok(0, "unexpected\n");
152 return DWRITE_READING_DIRECTION_RIGHT_TO_LEFT
;
155 static HRESULT WINAPI
analysissource_GetLocaleName(IDWriteTextAnalysisSource
*iface
,
156 UINT32 position
, UINT32
* text_len
, WCHAR
const** locale
)
163 static HRESULT WINAPI
analysissource_GetNumberSubstitution(IDWriteTextAnalysisSource
*iface
,
164 UINT32 position
, UINT32
* text_len
, IDWriteNumberSubstitution
**substitution
)
166 ok(0, "unexpected\n");
170 static IDWriteTextAnalysisSourceVtbl analysissourcevtbl
= {
171 analysissource_QueryInterface
,
172 analysissource_AddRef
,
173 analysissource_Release
,
174 analysissource_GetTextAtPosition
,
175 analysissource_GetTextBeforePosition
,
176 analysissource_GetParagraphReadingDirection
,
177 analysissource_GetLocaleName
,
178 analysissource_GetNumberSubstitution
181 static IDWriteTextAnalysisSource analysissource
= { &analysissourcevtbl
};
183 static IDWriteFactory
*create_factory(void)
185 IDWriteFactory
*factory
;
186 HRESULT hr
= DWriteCreateFactory(DWRITE_FACTORY_TYPE_ISOLATED
, &IID_IDWriteFactory
, (IUnknown
**)&factory
);
187 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
191 /* obvious limitation is that only last script data is returned, so this
192 helper is suitable for single script strings only */
193 static void get_script_analysis(const WCHAR
*str
, UINT32 len
, DWRITE_SCRIPT_ANALYSIS
*sa
)
195 IDWriteTextAnalyzer
*analyzer
;
196 IDWriteFactory
*factory
;
201 factory
= create_factory();
202 hr
= IDWriteFactory_CreateTextAnalyzer(factory
, &analyzer
);
203 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
205 hr
= IDWriteTextAnalyzer_AnalyzeScript(analyzer
, &analysissource
, 0, len
, &analysissink
);
206 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
209 IDWriteFactory_Release(factory
);
212 #define EXPECT_REF(obj,ref) _expect_ref((IUnknown*)obj, ref, __LINE__)
213 static void _expect_ref(IUnknown
* obj
, ULONG ref
, int line
)
215 ULONG rc
= IUnknown_AddRef(obj
);
216 IUnknown_Release(obj
);
217 ok_(__FILE__
,line
)(rc
-1 == ref
, "expected refcount %d, got %d\n", ref
, rc
-1);
220 enum drawcall_modifiers_kind
{
227 DRAW_STRIKETHROUGH
= 2,
230 DRAW_TOTAL_KINDS
= 5,
231 DRAW_KINDS_MASK
= 0xff
234 static const char *get_draw_kind_name(unsigned short kind
)
236 static const char *kind_names
[] = {
245 "STRIKETHROUGH|EFFECT",
249 if ((kind
& DRAW_KINDS_MASK
) > DRAW_LAST_KIND
)
251 return (kind
& DRAW_EFFECT
) ? kind_names
[(kind
& DRAW_KINDS_MASK
) + DRAW_TOTAL_KINDS
] :
255 struct drawcall_entry
{
256 enum drawcall_kind kind
;
257 WCHAR string
[10]; /* only meaningful for DrawGlyphRun() */
258 WCHAR locale
[LOCALE_NAME_MAX_LENGTH
];
261 struct drawcall_sequence
265 struct drawcall_entry
*sequence
;
268 struct drawtestcontext
{
276 #define NUM_CALL_SEQUENCES 1
277 #define RENDERER_ID 0
278 static struct drawcall_sequence
*sequences
[NUM_CALL_SEQUENCES
];
279 static struct drawcall_sequence
*expected_seq
[1];
281 static void add_call(struct drawcall_sequence
**seq
, int sequence_index
, const struct drawcall_entry
*call
)
283 struct drawcall_sequence
*call_seq
= seq
[sequence_index
];
285 if (!call_seq
->sequence
) {
287 call_seq
->sequence
= HeapAlloc(GetProcessHeap(), 0, call_seq
->size
* sizeof (struct drawcall_entry
));
290 if (call_seq
->count
== call_seq
->size
) {
292 call_seq
->sequence
= HeapReAlloc(GetProcessHeap(), 0,
294 call_seq
->size
* sizeof (struct drawcall_entry
));
297 assert(call_seq
->sequence
);
298 call_seq
->sequence
[call_seq
->count
++] = *call
;
301 static inline void flush_sequence(struct drawcall_sequence
**seg
, int sequence_index
)
303 struct drawcall_sequence
*call_seq
= seg
[sequence_index
];
305 HeapFree(GetProcessHeap(), 0, call_seq
->sequence
);
306 call_seq
->sequence
= NULL
;
307 call_seq
->count
= call_seq
->size
= 0;
310 static inline void flush_sequences(struct drawcall_sequence
**seq
, int n
)
313 for (i
= 0; i
< n
; i
++)
314 flush_sequence(seq
, i
);
317 static void init_call_sequences(struct drawcall_sequence
**seq
, int n
)
321 for (i
= 0; i
< n
; i
++)
322 seq
[i
] = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(struct drawcall_sequence
));
325 static void ok_sequence_(struct drawcall_sequence
**seq
, int sequence_index
,
326 const struct drawcall_entry
*expected
, const char *context
, BOOL todo
,
327 const char *file
, int line
)
329 static const struct drawcall_entry end_of_sequence
= { DRAW_LAST_KIND
};
330 struct drawcall_sequence
*call_seq
= seq
[sequence_index
];
331 const struct drawcall_entry
*actual
, *sequence
;
334 add_call(seq
, sequence_index
, &end_of_sequence
);
336 sequence
= call_seq
->sequence
;
339 while (expected
->kind
!= DRAW_LAST_KIND
&& actual
->kind
!= DRAW_LAST_KIND
) {
340 if (expected
->kind
!= actual
->kind
) {
344 ok_(file
, line
) (0, "%s: call %s was expected, but got call %s instead\n",
345 context
, get_draw_kind_name(expected
->kind
), get_draw_kind_name(actual
->kind
));
347 flush_sequence(seq
, sequence_index
);
351 ok_(file
, line
) (0, "%s: call %s was expected, but got call %s instead\n",
352 context
, get_draw_kind_name(expected
->kind
), get_draw_kind_name(actual
->kind
));
354 else if ((expected
->kind
& DRAW_KINDS_MASK
) == DRAW_GLYPHRUN
) {
355 int cmp
= lstrcmpW(expected
->string
, actual
->string
);
356 if (cmp
!= 0 && todo
) {
359 ok_(file
, line
) (0, "%s: glyphrun string %s was expected, but got %s instead\n",
360 context
, wine_dbgstr_w(expected
->string
), wine_dbgstr_w(actual
->string
));
363 ok_(file
, line
) (cmp
== 0, "%s: glyphrun string %s was expected, but got %s instead\n",
364 context
, wine_dbgstr_w(expected
->string
), wine_dbgstr_w(actual
->string
));
366 else if ((expected
->kind
& DRAW_KINDS_MASK
) == DRAW_UNDERLINE
) {
367 int cmp
= lstrcmpW(expected
->locale
, actual
->locale
);
368 if (cmp
!= 0 && todo
) {
371 ok_(file
, line
) (0, "%s: underline locale %s was expected, but got %s instead\n",
372 context
, wine_dbgstr_w(expected
->locale
), wine_dbgstr_w(actual
->locale
));
375 ok_(file
, line
) (cmp
== 0, "%s: underline locale %s was expected, but got %s instead\n",
376 context
, wine_dbgstr_w(expected
->locale
), wine_dbgstr_w(actual
->locale
));
384 if (expected
->kind
!= DRAW_LAST_KIND
|| actual
->kind
!= DRAW_LAST_KIND
) {
386 ok_(file
, line
) (0, "%s: the call sequence is not complete: expected %s - actual %s\n",
387 context
, get_draw_kind_name(expected
->kind
), get_draw_kind_name(actual
->kind
));
391 else if (expected
->kind
!= DRAW_LAST_KIND
|| actual
->kind
!= DRAW_LAST_KIND
)
392 ok_(file
, line
) (0, "%s: the call sequence is not complete: expected %s - actual %s\n",
393 context
, get_draw_kind_name(expected
->kind
), get_draw_kind_name(actual
->kind
));
395 if (todo
&& !failcount
) /* succeeded yet marked todo */
397 ok_(file
, line
)(1, "%s: marked \"todo_wine\" but succeeds\n", context
);
399 flush_sequence(seq
, sequence_index
);
402 #define ok_sequence(seq, index, exp, contx, todo) \
403 ok_sequence_(seq, index, (exp), (contx), (todo), __FILE__, __LINE__)
405 static HRESULT WINAPI
testrenderer_QI(IDWriteTextRenderer
*iface
, REFIID riid
, void **obj
)
407 if (IsEqualIID(riid
, &IID_IDWriteTextRenderer
) ||
408 IsEqualIID(riid
, &IID_IDWritePixelSnapping
) ||
409 IsEqualIID(riid
, &IID_IUnknown
)
417 /* IDWriteTextRenderer1 overrides drawing calls, ignore for now */
418 if (IsEqualIID(riid
, &IID_IDWriteTextRenderer1
))
419 return E_NOINTERFACE
;
421 ok(0, "unexpected QI %s\n", wine_dbgstr_guid(riid
));
422 return E_NOINTERFACE
;
425 static ULONG WINAPI
testrenderer_AddRef(IDWriteTextRenderer
*iface
)
430 static ULONG WINAPI
testrenderer_Release(IDWriteTextRenderer
*iface
)
435 struct renderer_context
{
437 BOOL use_gdi_natural
;
438 BOOL snapping_disabled
;
445 static HRESULT WINAPI
testrenderer_IsPixelSnappingDisabled(IDWriteTextRenderer
*iface
,
446 void *context
, BOOL
*disabled
)
448 struct renderer_context
*ctxt
= (struct renderer_context
*)context
;
450 *disabled
= ctxt
->snapping_disabled
;
456 static HRESULT WINAPI
testrenderer_GetCurrentTransform(IDWriteTextRenderer
*iface
,
457 void *context
, DWRITE_MATRIX
*m
)
459 struct renderer_context
*ctxt
= (struct renderer_context
*)context
;
460 ok(!ctxt
->snapping_disabled
, "expected enabled snapping\n");
465 static HRESULT WINAPI
testrenderer_GetPixelsPerDip(IDWriteTextRenderer
*iface
,
466 void *context
, FLOAT
*pixels_per_dip
)
468 struct renderer_context
*ctxt
= (struct renderer_context
*)context
;
469 *pixels_per_dip
= ctxt
->ppdip
;
473 #define TEST_MEASURING_MODE(ctxt, mode) test_measuring_mode(ctxt, mode, __LINE__)
474 static void test_measuring_mode(const struct renderer_context
*ctxt
, DWRITE_MEASURING_MODE mode
, int line
)
476 if (ctxt
->gdicompat
) {
477 if (ctxt
->use_gdi_natural
)
478 ok_(__FILE__
, line
)(mode
== DWRITE_MEASURING_MODE_GDI_NATURAL
, "got %d\n", mode
);
480 ok_(__FILE__
, line
)(mode
== DWRITE_MEASURING_MODE_GDI_CLASSIC
, "got %d\n", mode
);
483 ok_(__FILE__
, line
)(mode
== DWRITE_MEASURING_MODE_NATURAL
, "got %d\n", mode
);
486 static HRESULT WINAPI
testrenderer_DrawGlyphRun(IDWriteTextRenderer
*iface
,
488 FLOAT baselineOriginX
,
489 FLOAT baselineOriginY
,
490 DWRITE_MEASURING_MODE mode
,
491 DWRITE_GLYPH_RUN
const *run
,
492 DWRITE_GLYPH_RUN_DESCRIPTION
const *descr
,
495 struct renderer_context
*ctxt
= (struct renderer_context
*)context
;
496 struct drawcall_entry entry
;
497 DWRITE_SCRIPT_ANALYSIS sa
;
500 TEST_MEASURING_MODE(ctxt
, mode
);
501 ctxt
->originX
= baselineOriginX
;
502 ctxt
->originY
= baselineOriginY
;
505 ok(descr
->stringLength
< sizeof(entry
.string
)/sizeof(WCHAR
), "string is too long\n");
506 if (descr
->stringLength
&& descr
->stringLength
< sizeof(entry
.string
)/sizeof(WCHAR
)) {
507 memcpy(entry
.string
, descr
->string
, descr
->stringLength
*sizeof(WCHAR
));
508 entry
.string
[descr
->stringLength
] = 0;
513 /* see what's reported for control codes runs */
514 get_script_analysis(descr
->string
, descr
->stringLength
, &sa
);
515 if (sa
.shapes
== DWRITE_SCRIPT_SHAPES_NO_VISUAL
) {
518 /* glyphs are not reported at all for control code runs */
519 ok(run
->glyphCount
== 0, "got %u\n", run
->glyphCount
);
520 ok(run
->glyphAdvances
!= NULL
, "advances array %p\n", run
->glyphAdvances
);
521 ok(run
->glyphOffsets
!= NULL
, "offsets array %p\n", run
->glyphOffsets
);
522 ok(run
->fontFace
!= NULL
, "got %p\n", run
->fontFace
);
523 /* text positions are still valid */
524 ok(descr
->string
!= NULL
, "got string %p\n", descr
->string
);
525 ok(descr
->stringLength
> 0, "got string length %u\n", descr
->stringLength
);
526 ok(descr
->clusterMap
!= NULL
, "clustermap %p\n", descr
->clusterMap
);
527 for (i
= 0; i
< descr
->stringLength
; i
++)
528 ok(descr
->clusterMap
[i
] == i
, "got %u\n", descr
->clusterMap
[i
]);
531 entry
.kind
= DRAW_GLYPHRUN
;
533 entry
.kind
|= DRAW_EFFECT
;
534 add_call(sequences
, RENDERER_ID
, &entry
);
538 static HRESULT WINAPI
testrenderer_DrawUnderline(IDWriteTextRenderer
*iface
,
540 FLOAT baselineOriginX
,
541 FLOAT baselineOriginY
,
542 DWRITE_UNDERLINE
const* underline
,
545 struct renderer_context
*ctxt
= (struct renderer_context
*)context
;
546 struct drawcall_entry entry
;
549 TEST_MEASURING_MODE(ctxt
, underline
->measuringMode
);
551 entry
.kind
= DRAW_UNDERLINE
;
553 entry
.kind
|= DRAW_EFFECT
;
554 lstrcpyW(entry
.locale
, underline
->localeName
);
555 add_call(sequences
, RENDERER_ID
, &entry
);
559 static HRESULT WINAPI
testrenderer_DrawStrikethrough(IDWriteTextRenderer
*iface
,
561 FLOAT baselineOriginX
,
562 FLOAT baselineOriginY
,
563 DWRITE_STRIKETHROUGH
const* strikethrough
,
566 struct renderer_context
*ctxt
= (struct renderer_context
*)context
;
567 struct drawcall_entry entry
;
570 TEST_MEASURING_MODE(ctxt
, strikethrough
->measuringMode
);
572 entry
.kind
= DRAW_STRIKETHROUGH
;
574 entry
.kind
|= DRAW_EFFECT
;
575 add_call(sequences
, RENDERER_ID
, &entry
);
579 static HRESULT WINAPI
testrenderer_DrawInlineObject(IDWriteTextRenderer
*iface
,
583 IDWriteInlineObject
*object
,
588 struct drawcall_entry entry
;
589 entry
.kind
= DRAW_INLINE
;
591 entry
.kind
|= DRAW_EFFECT
;
592 add_call(sequences
, RENDERER_ID
, &entry
);
596 static const IDWriteTextRendererVtbl testrenderervtbl
= {
599 testrenderer_Release
,
600 testrenderer_IsPixelSnappingDisabled
,
601 testrenderer_GetCurrentTransform
,
602 testrenderer_GetPixelsPerDip
,
603 testrenderer_DrawGlyphRun
,
604 testrenderer_DrawUnderline
,
605 testrenderer_DrawStrikethrough
,
606 testrenderer_DrawInlineObject
609 static IDWriteTextRenderer testrenderer
= { &testrenderervtbl
};
611 /* test IDWriteInlineObject */
612 static HRESULT WINAPI
testinlineobj_QI(IDWriteInlineObject
*iface
, REFIID riid
, void **obj
)
614 if (IsEqualIID(riid
, &IID_IDWriteInlineObject
) || IsEqualIID(riid
, &IID_IUnknown
)) {
616 IDWriteInlineObject_AddRef(iface
);
621 return E_NOINTERFACE
;
624 static ULONG WINAPI
testinlineobj_AddRef(IDWriteInlineObject
*iface
)
629 static ULONG WINAPI
testinlineobj_Release(IDWriteInlineObject
*iface
)
634 static HRESULT WINAPI
testinlineobj_Draw(IDWriteInlineObject
*iface
,
635 void* client_drawingontext
, IDWriteTextRenderer
* renderer
,
636 FLOAT originX
, FLOAT originY
, BOOL is_sideways
, BOOL is_rtl
, IUnknown
*drawing_effect
)
638 ok(0, "unexpected call\n");
642 static HRESULT WINAPI
testinlineobj_GetMetrics(IDWriteInlineObject
*iface
, DWRITE_INLINE_OBJECT_METRICS
*metrics
)
644 metrics
->width
= 123.0;
648 static HRESULT WINAPI
testinlineobj_GetOverhangMetrics(IDWriteInlineObject
*iface
, DWRITE_OVERHANG_METRICS
*overhangs
)
650 ok(0, "unexpected call\n");
654 static HRESULT WINAPI
testinlineobj_GetBreakConditions(IDWriteInlineObject
*iface
, DWRITE_BREAK_CONDITION
*before
,
655 DWRITE_BREAK_CONDITION
*after
)
657 *before
= *after
= DWRITE_BREAK_CONDITION_MUST_BREAK
;
661 static HRESULT WINAPI
testinlineobj2_GetBreakConditions(IDWriteInlineObject
*iface
, DWRITE_BREAK_CONDITION
*before
,
662 DWRITE_BREAK_CONDITION
*after
)
664 *before
= *after
= DWRITE_BREAK_CONDITION_MAY_NOT_BREAK
;
668 static IDWriteInlineObjectVtbl testinlineobjvtbl
= {
670 testinlineobj_AddRef
,
671 testinlineobj_Release
,
673 testinlineobj_GetMetrics
,
674 testinlineobj_GetOverhangMetrics
,
675 testinlineobj_GetBreakConditions
678 static IDWriteInlineObjectVtbl testinlineobjvtbl2
= {
680 testinlineobj_AddRef
,
681 testinlineobj_Release
,
683 testinlineobj_GetMetrics
,
684 testinlineobj_GetOverhangMetrics
,
685 testinlineobj2_GetBreakConditions
688 static IDWriteInlineObject testinlineobj
= { &testinlineobjvtbl
};
689 static IDWriteInlineObject testinlineobj2
= { &testinlineobjvtbl
};
690 static IDWriteInlineObject testinlineobj3
= { &testinlineobjvtbl2
};
692 static HRESULT WINAPI
testeffect_QI(IUnknown
*iface
, REFIID riid
, void **obj
)
694 if (IsEqualIID(riid
, &IID_IUnknown
)) {
696 IUnknown_AddRef(iface
);
701 return E_NOINTERFACE
;
704 static ULONG WINAPI
testeffect_AddRef(IUnknown
*iface
)
709 static ULONG WINAPI
testeffect_Release(IUnknown
*iface
)
714 static const IUnknownVtbl testeffectvtbl
= {
720 static IUnknown testeffect
= { &testeffectvtbl
};
722 static void test_CreateTextLayout(void)
724 static const WCHAR strW
[] = {'s','t','r','i','n','g',0};
725 IDWriteTextLayout2
*layout2
;
726 IDWriteTextLayout
*layout
;
727 IDWriteTextFormat
*format
;
728 IDWriteFactory
*factory
;
731 factory
= create_factory();
733 layout
= (void*)0xdeadbeef;
734 hr
= IDWriteFactory_CreateTextLayout(factory
, NULL
, 0, NULL
, 0.0, 0.0, &layout
);
735 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
736 ok(layout
== NULL
, "got %p\n", layout
);
738 layout
= (void*)0xdeadbeef;
739 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 6, NULL
, 0.0, 0.0, &layout
);
740 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
741 ok(layout
== NULL
, "got %p\n", layout
);
743 layout
= (void*)0xdeadbeef;
744 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 6, NULL
, 1.0, 0.0, &layout
);
745 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
746 ok(layout
== NULL
, "got %p\n", layout
);
748 layout
= (void*)0xdeadbeef;
749 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 6, NULL
, 0.0, 1.0, &layout
);
750 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
751 ok(layout
== NULL
, "got %p\n", layout
);
753 layout
= (void*)0xdeadbeef;
754 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 6, NULL
, 1000.0, 1000.0, &layout
);
755 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
756 ok(layout
== NULL
, "got %p\n", layout
);
758 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
759 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
760 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
762 layout
= (void*)0xdeadbeef;
763 hr
= IDWriteFactory_CreateTextLayout(factory
, NULL
, 0, format
, 100.0f
, 100.0f
, &layout
);
764 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
765 ok(layout
== NULL
, "got %p\n", layout
);
767 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 0, format
, 0.0f
, 0.0f
, &layout
);
768 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
769 IDWriteTextLayout_Release(layout
);
771 EXPECT_REF(format
, 1);
772 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 6, format
, 1000.0, 1000.0, &layout
);
773 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
774 EXPECT_REF(format
, 1);
776 hr
= IDWriteTextLayout_QueryInterface(layout
, &IID_IDWriteTextLayout2
, (void**)&layout2
);
778 IDWriteTextLayout1
*layout1
;
779 IDWriteTextFormat1
*format1
;
780 IDWriteTextFormat
*format
;
782 hr
= IDWriteTextLayout2_QueryInterface(layout2
, &IID_IDWriteTextLayout1
, (void**)&layout1
);
783 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
784 IDWriteTextLayout1_Release(layout1
);
786 EXPECT_REF(layout2
, 2);
787 hr
= IDWriteTextLayout2_QueryInterface(layout2
, &IID_IDWriteTextFormat1
, (void**)&format1
);
788 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
789 EXPECT_REF(layout2
, 3);
791 hr
= IDWriteTextLayout2_QueryInterface(layout2
, &IID_IDWriteTextFormat
, (void**)&format
);
792 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
793 ok(format
== (IDWriteTextFormat
*)format1
, "got %p, %p\n", format
, format1
);
794 ok(format
!= (IDWriteTextFormat
*)layout2
, "got %p, %p\n", format
, layout2
);
795 EXPECT_REF(layout2
, 4);
797 hr
= IDWriteTextFormat_QueryInterface(format
, &IID_IDWriteTextLayout1
, (void**)&layout1
);
798 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
799 IDWriteTextLayout1_Release(layout1
);
801 IDWriteTextFormat1_Release(format1
);
802 IDWriteTextFormat_Release(format
);
804 hr
= IDWriteTextLayout_QueryInterface(layout
, &IID_IDWriteTextFormat1
, (void**)&format1
);
805 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
806 EXPECT_REF(layout2
, 3);
808 hr
= IDWriteTextLayout_QueryInterface(layout
, &IID_IDWriteTextFormat
, (void**)&format
);
809 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
810 ok(format
== (IDWriteTextFormat
*)format1
, "got %p, %p\n", format
, format1
);
811 EXPECT_REF(layout2
, 4);
813 IDWriteTextFormat1_Release(format1
);
814 IDWriteTextFormat_Release(format
);
815 IDWriteTextLayout2_Release(layout2
);
818 win_skip("IDWriteTextLayout2 is not supported.\n");
820 IDWriteTextLayout_Release(layout
);
821 IDWriteTextFormat_Release(format
);
822 IDWriteFactory_Release(factory
);
825 static DWRITE_MATRIX layoutcreate_transforms
[] = {
826 { 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 },
827 { 1.0, 0.0, 0.0, 1.0, 0.3, 0.2 },
828 { 1.0, 0.0, 0.0, 1.0,-0.3,-0.2 },
830 { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 },
831 { 1.0, 0.0, 0.0, 0.0, 0.0, 0.0 },
832 { 1.0, 2.0, 0.5, 1.0, 0.0, 0.0 },
835 static void test_CreateGdiCompatibleTextLayout(void)
837 static const WCHAR strW
[] = {'s','t','r','i','n','g',0};
838 IDWriteTextLayout
*layout
;
839 IDWriteTextFormat
*format
;
840 IDWriteFactory
*factory
;
845 factory
= create_factory();
847 layout
= (void*)0xdeadbeef;
848 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, NULL
, 0, NULL
, 0.0, 0.0, 0.0, NULL
, FALSE
, &layout
);
849 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
850 ok(layout
== NULL
, "got %p\n", layout
);
852 layout
= (void*)0xdeadbeef;
853 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, strW
, 6, NULL
, 0.0, 0.0, 0.0, NULL
, FALSE
, &layout
);
854 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
855 ok(layout
== NULL
, "got %p\n", layout
);
857 layout
= (void*)0xdeadbeef;
858 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, strW
, 6, NULL
, 1.0, 0.0, 0.0, NULL
, FALSE
, &layout
);
859 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
860 ok(layout
== NULL
, "got %p\n", layout
);
862 layout
= (void*)0xdeadbeef;
863 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, strW
, 6, NULL
, 1.0, 0.0, 1.0, NULL
, FALSE
, &layout
);
864 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
865 ok(layout
== NULL
, "got %p\n", layout
);
867 layout
= (void*)0xdeadbeef;
868 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, strW
, 6, NULL
, 1000.0, 1000.0, 1.0, NULL
, FALSE
, &layout
);
869 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
870 ok(layout
== NULL
, "got %p\n", layout
);
872 /* create with text format */
873 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
874 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
875 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
876 EXPECT_REF(format
, 1);
878 layout
= (void*)0xdeadbeef;
879 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, NULL
, 0, format
, 100.0f
, 100.0f
, 1.0f
, NULL
, FALSE
, &layout
);
880 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
881 ok(layout
== NULL
, "got %p\n", layout
);
883 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, strW
, 6, format
, 100.0, 100.0, 1.0, NULL
, FALSE
, &layout
);
884 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
885 EXPECT_REF(format
, 1);
886 EXPECT_REF(layout
, 1);
888 IDWriteTextLayout_AddRef(layout
);
889 EXPECT_REF(format
, 1);
890 EXPECT_REF(layout
, 2);
891 IDWriteTextLayout_Release(layout
);
892 IDWriteTextLayout_Release(layout
);
894 /* zero length string is okay */
895 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, strW
, 0, format
, 100.0, 100.0, 1.0, NULL
, FALSE
, &layout
);
896 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
898 dimension
= IDWriteTextLayout_GetMaxWidth(layout
);
899 ok(dimension
== 100.0, "got %f\n", dimension
);
901 dimension
= IDWriteTextLayout_GetMaxHeight(layout
);
902 ok(dimension
== 100.0, "got %f\n", dimension
);
904 IDWriteTextLayout_Release(layout
);
906 /* negative, zero ppdip */
907 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, strW
, 1, format
, 100.0, 100.0, -1.0, NULL
, FALSE
, &layout
);
908 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
909 IDWriteTextLayout_Release(layout
);
911 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, strW
, 1, format
, 100.0, 100.0, 0.0, NULL
, FALSE
, &layout
);
912 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
913 IDWriteTextLayout_Release(layout
);
916 for (i
= 0; i
< sizeof(layoutcreate_transforms
)/sizeof(layoutcreate_transforms
[0]); i
++) {
917 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, strW
, 1, format
, 100.0, 100.0, 1.0,
918 &layoutcreate_transforms
[i
], FALSE
, &layout
);
919 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
920 IDWriteTextLayout_Release(layout
);
923 IDWriteTextFormat_Release(format
);
924 IDWriteFactory_Release(factory
);
927 static void test_CreateTextFormat(void)
929 IDWriteFontCollection
*collection
, *syscoll
;
930 DWRITE_PARAGRAPH_ALIGNMENT paralign
;
931 DWRITE_READING_DIRECTION readdir
;
932 DWRITE_WORD_WRAPPING wrapping
;
933 DWRITE_TEXT_ALIGNMENT align
;
934 DWRITE_FLOW_DIRECTION flow
;
935 DWRITE_LINE_SPACING_METHOD method
;
936 DWRITE_TRIMMING trimming
;
937 IDWriteTextFormat
*format
;
938 FLOAT spacing
, baseline
;
939 IDWriteInlineObject
*trimmingsign
;
940 IDWriteFactory
*factory
;
943 factory
= create_factory();
945 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
946 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
947 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
949 if (0) /* crashes on native */
950 hr
= IDWriteTextFormat_GetFontCollection(format
, NULL
);
953 hr
= IDWriteTextFormat_GetFontCollection(format
, &collection
);
954 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
955 ok(collection
!= NULL
, "got %p\n", collection
);
957 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &syscoll
, FALSE
);
958 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
959 ok(collection
== syscoll
, "got %p, was %p\n", syscoll
, collection
);
960 IDWriteFontCollection_Release(syscoll
);
961 IDWriteFontCollection_Release(collection
);
963 /* default format properties */
964 align
= IDWriteTextFormat_GetTextAlignment(format
);
965 ok(align
== DWRITE_TEXT_ALIGNMENT_LEADING
, "got %d\n", align
);
967 paralign
= IDWriteTextFormat_GetParagraphAlignment(format
);
968 ok(paralign
== DWRITE_PARAGRAPH_ALIGNMENT_NEAR
, "got %d\n", paralign
);
970 wrapping
= IDWriteTextFormat_GetWordWrapping(format
);
971 ok(wrapping
== DWRITE_WORD_WRAPPING_WRAP
, "got %d\n", wrapping
);
973 readdir
= IDWriteTextFormat_GetReadingDirection(format
);
974 ok(readdir
== DWRITE_READING_DIRECTION_LEFT_TO_RIGHT
, "got %d\n", readdir
);
976 flow
= IDWriteTextFormat_GetFlowDirection(format
);
977 ok(flow
== DWRITE_FLOW_DIRECTION_TOP_TO_BOTTOM
, "got %d\n", flow
);
979 hr
= IDWriteTextFormat_GetLineSpacing(format
, &method
, &spacing
, &baseline
);
980 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
981 ok(spacing
== 0.0, "got %f\n", spacing
);
982 ok(baseline
== 0.0, "got %f\n", baseline
);
983 ok(method
== DWRITE_LINE_SPACING_METHOD_DEFAULT
, "got %d\n", method
);
985 trimming
.granularity
= DWRITE_TRIMMING_GRANULARITY_WORD
;
986 trimming
.delimiter
= 10;
987 trimming
.delimiterCount
= 10;
988 trimmingsign
= (void*)0xdeadbeef;
989 hr
= IDWriteTextFormat_GetTrimming(format
, &trimming
, &trimmingsign
);
990 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
991 ok(trimming
.granularity
== DWRITE_TRIMMING_GRANULARITY_NONE
, "got %d\n", trimming
.granularity
);
992 ok(trimming
.delimiter
== 0, "got %d\n", trimming
.delimiter
);
993 ok(trimming
.delimiterCount
== 0, "got %d\n", trimming
.delimiterCount
);
994 ok(trimmingsign
== NULL
, "got %p\n", trimmingsign
);
997 hr
= IDWriteTextFormat_SetTextAlignment(format
, DWRITE_TEXT_ALIGNMENT_LEADING
);
998 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1000 hr
= IDWriteTextFormat_SetTextAlignment(format
, DWRITE_TEXT_ALIGNMENT_JUSTIFIED
+1);
1001 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1003 hr
= IDWriteTextFormat_SetParagraphAlignment(format
, DWRITE_PARAGRAPH_ALIGNMENT_NEAR
);
1004 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1006 hr
= IDWriteTextFormat_SetParagraphAlignment(format
, DWRITE_PARAGRAPH_ALIGNMENT_CENTER
+1);
1007 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1009 hr
= IDWriteTextFormat_SetWordWrapping(format
, DWRITE_WORD_WRAPPING_WRAP
);
1010 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1012 hr
= IDWriteTextFormat_SetWordWrapping(format
, DWRITE_WORD_WRAPPING_CHARACTER
+1);
1013 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1015 hr
= IDWriteTextFormat_SetReadingDirection(format
, DWRITE_READING_DIRECTION_LEFT_TO_RIGHT
);
1016 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1018 hr
= IDWriteTextFormat_SetFlowDirection(format
, DWRITE_FLOW_DIRECTION_TOP_TO_BOTTOM
);
1019 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1021 hr
= IDWriteTextFormat_SetLineSpacing(format
, DWRITE_LINE_SPACING_METHOD_DEFAULT
, 0.0, 0.0);
1022 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1024 hr
= IDWriteTextFormat_SetLineSpacing(format
, DWRITE_LINE_SPACING_METHOD_DEFAULT
, 0.0, -10.0);
1025 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1027 hr
= IDWriteTextFormat_SetLineSpacing(format
, DWRITE_LINE_SPACING_METHOD_DEFAULT
, -10.0, 0.0);
1028 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1030 hr
= IDWriteTextFormat_SetLineSpacing(format
, DWRITE_LINE_SPACING_METHOD_PROPORTIONAL
+1, 0.0, 0.0);
1031 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1033 hr
= IDWriteTextFormat_SetTrimming(format
, &trimming
, NULL
);
1034 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1036 IDWriteTextFormat_Release(format
);
1037 IDWriteFactory_Release(factory
);
1040 static void test_GetLocaleName(void)
1042 static const WCHAR strW
[] = {'s','t','r','i','n','g',0};
1043 static const WCHAR ruW
[] = {'r','u',0};
1044 IDWriteTextLayout
*layout
;
1045 IDWriteTextFormat
*format
, *format2
;
1046 IDWriteFactory
*factory
;
1051 factory
= create_factory();
1053 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
1054 DWRITE_FONT_STRETCH_NORMAL
, 10.0, ruW
, &format
);
1055 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1057 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, strW
, 0, format
, 100.0, 100.0, 1.0, NULL
, FALSE
, &layout
);
1058 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1060 hr
= IDWriteTextLayout_QueryInterface(layout
, &IID_IDWriteTextFormat
, (void**)&format2
);
1061 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1063 len
= IDWriteTextFormat_GetLocaleNameLength(format2
);
1064 ok(len
== 2, "got %u\n", len
);
1065 len
= IDWriteTextFormat_GetLocaleNameLength(format
);
1066 ok(len
== 2, "got %u\n", len
);
1067 hr
= IDWriteTextFormat_GetLocaleName(format2
, buff
, len
);
1068 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
1069 hr
= IDWriteTextFormat_GetLocaleName(format2
, buff
, len
+1);
1070 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1071 ok(!lstrcmpW(buff
, ruW
), "got %s\n", wine_dbgstr_w(buff
));
1072 hr
= IDWriteTextFormat_GetLocaleName(format
, buff
, len
);
1073 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
1074 hr
= IDWriteTextFormat_GetLocaleName(format
, buff
, len
+1);
1075 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1076 ok(!lstrcmpW(buff
, ruW
), "got %s\n", wine_dbgstr_w(buff
));
1078 IDWriteTextLayout_Release(layout
);
1079 IDWriteTextFormat_Release(format
);
1080 IDWriteTextFormat_Release(format2
);
1081 IDWriteFactory_Release(factory
);
1084 static const struct drawcall_entry drawellipsis_seq
[] = {
1085 { DRAW_GLYPHRUN
, {0x2026, 0} },
1089 static void test_CreateEllipsisTrimmingSign(void)
1091 DWRITE_INLINE_OBJECT_METRICS metrics
;
1092 DWRITE_BREAK_CONDITION before
, after
;
1093 IDWriteTextFormat
*format
;
1094 IDWriteInlineObject
*sign
;
1095 IDWriteFactory
*factory
;
1099 factory
= create_factory();
1101 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
1102 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
1103 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1105 EXPECT_REF(format
, 1);
1106 hr
= IDWriteFactory_CreateEllipsisTrimmingSign(factory
, format
, &sign
);
1107 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1108 EXPECT_REF(format
, 1);
1110 hr
= IDWriteInlineObject_QueryInterface(sign
, &IID_IDWriteTextLayout
, (void**)&unk
);
1111 ok(hr
== E_NOINTERFACE
, "got 0x%08x\n", hr
);
1113 if (0) {/* crashes on native */
1114 hr
= IDWriteInlineObject_GetBreakConditions(sign
, NULL
, NULL
);
1115 hr
= IDWriteInlineObject_GetMetrics(sign
, NULL
);
1117 metrics
.width
= 0.0;
1118 metrics
.height
= 123.0;
1119 metrics
.baseline
= 123.0;
1120 metrics
.supportsSideways
= TRUE
;
1121 hr
= IDWriteInlineObject_GetMetrics(sign
, &metrics
);
1122 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1123 ok(metrics
.width
> 0.0, "got %.2f\n", metrics
.width
);
1124 ok(metrics
.height
== 0.0, "got %.2f\n", metrics
.height
);
1125 ok(metrics
.baseline
== 0.0, "got %.2f\n", metrics
.baseline
);
1126 ok(!metrics
.supportsSideways
, "got %d\n", metrics
.supportsSideways
);
1128 before
= after
= DWRITE_BREAK_CONDITION_CAN_BREAK
;
1129 hr
= IDWriteInlineObject_GetBreakConditions(sign
, &before
, &after
);
1130 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1131 ok(before
== DWRITE_BREAK_CONDITION_NEUTRAL
, "got %d\n", before
);
1132 ok(after
== DWRITE_BREAK_CONDITION_NEUTRAL
, "got %d\n", after
);
1135 flush_sequence(sequences
, RENDERER_ID
);
1136 hr
= IDWriteInlineObject_Draw(sign
, NULL
, &testrenderer
, 0.0, 0.0, FALSE
, FALSE
, NULL
);
1137 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1138 ok_sequence(sequences
, RENDERER_ID
, drawellipsis_seq
, "ellipsis sign draw test", FALSE
);
1139 IDWriteInlineObject_Release(sign
);
1141 /* non-orthogonal flow/reading combination */
1142 hr
= IDWriteTextFormat_SetReadingDirection(format
, DWRITE_READING_DIRECTION_LEFT_TO_RIGHT
);
1143 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1145 hr
= IDWriteTextFormat_SetFlowDirection(format
, DWRITE_FLOW_DIRECTION_LEFT_TO_RIGHT
);
1146 ok(hr
== S_OK
|| broken(hr
== E_INVALIDARG
) /* vista, win7 */, "got 0x%08x\n", hr
);
1148 hr
= IDWriteFactory_CreateEllipsisTrimmingSign(factory
, format
, &sign
);
1149 ok(hr
== DWRITE_E_FLOWDIRECTIONCONFLICTS
, "got 0x%08x\n", hr
);
1152 IDWriteTextFormat_Release(format
);
1153 IDWriteFactory_Release(factory
);
1156 static void test_fontweight(void)
1158 static const WCHAR strW
[] = {'s','t','r','i','n','g',0};
1159 static const WCHAR ruW
[] = {'r','u',0};
1160 IDWriteTextFormat
*format
, *fmt2
;
1161 IDWriteTextLayout
*layout
;
1162 DWRITE_FONT_WEIGHT weight
;
1163 DWRITE_TEXT_RANGE range
;
1164 IDWriteFactory
*factory
;
1168 factory
= create_factory();
1170 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_BOLD
, DWRITE_FONT_STYLE_NORMAL
,
1171 DWRITE_FONT_STRETCH_NORMAL
, 10.0, ruW
, &format
);
1172 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1174 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, strW
, 6, format
, 100.0, 100.0, 1.0, NULL
, FALSE
, &layout
);
1175 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1177 hr
= IDWriteTextLayout_QueryInterface(layout
, &IID_IDWriteTextFormat
, (void**)&fmt2
);
1178 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1180 weight
= IDWriteTextFormat_GetFontWeight(fmt2
);
1181 ok(weight
== DWRITE_FONT_WEIGHT_BOLD
, "got %u\n", weight
);
1183 range
.startPosition
= range
.length
= 0;
1184 hr
= IDWriteTextLayout_GetFontWeight(layout
, 0, &weight
, &range
);
1185 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1186 ok(range
.startPosition
== 0 && range
.length
== ~0u, "got %u, %u\n", range
.startPosition
, range
.length
);
1188 range
.startPosition
= 0;
1190 hr
= IDWriteTextLayout_SetFontWeight(layout
, DWRITE_FONT_WEIGHT_NORMAL
, range
);
1191 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1193 range
.startPosition
= range
.length
= 0;
1194 hr
= IDWriteTextLayout_GetFontWeight(layout
, 0, &weight
, &range
);
1195 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1196 ok(range
.startPosition
== 0 && range
.length
== 6, "got %u, %u\n", range
.startPosition
, range
.length
);
1198 /* IDWriteTextFormat methods output doesn't reflect layout changes */
1199 weight
= IDWriteTextFormat_GetFontWeight(fmt2
);
1200 ok(weight
== DWRITE_FONT_WEIGHT_BOLD
, "got %u\n", weight
);
1203 weight
= DWRITE_FONT_WEIGHT_BOLD
;
1204 hr
= IDWriteTextLayout_GetFontWeight(layout
, 0, &weight
, &range
);
1205 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1206 ok(weight
== DWRITE_FONT_WEIGHT_NORMAL
, "got %d\n", weight
);
1207 ok(range
.length
== 6, "got %d\n", range
.length
);
1209 size
= IDWriteTextLayout_GetMaxWidth(layout
);
1210 ok(size
== 100.0, "got %.2f\n", size
);
1212 hr
= IDWriteTextLayout_SetMaxWidth(layout
, 0.0);
1213 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1215 size
= IDWriteTextLayout_GetMaxWidth(layout
);
1216 ok(size
== 0.0, "got %.2f\n", size
);
1218 hr
= IDWriteTextLayout_SetMaxWidth(layout
, -1.0);
1219 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1221 size
= IDWriteTextLayout_GetMaxWidth(layout
);
1222 ok(size
== 0.0, "got %.2f\n", size
);
1224 hr
= IDWriteTextLayout_SetMaxWidth(layout
, 100.0);
1225 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1227 size
= IDWriteTextLayout_GetMaxWidth(layout
);
1228 ok(size
== 100.0, "got %.2f\n", size
);
1230 size
= IDWriteTextLayout_GetMaxHeight(layout
);
1231 ok(size
== 100.0, "got %.2f\n", size
);
1233 hr
= IDWriteTextLayout_SetMaxHeight(layout
, 0.0);
1234 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1236 size
= IDWriteTextLayout_GetMaxHeight(layout
);
1237 ok(size
== 0.0, "got %.2f\n", size
);
1239 hr
= IDWriteTextLayout_SetMaxHeight(layout
, -1.0);
1240 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1242 size
= IDWriteTextLayout_GetMaxHeight(layout
);
1243 ok(size
== 0.0, "got %.2f\n", size
);
1245 hr
= IDWriteTextLayout_SetMaxHeight(layout
, 100.0);
1246 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1248 size
= IDWriteTextLayout_GetMaxHeight(layout
);
1249 ok(size
== 100.0, "got %.2f\n", size
);
1251 IDWriteTextLayout_Release(layout
);
1252 IDWriteTextFormat_Release(fmt2
);
1253 IDWriteTextFormat_Release(format
);
1254 IDWriteFactory_Release(factory
);
1257 static void test_SetInlineObject(void)
1259 static const WCHAR strW
[] = {'s','t','r','i','n','g',0};
1260 static const WCHAR ruW
[] = {'r','u',0};
1262 IDWriteInlineObject
*inlineobj
, *inlineobj2
, *inlinetest
;
1263 IDWriteTextFormat
*format
;
1264 IDWriteTextLayout
*layout
;
1265 DWRITE_TEXT_RANGE range
, r2
;
1266 IDWriteFactory
*factory
;
1269 factory
= create_factory();
1271 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_BOLD
, DWRITE_FONT_STYLE_NORMAL
,
1272 DWRITE_FONT_STRETCH_NORMAL
, 10.0, ruW
, &format
);
1273 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1275 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, strW
, 6, format
, 100.0, 100.0, 1.0, NULL
, FALSE
, &layout
);
1276 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1278 hr
= IDWriteFactory_CreateEllipsisTrimmingSign(factory
, format
, &inlineobj
);
1279 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1281 hr
= IDWriteFactory_CreateEllipsisTrimmingSign(factory
, format
, &inlineobj2
);
1282 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1284 EXPECT_REF(inlineobj
, 1);
1285 EXPECT_REF(inlineobj2
, 1);
1287 inlinetest
= (void*)0x1;
1288 hr
= IDWriteTextLayout_GetInlineObject(layout
, 0, &inlinetest
, NULL
);
1289 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1290 ok(inlinetest
== NULL
, "got %p\n", inlinetest
);
1292 range
.startPosition
= 0;
1294 hr
= IDWriteTextLayout_SetInlineObject(layout
, inlineobj
, range
);
1295 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1297 EXPECT_REF(inlineobj
, 2);
1299 inlinetest
= (void*)0x1;
1300 hr
= IDWriteTextLayout_GetInlineObject(layout
, 2, &inlinetest
, NULL
);
1301 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1302 ok(inlinetest
== NULL
, "got %p\n", inlinetest
);
1305 r2
.startPosition
= r2
.length
= 100;
1306 hr
= IDWriteTextLayout_GetInlineObject(layout
, 0, &inlinetest
, &r2
);
1307 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1308 ok(inlinetest
== inlineobj
, "got %p\n", inlinetest
);
1309 ok(r2
.startPosition
== 0 && r2
.length
== 2, "got %d, %d\n", r2
.startPosition
, r2
.length
);
1310 IDWriteInlineObject_Release(inlinetest
);
1312 EXPECT_REF(inlineobj
, 2);
1314 /* get from somewhere inside a range */
1316 r2
.startPosition
= r2
.length
= 100;
1317 hr
= IDWriteTextLayout_GetInlineObject(layout
, 1, &inlinetest
, &r2
);
1318 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1319 ok(inlinetest
== inlineobj
, "got %p\n", inlinetest
);
1320 ok(r2
.startPosition
== 0 && r2
.length
== 2, "got %d, %d\n", r2
.startPosition
, r2
.length
);
1321 IDWriteInlineObject_Release(inlinetest
);
1323 EXPECT_REF(inlineobj
, 2);
1325 range
.startPosition
= 1;
1327 hr
= IDWriteTextLayout_SetInlineObject(layout
, inlineobj2
, range
);
1328 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1331 r2
.startPosition
= r2
.length
= 100;
1332 hr
= IDWriteTextLayout_GetInlineObject(layout
, 1, &inlinetest
, &r2
);
1333 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1334 ok(inlinetest
== inlineobj2
, "got %p\n", inlinetest
);
1335 ok(r2
.startPosition
== 1 && r2
.length
== 1, "got %d, %d\n", r2
.startPosition
, r2
.length
);
1336 IDWriteInlineObject_Release(inlinetest
);
1338 EXPECT_REF(inlineobj
, 2);
1339 EXPECT_REF(inlineobj2
, 2);
1342 r2
.startPosition
= r2
.length
= 100;
1343 hr
= IDWriteTextLayout_GetInlineObject(layout
, 0, &inlinetest
, &r2
);
1344 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1345 ok(inlinetest
== inlineobj
, "got %p\n", inlinetest
);
1346 ok(r2
.startPosition
== 0 && r2
.length
== 1, "got %d, %d\n", r2
.startPosition
, r2
.length
);
1347 IDWriteInlineObject_Release(inlinetest
);
1349 EXPECT_REF(inlineobj
, 2);
1351 range
.startPosition
= 1;
1353 hr
= IDWriteTextLayout_SetInlineObject(layout
, inlineobj
, range
);
1354 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1356 r2
.startPosition
= r2
.length
= 100;
1357 hr
= IDWriteTextLayout_GetInlineObject(layout
, 0, &inlinetest
, &r2
);
1358 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1359 ok(inlinetest
== inlineobj
, "got %p\n", inlinetest
);
1360 ok(r2
.startPosition
== 0 && r2
.length
== 2, "got %d, %d\n", r2
.startPosition
, r2
.length
);
1361 IDWriteInlineObject_Release(inlinetest
);
1363 EXPECT_REF(inlineobj
, 2);
1365 range
.startPosition
= 1;
1367 hr
= IDWriteTextLayout_SetInlineObject(layout
, inlineobj
, range
);
1368 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1370 EXPECT_REF(inlineobj
, 2);
1372 r2
.startPosition
= r2
.length
= 100;
1373 hr
= IDWriteTextLayout_GetInlineObject(layout
, 0, &inlinetest
, &r2
);
1374 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1375 ok(inlinetest
== inlineobj
, "got %p\n", inlinetest
);
1376 ok(r2
.startPosition
== 0 && r2
.length
== 3, "got %d, %d\n", r2
.startPosition
, r2
.length
);
1377 IDWriteInlineObject_Release(inlinetest
);
1379 EXPECT_REF(inlineobj
, 2);
1380 EXPECT_REF(inlineobj2
, 1);
1382 IDWriteTextLayout_Release(layout
);
1384 EXPECT_REF(inlineobj
, 1);
1386 IDWriteInlineObject_Release(inlineobj
);
1387 IDWriteInlineObject_Release(inlineobj2
);
1388 IDWriteTextFormat_Release(format
);
1389 IDWriteFactory_Release(factory
);
1392 /* drawing calls sequence doesn't depend on run order, instead all runs are
1393 drawn first, inline objects next and then underline/strikes */
1394 static const struct drawcall_entry draw_seq
[] = {
1395 { DRAW_GLYPHRUN
, {'s',0} },
1396 { DRAW_GLYPHRUN
, {'r','i',0} },
1397 { DRAW_GLYPHRUN
|DRAW_EFFECT
, {'n',0} },
1398 { DRAW_GLYPHRUN
, {'g',0} },
1400 { DRAW_UNDERLINE
, {0}, {'r','u',0} },
1401 { DRAW_STRIKETHROUGH
},
1405 static const struct drawcall_entry draw_seq2
[] = {
1406 { DRAW_GLYPHRUN
, {'s',0} },
1407 { DRAW_GLYPHRUN
, {'t',0} },
1408 { DRAW_GLYPHRUN
, {'r',0} },
1409 { DRAW_GLYPHRUN
, {'i',0} },
1410 { DRAW_GLYPHRUN
, {'n',0} },
1411 { DRAW_GLYPHRUN
, {'g',0} },
1415 static const struct drawcall_entry draw_seq3
[] = {
1416 { DRAW_GLYPHRUN
, {0x202a,0x202c,0} },
1417 { DRAW_GLYPHRUN
, {'a','b',0} },
1421 static const struct drawcall_entry draw_seq4
[] = {
1422 { DRAW_GLYPHRUN
, {'s','t','r',0} },
1423 { DRAW_GLYPHRUN
, {'i','n','g',0} },
1424 { DRAW_STRIKETHROUGH
},
1428 static const struct drawcall_entry draw_seq5
[] = {
1429 { DRAW_GLYPHRUN
, {'s','t',0} },
1430 { DRAW_GLYPHRUN
, {'r','i',0} },
1431 { DRAW_GLYPHRUN
, {'n','g',0} },
1432 { DRAW_STRIKETHROUGH
},
1436 static const struct drawcall_entry empty_seq
[] = {
1440 static const struct drawcall_entry draw_single_run_seq
[] = {
1441 { DRAW_GLYPHRUN
, {'s','t','r','i','n','g',0} },
1445 static const struct drawcall_entry draw_reordered_run_seq
[] = {
1446 { DRAW_GLYPHRUN
, {'1','2','3','-','5','2',0} },
1447 { DRAW_GLYPHRUN
, {0x64a,0x64f,0x633,0x627,0x648,0x650,0x64a,0} },
1448 { DRAW_GLYPHRUN
, {'7','1',0} },
1449 { DRAW_GLYPHRUN
, {'.',0} },
1453 static void test_Draw(void)
1455 static const WCHAR str3W
[] = {'1','2','3','-','5','2',0x64a,0x64f,0x633,0x627,0x648,0x650,
1456 0x64a,'7','1','.',0};
1457 static const WCHAR strW
[] = {'s','t','r','i','n','g',0};
1458 static const WCHAR str2W
[] = {0x202a,0x202c,'a','b',0};
1459 static const WCHAR ruW
[] = {'r','u',0};
1460 IDWriteInlineObject
*inlineobj
;
1461 struct renderer_context ctxt
;
1462 IDWriteTextFormat
*format
;
1463 IDWriteTextLayout
*layout
;
1464 DWRITE_TEXT_RANGE range
;
1465 IDWriteFactory
*factory
;
1466 DWRITE_TEXT_METRICS tm
;
1470 factory
= create_factory();
1472 ctxt
.gdicompat
= FALSE
;
1473 ctxt
.use_gdi_natural
= FALSE
;
1474 ctxt
.snapping_disabled
= TRUE
;
1476 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_BOLD
, DWRITE_FONT_STYLE_NORMAL
,
1477 DWRITE_FONT_STRETCH_NORMAL
, 10.0, ruW
, &format
);
1478 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1480 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 6, format
, 100.0, 100.0, &layout
);
1481 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1483 hr
= IDWriteFactory_CreateEllipsisTrimmingSign(factory
, format
, &inlineobj
);
1484 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1486 range
.startPosition
= 5;
1488 hr
= IDWriteTextLayout_SetStrikethrough(layout
, TRUE
, range
);
1489 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1491 range
.startPosition
= 1;
1493 hr
= IDWriteTextLayout_SetInlineObject(layout
, inlineobj
, range
);
1494 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1496 range
.startPosition
= 4;
1498 hr
= IDWriteTextLayout_SetDrawingEffect(layout
, (IUnknown
*)inlineobj
, range
);
1499 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1501 range
.startPosition
= 0;
1503 hr
= IDWriteTextLayout_SetUnderline(layout
, TRUE
, range
);
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
, draw_seq
, "draw test", FALSE
);
1510 IDWriteTextLayout_Release(layout
);
1512 /* with reduced width DrawGlyphRun() is called for every line */
1513 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 6, format
, 5.0, 100.0, &layout
);
1514 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1515 flush_sequence(sequences
, RENDERER_ID
);
1516 hr
= IDWriteTextLayout_Draw(layout
, &ctxt
, &testrenderer
, 0.0, 0.0);
1517 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1518 ok_sequence(sequences
, RENDERER_ID
, draw_seq2
, "draw test 2", TRUE
);
1519 IDWriteTextLayout_Release(layout
);
1521 /* string with control characters */
1522 hr
= IDWriteFactory_CreateTextLayout(factory
, str2W
, 4, format
, 500.0, 100.0, &layout
);
1523 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1524 flush_sequence(sequences
, RENDERER_ID
);
1525 hr
= IDWriteTextLayout_Draw(layout
, &ctxt
, &testrenderer
, 0.0, 0.0);
1526 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1527 ok_sequence(sequences
, RENDERER_ID
, draw_seq3
, "draw test 3", TRUE
);
1528 IDWriteTextLayout_Release(layout
);
1530 /* strikethrough splits ranges from renderer point of view, but doesn't break
1532 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 6, format
, 500.0, 100.0, &layout
);
1533 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1534 flush_sequence(sequences
, RENDERER_ID
);
1536 range
.startPosition
= 0;
1538 hr
= IDWriteTextLayout_SetStrikethrough(layout
, TRUE
, range
);
1539 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1541 hr
= IDWriteTextLayout_Draw(layout
, &ctxt
, &testrenderer
, 0.0, 0.0);
1542 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1543 ok_sequence(sequences
, RENDERER_ID
, draw_seq4
, "draw test 4", FALSE
);
1544 IDWriteTextLayout_Release(layout
);
1546 /* strikethrough somewhere in the middle */
1547 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 6, format
, 500.0, 100.0, &layout
);
1548 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1549 flush_sequence(sequences
, RENDERER_ID
);
1551 range
.startPosition
= 2;
1553 hr
= IDWriteTextLayout_SetStrikethrough(layout
, TRUE
, range
);
1554 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1556 hr
= IDWriteTextLayout_Draw(layout
, &ctxt
, &testrenderer
, 0.0, 0.0);
1557 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1558 ok_sequence(sequences
, RENDERER_ID
, draw_seq5
, "draw test 5", FALSE
);
1559 IDWriteTextLayout_Release(layout
);
1562 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 0, format
, 500.0, 100.0, &layout
);
1563 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1565 flush_sequence(sequences
, RENDERER_ID
);
1566 hr
= IDWriteTextLayout_Draw(layout
, &ctxt
, &testrenderer
, 0.0, 0.0);
1567 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1568 ok_sequence(sequences
, RENDERER_ID
, empty_seq
, "draw test 6", FALSE
);
1569 IDWriteTextLayout_Release(layout
);
1571 ctxt
.gdicompat
= TRUE
;
1572 ctxt
.use_gdi_natural
= TRUE
;
1574 /* different parameter combinations with gdi-compatible layout */
1575 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, strW
, 6, format
, 100.0, 100.0, 1.0, NULL
, TRUE
, &layout
);
1576 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1577 flush_sequence(sequences
, RENDERER_ID
);
1578 hr
= IDWriteTextLayout_Draw(layout
, &ctxt
, &testrenderer
, 0.0, 0.0);
1579 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1580 ok_sequence(sequences
, RENDERER_ID
, draw_single_run_seq
, "draw test 7", FALSE
);
1582 /* text alignment keeps pixel-aligned origin */
1583 hr
= IDWriteTextLayout_GetMetrics(layout
, &tm
);
1584 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1585 ok(tm
.width
== floorf(tm
.width
), "got %f\n", tm
.width
);
1587 hr
= IDWriteTextLayout_SetMaxWidth(layout
, tm
.width
+ 3.0);
1588 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1589 hr
= IDWriteTextLayout_SetTextAlignment(layout
, DWRITE_TEXT_ALIGNMENT_CENTER
);
1590 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1592 ctxt
.originX
= ctxt
.originY
= 0.0;
1593 flush_sequence(sequences
, RENDERER_ID
);
1594 hr
= IDWriteTextLayout_Draw(layout
, &ctxt
, &testrenderer
, 0.0, 0.0);
1595 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1596 ok_sequence(sequences
, RENDERER_ID
, draw_single_run_seq
, "draw test 7", FALSE
);
1597 ok(ctxt
.originX
!= 0.0 && ctxt
.originX
== floorf(ctxt
.originX
), "got %f\n", ctxt
.originX
);
1599 IDWriteTextLayout_Release(layout
);
1601 ctxt
.gdicompat
= TRUE
;
1602 ctxt
.use_gdi_natural
= FALSE
;
1604 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, strW
, 6, format
, 100.0, 100.0, 1.0, NULL
, FALSE
, &layout
);
1605 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1606 flush_sequence(sequences
, RENDERER_ID
);
1607 hr
= IDWriteTextLayout_Draw(layout
, &ctxt
, &testrenderer
, 0.0, 0.0);
1608 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1609 ok_sequence(sequences
, RENDERER_ID
, draw_single_run_seq
, "draw test 8", FALSE
);
1610 IDWriteTextLayout_Release(layout
);
1612 ctxt
.gdicompat
= TRUE
;
1613 ctxt
.use_gdi_natural
= TRUE
;
1615 m
.m11
= m
.m22
= 2.0;
1616 m
.m12
= m
.m21
= m
.dx
= m
.dy
= 0.0;
1617 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, strW
, 6, format
, 100.0, 100.0, 1.0, &m
, TRUE
, &layout
);
1618 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1619 flush_sequence(sequences
, RENDERER_ID
);
1620 hr
= IDWriteTextLayout_Draw(layout
, &ctxt
, &testrenderer
, 0.0, 0.0);
1621 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1622 ok_sequence(sequences
, RENDERER_ID
, draw_single_run_seq
, "draw test 9", FALSE
);
1623 IDWriteTextLayout_Release(layout
);
1625 ctxt
.gdicompat
= TRUE
;
1626 ctxt
.use_gdi_natural
= FALSE
;
1628 m
.m11
= m
.m22
= 2.0;
1629 m
.m12
= m
.m21
= m
.dx
= m
.dy
= 0.0;
1630 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, strW
, 6, format
, 100.0, 100.0, 1.0, &m
, FALSE
, &layout
);
1631 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1632 flush_sequence(sequences
, RENDERER_ID
);
1633 hr
= IDWriteTextLayout_Draw(layout
, &ctxt
, &testrenderer
, 0.0, 0.0);
1634 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1635 ok_sequence(sequences
, RENDERER_ID
, draw_single_run_seq
, "draw test 10", FALSE
);
1636 IDWriteTextLayout_Release(layout
);
1638 IDWriteInlineObject_Release(inlineobj
);
1640 /* text that triggers bidi run reordering */
1641 hr
= IDWriteFactory_CreateTextLayout(factory
, str3W
, lstrlenW(str3W
), format
, 1000.0f
, 100.0f
, &layout
);
1642 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1644 ctxt
.gdicompat
= FALSE
;
1645 ctxt
.use_gdi_natural
= FALSE
;
1646 ctxt
.snapping_disabled
= TRUE
;
1648 flush_sequence(sequences
, RENDERER_ID
);
1649 hr
= IDWriteTextLayout_Draw(layout
, &ctxt
, &testrenderer
, 0.0f
, 0.0f
);
1650 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1651 ok_sequence(sequences
, RENDERER_ID
, draw_reordered_run_seq
, "draw test 11", FALSE
);
1653 IDWriteTextLayout_Release(layout
);
1655 IDWriteTextFormat_Release(format
);
1656 IDWriteFactory_Release(factory
);
1659 static void test_typography(void)
1661 DWRITE_FONT_FEATURE feature
;
1662 IDWriteTypography
*typography
;
1663 IDWriteFactory
*factory
;
1667 factory
= create_factory();
1669 hr
= IDWriteFactory_CreateTypography(factory
, &typography
);
1670 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1672 feature
.nameTag
= DWRITE_FONT_FEATURE_TAG_KERNING
;
1673 feature
.parameter
= 1;
1674 hr
= IDWriteTypography_AddFontFeature(typography
, feature
);
1675 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1677 count
= IDWriteTypography_GetFontFeatureCount(typography
);
1678 ok(count
== 1, "got %u\n", count
);
1680 /* duplicated features work just fine */
1681 feature
.nameTag
= DWRITE_FONT_FEATURE_TAG_KERNING
;
1682 feature
.parameter
= 0;
1683 hr
= IDWriteTypography_AddFontFeature(typography
, feature
);
1684 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1686 count
= IDWriteTypography_GetFontFeatureCount(typography
);
1687 ok(count
== 2, "got %u\n", count
);
1689 memset(&feature
, 0xcc, sizeof(feature
));
1690 hr
= IDWriteTypography_GetFontFeature(typography
, 0, &feature
);
1691 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1692 ok(feature
.nameTag
== DWRITE_FONT_FEATURE_TAG_KERNING
, "got tag %x\n", feature
.nameTag
);
1693 ok(feature
.parameter
== 1, "got %u\n", feature
.parameter
);
1695 memset(&feature
, 0xcc, sizeof(feature
));
1696 hr
= IDWriteTypography_GetFontFeature(typography
, 1, &feature
);
1697 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1698 ok(feature
.nameTag
== DWRITE_FONT_FEATURE_TAG_KERNING
, "got tag %x\n", feature
.nameTag
);
1699 ok(feature
.parameter
== 0, "got %u\n", feature
.parameter
);
1701 hr
= IDWriteTypography_GetFontFeature(typography
, 2, &feature
);
1702 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1704 /* duplicated with same parameter value */
1705 feature
.nameTag
= DWRITE_FONT_FEATURE_TAG_KERNING
;
1706 feature
.parameter
= 0;
1707 hr
= IDWriteTypography_AddFontFeature(typography
, feature
);
1708 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1710 count
= IDWriteTypography_GetFontFeatureCount(typography
);
1711 ok(count
== 3, "got %u\n", count
);
1713 memset(&feature
, 0xcc, sizeof(feature
));
1714 hr
= IDWriteTypography_GetFontFeature(typography
, 2, &feature
);
1715 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1716 ok(feature
.nameTag
== DWRITE_FONT_FEATURE_TAG_KERNING
, "got tag %x\n", feature
.nameTag
);
1717 ok(feature
.parameter
== 0, "got %u\n", feature
.parameter
);
1719 IDWriteTypography_Release(typography
);
1720 IDWriteFactory_Release(factory
);
1723 static void test_GetClusterMetrics(void)
1725 static const WCHAR str_white_spaceW
[] = {
1726 /* BK - FORM FEED, LINE TABULATION, LINE SEP, PARA SEP */ 0xc, 0xb, 0x2028, 0x2029,
1727 /* ZW - ZERO WIDTH SPACE */ 0x200b,
1728 /* SP - SPACE */ 0x20
1730 static const WCHAR str5W
[] = {'a','\r','b','\n','c','\n','\r','d','\r','\n','e',0xb,'f',0xc,
1731 'g',0x0085,'h',0x2028,'i',0x2029,0xad,0xa,0};
1732 static const WCHAR str3W
[] = {0x2066,')',')',0x661,'(',0x627,')',0};
1733 static const WCHAR str2W
[] = {0x202a,0x202c,'a',0};
1734 static const WCHAR strW
[] = {'a','b','c','d',0};
1735 static const WCHAR str4W
[] = {'a',' ',0};
1736 DWRITE_INLINE_OBJECT_METRICS inline_metrics
;
1737 DWRITE_CLUSTER_METRICS metrics
[22];
1738 IDWriteTextLayout1
*layout1
;
1739 IDWriteInlineObject
*trimm
;
1740 IDWriteTextFormat
*format
;
1741 IDWriteTextLayout
*layout
;
1742 DWRITE_TEXT_RANGE range
;
1743 IDWriteFactory
*factory
;
1747 factory
= create_factory();
1749 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
1750 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
1751 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1753 hr
= IDWriteFactory_CreateTextLayout(factory
, str3W
, 7, format
, 1000.0, 1000.0, &layout
);
1754 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1755 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, NULL
, 0, &count
);
1756 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
1757 ok(count
== 7, "got %u\n", count
);
1758 IDWriteTextLayout_Release(layout
);
1760 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 1000.0, 1000.0, &layout
);
1761 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1764 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, NULL
, 0, &count
);
1765 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
1766 ok(count
== 4, "got %u\n", count
);
1768 /* check every cluster width */
1770 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, metrics
, sizeof(metrics
)/sizeof(metrics
[0]), &count
);
1771 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1772 ok(count
== 4, "got %u\n", count
);
1773 for (i
= 0; i
< count
; i
++) {
1774 ok(metrics
[i
].width
> 0.0, "%u: got width %.2f\n", i
, metrics
[i
].width
);
1775 ok(metrics
[i
].length
== 1, "%u: got length %u\n", i
, metrics
[i
].length
);
1778 /* apply spacing and check widths again */
1779 if (IDWriteTextLayout_QueryInterface(layout
, &IID_IDWriteTextLayout1
, (void**)&layout1
) == S_OK
) {
1780 DWRITE_CLUSTER_METRICS metrics2
[4];
1781 FLOAT leading
, trailing
, min_advance
;
1782 DWRITE_TEXT_RANGE r
;
1784 leading
= trailing
= min_advance
= 2.0;
1785 hr
= IDWriteTextLayout1_GetCharacterSpacing(layout1
, 500, &leading
, &trailing
,
1787 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1788 ok(leading
== 0.0 && trailing
== 0.0 && min_advance
== 0.0,
1789 "got %.2f, %.2f, %.2f\n", leading
, trailing
, min_advance
);
1790 ok(r
.startPosition
== 0 && r
.length
== ~0u, "got %u, %u\n", r
.startPosition
, r
.length
);
1792 leading
= trailing
= min_advance
= 2.0;
1793 hr
= IDWriteTextLayout1_GetCharacterSpacing(layout1
, 0, &leading
, &trailing
,
1794 &min_advance
, NULL
);
1795 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1796 ok(leading
== 0.0 && trailing
== 0.0 && min_advance
== 0.0,
1797 "got %.2f, %.2f, %.2f\n", leading
, trailing
, min_advance
);
1799 r
.startPosition
= 0;
1801 hr
= IDWriteTextLayout1_SetCharacterSpacing(layout1
, 10.0, 15.0, 0.0, r
);
1802 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1805 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, metrics2
, sizeof(metrics2
)/sizeof(metrics2
[0]), &count
);
1806 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1807 ok(count
== 4, "got %u\n", count
);
1808 for (i
= 0; i
< count
; i
++) {
1810 ok(metrics2
[i
].width
> metrics
[i
].width
, "%u: got width %.2f, was %.2f\n", i
, metrics2
[i
].width
,
1812 ok(metrics2
[i
].length
== 1, "%u: got length %u\n", i
, metrics2
[i
].length
);
1815 /* back to defaults */
1816 r
.startPosition
= 0;
1818 hr
= IDWriteTextLayout1_SetCharacterSpacing(layout1
, 0.0, 0.0, 0.0, r
);
1819 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1821 /* negative advance limit */
1822 r
.startPosition
= 0;
1824 hr
= IDWriteTextLayout1_SetCharacterSpacing(layout1
, 0.0, 0.0, -10.0, r
);
1825 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1827 IDWriteTextLayout1_Release(layout1
);
1830 win_skip("IDWriteTextLayout1 is not supported, cluster spacing test skipped.\n");
1832 hr
= IDWriteFactory_CreateEllipsisTrimmingSign(factory
, format
, &trimm
);
1833 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1835 range
.startPosition
= 0;
1837 hr
= IDWriteTextLayout_SetInlineObject(layout
, trimm
, range
);
1838 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1840 /* inline object takes a separate cluster, replaced codepoints number doesn't matter */
1842 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, NULL
, 0, &count
);
1843 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
1844 ok(count
== 3, "got %u\n", count
);
1847 memset(&metrics
, 0, sizeof(metrics
));
1848 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, metrics
, 1, &count
);
1849 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
1850 ok(count
== 3, "got %u\n", count
);
1851 ok(metrics
[0].length
== 2, "got %u\n", metrics
[0].length
);
1853 hr
= IDWriteInlineObject_GetMetrics(trimm
, &inline_metrics
);
1854 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1855 ok(inline_metrics
.width
> 0.0 && inline_metrics
.width
== metrics
[0].width
, "got %.2f, expected %.2f\n",
1856 inline_metrics
.width
, metrics
[0].width
);
1858 IDWriteTextLayout_Release(layout
);
1860 /* text with non-visual control codes */
1861 hr
= IDWriteFactory_CreateTextLayout(factory
, str2W
, 3, format
, 1000.0, 1000.0, &layout
);
1862 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1864 /* bidi control codes take a separate cluster */
1866 memset(metrics
, 0, sizeof(metrics
));
1867 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, metrics
, 3, &count
);
1868 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1869 ok(count
== 3, "got %u\n", count
);
1871 ok(metrics
[0].width
== 0.0, "got %.2f\n", metrics
[0].width
);
1872 ok(metrics
[0].length
== 1, "got %d\n", metrics
[0].length
);
1873 ok(metrics
[0].canWrapLineAfter
== 0, "got %d\n", metrics
[0].canWrapLineAfter
);
1874 ok(metrics
[0].isWhitespace
== 0, "got %d\n", metrics
[0].isWhitespace
);
1875 ok(metrics
[0].isNewline
== 0, "got %d\n", metrics
[0].isNewline
);
1876 ok(metrics
[0].isSoftHyphen
== 0, "got %d\n", metrics
[0].isSoftHyphen
);
1877 ok(metrics
[0].isRightToLeft
== 0, "got %d\n", metrics
[0].isRightToLeft
);
1879 ok(metrics
[1].width
== 0.0, "got %.2f\n", metrics
[1].width
);
1880 ok(metrics
[1].length
== 1, "got %d\n", metrics
[1].length
);
1881 ok(metrics
[1].canWrapLineAfter
== 0, "got %d\n", metrics
[1].canWrapLineAfter
);
1882 ok(metrics
[1].isWhitespace
== 0, "got %d\n", metrics
[1].isWhitespace
);
1883 ok(metrics
[1].isNewline
== 0, "got %d\n", metrics
[1].isNewline
);
1884 ok(metrics
[1].isSoftHyphen
== 0, "got %d\n", metrics
[1].isSoftHyphen
);
1885 ok(metrics
[1].isRightToLeft
== 0, "got %d\n", metrics
[1].isRightToLeft
);
1887 ok(metrics
[2].width
> 0.0, "got %.2f\n", metrics
[2].width
);
1888 ok(metrics
[2].length
== 1, "got %d\n", metrics
[2].length
);
1889 ok(metrics
[2].canWrapLineAfter
== 1, "got %d\n", metrics
[2].canWrapLineAfter
);
1890 ok(metrics
[2].isWhitespace
== 0, "got %d\n", metrics
[2].isWhitespace
);
1891 ok(metrics
[2].isNewline
== 0, "got %d\n", metrics
[2].isNewline
);
1892 ok(metrics
[2].isSoftHyphen
== 0, "got %d\n", metrics
[2].isSoftHyphen
);
1893 ok(metrics
[2].isRightToLeft
== 0, "got %d\n", metrics
[2].isRightToLeft
);
1895 IDWriteTextLayout_Release(layout
);
1897 /* single inline object that fails to report its metrics */
1898 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, 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
, &testinlineobj
, range
);
1904 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1907 memset(metrics
, 0, sizeof(metrics
));
1908 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, metrics
, 3, &count
);
1909 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1910 ok(count
== 1, "got %u\n", count
);
1912 /* object sets a width to 123.0, but returns failure from GetMetrics() */
1913 ok(metrics
[0].width
== 0.0, "got %.2f\n", metrics
[0].width
);
1914 ok(metrics
[0].length
== 4, "got %d\n", metrics
[0].length
);
1915 ok(metrics
[0].canWrapLineAfter
== 1, "got %d\n", metrics
[0].canWrapLineAfter
);
1916 ok(metrics
[0].isWhitespace
== 0, "got %d\n", metrics
[0].isWhitespace
);
1917 ok(metrics
[0].isNewline
== 0, "got %d\n", metrics
[0].isNewline
);
1918 ok(metrics
[0].isSoftHyphen
== 0, "got %d\n", metrics
[0].isSoftHyphen
);
1919 ok(metrics
[0].isRightToLeft
== 0, "got %d\n", metrics
[0].isRightToLeft
);
1921 /* now set two inline object for [0,1] and [2,3], both fail to report break conditions */
1922 range
.startPosition
= 2;
1924 hr
= IDWriteTextLayout_SetInlineObject(layout
, &testinlineobj2
, range
);
1925 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1928 memset(metrics
, 0, sizeof(metrics
));
1929 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, metrics
, 3, &count
);
1930 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1931 ok(count
== 2, "got %u\n", count
);
1933 ok(metrics
[0].width
== 0.0, "got %.2f\n", metrics
[0].width
);
1934 ok(metrics
[0].length
== 2, "got %d\n", metrics
[0].length
);
1935 ok(metrics
[0].canWrapLineAfter
== 0, "got %d\n", metrics
[0].canWrapLineAfter
);
1936 ok(metrics
[0].isWhitespace
== 0, "got %d\n", metrics
[0].isWhitespace
);
1937 ok(metrics
[0].isNewline
== 0, "got %d\n", metrics
[0].isNewline
);
1938 ok(metrics
[0].isSoftHyphen
== 0, "got %d\n", metrics
[0].isSoftHyphen
);
1939 ok(metrics
[0].isRightToLeft
== 0, "got %d\n", metrics
[0].isRightToLeft
);
1941 ok(metrics
[1].width
== 0.0, "got %.2f\n", metrics
[1].width
);
1942 ok(metrics
[1].length
== 2, "got %d\n", metrics
[1].length
);
1943 ok(metrics
[1].canWrapLineAfter
== 1, "got %d\n", metrics
[1].canWrapLineAfter
);
1944 ok(metrics
[1].isWhitespace
== 0, "got %d\n", metrics
[1].isWhitespace
);
1945 ok(metrics
[1].isNewline
== 0, "got %d\n", metrics
[1].isNewline
);
1946 ok(metrics
[1].isSoftHyphen
== 0, "got %d\n", metrics
[1].isSoftHyphen
);
1947 ok(metrics
[1].isRightToLeft
== 0, "got %d\n", metrics
[1].isRightToLeft
);
1949 IDWriteTextLayout_Release(layout
);
1951 /* zero length string */
1952 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 0, format
, 1000.0, 1000.0, &layout
);
1953 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1956 memset(metrics
, 0, sizeof(metrics
));
1957 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, metrics
, 3, &count
);
1958 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1959 ok(count
== 0, "got %u\n", count
);
1960 IDWriteTextLayout_Release(layout
);
1963 hr
= IDWriteFactory_CreateTextLayout(factory
, str4W
, 2, format
, 1000.0, 1000.0, &layout
);
1964 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1967 memset(metrics
, 0, sizeof(metrics
));
1968 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, metrics
, 2, &count
);
1969 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1970 ok(count
== 2, "got %u\n", count
);
1971 ok(metrics
[0].isWhitespace
== 0, "got %d\n", metrics
[0].isWhitespace
);
1972 ok(metrics
[0].canWrapLineAfter
== 0, "got %d\n", metrics
[0].canWrapLineAfter
);
1973 ok(metrics
[1].isWhitespace
== 1, "got %d\n", metrics
[1].isWhitespace
);
1974 ok(metrics
[1].canWrapLineAfter
== 1, "got %d\n", metrics
[1].canWrapLineAfter
);
1975 IDWriteTextLayout_Release(layout
);
1977 /* layout is fully covered by inline object with after condition DWRITE_BREAK_CONDITION_MAY_NOT_BREAK */
1978 hr
= IDWriteFactory_CreateTextLayout(factory
, str4W
, 2, format
, 1000.0, 1000.0, &layout
);
1979 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1981 range
.startPosition
= 0;
1983 hr
= IDWriteTextLayout_SetInlineObject(layout
, &testinlineobj3
, range
);
1984 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1987 memset(metrics
, 0, sizeof(metrics
));
1988 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, metrics
, 2, &count
);
1989 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1990 ok(count
== 1, "got %u\n", count
);
1991 ok(metrics
[0].canWrapLineAfter
== 1, "got %d\n", metrics
[0].canWrapLineAfter
);
1993 IDWriteTextLayout_Release(layout
);
1995 /* compare natural cluster width with gdi layout */
1996 hr
= IDWriteFactory_CreateTextLayout(factory
, str4W
, 1, format
, 100.0, 100.0, &layout
);
1997 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2000 memset(metrics
, 0, sizeof(metrics
));
2001 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, metrics
, 1, &count
);
2002 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2003 ok(count
== 1, "got %u\n", count
);
2004 ok(metrics
[0].width
!= floorf(metrics
[0].width
), "got %f\n", metrics
[0].width
);
2006 IDWriteTextLayout_Release(layout
);
2008 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, str4W
, 1, format
, 100.0, 100.0, 1.0, NULL
, FALSE
, &layout
);
2009 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2012 memset(metrics
, 0, sizeof(metrics
));
2013 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, metrics
, 1, &count
);
2014 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2015 ok(count
== 1, "got %u\n", count
);
2016 ok(metrics
[0].width
== floorf(metrics
[0].width
), "got %f\n", metrics
[0].width
);
2018 IDWriteTextLayout_Release(layout
);
2020 /* isNewline tests */
2021 hr
= IDWriteFactory_CreateTextLayout(factory
, str5W
, lstrlenW(str5W
), format
, 100.0f
, 200.0f
, &layout
);
2022 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2025 memset(metrics
, 0, sizeof(metrics
));
2026 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, metrics
, sizeof(metrics
)/sizeof(metrics
[0]), &count
);
2027 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2028 ok(count
== 22, "got %u\n", count
);
2030 ok(metrics
[1].isNewline
== 1, "got %d\n", metrics
[1].isNewline
);
2031 ok(metrics
[3].isNewline
== 1, "got %d\n", metrics
[3].isNewline
);
2032 ok(metrics
[5].isNewline
== 1, "got %d\n", metrics
[5].isNewline
);
2033 ok(metrics
[6].isNewline
== 1, "got %d\n", metrics
[6].isNewline
);
2034 ok(metrics
[9].isNewline
== 1, "got %d\n", metrics
[9].isNewline
);
2035 ok(metrics
[11].isNewline
== 1, "got %d\n", metrics
[11].isNewline
);
2036 ok(metrics
[13].isNewline
== 1, "got %d\n", metrics
[13].isNewline
);
2037 ok(metrics
[15].isNewline
== 1, "got %d\n", metrics
[15].isNewline
);
2038 ok(metrics
[17].isNewline
== 1, "got %d\n", metrics
[17].isNewline
);
2039 ok(metrics
[19].isNewline
== 1, "got %d\n", metrics
[19].isNewline
);
2040 ok(metrics
[21].isNewline
== 1, "got %d\n", metrics
[21].isNewline
);
2042 ok(metrics
[0].isNewline
== 0, "got %d\n", metrics
[0].isNewline
);
2043 ok(metrics
[2].isNewline
== 0, "got %d\n", metrics
[2].isNewline
);
2044 ok(metrics
[4].isNewline
== 0, "got %d\n", metrics
[4].isNewline
);
2045 ok(metrics
[7].isNewline
== 0, "got %d\n", metrics
[7].isNewline
);
2046 ok(metrics
[8].isNewline
== 0, "got %d\n", metrics
[8].isNewline
);
2047 ok(metrics
[10].isNewline
== 0, "got %d\n", metrics
[10].isNewline
);
2048 ok(metrics
[12].isNewline
== 0, "got %d\n", metrics
[12].isNewline
);
2049 ok(metrics
[14].isNewline
== 0, "got %d\n", metrics
[14].isNewline
);
2050 ok(metrics
[16].isNewline
== 0, "got %d\n", metrics
[16].isNewline
);
2051 ok(metrics
[18].isNewline
== 0, "got %d\n", metrics
[18].isNewline
);
2052 ok(metrics
[20].isNewline
== 0, "got %d\n", metrics
[20].isNewline
);
2054 for (i
= 0; i
< count
; i
++) {
2055 ok(metrics
[i
].length
== 1, "%d: got %d\n", i
, metrics
[i
].length
);
2056 ok(metrics
[i
].isSoftHyphen
== (i
== count
- 2), "%d: got %d\n", i
, metrics
[i
].isSoftHyphen
);
2057 if (metrics
[i
].isSoftHyphen
)
2058 ok(!metrics
[i
].isWhitespace
, "%u: got %d\n", i
, metrics
[i
].isWhitespace
);
2059 if (metrics
[i
].isNewline
) {
2060 if (i
== 17 || i
== 19)
2061 todo_wine
ok(metrics
[i
].width
== 0.0f
, "%u: got width %f\n", i
, metrics
[i
].width
);
2063 ok(metrics
[i
].width
== 0.0f
, "%u: got width %f\n", i
, metrics
[i
].width
);
2064 ok(metrics
[i
].isWhitespace
== 1, "%u: got %d\n", i
, metrics
[i
].isWhitespace
);
2065 ok(metrics
[i
].canWrapLineAfter
== 1, "%u: got %d\n", i
, metrics
[i
].canWrapLineAfter
);
2069 IDWriteTextLayout_Release(layout
);
2071 /* Test whitespace resolution from linebreaking classes BK, ZW, and SP */
2072 hr
= IDWriteFactory_CreateTextLayout(factory
, str_white_spaceW
, sizeof(str_white_spaceW
)/sizeof(WCHAR
), format
,
2073 100.0f
, 200.0f
, &layout
);
2074 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2077 memset(metrics
, 0, sizeof(metrics
));
2078 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, metrics
, 20, &count
);
2079 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2080 ok(count
== 6, "got %u\n", count
);
2082 ok(metrics
[0].isWhitespace
== 1, "got %d\n", metrics
[0].isWhitespace
);
2083 ok(metrics
[1].isWhitespace
== 1, "got %d\n", metrics
[1].isWhitespace
);
2084 ok(metrics
[2].isWhitespace
== 1, "got %d\n", metrics
[2].isWhitespace
);
2085 ok(metrics
[3].isWhitespace
== 1, "got %d\n", metrics
[3].isWhitespace
);
2086 ok(metrics
[4].isWhitespace
== 0, "got %d\n", metrics
[4].isWhitespace
);
2087 ok(metrics
[5].isWhitespace
== 1, "got %d\n", metrics
[5].isWhitespace
);
2089 IDWriteInlineObject_Release(trimm
);
2090 IDWriteTextFormat_Release(format
);
2091 IDWriteFactory_Release(factory
);
2094 static void test_SetLocaleName(void)
2096 static const WCHAR eNuSW
[] = {'e','N','-','u','S',0};
2097 static const WCHAR strW
[] = {'a','b','c','d',0};
2098 WCHAR buffW
[LOCALE_NAME_MAX_LENGTH
+sizeof(strW
)/sizeof(WCHAR
)];
2099 IDWriteTextFormat
*format
, *format2
;
2100 IDWriteTextLayout
*layout
;
2101 DWRITE_TEXT_RANGE range
;
2102 IDWriteFactory
*factory
;
2105 factory
= create_factory();
2107 /* create format with mixed case locale name, get it back */
2108 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
2109 DWRITE_FONT_STRETCH_NORMAL
, 10.0, eNuSW
, &format
);
2110 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2112 hr
= IDWriteTextFormat_GetLocaleName(format
, buffW
, sizeof(buffW
)/sizeof(buffW
[0]));
2113 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2114 ok(!lstrcmpW(buffW
, enusW
), "got %s\n", wine_dbgstr_w(buffW
));
2116 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 1000.0, 1000.0, &layout
);
2117 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2119 hr
= IDWriteTextLayout_QueryInterface(layout
, &IID_IDWriteTextFormat
, (void**)&format2
);
2120 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2122 hr
= IDWriteTextFormat_GetLocaleName(format2
, buffW
, sizeof(buffW
)/sizeof(buffW
[0]));
2123 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2124 ok(!lstrcmpW(buffW
, enusW
), "got %s\n", wine_dbgstr_w(buffW
));
2126 hr
= IDWriteTextLayout_GetLocaleName(layout
, 0, buffW
, sizeof(buffW
)/sizeof(buffW
[0]), NULL
);
2127 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2128 ok(!lstrcmpW(buffW
, enusW
), "got %s\n", wine_dbgstr_w(buffW
));
2130 IDWriteTextFormat_Release(format2
);
2131 IDWriteTextLayout_Release(layout
);
2132 IDWriteTextFormat_Release(format
);
2134 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
2135 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
2136 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2138 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 1000.0, 1000.0, &layout
);
2139 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2141 range
.startPosition
= 0;
2143 hr
= IDWriteTextLayout_SetLocaleName(layout
, enusW
, range
);
2144 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2146 hr
= IDWriteTextLayout_SetLocaleName(layout
, NULL
, range
);
2147 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
2149 /* invalid locale name is allowed */
2150 hr
= IDWriteTextLayout_SetLocaleName(layout
, strW
, range
);
2151 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2153 hr
= IDWriteTextLayout_GetLocaleName(layout
, 0, NULL
, 0, NULL
);
2154 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
2156 if (0) /* crashes on native */
2157 hr
= IDWriteTextLayout_GetLocaleName(layout
, 0, NULL
, 1, NULL
);
2161 hr
= IDWriteTextLayout_GetLocaleName(layout
, 0, buffW
, sizeof(buffW
)/sizeof(WCHAR
), &range
);
2162 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2163 ok(!lstrcmpW(buffW
, strW
), "got %s\n", wine_dbgstr_w(buffW
));
2164 ok(range
.startPosition
== 0 && range
.length
== 1, "got %u,%u\n", range
.startPosition
, range
.length
);
2166 /* get with a shorter buffer */
2168 hr
= IDWriteTextLayout_GetLocaleName(layout
, 0, buffW
, 1, NULL
);
2169 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
2170 ok(buffW
[0] == 0, "got %x\n", buffW
[0]);
2172 /* name is too long */
2173 lstrcpyW(buffW
, strW
);
2174 while (lstrlenW(buffW
) <= LOCALE_NAME_MAX_LENGTH
)
2175 lstrcatW(buffW
, strW
);
2177 range
.startPosition
= 0;
2179 hr
= IDWriteTextLayout_SetLocaleName(layout
, buffW
, range
);
2180 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
2183 hr
= IDWriteTextLayout_GetLocaleName(layout
, 0, buffW
, sizeof(buffW
)/sizeof(WCHAR
), NULL
);
2184 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2185 ok(!lstrcmpW(buffW
, strW
), "got %s\n", wine_dbgstr_w(buffW
));
2187 /* set initial locale name for whole text, except with a different casing */
2188 range
.startPosition
= 0;
2190 hr
= IDWriteTextLayout_SetLocaleName(layout
, eNuSW
, range
);
2191 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2195 hr
= IDWriteTextLayout_GetLocaleName(layout
, 0, buffW
, sizeof(buffW
)/sizeof(WCHAR
), &range
);
2196 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2197 ok(!lstrcmpW(buffW
, enusW
), "got %s\n", wine_dbgstr_w(buffW
));
2198 ok((range
.startPosition
== 0 && range
.length
== ~0u) ||
2199 broken(range
.startPosition
== 0 && range
.length
== 4) /* vista/win7 */, "got %u,%u\n", range
.startPosition
, range
.length
);
2201 /* check what's returned for positions after the text */
2204 hr
= IDWriteTextLayout_GetLocaleName(layout
, 100, buffW
, sizeof(buffW
)/sizeof(WCHAR
), &range
);
2205 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2206 ok(!lstrcmpW(buffW
, enusW
), "got %s\n", wine_dbgstr_w(buffW
));
2207 ok((range
.startPosition
== 0 && range
.length
== ~0u) ||
2208 broken(range
.startPosition
== 4 && range
.length
== ~0u-4) /* vista/win7 */, "got %u,%u\n", range
.startPosition
, range
.length
);
2210 IDWriteTextLayout_Release(layout
);
2211 IDWriteTextFormat_Release(format
);
2212 IDWriteFactory_Release(factory
);
2215 static void test_SetPairKerning(void)
2217 static const WCHAR strW
[] = {'a','e',0x0300,'d',0}; /* accent grave */
2218 DWRITE_CLUSTER_METRICS clusters
[4];
2219 IDWriteTextLayout1
*layout1
;
2220 IDWriteTextFormat
*format
;
2221 IDWriteTextLayout
*layout
;
2222 DWRITE_TEXT_RANGE range
;
2223 IDWriteFactory
*factory
;
2228 factory
= create_factory();
2230 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
2231 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
2232 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2234 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 1000.0, 1000.0, &layout
);
2235 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2236 IDWriteTextFormat_Release(format
);
2238 hr
= IDWriteTextLayout_QueryInterface(layout
, &IID_IDWriteTextLayout1
, (void**)&layout1
);
2239 IDWriteTextLayout_Release(layout
);
2242 win_skip("SetPairKerning() is not supported.\n");
2243 IDWriteFactory_Release(factory
);
2247 if (0) { /* crashes on native */
2248 hr
= IDWriteTextLayout1_GetPairKerning(layout1
, 0, NULL
, NULL
);
2249 hr
= IDWriteTextLayout1_GetPairKerning(layout1
, 0, NULL
, &range
);
2252 hr
= IDWriteTextLayout1_GetPairKerning(layout1
, 0, &kerning
, NULL
);
2253 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2255 range
.startPosition
= 0;
2258 hr
= IDWriteTextLayout1_GetPairKerning(layout1
, 0, &kerning
, &range
);
2259 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2260 ok(!kerning
, "got %d\n", kerning
);
2261 ok(range
.length
== ~0u, "got %u\n", range
.length
);
2264 hr
= IDWriteTextLayout1_GetClusterMetrics(layout1
, clusters
, 4, &count
);
2265 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2267 ok(count
== 3, "got %u\n", count
);
2269 ok(clusters
[0].length
== 1, "got %u\n", clusters
[0].length
);
2270 ok(clusters
[1].length
== 2, "got %u\n", clusters
[1].length
);
2271 ok(clusters
[2].length
== 1, "got %u\n", clusters
[2].length
);
2273 /* pair kerning flag participates in itemization - combining characters
2275 range
.startPosition
= 0;
2277 hr
= IDWriteTextLayout1_SetPairKerning(layout1
, 2, range
);
2278 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2281 hr
= IDWriteTextLayout1_GetPairKerning(layout1
, 0, &kerning
, &range
);
2282 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2283 ok(kerning
== TRUE
, "got %d\n", kerning
);
2286 hr
= IDWriteTextLayout1_GetClusterMetrics(layout1
, clusters
, 4, &count
);
2287 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2288 ok(count
== 4, "got %u\n", count
);
2289 ok(clusters
[0].length
== 1, "got %u\n", clusters
[0].length
);
2290 ok(clusters
[1].length
== 1, "got %u\n", clusters
[1].length
);
2291 ok(clusters
[2].length
== 1, "got %u\n", clusters
[2].length
);
2292 ok(clusters
[3].length
== 1, "got %u\n", clusters
[3].length
);
2294 IDWriteTextLayout1_Release(layout1
);
2295 IDWriteFactory_Release(factory
);
2298 static void test_SetVerticalGlyphOrientation(void)
2300 static const WCHAR strW
[] = {'a','b','c','d',0};
2301 DWRITE_VERTICAL_GLYPH_ORIENTATION orientation
;
2302 IDWriteTextLayout2
*layout2
;
2303 IDWriteTextFormat
*format
;
2304 IDWriteTextLayout
*layout
;
2305 IDWriteFactory
*factory
;
2308 factory
= create_factory();
2310 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
2311 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
2312 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2314 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 1000.0, 1000.0, &layout
);
2315 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2316 IDWriteTextFormat_Release(format
);
2318 hr
= IDWriteTextLayout_QueryInterface(layout
, &IID_IDWriteTextLayout2
, (void**)&layout2
);
2319 IDWriteTextLayout_Release(layout
);
2322 win_skip("SetVerticalGlyphOrientation() is not supported.\n");
2323 IDWriteFactory_Release(factory
);
2327 orientation
= IDWriteTextLayout2_GetVerticalGlyphOrientation(layout2
);
2328 ok(orientation
== DWRITE_VERTICAL_GLYPH_ORIENTATION_DEFAULT
, "got %d\n", orientation
);
2330 hr
= IDWriteTextLayout2_SetVerticalGlyphOrientation(layout2
, DWRITE_VERTICAL_GLYPH_ORIENTATION_STACKED
+1);
2331 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
2333 IDWriteTextLayout2_Release(layout2
);
2334 IDWriteFactory_Release(factory
);
2337 static void test_fallback(void)
2339 static const WCHAR strW
[] = {'a','b','c','d',0};
2340 IDWriteFontFallback
*fallback
, *fallback2
;
2341 IDWriteTextLayout2
*layout2
;
2342 IDWriteTextFormat1
*format1
;
2343 IDWriteTextFormat
*format
;
2344 IDWriteTextLayout
*layout
;
2345 IDWriteFactory2
*factory2
;
2346 IDWriteFactory
*factory
;
2349 factory
= create_factory();
2351 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
2352 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
2353 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2355 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 1000.0, 1000.0, &layout
);
2356 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2357 IDWriteTextFormat_Release(format
);
2359 hr
= IDWriteTextLayout_QueryInterface(layout
, &IID_IDWriteTextLayout2
, (void**)&layout2
);
2360 IDWriteTextLayout_Release(layout
);
2363 win_skip("GetFontFallback() is not supported.\n");
2364 IDWriteFactory_Release(factory
);
2368 if (0) /* crashes on native */
2369 hr
= IDWriteTextLayout2_GetFontFallback(layout2
, NULL
);
2371 fallback
= (void*)0xdeadbeef;
2372 hr
= IDWriteTextLayout2_GetFontFallback(layout2
, &fallback
);
2373 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2374 ok(fallback
== NULL
, "got %p\n", fallback
);
2376 hr
= IDWriteTextLayout2_QueryInterface(layout2
, &IID_IDWriteTextFormat1
, (void**)&format1
);
2377 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2379 fallback
= (void*)0xdeadbeef;
2380 hr
= IDWriteTextFormat1_GetFontFallback(format1
, &fallback
);
2381 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2382 ok(fallback
== NULL
, "got %p\n", fallback
);
2384 hr
= IDWriteFactory_QueryInterface(factory
, &IID_IDWriteFactory2
, (void**)&factory2
);
2385 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2388 hr
= IDWriteFactory2_GetSystemFontFallback(factory2
, &fallback
);
2389 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2390 ok(fallback
!= NULL
, "got %p\n", fallback
);
2392 hr
= IDWriteTextFormat1_SetFontFallback(format1
, fallback
);
2393 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2395 fallback2
= (void*)0xdeadbeef;
2396 hr
= IDWriteTextLayout2_GetFontFallback(layout2
, &fallback2
);
2397 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2398 ok(fallback2
== fallback
, "got %p\n", fallback2
);
2400 hr
= IDWriteTextLayout2_SetFontFallback(layout2
, NULL
);
2401 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2403 fallback2
= (void*)0xdeadbeef;
2404 hr
= IDWriteTextFormat1_GetFontFallback(format1
, &fallback2
);
2405 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2406 ok(fallback2
== NULL
, "got %p\n", fallback2
);
2408 IDWriteFontFallback_Release(fallback
);
2409 IDWriteTextFormat1_Release(format1
);
2410 IDWriteTextLayout2_Release(layout2
);
2411 IDWriteFactory_Release(factory
);
2414 static void test_DetermineMinWidth(void)
2416 struct minwidth_test
{
2417 const WCHAR text
[10]; /* text to create a layout for */
2418 const WCHAR mintext
[10]; /* text that represents sequence of minimal width */
2419 } minwidth_tests
[] = {
2420 { {' ','a','b',' ',0}, {'a','b',0} },
2421 { {'a','\n',' ',' ',0}, {'a',0} },
2422 { {'a','\n',' ',' ','b',0}, {'b',0} },
2423 { {'a','b','c','\n',' ',' ','b',0}, {'a','b','c',0} },
2425 static const WCHAR strW
[] = {'a','b','c','d',0};
2426 DWRITE_CLUSTER_METRICS metrics
[10];
2427 IDWriteTextFormat
*format
;
2428 IDWriteTextLayout
*layout
;
2429 IDWriteFactory
*factory
;
2434 factory
= create_factory();
2436 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
2437 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
2438 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2440 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, lstrlenW(strW
), format
, 1000.0, 1000.0, &layout
);
2441 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2443 hr
= IDWriteTextLayout_DetermineMinWidth(layout
, NULL
);
2444 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
2445 IDWriteTextLayout_Release(layout
);
2448 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 0, format
, 100.0f
, 100.0f
, &layout
);
2449 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2452 hr
= IDWriteTextLayout_DetermineMinWidth(layout
, &minwidth
);
2453 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2454 ok(minwidth
== 0.0f
, "got %f\n", minwidth
);
2455 IDWriteTextLayout_Release(layout
);
2457 for (i
= 0; i
< sizeof(minwidth_tests
)/sizeof(minwidth_tests
[0]); i
++) {
2460 /* measure expected width */
2461 hr
= IDWriteFactory_CreateTextLayout(factory
, minwidth_tests
[i
].mintext
, lstrlenW(minwidth_tests
[i
].mintext
), format
, 1000.0f
, 1000.0f
, &layout
);
2462 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2464 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, metrics
, sizeof(metrics
)/sizeof(metrics
[0]), &count
);
2465 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2467 for (j
= 0; j
< count
; j
++)
2468 width
+= metrics
[j
].width
;
2470 IDWriteTextLayout_Release(layout
);
2472 hr
= IDWriteFactory_CreateTextLayout(factory
, minwidth_tests
[i
].text
, lstrlenW(minwidth_tests
[i
].text
), format
, 1000.0f
, 1000.0f
, &layout
);
2473 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2476 hr
= IDWriteTextLayout_DetermineMinWidth(layout
, &minwidth
);
2477 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2478 ok(minwidth
== width
, "test %u: expected width %f, got %f\n", i
, width
, minwidth
);
2480 IDWriteTextLayout_Release(layout
);
2483 IDWriteTextFormat_Release(format
);
2484 IDWriteFactory_Release(factory
);
2487 static void test_SetFontSize(void)
2489 static const WCHAR strW
[] = {'a','b','c','d',0};
2490 IDWriteTextFormat
*format
;
2491 IDWriteTextLayout
*layout
;
2492 IDWriteFactory
*factory
;
2493 DWRITE_TEXT_RANGE r
;
2497 factory
= create_factory();
2499 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
2500 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
2501 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2503 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 1000.0, 1000.0, &layout
);
2504 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2506 /* negative/zero size */
2507 r
.startPosition
= 1;
2509 hr
= IDWriteTextLayout_SetFontSize(layout
, -15.0, r
);
2510 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
2512 hr
= IDWriteTextLayout_SetFontSize(layout
, 0.0, r
);
2513 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
2515 r
.startPosition
= 1;
2518 hr
= IDWriteTextLayout_GetFontSize(layout
, 0, &size
, &r
);
2519 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2520 ok(r
.startPosition
== 0 && r
.length
== ~0u, "got %u, %u\n", r
.startPosition
, r
.length
);
2521 ok(size
== 10.0, "got %.2f\n", size
);
2523 r
.startPosition
= 1;
2525 hr
= IDWriteTextLayout_SetFontSize(layout
, 15.0, r
);
2526 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2528 /* zero length range */
2529 r
.startPosition
= 1;
2531 hr
= IDWriteTextLayout_SetFontSize(layout
, 123.0, r
);
2532 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2535 hr
= IDWriteTextLayout_GetFontSize(layout
, 1, &size
, &r
);
2536 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2537 ok(size
== 15.0, "got %.2f\n", size
);
2539 r
.startPosition
= 0;
2541 hr
= IDWriteTextLayout_SetFontSize(layout
, 15.0, r
);
2542 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2545 hr
= IDWriteTextLayout_GetFontSize(layout
, 1, &size
, &r
);
2546 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2547 ok(size
== 15.0, "got %.2f\n", size
);
2550 hr
= IDWriteTextLayout_GetFontSize(layout
, 0, &size
, &r
);
2551 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2552 ok(r
.startPosition
== 0 && r
.length
== 4, "got %u, %u\n", r
.startPosition
, r
.length
);
2553 ok(size
== 15.0, "got %.2f\n", size
);
2556 r
.startPosition
= r
.length
= 0;
2557 hr
= IDWriteTextLayout_GetFontSize(layout
, 20, &size
, &r
);
2558 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2559 ok(r
.startPosition
== 4 && r
.length
== ~0u-4, "got %u, %u\n", r
.startPosition
, r
.length
);
2560 ok(size
== 10.0, "got %.2f\n", size
);
2562 r
.startPosition
= 100;
2564 hr
= IDWriteTextLayout_SetFontSize(layout
, 25.0, r
);
2565 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2568 r
.startPosition
= r
.length
= 0;
2569 hr
= IDWriteTextLayout_GetFontSize(layout
, 100, &size
, &r
);
2570 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2571 ok(r
.startPosition
== 100 && r
.length
== 4, "got %u, %u\n", r
.startPosition
, r
.length
);
2572 ok(size
== 25.0, "got %.2f\n", size
);
2574 IDWriteTextLayout_Release(layout
);
2575 IDWriteTextFormat_Release(format
);
2576 IDWriteFactory_Release(factory
);
2579 static void test_SetFontFamilyName(void)
2581 static const WCHAR taHomaW
[] = {'T','a','H','o','m','a',0};
2582 static const WCHAR arialW
[] = {'A','r','i','a','l',0};
2583 static const WCHAR strW
[] = {'a','b','c','d',0};
2584 IDWriteTextFormat
*format
;
2585 IDWriteTextLayout
*layout
;
2586 IDWriteFactory
*factory
;
2587 DWRITE_TEXT_RANGE r
;
2591 factory
= create_factory();
2593 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
2594 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
2595 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2597 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 1000.0, 1000.0, &layout
);
2598 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2601 r
.startPosition
= 1;
2603 hr
= IDWriteTextLayout_SetFontFamilyName(layout
, NULL
, r
);
2604 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
2606 r
.startPosition
= 1;
2609 hr
= IDWriteTextLayout_GetFontFamilyName(layout
, 1, nameW
, sizeof(nameW
)/sizeof(WCHAR
), &r
);
2610 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2611 ok(r
.startPosition
== 0 && r
.length
== ~0u, "got %u, %u\n", r
.startPosition
, r
.length
);
2613 /* set name only different in casing */
2614 r
.startPosition
= 1;
2616 hr
= IDWriteTextLayout_SetFontFamilyName(layout
, taHomaW
, r
);
2617 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2619 /* zero length range */
2620 r
.startPosition
= 1;
2622 hr
= IDWriteTextLayout_SetFontFamilyName(layout
, arialW
, r
);
2623 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2625 r
.startPosition
= 0;
2628 hr
= IDWriteTextLayout_GetFontFamilyName(layout
, 1, nameW
, sizeof(nameW
)/sizeof(WCHAR
), &r
);
2629 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2630 ok(!lstrcmpW(nameW
, taHomaW
), "got %s\n", wine_dbgstr_w(nameW
));
2631 ok(r
.startPosition
== 1 && r
.length
== 1, "got %u, %u\n", r
.startPosition
, r
.length
);
2633 r
.startPosition
= 1;
2635 hr
= IDWriteTextLayout_SetFontFamilyName(layout
, arialW
, r
);
2636 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2638 r
.startPosition
= 1;
2640 hr
= IDWriteTextLayout_GetFontFamilyName(layout
, 1, nameW
, sizeof(nameW
)/sizeof(WCHAR
), &r
);
2641 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2642 ok(r
.startPosition
== 1 && r
.length
== 1, "got %u, %u\n", r
.startPosition
, r
.length
);
2644 r
.startPosition
= 0;
2646 hr
= IDWriteTextLayout_SetFontFamilyName(layout
, arialW
, r
);
2647 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2650 hr
= IDWriteTextLayout_GetFontFamilyName(layout
, 1, nameW
, sizeof(nameW
)/sizeof(WCHAR
), &r
);
2651 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2652 ok(r
.startPosition
== 0 && r
.length
== 4, "got %u, %u\n", r
.startPosition
, r
.length
);
2653 ok(!lstrcmpW(nameW
, arialW
), "got name %s\n", wine_dbgstr_w(nameW
));
2655 IDWriteTextLayout_Release(layout
);
2656 IDWriteTextFormat_Release(format
);
2657 IDWriteFactory_Release(factory
);
2660 static void test_SetFontStyle(void)
2662 static const WCHAR strW
[] = {'a','b','c','d',0};
2663 IDWriteTextFormat
*format
;
2664 IDWriteTextLayout
*layout
;
2665 IDWriteFactory
*factory
;
2666 DWRITE_FONT_STYLE style
;
2667 DWRITE_TEXT_RANGE r
;
2670 factory
= create_factory();
2672 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
2673 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
2674 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2676 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 1000.0, 1000.0, &layout
);
2677 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2679 /* invalid style value */
2680 r
.startPosition
= 1;
2682 hr
= IDWriteTextLayout_SetFontStyle(layout
, DWRITE_FONT_STYLE_ITALIC
+1, r
);
2683 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
2685 r
.startPosition
= 1;
2687 hr
= IDWriteTextLayout_GetFontStyle(layout
, 0, &style
, &r
);
2688 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2689 ok(r
.startPosition
== 0 && r
.length
== ~0u, "got %u, %u\n", r
.startPosition
, r
.length
);
2690 ok(style
== DWRITE_FONT_STYLE_NORMAL
, "got %d\n", style
);
2692 r
.startPosition
= 1;
2694 hr
= IDWriteTextLayout_SetFontStyle(layout
, DWRITE_FONT_STYLE_ITALIC
, r
);
2695 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2697 /* zero length range */
2698 r
.startPosition
= 1;
2700 hr
= IDWriteTextLayout_SetFontStyle(layout
, DWRITE_FONT_STYLE_NORMAL
, r
);
2701 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2703 style
= DWRITE_FONT_STYLE_NORMAL
;
2704 hr
= IDWriteTextLayout_GetFontStyle(layout
, 1, &style
, &r
);
2705 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2706 ok(style
== DWRITE_FONT_STYLE_ITALIC
, "got %d\n", style
);
2708 r
.startPosition
= 0;
2710 hr
= IDWriteTextLayout_SetFontStyle(layout
, DWRITE_FONT_STYLE_OBLIQUE
, r
);
2711 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2713 style
= DWRITE_FONT_STYLE_ITALIC
;
2714 hr
= IDWriteTextLayout_GetFontStyle(layout
, 1, &style
, &r
);
2715 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2716 ok(style
== DWRITE_FONT_STYLE_OBLIQUE
, "got %d\n", style
);
2718 style
= DWRITE_FONT_STYLE_ITALIC
;
2719 hr
= IDWriteTextLayout_GetFontStyle(layout
, 0, &style
, &r
);
2720 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2721 ok(r
.startPosition
== 0 && r
.length
== 4, "got %u, %u\n", r
.startPosition
, r
.length
);
2722 ok(style
== DWRITE_FONT_STYLE_OBLIQUE
, "got %d\n", style
);
2724 style
= DWRITE_FONT_STYLE_ITALIC
;
2725 r
.startPosition
= r
.length
= 0;
2726 hr
= IDWriteTextLayout_GetFontStyle(layout
, 20, &style
, &r
);
2727 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2728 ok(r
.startPosition
== 4 && r
.length
== ~0u-4, "got %u, %u\n", r
.startPosition
, r
.length
);
2729 ok(style
== DWRITE_FONT_STYLE_NORMAL
, "got %d\n", style
);
2731 r
.startPosition
= 100;
2733 hr
= IDWriteTextLayout_SetFontStyle(layout
, DWRITE_FONT_STYLE_OBLIQUE
, r
);
2734 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2736 style
= DWRITE_FONT_STYLE_NORMAL
;
2737 r
.startPosition
= r
.length
= 0;
2738 hr
= IDWriteTextLayout_GetFontStyle(layout
, 100, &style
, &r
);
2739 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2740 ok(r
.startPosition
== 100 && r
.length
== 4, "got %u, %u\n", r
.startPosition
, r
.length
);
2741 ok(style
== DWRITE_FONT_STYLE_OBLIQUE
, "got %d\n", style
);
2743 IDWriteTextLayout_Release(layout
);
2744 IDWriteTextFormat_Release(format
);
2745 IDWriteFactory_Release(factory
);
2748 static void test_SetFontStretch(void)
2750 static const WCHAR strW
[] = {'a','b','c','d',0};
2751 DWRITE_FONT_STRETCH stretch
;
2752 IDWriteTextFormat
*format
;
2753 IDWriteTextLayout
*layout
;
2754 IDWriteFactory
*factory
;
2755 DWRITE_TEXT_RANGE r
;
2758 factory
= create_factory();
2760 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
2761 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
2762 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2764 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 1000.0, 1000.0, &layout
);
2765 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2767 /* invalid stretch value */
2768 r
.startPosition
= 1;
2770 hr
= IDWriteTextLayout_SetFontStretch(layout
, DWRITE_FONT_STRETCH_ULTRA_EXPANDED
+1, r
);
2771 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
2773 r
.startPosition
= 1;
2775 stretch
= DWRITE_FONT_STRETCH_UNDEFINED
;
2776 hr
= IDWriteTextLayout_GetFontStretch(layout
, 0, &stretch
, &r
);
2777 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2778 ok(r
.startPosition
== 0 && r
.length
== ~0u, "got %u, %u\n", r
.startPosition
, r
.length
);
2779 ok(stretch
== DWRITE_FONT_STRETCH_NORMAL
, "got %d\n", stretch
);
2781 r
.startPosition
= 1;
2783 hr
= IDWriteTextLayout_SetFontStretch(layout
, DWRITE_FONT_STRETCH_CONDENSED
, r
);
2784 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2786 /* zero length range */
2787 r
.startPosition
= 1;
2789 hr
= IDWriteTextLayout_SetFontStretch(layout
, DWRITE_FONT_STRETCH_NORMAL
, r
);
2790 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2792 stretch
= DWRITE_FONT_STRETCH_UNDEFINED
;
2793 hr
= IDWriteTextLayout_GetFontStretch(layout
, 1, &stretch
, &r
);
2794 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2795 ok(stretch
== DWRITE_FONT_STRETCH_CONDENSED
, "got %d\n", stretch
);
2797 r
.startPosition
= 0;
2799 hr
= IDWriteTextLayout_SetFontStretch(layout
, DWRITE_FONT_STRETCH_EXPANDED
, r
);
2800 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2802 stretch
= DWRITE_FONT_STRETCH_UNDEFINED
;
2803 hr
= IDWriteTextLayout_GetFontStretch(layout
, 1, &stretch
, &r
);
2804 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2805 ok(stretch
== DWRITE_FONT_STRETCH_EXPANDED
, "got %d\n", stretch
);
2807 stretch
= DWRITE_FONT_STRETCH_UNDEFINED
;
2808 hr
= IDWriteTextLayout_GetFontStretch(layout
, 0, &stretch
, &r
);
2809 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2810 ok(r
.startPosition
== 0 && r
.length
== 4, "got %u, %u\n", r
.startPosition
, r
.length
);
2811 ok(stretch
== DWRITE_FONT_STRETCH_EXPANDED
, "got %d\n", stretch
);
2813 stretch
= DWRITE_FONT_STRETCH_UNDEFINED
;
2814 r
.startPosition
= r
.length
= 0;
2815 hr
= IDWriteTextLayout_GetFontStretch(layout
, 20, &stretch
, &r
);
2816 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2817 ok(r
.startPosition
== 4 && r
.length
== ~0u-4, "got %u, %u\n", r
.startPosition
, r
.length
);
2818 ok(stretch
== DWRITE_FONT_STRETCH_NORMAL
, "got %d\n", stretch
);
2820 r
.startPosition
= 100;
2822 hr
= IDWriteTextLayout_SetFontStretch(layout
, DWRITE_FONT_STRETCH_EXPANDED
, r
);
2823 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2825 stretch
= DWRITE_FONT_STRETCH_UNDEFINED
;
2826 r
.startPosition
= r
.length
= 0;
2827 hr
= IDWriteTextLayout_GetFontStretch(layout
, 100, &stretch
, &r
);
2828 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2829 ok(r
.startPosition
== 100 && r
.length
== 4, "got %u, %u\n", r
.startPosition
, r
.length
);
2830 ok(stretch
== DWRITE_FONT_STRETCH_EXPANDED
, "got %d\n", stretch
);
2832 /* trying to set undefined value */
2833 r
.startPosition
= 0;
2835 hr
= IDWriteTextLayout_SetFontStretch(layout
, DWRITE_FONT_STRETCH_UNDEFINED
, r
);
2836 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
2838 IDWriteTextLayout_Release(layout
);
2839 IDWriteTextFormat_Release(format
);
2840 IDWriteFactory_Release(factory
);
2843 static void test_SetStrikethrough(void)
2845 static const WCHAR strW
[] = {'a','b','c','d',0};
2846 IDWriteTextFormat
*format
;
2847 IDWriteTextLayout
*layout
;
2848 IDWriteFactory
*factory
;
2849 DWRITE_TEXT_RANGE r
;
2853 factory
= create_factory();
2855 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
2856 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
2857 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2859 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 1000.0, 1000.0, &layout
);
2860 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2862 r
.startPosition
= 1;
2865 hr
= IDWriteTextLayout_GetStrikethrough(layout
, 0, &value
, &r
);
2866 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2867 ok(r
.startPosition
== 0 && r
.length
== ~0u, "got %u, %u\n", r
.startPosition
, r
.length
);
2868 ok(value
== FALSE
, "got %d\n", value
);
2870 r
.startPosition
= 1;
2872 hr
= IDWriteTextLayout_SetStrikethrough(layout
, TRUE
, r
);
2873 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2876 hr
= IDWriteTextLayout_GetStrikethrough(layout
, 1, &value
, &r
);
2877 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2878 ok(value
== TRUE
, "got %d\n", value
);
2879 ok(r
.startPosition
== 1 && r
.length
== 1, "got %u, %u\n", r
.startPosition
, r
.length
);
2882 r
.startPosition
= r
.length
= 0;
2883 hr
= IDWriteTextLayout_GetStrikethrough(layout
, 20, &value
, &r
);
2884 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2885 ok(r
.startPosition
== 2 && r
.length
== ~0u-2, "got %u, %u\n", r
.startPosition
, r
.length
);
2886 ok(value
== FALSE
, "got %d\n", value
);
2888 r
.startPosition
= 100;
2890 hr
= IDWriteTextLayout_SetStrikethrough(layout
, TRUE
, r
);
2891 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2894 r
.startPosition
= r
.length
= 0;
2895 hr
= IDWriteTextLayout_GetStrikethrough(layout
, 100, &value
, &r
);
2896 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2897 ok(r
.startPosition
== 100 && r
.length
== 4, "got %u, %u\n", r
.startPosition
, r
.length
);
2898 ok(value
== TRUE
, "got %d\n", value
);
2900 IDWriteTextLayout_Release(layout
);
2901 IDWriteTextFormat_Release(format
);
2902 IDWriteFactory_Release(factory
);
2905 static void test_GetMetrics(void)
2907 static const WCHAR str2W
[] = {0x2066,')',')',0x661,'(',0x627,')',0};
2908 static const WCHAR strW
[] = {'a','b','c','d',0};
2909 static const WCHAR str3W
[] = {'a',0};
2910 DWRITE_CLUSTER_METRICS clusters
[4];
2911 DWRITE_TEXT_METRICS metrics
;
2912 IDWriteTextFormat
*format
;
2913 IDWriteTextLayout
*layout
;
2914 IDWriteFactory
*factory
;
2919 factory
= create_factory();
2921 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
2922 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
2923 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2925 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 500.0, 1000.0, &layout
);
2926 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2929 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, clusters
, 4, &count
);
2930 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2931 ok(count
== 4, "got %u\n", count
);
2932 for (i
= 0, width
= 0.0; i
< count
; i
++)
2933 width
+= clusters
[i
].width
;
2935 memset(&metrics
, 0xcc, sizeof(metrics
));
2936 hr
= IDWriteTextLayout_GetMetrics(layout
, &metrics
);
2937 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2938 ok(metrics
.left
== 0.0, "got %.2f\n", metrics
.left
);
2939 ok(metrics
.top
== 0.0, "got %.2f\n", metrics
.top
);
2940 ok(metrics
.width
== width
, "got %.2f, expected %.2f\n", metrics
.width
, width
);
2941 ok(metrics
.widthIncludingTrailingWhitespace
== width
, "got %.2f, expected %.2f\n",
2942 metrics
.widthIncludingTrailingWhitespace
, width
);
2943 ok(metrics
.height
> 0.0, "got %.2f\n", metrics
.height
);
2944 ok(metrics
.layoutWidth
== 500.0, "got %.2f\n", metrics
.layoutWidth
);
2945 ok(metrics
.layoutHeight
== 1000.0, "got %.2f\n", metrics
.layoutHeight
);
2946 ok(metrics
.maxBidiReorderingDepth
== 1, "got %u\n", metrics
.maxBidiReorderingDepth
);
2947 ok(metrics
.lineCount
== 1, "got %u\n", metrics
.lineCount
);
2949 IDWriteTextLayout_Release(layout
);
2951 /* a string with more complex bidi sequence */
2952 hr
= IDWriteFactory_CreateTextLayout(factory
, str2W
, 7, format
, 500.0, 1000.0, &layout
);
2953 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2955 memset(&metrics
, 0xcc, sizeof(metrics
));
2956 metrics
.maxBidiReorderingDepth
= 0;
2957 hr
= IDWriteTextLayout_GetMetrics(layout
, &metrics
);
2958 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2959 ok(metrics
.left
== 0.0, "got %.2f\n", metrics
.left
);
2960 ok(metrics
.top
== 0.0, "got %.2f\n", metrics
.top
);
2961 ok(metrics
.width
> 0.0, "got %.2f\n", metrics
.width
);
2962 ok(metrics
.widthIncludingTrailingWhitespace
> 0.0, "got %.2f\n", metrics
.widthIncludingTrailingWhitespace
);
2963 ok(metrics
.height
> 0.0, "got %.2f\n", metrics
.height
);
2964 ok(metrics
.layoutWidth
== 500.0, "got %.2f\n", metrics
.layoutWidth
);
2965 ok(metrics
.layoutHeight
== 1000.0, "got %.2f\n", metrics
.layoutHeight
);
2967 ok(metrics
.maxBidiReorderingDepth
> 1, "got %u\n", metrics
.maxBidiReorderingDepth
);
2968 ok(metrics
.lineCount
== 1, "got %u\n", metrics
.lineCount
);
2970 IDWriteTextLayout_Release(layout
);
2972 /* single cluster layout */
2973 hr
= IDWriteFactory_CreateTextLayout(factory
, str3W
, 1, format
, 500.0, 1000.0, &layout
);
2974 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2977 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, clusters
, 1, &count
);
2978 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2979 ok(count
== 1, "got %u\n", count
);
2981 memset(&metrics
, 0xcc, sizeof(metrics
));
2982 hr
= IDWriteTextLayout_GetMetrics(layout
, &metrics
);
2983 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2984 ok(metrics
.left
== 0.0, "got %.2f\n", metrics
.left
);
2985 ok(metrics
.top
== 0.0, "got %.2f\n", metrics
.top
);
2986 ok(metrics
.width
== clusters
[0].width
, "got %.2f, expected %.2f\n", metrics
.width
, clusters
[0].width
);
2987 ok(metrics
.widthIncludingTrailingWhitespace
== clusters
[0].width
, "got %.2f\n", metrics
.widthIncludingTrailingWhitespace
);
2988 ok(metrics
.height
> 0.0, "got %.2f\n", metrics
.height
);
2989 ok(metrics
.layoutWidth
== 500.0, "got %.2f\n", metrics
.layoutWidth
);
2990 ok(metrics
.layoutHeight
== 1000.0, "got %.2f\n", metrics
.layoutHeight
);
2991 ok(metrics
.maxBidiReorderingDepth
== 1, "got %u\n", metrics
.maxBidiReorderingDepth
);
2992 ok(metrics
.lineCount
== 1, "got %u\n", metrics
.lineCount
);
2993 IDWriteTextLayout_Release(layout
);
2995 IDWriteTextFormat_Release(format
);
2996 IDWriteFactory_Release(factory
);
2999 static void test_SetFlowDirection(void)
3001 static const WCHAR strW
[] = {'a','b','c','d',0};
3002 DWRITE_READING_DIRECTION reading
;
3003 DWRITE_FLOW_DIRECTION flow
;
3004 IDWriteTextFormat
*format
;
3005 IDWriteTextLayout
*layout
;
3006 IDWriteFactory
*factory
;
3009 factory
= create_factory();
3011 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
3012 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
3013 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3015 flow
= IDWriteTextFormat_GetFlowDirection(format
);
3016 ok(flow
== DWRITE_FLOW_DIRECTION_TOP_TO_BOTTOM
, "got %d\n", flow
);
3018 reading
= IDWriteTextFormat_GetReadingDirection(format
);
3019 ok(reading
== DWRITE_READING_DIRECTION_LEFT_TO_RIGHT
, "got %d\n", reading
);
3021 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 500.0, 1000.0, &layout
);
3022 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3023 IDWriteTextLayout_Release(layout
);
3025 hr
= IDWriteTextFormat_SetFlowDirection(format
, DWRITE_FLOW_DIRECTION_LEFT_TO_RIGHT
);
3026 ok(hr
== S_OK
|| broken(hr
== E_INVALIDARG
) /* vista,win7 */, "got 0x%08x\n", hr
);
3028 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 500.0, 1000.0, &layout
);
3029 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3030 IDWriteTextLayout_Release(layout
);
3032 hr
= IDWriteTextFormat_SetReadingDirection(format
, DWRITE_READING_DIRECTION_TOP_TO_BOTTOM
);
3033 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3035 hr
= IDWriteTextFormat_SetFlowDirection(format
, DWRITE_FLOW_DIRECTION_TOP_TO_BOTTOM
);
3036 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3038 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 500.0, 1000.0, &layout
);
3039 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3040 IDWriteTextLayout_Release(layout
);
3043 win_skip("DWRITE_FLOW_DIRECTION_LEFT_TO_RIGHT is not supported\n");
3045 IDWriteTextFormat_Release(format
);
3046 IDWriteFactory_Release(factory
);
3049 static const struct drawcall_entry draweffect_seq
[] = {
3050 { DRAW_GLYPHRUN
|DRAW_EFFECT
, {'a','e',0x0300,0} },
3051 { DRAW_GLYPHRUN
, {'d',0} },
3055 static const struct drawcall_entry draweffect2_seq
[] = {
3056 { DRAW_GLYPHRUN
|DRAW_EFFECT
, {'a','e',0} },
3057 { DRAW_GLYPHRUN
, {'c','d',0} },
3061 static const struct drawcall_entry draweffect3_seq
[] = {
3062 { DRAW_INLINE
|DRAW_EFFECT
},
3066 static const struct drawcall_entry draweffect4_seq
[] = {
3071 static void test_SetDrawingEffect(void)
3073 static const WCHAR strW
[] = {'a','e',0x0300,'d',0}; /* accent grave */
3074 static const WCHAR str2W
[] = {'a','e','c','d',0};
3075 IDWriteInlineObject
*sign
;
3076 IDWriteTextFormat
*format
;
3077 IDWriteTextLayout
*layout
;
3078 IDWriteFactory
*factory
;
3079 DWRITE_TEXT_RANGE r
;
3083 factory
= create_factory();
3085 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
3086 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
3087 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3089 /* string with combining mark */
3090 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 500.0, 1000.0, &layout
);
3091 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3093 /* set effect past the end of text */
3094 r
.startPosition
= 100;
3096 hr
= IDWriteTextLayout_SetDrawingEffect(layout
, &testeffect
, r
);
3097 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3099 r
.startPosition
= r
.length
= 0;
3100 hr
= IDWriteTextLayout_GetDrawingEffect(layout
, 101, &unk
, &r
);
3101 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3102 ok(r
.startPosition
== 100 && r
.length
== 10, "got %u, %u\n", r
.startPosition
, r
.length
);
3104 r
.startPosition
= r
.length
= 0;
3105 unk
= (void*)0xdeadbeef;
3106 hr
= IDWriteTextLayout_GetDrawingEffect(layout
, 1000, &unk
, &r
);
3107 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3108 ok(r
.startPosition
== 110 && r
.length
== ~0u-110, "got %u, %u\n", r
.startPosition
, r
.length
);
3109 ok(unk
== NULL
, "got %p\n", unk
);
3111 /* effect is applied to clusters, not individual text positions */
3112 r
.startPosition
= 0;
3114 hr
= IDWriteTextLayout_SetDrawingEffect(layout
, &testeffect
, r
);
3115 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3117 flush_sequence(sequences
, RENDERER_ID
);
3118 hr
= IDWriteTextLayout_Draw(layout
, NULL
, &testrenderer
, 0.0, 0.0);
3119 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3120 ok_sequence(sequences
, RENDERER_ID
, draweffect_seq
, "effect draw test", TRUE
);
3121 IDWriteTextLayout_Release(layout
);
3124 hr
= IDWriteFactory_CreateTextLayout(factory
, str2W
, 4, format
, 500.0, 1000.0, &layout
);
3125 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3127 r
.startPosition
= 0;
3129 hr
= IDWriteTextLayout_SetDrawingEffect(layout
, &testeffect
, r
);
3130 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3132 flush_sequence(sequences
, RENDERER_ID
);
3133 hr
= IDWriteTextLayout_Draw(layout
, NULL
, &testrenderer
, 0.0, 0.0);
3134 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3135 ok_sequence(sequences
, RENDERER_ID
, draweffect2_seq
, "effect draw test 2", FALSE
);
3136 IDWriteTextLayout_Release(layout
);
3138 /* Inline object - effect set for same range */
3139 hr
= IDWriteFactory_CreateEllipsisTrimmingSign(factory
, format
, &sign
);
3140 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3142 hr
= IDWriteFactory_CreateTextLayout(factory
, str2W
, 4, format
, 500.0, 1000.0, &layout
);
3143 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3145 r
.startPosition
= 0;
3147 hr
= IDWriteTextLayout_SetInlineObject(layout
, sign
, r
);
3148 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3150 hr
= IDWriteTextLayout_SetDrawingEffect(layout
, &testeffect
, r
);
3151 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3153 flush_sequence(sequences
, RENDERER_ID
);
3154 hr
= IDWriteTextLayout_Draw(layout
, NULL
, &testrenderer
, 0.0, 0.0);
3155 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3156 ok_sequence(sequences
, RENDERER_ID
, draweffect3_seq
, "effect draw test 3", FALSE
);
3158 /* now set effect somewhere inside a range replaced by inline object */
3159 hr
= IDWriteTextLayout_SetDrawingEffect(layout
, NULL
, r
);
3160 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3162 r
.startPosition
= 1;
3164 hr
= IDWriteTextLayout_SetDrawingEffect(layout
, &testeffect
, r
);
3165 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3167 /* no effect is reported in this case */
3168 flush_sequence(sequences
, RENDERER_ID
);
3169 hr
= IDWriteTextLayout_Draw(layout
, NULL
, &testrenderer
, 0.0, 0.0);
3170 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3171 ok_sequence(sequences
, RENDERER_ID
, draweffect4_seq
, "effect draw test 4", FALSE
);
3173 r
.startPosition
= 0;
3175 hr
= IDWriteTextLayout_SetDrawingEffect(layout
, NULL
, r
);
3176 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3178 r
.startPosition
= 0;
3180 hr
= IDWriteTextLayout_SetDrawingEffect(layout
, &testeffect
, r
);
3181 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3183 /* first range position is all that matters for inline ranges */
3184 flush_sequence(sequences
, RENDERER_ID
);
3185 hr
= IDWriteTextLayout_Draw(layout
, NULL
, &testrenderer
, 0.0, 0.0);
3186 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3187 ok_sequence(sequences
, RENDERER_ID
, draweffect3_seq
, "effect draw test 5", FALSE
);
3189 IDWriteTextLayout_Release(layout
);
3191 IDWriteInlineObject_Release(sign
);
3192 IDWriteTextFormat_Release(format
);
3193 IDWriteFactory_Release(factory
);
3196 static IDWriteFontFace
*get_fontface_from_format(IDWriteTextFormat
*format
)
3198 IDWriteFontCollection
*collection
;
3199 IDWriteFontFamily
*family
;
3200 IDWriteFontFace
*fontface
;
3207 hr
= IDWriteTextFormat_GetFontCollection(format
, &collection
);
3208 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3210 hr
= IDWriteTextFormat_GetFontFamilyName(format
, nameW
, sizeof(nameW
)/sizeof(WCHAR
));
3211 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3213 hr
= IDWriteFontCollection_FindFamilyName(collection
, nameW
, &index
, &exists
);
3214 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3216 hr
= IDWriteFontCollection_GetFontFamily(collection
, index
, &family
);
3217 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3218 IDWriteFontCollection_Release(collection
);
3220 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
,
3221 IDWriteTextFormat_GetFontWeight(format
),
3222 IDWriteTextFormat_GetFontStretch(format
),
3223 IDWriteTextFormat_GetFontStyle(format
),
3225 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3227 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
3228 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3230 IDWriteFont_Release(font
);
3231 IDWriteFontFamily_Release(family
);
3236 static BOOL
get_enus_string(IDWriteLocalizedStrings
*strings
, WCHAR
*buff
, UINT32 size
)
3239 BOOL exists
= FALSE
;
3242 hr
= IDWriteLocalizedStrings_FindLocaleName(strings
, enusW
, &index
, &exists
);
3243 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3246 hr
= IDWriteLocalizedStrings_GetString(strings
, index
, buff
, size
);
3247 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3255 static void test_GetLineMetrics(void)
3257 static const WCHAR str3W
[] = {'a','\r','b','\n','c','\n','\r','d','\r','\n',0};
3258 static const WCHAR strW
[] = {'a','b','c','d',' ',0};
3259 static const WCHAR str2W
[] = {'a','b','\r','c','d',0};
3260 static const WCHAR str4W
[] = {'a','\r',0};
3261 IDWriteFontCollection
*syscollection
;
3262 DWRITE_FONT_METRICS fontmetrics
;
3263 DWRITE_LINE_METRICS metrics
[6];
3264 UINT32 count
, i
, familycount
;
3265 IDWriteTextFormat
*format
;
3266 IDWriteTextLayout
*layout
;
3267 IDWriteFontFace
*fontface
;
3268 IDWriteFactory
*factory
;
3269 DWRITE_TEXT_RANGE range
;
3273 factory
= create_factory();
3275 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
3276 DWRITE_FONT_STRETCH_NORMAL
, 2048.0, enusW
, &format
);
3277 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3279 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 5, format
, 30000.0, 1000.0, &layout
);
3280 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3283 hr
= IDWriteTextLayout_GetLineMetrics(layout
, metrics
, 0, &count
);
3284 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
3285 ok(count
== 1, "got count %u\n", count
);
3287 memset(metrics
, 0, sizeof(metrics
));
3288 hr
= IDWriteTextLayout_GetLineMetrics(layout
, metrics
, 1, &count
);
3289 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3290 ok(metrics
[0].length
== 5, "got %u\n", metrics
[0].length
);
3291 ok(metrics
[0].trailingWhitespaceLength
== 1, "got %u\n", metrics
[0].trailingWhitespaceLength
);
3293 ok(metrics
[0].newlineLength
== 0, "got %u\n", metrics
[0].newlineLength
);
3294 ok(metrics
[0].isTrimmed
== FALSE
, "got %d\n", metrics
[0].isTrimmed
);
3296 IDWriteTextLayout_Release(layout
);
3298 /* Test line height and baseline calculation */
3299 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &syscollection
, FALSE
);
3300 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3301 familycount
= IDWriteFontCollection_GetFontFamilyCount(syscollection
);
3303 for (i
= 0; i
< familycount
; i
++) {
3304 static const WCHAR mvboliW
[] = {'M','V',' ','B','o','l','i',0};
3305 IDWriteLocalizedStrings
*names
;
3306 IDWriteFontFamily
*family
;
3313 hr
= IDWriteFontCollection_GetFontFamily(syscollection
, i
, &family
);
3314 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3316 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STRETCH_NORMAL
,
3317 DWRITE_FONT_STYLE_NORMAL
, &font
);
3318 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3320 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
3321 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3323 hr
= IDWriteFontFamily_GetFamilyNames(family
, &names
);
3324 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3326 if (!(exists
= get_enus_string(names
, nameW
, sizeof(nameW
)/sizeof(nameW
[0])))) {
3327 IDWriteLocalFontFileLoader
*localloader
;
3328 IDWriteFontFileLoader
*loader
;
3329 IDWriteFontFile
*file
;
3335 hr
= IDWriteFontFace_GetFiles(fontface
, &count
, &file
);
3336 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3338 hr
= IDWriteFontFile_GetLoader(file
, &loader
);
3339 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3341 hr
= IDWriteFontFileLoader_QueryInterface(loader
, &IID_IDWriteLocalFontFileLoader
, (void**)&localloader
);
3342 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3343 IDWriteFontFileLoader_Release(loader
);
3345 hr
= IDWriteFontFile_GetReferenceKey(file
, &key
, &keysize
);
3346 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3348 hr
= IDWriteLocalFontFileLoader_GetFilePathFromKey(localloader
, key
, keysize
, nameW
, sizeof(nameW
)/sizeof(*nameW
));
3349 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3351 skip("Failed to get English family name, font file %s\n", wine_dbgstr_w(nameW
));
3353 IDWriteLocalFontFileLoader_Release(localloader
);
3354 IDWriteFontFile_Release(file
);
3357 IDWriteLocalizedStrings_Release(names
);
3358 IDWriteFont_Release(font
);
3363 /* This will effectively skip on Vista/2008 only, newer systems work just fine with this font. */
3364 if (!lstrcmpW(nameW
, mvboliW
)) {
3365 skip("Skipping line metrics test for %s, gives inconsistent results\n", wine_dbgstr_w(nameW
));
3369 IDWriteFontFace_GetMetrics(fontface
, &fontmetrics
);
3370 hr
= IDWriteFactory_CreateTextFormat(factory
, nameW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
3371 DWRITE_FONT_STRETCH_NORMAL
, fontmetrics
.designUnitsPerEm
, enusW
, &format
);
3372 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3374 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 5, format
, 30000.0f
, 100.0f
, &layout
);
3375 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3377 memset(metrics
, 0, sizeof(metrics
));
3379 hr
= IDWriteTextLayout_GetLineMetrics(layout
, metrics
, 2, &count
);
3380 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3381 ok(count
== 1, "got %u\n", count
);
3383 ok(metrics
[0].baseline
== fontmetrics
.ascent
+ fontmetrics
.lineGap
, "%s: got %.2f, expected %d, "
3384 "linegap %d\n", wine_dbgstr_w(nameW
), metrics
[0].baseline
, fontmetrics
.ascent
+ fontmetrics
.lineGap
,
3385 fontmetrics
.lineGap
);
3386 ok(metrics
[0].height
== fontmetrics
.ascent
+ fontmetrics
.descent
+ fontmetrics
.lineGap
,
3387 "%s: got %.2f, expected %d, linegap %d\n", wine_dbgstr_w(nameW
), metrics
[0].height
,
3388 fontmetrics
.ascent
+ fontmetrics
.descent
+ fontmetrics
.lineGap
, fontmetrics
.lineGap
);
3392 IDWriteTextLayout_Release(layout
);
3394 IDWriteTextFormat_Release(format
);
3395 IDWriteFontFace_Release(fontface
);
3396 IDWriteFontFamily_Release(family
);
3398 IDWriteFontCollection_Release(syscollection
);
3400 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
3401 DWRITE_FONT_STRETCH_NORMAL
, 2048.0f
, enusW
, &format
);
3402 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3404 fontface
= get_fontface_from_format(format
);
3405 ok(fontface
!= NULL
, "got %p\n", fontface
);
3408 hr
= IDWriteFactory_CreateTextLayout(factory
, str2W
, 5, format
, 10000.0, 1000.0, &layout
);
3409 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3411 memset(metrics
, 0, sizeof(metrics
));
3413 hr
= IDWriteTextLayout_GetLineMetrics(layout
, metrics
, sizeof(metrics
)/sizeof(*metrics
), &count
);
3414 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3415 ok(count
== 2, "got %u\n", count
);
3416 /* baseline is relative to a line, and is not accumulated */
3417 ok(metrics
[0].baseline
== metrics
[1].baseline
, "got %.2f, %.2f\n", metrics
[0].baseline
,
3418 metrics
[1].baseline
);
3420 IDWriteTextLayout_Release(layout
);
3421 IDWriteTextFormat_Release(format
);
3424 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
3425 DWRITE_FONT_STRETCH_NORMAL
, 12.0, enusW
, &format
);
3426 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3428 hr
= IDWriteFactory_CreateTextLayout(factory
, str3W
, 10, format
, 100.0, 300.0, &layout
);
3429 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3431 memset(metrics
, 0xcc, sizeof(metrics
));
3433 hr
= IDWriteTextLayout_GetLineMetrics(layout
, metrics
, sizeof(metrics
)/sizeof(*metrics
), &count
);
3434 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3435 ok(count
== 6, "got %u\n", count
);
3437 ok(metrics
[0].length
== 2, "got %u\n", metrics
[0].length
);
3438 ok(metrics
[1].length
== 2, "got %u\n", metrics
[1].length
);
3439 ok(metrics
[2].length
== 2, "got %u\n", metrics
[2].length
);
3440 ok(metrics
[3].length
== 1, "got %u\n", metrics
[3].length
);
3441 ok(metrics
[4].length
== 3, "got %u\n", metrics
[4].length
);
3442 ok(metrics
[5].length
== 0, "got %u\n", metrics
[5].length
);
3444 ok(metrics
[0].newlineLength
== 1, "got %u\n", metrics
[0].newlineLength
);
3445 ok(metrics
[1].newlineLength
== 1, "got %u\n", metrics
[1].newlineLength
);
3446 ok(metrics
[2].newlineLength
== 1, "got %u\n", metrics
[2].newlineLength
);
3447 ok(metrics
[3].newlineLength
== 1, "got %u\n", metrics
[3].newlineLength
);
3448 ok(metrics
[4].newlineLength
== 2, "got %u\n", metrics
[4].newlineLength
);
3449 ok(metrics
[5].newlineLength
== 0, "got %u\n", metrics
[5].newlineLength
);
3451 ok(metrics
[0].trailingWhitespaceLength
== 1, "got %u\n", metrics
[0].newlineLength
);
3452 ok(metrics
[1].trailingWhitespaceLength
== 1, "got %u\n", metrics
[1].newlineLength
);
3453 ok(metrics
[2].trailingWhitespaceLength
== 1, "got %u\n", metrics
[2].newlineLength
);
3454 ok(metrics
[3].trailingWhitespaceLength
== 1, "got %u\n", metrics
[3].newlineLength
);
3455 ok(metrics
[4].trailingWhitespaceLength
== 2, "got %u\n", metrics
[4].newlineLength
);
3456 ok(metrics
[5].trailingWhitespaceLength
== 0, "got %u\n", metrics
[5].newlineLength
);
3458 IDWriteTextLayout_Release(layout
);
3460 /* empty text layout */
3461 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 0, format
, 100.0f
, 300.0f
, &layout
);
3462 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3465 memset(metrics
, 0, sizeof(metrics
));
3466 hr
= IDWriteTextLayout_GetLineMetrics(layout
, metrics
, 1, &count
);
3467 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3468 ok(count
== 1, "got %u\n", count
);
3469 ok(metrics
[0].length
== 0, "got %u\n", metrics
[0].length
);
3470 ok(metrics
[0].trailingWhitespaceLength
== 0, "got %u\n", metrics
[0].trailingWhitespaceLength
);
3471 ok(metrics
[0].newlineLength
== 0, "got %u\n", metrics
[0].newlineLength
);
3472 ok(metrics
[0].height
> 0.0f
, "got %f\n", metrics
[0].height
);
3473 ok(metrics
[0].baseline
> 0.0f
, "got %f\n", metrics
[0].baseline
);
3474 ok(!metrics
[0].isTrimmed
, "got %d\n", metrics
[0].isTrimmed
);
3476 /* change font size at first position, see if metrics changed */
3477 range
.startPosition
= 0;
3479 hr
= IDWriteTextLayout_SetFontSize(layout
, 80.0f
, range
);
3480 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3483 hr
= IDWriteTextLayout_GetLineMetrics(layout
, metrics
+ 1, 1, &count
);
3484 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3485 ok(count
== 1, "got %u\n", count
);
3486 ok(metrics
[1].height
> metrics
[0].height
, "got %f\n", metrics
[1].height
);
3487 ok(metrics
[1].baseline
> metrics
[0].baseline
, "got %f\n", metrics
[1].baseline
);
3489 /* revert font size back to format value, set different size for position 1 */
3490 hr
= IDWriteTextLayout_SetFontSize(layout
, 12.0f
, range
);
3491 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3493 range
.startPosition
= 1;
3495 hr
= IDWriteTextLayout_SetFontSize(layout
, 80.0f
, range
);
3496 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3498 memset(metrics
+ 1, 0, sizeof(*metrics
));
3500 hr
= IDWriteTextLayout_GetLineMetrics(layout
, metrics
+ 1, 1, &count
);
3501 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3502 ok(count
== 1, "got %u\n", count
);
3503 ok(metrics
[1].height
== metrics
[0].height
, "got %f\n", metrics
[1].height
);
3504 ok(metrics
[1].baseline
== metrics
[0].baseline
, "got %f\n", metrics
[1].baseline
);
3506 IDWriteTextLayout_Release(layout
);
3509 hr
= IDWriteFactory_CreateTextLayout(factory
, str4W
, 2, format
, 100.0f
, 300.0f
, &layout
);
3510 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3513 memset(metrics
, 0, sizeof(metrics
));
3514 hr
= IDWriteTextLayout_GetLineMetrics(layout
, metrics
, sizeof(metrics
)/sizeof(*metrics
), &count
);
3515 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3516 ok(count
== 2, "got %u\n", count
);
3517 ok(metrics
[0].length
== 2, "got %u\n", metrics
[0].length
);
3518 ok(metrics
[0].newlineLength
== 1, "got %u\n", metrics
[0].newlineLength
);
3519 ok(metrics
[0].height
> 0.0f
, "got %f\n", metrics
[0].height
);
3520 ok(metrics
[0].baseline
> 0.0f
, "got %f\n", metrics
[0].baseline
);
3521 ok(metrics
[1].length
== 0, "got %u\n", metrics
[1].length
);
3522 ok(metrics
[1].newlineLength
== 0, "got %u\n", metrics
[1].newlineLength
);
3523 ok(metrics
[1].height
> 0.0f
, "got %f\n", metrics
[1].height
);
3524 ok(metrics
[1].baseline
> 0.0f
, "got %f\n", metrics
[1].baseline
);
3526 range
.startPosition
= 1;
3528 hr
= IDWriteTextLayout_SetFontSize(layout
, 80.0f
, range
);
3529 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3531 hr
= IDWriteTextLayout_GetLineMetrics(layout
, metrics
+ 2, 2, &count
);
3532 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3533 ok(count
== 2, "got %u\n", count
);
3534 ok(metrics
[3].height
> metrics
[1].height
, "got %f, old %f\n", metrics
[3].height
, metrics
[1].height
);
3535 ok(metrics
[3].baseline
> metrics
[1].baseline
, "got %f, old %f\n", metrics
[3].baseline
, metrics
[1].baseline
);
3537 /* revert to original format */
3538 hr
= IDWriteTextLayout_SetFontSize(layout
, 12.0f
, range
);
3539 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3540 hr
= IDWriteTextLayout_GetLineMetrics(layout
, metrics
+ 2, 2, &count
);
3541 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3542 ok(count
== 2, "got %u\n", count
);
3543 ok(metrics
[3].height
== metrics
[1].height
, "got %f, old %f\n", metrics
[3].height
, metrics
[1].height
);
3544 ok(metrics
[3].baseline
== metrics
[1].baseline
, "got %f, old %f\n", metrics
[3].baseline
, metrics
[1].baseline
);
3546 IDWriteTextLayout_Release(layout
);
3548 IDWriteTextFormat_Release(format
);
3549 IDWriteFontFace_Release(fontface
);
3550 IDWriteFactory_Release(factory
);
3553 static void test_SetTextAlignment(void)
3555 static const WCHAR strW
[] = {'a',0};
3557 static const WCHAR stringsW
[][10] = {
3562 DWRITE_CLUSTER_METRICS clusters
[10];
3563 DWRITE_TEXT_METRICS metrics
;
3564 IDWriteTextFormat1
*format1
;
3565 IDWriteTextFormat
*format
;
3566 IDWriteTextLayout
*layout
;
3567 IDWriteFactory
*factory
;
3568 DWRITE_TEXT_ALIGNMENT v
;
3572 factory
= create_factory();
3574 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
3575 DWRITE_FONT_STRETCH_NORMAL
, 12.0, enusW
, &format
);
3576 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3578 v
= IDWriteTextFormat_GetTextAlignment(format
);
3579 ok(v
== DWRITE_TEXT_ALIGNMENT_LEADING
, "got %d\n", v
);
3581 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 1, format
, 500.0, 100.0, &layout
);
3582 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3584 v
= IDWriteTextLayout_GetTextAlignment(layout
);
3585 ok(v
== DWRITE_TEXT_ALIGNMENT_LEADING
, "got %d\n", v
);
3587 hr
= IDWriteTextLayout_SetTextAlignment(layout
, DWRITE_TEXT_ALIGNMENT_TRAILING
);
3588 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3590 hr
= IDWriteTextLayout_SetTextAlignment(layout
, DWRITE_TEXT_ALIGNMENT_TRAILING
);
3591 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3593 v
= IDWriteTextFormat_GetTextAlignment(format
);
3594 ok(v
== DWRITE_TEXT_ALIGNMENT_LEADING
, "got %d\n", v
);
3596 v
= IDWriteTextLayout_GetTextAlignment(layout
);
3597 ok(v
== DWRITE_TEXT_ALIGNMENT_TRAILING
, "got %d\n", v
);
3599 hr
= IDWriteTextLayout_QueryInterface(layout
, &IID_IDWriteTextFormat1
, (void**)&format1
);
3601 hr
= IDWriteTextFormat1_SetTextAlignment(format1
, DWRITE_TEXT_ALIGNMENT_CENTER
);
3602 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3604 v
= IDWriteTextFormat_GetTextAlignment(format
);
3605 ok(v
== DWRITE_TEXT_ALIGNMENT_LEADING
, "got %d\n", v
);
3607 v
= IDWriteTextLayout_GetTextAlignment(layout
);
3608 ok(v
== DWRITE_TEXT_ALIGNMENT_CENTER
, "got %d\n", v
);
3610 v
= IDWriteTextFormat1_GetTextAlignment(format1
);
3611 ok(v
== DWRITE_TEXT_ALIGNMENT_CENTER
, "got %d\n", v
);
3613 IDWriteTextFormat1_Release(format1
);
3616 win_skip("IDWriteTextFormat1 is not supported\n");
3618 for (i
= 0; i
< sizeof(stringsW
)/sizeof(stringsW
[0]); i
++) {
3621 hr
= IDWriteTextFormat_SetTextAlignment(format
, DWRITE_TEXT_ALIGNMENT_LEADING
);
3622 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3624 hr
= IDWriteFactory_CreateTextLayout(factory
, stringsW
[i
], lstrlenW(stringsW
[i
]), format
, 500.0f
, 100.0f
, &layout
);
3625 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3627 hr
= IDWriteTextLayout_SetWordWrapping(layout
, DWRITE_WORD_WRAPPING_NO_WRAP
);
3628 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3631 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, clusters
, sizeof(clusters
)/sizeof(*clusters
), &count
);
3632 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3633 if (lstrlenW(stringsW
[i
]))
3634 ok(count
> 0, "got %u\n", count
);
3636 ok(count
== 0, "got %u\n", count
);
3640 text_width
+= clusters
[--count
].width
;
3642 /* maxwidth is 500, leading alignment */
3643 hr
= IDWriteTextLayout_SetTextAlignment(layout
, DWRITE_TEXT_ALIGNMENT_LEADING
);
3644 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3646 hr
= IDWriteTextLayout_GetMetrics(layout
, &metrics
);
3647 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3649 ok(metrics
.left
== 0.0f
, "got %.2f\n", metrics
.left
);
3650 ok(metrics
.width
== text_width
, "got %.2f\n", metrics
.width
);
3651 ok(metrics
.layoutWidth
== 500.0f
, "got %.2f\n", metrics
.layoutWidth
);
3652 ok(metrics
.lineCount
== 1, "got %d\n", metrics
.lineCount
);
3654 /* maxwidth is 500, trailing alignment */
3655 hr
= IDWriteTextLayout_SetTextAlignment(layout
, DWRITE_TEXT_ALIGNMENT_TRAILING
);
3656 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3658 hr
= IDWriteTextLayout_GetMetrics(layout
, &metrics
);
3659 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3661 ok(metrics
.left
== metrics
.layoutWidth
- metrics
.width
, "got %.2f\n", metrics
.left
);
3662 ok(metrics
.width
== text_width
, "got %.2f\n", metrics
.width
);
3663 ok(metrics
.layoutWidth
== 500.0f
, "got %.2f\n", metrics
.layoutWidth
);
3664 ok(metrics
.lineCount
== 1, "got %d\n", metrics
.lineCount
);
3665 IDWriteTextLayout_Release(layout
);
3667 /* initially created with trailing alignment */
3668 hr
= IDWriteTextFormat_SetTextAlignment(format
, DWRITE_TEXT_ALIGNMENT_TRAILING
);
3669 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3671 hr
= IDWriteFactory_CreateTextLayout(factory
, stringsW
[i
], lstrlenW(stringsW
[i
]), format
, 500.0f
, 100.0f
, &layout
);
3672 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3674 hr
= IDWriteTextLayout_GetMetrics(layout
, &metrics
);
3675 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3677 ok(metrics
.left
== metrics
.layoutWidth
- metrics
.width
, "got %.2f\n", metrics
.left
);
3678 ok(metrics
.width
== text_width
, "got %.2f\n", metrics
.width
);
3679 ok(metrics
.layoutWidth
== 500.0f
, "got %.2f\n", metrics
.layoutWidth
);
3680 ok(metrics
.lineCount
== 1, "got %d\n", metrics
.lineCount
);
3681 IDWriteTextLayout_Release(layout
);
3683 if (lstrlenW(stringsW
[i
]) > 0) {
3684 /* max width less than total run width, trailing alignment */
3685 hr
= IDWriteTextFormat_SetWordWrapping(format
, DWRITE_WORD_WRAPPING_NO_WRAP
);
3686 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3688 hr
= IDWriteFactory_CreateTextLayout(factory
, stringsW
[i
], lstrlenW(stringsW
[i
]), format
, clusters
[0].width
, 100.0f
, &layout
);
3689 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3690 hr
= IDWriteTextLayout_GetMetrics(layout
, &metrics
);
3691 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3692 ok(metrics
.left
== metrics
.layoutWidth
- metrics
.width
, "got %.2f\n", metrics
.left
);
3693 ok(metrics
.width
== text_width
, "got %.2f\n", metrics
.width
);
3694 ok(metrics
.lineCount
== 1, "got %d\n", metrics
.lineCount
);
3695 IDWriteTextLayout_Release(layout
);
3698 /* maxwidth is 500, centered */
3699 hr
= IDWriteTextFormat_SetTextAlignment(format
, DWRITE_TEXT_ALIGNMENT_CENTER
);
3700 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3702 hr
= IDWriteFactory_CreateTextLayout(factory
, stringsW
[i
], lstrlenW(stringsW
[i
]), format
, 500.0f
, 100.0f
, &layout
);
3703 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3705 hr
= IDWriteTextLayout_GetMetrics(layout
, &metrics
);
3706 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3707 ok(metrics
.left
== (metrics
.layoutWidth
- metrics
.width
) / 2.0f
, "got %.2f\n", metrics
.left
);
3708 ok(metrics
.width
== text_width
, "got %.2f\n", metrics
.width
);
3709 ok(metrics
.lineCount
== 1, "got %d\n", metrics
.lineCount
);
3711 IDWriteTextLayout_Release(layout
);
3714 IDWriteTextFormat_Release(format
);
3715 IDWriteFactory_Release(factory
);
3718 static void test_SetParagraphAlignment(void)
3720 static const WCHAR strW
[] = {'a',0};
3721 DWRITE_TEXT_METRICS metrics
;
3722 IDWriteTextFormat
*format
;
3723 IDWriteTextLayout
*layout
;
3724 IDWriteFactory
*factory
;
3725 DWRITE_PARAGRAPH_ALIGNMENT v
;
3726 DWRITE_LINE_METRICS lines
[1];
3730 factory
= create_factory();
3732 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
3733 DWRITE_FONT_STRETCH_NORMAL
, 12.0, enusW
, &format
);
3734 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3736 v
= IDWriteTextFormat_GetParagraphAlignment(format
);
3737 ok(v
== DWRITE_PARAGRAPH_ALIGNMENT_NEAR
, "got %d\n", v
);
3739 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 1, format
, 500.0, 100.0, &layout
);
3740 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3742 v
= IDWriteTextLayout_GetParagraphAlignment(layout
);
3743 ok(v
== DWRITE_PARAGRAPH_ALIGNMENT_NEAR
, "got %d\n", v
);
3745 hr
= IDWriteTextLayout_SetParagraphAlignment(layout
, DWRITE_PARAGRAPH_ALIGNMENT_FAR
);
3746 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3748 hr
= IDWriteTextLayout_SetParagraphAlignment(layout
, DWRITE_PARAGRAPH_ALIGNMENT_FAR
);
3749 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3751 v
= IDWriteTextFormat_GetParagraphAlignment(format
);
3752 ok(v
== DWRITE_PARAGRAPH_ALIGNMENT_NEAR
, "got %d\n", v
);
3754 v
= IDWriteTextLayout_GetParagraphAlignment(layout
);
3755 ok(v
== DWRITE_PARAGRAPH_ALIGNMENT_FAR
, "got %d\n", v
);
3757 hr
= IDWriteTextLayout_SetParagraphAlignment(layout
, DWRITE_PARAGRAPH_ALIGNMENT_CENTER
);
3758 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3760 v
= IDWriteTextLayout_GetParagraphAlignment(layout
);
3761 ok(v
== DWRITE_PARAGRAPH_ALIGNMENT_CENTER
, "got %d\n", v
);
3764 hr
= IDWriteTextLayout_GetLineMetrics(layout
, lines
, 1, &count
);
3765 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3766 ok(count
== 1, "got %u\n", count
);
3768 /* maxheight is 100, near alignment */
3769 hr
= IDWriteTextLayout_SetParagraphAlignment(layout
, DWRITE_PARAGRAPH_ALIGNMENT_NEAR
);
3770 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3772 hr
= IDWriteTextLayout_GetMetrics(layout
, &metrics
);
3773 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3775 ok(metrics
.top
== 0.0, "got %.2f\n", metrics
.top
);
3776 ok(metrics
.height
== lines
[0].height
, "got %.2f\n", metrics
.height
);
3777 ok(metrics
.layoutHeight
== 100.0, "got %.2f\n", metrics
.layoutHeight
);
3778 ok(metrics
.lineCount
== 1, "got %d\n", metrics
.lineCount
);
3780 /* maxwidth is 100, far alignment */
3781 hr
= IDWriteTextLayout_SetParagraphAlignment(layout
, DWRITE_PARAGRAPH_ALIGNMENT_FAR
);
3782 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3784 hr
= IDWriteTextLayout_GetMetrics(layout
, &metrics
);
3785 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3787 ok(metrics
.top
== metrics
.layoutHeight
- metrics
.height
, "got %.2f\n", metrics
.top
);
3788 ok(metrics
.height
== lines
[0].height
, "got %.2f\n", metrics
.height
);
3789 ok(metrics
.layoutHeight
== 100.0, "got %.2f\n", metrics
.layoutHeight
);
3790 ok(metrics
.lineCount
== 1, "got %d\n", metrics
.lineCount
);
3791 IDWriteTextLayout_Release(layout
);
3793 /* initially created with centered alignment */
3794 hr
= IDWriteTextFormat_SetParagraphAlignment(format
, DWRITE_PARAGRAPH_ALIGNMENT_CENTER
);
3795 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3797 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 1, format
, 500.0, 100.0, &layout
);
3798 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3800 hr
= IDWriteTextLayout_GetMetrics(layout
, &metrics
);
3801 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3803 ok(metrics
.top
== (metrics
.layoutHeight
- lines
[0].height
) / 2, "got %.2f\n", metrics
.top
);
3804 ok(metrics
.height
== lines
[0].height
, "got %.2f\n", metrics
.height
);
3805 ok(metrics
.lineCount
== 1, "got %d\n", metrics
.lineCount
);
3806 IDWriteTextLayout_Release(layout
);
3808 IDWriteTextFormat_Release(format
);
3809 IDWriteFactory_Release(factory
);
3812 static void test_SetReadingDirection(void)
3814 static const WCHAR strW
[] = {'a',0};
3815 DWRITE_CLUSTER_METRICS clusters
[1];
3816 DWRITE_TEXT_METRICS metrics
;
3817 IDWriteTextFormat
*format
;
3818 IDWriteTextLayout
*layout
;
3819 IDWriteFactory
*factory
;
3820 DWRITE_READING_DIRECTION v
;
3821 DWRITE_LINE_METRICS lines
[1];
3825 factory
= create_factory();
3827 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
3828 DWRITE_FONT_STRETCH_NORMAL
, 12.0, enusW
, &format
);
3829 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3831 v
= IDWriteTextFormat_GetReadingDirection(format
);
3832 ok(v
== DWRITE_READING_DIRECTION_LEFT_TO_RIGHT
, "got %d\n", v
);
3834 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 1, format
, 500.0, 100.0, &layout
);
3835 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3837 v
= IDWriteTextLayout_GetReadingDirection(layout
);
3838 ok(v
== DWRITE_READING_DIRECTION_LEFT_TO_RIGHT
, "got %d\n", v
);
3840 v
= IDWriteTextFormat_GetReadingDirection(format
);
3841 ok(v
== DWRITE_READING_DIRECTION_LEFT_TO_RIGHT
, "got %d\n", v
);
3843 hr
= IDWriteTextLayout_SetReadingDirection(layout
, DWRITE_READING_DIRECTION_RIGHT_TO_LEFT
);
3844 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3847 hr
= IDWriteTextLayout_GetLineMetrics(layout
, lines
, 1, &count
);
3848 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3849 ok(count
== 1, "got %u\n", count
);
3852 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, clusters
, 1, &count
);
3853 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3854 ok(count
== 1, "got %u\n", count
);
3856 /* leading alignment, RTL */
3857 hr
= IDWriteTextLayout_GetMetrics(layout
, &metrics
);
3858 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3860 ok(metrics
.left
== metrics
.layoutWidth
- clusters
[0].width
, "got %.2f\n", metrics
.left
);
3861 ok(metrics
.top
== 0.0, "got %.2f\n", metrics
.top
);
3862 ok(metrics
.width
== clusters
[0].width
, "got %.2f\n", metrics
.width
);
3863 ok(metrics
.height
== lines
[0].height
, "got %.2f\n", metrics
.height
);
3864 ok(metrics
.layoutWidth
== 500.0, "got %.2f\n", metrics
.layoutWidth
);
3865 ok(metrics
.layoutHeight
== 100.0, "got %.2f\n", metrics
.layoutHeight
);
3866 ok(metrics
.lineCount
== 1, "got %d\n", metrics
.lineCount
);
3868 /* trailing alignment, RTL */
3869 hr
= IDWriteTextLayout_SetTextAlignment(layout
, DWRITE_TEXT_ALIGNMENT_TRAILING
);
3870 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3872 hr
= IDWriteTextLayout_GetMetrics(layout
, &metrics
);
3873 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3875 ok(metrics
.left
== 0.0, "got %.2f\n", metrics
.left
);
3876 ok(metrics
.top
== 0.0, "got %.2f\n", metrics
.top
);
3877 ok(metrics
.width
== clusters
[0].width
, "got %.2f\n", metrics
.width
);
3878 ok(metrics
.height
== lines
[0].height
, "got %.2f\n", metrics
.height
);
3879 ok(metrics
.layoutWidth
== 500.0, "got %.2f\n", metrics
.layoutWidth
);
3880 ok(metrics
.layoutHeight
== 100.0, "got %.2f\n", metrics
.layoutHeight
);
3881 ok(metrics
.lineCount
== 1, "got %d\n", metrics
.lineCount
);
3883 /* centered alignment, RTL */
3884 hr
= IDWriteTextLayout_SetTextAlignment(layout
, DWRITE_TEXT_ALIGNMENT_CENTER
);
3885 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3887 hr
= IDWriteTextLayout_GetMetrics(layout
, &metrics
);
3888 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3890 ok(metrics
.left
== (metrics
.layoutWidth
- clusters
[0].width
) / 2.0, "got %.2f\n", metrics
.left
);
3891 ok(metrics
.top
== 0.0, "got %.2f\n", metrics
.top
);
3892 ok(metrics
.width
== clusters
[0].width
, "got %.2f\n", metrics
.width
);
3893 ok(metrics
.height
== lines
[0].height
, "got %.2f\n", metrics
.height
);
3894 ok(metrics
.layoutWidth
== 500.0, "got %.2f\n", metrics
.layoutWidth
);
3895 ok(metrics
.layoutHeight
== 100.0, "got %.2f\n", metrics
.layoutHeight
);
3896 ok(metrics
.lineCount
== 1, "got %d\n", metrics
.lineCount
);
3898 IDWriteTextLayout_Release(layout
);
3900 IDWriteTextFormat_Release(format
);
3901 IDWriteFactory_Release(factory
);
3904 static inline FLOAT
get_scaled_font_metric(UINT32 metric
, FLOAT emSize
, const DWRITE_FONT_METRICS
*metrics
)
3906 return (FLOAT
)metric
* emSize
/ (FLOAT
)metrics
->designUnitsPerEm
;
3909 static FLOAT
snap_coord(const DWRITE_MATRIX
*m
, FLOAT ppdip
, FLOAT coord
)
3911 FLOAT vec
[2], det
, vec2
[2];
3914 /* has to be a diagonal matrix */
3915 if ((ppdip
<= 0.0) ||
3916 (m
->m11
* m
->m22
!= 0.0 && (m
->m12
!= 0.0 || m
->m21
!= 0.0)) ||
3917 (m
->m12
* m
->m21
!= 0.0 && (m
->m11
!= 0.0 || m
->m22
!= 0.0)))
3920 det
= m
->m11
* m
->m22
- m
->m12
* m
->m21
;
3921 transform
= fabsf(det
) > 1e-10;
3924 /* apply transform */
3926 vec
[1] = coord
* ppdip
;
3928 vec2
[0] = m
->m11
* vec
[0] + m
->m21
* vec
[1] + m
->dx
;
3929 vec2
[1] = m
->m12
* vec
[0] + m
->m22
* vec
[1] + m
->dy
;
3932 vec2
[0] = floorf(vec2
[0] + 0.5f
);
3933 vec2
[1] = floorf(vec2
[1] + 0.5f
);
3935 /* apply inverted transform */
3936 vec
[1] = (-m
->m12
* vec2
[0] + m
->m11
* vec2
[1] - (m
->m11
* m
->dy
- m
->m12
* m
->dx
)) / det
;
3940 vec
[1] = floorf(coord
* ppdip
+ 0.5f
) / ppdip
;
3944 static inline BOOL
float_eq(FLOAT left
, FLOAT right
)
3946 int x
= *(int *)&left
;
3947 int y
= *(int *)&right
;
3954 return abs(x
- y
) <= 16;
3957 struct snapping_test
{
3962 static struct snapping_test snapping_tests
[] = {
3963 { { 0.0, 1.0, 2.0, 0.0, 0.2, 0.3 }, 1.0 },
3964 { { 0.0, 1.0, 2.0, 0.0, 0.0, 0.0 }, 1.0 },
3965 { { 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 }, 1.0 }, /* identity transform */
3966 { { 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 }, 0.9 },
3967 { { 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 }, -1.0 },
3968 { { 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 }, 0.0 },
3969 { { 1.0, 0.0, 0.0, 1.0, 0.0, 0.3 }, 1.0 }, /* simple Y shift */
3970 { { 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 }, 10.0 }, /* identity, 10 ppdip */
3971 { { 1.0, 0.0, 0.0, 10.0, 0.0, 0.0 }, 10.0 },
3972 { { 0.0, 1.0, 1.0, 0.0, 0.2, 0.6 }, 1.0 },
3973 { { 0.0, 2.0, 2.0, 0.0, 0.2, 0.6 }, 1.0 },
3974 { { 0.0, 0.5, -0.5, 0.0, 0.2, 0.6 }, 1.0 },
3975 { { 1.0, 2.0, 0.0, 1.0, 0.2, 0.6 }, 1.0 },
3976 { { 1.0, 1.0, 0.0, 1.0, 0.2, 0.6 }, 1.0 },
3977 { { 0.5, 0.5, -0.5, 0.5, 0.2, 0.6 }, 1.0 }, /* 45 degrees rotation */
3978 { { 0.5, 0.5, -0.5, 0.5, 0.0, 0.0 }, 100.0 }, /* 45 degrees rotation */
3979 { { 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 }, 100.0 },
3980 { { 0.0, 1.0, -1.0, 0.0, 0.2, 0.6 }, 1.0 }, /* 90 degrees rotation */
3981 { { -1.0, 0.0, 0.0, -1.0, 0.2, 0.6 }, 1.0 }, /* 180 degrees rotation */
3982 { { 0.0, -1.0, 1.0, 0.0, 0.2, 0.6 }, 1.0 }, /* 270 degrees rotation */
3983 { { 1.0, 0.0, 0.0, 1.0,-0.1, 0.2 }, 1.0 },
3984 { { 0.0, 1.0, -1.0, 0.0,-0.2,-0.3 }, 1.0 }, /* 90 degrees rotation */
3985 { { -1.0, 0.0, 0.0, -1.0,-0.3,-1.6 }, 1.0 }, /* 180 degrees rotation */
3986 { { 0.0, -1.0, 1.0, 0.0,-0.7, 0.6 }, 10.0 }, /* 270 degrees rotation */
3987 { { 0.0, 2.0, 1.0, 0.0, 0.2, 0.6 }, 1.0 },
3988 { { 0.0, 0.0, 1.0, 0.0, 0.0, 0.0 }, 1.0 },
3989 { { 3.0, 0.0, 0.0, 5.0, 0.2,-0.3 }, 10.0 },
3990 { { 0.0, -3.0, 5.0, 0.0,-0.1, 0.7 }, 10.0 },
3993 static DWRITE_MATRIX compattransforms
[] = {
3994 { 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 },
3995 { 1.0, 0.0, 0.0, 1.0, 0.2, 0.3 },
3996 { 2.0, 0.0, 0.0, 2.0, 0.2, 0.3 },
3997 { 2.0, 1.0, 2.0, 2.0, 0.2, 0.3 },
4000 static void test_pixelsnapping(void)
4002 static const WCHAR strW
[] = {'a',0};
4003 IDWriteTextLayout
*layout
, *layout2
;
4004 struct renderer_context ctxt
;
4005 DWRITE_FONT_METRICS metrics
;
4006 IDWriteTextFormat
*format
;
4007 IDWriteFontFace
*fontface
;
4008 IDWriteFactory
*factory
;
4009 FLOAT baseline
, originX
;
4013 factory
= create_factory();
4015 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
4016 DWRITE_FONT_STRETCH_NORMAL
, 12.0, enusW
, &format
);
4017 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4019 fontface
= get_fontface_from_format(format
);
4020 IDWriteFontFace_GetMetrics(fontface
, &metrics
);
4022 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 1, format
, 500.0, 100.0, &layout
);
4023 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4025 /* disabled snapping */
4026 ctxt
.snapping_disabled
= TRUE
;
4027 ctxt
.gdicompat
= FALSE
;
4028 ctxt
.use_gdi_natural
= FALSE
;
4030 memset(&ctxt
.m
, 0, sizeof(ctxt
.m
));
4031 ctxt
.m
.m11
= ctxt
.m
.m22
= 1.0;
4034 hr
= IDWriteTextLayout_Draw(layout
, &ctxt
, &testrenderer
, originX
, 0.0);
4035 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4037 baseline
= get_scaled_font_metric(metrics
.ascent
, 12.0, &metrics
);
4038 ok(ctxt
.originX
== originX
, "got %f, originX %f\n", ctxt
.originX
, originX
);
4039 ok(ctxt
.originY
== baseline
, "got %f, baseline %f\n", ctxt
.originY
, baseline
);
4040 ok(floor(baseline
) != baseline
, "got %f\n", baseline
);
4042 ctxt
.snapping_disabled
= FALSE
;
4044 for (i
= 0; i
< sizeof(snapping_tests
)/sizeof(snapping_tests
[0]); i
++) {
4045 struct snapping_test
*ptr
= &snapping_tests
[i
];
4049 ctxt
.ppdip
= ptr
->ppdip
;
4050 ctxt
.originX
= 678.9;
4051 ctxt
.originY
= 678.9;
4053 expectedY
= snap_coord(&ctxt
.m
, ctxt
.ppdip
, baseline
);
4054 hr
= IDWriteTextLayout_Draw(layout
, &ctxt
, &testrenderer
, originX
, 0.0);
4055 ok(hr
== S_OK
, "%d: got 0x%08x\n", i
, hr
);
4056 ok(ctxt
.originX
== originX
, "%d: got %f, originX %f\n", i
, ctxt
.originX
, originX
);
4057 ok(float_eq(ctxt
.originY
, expectedY
), "%d: got %f, expected %f, baseline %f\n",
4058 i
, ctxt
.originY
, expectedY
, baseline
);
4060 /* gdicompat layout transform doesn't affect snapping */
4061 for (j
= 0; j
< sizeof(compattransforms
)/sizeof(compattransforms
[0]); j
++) {
4062 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, strW
, 1, format
, 500.0, 100.0,
4063 1.0, &compattransforms
[j
], FALSE
, &layout2
);
4064 ok(hr
== S_OK
, "%d: got 0x%08x\n", i
, hr
);
4066 expectedY
= snap_coord(&ctxt
.m
, ctxt
.ppdip
, baseline
);
4067 hr
= IDWriteTextLayout_Draw(layout
, &ctxt
, &testrenderer
, originX
, 0.0);
4068 ok(hr
== S_OK
, "%d: got 0x%08x\n", i
, hr
);
4069 ok(ctxt
.originX
== originX
, "%d: got %f, originX %f\n", i
, ctxt
.originX
, originX
);
4070 ok(float_eq(ctxt
.originY
, expectedY
), "%d: got %f, expected %f, baseline %f\n",
4071 i
, ctxt
.originY
, expectedY
, baseline
);
4073 IDWriteTextLayout_Release(layout2
);
4077 IDWriteTextLayout_Release(layout
);
4078 IDWriteTextFormat_Release(format
);
4079 IDWriteFontFace_Release(fontface
);
4080 IDWriteFactory_Release(factory
);
4083 static void test_SetWordWrapping(void)
4085 static const WCHAR strW
[] = {'a',' ','s','o','m','e',' ','t','e','x','t',' ','a','n','d',
4086 ' ','a',' ','b','i','t',' ','m','o','r','e','\n','b'};
4087 IDWriteTextFormat
*format
;
4088 IDWriteTextLayout
*layout
;
4089 IDWriteFactory
*factory
;
4090 DWRITE_WORD_WRAPPING v
;
4094 factory
= create_factory();
4096 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
4097 DWRITE_FONT_STRETCH_NORMAL
, 12.0, enusW
, &format
);
4098 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4100 v
= IDWriteTextFormat_GetWordWrapping(format
);
4101 ok(v
== DWRITE_WORD_WRAPPING_WRAP
, "got %d\n", v
);
4103 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, sizeof(strW
)/sizeof(WCHAR
), format
, 10.0f
, 100.0f
, &layout
);
4104 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4106 v
= IDWriteTextLayout_GetWordWrapping(layout
);
4107 ok(v
== DWRITE_WORD_WRAPPING_WRAP
, "got %d\n", v
);
4109 hr
= IDWriteTextLayout_SetWordWrapping(layout
, DWRITE_WORD_WRAPPING_NO_WRAP
);
4110 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4112 hr
= IDWriteTextLayout_SetWordWrapping(layout
, DWRITE_WORD_WRAPPING_NO_WRAP
);
4113 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4115 v
= IDWriteTextFormat_GetWordWrapping(format
);
4116 ok(v
== DWRITE_WORD_WRAPPING_WRAP
, "got %d\n", v
);
4118 /* disable wrapping, text has explicit newline */
4119 hr
= IDWriteTextLayout_SetWordWrapping(layout
, DWRITE_WORD_WRAPPING_NO_WRAP
);
4120 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4123 hr
= IDWriteTextLayout_GetLineMetrics(layout
, NULL
, 0, &count
);
4124 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
4125 ok(count
== 2, "got %u\n", count
);
4127 hr
= IDWriteTextLayout_SetWordWrapping(layout
, DWRITE_WORD_WRAPPING_WRAP
);
4128 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4131 hr
= IDWriteTextLayout_GetLineMetrics(layout
, NULL
, 0, &count
);
4132 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
4133 ok(count
> 2, "got %u\n", count
);
4135 IDWriteTextLayout_Release(layout
);
4136 IDWriteTextFormat_Release(format
);
4137 IDWriteFactory_Release(factory
);
4140 /* Collection dedicated to fallback testing */
4142 static const WCHAR g_blahfontW
[] = {'B','l','a','h',0};
4143 static HRESULT WINAPI
fontcollection_QI(IDWriteFontCollection
*iface
, REFIID riid
, void **obj
)
4145 if (IsEqualIID(riid
, &IID_IDWriteFontCollection
) || IsEqualIID(riid
, &IID_IUnknown
)) {
4147 IDWriteFontCollection_AddRef(iface
);
4152 return E_NOINTERFACE
;
4155 static ULONG WINAPI
fontcollection_AddRef(IDWriteFontCollection
*iface
)
4160 static ULONG WINAPI
fontcollection_Release(IDWriteFontCollection
*iface
)
4165 static UINT32 WINAPI
fontcollection_GetFontFamilyCount(IDWriteFontCollection
*iface
)
4167 ok(0, "unexpected call\n");
4171 static HRESULT WINAPI
fontcollection_GetFontFamily(IDWriteFontCollection
*iface
, UINT32 index
, IDWriteFontFamily
**family
)
4173 if (index
== 123456) {
4174 IDWriteFactory
*factory
= create_factory();
4175 IDWriteFontCollection
*syscollection
;
4179 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &syscollection
, FALSE
);
4180 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4182 hr
= IDWriteFontCollection_FindFamilyName(syscollection
, tahomaW
, &index
, &exists
);
4183 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4185 hr
= IDWriteFontCollection_GetFontFamily(syscollection
, index
, family
);
4186 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4188 IDWriteFontCollection_Release(syscollection
);
4189 IDWriteFactory_Release(factory
);
4192 ok(0, "unexpected call\n");
4196 static HRESULT WINAPI
fontcollection_FindFamilyName(IDWriteFontCollection
*iface
, WCHAR
const *name
, UINT32
*index
, BOOL
*exists
)
4198 if (!lstrcmpW(name
, g_blahfontW
)) {
4203 ok(0, "unexpected call, name %s\n", wine_dbgstr_w(name
));
4207 static HRESULT WINAPI
fontcollection_GetFontFromFontFace(IDWriteFontCollection
*iface
, IDWriteFontFace
*face
, IDWriteFont
**font
)
4209 ok(0, "unexpected call\n");
4213 static const IDWriteFontCollectionVtbl fallbackcollectionvtbl
= {
4215 fontcollection_AddRef
,
4216 fontcollection_Release
,
4217 fontcollection_GetFontFamilyCount
,
4218 fontcollection_GetFontFamily
,
4219 fontcollection_FindFamilyName
,
4220 fontcollection_GetFontFromFontFace
4223 static IDWriteFontCollection fallbackcollection
= { &fallbackcollectionvtbl
};
4225 static void test_MapCharacters(void)
4227 static const WCHAR strW
[] = {'a','b','c',0};
4228 static const WCHAR str2W
[] = {'a',0x3058,'b',0};
4229 IDWriteLocalizedStrings
*strings
;
4230 IDWriteFontFallback
*fallback
;
4231 IDWriteFactory2
*factory2
;
4232 IDWriteFactory
*factory
;
4233 UINT32 mappedlength
;
4240 factory
= create_factory();
4242 hr
= IDWriteFactory_QueryInterface(factory
, &IID_IDWriteFactory2
, (void**)&factory2
);
4243 IDWriteFactory_Release(factory
);
4245 win_skip("MapCharacters() is not supported\n");
4250 hr
= IDWriteFactory2_GetSystemFontFallback(factory2
, &fallback
);
4251 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4252 ok(fallback
!= NULL
, "got %p\n", fallback
);
4256 font
= (void*)0xdeadbeef;
4257 hr
= IDWriteFontFallback_MapCharacters(fallback
, NULL
, 0, 0, NULL
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
,
4258 DWRITE_FONT_STYLE_NORMAL
, DWRITE_FONT_STRETCH_NORMAL
, &mappedlength
, &font
, &scale
);
4259 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
4260 ok(mappedlength
== 0, "got %u\n", mappedlength
);
4261 ok(scale
== 1.0f
, "got %f\n", scale
);
4262 ok(font
== NULL
, "got %p\n", font
);
4264 /* zero length source */
4268 font
= (void*)0xdeadbeef;
4269 hr
= IDWriteFontFallback_MapCharacters(fallback
, &analysissource
, 0, 0, NULL
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
,
4270 DWRITE_FONT_STYLE_NORMAL
, DWRITE_FONT_STRETCH_NORMAL
, &mappedlength
, &font
, &scale
);
4271 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4272 ok(mappedlength
== 0, "got %u\n", mappedlength
);
4273 ok(scale
== 1.0f
, "got %f\n", scale
);
4274 ok(font
== NULL
, "got %p\n", font
);
4280 hr
= IDWriteFontFallback_MapCharacters(fallback
, &analysissource
, 0, 1, NULL
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
,
4281 DWRITE_FONT_STYLE_NORMAL
, DWRITE_FONT_STRETCH_NORMAL
, &mappedlength
, &font
, &scale
);
4283 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4284 ok(mappedlength
== 1, "got %u\n", mappedlength
);
4286 ok(scale
== 1.0f
, "got %f\n", scale
);
4288 ok(font
!= NULL
, "got %p\n", font
);
4290 IDWriteFont_Release(font
);
4292 /* same latin text, full length */
4297 hr
= IDWriteFontFallback_MapCharacters(fallback
, &analysissource
, 0, 3, NULL
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
,
4298 DWRITE_FONT_STYLE_NORMAL
, DWRITE_FONT_STRETCH_NORMAL
, &mappedlength
, &font
, &scale
);
4300 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4301 ok(mappedlength
== 3, "got %u\n", mappedlength
);
4303 ok(scale
== 1.0f
, "got %f\n", scale
);
4305 ok(font
!= NULL
, "got %p\n", font
);
4307 IDWriteFont_Release(font
);
4309 /* string 'a\x3058b' */
4314 hr
= IDWriteFontFallback_MapCharacters(fallback
, &analysissource
, 0, 3, NULL
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
,
4315 DWRITE_FONT_STYLE_NORMAL
, DWRITE_FONT_STRETCH_NORMAL
, &mappedlength
, &font
, &scale
);
4317 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4318 ok(mappedlength
== 1, "got %u\n", mappedlength
);
4320 ok(scale
== 1.0f
, "got %f\n", scale
);
4322 ok(font
!= NULL
, "got %p\n", font
);
4324 IDWriteFont_Release(font
);
4330 hr
= IDWriteFontFallback_MapCharacters(fallback
, &analysissource
, 1, 2, NULL
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
,
4331 DWRITE_FONT_STYLE_NORMAL
, DWRITE_FONT_STRETCH_NORMAL
, &mappedlength
, &font
, &scale
);
4333 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4334 ok(mappedlength
== 1, "got %u\n", mappedlength
);
4336 ok(scale
== 1.0f
, "got %f\n", scale
);
4338 ok(font
!= NULL
, "got %p\n", font
);
4340 /* font returned for Hiragana character, check if it supports Latin too */
4342 hr
= IDWriteFont_HasCharacter(font
, 'b', &exists
);
4343 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4344 ok(exists
, "got %d\n", exists
);
4346 IDWriteFont_Release(font
);
4348 /* Try with explicit collection, Tahoma will be forced. */
4354 hr
= IDWriteFontFallback_MapCharacters(fallback
, &analysissource
, 0, 3, &fallbackcollection
, g_blahfontW
, DWRITE_FONT_WEIGHT_NORMAL
,
4355 DWRITE_FONT_STYLE_NORMAL
, DWRITE_FONT_STRETCH_NORMAL
, &mappedlength
, &font
, &scale
);
4356 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4357 ok(mappedlength
== 1, "got %u\n", mappedlength
);
4358 ok(scale
== 1.0f
, "got %f\n", scale
);
4359 ok(font
!= NULL
, "got %p\n", font
);
4362 hr
= IDWriteFont_GetInformationalStrings(font
, DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES
, &strings
, &exists
);
4363 ok(hr
== S_OK
&& exists
, "got 0x%08x, exists %d\n", hr
, exists
);
4364 hr
= IDWriteLocalizedStrings_GetString(strings
, 0, buffW
, sizeof(buffW
)/sizeof(WCHAR
));
4365 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4366 ok(!lstrcmpW(buffW
, tahomaW
), "%s\n", wine_dbgstr_w(buffW
));
4367 IDWriteLocalizedStrings_Release(strings
);
4368 IDWriteFont_Release(font
);
4370 /* 2. Hiragana character, force Tahoma font does not support Japanese */
4375 hr
= IDWriteFontFallback_MapCharacters(fallback
, &analysissource
, 1, 1, &fallbackcollection
, g_blahfontW
, DWRITE_FONT_WEIGHT_NORMAL
,
4376 DWRITE_FONT_STYLE_NORMAL
, DWRITE_FONT_STRETCH_NORMAL
, &mappedlength
, &font
, &scale
);
4377 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4378 ok(mappedlength
== 1, "got %u\n", mappedlength
);
4379 ok(scale
== 1.0f
, "got %f\n", scale
);
4380 ok(font
!= NULL
, "got %p\n", font
);
4383 hr
= IDWriteFont_GetInformationalStrings(font
, DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES
, &strings
, &exists
);
4384 ok(hr
== S_OK
&& exists
, "got 0x%08x, exists %d\n", hr
, exists
);
4385 hr
= IDWriteLocalizedStrings_GetString(strings
, 0, buffW
, sizeof(buffW
)/sizeof(WCHAR
));
4386 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4388 ok(lstrcmpW(buffW
, tahomaW
), "%s\n", wine_dbgstr_w(buffW
));
4389 IDWriteLocalizedStrings_Release(strings
);
4390 IDWriteFont_Release(font
);
4392 IDWriteFontFallback_Release(fallback
);
4393 IDWriteFactory2_Release(factory2
);
4396 static void test_FontFallbackBuilder(void)
4398 static const WCHAR localeW
[] = {'l','o','c','a','l','e',0};
4399 static const WCHAR strW
[] = {'A',0};
4400 IDWriteFontFallbackBuilder
*builder
;
4401 IDWriteFontFallback
*fallback
;
4402 DWRITE_UNICODE_RANGE range
;
4403 IDWriteFactory2
*factory2
;
4404 IDWriteFactory
*factory
;
4405 const WCHAR
*familyW
;
4406 UINT32 mappedlength
;
4411 factory
= create_factory();
4413 hr
= IDWriteFactory_QueryInterface(factory
, &IID_IDWriteFactory2
, (void**)&factory2
);
4414 IDWriteFactory_Release(factory
);
4417 hr
= IDWriteFactory2_CreateFontFallbackBuilder(factory2
, &builder
);
4420 skip("IDWriteFontFallbackBuilder is not supported\n");
4424 hr
= IDWriteFontFallbackBuilder_CreateFontFallback(builder
, &fallback
);
4425 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4427 hr
= IDWriteFontFallbackBuilder_AddMapping(builder
, NULL
, 0, NULL
, 0, NULL
, NULL
, NULL
, 0.0f
);
4428 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
4432 hr
= IDWriteFontFallbackBuilder_AddMapping(builder
, &range
, 0, NULL
, 0, NULL
, NULL
, NULL
, 0.0f
);
4433 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
4435 hr
= IDWriteFontFallbackBuilder_AddMapping(builder
, &range
, 0, NULL
, 0, NULL
, NULL
, NULL
, 1.0f
);
4436 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
4438 /* negative scaling factor */
4439 range
.first
= range
.last
= 0;
4440 familyW
= g_blahfontW
;
4441 hr
= IDWriteFontFallbackBuilder_AddMapping(builder
, &range
, 1, &familyW
, 1, NULL
, NULL
, NULL
, -1.0f
);
4442 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
4445 range
.first
= range
.last
= 0;
4446 familyW
= g_blahfontW
;
4447 hr
= IDWriteFontFallbackBuilder_AddMapping(builder
, &range
, 1, &familyW
, 1, NULL
, NULL
, NULL
, 1.0f
);
4448 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4450 range
.first
= range
.last
= 0;
4451 hr
= IDWriteFontFallbackBuilder_AddMapping(builder
, &range
, 1, &familyW
, 1, NULL
, NULL
, NULL
, 2.0f
);
4452 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4454 range
.first
= range
.last
= 'A';
4455 hr
= IDWriteFontFallbackBuilder_AddMapping(builder
, &range
, 1, &familyW
, 1, NULL
, NULL
, NULL
, 3.0f
);
4456 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4460 hr
= IDWriteFontFallbackBuilder_AddMapping(builder
, &range
, 1, &familyW
, 1, NULL
, NULL
, NULL
, 4.0f
);
4461 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4463 if (0) /* crashes on native */
4464 hr
= IDWriteFontFallbackBuilder_CreateFontFallback(builder
, NULL
);
4466 hr
= IDWriteFontFallbackBuilder_CreateFontFallback(builder
, &fallback
);
4467 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4469 /* fallback font missing from system collection */
4473 font
= (void*)0xdeadbeef;
4474 hr
= IDWriteFontFallback_MapCharacters(fallback
, &analysissource
, 0, 1, NULL
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
,
4475 DWRITE_FONT_STYLE_NORMAL
, DWRITE_FONT_STRETCH_NORMAL
, &mappedlength
, &font
, &scale
);
4476 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4477 ok(mappedlength
== 1, "got %u\n", mappedlength
);
4478 ok(scale
== 1.0f
, "got %f\n", scale
);
4479 ok(font
== NULL
, "got %p\n", font
);
4481 IDWriteFontFallback_Release(fallback
);
4483 /* remap with custom collection */
4484 range
.first
= range
.last
= 'A';
4485 hr
= IDWriteFontFallbackBuilder_AddMapping(builder
, &range
, 1, &familyW
, 1, &fallbackcollection
, NULL
, NULL
, 5.0f
);
4486 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4488 hr
= IDWriteFontFallbackBuilder_CreateFontFallback(builder
, &fallback
);
4489 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4495 hr
= IDWriteFontFallback_MapCharacters(fallback
, &analysissource
, 0, 1, NULL
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
,
4496 DWRITE_FONT_STYLE_NORMAL
, DWRITE_FONT_STRETCH_NORMAL
, &mappedlength
, &font
, &scale
);
4497 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4498 ok(mappedlength
== 1, "got %u\n", mappedlength
);
4499 ok(scale
== 5.0f
, "got %f\n", scale
);
4500 ok(font
!= NULL
, "got %p\n", font
);
4501 IDWriteFont_Release(font
);
4503 IDWriteFontFallback_Release(fallback
);
4507 hr
= IDWriteFontFallbackBuilder_AddMapping(builder
, &range
, 1, &familyW
, 1, &fallbackcollection
, NULL
, NULL
, 6.0f
);
4508 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4510 hr
= IDWriteFontFallbackBuilder_CreateFontFallback(builder
, &fallback
);
4511 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4517 hr
= IDWriteFontFallback_MapCharacters(fallback
, &analysissource
, 0, 1, NULL
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
,
4518 DWRITE_FONT_STYLE_NORMAL
, DWRITE_FONT_STRETCH_NORMAL
, &mappedlength
, &font
, &scale
);
4519 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4520 ok(mappedlength
== 1, "got %u\n", mappedlength
);
4521 ok(scale
== 5.0f
, "got %f\n", scale
);
4522 ok(font
!= NULL
, "got %p\n", font
);
4523 IDWriteFont_Release(font
);
4525 IDWriteFontFallback_Release(fallback
);
4527 /* explicit locale */
4530 hr
= IDWriteFontFallbackBuilder_AddMapping(builder
, &range
, 1, &familyW
, 1, &fallbackcollection
, localeW
, NULL
, 6.0f
);
4531 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4533 hr
= IDWriteFontFallbackBuilder_CreateFontFallback(builder
, &fallback
);
4534 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4540 hr
= IDWriteFontFallback_MapCharacters(fallback
, &analysissource
, 0, 1, NULL
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
,
4541 DWRITE_FONT_STYLE_NORMAL
, DWRITE_FONT_STRETCH_NORMAL
, &mappedlength
, &font
, &scale
);
4542 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4543 ok(mappedlength
== 1, "got %u\n", mappedlength
);
4544 ok(scale
== 5.0f
, "got %f\n", scale
);
4545 ok(font
!= NULL
, "got %p\n", font
);
4546 IDWriteFont_Release(font
);
4548 IDWriteFontFallbackBuilder_Release(builder
);
4549 IDWriteFactory2_Release(factory2
);
4552 static void test_SetTypography(void)
4554 static const WCHAR strW
[] = {'a','f','i','b',0};
4555 IDWriteTypography
*typography
, *typography2
;
4556 IDWriteTextFormat
*format
;
4557 IDWriteTextLayout
*layout
;
4558 DWRITE_TEXT_RANGE range
;
4559 IDWriteFactory
*factory
;
4562 factory
= create_factory();
4564 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
4565 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
4566 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4568 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 1000.0, 1000.0, &layout
);
4569 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4570 IDWriteTextFormat_Release(format
);
4572 hr
= IDWriteFactory_CreateTypography(factory
, &typography
);
4573 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4575 EXPECT_REF(typography
, 1);
4576 range
.startPosition
= 0;
4578 hr
= IDWriteTextLayout_SetTypography(layout
, typography
, range
);
4579 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4580 EXPECT_REF(typography
, 2);
4582 hr
= IDWriteTextLayout_GetTypography(layout
, 0, &typography2
, NULL
);
4583 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4584 ok(typography2
== typography
, "got %p, expected %p\n", typography2
, typography
);
4585 IDWriteTypography_Release(typography2
);
4586 IDWriteTypography_Release(typography
);
4588 hr
= IDWriteFactory_CreateTypography(factory
, &typography2
);
4589 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4591 range
.startPosition
= 0;
4593 hr
= IDWriteTextLayout_SetTypography(layout
, typography2
, range
);
4594 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4595 EXPECT_REF(typography2
, 2);
4596 IDWriteTypography_Release(typography2
);
4598 hr
= IDWriteTextLayout_GetTypography(layout
, 0, &typography
, &range
);
4599 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4600 ok(range
.length
== 1, "got %u\n", range
.length
);
4602 IDWriteTypography_Release(typography
);
4604 IDWriteTextLayout_Release(layout
);
4605 IDWriteFactory_Release(factory
);
4608 static void test_SetLastLineWrapping(void)
4610 static const WCHAR strW
[] = {'a',0};
4611 IDWriteTextLayout2
*layout2
;
4612 IDWriteTextFormat1
*format1
;
4613 IDWriteTextLayout
*layout
;
4614 IDWriteTextFormat
*format
;
4615 IDWriteFactory
*factory
;
4619 factory
= create_factory();
4621 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
4622 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
4623 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4625 hr
= IDWriteTextFormat_QueryInterface(format
, &IID_IDWriteTextFormat1
, (void**)&format1
);
4626 IDWriteTextFormat_Release(format
);
4628 win_skip("SetLastLineWrapping() is not supported\n");
4629 IDWriteFactory_Release(factory
);
4633 ret
= IDWriteTextFormat1_GetLastLineWrapping(format1
);
4634 ok(ret
, "got %d\n", ret
);
4636 hr
= IDWriteTextFormat1_SetLastLineWrapping(format1
, FALSE
);
4637 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4639 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 1, (IDWriteTextFormat
*)format1
, 1000.0, 1000.0, &layout
);
4640 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4642 hr
= IDWriteTextLayout_QueryInterface(layout
, &IID_IDWriteTextLayout2
, (void**)&layout2
);
4643 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4644 IDWriteTextLayout_Release(layout
);
4646 ret
= IDWriteTextLayout2_GetLastLineWrapping(layout2
);
4647 ok(!ret
, "got %d\n", ret
);
4649 hr
= IDWriteTextLayout2_SetLastLineWrapping(layout2
, TRUE
);
4650 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4652 IDWriteFactory_Release(factory
);
4655 static void test_SetOpticalAlignment(void)
4657 static const WCHAR strW
[] = {'a',0};
4658 DWRITE_OPTICAL_ALIGNMENT alignment
;
4659 IDWriteTextLayout2
*layout2
;
4660 IDWriteTextFormat1
*format1
;
4661 IDWriteTextLayout
*layout
;
4662 IDWriteTextFormat
*format
;
4663 IDWriteFactory
*factory
;
4666 factory
= create_factory();
4668 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
4669 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
4670 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4672 hr
= IDWriteTextFormat_QueryInterface(format
, &IID_IDWriteTextFormat1
, (void**)&format1
);
4673 IDWriteTextFormat_Release(format
);
4675 win_skip("SetOpticalAlignment() is not supported\n");
4676 IDWriteFactory_Release(factory
);
4680 alignment
= IDWriteTextFormat1_GetOpticalAlignment(format1
);
4681 ok(alignment
== DWRITE_OPTICAL_ALIGNMENT_NONE
, "got %d\n", alignment
);
4683 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 1, (IDWriteTextFormat
*)format1
, 1000.0, 1000.0, &layout
);
4684 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4686 hr
= IDWriteTextLayout_QueryInterface(layout
, &IID_IDWriteTextLayout2
, (void**)&layout2
);
4687 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4688 IDWriteTextLayout_Release(layout
);
4689 IDWriteTextFormat1_Release(format1
);
4691 alignment
= IDWriteTextLayout2_GetOpticalAlignment(layout2
);
4692 ok(alignment
== DWRITE_OPTICAL_ALIGNMENT_NONE
, "got %d\n", alignment
);
4694 hr
= IDWriteTextLayout2_QueryInterface(layout2
, &IID_IDWriteTextFormat1
, (void**)&format1
);
4695 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4697 alignment
= IDWriteTextFormat1_GetOpticalAlignment(format1
);
4698 ok(alignment
== DWRITE_OPTICAL_ALIGNMENT_NONE
, "got %d\n", alignment
);
4700 hr
= IDWriteTextLayout2_SetOpticalAlignment(layout2
, DWRITE_OPTICAL_ALIGNMENT_NO_SIDE_BEARINGS
);
4701 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4703 hr
= IDWriteTextLayout2_SetOpticalAlignment(layout2
, DWRITE_OPTICAL_ALIGNMENT_NO_SIDE_BEARINGS
+1);
4704 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
4706 alignment
= IDWriteTextFormat1_GetOpticalAlignment(format1
);
4707 ok(alignment
== DWRITE_OPTICAL_ALIGNMENT_NO_SIDE_BEARINGS
, "got %d\n", alignment
);
4709 hr
= IDWriteTextFormat1_SetOpticalAlignment(format1
, DWRITE_OPTICAL_ALIGNMENT_NONE
);
4710 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4712 hr
= IDWriteTextFormat1_SetOpticalAlignment(format1
, DWRITE_OPTICAL_ALIGNMENT_NO_SIDE_BEARINGS
+1);
4713 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
4715 alignment
= IDWriteTextLayout2_GetOpticalAlignment(layout2
);
4716 ok(alignment
== DWRITE_OPTICAL_ALIGNMENT_NONE
, "got %d\n", alignment
);
4718 IDWriteTextLayout2_Release(layout2
);
4719 IDWriteTextFormat1_Release(format1
);
4720 IDWriteFactory_Release(factory
);
4723 static const struct drawcall_entry drawunderline_seq
[] = {
4724 { DRAW_GLYPHRUN
, {'a','e',0x0300,0} }, /* reported runs can't mix different underline values */
4725 { DRAW_GLYPHRUN
, {'d',0} },
4726 { DRAW_UNDERLINE
, {0}, {'e','n','-','u','s',0} },
4730 static const struct drawcall_entry drawunderline2_seq
[] = {
4731 { DRAW_GLYPHRUN
, {'a',0} },
4732 { DRAW_GLYPHRUN
, {'e',0} },
4733 { DRAW_UNDERLINE
, {0}, {'e','n','-','u','s',0} },
4737 static const struct drawcall_entry drawunderline3_seq
[] = {
4738 { DRAW_GLYPHRUN
, {'a',0} },
4739 { DRAW_GLYPHRUN
, {'e',0} },
4740 { DRAW_UNDERLINE
, {0}, {'e','n','-','c','a',0} },
4741 { DRAW_UNDERLINE
, {0}, {'e','n','-','u','s',0} },
4745 static const struct drawcall_entry drawunderline4_seq
[] = {
4746 { DRAW_GLYPHRUN
, {'a',0} },
4747 { DRAW_GLYPHRUN
, {'e',0} },
4748 { DRAW_UNDERLINE
, {0}, {'e','n','-','u','s',0} },
4749 { DRAW_STRIKETHROUGH
},
4753 static void test_SetUnderline(void)
4755 static const WCHAR encaW
[] = {'e','n','-','C','A',0};
4756 static const WCHAR strW
[] = {'a','e',0x0300,'d',0}; /* accent grave */
4757 DWRITE_CLUSTER_METRICS clusters
[4];
4758 IDWriteTextFormat
*format
;
4759 IDWriteTextLayout
*layout
;
4760 DWRITE_TEXT_RANGE range
;
4761 IDWriteFactory
*factory
;
4765 factory
= create_factory();
4767 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
4768 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
4769 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4771 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 1000.0, 1000.0, &layout
);
4772 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4775 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, clusters
, sizeof(clusters
)/sizeof(clusters
[0]), &count
);
4776 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4778 ok(count
== 3, "got %u\n", count
);
4780 range
.startPosition
= 0;
4782 hr
= IDWriteTextLayout_SetUnderline(layout
, TRUE
, range
);
4783 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4786 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, clusters
, sizeof(clusters
)/sizeof(clusters
[0]), &count
);
4787 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4789 ok(count
== 3, "got %u\n", count
);
4791 flush_sequence(sequences
, RENDERER_ID
);
4792 hr
= IDWriteTextLayout_Draw(layout
, NULL
, &testrenderer
, 0.0, 0.0);
4793 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4794 ok_sequence(sequences
, RENDERER_ID
, drawunderline_seq
, "draw underline test", TRUE
);
4796 IDWriteTextLayout_Release(layout
);
4798 /* 2 characters, same font, significantly different font size. Set underline for both, see how many
4799 underline drawing calls is there. */
4800 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 2, format
, 1000.0f
, 1000.0f
, &layout
);
4801 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4803 range
.startPosition
= 0;
4805 hr
= IDWriteTextLayout_SetUnderline(layout
, TRUE
, range
);
4806 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4808 range
.startPosition
= 0;
4810 hr
= IDWriteTextLayout_SetFontSize(layout
, 100.0f
, range
);
4811 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4813 flush_sequence(sequences
, RENDERER_ID
);
4814 hr
= IDWriteTextLayout_Draw(layout
, NULL
, &testrenderer
, 0.0f
, 0.0f
);
4815 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4816 ok_sequence(sequences
, RENDERER_ID
, drawunderline2_seq
, "draw underline test 2", FALSE
);
4818 /* now set different locale for second char, draw again */
4819 range
.startPosition
= 0;
4821 hr
= IDWriteTextLayout_SetLocaleName(layout
, encaW
, range
);
4822 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4824 flush_sequence(sequences
, RENDERER_ID
);
4825 hr
= IDWriteTextLayout_Draw(layout
, NULL
, &testrenderer
, 0.0f
, 0.0f
);
4826 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4827 ok_sequence(sequences
, RENDERER_ID
, drawunderline3_seq
, "draw underline test 2", FALSE
);
4829 IDWriteTextLayout_Release(layout
);
4831 /* 2 characters, same font properties, first with strikethrough, both underlined */
4832 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 2, format
, 1000.0f
, 1000.0f
, &layout
);
4833 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4835 range
.startPosition
= 0;
4837 hr
= IDWriteTextLayout_SetStrikethrough(layout
, TRUE
, range
);
4838 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4840 range
.startPosition
= 0;
4842 hr
= IDWriteTextLayout_SetUnderline(layout
, TRUE
, range
);
4843 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4845 flush_sequence(sequences
, RENDERER_ID
);
4846 hr
= IDWriteTextLayout_Draw(layout
, NULL
, &testrenderer
, 0.0f
, 0.0f
);
4847 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4848 ok_sequence(sequences
, RENDERER_ID
, drawunderline4_seq
, "draw underline test 4", FALSE
);
4850 IDWriteTextLayout_Release(layout
);
4852 IDWriteTextFormat_Release(format
);
4853 IDWriteFactory_Release(factory
);
4856 static void test_InvalidateLayout(void)
4858 static const WCHAR strW
[] = {'a',0};
4859 IDWriteTextLayout3
*layout3
;
4860 IDWriteTextLayout
*layout
;
4861 IDWriteTextFormat
*format
;
4862 IDWriteFactory
*factory
;
4865 factory
= create_factory();
4867 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
4868 DWRITE_FONT_STRETCH_NORMAL
, 10.0f
, enusW
, &format
);
4869 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4871 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 1, format
, 1000.0f
, 1000.0f
, &layout
);
4872 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4874 hr
= IDWriteTextLayout_QueryInterface(layout
, &IID_IDWriteTextLayout3
, (void**)&layout3
);
4876 hr
= IDWriteTextLayout3_InvalidateLayout(layout3
);
4877 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4878 IDWriteTextLayout3_Release(layout3
);
4881 win_skip("IDWriteTextLayout3::InvalidateLayout() is not supported.\n");
4883 IDWriteTextLayout_Release(layout
);
4884 IDWriteTextFormat_Release(format
);
4885 IDWriteFactory_Release(factory
);
4890 IDWriteFactory
*factory
;
4892 if (!(factory
= create_factory())) {
4893 win_skip("failed to create factory\n");
4897 init_call_sequences(sequences
, NUM_CALL_SEQUENCES
);
4898 init_call_sequences(expected_seq
, 1);
4900 test_CreateTextLayout();
4901 test_CreateGdiCompatibleTextLayout();
4902 test_CreateTextFormat();
4903 test_GetLocaleName();
4904 test_CreateEllipsisTrimmingSign();
4906 test_SetInlineObject();
4909 test_GetClusterMetrics();
4910 test_SetLocaleName();
4911 test_SetPairKerning();
4912 test_SetVerticalGlyphOrientation();
4914 test_DetermineMinWidth();
4916 test_SetFontFamilyName();
4917 test_SetFontStyle();
4918 test_SetFontStretch();
4919 test_SetStrikethrough();
4921 test_SetFlowDirection();
4922 test_SetDrawingEffect();
4923 test_GetLineMetrics();
4924 test_SetTextAlignment();
4925 test_SetParagraphAlignment();
4926 test_SetReadingDirection();
4927 test_pixelsnapping();
4928 test_SetWordWrapping();
4929 test_MapCharacters();
4930 test_FontFallbackBuilder();
4931 test_SetTypography();
4932 test_SetLastLineWrapping();
4933 test_SetOpticalAlignment();
4934 test_SetUnderline();
4935 test_InvalidateLayout();
4937 IDWriteFactory_Release(factory
);