2 * Text layout/format tests
4 * Copyright 2012, 2014-2017 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 #define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0]))
34 static const WCHAR tahomaW
[] = {'T','a','h','o','m','a',0};
35 static const WCHAR enusW
[] = {'e','n','-','u','s',0};
37 struct testanalysissink
39 IDWriteTextAnalysisSink IDWriteTextAnalysisSink_iface
;
40 DWRITE_SCRIPT_ANALYSIS sa
; /* last analysis, with SetScriptAnalysis() */
43 static inline struct testanalysissink
*impl_from_IDWriteTextAnalysisSink(IDWriteTextAnalysisSink
*iface
)
45 return CONTAINING_RECORD(iface
, struct testanalysissink
, IDWriteTextAnalysisSink_iface
);
48 /* test IDWriteTextAnalysisSink */
49 static HRESULT WINAPI
analysissink_QueryInterface(IDWriteTextAnalysisSink
*iface
, REFIID riid
, void **obj
)
51 if (IsEqualIID(riid
, &IID_IDWriteTextAnalysisSink
) || IsEqualIID(riid
, &IID_IUnknown
))
61 static ULONG WINAPI
analysissink_AddRef(IDWriteTextAnalysisSink
*iface
)
66 static ULONG WINAPI
analysissink_Release(IDWriteTextAnalysisSink
*iface
)
71 static HRESULT WINAPI
analysissink_SetScriptAnalysis(IDWriteTextAnalysisSink
*iface
,
72 UINT32 position
, UINT32 length
, DWRITE_SCRIPT_ANALYSIS
const* sa
)
74 struct testanalysissink
*sink
= impl_from_IDWriteTextAnalysisSink(iface
);
79 static HRESULT WINAPI
analysissink_SetLineBreakpoints(IDWriteTextAnalysisSink
*iface
,
80 UINT32 position
, UINT32 length
, DWRITE_LINE_BREAKPOINT
const* breakpoints
)
82 ok(0, "unexpected call\n");
86 static HRESULT WINAPI
analysissink_SetBidiLevel(IDWriteTextAnalysisSink
*iface
,
87 UINT32 position
, UINT32 length
, UINT8 explicitLevel
, UINT8 resolvedLevel
)
89 ok(0, "unexpected\n");
93 static HRESULT WINAPI
analysissink_SetNumberSubstitution(IDWriteTextAnalysisSink
*iface
,
94 UINT32 position
, UINT32 length
, IDWriteNumberSubstitution
* substitution
)
96 ok(0, "unexpected\n");
100 static IDWriteTextAnalysisSinkVtbl analysissinkvtbl
= {
101 analysissink_QueryInterface
,
103 analysissink_Release
,
104 analysissink_SetScriptAnalysis
,
105 analysissink_SetLineBreakpoints
,
106 analysissink_SetBidiLevel
,
107 analysissink_SetNumberSubstitution
110 static struct testanalysissink analysissink
= {
111 { &analysissinkvtbl
},
115 /* test IDWriteTextAnalysisSource */
116 static HRESULT WINAPI
analysissource_QueryInterface(IDWriteTextAnalysisSource
*iface
,
117 REFIID riid
, void **obj
)
119 if (IsEqualIID(riid
, &IID_IDWriteTextAnalysisSource
) || IsEqualIID(riid
, &IID_IUnknown
)) {
121 IDWriteTextAnalysisSource_AddRef(iface
);
124 return E_NOINTERFACE
;
127 static ULONG WINAPI
analysissource_AddRef(IDWriteTextAnalysisSource
*iface
)
132 static ULONG WINAPI
analysissource_Release(IDWriteTextAnalysisSource
*iface
)
137 static const WCHAR
*g_source
;
139 static HRESULT WINAPI
analysissource_GetTextAtPosition(IDWriteTextAnalysisSource
*iface
,
140 UINT32 position
, WCHAR
const** text
, UINT32
* text_len
)
142 if (position
>= lstrlenW(g_source
))
149 *text
= &g_source
[position
];
150 *text_len
= lstrlenW(g_source
) - position
;
156 static HRESULT WINAPI
analysissource_GetTextBeforePosition(IDWriteTextAnalysisSource
*iface
,
157 UINT32 position
, WCHAR
const** text
, UINT32
* text_len
)
159 ok(0, "unexpected\n");
163 static DWRITE_READING_DIRECTION WINAPI
analysissource_GetParagraphReadingDirection(
164 IDWriteTextAnalysisSource
*iface
)
166 ok(0, "unexpected\n");
167 return DWRITE_READING_DIRECTION_RIGHT_TO_LEFT
;
170 static HRESULT WINAPI
analysissource_GetLocaleName(IDWriteTextAnalysisSource
*iface
,
171 UINT32 position
, UINT32
* text_len
, WCHAR
const** locale
)
178 static HRESULT WINAPI
analysissource_GetNumberSubstitution(IDWriteTextAnalysisSource
*iface
,
179 UINT32 position
, UINT32
* text_len
, IDWriteNumberSubstitution
**substitution
)
181 ok(0, "unexpected\n");
185 static IDWriteTextAnalysisSourceVtbl analysissourcevtbl
= {
186 analysissource_QueryInterface
,
187 analysissource_AddRef
,
188 analysissource_Release
,
189 analysissource_GetTextAtPosition
,
190 analysissource_GetTextBeforePosition
,
191 analysissource_GetParagraphReadingDirection
,
192 analysissource_GetLocaleName
,
193 analysissource_GetNumberSubstitution
196 static IDWriteTextAnalysisSource analysissource
= { &analysissourcevtbl
};
198 static IDWriteFactory
*create_factory(void)
200 IDWriteFactory
*factory
;
201 HRESULT hr
= DWriteCreateFactory(DWRITE_FACTORY_TYPE_ISOLATED
, &IID_IDWriteFactory
, (IUnknown
**)&factory
);
202 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
206 /* obvious limitation is that only last script data is returned, so this
207 helper is suitable for single script strings only */
208 static void get_script_analysis(const WCHAR
*str
, UINT32 len
, DWRITE_SCRIPT_ANALYSIS
*sa
)
210 IDWriteTextAnalyzer
*analyzer
;
211 IDWriteFactory
*factory
;
216 factory
= create_factory();
217 hr
= IDWriteFactory_CreateTextAnalyzer(factory
, &analyzer
);
218 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
220 hr
= IDWriteTextAnalyzer_AnalyzeScript(analyzer
, &analysissource
, 0, len
, &analysissink
.IDWriteTextAnalysisSink_iface
);
221 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
223 *sa
= analysissink
.sa
;
224 IDWriteFactory_Release(factory
);
227 static IDWriteFontFace
*get_fontface_from_format(IDWriteTextFormat
*format
)
229 IDWriteFontCollection
*collection
;
230 IDWriteFontFamily
*family
;
231 IDWriteFontFace
*fontface
;
238 hr
= IDWriteTextFormat_GetFontCollection(format
, &collection
);
239 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
241 hr
= IDWriteTextFormat_GetFontFamilyName(format
, nameW
, ARRAY_SIZE(nameW
));
242 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
244 hr
= IDWriteFontCollection_FindFamilyName(collection
, nameW
, &index
, &exists
);
245 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
247 hr
= IDWriteFontCollection_GetFontFamily(collection
, index
, &family
);
248 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
249 IDWriteFontCollection_Release(collection
);
251 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
,
252 IDWriteTextFormat_GetFontWeight(format
),
253 IDWriteTextFormat_GetFontStretch(format
),
254 IDWriteTextFormat_GetFontStyle(format
),
256 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
258 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
259 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
261 IDWriteFont_Release(font
);
262 IDWriteFontFamily_Release(family
);
267 #define EXPECT_REF(obj,ref) _expect_ref((IUnknown*)obj, ref, __LINE__)
268 static void _expect_ref(IUnknown
* obj
, ULONG ref
, int line
)
271 IUnknown_AddRef(obj
);
272 rc
= IUnknown_Release(obj
);
273 ok_(__FILE__
,line
)(rc
== ref
, "expected refcount %d, got %d\n", ref
, rc
);
276 enum drawcall_modifiers_kind
{
283 DRAW_STRIKETHROUGH
= 2,
286 DRAW_TOTAL_KINDS
= 5,
287 DRAW_KINDS_MASK
= 0xff
290 static const char *get_draw_kind_name(unsigned short kind
)
292 static const char *kind_names
[] = {
301 "STRIKETHROUGH|EFFECT",
305 if ((kind
& DRAW_KINDS_MASK
) > DRAW_LAST_KIND
)
307 return (kind
& DRAW_EFFECT
) ? kind_names
[(kind
& DRAW_KINDS_MASK
) + DRAW_TOTAL_KINDS
] :
311 struct drawcall_entry
{
312 enum drawcall_kind kind
;
313 WCHAR string
[10]; /* only meaningful for DrawGlyphRun() */
314 WCHAR locale
[LOCALE_NAME_MAX_LENGTH
];
315 UINT32 glyphcount
; /* only meaningful for DrawGlyphRun() */
318 struct drawcall_sequence
322 struct drawcall_entry
*sequence
;
325 struct drawtestcontext
{
333 #define NUM_CALL_SEQUENCES 1
334 #define RENDERER_ID 0
335 static struct drawcall_sequence
*sequences
[NUM_CALL_SEQUENCES
];
336 static struct drawcall_sequence
*expected_seq
[1];
338 static void add_call(struct drawcall_sequence
**seq
, int sequence_index
, const struct drawcall_entry
*call
)
340 struct drawcall_sequence
*call_seq
= seq
[sequence_index
];
342 if (!call_seq
->sequence
) {
344 call_seq
->sequence
= HeapAlloc(GetProcessHeap(), 0, call_seq
->size
* sizeof (struct drawcall_entry
));
347 if (call_seq
->count
== call_seq
->size
) {
349 call_seq
->sequence
= HeapReAlloc(GetProcessHeap(), 0,
351 call_seq
->size
* sizeof (struct drawcall_entry
));
354 assert(call_seq
->sequence
);
355 call_seq
->sequence
[call_seq
->count
++] = *call
;
358 static inline void flush_sequence(struct drawcall_sequence
**seg
, int sequence_index
)
360 struct drawcall_sequence
*call_seq
= seg
[sequence_index
];
362 HeapFree(GetProcessHeap(), 0, call_seq
->sequence
);
363 call_seq
->sequence
= NULL
;
364 call_seq
->count
= call_seq
->size
= 0;
367 static void init_call_sequences(struct drawcall_sequence
**seq
, int n
)
371 for (i
= 0; i
< n
; i
++)
372 seq
[i
] = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(struct drawcall_sequence
));
375 static void ok_sequence_(struct drawcall_sequence
**seq
, int sequence_index
,
376 const struct drawcall_entry
*expected
, const char *context
, BOOL todo
,
377 const char *file
, int line
)
379 static const struct drawcall_entry end_of_sequence
= { DRAW_LAST_KIND
};
380 struct drawcall_sequence
*call_seq
= seq
[sequence_index
];
381 const struct drawcall_entry
*actual
, *sequence
;
384 add_call(seq
, sequence_index
, &end_of_sequence
);
386 sequence
= call_seq
->sequence
;
389 while (expected
->kind
!= DRAW_LAST_KIND
&& actual
->kind
!= DRAW_LAST_KIND
) {
390 if (expected
->kind
!= actual
->kind
) {
394 ok_(file
, line
) (0, "%s: call %s was expected, but got call %s instead\n",
395 context
, get_draw_kind_name(expected
->kind
), get_draw_kind_name(actual
->kind
));
397 flush_sequence(seq
, sequence_index
);
401 ok_(file
, line
) (0, "%s: call %s was expected, but got call %s instead\n",
402 context
, get_draw_kind_name(expected
->kind
), get_draw_kind_name(actual
->kind
));
404 else if ((expected
->kind
& DRAW_KINDS_MASK
) == DRAW_GLYPHRUN
) {
405 int cmp
= lstrcmpW(expected
->string
, actual
->string
);
406 if (cmp
!= 0 && todo
) {
409 ok_(file
, line
) (0, "%s: glyphrun string %s was expected, but got %s instead\n",
410 context
, wine_dbgstr_w(expected
->string
), wine_dbgstr_w(actual
->string
));
413 ok_(file
, line
) (cmp
== 0, "%s: glyphrun string %s was expected, but got %s instead\n",
414 context
, wine_dbgstr_w(expected
->string
), wine_dbgstr_w(actual
->string
));
416 cmp
= lstrcmpW(expected
->locale
, actual
->locale
);
417 if (cmp
!= 0 && todo
) {
420 ok_(file
, line
) (0, "%s: glyph run locale %s was expected, but got %s instead\n",
421 context
, wine_dbgstr_w(expected
->locale
), wine_dbgstr_w(actual
->locale
));
424 ok_(file
, line
) (cmp
== 0, "%s: glyph run locale %s was expected, but got %s instead\n",
425 context
, wine_dbgstr_w(expected
->locale
), wine_dbgstr_w(actual
->locale
));
427 if (expected
->glyphcount
!= actual
->glyphcount
&& todo
) {
430 ok_(file
, line
) (0, "%s: wrong glyph count, %u was expected, but got %u instead\n",
431 context
, expected
->glyphcount
, actual
->glyphcount
);
434 ok_(file
, line
) (expected
->glyphcount
== actual
->glyphcount
,
435 "%s: wrong glyph count, %u was expected, but got %u instead\n",
436 context
, expected
->glyphcount
, actual
->glyphcount
);
438 else if ((expected
->kind
& DRAW_KINDS_MASK
) == DRAW_UNDERLINE
) {
439 int cmp
= lstrcmpW(expected
->locale
, actual
->locale
);
440 if (cmp
!= 0 && todo
) {
443 ok_(file
, line
) (0, "%s: underline locale %s was expected, but got %s instead\n",
444 context
, wine_dbgstr_w(expected
->locale
), wine_dbgstr_w(actual
->locale
));
447 ok_(file
, line
) (cmp
== 0, "%s: underline locale %s was expected, but got %s instead\n",
448 context
, wine_dbgstr_w(expected
->locale
), wine_dbgstr_w(actual
->locale
));
456 if (expected
->kind
!= DRAW_LAST_KIND
|| actual
->kind
!= DRAW_LAST_KIND
) {
458 ok_(file
, line
) (0, "%s: the call sequence is not complete: expected %s - actual %s\n",
459 context
, get_draw_kind_name(expected
->kind
), get_draw_kind_name(actual
->kind
));
463 else if (expected
->kind
!= DRAW_LAST_KIND
|| actual
->kind
!= DRAW_LAST_KIND
)
464 ok_(file
, line
) (0, "%s: the call sequence is not complete: expected %s - actual %s\n",
465 context
, get_draw_kind_name(expected
->kind
), get_draw_kind_name(actual
->kind
));
467 if (todo
&& !failcount
) /* succeeded yet marked todo */
469 ok_(file
, line
)(1, "%s: marked \"todo_wine\" but succeeds\n", context
);
471 flush_sequence(seq
, sequence_index
);
474 #define ok_sequence(seq, index, exp, contx, todo) \
475 ok_sequence_(seq, index, (exp), (contx), (todo), __FILE__, __LINE__)
477 static HRESULT WINAPI
testrenderer_QI(IDWriteTextRenderer
*iface
, REFIID riid
, void **obj
)
479 if (IsEqualIID(riid
, &IID_IDWriteTextRenderer
) ||
480 IsEqualIID(riid
, &IID_IDWritePixelSnapping
) ||
481 IsEqualIID(riid
, &IID_IUnknown
)
489 /* IDWriteTextRenderer1 overrides drawing calls, ignore for now */
490 if (IsEqualIID(riid
, &IID_IDWriteTextRenderer1
))
491 return E_NOINTERFACE
;
493 ok(0, "unexpected QI %s\n", wine_dbgstr_guid(riid
));
494 return E_NOINTERFACE
;
497 static ULONG WINAPI
testrenderer_AddRef(IDWriteTextRenderer
*iface
)
502 static ULONG WINAPI
testrenderer_Release(IDWriteTextRenderer
*iface
)
507 struct renderer_context
{
509 BOOL use_gdi_natural
;
510 BOOL snapping_disabled
;
515 IDWriteTextFormat
*format
;
516 const WCHAR
*familyW
;
519 static HRESULT WINAPI
testrenderer_IsPixelSnappingDisabled(IDWriteTextRenderer
*iface
,
520 void *context
, BOOL
*disabled
)
522 struct renderer_context
*ctxt
= (struct renderer_context
*)context
;
524 *disabled
= ctxt
->snapping_disabled
;
530 static HRESULT WINAPI
testrenderer_GetCurrentTransform(IDWriteTextRenderer
*iface
,
531 void *context
, DWRITE_MATRIX
*m
)
533 struct renderer_context
*ctxt
= (struct renderer_context
*)context
;
534 ok(!ctxt
->snapping_disabled
, "expected enabled snapping\n");
539 static HRESULT WINAPI
testrenderer_GetPixelsPerDip(IDWriteTextRenderer
*iface
,
540 void *context
, FLOAT
*pixels_per_dip
)
542 struct renderer_context
*ctxt
= (struct renderer_context
*)context
;
543 *pixels_per_dip
= ctxt
->ppdip
;
547 #define TEST_MEASURING_MODE(ctxt, mode) test_measuring_mode(ctxt, mode, __LINE__)
548 static void test_measuring_mode(const struct renderer_context
*ctxt
, DWRITE_MEASURING_MODE mode
, int line
)
550 if (ctxt
->gdicompat
) {
551 if (ctxt
->use_gdi_natural
)
552 ok_(__FILE__
, line
)(mode
== DWRITE_MEASURING_MODE_GDI_NATURAL
, "got %d\n", mode
);
554 ok_(__FILE__
, line
)(mode
== DWRITE_MEASURING_MODE_GDI_CLASSIC
, "got %d\n", mode
);
557 ok_(__FILE__
, line
)(mode
== DWRITE_MEASURING_MODE_NATURAL
, "got %d\n", mode
);
560 static HRESULT WINAPI
testrenderer_DrawGlyphRun(IDWriteTextRenderer
*iface
,
562 FLOAT baselineOriginX
,
563 FLOAT baselineOriginY
,
564 DWRITE_MEASURING_MODE mode
,
565 DWRITE_GLYPH_RUN
const *run
,
566 DWRITE_GLYPH_RUN_DESCRIPTION
const *descr
,
569 struct renderer_context
*ctxt
= (struct renderer_context
*)context
;
570 struct drawcall_entry entry
;
571 DWRITE_SCRIPT_ANALYSIS sa
;
574 TEST_MEASURING_MODE(ctxt
, mode
);
575 ctxt
->originX
= baselineOriginX
;
576 ctxt
->originY
= baselineOriginY
;
579 ok(descr
->stringLength
< ARRAY_SIZE(entry
.string
), "string is too long\n");
580 if (descr
->stringLength
&& descr
->stringLength
< ARRAY_SIZE(entry
.string
)) {
581 memcpy(entry
.string
, descr
->string
, descr
->stringLength
*sizeof(WCHAR
));
582 entry
.string
[descr
->stringLength
] = 0;
587 /* see what's reported for control codes runs */
588 get_script_analysis(descr
->string
, descr
->stringLength
, &sa
);
589 if (sa
.shapes
== DWRITE_SCRIPT_SHAPES_NO_VISUAL
) {
592 /* glyphs are not reported at all for control code runs */
593 ok(run
->glyphCount
== 0, "got %u\n", run
->glyphCount
);
594 ok(run
->glyphAdvances
!= NULL
, "advances array %p\n", run
->glyphAdvances
);
595 ok(run
->glyphOffsets
!= NULL
, "offsets array %p\n", run
->glyphOffsets
);
596 ok(run
->fontFace
!= NULL
, "got %p\n", run
->fontFace
);
597 /* text positions are still valid */
598 ok(descr
->string
!= NULL
, "got string %p\n", descr
->string
);
599 ok(descr
->stringLength
> 0, "got string length %u\n", descr
->stringLength
);
600 ok(descr
->clusterMap
!= NULL
, "clustermap %p\n", descr
->clusterMap
);
601 for (i
= 0; i
< descr
->stringLength
; i
++)
602 ok(descr
->clusterMap
[i
] == i
, "got %u\n", descr
->clusterMap
[i
]);
605 entry
.kind
= DRAW_GLYPHRUN
;
607 entry
.kind
|= DRAW_EFFECT
;
608 ok(lstrlenW(descr
->localeName
) < LOCALE_NAME_MAX_LENGTH
, "unexpectedly long locale name\n");
609 lstrcpyW(entry
.locale
, descr
->localeName
);
610 entry
.glyphcount
= run
->glyphCount
;
611 add_call(sequences
, RENDERER_ID
, &entry
);
615 static HRESULT WINAPI
testrenderer_DrawUnderline(IDWriteTextRenderer
*iface
,
617 FLOAT baselineOriginX
,
618 FLOAT baselineOriginY
,
619 DWRITE_UNDERLINE
const* underline
,
622 struct renderer_context
*ctxt
= (struct renderer_context
*)context
;
623 struct drawcall_entry entry
= { 0 };
626 TEST_MEASURING_MODE(ctxt
, underline
->measuringMode
);
628 ok(underline
->runHeight
> 0.0f
, "Expected non-zero run height\n");
629 if (ctxt
&& ctxt
->format
) {
630 DWRITE_FONT_METRICS metrics
;
631 IDWriteFontFace
*fontface
;
634 fontface
= get_fontface_from_format(ctxt
->format
);
635 emsize
= IDWriteTextFormat_GetFontSize(ctxt
->format
);
636 IDWriteFontFace_GetMetrics(fontface
, &metrics
);
638 ok(emsize
== metrics
.designUnitsPerEm
, "Unexpected font size %f\n", emsize
);
639 /* Expected height is in design units, allow some absolute difference from it. Seems to only happen on Vista */
640 ok(fabs(metrics
.capHeight
- underline
->runHeight
) < 2.0f
, "Expected runHeight %u, got %f, family %s\n",
641 metrics
.capHeight
, underline
->runHeight
, wine_dbgstr_w(ctxt
->familyW
));
643 IDWriteFontFace_Release(fontface
);
646 entry
.kind
= DRAW_UNDERLINE
;
648 entry
.kind
|= DRAW_EFFECT
;
649 lstrcpyW(entry
.locale
, underline
->localeName
);
650 add_call(sequences
, RENDERER_ID
, &entry
);
654 static HRESULT WINAPI
testrenderer_DrawStrikethrough(IDWriteTextRenderer
*iface
,
656 FLOAT baselineOriginX
,
657 FLOAT baselineOriginY
,
658 DWRITE_STRIKETHROUGH
const* strikethrough
,
661 struct renderer_context
*ctxt
= (struct renderer_context
*)context
;
662 struct drawcall_entry entry
= { 0 };
665 TEST_MEASURING_MODE(ctxt
, strikethrough
->measuringMode
);
667 entry
.kind
= DRAW_STRIKETHROUGH
;
669 entry
.kind
|= DRAW_EFFECT
;
670 add_call(sequences
, RENDERER_ID
, &entry
);
674 static HRESULT WINAPI
testrenderer_DrawInlineObject(IDWriteTextRenderer
*iface
,
678 IDWriteInlineObject
*object
,
683 struct drawcall_entry entry
= { 0 };
684 entry
.kind
= DRAW_INLINE
;
686 entry
.kind
|= DRAW_EFFECT
;
687 add_call(sequences
, RENDERER_ID
, &entry
);
691 static const IDWriteTextRendererVtbl testrenderervtbl
= {
694 testrenderer_Release
,
695 testrenderer_IsPixelSnappingDisabled
,
696 testrenderer_GetCurrentTransform
,
697 testrenderer_GetPixelsPerDip
,
698 testrenderer_DrawGlyphRun
,
699 testrenderer_DrawUnderline
,
700 testrenderer_DrawStrikethrough
,
701 testrenderer_DrawInlineObject
704 static IDWriteTextRenderer testrenderer
= { &testrenderervtbl
};
706 /* test IDWriteInlineObject */
707 static HRESULT WINAPI
testinlineobj_QI(IDWriteInlineObject
*iface
, REFIID riid
, void **obj
)
709 if (IsEqualIID(riid
, &IID_IDWriteInlineObject
) || IsEqualIID(riid
, &IID_IUnknown
)) {
711 IDWriteInlineObject_AddRef(iface
);
716 return E_NOINTERFACE
;
719 static ULONG WINAPI
testinlineobj_AddRef(IDWriteInlineObject
*iface
)
724 static ULONG WINAPI
testinlineobj_Release(IDWriteInlineObject
*iface
)
729 static HRESULT WINAPI
testinlineobj_Draw(IDWriteInlineObject
*iface
,
730 void* client_drawingontext
, IDWriteTextRenderer
* renderer
,
731 FLOAT originX
, FLOAT originY
, BOOL is_sideways
, BOOL is_rtl
, IUnknown
*drawing_effect
)
733 ok(0, "unexpected call\n");
737 static HRESULT WINAPI
testinlineobj_GetMetrics(IDWriteInlineObject
*iface
, DWRITE_INLINE_OBJECT_METRICS
*metrics
)
739 metrics
->width
= 123.0;
743 static HRESULT WINAPI
testinlineobj_GetOverhangMetrics(IDWriteInlineObject
*iface
, DWRITE_OVERHANG_METRICS
*overhangs
)
745 ok(0, "unexpected call\n");
749 static HRESULT WINAPI
testinlineobj_GetBreakConditions(IDWriteInlineObject
*iface
, DWRITE_BREAK_CONDITION
*before
,
750 DWRITE_BREAK_CONDITION
*after
)
752 *before
= *after
= DWRITE_BREAK_CONDITION_MUST_BREAK
;
756 static HRESULT WINAPI
testinlineobj2_GetBreakConditions(IDWriteInlineObject
*iface
, DWRITE_BREAK_CONDITION
*before
,
757 DWRITE_BREAK_CONDITION
*after
)
759 *before
= *after
= DWRITE_BREAK_CONDITION_MAY_NOT_BREAK
;
763 static IDWriteInlineObjectVtbl testinlineobjvtbl
= {
765 testinlineobj_AddRef
,
766 testinlineobj_Release
,
768 testinlineobj_GetMetrics
,
769 testinlineobj_GetOverhangMetrics
,
770 testinlineobj_GetBreakConditions
773 static IDWriteInlineObjectVtbl testinlineobjvtbl2
= {
775 testinlineobj_AddRef
,
776 testinlineobj_Release
,
778 testinlineobj_GetMetrics
,
779 testinlineobj_GetOverhangMetrics
,
780 testinlineobj2_GetBreakConditions
783 static IDWriteInlineObject testinlineobj
= { &testinlineobjvtbl
};
784 static IDWriteInlineObject testinlineobj2
= { &testinlineobjvtbl
};
785 static IDWriteInlineObject testinlineobj3
= { &testinlineobjvtbl2
};
787 struct test_inline_obj
789 IDWriteInlineObject IDWriteInlineObject_iface
;
790 DWRITE_INLINE_OBJECT_METRICS metrics
;
791 DWRITE_OVERHANG_METRICS overhangs
;
794 static inline struct test_inline_obj
*impl_from_IDWriteInlineObject(IDWriteInlineObject
*iface
)
796 return CONTAINING_RECORD(iface
, struct test_inline_obj
, IDWriteInlineObject_iface
);
799 static HRESULT WINAPI
testinlineobj3_GetMetrics(IDWriteInlineObject
*iface
, DWRITE_INLINE_OBJECT_METRICS
*metrics
)
801 struct test_inline_obj
*obj
= impl_from_IDWriteInlineObject(iface
);
802 *metrics
= obj
->metrics
;
806 static HRESULT WINAPI
testinlineobj3_GetOverhangMetrics(IDWriteInlineObject
*iface
, DWRITE_OVERHANG_METRICS
*overhangs
)
808 struct test_inline_obj
*obj
= impl_from_IDWriteInlineObject(iface
);
809 *overhangs
= obj
->overhangs
;
810 /* Return value is ignored. */
814 static const IDWriteInlineObjectVtbl testinlineobjvtbl3
= {
816 testinlineobj_AddRef
,
817 testinlineobj_Release
,
819 testinlineobj3_GetMetrics
,
820 testinlineobj3_GetOverhangMetrics
,
821 testinlineobj_GetBreakConditions
,
824 static void test_inline_obj_init(struct test_inline_obj
*obj
, const DWRITE_INLINE_OBJECT_METRICS
*metrics
,
825 const DWRITE_OVERHANG_METRICS
*overhangs
)
827 obj
->IDWriteInlineObject_iface
.lpVtbl
= &testinlineobjvtbl3
;
828 obj
->metrics
= *metrics
;
829 obj
->overhangs
= *overhangs
;
834 IUnknown IUnknown_iface
;
838 static inline struct test_effect
*test_effect_from_IUnknown(IUnknown
*iface
)
840 return CONTAINING_RECORD(iface
, struct test_effect
, IUnknown_iface
);
843 static HRESULT WINAPI
testeffect_QI(IUnknown
*iface
, REFIID riid
, void **obj
)
845 if (IsEqualIID(riid
, &IID_IUnknown
)) {
847 IUnknown_AddRef(iface
);
851 ok(0, "Unexpected riid %s.\n", wine_dbgstr_guid(riid
));
853 return E_NOINTERFACE
;
856 static ULONG WINAPI
testeffect_AddRef(IUnknown
*iface
)
858 struct test_effect
*effect
= test_effect_from_IUnknown(iface
);
859 return InterlockedIncrement(&effect
->ref
);
862 static ULONG WINAPI
testeffect_Release(IUnknown
*iface
)
864 struct test_effect
*effect
= test_effect_from_IUnknown(iface
);
865 LONG ref
= InterlockedDecrement(&effect
->ref
);
868 HeapFree(GetProcessHeap(), 0, effect
);
873 static const IUnknownVtbl testeffectvtbl
= {
879 static IUnknown
*create_test_effect(void)
881 struct test_effect
*effect
;
883 effect
= HeapAlloc(GetProcessHeap(), 0, sizeof(*effect
));
884 effect
->IUnknown_iface
.lpVtbl
= &testeffectvtbl
;
887 return &effect
->IUnknown_iface
;
890 static void test_CreateTextLayout(void)
892 static const WCHAR strW
[] = {'s','t','r','i','n','g',0};
893 IDWriteTextLayout2
*layout2
;
894 IDWriteTextLayout
*layout
;
895 IDWriteTextFormat
*format
;
896 IDWriteFactory
*factory
;
899 factory
= create_factory();
901 layout
= (void*)0xdeadbeef;
902 hr
= IDWriteFactory_CreateTextLayout(factory
, NULL
, 0, NULL
, 0.0, 0.0, &layout
);
903 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
904 ok(layout
== NULL
, "got %p\n", layout
);
906 layout
= (void*)0xdeadbeef;
907 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 6, NULL
, 0.0, 0.0, &layout
);
908 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
909 ok(layout
== NULL
, "got %p\n", layout
);
911 layout
= (void*)0xdeadbeef;
912 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 6, NULL
, 1.0, 0.0, &layout
);
913 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
914 ok(layout
== NULL
, "got %p\n", layout
);
916 layout
= (void*)0xdeadbeef;
917 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 6, NULL
, 0.0, 1.0, &layout
);
918 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
919 ok(layout
== NULL
, "got %p\n", layout
);
921 layout
= (void*)0xdeadbeef;
922 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 6, NULL
, 1000.0, 1000.0, &layout
);
923 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
924 ok(layout
== NULL
, "got %p\n", layout
);
926 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
927 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
928 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
930 layout
= (void*)0xdeadbeef;
931 hr
= IDWriteFactory_CreateTextLayout(factory
, NULL
, 0, format
, 100.0f
, 100.0f
, &layout
);
932 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
933 ok(layout
== NULL
, "got %p\n", layout
);
935 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 0, format
, 0.0f
, 0.0f
, &layout
);
936 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
937 IDWriteTextLayout_Release(layout
);
939 EXPECT_REF(format
, 1);
940 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 6, format
, 1000.0, 1000.0, &layout
);
941 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
942 EXPECT_REF(format
, 1);
944 hr
= IDWriteTextLayout_QueryInterface(layout
, &IID_IDWriteTextLayout2
, (void**)&layout2
);
946 IDWriteTextLayout1
*layout1
;
947 IDWriteTextFormat1
*format1
;
948 IDWriteTextFormat
*format
;
950 hr
= IDWriteTextLayout2_QueryInterface(layout2
, &IID_IDWriteTextLayout1
, (void**)&layout1
);
951 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
952 IDWriteTextLayout1_Release(layout1
);
954 EXPECT_REF(layout2
, 2);
955 hr
= IDWriteTextLayout2_QueryInterface(layout2
, &IID_IDWriteTextFormat1
, (void**)&format1
);
956 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
957 EXPECT_REF(layout2
, 3);
959 hr
= IDWriteTextLayout2_QueryInterface(layout2
, &IID_IDWriteTextFormat
, (void**)&format
);
960 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
961 ok(format
== (IDWriteTextFormat
*)format1
, "got %p, %p\n", format
, format1
);
962 ok(format
!= (IDWriteTextFormat
*)layout2
, "got %p, %p\n", format
, layout2
);
963 EXPECT_REF(layout2
, 4);
965 hr
= IDWriteTextFormat_QueryInterface(format
, &IID_IDWriteTextLayout1
, (void**)&layout1
);
966 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
967 IDWriteTextLayout1_Release(layout1
);
969 IDWriteTextFormat1_Release(format1
);
970 IDWriteTextFormat_Release(format
);
972 hr
= IDWriteTextLayout_QueryInterface(layout
, &IID_IDWriteTextFormat1
, (void**)&format1
);
973 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
974 EXPECT_REF(layout2
, 3);
976 hr
= IDWriteTextLayout_QueryInterface(layout
, &IID_IDWriteTextFormat
, (void**)&format
);
977 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
978 ok(format
== (IDWriteTextFormat
*)format1
, "got %p, %p\n", format
, format1
);
979 EXPECT_REF(layout2
, 4);
981 IDWriteTextFormat1_Release(format1
);
982 IDWriteTextFormat_Release(format
);
983 IDWriteTextLayout2_Release(layout2
);
986 win_skip("IDWriteTextLayout2 is not supported.\n");
988 IDWriteTextLayout_Release(layout
);
989 IDWriteTextFormat_Release(format
);
990 IDWriteFactory_Release(factory
);
993 static DWRITE_MATRIX layoutcreate_transforms
[] = {
994 { 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 },
995 { 1.0, 0.0, 0.0, 1.0, 0.3, 0.2 },
996 { 1.0, 0.0, 0.0, 1.0,-0.3,-0.2 },
998 { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 },
999 { 1.0, 0.0, 0.0, 0.0, 0.0, 0.0 },
1000 { 1.0, 2.0, 0.5, 1.0, 0.0, 0.0 },
1003 static void test_CreateGdiCompatibleTextLayout(void)
1005 static const WCHAR strW
[] = {'s','t','r','i','n','g',0};
1006 IDWriteTextLayout
*layout
;
1007 IDWriteTextFormat
*format
;
1008 IDWriteFactory
*factory
;
1013 factory
= create_factory();
1015 layout
= (void*)0xdeadbeef;
1016 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, NULL
, 0, NULL
, 0.0, 0.0, 0.0, NULL
, FALSE
, &layout
);
1017 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1018 ok(layout
== NULL
, "got %p\n", layout
);
1020 layout
= (void*)0xdeadbeef;
1021 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, strW
, 6, NULL
, 0.0, 0.0, 0.0, NULL
, FALSE
, &layout
);
1022 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1023 ok(layout
== NULL
, "got %p\n", layout
);
1025 layout
= (void*)0xdeadbeef;
1026 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, strW
, 6, NULL
, 1.0, 0.0, 0.0, NULL
, FALSE
, &layout
);
1027 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1028 ok(layout
== NULL
, "got %p\n", layout
);
1030 layout
= (void*)0xdeadbeef;
1031 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, strW
, 6, NULL
, 1.0, 0.0, 1.0, NULL
, FALSE
, &layout
);
1032 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1033 ok(layout
== NULL
, "got %p\n", layout
);
1035 layout
= (void*)0xdeadbeef;
1036 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, strW
, 6, NULL
, 1000.0, 1000.0, 1.0, NULL
, FALSE
, &layout
);
1037 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1038 ok(layout
== NULL
, "got %p\n", layout
);
1040 /* create with text format */
1041 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
1042 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
1043 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1044 EXPECT_REF(format
, 1);
1046 layout
= (void*)0xdeadbeef;
1047 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, NULL
, 0, format
, 100.0f
, 100.0f
, 1.0f
, NULL
, FALSE
, &layout
);
1048 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1049 ok(layout
== NULL
, "got %p\n", layout
);
1051 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, strW
, 6, format
, 100.0, 100.0, 1.0, NULL
, FALSE
, &layout
);
1052 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1053 EXPECT_REF(format
, 1);
1054 EXPECT_REF(layout
, 1);
1056 IDWriteTextLayout_AddRef(layout
);
1057 EXPECT_REF(format
, 1);
1058 EXPECT_REF(layout
, 2);
1059 IDWriteTextLayout_Release(layout
);
1060 IDWriteTextLayout_Release(layout
);
1062 /* zero length string is okay */
1063 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, strW
, 0, format
, 100.0, 100.0, 1.0, NULL
, FALSE
, &layout
);
1064 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1066 dimension
= IDWriteTextLayout_GetMaxWidth(layout
);
1067 ok(dimension
== 100.0, "got %f\n", dimension
);
1069 dimension
= IDWriteTextLayout_GetMaxHeight(layout
);
1070 ok(dimension
== 100.0, "got %f\n", dimension
);
1072 IDWriteTextLayout_Release(layout
);
1074 /* negative, zero ppdip */
1075 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, strW
, 1, format
, 100.0, 100.0, -1.0, NULL
, FALSE
, &layout
);
1076 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1077 IDWriteTextLayout_Release(layout
);
1079 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, strW
, 1, format
, 100.0, 100.0, 0.0, NULL
, FALSE
, &layout
);
1080 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1081 IDWriteTextLayout_Release(layout
);
1084 for (i
= 0; i
< ARRAY_SIZE(layoutcreate_transforms
); i
++) {
1085 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, strW
, 1, format
, 100.0, 100.0, 1.0,
1086 &layoutcreate_transforms
[i
], FALSE
, &layout
);
1087 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1088 IDWriteTextLayout_Release(layout
);
1091 IDWriteTextFormat_Release(format
);
1092 IDWriteFactory_Release(factory
);
1095 static void test_CreateTextFormat(void)
1097 static const WCHAR emptyW
[] = {0};
1098 IDWriteFontCollection
*collection
, *syscoll
;
1099 DWRITE_PARAGRAPH_ALIGNMENT paralign
;
1100 DWRITE_READING_DIRECTION readdir
;
1101 DWRITE_WORD_WRAPPING wrapping
;
1102 DWRITE_TEXT_ALIGNMENT align
;
1103 DWRITE_FLOW_DIRECTION flow
;
1104 DWRITE_LINE_SPACING_METHOD method
;
1105 DWRITE_TRIMMING trimming
;
1106 IDWriteTextFormat
*format
;
1107 FLOAT spacing
, baseline
;
1108 IDWriteInlineObject
*trimmingsign
;
1109 IDWriteFactory
*factory
;
1112 factory
= create_factory();
1114 /* zero/negative font size */
1115 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
1116 DWRITE_FONT_STRETCH_NORMAL
, 0.0f
, enusW
, &format
);
1117 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1119 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
1120 DWRITE_FONT_STRETCH_NORMAL
, -10.0f
, enusW
, &format
);
1121 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1123 /* invalid font properties */
1124 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, 1000, DWRITE_FONT_STYLE_NORMAL
,
1125 DWRITE_FONT_STRETCH_NORMAL
, 10.0f
, enusW
, &format
);
1126 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1128 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_ITALIC
+ 1,
1129 DWRITE_FONT_STRETCH_NORMAL
, 10.0f
, enusW
, &format
);
1130 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1132 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_ITALIC
,
1133 10, 10.0f
, enusW
, &format
);
1134 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1136 /* empty family name */
1137 hr
= IDWriteFactory_CreateTextFormat(factory
, emptyW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
1138 DWRITE_FONT_STRETCH_NORMAL
, 10.0f
, enusW
, &format
);
1139 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1140 IDWriteTextFormat_Release(format
);
1142 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
1143 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
1144 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1146 if (0) /* crashes on native */
1147 hr
= IDWriteTextFormat_GetFontCollection(format
, NULL
);
1150 hr
= IDWriteTextFormat_GetFontCollection(format
, &collection
);
1151 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1152 ok(collection
!= NULL
, "got %p\n", collection
);
1154 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &syscoll
, FALSE
);
1155 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1156 ok(collection
== syscoll
, "got %p, was %p\n", syscoll
, collection
);
1157 IDWriteFontCollection_Release(syscoll
);
1158 IDWriteFontCollection_Release(collection
);
1160 /* default format properties */
1161 align
= IDWriteTextFormat_GetTextAlignment(format
);
1162 ok(align
== DWRITE_TEXT_ALIGNMENT_LEADING
, "got %d\n", align
);
1164 paralign
= IDWriteTextFormat_GetParagraphAlignment(format
);
1165 ok(paralign
== DWRITE_PARAGRAPH_ALIGNMENT_NEAR
, "got %d\n", paralign
);
1167 wrapping
= IDWriteTextFormat_GetWordWrapping(format
);
1168 ok(wrapping
== DWRITE_WORD_WRAPPING_WRAP
, "got %d\n", wrapping
);
1170 readdir
= IDWriteTextFormat_GetReadingDirection(format
);
1171 ok(readdir
== DWRITE_READING_DIRECTION_LEFT_TO_RIGHT
, "got %d\n", readdir
);
1173 flow
= IDWriteTextFormat_GetFlowDirection(format
);
1174 ok(flow
== DWRITE_FLOW_DIRECTION_TOP_TO_BOTTOM
, "got %d\n", flow
);
1176 hr
= IDWriteTextFormat_GetLineSpacing(format
, &method
, &spacing
, &baseline
);
1177 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1178 ok(spacing
== 0.0, "got %f\n", spacing
);
1179 ok(baseline
== 0.0, "got %f\n", baseline
);
1180 ok(method
== DWRITE_LINE_SPACING_METHOD_DEFAULT
, "got %d\n", method
);
1182 trimming
.granularity
= DWRITE_TRIMMING_GRANULARITY_WORD
;
1183 trimming
.delimiter
= 10;
1184 trimming
.delimiterCount
= 10;
1185 trimmingsign
= (void*)0xdeadbeef;
1186 hr
= IDWriteTextFormat_GetTrimming(format
, &trimming
, &trimmingsign
);
1187 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1188 ok(trimming
.granularity
== DWRITE_TRIMMING_GRANULARITY_NONE
, "got %d\n", trimming
.granularity
);
1189 ok(trimming
.delimiter
== 0, "got %d\n", trimming
.delimiter
);
1190 ok(trimming
.delimiterCount
== 0, "got %d\n", trimming
.delimiterCount
);
1191 ok(trimmingsign
== NULL
, "got %p\n", trimmingsign
);
1194 hr
= IDWriteTextFormat_SetTextAlignment(format
, DWRITE_TEXT_ALIGNMENT_LEADING
);
1195 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1197 hr
= IDWriteTextFormat_SetTextAlignment(format
, DWRITE_TEXT_ALIGNMENT_JUSTIFIED
+1);
1198 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1200 hr
= IDWriteTextFormat_SetParagraphAlignment(format
, DWRITE_PARAGRAPH_ALIGNMENT_NEAR
);
1201 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1203 hr
= IDWriteTextFormat_SetParagraphAlignment(format
, DWRITE_PARAGRAPH_ALIGNMENT_CENTER
+1);
1204 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1206 hr
= IDWriteTextFormat_SetWordWrapping(format
, DWRITE_WORD_WRAPPING_WRAP
);
1207 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1209 hr
= IDWriteTextFormat_SetWordWrapping(format
, DWRITE_WORD_WRAPPING_CHARACTER
+1);
1210 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1212 hr
= IDWriteTextFormat_SetReadingDirection(format
, DWRITE_READING_DIRECTION_LEFT_TO_RIGHT
);
1213 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1215 hr
= IDWriteTextFormat_SetFlowDirection(format
, DWRITE_FLOW_DIRECTION_TOP_TO_BOTTOM
);
1216 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1219 hr
= IDWriteTextFormat_SetTrimming(format
, &trimming
, NULL
);
1220 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1222 /* invalid granularity */
1223 trimming
.granularity
= 10;
1224 trimming
.delimiter
= 0;
1225 trimming
.delimiterCount
= 0;
1226 hr
= IDWriteTextFormat_SetTrimming(format
, &trimming
, NULL
);
1227 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1229 IDWriteTextFormat_Release(format
);
1230 IDWriteFactory_Release(factory
);
1233 static void test_GetLocaleName(void)
1235 static const WCHAR strW
[] = {'s','t','r','i','n','g',0};
1236 static const WCHAR ruW
[] = {'r','u',0};
1237 IDWriteTextLayout
*layout
;
1238 IDWriteTextFormat
*format
, *format2
;
1239 IDWriteFactory
*factory
;
1244 factory
= create_factory();
1246 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
1247 DWRITE_FONT_STRETCH_NORMAL
, 10.0, ruW
, &format
);
1248 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1250 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, strW
, 0, format
, 100.0, 100.0, 1.0, NULL
, FALSE
, &layout
);
1251 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1253 hr
= IDWriteTextLayout_QueryInterface(layout
, &IID_IDWriteTextFormat
, (void**)&format2
);
1254 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1256 len
= IDWriteTextFormat_GetLocaleNameLength(format2
);
1257 ok(len
== 2, "got %u\n", len
);
1258 len
= IDWriteTextFormat_GetLocaleNameLength(format
);
1259 ok(len
== 2, "got %u\n", len
);
1260 hr
= IDWriteTextFormat_GetLocaleName(format2
, buff
, len
);
1261 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
1262 hr
= IDWriteTextFormat_GetLocaleName(format2
, buff
, len
+1);
1263 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1264 ok(!lstrcmpW(buff
, ruW
), "got %s\n", wine_dbgstr_w(buff
));
1265 hr
= IDWriteTextFormat_GetLocaleName(format
, buff
, len
);
1266 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
1267 hr
= IDWriteTextFormat_GetLocaleName(format
, buff
, len
+1);
1268 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1269 ok(!lstrcmpW(buff
, ruW
), "got %s\n", wine_dbgstr_w(buff
));
1271 IDWriteTextLayout_Release(layout
);
1272 IDWriteTextFormat_Release(format
);
1273 IDWriteTextFormat_Release(format2
);
1274 IDWriteFactory_Release(factory
);
1277 static const struct drawcall_entry drawellipsis_seq
[] = {
1278 { DRAW_GLYPHRUN
, {0x2026, 0}, {'e','n','-','g','b',0}, 1 },
1282 static void test_CreateEllipsisTrimmingSign(void)
1284 static const WCHAR engbW
[] = {'e','n','-','G','B',0};
1285 DWRITE_INLINE_OBJECT_METRICS metrics
;
1286 DWRITE_BREAK_CONDITION before
, after
;
1287 struct renderer_context ctxt
;
1288 IDWriteTextFormat
*format
;
1289 IDWriteInlineObject
*sign
;
1290 IDWriteFactory
*factory
;
1291 IUnknown
*unk
, *effect
;
1294 factory
= create_factory();
1296 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
1297 DWRITE_FONT_STRETCH_NORMAL
, 10.0, engbW
, &format
);
1298 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1300 EXPECT_REF(format
, 1);
1301 hr
= IDWriteFactory_CreateEllipsisTrimmingSign(factory
, format
, &sign
);
1302 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1303 EXPECT_REF(format
, 1);
1305 hr
= IDWriteInlineObject_QueryInterface(sign
, &IID_IDWriteTextLayout
, (void**)&unk
);
1306 ok(hr
== E_NOINTERFACE
, "got 0x%08x\n", hr
);
1308 if (0) {/* crashes on native */
1309 hr
= IDWriteInlineObject_GetBreakConditions(sign
, NULL
, NULL
);
1310 hr
= IDWriteInlineObject_GetMetrics(sign
, NULL
);
1312 metrics
.width
= 0.0;
1313 metrics
.height
= 123.0;
1314 metrics
.baseline
= 123.0;
1315 metrics
.supportsSideways
= TRUE
;
1316 hr
= IDWriteInlineObject_GetMetrics(sign
, &metrics
);
1317 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1318 ok(metrics
.width
> 0.0, "got %.2f\n", metrics
.width
);
1319 ok(metrics
.height
== 0.0, "got %.2f\n", metrics
.height
);
1320 ok(metrics
.baseline
== 0.0, "got %.2f\n", metrics
.baseline
);
1321 ok(!metrics
.supportsSideways
, "got %d\n", metrics
.supportsSideways
);
1323 before
= after
= DWRITE_BREAK_CONDITION_CAN_BREAK
;
1324 hr
= IDWriteInlineObject_GetBreakConditions(sign
, &before
, &after
);
1325 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1326 ok(before
== DWRITE_BREAK_CONDITION_NEUTRAL
, "got %d\n", before
);
1327 ok(after
== DWRITE_BREAK_CONDITION_NEUTRAL
, "got %d\n", after
);
1330 flush_sequence(sequences
, RENDERER_ID
);
1331 hr
= IDWriteInlineObject_Draw(sign
, NULL
, &testrenderer
, 0.0, 0.0, FALSE
, FALSE
, NULL
);
1332 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1333 ok_sequence(sequences
, RENDERER_ID
, drawellipsis_seq
, "ellipsis sign draw test", FALSE
);
1335 effect
= create_test_effect();
1337 EXPECT_REF(effect
, 1);
1338 flush_sequence(sequences
, RENDERER_ID
);
1339 hr
= IDWriteInlineObject_Draw(sign
, NULL
, &testrenderer
, 0.0f
, 0.0f
, FALSE
, FALSE
, effect
);
1340 ok(hr
== S_OK
, "Failed to draw trimming sign, hr %#x.\n", hr
);
1341 ok_sequence(sequences
, RENDERER_ID
, drawellipsis_seq
, "ellipsis sign draw with effect test", FALSE
);
1342 EXPECT_REF(effect
, 1);
1344 IUnknown_Release(effect
);
1346 flush_sequence(sequences
, RENDERER_ID
);
1347 hr
= IDWriteInlineObject_Draw(sign
, NULL
, &testrenderer
, 0.0f
, 0.0f
, FALSE
, FALSE
, (void *)0xdeadbeef);
1348 ok(hr
== S_OK
, "Failed to draw trimming sign, hr %#x.\n", hr
);
1349 ok_sequence(sequences
, RENDERER_ID
, drawellipsis_seq
, "ellipsis sign draw with effect test", FALSE
);
1351 memset(&ctxt
, 0, sizeof(ctxt
));
1352 hr
= IDWriteInlineObject_Draw(sign
, &ctxt
, &testrenderer
, 123.0f
, 456.0f
, FALSE
, FALSE
, NULL
);
1353 ok(hr
== S_OK
, "Failed to draw trimming sign, hr %#x.\n", hr
);
1354 ok(ctxt
.originX
== 123.0f
&& ctxt
.originY
== 456.0f
, "Unexpected drawing origin\n");
1356 IDWriteInlineObject_Release(sign
);
1358 /* Centered format */
1359 hr
= IDWriteTextFormat_SetTextAlignment(format
, DWRITE_TEXT_ALIGNMENT_CENTER
);
1360 ok(hr
== S_OK
, "Failed to set text alignment, hr %#x.\n", hr
);
1362 hr
= IDWriteFactory_CreateEllipsisTrimmingSign(factory
, format
, &sign
);
1363 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1365 memset(&ctxt
, 0, sizeof(ctxt
));
1366 hr
= IDWriteInlineObject_Draw(sign
, &ctxt
, &testrenderer
, 123.0f
, 456.0f
, FALSE
, FALSE
, NULL
);
1367 ok(hr
== S_OK
, "Failed to draw trimming sign, hr %#x.\n", hr
);
1368 ok(ctxt
.originX
== 123.0f
&& ctxt
.originY
== 456.0f
, "Unexpected drawing origin\n");
1370 IDWriteInlineObject_Release(sign
);
1372 /* non-orthogonal flow/reading combination */
1373 hr
= IDWriteTextFormat_SetReadingDirection(format
, DWRITE_READING_DIRECTION_LEFT_TO_RIGHT
);
1374 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1376 hr
= IDWriteTextFormat_SetFlowDirection(format
, DWRITE_FLOW_DIRECTION_LEFT_TO_RIGHT
);
1377 ok(hr
== S_OK
|| broken(hr
== E_INVALIDARG
) /* vista, win7 */, "got 0x%08x\n", hr
);
1379 hr
= IDWriteFactory_CreateEllipsisTrimmingSign(factory
, format
, &sign
);
1380 ok(hr
== DWRITE_E_FLOWDIRECTIONCONFLICTS
, "got 0x%08x\n", hr
);
1383 IDWriteTextFormat_Release(format
);
1384 IDWriteFactory_Release(factory
);
1387 static void test_fontweight(void)
1389 static const WCHAR strW
[] = {'s','t','r','i','n','g',0};
1390 static const WCHAR ruW
[] = {'r','u',0};
1391 IDWriteTextFormat
*format
, *fmt2
;
1392 IDWriteTextLayout
*layout
;
1393 DWRITE_FONT_WEIGHT weight
;
1394 DWRITE_TEXT_RANGE range
;
1395 IDWriteFactory
*factory
;
1399 factory
= create_factory();
1401 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_BOLD
, DWRITE_FONT_STYLE_NORMAL
,
1402 DWRITE_FONT_STRETCH_NORMAL
, 10.0, ruW
, &format
);
1403 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1405 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, strW
, 6, format
, 100.0, 100.0, 1.0, NULL
, FALSE
, &layout
);
1406 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1408 hr
= IDWriteTextLayout_QueryInterface(layout
, &IID_IDWriteTextFormat
, (void**)&fmt2
);
1409 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1411 weight
= IDWriteTextFormat_GetFontWeight(fmt2
);
1412 ok(weight
== DWRITE_FONT_WEIGHT_BOLD
, "got %u\n", weight
);
1414 range
.startPosition
= range
.length
= 0;
1415 hr
= IDWriteTextLayout_GetFontWeight(layout
, 0, &weight
, &range
);
1416 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1417 ok(range
.startPosition
== 0 && range
.length
== ~0u, "got %u, %u\n", range
.startPosition
, range
.length
);
1419 range
.startPosition
= 0;
1421 hr
= IDWriteTextLayout_SetFontWeight(layout
, DWRITE_FONT_WEIGHT_NORMAL
, range
);
1422 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1424 range
.startPosition
= range
.length
= 0;
1425 hr
= IDWriteTextLayout_GetFontWeight(layout
, 0, &weight
, &range
);
1426 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1427 ok(range
.startPosition
== 0 && range
.length
== 6, "got %u, %u\n", range
.startPosition
, range
.length
);
1429 /* IDWriteTextFormat methods output doesn't reflect layout changes */
1430 weight
= IDWriteTextFormat_GetFontWeight(fmt2
);
1431 ok(weight
== DWRITE_FONT_WEIGHT_BOLD
, "got %u\n", weight
);
1434 weight
= DWRITE_FONT_WEIGHT_BOLD
;
1435 hr
= IDWriteTextLayout_GetFontWeight(layout
, 0, &weight
, &range
);
1436 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1437 ok(weight
== DWRITE_FONT_WEIGHT_NORMAL
, "got %d\n", weight
);
1438 ok(range
.length
== 6, "got %d\n", range
.length
);
1440 range
.startPosition
= 0;
1442 hr
= IDWriteTextLayout_SetFontWeight(layout
, 1000, range
);
1443 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1445 size
= IDWriteTextLayout_GetMaxWidth(layout
);
1446 ok(size
== 100.0, "got %.2f\n", size
);
1448 hr
= IDWriteTextLayout_SetMaxWidth(layout
, 0.0);
1449 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1451 size
= IDWriteTextLayout_GetMaxWidth(layout
);
1452 ok(size
== 0.0, "got %.2f\n", size
);
1454 hr
= IDWriteTextLayout_SetMaxWidth(layout
, -1.0);
1455 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1457 size
= IDWriteTextLayout_GetMaxWidth(layout
);
1458 ok(size
== 0.0, "got %.2f\n", size
);
1460 hr
= IDWriteTextLayout_SetMaxWidth(layout
, 100.0);
1461 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1463 size
= IDWriteTextLayout_GetMaxWidth(layout
);
1464 ok(size
== 100.0, "got %.2f\n", size
);
1466 size
= IDWriteTextLayout_GetMaxHeight(layout
);
1467 ok(size
== 100.0, "got %.2f\n", size
);
1469 hr
= IDWriteTextLayout_SetMaxHeight(layout
, 0.0);
1470 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1472 size
= IDWriteTextLayout_GetMaxHeight(layout
);
1473 ok(size
== 0.0, "got %.2f\n", size
);
1475 hr
= IDWriteTextLayout_SetMaxHeight(layout
, -1.0);
1476 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1478 size
= IDWriteTextLayout_GetMaxHeight(layout
);
1479 ok(size
== 0.0, "got %.2f\n", size
);
1481 hr
= IDWriteTextLayout_SetMaxHeight(layout
, 100.0);
1482 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1484 size
= IDWriteTextLayout_GetMaxHeight(layout
);
1485 ok(size
== 100.0, "got %.2f\n", size
);
1487 IDWriteTextLayout_Release(layout
);
1488 IDWriteTextFormat_Release(fmt2
);
1489 IDWriteTextFormat_Release(format
);
1490 IDWriteFactory_Release(factory
);
1493 static void test_SetInlineObject(void)
1495 static const WCHAR strW
[] = {'s','t','r','i','n','g',0};
1496 static const WCHAR ruW
[] = {'r','u',0};
1498 IDWriteInlineObject
*inlineobj
, *inlineobj2
, *inlinetest
;
1499 IDWriteTextFormat
*format
;
1500 IDWriteTextLayout
*layout
;
1501 DWRITE_TEXT_RANGE range
, r2
;
1502 IDWriteFactory
*factory
;
1505 factory
= create_factory();
1507 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_BOLD
, DWRITE_FONT_STYLE_NORMAL
,
1508 DWRITE_FONT_STRETCH_NORMAL
, 10.0, ruW
, &format
);
1509 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1511 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, strW
, 6, format
, 100.0, 100.0, 1.0, NULL
, FALSE
, &layout
);
1512 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1514 hr
= IDWriteFactory_CreateEllipsisTrimmingSign(factory
, format
, &inlineobj
);
1515 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1517 hr
= IDWriteFactory_CreateEllipsisTrimmingSign(factory
, format
, &inlineobj2
);
1518 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1520 EXPECT_REF(inlineobj
, 1);
1521 EXPECT_REF(inlineobj2
, 1);
1523 inlinetest
= (void*)0x1;
1524 hr
= IDWriteTextLayout_GetInlineObject(layout
, 0, &inlinetest
, NULL
);
1525 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1526 ok(inlinetest
== NULL
, "got %p\n", inlinetest
);
1528 range
.startPosition
= 0;
1530 hr
= IDWriteTextLayout_SetInlineObject(layout
, inlineobj
, range
);
1531 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1533 EXPECT_REF(inlineobj
, 2);
1535 inlinetest
= (void*)0x1;
1536 hr
= IDWriteTextLayout_GetInlineObject(layout
, 2, &inlinetest
, NULL
);
1537 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1538 ok(inlinetest
== NULL
, "got %p\n", inlinetest
);
1541 r2
.startPosition
= r2
.length
= 100;
1542 hr
= IDWriteTextLayout_GetInlineObject(layout
, 0, &inlinetest
, &r2
);
1543 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1544 ok(inlinetest
== inlineobj
, "got %p\n", inlinetest
);
1545 ok(r2
.startPosition
== 0 && r2
.length
== 2, "got %d, %d\n", r2
.startPosition
, r2
.length
);
1546 IDWriteInlineObject_Release(inlinetest
);
1548 EXPECT_REF(inlineobj
, 2);
1550 /* get from somewhere inside a range */
1552 r2
.startPosition
= r2
.length
= 100;
1553 hr
= IDWriteTextLayout_GetInlineObject(layout
, 1, &inlinetest
, &r2
);
1554 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1555 ok(inlinetest
== inlineobj
, "got %p\n", inlinetest
);
1556 ok(r2
.startPosition
== 0 && r2
.length
== 2, "got %d, %d\n", r2
.startPosition
, r2
.length
);
1557 IDWriteInlineObject_Release(inlinetest
);
1559 EXPECT_REF(inlineobj
, 2);
1561 range
.startPosition
= 1;
1563 hr
= IDWriteTextLayout_SetInlineObject(layout
, inlineobj2
, range
);
1564 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1567 r2
.startPosition
= r2
.length
= 100;
1568 hr
= IDWriteTextLayout_GetInlineObject(layout
, 1, &inlinetest
, &r2
);
1569 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1570 ok(inlinetest
== inlineobj2
, "got %p\n", inlinetest
);
1571 ok(r2
.startPosition
== 1 && r2
.length
== 1, "got %d, %d\n", r2
.startPosition
, r2
.length
);
1572 IDWriteInlineObject_Release(inlinetest
);
1574 EXPECT_REF(inlineobj
, 2);
1575 EXPECT_REF(inlineobj2
, 2);
1578 r2
.startPosition
= r2
.length
= 100;
1579 hr
= IDWriteTextLayout_GetInlineObject(layout
, 0, &inlinetest
, &r2
);
1580 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1581 ok(inlinetest
== inlineobj
, "got %p\n", inlinetest
);
1582 ok(r2
.startPosition
== 0 && r2
.length
== 1, "got %d, %d\n", r2
.startPosition
, r2
.length
);
1583 IDWriteInlineObject_Release(inlinetest
);
1585 EXPECT_REF(inlineobj
, 2);
1587 range
.startPosition
= 1;
1589 hr
= IDWriteTextLayout_SetInlineObject(layout
, inlineobj
, range
);
1590 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1592 r2
.startPosition
= r2
.length
= 100;
1593 hr
= IDWriteTextLayout_GetInlineObject(layout
, 0, &inlinetest
, &r2
);
1594 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1595 ok(inlinetest
== inlineobj
, "got %p\n", inlinetest
);
1596 ok(r2
.startPosition
== 0 && r2
.length
== 2, "got %d, %d\n", r2
.startPosition
, r2
.length
);
1597 IDWriteInlineObject_Release(inlinetest
);
1599 EXPECT_REF(inlineobj
, 2);
1601 range
.startPosition
= 1;
1603 hr
= IDWriteTextLayout_SetInlineObject(layout
, inlineobj
, range
);
1604 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1606 EXPECT_REF(inlineobj
, 2);
1608 r2
.startPosition
= r2
.length
= 100;
1609 hr
= IDWriteTextLayout_GetInlineObject(layout
, 0, &inlinetest
, &r2
);
1610 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1611 ok(inlinetest
== inlineobj
, "got %p\n", inlinetest
);
1612 ok(r2
.startPosition
== 0 && r2
.length
== 3, "got %d, %d\n", r2
.startPosition
, r2
.length
);
1613 IDWriteInlineObject_Release(inlinetest
);
1615 EXPECT_REF(inlineobj
, 2);
1616 EXPECT_REF(inlineobj2
, 1);
1618 IDWriteTextLayout_Release(layout
);
1620 EXPECT_REF(inlineobj
, 1);
1622 IDWriteInlineObject_Release(inlineobj
);
1623 IDWriteInlineObject_Release(inlineobj2
);
1624 IDWriteTextFormat_Release(format
);
1625 IDWriteFactory_Release(factory
);
1628 /* drawing calls sequence doesn't depend on run order, instead all runs are
1629 drawn first, inline objects next and then underline/strikes */
1630 static const struct drawcall_entry draw_seq
[] = {
1631 { DRAW_GLYPHRUN
, {'s',0}, {'r','u',0}, 1 },
1632 { DRAW_GLYPHRUN
, {'r','i',0}, {'r','u',0}, 2 },
1633 { DRAW_GLYPHRUN
|DRAW_EFFECT
, {'n',0}, {'r','u',0}, 1 },
1634 { DRAW_GLYPHRUN
, {'g',0}, {'r','u',0}, 1 },
1636 { DRAW_UNDERLINE
, {0}, {'r','u',0} },
1637 { DRAW_STRIKETHROUGH
},
1641 static const struct drawcall_entry draw_seq2
[] = {
1642 { DRAW_GLYPHRUN
, {'s',0}, {'r','u',0}, 1 },
1643 { DRAW_GLYPHRUN
, {'t',0}, {'r','u',0}, 1 },
1644 { DRAW_GLYPHRUN
, {'r',0}, {'r','u',0}, 1 },
1645 { DRAW_GLYPHRUN
, {'i',0}, {'r','u',0}, 1 },
1646 { DRAW_GLYPHRUN
, {'n',0}, {'r','u',0}, 1 },
1647 { DRAW_GLYPHRUN
, {'g',0}, {'r','u',0}, 1 },
1651 static const struct drawcall_entry draw_seq3
[] = {
1652 { DRAW_GLYPHRUN
, {0x202a,0x202c,0}, {'r','u',0}, 0 },
1653 { DRAW_GLYPHRUN
, {'a','b',0}, {'r','u',0}, 2 },
1657 static const struct drawcall_entry draw_seq4
[] = {
1658 { DRAW_GLYPHRUN
, {'s','t','r',0}, {'r','u',0}, 3 },
1659 { DRAW_GLYPHRUN
, {'i','n','g',0}, {'r','u',0}, 3 },
1660 { DRAW_STRIKETHROUGH
},
1664 static const struct drawcall_entry draw_seq5
[] = {
1665 { DRAW_GLYPHRUN
, {'s','t',0}, {'r','u',0}, 2 },
1666 { DRAW_GLYPHRUN
, {'r','i',0}, {'r','u',0}, 2 },
1667 { DRAW_GLYPHRUN
, {'n','g',0}, {'r','u',0}, 2 },
1668 { DRAW_STRIKETHROUGH
},
1672 static const struct drawcall_entry empty_seq
[] = {
1676 static const struct drawcall_entry draw_single_run_seq
[] = {
1677 { DRAW_GLYPHRUN
, {'s','t','r','i','n','g',0}, {'r','u',0}, 6 },
1681 static const struct drawcall_entry draw_reordered_run_seq
[] = {
1682 { DRAW_GLYPHRUN
, {'1','2','3','-','5','2',0}, {'r','u',0}, 6 },
1683 { DRAW_GLYPHRUN
, {0x64a,0x64f,0x633,0x627,0x648,0x650,0x64a,0}, {'r','u',0}, 7 },
1684 { DRAW_GLYPHRUN
, {'7','1',0}, {'r','u',0}, 2 },
1685 { DRAW_GLYPHRUN
, {'.',0}, {'r','u',0}, 1 },
1689 static void test_Draw(void)
1691 static const WCHAR str3W
[] = {'1','2','3','-','5','2',0x64a,0x64f,0x633,0x627,0x648,0x650,
1692 0x64a,'7','1','.',0};
1693 static const WCHAR strW
[] = {'s','t','r','i','n','g',0};
1694 static const WCHAR str2W
[] = {0x202a,0x202c,'a','b',0};
1695 static const WCHAR ruW
[] = {'r','u',0};
1696 IDWriteInlineObject
*inlineobj
;
1697 struct renderer_context ctxt
;
1698 IDWriteTextFormat
*format
;
1699 IDWriteTextLayout
*layout
;
1700 DWRITE_TEXT_RANGE range
;
1701 IDWriteFactory
*factory
;
1702 DWRITE_TEXT_METRICS tm
;
1706 factory
= create_factory();
1708 memset(&ctxt
, 0, sizeof(ctxt
));
1709 ctxt
.snapping_disabled
= TRUE
;
1711 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_BOLD
, DWRITE_FONT_STYLE_NORMAL
,
1712 DWRITE_FONT_STRETCH_NORMAL
, 10.0, ruW
, &format
);
1713 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1715 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 6, format
, 100.0, 100.0, &layout
);
1716 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1718 hr
= IDWriteFactory_CreateEllipsisTrimmingSign(factory
, format
, &inlineobj
);
1719 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1721 range
.startPosition
= 5;
1723 hr
= IDWriteTextLayout_SetStrikethrough(layout
, TRUE
, range
);
1724 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1726 range
.startPosition
= 1;
1728 hr
= IDWriteTextLayout_SetInlineObject(layout
, inlineobj
, range
);
1729 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1731 range
.startPosition
= 4;
1733 hr
= IDWriteTextLayout_SetDrawingEffect(layout
, (IUnknown
*)inlineobj
, range
);
1734 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1736 range
.startPosition
= 0;
1738 hr
= IDWriteTextLayout_SetUnderline(layout
, TRUE
, range
);
1739 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1741 flush_sequence(sequences
, RENDERER_ID
);
1742 hr
= IDWriteTextLayout_Draw(layout
, &ctxt
, &testrenderer
, 0.0, 0.0);
1743 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1744 ok_sequence(sequences
, RENDERER_ID
, draw_seq
, "draw test", FALSE
);
1745 IDWriteTextLayout_Release(layout
);
1747 /* with reduced width DrawGlyphRun() is called for every line */
1748 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 6, format
, 5.0, 100.0, &layout
);
1749 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1750 flush_sequence(sequences
, RENDERER_ID
);
1751 hr
= IDWriteTextLayout_Draw(layout
, &ctxt
, &testrenderer
, 0.0, 0.0);
1752 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1753 ok_sequence(sequences
, RENDERER_ID
, draw_seq2
, "draw test 2", TRUE
);
1754 hr
= IDWriteTextLayout_GetMetrics(layout
, &tm
);
1755 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1757 ok(tm
.lineCount
== 6, "got %u\n", tm
.lineCount
);
1758 IDWriteTextLayout_Release(layout
);
1760 /* string with control characters */
1761 hr
= IDWriteFactory_CreateTextLayout(factory
, str2W
, 4, format
, 500.0, 100.0, &layout
);
1762 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1763 flush_sequence(sequences
, RENDERER_ID
);
1764 hr
= IDWriteTextLayout_Draw(layout
, &ctxt
, &testrenderer
, 0.0, 0.0);
1765 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1766 ok_sequence(sequences
, RENDERER_ID
, draw_seq3
, "draw test 3", FALSE
);
1767 IDWriteTextLayout_Release(layout
);
1769 /* strikethrough splits ranges from renderer point of view, but doesn't break
1771 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 6, format
, 500.0, 100.0, &layout
);
1772 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1773 flush_sequence(sequences
, RENDERER_ID
);
1775 range
.startPosition
= 0;
1777 hr
= IDWriteTextLayout_SetStrikethrough(layout
, TRUE
, range
);
1778 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1780 hr
= IDWriteTextLayout_Draw(layout
, &ctxt
, &testrenderer
, 0.0, 0.0);
1781 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1782 ok_sequence(sequences
, RENDERER_ID
, draw_seq4
, "draw test 4", FALSE
);
1783 IDWriteTextLayout_Release(layout
);
1785 /* strikethrough somewhere in the middle */
1786 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 6, format
, 500.0, 100.0, &layout
);
1787 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1788 flush_sequence(sequences
, RENDERER_ID
);
1790 range
.startPosition
= 2;
1792 hr
= IDWriteTextLayout_SetStrikethrough(layout
, TRUE
, range
);
1793 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1795 hr
= IDWriteTextLayout_Draw(layout
, &ctxt
, &testrenderer
, 0.0, 0.0);
1796 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1797 ok_sequence(sequences
, RENDERER_ID
, draw_seq5
, "draw test 5", FALSE
);
1798 IDWriteTextLayout_Release(layout
);
1801 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 0, format
, 500.0, 100.0, &layout
);
1802 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1804 flush_sequence(sequences
, RENDERER_ID
);
1805 hr
= IDWriteTextLayout_Draw(layout
, &ctxt
, &testrenderer
, 0.0, 0.0);
1806 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1807 ok_sequence(sequences
, RENDERER_ID
, empty_seq
, "draw test 6", FALSE
);
1808 IDWriteTextLayout_Release(layout
);
1810 ctxt
.gdicompat
= TRUE
;
1811 ctxt
.use_gdi_natural
= TRUE
;
1813 /* different parameter combinations with gdi-compatible layout */
1814 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, strW
, 6, format
, 100.0, 100.0, 1.0, NULL
, TRUE
, &layout
);
1815 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1816 flush_sequence(sequences
, RENDERER_ID
);
1817 hr
= IDWriteTextLayout_Draw(layout
, &ctxt
, &testrenderer
, 0.0, 0.0);
1818 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1819 ok_sequence(sequences
, RENDERER_ID
, draw_single_run_seq
, "draw test 7", FALSE
);
1821 /* text alignment keeps pixel-aligned origin */
1822 hr
= IDWriteTextLayout_GetMetrics(layout
, &tm
);
1823 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1824 ok(tm
.width
== floorf(tm
.width
), "got %f\n", tm
.width
);
1826 hr
= IDWriteTextLayout_SetMaxWidth(layout
, tm
.width
+ 3.0);
1827 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1828 hr
= IDWriteTextLayout_SetTextAlignment(layout
, DWRITE_TEXT_ALIGNMENT_CENTER
);
1829 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1831 ctxt
.originX
= ctxt
.originY
= 0.0;
1832 flush_sequence(sequences
, RENDERER_ID
);
1833 hr
= IDWriteTextLayout_Draw(layout
, &ctxt
, &testrenderer
, 0.0, 0.0);
1834 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1835 ok_sequence(sequences
, RENDERER_ID
, draw_single_run_seq
, "draw test 7", FALSE
);
1836 ok(ctxt
.originX
!= 0.0 && ctxt
.originX
== floorf(ctxt
.originX
), "got %f\n", ctxt
.originX
);
1838 IDWriteTextLayout_Release(layout
);
1840 ctxt
.gdicompat
= TRUE
;
1841 ctxt
.use_gdi_natural
= FALSE
;
1843 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, strW
, 6, format
, 100.0, 100.0, 1.0, NULL
, FALSE
, &layout
);
1844 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1845 flush_sequence(sequences
, RENDERER_ID
);
1846 hr
= IDWriteTextLayout_Draw(layout
, &ctxt
, &testrenderer
, 0.0, 0.0);
1847 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1848 ok_sequence(sequences
, RENDERER_ID
, draw_single_run_seq
, "draw test 8", FALSE
);
1849 IDWriteTextLayout_Release(layout
);
1851 ctxt
.gdicompat
= TRUE
;
1852 ctxt
.use_gdi_natural
= TRUE
;
1854 m
.m11
= m
.m22
= 2.0;
1855 m
.m12
= m
.m21
= m
.dx
= m
.dy
= 0.0;
1856 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, strW
, 6, format
, 100.0, 100.0, 1.0, &m
, TRUE
, &layout
);
1857 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1858 flush_sequence(sequences
, RENDERER_ID
);
1859 hr
= IDWriteTextLayout_Draw(layout
, &ctxt
, &testrenderer
, 0.0, 0.0);
1860 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1861 ok_sequence(sequences
, RENDERER_ID
, draw_single_run_seq
, "draw test 9", FALSE
);
1862 IDWriteTextLayout_Release(layout
);
1864 ctxt
.gdicompat
= TRUE
;
1865 ctxt
.use_gdi_natural
= FALSE
;
1867 m
.m11
= m
.m22
= 2.0;
1868 m
.m12
= m
.m21
= m
.dx
= m
.dy
= 0.0;
1869 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, strW
, 6, format
, 100.0, 100.0, 1.0, &m
, FALSE
, &layout
);
1870 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1871 flush_sequence(sequences
, RENDERER_ID
);
1872 hr
= IDWriteTextLayout_Draw(layout
, &ctxt
, &testrenderer
, 0.0, 0.0);
1873 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1874 ok_sequence(sequences
, RENDERER_ID
, draw_single_run_seq
, "draw test 10", FALSE
);
1875 IDWriteTextLayout_Release(layout
);
1877 IDWriteInlineObject_Release(inlineobj
);
1879 /* text that triggers bidi run reordering */
1880 hr
= IDWriteFactory_CreateTextLayout(factory
, str3W
, lstrlenW(str3W
), format
, 1000.0f
, 100.0f
, &layout
);
1881 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1883 ctxt
.gdicompat
= FALSE
;
1884 ctxt
.use_gdi_natural
= FALSE
;
1885 ctxt
.snapping_disabled
= TRUE
;
1887 flush_sequence(sequences
, RENDERER_ID
);
1888 hr
= IDWriteTextLayout_Draw(layout
, &ctxt
, &testrenderer
, 0.0f
, 0.0f
);
1889 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1890 ok_sequence(sequences
, RENDERER_ID
, draw_reordered_run_seq
, "draw test 11", FALSE
);
1892 IDWriteTextLayout_Release(layout
);
1894 IDWriteTextFormat_Release(format
);
1895 IDWriteFactory_Release(factory
);
1898 static void test_typography(void)
1900 DWRITE_FONT_FEATURE feature
;
1901 IDWriteTypography
*typography
;
1902 IDWriteFactory
*factory
;
1906 factory
= create_factory();
1908 hr
= IDWriteFactory_CreateTypography(factory
, &typography
);
1909 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1911 feature
.nameTag
= DWRITE_FONT_FEATURE_TAG_KERNING
;
1912 feature
.parameter
= 1;
1913 hr
= IDWriteTypography_AddFontFeature(typography
, feature
);
1914 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1916 count
= IDWriteTypography_GetFontFeatureCount(typography
);
1917 ok(count
== 1, "got %u\n", count
);
1919 /* duplicated features work just fine */
1920 feature
.nameTag
= DWRITE_FONT_FEATURE_TAG_KERNING
;
1921 feature
.parameter
= 0;
1922 hr
= IDWriteTypography_AddFontFeature(typography
, feature
);
1923 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1925 count
= IDWriteTypography_GetFontFeatureCount(typography
);
1926 ok(count
== 2, "got %u\n", count
);
1928 memset(&feature
, 0xcc, sizeof(feature
));
1929 hr
= IDWriteTypography_GetFontFeature(typography
, 0, &feature
);
1930 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1931 ok(feature
.nameTag
== DWRITE_FONT_FEATURE_TAG_KERNING
, "got tag %x\n", feature
.nameTag
);
1932 ok(feature
.parameter
== 1, "got %u\n", feature
.parameter
);
1934 memset(&feature
, 0xcc, sizeof(feature
));
1935 hr
= IDWriteTypography_GetFontFeature(typography
, 1, &feature
);
1936 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1937 ok(feature
.nameTag
== DWRITE_FONT_FEATURE_TAG_KERNING
, "got tag %x\n", feature
.nameTag
);
1938 ok(feature
.parameter
== 0, "got %u\n", feature
.parameter
);
1940 hr
= IDWriteTypography_GetFontFeature(typography
, 2, &feature
);
1941 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1943 /* duplicated with same parameter value */
1944 feature
.nameTag
= DWRITE_FONT_FEATURE_TAG_KERNING
;
1945 feature
.parameter
= 0;
1946 hr
= IDWriteTypography_AddFontFeature(typography
, feature
);
1947 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1949 count
= IDWriteTypography_GetFontFeatureCount(typography
);
1950 ok(count
== 3, "got %u\n", count
);
1952 memset(&feature
, 0xcc, sizeof(feature
));
1953 hr
= IDWriteTypography_GetFontFeature(typography
, 2, &feature
);
1954 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1955 ok(feature
.nameTag
== DWRITE_FONT_FEATURE_TAG_KERNING
, "got tag %x\n", feature
.nameTag
);
1956 ok(feature
.parameter
== 0, "got %u\n", feature
.parameter
);
1958 IDWriteTypography_Release(typography
);
1959 IDWriteFactory_Release(factory
);
1962 static void test_GetClusterMetrics(void)
1964 static const WCHAR str_white_spaceW
[] = {
1965 /* BK - FORM FEED, LINE TABULATION, LINE SEP, PARA SEP */ 0xc, 0xb, 0x2028, 0x2029,
1966 /* ZW - ZERO WIDTH SPACE */ 0x200b,
1967 /* SP - SPACE */ 0x20
1969 static const WCHAR str5W
[] = {'a','\r','b','\n','c','\n','\r','d','\r','\n','e',0xb,'f',0xc,
1970 'g',0x0085,'h',0x2028,'i',0x2029,0xad,0xa,0};
1971 static const WCHAR str3W
[] = {0x2066,')',')',0x661,'(',0x627,')',0};
1972 static const WCHAR str2W
[] = {0x202a,0x202c,'a',0};
1973 static const WCHAR strW
[] = {'a','b','c','d',0};
1974 static const WCHAR str4W
[] = {'a',' ',0};
1975 static const WCHAR str6W
[] = {'a',' ','b',0};
1976 DWRITE_INLINE_OBJECT_METRICS inline_metrics
;
1977 DWRITE_CLUSTER_METRICS metrics
[22];
1978 DWRITE_TEXT_METRICS text_metrics
;
1979 DWRITE_TRIMMING trimming_options
;
1980 IDWriteTextLayout1
*layout1
;
1981 IDWriteInlineObject
*trimm
;
1982 IDWriteTextFormat
*format
;
1983 IDWriteTextLayout
*layout
;
1984 DWRITE_LINE_METRICS line
;
1985 DWRITE_TEXT_RANGE range
;
1986 IDWriteFactory
*factory
;
1991 factory
= create_factory();
1993 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
1994 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
1995 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1997 hr
= IDWriteFactory_CreateTextLayout(factory
, str3W
, 7, format
, 1000.0, 1000.0, &layout
);
1998 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1999 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, NULL
, 0, &count
);
2000 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
2001 ok(count
== 7, "got %u\n", count
);
2002 IDWriteTextLayout_Release(layout
);
2004 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 1000.0, 1000.0, &layout
);
2005 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2008 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, NULL
, 0, &count
);
2009 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
2010 ok(count
== 4, "got %u\n", count
);
2012 /* check every cluster width */
2014 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, metrics
, ARRAY_SIZE(metrics
), &count
);
2015 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2016 ok(count
== 4, "got %u\n", count
);
2017 for (i
= 0; i
< count
; i
++) {
2018 ok(metrics
[i
].width
> 0.0, "%u: got width %.2f\n", i
, metrics
[i
].width
);
2019 ok(metrics
[i
].length
== 1, "%u: got length %u\n", i
, metrics
[i
].length
);
2022 /* apply spacing and check widths again */
2023 if (IDWriteTextLayout_QueryInterface(layout
, &IID_IDWriteTextLayout1
, (void**)&layout1
) == S_OK
) {
2024 DWRITE_CLUSTER_METRICS metrics2
[4];
2025 FLOAT leading
, trailing
, min_advance
;
2026 DWRITE_TEXT_RANGE r
;
2028 leading
= trailing
= min_advance
= 2.0;
2029 hr
= IDWriteTextLayout1_GetCharacterSpacing(layout1
, 500, &leading
, &trailing
,
2031 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2032 ok(leading
== 0.0 && trailing
== 0.0 && min_advance
== 0.0,
2033 "got %.2f, %.2f, %.2f\n", leading
, trailing
, min_advance
);
2034 ok(r
.startPosition
== 0 && r
.length
== ~0u, "got %u, %u\n", r
.startPosition
, r
.length
);
2036 leading
= trailing
= min_advance
= 2.0;
2037 hr
= IDWriteTextLayout1_GetCharacterSpacing(layout1
, 0, &leading
, &trailing
,
2038 &min_advance
, NULL
);
2039 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2040 ok(leading
== 0.0 && trailing
== 0.0 && min_advance
== 0.0,
2041 "got %.2f, %.2f, %.2f\n", leading
, trailing
, min_advance
);
2043 r
.startPosition
= 0;
2045 hr
= IDWriteTextLayout1_SetCharacterSpacing(layout1
, 10.0, 15.0, 0.0, r
);
2046 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2049 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, metrics2
, ARRAY_SIZE(metrics2
), &count
);
2050 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2051 ok(count
== 4, "got %u\n", count
);
2052 for (i
= 0; i
< count
; i
++) {
2054 ok(metrics2
[i
].width
> metrics
[i
].width
, "%u: got width %.2f, was %.2f\n", i
, metrics2
[i
].width
,
2056 ok(metrics2
[i
].length
== 1, "%u: got length %u\n", i
, metrics2
[i
].length
);
2059 /* back to defaults */
2060 r
.startPosition
= 0;
2062 hr
= IDWriteTextLayout1_SetCharacterSpacing(layout1
, 0.0, 0.0, 0.0, r
);
2063 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2065 /* negative advance limit */
2066 r
.startPosition
= 0;
2068 hr
= IDWriteTextLayout1_SetCharacterSpacing(layout1
, 0.0, 0.0, -10.0, r
);
2069 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
2071 IDWriteTextLayout1_Release(layout1
);
2074 win_skip("IDWriteTextLayout1 is not supported, cluster spacing test skipped.\n");
2076 hr
= IDWriteFactory_CreateEllipsisTrimmingSign(factory
, format
, &trimm
);
2077 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2079 range
.startPosition
= 0;
2081 hr
= IDWriteTextLayout_SetInlineObject(layout
, trimm
, range
);
2082 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2084 /* inline object takes a separate cluster, replaced codepoints number doesn't matter */
2086 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, NULL
, 0, &count
);
2087 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
2088 ok(count
== 3, "got %u\n", count
);
2091 memset(&metrics
, 0, sizeof(metrics
));
2092 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, metrics
, 1, &count
);
2093 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
2094 ok(count
== 3, "got %u\n", count
);
2095 ok(metrics
[0].length
== 2, "got %u\n", metrics
[0].length
);
2097 hr
= IDWriteInlineObject_GetMetrics(trimm
, &inline_metrics
);
2098 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2099 ok(inline_metrics
.width
> 0.0 && inline_metrics
.width
== metrics
[0].width
, "got %.2f, expected %.2f\n",
2100 inline_metrics
.width
, metrics
[0].width
);
2102 IDWriteTextLayout_Release(layout
);
2104 /* text with non-visual control codes */
2105 hr
= IDWriteFactory_CreateTextLayout(factory
, str2W
, 3, format
, 1000.0, 1000.0, &layout
);
2106 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2108 /* bidi control codes take a separate cluster */
2110 memset(metrics
, 0, sizeof(metrics
));
2111 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, metrics
, 3, &count
);
2112 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2113 ok(count
== 3, "got %u\n", count
);
2115 ok(metrics
[0].width
== 0.0, "got %.2f\n", metrics
[0].width
);
2116 ok(metrics
[0].length
== 1, "got %d\n", metrics
[0].length
);
2117 ok(metrics
[0].canWrapLineAfter
== 0, "got %d\n", metrics
[0].canWrapLineAfter
);
2118 ok(metrics
[0].isWhitespace
== 0, "got %d\n", metrics
[0].isWhitespace
);
2119 ok(metrics
[0].isNewline
== 0, "got %d\n", metrics
[0].isNewline
);
2120 ok(metrics
[0].isSoftHyphen
== 0, "got %d\n", metrics
[0].isSoftHyphen
);
2121 ok(metrics
[0].isRightToLeft
== 0, "got %d\n", metrics
[0].isRightToLeft
);
2123 ok(metrics
[1].width
== 0.0, "got %.2f\n", metrics
[1].width
);
2124 ok(metrics
[1].length
== 1, "got %d\n", metrics
[1].length
);
2125 ok(metrics
[1].canWrapLineAfter
== 0, "got %d\n", metrics
[1].canWrapLineAfter
);
2126 ok(metrics
[1].isWhitespace
== 0, "got %d\n", metrics
[1].isWhitespace
);
2127 ok(metrics
[1].isNewline
== 0, "got %d\n", metrics
[1].isNewline
);
2128 ok(metrics
[1].isSoftHyphen
== 0, "got %d\n", metrics
[1].isSoftHyphen
);
2129 ok(metrics
[1].isRightToLeft
== 0, "got %d\n", metrics
[1].isRightToLeft
);
2131 ok(metrics
[2].width
> 0.0, "got %.2f\n", metrics
[2].width
);
2132 ok(metrics
[2].length
== 1, "got %d\n", metrics
[2].length
);
2133 ok(metrics
[2].canWrapLineAfter
== 1, "got %d\n", metrics
[2].canWrapLineAfter
);
2134 ok(metrics
[2].isWhitespace
== 0, "got %d\n", metrics
[2].isWhitespace
);
2135 ok(metrics
[2].isNewline
== 0, "got %d\n", metrics
[2].isNewline
);
2136 ok(metrics
[2].isSoftHyphen
== 0, "got %d\n", metrics
[2].isSoftHyphen
);
2137 ok(metrics
[2].isRightToLeft
== 0, "got %d\n", metrics
[2].isRightToLeft
);
2139 IDWriteTextLayout_Release(layout
);
2141 /* single inline object that fails to report its metrics */
2142 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 1000.0, 1000.0, &layout
);
2143 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2145 range
.startPosition
= 0;
2147 hr
= IDWriteTextLayout_SetInlineObject(layout
, &testinlineobj
, range
);
2148 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2151 memset(metrics
, 0, sizeof(metrics
));
2152 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, metrics
, 3, &count
);
2153 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2154 ok(count
== 1, "got %u\n", count
);
2156 /* object sets a width to 123.0, but returns failure from GetMetrics() */
2157 ok(metrics
[0].width
== 0.0, "got %.2f\n", metrics
[0].width
);
2158 ok(metrics
[0].length
== 4, "got %d\n", metrics
[0].length
);
2159 ok(metrics
[0].canWrapLineAfter
== 1, "got %d\n", metrics
[0].canWrapLineAfter
);
2160 ok(metrics
[0].isWhitespace
== 0, "got %d\n", metrics
[0].isWhitespace
);
2161 ok(metrics
[0].isNewline
== 0, "got %d\n", metrics
[0].isNewline
);
2162 ok(metrics
[0].isSoftHyphen
== 0, "got %d\n", metrics
[0].isSoftHyphen
);
2163 ok(metrics
[0].isRightToLeft
== 0, "got %d\n", metrics
[0].isRightToLeft
);
2165 /* now set two inline object for [0,1] and [2,3], both fail to report break conditions */
2166 range
.startPosition
= 2;
2168 hr
= IDWriteTextLayout_SetInlineObject(layout
, &testinlineobj2
, range
);
2169 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2172 memset(metrics
, 0, sizeof(metrics
));
2173 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, metrics
, 3, &count
);
2174 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2175 ok(count
== 2, "got %u\n", count
);
2177 ok(metrics
[0].width
== 0.0, "got %.2f\n", metrics
[0].width
);
2178 ok(metrics
[0].length
== 2, "got %d\n", metrics
[0].length
);
2179 ok(metrics
[0].canWrapLineAfter
== 0, "got %d\n", metrics
[0].canWrapLineAfter
);
2180 ok(metrics
[0].isWhitespace
== 0, "got %d\n", metrics
[0].isWhitespace
);
2181 ok(metrics
[0].isNewline
== 0, "got %d\n", metrics
[0].isNewline
);
2182 ok(metrics
[0].isSoftHyphen
== 0, "got %d\n", metrics
[0].isSoftHyphen
);
2183 ok(metrics
[0].isRightToLeft
== 0, "got %d\n", metrics
[0].isRightToLeft
);
2185 ok(metrics
[1].width
== 0.0, "got %.2f\n", metrics
[1].width
);
2186 ok(metrics
[1].length
== 2, "got %d\n", metrics
[1].length
);
2187 ok(metrics
[1].canWrapLineAfter
== 1, "got %d\n", metrics
[1].canWrapLineAfter
);
2188 ok(metrics
[1].isWhitespace
== 0, "got %d\n", metrics
[1].isWhitespace
);
2189 ok(metrics
[1].isNewline
== 0, "got %d\n", metrics
[1].isNewline
);
2190 ok(metrics
[1].isSoftHyphen
== 0, "got %d\n", metrics
[1].isSoftHyphen
);
2191 ok(metrics
[1].isRightToLeft
== 0, "got %d\n", metrics
[1].isRightToLeft
);
2193 IDWriteTextLayout_Release(layout
);
2195 /* zero length string */
2196 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 0, format
, 1000.0, 1000.0, &layout
);
2197 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2200 memset(metrics
, 0, sizeof(metrics
));
2201 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, metrics
, 3, &count
);
2202 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2203 ok(count
== 0, "got %u\n", count
);
2204 IDWriteTextLayout_Release(layout
);
2207 hr
= IDWriteFactory_CreateTextLayout(factory
, str4W
, 2, format
, 1000.0, 1000.0, &layout
);
2208 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2211 memset(metrics
, 0, sizeof(metrics
));
2212 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, metrics
, 2, &count
);
2213 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2214 ok(count
== 2, "got %u\n", count
);
2215 ok(metrics
[0].isWhitespace
== 0, "got %d\n", metrics
[0].isWhitespace
);
2216 ok(metrics
[0].canWrapLineAfter
== 0, "got %d\n", metrics
[0].canWrapLineAfter
);
2217 ok(metrics
[1].isWhitespace
== 1, "got %d\n", metrics
[1].isWhitespace
);
2218 ok(metrics
[1].canWrapLineAfter
== 1, "got %d\n", metrics
[1].canWrapLineAfter
);
2219 IDWriteTextLayout_Release(layout
);
2221 /* layout is fully covered by inline object with after condition DWRITE_BREAK_CONDITION_MAY_NOT_BREAK */
2222 hr
= IDWriteFactory_CreateTextLayout(factory
, str4W
, 2, format
, 1000.0, 1000.0, &layout
);
2223 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2225 range
.startPosition
= 0;
2227 hr
= IDWriteTextLayout_SetInlineObject(layout
, &testinlineobj3
, range
);
2228 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2231 memset(metrics
, 0, sizeof(metrics
));
2232 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, metrics
, 2, &count
);
2233 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2234 ok(count
== 1, "got %u\n", count
);
2235 ok(metrics
[0].canWrapLineAfter
== 1, "got %d\n", metrics
[0].canWrapLineAfter
);
2237 IDWriteTextLayout_Release(layout
);
2239 /* compare natural cluster width with gdi layout */
2240 hr
= IDWriteFactory_CreateTextLayout(factory
, str4W
, 1, format
, 100.0, 100.0, &layout
);
2241 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2244 memset(metrics
, 0, sizeof(metrics
));
2245 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, metrics
, 1, &count
);
2246 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2247 ok(count
== 1, "got %u\n", count
);
2248 ok(metrics
[0].width
!= floorf(metrics
[0].width
), "got %f\n", metrics
[0].width
);
2250 IDWriteTextLayout_Release(layout
);
2252 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, str4W
, 1, format
, 100.0, 100.0, 1.0, NULL
, FALSE
, &layout
);
2253 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2256 memset(metrics
, 0, sizeof(metrics
));
2257 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, metrics
, 1, &count
);
2258 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2259 ok(count
== 1, "got %u\n", count
);
2260 ok(metrics
[0].width
== floorf(metrics
[0].width
), "got %f\n", metrics
[0].width
);
2262 IDWriteTextLayout_Release(layout
);
2264 /* isNewline tests */
2265 hr
= IDWriteFactory_CreateTextLayout(factory
, str5W
, lstrlenW(str5W
), format
, 100.0f
, 200.0f
, &layout
);
2266 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2269 memset(metrics
, 0, sizeof(metrics
));
2270 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, metrics
, ARRAY_SIZE(metrics
), &count
);
2271 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2272 ok(count
== 22, "got %u\n", count
);
2274 ok(metrics
[1].isNewline
== 1, "got %d\n", metrics
[1].isNewline
);
2275 ok(metrics
[3].isNewline
== 1, "got %d\n", metrics
[3].isNewline
);
2276 ok(metrics
[5].isNewline
== 1, "got %d\n", metrics
[5].isNewline
);
2277 ok(metrics
[6].isNewline
== 1, "got %d\n", metrics
[6].isNewline
);
2278 ok(metrics
[9].isNewline
== 1, "got %d\n", metrics
[9].isNewline
);
2279 ok(metrics
[11].isNewline
== 1, "got %d\n", metrics
[11].isNewline
);
2280 ok(metrics
[13].isNewline
== 1, "got %d\n", metrics
[13].isNewline
);
2281 ok(metrics
[15].isNewline
== 1, "got %d\n", metrics
[15].isNewline
);
2282 ok(metrics
[17].isNewline
== 1, "got %d\n", metrics
[17].isNewline
);
2283 ok(metrics
[19].isNewline
== 1, "got %d\n", metrics
[19].isNewline
);
2284 ok(metrics
[21].isNewline
== 1, "got %d\n", metrics
[21].isNewline
);
2286 ok(metrics
[0].isNewline
== 0, "got %d\n", metrics
[0].isNewline
);
2287 ok(metrics
[2].isNewline
== 0, "got %d\n", metrics
[2].isNewline
);
2288 ok(metrics
[4].isNewline
== 0, "got %d\n", metrics
[4].isNewline
);
2289 ok(metrics
[7].isNewline
== 0, "got %d\n", metrics
[7].isNewline
);
2290 ok(metrics
[8].isNewline
== 0, "got %d\n", metrics
[8].isNewline
);
2291 ok(metrics
[10].isNewline
== 0, "got %d\n", metrics
[10].isNewline
);
2292 ok(metrics
[12].isNewline
== 0, "got %d\n", metrics
[12].isNewline
);
2293 ok(metrics
[14].isNewline
== 0, "got %d\n", metrics
[14].isNewline
);
2294 ok(metrics
[16].isNewline
== 0, "got %d\n", metrics
[16].isNewline
);
2295 ok(metrics
[18].isNewline
== 0, "got %d\n", metrics
[18].isNewline
);
2296 ok(metrics
[20].isNewline
== 0, "got %d\n", metrics
[20].isNewline
);
2298 for (i
= 0; i
< count
; i
++) {
2299 ok(metrics
[i
].length
== 1, "%d: got %d\n", i
, metrics
[i
].length
);
2300 ok(metrics
[i
].isSoftHyphen
== (i
== count
- 2), "%d: got %d\n", i
, metrics
[i
].isSoftHyphen
);
2301 if (metrics
[i
].isSoftHyphen
)
2302 ok(!metrics
[i
].isWhitespace
, "%u: got %d\n", i
, metrics
[i
].isWhitespace
);
2303 if (metrics
[i
].isNewline
) {
2304 ok(metrics
[i
].width
== 0.0f
, "%u: got width %f\n", i
, metrics
[i
].width
);
2305 ok(metrics
[i
].isWhitespace
== 1, "%u: got %d\n", i
, metrics
[i
].isWhitespace
);
2306 ok(metrics
[i
].canWrapLineAfter
== 1, "%u: got %d\n", i
, metrics
[i
].canWrapLineAfter
);
2310 IDWriteTextLayout_Release(layout
);
2312 /* Test whitespace resolution from linebreaking classes BK, ZW, and SP */
2313 hr
= IDWriteFactory_CreateTextLayout(factory
, str_white_spaceW
, ARRAY_SIZE(str_white_spaceW
), format
,
2314 100.0f
, 200.0f
, &layout
);
2315 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2318 memset(metrics
, 0, sizeof(metrics
));
2319 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, metrics
, 20, &count
);
2320 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2321 ok(count
== 6, "got %u\n", count
);
2323 ok(metrics
[0].isWhitespace
== 1, "got %d\n", metrics
[0].isWhitespace
);
2324 ok(metrics
[1].isWhitespace
== 1, "got %d\n", metrics
[1].isWhitespace
);
2325 ok(metrics
[2].isWhitespace
== 1, "got %d\n", metrics
[2].isWhitespace
);
2326 ok(metrics
[3].isWhitespace
== 1, "got %d\n", metrics
[3].isWhitespace
);
2327 ok(metrics
[4].isWhitespace
== 0, "got %d\n", metrics
[4].isWhitespace
);
2328 ok(metrics
[5].isWhitespace
== 1, "got %d\n", metrics
[5].isWhitespace
);
2330 IDWriteTextLayout_Release(layout
);
2332 /* trigger line trimming */
2333 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, lstrlenW(strW
), format
, 100.0f
, 200.0f
, &layout
);
2334 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2337 memset(metrics
, 0, sizeof(metrics
));
2338 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, metrics
, 4, &count
);
2339 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2340 ok(count
== 4, "got %u\n", count
);
2342 hr
= IDWriteTextLayout_GetMetrics(layout
, &text_metrics
);
2343 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2345 width
= metrics
[0].width
+ inline_metrics
.width
;
2346 ok(width
< text_metrics
.width
, "unexpected trimming sign width\n");
2348 /* enable trimming, reduce layout width so only first cluster and trimming sign fits */
2349 trimming_options
.granularity
= DWRITE_TRIMMING_GRANULARITY_CHARACTER
;
2350 trimming_options
.delimiter
= 0;
2351 trimming_options
.delimiterCount
= 0;
2352 hr
= IDWriteTextLayout_SetTrimming(layout
, &trimming_options
, trimm
);
2353 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2355 hr
= IDWriteTextLayout_SetMaxWidth(layout
, width
);
2356 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2359 memset(metrics
, 0, sizeof(metrics
));
2360 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, metrics
, 4, &count
);
2361 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2362 ok(count
== 4, "got %u\n", count
);
2364 hr
= IDWriteTextLayout_GetLineMetrics(layout
, &line
, 1, &count
);
2365 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2366 ok(count
== 1, "got %u\n", count
);
2367 ok(line
.length
== 4, "got %u\n", line
.length
);
2368 ok(line
.isTrimmed
, "got %d\n", line
.isTrimmed
);
2370 IDWriteTextLayout_Release(layout
);
2372 /* NO_WRAP, check cluster wrapping attribute. */
2373 hr
= IDWriteTextFormat_SetWordWrapping(format
, DWRITE_WORD_WRAPPING_NO_WRAP
);
2374 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2376 hr
= IDWriteFactory_CreateTextLayout(factory
, str6W
, lstrlenW(str6W
), format
, 1000.0f
, 200.0f
, &layout
);
2377 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2380 memset(metrics
, 0, sizeof(metrics
));
2381 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, metrics
, 3, &count
);
2382 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2383 ok(count
== 3, "got %u\n", count
);
2385 ok(metrics
[0].canWrapLineAfter
== 0, "got %d\n", metrics
[0].canWrapLineAfter
);
2386 ok(metrics
[1].canWrapLineAfter
== 1, "got %d\n", metrics
[1].canWrapLineAfter
);
2387 ok(metrics
[2].canWrapLineAfter
== 1, "got %d\n", metrics
[2].canWrapLineAfter
);
2389 IDWriteTextLayout_Release(layout
);
2391 IDWriteInlineObject_Release(trimm
);
2392 IDWriteTextFormat_Release(format
);
2393 IDWriteFactory_Release(factory
);
2396 static void test_SetLocaleName(void)
2398 static const WCHAR eNuSW
[] = {'e','N','-','u','S',0};
2399 static const WCHAR strW
[] = {'a','b','c','d',0};
2400 WCHAR buffW
[LOCALE_NAME_MAX_LENGTH
+ ARRAY_SIZE(strW
)];
2401 IDWriteTextFormat
*format
, *format2
;
2402 IDWriteTextLayout
*layout
;
2403 DWRITE_TEXT_RANGE range
;
2404 IDWriteFactory
*factory
;
2407 factory
= create_factory();
2409 /* create format with mixed case locale name, get it back */
2410 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
2411 DWRITE_FONT_STRETCH_NORMAL
, 10.0, eNuSW
, &format
);
2412 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2414 hr
= IDWriteTextFormat_GetLocaleName(format
, buffW
, ARRAY_SIZE(buffW
));
2415 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2416 ok(!lstrcmpW(buffW
, enusW
), "got %s\n", wine_dbgstr_w(buffW
));
2418 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 1000.0, 1000.0, &layout
);
2419 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2421 hr
= IDWriteTextLayout_QueryInterface(layout
, &IID_IDWriteTextFormat
, (void**)&format2
);
2422 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2424 hr
= IDWriteTextFormat_GetLocaleName(format2
, buffW
, ARRAY_SIZE(buffW
));
2425 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2426 ok(!lstrcmpW(buffW
, enusW
), "got %s\n", wine_dbgstr_w(buffW
));
2428 hr
= IDWriteTextLayout_GetLocaleName(layout
, 0, buffW
, ARRAY_SIZE(buffW
), NULL
);
2429 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2430 ok(!lstrcmpW(buffW
, enusW
), "got %s\n", wine_dbgstr_w(buffW
));
2432 IDWriteTextFormat_Release(format2
);
2433 IDWriteTextLayout_Release(layout
);
2434 IDWriteTextFormat_Release(format
);
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
, 4, format
, 1000.0, 1000.0, &layout
);
2441 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2443 range
.startPosition
= 0;
2445 hr
= IDWriteTextLayout_SetLocaleName(layout
, enusW
, range
);
2446 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2448 hr
= IDWriteTextLayout_SetLocaleName(layout
, NULL
, range
);
2449 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
2451 /* invalid locale name is allowed */
2452 hr
= IDWriteTextLayout_SetLocaleName(layout
, strW
, range
);
2453 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2455 hr
= IDWriteTextLayout_GetLocaleName(layout
, 0, NULL
, 0, NULL
);
2456 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
2458 if (0) /* crashes on native */
2459 hr
= IDWriteTextLayout_GetLocaleName(layout
, 0, NULL
, 1, NULL
);
2463 hr
= IDWriteTextLayout_GetLocaleName(layout
, 0, buffW
, ARRAY_SIZE(buffW
), &range
);
2464 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2465 ok(!lstrcmpW(buffW
, strW
), "got %s\n", wine_dbgstr_w(buffW
));
2466 ok(range
.startPosition
== 0 && range
.length
== 1, "got %u,%u\n", range
.startPosition
, range
.length
);
2468 /* get with a shorter buffer */
2470 hr
= IDWriteTextLayout_GetLocaleName(layout
, 0, buffW
, 1, NULL
);
2471 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
2472 ok(buffW
[0] == 0, "got %x\n", buffW
[0]);
2474 /* name is too long */
2475 lstrcpyW(buffW
, strW
);
2476 while (lstrlenW(buffW
) <= LOCALE_NAME_MAX_LENGTH
)
2477 lstrcatW(buffW
, strW
);
2479 range
.startPosition
= 0;
2481 hr
= IDWriteTextLayout_SetLocaleName(layout
, buffW
, range
);
2482 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
2485 hr
= IDWriteTextLayout_GetLocaleName(layout
, 0, buffW
, ARRAY_SIZE(buffW
), NULL
);
2486 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2487 ok(!lstrcmpW(buffW
, strW
), "got %s\n", wine_dbgstr_w(buffW
));
2489 /* set initial locale name for whole text, except with a different casing */
2490 range
.startPosition
= 0;
2492 hr
= IDWriteTextLayout_SetLocaleName(layout
, eNuSW
, range
);
2493 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2497 hr
= IDWriteTextLayout_GetLocaleName(layout
, 0, buffW
, ARRAY_SIZE(buffW
), &range
);
2498 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2499 ok(!lstrcmpW(buffW
, enusW
), "got %s\n", wine_dbgstr_w(buffW
));
2500 ok((range
.startPosition
== 0 && range
.length
== ~0u) ||
2501 broken(range
.startPosition
== 0 && range
.length
== 4) /* vista/win7 */, "got %u,%u\n", range
.startPosition
, range
.length
);
2503 /* check what's returned for positions after the text */
2506 hr
= IDWriteTextLayout_GetLocaleName(layout
, 100, buffW
, ARRAY_SIZE(buffW
), &range
);
2507 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2508 ok(!lstrcmpW(buffW
, enusW
), "got %s\n", wine_dbgstr_w(buffW
));
2509 ok((range
.startPosition
== 0 && range
.length
== ~0u) ||
2510 broken(range
.startPosition
== 4 && range
.length
== ~0u-4) /* vista/win7 */, "got %u,%u\n", range
.startPosition
, range
.length
);
2512 IDWriteTextLayout_Release(layout
);
2513 IDWriteTextFormat_Release(format
);
2514 IDWriteFactory_Release(factory
);
2517 static void test_SetPairKerning(void)
2519 static const WCHAR strW
[] = {'a','e',0x0300,'d',0}; /* accent grave */
2520 DWRITE_CLUSTER_METRICS clusters
[4];
2521 IDWriteTextLayout1
*layout1
;
2522 IDWriteTextFormat
*format
;
2523 IDWriteTextLayout
*layout
;
2524 DWRITE_TEXT_RANGE range
;
2525 IDWriteFactory
*factory
;
2530 factory
= create_factory();
2532 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
2533 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
2534 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2536 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 1000.0, 1000.0, &layout
);
2537 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2538 IDWriteTextFormat_Release(format
);
2540 hr
= IDWriteTextLayout_QueryInterface(layout
, &IID_IDWriteTextLayout1
, (void**)&layout1
);
2541 IDWriteTextLayout_Release(layout
);
2544 win_skip("SetPairKerning() is not supported.\n");
2545 IDWriteFactory_Release(factory
);
2549 if (0) { /* crashes on native */
2550 hr
= IDWriteTextLayout1_GetPairKerning(layout1
, 0, NULL
, NULL
);
2551 hr
= IDWriteTextLayout1_GetPairKerning(layout1
, 0, NULL
, &range
);
2554 hr
= IDWriteTextLayout1_GetPairKerning(layout1
, 0, &kerning
, NULL
);
2555 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2557 range
.startPosition
= 0;
2560 hr
= IDWriteTextLayout1_GetPairKerning(layout1
, 0, &kerning
, &range
);
2561 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2562 ok(!kerning
, "got %d\n", kerning
);
2563 ok(range
.length
== ~0u, "got %u\n", range
.length
);
2566 hr
= IDWriteTextLayout1_GetClusterMetrics(layout1
, clusters
, 4, &count
);
2567 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2569 ok(count
== 3, "got %u\n", count
);
2571 ok(clusters
[0].length
== 1, "got %u\n", clusters
[0].length
);
2572 ok(clusters
[1].length
== 2, "got %u\n", clusters
[1].length
);
2573 ok(clusters
[2].length
== 1, "got %u\n", clusters
[2].length
);
2575 /* pair kerning flag participates in itemization - combining characters
2577 range
.startPosition
= 0;
2579 hr
= IDWriteTextLayout1_SetPairKerning(layout1
, 2, range
);
2580 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2583 hr
= IDWriteTextLayout1_GetPairKerning(layout1
, 0, &kerning
, &range
);
2584 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2585 ok(kerning
== TRUE
, "got %d\n", kerning
);
2588 hr
= IDWriteTextLayout1_GetClusterMetrics(layout1
, clusters
, 4, &count
);
2589 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2590 ok(count
== 4, "got %u\n", count
);
2591 ok(clusters
[0].length
== 1, "got %u\n", clusters
[0].length
);
2592 ok(clusters
[1].length
== 1, "got %u\n", clusters
[1].length
);
2593 ok(clusters
[2].length
== 1, "got %u\n", clusters
[2].length
);
2594 ok(clusters
[3].length
== 1, "got %u\n", clusters
[3].length
);
2596 IDWriteTextLayout1_Release(layout1
);
2597 IDWriteFactory_Release(factory
);
2600 static void test_SetVerticalGlyphOrientation(void)
2602 static const WCHAR strW
[] = {'a','b','c','d',0};
2603 DWRITE_VERTICAL_GLYPH_ORIENTATION orientation
;
2604 IDWriteTextLayout2
*layout2
;
2605 IDWriteTextFormat
*format
;
2606 IDWriteTextLayout
*layout
;
2607 IDWriteFactory
*factory
;
2610 factory
= create_factory();
2612 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
2613 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
2614 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2616 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 1000.0, 1000.0, &layout
);
2617 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2618 IDWriteTextFormat_Release(format
);
2620 hr
= IDWriteTextLayout_QueryInterface(layout
, &IID_IDWriteTextLayout2
, (void**)&layout2
);
2621 IDWriteTextLayout_Release(layout
);
2624 win_skip("SetVerticalGlyphOrientation() is not supported.\n");
2625 IDWriteFactory_Release(factory
);
2629 orientation
= IDWriteTextLayout2_GetVerticalGlyphOrientation(layout2
);
2630 ok(orientation
== DWRITE_VERTICAL_GLYPH_ORIENTATION_DEFAULT
, "got %d\n", orientation
);
2632 hr
= IDWriteTextLayout2_SetVerticalGlyphOrientation(layout2
, DWRITE_VERTICAL_GLYPH_ORIENTATION_STACKED
+1);
2633 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
2635 IDWriteTextLayout2_Release(layout2
);
2636 IDWriteFactory_Release(factory
);
2639 static void test_fallback(void)
2641 static const WCHAR strW
[] = {'a','b','c','d',0};
2642 IDWriteFontFallback
*fallback
, *fallback2
;
2643 IDWriteTextLayout2
*layout2
;
2644 IDWriteTextFormat1
*format1
;
2645 IDWriteTextFormat
*format
;
2646 IDWriteTextLayout
*layout
;
2647 IDWriteFactory2
*factory2
;
2648 IDWriteFactory
*factory
;
2651 factory
= create_factory();
2653 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
2654 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
2655 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2657 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 1000.0, 1000.0, &layout
);
2658 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2659 IDWriteTextFormat_Release(format
);
2661 hr
= IDWriteTextLayout_QueryInterface(layout
, &IID_IDWriteTextLayout2
, (void**)&layout2
);
2662 IDWriteTextLayout_Release(layout
);
2665 win_skip("GetFontFallback() is not supported.\n");
2666 IDWriteFactory_Release(factory
);
2670 if (0) /* crashes on native */
2671 hr
= IDWriteTextLayout2_GetFontFallback(layout2
, NULL
);
2673 fallback
= (void*)0xdeadbeef;
2674 hr
= IDWriteTextLayout2_GetFontFallback(layout2
, &fallback
);
2675 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2676 ok(fallback
== NULL
, "got %p\n", fallback
);
2678 hr
= IDWriteTextLayout2_QueryInterface(layout2
, &IID_IDWriteTextFormat1
, (void**)&format1
);
2679 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2681 fallback
= (void*)0xdeadbeef;
2682 hr
= IDWriteTextFormat1_GetFontFallback(format1
, &fallback
);
2683 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2684 ok(fallback
== NULL
, "got %p\n", fallback
);
2686 hr
= IDWriteFactory_QueryInterface(factory
, &IID_IDWriteFactory2
, (void**)&factory2
);
2687 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2690 hr
= IDWriteFactory2_GetSystemFontFallback(factory2
, &fallback
);
2691 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2692 ok(fallback
!= NULL
, "got %p\n", fallback
);
2694 hr
= IDWriteTextFormat1_SetFontFallback(format1
, fallback
);
2695 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2697 fallback2
= (void*)0xdeadbeef;
2698 hr
= IDWriteTextLayout2_GetFontFallback(layout2
, &fallback2
);
2699 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2700 ok(fallback2
== fallback
, "got %p\n", fallback2
);
2702 hr
= IDWriteTextLayout2_SetFontFallback(layout2
, NULL
);
2703 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2705 fallback2
= (void*)0xdeadbeef;
2706 hr
= IDWriteTextFormat1_GetFontFallback(format1
, &fallback2
);
2707 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2708 ok(fallback2
== NULL
, "got %p\n", fallback2
);
2710 IDWriteFontFallback_Release(fallback
);
2711 IDWriteTextFormat1_Release(format1
);
2712 IDWriteTextLayout2_Release(layout2
);
2713 IDWriteFactory_Release(factory
);
2716 static void test_DetermineMinWidth(void)
2718 struct minwidth_test
{
2719 const WCHAR text
[10]; /* text to create a layout for */
2720 const WCHAR mintext
[10]; /* text that represents sequence of minimal width */
2721 } minwidth_tests
[] = {
2722 { {' ','a','b',' ',0}, {'a','b',0} },
2723 { {'a','\n',' ',' ',0}, {'a',0} },
2724 { {'a','\n',' ',' ','b',0}, {'b',0} },
2725 { {'a','b','c','\n',' ',' ','b',0}, {'a','b','c',0} },
2727 static const WCHAR strW
[] = {'a','b','c','d',0};
2728 DWRITE_CLUSTER_METRICS metrics
[10];
2729 IDWriteTextFormat
*format
;
2730 IDWriteTextLayout
*layout
;
2731 IDWriteFactory
*factory
;
2736 factory
= create_factory();
2738 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
2739 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
2740 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2742 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, lstrlenW(strW
), format
, 1000.0, 1000.0, &layout
);
2743 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2745 hr
= IDWriteTextLayout_DetermineMinWidth(layout
, NULL
);
2746 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
2747 IDWriteTextLayout_Release(layout
);
2750 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 0, format
, 100.0f
, 100.0f
, &layout
);
2751 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2754 hr
= IDWriteTextLayout_DetermineMinWidth(layout
, &minwidth
);
2755 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2756 ok(minwidth
== 0.0f
, "got %f\n", minwidth
);
2757 IDWriteTextLayout_Release(layout
);
2759 for (i
= 0; i
< ARRAY_SIZE(minwidth_tests
); i
++) {
2762 /* measure expected width */
2763 hr
= IDWriteFactory_CreateTextLayout(factory
, minwidth_tests
[i
].mintext
, lstrlenW(minwidth_tests
[i
].mintext
), format
, 1000.0f
, 1000.0f
, &layout
);
2764 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2766 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, metrics
, ARRAY_SIZE(metrics
), &count
);
2767 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2769 for (j
= 0; j
< count
; j
++)
2770 width
+= metrics
[j
].width
;
2772 IDWriteTextLayout_Release(layout
);
2774 hr
= IDWriteFactory_CreateTextLayout(factory
, minwidth_tests
[i
].text
, lstrlenW(minwidth_tests
[i
].text
), format
, 1000.0f
, 1000.0f
, &layout
);
2775 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2778 hr
= IDWriteTextLayout_DetermineMinWidth(layout
, &minwidth
);
2779 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2780 ok(minwidth
== width
, "test %u: expected width %f, got %f\n", i
, width
, minwidth
);
2782 IDWriteTextLayout_Release(layout
);
2785 IDWriteTextFormat_Release(format
);
2786 IDWriteFactory_Release(factory
);
2789 static void test_SetFontSize(void)
2791 static const WCHAR strW
[] = {'a','b','c','d',0};
2792 IDWriteTextFormat
*format
;
2793 IDWriteTextLayout
*layout
;
2794 IDWriteFactory
*factory
;
2795 DWRITE_TEXT_RANGE r
;
2799 factory
= create_factory();
2801 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
2802 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
2803 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2805 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 1000.0, 1000.0, &layout
);
2806 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2808 /* negative/zero size */
2809 r
.startPosition
= 1;
2811 hr
= IDWriteTextLayout_SetFontSize(layout
, -15.0, r
);
2812 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
2814 hr
= IDWriteTextLayout_SetFontSize(layout
, 0.0, r
);
2815 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
2817 r
.startPosition
= 1;
2820 hr
= IDWriteTextLayout_GetFontSize(layout
, 0, &size
, &r
);
2821 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2822 ok(r
.startPosition
== 0 && r
.length
== ~0u, "got %u, %u\n", r
.startPosition
, r
.length
);
2823 ok(size
== 10.0, "got %.2f\n", size
);
2825 r
.startPosition
= 1;
2827 hr
= IDWriteTextLayout_SetFontSize(layout
, 15.0, r
);
2828 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2830 /* zero length range */
2831 r
.startPosition
= 1;
2833 hr
= IDWriteTextLayout_SetFontSize(layout
, 123.0, r
);
2834 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2837 hr
= IDWriteTextLayout_GetFontSize(layout
, 1, &size
, &r
);
2838 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2839 ok(size
== 15.0, "got %.2f\n", size
);
2841 r
.startPosition
= 0;
2843 hr
= IDWriteTextLayout_SetFontSize(layout
, 15.0, r
);
2844 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2847 hr
= IDWriteTextLayout_GetFontSize(layout
, 1, &size
, &r
);
2848 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2849 ok(size
== 15.0, "got %.2f\n", size
);
2852 hr
= IDWriteTextLayout_GetFontSize(layout
, 0, &size
, &r
);
2853 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2854 ok(r
.startPosition
== 0 && r
.length
== 4, "got %u, %u\n", r
.startPosition
, r
.length
);
2855 ok(size
== 15.0, "got %.2f\n", size
);
2858 r
.startPosition
= r
.length
= 0;
2859 hr
= IDWriteTextLayout_GetFontSize(layout
, 20, &size
, &r
);
2860 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2861 ok(r
.startPosition
== 4 && r
.length
== ~0u-4, "got %u, %u\n", r
.startPosition
, r
.length
);
2862 ok(size
== 10.0, "got %.2f\n", size
);
2864 r
.startPosition
= 100;
2866 hr
= IDWriteTextLayout_SetFontSize(layout
, 25.0, r
);
2867 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2870 r
.startPosition
= r
.length
= 0;
2871 hr
= IDWriteTextLayout_GetFontSize(layout
, 100, &size
, &r
);
2872 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2873 ok(r
.startPosition
== 100 && r
.length
== 4, "got %u, %u\n", r
.startPosition
, r
.length
);
2874 ok(size
== 25.0, "got %.2f\n", size
);
2876 IDWriteTextLayout_Release(layout
);
2877 IDWriteTextFormat_Release(format
);
2878 IDWriteFactory_Release(factory
);
2881 static void test_SetFontFamilyName(void)
2883 static const WCHAR taHomaW
[] = {'T','a','H','o','m','a',0};
2884 static const WCHAR arialW
[] = {'A','r','i','a','l',0};
2885 static const WCHAR strW
[] = {'a','b','c','d',0};
2886 IDWriteTextFormat
*format
;
2887 IDWriteTextLayout
*layout
;
2888 IDWriteFactory
*factory
;
2889 DWRITE_TEXT_RANGE r
;
2893 factory
= create_factory();
2895 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
2896 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
2897 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2899 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 1000.0, 1000.0, &layout
);
2900 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2903 r
.startPosition
= 1;
2905 hr
= IDWriteTextLayout_SetFontFamilyName(layout
, NULL
, r
);
2906 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
2908 r
.startPosition
= 1;
2911 hr
= IDWriteTextLayout_GetFontFamilyName(layout
, 1, nameW
, ARRAY_SIZE(nameW
), &r
);
2912 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2913 ok(r
.startPosition
== 0 && r
.length
== ~0u, "got %u, %u\n", r
.startPosition
, r
.length
);
2915 /* set name only different in casing */
2916 r
.startPosition
= 1;
2918 hr
= IDWriteTextLayout_SetFontFamilyName(layout
, taHomaW
, r
);
2919 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2921 /* zero length range */
2922 r
.startPosition
= 1;
2924 hr
= IDWriteTextLayout_SetFontFamilyName(layout
, arialW
, r
);
2925 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2927 r
.startPosition
= 0;
2930 hr
= IDWriteTextLayout_GetFontFamilyName(layout
, 1, nameW
, ARRAY_SIZE(nameW
), &r
);
2931 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2932 ok(!lstrcmpW(nameW
, taHomaW
), "got %s\n", wine_dbgstr_w(nameW
));
2933 ok(r
.startPosition
== 1 && r
.length
== 1, "got %u, %u\n", r
.startPosition
, r
.length
);
2935 r
.startPosition
= 1;
2937 hr
= IDWriteTextLayout_SetFontFamilyName(layout
, arialW
, r
);
2938 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2940 r
.startPosition
= 1;
2942 hr
= IDWriteTextLayout_GetFontFamilyName(layout
, 1, nameW
, ARRAY_SIZE(nameW
), &r
);
2943 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2944 ok(r
.startPosition
== 1 && r
.length
== 1, "got %u, %u\n", r
.startPosition
, r
.length
);
2946 r
.startPosition
= 0;
2948 hr
= IDWriteTextLayout_SetFontFamilyName(layout
, arialW
, r
);
2949 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2952 hr
= IDWriteTextLayout_GetFontFamilyName(layout
, 1, nameW
, ARRAY_SIZE(nameW
), &r
);
2953 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2954 ok(r
.startPosition
== 0 && r
.length
== 4, "got %u, %u\n", r
.startPosition
, r
.length
);
2955 ok(!lstrcmpW(nameW
, arialW
), "got name %s\n", wine_dbgstr_w(nameW
));
2957 IDWriteTextLayout_Release(layout
);
2958 IDWriteTextFormat_Release(format
);
2959 IDWriteFactory_Release(factory
);
2962 static void test_SetFontStyle(void)
2964 static const WCHAR strW
[] = {'a','b','c','d',0};
2965 IDWriteTextFormat
*format
;
2966 IDWriteTextLayout
*layout
;
2967 IDWriteFactory
*factory
;
2968 DWRITE_FONT_STYLE style
;
2969 DWRITE_TEXT_RANGE r
;
2972 factory
= create_factory();
2974 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
2975 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
2976 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2978 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 1000.0, 1000.0, &layout
);
2979 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2981 /* invalid style value */
2982 r
.startPosition
= 1;
2984 hr
= IDWriteTextLayout_SetFontStyle(layout
, DWRITE_FONT_STYLE_ITALIC
+1, r
);
2985 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
2987 r
.startPosition
= 1;
2989 hr
= IDWriteTextLayout_GetFontStyle(layout
, 0, &style
, &r
);
2990 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2991 ok(r
.startPosition
== 0 && r
.length
== ~0u, "got %u, %u\n", r
.startPosition
, r
.length
);
2992 ok(style
== DWRITE_FONT_STYLE_NORMAL
, "got %d\n", style
);
2994 r
.startPosition
= 1;
2996 hr
= IDWriteTextLayout_SetFontStyle(layout
, DWRITE_FONT_STYLE_ITALIC
, r
);
2997 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2999 /* zero length range */
3000 r
.startPosition
= 1;
3002 hr
= IDWriteTextLayout_SetFontStyle(layout
, DWRITE_FONT_STYLE_NORMAL
, r
);
3003 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3005 style
= DWRITE_FONT_STYLE_NORMAL
;
3006 hr
= IDWriteTextLayout_GetFontStyle(layout
, 1, &style
, &r
);
3007 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3008 ok(style
== DWRITE_FONT_STYLE_ITALIC
, "got %d\n", style
);
3010 r
.startPosition
= 0;
3012 hr
= IDWriteTextLayout_SetFontStyle(layout
, DWRITE_FONT_STYLE_OBLIQUE
, r
);
3013 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3015 style
= DWRITE_FONT_STYLE_ITALIC
;
3016 hr
= IDWriteTextLayout_GetFontStyle(layout
, 1, &style
, &r
);
3017 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3018 ok(style
== DWRITE_FONT_STYLE_OBLIQUE
, "got %d\n", style
);
3020 style
= DWRITE_FONT_STYLE_ITALIC
;
3021 hr
= IDWriteTextLayout_GetFontStyle(layout
, 0, &style
, &r
);
3022 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3023 ok(r
.startPosition
== 0 && r
.length
== 4, "got %u, %u\n", r
.startPosition
, r
.length
);
3024 ok(style
== DWRITE_FONT_STYLE_OBLIQUE
, "got %d\n", style
);
3026 style
= DWRITE_FONT_STYLE_ITALIC
;
3027 r
.startPosition
= r
.length
= 0;
3028 hr
= IDWriteTextLayout_GetFontStyle(layout
, 20, &style
, &r
);
3029 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3030 ok(r
.startPosition
== 4 && r
.length
== ~0u-4, "got %u, %u\n", r
.startPosition
, r
.length
);
3031 ok(style
== DWRITE_FONT_STYLE_NORMAL
, "got %d\n", style
);
3033 r
.startPosition
= 100;
3035 hr
= IDWriteTextLayout_SetFontStyle(layout
, DWRITE_FONT_STYLE_OBLIQUE
, r
);
3036 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3038 style
= DWRITE_FONT_STYLE_NORMAL
;
3039 r
.startPosition
= r
.length
= 0;
3040 hr
= IDWriteTextLayout_GetFontStyle(layout
, 100, &style
, &r
);
3041 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3042 ok(r
.startPosition
== 100 && r
.length
== 4, "got %u, %u\n", r
.startPosition
, r
.length
);
3043 ok(style
== DWRITE_FONT_STYLE_OBLIQUE
, "got %d\n", style
);
3045 IDWriteTextLayout_Release(layout
);
3046 IDWriteTextFormat_Release(format
);
3047 IDWriteFactory_Release(factory
);
3050 static void test_SetFontStretch(void)
3052 static const WCHAR strW
[] = {'a','b','c','d',0};
3053 DWRITE_FONT_STRETCH stretch
;
3054 IDWriteTextFormat
*format
;
3055 IDWriteTextLayout
*layout
;
3056 IDWriteFactory
*factory
;
3057 DWRITE_TEXT_RANGE r
;
3060 factory
= create_factory();
3062 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
3063 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
3064 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3066 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 1000.0, 1000.0, &layout
);
3067 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3069 /* invalid stretch value */
3070 r
.startPosition
= 1;
3072 hr
= IDWriteTextLayout_SetFontStretch(layout
, DWRITE_FONT_STRETCH_ULTRA_EXPANDED
+1, r
);
3073 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
3075 r
.startPosition
= 1;
3077 stretch
= DWRITE_FONT_STRETCH_UNDEFINED
;
3078 hr
= IDWriteTextLayout_GetFontStretch(layout
, 0, &stretch
, &r
);
3079 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3080 ok(r
.startPosition
== 0 && r
.length
== ~0u, "got %u, %u\n", r
.startPosition
, r
.length
);
3081 ok(stretch
== DWRITE_FONT_STRETCH_NORMAL
, "got %d\n", stretch
);
3083 r
.startPosition
= 1;
3085 hr
= IDWriteTextLayout_SetFontStretch(layout
, DWRITE_FONT_STRETCH_CONDENSED
, r
);
3086 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3088 /* zero length range */
3089 r
.startPosition
= 1;
3091 hr
= IDWriteTextLayout_SetFontStretch(layout
, DWRITE_FONT_STRETCH_NORMAL
, r
);
3092 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3094 stretch
= DWRITE_FONT_STRETCH_UNDEFINED
;
3095 hr
= IDWriteTextLayout_GetFontStretch(layout
, 1, &stretch
, &r
);
3096 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3097 ok(stretch
== DWRITE_FONT_STRETCH_CONDENSED
, "got %d\n", stretch
);
3099 r
.startPosition
= 0;
3101 hr
= IDWriteTextLayout_SetFontStretch(layout
, DWRITE_FONT_STRETCH_EXPANDED
, r
);
3102 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3104 stretch
= DWRITE_FONT_STRETCH_UNDEFINED
;
3105 hr
= IDWriteTextLayout_GetFontStretch(layout
, 1, &stretch
, &r
);
3106 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3107 ok(stretch
== DWRITE_FONT_STRETCH_EXPANDED
, "got %d\n", stretch
);
3109 stretch
= DWRITE_FONT_STRETCH_UNDEFINED
;
3110 hr
= IDWriteTextLayout_GetFontStretch(layout
, 0, &stretch
, &r
);
3111 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3112 ok(r
.startPosition
== 0 && r
.length
== 4, "got %u, %u\n", r
.startPosition
, r
.length
);
3113 ok(stretch
== DWRITE_FONT_STRETCH_EXPANDED
, "got %d\n", stretch
);
3115 stretch
= DWRITE_FONT_STRETCH_UNDEFINED
;
3116 r
.startPosition
= r
.length
= 0;
3117 hr
= IDWriteTextLayout_GetFontStretch(layout
, 20, &stretch
, &r
);
3118 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3119 ok(r
.startPosition
== 4 && r
.length
== ~0u-4, "got %u, %u\n", r
.startPosition
, r
.length
);
3120 ok(stretch
== DWRITE_FONT_STRETCH_NORMAL
, "got %d\n", stretch
);
3122 r
.startPosition
= 100;
3124 hr
= IDWriteTextLayout_SetFontStretch(layout
, DWRITE_FONT_STRETCH_EXPANDED
, r
);
3125 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3127 stretch
= DWRITE_FONT_STRETCH_UNDEFINED
;
3128 r
.startPosition
= r
.length
= 0;
3129 hr
= IDWriteTextLayout_GetFontStretch(layout
, 100, &stretch
, &r
);
3130 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3131 ok(r
.startPosition
== 100 && r
.length
== 4, "got %u, %u\n", r
.startPosition
, r
.length
);
3132 ok(stretch
== DWRITE_FONT_STRETCH_EXPANDED
, "got %d\n", stretch
);
3134 /* trying to set undefined value */
3135 r
.startPosition
= 0;
3137 hr
= IDWriteTextLayout_SetFontStretch(layout
, DWRITE_FONT_STRETCH_UNDEFINED
, r
);
3138 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
3140 IDWriteTextLayout_Release(layout
);
3141 IDWriteTextFormat_Release(format
);
3142 IDWriteFactory_Release(factory
);
3145 static void test_SetStrikethrough(void)
3147 static const WCHAR strW
[] = {'a','b','c','d',0};
3148 IDWriteTextFormat
*format
;
3149 IDWriteTextLayout
*layout
;
3150 IDWriteFactory
*factory
;
3151 DWRITE_TEXT_RANGE r
;
3155 factory
= create_factory();
3157 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
3158 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
3159 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3161 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 1000.0, 1000.0, &layout
);
3162 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3164 r
.startPosition
= 1;
3167 hr
= IDWriteTextLayout_GetStrikethrough(layout
, 0, &value
, &r
);
3168 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3169 ok(r
.startPosition
== 0 && r
.length
== ~0u, "got %u, %u\n", r
.startPosition
, r
.length
);
3170 ok(value
== FALSE
, "got %d\n", value
);
3172 r
.startPosition
= 1;
3174 hr
= IDWriteTextLayout_SetStrikethrough(layout
, TRUE
, r
);
3175 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3178 hr
= IDWriteTextLayout_GetStrikethrough(layout
, 1, &value
, &r
);
3179 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3180 ok(value
== TRUE
, "got %d\n", value
);
3181 ok(r
.startPosition
== 1 && r
.length
== 1, "got %u, %u\n", r
.startPosition
, r
.length
);
3184 r
.startPosition
= r
.length
= 0;
3185 hr
= IDWriteTextLayout_GetStrikethrough(layout
, 20, &value
, &r
);
3186 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3187 ok(r
.startPosition
== 2 && r
.length
== ~0u-2, "got %u, %u\n", r
.startPosition
, r
.length
);
3188 ok(value
== FALSE
, "got %d\n", value
);
3190 r
.startPosition
= 100;
3192 hr
= IDWriteTextLayout_SetStrikethrough(layout
, TRUE
, r
);
3193 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3196 r
.startPosition
= r
.length
= 0;
3197 hr
= IDWriteTextLayout_GetStrikethrough(layout
, 100, &value
, &r
);
3198 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3199 ok(r
.startPosition
== 100 && r
.length
== 4, "got %u, %u\n", r
.startPosition
, r
.length
);
3200 ok(value
== TRUE
, "got %d\n", value
);
3202 IDWriteTextLayout_Release(layout
);
3203 IDWriteTextFormat_Release(format
);
3204 IDWriteFactory_Release(factory
);
3207 static void test_GetMetrics(void)
3209 static const WCHAR str2W
[] = {0x2066,')',')',0x661,'(',0x627,')',0};
3210 static const WCHAR strW
[] = {'a','b','c','d',0};
3211 static const WCHAR str3W
[] = {'a',0};
3212 DWRITE_CLUSTER_METRICS clusters
[4];
3213 DWRITE_TEXT_METRICS metrics
;
3214 IDWriteTextFormat
*format
;
3215 IDWriteTextLayout
*layout
;
3216 IDWriteFactory
*factory
;
3221 factory
= create_factory();
3223 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
3224 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
3225 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3227 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 500.0, 1000.0, &layout
);
3228 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3231 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, clusters
, 4, &count
);
3232 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3233 ok(count
== 4, "got %u\n", count
);
3234 for (i
= 0, width
= 0.0; i
< count
; i
++)
3235 width
+= clusters
[i
].width
;
3237 memset(&metrics
, 0xcc, sizeof(metrics
));
3238 hr
= IDWriteTextLayout_GetMetrics(layout
, &metrics
);
3239 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3240 ok(metrics
.left
== 0.0, "got %.2f\n", metrics
.left
);
3241 ok(metrics
.top
== 0.0, "got %.2f\n", metrics
.top
);
3242 ok(metrics
.width
== width
, "got %.2f, expected %.2f\n", metrics
.width
, width
);
3243 ok(metrics
.widthIncludingTrailingWhitespace
== width
, "got %.2f, expected %.2f\n",
3244 metrics
.widthIncludingTrailingWhitespace
, width
);
3245 ok(metrics
.height
> 0.0, "got %.2f\n", metrics
.height
);
3246 ok(metrics
.layoutWidth
== 500.0, "got %.2f\n", metrics
.layoutWidth
);
3247 ok(metrics
.layoutHeight
== 1000.0, "got %.2f\n", metrics
.layoutHeight
);
3248 ok(metrics
.maxBidiReorderingDepth
== 1, "got %u\n", metrics
.maxBidiReorderingDepth
);
3249 ok(metrics
.lineCount
== 1, "got %u\n", metrics
.lineCount
);
3251 IDWriteTextLayout_Release(layout
);
3253 /* a string with more complex bidi sequence */
3254 hr
= IDWriteFactory_CreateTextLayout(factory
, str2W
, 7, format
, 500.0, 1000.0, &layout
);
3255 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3257 memset(&metrics
, 0xcc, sizeof(metrics
));
3258 metrics
.maxBidiReorderingDepth
= 0;
3259 hr
= IDWriteTextLayout_GetMetrics(layout
, &metrics
);
3260 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3261 ok(metrics
.left
== 0.0, "got %.2f\n", metrics
.left
);
3262 ok(metrics
.top
== 0.0, "got %.2f\n", metrics
.top
);
3263 ok(metrics
.width
> 0.0, "got %.2f\n", metrics
.width
);
3264 ok(metrics
.widthIncludingTrailingWhitespace
> 0.0, "got %.2f\n", metrics
.widthIncludingTrailingWhitespace
);
3265 ok(metrics
.height
> 0.0, "got %.2f\n", metrics
.height
);
3266 ok(metrics
.layoutWidth
== 500.0, "got %.2f\n", metrics
.layoutWidth
);
3267 ok(metrics
.layoutHeight
== 1000.0, "got %.2f\n", metrics
.layoutHeight
);
3269 ok(metrics
.maxBidiReorderingDepth
> 1, "got %u\n", metrics
.maxBidiReorderingDepth
);
3270 ok(metrics
.lineCount
== 1, "got %u\n", metrics
.lineCount
);
3272 IDWriteTextLayout_Release(layout
);
3274 /* single cluster layout */
3275 hr
= IDWriteFactory_CreateTextLayout(factory
, str3W
, 1, format
, 500.0, 1000.0, &layout
);
3276 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3279 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, clusters
, 1, &count
);
3280 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3281 ok(count
== 1, "got %u\n", count
);
3283 memset(&metrics
, 0xcc, sizeof(metrics
));
3284 hr
= IDWriteTextLayout_GetMetrics(layout
, &metrics
);
3285 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3286 ok(metrics
.left
== 0.0, "got %.2f\n", metrics
.left
);
3287 ok(metrics
.top
== 0.0, "got %.2f\n", metrics
.top
);
3288 ok(metrics
.width
== clusters
[0].width
, "got %.2f, expected %.2f\n", metrics
.width
, clusters
[0].width
);
3289 ok(metrics
.widthIncludingTrailingWhitespace
== clusters
[0].width
, "got %.2f\n", metrics
.widthIncludingTrailingWhitespace
);
3290 ok(metrics
.height
> 0.0, "got %.2f\n", metrics
.height
);
3291 ok(metrics
.layoutWidth
== 500.0, "got %.2f\n", metrics
.layoutWidth
);
3292 ok(metrics
.layoutHeight
== 1000.0, "got %.2f\n", metrics
.layoutHeight
);
3293 ok(metrics
.maxBidiReorderingDepth
== 1, "got %u\n", metrics
.maxBidiReorderingDepth
);
3294 ok(metrics
.lineCount
== 1, "got %u\n", metrics
.lineCount
);
3295 IDWriteTextLayout_Release(layout
);
3297 IDWriteTextFormat_Release(format
);
3298 IDWriteFactory_Release(factory
);
3301 static void test_SetFlowDirection(void)
3303 static const WCHAR strW
[] = {'a','b','c','d',0};
3304 DWRITE_READING_DIRECTION reading
;
3305 DWRITE_FLOW_DIRECTION flow
;
3306 IDWriteTextFormat
*format
;
3307 IDWriteTextLayout
*layout
;
3308 IDWriteFactory
*factory
;
3311 factory
= create_factory();
3313 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
3314 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
3315 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3317 flow
= IDWriteTextFormat_GetFlowDirection(format
);
3318 ok(flow
== DWRITE_FLOW_DIRECTION_TOP_TO_BOTTOM
, "got %d\n", flow
);
3320 reading
= IDWriteTextFormat_GetReadingDirection(format
);
3321 ok(reading
== DWRITE_READING_DIRECTION_LEFT_TO_RIGHT
, "got %d\n", reading
);
3323 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 500.0, 1000.0, &layout
);
3324 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3325 IDWriteTextLayout_Release(layout
);
3327 hr
= IDWriteTextFormat_SetFlowDirection(format
, DWRITE_FLOW_DIRECTION_LEFT_TO_RIGHT
);
3328 ok(hr
== S_OK
|| broken(hr
== E_INVALIDARG
) /* vista,win7 */, "got 0x%08x\n", hr
);
3330 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 500.0, 1000.0, &layout
);
3331 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3332 IDWriteTextLayout_Release(layout
);
3334 hr
= IDWriteTextFormat_SetReadingDirection(format
, DWRITE_READING_DIRECTION_TOP_TO_BOTTOM
);
3335 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3337 hr
= IDWriteTextFormat_SetFlowDirection(format
, DWRITE_FLOW_DIRECTION_TOP_TO_BOTTOM
);
3338 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3340 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 500.0, 1000.0, &layout
);
3341 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3342 IDWriteTextLayout_Release(layout
);
3345 win_skip("DWRITE_FLOW_DIRECTION_LEFT_TO_RIGHT is not supported\n");
3347 IDWriteTextFormat_Release(format
);
3348 IDWriteFactory_Release(factory
);
3351 static const struct drawcall_entry draweffect_seq
[] = {
3352 { DRAW_GLYPHRUN
|DRAW_EFFECT
, {'a','e',0x0300,0}, {'e','n','-','u','s',0}, 2 },
3353 { DRAW_GLYPHRUN
, {'d',0}, {'e','n','-','u','s',0}, 1 },
3357 static const struct drawcall_entry draweffect2_seq
[] = {
3358 { DRAW_GLYPHRUN
|DRAW_EFFECT
, {'a','e',0}, {'e','n','-','u','s',0}, 2 },
3359 { DRAW_GLYPHRUN
, {'c','d',0}, {'e','n','-','u','s',0}, 2 },
3363 static const struct drawcall_entry draweffect3_seq
[] = {
3364 { DRAW_INLINE
|DRAW_EFFECT
},
3368 static const struct drawcall_entry draweffect4_seq
[] = {
3373 static void test_SetDrawingEffect(void)
3375 static const WCHAR strW
[] = {'a','e',0x0300,'d',0}; /* accent grave */
3376 static const WCHAR str2W
[] = {'a','e','c','d',0};
3377 IDWriteInlineObject
*sign
;
3378 IDWriteTextFormat
*format
;
3379 IDWriteTextLayout
*layout
;
3380 IDWriteFactory
*factory
;
3381 IUnknown
*unk
, *effect
;
3382 DWRITE_TEXT_RANGE r
;
3386 factory
= create_factory();
3388 effect
= create_test_effect();
3390 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
3391 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
3392 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3394 /* string with combining mark */
3395 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 500.0, 1000.0, &layout
);
3396 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3398 /* set effect past the end of text */
3399 r
.startPosition
= 100;
3401 hr
= IDWriteTextLayout_SetDrawingEffect(layout
, effect
, r
);
3402 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3404 r
.startPosition
= r
.length
= 0;
3405 hr
= IDWriteTextLayout_GetDrawingEffect(layout
, 101, &unk
, &r
);
3406 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3407 ok(r
.startPosition
== 100 && r
.length
== 10, "got %u, %u\n", r
.startPosition
, r
.length
);
3408 IUnknown_Release(unk
);
3410 r
.startPosition
= r
.length
= 0;
3411 unk
= (void*)0xdeadbeef;
3412 hr
= IDWriteTextLayout_GetDrawingEffect(layout
, 1000, &unk
, &r
);
3413 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3414 ok(r
.startPosition
== 110 && r
.length
== ~0u-110, "got %u, %u\n", r
.startPosition
, r
.length
);
3415 ok(unk
== NULL
, "got %p\n", unk
);
3417 /* effect is applied to clusters, not individual text positions */
3418 r
.startPosition
= 0;
3420 hr
= IDWriteTextLayout_SetDrawingEffect(layout
, effect
, r
);
3421 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3423 flush_sequence(sequences
, RENDERER_ID
);
3424 hr
= IDWriteTextLayout_Draw(layout
, NULL
, &testrenderer
, 0.0, 0.0);
3425 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3426 ok_sequence(sequences
, RENDERER_ID
, draweffect_seq
, "effect draw test", TRUE
);
3427 IDWriteTextLayout_Release(layout
);
3430 hr
= IDWriteFactory_CreateTextLayout(factory
, str2W
, 4, format
, 500.0, 1000.0, &layout
);
3431 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3433 r
.startPosition
= 0;
3435 hr
= IDWriteTextLayout_SetDrawingEffect(layout
, effect
, r
);
3436 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3438 flush_sequence(sequences
, RENDERER_ID
);
3439 hr
= IDWriteTextLayout_Draw(layout
, NULL
, &testrenderer
, 0.0, 0.0);
3440 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3441 ok_sequence(sequences
, RENDERER_ID
, draweffect2_seq
, "effect draw test 2", FALSE
);
3442 IDWriteTextLayout_Release(layout
);
3444 /* Inline object - effect set for same range */
3445 hr
= IDWriteFactory_CreateEllipsisTrimmingSign(factory
, format
, &sign
);
3446 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3448 hr
= IDWriteFactory_CreateTextLayout(factory
, str2W
, 4, format
, 500.0, 1000.0, &layout
);
3449 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3451 r
.startPosition
= 0;
3453 hr
= IDWriteTextLayout_SetInlineObject(layout
, sign
, r
);
3454 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3456 hr
= IDWriteTextLayout_SetDrawingEffect(layout
, effect
, r
);
3457 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3459 flush_sequence(sequences
, RENDERER_ID
);
3460 hr
= IDWriteTextLayout_Draw(layout
, NULL
, &testrenderer
, 0.0, 0.0);
3461 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3462 ok_sequence(sequences
, RENDERER_ID
, draweffect3_seq
, "effect draw test 3", FALSE
);
3464 /* now set effect somewhere inside a range replaced by inline object */
3465 hr
= IDWriteTextLayout_SetDrawingEffect(layout
, NULL
, r
);
3466 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3468 r
.startPosition
= 1;
3470 hr
= IDWriteTextLayout_SetDrawingEffect(layout
, effect
, r
);
3471 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3473 /* no effect is reported in this case */
3474 flush_sequence(sequences
, RENDERER_ID
);
3475 hr
= IDWriteTextLayout_Draw(layout
, NULL
, &testrenderer
, 0.0, 0.0);
3476 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3477 ok_sequence(sequences
, RENDERER_ID
, draweffect4_seq
, "effect draw test 4", FALSE
);
3479 r
.startPosition
= 0;
3481 hr
= IDWriteTextLayout_SetDrawingEffect(layout
, NULL
, r
);
3482 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3484 r
.startPosition
= 0;
3486 hr
= IDWriteTextLayout_SetDrawingEffect(layout
, effect
, r
);
3487 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3489 /* first range position is all that matters for inline ranges */
3490 flush_sequence(sequences
, RENDERER_ID
);
3491 hr
= IDWriteTextLayout_Draw(layout
, NULL
, &testrenderer
, 0.0, 0.0);
3492 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3493 ok_sequence(sequences
, RENDERER_ID
, draweffect3_seq
, "effect draw test 5", FALSE
);
3495 IDWriteTextLayout_Release(layout
);
3497 ref
= IUnknown_Release(effect
);
3498 ok(ref
== 0, "Unexpected effect refcount %u\n", ref
);
3499 IDWriteInlineObject_Release(sign
);
3500 IDWriteTextFormat_Release(format
);
3501 IDWriteFactory_Release(factory
);
3504 static BOOL
get_enus_string(IDWriteLocalizedStrings
*strings
, WCHAR
*buff
, UINT32 size
)
3507 BOOL exists
= FALSE
;
3510 hr
= IDWriteLocalizedStrings_FindLocaleName(strings
, enusW
, &index
, &exists
);
3511 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3514 hr
= IDWriteLocalizedStrings_GetString(strings
, index
, buff
, size
);
3515 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3523 static void test_GetLineMetrics(void)
3525 static const WCHAR str3W
[] = {'a','\r','b','\n','c','\n','\r','d','\r','\n',0};
3526 static const WCHAR strW
[] = {'a','b','c','d',' ',0};
3527 static const WCHAR str2W
[] = {'a','b','\r','c','d',0};
3528 static const WCHAR str4W
[] = {'a','\r',0};
3529 static const WCHAR emptyW
[] = {0};
3530 IDWriteFontCollection
*syscollection
;
3531 DWRITE_FONT_METRICS fontmetrics
;
3532 DWRITE_LINE_METRICS metrics
[6];
3533 UINT32 count
, i
, familycount
;
3534 IDWriteTextFormat
*format
;
3535 IDWriteTextLayout
*layout
;
3536 IDWriteFontFace
*fontface
;
3537 IDWriteFactory
*factory
;
3538 DWRITE_TEXT_RANGE range
;
3542 factory
= create_factory();
3544 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
3545 DWRITE_FONT_STRETCH_NORMAL
, 2048.0, enusW
, &format
);
3546 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3548 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 5, format
, 30000.0, 1000.0, &layout
);
3549 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3552 hr
= IDWriteTextLayout_GetLineMetrics(layout
, metrics
, 0, &count
);
3553 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
3554 ok(count
== 1, "got count %u\n", count
);
3556 memset(metrics
, 0, sizeof(metrics
));
3557 hr
= IDWriteTextLayout_GetLineMetrics(layout
, metrics
, 1, &count
);
3558 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3559 ok(metrics
[0].length
== 5, "got %u\n", metrics
[0].length
);
3560 ok(metrics
[0].trailingWhitespaceLength
== 1, "got %u\n", metrics
[0].trailingWhitespaceLength
);
3562 ok(metrics
[0].newlineLength
== 0, "got %u\n", metrics
[0].newlineLength
);
3563 ok(metrics
[0].isTrimmed
== FALSE
, "got %d\n", metrics
[0].isTrimmed
);
3565 IDWriteTextLayout_Release(layout
);
3566 IDWriteTextFormat_Release(format
);
3568 /* Test line height and baseline calculation */
3569 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &syscollection
, FALSE
);
3570 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3571 familycount
= IDWriteFontCollection_GetFontFamilyCount(syscollection
);
3573 for (i
= 0; i
< familycount
; i
++) {
3574 IDWriteLocalizedStrings
*names
;
3575 IDWriteFontFamily
*family
;
3582 hr
= IDWriteFontCollection_GetFontFamily(syscollection
, i
, &family
);
3583 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3585 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STRETCH_NORMAL
,
3586 DWRITE_FONT_STYLE_NORMAL
, &font
);
3587 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3589 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
3590 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3592 hr
= IDWriteFontFamily_GetFamilyNames(family
, &names
);
3593 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3595 if (!(exists
= get_enus_string(names
, nameW
, ARRAY_SIZE(nameW
)))) {
3596 IDWriteLocalFontFileLoader
*localloader
;
3597 IDWriteFontFileLoader
*loader
;
3598 IDWriteFontFile
*file
;
3604 hr
= IDWriteFontFace_GetFiles(fontface
, &count
, &file
);
3605 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3607 hr
= IDWriteFontFile_GetLoader(file
, &loader
);
3608 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3610 hr
= IDWriteFontFileLoader_QueryInterface(loader
, &IID_IDWriteLocalFontFileLoader
, (void**)&localloader
);
3611 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3612 IDWriteFontFileLoader_Release(loader
);
3614 hr
= IDWriteFontFile_GetReferenceKey(file
, &key
, &keysize
);
3615 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3617 hr
= IDWriteLocalFontFileLoader_GetFilePathFromKey(localloader
, key
, keysize
, nameW
, ARRAY_SIZE(nameW
));
3618 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3620 skip("Failed to get English family name, font file %s\n", wine_dbgstr_w(nameW
));
3622 IDWriteLocalFontFileLoader_Release(localloader
);
3623 IDWriteFontFile_Release(file
);
3626 IDWriteLocalizedStrings_Release(names
);
3627 IDWriteFont_Release(font
);
3632 IDWriteFontFace_GetMetrics(fontface
, &fontmetrics
);
3633 hr
= IDWriteFactory_CreateTextFormat(factory
, nameW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
3634 DWRITE_FONT_STRETCH_NORMAL
, fontmetrics
.designUnitsPerEm
, enusW
, &format
);
3635 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3637 hr
= IDWriteFactory_CreateTextLayout(factory
, emptyW
, 1, format
, 30000.0f
, 100.0f
, &layout
);
3638 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3640 memset(metrics
, 0, sizeof(metrics
));
3642 hr
= IDWriteTextLayout_GetLineMetrics(layout
, metrics
, ARRAY_SIZE(metrics
), &count
);
3643 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3644 ok(count
== 1, "got %u\n", count
);
3646 ok(metrics
[0].baseline
== fontmetrics
.ascent
+ fontmetrics
.lineGap
, "%s: got %.2f, expected %d, "
3647 "linegap %d\n", wine_dbgstr_w(nameW
), metrics
[0].baseline
, fontmetrics
.ascent
+ fontmetrics
.lineGap
,
3648 fontmetrics
.lineGap
);
3649 ok(metrics
[0].height
== fontmetrics
.ascent
+ fontmetrics
.descent
+ fontmetrics
.lineGap
,
3650 "%s: got %.2f, expected %d, linegap %d\n", wine_dbgstr_w(nameW
), metrics
[0].height
,
3651 fontmetrics
.ascent
+ fontmetrics
.descent
+ fontmetrics
.lineGap
, fontmetrics
.lineGap
);
3655 IDWriteTextLayout_Release(layout
);
3657 IDWriteTextFormat_Release(format
);
3658 IDWriteFontFace_Release(fontface
);
3659 IDWriteFontFamily_Release(family
);
3661 IDWriteFontCollection_Release(syscollection
);
3663 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
3664 DWRITE_FONT_STRETCH_NORMAL
, 2048.0f
, enusW
, &format
);
3665 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3667 fontface
= get_fontface_from_format(format
);
3668 ok(fontface
!= NULL
, "got %p\n", fontface
);
3671 hr
= IDWriteFactory_CreateTextLayout(factory
, str2W
, 5, format
, 10000.0, 1000.0, &layout
);
3672 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3674 memset(metrics
, 0, sizeof(metrics
));
3676 hr
= IDWriteTextLayout_GetLineMetrics(layout
, metrics
, ARRAY_SIZE(metrics
), &count
);
3677 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3678 ok(count
== 2, "got %u\n", count
);
3679 /* baseline is relative to a line, and is not accumulated */
3680 ok(metrics
[0].baseline
== metrics
[1].baseline
, "got %.2f, %.2f\n", metrics
[0].baseline
,
3681 metrics
[1].baseline
);
3683 IDWriteTextLayout_Release(layout
);
3684 IDWriteTextFormat_Release(format
);
3687 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
3688 DWRITE_FONT_STRETCH_NORMAL
, 12.0, enusW
, &format
);
3689 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3691 hr
= IDWriteFactory_CreateTextLayout(factory
, str3W
, 10, format
, 100.0, 300.0, &layout
);
3692 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3694 memset(metrics
, 0xcc, sizeof(metrics
));
3696 hr
= IDWriteTextLayout_GetLineMetrics(layout
, metrics
, ARRAY_SIZE(metrics
), &count
);
3697 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3698 ok(count
== 6, "got %u\n", count
);
3700 ok(metrics
[0].length
== 2, "got %u\n", metrics
[0].length
);
3701 ok(metrics
[1].length
== 2, "got %u\n", metrics
[1].length
);
3702 ok(metrics
[2].length
== 2, "got %u\n", metrics
[2].length
);
3703 ok(metrics
[3].length
== 1, "got %u\n", metrics
[3].length
);
3704 ok(metrics
[4].length
== 3, "got %u\n", metrics
[4].length
);
3705 ok(metrics
[5].length
== 0, "got %u\n", metrics
[5].length
);
3707 ok(metrics
[0].newlineLength
== 1, "got %u\n", metrics
[0].newlineLength
);
3708 ok(metrics
[1].newlineLength
== 1, "got %u\n", metrics
[1].newlineLength
);
3709 ok(metrics
[2].newlineLength
== 1, "got %u\n", metrics
[2].newlineLength
);
3710 ok(metrics
[3].newlineLength
== 1, "got %u\n", metrics
[3].newlineLength
);
3711 ok(metrics
[4].newlineLength
== 2, "got %u\n", metrics
[4].newlineLength
);
3712 ok(metrics
[5].newlineLength
== 0, "got %u\n", metrics
[5].newlineLength
);
3714 ok(metrics
[0].trailingWhitespaceLength
== 1, "got %u\n", metrics
[0].newlineLength
);
3715 ok(metrics
[1].trailingWhitespaceLength
== 1, "got %u\n", metrics
[1].newlineLength
);
3716 ok(metrics
[2].trailingWhitespaceLength
== 1, "got %u\n", metrics
[2].newlineLength
);
3717 ok(metrics
[3].trailingWhitespaceLength
== 1, "got %u\n", metrics
[3].newlineLength
);
3718 ok(metrics
[4].trailingWhitespaceLength
== 2, "got %u\n", metrics
[4].newlineLength
);
3719 ok(metrics
[5].trailingWhitespaceLength
== 0, "got %u\n", metrics
[5].newlineLength
);
3721 IDWriteTextLayout_Release(layout
);
3723 /* empty text layout */
3724 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 0, format
, 100.0f
, 300.0f
, &layout
);
3725 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3728 memset(metrics
, 0, sizeof(metrics
));
3729 hr
= IDWriteTextLayout_GetLineMetrics(layout
, metrics
, 1, &count
);
3730 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3731 ok(count
== 1, "got %u\n", count
);
3732 ok(metrics
[0].length
== 0, "got %u\n", metrics
[0].length
);
3733 ok(metrics
[0].trailingWhitespaceLength
== 0, "got %u\n", metrics
[0].trailingWhitespaceLength
);
3734 ok(metrics
[0].newlineLength
== 0, "got %u\n", metrics
[0].newlineLength
);
3735 ok(metrics
[0].height
> 0.0f
, "got %f\n", metrics
[0].height
);
3736 ok(metrics
[0].baseline
> 0.0f
, "got %f\n", metrics
[0].baseline
);
3737 ok(!metrics
[0].isTrimmed
, "got %d\n", metrics
[0].isTrimmed
);
3739 /* change font size at first position, see if metrics changed */
3740 range
.startPosition
= 0;
3742 hr
= IDWriteTextLayout_SetFontSize(layout
, 80.0f
, range
);
3743 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3746 hr
= IDWriteTextLayout_GetLineMetrics(layout
, metrics
+ 1, 1, &count
);
3747 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3748 ok(count
== 1, "got %u\n", count
);
3749 ok(metrics
[1].height
> metrics
[0].height
, "got %f\n", metrics
[1].height
);
3750 ok(metrics
[1].baseline
> metrics
[0].baseline
, "got %f\n", metrics
[1].baseline
);
3752 /* revert font size back to format value, set different size for position 1 */
3753 hr
= IDWriteTextLayout_SetFontSize(layout
, 12.0f
, range
);
3754 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3756 range
.startPosition
= 1;
3758 hr
= IDWriteTextLayout_SetFontSize(layout
, 80.0f
, range
);
3759 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3761 memset(metrics
+ 1, 0, sizeof(*metrics
));
3763 hr
= IDWriteTextLayout_GetLineMetrics(layout
, metrics
+ 1, 1, &count
);
3764 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3765 ok(count
== 1, "got %u\n", count
);
3766 ok(metrics
[1].height
== metrics
[0].height
, "got %f\n", metrics
[1].height
);
3767 ok(metrics
[1].baseline
== metrics
[0].baseline
, "got %f\n", metrics
[1].baseline
);
3769 IDWriteTextLayout_Release(layout
);
3772 hr
= IDWriteFactory_CreateTextLayout(factory
, str4W
, 2, format
, 100.0f
, 300.0f
, &layout
);
3773 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3776 memset(metrics
, 0, sizeof(metrics
));
3777 hr
= IDWriteTextLayout_GetLineMetrics(layout
, metrics
, ARRAY_SIZE(metrics
), &count
);
3778 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3779 ok(count
== 2, "got %u\n", count
);
3780 ok(metrics
[0].length
== 2, "got %u\n", metrics
[0].length
);
3781 ok(metrics
[0].newlineLength
== 1, "got %u\n", metrics
[0].newlineLength
);
3782 ok(metrics
[0].height
> 0.0f
, "got %f\n", metrics
[0].height
);
3783 ok(metrics
[0].baseline
> 0.0f
, "got %f\n", metrics
[0].baseline
);
3784 ok(metrics
[1].length
== 0, "got %u\n", metrics
[1].length
);
3785 ok(metrics
[1].newlineLength
== 0, "got %u\n", metrics
[1].newlineLength
);
3786 ok(metrics
[1].height
> 0.0f
, "got %f\n", metrics
[1].height
);
3787 ok(metrics
[1].baseline
> 0.0f
, "got %f\n", metrics
[1].baseline
);
3789 range
.startPosition
= 1;
3791 hr
= IDWriteTextLayout_SetFontSize(layout
, 80.0f
, range
);
3792 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3794 hr
= IDWriteTextLayout_GetLineMetrics(layout
, metrics
+ 2, 2, &count
);
3795 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3796 ok(count
== 2, "got %u\n", count
);
3797 ok(metrics
[3].height
> metrics
[1].height
, "got %f, old %f\n", metrics
[3].height
, metrics
[1].height
);
3798 ok(metrics
[3].baseline
> metrics
[1].baseline
, "got %f, old %f\n", metrics
[3].baseline
, metrics
[1].baseline
);
3800 /* revert to original format */
3801 hr
= IDWriteTextLayout_SetFontSize(layout
, 12.0f
, range
);
3802 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3803 hr
= IDWriteTextLayout_GetLineMetrics(layout
, metrics
+ 2, 2, &count
);
3804 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3805 ok(count
== 2, "got %u\n", count
);
3806 ok(metrics
[3].height
== metrics
[1].height
, "got %f, old %f\n", metrics
[3].height
, metrics
[1].height
);
3807 ok(metrics
[3].baseline
== metrics
[1].baseline
, "got %f, old %f\n", metrics
[3].baseline
, metrics
[1].baseline
);
3809 /* Switch to uniform spacing */
3810 hr
= IDWriteTextLayout_SetLineSpacing(layout
, DWRITE_LINE_SPACING_METHOD_UNIFORM
, 456.0f
, 123.0f
);
3811 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3813 hr
= IDWriteTextLayout_GetLineMetrics(layout
, metrics
, ARRAY_SIZE(metrics
), &count
);
3814 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3815 ok(count
== 2, "got %u\n", count
);
3817 for (i
= 0; i
< count
; i
++) {
3818 ok(metrics
[i
].height
== 456.0f
, "%u: got line height %f\n", i
, metrics
[i
].height
);
3819 ok(metrics
[i
].baseline
== 123.0f
, "%u: got line baseline %f\n", i
, metrics
[i
].baseline
);
3822 IDWriteTextLayout_Release(layout
);
3824 /* Switch to proportional */
3825 hr
= IDWriteTextFormat_SetLineSpacing(format
, DWRITE_LINE_SPACING_METHOD_PROPORTIONAL
, 2.0f
, 4.0f
);
3827 hr
= IDWriteFactory_CreateTextLayout(factory
, str4W
, 1, format
, 100.0f
, 300.0f
, &layout
);
3828 ok(hr
== S_OK
, "Failed to create layout, hr %#x.\n", hr
);
3830 hr
= IDWriteTextLayout_GetLineMetrics(layout
, metrics
, ARRAY_SIZE(metrics
), &count
);
3831 ok(hr
== S_OK
, "Failed to get line metrics, hr %#x.\n", hr
);
3832 ok(count
== 1, "Unexpected line count %u\n", count
);
3834 /* Back to default mode. */
3835 hr
= IDWriteTextLayout_SetLineSpacing(layout
, DWRITE_LINE_SPACING_METHOD_DEFAULT
, 0.0f
, 0.0f
);
3836 ok(hr
== S_OK
, "Failed to set spacing method, hr %#x.\n", hr
);
3838 hr
= IDWriteTextLayout_GetLineMetrics(layout
, metrics
+ 1, 1, &count
);
3839 ok(hr
== S_OK
, "Failed to get line metrics, hr %#x.\n", hr
);
3840 ok(count
== 1, "Unexpected line count %u\n", count
);
3842 /* Proportional spacing applies multipliers to default, content based spacing. */
3843 ok(metrics
[0].height
== 2.0f
* metrics
[1].height
, "Unexpected line height %f.\n", metrics
[0].height
);
3844 ok(metrics
[0].baseline
== 4.0f
* metrics
[1].baseline
, "Unexpected line baseline %f.\n", metrics
[0].baseline
);
3846 IDWriteTextLayout_Release(layout
);
3849 win_skip("Proportional spacing is not supported.\n");
3851 IDWriteTextFormat_Release(format
);
3852 IDWriteFontFace_Release(fontface
);
3853 IDWriteFactory_Release(factory
);
3856 static void test_SetTextAlignment(void)
3858 static const WCHAR strW
[] = {'a',0};
3860 static const WCHAR stringsW
[][10] = {
3865 DWRITE_CLUSTER_METRICS clusters
[10];
3866 DWRITE_TEXT_METRICS metrics
;
3867 IDWriteTextFormat1
*format1
;
3868 IDWriteTextFormat
*format
;
3869 IDWriteTextLayout
*layout
;
3870 IDWriteFactory
*factory
;
3871 DWRITE_TEXT_ALIGNMENT v
;
3875 factory
= create_factory();
3877 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
3878 DWRITE_FONT_STRETCH_NORMAL
, 12.0, enusW
, &format
);
3879 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3881 v
= IDWriteTextFormat_GetTextAlignment(format
);
3882 ok(v
== DWRITE_TEXT_ALIGNMENT_LEADING
, "got %d\n", v
);
3884 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 1, format
, 500.0, 100.0, &layout
);
3885 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3887 v
= IDWriteTextLayout_GetTextAlignment(layout
);
3888 ok(v
== DWRITE_TEXT_ALIGNMENT_LEADING
, "got %d\n", v
);
3890 hr
= IDWriteTextLayout_SetTextAlignment(layout
, DWRITE_TEXT_ALIGNMENT_TRAILING
);
3891 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3893 hr
= IDWriteTextLayout_SetTextAlignment(layout
, DWRITE_TEXT_ALIGNMENT_TRAILING
);
3894 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3896 v
= IDWriteTextFormat_GetTextAlignment(format
);
3897 ok(v
== DWRITE_TEXT_ALIGNMENT_LEADING
, "got %d\n", v
);
3899 v
= IDWriteTextLayout_GetTextAlignment(layout
);
3900 ok(v
== DWRITE_TEXT_ALIGNMENT_TRAILING
, "got %d\n", v
);
3902 hr
= IDWriteTextLayout_QueryInterface(layout
, &IID_IDWriteTextFormat1
, (void**)&format1
);
3904 hr
= IDWriteTextFormat1_SetTextAlignment(format1
, DWRITE_TEXT_ALIGNMENT_CENTER
);
3905 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3907 v
= IDWriteTextFormat_GetTextAlignment(format
);
3908 ok(v
== DWRITE_TEXT_ALIGNMENT_LEADING
, "got %d\n", v
);
3910 v
= IDWriteTextLayout_GetTextAlignment(layout
);
3911 ok(v
== DWRITE_TEXT_ALIGNMENT_CENTER
, "got %d\n", v
);
3913 v
= IDWriteTextFormat1_GetTextAlignment(format1
);
3914 ok(v
== DWRITE_TEXT_ALIGNMENT_CENTER
, "got %d\n", v
);
3916 IDWriteTextFormat1_Release(format1
);
3919 win_skip("IDWriteTextFormat1 is not supported\n");
3921 IDWriteTextLayout_Release(layout
);
3923 for (i
= 0; i
< ARRAY_SIZE(stringsW
); i
++) {
3926 hr
= IDWriteTextFormat_SetTextAlignment(format
, DWRITE_TEXT_ALIGNMENT_LEADING
);
3927 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3929 hr
= IDWriteFactory_CreateTextLayout(factory
, stringsW
[i
], lstrlenW(stringsW
[i
]), format
, 500.0f
, 100.0f
, &layout
);
3930 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3932 hr
= IDWriteTextLayout_SetWordWrapping(layout
, DWRITE_WORD_WRAPPING_NO_WRAP
);
3933 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3936 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, clusters
, ARRAY_SIZE(clusters
), &count
);
3937 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3938 if (lstrlenW(stringsW
[i
]))
3939 ok(count
> 0, "got %u\n", count
);
3941 ok(count
== 0, "got %u\n", count
);
3945 text_width
+= clusters
[--count
].width
;
3947 /* maxwidth is 500, leading alignment */
3948 hr
= IDWriteTextLayout_SetTextAlignment(layout
, DWRITE_TEXT_ALIGNMENT_LEADING
);
3949 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3951 hr
= IDWriteTextLayout_GetMetrics(layout
, &metrics
);
3952 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3954 ok(metrics
.left
== 0.0f
, "got %.2f\n", metrics
.left
);
3955 ok(metrics
.width
== text_width
, "got %.2f\n", metrics
.width
);
3956 ok(metrics
.layoutWidth
== 500.0f
, "got %.2f\n", metrics
.layoutWidth
);
3957 ok(metrics
.lineCount
== 1, "got %d\n", metrics
.lineCount
);
3959 /* maxwidth is 500, trailing alignment */
3960 hr
= IDWriteTextLayout_SetTextAlignment(layout
, DWRITE_TEXT_ALIGNMENT_TRAILING
);
3961 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3963 hr
= IDWriteTextLayout_GetMetrics(layout
, &metrics
);
3964 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3966 ok(metrics
.left
== metrics
.layoutWidth
- metrics
.width
, "got %.2f\n", metrics
.left
);
3967 ok(metrics
.width
== text_width
, "got %.2f\n", metrics
.width
);
3968 ok(metrics
.layoutWidth
== 500.0f
, "got %.2f\n", metrics
.layoutWidth
);
3969 ok(metrics
.lineCount
== 1, "got %d\n", metrics
.lineCount
);
3970 IDWriteTextLayout_Release(layout
);
3972 /* initially created with trailing alignment */
3973 hr
= IDWriteTextFormat_SetTextAlignment(format
, DWRITE_TEXT_ALIGNMENT_TRAILING
);
3974 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3976 hr
= IDWriteFactory_CreateTextLayout(factory
, stringsW
[i
], lstrlenW(stringsW
[i
]), format
, 500.0f
, 100.0f
, &layout
);
3977 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3979 hr
= IDWriteTextLayout_GetMetrics(layout
, &metrics
);
3980 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3982 ok(metrics
.left
== metrics
.layoutWidth
- metrics
.width
, "got %.2f\n", metrics
.left
);
3983 ok(metrics
.width
== text_width
, "got %.2f\n", metrics
.width
);
3984 ok(metrics
.layoutWidth
== 500.0f
, "got %.2f\n", metrics
.layoutWidth
);
3985 ok(metrics
.lineCount
== 1, "got %d\n", metrics
.lineCount
);
3986 IDWriteTextLayout_Release(layout
);
3988 if (lstrlenW(stringsW
[i
]) > 0) {
3989 /* max width less than total run width, trailing alignment */
3990 hr
= IDWriteTextFormat_SetWordWrapping(format
, DWRITE_WORD_WRAPPING_NO_WRAP
);
3991 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3993 hr
= IDWriteFactory_CreateTextLayout(factory
, stringsW
[i
], lstrlenW(stringsW
[i
]), format
, clusters
[0].width
, 100.0f
, &layout
);
3994 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3995 hr
= IDWriteTextLayout_GetMetrics(layout
, &metrics
);
3996 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3997 ok(metrics
.left
== metrics
.layoutWidth
- metrics
.width
, "got %.2f\n", metrics
.left
);
3998 ok(metrics
.width
== text_width
, "got %.2f\n", metrics
.width
);
3999 ok(metrics
.lineCount
== 1, "got %d\n", metrics
.lineCount
);
4000 IDWriteTextLayout_Release(layout
);
4003 /* maxwidth is 500, centered */
4004 hr
= IDWriteTextFormat_SetTextAlignment(format
, DWRITE_TEXT_ALIGNMENT_CENTER
);
4005 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4007 hr
= IDWriteFactory_CreateTextLayout(factory
, stringsW
[i
], lstrlenW(stringsW
[i
]), format
, 500.0f
, 100.0f
, &layout
);
4008 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4010 hr
= IDWriteTextLayout_GetMetrics(layout
, &metrics
);
4011 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4012 ok(metrics
.left
== (metrics
.layoutWidth
- metrics
.width
) / 2.0f
, "got %.2f\n", metrics
.left
);
4013 ok(metrics
.width
== text_width
, "got %.2f\n", metrics
.width
);
4014 ok(metrics
.lineCount
== 1, "got %d\n", metrics
.lineCount
);
4016 IDWriteTextLayout_Release(layout
);
4019 IDWriteTextFormat_Release(format
);
4020 IDWriteFactory_Release(factory
);
4023 static void test_SetParagraphAlignment(void)
4025 static const WCHAR strW
[] = {'a',0};
4026 DWRITE_TEXT_METRICS metrics
;
4027 IDWriteTextFormat
*format
;
4028 IDWriteTextLayout
*layout
;
4029 IDWriteFactory
*factory
;
4030 DWRITE_PARAGRAPH_ALIGNMENT v
;
4031 DWRITE_LINE_METRICS lines
[1];
4035 factory
= create_factory();
4037 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
4038 DWRITE_FONT_STRETCH_NORMAL
, 12.0, enusW
, &format
);
4039 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4041 v
= IDWriteTextFormat_GetParagraphAlignment(format
);
4042 ok(v
== DWRITE_PARAGRAPH_ALIGNMENT_NEAR
, "got %d\n", v
);
4044 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 1, format
, 500.0, 100.0, &layout
);
4045 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4047 v
= IDWriteTextLayout_GetParagraphAlignment(layout
);
4048 ok(v
== DWRITE_PARAGRAPH_ALIGNMENT_NEAR
, "got %d\n", v
);
4050 hr
= IDWriteTextLayout_SetParagraphAlignment(layout
, DWRITE_PARAGRAPH_ALIGNMENT_FAR
);
4051 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4053 hr
= IDWriteTextLayout_SetParagraphAlignment(layout
, DWRITE_PARAGRAPH_ALIGNMENT_FAR
);
4054 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4056 v
= IDWriteTextFormat_GetParagraphAlignment(format
);
4057 ok(v
== DWRITE_PARAGRAPH_ALIGNMENT_NEAR
, "got %d\n", v
);
4059 v
= IDWriteTextLayout_GetParagraphAlignment(layout
);
4060 ok(v
== DWRITE_PARAGRAPH_ALIGNMENT_FAR
, "got %d\n", v
);
4062 hr
= IDWriteTextLayout_SetParagraphAlignment(layout
, DWRITE_PARAGRAPH_ALIGNMENT_CENTER
);
4063 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4065 v
= IDWriteTextLayout_GetParagraphAlignment(layout
);
4066 ok(v
== DWRITE_PARAGRAPH_ALIGNMENT_CENTER
, "got %d\n", v
);
4069 hr
= IDWriteTextLayout_GetLineMetrics(layout
, lines
, 1, &count
);
4070 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4071 ok(count
== 1, "got %u\n", count
);
4073 /* maxheight is 100, near alignment */
4074 hr
= IDWriteTextLayout_SetParagraphAlignment(layout
, DWRITE_PARAGRAPH_ALIGNMENT_NEAR
);
4075 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4077 hr
= IDWriteTextLayout_GetMetrics(layout
, &metrics
);
4078 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4080 ok(metrics
.top
== 0.0, "got %.2f\n", metrics
.top
);
4081 ok(metrics
.height
== lines
[0].height
, "got %.2f\n", metrics
.height
);
4082 ok(metrics
.layoutHeight
== 100.0, "got %.2f\n", metrics
.layoutHeight
);
4083 ok(metrics
.lineCount
== 1, "got %d\n", metrics
.lineCount
);
4085 /* maxwidth is 100, far alignment */
4086 hr
= IDWriteTextLayout_SetParagraphAlignment(layout
, DWRITE_PARAGRAPH_ALIGNMENT_FAR
);
4087 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4089 hr
= IDWriteTextLayout_GetMetrics(layout
, &metrics
);
4090 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4092 ok(metrics
.top
== metrics
.layoutHeight
- metrics
.height
, "got %.2f\n", metrics
.top
);
4093 ok(metrics
.height
== lines
[0].height
, "got %.2f\n", metrics
.height
);
4094 ok(metrics
.layoutHeight
== 100.0, "got %.2f\n", metrics
.layoutHeight
);
4095 ok(metrics
.lineCount
== 1, "got %d\n", metrics
.lineCount
);
4096 IDWriteTextLayout_Release(layout
);
4098 /* initially created with centered alignment */
4099 hr
= IDWriteTextFormat_SetParagraphAlignment(format
, DWRITE_PARAGRAPH_ALIGNMENT_CENTER
);
4100 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4102 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 1, format
, 500.0, 100.0, &layout
);
4103 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4105 hr
= IDWriteTextLayout_GetMetrics(layout
, &metrics
);
4106 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4108 ok(metrics
.top
== (metrics
.layoutHeight
- lines
[0].height
) / 2, "got %.2f\n", metrics
.top
);
4109 ok(metrics
.height
== lines
[0].height
, "got %.2f\n", metrics
.height
);
4110 ok(metrics
.lineCount
== 1, "got %d\n", metrics
.lineCount
);
4111 IDWriteTextLayout_Release(layout
);
4113 IDWriteTextFormat_Release(format
);
4114 IDWriteFactory_Release(factory
);
4117 static void test_SetReadingDirection(void)
4119 static const WCHAR strW
[] = {'a',0};
4120 DWRITE_CLUSTER_METRICS clusters
[1];
4121 DWRITE_TEXT_METRICS metrics
;
4122 IDWriteTextFormat
*format
;
4123 IDWriteTextLayout
*layout
;
4124 IDWriteFactory
*factory
;
4125 DWRITE_READING_DIRECTION v
;
4126 DWRITE_LINE_METRICS lines
[1];
4130 factory
= create_factory();
4132 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
4133 DWRITE_FONT_STRETCH_NORMAL
, 12.0, enusW
, &format
);
4134 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4136 v
= IDWriteTextFormat_GetReadingDirection(format
);
4137 ok(v
== DWRITE_READING_DIRECTION_LEFT_TO_RIGHT
, "got %d\n", v
);
4139 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 1, format
, 500.0, 100.0, &layout
);
4140 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4142 v
= IDWriteTextLayout_GetReadingDirection(layout
);
4143 ok(v
== DWRITE_READING_DIRECTION_LEFT_TO_RIGHT
, "got %d\n", v
);
4145 v
= IDWriteTextFormat_GetReadingDirection(format
);
4146 ok(v
== DWRITE_READING_DIRECTION_LEFT_TO_RIGHT
, "got %d\n", v
);
4148 hr
= IDWriteTextLayout_SetReadingDirection(layout
, DWRITE_READING_DIRECTION_RIGHT_TO_LEFT
);
4149 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4152 hr
= IDWriteTextLayout_GetLineMetrics(layout
, lines
, 1, &count
);
4153 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4154 ok(count
== 1, "got %u\n", count
);
4157 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, clusters
, 1, &count
);
4158 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4159 ok(count
== 1, "got %u\n", count
);
4161 /* leading alignment, RTL */
4162 hr
= IDWriteTextLayout_GetMetrics(layout
, &metrics
);
4163 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4165 ok(metrics
.left
== metrics
.layoutWidth
- clusters
[0].width
, "got %.2f\n", metrics
.left
);
4166 ok(metrics
.top
== 0.0, "got %.2f\n", metrics
.top
);
4167 ok(metrics
.width
== clusters
[0].width
, "got %.2f\n", metrics
.width
);
4168 ok(metrics
.height
== lines
[0].height
, "got %.2f\n", metrics
.height
);
4169 ok(metrics
.layoutWidth
== 500.0, "got %.2f\n", metrics
.layoutWidth
);
4170 ok(metrics
.layoutHeight
== 100.0, "got %.2f\n", metrics
.layoutHeight
);
4171 ok(metrics
.lineCount
== 1, "got %d\n", metrics
.lineCount
);
4173 /* trailing alignment, RTL */
4174 hr
= IDWriteTextLayout_SetTextAlignment(layout
, DWRITE_TEXT_ALIGNMENT_TRAILING
);
4175 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4177 hr
= IDWriteTextLayout_GetMetrics(layout
, &metrics
);
4178 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4180 ok(metrics
.left
== 0.0, "got %.2f\n", metrics
.left
);
4181 ok(metrics
.top
== 0.0, "got %.2f\n", metrics
.top
);
4182 ok(metrics
.width
== clusters
[0].width
, "got %.2f\n", metrics
.width
);
4183 ok(metrics
.height
== lines
[0].height
, "got %.2f\n", metrics
.height
);
4184 ok(metrics
.layoutWidth
== 500.0, "got %.2f\n", metrics
.layoutWidth
);
4185 ok(metrics
.layoutHeight
== 100.0, "got %.2f\n", metrics
.layoutHeight
);
4186 ok(metrics
.lineCount
== 1, "got %d\n", metrics
.lineCount
);
4188 /* centered alignment, RTL */
4189 hr
= IDWriteTextLayout_SetTextAlignment(layout
, DWRITE_TEXT_ALIGNMENT_CENTER
);
4190 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4192 hr
= IDWriteTextLayout_GetMetrics(layout
, &metrics
);
4193 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4195 ok(metrics
.left
== (metrics
.layoutWidth
- clusters
[0].width
) / 2.0, "got %.2f\n", metrics
.left
);
4196 ok(metrics
.top
== 0.0, "got %.2f\n", metrics
.top
);
4197 ok(metrics
.width
== clusters
[0].width
, "got %.2f\n", metrics
.width
);
4198 ok(metrics
.height
== lines
[0].height
, "got %.2f\n", metrics
.height
);
4199 ok(metrics
.layoutWidth
== 500.0, "got %.2f\n", metrics
.layoutWidth
);
4200 ok(metrics
.layoutHeight
== 100.0, "got %.2f\n", metrics
.layoutHeight
);
4201 ok(metrics
.lineCount
== 1, "got %d\n", metrics
.lineCount
);
4203 IDWriteTextLayout_Release(layout
);
4205 IDWriteTextFormat_Release(format
);
4206 IDWriteFactory_Release(factory
);
4209 static inline FLOAT
get_scaled_font_metric(UINT32 metric
, FLOAT emSize
, const DWRITE_FONT_METRICS
*metrics
)
4211 return (FLOAT
)metric
* emSize
/ (FLOAT
)metrics
->designUnitsPerEm
;
4214 static FLOAT
snap_coord(const DWRITE_MATRIX
*m
, FLOAT ppdip
, FLOAT coord
)
4216 FLOAT vec
[2], det
, vec2
[2];
4219 /* has to be a diagonal matrix */
4220 if ((ppdip
<= 0.0) ||
4221 (m
->m11
* m
->m22
!= 0.0 && (m
->m12
!= 0.0 || m
->m21
!= 0.0)) ||
4222 (m
->m12
* m
->m21
!= 0.0 && (m
->m11
!= 0.0 || m
->m22
!= 0.0)))
4225 det
= m
->m11
* m
->m22
- m
->m12
* m
->m21
;
4226 transform
= fabsf(det
) > 1e-10;
4229 /* apply transform */
4231 vec
[1] = coord
* ppdip
;
4233 vec2
[0] = m
->m11
* vec
[0] + m
->m21
* vec
[1] + m
->dx
;
4234 vec2
[1] = m
->m12
* vec
[0] + m
->m22
* vec
[1] + m
->dy
;
4237 vec2
[0] = floorf(vec2
[0] + 0.5f
);
4238 vec2
[1] = floorf(vec2
[1] + 0.5f
);
4240 /* apply inverted transform */
4241 vec
[1] = (-m
->m12
* vec2
[0] + m
->m11
* vec2
[1] - (m
->m11
* m
->dy
- m
->m12
* m
->dx
)) / det
;
4245 vec
[1] = floorf(coord
* ppdip
+ 0.5f
) / ppdip
;
4249 static inline BOOL
float_eq(FLOAT left
, FLOAT right
)
4251 int x
= *(int *)&left
;
4252 int y
= *(int *)&right
;
4259 return abs(x
- y
) <= 16;
4262 struct snapping_test
{
4267 static struct snapping_test snapping_tests
[] = {
4268 { { 0.0, 1.0, 2.0, 0.0, 0.2, 0.3 }, 1.0 },
4269 { { 0.0, 1.0, 2.0, 0.0, 0.0, 0.0 }, 1.0 },
4270 { { 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 }, 1.0 }, /* identity transform */
4271 { { 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 }, 0.9 },
4272 { { 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 }, -1.0 },
4273 { { 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 }, 0.0 },
4274 { { 1.0, 0.0, 0.0, 1.0, 0.0, 0.3 }, 1.0 }, /* simple Y shift */
4275 { { 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 }, 10.0 }, /* identity, 10 ppdip */
4276 { { 1.0, 0.0, 0.0, 10.0, 0.0, 0.0 }, 10.0 },
4277 { { 0.0, 1.0, 1.0, 0.0, 0.2, 0.6 }, 1.0 },
4278 { { 0.0, 2.0, 2.0, 0.0, 0.2, 0.6 }, 1.0 },
4279 { { 0.0, 0.5, -0.5, 0.0, 0.2, 0.6 }, 1.0 },
4280 { { 1.0, 2.0, 0.0, 1.0, 0.2, 0.6 }, 1.0 },
4281 { { 1.0, 1.0, 0.0, 1.0, 0.2, 0.6 }, 1.0 },
4282 { { 0.5, 0.5, -0.5, 0.5, 0.2, 0.6 }, 1.0 }, /* 45 degrees rotation */
4283 { { 0.5, 0.5, -0.5, 0.5, 0.0, 0.0 }, 100.0 }, /* 45 degrees rotation */
4284 { { 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 }, 100.0 },
4285 { { 0.0, 1.0, -1.0, 0.0, 0.2, 0.6 }, 1.0 }, /* 90 degrees rotation */
4286 { { -1.0, 0.0, 0.0, -1.0, 0.2, 0.6 }, 1.0 }, /* 180 degrees rotation */
4287 { { 0.0, -1.0, 1.0, 0.0, 0.2, 0.6 }, 1.0 }, /* 270 degrees rotation */
4288 { { 1.0, 0.0, 0.0, 1.0,-0.1, 0.2 }, 1.0 },
4289 { { 0.0, 1.0, -1.0, 0.0,-0.2,-0.3 }, 1.0 }, /* 90 degrees rotation */
4290 { { -1.0, 0.0, 0.0, -1.0,-0.3,-1.6 }, 1.0 }, /* 180 degrees rotation */
4291 { { 0.0, -1.0, 1.0, 0.0,-0.7, 0.6 }, 10.0 }, /* 270 degrees rotation */
4292 { { 0.0, 2.0, 1.0, 0.0, 0.2, 0.6 }, 1.0 },
4293 { { 0.0, 0.0, 1.0, 0.0, 0.0, 0.0 }, 1.0 },
4294 { { 3.0, 0.0, 0.0, 5.0, 0.2,-0.3 }, 10.0 },
4295 { { 0.0, -3.0, 5.0, 0.0,-0.1, 0.7 }, 10.0 },
4298 static DWRITE_MATRIX compattransforms
[] = {
4299 { 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 },
4300 { 1.0, 0.0, 0.0, 1.0, 0.2, 0.3 },
4301 { 2.0, 0.0, 0.0, 2.0, 0.2, 0.3 },
4302 { 2.0, 1.0, 2.0, 2.0, 0.2, 0.3 },
4305 static void test_pixelsnapping(void)
4307 static const WCHAR strW
[] = {'a',0};
4308 IDWriteTextLayout
*layout
, *layout2
;
4309 struct renderer_context ctxt
;
4310 DWRITE_FONT_METRICS metrics
;
4311 IDWriteTextFormat
*format
;
4312 IDWriteFontFace
*fontface
;
4313 IDWriteFactory
*factory
;
4314 FLOAT baseline
, originX
;
4318 factory
= create_factory();
4320 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
4321 DWRITE_FONT_STRETCH_NORMAL
, 12.0, enusW
, &format
);
4322 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4324 fontface
= get_fontface_from_format(format
);
4325 IDWriteFontFace_GetMetrics(fontface
, &metrics
);
4327 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 1, format
, 500.0, 100.0, &layout
);
4328 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4330 /* disabled snapping */
4331 ctxt
.snapping_disabled
= TRUE
;
4332 ctxt
.gdicompat
= FALSE
;
4333 ctxt
.use_gdi_natural
= FALSE
;
4335 memset(&ctxt
.m
, 0, sizeof(ctxt
.m
));
4336 ctxt
.m
.m11
= ctxt
.m
.m22
= 1.0;
4339 hr
= IDWriteTextLayout_Draw(layout
, &ctxt
, &testrenderer
, originX
, 0.0);
4340 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4342 baseline
= get_scaled_font_metric(metrics
.ascent
, 12.0, &metrics
);
4343 ok(ctxt
.originX
== originX
, "got %f, originX %f\n", ctxt
.originX
, originX
);
4344 ok(ctxt
.originY
== baseline
, "got %f, baseline %f\n", ctxt
.originY
, baseline
);
4345 ok(floor(baseline
) != baseline
, "got %f\n", baseline
);
4347 ctxt
.snapping_disabled
= FALSE
;
4349 for (i
= 0; i
< ARRAY_SIZE(snapping_tests
); i
++) {
4350 struct snapping_test
*ptr
= &snapping_tests
[i
];
4354 ctxt
.ppdip
= ptr
->ppdip
;
4355 ctxt
.originX
= 678.9;
4356 ctxt
.originY
= 678.9;
4358 expectedY
= snap_coord(&ctxt
.m
, ctxt
.ppdip
, baseline
);
4359 hr
= IDWriteTextLayout_Draw(layout
, &ctxt
, &testrenderer
, originX
, 0.0);
4360 ok(hr
== S_OK
, "%d: got 0x%08x\n", i
, hr
);
4361 ok(ctxt
.originX
== originX
, "%d: got %f, originX %f\n", i
, ctxt
.originX
, originX
);
4362 ok(float_eq(ctxt
.originY
, expectedY
), "%d: got %f, expected %f, baseline %f\n",
4363 i
, ctxt
.originY
, expectedY
, baseline
);
4365 /* gdicompat layout transform doesn't affect snapping */
4366 for (j
= 0; j
< ARRAY_SIZE(compattransforms
); j
++) {
4367 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, strW
, 1, format
, 500.0, 100.0,
4368 1.0, &compattransforms
[j
], FALSE
, &layout2
);
4369 ok(hr
== S_OK
, "%d: got 0x%08x\n", i
, hr
);
4371 expectedY
= snap_coord(&ctxt
.m
, ctxt
.ppdip
, baseline
);
4372 hr
= IDWriteTextLayout_Draw(layout
, &ctxt
, &testrenderer
, originX
, 0.0);
4373 ok(hr
== S_OK
, "%d: got 0x%08x\n", i
, hr
);
4374 ok(ctxt
.originX
== originX
, "%d: got %f, originX %f\n", i
, ctxt
.originX
, originX
);
4375 ok(float_eq(ctxt
.originY
, expectedY
), "%d: got %f, expected %f, baseline %f\n",
4376 i
, ctxt
.originY
, expectedY
, baseline
);
4378 IDWriteTextLayout_Release(layout2
);
4382 IDWriteTextLayout_Release(layout
);
4383 IDWriteTextFormat_Release(format
);
4384 IDWriteFontFace_Release(fontface
);
4385 IDWriteFactory_Release(factory
);
4388 static void test_SetWordWrapping(void)
4390 static const WCHAR strW
[] = {'a',' ','s','o','m','e',' ','t','e','x','t',' ','a','n','d',
4391 ' ','a',' ','b','i','t',' ','m','o','r','e','\n','b'};
4392 IDWriteTextFormat
*format
;
4393 IDWriteTextLayout
*layout
;
4394 IDWriteFactory
*factory
;
4395 DWRITE_WORD_WRAPPING v
;
4399 factory
= create_factory();
4401 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
4402 DWRITE_FONT_STRETCH_NORMAL
, 12.0, enusW
, &format
);
4403 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4405 v
= IDWriteTextFormat_GetWordWrapping(format
);
4406 ok(v
== DWRITE_WORD_WRAPPING_WRAP
, "got %d\n", v
);
4408 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, ARRAY_SIZE(strW
), format
, 10.0f
, 100.0f
, &layout
);
4409 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4411 v
= IDWriteTextLayout_GetWordWrapping(layout
);
4412 ok(v
== DWRITE_WORD_WRAPPING_WRAP
, "got %d\n", v
);
4414 hr
= IDWriteTextLayout_SetWordWrapping(layout
, DWRITE_WORD_WRAPPING_NO_WRAP
);
4415 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4417 hr
= IDWriteTextLayout_SetWordWrapping(layout
, DWRITE_WORD_WRAPPING_NO_WRAP
);
4418 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4420 v
= IDWriteTextFormat_GetWordWrapping(format
);
4421 ok(v
== DWRITE_WORD_WRAPPING_WRAP
, "got %d\n", v
);
4423 /* disable wrapping, text has explicit newline */
4424 hr
= IDWriteTextLayout_SetWordWrapping(layout
, DWRITE_WORD_WRAPPING_NO_WRAP
);
4425 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4428 hr
= IDWriteTextLayout_GetLineMetrics(layout
, NULL
, 0, &count
);
4429 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
4430 ok(count
== 2, "got %u\n", count
);
4432 hr
= IDWriteTextLayout_SetWordWrapping(layout
, DWRITE_WORD_WRAPPING_WRAP
);
4433 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4436 hr
= IDWriteTextLayout_GetLineMetrics(layout
, NULL
, 0, &count
);
4437 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
4438 ok(count
> 2, "got %u\n", count
);
4440 IDWriteTextLayout_Release(layout
);
4441 IDWriteTextFormat_Release(format
);
4442 IDWriteFactory_Release(factory
);
4445 /* Collection dedicated to fallback testing */
4447 static const WCHAR g_blahfontW
[] = {'B','l','a','h',0};
4448 static HRESULT WINAPI
fontcollection_QI(IDWriteFontCollection
*iface
, REFIID riid
, void **obj
)
4450 if (IsEqualIID(riid
, &IID_IDWriteFontCollection
) || IsEqualIID(riid
, &IID_IUnknown
)) {
4452 IDWriteFontCollection_AddRef(iface
);
4457 return E_NOINTERFACE
;
4460 static ULONG WINAPI
fontcollection_AddRef(IDWriteFontCollection
*iface
)
4465 static ULONG WINAPI
fontcollection_Release(IDWriteFontCollection
*iface
)
4470 static UINT32 WINAPI
fontcollection_GetFontFamilyCount(IDWriteFontCollection
*iface
)
4472 ok(0, "unexpected call\n");
4476 static HRESULT WINAPI
fontcollection_GetFontFamily(IDWriteFontCollection
*iface
, UINT32 index
, IDWriteFontFamily
**family
)
4478 if (index
== 123456) {
4479 IDWriteFactory
*factory
= create_factory();
4480 IDWriteFontCollection
*syscollection
;
4484 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &syscollection
, FALSE
);
4485 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4487 hr
= IDWriteFontCollection_FindFamilyName(syscollection
, tahomaW
, &index
, &exists
);
4488 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4490 hr
= IDWriteFontCollection_GetFontFamily(syscollection
, index
, family
);
4491 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4493 IDWriteFontCollection_Release(syscollection
);
4494 IDWriteFactory_Release(factory
);
4497 ok(0, "unexpected call\n");
4501 static HRESULT WINAPI
fontcollection_FindFamilyName(IDWriteFontCollection
*iface
, WCHAR
const *name
, UINT32
*index
, BOOL
*exists
)
4503 if (!lstrcmpW(name
, g_blahfontW
)) {
4508 ok(0, "unexpected call, name %s\n", wine_dbgstr_w(name
));
4512 static HRESULT WINAPI
fontcollection_GetFontFromFontFace(IDWriteFontCollection
*iface
, IDWriteFontFace
*face
, IDWriteFont
**font
)
4514 ok(0, "unexpected call\n");
4518 static const IDWriteFontCollectionVtbl fallbackcollectionvtbl
= {
4520 fontcollection_AddRef
,
4521 fontcollection_Release
,
4522 fontcollection_GetFontFamilyCount
,
4523 fontcollection_GetFontFamily
,
4524 fontcollection_FindFamilyName
,
4525 fontcollection_GetFontFromFontFace
4528 static IDWriteFontCollection fallbackcollection
= { &fallbackcollectionvtbl
};
4530 static void test_MapCharacters(void)
4532 static const WCHAR strW
[] = {'a','b','c',0};
4533 static const WCHAR str2W
[] = {'a',0x3058,'b',0};
4534 IDWriteLocalizedStrings
*strings
;
4535 IDWriteFontFallback
*fallback
;
4536 IDWriteFactory2
*factory2
;
4537 IDWriteFactory
*factory
;
4538 UINT32 mappedlength
;
4545 factory
= create_factory();
4547 hr
= IDWriteFactory_QueryInterface(factory
, &IID_IDWriteFactory2
, (void**)&factory2
);
4548 IDWriteFactory_Release(factory
);
4550 win_skip("MapCharacters() is not supported\n");
4555 hr
= IDWriteFactory2_GetSystemFontFallback(factory2
, &fallback
);
4556 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4557 ok(fallback
!= NULL
, "got %p\n", fallback
);
4561 font
= (void*)0xdeadbeef;
4562 hr
= IDWriteFontFallback_MapCharacters(fallback
, NULL
, 0, 0, NULL
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
,
4563 DWRITE_FONT_STYLE_NORMAL
, DWRITE_FONT_STRETCH_NORMAL
, &mappedlength
, &font
, &scale
);
4564 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
4565 ok(mappedlength
== 0, "got %u\n", mappedlength
);
4566 ok(scale
== 1.0f
, "got %f\n", scale
);
4567 ok(font
== NULL
, "got %p\n", font
);
4569 /* zero length source */
4573 font
= (void*)0xdeadbeef;
4574 hr
= IDWriteFontFallback_MapCharacters(fallback
, &analysissource
, 0, 0, NULL
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
,
4575 DWRITE_FONT_STYLE_NORMAL
, DWRITE_FONT_STRETCH_NORMAL
, &mappedlength
, &font
, &scale
);
4576 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4577 ok(mappedlength
== 0, "got %u\n", mappedlength
);
4578 ok(scale
== 1.0f
, "got %f\n", scale
);
4579 ok(font
== NULL
, "got %p\n", font
);
4585 hr
= IDWriteFontFallback_MapCharacters(fallback
, &analysissource
, 0, 1, NULL
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
,
4586 DWRITE_FONT_STYLE_NORMAL
, DWRITE_FONT_STRETCH_NORMAL
, &mappedlength
, &font
, &scale
);
4588 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4589 ok(mappedlength
== 1, "got %u\n", mappedlength
);
4591 ok(scale
== 1.0f
, "got %f\n", scale
);
4593 ok(font
!= NULL
, "got %p\n", font
);
4595 IDWriteFont_Release(font
);
4597 /* same latin text, full length */
4602 hr
= IDWriteFontFallback_MapCharacters(fallback
, &analysissource
, 0, 3, NULL
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
,
4603 DWRITE_FONT_STYLE_NORMAL
, DWRITE_FONT_STRETCH_NORMAL
, &mappedlength
, &font
, &scale
);
4605 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4606 ok(mappedlength
== 3, "got %u\n", mappedlength
);
4608 ok(scale
== 1.0f
, "got %f\n", scale
);
4610 ok(font
!= NULL
, "got %p\n", font
);
4612 IDWriteFont_Release(font
);
4614 /* string 'a\x3058b' */
4619 hr
= IDWriteFontFallback_MapCharacters(fallback
, &analysissource
, 0, 3, NULL
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
,
4620 DWRITE_FONT_STYLE_NORMAL
, DWRITE_FONT_STRETCH_NORMAL
, &mappedlength
, &font
, &scale
);
4622 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4623 ok(mappedlength
== 1, "got %u\n", mappedlength
);
4625 ok(scale
== 1.0f
, "got %f\n", scale
);
4627 ok(font
!= NULL
, "got %p\n", font
);
4629 IDWriteFont_Release(font
);
4635 hr
= IDWriteFontFallback_MapCharacters(fallback
, &analysissource
, 1, 2, NULL
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
,
4636 DWRITE_FONT_STYLE_NORMAL
, DWRITE_FONT_STRETCH_NORMAL
, &mappedlength
, &font
, &scale
);
4638 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4639 ok(mappedlength
== 1, "got %u\n", mappedlength
);
4641 ok(scale
== 1.0f
, "got %f\n", scale
);
4643 ok(font
!= NULL
, "got %p\n", font
);
4645 /* font returned for Hiragana character, check if it supports Latin too */
4647 hr
= IDWriteFont_HasCharacter(font
, 'b', &exists
);
4648 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4649 ok(exists
, "got %d\n", exists
);
4651 IDWriteFont_Release(font
);
4653 /* Try with explicit collection, Tahoma will be forced. */
4659 hr
= IDWriteFontFallback_MapCharacters(fallback
, &analysissource
, 0, 3, &fallbackcollection
, g_blahfontW
, DWRITE_FONT_WEIGHT_NORMAL
,
4660 DWRITE_FONT_STYLE_NORMAL
, DWRITE_FONT_STRETCH_NORMAL
, &mappedlength
, &font
, &scale
);
4661 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4662 ok(mappedlength
== 1, "got %u\n", mappedlength
);
4663 ok(scale
== 1.0f
, "got %f\n", scale
);
4664 ok(font
!= NULL
, "got %p\n", font
);
4667 hr
= IDWriteFont_GetInformationalStrings(font
, DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES
, &strings
, &exists
);
4668 ok(hr
== S_OK
&& exists
, "got 0x%08x, exists %d\n", hr
, exists
);
4669 hr
= IDWriteLocalizedStrings_GetString(strings
, 0, buffW
, ARRAY_SIZE(buffW
));
4670 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4671 ok(!lstrcmpW(buffW
, tahomaW
), "%s\n", wine_dbgstr_w(buffW
));
4672 IDWriteLocalizedStrings_Release(strings
);
4673 IDWriteFont_Release(font
);
4675 /* 2. Hiragana character, force Tahoma font does not support Japanese */
4680 hr
= IDWriteFontFallback_MapCharacters(fallback
, &analysissource
, 1, 1, &fallbackcollection
, g_blahfontW
, DWRITE_FONT_WEIGHT_NORMAL
,
4681 DWRITE_FONT_STYLE_NORMAL
, DWRITE_FONT_STRETCH_NORMAL
, &mappedlength
, &font
, &scale
);
4682 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4683 ok(mappedlength
== 1, "got %u\n", mappedlength
);
4684 ok(scale
== 1.0f
, "got %f\n", scale
);
4685 ok(font
!= NULL
, "got %p\n", font
);
4688 hr
= IDWriteFont_GetInformationalStrings(font
, DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES
, &strings
, &exists
);
4689 ok(hr
== S_OK
&& exists
, "got 0x%08x, exists %d\n", hr
, exists
);
4690 hr
= IDWriteLocalizedStrings_GetString(strings
, 0, buffW
, ARRAY_SIZE(buffW
));
4691 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4693 ok(lstrcmpW(buffW
, tahomaW
), "%s\n", wine_dbgstr_w(buffW
));
4694 IDWriteLocalizedStrings_Release(strings
);
4695 IDWriteFont_Release(font
);
4697 IDWriteFontFallback_Release(fallback
);
4698 IDWriteFactory2_Release(factory2
);
4701 static void test_FontFallbackBuilder(void)
4703 static const WCHAR localeW
[] = {'l','o','c','a','l','e',0};
4704 static const WCHAR strW
[] = {'A',0};
4705 IDWriteFontFallback
*fallback
, *fallback2
;
4706 IDWriteFontFallbackBuilder
*builder
;
4707 DWRITE_UNICODE_RANGE range
;
4708 IDWriteFactory2
*factory2
;
4709 IDWriteFactory
*factory
;
4710 const WCHAR
*familyW
;
4711 UINT32 mappedlength
;
4717 factory
= create_factory();
4719 hr
= IDWriteFactory_QueryInterface(factory
, &IID_IDWriteFactory2
, (void**)&factory2
);
4720 IDWriteFactory_Release(factory
);
4723 win_skip("IDWriteFontFallbackBuilder is not supported\n");
4727 EXPECT_REF(factory2
, 1);
4728 hr
= IDWriteFactory2_CreateFontFallbackBuilder(factory2
, &builder
);
4729 EXPECT_REF(factory2
, 2);
4732 EXPECT_REF(factory2
, 2);
4733 EXPECT_REF(builder
, 1);
4734 hr
= IDWriteFontFallbackBuilder_CreateFontFallback(builder
, &fallback
);
4735 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4736 EXPECT_REF(factory2
, 3);
4737 EXPECT_REF(fallback
, 1);
4738 EXPECT_REF(builder
, 1);
4740 IDWriteFontFallback_AddRef(fallback
);
4741 EXPECT_REF(builder
, 1);
4742 EXPECT_REF(fallback
, 2);
4743 EXPECT_REF(factory2
, 3);
4744 IDWriteFontFallback_Release(fallback
);
4746 /* New instance is created every time, even if mappings have not changed. */
4747 hr
= IDWriteFontFallbackBuilder_CreateFontFallback(builder
, &fallback2
);
4748 ok(hr
== S_OK
, "Failed to create fallback object, hr %#x.\n", hr
);
4749 ok(fallback
!= fallback2
, "Unexpected fallback instance.\n");
4750 IDWriteFontFallback_Release(fallback2
);
4752 hr
= IDWriteFontFallbackBuilder_AddMapping(builder
, NULL
, 0, NULL
, 0, NULL
, NULL
, NULL
, 0.0f
);
4753 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
4757 hr
= IDWriteFontFallbackBuilder_AddMapping(builder
, &range
, 0, NULL
, 0, NULL
, NULL
, NULL
, 0.0f
);
4758 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
4760 hr
= IDWriteFontFallbackBuilder_AddMapping(builder
, &range
, 0, NULL
, 0, NULL
, NULL
, NULL
, 1.0f
);
4761 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
4763 hr
= IDWriteFontFallbackBuilder_AddMapping(builder
, &range
, 0, &familyW
, 1, NULL
, NULL
, NULL
, 1.0f
);
4764 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
4766 hr
= IDWriteFontFallbackBuilder_AddMapping(builder
, NULL
, 0, &familyW
, 1, NULL
, NULL
, NULL
, 1.0f
);
4767 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
4769 /* negative scaling factor */
4770 range
.first
= range
.last
= 0;
4771 familyW
= g_blahfontW
;
4772 hr
= IDWriteFontFallbackBuilder_AddMapping(builder
, &range
, 1, &familyW
, 1, NULL
, NULL
, NULL
, -1.0f
);
4773 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
4775 hr
= IDWriteFontFallbackBuilder_AddMapping(builder
, &range
, 1, &familyW
, 1, NULL
, NULL
, NULL
, 0.0f
);
4776 ok(hr
== S_OK
, "Unexpected hr %#x.\n", hr
);
4779 range
.first
= range
.last
= 0;
4780 familyW
= g_blahfontW
;
4781 hr
= IDWriteFontFallbackBuilder_AddMapping(builder
, &range
, 1, &familyW
, 1, NULL
, NULL
, NULL
, 1.0f
);
4782 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4784 range
.first
= range
.last
= 0;
4785 hr
= IDWriteFontFallbackBuilder_AddMapping(builder
, &range
, 1, &familyW
, 1, NULL
, NULL
, NULL
, 2.0f
);
4786 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4788 range
.first
= range
.last
= 'A';
4789 hr
= IDWriteFontFallbackBuilder_AddMapping(builder
, &range
, 1, &familyW
, 1, NULL
, NULL
, NULL
, 3.0f
);
4790 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4794 hr
= IDWriteFontFallbackBuilder_AddMapping(builder
, &range
, 1, &familyW
, 1, NULL
, NULL
, NULL
, 4.0f
);
4795 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4797 IDWriteFontFallback_Release(fallback
);
4799 if (0) /* crashes on native */
4800 hr
= IDWriteFontFallbackBuilder_CreateFontFallback(builder
, NULL
);
4802 hr
= IDWriteFontFallbackBuilder_CreateFontFallback(builder
, &fallback
);
4803 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4805 /* fallback font missing from system collection */
4809 font
= (void*)0xdeadbeef;
4810 hr
= IDWriteFontFallback_MapCharacters(fallback
, &analysissource
, 0, 1, NULL
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
,
4811 DWRITE_FONT_STYLE_NORMAL
, DWRITE_FONT_STRETCH_NORMAL
, &mappedlength
, &font
, &scale
);
4813 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4814 ok(mappedlength
== 1, "got %u\n", mappedlength
);
4815 ok(scale
== 1.0f
, "got %f\n", scale
);
4816 ok(font
== NULL
, "got %p\n", font
);
4818 IDWriteFontFallback_Release(fallback
);
4820 /* remap with custom collection */
4821 range
.first
= range
.last
= 'A';
4822 hr
= IDWriteFontFallbackBuilder_AddMapping(builder
, &range
, 1, &familyW
, 1, &fallbackcollection
, NULL
, NULL
, 5.0f
);
4823 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4825 hr
= IDWriteFontFallbackBuilder_CreateFontFallback(builder
, &fallback
);
4826 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4832 hr
= IDWriteFontFallback_MapCharacters(fallback
, &analysissource
, 0, 1, NULL
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
,
4833 DWRITE_FONT_STYLE_NORMAL
, DWRITE_FONT_STRETCH_NORMAL
, &mappedlength
, &font
, &scale
);
4835 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4836 ok(mappedlength
== 1, "got %u\n", mappedlength
);
4837 ok(scale
== 5.0f
, "got %f\n", scale
);
4838 ok(font
!= NULL
, "got %p\n", font
);
4841 IDWriteFont_Release(font
);
4843 IDWriteFontFallback_Release(fallback
);
4847 hr
= IDWriteFontFallbackBuilder_AddMapping(builder
, &range
, 1, &familyW
, 1, &fallbackcollection
, NULL
, NULL
, 6.0f
);
4848 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4850 hr
= IDWriteFontFallbackBuilder_CreateFontFallback(builder
, &fallback
);
4851 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4857 hr
= IDWriteFontFallback_MapCharacters(fallback
, &analysissource
, 0, 1, NULL
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
,
4858 DWRITE_FONT_STYLE_NORMAL
, DWRITE_FONT_STRETCH_NORMAL
, &mappedlength
, &font
, &scale
);
4860 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4861 ok(mappedlength
== 1, "got %u\n", mappedlength
);
4862 ok(scale
== 5.0f
, "got %f\n", scale
);
4863 ok(font
!= NULL
, "got %p\n", font
);
4866 IDWriteFont_Release(font
);
4868 IDWriteFontFallback_Release(fallback
);
4870 /* explicit locale */
4873 hr
= IDWriteFontFallbackBuilder_AddMapping(builder
, &range
, 1, &familyW
, 1, &fallbackcollection
, localeW
, NULL
, 6.0f
);
4874 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4876 hr
= IDWriteFontFallbackBuilder_CreateFontFallback(builder
, &fallback
);
4877 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4883 hr
= IDWriteFontFallback_MapCharacters(fallback
, &analysissource
, 0, 1, NULL
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
,
4884 DWRITE_FONT_STYLE_NORMAL
, DWRITE_FONT_STRETCH_NORMAL
, &mappedlength
, &font
, &scale
);
4886 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4887 ok(mappedlength
== 1, "got %u\n", mappedlength
);
4888 ok(scale
== 5.0f
, "got %f\n", scale
);
4889 ok(font
!= NULL
, "got %p\n", font
);
4892 IDWriteFont_Release(font
);
4894 IDWriteFontFallback_Release(fallback
);
4896 IDWriteFontFallbackBuilder_Release(builder
);
4897 ref
= IDWriteFactory2_Release(factory2
);
4898 ok(ref
== 0, "Factory is not released, ref %u.\n", ref
);
4901 static void test_SetTypography(void)
4903 static const WCHAR strW
[] = {'a','f','i','b',0};
4904 IDWriteTypography
*typography
, *typography2
;
4905 IDWriteTextFormat
*format
;
4906 IDWriteTextLayout
*layout
;
4907 DWRITE_TEXT_RANGE range
;
4908 IDWriteFactory
*factory
;
4911 factory
= create_factory();
4913 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
4914 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
4915 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4917 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 1000.0, 1000.0, &layout
);
4918 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4919 IDWriteTextFormat_Release(format
);
4921 hr
= IDWriteFactory_CreateTypography(factory
, &typography
);
4922 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4924 EXPECT_REF(typography
, 1);
4925 range
.startPosition
= 0;
4927 hr
= IDWriteTextLayout_SetTypography(layout
, typography
, range
);
4928 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4929 EXPECT_REF(typography
, 2);
4931 hr
= IDWriteTextLayout_GetTypography(layout
, 0, &typography2
, NULL
);
4932 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4933 ok(typography2
== typography
, "got %p, expected %p\n", typography2
, typography
);
4934 IDWriteTypography_Release(typography2
);
4935 IDWriteTypography_Release(typography
);
4937 hr
= IDWriteFactory_CreateTypography(factory
, &typography2
);
4938 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4940 range
.startPosition
= 0;
4942 hr
= IDWriteTextLayout_SetTypography(layout
, typography2
, range
);
4943 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4944 EXPECT_REF(typography2
, 2);
4945 IDWriteTypography_Release(typography2
);
4947 hr
= IDWriteTextLayout_GetTypography(layout
, 0, &typography
, &range
);
4948 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4949 ok(range
.length
== 1, "got %u\n", range
.length
);
4951 IDWriteTypography_Release(typography
);
4953 IDWriteTextLayout_Release(layout
);
4954 IDWriteFactory_Release(factory
);
4957 static void test_SetLastLineWrapping(void)
4959 static const WCHAR strW
[] = {'a',0};
4960 IDWriteTextLayout2
*layout2
;
4961 IDWriteTextFormat1
*format1
;
4962 IDWriteTextLayout
*layout
;
4963 IDWriteTextFormat
*format
;
4964 IDWriteFactory
*factory
;
4968 factory
= create_factory();
4970 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
4971 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
4972 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4974 hr
= IDWriteTextFormat_QueryInterface(format
, &IID_IDWriteTextFormat1
, (void**)&format1
);
4975 IDWriteTextFormat_Release(format
);
4977 win_skip("SetLastLineWrapping() is not supported\n");
4978 IDWriteFactory_Release(factory
);
4982 ret
= IDWriteTextFormat1_GetLastLineWrapping(format1
);
4983 ok(ret
, "got %d\n", ret
);
4985 hr
= IDWriteTextFormat1_SetLastLineWrapping(format1
, FALSE
);
4986 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4988 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 1, (IDWriteTextFormat
*)format1
, 1000.0, 1000.0, &layout
);
4989 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4991 hr
= IDWriteTextLayout_QueryInterface(layout
, &IID_IDWriteTextLayout2
, (void**)&layout2
);
4992 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4993 IDWriteTextLayout_Release(layout
);
4995 ret
= IDWriteTextLayout2_GetLastLineWrapping(layout2
);
4996 ok(!ret
, "got %d\n", ret
);
4998 hr
= IDWriteTextLayout2_SetLastLineWrapping(layout2
, TRUE
);
4999 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5001 IDWriteTextLayout2_Release(layout2
);
5002 IDWriteTextFormat1_Release(format1
);
5003 IDWriteFactory_Release(factory
);
5006 static void test_SetOpticalAlignment(void)
5008 static const WCHAR strW
[] = {'a',0};
5009 DWRITE_OPTICAL_ALIGNMENT alignment
;
5010 IDWriteTextLayout2
*layout2
;
5011 IDWriteTextFormat1
*format1
;
5012 IDWriteTextLayout
*layout
;
5013 IDWriteTextFormat
*format
;
5014 IDWriteFactory
*factory
;
5017 factory
= create_factory();
5019 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
5020 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
5021 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5023 hr
= IDWriteTextFormat_QueryInterface(format
, &IID_IDWriteTextFormat1
, (void**)&format1
);
5024 IDWriteTextFormat_Release(format
);
5026 win_skip("SetOpticalAlignment() is not supported\n");
5027 IDWriteFactory_Release(factory
);
5031 alignment
= IDWriteTextFormat1_GetOpticalAlignment(format1
);
5032 ok(alignment
== DWRITE_OPTICAL_ALIGNMENT_NONE
, "got %d\n", alignment
);
5034 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 1, (IDWriteTextFormat
*)format1
, 1000.0, 1000.0, &layout
);
5035 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5037 hr
= IDWriteTextLayout_QueryInterface(layout
, &IID_IDWriteTextLayout2
, (void**)&layout2
);
5038 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5039 IDWriteTextLayout_Release(layout
);
5040 IDWriteTextFormat1_Release(format1
);
5042 alignment
= IDWriteTextLayout2_GetOpticalAlignment(layout2
);
5043 ok(alignment
== DWRITE_OPTICAL_ALIGNMENT_NONE
, "got %d\n", alignment
);
5045 hr
= IDWriteTextLayout2_QueryInterface(layout2
, &IID_IDWriteTextFormat1
, (void**)&format1
);
5046 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5048 alignment
= IDWriteTextFormat1_GetOpticalAlignment(format1
);
5049 ok(alignment
== DWRITE_OPTICAL_ALIGNMENT_NONE
, "got %d\n", alignment
);
5051 hr
= IDWriteTextLayout2_SetOpticalAlignment(layout2
, DWRITE_OPTICAL_ALIGNMENT_NO_SIDE_BEARINGS
);
5052 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5054 hr
= IDWriteTextLayout2_SetOpticalAlignment(layout2
, DWRITE_OPTICAL_ALIGNMENT_NO_SIDE_BEARINGS
+1);
5055 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5057 alignment
= IDWriteTextFormat1_GetOpticalAlignment(format1
);
5058 ok(alignment
== DWRITE_OPTICAL_ALIGNMENT_NO_SIDE_BEARINGS
, "got %d\n", alignment
);
5060 hr
= IDWriteTextFormat1_SetOpticalAlignment(format1
, DWRITE_OPTICAL_ALIGNMENT_NONE
);
5061 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5063 hr
= IDWriteTextFormat1_SetOpticalAlignment(format1
, DWRITE_OPTICAL_ALIGNMENT_NO_SIDE_BEARINGS
+1);
5064 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5066 alignment
= IDWriteTextLayout2_GetOpticalAlignment(layout2
);
5067 ok(alignment
== DWRITE_OPTICAL_ALIGNMENT_NONE
, "got %d\n", alignment
);
5069 IDWriteTextLayout2_Release(layout2
);
5070 IDWriteTextFormat1_Release(format1
);
5071 IDWriteFactory_Release(factory
);
5074 static const struct drawcall_entry drawunderline_seq
[] = {
5075 { DRAW_GLYPHRUN
, {'a','e',0x0300,0}, {'e','n','-','u','s',0}, 2 }, /* reported runs can't mix different underline values */
5076 { DRAW_GLYPHRUN
, {'d',0}, {'e','n','-','u','s',0}, 1 },
5077 { DRAW_UNDERLINE
, {0}, {'e','n','-','u','s',0} },
5081 static const struct drawcall_entry drawunderline2_seq
[] = {
5082 { DRAW_GLYPHRUN
, {'a',0}, {'e','n','-','u','s',0}, 1 },
5083 { DRAW_GLYPHRUN
, {'e',0}, {'e','n','-','u','s',0}, 1 },
5084 { DRAW_UNDERLINE
, {0}, {'e','n','-','u','s',0} },
5088 static const struct drawcall_entry drawunderline3_seq
[] = {
5089 { DRAW_GLYPHRUN
, {'a',0}, {'e','n','-','c','a',0}, 1 },
5090 { DRAW_GLYPHRUN
, {'e',0}, {'e','n','-','u','s',0}, 1 },
5091 { DRAW_UNDERLINE
, {0}, {'e','n','-','c','a',0} },
5092 { DRAW_UNDERLINE
, {0}, {'e','n','-','u','s',0} },
5096 static const struct drawcall_entry drawunderline4_seq
[] = {
5097 { DRAW_GLYPHRUN
, {'a',0}, {'e','n','-','u','s',0}, 1 },
5098 { DRAW_GLYPHRUN
, {'e',0}, {'e','n','-','u','s',0}, 1 },
5099 { DRAW_UNDERLINE
, {0}, {'e','n','-','u','s',0} },
5100 { DRAW_STRIKETHROUGH
},
5104 static void test_SetUnderline(void)
5106 static const WCHAR encaW
[] = {'e','n','-','C','A',0};
5107 static const WCHAR strW
[] = {'a','e',0x0300,'d',0}; /* accent grave */
5108 IDWriteFontCollection
*syscollection
;
5109 DWRITE_CLUSTER_METRICS clusters
[4];
5110 IDWriteTextFormat
*format
;
5111 IDWriteTextLayout
*layout
;
5112 DWRITE_TEXT_RANGE range
;
5113 IDWriteFactory
*factory
;
5117 factory
= create_factory();
5119 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
5120 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
5121 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5123 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 1000.0, 1000.0, &layout
);
5124 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5127 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, clusters
, ARRAY_SIZE(clusters
), &count
);
5128 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5130 ok(count
== 3, "got %u\n", count
);
5132 range
.startPosition
= 0;
5134 hr
= IDWriteTextLayout_SetUnderline(layout
, TRUE
, range
);
5135 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5138 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, clusters
, ARRAY_SIZE(clusters
), &count
);
5139 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5141 ok(count
== 3, "got %u\n", count
);
5143 flush_sequence(sequences
, RENDERER_ID
);
5144 hr
= IDWriteTextLayout_Draw(layout
, NULL
, &testrenderer
, 0.0, 0.0);
5145 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5146 ok_sequence(sequences
, RENDERER_ID
, drawunderline_seq
, "draw underline test", TRUE
);
5148 IDWriteTextLayout_Release(layout
);
5150 /* 2 characters, same font, significantly different font size. Set underline for both, see how many
5151 underline drawing calls is there. */
5152 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 2, format
, 1000.0f
, 1000.0f
, &layout
);
5153 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5155 range
.startPosition
= 0;
5157 hr
= IDWriteTextLayout_SetUnderline(layout
, TRUE
, range
);
5158 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5160 range
.startPosition
= 0;
5162 hr
= IDWriteTextLayout_SetFontSize(layout
, 100.0f
, range
);
5163 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5165 flush_sequence(sequences
, RENDERER_ID
);
5166 hr
= IDWriteTextLayout_Draw(layout
, NULL
, &testrenderer
, 0.0f
, 0.0f
);
5167 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5168 ok_sequence(sequences
, RENDERER_ID
, drawunderline2_seq
, "draw underline test 2", FALSE
);
5170 /* now set different locale for second char, draw again */
5171 range
.startPosition
= 0;
5173 hr
= IDWriteTextLayout_SetLocaleName(layout
, encaW
, range
);
5174 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5176 flush_sequence(sequences
, RENDERER_ID
);
5177 hr
= IDWriteTextLayout_Draw(layout
, NULL
, &testrenderer
, 0.0f
, 0.0f
);
5178 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5179 ok_sequence(sequences
, RENDERER_ID
, drawunderline3_seq
, "draw underline test 2", FALSE
);
5181 IDWriteTextLayout_Release(layout
);
5183 /* 2 characters, same font properties, first with strikethrough, both underlined */
5184 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 2, format
, 1000.0f
, 1000.0f
, &layout
);
5185 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5187 range
.startPosition
= 0;
5189 hr
= IDWriteTextLayout_SetStrikethrough(layout
, TRUE
, range
);
5190 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5192 range
.startPosition
= 0;
5194 hr
= IDWriteTextLayout_SetUnderline(layout
, TRUE
, range
);
5195 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5197 flush_sequence(sequences
, RENDERER_ID
);
5198 hr
= IDWriteTextLayout_Draw(layout
, NULL
, &testrenderer
, 0.0f
, 0.0f
);
5199 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5200 ok_sequence(sequences
, RENDERER_ID
, drawunderline4_seq
, "draw underline test 4", FALSE
);
5202 IDWriteTextLayout_Release(layout
);
5204 IDWriteTextFormat_Release(format
);
5206 /* Test runHeight value with all available fonts */
5207 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &syscollection
, FALSE
);
5208 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5209 count
= IDWriteFontCollection_GetFontFamilyCount(syscollection
);
5211 for (i
= 0; i
< count
; i
++) {
5212 DWRITE_FONT_METRICS fontmetrics
;
5213 IDWriteLocalizedStrings
*names
;
5214 struct renderer_context ctxt
;
5215 IDWriteFontFamily
*family
;
5216 IDWriteFontFace
*fontface
;
5224 hr
= IDWriteFontCollection_GetFontFamily(syscollection
, i
, &family
);
5225 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5227 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STRETCH_NORMAL
,
5228 DWRITE_FONT_STYLE_NORMAL
, &font
);
5229 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5231 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
5232 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5234 hr
= IDWriteFontFamily_GetFamilyNames(family
, &names
);
5235 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5237 if (!(exists
= get_enus_string(names
, nameW
, ARRAY_SIZE(nameW
)))) {
5238 IDWriteLocalFontFileLoader
*localloader
;
5239 IDWriteFontFileLoader
*loader
;
5240 IDWriteFontFile
*file
;
5246 hr
= IDWriteFontFace_GetFiles(fontface
, &count
, &file
);
5247 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5249 hr
= IDWriteFontFile_GetLoader(file
, &loader
);
5250 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5252 hr
= IDWriteFontFileLoader_QueryInterface(loader
, &IID_IDWriteLocalFontFileLoader
, (void**)&localloader
);
5253 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5254 IDWriteFontFileLoader_Release(loader
);
5256 hr
= IDWriteFontFile_GetReferenceKey(file
, &key
, &keysize
);
5257 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5259 hr
= IDWriteLocalFontFileLoader_GetFilePathFromKey(localloader
, key
, keysize
, nameW
, ARRAY_SIZE(nameW
));
5260 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5262 skip("Failed to get English family name, font file %s\n", wine_dbgstr_w(nameW
));
5264 IDWriteLocalFontFileLoader_Release(localloader
);
5265 IDWriteFontFile_Release(file
);
5268 IDWriteLocalizedStrings_Release(names
);
5269 IDWriteFont_Release(font
);
5274 IDWriteFontFace_GetMetrics(fontface
, &fontmetrics
);
5275 hr
= IDWriteFactory_CreateTextFormat(factory
, nameW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
5276 DWRITE_FONT_STRETCH_NORMAL
, fontmetrics
.designUnitsPerEm
, enusW
, &format
);
5277 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5279 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 2, format
, 30000.0f
, 100.0f
, &layout
);
5280 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5282 range
.startPosition
= 0;
5284 hr
= IDWriteTextLayout_SetUnderline(layout
, TRUE
, range
);
5285 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5287 memset(&ctxt
, 0, sizeof(ctxt
));
5288 ctxt
.format
= format
;
5289 ctxt
.familyW
= nameW
;
5290 hr
= IDWriteTextLayout_Draw(layout
, &ctxt
, &testrenderer
, 0.0f
, 0.0f
);
5291 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5295 IDWriteTextLayout_Release(layout
);
5297 IDWriteTextFormat_Release(format
);
5298 IDWriteFontFace_Release(fontface
);
5299 IDWriteFontFamily_Release(family
);
5301 IDWriteFontCollection_Release(syscollection
);
5303 IDWriteFactory_Release(factory
);
5306 static void test_InvalidateLayout(void)
5308 static const WCHAR strW
[] = {'a',0};
5309 IDWriteTextLayout3
*layout3
;
5310 IDWriteTextLayout
*layout
;
5311 IDWriteTextFormat
*format
;
5312 IDWriteFactory
*factory
;
5315 factory
= create_factory();
5317 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
5318 DWRITE_FONT_STRETCH_NORMAL
, 10.0f
, enusW
, &format
);
5319 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5321 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 1, format
, 1000.0f
, 1000.0f
, &layout
);
5322 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5324 hr
= IDWriteTextLayout_QueryInterface(layout
, &IID_IDWriteTextLayout3
, (void**)&layout3
);
5326 IDWriteTextFormat1
*format1
;
5327 IDWriteTextFormat2
*format2
;
5329 hr
= IDWriteTextFormat_QueryInterface(format
, &IID_IDWriteTextFormat2
, (void**)&format2
);
5330 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5331 IDWriteTextFormat2_Release(format2
);
5333 hr
= IDWriteTextLayout_QueryInterface(layout
, &IID_IDWriteTextFormat2
, (void**)&format2
);
5334 ok(hr
== S_OK
|| broken(hr
== E_NOINTERFACE
), "Unexpected hr %#x.\n", hr
);
5336 ok(format
!= (IDWriteTextFormat
*)format2
, "Unexpected interface pointer.\n");
5337 IDWriteTextFormat2_Release(format2
);
5340 hr
= IDWriteTextLayout_QueryInterface(layout
, &IID_IDWriteTextFormat1
, (void**)&format1
);
5341 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5343 hr
= IDWriteTextFormat1_QueryInterface(format1
, &IID_IDWriteTextFormat2
, (void**)&format2
);
5344 ok(hr
== S_OK
|| broken(hr
== E_NOINTERFACE
), "Unexpected hr %#x.\n", hr
);
5346 IDWriteTextFormat2_Release(format2
);
5347 IDWriteTextFormat1_Release(format1
);
5349 hr
= IDWriteTextLayout3_QueryInterface(layout3
, &IID_IDWriteTextFormat2
, (void**)&format2
);
5350 ok(hr
== S_OK
|| broken(hr
== E_NOINTERFACE
), "got 0x%08x\n", hr
);
5352 IDWriteTextFormat2_Release(format2
);
5354 hr
= IDWriteTextLayout3_InvalidateLayout(layout3
);
5355 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5356 IDWriteTextLayout3_Release(layout3
);
5359 win_skip("IDWriteTextLayout3::InvalidateLayout() is not supported.\n");
5361 IDWriteTextLayout_Release(layout
);
5362 IDWriteTextFormat_Release(format
);
5363 IDWriteFactory_Release(factory
);
5366 static void test_line_spacing(void)
5368 static const WCHAR strW
[] = {'a',0};
5369 IDWriteTextFormat2
*format2
;
5370 IDWriteTextLayout
*layout
;
5371 IDWriteTextFormat
*format
;
5372 IDWriteFactory
*factory
;
5375 factory
= create_factory();
5377 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
5378 DWRITE_FONT_STRETCH_NORMAL
, 10.0f
, enusW
, &format
);
5379 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5381 hr
= IDWriteTextFormat_SetLineSpacing(format
, DWRITE_LINE_SPACING_METHOD_DEFAULT
, 0.0f
, 0.0f
);
5382 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5384 hr
= IDWriteTextFormat_SetLineSpacing(format
, DWRITE_LINE_SPACING_METHOD_DEFAULT
, 0.0f
, -10.0f
);
5385 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5387 hr
= IDWriteTextFormat_SetLineSpacing(format
, DWRITE_LINE_SPACING_METHOD_DEFAULT
, -10.0f
, 0.0f
);
5388 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5390 hr
= IDWriteTextFormat_SetLineSpacing(format
, DWRITE_LINE_SPACING_METHOD_PROPORTIONAL
+1, 0.0f
, 0.0f
);
5391 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5393 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 1, format
, 1000.0f
, 1000.0f
, &layout
);
5394 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5396 hr
= IDWriteTextLayout_SetLineSpacing(layout
, DWRITE_LINE_SPACING_METHOD_DEFAULT
, 0.0f
, 0.0f
);
5397 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5399 hr
= IDWriteTextLayout_SetLineSpacing(layout
, DWRITE_LINE_SPACING_METHOD_DEFAULT
, 0.0f
, -10.0f
);
5400 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5402 hr
= IDWriteTextLayout_SetLineSpacing(layout
, DWRITE_LINE_SPACING_METHOD_DEFAULT
, -10.0f
, 0.0f
);
5403 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5405 hr
= IDWriteTextLayout_SetLineSpacing(layout
, DWRITE_LINE_SPACING_METHOD_PROPORTIONAL
+1, 0.0f
, 0.0f
);
5406 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5408 if (IDWriteTextFormat_QueryInterface(format
, &IID_IDWriteTextFormat2
, (void**)&format2
) == S_OK
) {
5409 DWRITE_LINE_SPACING spacing
;
5411 hr
= IDWriteTextFormat2_GetLineSpacing(format2
, &spacing
);
5412 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5414 ok(spacing
.method
== DWRITE_LINE_SPACING_METHOD_DEFAULT
, "got method %d\n", spacing
.method
);
5415 ok(spacing
.height
== 0.0f
, "got %f\n", spacing
.height
);
5416 ok(spacing
.baseline
== -10.0f
, "got %f\n", spacing
.baseline
);
5417 ok(spacing
.leadingBefore
== 0.0f
, "got %f\n", spacing
.leadingBefore
);
5418 ok(spacing
.fontLineGapUsage
== DWRITE_FONT_LINE_GAP_USAGE_DEFAULT
, "got %f\n", spacing
.leadingBefore
);
5420 spacing
.leadingBefore
= -1.0f
;
5422 hr
= IDWriteTextFormat2_SetLineSpacing(format2
, &spacing
);
5423 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5425 spacing
.leadingBefore
= 1.1f
;
5427 hr
= IDWriteTextFormat2_SetLineSpacing(format2
, &spacing
);
5428 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5430 spacing
.leadingBefore
= 1.0f
;
5432 hr
= IDWriteTextFormat2_SetLineSpacing(format2
, &spacing
);
5433 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5435 spacing
.method
= DWRITE_LINE_SPACING_METHOD_PROPORTIONAL
+ 1;
5436 hr
= IDWriteTextFormat2_SetLineSpacing(format2
, &spacing
);
5437 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5439 spacing
.method
= DWRITE_LINE_SPACING_METHOD_PROPORTIONAL
;
5440 spacing
.fontLineGapUsage
= DWRITE_FONT_LINE_GAP_USAGE_ENABLED
+ 1;
5441 hr
= IDWriteTextFormat2_SetLineSpacing(format2
, &spacing
);
5442 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5444 hr
= IDWriteTextFormat2_GetLineSpacing(format2
, &spacing
);
5445 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5446 ok(spacing
.fontLineGapUsage
== DWRITE_FONT_LINE_GAP_USAGE_ENABLED
+ 1, "got %d\n", spacing
.fontLineGapUsage
);
5448 IDWriteTextFormat2_Release(format2
);
5451 IDWriteTextLayout_Release(layout
);
5452 IDWriteTextFormat_Release(format
);
5453 IDWriteFactory_Release(factory
);
5456 static void test_GetOverhangMetrics(void)
5458 static const struct overhangs_test
5460 FLOAT uniform_baseline
;
5461 DWRITE_INLINE_OBJECT_METRICS metrics
;
5462 DWRITE_OVERHANG_METRICS overhang_metrics
;
5463 DWRITE_OVERHANG_METRICS expected
;
5464 } overhangs_tests
[] = {
5465 { 16.0f
, { 10.0f
, 50.0f
, 20.0f
}, { 1.0f
, 2.0f
, 3.0f
, 4.0f
}, { 1.0f
, 6.0f
, 3.0f
, 0.0f
} },
5466 { 15.0f
, { 10.0f
, 50.0f
, 20.0f
}, { 1.0f
, 2.0f
, 3.0f
, 4.0f
}, { 1.0f
, 7.0f
, 3.0f
, -1.0f
} },
5467 { 16.0f
, { 10.0f
, 50.0f
, 20.0f
}, { -1.0f
, 0.0f
, -3.0f
, 4.0f
}, { -1.0f
, 4.0f
, -3.0f
, 0.0f
} },
5468 { 15.0f
, { 10.0f
, 50.0f
, 20.0f
}, { -1.0f
, 10.0f
, 3.0f
, -4.0f
}, { -1.0f
, 15.0f
, 3.0f
, -9.0f
} },
5470 static const WCHAR strW
[] = {'A',0};
5471 IDWriteFactory
*factory
;
5472 IDWriteTextFormat
*format
;
5473 IDWriteTextLayout
*layout
;
5477 factory
= create_factory();
5479 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
5480 DWRITE_FONT_STRETCH_NORMAL
, 100.0f
, enusW
, &format
);
5481 ok(hr
== S_OK
, "Failed to create text format, hr %#x.\n", hr
);
5483 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 1, format
, 1000.0f
, 1000.0f
, &layout
);
5484 ok(hr
== S_OK
, "Failed to create text layout, hr %x.\n", hr
);
5486 for (i
= 0; i
< ARRAY_SIZE(overhangs_tests
); i
++) {
5487 const struct overhangs_test
*test
= &overhangs_tests
[i
];
5488 DWRITE_OVERHANG_METRICS overhang_metrics
;
5489 DWRITE_TEXT_RANGE range
= { 0, 1 };
5490 DWRITE_TEXT_METRICS metrics
;
5491 struct test_inline_obj obj
;
5493 test_inline_obj_init(&obj
, &test
->metrics
, &test
->overhang_metrics
);
5495 hr
= IDWriteTextLayout_SetLineSpacing(layout
, DWRITE_LINE_SPACING_METHOD_UNIFORM
, test
->metrics
.height
* 2.0f
,
5496 test
->uniform_baseline
);
5497 ok(hr
== S_OK
, "Failed to set line spacing, hr %#x.\n", hr
);
5499 hr
= IDWriteTextLayout_SetInlineObject(layout
, NULL
, range
);
5500 ok(hr
== S_OK
, "Failed to reset inline object, hr %#x.\n", hr
);
5502 hr
= IDWriteTextLayout_SetInlineObject(layout
, &obj
.IDWriteInlineObject_iface
, range
);
5503 ok(hr
== S_OK
, "Failed to set inline object, hr %#x.\n", hr
);
5505 hr
= IDWriteTextLayout_GetMetrics(layout
, &metrics
);
5506 ok(hr
== S_OK
, "Failed to get layout metrics, hr %#x.\n", hr
);
5508 ok(metrics
.width
== test
->metrics
.width
, "%u: unexpected formatted width.\n", i
);
5509 ok(metrics
.height
== test
->metrics
.height
* 2.0f
, "%u: unexpected formatted height.\n", i
);
5511 hr
= IDWriteTextLayout_SetMaxWidth(layout
, metrics
.width
);
5512 hr
= IDWriteTextLayout_SetMaxHeight(layout
, test
->metrics
.height
);
5514 hr
= IDWriteTextLayout_GetOverhangMetrics(layout
, &overhang_metrics
);
5515 ok(hr
== S_OK
, "Failed to get overhang metrics, hr %#x.\n", hr
);
5517 ok(!memcmp(&overhang_metrics
, &test
->expected
, sizeof(overhang_metrics
)),
5518 "%u: unexpected overhang metrics (%f, %f, %f, %f).\n", i
, overhang_metrics
.left
, overhang_metrics
.top
,
5519 overhang_metrics
.right
, overhang_metrics
.bottom
);
5522 IDWriteTextLayout_Release(layout
);
5523 IDWriteTextFormat_Release(format
);
5524 IDWriteFactory_Release(factory
);
5529 IDWriteFactory
*factory
;
5531 if (!(factory
= create_factory())) {
5532 win_skip("failed to create factory\n");
5536 init_call_sequences(sequences
, NUM_CALL_SEQUENCES
);
5537 init_call_sequences(expected_seq
, 1);
5539 test_CreateTextLayout();
5540 test_CreateGdiCompatibleTextLayout();
5541 test_CreateTextFormat();
5542 test_GetLocaleName();
5543 test_CreateEllipsisTrimmingSign();
5545 test_SetInlineObject();
5548 test_GetClusterMetrics();
5549 test_SetLocaleName();
5550 test_SetPairKerning();
5551 test_SetVerticalGlyphOrientation();
5553 test_DetermineMinWidth();
5555 test_SetFontFamilyName();
5556 test_SetFontStyle();
5557 test_SetFontStretch();
5558 test_SetStrikethrough();
5560 test_SetFlowDirection();
5561 test_SetDrawingEffect();
5562 test_GetLineMetrics();
5563 test_SetTextAlignment();
5564 test_SetParagraphAlignment();
5565 test_SetReadingDirection();
5566 test_pixelsnapping();
5567 test_SetWordWrapping();
5568 test_MapCharacters();
5569 test_FontFallbackBuilder();
5570 test_SetTypography();
5571 test_SetLastLineWrapping();
5572 test_SetOpticalAlignment();
5573 test_SetUnderline();
5574 test_InvalidateLayout();
5575 test_line_spacing();
5576 test_GetOverhangMetrics();
5578 IDWriteFactory_Release(factory
);