2 * Text layout/format tests
4 * Copyright 2012, 2014-2015 Nikolay Sivov for CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
29 #include "wine/test.h"
31 static const WCHAR tahomaW
[] = {'T','a','h','o','m','a',0};
32 static const WCHAR enusW
[] = {'e','n','-','u','s',0};
34 static DWRITE_SCRIPT_ANALYSIS g_sa
;
35 static DWRITE_SCRIPT_ANALYSIS g_control_sa
;
37 /* test IDWriteTextAnalysisSink */
38 static HRESULT WINAPI
analysissink_QueryInterface(IDWriteTextAnalysisSink
*iface
, REFIID riid
, void **obj
)
40 if (IsEqualIID(riid
, &IID_IDWriteTextAnalysisSink
) || IsEqualIID(riid
, &IID_IUnknown
))
50 static ULONG WINAPI
analysissink_AddRef(IDWriteTextAnalysisSink
*iface
)
55 static ULONG WINAPI
analysissink_Release(IDWriteTextAnalysisSink
*iface
)
60 static HRESULT WINAPI
analysissink_SetScriptAnalysis(IDWriteTextAnalysisSink
*iface
,
61 UINT32 position
, UINT32 length
, DWRITE_SCRIPT_ANALYSIS
const* sa
)
67 static HRESULT WINAPI
analysissink_SetLineBreakpoints(IDWriteTextAnalysisSink
*iface
,
68 UINT32 position
, UINT32 length
, DWRITE_LINE_BREAKPOINT
const* breakpoints
)
70 ok(0, "unexpected call\n");
74 static HRESULT WINAPI
analysissink_SetBidiLevel(IDWriteTextAnalysisSink
*iface
,
75 UINT32 position
, UINT32 length
, UINT8 explicitLevel
, UINT8 resolvedLevel
)
77 ok(0, "unexpected\n");
81 static HRESULT WINAPI
analysissink_SetNumberSubstitution(IDWriteTextAnalysisSink
*iface
,
82 UINT32 position
, UINT32 length
, IDWriteNumberSubstitution
* substitution
)
84 ok(0, "unexpected\n");
88 static IDWriteTextAnalysisSinkVtbl analysissinkvtbl
= {
89 analysissink_QueryInterface
,
92 analysissink_SetScriptAnalysis
,
93 analysissink_SetLineBreakpoints
,
94 analysissink_SetBidiLevel
,
95 analysissink_SetNumberSubstitution
98 static IDWriteTextAnalysisSink analysissink
= { &analysissinkvtbl
};
100 /* test IDWriteTextAnalysisSource */
101 static HRESULT WINAPI
analysissource_QueryInterface(IDWriteTextAnalysisSource
*iface
,
102 REFIID riid
, void **obj
)
104 ok(0, "QueryInterface not expected\n");
108 static ULONG WINAPI
analysissource_AddRef(IDWriteTextAnalysisSource
*iface
)
110 ok(0, "AddRef not expected\n");
114 static ULONG WINAPI
analysissource_Release(IDWriteTextAnalysisSource
*iface
)
116 ok(0, "Release not expected\n");
120 static const WCHAR
*g_source
;
122 static HRESULT WINAPI
analysissource_GetTextAtPosition(IDWriteTextAnalysisSource
*iface
,
123 UINT32 position
, WCHAR
const** text
, UINT32
* text_len
)
125 if (position
>= lstrlenW(g_source
))
132 *text
= &g_source
[position
];
133 *text_len
= lstrlenW(g_source
) - position
;
139 static HRESULT WINAPI
analysissource_GetTextBeforePosition(IDWriteTextAnalysisSource
*iface
,
140 UINT32 position
, WCHAR
const** text
, UINT32
* text_len
)
142 ok(0, "unexpected\n");
146 static DWRITE_READING_DIRECTION WINAPI
analysissource_GetParagraphReadingDirection(
147 IDWriteTextAnalysisSource
*iface
)
149 ok(0, "unexpected\n");
150 return DWRITE_READING_DIRECTION_RIGHT_TO_LEFT
;
153 static HRESULT WINAPI
analysissource_GetLocaleName(IDWriteTextAnalysisSource
*iface
,
154 UINT32 position
, UINT32
* text_len
, WCHAR
const** locale
)
161 static HRESULT WINAPI
analysissource_GetNumberSubstitution(IDWriteTextAnalysisSource
*iface
,
162 UINT32 position
, UINT32
* text_len
, IDWriteNumberSubstitution
**substitution
)
164 ok(0, "unexpected\n");
168 static IDWriteTextAnalysisSourceVtbl analysissourcevtbl
= {
169 analysissource_QueryInterface
,
170 analysissource_AddRef
,
171 analysissource_Release
,
172 analysissource_GetTextAtPosition
,
173 analysissource_GetTextBeforePosition
,
174 analysissource_GetParagraphReadingDirection
,
175 analysissource_GetLocaleName
,
176 analysissource_GetNumberSubstitution
179 static IDWriteTextAnalysisSource analysissource
= { &analysissourcevtbl
};
181 static IDWriteFactory
*create_factory(void)
183 IDWriteFactory
*factory
;
184 HRESULT hr
= DWriteCreateFactory(DWRITE_FACTORY_TYPE_ISOLATED
, &IID_IDWriteFactory
, (IUnknown
**)&factory
);
185 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
189 /* obvious limitation is that only last script data is returned, so this
190 helper is suitable for single script strings only */
191 static void get_script_analysis(const WCHAR
*str
, UINT32 len
, DWRITE_SCRIPT_ANALYSIS
*sa
)
193 IDWriteTextAnalyzer
*analyzer
;
194 IDWriteFactory
*factory
;
199 factory
= create_factory();
200 hr
= IDWriteFactory_CreateTextAnalyzer(factory
, &analyzer
);
201 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
203 hr
= IDWriteTextAnalyzer_AnalyzeScript(analyzer
, &analysissource
, 0, len
, &analysissink
);
204 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
207 IDWriteFactory_Release(factory
);
210 #define EXPECT_REF(obj,ref) _expect_ref((IUnknown*)obj, ref, __LINE__)
211 static void _expect_ref(IUnknown
* obj
, ULONG ref
, int line
)
213 ULONG rc
= IUnknown_AddRef(obj
);
214 IUnknown_Release(obj
);
215 ok_(__FILE__
,line
)(rc
-1 == ref
, "expected refcount %d, got %d\n", ref
, rc
-1);
226 static const char *get_draw_kind_name(enum drawcall_kind kind
)
228 static const char *kind_names
[] = { "GLYPH_RUN", "UNDERLINE", "STRIKETHROUGH", "INLINE", "END_OF_SEQ" };
229 return kind
> DRAW_LAST_KIND
? "unknown" : kind_names
[kind
];
232 struct drawcall_entry
{
233 enum drawcall_kind kind
;
234 WCHAR string
[10]; /* only meaningful for DrawGlyphRun() */
237 struct drawcall_sequence
241 struct drawcall_entry
*sequence
;
244 struct drawtestcontext
{
245 enum drawcall_kind kind
;
252 #define NUM_CALL_SEQUENCES 1
253 #define RENDERER_ID 0
254 static struct drawcall_sequence
*sequences
[NUM_CALL_SEQUENCES
];
255 static struct drawcall_sequence
*expected_seq
[1];
257 static void add_call(struct drawcall_sequence
**seq
, int sequence_index
, const struct drawcall_entry
*call
)
259 struct drawcall_sequence
*call_seq
= seq
[sequence_index
];
261 if (!call_seq
->sequence
) {
263 call_seq
->sequence
= HeapAlloc(GetProcessHeap(), 0, call_seq
->size
* sizeof (struct drawcall_entry
));
266 if (call_seq
->count
== call_seq
->size
) {
268 call_seq
->sequence
= HeapReAlloc(GetProcessHeap(), 0,
270 call_seq
->size
* sizeof (struct drawcall_entry
));
273 assert(call_seq
->sequence
);
274 call_seq
->sequence
[call_seq
->count
++] = *call
;
277 static inline void flush_sequence(struct drawcall_sequence
**seg
, int sequence_index
)
279 struct drawcall_sequence
*call_seq
= seg
[sequence_index
];
281 HeapFree(GetProcessHeap(), 0, call_seq
->sequence
);
282 call_seq
->sequence
= NULL
;
283 call_seq
->count
= call_seq
->size
= 0;
286 static inline void flush_sequences(struct drawcall_sequence
**seq
, int n
)
289 for (i
= 0; i
< n
; i
++)
290 flush_sequence(seq
, i
);
293 static void init_call_sequences(struct drawcall_sequence
**seq
, int n
)
297 for (i
= 0; i
< n
; i
++)
298 seq
[i
] = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(struct drawcall_sequence
));
301 static void ok_sequence_(struct drawcall_sequence
**seq
, int sequence_index
,
302 const struct drawcall_entry
*expected
, const char *context
, BOOL todo
,
303 const char *file
, int line
)
305 static const struct drawcall_entry end_of_sequence
= { DRAW_LAST_KIND
};
306 struct drawcall_sequence
*call_seq
= seq
[sequence_index
];
307 const struct drawcall_entry
*actual
, *sequence
;
310 add_call(seq
, sequence_index
, &end_of_sequence
);
312 sequence
= call_seq
->sequence
;
315 while (expected
->kind
!= DRAW_LAST_KIND
&& actual
->kind
!= DRAW_LAST_KIND
) {
316 if (expected
->kind
!= actual
->kind
) {
320 ok_(file
, line
) (0, "%s: call %s was expected, but got call %s instead\n",
321 context
, get_draw_kind_name(expected
->kind
), get_draw_kind_name(actual
->kind
));
323 flush_sequence(seq
, sequence_index
);
327 ok_(file
, line
) (0, "%s: call %s was expected, but got call %s instead\n",
328 context
, get_draw_kind_name(expected
->kind
), get_draw_kind_name(actual
->kind
));
330 else if (expected
->kind
== DRAW_GLYPHRUN
) {
331 int cmp
= lstrcmpW(expected
->string
, actual
->string
);
332 if (cmp
!= 0 && todo
) {
335 ok_(file
, line
) (0, "%s: glyphrun string %s was expected, but got %s instead\n",
336 context
, wine_dbgstr_w(expected
->string
), wine_dbgstr_w(actual
->string
));
339 ok_(file
, line
) (cmp
== 0, "%s: glyphrun string %s was expected, but got %s instead\n",
340 context
, wine_dbgstr_w(expected
->string
), wine_dbgstr_w(actual
->string
));
348 if (expected
->kind
!= DRAW_LAST_KIND
|| actual
->kind
!= DRAW_LAST_KIND
) {
350 ok_(file
, line
) (0, "%s: the call sequence is not complete: expected %s - actual %s\n",
351 context
, get_draw_kind_name(expected
->kind
), get_draw_kind_name(actual
->kind
));
355 else if (expected
->kind
!= DRAW_LAST_KIND
|| actual
->kind
!= DRAW_LAST_KIND
)
356 ok_(file
, line
) (0, "%s: the call sequence is not complete: expected %s - actual %s\n",
357 context
, get_draw_kind_name(expected
->kind
), get_draw_kind_name(actual
->kind
));
359 if (todo
&& !failcount
) /* succeeded yet marked todo */
361 ok_(file
, line
)(1, "%s: marked \"todo_wine\" but succeeds\n", context
);
363 flush_sequence(seq
, sequence_index
);
366 #define ok_sequence(seq, index, exp, contx, todo) \
367 ok_sequence_(seq, index, (exp), (contx), (todo), __FILE__, __LINE__)
369 static HRESULT WINAPI
testrenderer_QI(IDWriteTextRenderer
*iface
, REFIID riid
, void **obj
)
371 if (IsEqualIID(riid
, &IID_IDWriteTextRenderer
) ||
372 IsEqualIID(riid
, &IID_IDWritePixelSnapping
) ||
373 IsEqualIID(riid
, &IID_IUnknown
)
381 /* IDWriteTextRenderer1 overrides drawing calls, ignore for now */
382 if (IsEqualIID(riid
, &IID_IDWriteTextRenderer1
))
383 return E_NOINTERFACE
;
385 ok(0, "unexpected QI %s\n", wine_dbgstr_guid(riid
));
386 return E_NOINTERFACE
;
389 static ULONG WINAPI
testrenderer_AddRef(IDWriteTextRenderer
*iface
)
394 static ULONG WINAPI
testrenderer_Release(IDWriteTextRenderer
*iface
)
399 static HRESULT WINAPI
testrenderer_IsPixelSnappingDisabled(IDWriteTextRenderer
*iface
,
400 void *client_drawingcontext
, BOOL
*disabled
)
406 static HRESULT WINAPI
testrenderer_GetCurrentTransform(IDWriteTextRenderer
*iface
,
407 void *client_drawingcontext
, DWRITE_MATRIX
*transform
)
409 transform
->m11
= 1.0;
410 transform
->m12
= 0.0;
411 transform
->m21
= 0.0;
412 transform
->m22
= 1.0;
418 static HRESULT WINAPI
testrenderer_GetPixelsPerDip(IDWriteTextRenderer
*iface
,
419 void *client_drawingcontext
, FLOAT
*pixels_per_dip
)
421 *pixels_per_dip
= 1.0;
425 static HRESULT WINAPI
testrenderer_DrawGlyphRun(IDWriteTextRenderer
*iface
,
426 void* client_drawingcontext
,
427 FLOAT baselineOriginX
,
428 FLOAT baselineOriginY
,
429 DWRITE_MEASURING_MODE mode
,
430 DWRITE_GLYPH_RUN
const *run
,
431 DWRITE_GLYPH_RUN_DESCRIPTION
const *descr
,
432 IUnknown
*drawing_effect
)
434 struct drawcall_entry entry
;
435 DWRITE_SCRIPT_ANALYSIS sa
;
437 ok(descr
->stringLength
< sizeof(entry
.string
)/sizeof(WCHAR
), "string is too long\n");
438 if (descr
->stringLength
&& descr
->stringLength
< sizeof(entry
.string
)/sizeof(WCHAR
)) {
439 memcpy(entry
.string
, descr
->string
, descr
->stringLength
*sizeof(WCHAR
));
440 entry
.string
[descr
->stringLength
] = 0;
445 /* see what's reported for control codes runs */
446 get_script_analysis(descr
->string
, descr
->stringLength
, &sa
);
447 if (sa
.script
== g_control_sa
.script
) {
448 /* glyphs are not reported at all for control code runs */
449 ok(run
->glyphCount
== 0, "got %u\n", run
->glyphCount
);
450 ok(run
->glyphAdvances
!= NULL
, "advances array %p\n", run
->glyphAdvances
);
451 ok(run
->glyphOffsets
!= NULL
, "offsets array %p\n", run
->glyphOffsets
);
452 ok(run
->fontFace
!= NULL
, "got %p\n", run
->fontFace
);
453 /* text positions are still valid */
454 ok(descr
->string
!= NULL
, "got string %p\n", descr
->string
);
455 ok(descr
->stringLength
> 0, "got string length %u\n", descr
->stringLength
);
456 ok(descr
->clusterMap
!= NULL
, "clustermap %p\n", descr
->clusterMap
);
459 entry
.kind
= DRAW_GLYPHRUN
;
460 add_call(sequences
, RENDERER_ID
, &entry
);
464 static HRESULT WINAPI
testrenderer_DrawUnderline(IDWriteTextRenderer
*iface
,
465 void *client_drawingcontext
,
466 FLOAT baselineOriginX
,
467 FLOAT baselineOriginY
,
468 DWRITE_UNDERLINE
const* underline
,
469 IUnknown
*drawing_effect
)
471 struct drawcall_entry entry
;
472 entry
.kind
= DRAW_UNDERLINE
;
473 add_call(sequences
, RENDERER_ID
, &entry
);
477 static HRESULT WINAPI
testrenderer_DrawStrikethrough(IDWriteTextRenderer
*iface
,
478 void *client_drawingcontext
,
479 FLOAT baselineOriginX
,
480 FLOAT baselineOriginY
,
481 DWRITE_STRIKETHROUGH
const* strikethrough
,
482 IUnknown
*drawing_effect
)
484 struct drawcall_entry entry
;
485 entry
.kind
= DRAW_STRIKETHROUGH
;
486 add_call(sequences
, RENDERER_ID
, &entry
);
490 static HRESULT WINAPI
testrenderer_DrawInlineObject(IDWriteTextRenderer
*iface
,
491 void *client_drawingcontext
,
494 IDWriteInlineObject
*object
,
497 IUnknown
*drawing_effect
)
499 struct drawcall_entry entry
;
500 entry
.kind
= DRAW_INLINE
;
501 add_call(sequences
, RENDERER_ID
, &entry
);
505 static const IDWriteTextRendererVtbl testrenderervtbl
= {
508 testrenderer_Release
,
509 testrenderer_IsPixelSnappingDisabled
,
510 testrenderer_GetCurrentTransform
,
511 testrenderer_GetPixelsPerDip
,
512 testrenderer_DrawGlyphRun
,
513 testrenderer_DrawUnderline
,
514 testrenderer_DrawStrikethrough
,
515 testrenderer_DrawInlineObject
518 static IDWriteTextRenderer testrenderer
= { &testrenderervtbl
};
520 /* test IDWriteInlineObject */
521 static HRESULT WINAPI
testinlineobj_QI(IDWriteInlineObject
*iface
, REFIID riid
, void **obj
)
523 if (IsEqualIID(riid
, &IID_IDWriteInlineObject
) || IsEqualIID(riid
, &IID_IUnknown
)) {
525 IDWriteInlineObject_AddRef(iface
);
530 return E_NOINTERFACE
;
533 static ULONG WINAPI
testinlineobj_AddRef(IDWriteInlineObject
*iface
)
538 static ULONG WINAPI
testinlineobj_Release(IDWriteInlineObject
*iface
)
543 static HRESULT WINAPI
testinlineobj_Draw(IDWriteInlineObject
*iface
,
544 void* client_drawingontext
, IDWriteTextRenderer
* renderer
,
545 FLOAT originX
, FLOAT originY
, BOOL is_sideways
, BOOL is_rtl
, IUnknown
*drawing_effect
)
547 ok(0, "unexpected call\n");
551 static HRESULT WINAPI
testinlineobj_GetMetrics(IDWriteInlineObject
*iface
, DWRITE_INLINE_OBJECT_METRICS
*metrics
)
553 metrics
->width
= 123.0;
557 static HRESULT WINAPI
testinlineobj_GetOverhangMetrics(IDWriteInlineObject
*iface
, DWRITE_OVERHANG_METRICS
*overhangs
)
559 ok(0, "unexpected call\n");
563 static HRESULT WINAPI
testinlineobj_GetBreakConditions(IDWriteInlineObject
*iface
, DWRITE_BREAK_CONDITION
*before
,
564 DWRITE_BREAK_CONDITION
*after
)
566 *before
= *after
= DWRITE_BREAK_CONDITION_MUST_BREAK
;
570 static IDWriteInlineObjectVtbl testinlineobjvtbl
= {
572 testinlineobj_AddRef
,
573 testinlineobj_Release
,
575 testinlineobj_GetMetrics
,
576 testinlineobj_GetOverhangMetrics
,
577 testinlineobj_GetBreakConditions
580 static IDWriteInlineObject testinlineobj
= { &testinlineobjvtbl
};
581 static IDWriteInlineObject testinlineobj2
= { &testinlineobjvtbl
};
583 static void test_CreateTextLayout(void)
585 static const WCHAR strW
[] = {'s','t','r','i','n','g',0};
586 IDWriteTextLayout2
*layout2
;
587 IDWriteTextLayout
*layout
;
588 IDWriteTextFormat
*format
;
589 IDWriteFactory
*factory
;
592 factory
= create_factory();
594 hr
= IDWriteFactory_CreateTextLayout(factory
, NULL
, 0, NULL
, 0.0, 0.0, &layout
);
595 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
597 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 6, NULL
, 0.0, 0.0, &layout
);
598 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
600 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 6, NULL
, 1.0, 0.0, &layout
);
601 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
603 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 6, NULL
, 0.0, 1.0, &layout
);
604 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
606 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 6, NULL
, 1000.0, 1000.0, &layout
);
607 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
609 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
610 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
611 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
613 EXPECT_REF(format
, 1);
614 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 6, format
, 1000.0, 1000.0, &layout
);
615 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
616 EXPECT_REF(format
, 1);
618 hr
= IDWriteTextLayout_QueryInterface(layout
, &IID_IDWriteTextLayout2
, (void**)&layout2
);
620 IDWriteTextLayout1
*layout1
;
621 IDWriteTextFormat1
*format1
;
622 IDWriteTextFormat
*format
;
624 hr
= IDWriteTextLayout2_QueryInterface(layout2
, &IID_IDWriteTextLayout1
, (void**)&layout1
);
625 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
626 IDWriteTextLayout1_Release(layout1
);
628 EXPECT_REF(layout2
, 2);
629 hr
= IDWriteTextLayout2_QueryInterface(layout2
, &IID_IDWriteTextFormat1
, (void**)&format1
);
630 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
631 EXPECT_REF(layout2
, 3);
633 hr
= IDWriteTextLayout2_QueryInterface(layout2
, &IID_IDWriteTextFormat
, (void**)&format
);
634 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
635 ok(format
== (IDWriteTextFormat
*)format1
, "got %p, %p\n", format
, format1
);
636 ok(format
!= (IDWriteTextFormat
*)layout2
, "got %p, %p\n", format
, layout2
);
637 EXPECT_REF(layout2
, 4);
639 hr
= IDWriteTextFormat_QueryInterface(format
, &IID_IDWriteTextLayout1
, (void**)&layout1
);
640 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
641 IDWriteTextLayout1_Release(layout1
);
643 IDWriteTextFormat1_Release(format1
);
644 IDWriteTextFormat_Release(format
);
646 hr
= IDWriteTextLayout_QueryInterface(layout
, &IID_IDWriteTextFormat1
, (void**)&format1
);
647 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
648 EXPECT_REF(layout2
, 3);
650 hr
= IDWriteTextLayout_QueryInterface(layout
, &IID_IDWriteTextFormat
, (void**)&format
);
651 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
652 ok(format
== (IDWriteTextFormat
*)format1
, "got %p, %p\n", format
, format1
);
653 EXPECT_REF(layout2
, 4);
655 IDWriteTextFormat1_Release(format1
);
656 IDWriteTextFormat_Release(format
);
657 IDWriteTextLayout2_Release(layout2
);
660 win_skip("IDWriteTextLayout2 is not supported.\n");
662 IDWriteTextLayout_Release(layout
);
663 IDWriteTextFormat_Release(format
);
664 IDWriteFactory_Release(factory
);
667 static void test_CreateGdiCompatibleTextLayout(void)
669 static const WCHAR strW
[] = {'s','t','r','i','n','g',0};
670 IDWriteTextLayout
*layout
;
671 IDWriteTextFormat
*format
;
672 IDWriteFactory
*factory
;
676 factory
= create_factory();
678 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, NULL
, 0, NULL
, 0.0, 0.0, 0.0, NULL
, FALSE
, &layout
);
679 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
681 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, strW
, 6, NULL
, 0.0, 0.0, 0.0, NULL
, FALSE
, &layout
);
682 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
684 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, strW
, 6, NULL
, 1.0, 0.0, 0.0, NULL
, FALSE
, &layout
);
685 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
687 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, strW
, 6, NULL
, 1.0, 0.0, 1.0, NULL
, FALSE
, &layout
);
688 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
690 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, strW
, 6, NULL
, 1000.0, 1000.0, 1.0, NULL
, FALSE
, &layout
);
691 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
693 /* create with text format */
694 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
695 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
696 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
697 EXPECT_REF(format
, 1);
699 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, strW
, 6, format
, 100.0, 100.0, 1.0, NULL
, FALSE
, &layout
);
700 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
701 EXPECT_REF(format
, 1);
702 EXPECT_REF(layout
, 1);
704 IDWriteTextLayout_AddRef(layout
);
705 EXPECT_REF(format
, 1);
706 EXPECT_REF(layout
, 2);
707 IDWriteTextLayout_Release(layout
);
708 IDWriteTextLayout_Release(layout
);
710 /* zero length string is okay */
711 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, strW
, 0, format
, 100.0, 100.0, 1.0, NULL
, FALSE
, &layout
);
712 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
714 dimension
= IDWriteTextLayout_GetMaxWidth(layout
);
715 ok(dimension
== 100.0, "got %f\n", dimension
);
717 dimension
= IDWriteTextLayout_GetMaxHeight(layout
);
718 ok(dimension
== 100.0, "got %f\n", dimension
);
720 IDWriteTextLayout_Release(layout
);
721 IDWriteTextFormat_Release(format
);
722 IDWriteFactory_Release(factory
);
725 static void test_CreateTextFormat(void)
727 IDWriteFontCollection
*collection
, *syscoll
;
728 DWRITE_PARAGRAPH_ALIGNMENT paralign
;
729 DWRITE_READING_DIRECTION readdir
;
730 DWRITE_WORD_WRAPPING wrapping
;
731 DWRITE_TEXT_ALIGNMENT align
;
732 DWRITE_FLOW_DIRECTION flow
;
733 DWRITE_LINE_SPACING_METHOD method
;
734 DWRITE_TRIMMING trimming
;
735 IDWriteTextFormat
*format
;
736 FLOAT spacing
, baseline
;
737 IDWriteInlineObject
*trimmingsign
;
738 IDWriteFactory
*factory
;
741 factory
= create_factory();
743 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
744 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
745 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
747 if (0) /* crashes on native */
748 hr
= IDWriteTextFormat_GetFontCollection(format
, NULL
);
751 hr
= IDWriteTextFormat_GetFontCollection(format
, &collection
);
752 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
753 ok(collection
!= NULL
, "got %p\n", collection
);
755 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &syscoll
, FALSE
);
756 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
757 ok(collection
== syscoll
, "got %p, was %p\n", syscoll
, collection
);
758 IDWriteFontCollection_Release(syscoll
);
759 IDWriteFontCollection_Release(collection
);
761 /* default format properties */
762 align
= IDWriteTextFormat_GetTextAlignment(format
);
763 ok(align
== DWRITE_TEXT_ALIGNMENT_LEADING
, "got %d\n", align
);
765 paralign
= IDWriteTextFormat_GetParagraphAlignment(format
);
766 ok(paralign
== DWRITE_PARAGRAPH_ALIGNMENT_NEAR
, "got %d\n", paralign
);
768 wrapping
= IDWriteTextFormat_GetWordWrapping(format
);
769 ok(wrapping
== DWRITE_WORD_WRAPPING_WRAP
, "got %d\n", wrapping
);
771 readdir
= IDWriteTextFormat_GetReadingDirection(format
);
772 ok(readdir
== DWRITE_READING_DIRECTION_LEFT_TO_RIGHT
, "got %d\n", readdir
);
774 flow
= IDWriteTextFormat_GetFlowDirection(format
);
775 ok(flow
== DWRITE_FLOW_DIRECTION_TOP_TO_BOTTOM
, "got %d\n", flow
);
777 hr
= IDWriteTextFormat_GetLineSpacing(format
, &method
, &spacing
, &baseline
);
778 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
779 ok(spacing
== 0.0, "got %f\n", spacing
);
780 ok(baseline
== 0.0, "got %f\n", baseline
);
781 ok(method
== DWRITE_LINE_SPACING_METHOD_DEFAULT
, "got %d\n", method
);
783 trimming
.granularity
= DWRITE_TRIMMING_GRANULARITY_WORD
;
784 trimming
.delimiter
= 10;
785 trimming
.delimiterCount
= 10;
786 trimmingsign
= (void*)0xdeadbeef;
787 hr
= IDWriteTextFormat_GetTrimming(format
, &trimming
, &trimmingsign
);
788 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
789 ok(trimming
.granularity
== DWRITE_TRIMMING_GRANULARITY_NONE
, "got %d\n", trimming
.granularity
);
790 ok(trimming
.delimiter
== 0, "got %d\n", trimming
.delimiter
);
791 ok(trimming
.delimiterCount
== 0, "got %d\n", trimming
.delimiterCount
);
792 ok(trimmingsign
== NULL
, "got %p\n", trimmingsign
);
795 hr
= IDWriteTextFormat_SetTextAlignment(format
, DWRITE_TEXT_ALIGNMENT_LEADING
);
796 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
798 hr
= IDWriteTextFormat_SetParagraphAlignment(format
, DWRITE_PARAGRAPH_ALIGNMENT_NEAR
);
799 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
801 hr
= IDWriteTextFormat_SetWordWrapping(format
, DWRITE_WORD_WRAPPING_WRAP
);
802 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
804 hr
= IDWriteTextFormat_SetReadingDirection(format
, DWRITE_READING_DIRECTION_LEFT_TO_RIGHT
);
805 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
807 hr
= IDWriteTextFormat_SetFlowDirection(format
, DWRITE_FLOW_DIRECTION_TOP_TO_BOTTOM
);
808 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
810 hr
= IDWriteTextFormat_SetLineSpacing(format
, DWRITE_LINE_SPACING_METHOD_DEFAULT
, 0.0, 0.0);
811 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
813 hr
= IDWriteTextFormat_SetTrimming(format
, &trimming
, NULL
);
814 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
816 IDWriteTextFormat_Release(format
);
817 IDWriteFactory_Release(factory
);
820 static void test_GetLocaleName(void)
822 static const WCHAR strW
[] = {'s','t','r','i','n','g',0};
823 static const WCHAR ruW
[] = {'r','u',0};
824 IDWriteTextLayout
*layout
;
825 IDWriteTextFormat
*format
, *format2
;
826 IDWriteFactory
*factory
;
831 factory
= create_factory();
833 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
834 DWRITE_FONT_STRETCH_NORMAL
, 10.0, ruW
, &format
);
835 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
837 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, strW
, 0, format
, 100.0, 100.0, 1.0, NULL
, FALSE
, &layout
);
838 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
840 hr
= IDWriteTextLayout_QueryInterface(layout
, &IID_IDWriteTextFormat
, (void**)&format2
);
841 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
843 len
= IDWriteTextFormat_GetLocaleNameLength(format2
);
844 ok(len
== 2, "got %u\n", len
);
845 len
= IDWriteTextFormat_GetLocaleNameLength(format
);
846 ok(len
== 2, "got %u\n", len
);
847 hr
= IDWriteTextFormat_GetLocaleName(format2
, buff
, len
);
848 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
849 hr
= IDWriteTextFormat_GetLocaleName(format2
, buff
, len
+1);
850 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
851 ok(!lstrcmpW(buff
, ruW
), "got %s\n", wine_dbgstr_w(buff
));
852 hr
= IDWriteTextFormat_GetLocaleName(format
, buff
, len
);
853 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
854 hr
= IDWriteTextFormat_GetLocaleName(format
, buff
, len
+1);
855 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
856 ok(!lstrcmpW(buff
, ruW
), "got %s\n", wine_dbgstr_w(buff
));
858 IDWriteTextLayout_Release(layout
);
859 IDWriteTextFormat_Release(format
);
860 IDWriteTextFormat_Release(format2
);
861 IDWriteFactory_Release(factory
);
864 static void test_CreateEllipsisTrimmingSign(void)
866 DWRITE_BREAK_CONDITION before
, after
;
867 IDWriteTextFormat
*format
;
868 IDWriteInlineObject
*sign
;
869 IDWriteFactory
*factory
;
872 factory
= create_factory();
874 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
875 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
876 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
878 EXPECT_REF(format
, 1);
879 hr
= IDWriteFactory_CreateEllipsisTrimmingSign(factory
, format
, &sign
);
880 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
881 EXPECT_REF(format
, 1);
883 if (0) /* crashes on native */
884 hr
= IDWriteInlineObject_GetBreakConditions(sign
, NULL
, NULL
);
886 before
= after
= DWRITE_BREAK_CONDITION_CAN_BREAK
;
887 hr
= IDWriteInlineObject_GetBreakConditions(sign
, &before
, &after
);
888 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
889 ok(before
== DWRITE_BREAK_CONDITION_NEUTRAL
, "got %d\n", before
);
890 ok(after
== DWRITE_BREAK_CONDITION_NEUTRAL
, "got %d\n", after
);
892 IDWriteInlineObject_Release(sign
);
893 IDWriteTextFormat_Release(format
);
894 IDWriteFactory_Release(factory
);
897 static void test_fontweight(void)
899 static const WCHAR strW
[] = {'s','t','r','i','n','g',0};
900 static const WCHAR ruW
[] = {'r','u',0};
901 IDWriteTextFormat
*format
, *fmt2
;
902 IDWriteTextLayout
*layout
;
903 DWRITE_FONT_WEIGHT weight
;
904 DWRITE_TEXT_RANGE range
;
905 IDWriteFactory
*factory
;
909 factory
= create_factory();
911 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_BOLD
, DWRITE_FONT_STYLE_NORMAL
,
912 DWRITE_FONT_STRETCH_NORMAL
, 10.0, ruW
, &format
);
913 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
915 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, strW
, 6, format
, 100.0, 100.0, 1.0, NULL
, FALSE
, &layout
);
916 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
918 hr
= IDWriteTextLayout_QueryInterface(layout
, &IID_IDWriteTextFormat
, (void**)&fmt2
);
919 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
921 weight
= IDWriteTextFormat_GetFontWeight(fmt2
);
922 ok(weight
== DWRITE_FONT_WEIGHT_BOLD
, "got %u\n", weight
);
924 range
.startPosition
= range
.length
= 0;
925 hr
= IDWriteTextLayout_GetFontWeight(layout
, 0, &weight
, &range
);
926 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
927 ok(range
.startPosition
== 0 && range
.length
== ~0u, "got %u, %u\n", range
.startPosition
, range
.length
);
929 range
.startPosition
= 0;
931 hr
= IDWriteTextLayout_SetFontWeight(layout
, DWRITE_FONT_WEIGHT_NORMAL
, range
);
932 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
934 range
.startPosition
= range
.length
= 0;
935 hr
= IDWriteTextLayout_GetFontWeight(layout
, 0, &weight
, &range
);
936 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
937 ok(range
.startPosition
== 0 && range
.length
== 6, "got %u, %u\n", range
.startPosition
, range
.length
);
939 /* IDWriteTextFormat methods output doesn't reflect layout changes */
940 weight
= IDWriteTextFormat_GetFontWeight(fmt2
);
941 ok(weight
== DWRITE_FONT_WEIGHT_BOLD
, "got %u\n", weight
);
944 weight
= DWRITE_FONT_WEIGHT_BOLD
;
945 hr
= IDWriteTextLayout_GetFontWeight(layout
, 0, &weight
, &range
);
946 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
947 ok(weight
== DWRITE_FONT_WEIGHT_NORMAL
, "got %d\n", weight
);
948 ok(range
.length
== 6, "got %d\n", range
.length
);
950 size
= IDWriteTextLayout_GetMaxWidth(layout
);
951 ok(size
== 100.0, "got %.2f\n", size
);
953 hr
= IDWriteTextLayout_SetMaxWidth(layout
, 0.0);
954 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
956 size
= IDWriteTextLayout_GetMaxWidth(layout
);
957 ok(size
== 0.0, "got %.2f\n", size
);
959 hr
= IDWriteTextLayout_SetMaxWidth(layout
, -1.0);
960 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
962 size
= IDWriteTextLayout_GetMaxWidth(layout
);
963 ok(size
== 0.0, "got %.2f\n", size
);
965 hr
= IDWriteTextLayout_SetMaxWidth(layout
, 100.0);
966 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
968 size
= IDWriteTextLayout_GetMaxWidth(layout
);
969 ok(size
== 100.0, "got %.2f\n", size
);
971 size
= IDWriteTextLayout_GetMaxHeight(layout
);
972 ok(size
== 100.0, "got %.2f\n", size
);
974 hr
= IDWriteTextLayout_SetMaxHeight(layout
, 0.0);
975 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
977 size
= IDWriteTextLayout_GetMaxHeight(layout
);
978 ok(size
== 0.0, "got %.2f\n", size
);
980 hr
= IDWriteTextLayout_SetMaxHeight(layout
, -1.0);
981 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
983 size
= IDWriteTextLayout_GetMaxHeight(layout
);
984 ok(size
== 0.0, "got %.2f\n", size
);
986 hr
= IDWriteTextLayout_SetMaxHeight(layout
, 100.0);
987 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
989 size
= IDWriteTextLayout_GetMaxHeight(layout
);
990 ok(size
== 100.0, "got %.2f\n", size
);
992 IDWriteTextLayout_Release(layout
);
993 IDWriteTextFormat_Release(fmt2
);
994 IDWriteTextFormat_Release(format
);
995 IDWriteFactory_Release(factory
);
998 static void test_SetInlineObject(void)
1000 static const WCHAR strW
[] = {'s','t','r','i','n','g',0};
1001 static const WCHAR ruW
[] = {'r','u',0};
1003 IDWriteInlineObject
*inlineobj
, *inlineobj2
, *inlinetest
;
1004 IDWriteTextFormat
*format
;
1005 IDWriteTextLayout
*layout
;
1006 DWRITE_TEXT_RANGE range
, r2
;
1007 IDWriteFactory
*factory
;
1010 factory
= create_factory();
1012 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_BOLD
, DWRITE_FONT_STYLE_NORMAL
,
1013 DWRITE_FONT_STRETCH_NORMAL
, 10.0, ruW
, &format
);
1014 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1016 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(factory
, strW
, 6, format
, 100.0, 100.0, 1.0, NULL
, FALSE
, &layout
);
1017 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1019 hr
= IDWriteFactory_CreateEllipsisTrimmingSign(factory
, format
, &inlineobj
);
1020 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1022 hr
= IDWriteFactory_CreateEllipsisTrimmingSign(factory
, format
, &inlineobj2
);
1023 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1025 EXPECT_REF(inlineobj
, 1);
1026 EXPECT_REF(inlineobj2
, 1);
1028 inlinetest
= (void*)0x1;
1029 hr
= IDWriteTextLayout_GetInlineObject(layout
, 0, &inlinetest
, NULL
);
1030 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1031 ok(inlinetest
== NULL
, "got %p\n", inlinetest
);
1033 range
.startPosition
= 0;
1035 hr
= IDWriteTextLayout_SetInlineObject(layout
, inlineobj
, range
);
1036 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1038 EXPECT_REF(inlineobj
, 2);
1040 inlinetest
= (void*)0x1;
1041 hr
= IDWriteTextLayout_GetInlineObject(layout
, 2, &inlinetest
, NULL
);
1042 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1043 ok(inlinetest
== NULL
, "got %p\n", inlinetest
);
1046 r2
.startPosition
= r2
.length
= 100;
1047 hr
= IDWriteTextLayout_GetInlineObject(layout
, 0, &inlinetest
, &r2
);
1048 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1049 ok(inlinetest
== inlineobj
, "got %p\n", inlinetest
);
1050 ok(r2
.startPosition
== 0 && r2
.length
== 2, "got %d, %d\n", r2
.startPosition
, r2
.length
);
1051 IDWriteInlineObject_Release(inlinetest
);
1053 EXPECT_REF(inlineobj
, 2);
1055 /* get from somewhere inside a range */
1057 r2
.startPosition
= r2
.length
= 100;
1058 hr
= IDWriteTextLayout_GetInlineObject(layout
, 1, &inlinetest
, &r2
);
1059 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1060 ok(inlinetest
== inlineobj
, "got %p\n", inlinetest
);
1061 ok(r2
.startPosition
== 0 && r2
.length
== 2, "got %d, %d\n", r2
.startPosition
, r2
.length
);
1062 IDWriteInlineObject_Release(inlinetest
);
1064 EXPECT_REF(inlineobj
, 2);
1066 range
.startPosition
= 1;
1068 hr
= IDWriteTextLayout_SetInlineObject(layout
, inlineobj2
, range
);
1069 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1072 r2
.startPosition
= r2
.length
= 100;
1073 hr
= IDWriteTextLayout_GetInlineObject(layout
, 1, &inlinetest
, &r2
);
1074 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1075 ok(inlinetest
== inlineobj2
, "got %p\n", inlinetest
);
1076 ok(r2
.startPosition
== 1 && r2
.length
== 1, "got %d, %d\n", r2
.startPosition
, r2
.length
);
1077 IDWriteInlineObject_Release(inlinetest
);
1079 EXPECT_REF(inlineobj
, 2);
1080 EXPECT_REF(inlineobj2
, 2);
1083 r2
.startPosition
= r2
.length
= 100;
1084 hr
= IDWriteTextLayout_GetInlineObject(layout
, 0, &inlinetest
, &r2
);
1085 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1086 ok(inlinetest
== inlineobj
, "got %p\n", inlinetest
);
1087 ok(r2
.startPosition
== 0 && r2
.length
== 1, "got %d, %d\n", r2
.startPosition
, r2
.length
);
1088 IDWriteInlineObject_Release(inlinetest
);
1090 EXPECT_REF(inlineobj
, 2);
1092 range
.startPosition
= 1;
1094 hr
= IDWriteTextLayout_SetInlineObject(layout
, inlineobj
, range
);
1095 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1097 r2
.startPosition
= r2
.length
= 100;
1098 hr
= IDWriteTextLayout_GetInlineObject(layout
, 0, &inlinetest
, &r2
);
1099 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1100 ok(inlinetest
== inlineobj
, "got %p\n", inlinetest
);
1101 ok(r2
.startPosition
== 0 && r2
.length
== 2, "got %d, %d\n", r2
.startPosition
, r2
.length
);
1102 IDWriteInlineObject_Release(inlinetest
);
1104 EXPECT_REF(inlineobj
, 2);
1106 range
.startPosition
= 1;
1108 hr
= IDWriteTextLayout_SetInlineObject(layout
, inlineobj
, range
);
1109 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1111 EXPECT_REF(inlineobj
, 2);
1113 r2
.startPosition
= r2
.length
= 100;
1114 hr
= IDWriteTextLayout_GetInlineObject(layout
, 0, &inlinetest
, &r2
);
1115 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1116 ok(inlinetest
== inlineobj
, "got %p\n", inlinetest
);
1117 ok(r2
.startPosition
== 0 && r2
.length
== 3, "got %d, %d\n", r2
.startPosition
, r2
.length
);
1118 IDWriteInlineObject_Release(inlinetest
);
1120 EXPECT_REF(inlineobj
, 2);
1121 EXPECT_REF(inlineobj2
, 1);
1123 IDWriteTextLayout_Release(layout
);
1125 EXPECT_REF(inlineobj
, 1);
1127 IDWriteInlineObject_Release(inlineobj
);
1128 IDWriteInlineObject_Release(inlineobj2
);
1129 IDWriteTextFormat_Release(format
);
1130 IDWriteFactory_Release(factory
);
1133 /* drawing calls sequence doesn't depend on run order, instead all runs are
1134 drawn first, inline objects next and then underline/strikes */
1135 static const struct drawcall_entry draw_seq
[] = {
1136 { DRAW_GLYPHRUN
, {'s',0} },
1137 { DRAW_GLYPHRUN
, {'r','i',0} },
1138 { DRAW_GLYPHRUN
, {'n',0} },
1139 { DRAW_GLYPHRUN
, {'g',0} },
1142 { DRAW_STRIKETHROUGH
},
1146 static const struct drawcall_entry draw_seq2
[] = {
1147 { DRAW_GLYPHRUN
, {'s',0} },
1148 { DRAW_GLYPHRUN
, {'t',0} },
1149 { DRAW_GLYPHRUN
, {'r',0} },
1150 { DRAW_GLYPHRUN
, {'i',0} },
1151 { DRAW_GLYPHRUN
, {'n',0} },
1152 { DRAW_GLYPHRUN
, {'g',0} },
1156 static const struct drawcall_entry draw_seq3
[] = {
1158 { DRAW_GLYPHRUN
, {'a','b',0} },
1162 static const struct drawcall_entry draw_seq4
[] = {
1163 { DRAW_GLYPHRUN
, {'s','t','r',0} },
1164 { DRAW_GLYPHRUN
, {'i','n','g',0} },
1165 { DRAW_STRIKETHROUGH
},
1169 static const struct drawcall_entry draw_seq5
[] = {
1170 { DRAW_GLYPHRUN
, {'s','t',0} },
1171 { DRAW_GLYPHRUN
, {'r','i',0} },
1172 { DRAW_GLYPHRUN
, {'n','g',0} },
1173 { DRAW_STRIKETHROUGH
},
1177 static void test_Draw(void)
1179 static const WCHAR strW
[] = {'s','t','r','i','n','g',0};
1180 static const WCHAR str2W
[] = {0x202a,0x202c,'a','b',0};
1181 static const WCHAR ruW
[] = {'r','u',0};
1183 IDWriteInlineObject
*inlineobj
;
1184 IDWriteTextFormat
*format
;
1185 IDWriteTextLayout
*layout
;
1186 DWRITE_TEXT_RANGE range
;
1187 IDWriteFactory
*factory
;
1190 factory
= create_factory();
1192 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_BOLD
, DWRITE_FONT_STYLE_NORMAL
,
1193 DWRITE_FONT_STRETCH_NORMAL
, 10.0, ruW
, &format
);
1194 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1196 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 6, format
, 100.0, 100.0, &layout
);
1197 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1199 hr
= IDWriteFactory_CreateEllipsisTrimmingSign(factory
, format
, &inlineobj
);
1200 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1202 range
.startPosition
= 5;
1204 hr
= IDWriteTextLayout_SetStrikethrough(layout
, TRUE
, range
);
1205 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1207 range
.startPosition
= 1;
1209 hr
= IDWriteTextLayout_SetInlineObject(layout
, inlineobj
, range
);
1210 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1212 range
.startPosition
= 4;
1214 hr
= IDWriteTextLayout_SetDrawingEffect(layout
, (IUnknown
*)inlineobj
, range
);
1215 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1217 range
.startPosition
= 0;
1219 hr
= IDWriteTextLayout_SetUnderline(layout
, TRUE
, range
);
1220 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1222 flush_sequence(sequences
, RENDERER_ID
);
1223 hr
= IDWriteTextLayout_Draw(layout
, NULL
, &testrenderer
, 0.0, 0.0);
1224 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1225 ok_sequence(sequences
, RENDERER_ID
, draw_seq
, "draw test", TRUE
);
1226 IDWriteTextLayout_Release(layout
);
1228 /* with reduced width DrawGlyphRun() is called for every line */
1229 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 6, format
, 5.0, 100.0, &layout
);
1230 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1231 flush_sequence(sequences
, RENDERER_ID
);
1232 hr
= IDWriteTextLayout_Draw(layout
, NULL
, &testrenderer
, 0.0, 0.0);
1233 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1234 ok_sequence(sequences
, RENDERER_ID
, draw_seq2
, "draw test 2", TRUE
);
1235 IDWriteTextLayout_Release(layout
);
1237 /* string with control characters */
1238 hr
= IDWriteFactory_CreateTextLayout(factory
, str2W
, 4, format
, 500.0, 100.0, &layout
);
1239 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1240 flush_sequence(sequences
, RENDERER_ID
);
1241 hr
= IDWriteTextLayout_Draw(layout
, NULL
, &testrenderer
, 0.0, 0.0);
1242 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1243 ok_sequence(sequences
, RENDERER_ID
, draw_seq3
, "draw test 3", TRUE
);
1244 IDWriteTextLayout_Release(layout
);
1246 /* strikethrough splits ranges from renderer point of view, but doesn't break
1248 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 6, format
, 500.0, 100.0, &layout
);
1249 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1250 flush_sequence(sequences
, RENDERER_ID
);
1252 range
.startPosition
= 0;
1254 hr
= IDWriteTextLayout_SetStrikethrough(layout
, TRUE
, range
);
1255 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1257 hr
= IDWriteTextLayout_Draw(layout
, NULL
, &testrenderer
, 0.0, 0.0);
1258 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1259 ok_sequence(sequences
, RENDERER_ID
, draw_seq4
, "draw test 4", FALSE
);
1260 IDWriteTextLayout_Release(layout
);
1262 /* strikethrough somewhere in the middle */
1263 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 6, format
, 500.0, 100.0, &layout
);
1264 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1265 flush_sequence(sequences
, RENDERER_ID
);
1267 range
.startPosition
= 2;
1269 hr
= IDWriteTextLayout_SetStrikethrough(layout
, TRUE
, range
);
1270 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1272 hr
= IDWriteTextLayout_Draw(layout
, NULL
, &testrenderer
, 0.0, 0.0);
1273 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1274 ok_sequence(sequences
, RENDERER_ID
, draw_seq5
, "draw test 5", FALSE
);
1275 IDWriteTextLayout_Release(layout
);
1277 IDWriteTextFormat_Release(format
);
1278 IDWriteFactory_Release(factory
);
1281 static void test_typography(void)
1283 DWRITE_FONT_FEATURE feature
;
1284 IDWriteTypography
*typography
;
1285 IDWriteFactory
*factory
;
1289 factory
= create_factory();
1291 hr
= IDWriteFactory_CreateTypography(factory
, &typography
);
1292 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1294 feature
.nameTag
= DWRITE_FONT_FEATURE_TAG_KERNING
;
1295 feature
.parameter
= 1;
1296 hr
= IDWriteTypography_AddFontFeature(typography
, feature
);
1297 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1299 count
= IDWriteTypography_GetFontFeatureCount(typography
);
1300 ok(count
== 1, "got %u\n", count
);
1302 /* duplicated features work just fine */
1303 feature
.nameTag
= DWRITE_FONT_FEATURE_TAG_KERNING
;
1304 feature
.parameter
= 0;
1305 hr
= IDWriteTypography_AddFontFeature(typography
, feature
);
1306 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1308 count
= IDWriteTypography_GetFontFeatureCount(typography
);
1309 ok(count
== 2, "got %u\n", count
);
1311 memset(&feature
, 0, sizeof(feature
));
1312 hr
= IDWriteTypography_GetFontFeature(typography
, 0, &feature
);
1313 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1314 ok(feature
.nameTag
== DWRITE_FONT_FEATURE_TAG_KERNING
, "got tag %x\n", feature
.nameTag
);
1315 ok(feature
.parameter
== 1, "got %u\n", feature
.parameter
);
1317 memset(&feature
, 0, sizeof(feature
));
1318 hr
= IDWriteTypography_GetFontFeature(typography
, 1, &feature
);
1319 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1320 ok(feature
.nameTag
== DWRITE_FONT_FEATURE_TAG_KERNING
, "got tag %x\n", feature
.nameTag
);
1321 ok(feature
.parameter
== 0, "got %u\n", feature
.parameter
);
1323 hr
= IDWriteTypography_GetFontFeature(typography
, 2, &feature
);
1324 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1326 IDWriteTypography_Release(typography
);
1327 IDWriteFactory_Release(factory
);
1330 static void test_GetClusterMetrics(void)
1332 static const WCHAR str2W
[] = {0x202a,0x202c,'a',0};
1333 static const WCHAR strW
[] = {'a','b','c','d',0};
1334 DWRITE_INLINE_OBJECT_METRICS inline_metrics
;
1335 DWRITE_CLUSTER_METRICS metrics
[4];
1336 IDWriteTextLayout1
*layout1
;
1337 IDWriteInlineObject
*trimm
;
1338 IDWriteTextFormat
*format
;
1339 IDWriteTextLayout
*layout
;
1340 DWRITE_TEXT_RANGE range
;
1341 IDWriteFactory
*factory
;
1345 factory
= create_factory();
1347 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
1348 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
1349 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1351 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 1000.0, 1000.0, &layout
);
1352 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1355 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, NULL
, 0, &count
);
1356 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
1357 ok(count
== 4, "got %u\n", count
);
1359 /* check every cluster width */
1361 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, metrics
, sizeof(metrics
)/sizeof(metrics
[0]), &count
);
1362 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1363 ok(count
== 4, "got %u\n", count
);
1364 for (i
= 0; i
< count
; i
++) {
1365 ok(metrics
[i
].width
> 0.0, "%u: got width %.2f\n", i
, metrics
[i
].width
);
1366 ok(metrics
[i
].length
== 1, "%u: got length %u\n", i
, metrics
[i
].length
);
1369 /* apply spacing and check widths again */
1370 if (IDWriteTextLayout_QueryInterface(layout
, &IID_IDWriteTextLayout1
, (void**)&layout1
) == S_OK
) {
1371 DWRITE_CLUSTER_METRICS metrics2
[4];
1372 FLOAT leading
, trailing
, min_advance
;
1373 DWRITE_TEXT_RANGE r
;
1375 leading
= trailing
= min_advance
= 2.0;
1376 hr
= IDWriteTextLayout1_GetCharacterSpacing(layout1
, 0, &leading
, &trailing
,
1377 &min_advance
, NULL
);
1379 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1380 ok(leading
== 0.0 && trailing
== 0.0 && min_advance
== 0.0,
1381 "got %.2f, %.2f, %.2f\n", leading
, trailing
, min_advance
);
1383 r
.startPosition
= 0;
1385 hr
= IDWriteTextLayout1_SetCharacterSpacing(layout1
, 10.0, 15.0, 0.0, r
);
1387 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1390 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, metrics2
, sizeof(metrics2
)/sizeof(metrics2
[0]), &count
);
1391 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1392 ok(count
== 4, "got %u\n", count
);
1393 for (i
= 0; i
< count
; i
++) {
1395 ok(metrics2
[i
].width
> metrics
[i
].width
, "%u: got width %.2f, was %.2f\n", i
, metrics2
[i
].width
,
1397 ok(metrics2
[i
].length
== 1, "%u: got length %u\n", i
, metrics2
[i
].length
);
1400 /* back to defaults */
1401 r
.startPosition
= 0;
1403 hr
= IDWriteTextLayout1_SetCharacterSpacing(layout1
, 0.0, 0.0, 0.0, r
);
1405 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1407 IDWriteTextLayout1_Release(layout1
);
1410 win_skip("IDWriteTextLayout1 is not supported, cluster spacing test skipped.\n");
1412 hr
= IDWriteFactory_CreateEllipsisTrimmingSign(factory
, format
, &trimm
);
1413 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1415 range
.startPosition
= 0;
1417 hr
= IDWriteTextLayout_SetInlineObject(layout
, trimm
, range
);
1418 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1420 /* inline object takes a separate cluster, replaced codepoints number doesn't matter */
1422 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, NULL
, 0, &count
);
1423 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
1424 ok(count
== 3, "got %u\n", count
);
1427 memset(&metrics
, 0, sizeof(metrics
));
1428 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, metrics
, 1, &count
);
1429 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
1430 ok(count
== 3, "got %u\n", count
);
1431 ok(metrics
[0].length
== 2, "got %u\n", metrics
[0].length
);
1433 hr
= IDWriteInlineObject_GetMetrics(trimm
, &inline_metrics
);
1434 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1436 ok(inline_metrics
.width
> 0.0 && inline_metrics
.width
== metrics
[0].width
, "got %.2f, expected %.2f\n",
1437 inline_metrics
.width
, metrics
[0].width
);
1439 IDWriteTextLayout_Release(layout
);
1441 /* text with non-visual control codes */
1442 hr
= IDWriteFactory_CreateTextLayout(factory
, str2W
, 3, format
, 1000.0, 1000.0, &layout
);
1443 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1445 /* bidi control codes take a separate cluster */
1447 memset(metrics
, 0, sizeof(metrics
));
1448 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, metrics
, 3, &count
);
1449 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1450 ok(count
== 3, "got %u\n", count
);
1452 ok(metrics
[0].width
== 0.0, "got %.2f\n", metrics
[0].width
);
1453 ok(metrics
[0].length
== 1, "got %d\n", metrics
[0].length
);
1454 ok(metrics
[0].canWrapLineAfter
== 0, "got %d\n", metrics
[0].canWrapLineAfter
);
1455 ok(metrics
[0].isWhitespace
== 0, "got %d\n", metrics
[0].isWhitespace
);
1456 ok(metrics
[0].isNewline
== 0, "got %d\n", metrics
[0].isNewline
);
1457 ok(metrics
[0].isSoftHyphen
== 0, "got %d\n", metrics
[0].isSoftHyphen
);
1458 ok(metrics
[0].isRightToLeft
== 0, "got %d\n", metrics
[0].isRightToLeft
);
1460 ok(metrics
[1].width
== 0.0, "got %.2f\n", metrics
[1].width
);
1461 ok(metrics
[1].length
== 1, "got %d\n", metrics
[1].length
);
1462 ok(metrics
[1].canWrapLineAfter
== 0, "got %d\n", metrics
[1].canWrapLineAfter
);
1463 ok(metrics
[1].isWhitespace
== 0, "got %d\n", metrics
[1].isWhitespace
);
1464 ok(metrics
[1].isNewline
== 0, "got %d\n", metrics
[1].isNewline
);
1465 ok(metrics
[1].isSoftHyphen
== 0, "got %d\n", metrics
[1].isSoftHyphen
);
1466 ok(metrics
[1].isRightToLeft
== 0, "got %d\n", metrics
[1].isRightToLeft
);
1468 ok(metrics
[2].width
> 0.0, "got %.2f\n", metrics
[2].width
);
1469 ok(metrics
[2].length
== 1, "got %d\n", metrics
[2].length
);
1471 ok(metrics
[2].canWrapLineAfter
== 1, "got %d\n", metrics
[2].canWrapLineAfter
);
1472 ok(metrics
[2].isWhitespace
== 0, "got %d\n", metrics
[2].isWhitespace
);
1473 ok(metrics
[2].isNewline
== 0, "got %d\n", metrics
[2].isNewline
);
1474 ok(metrics
[2].isSoftHyphen
== 0, "got %d\n", metrics
[2].isSoftHyphen
);
1475 ok(metrics
[2].isRightToLeft
== 0, "got %d\n", metrics
[2].isRightToLeft
);
1477 IDWriteTextLayout_Release(layout
);
1479 /* single inline object that fails to report its metrics */
1480 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 1000.0, 1000.0, &layout
);
1481 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1483 range
.startPosition
= 0;
1485 hr
= IDWriteTextLayout_SetInlineObject(layout
, &testinlineobj
, range
);
1486 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1489 memset(metrics
, 0, sizeof(metrics
));
1490 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, metrics
, 3, &count
);
1491 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1492 ok(count
== 1, "got %u\n", count
);
1494 /* object sets a width to 123.0, but returns failure from GetMetrics() */
1495 ok(metrics
[0].width
== 0.0, "got %.2f\n", metrics
[0].width
);
1496 ok(metrics
[0].length
== 4, "got %d\n", metrics
[0].length
);
1498 ok(metrics
[0].canWrapLineAfter
== 1, "got %d\n", metrics
[0].canWrapLineAfter
);
1499 ok(metrics
[0].isWhitespace
== 0, "got %d\n", metrics
[0].isWhitespace
);
1500 ok(metrics
[0].isNewline
== 0, "got %d\n", metrics
[0].isNewline
);
1501 ok(metrics
[0].isSoftHyphen
== 0, "got %d\n", metrics
[0].isSoftHyphen
);
1502 ok(metrics
[0].isRightToLeft
== 0, "got %d\n", metrics
[0].isRightToLeft
);
1504 /* now set two inline object for [0,1] and [2,3], both fail to report break conditions */
1505 range
.startPosition
= 2;
1507 hr
= IDWriteTextLayout_SetInlineObject(layout
, &testinlineobj2
, range
);
1508 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1511 memset(metrics
, 0, sizeof(metrics
));
1512 hr
= IDWriteTextLayout_GetClusterMetrics(layout
, metrics
, 3, &count
);
1513 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1514 ok(count
== 2, "got %u\n", count
);
1516 ok(metrics
[0].width
== 0.0, "got %.2f\n", metrics
[0].width
);
1517 ok(metrics
[0].length
== 2, "got %d\n", metrics
[0].length
);
1518 ok(metrics
[0].canWrapLineAfter
== 0, "got %d\n", metrics
[0].canWrapLineAfter
);
1519 ok(metrics
[0].isWhitespace
== 0, "got %d\n", metrics
[0].isWhitespace
);
1520 ok(metrics
[0].isNewline
== 0, "got %d\n", metrics
[0].isNewline
);
1521 ok(metrics
[0].isSoftHyphen
== 0, "got %d\n", metrics
[0].isSoftHyphen
);
1522 ok(metrics
[0].isRightToLeft
== 0, "got %d\n", metrics
[0].isRightToLeft
);
1524 ok(metrics
[1].width
== 0.0, "got %.2f\n", metrics
[1].width
);
1525 ok(metrics
[1].length
== 2, "got %d\n", metrics
[1].length
);
1527 ok(metrics
[1].canWrapLineAfter
== 1, "got %d\n", metrics
[1].canWrapLineAfter
);
1528 ok(metrics
[1].isWhitespace
== 0, "got %d\n", metrics
[1].isWhitespace
);
1529 ok(metrics
[1].isNewline
== 0, "got %d\n", metrics
[1].isNewline
);
1530 ok(metrics
[1].isSoftHyphen
== 0, "got %d\n", metrics
[1].isSoftHyphen
);
1531 ok(metrics
[1].isRightToLeft
== 0, "got %d\n", metrics
[1].isRightToLeft
);
1533 IDWriteTextLayout_Release(layout
);
1535 IDWriteInlineObject_Release(trimm
);
1536 IDWriteTextFormat_Release(format
);
1537 IDWriteFactory_Release(factory
);
1540 static void test_SetLocaleName(void)
1542 static const WCHAR strW
[] = {'a','b','c','d',0};
1543 WCHAR buffW
[LOCALE_NAME_MAX_LENGTH
+sizeof(strW
)/sizeof(WCHAR
)];
1544 IDWriteTextFormat
*format
;
1545 IDWriteTextLayout
*layout
;
1546 DWRITE_TEXT_RANGE range
;
1547 IDWriteFactory
*factory
;
1550 factory
= create_factory();
1552 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
1553 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
1554 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1556 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 1000.0, 1000.0, &layout
);
1557 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1559 range
.startPosition
= 0;
1561 hr
= IDWriteTextLayout_SetLocaleName(layout
, enusW
, range
);
1562 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1564 hr
= IDWriteTextLayout_SetLocaleName(layout
, NULL
, range
);
1565 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1567 /* invalid locale name is allowed */
1568 hr
= IDWriteTextLayout_SetLocaleName(layout
, strW
, range
);
1569 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1571 hr
= IDWriteTextLayout_GetLocaleName(layout
, 0, NULL
, 0, NULL
);
1572 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1574 if (0) /* crashes on native */
1575 hr
= IDWriteTextLayout_GetLocaleName(layout
, 0, NULL
, 1, NULL
);
1578 hr
= IDWriteTextLayout_GetLocaleName(layout
, 0, buffW
, sizeof(buffW
)/sizeof(WCHAR
), NULL
);
1579 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1580 ok(!lstrcmpW(buffW
, strW
), "got %s\n", wine_dbgstr_w(buffW
));
1582 /* get with a shorter buffer */
1584 hr
= IDWriteTextLayout_GetLocaleName(layout
, 0, buffW
, 1, NULL
);
1585 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
1586 ok(buffW
[0] == 0, "got %x\n", buffW
[0]);
1588 /* name is too long */
1589 lstrcpyW(buffW
, strW
);
1590 while (lstrlenW(buffW
) <= LOCALE_NAME_MAX_LENGTH
)
1591 lstrcatW(buffW
, strW
);
1593 range
.startPosition
= 0;
1595 hr
= IDWriteTextLayout_SetLocaleName(layout
, buffW
, range
);
1596 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1599 hr
= IDWriteTextLayout_GetLocaleName(layout
, 0, buffW
, sizeof(buffW
)/sizeof(WCHAR
), NULL
);
1600 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1601 ok(!lstrcmpW(buffW
, strW
), "got %s\n", wine_dbgstr_w(buffW
));
1603 IDWriteTextLayout_Release(layout
);
1604 IDWriteTextFormat_Release(format
);
1605 IDWriteFactory_Release(factory
);
1608 static void test_SetPairKerning(void)
1610 static const WCHAR strW
[] = {'a','b','c','d',0};
1611 IDWriteTextLayout1
*layout1
;
1612 IDWriteTextFormat
*format
;
1613 IDWriteTextLayout
*layout
;
1614 DWRITE_TEXT_RANGE range
;
1615 IDWriteFactory
*factory
;
1619 factory
= create_factory();
1621 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
1622 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
1623 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1625 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 1000.0, 1000.0, &layout
);
1626 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1627 IDWriteTextFormat_Release(format
);
1629 hr
= IDWriteTextLayout_QueryInterface(layout
, &IID_IDWriteTextLayout1
, (void**)&layout1
);
1630 IDWriteTextLayout_Release(layout
);
1633 win_skip("SetPairKerning() is not supported.\n");
1634 IDWriteFactory_Release(factory
);
1638 if (0) { /* crashes on native */
1639 hr
= IDWriteTextLayout1_GetPairKerning(layout1
, 0, NULL
, NULL
);
1640 hr
= IDWriteTextLayout1_GetPairKerning(layout1
, 0, NULL
, &range
);
1643 hr
= IDWriteTextLayout1_GetPairKerning(layout1
, 0, &kerning
, NULL
);
1644 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1646 range
.startPosition
= 0;
1649 hr
= IDWriteTextLayout1_GetPairKerning(layout1
, 0, &kerning
, &range
);
1650 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1651 ok(!kerning
, "got %d\n", kerning
);
1653 range
.startPosition
= 0;
1655 hr
= IDWriteTextLayout1_SetPairKerning(layout1
, 2, range
);
1656 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1659 hr
= IDWriteTextLayout1_GetPairKerning(layout1
, 0, &kerning
, &range
);
1660 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1661 ok(kerning
== TRUE
, "got %d\n", kerning
);
1663 IDWriteTextLayout1_Release(layout1
);
1664 IDWriteFactory_Release(factory
);
1667 static void test_SetVerticalGlyphOrientation(void)
1669 static const WCHAR strW
[] = {'a','b','c','d',0};
1670 DWRITE_VERTICAL_GLYPH_ORIENTATION orientation
;
1671 IDWriteTextLayout2
*layout2
;
1672 IDWriteTextFormat
*format
;
1673 IDWriteTextLayout
*layout
;
1674 IDWriteFactory
*factory
;
1677 factory
= create_factory();
1679 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
1680 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
1681 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1683 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 1000.0, 1000.0, &layout
);
1684 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1685 IDWriteTextFormat_Release(format
);
1687 hr
= IDWriteTextLayout_QueryInterface(layout
, &IID_IDWriteTextLayout2
, (void**)&layout2
);
1688 IDWriteTextLayout_Release(layout
);
1691 win_skip("SetVerticalGlyphOrientation() is not supported.\n");
1692 IDWriteFactory_Release(factory
);
1696 orientation
= IDWriteTextLayout2_GetVerticalGlyphOrientation(layout2
);
1697 ok(orientation
== DWRITE_VERTICAL_GLYPH_ORIENTATION_DEFAULT
, "got %d\n", orientation
);
1699 hr
= IDWriteTextLayout2_SetVerticalGlyphOrientation(layout2
, DWRITE_VERTICAL_GLYPH_ORIENTATION_STACKED
+1);
1700 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1702 IDWriteTextLayout2_Release(layout2
);
1703 IDWriteFactory_Release(factory
);
1706 static void test_fallback(void)
1708 static const WCHAR strW
[] = {'a','b','c','d',0};
1709 IDWriteFontFallback
*fallback
, *fallback2
;
1710 IDWriteTextLayout2
*layout2
;
1711 IDWriteTextFormat1
*format1
;
1712 IDWriteTextFormat
*format
;
1713 IDWriteTextLayout
*layout
;
1714 IDWriteFactory2
*factory2
;
1715 IDWriteFactory
*factory
;
1718 factory
= create_factory();
1720 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
1721 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
1722 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1724 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 1000.0, 1000.0, &layout
);
1725 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1726 IDWriteTextFormat_Release(format
);
1728 hr
= IDWriteTextLayout_QueryInterface(layout
, &IID_IDWriteTextLayout2
, (void**)&layout2
);
1729 IDWriteTextLayout_Release(layout
);
1732 win_skip("GetFontFallback() is not supported.\n");
1733 IDWriteFactory_Release(factory
);
1737 if (0) /* crashes on native */
1738 hr
= IDWriteTextLayout2_GetFontFallback(layout2
, NULL
);
1740 fallback
= (void*)0xdeadbeef;
1741 hr
= IDWriteTextLayout2_GetFontFallback(layout2
, &fallback
);
1742 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1743 ok(fallback
== NULL
, "got %p\n", fallback
);
1745 hr
= IDWriteTextLayout2_QueryInterface(layout2
, &IID_IDWriteTextFormat1
, (void**)&format1
);
1746 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1748 fallback
= (void*)0xdeadbeef;
1749 hr
= IDWriteTextFormat1_GetFontFallback(format1
, &fallback
);
1750 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1751 ok(fallback
== NULL
, "got %p\n", fallback
);
1753 hr
= IDWriteFactory_QueryInterface(factory
, &IID_IDWriteFactory2
, (void**)&factory2
);
1754 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1757 hr
= IDWriteFactory2_GetSystemFontFallback(factory2
, &fallback
);
1759 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1761 ok(fallback
!= NULL
, "got %p\n", fallback
);
1763 hr
= IDWriteTextFormat1_SetFontFallback(format1
, fallback
);
1764 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1766 fallback2
= (void*)0xdeadbeef;
1767 hr
= IDWriteTextLayout2_GetFontFallback(layout2
, &fallback2
);
1768 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1769 ok(fallback2
== fallback
, "got %p\n", fallback2
);
1771 hr
= IDWriteTextLayout2_SetFontFallback(layout2
, NULL
);
1772 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1774 fallback2
= (void*)0xdeadbeef;
1775 hr
= IDWriteTextFormat1_GetFontFallback(format1
, &fallback2
);
1776 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1777 ok(fallback2
== NULL
, "got %p\n", fallback2
);
1779 IDWriteFontFallback_Release(fallback
);
1781 IDWriteTextFormat1_Release(format1
);
1782 IDWriteTextLayout2_Release(layout2
);
1783 IDWriteFactory_Release(factory
);
1786 static void test_DetermineMinWidth(void)
1788 static const WCHAR strW
[] = {'a','b','c','d',0};
1789 IDWriteTextFormat
*format
;
1790 IDWriteTextLayout
*layout
;
1791 IDWriteFactory
*factory
;
1795 factory
= create_factory();
1797 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
1798 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
1799 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1801 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, lstrlenW(strW
), format
, 1000.0, 1000.0, &layout
);
1802 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1804 hr
= IDWriteTextLayout_DetermineMinWidth(layout
, NULL
);
1805 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1808 hr
= IDWriteTextLayout_DetermineMinWidth(layout
, &minwidth
);
1809 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1810 ok(minwidth
> 0.0, "got %.2f\n", minwidth
);
1812 IDWriteTextLayout_Release(layout
);
1813 IDWriteTextFormat_Release(format
);
1816 static void test_SetFontSize(void)
1818 static const WCHAR strW
[] = {'a','b','c','d',0};
1819 IDWriteTextFormat
*format
;
1820 IDWriteTextLayout
*layout
;
1821 IDWriteFactory
*factory
;
1822 DWRITE_TEXT_RANGE r
;
1826 factory
= create_factory();
1828 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
1829 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
1830 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1832 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 1000.0, 1000.0, &layout
);
1833 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1835 r
.startPosition
= 1;
1838 hr
= IDWriteTextLayout_GetFontSize(layout
, 0, &size
, &r
);
1839 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1840 ok(r
.startPosition
== 0 && r
.length
== ~0u, "got %u, %u\n", r
.startPosition
, r
.length
);
1841 ok(size
== 10.0, "got %.2f\n", size
);
1843 r
.startPosition
= 1;
1845 hr
= IDWriteTextLayout_SetFontSize(layout
, 15.0, r
);
1846 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1849 hr
= IDWriteTextLayout_GetFontSize(layout
, 1, &size
, &r
);
1850 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1851 ok(size
== 15.0, "got %.2f\n", size
);
1853 r
.startPosition
= 0;
1855 hr
= IDWriteTextLayout_SetFontSize(layout
, 15.0, r
);
1856 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1859 hr
= IDWriteTextLayout_GetFontSize(layout
, 1, &size
, &r
);
1860 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1861 ok(size
== 15.0, "got %.2f\n", size
);
1864 hr
= IDWriteTextLayout_GetFontSize(layout
, 0, &size
, &r
);
1865 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1866 ok(r
.startPosition
== 0 && r
.length
== 4, "got %u, %u\n", r
.startPosition
, r
.length
);
1867 ok(size
== 15.0, "got %.2f\n", size
);
1870 r
.startPosition
= r
.length
= 0;
1871 hr
= IDWriteTextLayout_GetFontSize(layout
, 20, &size
, &r
);
1872 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1873 ok(r
.startPosition
== 4 && r
.length
== ~0u-4, "got %u, %u\n", r
.startPosition
, r
.length
);
1874 ok(size
== 10.0, "got %.2f\n", size
);
1876 r
.startPosition
= 100;
1878 hr
= IDWriteTextLayout_SetFontSize(layout
, 25.0, r
);
1879 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1882 r
.startPosition
= r
.length
= 0;
1883 hr
= IDWriteTextLayout_GetFontSize(layout
, 100, &size
, &r
);
1884 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1885 ok(r
.startPosition
== 100 && r
.length
== 4, "got %u, %u\n", r
.startPosition
, r
.length
);
1886 ok(size
== 25.0, "got %.2f\n", size
);
1888 IDWriteTextLayout_Release(layout
);
1889 IDWriteTextFormat_Release(format
);
1892 static void test_SetFontFamilyName(void)
1894 static const WCHAR arialW
[] = {'A','r','i','a','l',0};
1895 static const WCHAR strW
[] = {'a','b','c','d',0};
1896 IDWriteTextFormat
*format
;
1897 IDWriteTextLayout
*layout
;
1898 IDWriteFactory
*factory
;
1899 DWRITE_TEXT_RANGE r
;
1903 factory
= create_factory();
1905 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
1906 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
1907 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1909 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 1000.0, 1000.0, &layout
);
1910 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1912 r
.startPosition
= 1;
1915 hr
= IDWriteTextLayout_GetFontFamilyName(layout
, 1, nameW
, sizeof(nameW
)/sizeof(WCHAR
), &r
);
1916 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1917 ok(r
.startPosition
== 0 && r
.length
== ~0u, "got %u, %u\n", r
.startPosition
, r
.length
);
1919 r
.startPosition
= 1;
1921 hr
= IDWriteTextLayout_SetFontFamilyName(layout
, arialW
, r
);
1922 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1924 r
.startPosition
= 1;
1926 hr
= IDWriteTextLayout_GetFontFamilyName(layout
, 1, nameW
, sizeof(nameW
)/sizeof(WCHAR
), &r
);
1927 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1928 ok(r
.startPosition
== 1 && r
.length
== 1, "got %u, %u\n", r
.startPosition
, r
.length
);
1930 r
.startPosition
= 0;
1932 hr
= IDWriteTextLayout_SetFontFamilyName(layout
, arialW
, r
);
1933 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1936 hr
= IDWriteTextLayout_GetFontFamilyName(layout
, 1, nameW
, sizeof(nameW
)/sizeof(WCHAR
), &r
);
1937 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1938 ok(r
.startPosition
== 0 && r
.length
== 4, "got %u, %u\n", r
.startPosition
, r
.length
);
1939 ok(!lstrcmpW(nameW
, arialW
), "got name %s\n", wine_dbgstr_w(nameW
));
1941 IDWriteTextLayout_Release(layout
);
1942 IDWriteTextFormat_Release(format
);
1945 static void test_SetFontStyle(void)
1947 static const WCHAR strW
[] = {'a','b','c','d',0};
1948 IDWriteTextFormat
*format
;
1949 IDWriteTextLayout
*layout
;
1950 IDWriteFactory
*factory
;
1951 DWRITE_FONT_STYLE style
;
1952 DWRITE_TEXT_RANGE r
;
1955 factory
= create_factory();
1957 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
1958 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
1959 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1961 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 1000.0, 1000.0, &layout
);
1962 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1964 r
.startPosition
= 1;
1966 hr
= IDWriteTextLayout_GetFontStyle(layout
, 0, &style
, &r
);
1967 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1968 ok(r
.startPosition
== 0 && r
.length
== ~0u, "got %u, %u\n", r
.startPosition
, r
.length
);
1969 ok(style
== DWRITE_FONT_STYLE_NORMAL
, "got %d\n", style
);
1971 r
.startPosition
= 1;
1973 hr
= IDWriteTextLayout_SetFontStyle(layout
, DWRITE_FONT_STYLE_ITALIC
, r
);
1974 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1976 style
= DWRITE_FONT_STYLE_NORMAL
;
1977 hr
= IDWriteTextLayout_GetFontStyle(layout
, 1, &style
, &r
);
1978 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1979 ok(style
== DWRITE_FONT_STYLE_ITALIC
, "got %d\n", style
);
1981 r
.startPosition
= 0;
1983 hr
= IDWriteTextLayout_SetFontStyle(layout
, DWRITE_FONT_STYLE_OBLIQUE
, r
);
1984 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1986 style
= DWRITE_FONT_STYLE_ITALIC
;
1987 hr
= IDWriteTextLayout_GetFontStyle(layout
, 1, &style
, &r
);
1988 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1989 ok(style
== DWRITE_FONT_STYLE_OBLIQUE
, "got %d\n", style
);
1991 style
= DWRITE_FONT_STYLE_ITALIC
;
1992 hr
= IDWriteTextLayout_GetFontStyle(layout
, 0, &style
, &r
);
1993 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1994 ok(r
.startPosition
== 0 && r
.length
== 4, "got %u, %u\n", r
.startPosition
, r
.length
);
1995 ok(style
== DWRITE_FONT_STYLE_OBLIQUE
, "got %d\n", style
);
1997 style
= DWRITE_FONT_STYLE_ITALIC
;
1998 r
.startPosition
= r
.length
= 0;
1999 hr
= IDWriteTextLayout_GetFontStyle(layout
, 20, &style
, &r
);
2000 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2001 ok(r
.startPosition
== 4 && r
.length
== ~0u-4, "got %u, %u\n", r
.startPosition
, r
.length
);
2002 ok(style
== DWRITE_FONT_STYLE_NORMAL
, "got %d\n", style
);
2004 r
.startPosition
= 100;
2006 hr
= IDWriteTextLayout_SetFontStyle(layout
, DWRITE_FONT_STYLE_OBLIQUE
, r
);
2007 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2009 style
= DWRITE_FONT_STYLE_NORMAL
;
2010 r
.startPosition
= r
.length
= 0;
2011 hr
= IDWriteTextLayout_GetFontStyle(layout
, 100, &style
, &r
);
2012 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2013 ok(r
.startPosition
== 100 && r
.length
== 4, "got %u, %u\n", r
.startPosition
, r
.length
);
2014 ok(style
== DWRITE_FONT_STYLE_OBLIQUE
, "got %d\n", style
);
2016 IDWriteTextLayout_Release(layout
);
2017 IDWriteTextFormat_Release(format
);
2020 static void test_SetFontStretch(void)
2022 static const WCHAR strW
[] = {'a','b','c','d',0};
2023 DWRITE_FONT_STRETCH stretch
;
2024 IDWriteTextFormat
*format
;
2025 IDWriteTextLayout
*layout
;
2026 IDWriteFactory
*factory
;
2027 DWRITE_TEXT_RANGE r
;
2030 factory
= create_factory();
2032 hr
= IDWriteFactory_CreateTextFormat(factory
, tahomaW
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL
,
2033 DWRITE_FONT_STRETCH_NORMAL
, 10.0, enusW
, &format
);
2034 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2036 hr
= IDWriteFactory_CreateTextLayout(factory
, strW
, 4, format
, 1000.0, 1000.0, &layout
);
2037 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2039 r
.startPosition
= 1;
2041 stretch
= DWRITE_FONT_STRETCH_UNDEFINED
;
2042 hr
= IDWriteTextLayout_GetFontStretch(layout
, 0, &stretch
, &r
);
2043 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2044 ok(r
.startPosition
== 0 && r
.length
== ~0u, "got %u, %u\n", r
.startPosition
, r
.length
);
2045 ok(stretch
== DWRITE_FONT_STRETCH_NORMAL
, "got %d\n", stretch
);
2047 r
.startPosition
= 1;
2049 hr
= IDWriteTextLayout_SetFontStretch(layout
, DWRITE_FONT_STRETCH_CONDENSED
, r
);
2050 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2052 stretch
= DWRITE_FONT_STRETCH_UNDEFINED
;
2053 hr
= IDWriteTextLayout_GetFontStretch(layout
, 1, &stretch
, &r
);
2054 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2055 ok(stretch
== DWRITE_FONT_STRETCH_CONDENSED
, "got %d\n", stretch
);
2057 r
.startPosition
= 0;
2059 hr
= IDWriteTextLayout_SetFontStretch(layout
, DWRITE_FONT_STRETCH_EXPANDED
, r
);
2060 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2062 stretch
= DWRITE_FONT_STRETCH_UNDEFINED
;
2063 hr
= IDWriteTextLayout_GetFontStretch(layout
, 1, &stretch
, &r
);
2064 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2065 ok(stretch
== DWRITE_FONT_STRETCH_EXPANDED
, "got %d\n", stretch
);
2067 stretch
= DWRITE_FONT_STRETCH_UNDEFINED
;
2068 hr
= IDWriteTextLayout_GetFontStretch(layout
, 0, &stretch
, &r
);
2069 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2070 ok(r
.startPosition
== 0 && r
.length
== 4, "got %u, %u\n", r
.startPosition
, r
.length
);
2071 ok(stretch
== DWRITE_FONT_STRETCH_EXPANDED
, "got %d\n", stretch
);
2073 stretch
= DWRITE_FONT_STRETCH_UNDEFINED
;
2074 r
.startPosition
= r
.length
= 0;
2075 hr
= IDWriteTextLayout_GetFontStretch(layout
, 20, &stretch
, &r
);
2076 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2077 ok(r
.startPosition
== 4 && r
.length
== ~0u-4, "got %u, %u\n", r
.startPosition
, r
.length
);
2078 ok(stretch
== DWRITE_FONT_STRETCH_NORMAL
, "got %d\n", stretch
);
2080 r
.startPosition
= 100;
2082 hr
= IDWriteTextLayout_SetFontStretch(layout
, DWRITE_FONT_STRETCH_EXPANDED
, r
);
2083 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2085 stretch
= DWRITE_FONT_STRETCH_UNDEFINED
;
2086 r
.startPosition
= r
.length
= 0;
2087 hr
= IDWriteTextLayout_GetFontStretch(layout
, 100, &stretch
, &r
);
2088 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2089 ok(r
.startPosition
== 100 && r
.length
== 4, "got %u, %u\n", r
.startPosition
, r
.length
);
2090 ok(stretch
== DWRITE_FONT_STRETCH_EXPANDED
, "got %d\n", stretch
);
2092 /* trying to set undefined value */
2093 r
.startPosition
= 0;
2095 hr
= IDWriteTextLayout_SetFontStretch(layout
, DWRITE_FONT_STRETCH_UNDEFINED
, r
);
2097 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
2099 IDWriteTextLayout_Release(layout
);
2100 IDWriteTextFormat_Release(format
);
2105 static const WCHAR ctrlstrW
[] = {0x202a,0};
2106 IDWriteFactory
*factory
;
2108 if (!(factory
= create_factory())) {
2109 win_skip("failed to create factory\n");
2113 /* actual script ids are not fixed */
2114 get_script_analysis(ctrlstrW
, 1, &g_control_sa
);
2116 init_call_sequences(sequences
, NUM_CALL_SEQUENCES
);
2117 init_call_sequences(expected_seq
, 1);
2119 test_CreateTextLayout();
2120 test_CreateGdiCompatibleTextLayout();
2121 test_CreateTextFormat();
2122 test_GetLocaleName();
2123 test_CreateEllipsisTrimmingSign();
2125 test_SetInlineObject();
2128 test_GetClusterMetrics();
2129 test_SetLocaleName();
2130 test_SetPairKerning();
2131 test_SetVerticalGlyphOrientation();
2133 test_DetermineMinWidth();
2135 test_SetFontFamilyName();
2136 test_SetFontStyle();
2137 test_SetFontStretch();
2139 IDWriteFactory_Release(factory
);