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 struct test_fontenumerator
592 IDWriteFontFileEnumerator IDWriteFontFileEnumerator_iface
;
596 IDWriteFontFile
*font_file
;
599 static inline struct test_fontenumerator
*impl_from_IDWriteFontFileEnumerator(IDWriteFontFileEnumerator
* iface
)
601 return CONTAINING_RECORD(iface
, struct test_fontenumerator
, IDWriteFontFileEnumerator_iface
);
604 static HRESULT WINAPI
singlefontfileenumerator_QueryInterface(IDWriteFontFileEnumerator
*iface
, REFIID riid
, void **obj
)
606 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFontFileEnumerator
))
609 IDWriteFontFileEnumerator_AddRef(iface
);
612 return E_NOINTERFACE
;
615 static ULONG WINAPI
singlefontfileenumerator_AddRef(IDWriteFontFileEnumerator
*iface
)
617 struct test_fontenumerator
*This
= impl_from_IDWriteFontFileEnumerator(iface
);
618 return InterlockedIncrement(&This
->ref
);
621 static ULONG WINAPI
singlefontfileenumerator_Release(IDWriteFontFileEnumerator
*iface
)
623 struct test_fontenumerator
*This
= impl_from_IDWriteFontFileEnumerator(iface
);
624 ULONG ref
= InterlockedDecrement(&This
->ref
);
626 IDWriteFontFile_Release(This
->font_file
);
632 static HRESULT WINAPI
singlefontfileenumerator_GetCurrentFontFile(IDWriteFontFileEnumerator
*iface
, IDWriteFontFile
**font_file
)
634 struct test_fontenumerator
*This
= impl_from_IDWriteFontFileEnumerator(iface
);
635 IDWriteFontFile_AddRef(This
->font_file
);
636 *font_file
= This
->font_file
;
640 static HRESULT WINAPI
singlefontfileenumerator_MoveNext(IDWriteFontFileEnumerator
*iface
, BOOL
*current
)
642 struct test_fontenumerator
*This
= impl_from_IDWriteFontFileEnumerator(iface
);
644 if (This
->index
> 1) {
654 static const struct IDWriteFontFileEnumeratorVtbl singlefontfileenumeratorvtbl
=
656 singlefontfileenumerator_QueryInterface
,
657 singlefontfileenumerator_AddRef
,
658 singlefontfileenumerator_Release
,
659 singlefontfileenumerator_MoveNext
,
660 singlefontfileenumerator_GetCurrentFontFile
663 static HRESULT
create_enumerator(IDWriteFontFile
*font_file
, IDWriteFontFileEnumerator
**ret
)
665 struct test_fontenumerator
*enumerator
;
667 enumerator
= heap_alloc(sizeof(struct test_fontenumerator
));
669 return E_OUTOFMEMORY
;
671 enumerator
->IDWriteFontFileEnumerator_iface
.lpVtbl
= &singlefontfileenumeratorvtbl
;
673 enumerator
->index
= 0;
674 enumerator
->font_file
= font_file
;
675 IDWriteFontFile_AddRef(font_file
);
677 *ret
= &enumerator
->IDWriteFontFileEnumerator_iface
;
681 struct test_fontcollectionloader
683 IDWriteFontCollectionLoader IDWriteFontFileCollectionLoader_iface
;
684 IDWriteFontFileLoader
*loader
;
687 static inline struct test_fontcollectionloader
*impl_from_IDWriteFontFileCollectionLoader(IDWriteFontCollectionLoader
* iface
)
689 return CONTAINING_RECORD(iface
, struct test_fontcollectionloader
, IDWriteFontFileCollectionLoader_iface
);
692 static HRESULT WINAPI
resourcecollectionloader_QueryInterface(IDWriteFontCollectionLoader
*iface
, REFIID riid
, void **obj
)
694 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFontCollectionLoader
))
697 IDWriteFontCollectionLoader_AddRef(iface
);
700 return E_NOINTERFACE
;
703 static ULONG WINAPI
resourcecollectionloader_AddRef(IDWriteFontCollectionLoader
*iface
)
708 static ULONG WINAPI
resourcecollectionloader_Release(IDWriteFontCollectionLoader
*iface
)
713 static HRESULT WINAPI
resourcecollectionloader_CreateEnumeratorFromKey(IDWriteFontCollectionLoader
*iface
, IDWriteFactory
*factory
,
714 const void * collectionKey
, UINT32 collectionKeySize
, IDWriteFontFileEnumerator
** fontFileEnumerator
)
716 struct test_fontcollectionloader
*This
= impl_from_IDWriteFontFileCollectionLoader(iface
);
717 IDWriteFontFile
*font_file
;
720 hr
= IDWriteFactory_CreateCustomFontFileReference(factory
, collectionKey
, collectionKeySize
, This
->loader
, &font_file
);
721 ok(hr
== S_OK
, "Failed to create custom file reference, hr %#x.\n", hr
);
723 hr
= create_enumerator(font_file
, fontFileEnumerator
);
724 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
726 IDWriteFontFile_Release(font_file
);
730 static const struct IDWriteFontCollectionLoaderVtbl resourcecollectionloadervtbl
= {
731 resourcecollectionloader_QueryInterface
,
732 resourcecollectionloader_AddRef
,
733 resourcecollectionloader_Release
,
734 resourcecollectionloader_CreateEnumeratorFromKey
737 /* Here is a functional custom font set of interfaces */
738 struct test_fontdatastream
740 IDWriteFontFileStream IDWriteFontFileStream_iface
;
747 static inline struct test_fontdatastream
*impl_from_IDWriteFontFileStream(IDWriteFontFileStream
* iface
)
749 return CONTAINING_RECORD(iface
, struct test_fontdatastream
, IDWriteFontFileStream_iface
);
752 static HRESULT WINAPI
fontdatastream_QueryInterface(IDWriteFontFileStream
*iface
, REFIID riid
, void **obj
)
754 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFontFileStream
))
757 IDWriteFontFileStream_AddRef(iface
);
761 return E_NOINTERFACE
;
764 static ULONG WINAPI
fontdatastream_AddRef(IDWriteFontFileStream
*iface
)
766 struct test_fontdatastream
*This
= impl_from_IDWriteFontFileStream(iface
);
767 ULONG ref
= InterlockedIncrement(&This
->ref
);
771 static ULONG WINAPI
fontdatastream_Release(IDWriteFontFileStream
*iface
)
773 struct test_fontdatastream
*This
= impl_from_IDWriteFontFileStream(iface
);
774 ULONG ref
= InterlockedDecrement(&This
->ref
);
776 HeapFree(GetProcessHeap(), 0, This
);
780 static HRESULT WINAPI
fontdatastream_ReadFileFragment(IDWriteFontFileStream
*iface
, void const **fragment_start
, UINT64 offset
, UINT64 fragment_size
, void **fragment_context
)
782 struct test_fontdatastream
*This
= impl_from_IDWriteFontFileStream(iface
);
783 *fragment_context
= NULL
;
784 if (offset
+fragment_size
> This
->size
)
786 *fragment_start
= NULL
;
791 *fragment_start
= (BYTE
*)This
->data
+ offset
;
796 static void WINAPI
fontdatastream_ReleaseFileFragment(IDWriteFontFileStream
*iface
, void *fragment_context
)
801 static HRESULT WINAPI
fontdatastream_GetFileSize(IDWriteFontFileStream
*iface
, UINT64
*size
)
803 struct test_fontdatastream
*This
= impl_from_IDWriteFontFileStream(iface
);
808 static HRESULT WINAPI
fontdatastream_GetLastWriteTime(IDWriteFontFileStream
*iface
, UINT64
*last_writetime
)
813 static const IDWriteFontFileStreamVtbl fontdatastreamvtbl
=
815 fontdatastream_QueryInterface
,
816 fontdatastream_AddRef
,
817 fontdatastream_Release
,
818 fontdatastream_ReadFileFragment
,
819 fontdatastream_ReleaseFileFragment
,
820 fontdatastream_GetFileSize
,
821 fontdatastream_GetLastWriteTime
824 static HRESULT
create_fontdatastream(LPVOID data
, UINT size
, IDWriteFontFileStream
** iface
)
826 struct test_fontdatastream
*This
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct test_fontdatastream
));
828 return E_OUTOFMEMORY
;
833 This
->IDWriteFontFileStream_iface
.lpVtbl
= &fontdatastreamvtbl
;
835 *iface
= &This
->IDWriteFontFileStream_iface
;
839 static HRESULT WINAPI
resourcefontfileloader_QueryInterface(IDWriteFontFileLoader
*iface
, REFIID riid
, void **obj
)
841 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFontFileLoader
))
847 return E_NOINTERFACE
;
850 static ULONG WINAPI
resourcefontfileloader_AddRef(IDWriteFontFileLoader
*iface
)
855 static ULONG WINAPI
resourcefontfileloader_Release(IDWriteFontFileLoader
*iface
)
860 static HRESULT WINAPI
resourcefontfileloader_CreateStreamFromKey(IDWriteFontFileLoader
*iface
, const void *ref_key
, UINT32 key_size
,
861 IDWriteFontFileStream
**stream
)
867 mem
= LoadResource(GetModuleHandleA(NULL
), *(HRSRC
*)ref_key
);
868 ok(mem
!= NULL
, "Failed to lock font resource\n");
871 size
= SizeofResource(GetModuleHandleA(NULL
), *(HRSRC
*)ref_key
);
872 data
= LockResource(mem
);
873 return create_fontdatastream(data
, size
, stream
);
878 static const struct IDWriteFontFileLoaderVtbl resourcefontfileloadervtbl
= {
879 resourcefontfileloader_QueryInterface
,
880 resourcefontfileloader_AddRef
,
881 resourcefontfileloader_Release
,
882 resourcefontfileloader_CreateStreamFromKey
885 static IDWriteFontFileLoader rloader
= { &resourcefontfileloadervtbl
};
887 static D2D1_POINT_2F g_startpoints
[2];
888 static int g_startpoint_count
;
890 static HRESULT WINAPI
test_geometrysink_QueryInterface(ID2D1SimplifiedGeometrySink
*iface
, REFIID riid
, void **ret
)
892 if (IsEqualIID(riid
, &IID_ID2D1SimplifiedGeometrySink
) ||
893 IsEqualIID(riid
, &IID_IUnknown
))
896 ID2D1SimplifiedGeometrySink_AddRef(iface
);
901 return E_NOINTERFACE
;
904 static ULONG WINAPI
test_geometrysink_AddRef(ID2D1SimplifiedGeometrySink
*iface
)
909 static ULONG WINAPI
test_geometrysink_Release(ID2D1SimplifiedGeometrySink
*iface
)
914 static void WINAPI
test_geometrysink_SetFillMode(ID2D1SimplifiedGeometrySink
*iface
, D2D1_FILL_MODE mode
)
916 CHECK_EXPECT(setfillmode
);
917 ok(mode
== D2D1_FILL_MODE_WINDING
, "fill mode %d\n", mode
);
920 static void WINAPI
test_geometrysink_SetSegmentFlags(ID2D1SimplifiedGeometrySink
*iface
, D2D1_PATH_SEGMENT flags
)
922 ok(0, "unexpected SetSegmentFlags() - flags %d\n", flags
);
925 static void WINAPI
test_geometrysink_BeginFigure(ID2D1SimplifiedGeometrySink
*iface
,
926 D2D1_POINT_2F startPoint
, D2D1_FIGURE_BEGIN figureBegin
)
928 ok(figureBegin
== D2D1_FIGURE_BEGIN_FILLED
, "begin figure %d\n", figureBegin
);
929 if (g_startpoint_count
< ARRAY_SIZE(g_startpoints
))
930 g_startpoints
[g_startpoint_count
] = startPoint
;
931 g_startpoint_count
++;
934 static void WINAPI
test_geometrysink_AddLines(ID2D1SimplifiedGeometrySink
*iface
,
935 const D2D1_POINT_2F
*points
, UINT32 count
)
939 static void WINAPI
test_geometrysink_AddBeziers(ID2D1SimplifiedGeometrySink
*iface
,
940 const D2D1_BEZIER_SEGMENT
*beziers
, UINT32 count
)
944 static void WINAPI
test_geometrysink_EndFigure(ID2D1SimplifiedGeometrySink
*iface
, D2D1_FIGURE_END figureEnd
)
946 ok(figureEnd
== D2D1_FIGURE_END_CLOSED
, "end figure %d\n", figureEnd
);
949 static HRESULT WINAPI
test_geometrysink_Close(ID2D1SimplifiedGeometrySink
*iface
)
951 ok(0, "unexpected Close()\n");
955 static const ID2D1SimplifiedGeometrySinkVtbl test_geometrysink_vtbl
= {
956 test_geometrysink_QueryInterface
,
957 test_geometrysink_AddRef
,
958 test_geometrysink_Release
,
959 test_geometrysink_SetFillMode
,
960 test_geometrysink_SetSegmentFlags
,
961 test_geometrysink_BeginFigure
,
962 test_geometrysink_AddLines
,
963 test_geometrysink_AddBeziers
,
964 test_geometrysink_EndFigure
,
965 test_geometrysink_Close
968 static void WINAPI
test_geometrysink2_BeginFigure(ID2D1SimplifiedGeometrySink
*iface
,
969 D2D1_POINT_2F startPoint
, D2D1_FIGURE_BEGIN figureBegin
)
971 ok(0, "unexpected call\n");
974 static void WINAPI
test_geometrysink2_AddLines(ID2D1SimplifiedGeometrySink
*iface
,
975 const D2D1_POINT_2F
*points
, UINT32 count
)
977 ok(0, "unexpected call\n");
980 static void WINAPI
test_geometrysink2_AddBeziers(ID2D1SimplifiedGeometrySink
*iface
,
981 const D2D1_BEZIER_SEGMENT
*beziers
, UINT32 count
)
983 ok(0, "unexpected call\n");
986 static void WINAPI
test_geometrysink2_EndFigure(ID2D1SimplifiedGeometrySink
*iface
, D2D1_FIGURE_END figureEnd
)
988 ok(0, "unexpected call\n");
991 static const ID2D1SimplifiedGeometrySinkVtbl test_geometrysink2_vtbl
= {
992 test_geometrysink_QueryInterface
,
993 test_geometrysink_AddRef
,
994 test_geometrysink_Release
,
995 test_geometrysink_SetFillMode
,
996 test_geometrysink_SetSegmentFlags
,
997 test_geometrysink2_BeginFigure
,
998 test_geometrysink2_AddLines
,
999 test_geometrysink2_AddBeziers
,
1000 test_geometrysink2_EndFigure
,
1001 test_geometrysink_Close
1004 static ID2D1SimplifiedGeometrySink test_geomsink
= { &test_geometrysink_vtbl
};
1005 static ID2D1SimplifiedGeometrySink test_geomsink2
= { &test_geometrysink2_vtbl
};
1007 static void test_CreateFontFromLOGFONT(void)
1009 IDWriteGdiInterop1
*interop1
;
1010 IDWriteGdiInterop
*interop
;
1011 DWRITE_FONT_WEIGHT weight
;
1012 DWRITE_FONT_STYLE style
;
1015 LONG weights
[][2] = {
1016 {FW_NORMAL
, DWRITE_FONT_WEIGHT_NORMAL
},
1017 {FW_BOLD
, DWRITE_FONT_WEIGHT_BOLD
},
1018 { 0, DWRITE_FONT_WEIGHT_NORMAL
},
1019 { 50, DWRITE_FONT_WEIGHT_NORMAL
},
1020 {150, DWRITE_FONT_WEIGHT_NORMAL
},
1021 {250, DWRITE_FONT_WEIGHT_NORMAL
},
1022 {350, DWRITE_FONT_WEIGHT_NORMAL
},
1023 {450, DWRITE_FONT_WEIGHT_NORMAL
},
1024 {650, DWRITE_FONT_WEIGHT_BOLD
},
1025 {750, DWRITE_FONT_WEIGHT_BOLD
},
1026 {850, DWRITE_FONT_WEIGHT_BOLD
},
1027 {950, DWRITE_FONT_WEIGHT_BOLD
},
1028 {960, DWRITE_FONT_WEIGHT_BOLD
},
1030 OUTLINETEXTMETRICW otm
;
1031 IDWriteFactory
*factory
;
1041 factory
= create_factory();
1043 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop
);
1044 ok(hr
== S_OK
, "got %#x\n", hr
);
1047 /* null out parameter crashes this call */
1048 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, NULL
, NULL
);
1050 font
= (void*)0xdeadbeef;
1051 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, NULL
, &font
);
1052 EXPECT_HR(hr
, E_INVALIDARG
);
1053 ok(font
== NULL
, "got %p\n", font
);
1055 memset(&logfont
, 0, sizeof(logfont
));
1056 logfont
.lfHeight
= 12;
1057 logfont
.lfWidth
= 12;
1058 logfont
.lfWeight
= FW_NORMAL
;
1059 logfont
.lfItalic
= 1;
1060 lstrcpyW(logfont
.lfFaceName
, L
"Tahoma");
1062 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font
);
1063 EXPECT_HR(hr
, S_OK
);
1065 hfont
= CreateFontIndirectW(&logfont
);
1066 hdc
= CreateCompatibleDC(0);
1067 SelectObject(hdc
, hfont
);
1069 otm
.otmSize
= sizeof(otm
);
1070 r
= GetOutlineTextMetricsW(hdc
, otm
.otmSize
, &otm
);
1071 ok(r
, "got %d\n", r
);
1073 DeleteObject(hfont
);
1076 hr
= IDWriteFont_HasCharacter(font
, 0xd800, &exists
);
1077 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1078 ok(exists
== FALSE
, "got %d\n", exists
);
1081 hr
= IDWriteFont_HasCharacter(font
, 0x20, &exists
);
1082 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1083 ok(exists
== TRUE
, "got %d\n", exists
);
1085 /* now check properties */
1086 weight
= IDWriteFont_GetWeight(font
);
1087 ok(weight
== DWRITE_FONT_WEIGHT_NORMAL
, "got %d\n", weight
);
1089 style
= IDWriteFont_GetStyle(font
);
1090 ok(style
== DWRITE_FONT_STYLE_OBLIQUE
, "got %d\n", style
);
1091 ok(otm
.otmfsSelection
& 1, "got 0x%08x\n", otm
.otmfsSelection
);
1093 ret
= IDWriteFont_IsSymbolFont(font
);
1094 ok(!ret
, "got %d\n", ret
);
1096 IDWriteFont_Release(font
);
1099 for (i
= 0; i
< ARRAY_SIZE(weights
); i
++)
1101 memset(&logfont
, 0, sizeof(logfont
));
1102 logfont
.lfHeight
= 12;
1103 logfont
.lfWidth
= 12;
1104 logfont
.lfWeight
= weights
[i
][0];
1105 lstrcpyW(logfont
.lfFaceName
, L
"Tahoma");
1107 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font
);
1108 EXPECT_HR(hr
, S_OK
);
1110 weight
= IDWriteFont_GetWeight(font
);
1111 ok(weight
== weights
[i
][1],
1112 "%d: got %d, expected %d\n", i
, weight
, weights
[i
][1]);
1114 IDWriteFont_Release(font
);
1117 /* weight not from enum */
1118 memset(&logfont
, 0, sizeof(logfont
));
1119 logfont
.lfHeight
= 12;
1120 logfont
.lfWidth
= 12;
1121 logfont
.lfWeight
= 550;
1122 lstrcpyW(logfont
.lfFaceName
, L
"Tahoma");
1125 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font
);
1126 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1128 weight
= IDWriteFont_GetWeight(font
);
1129 ok(weight
== DWRITE_FONT_WEIGHT_NORMAL
|| weight
== DWRITE_FONT_WEIGHT_BOLD
,
1130 "got %d\n", weight
);
1132 IDWriteFont_Release(font
);
1134 /* empty or nonexistent face name */
1135 memset(&logfont
, 0, sizeof(logfont
));
1136 logfont
.lfHeight
= 12;
1137 logfont
.lfWidth
= 12;
1138 logfont
.lfWeight
= FW_NORMAL
;
1139 lstrcpyW(logfont
.lfFaceName
, L
"Blah!");
1141 font
= (void*)0xdeadbeef;
1142 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font
);
1143 ok(hr
== DWRITE_E_NOFONT
, "got 0x%08x\n", hr
);
1144 ok(font
== NULL
, "got %p\n", font
);
1146 /* Try with name 'Tahoma ' */
1147 memset(&logfont
, 0, sizeof(logfont
));
1148 logfont
.lfHeight
= 12;
1149 logfont
.lfWidth
= 12;
1150 logfont
.lfWeight
= FW_NORMAL
;
1151 lstrcpyW(logfont
.lfFaceName
, L
"Tahoma ");
1153 font
= (void*)0xdeadbeef;
1154 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font
);
1155 ok(hr
== DWRITE_E_NOFONT
, "got 0x%08x\n", hr
);
1156 ok(font
== NULL
, "got %p\n", font
);
1158 /* empty string as a facename */
1159 memset(&logfont
, 0, sizeof(logfont
));
1160 logfont
.lfHeight
= 12;
1161 logfont
.lfWidth
= 12;
1162 logfont
.lfWeight
= FW_NORMAL
;
1164 font
= (void*)0xdeadbeef;
1165 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font
);
1166 ok(hr
== DWRITE_E_NOFONT
, "got 0x%08x\n", hr
);
1167 ok(font
== NULL
, "got %p\n", font
);
1169 /* IDWriteGdiInterop1::CreateFontFromLOGFONT() */
1170 hr
= IDWriteGdiInterop_QueryInterface(interop
, &IID_IDWriteGdiInterop1
, (void**)&interop1
);
1172 memset(&logfont
, 0, sizeof(logfont
));
1173 logfont
.lfHeight
= 12;
1174 logfont
.lfWidth
= 12;
1175 logfont
.lfWeight
= FW_NORMAL
;
1176 logfont
.lfItalic
= 1;
1177 lstrcpyW(logfont
.lfFaceName
, L
"Tahoma");
1179 hr
= IDWriteGdiInterop1_CreateFontFromLOGFONT(interop1
, &logfont
, NULL
, &font
);
1180 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1182 IDWriteFont_Release(font
);
1183 IDWriteGdiInterop1_Release(interop1
);
1186 win_skip("IDWriteGdiInterop1 is not supported, skipping CreateFontFromLOGFONT() tests.\n");
1188 ref
= IDWriteGdiInterop_Release(interop
);
1189 ok(ref
== 0, "interop is not released, %u\n", ref
);
1190 ref
= IDWriteFactory_Release(factory
);
1191 ok(ref
== 0, "factory is not released, %u\n", ref
);
1194 static void test_CreateBitmapRenderTarget(void)
1196 IDWriteBitmapRenderTarget
*target
, *target2
;
1197 IDWriteBitmapRenderTarget1
*target1
;
1198 IDWriteRenderingParams
*params
;
1199 IDWriteGdiInterop
*interop
;
1200 IDWriteFontFace
*fontface
;
1201 IDWriteFactory
*factory
;
1202 DWRITE_GLYPH_RUN run
;
1217 factory
= create_factory();
1219 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop
);
1220 EXPECT_HR(hr
, S_OK
);
1223 hr
= IDWriteGdiInterop_CreateBitmapRenderTarget(interop
, NULL
, 0, 0, &target
);
1224 EXPECT_HR(hr
, S_OK
);
1226 if (0) /* crashes on native */
1227 hr
= IDWriteBitmapRenderTarget_GetSize(target
, NULL
);
1229 size
.cx
= size
.cy
= -1;
1230 hr
= IDWriteBitmapRenderTarget_GetSize(target
, &size
);
1231 EXPECT_HR(hr
, S_OK
);
1232 ok(size
.cx
== 0, "got %d\n", size
.cx
);
1233 ok(size
.cy
== 0, "got %d\n", size
.cy
);
1236 hr
= IDWriteGdiInterop_CreateBitmapRenderTarget(interop
, NULL
, 0, 0, &target2
);
1237 EXPECT_HR(hr
, S_OK
);
1238 ok(target
!= target2
, "got %p, %p\n", target2
, target
);
1239 IDWriteBitmapRenderTarget_Release(target2
);
1241 hdc
= IDWriteBitmapRenderTarget_GetMemoryDC(target
);
1242 ok(hdc
!= NULL
, "got %p\n", hdc
);
1245 ret
= GetGraphicsMode(hdc
);
1246 ok(ret
== GM_ADVANCED
, "got %d\n", ret
);
1248 hbm
= GetCurrentObject(hdc
, OBJ_BITMAP
);
1249 ok(hbm
!= NULL
, "got %p\n", hbm
);
1251 /* check DIB properties */
1252 ret
= GetObjectW(hbm
, sizeof(ds
), &ds
);
1253 ok(ret
== sizeof(BITMAP
), "got %d\n", ret
);
1254 ok(ds
.dsBm
.bmWidth
== 1, "got %d\n", ds
.dsBm
.bmWidth
);
1255 ok(ds
.dsBm
.bmHeight
== 1, "got %d\n", ds
.dsBm
.bmHeight
);
1256 ok(ds
.dsBm
.bmPlanes
== 1, "got %d\n", ds
.dsBm
.bmPlanes
);
1257 ok(ds
.dsBm
.bmBitsPixel
== 1, "got %d\n", ds
.dsBm
.bmBitsPixel
);
1258 ok(!ds
.dsBm
.bmBits
, "got %p\n", ds
.dsBm
.bmBits
);
1260 IDWriteBitmapRenderTarget_Release(target
);
1262 hbm
= GetCurrentObject(hdc
, OBJ_BITMAP
);
1263 ok(!hbm
, "got %p\n", hbm
);
1266 hr
= IDWriteGdiInterop_CreateBitmapRenderTarget(interop
, NULL
, 10, 5, &target
);
1267 EXPECT_HR(hr
, S_OK
);
1269 hdc
= IDWriteBitmapRenderTarget_GetMemoryDC(target
);
1270 ok(hdc
!= NULL
, "got %p\n", hdc
);
1272 /* test context settings */
1273 c
= GetTextColor(hdc
);
1274 ok(c
== RGB(0, 0, 0), "got 0x%08x\n", c
);
1275 ret
= GetBkMode(hdc
);
1276 ok(ret
== OPAQUE
, "got %d\n", ret
);
1277 c
= GetBkColor(hdc
);
1278 ok(c
== RGB(255, 255, 255), "got 0x%08x\n", c
);
1280 hbm
= GetCurrentObject(hdc
, OBJ_BITMAP
);
1281 ok(hbm
!= NULL
, "got %p\n", hbm
);
1283 /* check DIB properties */
1284 ret
= GetObjectW(hbm
, sizeof(ds
), &ds
);
1285 ok(ret
== sizeof(ds
), "got %d\n", ret
);
1286 ok(ds
.dsBm
.bmWidth
== 10, "got %d\n", ds
.dsBm
.bmWidth
);
1287 ok(ds
.dsBm
.bmHeight
== 5, "got %d\n", ds
.dsBm
.bmHeight
);
1288 ok(ds
.dsBm
.bmPlanes
== 1, "got %d\n", ds
.dsBm
.bmPlanes
);
1289 ok(ds
.dsBm
.bmBitsPixel
== 32, "got %d\n", ds
.dsBm
.bmBitsPixel
);
1290 ok(ds
.dsBm
.bmBits
!= NULL
, "got %p\n", ds
.dsBm
.bmBits
);
1292 size
.cx
= size
.cy
= -1;
1293 hr
= IDWriteBitmapRenderTarget_GetSize(target
, &size
);
1294 EXPECT_HR(hr
, S_OK
);
1295 ok(size
.cx
== 10, "got %d\n", size
.cx
);
1296 ok(size
.cy
== 5, "got %d\n", size
.cy
);
1298 /* resize to same size */
1299 hr
= IDWriteBitmapRenderTarget_Resize(target
, 10, 5);
1300 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1302 hbm2
= GetCurrentObject(hdc
, OBJ_BITMAP
);
1303 ok(hbm2
== hbm
, "got %p, %p\n", hbm2
, hbm
);
1306 hr
= IDWriteBitmapRenderTarget_Resize(target
, 5, 5);
1307 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1309 size
.cx
= size
.cy
= -1;
1310 hr
= IDWriteBitmapRenderTarget_GetSize(target
, &size
);
1311 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1312 ok(size
.cx
== 5, "got %d\n", size
.cx
);
1313 ok(size
.cy
== 5, "got %d\n", size
.cy
);
1315 hbm2
= GetCurrentObject(hdc
, OBJ_BITMAP
);
1316 ok(hbm2
!= hbm
, "got %p, %p\n", hbm2
, hbm
);
1318 hr
= IDWriteBitmapRenderTarget_Resize(target
, 20, 5);
1319 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1321 size
.cx
= size
.cy
= -1;
1322 hr
= IDWriteBitmapRenderTarget_GetSize(target
, &size
);
1323 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1324 ok(size
.cx
== 20, "got %d\n", size
.cx
);
1325 ok(size
.cy
== 5, "got %d\n", size
.cy
);
1327 hbm2
= GetCurrentObject(hdc
, OBJ_BITMAP
);
1328 ok(hbm2
!= hbm
, "got %p, %p\n", hbm2
, hbm
);
1330 hr
= IDWriteBitmapRenderTarget_Resize(target
, 1, 5);
1331 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1333 size
.cx
= size
.cy
= -1;
1334 hr
= IDWriteBitmapRenderTarget_GetSize(target
, &size
);
1335 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1336 ok(size
.cx
== 1, "got %d\n", size
.cx
);
1337 ok(size
.cy
== 5, "got %d\n", size
.cy
);
1339 hbm2
= GetCurrentObject(hdc
, OBJ_BITMAP
);
1340 ok(hbm2
!= hbm
, "got %p, %p\n", hbm2
, hbm
);
1342 ret
= GetObjectW(hbm2
, sizeof(ds
), &ds
);
1343 ok(ret
== sizeof(ds
), "got %d\n", ret
);
1344 ok(ds
.dsBm
.bmWidth
== 1, "got %d\n", ds
.dsBm
.bmWidth
);
1345 ok(ds
.dsBm
.bmHeight
== 5, "got %d\n", ds
.dsBm
.bmHeight
);
1346 ok(ds
.dsBm
.bmPlanes
== 1, "got %d\n", ds
.dsBm
.bmPlanes
);
1347 ok(ds
.dsBm
.bmBitsPixel
== 32, "got %d\n", ds
.dsBm
.bmBitsPixel
);
1348 ok(ds
.dsBm
.bmBits
!= NULL
, "got %p\n", ds
.dsBm
.bmBits
);
1350 /* empty rectangle */
1351 hr
= IDWriteBitmapRenderTarget_Resize(target
, 0, 5);
1352 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1354 size
.cx
= size
.cy
= -1;
1355 hr
= IDWriteBitmapRenderTarget_GetSize(target
, &size
);
1356 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1357 ok(size
.cx
== 0, "got %d\n", size
.cx
);
1358 ok(size
.cy
== 5, "got %d\n", size
.cy
);
1360 hbm2
= GetCurrentObject(hdc
, OBJ_BITMAP
);
1361 ok(hbm2
!= hbm
, "got %p, %p\n", hbm2
, hbm
);
1363 ret
= GetObjectW(hbm2
, sizeof(ds
), &ds
);
1364 ok(ret
== sizeof(BITMAP
), "got %d\n", ret
);
1365 ok(ds
.dsBm
.bmWidth
== 1, "got %d\n", ds
.dsBm
.bmWidth
);
1366 ok(ds
.dsBm
.bmHeight
== 1, "got %d\n", ds
.dsBm
.bmHeight
);
1367 ok(ds
.dsBm
.bmPlanes
== 1, "got %d\n", ds
.dsBm
.bmPlanes
);
1368 ok(ds
.dsBm
.bmBitsPixel
== 1, "got %d\n", ds
.dsBm
.bmBitsPixel
);
1369 ok(!ds
.dsBm
.bmBits
, "got %p\n", ds
.dsBm
.bmBits
);
1371 /* transform tests, current hdc transform is not immediately affected */
1372 if (0) /* crashes on native */
1373 hr
= IDWriteBitmapRenderTarget_GetCurrentTransform(target
, NULL
);
1375 memset(&m
, 0xcc, sizeof(m
));
1376 hr
= IDWriteBitmapRenderTarget_GetCurrentTransform(target
, &m
);
1377 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1378 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
);
1379 ok(m
.dx
== 0.0 && m
.dy
== 0.0, "got %.1f,%.1f\n", m
.dx
, m
.dy
);
1380 ret
= GetWorldTransform(hdc
, &xform
);
1381 ok(ret
, "got %d\n", ret
);
1382 ok(xform
.eM11
== 1.0 && xform
.eM22
== 1.0 && xform
.eM12
== 0.0 && xform
.eM21
== 0.0, "got wrong transform\n");
1383 ok(xform
.eDx
== 0.0 && xform
.eDy
== 0.0, "got %.1f,%.1f\n", xform
.eDx
, xform
.eDy
);
1385 memset(&m
, 0, sizeof(m
));
1386 hr
= IDWriteBitmapRenderTarget_SetCurrentTransform(target
, &m
);
1387 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
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
== 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
);
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 m
.m11
= 2.0; m
.m22
= 1.0;
1401 hr
= IDWriteBitmapRenderTarget_SetCurrentTransform(target
, &m
);
1402 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1403 ret
= GetWorldTransform(hdc
, &xform
);
1404 ok(ret
, "got %d\n", ret
);
1405 ok(xform
.eM11
== 1.0 && xform
.eM22
== 1.0 && xform
.eM12
== 0.0 && xform
.eM21
== 0.0, "got wrong transform\n");
1406 ok(xform
.eDx
== 0.0 && xform
.eDy
== 0.0, "got %.1f,%.1f\n", xform
.eDx
, xform
.eDy
);
1408 hr
= IDWriteBitmapRenderTarget_SetCurrentTransform(target
, NULL
);
1409 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1411 memset(&m
, 0xcc, sizeof(m
));
1412 hr
= IDWriteBitmapRenderTarget_GetCurrentTransform(target
, &m
);
1413 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1414 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
);
1415 ok(m
.dx
== 0.0 && m
.dy
== 0.0, "got %.1f,%.1f\n", m
.dx
, m
.dy
);
1417 /* pixels per dip */
1418 pdip
= IDWriteBitmapRenderTarget_GetPixelsPerDip(target
);
1419 ok(pdip
== 1.0, "got %.2f\n", pdip
);
1421 hr
= IDWriteBitmapRenderTarget_SetPixelsPerDip(target
, 2.0);
1422 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1424 hr
= IDWriteBitmapRenderTarget_SetPixelsPerDip(target
, -1.0);
1425 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1427 hr
= IDWriteBitmapRenderTarget_SetPixelsPerDip(target
, 0.0);
1428 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1430 pdip
= IDWriteBitmapRenderTarget_GetPixelsPerDip(target
);
1431 ok(pdip
== 2.0, "got %.2f\n", pdip
);
1433 hr
= IDWriteBitmapRenderTarget_QueryInterface(target
, &IID_IDWriteBitmapRenderTarget1
, (void**)&target1
);
1435 DWRITE_TEXT_ANTIALIAS_MODE mode
;
1437 mode
= IDWriteBitmapRenderTarget1_GetTextAntialiasMode(target1
);
1438 ok(mode
== DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE
, "got %d\n", mode
);
1440 hr
= IDWriteBitmapRenderTarget1_SetTextAntialiasMode(target1
, DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
+1);
1441 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1443 mode
= IDWriteBitmapRenderTarget1_GetTextAntialiasMode(target1
);
1444 ok(mode
== DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE
, "got %d\n", mode
);
1446 hr
= IDWriteBitmapRenderTarget1_SetTextAntialiasMode(target1
, DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
);
1447 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1449 mode
= IDWriteBitmapRenderTarget1_GetTextAntialiasMode(target1
);
1450 ok(mode
== DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
, "got %d\n", mode
);
1452 IDWriteBitmapRenderTarget1_Release(target1
);
1455 win_skip("IDWriteBitmapRenderTarget1 is not supported.\n");
1457 /* DrawGlyphRun() argument validation. */
1458 hr
= IDWriteBitmapRenderTarget_Resize(target
, 16, 16);
1459 ok(hr
== S_OK
, "Failed to resize target, hr %#x.\n", hr
);
1461 fontface
= create_fontface(factory
);
1465 hr
= IDWriteFontFace_GetGlyphIndices(fontface
, &ch
, 1, glyphs
);
1466 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1467 ok(glyphs
[0] > 0, "got %u\n", glyphs
[0]);
1468 glyphs
[1] = glyphs
[0];
1470 memset(&run
, 0, sizeof(run
));
1471 run
.fontFace
= fontface
;
1472 run
.fontEmSize
= 12.0f
;
1474 run
.glyphIndices
= glyphs
;
1476 hr
= IDWriteFactory_CreateCustomRenderingParams(factory
, 1.0f
, 0.0f
, 0.0f
, DWRITE_PIXEL_GEOMETRY_FLAT
,
1477 DWRITE_RENDERING_MODE_DEFAULT
, ¶ms
);
1478 ok(hr
== S_OK
, "Failed to create rendering params, hr %#x.\n", hr
);
1480 hr
= IDWriteBitmapRenderTarget_DrawGlyphRun(target
, 0.0f
, 0.0f
, DWRITE_MEASURING_MODE_NATURAL
,
1481 &run
, NULL
, RGB(255, 0, 0), NULL
);
1482 ok(hr
== E_INVALIDARG
, "Unexpected hr %#x.\n", hr
);
1484 hr
= IDWriteBitmapRenderTarget_DrawGlyphRun(target
, 0.0f
, 0.0f
, DWRITE_MEASURING_MODE_GDI_NATURAL
+ 1,
1485 &run
, NULL
, RGB(255, 0, 0), NULL
);
1486 ok(hr
== E_INVALIDARG
, "Unexpected hr %#x.\n", hr
);
1488 hr
= IDWriteBitmapRenderTarget_DrawGlyphRun(target
, 0.0f
, 0.0f
, DWRITE_MEASURING_MODE_GDI_NATURAL
+ 1,
1489 &run
, params
, RGB(255, 0, 0), NULL
);
1490 ok(hr
== E_INVALIDARG
|| broken(hr
== S_OK
) /* Vista */, "Unexpected hr %#x.\n", hr
);
1492 hr
= IDWriteBitmapRenderTarget_DrawGlyphRun(target
, 0.0f
, 0.0f
, DWRITE_MEASURING_MODE_GDI_NATURAL
,
1493 &run
, params
, RGB(255, 0, 0), NULL
);
1494 ok(hr
== S_OK
, "Failed to draw a run, hr %#x.\n", hr
);
1496 IDWriteRenderingParams_Release(params
);
1498 /* Zero sized target returns earlier. */
1499 hr
= IDWriteBitmapRenderTarget_Resize(target
, 0, 16);
1500 ok(hr
== S_OK
, "Failed to resize target, hr %#x.\n", hr
);
1502 hr
= IDWriteBitmapRenderTarget_DrawGlyphRun(target
, 0.0f
, 0.0f
, DWRITE_MEASURING_MODE_NATURAL
,
1503 &run
, NULL
, RGB(255, 0, 0), NULL
);
1504 ok(hr
== S_OK
, "Unexpected hr %#x.\n", hr
);
1506 hr
= IDWriteBitmapRenderTarget_DrawGlyphRun(target
, 0.0f
, 0.0f
, DWRITE_MEASURING_MODE_GDI_NATURAL
+ 1,
1507 &run
, params
, RGB(255, 0, 0), NULL
);
1508 ok(hr
== S_OK
, "Unexpected hr %#x.\n", hr
);
1510 IDWriteFontFace_Release(fontface
);
1512 ref
= IDWriteBitmapRenderTarget_Release(target
);
1513 ok(ref
== 0, "render target not released, %u\n", ref
);
1514 ref
= IDWriteGdiInterop_Release(interop
);
1515 ok(ref
== 0, "interop not released, %u\n", ref
);
1516 ref
= IDWriteFactory_Release(factory
);
1517 ok(ref
== 0, "factory not released, %u\n", ref
);
1520 static void test_GetFontFamily(void)
1522 IDWriteFontCollection
*collection
, *collection2
;
1523 IDWriteFontCollection
*syscoll
;
1524 IDWriteFontCollection2
*coll2
;
1525 IDWriteFontFamily
*family
, *family2
;
1526 IDWriteFontFamily1
*family1
;
1527 IDWriteGdiInterop
*interop
;
1528 IDWriteFont
*font
, *font2
;
1529 IDWriteFactory
*factory
;
1534 factory
= create_factory();
1536 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop
);
1537 EXPECT_HR(hr
, S_OK
);
1539 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &syscoll
, FALSE
);
1540 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1542 memset(&logfont
, 0, sizeof(logfont
));
1543 logfont
.lfHeight
= 12;
1544 logfont
.lfWidth
= 12;
1545 logfont
.lfWeight
= FW_NORMAL
;
1546 logfont
.lfItalic
= 1;
1547 lstrcpyW(logfont
.lfFaceName
, L
"Tahoma");
1549 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font
);
1550 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1552 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font2
);
1553 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1554 ok(font2
!= font
, "got %p, %p\n", font2
, font
);
1556 if (0) /* crashes on native */
1557 hr
= IDWriteFont_GetFontFamily(font
, NULL
);
1559 EXPECT_REF(font
, 1);
1560 hr
= IDWriteFont_GetFontFamily(font
, &family
);
1561 EXPECT_HR(hr
, S_OK
);
1562 EXPECT_REF(font
, 1);
1563 EXPECT_REF(family
, 2);
1565 hr
= IDWriteFont_GetFontFamily(font
, &family2
);
1566 EXPECT_HR(hr
, S_OK
);
1567 ok(family2
== family
, "got %p, previous %p\n", family2
, family
);
1568 EXPECT_REF(font
, 1);
1569 EXPECT_REF(family
, 3);
1570 IDWriteFontFamily_Release(family2
);
1572 hr
= IDWriteFont_QueryInterface(font
, &IID_IDWriteFontFamily
, (void**)&family2
);
1573 EXPECT_HR(hr
, E_NOINTERFACE
);
1574 ok(family2
== NULL
, "got %p\n", family2
);
1576 hr
= IDWriteFont_GetFontFamily(font2
, &family2
);
1577 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1578 ok(family2
!= family
, "got %p, %p\n", family2
, family
);
1581 hr
= IDWriteFontFamily_GetFontCollection(family
, &collection
);
1582 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1585 hr
= IDWriteFontFamily_GetFontCollection(family2
, &collection2
);
1586 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1587 ok(collection
== collection2
, "got %p, %p\n", collection
, collection2
);
1588 ok(collection
== syscoll
, "got %p, %p\n", collection
, syscoll
);
1590 IDWriteFont_Release(font
);
1591 IDWriteFont_Release(font2
);
1593 hr
= IDWriteFontFamily_QueryInterface(family
, &IID_IDWriteFontFamily1
, (void**)&family1
);
1595 IDWriteFontFaceReference
*ref
, *ref1
;
1596 IDWriteFontList1
*fontlist1
;
1597 IDWriteFontList2
*fontlist2
;
1598 IDWriteFontList
*fontlist
;
1599 IDWriteFont3
*font3
;
1600 IDWriteFont1
*font1
;
1602 font3
= (void*)0xdeadbeef;
1603 hr
= IDWriteFontFamily1_GetFont(family1
, ~0u, &font3
);
1604 ok(hr
== E_FAIL
, "got 0x%08x\n", hr
);
1605 ok(font3
== NULL
, "got %p\n", font3
);
1607 hr
= IDWriteFontFamily1_GetFont(family1
, 0, &font3
);
1608 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1610 hr
= IDWriteFont3_QueryInterface(font3
, &IID_IDWriteFont
, (void**)&font
);
1611 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1612 IDWriteFont_Release(font
);
1614 hr
= IDWriteFont3_QueryInterface(font3
, &IID_IDWriteFont1
, (void**)&font1
);
1615 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1616 IDWriteFont1_Release(font1
);
1618 hr
= IDWriteFontFamily1_QueryInterface(family1
, &IID_IDWriteFontList1
, (void **)&fontlist1
);
1619 ok(hr
== S_OK
|| broken(hr
== E_NOINTERFACE
), "Failed to get interface, hr %#x.\n", hr
);
1621 hr
= IDWriteFontFamily1_QueryInterface(family1
, &IID_IDWriteFontList
, (void **)&fontlist
);
1622 ok(hr
== S_OK
, "Unexpected hr %#x.\n", hr
);
1623 ok(fontlist
== (IDWriteFontList
*)fontlist1
, "Unexpected interface pointer.\n");
1624 ok(fontlist
!= (IDWriteFontList
*)family1
, "Unexpected interface pointer.\n");
1625 ok(fontlist
!= (IDWriteFontList
*)family
, "Unexpected interface pointer.\n");
1627 if (SUCCEEDED(IDWriteFontFamily1_QueryInterface(family1
, &IID_IDWriteFontList2
, (void **)&fontlist2
)))
1629 IDWriteFontSet1
*fontset
= NULL
, *fontset2
= NULL
;
1631 ok(fontlist
== (IDWriteFontList
*)fontlist2
, "Unexpected interface pointer.\n");
1633 hr
= IDWriteFontList2_GetFontSet(fontlist2
, &fontset
);
1634 ok(hr
== S_OK
, "Unexpected hr %#x.\n", hr
);
1636 hr
= IDWriteFontList2_GetFontSet(fontlist2
, &fontset2
);
1637 ok(hr
== S_OK
, "Unexpected hr %#x.\n", hr
);
1638 ok(fontset
!= fontset2
, "Unexpected instance.\n");
1640 IDWriteFontSet1_Release(fontset2
);
1641 IDWriteFontSet1_Release(fontset
);
1643 IDWriteFontList2_Release(fontlist2
);
1646 win_skip("IDWriteFontList2 is not supported.\n");
1648 IDWriteFontList1_Release(fontlist1
);
1649 IDWriteFontList_Release(fontlist
);
1652 hr
= IDWriteFontFamily1_QueryInterface(family1
, &IID_IDWriteFontList
, (void**)&fontlist
);
1653 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1654 IDWriteFontList_Release(fontlist
);
1656 IDWriteFont3_Release(font3
);
1658 hr
= IDWriteFontFamily1_GetFontFaceReference(family1
, 0, &ref
);
1659 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1661 hr
= IDWriteFontFamily1_GetFontFaceReference(family1
, 0, &ref1
);
1662 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1663 ok(ref
!= ref1
, "got %p, %p\n", ref
, ref1
);
1665 IDWriteFontFaceReference_Release(ref
);
1666 IDWriteFontFaceReference_Release(ref1
);
1668 IDWriteFontFamily1_Release(family1
);
1671 win_skip("IDWriteFontFamily1 is not supported.\n");
1673 /* IDWriteFontCollection2::GetFontFamily() */
1674 if (SUCCEEDED(IDWriteFontCollection_QueryInterface(syscoll
, &IID_IDWriteFontCollection2
, (void **)&coll2
)))
1676 IDWriteFontFamily2
*family2
;
1678 count
= IDWriteFontCollection2_GetFontFamilyCount(coll2
);
1679 ok(!!count
, "Unexpected family count.\n");
1681 family2
= (void *)0xdeadbeef;
1682 hr
= IDWriteFontCollection2_GetFontFamily(coll2
, count
, &family2
);
1683 ok(hr
== E_FAIL
, "Unexpected hr %#x.\n", hr
);
1684 ok(!family2
, "Unexpected pointer.\n");
1686 hr
= IDWriteFontCollection2_GetFontFamily(coll2
, 0, &family2
);
1687 ok(hr
== S_OK
, "Failed to get family, hr %#x.\n", hr
);
1688 IDWriteFontFamily2_Release(family2
);
1690 IDWriteFontCollection2_Release(coll2
);
1693 win_skip("IDWriteFontCollection2 is not supported.\n");
1695 IDWriteFontCollection_Release(syscoll
);
1696 IDWriteFontCollection_Release(collection2
);
1697 IDWriteFontCollection_Release(collection
);
1698 IDWriteFontFamily_Release(family2
);
1699 IDWriteFontFamily_Release(family
);
1700 IDWriteGdiInterop_Release(interop
);
1701 ref
= IDWriteFactory_Release(factory
);
1702 ok(ref
== 0, "factory not released, %u\n", ref
);
1705 static void test_GetFamilyNames(void)
1707 IDWriteLocalizedStrings
*names
, *names2
;
1708 IDWriteFontFace3
*fontface3
;
1709 IDWriteGdiInterop
*interop
;
1710 IDWriteFontFamily
*family
;
1711 IDWriteFontFace
*fontface
;
1712 IDWriteFactory
*factory
;
1720 factory
= create_factory();
1722 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop
);
1723 EXPECT_HR(hr
, S_OK
);
1725 memset(&logfont
, 0, sizeof(logfont
));
1726 logfont
.lfHeight
= 12;
1727 logfont
.lfWidth
= 12;
1728 logfont
.lfWeight
= FW_NORMAL
;
1729 logfont
.lfItalic
= 1;
1730 lstrcpyW(logfont
.lfFaceName
, L
"Tahoma");
1732 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font
);
1733 EXPECT_HR(hr
, S_OK
);
1735 hr
= IDWriteFont_GetFontFamily(font
, &family
);
1736 EXPECT_HR(hr
, S_OK
);
1738 if (0) /* crashes on native */
1739 hr
= IDWriteFontFamily_GetFamilyNames(family
, NULL
);
1741 hr
= IDWriteFontFamily_GetFamilyNames(family
, &names
);
1742 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1743 EXPECT_REF(names
, 1);
1745 hr
= IDWriteFontFamily_GetFamilyNames(family
, &names2
);
1746 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1747 EXPECT_REF(names2
, 1);
1748 ok(names
!= names2
, "got %p, was %p\n", names2
, names
);
1750 IDWriteLocalizedStrings_Release(names2
);
1752 /* GetStringLength */
1753 if (0) /* crashes on native */
1754 hr
= IDWriteLocalizedStrings_GetStringLength(names
, 0, NULL
);
1757 hr
= IDWriteLocalizedStrings_GetStringLength(names
, 10, &len
);
1758 ok(hr
== E_FAIL
, "got 0x%08x\n", hr
);
1759 ok(len
== (UINT32
)-1, "got %u\n", len
);
1762 hr
= IDWriteLocalizedStrings_GetStringLength(names
, 0, &len
);
1763 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1764 ok(len
> 0, "got %u\n", len
);
1767 hr
= IDWriteLocalizedStrings_GetString(names
, 0, NULL
, 0);
1768 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
1770 hr
= IDWriteLocalizedStrings_GetString(names
, 10, NULL
, 0);
1771 ok(FAILED(hr
), "Unexpected hr %#x.\n", hr
);
1774 hr
= IDWriteLocalizedStrings_GetString(names
, 0, NULL
, 100);
1777 hr
= IDWriteLocalizedStrings_GetString(names
, 10, buffer
, 100);
1778 ok(hr
== E_FAIL
, "got 0x%08x\n", hr
);
1779 ok(buffer
[0] == 0, "got %x\n", buffer
[0]);
1782 hr
= IDWriteLocalizedStrings_GetString(names
, 0, buffer
, len
-1);
1783 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
1784 ok(buffer
[0] == 0 || broken(buffer
[0] == 'T'), "Unexpected buffer contents, %#x.\n", buffer
[0]);
1787 hr
= IDWriteLocalizedStrings_GetString(names
, 0, buffer
, len
);
1788 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
1789 ok(buffer
[0] == 0 || broken(buffer
[0] == 'T'), "Unexpected buffer contents, %#x.\n", buffer
[0]);
1792 hr
= IDWriteLocalizedStrings_GetString(names
, 0, buffer
, len
+1);
1793 ok(hr
== S_OK
, "Failed to get a string, hr %#x.\n", hr
);
1794 ok(!lstrcmpW(buffer
, L
"Tahoma"), "Unexpected family name %s.\n", wine_dbgstr_w(buffer
));
1796 IDWriteLocalizedStrings_Release(names
);
1798 /* GetFamilyNames() on font face */
1799 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
1800 ok(hr
== S_OK
, "Failed to create fontface, hr %#x.\n", hr
);
1802 if (SUCCEEDED(IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace3
, (void **)&fontface3
)))
1804 hr
= IDWriteFontFace3_GetFamilyNames(fontface3
, &names
);
1805 ok(hr
== S_OK
, "Failed to get family names, hr %#x.\n", hr
);
1808 hr
= IDWriteLocalizedStrings_GetString(names
, 0, buffer
, len
+1);
1809 ok(hr
== S_OK
, "Failed to get a string, hr %#x.\n", hr
);
1810 ok(!lstrcmpW(buffer
, L
"Tahoma"), "Unexpected family name %s.\n", wine_dbgstr_w(buffer
));
1812 IDWriteLocalizedStrings_Release(names
);
1813 IDWriteFontFace3_Release(fontface3
);
1816 win_skip("IDWriteFontFace3::GetFamilyNames() is not supported.\n");
1818 IDWriteFontFace_Release(fontface
);
1820 IDWriteFontFamily_Release(family
);
1821 IDWriteFont_Release(font
);
1822 IDWriteGdiInterop_Release(interop
);
1823 ref
= IDWriteFactory_Release(factory
);
1824 ok(ref
== 0, "factory not released, %u\n", ref
);
1827 static void test_CreateFontFace(void)
1829 IDWriteFontFace
*fontface
, *fontface2
;
1830 IDWriteFontCollection
*collection
;
1831 DWRITE_FONT_FILE_TYPE file_type
;
1832 DWRITE_FONT_FACE_TYPE face_type
;
1833 IDWriteFontFace5
*fontface5
;
1834 IDWriteGdiInterop
*interop
;
1835 IDWriteFont
*font
, *font2
;
1836 IDWriteFontFamily
*family
;
1837 IDWriteFactory
*factory
;
1838 IDWriteFontFile
*file
;
1839 BOOL supported
, ret
;
1846 factory
= create_factory();
1848 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop
);
1849 EXPECT_HR(hr
, S_OK
);
1851 memset(&logfont
, 0, sizeof(logfont
));
1852 logfont
.lfHeight
= 12;
1853 logfont
.lfWidth
= 12;
1854 logfont
.lfWeight
= FW_NORMAL
;
1855 logfont
.lfItalic
= 1;
1856 lstrcpyW(logfont
.lfFaceName
, L
"Tahoma");
1859 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font
);
1860 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1863 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font2
);
1864 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1865 ok(font
!= font2
, "got %p, %p\n", font
, font2
);
1867 hr
= IDWriteFont_QueryInterface(font
, &IID_IDWriteFontFace
, (void**)&fontface
);
1868 ok(hr
== E_NOINTERFACE
, "got 0x%08x\n", hr
);
1870 if (0) /* crashes on native */
1871 hr
= IDWriteFont_CreateFontFace(font
, NULL
);
1874 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
1875 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1878 hr
= IDWriteFont_CreateFontFace(font
, &fontface2
);
1879 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1880 ok(fontface
== fontface2
, "got %p, was %p\n", fontface2
, fontface
);
1881 IDWriteFontFace_Release(fontface2
);
1884 hr
= IDWriteFont_CreateFontFace(font2
, &fontface2
);
1885 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1886 ok(fontface
== fontface2
, "got %p, was %p\n", fontface2
, fontface
);
1887 IDWriteFontFace_Release(fontface2
);
1889 IDWriteFont_Release(font2
);
1890 IDWriteFont_Release(font
);
1892 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFont
, (void**)&font
);
1893 ok(hr
== E_NOINTERFACE
|| broken(hr
== E_NOTIMPL
), "got 0x%08x\n", hr
);
1895 IDWriteFontFace_Release(fontface
);
1896 IDWriteGdiInterop_Release(interop
);
1898 /* Create from system collection */
1899 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &collection
, FALSE
);
1900 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1902 hr
= IDWriteFontCollection_GetFontFamily(collection
, 0, &family
);
1903 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1906 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
,
1907 DWRITE_FONT_STRETCH_NORMAL
, DWRITE_FONT_STYLE_NORMAL
, &font
);
1908 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1911 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
,
1912 DWRITE_FONT_STRETCH_NORMAL
, DWRITE_FONT_STYLE_NORMAL
, &font2
);
1913 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1914 ok(font
!= font2
, "got %p, %p\n", font
, font2
);
1917 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
1918 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1921 hr
= IDWriteFont_CreateFontFace(font2
, &fontface2
);
1922 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1923 ok(fontface
== fontface2
, "got %p, was %p\n", fontface2
, fontface
);
1925 /* Trivial equality test */
1926 if (SUCCEEDED(IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace5
, (void **)&fontface5
)))
1928 ret
= IDWriteFontFace5_Equals(fontface5
, fontface2
);
1929 ok(ret
, "Unexpected result %d.\n", ret
);
1930 IDWriteFontFace5_Release(fontface5
);
1933 IDWriteFontFace_Release(fontface
);
1934 IDWriteFontFace_Release(fontface2
);
1935 IDWriteFont_Release(font2
);
1936 IDWriteFont_Release(font
);
1937 IDWriteFontFamily_Release(family
);
1938 IDWriteFontCollection_Release(collection
);
1939 ref
= IDWriteFactory_Release(factory
);
1940 ok(ref
== 0, "factory not released, %u.\n", ref
);
1942 /* IDWriteFactory::CreateFontFace() */
1943 path
= create_testfontfile(test_fontfile
);
1944 factory
= create_factory();
1946 hr
= IDWriteFactory_CreateFontFileReference(factory
, path
, NULL
, &file
);
1947 ok(hr
== S_OK
, "got 0x%08x\n",hr
);
1950 file_type
= DWRITE_FONT_FILE_TYPE_UNKNOWN
;
1951 face_type
= DWRITE_FONT_FACE_TYPE_CFF
;
1953 hr
= IDWriteFontFile_Analyze(file
, &supported
, &file_type
, &face_type
, &count
);
1954 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1955 ok(supported
== TRUE
, "got %i\n", supported
);
1956 ok(file_type
== DWRITE_FONT_FILE_TYPE_TRUETYPE
, "got %i\n", file_type
);
1957 ok(face_type
== DWRITE_FONT_FACE_TYPE_TRUETYPE
, "got %i\n", face_type
);
1958 ok(count
== 1, "got %i\n", count
);
1960 /* invalid simulation flags */
1961 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_CFF
, 1, &file
, 0, ~0u, &fontface
);
1962 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1964 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_CFF
, 1, &file
, 0, 0xf, &fontface
);
1965 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1967 /* try mismatching face type, the one that's not supported */
1968 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_CFF
, 1, &file
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &fontface
);
1969 ok(hr
== DWRITE_E_FILEFORMAT
, "got 0x%08x\n", hr
);
1971 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_OPENTYPE_COLLECTION
, 1, &file
, 0,
1972 DWRITE_FONT_SIMULATIONS_NONE
, &fontface
);
1973 ok(hr
== DWRITE_E_FILEFORMAT
|| broken(hr
== E_FAIL
) /* < win10 */, "got 0x%08x\n", hr
);
1975 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_RAW_CFF
, 1, &file
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &fontface
);
1977 ok(hr
== DWRITE_E_UNSUPPORTEDOPERATION
|| broken(hr
== E_INVALIDARG
) /* older versions */, "got 0x%08x\n", hr
);
1979 fontface
= (void*)0xdeadbeef;
1980 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_TYPE1
, 1, &file
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &fontface
);
1981 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1982 ok(fontface
== NULL
, "got %p\n", fontface
);
1984 fontface
= (void*)0xdeadbeef;
1985 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_VECTOR
, 1, &file
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &fontface
);
1986 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1987 ok(fontface
== NULL
, "got %p\n", fontface
);
1989 fontface
= (void*)0xdeadbeef;
1990 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_BITMAP
, 1, &file
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &fontface
);
1991 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1992 ok(fontface
== NULL
, "got %p\n", fontface
);
1995 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_UNKNOWN
, 1, &file
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &fontface
);
1997 ok(hr
== S_OK
|| broken(hr
== E_INVALIDARG
) /* < win10 */, "got 0x%08x\n", hr
);
1999 ok(fontface
!= NULL
, "got %p\n", fontface
);
2000 face_type
= IDWriteFontFace_GetType(fontface
);
2001 ok(face_type
== DWRITE_FONT_FACE_TYPE_TRUETYPE
, "got %d\n", face_type
);
2002 IDWriteFontFace_Release(fontface
);
2005 IDWriteFontFile_Release(file
);
2006 ref
= IDWriteFactory_Release(factory
);
2007 ok(ref
== 0, "factory not released, %u.\n", ref
);
2008 DELETE_FONTFILE(path
);
2011 static void get_expected_font_metrics(IDWriteFontFace
*fontface
, DWRITE_FONT_METRICS1
*metrics
)
2013 void *os2_context
, *head_context
, *post_context
, *hhea_context
;
2014 const TT_OS2_V2
*tt_os2
;
2015 const TT_HEAD
*tt_head
;
2016 const TT_POST
*tt_post
;
2017 const TT_HHEA
*tt_hhea
;
2022 memset(metrics
, 0, sizeof(*metrics
));
2024 hr
= IDWriteFontFace_TryGetFontTable(fontface
, MS_OS2_TAG
, (const void **)&tt_os2
, &size
, &os2_context
, &exists
);
2025 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2026 hr
= IDWriteFontFace_TryGetFontTable(fontface
, MS_HEAD_TAG
, (const void**)&tt_head
, &size
, &head_context
, &exists
);
2027 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2028 hr
= IDWriteFontFace_TryGetFontTable(fontface
, MS_HHEA_TAG
, (const void**)&tt_hhea
, &size
, &hhea_context
, &exists
);
2029 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2030 hr
= IDWriteFontFace_TryGetFontTable(fontface
, MS_POST_TAG
, (const void**)&tt_post
, &size
, &post_context
, &exists
);
2031 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2034 metrics
->designUnitsPerEm
= GET_BE_WORD(tt_head
->unitsPerEm
);
2035 metrics
->glyphBoxLeft
= GET_BE_WORD(tt_head
->xMin
);
2036 metrics
->glyphBoxTop
= GET_BE_WORD(tt_head
->yMax
);
2037 metrics
->glyphBoxRight
= GET_BE_WORD(tt_head
->xMax
);
2038 metrics
->glyphBoxBottom
= GET_BE_WORD(tt_head
->yMin
);
2042 if (GET_BE_WORD(tt_os2
->fsSelection
) & OS2_FSSELECTION_USE_TYPO_METRICS
) {
2043 SHORT descent
= GET_BE_WORD(tt_os2
->sTypoDescender
);
2044 metrics
->ascent
= GET_BE_WORD(tt_os2
->sTypoAscender
);
2045 metrics
->descent
= descent
< 0 ? -descent
: 0;
2046 metrics
->lineGap
= GET_BE_WORD(tt_os2
->sTypoLineGap
);
2047 metrics
->hasTypographicMetrics
= TRUE
;
2050 metrics
->ascent
= GET_BE_WORD(tt_os2
->usWinAscent
);
2051 /* Some fonts have usWinDescent value stored as signed short, which could be wrongly
2052 interpreted as large unsigned value. */
2053 metrics
->descent
= abs((SHORT
)GET_BE_WORD(tt_os2
->usWinDescent
));
2056 SHORT descender
= (SHORT
)GET_BE_WORD(tt_hhea
->descender
);
2059 linegap
= GET_BE_WORD(tt_hhea
->ascender
) + abs(descender
) + GET_BE_WORD(tt_hhea
->linegap
) -
2060 metrics
->ascent
- metrics
->descent
;
2061 metrics
->lineGap
= linegap
> 0 ? linegap
: 0;
2065 metrics
->strikethroughPosition
= GET_BE_WORD(tt_os2
->yStrikeoutPosition
);
2066 metrics
->strikethroughThickness
= GET_BE_WORD(tt_os2
->yStrikeoutSize
);
2068 metrics
->subscriptPositionX
= GET_BE_WORD(tt_os2
->ySubscriptXOffset
);
2069 metrics
->subscriptPositionY
= -GET_BE_WORD(tt_os2
->ySubscriptYOffset
);
2070 metrics
->subscriptSizeX
= GET_BE_WORD(tt_os2
->ySubscriptXSize
);
2071 metrics
->subscriptSizeY
= GET_BE_WORD(tt_os2
->ySubscriptYSize
);
2072 metrics
->superscriptPositionX
= GET_BE_WORD(tt_os2
->ySuperscriptXOffset
);
2073 metrics
->superscriptPositionY
= GET_BE_WORD(tt_os2
->ySuperscriptYOffset
);
2074 metrics
->superscriptSizeX
= GET_BE_WORD(tt_os2
->ySuperscriptXSize
);
2075 metrics
->superscriptSizeY
= GET_BE_WORD(tt_os2
->ySuperscriptYSize
);
2078 metrics
->strikethroughPosition
= metrics
->designUnitsPerEm
/ 3;
2080 metrics
->ascent
= GET_BE_WORD(tt_hhea
->ascender
);
2081 metrics
->descent
= abs((SHORT
)GET_BE_WORD(tt_hhea
->descender
));
2086 metrics
->underlinePosition
= GET_BE_WORD(tt_post
->underlinePosition
);
2087 metrics
->underlineThickness
= GET_BE_WORD(tt_post
->underlineThickness
);
2090 if (metrics
->underlineThickness
== 0)
2091 metrics
->underlineThickness
= metrics
->designUnitsPerEm
/ 14;
2092 if (metrics
->strikethroughThickness
== 0)
2093 metrics
->strikethroughThickness
= metrics
->underlineThickness
;
2096 IDWriteFontFace_ReleaseFontTable(fontface
, os2_context
);
2098 IDWriteFontFace_ReleaseFontTable(fontface
, head_context
);
2100 IDWriteFontFace_ReleaseFontTable(fontface
, hhea_context
);
2102 IDWriteFontFace_ReleaseFontTable(fontface
, post_context
);
2105 static void check_font_metrics(const WCHAR
*nameW
, IDWriteFontFace
*fontface
, const DWRITE_FONT_METRICS1
*expected
)
2107 IDWriteFontFace1
*fontface1
= NULL
;
2108 DWRITE_FONT_METRICS1 metrics
;
2112 has_metrics1
= SUCCEEDED(IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void **)&fontface1
));
2113 simulations
= IDWriteFontFace_GetSimulations(fontface
);
2116 IDWriteFontFace1_GetMetrics(fontface1
, &metrics
);
2117 IDWriteFontFace1_Release(fontface1
);
2120 IDWriteFontFace_GetMetrics(fontface
, (DWRITE_FONT_METRICS
*)&metrics
);
2122 ok(metrics
.designUnitsPerEm
== expected
->designUnitsPerEm
, "font %s: designUnitsPerEm %u, expected %u\n",
2123 wine_dbgstr_w(nameW
), metrics
.designUnitsPerEm
, expected
->designUnitsPerEm
);
2124 ok(metrics
.ascent
== expected
->ascent
, "font %s: ascent %u, expected %u\n", wine_dbgstr_w(nameW
), metrics
.ascent
,
2126 ok(metrics
.descent
== expected
->descent
, "font %s: descent %u, expected %u\n", wine_dbgstr_w(nameW
),
2127 metrics
.descent
, expected
->descent
);
2128 ok(metrics
.lineGap
== expected
->lineGap
, "font %s: lineGap %d, expected %d\n", wine_dbgstr_w(nameW
),
2129 metrics
.lineGap
, expected
->lineGap
);
2130 ok(metrics
.underlinePosition
== expected
->underlinePosition
, "font %s: underlinePosition %d, expected %d\n",
2131 wine_dbgstr_w(nameW
), metrics
.underlinePosition
, expected
->underlinePosition
);
2132 ok(metrics
.underlineThickness
== expected
->underlineThickness
, "font %s: underlineThickness %u, "
2133 "expected %u\n", wine_dbgstr_w(nameW
), metrics
.underlineThickness
, expected
->underlineThickness
);
2134 ok(metrics
.strikethroughPosition
== expected
->strikethroughPosition
, "font %s: strikethroughPosition %d, expected %d\n",
2135 wine_dbgstr_w(nameW
), metrics
.strikethroughPosition
, expected
->strikethroughPosition
);
2136 ok(metrics
.strikethroughThickness
== expected
->strikethroughThickness
, "font %s: strikethroughThickness %u, "
2137 "expected %u\n", wine_dbgstr_w(nameW
), metrics
.strikethroughThickness
, expected
->strikethroughThickness
);
2140 /* For simulated faces metrics are adjusted. Enable tests when exact pattern is understood. */
2141 if (simulations
& DWRITE_FONT_SIMULATIONS_OBLIQUE
)
2144 ok(metrics
.hasTypographicMetrics
== expected
->hasTypographicMetrics
, "font %s: hasTypographicMetrics %d, "
2145 "expected %d\n", wine_dbgstr_w(nameW
), metrics
.hasTypographicMetrics
, expected
->hasTypographicMetrics
);
2146 ok(metrics
.glyphBoxLeft
== expected
->glyphBoxLeft
, "font %s: glyphBoxLeft %d, expected %d\n",
2147 wine_dbgstr_w(nameW
), metrics
.glyphBoxLeft
, expected
->glyphBoxLeft
);
2148 ok(metrics
.glyphBoxTop
== expected
->glyphBoxTop
, "font %s: glyphBoxTop %d, expected %d\n",
2149 wine_dbgstr_w(nameW
), metrics
.glyphBoxTop
, expected
->glyphBoxTop
);
2150 ok(metrics
.glyphBoxRight
== expected
->glyphBoxRight
, "font %s: glyphBoxRight %d, expected %d\n",
2151 wine_dbgstr_w(nameW
), metrics
.glyphBoxRight
, expected
->glyphBoxRight
);
2152 ok(metrics
.glyphBoxBottom
== expected
->glyphBoxBottom
, "font %s: glyphBoxBottom %d, expected %d\n",
2153 wine_dbgstr_w(nameW
), metrics
.glyphBoxBottom
, expected
->glyphBoxBottom
);
2155 ok(metrics
.subscriptPositionX
== expected
->subscriptPositionX
, "font %s: subscriptPositionX %d, expected %d\n",
2156 wine_dbgstr_w(nameW
), metrics
.subscriptPositionX
, expected
->subscriptPositionX
);
2157 ok(metrics
.subscriptPositionY
== expected
->subscriptPositionY
, "font %s: subscriptPositionY %d, expected %d\n",
2158 wine_dbgstr_w(nameW
), metrics
.subscriptPositionY
, expected
->subscriptPositionY
);
2159 ok(metrics
.subscriptSizeX
== expected
->subscriptSizeX
, "font %s: subscriptSizeX %d, expected %d\n",
2160 wine_dbgstr_w(nameW
), metrics
.subscriptSizeX
, expected
->subscriptSizeX
);
2161 ok(metrics
.subscriptSizeY
== expected
->subscriptSizeY
, "font %s: subscriptSizeY %d, expected %d\n",
2162 wine_dbgstr_w(nameW
), metrics
.subscriptSizeY
, expected
->subscriptSizeY
);
2163 ok(metrics
.superscriptPositionX
== expected
->superscriptPositionX
, "font %s: superscriptPositionX %d, expected %d\n",
2164 wine_dbgstr_w(nameW
), metrics
.superscriptPositionX
, expected
->superscriptPositionX
);
2165 ok(metrics
.superscriptPositionY
== expected
->superscriptPositionY
, "font %s: superscriptPositionY %d, expected %d\n",
2166 wine_dbgstr_w(nameW
), metrics
.superscriptPositionY
, expected
->superscriptPositionY
);
2167 ok(metrics
.superscriptSizeX
== expected
->superscriptSizeX
, "font %s: superscriptSizeX %d, expected %d\n",
2168 wine_dbgstr_w(nameW
), metrics
.superscriptSizeX
, expected
->superscriptSizeX
);
2169 ok(metrics
.superscriptSizeY
== expected
->superscriptSizeY
, "font %s: superscriptSizeY %d, expected %d\n",
2170 wine_dbgstr_w(nameW
), metrics
.superscriptSizeY
, expected
->superscriptSizeY
);
2174 static void get_enus_string(IDWriteLocalizedStrings
*strings
, WCHAR
*buff
, UINT32 size
)
2176 BOOL exists
= FALSE
;
2180 hr
= IDWriteLocalizedStrings_FindLocaleName(strings
, L
"en-us", &index
, &exists
);
2181 ok(hr
== S_OK
, "Unexpected hr %#x.\n", hr
);
2184 hr
= IDWriteLocalizedStrings_GetString(strings
, index
, buff
, size
);
2185 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2188 static void test_GetMetrics(void)
2190 DWRITE_FONT_METRICS metrics
, metrics2
;
2191 IDWriteFontCollection
*syscollection
;
2192 IDWriteGdiInterop
*interop
;
2193 IDWriteFontFace
*fontface
;
2194 IDWriteFactory
*factory
;
2195 OUTLINETEXTMETRICW otm
;
2196 IDWriteFontFile
*file
;
2197 IDWriteFont1
*font1
;
2207 factory
= create_factory();
2209 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop
);
2210 EXPECT_HR(hr
, S_OK
);
2212 memset(&logfont
, 0, sizeof(logfont
));
2213 logfont
.lfHeight
= 12;
2214 logfont
.lfWidth
= 12;
2215 logfont
.lfWeight
= FW_NORMAL
;
2216 logfont
.lfItalic
= 1;
2217 lstrcpyW(logfont
.lfFaceName
, L
"Tahoma");
2219 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font
);
2220 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2222 hfont
= CreateFontIndirectW(&logfont
);
2223 hdc
= CreateCompatibleDC(0);
2224 SelectObject(hdc
, hfont
);
2226 otm
.otmSize
= sizeof(otm
);
2227 ret
= GetOutlineTextMetricsW(hdc
, otm
.otmSize
, &otm
);
2228 ok(ret
, "got %d\n", ret
);
2230 DeleteObject(hfont
);
2232 if (0) /* crashes on native */
2233 IDWriteFont_GetMetrics(font
, NULL
);
2235 memset(&metrics
, 0, sizeof(metrics
));
2236 IDWriteFont_GetMetrics(font
, &metrics
);
2238 ok(metrics
.designUnitsPerEm
!= 0, "designUnitsPerEm %u\n", metrics
.designUnitsPerEm
);
2239 ok(metrics
.ascent
!= 0, "ascent %u\n", metrics
.ascent
);
2240 ok(metrics
.descent
!= 0, "descent %u\n", metrics
.descent
);
2241 ok(metrics
.lineGap
== 0, "lineGap %d\n", metrics
.lineGap
);
2242 ok(metrics
.capHeight
, "capHeight %u\n", metrics
.capHeight
);
2243 ok(metrics
.xHeight
!= 0, "xHeight %u\n", metrics
.xHeight
);
2244 ok(metrics
.underlinePosition
< 0, "underlinePosition %d\n", metrics
.underlinePosition
);
2245 ok(metrics
.underlineThickness
!= 0, "underlineThickness %u\n", metrics
.underlineThickness
);
2246 ok(metrics
.strikethroughPosition
> 0, "strikethroughPosition %d\n", metrics
.strikethroughPosition
);
2247 ok(metrics
.strikethroughThickness
!= 0, "strikethroughThickness %u\n", metrics
.strikethroughThickness
);
2249 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
2250 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2252 memset(&metrics
, 0, sizeof(metrics
));
2253 IDWriteFontFace_GetMetrics(fontface
, &metrics
);
2255 ok(metrics
.designUnitsPerEm
!= 0, "designUnitsPerEm %u\n", metrics
.designUnitsPerEm
);
2256 ok(metrics
.ascent
!= 0, "ascent %u\n", metrics
.ascent
);
2257 ok(metrics
.descent
!= 0, "descent %u\n", metrics
.descent
);
2258 ok(metrics
.lineGap
== 0, "lineGap %d\n", metrics
.lineGap
);
2259 ok(metrics
.capHeight
, "capHeight %u\n", metrics
.capHeight
);
2260 ok(metrics
.xHeight
!= 0, "xHeight %u\n", metrics
.xHeight
);
2261 ok(metrics
.underlinePosition
< 0, "underlinePosition %d\n", metrics
.underlinePosition
);
2262 ok(metrics
.underlineThickness
!= 0, "underlineThickness %u\n", metrics
.underlineThickness
);
2263 ok(metrics
.strikethroughPosition
> 0, "strikethroughPosition %d\n", metrics
.strikethroughPosition
);
2264 ok(metrics
.strikethroughThickness
!= 0, "strikethroughThickness %u\n", metrics
.strikethroughThickness
);
2266 hr
= IDWriteFont_QueryInterface(font
, &IID_IDWriteFont1
, (void**)&font1
);
2268 DWRITE_FONT_METRICS1 metrics1
;
2269 IDWriteFontFace1
*fontface1
;
2271 memset(&metrics1
, 0, sizeof(metrics1
));
2272 IDWriteFont1_GetMetrics(font1
, &metrics1
);
2274 ok(metrics1
.designUnitsPerEm
!= 0, "designUnitsPerEm %u\n", metrics1
.designUnitsPerEm
);
2275 ok(metrics1
.ascent
!= 0, "ascent %u\n", metrics1
.ascent
);
2276 ok(metrics1
.descent
!= 0, "descent %u\n", metrics1
.descent
);
2277 ok(metrics1
.lineGap
== 0, "lineGap %d\n", metrics1
.lineGap
);
2278 ok(metrics1
.capHeight
, "capHeight %u\n", metrics1
.capHeight
);
2279 ok(metrics1
.xHeight
!= 0, "xHeight %u\n", metrics1
.xHeight
);
2280 ok(metrics1
.underlinePosition
< 0, "underlinePosition %d\n", metrics1
.underlinePosition
);
2281 ok(metrics1
.underlineThickness
!= 0, "underlineThickness %u\n", metrics1
.underlineThickness
);
2282 ok(metrics1
.strikethroughPosition
> 0, "strikethroughPosition %d\n", metrics1
.strikethroughPosition
);
2283 ok(metrics1
.strikethroughThickness
!= 0, "strikethroughThickness %u\n", metrics1
.strikethroughThickness
);
2284 ok(metrics1
.glyphBoxLeft
< 0, "glyphBoxLeft %d\n", metrics1
.glyphBoxLeft
);
2285 ok(metrics1
.glyphBoxTop
> 0, "glyphBoxTop %d\n", metrics1
.glyphBoxTop
);
2286 ok(metrics1
.glyphBoxRight
> 0, "glyphBoxRight %d\n", metrics1
.glyphBoxRight
);
2287 ok(metrics1
.glyphBoxBottom
< 0, "glyphBoxBottom %d\n", metrics1
.glyphBoxBottom
);
2288 ok(metrics1
.subscriptPositionY
< 0, "subscriptPositionY %d\n", metrics1
.subscriptPositionY
);
2289 ok(metrics1
.subscriptSizeX
> 0, "subscriptSizeX %d\n", metrics1
.subscriptSizeX
);
2290 ok(metrics1
.subscriptSizeY
> 0, "subscriptSizeY %d\n", metrics1
.subscriptSizeY
);
2291 ok(metrics1
.superscriptPositionY
> 0, "superscriptPositionY %d\n", metrics1
.superscriptPositionY
);
2292 ok(metrics1
.superscriptSizeX
> 0, "superscriptSizeX %d\n", metrics1
.superscriptSizeX
);
2293 ok(metrics1
.superscriptSizeY
> 0, "superscriptSizeY %d\n", metrics1
.superscriptSizeY
);
2294 ok(!metrics1
.hasTypographicMetrics
, "hasTypographicMetrics %d\n", metrics1
.hasTypographicMetrics
);
2296 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void**)&fontface1
);
2297 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2299 memset(&metrics1
, 0, sizeof(metrics1
));
2300 IDWriteFontFace1_GetMetrics(fontface1
, &metrics1
);
2302 ok(metrics1
.designUnitsPerEm
!= 0, "designUnitsPerEm %u\n", metrics1
.designUnitsPerEm
);
2303 ok(metrics1
.ascent
!= 0, "ascent %u\n", metrics1
.ascent
);
2304 ok(metrics1
.descent
!= 0, "descent %u\n", metrics1
.descent
);
2305 ok(metrics1
.lineGap
== 0, "lineGap %d\n", metrics1
.lineGap
);
2306 ok(metrics1
.capHeight
, "capHeight %u\n", metrics1
.capHeight
);
2307 ok(metrics1
.xHeight
!= 0, "xHeight %u\n", metrics1
.xHeight
);
2308 ok(metrics1
.underlinePosition
< 0, "underlinePosition %d\n", metrics1
.underlinePosition
);
2309 ok(metrics1
.underlineThickness
!= 0, "underlineThickness %u\n", metrics1
.underlineThickness
);
2310 ok(metrics1
.strikethroughPosition
> 0, "strikethroughPosition %d\n", metrics1
.strikethroughPosition
);
2311 ok(metrics1
.strikethroughThickness
!= 0, "strikethroughThickness %u\n", metrics1
.strikethroughThickness
);
2312 ok(metrics1
.glyphBoxLeft
< 0, "glyphBoxLeft %d\n", metrics1
.glyphBoxLeft
);
2313 ok(metrics1
.glyphBoxTop
> 0, "glyphBoxTop %d\n", metrics1
.glyphBoxTop
);
2314 ok(metrics1
.glyphBoxRight
> 0, "glyphBoxRight %d\n", metrics1
.glyphBoxRight
);
2315 ok(metrics1
.glyphBoxBottom
< 0, "glyphBoxBottom %d\n", metrics1
.glyphBoxBottom
);
2316 ok(metrics1
.subscriptPositionY
< 0, "subscriptPositionY %d\n", metrics1
.subscriptPositionY
);
2317 ok(metrics1
.subscriptSizeX
> 0, "subscriptSizeX %d\n", metrics1
.subscriptSizeX
);
2318 ok(metrics1
.subscriptSizeY
> 0, "subscriptSizeY %d\n", metrics1
.subscriptSizeY
);
2319 ok(metrics1
.superscriptPositionY
> 0, "superscriptPositionY %d\n", metrics1
.superscriptPositionY
);
2320 ok(metrics1
.superscriptSizeX
> 0, "superscriptSizeX %d\n", metrics1
.superscriptSizeX
);
2321 ok(metrics1
.superscriptSizeY
> 0, "superscriptSizeY %d\n", metrics1
.superscriptSizeY
);
2322 ok(!metrics1
.hasTypographicMetrics
, "hasTypographicMetrics %d\n", metrics1
.hasTypographicMetrics
);
2324 IDWriteFontFace1_Release(fontface1
);
2325 IDWriteFont1_Release(font1
);
2328 win_skip("DWRITE_FONT_METRICS1 is not supported.\n");
2330 IDWriteFontFace_Release(fontface
);
2331 IDWriteFont_Release(font
);
2332 IDWriteGdiInterop_Release(interop
);
2334 /* bold simulation affects returned font metrics */
2335 font
= get_tahoma_instance(factory
, DWRITE_FONT_STYLE_NORMAL
);
2337 /* create regulat Tahoma with bold simulation */
2338 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
2339 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2342 hr
= IDWriteFontFace_GetFiles(fontface
, &count
, &file
);
2343 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2345 IDWriteFontFace_GetMetrics(fontface
, &metrics
);
2346 ok(IDWriteFontFace_GetSimulations(fontface
) == 0, "wrong simulations flags\n");
2347 IDWriteFontFace_Release(fontface
);
2349 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_TRUETYPE
, 1, &file
,
2350 0, DWRITE_FONT_SIMULATIONS_BOLD
, &fontface
);
2351 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2352 IDWriteFontFace_GetMetrics(fontface
, &metrics2
);
2353 ok(IDWriteFontFace_GetSimulations(fontface
) == DWRITE_FONT_SIMULATIONS_BOLD
, "wrong simulations flags\n");
2355 ok(metrics
.ascent
== metrics2
.ascent
, "got %u, %u\n", metrics2
.ascent
, metrics
.ascent
);
2356 ok(metrics
.descent
== metrics2
.descent
, "got %u, %u\n", metrics2
.descent
, metrics
.descent
);
2357 ok(metrics
.lineGap
== metrics2
.lineGap
, "got %d, %d\n", metrics2
.lineGap
, metrics
.lineGap
);
2358 ok(metrics
.capHeight
== metrics2
.capHeight
, "got %u, %u\n", metrics2
.capHeight
, metrics
.capHeight
);
2359 ok(metrics
.xHeight
== metrics2
.xHeight
, "got %u, %u\n", metrics2
.xHeight
, metrics
.xHeight
);
2360 ok(metrics
.underlinePosition
== metrics2
.underlinePosition
, "got %d, %d\n", metrics2
.underlinePosition
,
2361 metrics
.underlinePosition
);
2362 ok(metrics
.underlineThickness
== metrics2
.underlineThickness
, "got %u, %u\n", metrics2
.underlineThickness
,
2363 metrics
.underlineThickness
);
2364 ok(metrics
.strikethroughPosition
== metrics2
.strikethroughPosition
, "got %d, %d\n", metrics2
.strikethroughPosition
,
2365 metrics
.strikethroughPosition
);
2366 ok(metrics
.strikethroughThickness
== metrics2
.strikethroughThickness
, "got %u, %u\n", metrics2
.strikethroughThickness
,
2367 metrics
.strikethroughThickness
);
2369 IDWriteFontFile_Release(file
);
2370 IDWriteFontFace_Release(fontface
);
2371 IDWriteFont_Release(font
);
2373 /* test metrics for whole system collection */
2374 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &syscollection
, FALSE
);
2375 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2376 count
= IDWriteFontCollection_GetFontFamilyCount(syscollection
);
2378 for (i
= 0; i
< count
; i
++) {
2379 DWRITE_FONT_METRICS1 expected_metrics
;
2380 WCHAR familyW
[256], faceW
[256];
2381 IDWriteLocalizedStrings
*names
;
2382 IDWriteFontFamily
*family
;
2383 UINT32 fontcount
, j
;
2386 hr
= IDWriteFontCollection_GetFontFamily(syscollection
, i
, &family
);
2387 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2389 fontcount
= IDWriteFontFamily_GetFontCount(family
);
2391 hr
= IDWriteFontFamily_GetFamilyNames(family
, &names
);
2392 ok(hr
== S_OK
, "Failed to get family names, hr %#x.\n", hr
);
2393 get_enus_string(names
, familyW
, ARRAY_SIZE(familyW
));
2394 IDWriteLocalizedStrings_Release(names
);
2396 for (j
= 0; j
< fontcount
; j
++) {
2399 hr
= IDWriteFontFamily_GetFont(family
, j
, &font
);
2400 ok(hr
== S_OK
, "Failed to get a font, hr %#x.\n", hr
);
2402 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
2403 ok(hr
== S_OK
, "Failed to create face instance, hr %#x.\n", hr
);
2405 hr
= IDWriteFont_GetFaceNames(font
, &names
);
2406 ok(hr
== S_OK
, "Failed to get face names, hr %#x.\n", hr
);
2407 get_enus_string(names
, faceW
, ARRAY_SIZE(faceW
));
2408 IDWriteLocalizedStrings_Release(names
);
2410 IDWriteFont_Release(font
);
2412 get_combined_font_name(familyW
, faceW
, nameW
);
2414 if (has_face_variations(fontface
)) {
2415 skip("%s: test does not support variable fonts.\n", wine_dbgstr_w(nameW
));
2416 IDWriteFontFace_Release(fontface
);
2420 get_expected_font_metrics(fontface
, &expected_metrics
);
2421 check_font_metrics(nameW
, fontface
, &expected_metrics
);
2423 IDWriteFontFace_Release(fontface
);
2426 IDWriteFontFamily_Release(family
);
2428 IDWriteFontCollection_Release(syscollection
);
2429 ref
= IDWriteFactory_Release(factory
);
2430 ok(ref
== 0, "factory not released, %u\n", ref
);
2433 static void test_system_fontcollection(void)
2435 IDWriteFontCollection
*collection
, *coll2
;
2436 IDWriteLocalFontFileLoader
*localloader
;
2437 IDWriteFontCollection1
*collection1
;
2438 IDWriteFontCollection2
*collection2
;
2439 IDWriteFontCollection3
*collection3
;
2440 IDWriteFactory
*factory
, *factory2
;
2441 DWRITE_FONT_FAMILY_MODEL model
;
2442 IDWriteFontFileLoader
*loader
;
2443 IDWriteFontFamily
*family
;
2444 IDWriteFontFace
*fontface
;
2445 IDWriteFactory6
*factory6
;
2446 IDWriteFontFile
*file
;
2453 factory
= create_factory();
2455 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &collection
, FALSE
);
2456 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2458 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &coll2
, FALSE
);
2459 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2460 ok(coll2
== collection
, "got %p, was %p\n", coll2
, collection
);
2461 IDWriteFontCollection_Release(coll2
);
2463 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &coll2
, TRUE
);
2464 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2465 ok(coll2
== collection
, "got %p, was %p\n", coll2
, collection
);
2466 IDWriteFontCollection_Release(coll2
);
2468 factory2
= create_factory();
2469 hr
= IDWriteFactory_GetSystemFontCollection(factory2
, &coll2
, FALSE
);
2470 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2471 ok(coll2
!= collection
, "got %p, was %p\n", coll2
, collection
);
2472 IDWriteFontCollection_Release(coll2
);
2473 IDWriteFactory_Release(factory2
);
2475 i
= IDWriteFontCollection_GetFontFamilyCount(collection
);
2476 ok(i
, "got %u\n", i
);
2479 family
= (void*)0xdeadbeef;
2480 hr
= IDWriteFontCollection_GetFontFamily(collection
, i
, &family
);
2481 ok(hr
== E_FAIL
, "got 0x%08x\n", hr
);
2482 ok(family
== NULL
, "got %p\n", family
);
2486 hr
= IDWriteFontCollection_FindFamilyName(collection
, L
"Tahoma", &i
, &ret
);
2487 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2488 ok(ret
, "got %d\n", ret
);
2489 ok(i
!= (UINT32
)-1, "got %u\n", i
);
2493 hr
= IDWriteFontCollection_FindFamilyName(collection
, L
"TAHOMA", &i
, &ret
);
2494 ok(hr
== S_OK
, "Unexpected hr %#x.\n", hr
);
2495 ok(ret
, "got %d\n", ret
);
2496 ok(i
!= (UINT32
)-1, "got %u\n", i
);
2500 hr
= IDWriteFontCollection_FindFamilyName(collection
, L
"tAhOmA", &i
, &ret
);
2501 ok(hr
== S_OK
, "Unexpected hr %#x.\n", hr
);
2502 ok(ret
, "got %d\n", ret
);
2503 ok(i
!= (UINT32
)-1, "got %u\n", i
);
2505 /* get back local file loader */
2506 hr
= IDWriteFontCollection_GetFontFamily(collection
, i
, &family
);
2507 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2509 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
,
2510 DWRITE_FONT_STRETCH_NORMAL
, DWRITE_FONT_STYLE_NORMAL
, &font
);
2511 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2512 IDWriteFontFamily_Release(family
);
2514 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
2515 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2516 IDWriteFont_Release(font
);
2520 hr
= IDWriteFontFace_GetFiles(fontface
, &i
, &file
);
2521 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2522 ok(file
!= NULL
, "got %p\n", file
);
2523 IDWriteFontFace_Release(fontface
);
2525 hr
= IDWriteFontFile_GetLoader(file
, &loader
);
2526 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2527 IDWriteFontFile_Release(file
);
2529 hr
= IDWriteFontFileLoader_QueryInterface(loader
, &IID_IDWriteLocalFontFileLoader
, (void**)&localloader
);
2530 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2531 IDWriteLocalFontFileLoader_Release(localloader
);
2533 /* local loader is not registered by default */
2534 hr
= IDWriteFactory_RegisterFontFileLoader(factory
, loader
);
2535 ok(hr
== S_OK
|| broken(hr
== DWRITE_E_ALREADYREGISTERED
), "got 0x%08x\n", hr
);
2536 hr
= IDWriteFactory_UnregisterFontFileLoader(factory
, loader
);
2537 ok(hr
== S_OK
|| broken(hr
== E_INVALIDARG
), "got 0x%08x\n", hr
);
2539 /* try with a different factory */
2540 factory2
= create_factory();
2541 hr
= IDWriteFactory_RegisterFontFileLoader(factory2
, loader
);
2542 ok(hr
== S_OK
|| broken(hr
== DWRITE_E_ALREADYREGISTERED
), "got 0x%08x\n", hr
);
2543 hr
= IDWriteFactory_RegisterFontFileLoader(factory2
, loader
);
2544 ok(hr
== DWRITE_E_ALREADYREGISTERED
, "got 0x%08x\n", hr
);
2545 hr
= IDWriteFactory_UnregisterFontFileLoader(factory2
, loader
);
2546 ok(hr
== S_OK
|| broken(hr
== E_INVALIDARG
), "got 0x%08x\n", hr
);
2547 hr
= IDWriteFactory_UnregisterFontFileLoader(factory2
, loader
);
2548 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
2549 IDWriteFactory_Release(factory2
);
2551 IDWriteFontFileLoader_Release(loader
);
2555 hr
= IDWriteFontCollection_FindFamilyName(collection
, L
"Blah!", &i
, &ret
);
2556 ok(hr
== S_OK
, "Unexpected hr %#x.\n", hr
);
2557 ok(!ret
, "got %d\n", ret
);
2558 ok(i
== (UINT32
)-1, "got %u\n", i
);
2560 hr
= IDWriteFontCollection_QueryInterface(collection
, &IID_IDWriteFontCollection1
, (void**)&collection1
);
2562 IDWriteFontSet
*fontset
, *fontset2
;
2563 IDWriteFontFamily1
*family1
;
2564 IDWriteFactory3
*factory3
;
2566 hr
= IDWriteFontCollection1_QueryInterface(collection1
, &IID_IDWriteFontCollection
, (void**)&coll2
);
2567 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2568 ok(coll2
== collection
, "got %p, %p\n", collection
, coll2
);
2569 IDWriteFontCollection_Release(coll2
);
2571 family1
= (void*)0xdeadbeef;
2572 hr
= IDWriteFontCollection1_GetFontFamily(collection1
, ~0u, &family1
);
2573 ok(hr
== E_FAIL
, "got 0x%08x\n", hr
);
2574 ok(family1
== NULL
, "got %p\n", family1
);
2576 hr
= IDWriteFontCollection1_GetFontFamily(collection1
, 0, &family1
);
2577 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2578 IDWriteFontFamily1_Release(family1
);
2580 /* system fontset */
2581 EXPECT_REF(collection1
, 2);
2582 EXPECT_REF(factory
, 2);
2583 hr
= IDWriteFontCollection1_GetFontSet(collection1
, &fontset
);
2585 ok(hr
== S_OK
, "Failed to get fontset, hr %#x.\n", hr
);
2587 EXPECT_REF(collection1
, 2);
2588 EXPECT_REF(factory
, 2);
2589 EXPECT_REF(fontset
, 1);
2591 hr
= IDWriteFontCollection1_GetFontSet(collection1
, &fontset2
);
2592 ok(hr
== S_OK
, "Failed to get fontset, hr %#x.\n", hr
);
2593 ok(fontset
!= fontset2
, "Expected new fontset instance.\n");
2594 EXPECT_REF(fontset2
, 1);
2595 IDWriteFontSet_Release(fontset2
);
2597 hr
= IDWriteFactory_QueryInterface(factory
, &IID_IDWriteFactory3
, (void **)&factory3
);
2598 ok(hr
== S_OK
, "Failed to get IDWriteFactory3 interface, hr %#x.\n", hr
);
2600 EXPECT_REF(factory
, 3);
2601 hr
= IDWriteFactory3_GetSystemFontSet(factory3
, &fontset2
);
2602 ok(hr
== S_OK
, "Failed to get system font set, hr %#x.\n", hr
);
2603 ok(fontset
!= fontset2
, "Expected new fontset instance.\n");
2604 EXPECT_REF(fontset2
, 1);
2605 EXPECT_REF(factory
, 4);
2607 IDWriteFontSet_Release(fontset2
);
2608 IDWriteFontSet_Release(fontset
);
2610 IDWriteFactory3_Release(factory3
);
2612 IDWriteFontCollection1_Release(collection1
);
2615 win_skip("IDWriteFontCollection1 is not supported.\n");
2617 hr
= IDWriteFontCollection_QueryInterface(collection
, &IID_IDWriteFontCollection3
, (void **)&collection3
);
2622 event
= IDWriteFontCollection3_GetExpirationEvent(collection3
);
2624 ok(!!event
, "Expected event handle.\n");
2626 model
= IDWriteFontCollection3_GetFontFamilyModel(collection3
);
2627 ok(model
== DWRITE_FONT_FAMILY_MODEL_WEIGHT_STRETCH_STYLE
, "Unexpected model.\n");
2629 IDWriteFontCollection3_Release(collection3
);
2632 win_skip("IDWriteFontCollection3 is not supported.\n");
2634 /* With specified family model. */
2635 hr
= IDWriteFactory_QueryInterface(factory
, &IID_IDWriteFactory6
, (void **)&factory6
);
2638 IDWriteFontCollection2
*c2
;
2640 hr
= IDWriteFactory6_GetSystemFontCollection(factory6
, FALSE
, DWRITE_FONT_FAMILY_MODEL_TYPOGRAPHIC
,
2643 ok(hr
== S_OK
, "Failed to get collection, hr %#x.\n", hr
);
2646 hr
= IDWriteFactory6_GetSystemFontCollection(factory6
, FALSE
, DWRITE_FONT_FAMILY_MODEL_TYPOGRAPHIC
, &c2
);
2647 ok(hr
== S_OK
, "Failed to get collection, hr %#x.\n", hr
);
2648 ok(c2
== collection2
&& collection
!= (IDWriteFontCollection
*)c2
, "Unexpected collection instance.\n");
2649 IDWriteFontCollection2_Release(c2
);
2650 IDWriteFontCollection2_Release(collection2
);
2652 hr
= IDWriteFactory6_GetSystemFontCollection(factory6
, FALSE
, DWRITE_FONT_FAMILY_MODEL_WEIGHT_STRETCH_STYLE
,
2654 ok(hr
== S_OK
, "Failed to get collection, hr %#x.\n", hr
);
2655 ok(collection
== (IDWriteFontCollection
*)collection2
, "Unexpected instance.\n");
2656 IDWriteFontCollection2_Release(collection2
);
2659 IDWriteFactory6_Release(factory6
);
2662 win_skip("IDWriteFactory6 is not supported.\n");
2664 ref
= IDWriteFontCollection_Release(collection
);
2665 ok(!ref
, "Collection wasn't released, %u.\n", ref
);
2666 ref
= IDWriteFactory_Release(factory
);
2667 ok(!ref
, "Factory wasn't released, %u.\n", ref
);
2670 static void get_logfont_from_font(IDWriteFont
*font
, LOGFONTW
*logfont
)
2672 void *os2_context
, *head_context
;
2673 IDWriteLocalizedStrings
*names
;
2674 DWRITE_FONT_SIMULATIONS sim
;
2675 IDWriteFontFace
*fontface
;
2676 const TT_OS2_V2
*tt_os2
;
2677 DWRITE_FONT_STYLE style
;
2678 const TT_HEAD
*tt_head
;
2684 /* These are rendering time properties. */
2685 logfont
->lfHeight
= 0;
2686 logfont
->lfWidth
= 0;
2687 logfont
->lfEscapement
= 0;
2688 logfont
->lfOrientation
= 0;
2689 logfont
->lfUnderline
= 0;
2690 logfont
->lfStrikeOut
= 0;
2692 logfont
->lfWeight
= 0;
2693 logfont
->lfItalic
= 0;
2695 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
2696 ok(hr
== S_OK
, "Failed to create font face, %#x\n", hr
);
2698 hr
= IDWriteFontFace_TryGetFontTable(fontface
, MS_OS2_TAG
, (const void **)&tt_os2
, &size
,
2699 &os2_context
, &exists
);
2700 ok(hr
== S_OK
, "Failed to get OS/2 table, %#x\n", hr
);
2702 hr
= IDWriteFontFace_TryGetFontTable(fontface
, MS_HEAD_TAG
, (const void **)&tt_head
, &size
,
2703 &head_context
, &exists
);
2704 ok(hr
== S_OK
, "Failed to get head table, %#x\n", hr
);
2706 sim
= IDWriteFont_GetSimulations(font
);
2709 weight
= FW_REGULAR
;
2711 USHORT usWeightClass
= GET_BE_WORD(tt_os2
->usWeightClass
);
2713 if (usWeightClass
>= 1 && usWeightClass
<= 9)
2714 usWeightClass
*= 100;
2716 if (usWeightClass
> DWRITE_FONT_WEIGHT_ULTRA_BLACK
)
2717 weight
= DWRITE_FONT_WEIGHT_ULTRA_BLACK
;
2718 else if (usWeightClass
> 0)
2719 weight
= usWeightClass
;
2722 USHORT macStyle
= GET_BE_WORD(tt_head
->macStyle
);
2723 if (macStyle
& TT_HEAD_MACSTYLE_BOLD
)
2724 weight
= DWRITE_FONT_WEIGHT_BOLD
;
2726 if (sim
& DWRITE_FONT_SIMULATIONS_BOLD
)
2727 weight
+= (FW_BOLD
- FW_REGULAR
) / 2 + 1;
2728 logfont
->lfWeight
= weight
;
2731 if (IDWriteFont_GetSimulations(font
) & DWRITE_FONT_SIMULATIONS_OBLIQUE
)
2732 logfont
->lfItalic
= 1;
2734 style
= IDWriteFont_GetStyle(font
);
2735 if (!logfont
->lfItalic
&& ((style
== DWRITE_FONT_STYLE_ITALIC
) || (style
== DWRITE_FONT_STYLE_OBLIQUE
))) {
2737 USHORT fsSelection
= GET_BE_WORD(tt_os2
->fsSelection
);
2738 logfont
->lfItalic
= !!(fsSelection
& OS2_FSSELECTION_ITALIC
);
2741 USHORT macStyle
= GET_BE_WORD(tt_head
->macStyle
);
2742 logfont
->lfItalic
= !!(macStyle
& TT_HEAD_MACSTYLE_ITALIC
);
2748 logfont
->lfFaceName
[0] = 0;
2749 hr
= IDWriteFont_GetInformationalStrings(font
, DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES
, &names
, &exists
);
2754 WCHAR localeW
[LOCALE_NAME_MAX_LENGTH
];
2758 /* Fallback to en-us if there's no string for user locale. */
2760 if (GetSystemDefaultLocaleName(localeW
, ARRAY_SIZE(localeW
)))
2761 IDWriteLocalizedStrings_FindLocaleName(names
, localeW
, &index
, &exists
);
2764 IDWriteLocalizedStrings_FindLocaleName(names
, L
"en-us", &index
, &exists
);
2768 hr
= IDWriteLocalizedStrings_GetString(names
, index
, nameW
, ARRAY_SIZE(nameW
));
2769 ok(hr
== S_OK
, "Failed to get name string, hr %#x.\n", hr
);
2770 lstrcpynW(logfont
->lfFaceName
, nameW
, ARRAY_SIZE(logfont
->lfFaceName
));
2774 IDWriteLocalizedStrings_Release(names
);
2778 IDWriteFontFace_ReleaseFontTable(fontface
, os2_context
);
2780 IDWriteFontFace_ReleaseFontTable(fontface
, head_context
);
2781 IDWriteFontFace_Release(fontface
);
2784 static void test_ConvertFontFaceToLOGFONT(void)
2786 IDWriteFontCollection
*collection
;
2787 IDWriteGdiInterop
*interop
;
2788 IDWriteFontFace
*fontface
;
2789 IDWriteFactory
*factory
;
2795 factory
= create_factory();
2797 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop
);
2798 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2800 if (0) /* crashes on native */
2802 hr
= IDWriteGdiInterop_ConvertFontFaceToLOGFONT(interop
, NULL
, NULL
);
2803 hr
= IDWriteGdiInterop_ConvertFontFaceToLOGFONT(interop
, fontface
, NULL
);
2805 memset(&logfont
, 0xcc, sizeof(logfont
));
2806 hr
= IDWriteGdiInterop_ConvertFontFaceToLOGFONT(interop
, NULL
, &logfont
);
2807 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
2808 ok(logfont
.lfFaceName
[0] == 0, "got face name %s\n", wine_dbgstr_w(logfont
.lfFaceName
));
2810 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &collection
, FALSE
);
2811 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2813 count
= IDWriteFontCollection_GetFontFamilyCount(collection
);
2814 for (i
= 0; i
< count
; i
++) {
2815 WCHAR nameW
[128], familynameW
[64], facenameW
[64];
2816 IDWriteLocalizedStrings
*names
;
2817 DWRITE_FONT_SIMULATIONS sim
;
2818 IDWriteFontFamily
*family
;
2819 UINT32 font_count
, j
;
2823 hr
= IDWriteFontCollection_GetFontFamily(collection
, i
, &family
);
2824 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2826 hr
= IDWriteFontFamily_GetFamilyNames(family
, &names
);
2827 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2829 get_enus_string(names
, familynameW
, ARRAY_SIZE(familynameW
));
2830 IDWriteLocalizedStrings_Release(names
);
2832 font_count
= IDWriteFontFamily_GetFontCount(family
);
2834 for (j
= 0; j
< font_count
; j
++) {
2835 IDWriteFontFace
*fontface
;
2837 hr
= IDWriteFontFamily_GetFont(family
, j
, &font
);
2838 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2840 hr
= IDWriteFont_GetFaceNames(font
, &names
);
2841 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2843 get_enus_string(names
, facenameW
, ARRAY_SIZE(facenameW
));
2844 IDWriteLocalizedStrings_Release(names
);
2846 get_combined_font_name(familynameW
, facenameW
, nameW
);
2848 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
2849 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2851 if (has_face_variations(fontface
)) {
2852 skip("%s: test does not support variable fonts.\n", wine_dbgstr_w(nameW
));
2853 IDWriteFontFace_Release(fontface
);
2854 IDWriteFont_Release(font
);
2858 memset(&logfont
, 0xcc, sizeof(logfont
));
2859 hr
= IDWriteGdiInterop_ConvertFontFaceToLOGFONT(interop
, fontface
, &logfont
);
2860 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2862 sim
= IDWriteFontFace_GetSimulations(fontface
);
2863 get_logfont_from_font(font
, &lf
);
2865 ok(logfont
.lfWeight
== lf
.lfWeight
, "%s: unexpected lfWeight %d, expected lfWeight %d, font weight %d, "
2866 "bold simulation %s\n", wine_dbgstr_w(nameW
), logfont
.lfWeight
, lf
.lfWeight
, IDWriteFont_GetWeight(font
),
2867 sim
& DWRITE_FONT_SIMULATIONS_BOLD
? "yes" : "no");
2868 ok(logfont
.lfItalic
== lf
.lfItalic
, "%s: unexpected italic flag %d, oblique simulation %s\n",
2869 wine_dbgstr_w(nameW
), logfont
.lfItalic
, sim
& DWRITE_FONT_SIMULATIONS_OBLIQUE
? "yes" : "no");
2870 ok(!lstrcmpW(logfont
.lfFaceName
, lf
.lfFaceName
), "%s: unexpected facename %s, expected %s\n",
2871 wine_dbgstr_w(nameW
), wine_dbgstr_w(logfont
.lfFaceName
), wine_dbgstr_w(lf
.lfFaceName
));
2873 ok(logfont
.lfOutPrecision
== OUT_OUTLINE_PRECIS
, "%s: unexpected output precision %d\n", wine_dbgstr_w(nameW
),
2874 logfont
.lfOutPrecision
);
2875 ok(logfont
.lfClipPrecision
== CLIP_DEFAULT_PRECIS
, "%s: unexpected clipping precision %d\n", wine_dbgstr_w(nameW
),
2876 logfont
.lfClipPrecision
);
2877 ok(logfont
.lfQuality
== DEFAULT_QUALITY
, "%s: unexpected quality %d\n", wine_dbgstr_w(nameW
), logfont
.lfQuality
);
2878 ok(logfont
.lfPitchAndFamily
== DEFAULT_PITCH
, "%s: unexpected pitch %d\n", wine_dbgstr_w(nameW
),
2879 logfont
.lfPitchAndFamily
);
2881 IDWriteFontFace_Release(fontface
);
2882 IDWriteFont_Release(font
);
2885 IDWriteFontFamily_Release(family
);
2888 IDWriteFontCollection_Release(collection
);
2889 IDWriteGdiInterop_Release(interop
);
2890 ref
= IDWriteFactory_Release(factory
);
2891 ok(ref
== 0, "factory not released, %u\n", ref
);
2894 static HRESULT WINAPI
fontfileenumerator_QueryInterface(IDWriteFontFileEnumerator
*iface
, REFIID riid
, void **obj
)
2896 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFontFileEnumerator
))
2899 IDWriteFontFileEnumerator_AddRef(iface
);
2902 return E_NOINTERFACE
;
2905 static ULONG WINAPI
fontfileenumerator_AddRef(IDWriteFontFileEnumerator
*iface
)
2910 static ULONG WINAPI
fontfileenumerator_Release(IDWriteFontFileEnumerator
*iface
)
2915 static HRESULT WINAPI
fontfileenumerator_GetCurrentFontFile(IDWriteFontFileEnumerator
*iface
, IDWriteFontFile
**file
)
2921 static HRESULT WINAPI
fontfileenumerator_MoveNext(IDWriteFontFileEnumerator
*iface
, BOOL
*current
)
2927 static const struct IDWriteFontFileEnumeratorVtbl dwritefontfileenumeratorvtbl
=
2929 fontfileenumerator_QueryInterface
,
2930 fontfileenumerator_AddRef
,
2931 fontfileenumerator_Release
,
2932 fontfileenumerator_MoveNext
,
2933 fontfileenumerator_GetCurrentFontFile
,
2936 struct collection_loader
2938 IDWriteFontCollectionLoader IDWriteFontCollectionLoader_iface
;
2942 static inline struct collection_loader
*impl_from_IDWriteFontCollectionLoader(IDWriteFontCollectionLoader
*iface
)
2944 return CONTAINING_RECORD(iface
, struct collection_loader
, IDWriteFontCollectionLoader_iface
);
2947 static HRESULT WINAPI
fontcollectionloader_QueryInterface(IDWriteFontCollectionLoader
*iface
, REFIID riid
, void **obj
)
2949 struct collection_loader
*loader
= impl_from_IDWriteFontCollectionLoader(iface
);
2951 if (IsEqualIID(&IID_IDWriteFontCollectionLoader
, riid
) ||
2952 IsEqualIID(&IID_IUnknown
, riid
))
2954 *obj
= &loader
->IDWriteFontCollectionLoader_iface
;
2955 IDWriteFontCollectionLoader_AddRef(iface
);
2960 return E_NOINTERFACE
;
2963 static ULONG WINAPI
fontcollectionloader_AddRef(IDWriteFontCollectionLoader
*iface
)
2965 struct collection_loader
*loader
= impl_from_IDWriteFontCollectionLoader(iface
);
2966 return InterlockedIncrement(&loader
->ref
);
2969 static ULONG WINAPI
fontcollectionloader_Release(IDWriteFontCollectionLoader
*iface
)
2971 struct collection_loader
*loader
= impl_from_IDWriteFontCollectionLoader(iface
);
2972 ULONG ref
= InterlockedDecrement(&loader
->ref
);
2980 static HRESULT WINAPI
fontcollectionloader_CreateEnumeratorFromKey(IDWriteFontCollectionLoader
*iface
, IDWriteFactory
*factory
, const void *key
,
2981 UINT32 key_size
, IDWriteFontFileEnumerator
**ret
)
2983 static IDWriteFontFileEnumerator enumerator
= { &dwritefontfileenumeratorvtbl
};
2988 static const struct IDWriteFontCollectionLoaderVtbl dwritefontcollectionloadervtbl
= {
2989 fontcollectionloader_QueryInterface
,
2990 fontcollectionloader_AddRef
,
2991 fontcollectionloader_Release
,
2992 fontcollectionloader_CreateEnumeratorFromKey
2995 static IDWriteFontCollectionLoader
*create_collection_loader(void)
2997 struct collection_loader
*loader
= heap_alloc(sizeof(*loader
));
2999 loader
->IDWriteFontCollectionLoader_iface
.lpVtbl
= &dwritefontcollectionloadervtbl
;
3002 return &loader
->IDWriteFontCollectionLoader_iface
;
3005 static void test_CustomFontCollection(void)
3007 IDWriteFontCollectionLoader
*loader
, *loader2
, *loader3
;
3008 IDWriteFontCollection
*font_collection
= NULL
;
3009 static IDWriteFontFileLoader rloader
= { &resourcefontfileloadervtbl
};
3010 struct test_fontcollectionloader resource_collection
= { { &resourcecollectionloadervtbl
}, &rloader
};
3011 IDWriteFontFamily
*family
, *family2
, *family3
;
3012 IDWriteFontFace
*idfontface
, *idfontface2
;
3013 IDWriteFontFile
*fontfile
, *fontfile2
;
3014 IDWriteLocalizedStrings
*string
;
3015 IDWriteFont
*idfont
, *idfont2
;
3016 IDWriteFactory
*factory
;
3017 UINT32 index
, count
;
3023 factory
= create_factory();
3025 loader
= create_collection_loader();
3026 loader2
= create_collection_loader();
3027 loader3
= create_collection_loader();
3029 hr
= IDWriteFactory_RegisterFontCollectionLoader(factory
, NULL
);
3030 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
3032 hr
= IDWriteFactory_UnregisterFontCollectionLoader(factory
, NULL
);
3033 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
3035 EXPECT_REF(loader
, 1);
3036 EXPECT_REF(loader2
, 1);
3038 hr
= IDWriteFactory_RegisterFontCollectionLoader(factory
, loader
);
3039 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3040 hr
= IDWriteFactory_RegisterFontCollectionLoader(factory
, loader2
);
3041 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3042 hr
= IDWriteFactory_RegisterFontCollectionLoader(factory
, loader
);
3043 ok(hr
== DWRITE_E_ALREADYREGISTERED
, "got 0x%08x\n", hr
);
3045 EXPECT_REF(loader
, 2);
3046 EXPECT_REF(loader2
, 2);
3048 hr
= IDWriteFactory_RegisterFontFileLoader(factory
, &rloader
);
3049 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3050 hr
= IDWriteFactory_RegisterFontCollectionLoader(factory
, &resource_collection
.IDWriteFontFileCollectionLoader_iface
);
3051 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3053 /* Loader wasn't registered. */
3054 font_collection
= (void*)0xdeadbeef;
3055 hr
= IDWriteFactory_CreateCustomFontCollection(factory
, loader3
, "Billy", 6, &font_collection
);
3056 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
3057 ok(font_collection
== NULL
, "got %p\n", font_collection
);
3059 EXPECT_REF(factory
, 1);
3060 hr
= IDWriteFactory_CreateCustomFontCollection(factory
, loader
, "Billy", 6, &font_collection
);
3061 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3063 EXPECT_REF(factory
, 1);
3064 EXPECT_REF(loader
, 2);
3065 IDWriteFontCollection_Release(font_collection
);
3067 hr
= IDWriteFactory_CreateCustomFontCollection(factory
, loader2
, "Billy", 6, &font_collection
);
3068 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3069 IDWriteFontCollection_Release(font_collection
);
3071 font_collection
= (void*)0xdeadbeef;
3072 hr
= IDWriteFactory_CreateCustomFontCollection(factory
, (IDWriteFontCollectionLoader
*)0xdeadbeef, "Billy", 6, &font_collection
);
3073 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
3074 ok(font_collection
== NULL
, "got %p\n", font_collection
);
3076 font
= FindResourceA(GetModuleHandleA(NULL
), (LPCSTR
)MAKEINTRESOURCE(1), (LPCSTR
)RT_RCDATA
);
3077 ok(font
!= NULL
, "Failed to find font resource\n");
3079 hr
= IDWriteFactory_CreateCustomFontCollection(factory
, &resource_collection
.IDWriteFontFileCollectionLoader_iface
,
3080 &font
, sizeof(HRSRC
), &font_collection
);
3081 ok(hr
== S_OK
, "got 0x%08x\n",hr
);
3082 EXPECT_REF(font_collection
, 1);
3086 hr
= IDWriteFontCollection_FindFamilyName(font_collection
, L
"wine_test", &index
, &exists
);
3087 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3088 ok(index
== 0, "got index %i\n", index
);
3089 ok(exists
, "got exists %i\n", exists
);
3091 count
= IDWriteFontCollection_GetFontFamilyCount(font_collection
);
3092 ok(count
== 1, "got %u\n", count
);
3095 hr
= IDWriteFontCollection_GetFontFamily(font_collection
, 0, &family
);
3096 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3097 EXPECT_REF(family
, 1);
3100 hr
= IDWriteFontCollection_GetFontFamily(font_collection
, 0, &family2
);
3101 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3102 EXPECT_REF(family2
, 1);
3103 ok(family
!= family2
, "got %p, %p\n", family
, family2
);
3105 hr
= IDWriteFontFamily_GetFont(family
, 0, &idfont
);
3106 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3107 EXPECT_REF(idfont
, 1);
3108 EXPECT_REF(family
, 2);
3109 hr
= IDWriteFontFamily_GetFont(family
, 0, &idfont2
);
3110 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3111 EXPECT_REF(idfont2
, 1);
3112 EXPECT_REF(family
, 3);
3113 ok(idfont
!= idfont2
, "got %p, %p\n", idfont
, idfont2
);
3114 IDWriteFont_Release(idfont2
);
3116 hr
= IDWriteFont_GetInformationalStrings(idfont
, DWRITE_INFORMATIONAL_STRING_COPYRIGHT_NOTICE
, &string
, &exists
);
3117 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3118 ok(exists
, "got %d\n", exists
);
3119 EXPECT_REF(string
, 1);
3120 IDWriteLocalizedStrings_Release(string
);
3123 hr
= IDWriteFont_GetFontFamily(idfont
, &family3
);
3124 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3125 EXPECT_REF(family
, 3);
3126 ok(family
== family3
, "got %p, %p\n", family
, family3
);
3127 IDWriteFontFamily_Release(family3
);
3130 hr
= IDWriteFont_CreateFontFace(idfont
, &idfontface
);
3131 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3132 EXPECT_REF(idfont
, 1);
3135 hr
= IDWriteFontFamily_GetFont(family2
, 0, &idfont2
);
3136 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3137 EXPECT_REF(idfont2
, 1);
3138 EXPECT_REF(idfont
, 1);
3139 ok(idfont2
!= idfont
, "Font instances should not match\n");
3142 hr
= IDWriteFont_CreateFontFace(idfont2
, &idfontface2
);
3143 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3144 ok(idfontface2
== idfontface
, "fontfaces should match\n");
3148 hr
= IDWriteFontFace_GetFiles(idfontface
, &index
, &fontfile
);
3149 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3153 hr
= IDWriteFontFace_GetFiles(idfontface2
, &index
, &fontfile2
);
3154 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3155 ok(fontfile
== fontfile2
, "fontfiles should match\n");
3157 IDWriteFont_Release(idfont
);
3158 IDWriteFont_Release(idfont2
);
3159 IDWriteFontFile_Release(fontfile
);
3160 IDWriteFontFile_Release(fontfile2
);
3161 IDWriteFontFace_Release(idfontface
);
3162 IDWriteFontFace_Release(idfontface2
);
3163 IDWriteFontFamily_Release(family2
);
3164 IDWriteFontFamily_Release(family
);
3165 IDWriteFontCollection_Release(font_collection
);
3167 hr
= IDWriteFactory_UnregisterFontCollectionLoader(factory
, loader
);
3168 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3169 hr
= IDWriteFactory_UnregisterFontCollectionLoader(factory
, loader
);
3170 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
3171 hr
= IDWriteFactory_UnregisterFontCollectionLoader(factory
, loader2
);
3172 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3173 hr
= IDWriteFactory_UnregisterFontCollectionLoader(factory
, &resource_collection
.IDWriteFontFileCollectionLoader_iface
);
3174 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3175 hr
= IDWriteFactory_UnregisterFontFileLoader(factory
, &rloader
);
3176 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3178 IDWriteFontCollectionLoader_Release(loader
);
3179 IDWriteFontCollectionLoader_Release(loader2
);
3180 IDWriteFontCollectionLoader_Release(loader3
);
3182 ref
= IDWriteFactory_Release(factory
);
3183 ok(ref
== 0, "factory not released, %u\n", ref
);
3186 static HRESULT WINAPI
fontfileloader_QueryInterface(IDWriteFontFileLoader
*iface
, REFIID riid
, void **obj
)
3188 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFontFileLoader
))
3191 IDWriteFontFileLoader_AddRef(iface
);
3196 return E_NOINTERFACE
;
3199 static ULONG WINAPI
fontfileloader_AddRef(IDWriteFontFileLoader
*iface
)
3204 static ULONG WINAPI
fontfileloader_Release(IDWriteFontFileLoader
*iface
)
3209 static HRESULT WINAPI
fontfileloader_CreateStreamFromKey(IDWriteFontFileLoader
*iface
, const void *ref_key
, UINT32 key_size
,
3210 IDWriteFontFileStream
**stream
)
3215 static const struct IDWriteFontFileLoaderVtbl dwritefontfileloadervtbl
= {
3216 fontfileloader_QueryInterface
,
3217 fontfileloader_AddRef
,
3218 fontfileloader_Release
,
3219 fontfileloader_CreateStreamFromKey
3222 static void test_CreateCustomFontFileReference(void)
3224 IDWriteFontFileLoader floader
= { &dwritefontfileloadervtbl
};
3225 IDWriteFontFileLoader floader2
= { &dwritefontfileloadervtbl
};
3226 IDWriteFontFileLoader floader3
= { &dwritefontfileloadervtbl
};
3227 IDWriteFactory
*factory
, *factory2
;
3228 IDWriteFontFileLoader
*loader
;
3229 IDWriteFontFile
*file
, *file2
;
3231 DWRITE_FONT_FILE_TYPE file_type
;
3232 DWRITE_FONT_FACE_TYPE face_type
;
3234 IDWriteFontFace
*face
, *face2
;
3237 UINT32 codePoints
[1] = {0xa8};
3244 path
= create_testfontfile(test_fontfile
);
3246 factory
= create_factory();
3247 factory2
= create_factory();
3249 if (0) { /* crashes on win10 */
3250 hr
= IDWriteFactory_RegisterFontFileLoader(factory
, NULL
);
3251 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
3253 /* local loader is accepted too */
3254 hr
= IDWriteFactory_CreateFontFileReference(factory
, path
, NULL
, &file
);
3255 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3257 hr
= IDWriteFontFile_GetLoader(file
, &loader
);
3258 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3260 hr
= IDWriteFontFile_GetReferenceKey(file
, &key
, &key_size
);
3261 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3263 hr
= IDWriteFactory_CreateCustomFontFileReference(factory
, key
, key_size
, loader
, &file2
);
3264 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3266 IDWriteFontFile_Release(file2
);
3267 IDWriteFontFile_Release(file
);
3268 IDWriteFontFileLoader_Release(loader
);
3270 hr
= IDWriteFactory_RegisterFontFileLoader(factory
, &floader
);
3271 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3272 hr
= IDWriteFactory_RegisterFontFileLoader(factory
, &floader2
);
3273 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3274 hr
= IDWriteFactory_RegisterFontFileLoader(factory
, &floader
);
3275 ok(hr
== DWRITE_E_ALREADYREGISTERED
, "got 0x%08x\n", hr
);
3276 hr
= IDWriteFactory_RegisterFontFileLoader(factory
, &rloader
);
3277 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3280 hr
= IDWriteFactory_CreateCustomFontFileReference(factory
, "test", 4, &floader
, &file
);
3281 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3282 IDWriteFontFile_Release(file
);
3284 file
= (void*)0xdeadbeef;
3285 hr
= IDWriteFactory_CreateCustomFontFileReference(factory
, "test", 4, &floader3
, &file
);
3286 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
3287 ok(file
== NULL
, "got %p\n", file
);
3289 file
= (void*)0xdeadbeef;
3290 hr
= IDWriteFactory_CreateCustomFontFileReference(factory
, "test", 4, NULL
, &file
);
3291 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
3292 ok(file
== NULL
, "got %p\n", file
);
3295 hr
= IDWriteFactory_CreateCustomFontFileReference(factory
, "test", 4, &floader
, &file
);
3296 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3298 file_type
= DWRITE_FONT_FILE_TYPE_TRUETYPE
;
3299 face_type
= DWRITE_FONT_FACE_TYPE_TRUETYPE
;
3302 hr
= IDWriteFontFile_Analyze(file
, &support
, &file_type
, &face_type
, &count
);
3303 ok(hr
== 0x8faecafe, "got 0x%08x\n", hr
);
3304 ok(support
== FALSE
, "got %i\n", support
);
3305 ok(file_type
== DWRITE_FONT_FILE_TYPE_UNKNOWN
, "got %i\n", file_type
);
3306 ok(face_type
== DWRITE_FONT_FACE_TYPE_UNKNOWN
, "got %i\n", face_type
);
3307 ok(count
== 0, "got %i\n", count
);
3309 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_CFF
, 1, &file
, 0, 0, &face
);
3310 ok(hr
== 0x8faecafe, "got 0x%08x\n", hr
);
3311 IDWriteFontFile_Release(file
);
3313 fontrsrc
= FindResourceA(GetModuleHandleA(NULL
), (LPCSTR
)MAKEINTRESOURCE(1), (LPCSTR
)RT_RCDATA
);
3314 ok(fontrsrc
!= NULL
, "Failed to find font resource\n");
3316 hr
= IDWriteFactory_CreateCustomFontFileReference(factory
, &fontrsrc
, sizeof(HRSRC
), &rloader
, &file
);
3317 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3319 file_type
= DWRITE_FONT_FILE_TYPE_UNKNOWN
;
3320 face_type
= DWRITE_FONT_FACE_TYPE_UNKNOWN
;
3323 hr
= IDWriteFontFile_Analyze(file
, &support
, &file_type
, &face_type
, &count
);
3324 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3325 ok(support
== TRUE
, "got %i\n", support
);
3326 ok(file_type
== DWRITE_FONT_FILE_TYPE_TRUETYPE
, "got %i\n", file_type
);
3327 ok(face_type
== DWRITE_FONT_FACE_TYPE_TRUETYPE
, "got %i\n", face_type
);
3328 ok(count
== 1, "got %i\n", count
);
3331 face
= (void*)0xdeadbeef;
3332 hr
= IDWriteFactory_CreateFontFace(factory
, face_type
, 1, &file
, 1, DWRITE_FONT_SIMULATIONS_NONE
, &face
);
3333 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
3334 ok(face
== NULL
, "got %p\n", face
);
3336 hr
= IDWriteFactory_CreateFontFace(factory
, face_type
, 1, &file
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &face
);
3337 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3339 hr
= IDWriteFactory_CreateFontFace(factory
, face_type
, 1, &file
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &face2
);
3340 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3341 /* fontface instances are reused starting with win7 */
3342 ok(face
== face2
|| broken(face
!= face2
), "got %p, %p\n", face
, face2
);
3343 IDWriteFontFace_Release(face2
);
3345 /* file was created with different factory */
3347 hr
= IDWriteFactory_CreateFontFace(factory2
, face_type
, 1, &file
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &face2
);
3349 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3351 IDWriteFontFace_Release(face2
);
3354 hr
= IDWriteFactory_CreateCustomFontFileReference(factory
, &fontrsrc
, sizeof(HRSRC
), &rloader
, &file2
);
3355 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3356 ok(file
!= file2
, "got %p, %p\n", file
, file2
);
3358 hr
= IDWriteFactory_CreateFontFace(factory
, face_type
, 1, &file2
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &face2
);
3359 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3360 /* fontface instances are reused starting with win7 */
3361 ok(face
== face2
|| broken(face
!= face2
), "got %p, %p\n", face
, face2
);
3362 IDWriteFontFace_Release(face2
);
3363 IDWriteFontFile_Release(file2
);
3365 hr
= IDWriteFontFace_GetGlyphIndices(face
, NULL
, 0, NULL
);
3366 ok(hr
== E_INVALIDARG
|| broken(hr
== S_OK
) /* win8 */, "got 0x%08x\n", hr
);
3368 hr
= IDWriteFontFace_GetGlyphIndices(face
, codePoints
, 0, NULL
);
3369 ok(hr
== E_INVALIDARG
|| broken(hr
== S_OK
) /* win8 */, "got 0x%08x\n", hr
);
3371 hr
= IDWriteFontFace_GetGlyphIndices(face
, codePoints
, 0, indices
);
3372 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3374 hr
= IDWriteFontFace_GetGlyphIndices(face
, NULL
, 0, indices
);
3375 ok(hr
== E_INVALIDARG
|| broken(hr
== S_OK
) /* win8 */, "got 0x%08x\n", hr
);
3377 indices
[0] = indices
[1] = 11;
3378 hr
= IDWriteFontFace_GetGlyphIndices(face
, NULL
, 1, indices
);
3379 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
3380 ok(indices
[0] == 0, "got index %i\n", indices
[0]);
3381 ok(indices
[1] == 11, "got index %i\n", indices
[1]);
3383 if (0) /* crashes on native */
3384 hr
= IDWriteFontFace_GetGlyphIndices(face
, NULL
, 1, NULL
);
3386 hr
= IDWriteFontFace_GetGlyphIndices(face
, codePoints
, 1, indices
);
3387 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3388 ok(indices
[0] == 7, "Unexpected glyph index, %u.\n", indices
[0]);
3389 IDWriteFontFace_Release(face
);
3390 IDWriteFontFile_Release(file
);
3392 hr
= IDWriteFactory_UnregisterFontFileLoader(factory
, &floader
);
3393 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3394 hr
= IDWriteFactory_UnregisterFontFileLoader(factory
, &floader
);
3395 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
3396 hr
= IDWriteFactory_UnregisterFontFileLoader(factory
, &floader2
);
3397 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3398 hr
= IDWriteFactory_UnregisterFontFileLoader(factory
, &rloader
);
3399 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3401 ref
= IDWriteFactory_Release(factory2
);
3402 ok(ref
== 0, "factory not released, %u\n", ref
);
3403 ref
= IDWriteFactory_Release(factory
);
3404 ok(ref
== 0, "factory not released, %u\n", ref
);
3405 DELETE_FONTFILE(path
);
3408 static void test_CreateFontFileReference(void)
3411 IDWriteFontFile
*ffile
= NULL
;
3413 DWRITE_FONT_FILE_TYPE type
;
3414 DWRITE_FONT_FACE_TYPE face
;
3416 IDWriteFontFace
*fface
= NULL
;
3417 IDWriteFactory
*factory
;
3421 path
= create_testfontfile(test_fontfile
);
3422 factory
= create_factory();
3424 ffile
= (void*)0xdeadbeef;
3425 hr
= IDWriteFactory_CreateFontFileReference(factory
, NULL
, NULL
, &ffile
);
3426 ok(hr
== E_INVALIDARG
, "got 0x%08x\n",hr
);
3427 ok(ffile
== NULL
, "got %p\n", ffile
);
3429 hr
= IDWriteFactory_CreateFontFileReference(factory
, path
, NULL
, &ffile
);
3430 ok(hr
== S_OK
, "got 0x%08x\n",hr
);
3433 type
= DWRITE_FONT_FILE_TYPE_UNKNOWN
;
3434 face
= DWRITE_FONT_FACE_TYPE_CFF
;
3436 hr
= IDWriteFontFile_Analyze(ffile
, &support
, &type
, &face
, &count
);
3437 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3438 ok(support
== TRUE
, "got %i\n", support
);
3439 ok(type
== DWRITE_FONT_FILE_TYPE_TRUETYPE
, "got %i\n", type
);
3440 ok(face
== DWRITE_FONT_FACE_TYPE_TRUETYPE
, "got %i\n", face
);
3441 ok(count
== 1, "got %i\n", count
);
3443 hr
= IDWriteFactory_CreateFontFace(factory
, face
, 1, &ffile
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &fface
);
3444 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3446 IDWriteFontFace_Release(fface
);
3447 IDWriteFontFile_Release(ffile
);
3448 ref
= IDWriteFactory_Release(factory
);
3449 ok(ref
== 0, "factory not released, %u\n", ref
);
3451 DELETE_FONTFILE(path
);
3454 static void test_shared_isolated(void)
3456 IDWriteFactory
*isolated
, *isolated2
;
3457 IDWriteFactory
*shared
, *shared2
;
3463 hr
= DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED
+1, &IID_IDWriteFactory
, (IUnknown
**)&shared
);
3464 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3465 ok(shared
!= NULL
, "got %p\n", shared
);
3466 IDWriteFactory_Release(shared
);
3468 hr
= DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED
, &IID_IDWriteFactory
, (IUnknown
**)&shared
);
3469 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3471 hr
= DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED
, &IID_IDWriteFactory
, (IUnknown
**)&shared2
);
3472 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3473 ok(shared
== shared2
, "got %p, and %p\n", shared
, shared2
);
3474 IDWriteFactory_Release(shared2
);
3476 IDWriteFactory_Release(shared
);
3478 /* we got 2 references, released 2 - still same pointer is returned */
3479 hr
= DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED
, &IID_IDWriteFactory
, (IUnknown
**)&shared2
);
3480 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3481 ok(shared
== shared2
, "got %p, and %p\n", shared
, shared2
);
3482 IDWriteFactory_Release(shared2
);
3484 hr
= DWriteCreateFactory(DWRITE_FACTORY_TYPE_ISOLATED
, &IID_IDWriteFactory
, (IUnknown
**)&isolated
);
3485 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3487 hr
= DWriteCreateFactory(DWRITE_FACTORY_TYPE_ISOLATED
, &IID_IDWriteFactory
, (IUnknown
**)&isolated2
);
3488 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3489 ok(isolated
!= isolated2
, "got %p, and %p\n", isolated
, isolated2
);
3490 IDWriteFactory_Release(isolated2
);
3492 hr
= DWriteCreateFactory(DWRITE_FACTORY_TYPE_ISOLATED
, &IID_IUnknown
, (IUnknown
**)&isolated2
);
3493 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3494 IDWriteFactory_Release(isolated2
);
3496 hr
= DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED
+1, &IID_IDWriteFactory
, (IUnknown
**)&isolated2
);
3497 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3498 ok(shared
!= isolated2
, "got %p, and %p\n", shared
, isolated2
);
3500 ref
= IDWriteFactory_Release(isolated
);
3501 ok(ref
== 0, "factory not released, %u\n", ref
);
3502 ref
= IDWriteFactory_Release(isolated2
);
3503 ok(ref
== 0, "factory not released, %u\n", ref
);
3506 struct dwrite_fonttable
3513 static WORD
table_read_be_word(const struct dwrite_fonttable
*table
, void *ptr
, DWORD offset
)
3518 if ((BYTE
*)ptr
< table
->data
|| (BYTE
*)ptr
- table
->data
>= table
->size
)
3521 if (offset
> table
->size
- sizeof(WORD
))
3524 return GET_BE_WORD(*(WORD
*)((BYTE
*)ptr
+ offset
));
3527 static DWORD
table_read_be_dword(const struct dwrite_fonttable
*table
, void *ptr
, DWORD offset
)
3532 if ((BYTE
*)ptr
< table
->data
|| (BYTE
*)ptr
- table
->data
>= table
->size
)
3535 if (offset
> table
->size
- sizeof(WORD
))
3538 return GET_BE_DWORD(*(DWORD
*)((BYTE
*)ptr
+ offset
));
3541 static void array_reserve(void **elements
, size_t *capacity
, size_t count
, size_t size
)
3543 size_t new_capacity
, max_capacity
;
3546 if (count
<= *capacity
)
3549 max_capacity
= ~(SIZE_T
)0 / size
;
3550 if (count
> max_capacity
)
3553 new_capacity
= max(4, *capacity
);
3554 while (new_capacity
< count
&& new_capacity
<= max_capacity
/ 2)
3556 if (new_capacity
< count
)
3557 new_capacity
= max_capacity
;
3559 if (!(new_elements
= heap_realloc(*elements
, new_capacity
* size
)))
3562 *elements
= new_elements
;
3563 *capacity
= new_capacity
;
3566 static void opentype_cmap_read_table(const struct dwrite_fonttable
*table
, UINT16 cmap_index
, UINT32
*count
,
3567 size_t *capacity
, DWRITE_UNICODE_RANGE
**ranges
)
3569 const BYTE
*tables
= table
->data
+ FIELD_OFFSET(struct cmap_header
, tables
);
3570 struct cmap_encoding_record
*record
;
3575 record
= (struct cmap_encoding_record
*)(tables
+ cmap_index
* sizeof(*record
));
3577 if (!(table_offset
= table_read_be_dword(table
, record
, FIELD_OFFSET(struct cmap_encoding_record
, offset
))))
3580 format
= table_read_be_word(table
, NULL
, table_offset
);
3583 case OPENTYPE_CMAP_TABLE_SEGMENT_MAPPING
:
3585 UINT16 segment_count
= table_read_be_word(table
, NULL
, table_offset
+
3586 FIELD_OFFSET(struct cmap_segmented_mapping_0
, segCountX2
)) / 2;
3587 DWORD start_code_offset
= table_offset
+ sizeof(struct cmap_segmented_mapping_0
) +
3588 sizeof(WORD
) * segment_count
;
3590 for (j
= 0; j
< segment_count
; ++j
) {
3591 WORD endcode
= table_read_be_word(table
, NULL
, table_offset
+
3592 FIELD_OFFSET(struct cmap_segmented_mapping_0
, endCode
) + j
* sizeof(WORD
));
3595 if (endcode
== 0xffff)
3598 first
= table_read_be_word(table
, NULL
, start_code_offset
+ j
* sizeof(WORD
));
3600 array_reserve((void **)ranges
, capacity
, *count
+ 1, sizeof(**ranges
));
3601 (*ranges
)[*count
].first
= first
;
3602 (*ranges
)[*count
].last
= endcode
;
3607 case OPENTYPE_CMAP_TABLE_SEGMENTED_COVERAGE
:
3609 DWORD num_groups
= table_read_be_dword(table
, NULL
, table_offset
+
3610 FIELD_OFFSET(struct cmap_segmented_coverage
, nGroups
));
3612 for (j
= 0; j
< num_groups
; ++j
) {
3613 DWORD group_offset
= table_offset
+ FIELD_OFFSET(struct cmap_segmented_coverage
, groups
) +
3614 j
* sizeof(struct cmap_segmented_coverage_group
);
3615 DWORD first
= table_read_be_dword(table
, NULL
, group_offset
+
3616 FIELD_OFFSET(struct cmap_segmented_coverage_group
, startCharCode
));
3617 DWORD last
= table_read_be_dword(table
, NULL
, group_offset
+
3618 FIELD_OFFSET(struct cmap_segmented_coverage_group
, endCharCode
));
3620 array_reserve((void **)ranges
, capacity
, *count
+ 1, sizeof(**ranges
));
3621 (*ranges
)[*count
].first
= first
;
3622 (*ranges
)[*count
].last
= last
;
3628 ok(0, "%u table format %#x unhandled.\n", cmap_index
, format
);
3632 static UINT32
opentype_cmap_get_unicode_ranges(const struct dwrite_fonttable
*table
, DWRITE_UNICODE_RANGE
**ranges
)
3634 int index_full
= -1, index_bmp
= -1;
3635 unsigned int i
, count
= 0;
3636 size_t capacity
= 0;
3642 num_tables
= table_read_be_word(table
, 0, FIELD_OFFSET(struct cmap_header
, num_tables
));
3643 tables
= table
->data
+ FIELD_OFFSET(struct cmap_header
, tables
);
3645 for (i
= 0; i
< num_tables
; ++i
)
3647 struct cmap_encoding_record
*record
= (struct cmap_encoding_record
*)(tables
+ i
* sizeof(*record
));
3648 WORD platform
, encoding
;
3650 platform
= table_read_be_word(table
, record
, FIELD_OFFSET(struct cmap_encoding_record
, platformID
));
3651 encoding
= table_read_be_word(table
, record
, FIELD_OFFSET(struct cmap_encoding_record
, encodingID
));
3653 if (platform
== OPENTYPE_CMAP_TABLE_PLATFORM_WIN
)
3655 if (encoding
== OPENTYPE_CMAP_TABLE_ENCODING_UNICODE_FULL
)
3660 else if (encoding
== OPENTYPE_CMAP_TABLE_ENCODING_UNICODE_BMP
)
3665 if (index_full
!= -1)
3666 opentype_cmap_read_table(table
, index_full
, &count
, &capacity
, ranges
);
3667 else if (index_bmp
!= -1)
3668 opentype_cmap_read_table(table
, index_bmp
, &count
, &capacity
, ranges
);
3673 static UINT32
fontface_get_expected_unicode_ranges(IDWriteFontFace1
*fontface
, DWRITE_UNICODE_RANGE
**out
)
3675 struct dwrite_fonttable cmap
;
3676 DWRITE_UNICODE_RANGE
*ranges
;
3683 hr
= IDWriteFontFace1_TryGetFontTable(fontface
, MS_CMAP_TAG
, (const void **)&cmap
.data
,
3684 &cmap
.size
, &cmap
.context
, &exists
);
3685 if (FAILED(hr
) || !exists
)
3688 count
= opentype_cmap_get_unicode_ranges(&cmap
, &ranges
);
3689 IDWriteFontFace1_ReleaseFontTable(fontface
, cmap
.context
);
3691 *out
= heap_alloc(count
* sizeof(**out
));
3693 /* Eliminate duplicates and merge ranges together. */
3694 for (i
= 0, j
= 0; i
< count
; ++i
) {
3696 DWRITE_UNICODE_RANGE
*prev
= &(*out
)[j
-1];
3697 /* Merge adjacent ranges. */
3698 if (ranges
[i
].first
== prev
->last
+ 1) {
3699 prev
->last
= ranges
[i
].last
;
3703 (*out
)[j
++] = ranges
[i
];
3711 static void test_GetUnicodeRanges(void)
3713 IDWriteFontCollection
*syscollection
;
3714 DWRITE_UNICODE_RANGE
*ranges
, r
;
3715 IDWriteFontFile
*ffile
= NULL
;
3716 IDWriteFontFace1
*fontface1
;
3717 IDWriteFontFace
*fontface
;
3718 IDWriteFactory
*factory
;
3724 factory
= create_factory();
3726 hr
= IDWriteFactory_RegisterFontFileLoader(factory
, &rloader
);
3727 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3729 font
= FindResourceA(GetModuleHandleA(NULL
), (LPCSTR
)MAKEINTRESOURCE(1), (LPCSTR
)RT_RCDATA
);
3730 ok(font
!= NULL
, "Failed to find font resource\n");
3732 hr
= IDWriteFactory_CreateCustomFontFileReference(factory
, &font
, sizeof(HRSRC
), &rloader
, &ffile
);
3733 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3735 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_TRUETYPE
, 1, &ffile
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &fontface
);
3736 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3737 IDWriteFontFile_Release(ffile
);
3739 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void**)&fontface1
);
3740 IDWriteFontFace_Release(fontface
);
3742 win_skip("GetUnicodeRanges() is not supported.\n");
3743 IDWriteFactory_Release(factory
);
3748 hr
= IDWriteFontFace1_GetUnicodeRanges(fontface1
, 0, NULL
, &count
);
3749 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
3750 ok(count
> 0, "got %u\n", count
);
3753 hr
= IDWriteFontFace1_GetUnicodeRanges(fontface1
, 1, NULL
, &count
);
3754 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
3755 ok(count
== 0, "got %u\n", count
);
3758 hr
= IDWriteFontFace1_GetUnicodeRanges(fontface1
, 1, &r
, &count
);
3759 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
3760 ok(count
> 1, "got %u\n", count
);
3762 ranges
= heap_alloc(count
*sizeof(DWRITE_UNICODE_RANGE
));
3763 hr
= IDWriteFontFace1_GetUnicodeRanges(fontface1
, count
, ranges
, &count
);
3764 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3766 ranges
[0].first
= ranges
[0].last
= 0;
3767 hr
= IDWriteFontFace1_GetUnicodeRanges(fontface1
, 1, ranges
, &count
);
3768 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
3769 ok(ranges
[0].first
!= 0 && ranges
[0].last
!= 0, "got 0x%x-0x%0x\n", ranges
[0].first
, ranges
[0].last
);
3773 hr
= IDWriteFactory_UnregisterFontFileLoader(factory
, &rloader
);
3774 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3776 IDWriteFontFace1_Release(fontface1
);
3778 if (strcmp(winetest_platform
, "wine")) {
3780 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &syscollection
, FALSE
);
3781 ok(hr
== S_OK
, "Failed to get system collection, hr %#x.\n", hr
);
3783 count
= IDWriteFontCollection_GetFontFamilyCount(syscollection
);
3785 for (i
= 0; i
< count
; i
++) {
3786 WCHAR familynameW
[256], facenameW
[128];
3787 IDWriteLocalizedStrings
*names
;
3788 IDWriteFontFamily
*family
;
3789 UINT32 j
, k
, fontcount
;
3792 hr
= IDWriteFontCollection_GetFontFamily(syscollection
, i
, &family
);
3793 ok(hr
== S_OK
, "Failed to get font family, hr %#x.\n", hr
);
3795 hr
= IDWriteFontFamily_GetFamilyNames(family
, &names
);
3796 ok(hr
== S_OK
, "Failed to get family names, hr %#x.\n", hr
);
3798 get_enus_string(names
, familynameW
, ARRAY_SIZE(familynameW
));
3799 IDWriteLocalizedStrings_Release(names
);
3801 fontcount
= IDWriteFontFamily_GetFontCount(family
);
3802 for (j
= 0; j
< fontcount
; j
++) {
3803 DWRITE_UNICODE_RANGE
*expected_ranges
= NULL
;
3804 UINT32 range_count
, expected_count
;
3806 hr
= IDWriteFontFamily_GetFont(family
, j
, &font
);
3807 ok(hr
== S_OK
, "Failed to get font, hr %#x.\n", hr
);
3809 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
3810 ok(hr
== S_OK
, "Failed to create fontface, hr %#x.\n", hr
);
3812 hr
= IDWriteFont_GetFaceNames(font
, &names
);
3813 ok(hr
== S_OK
, "Failed to get face names, hr %#x.\n", hr
);
3814 IDWriteFont_Release(font
);
3816 get_enus_string(names
, facenameW
, ARRAY_SIZE(facenameW
));
3818 IDWriteLocalizedStrings_Release(names
);
3820 if (IDWriteFontFace_IsSymbolFont(fontface
)) {
3821 skip("Skipping for symbol font %s %s.\n", wine_dbgstr_w(familynameW
), wine_dbgstr_w(facenameW
));
3822 IDWriteFontFace_Release(fontface
);
3826 IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void **)&fontface1
);
3828 hr
= IDWriteFontFace1_GetUnicodeRanges(fontface1
, 0, NULL
, &range_count
);
3829 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "Unexpected hr %#x.\n", hr
);
3831 ranges
= heap_alloc(range_count
* sizeof(*ranges
));
3833 hr
= IDWriteFontFace1_GetUnicodeRanges(fontface1
, range_count
, ranges
, &range_count
);
3834 ok(hr
== S_OK
, "Failed to get ranges, hr %#x.\n", hr
);
3836 expected_count
= fontface_get_expected_unicode_ranges(fontface1
, &expected_ranges
);
3837 ok(expected_count
== range_count
, "%s - %s: unexpected range count %u, expected %u.\n",
3838 wine_dbgstr_w(familynameW
), wine_dbgstr_w(facenameW
), range_count
, expected_count
);
3840 if (expected_count
== range_count
) {
3841 if (memcmp(expected_ranges
, ranges
, expected_count
* sizeof(*ranges
))) {
3842 for (k
= 0; k
< expected_count
; ++k
) {
3843 BOOL failed
= memcmp(&expected_ranges
[k
], &ranges
[k
], sizeof(*ranges
));
3844 ok(!failed
, "%u: %s - %s mismatching range [%#x, %#x] vs [%#x, %#x].\n", k
,
3845 wine_dbgstr_w(familynameW
), wine_dbgstr_w(facenameW
), ranges
[k
].first
, ranges
[k
].last
,
3846 expected_ranges
[k
].first
, expected_ranges
[k
].last
);
3853 heap_free(expected_ranges
);
3856 IDWriteFontFace1_Release(fontface1
);
3857 IDWriteFontFace_Release(fontface
);
3860 IDWriteFontFamily_Release(family
);
3863 IDWriteFontCollection_Release(syscollection
);
3865 ref
= IDWriteFactory_Release(factory
);
3866 ok(ref
== 0, "factory not released, %u\n", ref
);
3869 static void test_GetFontFromFontFace(void)
3871 IDWriteFontFace
*fontface
, *fontface2
;
3872 IDWriteFontCollection
*collection
;
3873 IDWriteFont
*font
, *font2
, *font3
;
3874 IDWriteFontFamily
*family
;
3875 IDWriteFactory
*factory
;
3876 IDWriteFontFile
*file
;
3881 factory
= create_factory();
3883 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &collection
, FALSE
);
3884 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3886 hr
= IDWriteFontCollection_GetFontFamily(collection
, 0, &family
);
3887 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3889 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
,
3890 DWRITE_FONT_STRETCH_NORMAL
, DWRITE_FONT_STYLE_NORMAL
, &font
);
3891 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3893 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
3894 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3897 hr
= IDWriteFontCollection_GetFontFromFontFace(collection
, fontface
, &font2
);
3898 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3899 ok(font2
!= font
, "got %p, %p\n", font2
, font
);
3902 hr
= IDWriteFontCollection_GetFontFromFontFace(collection
, fontface
, &font3
);
3903 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3904 ok(font3
!= font
&& font3
!= font2
, "got %p, %p, %p\n", font3
, font2
, font
);
3906 hr
= IDWriteFont_CreateFontFace(font2
, &fontface2
);
3907 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3908 ok(fontface2
== fontface
, "got %p, %p\n", fontface2
, fontface
);
3909 IDWriteFontFace_Release(fontface2
);
3911 hr
= IDWriteFont_CreateFontFace(font3
, &fontface2
);
3912 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3913 ok(fontface2
== fontface
, "got %p, %p\n", fontface2
, fontface
);
3914 IDWriteFontFace_Release(fontface2
);
3915 IDWriteFontFace_Release(fontface
);
3916 IDWriteFont_Release(font3
);
3917 IDWriteFactory_Release(factory
);
3919 /* fontface that wasn't created from this collection */
3920 factory
= create_factory();
3921 path
= create_testfontfile(test_fontfile
);
3923 hr
= IDWriteFactory_CreateFontFileReference(factory
, path
, NULL
, &file
);
3924 ok(hr
== S_OK
, "got 0x%08x\n",hr
);
3926 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_TRUETYPE
, 1, &file
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &fontface
);
3927 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3928 IDWriteFontFile_Release(file
);
3930 hr
= IDWriteFontCollection_GetFontFromFontFace(collection
, fontface
, &font3
);
3931 ok(hr
== DWRITE_E_NOFONT
, "got 0x%08x\n", hr
);
3932 ok(font3
== NULL
, "got %p\n", font3
);
3933 IDWriteFontFace_Release(fontface
);
3935 IDWriteFont_Release(font
);
3936 IDWriteFont_Release(font2
);
3937 IDWriteFontFamily_Release(family
);
3938 IDWriteFontCollection_Release(collection
);
3939 ref
= IDWriteFactory_Release(factory
);
3940 ok(ref
== 0, "factory not released, %u\n", ref
);
3941 DELETE_FONTFILE(path
);
3944 static void test_GetFirstMatchingFont(void)
3946 DWRITE_FONT_SIMULATIONS simulations
;
3947 IDWriteFontCollection
*collection
;
3948 IDWriteFontFamily
*family
;
3949 IDWriteFont
*font
, *font2
;
3950 IDWriteFactory
*factory
;
3954 factory
= create_factory();
3956 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &collection
, FALSE
);
3957 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3959 hr
= IDWriteFontCollection_GetFontFamily(collection
, 0, &family
);
3960 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3962 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
,
3963 DWRITE_FONT_STRETCH_NORMAL
, DWRITE_FONT_STYLE_NORMAL
, &font
);
3964 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3966 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
,
3967 DWRITE_FONT_STRETCH_NORMAL
, DWRITE_FONT_STYLE_NORMAL
, &font2
);
3968 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3969 ok(font
!= font2
, "got %p, %p\n", font
, font2
);
3970 IDWriteFont_Release(font
);
3971 IDWriteFont_Release(font2
);
3973 /* out-of-range font props are allowed */
3974 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, 1000, DWRITE_FONT_STRETCH_NORMAL
, DWRITE_FONT_STYLE_NORMAL
, &font
);
3975 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3976 IDWriteFont_Release(font
);
3978 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
, 10, DWRITE_FONT_STYLE_NORMAL
, &font
);
3979 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3980 IDWriteFont_Release(font
);
3982 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STRETCH_NORMAL
,
3984 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3985 IDWriteFont_Release(font
);
3987 IDWriteFontFamily_Release(family
);
3989 font
= get_tahoma_instance(factory
, DWRITE_FONT_STYLE_ITALIC
);
3990 simulations
= IDWriteFont_GetSimulations(font
);
3991 ok(simulations
== DWRITE_FONT_SIMULATIONS_OBLIQUE
, "%d\n", simulations
);
3992 IDWriteFont_Release(font
);
3994 IDWriteFontCollection_Release(collection
);
3995 ref
= IDWriteFactory_Release(factory
);
3996 ok(ref
== 0, "factory not released, %u\n", ref
);
3999 static void test_GetMatchingFonts(void)
4001 IDWriteFontCollection
*collection
;
4002 IDWriteFontFamily
*family
;
4003 IDWriteFactory
*factory
;
4004 IDWriteFontList
*fontlist
, *fontlist2
;
4005 IDWriteFontList1
*fontlist1
;
4006 IDWriteFontList2
*fontlist3
;
4010 factory
= create_factory();
4012 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &collection
, FALSE
);
4013 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4015 hr
= IDWriteFontCollection_GetFontFamily(collection
, 0, &family
);
4016 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4018 /* out-of-range font props are allowed */
4019 hr
= IDWriteFontFamily_GetMatchingFonts(family
, 1000, DWRITE_FONT_STRETCH_NORMAL
,
4020 DWRITE_FONT_STYLE_NORMAL
, &fontlist
);
4021 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4022 IDWriteFontList_Release(fontlist
);
4024 hr
= IDWriteFontFamily_GetMatchingFonts(family
, DWRITE_FONT_WEIGHT_NORMAL
, 10,
4025 DWRITE_FONT_STYLE_NORMAL
, &fontlist
);
4026 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4027 IDWriteFontList_Release(fontlist
);
4029 hr
= IDWriteFontFamily_GetMatchingFonts(family
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STRETCH_NORMAL
,
4031 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4032 IDWriteFontList_Release(fontlist
);
4034 hr
= IDWriteFontFamily_GetMatchingFonts(family
, DWRITE_FONT_WEIGHT_NORMAL
,
4035 DWRITE_FONT_STRETCH_NORMAL
, DWRITE_FONT_STYLE_NORMAL
, &fontlist
);
4036 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4038 hr
= IDWriteFontFamily_GetMatchingFonts(family
, DWRITE_FONT_WEIGHT_NORMAL
,
4039 DWRITE_FONT_STRETCH_NORMAL
, DWRITE_FONT_STYLE_NORMAL
, &fontlist2
);
4040 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4041 ok(fontlist
!= fontlist2
, "got %p, %p\n", fontlist
, fontlist2
);
4042 IDWriteFontList_Release(fontlist2
);
4044 hr
= IDWriteFontList_QueryInterface(fontlist
, &IID_IDWriteFontList1
, (void**)&fontlist1
);
4046 IDWriteFontFaceReference
*ref
, *ref1
;
4050 count
= IDWriteFontList1_GetFontCount(fontlist1
);
4051 ok(count
> 0, "got %u\n", count
);
4053 font
= (void*)0xdeadbeef;
4054 hr
= IDWriteFontList1_GetFont(fontlist1
, ~0u, &font
);
4055 ok(hr
== E_FAIL
, "got 0x%08x\n", hr
);
4056 ok(font
== NULL
, "got %p\n", font
);
4058 font
= (void*)0xdeadbeef;
4059 hr
= IDWriteFontList1_GetFont(fontlist1
, count
, &font
);
4060 ok(hr
== E_FAIL
, "got 0x%08x\n", hr
);
4061 ok(font
== NULL
, "got %p\n", font
);
4063 hr
= IDWriteFontList1_GetFont(fontlist1
, 0, &font
);
4064 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4065 IDWriteFont3_Release(font
);
4067 hr
= IDWriteFontList1_GetFontFaceReference(fontlist1
, 0, &ref
);
4068 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4070 hr
= IDWriteFontList1_GetFontFaceReference(fontlist1
, 0, &ref1
);
4071 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4072 ok(ref
!= ref1
, "got %p, %p\n", ref
, ref1
);
4074 IDWriteFontFaceReference_Release(ref1
);
4075 IDWriteFontFaceReference_Release(ref
);
4076 IDWriteFontList1_Release(fontlist1
);
4079 win_skip("IDWriteFontList1 is not supported.\n");
4081 if (SUCCEEDED(IDWriteFontList_QueryInterface(fontlist
, &IID_IDWriteFontList2
, (void **)&fontlist3
)))
4083 IDWriteFontSet1
*fontset
, *fontset2
;
4085 hr
= IDWriteFontList2_GetFontSet(fontlist3
, &fontset
);
4086 ok(hr
== S_OK
, "Unexpected hr %#x.\n", hr
);
4088 hr
= IDWriteFontList2_GetFontSet(fontlist3
, &fontset2
);
4089 ok(hr
== S_OK
, "Unexpected hr %#x.\n", hr
);
4090 ok(fontset
!= fontset2
, "Unexpected instance.\n");
4092 IDWriteFontSet1_Release(fontset2
);
4093 IDWriteFontSet1_Release(fontset
);
4095 IDWriteFontList2_Release(fontlist3
);
4098 win_skip("IDWriteFontList2 is not supported.\n");
4100 IDWriteFontList_Release(fontlist
);
4101 IDWriteFontFamily_Release(family
);
4103 IDWriteFontCollection_Release(collection
);
4104 ref
= IDWriteFactory_Release(factory
);
4105 ok(ref
== 0, "factory not released, %u\n", ref
);
4108 static void test_GetInformationalStrings(void)
4110 IDWriteLocalizedStrings
*strings
, *strings2
;
4111 IDWriteFontCollection
*collection
;
4112 IDWriteFontFace3
*fontface3
;
4113 IDWriteFontFace
*fontface
;
4114 IDWriteFontFamily
*family
;
4115 IDWriteFactory
*factory
;
4121 factory
= create_factory();
4123 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &collection
, FALSE
);
4124 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4126 hr
= IDWriteFontCollection_GetFontFamily(collection
, 0, &family
);
4127 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4129 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
,
4130 DWRITE_FONT_STRETCH_NORMAL
, DWRITE_FONT_STYLE_NORMAL
, &font
);
4131 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4134 strings
= (void*)0xdeadbeef;
4135 hr
= IDWriteFont_GetInformationalStrings(font
, DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_CID_NAME
+1, &strings
, &exists
);
4136 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4137 ok(exists
== FALSE
, "got %d\n", exists
);
4138 ok(strings
== NULL
, "got %p\n", strings
);
4142 hr
= IDWriteFont_GetInformationalStrings(font
, DWRITE_INFORMATIONAL_STRING_NONE
, &strings
, &exists
);
4143 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4144 ok(exists
== FALSE
, "got %d\n", exists
);
4148 hr
= IDWriteFont_GetInformationalStrings(font
, DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES
, &strings
, &exists
);
4149 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4150 ok(exists
== TRUE
, "got %d\n", exists
);
4152 /* strings instance is not reused */
4154 hr
= IDWriteFont_GetInformationalStrings(font
, DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES
, &strings2
, &exists
);
4155 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4156 ok(strings2
!= strings
, "got %p, %p\n", strings2
, strings
);
4158 IDWriteLocalizedStrings_Release(strings
);
4159 IDWriteLocalizedStrings_Release(strings2
);
4161 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
4162 ok(hr
== S_OK
, "Failed to create fontface, hr %#x.\n", hr
);
4164 if (SUCCEEDED(hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace3
, (void **)&fontface3
)))
4166 hr
= IDWriteFontFace3_GetInformationalStrings(fontface3
, DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES
,
4168 ok(hr
== S_OK
, "Failed to get info strings, hr %#x.\n", hr
);
4169 IDWriteLocalizedStrings_Release(strings
);
4171 IDWriteFontFace3_Release(fontface3
);
4174 win_skip("IDWriteFontFace3::GetInformationalStrings() is not supported.\n");
4176 IDWriteFontFace_Release(fontface
);
4178 IDWriteFont_Release(font
);
4179 IDWriteFontFamily_Release(family
);
4180 IDWriteFontCollection_Release(collection
);
4181 ref
= IDWriteFactory_Release(factory
);
4182 ok(ref
== 0, "factory not released, %u\n", ref
);
4185 static void test_GetGdiInterop(void)
4187 IDWriteGdiInterop
*interop
, *interop2
;
4188 IDWriteFactory
*factory
, *factory2
;
4194 factory
= create_factory();
4197 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop
);
4198 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4201 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop2
);
4202 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4203 ok(interop
== interop2
, "got %p, %p\n", interop
, interop2
);
4204 IDWriteGdiInterop_Release(interop2
);
4206 hr
= DWriteCreateFactory(DWRITE_FACTORY_TYPE_ISOLATED
, &IID_IDWriteFactory
, (IUnknown
**)&factory2
);
4207 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4209 /* each factory gets its own interop */
4211 hr
= IDWriteFactory_GetGdiInterop(factory2
, &interop2
);
4212 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4213 ok(interop
!= interop2
, "got %p, %p\n", interop
, interop2
);
4215 /* release factory - interop still works */
4216 IDWriteFactory_Release(factory2
);
4218 memset(&logfont
, 0, sizeof(logfont
));
4219 logfont
.lfHeight
= 12;
4220 logfont
.lfWidth
= 12;
4221 logfont
.lfWeight
= FW_NORMAL
;
4222 logfont
.lfItalic
= 1;
4223 lstrcpyW(logfont
.lfFaceName
, L
"Tahoma");
4225 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop2
, &logfont
, &font
);
4226 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4227 IDWriteFont_Release(font
);
4229 IDWriteGdiInterop_Release(interop2
);
4230 IDWriteGdiInterop_Release(interop
);
4231 ref
= IDWriteFactory_Release(factory
);
4232 ok(ref
== 0, "factory not released, %u\n", ref
);
4235 static void *map_font_file(const WCHAR
*filename
, DWORD
*file_size
)
4237 HANDLE file
, mapping
;
4240 file
= CreateFileW(filename
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
, 0, 0);
4241 if (file
== INVALID_HANDLE_VALUE
) return NULL
;
4243 *file_size
= GetFileSize(file
, NULL
);
4245 mapping
= CreateFileMappingA(file
, NULL
, PAGE_READONLY
, 0, 0, NULL
);
4252 ptr
= MapViewOfFile(mapping
, FILE_MAP_READ
, 0, 0, 0);
4255 CloseHandle(mapping
);
4259 struct font_realization_info
4270 static void test_CreateFontFaceFromHdc(void)
4272 IDWriteFontFileStream
*stream
, *stream2
;
4273 void *font_data
, *fragment_context
;
4274 struct font_realization_info info
;
4275 const void *refkey
, *fragment
;
4276 IDWriteFontFileLoader
*loader
;
4277 DWORD data_size
, num_fonts
;
4278 IDWriteGdiInterop
*interop
;
4279 IDWriteFontFace
*fontface
;
4280 IDWriteFactory
*factory
;
4281 UINT64 size
, writetime
;
4282 IDWriteFontFile
*file
;
4283 HFONT hfont
, oldhfont
;
4284 UINT32 count
, dummy
;
4295 factory
= create_factory();
4297 pGetFontRealizationInfo
= (void *)GetProcAddress(GetModuleHandleA("gdi32"), "GetFontRealizationInfo");
4300 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop
);
4301 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4304 fontface
= (void*)0xdeadbeef;
4305 hr
= IDWriteGdiInterop_CreateFontFaceFromHdc(interop
, NULL
, &fontface
);
4306 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
4307 ok(fontface
== NULL
, "got %p\n", fontface
);
4309 fontface
= (void *)0xdeadbeef;
4310 hr
= IDWriteGdiInterop_CreateFontFaceFromHdc(interop
, (HDC
)0xdeadbeef, &fontface
);
4311 ok(hr
== E_FAIL
, "got 0x%08x\n", hr
);
4312 ok(fontface
== NULL
, "got %p\n", fontface
);
4314 memset(&logfont
, 0, sizeof(logfont
));
4315 logfont
.lfHeight
= 12;
4316 logfont
.lfWidth
= 12;
4317 logfont
.lfWeight
= FW_NORMAL
;
4318 logfont
.lfItalic
= 1;
4319 lstrcpyW(logfont
.lfFaceName
, L
"Tahoma");
4321 hfont
= CreateFontIndirectW(&logfont
);
4322 hdc
= CreateCompatibleDC(0);
4323 oldhfont
= SelectObject(hdc
, hfont
);
4326 hr
= IDWriteGdiInterop_CreateFontFaceFromHdc(interop
, hdc
, &fontface
);
4327 ok(hr
== S_OK
, "Failed to create font face, hr %#x.\n", hr
);
4330 hr
= IDWriteFontFace_GetFiles(fontface
, &count
, &file
);
4331 ok(hr
== S_OK
, "Failed to get font files, hr %#x.\n", hr
);
4333 hr
= IDWriteFontFile_GetLoader(file
, &loader
);
4334 ok(hr
== S_OK
, "Failed to get file loader, hr %#x.\n", hr
);
4336 hr
= IDWriteFontFileLoader_QueryInterface(loader
, &IID_IDWriteLocalFontFileLoader
, (void **)&unk
);
4337 ok(hr
== S_OK
|| broken(hr
== E_NOINTERFACE
) /* Vista */, "Expected local loader, hr %#x.\n", hr
);
4339 IUnknown_Release(unk
);
4341 IDWriteFontFileLoader_Release(loader
);
4342 IDWriteFontFile_Release(file
);
4344 IDWriteFontFace_Release(fontface
);
4345 DeleteObject(SelectObject(hdc
, oldhfont
));
4347 /* Select bitmap font MS Sans Serif, format that's not supported by DirectWrite. */
4348 memset(&lf
, 0, sizeof(lf
));
4350 strcpy(lf
.lfFaceName
, "MS Sans Serif");
4352 hfont
= CreateFontIndirectA(&lf
);
4353 oldhfont
= SelectObject(hdc
, hfont
);
4355 fontface
= (void *)0xdeadbeef;
4356 hr
= IDWriteGdiInterop_CreateFontFaceFromHdc(interop
, hdc
, &fontface
);
4357 ok(hr
== DWRITE_E_FILEFORMAT
|| broken(hr
== E_FAIL
) /* Vista */, "got 0x%08x\n", hr
);
4358 ok(fontface
== NULL
, "got %p\n", fontface
);
4360 DeleteObject(SelectObject(hdc
, oldhfont
));
4362 /* Memory resource font */
4363 path
= create_testfontfile(test_fontfile
);
4366 font_data
= map_font_file(path
, &data_size
);
4369 resource
= AddFontMemResourceEx(font_data
, data_size
, NULL
, &num_fonts
);
4370 ok(resource
!= NULL
, "Failed to add memory resource font, %d.\n", GetLastError());
4371 ok(num_fonts
== 1, "Unexpected number of fonts.\n");
4373 memset(&lf
, 0, sizeof(lf
));
4375 strcpy(lf
.lfFaceName
, "wine_test");
4377 hfont
= CreateFontIndirectA(&lf
);
4378 ok(hfont
!= NULL
, "Failed to create a font.\n");
4379 oldhfont
= SelectObject(hdc
, hfont
);
4381 hr
= IDWriteGdiInterop_CreateFontFaceFromHdc(interop
, hdc
, &fontface
);
4382 ok(hr
== S_OK
, "Failed to create fontface, hr %#x.\n", hr
);
4385 hr
= IDWriteFontFace_GetFiles(fontface
, &count
, &file
);
4386 ok(hr
== S_OK
, "Failed to get font files, hr %#x.\n", hr
);
4388 hr
= IDWriteFontFile_GetLoader(file
, &loader
);
4389 ok(hr
== S_OK
, "Failed to get file loader, hr %#x.\n", hr
);
4391 hr
= IDWriteFactory_RegisterFontFileLoader(factory
, loader
);
4392 ok(hr
== DWRITE_E_ALREADYREGISTERED
, "Unexpected hr %#x.\n", hr
);
4394 hr
= IDWriteFontFileLoader_QueryInterface(loader
, &IID_IDWriteInMemoryFontFileLoader
, (void **)&unk
);
4395 ok(hr
== E_NOINTERFACE
, "Unexpected hr %#x.\n", hr
);
4397 hr
= IDWriteFontFileLoader_QueryInterface(loader
, &IID_IDWriteLocalFontFileLoader
, (void **)&unk
);
4398 ok(hr
== E_NOINTERFACE
, "Unexpected hr %#x.\n", hr
);
4401 hr
= IDWriteFontFile_GetReferenceKey(file
, &refkey
, &count
);
4402 ok(hr
== S_OK
, "Failed to get ref key, hr %#x.\n", hr
);
4403 ok(count
> 0, "Unexpected key length %u.\n", count
);
4405 if (pGetFontRealizationInfo
)
4407 info
.size
= sizeof(info
);
4408 ret
= pGetFontRealizationInfo(hdc
, &info
);
4409 ok(ret
, "Failed to get realization info.\n");
4410 ok(count
== sizeof(info
.instance_id
), "Unexpected key size.\n");
4411 ok(*(DWORD
*)refkey
== info
.instance_id
, "Unexpected stream key.\n");
4414 win_skip("GetFontRealizationInfo() is not available.\n");
4416 hr
= IDWriteFontFileLoader_CreateStreamFromKey(loader
, refkey
, count
, &stream
);
4417 ok(hr
== S_OK
, "Failed to create file stream, hr %#x.\n", hr
);
4419 hr
= IDWriteFontFileLoader_CreateStreamFromKey(loader
, refkey
, count
, &stream2
);
4420 ok(hr
== S_OK
, "Failed to create file stream, hr %#x.\n", hr
);
4421 ok(stream2
!= stream
, "Unexpected stream instance.\n");
4422 IDWriteFontFileStream_Release(stream2
);
4425 hr
= IDWriteFontFileLoader_CreateStreamFromKey(loader
, &dummy
, count
, &stream2
);
4426 ok(hr
== S_OK
, "Failed to create file stream, hr %#x.\n", hr
);
4429 hr
= IDWriteFontFileStream_GetLastWriteTime(stream2
, &writetime
);
4430 ok(hr
== E_NOTIMPL
, "Unexpected hr %#x.\n", hr
);
4431 ok(writetime
== 1, "Unexpected write time.\n");
4433 IDWriteFontFileStream_Release(stream2
);
4435 hr
= IDWriteFontFileStream_GetFileSize(stream
, &size
);
4436 ok(hr
== S_OK
, "Failed to get stream size, hr %#x.\n", hr
);
4437 ok(size
== data_size
, "Unexpected stream size.\n");
4439 hr
= IDWriteFontFileStream_GetLastWriteTime(stream
, &writetime
);
4440 ok(hr
== E_NOTIMPL
, "Unexpected hr %#x.\n", hr
);
4442 fragment_context
= NULL
;
4443 hr
= IDWriteFontFileStream_ReadFileFragment(stream
, &fragment
, 0, size
, &fragment_context
);
4444 ok(hr
== S_OK
, "Failed to read fragment, hr %#x.\n", hr
);
4445 ok(fragment_context
!= NULL
, "Unexpected context %p.\n", fragment_context
);
4446 ok(fragment
== fragment_context
, "Unexpected data pointer %p, context %p.\n", fragment
, fragment_context
);
4447 IDWriteFontFileStream_ReleaseFileFragment(stream
, fragment_context
);
4449 hr
= IDWriteFontFileStream_ReadFileFragment(stream
, &fragment
, 0, size
+ 1, &fragment_context
);
4450 ok(FAILED(hr
), "Unexpected hr %#x.\n", hr
);
4452 hr
= IDWriteFontFileStream_ReadFileFragment(stream
, &fragment
, size
- 1, size
/ 2, &fragment_context
);
4453 ok(FAILED(hr
), "Unexpected hr %#x.\n", hr
);
4455 IDWriteFontFileStream_Release(stream
);
4457 IDWriteFontFileLoader_Release(loader
);
4458 IDWriteFontFile_Release(file
);
4460 IDWriteFontFace_Release(fontface
);
4462 ret
= RemoveFontMemResourceEx(resource
);
4463 ok(ret
, "Failed to remove memory resource font, %d.\n", GetLastError());
4465 UnmapViewOfFile(font_data
);
4467 DELETE_FONTFILE(path
);
4469 DeleteObject(SelectObject(hdc
, oldhfont
));
4471 IDWriteGdiInterop_Release(interop
);
4472 ref
= IDWriteFactory_Release(factory
);
4473 ok(ref
== 0, "factory not released, %u\n", ref
);
4476 static void test_GetSimulations(void)
4478 DWRITE_FONT_SIMULATIONS simulations
;
4479 IDWriteGdiInterop
*interop
;
4480 IDWriteFontFace
*fontface
;
4481 IDWriteFactory
*factory
;
4487 factory
= create_factory();
4489 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop
);
4490 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4492 memset(&logfont
, 0, sizeof(logfont
));
4493 logfont
.lfHeight
= 12;
4494 logfont
.lfWidth
= 12;
4495 logfont
.lfWeight
= FW_NORMAL
;
4496 logfont
.lfItalic
= 1;
4497 lstrcpyW(logfont
.lfFaceName
, L
"Tahoma");
4499 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font
);
4500 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4502 simulations
= IDWriteFont_GetSimulations(font
);
4503 ok(simulations
== DWRITE_FONT_SIMULATIONS_OBLIQUE
, "got %d\n", simulations
);
4504 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
4505 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4506 simulations
= IDWriteFontFace_GetSimulations(fontface
);
4507 ok(simulations
== DWRITE_FONT_SIMULATIONS_OBLIQUE
, "got %d\n", simulations
);
4508 IDWriteFontFace_Release(fontface
);
4509 IDWriteFont_Release(font
);
4511 memset(&logfont
, 0, sizeof(logfont
));
4512 logfont
.lfHeight
= 12;
4513 logfont
.lfWidth
= 12;
4514 logfont
.lfWeight
= FW_NORMAL
;
4515 logfont
.lfItalic
= 0;
4516 lstrcpyW(logfont
.lfFaceName
, L
"Tahoma");
4518 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font
);
4519 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4521 simulations
= IDWriteFont_GetSimulations(font
);
4522 ok(simulations
== DWRITE_FONT_SIMULATIONS_NONE
, "got %d\n", simulations
);
4523 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
4524 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4525 simulations
= IDWriteFontFace_GetSimulations(fontface
);
4526 ok(simulations
== DWRITE_FONT_SIMULATIONS_NONE
, "got %d\n", simulations
);
4527 IDWriteFontFace_Release(fontface
);
4528 IDWriteFont_Release(font
);
4530 IDWriteGdiInterop_Release(interop
);
4531 ref
= IDWriteFactory_Release(factory
);
4532 ok(ref
== 0, "factory not released, %u\n", ref
);
4535 static void test_GetFaceNames(void)
4537 IDWriteLocalizedStrings
*strings
, *strings2
, *strings3
;
4538 IDWriteFontFace3
*fontface3
;
4539 IDWriteGdiInterop
*interop
;
4540 IDWriteFontFace
*fontface
;
4541 IDWriteFactory
*factory
;
4542 UINT32 count
, index
;
4550 factory
= create_factory();
4552 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop
);
4553 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4555 memset(&logfont
, 0, sizeof(logfont
));
4556 logfont
.lfHeight
= 12;
4557 logfont
.lfWidth
= 12;
4558 logfont
.lfWeight
= FW_NORMAL
;
4559 logfont
.lfItalic
= 1;
4560 lstrcpyW(logfont
.lfFaceName
, L
"Tahoma");
4562 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font
);
4563 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4565 hr
= IDWriteFont_GetFaceNames(font
, &strings
);
4566 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4568 hr
= IDWriteFont_GetFaceNames(font
, &strings2
);
4569 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4570 ok(strings
!= strings2
, "got %p, %p\n", strings2
, strings
);
4571 IDWriteLocalizedStrings_Release(strings2
);
4573 count
= IDWriteLocalizedStrings_GetCount(strings
);
4574 ok(count
== 1, "got %d\n", count
);
4578 hr
= IDWriteLocalizedStrings_FindLocaleName(strings
, L
"en-Us", &index
, &exists
);
4579 ok(hr
== S_OK
, "Unexpected hr %#x.\n", hr
);
4580 ok(index
== 0 && exists
, "got %d, %d\n", index
, exists
);
4583 hr
= IDWriteLocalizedStrings_GetLocaleNameLength(strings
, 1, &count
);
4584 ok(hr
== E_FAIL
, "got 0x%08x\n", hr
);
4585 ok(count
== ~0, "got %d\n", count
);
4587 /* for simulated faces names are also simulated */
4589 hr
= IDWriteLocalizedStrings_GetLocaleName(strings
, 0, buffW
, ARRAY_SIZE(buffW
));
4590 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4591 ok(!lstrcmpW(buffW
, L
"en-us"), "Unexpected locale name %s.\n", wine_dbgstr_w(buffW
));
4594 hr
= IDWriteLocalizedStrings_GetString(strings
, 0, buffW
, ARRAY_SIZE(buffW
));
4595 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4596 ok(!lstrcmpW(buffW
, L
"Oblique"), "got %s\n", wine_dbgstr_w(buffW
));
4597 IDWriteLocalizedStrings_Release(strings
);
4599 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
4600 ok(hr
== S_OK
, "Failed to create a font face, hr %#x.\n", hr
);
4602 if (SUCCEEDED(IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace3
, (void **)&fontface3
)))
4604 hr
= IDWriteFontFace3_GetFaceNames(fontface3
, &strings2
);
4605 ok(hr
== S_OK
, "Failed to get face names, hr %#x.\n", hr
);
4607 hr
= IDWriteFontFace3_GetFaceNames(fontface3
, &strings3
);
4608 ok(hr
== S_OK
, "Failed to get face names, hr %#x.\n", hr
);
4609 ok(strings2
!= strings3
, "Unexpected instance.\n");
4610 IDWriteLocalizedStrings_Release(strings3
);
4613 hr
= IDWriteLocalizedStrings_GetString(strings2
, 0, buffW
, ARRAY_SIZE(buffW
));
4614 ok(hr
== S_OK
, "Failed to get a string, hr %#x.\n", hr
);
4615 ok(!lstrcmpW(buffW
, L
"Oblique"), "Unexpected name %s.\n", wine_dbgstr_w(buffW
));
4616 IDWriteLocalizedStrings_Release(strings2
);
4618 IDWriteFontFace3_Release(fontface3
);
4621 win_skip("GetFaceNames() is not supported.\n");
4623 IDWriteFontFace_Release(fontface
);
4625 IDWriteFont_Release(font
);
4626 IDWriteGdiInterop_Release(interop
);
4627 ref
= IDWriteFactory_Release(factory
);
4628 ok(ref
== 0, "factory not released, %u\n", ref
);
4637 static void test_TryGetFontTable(void)
4639 IDWriteLocalFontFileLoader
*localloader
;
4640 WIN32_FILE_ATTRIBUTE_DATA info
;
4641 const struct local_refkey
*key
;
4642 IDWriteFontFileLoader
*loader
;
4643 const void *table
, *table2
;
4644 IDWriteFontFace
*fontface
;
4645 void *context
, *context2
;
4646 IDWriteFactory
*factory
;
4647 IDWriteFontFile
*file
;
4648 WCHAR buffW
[MAX_PATH
];
4655 path
= create_testfontfile(test_fontfile
);
4657 factory
= create_factory();
4659 hr
= IDWriteFactory_CreateFontFileReference(factory
, path
, NULL
, &file
);
4660 ok(hr
== S_OK
, "got 0x%08x\n",hr
);
4664 hr
= IDWriteFontFile_GetReferenceKey(file
, (const void**)&key
, &size
);
4665 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4666 ok(size
!= 0, "got %u\n", size
);
4668 ret
= GetFileAttributesExW(path
, GetFileExInfoStandard
, &info
);
4669 ok(ret
, "got %d\n", ret
);
4670 ok(!memcmp(&info
.ftLastWriteTime
, &key
->writetime
, sizeof(key
->writetime
)), "got wrong write time\n");
4672 hr
= IDWriteFontFile_GetLoader(file
, &loader
);
4673 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4674 IDWriteFontFileLoader_QueryInterface(loader
, &IID_IDWriteLocalFontFileLoader
, (void**)&localloader
);
4675 IDWriteFontFileLoader_Release(loader
);
4677 hr
= IDWriteLocalFontFileLoader_GetFilePathLengthFromKey(localloader
, key
, size
, &len
);
4678 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4679 ok(lstrlenW(key
->name
) == len
, "path length %d\n", len
);
4681 hr
= IDWriteLocalFontFileLoader_GetFilePathFromKey(localloader
, key
, size
, buffW
, ARRAY_SIZE(buffW
));
4682 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4683 ok(!lstrcmpW(buffW
, key
->name
), "got %s, expected %s\n", wine_dbgstr_w(buffW
), wine_dbgstr_w(key
->name
));
4684 IDWriteLocalFontFileLoader_Release(localloader
);
4686 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_TRUETYPE
, 1, &file
, 0, 0, &fontface
);
4687 ok(hr
== S_OK
, "got 0x%08x\n",hr
);
4690 context
= (void*)0xdeadbeef;
4692 hr
= IDWriteFontFace_TryGetFontTable(fontface
, MS_CMAP_TAG
, &table
, &size
, &context
, &exists
);
4693 ok(hr
== S_OK
, "got 0x%08x\n",hr
);
4694 ok(exists
== TRUE
, "got %d\n", exists
);
4695 ok(context
== NULL
&& table
!= NULL
, "cmap: context %p, table %p\n", context
, table
);
4698 context2
= (void*)0xdeadbeef;
4700 hr
= IDWriteFontFace_TryGetFontTable(fontface
, MS_CMAP_TAG
, &table2
, &size
, &context2
, &exists
);
4701 ok(hr
== S_OK
, "got 0x%08x\n",hr
);
4702 ok(exists
== TRUE
, "got %d\n", exists
);
4703 ok(context2
== context
&& table2
== table
, "cmap: context2 %p, table2 %p\n", context2
, table2
);
4705 IDWriteFontFace_ReleaseFontTable(fontface
, context2
);
4706 IDWriteFontFace_ReleaseFontTable(fontface
, context
);
4708 /* table does not exist */
4710 context
= (void*)0xdeadbeef;
4711 table
= (void*)0xdeadbeef;
4712 hr
= IDWriteFontFace_TryGetFontTable(fontface
, 0xabababab, &table
, &size
, &context
, &exists
);
4713 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4714 ok(exists
== FALSE
, "got %d\n", exists
);
4715 ok(context
== NULL
&& table
== NULL
, "got context %p, table pointer %p\n", context
, table
);
4717 IDWriteFontFace_Release(fontface
);
4718 IDWriteFontFile_Release(file
);
4719 ref
= IDWriteFactory_Release(factory
);
4720 ok(ref
== 0, "factory not released, %u\n", ref
);
4721 DELETE_FONTFILE(path
);
4724 static void test_ConvertFontToLOGFONT(void)
4726 IDWriteFactory
*factory
, *factory2
;
4727 IDWriteFontCollection
*collection
;
4728 IDWriteGdiInterop
*interop
;
4729 IDWriteFontFamily
*family
;
4737 factory
= create_factory();
4738 factory2
= create_factory();
4741 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop
);
4742 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4744 hr
= IDWriteFactory_GetSystemFontCollection(factory2
, &collection
, FALSE
);
4745 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4747 hr
= IDWriteFontCollection_GetFontFamily(collection
, 0, &family
);
4748 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4750 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
,
4751 DWRITE_FONT_STRETCH_NORMAL
, DWRITE_FONT_STYLE_NORMAL
, &font
);
4752 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4754 if (0) { /* crashes on native */
4755 IDWriteGdiInterop_ConvertFontToLOGFONT(interop
, NULL
, NULL
, NULL
);
4756 IDWriteGdiInterop_ConvertFontToLOGFONT(interop
, NULL
, &logfont
, NULL
);
4757 IDWriteGdiInterop_ConvertFontToLOGFONT(interop
, font
, NULL
, &system
);
4760 memset(&logfont
, 0xcc, sizeof(logfont
));
4762 hr
= IDWriteGdiInterop_ConvertFontToLOGFONT(interop
, NULL
, &logfont
, &system
);
4763 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
4764 ok(!system
, "got %d\n", system
);
4765 ok(logfont
.lfFaceName
[0] == 0, "got face name %s\n", wine_dbgstr_w(logfont
.lfFaceName
));
4767 count
= IDWriteFontCollection_GetFontFamilyCount(collection
);
4768 for (i
= 0; i
< count
; i
++) {
4769 WCHAR nameW
[128], familynameW
[64], facenameW
[64];
4770 IDWriteLocalizedStrings
*names
;
4771 DWRITE_FONT_SIMULATIONS sim
;
4772 IDWriteFontFamily
*family
;
4773 UINT32 font_count
, j
;
4777 hr
= IDWriteFontCollection_GetFontFamily(collection
, i
, &family
);
4778 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4780 hr
= IDWriteFontFamily_GetFamilyNames(family
, &names
);
4781 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4783 get_enus_string(names
, familynameW
, ARRAY_SIZE(familynameW
));
4784 IDWriteLocalizedStrings_Release(names
);
4786 font_count
= IDWriteFontFamily_GetFontCount(family
);
4788 for (j
= 0; j
< font_count
; ++j
)
4790 IDWriteFontFace
*fontface
;
4791 BOOL has_variations
;
4793 hr
= IDWriteFontFamily_GetFont(family
, j
, &font
);
4794 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4796 hr
= IDWriteFont_GetFaceNames(font
, &names
);
4797 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4799 get_enus_string(names
, facenameW
, ARRAY_SIZE(facenameW
));
4800 IDWriteLocalizedStrings_Release(names
);
4802 lstrcpyW(nameW
, familynameW
);
4803 lstrcatW(nameW
, L
" ");
4804 lstrcatW(nameW
, facenameW
);
4806 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
4807 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4809 has_variations
= has_face_variations(fontface
);
4810 IDWriteFontFace_Release(fontface
);
4812 if (has_variations
) {
4813 skip("%s: test does not support variable fonts.\n", wine_dbgstr_w(nameW
));
4814 IDWriteFont_Release(font
);
4819 memset(&logfont
, 0xcc, sizeof(logfont
));
4820 hr
= IDWriteGdiInterop_ConvertFontToLOGFONT(interop
, font
, &logfont
, &system
);
4821 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4822 ok(system
, "got %d\n", system
);
4824 sim
= IDWriteFont_GetSimulations(font
);
4826 get_logfont_from_font(font
, &lf
);
4827 ok(logfont
.lfWeight
== lf
.lfWeight
, "%s: unexpected lfWeight %d, expected lfWeight %d, font weight %d, "
4828 "bold simulation %s\n", wine_dbgstr_w(nameW
), logfont
.lfWeight
, lf
.lfWeight
, IDWriteFont_GetWeight(font
),
4829 sim
& DWRITE_FONT_SIMULATIONS_BOLD
? "yes" : "no");
4830 ok(logfont
.lfItalic
== lf
.lfItalic
, "%s: unexpected italic flag %d, oblique simulation %s\n",
4831 wine_dbgstr_w(nameW
), logfont
.lfItalic
, sim
& DWRITE_FONT_SIMULATIONS_OBLIQUE
? "yes" : "no");
4832 ok(!lstrcmpW(logfont
.lfFaceName
, lf
.lfFaceName
), "%s: unexpected facename %s, expected %s\n",
4833 wine_dbgstr_w(nameW
), wine_dbgstr_w(logfont
.lfFaceName
), wine_dbgstr_w(lf
.lfFaceName
));
4835 ok(logfont
.lfOutPrecision
== OUT_OUTLINE_PRECIS
, "%s: unexpected output precision %d\n", wine_dbgstr_w(nameW
),
4836 logfont
.lfOutPrecision
);
4837 ok(logfont
.lfClipPrecision
== CLIP_DEFAULT_PRECIS
, "%s: unexpected clipping precision %d\n", wine_dbgstr_w(nameW
),
4838 logfont
.lfClipPrecision
);
4839 ok(logfont
.lfQuality
== DEFAULT_QUALITY
, "%s: unexpected quality %d\n", wine_dbgstr_w(nameW
), logfont
.lfQuality
);
4840 ok(logfont
.lfPitchAndFamily
== DEFAULT_PITCH
, "%s: unexpected pitch %d\n", wine_dbgstr_w(nameW
),
4841 logfont
.lfPitchAndFamily
);
4843 IDWriteFont_Release(font
);
4846 IDWriteFontFamily_Release(family
);
4849 IDWriteFactory_Release(factory2
);
4851 IDWriteFontCollection_Release(collection
);
4852 IDWriteFontFamily_Release(family
);
4853 IDWriteFont_Release(font
);
4854 IDWriteGdiInterop_Release(interop
);
4855 ref
= IDWriteFactory_Release(factory
);
4856 ok(ref
== 0, "factory not released, %u\n", ref
);
4859 static void test_CreateStreamFromKey(void)
4861 IDWriteLocalFontFileLoader
*localloader
;
4862 IDWriteFontFileStream
*stream
, *stream2
;
4863 IDWriteFontFileLoader
*loader
;
4864 IDWriteFactory
*factory
;
4865 IDWriteFontFile
*file
;
4873 factory
= create_factory();
4875 path
= create_testfontfile(test_fontfile
);
4877 hr
= IDWriteFactory_CreateFontFileReference(factory
, path
, NULL
, &file
);
4878 ok(hr
== S_OK
, "got 0x%08x\n",hr
);
4882 hr
= IDWriteFontFile_GetReferenceKey(file
, (const void**)&key
, &size
);
4883 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4884 ok(size
!= 0, "got %u\n", size
);
4886 hr
= IDWriteFontFile_GetLoader(file
, &loader
);
4887 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4888 IDWriteFontFileLoader_QueryInterface(loader
, &IID_IDWriteLocalFontFileLoader
, (void**)&localloader
);
4889 IDWriteFontFileLoader_Release(loader
);
4891 hr
= IDWriteLocalFontFileLoader_CreateStreamFromKey(localloader
, key
, size
, &stream
);
4892 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4893 EXPECT_REF(stream
, 1);
4895 hr
= IDWriteLocalFontFileLoader_CreateStreamFromKey(localloader
, key
, size
, &stream2
);
4896 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4897 ok(stream
== stream2
|| broken(stream
!= stream2
) /* Win7 SP0 */, "got %p, %p\n", stream
, stream2
);
4898 if (stream
== stream2
)
4899 EXPECT_REF(stream
, 2);
4900 IDWriteFontFileStream_Release(stream
);
4901 IDWriteFontFileStream_Release(stream2
);
4903 hr
= IDWriteLocalFontFileLoader_CreateStreamFromKey(localloader
, key
, size
, &stream
);
4904 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4905 EXPECT_REF(stream
, 1);
4908 hr
= IDWriteFontFileStream_GetLastWriteTime(stream
, &writetime
);
4909 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4910 ok(writetime
!= 0, "got %s\n", wine_dbgstr_longlong(writetime
));
4912 IDWriteFontFileStream_Release(stream
);
4913 IDWriteFontFile_Release(file
);
4915 IDWriteLocalFontFileLoader_Release(localloader
);
4916 ref
= IDWriteFactory_Release(factory
);
4917 ok(ref
== 0, "factory not released, %u\n", ref
);
4918 DELETE_FONTFILE(path
);
4921 static void test_ReadFileFragment(void)
4923 IDWriteLocalFontFileLoader
*localloader
;
4924 IDWriteFontFileStream
*stream
;
4925 IDWriteFontFileLoader
*loader
;
4926 IDWriteFactory
*factory
;
4927 IDWriteFontFile
*file
;
4928 const void *fragment
, *fragment2
;
4929 void *key
, *context
, *context2
;
4936 factory
= create_factory();
4938 path
= create_testfontfile(test_fontfile
);
4940 hr
= IDWriteFactory_CreateFontFileReference(factory
, path
, NULL
, &file
);
4941 ok(hr
== S_OK
, "got 0x%08x\n",hr
);
4945 hr
= IDWriteFontFile_GetReferenceKey(file
, (const void**)&key
, &size
);
4946 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4947 ok(size
!= 0, "got %u\n", size
);
4949 hr
= IDWriteFontFile_GetLoader(file
, &loader
);
4950 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4951 IDWriteFontFileLoader_QueryInterface(loader
, &IID_IDWriteLocalFontFileLoader
, (void**)&localloader
);
4952 IDWriteFontFileLoader_Release(loader
);
4954 hr
= IDWriteLocalFontFileLoader_CreateStreamFromKey(localloader
, key
, size
, &stream
);
4955 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4957 hr
= IDWriteFontFileStream_GetFileSize(stream
, &filesize
);
4958 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4960 /* reading past the end of the stream */
4961 fragment
= (void*)0xdeadbeef;
4962 context
= (void*)0xdeadbeef;
4963 hr
= IDWriteFontFileStream_ReadFileFragment(stream
, &fragment
, 0, filesize
+1, &context
);
4964 ok(hr
== E_FAIL
, "got 0x%08x\n", hr
);
4965 ok(context
== NULL
, "got %p\n", context
);
4966 ok(fragment
== NULL
, "got %p\n", fragment
);
4968 fragment
= (void*)0xdeadbeef;
4969 context
= (void*)0xdeadbeef;
4970 hr
= IDWriteFontFileStream_ReadFileFragment(stream
, &fragment
, 0, filesize
, &context
);
4971 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4972 ok(context
== NULL
, "got %p\n", context
);
4973 ok(fragment
!= NULL
, "got %p\n", fragment
);
4975 fragment2
= (void*)0xdeadbeef;
4976 context2
= (void*)0xdeadbeef;
4977 hr
= IDWriteFontFileStream_ReadFileFragment(stream
, &fragment2
, 0, filesize
, &context2
);
4978 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4979 ok(context2
== NULL
, "got %p\n", context2
);
4980 ok(fragment
== fragment2
, "got %p, %p\n", fragment
, fragment2
);
4982 IDWriteFontFileStream_ReleaseFileFragment(stream
, context
);
4983 IDWriteFontFileStream_ReleaseFileFragment(stream
, context2
);
4985 /* fragment is released, try again */
4986 fragment
= (void*)0xdeadbeef;
4987 context
= (void*)0xdeadbeef;
4988 hr
= IDWriteFontFileStream_ReadFileFragment(stream
, &fragment
, 0, filesize
, &context
);
4989 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4990 ok(context
== NULL
, "got %p\n", context
);
4991 ok(fragment
== fragment2
, "got %p, %p\n", fragment
, fragment2
);
4992 IDWriteFontFileStream_ReleaseFileFragment(stream
, context
);
4994 IDWriteFontFile_Release(file
);
4995 IDWriteFontFileStream_Release(stream
);
4996 IDWriteLocalFontFileLoader_Release(localloader
);
4997 ref
= IDWriteFactory_Release(factory
);
4998 ok(ref
== 0, "factory not released, %u\n", ref
);
4999 DELETE_FONTFILE(path
);
5002 static void test_GetDesignGlyphMetrics(void)
5004 DWRITE_GLYPH_METRICS metrics
[2];
5005 IDWriteFontFace
*fontface
;
5006 IDWriteFactory
*factory
;
5007 IDWriteFontFile
*file
;
5014 factory
= create_factory();
5016 path
= create_testfontfile(test_fontfile
);
5018 hr
= IDWriteFactory_CreateFontFileReference(factory
, path
, NULL
, &file
);
5019 ok(hr
== S_OK
, "got 0x%08x\n",hr
);
5021 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_TRUETYPE
, 1, &file
,
5022 0, DWRITE_FONT_SIMULATIONS_NONE
, &fontface
);
5023 ok(hr
== S_OK
, "got 0x%08x\n",hr
);
5024 IDWriteFontFile_Release(file
);
5028 hr
= IDWriteFontFace_GetGlyphIndices(fontface
, &codepoint
, 1, &indices
[0]);
5029 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5030 ok(indices
[0] > 0, "got %u\n", indices
[0]);
5032 hr
= IDWriteFontFace_GetDesignGlyphMetrics(fontface
, NULL
, 0, metrics
, FALSE
);
5033 ok(hr
== E_INVALIDARG
, "got 0x%08x\n",hr
);
5035 hr
= IDWriteFontFace_GetDesignGlyphMetrics(fontface
, NULL
, 1, metrics
, FALSE
);
5036 ok(hr
== E_INVALIDARG
, "got 0x%08x\n",hr
);
5038 hr
= IDWriteFontFace_GetDesignGlyphMetrics(fontface
, indices
, 0, metrics
, FALSE
);
5039 ok(hr
== S_OK
, "got 0x%08x\n",hr
);
5041 /* missing glyphs are ignored */
5043 memset(metrics
, 0xcc, sizeof(metrics
));
5044 hr
= IDWriteFontFace_GetDesignGlyphMetrics(fontface
, indices
, 2, metrics
, FALSE
);
5045 ok(hr
== S_OK
, "got 0x%08x\n",hr
);
5046 ok(metrics
[0].advanceWidth
== 1000, "got %d\n", metrics
[0].advanceWidth
);
5047 ok(metrics
[1].advanceWidth
== 0, "got %d\n", metrics
[1].advanceWidth
);
5049 IDWriteFontFace_Release(fontface
);
5050 ref
= IDWriteFactory_Release(factory
);
5051 ok(ref
== 0, "factory not released, %u\n", ref
);
5052 DELETE_FONTFILE(path
);
5055 static BOOL
get_expected_is_monospaced(IDWriteFontFace1
*fontface
, const DWRITE_PANOSE
*panose
)
5057 BOOL exists
, is_monospaced
= FALSE
;
5058 const TT_POST
*tt_post
;
5063 hr
= IDWriteFontFace1_TryGetFontTable(fontface
, MS_POST_TAG
, (const void **)&tt_post
, &size
,
5064 &post_context
, &exists
);
5065 ok(hr
== S_OK
, "Unexpected hr %#x.\n", hr
);
5069 is_monospaced
= !!tt_post
->fixed_pitch
;
5070 IDWriteFontFace1_ReleaseFontTable(fontface
, post_context
);
5074 is_monospaced
|= panose
->text
.proportion
== DWRITE_PANOSE_PROPORTION_MONOSPACED
;
5076 return is_monospaced
;
5079 static void test_IsMonospacedFont(void)
5081 IDWriteFontCollection
*collection
;
5082 IDWriteFactory1
*factory
;
5087 factory
= create_factory_iid(&IID_IDWriteFactory1
);
5091 win_skip("IsMonospacedFont() is not supported.\n");
5095 hr
= IDWriteFactory1_GetSystemFontCollection(factory
, &collection
, FALSE
);
5096 ok(hr
== S_OK
, "Failed to get font collection, hr %#x.\n", hr
);
5098 count
= IDWriteFontCollection_GetFontFamilyCount(collection
);
5099 for (i
= 0; i
< count
; ++i
)
5101 IDWriteLocalizedStrings
*names
;
5102 IDWriteFontFamily
*family
;
5103 UINT32 font_count
, j
;
5106 hr
= IDWriteFontCollection_GetFontFamily(collection
, i
, &family
);
5107 ok(hr
== S_OK
, "Failed to get family, hr %#x.\n", hr
);
5109 hr
= IDWriteFontFamily_GetFamilyNames(family
, &names
);
5110 ok(hr
== S_OK
, "Failed to get names, hr %#x.\n", hr
);
5111 get_enus_string(names
, nameW
, ARRAY_SIZE(nameW
));
5112 IDWriteLocalizedStrings_Release(names
);
5114 font_count
= IDWriteFontFamily_GetFontCount(family
);
5116 for (j
= 0; j
< font_count
; ++j
)
5118 BOOL is_monospaced_font
, is_monospaced_face
, is_monospaced_expected
;
5119 IDWriteFontFace1
*fontface1
;
5120 IDWriteFontFace
*fontface
;
5121 DWRITE_PANOSE panose
;
5122 IDWriteFont1
*font1
;
5125 hr
= IDWriteFontFamily_GetFont(family
, j
, &font
);
5126 ok(hr
== S_OK
, "Failed to get font, hr %#x.\n", hr
);
5128 hr
= IDWriteFont_QueryInterface(font
, &IID_IDWriteFont1
, (void **)&font1
);
5129 ok(hr
== S_OK
, "Failed to get interface, hr %#x.\n", hr
);
5130 IDWriteFont_Release(font
);
5132 hr
= IDWriteFont1_CreateFontFace(font1
, &fontface
);
5133 ok(hr
== S_OK
, "Failed to create fontface, hr %#x.\n", hr
);
5135 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void **)&fontface1
);
5136 ok(hr
== S_OK
, "Failed to get interface, hr %#x.\n", hr
);
5137 IDWriteFontFace_Release(fontface
);
5139 is_monospaced_font
= IDWriteFont1_IsMonospacedFont(font1
);
5140 is_monospaced_face
= IDWriteFontFace1_IsMonospacedFont(fontface1
);
5141 ok(is_monospaced_font
== is_monospaced_face
, "Unexpected monospaced flag.\n");
5143 IDWriteFont1_GetPanose(font1
, &panose
);
5145 is_monospaced_expected
= get_expected_is_monospaced(fontface1
, &panose
);
5146 ok(is_monospaced_expected
== is_monospaced_face
, "Unexpected is_monospaced flag %d for %s, font %d.\n",
5147 is_monospaced_face
, wine_dbgstr_w(nameW
), j
);
5149 IDWriteFontFace1_Release(fontface1
);
5150 IDWriteFont1_Release(font1
);
5153 IDWriteFontFamily_Release(family
);
5156 IDWriteFontCollection_Release(collection
);
5157 ref
= IDWriteFactory1_Release(factory
);
5158 ok(ref
== 0, "factory not released, %u\n", ref
);
5161 static void test_GetDesignGlyphAdvances(void)
5163 IDWriteFontFace1
*fontface1
;
5164 IDWriteFontFace
*fontface
;
5165 IDWriteFactory
*factory
;
5166 IDWriteFontFile
*file
;
5171 factory
= create_factory();
5173 path
= create_testfontfile(test_fontfile
);
5175 hr
= IDWriteFactory_CreateFontFileReference(factory
, path
, NULL
, &file
);
5176 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5178 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_TRUETYPE
, 1, &file
,
5179 0, DWRITE_FONT_SIMULATIONS_NONE
, &fontface
);
5180 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5181 IDWriteFontFile_Release(file
);
5183 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void**)&fontface1
);
5191 hr
= IDWriteFontFace1_GetGlyphIndices(fontface1
, &codepoint
, 1, &index
);
5192 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5193 ok(index
> 0, "got %u\n", index
);
5196 hr
= IDWriteFontFace1_GetDesignGlyphAdvances(fontface1
, 1, &index
, &advance
, FALSE
);
5197 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5198 ok(advance
== 1000, "got %i\n", advance
);
5201 hr
= IDWriteFontFace1_GetDesignGlyphAdvances(fontface1
, 1, &index
, &advance
, TRUE
);
5202 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5204 ok(advance
== 2048, "got %i\n", advance
);
5206 IDWriteFontFace1_Release(fontface1
);
5209 win_skip("GetDesignGlyphAdvances() is not supported.\n");
5211 IDWriteFontFace_Release(fontface
);
5212 ref
= IDWriteFactory_Release(factory
);
5213 ok(ref
== 0, "factory not released, %u\n", ref
);
5214 DELETE_FONTFILE(path
);
5217 static void test_GetGlyphRunOutline(void)
5219 DWRITE_GLYPH_OFFSET offsets
[2];
5220 IDWriteFactory
*factory
;
5221 IDWriteFontFile
*file
;
5222 IDWriteFontFace
*face
;
5230 path
= create_testfontfile(test_fontfile
);
5231 factory
= create_factory();
5233 hr
= IDWriteFactory_CreateFontFileReference(factory
, path
, NULL
, &file
);
5234 ok(hr
== S_OK
, "got 0x%08x\n",hr
);
5236 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_TRUETYPE
, 1, &file
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &face
);
5237 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5238 IDWriteFontFile_Release(file
);
5242 hr
= IDWriteFontFace_GetGlyphIndices(face
, &codepoint
, 1, glyphs
);
5243 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5244 ok(glyphs
[0] > 0, "got %u\n", glyphs
[0]);
5245 glyphs
[1] = glyphs
[0];
5247 hr
= IDWriteFontFace_GetGlyphRunOutline(face
, 2048.0, glyphs
, advances
, offsets
, 1, FALSE
, FALSE
, NULL
);
5248 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5250 hr
= IDWriteFontFace_GetGlyphRunOutline(face
, 2048.0, NULL
, NULL
, offsets
, 1, FALSE
, FALSE
, &test_geomsink
);
5251 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5256 offsets
[0].advanceOffset
= 1.0;
5257 offsets
[0].ascenderOffset
= 1.0;
5258 offsets
[1].advanceOffset
= 0.0;
5259 offsets
[1].ascenderOffset
= 0.0;
5261 /* default advances, no offsets */
5262 memset(g_startpoints
, 0, sizeof(g_startpoints
));
5263 g_startpoint_count
= 0;
5264 SET_EXPECT(setfillmode
);
5265 hr
= IDWriteFontFace_GetGlyphRunOutline(face
, 1024.0, glyphs
, NULL
, NULL
, 2, FALSE
, FALSE
, &test_geomsink
);
5266 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5267 ok(g_startpoint_count
== 2, "got %d\n", g_startpoint_count
);
5268 if (g_startpoint_count
== 2) {
5269 /* glyph advance of 500 is applied */
5270 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
);
5271 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
);
5273 CHECK_CALLED(setfillmode
);
5275 /* default advances, no offsets, RTL */
5276 memset(g_startpoints
, 0, sizeof(g_startpoints
));
5277 g_startpoint_count
= 0;
5278 SET_EXPECT(setfillmode
);
5279 hr
= IDWriteFontFace_GetGlyphRunOutline(face
, 1024.0, glyphs
, NULL
, NULL
, 2, FALSE
, TRUE
, &test_geomsink
);
5280 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5281 ok(g_startpoint_count
== 2, "got %d\n", g_startpoint_count
);
5282 if (g_startpoint_count
== 2) {
5283 /* advance is -500 now */
5284 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
);
5285 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
);
5287 CHECK_CALLED(setfillmode
);
5289 /* default advances, additional offsets */
5290 memset(g_startpoints
, 0, sizeof(g_startpoints
));
5291 g_startpoint_count
= 0;
5292 SET_EXPECT(setfillmode
);
5293 hr
= IDWriteFontFace_GetGlyphRunOutline(face
, 1024.0, glyphs
, NULL
, offsets
, 2, FALSE
, FALSE
, &test_geomsink
);
5294 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5295 ok(g_startpoint_count
== 2, "got %d\n", g_startpoint_count
);
5296 if (g_startpoint_count
== 2) {
5297 /* offsets applied to first contour */
5298 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
);
5299 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
);
5301 CHECK_CALLED(setfillmode
);
5303 /* default advances, additional offsets, RTL */
5304 memset(g_startpoints
, 0, sizeof(g_startpoints
));
5305 g_startpoint_count
= 0;
5306 SET_EXPECT(setfillmode
);
5307 hr
= IDWriteFontFace_GetGlyphRunOutline(face
, 1024.0, glyphs
, NULL
, offsets
, 2, FALSE
, TRUE
, &test_geomsink
);
5308 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5309 ok(g_startpoint_count
== 2, "got %d\n", g_startpoint_count
);
5310 if (g_startpoint_count
== 2) {
5311 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
);
5312 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
);
5314 CHECK_CALLED(setfillmode
);
5316 /* custom advances and offsets, offset turns total advance value to zero */
5317 memset(g_startpoints
, 0, sizeof(g_startpoints
));
5318 g_startpoint_count
= 0;
5319 SET_EXPECT(setfillmode
);
5320 hr
= IDWriteFontFace_GetGlyphRunOutline(face
, 1024.0, glyphs
, advances
, offsets
, 2, FALSE
, FALSE
, &test_geomsink
);
5321 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5322 ok(g_startpoint_count
== 2, "got %d\n", g_startpoint_count
);
5323 if (g_startpoint_count
== 2) {
5324 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
);
5325 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
);
5327 CHECK_CALLED(setfillmode
);
5330 hr
= IDWriteFontFace_GetGlyphRunOutline(face
, 1024.0, glyphs
, NULL
, NULL
, 0, FALSE
, FALSE
, &test_geomsink2
);
5331 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5333 /* Glyph with open figure, single contour point. */
5336 hr
= IDWriteFontFace_GetGlyphIndices(face
, &codepoint
, 1, glyphs
);
5337 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5338 ok(glyphs
[0] > 0, "got %u\n", glyphs
[0]);
5340 SET_EXPECT(setfillmode
);
5341 hr
= IDWriteFontFace_GetGlyphRunOutline(face
, 1024.0, glyphs
, NULL
, NULL
, 1, FALSE
, FALSE
, &test_geomsink2
);
5342 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5343 CHECK_CALLED(setfillmode
);
5345 IDWriteFactory_Release(factory
);
5346 IDWriteFontFace_Release(face
);
5347 DELETE_FONTFILE(path
);
5350 factory
= create_factory();
5351 face
= create_fontface(factory
);
5355 hr
= IDWriteFontFace_GetGlyphIndices(face
, &codepoint
, 1, glyphs
);
5356 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5357 ok(glyphs
[0] > 0, "got %u\n", glyphs
[0]);
5359 SET_EXPECT(setfillmode
);
5360 hr
= IDWriteFontFace_GetGlyphRunOutline(face
, 1024.0, glyphs
, NULL
, NULL
, 1, FALSE
, FALSE
, &test_geomsink2
);
5361 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5362 CHECK_CALLED(setfillmode
);
5364 IDWriteFontFace_Release(face
);
5365 ref
= IDWriteFactory_Release(factory
);
5366 ok(ref
== 0, "factory not released, %u\n", ref
);
5369 static void test_GetEudcFontCollection(void)
5371 IDWriteFontCollection
*coll
, *coll2
;
5372 IDWriteFactory1
*factory
;
5376 factory
= create_factory_iid(&IID_IDWriteFactory1
);
5378 win_skip("GetEudcFontCollection() is not supported.\n");
5382 EXPECT_REF(factory
, 1);
5383 hr
= IDWriteFactory1_GetEudcFontCollection(factory
, &coll
, FALSE
);
5384 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5385 EXPECT_REF(factory
, 2);
5386 hr
= IDWriteFactory1_GetEudcFontCollection(factory
, &coll2
, FALSE
);
5387 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5388 EXPECT_REF(factory
, 2);
5389 ok(coll
== coll2
, "got %p, %p\n", coll
, coll2
);
5390 IDWriteFontCollection_Release(coll
);
5391 IDWriteFontCollection_Release(coll2
);
5393 ref
= IDWriteFactory1_Release(factory
);
5394 ok(ref
== 0, "factory not released, %u\n", ref
);
5397 static void test_GetCaretMetrics(void)
5399 DWRITE_FONT_METRICS1 metrics
;
5400 IDWriteFontFace1
*fontface1
;
5401 DWRITE_CARET_METRICS caret
;
5402 IDWriteFontFace
*fontface
;
5403 IDWriteFactory
*factory
;
5404 IDWriteFontFile
*file
;
5410 path
= create_testfontfile(test_fontfile
);
5411 factory
= create_factory();
5413 hr
= IDWriteFactory_CreateFontFileReference(factory
, path
, NULL
, &file
);
5414 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5416 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_TRUETYPE
, 1, &file
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &fontface
);
5417 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5418 IDWriteFontFile_Release(file
);
5420 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void**)&fontface1
);
5421 IDWriteFontFace_Release(fontface
);
5423 win_skip("GetCaretMetrics() is not supported.\n");
5424 ref
= IDWriteFactory_Release(factory
);
5425 ok(ref
== 0, "factory not released, %u\n", ref
);
5426 DELETE_FONTFILE(path
);
5430 memset(&caret
, 0xcc, sizeof(caret
));
5431 IDWriteFontFace1_GetCaretMetrics(fontface1
, &caret
);
5432 ok(caret
.slopeRise
== 1, "got %d\n", caret
.slopeRise
);
5433 ok(caret
.slopeRun
== 0, "got %d\n", caret
.slopeRun
);
5434 ok(caret
.offset
== 0, "got %d\n", caret
.offset
);
5435 IDWriteFontFace1_Release(fontface1
);
5436 IDWriteFactory_Release(factory
);
5438 /* now with Tahoma Normal */
5439 factory
= create_factory();
5440 font
= get_tahoma_instance(factory
, DWRITE_FONT_STYLE_NORMAL
);
5441 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
5442 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5443 IDWriteFont_Release(font
);
5444 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void**)&fontface1
);
5445 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5446 IDWriteFontFace_Release(fontface
);
5448 memset(&caret
, 0xcc, sizeof(caret
));
5449 IDWriteFontFace1_GetCaretMetrics(fontface1
, &caret
);
5450 ok(caret
.slopeRise
== 1, "got %d\n", caret
.slopeRise
);
5451 ok(caret
.slopeRun
== 0, "got %d\n", caret
.slopeRun
);
5452 ok(caret
.offset
== 0, "got %d\n", caret
.offset
);
5453 IDWriteFontFace1_Release(fontface1
);
5455 /* simulated italic */
5456 font
= get_tahoma_instance(factory
, DWRITE_FONT_STYLE_ITALIC
);
5457 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
5458 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5459 IDWriteFont_Release(font
);
5460 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void**)&fontface1
);
5461 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5462 IDWriteFontFace_Release(fontface
);
5464 IDWriteFontFace1_GetMetrics(fontface1
, &metrics
);
5466 memset(&caret
, 0xcc, sizeof(caret
));
5467 IDWriteFontFace1_GetCaretMetrics(fontface1
, &caret
);
5468 ok(caret
.slopeRise
== metrics
.designUnitsPerEm
, "got %d\n", caret
.slopeRise
);
5469 ok(caret
.slopeRun
> 0, "got %d\n", caret
.slopeRun
);
5470 ok(caret
.offset
== 0, "got %d\n", caret
.offset
);
5471 IDWriteFontFace1_Release(fontface1
);
5473 ref
= IDWriteFactory_Release(factory
);
5474 ok(ref
== 0, "factory not released, %u\n", ref
);
5475 DELETE_FONTFILE(path
);
5478 static void test_GetGlyphCount(void)
5480 IDWriteFontFace
*fontface
;
5481 IDWriteFactory
*factory
;
5482 IDWriteFontFile
*file
;
5488 path
= create_testfontfile(test_fontfile
);
5489 factory
= create_factory();
5491 hr
= IDWriteFactory_CreateFontFileReference(factory
, path
, NULL
, &file
);
5492 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5494 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_TRUETYPE
, 1, &file
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &fontface
);
5495 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5496 IDWriteFontFile_Release(file
);
5498 count
= IDWriteFontFace_GetGlyphCount(fontface
);
5499 ok(count
== 8, "got %u\n", count
);
5501 IDWriteFontFace_Release(fontface
);
5502 ref
= IDWriteFactory_Release(factory
);
5503 ok(ref
== 0, "factory not released, %u\n", ref
);
5504 DELETE_FONTFILE(path
);
5507 static void test_GetKerningPairAdjustments(void)
5509 IDWriteFontFace1
*fontface1
;
5510 IDWriteFontFace
*fontface
;
5511 IDWriteFactory
*factory
;
5512 IDWriteFontFile
*file
;
5517 path
= create_testfontfile(test_fontfile
);
5518 factory
= create_factory();
5520 hr
= IDWriteFactory_CreateFontFileReference(factory
, path
, NULL
, &file
);
5521 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5523 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_TRUETYPE
, 1, &file
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &fontface
);
5524 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5525 IDWriteFontFile_Release(file
);
5527 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void**)&fontface1
);
5529 INT32 adjustments
[1];
5531 hr
= IDWriteFontFace1_GetKerningPairAdjustments(fontface1
, 0, NULL
, NULL
);
5532 ok(hr
== E_INVALIDARG
|| broken(hr
== S_OK
) /* win8 */, "got 0x%08x\n", hr
);
5534 if (0) /* crashes on native */
5535 hr
= IDWriteFontFace1_GetKerningPairAdjustments(fontface1
, 1, NULL
, NULL
);
5538 hr
= IDWriteFontFace1_GetKerningPairAdjustments(fontface1
, 1, NULL
, adjustments
);
5539 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5540 ok(adjustments
[0] == 0, "got %d\n", adjustments
[0]);
5542 IDWriteFontFace1_Release(fontface1
);
5545 win_skip("GetKerningPairAdjustments() is not supported.\n");
5547 IDWriteFontFace_Release(fontface
);
5548 ref
= IDWriteFactory_Release(factory
);
5549 ok(ref
== 0, "factory not released, %u\n", ref
);
5550 DELETE_FONTFILE(path
);
5553 static void test_CreateRenderingParams(void)
5555 IDWriteRenderingParams2
*params2
;
5556 IDWriteRenderingParams1
*params1
;
5557 IDWriteRenderingParams
*params
;
5558 DWRITE_RENDERING_MODE mode
;
5559 IDWriteFactory3
*factory3
;
5560 IDWriteFactory
*factory
;
5564 factory
= create_factory();
5566 hr
= IDWriteFactory_CreateCustomRenderingParams(factory
, 1.0, 0.0, 0.0, DWRITE_PIXEL_GEOMETRY_FLAT
,
5567 DWRITE_RENDERING_MODE_DEFAULT
, ¶ms
);
5568 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5570 hr
= IDWriteRenderingParams_QueryInterface(params
, &IID_IDWriteRenderingParams1
, (void**)¶ms1
);
5574 /* test what enhanced contrast setting set by default to */
5575 enhcontrast
= IDWriteRenderingParams1_GetGrayscaleEnhancedContrast(params1
);
5576 ok(enhcontrast
== 1.0, "got %.2f\n", enhcontrast
);
5577 IDWriteRenderingParams1_Release(params1
);
5579 hr
= IDWriteRenderingParams_QueryInterface(params
, &IID_IDWriteRenderingParams2
, (void**)¶ms2
);
5581 DWRITE_GRID_FIT_MODE gridfit
;
5583 /* default gridfit mode */
5584 gridfit
= IDWriteRenderingParams2_GetGridFitMode(params2
);
5585 ok(gridfit
== DWRITE_GRID_FIT_MODE_DEFAULT
, "got %d\n", gridfit
);
5587 IDWriteRenderingParams2_Release(params2
);
5590 win_skip("IDWriteRenderingParams2 not supported.\n");
5593 win_skip("IDWriteRenderingParams1 not supported.\n");
5595 IDWriteRenderingParams_Release(params
);
5597 hr
= IDWriteFactory_CreateRenderingParams(factory
, ¶ms
);
5598 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5600 mode
= IDWriteRenderingParams_GetRenderingMode(params
);
5601 ok(mode
== DWRITE_RENDERING_MODE_DEFAULT
, "got %d\n", mode
);
5602 IDWriteRenderingParams_Release(params
);
5604 hr
= IDWriteFactory_QueryInterface(factory
, &IID_IDWriteFactory3
, (void**)&factory3
);
5606 IDWriteRenderingParams3
*params3
;
5608 hr
= IDWriteFactory3_CreateCustomRenderingParams(factory3
, 1.0f
, 0.0f
, 0.0f
, 1.0f
, DWRITE_PIXEL_GEOMETRY_FLAT
,
5609 DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC_DOWNSAMPLED
, DWRITE_GRID_FIT_MODE_DEFAULT
, ¶ms3
);
5610 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5612 hr
= IDWriteRenderingParams3_QueryInterface(params3
, &IID_IDWriteRenderingParams
, (void**)¶ms
);
5613 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5615 mode
= IDWriteRenderingParams_GetRenderingMode(params
);
5616 ok(mode
== DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
, "got %d\n", mode
);
5618 IDWriteRenderingParams_Release(params
);
5619 IDWriteRenderingParams3_Release(params3
);
5620 IDWriteFactory3_Release(factory3
);
5623 win_skip("IDWriteRenderingParams3 not supported.\n");
5625 ref
= IDWriteFactory_Release(factory
);
5626 ok(ref
== 0, "factory not released, %u\n", ref
);
5629 static void test_CreateGlyphRunAnalysis(void)
5631 static const DWRITE_RENDERING_MODE rendermodes
[] = {
5632 DWRITE_RENDERING_MODE_ALIASED
,
5633 DWRITE_RENDERING_MODE_GDI_CLASSIC
,
5634 DWRITE_RENDERING_MODE_GDI_NATURAL
,
5635 DWRITE_RENDERING_MODE_NATURAL
,
5636 DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
,
5639 IDWriteGlyphRunAnalysis
*analysis
, *analysis2
;
5640 IDWriteRenderingParams
*params
;
5641 IDWriteFactory3
*factory3
;
5642 IDWriteFactory2
*factory2
;
5643 IDWriteFactory
*factory
;
5644 DWRITE_GLYPH_RUN run
;
5645 IDWriteFontFace
*face
;
5646 UINT16 glyph
, glyphs
[10];
5651 DWRITE_GLYPH_OFFSET offsets
[2];
5652 DWRITE_GLYPH_METRICS metrics
;
5653 DWRITE_FONT_METRICS fm
;
5660 factory
= create_factory();
5661 face
= create_fontface(factory
);
5665 hr
= IDWriteFontFace_GetGlyphIndices(face
, &ch
, 1, &glyph
);
5666 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5667 ok(glyph
> 0, "got %u\n", glyph
);
5669 hr
= IDWriteFontFace_GetDesignGlyphMetrics(face
, &glyph
, 1, &metrics
, FALSE
);
5670 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5671 advances
[0] = metrics
.advanceWidth
;
5673 offsets
[0].advanceOffset
= 0.0;
5674 offsets
[0].ascenderOffset
= 0.0;
5676 run
.fontFace
= face
;
5677 run
.fontEmSize
= 24.0;
5679 run
.glyphIndices
= &glyph
;
5680 run
.glyphAdvances
= advances
;
5681 run
.glyphOffsets
= offsets
;
5682 run
.isSideways
= FALSE
;
5686 analysis
= (void*)0xdeadbeef;
5687 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 0.0, NULL
,
5688 DWRITE_RENDERING_MODE_ALIASED
, DWRITE_MEASURING_MODE_NATURAL
,
5689 0.0, 0.0, &analysis
);
5690 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5691 ok(analysis
== NULL
, "got %p\n", analysis
);
5693 /* negative ppdip */
5694 analysis
= (void*)0xdeadbeef;
5695 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, -1.0, NULL
,
5696 DWRITE_RENDERING_MODE_ALIASED
, DWRITE_MEASURING_MODE_NATURAL
,
5697 0.0, 0.0, &analysis
);
5698 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5699 ok(analysis
== NULL
, "got %p\n", analysis
);
5701 /* default mode is not allowed */
5702 analysis
= (void*)0xdeadbeef;
5703 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 1.0, NULL
,
5704 DWRITE_RENDERING_MODE_DEFAULT
, DWRITE_MEASURING_MODE_NATURAL
,
5705 0.0, 0.0, &analysis
);
5706 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5707 ok(analysis
== NULL
, "got %p\n", analysis
);
5710 analysis
= (void*)0xdeadbeef;
5711 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 1.0, NULL
,
5712 DWRITE_RENDERING_MODE_OUTLINE
, DWRITE_MEASURING_MODE_NATURAL
,
5713 0.0, 0.0, &analysis
);
5714 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5715 ok(analysis
== NULL
, "got %p\n", analysis
);
5717 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 1.0, NULL
,
5718 DWRITE_RENDERING_MODE_ALIASED
, DWRITE_MEASURING_MODE_NATURAL
,
5719 0.0, 0.0, &analysis
);
5720 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5722 /* invalid texture type */
5723 memset(&rect
, 0xcc, sizeof(rect
));
5724 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_CLEARTYPE_3x1
+1, &rect
);
5725 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5726 ok(rect
.left
== 0 && rect
.right
== 0 &&
5727 rect
.top
== 0 && rect
.bottom
== 0, "unexpected rect\n");
5729 /* check how origin affects bounds */
5730 SetRectEmpty(&rect
);
5731 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect
);
5732 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5733 ok(!IsRectEmpty(&rect
), "got empty rect\n");
5734 IDWriteGlyphRunAnalysis_Release(analysis
);
5737 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 2.0, NULL
,
5738 DWRITE_RENDERING_MODE_ALIASED
, DWRITE_MEASURING_MODE_NATURAL
,
5739 0.0, 0.0, &analysis
);
5740 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5741 SetRectEmpty(&rect2
);
5742 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect2
);
5743 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5744 ok(rect
.right
- rect
.left
< rect2
.right
- rect2
.left
, "expected wider rect\n");
5745 ok(rect
.bottom
- rect
.top
< rect2
.bottom
- rect2
.top
, "expected taller rect\n");
5746 IDWriteGlyphRunAnalysis_Release(analysis
);
5748 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 1.0, NULL
,
5749 DWRITE_RENDERING_MODE_ALIASED
, DWRITE_MEASURING_MODE_NATURAL
,
5750 10.0, -5.0, &analysis
);
5751 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5753 SetRectEmpty(&rect2
);
5754 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect2
);
5755 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5756 ok(!IsRectEmpty(&rect2
), "got empty rect\n");
5757 IDWriteGlyphRunAnalysis_Release(analysis
);
5759 ok(!EqualRect(&rect
, &rect2
), "got equal bounds\n");
5760 OffsetRect(&rect
, 10, -5);
5761 ok(EqualRect(&rect
, &rect2
), "got different bounds\n");
5763 for (i
= 0; i
< ARRAY_SIZE(rendermodes
); i
++) {
5764 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 1.0, NULL
,
5765 rendermodes
[i
], DWRITE_MEASURING_MODE_NATURAL
,
5766 0.0, 0.0, &analysis
);
5767 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5769 if (rendermodes
[i
] == DWRITE_RENDERING_MODE_ALIASED
) {
5770 SetRectEmpty(&rect
);
5771 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect
);
5772 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5773 ok(!IsRectEmpty(&rect
), "got empty rect\n");
5775 SetRect(&rect
, 0, 0, 1, 1);
5776 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_CLEARTYPE_3x1
, &rect
);
5777 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5778 ok(IsRectEmpty(&rect
), "unexpected empty rect\n");
5781 SetRect(&rect
, 0, 0, 1, 1);
5782 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect
);
5783 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5784 ok(IsRectEmpty(&rect
), "got empty rect\n");
5786 SetRectEmpty(&rect
);
5787 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_CLEARTYPE_3x1
, &rect
);
5788 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5789 ok(!IsRectEmpty(&rect
), "got empty rect\n");
5792 IDWriteGlyphRunAnalysis_Release(analysis
);
5795 IDWriteFontFace_GetMetrics(run
.fontFace
, &fm
);
5797 /* check bbox for a single glyph run */
5798 for (run
.fontEmSize
= 1.0; run
.fontEmSize
<= 100.0; run
.fontEmSize
+= 1.0) {
5799 DWRITE_GLYPH_METRICS gm
;
5802 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 1.0, NULL
,
5803 DWRITE_RENDERING_MODE_ALIASED
, DWRITE_MEASURING_MODE_GDI_CLASSIC
,
5804 0.0, 0.0, &analysis
);
5805 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5807 SetRectEmpty(&rect
);
5808 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect
);
5809 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5811 hr
= IDWriteFontFace_GetGdiCompatibleGlyphMetrics(run
.fontFace
, run
.fontEmSize
, 1.0, NULL
,
5812 DWRITE_MEASURING_MODE_GDI_CLASSIC
, run
.glyphIndices
, 1, &gm
, run
.isSideways
);
5813 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5815 /* metrics are in design units */
5816 bboxX
= (int)floorf((gm
.advanceWidth
- gm
.leftSideBearing
- gm
.rightSideBearing
) * run
.fontEmSize
/ fm
.designUnitsPerEm
+ 0.5f
);
5817 bboxY
= (int)floorf((gm
.advanceHeight
- gm
.topSideBearing
- gm
.bottomSideBearing
) * run
.fontEmSize
/ fm
.designUnitsPerEm
+ 0.5f
);
5819 rect
.right
-= rect
.left
;
5820 rect
.bottom
-= rect
.top
;
5821 ok(abs(bboxX
- rect
.right
) <= 2, "%.0f: bbox width %d, from metrics %d\n", run
.fontEmSize
, rect
.right
, bboxX
);
5822 ok(abs(bboxY
- rect
.bottom
) <= 2, "%.0f: bbox height %d, from metrics %d\n", run
.fontEmSize
, rect
.bottom
, bboxY
);
5824 IDWriteGlyphRunAnalysis_Release(analysis
);
5827 /* without offsets */
5828 run
.fontFace
= face
;
5829 run
.fontEmSize
= 24.0;
5831 run
.glyphIndices
= &glyph
;
5832 run
.glyphAdvances
= advances
;
5833 run
.glyphOffsets
= NULL
;
5834 run
.isSideways
= FALSE
;
5837 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 1.0, NULL
,
5838 DWRITE_RENDERING_MODE_ALIASED
, DWRITE_MEASURING_MODE_NATURAL
,
5839 0.0, 0.0, &analysis
);
5840 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5842 SetRectEmpty(&rect
);
5843 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect
);
5844 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5845 ok(!IsRectEmpty(&rect
), "got empty bounds\n");
5847 IDWriteGlyphRunAnalysis_Release(analysis
);
5849 /* without explicit advances */
5850 run
.fontFace
= face
;
5851 run
.fontEmSize
= 24.0;
5853 run
.glyphIndices
= &glyph
;
5854 run
.glyphAdvances
= NULL
;
5855 run
.glyphOffsets
= NULL
;
5856 run
.isSideways
= FALSE
;
5859 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 1.0, NULL
,
5860 DWRITE_RENDERING_MODE_ALIASED
, DWRITE_MEASURING_MODE_NATURAL
,
5861 0.0, 0.0, &analysis
);
5862 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5864 SetRectEmpty(&rect
);
5865 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect
);
5866 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5867 ok(!IsRectEmpty(&rect
), "got empty bounds\n");
5869 IDWriteGlyphRunAnalysis_Release(analysis
);
5871 /* test that advances are scaled according to ppdip too */
5872 glyphs
[0] = glyphs
[1] = glyph
;
5873 advances
[0] = advances
[1] = 100.0f
;
5874 run
.fontFace
= face
;
5875 run
.fontEmSize
= 24.0;
5877 run
.glyphIndices
= glyphs
;
5878 run
.glyphAdvances
= advances
;
5879 run
.glyphOffsets
= NULL
;
5880 run
.isSideways
= FALSE
;
5883 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 1.0, NULL
,
5884 DWRITE_RENDERING_MODE_ALIASED
, DWRITE_MEASURING_MODE_NATURAL
,
5885 0.0, 0.0, &analysis
);
5886 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5888 SetRectEmpty(&rect2
);
5889 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect2
);
5890 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5891 ok(!IsRectEmpty(&rect2
), "got empty bounds\n");
5892 ok(!EqualRect(&rect
, &rect2
), "got wrong rect2\n");
5893 ok((rect2
.right
- rect
.left
) > advances
[0], "got rect width %d for advance %f\n", rect
.right
- rect
.left
, advances
[0]);
5894 IDWriteGlyphRunAnalysis_Release(analysis
);
5896 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 2.0, NULL
,
5897 DWRITE_RENDERING_MODE_ALIASED
, DWRITE_MEASURING_MODE_NATURAL
,
5898 0.0, 0.0, &analysis
);
5899 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5901 SetRectEmpty(&rect
);
5902 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect
);
5903 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5904 ok((rect
.right
- rect
.left
) > 2 * advances
[0], "got rect width %d for advance %f\n", rect
.right
- rect
.left
, advances
[0]);
5905 IDWriteGlyphRunAnalysis_Release(analysis
);
5907 /* with scaling transform */
5908 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 1.0, NULL
,
5909 DWRITE_RENDERING_MODE_ALIASED
, DWRITE_MEASURING_MODE_NATURAL
,
5910 0.0, 0.0, &analysis
);
5911 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5913 SetRectEmpty(&rect
);
5914 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect
);
5915 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5916 ok(!IsRectEmpty(&rect
), "got rect width %d\n", rect
.right
- rect
.left
);
5917 IDWriteGlyphRunAnalysis_Release(analysis
);
5919 memset(&m
, 0, sizeof(m
));
5922 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 1.0, &m
,
5923 DWRITE_RENDERING_MODE_ALIASED
, DWRITE_MEASURING_MODE_NATURAL
,
5924 0.0, 0.0, &analysis
);
5925 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5927 SetRectEmpty(&rect2
);
5928 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect2
);
5929 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5930 ok((rect2
.right
- rect2
.left
) > (rect
.right
- rect
.left
), "got rect width %d\n", rect2
.right
- rect2
.left
);
5932 /* instances are not reused for same runs */
5933 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 1.0, &m
,
5934 DWRITE_RENDERING_MODE_ALIASED
, DWRITE_MEASURING_MODE_NATURAL
,
5935 0.0, 0.0, &analysis2
);
5936 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5937 ok(analysis2
!= analysis
, "got %p, previous instance %p\n", analysis2
, analysis
);
5938 IDWriteGlyphRunAnalysis_Release(analysis2
);
5940 IDWriteGlyphRunAnalysis_Release(analysis
);
5942 if (IDWriteFactory_QueryInterface(factory
, &IID_IDWriteFactory2
, (void **)&factory2
) == S_OK
) {
5943 FLOAT gamma
, contrast
, cleartype_level
;
5945 /* Invalid antialias mode. */
5946 hr
= IDWriteFactory2_CreateGlyphRunAnalysis(factory2
, &run
, NULL
, DWRITE_RENDERING_MODE_ALIASED
,
5947 DWRITE_MEASURING_MODE_NATURAL
, DWRITE_GRID_FIT_MODE_DEFAULT
, DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
+ 1,
5948 0.0f
, 0.0f
, &analysis
);
5949 ok(hr
== E_INVALIDARG
, "Unexpected hr %#x.\n", hr
);
5951 /* Invalid grid fit mode. */
5952 hr
= IDWriteFactory2_CreateGlyphRunAnalysis(factory2
, &run
, NULL
, DWRITE_RENDERING_MODE_ALIASED
,
5953 DWRITE_MEASURING_MODE_NATURAL
, DWRITE_GRID_FIT_MODE_ENABLED
+ 1, DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
,
5954 0.0f
, 0.0f
, &analysis
);
5955 ok(hr
== E_INVALIDARG
, "Unexpected hr %#x.\n", hr
);
5957 /* Invalid rendering mode. */
5958 hr
= IDWriteFactory2_CreateGlyphRunAnalysis(factory2
, &run
, NULL
, DWRITE_RENDERING_MODE_OUTLINE
,
5959 DWRITE_MEASURING_MODE_NATURAL
, DWRITE_GRID_FIT_MODE_ENABLED
, DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
,
5960 0.0f
, 0.0f
, &analysis
);
5961 ok(hr
== E_INVALIDARG
, "Unexpected hr %#x.\n", hr
);
5963 /* Invalid measuring mode. */
5964 hr
= IDWriteFactory2_CreateGlyphRunAnalysis(factory2
, &run
, NULL
, DWRITE_RENDERING_MODE_ALIASED
,
5965 DWRITE_MEASURING_MODE_GDI_NATURAL
+ 1, DWRITE_GRID_FIT_MODE_ENABLED
, DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
,
5966 0.0f
, 0.0f
, &analysis
);
5967 ok(hr
== E_INVALIDARG
, "Unexpected hr %#x.\n", hr
);
5969 /* Win8 does not accept default grid fitting mode. */
5970 hr
= IDWriteFactory2_CreateGlyphRunAnalysis(factory2
, &run
, NULL
, DWRITE_RENDERING_MODE_NATURAL
,
5971 DWRITE_MEASURING_MODE_NATURAL
, DWRITE_GRID_FIT_MODE_DEFAULT
, DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
,
5972 0.0f
, 0.0f
, &analysis
);
5973 ok(hr
== S_OK
|| broken(hr
== E_INVALIDARG
) /* Win8 */, "Failed to create analysis, hr %#x.\n", hr
);
5975 IDWriteGlyphRunAnalysis_Release(analysis
);
5977 /* Natural mode, grayscale antialiased. */
5978 hr
= IDWriteFactory2_CreateGlyphRunAnalysis(factory2
, &run
, NULL
, DWRITE_RENDERING_MODE_NATURAL
,
5979 DWRITE_MEASURING_MODE_NATURAL
, DWRITE_GRID_FIT_MODE_DISABLED
, DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
,
5980 0.0f
, 0.0f
, &analysis
);
5981 ok(hr
== S_OK
, "Failed to create analysis, hr %#x.\n", hr
);
5983 SetRect(&rect
, 0, 1, 0, 1);
5984 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_CLEARTYPE_3x1
, &rect
);
5985 ok(hr
== S_OK
, "Failed to get texture bounds, hr %#x.\n", hr
);
5986 ok(IsRectEmpty(&rect
), "Expected empty bbox.\n");
5988 SetRectEmpty(&rect
);
5989 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect
);
5990 ok(hr
== S_OK
, "Failed to get texture bounds, hr %#x.\n", hr
);
5991 ok(!IsRectEmpty(&rect
), "Unexpected empty bbox.\n");
5993 size
= (rect
.right
- rect
.left
) * (rect
.bottom
- rect
.top
);
5994 bits
= HeapAlloc(GetProcessHeap(), 0, size
);
5996 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect
, bits
, size
);
5997 ok(hr
== S_OK
, "Failed to get alpha texture, hr %#x.\n", hr
);
5999 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect
, bits
, size
- 1);
6000 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "Unexpected hr %#x.\n", hr
);
6002 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_CLEARTYPE_3x1
, &rect
, bits
, size
);
6003 ok(hr
== DWRITE_E_UNSUPPORTEDOPERATION
, "Unexpected hr %#x.\n", hr
);
6005 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_CLEARTYPE_3x1
, &rect
, bits
, size
- 1);
6007 ok(hr
== DWRITE_E_UNSUPPORTEDOPERATION
, "Unexpected hr %#x.\n", hr
);
6009 HeapFree(GetProcessHeap(), 0, bits
);
6011 hr
= IDWriteFactory_CreateCustomRenderingParams(factory
, 0.1f
, 0.0f
, 1.0f
, DWRITE_PIXEL_GEOMETRY_FLAT
,
6012 DWRITE_RENDERING_MODE_NATURAL
, ¶ms
);
6013 ok(hr
== S_OK
, "Failed to create custom parameters, hr %#x.\n", hr
);
6015 hr
= IDWriteGlyphRunAnalysis_GetAlphaBlendParams(analysis
, params
, &gamma
, &contrast
, &cleartype_level
);
6016 ok(hr
== S_OK
, "Failed to get alpha blend params, hr %#x.\n", hr
);
6018 ok(cleartype_level
== 0.0f
, "Unexpected cleartype level %f.\n", cleartype_level
);
6020 IDWriteRenderingParams_Release(params
);
6021 IDWriteGlyphRunAnalysis_Release(analysis
);
6023 IDWriteFactory2_Release(factory2
);
6026 if (IDWriteFactory_QueryInterface(factory
, &IID_IDWriteFactory3
, (void **)&factory3
) == S_OK
) {
6028 /* Invalid antialias mode. */
6029 hr
= IDWriteFactory3_CreateGlyphRunAnalysis(factory3
, &run
, NULL
, DWRITE_RENDERING_MODE1_ALIASED
,
6030 DWRITE_MEASURING_MODE_NATURAL
, DWRITE_GRID_FIT_MODE_DEFAULT
, DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
+ 1,
6031 0.0f
, 0.0f
, &analysis
);
6032 ok(hr
== E_INVALIDARG
, "Unexpected hr %#x.\n", hr
);
6034 /* Invalid grid fit mode. */
6035 hr
= IDWriteFactory3_CreateGlyphRunAnalysis(factory3
, &run
, NULL
, DWRITE_RENDERING_MODE1_ALIASED
,
6036 DWRITE_MEASURING_MODE_NATURAL
, DWRITE_GRID_FIT_MODE_ENABLED
+ 1, DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
,
6037 0.0f
, 0.0f
, &analysis
);
6038 ok(hr
== E_INVALIDARG
, "Unexpected hr %#x.\n", hr
);
6040 /* Invalid rendering mode. */
6041 hr
= IDWriteFactory3_CreateGlyphRunAnalysis(factory3
, &run
, NULL
, DWRITE_RENDERING_MODE1_OUTLINE
,
6042 DWRITE_MEASURING_MODE_NATURAL
, DWRITE_GRID_FIT_MODE_ENABLED
, DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
,
6043 0.0f
, 0.0f
, &analysis
);
6044 ok(hr
== E_INVALIDARG
, "Unexpected hr %#x.\n", hr
);
6046 /* Invalid measuring mode. */
6047 hr
= IDWriteFactory3_CreateGlyphRunAnalysis(factory3
, &run
, NULL
, DWRITE_RENDERING_MODE1_ALIASED
,
6048 DWRITE_MEASURING_MODE_GDI_NATURAL
+ 1, DWRITE_GRID_FIT_MODE_ENABLED
,
6049 DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
, 0.0f
, 0.0f
, &analysis
);
6050 ok(hr
== E_INVALIDARG
, "Unexpected hr %#x.\n", hr
);
6052 hr
= IDWriteFactory3_CreateGlyphRunAnalysis(factory3
, &run
, NULL
, DWRITE_RENDERING_MODE1_NATURAL
,
6053 DWRITE_MEASURING_MODE_NATURAL
, DWRITE_GRID_FIT_MODE_DEFAULT
, DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
,
6054 0.0f
, 0.0f
, &analysis
);
6055 ok(hr
== S_OK
, "Failed to create analysis, hr %#x.\n", hr
);
6056 IDWriteGlyphRunAnalysis_Release(analysis
);
6058 /* Natural mode, grayscale antialiased. */
6059 hr
= IDWriteFactory3_CreateGlyphRunAnalysis(factory3
, &run
, NULL
, DWRITE_RENDERING_MODE1_NATURAL
,
6060 DWRITE_MEASURING_MODE_NATURAL
, DWRITE_GRID_FIT_MODE_DISABLED
, DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
,
6061 0.0f
, 0.0f
, &analysis
);
6062 ok(hr
== S_OK
, "Failed to create analysis, hr %#x.\n", hr
);
6064 SetRect(&rect
, 0, 1, 0, 1);
6065 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_CLEARTYPE_3x1
, &rect
);
6066 ok(hr
== S_OK
, "Failed to get texture bounds, hr %#x.\n", hr
);
6067 ok(IsRectEmpty(&rect
), "Expected empty bbox.\n");
6069 SetRectEmpty(&rect
);
6070 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect
);
6071 ok(hr
== S_OK
, "Failed to get texture bounds, hr %#x.\n", hr
);
6072 ok(!IsRectEmpty(&rect
), "Unexpected empty bbox.\n");
6074 size
= (rect
.right
- rect
.left
) * (rect
.bottom
- rect
.top
);
6075 bits
= HeapAlloc(GetProcessHeap(), 0, size
);
6077 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect
, bits
, size
);
6078 ok(hr
== S_OK
, "Failed to get alpha texture, hr %#x.\n", hr
);
6080 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect
, bits
, size
- 1);
6081 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "Unexpected hr %#x.\n", hr
);
6083 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_CLEARTYPE_3x1
, &rect
, bits
, size
);
6084 ok(hr
== DWRITE_E_UNSUPPORTEDOPERATION
, "Unexpected hr %#x.\n", hr
);
6086 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_CLEARTYPE_3x1
, &rect
, bits
, size
- 1);
6088 ok(hr
== DWRITE_E_UNSUPPORTEDOPERATION
, "Unexpected hr %#x.\n", hr
);
6090 HeapFree(GetProcessHeap(), 0, bits
);
6092 IDWriteGlyphRunAnalysis_Release(analysis
);
6094 IDWriteFactory3_Release(factory3
);
6097 IDWriteFontFace_Release(face
);
6098 ref
= IDWriteFactory_Release(factory
);
6099 ok(ref
== 0, "factory not released, %u\n", ref
);
6102 #define round(x) ((int)floor((x) + 0.5))
6133 static const struct VDMX_group
*find_vdmx_group(const struct VDMX_Header
*hdr
)
6135 WORD num_ratios
, i
, group_offset
= 0;
6136 struct VDMX_Ratio
*ratios
= (struct VDMX_Ratio
*)(hdr
+ 1);
6137 BYTE dev_x_ratio
= 1, dev_y_ratio
= 1;
6139 num_ratios
= GET_BE_WORD(hdr
->numRatios
);
6141 for (i
= 0; i
< num_ratios
; i
++)
6143 if (!ratios
[i
].bCharSet
) continue;
6145 if ((ratios
[i
].xRatio
== 0 && ratios
[i
].yStartRatio
== 0 &&
6146 ratios
[i
].yEndRatio
== 0) ||
6147 (ratios
[i
].xRatio
== dev_x_ratio
&& ratios
[i
].yStartRatio
<= dev_y_ratio
&&
6148 ratios
[i
].yEndRatio
>= dev_y_ratio
))
6150 group_offset
= GET_BE_WORD(*((WORD
*)(ratios
+ num_ratios
) + i
));
6155 return (const struct VDMX_group
*)((BYTE
*)hdr
+ group_offset
);
6159 static BOOL
get_vdmx_size(const struct VDMX_group
*group
, int emsize
, int *a
, int *d
)
6162 const struct VDMX_vTable
*tables
;
6164 if (!group
) return FALSE
;
6166 recs
= GET_BE_WORD(group
->recs
);
6167 if (emsize
< group
->startsz
|| emsize
>= group
->endsz
) return FALSE
;
6169 tables
= (const struct VDMX_vTable
*)(group
+ 1);
6170 for (i
= 0; i
< recs
; i
++)
6172 WORD ppem
= GET_BE_WORD(tables
[i
].yPelHeight
);
6175 /* FIXME: Supposed to interpolate */
6176 trace("FIXME interpolate %d\n", emsize
);
6182 *a
= (SHORT
)GET_BE_WORD(tables
[i
].yMax
);
6183 *d
= -(SHORT
)GET_BE_WORD(tables
[i
].yMin
);
6190 static void test_metrics_cmp(FLOAT emsize
, const DWRITE_FONT_METRICS
*metrics
, const DWRITE_FONT_METRICS1
*expected
)
6192 ok(metrics
->designUnitsPerEm
== expected
->designUnitsPerEm
, "%.2f: emsize: got %u expect %u\n",
6193 emsize
, metrics
->designUnitsPerEm
, expected
->designUnitsPerEm
);
6194 ok(metrics
->ascent
== expected
->ascent
, "%.2f a: got %u expect %u\n",
6195 emsize
, metrics
->ascent
, expected
->ascent
);
6196 ok(metrics
->descent
== expected
->descent
, "%.2f d: got %u expect %u\n",
6197 emsize
, metrics
->descent
, expected
->descent
);
6198 ok(metrics
->lineGap
== expected
->lineGap
, "%.2f lg: got %d expect %d\n",
6199 emsize
, metrics
->lineGap
, expected
->lineGap
);
6200 ok(metrics
->capHeight
== expected
->capHeight
, "%.2f capH: got %u expect %u\n",
6201 emsize
, metrics
->capHeight
, expected
->capHeight
);
6202 ok(metrics
->xHeight
== expected
->xHeight
, "%.2f xH: got %u expect %u\n",
6203 emsize
, metrics
->xHeight
, expected
->xHeight
);
6204 ok(metrics
->underlinePosition
== expected
->underlinePosition
, "%.2f ulP: got %d expect %d\n",
6205 emsize
, metrics
->underlinePosition
, expected
->underlinePosition
);
6206 ok(metrics
->underlineThickness
== expected
->underlineThickness
, "%.2f ulTh: got %u expect %u\n",
6207 emsize
, metrics
->underlineThickness
, expected
->underlineThickness
);
6208 ok(metrics
->strikethroughPosition
== expected
->strikethroughPosition
, "%.2f stP: got %d expect %d\n",
6209 emsize
, metrics
->strikethroughPosition
, expected
->strikethroughPosition
);
6210 ok(metrics
->strikethroughThickness
== expected
->strikethroughThickness
, "%.2f stTh: got %u expect %u\n",
6211 emsize
, metrics
->strikethroughThickness
, expected
->strikethroughThickness
);
6214 static void test_metrics1_cmp(FLOAT emsize
, const DWRITE_FONT_METRICS1
*metrics
, const DWRITE_FONT_METRICS1
*expected
)
6216 ok(metrics
->designUnitsPerEm
== expected
->designUnitsPerEm
, "%.2f: emsize: got %u expect %u\n",
6217 emsize
, metrics
->designUnitsPerEm
, expected
->designUnitsPerEm
);
6218 ok(metrics
->ascent
== expected
->ascent
, "%.2f a: got %u expect %u\n",
6219 emsize
, metrics
->ascent
, expected
->ascent
);
6220 ok(metrics
->descent
== expected
->descent
, "%.2f d: got %u expect %u\n",
6221 emsize
, metrics
->descent
, expected
->descent
);
6222 ok(metrics
->lineGap
== expected
->lineGap
, "%.2f lg: got %d expect %d\n",
6223 emsize
, metrics
->lineGap
, expected
->lineGap
);
6224 ok(metrics
->capHeight
== expected
->capHeight
, "%.2f capH: got %u expect %u\n",
6225 emsize
, metrics
->capHeight
, expected
->capHeight
);
6226 ok(metrics
->xHeight
== expected
->xHeight
, "%.2f xH: got %u expect %u\n",
6227 emsize
, metrics
->xHeight
, expected
->xHeight
);
6228 ok(metrics
->underlinePosition
== expected
->underlinePosition
, "%.2f ulP: got %d expect %d\n",
6229 emsize
, metrics
->underlinePosition
, expected
->underlinePosition
);
6230 ok(metrics
->underlineThickness
== expected
->underlineThickness
, "%.2f ulTh: got %u expect %u\n",
6231 emsize
, metrics
->underlineThickness
, expected
->underlineThickness
);
6232 ok(metrics
->strikethroughPosition
== expected
->strikethroughPosition
, "%.2f stP: got %d expect %d\n",
6233 emsize
, metrics
->strikethroughPosition
, expected
->strikethroughPosition
);
6234 ok(metrics
->strikethroughThickness
== expected
->strikethroughThickness
, "%.2f stTh: got %u expect %u\n",
6235 emsize
, metrics
->strikethroughThickness
, expected
->strikethroughThickness
);
6236 ok(metrics
->glyphBoxLeft
== expected
->glyphBoxLeft
, "%.2f box left: got %d expect %d\n",
6237 emsize
, metrics
->glyphBoxLeft
, expected
->glyphBoxLeft
);
6238 if (0) { /* this is not consistent */
6239 ok(metrics
->glyphBoxTop
== expected
->glyphBoxTop
, "%.2f box top: got %d expect %d\n",
6240 emsize
, metrics
->glyphBoxTop
, expected
->glyphBoxTop
);
6241 ok(metrics
->glyphBoxRight
== expected
->glyphBoxRight
, "%.2f box right: got %d expect %d\n",
6242 emsize
, metrics
->glyphBoxRight
, expected
->glyphBoxRight
);
6244 ok(metrics
->glyphBoxBottom
== expected
->glyphBoxBottom
, "%.2f box bottom: got %d expect %d\n",
6245 emsize
, metrics
->glyphBoxBottom
, expected
->glyphBoxBottom
);
6246 ok(metrics
->subscriptPositionX
== expected
->subscriptPositionX
, "%.2f subX: got %d expect %d\n",
6247 emsize
, metrics
->subscriptPositionX
, expected
->subscriptPositionX
);
6248 ok(metrics
->subscriptPositionY
== expected
->subscriptPositionY
, "%.2f subY: got %d expect %d\n",
6249 emsize
, metrics
->subscriptPositionY
, expected
->subscriptPositionY
);
6250 ok(metrics
->subscriptSizeX
== expected
->subscriptSizeX
, "%.2f subsizeX: got %d expect %d\n",
6251 emsize
, metrics
->subscriptSizeX
, expected
->subscriptSizeX
);
6252 ok(metrics
->subscriptPositionY
== expected
->subscriptPositionY
, "%.2f subsizeY: got %d expect %d\n",
6253 emsize
, metrics
->subscriptSizeY
, expected
->subscriptSizeY
);
6254 ok(metrics
->superscriptPositionX
== expected
->superscriptPositionX
, "%.2f supX: got %d expect %d\n",
6255 emsize
, metrics
->superscriptPositionX
, expected
->superscriptPositionX
);
6257 ok(metrics
->superscriptPositionY
== expected
->superscriptPositionY
, "%.2f supY: got %d expect %d\n",
6258 emsize
, metrics
->superscriptPositionY
, expected
->superscriptPositionY
);
6259 ok(metrics
->superscriptSizeX
== expected
->superscriptSizeX
, "%.2f supsizeX: got %d expect %d\n",
6260 emsize
, metrics
->superscriptSizeX
, expected
->superscriptSizeX
);
6261 ok(metrics
->superscriptSizeY
== expected
->superscriptSizeY
, "%.2f supsizeY: got %d expect %d\n",
6262 emsize
, metrics
->superscriptSizeY
, expected
->superscriptSizeY
);
6263 ok(metrics
->hasTypographicMetrics
== expected
->hasTypographicMetrics
, "%.2f hastypo: got %d expect %d\n",
6264 emsize
, metrics
->hasTypographicMetrics
, expected
->hasTypographicMetrics
);
6267 struct compatmetrics_test
{
6273 static struct compatmetrics_test compatmetrics_tests
[] = {
6274 { { 0.0, 0.0, 0.0, 1.0, 0.0, 0.0 }, 1.0, 5.0 },
6275 { { 0.0, 0.0, 0.0, -1.0, 0.0, 0.0 }, 1.0, 5.0 },
6276 { { 0.0, 0.0, 0.0, -1.0, 0.0, 0.0 }, 2.0, 5.0 },
6277 { { 0.0, 0.0, 0.0, 3.0, 0.0, 0.0 }, 2.0, 5.0 },
6278 { { 0.0, 0.0, 0.0, -3.0, 0.0, 0.0 }, 2.0, 5.0 },
6279 { { 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 }, 2.0, 5.0 },
6280 { { 1.0, 0.0, 0.0, 1.0, 5.0, 0.0 }, 2.0, 5.0 },
6281 { { 1.0, 0.0, 0.0, 1.0, 0.0, 5.0 }, 2.0, 5.0 },
6284 static void get_expected_metrics(IDWriteFontFace
*fontface
, struct compatmetrics_test
*ptr
,
6285 DWRITE_FONT_METRICS
*expected
)
6289 memset(expected
, 0, sizeof(*expected
));
6290 hr
= IDWriteFontFace_GetGdiCompatibleMetrics(fontface
, ptr
->ppdip
* fabsf(ptr
->m
.m22
) * ptr
->emsize
, 1.0, NULL
, expected
);
6291 ok(hr
== S_OK
, "got %08x\n", hr
);
6294 static void test_gdicompat_metrics(IDWriteFontFace
*face
)
6296 IDWriteFontFace1
*fontface1
= NULL
;
6298 DWRITE_FONT_METRICS design_metrics
, comp_metrics
;
6299 DWRITE_FONT_METRICS1 design_metrics1
, expected
;
6300 FLOAT emsize
, scale
;
6301 int ascent
, descent
;
6302 const struct VDMX_Header
*vdmx
;
6306 const struct VDMX_group
*vdmx_group
= NULL
;
6309 hr
= IDWriteFontFace_QueryInterface(face
, &IID_IDWriteFontFace1
, (void**)&fontface1
);
6311 win_skip("gdi compatible DWRITE_FONT_METRICS1 are not supported.\n");
6314 IDWriteFontFace1_GetMetrics(fontface1
, &design_metrics1
);
6315 memcpy(&design_metrics
, &design_metrics1
, sizeof(design_metrics
));
6318 IDWriteFontFace_GetMetrics(face
, &design_metrics
);
6320 hr
= IDWriteFontFace_TryGetFontTable(face
, MS_VDMX_TAG
, (const void **)&vdmx
,
6321 &vdmx_len
, &vdmx_ctx
, &exists
);
6322 if (hr
!= S_OK
|| !exists
)
6325 vdmx_group
= find_vdmx_group(vdmx
);
6327 /* negative emsize */
6328 memset(&comp_metrics
, 0xcc, sizeof(comp_metrics
));
6329 memset(&expected
, 0, sizeof(expected
));
6330 hr
= IDWriteFontFace_GetGdiCompatibleMetrics(face
, -10.0, 1.0, NULL
, &comp_metrics
);
6331 ok(hr
== E_INVALIDARG
, "got %08x\n", hr
);
6332 test_metrics_cmp(0.0, &comp_metrics
, &expected
);
6335 memset(&comp_metrics
, 0xcc, sizeof(comp_metrics
));
6336 memset(&expected
, 0, sizeof(expected
));
6337 hr
= IDWriteFontFace_GetGdiCompatibleMetrics(face
, 0.0, 1.0, NULL
, &comp_metrics
);
6338 ok(hr
== E_INVALIDARG
, "got %08x\n", hr
);
6339 test_metrics_cmp(0.0, &comp_metrics
, &expected
);
6341 /* zero pixels per dip */
6342 memset(&comp_metrics
, 0xcc, sizeof(comp_metrics
));
6343 memset(&expected
, 0, sizeof(expected
));
6344 hr
= IDWriteFontFace_GetGdiCompatibleMetrics(face
, 5.0, 0.0, NULL
, &comp_metrics
);
6345 ok(hr
== E_INVALIDARG
, "got %08x\n", hr
);
6346 test_metrics_cmp(5.0, &comp_metrics
, &expected
);
6348 memset(&comp_metrics
, 0xcc, sizeof(comp_metrics
));
6349 hr
= IDWriteFontFace_GetGdiCompatibleMetrics(face
, 5.0, -1.0, NULL
, &comp_metrics
);
6350 ok(hr
== E_INVALIDARG
, "got %08x\n", hr
);
6351 test_metrics_cmp(5.0, &comp_metrics
, &expected
);
6353 for (i
= 0; i
< ARRAY_SIZE(compatmetrics_tests
); i
++) {
6354 struct compatmetrics_test
*ptr
= &compatmetrics_tests
[i
];
6356 get_expected_metrics(face
, ptr
, (DWRITE_FONT_METRICS
*)&expected
);
6357 hr
= IDWriteFontFace_GetGdiCompatibleMetrics(face
, ptr
->emsize
, ptr
->ppdip
, &ptr
->m
, &comp_metrics
);
6358 ok(hr
== S_OK
, "got %08x\n", hr
);
6359 test_metrics_cmp(ptr
->emsize
, &comp_metrics
, &expected
);
6362 for (emsize
= 5; emsize
<= design_metrics
.designUnitsPerEm
; emsize
++)
6364 DWRITE_FONT_METRICS1 comp_metrics1
, expected
;
6367 hr
= IDWriteFontFace1_GetGdiCompatibleMetrics(fontface1
, emsize
, 1.0, NULL
, &comp_metrics1
);
6368 ok(hr
== S_OK
, "got %08x\n", hr
);
6371 hr
= IDWriteFontFace_GetGdiCompatibleMetrics(face
, emsize
, 1.0, NULL
, &comp_metrics
);
6372 ok(hr
== S_OK
, "got %08x\n", hr
);
6375 scale
= emsize
/ design_metrics
.designUnitsPerEm
;
6376 if (!get_vdmx_size(vdmx_group
, emsize
, &ascent
, &descent
))
6378 ascent
= round(design_metrics
.ascent
* scale
);
6379 descent
= round(design_metrics
.descent
* scale
);
6382 expected
.designUnitsPerEm
= design_metrics
.designUnitsPerEm
;
6383 expected
.ascent
= round(ascent
/ scale
);
6384 expected
.descent
= round(descent
/ scale
);
6385 expected
.lineGap
= round(round(design_metrics
.lineGap
* scale
) / scale
);
6386 expected
.capHeight
= round(round(design_metrics
.capHeight
* scale
) / scale
);
6387 expected
.xHeight
= round(round(design_metrics
.xHeight
* scale
) / scale
);
6388 expected
.underlinePosition
= round(round(design_metrics
.underlinePosition
* scale
) / scale
);
6389 expected
.underlineThickness
= round(round(design_metrics
.underlineThickness
* scale
) / scale
);
6390 expected
.strikethroughPosition
= round(round(design_metrics
.strikethroughPosition
* scale
) / scale
);
6391 expected
.strikethroughThickness
= round(round(design_metrics
.strikethroughThickness
* scale
) / scale
);
6394 expected
.glyphBoxLeft
= round(round(design_metrics1
.glyphBoxLeft
* scale
) / scale
);
6396 if (0) { /* those two fail on Tahoma and Win7 */
6397 expected
.glyphBoxTop
= round(round(design_metrics1
.glyphBoxTop
* scale
) / scale
);
6398 expected
.glyphBoxRight
= round(round(design_metrics1
.glyphBoxRight
* scale
) / scale
);
6400 expected
.glyphBoxBottom
= round(round(design_metrics1
.glyphBoxBottom
* scale
) / scale
);
6401 expected
.subscriptPositionX
= round(round(design_metrics1
.subscriptPositionX
* scale
) / scale
);
6402 expected
.subscriptPositionY
= round(round(design_metrics1
.subscriptPositionY
* scale
) / scale
);
6403 expected
.subscriptSizeX
= round(round(design_metrics1
.subscriptSizeX
* scale
) / scale
);
6404 expected
.subscriptSizeY
= round(round(design_metrics1
.subscriptSizeY
* scale
) / scale
);
6405 expected
.superscriptPositionX
= round(round(design_metrics1
.superscriptPositionX
* scale
) / scale
);
6406 if (0) /* this fails for 3 emsizes, Tahoma from [5, 2048] range */ {
6407 expected
.superscriptPositionY
= round(round(design_metrics1
.superscriptPositionY
* scale
) / scale
);
6409 expected
.superscriptSizeX
= round(round(design_metrics1
.superscriptSizeX
* scale
) / scale
);
6410 expected
.superscriptSizeY
= round(round(design_metrics1
.superscriptSizeY
* scale
) / scale
);
6411 expected
.hasTypographicMetrics
= design_metrics1
.hasTypographicMetrics
;
6413 test_metrics1_cmp(emsize
, &comp_metrics1
, &expected
);
6416 test_metrics_cmp(emsize
, &comp_metrics
, &expected
);
6421 IDWriteFontFace1_Release(fontface1
);
6422 if (vdmx
) IDWriteFontFace_ReleaseFontTable(face
, vdmx_ctx
);
6425 static void test_GetGdiCompatibleMetrics(void)
6427 IDWriteFactory
*factory
;
6429 IDWriteFontFace
*fontface
;
6433 factory
= create_factory();
6435 font
= get_font(factory
, L
"Tahoma", DWRITE_FONT_STYLE_NORMAL
);
6436 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
6437 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6438 IDWriteFont_Release(font
);
6439 test_gdicompat_metrics(fontface
);
6440 IDWriteFontFace_Release(fontface
);
6442 font
= get_font(factory
, L
"Arial", DWRITE_FONT_STYLE_NORMAL
);
6444 skip("Skipping tests with Arial\n");
6447 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
6448 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6449 IDWriteFont_Release(font
);
6451 test_gdicompat_metrics(fontface
);
6452 IDWriteFontFace_Release(fontface
);
6455 ref
= IDWriteFactory_Release(factory
);
6456 ok(ref
== 0, "factory not released, %u\n", ref
);
6459 static void get_expected_panose(IDWriteFont1
*font
, DWRITE_PANOSE
*panose
)
6461 IDWriteFontFace
*fontface
;
6462 const TT_OS2_V2
*tt_os2
;
6468 memset(panose
, 0, sizeof(*panose
));
6470 hr
= IDWriteFont1_CreateFontFace(font
, &fontface
);
6471 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6473 hr
= IDWriteFontFace_TryGetFontTable(fontface
, MS_OS2_TAG
, (const void **)&tt_os2
, &size
, &os2_context
, &exists
);
6474 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6477 memcpy(panose
, &tt_os2
->panose
, sizeof(*panose
));
6478 IDWriteFontFace_ReleaseFontTable(fontface
, os2_context
);
6481 IDWriteFontFace_Release(fontface
);
6484 static void test_GetPanose(void)
6486 IDWriteFontCollection
*syscollection
;
6487 IDWriteFactory
*factory
;
6488 IDWriteFont1
*font1
;
6494 factory
= create_factory();
6495 font
= get_tahoma_instance(factory
, DWRITE_FONT_STYLE_NORMAL
);
6497 hr
= IDWriteFont_QueryInterface(font
, &IID_IDWriteFont1
, (void **)&font1
);
6498 IDWriteFont_Release(font
);
6501 ref
= IDWriteFactory_Release(factory
);
6502 ok(ref
== 0, "factory not released, %u\n", ref
);
6503 win_skip("GetPanose() is not supported.\n");
6506 IDWriteFont1_Release(font1
);
6508 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &syscollection
, FALSE
);
6509 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6510 count
= IDWriteFontCollection_GetFontFamilyCount(syscollection
);
6512 for (i
= 0; i
< count
; i
++) {
6513 DWRITE_PANOSE panose
, expected_panose
;
6514 IDWriteLocalizedStrings
*names
;
6515 IDWriteFontFace3
*fontface3
;
6516 IDWriteFontFace
*fontface
;
6517 IDWriteFontFamily
*family
;
6518 IDWriteFont1
*font1
;
6522 hr
= IDWriteFontCollection_GetFontFamily(syscollection
, i
, &family
);
6523 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6525 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STRETCH_NORMAL
,
6526 DWRITE_FONT_STYLE_NORMAL
, &font
);
6527 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6529 hr
= IDWriteFont_QueryInterface(font
, &IID_IDWriteFont1
, (void **)&font1
);
6530 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6531 IDWriteFont_Release(font
);
6533 hr
= IDWriteFontFamily_GetFamilyNames(family
, &names
);
6534 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6536 get_enus_string(names
, nameW
, ARRAY_SIZE(nameW
));
6538 IDWriteLocalizedStrings_Release(names
);
6540 IDWriteFont1_GetPanose(font1
, &panose
);
6541 get_expected_panose(font1
, &expected_panose
);
6543 ok(panose
.values
[0] == expected_panose
.values
[0], "%s: values[0] %#x, expected %#x.\n", wine_dbgstr_w(nameW
),
6544 panose
.values
[0], expected_panose
.values
[0]);
6545 ok(panose
.values
[1] == expected_panose
.values
[1], "%s: values[1] %#x, expected %#x.\n", wine_dbgstr_w(nameW
),
6546 panose
.values
[1], expected_panose
.values
[1]);
6547 ok(panose
.values
[2] == expected_panose
.values
[2], "%s: values[2] %#x, expected %#x.\n", wine_dbgstr_w(nameW
),
6548 panose
.values
[2], expected_panose
.values
[2]);
6549 ok(panose
.values
[3] == expected_panose
.values
[3], "%s: values[3] %#x, expected %#x.\n", wine_dbgstr_w(nameW
),
6550 panose
.values
[3], expected_panose
.values
[3]);
6551 ok(panose
.values
[4] == expected_panose
.values
[4], "%s: values[4] %#x, expected %#x.\n", wine_dbgstr_w(nameW
),
6552 panose
.values
[4], expected_panose
.values
[4]);
6553 ok(panose
.values
[5] == expected_panose
.values
[5], "%s: values[5] %#x, expected %#x.\n", wine_dbgstr_w(nameW
),
6554 panose
.values
[5], expected_panose
.values
[5]);
6555 ok(panose
.values
[6] == expected_panose
.values
[6], "%s: values[6] %#x, expected %#x.\n", wine_dbgstr_w(nameW
),
6556 panose
.values
[6], expected_panose
.values
[6]);
6557 ok(panose
.values
[7] == expected_panose
.values
[7], "%s: values[7] %#x, expected %#x.\n", wine_dbgstr_w(nameW
),
6558 panose
.values
[7], expected_panose
.values
[7]);
6559 ok(panose
.values
[8] == expected_panose
.values
[8], "%s: values[8] %#x, expected %#x.\n", wine_dbgstr_w(nameW
),
6560 panose
.values
[8], expected_panose
.values
[8]);
6561 ok(panose
.values
[9] == expected_panose
.values
[9], "%s: values[9] %#x, expected %#x.\n", wine_dbgstr_w(nameW
),
6562 panose
.values
[9], expected_panose
.values
[9]);
6564 hr
= IDWriteFont1_CreateFontFace(font1
, &fontface
);
6565 ok(hr
== S_OK
, "Failed to create a font face, %#x.\n", hr
);
6566 if (IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace3
, (void **)&fontface3
) == S_OK
) {
6567 ok(!memcmp(&panose
, &expected_panose
, sizeof(panose
)), "%s: Unexpected panose from font face.\n",
6568 wine_dbgstr_w(nameW
));
6569 IDWriteFontFace3_Release(fontface3
);
6571 IDWriteFontFace_Release(fontface
);
6573 IDWriteFont1_Release(font1
);
6574 IDWriteFontFamily_Release(family
);
6577 IDWriteFontCollection_Release(syscollection
);
6578 ref
= IDWriteFactory_Release(factory
);
6579 ok(ref
== 0, "factory not released, %u\n", ref
);
6582 static INT32
get_gdi_font_advance(HDC hdc
, FLOAT emsize
)
6589 memset(&logfont
, 0, sizeof(logfont
));
6590 logfont
.lfHeight
= (LONG
)-emsize
;
6591 logfont
.lfWeight
= FW_NORMAL
;
6592 logfont
.lfQuality
= CLEARTYPE_QUALITY
;
6593 lstrcpyW(logfont
.lfFaceName
, L
"Tahoma");
6595 hfont
= CreateFontIndirectW(&logfont
);
6596 SelectObject(hdc
, hfont
);
6598 ret
= GetCharABCWidthsW(hdc
, 'A', 'A', &abc
);
6599 ok(ret
, "got %d\n", ret
);
6601 DeleteObject(hfont
);
6603 return abc
.abcA
+ abc
.abcB
+ abc
.abcC
;
6606 static void test_GetGdiCompatibleGlyphAdvances(void)
6608 IDWriteFontFace1
*fontface1
;
6609 IDWriteFontFace
*fontface
;
6610 IDWriteFactory
*factory
;
6617 DWRITE_FONT_METRICS1 fm
;
6621 factory
= create_factory();
6622 font
= get_tahoma_instance(factory
, DWRITE_FONT_STYLE_NORMAL
);
6624 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
6625 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6626 IDWriteFont_Release(font
);
6628 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void **)&fontface1
);
6629 IDWriteFontFace_Release(fontface
);
6632 ref
= IDWriteFactory_Release(factory
);
6633 ok(ref
== 0, "factory not released, %u\n", ref
);
6634 win_skip("GetGdiCompatibleGlyphAdvances() is not supported\n");
6640 hr
= IDWriteFontFace1_GetGlyphIndices(fontface1
, &codepoint
, 1, &glyph
);
6641 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6642 ok(glyph
> 0, "got %u\n", glyph
);
6646 hr
= IDWriteFontFace1_GetGdiCompatibleGlyphAdvances(fontface1
, 0.0,
6647 1.0, NULL
, FALSE
, FALSE
, 1, &glyph
, &advance
);
6648 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6649 ok(advance
== 0, "got %d\n", advance
);
6651 /* negative emsize */
6653 hr
= IDWriteFontFace1_GetGdiCompatibleGlyphAdvances(fontface1
, -1.0,
6654 1.0, NULL
, FALSE
, FALSE
, 1, &glyph
, &advance
);
6655 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
6656 ok(advance
== 0, "got %d\n", advance
);
6660 hr
= IDWriteFontFace1_GetGdiCompatibleGlyphAdvances(fontface1
, 1.0,
6661 0.0, NULL
, FALSE
, FALSE
, 1, &glyph
, &advance
);
6662 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
6663 ok(advance
== 0, "got %d\n", advance
);
6665 /* negative ppdip */
6667 hr
= IDWriteFontFace1_GetGdiCompatibleGlyphAdvances(fontface1
, 1.0,
6668 -1.0, NULL
, FALSE
, FALSE
, 1, &glyph
, &advance
);
6669 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
6670 ok(advance
== 0, "got %d\n", advance
);
6672 IDWriteFontFace1_GetMetrics(fontface1
, &fm
);
6674 hdc
= CreateCompatibleDC(0);
6676 for (emsize
= 1.0; emsize
<= fm
.designUnitsPerEm
; emsize
+= 1.0) {
6679 gdi_advance
= get_gdi_font_advance(hdc
, emsize
);
6680 hr
= IDWriteFontFace1_GetGdiCompatibleGlyphAdvances(fontface1
, emsize
,
6681 1.0, NULL
, FALSE
, FALSE
, 1, &glyph
, &advance
);
6682 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6684 /* advance is in design units */
6685 advance
= (int)floorf(emsize
* advance
/ fm
.designUnitsPerEm
+ 0.5f
);
6686 ok((advance
- gdi_advance
) <= 2, "%.0f: got advance %d, expected %d\n", emsize
, advance
, gdi_advance
);
6691 IDWriteFontFace1_Release(fontface1
);
6692 ref
= IDWriteFactory_Release(factory
);
6693 ok(ref
== 0, "factory not released, %u\n", ref
);
6696 static WORD
get_gasp_flags(IDWriteFontFace
*fontface
, FLOAT emsize
, FLOAT ppdip
)
6698 WORD num_recs
, version
;
6709 hr
= IDWriteFontFace_TryGetFontTable(fontface
, MS_GASP_TAG
,
6710 (const void**)&ptr
, &size
, &ctxt
, &exists
);
6711 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6716 version
= GET_BE_WORD( *ptr
++ );
6717 num_recs
= GET_BE_WORD( *ptr
++ );
6718 if (version
> 1 || size
< (num_recs
* 2 + 2) * sizeof(WORD
)) {
6719 ok(0, "unsupported gasp table: ver %d size %d recs %d\n", version
, size
, num_recs
);
6725 flags
= GET_BE_WORD( *(ptr
+ 1) );
6726 if (emsize
<= GET_BE_WORD( *ptr
)) break;
6731 IDWriteFontFace_ReleaseFontTable(fontface
, ctxt
);
6735 #define GASP_GRIDFIT 0x0001
6736 #define GASP_DOGRAY 0x0002
6737 #define GASP_SYMMETRIC_GRIDFIT 0x0004
6738 #define GASP_SYMMETRIC_SMOOTHING 0x0008
6740 static BOOL g_is_vista
;
6741 static DWRITE_RENDERING_MODE
get_expected_rendering_mode(FLOAT emsize
, WORD gasp
, DWRITE_MEASURING_MODE mode
,
6742 DWRITE_OUTLINE_THRESHOLD threshold
)
6744 static const FLOAT aa_threshold
= 100.0f
;
6745 static const FLOAT a_threshold
= 350.0f
;
6746 static const FLOAT naturalemsize
= 20.0f
;
6749 /* outline threshold */
6751 v
= mode
== DWRITE_MEASURING_MODE_NATURAL
? aa_threshold
: a_threshold
;
6753 v
= threshold
== DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
? aa_threshold
: a_threshold
;
6756 return DWRITE_RENDERING_MODE_OUTLINE
;
6760 case DWRITE_MEASURING_MODE_NATURAL
:
6761 if (!(gasp
& GASP_SYMMETRIC_SMOOTHING
) && (emsize
<= naturalemsize
))
6762 return DWRITE_RENDERING_MODE_NATURAL
;
6764 return DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
;
6765 case DWRITE_MEASURING_MODE_GDI_CLASSIC
:
6766 return DWRITE_RENDERING_MODE_GDI_CLASSIC
;
6767 case DWRITE_MEASURING_MODE_GDI_NATURAL
:
6768 return DWRITE_RENDERING_MODE_GDI_NATURAL
;
6773 /* should be unreachable */
6774 return DWRITE_RENDERING_MODE_DEFAULT
;
6777 static DWRITE_GRID_FIT_MODE
get_expected_gridfit_mode(FLOAT emsize
, WORD gasp
, DWRITE_MEASURING_MODE mode
,
6778 DWRITE_OUTLINE_THRESHOLD threshold
)
6780 static const FLOAT aa_threshold
= 100.0f
;
6781 static const FLOAT a_threshold
= 350.0f
;
6784 v
= threshold
== DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
? aa_threshold
: a_threshold
;
6786 return DWRITE_GRID_FIT_MODE_DISABLED
;
6788 if (mode
== DWRITE_MEASURING_MODE_GDI_CLASSIC
|| mode
== DWRITE_MEASURING_MODE_GDI_NATURAL
)
6789 return DWRITE_GRID_FIT_MODE_ENABLED
;
6791 return (gasp
& (GASP_GRIDFIT
|GASP_SYMMETRIC_GRIDFIT
)) ? DWRITE_GRID_FIT_MODE_ENABLED
: DWRITE_GRID_FIT_MODE_DISABLED
;
6794 struct recommendedmode_test
6796 DWRITE_MEASURING_MODE measuring
;
6797 DWRITE_OUTLINE_THRESHOLD threshold
;
6800 static const struct recommendedmode_test recmode_tests
[] = {
6801 { DWRITE_MEASURING_MODE_NATURAL
, DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
},
6802 { DWRITE_MEASURING_MODE_GDI_CLASSIC
, DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
},
6803 { DWRITE_MEASURING_MODE_GDI_NATURAL
, DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
},
6806 static const struct recommendedmode_test recmode_tests1
[] = {
6807 { DWRITE_MEASURING_MODE_NATURAL
, DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
},
6808 { DWRITE_MEASURING_MODE_GDI_CLASSIC
, DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
},
6809 { DWRITE_MEASURING_MODE_GDI_NATURAL
, DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
},
6810 { DWRITE_MEASURING_MODE_NATURAL
, DWRITE_OUTLINE_THRESHOLD_ALIASED
},
6811 { DWRITE_MEASURING_MODE_GDI_CLASSIC
, DWRITE_OUTLINE_THRESHOLD_ALIASED
},
6812 { DWRITE_MEASURING_MODE_GDI_NATURAL
, DWRITE_OUTLINE_THRESHOLD_ALIASED
},
6815 static void test_GetRecommendedRenderingMode(void)
6817 IDWriteRenderingParams
*params
;
6818 IDWriteFontFace3
*fontface3
;
6819 IDWriteFontFace2
*fontface2
;
6820 IDWriteFontFace1
*fontface1
;
6821 IDWriteFontFace
*fontface
;
6822 DWRITE_RENDERING_MODE mode
;
6823 IDWriteFactory
*factory
;
6828 factory
= create_factory();
6829 fontface
= create_fontface(factory
);
6832 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void**)&fontface1
);
6834 win_skip("IDWriteFontFace1::GetRecommendedRenderingMode() is not supported.\n");
6837 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace2
, (void**)&fontface2
);
6839 win_skip("IDWriteFontFace2::GetRecommendedRenderingMode() is not supported.\n");
6842 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace3
, (void**)&fontface3
);
6844 win_skip("IDWriteFontFace3::GetRecommendedRenderingMode() is not supported.\n");
6846 if (0) /* crashes on native */
6847 hr
= IDWriteFontFace_GetRecommendedRenderingMode(fontface
, 3.0, 1.0,
6848 DWRITE_MEASURING_MODE_GDI_CLASSIC
, NULL
, NULL
);
6851 hr
= IDWriteFontFace_GetRecommendedRenderingMode(fontface
, 3.0, 1.0,
6852 DWRITE_MEASURING_MODE_GDI_CLASSIC
, NULL
, &mode
);
6853 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
6854 ok(mode
== DWRITE_RENDERING_MODE_DEFAULT
, "got %d\n", mode
);
6856 hr
= IDWriteFactory_CreateRenderingParams(factory
, ¶ms
);
6857 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6859 /* detect old dwrite version, that is using higher threshold value */
6860 g_is_vista
= fontface1
== NULL
;
6862 for (emsize
= 1.0; emsize
< 500.0; emsize
+= 1.0) {
6863 DWRITE_RENDERING_MODE expected
;
6868 for (i
= 0; i
< ARRAY_SIZE(recmode_tests
); i
++) {
6871 gasp
= get_gasp_flags(fontface
, emsize
, ppdip
);
6872 expected
= get_expected_rendering_mode(emsize
* ppdip
, gasp
, recmode_tests
[i
].measuring
, recmode_tests
[i
].threshold
);
6873 hr
= IDWriteFontFace_GetRecommendedRenderingMode(fontface
, emsize
, ppdip
, recmode_tests
[i
].measuring
, params
, &mode
);
6874 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6875 ok(mode
== expected
, "%.2f/%d: got %d, ppdip %f, flags 0x%04x, expected %d\n", emsize
, i
, mode
, ppdip
, gasp
, expected
);
6877 /* some ppdip variants */
6880 gasp
= get_gasp_flags(fontface
, emsize
, ppdip
);
6881 expected
= get_expected_rendering_mode(emsize
* ppdip
, gasp
, recmode_tests
[i
].measuring
, recmode_tests
[i
].threshold
);
6882 hr
= IDWriteFontFace_GetRecommendedRenderingMode(fontface
, emsize
, ppdip
, recmode_tests
[i
].measuring
, params
, &mode
);
6883 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6884 ok(mode
== expected
, "%.2f/%d: got %d, ppdip %f, flags 0x%04x, expected %d\n", emsize
, i
, mode
, ppdip
, gasp
, expected
);
6886 /* Only test larger sizes to workaround Win7 differences, where unscaled natural emsize threshold is used;
6887 Win8 and Win10 handle this as expected. */
6888 if (emsize
> 20.0f
) {
6891 gasp
= get_gasp_flags(fontface
, emsize
, ppdip
);
6892 expected
= get_expected_rendering_mode(emsize
* ppdip
, gasp
, recmode_tests
[i
].measuring
, recmode_tests
[i
].threshold
);
6893 hr
= IDWriteFontFace_GetRecommendedRenderingMode(fontface
, emsize
, ppdip
, recmode_tests
[i
].measuring
, params
, &mode
);
6894 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6895 ok(mode
== expected
, "%.2f/%d: got %d, ppdip %f, flags 0x%04x, expected %d\n", emsize
, i
, mode
, ppdip
, gasp
, expected
);
6899 gasp
= get_gasp_flags(fontface
, emsize
, ppdip
);
6900 expected
= get_expected_rendering_mode(emsize
* ppdip
, gasp
, recmode_tests
[i
].measuring
, recmode_tests
[i
].threshold
);
6901 hr
= IDWriteFontFace_GetRecommendedRenderingMode(fontface
, emsize
, ppdip
, recmode_tests
[i
].measuring
, params
, &mode
);
6902 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6903 ok(mode
== expected
, "%.2f/%d: got %d, ppdip %f, flags 0x%04x, expected %d\n", emsize
, i
, mode
, ppdip
, gasp
, expected
);
6907 /* IDWriteFontFace1 offers another variant of this method */
6909 for (i
= 0; i
< ARRAY_SIZE(recmode_tests1
); i
++) {
6913 dpi
= 96.0f
* ppdip
;
6915 gasp
= get_gasp_flags(fontface
, emsize
, ppdip
);
6916 expected
= get_expected_rendering_mode(emsize
* ppdip
, gasp
, recmode_tests1
[i
].measuring
, recmode_tests1
[i
].threshold
);
6917 hr
= IDWriteFontFace1_GetRecommendedRenderingMode(fontface1
, emsize
, dpi
, dpi
,
6918 NULL
, FALSE
, recmode_tests1
[i
].threshold
, recmode_tests1
[i
].measuring
, &mode
);
6919 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6920 ok(mode
== expected
, "%.2f/%d: got %d, dpi %f, flags 0x%04x, expected %d\n", emsize
, i
, mode
, dpi
, gasp
, expected
);
6922 /* Only test larger sizes to workaround Win7 differences, where unscaled natural emsize threshold is used;
6923 Win8 and Win10 handle this as expected. */
6924 if (emsize
> 20.0f
) {
6926 dpi
= 96.0f
* ppdip
;
6928 gasp
= get_gasp_flags(fontface
, emsize
, ppdip
);
6929 expected
= get_expected_rendering_mode(emsize
* ppdip
, gasp
, recmode_tests1
[i
].measuring
, recmode_tests1
[i
].threshold
);
6930 hr
= IDWriteFontFace1_GetRecommendedRenderingMode(fontface1
, emsize
, dpi
, dpi
,
6931 NULL
, FALSE
, recmode_tests1
[i
].threshold
, recmode_tests1
[i
].measuring
, &mode
);
6932 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6933 ok(mode
== expected
, "%.2f/%d: got %d, dpi %f, flags 0x%04x, expected %d\n", emsize
, i
, mode
, dpi
, gasp
, expected
);
6936 dpi
= 96.0f
* ppdip
;
6938 gasp
= get_gasp_flags(fontface
, emsize
, ppdip
);
6939 expected
= get_expected_rendering_mode(emsize
* ppdip
, gasp
, recmode_tests1
[i
].measuring
, recmode_tests1
[i
].threshold
);
6940 hr
= IDWriteFontFace1_GetRecommendedRenderingMode(fontface1
, emsize
, dpi
, dpi
,
6941 NULL
, FALSE
, recmode_tests1
[i
].threshold
, recmode_tests1
[i
].measuring
, &mode
);
6942 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6943 ok(mode
== expected
, "%.2f/%d: got %d, dpi %f, flags 0x%04x, expected %d\n", emsize
, i
, mode
, dpi
, gasp
, expected
);
6945 /* try different dpis for X and Y direction */
6947 dpi
= 96.0f
* ppdip
;
6949 gasp
= get_gasp_flags(fontface
, emsize
, ppdip
);
6950 expected
= get_expected_rendering_mode(emsize
* ppdip
, gasp
, recmode_tests1
[i
].measuring
, recmode_tests1
[i
].threshold
);
6951 hr
= IDWriteFontFace1_GetRecommendedRenderingMode(fontface1
, emsize
, dpi
* 0.5f
, dpi
,
6952 NULL
, FALSE
, recmode_tests1
[i
].threshold
, recmode_tests1
[i
].measuring
, &mode
);
6953 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6954 ok(mode
== expected
, "%.2f/%d: got %d, dpi %f, flags 0x%04x, expected %d\n", emsize
, i
, mode
, dpi
, gasp
, expected
);
6957 dpi
= 96.0f
* ppdip
;
6959 gasp
= get_gasp_flags(fontface
, emsize
, ppdip
);
6960 expected
= get_expected_rendering_mode(emsize
* ppdip
, gasp
, recmode_tests1
[i
].measuring
, recmode_tests1
[i
].threshold
);
6961 hr
= IDWriteFontFace1_GetRecommendedRenderingMode(fontface1
, emsize
, dpi
, dpi
* 0.5f
,
6962 NULL
, FALSE
, recmode_tests1
[i
].threshold
, recmode_tests1
[i
].measuring
, &mode
);
6963 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6964 ok(mode
== expected
, "%.2f/%d: got %d, dpi %f, flags 0x%04x, expected %d\n", emsize
, i
, mode
, dpi
, gasp
, expected
);
6967 dpi
= 96.0f
* ppdip
;
6969 gasp
= get_gasp_flags(fontface
, emsize
, ppdip
);
6970 expected
= get_expected_rendering_mode(emsize
* ppdip
, gasp
, recmode_tests1
[i
].measuring
, recmode_tests1
[i
].threshold
);
6971 hr
= IDWriteFontFace1_GetRecommendedRenderingMode(fontface1
, emsize
, dpi
* 0.5f
, dpi
,
6972 NULL
, FALSE
, recmode_tests1
[i
].threshold
, recmode_tests1
[i
].measuring
, &mode
);
6973 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6974 ok(mode
== expected
, "%.2f/%d: got %d, dpi %f, flags 0x%04x, expected %d\n", emsize
, i
, mode
, dpi
, gasp
, expected
);
6977 dpi
= 96.0f
* ppdip
;
6979 gasp
= get_gasp_flags(fontface
, emsize
, ppdip
);
6980 expected
= get_expected_rendering_mode(emsize
* ppdip
, gasp
, recmode_tests1
[i
].measuring
, recmode_tests1
[i
].threshold
);
6981 hr
= IDWriteFontFace1_GetRecommendedRenderingMode(fontface1
, emsize
, dpi
, dpi
* 0.5f
,
6982 NULL
, FALSE
, recmode_tests1
[i
].threshold
, recmode_tests1
[i
].measuring
, &mode
);
6983 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6984 ok(mode
== expected
, "%.2f/%d: got %d, dpi %f, flags 0x%04x, expected %d\n", emsize
, i
, mode
, dpi
, gasp
, expected
);
6989 /* IDWriteFontFace2 - another one */
6991 DWRITE_GRID_FIT_MODE gridfit
, expected_gridfit
;
6993 gasp
= get_gasp_flags(fontface
, emsize
, 1.0f
);
6994 for (i
= 0; i
< ARRAY_SIZE(recmode_tests1
); i
++) {
6996 expected
= get_expected_rendering_mode(emsize
, gasp
, recmode_tests1
[i
].measuring
, recmode_tests1
[i
].threshold
);
6997 expected_gridfit
= get_expected_gridfit_mode(emsize
, gasp
, recmode_tests1
[i
].measuring
, recmode_tests1
[i
].threshold
);
6998 hr
= IDWriteFontFace2_GetRecommendedRenderingMode(fontface2
, emsize
, 96.0f
, 96.0f
,
6999 NULL
, FALSE
, recmode_tests1
[i
].threshold
, recmode_tests1
[i
].measuring
, params
, &mode
, &gridfit
);
7000 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7001 ok(mode
== expected
, "%.2f: got %d, flags 0x%04x, expected %d\n", emsize
, mode
, gasp
, expected
);
7002 ok(gridfit
== expected_gridfit
, "%.2f/%d: gridfit: got %d, flags 0x%04x, expected %d\n", emsize
, i
, gridfit
,
7003 gasp
, expected_gridfit
);
7007 /* IDWriteFontFace3 - and another one */
7009 DWRITE_GRID_FIT_MODE gridfit
, expected_gridfit
;
7010 DWRITE_RENDERING_MODE1 mode1
, expected1
;
7012 gasp
= get_gasp_flags(fontface
, emsize
, 1.0f
);
7013 for (i
= 0; i
< ARRAY_SIZE(recmode_tests1
); i
++) {
7015 expected1
= get_expected_rendering_mode(emsize
, gasp
, recmode_tests1
[i
].measuring
, recmode_tests1
[i
].threshold
);
7016 expected_gridfit
= get_expected_gridfit_mode(emsize
, gasp
, recmode_tests1
[i
].measuring
, recmode_tests1
[i
].threshold
);
7017 hr
= IDWriteFontFace3_GetRecommendedRenderingMode(fontface3
, emsize
, 96.0f
, 96.0f
,
7018 NULL
, FALSE
, recmode_tests1
[i
].threshold
, recmode_tests1
[i
].measuring
, params
, &mode1
, &gridfit
);
7019 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7020 ok(mode1
== expected1
, "%.2f: got %d, flags 0x%04x, expected %d\n", emsize
, mode1
, gasp
, expected1
);
7021 ok(gridfit
== expected_gridfit
, "%.2f/%d: gridfit: got %d, flags 0x%04x, expected %d\n", emsize
, i
, gridfit
,
7022 gasp
, expected_gridfit
);
7027 IDWriteRenderingParams_Release(params
);
7029 /* test how parameters override returned modes */
7030 hr
= IDWriteFactory_CreateCustomRenderingParams(factory
, 1.0, 0.0, 0.0, DWRITE_PIXEL_GEOMETRY_FLAT
,
7031 DWRITE_RENDERING_MODE_GDI_CLASSIC
, ¶ms
);
7032 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7035 hr
= IDWriteFontFace_GetRecommendedRenderingMode(fontface
, 500.0, 1.0, DWRITE_MEASURING_MODE_NATURAL
, params
, &mode
);
7036 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7037 ok(mode
== DWRITE_RENDERING_MODE_GDI_CLASSIC
, "got %d\n", mode
);
7039 IDWriteRenderingParams_Release(params
);
7042 IDWriteRenderingParams2
*params2
;
7043 IDWriteFactory2
*factory2
;
7044 DWRITE_GRID_FIT_MODE gridfit
;
7046 hr
= IDWriteFactory_QueryInterface(factory
, &IID_IDWriteFactory2
, (void**)&factory2
);
7047 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7049 hr
= IDWriteFactory2_CreateCustomRenderingParams(factory2
, 1.0, 0.0, 0.0, 0.5, DWRITE_PIXEL_GEOMETRY_FLAT
,
7050 DWRITE_RENDERING_MODE_OUTLINE
, DWRITE_GRID_FIT_MODE_ENABLED
, ¶ms2
);
7051 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7055 hr
= IDWriteFontFace2_GetRecommendedRenderingMode(fontface2
, 5.0, 96.0, 96.0,
7056 NULL
, FALSE
, DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
, DWRITE_MEASURING_MODE_GDI_CLASSIC
,
7057 NULL
, &mode
, &gridfit
);
7058 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7059 ok(mode
== DWRITE_RENDERING_MODE_GDI_CLASSIC
, "got %d\n", mode
);
7060 ok(gridfit
== DWRITE_GRID_FIT_MODE_ENABLED
, "got %d\n", gridfit
);
7064 hr
= IDWriteFontFace2_GetRecommendedRenderingMode(fontface2
, 5.0, 96.0, 96.0,
7065 NULL
, FALSE
, DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
, DWRITE_MEASURING_MODE_GDI_CLASSIC
,
7066 (IDWriteRenderingParams
*)params2
, &mode
, &gridfit
);
7067 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7068 ok(mode
== DWRITE_RENDERING_MODE_OUTLINE
, "got %d\n", mode
);
7069 ok(gridfit
== DWRITE_GRID_FIT_MODE_ENABLED
, "got %d\n", gridfit
);
7071 IDWriteRenderingParams2_Release(params2
);
7072 IDWriteFactory2_Release(factory2
);
7076 IDWriteRenderingParams3
*params3
;
7077 IDWriteRenderingParams2
*params2
;
7078 IDWriteRenderingParams
*params
;
7079 IDWriteFactory3
*factory3
;
7080 DWRITE_GRID_FIT_MODE gridfit
;
7081 DWRITE_RENDERING_MODE1 mode1
;
7083 hr
= IDWriteFactory_QueryInterface(factory
, &IID_IDWriteFactory3
, (void**)&factory3
);
7084 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7086 hr
= IDWriteFactory3_CreateCustomRenderingParams(factory3
, 1.0f
, 0.0f
, 0.0f
, 0.5f
, DWRITE_PIXEL_GEOMETRY_FLAT
,
7087 DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC_DOWNSAMPLED
, DWRITE_GRID_FIT_MODE_ENABLED
, ¶ms3
);
7088 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7090 mode1
= IDWriteRenderingParams3_GetRenderingMode1(params3
);
7091 ok(mode1
== DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC_DOWNSAMPLED
, "got %d\n", mode1
);
7093 mode
= IDWriteRenderingParams3_GetRenderingMode(params3
);
7094 ok(mode
== DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
, "got %d\n", mode
);
7096 hr
= IDWriteRenderingParams3_QueryInterface(params3
, &IID_IDWriteRenderingParams
, (void**)¶ms
);
7097 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7098 ok(params
== (IDWriteRenderingParams
*)params3
, "got %p, %p\n", params3
, params
);
7099 mode
= IDWriteRenderingParams_GetRenderingMode(params
);
7100 ok(mode
== DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
, "got %d\n", mode
);
7101 IDWriteRenderingParams_Release(params
);
7103 hr
= IDWriteRenderingParams3_QueryInterface(params3
, &IID_IDWriteRenderingParams2
, (void**)¶ms2
);
7104 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7105 ok(params2
== (IDWriteRenderingParams2
*)params3
, "got %p, %p\n", params3
, params2
);
7106 mode
= IDWriteRenderingParams2_GetRenderingMode(params2
);
7107 ok(mode
== DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
, "got %d\n", mode
);
7108 IDWriteRenderingParams2_Release(params2
);
7112 hr
= IDWriteFontFace2_GetRecommendedRenderingMode(fontface2
, 5.0f
, 96.0f
, 96.0f
,
7113 NULL
, FALSE
, DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
, DWRITE_MEASURING_MODE_GDI_CLASSIC
,
7114 NULL
, &mode
, &gridfit
);
7115 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7116 ok(mode
== DWRITE_RENDERING_MODE_GDI_CLASSIC
, "got %d\n", mode
);
7117 ok(gridfit
== DWRITE_GRID_FIT_MODE_ENABLED
, "got %d\n", gridfit
);
7121 hr
= IDWriteFontFace2_GetRecommendedRenderingMode(fontface2
, 5.0f
, 96.0f
, 96.0f
,
7122 NULL
, FALSE
, DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
, DWRITE_MEASURING_MODE_GDI_CLASSIC
,
7123 (IDWriteRenderingParams
*)params3
, &mode
, &gridfit
);
7124 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7125 ok(mode
== DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
, "got %d\n", mode
);
7126 ok(gridfit
== DWRITE_GRID_FIT_MODE_ENABLED
, "got %d\n", gridfit
);
7128 IDWriteRenderingParams3_Release(params3
);
7129 IDWriteFactory3_Release(factory3
);
7133 IDWriteFontFace3_Release(fontface3
);
7135 IDWriteFontFace2_Release(fontface2
);
7137 IDWriteFontFace1_Release(fontface1
);
7138 IDWriteFontFace_Release(fontface
);
7139 ref
= IDWriteFactory_Release(factory
);
7140 ok(ref
== 0, "factory not released, %u\n", ref
);
7143 static inline BOOL
float_eq(FLOAT left
, FLOAT right
)
7145 int x
= *(int *)&left
;
7146 int y
= *(int *)&right
;
7153 return abs(x
- y
) <= 8;
7156 static void test_GetAlphaBlendParams(void)
7158 static const DWRITE_RENDERING_MODE rendermodes
[] = {
7159 DWRITE_RENDERING_MODE_ALIASED
,
7160 DWRITE_RENDERING_MODE_GDI_CLASSIC
,
7161 DWRITE_RENDERING_MODE_GDI_NATURAL
,
7162 DWRITE_RENDERING_MODE_NATURAL
,
7163 DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
,
7166 IDWriteGlyphRunAnalysis
*analysis
;
7167 FLOAT gamma
, contrast
, ctlevel
;
7168 IDWriteRenderingParams
*params
;
7169 DWRITE_GLYPH_METRICS metrics
;
7170 DWRITE_GLYPH_OFFSET offset
;
7171 IDWriteFontFace
*fontface
;
7172 IDWriteFactory
*factory
;
7173 DWRITE_GLYPH_RUN run
;
7174 FLOAT advance
, expected_gdi_gamma
;
7182 factory
= create_factory();
7183 fontface
= create_fontface(factory
);
7187 hr
= IDWriteFontFace_GetGlyphIndices(fontface
, &ch
, 1, &glyph
);
7188 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7189 ok(glyph
> 0, "got %u\n", glyph
);
7191 hr
= IDWriteFontFace_GetDesignGlyphMetrics(fontface
, &glyph
, 1, &metrics
, FALSE
);
7192 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7193 advance
= metrics
.advanceWidth
;
7195 offset
.advanceOffset
= 0.0;
7196 offset
.ascenderOffset
= 0.0;
7198 run
.fontFace
= fontface
;
7199 run
.fontEmSize
= 24.0;
7201 run
.glyphIndices
= &glyph
;
7202 run
.glyphAdvances
= &advance
;
7203 run
.glyphOffsets
= &offset
;
7204 run
.isSideways
= FALSE
;
7207 hr
= IDWriteFactory_CreateCustomRenderingParams(factory
, 0.9, 0.3, 0.1, DWRITE_PIXEL_GEOMETRY_RGB
,
7208 DWRITE_RENDERING_MODE_DEFAULT
, ¶ms
);
7209 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7212 ret
= SystemParametersInfoW(SPI_GETFONTSMOOTHINGCONTRAST
, 0, &value
, 0);
7213 ok(ret
, "got %d\n", ret
);
7214 expected_gdi_gamma
= (FLOAT
)(value
/ 1000.0);
7216 for (i
= 0; i
< ARRAY_SIZE(rendermodes
); i
++) {
7217 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 1.0, NULL
,
7218 rendermodes
[i
], DWRITE_MEASURING_MODE_NATURAL
,
7219 0.0, 0.0, &analysis
);
7220 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7222 gamma
= contrast
= ctlevel
= -1.0;
7223 hr
= IDWriteGlyphRunAnalysis_GetAlphaBlendParams(analysis
, NULL
, &gamma
, &contrast
, &ctlevel
);
7224 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
7225 ok(gamma
== -1.0, "got %.2f\n", gamma
);
7226 ok(contrast
== -1.0, "got %.2f\n", contrast
);
7227 ok(ctlevel
== -1.0, "got %.2f\n", ctlevel
);
7229 gamma
= contrast
= ctlevel
= -1.0;
7230 hr
= IDWriteGlyphRunAnalysis_GetAlphaBlendParams(analysis
, params
, &gamma
, &contrast
, &ctlevel
);
7231 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7233 if (rendermodes
[i
] == DWRITE_RENDERING_MODE_GDI_CLASSIC
|| rendermodes
[i
] == DWRITE_RENDERING_MODE_GDI_NATURAL
) {
7234 ok(float_eq(gamma
, expected_gdi_gamma
), "got %.2f, expected %.2f\n", gamma
, expected_gdi_gamma
);
7235 ok(contrast
== 0.0f
, "got %.2f\n", contrast
);
7236 ok(ctlevel
== 1.0f
, "got %.2f\n", ctlevel
);
7239 ok(gamma
== 0.9f
, "got %.2f\n", gamma
);
7240 ok(contrast
== 0.3f
, "got %.2f\n", contrast
);
7241 ok(ctlevel
== 0.1f
, "got %.2f\n", ctlevel
);
7244 IDWriteGlyphRunAnalysis_Release(analysis
);
7247 IDWriteRenderingParams_Release(params
);
7248 IDWriteFontFace_Release(fontface
);
7249 ref
= IDWriteFactory_Release(factory
);
7250 ok(ref
== 0, "factory not released, %u\n", ref
);
7253 static void test_CreateAlphaTexture(void)
7255 IDWriteGlyphRunAnalysis
*analysis
;
7256 DWRITE_GLYPH_METRICS metrics
;
7257 DWRITE_GLYPH_OFFSET offset
;
7258 IDWriteFontFace
*fontface
;
7259 IDWriteFactory
*factory
;
7260 DWRITE_GLYPH_RUN run
;
7269 factory
= create_factory();
7270 fontface
= create_fontface(factory
);
7274 hr
= IDWriteFontFace_GetGlyphIndices(fontface
, &ch
, 1, &glyph
);
7275 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7276 ok(glyph
> 0, "got %u\n", glyph
);
7278 hr
= IDWriteFontFace_GetDesignGlyphMetrics(fontface
, &glyph
, 1, &metrics
, FALSE
);
7279 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7280 advance
= metrics
.advanceWidth
;
7282 offset
.advanceOffset
= 0.0;
7283 offset
.ascenderOffset
= 0.0;
7285 run
.fontFace
= fontface
;
7286 run
.fontEmSize
= 24.0;
7288 run
.glyphIndices
= &glyph
;
7289 run
.glyphAdvances
= &advance
;
7290 run
.glyphOffsets
= &offset
;
7291 run
.isSideways
= FALSE
;
7294 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 1.0, NULL
,
7295 DWRITE_RENDERING_MODE_NATURAL
, DWRITE_MEASURING_MODE_NATURAL
,
7296 0.0, 0.0, &analysis
);
7297 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7299 SetRectEmpty(&bounds
);
7300 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_CLEARTYPE_3x1
, &bounds
);
7301 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7302 ok(!IsRectEmpty(&bounds
), "got empty rect\n");
7303 size
= (bounds
.right
- bounds
.left
)*(bounds
.bottom
- bounds
.top
)*3;
7304 ok(sizeof(buff
) >= size
, "required %u\n", size
);
7306 /* invalid type value */
7307 memset(buff
, 0xcf, sizeof(buff
));
7308 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_CLEARTYPE_3x1
+1, &bounds
, buff
, sizeof(buff
));
7309 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
7310 ok(buff
[0] == 0xcf, "got %1x\n", buff
[0]);
7312 memset(buff
, 0xcf, sizeof(buff
));
7313 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &bounds
, buff
, 2);
7314 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
7315 ok(buff
[0] == 0xcf, "got %1x\n", buff
[0]);
7317 /* vista version allows texture type mismatch, mark it broken for now */
7318 memset(buff
, 0xcf, sizeof(buff
));
7319 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &bounds
, buff
, sizeof(buff
));
7320 ok(hr
== DWRITE_E_UNSUPPORTEDOPERATION
|| broken(hr
== S_OK
), "got 0x%08x\n", hr
);
7321 ok(buff
[0] == 0xcf || broken(buff
[0] == 0), "got %1x\n", buff
[0]);
7323 memset(buff
, 0xcf, sizeof(buff
));
7324 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_CLEARTYPE_3x1
, &bounds
, buff
, size
-1);
7325 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
7326 ok(buff
[0] == 0xcf, "got %1x\n", buff
[0]);
7328 IDWriteGlyphRunAnalysis_Release(analysis
);
7330 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 1.0, NULL
,
7331 DWRITE_RENDERING_MODE_ALIASED
, DWRITE_MEASURING_MODE_GDI_CLASSIC
,
7332 0.0, 0.0, &analysis
);
7333 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7335 SetRectEmpty(&bounds
);
7336 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &bounds
);
7337 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7338 ok(!IsRectEmpty(&bounds
), "got empty rect\n");
7339 size
= (bounds
.right
- bounds
.left
)*(bounds
.bottom
- bounds
.top
);
7340 ok(sizeof(buff
) >= size
, "required %u\n", size
);
7342 memset(buff
, 0xcf, sizeof(buff
));
7343 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, NULL
, buff
, sizeof(buff
));
7344 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
7345 ok(buff
[0] == 0xcf, "got %1x\n", buff
[0]);
7347 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, NULL
, NULL
, sizeof(buff
));
7348 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
7350 memset(buff
, 0xcf, sizeof(buff
));
7351 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, NULL
, buff
, 0);
7352 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
7353 ok(buff
[0] == 0xcf, "got %1x\n", buff
[0]);
7355 /* buffer size is not enough */
7356 memset(buff
, 0xcf, sizeof(buff
));
7357 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &bounds
, buff
, size
-1);
7358 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
7359 ok(buff
[0] == 0xcf, "got %1x\n", buff
[0]);
7361 /* request texture for rectangle that doesn't intersect */
7362 memset(buff
, 0xcf, sizeof(buff
));
7364 OffsetRect(&r
, (bounds
.right
- bounds
.left
)*2, 0);
7365 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &r
, buff
, sizeof(buff
));
7366 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7367 ok(buff
[0] == 0, "got %1x\n", buff
[0]);
7369 memset(buff
, 0xcf, sizeof(buff
));
7371 OffsetRect(&r
, (bounds
.right
- bounds
.left
)*2, 0);
7372 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &r
, buff
, sizeof(buff
));
7373 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7374 ok(buff
[0] == 0, "got %1x\n", buff
[0]);
7376 /* request texture for rectangle that doesn't intersect, small buffer */
7377 memset(buff
, 0xcf, sizeof(buff
));
7379 OffsetRect(&r
, (bounds
.right
- bounds
.left
)*2, 0);
7380 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &r
, buff
, size
-1);
7381 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
7382 ok(buff
[0] == 0xcf, "got %1x\n", buff
[0]);
7384 /* vista version allows texture type mismatch, mark it broken for now */
7385 memset(buff
, 0xcf, sizeof(buff
));
7386 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_CLEARTYPE_3x1
, &bounds
, buff
, sizeof(buff
));
7387 ok(hr
== DWRITE_E_UNSUPPORTEDOPERATION
|| broken(hr
== S_OK
), "got 0x%08x\n", hr
);
7388 ok(buff
[0] == 0xcf || broken(buff
[0] == 0), "got %1x\n", buff
[0]);
7390 IDWriteGlyphRunAnalysis_Release(analysis
);
7391 IDWriteFontFace_Release(fontface
);
7392 ref
= IDWriteFactory_Release(factory
);
7393 ok(ref
== 0, "factory not released, %u\n", ref
);
7396 static BOOL
get_expected_is_symbol(IDWriteFontFace
*fontface
)
7398 BOOL exists
, is_symbol
= FALSE
;
7399 struct dwrite_fonttable cmap
;
7400 const TT_OS2_V2
*tt_os2
;
7408 hr
= IDWriteFontFace_TryGetFontTable(fontface
, MS_OS2_TAG
, (const void **)&tt_os2
, &size
, &os2_context
, &exists
);
7409 ok(hr
== S_OK
, "Failed to get OS/2 table, hr %#x.\n", hr
);
7413 is_symbol
= tt_os2
->panose
.bFamilyType
== PAN_FAMILY_PICTORIAL
;
7414 IDWriteFontFace_ReleaseFontTable(fontface
, os2_context
);
7420 hr
= IDWriteFontFace_TryGetFontTable(fontface
, MS_CMAP_TAG
, (const void **)&cmap
.data
,
7421 &cmap
.size
, &cmap
.context
, &exists
);
7422 if (FAILED(hr
) || !exists
)
7425 num_tables
= table_read_be_word(&cmap
, 0, FIELD_OFFSET(struct cmap_header
, num_tables
));
7426 tables
= cmap
.data
+ FIELD_OFFSET(struct cmap_header
, tables
);
7428 for (i
= 0; i
< num_tables
; ++i
)
7430 struct cmap_encoding_record
*record
= (struct cmap_encoding_record
*)(tables
+ i
* sizeof(*record
));
7431 WORD platform
, encoding
;
7433 platform
= table_read_be_word(&cmap
, record
, FIELD_OFFSET(struct cmap_encoding_record
, platformID
));
7434 encoding
= table_read_be_word(&cmap
, record
, FIELD_OFFSET(struct cmap_encoding_record
, encodingID
));
7436 if (platform
== OPENTYPE_CMAP_TABLE_PLATFORM_WIN
&& encoding
== OPENTYPE_CMAP_TABLE_ENCODING_SYMBOL
)
7443 IDWriteFontFace_ReleaseFontTable(fontface
, cmap
.context
);
7448 static void test_IsSymbolFont(void)
7450 IDWriteFontCollection
*collection
;
7451 IDWriteFontFace
*fontface
;
7452 IDWriteFactory
*factory
;
7458 factory
= create_factory();
7460 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &collection
, FALSE
);
7461 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7463 count
= IDWriteFontCollection_GetFontFamilyCount(collection
);
7464 for (i
= 0; i
< count
; ++i
)
7466 IDWriteLocalizedStrings
*names
;
7467 IDWriteFontFamily
*family
;
7468 UINT32 font_count
, j
;
7471 hr
= IDWriteFontCollection_GetFontFamily(collection
, i
, &family
);
7472 ok(hr
== S_OK
, "Failed to get family, hr %#x.\n", hr
);
7474 hr
= IDWriteFontFamily_GetFamilyNames(family
, &names
);
7475 ok(hr
== S_OK
, "Failed to get names, hr %#x.\n", hr
);
7476 get_enus_string(names
, nameW
, ARRAY_SIZE(nameW
));
7477 IDWriteLocalizedStrings_Release(names
);
7479 font_count
= IDWriteFontFamily_GetFontCount(family
);
7481 for (j
= 0; j
< font_count
; ++j
)
7483 BOOL is_symbol_font
, is_symbol_face
, is_symbol_expected
;
7485 hr
= IDWriteFontFamily_GetFont(family
, j
, &font
);
7486 ok(hr
== S_OK
, "Failed to get font, hr %#x.\n", hr
);
7488 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
7489 ok(hr
== S_OK
, "Failed to create fontface, hr %#x.\n", hr
);
7491 is_symbol_font
= IDWriteFont_IsSymbolFont(font
);
7492 is_symbol_face
= IDWriteFontFace_IsSymbolFont(fontface
);
7493 ok(is_symbol_font
== is_symbol_face
, "Unexpected symbol flag.\n");
7495 is_symbol_expected
= get_expected_is_symbol(fontface
);
7496 ok(is_symbol_expected
== is_symbol_face
, "Unexpected is_symbol flag %d for %s, font %d.\n",
7497 is_symbol_face
, wine_dbgstr_w(nameW
), j
);
7499 IDWriteFontFace_Release(fontface
);
7500 IDWriteFont_Release(font
);
7503 IDWriteFontFamily_Release(family
);
7506 IDWriteFontCollection_Release(collection
);
7508 ref
= IDWriteFactory_Release(factory
);
7509 ok(ref
== 0, "factory not released, %u\n", ref
);
7512 struct CPAL_Header_0
7515 USHORT numPaletteEntries
;
7517 USHORT numColorRecords
;
7518 ULONG offsetFirstColorRecord
;
7519 USHORT colorRecordIndices
[1];
7522 static void test_GetPaletteEntries(void)
7524 IDWriteFontFace2
*fontface2
;
7525 IDWriteFontFace
*fontface
;
7526 IDWriteFactory
*factory
;
7528 DWRITE_COLOR_F color
;
7529 UINT32 palettecount
, entrycount
, size
, colorrecords
;
7531 const struct CPAL_Header_0
*cpal_header
;
7536 factory
= create_factory();
7538 /* Tahoma, no color support */
7539 fontface
= create_fontface(factory
);
7540 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace2
, (void**)&fontface2
);
7541 IDWriteFontFace_Release(fontface
);
7543 ref
= IDWriteFactory_Release(factory
);
7544 ok(ref
== 0, "factory not released, %u\n", ref
);
7545 win_skip("GetPaletteEntries() is not supported.\n");
7549 hr
= IDWriteFontFace2_GetPaletteEntries(fontface2
, 0, 0, 1, &color
);
7550 ok(hr
== DWRITE_E_NOCOLOR
, "got 0x%08x\n", hr
);
7551 IDWriteFontFace2_Release(fontface2
);
7553 /* Segoe UI Emoji, with color support */
7554 font
= get_font(factory
, L
"Segoe UI Emoji", DWRITE_FONT_STYLE_NORMAL
);
7556 ref
= IDWriteFactory_Release(factory
);
7557 ok(ref
== 0, "factory not released, %u\n", ref
);
7558 skip("Segoe UI Emoji font not found.\n");
7562 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
7563 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7564 IDWriteFont_Release(font
);
7566 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace2
, (void**)&fontface2
);
7567 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7568 IDWriteFontFace_Release(fontface
);
7570 palettecount
= IDWriteFontFace2_GetColorPaletteCount(fontface2
);
7571 ok(palettecount
>= 1, "got %u\n", palettecount
);
7573 entrycount
= IDWriteFontFace2_GetPaletteEntryCount(fontface2
);
7574 ok(entrycount
>= 1, "got %u\n", entrycount
);
7577 hr
= IDWriteFontFace2_TryGetFontTable(fontface2
, MS_CPAL_TAG
, (const void**)&cpal_header
, &size
, &ctxt
, &exists
);
7578 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7579 ok(exists
, "got %d\n", exists
);
7580 colorrecords
= GET_BE_WORD(cpal_header
->numColorRecords
);
7581 ok(colorrecords
>= 1, "got %u\n", colorrecords
);
7583 /* invalid palette index */
7584 color
.r
= color
.g
= color
.b
= color
.a
= 123.0;
7585 hr
= IDWriteFontFace2_GetPaletteEntries(fontface2
, palettecount
, 0, 1, &color
);
7586 ok(hr
== DWRITE_E_NOCOLOR
, "got 0x%08x\n", hr
);
7587 ok(color
.r
== 123.0 && color
.g
== 123.0 && color
.b
== 123.0 && color
.a
== 123.0,
7588 "got wrong color %.2fx%.2fx%.2fx%.2f\n", color
.r
, color
.g
, color
.b
, color
.a
);
7590 /* invalid entry index */
7591 color
.r
= color
.g
= color
.b
= color
.a
= 123.0;
7592 hr
= IDWriteFontFace2_GetPaletteEntries(fontface2
, 0, entrycount
, 1, &color
);
7593 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
7594 ok(color
.r
== 123.0 && color
.g
== 123.0 && color
.b
== 123.0 && color
.a
== 123.0,
7595 "got wrong color %.2fx%.2fx%.2fx%.2f\n", color
.r
, color
.g
, color
.b
, color
.a
);
7597 color
.r
= color
.g
= color
.b
= color
.a
= 123.0;
7598 hr
= IDWriteFontFace2_GetPaletteEntries(fontface2
, 0, entrycount
- 1, 1, &color
);
7599 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7600 ok(color
.r
!= 123.0 && color
.g
!= 123.0 && color
.b
!= 123.0 && color
.a
!= 123.0,
7601 "got wrong color %.2fx%.2fx%.2fx%.2f\n", color
.r
, color
.g
, color
.b
, color
.a
);
7603 /* zero return length */
7604 color
.r
= color
.g
= color
.b
= color
.a
= 123.0;
7605 hr
= IDWriteFontFace2_GetPaletteEntries(fontface2
, 0, 0, 0, &color
);
7606 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7607 ok(color
.r
== 123.0 && color
.g
== 123.0 && color
.b
== 123.0 && color
.a
== 123.0,
7608 "got wrong color %.2fx%.2fx%.2fx%.2f\n", color
.r
, color
.g
, color
.b
, color
.a
);
7610 IDWriteFontFace2_Release(fontface2
);
7611 ref
= IDWriteFactory_Release(factory
);
7612 ok(ref
== 0, "factory not released, %u\n", ref
);
7615 static void test_TranslateColorGlyphRun(void)
7617 IDWriteColorGlyphRunEnumerator1
*layers1
;
7618 IDWriteColorGlyphRunEnumerator
*layers
;
7619 const DWRITE_COLOR_GLYPH_RUN1
*colorrun1
;
7620 const DWRITE_COLOR_GLYPH_RUN
*colorrun
;
7621 IDWriteFontFace2
*fontface2
;
7622 IDWriteFontFace
*fontface
;
7623 IDWriteFactory2
*factory
;
7624 DWRITE_GLYPH_RUN run
;
7625 UINT32 codepoints
[2];
7632 factory
= create_factory_iid(&IID_IDWriteFactory2
);
7634 win_skip("TranslateColorGlyphRun() is not supported.\n");
7638 /* Tahoma, no color support */
7639 fontface
= create_fontface((IDWriteFactory
*)factory
);
7641 codepoints
[0] = 'A';
7642 hr
= IDWriteFontFace_GetGlyphIndices(fontface
, codepoints
, 1, glyphs
);
7643 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7645 run
.fontFace
= fontface
;
7646 run
.fontEmSize
= 20.0f
;
7648 run
.glyphIndices
= glyphs
;
7649 run
.glyphAdvances
= NULL
;
7650 run
.glyphOffsets
= NULL
;
7651 run
.isSideways
= FALSE
;
7654 layers
= (void*)0xdeadbeef;
7655 hr
= IDWriteFactory2_TranslateColorGlyphRun(factory
, 0.0f
, 0.0f
, &run
, NULL
,
7656 DWRITE_MEASURING_MODE_NATURAL
, NULL
, 0, &layers
);
7657 ok(hr
== DWRITE_E_NOCOLOR
, "got 0x%08x\n", hr
);
7658 ok(layers
== NULL
, "got %p\n", layers
);
7659 IDWriteFontFace_Release(fontface
);
7661 /* Segoe UI Emoji, with color support */
7662 font
= get_font((IDWriteFactory
*)factory
, L
"Segoe UI Emoji", DWRITE_FONT_STYLE_NORMAL
);
7664 IDWriteFactory2_Release(factory
);
7665 skip("Segoe UI Emoji font not found.\n");
7669 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
7670 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7671 IDWriteFont_Release(font
);
7673 codepoints
[0] = 0x26c4;
7674 hr
= IDWriteFontFace_GetGlyphIndices(fontface
, codepoints
, 1, glyphs
);
7675 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7677 run
.fontFace
= fontface
;
7680 hr
= IDWriteFactory2_TranslateColorGlyphRun(factory
, 0.0f
, 0.0f
, &run
, NULL
,
7681 DWRITE_MEASURING_MODE_NATURAL
, NULL
, 0, &layers
);
7682 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7683 ok(layers
!= NULL
, "got %p\n", layers
);
7685 hr
= IDWriteColorGlyphRunEnumerator_QueryInterface(layers
, &IID_IDWriteColorGlyphRunEnumerator1
, (void **)&layers1
);
7689 win_skip("IDWriteColorGlyphRunEnumerator1 is not supported.\n");
7694 hr
= IDWriteColorGlyphRunEnumerator_MoveNext(layers
, &hasrun
);
7695 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7700 hr
= IDWriteColorGlyphRunEnumerator_GetCurrentRun(layers
, &colorrun
);
7701 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7702 ok(colorrun
->glyphRun
.fontFace
!= NULL
, "got fontface %p\n", colorrun
->glyphRun
.fontFace
);
7703 ok(colorrun
->glyphRun
.fontEmSize
== 20.0f
, "got wrong font size %f\n", colorrun
->glyphRun
.fontEmSize
);
7704 ok(colorrun
->glyphRun
.glyphCount
> 0, "got wrong glyph count %u\n", colorrun
->glyphRun
.glyphCount
);
7705 ok(colorrun
->glyphRun
.glyphIndices
!= NULL
, "got null glyph indices %p\n", colorrun
->glyphRun
.glyphIndices
);
7706 ok(colorrun
->glyphRun
.glyphAdvances
!= NULL
, "got null glyph advances %p\n", colorrun
->glyphRun
.glyphAdvances
);
7710 hr
= IDWriteColorGlyphRunEnumerator1_GetCurrentRun(layers1
, &colorrun1
);
7711 ok(hr
== S_OK
, "Failed to get color runt, hr %#x.\n", hr
);
7712 ok(colorrun1
->glyphRun
.fontFace
!= NULL
, "Unexpected fontface %p.\n", colorrun1
->glyphRun
.fontFace
);
7713 ok(colorrun1
->glyphRun
.fontEmSize
== 20.0f
, "Unexpected font size %f.\n", colorrun1
->glyphRun
.fontEmSize
);
7714 ok(colorrun1
->glyphRun
.glyphCount
> 0, "Unexpected glyph count %u\n", colorrun1
->glyphRun
.glyphCount
);
7715 ok(colorrun1
->glyphRun
.glyphIndices
!= NULL
, "Unexpected indices array.\n");
7716 ok(colorrun1
->glyphRun
.glyphAdvances
!= NULL
, "Unexpected advances array.\n");
7720 /* iterated all way through */
7721 hr
= IDWriteColorGlyphRunEnumerator_GetCurrentRun(layers
, &colorrun
);
7722 ok(hr
== E_NOT_VALID_STATE
, "got 0x%08x\n", hr
);
7726 hr
= IDWriteColorGlyphRunEnumerator1_GetCurrentRun(layers1
, &colorrun1
);
7727 ok(hr
== E_NOT_VALID_STATE
, "Unexpected hr %#x.\n", hr
);
7730 IDWriteColorGlyphRunEnumerator_Release(layers
);
7732 IDWriteColorGlyphRunEnumerator1_Release(layers1
);
7734 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace2
, (void**)&fontface2
);
7735 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7737 /* invalid palette index */
7738 layers
= (void*)0xdeadbeef;
7739 hr
= IDWriteFactory2_TranslateColorGlyphRun(factory
, 0.0f
, 0.0f
, &run
, NULL
,
7740 DWRITE_MEASURING_MODE_NATURAL
, NULL
, IDWriteFontFace2_GetColorPaletteCount(fontface2
),
7742 ok(hr
== DWRITE_E_NOCOLOR
, "got 0x%08x\n", hr
);
7743 ok(layers
== NULL
, "got %p\n", layers
);
7746 hr
= IDWriteFactory2_TranslateColorGlyphRun(factory
, 0.0f
, 0.0f
, &run
, NULL
,
7747 DWRITE_MEASURING_MODE_NATURAL
, NULL
, IDWriteFontFace2_GetColorPaletteCount(fontface2
) - 1,
7749 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7750 IDWriteColorGlyphRunEnumerator_Release(layers
);
7752 /* color font, glyph without color info */
7753 codepoints
[0] = 'A';
7754 hr
= IDWriteFontFace_GetGlyphIndices(fontface
, codepoints
, 1, glyphs
);
7755 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7757 layers
= (void*)0xdeadbeef;
7758 hr
= IDWriteFactory2_TranslateColorGlyphRun(factory
, 0.0f
, 0.0f
, &run
, NULL
,
7759 DWRITE_MEASURING_MODE_NATURAL
, NULL
, 0, &layers
);
7760 ok(hr
== DWRITE_E_NOCOLOR
, "got 0x%08x\n", hr
);
7761 ok(layers
== NULL
, "got %p\n", layers
);
7763 /* one glyph with, one without */
7764 codepoints
[0] = 'A';
7765 codepoints
[1] = 0x26c4;
7767 hr
= IDWriteFontFace_GetGlyphIndices(fontface
, codepoints
, 2, glyphs
);
7768 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7773 hr
= IDWriteFactory2_TranslateColorGlyphRun(factory
, 0.0f
, 0.0f
, &run
, NULL
,
7774 DWRITE_MEASURING_MODE_NATURAL
, NULL
, 0, &layers
);
7775 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7776 ok(layers
!= NULL
, "got %p\n", layers
);
7777 IDWriteColorGlyphRunEnumerator_Release(layers
);
7779 IDWriteFontFace2_Release(fontface2
);
7780 IDWriteFontFace_Release(fontface
);
7781 ref
= IDWriteFactory2_Release(factory
);
7782 ok(ref
== 0, "factory not released, %u\n", ref
);
7785 static void test_HasCharacter(void)
7787 IDWriteFactory3
*factory3
;
7788 IDWriteFactory
*factory
;
7789 IDWriteFont3
*font3
;
7795 factory
= create_factory();
7797 font
= get_tahoma_instance(factory
, DWRITE_FONT_STYLE_NORMAL
);
7798 ok(font
!= NULL
, "failed to create font\n");
7800 /* Win8 is broken, QI claims to support IDWriteFont3, but in fact it does not */
7801 hr
= IDWriteFactory_QueryInterface(factory
, &IID_IDWriteFactory3
, (void**)&factory3
);
7803 hr
= IDWriteFont_QueryInterface(font
, &IID_IDWriteFont3
, (void**)&font3
);
7804 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7806 ret
= IDWriteFont3_HasCharacter(font3
, 'A');
7807 ok(ret
, "got %d\n", ret
);
7809 IDWriteFont3_Release(font3
);
7810 IDWriteFactory3_Release(factory3
);
7813 win_skip("IDWriteFont3 is not supported.\n");
7815 IDWriteFont_Release(font
);
7816 ref
= IDWriteFactory_Release(factory
);
7817 ok(ref
== 0, "factory not released, %u\n", ref
);
7820 static void test_CreateFontFaceReference(void)
7822 IDWriteFontFaceReference
*ref
, *ref1
, *ref3
;
7823 IDWriteFontFace3
*fontface
, *fontface1
;
7824 IDWriteFontCollection1
*collection
;
7825 IDWriteFontFile
*file
, *file1
;
7826 IDWriteFactory3
*factory
;
7827 UINT32 index
, count
, i
;
7828 IDWriteFont3
*font3
;
7834 factory
= create_factory_iid(&IID_IDWriteFactory3
);
7836 win_skip("CreateFontFaceReference() is not supported.\n");
7840 path
= create_testfontfile(test_fontfile
);
7842 hr
= IDWriteFactory3_CreateFontFaceReference(factory
, NULL
, NULL
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &ref
);
7843 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
7845 /* out of range simulation flags */
7846 hr
= IDWriteFactory3_CreateFontFaceReference(factory
, path
, NULL
, 0, ~0u, &ref
);
7847 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
7849 /* test file is not a collection, but reference could still be created with non-zero face index */
7850 hr
= IDWriteFactory3_CreateFontFaceReference(factory
, path
, NULL
, 1, DWRITE_FONT_SIMULATIONS_NONE
, &ref
);
7851 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7853 index
= IDWriteFontFaceReference_GetFontFaceIndex(ref
);
7854 ok(index
== 1, "got %u\n", index
);
7856 hr
= IDWriteFontFaceReference_GetFontFile(ref
, &file
);
7857 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7858 IDWriteFontFile_Release(file
);
7860 hr
= IDWriteFontFaceReference_CreateFontFace(ref
, &fontface
);
7862 ok(hr
== DWRITE_E_FILEFORMAT
, "got 0x%08x\n", hr
);
7864 IDWriteFontFaceReference_Release(ref
);
7866 /* path however has to be valid */
7867 hr
= IDWriteFactory3_CreateFontFaceReference(factory
, L
"dummy", NULL
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &ref
);
7869 ok(hr
== DWRITE_E_FILENOTFOUND
, "got 0x%08x\n", hr
);
7871 IDWriteFontFaceReference_Release(ref
);
7873 EXPECT_REF(factory
, 1);
7874 hr
= IDWriteFactory3_CreateFontFaceReference(factory
, path
, NULL
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &ref
);
7875 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7876 EXPECT_REF(factory
, 2);
7878 /* new file is returned */
7879 hr
= IDWriteFontFaceReference_GetFontFile(ref
, &file
);
7880 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7882 hr
= IDWriteFontFaceReference_GetFontFile(ref
, &file1
);
7883 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7884 ok(file
!= file1
, "got %p, previous file %p\n", file1
, file
);
7886 IDWriteFontFile_Release(file
);
7887 IDWriteFontFile_Release(file1
);
7889 /* references are not reused */
7890 hr
= IDWriteFactory3_CreateFontFaceReference(factory
, path
, NULL
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &ref1
);
7891 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7892 ok(ref1
!= ref
, "got %p, previous ref %p\n", ref1
, ref
);
7894 /* created fontfaces are cached */
7895 hr
= IDWriteFontFaceReference_CreateFontFace(ref
, &fontface
);
7896 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7898 hr
= IDWriteFontFaceReference_CreateFontFace(ref1
, &fontface1
);
7899 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7900 ok(fontface
== fontface1
, "got %p, expected %p\n", fontface1
, fontface
);
7901 IDWriteFontFace3_Release(fontface
);
7902 IDWriteFontFace3_Release(fontface1
);
7904 /* reference equality */
7905 ret
= IDWriteFontFaceReference_Equals(ref
, ref1
);
7906 ok(ret
, "got %d\n", ret
);
7907 IDWriteFontFaceReference_Release(ref1
);
7909 hr
= IDWriteFactory3_CreateFontFaceReference(factory
, path
, NULL
, 1, DWRITE_FONT_SIMULATIONS_NONE
, &ref1
);
7910 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7911 ret
= IDWriteFontFaceReference_Equals(ref
, ref1
);
7912 ok(!ret
, "got %d\n", ret
);
7913 IDWriteFontFaceReference_Release(ref1
);
7915 hr
= IDWriteFactory3_CreateFontFaceReference(factory
, path
, NULL
, 0, DWRITE_FONT_SIMULATIONS_BOLD
, &ref1
);
7916 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7917 ret
= IDWriteFontFaceReference_Equals(ref
, ref1
);
7918 ok(!ret
, "got %d\n", ret
);
7919 IDWriteFontFaceReference_Release(ref1
);
7921 IDWriteFontFaceReference_Release(ref
);
7923 /* create reference from a file */
7924 hr
= IDWriteFactory3_CreateFontFileReference(factory
, path
, NULL
, &file
);
7925 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7927 hr
= IDWriteFactory3_CreateFontFaceReference_(factory
, file
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &ref
);
7928 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7930 hr
= IDWriteFontFaceReference_GetFontFile(ref
, &file1
);
7931 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7932 ok(file
!= file1
, "got %p, previous file %p\n", file1
, file
);
7934 IDWriteFontFaceReference_Release(ref
);
7935 IDWriteFontFile_Release(file
);
7936 IDWriteFontFile_Release(file1
);
7938 /* References returned from IDWriteFont3/IDWriteFontFace3. */
7939 hr
= IDWriteFactory3_GetSystemFontCollection(factory
, FALSE
, &collection
, FALSE
);
7940 ok(hr
== S_OK
, "Failed to get system collection, hr %#x.\n", hr
);
7942 count
= IDWriteFontCollection1_GetFontFamilyCount(collection
);
7943 for (i
= 0; i
< count
; i
++)
7945 IDWriteFontFamily1
*family
;
7946 UINT32 font_count
, j
;
7948 hr
= IDWriteFontCollection1_GetFontFamily(collection
, i
, &family
);
7949 ok(hr
== S_OK
, "Failed to get family, hr %#x.\n", hr
);
7951 font_count
= IDWriteFontFamily1_GetFontCount(family
);
7953 for (j
= 0; j
< font_count
; j
++)
7955 IDWriteFontFaceReference1
*ref2
;
7957 hr
= IDWriteFontFamily1_GetFont(family
, j
, &font3
);
7958 ok(hr
== S_OK
, "Failed to get font, hr %#x.\n", hr
);
7960 hr
= IDWriteFont3_GetFontFaceReference(font3
, &ref
);
7961 ok(hr
== S_OK
, "Failed to get reference object, hr %#x.\n", hr
);
7963 hr
= IDWriteFont3_GetFontFaceReference(font3
, &ref1
);
7964 ok(hr
== S_OK
, "Failed to get reference object, hr %#x.\n", hr
);
7965 ok(ref
!= ref1
, "Unexpected reference object %p, %p.\n", ref1
, ref
);
7967 hr
= IDWriteFont3_CreateFontFace(font3
, &fontface
);
7968 ok(hr
== S_OK
, "Failed to create a fontface, hr %#x.\n", hr
);
7970 /* Fonts present regular properties as axis values, for non-variable fonts too.
7971 Normally it would include weight/width/slant/italic, but could also contain optical size axis. */
7972 if (SUCCEEDED(hr
= IDWriteFontFaceReference_QueryInterface(ref
, &IID_IDWriteFontFaceReference1
,
7975 UINT32 axis_count
= IDWriteFontFaceReference1_GetFontAxisValueCount(ref2
);
7976 ok(axis_count
> 0, "Unexpected axis value count.\n");
7977 IDWriteFontFaceReference1_Release(ref2
);
7980 IDWriteFontFaceReference_Release(ref
);
7981 IDWriteFontFaceReference_Release(ref1
);
7983 hr
= IDWriteFontFace3_GetFontFaceReference(fontface
, &ref
);
7984 ok(hr
== S_OK
, "Failed to get a reference, hr %#x.\n", hr
);
7985 EXPECT_REF(fontface
, 2);
7987 hr
= IDWriteFontFace3_GetFontFaceReference(fontface
, &ref1
);
7988 ok(hr
== S_OK
, "Failed to get a reference, hr %#x.\n", hr
);
7989 ok(ref
== ref1
, "Unexpected reference %p, %p.\n", ref1
, ref
);
7990 EXPECT_REF(fontface
, 3);
7992 hr
= IDWriteFontFace3_QueryInterface(fontface
, &IID_IDWriteFontFaceReference
, (void **)&ref3
);
7993 ok(hr
== S_OK
|| broken(FAILED(hr
)), "Failed to get interface, hr %#x.\n", hr
);
7996 ok(ref
== ref3
, "Unexpected reference %p.\n", ref3
);
7997 IDWriteFontFaceReference_Release(ref3
);
8000 hr
= IDWriteFontFaceReference_CreateFontFace(ref
, &fontface1
);
8001 ok(hr
== S_OK
, "Failed to create fontface, hr %#x.\n", hr
);
8002 ok(fontface1
== fontface
, "Unexpected fontface %p, %p.\n", fontface1
, fontface
);
8003 IDWriteFontFace3_Release(fontface1
);
8005 IDWriteFontFaceReference_Release(ref
);
8006 IDWriteFontFaceReference_Release(ref1
);
8008 IDWriteFontFace3_Release(fontface
);
8009 IDWriteFont3_Release(font3
);
8012 IDWriteFontFamily1_Release(family
);
8014 IDWriteFontCollection1_Release(collection
);
8016 refcount
= IDWriteFactory3_Release(factory
);
8017 ok(refcount
== 0, "factory not released, %u\n", refcount
);
8018 DELETE_FONTFILE(path
);
8021 static void get_expected_fontsig(IDWriteFont
*font
, FONTSIGNATURE
*fontsig
)
8024 IDWriteFontFace
*fontface
;
8025 const TT_OS2_V2
*tt_os2
;
8030 memset(fontsig
, 0, sizeof(*fontsig
));
8032 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
8033 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
8035 hr
= IDWriteFontFace_TryGetFontTable(fontface
, MS_OS2_TAG
, (const void **)&tt_os2
, &size
, &os2_context
, &exists
);
8036 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
8039 fontsig
->fsUsb
[0] = GET_BE_DWORD(tt_os2
->ulUnicodeRange1
);
8040 fontsig
->fsUsb
[1] = GET_BE_DWORD(tt_os2
->ulUnicodeRange2
);
8041 fontsig
->fsUsb
[2] = GET_BE_DWORD(tt_os2
->ulUnicodeRange3
);
8042 fontsig
->fsUsb
[3] = GET_BE_DWORD(tt_os2
->ulUnicodeRange4
);
8044 if (GET_BE_WORD(tt_os2
->version
) == 0) {
8045 fontsig
->fsCsb
[0] = 0;
8046 fontsig
->fsCsb
[1] = 0;
8049 fontsig
->fsCsb
[0] = GET_BE_DWORD(tt_os2
->ulCodePageRange1
);
8050 fontsig
->fsCsb
[1] = GET_BE_DWORD(tt_os2
->ulCodePageRange2
);
8053 IDWriteFontFace_ReleaseFontTable(fontface
, os2_context
);
8056 IDWriteFontFace_Release(fontface
);
8059 static void test_GetFontSignature(void)
8061 IDWriteFontCollection
*syscollection
;
8062 IDWriteGdiInterop1
*interop1
;
8063 IDWriteGdiInterop
*interop
;
8064 IDWriteFactory
*factory
;
8065 FONTSIGNATURE fontsig
;
8070 factory
= create_factory();
8072 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop
);
8073 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
8075 hr
= IDWriteGdiInterop_QueryInterface(interop
, &IID_IDWriteGdiInterop1
, (void**)&interop1
);
8076 IDWriteGdiInterop_Release(interop
);
8078 win_skip("GetFontSignature() is not supported.\n");
8079 IDWriteGdiInterop_Release(interop
);
8080 IDWriteFactory_Release(factory
);
8083 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
8085 hr
= IDWriteGdiInterop1_GetFontSignature(interop1
, NULL
, &fontsig
);
8086 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
8088 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &syscollection
, FALSE
);
8089 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
8090 count
= IDWriteFontCollection_GetFontFamilyCount(syscollection
);
8092 for (i
= 0; i
< count
; i
++) {
8093 FONTSIGNATURE expected_signature
;
8094 IDWriteLocalizedStrings
*names
;
8095 IDWriteFontFamily
*family
;
8099 hr
= IDWriteFontCollection_GetFontFamily(syscollection
, i
, &family
);
8100 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
8102 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STRETCH_NORMAL
,
8103 DWRITE_FONT_STYLE_NORMAL
, &font
);
8104 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
8106 hr
= IDWriteFontFamily_GetFamilyNames(family
, &names
);
8107 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
8109 get_enus_string(names
, nameW
, ARRAY_SIZE(nameW
));
8111 IDWriteLocalizedStrings_Release(names
);
8113 hr
= IDWriteGdiInterop1_GetFontSignature(interop1
, font
, &fontsig
);
8114 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
8116 get_expected_fontsig(font
, &expected_signature
);
8118 ok(fontsig
.fsUsb
[0] == expected_signature
.fsUsb
[0], "%s: fsUsb[0] %#x, expected %#x\n", wine_dbgstr_w(nameW
),
8119 fontsig
.fsUsb
[0], expected_signature
.fsUsb
[0]);
8120 ok(fontsig
.fsUsb
[1] == expected_signature
.fsUsb
[1], "%s: fsUsb[1] %#x, expected %#x\n", wine_dbgstr_w(nameW
),
8121 fontsig
.fsUsb
[1], expected_signature
.fsUsb
[1]);
8122 ok(fontsig
.fsUsb
[2] == expected_signature
.fsUsb
[2], "%s: fsUsb[2] %#x, expected %#x\n", wine_dbgstr_w(nameW
),
8123 fontsig
.fsUsb
[2], expected_signature
.fsUsb
[2]);
8124 ok(fontsig
.fsUsb
[3] == expected_signature
.fsUsb
[3], "%s: fsUsb[3] %#x, expected %#x\n", wine_dbgstr_w(nameW
),
8125 fontsig
.fsUsb
[3], expected_signature
.fsUsb
[3]);
8127 ok(fontsig
.fsCsb
[0] == expected_signature
.fsCsb
[0], "%s: fsCsb[0] %#x, expected %#x\n", wine_dbgstr_w(nameW
),
8128 fontsig
.fsCsb
[0], expected_signature
.fsCsb
[0]);
8129 ok(fontsig
.fsCsb
[1] == expected_signature
.fsCsb
[1], "%s: fsCsb[1] %#x, expected %#x\n", wine_dbgstr_w(nameW
),
8130 fontsig
.fsCsb
[1], expected_signature
.fsCsb
[1]);
8132 IDWriteFont_Release(font
);
8133 IDWriteFontFamily_Release(family
);
8136 IDWriteGdiInterop1_Release(interop1
);
8137 IDWriteFontCollection_Release(syscollection
);
8138 ref
= IDWriteFactory_Release(factory
);
8139 ok(ref
== 0, "factory not released, %u\n", ref
);
8142 static void test_font_properties(void)
8144 IDWriteFontFace3
*fontface3
;
8145 IDWriteFontFace
*fontface
;
8146 IDWriteFactory
*factory
;
8147 DWRITE_FONT_STYLE style
;
8152 factory
= create_factory();
8154 /* this creates simulated font */
8155 font
= get_tahoma_instance(factory
, DWRITE_FONT_STYLE_ITALIC
);
8157 style
= IDWriteFont_GetStyle(font
);
8158 ok(style
== DWRITE_FONT_STYLE_OBLIQUE
, "got %u\n", style
);
8160 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
8161 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
8163 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace3
, (void**)&fontface3
);
8164 IDWriteFontFace_Release(fontface
);
8166 style
= IDWriteFontFace3_GetStyle(fontface3
);
8167 ok(style
== DWRITE_FONT_STYLE_OBLIQUE
, "got %u\n", style
);
8169 IDWriteFontFace3_Release(fontface3
);
8172 IDWriteFont_Release(font
);
8173 ref
= IDWriteFactory_Release(factory
);
8174 ok(ref
== 0, "factory not released, %u\n", ref
);
8177 static BOOL
has_vertical_glyph_variants(IDWriteFontFace1
*fontface
)
8179 const OT_FeatureList
*featurelist
;
8180 const OT_LookupList
*lookup_list
;
8181 BOOL exists
= FALSE
, ret
= FALSE
;
8182 const GSUB_Header
*header
;
8189 hr
= IDWriteFontFace1_TryGetFontTable(fontface
, MS_GSUB_TAG
, &data
, &size
, &context
, &exists
);
8190 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
8196 featurelist
= (OT_FeatureList
*)((BYTE
*)header
+ GET_BE_WORD(header
->FeatureList
));
8197 lookup_list
= (const OT_LookupList
*)((BYTE
*)header
+ GET_BE_WORD(header
->LookupList
));
8199 for (i
= 0; i
< GET_BE_WORD(featurelist
->FeatureCount
); i
++) {
8200 if (*(UINT32
*)featurelist
->FeatureRecord
[i
].FeatureTag
== DWRITE_FONT_FEATURE_TAG_VERTICAL_WRITING
) {
8201 const OT_Feature
*feature
= (const OT_Feature
*)((BYTE
*)featurelist
+ GET_BE_WORD(featurelist
->FeatureRecord
[i
].Feature
));
8202 UINT16 lookup_count
= GET_BE_WORD(feature
->LookupCount
), i
, index
, count
, type
;
8203 const GSUB_SingleSubstFormat2
*subst2
;
8204 const OT_LookupTable
*lookup_table
;
8207 if (lookup_count
== 0)
8210 for (i
= 0; i
< lookup_count
; i
++) {
8211 /* check if lookup is empty */
8212 index
= GET_BE_WORD(feature
->LookupListIndex
[i
]);
8213 lookup_table
= (const OT_LookupTable
*)((BYTE
*)lookup_list
+ GET_BE_WORD(lookup_list
->Lookup
[index
]));
8215 type
= GET_BE_WORD(lookup_table
->LookupType
);
8216 ok(type
== 1 || type
== 7, "got unexpected lookup type %u\n", type
);
8218 count
= GET_BE_WORD(lookup_table
->SubTableCount
);
8222 ok(count
> 0, "got unexpected subtable count %u\n", count
);
8224 offset
= GET_BE_WORD(lookup_table
->SubTable
[0]);
8226 const GSUB_ExtensionPosFormat1
*ext
= (const GSUB_ExtensionPosFormat1
*)((const BYTE
*)lookup_table
+ offset
);
8227 if (GET_BE_WORD(ext
->SubstFormat
) == 1)
8228 offset
+= GET_BE_DWORD(ext
->ExtensionOffset
);
8230 ok(0, "Unhandled Extension Substitution Format %u\n", GET_BE_WORD(ext
->SubstFormat
));
8233 subst2
= (const GSUB_SingleSubstFormat2
*)((BYTE
*)lookup_table
+ offset
);
8234 index
= GET_BE_WORD(subst2
->SubstFormat
);
8237 else if (index
== 2) {
8238 /* SimSun-ExtB has 0 glyph count for this substitution */
8239 if (GET_BE_WORD(subst2
->GlyphCount
) > 0)
8243 ok(0, "unknown Single Substitution Format, %u\n", index
);
8251 IDWriteFontFace1_ReleaseFontTable(fontface
, context
);
8256 static void test_HasVerticalGlyphVariants(void)
8258 IDWriteFontCollection
*syscollection
;
8259 IDWriteFontFace1
*fontface1
;
8260 IDWriteFontFace
*fontface
;
8261 IDWriteFactory
*factory
;
8266 factory
= create_factory();
8267 fontface
= create_fontface(factory
);
8269 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void**)&fontface1
);
8270 IDWriteFontFace_Release(fontface
);
8272 win_skip("HasVerticalGlyphVariants() is not supported.\n");
8273 IDWriteFactory_Release(factory
);
8276 IDWriteFontFace1_Release(fontface1
);
8278 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &syscollection
, FALSE
);
8279 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
8280 count
= IDWriteFontCollection_GetFontFamilyCount(syscollection
);
8282 for (i
= 0; i
< count
; i
++) {
8283 IDWriteLocalizedStrings
*names
;
8284 BOOL expected_vert
, has_vert
;
8285 IDWriteFontFamily
*family
;
8289 hr
= IDWriteFontCollection_GetFontFamily(syscollection
, i
, &family
);
8290 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
8292 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STRETCH_NORMAL
,
8293 DWRITE_FONT_STYLE_NORMAL
, &font
);
8294 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
8296 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
8297 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
8299 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void**)&fontface1
);
8300 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
8302 hr
= IDWriteFontFamily_GetFamilyNames(family
, &names
);
8303 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
8305 get_enus_string(names
, nameW
, ARRAY_SIZE(nameW
));
8307 expected_vert
= has_vertical_glyph_variants(fontface1
);
8308 has_vert
= IDWriteFontFace1_HasVerticalGlyphVariants(fontface1
);
8310 ok(expected_vert
== has_vert
, "%s: expected vertical feature %d, got %d\n",
8311 wine_dbgstr_w(nameW
), expected_vert
, has_vert
);
8313 IDWriteLocalizedStrings_Release(names
);
8314 IDWriteFont_Release(font
);
8316 IDWriteFontFace1_Release(fontface1
);
8317 IDWriteFontFace_Release(fontface
);
8318 IDWriteFontFamily_Release(family
);
8321 IDWriteFontCollection_Release(syscollection
);
8322 ref
= IDWriteFactory_Release(factory
);
8323 ok(ref
== 0, "factory not released, %u\n", ref
);
8326 static void test_HasKerningPairs(void)
8328 IDWriteFontCollection
*syscollection
;
8329 IDWriteFontFace1
*fontface1
;
8330 IDWriteFontFace
*fontface
;
8331 IDWriteFactory
*factory
;
8336 factory
= create_factory();
8337 fontface
= create_fontface(factory
);
8339 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void**)&fontface1
);
8340 IDWriteFontFace_Release(fontface
);
8342 win_skip("HasKerningPairs() is not supported.\n");
8343 IDWriteFactory_Release(factory
);
8346 IDWriteFontFace1_Release(fontface1
);
8348 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &syscollection
, FALSE
);
8349 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
8350 count
= IDWriteFontCollection_GetFontFamilyCount(syscollection
);
8352 for (i
= 0; i
< count
; i
++) {
8353 IDWriteLocalizedStrings
*names
;
8354 BOOL exists
, has_kerningpairs
;
8355 IDWriteFontFamily
*family
;
8362 hr
= IDWriteFontCollection_GetFontFamily(syscollection
, i
, &family
);
8363 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
8365 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STRETCH_NORMAL
,
8366 DWRITE_FONT_STYLE_NORMAL
, &font
);
8367 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
8369 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
8370 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
8372 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void **)&fontface1
);
8373 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
8375 hr
= IDWriteFontFamily_GetFamilyNames(family
, &names
);
8376 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
8378 get_enus_string(names
, nameW
, ARRAY_SIZE(nameW
));
8381 hr
= IDWriteFontFace1_TryGetFontTable(fontface1
, MS_KERN_TAG
, &data
, &size
, &context
, &exists
);
8382 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
8383 IDWriteFontFace1_ReleaseFontTable(fontface1
, context
);
8385 has_kerningpairs
= IDWriteFontFace1_HasKerningPairs(fontface1
);
8387 ok(!has_kerningpairs
, "%s: expected %d, got %d\n", wine_dbgstr_w(nameW
), exists
, has_kerningpairs
);
8389 IDWriteLocalizedStrings_Release(names
);
8390 IDWriteFont_Release(font
);
8392 IDWriteFontFace1_Release(fontface1
);
8393 IDWriteFontFace_Release(fontface
);
8394 IDWriteFontFamily_Release(family
);
8397 IDWriteFontCollection_Release(syscollection
);
8398 ref
= IDWriteFactory_Release(factory
);
8399 ok(ref
== 0, "factory not released, %u\n", ref
);
8402 static void get_expected_glyph_origins(D2D1_POINT_2F baseline_origin
, const DWRITE_GLYPH_RUN
*run
,
8403 D2D1_POINT_2F
*origins
)
8407 if (run
->bidiLevel
& 1)
8409 DWRITE_GLYPH_METRICS glyph_metrics
[2];
8410 DWRITE_FONT_METRICS metrics
;
8414 hr
= IDWriteFontFace_GetDesignGlyphMetrics(run
->fontFace
, run
->glyphIndices
, run
->glyphCount
, glyph_metrics
, FALSE
);
8415 ok(hr
== S_OK
, "Failed to get glyph metrics, hr %#x.\n", hr
);
8417 IDWriteFontFace_GetMetrics(run
->fontFace
, &metrics
);
8419 advance
= run
->fontEmSize
* glyph_metrics
[0].advanceWidth
/ metrics
.designUnitsPerEm
;
8421 baseline_origin
.x
-= advance
;
8423 for (i
= 0; i
< run
->glyphCount
; ++i
)
8425 origins
[i
].x
= baseline_origin
.x
- run
->glyphOffsets
[i
].advanceOffset
;
8426 origins
[i
].y
= baseline_origin
.y
- run
->glyphOffsets
[i
].ascenderOffset
;
8428 baseline_origin
.x
-= run
->glyphAdvances
[i
];
8433 for (i
= 0; i
< run
->glyphCount
; ++i
)
8435 origins
[i
].x
= baseline_origin
.x
+ run
->glyphOffsets
[i
].advanceOffset
;
8436 origins
[i
].y
= baseline_origin
.y
- run
->glyphOffsets
[i
].ascenderOffset
;
8438 baseline_origin
.x
+= run
->glyphAdvances
[i
];
8443 static void test_ComputeGlyphOrigins(void)
8445 static const struct origins_test
8447 D2D1_POINT_2F baseline_origin
;
8449 DWRITE_GLYPH_OFFSET offsets
[2];
8450 unsigned int bidi_level
;
8454 { { 123.0f
, 321.0f
}, { 10.0f
, 20.0f
}, { { 0 } } },
8455 { { 123.0f
, 321.0f
}, { 10.0f
, 20.0f
}, { { 0.3f
, 0.5f
}, { -0.1f
, 0.9f
} } },
8456 { { 123.0f
, 321.0f
}, { 10.0f
, 20.0f
}, { { 0 } }, 1 },
8458 IDWriteFactory4
*factory
;
8459 DWRITE_GLYPH_RUN run
;
8461 D2D1_POINT_2F origins
[2], expected_origins
[2];
8462 D2D1_POINT_2F baseline_origin
;
8463 UINT16 glyphs
[2] = { 0 };
8468 IDWriteFontFace
*fontface
;
8470 factory
= create_factory_iid(&IID_IDWriteFactory4
);
8472 win_skip("ComputeGlyphOrigins() is not supported.\n");
8476 fontface
= create_fontface((IDWriteFactory
*)factory
);
8478 for (i
= 0; i
< ARRAY_SIZE(origins_tests
); ++i
)
8480 run
.fontFace
= fontface
;
8481 run
.fontEmSize
= 32.0f
;
8483 run
.glyphIndices
= glyphs
;
8484 run
.glyphAdvances
= origins_tests
[i
].advances
;
8485 run
.glyphOffsets
= origins_tests
[i
].offsets
;
8486 run
.isSideways
= FALSE
;
8487 run
.bidiLevel
= origins_tests
[i
].bidi_level
;
8489 get_expected_glyph_origins(origins_tests
[i
].baseline_origin
, &run
, expected_origins
);
8491 memset(origins
, 0, sizeof(origins
));
8492 hr
= IDWriteFactory4_ComputeGlyphOrigins_(factory
, &run
, origins_tests
[i
].baseline_origin
, origins
);
8493 ok(hr
== S_OK
, "%u: failed to compute glyph origins, hr %#x.\n", i
, hr
);
8494 for (j
= 0; j
< run
.glyphCount
; ++j
)
8496 ok(!memcmp(&origins
[j
], &expected_origins
[j
], sizeof(origins
[j
])),
8497 "%u: unexpected origin[%u] (%f, %f) - (%f, %f).\n", i
, j
, origins
[j
].x
, origins
[j
].y
,
8498 expected_origins
[j
].x
, expected_origins
[j
].y
);
8502 IDWriteFontFace_Release(fontface
);
8504 advances
[0] = 10.0f
;
8505 advances
[1] = 20.0f
;
8507 run
.fontFace
= NULL
;
8508 run
.fontEmSize
= 16.0f
;
8510 run
.glyphIndices
= glyphs
;
8511 run
.glyphAdvances
= advances
;
8512 run
.glyphOffsets
= NULL
;
8513 run
.isSideways
= FALSE
;
8516 baseline_origin
.x
= 123.0f
;
8517 baseline_origin
.y
= 321.0f
;
8519 memset(origins
, 0, sizeof(origins
));
8520 hr
= IDWriteFactory4_ComputeGlyphOrigins_(factory
, &run
, baseline_origin
, origins
);
8521 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
8522 ok(origins
[0].x
== 123.0f
&& origins
[0].y
== 321.0f
, "origins[0] %f,%f\n", origins
[0].x
, origins
[0].y
);
8523 ok(origins
[1].x
== 133.0f
&& origins
[1].y
== 321.0f
, "origins[1] %f,%f\n", origins
[1].x
, origins
[1].y
);
8525 memset(origins
, 0, sizeof(origins
));
8526 hr
= IDWriteFactory4_ComputeGlyphOrigins(factory
, &run
, DWRITE_MEASURING_MODE_NATURAL
, baseline_origin
,
8528 ok(origins
[0].x
== 123.0f
&& origins
[0].y
== 321.0f
, "origins[0] %f,%f\n", origins
[0].x
, origins
[0].y
);
8529 ok(origins
[1].x
== 133.0f
&& origins
[1].y
== 321.0f
, "origins[1] %f,%f\n", origins
[1].x
, origins
[1].y
);
8531 /* transform is not applied to returned origins */
8539 memset(origins
, 0, sizeof(origins
));
8540 hr
= IDWriteFactory4_ComputeGlyphOrigins(factory
, &run
, DWRITE_MEASURING_MODE_NATURAL
, baseline_origin
,
8542 ok(origins
[0].x
== 123.0f
&& origins
[0].y
== 321.0f
, "origins[0] %f,%f\n", origins
[0].x
, origins
[0].y
);
8543 ok(origins
[1].x
== 133.0f
&& origins
[1].y
== 321.0f
, "origins[1] %f,%f\n", origins
[1].x
, origins
[1].y
);
8545 ref
= IDWriteFactory4_Release(factory
);
8546 ok(ref
== 0, "factory not released, %u\n", ref
);
8549 static void test_object_lifetime(void)
8551 IDWriteFontCollection
*collection
, *collection2
;
8552 IDWriteFontList
*fontlist
, *fontlist2
;
8553 IDWriteGdiInterop
*interop
, *interop2
;
8554 IDWriteFontFamily
*family
, *family2
;
8555 IDWriteFontFace
*fontface
;
8556 IDWriteFont
*font
, *font2
;
8557 IDWriteFactory
*factory
;
8561 factory
= create_factory();
8562 EXPECT_REF(factory
, 1);
8564 /* system collection takes factory reference */
8565 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &collection
, FALSE
);
8566 ok(hr
== S_OK
, "got %#x\n", hr
);
8568 EXPECT_REF(collection
, 1);
8569 EXPECT_REF(factory
, 2);
8571 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &collection2
, FALSE
);
8572 ok(hr
== S_OK
, "got %#x\n", hr
);
8573 ok(collection2
== collection
, "expected same collection\n");
8575 EXPECT_REF(collection
, 2);
8576 EXPECT_REF(factory
, 2);
8578 IDWriteFontCollection_Release(collection2
);
8580 IDWriteFontCollection_AddRef(collection
);
8581 EXPECT_REF(collection
, 2);
8582 EXPECT_REF(factory
, 2);
8583 IDWriteFontCollection_Release(collection
);
8585 EXPECT_REF(collection
, 1);
8587 /* family takes collection reference */
8588 hr
= IDWriteFontCollection_GetFontFamily(collection
, 0, &family
);
8589 ok(hr
== S_OK
, "got %#x\n", hr
);
8591 EXPECT_REF(family
, 1);
8592 EXPECT_REF(collection
, 2);
8593 EXPECT_REF(factory
, 2);
8595 hr
= IDWriteFontCollection_GetFontFamily(collection
, 0, &family2
);
8596 ok(hr
== S_OK
, "got %#x\n", hr
);
8598 EXPECT_REF(family2
, 1);
8599 EXPECT_REF(collection
, 3);
8600 EXPECT_REF(factory
, 2);
8602 IDWriteFontFamily_Release(family2
);
8604 EXPECT_REF(family
, 1);
8605 EXPECT_REF(collection
, 2);
8606 EXPECT_REF(factory
, 2);
8608 /* font takes family reference */
8609 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
,
8610 DWRITE_FONT_STRETCH_NORMAL
, DWRITE_FONT_STYLE_NORMAL
, &font
);
8611 ok(hr
== S_OK
, "got %#x\n", hr
);
8613 EXPECT_REF(family
, 2);
8614 EXPECT_REF(collection
, 2);
8615 EXPECT_REF(factory
, 2);
8617 hr
= IDWriteFont_GetFontFamily(font
, &family2
);
8618 ok(hr
== S_OK
, "got %#x\n", hr
);
8619 ok(family2
== family
, "unexpected family pointer\n");
8620 IDWriteFontFamily_Release(family2
);
8622 EXPECT_REF(font
, 1);
8623 EXPECT_REF(factory
, 2);
8625 /* Fontface takes factory reference and nothing else. */
8626 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
8627 ok(hr
== S_OK
, "got %#x\n", hr
);
8629 EXPECT_REF(font
, 1);
8630 EXPECT_REF_BROKEN(fontface
, 1, 2);
8631 EXPECT_REF(family
, 2);
8632 EXPECT_REF(collection
, 2);
8633 EXPECT_REF_BROKEN(factory
, 3, 2);
8635 /* get font from fontface */
8636 hr
= IDWriteFontCollection_GetFontFromFontFace(collection
, fontface
, &font2
);
8637 ok(hr
== S_OK
, "got %#x\n", hr
);
8639 EXPECT_REF(font
, 1);
8640 EXPECT_REF(font2
, 1);
8641 EXPECT_REF_BROKEN(fontface
, 1, 2);
8642 EXPECT_REF(family
, 2);
8643 EXPECT_REF(collection
, 3);
8644 EXPECT_REF_BROKEN(factory
, 3, 2);
8646 IDWriteFont_Release(font2
);
8647 IDWriteFontFace_Release(fontface
);
8649 EXPECT_REF(font
, 1);
8650 EXPECT_REF(family
, 2);
8651 EXPECT_REF(collection
, 2);
8652 EXPECT_REF(factory
, 2);
8654 IDWriteFont_Release(font
);
8656 EXPECT_REF(family
, 1);
8657 EXPECT_REF(collection
, 2);
8658 EXPECT_REF(factory
, 2);
8660 /* Matching fonts list takes family reference. */
8661 hr
= IDWriteFontFamily_GetMatchingFonts(family
, DWRITE_FONT_WEIGHT_NORMAL
,
8662 DWRITE_FONT_STRETCH_NORMAL
, DWRITE_FONT_STYLE_NORMAL
, &fontlist
);
8663 ok(hr
== S_OK
, "got %#x\n", hr
);
8665 EXPECT_REF(family
, 2);
8666 EXPECT_REF(collection
, 2);
8667 EXPECT_REF(factory
, 2);
8669 hr
= IDWriteFontFamily_GetMatchingFonts(family
, DWRITE_FONT_WEIGHT_NORMAL
,
8670 DWRITE_FONT_STRETCH_NORMAL
, DWRITE_FONT_STYLE_NORMAL
, &fontlist2
);
8671 ok(hr
== S_OK
, "got %#x\n", hr
);
8672 ok(fontlist2
!= fontlist
, "unexpected font list\n");
8673 IDWriteFontList_Release(fontlist2
);
8675 IDWriteFontList_Release(fontlist
);
8677 IDWriteFontFamily_Release(family
);
8678 EXPECT_REF(collection
, 1);
8680 EXPECT_REF(factory
, 2);
8681 ref
= IDWriteFontCollection_Release(collection
);
8682 ok(ref
== 0, "collection not released, %u\n", ref
);
8683 EXPECT_REF(factory
, 1);
8685 /* GDI interop object takes factory reference */
8686 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop
);
8687 ok(hr
== S_OK
, "got %#x\n", hr
);
8688 EXPECT_REF(interop
, 1);
8689 EXPECT_REF(factory
, 2);
8691 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop2
);
8692 ok(hr
== S_OK
, "got %#x\n", hr
);
8693 ok(interop
== interop2
, "got unexpected interop pointer\n");
8695 EXPECT_REF(interop
, 2);
8696 EXPECT_REF(factory
, 2);
8698 IDWriteGdiInterop_Release(interop2
);
8699 ref
= IDWriteGdiInterop_Release(interop
);
8700 ok(ref
== 0, "interop not released, %u\n", ref
);
8702 ref
= IDWriteFactory_Release(factory
);
8703 ok(ref
== 0, "factory not released, %u\n", ref
);
8706 struct testowner_object
8708 IUnknown IUnknown_iface
;
8712 static inline struct testowner_object
*impl_from_IUnknown(IUnknown
*iface
)
8714 return CONTAINING_RECORD(iface
, struct testowner_object
, IUnknown_iface
);
8717 static HRESULT WINAPI
testowner_QueryInterface(IUnknown
*iface
, REFIID riid
, void **obj
)
8719 if (IsEqualIID(riid
, &IID_IUnknown
)) {
8721 IUnknown_AddRef(iface
);
8726 return E_NOINTERFACE
;
8729 static ULONG WINAPI
testowner_AddRef(IUnknown
*iface
)
8731 struct testowner_object
*object
= impl_from_IUnknown(iface
);
8732 return InterlockedIncrement(&object
->ref
);
8735 static ULONG WINAPI
testowner_Release(IUnknown
*iface
)
8737 struct testowner_object
*object
= impl_from_IUnknown(iface
);
8738 return InterlockedDecrement(&object
->ref
);
8741 static const IUnknownVtbl testownervtbl
= {
8742 testowner_QueryInterface
,
8747 static void testowner_init(struct testowner_object
*object
)
8749 object
->IUnknown_iface
.lpVtbl
= &testownervtbl
;
8753 static void test_inmemory_file_loader(void)
8755 IDWriteFontFileStream
*stream
, *stream2
, *stream3
;
8756 IDWriteInMemoryFontFileLoader
*loader
, *loader2
;
8757 IDWriteInMemoryFontFileLoader
*inmemory
;
8758 IDWriteFontFileLoader
*fileloader
;
8759 struct testowner_object ownerobject
;
8760 const void *key
, *data
, *frag_start
;
8761 UINT64 file_size
, size
, writetime
;
8762 IDWriteFontFile
*file
, *file2
;
8763 IDWriteFontFace
*fontface
;
8764 void *context
, *context2
;
8765 IDWriteFactory5
*factory
;
8766 UINT32 count
, key_size
;
8771 factory
= create_factory_iid(&IID_IDWriteFactory5
);
8773 win_skip("CreateInMemoryFontFileLoader() is not supported\n");
8777 EXPECT_REF(factory
, 1);
8778 hr
= IDWriteFactory5_CreateInMemoryFontFileLoader(factory
, &loader
);
8779 ok(hr
== S_OK
, "got %#x\n", hr
);
8780 EXPECT_REF(factory
, 1);
8782 testowner_init(&ownerobject
);
8783 fontface
= create_fontface((IDWriteFactory
*)factory
);
8785 hr
= IDWriteFactory5_CreateInMemoryFontFileLoader(factory
, &loader2
);
8786 ok(hr
== S_OK
, "got %#x\n", hr
);
8787 ok(loader
!= loader2
, "unexpected pointer\n");
8788 IDWriteInMemoryFontFileLoader_Release(loader2
);
8792 count
= IDWriteInMemoryFontFileLoader_GetFileCount(inmemory
);
8793 ok(!count
, "Unexpected file count %u.\n", count
);
8795 /* Use whole font blob to construct in-memory file. */
8797 hr
= IDWriteFontFace_GetFiles(fontface
, &count
, &file
);
8798 ok(hr
== S_OK
, "got %#x\n", hr
);
8800 hr
= IDWriteFontFile_GetLoader(file
, &fileloader
);
8801 ok(hr
== S_OK
, "got %#x\n", hr
);
8803 hr
= IDWriteFontFile_GetReferenceKey(file
, &key
, &key_size
);
8804 ok(hr
== S_OK
, "got %#x\n", hr
);
8806 hr
= IDWriteFontFileLoader_CreateStreamFromKey(fileloader
, key
, key_size
, &stream
);
8807 ok(hr
== S_OK
, "got %#x\n", hr
);
8808 IDWriteFontFileLoader_Release(fileloader
);
8809 IDWriteFontFile_Release(file
);
8811 hr
= IDWriteFontFileStream_GetFileSize(stream
, &file_size
);
8812 ok(hr
== S_OK
, "got %#x\n", hr
);
8814 hr
= IDWriteFontFileStream_ReadFileFragment(stream
, &data
, 0, file_size
, &context
);
8815 ok(hr
== S_OK
, "got %#x\n", hr
);
8817 /* Not registered yet. */
8818 hr
= IDWriteInMemoryFontFileLoader_CreateInMemoryFontFileReference(inmemory
, (IDWriteFactory
*)factory
, data
,
8819 file_size
, NULL
, &file
);
8820 ok(hr
== E_INVALIDARG
, "got %#x\n", hr
);
8822 count
= IDWriteInMemoryFontFileLoader_GetFileCount(inmemory
);
8823 ok(count
== 1, "Unexpected file count %u.\n", count
);
8825 hr
= IDWriteFactory5_RegisterFontFileLoader(factory
, (IDWriteFontFileLoader
*)inmemory
);
8826 ok(hr
== S_OK
, "got %#x\n", hr
);
8827 EXPECT_REF(inmemory
, 2);
8829 EXPECT_REF(&ownerobject
.IUnknown_iface
, 1);
8830 hr
= IDWriteInMemoryFontFileLoader_CreateInMemoryFontFileReference(inmemory
, (IDWriteFactory
*)factory
, data
,
8831 file_size
, &ownerobject
.IUnknown_iface
, &file
);
8832 ok(hr
== S_OK
, "got %#x\n", hr
);
8833 EXPECT_REF(&ownerobject
.IUnknown_iface
, 2);
8834 EXPECT_REF(inmemory
, 3);
8836 count
= IDWriteInMemoryFontFileLoader_GetFileCount(inmemory
);
8837 ok(count
== 2, "Unexpected file count %u.\n", count
);
8839 hr
= IDWriteInMemoryFontFileLoader_CreateInMemoryFontFileReference(inmemory
, (IDWriteFactory
*)factory
, data
,
8840 file_size
, &ownerobject
.IUnknown_iface
, &file2
);
8841 ok(hr
== S_OK
, "got %#x\n", hr
);
8842 ok(file2
!= file
, "got unexpected file\n");
8843 EXPECT_REF(&ownerobject
.IUnknown_iface
, 3);
8844 EXPECT_REF(inmemory
, 4);
8846 count
= IDWriteInMemoryFontFileLoader_GetFileCount(inmemory
);
8847 ok(count
== 3, "Unexpected file count %u.\n", count
);
8849 /* Check in-memory reference key format. */
8850 hr
= IDWriteFontFile_GetReferenceKey(file
, &key
, &key_size
);
8851 ok(hr
== S_OK
, "got %#x\n", hr
);
8853 ok(key
&& *(DWORD
*)key
== 1, "got wrong ref key\n");
8854 ok(key_size
== 4, "ref key size %u\n", key_size
);
8856 hr
= IDWriteFontFile_GetReferenceKey(file2
, &key
, &key_size
);
8857 ok(hr
== S_OK
, "got %#x\n", hr
);
8859 ok(key
&& *(DWORD
*)key
== 2, "got wrong ref key\n");
8860 ok(key_size
== 4, "ref key size %u\n", key_size
);
8862 EXPECT_REF(inmemory
, 4);
8863 hr
= IDWriteInMemoryFontFileLoader_CreateStreamFromKey(inmemory
, key
, key_size
, &stream2
);
8864 ok(hr
== S_OK
, "Failed to create a stream, hr %#x.\n", hr
);
8865 EXPECT_REF(stream2
, 1);
8866 EXPECT_REF(inmemory
, 4);
8868 hr
= IDWriteInMemoryFontFileLoader_CreateStreamFromKey(inmemory
, key
, key_size
, &stream3
);
8869 ok(hr
== S_OK
, "Failed to create a stream, hr %#x.\n", hr
);
8871 ok(stream2
!= stream3
, "Unexpected stream.\n");
8873 IDWriteFontFileStream_Release(stream2
);
8874 IDWriteFontFileStream_Release(stream3
);
8876 /* Release file at index 1, create new one to see if index is reused. */
8877 EXPECT_REF(&ownerobject
.IUnknown_iface
, 3);
8878 ref
= IDWriteFontFile_Release(file
);
8879 ok(ref
== 0, "File object not released, %u.\n", ref
);
8880 EXPECT_REF(&ownerobject
.IUnknown_iface
, 3);
8882 count
= IDWriteInMemoryFontFileLoader_GetFileCount(inmemory
);
8883 ok(count
== 3, "Unexpected file count %u.\n", count
);
8885 EXPECT_REF(&ownerobject
.IUnknown_iface
, 3);
8886 ref
= IDWriteFontFile_Release(file2
);
8887 ok(ref
== 0, "File object not released, %u.\n", ref
);
8888 EXPECT_REF(&ownerobject
.IUnknown_iface
, 3);
8890 count
= IDWriteInMemoryFontFileLoader_GetFileCount(inmemory
);
8891 ok(count
== 3, "Unexpected file count %u.\n", count
);
8893 hr
= IDWriteFactory5_UnregisterFontFileLoader(factory
, (IDWriteFontFileLoader
*)inmemory
);
8894 ok(hr
== S_OK
, "got %#x\n", hr
);
8895 EXPECT_REF(&ownerobject
.IUnknown_iface
, 3);
8897 EXPECT_REF(&ownerobject
.IUnknown_iface
, 3);
8898 ref
= IDWriteInMemoryFontFileLoader_Release(inmemory
);
8899 ok(ref
== 0, "loader not released, %u.\n", ref
);
8900 EXPECT_REF(&ownerobject
.IUnknown_iface
, 1);
8902 /* Test reference key for first added file. */
8903 hr
= IDWriteFactory5_CreateInMemoryFontFileLoader(factory
, &loader
);
8904 ok(hr
== S_OK
, "Failed to create loader, hr %#x.\n", hr
);
8908 hr
= IDWriteFactory5_RegisterFontFileLoader(factory
, (IDWriteFontFileLoader
*)inmemory
);
8909 ok(hr
== S_OK
, "Failed to register loader, hr %#x.\n", hr
);
8912 hr
= IDWriteInMemoryFontFileLoader_CreateStreamFromKey(inmemory
, &ref_key
, sizeof(ref_key
), &stream2
);
8913 ok(hr
== E_INVALIDARG
, "Unexpected hr %#x.\n", hr
);
8915 /* With owner object. */
8916 hr
= IDWriteInMemoryFontFileLoader_CreateInMemoryFontFileReference(inmemory
, (IDWriteFactory
*)factory
, data
,
8917 file_size
, &ownerobject
.IUnknown_iface
, &file
);
8918 ok(hr
== S_OK
, "Failed to create in-memory file reference, hr %#x.\n", hr
);
8921 hr
= IDWriteInMemoryFontFileLoader_CreateStreamFromKey(inmemory
, &ref_key
, sizeof(ref_key
), &stream2
);
8922 ok(hr
== S_OK
, "Failed to create a stream, hr %#x.\n", hr
);
8924 context2
= (void *)0xdeadbeef;
8925 hr
= IDWriteFontFileStream_ReadFileFragment(stream2
, &frag_start
, 0, file_size
, &context2
);
8926 ok(hr
== S_OK
, "Failed to read a fragment, hr %#x.\n", hr
);
8927 ok(context2
== NULL
, "Unexpected context %p.\n", context2
);
8928 ok(frag_start
== data
, "Unexpected fragment pointer %p.\n", frag_start
);
8930 hr
= IDWriteFontFileStream_GetFileSize(stream2
, &size
);
8931 ok(hr
== S_OK
, "Failed to get file size, hr %#x.\n", hr
);
8932 ok(size
== file_size
, "Unexpected file size.\n");
8934 IDWriteFontFileStream_ReleaseFileFragment(stream2
, context2
);
8937 hr
= IDWriteFontFileStream_GetLastWriteTime(stream2
, &writetime
);
8938 ok(hr
== E_NOTIMPL
, "Unexpected hr %#x.\n", hr
);
8939 ok(writetime
== 0, "Unexpected writetime.\n");
8941 IDWriteFontFileStream_Release(stream2
);
8943 /* Without owner object. */
8944 hr
= IDWriteInMemoryFontFileLoader_CreateInMemoryFontFileReference(inmemory
, (IDWriteFactory
*)factory
, data
,
8945 file_size
, NULL
, &file2
);
8946 ok(hr
== S_OK
, "Failed to create in-memory file reference, hr %#x.\n", hr
);
8949 hr
= IDWriteInMemoryFontFileLoader_CreateStreamFromKey(inmemory
, &ref_key
, sizeof(ref_key
), &stream2
);
8950 ok(hr
== S_OK
, "Failed to create a stream, hr %#x.\n", hr
);
8952 context2
= (void *)0xdeadbeef;
8953 hr
= IDWriteFontFileStream_ReadFileFragment(stream2
, &frag_start
, 0, file_size
, &context2
);
8954 ok(hr
== S_OK
, "Failed to read a fragment, hr %#x.\n", hr
);
8955 ok(context2
== NULL
, "Unexpected context %p.\n", context2
);
8956 ok(frag_start
!= data
, "Unexpected fragment pointer %p.\n", frag_start
);
8958 hr
= IDWriteFontFileStream_GetFileSize(stream2
, &size
);
8959 ok(hr
== S_OK
, "Failed to get file size, hr %#x.\n", hr
);
8960 ok(size
== file_size
, "Unexpected file size.\n");
8962 IDWriteFontFileStream_ReleaseFileFragment(stream2
, context2
);
8965 hr
= IDWriteFontFileStream_GetLastWriteTime(stream2
, &writetime
);
8966 ok(hr
== E_NOTIMPL
, "Unexpected hr %#x.\n", hr
);
8967 ok(writetime
== 0, "Unexpected writetime.\n");
8969 IDWriteFontFileStream_Release(stream2
);
8970 IDWriteFontFile_Release(file2
);
8972 /* Key size validation. */
8974 hr
= IDWriteInMemoryFontFileLoader_CreateStreamFromKey(inmemory
, NULL
, sizeof(ref_key
) - 1, &stream2
);
8975 ok(hr
== E_INVALIDARG
, "Unexpected hr %#x.\n", hr
);
8978 hr
= IDWriteInMemoryFontFileLoader_CreateStreamFromKey(inmemory
, &ref_key
, sizeof(ref_key
) - 1, &stream2
);
8979 ok(hr
== E_INVALIDARG
, "Unexpected hr %#x.\n", hr
);
8982 hr
= IDWriteInMemoryFontFileLoader_CreateStreamFromKey(inmemory
, &ref_key
, sizeof(ref_key
) + 1, &stream2
);
8983 ok(hr
== E_INVALIDARG
, "Unexpected hr %#x.\n", hr
);
8985 count
= IDWriteInMemoryFontFileLoader_GetFileCount(inmemory
);
8986 ok(count
== 2, "Unexpected file count %u.\n", count
);
8988 hr
= IDWriteFontFile_GetReferenceKey(file
, &key
, &key_size
);
8989 ok(hr
== S_OK
, "Failed to get reference key, hr %#x.\n", hr
);
8991 ok(key
&& *(DWORD
*)key
== 0, "Unexpected reference key.\n");
8992 ok(key_size
== 4, "Unexpected key size %u.\n", key_size
);
8994 IDWriteFontFile_Release(file
);
8996 count
= IDWriteInMemoryFontFileLoader_GetFileCount(inmemory
);
8997 ok(count
== 2, "Unexpected file count %u.\n", count
);
8999 hr
= IDWriteFactory5_UnregisterFontFileLoader(factory
, (IDWriteFontFileLoader
*)inmemory
);
9000 ok(hr
== S_OK
, "Failed to unregister loader, hr %#x.\n", hr
);
9002 IDWriteFontFileStream_ReleaseFileFragment(stream
, context
);
9003 IDWriteFontFileStream_Release(stream
);
9004 IDWriteFontFace_Release(fontface
);
9006 ref
= IDWriteInMemoryFontFileLoader_Release(inmemory
);
9007 ok(ref
== 0, "loader not released, %u.\n", ref
);
9009 ref
= IDWriteFactory5_Release(factory
);
9010 ok(ref
== 0, "factory not released, %u\n", ref
);
9013 static BOOL
face_has_table(IDWriteFontFace4
*fontface
, UINT32 tag
)
9015 BOOL exists
= FALSE
;
9021 hr
= IDWriteFontFace4_TryGetFontTable(fontface
, tag
, &data
, &size
, &context
, &exists
);
9022 ok(hr
== S_OK
, "TryGetFontTable() failed, %#x\n", hr
);
9024 IDWriteFontFace4_ReleaseFontTable(fontface
, context
);
9029 static DWORD
get_sbix_formats(IDWriteFontFace4
*fontface
)
9031 UINT32 size
, s
, num_strikes
;
9032 const sbix_header
*header
;
9033 UINT16 g
, num_glyphs
;
9034 BOOL exists
= FALSE
;
9041 hr
= IDWriteFontFace4_TryGetFontTable(fontface
, MS_MAXP_TAG
, &data
, &size
, &context
, &exists
);
9042 ok(hr
== S_OK
, "TryGetFontTable() failed, %#x\n", hr
);
9043 ok(exists
, "Expected maxp table\n");
9049 num_glyphs
= GET_BE_WORD(maxp
->numGlyphs
);
9051 hr
= IDWriteFontFace4_TryGetFontTable(fontface
, MS_SBIX_TAG
, &data
, &size
, &context
, &exists
);
9052 ok(hr
== S_OK
, "TryGetFontTable() failed, %#x\n", hr
);
9053 ok(exists
, "Expected sbix table\n");
9056 num_strikes
= GET_BE_DWORD(header
->numStrikes
);
9058 for (s
= 0; s
< num_strikes
; s
++) {
9059 sbix_strike
*strike
= (sbix_strike
*)((BYTE
*)header
+ GET_BE_DWORD(header
->strikeOffset
[s
]));
9061 for (g
= 0; g
< num_glyphs
; g
++) {
9062 DWORD offset
= GET_BE_DWORD(strike
->glyphDataOffsets
[g
]);
9063 DWORD offset_next
= GET_BE_DWORD(strike
->glyphDataOffsets
[g
+ 1]);
9064 sbix_glyph_data
*glyph_data
;
9067 if (offset
== offset_next
)
9070 glyph_data
= (sbix_glyph_data
*)((BYTE
*)strike
+ offset
);
9071 switch (format
= glyph_data
->graphicType
)
9074 ret
|= DWRITE_GLYPH_IMAGE_FORMATS_PNG
;
9077 ret
|= DWRITE_GLYPH_IMAGE_FORMATS_JPEG
;
9080 ret
|= DWRITE_GLYPH_IMAGE_FORMATS_TIFF
;
9083 ok(0, "unexpected format, %#x\n", GET_BE_DWORD(format
));
9088 IDWriteFontFace4_ReleaseFontTable(fontface
, context
);
9093 static DWORD
get_cblc_formats(IDWriteFontFace4
*fontface
)
9095 CBLCBitmapSizeTable
*sizes
;
9096 UINT32 num_sizes
, size
, s
;
9097 BOOL exists
= FALSE
;
9103 hr
= IDWriteFontFace4_TryGetFontTable(fontface
, MS_CBLC_TAG
, (const void **)&header
, &size
, &context
, &exists
);
9104 ok(hr
== S_OK
, "TryGetFontTable() failed, %#x\n", hr
);
9105 ok(exists
, "Expected CBLC table\n");
9110 num_sizes
= GET_BE_DWORD(header
->numSizes
);
9111 sizes
= (CBLCBitmapSizeTable
*)(header
+ 1);
9113 for (s
= 0; s
< num_sizes
; s
++) {
9114 BYTE bpp
= sizes
[s
].bitDepth
;
9116 if (bpp
== 1 || bpp
== 2 || bpp
== 4 || bpp
== 8)
9117 ret
|= DWRITE_GLYPH_IMAGE_FORMATS_PNG
;
9119 ret
|= DWRITE_GLYPH_IMAGE_FORMATS_PREMULTIPLIED_B8G8R8A8
;
9122 IDWriteFontFace4_ReleaseFontTable(fontface
, context
);
9127 static DWORD
get_face_glyph_image_formats(IDWriteFontFace4
*fontface
)
9129 DWORD ret
= DWRITE_GLYPH_IMAGE_FORMATS_NONE
;
9131 if (face_has_table(fontface
, MS_GLYF_TAG
))
9132 ret
|= DWRITE_GLYPH_IMAGE_FORMATS_TRUETYPE
;
9134 if (face_has_table(fontface
, MS_CFF__TAG
) ||
9135 face_has_table(fontface
, MS_CFF2_TAG
))
9136 ret
|= DWRITE_GLYPH_IMAGE_FORMATS_CFF
;
9138 if (face_has_table(fontface
, MS_COLR_TAG
))
9139 ret
|= DWRITE_GLYPH_IMAGE_FORMATS_COLR
;
9141 if (face_has_table(fontface
, MS_SVG__TAG
))
9142 ret
|= DWRITE_GLYPH_IMAGE_FORMATS_SVG
;
9144 if (face_has_table(fontface
, MS_SBIX_TAG
))
9145 ret
|= get_sbix_formats(fontface
);
9147 if (face_has_table(fontface
, MS_CBLC_TAG
))
9148 ret
|= get_cblc_formats(fontface
);
9153 static void test_GetGlyphImageFormats(void)
9155 IDWriteFontCollection
*syscollection
;
9156 IDWriteFactory
*factory
;
9160 IDWriteFontFace
*fontface
;
9161 IDWriteFontFace4
*fontface4
;
9163 factory
= create_factory();
9165 fontface
= create_fontface(factory
);
9166 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace4
, (void **)&fontface4
);
9167 IDWriteFontFace_Release(fontface
);
9169 win_skip("GetGlyphImageFormats() is not supported\n");
9170 IDWriteFactory_Release(factory
);
9173 IDWriteFontFace4_Release(fontface4
);
9175 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &syscollection
, FALSE
);
9176 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
9177 count
= IDWriteFontCollection_GetFontFamilyCount(syscollection
);
9179 for (i
= 0; i
< count
; i
++) {
9180 WCHAR familynameW
[256], facenameW
[128];
9181 IDWriteLocalizedStrings
*names
;
9182 IDWriteFontFamily
*family
;
9183 UINT32 j
, fontcount
;
9186 hr
= IDWriteFontCollection_GetFontFamily(syscollection
, i
, &family
);
9187 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
9189 hr
= IDWriteFontFamily_GetFamilyNames(family
, &names
);
9190 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
9192 get_enus_string(names
, familynameW
, ARRAY_SIZE(familynameW
));
9193 IDWriteLocalizedStrings_Release(names
);
9195 fontcount
= IDWriteFontFamily_GetFontCount(family
);
9196 for (j
= 0; j
< fontcount
; j
++) {
9197 DWORD formats
, expected_formats
;
9199 hr
= IDWriteFontFamily_GetFont(family
, j
, &font
);
9200 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
9202 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
9203 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
9205 hr
= IDWriteFont_GetFaceNames(font
, &names
);
9206 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
9208 get_enus_string(names
, facenameW
, ARRAY_SIZE(facenameW
));
9210 IDWriteLocalizedStrings_Release(names
);
9212 IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace4
, (void **)&fontface4
);
9214 /* Mask describes font as a whole. */
9215 formats
= IDWriteFontFace4_GetGlyphImageFormats(fontface4
);
9216 expected_formats
= get_face_glyph_image_formats(fontface4
);
9217 ok(formats
== expected_formats
, "%s - %s, expected formats %#x, got formats %#x.\n",
9218 wine_dbgstr_w(familynameW
), wine_dbgstr_w(facenameW
), expected_formats
, formats
);
9220 IDWriteFontFace4_Release(fontface4
);
9221 IDWriteFontFace_Release(fontface
);
9222 IDWriteFont_Release(font
);
9225 IDWriteFontFamily_Release(family
);
9228 IDWriteFontCollection_Release(syscollection
);
9229 ref
= IDWriteFactory_Release(factory
);
9230 ok(ref
== 0, "factory not released, %u\n", ref
);
9233 static void test_CreateCustomRenderingParams(void)
9235 static const struct custom_params_test
9239 FLOAT cleartype_level
;
9240 DWRITE_PIXEL_GEOMETRY geometry
;
9241 DWRITE_RENDERING_MODE rendering_mode
;
9245 { 0.0f
, 0.0f
, 0.0f
, DWRITE_PIXEL_GEOMETRY_FLAT
, DWRITE_RENDERING_MODE_NATURAL
, E_INVALIDARG
},
9246 { 0.0f
, 0.1f
, 0.0f
, DWRITE_PIXEL_GEOMETRY_FLAT
, DWRITE_RENDERING_MODE_NATURAL
, E_INVALIDARG
},
9247 { 0.0f
, 0.0f
, 0.1f
, DWRITE_PIXEL_GEOMETRY_FLAT
, DWRITE_RENDERING_MODE_NATURAL
, E_INVALIDARG
},
9248 { -0.1f
, 0.0f
, 0.0f
, DWRITE_PIXEL_GEOMETRY_FLAT
, DWRITE_RENDERING_MODE_NATURAL
, E_INVALIDARG
},
9249 { 0.1f
, -0.1f
, 0.0f
, DWRITE_PIXEL_GEOMETRY_FLAT
, DWRITE_RENDERING_MODE_NATURAL
, E_INVALIDARG
},
9250 { 0.1f
, 0.0f
, -0.1f
, DWRITE_PIXEL_GEOMETRY_FLAT
, DWRITE_RENDERING_MODE_NATURAL
, E_INVALIDARG
},
9251 { 0.1f
, 0.0f
, 0.0f
, DWRITE_PIXEL_GEOMETRY_FLAT
, DWRITE_RENDERING_MODE_NATURAL
},
9252 { 0.01f
, 0.0f
, 0.0f
, DWRITE_PIXEL_GEOMETRY_FLAT
, DWRITE_RENDERING_MODE_NATURAL
},
9253 { 0.1f
, 0.0f
, 0.0f
, DWRITE_PIXEL_GEOMETRY_BGR
+ 1, DWRITE_RENDERING_MODE_NATURAL
, E_INVALIDARG
},
9254 { 0.1f
, 0.0f
, 0.0f
, DWRITE_PIXEL_GEOMETRY_BGR
, DWRITE_RENDERING_MODE_OUTLINE
+ 1, E_INVALIDARG
},
9255 { 0.1f
, 0.0f
, 2.0f
, DWRITE_PIXEL_GEOMETRY_BGR
, DWRITE_RENDERING_MODE_NATURAL
},
9257 IDWriteFactory
*factory
;
9262 factory
= create_factory();
9264 for (i
= 0; i
< ARRAY_SIZE(params_tests
); i
++) {
9265 IDWriteRenderingParams
*params
;
9267 params
= (void *)0xdeadbeef;
9268 hr
= IDWriteFactory_CreateCustomRenderingParams(factory
, params_tests
[i
].gamma
, params_tests
[i
].contrast
,
9269 params_tests
[i
].cleartype_level
, params_tests
[i
].geometry
, params_tests
[i
].rendering_mode
, ¶ms
);
9270 ok(hr
== params_tests
[i
].hr
, "%u: unexpected hr %#x, expected %#x.\n", i
, hr
, params_tests
[i
].hr
);
9273 ok(params_tests
[i
].gamma
== IDWriteRenderingParams_GetGamma(params
), "%u: unexpected gamma %f, expected %f.\n",
9274 i
, IDWriteRenderingParams_GetGamma(params
), params_tests
[i
].gamma
);
9275 ok(params_tests
[i
].contrast
== IDWriteRenderingParams_GetEnhancedContrast(params
),
9276 "%u: unexpected contrast %f, expected %f.\n",
9277 i
, IDWriteRenderingParams_GetEnhancedContrast(params
), params_tests
[i
].contrast
);
9278 ok(params_tests
[i
].cleartype_level
== IDWriteRenderingParams_GetClearTypeLevel(params
),
9279 "%u: unexpected ClearType level %f, expected %f.\n",
9280 i
, IDWriteRenderingParams_GetClearTypeLevel(params
), params_tests
[i
].cleartype_level
);
9281 ok(params_tests
[i
].geometry
== IDWriteRenderingParams_GetPixelGeometry(params
),
9282 "%u: unexpected pixel geometry %u, expected %u.\n", i
, IDWriteRenderingParams_GetPixelGeometry(params
),
9283 params_tests
[i
].geometry
);
9284 ok(params_tests
[i
].rendering_mode
== IDWriteRenderingParams_GetRenderingMode(params
),
9285 "%u: unexpected rendering mode %u, expected %u.\n", i
, IDWriteRenderingParams_GetRenderingMode(params
),
9286 params_tests
[i
].rendering_mode
);
9287 IDWriteRenderingParams_Release(params
);
9290 ok(params
== NULL
, "%u: expected NULL interface pointer on failure.\n", i
);
9293 ref
= IDWriteFactory_Release(factory
);
9294 ok(ref
== 0, "factory not released, %u\n", ref
);
9297 static void test_localfontfileloader(void)
9299 IDWriteFontFileLoader
*loader
, *loader2
;
9300 IDWriteFactory
*factory
, *factory2
;
9301 IDWriteFontFile
*file
, *file2
;
9306 factory
= create_factory();
9307 factory2
= create_factory();
9309 path
= create_testfontfile(test_fontfile
);
9311 hr
= IDWriteFactory_CreateFontFileReference(factory
, path
, NULL
, &file
);
9312 ok(hr
== S_OK
, "Failed to create file reference, hr %#x.\n", hr
);
9314 hr
= IDWriteFactory_CreateFontFileReference(factory2
, path
, NULL
, &file2
);
9315 ok(hr
== S_OK
, "Failed to create file reference, hr %#x.\n", hr
);
9316 ok(file
!= file2
, "Unexpected file instance.\n");
9318 hr
= IDWriteFontFile_GetLoader(file
, &loader
);
9319 ok(hr
== S_OK
, "Failed to get loader, hr %#x.\n", hr
);
9321 hr
= IDWriteFontFile_GetLoader(file2
, &loader2
);
9322 ok(hr
== S_OK
, "Failed to get loader, hr %#x.\n", hr
);
9323 ok(loader
== loader2
, "Unexpected loader instance\n");
9325 IDWriteFontFile_Release(file
);
9326 IDWriteFontFile_Release(file2
);
9327 IDWriteFontFileLoader_Release(loader
);
9328 IDWriteFontFileLoader_Release(loader2
);
9329 ref
= IDWriteFactory_Release(factory
);
9330 ok(ref
== 0, "factory not released, %u\n", ref
);
9331 ref
= IDWriteFactory_Release(factory2
);
9332 ok(ref
== 0, "factory not released, %u\n", ref
);
9333 DELETE_FONTFILE(path
);
9336 static void test_AnalyzeContainerType(void)
9338 struct WOFFHeader2 woff2_header
;
9339 struct WOFFHeader woff_header
;
9340 DWRITE_CONTAINER_TYPE type
;
9341 IDWriteFactory5
*factory
;
9343 factory
= create_factory_iid(&IID_IDWriteFactory5
);
9345 win_skip("AnalyzeContainerType() is not supported.\n");
9349 type
= IDWriteFactory5_AnalyzeContainerType(factory
, NULL
, 0);
9350 ok(type
== DWRITE_CONTAINER_TYPE_UNKNOWN
, "Unexpected container type %u.\n", type
);
9352 type
= IDWriteFactory5_AnalyzeContainerType(factory
, (void const *)0xdeadbeef, 0);
9353 ok(type
== DWRITE_CONTAINER_TYPE_UNKNOWN
, "Unexpected container type %u.\n", type
);
9355 memset(&woff_header
, 0xff, sizeof(woff_header
));
9356 woff_header
.signature
= GET_LE_DWORD(MS_WOFF_TAG
);
9357 woff_header
.length
= 0;
9358 type
= IDWriteFactory5_AnalyzeContainerType(factory
, &woff_header
, sizeof(woff_header
));
9359 ok(type
== DWRITE_CONTAINER_TYPE_WOFF
, "Unexpected container type %u.\n", type
);
9361 memset(&woff_header
, 0xff, sizeof(woff_header
));
9362 woff_header
.signature
= GET_LE_DWORD(MS_WOFF_TAG
);
9363 type
= IDWriteFactory5_AnalyzeContainerType(factory
, &woff_header
, sizeof(woff_header
.signature
));
9364 ok(type
== DWRITE_CONTAINER_TYPE_WOFF
, "Unexpected container type %u.\n", type
);
9366 memset(&woff_header
, 0xff, sizeof(woff_header
));
9367 woff_header
.signature
= GET_LE_DWORD(MS_WOFF_TAG
);
9368 type
= IDWriteFactory5_AnalyzeContainerType(factory
, &woff_header
, sizeof(woff_header
.signature
) - 1);
9369 ok(type
== DWRITE_CONTAINER_TYPE_UNKNOWN
, "Unexpected container type %u.\n", type
);
9371 memset(&woff2_header
, 0xff, sizeof(woff2_header
));
9372 woff2_header
.signature
= GET_LE_DWORD(MS_WOF2_TAG
);
9373 type
= IDWriteFactory5_AnalyzeContainerType(factory
, &woff2_header
, sizeof(woff2_header
));
9374 ok(type
== DWRITE_CONTAINER_TYPE_WOFF2
, "Unexpected container type %u.\n", type
);
9376 memset(&woff2_header
, 0xff, sizeof(woff2_header
));
9377 woff2_header
.signature
= GET_LE_DWORD(MS_WOF2_TAG
);
9378 type
= IDWriteFactory5_AnalyzeContainerType(factory
, &woff2_header
, sizeof(woff2_header
.signature
));
9379 ok(type
== DWRITE_CONTAINER_TYPE_WOFF2
, "Unexpected container type %u.\n", type
);
9381 memset(&woff2_header
, 0xff, sizeof(woff2_header
));
9382 woff2_header
.signature
= GET_LE_DWORD(MS_WOF2_TAG
);
9383 type
= IDWriteFactory5_AnalyzeContainerType(factory
, &woff2_header
, sizeof(woff2_header
.signature
) - 1);
9384 ok(type
== DWRITE_CONTAINER_TYPE_UNKNOWN
, "Unexpected container type %u.\n", type
);
9386 IDWriteFactory5_Release(factory
);
9389 static void test_fontsetbuilder(void)
9391 IDWriteFontFaceReference
*ref
, *ref2
, *ref3
;
9392 IDWriteFontCollection1
*collection
;
9393 IDWriteFontSetBuilder1
*builder1
;
9394 IDWriteFontSetBuilder
*builder
;
9395 IDWriteFactory3
*factory
;
9396 UINT32 count
, i
, refcount
;
9397 IDWriteFontSet
*fontset
;
9398 IDWriteFontFile
*file
;
9402 factory
= create_factory_iid(&IID_IDWriteFactory3
);
9405 win_skip("IDWriteFontSetBuilder is not supported.\n");
9409 EXPECT_REF(factory
, 1);
9410 hr
= IDWriteFactory3_CreateFontSetBuilder(factory
, &builder
);
9411 ok(hr
== S_OK
, "Failed to create font set builder, hr %#x.\n", hr
);
9412 EXPECT_REF(factory
, 2);
9414 if (SUCCEEDED(hr
= IDWriteFontSetBuilder_QueryInterface(builder
, &IID_IDWriteFontSetBuilder1
, (void **)&builder1
)))
9416 path
= create_testfontfile(test_fontfile
);
9418 hr
= IDWriteFactory3_CreateFontFileReference(factory
, path
, NULL
, &file
);
9419 ok(hr
== S_OK
, "Unexpected hr %#x.\n",hr
);
9421 hr
= IDWriteFontSetBuilder1_AddFontFile(builder1
, file
);
9422 ok(hr
== S_OK
, "Unexpected hr %#x.\n",hr
);
9424 hr
= IDWriteFontSetBuilder1_AddFontFile(builder1
, file
);
9425 ok(hr
== S_OK
, "Unexpected hr %#x.\n",hr
);
9427 hr
= IDWriteFontSetBuilder1_CreateFontSet(builder1
, &fontset
);
9428 ok(hr
== S_OK
, "Unexpected hr %#x.\n",hr
);
9430 /* No attempt to eliminate duplicates. */
9431 count
= IDWriteFontSet_GetFontCount(fontset
);
9432 ok(count
== 2, "Unexpected font count %u.\n", count
);
9434 IDWriteFontSet_Release(fontset
);
9436 IDWriteFontFile_Release(file
);
9437 IDWriteFontSetBuilder1_Release(builder1
);
9440 win_skip("IDWriteFontSetBuilder1 is not available.\n");
9441 IDWriteFontSetBuilder_Release(builder
);
9443 hr
= IDWriteFactory3_GetSystemFontCollection(factory
, FALSE
, &collection
, FALSE
);
9444 ok(hr
== S_OK
, "Failed to get system collection, hr %#x.\n", hr
);
9445 count
= IDWriteFontCollection1_GetFontFamilyCount(collection
);
9447 for (i
= 0; i
< count
; i
++) {
9448 IDWriteFontFamily1
*family
;
9449 UINT32 j
, fontcount
;
9452 hr
= IDWriteFontCollection1_GetFontFamily(collection
, i
, &family
);
9453 ok(hr
== S_OK
, "Failed to get family, hr %#x.\n", hr
);
9455 fontcount
= IDWriteFontFamily1_GetFontCount(family
);
9456 for (j
= 0; j
< fontcount
; ++j
)
9458 IDWriteFontSet
*fontset
;
9459 UINT32 setcount
, id
;
9461 hr
= IDWriteFontFamily1_GetFont(family
, j
, &font
);
9462 ok(hr
== S_OK
, "Failed to get font, hr %#x.\n", hr
);
9464 /* Create a set with a single font reference, test set properties. */
9465 hr
= IDWriteFactory3_CreateFontSetBuilder(factory
, &builder
);
9466 ok(hr
== S_OK
, "Failed to create font set builder, hr %#x.\n", hr
);
9468 hr
= IDWriteFont3_GetFontFaceReference(font
, &ref
);
9469 ok(hr
== S_OK
, "Failed to get fontface reference, hr %#x.\n", hr
);
9472 hr
= IDWriteFontSetBuilder_AddFontFaceReference(builder
, ref
);
9473 ok(hr
== S_OK
, "Failed to add fontface reference, hr %#x.\n", hr
);
9476 hr
= IDWriteFontSetBuilder_CreateFontSet(builder
, &fontset
);
9477 ok(hr
== S_OK
, "Failed to create a font set, hr %#x.\n", hr
);
9479 setcount
= IDWriteFontSet_GetFontCount(fontset
);
9480 ok(setcount
== 1, "Unexpected font count %u.\n", setcount
);
9482 ref2
= (void *)0xdeadbeef;
9483 hr
= IDWriteFontSet_GetFontFaceReference(fontset
, setcount
, &ref2
);
9484 ok(hr
== E_INVALIDARG
, "Unexpected hr %#x.\n", hr
);
9485 ok(!ref2
, "Unexpected pointer.\n");
9488 hr
= IDWriteFontSet_GetFontFaceReference(fontset
, 0, &ref2
);
9489 ok(hr
== S_OK
, "Failed to get font face reference, hr %#x.\n", hr
);
9490 ok(ref2
!= ref
, "Unexpected reference.\n");
9493 hr
= IDWriteFontSet_GetFontFaceReference(fontset
, 0, &ref3
);
9494 ok(hr
== S_OK
, "Failed to get font face reference, hr %#x.\n", hr
);
9495 ok(ref2
!= ref3
, "Unexpected reference.\n");
9497 IDWriteFontFaceReference_Release(ref3
);
9498 IDWriteFontFaceReference_Release(ref2
);
9500 for (id
= DWRITE_FONT_PROPERTY_ID_FAMILY_NAME
; id
< DWRITE_FONT_PROPERTY_ID_TOTAL
; ++id
)
9502 IDWriteLocalizedStrings
*values
;
9503 WCHAR buffW
[255], buff2W
[255];
9504 UINT32 c
, ivalue
= 0;
9505 BOOL exists
= FALSE
;
9507 hr
= IDWriteFontSet_GetPropertyValues(fontset
, 0, id
, &exists
, &values
);
9509 ok(hr
== S_OK
, "Failed to get property value, hr %#x.\n", hr
);
9516 case DWRITE_FONT_PROPERTY_ID_WEIGHT
:
9517 ivalue
= IDWriteFont3_GetWeight(font
);
9519 case DWRITE_FONT_PROPERTY_ID_STRETCH
:
9520 ivalue
= IDWriteFont3_GetStretch(font
);
9522 case DWRITE_FONT_PROPERTY_ID_STYLE
:
9523 ivalue
= IDWriteFont3_GetStyle(font
);
9531 case DWRITE_FONT_PROPERTY_ID_WEIGHT
:
9532 case DWRITE_FONT_PROPERTY_ID_STRETCH
:
9533 case DWRITE_FONT_PROPERTY_ID_STYLE
:
9534 c
= IDWriteLocalizedStrings_GetCount(values
);
9535 ok(c
== 1, "Unexpected string count %u.\n", c
);
9538 hr
= IDWriteLocalizedStrings_GetLocaleName(values
, 0, buffW
, ARRAY_SIZE(buffW
));
9539 ok(hr
== S_OK
, "Failed to get locale name, hr %#x.\n", hr
);
9540 ok(!*buffW
, "Unexpected locale %s.\n", wine_dbgstr_w(buffW
));
9543 hr
= IDWriteLocalizedStrings_GetString(values
, 0, buff2W
, ARRAY_SIZE(buff2W
));
9544 ok(hr
== S_OK
, "Failed to get property string, hr %#x.\n", hr
);
9546 wsprintfW(buffW
, L
"%u", ivalue
);
9547 ok(!lstrcmpW(buffW
, buff2W
), "Unexpected property value %s, expected %s.\n", wine_dbgstr_w(buff2W
),
9548 wine_dbgstr_w(buffW
));
9554 IDWriteLocalizedStrings_Release(values
);
9557 IDWriteFontSet_Release(fontset
);
9558 IDWriteFontFaceReference_Release(ref
);
9559 IDWriteFontSetBuilder_Release(builder
);
9561 IDWriteFont3_Release(font
);
9564 IDWriteFontFamily1_Release(family
);
9567 IDWriteFontCollection1_Release(collection
);
9569 refcount
= IDWriteFactory3_Release(factory
);
9570 ok(!refcount
, "Factory not released, %u.\n", refcount
);
9573 static void test_font_resource(void)
9575 IDWriteFontFaceReference1
*reference
, *reference2
;
9576 IDWriteFontResource
*resource
, *resource2
;
9577 IDWriteFontFile
*fontfile
, *fontfile2
;
9578 DWRITE_FONT_AXIS_VALUE axis_values
[2];
9579 IDWriteFontFace5
*fontface5
;
9580 IDWriteFontFace
*fontface
;
9581 IDWriteFactory6
*factory
;
9582 UINT32 count
, index
;
9587 if (!(factory
= create_factory_iid(&IID_IDWriteFactory6
)))
9589 win_skip("IDWriteFactory6 is not supported.\n");
9593 fontface
= create_fontface((IDWriteFactory
*)factory
);
9596 hr
= IDWriteFontFace_GetFiles(fontface
, &count
, &fontfile
);
9597 ok(hr
== S_OK
, "Failed to get file object, hr %#x.\n", hr
);
9599 hr
= IDWriteFactory6_CreateFontResource(factory
, fontfile
, 0, &resource
);
9600 ok(hr
== S_OK
, "Failed to create font resource, hr %#x.\n", hr
);
9602 hr
= IDWriteFactory6_CreateFontResource(factory
, fontfile
, 0, &resource2
);
9603 ok(hr
== S_OK
, "Failed to create font resource, hr %#x.\n", hr
);
9604 ok(resource
!= resource2
, "Unexpected instance.\n");
9605 IDWriteFontResource_Release(resource2
);
9607 hr
= IDWriteFontResource_GetFontFile(resource
, &fontfile2
);
9608 ok(hr
== S_OK
, "Failed to get font file, hr %#x.\n", hr
);
9609 ok(fontfile2
== fontfile
, "Unexpected file instance.\n");
9610 IDWriteFontFile_Release(fontfile2
);
9612 index
= IDWriteFontResource_GetFontFaceIndex(resource
);
9613 ok(!index
, "Unexpected index %u.\n", index
);
9615 /* Specify axis value, font has no variations. */
9616 axis_values
[0].axisTag
= DWRITE_FONT_AXIS_TAG_WEIGHT
;
9617 axis_values
[0].value
= 400.0f
;
9618 hr
= IDWriteFontResource_CreateFontFaceReference(resource
, DWRITE_FONT_SIMULATIONS_NONE
, axis_values
, 1, &reference
);
9619 ok(hr
== S_OK
, "Failed to create reference object, hr %#x.\n", hr
);
9621 count
= IDWriteFontFaceReference1_GetFontAxisValueCount(reference
);
9622 ok(count
== 1, "Unexpected axis value count.\n");
9624 IDWriteFontFaceReference1_Release(reference
);
9626 hr
= IDWriteFactory6_CreateFontFaceReference(factory
, fontfile
, 0, DWRITE_FONT_SIMULATIONS_NONE
, axis_values
, 1,
9628 count
= IDWriteFontFaceReference1_GetFontAxisValueCount(reference
);
9629 ok(count
== 1, "Unexpected axis value count.\n");
9630 IDWriteFontFaceReference1_Release(reference
);
9632 EXPECT_REF(resource
, 1);
9633 hr
= IDWriteFontResource_CreateFontFaceReference(resource
, DWRITE_FONT_SIMULATIONS_NONE
, NULL
, 0, &reference
);
9634 ok(hr
== S_OK
, "Failed to create reference object, hr %#x.\n", hr
);
9635 EXPECT_REF(resource
, 1);
9637 hr
= IDWriteFontResource_CreateFontFaceReference(resource
, DWRITE_FONT_SIMULATIONS_NONE
, NULL
, 0, &reference2
);
9638 ok(hr
== S_OK
, "Failed to create reference object, hr %#x.\n", hr
);
9639 ok(reference
!= reference2
, "Unexpected reference instance.\n");
9640 IDWriteFontFaceReference1_Release(reference2
);
9641 IDWriteFontFaceReference1_Release(reference
);
9643 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace5
, (void **)&fontface5
);
9644 ok(hr
== S_OK
, "Failed to get interface, hr %#x.\n", hr
);
9646 hr
= IDWriteFontFace5_GetFontResource(fontface5
, &resource2
);
9647 ok(hr
== S_OK
, "Failed to get font resource, hr %#x.\n", hr
);
9648 ok(resource
!= resource2
, "Unexpected resource instance.\n");
9649 IDWriteFontResource_Release(resource
);
9651 hr
= IDWriteFontFace5_GetFontResource(fontface5
, &resource
);
9652 ok(hr
== S_OK
, "Failed to get font resource, hr %#x.\n", hr
);
9653 ok(resource
!= resource2
, "Unexpected resource instance.\n");
9654 EXPECT_REF(resource
, 1);
9655 IDWriteFontResource_Release(resource
);
9656 IDWriteFontResource_Release(resource2
);
9658 IDWriteFontFace5_Release(fontface5
);
9660 /* Reference equality regarding set axis values. */
9661 axis_values
[0].axisTag
= DWRITE_FONT_AXIS_TAG_WEIGHT
;
9662 axis_values
[0].value
= 400.0f
;
9663 axis_values
[1].axisTag
= DWRITE_FONT_AXIS_TAG_ITALIC
;
9664 axis_values
[1].value
= 1.0f
;
9665 hr
= IDWriteFactory6_CreateFontFaceReference(factory
, fontfile
, 0, DWRITE_FONT_SIMULATIONS_NONE
, axis_values
, 2,
9667 count
= IDWriteFontFaceReference1_GetFontAxisValueCount(reference
);
9668 ok(count
== 2, "Unexpected axis value count.\n");
9670 hr
= IDWriteFactory6_CreateFontFaceReference(factory
, fontfile
, 0, DWRITE_FONT_SIMULATIONS_NONE
, NULL
, 0,
9672 count
= IDWriteFontFaceReference1_GetFontAxisValueCount(reference2
);
9673 ok(!count
, "Unexpected axis value count.\n");
9675 ret
= IDWriteFontFaceReference1_Equals(reference
, (IDWriteFontFaceReference
*)reference2
);
9676 ok(!ret
, "Unexpected result.\n");
9677 IDWriteFontFaceReference1_Release(reference2
);
9679 /* Different values order. */
9680 axis_values
[0].axisTag
= DWRITE_FONT_AXIS_TAG_ITALIC
;
9681 axis_values
[0].value
= 1.0f
;
9682 axis_values
[1].axisTag
= DWRITE_FONT_AXIS_TAG_WEIGHT
;
9683 axis_values
[1].value
= 400.0f
;
9684 hr
= IDWriteFactory6_CreateFontFaceReference(factory
, fontfile
, 0, DWRITE_FONT_SIMULATIONS_NONE
, axis_values
, 2,
9686 count
= IDWriteFontFaceReference1_GetFontAxisValueCount(reference2
);
9687 ok(count
== 2, "Unexpected axis value count.\n");
9689 ret
= IDWriteFontFaceReference1_Equals(reference
, (IDWriteFontFaceReference
*)reference2
);
9690 ok(!ret
, "Unexpected result.\n");
9691 IDWriteFontFaceReference1_Release(reference2
);
9693 /* Different axis values. */
9694 axis_values
[0].axisTag
= DWRITE_FONT_AXIS_TAG_ITALIC
;
9695 axis_values
[0].value
= 1.0f
;
9696 axis_values
[1].axisTag
= DWRITE_FONT_AXIS_TAG_WEIGHT
;
9697 axis_values
[1].value
= 401.0f
;
9698 hr
= IDWriteFactory6_CreateFontFaceReference(factory
, fontfile
, 0, DWRITE_FONT_SIMULATIONS_NONE
, axis_values
, 2,
9700 count
= IDWriteFontFaceReference1_GetFontAxisValueCount(reference2
);
9701 ok(count
== 2, "Unexpected axis value count.\n");
9703 ret
= IDWriteFontFaceReference1_Equals(reference
, (IDWriteFontFaceReference
*)reference2
);
9704 ok(!ret
, "Unexpected result.\n");
9705 IDWriteFontFaceReference1_Release(reference2
);
9707 memset(axis_values
, 0, sizeof(axis_values
));
9708 hr
= IDWriteFontFaceReference1_GetFontAxisValues(reference
, axis_values
, 1);
9709 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "Unexpected hr %#x.\n", hr
);
9710 ok(!axis_values
[0].axisTag
, "Unexpected axis tag.\n");
9712 memset(axis_values
, 0, sizeof(axis_values
));
9713 hr
= IDWriteFontFaceReference1_GetFontAxisValues(reference
, axis_values
, 2);
9714 ok(hr
== S_OK
, "Failed to get axis values, hr %#x.\n", hr
);
9715 ok(axis_values
[0].axisTag
== DWRITE_FONT_AXIS_TAG_WEIGHT
, "Unexpected axis tag.\n");
9717 hr
= IDWriteFontFaceReference1_CreateFontFace(reference
, &fontface5
);
9718 ok(hr
== S_OK
, "Failed to create a font face, hr %#x.\n", hr
);
9719 IDWriteFontFace5_Release(fontface5
);
9721 IDWriteFontFaceReference1_Release(reference
);
9723 IDWriteFontFile_Release(fontfile
);
9725 IDWriteFontFace_Release(fontface
);
9726 ref
= IDWriteFactory6_Release(factory
);
9727 ok(ref
== 0, "Factory wasn't released, %u.\n", ref
);
9730 static BOOL
get_expected_is_color(IDWriteFontFace2
*fontface
)
9738 hr
= IDWriteFontFace2_TryGetFontTable(fontface
, MS_CPAL_TAG
, (const void **)&data
, &size
, &context
, &exists
);
9739 ok(hr
== S_OK
, "Unexpected hr %#x.\n", hr
);
9741 IDWriteFontFace2_ReleaseFontTable(fontface
, context
);
9745 hr
= IDWriteFontFace2_TryGetFontTable(fontface
, MS_COLR_TAG
, (const void **)&data
, &size
, &context
, &exists
);
9746 ok(hr
== S_OK
, "Unexpected hr %#x.\n", hr
);
9748 IDWriteFontFace2_ReleaseFontTable(fontface
, context
);
9754 static void test_IsColorFont(void)
9756 IDWriteFontCollection
*collection
;
9757 IDWriteFactory2
*factory
;
9762 factory
= create_factory_iid(&IID_IDWriteFactory2
);
9766 win_skip("IsColorFont() is not supported.\n");
9770 hr
= IDWriteFactory2_GetSystemFontCollection(factory
, &collection
, FALSE
);
9771 ok(hr
== S_OK
, "Failed to get font collection, hr %#x.\n", hr
);
9773 count
= IDWriteFontCollection_GetFontFamilyCount(collection
);
9774 for (i
= 0; i
< count
; ++i
)
9776 IDWriteLocalizedStrings
*names
;
9777 IDWriteFontFamily
*family
;
9778 UINT32 font_count
, j
;
9781 hr
= IDWriteFontCollection_GetFontFamily(collection
, i
, &family
);
9782 ok(hr
== S_OK
, "Failed to get family, hr %#x.\n", hr
);
9784 hr
= IDWriteFontFamily_GetFamilyNames(family
, &names
);
9785 ok(hr
== S_OK
, "Failed to get names, hr %#x.\n", hr
);
9786 get_enus_string(names
, nameW
, ARRAY_SIZE(nameW
));
9787 IDWriteLocalizedStrings_Release(names
);
9789 font_count
= IDWriteFontFamily_GetFontCount(family
);
9791 for (j
= 0; j
< font_count
; ++j
)
9793 BOOL is_color_font
, is_color_face
, is_color_expected
;
9794 IDWriteFontFace2
*fontface2
;
9795 IDWriteFontFace
*fontface
;
9796 IDWriteFont2
*font2
;
9799 hr
= IDWriteFontFamily_GetFont(family
, j
, &font
);
9800 ok(hr
== S_OK
, "Failed to get font, hr %#x.\n", hr
);
9802 hr
= IDWriteFont_QueryInterface(font
, &IID_IDWriteFont2
, (void **)&font2
);
9803 ok(hr
== S_OK
, "Failed to get interface, hr %#x.\n", hr
);
9804 IDWriteFont_Release(font
);
9806 hr
= IDWriteFont2_CreateFontFace(font2
, &fontface
);
9807 ok(hr
== S_OK
, "Failed to create fontface, hr %#x.\n", hr
);
9809 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace2
, (void **)&fontface2
);
9810 ok(hr
== S_OK
, "Failed to get interface, hr %#x.\n", hr
);
9811 IDWriteFontFace_Release(fontface
);
9813 is_color_font
= IDWriteFont2_IsColorFont(font2
);
9814 is_color_face
= IDWriteFontFace2_IsColorFont(fontface2
);
9815 ok(is_color_font
== is_color_face
, "Unexpected color flag.\n");
9817 is_color_expected
= get_expected_is_color(fontface2
);
9818 ok(is_color_expected
== is_color_face
, "Unexpected is_color flag %d for %s, font %d.\n",
9819 is_color_face
, wine_dbgstr_w(nameW
), j
);
9821 IDWriteFontFace2_Release(fontface2
);
9822 IDWriteFont2_Release(font2
);
9825 IDWriteFontFamily_Release(family
);
9828 IDWriteFontCollection_Release(collection
);
9829 refcount
= IDWriteFactory2_Release(factory
);
9830 ok(refcount
== 0, "Factory not released, refcount %u.\n", refcount
);
9833 static void test_GetVerticalGlyphVariants(void)
9835 UINT16 glyphs
[1], glyph_variants
[1];
9836 IDWriteFontFace1
*fontface1
;
9837 IDWriteFontFace
*fontface
;
9838 IDWriteFactory
*factory
;
9844 factory
= create_factory();
9846 fontface
= create_fontface(factory
);
9847 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void **)&fontface1
);
9848 IDWriteFontFace_Release(fontface
);
9851 win_skip("GetVerticalGlyphVariants() is not supported.\n");
9852 IDWriteFactory_Release(factory
);
9858 hr
= IDWriteFontFace1_GetGlyphIndices(fontface1
, &ch
, 1, glyphs
);
9859 ok(hr
== S_OK
, "Failed to get glyph, hr %#x.\n", hr
);
9860 ok(!!*glyphs
, "Unexpected glyph %u.\n", glyphs
[0]);
9862 memset(glyph_variants
, 0, sizeof(glyph_variants
));
9863 hr
= IDWriteFontFace1_GetVerticalGlyphVariants(fontface1
, 1, glyphs
, glyph_variants
);
9864 ok(hr
== S_OK
, "Unexpected hr %#x.\n", hr
);
9865 ok(glyphs
[0] == glyph_variants
[0], "Unexpected glyph.\n");
9867 ret
= IDWriteFontFace1_HasVerticalGlyphVariants(fontface1
);
9868 ok(!ret
, "Unexpected flag.\n");
9870 IDWriteFontFace1_Release(fontface1
);
9871 refcount
= IDWriteFactory_Release(factory
);
9872 ok(!refcount
, "Factory not released, refcount %u.\n", refcount
);
9875 static HANDLE
get_collection_expiration_event(IDWriteFontCollection
*collection
)
9877 IDWriteFontCollection3
*collection3
;
9881 hr
= IDWriteFontCollection_QueryInterface(collection
, &IID_IDWriteFontCollection3
, (void **)&collection3
);
9882 ok(hr
== S_OK
, "Unexpected hr %#x.\n", hr
);
9883 event
= IDWriteFontCollection3_GetExpirationEvent(collection3
);
9884 IDWriteFontCollection3_Release(collection3
);
9889 static void test_expiration_event(void)
9891 IDWriteFontCollection
*collection
, *collection2
;
9892 IDWriteFontCollection3
*collection3
;
9893 IDWriteFactory
*factory
, *factory2
;
9894 unsigned int refcount
;
9895 HANDLE event
, event2
;
9898 factory
= create_factory();
9900 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &collection
, FALSE
);
9901 ok(hr
== S_OK
, "Unexpected hr %#x.\n", hr
);
9903 hr
= IDWriteFontCollection_QueryInterface(collection
, &IID_IDWriteFontCollection3
, (void **)&collection3
);
9906 win_skip("Expiration events are not supported.\n");
9907 IDWriteFontCollection_Release(collection
);
9908 IDWriteFactory_Release(factory
);
9911 IDWriteFontCollection3_Release(collection3
);
9913 event
= get_collection_expiration_event(collection
);
9915 ok(!!event
, "Unexpected event handle.\n");
9917 /* Compare handles with another isolated factory. */
9918 factory2
= create_factory();
9920 hr
= IDWriteFactory_GetSystemFontCollection(factory2
, &collection2
, FALSE
);
9921 ok(hr
== S_OK
, "Unexpected hr %#x.\n", hr
);
9922 event2
= get_collection_expiration_event(collection2
);
9924 ok(!!event2
, "Unexpected event handle.\n");
9925 ok(event
!= event2
, "Unexpected event handle.\n");
9927 IDWriteFontCollection_Release(collection2
);
9929 IDWriteFontCollection_Release(collection
);
9931 refcount
= IDWriteFactory_Release(factory2
);
9932 ok(!refcount
, "Unexpected factory refcount %u.\n", refcount
);
9933 refcount
= IDWriteFactory_Release(factory
);
9934 ok(!refcount
, "Unexpected factory refcount %u.\n", refcount
);
9937 static void test_family_font_set(void)
9939 IDWriteFontCollection
*collection
;
9940 IDWriteFontFamily2
*family2
;
9941 IDWriteFontFamily
*family
;
9942 IDWriteFactory
*factory
;
9943 unsigned int refcount
;
9944 IDWriteFontSet1
*fontset
, *fontset2
;
9947 factory
= create_factory();
9949 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &collection
, FALSE
);
9950 ok(hr
== S_OK
, "Unexpected hr %#x.\n", hr
);
9952 hr
= IDWriteFontCollection_GetFontFamily(collection
, 0, &family
);
9953 ok(hr
== S_OK
, "Unexpected hr %#x.\n", hr
);
9955 if (SUCCEEDED(IDWriteFontFamily_QueryInterface(family
, &IID_IDWriteFontFamily2
, (void **)&family2
)))
9957 hr
= IDWriteFontFamily2_GetFontSet(family2
, &fontset
);
9958 ok(hr
== S_OK
, "Unexpected hr %#x.\n", hr
);
9959 hr
= IDWriteFontFamily2_GetFontSet(family2
, &fontset2
);
9960 ok(hr
== S_OK
, "Unexpected hr %#x.\n", hr
);
9961 ok(fontset
!= fontset2
, "Unexpected fontset instance.\n");
9962 IDWriteFontSet1_Release(fontset2
);
9963 IDWriteFontSet1_Release(fontset
);
9965 IDWriteFontFamily2_Release(family2
);
9968 win_skip("IDWriteFontFamily2 is not supported.\n");
9970 IDWriteFontFamily_Release(family
);
9971 IDWriteFontCollection_Release(collection
);
9973 refcount
= IDWriteFactory_Release(factory
);
9974 ok(!refcount
, "Unexpected factory refcount %u.\n", refcount
);
9979 IDWriteFactory
*factory
;
9981 if (!(factory
= create_factory())) {
9982 win_skip("failed to create factory\n");
9986 test_object_lifetime();
9987 test_CreateFontFromLOGFONT();
9988 test_CreateBitmapRenderTarget();
9989 test_GetFontFamily();
9990 test_GetFamilyNames();
9991 test_CreateFontFace();
9993 test_system_fontcollection();
9994 test_ConvertFontFaceToLOGFONT();
9995 test_CustomFontCollection();
9996 test_CreateCustomFontFileReference();
9997 test_CreateFontFileReference();
9998 test_shared_isolated();
9999 test_GetUnicodeRanges();
10000 test_GetFontFromFontFace();
10001 test_GetFirstMatchingFont();
10002 test_GetMatchingFonts();
10003 test_GetInformationalStrings();
10004 test_GetGdiInterop();
10005 test_CreateFontFaceFromHdc();
10006 test_GetSimulations();
10007 test_GetFaceNames();
10008 test_TryGetFontTable();
10009 test_ConvertFontToLOGFONT();
10010 test_CreateStreamFromKey();
10011 test_ReadFileFragment();
10012 test_GetDesignGlyphMetrics();
10013 test_GetDesignGlyphAdvances();
10014 test_IsMonospacedFont();
10015 test_GetGlyphRunOutline();
10016 test_GetEudcFontCollection();
10017 test_GetCaretMetrics();
10018 test_GetGlyphCount();
10019 test_GetKerningPairAdjustments();
10020 test_CreateRenderingParams();
10021 test_CreateGlyphRunAnalysis();
10022 test_GetGdiCompatibleMetrics();
10024 test_GetGdiCompatibleGlyphAdvances();
10025 test_GetRecommendedRenderingMode();
10026 test_GetAlphaBlendParams();
10027 test_CreateAlphaTexture();
10028 test_IsSymbolFont();
10029 test_GetPaletteEntries();
10030 test_TranslateColorGlyphRun();
10031 test_HasCharacter();
10032 test_CreateFontFaceReference();
10033 test_GetFontSignature();
10034 test_font_properties();
10035 test_HasVerticalGlyphVariants();
10036 test_HasKerningPairs();
10037 test_ComputeGlyphOrigins();
10038 test_inmemory_file_loader();
10039 test_GetGlyphImageFormats();
10040 test_CreateCustomRenderingParams();
10041 test_localfontfileloader();
10042 test_AnalyzeContainerType();
10043 test_fontsetbuilder();
10044 test_font_resource();
10045 test_IsColorFont();
10046 test_GetVerticalGlyphVariants();
10047 test_expiration_event();
10048 test_family_font_set();
10050 IDWriteFactory_Release(factory
);