4 * Copyright 2012, 2014-2020 Nikolay Sivov for CodeWeavers
5 * Copyright 2014 Aric Stewart for CodeWeavers
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
33 #include "wine/heap.h"
34 #include "wine/test.h"
36 #define MS_CMAP_TAG DWRITE_MAKE_OPENTYPE_TAG('c','m','a','p')
37 #define MS_VDMX_TAG DWRITE_MAKE_OPENTYPE_TAG('V','D','M','X')
38 #define MS_GASP_TAG DWRITE_MAKE_OPENTYPE_TAG('g','a','s','p')
39 #define MS_CPAL_TAG DWRITE_MAKE_OPENTYPE_TAG('C','P','A','L')
40 #define MS_OS2_TAG DWRITE_MAKE_OPENTYPE_TAG('O','S','/','2')
41 #define MS_HEAD_TAG DWRITE_MAKE_OPENTYPE_TAG('h','e','a','d')
42 #define MS_HHEA_TAG DWRITE_MAKE_OPENTYPE_TAG('h','h','e','a')
43 #define MS_POST_TAG DWRITE_MAKE_OPENTYPE_TAG('p','o','s','t')
44 #define MS_GSUB_TAG DWRITE_MAKE_OPENTYPE_TAG('G','S','U','B')
45 #define MS_KERN_TAG DWRITE_MAKE_OPENTYPE_TAG('k','e','r','n')
46 #define MS_GLYF_TAG DWRITE_MAKE_OPENTYPE_TAG('g','l','y','f')
47 #define MS_CFF__TAG DWRITE_MAKE_OPENTYPE_TAG('C','F','F',' ')
48 #define MS_CFF2_TAG DWRITE_MAKE_OPENTYPE_TAG('C','F','F','2')
49 #define MS_COLR_TAG DWRITE_MAKE_OPENTYPE_TAG('C','O','L','R')
50 #define MS_SVG__TAG DWRITE_MAKE_OPENTYPE_TAG('S','V','G',' ')
51 #define MS_SBIX_TAG DWRITE_MAKE_OPENTYPE_TAG('s','b','i','x')
52 #define MS_MAXP_TAG DWRITE_MAKE_OPENTYPE_TAG('m','a','x','p')
53 #define MS_CBLC_TAG DWRITE_MAKE_OPENTYPE_TAG('C','B','L','C')
56 #define MS_PNG__TAG DWRITE_MAKE_OPENTYPE_TAG('p','n','g',' ')
57 #define MS_JPG__TAG DWRITE_MAKE_OPENTYPE_TAG('j','p','g',' ')
58 #define MS_TIFF_TAG DWRITE_MAKE_OPENTYPE_TAG('t','i','f','f')
60 #define MS_WOFF_TAG DWRITE_MAKE_OPENTYPE_TAG('w','O','F','F')
61 #define MS_WOF2_TAG DWRITE_MAKE_OPENTYPE_TAG('w','O','F','2')
63 #ifdef WORDS_BIGENDIAN
64 #define GET_BE_WORD(x) (x)
65 #define GET_BE_DWORD(x) (x)
66 #define GET_LE_WORD(x) RtlUshortByteSwap(x)
67 #define GET_LE_DWORD(x) RtlUlongByteSwap(x)
69 #define GET_BE_WORD(x) RtlUshortByteSwap(x)
70 #define GET_BE_DWORD(x) RtlUlongByteSwap(x)
71 #define GET_LE_WORD(x) (x)
72 #define GET_LE_DWORD(x) (x)
75 #define EXPECT_HR(hr,hr_exp) \
76 ok(hr == hr_exp, "got 0x%08x, expected 0x%08x\n", hr, hr_exp)
78 #define DEFINE_EXPECT(func) \
79 static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
81 #define SET_EXPECT(func) \
82 do { called_ ## func = FALSE; expect_ ## func = TRUE; } while(0)
84 #define CHECK_EXPECT2(func) \
86 ok(expect_ ##func, "unexpected call " #func "\n"); \
87 called_ ## func = TRUE; \
90 #define CHECK_EXPECT(func) \
92 CHECK_EXPECT2(func); \
93 expect_ ## func = FALSE; \
96 #define CHECK_CALLED(func) \
98 ok(called_ ## func, "expected " #func "\n"); \
99 expect_ ## func = called_ ## func = FALSE; \
102 #define CLEAR_CALLED(func) \
103 expect_ ## func = called_ ## func = FALSE
105 DEFINE_EXPECT(setfillmode
);
107 #define EXPECT_REF(obj,ref) _expect_ref((IUnknown*)obj, ref, __LINE__)
108 static void _expect_ref(IUnknown
* obj
, ULONG ref
, int line
)
111 IUnknown_AddRef(obj
);
112 rc
= IUnknown_Release(obj
);
113 ok_(__FILE__
,line
)(rc
== ref
, "expected refcount %d, got %d\n", ref
, rc
);
116 #define EXPECT_REF_BROKEN(obj,ref,brokenref) _expect_ref_broken((IUnknown*)obj, ref, brokenref, __LINE__)
117 static void _expect_ref_broken(IUnknown
* obj
, ULONG ref
, ULONG brokenref
, int line
)
120 IUnknown_AddRef(obj
);
121 rc
= IUnknown_Release(obj
);
122 ok_(__FILE__
,line
)(rc
== ref
|| broken(rc
== brokenref
), "expected refcount %d, got %d\n", ref
, rc
);
125 static BOOL (WINAPI
*pGetFontRealizationInfo
)(HDC hdc
, void *);
127 static const WCHAR test_fontfile
[] = L
"wine_test_font.ttf";
129 /* PANOSE is 10 bytes in size, need to pack the structure properly */
130 #include "pshpack2.h"
147 USHORT lowestRecPPEM
;
148 SHORT direction_hint
;
150 SHORT glyphdata_format
;
153 enum TT_HEAD_MACSTYLE
155 TT_HEAD_MACSTYLE_BOLD
= 1 << 0,
156 TT_HEAD_MACSTYLE_ITALIC
= 1 << 1,
157 TT_HEAD_MACSTYLE_UNDERLINE
= 1 << 2,
158 TT_HEAD_MACSTYLE_OUTLINE
= 1 << 3,
159 TT_HEAD_MACSTYLE_SHADOW
= 1 << 4,
160 TT_HEAD_MACSTYLE_CONDENSED
= 1 << 5,
161 TT_HEAD_MACSTYLE_EXTENDED
= 1 << 6,
168 USHORT usWeightClass
;
171 SHORT ySubscriptXSize
;
172 SHORT ySubscriptYSize
;
173 SHORT ySubscriptXOffset
;
174 SHORT ySubscriptYOffset
;
175 SHORT ySuperscriptXSize
;
176 SHORT ySuperscriptYSize
;
177 SHORT ySuperscriptXOffset
;
178 SHORT ySuperscriptYOffset
;
179 SHORT yStrikeoutSize
;
180 SHORT yStrikeoutPosition
;
183 ULONG ulUnicodeRange1
;
184 ULONG ulUnicodeRange2
;
185 ULONG ulUnicodeRange3
;
186 ULONG ulUnicodeRange4
;
189 USHORT usFirstCharIndex
;
190 USHORT usLastCharIndex
;
191 /* According to the Apple spec, original version didn't have the below fields,
192 * version numbers were taken from the OpenType spec.
194 /* version 0 (TrueType 1.5) */
195 USHORT sTypoAscender
;
196 USHORT sTypoDescender
;
200 /* version 1 (TrueType 1.66) */
201 ULONG ulCodePageRange1
;
202 ULONG ulCodePageRange2
;
203 /* version 2 (OpenType 1.2) */
206 USHORT usDefaultChar
;
211 enum OS2_FSSELECTION
{
212 OS2_FSSELECTION_ITALIC
= 1 << 0,
213 OS2_FSSELECTION_UNDERSCORE
= 1 << 1,
214 OS2_FSSELECTION_NEGATIVE
= 1 << 2,
215 OS2_FSSELECTION_OUTLINED
= 1 << 3,
216 OS2_FSSELECTION_STRIKEOUT
= 1 << 4,
217 OS2_FSSELECTION_BOLD
= 1 << 5,
218 OS2_FSSELECTION_REGULAR
= 1 << 6,
219 OS2_FSSELECTION_USE_TYPO_METRICS
= 1 << 7,
220 OS2_FSSELECTION_WWS
= 1 << 8,
221 OS2_FSSELECTION_OBLIQUE
= 1 << 9
227 SHORT underlinePosition
;
228 SHORT underlineThickness
;
242 USHORT advanceWidthMax
;
243 SHORT minLeftSideBearing
;
244 SHORT minRightSideBearing
;
246 SHORT caretSlopeRise
;
250 SHORT metricDataFormat
;
251 USHORT numberOfHMetrics
;
268 OT_FeatureRecord FeatureRecord
[1];
274 WORD LookupListIndex
[1];
293 } GSUB_SingleSubstFormat1
;
300 } GSUB_SingleSubstFormat2
;
304 WORD ExtensionLookupType
;
305 DWORD ExtensionOffset
;
306 } GSUB_ExtensionPosFormat1
;
312 DWORD strikeOffset
[1];
318 DWORD glyphDataOffsets
[1];
339 DWORD indexSubTableArrayOffset
;
340 DWORD indexTablesSize
;
341 DWORD numberofIndexSubTables
;
343 sbitLineMetrics hori
;
344 sbitLineMetrics vert
;
345 WORD startGlyphIndex
;
351 } CBLCBitmapSizeTable
;
370 ULONG metaOrigLength
;
383 ULONG totalCompressedSize
;
388 ULONG metaOrigLength
;
393 struct cmap_encoding_record
404 struct cmap_encoding_record tables
[1];
407 struct cmap_segmented_coverage_group
414 struct cmap_segmented_coverage
421 struct cmap_segmented_coverage_group groups
[1];
424 struct cmap_segmented_mapping_0
436 enum opentype_cmap_table_platform
438 OPENTYPE_CMAP_TABLE_PLATFORM_WIN
= 3,
441 enum opentype_cmap_table_encoding
443 OPENTYPE_CMAP_TABLE_ENCODING_SYMBOL
= 0,
444 OPENTYPE_CMAP_TABLE_ENCODING_UNICODE_BMP
= 1,
445 OPENTYPE_CMAP_TABLE_ENCODING_UNICODE_FULL
= 10,
448 enum opentype_cmap_table_format
450 OPENTYPE_CMAP_TABLE_SEGMENT_MAPPING
= 4,
451 OPENTYPE_CMAP_TABLE_SEGMENTED_COVERAGE
= 12,
456 static void *create_factory_iid(REFIID riid
)
458 IUnknown
*factory
= NULL
;
459 DWriteCreateFactory(DWRITE_FACTORY_TYPE_ISOLATED
, riid
, &factory
);
463 static IDWriteFactory
*create_factory(void)
465 IDWriteFactory
*factory
= create_factory_iid(&IID_IDWriteFactory
);
466 ok(factory
!= NULL
, "Failed to create factory.\n");
470 static IDWriteFontFace
*create_fontface(IDWriteFactory
*factory
)
472 IDWriteGdiInterop
*interop
;
473 IDWriteFontFace
*fontface
;
478 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop
);
479 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
481 memset(&logfont
, 0, sizeof(logfont
));
482 logfont
.lfHeight
= 12;
483 logfont
.lfWidth
= 12;
484 logfont
.lfWeight
= FW_NORMAL
;
485 logfont
.lfItalic
= 1;
486 lstrcpyW(logfont
.lfFaceName
, L
"Tahoma");
488 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font
);
489 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
491 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
492 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
494 IDWriteFont_Release(font
);
495 IDWriteGdiInterop_Release(interop
);
500 static IDWriteFont
*get_font(IDWriteFactory
*factory
, const WCHAR
*name
, DWRITE_FONT_STYLE style
)
502 IDWriteFontCollection
*collection
;
503 IDWriteFontFamily
*family
;
504 IDWriteFont
*font
= NULL
;
509 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &collection
, FALSE
);
510 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
514 hr
= IDWriteFontCollection_FindFamilyName(collection
, name
, &index
, &exists
);
515 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
516 if (!exists
) goto not_found
;
518 hr
= IDWriteFontCollection_GetFontFamily(collection
, index
, &family
);
519 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
521 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
,
522 DWRITE_FONT_STRETCH_NORMAL
, style
, &font
);
523 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
525 IDWriteFontFamily_Release(family
);
527 IDWriteFontCollection_Release(collection
);
531 static IDWriteFont
*get_tahoma_instance(IDWriteFactory
*factory
, DWRITE_FONT_STYLE style
)
533 IDWriteFont
*font
= get_font(factory
, L
"Tahoma", style
);
534 ok(font
!= NULL
, "failed to get Tahoma\n");
538 static WCHAR
*create_testfontfile(const WCHAR
*filename
)
540 static WCHAR pathW
[MAX_PATH
];
546 GetTempPathW(ARRAY_SIZE(pathW
), pathW
);
547 lstrcatW(pathW
, filename
);
549 file
= CreateFileW(pathW
, GENERIC_READ
|GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, 0);
550 ok(file
!= INVALID_HANDLE_VALUE
, "file creation failed, at %s, error %d\n", wine_dbgstr_w(pathW
),
553 res
= FindResourceA(GetModuleHandleA(NULL
), (LPCSTR
)MAKEINTRESOURCE(1), (LPCSTR
)RT_RCDATA
);
554 ok( res
!= 0, "couldn't find resource\n" );
555 ptr
= LockResource( LoadResource( GetModuleHandleA(NULL
), res
));
556 WriteFile( file
, ptr
, SizeofResource( GetModuleHandleA(NULL
), res
), &written
, NULL
);
557 ok( written
== SizeofResource( GetModuleHandleA(NULL
), res
), "couldn't write resource\n" );
563 #define DELETE_FONTFILE(filename) _delete_testfontfile(filename, __LINE__)
564 static void _delete_testfontfile(const WCHAR
*filename
, int line
)
566 BOOL ret
= DeleteFileW(filename
);
567 ok_(__FILE__
,line
)(ret
, "failed to delete file %s, error %d\n", wine_dbgstr_w(filename
), GetLastError());
570 static void get_combined_font_name(const WCHAR
*familyW
, const WCHAR
*faceW
, WCHAR
*nameW
)
572 lstrcpyW(nameW
, familyW
);
573 lstrcatW(nameW
, L
" ");
574 lstrcatW(nameW
, faceW
);
577 static BOOL
has_face_variations(IDWriteFontFace
*fontface
)
579 IDWriteFontFace5
*fontface5
;
582 if (SUCCEEDED(IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace5
, (void **)&fontface5
))) {
583 ret
= IDWriteFontFace5_HasVariations(fontface5
);
584 IDWriteFontFace5_Release(fontface5
);
590 #define check_familymodel(a,b) _check_familymodel(a,b,__LINE__)
591 static void _check_familymodel(void *iface_ptr
, DWRITE_FONT_FAMILY_MODEL expected_model
, unsigned int line
)
593 IDWriteFontCollection2
*collection
;
594 DWRITE_FONT_FAMILY_MODEL model
;
596 if (SUCCEEDED(IUnknown_QueryInterface((IUnknown
*)iface_ptr
, &IID_IDWriteFontCollection2
, (void **)&collection
)))
598 model
= IDWriteFontCollection2_GetFontFamilyModel(collection
);
599 ok_(__FILE__
,line
)(model
== expected_model
, "Unexpected family model %d, expected %d.\n", model
, expected_model
);
600 IDWriteFontCollection2_Release(collection
);
604 struct test_fontenumerator
606 IDWriteFontFileEnumerator IDWriteFontFileEnumerator_iface
;
610 IDWriteFontFile
*font_file
;
613 static inline struct test_fontenumerator
*impl_from_IDWriteFontFileEnumerator(IDWriteFontFileEnumerator
* iface
)
615 return CONTAINING_RECORD(iface
, struct test_fontenumerator
, IDWriteFontFileEnumerator_iface
);
618 static HRESULT WINAPI
singlefontfileenumerator_QueryInterface(IDWriteFontFileEnumerator
*iface
, REFIID riid
, void **obj
)
620 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFontFileEnumerator
))
623 IDWriteFontFileEnumerator_AddRef(iface
);
626 return E_NOINTERFACE
;
629 static ULONG WINAPI
singlefontfileenumerator_AddRef(IDWriteFontFileEnumerator
*iface
)
631 struct test_fontenumerator
*This
= impl_from_IDWriteFontFileEnumerator(iface
);
632 return InterlockedIncrement(&This
->ref
);
635 static ULONG WINAPI
singlefontfileenumerator_Release(IDWriteFontFileEnumerator
*iface
)
637 struct test_fontenumerator
*This
= impl_from_IDWriteFontFileEnumerator(iface
);
638 ULONG ref
= InterlockedDecrement(&This
->ref
);
640 IDWriteFontFile_Release(This
->font_file
);
646 static HRESULT WINAPI
singlefontfileenumerator_GetCurrentFontFile(IDWriteFontFileEnumerator
*iface
, IDWriteFontFile
**font_file
)
648 struct test_fontenumerator
*This
= impl_from_IDWriteFontFileEnumerator(iface
);
649 IDWriteFontFile_AddRef(This
->font_file
);
650 *font_file
= This
->font_file
;
654 static HRESULT WINAPI
singlefontfileenumerator_MoveNext(IDWriteFontFileEnumerator
*iface
, BOOL
*current
)
656 struct test_fontenumerator
*This
= impl_from_IDWriteFontFileEnumerator(iface
);
658 if (This
->index
> 1) {
668 static const struct IDWriteFontFileEnumeratorVtbl singlefontfileenumeratorvtbl
=
670 singlefontfileenumerator_QueryInterface
,
671 singlefontfileenumerator_AddRef
,
672 singlefontfileenumerator_Release
,
673 singlefontfileenumerator_MoveNext
,
674 singlefontfileenumerator_GetCurrentFontFile
677 static HRESULT
create_enumerator(IDWriteFontFile
*font_file
, IDWriteFontFileEnumerator
**ret
)
679 struct test_fontenumerator
*enumerator
;
681 enumerator
= heap_alloc(sizeof(struct test_fontenumerator
));
683 return E_OUTOFMEMORY
;
685 enumerator
->IDWriteFontFileEnumerator_iface
.lpVtbl
= &singlefontfileenumeratorvtbl
;
687 enumerator
->index
= 0;
688 enumerator
->font_file
= font_file
;
689 IDWriteFontFile_AddRef(font_file
);
691 *ret
= &enumerator
->IDWriteFontFileEnumerator_iface
;
695 struct test_fontcollectionloader
697 IDWriteFontCollectionLoader IDWriteFontFileCollectionLoader_iface
;
698 IDWriteFontFileLoader
*loader
;
701 static inline struct test_fontcollectionloader
*impl_from_IDWriteFontFileCollectionLoader(IDWriteFontCollectionLoader
* iface
)
703 return CONTAINING_RECORD(iface
, struct test_fontcollectionloader
, IDWriteFontFileCollectionLoader_iface
);
706 static HRESULT WINAPI
resourcecollectionloader_QueryInterface(IDWriteFontCollectionLoader
*iface
, REFIID riid
, void **obj
)
708 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFontCollectionLoader
))
711 IDWriteFontCollectionLoader_AddRef(iface
);
714 return E_NOINTERFACE
;
717 static ULONG WINAPI
resourcecollectionloader_AddRef(IDWriteFontCollectionLoader
*iface
)
722 static ULONG WINAPI
resourcecollectionloader_Release(IDWriteFontCollectionLoader
*iface
)
727 static HRESULT WINAPI
resourcecollectionloader_CreateEnumeratorFromKey(IDWriteFontCollectionLoader
*iface
, IDWriteFactory
*factory
,
728 const void * collectionKey
, UINT32 collectionKeySize
, IDWriteFontFileEnumerator
** fontFileEnumerator
)
730 struct test_fontcollectionloader
*This
= impl_from_IDWriteFontFileCollectionLoader(iface
);
731 IDWriteFontFile
*font_file
;
734 hr
= IDWriteFactory_CreateCustomFontFileReference(factory
, collectionKey
, collectionKeySize
, This
->loader
, &font_file
);
735 ok(hr
== S_OK
, "Failed to create custom file reference, hr %#x.\n", hr
);
737 hr
= create_enumerator(font_file
, fontFileEnumerator
);
738 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
740 IDWriteFontFile_Release(font_file
);
744 static const struct IDWriteFontCollectionLoaderVtbl resourcecollectionloadervtbl
= {
745 resourcecollectionloader_QueryInterface
,
746 resourcecollectionloader_AddRef
,
747 resourcecollectionloader_Release
,
748 resourcecollectionloader_CreateEnumeratorFromKey
751 /* Here is a functional custom font set of interfaces */
752 struct test_fontdatastream
754 IDWriteFontFileStream IDWriteFontFileStream_iface
;
761 static inline struct test_fontdatastream
*impl_from_IDWriteFontFileStream(IDWriteFontFileStream
* iface
)
763 return CONTAINING_RECORD(iface
, struct test_fontdatastream
, IDWriteFontFileStream_iface
);
766 static HRESULT WINAPI
fontdatastream_QueryInterface(IDWriteFontFileStream
*iface
, REFIID riid
, void **obj
)
768 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFontFileStream
))
771 IDWriteFontFileStream_AddRef(iface
);
775 return E_NOINTERFACE
;
778 static ULONG WINAPI
fontdatastream_AddRef(IDWriteFontFileStream
*iface
)
780 struct test_fontdatastream
*This
= impl_from_IDWriteFontFileStream(iface
);
781 ULONG ref
= InterlockedIncrement(&This
->ref
);
785 static ULONG WINAPI
fontdatastream_Release(IDWriteFontFileStream
*iface
)
787 struct test_fontdatastream
*This
= impl_from_IDWriteFontFileStream(iface
);
788 ULONG ref
= InterlockedDecrement(&This
->ref
);
790 HeapFree(GetProcessHeap(), 0, This
);
794 static HRESULT WINAPI
fontdatastream_ReadFileFragment(IDWriteFontFileStream
*iface
, void const **fragment_start
, UINT64 offset
, UINT64 fragment_size
, void **fragment_context
)
796 struct test_fontdatastream
*This
= impl_from_IDWriteFontFileStream(iface
);
797 *fragment_context
= NULL
;
798 if (offset
+fragment_size
> This
->size
)
800 *fragment_start
= NULL
;
805 *fragment_start
= (BYTE
*)This
->data
+ offset
;
810 static void WINAPI
fontdatastream_ReleaseFileFragment(IDWriteFontFileStream
*iface
, void *fragment_context
)
815 static HRESULT WINAPI
fontdatastream_GetFileSize(IDWriteFontFileStream
*iface
, UINT64
*size
)
817 struct test_fontdatastream
*This
= impl_from_IDWriteFontFileStream(iface
);
822 static HRESULT WINAPI
fontdatastream_GetLastWriteTime(IDWriteFontFileStream
*iface
, UINT64
*last_writetime
)
827 static const IDWriteFontFileStreamVtbl fontdatastreamvtbl
=
829 fontdatastream_QueryInterface
,
830 fontdatastream_AddRef
,
831 fontdatastream_Release
,
832 fontdatastream_ReadFileFragment
,
833 fontdatastream_ReleaseFileFragment
,
834 fontdatastream_GetFileSize
,
835 fontdatastream_GetLastWriteTime
838 static HRESULT
create_fontdatastream(LPVOID data
, UINT size
, IDWriteFontFileStream
** iface
)
840 struct test_fontdatastream
*This
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct test_fontdatastream
));
842 return E_OUTOFMEMORY
;
847 This
->IDWriteFontFileStream_iface
.lpVtbl
= &fontdatastreamvtbl
;
849 *iface
= &This
->IDWriteFontFileStream_iface
;
853 static HRESULT WINAPI
resourcefontfileloader_QueryInterface(IDWriteFontFileLoader
*iface
, REFIID riid
, void **obj
)
855 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFontFileLoader
))
861 return E_NOINTERFACE
;
864 static ULONG WINAPI
resourcefontfileloader_AddRef(IDWriteFontFileLoader
*iface
)
869 static ULONG WINAPI
resourcefontfileloader_Release(IDWriteFontFileLoader
*iface
)
874 static HRESULT WINAPI
resourcefontfileloader_CreateStreamFromKey(IDWriteFontFileLoader
*iface
, const void *ref_key
, UINT32 key_size
,
875 IDWriteFontFileStream
**stream
)
881 mem
= LoadResource(GetModuleHandleA(NULL
), *(HRSRC
*)ref_key
);
882 ok(mem
!= NULL
, "Failed to lock font resource\n");
885 size
= SizeofResource(GetModuleHandleA(NULL
), *(HRSRC
*)ref_key
);
886 data
= LockResource(mem
);
887 return create_fontdatastream(data
, size
, stream
);
892 static const struct IDWriteFontFileLoaderVtbl resourcefontfileloadervtbl
= {
893 resourcefontfileloader_QueryInterface
,
894 resourcefontfileloader_AddRef
,
895 resourcefontfileloader_Release
,
896 resourcefontfileloader_CreateStreamFromKey
899 static IDWriteFontFileLoader rloader
= { &resourcefontfileloadervtbl
};
901 static D2D1_POINT_2F g_startpoints
[2];
902 static int g_startpoint_count
;
904 static HRESULT WINAPI
test_geometrysink_QueryInterface(ID2D1SimplifiedGeometrySink
*iface
, REFIID riid
, void **ret
)
906 if (IsEqualIID(riid
, &IID_ID2D1SimplifiedGeometrySink
) ||
907 IsEqualIID(riid
, &IID_IUnknown
))
910 ID2D1SimplifiedGeometrySink_AddRef(iface
);
915 return E_NOINTERFACE
;
918 static ULONG WINAPI
test_geometrysink_AddRef(ID2D1SimplifiedGeometrySink
*iface
)
923 static ULONG WINAPI
test_geometrysink_Release(ID2D1SimplifiedGeometrySink
*iface
)
928 static void WINAPI
test_geometrysink_SetFillMode(ID2D1SimplifiedGeometrySink
*iface
, D2D1_FILL_MODE mode
)
930 CHECK_EXPECT(setfillmode
);
931 ok(mode
== D2D1_FILL_MODE_WINDING
, "fill mode %d\n", mode
);
934 static void WINAPI
test_geometrysink_SetSegmentFlags(ID2D1SimplifiedGeometrySink
*iface
, D2D1_PATH_SEGMENT flags
)
936 ok(0, "unexpected SetSegmentFlags() - flags %d\n", flags
);
939 static void WINAPI
test_geometrysink_BeginFigure(ID2D1SimplifiedGeometrySink
*iface
,
940 D2D1_POINT_2F startPoint
, D2D1_FIGURE_BEGIN figureBegin
)
942 ok(figureBegin
== D2D1_FIGURE_BEGIN_FILLED
, "begin figure %d\n", figureBegin
);
943 if (g_startpoint_count
< ARRAY_SIZE(g_startpoints
))
944 g_startpoints
[g_startpoint_count
] = startPoint
;
945 g_startpoint_count
++;
948 static void WINAPI
test_geometrysink_AddLines(ID2D1SimplifiedGeometrySink
*iface
,
949 const D2D1_POINT_2F
*points
, UINT32 count
)
953 static void WINAPI
test_geometrysink_AddBeziers(ID2D1SimplifiedGeometrySink
*iface
,
954 const D2D1_BEZIER_SEGMENT
*beziers
, UINT32 count
)
958 static void WINAPI
test_geometrysink_EndFigure(ID2D1SimplifiedGeometrySink
*iface
, D2D1_FIGURE_END figureEnd
)
960 ok(figureEnd
== D2D1_FIGURE_END_CLOSED
, "end figure %d\n", figureEnd
);
963 static HRESULT WINAPI
test_geometrysink_Close(ID2D1SimplifiedGeometrySink
*iface
)
965 ok(0, "unexpected Close()\n");
969 static const ID2D1SimplifiedGeometrySinkVtbl test_geometrysink_vtbl
= {
970 test_geometrysink_QueryInterface
,
971 test_geometrysink_AddRef
,
972 test_geometrysink_Release
,
973 test_geometrysink_SetFillMode
,
974 test_geometrysink_SetSegmentFlags
,
975 test_geometrysink_BeginFigure
,
976 test_geometrysink_AddLines
,
977 test_geometrysink_AddBeziers
,
978 test_geometrysink_EndFigure
,
979 test_geometrysink_Close
982 static void WINAPI
test_geometrysink2_BeginFigure(ID2D1SimplifiedGeometrySink
*iface
,
983 D2D1_POINT_2F startPoint
, D2D1_FIGURE_BEGIN figureBegin
)
985 ok(0, "unexpected call\n");
988 static void WINAPI
test_geometrysink2_AddLines(ID2D1SimplifiedGeometrySink
*iface
,
989 const D2D1_POINT_2F
*points
, UINT32 count
)
991 ok(0, "unexpected call\n");
994 static void WINAPI
test_geometrysink2_AddBeziers(ID2D1SimplifiedGeometrySink
*iface
,
995 const D2D1_BEZIER_SEGMENT
*beziers
, UINT32 count
)
997 ok(0, "unexpected call\n");
1000 static void WINAPI
test_geometrysink2_EndFigure(ID2D1SimplifiedGeometrySink
*iface
, D2D1_FIGURE_END figureEnd
)
1002 ok(0, "unexpected call\n");
1005 static const ID2D1SimplifiedGeometrySinkVtbl test_geometrysink2_vtbl
= {
1006 test_geometrysink_QueryInterface
,
1007 test_geometrysink_AddRef
,
1008 test_geometrysink_Release
,
1009 test_geometrysink_SetFillMode
,
1010 test_geometrysink_SetSegmentFlags
,
1011 test_geometrysink2_BeginFigure
,
1012 test_geometrysink2_AddLines
,
1013 test_geometrysink2_AddBeziers
,
1014 test_geometrysink2_EndFigure
,
1015 test_geometrysink_Close
1018 static ID2D1SimplifiedGeometrySink test_geomsink
= { &test_geometrysink_vtbl
};
1019 static ID2D1SimplifiedGeometrySink test_geomsink2
= { &test_geometrysink2_vtbl
};
1021 static void test_CreateFontFromLOGFONT(void)
1023 IDWriteGdiInterop1
*interop1
;
1024 IDWriteGdiInterop
*interop
;
1025 DWRITE_FONT_WEIGHT weight
;
1026 DWRITE_FONT_STYLE style
;
1029 LONG weights
[][2] = {
1030 {FW_NORMAL
, DWRITE_FONT_WEIGHT_NORMAL
},
1031 {FW_BOLD
, DWRITE_FONT_WEIGHT_BOLD
},
1032 { 0, DWRITE_FONT_WEIGHT_NORMAL
},
1033 { 50, DWRITE_FONT_WEIGHT_NORMAL
},
1034 {150, DWRITE_FONT_WEIGHT_NORMAL
},
1035 {250, DWRITE_FONT_WEIGHT_NORMAL
},
1036 {350, DWRITE_FONT_WEIGHT_NORMAL
},
1037 {450, DWRITE_FONT_WEIGHT_NORMAL
},
1038 {650, DWRITE_FONT_WEIGHT_BOLD
},
1039 {750, DWRITE_FONT_WEIGHT_BOLD
},
1040 {850, DWRITE_FONT_WEIGHT_BOLD
},
1041 {950, DWRITE_FONT_WEIGHT_BOLD
},
1042 {960, DWRITE_FONT_WEIGHT_BOLD
},
1044 OUTLINETEXTMETRICW otm
;
1045 IDWriteFactory
*factory
;
1055 factory
= create_factory();
1057 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop
);
1058 ok(hr
== S_OK
, "got %#x\n", hr
);
1061 /* null out parameter crashes this call */
1062 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, NULL
, NULL
);
1064 font
= (void*)0xdeadbeef;
1065 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, NULL
, &font
);
1066 EXPECT_HR(hr
, E_INVALIDARG
);
1067 ok(font
== NULL
, "got %p\n", font
);
1069 memset(&logfont
, 0, sizeof(logfont
));
1070 logfont
.lfHeight
= 12;
1071 logfont
.lfWidth
= 12;
1072 logfont
.lfWeight
= FW_NORMAL
;
1073 logfont
.lfItalic
= 1;
1074 lstrcpyW(logfont
.lfFaceName
, L
"Tahoma");
1076 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font
);
1077 EXPECT_HR(hr
, S_OK
);
1079 hfont
= CreateFontIndirectW(&logfont
);
1080 hdc
= CreateCompatibleDC(0);
1081 SelectObject(hdc
, hfont
);
1083 otm
.otmSize
= sizeof(otm
);
1084 r
= GetOutlineTextMetricsW(hdc
, otm
.otmSize
, &otm
);
1085 ok(r
, "got %d\n", r
);
1087 DeleteObject(hfont
);
1090 hr
= IDWriteFont_HasCharacter(font
, 0xd800, &exists
);
1091 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1092 ok(exists
== FALSE
, "got %d\n", exists
);
1095 hr
= IDWriteFont_HasCharacter(font
, 0x20, &exists
);
1096 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1097 ok(exists
== TRUE
, "got %d\n", exists
);
1099 /* now check properties */
1100 weight
= IDWriteFont_GetWeight(font
);
1101 ok(weight
== DWRITE_FONT_WEIGHT_NORMAL
, "got %d\n", weight
);
1103 style
= IDWriteFont_GetStyle(font
);
1104 ok(style
== DWRITE_FONT_STYLE_OBLIQUE
, "got %d\n", style
);
1105 ok(otm
.otmfsSelection
& 1, "got 0x%08x\n", otm
.otmfsSelection
);
1107 ret
= IDWriteFont_IsSymbolFont(font
);
1108 ok(!ret
, "got %d\n", ret
);
1110 IDWriteFont_Release(font
);
1113 for (i
= 0; i
< ARRAY_SIZE(weights
); i
++)
1115 memset(&logfont
, 0, sizeof(logfont
));
1116 logfont
.lfHeight
= 12;
1117 logfont
.lfWidth
= 12;
1118 logfont
.lfWeight
= weights
[i
][0];
1119 lstrcpyW(logfont
.lfFaceName
, L
"Tahoma");
1121 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font
);
1122 EXPECT_HR(hr
, S_OK
);
1124 weight
= IDWriteFont_GetWeight(font
);
1125 ok(weight
== weights
[i
][1],
1126 "%d: got %d, expected %d\n", i
, weight
, weights
[i
][1]);
1128 IDWriteFont_Release(font
);
1131 /* weight not from enum */
1132 memset(&logfont
, 0, sizeof(logfont
));
1133 logfont
.lfHeight
= 12;
1134 logfont
.lfWidth
= 12;
1135 logfont
.lfWeight
= 550;
1136 lstrcpyW(logfont
.lfFaceName
, L
"Tahoma");
1139 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font
);
1140 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1142 weight
= IDWriteFont_GetWeight(font
);
1143 ok(weight
== DWRITE_FONT_WEIGHT_NORMAL
|| weight
== DWRITE_FONT_WEIGHT_BOLD
,
1144 "got %d\n", weight
);
1146 IDWriteFont_Release(font
);
1148 /* empty or nonexistent face name */
1149 memset(&logfont
, 0, sizeof(logfont
));
1150 logfont
.lfHeight
= 12;
1151 logfont
.lfWidth
= 12;
1152 logfont
.lfWeight
= FW_NORMAL
;
1153 lstrcpyW(logfont
.lfFaceName
, L
"Blah!");
1155 font
= (void*)0xdeadbeef;
1156 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font
);
1157 ok(hr
== DWRITE_E_NOFONT
, "got 0x%08x\n", hr
);
1158 ok(font
== NULL
, "got %p\n", font
);
1160 /* Try with name 'Tahoma ' */
1161 memset(&logfont
, 0, sizeof(logfont
));
1162 logfont
.lfHeight
= 12;
1163 logfont
.lfWidth
= 12;
1164 logfont
.lfWeight
= FW_NORMAL
;
1165 lstrcpyW(logfont
.lfFaceName
, L
"Tahoma ");
1167 font
= (void*)0xdeadbeef;
1168 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font
);
1169 ok(hr
== DWRITE_E_NOFONT
, "got 0x%08x\n", hr
);
1170 ok(font
== NULL
, "got %p\n", font
);
1172 /* empty string as a facename */
1173 memset(&logfont
, 0, sizeof(logfont
));
1174 logfont
.lfHeight
= 12;
1175 logfont
.lfWidth
= 12;
1176 logfont
.lfWeight
= FW_NORMAL
;
1178 font
= (void*)0xdeadbeef;
1179 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font
);
1180 ok(hr
== DWRITE_E_NOFONT
, "got 0x%08x\n", hr
);
1181 ok(font
== NULL
, "got %p\n", font
);
1183 /* IDWriteGdiInterop1::CreateFontFromLOGFONT() */
1184 hr
= IDWriteGdiInterop_QueryInterface(interop
, &IID_IDWriteGdiInterop1
, (void**)&interop1
);
1186 memset(&logfont
, 0, sizeof(logfont
));
1187 logfont
.lfHeight
= 12;
1188 logfont
.lfWidth
= 12;
1189 logfont
.lfWeight
= FW_NORMAL
;
1190 logfont
.lfItalic
= 1;
1191 lstrcpyW(logfont
.lfFaceName
, L
"Tahoma");
1193 hr
= IDWriteGdiInterop1_CreateFontFromLOGFONT(interop1
, &logfont
, NULL
, &font
);
1194 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1196 IDWriteFont_Release(font
);
1197 IDWriteGdiInterop1_Release(interop1
);
1200 win_skip("IDWriteGdiInterop1 is not supported, skipping CreateFontFromLOGFONT() tests.\n");
1202 ref
= IDWriteGdiInterop_Release(interop
);
1203 ok(ref
== 0, "interop is not released, %u\n", ref
);
1204 ref
= IDWriteFactory_Release(factory
);
1205 ok(ref
== 0, "factory is not released, %u\n", ref
);
1208 static void test_CreateBitmapRenderTarget(void)
1210 IDWriteBitmapRenderTarget
*target
, *target2
;
1211 IDWriteBitmapRenderTarget1
*target1
;
1212 IDWriteRenderingParams
*params
;
1213 IDWriteGdiInterop
*interop
;
1214 IDWriteFontFace
*fontface
;
1215 IDWriteFactory
*factory
;
1216 DWRITE_GLYPH_RUN run
;
1231 factory
= create_factory();
1233 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop
);
1234 EXPECT_HR(hr
, S_OK
);
1237 hr
= IDWriteGdiInterop_CreateBitmapRenderTarget(interop
, NULL
, 0, 0, &target
);
1238 EXPECT_HR(hr
, S_OK
);
1240 if (0) /* crashes on native */
1241 hr
= IDWriteBitmapRenderTarget_GetSize(target
, NULL
);
1243 size
.cx
= size
.cy
= -1;
1244 hr
= IDWriteBitmapRenderTarget_GetSize(target
, &size
);
1245 EXPECT_HR(hr
, S_OK
);
1246 ok(size
.cx
== 0, "got %d\n", size
.cx
);
1247 ok(size
.cy
== 0, "got %d\n", size
.cy
);
1250 hr
= IDWriteGdiInterop_CreateBitmapRenderTarget(interop
, NULL
, 0, 0, &target2
);
1251 EXPECT_HR(hr
, S_OK
);
1252 ok(target
!= target2
, "got %p, %p\n", target2
, target
);
1253 IDWriteBitmapRenderTarget_Release(target2
);
1255 hdc
= IDWriteBitmapRenderTarget_GetMemoryDC(target
);
1256 ok(hdc
!= NULL
, "got %p\n", hdc
);
1259 ret
= GetGraphicsMode(hdc
);
1260 ok(ret
== GM_ADVANCED
, "got %d\n", ret
);
1262 hbm
= GetCurrentObject(hdc
, OBJ_BITMAP
);
1263 ok(hbm
!= NULL
, "got %p\n", hbm
);
1265 /* check DIB properties */
1266 ret
= GetObjectW(hbm
, sizeof(ds
), &ds
);
1267 ok(ret
== sizeof(BITMAP
), "got %d\n", ret
);
1268 ok(ds
.dsBm
.bmWidth
== 1, "got %d\n", ds
.dsBm
.bmWidth
);
1269 ok(ds
.dsBm
.bmHeight
== 1, "got %d\n", ds
.dsBm
.bmHeight
);
1270 ok(ds
.dsBm
.bmPlanes
== 1, "got %d\n", ds
.dsBm
.bmPlanes
);
1271 ok(ds
.dsBm
.bmBitsPixel
== 1, "got %d\n", ds
.dsBm
.bmBitsPixel
);
1272 ok(!ds
.dsBm
.bmBits
, "got %p\n", ds
.dsBm
.bmBits
);
1274 IDWriteBitmapRenderTarget_Release(target
);
1276 hbm
= GetCurrentObject(hdc
, OBJ_BITMAP
);
1277 ok(!hbm
, "got %p\n", hbm
);
1280 hr
= IDWriteGdiInterop_CreateBitmapRenderTarget(interop
, NULL
, 10, 5, &target
);
1281 EXPECT_HR(hr
, S_OK
);
1283 hdc
= IDWriteBitmapRenderTarget_GetMemoryDC(target
);
1284 ok(hdc
!= NULL
, "got %p\n", hdc
);
1286 /* test context settings */
1287 c
= GetTextColor(hdc
);
1288 ok(c
== RGB(0, 0, 0), "got 0x%08x\n", c
);
1289 ret
= GetBkMode(hdc
);
1290 ok(ret
== OPAQUE
, "got %d\n", ret
);
1291 c
= GetBkColor(hdc
);
1292 ok(c
== RGB(255, 255, 255), "got 0x%08x\n", c
);
1294 hbm
= GetCurrentObject(hdc
, OBJ_BITMAP
);
1295 ok(hbm
!= NULL
, "got %p\n", hbm
);
1297 /* check DIB properties */
1298 ret
= GetObjectW(hbm
, sizeof(ds
), &ds
);
1299 ok(ret
== sizeof(ds
), "got %d\n", ret
);
1300 ok(ds
.dsBm
.bmWidth
== 10, "got %d\n", ds
.dsBm
.bmWidth
);
1301 ok(ds
.dsBm
.bmHeight
== 5, "got %d\n", ds
.dsBm
.bmHeight
);
1302 ok(ds
.dsBm
.bmPlanes
== 1, "got %d\n", ds
.dsBm
.bmPlanes
);
1303 ok(ds
.dsBm
.bmBitsPixel
== 32, "got %d\n", ds
.dsBm
.bmBitsPixel
);
1304 ok(ds
.dsBm
.bmBits
!= NULL
, "got %p\n", ds
.dsBm
.bmBits
);
1306 size
.cx
= size
.cy
= -1;
1307 hr
= IDWriteBitmapRenderTarget_GetSize(target
, &size
);
1308 EXPECT_HR(hr
, S_OK
);
1309 ok(size
.cx
== 10, "got %d\n", size
.cx
);
1310 ok(size
.cy
== 5, "got %d\n", size
.cy
);
1312 /* resize to same size */
1313 hr
= IDWriteBitmapRenderTarget_Resize(target
, 10, 5);
1314 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1316 hbm2
= GetCurrentObject(hdc
, OBJ_BITMAP
);
1317 ok(hbm2
== hbm
, "got %p, %p\n", hbm2
, hbm
);
1320 hr
= IDWriteBitmapRenderTarget_Resize(target
, 5, 5);
1321 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1323 size
.cx
= size
.cy
= -1;
1324 hr
= IDWriteBitmapRenderTarget_GetSize(target
, &size
);
1325 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1326 ok(size
.cx
== 5, "got %d\n", size
.cx
);
1327 ok(size
.cy
== 5, "got %d\n", size
.cy
);
1329 hbm2
= GetCurrentObject(hdc
, OBJ_BITMAP
);
1330 ok(hbm2
!= hbm
, "got %p, %p\n", hbm2
, hbm
);
1332 hr
= IDWriteBitmapRenderTarget_Resize(target
, 20, 5);
1333 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1335 size
.cx
= size
.cy
= -1;
1336 hr
= IDWriteBitmapRenderTarget_GetSize(target
, &size
);
1337 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1338 ok(size
.cx
== 20, "got %d\n", size
.cx
);
1339 ok(size
.cy
== 5, "got %d\n", size
.cy
);
1341 hbm2
= GetCurrentObject(hdc
, OBJ_BITMAP
);
1342 ok(hbm2
!= hbm
, "got %p, %p\n", hbm2
, hbm
);
1344 hr
= IDWriteBitmapRenderTarget_Resize(target
, 1, 5);
1345 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1347 size
.cx
= size
.cy
= -1;
1348 hr
= IDWriteBitmapRenderTarget_GetSize(target
, &size
);
1349 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1350 ok(size
.cx
== 1, "got %d\n", size
.cx
);
1351 ok(size
.cy
== 5, "got %d\n", size
.cy
);
1353 hbm2
= GetCurrentObject(hdc
, OBJ_BITMAP
);
1354 ok(hbm2
!= hbm
, "got %p, %p\n", hbm2
, hbm
);
1356 ret
= GetObjectW(hbm2
, sizeof(ds
), &ds
);
1357 ok(ret
== sizeof(ds
), "got %d\n", ret
);
1358 ok(ds
.dsBm
.bmWidth
== 1, "got %d\n", ds
.dsBm
.bmWidth
);
1359 ok(ds
.dsBm
.bmHeight
== 5, "got %d\n", ds
.dsBm
.bmHeight
);
1360 ok(ds
.dsBm
.bmPlanes
== 1, "got %d\n", ds
.dsBm
.bmPlanes
);
1361 ok(ds
.dsBm
.bmBitsPixel
== 32, "got %d\n", ds
.dsBm
.bmBitsPixel
);
1362 ok(ds
.dsBm
.bmBits
!= NULL
, "got %p\n", ds
.dsBm
.bmBits
);
1364 /* empty rectangle */
1365 hr
= IDWriteBitmapRenderTarget_Resize(target
, 0, 5);
1366 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1368 size
.cx
= size
.cy
= -1;
1369 hr
= IDWriteBitmapRenderTarget_GetSize(target
, &size
);
1370 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1371 ok(size
.cx
== 0, "got %d\n", size
.cx
);
1372 ok(size
.cy
== 5, "got %d\n", size
.cy
);
1374 hbm2
= GetCurrentObject(hdc
, OBJ_BITMAP
);
1375 ok(hbm2
!= hbm
, "got %p, %p\n", hbm2
, hbm
);
1377 ret
= GetObjectW(hbm2
, sizeof(ds
), &ds
);
1378 ok(ret
== sizeof(BITMAP
), "got %d\n", ret
);
1379 ok(ds
.dsBm
.bmWidth
== 1, "got %d\n", ds
.dsBm
.bmWidth
);
1380 ok(ds
.dsBm
.bmHeight
== 1, "got %d\n", ds
.dsBm
.bmHeight
);
1381 ok(ds
.dsBm
.bmPlanes
== 1, "got %d\n", ds
.dsBm
.bmPlanes
);
1382 ok(ds
.dsBm
.bmBitsPixel
== 1, "got %d\n", ds
.dsBm
.bmBitsPixel
);
1383 ok(!ds
.dsBm
.bmBits
, "got %p\n", ds
.dsBm
.bmBits
);
1385 /* transform tests, current hdc transform is not immediately affected */
1386 if (0) /* crashes on native */
1387 hr
= IDWriteBitmapRenderTarget_GetCurrentTransform(target
, NULL
);
1389 memset(&m
, 0xcc, sizeof(m
));
1390 hr
= IDWriteBitmapRenderTarget_GetCurrentTransform(target
, &m
);
1391 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1392 ok(m
.m11
== 1.0 && m
.m22
== 1.0 && m
.m12
== 0.0 && m
.m21
== 0.0, "got %.1f,%.1f,%.1f,%.1f\n", m
.m11
, m
.m22
, m
.m12
, m
.m21
);
1393 ok(m
.dx
== 0.0 && m
.dy
== 0.0, "got %.1f,%.1f\n", m
.dx
, m
.dy
);
1394 ret
= GetWorldTransform(hdc
, &xform
);
1395 ok(ret
, "got %d\n", ret
);
1396 ok(xform
.eM11
== 1.0 && xform
.eM22
== 1.0 && xform
.eM12
== 0.0 && xform
.eM21
== 0.0, "got wrong transform\n");
1397 ok(xform
.eDx
== 0.0 && xform
.eDy
== 0.0, "got %.1f,%.1f\n", xform
.eDx
, xform
.eDy
);
1399 memset(&m
, 0, sizeof(m
));
1400 hr
= IDWriteBitmapRenderTarget_SetCurrentTransform(target
, &m
);
1401 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1403 memset(&m
, 0xcc, sizeof(m
));
1404 hr
= IDWriteBitmapRenderTarget_GetCurrentTransform(target
, &m
);
1405 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1406 ok(m
.m11
== 0.0 && m
.m22
== 0.0 && m
.m12
== 0.0 && m
.m21
== 0.0, "got %.1f,%.1f,%.1f,%.1f\n", m
.m11
, m
.m22
, m
.m12
, m
.m21
);
1407 ok(m
.dx
== 0.0 && m
.dy
== 0.0, "got %.1f,%.1f\n", m
.dx
, m
.dy
);
1408 ret
= GetWorldTransform(hdc
, &xform
);
1409 ok(ret
, "got %d\n", ret
);
1410 ok(xform
.eM11
== 1.0 && xform
.eM22
== 1.0 && xform
.eM12
== 0.0 && xform
.eM21
== 0.0, "got wrong transform\n");
1411 ok(xform
.eDx
== 0.0 && xform
.eDy
== 0.0, "got %.1f,%.1f\n", xform
.eDx
, xform
.eDy
);
1413 memset(&m
, 0, sizeof(m
));
1414 m
.m11
= 2.0; m
.m22
= 1.0;
1415 hr
= IDWriteBitmapRenderTarget_SetCurrentTransform(target
, &m
);
1416 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1417 ret
= GetWorldTransform(hdc
, &xform
);
1418 ok(ret
, "got %d\n", ret
);
1419 ok(xform
.eM11
== 1.0 && xform
.eM22
== 1.0 && xform
.eM12
== 0.0 && xform
.eM21
== 0.0, "got wrong transform\n");
1420 ok(xform
.eDx
== 0.0 && xform
.eDy
== 0.0, "got %.1f,%.1f\n", xform
.eDx
, xform
.eDy
);
1422 hr
= IDWriteBitmapRenderTarget_SetCurrentTransform(target
, NULL
);
1423 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1425 memset(&m
, 0xcc, sizeof(m
));
1426 hr
= IDWriteBitmapRenderTarget_GetCurrentTransform(target
, &m
);
1427 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1428 ok(m
.m11
== 1.0 && m
.m22
== 1.0 && m
.m12
== 0.0 && m
.m21
== 0.0, "got %.1f,%.1f,%.1f,%.1f\n", m
.m11
, m
.m22
, m
.m12
, m
.m21
);
1429 ok(m
.dx
== 0.0 && m
.dy
== 0.0, "got %.1f,%.1f\n", m
.dx
, m
.dy
);
1431 /* pixels per dip */
1432 pdip
= IDWriteBitmapRenderTarget_GetPixelsPerDip(target
);
1433 ok(pdip
== 1.0, "got %.2f\n", pdip
);
1435 hr
= IDWriteBitmapRenderTarget_SetPixelsPerDip(target
, 2.0);
1436 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1438 hr
= IDWriteBitmapRenderTarget_SetPixelsPerDip(target
, -1.0);
1439 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1441 hr
= IDWriteBitmapRenderTarget_SetPixelsPerDip(target
, 0.0);
1442 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1444 pdip
= IDWriteBitmapRenderTarget_GetPixelsPerDip(target
);
1445 ok(pdip
== 2.0, "got %.2f\n", pdip
);
1447 hr
= IDWriteBitmapRenderTarget_QueryInterface(target
, &IID_IDWriteBitmapRenderTarget1
, (void**)&target1
);
1449 DWRITE_TEXT_ANTIALIAS_MODE mode
;
1451 mode
= IDWriteBitmapRenderTarget1_GetTextAntialiasMode(target1
);
1452 ok(mode
== DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE
, "got %d\n", mode
);
1454 hr
= IDWriteBitmapRenderTarget1_SetTextAntialiasMode(target1
, DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
+1);
1455 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1457 mode
= IDWriteBitmapRenderTarget1_GetTextAntialiasMode(target1
);
1458 ok(mode
== DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE
, "got %d\n", mode
);
1460 hr
= IDWriteBitmapRenderTarget1_SetTextAntialiasMode(target1
, DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
);
1461 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1463 mode
= IDWriteBitmapRenderTarget1_GetTextAntialiasMode(target1
);
1464 ok(mode
== DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
, "got %d\n", mode
);
1466 IDWriteBitmapRenderTarget1_Release(target1
);
1469 win_skip("IDWriteBitmapRenderTarget1 is not supported.\n");
1471 /* DrawGlyphRun() argument validation. */
1472 hr
= IDWriteBitmapRenderTarget_Resize(target
, 16, 16);
1473 ok(hr
== S_OK
, "Failed to resize target, hr %#x.\n", hr
);
1475 fontface
= create_fontface(factory
);
1479 hr
= IDWriteFontFace_GetGlyphIndices(fontface
, &ch
, 1, glyphs
);
1480 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1481 ok(glyphs
[0] > 0, "got %u\n", glyphs
[0]);
1482 glyphs
[1] = glyphs
[0];
1484 memset(&run
, 0, sizeof(run
));
1485 run
.fontFace
= fontface
;
1486 run
.fontEmSize
= 12.0f
;
1488 run
.glyphIndices
= glyphs
;
1490 hr
= IDWriteFactory_CreateCustomRenderingParams(factory
, 1.0f
, 0.0f
, 0.0f
, DWRITE_PIXEL_GEOMETRY_FLAT
,
1491 DWRITE_RENDERING_MODE_DEFAULT
, ¶ms
);
1492 ok(hr
== S_OK
, "Failed to create rendering params, hr %#x.\n", hr
);
1494 hr
= IDWriteBitmapRenderTarget_DrawGlyphRun(target
, 0.0f
, 0.0f
, DWRITE_MEASURING_MODE_NATURAL
,
1495 &run
, NULL
, RGB(255, 0, 0), NULL
);
1496 ok(hr
== E_INVALIDARG
, "Unexpected hr %#x.\n", hr
);
1498 hr
= IDWriteBitmapRenderTarget_DrawGlyphRun(target
, 0.0f
, 0.0f
, DWRITE_MEASURING_MODE_GDI_NATURAL
+ 1,
1499 &run
, NULL
, RGB(255, 0, 0), NULL
);
1500 ok(hr
== E_INVALIDARG
, "Unexpected hr %#x.\n", hr
);
1502 hr
= IDWriteBitmapRenderTarget_DrawGlyphRun(target
, 0.0f
, 0.0f
, DWRITE_MEASURING_MODE_GDI_NATURAL
+ 1,
1503 &run
, params
, RGB(255, 0, 0), NULL
);
1504 ok(hr
== E_INVALIDARG
|| broken(hr
== S_OK
) /* Vista */, "Unexpected hr %#x.\n", hr
);
1506 hr
= IDWriteBitmapRenderTarget_DrawGlyphRun(target
, 0.0f
, 0.0f
, DWRITE_MEASURING_MODE_GDI_NATURAL
,
1507 &run
, params
, RGB(255, 0, 0), NULL
);
1508 ok(hr
== S_OK
, "Failed to draw a run, hr %#x.\n", hr
);
1510 IDWriteRenderingParams_Release(params
);
1512 /* Zero sized target returns earlier. */
1513 hr
= IDWriteBitmapRenderTarget_Resize(target
, 0, 16);
1514 ok(hr
== S_OK
, "Failed to resize target, hr %#x.\n", hr
);
1516 hr
= IDWriteBitmapRenderTarget_DrawGlyphRun(target
, 0.0f
, 0.0f
, DWRITE_MEASURING_MODE_NATURAL
,
1517 &run
, NULL
, RGB(255, 0, 0), NULL
);
1518 ok(hr
== S_OK
, "Unexpected hr %#x.\n", hr
);
1520 hr
= IDWriteBitmapRenderTarget_DrawGlyphRun(target
, 0.0f
, 0.0f
, DWRITE_MEASURING_MODE_GDI_NATURAL
+ 1,
1521 &run
, params
, RGB(255, 0, 0), NULL
);
1522 ok(hr
== S_OK
, "Unexpected hr %#x.\n", hr
);
1524 IDWriteFontFace_Release(fontface
);
1526 ref
= IDWriteBitmapRenderTarget_Release(target
);
1527 ok(ref
== 0, "render target not released, %u\n", ref
);
1528 ref
= IDWriteGdiInterop_Release(interop
);
1529 ok(ref
== 0, "interop not released, %u\n", ref
);
1530 ref
= IDWriteFactory_Release(factory
);
1531 ok(ref
== 0, "factory not released, %u\n", ref
);
1534 static void test_GetFontFamily(void)
1536 IDWriteFontCollection
*collection
, *collection2
;
1537 IDWriteFontCollection
*syscoll
;
1538 IDWriteFontCollection2
*coll2
;
1539 IDWriteFontFamily
*family
, *family2
;
1540 IDWriteFontFamily1
*family1
;
1541 IDWriteGdiInterop
*interop
;
1542 IDWriteFont
*font
, *font2
;
1543 IDWriteFactory
*factory
;
1548 factory
= create_factory();
1550 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop
);
1551 EXPECT_HR(hr
, S_OK
);
1553 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &syscoll
, FALSE
);
1554 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1556 memset(&logfont
, 0, sizeof(logfont
));
1557 logfont
.lfHeight
= 12;
1558 logfont
.lfWidth
= 12;
1559 logfont
.lfWeight
= FW_NORMAL
;
1560 logfont
.lfItalic
= 1;
1561 lstrcpyW(logfont
.lfFaceName
, L
"Tahoma");
1563 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font
);
1564 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1566 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font2
);
1567 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1568 ok(font2
!= font
, "got %p, %p\n", font2
, font
);
1570 if (0) /* crashes on native */
1571 hr
= IDWriteFont_GetFontFamily(font
, NULL
);
1573 EXPECT_REF(font
, 1);
1574 hr
= IDWriteFont_GetFontFamily(font
, &family
);
1575 EXPECT_HR(hr
, S_OK
);
1576 EXPECT_REF(font
, 1);
1577 EXPECT_REF(family
, 2);
1579 hr
= IDWriteFont_GetFontFamily(font
, &family2
);
1580 EXPECT_HR(hr
, S_OK
);
1581 ok(family2
== family
, "got %p, previous %p\n", family2
, family
);
1582 EXPECT_REF(font
, 1);
1583 EXPECT_REF(family
, 3);
1584 IDWriteFontFamily_Release(family2
);
1586 hr
= IDWriteFont_QueryInterface(font
, &IID_IDWriteFontFamily
, (void**)&family2
);
1587 EXPECT_HR(hr
, E_NOINTERFACE
);
1588 ok(family2
== NULL
, "got %p\n", family2
);
1590 hr
= IDWriteFont_GetFontFamily(font2
, &family2
);
1591 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1592 ok(family2
!= family
, "got %p, %p\n", family2
, family
);
1595 hr
= IDWriteFontFamily_GetFontCollection(family
, &collection
);
1596 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1599 hr
= IDWriteFontFamily_GetFontCollection(family2
, &collection2
);
1600 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1601 ok(collection
== collection2
, "got %p, %p\n", collection
, collection2
);
1602 ok(collection
== syscoll
, "got %p, %p\n", collection
, syscoll
);
1604 IDWriteFont_Release(font
);
1605 IDWriteFont_Release(font2
);
1607 hr
= IDWriteFontFamily_QueryInterface(family
, &IID_IDWriteFontFamily1
, (void**)&family1
);
1609 IDWriteFontFaceReference
*ref
, *ref1
;
1610 IDWriteFontList1
*fontlist1
;
1611 IDWriteFontList2
*fontlist2
;
1612 IDWriteFontList
*fontlist
;
1613 IDWriteFont3
*font3
;
1614 IDWriteFont1
*font1
;
1616 font3
= (void*)0xdeadbeef;
1617 hr
= IDWriteFontFamily1_GetFont(family1
, ~0u, &font3
);
1618 ok(hr
== E_FAIL
, "got 0x%08x\n", hr
);
1619 ok(font3
== NULL
, "got %p\n", font3
);
1621 hr
= IDWriteFontFamily1_GetFont(family1
, 0, &font3
);
1622 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1624 hr
= IDWriteFont3_QueryInterface(font3
, &IID_IDWriteFont
, (void**)&font
);
1625 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1626 IDWriteFont_Release(font
);
1628 hr
= IDWriteFont3_QueryInterface(font3
, &IID_IDWriteFont1
, (void**)&font1
);
1629 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1630 IDWriteFont1_Release(font1
);
1632 hr
= IDWriteFontFamily1_QueryInterface(family1
, &IID_IDWriteFontList1
, (void **)&fontlist1
);
1633 ok(hr
== S_OK
|| broken(hr
== E_NOINTERFACE
), "Failed to get interface, hr %#x.\n", hr
);
1635 hr
= IDWriteFontFamily1_QueryInterface(family1
, &IID_IDWriteFontList
, (void **)&fontlist
);
1636 ok(hr
== S_OK
, "Unexpected hr %#x.\n", hr
);
1637 ok(fontlist
== (IDWriteFontList
*)fontlist1
, "Unexpected interface pointer.\n");
1638 ok(fontlist
!= (IDWriteFontList
*)family1
, "Unexpected interface pointer.\n");
1639 ok(fontlist
!= (IDWriteFontList
*)family
, "Unexpected interface pointer.\n");
1641 if (SUCCEEDED(IDWriteFontFamily1_QueryInterface(family1
, &IID_IDWriteFontList2
, (void **)&fontlist2
)))
1643 IDWriteFontSet1
*fontset
= NULL
, *fontset2
= NULL
;
1645 ok(fontlist
== (IDWriteFontList
*)fontlist2
, "Unexpected interface pointer.\n");
1647 hr
= IDWriteFontList2_GetFontSet(fontlist2
, &fontset
);
1648 ok(hr
== S_OK
, "Unexpected hr %#x.\n", hr
);
1650 hr
= IDWriteFontList2_GetFontSet(fontlist2
, &fontset2
);
1651 ok(hr
== S_OK
, "Unexpected hr %#x.\n", hr
);
1652 ok(fontset
!= fontset2
, "Unexpected instance.\n");
1654 IDWriteFontSet1_Release(fontset2
);
1655 IDWriteFontSet1_Release(fontset
);
1657 IDWriteFontList2_Release(fontlist2
);
1660 win_skip("IDWriteFontList2 is not supported.\n");
1662 IDWriteFontList1_Release(fontlist1
);
1663 IDWriteFontList_Release(fontlist
);
1666 hr
= IDWriteFontFamily1_QueryInterface(family1
, &IID_IDWriteFontList
, (void**)&fontlist
);
1667 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1668 IDWriteFontList_Release(fontlist
);
1670 IDWriteFont3_Release(font3
);
1672 hr
= IDWriteFontFamily1_GetFontFaceReference(family1
, 0, &ref
);
1673 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1675 hr
= IDWriteFontFamily1_GetFontFaceReference(family1
, 0, &ref1
);
1676 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1677 ok(ref
!= ref1
, "got %p, %p\n", ref
, ref1
);
1679 IDWriteFontFaceReference_Release(ref
);
1680 IDWriteFontFaceReference_Release(ref1
);
1682 IDWriteFontFamily1_Release(family1
);
1685 win_skip("IDWriteFontFamily1 is not supported.\n");
1687 /* IDWriteFontCollection2::GetFontFamily() */
1688 if (SUCCEEDED(IDWriteFontCollection_QueryInterface(syscoll
, &IID_IDWriteFontCollection2
, (void **)&coll2
)))
1690 IDWriteFontFamily2
*family2
;
1692 count
= IDWriteFontCollection2_GetFontFamilyCount(coll2
);
1693 ok(!!count
, "Unexpected family count.\n");
1695 family2
= (void *)0xdeadbeef;
1696 hr
= IDWriteFontCollection2_GetFontFamily(coll2
, count
, &family2
);
1697 ok(hr
== E_FAIL
, "Unexpected hr %#x.\n", hr
);
1698 ok(!family2
, "Unexpected pointer.\n");
1700 hr
= IDWriteFontCollection2_GetFontFamily(coll2
, 0, &family2
);
1701 ok(hr
== S_OK
, "Failed to get family, hr %#x.\n", hr
);
1702 IDWriteFontFamily2_Release(family2
);
1704 IDWriteFontCollection2_Release(coll2
);
1707 win_skip("IDWriteFontCollection2 is not supported.\n");
1709 IDWriteFontCollection_Release(syscoll
);
1710 IDWriteFontCollection_Release(collection2
);
1711 IDWriteFontCollection_Release(collection
);
1712 IDWriteFontFamily_Release(family2
);
1713 IDWriteFontFamily_Release(family
);
1714 IDWriteGdiInterop_Release(interop
);
1715 ref
= IDWriteFactory_Release(factory
);
1716 ok(ref
== 0, "factory not released, %u\n", ref
);
1719 static void test_GetFamilyNames(void)
1721 IDWriteLocalizedStrings
*names
, *names2
;
1722 IDWriteFontFace3
*fontface3
;
1723 IDWriteGdiInterop
*interop
;
1724 IDWriteFontFamily
*family
;
1725 IDWriteFontFace
*fontface
;
1726 IDWriteFactory
*factory
;
1734 factory
= create_factory();
1736 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop
);
1737 EXPECT_HR(hr
, S_OK
);
1739 memset(&logfont
, 0, sizeof(logfont
));
1740 logfont
.lfHeight
= 12;
1741 logfont
.lfWidth
= 12;
1742 logfont
.lfWeight
= FW_NORMAL
;
1743 logfont
.lfItalic
= 1;
1744 lstrcpyW(logfont
.lfFaceName
, L
"Tahoma");
1746 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font
);
1747 EXPECT_HR(hr
, S_OK
);
1749 hr
= IDWriteFont_GetFontFamily(font
, &family
);
1750 EXPECT_HR(hr
, S_OK
);
1752 if (0) /* crashes on native */
1753 hr
= IDWriteFontFamily_GetFamilyNames(family
, NULL
);
1755 hr
= IDWriteFontFamily_GetFamilyNames(family
, &names
);
1756 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1757 EXPECT_REF(names
, 1);
1759 hr
= IDWriteFontFamily_GetFamilyNames(family
, &names2
);
1760 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1761 EXPECT_REF(names2
, 1);
1762 ok(names
!= names2
, "got %p, was %p\n", names2
, names
);
1764 IDWriteLocalizedStrings_Release(names2
);
1766 /* GetStringLength */
1767 if (0) /* crashes on native */
1768 hr
= IDWriteLocalizedStrings_GetStringLength(names
, 0, NULL
);
1771 hr
= IDWriteLocalizedStrings_GetStringLength(names
, 10, &len
);
1772 ok(hr
== E_FAIL
, "got 0x%08x\n", hr
);
1773 ok(len
== (UINT32
)-1, "got %u\n", len
);
1776 hr
= IDWriteLocalizedStrings_GetStringLength(names
, 0, &len
);
1777 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1778 ok(len
> 0, "got %u\n", len
);
1781 hr
= IDWriteLocalizedStrings_GetString(names
, 0, NULL
, 0);
1782 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
1784 hr
= IDWriteLocalizedStrings_GetString(names
, 10, NULL
, 0);
1785 ok(FAILED(hr
), "Unexpected hr %#x.\n", hr
);
1788 hr
= IDWriteLocalizedStrings_GetString(names
, 0, NULL
, 100);
1791 hr
= IDWriteLocalizedStrings_GetString(names
, 10, buffer
, 100);
1792 ok(hr
== E_FAIL
, "got 0x%08x\n", hr
);
1793 ok(buffer
[0] == 0, "got %x\n", buffer
[0]);
1796 hr
= IDWriteLocalizedStrings_GetString(names
, 0, buffer
, len
-1);
1797 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
1798 ok(buffer
[0] == 0 || broken(buffer
[0] == 'T'), "Unexpected buffer contents, %#x.\n", buffer
[0]);
1801 hr
= IDWriteLocalizedStrings_GetString(names
, 0, buffer
, len
);
1802 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
1803 ok(buffer
[0] == 0 || broken(buffer
[0] == 'T'), "Unexpected buffer contents, %#x.\n", buffer
[0]);
1806 hr
= IDWriteLocalizedStrings_GetString(names
, 0, buffer
, len
+1);
1807 ok(hr
== S_OK
, "Failed to get a string, hr %#x.\n", hr
);
1808 ok(!lstrcmpW(buffer
, L
"Tahoma"), "Unexpected family name %s.\n", wine_dbgstr_w(buffer
));
1810 IDWriteLocalizedStrings_Release(names
);
1812 /* GetFamilyNames() on font face */
1813 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
1814 ok(hr
== S_OK
, "Failed to create fontface, hr %#x.\n", hr
);
1816 if (SUCCEEDED(IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace3
, (void **)&fontface3
)))
1818 hr
= IDWriteFontFace3_GetFamilyNames(fontface3
, &names
);
1819 ok(hr
== S_OK
, "Failed to get family names, hr %#x.\n", hr
);
1822 hr
= IDWriteLocalizedStrings_GetString(names
, 0, buffer
, len
+1);
1823 ok(hr
== S_OK
, "Failed to get a string, hr %#x.\n", hr
);
1824 ok(!lstrcmpW(buffer
, L
"Tahoma"), "Unexpected family name %s.\n", wine_dbgstr_w(buffer
));
1826 IDWriteLocalizedStrings_Release(names
);
1827 IDWriteFontFace3_Release(fontface3
);
1830 win_skip("IDWriteFontFace3::GetFamilyNames() is not supported.\n");
1832 IDWriteFontFace_Release(fontface
);
1834 IDWriteFontFamily_Release(family
);
1835 IDWriteFont_Release(font
);
1836 IDWriteGdiInterop_Release(interop
);
1837 ref
= IDWriteFactory_Release(factory
);
1838 ok(ref
== 0, "factory not released, %u\n", ref
);
1841 static void test_CreateFontFace(void)
1843 IDWriteFontFace
*fontface
, *fontface2
;
1844 IDWriteFontCollection
*collection
;
1845 DWRITE_FONT_FILE_TYPE file_type
;
1846 DWRITE_FONT_FACE_TYPE face_type
;
1847 IDWriteFontFace5
*fontface5
;
1848 IDWriteGdiInterop
*interop
;
1849 IDWriteFont
*font
, *font2
;
1850 IDWriteFontFamily
*family
;
1851 IDWriteFactory
*factory
;
1852 IDWriteFontFile
*file
;
1853 BOOL supported
, ret
;
1860 factory
= create_factory();
1862 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop
);
1863 EXPECT_HR(hr
, S_OK
);
1865 memset(&logfont
, 0, sizeof(logfont
));
1866 logfont
.lfHeight
= 12;
1867 logfont
.lfWidth
= 12;
1868 logfont
.lfWeight
= FW_NORMAL
;
1869 logfont
.lfItalic
= 1;
1870 lstrcpyW(logfont
.lfFaceName
, L
"Tahoma");
1873 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font
);
1874 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1877 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font2
);
1878 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1879 ok(font
!= font2
, "got %p, %p\n", font
, font2
);
1881 hr
= IDWriteFont_QueryInterface(font
, &IID_IDWriteFontFace
, (void**)&fontface
);
1882 ok(hr
== E_NOINTERFACE
, "got 0x%08x\n", hr
);
1884 if (0) /* crashes on native */
1885 hr
= IDWriteFont_CreateFontFace(font
, NULL
);
1888 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
1889 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1892 hr
= IDWriteFont_CreateFontFace(font
, &fontface2
);
1893 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1894 ok(fontface
== fontface2
, "got %p, was %p\n", fontface2
, fontface
);
1895 IDWriteFontFace_Release(fontface2
);
1898 hr
= IDWriteFont_CreateFontFace(font2
, &fontface2
);
1899 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1900 ok(fontface
== fontface2
, "got %p, was %p\n", fontface2
, fontface
);
1901 IDWriteFontFace_Release(fontface2
);
1903 IDWriteFont_Release(font2
);
1904 IDWriteFont_Release(font
);
1906 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFont
, (void**)&font
);
1907 ok(hr
== E_NOINTERFACE
|| broken(hr
== E_NOTIMPL
), "got 0x%08x\n", hr
);
1909 IDWriteFontFace_Release(fontface
);
1910 IDWriteGdiInterop_Release(interop
);
1912 /* Create from system collection */
1913 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &collection
, FALSE
);
1914 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1916 hr
= IDWriteFontCollection_GetFontFamily(collection
, 0, &family
);
1917 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1920 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
,
1921 DWRITE_FONT_STRETCH_NORMAL
, DWRITE_FONT_STYLE_NORMAL
, &font
);
1922 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1925 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
,
1926 DWRITE_FONT_STRETCH_NORMAL
, DWRITE_FONT_STYLE_NORMAL
, &font2
);
1927 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1928 ok(font
!= font2
, "got %p, %p\n", font
, font2
);
1931 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
1932 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1935 hr
= IDWriteFont_CreateFontFace(font2
, &fontface2
);
1936 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1937 ok(fontface
== fontface2
, "got %p, was %p\n", fontface2
, fontface
);
1939 /* Trivial equality test */
1940 if (SUCCEEDED(IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace5
, (void **)&fontface5
)))
1942 ret
= IDWriteFontFace5_Equals(fontface5
, fontface2
);
1943 ok(ret
, "Unexpected result %d.\n", ret
);
1944 IDWriteFontFace5_Release(fontface5
);
1947 IDWriteFontFace_Release(fontface
);
1948 IDWriteFontFace_Release(fontface2
);
1949 IDWriteFont_Release(font2
);
1950 IDWriteFont_Release(font
);
1951 IDWriteFontFamily_Release(family
);
1952 IDWriteFontCollection_Release(collection
);
1953 ref
= IDWriteFactory_Release(factory
);
1954 ok(ref
== 0, "factory not released, %u.\n", ref
);
1956 /* IDWriteFactory::CreateFontFace() */
1957 path
= create_testfontfile(test_fontfile
);
1958 factory
= create_factory();
1960 hr
= IDWriteFactory_CreateFontFileReference(factory
, path
, NULL
, &file
);
1961 ok(hr
== S_OK
, "got 0x%08x\n",hr
);
1964 file_type
= DWRITE_FONT_FILE_TYPE_UNKNOWN
;
1965 face_type
= DWRITE_FONT_FACE_TYPE_CFF
;
1967 hr
= IDWriteFontFile_Analyze(file
, &supported
, &file_type
, &face_type
, &count
);
1968 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1969 ok(supported
== TRUE
, "got %i\n", supported
);
1970 ok(file_type
== DWRITE_FONT_FILE_TYPE_TRUETYPE
, "got %i\n", file_type
);
1971 ok(face_type
== DWRITE_FONT_FACE_TYPE_TRUETYPE
, "got %i\n", face_type
);
1972 ok(count
== 1, "got %i\n", count
);
1974 /* invalid simulation flags */
1975 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_CFF
, 1, &file
, 0, ~0u, &fontface
);
1976 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1978 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_CFF
, 1, &file
, 0, 0xf, &fontface
);
1979 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1981 /* try mismatching face type, the one that's not supported */
1982 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_CFF
, 1, &file
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &fontface
);
1983 ok(hr
== DWRITE_E_FILEFORMAT
, "got 0x%08x\n", hr
);
1985 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_OPENTYPE_COLLECTION
, 1, &file
, 0,
1986 DWRITE_FONT_SIMULATIONS_NONE
, &fontface
);
1987 ok(hr
== DWRITE_E_FILEFORMAT
|| broken(hr
== E_FAIL
) /* < win10 */, "got 0x%08x\n", hr
);
1989 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_RAW_CFF
, 1, &file
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &fontface
);
1991 ok(hr
== DWRITE_E_UNSUPPORTEDOPERATION
|| broken(hr
== E_INVALIDARG
) /* older versions */, "got 0x%08x\n", hr
);
1993 fontface
= (void*)0xdeadbeef;
1994 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_TYPE1
, 1, &file
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &fontface
);
1995 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1996 ok(fontface
== NULL
, "got %p\n", fontface
);
1998 fontface
= (void*)0xdeadbeef;
1999 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_VECTOR
, 1, &file
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &fontface
);
2000 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
2001 ok(fontface
== NULL
, "got %p\n", fontface
);
2003 fontface
= (void*)0xdeadbeef;
2004 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_BITMAP
, 1, &file
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &fontface
);
2005 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
2006 ok(fontface
== NULL
, "got %p\n", fontface
);
2009 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_UNKNOWN
, 1, &file
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &fontface
);
2011 ok(hr
== S_OK
|| broken(hr
== E_INVALIDARG
) /* < win10 */, "got 0x%08x\n", hr
);
2013 ok(fontface
!= NULL
, "got %p\n", fontface
);
2014 face_type
= IDWriteFontFace_GetType(fontface
);
2015 ok(face_type
== DWRITE_FONT_FACE_TYPE_TRUETYPE
, "got %d\n", face_type
);
2016 IDWriteFontFace_Release(fontface
);
2019 IDWriteFontFile_Release(file
);
2020 ref
= IDWriteFactory_Release(factory
);
2021 ok(ref
== 0, "factory not released, %u.\n", ref
);
2022 DELETE_FONTFILE(path
);
2025 static void get_expected_font_metrics(IDWriteFontFace
*fontface
, DWRITE_FONT_METRICS1
*metrics
)
2027 void *os2_context
, *head_context
, *post_context
, *hhea_context
;
2028 const TT_OS2_V2
*tt_os2
;
2029 const TT_HEAD
*tt_head
;
2030 const TT_POST
*tt_post
;
2031 const TT_HHEA
*tt_hhea
;
2036 memset(metrics
, 0, sizeof(*metrics
));
2038 hr
= IDWriteFontFace_TryGetFontTable(fontface
, MS_OS2_TAG
, (const void **)&tt_os2
, &size
, &os2_context
, &exists
);
2039 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2040 hr
= IDWriteFontFace_TryGetFontTable(fontface
, MS_HEAD_TAG
, (const void**)&tt_head
, &size
, &head_context
, &exists
);
2041 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2042 hr
= IDWriteFontFace_TryGetFontTable(fontface
, MS_HHEA_TAG
, (const void**)&tt_hhea
, &size
, &hhea_context
, &exists
);
2043 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2044 hr
= IDWriteFontFace_TryGetFontTable(fontface
, MS_POST_TAG
, (const void**)&tt_post
, &size
, &post_context
, &exists
);
2045 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2048 metrics
->designUnitsPerEm
= GET_BE_WORD(tt_head
->unitsPerEm
);
2049 metrics
->glyphBoxLeft
= GET_BE_WORD(tt_head
->xMin
);
2050 metrics
->glyphBoxTop
= GET_BE_WORD(tt_head
->yMax
);
2051 metrics
->glyphBoxRight
= GET_BE_WORD(tt_head
->xMax
);
2052 metrics
->glyphBoxBottom
= GET_BE_WORD(tt_head
->yMin
);
2056 if (GET_BE_WORD(tt_os2
->fsSelection
) & OS2_FSSELECTION_USE_TYPO_METRICS
) {
2057 SHORT descent
= GET_BE_WORD(tt_os2
->sTypoDescender
);
2058 metrics
->ascent
= GET_BE_WORD(tt_os2
->sTypoAscender
);
2059 metrics
->descent
= descent
< 0 ? -descent
: 0;
2060 metrics
->lineGap
= GET_BE_WORD(tt_os2
->sTypoLineGap
);
2061 metrics
->hasTypographicMetrics
= TRUE
;
2064 metrics
->ascent
= GET_BE_WORD(tt_os2
->usWinAscent
);
2065 /* Some fonts have usWinDescent value stored as signed short, which could be wrongly
2066 interpreted as large unsigned value. */
2067 metrics
->descent
= abs((SHORT
)GET_BE_WORD(tt_os2
->usWinDescent
));
2070 SHORT descender
= (SHORT
)GET_BE_WORD(tt_hhea
->descender
);
2073 linegap
= GET_BE_WORD(tt_hhea
->ascender
) + abs(descender
) + GET_BE_WORD(tt_hhea
->linegap
) -
2074 metrics
->ascent
- metrics
->descent
;
2075 metrics
->lineGap
= linegap
> 0 ? linegap
: 0;
2079 metrics
->strikethroughPosition
= GET_BE_WORD(tt_os2
->yStrikeoutPosition
);
2080 metrics
->strikethroughThickness
= GET_BE_WORD(tt_os2
->yStrikeoutSize
);
2082 metrics
->subscriptPositionX
= GET_BE_WORD(tt_os2
->ySubscriptXOffset
);
2083 metrics
->subscriptPositionY
= -GET_BE_WORD(tt_os2
->ySubscriptYOffset
);
2084 metrics
->subscriptSizeX
= GET_BE_WORD(tt_os2
->ySubscriptXSize
);
2085 metrics
->subscriptSizeY
= GET_BE_WORD(tt_os2
->ySubscriptYSize
);
2086 metrics
->superscriptPositionX
= GET_BE_WORD(tt_os2
->ySuperscriptXOffset
);
2087 metrics
->superscriptPositionY
= GET_BE_WORD(tt_os2
->ySuperscriptYOffset
);
2088 metrics
->superscriptSizeX
= GET_BE_WORD(tt_os2
->ySuperscriptXSize
);
2089 metrics
->superscriptSizeY
= GET_BE_WORD(tt_os2
->ySuperscriptYSize
);
2092 metrics
->strikethroughPosition
= metrics
->designUnitsPerEm
/ 3;
2094 metrics
->ascent
= GET_BE_WORD(tt_hhea
->ascender
);
2095 metrics
->descent
= abs((SHORT
)GET_BE_WORD(tt_hhea
->descender
));
2100 metrics
->underlinePosition
= GET_BE_WORD(tt_post
->underlinePosition
);
2101 metrics
->underlineThickness
= GET_BE_WORD(tt_post
->underlineThickness
);
2104 if (metrics
->underlineThickness
== 0)
2105 metrics
->underlineThickness
= metrics
->designUnitsPerEm
/ 14;
2106 if (metrics
->strikethroughThickness
== 0)
2107 metrics
->strikethroughThickness
= metrics
->underlineThickness
;
2110 IDWriteFontFace_ReleaseFontTable(fontface
, os2_context
);
2112 IDWriteFontFace_ReleaseFontTable(fontface
, head_context
);
2114 IDWriteFontFace_ReleaseFontTable(fontface
, hhea_context
);
2116 IDWriteFontFace_ReleaseFontTable(fontface
, post_context
);
2119 static void check_font_metrics(const WCHAR
*nameW
, IDWriteFontFace
*fontface
, const DWRITE_FONT_METRICS1
*expected
)
2121 IDWriteFontFace1
*fontface1
= NULL
;
2122 DWRITE_FONT_METRICS1 metrics
;
2126 has_metrics1
= SUCCEEDED(IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void **)&fontface1
));
2127 simulations
= IDWriteFontFace_GetSimulations(fontface
);
2130 IDWriteFontFace1_GetMetrics(fontface1
, &metrics
);
2131 IDWriteFontFace1_Release(fontface1
);
2134 IDWriteFontFace_GetMetrics(fontface
, (DWRITE_FONT_METRICS
*)&metrics
);
2136 ok(metrics
.designUnitsPerEm
== expected
->designUnitsPerEm
, "font %s: designUnitsPerEm %u, expected %u\n",
2137 wine_dbgstr_w(nameW
), metrics
.designUnitsPerEm
, expected
->designUnitsPerEm
);
2138 ok(metrics
.ascent
== expected
->ascent
, "font %s: ascent %u, expected %u\n", wine_dbgstr_w(nameW
), metrics
.ascent
,
2140 ok(metrics
.descent
== expected
->descent
, "font %s: descent %u, expected %u\n", wine_dbgstr_w(nameW
),
2141 metrics
.descent
, expected
->descent
);
2142 ok(metrics
.lineGap
== expected
->lineGap
, "font %s: lineGap %d, expected %d\n", wine_dbgstr_w(nameW
),
2143 metrics
.lineGap
, expected
->lineGap
);
2144 ok(metrics
.underlinePosition
== expected
->underlinePosition
, "font %s: underlinePosition %d, expected %d\n",
2145 wine_dbgstr_w(nameW
), metrics
.underlinePosition
, expected
->underlinePosition
);
2146 ok(metrics
.underlineThickness
== expected
->underlineThickness
, "font %s: underlineThickness %u, "
2147 "expected %u\n", wine_dbgstr_w(nameW
), metrics
.underlineThickness
, expected
->underlineThickness
);
2148 ok(metrics
.strikethroughPosition
== expected
->strikethroughPosition
, "font %s: strikethroughPosition %d, expected %d\n",
2149 wine_dbgstr_w(nameW
), metrics
.strikethroughPosition
, expected
->strikethroughPosition
);
2150 ok(metrics
.strikethroughThickness
== expected
->strikethroughThickness
, "font %s: strikethroughThickness %u, "
2151 "expected %u\n", wine_dbgstr_w(nameW
), metrics
.strikethroughThickness
, expected
->strikethroughThickness
);
2154 /* For simulated faces metrics are adjusted. Enable tests when exact pattern is understood. */
2155 if (simulations
& DWRITE_FONT_SIMULATIONS_OBLIQUE
)
2158 ok(metrics
.hasTypographicMetrics
== expected
->hasTypographicMetrics
, "font %s: hasTypographicMetrics %d, "
2159 "expected %d\n", wine_dbgstr_w(nameW
), metrics
.hasTypographicMetrics
, expected
->hasTypographicMetrics
);
2160 ok(metrics
.glyphBoxLeft
== expected
->glyphBoxLeft
, "font %s: glyphBoxLeft %d, expected %d\n",
2161 wine_dbgstr_w(nameW
), metrics
.glyphBoxLeft
, expected
->glyphBoxLeft
);
2162 ok(metrics
.glyphBoxTop
== expected
->glyphBoxTop
, "font %s: glyphBoxTop %d, expected %d\n",
2163 wine_dbgstr_w(nameW
), metrics
.glyphBoxTop
, expected
->glyphBoxTop
);
2164 ok(metrics
.glyphBoxRight
== expected
->glyphBoxRight
, "font %s: glyphBoxRight %d, expected %d\n",
2165 wine_dbgstr_w(nameW
), metrics
.glyphBoxRight
, expected
->glyphBoxRight
);
2166 ok(metrics
.glyphBoxBottom
== expected
->glyphBoxBottom
, "font %s: glyphBoxBottom %d, expected %d\n",
2167 wine_dbgstr_w(nameW
), metrics
.glyphBoxBottom
, expected
->glyphBoxBottom
);
2169 ok(metrics
.subscriptPositionX
== expected
->subscriptPositionX
, "font %s: subscriptPositionX %d, expected %d\n",
2170 wine_dbgstr_w(nameW
), metrics
.subscriptPositionX
, expected
->subscriptPositionX
);
2171 ok(metrics
.subscriptPositionY
== expected
->subscriptPositionY
, "font %s: subscriptPositionY %d, expected %d\n",
2172 wine_dbgstr_w(nameW
), metrics
.subscriptPositionY
, expected
->subscriptPositionY
);
2173 ok(metrics
.subscriptSizeX
== expected
->subscriptSizeX
, "font %s: subscriptSizeX %d, expected %d\n",
2174 wine_dbgstr_w(nameW
), metrics
.subscriptSizeX
, expected
->subscriptSizeX
);
2175 ok(metrics
.subscriptSizeY
== expected
->subscriptSizeY
, "font %s: subscriptSizeY %d, expected %d\n",
2176 wine_dbgstr_w(nameW
), metrics
.subscriptSizeY
, expected
->subscriptSizeY
);
2177 ok(metrics
.superscriptPositionX
== expected
->superscriptPositionX
, "font %s: superscriptPositionX %d, expected %d\n",
2178 wine_dbgstr_w(nameW
), metrics
.superscriptPositionX
, expected
->superscriptPositionX
);
2179 ok(metrics
.superscriptPositionY
== expected
->superscriptPositionY
, "font %s: superscriptPositionY %d, expected %d\n",
2180 wine_dbgstr_w(nameW
), metrics
.superscriptPositionY
, expected
->superscriptPositionY
);
2181 ok(metrics
.superscriptSizeX
== expected
->superscriptSizeX
, "font %s: superscriptSizeX %d, expected %d\n",
2182 wine_dbgstr_w(nameW
), metrics
.superscriptSizeX
, expected
->superscriptSizeX
);
2183 ok(metrics
.superscriptSizeY
== expected
->superscriptSizeY
, "font %s: superscriptSizeY %d, expected %d\n",
2184 wine_dbgstr_w(nameW
), metrics
.superscriptSizeY
, expected
->superscriptSizeY
);
2188 static void get_enus_string(IDWriteLocalizedStrings
*strings
, WCHAR
*buff
, UINT32 size
)
2190 BOOL exists
= FALSE
;
2194 hr
= IDWriteLocalizedStrings_FindLocaleName(strings
, L
"en-us", &index
, &exists
);
2195 ok(hr
== S_OK
, "Unexpected hr %#x.\n", hr
);
2198 hr
= IDWriteLocalizedStrings_GetString(strings
, index
, buff
, size
);
2199 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2202 static void test_GetMetrics(void)
2204 DWRITE_FONT_METRICS metrics
, metrics2
;
2205 IDWriteFontCollection
*syscollection
;
2206 IDWriteGdiInterop
*interop
;
2207 IDWriteFontFace
*fontface
;
2208 IDWriteFactory
*factory
;
2209 OUTLINETEXTMETRICW otm
;
2210 IDWriteFontFile
*file
;
2211 IDWriteFont1
*font1
;
2221 factory
= create_factory();
2223 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop
);
2224 EXPECT_HR(hr
, S_OK
);
2226 memset(&logfont
, 0, sizeof(logfont
));
2227 logfont
.lfHeight
= 12;
2228 logfont
.lfWidth
= 12;
2229 logfont
.lfWeight
= FW_NORMAL
;
2230 logfont
.lfItalic
= 1;
2231 lstrcpyW(logfont
.lfFaceName
, L
"Tahoma");
2233 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font
);
2234 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2236 hfont
= CreateFontIndirectW(&logfont
);
2237 hdc
= CreateCompatibleDC(0);
2238 SelectObject(hdc
, hfont
);
2240 otm
.otmSize
= sizeof(otm
);
2241 ret
= GetOutlineTextMetricsW(hdc
, otm
.otmSize
, &otm
);
2242 ok(ret
, "got %d\n", ret
);
2244 DeleteObject(hfont
);
2246 if (0) /* crashes on native */
2247 IDWriteFont_GetMetrics(font
, NULL
);
2249 memset(&metrics
, 0, sizeof(metrics
));
2250 IDWriteFont_GetMetrics(font
, &metrics
);
2252 ok(metrics
.designUnitsPerEm
!= 0, "designUnitsPerEm %u\n", metrics
.designUnitsPerEm
);
2253 ok(metrics
.ascent
!= 0, "ascent %u\n", metrics
.ascent
);
2254 ok(metrics
.descent
!= 0, "descent %u\n", metrics
.descent
);
2255 ok(metrics
.lineGap
== 0, "lineGap %d\n", metrics
.lineGap
);
2256 ok(metrics
.capHeight
, "capHeight %u\n", metrics
.capHeight
);
2257 ok(metrics
.xHeight
!= 0, "xHeight %u\n", metrics
.xHeight
);
2258 ok(metrics
.underlinePosition
< 0, "underlinePosition %d\n", metrics
.underlinePosition
);
2259 ok(metrics
.underlineThickness
!= 0, "underlineThickness %u\n", metrics
.underlineThickness
);
2260 ok(metrics
.strikethroughPosition
> 0, "strikethroughPosition %d\n", metrics
.strikethroughPosition
);
2261 ok(metrics
.strikethroughThickness
!= 0, "strikethroughThickness %u\n", metrics
.strikethroughThickness
);
2263 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
2264 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2266 memset(&metrics
, 0, sizeof(metrics
));
2267 IDWriteFontFace_GetMetrics(fontface
, &metrics
);
2269 ok(metrics
.designUnitsPerEm
!= 0, "designUnitsPerEm %u\n", metrics
.designUnitsPerEm
);
2270 ok(metrics
.ascent
!= 0, "ascent %u\n", metrics
.ascent
);
2271 ok(metrics
.descent
!= 0, "descent %u\n", metrics
.descent
);
2272 ok(metrics
.lineGap
== 0, "lineGap %d\n", metrics
.lineGap
);
2273 ok(metrics
.capHeight
, "capHeight %u\n", metrics
.capHeight
);
2274 ok(metrics
.xHeight
!= 0, "xHeight %u\n", metrics
.xHeight
);
2275 ok(metrics
.underlinePosition
< 0, "underlinePosition %d\n", metrics
.underlinePosition
);
2276 ok(metrics
.underlineThickness
!= 0, "underlineThickness %u\n", metrics
.underlineThickness
);
2277 ok(metrics
.strikethroughPosition
> 0, "strikethroughPosition %d\n", metrics
.strikethroughPosition
);
2278 ok(metrics
.strikethroughThickness
!= 0, "strikethroughThickness %u\n", metrics
.strikethroughThickness
);
2280 hr
= IDWriteFont_QueryInterface(font
, &IID_IDWriteFont1
, (void**)&font1
);
2282 DWRITE_FONT_METRICS1 metrics1
;
2283 IDWriteFontFace1
*fontface1
;
2285 memset(&metrics1
, 0, sizeof(metrics1
));
2286 IDWriteFont1_GetMetrics(font1
, &metrics1
);
2288 ok(metrics1
.designUnitsPerEm
!= 0, "designUnitsPerEm %u\n", metrics1
.designUnitsPerEm
);
2289 ok(metrics1
.ascent
!= 0, "ascent %u\n", metrics1
.ascent
);
2290 ok(metrics1
.descent
!= 0, "descent %u\n", metrics1
.descent
);
2291 ok(metrics1
.lineGap
== 0, "lineGap %d\n", metrics1
.lineGap
);
2292 ok(metrics1
.capHeight
, "capHeight %u\n", metrics1
.capHeight
);
2293 ok(metrics1
.xHeight
!= 0, "xHeight %u\n", metrics1
.xHeight
);
2294 ok(metrics1
.underlinePosition
< 0, "underlinePosition %d\n", metrics1
.underlinePosition
);
2295 ok(metrics1
.underlineThickness
!= 0, "underlineThickness %u\n", metrics1
.underlineThickness
);
2296 ok(metrics1
.strikethroughPosition
> 0, "strikethroughPosition %d\n", metrics1
.strikethroughPosition
);
2297 ok(metrics1
.strikethroughThickness
!= 0, "strikethroughThickness %u\n", metrics1
.strikethroughThickness
);
2298 ok(metrics1
.glyphBoxLeft
< 0, "glyphBoxLeft %d\n", metrics1
.glyphBoxLeft
);
2299 ok(metrics1
.glyphBoxTop
> 0, "glyphBoxTop %d\n", metrics1
.glyphBoxTop
);
2300 ok(metrics1
.glyphBoxRight
> 0, "glyphBoxRight %d\n", metrics1
.glyphBoxRight
);
2301 ok(metrics1
.glyphBoxBottom
< 0, "glyphBoxBottom %d\n", metrics1
.glyphBoxBottom
);
2302 ok(metrics1
.subscriptPositionY
< 0, "subscriptPositionY %d\n", metrics1
.subscriptPositionY
);
2303 ok(metrics1
.subscriptSizeX
> 0, "subscriptSizeX %d\n", metrics1
.subscriptSizeX
);
2304 ok(metrics1
.subscriptSizeY
> 0, "subscriptSizeY %d\n", metrics1
.subscriptSizeY
);
2305 ok(metrics1
.superscriptPositionY
> 0, "superscriptPositionY %d\n", metrics1
.superscriptPositionY
);
2306 ok(metrics1
.superscriptSizeX
> 0, "superscriptSizeX %d\n", metrics1
.superscriptSizeX
);
2307 ok(metrics1
.superscriptSizeY
> 0, "superscriptSizeY %d\n", metrics1
.superscriptSizeY
);
2308 ok(!metrics1
.hasTypographicMetrics
, "hasTypographicMetrics %d\n", metrics1
.hasTypographicMetrics
);
2310 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void**)&fontface1
);
2311 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2313 memset(&metrics1
, 0, sizeof(metrics1
));
2314 IDWriteFontFace1_GetMetrics(fontface1
, &metrics1
);
2316 ok(metrics1
.designUnitsPerEm
!= 0, "designUnitsPerEm %u\n", metrics1
.designUnitsPerEm
);
2317 ok(metrics1
.ascent
!= 0, "ascent %u\n", metrics1
.ascent
);
2318 ok(metrics1
.descent
!= 0, "descent %u\n", metrics1
.descent
);
2319 ok(metrics1
.lineGap
== 0, "lineGap %d\n", metrics1
.lineGap
);
2320 ok(metrics1
.capHeight
, "capHeight %u\n", metrics1
.capHeight
);
2321 ok(metrics1
.xHeight
!= 0, "xHeight %u\n", metrics1
.xHeight
);
2322 ok(metrics1
.underlinePosition
< 0, "underlinePosition %d\n", metrics1
.underlinePosition
);
2323 ok(metrics1
.underlineThickness
!= 0, "underlineThickness %u\n", metrics1
.underlineThickness
);
2324 ok(metrics1
.strikethroughPosition
> 0, "strikethroughPosition %d\n", metrics1
.strikethroughPosition
);
2325 ok(metrics1
.strikethroughThickness
!= 0, "strikethroughThickness %u\n", metrics1
.strikethroughThickness
);
2326 ok(metrics1
.glyphBoxLeft
< 0, "glyphBoxLeft %d\n", metrics1
.glyphBoxLeft
);
2327 ok(metrics1
.glyphBoxTop
> 0, "glyphBoxTop %d\n", metrics1
.glyphBoxTop
);
2328 ok(metrics1
.glyphBoxRight
> 0, "glyphBoxRight %d\n", metrics1
.glyphBoxRight
);
2329 ok(metrics1
.glyphBoxBottom
< 0, "glyphBoxBottom %d\n", metrics1
.glyphBoxBottom
);
2330 ok(metrics1
.subscriptPositionY
< 0, "subscriptPositionY %d\n", metrics1
.subscriptPositionY
);
2331 ok(metrics1
.subscriptSizeX
> 0, "subscriptSizeX %d\n", metrics1
.subscriptSizeX
);
2332 ok(metrics1
.subscriptSizeY
> 0, "subscriptSizeY %d\n", metrics1
.subscriptSizeY
);
2333 ok(metrics1
.superscriptPositionY
> 0, "superscriptPositionY %d\n", metrics1
.superscriptPositionY
);
2334 ok(metrics1
.superscriptSizeX
> 0, "superscriptSizeX %d\n", metrics1
.superscriptSizeX
);
2335 ok(metrics1
.superscriptSizeY
> 0, "superscriptSizeY %d\n", metrics1
.superscriptSizeY
);
2336 ok(!metrics1
.hasTypographicMetrics
, "hasTypographicMetrics %d\n", metrics1
.hasTypographicMetrics
);
2338 IDWriteFontFace1_Release(fontface1
);
2339 IDWriteFont1_Release(font1
);
2342 win_skip("DWRITE_FONT_METRICS1 is not supported.\n");
2344 IDWriteFontFace_Release(fontface
);
2345 IDWriteFont_Release(font
);
2346 IDWriteGdiInterop_Release(interop
);
2348 /* bold simulation affects returned font metrics */
2349 font
= get_tahoma_instance(factory
, DWRITE_FONT_STYLE_NORMAL
);
2351 /* create regulat Tahoma with bold simulation */
2352 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
2353 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2356 hr
= IDWriteFontFace_GetFiles(fontface
, &count
, &file
);
2357 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2359 IDWriteFontFace_GetMetrics(fontface
, &metrics
);
2360 ok(IDWriteFontFace_GetSimulations(fontface
) == 0, "wrong simulations flags\n");
2361 IDWriteFontFace_Release(fontface
);
2363 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_TRUETYPE
, 1, &file
,
2364 0, DWRITE_FONT_SIMULATIONS_BOLD
, &fontface
);
2365 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2366 IDWriteFontFace_GetMetrics(fontface
, &metrics2
);
2367 ok(IDWriteFontFace_GetSimulations(fontface
) == DWRITE_FONT_SIMULATIONS_BOLD
, "wrong simulations flags\n");
2369 ok(metrics
.ascent
== metrics2
.ascent
, "got %u, %u\n", metrics2
.ascent
, metrics
.ascent
);
2370 ok(metrics
.descent
== metrics2
.descent
, "got %u, %u\n", metrics2
.descent
, metrics
.descent
);
2371 ok(metrics
.lineGap
== metrics2
.lineGap
, "got %d, %d\n", metrics2
.lineGap
, metrics
.lineGap
);
2372 ok(metrics
.capHeight
== metrics2
.capHeight
, "got %u, %u\n", metrics2
.capHeight
, metrics
.capHeight
);
2373 ok(metrics
.xHeight
== metrics2
.xHeight
, "got %u, %u\n", metrics2
.xHeight
, metrics
.xHeight
);
2374 ok(metrics
.underlinePosition
== metrics2
.underlinePosition
, "got %d, %d\n", metrics2
.underlinePosition
,
2375 metrics
.underlinePosition
);
2376 ok(metrics
.underlineThickness
== metrics2
.underlineThickness
, "got %u, %u\n", metrics2
.underlineThickness
,
2377 metrics
.underlineThickness
);
2378 ok(metrics
.strikethroughPosition
== metrics2
.strikethroughPosition
, "got %d, %d\n", metrics2
.strikethroughPosition
,
2379 metrics
.strikethroughPosition
);
2380 ok(metrics
.strikethroughThickness
== metrics2
.strikethroughThickness
, "got %u, %u\n", metrics2
.strikethroughThickness
,
2381 metrics
.strikethroughThickness
);
2383 IDWriteFontFile_Release(file
);
2384 IDWriteFontFace_Release(fontface
);
2385 IDWriteFont_Release(font
);
2387 /* test metrics for whole system collection */
2388 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &syscollection
, FALSE
);
2389 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2390 count
= IDWriteFontCollection_GetFontFamilyCount(syscollection
);
2392 for (i
= 0; i
< count
; i
++) {
2393 DWRITE_FONT_METRICS1 expected_metrics
;
2394 WCHAR familyW
[256], faceW
[256];
2395 IDWriteLocalizedStrings
*names
;
2396 IDWriteFontFamily
*family
;
2397 UINT32 fontcount
, j
;
2400 hr
= IDWriteFontCollection_GetFontFamily(syscollection
, i
, &family
);
2401 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2403 fontcount
= IDWriteFontFamily_GetFontCount(family
);
2405 hr
= IDWriteFontFamily_GetFamilyNames(family
, &names
);
2406 ok(hr
== S_OK
, "Failed to get family names, hr %#x.\n", hr
);
2407 get_enus_string(names
, familyW
, ARRAY_SIZE(familyW
));
2408 IDWriteLocalizedStrings_Release(names
);
2410 for (j
= 0; j
< fontcount
; j
++) {
2413 hr
= IDWriteFontFamily_GetFont(family
, j
, &font
);
2414 ok(hr
== S_OK
, "Failed to get a font, hr %#x.\n", hr
);
2416 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
2417 ok(hr
== S_OK
, "Failed to create face instance, hr %#x.\n", hr
);
2419 hr
= IDWriteFont_GetFaceNames(font
, &names
);
2420 ok(hr
== S_OK
, "Failed to get face names, hr %#x.\n", hr
);
2421 get_enus_string(names
, faceW
, ARRAY_SIZE(faceW
));
2422 IDWriteLocalizedStrings_Release(names
);
2424 IDWriteFont_Release(font
);
2426 get_combined_font_name(familyW
, faceW
, nameW
);
2428 if (has_face_variations(fontface
))
2432 skip("GetMetrics() test does not support variable fonts.\n");
2433 IDWriteFontFace_Release(fontface
);
2437 get_expected_font_metrics(fontface
, &expected_metrics
);
2438 check_font_metrics(nameW
, fontface
, &expected_metrics
);
2440 IDWriteFontFace_Release(fontface
);
2443 IDWriteFontFamily_Release(family
);
2445 IDWriteFontCollection_Release(syscollection
);
2446 ref
= IDWriteFactory_Release(factory
);
2447 ok(ref
== 0, "factory not released, %u\n", ref
);
2450 static void test_system_fontcollection(void)
2452 IDWriteFontCollection
*collection
, *coll2
;
2453 IDWriteLocalFontFileLoader
*localloader
;
2454 IDWriteFontCollection1
*collection1
;
2455 IDWriteFontCollection2
*collection2
;
2456 IDWriteFontCollection3
*collection3
;
2457 IDWriteFactory
*factory
, *factory2
;
2458 IDWriteFontFileLoader
*loader
;
2459 IDWriteFontFamily
*family
;
2460 IDWriteFontFace
*fontface
;
2461 IDWriteFactory6
*factory6
;
2462 IDWriteFontFile
*file
;
2469 factory
= create_factory();
2471 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &collection
, FALSE
);
2472 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2474 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &coll2
, FALSE
);
2475 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2476 ok(coll2
== collection
, "got %p, was %p\n", coll2
, collection
);
2477 IDWriteFontCollection_Release(coll2
);
2479 factory2
= create_factory();
2480 hr
= IDWriteFactory_GetSystemFontCollection(factory2
, &coll2
, FALSE
);
2481 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2482 ok(coll2
!= collection
, "got %p, was %p\n", coll2
, collection
);
2483 IDWriteFontCollection_Release(coll2
);
2484 IDWriteFactory_Release(factory2
);
2486 i
= IDWriteFontCollection_GetFontFamilyCount(collection
);
2487 ok(i
, "got %u\n", i
);
2490 family
= (void*)0xdeadbeef;
2491 hr
= IDWriteFontCollection_GetFontFamily(collection
, i
, &family
);
2492 ok(hr
== E_FAIL
, "got 0x%08x\n", hr
);
2493 ok(family
== NULL
, "got %p\n", family
);
2497 hr
= IDWriteFontCollection_FindFamilyName(collection
, L
"Tahoma", &i
, &ret
);
2498 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2499 ok(ret
, "got %d\n", ret
);
2500 ok(i
!= (UINT32
)-1, "got %u\n", i
);
2504 hr
= IDWriteFontCollection_FindFamilyName(collection
, L
"TAHOMA", &i
, &ret
);
2505 ok(hr
== S_OK
, "Unexpected hr %#x.\n", hr
);
2506 ok(ret
, "got %d\n", ret
);
2507 ok(i
!= (UINT32
)-1, "got %u\n", i
);
2511 hr
= IDWriteFontCollection_FindFamilyName(collection
, L
"tAhOmA", &i
, &ret
);
2512 ok(hr
== S_OK
, "Unexpected hr %#x.\n", hr
);
2513 ok(ret
, "got %d\n", ret
);
2514 ok(i
!= (UINT32
)-1, "got %u\n", i
);
2516 /* get back local file loader */
2517 hr
= IDWriteFontCollection_GetFontFamily(collection
, i
, &family
);
2518 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2520 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
,
2521 DWRITE_FONT_STRETCH_NORMAL
, DWRITE_FONT_STYLE_NORMAL
, &font
);
2522 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2523 IDWriteFontFamily_Release(family
);
2525 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
2526 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2527 IDWriteFont_Release(font
);
2531 hr
= IDWriteFontFace_GetFiles(fontface
, &i
, &file
);
2532 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2533 ok(file
!= NULL
, "got %p\n", file
);
2534 IDWriteFontFace_Release(fontface
);
2536 hr
= IDWriteFontFile_GetLoader(file
, &loader
);
2537 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2538 IDWriteFontFile_Release(file
);
2540 hr
= IDWriteFontFileLoader_QueryInterface(loader
, &IID_IDWriteLocalFontFileLoader
, (void**)&localloader
);
2541 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2542 IDWriteLocalFontFileLoader_Release(localloader
);
2544 /* local loader is not registered by default */
2545 hr
= IDWriteFactory_RegisterFontFileLoader(factory
, loader
);
2546 ok(hr
== S_OK
|| broken(hr
== DWRITE_E_ALREADYREGISTERED
), "got 0x%08x\n", hr
);
2547 hr
= IDWriteFactory_UnregisterFontFileLoader(factory
, loader
);
2548 ok(hr
== S_OK
|| broken(hr
== E_INVALIDARG
), "got 0x%08x\n", hr
);
2550 /* try with a different factory */
2551 factory2
= create_factory();
2552 hr
= IDWriteFactory_RegisterFontFileLoader(factory2
, loader
);
2553 ok(hr
== S_OK
|| broken(hr
== DWRITE_E_ALREADYREGISTERED
), "got 0x%08x\n", hr
);
2554 hr
= IDWriteFactory_RegisterFontFileLoader(factory2
, loader
);
2555 ok(hr
== DWRITE_E_ALREADYREGISTERED
, "got 0x%08x\n", hr
);
2556 hr
= IDWriteFactory_UnregisterFontFileLoader(factory2
, loader
);
2557 ok(hr
== S_OK
|| broken(hr
== E_INVALIDARG
), "got 0x%08x\n", hr
);
2558 hr
= IDWriteFactory_UnregisterFontFileLoader(factory2
, loader
);
2559 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
2560 IDWriteFactory_Release(factory2
);
2562 IDWriteFontFileLoader_Release(loader
);
2566 hr
= IDWriteFontCollection_FindFamilyName(collection
, L
"Blah!", &i
, &ret
);
2567 ok(hr
== S_OK
, "Unexpected hr %#x.\n", hr
);
2568 ok(!ret
, "got %d\n", ret
);
2569 ok(i
== (UINT32
)-1, "got %u\n", i
);
2571 hr
= IDWriteFontCollection_QueryInterface(collection
, &IID_IDWriteFontCollection1
, (void**)&collection1
);
2573 IDWriteFontSet
*fontset
, *fontset2
;
2574 IDWriteFontFamily1
*family1
;
2575 IDWriteFactory3
*factory3
;
2577 hr
= IDWriteFontCollection1_QueryInterface(collection1
, &IID_IDWriteFontCollection
, (void**)&coll2
);
2578 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2579 ok(coll2
== collection
, "got %p, %p\n", collection
, coll2
);
2580 IDWriteFontCollection_Release(coll2
);
2582 family1
= (void*)0xdeadbeef;
2583 hr
= IDWriteFontCollection1_GetFontFamily(collection1
, ~0u, &family1
);
2584 ok(hr
== E_FAIL
, "got 0x%08x\n", hr
);
2585 ok(family1
== NULL
, "got %p\n", family1
);
2587 hr
= IDWriteFontCollection1_GetFontFamily(collection1
, 0, &family1
);
2588 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2589 IDWriteFontFamily1_Release(family1
);
2591 /* system fontset */
2592 EXPECT_REF(collection1
, 2);
2593 EXPECT_REF(factory
, 2);
2594 hr
= IDWriteFontCollection1_GetFontSet(collection1
, &fontset
);
2596 ok(hr
== S_OK
, "Failed to get fontset, hr %#x.\n", hr
);
2598 EXPECT_REF(collection1
, 2);
2599 EXPECT_REF(factory
, 2);
2600 EXPECT_REF(fontset
, 1);
2602 hr
= IDWriteFontCollection1_GetFontSet(collection1
, &fontset2
);
2603 ok(hr
== S_OK
, "Failed to get fontset, hr %#x.\n", hr
);
2604 ok(fontset
!= fontset2
, "Expected new fontset instance.\n");
2605 EXPECT_REF(fontset2
, 1);
2606 IDWriteFontSet_Release(fontset2
);
2608 hr
= IDWriteFactory_QueryInterface(factory
, &IID_IDWriteFactory3
, (void **)&factory3
);
2609 ok(hr
== S_OK
, "Failed to get IDWriteFactory3 interface, hr %#x.\n", hr
);
2611 EXPECT_REF(factory
, 3);
2612 hr
= IDWriteFactory3_GetSystemFontSet(factory3
, &fontset2
);
2613 ok(hr
== S_OK
, "Failed to get system font set, hr %#x.\n", hr
);
2614 ok(fontset
!= fontset2
, "Expected new fontset instance.\n");
2615 EXPECT_REF(fontset2
, 1);
2616 EXPECT_REF(factory
, 4);
2618 IDWriteFontSet_Release(fontset2
);
2619 IDWriteFontSet_Release(fontset
);
2621 IDWriteFactory3_Release(factory3
);
2623 IDWriteFontCollection1_Release(collection1
);
2626 win_skip("IDWriteFontCollection1 is not supported.\n");
2628 hr
= IDWriteFontCollection_QueryInterface(collection
, &IID_IDWriteFontCollection3
, (void **)&collection3
);
2633 event
= IDWriteFontCollection3_GetExpirationEvent(collection3
);
2635 ok(!!event
, "Expected event handle.\n");
2637 check_familymodel(collection3
, DWRITE_FONT_FAMILY_MODEL_WEIGHT_STRETCH_STYLE
);
2639 IDWriteFontCollection3_Release(collection3
);
2642 win_skip("IDWriteFontCollection3 is not supported.\n");
2644 /* With specified family model. */
2645 hr
= IDWriteFactory_QueryInterface(factory
, &IID_IDWriteFactory6
, (void **)&factory6
);
2648 IDWriteFontCollection2
*c2
;
2650 hr
= IDWriteFactory6_GetSystemFontCollection(factory6
, FALSE
, DWRITE_FONT_FAMILY_MODEL_TYPOGRAPHIC
,
2653 ok(hr
== S_OK
, "Failed to get collection, hr %#x.\n", hr
);
2656 hr
= IDWriteFactory6_GetSystemFontCollection(factory6
, FALSE
, DWRITE_FONT_FAMILY_MODEL_TYPOGRAPHIC
, &c2
);
2657 ok(hr
== S_OK
, "Failed to get collection, hr %#x.\n", hr
);
2658 ok(c2
== collection2
&& collection
!= (IDWriteFontCollection
*)c2
, "Unexpected collection instance.\n");
2659 IDWriteFontCollection2_Release(c2
);
2660 IDWriteFontCollection2_Release(collection2
);
2662 hr
= IDWriteFactory6_GetSystemFontCollection(factory6
, FALSE
, DWRITE_FONT_FAMILY_MODEL_WEIGHT_STRETCH_STYLE
,
2664 ok(hr
== S_OK
, "Failed to get collection, hr %#x.\n", hr
);
2665 IDWriteFontCollection2_Release(collection2
);
2667 IDWriteFactory6_Release(factory6
);
2670 win_skip("IDWriteFactory6 is not supported.\n");
2672 ref
= IDWriteFontCollection_Release(collection
);
2673 ok(!ref
, "Collection wasn't released, %u.\n", ref
);
2674 ref
= IDWriteFactory_Release(factory
);
2675 ok(!ref
, "Factory wasn't released, %u.\n", ref
);
2678 static void get_logfont_from_font(IDWriteFont
*font
, LOGFONTW
*logfont
)
2680 void *os2_context
, *head_context
;
2681 IDWriteLocalizedStrings
*names
;
2682 DWRITE_FONT_SIMULATIONS sim
;
2683 IDWriteFontFace
*fontface
;
2684 const TT_OS2_V2
*tt_os2
;
2685 DWRITE_FONT_STYLE style
;
2686 const TT_HEAD
*tt_head
;
2692 /* These are rendering time properties. */
2693 logfont
->lfHeight
= 0;
2694 logfont
->lfWidth
= 0;
2695 logfont
->lfEscapement
= 0;
2696 logfont
->lfOrientation
= 0;
2697 logfont
->lfUnderline
= 0;
2698 logfont
->lfStrikeOut
= 0;
2700 logfont
->lfWeight
= 0;
2701 logfont
->lfItalic
= 0;
2703 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
2704 ok(hr
== S_OK
, "Failed to create font face, %#x\n", hr
);
2706 hr
= IDWriteFontFace_TryGetFontTable(fontface
, MS_OS2_TAG
, (const void **)&tt_os2
, &size
,
2707 &os2_context
, &exists
);
2708 ok(hr
== S_OK
, "Failed to get OS/2 table, %#x\n", hr
);
2710 hr
= IDWriteFontFace_TryGetFontTable(fontface
, MS_HEAD_TAG
, (const void **)&tt_head
, &size
,
2711 &head_context
, &exists
);
2712 ok(hr
== S_OK
, "Failed to get head table, %#x\n", hr
);
2714 sim
= IDWriteFont_GetSimulations(font
);
2717 weight
= FW_REGULAR
;
2719 USHORT usWeightClass
= GET_BE_WORD(tt_os2
->usWeightClass
);
2721 if (usWeightClass
>= 1 && usWeightClass
<= 9)
2722 usWeightClass
*= 100;
2724 if (usWeightClass
> DWRITE_FONT_WEIGHT_ULTRA_BLACK
)
2725 weight
= DWRITE_FONT_WEIGHT_ULTRA_BLACK
;
2726 else if (usWeightClass
> 0)
2727 weight
= usWeightClass
;
2730 USHORT macStyle
= GET_BE_WORD(tt_head
->macStyle
);
2731 if (macStyle
& TT_HEAD_MACSTYLE_BOLD
)
2732 weight
= DWRITE_FONT_WEIGHT_BOLD
;
2734 if (sim
& DWRITE_FONT_SIMULATIONS_BOLD
)
2735 weight
+= (FW_BOLD
- FW_REGULAR
) / 2 + 1;
2736 logfont
->lfWeight
= weight
;
2739 if (IDWriteFont_GetSimulations(font
) & DWRITE_FONT_SIMULATIONS_OBLIQUE
)
2740 logfont
->lfItalic
= 1;
2742 style
= IDWriteFont_GetStyle(font
);
2743 if (!logfont
->lfItalic
&& ((style
== DWRITE_FONT_STYLE_ITALIC
) || (style
== DWRITE_FONT_STYLE_OBLIQUE
))) {
2745 USHORT fsSelection
= GET_BE_WORD(tt_os2
->fsSelection
);
2746 logfont
->lfItalic
= !!(fsSelection
& OS2_FSSELECTION_ITALIC
);
2749 USHORT macStyle
= GET_BE_WORD(tt_head
->macStyle
);
2750 logfont
->lfItalic
= !!(macStyle
& TT_HEAD_MACSTYLE_ITALIC
);
2756 logfont
->lfFaceName
[0] = 0;
2757 hr
= IDWriteFont_GetInformationalStrings(font
, DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES
, &names
, &exists
);
2762 WCHAR localeW
[LOCALE_NAME_MAX_LENGTH
];
2766 /* Fallback to en-us if there's no string for user locale. */
2768 if (GetSystemDefaultLocaleName(localeW
, ARRAY_SIZE(localeW
)))
2769 IDWriteLocalizedStrings_FindLocaleName(names
, localeW
, &index
, &exists
);
2772 IDWriteLocalizedStrings_FindLocaleName(names
, L
"en-us", &index
, &exists
);
2776 hr
= IDWriteLocalizedStrings_GetString(names
, index
, nameW
, ARRAY_SIZE(nameW
));
2777 ok(hr
== S_OK
, "Failed to get name string, hr %#x.\n", hr
);
2778 lstrcpynW(logfont
->lfFaceName
, nameW
, ARRAY_SIZE(logfont
->lfFaceName
));
2782 IDWriteLocalizedStrings_Release(names
);
2786 IDWriteFontFace_ReleaseFontTable(fontface
, os2_context
);
2788 IDWriteFontFace_ReleaseFontTable(fontface
, head_context
);
2789 IDWriteFontFace_Release(fontface
);
2792 static void test_ConvertFontFaceToLOGFONT(void)
2794 IDWriteFontCollection
*collection
;
2795 IDWriteGdiInterop
*interop
;
2796 IDWriteFontFace
*fontface
;
2797 IDWriteFactory
*factory
;
2803 factory
= create_factory();
2805 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop
);
2806 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2808 if (0) /* crashes on native */
2810 hr
= IDWriteGdiInterop_ConvertFontFaceToLOGFONT(interop
, NULL
, NULL
);
2811 hr
= IDWriteGdiInterop_ConvertFontFaceToLOGFONT(interop
, fontface
, NULL
);
2813 memset(&logfont
, 0xcc, sizeof(logfont
));
2814 hr
= IDWriteGdiInterop_ConvertFontFaceToLOGFONT(interop
, NULL
, &logfont
);
2815 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
2816 ok(logfont
.lfFaceName
[0] == 0, "got face name %s\n", wine_dbgstr_w(logfont
.lfFaceName
));
2818 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &collection
, FALSE
);
2819 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2821 count
= IDWriteFontCollection_GetFontFamilyCount(collection
);
2822 for (i
= 0; i
< count
; i
++) {
2823 WCHAR nameW
[128], familynameW
[64], facenameW
[64];
2824 IDWriteLocalizedStrings
*names
;
2825 DWRITE_FONT_SIMULATIONS sim
;
2826 IDWriteFontFamily
*family
;
2827 UINT32 font_count
, j
;
2831 hr
= IDWriteFontCollection_GetFontFamily(collection
, i
, &family
);
2832 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2834 hr
= IDWriteFontFamily_GetFamilyNames(family
, &names
);
2835 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2837 get_enus_string(names
, familynameW
, ARRAY_SIZE(familynameW
));
2838 IDWriteLocalizedStrings_Release(names
);
2840 font_count
= IDWriteFontFamily_GetFontCount(family
);
2842 for (j
= 0; j
< font_count
; j
++) {
2843 IDWriteFontFace
*fontface
;
2845 hr
= IDWriteFontFamily_GetFont(family
, j
, &font
);
2846 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2848 hr
= IDWriteFont_GetFaceNames(font
, &names
);
2849 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2851 get_enus_string(names
, facenameW
, ARRAY_SIZE(facenameW
));
2852 IDWriteLocalizedStrings_Release(names
);
2854 get_combined_font_name(familynameW
, facenameW
, nameW
);
2856 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
2857 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2859 if (has_face_variations(fontface
))
2863 skip("ConvertFontFaceToLOGFONT() test does not support variable fonts.\n");
2864 IDWriteFontFace_Release(fontface
);
2865 IDWriteFont_Release(font
);
2869 memset(&logfont
, 0xcc, sizeof(logfont
));
2870 hr
= IDWriteGdiInterop_ConvertFontFaceToLOGFONT(interop
, fontface
, &logfont
);
2871 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2873 sim
= IDWriteFontFace_GetSimulations(fontface
);
2874 get_logfont_from_font(font
, &lf
);
2876 ok(logfont
.lfWeight
== lf
.lfWeight
, "%s: unexpected lfWeight %d, expected lfWeight %d, font weight %d, "
2877 "bold simulation %s\n", wine_dbgstr_w(nameW
), logfont
.lfWeight
, lf
.lfWeight
, IDWriteFont_GetWeight(font
),
2878 sim
& DWRITE_FONT_SIMULATIONS_BOLD
? "yes" : "no");
2879 ok(logfont
.lfItalic
== lf
.lfItalic
, "%s: unexpected italic flag %d, oblique simulation %s\n",
2880 wine_dbgstr_w(nameW
), logfont
.lfItalic
, sim
& DWRITE_FONT_SIMULATIONS_OBLIQUE
? "yes" : "no");
2881 ok(!lstrcmpW(logfont
.lfFaceName
, lf
.lfFaceName
), "%s: unexpected facename %s, expected %s\n",
2882 wine_dbgstr_w(nameW
), wine_dbgstr_w(logfont
.lfFaceName
), wine_dbgstr_w(lf
.lfFaceName
));
2884 ok(logfont
.lfOutPrecision
== OUT_OUTLINE_PRECIS
, "%s: unexpected output precision %d\n", wine_dbgstr_w(nameW
),
2885 logfont
.lfOutPrecision
);
2886 ok(logfont
.lfClipPrecision
== CLIP_DEFAULT_PRECIS
, "%s: unexpected clipping precision %d\n", wine_dbgstr_w(nameW
),
2887 logfont
.lfClipPrecision
);
2888 ok(logfont
.lfQuality
== DEFAULT_QUALITY
, "%s: unexpected quality %d\n", wine_dbgstr_w(nameW
), logfont
.lfQuality
);
2889 ok(logfont
.lfPitchAndFamily
== DEFAULT_PITCH
, "%s: unexpected pitch %d\n", wine_dbgstr_w(nameW
),
2890 logfont
.lfPitchAndFamily
);
2892 IDWriteFontFace_Release(fontface
);
2893 IDWriteFont_Release(font
);
2896 IDWriteFontFamily_Release(family
);
2899 IDWriteFontCollection_Release(collection
);
2900 IDWriteGdiInterop_Release(interop
);
2901 ref
= IDWriteFactory_Release(factory
);
2902 ok(ref
== 0, "factory not released, %u\n", ref
);
2905 static HRESULT WINAPI
fontfileenumerator_QueryInterface(IDWriteFontFileEnumerator
*iface
, REFIID riid
, void **obj
)
2907 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFontFileEnumerator
))
2910 IDWriteFontFileEnumerator_AddRef(iface
);
2913 return E_NOINTERFACE
;
2916 static ULONG WINAPI
fontfileenumerator_AddRef(IDWriteFontFileEnumerator
*iface
)
2921 static ULONG WINAPI
fontfileenumerator_Release(IDWriteFontFileEnumerator
*iface
)
2926 static HRESULT WINAPI
fontfileenumerator_GetCurrentFontFile(IDWriteFontFileEnumerator
*iface
, IDWriteFontFile
**file
)
2932 static HRESULT WINAPI
fontfileenumerator_MoveNext(IDWriteFontFileEnumerator
*iface
, BOOL
*current
)
2938 static const struct IDWriteFontFileEnumeratorVtbl dwritefontfileenumeratorvtbl
=
2940 fontfileenumerator_QueryInterface
,
2941 fontfileenumerator_AddRef
,
2942 fontfileenumerator_Release
,
2943 fontfileenumerator_MoveNext
,
2944 fontfileenumerator_GetCurrentFontFile
,
2947 struct collection_loader
2949 IDWriteFontCollectionLoader IDWriteFontCollectionLoader_iface
;
2953 static inline struct collection_loader
*impl_from_IDWriteFontCollectionLoader(IDWriteFontCollectionLoader
*iface
)
2955 return CONTAINING_RECORD(iface
, struct collection_loader
, IDWriteFontCollectionLoader_iface
);
2958 static HRESULT WINAPI
fontcollectionloader_QueryInterface(IDWriteFontCollectionLoader
*iface
, REFIID riid
, void **obj
)
2960 struct collection_loader
*loader
= impl_from_IDWriteFontCollectionLoader(iface
);
2962 if (IsEqualIID(&IID_IDWriteFontCollectionLoader
, riid
) ||
2963 IsEqualIID(&IID_IUnknown
, riid
))
2965 *obj
= &loader
->IDWriteFontCollectionLoader_iface
;
2966 IDWriteFontCollectionLoader_AddRef(iface
);
2971 return E_NOINTERFACE
;
2974 static ULONG WINAPI
fontcollectionloader_AddRef(IDWriteFontCollectionLoader
*iface
)
2976 struct collection_loader
*loader
= impl_from_IDWriteFontCollectionLoader(iface
);
2977 return InterlockedIncrement(&loader
->ref
);
2980 static ULONG WINAPI
fontcollectionloader_Release(IDWriteFontCollectionLoader
*iface
)
2982 struct collection_loader
*loader
= impl_from_IDWriteFontCollectionLoader(iface
);
2983 ULONG ref
= InterlockedDecrement(&loader
->ref
);
2991 static HRESULT WINAPI
fontcollectionloader_CreateEnumeratorFromKey(IDWriteFontCollectionLoader
*iface
, IDWriteFactory
*factory
, const void *key
,
2992 UINT32 key_size
, IDWriteFontFileEnumerator
**ret
)
2994 static IDWriteFontFileEnumerator enumerator
= { &dwritefontfileenumeratorvtbl
};
2999 static const struct IDWriteFontCollectionLoaderVtbl dwritefontcollectionloadervtbl
= {
3000 fontcollectionloader_QueryInterface
,
3001 fontcollectionloader_AddRef
,
3002 fontcollectionloader_Release
,
3003 fontcollectionloader_CreateEnumeratorFromKey
3006 static IDWriteFontCollectionLoader
*create_collection_loader(void)
3008 struct collection_loader
*loader
= heap_alloc(sizeof(*loader
));
3010 loader
->IDWriteFontCollectionLoader_iface
.lpVtbl
= &dwritefontcollectionloadervtbl
;
3013 return &loader
->IDWriteFontCollectionLoader_iface
;
3016 static void test_CustomFontCollection(void)
3018 IDWriteFontCollectionLoader
*loader
, *loader2
, *loader3
;
3019 IDWriteFontCollection
*font_collection
= NULL
;
3020 static IDWriteFontFileLoader rloader
= { &resourcefontfileloadervtbl
};
3021 struct test_fontcollectionloader resource_collection
= { { &resourcecollectionloadervtbl
}, &rloader
};
3022 IDWriteFontFamily
*family
, *family2
, *family3
;
3023 IDWriteFontFace
*idfontface
, *idfontface2
;
3024 IDWriteFontFile
*fontfile
, *fontfile2
;
3025 IDWriteLocalizedStrings
*string
;
3026 IDWriteFont
*idfont
, *idfont2
;
3027 IDWriteFactory
*factory
;
3028 UINT32 index
, count
;
3034 factory
= create_factory();
3036 loader
= create_collection_loader();
3037 loader2
= create_collection_loader();
3038 loader3
= create_collection_loader();
3040 hr
= IDWriteFactory_RegisterFontCollectionLoader(factory
, NULL
);
3041 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
3043 hr
= IDWriteFactory_UnregisterFontCollectionLoader(factory
, NULL
);
3044 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
3046 EXPECT_REF(loader
, 1);
3047 EXPECT_REF(loader2
, 1);
3049 hr
= IDWriteFactory_RegisterFontCollectionLoader(factory
, loader
);
3050 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3051 hr
= IDWriteFactory_RegisterFontCollectionLoader(factory
, loader2
);
3052 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3053 hr
= IDWriteFactory_RegisterFontCollectionLoader(factory
, loader
);
3054 ok(hr
== DWRITE_E_ALREADYREGISTERED
, "got 0x%08x\n", hr
);
3056 EXPECT_REF(loader
, 2);
3057 EXPECT_REF(loader2
, 2);
3059 hr
= IDWriteFactory_RegisterFontFileLoader(factory
, &rloader
);
3060 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3061 hr
= IDWriteFactory_RegisterFontCollectionLoader(factory
, &resource_collection
.IDWriteFontFileCollectionLoader_iface
);
3062 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3064 /* Loader wasn't registered. */
3065 font_collection
= (void*)0xdeadbeef;
3066 hr
= IDWriteFactory_CreateCustomFontCollection(factory
, loader3
, "Billy", 6, &font_collection
);
3067 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
3068 ok(font_collection
== NULL
, "got %p\n", font_collection
);
3070 EXPECT_REF(factory
, 1);
3071 hr
= IDWriteFactory_CreateCustomFontCollection(factory
, loader
, "Billy", 6, &font_collection
);
3072 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3074 EXPECT_REF(factory
, 1);
3075 EXPECT_REF(loader
, 2);
3076 IDWriteFontCollection_Release(font_collection
);
3078 hr
= IDWriteFactory_CreateCustomFontCollection(factory
, loader2
, "Billy", 6, &font_collection
);
3079 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3080 IDWriteFontCollection_Release(font_collection
);
3082 font_collection
= (void*)0xdeadbeef;
3083 hr
= IDWriteFactory_CreateCustomFontCollection(factory
, (IDWriteFontCollectionLoader
*)0xdeadbeef, "Billy", 6, &font_collection
);
3084 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
3085 ok(font_collection
== NULL
, "got %p\n", font_collection
);
3087 font
= FindResourceA(GetModuleHandleA(NULL
), (LPCSTR
)MAKEINTRESOURCE(1), (LPCSTR
)RT_RCDATA
);
3088 ok(font
!= NULL
, "Failed to find font resource\n");
3090 hr
= IDWriteFactory_CreateCustomFontCollection(factory
, &resource_collection
.IDWriteFontFileCollectionLoader_iface
,
3091 &font
, sizeof(HRSRC
), &font_collection
);
3092 ok(hr
== S_OK
, "got 0x%08x\n",hr
);
3093 EXPECT_REF(font_collection
, 1);
3097 hr
= IDWriteFontCollection_FindFamilyName(font_collection
, L
"wine_test", &index
, &exists
);
3098 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3099 ok(index
== 0, "got index %i\n", index
);
3100 ok(exists
, "got exists %i\n", exists
);
3102 count
= IDWriteFontCollection_GetFontFamilyCount(font_collection
);
3103 ok(count
== 1, "got %u\n", count
);
3106 hr
= IDWriteFontCollection_GetFontFamily(font_collection
, 0, &family
);
3107 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3108 EXPECT_REF(family
, 1);
3111 hr
= IDWriteFontCollection_GetFontFamily(font_collection
, 0, &family2
);
3112 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3113 EXPECT_REF(family2
, 1);
3114 ok(family
!= family2
, "got %p, %p\n", family
, family2
);
3116 hr
= IDWriteFontFamily_GetFont(family
, 0, &idfont
);
3117 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3118 EXPECT_REF(idfont
, 1);
3119 EXPECT_REF(family
, 2);
3120 hr
= IDWriteFontFamily_GetFont(family
, 0, &idfont2
);
3121 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3122 EXPECT_REF(idfont2
, 1);
3123 EXPECT_REF(family
, 3);
3124 ok(idfont
!= idfont2
, "got %p, %p\n", idfont
, idfont2
);
3125 IDWriteFont_Release(idfont2
);
3127 hr
= IDWriteFont_GetInformationalStrings(idfont
, DWRITE_INFORMATIONAL_STRING_COPYRIGHT_NOTICE
, &string
, &exists
);
3128 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3129 ok(exists
, "got %d\n", exists
);
3130 EXPECT_REF(string
, 1);
3131 IDWriteLocalizedStrings_Release(string
);
3134 hr
= IDWriteFont_GetFontFamily(idfont
, &family3
);
3135 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3136 EXPECT_REF(family
, 3);
3137 ok(family
== family3
, "got %p, %p\n", family
, family3
);
3138 IDWriteFontFamily_Release(family3
);
3141 hr
= IDWriteFont_CreateFontFace(idfont
, &idfontface
);
3142 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3143 EXPECT_REF(idfont
, 1);
3146 hr
= IDWriteFontFamily_GetFont(family2
, 0, &idfont2
);
3147 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3148 EXPECT_REF(idfont2
, 1);
3149 EXPECT_REF(idfont
, 1);
3150 ok(idfont2
!= idfont
, "Font instances should not match\n");
3153 hr
= IDWriteFont_CreateFontFace(idfont2
, &idfontface2
);
3154 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3155 ok(idfontface2
== idfontface
, "fontfaces should match\n");
3159 hr
= IDWriteFontFace_GetFiles(idfontface
, &index
, &fontfile
);
3160 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3164 hr
= IDWriteFontFace_GetFiles(idfontface2
, &index
, &fontfile2
);
3165 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3166 ok(fontfile
== fontfile2
, "fontfiles should match\n");
3168 IDWriteFont_Release(idfont
);
3169 IDWriteFont_Release(idfont2
);
3170 IDWriteFontFile_Release(fontfile
);
3171 IDWriteFontFile_Release(fontfile2
);
3172 IDWriteFontFace_Release(idfontface
);
3173 IDWriteFontFace_Release(idfontface2
);
3174 IDWriteFontFamily_Release(family2
);
3175 IDWriteFontFamily_Release(family
);
3176 IDWriteFontCollection_Release(font_collection
);
3178 hr
= IDWriteFactory_UnregisterFontCollectionLoader(factory
, loader
);
3179 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3180 hr
= IDWriteFactory_UnregisterFontCollectionLoader(factory
, loader
);
3181 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
3182 hr
= IDWriteFactory_UnregisterFontCollectionLoader(factory
, loader2
);
3183 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3184 hr
= IDWriteFactory_UnregisterFontCollectionLoader(factory
, &resource_collection
.IDWriteFontFileCollectionLoader_iface
);
3185 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3186 hr
= IDWriteFactory_UnregisterFontFileLoader(factory
, &rloader
);
3187 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3189 IDWriteFontCollectionLoader_Release(loader
);
3190 IDWriteFontCollectionLoader_Release(loader2
);
3191 IDWriteFontCollectionLoader_Release(loader3
);
3193 ref
= IDWriteFactory_Release(factory
);
3194 ok(ref
== 0, "factory not released, %u\n", ref
);
3197 static HRESULT WINAPI
fontfileloader_QueryInterface(IDWriteFontFileLoader
*iface
, REFIID riid
, void **obj
)
3199 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFontFileLoader
))
3202 IDWriteFontFileLoader_AddRef(iface
);
3207 return E_NOINTERFACE
;
3210 static ULONG WINAPI
fontfileloader_AddRef(IDWriteFontFileLoader
*iface
)
3215 static ULONG WINAPI
fontfileloader_Release(IDWriteFontFileLoader
*iface
)
3220 static HRESULT WINAPI
fontfileloader_CreateStreamFromKey(IDWriteFontFileLoader
*iface
, const void *ref_key
, UINT32 key_size
,
3221 IDWriteFontFileStream
**stream
)
3226 static const struct IDWriteFontFileLoaderVtbl dwritefontfileloadervtbl
= {
3227 fontfileloader_QueryInterface
,
3228 fontfileloader_AddRef
,
3229 fontfileloader_Release
,
3230 fontfileloader_CreateStreamFromKey
3233 static void test_CreateCustomFontFileReference(void)
3235 IDWriteFontFileLoader floader
= { &dwritefontfileloadervtbl
};
3236 IDWriteFontFileLoader floader2
= { &dwritefontfileloadervtbl
};
3237 IDWriteFontFileLoader floader3
= { &dwritefontfileloadervtbl
};
3238 IDWriteFactory
*factory
, *factory2
;
3239 IDWriteFontFileLoader
*loader
;
3240 IDWriteFontFile
*file
, *file2
;
3242 DWRITE_FONT_FILE_TYPE file_type
;
3243 DWRITE_FONT_FACE_TYPE face_type
;
3245 IDWriteFontFace
*face
, *face2
;
3248 UINT32 codePoints
[1] = {0xa8};
3255 path
= create_testfontfile(test_fontfile
);
3257 factory
= create_factory();
3258 factory2
= create_factory();
3260 if (0) { /* crashes on win10 */
3261 hr
= IDWriteFactory_RegisterFontFileLoader(factory
, NULL
);
3262 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
3264 /* local loader is accepted too */
3265 hr
= IDWriteFactory_CreateFontFileReference(factory
, path
, NULL
, &file
);
3266 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3268 hr
= IDWriteFontFile_GetLoader(file
, &loader
);
3269 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3271 hr
= IDWriteFontFile_GetReferenceKey(file
, &key
, &key_size
);
3272 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3274 hr
= IDWriteFactory_CreateCustomFontFileReference(factory
, key
, key_size
, loader
, &file2
);
3275 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3277 IDWriteFontFile_Release(file2
);
3278 IDWriteFontFile_Release(file
);
3279 IDWriteFontFileLoader_Release(loader
);
3281 hr
= IDWriteFactory_RegisterFontFileLoader(factory
, &floader
);
3282 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3283 hr
= IDWriteFactory_RegisterFontFileLoader(factory
, &floader2
);
3284 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3285 hr
= IDWriteFactory_RegisterFontFileLoader(factory
, &floader
);
3286 ok(hr
== DWRITE_E_ALREADYREGISTERED
, "got 0x%08x\n", hr
);
3287 hr
= IDWriteFactory_RegisterFontFileLoader(factory
, &rloader
);
3288 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3291 hr
= IDWriteFactory_CreateCustomFontFileReference(factory
, "test", 4, &floader
, &file
);
3292 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3293 IDWriteFontFile_Release(file
);
3295 file
= (void*)0xdeadbeef;
3296 hr
= IDWriteFactory_CreateCustomFontFileReference(factory
, "test", 4, &floader3
, &file
);
3297 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
3298 ok(file
== NULL
, "got %p\n", file
);
3300 file
= (void*)0xdeadbeef;
3301 hr
= IDWriteFactory_CreateCustomFontFileReference(factory
, "test", 4, NULL
, &file
);
3302 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
3303 ok(file
== NULL
, "got %p\n", file
);
3306 hr
= IDWriteFactory_CreateCustomFontFileReference(factory
, "test", 4, &floader
, &file
);
3307 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3309 file_type
= DWRITE_FONT_FILE_TYPE_TRUETYPE
;
3310 face_type
= DWRITE_FONT_FACE_TYPE_TRUETYPE
;
3313 hr
= IDWriteFontFile_Analyze(file
, &support
, &file_type
, &face_type
, &count
);
3314 ok(hr
== 0x8faecafe, "got 0x%08x\n", hr
);
3315 ok(support
== FALSE
, "got %i\n", support
);
3316 ok(file_type
== DWRITE_FONT_FILE_TYPE_UNKNOWN
, "got %i\n", file_type
);
3317 ok(face_type
== DWRITE_FONT_FACE_TYPE_UNKNOWN
, "got %i\n", face_type
);
3318 ok(count
== 0, "got %i\n", count
);
3320 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_CFF
, 1, &file
, 0, 0, &face
);
3321 ok(hr
== 0x8faecafe, "got 0x%08x\n", hr
);
3322 IDWriteFontFile_Release(file
);
3324 fontrsrc
= FindResourceA(GetModuleHandleA(NULL
), (LPCSTR
)MAKEINTRESOURCE(1), (LPCSTR
)RT_RCDATA
);
3325 ok(fontrsrc
!= NULL
, "Failed to find font resource\n");
3327 hr
= IDWriteFactory_CreateCustomFontFileReference(factory
, &fontrsrc
, sizeof(HRSRC
), &rloader
, &file
);
3328 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3330 file_type
= DWRITE_FONT_FILE_TYPE_UNKNOWN
;
3331 face_type
= DWRITE_FONT_FACE_TYPE_UNKNOWN
;
3334 hr
= IDWriteFontFile_Analyze(file
, &support
, &file_type
, &face_type
, &count
);
3335 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3336 ok(support
== TRUE
, "got %i\n", support
);
3337 ok(file_type
== DWRITE_FONT_FILE_TYPE_TRUETYPE
, "got %i\n", file_type
);
3338 ok(face_type
== DWRITE_FONT_FACE_TYPE_TRUETYPE
, "got %i\n", face_type
);
3339 ok(count
== 1, "got %i\n", count
);
3342 face
= (void*)0xdeadbeef;
3343 hr
= IDWriteFactory_CreateFontFace(factory
, face_type
, 1, &file
, 1, DWRITE_FONT_SIMULATIONS_NONE
, &face
);
3344 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
3345 ok(face
== NULL
, "got %p\n", face
);
3347 hr
= IDWriteFactory_CreateFontFace(factory
, face_type
, 1, &file
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &face
);
3348 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3350 hr
= IDWriteFactory_CreateFontFace(factory
, face_type
, 1, &file
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &face2
);
3351 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3352 /* fontface instances are reused starting with win7 */
3353 ok(face
== face2
|| broken(face
!= face2
), "got %p, %p\n", face
, face2
);
3354 IDWriteFontFace_Release(face2
);
3356 /* file was created with different factory */
3358 hr
= IDWriteFactory_CreateFontFace(factory2
, face_type
, 1, &file
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &face2
);
3360 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3362 IDWriteFontFace_Release(face2
);
3365 hr
= IDWriteFactory_CreateCustomFontFileReference(factory
, &fontrsrc
, sizeof(HRSRC
), &rloader
, &file2
);
3366 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3367 ok(file
!= file2
, "got %p, %p\n", file
, file2
);
3369 hr
= IDWriteFactory_CreateFontFace(factory
, face_type
, 1, &file2
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &face2
);
3370 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3371 /* fontface instances are reused starting with win7 */
3372 ok(face
== face2
|| broken(face
!= face2
), "got %p, %p\n", face
, face2
);
3373 IDWriteFontFace_Release(face2
);
3374 IDWriteFontFile_Release(file2
);
3376 hr
= IDWriteFontFace_GetGlyphIndices(face
, NULL
, 0, NULL
);
3377 ok(hr
== E_INVALIDARG
|| broken(hr
== S_OK
) /* win8 */, "got 0x%08x\n", hr
);
3379 hr
= IDWriteFontFace_GetGlyphIndices(face
, codePoints
, 0, NULL
);
3380 ok(hr
== E_INVALIDARG
|| broken(hr
== S_OK
) /* win8 */, "got 0x%08x\n", hr
);
3382 hr
= IDWriteFontFace_GetGlyphIndices(face
, codePoints
, 0, indices
);
3383 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3385 hr
= IDWriteFontFace_GetGlyphIndices(face
, NULL
, 0, indices
);
3386 ok(hr
== E_INVALIDARG
|| broken(hr
== S_OK
) /* win8 */, "got 0x%08x\n", hr
);
3388 indices
[0] = indices
[1] = 11;
3389 hr
= IDWriteFontFace_GetGlyphIndices(face
, NULL
, 1, indices
);
3390 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
3391 ok(indices
[0] == 0, "got index %i\n", indices
[0]);
3392 ok(indices
[1] == 11, "got index %i\n", indices
[1]);
3394 if (0) /* crashes on native */
3395 hr
= IDWriteFontFace_GetGlyphIndices(face
, NULL
, 1, NULL
);
3397 hr
= IDWriteFontFace_GetGlyphIndices(face
, codePoints
, 1, indices
);
3398 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3399 ok(indices
[0] == 7, "Unexpected glyph index, %u.\n", indices
[0]);
3400 IDWriteFontFace_Release(face
);
3401 IDWriteFontFile_Release(file
);
3403 hr
= IDWriteFactory_UnregisterFontFileLoader(factory
, &floader
);
3404 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3405 hr
= IDWriteFactory_UnregisterFontFileLoader(factory
, &floader
);
3406 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
3407 hr
= IDWriteFactory_UnregisterFontFileLoader(factory
, &floader2
);
3408 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3409 hr
= IDWriteFactory_UnregisterFontFileLoader(factory
, &rloader
);
3410 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3412 ref
= IDWriteFactory_Release(factory2
);
3413 ok(ref
== 0, "factory not released, %u\n", ref
);
3414 ref
= IDWriteFactory_Release(factory
);
3415 ok(ref
== 0, "factory not released, %u\n", ref
);
3416 DELETE_FONTFILE(path
);
3419 static void test_CreateFontFileReference(void)
3422 IDWriteFontFile
*ffile
= NULL
;
3424 DWRITE_FONT_FILE_TYPE type
;
3425 DWRITE_FONT_FACE_TYPE face
;
3427 IDWriteFontFace
*fface
= NULL
;
3428 IDWriteFactory
*factory
;
3432 path
= create_testfontfile(test_fontfile
);
3433 factory
= create_factory();
3435 ffile
= (void*)0xdeadbeef;
3436 hr
= IDWriteFactory_CreateFontFileReference(factory
, NULL
, NULL
, &ffile
);
3437 ok(hr
== E_INVALIDARG
, "got 0x%08x\n",hr
);
3438 ok(ffile
== NULL
, "got %p\n", ffile
);
3440 hr
= IDWriteFactory_CreateFontFileReference(factory
, path
, NULL
, &ffile
);
3441 ok(hr
== S_OK
, "got 0x%08x\n",hr
);
3444 type
= DWRITE_FONT_FILE_TYPE_UNKNOWN
;
3445 face
= DWRITE_FONT_FACE_TYPE_CFF
;
3447 hr
= IDWriteFontFile_Analyze(ffile
, &support
, &type
, &face
, &count
);
3448 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3449 ok(support
== TRUE
, "got %i\n", support
);
3450 ok(type
== DWRITE_FONT_FILE_TYPE_TRUETYPE
, "got %i\n", type
);
3451 ok(face
== DWRITE_FONT_FACE_TYPE_TRUETYPE
, "got %i\n", face
);
3452 ok(count
== 1, "got %i\n", count
);
3454 hr
= IDWriteFactory_CreateFontFace(factory
, face
, 1, &ffile
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &fface
);
3455 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3457 IDWriteFontFace_Release(fface
);
3458 IDWriteFontFile_Release(ffile
);
3459 ref
= IDWriteFactory_Release(factory
);
3460 ok(ref
== 0, "factory not released, %u\n", ref
);
3462 DELETE_FONTFILE(path
);
3465 static void test_shared_isolated(void)
3467 IDWriteFactory
*isolated
, *isolated2
;
3468 IDWriteFactory
*shared
, *shared2
;
3474 hr
= DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED
+1, &IID_IDWriteFactory
, (IUnknown
**)&shared
);
3475 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3476 ok(shared
!= NULL
, "got %p\n", shared
);
3477 IDWriteFactory_Release(shared
);
3479 hr
= DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED
, &IID_IDWriteFactory
, (IUnknown
**)&shared
);
3480 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3482 hr
= DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED
, &IID_IDWriteFactory
, (IUnknown
**)&shared2
);
3483 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3484 ok(shared
== shared2
, "got %p, and %p\n", shared
, shared2
);
3485 IDWriteFactory_Release(shared2
);
3487 IDWriteFactory_Release(shared
);
3489 /* we got 2 references, released 2 - still same pointer is returned */
3490 hr
= DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED
, &IID_IDWriteFactory
, (IUnknown
**)&shared2
);
3491 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3492 ok(shared
== shared2
, "got %p, and %p\n", shared
, shared2
);
3493 IDWriteFactory_Release(shared2
);
3495 hr
= DWriteCreateFactory(DWRITE_FACTORY_TYPE_ISOLATED
, &IID_IDWriteFactory
, (IUnknown
**)&isolated
);
3496 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3498 hr
= DWriteCreateFactory(DWRITE_FACTORY_TYPE_ISOLATED
, &IID_IDWriteFactory
, (IUnknown
**)&isolated2
);
3499 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3500 ok(isolated
!= isolated2
, "got %p, and %p\n", isolated
, isolated2
);
3501 IDWriteFactory_Release(isolated2
);
3503 hr
= DWriteCreateFactory(DWRITE_FACTORY_TYPE_ISOLATED
, &IID_IUnknown
, (IUnknown
**)&isolated2
);
3504 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3505 IDWriteFactory_Release(isolated2
);
3507 hr
= DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED
+1, &IID_IDWriteFactory
, (IUnknown
**)&isolated2
);
3508 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3509 ok(shared
!= isolated2
, "got %p, and %p\n", shared
, isolated2
);
3511 ref
= IDWriteFactory_Release(isolated
);
3512 ok(ref
== 0, "factory not released, %u\n", ref
);
3513 ref
= IDWriteFactory_Release(isolated2
);
3514 ok(ref
== 0, "factory not released, %u\n", ref
);
3517 struct dwrite_fonttable
3524 static WORD
table_read_be_word(const struct dwrite_fonttable
*table
, void *ptr
, DWORD offset
)
3529 if ((BYTE
*)ptr
< table
->data
|| (BYTE
*)ptr
- table
->data
>= table
->size
)
3532 if (offset
> table
->size
- sizeof(WORD
))
3535 return GET_BE_WORD(*(WORD
*)((BYTE
*)ptr
+ offset
));
3538 static DWORD
table_read_be_dword(const struct dwrite_fonttable
*table
, void *ptr
, DWORD offset
)
3543 if ((BYTE
*)ptr
< table
->data
|| (BYTE
*)ptr
- table
->data
>= table
->size
)
3546 if (offset
> table
->size
- sizeof(WORD
))
3549 return GET_BE_DWORD(*(DWORD
*)((BYTE
*)ptr
+ offset
));
3552 static void array_reserve(void **elements
, size_t *capacity
, size_t count
, size_t size
)
3554 size_t new_capacity
, max_capacity
;
3557 if (count
<= *capacity
)
3560 max_capacity
= ~(SIZE_T
)0 / size
;
3561 if (count
> max_capacity
)
3564 new_capacity
= max(4, *capacity
);
3565 while (new_capacity
< count
&& new_capacity
<= max_capacity
/ 2)
3567 if (new_capacity
< count
)
3568 new_capacity
= max_capacity
;
3570 if (!(new_elements
= heap_realloc(*elements
, new_capacity
* size
)))
3573 *elements
= new_elements
;
3574 *capacity
= new_capacity
;
3577 static void opentype_cmap_read_table(const struct dwrite_fonttable
*table
, UINT16 cmap_index
, UINT32
*count
,
3578 size_t *capacity
, DWRITE_UNICODE_RANGE
**ranges
)
3580 const BYTE
*tables
= table
->data
+ FIELD_OFFSET(struct cmap_header
, tables
);
3581 struct cmap_encoding_record
*record
;
3586 record
= (struct cmap_encoding_record
*)(tables
+ cmap_index
* sizeof(*record
));
3588 if (!(table_offset
= table_read_be_dword(table
, record
, FIELD_OFFSET(struct cmap_encoding_record
, offset
))))
3591 format
= table_read_be_word(table
, NULL
, table_offset
);
3594 case OPENTYPE_CMAP_TABLE_SEGMENT_MAPPING
:
3596 UINT16 segment_count
= table_read_be_word(table
, NULL
, table_offset
+
3597 FIELD_OFFSET(struct cmap_segmented_mapping_0
, segCountX2
)) / 2;
3598 DWORD start_code_offset
= table_offset
+ sizeof(struct cmap_segmented_mapping_0
) +
3599 sizeof(WORD
) * segment_count
;
3601 for (j
= 0; j
< segment_count
; ++j
) {
3602 WORD endcode
= table_read_be_word(table
, NULL
, table_offset
+
3603 FIELD_OFFSET(struct cmap_segmented_mapping_0
, endCode
) + j
* sizeof(WORD
));
3606 if (endcode
== 0xffff)
3609 first
= table_read_be_word(table
, NULL
, start_code_offset
+ j
* sizeof(WORD
));
3611 array_reserve((void **)ranges
, capacity
, *count
+ 1, sizeof(**ranges
));
3612 (*ranges
)[*count
].first
= first
;
3613 (*ranges
)[*count
].last
= endcode
;
3618 case OPENTYPE_CMAP_TABLE_SEGMENTED_COVERAGE
:
3620 DWORD num_groups
= table_read_be_dword(table
, NULL
, table_offset
+
3621 FIELD_OFFSET(struct cmap_segmented_coverage
, nGroups
));
3623 for (j
= 0; j
< num_groups
; ++j
) {
3624 DWORD group_offset
= table_offset
+ FIELD_OFFSET(struct cmap_segmented_coverage
, groups
) +
3625 j
* sizeof(struct cmap_segmented_coverage_group
);
3626 DWORD first
= table_read_be_dword(table
, NULL
, group_offset
+
3627 FIELD_OFFSET(struct cmap_segmented_coverage_group
, startCharCode
));
3628 DWORD last
= table_read_be_dword(table
, NULL
, group_offset
+
3629 FIELD_OFFSET(struct cmap_segmented_coverage_group
, endCharCode
));
3631 array_reserve((void **)ranges
, capacity
, *count
+ 1, sizeof(**ranges
));
3632 (*ranges
)[*count
].first
= first
;
3633 (*ranges
)[*count
].last
= last
;
3639 ok(0, "%u table format %#x unhandled.\n", cmap_index
, format
);
3643 static UINT32
opentype_cmap_get_unicode_ranges(const struct dwrite_fonttable
*table
, DWRITE_UNICODE_RANGE
**ranges
)
3645 int index_full
= -1, index_bmp
= -1;
3646 unsigned int i
, count
= 0;
3647 size_t capacity
= 0;
3653 num_tables
= table_read_be_word(table
, 0, FIELD_OFFSET(struct cmap_header
, num_tables
));
3654 tables
= table
->data
+ FIELD_OFFSET(struct cmap_header
, tables
);
3656 for (i
= 0; i
< num_tables
; ++i
)
3658 struct cmap_encoding_record
*record
= (struct cmap_encoding_record
*)(tables
+ i
* sizeof(*record
));
3659 WORD platform
, encoding
;
3661 platform
= table_read_be_word(table
, record
, FIELD_OFFSET(struct cmap_encoding_record
, platformID
));
3662 encoding
= table_read_be_word(table
, record
, FIELD_OFFSET(struct cmap_encoding_record
, encodingID
));
3664 if (platform
== OPENTYPE_CMAP_TABLE_PLATFORM_WIN
)
3666 if (encoding
== OPENTYPE_CMAP_TABLE_ENCODING_UNICODE_FULL
)
3671 else if (encoding
== OPENTYPE_CMAP_TABLE_ENCODING_UNICODE_BMP
)
3676 if (index_full
!= -1)
3677 opentype_cmap_read_table(table
, index_full
, &count
, &capacity
, ranges
);
3678 else if (index_bmp
!= -1)
3679 opentype_cmap_read_table(table
, index_bmp
, &count
, &capacity
, ranges
);
3684 static UINT32
fontface_get_expected_unicode_ranges(IDWriteFontFace1
*fontface
, DWRITE_UNICODE_RANGE
**out
)
3686 struct dwrite_fonttable cmap
;
3687 DWRITE_UNICODE_RANGE
*ranges
;
3694 hr
= IDWriteFontFace1_TryGetFontTable(fontface
, MS_CMAP_TAG
, (const void **)&cmap
.data
,
3695 &cmap
.size
, &cmap
.context
, &exists
);
3696 if (FAILED(hr
) || !exists
)
3699 count
= opentype_cmap_get_unicode_ranges(&cmap
, &ranges
);
3700 IDWriteFontFace1_ReleaseFontTable(fontface
, cmap
.context
);
3702 *out
= heap_alloc(count
* sizeof(**out
));
3704 /* Eliminate duplicates and merge ranges together. */
3705 for (i
= 0, j
= 0; i
< count
; ++i
) {
3707 DWRITE_UNICODE_RANGE
*prev
= &(*out
)[j
-1];
3708 /* Merge adjacent ranges. */
3709 if (ranges
[i
].first
== prev
->last
+ 1) {
3710 prev
->last
= ranges
[i
].last
;
3714 (*out
)[j
++] = ranges
[i
];
3722 static void test_GetUnicodeRanges(void)
3724 IDWriteFontCollection
*syscollection
;
3725 DWRITE_UNICODE_RANGE
*ranges
, r
;
3726 IDWriteFontFile
*ffile
= NULL
;
3727 IDWriteFontFace1
*fontface1
;
3728 IDWriteFontFace
*fontface
;
3729 IDWriteFactory
*factory
;
3735 factory
= create_factory();
3737 hr
= IDWriteFactory_RegisterFontFileLoader(factory
, &rloader
);
3738 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3740 font
= FindResourceA(GetModuleHandleA(NULL
), (LPCSTR
)MAKEINTRESOURCE(1), (LPCSTR
)RT_RCDATA
);
3741 ok(font
!= NULL
, "Failed to find font resource\n");
3743 hr
= IDWriteFactory_CreateCustomFontFileReference(factory
, &font
, sizeof(HRSRC
), &rloader
, &ffile
);
3744 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3746 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_TRUETYPE
, 1, &ffile
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &fontface
);
3747 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3748 IDWriteFontFile_Release(ffile
);
3750 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void**)&fontface1
);
3751 IDWriteFontFace_Release(fontface
);
3753 win_skip("GetUnicodeRanges() is not supported.\n");
3754 IDWriteFactory_Release(factory
);
3759 hr
= IDWriteFontFace1_GetUnicodeRanges(fontface1
, 0, NULL
, &count
);
3760 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
3761 ok(count
> 0, "got %u\n", count
);
3764 hr
= IDWriteFontFace1_GetUnicodeRanges(fontface1
, 1, NULL
, &count
);
3765 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
3766 ok(count
== 0, "got %u\n", count
);
3769 hr
= IDWriteFontFace1_GetUnicodeRanges(fontface1
, 1, &r
, &count
);
3770 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
3771 ok(count
> 1, "got %u\n", count
);
3773 ranges
= heap_alloc(count
*sizeof(DWRITE_UNICODE_RANGE
));
3774 hr
= IDWriteFontFace1_GetUnicodeRanges(fontface1
, count
, ranges
, &count
);
3775 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3777 ranges
[0].first
= ranges
[0].last
= 0;
3778 hr
= IDWriteFontFace1_GetUnicodeRanges(fontface1
, 1, ranges
, &count
);
3779 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
3780 ok(ranges
[0].first
!= 0 && ranges
[0].last
!= 0, "got 0x%x-0x%0x\n", ranges
[0].first
, ranges
[0].last
);
3784 hr
= IDWriteFactory_UnregisterFontFileLoader(factory
, &rloader
);
3785 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3787 IDWriteFontFace1_Release(fontface1
);
3789 if (strcmp(winetest_platform
, "wine")) {
3791 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &syscollection
, FALSE
);
3792 ok(hr
== S_OK
, "Failed to get system collection, hr %#x.\n", hr
);
3794 count
= IDWriteFontCollection_GetFontFamilyCount(syscollection
);
3796 for (i
= 0; i
< count
; i
++) {
3797 WCHAR familynameW
[256], facenameW
[128];
3798 IDWriteLocalizedStrings
*names
;
3799 IDWriteFontFamily
*family
;
3800 UINT32 j
, k
, fontcount
;
3803 hr
= IDWriteFontCollection_GetFontFamily(syscollection
, i
, &family
);
3804 ok(hr
== S_OK
, "Failed to get font family, hr %#x.\n", hr
);
3806 hr
= IDWriteFontFamily_GetFamilyNames(family
, &names
);
3807 ok(hr
== S_OK
, "Failed to get family names, hr %#x.\n", hr
);
3809 get_enus_string(names
, familynameW
, ARRAY_SIZE(familynameW
));
3810 IDWriteLocalizedStrings_Release(names
);
3812 fontcount
= IDWriteFontFamily_GetFontCount(family
);
3813 for (j
= 0; j
< fontcount
; j
++) {
3814 DWRITE_UNICODE_RANGE
*expected_ranges
= NULL
;
3815 UINT32 range_count
, expected_count
;
3817 hr
= IDWriteFontFamily_GetFont(family
, j
, &font
);
3818 ok(hr
== S_OK
, "Failed to get font, hr %#x.\n", hr
);
3820 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
3821 ok(hr
== S_OK
, "Failed to create fontface, hr %#x.\n", hr
);
3823 hr
= IDWriteFont_GetFaceNames(font
, &names
);
3824 ok(hr
== S_OK
, "Failed to get face names, hr %#x.\n", hr
);
3825 IDWriteFont_Release(font
);
3827 get_enus_string(names
, facenameW
, ARRAY_SIZE(facenameW
));
3829 IDWriteLocalizedStrings_Release(names
);
3831 if (IDWriteFontFace_IsSymbolFont(fontface
))
3835 skip("GetUnicodeRanges() test does not support symbol fonts.\n");
3836 IDWriteFontFace_Release(fontface
);
3840 IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void **)&fontface1
);
3842 hr
= IDWriteFontFace1_GetUnicodeRanges(fontface1
, 0, NULL
, &range_count
);
3843 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "Unexpected hr %#x.\n", hr
);
3845 ranges
= heap_alloc(range_count
* sizeof(*ranges
));
3847 hr
= IDWriteFontFace1_GetUnicodeRanges(fontface1
, range_count
, ranges
, &range_count
);
3848 ok(hr
== S_OK
, "Failed to get ranges, hr %#x.\n", hr
);
3850 expected_count
= fontface_get_expected_unicode_ranges(fontface1
, &expected_ranges
);
3851 ok(expected_count
== range_count
, "%s - %s: unexpected range count %u, expected %u.\n",
3852 wine_dbgstr_w(familynameW
), wine_dbgstr_w(facenameW
), range_count
, expected_count
);
3854 if (expected_count
== range_count
) {
3855 if (memcmp(expected_ranges
, ranges
, expected_count
* sizeof(*ranges
))) {
3856 for (k
= 0; k
< expected_count
; ++k
) {
3857 BOOL failed
= memcmp(&expected_ranges
[k
], &ranges
[k
], sizeof(*ranges
));
3858 ok(!failed
, "%u: %s - %s mismatching range [%#x, %#x] vs [%#x, %#x].\n", k
,
3859 wine_dbgstr_w(familynameW
), wine_dbgstr_w(facenameW
), ranges
[k
].first
, ranges
[k
].last
,
3860 expected_ranges
[k
].first
, expected_ranges
[k
].last
);
3867 heap_free(expected_ranges
);
3870 IDWriteFontFace1_Release(fontface1
);
3871 IDWriteFontFace_Release(fontface
);
3874 IDWriteFontFamily_Release(family
);
3877 IDWriteFontCollection_Release(syscollection
);
3879 ref
= IDWriteFactory_Release(factory
);
3880 ok(ref
== 0, "factory not released, %u\n", ref
);
3883 static void test_GetFontFromFontFace(void)
3885 IDWriteFontFace
*fontface
, *fontface2
;
3886 IDWriteFontCollection
*collection
;
3887 IDWriteFont
*font
, *font2
, *font3
;
3888 IDWriteFontFamily
*family
;
3889 IDWriteFactory
*factory
;
3890 IDWriteFontFile
*file
;
3895 factory
= create_factory();
3897 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &collection
, FALSE
);
3898 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3900 hr
= IDWriteFontCollection_GetFontFamily(collection
, 0, &family
);
3901 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3903 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
,
3904 DWRITE_FONT_STRETCH_NORMAL
, DWRITE_FONT_STYLE_NORMAL
, &font
);
3905 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3907 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
3908 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3911 hr
= IDWriteFontCollection_GetFontFromFontFace(collection
, fontface
, &font2
);
3912 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3913 ok(font2
!= font
, "got %p, %p\n", font2
, font
);
3916 hr
= IDWriteFontCollection_GetFontFromFontFace(collection
, fontface
, &font3
);
3917 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3918 ok(font3
!= font
&& font3
!= font2
, "got %p, %p, %p\n", font3
, font2
, font
);
3920 hr
= IDWriteFont_CreateFontFace(font2
, &fontface2
);
3921 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3922 ok(fontface2
== fontface
, "got %p, %p\n", fontface2
, fontface
);
3923 IDWriteFontFace_Release(fontface2
);
3925 hr
= IDWriteFont_CreateFontFace(font3
, &fontface2
);
3926 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3927 ok(fontface2
== fontface
, "got %p, %p\n", fontface2
, fontface
);
3928 IDWriteFontFace_Release(fontface2
);
3929 IDWriteFontFace_Release(fontface
);
3930 IDWriteFont_Release(font3
);
3931 IDWriteFactory_Release(factory
);
3933 /* fontface that wasn't created from this collection */
3934 factory
= create_factory();
3935 path
= create_testfontfile(test_fontfile
);
3937 hr
= IDWriteFactory_CreateFontFileReference(factory
, path
, NULL
, &file
);
3938 ok(hr
== S_OK
, "got 0x%08x\n",hr
);
3940 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_TRUETYPE
, 1, &file
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &fontface
);
3941 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3942 IDWriteFontFile_Release(file
);
3944 hr
= IDWriteFontCollection_GetFontFromFontFace(collection
, fontface
, &font3
);
3945 ok(hr
== DWRITE_E_NOFONT
, "got 0x%08x\n", hr
);
3946 ok(font3
== NULL
, "got %p\n", font3
);
3947 IDWriteFontFace_Release(fontface
);
3949 IDWriteFont_Release(font
);
3950 IDWriteFont_Release(font2
);
3951 IDWriteFontFamily_Release(family
);
3952 IDWriteFontCollection_Release(collection
);
3953 ref
= IDWriteFactory_Release(factory
);
3954 ok(ref
== 0, "factory not released, %u\n", ref
);
3955 DELETE_FONTFILE(path
);
3958 static void test_GetFirstMatchingFont(void)
3960 DWRITE_FONT_SIMULATIONS simulations
;
3961 IDWriteFontCollection
*collection
;
3962 IDWriteFontFamily
*family
;
3963 IDWriteFont
*font
, *font2
;
3964 IDWriteFactory
*factory
;
3968 factory
= create_factory();
3970 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &collection
, FALSE
);
3971 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3973 hr
= IDWriteFontCollection_GetFontFamily(collection
, 0, &family
);
3974 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3976 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
,
3977 DWRITE_FONT_STRETCH_NORMAL
, DWRITE_FONT_STYLE_NORMAL
, &font
);
3978 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3980 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
,
3981 DWRITE_FONT_STRETCH_NORMAL
, DWRITE_FONT_STYLE_NORMAL
, &font2
);
3982 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3983 ok(font
!= font2
, "got %p, %p\n", font
, font2
);
3984 IDWriteFont_Release(font
);
3985 IDWriteFont_Release(font2
);
3987 /* out-of-range font props are allowed */
3988 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, 1000, DWRITE_FONT_STRETCH_NORMAL
, DWRITE_FONT_STYLE_NORMAL
, &font
);
3989 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3990 IDWriteFont_Release(font
);
3992 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
, 10, DWRITE_FONT_STYLE_NORMAL
, &font
);
3993 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3994 IDWriteFont_Release(font
);
3996 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STRETCH_NORMAL
,
3998 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3999 IDWriteFont_Release(font
);
4001 IDWriteFontFamily_Release(family
);
4003 font
= get_tahoma_instance(factory
, DWRITE_FONT_STYLE_ITALIC
);
4004 simulations
= IDWriteFont_GetSimulations(font
);
4005 ok(simulations
== DWRITE_FONT_SIMULATIONS_OBLIQUE
, "%d\n", simulations
);
4006 IDWriteFont_Release(font
);
4008 IDWriteFontCollection_Release(collection
);
4009 ref
= IDWriteFactory_Release(factory
);
4010 ok(ref
== 0, "factory not released, %u\n", ref
);
4013 static void test_GetMatchingFonts(void)
4015 IDWriteFontCollection
*collection
;
4016 IDWriteFontFamily
*family
;
4017 IDWriteFactory
*factory
;
4018 IDWriteFontList
*fontlist
, *fontlist2
;
4019 IDWriteFontList1
*fontlist1
;
4020 IDWriteFontList2
*fontlist3
;
4024 factory
= create_factory();
4026 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &collection
, FALSE
);
4027 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4029 hr
= IDWriteFontCollection_GetFontFamily(collection
, 0, &family
);
4030 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4032 /* out-of-range font props are allowed */
4033 hr
= IDWriteFontFamily_GetMatchingFonts(family
, 1000, DWRITE_FONT_STRETCH_NORMAL
,
4034 DWRITE_FONT_STYLE_NORMAL
, &fontlist
);
4035 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4036 IDWriteFontList_Release(fontlist
);
4038 hr
= IDWriteFontFamily_GetMatchingFonts(family
, DWRITE_FONT_WEIGHT_NORMAL
, 10,
4039 DWRITE_FONT_STYLE_NORMAL
, &fontlist
);
4040 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4041 IDWriteFontList_Release(fontlist
);
4043 hr
= IDWriteFontFamily_GetMatchingFonts(family
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STRETCH_NORMAL
,
4045 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4046 IDWriteFontList_Release(fontlist
);
4048 hr
= IDWriteFontFamily_GetMatchingFonts(family
, DWRITE_FONT_WEIGHT_NORMAL
,
4049 DWRITE_FONT_STRETCH_NORMAL
, DWRITE_FONT_STYLE_NORMAL
, &fontlist
);
4050 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4052 hr
= IDWriteFontFamily_GetMatchingFonts(family
, DWRITE_FONT_WEIGHT_NORMAL
,
4053 DWRITE_FONT_STRETCH_NORMAL
, DWRITE_FONT_STYLE_NORMAL
, &fontlist2
);
4054 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4055 ok(fontlist
!= fontlist2
, "got %p, %p\n", fontlist
, fontlist2
);
4056 IDWriteFontList_Release(fontlist2
);
4058 hr
= IDWriteFontList_QueryInterface(fontlist
, &IID_IDWriteFontList1
, (void**)&fontlist1
);
4060 IDWriteFontFaceReference
*ref
, *ref1
;
4064 count
= IDWriteFontList1_GetFontCount(fontlist1
);
4065 ok(count
> 0, "got %u\n", count
);
4067 font
= (void*)0xdeadbeef;
4068 hr
= IDWriteFontList1_GetFont(fontlist1
, ~0u, &font
);
4069 ok(hr
== E_FAIL
, "got 0x%08x\n", hr
);
4070 ok(font
== NULL
, "got %p\n", font
);
4072 font
= (void*)0xdeadbeef;
4073 hr
= IDWriteFontList1_GetFont(fontlist1
, count
, &font
);
4074 ok(hr
== E_FAIL
, "got 0x%08x\n", hr
);
4075 ok(font
== NULL
, "got %p\n", font
);
4077 hr
= IDWriteFontList1_GetFont(fontlist1
, 0, &font
);
4078 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4079 IDWriteFont3_Release(font
);
4081 hr
= IDWriteFontList1_GetFontFaceReference(fontlist1
, 0, &ref
);
4082 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4084 hr
= IDWriteFontList1_GetFontFaceReference(fontlist1
, 0, &ref1
);
4085 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4086 ok(ref
!= ref1
, "got %p, %p\n", ref
, ref1
);
4088 IDWriteFontFaceReference_Release(ref1
);
4089 IDWriteFontFaceReference_Release(ref
);
4090 IDWriteFontList1_Release(fontlist1
);
4093 win_skip("IDWriteFontList1 is not supported.\n");
4095 if (SUCCEEDED(IDWriteFontList_QueryInterface(fontlist
, &IID_IDWriteFontList2
, (void **)&fontlist3
)))
4097 IDWriteFontSet1
*fontset
, *fontset2
;
4099 hr
= IDWriteFontList2_GetFontSet(fontlist3
, &fontset
);
4100 ok(hr
== S_OK
, "Unexpected hr %#x.\n", hr
);
4102 hr
= IDWriteFontList2_GetFontSet(fontlist3
, &fontset2
);
4103 ok(hr
== S_OK
, "Unexpected hr %#x.\n", hr
);
4104 ok(fontset
!= fontset2
, "Unexpected instance.\n");
4106 IDWriteFontSet1_Release(fontset2
);
4107 IDWriteFontSet1_Release(fontset
);
4109 IDWriteFontList2_Release(fontlist3
);
4112 win_skip("IDWriteFontList2 is not supported.\n");
4114 IDWriteFontList_Release(fontlist
);
4115 IDWriteFontFamily_Release(family
);
4117 IDWriteFontCollection_Release(collection
);
4118 ref
= IDWriteFactory_Release(factory
);
4119 ok(ref
== 0, "factory not released, %u\n", ref
);
4122 static void test_GetInformationalStrings(void)
4124 IDWriteLocalizedStrings
*strings
, *strings2
;
4125 IDWriteFontCollection
*collection
;
4126 IDWriteFontFace3
*fontface3
;
4127 IDWriteFontFace
*fontface
;
4128 IDWriteFontFamily
*family
;
4129 IDWriteFactory
*factory
;
4135 factory
= create_factory();
4137 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &collection
, FALSE
);
4138 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4140 hr
= IDWriteFontCollection_GetFontFamily(collection
, 0, &family
);
4141 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4143 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
,
4144 DWRITE_FONT_STRETCH_NORMAL
, DWRITE_FONT_STYLE_NORMAL
, &font
);
4145 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4148 strings
= (void*)0xdeadbeef;
4149 hr
= IDWriteFont_GetInformationalStrings(font
, DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_CID_NAME
+1, &strings
, &exists
);
4150 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4151 ok(exists
== FALSE
, "got %d\n", exists
);
4152 ok(strings
== NULL
, "got %p\n", strings
);
4156 hr
= IDWriteFont_GetInformationalStrings(font
, DWRITE_INFORMATIONAL_STRING_NONE
, &strings
, &exists
);
4157 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4158 ok(exists
== FALSE
, "got %d\n", exists
);
4162 hr
= IDWriteFont_GetInformationalStrings(font
, DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES
, &strings
, &exists
);
4163 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4164 ok(exists
== TRUE
, "got %d\n", exists
);
4166 /* strings instance is not reused */
4168 hr
= IDWriteFont_GetInformationalStrings(font
, DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES
, &strings2
, &exists
);
4169 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4170 ok(strings2
!= strings
, "got %p, %p\n", strings2
, strings
);
4172 IDWriteLocalizedStrings_Release(strings
);
4173 IDWriteLocalizedStrings_Release(strings2
);
4175 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
4176 ok(hr
== S_OK
, "Failed to create fontface, hr %#x.\n", hr
);
4178 if (SUCCEEDED(hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace3
, (void **)&fontface3
)))
4180 hr
= IDWriteFontFace3_GetInformationalStrings(fontface3
, DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES
,
4182 ok(hr
== S_OK
, "Failed to get info strings, hr %#x.\n", hr
);
4183 IDWriteLocalizedStrings_Release(strings
);
4185 IDWriteFontFace3_Release(fontface3
);
4188 win_skip("IDWriteFontFace3::GetInformationalStrings() is not supported.\n");
4190 IDWriteFontFace_Release(fontface
);
4192 IDWriteFont_Release(font
);
4193 IDWriteFontFamily_Release(family
);
4194 IDWriteFontCollection_Release(collection
);
4195 ref
= IDWriteFactory_Release(factory
);
4196 ok(ref
== 0, "factory not released, %u\n", ref
);
4199 static void test_GetGdiInterop(void)
4201 IDWriteGdiInterop
*interop
, *interop2
;
4202 IDWriteFactory
*factory
, *factory2
;
4208 factory
= create_factory();
4211 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop
);
4212 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4215 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop2
);
4216 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4217 ok(interop
== interop2
, "got %p, %p\n", interop
, interop2
);
4218 IDWriteGdiInterop_Release(interop2
);
4220 hr
= DWriteCreateFactory(DWRITE_FACTORY_TYPE_ISOLATED
, &IID_IDWriteFactory
, (IUnknown
**)&factory2
);
4221 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4223 /* each factory gets its own interop */
4225 hr
= IDWriteFactory_GetGdiInterop(factory2
, &interop2
);
4226 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4227 ok(interop
!= interop2
, "got %p, %p\n", interop
, interop2
);
4229 /* release factory - interop still works */
4230 IDWriteFactory_Release(factory2
);
4232 memset(&logfont
, 0, sizeof(logfont
));
4233 logfont
.lfHeight
= 12;
4234 logfont
.lfWidth
= 12;
4235 logfont
.lfWeight
= FW_NORMAL
;
4236 logfont
.lfItalic
= 1;
4237 lstrcpyW(logfont
.lfFaceName
, L
"Tahoma");
4239 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop2
, &logfont
, &font
);
4240 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4241 IDWriteFont_Release(font
);
4243 IDWriteGdiInterop_Release(interop2
);
4244 IDWriteGdiInterop_Release(interop
);
4245 ref
= IDWriteFactory_Release(factory
);
4246 ok(ref
== 0, "factory not released, %u\n", ref
);
4249 static void *map_font_file(const WCHAR
*filename
, DWORD
*file_size
)
4251 HANDLE file
, mapping
;
4254 file
= CreateFileW(filename
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
, 0, 0);
4255 if (file
== INVALID_HANDLE_VALUE
) return NULL
;
4257 *file_size
= GetFileSize(file
, NULL
);
4259 mapping
= CreateFileMappingA(file
, NULL
, PAGE_READONLY
, 0, 0, NULL
);
4266 ptr
= MapViewOfFile(mapping
, FILE_MAP_READ
, 0, 0, 0);
4269 CloseHandle(mapping
);
4273 struct font_realization_info
4284 static void test_CreateFontFaceFromHdc(void)
4286 IDWriteFontFileStream
*stream
, *stream2
;
4287 void *font_data
, *fragment_context
;
4288 struct font_realization_info info
;
4289 const void *refkey
, *fragment
;
4290 IDWriteFontFileLoader
*loader
;
4291 DWORD data_size
, num_fonts
;
4292 IDWriteGdiInterop
*interop
;
4293 IDWriteFontFace
*fontface
;
4294 IDWriteFactory
*factory
;
4295 UINT64 size
, writetime
;
4296 IDWriteFontFile
*file
;
4297 HFONT hfont
, oldhfont
;
4298 UINT32 count
, dummy
;
4309 factory
= create_factory();
4311 pGetFontRealizationInfo
= (void *)GetProcAddress(GetModuleHandleA("gdi32"), "GetFontRealizationInfo");
4314 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop
);
4315 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4318 fontface
= (void*)0xdeadbeef;
4319 hr
= IDWriteGdiInterop_CreateFontFaceFromHdc(interop
, NULL
, &fontface
);
4320 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
4321 ok(fontface
== NULL
, "got %p\n", fontface
);
4323 fontface
= (void *)0xdeadbeef;
4324 hr
= IDWriteGdiInterop_CreateFontFaceFromHdc(interop
, (HDC
)0xdeadbeef, &fontface
);
4325 ok(hr
== E_FAIL
, "got 0x%08x\n", hr
);
4326 ok(fontface
== NULL
, "got %p\n", fontface
);
4328 memset(&logfont
, 0, sizeof(logfont
));
4329 logfont
.lfHeight
= 12;
4330 logfont
.lfWidth
= 12;
4331 logfont
.lfWeight
= FW_NORMAL
;
4332 logfont
.lfItalic
= 1;
4333 lstrcpyW(logfont
.lfFaceName
, L
"Tahoma");
4335 hfont
= CreateFontIndirectW(&logfont
);
4336 hdc
= CreateCompatibleDC(0);
4337 oldhfont
= SelectObject(hdc
, hfont
);
4340 hr
= IDWriteGdiInterop_CreateFontFaceFromHdc(interop
, hdc
, &fontface
);
4341 ok(hr
== S_OK
, "Failed to create font face, hr %#x.\n", hr
);
4344 hr
= IDWriteFontFace_GetFiles(fontface
, &count
, &file
);
4345 ok(hr
== S_OK
, "Failed to get font files, hr %#x.\n", hr
);
4347 hr
= IDWriteFontFile_GetLoader(file
, &loader
);
4348 ok(hr
== S_OK
, "Failed to get file loader, hr %#x.\n", hr
);
4350 hr
= IDWriteFontFileLoader_QueryInterface(loader
, &IID_IDWriteLocalFontFileLoader
, (void **)&unk
);
4351 ok(hr
== S_OK
|| broken(hr
== E_NOINTERFACE
) /* Vista */, "Expected local loader, hr %#x.\n", hr
);
4353 IUnknown_Release(unk
);
4355 IDWriteFontFileLoader_Release(loader
);
4356 IDWriteFontFile_Release(file
);
4358 IDWriteFontFace_Release(fontface
);
4359 DeleteObject(SelectObject(hdc
, oldhfont
));
4361 /* Select bitmap font MS Sans Serif, format that's not supported by DirectWrite. */
4362 memset(&lf
, 0, sizeof(lf
));
4364 strcpy(lf
.lfFaceName
, "MS Sans Serif");
4366 hfont
= CreateFontIndirectA(&lf
);
4367 oldhfont
= SelectObject(hdc
, hfont
);
4369 fontface
= (void *)0xdeadbeef;
4370 hr
= IDWriteGdiInterop_CreateFontFaceFromHdc(interop
, hdc
, &fontface
);
4371 ok(hr
== DWRITE_E_FILEFORMAT
|| broken(hr
== E_FAIL
) /* Vista */, "got 0x%08x\n", hr
);
4372 ok(fontface
== NULL
, "got %p\n", fontface
);
4374 DeleteObject(SelectObject(hdc
, oldhfont
));
4376 /* Memory resource font */
4377 path
= create_testfontfile(test_fontfile
);
4380 font_data
= map_font_file(path
, &data_size
);
4383 resource
= AddFontMemResourceEx(font_data
, data_size
, NULL
, &num_fonts
);
4384 ok(resource
!= NULL
, "Failed to add memory resource font, %d.\n", GetLastError());
4385 ok(num_fonts
== 1, "Unexpected number of fonts.\n");
4387 memset(&lf
, 0, sizeof(lf
));
4389 strcpy(lf
.lfFaceName
, "wine_test");
4391 hfont
= CreateFontIndirectA(&lf
);
4392 ok(hfont
!= NULL
, "Failed to create a font.\n");
4393 oldhfont
= SelectObject(hdc
, hfont
);
4395 hr
= IDWriteGdiInterop_CreateFontFaceFromHdc(interop
, hdc
, &fontface
);
4396 ok(hr
== S_OK
, "Failed to create fontface, hr %#x.\n", hr
);
4399 hr
= IDWriteFontFace_GetFiles(fontface
, &count
, &file
);
4400 ok(hr
== S_OK
, "Failed to get font files, hr %#x.\n", hr
);
4402 hr
= IDWriteFontFile_GetLoader(file
, &loader
);
4403 ok(hr
== S_OK
, "Failed to get file loader, hr %#x.\n", hr
);
4405 hr
= IDWriteFactory_RegisterFontFileLoader(factory
, loader
);
4406 ok(hr
== DWRITE_E_ALREADYREGISTERED
, "Unexpected hr %#x.\n", hr
);
4408 hr
= IDWriteFontFileLoader_QueryInterface(loader
, &IID_IDWriteInMemoryFontFileLoader
, (void **)&unk
);
4409 ok(hr
== E_NOINTERFACE
, "Unexpected hr %#x.\n", hr
);
4411 hr
= IDWriteFontFileLoader_QueryInterface(loader
, &IID_IDWriteLocalFontFileLoader
, (void **)&unk
);
4412 ok(hr
== E_NOINTERFACE
, "Unexpected hr %#x.\n", hr
);
4415 hr
= IDWriteFontFile_GetReferenceKey(file
, &refkey
, &count
);
4416 ok(hr
== S_OK
, "Failed to get ref key, hr %#x.\n", hr
);
4417 ok(count
> 0, "Unexpected key length %u.\n", count
);
4419 if (pGetFontRealizationInfo
)
4421 info
.size
= sizeof(info
);
4422 ret
= pGetFontRealizationInfo(hdc
, &info
);
4423 ok(ret
, "Failed to get realization info.\n");
4424 ok(count
== sizeof(info
.instance_id
), "Unexpected key size.\n");
4425 ok(*(DWORD
*)refkey
== info
.instance_id
, "Unexpected stream key.\n");
4428 win_skip("GetFontRealizationInfo() is not available.\n");
4430 hr
= IDWriteFontFileLoader_CreateStreamFromKey(loader
, refkey
, count
, &stream
);
4431 ok(hr
== S_OK
, "Failed to create file stream, hr %#x.\n", hr
);
4433 hr
= IDWriteFontFileLoader_CreateStreamFromKey(loader
, refkey
, count
, &stream2
);
4434 ok(hr
== S_OK
, "Failed to create file stream, hr %#x.\n", hr
);
4435 ok(stream2
!= stream
, "Unexpected stream instance.\n");
4436 IDWriteFontFileStream_Release(stream2
);
4439 hr
= IDWriteFontFileLoader_CreateStreamFromKey(loader
, &dummy
, count
, &stream2
);
4440 ok(hr
== S_OK
, "Failed to create file stream, hr %#x.\n", hr
);
4443 hr
= IDWriteFontFileStream_GetLastWriteTime(stream2
, &writetime
);
4444 ok(hr
== E_NOTIMPL
, "Unexpected hr %#x.\n", hr
);
4445 ok(writetime
== 1, "Unexpected write time.\n");
4447 IDWriteFontFileStream_Release(stream2
);
4449 hr
= IDWriteFontFileStream_GetFileSize(stream
, &size
);
4450 ok(hr
== S_OK
, "Failed to get stream size, hr %#x.\n", hr
);
4451 ok(size
== data_size
, "Unexpected stream size.\n");
4453 hr
= IDWriteFontFileStream_GetLastWriteTime(stream
, &writetime
);
4454 ok(hr
== E_NOTIMPL
, "Unexpected hr %#x.\n", hr
);
4456 fragment_context
= NULL
;
4457 hr
= IDWriteFontFileStream_ReadFileFragment(stream
, &fragment
, 0, size
, &fragment_context
);
4458 ok(hr
== S_OK
, "Failed to read fragment, hr %#x.\n", hr
);
4459 ok(fragment_context
!= NULL
, "Unexpected context %p.\n", fragment_context
);
4460 ok(fragment
== fragment_context
, "Unexpected data pointer %p, context %p.\n", fragment
, fragment_context
);
4461 IDWriteFontFileStream_ReleaseFileFragment(stream
, fragment_context
);
4463 hr
= IDWriteFontFileStream_ReadFileFragment(stream
, &fragment
, 0, size
+ 1, &fragment_context
);
4464 ok(FAILED(hr
), "Unexpected hr %#x.\n", hr
);
4466 hr
= IDWriteFontFileStream_ReadFileFragment(stream
, &fragment
, size
- 1, size
/ 2, &fragment_context
);
4467 ok(FAILED(hr
), "Unexpected hr %#x.\n", hr
);
4469 IDWriteFontFileStream_Release(stream
);
4471 IDWriteFontFileLoader_Release(loader
);
4472 IDWriteFontFile_Release(file
);
4474 IDWriteFontFace_Release(fontface
);
4476 ret
= RemoveFontMemResourceEx(resource
);
4477 ok(ret
, "Failed to remove memory resource font, %d.\n", GetLastError());
4479 UnmapViewOfFile(font_data
);
4481 DELETE_FONTFILE(path
);
4483 DeleteObject(SelectObject(hdc
, oldhfont
));
4485 IDWriteGdiInterop_Release(interop
);
4486 ref
= IDWriteFactory_Release(factory
);
4487 ok(ref
== 0, "factory not released, %u\n", ref
);
4490 static void test_GetSimulations(void)
4492 DWRITE_FONT_SIMULATIONS simulations
;
4493 IDWriteGdiInterop
*interop
;
4494 IDWriteFontFace
*fontface
;
4495 IDWriteFactory
*factory
;
4501 factory
= create_factory();
4503 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop
);
4504 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4506 memset(&logfont
, 0, sizeof(logfont
));
4507 logfont
.lfHeight
= 12;
4508 logfont
.lfWidth
= 12;
4509 logfont
.lfWeight
= FW_NORMAL
;
4510 logfont
.lfItalic
= 1;
4511 lstrcpyW(logfont
.lfFaceName
, L
"Tahoma");
4513 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font
);
4514 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4516 simulations
= IDWriteFont_GetSimulations(font
);
4517 ok(simulations
== DWRITE_FONT_SIMULATIONS_OBLIQUE
, "got %d\n", simulations
);
4518 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
4519 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4520 simulations
= IDWriteFontFace_GetSimulations(fontface
);
4521 ok(simulations
== DWRITE_FONT_SIMULATIONS_OBLIQUE
, "got %d\n", simulations
);
4522 IDWriteFontFace_Release(fontface
);
4523 IDWriteFont_Release(font
);
4525 memset(&logfont
, 0, sizeof(logfont
));
4526 logfont
.lfHeight
= 12;
4527 logfont
.lfWidth
= 12;
4528 logfont
.lfWeight
= FW_NORMAL
;
4529 logfont
.lfItalic
= 0;
4530 lstrcpyW(logfont
.lfFaceName
, L
"Tahoma");
4532 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font
);
4533 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4535 simulations
= IDWriteFont_GetSimulations(font
);
4536 ok(simulations
== DWRITE_FONT_SIMULATIONS_NONE
, "got %d\n", simulations
);
4537 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
4538 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4539 simulations
= IDWriteFontFace_GetSimulations(fontface
);
4540 ok(simulations
== DWRITE_FONT_SIMULATIONS_NONE
, "got %d\n", simulations
);
4541 IDWriteFontFace_Release(fontface
);
4542 IDWriteFont_Release(font
);
4544 IDWriteGdiInterop_Release(interop
);
4545 ref
= IDWriteFactory_Release(factory
);
4546 ok(ref
== 0, "factory not released, %u\n", ref
);
4549 static void test_GetFaceNames(void)
4551 IDWriteLocalizedStrings
*strings
, *strings2
, *strings3
;
4552 IDWriteFontFace3
*fontface3
;
4553 IDWriteGdiInterop
*interop
;
4554 IDWriteFontFace
*fontface
;
4555 IDWriteFactory
*factory
;
4556 UINT32 count
, index
;
4564 factory
= create_factory();
4566 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop
);
4567 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4569 memset(&logfont
, 0, sizeof(logfont
));
4570 logfont
.lfHeight
= 12;
4571 logfont
.lfWidth
= 12;
4572 logfont
.lfWeight
= FW_NORMAL
;
4573 logfont
.lfItalic
= 1;
4574 lstrcpyW(logfont
.lfFaceName
, L
"Tahoma");
4576 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font
);
4577 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4579 hr
= IDWriteFont_GetFaceNames(font
, &strings
);
4580 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4582 hr
= IDWriteFont_GetFaceNames(font
, &strings2
);
4583 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4584 ok(strings
!= strings2
, "got %p, %p\n", strings2
, strings
);
4585 IDWriteLocalizedStrings_Release(strings2
);
4587 count
= IDWriteLocalizedStrings_GetCount(strings
);
4588 ok(count
== 1, "got %d\n", count
);
4592 hr
= IDWriteLocalizedStrings_FindLocaleName(strings
, L
"en-Us", &index
, &exists
);
4593 ok(hr
== S_OK
, "Unexpected hr %#x.\n", hr
);
4594 ok(index
== 0 && exists
, "got %d, %d\n", index
, exists
);
4597 hr
= IDWriteLocalizedStrings_GetLocaleNameLength(strings
, 1, &count
);
4598 ok(hr
== E_FAIL
, "got 0x%08x\n", hr
);
4599 ok(count
== ~0, "got %d\n", count
);
4601 /* for simulated faces names are also simulated */
4603 hr
= IDWriteLocalizedStrings_GetLocaleName(strings
, 0, buffW
, ARRAY_SIZE(buffW
));
4604 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4605 ok(!lstrcmpW(buffW
, L
"en-us"), "Unexpected locale name %s.\n", wine_dbgstr_w(buffW
));
4608 hr
= IDWriteLocalizedStrings_GetString(strings
, 0, buffW
, ARRAY_SIZE(buffW
));
4609 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4610 ok(!lstrcmpW(buffW
, L
"Oblique"), "got %s\n", wine_dbgstr_w(buffW
));
4611 IDWriteLocalizedStrings_Release(strings
);
4613 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
4614 ok(hr
== S_OK
, "Failed to create a font face, hr %#x.\n", hr
);
4616 if (SUCCEEDED(IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace3
, (void **)&fontface3
)))
4618 hr
= IDWriteFontFace3_GetFaceNames(fontface3
, &strings2
);
4619 ok(hr
== S_OK
, "Failed to get face names, hr %#x.\n", hr
);
4621 hr
= IDWriteFontFace3_GetFaceNames(fontface3
, &strings3
);
4622 ok(hr
== S_OK
, "Failed to get face names, hr %#x.\n", hr
);
4623 ok(strings2
!= strings3
, "Unexpected instance.\n");
4624 IDWriteLocalizedStrings_Release(strings3
);
4627 hr
= IDWriteLocalizedStrings_GetString(strings2
, 0, buffW
, ARRAY_SIZE(buffW
));
4628 ok(hr
== S_OK
, "Failed to get a string, hr %#x.\n", hr
);
4629 ok(!lstrcmpW(buffW
, L
"Oblique"), "Unexpected name %s.\n", wine_dbgstr_w(buffW
));
4630 IDWriteLocalizedStrings_Release(strings2
);
4632 IDWriteFontFace3_Release(fontface3
);
4635 win_skip("GetFaceNames() is not supported.\n");
4637 IDWriteFontFace_Release(fontface
);
4639 IDWriteFont_Release(font
);
4640 IDWriteGdiInterop_Release(interop
);
4641 ref
= IDWriteFactory_Release(factory
);
4642 ok(ref
== 0, "factory not released, %u\n", ref
);
4651 static void test_TryGetFontTable(void)
4653 IDWriteLocalFontFileLoader
*localloader
;
4654 WIN32_FILE_ATTRIBUTE_DATA info
;
4655 const struct local_refkey
*key
;
4656 IDWriteFontFileLoader
*loader
;
4657 const void *table
, *table2
;
4658 IDWriteFontFace
*fontface
;
4659 void *context
, *context2
;
4660 IDWriteFactory
*factory
;
4661 IDWriteFontFile
*file
;
4662 WCHAR buffW
[MAX_PATH
];
4669 path
= create_testfontfile(test_fontfile
);
4671 factory
= create_factory();
4673 hr
= IDWriteFactory_CreateFontFileReference(factory
, path
, NULL
, &file
);
4674 ok(hr
== S_OK
, "got 0x%08x\n",hr
);
4678 hr
= IDWriteFontFile_GetReferenceKey(file
, (const void**)&key
, &size
);
4679 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4680 ok(size
!= 0, "got %u\n", size
);
4682 ret
= GetFileAttributesExW(path
, GetFileExInfoStandard
, &info
);
4683 ok(ret
, "got %d\n", ret
);
4684 ok(!memcmp(&info
.ftLastWriteTime
, &key
->writetime
, sizeof(key
->writetime
)), "got wrong write time\n");
4686 hr
= IDWriteFontFile_GetLoader(file
, &loader
);
4687 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4688 IDWriteFontFileLoader_QueryInterface(loader
, &IID_IDWriteLocalFontFileLoader
, (void**)&localloader
);
4689 IDWriteFontFileLoader_Release(loader
);
4691 hr
= IDWriteLocalFontFileLoader_GetFilePathLengthFromKey(localloader
, key
, size
, &len
);
4692 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4693 ok(lstrlenW(key
->name
) == len
, "path length %d\n", len
);
4695 hr
= IDWriteLocalFontFileLoader_GetFilePathFromKey(localloader
, key
, size
, buffW
, ARRAY_SIZE(buffW
));
4696 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4697 ok(!lstrcmpW(buffW
, key
->name
), "got %s, expected %s\n", wine_dbgstr_w(buffW
), wine_dbgstr_w(key
->name
));
4698 IDWriteLocalFontFileLoader_Release(localloader
);
4700 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_TRUETYPE
, 1, &file
, 0, 0, &fontface
);
4701 ok(hr
== S_OK
, "got 0x%08x\n",hr
);
4704 context
= (void*)0xdeadbeef;
4706 hr
= IDWriteFontFace_TryGetFontTable(fontface
, MS_CMAP_TAG
, &table
, &size
, &context
, &exists
);
4707 ok(hr
== S_OK
, "got 0x%08x\n",hr
);
4708 ok(exists
== TRUE
, "got %d\n", exists
);
4709 ok(context
== NULL
&& table
!= NULL
, "cmap: context %p, table %p\n", context
, table
);
4712 context2
= (void*)0xdeadbeef;
4714 hr
= IDWriteFontFace_TryGetFontTable(fontface
, MS_CMAP_TAG
, &table2
, &size
, &context2
, &exists
);
4715 ok(hr
== S_OK
, "got 0x%08x\n",hr
);
4716 ok(exists
== TRUE
, "got %d\n", exists
);
4717 ok(context2
== context
&& table2
== table
, "cmap: context2 %p, table2 %p\n", context2
, table2
);
4719 IDWriteFontFace_ReleaseFontTable(fontface
, context2
);
4720 IDWriteFontFace_ReleaseFontTable(fontface
, context
);
4722 /* table does not exist */
4724 context
= (void*)0xdeadbeef;
4725 table
= (void*)0xdeadbeef;
4726 hr
= IDWriteFontFace_TryGetFontTable(fontface
, 0xabababab, &table
, &size
, &context
, &exists
);
4727 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4728 ok(exists
== FALSE
, "got %d\n", exists
);
4729 ok(context
== NULL
&& table
== NULL
, "got context %p, table pointer %p\n", context
, table
);
4731 IDWriteFontFace_Release(fontface
);
4732 IDWriteFontFile_Release(file
);
4733 ref
= IDWriteFactory_Release(factory
);
4734 ok(ref
== 0, "factory not released, %u\n", ref
);
4735 DELETE_FONTFILE(path
);
4738 static void test_ConvertFontToLOGFONT(void)
4740 IDWriteFactory
*factory
, *factory2
;
4741 IDWriteFontCollection
*collection
;
4742 IDWriteGdiInterop
*interop
;
4743 IDWriteFontFamily
*family
;
4751 factory
= create_factory();
4752 factory2
= create_factory();
4755 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop
);
4756 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4758 hr
= IDWriteFactory_GetSystemFontCollection(factory2
, &collection
, FALSE
);
4759 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4761 hr
= IDWriteFontCollection_GetFontFamily(collection
, 0, &family
);
4762 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4764 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
,
4765 DWRITE_FONT_STRETCH_NORMAL
, DWRITE_FONT_STYLE_NORMAL
, &font
);
4766 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4768 if (0) { /* crashes on native */
4769 IDWriteGdiInterop_ConvertFontToLOGFONT(interop
, NULL
, NULL
, NULL
);
4770 IDWriteGdiInterop_ConvertFontToLOGFONT(interop
, NULL
, &logfont
, NULL
);
4771 IDWriteGdiInterop_ConvertFontToLOGFONT(interop
, font
, NULL
, &system
);
4774 memset(&logfont
, 0xcc, sizeof(logfont
));
4776 hr
= IDWriteGdiInterop_ConvertFontToLOGFONT(interop
, NULL
, &logfont
, &system
);
4777 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
4778 ok(!system
, "got %d\n", system
);
4779 ok(logfont
.lfFaceName
[0] == 0, "got face name %s\n", wine_dbgstr_w(logfont
.lfFaceName
));
4781 count
= IDWriteFontCollection_GetFontFamilyCount(collection
);
4782 for (i
= 0; i
< count
; i
++) {
4783 WCHAR nameW
[128], familynameW
[64], facenameW
[64];
4784 IDWriteLocalizedStrings
*names
;
4785 DWRITE_FONT_SIMULATIONS sim
;
4786 IDWriteFontFamily
*family
;
4787 UINT32 font_count
, j
;
4791 hr
= IDWriteFontCollection_GetFontFamily(collection
, i
, &family
);
4792 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4794 hr
= IDWriteFontFamily_GetFamilyNames(family
, &names
);
4795 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4797 get_enus_string(names
, familynameW
, ARRAY_SIZE(familynameW
));
4798 IDWriteLocalizedStrings_Release(names
);
4800 font_count
= IDWriteFontFamily_GetFontCount(family
);
4802 for (j
= 0; j
< font_count
; ++j
)
4804 IDWriteFontFace
*fontface
;
4805 BOOL has_variations
;
4807 hr
= IDWriteFontFamily_GetFont(family
, j
, &font
);
4808 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4810 hr
= IDWriteFont_GetFaceNames(font
, &names
);
4811 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4813 get_enus_string(names
, facenameW
, ARRAY_SIZE(facenameW
));
4814 IDWriteLocalizedStrings_Release(names
);
4816 lstrcpyW(nameW
, familynameW
);
4817 lstrcatW(nameW
, L
" ");
4818 lstrcatW(nameW
, facenameW
);
4820 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
4821 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4823 has_variations
= has_face_variations(fontface
);
4824 IDWriteFontFace_Release(fontface
);
4830 skip("ConvertFontToLOGFONT() test does not support variable fonts.\n");
4831 IDWriteFont_Release(font
);
4836 memset(&logfont
, 0xcc, sizeof(logfont
));
4837 hr
= IDWriteGdiInterop_ConvertFontToLOGFONT(interop
, font
, &logfont
, &system
);
4838 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4839 ok(system
, "got %d\n", system
);
4841 sim
= IDWriteFont_GetSimulations(font
);
4843 get_logfont_from_font(font
, &lf
);
4844 ok(logfont
.lfWeight
== lf
.lfWeight
, "%s: unexpected lfWeight %d, expected lfWeight %d, font weight %d, "
4845 "bold simulation %s\n", wine_dbgstr_w(nameW
), logfont
.lfWeight
, lf
.lfWeight
, IDWriteFont_GetWeight(font
),
4846 sim
& DWRITE_FONT_SIMULATIONS_BOLD
? "yes" : "no");
4847 ok(logfont
.lfItalic
== lf
.lfItalic
, "%s: unexpected italic flag %d, oblique simulation %s\n",
4848 wine_dbgstr_w(nameW
), logfont
.lfItalic
, sim
& DWRITE_FONT_SIMULATIONS_OBLIQUE
? "yes" : "no");
4849 ok(!lstrcmpW(logfont
.lfFaceName
, lf
.lfFaceName
), "%s: unexpected facename %s, expected %s\n",
4850 wine_dbgstr_w(nameW
), wine_dbgstr_w(logfont
.lfFaceName
), wine_dbgstr_w(lf
.lfFaceName
));
4852 ok(logfont
.lfOutPrecision
== OUT_OUTLINE_PRECIS
, "%s: unexpected output precision %d\n", wine_dbgstr_w(nameW
),
4853 logfont
.lfOutPrecision
);
4854 ok(logfont
.lfClipPrecision
== CLIP_DEFAULT_PRECIS
, "%s: unexpected clipping precision %d\n", wine_dbgstr_w(nameW
),
4855 logfont
.lfClipPrecision
);
4856 ok(logfont
.lfQuality
== DEFAULT_QUALITY
, "%s: unexpected quality %d\n", wine_dbgstr_w(nameW
), logfont
.lfQuality
);
4857 ok(logfont
.lfPitchAndFamily
== DEFAULT_PITCH
, "%s: unexpected pitch %d\n", wine_dbgstr_w(nameW
),
4858 logfont
.lfPitchAndFamily
);
4860 IDWriteFont_Release(font
);
4863 IDWriteFontFamily_Release(family
);
4866 IDWriteFactory_Release(factory2
);
4868 IDWriteFontCollection_Release(collection
);
4869 IDWriteFontFamily_Release(family
);
4870 IDWriteFont_Release(font
);
4871 IDWriteGdiInterop_Release(interop
);
4872 ref
= IDWriteFactory_Release(factory
);
4873 ok(ref
== 0, "factory not released, %u\n", ref
);
4876 static void test_CreateStreamFromKey(void)
4878 IDWriteLocalFontFileLoader
*localloader
;
4879 IDWriteFontFileStream
*stream
, *stream2
;
4880 IDWriteFontFileLoader
*loader
;
4881 IDWriteFactory
*factory
;
4882 IDWriteFontFile
*file
;
4890 factory
= create_factory();
4892 path
= create_testfontfile(test_fontfile
);
4894 hr
= IDWriteFactory_CreateFontFileReference(factory
, path
, NULL
, &file
);
4895 ok(hr
== S_OK
, "got 0x%08x\n",hr
);
4899 hr
= IDWriteFontFile_GetReferenceKey(file
, (const void**)&key
, &size
);
4900 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4901 ok(size
!= 0, "got %u\n", size
);
4903 hr
= IDWriteFontFile_GetLoader(file
, &loader
);
4904 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4905 IDWriteFontFileLoader_QueryInterface(loader
, &IID_IDWriteLocalFontFileLoader
, (void**)&localloader
);
4906 IDWriteFontFileLoader_Release(loader
);
4908 hr
= IDWriteLocalFontFileLoader_CreateStreamFromKey(localloader
, key
, size
, &stream
);
4909 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4910 EXPECT_REF(stream
, 1);
4912 hr
= IDWriteLocalFontFileLoader_CreateStreamFromKey(localloader
, key
, size
, &stream2
);
4913 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4914 ok(stream
== stream2
|| broken(stream
!= stream2
) /* Win7 SP0 */, "got %p, %p\n", stream
, stream2
);
4915 if (stream
== stream2
)
4916 EXPECT_REF(stream
, 2);
4917 IDWriteFontFileStream_Release(stream
);
4918 IDWriteFontFileStream_Release(stream2
);
4920 hr
= IDWriteLocalFontFileLoader_CreateStreamFromKey(localloader
, key
, size
, &stream
);
4921 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4922 EXPECT_REF(stream
, 1);
4925 hr
= IDWriteFontFileStream_GetLastWriteTime(stream
, &writetime
);
4926 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4927 ok(writetime
!= 0, "got %s\n", wine_dbgstr_longlong(writetime
));
4929 IDWriteFontFileStream_Release(stream
);
4930 IDWriteFontFile_Release(file
);
4932 IDWriteLocalFontFileLoader_Release(localloader
);
4933 ref
= IDWriteFactory_Release(factory
);
4934 ok(ref
== 0, "factory not released, %u\n", ref
);
4935 DELETE_FONTFILE(path
);
4938 static void test_ReadFileFragment(void)
4940 IDWriteLocalFontFileLoader
*localloader
;
4941 IDWriteFontFileStream
*stream
;
4942 IDWriteFontFileLoader
*loader
;
4943 IDWriteFactory
*factory
;
4944 IDWriteFontFile
*file
;
4945 const void *fragment
, *fragment2
;
4946 void *key
, *context
, *context2
;
4953 factory
= create_factory();
4955 path
= create_testfontfile(test_fontfile
);
4957 hr
= IDWriteFactory_CreateFontFileReference(factory
, path
, NULL
, &file
);
4958 ok(hr
== S_OK
, "got 0x%08x\n",hr
);
4962 hr
= IDWriteFontFile_GetReferenceKey(file
, (const void**)&key
, &size
);
4963 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4964 ok(size
!= 0, "got %u\n", size
);
4966 hr
= IDWriteFontFile_GetLoader(file
, &loader
);
4967 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4968 IDWriteFontFileLoader_QueryInterface(loader
, &IID_IDWriteLocalFontFileLoader
, (void**)&localloader
);
4969 IDWriteFontFileLoader_Release(loader
);
4971 hr
= IDWriteLocalFontFileLoader_CreateStreamFromKey(localloader
, key
, size
, &stream
);
4972 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4974 hr
= IDWriteFontFileStream_GetFileSize(stream
, &filesize
);
4975 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4977 /* reading past the end of the stream */
4978 fragment
= (void*)0xdeadbeef;
4979 context
= (void*)0xdeadbeef;
4980 hr
= IDWriteFontFileStream_ReadFileFragment(stream
, &fragment
, 0, filesize
+1, &context
);
4981 ok(hr
== E_FAIL
, "got 0x%08x\n", hr
);
4982 ok(context
== NULL
, "got %p\n", context
);
4983 ok(fragment
== NULL
, "got %p\n", fragment
);
4985 fragment
= (void*)0xdeadbeef;
4986 context
= (void*)0xdeadbeef;
4987 hr
= IDWriteFontFileStream_ReadFileFragment(stream
, &fragment
, 0, filesize
, &context
);
4988 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4989 ok(context
== NULL
, "got %p\n", context
);
4990 ok(fragment
!= NULL
, "got %p\n", fragment
);
4992 fragment2
= (void*)0xdeadbeef;
4993 context2
= (void*)0xdeadbeef;
4994 hr
= IDWriteFontFileStream_ReadFileFragment(stream
, &fragment2
, 0, filesize
, &context2
);
4995 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4996 ok(context2
== NULL
, "got %p\n", context2
);
4997 ok(fragment
== fragment2
, "got %p, %p\n", fragment
, fragment2
);
4999 IDWriteFontFileStream_ReleaseFileFragment(stream
, context
);
5000 IDWriteFontFileStream_ReleaseFileFragment(stream
, context2
);
5002 /* fragment is released, try again */
5003 fragment
= (void*)0xdeadbeef;
5004 context
= (void*)0xdeadbeef;
5005 hr
= IDWriteFontFileStream_ReadFileFragment(stream
, &fragment
, 0, filesize
, &context
);
5006 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5007 ok(context
== NULL
, "got %p\n", context
);
5008 ok(fragment
== fragment2
, "got %p, %p\n", fragment
, fragment2
);
5009 IDWriteFontFileStream_ReleaseFileFragment(stream
, context
);
5011 IDWriteFontFile_Release(file
);
5012 IDWriteFontFileStream_Release(stream
);
5013 IDWriteLocalFontFileLoader_Release(localloader
);
5014 ref
= IDWriteFactory_Release(factory
);
5015 ok(ref
== 0, "factory not released, %u\n", ref
);
5016 DELETE_FONTFILE(path
);
5019 static void test_GetDesignGlyphMetrics(void)
5021 DWRITE_GLYPH_METRICS metrics
[2];
5022 IDWriteFontFace
*fontface
;
5023 IDWriteFactory
*factory
;
5024 IDWriteFontFile
*file
;
5031 factory
= create_factory();
5033 path
= create_testfontfile(test_fontfile
);
5035 hr
= IDWriteFactory_CreateFontFileReference(factory
, path
, NULL
, &file
);
5036 ok(hr
== S_OK
, "got 0x%08x\n",hr
);
5038 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_TRUETYPE
, 1, &file
,
5039 0, DWRITE_FONT_SIMULATIONS_NONE
, &fontface
);
5040 ok(hr
== S_OK
, "got 0x%08x\n",hr
);
5041 IDWriteFontFile_Release(file
);
5045 hr
= IDWriteFontFace_GetGlyphIndices(fontface
, &codepoint
, 1, &indices
[0]);
5046 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5047 ok(indices
[0] > 0, "got %u\n", indices
[0]);
5049 hr
= IDWriteFontFace_GetDesignGlyphMetrics(fontface
, NULL
, 0, metrics
, FALSE
);
5050 ok(hr
== E_INVALIDARG
, "got 0x%08x\n",hr
);
5052 hr
= IDWriteFontFace_GetDesignGlyphMetrics(fontface
, NULL
, 1, metrics
, FALSE
);
5053 ok(hr
== E_INVALIDARG
, "got 0x%08x\n",hr
);
5055 hr
= IDWriteFontFace_GetDesignGlyphMetrics(fontface
, indices
, 0, metrics
, FALSE
);
5056 ok(hr
== S_OK
, "got 0x%08x\n",hr
);
5058 /* missing glyphs are ignored */
5060 memset(metrics
, 0xcc, sizeof(metrics
));
5061 hr
= IDWriteFontFace_GetDesignGlyphMetrics(fontface
, indices
, 2, metrics
, FALSE
);
5062 ok(hr
== S_OK
, "got 0x%08x\n",hr
);
5063 ok(metrics
[0].advanceWidth
== 1000, "got %d\n", metrics
[0].advanceWidth
);
5064 ok(metrics
[1].advanceWidth
== 0, "got %d\n", metrics
[1].advanceWidth
);
5066 IDWriteFontFace_Release(fontface
);
5067 ref
= IDWriteFactory_Release(factory
);
5068 ok(ref
== 0, "factory not released, %u\n", ref
);
5069 DELETE_FONTFILE(path
);
5072 static BOOL
get_expected_is_monospaced(IDWriteFontFace1
*fontface
, const DWRITE_PANOSE
*panose
)
5074 BOOL exists
, is_monospaced
= FALSE
;
5075 const TT_POST
*tt_post
;
5080 hr
= IDWriteFontFace1_TryGetFontTable(fontface
, MS_POST_TAG
, (const void **)&tt_post
, &size
,
5081 &post_context
, &exists
);
5082 ok(hr
== S_OK
, "Unexpected hr %#x.\n", hr
);
5086 is_monospaced
= !!tt_post
->fixed_pitch
;
5087 IDWriteFontFace1_ReleaseFontTable(fontface
, post_context
);
5091 is_monospaced
|= panose
->text
.proportion
== DWRITE_PANOSE_PROPORTION_MONOSPACED
;
5093 return is_monospaced
;
5096 static void test_IsMonospacedFont(void)
5098 IDWriteFontCollection
*collection
;
5099 IDWriteFactory1
*factory
;
5104 factory
= create_factory_iid(&IID_IDWriteFactory1
);
5108 win_skip("IsMonospacedFont() is not supported.\n");
5112 hr
= IDWriteFactory1_GetSystemFontCollection(factory
, &collection
, FALSE
);
5113 ok(hr
== S_OK
, "Failed to get font collection, hr %#x.\n", hr
);
5115 count
= IDWriteFontCollection_GetFontFamilyCount(collection
);
5116 for (i
= 0; i
< count
; ++i
)
5118 IDWriteLocalizedStrings
*names
;
5119 IDWriteFontFamily
*family
;
5120 UINT32 font_count
, j
;
5123 hr
= IDWriteFontCollection_GetFontFamily(collection
, i
, &family
);
5124 ok(hr
== S_OK
, "Failed to get family, hr %#x.\n", hr
);
5126 hr
= IDWriteFontFamily_GetFamilyNames(family
, &names
);
5127 ok(hr
== S_OK
, "Failed to get names, hr %#x.\n", hr
);
5128 get_enus_string(names
, nameW
, ARRAY_SIZE(nameW
));
5129 IDWriteLocalizedStrings_Release(names
);
5131 font_count
= IDWriteFontFamily_GetFontCount(family
);
5133 for (j
= 0; j
< font_count
; ++j
)
5135 BOOL is_monospaced_font
, is_monospaced_face
, is_monospaced_expected
;
5136 IDWriteFontFace1
*fontface1
;
5137 IDWriteFontFace
*fontface
;
5138 DWRITE_PANOSE panose
;
5139 IDWriteFont1
*font1
;
5142 hr
= IDWriteFontFamily_GetFont(family
, j
, &font
);
5143 ok(hr
== S_OK
, "Failed to get font, hr %#x.\n", hr
);
5145 hr
= IDWriteFont_QueryInterface(font
, &IID_IDWriteFont1
, (void **)&font1
);
5146 ok(hr
== S_OK
, "Failed to get interface, hr %#x.\n", hr
);
5147 IDWriteFont_Release(font
);
5149 hr
= IDWriteFont1_CreateFontFace(font1
, &fontface
);
5150 ok(hr
== S_OK
, "Failed to create fontface, hr %#x.\n", hr
);
5152 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void **)&fontface1
);
5153 ok(hr
== S_OK
, "Failed to get interface, hr %#x.\n", hr
);
5154 IDWriteFontFace_Release(fontface
);
5156 is_monospaced_font
= IDWriteFont1_IsMonospacedFont(font1
);
5157 is_monospaced_face
= IDWriteFontFace1_IsMonospacedFont(fontface1
);
5158 ok(is_monospaced_font
== is_monospaced_face
, "Unexpected monospaced flag.\n");
5160 IDWriteFont1_GetPanose(font1
, &panose
);
5162 is_monospaced_expected
= get_expected_is_monospaced(fontface1
, &panose
);
5163 ok(is_monospaced_expected
== is_monospaced_face
, "Unexpected is_monospaced flag %d for %s, font %d.\n",
5164 is_monospaced_face
, wine_dbgstr_w(nameW
), j
);
5166 IDWriteFontFace1_Release(fontface1
);
5167 IDWriteFont1_Release(font1
);
5170 IDWriteFontFamily_Release(family
);
5173 IDWriteFontCollection_Release(collection
);
5174 ref
= IDWriteFactory1_Release(factory
);
5175 ok(ref
== 0, "factory not released, %u\n", ref
);
5178 static void test_GetDesignGlyphAdvances(void)
5180 IDWriteFontFace1
*fontface1
;
5181 IDWriteFontFace
*fontface
;
5182 IDWriteFactory
*factory
;
5183 IDWriteFontFile
*file
;
5188 factory
= create_factory();
5190 path
= create_testfontfile(test_fontfile
);
5192 hr
= IDWriteFactory_CreateFontFileReference(factory
, path
, NULL
, &file
);
5193 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5195 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_TRUETYPE
, 1, &file
,
5196 0, DWRITE_FONT_SIMULATIONS_NONE
, &fontface
);
5197 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5198 IDWriteFontFile_Release(file
);
5200 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void**)&fontface1
);
5208 hr
= IDWriteFontFace1_GetGlyphIndices(fontface1
, &codepoint
, 1, &index
);
5209 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5210 ok(index
> 0, "got %u\n", index
);
5213 hr
= IDWriteFontFace1_GetDesignGlyphAdvances(fontface1
, 1, &index
, &advance
, FALSE
);
5214 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5215 ok(advance
== 1000, "got %i\n", advance
);
5218 hr
= IDWriteFontFace1_GetDesignGlyphAdvances(fontface1
, 1, &index
, &advance
, TRUE
);
5219 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5221 ok(advance
== 2048, "got %i\n", advance
);
5223 IDWriteFontFace1_Release(fontface1
);
5226 win_skip("GetDesignGlyphAdvances() is not supported.\n");
5228 IDWriteFontFace_Release(fontface
);
5229 ref
= IDWriteFactory_Release(factory
);
5230 ok(ref
== 0, "factory not released, %u\n", ref
);
5231 DELETE_FONTFILE(path
);
5234 static void test_GetGlyphRunOutline(void)
5236 DWRITE_GLYPH_OFFSET offsets
[2];
5237 IDWriteFactory
*factory
;
5238 IDWriteFontFile
*file
;
5239 IDWriteFontFace
*face
;
5247 path
= create_testfontfile(test_fontfile
);
5248 factory
= create_factory();
5250 hr
= IDWriteFactory_CreateFontFileReference(factory
, path
, NULL
, &file
);
5251 ok(hr
== S_OK
, "got 0x%08x\n",hr
);
5253 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_TRUETYPE
, 1, &file
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &face
);
5254 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5255 IDWriteFontFile_Release(file
);
5259 hr
= IDWriteFontFace_GetGlyphIndices(face
, &codepoint
, 1, glyphs
);
5260 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5261 ok(glyphs
[0] > 0, "got %u\n", glyphs
[0]);
5262 glyphs
[1] = glyphs
[0];
5264 hr
= IDWriteFontFace_GetGlyphRunOutline(face
, 2048.0, glyphs
, advances
, offsets
, 1, FALSE
, FALSE
, NULL
);
5265 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5267 hr
= IDWriteFontFace_GetGlyphRunOutline(face
, 2048.0, NULL
, NULL
, offsets
, 1, FALSE
, FALSE
, &test_geomsink
);
5268 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5273 offsets
[0].advanceOffset
= 1.0;
5274 offsets
[0].ascenderOffset
= 1.0;
5275 offsets
[1].advanceOffset
= 0.0;
5276 offsets
[1].ascenderOffset
= 0.0;
5278 /* default advances, no offsets */
5279 memset(g_startpoints
, 0, sizeof(g_startpoints
));
5280 g_startpoint_count
= 0;
5281 SET_EXPECT(setfillmode
);
5282 hr
= IDWriteFontFace_GetGlyphRunOutline(face
, 1024.0, glyphs
, NULL
, NULL
, 2, FALSE
, FALSE
, &test_geomsink
);
5283 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5284 ok(g_startpoint_count
== 2, "got %d\n", g_startpoint_count
);
5285 if (g_startpoint_count
== 2) {
5286 /* glyph advance of 500 is applied */
5287 ok(g_startpoints
[0].x
== 229.5 && g_startpoints
[0].y
== -629.0, "0: got (%.2f,%.2f)\n", g_startpoints
[0].x
, g_startpoints
[0].y
);
5288 ok(g_startpoints
[1].x
== 729.5 && g_startpoints
[1].y
== -629.0, "1: got (%.2f,%.2f)\n", g_startpoints
[1].x
, g_startpoints
[1].y
);
5290 CHECK_CALLED(setfillmode
);
5292 /* default advances, no offsets, RTL */
5293 memset(g_startpoints
, 0, sizeof(g_startpoints
));
5294 g_startpoint_count
= 0;
5295 SET_EXPECT(setfillmode
);
5296 hr
= IDWriteFontFace_GetGlyphRunOutline(face
, 1024.0, glyphs
, NULL
, NULL
, 2, FALSE
, TRUE
, &test_geomsink
);
5297 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5298 ok(g_startpoint_count
== 2, "got %d\n", g_startpoint_count
);
5299 if (g_startpoint_count
== 2) {
5300 /* advance is -500 now */
5301 ok(g_startpoints
[0].x
== -270.5 && g_startpoints
[0].y
== -629.0, "0: got (%.2f,%.2f)\n", g_startpoints
[0].x
, g_startpoints
[0].y
);
5302 ok(g_startpoints
[1].x
== -770.5 && g_startpoints
[1].y
== -629.0, "1: got (%.2f,%.2f)\n", g_startpoints
[1].x
, g_startpoints
[1].y
);
5304 CHECK_CALLED(setfillmode
);
5306 /* default advances, additional offsets */
5307 memset(g_startpoints
, 0, sizeof(g_startpoints
));
5308 g_startpoint_count
= 0;
5309 SET_EXPECT(setfillmode
);
5310 hr
= IDWriteFontFace_GetGlyphRunOutline(face
, 1024.0, glyphs
, NULL
, offsets
, 2, FALSE
, FALSE
, &test_geomsink
);
5311 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5312 ok(g_startpoint_count
== 2, "got %d\n", g_startpoint_count
);
5313 if (g_startpoint_count
== 2) {
5314 /* offsets applied to first contour */
5315 ok(g_startpoints
[0].x
== 230.5 && g_startpoints
[0].y
== -630.0, "0: got (%.2f,%.2f)\n", g_startpoints
[0].x
, g_startpoints
[0].y
);
5316 ok(g_startpoints
[1].x
== 729.5 && g_startpoints
[1].y
== -629.0, "1: got (%.2f,%.2f)\n", g_startpoints
[1].x
, g_startpoints
[1].y
);
5318 CHECK_CALLED(setfillmode
);
5320 /* default advances, additional offsets, RTL */
5321 memset(g_startpoints
, 0, sizeof(g_startpoints
));
5322 g_startpoint_count
= 0;
5323 SET_EXPECT(setfillmode
);
5324 hr
= IDWriteFontFace_GetGlyphRunOutline(face
, 1024.0, glyphs
, NULL
, offsets
, 2, FALSE
, TRUE
, &test_geomsink
);
5325 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5326 ok(g_startpoint_count
== 2, "got %d\n", g_startpoint_count
);
5327 if (g_startpoint_count
== 2) {
5328 ok(g_startpoints
[0].x
== -271.5 && g_startpoints
[0].y
== -630.0, "0: got (%.2f,%.2f)\n", g_startpoints
[0].x
, g_startpoints
[0].y
);
5329 ok(g_startpoints
[1].x
== -770.5 && g_startpoints
[1].y
== -629.0, "1: got (%.2f,%.2f)\n", g_startpoints
[1].x
, g_startpoints
[1].y
);
5331 CHECK_CALLED(setfillmode
);
5333 /* custom advances and offsets, offset turns total advance value to zero */
5334 memset(g_startpoints
, 0, sizeof(g_startpoints
));
5335 g_startpoint_count
= 0;
5336 SET_EXPECT(setfillmode
);
5337 hr
= IDWriteFontFace_GetGlyphRunOutline(face
, 1024.0, glyphs
, advances
, offsets
, 2, FALSE
, FALSE
, &test_geomsink
);
5338 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5339 ok(g_startpoint_count
== 2, "got %d\n", g_startpoint_count
);
5340 if (g_startpoint_count
== 2) {
5341 ok(g_startpoints
[0].x
== 230.5 && g_startpoints
[0].y
== -630.0, "0: got (%.2f,%.2f)\n", g_startpoints
[0].x
, g_startpoints
[0].y
);
5342 ok(g_startpoints
[1].x
== 230.5 && g_startpoints
[1].y
== -629.0, "1: got (%.2f,%.2f)\n", g_startpoints
[1].x
, g_startpoints
[1].y
);
5344 CHECK_CALLED(setfillmode
);
5347 hr
= IDWriteFontFace_GetGlyphRunOutline(face
, 1024.0, glyphs
, NULL
, NULL
, 0, FALSE
, FALSE
, &test_geomsink2
);
5348 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5350 /* Glyph with open figure, single contour point. */
5353 hr
= IDWriteFontFace_GetGlyphIndices(face
, &codepoint
, 1, glyphs
);
5354 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5355 ok(glyphs
[0] > 0, "got %u\n", glyphs
[0]);
5357 SET_EXPECT(setfillmode
);
5358 hr
= IDWriteFontFace_GetGlyphRunOutline(face
, 1024.0, glyphs
, NULL
, NULL
, 1, FALSE
, FALSE
, &test_geomsink2
);
5359 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5360 CHECK_CALLED(setfillmode
);
5362 IDWriteFactory_Release(factory
);
5363 IDWriteFontFace_Release(face
);
5364 DELETE_FONTFILE(path
);
5367 factory
= create_factory();
5368 face
= create_fontface(factory
);
5372 hr
= IDWriteFontFace_GetGlyphIndices(face
, &codepoint
, 1, glyphs
);
5373 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5374 ok(glyphs
[0] > 0, "got %u\n", glyphs
[0]);
5376 SET_EXPECT(setfillmode
);
5377 hr
= IDWriteFontFace_GetGlyphRunOutline(face
, 1024.0, glyphs
, NULL
, NULL
, 1, FALSE
, FALSE
, &test_geomsink2
);
5378 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5379 CHECK_CALLED(setfillmode
);
5381 IDWriteFontFace_Release(face
);
5382 ref
= IDWriteFactory_Release(factory
);
5383 ok(ref
== 0, "factory not released, %u\n", ref
);
5386 static void test_GetEudcFontCollection(void)
5388 IDWriteFontCollection
*coll
, *coll2
;
5389 IDWriteFactory1
*factory
;
5393 factory
= create_factory_iid(&IID_IDWriteFactory1
);
5395 win_skip("GetEudcFontCollection() is not supported.\n");
5399 EXPECT_REF(factory
, 1);
5400 hr
= IDWriteFactory1_GetEudcFontCollection(factory
, &coll
, FALSE
);
5401 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5402 EXPECT_REF(factory
, 2);
5403 hr
= IDWriteFactory1_GetEudcFontCollection(factory
, &coll2
, FALSE
);
5404 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5405 EXPECT_REF(factory
, 2);
5406 ok(coll
== coll2
, "got %p, %p\n", coll
, coll2
);
5407 IDWriteFontCollection_Release(coll
);
5408 IDWriteFontCollection_Release(coll2
);
5410 ref
= IDWriteFactory1_Release(factory
);
5411 ok(ref
== 0, "factory not released, %u\n", ref
);
5414 static void test_GetCaretMetrics(void)
5416 DWRITE_FONT_METRICS1 metrics
;
5417 IDWriteFontFace1
*fontface1
;
5418 DWRITE_CARET_METRICS caret
;
5419 IDWriteFontFace
*fontface
;
5420 IDWriteFactory
*factory
;
5421 IDWriteFontFile
*file
;
5427 path
= create_testfontfile(test_fontfile
);
5428 factory
= create_factory();
5430 hr
= IDWriteFactory_CreateFontFileReference(factory
, path
, NULL
, &file
);
5431 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5433 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_TRUETYPE
, 1, &file
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &fontface
);
5434 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5435 IDWriteFontFile_Release(file
);
5437 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void**)&fontface1
);
5438 IDWriteFontFace_Release(fontface
);
5440 win_skip("GetCaretMetrics() is not supported.\n");
5441 ref
= IDWriteFactory_Release(factory
);
5442 ok(ref
== 0, "factory not released, %u\n", ref
);
5443 DELETE_FONTFILE(path
);
5447 memset(&caret
, 0xcc, sizeof(caret
));
5448 IDWriteFontFace1_GetCaretMetrics(fontface1
, &caret
);
5449 ok(caret
.slopeRise
== 1, "got %d\n", caret
.slopeRise
);
5450 ok(caret
.slopeRun
== 0, "got %d\n", caret
.slopeRun
);
5451 ok(caret
.offset
== 0, "got %d\n", caret
.offset
);
5452 IDWriteFontFace1_Release(fontface1
);
5453 IDWriteFactory_Release(factory
);
5455 /* now with Tahoma Normal */
5456 factory
= create_factory();
5457 font
= get_tahoma_instance(factory
, DWRITE_FONT_STYLE_NORMAL
);
5458 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
5459 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5460 IDWriteFont_Release(font
);
5461 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void**)&fontface1
);
5462 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5463 IDWriteFontFace_Release(fontface
);
5465 memset(&caret
, 0xcc, sizeof(caret
));
5466 IDWriteFontFace1_GetCaretMetrics(fontface1
, &caret
);
5467 ok(caret
.slopeRise
== 1, "got %d\n", caret
.slopeRise
);
5468 ok(caret
.slopeRun
== 0, "got %d\n", caret
.slopeRun
);
5469 ok(caret
.offset
== 0, "got %d\n", caret
.offset
);
5470 IDWriteFontFace1_Release(fontface1
);
5472 /* simulated italic */
5473 font
= get_tahoma_instance(factory
, DWRITE_FONT_STYLE_ITALIC
);
5474 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
5475 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5476 IDWriteFont_Release(font
);
5477 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void**)&fontface1
);
5478 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5479 IDWriteFontFace_Release(fontface
);
5481 IDWriteFontFace1_GetMetrics(fontface1
, &metrics
);
5483 memset(&caret
, 0xcc, sizeof(caret
));
5484 IDWriteFontFace1_GetCaretMetrics(fontface1
, &caret
);
5485 ok(caret
.slopeRise
== metrics
.designUnitsPerEm
, "got %d\n", caret
.slopeRise
);
5486 ok(caret
.slopeRun
> 0, "got %d\n", caret
.slopeRun
);
5487 ok(caret
.offset
== 0, "got %d\n", caret
.offset
);
5488 IDWriteFontFace1_Release(fontface1
);
5490 ref
= IDWriteFactory_Release(factory
);
5491 ok(ref
== 0, "factory not released, %u\n", ref
);
5492 DELETE_FONTFILE(path
);
5495 static void test_GetGlyphCount(void)
5497 IDWriteFontFace
*fontface
;
5498 IDWriteFactory
*factory
;
5499 IDWriteFontFile
*file
;
5505 path
= create_testfontfile(test_fontfile
);
5506 factory
= create_factory();
5508 hr
= IDWriteFactory_CreateFontFileReference(factory
, path
, NULL
, &file
);
5509 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5511 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_TRUETYPE
, 1, &file
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &fontface
);
5512 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5513 IDWriteFontFile_Release(file
);
5515 count
= IDWriteFontFace_GetGlyphCount(fontface
);
5516 ok(count
== 8, "got %u\n", count
);
5518 IDWriteFontFace_Release(fontface
);
5519 ref
= IDWriteFactory_Release(factory
);
5520 ok(ref
== 0, "factory not released, %u\n", ref
);
5521 DELETE_FONTFILE(path
);
5524 static void test_GetKerningPairAdjustments(void)
5526 IDWriteFontFace1
*fontface1
;
5527 IDWriteFontFace
*fontface
;
5528 IDWriteFactory
*factory
;
5529 IDWriteFontFile
*file
;
5534 path
= create_testfontfile(test_fontfile
);
5535 factory
= create_factory();
5537 hr
= IDWriteFactory_CreateFontFileReference(factory
, path
, NULL
, &file
);
5538 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5540 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_TRUETYPE
, 1, &file
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &fontface
);
5541 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5542 IDWriteFontFile_Release(file
);
5544 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void**)&fontface1
);
5546 INT32 adjustments
[1];
5548 hr
= IDWriteFontFace1_GetKerningPairAdjustments(fontface1
, 0, NULL
, NULL
);
5549 ok(hr
== E_INVALIDARG
|| broken(hr
== S_OK
) /* win8 */, "got 0x%08x\n", hr
);
5551 if (0) /* crashes on native */
5552 hr
= IDWriteFontFace1_GetKerningPairAdjustments(fontface1
, 1, NULL
, NULL
);
5555 hr
= IDWriteFontFace1_GetKerningPairAdjustments(fontface1
, 1, NULL
, adjustments
);
5556 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5557 ok(adjustments
[0] == 0, "got %d\n", adjustments
[0]);
5559 IDWriteFontFace1_Release(fontface1
);
5562 win_skip("GetKerningPairAdjustments() is not supported.\n");
5564 IDWriteFontFace_Release(fontface
);
5565 ref
= IDWriteFactory_Release(factory
);
5566 ok(ref
== 0, "factory not released, %u\n", ref
);
5567 DELETE_FONTFILE(path
);
5570 static void test_CreateRenderingParams(void)
5572 IDWriteRenderingParams2
*params2
;
5573 IDWriteRenderingParams1
*params1
;
5574 IDWriteRenderingParams
*params
;
5575 DWRITE_RENDERING_MODE mode
;
5576 IDWriteFactory3
*factory3
;
5577 IDWriteFactory
*factory
;
5581 factory
= create_factory();
5583 hr
= IDWriteFactory_CreateCustomRenderingParams(factory
, 1.0, 0.0, 0.0, DWRITE_PIXEL_GEOMETRY_FLAT
,
5584 DWRITE_RENDERING_MODE_DEFAULT
, ¶ms
);
5585 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5587 hr
= IDWriteRenderingParams_QueryInterface(params
, &IID_IDWriteRenderingParams1
, (void**)¶ms1
);
5591 /* test what enhanced contrast setting set by default to */
5592 enhcontrast
= IDWriteRenderingParams1_GetGrayscaleEnhancedContrast(params1
);
5593 ok(enhcontrast
== 1.0, "got %.2f\n", enhcontrast
);
5594 IDWriteRenderingParams1_Release(params1
);
5596 hr
= IDWriteRenderingParams_QueryInterface(params
, &IID_IDWriteRenderingParams2
, (void**)¶ms2
);
5598 DWRITE_GRID_FIT_MODE gridfit
;
5600 /* default gridfit mode */
5601 gridfit
= IDWriteRenderingParams2_GetGridFitMode(params2
);
5602 ok(gridfit
== DWRITE_GRID_FIT_MODE_DEFAULT
, "got %d\n", gridfit
);
5604 IDWriteRenderingParams2_Release(params2
);
5607 win_skip("IDWriteRenderingParams2 not supported.\n");
5610 win_skip("IDWriteRenderingParams1 not supported.\n");
5612 IDWriteRenderingParams_Release(params
);
5614 hr
= IDWriteFactory_CreateRenderingParams(factory
, ¶ms
);
5615 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5617 mode
= IDWriteRenderingParams_GetRenderingMode(params
);
5618 ok(mode
== DWRITE_RENDERING_MODE_DEFAULT
, "got %d\n", mode
);
5619 IDWriteRenderingParams_Release(params
);
5621 hr
= IDWriteFactory_QueryInterface(factory
, &IID_IDWriteFactory3
, (void**)&factory3
);
5623 IDWriteRenderingParams3
*params3
;
5625 hr
= IDWriteFactory3_CreateCustomRenderingParams(factory3
, 1.0f
, 0.0f
, 0.0f
, 1.0f
, DWRITE_PIXEL_GEOMETRY_FLAT
,
5626 DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC_DOWNSAMPLED
, DWRITE_GRID_FIT_MODE_DEFAULT
, ¶ms3
);
5627 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5629 hr
= IDWriteRenderingParams3_QueryInterface(params3
, &IID_IDWriteRenderingParams
, (void**)¶ms
);
5630 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5632 mode
= IDWriteRenderingParams_GetRenderingMode(params
);
5633 ok(mode
== DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
, "got %d\n", mode
);
5635 IDWriteRenderingParams_Release(params
);
5636 IDWriteRenderingParams3_Release(params3
);
5637 IDWriteFactory3_Release(factory3
);
5640 win_skip("IDWriteRenderingParams3 not supported.\n");
5642 ref
= IDWriteFactory_Release(factory
);
5643 ok(ref
== 0, "factory not released, %u\n", ref
);
5646 static void test_CreateGlyphRunAnalysis(void)
5648 static const DWRITE_RENDERING_MODE rendermodes
[] = {
5649 DWRITE_RENDERING_MODE_ALIASED
,
5650 DWRITE_RENDERING_MODE_GDI_CLASSIC
,
5651 DWRITE_RENDERING_MODE_GDI_NATURAL
,
5652 DWRITE_RENDERING_MODE_NATURAL
,
5653 DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
,
5656 IDWriteGlyphRunAnalysis
*analysis
, *analysis2
;
5657 IDWriteRenderingParams
*params
;
5658 IDWriteFactory3
*factory3
;
5659 IDWriteFactory2
*factory2
;
5660 IDWriteFactory
*factory
;
5661 DWRITE_GLYPH_RUN run
;
5662 IDWriteFontFace
*face
;
5663 UINT16 glyph
, glyphs
[10];
5668 DWRITE_GLYPH_OFFSET offsets
[2];
5669 DWRITE_GLYPH_METRICS metrics
;
5670 DWRITE_FONT_METRICS fm
;
5677 factory
= create_factory();
5678 face
= create_fontface(factory
);
5682 hr
= IDWriteFontFace_GetGlyphIndices(face
, &ch
, 1, &glyph
);
5683 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5684 ok(glyph
> 0, "got %u\n", glyph
);
5686 hr
= IDWriteFontFace_GetDesignGlyphMetrics(face
, &glyph
, 1, &metrics
, FALSE
);
5687 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5688 advances
[0] = metrics
.advanceWidth
;
5690 offsets
[0].advanceOffset
= 0.0;
5691 offsets
[0].ascenderOffset
= 0.0;
5693 run
.fontFace
= face
;
5694 run
.fontEmSize
= 24.0;
5696 run
.glyphIndices
= &glyph
;
5697 run
.glyphAdvances
= advances
;
5698 run
.glyphOffsets
= offsets
;
5699 run
.isSideways
= FALSE
;
5703 analysis
= (void*)0xdeadbeef;
5704 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 0.0, NULL
,
5705 DWRITE_RENDERING_MODE_ALIASED
, DWRITE_MEASURING_MODE_NATURAL
,
5706 0.0, 0.0, &analysis
);
5707 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5708 ok(analysis
== NULL
, "got %p\n", analysis
);
5710 /* negative ppdip */
5711 analysis
= (void*)0xdeadbeef;
5712 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, -1.0, NULL
,
5713 DWRITE_RENDERING_MODE_ALIASED
, DWRITE_MEASURING_MODE_NATURAL
,
5714 0.0, 0.0, &analysis
);
5715 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5716 ok(analysis
== NULL
, "got %p\n", analysis
);
5718 /* default mode is not allowed */
5719 analysis
= (void*)0xdeadbeef;
5720 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 1.0, NULL
,
5721 DWRITE_RENDERING_MODE_DEFAULT
, DWRITE_MEASURING_MODE_NATURAL
,
5722 0.0, 0.0, &analysis
);
5723 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5724 ok(analysis
== NULL
, "got %p\n", analysis
);
5727 analysis
= (void*)0xdeadbeef;
5728 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 1.0, NULL
,
5729 DWRITE_RENDERING_MODE_OUTLINE
, DWRITE_MEASURING_MODE_NATURAL
,
5730 0.0, 0.0, &analysis
);
5731 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5732 ok(analysis
== NULL
, "got %p\n", analysis
);
5734 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 1.0, NULL
,
5735 DWRITE_RENDERING_MODE_ALIASED
, DWRITE_MEASURING_MODE_NATURAL
,
5736 0.0, 0.0, &analysis
);
5737 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5739 /* invalid texture type */
5740 memset(&rect
, 0xcc, sizeof(rect
));
5741 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_CLEARTYPE_3x1
+1, &rect
);
5742 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5743 ok(rect
.left
== 0 && rect
.right
== 0 &&
5744 rect
.top
== 0 && rect
.bottom
== 0, "unexpected rect\n");
5746 /* check how origin affects bounds */
5747 SetRectEmpty(&rect
);
5748 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect
);
5749 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5750 ok(!IsRectEmpty(&rect
), "got empty rect\n");
5751 IDWriteGlyphRunAnalysis_Release(analysis
);
5754 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 2.0, NULL
,
5755 DWRITE_RENDERING_MODE_ALIASED
, DWRITE_MEASURING_MODE_NATURAL
,
5756 0.0, 0.0, &analysis
);
5757 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5758 SetRectEmpty(&rect2
);
5759 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect2
);
5760 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5761 ok(rect
.right
- rect
.left
< rect2
.right
- rect2
.left
, "expected wider rect\n");
5762 ok(rect
.bottom
- rect
.top
< rect2
.bottom
- rect2
.top
, "expected taller rect\n");
5763 IDWriteGlyphRunAnalysis_Release(analysis
);
5765 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 1.0, NULL
,
5766 DWRITE_RENDERING_MODE_ALIASED
, DWRITE_MEASURING_MODE_NATURAL
,
5767 10.0, -5.0, &analysis
);
5768 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5770 SetRectEmpty(&rect2
);
5771 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect2
);
5772 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5773 ok(!IsRectEmpty(&rect2
), "got empty rect\n");
5774 IDWriteGlyphRunAnalysis_Release(analysis
);
5776 ok(!EqualRect(&rect
, &rect2
), "got equal bounds\n");
5777 OffsetRect(&rect
, 10, -5);
5778 ok(EqualRect(&rect
, &rect2
), "got different bounds\n");
5780 for (i
= 0; i
< ARRAY_SIZE(rendermodes
); i
++) {
5781 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 1.0, NULL
,
5782 rendermodes
[i
], DWRITE_MEASURING_MODE_NATURAL
,
5783 0.0, 0.0, &analysis
);
5784 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5786 if (rendermodes
[i
] == DWRITE_RENDERING_MODE_ALIASED
) {
5787 SetRectEmpty(&rect
);
5788 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect
);
5789 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5790 ok(!IsRectEmpty(&rect
), "got empty rect\n");
5792 SetRect(&rect
, 0, 0, 1, 1);
5793 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_CLEARTYPE_3x1
, &rect
);
5794 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5795 ok(IsRectEmpty(&rect
), "unexpected empty rect\n");
5798 SetRect(&rect
, 0, 0, 1, 1);
5799 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect
);
5800 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5801 ok(IsRectEmpty(&rect
), "got empty rect\n");
5803 SetRectEmpty(&rect
);
5804 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_CLEARTYPE_3x1
, &rect
);
5805 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5806 ok(!IsRectEmpty(&rect
), "got empty rect\n");
5809 IDWriteGlyphRunAnalysis_Release(analysis
);
5812 IDWriteFontFace_GetMetrics(run
.fontFace
, &fm
);
5814 /* check bbox for a single glyph run */
5815 for (run
.fontEmSize
= 1.0; run
.fontEmSize
<= 100.0; run
.fontEmSize
+= 1.0) {
5816 DWRITE_GLYPH_METRICS gm
;
5819 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 1.0, NULL
,
5820 DWRITE_RENDERING_MODE_ALIASED
, DWRITE_MEASURING_MODE_GDI_CLASSIC
,
5821 0.0, 0.0, &analysis
);
5822 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5824 SetRectEmpty(&rect
);
5825 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect
);
5826 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5828 hr
= IDWriteFontFace_GetGdiCompatibleGlyphMetrics(run
.fontFace
, run
.fontEmSize
, 1.0, NULL
,
5829 DWRITE_MEASURING_MODE_GDI_CLASSIC
, run
.glyphIndices
, 1, &gm
, run
.isSideways
);
5830 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5832 /* metrics are in design units */
5833 bboxX
= (int)floorf((gm
.advanceWidth
- gm
.leftSideBearing
- gm
.rightSideBearing
) * run
.fontEmSize
/ fm
.designUnitsPerEm
+ 0.5f
);
5834 bboxY
= (int)floorf((gm
.advanceHeight
- gm
.topSideBearing
- gm
.bottomSideBearing
) * run
.fontEmSize
/ fm
.designUnitsPerEm
+ 0.5f
);
5836 rect
.right
-= rect
.left
;
5837 rect
.bottom
-= rect
.top
;
5838 ok(abs(bboxX
- rect
.right
) <= 2, "%.0f: bbox width %d, from metrics %d\n", run
.fontEmSize
, rect
.right
, bboxX
);
5839 ok(abs(bboxY
- rect
.bottom
) <= 2, "%.0f: bbox height %d, from metrics %d\n", run
.fontEmSize
, rect
.bottom
, bboxY
);
5841 IDWriteGlyphRunAnalysis_Release(analysis
);
5844 /* without offsets */
5845 run
.fontFace
= face
;
5846 run
.fontEmSize
= 24.0;
5848 run
.glyphIndices
= &glyph
;
5849 run
.glyphAdvances
= advances
;
5850 run
.glyphOffsets
= NULL
;
5851 run
.isSideways
= FALSE
;
5854 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 1.0, NULL
,
5855 DWRITE_RENDERING_MODE_ALIASED
, DWRITE_MEASURING_MODE_NATURAL
,
5856 0.0, 0.0, &analysis
);
5857 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5859 SetRectEmpty(&rect
);
5860 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect
);
5861 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5862 ok(!IsRectEmpty(&rect
), "got empty bounds\n");
5864 IDWriteGlyphRunAnalysis_Release(analysis
);
5866 /* without explicit advances */
5867 run
.fontFace
= face
;
5868 run
.fontEmSize
= 24.0;
5870 run
.glyphIndices
= &glyph
;
5871 run
.glyphAdvances
= NULL
;
5872 run
.glyphOffsets
= NULL
;
5873 run
.isSideways
= FALSE
;
5876 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 1.0, NULL
,
5877 DWRITE_RENDERING_MODE_ALIASED
, DWRITE_MEASURING_MODE_NATURAL
,
5878 0.0, 0.0, &analysis
);
5879 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5881 SetRectEmpty(&rect
);
5882 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect
);
5883 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5884 ok(!IsRectEmpty(&rect
), "got empty bounds\n");
5886 IDWriteGlyphRunAnalysis_Release(analysis
);
5888 /* test that advances are scaled according to ppdip too */
5889 glyphs
[0] = glyphs
[1] = glyph
;
5890 advances
[0] = advances
[1] = 100.0f
;
5891 run
.fontFace
= face
;
5892 run
.fontEmSize
= 24.0;
5894 run
.glyphIndices
= glyphs
;
5895 run
.glyphAdvances
= advances
;
5896 run
.glyphOffsets
= NULL
;
5897 run
.isSideways
= FALSE
;
5900 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 1.0, NULL
,
5901 DWRITE_RENDERING_MODE_ALIASED
, DWRITE_MEASURING_MODE_NATURAL
,
5902 0.0, 0.0, &analysis
);
5903 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5905 SetRectEmpty(&rect2
);
5906 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect2
);
5907 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5908 ok(!IsRectEmpty(&rect2
), "got empty bounds\n");
5909 ok(!EqualRect(&rect
, &rect2
), "got wrong rect2\n");
5910 ok((rect2
.right
- rect
.left
) > advances
[0], "got rect width %d for advance %f\n", rect
.right
- rect
.left
, advances
[0]);
5911 IDWriteGlyphRunAnalysis_Release(analysis
);
5913 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 2.0, NULL
,
5914 DWRITE_RENDERING_MODE_ALIASED
, DWRITE_MEASURING_MODE_NATURAL
,
5915 0.0, 0.0, &analysis
);
5916 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5918 SetRectEmpty(&rect
);
5919 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect
);
5920 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5921 ok((rect
.right
- rect
.left
) > 2 * advances
[0], "got rect width %d for advance %f\n", rect
.right
- rect
.left
, advances
[0]);
5922 IDWriteGlyphRunAnalysis_Release(analysis
);
5924 /* with scaling transform */
5925 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 1.0, NULL
,
5926 DWRITE_RENDERING_MODE_ALIASED
, DWRITE_MEASURING_MODE_NATURAL
,
5927 0.0, 0.0, &analysis
);
5928 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5930 SetRectEmpty(&rect
);
5931 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect
);
5932 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5933 ok(!IsRectEmpty(&rect
), "got rect width %d\n", rect
.right
- rect
.left
);
5934 IDWriteGlyphRunAnalysis_Release(analysis
);
5936 memset(&m
, 0, sizeof(m
));
5939 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 1.0, &m
,
5940 DWRITE_RENDERING_MODE_ALIASED
, DWRITE_MEASURING_MODE_NATURAL
,
5941 0.0, 0.0, &analysis
);
5942 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5944 SetRectEmpty(&rect2
);
5945 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect2
);
5946 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5947 ok((rect2
.right
- rect2
.left
) > (rect
.right
- rect
.left
), "got rect width %d\n", rect2
.right
- rect2
.left
);
5949 /* instances are not reused for same runs */
5950 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 1.0, &m
,
5951 DWRITE_RENDERING_MODE_ALIASED
, DWRITE_MEASURING_MODE_NATURAL
,
5952 0.0, 0.0, &analysis2
);
5953 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5954 ok(analysis2
!= analysis
, "got %p, previous instance %p\n", analysis2
, analysis
);
5955 IDWriteGlyphRunAnalysis_Release(analysis2
);
5957 IDWriteGlyphRunAnalysis_Release(analysis
);
5959 if (IDWriteFactory_QueryInterface(factory
, &IID_IDWriteFactory2
, (void **)&factory2
) == S_OK
) {
5960 FLOAT gamma
, contrast
, cleartype_level
;
5962 /* Invalid antialias mode. */
5963 hr
= IDWriteFactory2_CreateGlyphRunAnalysis(factory2
, &run
, NULL
, DWRITE_RENDERING_MODE_ALIASED
,
5964 DWRITE_MEASURING_MODE_NATURAL
, DWRITE_GRID_FIT_MODE_DEFAULT
, DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
+ 1,
5965 0.0f
, 0.0f
, &analysis
);
5966 ok(hr
== E_INVALIDARG
, "Unexpected hr %#x.\n", hr
);
5968 /* Invalid grid fit mode. */
5969 hr
= IDWriteFactory2_CreateGlyphRunAnalysis(factory2
, &run
, NULL
, DWRITE_RENDERING_MODE_ALIASED
,
5970 DWRITE_MEASURING_MODE_NATURAL
, DWRITE_GRID_FIT_MODE_ENABLED
+ 1, DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
,
5971 0.0f
, 0.0f
, &analysis
);
5972 ok(hr
== E_INVALIDARG
, "Unexpected hr %#x.\n", hr
);
5974 /* Invalid rendering mode. */
5975 hr
= IDWriteFactory2_CreateGlyphRunAnalysis(factory2
, &run
, NULL
, DWRITE_RENDERING_MODE_OUTLINE
,
5976 DWRITE_MEASURING_MODE_NATURAL
, DWRITE_GRID_FIT_MODE_ENABLED
, DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
,
5977 0.0f
, 0.0f
, &analysis
);
5978 ok(hr
== E_INVALIDARG
, "Unexpected hr %#x.\n", hr
);
5980 /* Invalid measuring mode. */
5981 hr
= IDWriteFactory2_CreateGlyphRunAnalysis(factory2
, &run
, NULL
, DWRITE_RENDERING_MODE_ALIASED
,
5982 DWRITE_MEASURING_MODE_GDI_NATURAL
+ 1, DWRITE_GRID_FIT_MODE_ENABLED
, DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
,
5983 0.0f
, 0.0f
, &analysis
);
5984 ok(hr
== E_INVALIDARG
, "Unexpected hr %#x.\n", hr
);
5986 /* Win8 does not accept default grid fitting mode. */
5987 hr
= IDWriteFactory2_CreateGlyphRunAnalysis(factory2
, &run
, NULL
, DWRITE_RENDERING_MODE_NATURAL
,
5988 DWRITE_MEASURING_MODE_NATURAL
, DWRITE_GRID_FIT_MODE_DEFAULT
, DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
,
5989 0.0f
, 0.0f
, &analysis
);
5990 ok(hr
== S_OK
|| broken(hr
== E_INVALIDARG
) /* Win8 */, "Failed to create analysis, hr %#x.\n", hr
);
5992 IDWriteGlyphRunAnalysis_Release(analysis
);
5994 /* Natural mode, grayscale antialiased. */
5995 hr
= IDWriteFactory2_CreateGlyphRunAnalysis(factory2
, &run
, NULL
, DWRITE_RENDERING_MODE_NATURAL
,
5996 DWRITE_MEASURING_MODE_NATURAL
, DWRITE_GRID_FIT_MODE_DISABLED
, DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
,
5997 0.0f
, 0.0f
, &analysis
);
5998 ok(hr
== S_OK
, "Failed to create analysis, hr %#x.\n", hr
);
6000 SetRect(&rect
, 0, 1, 0, 1);
6001 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_CLEARTYPE_3x1
, &rect
);
6002 ok(hr
== S_OK
, "Failed to get texture bounds, hr %#x.\n", hr
);
6003 ok(IsRectEmpty(&rect
), "Expected empty bbox.\n");
6005 SetRectEmpty(&rect
);
6006 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect
);
6007 ok(hr
== S_OK
, "Failed to get texture bounds, hr %#x.\n", hr
);
6008 ok(!IsRectEmpty(&rect
), "Unexpected empty bbox.\n");
6010 size
= (rect
.right
- rect
.left
) * (rect
.bottom
- rect
.top
);
6011 bits
= HeapAlloc(GetProcessHeap(), 0, size
);
6013 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect
, bits
, size
);
6014 ok(hr
== S_OK
, "Failed to get alpha texture, hr %#x.\n", hr
);
6016 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect
, bits
, size
- 1);
6017 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "Unexpected hr %#x.\n", hr
);
6019 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_CLEARTYPE_3x1
, &rect
, bits
, size
);
6020 ok(hr
== DWRITE_E_UNSUPPORTEDOPERATION
, "Unexpected hr %#x.\n", hr
);
6022 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_CLEARTYPE_3x1
, &rect
, bits
, size
- 1);
6024 ok(hr
== DWRITE_E_UNSUPPORTEDOPERATION
, "Unexpected hr %#x.\n", hr
);
6026 HeapFree(GetProcessHeap(), 0, bits
);
6028 hr
= IDWriteFactory_CreateCustomRenderingParams(factory
, 0.1f
, 0.0f
, 1.0f
, DWRITE_PIXEL_GEOMETRY_FLAT
,
6029 DWRITE_RENDERING_MODE_NATURAL
, ¶ms
);
6030 ok(hr
== S_OK
, "Failed to create custom parameters, hr %#x.\n", hr
);
6032 hr
= IDWriteGlyphRunAnalysis_GetAlphaBlendParams(analysis
, params
, &gamma
, &contrast
, &cleartype_level
);
6033 ok(hr
== S_OK
, "Failed to get alpha blend params, hr %#x.\n", hr
);
6035 ok(cleartype_level
== 0.0f
, "Unexpected cleartype level %f.\n", cleartype_level
);
6037 IDWriteRenderingParams_Release(params
);
6038 IDWriteGlyphRunAnalysis_Release(analysis
);
6040 IDWriteFactory2_Release(factory2
);
6043 if (IDWriteFactory_QueryInterface(factory
, &IID_IDWriteFactory3
, (void **)&factory3
) == S_OK
) {
6045 /* Invalid antialias mode. */
6046 hr
= IDWriteFactory3_CreateGlyphRunAnalysis(factory3
, &run
, NULL
, DWRITE_RENDERING_MODE1_ALIASED
,
6047 DWRITE_MEASURING_MODE_NATURAL
, DWRITE_GRID_FIT_MODE_DEFAULT
, DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
+ 1,
6048 0.0f
, 0.0f
, &analysis
);
6049 ok(hr
== E_INVALIDARG
, "Unexpected hr %#x.\n", hr
);
6051 /* Invalid grid fit mode. */
6052 hr
= IDWriteFactory3_CreateGlyphRunAnalysis(factory3
, &run
, NULL
, DWRITE_RENDERING_MODE1_ALIASED
,
6053 DWRITE_MEASURING_MODE_NATURAL
, DWRITE_GRID_FIT_MODE_ENABLED
+ 1, DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
,
6054 0.0f
, 0.0f
, &analysis
);
6055 ok(hr
== E_INVALIDARG
, "Unexpected hr %#x.\n", hr
);
6057 /* Invalid rendering mode. */
6058 hr
= IDWriteFactory3_CreateGlyphRunAnalysis(factory3
, &run
, NULL
, DWRITE_RENDERING_MODE1_OUTLINE
,
6059 DWRITE_MEASURING_MODE_NATURAL
, DWRITE_GRID_FIT_MODE_ENABLED
, DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
,
6060 0.0f
, 0.0f
, &analysis
);
6061 ok(hr
== E_INVALIDARG
, "Unexpected hr %#x.\n", hr
);
6063 /* Invalid measuring mode. */
6064 hr
= IDWriteFactory3_CreateGlyphRunAnalysis(factory3
, &run
, NULL
, DWRITE_RENDERING_MODE1_ALIASED
,
6065 DWRITE_MEASURING_MODE_GDI_NATURAL
+ 1, DWRITE_GRID_FIT_MODE_ENABLED
,
6066 DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
, 0.0f
, 0.0f
, &analysis
);
6067 ok(hr
== E_INVALIDARG
, "Unexpected hr %#x.\n", hr
);
6069 hr
= IDWriteFactory3_CreateGlyphRunAnalysis(factory3
, &run
, NULL
, DWRITE_RENDERING_MODE1_NATURAL
,
6070 DWRITE_MEASURING_MODE_NATURAL
, DWRITE_GRID_FIT_MODE_DEFAULT
, DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
,
6071 0.0f
, 0.0f
, &analysis
);
6072 ok(hr
== S_OK
, "Failed to create analysis, hr %#x.\n", hr
);
6073 IDWriteGlyphRunAnalysis_Release(analysis
);
6075 /* Natural mode, grayscale antialiased. */
6076 hr
= IDWriteFactory3_CreateGlyphRunAnalysis(factory3
, &run
, NULL
, DWRITE_RENDERING_MODE1_NATURAL
,
6077 DWRITE_MEASURING_MODE_NATURAL
, DWRITE_GRID_FIT_MODE_DISABLED
, DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
,
6078 0.0f
, 0.0f
, &analysis
);
6079 ok(hr
== S_OK
, "Failed to create analysis, hr %#x.\n", hr
);
6081 SetRect(&rect
, 0, 1, 0, 1);
6082 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_CLEARTYPE_3x1
, &rect
);
6083 ok(hr
== S_OK
, "Failed to get texture bounds, hr %#x.\n", hr
);
6084 ok(IsRectEmpty(&rect
), "Expected empty bbox.\n");
6086 SetRectEmpty(&rect
);
6087 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect
);
6088 ok(hr
== S_OK
, "Failed to get texture bounds, hr %#x.\n", hr
);
6089 ok(!IsRectEmpty(&rect
), "Unexpected empty bbox.\n");
6091 size
= (rect
.right
- rect
.left
) * (rect
.bottom
- rect
.top
);
6092 bits
= HeapAlloc(GetProcessHeap(), 0, size
);
6094 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect
, bits
, size
);
6095 ok(hr
== S_OK
, "Failed to get alpha texture, hr %#x.\n", hr
);
6097 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect
, bits
, size
- 1);
6098 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "Unexpected hr %#x.\n", hr
);
6100 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_CLEARTYPE_3x1
, &rect
, bits
, size
);
6101 ok(hr
== DWRITE_E_UNSUPPORTEDOPERATION
, "Unexpected hr %#x.\n", hr
);
6103 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_CLEARTYPE_3x1
, &rect
, bits
, size
- 1);
6105 ok(hr
== DWRITE_E_UNSUPPORTEDOPERATION
, "Unexpected hr %#x.\n", hr
);
6107 HeapFree(GetProcessHeap(), 0, bits
);
6109 IDWriteGlyphRunAnalysis_Release(analysis
);
6111 IDWriteFactory3_Release(factory3
);
6114 IDWriteFontFace_Release(face
);
6115 ref
= IDWriteFactory_Release(factory
);
6116 ok(ref
== 0, "factory not released, %u\n", ref
);
6119 #define round(x) ((int)floor((x) + 0.5))
6150 static const struct VDMX_group
*find_vdmx_group(const struct VDMX_Header
*hdr
)
6152 WORD num_ratios
, i
, group_offset
= 0;
6153 struct VDMX_Ratio
*ratios
= (struct VDMX_Ratio
*)(hdr
+ 1);
6154 BYTE dev_x_ratio
= 1, dev_y_ratio
= 1;
6156 num_ratios
= GET_BE_WORD(hdr
->numRatios
);
6158 for (i
= 0; i
< num_ratios
; i
++)
6160 if (!ratios
[i
].bCharSet
) continue;
6162 if ((ratios
[i
].xRatio
== 0 && ratios
[i
].yStartRatio
== 0 &&
6163 ratios
[i
].yEndRatio
== 0) ||
6164 (ratios
[i
].xRatio
== dev_x_ratio
&& ratios
[i
].yStartRatio
<= dev_y_ratio
&&
6165 ratios
[i
].yEndRatio
>= dev_y_ratio
))
6167 group_offset
= GET_BE_WORD(*((WORD
*)(ratios
+ num_ratios
) + i
));
6172 return (const struct VDMX_group
*)((BYTE
*)hdr
+ group_offset
);
6176 static BOOL
get_vdmx_size(const struct VDMX_group
*group
, int emsize
, int *a
, int *d
)
6179 const struct VDMX_vTable
*tables
;
6181 if (!group
) return FALSE
;
6183 recs
= GET_BE_WORD(group
->recs
);
6184 if (emsize
< group
->startsz
|| emsize
>= group
->endsz
) return FALSE
;
6186 tables
= (const struct VDMX_vTable
*)(group
+ 1);
6187 for (i
= 0; i
< recs
; i
++)
6189 WORD ppem
= GET_BE_WORD(tables
[i
].yPelHeight
);
6192 /* FIXME: Supposed to interpolate */
6193 trace("FIXME interpolate %d\n", emsize
);
6199 *a
= (SHORT
)GET_BE_WORD(tables
[i
].yMax
);
6200 *d
= -(SHORT
)GET_BE_WORD(tables
[i
].yMin
);
6207 static void test_metrics_cmp(FLOAT emsize
, const DWRITE_FONT_METRICS
*metrics
, const DWRITE_FONT_METRICS1
*expected
)
6209 ok(metrics
->designUnitsPerEm
== expected
->designUnitsPerEm
, "%.2f: emsize: got %u expect %u\n",
6210 emsize
, metrics
->designUnitsPerEm
, expected
->designUnitsPerEm
);
6211 ok(metrics
->ascent
== expected
->ascent
, "%.2f a: got %u expect %u\n",
6212 emsize
, metrics
->ascent
, expected
->ascent
);
6213 ok(metrics
->descent
== expected
->descent
, "%.2f d: got %u expect %u\n",
6214 emsize
, metrics
->descent
, expected
->descent
);
6215 ok(metrics
->lineGap
== expected
->lineGap
, "%.2f lg: got %d expect %d\n",
6216 emsize
, metrics
->lineGap
, expected
->lineGap
);
6217 ok(metrics
->capHeight
== expected
->capHeight
, "%.2f capH: got %u expect %u\n",
6218 emsize
, metrics
->capHeight
, expected
->capHeight
);
6219 ok(metrics
->xHeight
== expected
->xHeight
, "%.2f xH: got %u expect %u\n",
6220 emsize
, metrics
->xHeight
, expected
->xHeight
);
6221 ok(metrics
->underlinePosition
== expected
->underlinePosition
, "%.2f ulP: got %d expect %d\n",
6222 emsize
, metrics
->underlinePosition
, expected
->underlinePosition
);
6223 ok(metrics
->underlineThickness
== expected
->underlineThickness
, "%.2f ulTh: got %u expect %u\n",
6224 emsize
, metrics
->underlineThickness
, expected
->underlineThickness
);
6225 ok(metrics
->strikethroughPosition
== expected
->strikethroughPosition
, "%.2f stP: got %d expect %d\n",
6226 emsize
, metrics
->strikethroughPosition
, expected
->strikethroughPosition
);
6227 ok(metrics
->strikethroughThickness
== expected
->strikethroughThickness
, "%.2f stTh: got %u expect %u\n",
6228 emsize
, metrics
->strikethroughThickness
, expected
->strikethroughThickness
);
6231 static void test_metrics1_cmp(FLOAT emsize
, const DWRITE_FONT_METRICS1
*metrics
, const DWRITE_FONT_METRICS1
*expected
)
6233 ok(metrics
->designUnitsPerEm
== expected
->designUnitsPerEm
, "%.2f: emsize: got %u expect %u\n",
6234 emsize
, metrics
->designUnitsPerEm
, expected
->designUnitsPerEm
);
6235 ok(metrics
->ascent
== expected
->ascent
, "%.2f a: got %u expect %u\n",
6236 emsize
, metrics
->ascent
, expected
->ascent
);
6237 ok(metrics
->descent
== expected
->descent
, "%.2f d: got %u expect %u\n",
6238 emsize
, metrics
->descent
, expected
->descent
);
6239 ok(metrics
->lineGap
== expected
->lineGap
, "%.2f lg: got %d expect %d\n",
6240 emsize
, metrics
->lineGap
, expected
->lineGap
);
6241 ok(metrics
->capHeight
== expected
->capHeight
, "%.2f capH: got %u expect %u\n",
6242 emsize
, metrics
->capHeight
, expected
->capHeight
);
6243 ok(metrics
->xHeight
== expected
->xHeight
, "%.2f xH: got %u expect %u\n",
6244 emsize
, metrics
->xHeight
, expected
->xHeight
);
6245 ok(metrics
->underlinePosition
== expected
->underlinePosition
, "%.2f ulP: got %d expect %d\n",
6246 emsize
, metrics
->underlinePosition
, expected
->underlinePosition
);
6247 ok(metrics
->underlineThickness
== expected
->underlineThickness
, "%.2f ulTh: got %u expect %u\n",
6248 emsize
, metrics
->underlineThickness
, expected
->underlineThickness
);
6249 ok(metrics
->strikethroughPosition
== expected
->strikethroughPosition
, "%.2f stP: got %d expect %d\n",
6250 emsize
, metrics
->strikethroughPosition
, expected
->strikethroughPosition
);
6251 ok(metrics
->strikethroughThickness
== expected
->strikethroughThickness
, "%.2f stTh: got %u expect %u\n",
6252 emsize
, metrics
->strikethroughThickness
, expected
->strikethroughThickness
);
6253 ok(metrics
->glyphBoxLeft
== expected
->glyphBoxLeft
, "%.2f box left: got %d expect %d\n",
6254 emsize
, metrics
->glyphBoxLeft
, expected
->glyphBoxLeft
);
6255 if (0) { /* this is not consistent */
6256 ok(metrics
->glyphBoxTop
== expected
->glyphBoxTop
, "%.2f box top: got %d expect %d\n",
6257 emsize
, metrics
->glyphBoxTop
, expected
->glyphBoxTop
);
6258 ok(metrics
->glyphBoxRight
== expected
->glyphBoxRight
, "%.2f box right: got %d expect %d\n",
6259 emsize
, metrics
->glyphBoxRight
, expected
->glyphBoxRight
);
6261 ok(metrics
->glyphBoxBottom
== expected
->glyphBoxBottom
, "%.2f box bottom: got %d expect %d\n",
6262 emsize
, metrics
->glyphBoxBottom
, expected
->glyphBoxBottom
);
6263 ok(metrics
->subscriptPositionX
== expected
->subscriptPositionX
, "%.2f subX: got %d expect %d\n",
6264 emsize
, metrics
->subscriptPositionX
, expected
->subscriptPositionX
);
6265 ok(metrics
->subscriptPositionY
== expected
->subscriptPositionY
, "%.2f subY: got %d expect %d\n",
6266 emsize
, metrics
->subscriptPositionY
, expected
->subscriptPositionY
);
6267 ok(metrics
->subscriptSizeX
== expected
->subscriptSizeX
, "%.2f subsizeX: got %d expect %d\n",
6268 emsize
, metrics
->subscriptSizeX
, expected
->subscriptSizeX
);
6269 ok(metrics
->subscriptPositionY
== expected
->subscriptPositionY
, "%.2f subsizeY: got %d expect %d\n",
6270 emsize
, metrics
->subscriptSizeY
, expected
->subscriptSizeY
);
6271 ok(metrics
->superscriptPositionX
== expected
->superscriptPositionX
, "%.2f supX: got %d expect %d\n",
6272 emsize
, metrics
->superscriptPositionX
, expected
->superscriptPositionX
);
6274 ok(metrics
->superscriptPositionY
== expected
->superscriptPositionY
, "%.2f supY: got %d expect %d\n",
6275 emsize
, metrics
->superscriptPositionY
, expected
->superscriptPositionY
);
6276 ok(metrics
->superscriptSizeX
== expected
->superscriptSizeX
, "%.2f supsizeX: got %d expect %d\n",
6277 emsize
, metrics
->superscriptSizeX
, expected
->superscriptSizeX
);
6278 ok(metrics
->superscriptSizeY
== expected
->superscriptSizeY
, "%.2f supsizeY: got %d expect %d\n",
6279 emsize
, metrics
->superscriptSizeY
, expected
->superscriptSizeY
);
6280 ok(metrics
->hasTypographicMetrics
== expected
->hasTypographicMetrics
, "%.2f hastypo: got %d expect %d\n",
6281 emsize
, metrics
->hasTypographicMetrics
, expected
->hasTypographicMetrics
);
6284 struct compatmetrics_test
{
6290 static struct compatmetrics_test compatmetrics_tests
[] = {
6291 { { 0.0, 0.0, 0.0, 1.0, 0.0, 0.0 }, 1.0, 5.0 },
6292 { { 0.0, 0.0, 0.0, -1.0, 0.0, 0.0 }, 1.0, 5.0 },
6293 { { 0.0, 0.0, 0.0, -1.0, 0.0, 0.0 }, 2.0, 5.0 },
6294 { { 0.0, 0.0, 0.0, 3.0, 0.0, 0.0 }, 2.0, 5.0 },
6295 { { 0.0, 0.0, 0.0, -3.0, 0.0, 0.0 }, 2.0, 5.0 },
6296 { { 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 }, 2.0, 5.0 },
6297 { { 1.0, 0.0, 0.0, 1.0, 5.0, 0.0 }, 2.0, 5.0 },
6298 { { 1.0, 0.0, 0.0, 1.0, 0.0, 5.0 }, 2.0, 5.0 },
6301 static void get_expected_metrics(IDWriteFontFace
*fontface
, struct compatmetrics_test
*ptr
,
6302 DWRITE_FONT_METRICS
*expected
)
6306 memset(expected
, 0, sizeof(*expected
));
6307 hr
= IDWriteFontFace_GetGdiCompatibleMetrics(fontface
, ptr
->ppdip
* fabsf(ptr
->m
.m22
) * ptr
->emsize
, 1.0, NULL
, expected
);
6308 ok(hr
== S_OK
, "got %08x\n", hr
);
6311 static void test_gdicompat_metrics(IDWriteFontFace
*face
)
6313 IDWriteFontFace1
*fontface1
= NULL
;
6315 DWRITE_FONT_METRICS design_metrics
, comp_metrics
;
6316 DWRITE_FONT_METRICS1 design_metrics1
, expected
;
6317 FLOAT emsize
, scale
;
6318 int ascent
, descent
;
6319 const struct VDMX_Header
*vdmx
;
6323 const struct VDMX_group
*vdmx_group
= NULL
;
6326 hr
= IDWriteFontFace_QueryInterface(face
, &IID_IDWriteFontFace1
, (void**)&fontface1
);
6328 win_skip("gdi compatible DWRITE_FONT_METRICS1 are not supported.\n");
6331 IDWriteFontFace1_GetMetrics(fontface1
, &design_metrics1
);
6332 memcpy(&design_metrics
, &design_metrics1
, sizeof(design_metrics
));
6335 IDWriteFontFace_GetMetrics(face
, &design_metrics
);
6337 hr
= IDWriteFontFace_TryGetFontTable(face
, MS_VDMX_TAG
, (const void **)&vdmx
,
6338 &vdmx_len
, &vdmx_ctx
, &exists
);
6339 if (hr
!= S_OK
|| !exists
)
6342 vdmx_group
= find_vdmx_group(vdmx
);
6344 /* negative emsize */
6345 memset(&comp_metrics
, 0xcc, sizeof(comp_metrics
));
6346 memset(&expected
, 0, sizeof(expected
));
6347 hr
= IDWriteFontFace_GetGdiCompatibleMetrics(face
, -10.0, 1.0, NULL
, &comp_metrics
);
6348 ok(hr
== E_INVALIDARG
, "got %08x\n", hr
);
6349 test_metrics_cmp(0.0, &comp_metrics
, &expected
);
6352 memset(&comp_metrics
, 0xcc, sizeof(comp_metrics
));
6353 memset(&expected
, 0, sizeof(expected
));
6354 hr
= IDWriteFontFace_GetGdiCompatibleMetrics(face
, 0.0, 1.0, NULL
, &comp_metrics
);
6355 ok(hr
== E_INVALIDARG
, "got %08x\n", hr
);
6356 test_metrics_cmp(0.0, &comp_metrics
, &expected
);
6358 /* zero pixels per dip */
6359 memset(&comp_metrics
, 0xcc, sizeof(comp_metrics
));
6360 memset(&expected
, 0, sizeof(expected
));
6361 hr
= IDWriteFontFace_GetGdiCompatibleMetrics(face
, 5.0, 0.0, NULL
, &comp_metrics
);
6362 ok(hr
== E_INVALIDARG
, "got %08x\n", hr
);
6363 test_metrics_cmp(5.0, &comp_metrics
, &expected
);
6365 memset(&comp_metrics
, 0xcc, sizeof(comp_metrics
));
6366 hr
= IDWriteFontFace_GetGdiCompatibleMetrics(face
, 5.0, -1.0, NULL
, &comp_metrics
);
6367 ok(hr
== E_INVALIDARG
, "got %08x\n", hr
);
6368 test_metrics_cmp(5.0, &comp_metrics
, &expected
);
6370 for (i
= 0; i
< ARRAY_SIZE(compatmetrics_tests
); i
++) {
6371 struct compatmetrics_test
*ptr
= &compatmetrics_tests
[i
];
6373 get_expected_metrics(face
, ptr
, (DWRITE_FONT_METRICS
*)&expected
);
6374 hr
= IDWriteFontFace_GetGdiCompatibleMetrics(face
, ptr
->emsize
, ptr
->ppdip
, &ptr
->m
, &comp_metrics
);
6375 ok(hr
== S_OK
, "got %08x\n", hr
);
6376 test_metrics_cmp(ptr
->emsize
, &comp_metrics
, &expected
);
6379 for (emsize
= 5; emsize
<= design_metrics
.designUnitsPerEm
; emsize
++)
6381 DWRITE_FONT_METRICS1 comp_metrics1
, expected
;
6384 hr
= IDWriteFontFace1_GetGdiCompatibleMetrics(fontface1
, emsize
, 1.0, NULL
, &comp_metrics1
);
6385 ok(hr
== S_OK
, "got %08x\n", hr
);
6388 hr
= IDWriteFontFace_GetGdiCompatibleMetrics(face
, emsize
, 1.0, NULL
, &comp_metrics
);
6389 ok(hr
== S_OK
, "got %08x\n", hr
);
6392 scale
= emsize
/ design_metrics
.designUnitsPerEm
;
6393 if (!get_vdmx_size(vdmx_group
, emsize
, &ascent
, &descent
))
6395 ascent
= round(design_metrics
.ascent
* scale
);
6396 descent
= round(design_metrics
.descent
* scale
);
6399 expected
.designUnitsPerEm
= design_metrics
.designUnitsPerEm
;
6400 expected
.ascent
= round(ascent
/ scale
);
6401 expected
.descent
= round(descent
/ scale
);
6402 expected
.lineGap
= round(round(design_metrics
.lineGap
* scale
) / scale
);
6403 expected
.capHeight
= round(round(design_metrics
.capHeight
* scale
) / scale
);
6404 expected
.xHeight
= round(round(design_metrics
.xHeight
* scale
) / scale
);
6405 expected
.underlinePosition
= round(round(design_metrics
.underlinePosition
* scale
) / scale
);
6406 expected
.underlineThickness
= round(round(design_metrics
.underlineThickness
* scale
) / scale
);
6407 expected
.strikethroughPosition
= round(round(design_metrics
.strikethroughPosition
* scale
) / scale
);
6408 expected
.strikethroughThickness
= round(round(design_metrics
.strikethroughThickness
* scale
) / scale
);
6411 expected
.glyphBoxLeft
= round(round(design_metrics1
.glyphBoxLeft
* scale
) / scale
);
6413 if (0) { /* those two fail on Tahoma and Win7 */
6414 expected
.glyphBoxTop
= round(round(design_metrics1
.glyphBoxTop
* scale
) / scale
);
6415 expected
.glyphBoxRight
= round(round(design_metrics1
.glyphBoxRight
* scale
) / scale
);
6417 expected
.glyphBoxBottom
= round(round(design_metrics1
.glyphBoxBottom
* scale
) / scale
);
6418 expected
.subscriptPositionX
= round(round(design_metrics1
.subscriptPositionX
* scale
) / scale
);
6419 expected
.subscriptPositionY
= round(round(design_metrics1
.subscriptPositionY
* scale
) / scale
);
6420 expected
.subscriptSizeX
= round(round(design_metrics1
.subscriptSizeX
* scale
) / scale
);
6421 expected
.subscriptSizeY
= round(round(design_metrics1
.subscriptSizeY
* scale
) / scale
);
6422 expected
.superscriptPositionX
= round(round(design_metrics1
.superscriptPositionX
* scale
) / scale
);
6423 if (0) /* this fails for 3 emsizes, Tahoma from [5, 2048] range */ {
6424 expected
.superscriptPositionY
= round(round(design_metrics1
.superscriptPositionY
* scale
) / scale
);
6426 expected
.superscriptSizeX
= round(round(design_metrics1
.superscriptSizeX
* scale
) / scale
);
6427 expected
.superscriptSizeY
= round(round(design_metrics1
.superscriptSizeY
* scale
) / scale
);
6428 expected
.hasTypographicMetrics
= design_metrics1
.hasTypographicMetrics
;
6430 test_metrics1_cmp(emsize
, &comp_metrics1
, &expected
);
6433 test_metrics_cmp(emsize
, &comp_metrics
, &expected
);
6438 IDWriteFontFace1_Release(fontface1
);
6439 if (vdmx
) IDWriteFontFace_ReleaseFontTable(face
, vdmx_ctx
);
6442 static void test_GetGdiCompatibleMetrics(void)
6444 IDWriteFactory
*factory
;
6446 IDWriteFontFace
*fontface
;
6450 factory
= create_factory();
6452 font
= get_font(factory
, L
"Tahoma", DWRITE_FONT_STYLE_NORMAL
);
6453 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
6454 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6455 IDWriteFont_Release(font
);
6456 test_gdicompat_metrics(fontface
);
6457 IDWriteFontFace_Release(fontface
);
6459 font
= get_font(factory
, L
"Arial", DWRITE_FONT_STYLE_NORMAL
);
6461 skip("Skipping tests with Arial\n");
6464 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
6465 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6466 IDWriteFont_Release(font
);
6468 test_gdicompat_metrics(fontface
);
6469 IDWriteFontFace_Release(fontface
);
6472 ref
= IDWriteFactory_Release(factory
);
6473 ok(ref
== 0, "factory not released, %u\n", ref
);
6476 static void get_expected_panose(IDWriteFont1
*font
, DWRITE_PANOSE
*panose
)
6478 IDWriteFontFace
*fontface
;
6479 const TT_OS2_V2
*tt_os2
;
6485 memset(panose
, 0, sizeof(*panose
));
6487 hr
= IDWriteFont1_CreateFontFace(font
, &fontface
);
6488 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6490 hr
= IDWriteFontFace_TryGetFontTable(fontface
, MS_OS2_TAG
, (const void **)&tt_os2
, &size
, &os2_context
, &exists
);
6491 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6494 memcpy(panose
, &tt_os2
->panose
, sizeof(*panose
));
6495 IDWriteFontFace_ReleaseFontTable(fontface
, os2_context
);
6498 IDWriteFontFace_Release(fontface
);
6501 static void test_GetPanose(void)
6503 IDWriteFontCollection
*syscollection
;
6504 IDWriteFactory
*factory
;
6505 IDWriteFont1
*font1
;
6511 factory
= create_factory();
6512 font
= get_tahoma_instance(factory
, DWRITE_FONT_STYLE_NORMAL
);
6514 hr
= IDWriteFont_QueryInterface(font
, &IID_IDWriteFont1
, (void **)&font1
);
6515 IDWriteFont_Release(font
);
6518 ref
= IDWriteFactory_Release(factory
);
6519 ok(ref
== 0, "factory not released, %u\n", ref
);
6520 win_skip("GetPanose() is not supported.\n");
6523 IDWriteFont1_Release(font1
);
6525 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &syscollection
, FALSE
);
6526 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6527 count
= IDWriteFontCollection_GetFontFamilyCount(syscollection
);
6529 for (i
= 0; i
< count
; i
++) {
6530 DWRITE_PANOSE panose
, expected_panose
;
6531 IDWriteLocalizedStrings
*names
;
6532 IDWriteFontFace3
*fontface3
;
6533 IDWriteFontFace
*fontface
;
6534 IDWriteFontFamily
*family
;
6535 IDWriteFont1
*font1
;
6539 hr
= IDWriteFontCollection_GetFontFamily(syscollection
, i
, &family
);
6540 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6542 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STRETCH_NORMAL
,
6543 DWRITE_FONT_STYLE_NORMAL
, &font
);
6544 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6546 hr
= IDWriteFont_QueryInterface(font
, &IID_IDWriteFont1
, (void **)&font1
);
6547 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6548 IDWriteFont_Release(font
);
6550 hr
= IDWriteFontFamily_GetFamilyNames(family
, &names
);
6551 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6553 get_enus_string(names
, nameW
, ARRAY_SIZE(nameW
));
6555 IDWriteLocalizedStrings_Release(names
);
6557 IDWriteFont1_GetPanose(font1
, &panose
);
6558 get_expected_panose(font1
, &expected_panose
);
6560 ok(panose
.values
[0] == expected_panose
.values
[0], "%s: values[0] %#x, expected %#x.\n", wine_dbgstr_w(nameW
),
6561 panose
.values
[0], expected_panose
.values
[0]);
6562 ok(panose
.values
[1] == expected_panose
.values
[1], "%s: values[1] %#x, expected %#x.\n", wine_dbgstr_w(nameW
),
6563 panose
.values
[1], expected_panose
.values
[1]);
6564 ok(panose
.values
[2] == expected_panose
.values
[2], "%s: values[2] %#x, expected %#x.\n", wine_dbgstr_w(nameW
),
6565 panose
.values
[2], expected_panose
.values
[2]);
6566 ok(panose
.values
[3] == expected_panose
.values
[3], "%s: values[3] %#x, expected %#x.\n", wine_dbgstr_w(nameW
),
6567 panose
.values
[3], expected_panose
.values
[3]);
6568 ok(panose
.values
[4] == expected_panose
.values
[4], "%s: values[4] %#x, expected %#x.\n", wine_dbgstr_w(nameW
),
6569 panose
.values
[4], expected_panose
.values
[4]);
6570 ok(panose
.values
[5] == expected_panose
.values
[5], "%s: values[5] %#x, expected %#x.\n", wine_dbgstr_w(nameW
),
6571 panose
.values
[5], expected_panose
.values
[5]);
6572 ok(panose
.values
[6] == expected_panose
.values
[6], "%s: values[6] %#x, expected %#x.\n", wine_dbgstr_w(nameW
),
6573 panose
.values
[6], expected_panose
.values
[6]);
6574 ok(panose
.values
[7] == expected_panose
.values
[7], "%s: values[7] %#x, expected %#x.\n", wine_dbgstr_w(nameW
),
6575 panose
.values
[7], expected_panose
.values
[7]);
6576 ok(panose
.values
[8] == expected_panose
.values
[8], "%s: values[8] %#x, expected %#x.\n", wine_dbgstr_w(nameW
),
6577 panose
.values
[8], expected_panose
.values
[8]);
6578 ok(panose
.values
[9] == expected_panose
.values
[9], "%s: values[9] %#x, expected %#x.\n", wine_dbgstr_w(nameW
),
6579 panose
.values
[9], expected_panose
.values
[9]);
6581 hr
= IDWriteFont1_CreateFontFace(font1
, &fontface
);
6582 ok(hr
== S_OK
, "Failed to create a font face, %#x.\n", hr
);
6583 if (IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace3
, (void **)&fontface3
) == S_OK
) {
6584 ok(!memcmp(&panose
, &expected_panose
, sizeof(panose
)), "%s: Unexpected panose from font face.\n",
6585 wine_dbgstr_w(nameW
));
6586 IDWriteFontFace3_Release(fontface3
);
6588 IDWriteFontFace_Release(fontface
);
6590 IDWriteFont1_Release(font1
);
6591 IDWriteFontFamily_Release(family
);
6594 IDWriteFontCollection_Release(syscollection
);
6595 ref
= IDWriteFactory_Release(factory
);
6596 ok(ref
== 0, "factory not released, %u\n", ref
);
6599 static INT32
get_gdi_font_advance(HDC hdc
, FLOAT emsize
)
6606 memset(&logfont
, 0, sizeof(logfont
));
6607 logfont
.lfHeight
= (LONG
)-emsize
;
6608 logfont
.lfWeight
= FW_NORMAL
;
6609 logfont
.lfQuality
= CLEARTYPE_QUALITY
;
6610 lstrcpyW(logfont
.lfFaceName
, L
"Tahoma");
6612 hfont
= CreateFontIndirectW(&logfont
);
6613 SelectObject(hdc
, hfont
);
6615 ret
= GetCharABCWidthsW(hdc
, 'A', 'A', &abc
);
6616 ok(ret
, "got %d\n", ret
);
6618 DeleteObject(hfont
);
6620 return abc
.abcA
+ abc
.abcB
+ abc
.abcC
;
6623 static void test_GetGdiCompatibleGlyphAdvances(void)
6625 IDWriteFontFace1
*fontface1
;
6626 IDWriteFontFace
*fontface
;
6627 IDWriteFactory
*factory
;
6634 DWRITE_FONT_METRICS1 fm
;
6638 factory
= create_factory();
6639 font
= get_tahoma_instance(factory
, DWRITE_FONT_STYLE_NORMAL
);
6641 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
6642 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6643 IDWriteFont_Release(font
);
6645 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void **)&fontface1
);
6646 IDWriteFontFace_Release(fontface
);
6649 ref
= IDWriteFactory_Release(factory
);
6650 ok(ref
== 0, "factory not released, %u\n", ref
);
6651 win_skip("GetGdiCompatibleGlyphAdvances() is not supported\n");
6657 hr
= IDWriteFontFace1_GetGlyphIndices(fontface1
, &codepoint
, 1, &glyph
);
6658 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6659 ok(glyph
> 0, "got %u\n", glyph
);
6663 hr
= IDWriteFontFace1_GetGdiCompatibleGlyphAdvances(fontface1
, 0.0,
6664 1.0, NULL
, FALSE
, FALSE
, 1, &glyph
, &advance
);
6665 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6666 ok(advance
== 0, "got %d\n", advance
);
6668 /* negative emsize */
6670 hr
= IDWriteFontFace1_GetGdiCompatibleGlyphAdvances(fontface1
, -1.0,
6671 1.0, NULL
, FALSE
, FALSE
, 1, &glyph
, &advance
);
6672 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
6673 ok(advance
== 0, "got %d\n", advance
);
6677 hr
= IDWriteFontFace1_GetGdiCompatibleGlyphAdvances(fontface1
, 1.0,
6678 0.0, NULL
, FALSE
, FALSE
, 1, &glyph
, &advance
);
6679 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
6680 ok(advance
== 0, "got %d\n", advance
);
6682 /* negative ppdip */
6684 hr
= IDWriteFontFace1_GetGdiCompatibleGlyphAdvances(fontface1
, 1.0,
6685 -1.0, NULL
, FALSE
, FALSE
, 1, &glyph
, &advance
);
6686 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
6687 ok(advance
== 0, "got %d\n", advance
);
6689 IDWriteFontFace1_GetMetrics(fontface1
, &fm
);
6691 hdc
= CreateCompatibleDC(0);
6693 for (emsize
= 1.0; emsize
<= fm
.designUnitsPerEm
; emsize
+= 1.0) {
6696 gdi_advance
= get_gdi_font_advance(hdc
, emsize
);
6697 hr
= IDWriteFontFace1_GetGdiCompatibleGlyphAdvances(fontface1
, emsize
,
6698 1.0, NULL
, FALSE
, FALSE
, 1, &glyph
, &advance
);
6699 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6701 /* advance is in design units */
6702 advance
= (int)floorf(emsize
* advance
/ fm
.designUnitsPerEm
+ 0.5f
);
6703 ok((advance
- gdi_advance
) <= 2, "%.0f: got advance %d, expected %d\n", emsize
, advance
, gdi_advance
);
6708 IDWriteFontFace1_Release(fontface1
);
6709 ref
= IDWriteFactory_Release(factory
);
6710 ok(ref
== 0, "factory not released, %u\n", ref
);
6713 static WORD
get_gasp_flags(IDWriteFontFace
*fontface
, FLOAT emsize
, FLOAT ppdip
)
6715 WORD num_recs
, version
;
6726 hr
= IDWriteFontFace_TryGetFontTable(fontface
, MS_GASP_TAG
,
6727 (const void**)&ptr
, &size
, &ctxt
, &exists
);
6728 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6733 version
= GET_BE_WORD( *ptr
++ );
6734 num_recs
= GET_BE_WORD( *ptr
++ );
6735 if (version
> 1 || size
< (num_recs
* 2 + 2) * sizeof(WORD
)) {
6736 ok(0, "unsupported gasp table: ver %d size %d recs %d\n", version
, size
, num_recs
);
6742 flags
= GET_BE_WORD( *(ptr
+ 1) );
6743 if (emsize
<= GET_BE_WORD( *ptr
)) break;
6748 IDWriteFontFace_ReleaseFontTable(fontface
, ctxt
);
6752 #define GASP_GRIDFIT 0x0001
6753 #define GASP_DOGRAY 0x0002
6754 #define GASP_SYMMETRIC_GRIDFIT 0x0004
6755 #define GASP_SYMMETRIC_SMOOTHING 0x0008
6757 static BOOL g_is_vista
;
6758 static DWRITE_RENDERING_MODE
get_expected_rendering_mode(FLOAT emsize
, WORD gasp
, DWRITE_MEASURING_MODE mode
,
6759 DWRITE_OUTLINE_THRESHOLD threshold
)
6761 static const FLOAT aa_threshold
= 100.0f
;
6762 static const FLOAT a_threshold
= 350.0f
;
6763 static const FLOAT naturalemsize
= 20.0f
;
6766 /* outline threshold */
6768 v
= mode
== DWRITE_MEASURING_MODE_NATURAL
? aa_threshold
: a_threshold
;
6770 v
= threshold
== DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
? aa_threshold
: a_threshold
;
6773 return DWRITE_RENDERING_MODE_OUTLINE
;
6777 case DWRITE_MEASURING_MODE_NATURAL
:
6778 if (!(gasp
& GASP_SYMMETRIC_SMOOTHING
) && (emsize
<= naturalemsize
))
6779 return DWRITE_RENDERING_MODE_NATURAL
;
6781 return DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
;
6782 case DWRITE_MEASURING_MODE_GDI_CLASSIC
:
6783 return DWRITE_RENDERING_MODE_GDI_CLASSIC
;
6784 case DWRITE_MEASURING_MODE_GDI_NATURAL
:
6785 return DWRITE_RENDERING_MODE_GDI_NATURAL
;
6790 /* should be unreachable */
6791 return DWRITE_RENDERING_MODE_DEFAULT
;
6794 static DWRITE_GRID_FIT_MODE
get_expected_gridfit_mode(FLOAT emsize
, WORD gasp
, DWRITE_MEASURING_MODE mode
,
6795 DWRITE_OUTLINE_THRESHOLD threshold
)
6797 static const FLOAT aa_threshold
= 100.0f
;
6798 static const FLOAT a_threshold
= 350.0f
;
6801 v
= threshold
== DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
? aa_threshold
: a_threshold
;
6803 return DWRITE_GRID_FIT_MODE_DISABLED
;
6805 if (mode
== DWRITE_MEASURING_MODE_GDI_CLASSIC
|| mode
== DWRITE_MEASURING_MODE_GDI_NATURAL
)
6806 return DWRITE_GRID_FIT_MODE_ENABLED
;
6808 return (gasp
& (GASP_GRIDFIT
|GASP_SYMMETRIC_GRIDFIT
)) ? DWRITE_GRID_FIT_MODE_ENABLED
: DWRITE_GRID_FIT_MODE_DISABLED
;
6811 struct recommendedmode_test
6813 DWRITE_MEASURING_MODE measuring
;
6814 DWRITE_OUTLINE_THRESHOLD threshold
;
6817 static const struct recommendedmode_test recmode_tests
[] = {
6818 { DWRITE_MEASURING_MODE_NATURAL
, DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
},
6819 { DWRITE_MEASURING_MODE_GDI_CLASSIC
, DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
},
6820 { DWRITE_MEASURING_MODE_GDI_NATURAL
, DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
},
6823 static const struct recommendedmode_test recmode_tests1
[] = {
6824 { DWRITE_MEASURING_MODE_NATURAL
, DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
},
6825 { DWRITE_MEASURING_MODE_GDI_CLASSIC
, DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
},
6826 { DWRITE_MEASURING_MODE_GDI_NATURAL
, DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
},
6827 { DWRITE_MEASURING_MODE_NATURAL
, DWRITE_OUTLINE_THRESHOLD_ALIASED
},
6828 { DWRITE_MEASURING_MODE_GDI_CLASSIC
, DWRITE_OUTLINE_THRESHOLD_ALIASED
},
6829 { DWRITE_MEASURING_MODE_GDI_NATURAL
, DWRITE_OUTLINE_THRESHOLD_ALIASED
},
6832 static void test_GetRecommendedRenderingMode(void)
6834 IDWriteRenderingParams
*params
;
6835 IDWriteFontFace3
*fontface3
;
6836 IDWriteFontFace2
*fontface2
;
6837 IDWriteFontFace1
*fontface1
;
6838 IDWriteFontFace
*fontface
;
6839 DWRITE_RENDERING_MODE mode
;
6840 IDWriteFactory
*factory
;
6845 factory
= create_factory();
6846 fontface
= create_fontface(factory
);
6849 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void**)&fontface1
);
6851 win_skip("IDWriteFontFace1::GetRecommendedRenderingMode() is not supported.\n");
6854 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace2
, (void**)&fontface2
);
6856 win_skip("IDWriteFontFace2::GetRecommendedRenderingMode() is not supported.\n");
6859 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace3
, (void**)&fontface3
);
6861 win_skip("IDWriteFontFace3::GetRecommendedRenderingMode() is not supported.\n");
6863 if (0) /* crashes on native */
6864 hr
= IDWriteFontFace_GetRecommendedRenderingMode(fontface
, 3.0, 1.0,
6865 DWRITE_MEASURING_MODE_GDI_CLASSIC
, NULL
, NULL
);
6868 hr
= IDWriteFontFace_GetRecommendedRenderingMode(fontface
, 3.0, 1.0,
6869 DWRITE_MEASURING_MODE_GDI_CLASSIC
, NULL
, &mode
);
6870 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
6871 ok(mode
== DWRITE_RENDERING_MODE_DEFAULT
, "got %d\n", mode
);
6873 hr
= IDWriteFactory_CreateRenderingParams(factory
, ¶ms
);
6874 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6876 /* detect old dwrite version, that is using higher threshold value */
6877 g_is_vista
= fontface1
== NULL
;
6879 for (emsize
= 1.0; emsize
< 500.0; emsize
+= 1.0) {
6880 DWRITE_RENDERING_MODE expected
;
6885 for (i
= 0; i
< ARRAY_SIZE(recmode_tests
); i
++) {
6888 gasp
= get_gasp_flags(fontface
, emsize
, ppdip
);
6889 expected
= get_expected_rendering_mode(emsize
* ppdip
, gasp
, recmode_tests
[i
].measuring
, recmode_tests
[i
].threshold
);
6890 hr
= IDWriteFontFace_GetRecommendedRenderingMode(fontface
, emsize
, ppdip
, recmode_tests
[i
].measuring
, params
, &mode
);
6891 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6892 ok(mode
== expected
, "%.2f/%d: got %d, ppdip %f, flags 0x%04x, expected %d\n", emsize
, i
, mode
, ppdip
, gasp
, expected
);
6894 /* some ppdip variants */
6897 gasp
= get_gasp_flags(fontface
, emsize
, ppdip
);
6898 expected
= get_expected_rendering_mode(emsize
* ppdip
, gasp
, recmode_tests
[i
].measuring
, recmode_tests
[i
].threshold
);
6899 hr
= IDWriteFontFace_GetRecommendedRenderingMode(fontface
, emsize
, ppdip
, recmode_tests
[i
].measuring
, params
, &mode
);
6900 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6901 ok(mode
== expected
, "%.2f/%d: got %d, ppdip %f, flags 0x%04x, expected %d\n", emsize
, i
, mode
, ppdip
, gasp
, expected
);
6903 /* Only test larger sizes to workaround Win7 differences, where unscaled natural emsize threshold is used;
6904 Win8 and Win10 handle this as expected. */
6905 if (emsize
> 20.0f
) {
6908 gasp
= get_gasp_flags(fontface
, emsize
, ppdip
);
6909 expected
= get_expected_rendering_mode(emsize
* ppdip
, gasp
, recmode_tests
[i
].measuring
, recmode_tests
[i
].threshold
);
6910 hr
= IDWriteFontFace_GetRecommendedRenderingMode(fontface
, emsize
, ppdip
, recmode_tests
[i
].measuring
, params
, &mode
);
6911 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6912 ok(mode
== expected
, "%.2f/%d: got %d, ppdip %f, flags 0x%04x, expected %d\n", emsize
, i
, mode
, ppdip
, gasp
, expected
);
6916 gasp
= get_gasp_flags(fontface
, emsize
, ppdip
);
6917 expected
= get_expected_rendering_mode(emsize
* ppdip
, gasp
, recmode_tests
[i
].measuring
, recmode_tests
[i
].threshold
);
6918 hr
= IDWriteFontFace_GetRecommendedRenderingMode(fontface
, emsize
, ppdip
, recmode_tests
[i
].measuring
, params
, &mode
);
6919 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6920 ok(mode
== expected
, "%.2f/%d: got %d, ppdip %f, flags 0x%04x, expected %d\n", emsize
, i
, mode
, ppdip
, gasp
, expected
);
6924 /* IDWriteFontFace1 offers another variant of this method */
6926 for (i
= 0; i
< ARRAY_SIZE(recmode_tests1
); i
++) {
6930 dpi
= 96.0f
* ppdip
;
6932 gasp
= get_gasp_flags(fontface
, emsize
, ppdip
);
6933 expected
= get_expected_rendering_mode(emsize
* ppdip
, gasp
, recmode_tests1
[i
].measuring
, recmode_tests1
[i
].threshold
);
6934 hr
= IDWriteFontFace1_GetRecommendedRenderingMode(fontface1
, emsize
, dpi
, dpi
,
6935 NULL
, FALSE
, recmode_tests1
[i
].threshold
, recmode_tests1
[i
].measuring
, &mode
);
6936 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6937 ok(mode
== expected
, "%.2f/%d: got %d, dpi %f, flags 0x%04x, expected %d\n", emsize
, i
, mode
, dpi
, gasp
, expected
);
6939 /* Only test larger sizes to workaround Win7 differences, where unscaled natural emsize threshold is used;
6940 Win8 and Win10 handle this as expected. */
6941 if (emsize
> 20.0f
) {
6943 dpi
= 96.0f
* ppdip
;
6945 gasp
= get_gasp_flags(fontface
, emsize
, ppdip
);
6946 expected
= get_expected_rendering_mode(emsize
* ppdip
, gasp
, recmode_tests1
[i
].measuring
, recmode_tests1
[i
].threshold
);
6947 hr
= IDWriteFontFace1_GetRecommendedRenderingMode(fontface1
, emsize
, dpi
, dpi
,
6948 NULL
, FALSE
, recmode_tests1
[i
].threshold
, recmode_tests1
[i
].measuring
, &mode
);
6949 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6950 ok(mode
== expected
, "%.2f/%d: got %d, dpi %f, flags 0x%04x, expected %d\n", emsize
, i
, mode
, dpi
, gasp
, expected
);
6953 dpi
= 96.0f
* ppdip
;
6955 gasp
= get_gasp_flags(fontface
, emsize
, ppdip
);
6956 expected
= get_expected_rendering_mode(emsize
* ppdip
, gasp
, recmode_tests1
[i
].measuring
, recmode_tests1
[i
].threshold
);
6957 hr
= IDWriteFontFace1_GetRecommendedRenderingMode(fontface1
, emsize
, dpi
, dpi
,
6958 NULL
, FALSE
, recmode_tests1
[i
].threshold
, recmode_tests1
[i
].measuring
, &mode
);
6959 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6960 ok(mode
== expected
, "%.2f/%d: got %d, dpi %f, flags 0x%04x, expected %d\n", emsize
, i
, mode
, dpi
, gasp
, expected
);
6962 /* try different dpis for X and Y direction */
6964 dpi
= 96.0f
* ppdip
;
6966 gasp
= get_gasp_flags(fontface
, emsize
, ppdip
);
6967 expected
= get_expected_rendering_mode(emsize
* ppdip
, gasp
, recmode_tests1
[i
].measuring
, recmode_tests1
[i
].threshold
);
6968 hr
= IDWriteFontFace1_GetRecommendedRenderingMode(fontface1
, emsize
, dpi
* 0.5f
, dpi
,
6969 NULL
, FALSE
, recmode_tests1
[i
].threshold
, recmode_tests1
[i
].measuring
, &mode
);
6970 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6971 ok(mode
== expected
, "%.2f/%d: got %d, dpi %f, flags 0x%04x, expected %d\n", emsize
, i
, mode
, dpi
, gasp
, expected
);
6974 dpi
= 96.0f
* ppdip
;
6976 gasp
= get_gasp_flags(fontface
, emsize
, ppdip
);
6977 expected
= get_expected_rendering_mode(emsize
* ppdip
, gasp
, recmode_tests1
[i
].measuring
, recmode_tests1
[i
].threshold
);
6978 hr
= IDWriteFontFace1_GetRecommendedRenderingMode(fontface1
, emsize
, dpi
, dpi
* 0.5f
,
6979 NULL
, FALSE
, recmode_tests1
[i
].threshold
, recmode_tests1
[i
].measuring
, &mode
);
6980 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6981 ok(mode
== expected
, "%.2f/%d: got %d, dpi %f, flags 0x%04x, expected %d\n", emsize
, i
, mode
, dpi
, gasp
, expected
);
6984 dpi
= 96.0f
* ppdip
;
6986 gasp
= get_gasp_flags(fontface
, emsize
, ppdip
);
6987 expected
= get_expected_rendering_mode(emsize
* ppdip
, gasp
, recmode_tests1
[i
].measuring
, recmode_tests1
[i
].threshold
);
6988 hr
= IDWriteFontFace1_GetRecommendedRenderingMode(fontface1
, emsize
, dpi
* 0.5f
, dpi
,
6989 NULL
, FALSE
, recmode_tests1
[i
].threshold
, recmode_tests1
[i
].measuring
, &mode
);
6990 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6991 ok(mode
== expected
, "%.2f/%d: got %d, dpi %f, flags 0x%04x, expected %d\n", emsize
, i
, mode
, dpi
, gasp
, expected
);
6994 dpi
= 96.0f
* ppdip
;
6996 gasp
= get_gasp_flags(fontface
, emsize
, ppdip
);
6997 expected
= get_expected_rendering_mode(emsize
* ppdip
, gasp
, recmode_tests1
[i
].measuring
, recmode_tests1
[i
].threshold
);
6998 hr
= IDWriteFontFace1_GetRecommendedRenderingMode(fontface1
, emsize
, dpi
, dpi
* 0.5f
,
6999 NULL
, FALSE
, recmode_tests1
[i
].threshold
, recmode_tests1
[i
].measuring
, &mode
);
7000 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7001 ok(mode
== expected
, "%.2f/%d: got %d, dpi %f, flags 0x%04x, expected %d\n", emsize
, i
, mode
, dpi
, gasp
, expected
);
7006 /* IDWriteFontFace2 - another one */
7008 DWRITE_GRID_FIT_MODE gridfit
, expected_gridfit
;
7010 gasp
= get_gasp_flags(fontface
, emsize
, 1.0f
);
7011 for (i
= 0; i
< ARRAY_SIZE(recmode_tests1
); i
++) {
7013 expected
= get_expected_rendering_mode(emsize
, gasp
, recmode_tests1
[i
].measuring
, recmode_tests1
[i
].threshold
);
7014 expected_gridfit
= get_expected_gridfit_mode(emsize
, gasp
, recmode_tests1
[i
].measuring
, recmode_tests1
[i
].threshold
);
7015 hr
= IDWriteFontFace2_GetRecommendedRenderingMode(fontface2
, emsize
, 96.0f
, 96.0f
,
7016 NULL
, FALSE
, recmode_tests1
[i
].threshold
, recmode_tests1
[i
].measuring
, params
, &mode
, &gridfit
);
7017 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7018 ok(mode
== expected
, "%.2f: got %d, flags 0x%04x, expected %d\n", emsize
, mode
, gasp
, expected
);
7019 ok(gridfit
== expected_gridfit
, "%.2f/%d: gridfit: got %d, flags 0x%04x, expected %d\n", emsize
, i
, gridfit
,
7020 gasp
, expected_gridfit
);
7024 /* IDWriteFontFace3 - and another one */
7026 DWRITE_GRID_FIT_MODE gridfit
, expected_gridfit
;
7027 DWRITE_RENDERING_MODE1 mode1
, expected1
;
7029 gasp
= get_gasp_flags(fontface
, emsize
, 1.0f
);
7030 for (i
= 0; i
< ARRAY_SIZE(recmode_tests1
); i
++) {
7032 expected1
= get_expected_rendering_mode(emsize
, gasp
, recmode_tests1
[i
].measuring
, recmode_tests1
[i
].threshold
);
7033 expected_gridfit
= get_expected_gridfit_mode(emsize
, gasp
, recmode_tests1
[i
].measuring
, recmode_tests1
[i
].threshold
);
7034 hr
= IDWriteFontFace3_GetRecommendedRenderingMode(fontface3
, emsize
, 96.0f
, 96.0f
,
7035 NULL
, FALSE
, recmode_tests1
[i
].threshold
, recmode_tests1
[i
].measuring
, params
, &mode1
, &gridfit
);
7036 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7037 ok(mode1
== expected1
, "%.2f: got %d, flags 0x%04x, expected %d\n", emsize
, mode1
, gasp
, expected1
);
7038 ok(gridfit
== expected_gridfit
, "%.2f/%d: gridfit: got %d, flags 0x%04x, expected %d\n", emsize
, i
, gridfit
,
7039 gasp
, expected_gridfit
);
7044 IDWriteRenderingParams_Release(params
);
7046 /* test how parameters override returned modes */
7047 hr
= IDWriteFactory_CreateCustomRenderingParams(factory
, 1.0, 0.0, 0.0, DWRITE_PIXEL_GEOMETRY_FLAT
,
7048 DWRITE_RENDERING_MODE_GDI_CLASSIC
, ¶ms
);
7049 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7052 hr
= IDWriteFontFace_GetRecommendedRenderingMode(fontface
, 500.0, 1.0, DWRITE_MEASURING_MODE_NATURAL
, params
, &mode
);
7053 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7054 ok(mode
== DWRITE_RENDERING_MODE_GDI_CLASSIC
, "got %d\n", mode
);
7056 IDWriteRenderingParams_Release(params
);
7059 IDWriteRenderingParams2
*params2
;
7060 IDWriteFactory2
*factory2
;
7061 DWRITE_GRID_FIT_MODE gridfit
;
7063 hr
= IDWriteFactory_QueryInterface(factory
, &IID_IDWriteFactory2
, (void**)&factory2
);
7064 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7066 hr
= IDWriteFactory2_CreateCustomRenderingParams(factory2
, 1.0, 0.0, 0.0, 0.5, DWRITE_PIXEL_GEOMETRY_FLAT
,
7067 DWRITE_RENDERING_MODE_OUTLINE
, DWRITE_GRID_FIT_MODE_ENABLED
, ¶ms2
);
7068 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7072 hr
= IDWriteFontFace2_GetRecommendedRenderingMode(fontface2
, 5.0, 96.0, 96.0,
7073 NULL
, FALSE
, DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
, DWRITE_MEASURING_MODE_GDI_CLASSIC
,
7074 NULL
, &mode
, &gridfit
);
7075 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7076 ok(mode
== DWRITE_RENDERING_MODE_GDI_CLASSIC
, "got %d\n", mode
);
7077 ok(gridfit
== DWRITE_GRID_FIT_MODE_ENABLED
, "got %d\n", gridfit
);
7081 hr
= IDWriteFontFace2_GetRecommendedRenderingMode(fontface2
, 5.0, 96.0, 96.0,
7082 NULL
, FALSE
, DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
, DWRITE_MEASURING_MODE_GDI_CLASSIC
,
7083 (IDWriteRenderingParams
*)params2
, &mode
, &gridfit
);
7084 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7085 ok(mode
== DWRITE_RENDERING_MODE_OUTLINE
, "got %d\n", mode
);
7086 ok(gridfit
== DWRITE_GRID_FIT_MODE_ENABLED
, "got %d\n", gridfit
);
7088 IDWriteRenderingParams2_Release(params2
);
7089 IDWriteFactory2_Release(factory2
);
7093 IDWriteRenderingParams3
*params3
;
7094 IDWriteRenderingParams2
*params2
;
7095 IDWriteRenderingParams
*params
;
7096 IDWriteFactory3
*factory3
;
7097 DWRITE_GRID_FIT_MODE gridfit
;
7098 DWRITE_RENDERING_MODE1 mode1
;
7100 hr
= IDWriteFactory_QueryInterface(factory
, &IID_IDWriteFactory3
, (void**)&factory3
);
7101 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7103 hr
= IDWriteFactory3_CreateCustomRenderingParams(factory3
, 1.0f
, 0.0f
, 0.0f
, 0.5f
, DWRITE_PIXEL_GEOMETRY_FLAT
,
7104 DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC_DOWNSAMPLED
, DWRITE_GRID_FIT_MODE_ENABLED
, ¶ms3
);
7105 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7107 mode1
= IDWriteRenderingParams3_GetRenderingMode1(params3
);
7108 ok(mode1
== DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC_DOWNSAMPLED
, "got %d\n", mode1
);
7110 mode
= IDWriteRenderingParams3_GetRenderingMode(params3
);
7111 ok(mode
== DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
, "got %d\n", mode
);
7113 hr
= IDWriteRenderingParams3_QueryInterface(params3
, &IID_IDWriteRenderingParams
, (void**)¶ms
);
7114 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7115 ok(params
== (IDWriteRenderingParams
*)params3
, "got %p, %p\n", params3
, params
);
7116 mode
= IDWriteRenderingParams_GetRenderingMode(params
);
7117 ok(mode
== DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
, "got %d\n", mode
);
7118 IDWriteRenderingParams_Release(params
);
7120 hr
= IDWriteRenderingParams3_QueryInterface(params3
, &IID_IDWriteRenderingParams2
, (void**)¶ms2
);
7121 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7122 ok(params2
== (IDWriteRenderingParams2
*)params3
, "got %p, %p\n", params3
, params2
);
7123 mode
= IDWriteRenderingParams2_GetRenderingMode(params2
);
7124 ok(mode
== DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
, "got %d\n", mode
);
7125 IDWriteRenderingParams2_Release(params2
);
7129 hr
= IDWriteFontFace2_GetRecommendedRenderingMode(fontface2
, 5.0f
, 96.0f
, 96.0f
,
7130 NULL
, FALSE
, DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
, DWRITE_MEASURING_MODE_GDI_CLASSIC
,
7131 NULL
, &mode
, &gridfit
);
7132 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7133 ok(mode
== DWRITE_RENDERING_MODE_GDI_CLASSIC
, "got %d\n", mode
);
7134 ok(gridfit
== DWRITE_GRID_FIT_MODE_ENABLED
, "got %d\n", gridfit
);
7138 hr
= IDWriteFontFace2_GetRecommendedRenderingMode(fontface2
, 5.0f
, 96.0f
, 96.0f
,
7139 NULL
, FALSE
, DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
, DWRITE_MEASURING_MODE_GDI_CLASSIC
,
7140 (IDWriteRenderingParams
*)params3
, &mode
, &gridfit
);
7141 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7142 ok(mode
== DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
, "got %d\n", mode
);
7143 ok(gridfit
== DWRITE_GRID_FIT_MODE_ENABLED
, "got %d\n", gridfit
);
7145 IDWriteRenderingParams3_Release(params3
);
7146 IDWriteFactory3_Release(factory3
);
7150 IDWriteFontFace3_Release(fontface3
);
7152 IDWriteFontFace2_Release(fontface2
);
7154 IDWriteFontFace1_Release(fontface1
);
7155 IDWriteFontFace_Release(fontface
);
7156 ref
= IDWriteFactory_Release(factory
);
7157 ok(ref
== 0, "factory not released, %u\n", ref
);
7160 static inline BOOL
float_eq(FLOAT left
, FLOAT right
)
7162 int x
= *(int *)&left
;
7163 int y
= *(int *)&right
;
7170 return abs(x
- y
) <= 8;
7173 static void test_GetAlphaBlendParams(void)
7175 static const DWRITE_RENDERING_MODE rendermodes
[] = {
7176 DWRITE_RENDERING_MODE_ALIASED
,
7177 DWRITE_RENDERING_MODE_GDI_CLASSIC
,
7178 DWRITE_RENDERING_MODE_GDI_NATURAL
,
7179 DWRITE_RENDERING_MODE_NATURAL
,
7180 DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
,
7183 IDWriteGlyphRunAnalysis
*analysis
;
7184 FLOAT gamma
, contrast
, ctlevel
;
7185 IDWriteRenderingParams
*params
;
7186 DWRITE_GLYPH_METRICS metrics
;
7187 DWRITE_GLYPH_OFFSET offset
;
7188 IDWriteFontFace
*fontface
;
7189 IDWriteFactory
*factory
;
7190 DWRITE_GLYPH_RUN run
;
7191 FLOAT advance
, expected_gdi_gamma
;
7199 factory
= create_factory();
7200 fontface
= create_fontface(factory
);
7204 hr
= IDWriteFontFace_GetGlyphIndices(fontface
, &ch
, 1, &glyph
);
7205 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7206 ok(glyph
> 0, "got %u\n", glyph
);
7208 hr
= IDWriteFontFace_GetDesignGlyphMetrics(fontface
, &glyph
, 1, &metrics
, FALSE
);
7209 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7210 advance
= metrics
.advanceWidth
;
7212 offset
.advanceOffset
= 0.0;
7213 offset
.ascenderOffset
= 0.0;
7215 run
.fontFace
= fontface
;
7216 run
.fontEmSize
= 24.0;
7218 run
.glyphIndices
= &glyph
;
7219 run
.glyphAdvances
= &advance
;
7220 run
.glyphOffsets
= &offset
;
7221 run
.isSideways
= FALSE
;
7224 hr
= IDWriteFactory_CreateCustomRenderingParams(factory
, 0.9, 0.3, 0.1, DWRITE_PIXEL_GEOMETRY_RGB
,
7225 DWRITE_RENDERING_MODE_DEFAULT
, ¶ms
);
7226 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7229 ret
= SystemParametersInfoW(SPI_GETFONTSMOOTHINGCONTRAST
, 0, &value
, 0);
7230 ok(ret
, "got %d\n", ret
);
7231 expected_gdi_gamma
= (FLOAT
)(value
/ 1000.0);
7233 for (i
= 0; i
< ARRAY_SIZE(rendermodes
); i
++) {
7234 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 1.0, NULL
,
7235 rendermodes
[i
], DWRITE_MEASURING_MODE_NATURAL
,
7236 0.0, 0.0, &analysis
);
7237 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7239 gamma
= contrast
= ctlevel
= -1.0;
7240 hr
= IDWriteGlyphRunAnalysis_GetAlphaBlendParams(analysis
, NULL
, &gamma
, &contrast
, &ctlevel
);
7241 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
7242 ok(gamma
== -1.0, "got %.2f\n", gamma
);
7243 ok(contrast
== -1.0, "got %.2f\n", contrast
);
7244 ok(ctlevel
== -1.0, "got %.2f\n", ctlevel
);
7246 gamma
= contrast
= ctlevel
= -1.0;
7247 hr
= IDWriteGlyphRunAnalysis_GetAlphaBlendParams(analysis
, params
, &gamma
, &contrast
, &ctlevel
);
7248 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7250 if (rendermodes
[i
] == DWRITE_RENDERING_MODE_GDI_CLASSIC
|| rendermodes
[i
] == DWRITE_RENDERING_MODE_GDI_NATURAL
) {
7251 ok(float_eq(gamma
, expected_gdi_gamma
), "got %.2f, expected %.2f\n", gamma
, expected_gdi_gamma
);
7252 ok(contrast
== 0.0f
, "got %.2f\n", contrast
);
7253 ok(ctlevel
== 1.0f
, "got %.2f\n", ctlevel
);
7256 ok(gamma
== 0.9f
, "got %.2f\n", gamma
);
7257 ok(contrast
== 0.3f
, "got %.2f\n", contrast
);
7258 ok(ctlevel
== 0.1f
, "got %.2f\n", ctlevel
);
7261 IDWriteGlyphRunAnalysis_Release(analysis
);
7264 IDWriteRenderingParams_Release(params
);
7265 IDWriteFontFace_Release(fontface
);
7266 ref
= IDWriteFactory_Release(factory
);
7267 ok(ref
== 0, "factory not released, %u\n", ref
);
7270 static void test_CreateAlphaTexture(void)
7272 IDWriteGlyphRunAnalysis
*analysis
;
7273 DWRITE_GLYPH_METRICS metrics
;
7274 DWRITE_GLYPH_OFFSET offset
;
7275 IDWriteFontFace
*fontface
;
7276 IDWriteFactory
*factory
;
7277 DWRITE_GLYPH_RUN run
;
7286 factory
= create_factory();
7287 fontface
= create_fontface(factory
);
7291 hr
= IDWriteFontFace_GetGlyphIndices(fontface
, &ch
, 1, &glyph
);
7292 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7293 ok(glyph
> 0, "got %u\n", glyph
);
7295 hr
= IDWriteFontFace_GetDesignGlyphMetrics(fontface
, &glyph
, 1, &metrics
, FALSE
);
7296 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7297 advance
= metrics
.advanceWidth
;
7299 offset
.advanceOffset
= 0.0;
7300 offset
.ascenderOffset
= 0.0;
7302 run
.fontFace
= fontface
;
7303 run
.fontEmSize
= 24.0;
7305 run
.glyphIndices
= &glyph
;
7306 run
.glyphAdvances
= &advance
;
7307 run
.glyphOffsets
= &offset
;
7308 run
.isSideways
= FALSE
;
7311 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 1.0, NULL
,
7312 DWRITE_RENDERING_MODE_NATURAL
, DWRITE_MEASURING_MODE_NATURAL
,
7313 0.0, 0.0, &analysis
);
7314 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7316 SetRectEmpty(&bounds
);
7317 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_CLEARTYPE_3x1
, &bounds
);
7318 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7319 ok(!IsRectEmpty(&bounds
), "got empty rect\n");
7320 size
= (bounds
.right
- bounds
.left
)*(bounds
.bottom
- bounds
.top
)*3;
7321 ok(sizeof(buff
) >= size
, "required %u\n", size
);
7323 /* invalid type value */
7324 memset(buff
, 0xcf, sizeof(buff
));
7325 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_CLEARTYPE_3x1
+1, &bounds
, buff
, sizeof(buff
));
7326 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
7327 ok(buff
[0] == 0xcf, "got %1x\n", buff
[0]);
7329 memset(buff
, 0xcf, sizeof(buff
));
7330 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &bounds
, buff
, 2);
7331 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
7332 ok(buff
[0] == 0xcf, "got %1x\n", buff
[0]);
7334 /* vista version allows texture type mismatch, mark it broken for now */
7335 memset(buff
, 0xcf, sizeof(buff
));
7336 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &bounds
, buff
, sizeof(buff
));
7337 ok(hr
== DWRITE_E_UNSUPPORTEDOPERATION
|| broken(hr
== S_OK
), "got 0x%08x\n", hr
);
7338 ok(buff
[0] == 0xcf || broken(buff
[0] == 0), "got %1x\n", buff
[0]);
7340 memset(buff
, 0xcf, sizeof(buff
));
7341 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_CLEARTYPE_3x1
, &bounds
, buff
, size
-1);
7342 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
7343 ok(buff
[0] == 0xcf, "got %1x\n", buff
[0]);
7345 IDWriteGlyphRunAnalysis_Release(analysis
);
7347 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 1.0, NULL
,
7348 DWRITE_RENDERING_MODE_ALIASED
, DWRITE_MEASURING_MODE_GDI_CLASSIC
,
7349 0.0, 0.0, &analysis
);
7350 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7352 SetRectEmpty(&bounds
);
7353 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &bounds
);
7354 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7355 ok(!IsRectEmpty(&bounds
), "got empty rect\n");
7356 size
= (bounds
.right
- bounds
.left
)*(bounds
.bottom
- bounds
.top
);
7357 ok(sizeof(buff
) >= size
, "required %u\n", size
);
7359 memset(buff
, 0xcf, sizeof(buff
));
7360 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, NULL
, buff
, sizeof(buff
));
7361 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
7362 ok(buff
[0] == 0xcf, "got %1x\n", buff
[0]);
7364 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, NULL
, NULL
, sizeof(buff
));
7365 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
7367 memset(buff
, 0xcf, sizeof(buff
));
7368 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, NULL
, buff
, 0);
7369 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
7370 ok(buff
[0] == 0xcf, "got %1x\n", buff
[0]);
7372 /* buffer size is not enough */
7373 memset(buff
, 0xcf, sizeof(buff
));
7374 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &bounds
, buff
, size
-1);
7375 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
7376 ok(buff
[0] == 0xcf, "got %1x\n", buff
[0]);
7378 /* request texture for rectangle that doesn't intersect */
7379 memset(buff
, 0xcf, sizeof(buff
));
7381 OffsetRect(&r
, (bounds
.right
- bounds
.left
)*2, 0);
7382 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &r
, buff
, sizeof(buff
));
7383 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7384 ok(buff
[0] == 0, "got %1x\n", buff
[0]);
7386 memset(buff
, 0xcf, sizeof(buff
));
7388 OffsetRect(&r
, (bounds
.right
- bounds
.left
)*2, 0);
7389 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &r
, buff
, sizeof(buff
));
7390 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7391 ok(buff
[0] == 0, "got %1x\n", buff
[0]);
7393 /* request texture for rectangle that doesn't intersect, small buffer */
7394 memset(buff
, 0xcf, sizeof(buff
));
7396 OffsetRect(&r
, (bounds
.right
- bounds
.left
)*2, 0);
7397 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &r
, buff
, size
-1);
7398 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
7399 ok(buff
[0] == 0xcf, "got %1x\n", buff
[0]);
7401 /* vista version allows texture type mismatch, mark it broken for now */
7402 memset(buff
, 0xcf, sizeof(buff
));
7403 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_CLEARTYPE_3x1
, &bounds
, buff
, sizeof(buff
));
7404 ok(hr
== DWRITE_E_UNSUPPORTEDOPERATION
|| broken(hr
== S_OK
), "got 0x%08x\n", hr
);
7405 ok(buff
[0] == 0xcf || broken(buff
[0] == 0), "got %1x\n", buff
[0]);
7407 IDWriteGlyphRunAnalysis_Release(analysis
);
7408 IDWriteFontFace_Release(fontface
);
7409 ref
= IDWriteFactory_Release(factory
);
7410 ok(ref
== 0, "factory not released, %u\n", ref
);
7413 static BOOL
get_expected_is_symbol(IDWriteFontFace
*fontface
)
7415 BOOL exists
, is_symbol
= FALSE
;
7416 struct dwrite_fonttable cmap
;
7417 const TT_OS2_V2
*tt_os2
;
7425 hr
= IDWriteFontFace_TryGetFontTable(fontface
, MS_OS2_TAG
, (const void **)&tt_os2
, &size
, &os2_context
, &exists
);
7426 ok(hr
== S_OK
, "Failed to get OS/2 table, hr %#x.\n", hr
);
7430 is_symbol
= tt_os2
->panose
.bFamilyType
== PAN_FAMILY_PICTORIAL
;
7431 IDWriteFontFace_ReleaseFontTable(fontface
, os2_context
);
7437 hr
= IDWriteFontFace_TryGetFontTable(fontface
, MS_CMAP_TAG
, (const void **)&cmap
.data
,
7438 &cmap
.size
, &cmap
.context
, &exists
);
7439 if (FAILED(hr
) || !exists
)
7442 num_tables
= table_read_be_word(&cmap
, 0, FIELD_OFFSET(struct cmap_header
, num_tables
));
7443 tables
= cmap
.data
+ FIELD_OFFSET(struct cmap_header
, tables
);
7445 for (i
= 0; i
< num_tables
; ++i
)
7447 struct cmap_encoding_record
*record
= (struct cmap_encoding_record
*)(tables
+ i
* sizeof(*record
));
7448 WORD platform
, encoding
;
7450 platform
= table_read_be_word(&cmap
, record
, FIELD_OFFSET(struct cmap_encoding_record
, platformID
));
7451 encoding
= table_read_be_word(&cmap
, record
, FIELD_OFFSET(struct cmap_encoding_record
, encodingID
));
7453 if (platform
== OPENTYPE_CMAP_TABLE_PLATFORM_WIN
&& encoding
== OPENTYPE_CMAP_TABLE_ENCODING_SYMBOL
)
7460 IDWriteFontFace_ReleaseFontTable(fontface
, cmap
.context
);
7465 static void test_IsSymbolFont(void)
7467 IDWriteFontCollection
*collection
;
7468 IDWriteFontFace
*fontface
;
7469 IDWriteFactory
*factory
;
7475 factory
= create_factory();
7477 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &collection
, FALSE
);
7478 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7480 count
= IDWriteFontCollection_GetFontFamilyCount(collection
);
7481 for (i
= 0; i
< count
; ++i
)
7483 IDWriteLocalizedStrings
*names
;
7484 IDWriteFontFamily
*family
;
7485 UINT32 font_count
, j
;
7488 hr
= IDWriteFontCollection_GetFontFamily(collection
, i
, &family
);
7489 ok(hr
== S_OK
, "Failed to get family, hr %#x.\n", hr
);
7491 hr
= IDWriteFontFamily_GetFamilyNames(family
, &names
);
7492 ok(hr
== S_OK
, "Failed to get names, hr %#x.\n", hr
);
7493 get_enus_string(names
, nameW
, ARRAY_SIZE(nameW
));
7494 IDWriteLocalizedStrings_Release(names
);
7496 font_count
= IDWriteFontFamily_GetFontCount(family
);
7498 for (j
= 0; j
< font_count
; ++j
)
7500 BOOL is_symbol_font
, is_symbol_face
, is_symbol_expected
;
7502 hr
= IDWriteFontFamily_GetFont(family
, j
, &font
);
7503 ok(hr
== S_OK
, "Failed to get font, hr %#x.\n", hr
);
7505 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
7506 ok(hr
== S_OK
, "Failed to create fontface, hr %#x.\n", hr
);
7508 is_symbol_font
= IDWriteFont_IsSymbolFont(font
);
7509 is_symbol_face
= IDWriteFontFace_IsSymbolFont(fontface
);
7510 ok(is_symbol_font
== is_symbol_face
, "Unexpected symbol flag.\n");
7512 is_symbol_expected
= get_expected_is_symbol(fontface
);
7513 ok(is_symbol_expected
== is_symbol_face
, "Unexpected is_symbol flag %d for %s, font %d.\n",
7514 is_symbol_face
, wine_dbgstr_w(nameW
), j
);
7516 IDWriteFontFace_Release(fontface
);
7517 IDWriteFont_Release(font
);
7520 IDWriteFontFamily_Release(family
);
7523 IDWriteFontCollection_Release(collection
);
7525 ref
= IDWriteFactory_Release(factory
);
7526 ok(ref
== 0, "factory not released, %u\n", ref
);
7529 struct CPAL_Header_0
7532 USHORT numPaletteEntries
;
7534 USHORT numColorRecords
;
7535 ULONG offsetFirstColorRecord
;
7536 USHORT colorRecordIndices
[1];
7539 static void test_GetPaletteEntries(void)
7541 IDWriteFontFace2
*fontface2
;
7542 IDWriteFontFace
*fontface
;
7543 IDWriteFactory
*factory
;
7545 DWRITE_COLOR_F color
;
7546 UINT32 palettecount
, entrycount
, size
, colorrecords
;
7548 const struct CPAL_Header_0
*cpal_header
;
7553 factory
= create_factory();
7555 /* Tahoma, no color support */
7556 fontface
= create_fontface(factory
);
7557 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace2
, (void**)&fontface2
);
7558 IDWriteFontFace_Release(fontface
);
7560 ref
= IDWriteFactory_Release(factory
);
7561 ok(ref
== 0, "factory not released, %u\n", ref
);
7562 win_skip("GetPaletteEntries() is not supported.\n");
7566 hr
= IDWriteFontFace2_GetPaletteEntries(fontface2
, 0, 0, 1, &color
);
7567 ok(hr
== DWRITE_E_NOCOLOR
, "got 0x%08x\n", hr
);
7568 IDWriteFontFace2_Release(fontface2
);
7570 /* Segoe UI Emoji, with color support */
7571 font
= get_font(factory
, L
"Segoe UI Emoji", DWRITE_FONT_STYLE_NORMAL
);
7573 ref
= IDWriteFactory_Release(factory
);
7574 ok(ref
== 0, "factory not released, %u\n", ref
);
7575 skip("Segoe UI Emoji font not found.\n");
7579 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
7580 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7581 IDWriteFont_Release(font
);
7583 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace2
, (void**)&fontface2
);
7584 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7585 IDWriteFontFace_Release(fontface
);
7587 palettecount
= IDWriteFontFace2_GetColorPaletteCount(fontface2
);
7588 ok(palettecount
>= 1, "got %u\n", palettecount
);
7590 entrycount
= IDWriteFontFace2_GetPaletteEntryCount(fontface2
);
7591 ok(entrycount
>= 1, "got %u\n", entrycount
);
7594 hr
= IDWriteFontFace2_TryGetFontTable(fontface2
, MS_CPAL_TAG
, (const void**)&cpal_header
, &size
, &ctxt
, &exists
);
7595 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7596 ok(exists
, "got %d\n", exists
);
7597 colorrecords
= GET_BE_WORD(cpal_header
->numColorRecords
);
7598 ok(colorrecords
>= 1, "got %u\n", colorrecords
);
7600 /* invalid palette index */
7601 color
.r
= color
.g
= color
.b
= color
.a
= 123.0;
7602 hr
= IDWriteFontFace2_GetPaletteEntries(fontface2
, palettecount
, 0, 1, &color
);
7603 ok(hr
== DWRITE_E_NOCOLOR
, "got 0x%08x\n", hr
);
7604 ok(color
.r
== 123.0 && color
.g
== 123.0 && color
.b
== 123.0 && color
.a
== 123.0,
7605 "got wrong color %.2fx%.2fx%.2fx%.2f\n", color
.r
, color
.g
, color
.b
, color
.a
);
7607 /* invalid entry index */
7608 color
.r
= color
.g
= color
.b
= color
.a
= 123.0;
7609 hr
= IDWriteFontFace2_GetPaletteEntries(fontface2
, 0, entrycount
, 1, &color
);
7610 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
7611 ok(color
.r
== 123.0 && color
.g
== 123.0 && color
.b
== 123.0 && color
.a
== 123.0,
7612 "got wrong color %.2fx%.2fx%.2fx%.2f\n", color
.r
, color
.g
, color
.b
, color
.a
);
7614 color
.r
= color
.g
= color
.b
= color
.a
= 123.0;
7615 hr
= IDWriteFontFace2_GetPaletteEntries(fontface2
, 0, entrycount
- 1, 1, &color
);
7616 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7617 ok(color
.r
!= 123.0 && color
.g
!= 123.0 && color
.b
!= 123.0 && color
.a
!= 123.0,
7618 "got wrong color %.2fx%.2fx%.2fx%.2f\n", color
.r
, color
.g
, color
.b
, color
.a
);
7620 /* zero return length */
7621 color
.r
= color
.g
= color
.b
= color
.a
= 123.0;
7622 hr
= IDWriteFontFace2_GetPaletteEntries(fontface2
, 0, 0, 0, &color
);
7623 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7624 ok(color
.r
== 123.0 && color
.g
== 123.0 && color
.b
== 123.0 && color
.a
== 123.0,
7625 "got wrong color %.2fx%.2fx%.2fx%.2f\n", color
.r
, color
.g
, color
.b
, color
.a
);
7627 IDWriteFontFace2_Release(fontface2
);
7628 ref
= IDWriteFactory_Release(factory
);
7629 ok(ref
== 0, "factory not released, %u\n", ref
);
7632 static void test_TranslateColorGlyphRun(void)
7634 IDWriteColorGlyphRunEnumerator1
*layers1
;
7635 IDWriteColorGlyphRunEnumerator
*layers
;
7636 const DWRITE_COLOR_GLYPH_RUN1
*colorrun1
;
7637 const DWRITE_COLOR_GLYPH_RUN
*colorrun
;
7638 IDWriteFontFace2
*fontface2
;
7639 IDWriteFontFace
*fontface
;
7640 IDWriteFactory2
*factory
;
7641 DWRITE_GLYPH_RUN run
;
7642 UINT32 codepoints
[2];
7649 factory
= create_factory_iid(&IID_IDWriteFactory2
);
7651 win_skip("TranslateColorGlyphRun() is not supported.\n");
7655 /* Tahoma, no color support */
7656 fontface
= create_fontface((IDWriteFactory
*)factory
);
7658 codepoints
[0] = 'A';
7659 hr
= IDWriteFontFace_GetGlyphIndices(fontface
, codepoints
, 1, glyphs
);
7660 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7662 run
.fontFace
= fontface
;
7663 run
.fontEmSize
= 20.0f
;
7665 run
.glyphIndices
= glyphs
;
7666 run
.glyphAdvances
= NULL
;
7667 run
.glyphOffsets
= NULL
;
7668 run
.isSideways
= FALSE
;
7671 layers
= (void*)0xdeadbeef;
7672 hr
= IDWriteFactory2_TranslateColorGlyphRun(factory
, 0.0f
, 0.0f
, &run
, NULL
,
7673 DWRITE_MEASURING_MODE_NATURAL
, NULL
, 0, &layers
);
7674 ok(hr
== DWRITE_E_NOCOLOR
, "got 0x%08x\n", hr
);
7675 ok(layers
== NULL
, "got %p\n", layers
);
7676 IDWriteFontFace_Release(fontface
);
7678 /* Segoe UI Emoji, with color support */
7679 font
= get_font((IDWriteFactory
*)factory
, L
"Segoe UI Emoji", DWRITE_FONT_STYLE_NORMAL
);
7681 IDWriteFactory2_Release(factory
);
7682 skip("Segoe UI Emoji font not found.\n");
7686 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
7687 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7688 IDWriteFont_Release(font
);
7690 codepoints
[0] = 0x26c4;
7691 hr
= IDWriteFontFace_GetGlyphIndices(fontface
, codepoints
, 1, glyphs
);
7692 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7694 run
.fontFace
= fontface
;
7697 hr
= IDWriteFactory2_TranslateColorGlyphRun(factory
, 0.0f
, 0.0f
, &run
, NULL
,
7698 DWRITE_MEASURING_MODE_NATURAL
, NULL
, 0, &layers
);
7699 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7700 ok(layers
!= NULL
, "got %p\n", layers
);
7702 hr
= IDWriteColorGlyphRunEnumerator_QueryInterface(layers
, &IID_IDWriteColorGlyphRunEnumerator1
, (void **)&layers1
);
7706 win_skip("IDWriteColorGlyphRunEnumerator1 is not supported.\n");
7711 hr
= IDWriteColorGlyphRunEnumerator_MoveNext(layers
, &hasrun
);
7712 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7717 hr
= IDWriteColorGlyphRunEnumerator_GetCurrentRun(layers
, &colorrun
);
7718 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7719 ok(colorrun
->glyphRun
.fontFace
!= NULL
, "got fontface %p\n", colorrun
->glyphRun
.fontFace
);
7720 ok(colorrun
->glyphRun
.fontEmSize
== 20.0f
, "got wrong font size %f\n", colorrun
->glyphRun
.fontEmSize
);
7721 ok(colorrun
->glyphRun
.glyphCount
> 0, "got wrong glyph count %u\n", colorrun
->glyphRun
.glyphCount
);
7722 ok(colorrun
->glyphRun
.glyphIndices
!= NULL
, "got null glyph indices %p\n", colorrun
->glyphRun
.glyphIndices
);
7723 ok(colorrun
->glyphRun
.glyphAdvances
!= NULL
, "got null glyph advances %p\n", colorrun
->glyphRun
.glyphAdvances
);
7727 hr
= IDWriteColorGlyphRunEnumerator1_GetCurrentRun(layers1
, &colorrun1
);
7728 ok(hr
== S_OK
, "Failed to get color runt, hr %#x.\n", hr
);
7729 ok(colorrun1
->glyphRun
.fontFace
!= NULL
, "Unexpected fontface %p.\n", colorrun1
->glyphRun
.fontFace
);
7730 ok(colorrun1
->glyphRun
.fontEmSize
== 20.0f
, "Unexpected font size %f.\n", colorrun1
->glyphRun
.fontEmSize
);
7731 ok(colorrun1
->glyphRun
.glyphCount
> 0, "Unexpected glyph count %u\n", colorrun1
->glyphRun
.glyphCount
);
7732 ok(colorrun1
->glyphRun
.glyphIndices
!= NULL
, "Unexpected indices array.\n");
7733 ok(colorrun1
->glyphRun
.glyphAdvances
!= NULL
, "Unexpected advances array.\n");
7737 /* iterated all way through */
7738 hr
= IDWriteColorGlyphRunEnumerator_GetCurrentRun(layers
, &colorrun
);
7739 ok(hr
== E_NOT_VALID_STATE
, "got 0x%08x\n", hr
);
7743 hr
= IDWriteColorGlyphRunEnumerator1_GetCurrentRun(layers1
, &colorrun1
);
7744 ok(hr
== E_NOT_VALID_STATE
, "Unexpected hr %#x.\n", hr
);
7747 IDWriteColorGlyphRunEnumerator_Release(layers
);
7749 IDWriteColorGlyphRunEnumerator1_Release(layers1
);
7751 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace2
, (void**)&fontface2
);
7752 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7754 /* invalid palette index */
7755 layers
= (void*)0xdeadbeef;
7756 hr
= IDWriteFactory2_TranslateColorGlyphRun(factory
, 0.0f
, 0.0f
, &run
, NULL
,
7757 DWRITE_MEASURING_MODE_NATURAL
, NULL
, IDWriteFontFace2_GetColorPaletteCount(fontface2
),
7759 ok(hr
== DWRITE_E_NOCOLOR
, "got 0x%08x\n", hr
);
7760 ok(layers
== NULL
, "got %p\n", layers
);
7763 hr
= IDWriteFactory2_TranslateColorGlyphRun(factory
, 0.0f
, 0.0f
, &run
, NULL
,
7764 DWRITE_MEASURING_MODE_NATURAL
, NULL
, IDWriteFontFace2_GetColorPaletteCount(fontface2
) - 1,
7766 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7767 IDWriteColorGlyphRunEnumerator_Release(layers
);
7769 /* color font, glyph without color info */
7770 codepoints
[0] = 'A';
7771 hr
= IDWriteFontFace_GetGlyphIndices(fontface
, codepoints
, 1, glyphs
);
7772 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7774 layers
= (void*)0xdeadbeef;
7775 hr
= IDWriteFactory2_TranslateColorGlyphRun(factory
, 0.0f
, 0.0f
, &run
, NULL
,
7776 DWRITE_MEASURING_MODE_NATURAL
, NULL
, 0, &layers
);
7777 ok(hr
== DWRITE_E_NOCOLOR
, "got 0x%08x\n", hr
);
7778 ok(layers
== NULL
, "got %p\n", layers
);
7780 /* one glyph with, one without */
7781 codepoints
[0] = 'A';
7782 codepoints
[1] = 0x26c4;
7784 hr
= IDWriteFontFace_GetGlyphIndices(fontface
, codepoints
, 2, glyphs
);
7785 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7790 hr
= IDWriteFactory2_TranslateColorGlyphRun(factory
, 0.0f
, 0.0f
, &run
, NULL
,
7791 DWRITE_MEASURING_MODE_NATURAL
, NULL
, 0, &layers
);
7792 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7793 ok(layers
!= NULL
, "got %p\n", layers
);
7794 IDWriteColorGlyphRunEnumerator_Release(layers
);
7796 IDWriteFontFace2_Release(fontface2
);
7797 IDWriteFontFace_Release(fontface
);
7798 ref
= IDWriteFactory2_Release(factory
);
7799 ok(ref
== 0, "factory not released, %u\n", ref
);
7802 static void test_HasCharacter(void)
7804 IDWriteFactory3
*factory3
;
7805 IDWriteFactory
*factory
;
7806 IDWriteFont3
*font3
;
7812 factory
= create_factory();
7814 font
= get_tahoma_instance(factory
, DWRITE_FONT_STYLE_NORMAL
);
7815 ok(font
!= NULL
, "failed to create font\n");
7817 /* Win8 is broken, QI claims to support IDWriteFont3, but in fact it does not */
7818 hr
= IDWriteFactory_QueryInterface(factory
, &IID_IDWriteFactory3
, (void**)&factory3
);
7820 hr
= IDWriteFont_QueryInterface(font
, &IID_IDWriteFont3
, (void**)&font3
);
7821 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7823 ret
= IDWriteFont3_HasCharacter(font3
, 'A');
7824 ok(ret
, "got %d\n", ret
);
7826 IDWriteFont3_Release(font3
);
7827 IDWriteFactory3_Release(factory3
);
7830 win_skip("IDWriteFont3 is not supported.\n");
7832 IDWriteFont_Release(font
);
7833 ref
= IDWriteFactory_Release(factory
);
7834 ok(ref
== 0, "factory not released, %u\n", ref
);
7837 static BOOL
has_main_axis_values(const DWRITE_FONT_AXIS_VALUE
*values
, unsigned int count
)
7839 BOOL has_wght
= FALSE
, has_wdth
= FALSE
, has_ital
= FALSE
, has_slnt
= FALSE
;
7842 for (i
= 0; i
< count
; ++i
)
7844 if (values
[i
].axisTag
== DWRITE_FONT_AXIS_TAG_WEIGHT
)
7846 else if (values
[i
].axisTag
== DWRITE_FONT_AXIS_TAG_WIDTH
)
7848 else if (values
[i
].axisTag
== DWRITE_FONT_AXIS_TAG_ITALIC
)
7850 else if (values
[i
].axisTag
== DWRITE_FONT_AXIS_TAG_SLANT
)
7854 return has_wght
&& has_wdth
&& has_ital
&& has_slnt
;
7857 static void test_CreateFontFaceReference(void)
7859 IDWriteFontFaceReference
*ref
, *ref1
, *ref3
;
7860 IDWriteFontFace3
*fontface
, *fontface1
;
7861 DWRITE_FONT_AXIS_VALUE axis_values
[16];
7862 IDWriteFontCollection1
*collection
;
7863 IDWriteFontFile
*file
, *file1
;
7864 IDWriteFactory3
*factory
;
7865 UINT32 index
, count
, i
;
7866 IDWriteFont3
*font3
;
7872 factory
= create_factory_iid(&IID_IDWriteFactory3
);
7874 win_skip("CreateFontFaceReference() is not supported.\n");
7878 path
= create_testfontfile(test_fontfile
);
7880 hr
= IDWriteFactory3_CreateFontFaceReference(factory
, NULL
, NULL
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &ref
);
7881 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
7883 /* out of range simulation flags */
7884 hr
= IDWriteFactory3_CreateFontFaceReference(factory
, path
, NULL
, 0, ~0u, &ref
);
7885 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
7887 /* test file is not a collection, but reference could still be created with non-zero face index */
7888 hr
= IDWriteFactory3_CreateFontFaceReference(factory
, path
, NULL
, 1, DWRITE_FONT_SIMULATIONS_NONE
, &ref
);
7889 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7891 index
= IDWriteFontFaceReference_GetFontFaceIndex(ref
);
7892 ok(index
== 1, "got %u\n", index
);
7894 hr
= IDWriteFontFaceReference_GetFontFile(ref
, &file
);
7895 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7896 IDWriteFontFile_Release(file
);
7898 hr
= IDWriteFontFaceReference_CreateFontFace(ref
, &fontface
);
7900 ok(hr
== DWRITE_E_FILEFORMAT
, "got 0x%08x\n", hr
);
7902 IDWriteFontFaceReference_Release(ref
);
7904 /* path however has to be valid */
7905 hr
= IDWriteFactory3_CreateFontFaceReference(factory
, L
"dummy", NULL
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &ref
);
7907 ok(hr
== DWRITE_E_FILENOTFOUND
, "got 0x%08x\n", hr
);
7909 IDWriteFontFaceReference_Release(ref
);
7911 EXPECT_REF(factory
, 1);
7912 hr
= IDWriteFactory3_CreateFontFaceReference(factory
, path
, NULL
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &ref
);
7913 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7914 EXPECT_REF(factory
, 2);
7916 /* new file is returned */
7917 hr
= IDWriteFontFaceReference_GetFontFile(ref
, &file
);
7918 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7920 hr
= IDWriteFontFaceReference_GetFontFile(ref
, &file1
);
7921 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7922 ok(file
!= file1
, "got %p, previous file %p\n", file1
, file
);
7924 IDWriteFontFile_Release(file
);
7925 IDWriteFontFile_Release(file1
);
7927 /* references are not reused */
7928 hr
= IDWriteFactory3_CreateFontFaceReference(factory
, path
, NULL
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &ref1
);
7929 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7930 ok(ref1
!= ref
, "got %p, previous ref %p\n", ref1
, ref
);
7932 /* created fontfaces are cached */
7933 hr
= IDWriteFontFaceReference_CreateFontFace(ref
, &fontface
);
7934 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7936 hr
= IDWriteFontFaceReference_CreateFontFace(ref1
, &fontface1
);
7937 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7938 ok(fontface
== fontface1
, "got %p, expected %p\n", fontface1
, fontface
);
7939 IDWriteFontFace3_Release(fontface
);
7940 IDWriteFontFace3_Release(fontface1
);
7942 /* reference equality */
7943 ret
= IDWriteFontFaceReference_Equals(ref
, ref1
);
7944 ok(ret
, "got %d\n", ret
);
7945 IDWriteFontFaceReference_Release(ref1
);
7947 hr
= IDWriteFactory3_CreateFontFaceReference(factory
, path
, NULL
, 1, DWRITE_FONT_SIMULATIONS_NONE
, &ref1
);
7948 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7949 ret
= IDWriteFontFaceReference_Equals(ref
, ref1
);
7950 ok(!ret
, "got %d\n", ret
);
7951 IDWriteFontFaceReference_Release(ref1
);
7953 hr
= IDWriteFactory3_CreateFontFaceReference(factory
, path
, NULL
, 0, DWRITE_FONT_SIMULATIONS_BOLD
, &ref1
);
7954 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7955 ret
= IDWriteFontFaceReference_Equals(ref
, ref1
);
7956 ok(!ret
, "got %d\n", ret
);
7957 IDWriteFontFaceReference_Release(ref1
);
7959 IDWriteFontFaceReference_Release(ref
);
7961 /* create reference from a file */
7962 hr
= IDWriteFactory3_CreateFontFileReference(factory
, path
, NULL
, &file
);
7963 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7965 hr
= IDWriteFactory3_CreateFontFaceReference_(factory
, file
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &ref
);
7966 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7968 hr
= IDWriteFontFaceReference_GetFontFile(ref
, &file1
);
7969 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7970 ok(file
!= file1
, "got %p, previous file %p\n", file1
, file
);
7972 IDWriteFontFaceReference_Release(ref
);
7973 IDWriteFontFile_Release(file
);
7974 IDWriteFontFile_Release(file1
);
7976 /* References returned from IDWriteFont3/IDWriteFontFace3. */
7977 hr
= IDWriteFactory3_GetSystemFontCollection(factory
, FALSE
, &collection
, FALSE
);
7978 ok(hr
== S_OK
, "Failed to get system collection, hr %#x.\n", hr
);
7980 count
= IDWriteFontCollection1_GetFontFamilyCount(collection
);
7981 for (i
= 0; i
< count
; i
++)
7983 IDWriteFontFamily1
*family
;
7984 UINT32 font_count
, j
;
7986 hr
= IDWriteFontCollection1_GetFontFamily(collection
, i
, &family
);
7987 ok(hr
== S_OK
, "Failed to get family, hr %#x.\n", hr
);
7989 font_count
= IDWriteFontFamily1_GetFontCount(family
);
7991 for (j
= 0; j
< font_count
; j
++)
7993 IDWriteFontFaceReference1
*ref2
;
7995 hr
= IDWriteFontFamily1_GetFont(family
, j
, &font3
);
7996 ok(hr
== S_OK
, "Failed to get font, hr %#x.\n", hr
);
7998 hr
= IDWriteFont3_GetFontFaceReference(font3
, &ref
);
7999 ok(hr
== S_OK
, "Failed to get reference object, hr %#x.\n", hr
);
8001 hr
= IDWriteFont3_GetFontFaceReference(font3
, &ref1
);
8002 ok(hr
== S_OK
, "Failed to get reference object, hr %#x.\n", hr
);
8003 ok(ref
!= ref1
, "Unexpected reference object %p, %p.\n", ref1
, ref
);
8005 hr
= IDWriteFont3_CreateFontFace(font3
, &fontface
);
8006 ok(hr
== S_OK
, "Failed to create a fontface, hr %#x.\n", hr
);
8008 /* Fonts present regular properties as axis values, for non-variable fonts too.
8009 Normally it would include weight/width/slant/italic, but could also contain optical size axis. */
8010 if (SUCCEEDED(hr
= IDWriteFontFaceReference_QueryInterface(ref
, &IID_IDWriteFontFaceReference1
,
8013 UINT32 axis_count
= IDWriteFontFaceReference1_GetFontAxisValueCount(ref2
);
8015 ok(axis_count
>= 4, "Unexpected axis value count.\n");
8017 hr
= IDWriteFontFaceReference1_GetFontAxisValues(ref2
, axis_values
, ARRAY_SIZE(axis_values
));
8018 ok(hr
== S_OK
, "Unexpected hr %#x.\n", hr
);
8021 ok(has_main_axis_values(axis_values
, axis_count
), "Unexpected axis returned.\n");
8023 IDWriteFontFaceReference1_Release(ref2
);
8026 IDWriteFontFaceReference_Release(ref
);
8027 IDWriteFontFaceReference_Release(ref1
);
8029 hr
= IDWriteFontFace3_GetFontFaceReference(fontface
, &ref
);
8030 ok(hr
== S_OK
, "Failed to get a reference, hr %#x.\n", hr
);
8031 EXPECT_REF(fontface
, 2);
8033 hr
= IDWriteFontFace3_GetFontFaceReference(fontface
, &ref1
);
8034 ok(hr
== S_OK
, "Failed to get a reference, hr %#x.\n", hr
);
8035 ok(ref
== ref1
, "Unexpected reference %p, %p.\n", ref1
, ref
);
8036 EXPECT_REF(fontface
, 3);
8038 hr
= IDWriteFontFace3_QueryInterface(fontface
, &IID_IDWriteFontFaceReference
, (void **)&ref3
);
8039 ok(hr
== S_OK
|| broken(FAILED(hr
)), "Failed to get interface, hr %#x.\n", hr
);
8042 ok(ref
== ref3
, "Unexpected reference %p.\n", ref3
);
8043 IDWriteFontFaceReference_Release(ref3
);
8046 hr
= IDWriteFontFaceReference_CreateFontFace(ref
, &fontface1
);
8047 ok(hr
== S_OK
, "Failed to create fontface, hr %#x.\n", hr
);
8048 ok(fontface1
== fontface
, "Unexpected fontface %p, %p.\n", fontface1
, fontface
);
8049 IDWriteFontFace3_Release(fontface1
);
8051 IDWriteFontFaceReference_Release(ref
);
8052 IDWriteFontFaceReference_Release(ref1
);
8054 IDWriteFontFace3_Release(fontface
);
8055 IDWriteFont3_Release(font3
);
8058 IDWriteFontFamily1_Release(family
);
8060 IDWriteFontCollection1_Release(collection
);
8062 refcount
= IDWriteFactory3_Release(factory
);
8063 ok(refcount
== 0, "factory not released, %u\n", refcount
);
8064 DELETE_FONTFILE(path
);
8067 static void get_expected_fontsig(IDWriteFont
*font
, FONTSIGNATURE
*fontsig
)
8070 IDWriteFontFace
*fontface
;
8071 const TT_OS2_V2
*tt_os2
;
8076 memset(fontsig
, 0, sizeof(*fontsig
));
8078 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
8079 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
8081 hr
= IDWriteFontFace_TryGetFontTable(fontface
, MS_OS2_TAG
, (const void **)&tt_os2
, &size
, &os2_context
, &exists
);
8082 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
8085 fontsig
->fsUsb
[0] = GET_BE_DWORD(tt_os2
->ulUnicodeRange1
);
8086 fontsig
->fsUsb
[1] = GET_BE_DWORD(tt_os2
->ulUnicodeRange2
);
8087 fontsig
->fsUsb
[2] = GET_BE_DWORD(tt_os2
->ulUnicodeRange3
);
8088 fontsig
->fsUsb
[3] = GET_BE_DWORD(tt_os2
->ulUnicodeRange4
);
8090 if (GET_BE_WORD(tt_os2
->version
) == 0) {
8091 fontsig
->fsCsb
[0] = 0;
8092 fontsig
->fsCsb
[1] = 0;
8095 fontsig
->fsCsb
[0] = GET_BE_DWORD(tt_os2
->ulCodePageRange1
);
8096 fontsig
->fsCsb
[1] = GET_BE_DWORD(tt_os2
->ulCodePageRange2
);
8099 IDWriteFontFace_ReleaseFontTable(fontface
, os2_context
);
8102 IDWriteFontFace_Release(fontface
);
8105 static void test_GetFontSignature(void)
8107 IDWriteFontCollection
*syscollection
;
8108 IDWriteGdiInterop1
*interop1
;
8109 IDWriteGdiInterop
*interop
;
8110 IDWriteFactory
*factory
;
8111 FONTSIGNATURE fontsig
;
8116 factory
= create_factory();
8118 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop
);
8119 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
8121 hr
= IDWriteGdiInterop_QueryInterface(interop
, &IID_IDWriteGdiInterop1
, (void**)&interop1
);
8122 IDWriteGdiInterop_Release(interop
);
8124 win_skip("GetFontSignature() is not supported.\n");
8125 IDWriteGdiInterop_Release(interop
);
8126 IDWriteFactory_Release(factory
);
8129 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
8131 hr
= IDWriteGdiInterop1_GetFontSignature(interop1
, NULL
, &fontsig
);
8132 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
8134 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &syscollection
, FALSE
);
8135 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
8136 count
= IDWriteFontCollection_GetFontFamilyCount(syscollection
);
8138 for (i
= 0; i
< count
; i
++) {
8139 FONTSIGNATURE expected_signature
;
8140 IDWriteLocalizedStrings
*names
;
8141 IDWriteFontFamily
*family
;
8145 hr
= IDWriteFontCollection_GetFontFamily(syscollection
, i
, &family
);
8146 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
8148 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STRETCH_NORMAL
,
8149 DWRITE_FONT_STYLE_NORMAL
, &font
);
8150 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
8152 hr
= IDWriteFontFamily_GetFamilyNames(family
, &names
);
8153 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
8155 get_enus_string(names
, nameW
, ARRAY_SIZE(nameW
));
8157 IDWriteLocalizedStrings_Release(names
);
8159 hr
= IDWriteGdiInterop1_GetFontSignature(interop1
, font
, &fontsig
);
8160 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
8162 get_expected_fontsig(font
, &expected_signature
);
8164 ok(fontsig
.fsUsb
[0] == expected_signature
.fsUsb
[0], "%s: fsUsb[0] %#x, expected %#x\n", wine_dbgstr_w(nameW
),
8165 fontsig
.fsUsb
[0], expected_signature
.fsUsb
[0]);
8166 ok(fontsig
.fsUsb
[1] == expected_signature
.fsUsb
[1], "%s: fsUsb[1] %#x, expected %#x\n", wine_dbgstr_w(nameW
),
8167 fontsig
.fsUsb
[1], expected_signature
.fsUsb
[1]);
8168 ok(fontsig
.fsUsb
[2] == expected_signature
.fsUsb
[2], "%s: fsUsb[2] %#x, expected %#x\n", wine_dbgstr_w(nameW
),
8169 fontsig
.fsUsb
[2], expected_signature
.fsUsb
[2]);
8170 ok(fontsig
.fsUsb
[3] == expected_signature
.fsUsb
[3], "%s: fsUsb[3] %#x, expected %#x\n", wine_dbgstr_w(nameW
),
8171 fontsig
.fsUsb
[3], expected_signature
.fsUsb
[3]);
8173 ok(fontsig
.fsCsb
[0] == expected_signature
.fsCsb
[0], "%s: fsCsb[0] %#x, expected %#x\n", wine_dbgstr_w(nameW
),
8174 fontsig
.fsCsb
[0], expected_signature
.fsCsb
[0]);
8175 ok(fontsig
.fsCsb
[1] == expected_signature
.fsCsb
[1], "%s: fsCsb[1] %#x, expected %#x\n", wine_dbgstr_w(nameW
),
8176 fontsig
.fsCsb
[1], expected_signature
.fsCsb
[1]);
8178 IDWriteFont_Release(font
);
8179 IDWriteFontFamily_Release(family
);
8182 IDWriteGdiInterop1_Release(interop1
);
8183 IDWriteFontCollection_Release(syscollection
);
8184 ref
= IDWriteFactory_Release(factory
);
8185 ok(ref
== 0, "factory not released, %u\n", ref
);
8188 static void test_font_properties(void)
8190 IDWriteFontFace3
*fontface3
;
8191 IDWriteFontFace
*fontface
;
8192 IDWriteFactory
*factory
;
8193 DWRITE_FONT_STYLE style
;
8198 factory
= create_factory();
8200 /* this creates simulated font */
8201 font
= get_tahoma_instance(factory
, DWRITE_FONT_STYLE_ITALIC
);
8203 style
= IDWriteFont_GetStyle(font
);
8204 ok(style
== DWRITE_FONT_STYLE_OBLIQUE
, "got %u\n", style
);
8206 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
8207 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
8209 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace3
, (void**)&fontface3
);
8210 IDWriteFontFace_Release(fontface
);
8212 style
= IDWriteFontFace3_GetStyle(fontface3
);
8213 ok(style
== DWRITE_FONT_STYLE_OBLIQUE
, "got %u\n", style
);
8215 IDWriteFontFace3_Release(fontface3
);
8218 IDWriteFont_Release(font
);
8219 ref
= IDWriteFactory_Release(factory
);
8220 ok(ref
== 0, "factory not released, %u\n", ref
);
8223 static BOOL
has_vertical_glyph_variants(IDWriteFontFace1
*fontface
)
8225 const OT_FeatureList
*featurelist
;
8226 const OT_LookupList
*lookup_list
;
8227 BOOL exists
= FALSE
, ret
= FALSE
;
8228 const GSUB_Header
*header
;
8235 hr
= IDWriteFontFace1_TryGetFontTable(fontface
, MS_GSUB_TAG
, &data
, &size
, &context
, &exists
);
8236 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
8242 featurelist
= (OT_FeatureList
*)((BYTE
*)header
+ GET_BE_WORD(header
->FeatureList
));
8243 lookup_list
= (const OT_LookupList
*)((BYTE
*)header
+ GET_BE_WORD(header
->LookupList
));
8245 for (i
= 0; i
< GET_BE_WORD(featurelist
->FeatureCount
); i
++) {
8246 if (*(UINT32
*)featurelist
->FeatureRecord
[i
].FeatureTag
== DWRITE_FONT_FEATURE_TAG_VERTICAL_WRITING
) {
8247 const OT_Feature
*feature
= (const OT_Feature
*)((BYTE
*)featurelist
+ GET_BE_WORD(featurelist
->FeatureRecord
[i
].Feature
));
8248 UINT16 lookup_count
= GET_BE_WORD(feature
->LookupCount
), i
, index
, count
, type
;
8249 const GSUB_SingleSubstFormat2
*subst2
;
8250 const OT_LookupTable
*lookup_table
;
8253 if (lookup_count
== 0)
8256 for (i
= 0; i
< lookup_count
; i
++) {
8257 /* check if lookup is empty */
8258 index
= GET_BE_WORD(feature
->LookupListIndex
[i
]);
8259 lookup_table
= (const OT_LookupTable
*)((BYTE
*)lookup_list
+ GET_BE_WORD(lookup_list
->Lookup
[index
]));
8261 type
= GET_BE_WORD(lookup_table
->LookupType
);
8262 ok(type
== 1 || type
== 7, "got unexpected lookup type %u\n", type
);
8264 count
= GET_BE_WORD(lookup_table
->SubTableCount
);
8268 ok(count
> 0, "got unexpected subtable count %u\n", count
);
8270 offset
= GET_BE_WORD(lookup_table
->SubTable
[0]);
8272 const GSUB_ExtensionPosFormat1
*ext
= (const GSUB_ExtensionPosFormat1
*)((const BYTE
*)lookup_table
+ offset
);
8273 if (GET_BE_WORD(ext
->SubstFormat
) == 1)
8274 offset
+= GET_BE_DWORD(ext
->ExtensionOffset
);
8276 ok(0, "Unhandled Extension Substitution Format %u\n", GET_BE_WORD(ext
->SubstFormat
));
8279 subst2
= (const GSUB_SingleSubstFormat2
*)((BYTE
*)lookup_table
+ offset
);
8280 index
= GET_BE_WORD(subst2
->SubstFormat
);
8283 else if (index
== 2) {
8284 /* SimSun-ExtB has 0 glyph count for this substitution */
8285 if (GET_BE_WORD(subst2
->GlyphCount
) > 0)
8289 ok(0, "unknown Single Substitution Format, %u\n", index
);
8297 IDWriteFontFace1_ReleaseFontTable(fontface
, context
);
8302 static void test_HasVerticalGlyphVariants(void)
8304 IDWriteFontCollection
*syscollection
;
8305 IDWriteFontFace1
*fontface1
;
8306 IDWriteFontFace
*fontface
;
8307 IDWriteFactory
*factory
;
8312 factory
= create_factory();
8313 fontface
= create_fontface(factory
);
8315 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void**)&fontface1
);
8316 IDWriteFontFace_Release(fontface
);
8318 win_skip("HasVerticalGlyphVariants() is not supported.\n");
8319 IDWriteFactory_Release(factory
);
8322 IDWriteFontFace1_Release(fontface1
);
8324 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &syscollection
, FALSE
);
8325 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
8326 count
= IDWriteFontCollection_GetFontFamilyCount(syscollection
);
8328 for (i
= 0; i
< count
; i
++) {
8329 IDWriteLocalizedStrings
*names
;
8330 BOOL expected_vert
, has_vert
;
8331 IDWriteFontFamily
*family
;
8335 hr
= IDWriteFontCollection_GetFontFamily(syscollection
, i
, &family
);
8336 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
8338 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STRETCH_NORMAL
,
8339 DWRITE_FONT_STYLE_NORMAL
, &font
);
8340 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
8342 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
8343 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
8345 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void**)&fontface1
);
8346 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
8348 hr
= IDWriteFontFamily_GetFamilyNames(family
, &names
);
8349 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
8351 get_enus_string(names
, nameW
, ARRAY_SIZE(nameW
));
8353 expected_vert
= has_vertical_glyph_variants(fontface1
);
8354 has_vert
= IDWriteFontFace1_HasVerticalGlyphVariants(fontface1
);
8356 ok(expected_vert
== has_vert
, "%s: expected vertical feature %d, got %d\n",
8357 wine_dbgstr_w(nameW
), expected_vert
, has_vert
);
8359 IDWriteLocalizedStrings_Release(names
);
8360 IDWriteFont_Release(font
);
8362 IDWriteFontFace1_Release(fontface1
);
8363 IDWriteFontFace_Release(fontface
);
8364 IDWriteFontFamily_Release(family
);
8367 IDWriteFontCollection_Release(syscollection
);
8368 ref
= IDWriteFactory_Release(factory
);
8369 ok(ref
== 0, "factory not released, %u\n", ref
);
8372 static void test_HasKerningPairs(void)
8374 IDWriteFontCollection
*syscollection
;
8375 IDWriteFontFace1
*fontface1
;
8376 IDWriteFontFace
*fontface
;
8377 IDWriteFactory
*factory
;
8382 factory
= create_factory();
8383 fontface
= create_fontface(factory
);
8385 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void**)&fontface1
);
8386 IDWriteFontFace_Release(fontface
);
8388 win_skip("HasKerningPairs() is not supported.\n");
8389 IDWriteFactory_Release(factory
);
8392 IDWriteFontFace1_Release(fontface1
);
8394 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &syscollection
, FALSE
);
8395 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
8396 count
= IDWriteFontCollection_GetFontFamilyCount(syscollection
);
8398 for (i
= 0; i
< count
; i
++) {
8399 IDWriteLocalizedStrings
*names
;
8400 BOOL exists
, has_kerningpairs
;
8401 IDWriteFontFamily
*family
;
8408 hr
= IDWriteFontCollection_GetFontFamily(syscollection
, i
, &family
);
8409 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
8411 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STRETCH_NORMAL
,
8412 DWRITE_FONT_STYLE_NORMAL
, &font
);
8413 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
8415 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
8416 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
8418 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void **)&fontface1
);
8419 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
8421 hr
= IDWriteFontFamily_GetFamilyNames(family
, &names
);
8422 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
8424 get_enus_string(names
, nameW
, ARRAY_SIZE(nameW
));
8427 hr
= IDWriteFontFace1_TryGetFontTable(fontface1
, MS_KERN_TAG
, &data
, &size
, &context
, &exists
);
8428 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
8429 IDWriteFontFace1_ReleaseFontTable(fontface1
, context
);
8431 has_kerningpairs
= IDWriteFontFace1_HasKerningPairs(fontface1
);
8433 ok(!has_kerningpairs
, "%s: expected %d, got %d\n", wine_dbgstr_w(nameW
), exists
, has_kerningpairs
);
8435 IDWriteLocalizedStrings_Release(names
);
8436 IDWriteFont_Release(font
);
8438 IDWriteFontFace1_Release(fontface1
);
8439 IDWriteFontFace_Release(fontface
);
8440 IDWriteFontFamily_Release(family
);
8443 IDWriteFontCollection_Release(syscollection
);
8444 ref
= IDWriteFactory_Release(factory
);
8445 ok(ref
== 0, "factory not released, %u\n", ref
);
8448 static void get_expected_glyph_origins(D2D1_POINT_2F baseline_origin
, const DWRITE_GLYPH_RUN
*run
,
8449 D2D1_POINT_2F
*origins
)
8453 if (run
->bidiLevel
& 1)
8455 DWRITE_GLYPH_METRICS glyph_metrics
[2];
8456 DWRITE_FONT_METRICS metrics
;
8460 hr
= IDWriteFontFace_GetDesignGlyphMetrics(run
->fontFace
, run
->glyphIndices
, run
->glyphCount
, glyph_metrics
, FALSE
);
8461 ok(hr
== S_OK
, "Failed to get glyph metrics, hr %#x.\n", hr
);
8463 IDWriteFontFace_GetMetrics(run
->fontFace
, &metrics
);
8465 advance
= run
->fontEmSize
* glyph_metrics
[0].advanceWidth
/ metrics
.designUnitsPerEm
;
8467 baseline_origin
.x
-= advance
;
8469 for (i
= 0; i
< run
->glyphCount
; ++i
)
8471 origins
[i
].x
= baseline_origin
.x
- run
->glyphOffsets
[i
].advanceOffset
;
8472 origins
[i
].y
= baseline_origin
.y
- run
->glyphOffsets
[i
].ascenderOffset
;
8474 baseline_origin
.x
-= run
->glyphAdvances
[i
];
8479 for (i
= 0; i
< run
->glyphCount
; ++i
)
8481 origins
[i
].x
= baseline_origin
.x
+ run
->glyphOffsets
[i
].advanceOffset
;
8482 origins
[i
].y
= baseline_origin
.y
- run
->glyphOffsets
[i
].ascenderOffset
;
8484 baseline_origin
.x
+= run
->glyphAdvances
[i
];
8489 static void test_ComputeGlyphOrigins(void)
8491 static const struct origins_test
8493 D2D1_POINT_2F baseline_origin
;
8495 DWRITE_GLYPH_OFFSET offsets
[2];
8496 unsigned int bidi_level
;
8500 { { 123.0f
, 321.0f
}, { 10.0f
, 20.0f
}, { { 0 } } },
8501 { { 123.0f
, 321.0f
}, { 10.0f
, 20.0f
}, { { 0.3f
, 0.5f
}, { -0.1f
, 0.9f
} } },
8502 { { 123.0f
, 321.0f
}, { 10.0f
, 20.0f
}, { { 0 } }, 1 },
8504 IDWriteFactory4
*factory
;
8505 DWRITE_GLYPH_RUN run
;
8507 D2D1_POINT_2F origins
[2], expected_origins
[2];
8508 D2D1_POINT_2F baseline_origin
;
8509 UINT16 glyphs
[2] = { 0 };
8514 IDWriteFontFace
*fontface
;
8516 factory
= create_factory_iid(&IID_IDWriteFactory4
);
8518 win_skip("ComputeGlyphOrigins() is not supported.\n");
8522 fontface
= create_fontface((IDWriteFactory
*)factory
);
8524 for (i
= 0; i
< ARRAY_SIZE(origins_tests
); ++i
)
8526 run
.fontFace
= fontface
;
8527 run
.fontEmSize
= 32.0f
;
8529 run
.glyphIndices
= glyphs
;
8530 run
.glyphAdvances
= origins_tests
[i
].advances
;
8531 run
.glyphOffsets
= origins_tests
[i
].offsets
;
8532 run
.isSideways
= FALSE
;
8533 run
.bidiLevel
= origins_tests
[i
].bidi_level
;
8535 get_expected_glyph_origins(origins_tests
[i
].baseline_origin
, &run
, expected_origins
);
8537 memset(origins
, 0, sizeof(origins
));
8538 hr
= IDWriteFactory4_ComputeGlyphOrigins_(factory
, &run
, origins_tests
[i
].baseline_origin
, origins
);
8539 ok(hr
== S_OK
, "%u: failed to compute glyph origins, hr %#x.\n", i
, hr
);
8540 for (j
= 0; j
< run
.glyphCount
; ++j
)
8542 ok(!memcmp(&origins
[j
], &expected_origins
[j
], sizeof(origins
[j
])),
8543 "%u: unexpected origin[%u] (%f, %f) - (%f, %f).\n", i
, j
, origins
[j
].x
, origins
[j
].y
,
8544 expected_origins
[j
].x
, expected_origins
[j
].y
);
8548 IDWriteFontFace_Release(fontface
);
8550 advances
[0] = 10.0f
;
8551 advances
[1] = 20.0f
;
8553 run
.fontFace
= NULL
;
8554 run
.fontEmSize
= 16.0f
;
8556 run
.glyphIndices
= glyphs
;
8557 run
.glyphAdvances
= advances
;
8558 run
.glyphOffsets
= NULL
;
8559 run
.isSideways
= FALSE
;
8562 baseline_origin
.x
= 123.0f
;
8563 baseline_origin
.y
= 321.0f
;
8565 memset(origins
, 0, sizeof(origins
));
8566 hr
= IDWriteFactory4_ComputeGlyphOrigins_(factory
, &run
, baseline_origin
, origins
);
8567 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
8568 ok(origins
[0].x
== 123.0f
&& origins
[0].y
== 321.0f
, "origins[0] %f,%f\n", origins
[0].x
, origins
[0].y
);
8569 ok(origins
[1].x
== 133.0f
&& origins
[1].y
== 321.0f
, "origins[1] %f,%f\n", origins
[1].x
, origins
[1].y
);
8571 memset(origins
, 0, sizeof(origins
));
8572 hr
= IDWriteFactory4_ComputeGlyphOrigins(factory
, &run
, DWRITE_MEASURING_MODE_NATURAL
, baseline_origin
,
8574 ok(origins
[0].x
== 123.0f
&& origins
[0].y
== 321.0f
, "origins[0] %f,%f\n", origins
[0].x
, origins
[0].y
);
8575 ok(origins
[1].x
== 133.0f
&& origins
[1].y
== 321.0f
, "origins[1] %f,%f\n", origins
[1].x
, origins
[1].y
);
8577 /* transform is not applied to returned origins */
8585 memset(origins
, 0, sizeof(origins
));
8586 hr
= IDWriteFactory4_ComputeGlyphOrigins(factory
, &run
, DWRITE_MEASURING_MODE_NATURAL
, baseline_origin
,
8588 ok(origins
[0].x
== 123.0f
&& origins
[0].y
== 321.0f
, "origins[0] %f,%f\n", origins
[0].x
, origins
[0].y
);
8589 ok(origins
[1].x
== 133.0f
&& origins
[1].y
== 321.0f
, "origins[1] %f,%f\n", origins
[1].x
, origins
[1].y
);
8591 ref
= IDWriteFactory4_Release(factory
);
8592 ok(ref
== 0, "factory not released, %u\n", ref
);
8595 static void test_object_lifetime(void)
8597 IDWriteFontCollection
*collection
, *collection2
;
8598 IDWriteFontList
*fontlist
, *fontlist2
;
8599 IDWriteGdiInterop
*interop
, *interop2
;
8600 IDWriteFontFamily
*family
, *family2
;
8601 IDWriteFontFace
*fontface
;
8602 IDWriteFont
*font
, *font2
;
8603 IDWriteFactory
*factory
;
8607 factory
= create_factory();
8608 EXPECT_REF(factory
, 1);
8610 /* system collection takes factory reference */
8611 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &collection
, FALSE
);
8612 ok(hr
== S_OK
, "got %#x\n", hr
);
8614 EXPECT_REF(collection
, 1);
8615 EXPECT_REF(factory
, 2);
8617 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &collection2
, FALSE
);
8618 ok(hr
== S_OK
, "got %#x\n", hr
);
8619 ok(collection2
== collection
, "expected same collection\n");
8621 EXPECT_REF(collection
, 2);
8622 EXPECT_REF(factory
, 2);
8624 IDWriteFontCollection_Release(collection2
);
8626 IDWriteFontCollection_AddRef(collection
);
8627 EXPECT_REF(collection
, 2);
8628 EXPECT_REF(factory
, 2);
8629 IDWriteFontCollection_Release(collection
);
8631 EXPECT_REF(collection
, 1);
8633 /* family takes collection reference */
8634 hr
= IDWriteFontCollection_GetFontFamily(collection
, 0, &family
);
8635 ok(hr
== S_OK
, "got %#x\n", hr
);
8637 EXPECT_REF(family
, 1);
8638 EXPECT_REF(collection
, 2);
8639 EXPECT_REF(factory
, 2);
8641 hr
= IDWriteFontCollection_GetFontFamily(collection
, 0, &family2
);
8642 ok(hr
== S_OK
, "got %#x\n", hr
);
8644 EXPECT_REF(family2
, 1);
8645 EXPECT_REF(collection
, 3);
8646 EXPECT_REF(factory
, 2);
8648 IDWriteFontFamily_Release(family2
);
8650 EXPECT_REF(family
, 1);
8651 EXPECT_REF(collection
, 2);
8652 EXPECT_REF(factory
, 2);
8654 /* font takes family reference */
8655 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
,
8656 DWRITE_FONT_STRETCH_NORMAL
, DWRITE_FONT_STYLE_NORMAL
, &font
);
8657 ok(hr
== S_OK
, "got %#x\n", hr
);
8659 EXPECT_REF(family
, 2);
8660 EXPECT_REF(collection
, 2);
8661 EXPECT_REF(factory
, 2);
8663 hr
= IDWriteFont_GetFontFamily(font
, &family2
);
8664 ok(hr
== S_OK
, "got %#x\n", hr
);
8665 ok(family2
== family
, "unexpected family pointer\n");
8666 IDWriteFontFamily_Release(family2
);
8668 EXPECT_REF(font
, 1);
8669 EXPECT_REF(factory
, 2);
8671 /* Fontface takes factory reference and nothing else. */
8672 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
8673 ok(hr
== S_OK
, "got %#x\n", hr
);
8675 EXPECT_REF(font
, 1);
8676 EXPECT_REF_BROKEN(fontface
, 1, 2);
8677 EXPECT_REF(family
, 2);
8678 EXPECT_REF(collection
, 2);
8679 EXPECT_REF_BROKEN(factory
, 3, 2);
8681 /* get font from fontface */
8682 hr
= IDWriteFontCollection_GetFontFromFontFace(collection
, fontface
, &font2
);
8683 ok(hr
== S_OK
, "got %#x\n", hr
);
8685 EXPECT_REF(font
, 1);
8686 EXPECT_REF(font2
, 1);
8687 EXPECT_REF_BROKEN(fontface
, 1, 2);
8688 EXPECT_REF(family
, 2);
8689 EXPECT_REF(collection
, 3);
8690 EXPECT_REF_BROKEN(factory
, 3, 2);
8692 IDWriteFont_Release(font2
);
8693 IDWriteFontFace_Release(fontface
);
8695 EXPECT_REF(font
, 1);
8696 EXPECT_REF(family
, 2);
8697 EXPECT_REF(collection
, 2);
8698 EXPECT_REF(factory
, 2);
8700 IDWriteFont_Release(font
);
8702 EXPECT_REF(family
, 1);
8703 EXPECT_REF(collection
, 2);
8704 EXPECT_REF(factory
, 2);
8706 /* Matching fonts list takes family reference. */
8707 hr
= IDWriteFontFamily_GetMatchingFonts(family
, DWRITE_FONT_WEIGHT_NORMAL
,
8708 DWRITE_FONT_STRETCH_NORMAL
, DWRITE_FONT_STYLE_NORMAL
, &fontlist
);
8709 ok(hr
== S_OK
, "got %#x\n", hr
);
8711 EXPECT_REF(family
, 2);
8712 EXPECT_REF(collection
, 2);
8713 EXPECT_REF(factory
, 2);
8715 hr
= IDWriteFontFamily_GetMatchingFonts(family
, DWRITE_FONT_WEIGHT_NORMAL
,
8716 DWRITE_FONT_STRETCH_NORMAL
, DWRITE_FONT_STYLE_NORMAL
, &fontlist2
);
8717 ok(hr
== S_OK
, "got %#x\n", hr
);
8718 ok(fontlist2
!= fontlist
, "unexpected font list\n");
8719 IDWriteFontList_Release(fontlist2
);
8721 IDWriteFontList_Release(fontlist
);
8723 IDWriteFontFamily_Release(family
);
8724 EXPECT_REF(collection
, 1);
8726 EXPECT_REF(factory
, 2);
8727 ref
= IDWriteFontCollection_Release(collection
);
8728 ok(ref
== 0, "collection not released, %u\n", ref
);
8729 EXPECT_REF(factory
, 1);
8731 /* GDI interop object takes factory reference */
8732 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop
);
8733 ok(hr
== S_OK
, "got %#x\n", hr
);
8734 EXPECT_REF(interop
, 1);
8735 EXPECT_REF(factory
, 2);
8737 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop2
);
8738 ok(hr
== S_OK
, "got %#x\n", hr
);
8739 ok(interop
== interop2
, "got unexpected interop pointer\n");
8741 EXPECT_REF(interop
, 2);
8742 EXPECT_REF(factory
, 2);
8744 IDWriteGdiInterop_Release(interop2
);
8745 ref
= IDWriteGdiInterop_Release(interop
);
8746 ok(ref
== 0, "interop not released, %u\n", ref
);
8748 ref
= IDWriteFactory_Release(factory
);
8749 ok(ref
== 0, "factory not released, %u\n", ref
);
8752 struct testowner_object
8754 IUnknown IUnknown_iface
;
8758 static inline struct testowner_object
*impl_from_IUnknown(IUnknown
*iface
)
8760 return CONTAINING_RECORD(iface
, struct testowner_object
, IUnknown_iface
);
8763 static HRESULT WINAPI
testowner_QueryInterface(IUnknown
*iface
, REFIID riid
, void **obj
)
8765 if (IsEqualIID(riid
, &IID_IUnknown
)) {
8767 IUnknown_AddRef(iface
);
8772 return E_NOINTERFACE
;
8775 static ULONG WINAPI
testowner_AddRef(IUnknown
*iface
)
8777 struct testowner_object
*object
= impl_from_IUnknown(iface
);
8778 return InterlockedIncrement(&object
->ref
);
8781 static ULONG WINAPI
testowner_Release(IUnknown
*iface
)
8783 struct testowner_object
*object
= impl_from_IUnknown(iface
);
8784 return InterlockedDecrement(&object
->ref
);
8787 static const IUnknownVtbl testownervtbl
= {
8788 testowner_QueryInterface
,
8793 static void testowner_init(struct testowner_object
*object
)
8795 object
->IUnknown_iface
.lpVtbl
= &testownervtbl
;
8799 static void test_inmemory_file_loader(void)
8801 IDWriteFontFileStream
*stream
, *stream2
, *stream3
;
8802 IDWriteInMemoryFontFileLoader
*loader
, *loader2
;
8803 IDWriteInMemoryFontFileLoader
*inmemory
;
8804 IDWriteFontFileLoader
*fileloader
;
8805 struct testowner_object ownerobject
;
8806 const void *key
, *data
, *frag_start
;
8807 UINT64 file_size
, size
, writetime
;
8808 IDWriteFontFile
*file
, *file2
;
8809 IDWriteFontFace
*fontface
;
8810 void *context
, *context2
;
8811 IDWriteFactory5
*factory
;
8812 UINT32 count
, key_size
;
8817 factory
= create_factory_iid(&IID_IDWriteFactory5
);
8819 win_skip("CreateInMemoryFontFileLoader() is not supported\n");
8823 EXPECT_REF(factory
, 1);
8824 hr
= IDWriteFactory5_CreateInMemoryFontFileLoader(factory
, &loader
);
8825 ok(hr
== S_OK
, "got %#x\n", hr
);
8826 EXPECT_REF(factory
, 1);
8828 testowner_init(&ownerobject
);
8829 fontface
= create_fontface((IDWriteFactory
*)factory
);
8831 hr
= IDWriteFactory5_CreateInMemoryFontFileLoader(factory
, &loader2
);
8832 ok(hr
== S_OK
, "got %#x\n", hr
);
8833 ok(loader
!= loader2
, "unexpected pointer\n");
8834 IDWriteInMemoryFontFileLoader_Release(loader2
);
8838 count
= IDWriteInMemoryFontFileLoader_GetFileCount(inmemory
);
8839 ok(!count
, "Unexpected file count %u.\n", count
);
8841 /* Use whole font blob to construct in-memory file. */
8843 hr
= IDWriteFontFace_GetFiles(fontface
, &count
, &file
);
8844 ok(hr
== S_OK
, "got %#x\n", hr
);
8846 hr
= IDWriteFontFile_GetLoader(file
, &fileloader
);
8847 ok(hr
== S_OK
, "got %#x\n", hr
);
8849 hr
= IDWriteFontFile_GetReferenceKey(file
, &key
, &key_size
);
8850 ok(hr
== S_OK
, "got %#x\n", hr
);
8852 hr
= IDWriteFontFileLoader_CreateStreamFromKey(fileloader
, key
, key_size
, &stream
);
8853 ok(hr
== S_OK
, "got %#x\n", hr
);
8854 IDWriteFontFileLoader_Release(fileloader
);
8855 IDWriteFontFile_Release(file
);
8857 hr
= IDWriteFontFileStream_GetFileSize(stream
, &file_size
);
8858 ok(hr
== S_OK
, "got %#x\n", hr
);
8860 hr
= IDWriteFontFileStream_ReadFileFragment(stream
, &data
, 0, file_size
, &context
);
8861 ok(hr
== S_OK
, "got %#x\n", hr
);
8863 /* Not registered yet. */
8864 hr
= IDWriteInMemoryFontFileLoader_CreateInMemoryFontFileReference(inmemory
, (IDWriteFactory
*)factory
, data
,
8865 file_size
, NULL
, &file
);
8866 ok(hr
== E_INVALIDARG
, "got %#x\n", hr
);
8868 count
= IDWriteInMemoryFontFileLoader_GetFileCount(inmemory
);
8869 ok(count
== 1, "Unexpected file count %u.\n", count
);
8871 hr
= IDWriteFactory5_RegisterFontFileLoader(factory
, (IDWriteFontFileLoader
*)inmemory
);
8872 ok(hr
== S_OK
, "got %#x\n", hr
);
8873 EXPECT_REF(inmemory
, 2);
8875 EXPECT_REF(&ownerobject
.IUnknown_iface
, 1);
8876 hr
= IDWriteInMemoryFontFileLoader_CreateInMemoryFontFileReference(inmemory
, (IDWriteFactory
*)factory
, data
,
8877 file_size
, &ownerobject
.IUnknown_iface
, &file
);
8878 ok(hr
== S_OK
, "got %#x\n", hr
);
8879 EXPECT_REF(&ownerobject
.IUnknown_iface
, 2);
8880 EXPECT_REF(inmemory
, 3);
8882 count
= IDWriteInMemoryFontFileLoader_GetFileCount(inmemory
);
8883 ok(count
== 2, "Unexpected file count %u.\n", count
);
8885 hr
= IDWriteInMemoryFontFileLoader_CreateInMemoryFontFileReference(inmemory
, (IDWriteFactory
*)factory
, data
,
8886 file_size
, &ownerobject
.IUnknown_iface
, &file2
);
8887 ok(hr
== S_OK
, "got %#x\n", hr
);
8888 ok(file2
!= file
, "got unexpected file\n");
8889 EXPECT_REF(&ownerobject
.IUnknown_iface
, 3);
8890 EXPECT_REF(inmemory
, 4);
8892 count
= IDWriteInMemoryFontFileLoader_GetFileCount(inmemory
);
8893 ok(count
== 3, "Unexpected file count %u.\n", count
);
8895 /* Check in-memory reference key format. */
8896 hr
= IDWriteFontFile_GetReferenceKey(file
, &key
, &key_size
);
8897 ok(hr
== S_OK
, "got %#x\n", hr
);
8899 ok(key
&& *(DWORD
*)key
== 1, "got wrong ref key\n");
8900 ok(key_size
== 4, "ref key size %u\n", key_size
);
8902 hr
= IDWriteFontFile_GetReferenceKey(file2
, &key
, &key_size
);
8903 ok(hr
== S_OK
, "got %#x\n", hr
);
8905 ok(key
&& *(DWORD
*)key
== 2, "got wrong ref key\n");
8906 ok(key_size
== 4, "ref key size %u\n", key_size
);
8908 EXPECT_REF(inmemory
, 4);
8909 hr
= IDWriteInMemoryFontFileLoader_CreateStreamFromKey(inmemory
, key
, key_size
, &stream2
);
8910 ok(hr
== S_OK
, "Failed to create a stream, hr %#x.\n", hr
);
8911 EXPECT_REF(stream2
, 1);
8912 EXPECT_REF(inmemory
, 4);
8914 hr
= IDWriteInMemoryFontFileLoader_CreateStreamFromKey(inmemory
, key
, key_size
, &stream3
);
8915 ok(hr
== S_OK
, "Failed to create a stream, hr %#x.\n", hr
);
8917 ok(stream2
!= stream3
, "Unexpected stream.\n");
8919 IDWriteFontFileStream_Release(stream2
);
8920 IDWriteFontFileStream_Release(stream3
);
8922 /* Release file at index 1, create new one to see if index is reused. */
8923 EXPECT_REF(&ownerobject
.IUnknown_iface
, 3);
8924 ref
= IDWriteFontFile_Release(file
);
8925 ok(ref
== 0, "File object not released, %u.\n", ref
);
8926 EXPECT_REF(&ownerobject
.IUnknown_iface
, 3);
8928 count
= IDWriteInMemoryFontFileLoader_GetFileCount(inmemory
);
8929 ok(count
== 3, "Unexpected file count %u.\n", count
);
8931 EXPECT_REF(&ownerobject
.IUnknown_iface
, 3);
8932 ref
= IDWriteFontFile_Release(file2
);
8933 ok(ref
== 0, "File object not released, %u.\n", ref
);
8934 EXPECT_REF(&ownerobject
.IUnknown_iface
, 3);
8936 count
= IDWriteInMemoryFontFileLoader_GetFileCount(inmemory
);
8937 ok(count
== 3, "Unexpected file count %u.\n", count
);
8939 hr
= IDWriteFactory5_UnregisterFontFileLoader(factory
, (IDWriteFontFileLoader
*)inmemory
);
8940 ok(hr
== S_OK
, "got %#x\n", hr
);
8941 EXPECT_REF(&ownerobject
.IUnknown_iface
, 3);
8943 EXPECT_REF(&ownerobject
.IUnknown_iface
, 3);
8944 ref
= IDWriteInMemoryFontFileLoader_Release(inmemory
);
8945 ok(ref
== 0, "loader not released, %u.\n", ref
);
8946 EXPECT_REF(&ownerobject
.IUnknown_iface
, 1);
8948 /* Test reference key for first added file. */
8949 hr
= IDWriteFactory5_CreateInMemoryFontFileLoader(factory
, &loader
);
8950 ok(hr
== S_OK
, "Failed to create loader, hr %#x.\n", hr
);
8954 hr
= IDWriteFactory5_RegisterFontFileLoader(factory
, (IDWriteFontFileLoader
*)inmemory
);
8955 ok(hr
== S_OK
, "Failed to register loader, hr %#x.\n", hr
);
8958 hr
= IDWriteInMemoryFontFileLoader_CreateStreamFromKey(inmemory
, &ref_key
, sizeof(ref_key
), &stream2
);
8959 ok(hr
== E_INVALIDARG
, "Unexpected hr %#x.\n", hr
);
8961 /* With owner object. */
8962 hr
= IDWriteInMemoryFontFileLoader_CreateInMemoryFontFileReference(inmemory
, (IDWriteFactory
*)factory
, data
,
8963 file_size
, &ownerobject
.IUnknown_iface
, &file
);
8964 ok(hr
== S_OK
, "Failed to create in-memory file reference, hr %#x.\n", hr
);
8967 hr
= IDWriteInMemoryFontFileLoader_CreateStreamFromKey(inmemory
, &ref_key
, sizeof(ref_key
), &stream2
);
8968 ok(hr
== S_OK
, "Failed to create a stream, hr %#x.\n", hr
);
8970 context2
= (void *)0xdeadbeef;
8971 hr
= IDWriteFontFileStream_ReadFileFragment(stream2
, &frag_start
, 0, file_size
, &context2
);
8972 ok(hr
== S_OK
, "Failed to read a fragment, hr %#x.\n", hr
);
8973 ok(context2
== NULL
, "Unexpected context %p.\n", context2
);
8974 ok(frag_start
== data
, "Unexpected fragment pointer %p.\n", frag_start
);
8976 hr
= IDWriteFontFileStream_GetFileSize(stream2
, &size
);
8977 ok(hr
== S_OK
, "Failed to get file size, hr %#x.\n", hr
);
8978 ok(size
== file_size
, "Unexpected file size.\n");
8980 IDWriteFontFileStream_ReleaseFileFragment(stream2
, context2
);
8983 hr
= IDWriteFontFileStream_GetLastWriteTime(stream2
, &writetime
);
8984 ok(hr
== E_NOTIMPL
, "Unexpected hr %#x.\n", hr
);
8985 ok(writetime
== 0, "Unexpected writetime.\n");
8987 IDWriteFontFileStream_Release(stream2
);
8989 /* Without owner object. */
8990 hr
= IDWriteInMemoryFontFileLoader_CreateInMemoryFontFileReference(inmemory
, (IDWriteFactory
*)factory
, data
,
8991 file_size
, NULL
, &file2
);
8992 ok(hr
== S_OK
, "Failed to create in-memory file reference, hr %#x.\n", hr
);
8995 hr
= IDWriteInMemoryFontFileLoader_CreateStreamFromKey(inmemory
, &ref_key
, sizeof(ref_key
), &stream2
);
8996 ok(hr
== S_OK
, "Failed to create a stream, hr %#x.\n", hr
);
8998 context2
= (void *)0xdeadbeef;
8999 hr
= IDWriteFontFileStream_ReadFileFragment(stream2
, &frag_start
, 0, file_size
, &context2
);
9000 ok(hr
== S_OK
, "Failed to read a fragment, hr %#x.\n", hr
);
9001 ok(context2
== NULL
, "Unexpected context %p.\n", context2
);
9002 ok(frag_start
!= data
, "Unexpected fragment pointer %p.\n", frag_start
);
9004 hr
= IDWriteFontFileStream_GetFileSize(stream2
, &size
);
9005 ok(hr
== S_OK
, "Failed to get file size, hr %#x.\n", hr
);
9006 ok(size
== file_size
, "Unexpected file size.\n");
9008 IDWriteFontFileStream_ReleaseFileFragment(stream2
, context2
);
9011 hr
= IDWriteFontFileStream_GetLastWriteTime(stream2
, &writetime
);
9012 ok(hr
== E_NOTIMPL
, "Unexpected hr %#x.\n", hr
);
9013 ok(writetime
== 0, "Unexpected writetime.\n");
9015 IDWriteFontFileStream_Release(stream2
);
9016 IDWriteFontFile_Release(file2
);
9018 /* Key size validation. */
9020 hr
= IDWriteInMemoryFontFileLoader_CreateStreamFromKey(inmemory
, NULL
, sizeof(ref_key
) - 1, &stream2
);
9021 ok(hr
== E_INVALIDARG
, "Unexpected hr %#x.\n", hr
);
9024 hr
= IDWriteInMemoryFontFileLoader_CreateStreamFromKey(inmemory
, &ref_key
, sizeof(ref_key
) - 1, &stream2
);
9025 ok(hr
== E_INVALIDARG
, "Unexpected hr %#x.\n", hr
);
9028 hr
= IDWriteInMemoryFontFileLoader_CreateStreamFromKey(inmemory
, &ref_key
, sizeof(ref_key
) + 1, &stream2
);
9029 ok(hr
== E_INVALIDARG
, "Unexpected hr %#x.\n", hr
);
9031 count
= IDWriteInMemoryFontFileLoader_GetFileCount(inmemory
);
9032 ok(count
== 2, "Unexpected file count %u.\n", count
);
9034 hr
= IDWriteFontFile_GetReferenceKey(file
, &key
, &key_size
);
9035 ok(hr
== S_OK
, "Failed to get reference key, hr %#x.\n", hr
);
9037 ok(key
&& *(DWORD
*)key
== 0, "Unexpected reference key.\n");
9038 ok(key_size
== 4, "Unexpected key size %u.\n", key_size
);
9040 IDWriteFontFile_Release(file
);
9042 count
= IDWriteInMemoryFontFileLoader_GetFileCount(inmemory
);
9043 ok(count
== 2, "Unexpected file count %u.\n", count
);
9045 hr
= IDWriteFactory5_UnregisterFontFileLoader(factory
, (IDWriteFontFileLoader
*)inmemory
);
9046 ok(hr
== S_OK
, "Failed to unregister loader, hr %#x.\n", hr
);
9048 IDWriteFontFileStream_ReleaseFileFragment(stream
, context
);
9049 IDWriteFontFileStream_Release(stream
);
9050 IDWriteFontFace_Release(fontface
);
9052 ref
= IDWriteInMemoryFontFileLoader_Release(inmemory
);
9053 ok(ref
== 0, "loader not released, %u.\n", ref
);
9055 ref
= IDWriteFactory5_Release(factory
);
9056 ok(ref
== 0, "factory not released, %u\n", ref
);
9059 static BOOL
face_has_table(IDWriteFontFace4
*fontface
, UINT32 tag
)
9061 BOOL exists
= FALSE
;
9067 hr
= IDWriteFontFace4_TryGetFontTable(fontface
, tag
, &data
, &size
, &context
, &exists
);
9068 ok(hr
== S_OK
, "TryGetFontTable() failed, %#x\n", hr
);
9070 IDWriteFontFace4_ReleaseFontTable(fontface
, context
);
9075 static DWORD
get_sbix_formats(IDWriteFontFace4
*fontface
)
9077 UINT32 size
, s
, num_strikes
;
9078 const sbix_header
*header
;
9079 UINT16 g
, num_glyphs
;
9080 BOOL exists
= FALSE
;
9087 hr
= IDWriteFontFace4_TryGetFontTable(fontface
, MS_MAXP_TAG
, &data
, &size
, &context
, &exists
);
9088 ok(hr
== S_OK
, "TryGetFontTable() failed, %#x\n", hr
);
9089 ok(exists
, "Expected maxp table\n");
9095 num_glyphs
= GET_BE_WORD(maxp
->numGlyphs
);
9097 hr
= IDWriteFontFace4_TryGetFontTable(fontface
, MS_SBIX_TAG
, &data
, &size
, &context
, &exists
);
9098 ok(hr
== S_OK
, "TryGetFontTable() failed, %#x\n", hr
);
9099 ok(exists
, "Expected sbix table\n");
9102 num_strikes
= GET_BE_DWORD(header
->numStrikes
);
9104 for (s
= 0; s
< num_strikes
; s
++) {
9105 sbix_strike
*strike
= (sbix_strike
*)((BYTE
*)header
+ GET_BE_DWORD(header
->strikeOffset
[s
]));
9107 for (g
= 0; g
< num_glyphs
; g
++) {
9108 DWORD offset
= GET_BE_DWORD(strike
->glyphDataOffsets
[g
]);
9109 DWORD offset_next
= GET_BE_DWORD(strike
->glyphDataOffsets
[g
+ 1]);
9110 sbix_glyph_data
*glyph_data
;
9113 if (offset
== offset_next
)
9116 glyph_data
= (sbix_glyph_data
*)((BYTE
*)strike
+ offset
);
9117 switch (format
= glyph_data
->graphicType
)
9120 ret
|= DWRITE_GLYPH_IMAGE_FORMATS_PNG
;
9123 ret
|= DWRITE_GLYPH_IMAGE_FORMATS_JPEG
;
9126 ret
|= DWRITE_GLYPH_IMAGE_FORMATS_TIFF
;
9129 ok(0, "unexpected format, %#x\n", GET_BE_DWORD(format
));
9134 IDWriteFontFace4_ReleaseFontTable(fontface
, context
);
9139 static DWORD
get_cblc_formats(IDWriteFontFace4
*fontface
)
9141 CBLCBitmapSizeTable
*sizes
;
9142 UINT32 num_sizes
, size
, s
;
9143 BOOL exists
= FALSE
;
9149 hr
= IDWriteFontFace4_TryGetFontTable(fontface
, MS_CBLC_TAG
, (const void **)&header
, &size
, &context
, &exists
);
9150 ok(hr
== S_OK
, "TryGetFontTable() failed, %#x\n", hr
);
9151 ok(exists
, "Expected CBLC table\n");
9156 num_sizes
= GET_BE_DWORD(header
->numSizes
);
9157 sizes
= (CBLCBitmapSizeTable
*)(header
+ 1);
9159 for (s
= 0; s
< num_sizes
; s
++) {
9160 BYTE bpp
= sizes
[s
].bitDepth
;
9162 if (bpp
== 1 || bpp
== 2 || bpp
== 4 || bpp
== 8)
9163 ret
|= DWRITE_GLYPH_IMAGE_FORMATS_PNG
;
9165 ret
|= DWRITE_GLYPH_IMAGE_FORMATS_PREMULTIPLIED_B8G8R8A8
;
9168 IDWriteFontFace4_ReleaseFontTable(fontface
, context
);
9173 static DWORD
get_face_glyph_image_formats(IDWriteFontFace4
*fontface
)
9175 DWORD ret
= DWRITE_GLYPH_IMAGE_FORMATS_NONE
;
9177 if (face_has_table(fontface
, MS_GLYF_TAG
))
9178 ret
|= DWRITE_GLYPH_IMAGE_FORMATS_TRUETYPE
;
9180 if (face_has_table(fontface
, MS_CFF__TAG
) ||
9181 face_has_table(fontface
, MS_CFF2_TAG
))
9182 ret
|= DWRITE_GLYPH_IMAGE_FORMATS_CFF
;
9184 if (face_has_table(fontface
, MS_COLR_TAG
))
9185 ret
|= DWRITE_GLYPH_IMAGE_FORMATS_COLR
;
9187 if (face_has_table(fontface
, MS_SVG__TAG
))
9188 ret
|= DWRITE_GLYPH_IMAGE_FORMATS_SVG
;
9190 if (face_has_table(fontface
, MS_SBIX_TAG
))
9191 ret
|= get_sbix_formats(fontface
);
9193 if (face_has_table(fontface
, MS_CBLC_TAG
))
9194 ret
|= get_cblc_formats(fontface
);
9199 static void test_GetGlyphImageFormats(void)
9201 IDWriteFontCollection
*syscollection
;
9202 IDWriteFactory
*factory
;
9206 IDWriteFontFace
*fontface
;
9207 IDWriteFontFace4
*fontface4
;
9209 factory
= create_factory();
9211 fontface
= create_fontface(factory
);
9212 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace4
, (void **)&fontface4
);
9213 IDWriteFontFace_Release(fontface
);
9215 win_skip("GetGlyphImageFormats() is not supported\n");
9216 IDWriteFactory_Release(factory
);
9219 IDWriteFontFace4_Release(fontface4
);
9221 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &syscollection
, FALSE
);
9222 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
9223 count
= IDWriteFontCollection_GetFontFamilyCount(syscollection
);
9225 for (i
= 0; i
< count
; i
++) {
9226 WCHAR familynameW
[256], facenameW
[128];
9227 IDWriteLocalizedStrings
*names
;
9228 IDWriteFontFamily
*family
;
9229 UINT32 j
, fontcount
;
9232 hr
= IDWriteFontCollection_GetFontFamily(syscollection
, i
, &family
);
9233 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
9235 hr
= IDWriteFontFamily_GetFamilyNames(family
, &names
);
9236 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
9238 get_enus_string(names
, familynameW
, ARRAY_SIZE(familynameW
));
9239 IDWriteLocalizedStrings_Release(names
);
9241 fontcount
= IDWriteFontFamily_GetFontCount(family
);
9242 for (j
= 0; j
< fontcount
; j
++) {
9243 DWORD formats
, expected_formats
;
9245 hr
= IDWriteFontFamily_GetFont(family
, j
, &font
);
9246 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
9248 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
9249 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
9251 hr
= IDWriteFont_GetFaceNames(font
, &names
);
9252 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
9254 get_enus_string(names
, facenameW
, ARRAY_SIZE(facenameW
));
9256 IDWriteLocalizedStrings_Release(names
);
9258 IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace4
, (void **)&fontface4
);
9260 /* Mask describes font as a whole. */
9261 formats
= IDWriteFontFace4_GetGlyphImageFormats(fontface4
);
9262 expected_formats
= get_face_glyph_image_formats(fontface4
);
9263 ok(formats
== expected_formats
, "%s - %s, expected formats %#x, got formats %#x.\n",
9264 wine_dbgstr_w(familynameW
), wine_dbgstr_w(facenameW
), expected_formats
, formats
);
9266 IDWriteFontFace4_Release(fontface4
);
9267 IDWriteFontFace_Release(fontface
);
9268 IDWriteFont_Release(font
);
9271 IDWriteFontFamily_Release(family
);
9274 IDWriteFontCollection_Release(syscollection
);
9275 ref
= IDWriteFactory_Release(factory
);
9276 ok(ref
== 0, "factory not released, %u\n", ref
);
9279 static void test_CreateCustomRenderingParams(void)
9281 static const struct custom_params_test
9285 FLOAT cleartype_level
;
9286 DWRITE_PIXEL_GEOMETRY geometry
;
9287 DWRITE_RENDERING_MODE rendering_mode
;
9291 { 0.0f
, 0.0f
, 0.0f
, DWRITE_PIXEL_GEOMETRY_FLAT
, DWRITE_RENDERING_MODE_NATURAL
, E_INVALIDARG
},
9292 { 0.0f
, 0.1f
, 0.0f
, DWRITE_PIXEL_GEOMETRY_FLAT
, DWRITE_RENDERING_MODE_NATURAL
, E_INVALIDARG
},
9293 { 0.0f
, 0.0f
, 0.1f
, DWRITE_PIXEL_GEOMETRY_FLAT
, DWRITE_RENDERING_MODE_NATURAL
, E_INVALIDARG
},
9294 { -0.1f
, 0.0f
, 0.0f
, DWRITE_PIXEL_GEOMETRY_FLAT
, DWRITE_RENDERING_MODE_NATURAL
, E_INVALIDARG
},
9295 { 0.1f
, -0.1f
, 0.0f
, DWRITE_PIXEL_GEOMETRY_FLAT
, DWRITE_RENDERING_MODE_NATURAL
, E_INVALIDARG
},
9296 { 0.1f
, 0.0f
, -0.1f
, DWRITE_PIXEL_GEOMETRY_FLAT
, DWRITE_RENDERING_MODE_NATURAL
, E_INVALIDARG
},
9297 { 0.1f
, 0.0f
, 0.0f
, DWRITE_PIXEL_GEOMETRY_FLAT
, DWRITE_RENDERING_MODE_NATURAL
},
9298 { 0.01f
, 0.0f
, 0.0f
, DWRITE_PIXEL_GEOMETRY_FLAT
, DWRITE_RENDERING_MODE_NATURAL
},
9299 { 0.1f
, 0.0f
, 0.0f
, DWRITE_PIXEL_GEOMETRY_BGR
+ 1, DWRITE_RENDERING_MODE_NATURAL
, E_INVALIDARG
},
9300 { 0.1f
, 0.0f
, 0.0f
, DWRITE_PIXEL_GEOMETRY_BGR
, DWRITE_RENDERING_MODE_OUTLINE
+ 1, E_INVALIDARG
},
9301 { 0.1f
, 0.0f
, 2.0f
, DWRITE_PIXEL_GEOMETRY_BGR
, DWRITE_RENDERING_MODE_NATURAL
},
9303 IDWriteFactory
*factory
;
9308 factory
= create_factory();
9310 for (i
= 0; i
< ARRAY_SIZE(params_tests
); i
++) {
9311 IDWriteRenderingParams
*params
;
9313 params
= (void *)0xdeadbeef;
9314 hr
= IDWriteFactory_CreateCustomRenderingParams(factory
, params_tests
[i
].gamma
, params_tests
[i
].contrast
,
9315 params_tests
[i
].cleartype_level
, params_tests
[i
].geometry
, params_tests
[i
].rendering_mode
, ¶ms
);
9316 ok(hr
== params_tests
[i
].hr
, "%u: unexpected hr %#x, expected %#x.\n", i
, hr
, params_tests
[i
].hr
);
9319 ok(params_tests
[i
].gamma
== IDWriteRenderingParams_GetGamma(params
), "%u: unexpected gamma %f, expected %f.\n",
9320 i
, IDWriteRenderingParams_GetGamma(params
), params_tests
[i
].gamma
);
9321 ok(params_tests
[i
].contrast
== IDWriteRenderingParams_GetEnhancedContrast(params
),
9322 "%u: unexpected contrast %f, expected %f.\n",
9323 i
, IDWriteRenderingParams_GetEnhancedContrast(params
), params_tests
[i
].contrast
);
9324 ok(params_tests
[i
].cleartype_level
== IDWriteRenderingParams_GetClearTypeLevel(params
),
9325 "%u: unexpected ClearType level %f, expected %f.\n",
9326 i
, IDWriteRenderingParams_GetClearTypeLevel(params
), params_tests
[i
].cleartype_level
);
9327 ok(params_tests
[i
].geometry
== IDWriteRenderingParams_GetPixelGeometry(params
),
9328 "%u: unexpected pixel geometry %u, expected %u.\n", i
, IDWriteRenderingParams_GetPixelGeometry(params
),
9329 params_tests
[i
].geometry
);
9330 ok(params_tests
[i
].rendering_mode
== IDWriteRenderingParams_GetRenderingMode(params
),
9331 "%u: unexpected rendering mode %u, expected %u.\n", i
, IDWriteRenderingParams_GetRenderingMode(params
),
9332 params_tests
[i
].rendering_mode
);
9333 IDWriteRenderingParams_Release(params
);
9336 ok(params
== NULL
, "%u: expected NULL interface pointer on failure.\n", i
);
9339 ref
= IDWriteFactory_Release(factory
);
9340 ok(ref
== 0, "factory not released, %u\n", ref
);
9343 static void test_localfontfileloader(void)
9345 IDWriteFontFileLoader
*loader
, *loader2
;
9346 IDWriteFactory
*factory
, *factory2
;
9347 IDWriteFontFile
*file
, *file2
;
9352 factory
= create_factory();
9353 factory2
= create_factory();
9355 path
= create_testfontfile(test_fontfile
);
9357 hr
= IDWriteFactory_CreateFontFileReference(factory
, path
, NULL
, &file
);
9358 ok(hr
== S_OK
, "Failed to create file reference, hr %#x.\n", hr
);
9360 hr
= IDWriteFactory_CreateFontFileReference(factory2
, path
, NULL
, &file2
);
9361 ok(hr
== S_OK
, "Failed to create file reference, hr %#x.\n", hr
);
9362 ok(file
!= file2
, "Unexpected file instance.\n");
9364 hr
= IDWriteFontFile_GetLoader(file
, &loader
);
9365 ok(hr
== S_OK
, "Failed to get loader, hr %#x.\n", hr
);
9367 hr
= IDWriteFontFile_GetLoader(file2
, &loader2
);
9368 ok(hr
== S_OK
, "Failed to get loader, hr %#x.\n", hr
);
9369 ok(loader
== loader2
, "Unexpected loader instance\n");
9371 IDWriteFontFile_Release(file
);
9372 IDWriteFontFile_Release(file2
);
9373 IDWriteFontFileLoader_Release(loader
);
9374 IDWriteFontFileLoader_Release(loader2
);
9375 ref
= IDWriteFactory_Release(factory
);
9376 ok(ref
== 0, "factory not released, %u\n", ref
);
9377 ref
= IDWriteFactory_Release(factory2
);
9378 ok(ref
== 0, "factory not released, %u\n", ref
);
9379 DELETE_FONTFILE(path
);
9382 static void test_AnalyzeContainerType(void)
9384 struct WOFFHeader2 woff2_header
;
9385 struct WOFFHeader woff_header
;
9386 DWRITE_CONTAINER_TYPE type
;
9387 IDWriteFactory5
*factory
;
9389 factory
= create_factory_iid(&IID_IDWriteFactory5
);
9391 win_skip("AnalyzeContainerType() is not supported.\n");
9395 type
= IDWriteFactory5_AnalyzeContainerType(factory
, NULL
, 0);
9396 ok(type
== DWRITE_CONTAINER_TYPE_UNKNOWN
, "Unexpected container type %u.\n", type
);
9398 type
= IDWriteFactory5_AnalyzeContainerType(factory
, (void const *)0xdeadbeef, 0);
9399 ok(type
== DWRITE_CONTAINER_TYPE_UNKNOWN
, "Unexpected container type %u.\n", type
);
9401 memset(&woff_header
, 0xff, sizeof(woff_header
));
9402 woff_header
.signature
= GET_LE_DWORD(MS_WOFF_TAG
);
9403 woff_header
.length
= 0;
9404 type
= IDWriteFactory5_AnalyzeContainerType(factory
, &woff_header
, sizeof(woff_header
));
9405 ok(type
== DWRITE_CONTAINER_TYPE_WOFF
, "Unexpected container type %u.\n", type
);
9407 memset(&woff_header
, 0xff, sizeof(woff_header
));
9408 woff_header
.signature
= GET_LE_DWORD(MS_WOFF_TAG
);
9409 type
= IDWriteFactory5_AnalyzeContainerType(factory
, &woff_header
, sizeof(woff_header
.signature
));
9410 ok(type
== DWRITE_CONTAINER_TYPE_WOFF
, "Unexpected container type %u.\n", type
);
9412 memset(&woff_header
, 0xff, sizeof(woff_header
));
9413 woff_header
.signature
= GET_LE_DWORD(MS_WOFF_TAG
);
9414 type
= IDWriteFactory5_AnalyzeContainerType(factory
, &woff_header
, sizeof(woff_header
.signature
) - 1);
9415 ok(type
== DWRITE_CONTAINER_TYPE_UNKNOWN
, "Unexpected container type %u.\n", type
);
9417 memset(&woff2_header
, 0xff, sizeof(woff2_header
));
9418 woff2_header
.signature
= GET_LE_DWORD(MS_WOF2_TAG
);
9419 type
= IDWriteFactory5_AnalyzeContainerType(factory
, &woff2_header
, sizeof(woff2_header
));
9420 ok(type
== DWRITE_CONTAINER_TYPE_WOFF2
, "Unexpected container type %u.\n", type
);
9422 memset(&woff2_header
, 0xff, sizeof(woff2_header
));
9423 woff2_header
.signature
= GET_LE_DWORD(MS_WOF2_TAG
);
9424 type
= IDWriteFactory5_AnalyzeContainerType(factory
, &woff2_header
, sizeof(woff2_header
.signature
));
9425 ok(type
== DWRITE_CONTAINER_TYPE_WOFF2
, "Unexpected container type %u.\n", type
);
9427 memset(&woff2_header
, 0xff, sizeof(woff2_header
));
9428 woff2_header
.signature
= GET_LE_DWORD(MS_WOF2_TAG
);
9429 type
= IDWriteFactory5_AnalyzeContainerType(factory
, &woff2_header
, sizeof(woff2_header
.signature
) - 1);
9430 ok(type
== DWRITE_CONTAINER_TYPE_UNKNOWN
, "Unexpected container type %u.\n", type
);
9432 IDWriteFactory5_Release(factory
);
9435 static void test_fontsetbuilder(void)
9437 IDWriteFontFaceReference
*ref
, *ref2
, *ref3
;
9438 IDWriteFontCollection1
*collection
;
9439 IDWriteFontFaceReference1
*ref1
;
9440 IDWriteFontSetBuilder1
*builder1
;
9441 IDWriteFontSetBuilder
*builder
;
9442 DWRITE_FONT_AXIS_VALUE axis_values
[4];
9443 IDWriteFactory3
*factory
;
9444 UINT32 count
, i
, refcount
;
9445 IDWriteFontSet
*fontset
;
9446 IDWriteFontFile
*file
;
9450 factory
= create_factory_iid(&IID_IDWriteFactory3
);
9453 win_skip("IDWriteFontSetBuilder is not supported.\n");
9457 EXPECT_REF(factory
, 1);
9458 hr
= IDWriteFactory3_CreateFontSetBuilder(factory
, &builder
);
9459 ok(hr
== S_OK
, "Failed to create font set builder, hr %#x.\n", hr
);
9460 EXPECT_REF(factory
, 2);
9462 if (SUCCEEDED(hr
= IDWriteFontSetBuilder_QueryInterface(builder
, &IID_IDWriteFontSetBuilder1
, (void **)&builder1
)))
9464 path
= create_testfontfile(test_fontfile
);
9466 hr
= IDWriteFactory3_CreateFontFileReference(factory
, path
, NULL
, &file
);
9467 ok(hr
== S_OK
, "Unexpected hr %#x.\n",hr
);
9469 hr
= IDWriteFontSetBuilder1_AddFontFile(builder1
, file
);
9470 ok(hr
== S_OK
, "Unexpected hr %#x.\n",hr
);
9472 hr
= IDWriteFontSetBuilder1_CreateFontSet(builder1
, &fontset
);
9473 ok(hr
== S_OK
, "Unexpected hr %#x.\n",hr
);
9474 hr
= IDWriteFactory3_CreateFontCollectionFromFontSet(factory
, fontset
, &collection
);
9476 ok(hr
== S_OK
, "Unexpected hr %#x.\n",hr
);
9479 count
= IDWriteFontCollection1_GetFontFamilyCount(collection
);
9480 ok(count
== 1, "Unexpected family count %u.\n", count
);
9481 IDWriteFontCollection1_Release(collection
);
9483 IDWriteFontSet_Release(fontset
);
9485 hr
= IDWriteFontSetBuilder1_AddFontFile(builder1
, file
);
9486 ok(hr
== S_OK
, "Unexpected hr %#x.\n",hr
);
9488 hr
= IDWriteFontSetBuilder1_CreateFontSet(builder1
, &fontset
);
9489 ok(hr
== S_OK
, "Unexpected hr %#x.\n",hr
);
9491 hr
= IDWriteFactory3_CreateFontCollectionFromFontSet(factory
, fontset
, &collection
);
9493 ok(hr
== S_OK
, "Unexpected hr %#x.\n",hr
);
9496 check_familymodel(collection
, DWRITE_FONT_FAMILY_MODEL_WEIGHT_STRETCH_STYLE
);
9497 count
= IDWriteFontCollection1_GetFontFamilyCount(collection
);
9498 ok(count
== 1, "Unexpected family count %u.\n", count
);
9499 IDWriteFontCollection1_Release(collection
);
9502 /* No attempt to eliminate duplicates. */
9503 count
= IDWriteFontSet_GetFontCount(fontset
);
9504 ok(count
== 2, "Unexpected font count %u.\n", count
);
9506 hr
= IDWriteFontSet_GetFontFaceReference(fontset
, 0, &ref
);
9507 ok(hr
== S_OK
, "Unexpected hr %#x.\n",hr
);
9509 hr
= IDWriteFontFaceReference_QueryInterface(ref
, &IID_IDWriteFontFaceReference1
, (void **)&ref1
);
9510 ok(hr
== S_OK
, "Unexpected hr %#x.\n",hr
);
9512 count
= IDWriteFontFaceReference1_GetFontAxisValueCount(ref1
);
9514 ok(count
== 4, "Unexpected axis count %u.\n", count
);
9518 hr
= IDWriteFontFaceReference1_GetFontAxisValues(ref1
, axis_values
, ARRAY_SIZE(axis_values
));
9519 ok(hr
== S_OK
, "Unexpected hr %#x.\n",hr
);
9521 ok(axis_values
[0].axisTag
== DWRITE_FONT_AXIS_TAG_WEIGHT
, "Unexpected tag[0] %s.\n",
9522 wine_dbgstr_an((char *)&axis_values
[0].axisTag
, 4));
9523 ok(axis_values
[0].value
== 500.0f
, "Unexpected value[0] %f.\n", axis_values
[0].value
);
9524 ok(axis_values
[1].axisTag
== DWRITE_FONT_AXIS_TAG_WIDTH
, "Unexpected tag[1] %s.\n",
9525 wine_dbgstr_an((char *)&axis_values
[1].axisTag
, 4));
9526 ok(axis_values
[1].value
== 100.0f
, "Unexpected value[1] %f.\n", axis_values
[1].value
);
9527 ok(axis_values
[2].axisTag
== DWRITE_FONT_AXIS_TAG_ITALIC
, "Unexpected tag[2] %s.\n",
9528 wine_dbgstr_an((char *)&axis_values
[2].axisTag
, 4));
9529 ok(axis_values
[2].value
== 0.0f
, "Unexpected value[2] %f.\n", axis_values
[2].value
);
9530 ok(axis_values
[3].axisTag
== DWRITE_FONT_AXIS_TAG_SLANT
, "Unexpected tag[3] %s.\n",
9531 wine_dbgstr_an((char *)&axis_values
[3].axisTag
, 4));
9532 ok(axis_values
[3].value
== 0.0f
, "Unexpected value[3] %f.\n", axis_values
[3].value
);
9535 IDWriteFontFaceReference1_Release(ref1
);
9537 IDWriteFontFaceReference_Release(ref
);
9539 IDWriteFontSet_Release(fontset
);
9541 IDWriteFontFile_Release(file
);
9542 IDWriteFontSetBuilder1_Release(builder1
);
9545 win_skip("IDWriteFontSetBuilder1 is not available.\n");
9546 IDWriteFontSetBuilder_Release(builder
);
9548 hr
= IDWriteFactory3_GetSystemFontCollection(factory
, FALSE
, &collection
, FALSE
);
9549 ok(hr
== S_OK
, "Failed to get system collection, hr %#x.\n", hr
);
9550 count
= IDWriteFontCollection1_GetFontFamilyCount(collection
);
9552 for (i
= 0; i
< count
; i
++) {
9553 IDWriteFontFamily1
*family
;
9554 UINT32 j
, fontcount
;
9557 hr
= IDWriteFontCollection1_GetFontFamily(collection
, i
, &family
);
9558 ok(hr
== S_OK
, "Failed to get family, hr %#x.\n", hr
);
9560 fontcount
= IDWriteFontFamily1_GetFontCount(family
);
9561 for (j
= 0; j
< fontcount
; ++j
)
9563 IDWriteFontSet
*fontset
;
9564 UINT32 setcount
, id
;
9566 hr
= IDWriteFontFamily1_GetFont(family
, j
, &font
);
9567 ok(hr
== S_OK
, "Failed to get font, hr %#x.\n", hr
);
9569 /* Create a set with a single font reference, test set properties. */
9570 hr
= IDWriteFactory3_CreateFontSetBuilder(factory
, &builder
);
9571 ok(hr
== S_OK
, "Failed to create font set builder, hr %#x.\n", hr
);
9573 hr
= IDWriteFont3_GetFontFaceReference(font
, &ref
);
9574 ok(hr
== S_OK
, "Failed to get fontface reference, hr %#x.\n", hr
);
9577 hr
= IDWriteFontSetBuilder_AddFontFaceReference(builder
, ref
);
9578 ok(hr
== S_OK
, "Failed to add fontface reference, hr %#x.\n", hr
);
9581 hr
= IDWriteFontSetBuilder_CreateFontSet(builder
, &fontset
);
9582 ok(hr
== S_OK
, "Failed to create a font set, hr %#x.\n", hr
);
9584 setcount
= IDWriteFontSet_GetFontCount(fontset
);
9585 ok(setcount
== 1, "Unexpected font count %u.\n", setcount
);
9587 ref2
= (void *)0xdeadbeef;
9588 hr
= IDWriteFontSet_GetFontFaceReference(fontset
, setcount
, &ref2
);
9589 ok(hr
== E_INVALIDARG
, "Unexpected hr %#x.\n", hr
);
9590 ok(!ref2
, "Unexpected pointer.\n");
9593 hr
= IDWriteFontSet_GetFontFaceReference(fontset
, 0, &ref2
);
9594 ok(hr
== S_OK
, "Failed to get font face reference, hr %#x.\n", hr
);
9595 ok(ref2
!= ref
, "Unexpected reference.\n");
9598 hr
= IDWriteFontSet_GetFontFaceReference(fontset
, 0, &ref3
);
9599 ok(hr
== S_OK
, "Failed to get font face reference, hr %#x.\n", hr
);
9600 ok(ref2
!= ref3
, "Unexpected reference.\n");
9602 IDWriteFontFaceReference_Release(ref3
);
9603 IDWriteFontFaceReference_Release(ref2
);
9605 for (id
= DWRITE_FONT_PROPERTY_ID_FAMILY_NAME
; id
< DWRITE_FONT_PROPERTY_ID_TOTAL
; ++id
)
9607 IDWriteLocalizedStrings
*values
;
9608 WCHAR buffW
[255], buff2W
[255];
9609 UINT32 c
, ivalue
= 0;
9610 BOOL exists
= FALSE
;
9612 hr
= IDWriteFontSet_GetPropertyValues(fontset
, 0, id
, &exists
, &values
);
9613 ok(hr
== S_OK
, "Failed to get property value, hr %#x.\n", hr
);
9615 if (id
== DWRITE_FONT_PROPERTY_ID_WEIGHT
|| id
== DWRITE_FONT_PROPERTY_ID_STRETCH
9616 || id
== DWRITE_FONT_PROPERTY_ID_STYLE
)
9619 ok(exists
, "Property %u expected to exist.\n", id
);
9627 case DWRITE_FONT_PROPERTY_ID_WEIGHT
:
9628 ivalue
= IDWriteFont3_GetWeight(font
);
9630 case DWRITE_FONT_PROPERTY_ID_STRETCH
:
9631 ivalue
= IDWriteFont3_GetStretch(font
);
9633 case DWRITE_FONT_PROPERTY_ID_STYLE
:
9634 ivalue
= IDWriteFont3_GetStyle(font
);
9642 case DWRITE_FONT_PROPERTY_ID_WEIGHT
:
9643 case DWRITE_FONT_PROPERTY_ID_STRETCH
:
9644 case DWRITE_FONT_PROPERTY_ID_STYLE
:
9645 c
= IDWriteLocalizedStrings_GetCount(values
);
9646 ok(c
== 1, "Unexpected string count %u.\n", c
);
9649 hr
= IDWriteLocalizedStrings_GetLocaleName(values
, 0, buffW
, ARRAY_SIZE(buffW
));
9650 ok(hr
== S_OK
, "Failed to get locale name, hr %#x.\n", hr
);
9651 ok(!*buffW
, "Unexpected locale %s.\n", wine_dbgstr_w(buffW
));
9654 hr
= IDWriteLocalizedStrings_GetString(values
, 0, buff2W
, ARRAY_SIZE(buff2W
));
9655 ok(hr
== S_OK
, "Failed to get property string, hr %#x.\n", hr
);
9657 wsprintfW(buffW
, L
"%u", ivalue
);
9658 ok(!lstrcmpW(buffW
, buff2W
), "Unexpected property value %s, expected %s.\n", wine_dbgstr_w(buff2W
),
9659 wine_dbgstr_w(buffW
));
9665 IDWriteLocalizedStrings_Release(values
);
9668 IDWriteFontSet_Release(fontset
);
9669 IDWriteFontFaceReference_Release(ref
);
9670 IDWriteFontSetBuilder_Release(builder
);
9672 IDWriteFont3_Release(font
);
9675 IDWriteFontFamily1_Release(family
);
9678 IDWriteFontCollection1_Release(collection
);
9680 refcount
= IDWriteFactory3_Release(factory
);
9681 ok(!refcount
, "Factory not released, %u.\n", refcount
);
9684 static void test_font_resource(void)
9686 IDWriteFontFaceReference1
*reference
, *reference2
;
9687 IDWriteFontResource
*resource
, *resource2
;
9688 IDWriteFontFile
*fontfile
, *fontfile2
;
9689 DWRITE_FONT_AXIS_VALUE axis_values
[2];
9690 IDWriteFontFace5
*fontface5
;
9691 IDWriteFontFace
*fontface
;
9692 IDWriteFactory6
*factory
;
9693 UINT32 count
, index
;
9698 if (!(factory
= create_factory_iid(&IID_IDWriteFactory6
)))
9700 win_skip("IDWriteFactory6 is not supported.\n");
9704 fontface
= create_fontface((IDWriteFactory
*)factory
);
9707 hr
= IDWriteFontFace_GetFiles(fontface
, &count
, &fontfile
);
9708 ok(hr
== S_OK
, "Failed to get file object, hr %#x.\n", hr
);
9710 hr
= IDWriteFactory6_CreateFontResource(factory
, fontfile
, 0, &resource
);
9711 ok(hr
== S_OK
, "Failed to create font resource, hr %#x.\n", hr
);
9713 hr
= IDWriteFactory6_CreateFontResource(factory
, fontfile
, 0, &resource2
);
9714 ok(hr
== S_OK
, "Failed to create font resource, hr %#x.\n", hr
);
9715 ok(resource
!= resource2
, "Unexpected instance.\n");
9716 IDWriteFontResource_Release(resource2
);
9718 hr
= IDWriteFontResource_GetFontFile(resource
, &fontfile2
);
9719 ok(hr
== S_OK
, "Failed to get font file, hr %#x.\n", hr
);
9720 ok(fontfile2
== fontfile
, "Unexpected file instance.\n");
9721 IDWriteFontFile_Release(fontfile2
);
9723 index
= IDWriteFontResource_GetFontFaceIndex(resource
);
9724 ok(!index
, "Unexpected index %u.\n", index
);
9726 /* Specify axis value, font has no variations. */
9727 axis_values
[0].axisTag
= DWRITE_FONT_AXIS_TAG_WEIGHT
;
9728 axis_values
[0].value
= 400.0f
;
9729 hr
= IDWriteFontResource_CreateFontFaceReference(resource
, DWRITE_FONT_SIMULATIONS_NONE
, axis_values
, 1, &reference
);
9730 ok(hr
== S_OK
, "Failed to create reference object, hr %#x.\n", hr
);
9732 count
= IDWriteFontFaceReference1_GetFontAxisValueCount(reference
);
9733 ok(count
== 1, "Unexpected axis value count.\n");
9735 IDWriteFontFaceReference1_Release(reference
);
9737 hr
= IDWriteFactory6_CreateFontFaceReference(factory
, fontfile
, 0, DWRITE_FONT_SIMULATIONS_NONE
, axis_values
, 1,
9739 count
= IDWriteFontFaceReference1_GetFontAxisValueCount(reference
);
9740 ok(count
== 1, "Unexpected axis value count.\n");
9741 IDWriteFontFaceReference1_Release(reference
);
9743 EXPECT_REF(resource
, 1);
9744 hr
= IDWriteFontResource_CreateFontFaceReference(resource
, DWRITE_FONT_SIMULATIONS_NONE
, NULL
, 0, &reference
);
9745 ok(hr
== S_OK
, "Failed to create reference object, hr %#x.\n", hr
);
9746 EXPECT_REF(resource
, 1);
9748 hr
= IDWriteFontResource_CreateFontFaceReference(resource
, DWRITE_FONT_SIMULATIONS_NONE
, NULL
, 0, &reference2
);
9749 ok(hr
== S_OK
, "Failed to create reference object, hr %#x.\n", hr
);
9750 ok(reference
!= reference2
, "Unexpected reference instance.\n");
9751 IDWriteFontFaceReference1_Release(reference2
);
9752 IDWriteFontFaceReference1_Release(reference
);
9754 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace5
, (void **)&fontface5
);
9755 ok(hr
== S_OK
, "Failed to get interface, hr %#x.\n", hr
);
9757 hr
= IDWriteFontFace5_GetFontResource(fontface5
, &resource2
);
9758 ok(hr
== S_OK
, "Failed to get font resource, hr %#x.\n", hr
);
9759 ok(resource
!= resource2
, "Unexpected resource instance.\n");
9760 IDWriteFontResource_Release(resource
);
9762 hr
= IDWriteFontFace5_GetFontResource(fontface5
, &resource
);
9763 ok(hr
== S_OK
, "Failed to get font resource, hr %#x.\n", hr
);
9764 ok(resource
!= resource2
, "Unexpected resource instance.\n");
9765 EXPECT_REF(resource
, 1);
9766 IDWriteFontResource_Release(resource
);
9767 IDWriteFontResource_Release(resource2
);
9769 IDWriteFontFace5_Release(fontface5
);
9771 /* Reference equality regarding set axis values. */
9772 axis_values
[0].axisTag
= DWRITE_FONT_AXIS_TAG_WEIGHT
;
9773 axis_values
[0].value
= 400.0f
;
9774 axis_values
[1].axisTag
= DWRITE_FONT_AXIS_TAG_ITALIC
;
9775 axis_values
[1].value
= 1.0f
;
9776 hr
= IDWriteFactory6_CreateFontFaceReference(factory
, fontfile
, 0, DWRITE_FONT_SIMULATIONS_NONE
, axis_values
, 2,
9778 count
= IDWriteFontFaceReference1_GetFontAxisValueCount(reference
);
9779 ok(count
== 2, "Unexpected axis value count.\n");
9781 hr
= IDWriteFactory6_CreateFontFaceReference(factory
, fontfile
, 0, DWRITE_FONT_SIMULATIONS_NONE
, NULL
, 0,
9783 count
= IDWriteFontFaceReference1_GetFontAxisValueCount(reference2
);
9784 ok(!count
, "Unexpected axis value count.\n");
9786 ret
= IDWriteFontFaceReference1_Equals(reference
, (IDWriteFontFaceReference
*)reference2
);
9787 ok(!ret
, "Unexpected result.\n");
9788 IDWriteFontFaceReference1_Release(reference2
);
9790 /* Different values order. */
9791 axis_values
[0].axisTag
= DWRITE_FONT_AXIS_TAG_ITALIC
;
9792 axis_values
[0].value
= 1.0f
;
9793 axis_values
[1].axisTag
= DWRITE_FONT_AXIS_TAG_WEIGHT
;
9794 axis_values
[1].value
= 400.0f
;
9795 hr
= IDWriteFactory6_CreateFontFaceReference(factory
, fontfile
, 0, DWRITE_FONT_SIMULATIONS_NONE
, axis_values
, 2,
9797 count
= IDWriteFontFaceReference1_GetFontAxisValueCount(reference2
);
9798 ok(count
== 2, "Unexpected axis value count.\n");
9800 ret
= IDWriteFontFaceReference1_Equals(reference
, (IDWriteFontFaceReference
*)reference2
);
9801 ok(!ret
, "Unexpected result.\n");
9802 IDWriteFontFaceReference1_Release(reference2
);
9804 /* Different axis values. */
9805 axis_values
[0].axisTag
= DWRITE_FONT_AXIS_TAG_ITALIC
;
9806 axis_values
[0].value
= 1.0f
;
9807 axis_values
[1].axisTag
= DWRITE_FONT_AXIS_TAG_WEIGHT
;
9808 axis_values
[1].value
= 401.0f
;
9809 hr
= IDWriteFactory6_CreateFontFaceReference(factory
, fontfile
, 0, DWRITE_FONT_SIMULATIONS_NONE
, axis_values
, 2,
9811 count
= IDWriteFontFaceReference1_GetFontAxisValueCount(reference2
);
9812 ok(count
== 2, "Unexpected axis value count.\n");
9814 ret
= IDWriteFontFaceReference1_Equals(reference
, (IDWriteFontFaceReference
*)reference2
);
9815 ok(!ret
, "Unexpected result.\n");
9816 IDWriteFontFaceReference1_Release(reference2
);
9818 memset(axis_values
, 0, sizeof(axis_values
));
9819 hr
= IDWriteFontFaceReference1_GetFontAxisValues(reference
, axis_values
, 1);
9820 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "Unexpected hr %#x.\n", hr
);
9821 ok(!axis_values
[0].axisTag
, "Unexpected axis tag.\n");
9823 memset(axis_values
, 0, sizeof(axis_values
));
9824 hr
= IDWriteFontFaceReference1_GetFontAxisValues(reference
, axis_values
, 2);
9825 ok(hr
== S_OK
, "Failed to get axis values, hr %#x.\n", hr
);
9826 ok(axis_values
[0].axisTag
== DWRITE_FONT_AXIS_TAG_WEIGHT
, "Unexpected axis tag.\n");
9828 hr
= IDWriteFontFaceReference1_CreateFontFace(reference
, &fontface5
);
9829 ok(hr
== S_OK
, "Failed to create a font face, hr %#x.\n", hr
);
9830 IDWriteFontFace5_Release(fontface5
);
9832 IDWriteFontFaceReference1_Release(reference
);
9834 IDWriteFontFile_Release(fontfile
);
9836 IDWriteFontFace_Release(fontface
);
9837 ref
= IDWriteFactory6_Release(factory
);
9838 ok(ref
== 0, "Factory wasn't released, %u.\n", ref
);
9841 static BOOL
get_expected_is_color(IDWriteFontFace2
*fontface
)
9849 hr
= IDWriteFontFace2_TryGetFontTable(fontface
, MS_CPAL_TAG
, (const void **)&data
, &size
, &context
, &exists
);
9850 ok(hr
== S_OK
, "Unexpected hr %#x.\n", hr
);
9852 IDWriteFontFace2_ReleaseFontTable(fontface
, context
);
9856 hr
= IDWriteFontFace2_TryGetFontTable(fontface
, MS_COLR_TAG
, (const void **)&data
, &size
, &context
, &exists
);
9857 ok(hr
== S_OK
, "Unexpected hr %#x.\n", hr
);
9859 IDWriteFontFace2_ReleaseFontTable(fontface
, context
);
9865 static void test_IsColorFont(void)
9867 IDWriteFontCollection
*collection
;
9868 IDWriteFactory2
*factory
;
9873 factory
= create_factory_iid(&IID_IDWriteFactory2
);
9877 win_skip("IsColorFont() is not supported.\n");
9881 hr
= IDWriteFactory2_GetSystemFontCollection(factory
, &collection
, FALSE
);
9882 ok(hr
== S_OK
, "Failed to get font collection, hr %#x.\n", hr
);
9884 count
= IDWriteFontCollection_GetFontFamilyCount(collection
);
9885 for (i
= 0; i
< count
; ++i
)
9887 IDWriteLocalizedStrings
*names
;
9888 IDWriteFontFamily
*family
;
9889 UINT32 font_count
, j
;
9892 hr
= IDWriteFontCollection_GetFontFamily(collection
, i
, &family
);
9893 ok(hr
== S_OK
, "Failed to get family, hr %#x.\n", hr
);
9895 hr
= IDWriteFontFamily_GetFamilyNames(family
, &names
);
9896 ok(hr
== S_OK
, "Failed to get names, hr %#x.\n", hr
);
9897 get_enus_string(names
, nameW
, ARRAY_SIZE(nameW
));
9898 IDWriteLocalizedStrings_Release(names
);
9900 font_count
= IDWriteFontFamily_GetFontCount(family
);
9902 for (j
= 0; j
< font_count
; ++j
)
9904 BOOL is_color_font
, is_color_face
, is_color_expected
;
9905 IDWriteFontFace2
*fontface2
;
9906 IDWriteFontFace
*fontface
;
9907 IDWriteFont2
*font2
;
9910 hr
= IDWriteFontFamily_GetFont(family
, j
, &font
);
9911 ok(hr
== S_OK
, "Failed to get font, hr %#x.\n", hr
);
9913 hr
= IDWriteFont_QueryInterface(font
, &IID_IDWriteFont2
, (void **)&font2
);
9914 ok(hr
== S_OK
, "Failed to get interface, hr %#x.\n", hr
);
9915 IDWriteFont_Release(font
);
9917 hr
= IDWriteFont2_CreateFontFace(font2
, &fontface
);
9918 ok(hr
== S_OK
, "Failed to create fontface, hr %#x.\n", hr
);
9920 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace2
, (void **)&fontface2
);
9921 ok(hr
== S_OK
, "Failed to get interface, hr %#x.\n", hr
);
9922 IDWriteFontFace_Release(fontface
);
9924 is_color_font
= IDWriteFont2_IsColorFont(font2
);
9925 is_color_face
= IDWriteFontFace2_IsColorFont(fontface2
);
9926 ok(is_color_font
== is_color_face
, "Unexpected color flag.\n");
9928 is_color_expected
= get_expected_is_color(fontface2
);
9929 ok(is_color_expected
== is_color_face
, "Unexpected is_color flag %d for %s, font %d.\n",
9930 is_color_face
, wine_dbgstr_w(nameW
), j
);
9932 IDWriteFontFace2_Release(fontface2
);
9933 IDWriteFont2_Release(font2
);
9936 IDWriteFontFamily_Release(family
);
9939 IDWriteFontCollection_Release(collection
);
9940 refcount
= IDWriteFactory2_Release(factory
);
9941 ok(refcount
== 0, "Factory not released, refcount %u.\n", refcount
);
9944 static void test_GetVerticalGlyphVariants(void)
9946 UINT16 glyphs
[1], glyph_variants
[1];
9947 IDWriteFontFace1
*fontface1
;
9948 IDWriteFontFace
*fontface
;
9949 IDWriteFactory
*factory
;
9955 factory
= create_factory();
9957 fontface
= create_fontface(factory
);
9958 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void **)&fontface1
);
9959 IDWriteFontFace_Release(fontface
);
9962 win_skip("GetVerticalGlyphVariants() is not supported.\n");
9963 IDWriteFactory_Release(factory
);
9969 hr
= IDWriteFontFace1_GetGlyphIndices(fontface1
, &ch
, 1, glyphs
);
9970 ok(hr
== S_OK
, "Failed to get glyph, hr %#x.\n", hr
);
9971 ok(!!*glyphs
, "Unexpected glyph %u.\n", glyphs
[0]);
9973 memset(glyph_variants
, 0, sizeof(glyph_variants
));
9974 hr
= IDWriteFontFace1_GetVerticalGlyphVariants(fontface1
, 1, glyphs
, glyph_variants
);
9975 ok(hr
== S_OK
, "Unexpected hr %#x.\n", hr
);
9976 ok(glyphs
[0] == glyph_variants
[0], "Unexpected glyph.\n");
9978 ret
= IDWriteFontFace1_HasVerticalGlyphVariants(fontface1
);
9979 ok(!ret
, "Unexpected flag.\n");
9981 IDWriteFontFace1_Release(fontface1
);
9982 refcount
= IDWriteFactory_Release(factory
);
9983 ok(!refcount
, "Factory not released, refcount %u.\n", refcount
);
9986 static HANDLE
get_collection_expiration_event(IDWriteFontCollection
*collection
)
9988 IDWriteFontCollection3
*collection3
;
9992 hr
= IDWriteFontCollection_QueryInterface(collection
, &IID_IDWriteFontCollection3
, (void **)&collection3
);
9993 ok(hr
== S_OK
, "Unexpected hr %#x.\n", hr
);
9994 event
= IDWriteFontCollection3_GetExpirationEvent(collection3
);
9995 IDWriteFontCollection3_Release(collection3
);
10000 static void test_expiration_event(void)
10002 IDWriteFontCollection
*collection
, *collection2
;
10003 IDWriteFontCollection3
*collection3
;
10004 IDWriteFactory
*factory
, *factory2
;
10005 unsigned int refcount
;
10006 HANDLE event
, event2
;
10009 factory
= create_factory();
10011 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &collection
, FALSE
);
10012 ok(hr
== S_OK
, "Unexpected hr %#x.\n", hr
);
10014 hr
= IDWriteFontCollection_QueryInterface(collection
, &IID_IDWriteFontCollection3
, (void **)&collection3
);
10017 win_skip("Expiration events are not supported.\n");
10018 IDWriteFontCollection_Release(collection
);
10019 IDWriteFactory_Release(factory
);
10022 IDWriteFontCollection3_Release(collection3
);
10024 event
= get_collection_expiration_event(collection
);
10026 ok(!!event
, "Unexpected event handle.\n");
10028 /* Compare handles with another isolated factory. */
10029 factory2
= create_factory();
10031 hr
= IDWriteFactory_GetSystemFontCollection(factory2
, &collection2
, FALSE
);
10032 ok(hr
== S_OK
, "Unexpected hr %#x.\n", hr
);
10033 event2
= get_collection_expiration_event(collection2
);
10035 ok(!!event2
, "Unexpected event handle.\n");
10036 ok(event
!= event2
, "Unexpected event handle.\n");
10038 IDWriteFontCollection_Release(collection2
);
10040 IDWriteFontCollection_Release(collection
);
10042 refcount
= IDWriteFactory_Release(factory2
);
10043 ok(!refcount
, "Unexpected factory refcount %u.\n", refcount
);
10044 refcount
= IDWriteFactory_Release(factory
);
10045 ok(!refcount
, "Unexpected factory refcount %u.\n", refcount
);
10048 static void test_family_font_set(void)
10050 IDWriteFontCollection
*collection
;
10051 IDWriteFontFamily2
*family2
;
10052 IDWriteFontFamily
*family
;
10053 IDWriteFactory
*factory
;
10054 unsigned int count
, refcount
;
10055 IDWriteFontSet1
*fontset
, *fontset2
;
10056 IDWriteLocalizedStrings
*values
;
10057 IDWriteFontResource
*resource
;
10062 factory
= create_factory();
10064 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &collection
, FALSE
);
10065 ok(hr
== S_OK
, "Unexpected hr %#x.\n", hr
);
10067 hr
= IDWriteFontCollection_GetFontFamily(collection
, 0, &family
);
10068 ok(hr
== S_OK
, "Unexpected hr %#x.\n", hr
);
10070 if (SUCCEEDED(IDWriteFontFamily_QueryInterface(family
, &IID_IDWriteFontFamily2
, (void **)&family2
)))
10072 hr
= IDWriteFontFamily2_GetFontSet(family2
, &fontset
);
10073 ok(hr
== S_OK
, "Unexpected hr %#x.\n", hr
);
10074 hr
= IDWriteFontFamily2_GetFontSet(family2
, &fontset2
);
10075 ok(hr
== S_OK
, "Unexpected hr %#x.\n", hr
);
10076 ok(fontset
!= fontset2
, "Unexpected fontset instance.\n");
10078 count
= IDWriteFontSet1_GetFontCount(fontset
);
10080 /* Invalid property id. */
10082 values
= (void *)0xdeadbeef;
10083 hr
= IDWriteFontSet1_GetPropertyValues(fontset
, 0, 100, &exists
, &values
);
10084 ok(FAILED(hr
), "Unexpected hr %#x.\n", hr
);
10085 ok(!exists
&& !values
, "Unexpected return value.\n");
10087 /* Invalid index. */
10089 values
= (void *)0xdeadbeef;
10090 hr
= IDWriteFontSet1_GetPropertyValues(fontset
, count
, DWRITE_FONT_PROPERTY_ID_POSTSCRIPT_NAME
, &exists
, &values
);
10091 ok(FAILED(hr
), "Unexpected hr %#x.\n", hr
);
10092 ok(!exists
&& !values
, "Unexpected return value.\n");
10095 values
= (void *)0xdeadbeef;
10096 hr
= IDWriteFontSet1_GetPropertyValues(fontset
, count
, 100, &exists
, &values
);
10097 ok(FAILED(hr
), "Unexpected hr %#x.\n", hr
);
10098 ok(!exists
&& !values
, "Unexpected return value.\n");
10100 hr
= IDWriteFontSet1_GetPropertyValues(fontset
, 0, DWRITE_FONT_PROPERTY_ID_POSTSCRIPT_NAME
, &exists
, &values
);
10101 ok(hr
== S_OK
, "Unexpected hr %#x.\n", hr
);
10102 ok(exists
== !!values
, "Unexpected return value.\n");
10105 hr
= IDWriteLocalizedStrings_GetString(values
, 0, buffW
, ARRAY_SIZE(buffW
));
10106 ok(hr
== S_OK
, "Unexpected hr %#x.\n", hr
);
10107 IDWriteLocalizedStrings_Release(values
);
10110 hr
= IDWriteFontSet1_CreateFontResource(fontset
, 100, &resource
);
10111 ok(hr
== E_INVALIDARG
, "Unexpected hr %#x.\n", hr
);
10113 hr
= IDWriteFontSet1_CreateFontResource(fontset
, 0, &resource
);
10114 ok(hr
== S_OK
, "Unexpected hr %#x.\n", hr
);
10115 IDWriteFontResource_Release(resource
);
10117 IDWriteFontSet1_Release(fontset2
);
10118 IDWriteFontSet1_Release(fontset
);
10120 IDWriteFontFamily2_Release(family2
);
10123 win_skip("IDWriteFontFamily2 is not supported.\n");
10125 IDWriteFontFamily_Release(family
);
10126 IDWriteFontCollection_Release(collection
);
10128 refcount
= IDWriteFactory_Release(factory
);
10129 ok(!refcount
, "Unexpected factory refcount %u.\n", refcount
);
10132 static void test_system_font_set(void)
10134 IDWriteFontSet
*fontset
, *filtered_set
;
10135 IDWriteFontFaceReference
*ref
;
10136 IDWriteFontFace3
*fontface
;
10137 IDWriteFactory3
*factory
;
10138 DWRITE_FONT_PROPERTY p
;
10139 unsigned int count
;
10142 if (!(factory
= create_factory_iid(&IID_IDWriteFactory3
)))
10144 win_skip("System font set is not supported.\n");
10148 hr
= IDWriteFactory3_GetSystemFontSet(factory
, &fontset
);
10149 ok(hr
== S_OK
, "Unexpected hr %#x.\n", hr
);
10151 count
= IDWriteFontSet_GetFontCount(fontset
);
10152 ok(!!count
, "Unexpected font count %u.\n", count
);
10154 p
.propertyId
= DWRITE_FONT_PROPERTY_ID_FULL_NAME
;
10155 p
.propertyValue
= L
"Tahoma";
10156 p
.localeName
= L
"";
10157 hr
= IDWriteFontSet_GetMatchingFonts(fontset
, &p
, 1, &filtered_set
);
10158 ok(hr
== S_OK
, "Unexpected hr %#x.\n", hr
);
10159 count
= IDWriteFontSet_GetFontCount(filtered_set
);
10160 ok(!!count
, "Unexpected font count %u.\n", count
);
10162 hr
= IDWriteFontSet_GetFontFaceReference(filtered_set
, 0, &ref
);
10163 ok(hr
== S_OK
, "Unexpected hr %#x.\n", hr
);
10165 hr
= IDWriteFontFaceReference_CreateFontFace(ref
, &fontface
);
10166 ok(hr
== S_OK
, "Unexpected hr %#x.\n", hr
);
10168 IDWriteFontFace3_Release(fontface
);
10169 IDWriteFontFaceReference_Release(ref
);
10171 IDWriteFontSet_Release(filtered_set
);
10173 IDWriteFontSet_Release(fontset
);
10175 IDWriteFactory3_Release(factory
);
10178 static void test_CreateFontCollectionFromFontSet(void)
10180 unsigned int index
, count
, refcount
;
10181 IDWriteFontCollection1
*collection
;
10182 IDWriteFontSetBuilder1
*builder
;
10183 DWRITE_FONT_PROPERTY props
[1];
10184 IDWriteFontFaceReference
*ref
;
10185 IDWriteFactory5
*factory
;
10186 IDWriteFontSet
*fontset
;
10187 IDWriteFontFile
*file
;
10192 if (!(factory
= create_factory_iid(&IID_IDWriteFactory5
)))
10194 win_skip("_CreateFontCollectionFromFontSet() is not available.\n");
10198 hr
= IDWriteFactory5_CreateFontSetBuilder(factory
, &builder
);
10199 ok(hr
== S_OK
, "Failed to create font set builder, hr %#x.\n", hr
);
10201 path
= create_testfontfile(test_fontfile
);
10203 hr
= IDWriteFactory5_CreateFontFileReference(factory
, path
, NULL
, &file
);
10204 ok(hr
== S_OK
, "Unexpected hr %#x.\n",hr
);
10206 hr
= IDWriteFontSetBuilder1_AddFontFile(builder
, file
);
10207 ok(hr
== S_OK
, "Unexpected hr %#x.\n",hr
);
10209 /* Add same file, with explicit properties. */
10210 hr
= IDWriteFactory5_CreateFontFaceReference_(factory
, file
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &ref
);
10211 ok(hr
== S_OK
, "Unexpected hr %#x.\n",hr
);
10212 props
[0].propertyId
= DWRITE_FONT_PROPERTY_ID_WEIGHT_STRETCH_STYLE_FAMILY_NAME
;
10213 props
[0].propertyValue
= L
"Another Font";
10214 props
[0].localeName
= L
"en-US";
10215 hr
= IDWriteFontSetBuilder1_AddFontFaceReference_(builder
, ref
, props
, 1);
10217 ok(hr
== S_OK
, "Unexpected hr %#x.\n",hr
);
10218 IDWriteFontFaceReference_Release(ref
);
10220 hr
= IDWriteFontSetBuilder1_CreateFontSet(builder
, &fontset
);
10221 ok(hr
== S_OK
, "Unexpected hr %#x.\n",hr
);
10223 hr
= IDWriteFactory5_CreateFontCollectionFromFontSet(factory
, fontset
, &collection
);
10225 ok(hr
== S_OK
, "Unexpected hr %#x.\n",hr
);
10229 count
= IDWriteFontCollection1_GetFontFamilyCount(collection
);
10230 ok(count
== 2, "Unexpected family count %u.\n", count
);
10232 /* Explicit fontset properties are prioritized and not replaced by actual properties from a file. */
10234 hr
= IDWriteFontCollection1_FindFamilyName(collection
, L
"Another Font", &index
, &exists
);
10235 ok(hr
== S_OK
, "Unexpected hr %#x.\n",hr
);
10236 ok(!!exists
, "Unexpected return value %d.\n", exists
);
10238 IDWriteFontCollection1_Release(collection
);
10240 IDWriteFontSet_Release(fontset
);
10242 IDWriteFontSetBuilder1_Release(builder
);
10244 IDWriteFontFile_Release(file
);
10245 refcount
= IDWriteFactory5_Release(factory
);
10246 ok(!refcount
, "Unexpected factory refcount %u.\n", refcount
);
10247 DELETE_FONTFILE(path
);
10252 IDWriteFactory
*factory
;
10254 if (!(factory
= create_factory())) {
10255 win_skip("failed to create factory\n");
10259 test_object_lifetime();
10260 test_CreateFontFromLOGFONT();
10261 test_CreateBitmapRenderTarget();
10262 test_GetFontFamily();
10263 test_GetFamilyNames();
10264 test_CreateFontFace();
10266 test_system_fontcollection();
10267 test_ConvertFontFaceToLOGFONT();
10268 test_CustomFontCollection();
10269 test_CreateCustomFontFileReference();
10270 test_CreateFontFileReference();
10271 test_shared_isolated();
10272 test_GetUnicodeRanges();
10273 test_GetFontFromFontFace();
10274 test_GetFirstMatchingFont();
10275 test_GetMatchingFonts();
10276 test_GetInformationalStrings();
10277 test_GetGdiInterop();
10278 test_CreateFontFaceFromHdc();
10279 test_GetSimulations();
10280 test_GetFaceNames();
10281 test_TryGetFontTable();
10282 test_ConvertFontToLOGFONT();
10283 test_CreateStreamFromKey();
10284 test_ReadFileFragment();
10285 test_GetDesignGlyphMetrics();
10286 test_GetDesignGlyphAdvances();
10287 test_IsMonospacedFont();
10288 test_GetGlyphRunOutline();
10289 test_GetEudcFontCollection();
10290 test_GetCaretMetrics();
10291 test_GetGlyphCount();
10292 test_GetKerningPairAdjustments();
10293 test_CreateRenderingParams();
10294 test_CreateGlyphRunAnalysis();
10295 test_GetGdiCompatibleMetrics();
10297 test_GetGdiCompatibleGlyphAdvances();
10298 test_GetRecommendedRenderingMode();
10299 test_GetAlphaBlendParams();
10300 test_CreateAlphaTexture();
10301 test_IsSymbolFont();
10302 test_GetPaletteEntries();
10303 test_TranslateColorGlyphRun();
10304 test_HasCharacter();
10305 test_CreateFontFaceReference();
10306 test_GetFontSignature();
10307 test_font_properties();
10308 test_HasVerticalGlyphVariants();
10309 test_HasKerningPairs();
10310 test_ComputeGlyphOrigins();
10311 test_inmemory_file_loader();
10312 test_GetGlyphImageFormats();
10313 test_CreateCustomRenderingParams();
10314 test_localfontfileloader();
10315 test_AnalyzeContainerType();
10316 test_fontsetbuilder();
10317 test_font_resource();
10318 test_IsColorFont();
10319 test_GetVerticalGlyphVariants();
10320 test_expiration_event();
10321 test_family_font_set();
10322 test_system_font_set();
10323 test_CreateFontCollectionFromFontSet();
10325 IDWriteFactory_Release(factory
);