ReactOS 0.4.17-dev-970-gcf0f1a6
layout.c
Go to the documentation of this file.
1/*
2 * Text layout/format tests
3 *
4 * Copyright 2012, 2014-2020 Nikolay Sivov for CodeWeavers
5 *
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.
10 *
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.
15 *
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
19 */
20
21#define COBJMACROS
22
23#include <assert.h>
24#include <math.h>
25#include <limits.h>
26
27#include "windows.h"
28#include "dwrite_3.h"
29
30#include "wine/test.h"
31
33{
36
39};
40
42{
44}
45
47{
48 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFontFileEnumerator))
49 {
50 *obj = iface;
51 IDWriteFontFileEnumerator_AddRef(iface);
52 return S_OK;
53 }
54 return E_NOINTERFACE;
55}
56
58{
60 return InterlockedIncrement(&enumerator->refcount);
61}
62
64{
67
68 if (!refcount)
69 {
70 IDWriteFontFile_Release(enumerator->file);
71 free(enumerator);
72 }
73
74 return refcount;
75}
76
79{
81
82#ifdef __REACTOS__
83 *file = enumerator->file;
84 IDWriteFontFile_AddRef(*file);
85#else
86 IDWriteFontFile_AddRef((*file = enumerator->file));
87#endif
88
89 return S_OK;
90}
91
93{
95
96 if (enumerator->index > 1)
97 {
98 *current = FALSE;
99 return S_OK;
100 }
101
102 enumerator->index++;
103 *current = TRUE;
104 return S_OK;
105}
106
107static const struct IDWriteFontFileEnumeratorVtbl singlefontfileenumeratorvtbl =
108{
114};
115
117{
118 struct test_fontenumerator *enumerator;
119
120 if (!(enumerator = calloc(1, sizeof(*enumerator))))
121 return E_OUTOFMEMORY;
122
124 enumerator->refcount = 1;
125 enumerator->index = 0;
126 enumerator->file = file;
127 IDWriteFontFile_AddRef(file);
128
129 *ret = &enumerator->IDWriteFontFileEnumerator_iface;
130 return S_OK;
131}
132
134{
137
138 void *data;
139 DWORD size;
140};
141
143{
145}
146
148{
149 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFontFileStream))
150 {
151 *obj = iface;
152 IDWriteFontFileStream_AddRef(iface);
153 return S_OK;
154 }
155 *obj = NULL;
156 return E_NOINTERFACE;
157}
158
160{
162 return InterlockedIncrement(&stream->refcount);
163}
164
166{
169
170 if (!refcount)
171 free(stream);
172
173 return refcount;
174}
175
176static HRESULT WINAPI fontdatastream_ReadFileFragment(IDWriteFontFileStream *iface, void const **fragment_start,
177 UINT64 offset, UINT64 fragment_size, void **fragment_context)
178{
180
181 *fragment_context = NULL;
182
183 if (offset + fragment_size > stream->size)
184 {
185 *fragment_start = NULL;
186 return E_FAIL;
187 }
188 else
189 {
190 *fragment_start = (BYTE *)stream->data + offset;
191 return S_OK;
192 }
193}
194
195static void WINAPI fontdatastream_ReleaseFileFragment(IDWriteFontFileStream *iface, void *fragment_context)
196{
197}
198
200{
202 *size = stream->size;
203 return S_OK;
204}
205
207{
208 return E_NOTIMPL;
209}
210
211static const IDWriteFontFileStreamVtbl fontdatastreamvtbl =
212{
220};
221
223{
225
226 if (!(object = calloc(1, sizeof(*object))))
227 return E_OUTOFMEMORY;
228
229 object->IDWriteFontFileStream_iface.lpVtbl = &fontdatastreamvtbl;
230 object->refcount = 1;
231 object->data = data;
232 object->size = size;
233
234 *iface = &object->IDWriteFontFileStream_iface;
235
236 return S_OK;
237}
238
240{
243};
244
246{
248}
249
251{
252 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFontFileLoader))
253 {
254 *obj = iface;
255 return S_OK;
256 }
257 *obj = NULL;
258 return E_NOINTERFACE;
259}
260
262{
264 return InterlockedIncrement(&loader->refcount);
265}
266
268{
271
272 if (!refcount)
273 free(loader);
274
275 return refcount;
276}
277
280{
281 LPVOID data;
282 DWORD size;
283 HGLOBAL mem;
284
285 mem = LoadResource(GetModuleHandleA(NULL), *(HRSRC*)ref_key);
286 ok(mem != NULL, "Failed to lock font resource\n");
287 if (mem)
288 {
289 size = SizeofResource(GetModuleHandleA(NULL), *(HRSRC*)ref_key);
292 }
293 return E_FAIL;
294}
295
296static const struct IDWriteFontFileLoaderVtbl resourcefontfileloadervtbl =
297{
302};
303
305{
307
308 object = calloc(1, sizeof(*object));
309
310 object->IDWriteFontFileLoader_iface.lpVtbl = &resourcefontfileloadervtbl;
311 object->refcount = 1;
312
313 return &object->IDWriteFontFileLoader_iface;
314}
315
317{
321};
322
324{
326}
327
329{
330 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFontCollectionLoader))
331 {
332 *obj = iface;
333 IDWriteFontCollectionLoader_AddRef(iface);
334 return S_OK;
335 }
336
337 return E_NOINTERFACE;
338}
339
341{
343 return InterlockedIncrement(&loader->refcount);
344}
345
347{
350
351 if (!refcount)
352 {
353 IDWriteFontFileLoader_Release(loader->loader);
354 free(loader);
355 }
356
357 return refcount;
358}
359
361 IDWriteFactory *factory, const void *key, UINT32 key_size, IDWriteFontFileEnumerator **enumerator)
362{
364 IDWriteFontFile *font_file;
365 HRESULT hr;
366
367 hr = IDWriteFactory_CreateCustomFontFileReference(factory, key, key_size, loader->loader, &font_file);
368 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
369
370 hr = create_enumerator(font_file, enumerator);
371 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
372
373 IDWriteFontFile_Release(font_file);
374 return hr;
375}
376
377static const struct IDWriteFontCollectionLoaderVtbl resourcecollectionloadervtbl =
378{
383};
384
386{
388
389 object = calloc(1, sizeof(*object));
390 object->IDWriteFontCollectionLoader_iface.lpVtbl = &resourcecollectionloadervtbl;
391 object->refcount = 1;
392 object->loader = loader;
393 IDWriteFontFileLoader_AddRef(object->loader);
394
395 return &object->IDWriteFontCollectionLoader_iface;
396}
397
399{
401 DWRITE_SCRIPT_ANALYSIS sa; /* last analysis, with SetScriptAnalysis() */
402};
403
405{
407}
408
409/* test IDWriteTextAnalysisSink */
411{
412 if (IsEqualIID(riid, &IID_IDWriteTextAnalysisSink) || IsEqualIID(riid, &IID_IUnknown))
413 {
414 *obj = iface;
415 return S_OK;
416 }
417
418 *obj = NULL;
419 return E_NOINTERFACE;
420}
421
423{
424 return 2;
425}
426
428{
429 return 1;
430}
431
433 UINT32 position, UINT32 length, DWRITE_SCRIPT_ANALYSIS const* sa)
434{
436 sink->sa = *sa;
437 return S_OK;
438}
439
441 UINT32 position, UINT32 length, DWRITE_LINE_BREAKPOINT const* breakpoints)
442{
443 ok(0, "unexpected call\n");
444 return E_NOTIMPL;
445}
446
448 UINT32 position, UINT32 length, UINT8 explicitLevel, UINT8 resolvedLevel)
449{
450 ok(0, "unexpected\n");
451 return E_NOTIMPL;
452}
453
455 UINT32 position, UINT32 length, IDWriteNumberSubstitution* substitution)
456{
457 ok(0, "unexpected\n");
458 return E_NOTIMPL;
459}
460
461static IDWriteTextAnalysisSinkVtbl analysissinkvtbl = {
469};
470
472 { &analysissinkvtbl },
473 { 0 }
474};
475
476/* test IDWriteTextAnalysisSource */
478 REFIID riid, void **obj)
479{
480 if (IsEqualIID(riid, &IID_IDWriteTextAnalysisSource) || IsEqualIID(riid, &IID_IUnknown)) {
481 *obj = iface;
482 IDWriteTextAnalysisSource_AddRef(iface);
483 return S_OK;
484 }
485 return E_NOINTERFACE;
486}
487
489{
490 return 2;
491}
492
494{
495 return 1;
496}
497
498static const WCHAR *g_source;
499
501 UINT32 position, WCHAR const** text, UINT32* text_len)
502{
503 if (position >= lstrlenW(g_source))
504 {
505 *text = NULL;
506 *text_len = 0;
507 }
508 else
509 {
510 *text = &g_source[position];
511 *text_len = lstrlenW(g_source) - position;
512 }
513
514 return S_OK;
515}
516
518 UINT32 position, WCHAR const** text, UINT32* text_len)
519{
520 ok(0, "unexpected\n");
521 return E_NOTIMPL;
522}
523
526{
527 ok(0, "unexpected\n");
529}
530
532 UINT32 position, UINT32* text_len, WCHAR const** locale)
533{
534 *locale = NULL;
535 *text_len = 0;
536 return S_OK;
537}
538
540 UINT32 position, UINT32* text_len, IDWriteNumberSubstitution **substitution)
541{
542 ok(0, "unexpected\n");
543 return E_NOTIMPL;
544}
545
546static IDWriteTextAnalysisSourceVtbl analysissourcevtbl = {
555};
556
558
560{
563 return factory;
564}
565
567{
568 IDWriteFactory *factory = create_factory_iid(&IID_IDWriteFactory);
569 ok(factory != NULL, "Failed to create factory.\n");
570 return factory;
571}
572
573/* obvious limitation is that only last script data is returned, so this
574 helper is suitable for single script strings only */
576{
577 IDWriteTextAnalyzer *analyzer;
579 HRESULT hr;
580
581 g_source = str;
582
584 hr = IDWriteFactory_CreateTextAnalyzer(factory, &analyzer);
585 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
586
587 hr = IDWriteTextAnalyzer_AnalyzeScript(analyzer, &analysissource, 0, len, &analysissink.IDWriteTextAnalysisSink_iface);
588 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
589
590 *sa = analysissink.sa;
591 IDWriteFactory_Release(factory);
592}
593
595{
597 IDWriteFontFamily *family;
598 IDWriteFontFace *fontface;
600 WCHAR nameW[255];
602 BOOL exists;
603 HRESULT hr;
604
605 hr = IDWriteTextFormat_GetFontCollection(format, &collection);
606 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
607
608 hr = IDWriteTextFormat_GetFontFamilyName(format, nameW, ARRAY_SIZE(nameW));
609 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
610
611 hr = IDWriteFontCollection_FindFamilyName(collection, nameW, &index, &exists);
612 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
613
614 hr = IDWriteFontCollection_GetFontFamily(collection, index, &family);
615 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
616 IDWriteFontCollection_Release(collection);
617
618 hr = IDWriteFontFamily_GetFirstMatchingFont(family,
619 IDWriteTextFormat_GetFontWeight(format),
620 IDWriteTextFormat_GetFontStretch(format),
621 IDWriteTextFormat_GetFontStyle(format),
622 &font);
623 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
624
625 hr = IDWriteFont_CreateFontFace(font, &fontface);
626 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
627
628 IDWriteFont_Release(font);
629 IDWriteFontFamily_Release(family);
630
631 return fontface;
632}
633
634#define EXPECT_REF(obj,ref) _expect_ref((IUnknown*)obj, ref, __LINE__)
636{
637 ULONG rc;
638 IUnknown_AddRef(obj);
639 rc = IUnknown_Release(obj);
640 ok_(__FILE__,line)(rc == ref, "expected refcount %ld, got %ld\n", ref, rc);
641}
642
644 DRAW_EFFECT = 0x1000
646
654 DRAW_KINDS_MASK = 0xff
656
657static const char *get_draw_kind_name(unsigned short kind)
658{
659 static const char *kind_names[] = {
660 "GLYPH_RUN",
661 "UNDERLINE",
662 "STRIKETHROUGH",
663 "INLINE",
664 "END_OF_SEQ",
665
666 "GLYPH_RUN|EFFECT",
667 "UNDERLINE|EFFECT",
668 "STRIKETHROUGH|EFFECT",
669 "INLINE|EFFECT",
670 "END_OF_SEQ"
671 };
672 if ((kind & DRAW_KINDS_MASK) > DRAW_LAST_KIND)
673 return "unknown";
674 return (kind & DRAW_EFFECT) ? kind_names[(kind & DRAW_KINDS_MASK) + DRAW_TOTAL_KINDS] :
675 kind_names[kind];
676}
677
680 WCHAR string[10]; /* only meaningful for DrawGlyphRun() */
682 UINT32 glyphcount; /* only meaningful for DrawGlyphRun() */
684};
685
687{
688 int count;
689 int size;
691};
692
694 unsigned short kind;
697 const char *file;
698 int line;
699};
700
701#define NUM_CALL_SEQUENCES 1
702#define RENDERER_ID 0
705
706static void add_call(struct drawcall_sequence **seq, int sequence_index, const struct drawcall_entry *call)
707{
708 struct drawcall_sequence *call_seq = seq[sequence_index];
709
710 if (!call_seq->sequence) {
711 call_seq->size = 10;
712 call_seq->sequence = malloc(call_seq->size * sizeof(*call_seq->sequence));
713 }
714
715 if (call_seq->count == call_seq->size) {
716 call_seq->size *= 2;
717 call_seq->sequence = realloc(call_seq->sequence, call_seq->size * sizeof(*call_seq->sequence));
718 }
719
720 assert(call_seq->sequence);
721 call_seq->sequence[call_seq->count++] = *call;
722}
723
724static inline void flush_sequence(struct drawcall_sequence **seg, int sequence_index)
725{
726 struct drawcall_sequence *call_seq = seg[sequence_index];
727
728 free(call_seq->sequence);
729 call_seq->sequence = NULL;
730 call_seq->count = call_seq->size = 0;
731}
732
733static void init_call_sequences(struct drawcall_sequence **seq, int n)
734{
735 int i;
736
737 for (i = 0; i < n; i++)
738 seq[i] = calloc(1, sizeof(*seq[i]));
739}
740
741static void ok_sequence_(struct drawcall_sequence **seq, int sequence_index,
742 const struct drawcall_entry *expected, const char *context, BOOL todo,
743 const char *file, int line)
744{
745 static const struct drawcall_entry end_of_sequence = { DRAW_LAST_KIND };
746 struct drawcall_sequence *call_seq = seq[sequence_index];
747 const struct drawcall_entry *actual, *sequence;
748 int failcount = 0;
749
750 add_call(seq, sequence_index, &end_of_sequence);
751
752 sequence = call_seq->sequence;
753 actual = sequence;
754
755 while (expected->kind != DRAW_LAST_KIND && actual->kind != DRAW_LAST_KIND) {
756 if (expected->kind != actual->kind) {
757 if (todo) {
758 failcount++;
760 ok_(file, line) (0, "%s: call %s was expected, but got call %s instead\n",
762
763 flush_sequence(seq, sequence_index);
764 return;
765 }
766 else
767 ok_(file, line) (0, "%s: call %s was expected, but got call %s instead\n",
769 }
770 else if ((expected->kind & DRAW_KINDS_MASK) == DRAW_GLYPHRUN) {
771 int cmp = lstrcmpW(expected->string, actual->string);
772 if (cmp != 0 && todo) {
773 failcount++;
775 ok_(file, line) (0, "%s: glyphrun string %s was expected, but got %s instead\n",
777 }
778 else
779 ok_(file, line) (cmp == 0, "%s: glyphrun string %s was expected, but got %s instead\n",
781
782 cmp = lstrcmpW(expected->locale, actual->locale);
783 if (cmp != 0 && todo) {
784 failcount++;
786 ok_(file, line) (0, "%s: glyph run locale %s was expected, but got %s instead\n",
788 }
789 else
790 ok_(file, line) (cmp == 0, "%s: glyph run locale %s was expected, but got %s instead\n",
792
793 if (expected->glyphcount != actual->glyphcount && todo) {
794 failcount++;
796 ok_(file, line) (0, "%s: wrong glyph count, %u was expected, but got %u instead\n",
797 context, expected->glyphcount, actual->glyphcount);
798 }
799 else
800 ok_(file, line) (expected->glyphcount == actual->glyphcount,
801 "%s: wrong glyph count, %u was expected, but got %u instead\n",
802 context, expected->glyphcount, actual->glyphcount);
803
804 if (expected->bidilevel != actual->bidilevel && todo) {
805 failcount++;
807 ok_(file, line) (0, "%s: wrong bidi level, %u was expected, but got %u instead\n",
808 context, expected->bidilevel, actual->bidilevel);
809 }
810 else
811 ok_(file, line) (expected->bidilevel == actual->bidilevel,
812 "%s: wrong bidi level, %u was expected, but got %u instead\n",
813 context, expected->bidilevel, actual->bidilevel);
814 }
815 else if ((expected->kind & DRAW_KINDS_MASK) == DRAW_UNDERLINE) {
816 int cmp = lstrcmpW(expected->locale, actual->locale);
817 if (cmp != 0 && todo) {
818 failcount++;
820 ok_(file, line) (0, "%s: underline locale %s was expected, but got %s instead\n",
822 }
823 else
824 ok_(file, line) (cmp == 0, "%s: underline locale %s was expected, but got %s instead\n",
826 }
827 expected++;
828 actual++;
829 }
830
831 if (todo) {
832 todo_wine {
833 if (expected->kind != DRAW_LAST_KIND || actual->kind != DRAW_LAST_KIND) {
834 failcount++;
835 ok_(file, line) (0, "%s: the call sequence is not complete: expected %s - actual %s\n",
837 }
838 }
839 }
840 else if (expected->kind != DRAW_LAST_KIND || actual->kind != DRAW_LAST_KIND)
841 ok_(file, line) (0, "%s: the call sequence is not complete: expected %s - actual %s\n",
843
844 if (todo && !failcount) /* succeeded yet marked todo */
846 ok_(file, line)(1, "%s: marked \"todo_wine\" but succeeds\n", context);
847
848 flush_sequence(seq, sequence_index);
849}
850
851#define ok_sequence(seq, index, exp, contx, todo) \
852 ok_sequence_(seq, index, (exp), (contx), (todo), __FILE__, __LINE__)
853
855{
856 if (IsEqualIID(riid, &IID_IDWriteTextRenderer) ||
857 IsEqualIID(riid, &IID_IDWritePixelSnapping) ||
859 ) {
860 *obj = iface;
861 return S_OK;
862 }
863
864 *obj = NULL;
865
866 /* IDWriteTextRenderer1 overrides drawing calls, ignore for now */
867 if (IsEqualIID(riid, &IID_IDWriteTextRenderer1))
868 return E_NOINTERFACE;
869
870 ok(0, "unexpected QI %s\n", wine_dbgstr_guid(riid));
871 return E_NOINTERFACE;
872}
873
875{
876 return 2;
877}
878
880{
881 return 1;
882}
883
894};
895
897 void *context, BOOL *disabled)
898{
899 struct renderer_context *ctxt = (struct renderer_context*)context;
900 if (ctxt)
901 *disabled = ctxt->snapping_disabled;
902 else
903 *disabled = TRUE;
904 return S_OK;
905}
906
908 void *context, DWRITE_MATRIX *m)
909{
910 struct renderer_context *ctxt = (struct renderer_context*)context;
911 ok(!ctxt->snapping_disabled, "expected enabled snapping\n");
912 *m = ctxt->m;
913 return S_OK;
914}
915
917 void *context, FLOAT *pixels_per_dip)
918{
919 struct renderer_context *ctxt = (struct renderer_context*)context;
920 *pixels_per_dip = ctxt->ppdip;
921 return S_OK;
922}
923
924#define TEST_MEASURING_MODE(ctxt, mode) test_measuring_mode(ctxt, mode, __LINE__)
926{
927 if (ctxt->gdicompat) {
928 if (ctxt->use_gdi_natural)
929 ok_(__FILE__, line)(mode == DWRITE_MEASURING_MODE_GDI_NATURAL, "got %d\n", mode);
930 else
931 ok_(__FILE__, line)(mode == DWRITE_MEASURING_MODE_GDI_CLASSIC, "got %d\n", mode);
932 }
933 else
934 ok_(__FILE__, line)(mode == DWRITE_MEASURING_MODE_NATURAL, "got %d\n", mode);
935}
936
938 void *context,
939 FLOAT baselineOriginX,
940 FLOAT baselineOriginY,
942 DWRITE_GLYPH_RUN const *run,
944 IUnknown *effect)
945{
946 struct renderer_context *ctxt = (struct renderer_context*)context;
947 struct drawcall_entry entry;
949
950 if (ctxt) {
952 ctxt->originX = baselineOriginX;
953 ctxt->originY = baselineOriginY;
954 }
955
956 ok(descr->stringLength < ARRAY_SIZE(entry.string), "string is too long\n");
957 if (descr->stringLength && descr->stringLength < ARRAY_SIZE(entry.string)) {
958 memcpy(entry.string, descr->string, descr->stringLength*sizeof(WCHAR));
959 entry.string[descr->stringLength] = 0;
960 }
961 else
962 entry.string[0] = 0;
963
964 /* see what's reported for control codes runs */
965 get_script_analysis(descr->string, descr->stringLength, &sa);
966 if (sa.shapes == DWRITE_SCRIPT_SHAPES_NO_VISUAL) {
967 UINT32 i;
968
969 /* glyphs are not reported at all for control code runs */
970 ok(run->glyphCount == 0, "got %u\n", run->glyphCount);
971 ok(run->glyphAdvances != NULL, "advances array %p\n", run->glyphAdvances);
972 ok(run->glyphOffsets != NULL, "offsets array %p\n", run->glyphOffsets);
973 ok(run->fontFace != NULL, "got %p\n", run->fontFace);
974 /* text positions are still valid */
975 ok(descr->string != NULL, "got string %p\n", descr->string);
976 ok(descr->stringLength > 0, "got string length %u\n", descr->stringLength);
977 ok(descr->clusterMap != NULL, "clustermap %p\n", descr->clusterMap);
978 for (i = 0; i < descr->stringLength; i++)
979 ok(descr->clusterMap[i] == i, "got %u\n", descr->clusterMap[i]);
980 }
981
982 entry.kind = DRAW_GLYPHRUN;
983 if (effect)
984 entry.kind |= DRAW_EFFECT;
985 ok(lstrlenW(descr->localeName) < LOCALE_NAME_MAX_LENGTH, "unexpectedly long locale name\n");
986 lstrcpyW(entry.locale, descr->localeName);
987 entry.glyphcount = run->glyphCount;
988 entry.bidilevel = run->bidiLevel;
990 return S_OK;
991}
992
994 void *context,
995 FLOAT baselineOriginX,
996 FLOAT baselineOriginY,
997 DWRITE_UNDERLINE const* underline,
998 IUnknown *effect)
999{
1000 struct renderer_context *ctxt = (struct renderer_context*)context;
1001 struct drawcall_entry entry = { 0 };
1002
1003 if (ctxt)
1004 TEST_MEASURING_MODE(ctxt, underline->measuringMode);
1005
1006 ok(underline->runHeight > 0.0f, "Expected non-zero run height\n");
1007 if (ctxt && ctxt->format) {
1009 IDWriteFontFace *fontface;
1010 FLOAT emsize;
1011
1012 fontface = get_fontface_from_format(ctxt->format);
1013 emsize = IDWriteTextFormat_GetFontSize(ctxt->format);
1014 IDWriteFontFace_GetMetrics(fontface, &metrics);
1015
1016 ok(emsize == metrics.designUnitsPerEm, "Unexpected font size %f\n", emsize);
1017 /* Expected height is in design units, allow some absolute difference from it. Seems to only happen on Vista */
1018 ok(fabs(metrics.capHeight - underline->runHeight) < 2.0f, "Expected runHeight %u, got %f, family %s\n",
1019 metrics.capHeight, underline->runHeight, wine_dbgstr_w(ctxt->familyW));
1020
1021 IDWriteFontFace_Release(fontface);
1022 }
1023
1024 entry.kind = DRAW_UNDERLINE;
1025 if (effect)
1026 entry.kind |= DRAW_EFFECT;
1027 lstrcpyW(entry.locale, underline->localeName);
1029 return S_OK;
1030}
1031
1033 void *context,
1034 FLOAT baselineOriginX,
1035 FLOAT baselineOriginY,
1036 DWRITE_STRIKETHROUGH const* strikethrough,
1037 IUnknown *effect)
1038{
1039 struct renderer_context *ctxt = (struct renderer_context*)context;
1040 struct drawcall_entry entry = { 0 };
1041
1042 if (ctxt)
1043 TEST_MEASURING_MODE(ctxt, strikethrough->measuringMode);
1044
1046 if (effect)
1047 entry.kind |= DRAW_EFFECT;
1049 return S_OK;
1050}
1051
1053 void *context,
1054 FLOAT originX,
1055 FLOAT originY,
1056 IDWriteInlineObject *object,
1057 BOOL is_sideways,
1058 BOOL is_rtl,
1059 IUnknown *effect)
1060{
1061 struct drawcall_entry entry = { 0 };
1062 entry.kind = DRAW_INLINE;
1063 if (effect)
1064 entry.kind |= DRAW_EFFECT;
1066 return S_OK;
1067}
1068
1069static const IDWriteTextRendererVtbl testrenderervtbl = {
1080};
1081
1083
1084/* test IDWriteInlineObject */
1086{
1089
1092};
1093
1095{
1097}
1098
1100{
1101 if (IsEqualIID(riid, &IID_IDWriteInlineObject) || IsEqualIID(riid, &IID_IUnknown)) {
1102 *obj = iface;
1103 IDWriteInlineObject_AddRef(iface);
1104 return S_OK;
1105 }
1106
1107 *obj = NULL;
1108 return E_NOINTERFACE;
1109}
1110
1112{
1114 return InterlockedIncrement(&obj->refcount);
1115}
1116
1118{
1120 ULONG refcount = InterlockedDecrement(&obj->refcount);
1121
1122 if (!refcount)
1123 free(obj);
1124
1125 return refcount;
1126}
1127
1129 void* client_drawingontext, IDWriteTextRenderer* renderer,
1130 FLOAT originX, FLOAT originY, BOOL is_sideways, BOOL is_rtl, IUnknown *drawing_effect)
1131{
1132 ok(0, "unexpected call\n");
1133 return E_NOTIMPL;
1134}
1135
1137{
1138 metrics->width = 123.0;
1139 return 0x8faecafe;
1140}
1141
1143{
1144 ok(0, "unexpected call\n");
1145 return E_NOTIMPL;
1146}
1147
1150{
1152 return 0x8feacafe;
1153}
1154
1157{
1159 return S_OK;
1160}
1161
1162static const IDWriteInlineObjectVtbl testinlineobjvtbl = {
1170};
1171
1172static const IDWriteInlineObjectVtbl testinlineobjvtbl2 =
1173{
1181};
1182
1183static struct test_inline_obj *create_test_inline_object(const IDWriteInlineObjectVtbl *vtable)
1184{
1185 struct test_inline_obj *object = calloc(1, sizeof(*object));
1186
1187 object->IDWriteInlineObject_iface.lpVtbl = vtable;
1188 object->refcount = 1;
1189
1190 return object;
1191}
1192
1194{
1196 *metrics = obj->metrics;
1197 return S_OK;
1198}
1199
1201{
1203 *overhangs = obj->overhangs;
1204 /* Return value is ignored. */
1205 return E_NOTIMPL;
1206}
1207
1208static const IDWriteInlineObjectVtbl testinlineobjvtbl3 = {
1216};
1217
1219{
1222};
1223
1225{
1226 return CONTAINING_RECORD(iface, struct test_effect, IUnknown_iface);
1227}
1228
1230{
1231 if (IsEqualIID(riid, &IID_IUnknown)) {
1232 *obj = iface;
1233 IUnknown_AddRef(iface);
1234 return S_OK;
1235 }
1236
1237 ok(0, "Unexpected riid %s.\n", wine_dbgstr_guid(riid));
1238 *obj = NULL;
1239 return E_NOINTERFACE;
1240}
1241
1243{
1244 struct test_effect *effect = test_effect_from_IUnknown(iface);
1245 return InterlockedIncrement(&effect->ref);
1246}
1247
1249{
1250 struct test_effect *effect = test_effect_from_IUnknown(iface);
1251 LONG ref = InterlockedDecrement(&effect->ref);
1252
1253 if (!ref)
1254 free(effect);
1255
1256 return ref;
1257}
1258
1259static const IUnknownVtbl testeffectvtbl = {
1263};
1264
1266{
1267 struct test_effect *effect;
1268
1269 effect = calloc(1, sizeof(*effect));
1270 effect->IUnknown_iface.lpVtbl = &testeffectvtbl;
1271 effect->ref = 1;
1272
1273 return &effect->IUnknown_iface;
1274}
1275
1276static void test_CreateTextLayout(void)
1277{
1278 IDWriteTextLayout4 *layout4;
1279 IDWriteTextLayout2 *layout2 = NULL;
1280 IDWriteTextLayout *layout;
1281 IDWriteTextFormat3 *format3;
1284 HRESULT hr;
1285
1287
1288 layout = (void*)0xdeadbeef;
1289 hr = IDWriteFactory_CreateTextLayout(factory, NULL, 0, NULL, 0.0f, 0.0f, &layout);
1290 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
1291 ok(layout == NULL, "got %p\n", layout);
1292
1293 layout = (void*)0xdeadbeef;
1294 hr = IDWriteFactory_CreateTextLayout(factory, L"string", 6, NULL, 0.0f, 0.0f, &layout);
1295 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
1296 ok(layout == NULL, "got %p\n", layout);
1297
1298 layout = (void*)0xdeadbeef;
1299 hr = IDWriteFactory_CreateTextLayout(factory, L"string", 6, NULL, 1.0f, 0.0f, &layout);
1300 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
1301 ok(layout == NULL, "got %p\n", layout);
1302
1303 layout = (void*)0xdeadbeef;
1304 hr = IDWriteFactory_CreateTextLayout(factory, L"string", 6, NULL, 0.0f, 1.0f, &layout);
1305 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
1306 ok(layout == NULL, "got %p\n", layout);
1307
1308 layout = (void*)0xdeadbeef;
1309 hr = IDWriteFactory_CreateTextLayout(factory, L"string", 6, NULL, 1000.0f, 1000.0f, &layout);
1310 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
1311 ok(layout == NULL, "got %p\n", layout);
1312
1313 hr = IDWriteFactory_CreateTextFormat(factory, L"Tahoma", NULL, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL,
1314 DWRITE_FONT_STRETCH_NORMAL, 10.0f, L"en-us", &format);
1315 ok(hr == S_OK, "Failed to create format, hr %#lx.\n", hr);
1316
1317 layout = (void*)0xdeadbeef;
1318 hr = IDWriteFactory_CreateTextLayout(factory, NULL, 0, format, 100.0f, 100.0f, &layout);
1319 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
1320 ok(layout == NULL, "got %p\n", layout);
1321
1322 layout = (void *)0xdeadbeef;
1323 hr = IDWriteFactory_CreateTextLayout(factory, L"string", 6, format, -100.0f, 100.0f, &layout);
1324 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
1325 ok(layout == NULL, "Unexpected pointer %p.\n", layout);
1326
1327 layout = (void *)0xdeadbeef;
1328 hr = IDWriteFactory_CreateTextLayout(factory, L"string", 6, format, 100.0f, -100.0f, &layout);
1329 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
1330 ok(layout == NULL, "Unexpected pointer %p.\n", layout);
1331
1332 layout = (void *)0xdeadbeef;
1333 hr = IDWriteFactory_CreateTextLayout(factory, L"string", 6, format, -100.0f, -100.0f, &layout);
1334 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
1335 ok(layout == NULL, "Unexpected pointer %p.\n", layout);
1336
1337 hr = IDWriteFactory_CreateTextLayout(factory, L"string", 0, format, 0.0f, 0.0f, &layout);
1338 ok(hr == S_OK, "Failed to create text layout, hr %#lx.\n", hr);
1339 IDWriteTextLayout_Release(layout);
1340
1341 EXPECT_REF(format, 1);
1342 hr = IDWriteFactory_CreateTextLayout(factory, L"string", 6, format, 1000.0f, 1000.0f, &layout);
1343 ok(hr == S_OK, "Failed to create text layout, hr %#lx.\n", hr);
1344 EXPECT_REF(format, 1);
1345
1346 hr = IDWriteTextLayout_QueryInterface(layout, &IID_IDWriteTextLayout2, (void**)&layout2);
1347 if (hr == S_OK) {
1348 IDWriteTextLayout1 *layout1;
1349 IDWriteTextFormat1 *format1;
1351
1352 hr = IDWriteTextLayout2_QueryInterface(layout2, &IID_IDWriteTextLayout1, (void**)&layout1);
1353 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1354 IDWriteTextLayout1_Release(layout1);
1355
1356 EXPECT_REF(layout2, 2);
1357 hr = IDWriteTextLayout2_QueryInterface(layout2, &IID_IDWriteTextFormat1, (void**)&format1);
1358 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1359 EXPECT_REF(layout2, 3);
1360
1361 hr = IDWriteTextLayout2_QueryInterface(layout2, &IID_IDWriteTextFormat, (void**)&format);
1362 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1363 ok(format == (IDWriteTextFormat*)format1, "got %p, %p\n", format, format1);
1364 ok(format != (IDWriteTextFormat*)layout2, "got %p, %p\n", format, layout2);
1365 EXPECT_REF(layout2, 4);
1366
1367 hr = IDWriteTextFormat_QueryInterface(format, &IID_IDWriteTextLayout1, (void**)&layout1);
1368 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1369 IDWriteTextLayout1_Release(layout1);
1370
1371 IDWriteTextFormat1_Release(format1);
1372 IDWriteTextFormat_Release(format);
1373
1374 hr = IDWriteTextLayout_QueryInterface(layout, &IID_IDWriteTextFormat1, (void**)&format1);
1375 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1376 EXPECT_REF(layout2, 3);
1377
1378 hr = IDWriteTextLayout_QueryInterface(layout, &IID_IDWriteTextFormat, (void**)&format);
1379 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1380 ok(format == (IDWriteTextFormat*)format1, "got %p, %p\n", format, format1);
1381 EXPECT_REF(layout2, 4);
1382
1383 IDWriteTextFormat1_Release(format1);
1384 IDWriteTextFormat_Release(format);
1385 }
1386 else
1387 win_skip("IDWriteTextLayout2 is not supported.\n");
1388
1389 if (layout2 && SUCCEEDED(IDWriteTextLayout2_QueryInterface(layout2, &IID_IDWriteTextLayout4, (void **)&layout4)))
1390 {
1391 hr = IDWriteTextLayout4_QueryInterface(layout4, &IID_IDWriteTextFormat3, (void **)&format3);
1392 ok(hr == S_OK, "Failed to get text format, hr %#lx.\n", hr);
1393 IDWriteTextFormat3_Release(format3);
1394 }
1395 else
1396 win_skip("IDWriteTextLayout4 is not supported.\n");
1397
1398 if (layout2)
1399 IDWriteTextLayout2_Release(layout2);
1400 IDWriteTextLayout_Release(layout);
1401 IDWriteTextFormat_Release(format);
1402 IDWriteFactory_Release(factory);
1403}
1404
1406 { 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 },
1407 { 1.0, 0.0, 0.0, 1.0, 0.3, 0.2 },
1408 { 1.0, 0.0, 0.0, 1.0,-0.3,-0.2 },
1409
1410 { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 },
1411 { 1.0, 0.0, 0.0, 0.0, 0.0, 0.0 },
1412 { 1.0, 2.0, 0.5, 1.0, 0.0, 0.0 },
1413};
1414
1416{
1417 IDWriteTextLayout *layout;
1420 FLOAT dimension;
1421 HRESULT hr;
1422 int i;
1423
1425
1426 layout = (void*)0xdeadbeef;
1427 hr = IDWriteFactory_CreateGdiCompatibleTextLayout(factory, NULL, 0, NULL, 0.0f, 0.0f, 0.0f, NULL, FALSE, &layout);
1428 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
1429 ok(layout == NULL, "got %p\n", layout);
1430
1431 layout = (void*)0xdeadbeef;
1432 hr = IDWriteFactory_CreateGdiCompatibleTextLayout(factory, L"string", 6, NULL, 0.0f, 0.0f, 0.0f, NULL,
1433 FALSE, &layout);
1434 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
1435 ok(layout == NULL, "got %p\n", layout);
1436
1437 layout = (void*)0xdeadbeef;
1438 hr = IDWriteFactory_CreateGdiCompatibleTextLayout(factory, L"string", 6, NULL, 1.0f, 0.0f, 0.0f, NULL,
1439 FALSE, &layout);
1440 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
1441 ok(layout == NULL, "got %p\n", layout);
1442
1443 layout = (void*)0xdeadbeef;
1444 hr = IDWriteFactory_CreateGdiCompatibleTextLayout(factory, L"string", 6, NULL, 1.0f, 0.0f, 1.0f, NULL,
1445 FALSE, &layout);
1446 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
1447 ok(layout == NULL, "got %p\n", layout);
1448
1449 layout = (void*)0xdeadbeef;
1450 hr = IDWriteFactory_CreateGdiCompatibleTextLayout(factory, L"string", 6, NULL, 1000.0f, 1000.0f, 1.0f, NULL,
1451 FALSE, &layout);
1452 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
1453 ok(layout == NULL, "got %p\n", layout);
1454
1455 /* create with text format */
1456 hr = IDWriteFactory_CreateTextFormat(factory, L"Tahoma", NULL, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL,
1457 DWRITE_FONT_STRETCH_NORMAL, 10.0f, L"en-us", &format);
1458 ok(hr == S_OK, "Failed to create text format, hr %#lx.\n", hr);
1459 EXPECT_REF(format, 1);
1460
1461 layout = (void*)0xdeadbeef;
1462 hr = IDWriteFactory_CreateGdiCompatibleTextLayout(factory, NULL, 0, format, 100.0f, 100.0f, 1.0f, NULL, FALSE, &layout);
1463 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
1464 ok(layout == NULL, "got %p\n", layout);
1465
1466 layout = (void *)0xdeadbeef;
1467 hr = IDWriteFactory_CreateGdiCompatibleTextLayout(factory, L"string", 6, format, -100.0f, 100.0f, 1.0f,
1468 NULL, FALSE, &layout);
1469 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
1470 ok(layout == NULL, "Unexpected pointer %p.\n", layout);
1471
1472 layout = (void *)0xdeadbeef;
1473 hr = IDWriteFactory_CreateGdiCompatibleTextLayout(factory, L"string", 6, format, 100.0f, -100.0f, 1.0f,
1474 NULL, FALSE, &layout);
1475 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
1476 ok(layout == NULL, "Unexpected pointer %p.\n", layout);
1477
1478 layout = (void *)0xdeadbeef;
1479 hr = IDWriteFactory_CreateGdiCompatibleTextLayout(factory, L"string", 6, format, -100.0f, -100.0f, 1.0f,
1480 NULL, FALSE, &layout);
1481 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
1482 ok(layout == NULL, "Unexpected pointer %p.\n", layout);
1483
1484 hr = IDWriteFactory_CreateGdiCompatibleTextLayout(factory, L"string", 6, format, 100.0f, 100.0f, 1.0f, NULL,
1485 FALSE, &layout);
1486 ok(hr == S_OK, "Failed to create text layout, hr %#lx.\n", hr);
1487 EXPECT_REF(format, 1);
1488 EXPECT_REF(layout, 1);
1489
1490 IDWriteTextLayout_AddRef(layout);
1491 EXPECT_REF(format, 1);
1492 EXPECT_REF(layout, 2);
1493 IDWriteTextLayout_Release(layout);
1494 IDWriteTextLayout_Release(layout);
1495
1496 /* zero length string is okay */
1497 hr = IDWriteFactory_CreateGdiCompatibleTextLayout(factory, L"string", 0, format, 100.0f, 100.0f, 1.0f, NULL,
1498 FALSE, &layout);
1499 ok(hr == S_OK, "Failed to create text layout, hr %#lx.\n", hr);
1500
1501 dimension = IDWriteTextLayout_GetMaxWidth(layout);
1502 ok(dimension == 100.0, "got %f\n", dimension);
1503
1504 dimension = IDWriteTextLayout_GetMaxHeight(layout);
1505 ok(dimension == 100.0, "got %f\n", dimension);
1506
1507 IDWriteTextLayout_Release(layout);
1508
1509 /* negative, zero ppdip */
1510 hr = IDWriteFactory_CreateGdiCompatibleTextLayout(factory, L"string", 1, format, 100.0f, 100.0f, -1.0f, NULL,
1511 FALSE, &layout);
1512 ok(hr == S_OK, "Failed to create text layout, hr %#lx.\n", hr);
1513 IDWriteTextLayout_Release(layout);
1514
1515 hr = IDWriteFactory_CreateGdiCompatibleTextLayout(factory, L"string", 1, format, 100.0f, 100.0f, 0.0f, NULL,
1516 FALSE, &layout);
1517 ok(hr == S_OK, "Failed to create text layout, hr %#lx.\n", hr);
1518 IDWriteTextLayout_Release(layout);
1519
1520 /* transforms */
1521 for (i = 0; i < ARRAY_SIZE(layoutcreate_transforms); ++i)
1522 {
1523 hr = IDWriteFactory_CreateGdiCompatibleTextLayout(factory, L"string", 1, format, 100.0f, 100.0f, 1.0f,
1524 &layoutcreate_transforms[i], FALSE, &layout);
1525 ok(hr == S_OK, "Failed to create text layout, hr %#lx.\n", hr);
1526 IDWriteTextLayout_Release(layout);
1527 }
1528
1529 IDWriteTextFormat_Release(format);
1530 IDWriteFactory_Release(factory);
1531}
1532
1533static void test_CreateTextFormat(void)
1534{
1538 DWRITE_WORD_WRAPPING wrapping;
1542 DWRITE_TRIMMING trimming;
1544 FLOAT spacing, baseline;
1545 IDWriteInlineObject *trimmingsign;
1547 HRESULT hr;
1548
1550
1551 /* zero/negative font size */
1552 hr = IDWriteFactory_CreateTextFormat(factory, L"Tahoma", NULL, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL,
1553 DWRITE_FONT_STRETCH_NORMAL, 0.0f, L"en-us", &format);
1554 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
1555
1556 hr = IDWriteFactory_CreateTextFormat(factory, L"Tahoma", NULL, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL,
1557 DWRITE_FONT_STRETCH_NORMAL, -10.0f, L"en-us", &format);
1558 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
1559
1560 /* invalid font properties */
1561 hr = IDWriteFactory_CreateTextFormat(factory, L"Tahoma", NULL, 1000, DWRITE_FONT_STYLE_NORMAL,
1562 DWRITE_FONT_STRETCH_NORMAL, 10.0f, L"en-us", &format);
1563 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
1564
1565 hr = IDWriteFactory_CreateTextFormat(factory, L"Tahoma", NULL, DWRITE_FONT_WEIGHT_NORMAL,
1567 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
1568
1569 hr = IDWriteFactory_CreateTextFormat(factory, L"Tahoma", NULL, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_ITALIC,
1570 10, 10.0f, L"en-us", &format);
1571 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
1572
1573 hr = IDWriteFactory_CreateTextFormat(factory, L"Tahoma", NULL, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_ITALIC,
1574 DWRITE_FONT_STRETCH_UNDEFINED, 10.0f, L"en-us", &format);
1575 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
1576
1577 /* empty family name */
1578 hr = IDWriteFactory_CreateTextFormat(factory, L"", NULL, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL,
1579 DWRITE_FONT_STRETCH_NORMAL, 10.0f, L"en-us", &format);
1580 ok(hr == S_OK, "Failed to create text format, hr %#lx.\n", hr);
1581 IDWriteTextFormat_Release(format);
1582
1583 hr = IDWriteFactory_CreateTextFormat(factory, L"Tahoma", NULL, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL,
1584 DWRITE_FONT_STRETCH_NORMAL, 10.0f, L"en-us", &format);
1585 ok(hr == S_OK, "Failed to create text format, hr %#lx.\n", hr);
1586
1587 if (0) /* crashes on native */
1588 hr = IDWriteTextFormat_GetFontCollection(format, NULL);
1589
1590 collection = NULL;
1591 hr = IDWriteTextFormat_GetFontCollection(format, &collection);
1592 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1593 ok(collection != NULL, "got %p\n", collection);
1594
1595 hr = IDWriteFactory_GetSystemFontCollection(factory, &syscoll, FALSE);
1596 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1597 ok(collection == syscoll, "got %p, was %p\n", syscoll, collection);
1598 IDWriteFontCollection_Release(syscoll);
1599 IDWriteFontCollection_Release(collection);
1600
1601 /* default format properties */
1602 align = IDWriteTextFormat_GetTextAlignment(format);
1604
1605 paralign = IDWriteTextFormat_GetParagraphAlignment(format);
1606 ok(paralign == DWRITE_PARAGRAPH_ALIGNMENT_NEAR, "got %d\n", paralign);
1607
1608 wrapping = IDWriteTextFormat_GetWordWrapping(format);
1609 ok(wrapping == DWRITE_WORD_WRAPPING_WRAP, "got %d\n", wrapping);
1610
1611 readdir = IDWriteTextFormat_GetReadingDirection(format);
1613
1614 flow = IDWriteTextFormat_GetFlowDirection(format);
1615 ok(flow == DWRITE_FLOW_DIRECTION_TOP_TO_BOTTOM, "got %d\n", flow);
1616
1617 hr = IDWriteTextFormat_GetLineSpacing(format, &method, &spacing, &baseline);
1618 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1619 ok(spacing == 0.0, "got %f\n", spacing);
1620 ok(baseline == 0.0, "got %f\n", baseline);
1622
1624 trimming.delimiter = 10;
1625 trimming.delimiterCount = 10;
1626 trimmingsign = (void*)0xdeadbeef;
1627 hr = IDWriteTextFormat_GetTrimming(format, &trimming, &trimmingsign);
1628 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1629 ok(trimming.granularity == DWRITE_TRIMMING_GRANULARITY_NONE, "got %d\n", trimming.granularity);
1630 ok(trimming.delimiter == 0, "got %d\n", trimming.delimiter);
1631 ok(trimming.delimiterCount == 0, "got %d\n", trimming.delimiterCount);
1632 ok(trimmingsign == NULL, "got %p\n", trimmingsign);
1633
1634 /* setters */
1635 hr = IDWriteTextFormat_SetTextAlignment(format, DWRITE_TEXT_ALIGNMENT_LEADING);
1636 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1637
1638 hr = IDWriteTextFormat_SetTextAlignment(format, DWRITE_TEXT_ALIGNMENT_JUSTIFIED+1);
1639 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
1640
1641 hr = IDWriteTextFormat_SetParagraphAlignment(format, DWRITE_PARAGRAPH_ALIGNMENT_NEAR);
1642 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1643
1644 hr = IDWriteTextFormat_SetParagraphAlignment(format, DWRITE_PARAGRAPH_ALIGNMENT_CENTER+1);
1645 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
1646
1647 hr = IDWriteTextFormat_SetWordWrapping(format, DWRITE_WORD_WRAPPING_WRAP);
1648 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1649
1650 hr = IDWriteTextFormat_SetWordWrapping(format, DWRITE_WORD_WRAPPING_CHARACTER+1);
1651 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
1652
1653 hr = IDWriteTextFormat_SetReadingDirection(format, DWRITE_READING_DIRECTION_LEFT_TO_RIGHT);
1654 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1655
1656 hr = IDWriteTextFormat_SetFlowDirection(format, DWRITE_FLOW_DIRECTION_TOP_TO_BOTTOM);
1657 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1658
1659
1660 hr = IDWriteTextFormat_SetTrimming(format, &trimming, NULL);
1661 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1662
1663 /* invalid granularity */
1664 trimming.granularity = 10;
1665 trimming.delimiter = 0;
1666 trimming.delimiterCount = 0;
1667 hr = IDWriteTextFormat_SetTrimming(format, &trimming, NULL);
1668 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
1669
1670 IDWriteTextFormat_Release(format);
1671 IDWriteFactory_Release(factory);
1672}
1673
1674static void test_GetLocaleName(void)
1675{
1676 IDWriteTextFormat *format, *format2;
1677 IDWriteTextLayout *layout;
1679 WCHAR buff[10];
1680 UINT32 len;
1681 HRESULT hr;
1682
1684
1685 hr = IDWriteFactory_CreateTextFormat(factory, L"Tahoma", NULL, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL,
1686 DWRITE_FONT_STRETCH_NORMAL, 10.0f, L"ru", &format);
1687 ok(hr == S_OK, "Failed to create text format, hr %#lx.\n", hr);
1688
1689 hr = IDWriteFactory_CreateGdiCompatibleTextLayout(factory, L"string", 0, format, 100.0f, 100.0f, 1.0f, NULL,
1690 FALSE, &layout);
1691 ok(hr == S_OK, "Failed to create text layout, hr %#lx.\n", hr);
1692
1693 hr = IDWriteTextLayout_QueryInterface(layout, &IID_IDWriteTextFormat, (void**)&format2);
1694 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1695
1696 len = IDWriteTextFormat_GetLocaleNameLength(format2);
1697 ok(len == 2, "got %u\n", len);
1698 len = IDWriteTextFormat_GetLocaleNameLength(format);
1699 ok(len == 2, "got %u\n", len);
1700 hr = IDWriteTextFormat_GetLocaleName(format2, buff, len);
1701 ok(hr == E_NOT_SUFFICIENT_BUFFER, "Unexpected hr %#lx.\n", hr);
1702 hr = IDWriteTextFormat_GetLocaleName(format2, buff, len+1);
1703 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1704 ok(!lstrcmpW(buff, L"ru"), "Unexpected locale name %s.\n", wine_dbgstr_w(buff));
1705 hr = IDWriteTextFormat_GetLocaleName(format, buff, len);
1706 ok(hr == E_NOT_SUFFICIENT_BUFFER, "Unexpected hr %#lx.\n", hr);
1707 hr = IDWriteTextFormat_GetLocaleName(format, buff, len+1);
1708 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1709 ok(!lstrcmpW(buff, L"ru"), "Unexpected locale name %s.\n", wine_dbgstr_w(buff));
1710
1711 IDWriteTextLayout_Release(layout);
1712 IDWriteTextFormat_Release(format);
1713 IDWriteTextFormat_Release(format2);
1714 IDWriteFactory_Release(factory);
1715}
1716
1717static const struct drawcall_entry drawellipsis_seq[] = {
1718 { DRAW_GLYPHRUN, {0x2026, 0}, {'e','n','-','g','b',0}, 1 },
1719 { DRAW_LAST_KIND }
1720};
1721
1723{
1726 struct renderer_context ctxt;
1730 IUnknown *unk, *effect;
1731 HRESULT hr;
1732
1734
1735 hr = IDWriteFactory_CreateTextFormat(factory, L"Tahoma", NULL, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL,
1736 DWRITE_FONT_STRETCH_NORMAL, 10.0f, L"en-GB", &format);
1737 ok(hr == S_OK, "Failed to create text format, hr %#lx.\n", hr);
1738
1739 sign = (void *)0xdeadbeef;
1740 hr = IDWriteFactory_CreateEllipsisTrimmingSign(factory, NULL, &sign);
1741 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
1742 ok(!sign, "Unexpected pointer %p.\n", sign);
1743
1744 EXPECT_REF(format, 1);
1745 hr = IDWriteFactory_CreateEllipsisTrimmingSign(factory, format, &sign);
1746 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1747 EXPECT_REF(format, 1);
1748
1749 hr = IDWriteInlineObject_QueryInterface(sign, &IID_IDWriteTextLayout, (void**)&unk);
1750 ok(hr == E_NOINTERFACE, "Unexpected hr %#lx.\n", hr);
1751
1752if (0) {/* crashes on native */
1753 hr = IDWriteInlineObject_GetBreakConditions(sign, NULL, NULL);
1754 hr = IDWriteInlineObject_GetMetrics(sign, NULL);
1755}
1756 metrics.width = 0.0;
1757 metrics.height = 123.0;
1758 metrics.baseline = 123.0;
1759 metrics.supportsSideways = TRUE;
1760 hr = IDWriteInlineObject_GetMetrics(sign, &metrics);
1761 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1762 ok(metrics.width > 0.0, "got %.2f\n", metrics.width);
1763 ok(metrics.height == 0.0, "got %.2f\n", metrics.height);
1764 ok(metrics.baseline == 0.0, "got %.2f\n", metrics.baseline);
1765 ok(!metrics.supportsSideways, "got %d\n", metrics.supportsSideways);
1766
1768 hr = IDWriteInlineObject_GetBreakConditions(sign, &before, &after);
1769 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1772
1773 /* Draw tests */
1775 hr = IDWriteInlineObject_Draw(sign, NULL, &testrenderer, 0.0, 0.0, FALSE, FALSE, NULL);
1776 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1777 ok_sequence(sequences, RENDERER_ID, drawellipsis_seq, "ellipsis sign draw test", FALSE);
1778
1779 effect = create_test_effect();
1780
1781 EXPECT_REF(effect, 1);
1783 hr = IDWriteInlineObject_Draw(sign, NULL, &testrenderer, 0.0f, 0.0f, FALSE, FALSE, effect);
1784 ok(hr == S_OK, "Failed to draw trimming sign, hr %#lx.\n", hr);
1785 ok_sequence(sequences, RENDERER_ID, drawellipsis_seq, "ellipsis sign draw with effect test", FALSE);
1786 EXPECT_REF(effect, 1);
1787
1788 IUnknown_Release(effect);
1789
1791 hr = IDWriteInlineObject_Draw(sign, NULL, &testrenderer, 0.0f, 0.0f, FALSE, FALSE, (void *)0xdeadbeef);
1792 ok(hr == S_OK, "Failed to draw trimming sign, hr %#lx.\n", hr);
1793 ok_sequence(sequences, RENDERER_ID, drawellipsis_seq, "ellipsis sign draw with effect test", FALSE);
1794
1795 memset(&ctxt, 0, sizeof(ctxt));
1796 hr = IDWriteInlineObject_Draw(sign, &ctxt, &testrenderer, 123.0f, 456.0f, FALSE, FALSE, NULL);
1797 ok(hr == S_OK, "Failed to draw trimming sign, hr %#lx.\n", hr);
1798 ok(ctxt.originX == 123.0f && ctxt.originY == 456.0f, "Unexpected drawing origin\n");
1799
1800 IDWriteInlineObject_Release(sign);
1801
1802 /* Centered format */
1803 hr = IDWriteTextFormat_SetTextAlignment(format, DWRITE_TEXT_ALIGNMENT_CENTER);
1804 ok(hr == S_OK, "Failed to set text alignment, hr %#lx.\n", hr);
1805
1806 hr = IDWriteFactory_CreateEllipsisTrimmingSign(factory, format, &sign);
1807 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1808
1809 memset(&ctxt, 0, sizeof(ctxt));
1810 hr = IDWriteInlineObject_Draw(sign, &ctxt, &testrenderer, 123.0f, 456.0f, FALSE, FALSE, NULL);
1811 ok(hr == S_OK, "Failed to draw trimming sign, hr %#lx.\n", hr);
1812 ok(ctxt.originX == 123.0f && ctxt.originY == 456.0f, "Unexpected drawing origin\n");
1813
1814 IDWriteInlineObject_Release(sign);
1815
1816 /* non-orthogonal flow/reading combination */
1817 hr = IDWriteTextFormat_SetReadingDirection(format, DWRITE_READING_DIRECTION_LEFT_TO_RIGHT);
1818 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1819
1820 hr = IDWriteTextFormat_SetFlowDirection(format, DWRITE_FLOW_DIRECTION_LEFT_TO_RIGHT);
1821 ok(hr == S_OK || broken(hr == E_INVALIDARG) /* vista, win7 */, "Unexpected hr %#lx.\n", hr);
1822 if (hr == S_OK) {
1823 hr = IDWriteFactory_CreateEllipsisTrimmingSign(factory, format, &sign);
1824 ok(hr == DWRITE_E_FLOWDIRECTIONCONFLICTS, "Unexpected hr %#lx.\n", hr);
1825 }
1826
1827 IDWriteTextFormat_Release(format);
1828 IDWriteFactory_Release(factory);
1829}
1830
1831static void test_fontweight(void)
1832{
1833 IDWriteTextFormat *format, *fmt2;
1834 IDWriteTextLayout *layout;
1838 FLOAT size;
1839 HRESULT hr;
1840
1842
1843 hr = IDWriteFactory_CreateTextFormat(factory, L"Tahoma", NULL, DWRITE_FONT_WEIGHT_BOLD, DWRITE_FONT_STYLE_NORMAL,
1844 DWRITE_FONT_STRETCH_NORMAL, 10.0, L"ru", &format);
1845 ok(hr == S_OK, "Failed to create text format, hr %#lx.\n", hr);
1846
1847 hr = IDWriteFactory_CreateGdiCompatibleTextLayout(factory, L"string", 6, format, 100.0f, 100.0f, 1.0f, NULL,
1848 FALSE, &layout);
1849 ok(hr == S_OK, "Failed to create text layout, hr %#lx.\n", hr);
1850
1851 hr = IDWriteTextLayout_QueryInterface(layout, &IID_IDWriteTextFormat, (void**)&fmt2);
1852 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1853
1854 weight = IDWriteTextFormat_GetFontWeight(fmt2);
1855 ok(weight == DWRITE_FONT_WEIGHT_BOLD, "got %u\n", weight);
1856
1857 range.startPosition = range.length = 0;
1858 hr = IDWriteTextLayout_GetFontWeight(layout, 0, &weight, &range);
1859 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1860 ok(range.startPosition == 0 && range.length == ~0u, "got %u, %u\n", range.startPosition, range.length);
1861
1862 range.startPosition = 0;
1863 range.length = 6;
1864 hr = IDWriteTextLayout_SetFontWeight(layout, DWRITE_FONT_WEIGHT_NORMAL, range);
1865 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1866
1867 range.startPosition = range.length = 0;
1868 hr = IDWriteTextLayout_GetFontWeight(layout, 0, &weight, &range);
1869 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1870 ok(range.startPosition == 0 && range.length == 6, "got %u, %u\n", range.startPosition, range.length);
1871
1872 /* IDWriteTextFormat methods output doesn't reflect layout changes */
1873 weight = IDWriteTextFormat_GetFontWeight(fmt2);
1874 ok(weight == DWRITE_FONT_WEIGHT_BOLD, "got %u\n", weight);
1875
1876 range.length = 0;
1878 hr = IDWriteTextLayout_GetFontWeight(layout, 0, &weight, &range);
1879 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1880 ok(weight == DWRITE_FONT_WEIGHT_NORMAL, "got %d\n", weight);
1881 ok(range.length == 6, "got %d\n", range.length);
1882
1883 range.startPosition = 0;
1884 range.length = 6;
1885 hr = IDWriteTextLayout_SetFontWeight(layout, 1000, range);
1886 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
1887
1888 size = IDWriteTextLayout_GetMaxWidth(layout);
1889 ok(size == 100.0, "got %.2f\n", size);
1890
1891 hr = IDWriteTextLayout_SetMaxWidth(layout, 0.0);
1892 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1893
1894 size = IDWriteTextLayout_GetMaxWidth(layout);
1895 ok(size == 0.0, "got %.2f\n", size);
1896
1897 hr = IDWriteTextLayout_SetMaxWidth(layout, -1.0);
1898 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
1899
1900 size = IDWriteTextLayout_GetMaxWidth(layout);
1901 ok(size == 0.0, "got %.2f\n", size);
1902
1903 hr = IDWriteTextLayout_SetMaxWidth(layout, 100.0);
1904 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1905
1906 size = IDWriteTextLayout_GetMaxWidth(layout);
1907 ok(size == 100.0, "got %.2f\n", size);
1908
1909 size = IDWriteTextLayout_GetMaxHeight(layout);
1910 ok(size == 100.0, "got %.2f\n", size);
1911
1912 hr = IDWriteTextLayout_SetMaxHeight(layout, 0.0);
1913 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1914
1915 size = IDWriteTextLayout_GetMaxHeight(layout);
1916 ok(size == 0.0, "got %.2f\n", size);
1917
1918 hr = IDWriteTextLayout_SetMaxHeight(layout, -1.0);
1919 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
1920
1921 size = IDWriteTextLayout_GetMaxHeight(layout);
1922 ok(size == 0.0, "got %.2f\n", size);
1923
1924 hr = IDWriteTextLayout_SetMaxHeight(layout, 100.0);
1925 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1926
1927 size = IDWriteTextLayout_GetMaxHeight(layout);
1928 ok(size == 100.0, "got %.2f\n", size);
1929
1930 IDWriteTextLayout_Release(layout);
1931 IDWriteTextFormat_Release(fmt2);
1932 IDWriteTextFormat_Release(format);
1933 IDWriteFactory_Release(factory);
1934}
1935
1936static void test_SetInlineObject(void)
1937{
1938 IDWriteInlineObject *inlineobj, *inlineobj2, *inlinetest;
1941 IDWriteTextLayout *layout;
1943 HRESULT hr;
1944
1946
1947 hr = IDWriteFactory_CreateTextFormat(factory, L"Tahoma", NULL, DWRITE_FONT_WEIGHT_BOLD, DWRITE_FONT_STYLE_NORMAL,
1948 DWRITE_FONT_STRETCH_NORMAL, 10.0f, L"ru", &format);
1949 ok(hr == S_OK, "Failed to create text format, hr %#lx.\n", hr);
1950
1951 hr = IDWriteFactory_CreateGdiCompatibleTextLayout(factory, L"string", 6, format, 100.0f, 100.0f, 1.0f, NULL,
1952 FALSE, &layout);
1953 ok(hr == S_OK, "Failed to create text layout, hr %#lx.\n", hr);
1954
1955 hr = IDWriteFactory_CreateEllipsisTrimmingSign(factory, format, &inlineobj);
1956 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1957
1958 hr = IDWriteFactory_CreateEllipsisTrimmingSign(factory, format, &inlineobj2);
1959 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1960
1961 EXPECT_REF(inlineobj, 1);
1962 EXPECT_REF(inlineobj2, 1);
1963
1964 inlinetest = (void*)0x1;
1965 hr = IDWriteTextLayout_GetInlineObject(layout, 0, &inlinetest, NULL);
1966 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1967 ok(inlinetest == NULL, "got %p\n", inlinetest);
1968
1969 range.startPosition = 0;
1970 range.length = 2;
1971 hr = IDWriteTextLayout_SetInlineObject(layout, inlineobj, range);
1972 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1973
1974 EXPECT_REF(inlineobj, 2);
1975
1976 inlinetest = (void*)0x1;
1977 hr = IDWriteTextLayout_GetInlineObject(layout, 2, &inlinetest, NULL);
1978 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1979 ok(inlinetest == NULL, "got %p\n", inlinetest);
1980
1981 inlinetest = NULL;
1982 r2.startPosition = r2.length = 100;
1983 hr = IDWriteTextLayout_GetInlineObject(layout, 0, &inlinetest, &r2);
1984 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1985 ok(inlinetest == inlineobj, "got %p\n", inlinetest);
1986 ok(r2.startPosition == 0 && r2.length == 2, "got %d, %d\n", r2.startPosition, r2.length);
1987 IDWriteInlineObject_Release(inlinetest);
1988
1989 EXPECT_REF(inlineobj, 2);
1990
1991 /* get from somewhere inside a range */
1992 inlinetest = NULL;
1993 r2.startPosition = r2.length = 100;
1994 hr = IDWriteTextLayout_GetInlineObject(layout, 1, &inlinetest, &r2);
1995 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1996 ok(inlinetest == inlineobj, "got %p\n", inlinetest);
1997 ok(r2.startPosition == 0 && r2.length == 2, "got %d, %d\n", r2.startPosition, r2.length);
1998 IDWriteInlineObject_Release(inlinetest);
1999
2000 EXPECT_REF(inlineobj, 2);
2001
2002 range.startPosition = 1;
2003 range.length = 1;
2004 hr = IDWriteTextLayout_SetInlineObject(layout, inlineobj2, range);
2005 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2006
2007 inlinetest = NULL;
2008 r2.startPosition = r2.length = 100;
2009 hr = IDWriteTextLayout_GetInlineObject(layout, 1, &inlinetest, &r2);
2010 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2011 ok(inlinetest == inlineobj2, "got %p\n", inlinetest);
2012 ok(r2.startPosition == 1 && r2.length == 1, "got %d, %d\n", r2.startPosition, r2.length);
2013 IDWriteInlineObject_Release(inlinetest);
2014
2015 EXPECT_REF(inlineobj, 2);
2016 EXPECT_REF(inlineobj2, 2);
2017
2018 inlinetest = NULL;
2019 r2.startPosition = r2.length = 100;
2020 hr = IDWriteTextLayout_GetInlineObject(layout, 0, &inlinetest, &r2);
2021 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2022 ok(inlinetest == inlineobj, "got %p\n", inlinetest);
2023 ok(r2.startPosition == 0 && r2.length == 1, "got %d, %d\n", r2.startPosition, r2.length);
2024 IDWriteInlineObject_Release(inlinetest);
2025
2026 EXPECT_REF(inlineobj, 2);
2027
2028 range.startPosition = 1;
2029 range.length = 1;
2030 hr = IDWriteTextLayout_SetInlineObject(layout, inlineobj, range);
2031 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2032
2033 r2.startPosition = r2.length = 100;
2034 hr = IDWriteTextLayout_GetInlineObject(layout, 0, &inlinetest, &r2);
2035 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2036 ok(inlinetest == inlineobj, "got %p\n", inlinetest);
2037 ok(r2.startPosition == 0 && r2.length == 2, "got %d, %d\n", r2.startPosition, r2.length);
2038 IDWriteInlineObject_Release(inlinetest);
2039
2040 EXPECT_REF(inlineobj, 2);
2041
2042 range.startPosition = 1;
2043 range.length = 2;
2044 hr = IDWriteTextLayout_SetInlineObject(layout, inlineobj, range);
2045 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2046
2047 EXPECT_REF(inlineobj, 2);
2048
2049 r2.startPosition = r2.length = 100;
2050 hr = IDWriteTextLayout_GetInlineObject(layout, 0, &inlinetest, &r2);
2051 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2052 ok(inlinetest == inlineobj, "got %p\n", inlinetest);
2053 ok(r2.startPosition == 0 && r2.length == 3, "got %d, %d\n", r2.startPosition, r2.length);
2054 IDWriteInlineObject_Release(inlinetest);
2055
2056 EXPECT_REF(inlineobj, 2);
2057 EXPECT_REF(inlineobj2, 1);
2058
2059 IDWriteTextLayout_Release(layout);
2060
2061 EXPECT_REF(inlineobj, 1);
2062
2063 IDWriteInlineObject_Release(inlineobj);
2064 IDWriteInlineObject_Release(inlineobj2);
2065 IDWriteTextFormat_Release(format);
2066 IDWriteFactory_Release(factory);
2067}
2068
2069/* drawing calls sequence doesn't depend on run order, instead all runs are
2070 drawn first, inline objects next and then underline/strikes */
2071static const struct drawcall_entry draw_seq[] = {
2072 { DRAW_GLYPHRUN, {'s',0}, {'r','u',0}, 1 },
2073 { DRAW_GLYPHRUN, {'r','i',0}, {'r','u',0}, 2 },
2074 { DRAW_GLYPHRUN|DRAW_EFFECT, {'n',0}, {'r','u',0}, 1 },
2075 { DRAW_GLYPHRUN, {'g',0}, {'r','u',0}, 1 },
2076 { DRAW_INLINE },
2077 { DRAW_UNDERLINE, {0}, {'r','u',0} },
2079 { DRAW_LAST_KIND }
2080};
2081
2082static const struct drawcall_entry draw_trimmed_seq[] = {
2083 { DRAW_GLYPHRUN, {'a',0}, {'e','n','-','u','s',0}, 1 },
2084 { DRAW_LAST_KIND }
2085};
2086
2087static const struct drawcall_entry draw_seq2[] = {
2088 { DRAW_GLYPHRUN, {'s',0}, {'r','u',0}, 1 },
2089 { DRAW_GLYPHRUN, {'t',0}, {'r','u',0}, 1 },
2090 { DRAW_GLYPHRUN, {'r',0}, {'r','u',0}, 1 },
2091 { DRAW_GLYPHRUN, {'i',0}, {'r','u',0}, 1 },
2092 { DRAW_GLYPHRUN, {'n',0}, {'r','u',0}, 1 },
2093 { DRAW_GLYPHRUN, {'g',0}, {'r','u',0}, 1 },
2094 { DRAW_LAST_KIND }
2095};
2096
2097static const struct drawcall_entry draw_seq3[] = {
2098 { DRAW_GLYPHRUN, {0x202a,0x202c,0}, {'r','u',0}, 0 },
2099 { DRAW_GLYPHRUN, {'a','b',0}, {'r','u',0}, 2 },
2100 { DRAW_LAST_KIND }
2101};
2102
2103static const struct drawcall_entry draw_seq4[] = {
2104 { DRAW_GLYPHRUN, {'s','t','r',0}, {'r','u',0}, 3 },
2105 { DRAW_GLYPHRUN, {'i','n','g',0}, {'r','u',0}, 3 },
2107 { DRAW_LAST_KIND }
2108};
2109
2110static const struct drawcall_entry draw_seq5[] = {
2111 { DRAW_GLYPHRUN, {'s','t',0}, {'r','u',0}, 2 },
2112 { DRAW_GLYPHRUN, {'r','i',0}, {'r','u',0}, 2 },
2113 { DRAW_GLYPHRUN, {'n','g',0}, {'r','u',0}, 2 },
2115 { DRAW_LAST_KIND }
2116};
2117
2118static const struct drawcall_entry empty_seq[] = {
2119 { DRAW_LAST_KIND }
2120};
2121
2122static const struct drawcall_entry draw_single_run_seq[] = {
2123 { DRAW_GLYPHRUN, {'s','t','r','i','n','g',0}, {'r','u',0}, 6 },
2124 { DRAW_LAST_KIND }
2125};
2126
2128 { DRAW_GLYPHRUN, {'1','2','3','-','5','2',0}, {'r','u',0}, 6 },
2129 { DRAW_GLYPHRUN, {0x64a,0x64f,0x633,0x627,0x648,0x650,0x64a,0}, {'r','u',0}, 7, 1 },
2130 { DRAW_GLYPHRUN, {'7','1',0}, {'r','u',0}, 2, 2 },
2131 { DRAW_GLYPHRUN, {'.',0}, {'r','u',0}, 1 },
2132 { DRAW_LAST_KIND }
2133};
2134
2135static void test_Draw(void)
2136{
2137 static const WCHAR str3W[] = {'1','2','3','-','5','2',0x64a,0x64f,0x633,0x627,0x648,0x650,
2138 0x64a,'7','1','.',0};
2139 static const WCHAR str2W[] = {0x202a,0x202c,'a','b',0};
2140 IDWriteInlineObject *inlineobj;
2141 struct renderer_context ctxt;
2143 IDWriteTextLayout *layout;
2148 HRESULT hr;
2149
2151
2152 memset(&ctxt, 0, sizeof(ctxt));
2153 ctxt.snapping_disabled = TRUE;
2154
2155 hr = IDWriteFactory_CreateTextFormat(factory, L"Tahoma", NULL, DWRITE_FONT_WEIGHT_BOLD, DWRITE_FONT_STYLE_NORMAL,
2156 DWRITE_FONT_STRETCH_NORMAL, 10.0f, L"ru", &format);
2157 ok(hr == S_OK, "Failed to create text format, hr %#lx.\n", hr);
2158
2159 hr = IDWriteFactory_CreateTextLayout(factory, L"string", 6, format, 100.0f, 100.0f, &layout);
2160 ok(hr == S_OK, "Failed to create text layout, hr %#lx.\n", hr);
2161
2162 hr = IDWriteFactory_CreateEllipsisTrimmingSign(factory, format, &inlineobj);
2163 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2164
2165 range.startPosition = 5;
2166 range.length = 1;
2167 hr = IDWriteTextLayout_SetStrikethrough(layout, TRUE, range);
2168 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2169
2170 range.startPosition = 1;
2171 range.length = 1;
2172 hr = IDWriteTextLayout_SetInlineObject(layout, inlineobj, range);
2173 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2174
2175 range.startPosition = 4;
2176 range.length = 1;
2177 hr = IDWriteTextLayout_SetDrawingEffect(layout, (IUnknown*)inlineobj, range);
2178 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2179
2180 range.startPosition = 0;
2181 range.length = 1;
2182 hr = IDWriteTextLayout_SetUnderline(layout, TRUE, range);
2183 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2184
2186 hr = IDWriteTextLayout_Draw(layout, &ctxt, &testrenderer, 0.0, 0.0);
2187 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2189 IDWriteTextLayout_Release(layout);
2190
2191 /* with reduced width DrawGlyphRun() is called for every line */
2192 hr = IDWriteFactory_CreateTextLayout(factory, L"string", 6, format, 5.0f, 100.0f, &layout);
2193 ok(hr == S_OK, "Failed to create text layout, hr %#lx.\n", hr);
2195 hr = IDWriteTextLayout_Draw(layout, &ctxt, &testrenderer, 0.0, 0.0);
2196 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2197 ok_sequence(sequences, RENDERER_ID, draw_seq2, "draw test 2", TRUE);
2198 hr = IDWriteTextLayout_GetMetrics(layout, &tm);
2199 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2200 todo_wine
2201 ok(tm.lineCount == 6, "got %u\n", tm.lineCount);
2202 IDWriteTextLayout_Release(layout);
2203
2204 /* string with control characters */
2205 hr = IDWriteFactory_CreateTextLayout(factory, str2W, 4, format, 500.0, 100.0, &layout);
2206 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2208 hr = IDWriteTextLayout_Draw(layout, &ctxt, &testrenderer, 0.0, 0.0);
2209 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2210 ok_sequence(sequences, RENDERER_ID, draw_seq3, "draw test 3", FALSE);
2211 IDWriteTextLayout_Release(layout);
2212
2213 /* strikethrough splits ranges from renderer point of view, but doesn't break
2214 shaping */
2215 hr = IDWriteFactory_CreateTextLayout(factory, L"string", 6, format, 500.0f, 100.0f, &layout);
2216 ok(hr == S_OK, "Failed to create text layout, hr %#lx.\n", hr);
2218
2219 range.startPosition = 0;
2220 range.length = 3;
2221 hr = IDWriteTextLayout_SetStrikethrough(layout, TRUE, range);
2222 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2223
2224 hr = IDWriteTextLayout_Draw(layout, &ctxt, &testrenderer, 0.0, 0.0);
2225 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2226 ok_sequence(sequences, RENDERER_ID, draw_seq4, "draw test 4", FALSE);
2227 IDWriteTextLayout_Release(layout);
2228
2229 /* Strike through somewhere in the middle */
2230 hr = IDWriteFactory_CreateTextLayout(factory, L"string", 6, format, 500.0f, 100.0f, &layout);
2231 ok(hr == S_OK, "Failed to create text layout, hr %#lx.\n", hr);
2233
2234 range.startPosition = 2;
2235 range.length = 2;
2236 hr = IDWriteTextLayout_SetStrikethrough(layout, TRUE, range);
2237 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2238
2239 hr = IDWriteTextLayout_Draw(layout, &ctxt, &testrenderer, 0.0, 0.0);
2240 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2241 ok_sequence(sequences, RENDERER_ID, draw_seq5, "draw test 5", FALSE);
2242 IDWriteTextLayout_Release(layout);
2243
2244 /* empty string */
2245 hr = IDWriteFactory_CreateTextLayout(factory, L"string", 0, format, 500.0f, 100.0f, &layout);
2246 ok(hr == S_OK, "Failed to create text layout, hr %#lx.\n", hr);
2247
2249 hr = IDWriteTextLayout_Draw(layout, &ctxt, &testrenderer, 0.0, 0.0);
2250 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2251 ok_sequence(sequences, RENDERER_ID, empty_seq, "draw test 6", FALSE);
2252 IDWriteTextLayout_Release(layout);
2253
2254 ctxt.gdicompat = TRUE;
2255 ctxt.use_gdi_natural = TRUE;
2256
2257 /* different parameter combinations with gdi-compatible layout */
2258 hr = IDWriteFactory_CreateGdiCompatibleTextLayout(factory, L"string", 6, format, 100.0f, 100.0f, 1.0f, NULL,
2259 TRUE, &layout);
2260 ok(hr == S_OK, "Failed to create text layout, hr %#lx.\n", hr);
2262 hr = IDWriteTextLayout_Draw(layout, &ctxt, &testrenderer, 0.0, 0.0);
2263 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2265
2266 /* text alignment keeps pixel-aligned origin */
2267 hr = IDWriteTextLayout_GetMetrics(layout, &tm);
2268 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2269 ok(tm.width == floorf(tm.width), "got %f\n", tm.width);
2270
2271 hr = IDWriteTextLayout_SetMaxWidth(layout, tm.width + 3.0);
2272 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2273 hr = IDWriteTextLayout_SetTextAlignment(layout, DWRITE_TEXT_ALIGNMENT_CENTER);
2274 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2275
2276 ctxt.originX = ctxt.originY = 0.0;
2278 hr = IDWriteTextLayout_Draw(layout, &ctxt, &testrenderer, 0.0, 0.0);
2279 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2281 ok(ctxt.originX != 0.0 && ctxt.originX == floorf(ctxt.originX), "got %f\n", ctxt.originX);
2282
2283 IDWriteTextLayout_Release(layout);
2284
2285 ctxt.gdicompat = TRUE;
2286 ctxt.use_gdi_natural = FALSE;
2287
2288 hr = IDWriteFactory_CreateGdiCompatibleTextLayout(factory, L"string", 6, format, 100.0f, 100.0f, 1.0f, NULL,
2289 FALSE, &layout);
2290 ok(hr == S_OK, "Failed to create text layout, hr %#lx.\n", hr);
2292 hr = IDWriteTextLayout_Draw(layout, &ctxt, &testrenderer, 0.0, 0.0);
2293 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2295 IDWriteTextLayout_Release(layout);
2296
2297 ctxt.gdicompat = TRUE;
2298 ctxt.use_gdi_natural = TRUE;
2299
2300 m.m11 = m.m22 = 2.0;
2301 m.m12 = m.m21 = m.dx = m.dy = 0.0;
2302 hr = IDWriteFactory_CreateGdiCompatibleTextLayout(factory, L"string", 6, format, 100.0f, 100.0f, 1.0f, &m,
2303 TRUE, &layout);
2304 ok(hr == S_OK, "Failed to create text layout, hr %#lx.\n", hr);
2306 hr = IDWriteTextLayout_Draw(layout, &ctxt, &testrenderer, 0.0, 0.0);
2307 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2309 IDWriteTextLayout_Release(layout);
2310
2311 ctxt.gdicompat = TRUE;
2312 ctxt.use_gdi_natural = FALSE;
2313
2314 m.m11 = m.m22 = 2.0;
2315 m.m12 = m.m21 = m.dx = m.dy = 0.0;
2316 hr = IDWriteFactory_CreateGdiCompatibleTextLayout(factory, L"string", 6, format, 100.0f, 100.0f, 1.0f, &m,
2317 FALSE, &layout);
2318 ok(hr == S_OK, "Failed to create text layout, hr %#lx.\n", hr);
2320 hr = IDWriteTextLayout_Draw(layout, &ctxt, &testrenderer, 0.0, 0.0);
2321 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2323 IDWriteTextLayout_Release(layout);
2324
2325 IDWriteInlineObject_Release(inlineobj);
2326
2327 /* text that triggers bidi run reordering */
2328 hr = IDWriteFactory_CreateTextLayout(factory, str3W, lstrlenW(str3W), format, 1000.0f, 100.0f, &layout);
2329 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2330
2331 ctxt.gdicompat = FALSE;
2332 ctxt.use_gdi_natural = FALSE;
2333 ctxt.snapping_disabled = TRUE;
2334
2335 hr = IDWriteTextLayout_SetReadingDirection(layout, DWRITE_READING_DIRECTION_LEFT_TO_RIGHT);
2336 ok(hr == S_OK, "Failed to set reading direction, hr %#lx.\n", hr);
2337
2339 hr = IDWriteTextLayout_Draw(layout, &ctxt, &testrenderer, 0.0f, 0.0f);
2340 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2342
2343 IDWriteTextLayout_Release(layout);
2344
2345 IDWriteTextFormat_Release(format);
2346 IDWriteFactory_Release(factory);
2347}
2348
2349static void test_typography(void)
2350{
2352 IDWriteTypography *typography;
2354 UINT32 count;
2355 HRESULT hr;
2356
2358
2359 hr = IDWriteFactory_CreateTypography(factory, &typography);
2360 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2361
2363 feature.parameter = 1;
2364 hr = IDWriteTypography_AddFontFeature(typography, feature);
2365 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2366
2367 count = IDWriteTypography_GetFontFeatureCount(typography);
2368 ok(count == 1, "got %u\n", count);
2369
2370 /* duplicated features work just fine */
2372 feature.parameter = 0;
2373 hr = IDWriteTypography_AddFontFeature(typography, feature);
2374 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2375
2376 count = IDWriteTypography_GetFontFeatureCount(typography);
2377 ok(count == 2, "got %u\n", count);
2378
2379 memset(&feature, 0xcc, sizeof(feature));
2380 hr = IDWriteTypography_GetFontFeature(typography, 0, &feature);
2381 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2382 ok(feature.nameTag == DWRITE_FONT_FEATURE_TAG_KERNING, "got tag %x\n", feature.nameTag);
2383 ok(feature.parameter == 1, "got %u\n", feature.parameter);
2384
2385 memset(&feature, 0xcc, sizeof(feature));
2386 hr = IDWriteTypography_GetFontFeature(typography, 1, &feature);
2387 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2388 ok(feature.nameTag == DWRITE_FONT_FEATURE_TAG_KERNING, "got tag %x\n", feature.nameTag);
2389 ok(feature.parameter == 0, "got %u\n", feature.parameter);
2390
2391 hr = IDWriteTypography_GetFontFeature(typography, 2, &feature);
2392 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
2393
2394 /* duplicated with same parameter value */
2396 feature.parameter = 0;
2397 hr = IDWriteTypography_AddFontFeature(typography, feature);
2398 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2399
2400 count = IDWriteTypography_GetFontFeatureCount(typography);
2401 ok(count == 3, "got %u\n", count);
2402
2403 memset(&feature, 0xcc, sizeof(feature));
2404 hr = IDWriteTypography_GetFontFeature(typography, 2, &feature);
2405 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2406 ok(feature.nameTag == DWRITE_FONT_FEATURE_TAG_KERNING, "got tag %x\n", feature.nameTag);
2407 ok(feature.parameter == 0, "got %u\n", feature.parameter);
2408
2409 IDWriteTypography_Release(typography);
2410 IDWriteFactory_Release(factory);
2411}
2412
2413static void test_GetClusterMetrics(void)
2414{
2415 static const WCHAR str_white_spaceW[] = {
2416 /* BK - FORM FEED, LINE TABULATION, LINE SEP, PARA SEP */ 0xc, 0xb, 0x2028, 0x2029,
2417 /* ZW - ZERO WIDTH SPACE */ 0x200b,
2418 /* SP - SPACE */ 0x20
2419 };
2420 static const WCHAR str5W[] = {'a','\r','b','\n','c','\n','\r','d','\r','\n','e',0xb,'f',0xc,
2421 'g',0x0085,'h',0x2028,'i',0x2029,0xad,0xa,0};
2422 static const WCHAR str3W[] = {0x2066,')',')',0x661,'(',0x627,')',0};
2423 static const WCHAR str2W[] = {0x202a,0x202c,'a',0};
2424
2425 struct test_inline_obj *testinlineobj, *testinlineobj2, *testinlineobj3;
2426 DWRITE_INLINE_OBJECT_METRICS inline_metrics;
2428 DWRITE_TEXT_METRICS text_metrics;
2429 DWRITE_TRIMMING trimming_options;
2430 IDWriteTextLayout1 *layout1;
2431 IDWriteInlineObject *trimm;
2433 IDWriteTextLayout *layout;
2437 UINT32 count, i;
2438 FLOAT width;
2439 HRESULT hr;
2440
2442 ok(!!testinlineobj, "Failed to create test inline object.\n");
2444 ok(!!testinlineobj2, "Failed to create test inline object.\n");
2446 ok(!!testinlineobj3, "Failed to create test inline object.\n");
2447
2449
2450 hr = IDWriteFactory_CreateTextFormat(factory, L"Tahoma", NULL, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL,
2451 DWRITE_FONT_STRETCH_NORMAL, 10.0f, L"en-us", &format);
2452 ok(hr == S_OK, "Failed to create text format, hr %#lx.\n", hr);
2453
2454 hr = IDWriteFactory_CreateTextLayout(factory, str3W, 7, format, 1000.0, 1000.0, &layout);
2455 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2456 hr = IDWriteTextLayout_GetClusterMetrics(layout, NULL, 0, &count);
2457 ok(hr == E_NOT_SUFFICIENT_BUFFER, "Unexpected hr %#lx.\n", hr);
2458 ok(count == 7, "got %u\n", count);
2459 IDWriteTextLayout_Release(layout);
2460
2461 hr = IDWriteFactory_CreateTextLayout(factory, L"abcd", 4, format, 1000.0f, 1000.0f, &layout);
2462 ok(hr == S_OK, "Failed to create text layout, hr %#lx.\n", hr);
2463
2464 count = 0;
2465 hr = IDWriteTextLayout_GetClusterMetrics(layout, NULL, 0, &count);
2466 ok(hr == E_NOT_SUFFICIENT_BUFFER, "Unexpected hr %#lx.\n", hr);
2467 ok(count == 4, "got %u\n", count);
2468
2469 /* check every cluster width */
2470 count = 0;
2471 hr = IDWriteTextLayout_GetClusterMetrics(layout, metrics, ARRAY_SIZE(metrics), &count);
2472 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2473 ok(count == 4, "got %u\n", count);
2474 for (i = 0; i < count; i++) {
2475 ok(metrics[i].width > 0.0, "%u: got width %.2f\n", i, metrics[i].width);
2476 ok(metrics[i].length == 1, "%u: got length %u\n", i, metrics[i].length);
2477 }
2478
2479 /* apply spacing and check widths again */
2480 if (IDWriteTextLayout_QueryInterface(layout, &IID_IDWriteTextLayout1, (void**)&layout1) == S_OK) {
2481 DWRITE_CLUSTER_METRICS metrics2[4];
2482 FLOAT leading, trailing, min_advance;
2484
2485 leading = trailing = min_advance = 2.0;
2486 hr = IDWriteTextLayout1_GetCharacterSpacing(layout1, 500, &leading, &trailing,
2487 &min_advance, &r);
2488 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2489 ok(leading == 0.0 && trailing == 0.0 && min_advance == 0.0,
2490 "got %.2f, %.2f, %.2f\n", leading, trailing, min_advance);
2491 ok(r.startPosition == 0 && r.length == ~0u, "got %u, %u\n", r.startPosition, r.length);
2492
2493 leading = trailing = min_advance = 2.0;
2494 hr = IDWriteTextLayout1_GetCharacterSpacing(layout1, 0, &leading, &trailing,
2495 &min_advance, NULL);
2496 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2497 ok(leading == 0.0 && trailing == 0.0 && min_advance == 0.0,
2498 "got %.2f, %.2f, %.2f\n", leading, trailing, min_advance);
2499
2500 r.startPosition = 0;
2501 r.length = 4;
2502 hr = IDWriteTextLayout1_SetCharacterSpacing(layout1, 10.0, 15.0, 0.0, r);
2503 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2504
2505 count = 0;
2506 hr = IDWriteTextLayout_GetClusterMetrics(layout, metrics2, ARRAY_SIZE(metrics2), &count);
2507 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2508 ok(count == 4, "got %u\n", count);
2509 for (i = 0; i < count; ++i)
2510 {
2511 ok(metrics2[i].width > metrics[i].width, "%u: got width %.2f, was %.2f\n", i, metrics2[i].width,
2512 metrics[i].width);
2513 ok(metrics2[i].length == 1, "%u: got length %u\n", i, metrics2[i].length);
2514 }
2515
2516 /* back to defaults */
2517 r.startPosition = 0;
2518 r.length = 4;
2519 hr = IDWriteTextLayout1_SetCharacterSpacing(layout1, 0.0, 0.0, 0.0, r);
2520 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2521
2522 /* negative advance limit */
2523 r.startPosition = 0;
2524 r.length = 4;
2525 hr = IDWriteTextLayout1_SetCharacterSpacing(layout1, 0.0, 0.0, -10.0, r);
2526 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
2527
2528 IDWriteTextLayout1_Release(layout1);
2529 }
2530 else
2531 win_skip("IDWriteTextLayout1 is not supported, cluster spacing test skipped.\n");
2532
2533 hr = IDWriteFactory_CreateEllipsisTrimmingSign(factory, format, &trimm);
2534 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2535
2536 range.startPosition = 0;
2537 range.length = 2;
2538 hr = IDWriteTextLayout_SetInlineObject(layout, trimm, range);
2539 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2540
2541 /* inline object takes a separate cluster, replaced codepoints number doesn't matter */
2542 count = 0;
2543 hr = IDWriteTextLayout_GetClusterMetrics(layout, NULL, 0, &count);
2544 ok(hr == E_NOT_SUFFICIENT_BUFFER, "Unexpected hr %#lx.\n", hr);
2545 ok(count == 3, "got %u\n", count);
2546
2547 count = 0;
2548 memset(&metrics, 0, sizeof(metrics));
2549 hr = IDWriteTextLayout_GetClusterMetrics(layout, metrics, 1, &count);
2550 ok(hr == E_NOT_SUFFICIENT_BUFFER, "Unexpected hr %#lx.\n", hr);
2551 ok(count == 3, "got %u\n", count);
2552 ok(metrics[0].length == 2, "got %u\n", metrics[0].length);
2553
2554 hr = IDWriteInlineObject_GetMetrics(trimm, &inline_metrics);
2555 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2556 ok(inline_metrics.width > 0.0 && inline_metrics.width == metrics[0].width, "got %.2f, expected %.2f\n",
2557 inline_metrics.width, metrics[0].width);
2558
2559 IDWriteTextLayout_Release(layout);
2560
2561 /* text with non-visual control codes */
2562 hr = IDWriteFactory_CreateTextLayout(factory, str2W, 3, format, 1000.0, 1000.0, &layout);
2563 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2564
2565 /* bidi control codes take a separate cluster */
2566 count = 0;
2567 memset(metrics, 0, sizeof(metrics));
2568 hr = IDWriteTextLayout_GetClusterMetrics(layout, metrics, 3, &count);
2569 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2570 ok(count == 3, "got %u\n", count);
2571
2572 ok(metrics[0].width == 0.0, "got %.2f\n", metrics[0].width);
2573 ok(metrics[0].length == 1, "got %d\n", metrics[0].length);
2574 ok(metrics[0].canWrapLineAfter == 0, "got %d\n", metrics[0].canWrapLineAfter);
2575 ok(metrics[0].isWhitespace == 0, "got %d\n", metrics[0].isWhitespace);
2576 ok(metrics[0].isNewline == 0, "got %d\n", metrics[0].isNewline);
2577 ok(metrics[0].isSoftHyphen == 0, "got %d\n", metrics[0].isSoftHyphen);
2578 ok(metrics[0].isRightToLeft == 0, "got %d\n", metrics[0].isRightToLeft);
2579
2580 ok(metrics[1].width == 0.0, "got %.2f\n", metrics[1].width);
2581 ok(metrics[1].length == 1, "got %d\n", metrics[1].length);
2582 ok(metrics[1].canWrapLineAfter == 0, "got %d\n", metrics[1].canWrapLineAfter);
2583 ok(metrics[1].isWhitespace == 0, "got %d\n", metrics[1].isWhitespace);
2584 ok(metrics[1].isNewline == 0, "got %d\n", metrics[1].isNewline);
2585 ok(metrics[1].isSoftHyphen == 0, "got %d\n", metrics[1].isSoftHyphen);
2586 ok(metrics[1].isRightToLeft == 0, "got %d\n", metrics[1].isRightToLeft);
2587
2588 ok(metrics[2].width > 0.0, "got %.2f\n", metrics[2].width);
2589 ok(metrics[2].length == 1, "got %d\n", metrics[2].length);
2590 ok(metrics[2].canWrapLineAfter == 1, "got %d\n", metrics[2].canWrapLineAfter);
2591 ok(metrics[2].isWhitespace == 0, "got %d\n", metrics[2].isWhitespace);
2592 ok(metrics[2].isNewline == 0, "got %d\n", metrics[2].isNewline);
2593 ok(metrics[2].isSoftHyphen == 0, "got %d\n", metrics[2].isSoftHyphen);
2594 ok(metrics[2].isRightToLeft == 0, "got %d\n", metrics[2].isRightToLeft);
2595
2596 IDWriteTextLayout_Release(layout);
2597
2598 /* single inline object that fails to report its metrics */
2599 hr = IDWriteFactory_CreateTextLayout(factory, L"abcd", 4, format, 1000.0f, 1000.0f, &layout);
2600 ok(hr == S_OK, "Failed to create text layout, hr %#lx.\n", hr);
2601
2602 range.startPosition = 0;
2603 range.length = 4;
2604 hr = IDWriteTextLayout_SetInlineObject(layout, &testinlineobj->IDWriteInlineObject_iface, range);
2605 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2606
2607 count = 0;
2608 memset(metrics, 0, sizeof(metrics));
2609 hr = IDWriteTextLayout_GetClusterMetrics(layout, metrics, 3, &count);
2610 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2611 ok(count == 1, "got %u\n", count);
2612
2613 /* object sets a width to 123.0, but returns failure from GetMetrics() */
2614 ok(metrics[0].width == 0.0, "got %.2f\n", metrics[0].width);
2615 ok(metrics[0].length == 4, "got %d\n", metrics[0].length);
2616 ok(metrics[0].canWrapLineAfter == 1, "got %d\n", metrics[0].canWrapLineAfter);
2617 ok(metrics[0].isWhitespace == 0, "got %d\n", metrics[0].isWhitespace);
2618 ok(metrics[0].isNewline == 0, "got %d\n", metrics[0].isNewline);
2619 ok(metrics[0].isSoftHyphen == 0, "got %d\n", metrics[0].isSoftHyphen);
2620 ok(metrics[0].isRightToLeft == 0, "got %d\n", metrics[0].isRightToLeft);
2621
2622 /* now set two inline object for [0,1] and [2,3], both fail to report break conditions */
2623 range.startPosition = 2;
2624 range.length = 2;
2625 hr = IDWriteTextLayout_SetInlineObject(layout, &testinlineobj2->IDWriteInlineObject_iface, range);
2626 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2627
2628 count = 0;
2629 memset(metrics, 0, sizeof(metrics));
2630 hr = IDWriteTextLayout_GetClusterMetrics(layout, metrics, 3, &count);
2631 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2632 ok(count == 2, "got %u\n", count);
2633
2634 ok(metrics[0].width == 0.0, "got %.2f\n", metrics[0].width);
2635 ok(metrics[0].length == 2, "got %d\n", metrics[0].length);
2636 ok(metrics[0].canWrapLineAfter == 0, "got %d\n", metrics[0].canWrapLineAfter);
2637 ok(metrics[0].isWhitespace == 0, "got %d\n", metrics[0].isWhitespace);
2638 ok(metrics[0].isNewline == 0, "got %d\n", metrics[0].isNewline);
2639 ok(metrics[0].isSoftHyphen == 0, "got %d\n", metrics[0].isSoftHyphen);
2640 ok(metrics[0].isRightToLeft == 0, "got %d\n", metrics[0].isRightToLeft);
2641
2642 ok(metrics[1].width == 0.0, "got %.2f\n", metrics[1].width);
2643 ok(metrics[1].length == 2, "got %d\n", metrics[1].length);
2644 ok(metrics[1].canWrapLineAfter == 1, "got %d\n", metrics[1].canWrapLineAfter);
2645 ok(metrics[1].isWhitespace == 0, "got %d\n", metrics[1].isWhitespace);
2646 ok(metrics[1].isNewline == 0, "got %d\n", metrics[1].isNewline);
2647 ok(metrics[1].isSoftHyphen == 0, "got %d\n", metrics[1].isSoftHyphen);
2648 ok(metrics[1].isRightToLeft == 0, "got %d\n", metrics[1].isRightToLeft);
2649
2650 IDWriteTextLayout_Release(layout);
2651
2652 /* zero length string */
2653 hr = IDWriteFactory_CreateTextLayout(factory, L"abcd", 0, format, 1000.0f, 1000.0f, &layout);
2654 ok(hr == S_OK, "Failed to create text layout, hr %#lx.\n", hr);
2655
2656 count = 1;
2657 memset(metrics, 0, sizeof(metrics));
2658 hr = IDWriteTextLayout_GetClusterMetrics(layout, metrics, 3, &count);
2659 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2660 ok(count == 0, "got %u\n", count);
2661 IDWriteTextLayout_Release(layout);
2662
2663 /* Whitespace */
2664 hr = IDWriteFactory_CreateTextLayout(factory, L"a ", 2, format, 1000.0f, 1000.0f, &layout);
2665 ok(hr == S_OK, "Failed to create text layout, hr %#lx.\n", hr);
2666
2667 count = 0;
2668 memset(metrics, 0, sizeof(metrics));
2669 hr = IDWriteTextLayout_GetClusterMetrics(layout, metrics, 2, &count);
2670 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2671 ok(count == 2, "got %u\n", count);
2672 ok(metrics[0].isWhitespace == 0, "got %d\n", metrics[0].isWhitespace);
2673 ok(metrics[0].canWrapLineAfter == 0, "got %d\n", metrics[0].canWrapLineAfter);
2674 ok(metrics[1].isWhitespace == 1, "got %d\n", metrics[1].isWhitespace);
2675 ok(metrics[1].canWrapLineAfter == 1, "got %d\n", metrics[1].canWrapLineAfter);
2676 IDWriteTextLayout_Release(layout);
2677
2678 /* Layout is fully covered by inline object with after condition DWRITE_BREAK_CONDITION_MAY_NOT_BREAK. */
2679 hr = IDWriteFactory_CreateTextLayout(factory, L"a ", 2, format, 1000.0f, 1000.0f, &layout);
2680 ok(hr == S_OK, "Failed to create text layout, hr %#lx.\n", hr);
2681
2682 range.startPosition = 0;
2683 hr = IDWriteTextLayout_SetInlineObject(layout, &testinlineobj3->IDWriteInlineObject_iface, range);
2684 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2685
2686 count = 0;
2687 memset(metrics, 0, sizeof(metrics));
2688 hr = IDWriteTextLayout_GetClusterMetrics(layout, metrics, 2, &count);
2689 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2690 ok(count == 1, "got %u\n", count);
2691 ok(metrics[0].canWrapLineAfter == 1, "got %d\n", metrics[0].canWrapLineAfter);
2692
2693 IDWriteTextLayout_Release(layout);
2694
2695 /* compare natural cluster width with gdi layout */
2696 hr = IDWriteFactory_CreateTextLayout(factory, L"a ", 1, format, 100.0f, 100.0f, &layout);
2697 ok(hr == S_OK, "Failed to create text layout, hr %#lx.\n", hr);
2698
2699 count = 0;
2700 memset(metrics, 0, sizeof(metrics));
2701 hr = IDWriteTextLayout_GetClusterMetrics(layout, metrics, 1, &count);
2702 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2703 ok(count == 1, "got %u\n", count);
2704 ok(metrics[0].width != floorf(metrics[0].width), "got %f\n", metrics[0].width);
2705
2706 IDWriteTextLayout_Release(layout);
2707
2708 hr = IDWriteFactory_CreateGdiCompatibleTextLayout(factory, L"a ", 1, format, 100.0f, 100.0f, 1.0f, NULL,
2709 FALSE, &layout);
2710 ok(hr == S_OK, "Failed to create text layout, hr %#lx.\n", hr);
2711
2712 count = 0;
2713 memset(metrics, 0, sizeof(metrics));
2714 hr = IDWriteTextLayout_GetClusterMetrics(layout, metrics, 1, &count);
2715 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2716 ok(count == 1, "got %u\n", count);
2717 ok(metrics[0].width == floorf(metrics[0].width), "got %f\n", metrics[0].width);
2718
2719 IDWriteTextLayout_Release(layout);
2720
2721 /* isNewline tests */
2722 hr = IDWriteFactory_CreateTextLayout(factory, str5W, lstrlenW(str5W), format, 100.0f, 200.0f, &layout);
2723 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2724
2725 count = 0;
2726 memset(metrics, 0, sizeof(metrics));
2727 hr = IDWriteTextLayout_GetClusterMetrics(layout, metrics, ARRAY_SIZE(metrics), &count);
2728 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2729 ok(count == 22, "got %u\n", count);
2730
2731 ok(metrics[1].isNewline == 1, "got %d\n", metrics[1].isNewline);
2732 ok(metrics[3].isNewline == 1, "got %d\n", metrics[3].isNewline);
2733 ok(metrics[5].isNewline == 1, "got %d\n", metrics[5].isNewline);
2734 ok(metrics[6].isNewline == 1, "got %d\n", metrics[6].isNewline);
2735 ok(metrics[9].isNewline == 1, "got %d\n", metrics[9].isNewline);
2736 ok(metrics[11].isNewline == 1, "got %d\n", metrics[11].isNewline);
2737 ok(metrics[13].isNewline == 1, "got %d\n", metrics[13].isNewline);
2738 ok(metrics[15].isNewline == 1, "got %d\n", metrics[15].isNewline);
2739 ok(metrics[17].isNewline == 1, "got %d\n", metrics[17].isNewline);
2740 ok(metrics[19].isNewline == 1, "got %d\n", metrics[19].isNewline);
2741 ok(metrics[21].isNewline == 1, "got %d\n", metrics[21].isNewline);
2742
2743 ok(metrics[0].isNewline == 0, "got %d\n", metrics[0].isNewline);
2744 ok(metrics[2].isNewline == 0, "got %d\n", metrics[2].isNewline);
2745 ok(metrics[4].isNewline == 0, "got %d\n", metrics[4].isNewline);
2746 ok(metrics[7].isNewline == 0, "got %d\n", metrics[7].isNewline);
2747 ok(metrics[8].isNewline == 0, "got %d\n", metrics[8].isNewline);
2748 ok(metrics[10].isNewline == 0, "got %d\n", metrics[10].isNewline);
2749 ok(metrics[12].isNewline == 0, "got %d\n", metrics[12].isNewline);
2750 ok(metrics[14].isNewline == 0, "got %d\n", metrics[14].isNewline);
2751 ok(metrics[16].isNewline == 0, "got %d\n", metrics[16].isNewline);
2752 ok(metrics[18].isNewline == 0, "got %d\n", metrics[18].isNewline);
2753 ok(metrics[20].isNewline == 0, "got %d\n", metrics[20].isNewline);
2754
2755 for (i = 0; i < count; i++) {
2756 ok(metrics[i].length == 1, "%d: got %d\n", i, metrics[i].length);
2757 ok(metrics[i].isSoftHyphen == (i == count - 2), "%d: got %d\n", i, metrics[i].isSoftHyphen);
2758 if (metrics[i].isSoftHyphen)
2759 ok(!metrics[i].isWhitespace, "%u: got %d\n", i, metrics[i].isWhitespace);
2760 if (metrics[i].isNewline) {
2761 ok(metrics[i].width == 0.0f, "%u: got width %f\n", i, metrics[i].width);
2762 ok(metrics[i].isWhitespace == 1, "%u: got %d\n", i, metrics[i].isWhitespace);
2763 ok(metrics[i].canWrapLineAfter == 1, "%u: got %d\n", i, metrics[i].canWrapLineAfter);
2764 }
2765 }
2766
2767 IDWriteTextLayout_Release(layout);
2768
2769 /* Test whitespace resolution from linebreaking classes BK, ZW, and SP */
2770 hr = IDWriteFactory_CreateTextLayout(factory, str_white_spaceW, ARRAY_SIZE(str_white_spaceW), format,
2771 100.0f, 200.0f, &layout);
2772 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2773
2774 count = 0;
2775 memset(metrics, 0, sizeof(metrics));
2776 hr = IDWriteTextLayout_GetClusterMetrics(layout, metrics, 20, &count);
2777 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2778 ok(count == 6, "got %u\n", count);
2779
2780 ok(metrics[0].isWhitespace == 1, "got %d\n", metrics[0].isWhitespace);
2781 ok(metrics[1].isWhitespace == 1, "got %d\n", metrics[1].isWhitespace);
2782 ok(metrics[2].isWhitespace == 1, "got %d\n", metrics[2].isWhitespace);
2783 ok(metrics[3].isWhitespace == 1, "got %d\n", metrics[3].isWhitespace);
2784 ok(metrics[4].isWhitespace == 0, "got %d\n", metrics[4].isWhitespace);
2785 ok(metrics[5].isWhitespace == 1, "got %d\n", metrics[5].isWhitespace);
2786
2787 IDWriteTextLayout_Release(layout);
2788
2789 /* Trigger line trimming. */
2790 hr = IDWriteFactory_CreateTextLayout(factory, L"abcd", 4, format, 100.0f, 200.0f, &layout);
2791 ok(hr == S_OK, "Failed to create text layout, hr %#lx.\n", hr);
2792
2793 count = 0;
2794 memset(metrics, 0, sizeof(metrics));
2795 hr = IDWriteTextLayout_GetClusterMetrics(layout, metrics, 4, &count);
2796 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2797 ok(count == 4, "got %u\n", count);
2798
2799 hr = IDWriteTextLayout_GetMetrics(layout, &text_metrics);
2800 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2801
2802 width = metrics[0].width + inline_metrics.width;
2803 ok(width < text_metrics.width, "unexpected trimming sign width\n");
2804
2805 /* enable trimming, reduce layout width so only first cluster and trimming sign fits */
2807 trimming_options.delimiter = 0;
2808 trimming_options.delimiterCount = 0;
2809 hr = IDWriteTextLayout_SetTrimming(layout, &trimming_options, trimm);
2810 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2811
2812 hr = IDWriteTextLayout_SetMaxWidth(layout, width);
2813 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2814
2815 count = 0;
2816 memset(metrics, 0, sizeof(metrics));
2817 hr = IDWriteTextLayout_GetClusterMetrics(layout, metrics, 4, &count);
2818 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2819 ok(count == 4, "got %u\n", count);
2820
2821 hr = IDWriteTextLayout_GetLineMetrics(layout, &line, 1, &count);
2822 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2823 ok(count == 1, "got %u\n", count);
2824 ok(line.length == 4, "got %u\n", line.length);
2825 ok(line.isTrimmed, "got %d\n", line.isTrimmed);
2826
2827 IDWriteTextLayout_Release(layout);
2828
2829 /* NO_WRAP, check cluster wrapping attribute. */
2830 hr = IDWriteTextFormat_SetWordWrapping(format, DWRITE_WORD_WRAPPING_NO_WRAP);
2831 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2832
2833 hr = IDWriteFactory_CreateTextLayout(factory, L"a b", 3, format, 1000.0f, 200.0f, &layout);
2834 ok(hr == S_OK, "Failed to create text layout, hr %#lx.\n", hr);
2835
2836 count = 0;
2837 memset(metrics, 0, sizeof(metrics));
2838 hr = IDWriteTextLayout_GetClusterMetrics(layout, metrics, 3, &count);
2839 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2840 ok(count == 3, "got %u\n", count);
2841
2842 ok(metrics[0].canWrapLineAfter == 0, "got %d\n", metrics[0].canWrapLineAfter);
2843 ok(metrics[1].canWrapLineAfter == 1, "got %d\n", metrics[1].canWrapLineAfter);
2844 ok(metrics[2].canWrapLineAfter == 1, "got %d\n", metrics[2].canWrapLineAfter);
2845
2846 IDWriteTextLayout_Release(layout);
2847
2848 /* Single cluster layout, trigger trimming. */
2849 hr = IDWriteFactory_CreateTextLayout(factory, L"a b", 1, format, 1000.0f, 200.0f, &layout);
2850 ok(hr == S_OK, "Failed to create layout, hr %#lx.\n", hr);
2851
2852 count = 0;
2853 memset(metrics, 0, sizeof(metrics));
2854 hr = IDWriteTextLayout_GetClusterMetrics(layout, metrics, 1, &count);
2855 ok(hr == S_OK, "Failed to get cluster metrics, hr %#lx.\n", hr);
2856 ok(count == 1, "Unexpected cluster count %u.\n", count);
2857
2858 hr = IDWriteTextLayout_SetMaxWidth(layout, metrics[0].width / 2.0f);
2859 ok(hr == S_OK, "Failed to set layout width, hr %#lx.\n", hr);
2860
2862 trimming_options.delimiter = 0;
2863 trimming_options.delimiterCount = 0;
2864 hr = IDWriteTextLayout_SetTrimming(layout, &trimming_options, trimm);
2865 ok(hr == S_OK, "Failed to set trimming options, hr %#lx.\n", hr);
2866
2867 count = 0;
2868 memset(metrics, 0, sizeof(metrics));
2869 hr = IDWriteTextLayout_GetClusterMetrics(layout, metrics, 1, &count);
2870 ok(hr == S_OK, "Failed to get cluster metrics, hr %#lx.\n", hr);
2871 ok(count == 1, "Unexpected cluster count %u.\n", count);
2872
2873 hr = IDWriteTextLayout_GetLineMetrics(layout, &line, 1, &count);
2874 ok(hr == S_OK, "Failed to get line metrics, hr %#lx.\n", hr);
2875 ok(count == 1, "Unexpected line count %u.\n", count);
2876 ok(line.length == 1, "Unexpected line length %u.\n", line.length);
2877 ok(line.isTrimmed, "Unexpected trimming flag %x.\n", line.isTrimmed);
2878
2880 hr = IDWriteTextLayout_Draw(layout, NULL, &testrenderer, 0.0f, 0.0f);
2881 ok(hr == S_OK, "Draw() failed, hr %#lx.\n", hr);
2882 ok_sequence(sequences, RENDERER_ID, draw_trimmed_seq, "Trimmed draw test", FALSE);
2883
2884 IDWriteTextLayout_Release(layout);
2885
2886 IDWriteInlineObject_Release(&testinlineobj->IDWriteInlineObject_iface);
2887 IDWriteInlineObject_Release(&testinlineobj2->IDWriteInlineObject_iface);
2888 IDWriteInlineObject_Release(&testinlineobj3->IDWriteInlineObject_iface);
2889 IDWriteInlineObject_Release(trimm);
2890 IDWriteTextFormat_Release(format);
2891 IDWriteFactory_Release(factory);
2892}
2893
2894static void test_SetLocaleName(void)
2895{
2896 WCHAR buffW[LOCALE_NAME_MAX_LENGTH + 5];
2897 IDWriteTextFormat *format, *format2;
2898 IDWriteTextLayout *layout;
2901 HRESULT hr;
2902
2904
2905 /* create format with mixed case locale name, get it back */
2906 hr = IDWriteFactory_CreateTextFormat(factory, L"Tahoma", NULL, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL,
2907 DWRITE_FONT_STRETCH_NORMAL, 10.0f, L"eN-uS", &format);
2908 ok(hr == S_OK, "Failed to create text format, hr %#lx.\n", hr);
2909
2910 hr = IDWriteTextFormat_GetLocaleName(format, buffW, ARRAY_SIZE(buffW));
2911 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2912 ok(!lstrcmpW(buffW, L"en-us"), "Unexpected locale name %s.\n", wine_dbgstr_w(buffW));
2913
2914 hr = IDWriteFactory_CreateTextLayout(factory, L"abcd", 4, format, 1000.0f, 1000.0f, &layout);
2915 ok(hr == S_OK, "Failed to create text layout, hr %#lx.\n", hr);
2916
2917 hr = IDWriteTextLayout_QueryInterface(layout, &IID_IDWriteTextFormat, (void**)&format2);
2918 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2919
2920 hr = IDWriteTextFormat_GetLocaleName(format2, buffW, ARRAY_SIZE(buffW));
2921 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2922 ok(!lstrcmpW(buffW, L"en-us"), "Unexpected locale name %s.\n", wine_dbgstr_w(buffW));
2923
2924 hr = IDWriteTextLayout_GetLocaleName(layout, 0, buffW, ARRAY_SIZE(buffW), NULL);
2925 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2926 ok(!lstrcmpW(buffW, L"en-us"), "Unexpected locale name %s.\n", wine_dbgstr_w(buffW));
2927
2928 IDWriteTextFormat_Release(format2);
2929 IDWriteTextLayout_Release(layout);
2930 IDWriteTextFormat_Release(format);
2931
2932 hr = IDWriteFactory_CreateTextFormat(factory, L"Tahoma", NULL, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL,
2933 DWRITE_FONT_STRETCH_NORMAL, 10.0f, L"en-us", &format);
2934 ok(hr == S_OK, "Failed to create text format, hr %#lx.\n", hr);
2935
2936 hr = IDWriteFactory_CreateTextLayout(factory, L"abcd", 4, format, 1000.0f, 1000.0f, &layout);
2937 ok(hr == S_OK, "Failed to create text layout, hr %#lx.\n", hr);
2938
2939 range.startPosition = 0;
2940 range.length = 1;
2941 hr = IDWriteTextLayout_SetLocaleName(layout, L"en-us", range);
2942 ok(hr == S_OK, "Failed to set locale name, hr %#lx.\n", hr);
2943
2944 hr = IDWriteTextLayout_SetLocaleName(layout, NULL, range);
2945 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
2946
2947 /* invalid locale name is allowed */
2948 hr = IDWriteTextLayout_SetLocaleName(layout, L"abcd", range);
2949 ok(hr == S_OK, "Failed to set locale name, hr %#lx.\n", hr);
2950
2951 hr = IDWriteTextLayout_GetLocaleName(layout, 0, NULL, 0, NULL);
2952 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
2953
2954 if (0) /* crashes on native */
2955 hr = IDWriteTextLayout_GetLocaleName(layout, 0, NULL, 1, NULL);
2956
2957 buffW[0] = 0;
2958 range.length = 0;
2959 hr = IDWriteTextLayout_GetLocaleName(layout, 0, buffW, ARRAY_SIZE(buffW), &range);
2960 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2961 ok(!lstrcmpW(buffW, L"abcd"), "Unexpected locale name %s.\n", wine_dbgstr_w(buffW));
2962 ok(range.startPosition == 0 && range.length == 1, "got %u,%u\n", range.startPosition, range.length);
2963
2964 /* get with a shorter buffer */
2965 buffW[0] = 0xa;
2966 hr = IDWriteTextLayout_GetLocaleName(layout, 0, buffW, 1, NULL);
2967 ok(hr == E_NOT_SUFFICIENT_BUFFER, "Unexpected hr %#lx.\n", hr);
2968 ok(buffW[0] == 0, "got %x\n", buffW[0]);
2969
2970 /* name is too long */
2971 lstrcpyW(buffW, L"abcd");
2972 while (lstrlenW(buffW) <= LOCALE_NAME_MAX_LENGTH)
2973 lstrcatW(buffW, L"abcd");
2974
2975 range.startPosition = 0;
2976 range.length = 1;
2977 hr = IDWriteTextLayout_SetLocaleName(layout, buffW, range);
2978 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
2979
2980 buffW[0] = 0;
2981 hr = IDWriteTextLayout_GetLocaleName(layout, 0, buffW, ARRAY_SIZE(buffW), NULL);
2982 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2983 ok(!lstrcmpW(buffW, L"abcd"), "Unexpected locale name %s.\n", wine_dbgstr_w(buffW));
2984
2985 /* set initial locale name for whole text, except with a different casing */
2986 range.startPosition = 0;
2987 range.length = 4;
2988 hr = IDWriteTextLayout_SetLocaleName(layout, L"eN-uS", range);
2989 ok(hr == S_OK, "Failed to set locale name, hr %#lx.\n", hr);
2990
2991 buffW[0] = 0;
2992 range.length = 0;
2993 hr = IDWriteTextLayout_GetLocaleName(layout, 0, buffW, ARRAY_SIZE(buffW), &range);
2994 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2995 ok(!lstrcmpW(buffW, L"en-us"), "Unexpected locale name %s.\n", wine_dbgstr_w(buffW));
2996 ok((range.startPosition == 0 && range.length == ~0u) ||
2997 broken(range.startPosition == 0 && range.length == 4) /* vista/win7 */, "got %u,%u\n", range.startPosition, range.length);
2998
2999 /* check what's returned for positions after the text */
3000 buffW[0] = 0;
3001 range.length = 0;
3002 hr = IDWriteTextLayout_GetLocaleName(layout, 100, buffW, ARRAY_SIZE(buffW), &range);
3003 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3004 ok(!lstrcmpW(buffW, L"en-us"), "Unexpected locale name %s.\n", wine_dbgstr_w(buffW));
3005 ok((range.startPosition == 0 && range.length == ~0u) ||
3006 broken(range.startPosition == 4 && range.length == ~0u-4) /* vista/win7 */, "got %u,%u\n", range.startPosition, range.length);
3007
3008 IDWriteTextLayout_Release(layout);
3009 IDWriteTextFormat_Release(format);
3010 IDWriteFactory_Release(factory);
3011}
3012
3013static void test_SetPairKerning(void)
3014{
3015 static const WCHAR strW[] = {'a','e',0x0300,'d',0}; /* accent grave */
3016 DWRITE_CLUSTER_METRICS clusters[4];
3017 IDWriteTextLayout1 *layout1;
3019 IDWriteTextLayout *layout;
3022 BOOL kerning;
3023 UINT32 count;
3024 HRESULT hr;
3025
3027
3028 hr = IDWriteFactory_CreateTextFormat(factory, L"Tahoma", NULL, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL,
3029 DWRITE_FONT_STRETCH_NORMAL, 10.0f, L"en-us", &format);
3030 ok(hr == S_OK, "Failed to create text format, hr %#lx.\n", hr);
3031
3032 hr = IDWriteFactory_CreateTextLayout(factory, strW, 4, format, 1000.0, 1000.0, &layout);
3033 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3034 IDWriteTextFormat_Release(format);
3035
3036 hr = IDWriteTextLayout_QueryInterface(layout, &IID_IDWriteTextLayout1, (void**)&layout1);
3037 IDWriteTextLayout_Release(layout);
3038
3039 if (hr != S_OK) {
3040 win_skip("SetPairKerning() is not supported.\n");
3041 IDWriteFactory_Release(factory);
3042 return;
3043 }
3044
3045if (0) { /* crashes on native */
3046 hr = IDWriteTextLayout1_GetPairKerning(layout1, 0, NULL, NULL);
3047 hr = IDWriteTextLayout1_GetPairKerning(layout1, 0, NULL, &range);
3048}
3049
3050 hr = IDWriteTextLayout1_GetPairKerning(layout1, 0, &kerning, NULL);
3051 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3052
3053 range.startPosition = 0;
3054 range.length = 0;
3055 kerning = TRUE;
3056 hr = IDWriteTextLayout1_GetPairKerning(layout1, 0, &kerning, &range);
3057 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3058 ok(!kerning, "got %d\n", kerning);
3059 ok(range.length == ~0u, "got %u\n", range.length);
3060
3061 count = 0;
3062 hr = IDWriteTextLayout1_GetClusterMetrics(layout1, clusters, 4, &count);
3063 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3064 todo_wine ok(count == 3, "Unexpected cluster count %u.\n", count);
3065 ok(clusters[0].length == 1, "got %u\n", clusters[0].length);
3066 todo_wine ok(clusters[1].length == 2, "got %u\n", clusters[1].length);
3067 ok(clusters[2].length == 1, "got %u\n", clusters[2].length);
3068
3069 /* pair kerning flag participates in itemization - combining characters
3070 breaks */
3071 range.startPosition = 0;
3072 range.length = 2;
3073 hr = IDWriteTextLayout1_SetPairKerning(layout1, 2, range);
3074 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3075
3076 kerning = FALSE;
3077 hr = IDWriteTextLayout1_GetPairKerning(layout1, 0, &kerning, &range);
3078 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3079 ok(kerning == TRUE, "got %d\n", kerning);
3080
3081 count = 0;
3082 hr = IDWriteTextLayout1_GetClusterMetrics(layout1, clusters, 4, &count);
3083 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3084 ok(count == 4, "got %u\n", count);
3085 ok(clusters[0].length == 1, "got %u\n", clusters[0].length);
3086 ok(clusters[1].length == 1, "got %u\n", clusters[1].length);
3087 ok(clusters[2].length == 1, "got %u\n", clusters[2].length);
3088 ok(clusters[3].length == 1, "got %u\n", clusters[3].length);
3089
3090 IDWriteTextLayout1_Release(layout1);
3091 IDWriteFactory_Release(factory);
3092}
3093
3095{
3097 IDWriteTextLayout2 *layout2;
3098 IDWriteTextFormat1 *format1;
3100 IDWriteTextLayout *layout;
3102 HRESULT hr;
3103
3105
3106 hr = IDWriteFactory_CreateTextFormat(factory, L"Tahoma", NULL, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL,
3107 DWRITE_FONT_STRETCH_NORMAL, 10.0f, L"en-us", &format);
3108 ok(hr == S_OK, "Failed to create text format, hr %#lx.\n", hr);
3109
3110 hr = IDWriteFactory_CreateTextLayout(factory, L"abcd", 4, format, 1000.0f, 1000.0f, &layout);
3111 ok(hr == S_OK, "Failed to create text layout, hr %#lx.\n", hr);
3112 IDWriteTextFormat_Release(format);
3113
3114 hr = IDWriteTextLayout_QueryInterface(layout, &IID_IDWriteTextLayout2, (void**)&layout2);
3115 IDWriteTextLayout_Release(layout);
3116
3117 if (hr != S_OK) {
3118 win_skip("SetVerticalGlyphOrientation() is not supported.\n");
3119 IDWriteFactory_Release(factory);
3120 return;
3121 }
3122
3123 orientation = IDWriteTextLayout2_GetVerticalGlyphOrientation(layout2);
3124 ok(orientation == DWRITE_VERTICAL_GLYPH_ORIENTATION_DEFAULT, "got %d\n", orientation);
3125
3126 hr = IDWriteTextLayout2_SetVerticalGlyphOrientation(layout2, DWRITE_VERTICAL_GLYPH_ORIENTATION_STACKED+1);
3127 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
3128
3129 hr = IDWriteTextLayout2_QueryInterface(layout2, &IID_IDWriteTextFormat1, (void **)&format1);
3130 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3131
3132 orientation = IDWriteTextFormat1_GetVerticalGlyphOrientation(format1);
3133 ok(orientation == DWRITE_VERTICAL_GLYPH_ORIENTATION_DEFAULT, "Unexpected orientation %d.\n", orientation);
3134
3135 hr = IDWriteTextLayout2_SetVerticalGlyphOrientation(layout2, DWRITE_VERTICAL_GLYPH_ORIENTATION_STACKED);
3136 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3137
3138 orientation = IDWriteTextLayout2_GetVerticalGlyphOrientation(layout2);
3139 ok(orientation == DWRITE_VERTICAL_GLYPH_ORIENTATION_STACKED, "Unexpected orientation %d.\n", orientation);
3140
3141 orientation = IDWriteTextFormat1_GetVerticalGlyphOrientation(format1);
3142 ok(orientation == DWRITE_VERTICAL_GLYPH_ORIENTATION_STACKED, "Unexpected orientation %d.\n", orientation);
3143
3144 hr = IDWriteTextFormat1_SetVerticalGlyphOrientation(format1, DWRITE_VERTICAL_GLYPH_ORIENTATION_DEFAULT);
3145 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3146
3147 orientation = IDWriteTextLayout2_GetVerticalGlyphOrientation(layout2);
3148 ok(orientation == DWRITE_VERTICAL_GLYPH_ORIENTATION_DEFAULT, "Unexpected orientation %d.\n", orientation);
3149
3150 IDWriteTextFormat1_Release(format1);
3151
3152 IDWriteTextLayout2_Release(layout2);
3153 IDWriteFactory_Release(factory);
3154}
3155
3156static void test_DetermineMinWidth(void)
3157{
3158 struct minwidth_test {
3159 const WCHAR text[10]; /* text to create a layout for */
3160 const WCHAR mintext[10]; /* text that represents sequence of minimal width */
3161 } minwidth_tests[] = {
3162 { {' ','a','b',' ',0}, {'a','b',0} },
3163 { {'a','\n',' ',' ',0}, {'a',0} },
3164 { {'a','\n',' ',' ','b',0}, {'b',0} },
3165 { {'a','b','c','\n',' ',' ','b',0}, {'a','b','c',0} },
3166 };
3169 IDWriteTextLayout *layout;
3171 UINT32 count, i, j;
3172 FLOAT minwidth;
3173 HRESULT hr;
3174
3176
3177 hr = IDWriteFactory_CreateTextFormat(factory, L"Tahoma", NULL, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL,
3178 DWRITE_FONT_STRETCH_NORMAL, 10.0f, L"en-us", &format);
3179 ok(hr == S_OK, "Failed to create text format, hr %#lx.\n", hr);
3180
3181 hr = IDWriteFactory_CreateTextLayout(factory, L"abcd", 4, format, 1000.0f, 1000.0f, &layout);
3182 ok(hr == S_OK, "Failed to create text layout, hr %#lx.\n", hr);
3183
3184 hr = IDWriteTextLayout_DetermineMinWidth(layout, NULL);
3185 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
3186 IDWriteTextLayout_Release(layout);
3187
3188 /* empty string */
3189 hr = IDWriteFactory_CreateTextLayout(factory, L"abcd", 0, format, 100.0f, 100.0f, &layout);
3190 ok(hr == S_OK, "Failed to create text layout, hr %#lx.\n", hr);
3191
3192 minwidth = 1.0f;
3193 hr = IDWriteTextLayout_DetermineMinWidth(layout, &minwidth);
3194 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3195 ok(minwidth == 0.0f, "got %f\n", minwidth);
3196 IDWriteTextLayout_Release(layout);
3197
3198 for (i = 0; i < ARRAY_SIZE(minwidth_tests); i++) {
3199 FLOAT width = 0.0f;
3200
3201 /* measure expected width */
3202 hr = IDWriteFactory_CreateTextLayout(factory, minwidth_tests[i].mintext, lstrlenW(minwidth_tests[i].mintext), format, 1000.0f, 1000.0f, &layout);
3203 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3204
3205 hr = IDWriteTextLayout_GetClusterMetrics(layout, metrics, ARRAY_SIZE(metrics), &count);
3206 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3207
3208 for (j = 0; j < count; j++)
3209 width += metrics[j].width;
3210
3211 IDWriteTextLayout_Release(layout);
3212
3213 hr = IDWriteFactory_CreateTextLayout(factory, minwidth_tests[i].text, lstrlenW(minwidth_tests[i].text), format, 1000.0f, 1000.0f, &layout);
3214 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3215
3216 minwidth = 0.0f;
3217 hr = IDWriteTextLayout_DetermineMinWidth(layout, &minwidth);
3218 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3219 ok(minwidth == width, "test %u: expected width %f, got %f\n", i, width, minwidth);
3220
3221 IDWriteTextLayout_Release(layout);
3222 }
3223
3224 IDWriteTextFormat_Release(format);
3225 IDWriteFactory_Release(factory);
3226}
3227
3228static void test_SetFontSize(void)
3229{
3231 IDWriteTextLayout *layout;
3234 FLOAT size;
3235 HRESULT hr;
3236
3238
3239 hr = IDWriteFactory_CreateTextFormat(factory, L"Tahoma", NULL, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL,
3240 DWRITE_FONT_STRETCH_NORMAL, 10.0f, L"en-us", &format);
3241 ok(hr == S_OK, "Failed to create text format, hr %#lx.\n", hr);
3242
3243 hr = IDWriteFactory_CreateTextLayout(factory, L"abcd", 4, format, 1000.0f, 1000.0f, &layout);
3244 ok(hr == S_OK, "Failed to create text layout, hr %#lx.\n", hr);
3245
3246 /* negative/zero size */
3247 r.startPosition = 1;
3248 r.length = 1;
3249 hr = IDWriteTextLayout_SetFontSize(layout, -15.0, r);
3250 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
3251
3252 hr = IDWriteTextLayout_SetFontSize(layout, 0.0, r);
3253 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
3254
3255 r.startPosition = 1;
3256 r.length = 0;
3257 size = 0.0;
3258 hr = IDWriteTextLayout_GetFontSize(layout, 0, &size, &r);
3259 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3260 ok(r.startPosition == 0 && r.length == ~0u, "got %u, %u\n", r.startPosition, r.length);
3261 ok(size == 10.0, "got %.2f\n", size);
3262
3263 r.startPosition = 1;
3264 r.length = 1;
3265 hr = IDWriteTextLayout_SetFontSize(layout, 15.0, r);
3266 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3267
3268 /* zero length range */
3269 r.startPosition = 1;
3270 r.length = 0;
3271 hr = IDWriteTextLayout_SetFontSize(layout, 123.0, r);
3272 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3273
3274 size = 0.0;
3275 hr = IDWriteTextLayout_GetFontSize(layout, 1, &size, &r);
3276 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3277 ok(size == 15.0, "got %.2f\n", size);
3278
3279 r.startPosition = 0;
3280 r.length = 4;
3281 hr = IDWriteTextLayout_SetFontSize(layout, 15.0, r);
3282 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3283
3284 size = 0.0;
3285 hr = IDWriteTextLayout_GetFontSize(layout, 1, &size, &r);
3286 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3287 ok(size == 15.0, "got %.2f\n", size);
3288
3289 size = 0.0;
3290 hr = IDWriteTextLayout_GetFontSize(layout, 0, &size, &r);
3291 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3292 ok(r.startPosition == 0 && r.length == 4, "got %u, %u\n", r.startPosition, r.length);
3293 ok(size == 15.0, "got %.2f\n", size);
3294
3295 size = 15.0;
3296 r.startPosition = r.length = 0;
3297 hr = IDWriteTextLayout_GetFontSize(layout, 20, &size, &r);
3298 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3299 ok(r.startPosition == 4 && r.length == ~0u-4, "got %u, %u\n", r.startPosition, r.length);
3300 ok(size == 10.0, "got %.2f\n", size);
3301
3302 r.startPosition = 100;
3303 r.length = 4;
3304 hr = IDWriteTextLayout_SetFontSize(layout, 25.0, r);
3305 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3306
3307 size = 15.0;
3308 r.startPosition = r.length = 0;
3309 hr = IDWriteTextLayout_GetFontSize(layout, 100, &size, &r);
3310 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3311 ok(r.startPosition == 100 && r.length == 4, "got %u, %u\n", r.startPosition, r.length);
3312 ok(size == 25.0, "got %.2f\n", size);
3313
3314 IDWriteTextLayout_Release(layout);
3315 IDWriteTextFormat_Release(format);
3316 IDWriteFactory_Release(factory);
3317}
3318
3319static void test_SetFontFamilyName(void)
3320{
3322 IDWriteTextLayout *layout;
3325 WCHAR nameW[50];
3326 HRESULT hr;
3327
3329
3330 hr = IDWriteFactory_CreateTextFormat(factory, L"Tahoma", NULL, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL,
3331 DWRITE_FONT_STRETCH_NORMAL, 10.0f, L"en-us", &format);
3332 ok(hr == S_OK, "Failed to create text format, hr %#lx.\n", hr);
3333
3334 hr = IDWriteFactory_CreateTextLayout(factory, L"abcd", 4, format, 1000.0f, 1000.0f, &layout);
3335 ok(hr == S_OK, "Failed to create text layout, hr %#lx.\n", hr);
3336
3337 /* NULL name */
3338 r.startPosition = 1;
3339 r.length = 1;
3340 hr = IDWriteTextLayout_SetFontFamilyName(layout, NULL, r);
3341 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
3342
3343 r.startPosition = 1;
3344 r.length = 0;
3345 nameW[0] = 0;
3346 hr = IDWriteTextLayout_GetFontFamilyName(layout, 1, nameW, ARRAY_SIZE(nameW), &r);
3347 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3348 ok(r.startPosition == 0 && r.length == ~0u, "got %u, %u\n", r.startPosition, r.length);
3349
3350 /* set name only different in casing */
3351 r.startPosition = 1;
3352 r.length = 1;
3353 hr = IDWriteTextLayout_SetFontFamilyName(layout, L"TaHoma", r);
3354 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3355
3356 /* zero length range */
3357 r.startPosition = 1;
3358 r.length = 0;
3359 hr = IDWriteTextLayout_SetFontFamilyName(layout, L"Arial", r);
3360 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3361
3362 r.startPosition = 0;
3363 r.length = 0;
3364 nameW[0] = 0;
3365 hr = IDWriteTextLayout_GetFontFamilyName(layout, 1, nameW, ARRAY_SIZE(nameW), &r);
3366 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3367 ok(!lstrcmpW(nameW, L"TaHoma"), "Unexpected family name %s.\n", wine_dbgstr_w(nameW));
3368 ok(r.startPosition == 1 && r.length == 1, "got %u, %u\n", r.startPosition, r.length);
3369
3370 r.startPosition = 1;
3371 r.length = 1;
3372 hr = IDWriteTextLayout_SetFontFamilyName(layout, L"Arial", r);
3373 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3374
3375 r.startPosition = 1;
3376 r.length = 0;
3377 hr = IDWriteTextLayout_GetFontFamilyName(layout, 1, nameW, ARRAY_SIZE(nameW), &r);
3378 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3379 ok(r.startPosition == 1 && r.length == 1, "got %u, %u\n", r.startPosition, r.length);
3380
3381 r.startPosition = 0;
3382 r.length = 4;
3383 hr = IDWriteTextLayout_SetFontFamilyName(layout, L"Arial", r);
3384 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3385
3386 nameW[0] = 0;
3387 hr = IDWriteTextLayout_GetFontFamilyName(layout, 1, nameW, ARRAY_SIZE(nameW), &r);
3388 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3389 ok(r.startPosition == 0 && r.length == 4, "got %u, %u\n", r.startPosition, r.length);
3390 ok(!lstrcmpW(nameW, L"Arial"), "Unexpected family name %s.\n", wine_dbgstr_w(nameW));
3391
3392 IDWriteTextLayout_Release(layout);
3393 IDWriteTextFormat_Release(format);
3394 IDWriteFactory_Release(factory);
3395}
3396
3397static void test_SetFontStyle(void)
3398{
3400 IDWriteTextLayout *layout;
3404 HRESULT hr;
3405
3407
3408 hr = IDWriteFactory_CreateTextFormat(factory, L"Tahoma", NULL, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL,
3409 DWRITE_FONT_STRETCH_NORMAL, 10.0f, L"en-us", &format);
3410 ok(hr == S_OK, "Failed to create text format, hr %#lx.\n", hr);
3411
3412 hr = IDWriteFactory_CreateTextLayout(factory, L"abcd", 4, format, 1000.0f, 1000.0f, &layout);
3413 ok(hr == S_OK, "Failed to create text layout, hr %#lx.\n", hr);
3414
3415 /* invalid style value */
3416 r.startPosition = 1;
3417 r.length = 1;
3418 hr = IDWriteTextLayout_SetFontStyle(layout, DWRITE_FONT_STYLE_ITALIC+1, r);
3419 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
3420
3421 r.startPosition = 1;
3422 r.length = 0;
3423 hr = IDWriteTextLayout_GetFontStyle(layout, 0, &style, &r);
3424 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3425 ok(r.startPosition == 0 && r.length == ~0u, "got %u, %u\n", r.startPosition, r.length);
3426 ok(style == DWRITE_FONT_STYLE_NORMAL, "got %d\n", style);
3427
3428 r.startPosition = 1;
3429 r.length = 1;
3430 hr = IDWriteTextLayout_SetFontStyle(layout, DWRITE_FONT_STYLE_ITALIC, r);
3431 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3432
3433 /* zero length range */
3434 r.startPosition = 1;
3435 r.length = 0;
3436 hr = IDWriteTextLayout_SetFontStyle(layout, DWRITE_FONT_STYLE_NORMAL, r);
3437 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3438
3440 hr = IDWriteTextLayout_GetFontStyle(layout, 1, &style, &r);
3441 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3442 ok(style == DWRITE_FONT_STYLE_ITALIC, "got %d\n", style);
3443
3444 r.startPosition = 0;
3445 r.length = 4;
3446 hr = IDWriteTextLayout_SetFontStyle(layout, DWRITE_FONT_STYLE_OBLIQUE, r);
3447 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3448
3450 hr = IDWriteTextLayout_GetFontStyle(layout, 1, &style, &r);
3451 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3452 ok(style == DWRITE_FONT_STYLE_OBLIQUE, "got %d\n", style);
3453
3455 hr = IDWriteTextLayout_GetFontStyle(layout, 0, &style, &r);
3456 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3457 ok(r.startPosition == 0 && r.length == 4, "got %u, %u\n", r.startPosition, r.length);
3458 ok(style == DWRITE_FONT_STYLE_OBLIQUE, "got %d\n", style);
3459
3461 r.startPosition = r.length = 0;
3462 hr = IDWriteTextLayout_GetFontStyle(layout, 20, &style, &r);
3463 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3464 ok(r.startPosition == 4 && r.length == ~0u-4, "got %u, %u\n", r.startPosition, r.length);
3465 ok(style == DWRITE_FONT_STYLE_NORMAL, "got %d\n", style);
3466
3467 r.startPosition = 100;
3468 r.length = 4;
3469 hr = IDWriteTextLayout_SetFontStyle(layout, DWRITE_FONT_STYLE_OBLIQUE, r);
3470 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3471
3473 r.startPosition = r.length = 0;
3474 hr = IDWriteTextLayout_GetFontStyle(layout, 100, &style, &r);
3475 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3476 ok(r.startPosition == 100 && r.length == 4, "got %u, %u\n", r.startPosition, r.length);
3477 ok(style == DWRITE_FONT_STYLE_OBLIQUE, "got %d\n", style);
3478
3479 IDWriteTextLayout_Release(layout);
3480 IDWriteTextFormat_Release(format);
3481 IDWriteFactory_Release(factory);
3482}
3483
3484static void test_SetFontStretch(void)
3485{
3486 DWRITE_FONT_STRETCH stretch;
3488 IDWriteTextLayout *layout;
3491 HRESULT hr;
3492
3494
3495 hr = IDWriteFactory_CreateTextFormat(factory, L"Tahoma", NULL, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL,
3496 DWRITE_FONT_STRETCH_NORMAL, 10.0f, L"en-us", &format);
3497 ok(hr == S_OK, "Failed to create text format, hr %#lx.\n", hr);
3498
3499 hr = IDWriteFactory_CreateTextLayout(factory, L"abcd", 4, format, 1000.0f, 1000.0f, &layout);
3500 ok(hr == S_OK, "Failed to create text layout, hr %#lx.\n", hr);
3501
3502 /* invalid stretch value */
3503 r.startPosition = 1;
3504 r.length = 1;
3505 hr = IDWriteTextLayout_SetFontStretch(layout, DWRITE_FONT_STRETCH_ULTRA_EXPANDED+1, r);
3506 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
3507
3508 r.startPosition = 1;
3509 r.length = 0;
3511 hr = IDWriteTextLayout_GetFontStretch(layout, 0, &stretch, &r);
3512 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3513 ok(r.startPosition == 0 && r.length == ~0u, "got %u, %u\n", r.startPosition, r.length);
3514 ok(stretch == DWRITE_FONT_STRETCH_NORMAL, "got %d\n", stretch);
3515
3516 r.startPosition = 1;
3517 r.length = 1;
3518 hr = IDWriteTextLayout_SetFontStretch(layout, DWRITE_FONT_STRETCH_CONDENSED, r);
3519 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3520
3521 /* zero length range */
3522 r.startPosition = 1;
3523 r.length = 0;
3524 hr = IDWriteTextLayout_SetFontStretch(layout, DWRITE_FONT_STRETCH_NORMAL, r);
3525 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3526
3528 hr = IDWriteTextLayout_GetFontStretch(layout, 1, &stretch, &r);
3529 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3530 ok(stretch == DWRITE_FONT_STRETCH_CONDENSED, "got %d\n", stretch);
3531
3532 r.startPosition = 0;
3533 r.length = 4;
3534 hr = IDWriteTextLayout_SetFontStretch(layout, DWRITE_FONT_STRETCH_EXPANDED, r);
3535 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3536
3538 hr = IDWriteTextLayout_GetFontStretch(layout, 1, &stretch, &r);
3539 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3540 ok(stretch == DWRITE_FONT_STRETCH_EXPANDED, "got %d\n", stretch);
3541
3543 hr = IDWriteTextLayout_GetFontStretch(layout, 0, &stretch, &r);
3544 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3545 ok(r.startPosition == 0 && r.length == 4, "got %u, %u\n", r.startPosition, r.length);
3546 ok(stretch == DWRITE_FONT_STRETCH_EXPANDED, "got %d\n", stretch);
3547
3549 r.startPosition = r.length = 0;
3550 hr = IDWriteTextLayout_GetFontStretch(layout, 20, &stretch, &r);
3551 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3552 ok(r.startPosition == 4 && r.length == ~0u-4, "got %u, %u\n", r.startPosition, r.length);
3553 ok(stretch == DWRITE_FONT_STRETCH_NORMAL, "got %d\n", stretch);
3554
3555 r.startPosition = 100;
3556 r.length = 4;
3557 hr = IDWriteTextLayout_SetFontStretch(layout, DWRITE_FONT_STRETCH_EXPANDED, r);
3558 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3559
3561 r.startPosition = r.length = 0;
3562 hr = IDWriteTextLayout_GetFontStretch(layout, 100, &stretch, &r);
3563 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3564 ok(r.startPosition == 100 && r.length == 4, "got %u, %u\n", r.startPosition, r.length);
3565 ok(stretch == DWRITE_FONT_STRETCH_EXPANDED, "got %d\n", stretch);
3566
3567 /* trying to set undefined value */
3568 r.startPosition = 0;
3569 r.length = 2;
3570 hr = IDWriteTextLayout_SetFontStretch(layout, DWRITE_FONT_STRETCH_UNDEFINED, r);
3571 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
3572
3573 IDWriteTextLayout_Release(layout);
3574 IDWriteTextFormat_Release(format);
3575 IDWriteFactory_Release(factory);
3576}
3577
3578static void test_SetStrikethrough(void)
3579{
3581 IDWriteTextLayout *layout;
3584 BOOL value;
3585 HRESULT hr;
3586
3588
3589 hr = IDWriteFactory_CreateTextFormat(factory, L"Tahoma", NULL, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL,
3590 DWRITE_FONT_STRETCH_NORMAL, 10.0f, L"en-us", &format);
3591 ok(hr == S_OK, "Failed to create text format, hr %#lx.\n", hr);
3592
3593 hr = IDWriteFactory_CreateTextLayout(factory, L"abcd", 4, format, 1000.0f, 1000.0f, &layout);
3594 ok(hr == S_OK, "Failed to create text layout, hr %#lx.\n", hr);
3595
3596 r.startPosition = 1;
3597 r.length = 0;
3598 value = TRUE;
3599 hr = IDWriteTextLayout_GetStrikethrough(layout, 0, &value, &r);
3600 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3601 ok(r.startPosition == 0 && r.length == ~0u, "got %u, %u\n", r.startPosition, r.length);
3602 ok(value == FALSE, "got %d\n", value);
3603
3604 r.startPosition = 1;
3605 r.length = 1;
3606 hr = IDWriteTextLayout_SetStrikethrough(layout, TRUE, r);
3607 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3608
3609 value = FALSE;
3610 hr = IDWriteTextLayout_GetStrikethrough(layout, 1, &value, &r);
3611 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3612 ok(value == TRUE, "got %d\n", value);
3613 ok(r.startPosition == 1 && r.length == 1, "got %u, %u\n", r.startPosition, r.length);
3614
3615 value = TRUE;
3616 r.startPosition = r.length = 0;
3617 hr = IDWriteTextLayout_GetStrikethrough(layout, 20, &value, &r);
3618 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3619 ok(r.startPosition == 2 && r.length == ~0u-2, "got %u, %u\n", r.startPosition, r.length);
3620 ok(value == FALSE, "got %d\n", value);
3621
3622 r.startPosition = 100;
3623 r.length = 4;
3624 hr = IDWriteTextLayout_SetStrikethrough(layout, TRUE, r);
3625 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3626
3627 value = FALSE;
3628 r.startPosition = r.length = 0;
3629 hr = IDWriteTextLayout_GetStrikethrough(layout, 100, &value, &r);
3630 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3631 ok(r.startPosition == 100 && r.length == 4, "got %u, %u\n", r.startPosition, r.length);
3632 ok(value == TRUE, "got %d\n", value);
3633
3634 IDWriteTextLayout_Release(layout);
3635 IDWriteTextFormat_Release(format);
3636 IDWriteFactory_Release(factory);
3637}
3638
3639static void test_GetMetrics(void)
3640{
3641 static const WCHAR str2W[] = {0x2066,')',')',0x661,'(',0x627,')',0};
3642 DWRITE_CLUSTER_METRICS clusters[4];
3645 IDWriteTextLayout *layout;
3647 UINT32 count, i;
3648 FLOAT width;
3649 HRESULT hr;
3650
3652
3653 hr = IDWriteFactory_CreateTextFormat(factory, L"Tahoma", NULL, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL,
3654 DWRITE_FONT_STRETCH_NORMAL, 10.0f, L"en-us", &format);
3655 ok(hr == S_OK, "Failed to create text format, hr %#lx.\n", hr);
3656
3657 hr = IDWriteFactory_CreateTextLayout(factory, L"abcd", 4, format, 500.0f, 1000.0f, &layout);
3658 ok(hr == S_OK, "Failed to create text layout, hr %#lx.\n", hr);
3659
3660 count = 0;
3661 hr = IDWriteTextLayout_GetClusterMetrics(layout, clusters, 4, &count);
3662 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3663 ok(count == 4, "got %u\n", count);
3664 for (i = 0, width = 0.0; i < count; i++)
3665 width += clusters[i].width;
3666
3667 memset(&metrics, 0xcc, sizeof(metrics));
3668 hr = IDWriteTextLayout_GetMetrics(layout, &metrics);
3669 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3670 ok(metrics.left == 0.0, "got %.2f\n", metrics.left);
3671 ok(metrics.top == 0.0, "got %.2f\n", metrics.top);
3672 ok(metrics.width == width, "got %.2f, expected %.2f\n", metrics.width, width);
3673 ok(metrics.widthIncludingTrailingWhitespace == width, "got %.2f, expected %.2f\n",
3674 metrics.widthIncludingTrailingWhitespace, width);
3675 ok(metrics.height > 0.0, "got %.2f\n", metrics.height);
3676 ok(metrics.layoutWidth == 500.0, "got %.2f\n", metrics.layoutWidth);
3677 ok(metrics.layoutHeight == 1000.0, "got %.2f\n", metrics.layoutHeight);
3678 ok(metrics.maxBidiReorderingDepth == 1, "got %u\n", metrics.maxBidiReorderingDepth);
3679 ok(metrics.lineCount == 1, "got %u\n", metrics.lineCount);
3680
3681 IDWriteTextLayout_Release(layout);
3682
3683 /* a string with more complex bidi sequence */
3684 hr = IDWriteFactory_CreateTextLayout(factory, str2W, 7, format, 500.0, 1000.0, &layout);
3685 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3686
3687 memset(&metrics, 0xcc, sizeof(metrics));
3688 metrics.maxBidiReorderingDepth = 0;
3689 hr = IDWriteTextLayout_GetMetrics(layout, &metrics);
3690 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3691 ok(metrics.left == 0.0, "got %.2f\n", metrics.left);
3692 ok(metrics.top == 0.0, "got %.2f\n", metrics.top);
3693 ok(metrics.width > 0.0, "got %.2f\n", metrics.width);
3694 ok(metrics.widthIncludingTrailingWhitespace > 0.0, "got %.2f\n", metrics.widthIncludingTrailingWhitespace);
3695 ok(metrics.height > 0.0, "got %.2f\n", metrics.height);
3696 ok(metrics.layoutWidth == 500.0, "got %.2f\n", metrics.layoutWidth);
3697 ok(metrics.layoutHeight == 1000.0, "got %.2f\n", metrics.layoutHeight);
3698 todo_wine
3699 ok(metrics.maxBidiReorderingDepth > 1, "got %u\n", metrics.maxBidiReorderingDepth);
3700 ok(metrics.lineCount == 1, "got %u\n", metrics.lineCount);
3701
3702 IDWriteTextLayout_Release(layout);
3703
3704 /* single cluster layout */
3705 hr = IDWriteFactory_CreateTextLayout(factory, L"a", 1, format, 500.0f, 1000.0f, &layout);
3706 ok(hr == S_OK, "Failed to create text layout, hr %#lx.\n", hr);
3707
3708 count = 0;
3709 hr = IDWriteTextLayout_GetClusterMetrics(layout, clusters, 1, &count);
3710 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3711 ok(count == 1, "got %u\n", count);
3712
3713 memset(&metrics, 0xcc, sizeof(metrics));
3714 hr = IDWriteTextLayout_GetMetrics(layout, &metrics);
3715 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3716 ok(metrics.left == 0.0, "got %.2f\n", metrics.left);
3717 ok(metrics.top == 0.0, "got %.2f\n", metrics.top);
3718 ok(metrics.width == clusters[0].width, "got %.2f, expected %.2f\n", metrics.width, clusters[0].width);
3719 ok(metrics.widthIncludingTrailingWhitespace == clusters[0].width, "got %.2f\n", metrics.widthIncludingTrailingWhitespace);
3720 ok(metrics.height > 0.0, "got %.2f\n", metrics.height);
3721 ok(metrics.layoutWidth == 500.0, "got %.2f\n", metrics.layoutWidth);
3722 ok(metrics.layoutHeight == 1000.0, "got %.2f\n", metrics.layoutHeight);
3723 ok(metrics.maxBidiReorderingDepth == 1, "got %u\n", metrics.maxBidiReorderingDepth);
3724 ok(metrics.lineCount == 1, "got %u\n", metrics.lineCount);
3725 IDWriteTextLayout_Release(layout);
3726
3727 /* Whitespace only. */
3728 hr = IDWriteFactory_CreateTextLayout(factory, L" ", 1, format, 500.0f, 1000.0f, &layout);
3729 ok(hr == S_OK, "Failed to create text layout, hr %#lx.\n", hr);
3730
3731 memset(&metrics, 0xcc, sizeof(metrics));
3732 hr = IDWriteTextLayout_GetMetrics(layout, &metrics);
3733 ok(hr == S_OK, "Failed to get layout metrics, hr %#lx.\n", hr);
3734 ok(metrics.left == 0.0f, "Unexpected value for left %f.\n", metrics.left);
3735 ok(metrics.top == 0.0f, "Unexpected value for top %f.\n", metrics.top);
3736 ok(metrics.width == 0.0f, "Unexpected width %f.\n", metrics.width);
3737 ok(metrics.widthIncludingTrailingWhitespace > 0.0f, "Unexpected full width %f.\n",
3738 metrics.widthIncludingTrailingWhitespace);
3739 ok(metrics.height > 0.0, "Unexpected height %f.\n", metrics.height);
3740 ok(metrics.layoutWidth == 500.0, "Unexpected box width %f.\n", metrics.layoutWidth);
3741 ok(metrics.layoutHeight == 1000.0, "Unexpected box height %f.\n", metrics.layoutHeight);
3742 ok(metrics.maxBidiReorderingDepth == 1, "Unexpected reordering depth %u.\n", metrics.maxBidiReorderingDepth);
3743 ok(metrics.lineCount == 1, "Unexpected line count %u.\n", metrics.lineCount);
3744 IDWriteTextLayout_Release(layout);
3745
3746 IDWriteTextFormat_Release(format);
3747 IDWriteFactory_Release(factory);
3748}
3749
3750static void test_SetFlowDirection(void)
3751{
3755 IDWriteTextLayout *layout;
3757 HRESULT hr;
3758
3760
3761 hr = IDWriteFactory_CreateTextFormat(factory, L"Tahoma", NULL, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL,
3762 DWRITE_FONT_STRETCH_NORMAL, 10.0f, L"en-us", &format);
3763 ok(hr == S_OK, "Failed to create text format, hr %#lx.\n", hr);
3764
3765 flow = IDWriteTextFormat_GetFlowDirection(format);
3766 ok(flow == DWRITE_FLOW_DIRECTION_TOP_TO_BOTTOM, "got %d\n", flow);
3767
3768 reading = IDWriteTextFormat_GetReadingDirection(format);
3769 ok(reading == DWRITE_READING_DIRECTION_LEFT_TO_RIGHT, "got %d\n", reading);
3770
3771 hr = IDWriteFactory_CreateTextLayout(factory, L"abcd", 4, format, 500.0f, 1000.0f, &layout);
3772 ok(hr == S_OK, "Failed to create text layout, hr %#lx.\n", hr);
3773 IDWriteTextLayout_Release(layout);
3774
3775 hr = IDWriteTextFormat_SetFlowDirection(format, DWRITE_FLOW_DIRECTION_LEFT_TO_RIGHT);
3776 ok(hr == S_OK || broken(hr == E_INVALIDARG) /* vista,win7 */, "Unexpected hr %#lx.\n", hr);
3777 if (hr == S_OK)
3778 {
3779 hr = IDWriteFactory_CreateTextLayout(factory, L"abcd", 4, format, 500.0f, 1000.0f, &layout);
3780 ok(hr == S_OK, "Failed to create text layout, hr %#lx.\n", hr);
3781 IDWriteTextLayout_Release(layout);
3782
3783 hr = IDWriteTextFormat_SetReadingDirection(format, DWRITE_READING_DIRECTION_TOP_TO_BOTTOM);
3784 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3785
3786 hr = IDWriteTextFormat_SetFlowDirection(format, DWRITE_FLOW_DIRECTION_TOP_TO_BOTTOM);
3787 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3788
3789 hr = IDWriteFactory_CreateTextLayout(factory, L"abcd", 4, format, 500.0f, 1000.0f, &layout);
3790 ok(hr == S_OK, "Failed to create text layout, hr %#lx.\n", hr);
3791 IDWriteTextLayout_Release(layout);
3792 }
3793 else
3794 win_skip("DWRITE_FLOW_DIRECTION_LEFT_TO_RIGHT is not supported\n");
3795
3796 IDWriteTextFormat_Release(format);
3797 IDWriteFactory_Release(factory);
3798}
3799
3800static const struct drawcall_entry draweffect_seq[] = {
3801 { DRAW_GLYPHRUN|DRAW_EFFECT, {'a','e',0x0300,0}, {'e','n','-','u','s',0}, 2 },
3802 { DRAW_GLYPHRUN, {'d',0}, {'e','n','-','u','s',0}, 1 },
3803 { DRAW_LAST_KIND }
3804};
3805
3806static const struct drawcall_entry draweffect2_seq[] = {
3807 { DRAW_GLYPHRUN|DRAW_EFFECT, {'a','e',0}, {'e','n','-','u','s',0}, 2 },
3808 { DRAW_GLYPHRUN, {'c','d',0}, {'e','n','-','u','s',0}, 2 },
3809 { DRAW_LAST_KIND }
3810};
3811
3812static const struct drawcall_entry draweffect3_seq[] = {
3814 { DRAW_LAST_KIND }
3815};
3816
3817static const struct drawcall_entry draweffect4_seq[] = {
3818 { DRAW_INLINE },
3819 { DRAW_LAST_KIND }
3820};
3821
3822static void test_SetDrawingEffect(void)
3823{
3824 static const WCHAR strW[] = {'a','e',0x0300,'d',0}; /* accent grave */
3827 IDWriteTextLayout *layout;
3829 IUnknown *unk, *effect;
3831 HRESULT hr;
3832 LONG ref;
3833
3835
3836 effect = create_test_effect();
3837
3838 hr = IDWriteFactory_CreateTextFormat(factory, L"Tahoma", NULL, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL,
3839 DWRITE_FONT_STRETCH_NORMAL, 10.0f, L"en-us", &format);
3840 ok(hr == S_OK, "Failed to create text format, hr %#lx.\n", hr);
3841
3842 /* string with combining mark */
3843 hr = IDWriteFactory_CreateTextLayout(factory, strW, 4, format, 500.0, 1000.0, &layout);
3844 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3845
3846 /* set effect past the end of text */
3847 r.startPosition = 100;
3848 r.length = 10;
3849 hr = IDWriteTextLayout_SetDrawingEffect(layout, effect, r);
3850 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3851
3852 r.startPosition = r.length = 0;
3853 hr = IDWriteTextLayout_GetDrawingEffect(layout, 101, &unk, &r);
3854 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3855 ok(r.startPosition == 100 && r.length == 10, "got %u, %u\n", r.startPosition, r.length);
3856 IUnknown_Release(unk);
3857
3858 r.startPosition = r.length = 0;
3859 unk = (void*)0xdeadbeef;
3860 hr = IDWriteTextLayout_GetDrawingEffect(layout, 1000, &unk, &r);
3861 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3862 ok(r.startPosition == 110 && r.length == ~0u-110, "got %u, %u\n", r.startPosition, r.length);
3863 ok(unk == NULL, "got %p\n", unk);
3864
3865 /* effect is applied to clusters, not individual text positions */
3866 r.startPosition = 0;
3867 r.length = 2;
3868 hr = IDWriteTextLayout_SetDrawingEffect(layout, effect, r);
3869 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3870
3872 hr = IDWriteTextLayout_Draw(layout, NULL, &testrenderer, 0.0, 0.0);
3873 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3874 ok_sequence(sequences, RENDERER_ID, draweffect_seq, "effect draw test", TRUE);
3875 IDWriteTextLayout_Release(layout);
3876
3877 /* simple string */
3878 hr = IDWriteFactory_CreateTextLayout(factory, L"aecd", 4, format, 500.0f, 1000.0f, &layout);
3879 ok(hr == S_OK, "Failed to create text layout, hr %#lx.\n", hr);
3880
3881 r.startPosition = 0;
3882 r.length = 2;
3883 hr = IDWriteTextLayout_SetDrawingEffect(layout, effect, r);
3884 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3885
3887 hr = IDWriteTextLayout_Draw(layout, NULL, &testrenderer, 0.0, 0.0);
3888 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3889 ok_sequence(sequences, RENDERER_ID, draweffect2_seq, "effect draw test 2", FALSE);
3890 IDWriteTextLayout_Release(layout);
3891
3892 /* Inline object - effect set for same range */
3893 hr = IDWriteFactory_CreateEllipsisTrimmingSign(factory, format, &sign);
3894 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3895
3896 hr = IDWriteFactory_CreateTextLayout(factory, L"aecd", 4, format, 500.0f, 1000.0f, &layout);
3897 ok(hr == S_OK, "Failed to create text layout, hr %#lx.\n", hr);
3898
3899 r.startPosition = 0;
3900 r.length = 4;
3901 hr = IDWriteTextLayout_SetInlineObject(layout, sign, r);
3902 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3903
3904 hr = IDWriteTextLayout_SetDrawingEffect(layout, effect, r);
3905 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3906
3908 hr = IDWriteTextLayout_Draw(layout, NULL, &testrenderer, 0.0, 0.0);
3909 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3910 ok_sequence(sequences, RENDERER_ID, draweffect3_seq, "effect draw test 3", FALSE);
3911
3912 /* now set effect somewhere inside a range replaced by inline object */
3913 hr = IDWriteTextLayout_SetDrawingEffect(layout, NULL, r);
3914 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3915
3916 r.startPosition = 1;
3917 r.length = 1;
3918 hr = IDWriteTextLayout_SetDrawingEffect(layout, effect, r);
3919 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3920
3921 /* no effect is reported in this case */
3923 hr = IDWriteTextLayout_Draw(layout, NULL, &testrenderer, 0.0, 0.0);
3924 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3925 ok_sequence(sequences, RENDERER_ID, draweffect4_seq, "effect draw test 4", FALSE);
3926
3927 r.startPosition = 0;
3928 r.length = 4;
3929 hr = IDWriteTextLayout_SetDrawingEffect(layout, NULL, r);
3930 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3931
3932 r.startPosition = 0;
3933 r.length = 1;
3934 hr = IDWriteTextLayout_SetDrawingEffect(layout, effect, r);
3935 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3936
3937 /* first range position is all that matters for inline ranges */
3939 hr = IDWriteTextLayout_Draw(layout, NULL, &testrenderer, 0.0, 0.0);
3940 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3941 ok_sequence(sequences, RENDERER_ID, draweffect3_seq, "effect draw test 5", FALSE);
3942
3943 IDWriteTextLayout_Release(layout);
3944
3945 ref = IUnknown_Release(effect);
3946 ok(ref == 0, "Unexpected effect refcount %lu\n", ref);
3947 IDWriteInlineObject_Release(sign);
3948 IDWriteTextFormat_Release(format);
3949 IDWriteFactory_Release(factory);
3950}
3951
3953{
3954 UINT32 index;
3955 BOOL exists = FALSE;
3956 HRESULT hr;
3957
3958 hr = IDWriteLocalizedStrings_FindLocaleName(strings, L"en-us", &index, &exists);
3959 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3960
3961 if (exists) {
3962 hr = IDWriteLocalizedStrings_GetString(strings, index, buff, size);
3963 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3964 }
3965 else
3966 *buff = 0;
3967
3968 return exists;
3969}
3970
3971static void test_GetLineMetrics(void)
3972{
3973 static const WCHAR str3W[] = {'a','\r','b','\n','c','\n','\r','d','\r','\n',0};
3974 static const WCHAR strW[] = {'a','b','c','d',' ',0};
3975 static const WCHAR str2W[] = {'a','b','\r','c','d',0};
3976 static const WCHAR str4W[] = {'a','\r',0};
3977 IDWriteFontCollection *syscollection;
3978 DWRITE_FONT_METRICS fontmetrics;
3980 UINT32 count, i, familycount;
3982 IDWriteTextLayout *layout;
3983 IDWriteFontFace *fontface;
3986 WCHAR nameW[256];
3987 HRESULT hr;
3988
3990
3991 hr = IDWriteFactory_CreateTextFormat(factory, L"Tahoma", NULL, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL,
3992 DWRITE_FONT_STRETCH_NORMAL, 2048.0f, L"en-us", &format);
3993 ok(hr == S_OK, "Failed to create text format, hr %#lx.\n", hr);
3994
3995 hr = IDWriteFactory_CreateTextLayout(factory, strW, 5, format, 30000.0, 1000.0, &layout);
3996 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3997
3998 count = 0;
3999 hr = IDWriteTextLayout_GetLineMetrics(layout, metrics, 0, &count);
4000 ok(hr == E_NOT_SUFFICIENT_BUFFER, "Unexpected hr %#lx.\n", hr);
4001 ok(count == 1, "got count %u\n", count);
4002
4003 memset(metrics, 0, sizeof(metrics));
4004 hr = IDWriteTextLayout_GetLineMetrics(layout, metrics, 1, &count);
4005 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4006 ok(metrics[0].length == 5, "got %u\n", metrics[0].length);
4008
4009 ok(metrics[0].newlineLength == 0, "got %u\n", metrics[0].newlineLength);
4010 ok(metrics[0].isTrimmed == FALSE, "got %d\n", metrics[0].isTrimmed);
4011
4012 IDWriteTextLayout_Release(layout);
4013 IDWriteTextFormat_Release(format);
4014
4015 /* Test line height and baseline calculation */
4016 hr = IDWriteFactory_GetSystemFontCollection(factory, &syscollection, FALSE);
4017 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4018 familycount = IDWriteFontCollection_GetFontFamilyCount(syscollection);
4019
4020 for (i = 0; i < familycount; i++) {
4022 IDWriteFontFamily *family;
4024 BOOL exists;
4025
4026 format = NULL;
4027 layout = NULL;
4028
4029 hr = IDWriteFontCollection_GetFontFamily(syscollection, i, &family);
4030 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4031
4032 hr = IDWriteFontFamily_GetFirstMatchingFont(family, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STRETCH_NORMAL,
4034 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4035
4036 hr = IDWriteFont_CreateFontFace(font, &fontface);
4037 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4038
4039 hr = IDWriteFontFamily_GetFamilyNames(family, &names);
4040 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4041
4042 if (!(exists = get_enus_string(names, nameW, ARRAY_SIZE(nameW)))) {
4043 IDWriteLocalFontFileLoader *localloader;
4046 const void *key;
4047 UINT32 keysize;
4048 UINT32 count;
4049
4050 count = 1;
4051 hr = IDWriteFontFace_GetFiles(fontface, &count, &file);
4052 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4053
4054 hr = IDWriteFontFile_GetLoader(file, &loader);
4055 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4056
4057 hr = IDWriteFontFileLoader_QueryInterface(loader, &IID_IDWriteLocalFontFileLoader, (void**)&localloader);
4058 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4059 IDWriteFontFileLoader_Release(loader);
4060
4061 hr = IDWriteFontFile_GetReferenceKey(file, &key, &keysize);
4062 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4063
4064 hr = IDWriteLocalFontFileLoader_GetFilePathFromKey(localloader, key, keysize, nameW, ARRAY_SIZE(nameW));
4065 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4066
4067 skip("Failed to get English family name, font file %s\n", wine_dbgstr_w(nameW));
4068
4069 IDWriteLocalFontFileLoader_Release(localloader);
4070 IDWriteFontFile_Release(file);
4071 }
4072
4073 IDWriteLocalizedStrings_Release(names);
4074 IDWriteFont_Release(font);
4075
4076 if (!exists)
4077 goto cleanup;
4078
4079 IDWriteFontFace_GetMetrics(fontface, &fontmetrics);
4080 hr = IDWriteFactory_CreateTextFormat(factory, nameW, NULL, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL,
4081 DWRITE_FONT_STRETCH_NORMAL, fontmetrics.designUnitsPerEm, L"en-us", &format);
4082 ok(hr == S_OK, "Failed to create text format, hr %#lx.\n", hr);
4083
4084 hr = IDWriteFactory_CreateTextLayout(factory, L"", 1, format, 30000.0f, 100.0f, &layout);
4085 ok(hr == S_OK, "Failed to create text layout, hr %#lx.\n", hr);
4086
4087 memset(metrics, 0, sizeof(metrics));
4088 count = 0;
4089 hr = IDWriteTextLayout_GetLineMetrics(layout, metrics, ARRAY_SIZE(metrics), &count);
4090 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4091 ok(count == 1, "got %u\n", count);
4092
4093 ok(metrics[0].baseline == fontmetrics.ascent + fontmetrics.lineGap, "%s: got %.2f, expected %d, "
4094 "linegap %d\n", wine_dbgstr_w(nameW), metrics[0].baseline, fontmetrics.ascent + fontmetrics.lineGap,
4095 fontmetrics.lineGap);
4096 ok(metrics[0].height == fontmetrics.ascent + fontmetrics.descent + fontmetrics.lineGap,
4097 "%s: got %.2f, expected %d, linegap %d\n", wine_dbgstr_w(nameW), metrics[0].height,
4098 fontmetrics.ascent + fontmetrics.descent + fontmetrics.lineGap, fontmetrics.lineGap);
4099
4100 cleanup:
4101 if (layout)
4102 IDWriteTextLayout_Release(layout);
4103 if (format)
4104 IDWriteTextFormat_Release(format);
4105 IDWriteFontFace_Release(fontface);
4106 IDWriteFontFamily_Release(family);
4107 }
4108 IDWriteFontCollection_Release(syscollection);
4109
4110 hr = IDWriteFactory_CreateTextFormat(factory, L"Tahoma", NULL, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL,
4111 DWRITE_FONT_STRETCH_NORMAL, 2048.0f, L"en-us", &format);
4112 ok(hr == S_OK, "Failed to create text format, hr %#lx.\n", hr);
4113
4114 fontface = get_fontface_from_format(format);
4115 ok(fontface != NULL, "got %p\n", fontface);
4116
4117 /* force 2 lines */
4118 hr = IDWriteFactory_CreateTextLayout(factory, str2W, 5, format, 10000.0, 1000.0, &layout);
4119 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4120
4121 memset(metrics, 0, sizeof(metrics));
4122 count = 0;
4123 hr = IDWriteTextLayout_GetLineMetrics(layout, metrics, ARRAY_SIZE(metrics), &count);
4124 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4125 ok(count == 2, "got %u\n", count);
4126 /* baseline is relative to a line, and is not accumulated */
4127 ok(metrics[0].baseline == metrics[1].baseline, "got %.2f, %.2f\n", metrics[0].baseline,
4128 metrics[1].baseline);
4129
4130 IDWriteTextLayout_Release(layout);
4131 IDWriteTextFormat_Release(format);
4132
4133 /* line breaks */
4134 hr = IDWriteFactory_CreateTextFormat(factory, L"Tahoma", NULL, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL,
4135 DWRITE_FONT_STRETCH_NORMAL, 12.0f, L"en-us", &format);
4136 ok(hr == S_OK, "Failed to create text format, hr %#lx.\n", hr);
4137
4138 hr = IDWriteFactory_CreateTextLayout(factory, str3W, 10, format, 100.0, 300.0, &layout);
4139 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4140
4141 memset(metrics, 0xcc, sizeof(metrics));
4142 count = 0;
4143 hr = IDWriteTextLayout_GetLineMetrics(layout, metrics, ARRAY_SIZE(metrics), &count);
4144 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4145 ok(count == 6, "got %u\n", count);
4146
4147 ok(metrics[0].length == 2, "got %u\n", metrics[0].length);
4148 ok(metrics[1].length == 2, "got %u\n", metrics[1].length);
4149 ok(metrics[2].length == 2, "got %u\n", metrics[2].length);
4150 ok(metrics[3].length == 1, "got %u\n", metrics[3].length);
4151 ok(metrics[4].length == 3, "got %u\n", metrics[4].length);
4152 ok(metrics[5].length == 0, "got %u\n", metrics[5].length);
4153
4154 ok(metrics[0].newlineLength == 1, "got %u\n", metrics[0].newlineLength);
4155 ok(metrics[1].newlineLength == 1, "got %u\n", metrics[1].newlineLength);
4156 ok(metrics[2].newlineLength == 1, "got %u\n", metrics[2].newlineLength);
4157 ok(metrics[3].newlineLength == 1, "got %u\n", metrics[3].newlineLength);
4158 ok(metrics[4].newlineLength == 2, "got %u\n", metrics[4].newlineLength);
4159 ok(metrics[5].newlineLength == 0, "got %u\n", metrics[5].newlineLength);
4160
4161 ok(metrics[0].trailingWhitespaceLength == 1, "got %u\n", metrics[0].newlineLength);
4162 ok(metrics[1].trailingWhitespaceLength == 1, "got %u\n", metrics[1].newlineLength);
4163 ok(metrics[2].trailingWhitespaceLength == 1, "got %u\n", metrics[2].newlineLength);
4164 ok(metrics[3].trailingWhitespaceLength == 1, "got %u\n", metrics[3].newlineLength);
4165 ok(metrics[4].trailingWhitespaceLength == 2, "got %u\n", metrics[4].newlineLength);
4166 ok(metrics[5].trailingWhitespaceLength == 0, "got %u\n", metrics[5].newlineLength);
4167
4168 IDWriteTextLayout_Release(layout);
4169
4170 /* empty text layout */
4171 hr = IDWriteFactory_CreateTextLayout(factory, strW, 0, format, 100.0f, 300.0f, &layout);
4172 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4173
4174 count = 0;
4175 memset(metrics, 0, sizeof(metrics));
4176 hr = IDWriteTextLayout_GetLineMetrics(layout, metrics, 1, &count);
4177 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4178 ok(count == 1, "got %u\n", count);
4179 ok(metrics[0].length == 0, "got %u\n", metrics[0].length);
4181 ok(metrics[0].newlineLength == 0, "got %u\n", metrics[0].newlineLength);
4182 ok(metrics[0].height > 0.0f, "got %f\n", metrics[0].height);
4183 ok(metrics[0].baseline > 0.0f, "got %f\n", metrics[0].baseline);
4184 ok(!metrics[0].isTrimmed, "got %d\n", metrics[0].isTrimmed);
4185
4186 /* change font size at first position, see if metrics changed */
4187 range.startPosition = 0;
4188 range.length = 1;
4189 hr = IDWriteTextLayout_SetFontSize(layout, 80.0f, range);
4190 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4191
4192 count = 0;
4193 hr = IDWriteTextLayout_GetLineMetrics(layout, metrics + 1, 1, &count);
4194 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4195 ok(count == 1, "got %u\n", count);
4196 ok(metrics[1].height > metrics[0].height, "got %f\n", metrics[1].height);
4197 ok(metrics[1].baseline > metrics[0].baseline, "got %f\n", metrics[1].baseline);
4198
4199 /* revert font size back to format value, set different size for position 1 */
4200 hr = IDWriteTextLayout_SetFontSize(layout, 12.0f, range);
4201 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4202
4203 range.startPosition = 1;
4204 range.length = 1;
4205 hr = IDWriteTextLayout_SetFontSize(layout, 80.0f, range);
4206 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4207
4208 memset(metrics + 1, 0, sizeof(*metrics));
4209 count = 0;
4210 hr = IDWriteTextLayout_GetLineMetrics(layout, metrics + 1, 1, &count);
4211 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4212 ok(count == 1, "got %u\n", count);
4213 ok(metrics[1].height == metrics[0].height, "got %f\n", metrics[1].height);
4214 ok(metrics[1].baseline == metrics[0].baseline, "got %f\n", metrics[1].baseline);
4215
4216 IDWriteTextLayout_Release(layout);
4217
4218 /* text is "a\r" */
4219 hr = IDWriteFactory_CreateTextLayout(factory, str4W, 2, format, 100.0f, 300.0f, &layout);
4220 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4221
4222 count = 0;
4223 memset(metrics, 0, sizeof(metrics));
4224 hr = IDWriteTextLayout_GetLineMetrics(layout, metrics, ARRAY_SIZE(metrics), &count);
4225 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4226 ok(count == 2, "got %u\n", count);
4227 ok(metrics[0].length == 2, "got %u\n", metrics[0].length);
4228 ok(metrics[0].newlineLength == 1, "got %u\n", metrics[0].newlineLength);
4229 ok(metrics[0].height > 0.0f, "got %f\n", metrics[0].height);
4230 ok(metrics[0].baseline > 0.0f, "got %f\n", metrics[0].baseline);
4231 ok(metrics[1].length == 0, "got %u\n", metrics[1].length);
4232 ok(metrics[1].newlineLength == 0, "got %u\n", metrics[1].newlineLength);
4233 ok(metrics[1].height > 0.0f, "got %f\n", metrics[1].height);
4234 ok(metrics[1].baseline > 0.0f, "got %f\n", metrics[1].baseline);
4235
4236 range.startPosition = 1;
4237 range.length = 1;
4238 hr = IDWriteTextLayout_SetFontSize(layout, 80.0f, range);
4239 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4240
4241 hr = IDWriteTextLayout_GetLineMetrics(layout, metrics + 2, 2, &count);
4242 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4243 ok(count == 2, "got %u\n", count);
4244 ok(metrics[3].height > metrics[1].height, "got %f, old %f\n", metrics[3].height, metrics[1].height);
4245 ok(metrics[3].baseline > metrics[1].baseline, "got %f, old %f\n", metrics[3].baseline, metrics[1].baseline);
4246
4247 /* revert to original format */
4248 hr = IDWriteTextLayout_SetFontSize(layout, 12.0f, range);
4249 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4250 hr = IDWriteTextLayout_GetLineMetrics(layout, metrics + 2, 2, &count);
4251 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4252 ok(count == 2, "got %u\n", count);
4253 ok(metrics[3].height == metrics[1].height, "got %f, old %f\n", metrics[3].height, metrics[1].height);
4254 ok(metrics[3].baseline == metrics[1].baseline, "got %f, old %f\n", metrics[3].baseline, metrics[1].baseline);
4255
4256 /* Switch to uniform spacing */
4257 hr = IDWriteTextLayout_SetLineSpacing(layout, DWRITE_LINE_SPACING_METHOD_UNIFORM, 456.0f, 123.0f);
4258 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4259
4260 hr = IDWriteTextLayout_GetLineMetrics(layout, metrics, ARRAY_SIZE(metrics), &count);
4261 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4262 ok(count == 2, "got %u\n", count);
4263
4264 for (i = 0; i < count; i++) {
4265 ok(metrics[i].height == 456.0f, "%u: got line height %f\n", i, metrics[i].height);
4266 ok(metrics[i].baseline == 123.0f, "%u: got line baseline %f\n", i, metrics[i].baseline);
4267 }
4268
4269 IDWriteTextLayout_Release(layout);
4270
4271 /* Switch to proportional */
4272 hr = IDWriteTextFormat_SetLineSpacing(format, DWRITE_LINE_SPACING_METHOD_PROPORTIONAL, 2.0f, 4.0f);
4273 if (hr == S_OK) {
4274 hr = IDWriteFactory_CreateTextLayout(factory, str4W, 1, format, 100.0f, 300.0f, &layout);
4275 ok(hr == S_OK, "Failed to create layout, hr %#lx.\n", hr);
4276
4277 hr = IDWriteTextLayout_GetLineMetrics(layout, metrics, ARRAY_SIZE(metrics), &count);
4278 ok(hr == S_OK, "Failed to get line metrics, hr %#lx.\n", hr);
4279 ok(count == 1, "Unexpected line count %u\n", count);
4280
4281 /* Back to default mode. */
4282 hr = IDWriteTextLayout_SetLineSpacing(layout, DWRITE_LINE_SPACING_METHOD_DEFAULT, 0.0f, 0.0f);
4283 ok(hr == S_OK, "Failed to set spacing method, hr %#lx.\n", hr);
4284
4285 hr = IDWriteTextLayout_GetLineMetrics(layout, metrics + 1, 1, &count);
4286 ok(hr == S_OK, "Failed to get line metrics, hr %#lx.\n", hr);
4287 ok(count == 1, "Unexpected line count %u\n", count);
4288
4289 /* Proportional spacing applies multipliers to default, content based spacing. */
4290 ok(metrics[0].height == 2.0f * metrics[1].height, "Unexpected line height %f.\n", metrics[0].height);
4291 ok(metrics[0].baseline == 4.0f * metrics[1].baseline, "Unexpected line baseline %f.\n", metrics[0].baseline);
4292
4293 IDWriteTextLayout_Release(layout);
4294 }
4295 else
4296 win_skip("Proportional spacing is not supported.\n");
4297
4298 IDWriteTextFormat_Release(format);
4299 IDWriteFontFace_Release(fontface);
4300 IDWriteFactory_Release(factory);
4301}
4302
4303static void test_SetTextAlignment(void)
4304{
4305 static const WCHAR stringsW[][10] = {
4306 {'a',0},
4307 {0}
4308 };
4309
4310 DWRITE_CLUSTER_METRICS clusters[10];
4312 IDWriteTextFormat1 *format1;
4314 IDWriteTextLayout *layout;
4317 UINT32 count, i;
4318 HRESULT hr;
4319
4321
4322 hr = IDWriteFactory_CreateTextFormat(factory, L"Tahoma", NULL, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL,
4323 DWRITE_FONT_STRETCH_NORMAL, 12.0f, L"en-us", &format);
4324 ok(hr == S_OK, "Failed to create text format, hr %#lx.\n", hr);
4325
4326 v = IDWriteTextFormat_GetTextAlignment(format);
4327 ok(v == DWRITE_TEXT_ALIGNMENT_LEADING, "got %d\n", v);
4328
4329 hr = IDWriteFactory_CreateTextLayout(factory, L"a", 1, format, 500.0f, 100.0f, &layout);
4330 ok(hr == S_OK, "Failed to create text layout, hr %#lx.\n", hr);
4331
4332 v = IDWriteTextLayout_GetTextAlignment(layout);
4333 ok(v == DWRITE_TEXT_ALIGNMENT_LEADING, "got %d\n", v);
4334
4335 hr = IDWriteTextLayout_SetTextAlignment(layout, DWRITE_TEXT_ALIGNMENT_TRAILING);
4336 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4337
4338 hr = IDWriteTextLayout_SetTextAlignment(layout, DWRITE_TEXT_ALIGNMENT_TRAILING);
4339 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4340
4341 v = IDWriteTextFormat_GetTextAlignment(format);
4342 ok(v == DWRITE_TEXT_ALIGNMENT_LEADING, "got %d\n", v);
4343
4344 v = IDWriteTextLayout_GetTextAlignment(layout);
4345 ok(v == DWRITE_TEXT_ALIGNMENT_TRAILING, "got %d\n", v);
4346
4347 hr = IDWriteTextLayout_QueryInterface(layout, &IID_IDWriteTextFormat1, (void**)&format1);
4348 if (hr == S_OK) {
4349 hr = IDWriteTextFormat1_SetTextAlignment(format1, DWRITE_TEXT_ALIGNMENT_CENTER);
4350 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4351
4352 v = IDWriteTextFormat_GetTextAlignment(format);
4353 ok(v == DWRITE_TEXT_ALIGNMENT_LEADING, "got %d\n", v);
4354
4355 v = IDWriteTextLayout_GetTextAlignment(layout);
4356 ok(v == DWRITE_TEXT_ALIGNMENT_CENTER, "got %d\n", v);
4357
4358 v = IDWriteTextFormat1_GetTextAlignment(format1);
4359 ok(v == DWRITE_TEXT_ALIGNMENT_CENTER, "got %d\n", v);
4360
4361 IDWriteTextFormat1_Release(format1);
4362 }
4363 else
4364 win_skip("IDWriteTextFormat1 is not supported\n");
4365
4366 IDWriteTextLayout_Release(layout);
4367
4368 for (i = 0; i < ARRAY_SIZE(stringsW); i++) {
4369 FLOAT text_width;
4370
4371 hr = IDWriteTextFormat_SetTextAlignment(format, DWRITE_TEXT_ALIGNMENT_LEADING);
4372 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4373
4374 hr = IDWriteFactory_CreateTextLayout(factory, stringsW[i], lstrlenW(stringsW[i]), format, 500.0f, 100.0f, &layout);
4375 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4376
4377 hr = IDWriteTextLayout_SetWordWrapping(layout, DWRITE_WORD_WRAPPING_NO_WRAP);
4378 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4379
4380 count = 0;
4381 hr = IDWriteTextLayout_GetClusterMetrics(layout, clusters, ARRAY_SIZE(clusters), &count);
4382 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4383 if (stringsW[i][0])
4384 ok(count > 0, "got %u\n", count);
4385 else
4386 ok(count == 0, "got %u\n", count);
4387
4388 text_width = 0.0f;
4389 while (count)
4390 text_width += clusters[--count].width;
4391
4392 /* maxwidth is 500, leading alignment */
4393 hr = IDWriteTextLayout_SetTextAlignment(layout, DWRITE_TEXT_ALIGNMENT_LEADING);
4394 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4395
4396 hr = IDWriteTextLayout_GetMetrics(layout, &metrics);
4397 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4398
4399 ok(metrics.left == 0.0f, "got %.2f\n", metrics.left);
4400 ok(metrics.width == text_width, "got %.2f\n", metrics.width);
4401 ok(metrics.layoutWidth == 500.0f, "got %.2f\n", metrics.layoutWidth);
4402 ok(metrics.lineCount == 1, "got %d\n", metrics.lineCount);
4403
4404 /* maxwidth is 500, trailing alignment */
4405 hr = IDWriteTextLayout_SetTextAlignment(layout, DWRITE_TEXT_ALIGNMENT_TRAILING);
4406 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4407
4408 hr = IDWriteTextLayout_GetMetrics(layout, &metrics);
4409 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4410
4411 ok(metrics.left == metrics.layoutWidth - metrics.width, "got %.2f\n", metrics.left);
4412 ok(metrics.width == text_width, "got %.2f\n", metrics.width);
4413 ok(metrics.layoutWidth == 500.0f, "got %.2f\n", metrics.layoutWidth);
4414 ok(metrics.lineCount == 1, "got %d\n", metrics.lineCount);
4415 IDWriteTextLayout_Release(layout);
4416
4417 /* initially created with trailing alignment */
4418 hr = IDWriteTextFormat_SetTextAlignment(format, DWRITE_TEXT_ALIGNMENT_TRAILING);
4419 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4420
4421 hr = IDWriteFactory_CreateTextLayout(factory, stringsW[i], lstrlenW(stringsW[i]), format, 500.0f, 100.0f, &layout);
4422 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4423
4424 hr = IDWriteTextLayout_GetMetrics(layout, &metrics);
4425 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4426
4427 ok(metrics.left == metrics.layoutWidth - metrics.width, "got %.2f\n", metrics.left);
4428 ok(metrics.width == text_width, "got %.2f\n", metrics.width);
4429 ok(metrics.layoutWidth == 500.0f, "got %.2f\n", metrics.layoutWidth);
4430 ok(metrics.lineCount == 1, "got %d\n", metrics.lineCount);
4431 IDWriteTextLayout_Release(layout);
4432
4433 if (stringsW[i][0]) {
4434 /* max width less than total run width, trailing alignment */
4435 hr = IDWriteTextFormat_SetWordWrapping(format, DWRITE_WORD_WRAPPING_NO_WRAP);
4436 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4437
4438 hr = IDWriteFactory_CreateTextLayout(factory, stringsW[i], lstrlenW(stringsW[i]), format, clusters[0].width, 100.0f, &layout);
4439 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4440 hr = IDWriteTextLayout_GetMetrics(layout, &metrics);
4441 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4442 ok(metrics.left == metrics.layoutWidth - metrics.width, "got %.2f\n", metrics.left);
4443 ok(metrics.width == text_width, "got %.2f\n", metrics.width);
4444 ok(metrics.lineCount == 1, "got %d\n", metrics.lineCount);
4445 IDWriteTextLayout_Release(layout);
4446 }
4447
4448 /* maxwidth is 500, centered */
4449 hr = IDWriteTextFormat_SetTextAlignment(format, DWRITE_TEXT_ALIGNMENT_CENTER);
4450 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4451
4452 hr = IDWriteFactory_CreateTextLayout(factory, stringsW[i], lstrlenW(stringsW[i]), format, 500.0f, 100.0f, &layout);
4453 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4454
4455 hr = IDWriteTextLayout_GetMetrics(layout, &metrics);
4456 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4457 ok(metrics.left == (metrics.layoutWidth - metrics.width) / 2.0f, "got %.2f\n", metrics.left);
4458 ok(metrics.width == text_width, "got %.2f\n", metrics.width);
4459 ok(metrics.lineCount == 1, "got %d\n", metrics.lineCount);
4460
4461 IDWriteTextLayout_Release(layout);
4462 }
4463
4464 IDWriteTextFormat_Release(format);
4465 IDWriteFactory_Release(factory);
4466}
4467
4469{
4472 IDWriteTextLayout *layout;
4476 UINT32 count;
4477 HRESULT hr;
4478
4480
4481 hr = IDWriteFactory_CreateTextFormat(factory, L"Tahoma", NULL, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL,
4482 DWRITE_FONT_STRETCH_NORMAL, 12.0f, L"en-us", &format);
4483 ok(hr == S_OK, "Failed to create text format, hr %#lx.\n", hr);
4484
4485 v = IDWriteTextFormat_GetParagraphAlignment(format);
4486 ok(v == DWRITE_PARAGRAPH_ALIGNMENT_NEAR, "got %d\n", v);
4487
4488 hr = IDWriteFactory_CreateTextLayout(factory, L"a", 1, format, 500.0f, 100.0f, &layout);
4489 ok(hr == S_OK, "Failed to create text layout, hr %#lx.\n", hr);
4490
4491 v = IDWriteTextLayout_GetParagraphAlignment(layout);
4492 ok(v == DWRITE_PARAGRAPH_ALIGNMENT_NEAR, "got %d\n", v);
4493
4494 hr = IDWriteTextLayout_SetParagraphAlignment(layout, DWRITE_PARAGRAPH_ALIGNMENT_FAR);
4495 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4496
4497 hr = IDWriteTextLayout_SetParagraphAlignment(layout, DWRITE_PARAGRAPH_ALIGNMENT_FAR);
4498 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4499
4500 v = IDWriteTextFormat_GetParagraphAlignment(format);
4501 ok(v == DWRITE_PARAGRAPH_ALIGNMENT_NEAR, "got %d\n", v);
4502
4503 v = IDWriteTextLayout_GetParagraphAlignment(layout);
4504 ok(v == DWRITE_PARAGRAPH_ALIGNMENT_FAR, "got %d\n", v);
4505
4506 hr = IDWriteTextLayout_SetParagraphAlignment(layout, DWRITE_PARAGRAPH_ALIGNMENT_CENTER);
4507 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4508
4509 v = IDWriteTextLayout_GetParagraphAlignment(layout);
4510 ok(v == DWRITE_PARAGRAPH_ALIGNMENT_CENTER, "got %d\n", v);
4511
4512 count = 0;
4513 hr = IDWriteTextLayout_GetLineMetrics(layout, lines, 1, &count);
4514 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4515 ok(count == 1, "got %u\n", count);
4516
4517 /* maxheight is 100, near alignment */
4518 hr = IDWriteTextLayout_SetParagraphAlignment(layout, DWRITE_PARAGRAPH_ALIGNMENT_NEAR);
4519 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4520
4521 hr = IDWriteTextLayout_GetMetrics(layout, &metrics);
4522 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4523
4524 ok(metrics.top == 0.0, "got %.2f\n", metrics.top);
4525 ok(metrics.height == lines[0].height, "got %.2f\n", metrics.height);
4526 ok(metrics.layoutHeight == 100.0, "got %.2f\n", metrics.layoutHeight);
4527 ok(metrics.lineCount == 1, "got %d\n", metrics.lineCount);
4528
4529 /* maxwidth is 100, far alignment */
4530 hr = IDWriteTextLayout_SetParagraphAlignment(layout, DWRITE_PARAGRAPH_ALIGNMENT_FAR);
4531 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4532
4533 hr = IDWriteTextLayout_GetMetrics(layout, &metrics);
4534 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4535
4536 ok(metrics.top == metrics.layoutHeight - metrics.height, "got %.2f\n", metrics.top);
4537 ok(metrics.height == lines[0].height, "got %.2f\n", metrics.height);
4538 ok(metrics.layoutHeight == 100.0, "got %.2f\n", metrics.layoutHeight);
4539 ok(metrics.lineCount == 1, "got %d\n", metrics.lineCount);
4540 IDWriteTextLayout_Release(layout);
4541
4542 /* initially created with centered alignment */
4543 hr = IDWriteTextFormat_SetParagraphAlignment(format, DWRITE_PARAGRAPH_ALIGNMENT_CENTER);
4544 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4545
4546 hr = IDWriteFactory_CreateTextLayout(factory, L"a", 1, format, 500.0f, 100.0f, &layout);
4547 ok(hr == S_OK, "Failed to create text layout, hr %#lx.\n", hr);
4548
4549 hr = IDWriteTextLayout_GetMetrics(layout, &metrics);
4550 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4551
4552 ok(metrics.top == (metrics.layoutHeight - lines[0].height) / 2, "got %.2f\n", metrics.top);
4553 ok(metrics.height == lines[0].height, "got %.2f\n", metrics.height);
4554 ok(metrics.lineCount == 1, "got %d\n", metrics.lineCount);
4555 IDWriteTextLayout_Release(layout);
4556
4557 IDWriteTextFormat_Release(format);
4558 IDWriteFactory_Release(factory);
4559}
4560
4562{
4563 DWRITE_CLUSTER_METRICS clusters[1];
4566 IDWriteTextLayout *layout;
4570 UINT32 count;
4571 HRESULT hr;
4572
4574
4575 hr = IDWriteFactory_CreateTextFormat(factory, L"Tahoma", NULL, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL,
4576 DWRITE_FONT_STRETCH_NORMAL, 12.0f, L"en-us", &format);
4577 ok(hr == S_OK, "Failed to create text format, hr %#lx.\n", hr);
4578
4579 v = IDWriteTextFormat_GetReadingDirection(format);
4581
4582 hr = IDWriteFactory_CreateTextLayout(factory, L"a", 1, format, 500.0f, 100.0f, &layout);
4583 ok(hr == S_OK, "Failed to create text layout, hr %#lx.\n", hr);
4584
4585 v = IDWriteTextLayout_GetReadingDirection(layout);
4587
4588 v = IDWriteTextFormat_GetReadingDirection(format);
4590
4591 hr = IDWriteTextLayout_SetReadingDirection(layout, DWRITE_READING_DIRECTION_RIGHT_TO_LEFT);
4592 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4593
4594 count = 0;
4595 hr = IDWriteTextLayout_GetLineMetrics(layout, lines, 1, &count);
4596 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4597 ok(count == 1, "got %u\n", count);
4598
4599 count = 0;
4600 hr = IDWriteTextLayout_GetClusterMetrics(layout, clusters, 1, &count);
4601 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4602 ok(count == 1, "got %u\n", count);
4603
4604 /* leading alignment, RTL */
4605 hr = IDWriteTextLayout_GetMetrics(layout, &metrics);
4606 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4607
4608 ok(metrics.left == metrics.layoutWidth - clusters[0].width, "got %.2f\n", metrics.left);
4609 ok(metrics.top == 0.0, "got %.2f\n", metrics.top);
4610 ok(metrics.width == clusters[0].width, "got %.2f\n", metrics.width);
4611 ok(metrics.height == lines[0].height, "got %.2f\n", metrics.height);
4612 ok(metrics.layoutWidth == 500.0, "got %.2f\n", metrics.layoutWidth);
4613 ok(metrics.layoutHeight == 100.0, "got %.2f\n", metrics.layoutHeight);
4614 ok(metrics.lineCount == 1, "got %d\n", metrics.lineCount);
4615
4616 /* trailing alignment, RTL */
4617 hr = IDWriteTextLayout_SetTextAlignment(layout, DWRITE_TEXT_ALIGNMENT_TRAILING);
4618 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4619
4620 hr = IDWriteTextLayout_GetMetrics(layout, &metrics);
4621 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4622
4623 ok(metrics.left == 0.0, "got %.2f\n", metrics.left);
4624 ok(metrics.top == 0.0, "got %.2f\n", metrics.top);
4625 ok(metrics.width == clusters[0].width, "got %.2f\n", metrics.width);
4626 ok(metrics.height == lines[0].height, "got %.2f\n", metrics.height);
4627 ok(metrics.layoutWidth == 500.0, "got %.2f\n", metrics.layoutWidth);
4628 ok(metrics.layoutHeight == 100.0, "got %.2f\n", metrics.layoutHeight);
4629 ok(metrics.lineCount == 1, "got %d\n", metrics.lineCount);
4630
4631 /* centered alignment, RTL */
4632 hr = IDWriteTextLayout_SetTextAlignment(layout, DWRITE_TEXT_ALIGNMENT_CENTER);
4633 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4634
4635 hr = IDWriteTextLayout_GetMetrics(layout, &metrics);
4636 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4637
4638 ok(metrics.left == (metrics.layoutWidth - clusters[0].width) / 2.0, "got %.2f\n", metrics.left);
4639 ok(metrics.top == 0.0, "got %.2f\n", metrics.top);
4640 ok(metrics.width == clusters[0].width, "got %.2f\n", metrics.width);
4641 ok(metrics.height == lines[0].height, "got %.2f\n", metrics.height);
4642 ok(metrics.layoutWidth == 500.0, "got %.2f\n", metrics.layoutWidth);
4643 ok(metrics.layoutHeight == 100.0, "got %.2f\n", metrics.layoutHeight);
4644 ok(metrics.lineCount == 1, "got %d\n", metrics.lineCount);
4645
4646 IDWriteTextLayout_Release(layout);
4647
4648 IDWriteTextFormat_Release(format);
4649 IDWriteFactory_Release(factory);
4650}
4651
4653{
4654 return (FLOAT)metric * emSize / (FLOAT)metrics->designUnitsPerEm;
4655}
4656
4658{
4659 FLOAT vec[2], det, vec2[2];
4661
4662 /* has to be a diagonal matrix */
4663 if ((ppdip <= 0.0) ||
4664 (m->m11 * m->m22 != 0.0 && (m->m12 != 0.0 || m->m21 != 0.0)) ||
4665 (m->m12 * m->m21 != 0.0 && (m->m11 != 0.0 || m->m22 != 0.0)))
4666 return coord;
4667
4668 det = m->m11 * m->m22 - m->m12 * m->m21;
4669 transform = fabsf(det) > 1e-10;
4670
4671 if (transform) {
4672 /* apply transform */
4673 vec[0] = 0.0;
4674 vec[1] = coord * ppdip;
4675
4676 vec2[0] = m->m11 * vec[0] + m->m21 * vec[1] + m->dx;
4677 vec2[1] = m->m12 * vec[0] + m->m22 * vec[1] + m->dy;
4678
4679 /* snap */
4680 vec2[0] = floorf(vec2[0] + 0.5f);
4681 vec2[1] = floorf(vec2[1] + 0.5f);
4682
4683 /* apply inverted transform */
4684 vec[1] = (-m->m12 * vec2[0] + m->m11 * vec2[1] - (m->m11 * m->dy - m->m12 * m->dx)) / det;
4685 vec[1] /= ppdip;
4686 }
4687 else
4688 vec[1] = floorf(coord * ppdip + 0.5f) / ppdip;
4689 return vec[1];
4690}
4691
4693{
4694 int x = *(int *)&left;
4695 int y = *(int *)&right;
4696
4697 if (x < 0)
4698 x = INT_MIN - x;
4699 if (y < 0)
4700 y = INT_MIN - y;
4701
4702 return abs(x - y) <= 16;
4703}
4704
4708};
4709
4711 { { 0.0, 1.0, 2.0, 0.0, 0.2, 0.3 }, 1.0 },
4712 { { 0.0, 1.0, 2.0, 0.0, 0.0, 0.0 }, 1.0 },
4713 { { 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 }, 1.0 }, /* identity transform */
4714 { { 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 }, 0.9 },
4715 { { 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 }, -1.0 },
4716 { { 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 }, 0.0 },
4717 { { 1.0, 0.0, 0.0, 1.0, 0.0, 0.3 }, 1.0 }, /* simple Y shift */
4718 { { 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 }, 10.0 }, /* identity, 10 ppdip */
4719 { { 1.0, 0.0, 0.0, 10.0, 0.0, 0.0 }, 10.0 },
4720 { { 0.0, 1.0, 1.0, 0.0, 0.2, 0.6 }, 1.0 },
4721 { { 0.0, 2.0, 2.0, 0.0, 0.2, 0.6 }, 1.0 },
4722 { { 0.0, 0.5, -0.5, 0.0, 0.2, 0.6 }, 1.0 },
4723 { { 1.0, 2.0, 0.0, 1.0, 0.2, 0.6 }, 1.0 },
4724 { { 1.0, 1.0, 0.0, 1.0, 0.2, 0.6 }, 1.0 },
4725 { { 0.5, 0.5, -0.5, 0.5, 0.2, 0.6 }, 1.0 }, /* 45 degrees rotation */
4726 { { 0.5, 0.5, -0.5, 0.5, 0.0, 0.0 }, 100.0 }, /* 45 degrees rotation */
4727 { { 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 }, 100.0 },
4728 { { 0.0, 1.0, -1.0, 0.0, 0.2, 0.6 }, 1.0 }, /* 90 degrees rotation */
4729 { { -1.0, 0.0, 0.0, -1.0, 0.2, 0.6 }, 1.0 }, /* 180 degrees rotation */
4730 { { 0.0, -1.0, 1.0, 0.0, 0.2, 0.6 }, 1.0 }, /* 270 degrees rotation */
4731 { { 1.0, 0.0, 0.0, 1.0,-0.1, 0.2 }, 1.0 },
4732 { { 0.0, 1.0, -1.0, 0.0,-0.2,-0.3 }, 1.0 }, /* 90 degrees rotation */
4733 { { -1.0, 0.0, 0.0, -1.0,-0.3,-1.6 }, 1.0 }, /* 180 degrees rotation */
4734 { { 0.0, -1.0, 1.0, 0.0,-0.7, 0.6 }, 10.0 }, /* 270 degrees rotation */
4735 { { 0.0, 2.0, 1.0, 0.0, 0.2, 0.6 }, 1.0 },
4736 { { 0.0, 0.0, 1.0, 0.0, 0.0, 0.0 }, 1.0 },
4737 { { 3.0, 0.0, 0.0, 5.0, 0.2,-0.3 }, 10.0 },
4738 { { 0.0, -3.0, 5.0, 0.0,-0.1, 0.7 }, 10.0 },
4739};
4740
4742 { 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 },
4743 { 1.0, 0.0, 0.0, 1.0, 0.2, 0.3 },
4744 { 2.0, 0.0, 0.0, 2.0, 0.2, 0.3 },
4745 { 2.0, 1.0, 2.0, 2.0, 0.2, 0.3 },
4746};
4747
4748static void test_pixelsnapping(void)
4749{
4750 IDWriteTextLayout *layout, *layout2;
4751 struct renderer_context ctxt;
4754 IDWriteFontFace *fontface;
4757 HRESULT hr;
4758 int i, j;
4759
4761
4762 hr = IDWriteFactory_CreateTextFormat(factory, L"Tahoma", NULL, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL,
4763 DWRITE_FONT_STRETCH_NORMAL, 12.0f, L"en-us", &format);
4764 ok(hr == S_OK, "Failed to create text format, hr %#lx.\n", hr);
4765
4766 fontface = get_fontface_from_format(format);
4767 IDWriteFontFace_GetMetrics(fontface, &metrics);
4768
4769 hr = IDWriteFactory_CreateTextLayout(factory, L"a", 1, format, 500.0f, 100.0f, &layout);
4770 ok(hr == S_OK, "Failed to create text layout, hr %#lx.\n", hr);
4771
4772 /* disabled snapping */
4773 ctxt.snapping_disabled = TRUE;
4774 ctxt.gdicompat = FALSE;
4775 ctxt.use_gdi_natural = FALSE;
4776 ctxt.ppdip = 1.0f;
4777 memset(&ctxt.m, 0, sizeof(ctxt.m));
4778 ctxt.m.m11 = ctxt.m.m22 = 1.0;
4779 originX = 0.1;
4780
4781 hr = IDWriteTextLayout_Draw(layout, &ctxt, &testrenderer, originX, 0.0);
4782 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4783
4785 ok(ctxt.originX == originX, "got %f, originX %f\n", ctxt.originX, originX);
4786 ok(ctxt.originY == baseline, "got %f, baseline %f\n", ctxt.originY, baseline);
4787 ok(floor(baseline) != baseline, "got %f\n", baseline);
4788
4789 ctxt.snapping_disabled = FALSE;
4790
4791 for (i = 0; i < ARRAY_SIZE(snapping_tests); i++) {
4792 struct snapping_test *ptr = &snapping_tests[i];
4793 FLOAT expectedY;
4794
4795 ctxt.m = ptr->m;
4796 ctxt.ppdip = ptr->ppdip;
4797 ctxt.originX = 678.9;
4798 ctxt.originY = 678.9;
4799
4800 expectedY = snap_coord(&ctxt.m, ctxt.ppdip, baseline);
4801 hr = IDWriteTextLayout_Draw(layout, &ctxt, &testrenderer, originX, 0.0);
4802 ok(hr == S_OK, "%d: unexpected hr %#lx.\n", i, hr);
4803 ok(ctxt.originX == originX, "%d: got %f, originX %f\n", i, ctxt.originX, originX);
4804 ok(float_eq(ctxt.originY, expectedY), "%d: got %f, expected %f, baseline %f\n",
4805 i, ctxt.originY, expectedY, baseline);
4806
4807 /* gdicompat layout transform doesn't affect snapping */
4808 for (j = 0; j < ARRAY_SIZE(compattransforms); ++j)
4809 {
4810 hr = IDWriteFactory_CreateGdiCompatibleTextLayout(factory, L"a", 1, format, 500.0f, 100.0f,
4811 1.0f, &compattransforms[j], FALSE, &layout2);
4812 ok(hr == S_OK, "%d: failed to create text layout, hr %#lx.\n", i, hr);
4813
4814 expectedY = snap_coord(&ctxt.m, ctxt.ppdip, baseline);
4815 hr = IDWriteTextLayout_Draw(layout, &ctxt, &testrenderer, originX, 0.0);
4816 ok(hr == S_OK, "%d: unexpected hr %#lx.\n", i, hr);
4817 ok(ctxt.originX == originX, "%d: got %f, originX %f\n", i, ctxt.originX, originX);
4818 ok(float_eq(ctxt.originY, expectedY), "%d: got %f, expected %f, baseline %f\n",
4819 i, ctxt.originY, expectedY, baseline);
4820
4821 IDWriteTextLayout_Release(layout2);
4822 }
4823 }
4824
4825 IDWriteTextLayout_Release(layout);
4826 IDWriteTextFormat_Release(format);
4827 IDWriteFontFace_Release(fontface);
4828 IDWriteFactory_Release(factory);
4829}
4830
4831static void test_SetWordWrapping(void)
4832{
4833 static const WCHAR strW[] = {'a',' ','s','o','m','e',' ','t','e','x','t',' ','a','n','d',
4834 ' ','a',' ','b','i','t',' ','m','o','r','e','\n','b'};
4836 IDWriteTextLayout *layout;
4839 UINT32 count;
4840 HRESULT hr;
4841
4843
4844 hr = IDWriteFactory_CreateTextFormat(factory, L"Tahoma", NULL, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL,
4845 DWRITE_FONT_STRETCH_NORMAL, 12.0f, L"en-us", &format);
4846 ok(hr == S_OK, "Failed to create text format, hr %#lx.\n", hr);
4847
4848 v = IDWriteTextFormat_GetWordWrapping(format);
4849 ok(v == DWRITE_WORD_WRAPPING_WRAP, "got %d\n", v);
4850
4851 hr = IDWriteFactory_CreateTextLayout(factory, strW, ARRAY_SIZE(strW), format, 10.0f, 100.0f, &layout);
4852 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4853
4854 v = IDWriteTextLayout_GetWordWrapping(layout);
4855 ok(v == DWRITE_WORD_WRAPPING_WRAP, "got %d\n", v);
4856
4857 hr = IDWriteTextLayout_SetWordWrapping(layout, DWRITE_WORD_WRAPPING_NO_WRAP);
4858 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4859
4860 hr = IDWriteTextLayout_SetWordWrapping(layout, DWRITE_WORD_WRAPPING_NO_WRAP);
4861 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4862
4863 v = IDWriteTextFormat_GetWordWrapping(format);
4864 ok(v == DWRITE_WORD_WRAPPING_WRAP, "got %d\n", v);
4865
4866 /* disable wrapping, text has explicit newline */
4867 hr = IDWriteTextLayout_SetWordWrapping(layout, DWRITE_WORD_WRAPPING_NO_WRAP);
4868 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4869
4870 count = 0;
4871 hr = IDWriteTextLayout_GetLineMetrics(layout, NULL, 0, &count);
4872 ok(hr == E_NOT_SUFFICIENT_BUFFER, "Unexpected hr %#lx.\n", hr);
4873 ok(count == 2, "got %u\n", count);
4874
4875 hr = IDWriteTextLayout_SetWordWrapping(layout, DWRITE_WORD_WRAPPING_WRAP);
4876 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4877
4878 count = 0;
4879 hr = IDWriteTextLayout_GetLineMetrics(layout, NULL, 0, &count);
4880 ok(hr == E_NOT_SUFFICIENT_BUFFER, "Unexpected hr %#lx.\n", hr);
4881 ok(count > 2, "got %u\n", count);
4882
4883 IDWriteTextLayout_Release(layout);
4884 IDWriteTextFormat_Release(format);
4885 IDWriteFactory_Release(factory);
4886}
4887
4888/* Collection dedicated to fallback testing */
4889
4890static const WCHAR g_blahfontW[] = {'B','l','a','h',0};
4892{
4893 if (IsEqualIID(riid, &IID_IDWriteFontCollection) || IsEqualIID(riid, &IID_IUnknown)) {
4894 *obj = iface;
4895 IDWriteFontCollection_AddRef(iface);
4896 return S_OK;
4897 }
4898
4899 *obj = NULL;
4900 return E_NOINTERFACE;
4901}
4902
4904{
4905 return 2;
4906}
4907
4909{
4910 return 1;
4911}
4912
4914{
4915 ok(0, "unexpected call\n");
4916 return 0;
4917}
4918
4920{
4921 if (index == 123456)
4922 {
4924 IDWriteFontCollection *syscollection;
4925 BOOL exists;
4926 HRESULT hr;
4927
4928 hr = IDWriteFactory_GetSystemFontCollection(factory, &syscollection, FALSE);
4929 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4930
4931 hr = IDWriteFontCollection_FindFamilyName(syscollection, L"Tahoma", &index, &exists);
4932 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4933
4934 hr = IDWriteFontCollection_GetFontFamily(syscollection, index, family);
4935 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4936
4937 IDWriteFontCollection_Release(syscollection);
4938 IDWriteFactory_Release(factory);
4939 return S_OK;
4940 }
4941
4942 ok(0, "unexpected call\n");
4943 return E_NOTIMPL;
4944}
4945
4947{
4948 if (!lstrcmpW(name, g_blahfontW)) {
4949 *index = 123456;
4950 *exists = TRUE;
4951 return S_OK;
4952 }
4953 ok(0, "unexpected call, name %s\n", wine_dbgstr_w(name));
4954 return E_NOTIMPL;
4955}
4956
4958{
4959 ok(0, "unexpected call\n");
4960 return E_NOTIMPL;
4961}
4962
4963static const IDWriteFontCollectionVtbl fallbackcollectionvtbl = {
4971};
4972
4974
4976{
4978 IDWriteFontFamily *family;
4979 UINT32 index;
4980 BOOL exists;
4981 HRESULT hr;
4982
4983 hr = IDWriteFont_GetFontFamily(font, &family);
4984 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4985
4986 hr = IDWriteFontFamily_GetFamilyNames(family, &names);
4987 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4988
4989 hr = IDWriteLocalizedStrings_FindLocaleName(names, L"en-us", &index, &exists);
4990 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4991 ok(index != UINT_MAX && exists, "Name was not found.\n");
4992 hr = IDWriteLocalizedStrings_GetString(names, index, name, size);
4993 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4994
4995 IDWriteLocalizedStrings_Release(names);
4996 IDWriteFontFamily_Release(family);
4997}
4998
5000{
5001 if (C > 0xffff)
5002 {
5003 WCHAR X = (WCHAR)C;
5004 UINT32 U = (C >> 16) & ((1 << 5) - 1);
5005 WCHAR W = (WCHAR)U - 1;
5006
5007 **ptr = 0xD800 | (W << 6) | X >> 10; *ptr += 1;
5008 **ptr = (WCHAR)(0xDC00 | (X & ((1 << 10) - 1))); *ptr += 1;
5009 }
5010 else
5011 {
5012 **ptr = C; *ptr += 1;
5013 }
5014}
5015
5016static void test_MapCharacters(void)
5017{
5018 static const WCHAR str2W[] = {'a',0x3058,'b',0};
5019 static const UINT32 variation_selectors[] =
5020 {
5021 0x180b, 0x180c, 0x180d,
5022
5023 0xfe00, 0xfe01, 0xfe02, 0xfe03, 0xfe04, 0xfe05, 0xfe06, 0xfe07,
5024 0xfe08, 0xfe09, 0xfe0a, 0xfe0b, 0xfe0c, 0xfe0d, 0xfe0e, 0xfe0f,
5025
5026 0xe0100, 0xe0121, 0xe01ef,
5027 };
5029 IDWriteFontFileLoader *resource_loader;
5032 UINT32 mappedlength, vs_length;
5033 IDWriteFontFallback *fallback;
5034 IDWriteFactory2 *factory2;
5036 WCHAR buffW[50];
5037 WCHAR name[64];
5038 unsigned int i;
5039 HRSRC hrsrc;
5040 BOOL exists;
5041 FLOAT scale;
5042 WCHAR *ptr;
5043 HRESULT hr;
5044
5045 factory2 = create_factory_iid(&IID_IDWriteFactory2);
5046 if (!factory2)
5047 {
5048 win_skip("MapCharacters() is not supported.\n");
5049 return;
5050 }
5051
5052 fallback = NULL;
5053 hr = IDWriteFactory2_GetSystemFontFallback(factory2, &fallback);
5054 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5055 ok(fallback != NULL, "got %p\n", fallback);
5056
5057 mappedlength = 1;
5058 scale = 0.0f;
5059 font = (void*)0xdeadbeef;
5060 hr = IDWriteFontFallback_MapCharacters(fallback, NULL, 0, 0, NULL, NULL, DWRITE_FONT_WEIGHT_NORMAL,
5062 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
5063 ok(mappedlength == 0, "got %u\n", mappedlength);
5064 ok(scale == 1.0f, "got %f\n", scale);
5065 ok(font == NULL, "got %p\n", font);
5066
5067 /* zero length source */
5068 g_source = L"abc";
5069 mappedlength = 1;
5070 scale = 0.0f;
5071 font = (void*)0xdeadbeef;
5072 hr = IDWriteFontFallback_MapCharacters(fallback, &analysissource, 0, 0, NULL, NULL, DWRITE_FONT_WEIGHT_NORMAL,
5074 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5075 ok(mappedlength == 0, "got %u\n", mappedlength);
5076 ok(scale == 1.0f, "got %f\n", scale);
5077 ok(font == NULL, "got %p\n", font);
5078
5079 g_source = L"abc";
5080 mappedlength = 0;
5081 scale = 0.0f;
5082 font = NULL;
5083 hr = IDWriteFontFallback_MapCharacters(fallback, &analysissource, 0, 1, NULL, NULL, DWRITE_FONT_WEIGHT_NORMAL,
5085 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5086 ok(mappedlength == 1, "got %u\n", mappedlength);
5087 ok(scale == 1.0f, "got %f\n", scale);
5088 ok(font != NULL, "got %p\n", font);
5089 if (font)
5090 IDWriteFont_Release(font);
5091
5092 /* same Latin text, full length */
5093 g_source = L"abc";
5094 mappedlength = 0;
5095 scale = 0.0f;
5096 font = NULL;
5097 hr = IDWriteFontFallback_MapCharacters(fallback, &analysissource, 0, 3, NULL, NULL, DWRITE_FONT_WEIGHT_NORMAL,
5099 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5100 ok(mappedlength == 3, "got %u\n", mappedlength);
5101
5102 ok(scale == 1.0f, "got %f\n", scale);
5103 ok(font != NULL, "got %p\n", font);
5104 if (font)
5105 IDWriteFont_Release(font);
5106
5107 /* string 'a\x3058b' */
5108 g_source = str2W;
5109 mappedlength = 0;
5110 scale = 0.0f;
5111 font = NULL;
5112 hr = IDWriteFontFallback_MapCharacters(fallback, &analysissource, 0, 3, NULL, NULL, DWRITE_FONT_WEIGHT_NORMAL,
5114 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5115 ok(mappedlength == 1, "got %u\n", mappedlength);
5116 ok(scale == 1.0f, "got %f\n", scale);
5117 ok(font != NULL, "got %p\n", font);
5118 if (font)
5119 IDWriteFont_Release(font);
5120
5121 g_source = str2W;
5122 mappedlength = 0;
5123 scale = 0.0f;
5124 font = NULL;
5125 hr = IDWriteFontFallback_MapCharacters(fallback, &analysissource, 1, 2, NULL, NULL, DWRITE_FONT_WEIGHT_NORMAL,
5127 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5128 ok(mappedlength == 1, "Unexpected length %u.\n", mappedlength);
5129 ok(scale == 1.0f, "got %f\n", scale);
5130 ok(font != NULL, "got %p\n", font);
5131 if (font)
5132 IDWriteFont_Release(font);
5133
5134 /* Try with explicit collection, Tahoma will be forced. */
5135 /* 1. Latin part */
5136 g_source = str2W;
5137 mappedlength = 0;
5138 scale = 0.0f;
5139 font = NULL;
5140 hr = IDWriteFontFallback_MapCharacters(fallback, &analysissource, 0, 3, &fallbackcollection, g_blahfontW, DWRITE_FONT_WEIGHT_NORMAL,
5142 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5143 ok(mappedlength == 1, "got %u\n", mappedlength);
5144 ok(scale == 1.0f, "got %f\n", scale);
5145 ok(font != NULL, "got %p\n", font);
5146
5147 exists = FALSE;
5148 hr = IDWriteFont_GetInformationalStrings(font, DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES, &strings, &exists);
5149 ok(hr == S_OK && exists, "Unexpected hr %#lx, exists %d.\n", hr, exists);
5150 hr = IDWriteLocalizedStrings_GetString(strings, 0, buffW, ARRAY_SIZE(buffW));
5151 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5152 ok(!lstrcmpW(buffW, L"Tahoma"), "Unexpected string %s.\n", wine_dbgstr_w(buffW));
5153 IDWriteLocalizedStrings_Release(strings);
5154 IDWriteFont_Release(font);
5155
5156 /* 2. Hiragana character, force Tahoma font does not support Japanese */
5157 g_source = str2W;
5158 mappedlength = 0;
5159 scale = 0.0f;
5160 font = NULL;
5161 hr = IDWriteFontFallback_MapCharacters(fallback, &analysissource, 1, 1, &fallbackcollection, g_blahfontW, DWRITE_FONT_WEIGHT_NORMAL,
5163 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5164 ok(mappedlength == 1, "got %u\n", mappedlength);
5165 ok(scale == 1.0f, "got %f\n", scale);
5166 ok(font != NULL, "got %p\n", font);
5167
5168 if (font)
5169 {
5170 exists = FALSE;
5171 hr = IDWriteFont_GetInformationalStrings(font, DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES, &strings, &exists);
5172 ok(hr == S_OK && exists, "Unexpected hr %#lx, exists %d.\n", hr, exists);
5173 hr = IDWriteLocalizedStrings_GetString(strings, 0, buffW, ARRAY_SIZE(buffW));
5174 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5175 ok(lstrcmpW(buffW, L"Tahoma"), "Unexpected string %s.\n", wine_dbgstr_w(buffW));
5176 IDWriteLocalizedStrings_Release(strings);
5177 IDWriteFont_Release(font);
5178 }
5179
5180 /* Control characters. The test is using a bundled font that does not support them. */
5181 resource_loader = create_resource_file_loader();
5183
5184 hr = IDWriteFactory2_RegisterFontFileLoader(factory2, resource_loader);
5185 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5186 hr = IDWriteFactory2_RegisterFontCollectionLoader(factory2, resource_collection_loader);
5187 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5188
5190 ok(!!hrsrc, "Failed to find font resource\n");
5191
5192 hr = IDWriteFactory2_CreateCustomFontCollection(factory2, resource_collection_loader, &hrsrc, sizeof(hrsrc), &collection);
5193 ok(hr == S_OK, "Unexpected hr %#lx.\n",hr);
5194
5195 /* Variation selectors are skipped. */
5196 for (i = 0; i < ARRAY_SIZE(variation_selectors); ++i)
5197 {
5198 g_source = buffW;
5199
5200 vs_length = variation_selectors[i] > 0xffff ? 2 : 1;
5201
5202 winetest_push_context("Test %#x", variation_selectors[i]);
5203
5204 /* Selector within supported text. */
5205
5206 font = NULL;
5207 ptr = buffW;
5208
5209 *ptr = 'A'; ptr++;
5210 utf32_to_utf16(variation_selectors[i], &ptr);
5211 *ptr = 'A';
5212
5213 hr = IDWriteFontFallback_MapCharacters(fallback, &analysissource, 0, vs_length + 1, collection, L"wine_test",
5215 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5216 ok(mappedlength == vs_length + 1, "Unexpected mapped length %u.\n", mappedlength);
5218 ok(!wcscmp(name, L"wine_test"), "Unexpected font %s.\n", debugstr_w(name));
5219 IDWriteFont_Release(font);
5220
5221 /* Only selectors. */
5222 font = NULL;
5223 ptr = buffW;
5224 utf32_to_utf16(variation_selectors[i], &ptr);
5225 hr = IDWriteFontFallback_MapCharacters(fallback, &analysissource, 0, vs_length, collection, L"wine_test",
5227 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5228 ok(mappedlength == vs_length, "Unexpected mapped length %u.\n", mappedlength);
5229 if (variation_selectors[i] < 0xfe00)
5230 {
5231 /* Mongolian selectors belong to Mongolian range, and are mapped to a specific font. */
5232 if (font) IDWriteFont_Release(font);
5233 }
5234 else
5235 {
5236 /* Variation selectors do not have a fallback mapping on their own. */
5237 ok(!font, "Unexpected font instance.\n");
5238 }
5239
5240 /* Leading selector. Only use VS-1..16 so we don't hit a valid mapping range. */
5241 if (variation_selectors[i] >= 0xfe00)
5242 {
5243 ptr = buffW;
5244 utf32_to_utf16(variation_selectors[i], &ptr);
5245 utf32_to_utf16(variation_selectors[i], &ptr);
5246 *ptr = 'A';
5247
5248 font = (void *)0xdeadbeef;
5249 hr = IDWriteFontFallback_MapCharacters(fallback, &analysissource, 0, vs_length * 2 + 1, collection, L"wine_test",
5251 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5252 ok(mappedlength == vs_length * 2, "Unexpected mapped length %u.\n", mappedlength);
5253 ok(!font, "Unexpected font instance.\n");
5254
5255 hr = IDWriteFontFallback_MapCharacters(fallback, &analysissource, 0, vs_length * 2 + 1, NULL, NULL,
5257 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5258 ok(mappedlength == vs_length * 2, "Unexpected mapped length %u.\n", mappedlength);
5259 ok(!font, "Unexpected font instance.\n");
5260 }
5261
5262 /* Trailing selector. */
5263 ptr = buffW;
5264 *ptr = 'A'; ptr++;
5265 utf32_to_utf16(variation_selectors[i], &ptr);
5266
5267 font = (void *)0xdeadbeef;
5268 hr = IDWriteFontFallback_MapCharacters(fallback, &analysissource, 0, vs_length + 1, collection, L"wine_test",
5270 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5271 ok(mappedlength == vs_length + 1, "Unexpected mapped length %u.\n", mappedlength);
5273 ok(!wcscmp(name, L"wine_test"), "Unexpected font %s.\n", debugstr_w(name));
5274 IDWriteFont_Release(font);
5275
5277 }
5278
5279 IDWriteFontCollection_Release(collection);
5280
5281 hr = IDWriteFactory2_UnregisterFontCollectionLoader(factory2, resource_collection_loader);
5282 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5283 hr = IDWriteFactory2_UnregisterFontFileLoader(factory2, resource_loader);
5284 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5285
5286 IDWriteFontCollectionLoader_Release(resource_collection_loader);
5287 IDWriteFontFileLoader_Release(resource_loader);
5288
5289 IDWriteFontFallback_Release(fallback);
5290 IDWriteFactory2_Release(factory2);
5291}
5292
5294{
5295 WCHAR *p, str[256];
5296
5297 wcscpy(str, list);
5298 for (p = wcstok(str, L";"); p; p = wcstok(NULL, L";"))
5299 {
5300 if (!wcscmp(p, name))
5301 return TRUE;
5302 }
5303 return FALSE;
5304}
5305
5306static void test_system_fallback(void)
5307{
5308 static const struct fallback_test
5309 {
5310 const WCHAR text[2];
5311 const WCHAR *name;
5312 }
5313 tests[] =
5314 {
5315 { { 0x25d4, 0}, L"Segoe UI Symbol;Meiryo UI" },
5316 };
5317 IDWriteFontFallback *fallback;
5320 UINT32 i, length;
5321 WCHAR name[256];
5322 BOOL exists;
5323 float scale;
5324 HRESULT hr;
5325
5326 if (!(factory = create_factory_iid(&IID_IDWriteFactory2)))
5327 {
5328 win_skip("System font fallback API is not supported.\n");
5329 return;
5330 }
5331
5332 hr = IDWriteFactory2_GetSystemFontFallback(factory, &fallback);
5333 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5334
5335 for (i = 0; i < ARRAY_SIZE(tests); ++i)
5336 {
5337 font = NULL;
5338
5339 g_source = tests[i].text;
5340 hr = IDWriteFontFallback_MapCharacters(fallback, &analysissource, 0, 1, NULL, NULL, DWRITE_FONT_WEIGHT_NORMAL,
5342 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5343 if (hr != S_OK) continue;
5344 ok(length == 1, "Unexpected length %u\n", length);
5345 ok(scale == 1.0f, "got %f\n", scale);
5346 if (!font) continue;
5347
5349 todo_wine
5350 ok(is_font_name_match(name, tests[i].name), "%u: unexpected name %s.\n", i, wine_dbgstr_w(name));
5351
5352 hr = IDWriteFont_HasCharacter(font, g_source[0], &exists);
5353 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5354 todo_wine
5355 ok(exists, "%s missing character %#x\n", wine_dbgstr_w(name), g_source[0]);
5356
5357 IDWriteFont_Release(font);
5358 }
5359
5360 IDWriteFontFallback_Release(fallback);
5361 IDWriteFactory2_Release(factory);
5362}
5363
5365{
5366 IDWriteFontFallback *fallback, *fallback2;
5368 IDWriteFontFallback1 *fallback1;
5370 IDWriteFactory2 *factory2;
5372 const WCHAR *familyW;
5373 UINT32 mappedlength;
5375 FLOAT scale;
5376 HRESULT hr;
5377 ULONG ref;
5378
5380
5381 hr = IDWriteFactory_QueryInterface(factory, &IID_IDWriteFactory2, (void**)&factory2);
5382 IDWriteFactory_Release(factory);
5383
5384 if (hr != S_OK) {
5385 win_skip("IDWriteFontFallbackBuilder is not supported\n");
5386 return;
5387 }
5388
5389 EXPECT_REF(factory2, 1);
5390 hr = IDWriteFactory2_CreateFontFallbackBuilder(factory2, &builder);
5391 EXPECT_REF(factory2, 2);
5392
5393 fallback = NULL;
5394 EXPECT_REF(factory2, 2);
5395 EXPECT_REF(builder, 1);
5396 hr = IDWriteFontFallbackBuilder_CreateFontFallback(builder, &fallback);
5397 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5398 todo_wine EXPECT_REF(factory2, 3);
5399 EXPECT_REF(fallback, 1);
5400 EXPECT_REF(builder, 1);
5401
5402 IDWriteFontFallback_AddRef(fallback);
5403 EXPECT_REF(builder, 1);
5404 EXPECT_REF(fallback, 2);
5405 todo_wine EXPECT_REF(factory2, 3);
5406 IDWriteFontFallback_Release(fallback);
5407
5408 /* New instance is created every time, even if mappings have not changed. */
5409 hr = IDWriteFontFallbackBuilder_CreateFontFallback(builder, &fallback2);
5410 ok(hr == S_OK, "Failed to create fallback object, hr %#lx.\n", hr);
5411 ok(fallback != fallback2, "Unexpected fallback instance.\n");
5412 IDWriteFontFallback_Release(fallback2);
5413
5414 hr = IDWriteFontFallbackBuilder_AddMapping(builder, NULL, 0, NULL, 0, NULL, NULL, NULL, 0.0f);
5415 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
5416
5417 range.first = 'A';
5418 range.last = 'B';
5419 hr = IDWriteFontFallbackBuilder_AddMapping(builder, &range, 0, NULL, 0, NULL, NULL, NULL, 0.0f);
5420 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
5421
5422 hr = IDWriteFontFallbackBuilder_AddMapping(builder, &range, 0, NULL, 0, NULL, NULL, NULL, 1.0f);
5423 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
5424
5425 hr = IDWriteFontFallbackBuilder_AddMapping(builder, &range, 0, &familyW, 1, NULL, NULL, NULL, 1.0f);
5426 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
5427
5428 hr = IDWriteFontFallbackBuilder_AddMapping(builder, NULL, 0, &familyW, 1, NULL, NULL, NULL, 1.0f);
5429 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
5430
5431 /* negative scaling factor */
5432 range.first = range.last = 0;
5433 familyW = g_blahfontW;
5434 hr = IDWriteFontFallbackBuilder_AddMapping(builder, &range, 1, &familyW, 1, NULL, NULL, NULL, -1.0f);
5435 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
5436
5437 hr = IDWriteFontFallbackBuilder_AddMapping(builder, &range, 1, &familyW, 1, NULL, NULL, NULL, 0.0f);
5438 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5439
5440 /* empty range */
5441 range.first = range.last = 0;
5442 familyW = g_blahfontW;
5443 hr = IDWriteFontFallbackBuilder_AddMapping(builder, &range, 1, &familyW, 1, NULL, NULL, NULL, 1.0f);
5444 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5445
5446 range.first = range.last = 0;
5447 hr = IDWriteFontFallbackBuilder_AddMapping(builder, &range, 1, &familyW, 1, NULL, NULL, NULL, 2.0f);
5448 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5449
5450 range.first = range.last = 'A';
5451 hr = IDWriteFontFallbackBuilder_AddMapping(builder, &range, 1, &familyW, 1, NULL, NULL, NULL, 3.0f);
5452 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5453
5454 range.first = 'B';
5455 range.last = 'A';
5456 hr = IDWriteFontFallbackBuilder_AddMapping(builder, &range, 1, &familyW, 1, NULL, NULL, NULL, 4.0f);
5457 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5458
5459 IDWriteFontFallback_Release(fallback);
5460
5461 if (0) /* crashes on native */
5462 hr = IDWriteFontFallbackBuilder_CreateFontFallback(builder, NULL);
5463
5464 hr = IDWriteFontFallbackBuilder_CreateFontFallback(builder, &fallback);
5465 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5466
5467 /* fallback font missing from system collection */
5468 g_source = L"A";
5469 mappedlength = 0;
5470 scale = 0.0f;
5471 font = (void*)0xdeadbeef;
5472 hr = IDWriteFontFallback_MapCharacters(fallback, &analysissource, 0, 1, NULL, NULL, DWRITE_FONT_WEIGHT_NORMAL,
5474 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5475 ok(mappedlength == 1, "Unexpected length %u.\n", mappedlength);
5476 ok(scale == 1.0f, "Unexpected scale %f.\n", scale);
5477 ok(!font, "Unexpected font instance %p.\n", font);
5478
5479 IDWriteFontFallback_Release(fallback);
5480
5481 /* remap with custom collection */
5482 range.first = range.last = 'A';
5483 hr = IDWriteFontFallbackBuilder_AddMapping(builder, &range, 1, &familyW, 1, &fallbackcollection, NULL, NULL, 5.0f);
5484 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5485
5486 hr = IDWriteFontFallbackBuilder_CreateFontFallback(builder, &fallback);
5487 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5488
5489 g_source = L"A";
5490 mappedlength = 0;
5491 scale = 0.0f;
5492 font = NULL;
5493 hr = IDWriteFontFallback_MapCharacters(fallback, &analysissource, 0, 1, NULL, NULL, DWRITE_FONT_WEIGHT_NORMAL,
5495 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5496 ok(mappedlength == 1, "Unexpected length %u.\n", mappedlength);
5497 ok(scale == 5.0f, "Unexpected scale %f.\n", scale);
5498 ok(font != NULL, "Expected font instance %p.\n", font);
5499 if (font)
5500 IDWriteFont_Release(font);
5501
5502 IDWriteFontFallback_Release(fallback);
5503
5504 range.first = 'B';
5505 range.last = 'A';
5506 hr = IDWriteFontFallbackBuilder_AddMapping(builder, &range, 1, &familyW, 1, &fallbackcollection, NULL, NULL, 6.0f);
5507 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5508
5509 hr = IDWriteFontFallbackBuilder_CreateFontFallback(builder, &fallback);
5510 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5511
5512 g_source = L"A";
5513 mappedlength = 0;
5514 scale = 0.0f;
5515 font = NULL;
5516 hr = IDWriteFontFallback_MapCharacters(fallback, &analysissource, 0, 1, NULL, NULL, DWRITE_FONT_WEIGHT_NORMAL,
5518 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5519 ok(mappedlength == 1, "Unexpected length %u.\n", mappedlength);
5520 ok(scale == 5.0f, "Unexpected scale %f.\n", scale);
5521 ok(font != NULL, "Expected font instance %p.\n", font);
5522 if (font)
5523 IDWriteFont_Release(font);
5524
5525 IDWriteFontFallback_Release(fallback);
5526
5527 /* explicit locale */
5528 range.first = 'A';
5529 range.last = 'B';
5530 hr = IDWriteFontFallbackBuilder_AddMapping(builder, &range, 1, &familyW, 1, &fallbackcollection, L"locale", NULL, 6.0f);
5531 ok(hr == S_OK, "Failed to add mapping, hr %#lx.\n", hr);
5532
5533 hr = IDWriteFontFallbackBuilder_CreateFontFallback(builder, &fallback);
5534 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5535
5536 g_source = L"A";
5537 mappedlength = 0;
5538 scale = 0.0f;
5539 font = NULL;
5540 hr = IDWriteFontFallback_MapCharacters(fallback, &analysissource, 0, 1, NULL, NULL, DWRITE_FONT_WEIGHT_NORMAL,
5542 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5543 ok(mappedlength == 1, "Unexpected length %u.\n", mappedlength);
5544 ok(scale == 5.0f, "Unexpected scale %f.\n", scale);
5545 ok(font != NULL, "Expected font instance %p.\n", font);
5546 if (font)
5547 IDWriteFont_Release(font);
5548
5549 if (SUCCEEDED(IDWriteFontFallback_QueryInterface(fallback, &IID_IDWriteFontFallback1, (void **)&fallback1)))
5550 {
5551 IDWriteFontFallback1_Release(fallback1);
5552 }
5553 else
5554 win_skip("IDWriteFontFallback1 is not supported.\n");
5555
5556 IDWriteFontFallback_Release(fallback);
5557
5558 IDWriteFontFallbackBuilder_Release(builder);
5559 ref = IDWriteFactory2_Release(factory2);
5560 ok(ref == 0, "Factory is not released, ref %lu.\n", ref);
5561}
5562
5563static void test_fallback(void)
5564{
5565 IDWriteFontFallback *fallback, *fallback2;
5566 IDWriteFontFallback1 *fallback1;
5567 DWRITE_CLUSTER_METRICS clusters[4];
5569 IDWriteTextLayout2 *layout2;
5570 IDWriteTextFormat1 *format1;
5572 IDWriteTextLayout *layout;
5573 IDWriteFactory2 *factory2;
5575 UINT32 count, i;
5576 FLOAT width;
5577 HRESULT hr;
5578
5580
5581 /* Font does not exist in system collection. */
5582 hr = IDWriteFactory_CreateTextFormat(factory, g_blahfontW, NULL, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL,
5583 DWRITE_FONT_STRETCH_NORMAL, 10.0f, L"en-us", &format);
5584 ok(hr == S_OK, "Failed to create text format, hr %#lx.\n", hr);
5585
5586 hr = IDWriteFactory_CreateTextLayout(factory, L"abcd", 4, format, 1000.0f, 1000.0f, &layout);
5587 ok(hr == S_OK, "Failed to create text layout, hr %#lx.\n", hr);
5588
5589 count = 0;
5590 hr = IDWriteTextLayout_GetClusterMetrics(layout, clusters, 4, &count);
5591 ok(hr == S_OK, "Failed to get cluster metrics, hr %#lx.\n", hr);
5592 ok(count == 4, "Unexpected count %u.\n", count);
5593 for (i = 0, width = 0.0; i < count; i++)
5594 width += clusters[i].width;
5595
5596 memset(&metrics, 0xcc, sizeof(metrics));
5597 hr = IDWriteTextLayout_GetMetrics(layout, &metrics);
5598 ok(hr == S_OK, "Failed to get layout metrics, hr %#lx.\n", hr);
5599 ok(metrics.width > 0.0 && metrics.width == width, "Unexpected width %.2f, expected %.2f.\n", metrics.width, width);
5600 ok(metrics.height > 0.0, "Unexpected height %.2f.\n", metrics.height);
5601 ok(metrics.lineCount == 1, "Unexpected line count %u.\n", metrics.lineCount);
5602 IDWriteTextLayout_Release(layout);
5603 IDWriteTextFormat_Release(format);
5604
5605 hr = IDWriteFactory_CreateTextFormat(factory, L"Tahoma", NULL, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL,
5606 DWRITE_FONT_STRETCH_NORMAL, 10.0f, L"en-us", &format);
5607 ok(hr == S_OK, "Failed to create text format, hr %#lx.\n", hr);
5608
5609 /* Existing font. */
5610 hr = IDWriteFactory_CreateTextLayout(factory, L"abcd", 4, format, 1000.0f, 1000.0f, &layout);
5611 ok(hr == S_OK, "Failed to create text layout, hr %#lx.\n", hr);
5612 IDWriteTextFormat_Release(format);
5613
5614 hr = IDWriteTextLayout_QueryInterface(layout, &IID_IDWriteTextLayout2, (void**)&layout2);
5615 IDWriteTextLayout_Release(layout);
5616
5617 if (hr != S_OK) {
5618 win_skip("GetFontFallback() is not supported.\n");
5619 IDWriteFactory_Release(factory);
5620 return;
5621 }
5622
5623 if (0) /* crashes on native */
5624 hr = IDWriteTextLayout2_GetFontFallback(layout2, NULL);
5625
5626 fallback = (void*)0xdeadbeef;
5627 hr = IDWriteTextLayout2_GetFontFallback(layout2, &fallback);
5628 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5629 ok(fallback == NULL, "got %p\n", fallback);
5630
5631 hr = IDWriteTextLayout2_QueryInterface(layout2, &IID_IDWriteTextFormat1, (void**)&format1);
5632 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5633
5634 fallback = (void*)0xdeadbeef;
5635 hr = IDWriteTextFormat1_GetFontFallback(format1, &fallback);
5636 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5637 ok(fallback == NULL, "got %p\n", fallback);
5638
5639 hr = IDWriteFactory_QueryInterface(factory, &IID_IDWriteFactory2, (void**)&factory2);
5640 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5641
5642 fallback = NULL;
5643 hr = IDWriteFactory2_GetSystemFontFallback(factory2, &fallback);
5644 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5645 ok(fallback != NULL, "got %p\n", fallback);
5646
5647 hr = IDWriteTextFormat1_SetFontFallback(format1, fallback);
5648 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5649
5650 fallback2 = (void*)0xdeadbeef;
5651 hr = IDWriteTextLayout2_GetFontFallback(layout2, &fallback2);
5652 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5653 ok(fallback2 == fallback, "got %p\n", fallback2);
5654
5655 hr = IDWriteTextLayout2_SetFontFallback(layout2, NULL);
5656 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5657
5658 fallback2 = (void*)0xdeadbeef;
5659 hr = IDWriteTextFormat1_GetFontFallback(format1, &fallback2);
5660 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5661 ok(fallback2 == NULL, "got %p\n", fallback2);
5662
5663 if (SUCCEEDED(IDWriteFontFallback_QueryInterface(fallback, &IID_IDWriteFontFallback1, (void **)&fallback1)))
5664 {
5665 IDWriteFontFallback1_Release(fallback1);
5666 }
5667 else
5668 win_skip("IDWriteFontFallback1 is not supported.\n");
5669
5670 IDWriteFontFallback_Release(fallback);
5671 IDWriteTextFormat1_Release(format1);
5672 IDWriteTextLayout2_Release(layout2);
5673 IDWriteFactory_Release(factory);
5674}
5675
5676static void test_SetTypography(void)
5677{
5678 IDWriteTypography *typography, *typography2;
5680 IDWriteTextLayout *layout;
5683 HRESULT hr;
5684
5686
5687 hr = IDWriteFactory_CreateTextFormat(factory, L"Tahoma", NULL, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL,
5688 DWRITE_FONT_STRETCH_NORMAL, 10.0f, L"en-us", &format);
5689 ok(hr == S_OK, "Failed to create text format, hr %#lx.\n", hr);
5690
5691 hr = IDWriteFactory_CreateTextLayout(factory, L"afib", 4, format, 1000.0f, 1000.0f, &layout);
5692 ok(hr == S_OK, "Failed to create text layout, hr %#lx.\n", hr);
5693 IDWriteTextFormat_Release(format);
5694
5695 hr = IDWriteFactory_CreateTypography(factory, &typography);
5696 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5697
5698 EXPECT_REF(typography, 1);
5699 range.startPosition = 0;
5700 range.length = 2;
5701 hr = IDWriteTextLayout_SetTypography(layout, typography, range);
5702 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5703 EXPECT_REF(typography, 2);
5704
5705 hr = IDWriteTextLayout_GetTypography(layout, 0, &typography2, NULL);
5706 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5707 ok(typography2 == typography, "got %p, expected %p\n", typography2, typography);
5708 IDWriteTypography_Release(typography2);
5709 IDWriteTypography_Release(typography);
5710
5711 hr = IDWriteFactory_CreateTypography(factory, &typography2);
5712 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5713
5714 range.startPosition = 0;
5715 range.length = 1;
5716 hr = IDWriteTextLayout_SetTypography(layout, typography2, range);
5717 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5718 EXPECT_REF(typography2, 2);
5719 IDWriteTypography_Release(typography2);
5720
5721 hr = IDWriteTextLayout_GetTypography(layout, 0, &typography, &range);
5722 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5723 ok(range.length == 1, "got %u\n", range.length);
5724
5725 IDWriteTypography_Release(typography);
5726
5727 IDWriteTextLayout_Release(layout);
5728 IDWriteFactory_Release(factory);
5729}
5730
5732{
5733 IDWriteTextLayout2 *layout2;
5734 IDWriteTextFormat1 *format1;
5735 IDWriteTextLayout *layout;
5738 HRESULT hr;
5739 BOOL ret;
5740
5742
5743 hr = IDWriteFactory_CreateTextFormat(factory, L"Tahoma", NULL, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL,
5744 DWRITE_FONT_STRETCH_NORMAL, 10.0f, L"en-us", &format);
5745 ok(hr == S_OK, "Failed to create text format, hr %#lx.\n", hr);
5746
5747 hr = IDWriteTextFormat_QueryInterface(format, &IID_IDWriteTextFormat1, (void**)&format1);
5748 IDWriteTextFormat_Release(format);
5749 if (hr != S_OK) {
5750 win_skip("SetLastLineWrapping() is not supported\n");
5751 IDWriteFactory_Release(factory);
5752 return;
5753 }
5754
5755 ret = IDWriteTextFormat1_GetLastLineWrapping(format1);
5756 ok(ret, "got %d\n", ret);
5757
5758 hr = IDWriteTextFormat1_SetLastLineWrapping(format1, FALSE);
5759 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5760
5761 hr = IDWriteFactory_CreateTextLayout(factory, L"a", 1, (IDWriteTextFormat *)format1, 1000.0f, 1000.0f, &layout);
5762 ok(hr == S_OK, "Failed to create text layout, hr %#lx.\n", hr);
5763
5764 hr = IDWriteTextLayout_QueryInterface(layout, &IID_IDWriteTextLayout2, (void**)&layout2);
5765 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5766 IDWriteTextLayout_Release(layout);
5767
5768 ret = IDWriteTextLayout2_GetLastLineWrapping(layout2);
5769 ok(!ret, "got %d\n", ret);
5770
5771 hr = IDWriteTextLayout2_SetLastLineWrapping(layout2, TRUE);
5772 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5773
5774 IDWriteTextLayout2_Release(layout2);
5775 IDWriteTextFormat1_Release(format1);
5776 IDWriteFactory_Release(factory);
5777}
5778
5780{
5782 IDWriteTextLayout2 *layout2;
5783 IDWriteTextFormat1 *format1;
5784 IDWriteTextLayout *layout;
5787 HRESULT hr;
5788
5790
5791 hr = IDWriteFactory_CreateTextFormat(factory, L"Tahoma", NULL, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL,
5792 DWRITE_FONT_STRETCH_NORMAL, 10.0f, L"en-us", &format);
5793 ok(hr == S_OK, "Failed to create text format, hr %#lx.\n", hr);
5794
5795 hr = IDWriteTextFormat_QueryInterface(format, &IID_IDWriteTextFormat1, (void**)&format1);
5796 IDWriteTextFormat_Release(format);
5797 if (hr != S_OK) {
5798 win_skip("SetOpticalAlignment() is not supported\n");
5799 IDWriteFactory_Release(factory);
5800 return;
5801 }
5802
5803 alignment = IDWriteTextFormat1_GetOpticalAlignment(format1);
5805
5806 hr = IDWriteFactory_CreateTextLayout(factory, L"a", 1, (IDWriteTextFormat *)format1, 1000.0f, 1000.0f, &layout);
5807 ok(hr == S_OK, "Failed to create text layout, hr %#lx.\n", hr);
5808
5809 hr = IDWriteTextLayout_QueryInterface(layout, &IID_IDWriteTextLayout2, (void**)&layout2);
5810 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5811 IDWriteTextLayout_Release(layout);
5812 IDWriteTextFormat1_Release(format1);
5813
5814 alignment = IDWriteTextLayout2_GetOpticalAlignment(layout2);
5816
5817 hr = IDWriteTextLayout2_QueryInterface(layout2, &IID_IDWriteTextFormat1, (void**)&format1);
5818 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5819
5820 alignment = IDWriteTextFormat1_GetOpticalAlignment(format1);
5822
5823 hr = IDWriteTextLayout2_SetOpticalAlignment(layout2, DWRITE_OPTICAL_ALIGNMENT_NO_SIDE_BEARINGS);
5824 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5825
5826 hr = IDWriteTextLayout2_SetOpticalAlignment(layout2, DWRITE_OPTICAL_ALIGNMENT_NO_SIDE_BEARINGS+1);
5827 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
5828
5829 alignment = IDWriteTextFormat1_GetOpticalAlignment(format1);
5831
5832 hr = IDWriteTextFormat1_SetOpticalAlignment(format1, DWRITE_OPTICAL_ALIGNMENT_NONE);
5833 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5834
5835 hr = IDWriteTextFormat1_SetOpticalAlignment(format1, DWRITE_OPTICAL_ALIGNMENT_NO_SIDE_BEARINGS+1);
5836 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
5837
5838 alignment = IDWriteTextLayout2_GetOpticalAlignment(layout2);
5840
5841 IDWriteTextLayout2_Release(layout2);
5842 IDWriteTextFormat1_Release(format1);
5843 IDWriteFactory_Release(factory);
5844}
5845
5846static const struct drawcall_entry drawunderline_seq[] = {
5847 { DRAW_GLYPHRUN, {'a','e',0x0300,0}, {'e','n','-','u','s',0}, 2 }, /* reported runs can't mix different underline values */
5848 { DRAW_GLYPHRUN, {'d',0}, {'e','n','-','u','s',0}, 1 },
5849 { DRAW_UNDERLINE, {0}, {'e','n','-','u','s',0} },
5850 { DRAW_LAST_KIND }
5851};
5852
5853static const struct drawcall_entry drawunderline2_seq[] = {
5854 { DRAW_GLYPHRUN, {'a',0}, {'e','n','-','u','s',0}, 1 },
5855 { DRAW_GLYPHRUN, {'e',0}, {'e','n','-','u','s',0}, 1 },
5856 { DRAW_UNDERLINE, {0}, {'e','n','-','u','s',0} },
5857 { DRAW_LAST_KIND }
5858};
5859
5860static const struct drawcall_entry drawunderline3_seq[] = {
5861 { DRAW_GLYPHRUN, {'a',0}, {'e','n','-','c','a',0}, 1 },
5862 { DRAW_GLYPHRUN, {'e',0}, {'e','n','-','u','s',0}, 1 },
5863 { DRAW_UNDERLINE, {0}, {'e','n','-','c','a',0} },
5864 { DRAW_UNDERLINE, {0}, {'e','n','-','u','s',0} },
5865 { DRAW_LAST_KIND }
5866};
5867
5868static const struct drawcall_entry drawunderline4_seq[] = {
5869 { DRAW_GLYPHRUN, {'a',0}, {'e','n','-','u','s',0}, 1 },
5870 { DRAW_GLYPHRUN, {'e',0}, {'e','n','-','u','s',0}, 1 },
5871 { DRAW_UNDERLINE, {0}, {'e','n','-','u','s',0} },
5873 { DRAW_LAST_KIND }
5874};
5875
5876static void test_SetUnderline(void)
5877{
5878 static const WCHAR strW[] = {'a','e',0x0300,'d',0}; /* accent grave */
5879 IDWriteFontCollection *syscollection;
5880 DWRITE_CLUSTER_METRICS clusters[4];
5882 IDWriteTextLayout *layout;
5885 UINT32 count, i;
5886 HRESULT hr;
5887
5889
5890 hr = IDWriteFactory_CreateTextFormat(factory, L"Tahoma", NULL, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL,
5891 DWRITE_FONT_STRETCH_NORMAL, 10.0f, L"en-us", &format);
5892 ok(hr == S_OK, "Failed to create text format, hr %#lx.\n", hr);
5893
5894 hr = IDWriteFactory_CreateTextLayout(factory, strW, 4, format, 1000.0, 1000.0, &layout);
5895 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5896
5897 count = 0;
5898 hr = IDWriteTextLayout_GetClusterMetrics(layout, clusters, ARRAY_SIZE(clusters), &count);
5899 ok(hr == S_OK, "Failed to get cluster metrics, hr %#lx.\n", hr);
5900 todo_wine
5901 ok(count == 3, "Unexpected cluster count %u.\n", count);
5902
5903 range.startPosition = 0;
5904 range.length = 2;
5905 hr = IDWriteTextLayout_SetUnderline(layout, TRUE, range);
5906 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5907
5908 count = 0;
5909 hr = IDWriteTextLayout_GetClusterMetrics(layout, clusters, ARRAY_SIZE(clusters), &count);
5910 ok(hr == S_OK, "Failed to get cluster metrics, hr %#lx.\n", hr);
5911 todo_wine
5912 ok(count == 3, "Unexpected cluster count %u.\n", count);
5913
5915 hr = IDWriteTextLayout_Draw(layout, NULL, &testrenderer, 0.0, 0.0);
5916 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5917 ok_sequence(sequences, RENDERER_ID, drawunderline_seq, "draw underline test", TRUE);
5918
5919 IDWriteTextLayout_Release(layout);
5920
5921 /* 2 characters, same font, significantly different font size. Set underline for both, see how many
5922 underline drawing calls is there. */
5923 hr = IDWriteFactory_CreateTextLayout(factory, strW, 2, format, 1000.0f, 1000.0f, &layout);
5924 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5925
5926 range.startPosition = 0;
5927 range.length = 2;
5928 hr = IDWriteTextLayout_SetUnderline(layout, TRUE, range);
5929 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5930
5931 range.startPosition = 0;
5932 range.length = 1;
5933 hr = IDWriteTextLayout_SetFontSize(layout, 100.0f, range);
5934 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5935
5937 hr = IDWriteTextLayout_Draw(layout, NULL, &testrenderer, 0.0f, 0.0f);
5938 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5939 ok_sequence(sequences, RENDERER_ID, drawunderline2_seq, "draw underline test 2", FALSE);
5940
5941 /* now set different locale for second char, draw again */
5942 range.startPosition = 0;
5943 range.length = 1;
5944 hr = IDWriteTextLayout_SetLocaleName(layout, L"en-CA", range);
5945 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5946
5948 hr = IDWriteTextLayout_Draw(layout, NULL, &testrenderer, 0.0f, 0.0f);
5949 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5950 ok_sequence(sequences, RENDERER_ID, drawunderline3_seq, "draw underline test 2", FALSE);
5951
5952 IDWriteTextLayout_Release(layout);
5953
5954 /* 2 characters, same font properties, first with strikethrough, both underlined */
5955 hr = IDWriteFactory_CreateTextLayout(factory, strW, 2, format, 1000.0f, 1000.0f, &layout);
5956 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5957
5958 range.startPosition = 0;
5959 range.length = 1;
5960 hr = IDWriteTextLayout_SetStrikethrough(layout, TRUE, range);
5961 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5962
5963 range.startPosition = 0;
5964 range.length = 2;
5965 hr = IDWriteTextLayout_SetUnderline(layout, TRUE, range);
5966 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5967
5969 hr = IDWriteTextLayout_Draw(layout, NULL, &testrenderer, 0.0f, 0.0f);
5970 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5971 ok_sequence(sequences, RENDERER_ID, drawunderline4_seq, "draw underline test 4", FALSE);
5972
5973 IDWriteTextLayout_Release(layout);
5974
5975 IDWriteTextFormat_Release(format);
5976
5977 /* Test runHeight value with all available fonts */
5978 hr = IDWriteFactory_GetSystemFontCollection(factory, &syscollection, FALSE);
5979 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5980 count = IDWriteFontCollection_GetFontFamilyCount(syscollection);
5981
5982 for (i = 0; i < count; ++i)
5983 {
5984 DWRITE_FONT_METRICS fontmetrics;
5986 struct renderer_context ctxt;
5987 IDWriteFontFamily *family;
5988 IDWriteFontFace *fontface;
5989 WCHAR nameW[256], str[1];
5991 UINT32 codepoint;
5992 UINT16 glyph;
5993 BOOL exists;
5994
5995 format = NULL;
5996 layout = NULL;
5997
5998 hr = IDWriteFontCollection_GetFontFamily(syscollection, i, &family);
5999 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6000
6001 hr = IDWriteFontFamily_GetFirstMatchingFont(family, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STRETCH_NORMAL,
6003 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6004
6005 hr = IDWriteFont_CreateFontFace(font, &fontface);
6006 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6007
6008 hr = IDWriteFontFamily_GetFamilyNames(family, &names);
6009 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6010
6011 if (!(exists = get_enus_string(names, nameW, ARRAY_SIZE(nameW)))) {
6012 IDWriteLocalFontFileLoader *localloader;
6015 const void *key;
6016 UINT32 keysize;
6017 UINT32 count;
6018
6019 count = 1;
6020 hr = IDWriteFontFace_GetFiles(fontface, &count, &file);
6021 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6022
6023 hr = IDWriteFontFile_GetLoader(file, &loader);
6024 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6025
6026 hr = IDWriteFontFileLoader_QueryInterface(loader, &IID_IDWriteLocalFontFileLoader, (void**)&localloader);
6027 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6028 IDWriteFontFileLoader_Release(loader);
6029
6030 hr = IDWriteFontFile_GetReferenceKey(file, &key, &keysize);
6031 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6032
6033 hr = IDWriteLocalFontFileLoader_GetFilePathFromKey(localloader, key, keysize, nameW, ARRAY_SIZE(nameW));
6034 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6035
6036 skip("Failed to get English family name, font file %s\n", wine_dbgstr_w(nameW));
6037
6038 IDWriteLocalFontFileLoader_Release(localloader);
6039 IDWriteFontFile_Release(file);
6040 }
6041
6042 IDWriteLocalizedStrings_Release(names);
6043 IDWriteFont_Release(font);
6044
6045 if (!exists)
6046 goto cleanup;
6047
6048 IDWriteFontFace_GetMetrics(fontface, &fontmetrics);
6049 hr = IDWriteFactory_CreateTextFormat(factory, nameW, NULL, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL,
6050 DWRITE_FONT_STRETCH_NORMAL, fontmetrics.designUnitsPerEm, L"en-us", &format);
6051 ok(hr == S_OK, "Failed to create text format, hr %#lx.\n", hr);
6052
6053 /* Look for first supported character to avoid triggering fallback path. With fallback it's harder to test
6054 DrawUnderline() metrics, because actual resolved fontface is not passed to it. Grabbing fontface instance
6055 from corresponding DrawGlyphRun() call is not straightforward. */
6056 for (codepoint = ' '; codepoint < 0xffff; ++codepoint)
6057 {
6058 glyph = 0;
6059 hr = IDWriteFontFace_GetGlyphIndices(fontface, &codepoint, 1, &glyph);
6060 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6061 if (glyph)
6062 break;
6063 }
6064
6065 if (!glyph)
6066 {
6067 skip("Couldn't find reasonable test string.\n");
6068 goto cleanup;
6069 }
6070
6071 str[0] = codepoint;
6072 hr = IDWriteFactory_CreateTextLayout(factory, str, 1, format, 30000.0f, 100.0f, &layout);
6073 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6074
6075 range.startPosition = 0;
6076 range.length = 2;
6077 hr = IDWriteTextLayout_SetUnderline(layout, TRUE, range);
6078 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6079
6080 memset(&ctxt, 0, sizeof(ctxt));
6081 ctxt.format = format;
6082 ctxt.familyW = nameW;
6083 hr = IDWriteTextLayout_Draw(layout, &ctxt, &testrenderer, 0.0f, 0.0f);
6084 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6085
6086 cleanup:
6087 if (layout)
6088 IDWriteTextLayout_Release(layout);
6089 if (format)
6090 IDWriteTextFormat_Release(format);
6091 IDWriteFontFace_Release(fontface);
6092 IDWriteFontFamily_Release(family);
6093 }
6094 IDWriteFontCollection_Release(syscollection);
6095
6096 IDWriteFactory_Release(factory);
6097}
6098
6099static void test_InvalidateLayout(void)
6100{
6101 IDWriteTextLayout3 *layout3;
6102 IDWriteTextLayout *layout;
6105 HRESULT hr;
6106
6108
6109 hr = IDWriteFactory_CreateTextFormat(factory, L"Tahoma", NULL, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL,
6110 DWRITE_FONT_STRETCH_NORMAL, 10.0f, L"en-us", &format);
6111 ok(hr == S_OK, "Failed to create text format, hr %#lx.\n", hr);
6112
6113 hr = IDWriteFactory_CreateTextLayout(factory, L"a", 1, format, 1000.0f, 1000.0f, &layout);
6114 ok(hr == S_OK, "Failed to create text layout, hr %#lx.\n", hr);
6115
6116 hr = IDWriteTextLayout_QueryInterface(layout, &IID_IDWriteTextLayout3, (void**)&layout3);
6117 if (hr == S_OK) {
6118 IDWriteTextFormat1 *format1;
6119 IDWriteTextFormat2 *format2;
6120
6121 hr = IDWriteTextFormat_QueryInterface(format, &IID_IDWriteTextFormat2, (void**)&format2);
6122 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6123 IDWriteTextFormat2_Release(format2);
6124
6125 hr = IDWriteTextLayout_QueryInterface(layout, &IID_IDWriteTextFormat2, (void**)&format2);
6126 ok(hr == S_OK || broken(hr == E_NOINTERFACE), "Unexpected hr %#lx.\n", hr);
6127 if (hr == S_OK) {
6128 ok(format != (IDWriteTextFormat *)format2, "Unexpected interface pointer.\n");
6129 IDWriteTextFormat2_Release(format2);
6130 }
6131
6132 hr = IDWriteTextLayout_QueryInterface(layout, &IID_IDWriteTextFormat1, (void**)&format1);
6133 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6134
6135 hr = IDWriteTextFormat1_QueryInterface(format1, &IID_IDWriteTextFormat2, (void**)&format2);
6136 ok(hr == S_OK || broken(hr == E_NOINTERFACE), "Unexpected hr %#lx.\n", hr);
6137 if (hr == S_OK)
6138 IDWriteTextFormat2_Release(format2);
6139 IDWriteTextFormat1_Release(format1);
6140
6141 hr = IDWriteTextLayout3_QueryInterface(layout3, &IID_IDWriteTextFormat2, (void**)&format2);
6142 ok(hr == S_OK || broken(hr == E_NOINTERFACE), "Unexpected hr %#lx.\n", hr);
6143 if (hr == S_OK)
6144 IDWriteTextFormat2_Release(format2);
6145
6146 hr = IDWriteTextLayout3_InvalidateLayout(layout3);
6147 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6148 IDWriteTextLayout3_Release(layout3);
6149 }
6150 else
6151 win_skip("IDWriteTextLayout3::InvalidateLayout() is not supported.\n");
6152
6153 IDWriteTextLayout_Release(layout);
6154 IDWriteTextFormat_Release(format);
6155 IDWriteFactory_Release(factory);
6156}
6157
6158static void test_line_spacing(void)
6159{
6160 IDWriteTextFormat2 *format2;
6161 IDWriteTextLayout *layout;
6164 HRESULT hr;
6165
6167
6168 hr = IDWriteFactory_CreateTextFormat(factory, L"Tahoma", NULL, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL,
6169 DWRITE_FONT_STRETCH_NORMAL, 10.0f, L"en-us", &format);
6170 ok(hr == S_OK, "Failed to create text format, hr %#lx.\n", hr);
6171
6172 hr = IDWriteTextFormat_SetLineSpacing(format, DWRITE_LINE_SPACING_METHOD_DEFAULT, 0.0f, 0.0f);
6173 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6174
6175 hr = IDWriteTextFormat_SetLineSpacing(format, DWRITE_LINE_SPACING_METHOD_DEFAULT, 0.0f, -10.0f);
6176 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6177
6178 hr = IDWriteTextFormat_SetLineSpacing(format, DWRITE_LINE_SPACING_METHOD_DEFAULT, -10.0f, 0.0f);
6179 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
6180
6181 hr = IDWriteTextFormat_SetLineSpacing(format, DWRITE_LINE_SPACING_METHOD_PROPORTIONAL+1, 0.0f, 0.0f);
6182 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
6183
6184 hr = IDWriteFactory_CreateTextLayout(factory, L"a", 1, format, 1000.0f, 1000.0f, &layout);
6185 ok(hr == S_OK, "Failed to create text layout, hr %#lx.\n", hr);
6186
6187 hr = IDWriteTextLayout_SetLineSpacing(layout, DWRITE_LINE_SPACING_METHOD_DEFAULT, 0.0f, 0.0f);
6188 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6189
6190 hr = IDWriteTextLayout_SetLineSpacing(layout, DWRITE_LINE_SPACING_METHOD_DEFAULT, 0.0f, -10.0f);
6191 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6192
6193 hr = IDWriteTextLayout_SetLineSpacing(layout, DWRITE_LINE_SPACING_METHOD_DEFAULT, -10.0f, 0.0f);
6194 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
6195
6196 hr = IDWriteTextLayout_SetLineSpacing(layout, DWRITE_LINE_SPACING_METHOD_PROPORTIONAL+1, 0.0f, 0.0f);
6197 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
6198
6199 if (IDWriteTextFormat_QueryInterface(format, &IID_IDWriteTextFormat2, (void**)&format2) == S_OK) {
6200 DWRITE_LINE_SPACING spacing;
6201
6202 hr = IDWriteTextFormat2_GetLineSpacing(format2, &spacing);
6203 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6204
6205 ok(spacing.method == DWRITE_LINE_SPACING_METHOD_DEFAULT, "got method %d\n", spacing.method);
6206 ok(spacing.height == 0.0f, "got %f\n", spacing.height);
6207 ok(spacing.baseline == -10.0f, "got %f\n", spacing.baseline);
6208 ok(spacing.leadingBefore == 0.0f, "got %f\n", spacing.leadingBefore);
6210
6211 spacing.leadingBefore = -1.0f;
6212
6213 hr = IDWriteTextFormat2_SetLineSpacing(format2, &spacing);
6214 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
6215
6216 spacing.leadingBefore = 1.1f;
6217
6218 hr = IDWriteTextFormat2_SetLineSpacing(format2, &spacing);
6219 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
6220
6221 spacing.leadingBefore = 1.0f;
6222
6223 hr = IDWriteTextFormat2_SetLineSpacing(format2, &spacing);
6224 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6225
6227 hr = IDWriteTextFormat2_SetLineSpacing(format2, &spacing);
6228 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
6229
6232 hr = IDWriteTextFormat2_SetLineSpacing(format2, &spacing);
6233 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6234
6235 hr = IDWriteTextFormat2_GetLineSpacing(format2, &spacing);
6236 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6237 ok(spacing.fontLineGapUsage == DWRITE_FONT_LINE_GAP_USAGE_ENABLED + 1, "got %d\n", spacing.fontLineGapUsage);
6238
6239 IDWriteTextFormat2_Release(format2);
6240 }
6241
6242 IDWriteTextLayout_Release(layout);
6243 IDWriteTextFormat_Release(format);
6244 IDWriteFactory_Release(factory);
6245}
6246
6248{
6249 static const struct overhangs_test
6250 {
6251 FLOAT uniform_baseline;
6253 DWRITE_OVERHANG_METRICS overhang_metrics;
6255 } overhangs_tests[] = {
6256 { 16.0f, { 10.0f, 50.0f, 20.0f }, { 1.0f, 2.0f, 3.0f, 4.0f }, { 1.0f, 6.0f, 3.0f, 0.0f } },
6257 { 15.0f, { 10.0f, 50.0f, 20.0f }, { 1.0f, 2.0f, 3.0f, 4.0f }, { 1.0f, 7.0f, 3.0f, -1.0f } },
6258 { 16.0f, { 10.0f, 50.0f, 20.0f }, { -1.0f, 0.0f, -3.0f, 4.0f }, { -1.0f, 4.0f, -3.0f, 0.0f } },
6259 { 15.0f, { 10.0f, 50.0f, 20.0f }, { -1.0f, 10.0f, 3.0f, -4.0f }, { -1.0f, 15.0f, 3.0f, -9.0f } },
6260 };
6261 struct test_inline_obj *inline_obj;
6264 IDWriteTextLayout *layout;
6265 HRESULT hr;
6266 UINT32 i;
6267
6269 ok(!!inline_obj, "Failed to create test inline object.\n");
6270
6272
6273 hr = IDWriteFactory_CreateTextFormat(factory, L"Tahoma", NULL, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL,
6274 DWRITE_FONT_STRETCH_NORMAL, 100.0f, L"en-us", &format);
6275 ok(hr == S_OK, "Failed to create text format, hr %#lx.\n", hr);
6276
6277 hr = IDWriteFactory_CreateTextLayout(factory, L"A", 1, format, 1000.0f, 1000.0f, &layout);
6278 ok(hr == S_OK, "Failed to create text layout, hr %lx.\n", hr);
6279
6280 for (i = 0; i < ARRAY_SIZE(overhangs_tests); i++) {
6281 const struct overhangs_test *test = &overhangs_tests[i];
6282 DWRITE_OVERHANG_METRICS overhang_metrics;
6283 DWRITE_TEXT_RANGE range = { 0, 1 };
6285
6286 inline_obj->metrics = test->metrics;
6287 inline_obj->overhangs = test->overhang_metrics;
6288
6289 hr = IDWriteTextLayout_SetLineSpacing(layout, DWRITE_LINE_SPACING_METHOD_UNIFORM, test->metrics.height * 2.0f,
6290 test->uniform_baseline);
6291 ok(hr == S_OK, "Failed to set line spacing, hr %#lx.\n", hr);
6292
6293 hr = IDWriteTextLayout_SetInlineObject(layout, NULL, range);
6294 ok(hr == S_OK, "Failed to reset inline object, hr %#lx.\n", hr);
6295
6296 hr = IDWriteTextLayout_SetInlineObject(layout, &inline_obj->IDWriteInlineObject_iface, range);
6297 ok(hr == S_OK, "Failed to set inline object, hr %#lx.\n", hr);
6298
6299 hr = IDWriteTextLayout_GetMetrics(layout, &metrics);
6300 ok(hr == S_OK, "Failed to get layout metrics, hr %#lx.\n", hr);
6301
6302 ok(metrics.width == test->metrics.width, "%u: unexpected formatted width.\n", i);
6303 ok(metrics.height == test->metrics.height * 2.0f, "%u: unexpected formatted height.\n", i);
6304
6305 hr = IDWriteTextLayout_SetMaxWidth(layout, metrics.width);
6306 hr = IDWriteTextLayout_SetMaxHeight(layout, test->metrics.height);
6307
6308 hr = IDWriteTextLayout_GetOverhangMetrics(layout, &overhang_metrics);
6309 ok(hr == S_OK, "Failed to get overhang metrics, hr %#lx.\n", hr);
6310
6311 ok(!memcmp(&overhang_metrics, &test->expected, sizeof(overhang_metrics)),
6312 "%u: unexpected overhang metrics (%f, %f, %f, %f).\n", i, overhang_metrics.left, overhang_metrics.top,
6313 overhang_metrics.right, overhang_metrics.bottom);
6314 }
6315
6316 IDWriteInlineObject_Release(&inline_obj->IDWriteInlineObject_iface);
6317 IDWriteTextLayout_Release(layout);
6318 IDWriteTextFormat_Release(format);
6319 IDWriteFactory_Release(factory);
6320}
6321
6322static void test_tab_stops(void)
6323{
6324 DWRITE_CLUSTER_METRICS clusters[4];
6325 IDWriteTextLayout *layout;
6329 FLOAT tabstop, size;
6330 UINT count;
6331 HRESULT hr;
6332
6334
6335 /* Default tab stop value. */
6336 for (size = 1.0f; size < 25.0f; size += 5.0f)
6337 {
6338 hr = IDWriteFactory_CreateTextFormat(factory, L"Tahoma", NULL, DWRITE_FONT_WEIGHT_NORMAL,
6340 ok(hr == S_OK, "Failed to create text format, hr %#lx.\n", hr);
6341
6342 tabstop = IDWriteTextFormat_GetIncrementalTabStop(format);
6343 ok(tabstop == 4.0f * size, "Unexpected tab stop %f.\n", tabstop);
6344
6345 IDWriteTextFormat_Release(format);
6346 }
6347
6348 hr = IDWriteFactory_CreateTextFormat(factory, L"Tahoma", NULL, DWRITE_FONT_WEIGHT_NORMAL,
6350 ok(hr == S_OK, "Failed to create text format, hr %#lx.\n", hr);
6351
6352 hr = IDWriteTextFormat_SetIncrementalTabStop(format, 0.0f);
6353 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
6354
6355 hr = IDWriteTextFormat_SetIncrementalTabStop(format, -10.0f);
6356 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
6357
6358 tabstop = IDWriteTextFormat_GetIncrementalTabStop(format);
6359 ok(tabstop == 40.0f, "Unexpected tab stop %f.\n", tabstop);
6360
6361 hr = IDWriteTextFormat_SetIncrementalTabStop(format, 100.0f);
6362 ok(hr == S_OK, "Failed to set tab stop value, hr %#lx.\n", hr);
6363
6364 tabstop = IDWriteTextFormat_GetIncrementalTabStop(format);
6365 ok(tabstop == 100.0f, "Unexpected tab stop %f.\n", tabstop);
6366
6367 hr = IDWriteFactory_CreateTextLayout(factory, L"\ta\tb", 4, format, 1000.0f, 1000.0f, &layout);
6368 ok(hr == S_OK, "Failed to create text layout, hr %lx.\n", hr);
6369
6370 hr = IDWriteTextLayout_GetClusterMetrics(layout, clusters, 4, &count);
6371 ok(hr == S_OK, "Failed to get cluster metrics, hr %#lx.\n", hr);
6372 ok(clusters[0].isWhitespace, "Unexpected isWhitespace.\n");
6373 ok(!clusters[1].isWhitespace, "Unexpected isWhitespace.\n");
6374 ok(clusters[2].isWhitespace, "Unexpected isWhitespace.\n");
6375 ok(!clusters[3].isWhitespace, "Unexpected isWhitespace.\n");
6376todo_wine {
6377 ok(clusters[0].width == tabstop, "Unexpected tab width.\n");
6378 ok(clusters[1].width + clusters[2].width == tabstop, "Unexpected tab width.\n");
6379}
6380 range.startPosition = 0;
6381 range.length = ~0u;
6382 hr = IDWriteTextLayout_SetFontSize(layout, 20.0f, range);
6383 ok(hr == S_OK, "Failed to set font size, hr %#lx.\n", hr);
6384
6385 tabstop = IDWriteTextLayout_GetIncrementalTabStop(layout);
6386 ok(tabstop == 100.0f, "Unexpected tab stop %f.\n", tabstop);
6387
6388 hr = IDWriteTextLayout_GetClusterMetrics(layout, clusters, 4, &count);
6389 ok(hr == S_OK, "Failed to get cluster metrics, hr %#lx.\n", hr);
6390 ok(clusters[0].isWhitespace, "Unexpected isWhitespace.\n");
6391 ok(!clusters[1].isWhitespace, "Unexpected isWhitespace.\n");
6392 ok(clusters[2].isWhitespace, "Unexpected isWhitespace.\n");
6393 ok(!clusters[3].isWhitespace, "Unexpected isWhitespace.\n");
6394todo_wine {
6395 ok(clusters[0].width == tabstop, "Unexpected tab width.\n");
6396 ok(clusters[1].width + clusters[2].width == tabstop, "Unexpected tab width.\n");
6397}
6398 IDWriteTextLayout_Release(layout);
6399
6400 IDWriteTextFormat_Release(format);
6401
6402 IDWriteFactory_Release(factory);
6403}
6404
6406{
6408 IDWriteTextLayout4 *layout4 = NULL;
6409 IDWriteTextFormat3 *format3;
6410 IDWriteTextLayout *layout;
6413 HRESULT hr;
6414
6416
6417 hr = IDWriteFactory_CreateTextFormat(factory, L"Tahoma", NULL, DWRITE_FONT_WEIGHT_NORMAL,
6419 ok(hr == S_OK, "Failed to create text format, hr %#lx.\n", hr);
6420
6421 hr = IDWriteFactory_CreateTextLayout(factory, L"a", 1, format, 1000.0f, 1000.0f, &layout);
6422 ok(hr == S_OK, "Failed to create text layout, hr %lx.\n", hr);
6423
6424 IDWriteTextLayout_QueryInterface(layout, &IID_IDWriteTextLayout4, (void **)&layout4);
6425
6426 IDWriteTextLayout_Release(layout);
6427
6428 if (!layout4)
6429 {
6430 win_skip("Text layout does not support variable fonts.\n");
6431 IDWriteFactory_Release(factory);
6432 IDWriteTextFormat_Release(format);
6433 return;
6434 }
6435
6436 hr = IDWriteTextFormat_QueryInterface(format, &IID_IDWriteTextFormat3, (void **)&format3);
6437 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6438
6439 axes = IDWriteTextFormat3_GetAutomaticFontAxes(format3);
6440 ok(axes == DWRITE_AUTOMATIC_FONT_AXES_NONE, "Unexpected automatic axes %u.\n", axes);
6441
6442 hr = IDWriteTextFormat3_SetAutomaticFontAxes(format3, DWRITE_AUTOMATIC_FONT_AXES_OPTICAL_SIZE);
6443 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6444
6445 hr = IDWriteTextFormat3_SetAutomaticFontAxes(format3, DWRITE_AUTOMATIC_FONT_AXES_OPTICAL_SIZE + 1);
6446 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6447
6448 IDWriteTextFormat3_Release(format3);
6449
6450 axes = IDWriteTextLayout4_GetAutomaticFontAxes(layout4);
6451 ok(axes == DWRITE_AUTOMATIC_FONT_AXES_NONE, "Unexpected automatic axes %u.\n", axes);
6452
6453 hr = IDWriteTextLayout4_SetAutomaticFontAxes(layout4, DWRITE_AUTOMATIC_FONT_AXES_OPTICAL_SIZE + 1);
6454 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
6455
6456 hr = IDWriteTextLayout4_SetAutomaticFontAxes(layout4, DWRITE_AUTOMATIC_FONT_AXES_OPTICAL_SIZE);
6457 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6458
6459 IDWriteTextLayout4_Release(layout4);
6460
6461 /* Out of range values allow for formats, but not for layouts. */
6462 hr = IDWriteFactory_CreateTextLayout(factory, L"a", 1, format, 1000.0f, 1000.0f, &layout);
6463 ok(hr == S_OK, "Failed to create text layout, hr %lx.\n", hr);
6464
6465 hr = IDWriteTextLayout_QueryInterface(layout, &IID_IDWriteTextLayout4, (void **)&layout4);
6466 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6467
6468 axes = IDWriteTextLayout4_GetAutomaticFontAxes(layout4);
6469 ok(axes == DWRITE_AUTOMATIC_FONT_AXES_OPTICAL_SIZE + 1, "Unexpected automatic axes %u.\n", axes);
6470
6471 hr = IDWriteTextLayout4_QueryInterface(layout4, &IID_IDWriteTextFormat3, (void **)&format3);
6472 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6473
6474 axes = IDWriteTextFormat3_GetAutomaticFontAxes(format3);
6475 ok(axes == DWRITE_AUTOMATIC_FONT_AXES_OPTICAL_SIZE + 1, "Unexpected automatic axes %u.\n", axes);
6476
6477 hr = IDWriteTextLayout4_SetAutomaticFontAxes(layout4, DWRITE_AUTOMATIC_FONT_AXES_OPTICAL_SIZE);
6478 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6479
6480 axes = IDWriteTextFormat3_GetAutomaticFontAxes(format3);
6481 ok(axes == DWRITE_AUTOMATIC_FONT_AXES_OPTICAL_SIZE, "Unexpected automatic axes %u.\n", axes);
6482
6483 hr = IDWriteTextFormat3_SetAutomaticFontAxes(format3, DWRITE_AUTOMATIC_FONT_AXES_OPTICAL_SIZE + 1);
6484 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
6485
6486 IDWriteTextFormat3_Release(format3);
6487
6488 IDWriteTextLayout_Release(layout);
6489
6490 IDWriteTextLayout4_Release(layout4);
6491 IDWriteTextFormat_Release(format);
6492 IDWriteFactory_Release(factory);
6493}
6494
6495static void test_text_format_axes(void)
6496{
6498 IDWriteFontCollection2 *collection2;
6499 DWRITE_FONT_AXIS_VALUE axes[2];
6500 IDWriteTextFormat3 *format3;
6501 DWRITE_FONT_STRETCH stretch;
6507 unsigned int count;
6508 HRESULT hr;
6509
6510 factory = create_factory_iid(&IID_IDWriteFactory6);
6511
6512 if (!factory)
6513 {
6514 win_skip("Text format does not support variations.\n");
6515 return;
6516 }
6517
6518 hr = IDWriteFactory6_CreateTextFormat(factory, L"test_family", NULL, NULL, 0, 10.0f, L"en-us", &format3);
6519 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6520
6521 hr = IDWriteTextFormat3_GetFontCollection(format3, &collection);
6522 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6523
6524 hr = IDWriteFontCollection_QueryInterface(collection, &IID_IDWriteFontCollection2, (void **)&collection2);
6525 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6526
6527 model = IDWriteFontCollection2_GetFontFamilyModel(collection2);
6528 ok(model == DWRITE_FONT_FAMILY_MODEL_TYPOGRAPHIC, "Unexpected model %d.\n", model);
6529
6530 IDWriteFontCollection_Release(collection);
6531 IDWriteFontCollection2_Release(collection2);
6532
6533 count = IDWriteTextFormat3_GetFontAxisValueCount(format3);
6534 ok(!count, "Unexpected axis count %u.\n", count);
6535
6536 stretch = IDWriteTextFormat3_GetFontStretch(format3);
6537 ok(stretch == DWRITE_FONT_STRETCH_NORMAL, "Unexpected font stretch %d.\n", stretch);
6538
6539 style = IDWriteTextFormat3_GetFontStyle(format3);
6540 ok(style == DWRITE_FONT_STYLE_NORMAL, "Unexpected font style %d.\n", style);
6541
6542 weight = IDWriteTextFormat3_GetFontWeight(format3);
6543 ok(weight == DWRITE_FONT_WEIGHT_NORMAL, "Unexpected font weight %d.\n", weight);
6544
6545 /* Regular properties are not set from axis values. */
6547 axes[0].value = 200.0f;
6548 hr = IDWriteTextFormat3_SetFontAxisValues(format3, axes, 1);
6549 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6550
6551 weight = IDWriteTextFormat3_GetFontWeight(format3);
6552 ok(weight == DWRITE_FONT_WEIGHT_NORMAL, "Unexpected font weight %d.\n", weight);
6553
6554 IDWriteTextFormat3_Release(format3);
6555
6556 hr = IDWriteFactory_CreateTextFormat((IDWriteFactory *)factory, L"test_family", NULL,
6558 10.0f, L"en-us", &format);
6559 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6560
6561 hr = IDWriteTextFormat_QueryInterface(format, &IID_IDWriteTextFormat3, (void **)&format3);
6562 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6563
6564 count = IDWriteTextFormat3_GetFontAxisValueCount(format3);
6565 ok(!count, "Unexpected axis count %u.\n", count);
6566
6568 hr = IDWriteTextFormat3_GetFontAxisValues(format3, axes, 1);
6569 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6570 ok(axes[0].axisTag == 0 && axes[0].value == 0.0f, "Unexpected value.\n");
6571
6573 axes[0].value = 200.0f;
6575 axes[1].value = 2.0f;
6576 hr = IDWriteTextFormat3_SetFontAxisValues(format3, axes, 2);
6577 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6578
6579 count = IDWriteTextFormat3_GetFontAxisValueCount(format3);
6580 ok(count == 2, "Unexpected axis count %u.\n", count);
6581
6582 hr = IDWriteTextFormat3_GetFontAxisValues(format3, axes, 1);
6583 ok(hr == E_NOT_SUFFICIENT_BUFFER, "Unexpected hr %#lx.\n", hr);
6584
6585 hr = IDWriteTextFormat3_GetFontAxisValues(format3, axes, 0);
6586 ok(hr == E_NOT_SUFFICIENT_BUFFER, "Unexpected hr %#lx.\n", hr);
6587
6588 hr = IDWriteTextFormat3_GetFontAxisValues(format3, axes, 2);
6589 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6590
6591 hr = IDWriteTextFormat3_SetFontAxisValues(format3, axes, 0);
6592 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6593
6594 count = IDWriteTextFormat3_GetFontAxisValueCount(format3);
6595 ok(!count, "Unexpected axis count %u.\n", count);
6596
6597 IDWriteTextFormat3_Release(format3);
6598 IDWriteTextFormat_Release(format);
6599
6600 IDWriteFactory6_Release(factory);
6601}
6602
6604{
6605 IDWriteFontCollection *collection, *collection2;
6607 IDWriteTypography *typography;
6608 DWRITE_FONT_STRETCH stretch;
6609 IDWriteTextLayout1 *layout1;
6611 IDWriteTextLayout *layout;
6616 HRESULT hr;
6617 BOOL value;
6618
6620
6621 hr = IDWriteFactory_CreateTextFormat(factory, L"Tahoma", NULL, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL,
6622 DWRITE_FONT_STRETCH_NORMAL, 10.0f, L"ru", &format);
6623 ok(hr == S_OK, "Failed to create text format, hr %#lx.\n", hr);
6624
6625 /* Range length is validated when setting properties. */
6626
6627 hr = IDWriteFactory_CreateTextLayout(factory, L"string", 6, format, 100.0f, 100.0f, &layout);
6628 ok(hr == S_OK, "Failed to create text layout, hr %#lx.\n", hr);
6629
6630 /* Weight */
6631 range.startPosition = 10;
6632 range.length = ~0u;
6633 hr = IDWriteTextLayout_SetFontWeight(layout, DWRITE_FONT_WEIGHT_NORMAL, range);
6634 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
6635
6636 range.startPosition = 10;
6637 range.length = ~0u - 9;
6638 hr = IDWriteTextLayout_SetFontWeight(layout, DWRITE_FONT_WEIGHT_NORMAL, range);
6639 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
6640
6641 range.startPosition = 10;
6642 range.length = ~0u - 10;
6643 hr = IDWriteTextLayout_SetFontWeight(layout, DWRITE_FONT_WEIGHT_HEAVY, range);
6644 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6645
6646 range.startPosition = range.length = 0;
6647 hr = IDWriteTextLayout_GetFontWeight(layout, 0, &weight, &range);
6648 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6649 ok(range.startPosition == 0 && range.length == 10, "Unexpected range (%u, %u).\n", range.startPosition, range.length);
6650
6651 range.startPosition = range.length = 0;
6652 hr = IDWriteTextLayout_GetFontWeight(layout, 10, &weight, &range);
6653 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6654 ok(range.startPosition == 10 && range.length == ~0u - 10, "Unexpected range (%u, %u).\n",
6655 range.startPosition, range.length);
6656
6657 range.startPosition = 0;
6658 range.length = ~0u;
6659 hr = IDWriteTextLayout_SetFontWeight(layout, DWRITE_FONT_WEIGHT_NORMAL, range);
6660 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6661
6662 /* Family name */
6663 range.startPosition = 10;
6664 range.length = ~0u;
6665 hr = IDWriteTextLayout_SetFontFamilyName(layout, L"family", range);
6666 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
6667
6668 range.startPosition = 10;
6669 range.length = ~0u - 9;
6670 hr = IDWriteTextLayout_SetFontFamilyName(layout, L"family", range);
6671 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
6672
6673 range.startPosition = 10;
6674 range.length = ~0u - 10;
6675 hr = IDWriteTextLayout_SetFontFamilyName(layout, L"family", range);
6676 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6677
6678 range.startPosition = 0;
6679 range.length = ~0u;
6680 hr = IDWriteTextLayout_SetFontFamilyName(layout, L"Tahoma", range);
6681 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6682
6683 /* Style */
6684 range.startPosition = 10;
6685 range.length = ~0u;
6686 hr = IDWriteTextLayout_SetFontStyle(layout, DWRITE_FONT_STYLE_ITALIC, range);
6687 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
6688
6689 range.startPosition = 10;
6690 range.length = ~0u - 9;
6691 hr = IDWriteTextLayout_SetFontStyle(layout, DWRITE_FONT_STYLE_ITALIC, range);
6692 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
6693
6694 range.startPosition = 10;
6695 range.length = ~0u - 10;
6696 hr = IDWriteTextLayout_SetFontStyle(layout, DWRITE_FONT_STYLE_ITALIC, range);
6697 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6698
6699 range.startPosition = range.length = 0;
6700 hr = IDWriteTextLayout_GetFontStyle(layout, 0, &style, &range);
6701 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6702 ok(range.startPosition == 0 && range.length == 10, "Unexpected range (%u, %u).\n", range.startPosition, range.length);
6703
6704 range.startPosition = range.length = 0;
6705 hr = IDWriteTextLayout_GetFontStyle(layout, 10, &style, &range);
6706 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6707 ok(range.startPosition == 10 && range.length == ~0u - 10, "Unexpected range (%u, %u).\n",
6708 range.startPosition, range.length);
6709
6710 range.startPosition = 0;
6711 range.length = ~0u;
6712 hr = IDWriteTextLayout_SetFontStyle(layout, DWRITE_FONT_STYLE_NORMAL, range);
6713 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6714
6715 /* Stretch */
6716 range.startPosition = 10;
6717 range.length = ~0u;
6718 hr = IDWriteTextLayout_SetFontStretch(layout, DWRITE_FONT_STRETCH_CONDENSED, range);
6719 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
6720
6721 range.startPosition = 10;
6722 range.length = ~0u - 9;
6723 hr = IDWriteTextLayout_SetFontStretch(layout, DWRITE_FONT_STRETCH_CONDENSED, range);
6724 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
6725
6726 range.startPosition = 10;
6727 range.length = ~0u - 10;
6728 hr = IDWriteTextLayout_SetFontStretch(layout, DWRITE_FONT_STRETCH_CONDENSED, range);
6729 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6730
6731 range.startPosition = range.length = 0;
6732 hr = IDWriteTextLayout_GetFontStretch(layout, 0, &stretch, &range);
6733 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6734 ok(range.startPosition == 0 && range.length == 10, "Unexpected range (%u, %u).\n", range.startPosition, range.length);
6735
6736 range.startPosition = range.length = 0;
6737 hr = IDWriteTextLayout_GetFontStretch(layout, 10, &stretch, &range);
6738 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6739 ok(range.startPosition == 10 && range.length == ~0u - 10, "Unexpected range (%u, %u).\n",
6740 range.startPosition, range.length);
6741
6742 range.startPosition = 0;
6743 range.length = ~0u;
6744 hr = IDWriteTextLayout_SetFontStretch(layout, DWRITE_FONT_STRETCH_NORMAL, range);
6745 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6746
6747 /* Underline */
6748 range.startPosition = 10;
6749 range.length = ~0u;
6750 hr = IDWriteTextLayout_SetUnderline(layout, TRUE, range);
6751 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
6752
6753 range.startPosition = 10;
6754 range.length = ~0u - 9;
6755 hr = IDWriteTextLayout_SetUnderline(layout, TRUE, range);
6756 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
6757
6758 range.startPosition = 10;
6759 range.length = ~0u - 10;
6760 hr = IDWriteTextLayout_SetUnderline(layout, TRUE, range);
6761 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6762
6763 range.startPosition = range.length = 0;
6764 hr = IDWriteTextLayout_GetUnderline(layout, 0, &value, &range);
6765 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6766 ok(range.startPosition == 0 && range.length == 10, "Unexpected range (%u, %u).\n", range.startPosition, range.length);
6767
6768 range.startPosition = range.length = 0;
6769 hr = IDWriteTextLayout_GetUnderline(layout, 10, &value, &range);
6770 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6771 ok(range.startPosition == 10 && range.length == ~0u - 10, "Unexpected range (%u, %u).\n",
6772 range.startPosition, range.length);
6773
6774 range.startPosition = 0;
6775 range.length = ~0u;
6776 hr = IDWriteTextLayout_SetUnderline(layout, FALSE, range);
6777 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6778
6779 /* Strikethrough */
6780 range.startPosition = 10;
6781 range.length = ~0u;
6782 hr = IDWriteTextLayout_SetStrikethrough(layout, TRUE, range);
6783 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
6784
6785 range.startPosition = 10;
6786 range.length = ~0u - 9;
6787 hr = IDWriteTextLayout_SetStrikethrough(layout, TRUE, range);
6788 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
6789
6790 range.startPosition = 10;
6791 range.length = ~0u - 10;
6792 hr = IDWriteTextLayout_SetStrikethrough(layout, TRUE, range);
6793 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6794
6795 range.startPosition = range.length = 0;
6796 hr = IDWriteTextLayout_GetStrikethrough(layout, 0, &value, &range);
6797 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6798 ok(range.startPosition == 0 && range.length == 10, "Unexpected range (%u, %u).\n", range.startPosition, range.length);
6799
6800 range.startPosition = range.length = 0;
6801 hr = IDWriteTextLayout_GetStrikethrough(layout, 10, &value, &range);
6802 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6803 ok(range.startPosition == 10 && range.length == ~0u - 10, "Unexpected range (%u, %u).\n",
6804 range.startPosition, range.length);
6805
6806 range.startPosition = 0;
6807 range.length = ~0u;
6808 hr = IDWriteTextLayout_SetStrikethrough(layout, FALSE, range);
6809 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6810
6811 /* Locale name */
6812 range.startPosition = 10;
6813 range.length = ~0u;
6814 hr = IDWriteTextLayout_SetLocaleName(layout, L"locale", range);
6815 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
6816
6817 range.startPosition = 10;
6818 range.length = ~0u - 9;
6819 hr = IDWriteTextLayout_SetLocaleName(layout, L"locale", range);
6820 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
6821
6822 range.startPosition = 10;
6823 range.length = ~0u - 10;
6824 hr = IDWriteTextLayout_SetLocaleName(layout, L"locale", range);
6825 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6826
6827 range.startPosition = 0;
6828 range.length = ~0u;
6829 hr = IDWriteTextLayout_SetLocaleName(layout, L"ru", range);
6830 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6831
6832 /* Inline object */
6833 hr = IDWriteFactory_CreateEllipsisTrimmingSign(factory, format, &sign);
6834 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6835
6836 range.startPosition = 10;
6837 range.length = ~0u;
6838 hr = IDWriteTextLayout_SetInlineObject(layout, sign, range);
6839 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
6840
6841 range.startPosition = 10;
6842 range.length = ~0u - 9;
6843 hr = IDWriteTextLayout_SetInlineObject(layout, sign, range);
6844 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
6845
6846 range.startPosition = 10;
6847 range.length = ~0u - 10;
6848 hr = IDWriteTextLayout_SetInlineObject(layout, sign, range);
6849 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6850
6851 range.startPosition = range.length = 0;
6852 object = NULL;
6853 hr = IDWriteTextLayout_GetInlineObject(layout, 10, &object, &range);
6854 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6855 ok(range.startPosition == 10 && range.length == ~0u - 10, "Unexpected range (%u, %u).\n",
6856 range.startPosition, range.length);
6857 IDWriteInlineObject_Release(object);
6858
6859 range.startPosition = 0;
6860 range.length = ~0u;
6861 hr = IDWriteTextLayout_SetInlineObject(layout, NULL, range);
6862 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6863
6864 /* Drawing effect */
6865 range.startPosition = 10;
6866 range.length = ~0u;
6867 hr = IDWriteTextLayout_SetDrawingEffect(layout, (IUnknown *)sign, range);
6868 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
6869
6870 range.startPosition = 10;
6871 range.length = ~0u - 9;
6872 hr = IDWriteTextLayout_SetDrawingEffect(layout, (IUnknown *)sign, range);
6873 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
6874
6875 range.startPosition = 10;
6876 range.length = ~0u - 10;
6877 hr = IDWriteTextLayout_SetDrawingEffect(layout, (IUnknown *)sign, range);
6878 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6879
6880 range.startPosition = 0;
6881 range.length = ~0u;
6882 hr = IDWriteTextLayout_SetDrawingEffect(layout, NULL, range);
6883 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6884
6885 IDWriteInlineObject_Release(sign);
6886
6887 /* Typography */
6888 hr = IDWriteFactory_CreateTypography(factory, &typography);
6889 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6890
6891 range.startPosition = 10;
6892 range.length = ~0u;
6893 hr = IDWriteTextLayout_SetTypography(layout, typography, range);
6894 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
6895
6896 range.startPosition = 10;
6897 range.length = ~0u - 9;
6898 hr = IDWriteTextLayout_SetTypography(layout, typography, range);
6899 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
6900
6901 range.startPosition = 10;
6902 range.length = ~0u - 10;
6903 hr = IDWriteTextLayout_SetTypography(layout, typography, range);
6904 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6905
6906 range.startPosition = 0;
6907 range.length = ~0u;
6908 hr = IDWriteTextLayout_SetTypography(layout, NULL, range);
6909 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6910
6911 IDWriteTypography_Release(typography);
6912
6913 /* Font collection */
6914 hr = IDWriteFactory_GetSystemFontCollection(factory, &collection, FALSE);
6915 ok(hr == S_OK, "Failed to get system collection, hr %#lx.\n", hr);
6916
6917 range.startPosition = 10;
6918 range.length = ~0u;
6919 hr = IDWriteTextLayout_SetFontCollection(layout, collection, range);
6920 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
6921
6922 range.startPosition = 10;
6923 range.length = ~0u - 9;
6924 hr = IDWriteTextLayout_SetFontCollection(layout, collection, range);
6925 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
6926
6927 range.startPosition = 10;
6928 range.length = ~0u - 10;
6929 hr = IDWriteTextLayout_SetFontCollection(layout, collection, range);
6930 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6931
6932 range.startPosition = 0;
6933 range.length = ~0u;
6934 hr = IDWriteTextLayout_SetFontCollection(layout, NULL, range);
6935 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6936
6937 range.startPosition = range.length = 0;
6938 collection2 = NULL;
6939 hr = IDWriteTextLayout_GetFontCollection(layout, 10, &collection2, &range);
6940 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6941 ok(range.length == ~0u, "Unexpected range length %u.\n", range.length);
6942 if (collection2)
6943 IDWriteFontCollection_Release(collection2);
6944
6945 IDWriteFontCollection_Release(collection);
6946
6947 if (SUCCEEDED(IDWriteTextLayout_QueryInterface(layout, &IID_IDWriteTextLayout1, (void **)&layout1)))
6948 {
6949 /* Pair kerning */
6950 range.startPosition = 10;
6951 range.length = ~0u;
6952 hr = IDWriteTextLayout1_SetPairKerning(layout1, TRUE, range);
6953 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
6954
6955 range.startPosition = 10;
6956 range.length = ~0u - 9;
6957 hr = IDWriteTextLayout1_SetPairKerning(layout1, TRUE, range);
6958 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
6959
6960 range.startPosition = 10;
6961 range.length = ~0u - 10;
6962 hr = IDWriteTextLayout1_SetPairKerning(layout1, TRUE, range);
6963 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6964
6965 range.startPosition = range.length = 0;
6966 hr = IDWriteTextLayout1_GetPairKerning(layout1, 0, &value, &range);
6967 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6968 ok(range.startPosition == 0 && range.length == 10, "Unexpected range (%u, %u).\n", range.startPosition, range.length);
6969
6970 range.startPosition = range.length = 0;
6971 value = FALSE;
6972 hr = IDWriteTextLayout1_GetPairKerning(layout1, 10, &value, &range);
6973 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6974 ok(range.startPosition == 10 && range.length == ~0u - 10, "Unexpected range (%u, %u).\n",
6975 range.startPosition, range.length);
6976 ok(!!value, "Unexpected value %d.\n", value);
6977
6978 range.startPosition = 0;
6979 range.length = ~0u;
6980 hr = IDWriteTextLayout1_SetPairKerning(layout1, FALSE, range);
6981 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6982
6983 IDWriteTextLayout1_Release(layout1);
6984 }
6985
6986 IDWriteTextLayout_Release(layout);
6987
6988 IDWriteTextFormat_Release(format);
6989 IDWriteFactory_Release(factory);
6990}
6991
6992static void test_HitTestTextRange(void)
6993{
6995 IDWriteInlineObject *inlineobj;
6998 IDWriteTextLayout *layout;
7001 unsigned int count;
7002 HRESULT hr;
7003
7005
7006 hr = IDWriteFactory_CreateTextFormat(factory, L"Tahoma", NULL, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL,
7007 DWRITE_FONT_STRETCH_NORMAL, 10.0f, L"ru", &format);
7008 ok(hr == S_OK, "Failed to create text format, hr %#lx.\n", hr);
7009
7010 hr = IDWriteFactory_CreateTextLayout(factory, L"string", 6, format, 100.0f, 100.0f, &layout);
7011 ok(hr == S_OK, "Failed to create text layout, hr %#lx.\n", hr);
7012
7013 /* Start index exceeding layout text length, dummy range returned. */
7014 count = 0;
7015 hr = IDWriteTextLayout_HitTestTextRange(layout, 7, 10, 0.0f, 0.0f, metrics, ARRAY_SIZE(metrics), &count);
7016 todo_wine
7017 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7018if (SUCCEEDED(hr))
7019{
7020 ok(count == 1, "Unexpected metrics count %u.\n", count);
7021 ok(metrics[0].textPosition == 6 && metrics[0].length == 0, "Unexpected metrics range %u, %u.\n",
7022 metrics[0].textPosition, metrics[0].length);
7023 ok(!!metrics[0].isText, "Expected text range.\n");
7024}
7025 /* Length exceeding layout text length, trimmed. */
7026 count = 0;
7027 hr = IDWriteTextLayout_HitTestTextRange(layout, 0, 10, 0.0f, 0.0f, metrics, ARRAY_SIZE(metrics), &count);
7028 todo_wine
7029 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7030if (SUCCEEDED(hr))
7031{
7032 ok(count == 1, "Unexpected metrics count %u.\n", count);
7033 ok(metrics[0].textPosition == 0 && metrics[0].length == 6, "Unexpected metrics range %u, %u.\n",
7034 metrics[0].textPosition, metrics[0].length);
7035 ok(!!metrics[0].isText, "Expected text range.\n");
7036}
7037 /* Change font size for second half. */
7038 range.startPosition = 3;
7039 range.length = 3;
7040 hr = IDWriteTextLayout_SetFontSize(layout, 20.0f, range);
7041 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7042
7043 count = 0;
7044 hr = IDWriteTextLayout_HitTestTextRange(layout, 0, 6, 0.0f, 0.0f, metrics, ARRAY_SIZE(metrics), &count);
7045 todo_wine
7046 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7047if (SUCCEEDED(hr))
7048{
7049 ok(count == 1, "Unexpected metrics count %u.\n", count);
7050 ok(metrics[0].textPosition == 0 && metrics[0].length == 6, "Unexpected metrics range %u, %u.\n",
7051 metrics[0].textPosition, metrics[0].length);
7052 ok(!!metrics[0].isText, "Expected text range.\n");
7053
7054 hr = IDWriteTextLayout_GetLineMetrics(layout, &line, 1, &count);
7055 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7056 ok(line.height == metrics[0].height, "Unexpected range height.\n");
7057}
7058 /* With inline object. */
7059 hr = IDWriteFactory_CreateEllipsisTrimmingSign(factory, format, &inlineobj);
7060 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7061
7062 hr = IDWriteTextLayout_SetInlineObject(layout, inlineobj, range);
7063 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7064
7065 count = 0;
7066 hr = IDWriteTextLayout_HitTestTextRange(layout, 0, 6, 0.0f, 0.0f, metrics, ARRAY_SIZE(metrics), &count);
7067 todo_wine
7068 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7069if (SUCCEEDED(hr))
7070{
7071 ok(count == 2, "Unexpected metrics count %u.\n", count);
7072 ok(metrics[0].textPosition == 0 && metrics[0].length == 3, "Unexpected metrics range %u, %u.\n",
7073 metrics[0].textPosition, metrics[0].length);
7074 ok(!!metrics[0].isText, "Expected text range.\n");
7075 ok(metrics[1].textPosition == 3 && metrics[1].length == 3, "Unexpected metrics range %u, %u.\n",
7076 metrics[1].textPosition, metrics[1].length);
7077 ok(!metrics[1].isText, "Unexpected text range.\n");
7078}
7079 count = 0;
7080 hr = IDWriteTextLayout_HitTestTextRange(layout, 7, 10, 0.0f, 0.0f, metrics, ARRAY_SIZE(metrics), &count);
7081 todo_wine
7082 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7083if (SUCCEEDED(hr))
7084{
7085 ok(count == 1, "Unexpected metrics count %u.\n", count);
7086 ok(metrics[0].textPosition == 6 && metrics[0].length == 0, "Unexpected metrics range %u, %u.\n",
7087 metrics[0].textPosition, metrics[0].length);
7088 ok(!metrics[0].isText, "Unexpected text range.\n");
7089}
7090 IDWriteInlineObject_Release(inlineobj);
7091 IDWriteTextLayout_Release(layout);
7092 IDWriteTextFormat_Release(format);
7093
7094 IDWriteFactory_Release(factory);
7095}
7096
7098{
7100
7101 if (!(factory = create_factory())) {
7102 win_skip("failed to create factory\n");
7103 return;
7104 }
7105
7108
7116 test_Draw();
7122 test_fallback();
7153
7154 IDWriteFactory_Release(factory);
7155}
static void flush_sequence(void)
Definition: SystemMenu.c:184
static struct recvd_message * sequence
Definition: SystemMenu.c:63
unsigned short UINT16
Definition: actypes.h:129
unsigned char UINT8
Definition: actypes.h:128
COMPILER_DEPENDENT_UINT64 UINT64
Definition: actypes.h:131
static struct sockaddr_in sa
Definition: adnsresfilter.c:69
_Check_return_ _Ret_maybenull_ _In_ size_t alignment
Definition: align.cpp:48
#define InterlockedIncrement
Definition: armddk.h:53
#define InterlockedDecrement
Definition: armddk.h:52
#define ok(value,...)
Definition: atltest.h:57
#define skip(...)
Definition: atltest.h:64
#define broken(x)
Definition: atltest.h:178
#define START_TEST(x)
Definition: atltest.h:75
#define ok_(x1, x2)
Definition: atltest.h:61
static const WCHAR nameW[]
Definition: main.c:49
#define index(s, c)
Definition: various.h:29
#define ARRAY_SIZE(A)
Definition: main.h:20
#define U(x)
Definition: wordpad.c:45
const GUID IID_IUnknown
#define C(c)
Definition: builtin.c:4556
Definition: terminate.cpp:24
Definition: list.h:39
Definition: _locale.h:75
range
Definition: d3dx9_private.h:58
DWRITE_MEASURING_MODE
Definition: dcommon.idl:36
@ DWRITE_MEASURING_MODE_GDI_CLASSIC
Definition: dcommon.idl:38
@ DWRITE_MEASURING_MODE_NATURAL
Definition: dcommon.idl:37
@ DWRITE_MEASURING_MODE_GDI_NATURAL
Definition: dcommon.idl:39
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
#define E_INVALIDARG
Definition: ddrawi.h:101
#define E_NOTIMPL
Definition: ddrawi.h:99
#define E_FAIL
Definition: ddrawi.h:102
#define realloc
Definition: debug_ros.c:6
#define free
Definition: debug_ros.c:5
#define malloc
Definition: debug_ros.c:4
HRESULT hr
Definition: delayimp.cpp:582
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
HRESULT WINAPI DWriteCreateFactory(DWRITE_FACTORY_TYPE type, REFIID riid, IUnknown **ret)
Definition: main.c:2110
#define lstrcpyW
Definition: compat.h:749
#define lstrlenW
Definition: compat.h:750
static void cleanup(void)
Definition: main.c:1335
HMODULE WINAPI DECLSPEC_HOTPATCH GetModuleHandleA(LPCSTR lpModuleName)
Definition: loader.c:812
HRSRC WINAPI FindResourceA(HMODULE hModule, LPCSTR name, LPCSTR type)
Definition: res.c:155
DWORD WINAPI SizeofResource(HINSTANCE hModule, HRSRC hRsrc)
Definition: res.c:568
LPVOID WINAPI LockResource(HGLOBAL handle)
Definition: res.c:550
HGLOBAL WINAPI LoadResource(HINSTANCE hModule, HRSRC hRsrc)
Definition: res.c:532
int WINAPI lstrcmpW(LPCWSTR str1, LPCWSTR str2)
Definition: locale.c:4152
const WCHAR * text
Definition: package.c:1826
#define assert(_expr)
Definition: assert.h:32
_ACRTIMP int __cdecl wcscmp(const wchar_t *, const wchar_t *)
Definition: wcs.c:1977
_ACRTIMP int __cdecl memcmp(const void *, const void *, size_t)
Definition: string.c:2807
_ACRTIMP wchar_t *__cdecl wcstok(wchar_t *, const wchar_t *)
Definition: wcs.c:2070
#define INT_MIN
Definition: limits.h:25
#define UINT_MAX
Definition: limits.h:27
_ACRTIMP double __cdecl fabs(double)
_ACRTIMP float __cdecl fabsf(float)
_ACRTIMP double __cdecl floor(double)
Definition: floor.c:18
method
Definition: dragdrop.c:54
return ret
Definition: mutex.c:147
#define L(x)
Definition: resources.c:13
@ DWRITE_SCRIPT_SHAPES_NO_VISUAL
Definition: dwrite.idl:330
DWRITE_PARAGRAPH_ALIGNMENT
Definition: dwrite.idl:183
@ DWRITE_PARAGRAPH_ALIGNMENT_FAR
Definition: dwrite.idl:185
@ DWRITE_PARAGRAPH_ALIGNMENT_NEAR
Definition: dwrite.idl:184
@ DWRITE_PARAGRAPH_ALIGNMENT_CENTER
Definition: dwrite.idl:186
DWRITE_BREAK_CONDITION
Definition: dwrite.idl:222
@ DWRITE_BREAK_CONDITION_MUST_BREAK
Definition: dwrite.idl:226
@ DWRITE_BREAK_CONDITION_CAN_BREAK
Definition: dwrite.idl:224
@ DWRITE_BREAK_CONDITION_MAY_NOT_BREAK
Definition: dwrite.idl:225
@ DWRITE_BREAK_CONDITION_NEUTRAL
Definition: dwrite.idl:223
DWRITE_WORD_WRAPPING
Definition: dwrite.idl:190
@ DWRITE_WORD_WRAPPING_NO_WRAP
Definition: dwrite.idl:192
@ DWRITE_WORD_WRAPPING_WRAP
Definition: dwrite.idl:191
@ DWRITE_WORD_WRAPPING_CHARACTER
Definition: dwrite.idl:195
@ DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES
Definition: dwrite.idl:128
DWRITE_FONT_WEIGHT
Definition: dwrite.idl:73
@ DWRITE_FONT_WEIGHT_NORMAL
Definition: dwrite.idl:79
@ DWRITE_FONT_WEIGHT_BOLD
Definition: dwrite.idl:84
@ DWRITE_FONT_WEIGHT_HEAVY
Definition: dwrite.idl:88
DWRITE_FLOW_DIRECTION
Definition: dwrite.idl:207
@ DWRITE_FLOW_DIRECTION_LEFT_TO_RIGHT
Definition: dwrite.idl:210
@ DWRITE_FLOW_DIRECTION_TOP_TO_BOTTOM
Definition: dwrite.idl:208
DWRITE_FONT_STYLE
Definition: dwrite.idl:109
@ DWRITE_FONT_STYLE_NORMAL
Definition: dwrite.idl:110
@ DWRITE_FONT_STYLE_ITALIC
Definition: dwrite.idl:112
@ DWRITE_FONT_STYLE_OBLIQUE
Definition: dwrite.idl:111
@ DWRITE_FACTORY_TYPE_ISOLATED
Definition: dwrite.idl:43
DWRITE_TEXT_ALIGNMENT
Definition: dwrite.idl:175
@ DWRITE_TEXT_ALIGNMENT_CENTER
Definition: dwrite.idl:178
@ DWRITE_TEXT_ALIGNMENT_JUSTIFIED
Definition: dwrite.idl:179
@ DWRITE_TEXT_ALIGNMENT_LEADING
Definition: dwrite.idl:176
@ DWRITE_TEXT_ALIGNMENT_TRAILING
Definition: dwrite.idl:177
@ DWRITE_TRIMMING_GRANULARITY_WORD
Definition: dwrite.idl:218
@ DWRITE_TRIMMING_GRANULARITY_CHARACTER
Definition: dwrite.idl:217
@ DWRITE_TRIMMING_GRANULARITY_NONE
Definition: dwrite.idl:216
DWRITE_READING_DIRECTION
Definition: dwrite.idl:199
@ DWRITE_READING_DIRECTION_TOP_TO_BOTTOM
Definition: dwrite.idl:202
@ DWRITE_READING_DIRECTION_RIGHT_TO_LEFT
Definition: dwrite.idl:201
@ DWRITE_READING_DIRECTION_LEFT_TO_RIGHT
Definition: dwrite.idl:200
DWRITE_FONT_STRETCH
Definition: dwrite.idl:94
@ DWRITE_FONT_STRETCH_EXPANDED
Definition: dwrite.idl:103
@ DWRITE_FONT_STRETCH_NORMAL
Definition: dwrite.idl:100
@ DWRITE_FONT_STRETCH_UNDEFINED
Definition: dwrite.idl:95
@ DWRITE_FONT_STRETCH_ULTRA_EXPANDED
Definition: dwrite.idl:105
@ DWRITE_FONT_STRETCH_CONDENSED
Definition: dwrite.idl:98
@ DWRITE_FONT_FEATURE_TAG_KERNING
Definition: dwrite.idl:271
DWRITE_LINE_SPACING_METHOD
Definition: dwrite.idl:230
@ DWRITE_LINE_SPACING_METHOD_PROPORTIONAL
Definition: dwrite.idl:233
@ DWRITE_LINE_SPACING_METHOD_UNIFORM
Definition: dwrite.idl:232
@ DWRITE_LINE_SPACING_METHOD_DEFAULT
Definition: dwrite.idl:231
DWRITE_VERTICAL_GLYPH_ORIENTATION
Definition: dwrite_1.idl:426
@ DWRITE_VERTICAL_GLYPH_ORIENTATION_STACKED
Definition: dwrite_1.idl:428
@ DWRITE_VERTICAL_GLYPH_ORIENTATION_DEFAULT
Definition: dwrite_1.idl:427
DWRITE_OPTICAL_ALIGNMENT
Definition: dwrite_2.idl:22
@ DWRITE_OPTICAL_ALIGNMENT_NONE
Definition: dwrite_2.idl:23
@ DWRITE_OPTICAL_ALIGNMENT_NO_SIDE_BEARINGS
Definition: dwrite_2.idl:24
DWRITE_FONT_FAMILY_MODEL
Definition: dwrite_3.idl:169
@ DWRITE_FONT_FAMILY_MODEL_TYPOGRAPHIC
Definition: dwrite_3.idl:170
UINT32 trailingWhitespaceLength
Definition: dwrite_3.idl:857
@ DWRITE_FONT_AXIS_TAG_WEIGHT
Definition: dwrite_3.idl:126
@ DWRITE_FONT_AXIS_TAG_WIDTH
Definition: dwrite_3.idl:127
UINT32 newlineLength
Definition: dwrite_3.idl:858
DWRITE_AUTOMATIC_FONT_AXES
Definition: dwrite_3.idl:156
@ DWRITE_AUTOMATIC_FONT_AXES_OPTICAL_SIZE
Definition: dwrite_3.idl:158
@ DWRITE_AUTOMATIC_FONT_AXES_NONE
Definition: dwrite_3.idl:157
FLOAT baseline
Definition: dwrite_3.idl:860
BOOL isTrimmed
Definition: dwrite_3.idl:861
@ DWRITE_FONT_LINE_GAP_USAGE_DEFAULT
Definition: dwrite_3.idl:868
@ DWRITE_FONT_LINE_GAP_USAGE_ENABLED
Definition: dwrite_3.idl:870
#define abs(i)
Definition: fconv.c:206
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
FT_Vector * vec
Definition: ftbbox.c:469
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
const GLdouble * v
Definition: gl.h:2040
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLint GLint GLsizei GLsizei height
Definition: gl.h:1546
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
GLint GLint GLsizei width
Definition: gl.h:1546
GLdouble n
Definition: glext.h:7729
GLuint GLenum GLenum transform
Definition: glext.h:9407
GLenum GLenum GLenum GLenum GLenum scale
Definition: glext.h:9032
GLuint GLuint * names
Definition: glext.h:11545
GLsizei const GLchar *const * strings
Definition: glext.h:7622
GLsizeiptr size
Definition: glext.h:5919
GLintptr offset
Definition: glext.h:5920
GLuint coord
Definition: glext.h:9511
GLuint index
Definition: glext.h:6031
GLdouble GLdouble right
Definition: glext.h:10859
GLenum GLuint GLint GLenum face
Definition: glext.h:7025
GLsizei GLenum const GLvoid GLuint GLsizei GLfloat * metrics
Definition: glext.h:11745
GLenum mode
Definition: glext.h:6217
GLint left
Definition: glext.h:7726
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
GLsizei GLenum GLboolean sink
Definition: glext.h:5672
GLfloat GLfloat p
Definition: glext.h:8902
GLenum GLsizei len
Definition: glext.h:6722
const GLfloat * m
Definition: glext.h:10848
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble * u
Definition: glfuncs.h:240
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
unsigned int UINT
Definition: sysinfo.c:13
#define FLOAT
Definition: i386-dis.c:525
REFIID riid
Definition: atlbase.h:39
#define S_OK
Definition: intsafe.h:52
#define SUCCEEDED(hr)
Definition: intsafe.h:50
uint32_t entry
Definition: isohybrid.c:63
#define e
Definition: ke_i.h:82
#define debugstr_w
Definition: kernel32.h:32
#define wine_dbgstr_w
Definition: kernel32.h:34
LPWSTR WINAPI lstrcatW(LPWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:274
#define sign(x)
Definition: mapdesc.cc:613
#define win_skip
Definition: minitest.h:67
void __cdecl void __cdecl void __cdecl void __cdecl void __cdecl void winetest_pop_context(void)
void __cdecl void __cdecl void __cdecl void __cdecl void __cdecl winetest_push_context(const char *fmt,...) __WINE_PRINTF_ATTR(1
Definition: test.h:539
#define todo_wine
Definition: minitest.h:80
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
struct task_struct * current
Definition: linux.c:32
static PVOID ptr
Definition: dispmode.c:27
static struct test_info tests[]
BOOL todo
Definition: filedlg.c:313
BOOL expected
Definition: store.c:2000
static DNS_RECORDW r2
Definition: record.c:38
static HRESULT WINAPI fontcollection_QI(IDWriteFontCollection *iface, REFIID riid, void **obj)
Definition: layout.c:4891
static void test_line_spacing(void)
Definition: layout.c:6158
static ULONG WINAPI testeffect_AddRef(IUnknown *iface)
Definition: layout.c:1242
static const struct drawcall_entry draweffect4_seq[]
Definition: layout.c:3817
static ULONG WINAPI singlefontfileenumerator_AddRef(IDWriteFontFileEnumerator *iface)
Definition: layout.c:57
static HRESULT WINAPI testrenderer_IsPixelSnappingDisabled(IDWriteTextRenderer *iface, void *context, BOOL *disabled)
Definition: layout.c:896
static ULONG WINAPI fontdatastream_Release(IDWriteFontFileStream *iface)
Definition: layout.c:165
static void test_InvalidateLayout(void)
Definition: layout.c:6099
static IDWriteTextRenderer testrenderer
Definition: layout.c:1082
static const struct drawcall_entry drawunderline_seq[]
Definition: layout.c:5846
static const struct drawcall_entry drawunderline4_seq[]
Definition: layout.c:5868
#define TEST_MEASURING_MODE(ctxt, mode)
Definition: layout.c:924
static HRESULT create_fontdatastream(LPVOID data, UINT size, IDWriteFontFileStream **iface)
Definition: layout.c:222
static const struct drawcall_entry drawunderline3_seq[]
Definition: layout.c:5860
static void test_pixelsnapping(void)
Definition: layout.c:4748
static void test_SetWordWrapping(void)
Definition: layout.c:4831
static HRESULT WINAPI fontdatastream_GetLastWriteTime(IDWriteFontFileStream *iface, UINT64 *last_writetime)
Definition: layout.c:206
static DWRITE_READING_DIRECTION WINAPI analysissource_GetParagraphReadingDirection(IDWriteTextAnalysisSource *iface)
Definition: layout.c:524
static void test_SetTextAlignment(void)
Definition: layout.c:4303
static ULONG WINAPI analysissource_Release(IDWriteTextAnalysisSource *iface)
Definition: layout.c:493
static BOOL get_enus_string(IDWriteLocalizedStrings *strings, WCHAR *buff, UINT32 size)
Definition: layout.c:3952
static HRESULT WINAPI fontdatastream_ReadFileFragment(IDWriteFontFileStream *iface, void const **fragment_start, UINT64 offset, UINT64 fragment_size, void **fragment_context)
Definition: layout.c:176
static const IDWriteTextRendererVtbl testrenderervtbl
Definition: layout.c:1069
static HRESULT WINAPI resourcecollectionloader_CreateEnumeratorFromKey(IDWriteFontCollectionLoader *iface, IDWriteFactory *factory, const void *key, UINT32 key_size, IDWriteFontFileEnumerator **enumerator)
Definition: layout.c:360
static struct testanalysissink analysissink
Definition: layout.c:471
static DWRITE_MATRIX compattransforms[]
Definition: layout.c:4741
static void test_SetFontStretch(void)
Definition: layout.c:3484
static HRESULT WINAPI analysissink_SetBidiLevel(IDWriteTextAnalysisSink *iface, UINT32 position, UINT32 length, UINT8 explicitLevel, UINT8 resolvedLevel)
Definition: layout.c:447
static const struct drawcall_entry draw_trimmed_seq[]
Definition: layout.c:2082
static HRESULT WINAPI analysissource_GetNumberSubstitution(IDWriteTextAnalysisSource *iface, UINT32 position, UINT32 *text_len, IDWriteNumberSubstitution **substitution)
Definition: layout.c:539
static void test_SetFontSize(void)
Definition: layout.c:3228
static void test_GetLocaleName(void)
Definition: layout.c:1674
static void test_CreateEllipsisTrimmingSign(void)
Definition: layout.c:1722
static void test_SetVerticalGlyphOrientation(void)
Definition: layout.c:3094
static HRESULT WINAPI testinlineobj_GetMetrics(IDWriteInlineObject *iface, DWRITE_INLINE_OBJECT_METRICS *metrics)
Definition: layout.c:1136
static struct drawcall_sequence * expected_seq[1]
Definition: layout.c:704
static void test_SetParagraphAlignment(void)
Definition: layout.c:4468
static BOOL float_eq(FLOAT left, FLOAT right)
Definition: layout.c:4692
static void test_Draw(void)
Definition: layout.c:2135
static const struct drawcall_entry draweffect3_seq[]
Definition: layout.c:3812
static IDWriteTextAnalysisSource analysissource
Definition: layout.c:557
static ULONG WINAPI resourcecollectionloader_Release(IDWriteFontCollectionLoader *iface)
Definition: layout.c:346
static void test_layout_range_length(void)
Definition: layout.c:6603
static void test_GetMetrics(void)
Definition: layout.c:3639
static void test_typography(void)
Definition: layout.c:2349
static ULONG WINAPI testinlineobj_AddRef(IDWriteInlineObject *iface)
Definition: layout.c:1111
static IDWriteFontCollection fallbackcollection
Definition: layout.c:4973
static HRESULT WINAPI testinlineobj3_GetMetrics(IDWriteInlineObject *iface, DWRITE_INLINE_OBJECT_METRICS *metrics)
Definition: layout.c:1193
static void test_CreateGdiCompatibleTextLayout(void)
Definition: layout.c:1415
static HRESULT WINAPI fontcollection_GetFontFamily(IDWriteFontCollection *iface, UINT32 index, IDWriteFontFamily **family)
Definition: layout.c:4919
static IUnknown * create_test_effect(void)
Definition: layout.c:1265
static void test_HitTestTextRange(void)
Definition: layout.c:6992
static UINT32 WINAPI fontcollection_GetFontFamilyCount(IDWriteFontCollection *iface)
Definition: layout.c:4913
static void _expect_ref(IUnknown *obj, ULONG ref, int line)
Definition: layout.c:635
static HRESULT WINAPI testrenderer_DrawStrikethrough(IDWriteTextRenderer *iface, void *context, FLOAT baselineOriginX, FLOAT baselineOriginY, DWRITE_STRIKETHROUGH const *strikethrough, IUnknown *effect)
Definition: layout.c:1032
static const IDWriteFontCollectionVtbl fallbackcollectionvtbl
Definition: layout.c:4963
static void test_SetFontStyle(void)
Definition: layout.c:3397
static void test_text_format_axes(void)
Definition: layout.c:6495
static HRESULT WINAPI testinlineobj_Draw(IDWriteInlineObject *iface, void *client_drawingontext, IDWriteTextRenderer *renderer, FLOAT originX, FLOAT originY, BOOL is_sideways, BOOL is_rtl, IUnknown *drawing_effect)
Definition: layout.c:1128
static HRESULT WINAPI testrenderer_QI(IDWriteTextRenderer *iface, REFIID riid, void **obj)
Definition: layout.c:854
static void test_GetLineMetrics(void)
Definition: layout.c:3971
static void utf32_to_utf16(UINT32 C, WCHAR **ptr)
Definition: layout.c:4999
static HRESULT create_enumerator(IDWriteFontFile *file, IDWriteFontFileEnumerator **ret)
Definition: layout.c:116
static HRESULT WINAPI singlefontfileenumerator_QueryInterface(IDWriteFontFileEnumerator *iface, REFIID riid, void **obj)
Definition: layout.c:46
static void test_GetOverhangMetrics(void)
Definition: layout.c:6247
static ULONG WINAPI resourcefontfileloader_AddRef(IDWriteFontFileLoader *iface)
Definition: layout.c:261
static void test_SetUnderline(void)
Definition: layout.c:5876
static struct test_inline_obj * create_test_inline_object(const IDWriteInlineObjectVtbl *vtable)
Definition: layout.c:1183
static HRESULT WINAPI analysissink_SetNumberSubstitution(IDWriteTextAnalysisSink *iface, UINT32 position, UINT32 length, IDWriteNumberSubstitution *substitution)
Definition: layout.c:454
static const struct IDWriteFontFileLoaderVtbl resourcefontfileloadervtbl
Definition: layout.c:296
static struct test_effect * test_effect_from_IUnknown(IUnknown *iface)
Definition: layout.c:1224
#define RENDERER_ID
Definition: layout.c:702
static const struct drawcall_entry draweffect2_seq[]
Definition: layout.c:3806
static FLOAT get_scaled_font_metric(UINT32 metric, FLOAT emSize, const DWRITE_FONT_METRICS *metrics)
Definition: layout.c:4652
static void test_SetLastLineWrapping(void)
Definition: layout.c:5731
static ULONG WINAPI fontdatastream_AddRef(IDWriteFontFileStream *iface)
Definition: layout.c:159
static struct resource_file_loader * impl_from_IDWriteFontFileLoader(IDWriteFontFileLoader *iface)
Definition: layout.c:245
static HRESULT WINAPI testrenderer_DrawUnderline(IDWriteTextRenderer *iface, void *context, FLOAT baselineOriginX, FLOAT baselineOriginY, DWRITE_UNDERLINE const *underline, IUnknown *effect)
Definition: layout.c:993
static void ok_sequence_(struct drawcall_sequence **seq, int sequence_index, const struct drawcall_entry *expected, const char *context, BOOL todo, const char *file, int line)
Definition: layout.c:741
static void add_call(struct drawcall_sequence **seq, int sequence_index, const struct drawcall_entry *call)
Definition: layout.c:706
static const struct drawcall_entry drawellipsis_seq[]
Definition: layout.c:1717
static ULONG WINAPI testrenderer_Release(IDWriteTextRenderer *iface)
Definition: layout.c:879
static HRESULT WINAPI testrenderer_GetPixelsPerDip(IDWriteTextRenderer *iface, void *context, FLOAT *pixels_per_dip)
Definition: layout.c:916
static ULONG WINAPI analysissource_AddRef(IDWriteTextAnalysisSource *iface)
Definition: layout.c:488
static HRESULT WINAPI resourcecollectionloader_QueryInterface(IDWriteFontCollectionLoader *iface, REFIID riid, void **obj)
Definition: layout.c:328
static HRESULT WINAPI analysissink_SetLineBreakpoints(IDWriteTextAnalysisSink *iface, UINT32 position, UINT32 length, DWRITE_LINE_BREAKPOINT const *breakpoints)
Definition: layout.c:440
static IDWriteTextAnalysisSourceVtbl analysissourcevtbl
Definition: layout.c:546
drawcall_modifiers_kind
Definition: layout.c:643
@ DRAW_EFFECT
Definition: layout.c:644
static const struct drawcall_entry draw_seq3[]
Definition: layout.c:2097
static ULONG WINAPI resourcecollectionloader_AddRef(IDWriteFontCollectionLoader *iface)
Definition: layout.c:340
static DWRITE_MATRIX layoutcreate_transforms[]
Definition: layout.c:1405
static const IDWriteInlineObjectVtbl testinlineobjvtbl3
Definition: layout.c:1208
static IDWriteFontCollectionLoader * create_resource_collection_loader(IDWriteFontFileLoader *loader)
Definition: layout.c:385
static void test_FontFallbackBuilder(void)
Definition: layout.c:5364
#define ok_sequence(seq, index, exp, contx, todo)
Definition: layout.c:851
static void test_SetFlowDirection(void)
Definition: layout.c:3750
static HRESULT WINAPI fontdatastream_QueryInterface(IDWriteFontFileStream *iface, REFIID riid, void **obj)
Definition: layout.c:147
static HRESULT WINAPI resourcefontfileloader_QueryInterface(IDWriteFontFileLoader *iface, REFIID riid, void **obj)
Definition: layout.c:250
static const struct drawcall_entry draw_seq5[]
Definition: layout.c:2110
static HRESULT WINAPI analysissource_GetTextAtPosition(IDWriteTextAnalysisSource *iface, UINT32 position, WCHAR const **text, UINT32 *text_len)
Definition: layout.c:500
static const struct drawcall_entry draw_single_run_seq[]
Definition: layout.c:2122
static IDWriteFactory * create_factory(void)
Definition: layout.c:566
static struct test_inline_obj * impl_from_IDWriteInlineObject(IDWriteInlineObject *iface)
Definition: layout.c:1094
static void WINAPI fontdatastream_ReleaseFileFragment(IDWriteFontFileStream *iface, void *fragment_context)
Definition: layout.c:195
#define EXPECT_REF(obj, ref)
Definition: layout.c:634
static const struct IDWriteFontCollectionLoaderVtbl resourcecollectionloadervtbl
Definition: layout.c:377
static const struct drawcall_entry draw_seq4[]
Definition: layout.c:2103
static HRESULT WINAPI testinlineobj_GetBreakConditions(IDWriteInlineObject *iface, DWRITE_BREAK_CONDITION *before, DWRITE_BREAK_CONDITION *after)
Definition: layout.c:1148
static void init_call_sequences(struct drawcall_sequence **seq, int n)
Definition: layout.c:733
static ULONG WINAPI fontcollection_AddRef(IDWriteFontCollection *iface)
Definition: layout.c:4903
#define NUM_CALL_SEQUENCES
Definition: layout.c:701
static HRESULT WINAPI testinlineobj_GetOverhangMetrics(IDWriteInlineObject *iface, DWRITE_OVERHANG_METRICS *overhangs)
Definition: layout.c:1142
static HRESULT WINAPI testinlineobj3_GetOverhangMetrics(IDWriteInlineObject *iface, DWRITE_OVERHANG_METRICS *overhangs)
Definition: layout.c:1200
static BOOL is_font_name_match(const WCHAR *name, const WCHAR *list)
Definition: layout.c:5293
static HRESULT WINAPI singlefontfileenumerator_MoveNext(IDWriteFontFileEnumerator *iface, BOOL *current)
Definition: layout.c:92
static void test_SetDrawingEffect(void)
Definition: layout.c:3822
static ULONG WINAPI analysissink_Release(IDWriteTextAnalysisSink *iface)
Definition: layout.c:427
static HRESULT WINAPI resourcefontfileloader_CreateStreamFromKey(IDWriteFontFileLoader *iface, const void *ref_key, UINT32 key_size, IDWriteFontFileStream **stream)
Definition: layout.c:278
static ULONG WINAPI testeffect_Release(IUnknown *iface)
Definition: layout.c:1248
static void test_SetInlineObject(void)
Definition: layout.c:1936
static HRESULT WINAPI analysissource_QueryInterface(IDWriteTextAnalysisSource *iface, REFIID riid, void **obj)
Definition: layout.c:477
static const struct drawcall_entry draweffect_seq[]
Definition: layout.c:3800
static HRESULT WINAPI analysissink_SetScriptAnalysis(IDWriteTextAnalysisSink *iface, UINT32 position, UINT32 length, DWRITE_SCRIPT_ANALYSIS const *sa)
Definition: layout.c:432
static const struct drawcall_entry draw_seq2[]
Definition: layout.c:2087
static HRESULT WINAPI fontdatastream_GetFileSize(IDWriteFontFileStream *iface, UINT64 *size)
Definition: layout.c:199
static void test_SetReadingDirection(void)
Definition: layout.c:4561
static const IDWriteFontFileStreamVtbl fontdatastreamvtbl
Definition: layout.c:211
static const WCHAR g_blahfontW[]
Definition: layout.c:4890
static FLOAT snap_coord(const DWRITE_MATRIX *m, FLOAT ppdip, FLOAT coord)
Definition: layout.c:4657
static void test_fallback(void)
Definition: layout.c:5563
static struct test_fontdatastream * impl_from_IDWriteFontFileStream(IDWriteFontFileStream *iface)
Definition: layout.c:142
static ULONG WINAPI fontcollection_Release(IDWriteFontCollection *iface)
Definition: layout.c:4908
static ULONG WINAPI testrenderer_AddRef(IDWriteTextRenderer *iface)
Definition: layout.c:874
static void test_system_fallback(void)
Definition: layout.c:5306
static const IDWriteInlineObjectVtbl testinlineobjvtbl
Definition: layout.c:1162
static HRESULT WINAPI testeffect_QI(IUnknown *iface, REFIID riid, void **obj)
Definition: layout.c:1229
static void get_font_name(IDWriteFont *font, WCHAR *name, UINT32 size)
Definition: layout.c:4975
static const IDWriteInlineObjectVtbl testinlineobjvtbl2
Definition: layout.c:1172
static struct drawcall_sequence * sequences[NUM_CALL_SEQUENCES]
Definition: layout.c:703
static void * create_factory_iid(REFIID riid)
Definition: layout.c:559
static void test_SetPairKerning(void)
Definition: layout.c:3013
static void test_DetermineMinWidth(void)
Definition: layout.c:3156
static HRESULT WINAPI singlefontfileenumerator_GetCurrentFontFile(IDWriteFontFileEnumerator *iface, IDWriteFontFile **file)
Definition: layout.c:77
static HRESULT WINAPI analysissource_GetLocaleName(IDWriteTextAnalysisSource *iface, UINT32 position, UINT32 *text_len, WCHAR const **locale)
Definition: layout.c:531
static void test_SetOpticalAlignment(void)
Definition: layout.c:5779
static const struct drawcall_entry draw_seq[]
Definition: layout.c:2071
static void test_SetLocaleName(void)
Definition: layout.c:2894
static const struct drawcall_entry empty_seq[]
Definition: layout.c:2118
static void test_SetTypography(void)
Definition: layout.c:5676
static struct snapping_test snapping_tests[]
Definition: layout.c:4710
static void get_script_analysis(const WCHAR *str, UINT32 len, DWRITE_SCRIPT_ANALYSIS *sa)
Definition: layout.c:575
static struct testanalysissink * impl_from_IDWriteTextAnalysisSink(IDWriteTextAnalysisSink *iface)
Definition: layout.c:404
static HRESULT WINAPI fontcollection_FindFamilyName(IDWriteFontCollection *iface, WCHAR const *name, UINT32 *index, BOOL *exists)
Definition: layout.c:4946
static void test_SetStrikethrough(void)
Definition: layout.c:3578
static void test_fontweight(void)
Definition: layout.c:1831
static ULONG WINAPI resourcefontfileloader_Release(IDWriteFontFileLoader *iface)
Definition: layout.c:267
static ULONG WINAPI analysissink_AddRef(IDWriteTextAnalysisSink *iface)
Definition: layout.c:422
static const struct drawcall_entry drawunderline2_seq[]
Definition: layout.c:5853
static struct resource_collection_loader * impl_from_IDWriteFontFileCollectionLoader(IDWriteFontCollectionLoader *iface)
Definition: layout.c:323
static HRESULT WINAPI testinlineobj2_GetBreakConditions(IDWriteInlineObject *iface, DWRITE_BREAK_CONDITION *before, DWRITE_BREAK_CONDITION *after)
Definition: layout.c:1155
static ULONG WINAPI testinlineobj_Release(IDWriteInlineObject *iface)
Definition: layout.c:1117
static void test_CreateTextLayout(void)
Definition: layout.c:1276
static HRESULT WINAPI testrenderer_DrawInlineObject(IDWriteTextRenderer *iface, void *context, FLOAT originX, FLOAT originY, IDWriteInlineObject *object, BOOL is_sideways, BOOL is_rtl, IUnknown *effect)
Definition: layout.c:1052
static void test_CreateTextFormat(void)
Definition: layout.c:1533
static const struct drawcall_entry draw_ltr_reordered_run_seq[]
Definition: layout.c:2127
static void test_automatic_font_axes(void)
Definition: layout.c:6405
static IDWriteTextAnalysisSinkVtbl analysissinkvtbl
Definition: layout.c:461
static IDWriteFontFace * get_fontface_from_format(IDWriteTextFormat *format)
Definition: layout.c:594
static void test_tab_stops(void)
Definition: layout.c:6322
static IDWriteFontFileLoader * create_resource_file_loader(void)
Definition: layout.c:304
static const IUnknownVtbl testeffectvtbl
Definition: layout.c:1259
static void test_SetFontFamilyName(void)
Definition: layout.c:3319
static HRESULT WINAPI analysissource_GetTextBeforePosition(IDWriteTextAnalysisSource *iface, UINT32 position, WCHAR const **text, UINT32 *text_len)
Definition: layout.c:517
static HRESULT WINAPI testrenderer_GetCurrentTransform(IDWriteTextRenderer *iface, void *context, DWRITE_MATRIX *m)
Definition: layout.c:907
static ULONG WINAPI singlefontfileenumerator_Release(IDWriteFontFileEnumerator *iface)
Definition: layout.c:63
static const struct IDWriteFontFileEnumeratorVtbl singlefontfileenumeratorvtbl
Definition: layout.c:107
static HRESULT WINAPI analysissink_QueryInterface(IDWriteTextAnalysisSink *iface, REFIID riid, void **obj)
Definition: layout.c:410
static HRESULT WINAPI testrenderer_DrawGlyphRun(IDWriteTextRenderer *iface, void *context, FLOAT baselineOriginX, FLOAT baselineOriginY, DWRITE_MEASURING_MODE mode, DWRITE_GLYPH_RUN const *run, DWRITE_GLYPH_RUN_DESCRIPTION const *descr, IUnknown *effect)
Definition: layout.c:937
static void test_measuring_mode(const struct renderer_context *ctxt, DWRITE_MEASURING_MODE mode, int line)
Definition: layout.c:925
static void test_GetClusterMetrics(void)
Definition: layout.c:2413
static const char * get_draw_kind_name(unsigned short kind)
Definition: layout.c:657
static HRESULT WINAPI fontcollection_GetFontFromFontFace(IDWriteFontCollection *iface, IDWriteFontFace *face, IDWriteFont **font)
Definition: layout.c:4957
static HRESULT WINAPI testinlineobj_QI(IDWriteInlineObject *iface, REFIID riid, void **obj)
Definition: layout.c:1099
static const WCHAR * g_source
Definition: layout.c:498
static void test_MapCharacters(void)
Definition: layout.c:5016
static struct test_fontenumerator * impl_from_IDWriteFontFileEnumerator(IDWriteFontFileEnumerator *iface)
Definition: layout.c:41
drawcall_kind
Definition: layout.c:647
@ DRAW_KINDS_MASK
Definition: layout.c:654
@ DRAW_LAST_KIND
Definition: layout.c:652
@ DRAW_UNDERLINE
Definition: layout.c:649
@ DRAW_GLYPHRUN
Definition: layout.c:648
@ DRAW_INLINE
Definition: layout.c:651
@ DRAW_STRIKETHROUGH
Definition: layout.c:650
@ DRAW_TOTAL_KINDS
Definition: layout.c:653
#define cmp(status, error)
Definition: error.c:118
static void * vtable[]
Definition: typelib.c:1500
static BOOL is_rtl(void)
Definition: editor.c:53
INTERNETFEATURELIST feature
Definition: misc.c:1807
WCHAR strW[12]
Definition: clipboard.c:2216
#define floorf(x)
Definition: mymath.h:65
Definition: mk_font.cpp:20
#define LOCALE_NAME_MAX_LENGTH
#define MAKEINTRESOURCE(i)
Definition: ntverrsrc.c:25
short WCHAR
Definition: pedump.c:58
#define RT_RCDATA
Definition: pedump.c:372
long LONG
Definition: pedump.c:60
#define IsEqualIID(riid1, riid2)
Definition: guiddef.h:95
#define REFIID
Definition: guiddef.h:118
#define calloc
Definition: rosglue.h:14
#define test
Definition: rosglue.h:37
const WCHAR * str
struct dirent *__cdecl readdir(DIR *)
wcscpy
static __inline const char * wine_dbgstr_guid(const GUID *id)
Definition: debug.h:181
const char * descr
Definition: boot.c:45
#define memset(x, y, z)
Definition: compat.h:39
weight
Definition: sortkey.c:157
static const char *static const char const char DWORD void DWORD *static const char const char DWORD void DWORD *static const char DWORD DWORD void * buff
Definition: shcore.c:41
DWRITE_FONT_AXIS_TAG axisTag
Definition: dwrite_3.idl:144
UINT16 designUnitsPerEm
Definition: dwrite.idl:353
IDWriteFontFace * fontFace
Definition: dwrite.idl:405
DWRITE_GLYPH_OFFSET const * glyphOffsets
Definition: dwrite.idl:410
UINT32 bidiLevel
Definition: dwrite.idl:412
FLOAT const * glyphAdvances
Definition: dwrite.idl:409
UINT32 glyphCount
Definition: dwrite.idl:407
DWRITE_FONT_LINE_GAP_USAGE fontLineGapUsage
Definition: dwrite_3.idl:879
DWRITE_LINE_SPACING_METHOD method
Definition: dwrite_3.idl:875
DWRITE_MEASURING_MODE measuringMode
Definition: dwrite.idl:448
DWRITE_TRIMMING_GRANULARITY granularity
Definition: dwrite.idl:394
UINT32 delimiter
Definition: dwrite.idl:395
UINT32 delimiterCount
Definition: dwrite.idl:396
WCHAR const * localeName
Definition: dwrite.idl:436
DWRITE_MEASURING_MODE measuringMode
Definition: dwrite.idl:437
Definition: polytest.cpp:36
Definition: http.c:7252
Definition: layout.c:678
enum drawcall_kind kind
Definition: layout.c:679
UINT32 bidilevel
Definition: layout.c:683
UINT32 glyphcount
Definition: layout.c:682
WCHAR locale[LOCALE_NAME_MAX_LENGTH]
Definition: layout.c:681
WCHAR string[10]
Definition: layout.c:680
struct drawcall_entry * sequence
Definition: layout.c:690
int * failcount
Definition: layout.c:696
const char * file
Definition: layout.c:697
unsigned short kind
Definition: layout.c:694
Definition: main.c:439
Definition: fci.c:123
Definition: copy.c:22
Definition: parser.c:49
Definition: loader.c:72
Definition: mem.c:349
Definition: name.c:39
Definition: send.c:48
DWRITE_MATRIX m
Definition: layout.c:888
const WCHAR * familyW
Definition: layout.c:893
FLOAT originX
Definition: layout.c:890
IDWriteTextFormat * format
Definition: layout.c:892
FLOAT originY
Definition: layout.c:891
BOOL gdicompat
Definition: layout.c:885
BOOL use_gdi_natural
Definition: layout.c:886
BOOL snapping_disabled
Definition: layout.c:887
IDWriteFontCollectionLoader IDWriteFontCollectionLoader_iface
Definition: layout.c:318
IDWriteFontFileLoader * loader
Definition: layout.c:320
IDWriteFontFileLoader IDWriteFontFileLoader_iface
Definition: layout.c:241
DWRITE_MATRIX m
Definition: layout.c:4706
FLOAT ppdip
Definition: layout.c:4707
Definition: parse.h:23
unsigned int size
Definition: parse.h:27
unsigned char * data
Definition: parse.h:26
Definition: style.c:91
LONG ref
Definition: layout.c:1221
IUnknown IUnknown_iface
Definition: layout.c:1220
IDWriteFontFileStream IDWriteFontFileStream_iface
Definition: font.c:751
IDWriteFontFileEnumerator IDWriteFontFileEnumerator_iface
Definition: font.c:603
IDWriteFontFile * file
Definition: layout.c:38
IDWriteInlineObject IDWriteInlineObject_iface
Definition: layout.c:1087
DWRITE_INLINE_OBJECT_METRICS metrics
Definition: layout.c:1090
DWRITE_OVERHANG_METRICS overhangs
Definition: layout.c:1091
DWRITE_SCRIPT_ANALYSIS sa
Definition: layout.c:401
IDWriteTextAnalysisSink IDWriteTextAnalysisSink_iface
Definition: layout.c:400
__inline int before(__u32 seq1, __u32 seq2)
Definition: tcpcore.h:2390
__inline int after(__u32 seq1, __u32 seq2)
Definition: tcpcore.h:2395
eMaj lines
Definition: tritemp.h:206
FT_UInt FT_UInt FT_Vector * kerning
Definition: ttdriver.c:206
const char * LPCSTR
Definition: typedefs.h:52
float FLOAT
Definition: typedefs.h:69
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t UINT32
Definition: typedefs.h:59
uint32_t ULONG
Definition: typedefs.h:59
Definition: pdh_main.c:64
#define WINAPI
Definition: msvc.h:6
static size_t align(size_t addr, size_t alignment)
#define DWRITE_E_FLOWDIRECTIONCONFLICTS
Definition: winerror.h:7345
#define E_NOT_SUFFICIENT_BUFFER
Definition: winerror.h:3437
#define E_NOINTERFACE
Definition: winerror.h:3479
unsigned char BYTE
Definition: xxhash.c:193