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/test.h"
35 #define MS_CMAP_TAG DWRITE_MAKE_OPENTYPE_TAG('c','m','a','p')
36 #define MS_VDMX_TAG DWRITE_MAKE_OPENTYPE_TAG('V','D','M','X')
37 #define MS_GASP_TAG DWRITE_MAKE_OPENTYPE_TAG('g','a','s','p')
38 #define MS_CPAL_TAG DWRITE_MAKE_OPENTYPE_TAG('C','P','A','L')
39 #define MS_OS2_TAG DWRITE_MAKE_OPENTYPE_TAG('O','S','/','2')
40 #define MS_HEAD_TAG DWRITE_MAKE_OPENTYPE_TAG('h','e','a','d')
41 #define MS_HHEA_TAG DWRITE_MAKE_OPENTYPE_TAG('h','h','e','a')
42 #define MS_POST_TAG DWRITE_MAKE_OPENTYPE_TAG('p','o','s','t')
43 #define MS_GSUB_TAG DWRITE_MAKE_OPENTYPE_TAG('G','S','U','B')
44 #define MS_KERN_TAG DWRITE_MAKE_OPENTYPE_TAG('k','e','r','n')
45 #define MS_GLYF_TAG DWRITE_MAKE_OPENTYPE_TAG('g','l','y','f')
46 #define MS_CFF__TAG DWRITE_MAKE_OPENTYPE_TAG('C','F','F',' ')
47 #define MS_CFF2_TAG DWRITE_MAKE_OPENTYPE_TAG('C','F','F','2')
48 #define MS_COLR_TAG DWRITE_MAKE_OPENTYPE_TAG('C','O','L','R')
49 #define MS_SVG__TAG DWRITE_MAKE_OPENTYPE_TAG('S','V','G',' ')
50 #define MS_SBIX_TAG DWRITE_MAKE_OPENTYPE_TAG('s','b','i','x')
51 #define MS_MAXP_TAG DWRITE_MAKE_OPENTYPE_TAG('m','a','x','p')
52 #define MS_CBLC_TAG DWRITE_MAKE_OPENTYPE_TAG('C','B','L','C')
55 #define MS_PNG__TAG DWRITE_MAKE_OPENTYPE_TAG('p','n','g',' ')
56 #define MS_JPG__TAG DWRITE_MAKE_OPENTYPE_TAG('j','p','g',' ')
57 #define MS_TIFF_TAG DWRITE_MAKE_OPENTYPE_TAG('t','i','f','f')
59 #define MS_WOFF_TAG DWRITE_MAKE_OPENTYPE_TAG('w','O','F','F')
60 #define MS_WOF2_TAG DWRITE_MAKE_OPENTYPE_TAG('w','O','F','2')
62 #ifdef WORDS_BIGENDIAN
63 #define GET_BE_WORD(x) (x)
64 #define GET_BE_DWORD(x) (x)
65 #define GET_LE_WORD(x) RtlUshortByteSwap(x)
66 #define GET_LE_DWORD(x) RtlUlongByteSwap(x)
68 #define GET_BE_WORD(x) RtlUshortByteSwap(x)
69 #define GET_BE_DWORD(x) RtlUlongByteSwap(x)
70 #define GET_LE_WORD(x) (x)
71 #define GET_LE_DWORD(x) (x)
74 #define DEFINE_EXPECT(func) \
75 static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
77 #define SET_EXPECT(func) \
78 do { called_ ## func = FALSE; expect_ ## func = TRUE; } while(0)
80 #define CHECK_EXPECT2(func) \
82 ok(expect_ ##func, "unexpected call " #func "\n"); \
83 called_ ## func = TRUE; \
86 #define CHECK_EXPECT(func) \
88 CHECK_EXPECT2(func); \
89 expect_ ## func = FALSE; \
92 #define CHECK_CALLED(func) \
94 ok(called_ ## func, "expected " #func "\n"); \
95 expect_ ## func = called_ ## func = FALSE; \
98 #define CLEAR_CALLED(func) \
99 expect_ ## func = called_ ## func = FALSE
101 DEFINE_EXPECT(setfillmode
);
103 #define EXPECT_REF(obj,ref) _expect_ref((IUnknown*)obj, ref, __LINE__)
104 static void _expect_ref(IUnknown
* obj
, ULONG ref
, int line
)
107 IUnknown_AddRef(obj
);
108 rc
= IUnknown_Release(obj
);
109 ok_(__FILE__
,line
)(rc
== ref
, "expected refcount %ld, got %ld\n", ref
, rc
);
112 #define EXPECT_REF_BROKEN(obj,ref,brokenref) _expect_ref_broken((IUnknown*)obj, ref, brokenref, __LINE__)
113 static void _expect_ref_broken(IUnknown
* obj
, ULONG ref
, ULONG brokenref
, int line
)
116 IUnknown_AddRef(obj
);
117 rc
= IUnknown_Release(obj
);
118 ok_(__FILE__
,line
)(rc
== ref
|| broken(rc
== brokenref
), "expected refcount %ld, got %ld\n", ref
, rc
);
121 static BOOL (WINAPI
*pGetFontRealizationInfo
)(HDC hdc
, void *);
123 static const WCHAR test_fontfile
[] = L
"wine_test_font.ttf";
125 /* PANOSE is 10 bytes in size, need to pack the structure properly */
126 #include "pshpack2.h"
143 USHORT lowestRecPPEM
;
144 SHORT direction_hint
;
146 SHORT glyphdata_format
;
149 enum TT_HEAD_MACSTYLE
151 TT_HEAD_MACSTYLE_BOLD
= 1 << 0,
152 TT_HEAD_MACSTYLE_ITALIC
= 1 << 1,
153 TT_HEAD_MACSTYLE_UNDERLINE
= 1 << 2,
154 TT_HEAD_MACSTYLE_OUTLINE
= 1 << 3,
155 TT_HEAD_MACSTYLE_SHADOW
= 1 << 4,
156 TT_HEAD_MACSTYLE_CONDENSED
= 1 << 5,
157 TT_HEAD_MACSTYLE_EXTENDED
= 1 << 6,
164 USHORT usWeightClass
;
167 SHORT ySubscriptXSize
;
168 SHORT ySubscriptYSize
;
169 SHORT ySubscriptXOffset
;
170 SHORT ySubscriptYOffset
;
171 SHORT ySuperscriptXSize
;
172 SHORT ySuperscriptYSize
;
173 SHORT ySuperscriptXOffset
;
174 SHORT ySuperscriptYOffset
;
175 SHORT yStrikeoutSize
;
176 SHORT yStrikeoutPosition
;
179 ULONG ulUnicodeRange1
;
180 ULONG ulUnicodeRange2
;
181 ULONG ulUnicodeRange3
;
182 ULONG ulUnicodeRange4
;
185 USHORT usFirstCharIndex
;
186 USHORT usLastCharIndex
;
187 /* According to the Apple spec, original version didn't have the below fields,
188 * version numbers were taken from the OpenType spec.
190 /* version 0 (TrueType 1.5) */
191 USHORT sTypoAscender
;
192 USHORT sTypoDescender
;
196 /* version 1 (TrueType 1.66) */
197 ULONG ulCodePageRange1
;
198 ULONG ulCodePageRange2
;
199 /* version 2 (OpenType 1.2) */
202 USHORT usDefaultChar
;
207 enum OS2_FSSELECTION
{
208 OS2_FSSELECTION_ITALIC
= 1 << 0,
209 OS2_FSSELECTION_UNDERSCORE
= 1 << 1,
210 OS2_FSSELECTION_NEGATIVE
= 1 << 2,
211 OS2_FSSELECTION_OUTLINED
= 1 << 3,
212 OS2_FSSELECTION_STRIKEOUT
= 1 << 4,
213 OS2_FSSELECTION_BOLD
= 1 << 5,
214 OS2_FSSELECTION_REGULAR
= 1 << 6,
215 OS2_FSSELECTION_USE_TYPO_METRICS
= 1 << 7,
216 OS2_FSSELECTION_WWS
= 1 << 8,
217 OS2_FSSELECTION_OBLIQUE
= 1 << 9
223 SHORT underlinePosition
;
224 SHORT underlineThickness
;
238 USHORT advanceWidthMax
;
239 SHORT minLeftSideBearing
;
240 SHORT minRightSideBearing
;
242 SHORT caretSlopeRise
;
246 SHORT metricDataFormat
;
247 USHORT numberOfHMetrics
;
264 OT_FeatureRecord FeatureRecord
[1];
270 WORD LookupListIndex
[1];
289 } GSUB_SingleSubstFormat1
;
296 } GSUB_SingleSubstFormat2
;
300 WORD ExtensionLookupType
;
301 DWORD ExtensionOffset
;
302 } GSUB_ExtensionPosFormat1
;
308 DWORD strikeOffset
[1];
314 DWORD glyphDataOffsets
[1];
335 DWORD indexSubTableArrayOffset
;
336 DWORD indexTablesSize
;
337 DWORD numberofIndexSubTables
;
339 sbitLineMetrics hori
;
340 sbitLineMetrics vert
;
341 WORD startGlyphIndex
;
347 } CBLCBitmapSizeTable
;
366 ULONG metaOrigLength
;
379 ULONG totalCompressedSize
;
384 ULONG metaOrigLength
;
389 struct cmap_encoding_record
400 struct cmap_encoding_record tables
[1];
403 struct cmap_segmented_coverage_group
410 struct cmap_segmented_coverage
417 struct cmap_segmented_coverage_group groups
[1];
420 struct cmap_segmented_mapping_0
432 enum opentype_cmap_table_platform
434 OPENTYPE_CMAP_TABLE_PLATFORM_WIN
= 3,
437 enum opentype_cmap_table_encoding
439 OPENTYPE_CMAP_TABLE_ENCODING_SYMBOL
= 0,
440 OPENTYPE_CMAP_TABLE_ENCODING_UNICODE_BMP
= 1,
441 OPENTYPE_CMAP_TABLE_ENCODING_UNICODE_FULL
= 10,
444 enum opentype_cmap_table_format
446 OPENTYPE_CMAP_TABLE_SEGMENT_MAPPING
= 4,
447 OPENTYPE_CMAP_TABLE_SEGMENTED_COVERAGE
= 12,
452 static void *create_factory_iid(REFIID riid
)
454 IUnknown
*factory
= NULL
;
455 DWriteCreateFactory(DWRITE_FACTORY_TYPE_ISOLATED
, riid
, &factory
);
459 static IDWriteFactory
*create_factory(void)
461 IDWriteFactory
*factory
= create_factory_iid(&IID_IDWriteFactory
);
462 ok(factory
!= NULL
, "Failed to create factory.\n");
466 static IDWriteFontFace
*create_fontface(IDWriteFactory
*factory
)
468 IDWriteGdiInterop
*interop
;
469 IDWriteFontFace
*fontface
;
474 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop
);
475 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
477 memset(&logfont
, 0, sizeof(logfont
));
478 logfont
.lfHeight
= 12;
479 logfont
.lfWidth
= 12;
480 logfont
.lfWeight
= FW_NORMAL
;
481 logfont
.lfItalic
= 1;
482 lstrcpyW(logfont
.lfFaceName
, L
"Tahoma");
484 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font
);
485 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
487 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
488 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
490 IDWriteFont_Release(font
);
491 IDWriteGdiInterop_Release(interop
);
496 static IDWriteFont
*get_font(IDWriteFactory
*factory
, const WCHAR
*name
, DWRITE_FONT_STYLE style
)
498 IDWriteFontCollection
*collection
;
499 IDWriteFontFamily
*family
;
500 IDWriteFont
*font
= NULL
;
505 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &collection
, FALSE
);
506 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
510 hr
= IDWriteFontCollection_FindFamilyName(collection
, name
, &index
, &exists
);
511 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
512 if (!exists
) goto not_found
;
514 hr
= IDWriteFontCollection_GetFontFamily(collection
, index
, &family
);
515 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
517 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
,
518 DWRITE_FONT_STRETCH_NORMAL
, style
, &font
);
519 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
521 IDWriteFontFamily_Release(family
);
523 IDWriteFontCollection_Release(collection
);
527 static IDWriteFont
*get_tahoma_instance(IDWriteFactory
*factory
, DWRITE_FONT_STYLE style
)
529 IDWriteFont
*font
= get_font(factory
, L
"Tahoma", style
);
530 ok(font
!= NULL
, "failed to get Tahoma\n");
534 static WCHAR
*create_testfontfile(const WCHAR
*filename
)
536 static WCHAR pathW
[MAX_PATH
];
542 GetTempPathW(ARRAY_SIZE(pathW
), pathW
);
543 lstrcatW(pathW
, filename
);
545 file
= CreateFileW(pathW
, GENERIC_READ
|GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, 0);
546 ok(file
!= INVALID_HANDLE_VALUE
, "file creation failed, at %s, error %ld\n", wine_dbgstr_w(pathW
),
549 res
= FindResourceA(GetModuleHandleA(NULL
), (LPCSTR
)MAKEINTRESOURCE(1), (LPCSTR
)RT_RCDATA
);
550 ok( res
!= 0, "couldn't find resource\n" );
551 ptr
= LockResource( LoadResource( GetModuleHandleA(NULL
), res
));
552 WriteFile( file
, ptr
, SizeofResource( GetModuleHandleA(NULL
), res
), &written
, NULL
);
553 ok( written
== SizeofResource( GetModuleHandleA(NULL
), res
), "couldn't write resource\n" );
559 #define DELETE_FONTFILE(filename) _delete_testfontfile(filename, __LINE__)
560 static void _delete_testfontfile(const WCHAR
*filename
, int line
)
562 BOOL ret
= DeleteFileW(filename
);
563 ok_(__FILE__
,line
)(ret
, "failed to delete file %s, error %ld\n", wine_dbgstr_w(filename
), GetLastError());
566 static void get_combined_font_name(const WCHAR
*familyW
, const WCHAR
*faceW
, WCHAR
*nameW
)
568 lstrcpyW(nameW
, familyW
);
569 lstrcatW(nameW
, L
" ");
570 lstrcatW(nameW
, faceW
);
573 static BOOL
has_face_variations(IDWriteFontFace
*fontface
)
575 IDWriteFontFace5
*fontface5
;
578 if (SUCCEEDED(IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace5
, (void **)&fontface5
))) {
579 ret
= IDWriteFontFace5_HasVariations(fontface5
);
580 IDWriteFontFace5_Release(fontface5
);
586 #define check_familymodel(a,b) _check_familymodel(a,b,__LINE__)
587 static void _check_familymodel(void *iface_ptr
, DWRITE_FONT_FAMILY_MODEL expected_model
, unsigned int line
)
589 IDWriteFontCollection2
*collection
;
590 DWRITE_FONT_FAMILY_MODEL model
;
592 if (SUCCEEDED(IUnknown_QueryInterface((IUnknown
*)iface_ptr
, &IID_IDWriteFontCollection2
, (void **)&collection
)))
594 model
= IDWriteFontCollection2_GetFontFamilyModel(collection
);
595 ok_(__FILE__
,line
)(model
== expected_model
, "Unexpected family model %d, expected %d.\n", model
, expected_model
);
596 IDWriteFontCollection2_Release(collection
);
600 struct test_fontenumerator
602 IDWriteFontFileEnumerator IDWriteFontFileEnumerator_iface
;
606 IDWriteFontFile
*font_file
;
609 static inline struct test_fontenumerator
*impl_from_IDWriteFontFileEnumerator(IDWriteFontFileEnumerator
* iface
)
611 return CONTAINING_RECORD(iface
, struct test_fontenumerator
, IDWriteFontFileEnumerator_iface
);
614 static HRESULT WINAPI
singlefontfileenumerator_QueryInterface(IDWriteFontFileEnumerator
*iface
, REFIID riid
, void **obj
)
616 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFontFileEnumerator
))
619 IDWriteFontFileEnumerator_AddRef(iface
);
622 return E_NOINTERFACE
;
625 static ULONG WINAPI
singlefontfileenumerator_AddRef(IDWriteFontFileEnumerator
*iface
)
627 struct test_fontenumerator
*This
= impl_from_IDWriteFontFileEnumerator(iface
);
628 return InterlockedIncrement(&This
->ref
);
631 static ULONG WINAPI
singlefontfileenumerator_Release(IDWriteFontFileEnumerator
*iface
)
633 struct test_fontenumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
634 ULONG ref
= InterlockedDecrement(&enumerator
->ref
);
637 IDWriteFontFile_Release(enumerator
->font_file
);
643 static HRESULT WINAPI
singlefontfileenumerator_GetCurrentFontFile(IDWriteFontFileEnumerator
*iface
, IDWriteFontFile
**font_file
)
645 struct test_fontenumerator
*This
= impl_from_IDWriteFontFileEnumerator(iface
);
646 IDWriteFontFile_AddRef(This
->font_file
);
647 *font_file
= This
->font_file
;
651 static HRESULT WINAPI
singlefontfileenumerator_MoveNext(IDWriteFontFileEnumerator
*iface
, BOOL
*current
)
653 struct test_fontenumerator
*This
= impl_from_IDWriteFontFileEnumerator(iface
);
655 if (This
->index
> 1) {
665 static const struct IDWriteFontFileEnumeratorVtbl singlefontfileenumeratorvtbl
=
667 singlefontfileenumerator_QueryInterface
,
668 singlefontfileenumerator_AddRef
,
669 singlefontfileenumerator_Release
,
670 singlefontfileenumerator_MoveNext
,
671 singlefontfileenumerator_GetCurrentFontFile
674 static HRESULT
create_enumerator(IDWriteFontFile
*font_file
, IDWriteFontFileEnumerator
**ret
)
676 struct test_fontenumerator
*enumerator
;
678 if (!(enumerator
= calloc(1, sizeof(*enumerator
))))
679 return E_OUTOFMEMORY
;
681 enumerator
->IDWriteFontFileEnumerator_iface
.lpVtbl
= &singlefontfileenumeratorvtbl
;
683 enumerator
->index
= 0;
684 enumerator
->font_file
= font_file
;
685 IDWriteFontFile_AddRef(font_file
);
687 *ret
= &enumerator
->IDWriteFontFileEnumerator_iface
;
691 struct test_fontcollectionloader
693 IDWriteFontCollectionLoader IDWriteFontFileCollectionLoader_iface
;
694 IDWriteFontFileLoader
*loader
;
697 static inline struct test_fontcollectionloader
*impl_from_IDWriteFontFileCollectionLoader(IDWriteFontCollectionLoader
* iface
)
699 return CONTAINING_RECORD(iface
, struct test_fontcollectionloader
, IDWriteFontFileCollectionLoader_iface
);
702 static HRESULT WINAPI
resourcecollectionloader_QueryInterface(IDWriteFontCollectionLoader
*iface
, REFIID riid
, void **obj
)
704 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFontCollectionLoader
))
707 IDWriteFontCollectionLoader_AddRef(iface
);
710 return E_NOINTERFACE
;
713 static ULONG WINAPI
resourcecollectionloader_AddRef(IDWriteFontCollectionLoader
*iface
)
718 static ULONG WINAPI
resourcecollectionloader_Release(IDWriteFontCollectionLoader
*iface
)
723 static HRESULT WINAPI
resourcecollectionloader_CreateEnumeratorFromKey(IDWriteFontCollectionLoader
*iface
, IDWriteFactory
*factory
,
724 const void * collectionKey
, UINT32 collectionKeySize
, IDWriteFontFileEnumerator
** fontFileEnumerator
)
726 struct test_fontcollectionloader
*This
= impl_from_IDWriteFontFileCollectionLoader(iface
);
727 IDWriteFontFile
*font_file
;
730 hr
= IDWriteFactory_CreateCustomFontFileReference(factory
, collectionKey
, collectionKeySize
, This
->loader
, &font_file
);
731 ok(hr
== S_OK
, "Failed to create custom file reference, hr %#lx.\n", hr
);
733 hr
= create_enumerator(font_file
, fontFileEnumerator
);
734 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
736 IDWriteFontFile_Release(font_file
);
740 static const struct IDWriteFontCollectionLoaderVtbl resourcecollectionloadervtbl
= {
741 resourcecollectionloader_QueryInterface
,
742 resourcecollectionloader_AddRef
,
743 resourcecollectionloader_Release
,
744 resourcecollectionloader_CreateEnumeratorFromKey
747 /* Here is a functional custom font set of interfaces */
748 struct test_fontdatastream
750 IDWriteFontFileStream IDWriteFontFileStream_iface
;
757 static inline struct test_fontdatastream
*impl_from_IDWriteFontFileStream(IDWriteFontFileStream
* iface
)
759 return CONTAINING_RECORD(iface
, struct test_fontdatastream
, IDWriteFontFileStream_iface
);
762 static HRESULT WINAPI
fontdatastream_QueryInterface(IDWriteFontFileStream
*iface
, REFIID riid
, void **obj
)
764 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFontFileStream
))
767 IDWriteFontFileStream_AddRef(iface
);
771 return E_NOINTERFACE
;
774 static ULONG WINAPI
fontdatastream_AddRef(IDWriteFontFileStream
*iface
)
776 struct test_fontdatastream
*This
= impl_from_IDWriteFontFileStream(iface
);
777 ULONG ref
= InterlockedIncrement(&This
->ref
);
781 static ULONG WINAPI
fontdatastream_Release(IDWriteFontFileStream
*iface
)
783 struct test_fontdatastream
*stream
= impl_from_IDWriteFontFileStream(iface
);
784 ULONG refcount
= InterlockedDecrement(&stream
->ref
);
792 static HRESULT WINAPI
fontdatastream_ReadFileFragment(IDWriteFontFileStream
*iface
, void const **fragment_start
, UINT64 offset
, UINT64 fragment_size
, void **fragment_context
)
794 struct test_fontdatastream
*This
= impl_from_IDWriteFontFileStream(iface
);
795 *fragment_context
= NULL
;
796 if (offset
+fragment_size
> This
->size
)
798 *fragment_start
= NULL
;
803 *fragment_start
= (BYTE
*)This
->data
+ offset
;
808 static void WINAPI
fontdatastream_ReleaseFileFragment(IDWriteFontFileStream
*iface
, void *fragment_context
)
813 static HRESULT WINAPI
fontdatastream_GetFileSize(IDWriteFontFileStream
*iface
, UINT64
*size
)
815 struct test_fontdatastream
*This
= impl_from_IDWriteFontFileStream(iface
);
820 static HRESULT WINAPI
fontdatastream_GetLastWriteTime(IDWriteFontFileStream
*iface
, UINT64
*last_writetime
)
825 static const IDWriteFontFileStreamVtbl fontdatastreamvtbl
=
827 fontdatastream_QueryInterface
,
828 fontdatastream_AddRef
,
829 fontdatastream_Release
,
830 fontdatastream_ReadFileFragment
,
831 fontdatastream_ReleaseFileFragment
,
832 fontdatastream_GetFileSize
,
833 fontdatastream_GetLastWriteTime
836 static HRESULT
create_fontdatastream(LPVOID data
, UINT size
, IDWriteFontFileStream
** iface
)
838 struct test_fontdatastream
*object
= calloc(1, sizeof(*object
));
840 return E_OUTOFMEMORY
;
842 object
->IDWriteFontFileStream_iface
.lpVtbl
= &fontdatastreamvtbl
;
847 *iface
= &object
->IDWriteFontFileStream_iface
;
852 static HRESULT WINAPI
resourcefontfileloader_QueryInterface(IDWriteFontFileLoader
*iface
, REFIID riid
, void **obj
)
854 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFontFileLoader
))
860 return E_NOINTERFACE
;
863 static ULONG WINAPI
resourcefontfileloader_AddRef(IDWriteFontFileLoader
*iface
)
868 static ULONG WINAPI
resourcefontfileloader_Release(IDWriteFontFileLoader
*iface
)
873 static HRESULT WINAPI
resourcefontfileloader_CreateStreamFromKey(IDWriteFontFileLoader
*iface
, const void *ref_key
, UINT32 key_size
,
874 IDWriteFontFileStream
**stream
)
880 mem
= LoadResource(GetModuleHandleA(NULL
), *(HRSRC
*)ref_key
);
881 ok(mem
!= NULL
, "Failed to lock font resource\n");
884 size
= SizeofResource(GetModuleHandleA(NULL
), *(HRSRC
*)ref_key
);
885 data
= LockResource(mem
);
886 return create_fontdatastream(data
, size
, stream
);
891 static const struct IDWriteFontFileLoaderVtbl resourcefontfileloadervtbl
= {
892 resourcefontfileloader_QueryInterface
,
893 resourcefontfileloader_AddRef
,
894 resourcefontfileloader_Release
,
895 resourcefontfileloader_CreateStreamFromKey
898 static IDWriteFontFileLoader rloader
= { &resourcefontfileloadervtbl
};
900 static D2D1_POINT_2F g_startpoints
[2];
901 static int g_startpoint_count
;
903 static HRESULT WINAPI
test_geometrysink_QueryInterface(ID2D1SimplifiedGeometrySink
*iface
, REFIID riid
, void **ret
)
905 if (IsEqualIID(riid
, &IID_ID2D1SimplifiedGeometrySink
) ||
906 IsEqualIID(riid
, &IID_IUnknown
))
909 ID2D1SimplifiedGeometrySink_AddRef(iface
);
914 return E_NOINTERFACE
;
917 static ULONG WINAPI
test_geometrysink_AddRef(ID2D1SimplifiedGeometrySink
*iface
)
922 static ULONG WINAPI
test_geometrysink_Release(ID2D1SimplifiedGeometrySink
*iface
)
927 static void WINAPI
test_geometrysink_SetFillMode(ID2D1SimplifiedGeometrySink
*iface
, D2D1_FILL_MODE mode
)
929 CHECK_EXPECT(setfillmode
);
930 ok(mode
== D2D1_FILL_MODE_WINDING
, "fill mode %d\n", mode
);
933 static void WINAPI
test_geometrysink_SetSegmentFlags(ID2D1SimplifiedGeometrySink
*iface
, D2D1_PATH_SEGMENT flags
)
935 ok(0, "unexpected SetSegmentFlags() - flags %d\n", flags
);
938 static void WINAPI
test_geometrysink_BeginFigure(ID2D1SimplifiedGeometrySink
*iface
,
939 D2D1_POINT_2F startPoint
, D2D1_FIGURE_BEGIN figureBegin
)
941 ok(figureBegin
== D2D1_FIGURE_BEGIN_FILLED
, "begin figure %d\n", figureBegin
);
942 if (g_startpoint_count
< ARRAY_SIZE(g_startpoints
))
943 g_startpoints
[g_startpoint_count
] = startPoint
;
944 g_startpoint_count
++;
947 static void WINAPI
test_geometrysink_AddLines(ID2D1SimplifiedGeometrySink
*iface
,
948 const D2D1_POINT_2F
*points
, UINT32 count
)
952 static void WINAPI
test_geometrysink_AddBeziers(ID2D1SimplifiedGeometrySink
*iface
,
953 const D2D1_BEZIER_SEGMENT
*beziers
, UINT32 count
)
957 static void WINAPI
test_geometrysink_EndFigure(ID2D1SimplifiedGeometrySink
*iface
, D2D1_FIGURE_END figureEnd
)
959 ok(figureEnd
== D2D1_FIGURE_END_CLOSED
, "end figure %d\n", figureEnd
);
962 static HRESULT WINAPI
test_geometrysink_Close(ID2D1SimplifiedGeometrySink
*iface
)
964 ok(0, "unexpected Close()\n");
968 static const ID2D1SimplifiedGeometrySinkVtbl test_geometrysink_vtbl
= {
969 test_geometrysink_QueryInterface
,
970 test_geometrysink_AddRef
,
971 test_geometrysink_Release
,
972 test_geometrysink_SetFillMode
,
973 test_geometrysink_SetSegmentFlags
,
974 test_geometrysink_BeginFigure
,
975 test_geometrysink_AddLines
,
976 test_geometrysink_AddBeziers
,
977 test_geometrysink_EndFigure
,
978 test_geometrysink_Close
981 static void WINAPI
test_geometrysink2_BeginFigure(ID2D1SimplifiedGeometrySink
*iface
,
982 D2D1_POINT_2F startPoint
, D2D1_FIGURE_BEGIN figureBegin
)
984 ok(0, "unexpected call\n");
987 static void WINAPI
test_geometrysink2_AddLines(ID2D1SimplifiedGeometrySink
*iface
,
988 const D2D1_POINT_2F
*points
, UINT32 count
)
990 ok(0, "unexpected call\n");
993 static void WINAPI
test_geometrysink2_AddBeziers(ID2D1SimplifiedGeometrySink
*iface
,
994 const D2D1_BEZIER_SEGMENT
*beziers
, UINT32 count
)
996 ok(0, "unexpected call\n");
999 static void WINAPI
test_geometrysink2_EndFigure(ID2D1SimplifiedGeometrySink
*iface
, D2D1_FIGURE_END figureEnd
)
1001 ok(0, "unexpected call\n");
1004 static const ID2D1SimplifiedGeometrySinkVtbl test_geometrysink2_vtbl
= {
1005 test_geometrysink_QueryInterface
,
1006 test_geometrysink_AddRef
,
1007 test_geometrysink_Release
,
1008 test_geometrysink_SetFillMode
,
1009 test_geometrysink_SetSegmentFlags
,
1010 test_geometrysink2_BeginFigure
,
1011 test_geometrysink2_AddLines
,
1012 test_geometrysink2_AddBeziers
,
1013 test_geometrysink2_EndFigure
,
1014 test_geometrysink_Close
1017 static ID2D1SimplifiedGeometrySink test_geomsink
= { &test_geometrysink_vtbl
};
1018 static ID2D1SimplifiedGeometrySink test_geomsink2
= { &test_geometrysink2_vtbl
};
1020 static void test_CreateFontFromLOGFONT(void)
1022 IDWriteGdiInterop1
*interop1
;
1023 IDWriteGdiInterop
*interop
;
1024 DWRITE_FONT_WEIGHT weight
;
1025 DWRITE_FONT_STYLE style
;
1028 LONG weights
[][2] = {
1029 {FW_NORMAL
, DWRITE_FONT_WEIGHT_NORMAL
},
1030 {FW_BOLD
, DWRITE_FONT_WEIGHT_BOLD
},
1031 { 0, DWRITE_FONT_WEIGHT_NORMAL
},
1032 { 50, DWRITE_FONT_WEIGHT_NORMAL
},
1033 {150, DWRITE_FONT_WEIGHT_NORMAL
},
1034 {250, DWRITE_FONT_WEIGHT_NORMAL
},
1035 {350, DWRITE_FONT_WEIGHT_NORMAL
},
1036 {450, DWRITE_FONT_WEIGHT_NORMAL
},
1037 {650, DWRITE_FONT_WEIGHT_BOLD
},
1038 {750, DWRITE_FONT_WEIGHT_BOLD
},
1039 {850, DWRITE_FONT_WEIGHT_BOLD
},
1040 {950, DWRITE_FONT_WEIGHT_BOLD
},
1041 {960, DWRITE_FONT_WEIGHT_BOLD
},
1043 OUTLINETEXTMETRICW otm
;
1044 IDWriteFactory
*factory
;
1054 factory
= create_factory();
1056 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop
);
1057 ok(hr
== S_OK
, "got %#lx\n", hr
);
1060 /* null out parameter crashes this call */
1061 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, NULL
, NULL
);
1063 font
= (void*)0xdeadbeef;
1064 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, NULL
, &font
);
1065 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
1066 ok(font
== NULL
, "got %p\n", font
);
1068 memset(&logfont
, 0, sizeof(logfont
));
1069 logfont
.lfHeight
= 12;
1070 logfont
.lfWidth
= 12;
1071 logfont
.lfWeight
= FW_NORMAL
;
1072 logfont
.lfItalic
= 1;
1073 lstrcpyW(logfont
.lfFaceName
, L
"Tahoma");
1075 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font
);
1076 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1078 hfont
= CreateFontIndirectW(&logfont
);
1079 hdc
= CreateCompatibleDC(0);
1080 SelectObject(hdc
, hfont
);
1082 otm
.otmSize
= sizeof(otm
);
1083 r
= GetOutlineTextMetricsW(hdc
, otm
.otmSize
, &otm
);
1084 ok(r
, "got %d\n", r
);
1086 DeleteObject(hfont
);
1089 hr
= IDWriteFont_HasCharacter(font
, 0xd800, &exists
);
1090 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1091 ok(exists
== FALSE
, "got %d\n", exists
);
1094 hr
= IDWriteFont_HasCharacter(font
, 0x20, &exists
);
1095 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1096 ok(exists
== TRUE
, "got %d\n", exists
);
1098 /* now check properties */
1099 weight
= IDWriteFont_GetWeight(font
);
1100 ok(weight
== DWRITE_FONT_WEIGHT_NORMAL
, "got %d\n", weight
);
1102 style
= IDWriteFont_GetStyle(font
);
1103 ok(style
== DWRITE_FONT_STYLE_OBLIQUE
, "got %d\n", style
);
1104 ok(otm
.otmfsSelection
& 1, "got 0x%08x\n", otm
.otmfsSelection
);
1106 ret
= IDWriteFont_IsSymbolFont(font
);
1107 ok(!ret
, "got %d\n", ret
);
1109 IDWriteFont_Release(font
);
1112 for (i
= 0; i
< ARRAY_SIZE(weights
); i
++)
1114 memset(&logfont
, 0, sizeof(logfont
));
1115 logfont
.lfHeight
= 12;
1116 logfont
.lfWidth
= 12;
1117 logfont
.lfWeight
= weights
[i
][0];
1118 lstrcpyW(logfont
.lfFaceName
, L
"Tahoma");
1120 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font
);
1121 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1123 weight
= IDWriteFont_GetWeight(font
);
1124 ok(weight
== weights
[i
][1],
1125 "%d: got %d, expected %ld\n", i
, weight
, weights
[i
][1]);
1127 IDWriteFont_Release(font
);
1130 /* weight not from enum */
1131 memset(&logfont
, 0, sizeof(logfont
));
1132 logfont
.lfHeight
= 12;
1133 logfont
.lfWidth
= 12;
1134 logfont
.lfWeight
= 550;
1135 lstrcpyW(logfont
.lfFaceName
, L
"Tahoma");
1138 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font
);
1139 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1141 weight
= IDWriteFont_GetWeight(font
);
1142 ok(weight
== DWRITE_FONT_WEIGHT_NORMAL
|| weight
== DWRITE_FONT_WEIGHT_BOLD
,
1143 "got %d\n", weight
);
1145 IDWriteFont_Release(font
);
1147 /* empty or nonexistent face name */
1148 memset(&logfont
, 0, sizeof(logfont
));
1149 logfont
.lfHeight
= 12;
1150 logfont
.lfWidth
= 12;
1151 logfont
.lfWeight
= FW_NORMAL
;
1152 lstrcpyW(logfont
.lfFaceName
, L
"Blah!");
1154 font
= (void*)0xdeadbeef;
1155 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font
);
1156 ok(hr
== DWRITE_E_NOFONT
, "Unexpected hr %#lx.\n", hr
);
1157 ok(font
== NULL
, "got %p\n", font
);
1159 /* Try with name 'Tahoma ' */
1160 memset(&logfont
, 0, sizeof(logfont
));
1161 logfont
.lfHeight
= 12;
1162 logfont
.lfWidth
= 12;
1163 logfont
.lfWeight
= FW_NORMAL
;
1164 lstrcpyW(logfont
.lfFaceName
, L
"Tahoma ");
1166 font
= (void*)0xdeadbeef;
1167 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font
);
1168 ok(hr
== DWRITE_E_NOFONT
, "Unexpected hr %#lx.\n", hr
);
1169 ok(font
== NULL
, "got %p\n", font
);
1171 /* empty string as a facename */
1172 memset(&logfont
, 0, sizeof(logfont
));
1173 logfont
.lfHeight
= 12;
1174 logfont
.lfWidth
= 12;
1175 logfont
.lfWeight
= FW_NORMAL
;
1177 font
= (void*)0xdeadbeef;
1178 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font
);
1179 ok(hr
== DWRITE_E_NOFONT
, "Unexpected hr %#lx.\n", hr
);
1180 ok(font
== NULL
, "got %p\n", font
);
1182 /* IDWriteGdiInterop1::CreateFontFromLOGFONT() */
1183 hr
= IDWriteGdiInterop_QueryInterface(interop
, &IID_IDWriteGdiInterop1
, (void**)&interop1
);
1185 memset(&logfont
, 0, sizeof(logfont
));
1186 logfont
.lfHeight
= 12;
1187 logfont
.lfWidth
= 12;
1188 logfont
.lfWeight
= FW_NORMAL
;
1189 logfont
.lfItalic
= 1;
1190 lstrcpyW(logfont
.lfFaceName
, L
"Tahoma");
1192 hr
= IDWriteGdiInterop1_CreateFontFromLOGFONT(interop1
, &logfont
, NULL
, &font
);
1193 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1195 IDWriteFont_Release(font
);
1196 IDWriteGdiInterop1_Release(interop1
);
1199 win_skip("IDWriteGdiInterop1 is not supported, skipping CreateFontFromLOGFONT() tests.\n");
1201 ref
= IDWriteGdiInterop_Release(interop
);
1202 ok(ref
== 0, "interop is not released, %lu\n", ref
);
1203 ref
= IDWriteFactory_Release(factory
);
1204 ok(ref
== 0, "factory is not released, %lu\n", ref
);
1207 static void test_CreateBitmapRenderTarget(void)
1209 IDWriteBitmapRenderTarget
*target
, *target2
;
1210 IDWriteBitmapRenderTarget1
*target1
;
1211 IDWriteRenderingParams
*params
;
1212 IDWriteGdiInterop
*interop
;
1213 IDWriteFontFace
*fontface
;
1214 IDWriteFactory
*factory
;
1215 DWRITE_GLYPH_RUN run
;
1230 factory
= create_factory();
1232 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop
);
1233 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1236 hr
= IDWriteGdiInterop_CreateBitmapRenderTarget(interop
, NULL
, 0, 0, &target
);
1237 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1239 if (0) /* crashes on native */
1240 hr
= IDWriteBitmapRenderTarget_GetSize(target
, NULL
);
1242 size
.cx
= size
.cy
= -1;
1243 hr
= IDWriteBitmapRenderTarget_GetSize(target
, &size
);
1244 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1245 ok(size
.cx
== 0, "got %ld\n", size
.cx
);
1246 ok(size
.cy
== 0, "got %ld\n", size
.cy
);
1249 hr
= IDWriteGdiInterop_CreateBitmapRenderTarget(interop
, NULL
, 0, 0, &target2
);
1250 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1251 ok(target
!= target2
, "got %p, %p\n", target2
, target
);
1252 IDWriteBitmapRenderTarget_Release(target2
);
1254 hdc
= IDWriteBitmapRenderTarget_GetMemoryDC(target
);
1255 ok(hdc
!= NULL
, "got %p\n", hdc
);
1258 ret
= GetGraphicsMode(hdc
);
1259 ok(ret
== GM_ADVANCED
, "got %d\n", ret
);
1261 hbm
= GetCurrentObject(hdc
, OBJ_BITMAP
);
1262 ok(hbm
!= NULL
, "got %p\n", hbm
);
1264 /* check DIB properties */
1265 ret
= GetObjectW(hbm
, sizeof(ds
), &ds
);
1266 ok(ret
== sizeof(BITMAP
), "got %d\n", ret
);
1267 ok(ds
.dsBm
.bmWidth
== 1, "got %d\n", ds
.dsBm
.bmWidth
);
1268 ok(ds
.dsBm
.bmHeight
== 1, "got %d\n", ds
.dsBm
.bmHeight
);
1269 ok(ds
.dsBm
.bmPlanes
== 1, "got %d\n", ds
.dsBm
.bmPlanes
);
1270 ok(ds
.dsBm
.bmBitsPixel
== 1, "got %d\n", ds
.dsBm
.bmBitsPixel
);
1271 ok(!ds
.dsBm
.bmBits
, "got %p\n", ds
.dsBm
.bmBits
);
1273 IDWriteBitmapRenderTarget_Release(target
);
1275 hbm
= GetCurrentObject(hdc
, OBJ_BITMAP
);
1276 ok(!hbm
, "got %p\n", hbm
);
1279 hr
= IDWriteGdiInterop_CreateBitmapRenderTarget(interop
, NULL
, 10, 5, &target
);
1280 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1282 hdc
= IDWriteBitmapRenderTarget_GetMemoryDC(target
);
1283 ok(hdc
!= NULL
, "got %p\n", hdc
);
1285 /* test context settings */
1286 c
= GetTextColor(hdc
);
1287 ok(c
== RGB(0, 0, 0), "got 0x%08lx\n", c
);
1288 ret
= GetBkMode(hdc
);
1289 ok(ret
== OPAQUE
, "got %d\n", ret
);
1290 c
= GetBkColor(hdc
);
1291 ok(c
== RGB(255, 255, 255), "got 0x%08lx\n", c
);
1293 hbm
= GetCurrentObject(hdc
, OBJ_BITMAP
);
1294 ok(hbm
!= NULL
, "got %p\n", hbm
);
1296 /* check DIB properties */
1297 ret
= GetObjectW(hbm
, sizeof(ds
), &ds
);
1298 ok(ret
== sizeof(ds
), "got %d\n", ret
);
1299 ok(ds
.dsBm
.bmWidth
== 10, "got %d\n", ds
.dsBm
.bmWidth
);
1300 ok(ds
.dsBm
.bmHeight
== 5, "got %d\n", ds
.dsBm
.bmHeight
);
1301 ok(ds
.dsBm
.bmPlanes
== 1, "got %d\n", ds
.dsBm
.bmPlanes
);
1302 ok(ds
.dsBm
.bmBitsPixel
== 32, "got %d\n", ds
.dsBm
.bmBitsPixel
);
1303 ok(ds
.dsBm
.bmBits
!= NULL
, "got %p\n", ds
.dsBm
.bmBits
);
1305 size
.cx
= size
.cy
= -1;
1306 hr
= IDWriteBitmapRenderTarget_GetSize(target
, &size
);
1307 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1308 ok(size
.cx
== 10, "got %ld\n", size
.cx
);
1309 ok(size
.cy
== 5, "got %ld\n", size
.cy
);
1311 /* resize to same size */
1312 hr
= IDWriteBitmapRenderTarget_Resize(target
, 10, 5);
1313 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1315 hbm2
= GetCurrentObject(hdc
, OBJ_BITMAP
);
1316 ok(hbm2
== hbm
, "got %p, %p\n", hbm2
, hbm
);
1319 hr
= IDWriteBitmapRenderTarget_Resize(target
, 5, 5);
1320 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1322 size
.cx
= size
.cy
= -1;
1323 hr
= IDWriteBitmapRenderTarget_GetSize(target
, &size
);
1324 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1325 ok(size
.cx
== 5, "got %ld\n", size
.cx
);
1326 ok(size
.cy
== 5, "got %ld\n", size
.cy
);
1328 hbm2
= GetCurrentObject(hdc
, OBJ_BITMAP
);
1329 ok(hbm2
!= hbm
, "got %p, %p\n", hbm2
, hbm
);
1331 hr
= IDWriteBitmapRenderTarget_Resize(target
, 20, 5);
1332 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1334 size
.cx
= size
.cy
= -1;
1335 hr
= IDWriteBitmapRenderTarget_GetSize(target
, &size
);
1336 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1337 ok(size
.cx
== 20, "got %ld\n", size
.cx
);
1338 ok(size
.cy
== 5, "got %ld\n", size
.cy
);
1340 hbm2
= GetCurrentObject(hdc
, OBJ_BITMAP
);
1341 ok(hbm2
!= hbm
, "got %p, %p\n", hbm2
, hbm
);
1343 hr
= IDWriteBitmapRenderTarget_Resize(target
, 1, 5);
1344 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1346 size
.cx
= size
.cy
= -1;
1347 hr
= IDWriteBitmapRenderTarget_GetSize(target
, &size
);
1348 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1349 ok(size
.cx
== 1, "got %ld\n", size
.cx
);
1350 ok(size
.cy
== 5, "got %ld\n", size
.cy
);
1352 hbm2
= GetCurrentObject(hdc
, OBJ_BITMAP
);
1353 ok(hbm2
!= hbm
, "got %p, %p\n", hbm2
, hbm
);
1355 ret
= GetObjectW(hbm2
, sizeof(ds
), &ds
);
1356 ok(ret
== sizeof(ds
), "got %d\n", ret
);
1357 ok(ds
.dsBm
.bmWidth
== 1, "got %d\n", ds
.dsBm
.bmWidth
);
1358 ok(ds
.dsBm
.bmHeight
== 5, "got %d\n", ds
.dsBm
.bmHeight
);
1359 ok(ds
.dsBm
.bmPlanes
== 1, "got %d\n", ds
.dsBm
.bmPlanes
);
1360 ok(ds
.dsBm
.bmBitsPixel
== 32, "got %d\n", ds
.dsBm
.bmBitsPixel
);
1361 ok(ds
.dsBm
.bmBits
!= NULL
, "got %p\n", ds
.dsBm
.bmBits
);
1363 /* empty rectangle */
1364 hr
= IDWriteBitmapRenderTarget_Resize(target
, 0, 5);
1365 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1367 size
.cx
= size
.cy
= -1;
1368 hr
= IDWriteBitmapRenderTarget_GetSize(target
, &size
);
1369 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1370 ok(size
.cx
== 0, "got %ld\n", size
.cx
);
1371 ok(size
.cy
== 5, "got %ld\n", size
.cy
);
1373 hbm2
= GetCurrentObject(hdc
, OBJ_BITMAP
);
1374 ok(hbm2
!= hbm
, "got %p, %p\n", hbm2
, hbm
);
1376 ret
= GetObjectW(hbm2
, sizeof(ds
), &ds
);
1377 ok(ret
== sizeof(BITMAP
), "got %d\n", ret
);
1378 ok(ds
.dsBm
.bmWidth
== 1, "got %d\n", ds
.dsBm
.bmWidth
);
1379 ok(ds
.dsBm
.bmHeight
== 1, "got %d\n", ds
.dsBm
.bmHeight
);
1380 ok(ds
.dsBm
.bmPlanes
== 1, "got %d\n", ds
.dsBm
.bmPlanes
);
1381 ok(ds
.dsBm
.bmBitsPixel
== 1, "got %d\n", ds
.dsBm
.bmBitsPixel
);
1382 ok(!ds
.dsBm
.bmBits
, "got %p\n", ds
.dsBm
.bmBits
);
1384 /* transform tests, current hdc transform is not immediately affected */
1385 if (0) /* crashes on native */
1386 hr
= IDWriteBitmapRenderTarget_GetCurrentTransform(target
, NULL
);
1388 memset(&m
, 0xcc, sizeof(m
));
1389 hr
= IDWriteBitmapRenderTarget_GetCurrentTransform(target
, &m
);
1390 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1391 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
);
1392 ok(m
.dx
== 0.0 && m
.dy
== 0.0, "got %.1f,%.1f\n", m
.dx
, m
.dy
);
1393 ret
= GetWorldTransform(hdc
, &xform
);
1394 ok(ret
, "got %d\n", ret
);
1395 ok(xform
.eM11
== 1.0 && xform
.eM22
== 1.0 && xform
.eM12
== 0.0 && xform
.eM21
== 0.0, "got wrong transform\n");
1396 ok(xform
.eDx
== 0.0 && xform
.eDy
== 0.0, "got %.1f,%.1f\n", xform
.eDx
, xform
.eDy
);
1398 memset(&m
, 0, sizeof(m
));
1399 hr
= IDWriteBitmapRenderTarget_SetCurrentTransform(target
, &m
);
1400 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1402 memset(&m
, 0xcc, sizeof(m
));
1403 hr
= IDWriteBitmapRenderTarget_GetCurrentTransform(target
, &m
);
1404 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1405 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
);
1406 ok(m
.dx
== 0.0 && m
.dy
== 0.0, "got %.1f,%.1f\n", m
.dx
, m
.dy
);
1407 ret
= GetWorldTransform(hdc
, &xform
);
1408 ok(ret
, "got %d\n", ret
);
1409 ok(xform
.eM11
== 1.0 && xform
.eM22
== 1.0 && xform
.eM12
== 0.0 && xform
.eM21
== 0.0, "got wrong transform\n");
1410 ok(xform
.eDx
== 0.0 && xform
.eDy
== 0.0, "got %.1f,%.1f\n", xform
.eDx
, xform
.eDy
);
1412 memset(&m
, 0, sizeof(m
));
1413 m
.m11
= 2.0; m
.m22
= 1.0;
1414 hr
= IDWriteBitmapRenderTarget_SetCurrentTransform(target
, &m
);
1415 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1416 ret
= GetWorldTransform(hdc
, &xform
);
1417 ok(ret
, "got %d\n", ret
);
1418 ok(xform
.eM11
== 1.0 && xform
.eM22
== 1.0 && xform
.eM12
== 0.0 && xform
.eM21
== 0.0, "got wrong transform\n");
1419 ok(xform
.eDx
== 0.0 && xform
.eDy
== 0.0, "got %.1f,%.1f\n", xform
.eDx
, xform
.eDy
);
1421 hr
= IDWriteBitmapRenderTarget_SetCurrentTransform(target
, NULL
);
1422 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1424 memset(&m
, 0xcc, sizeof(m
));
1425 hr
= IDWriteBitmapRenderTarget_GetCurrentTransform(target
, &m
);
1426 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1427 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
);
1428 ok(m
.dx
== 0.0 && m
.dy
== 0.0, "got %.1f,%.1f\n", m
.dx
, m
.dy
);
1430 /* pixels per dip */
1431 pdip
= IDWriteBitmapRenderTarget_GetPixelsPerDip(target
);
1432 ok(pdip
== 1.0, "got %.2f\n", pdip
);
1434 hr
= IDWriteBitmapRenderTarget_SetPixelsPerDip(target
, 2.0);
1435 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1437 hr
= IDWriteBitmapRenderTarget_SetPixelsPerDip(target
, -1.0);
1438 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
1440 hr
= IDWriteBitmapRenderTarget_SetPixelsPerDip(target
, 0.0);
1441 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
1443 pdip
= IDWriteBitmapRenderTarget_GetPixelsPerDip(target
);
1444 ok(pdip
== 2.0, "got %.2f\n", pdip
);
1446 hr
= IDWriteBitmapRenderTarget_QueryInterface(target
, &IID_IDWriteBitmapRenderTarget1
, (void**)&target1
);
1448 DWRITE_TEXT_ANTIALIAS_MODE mode
;
1450 mode
= IDWriteBitmapRenderTarget1_GetTextAntialiasMode(target1
);
1451 ok(mode
== DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE
, "got %d\n", mode
);
1453 hr
= IDWriteBitmapRenderTarget1_SetTextAntialiasMode(target1
, DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
+1);
1454 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
1456 mode
= IDWriteBitmapRenderTarget1_GetTextAntialiasMode(target1
);
1457 ok(mode
== DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE
, "got %d\n", mode
);
1459 hr
= IDWriteBitmapRenderTarget1_SetTextAntialiasMode(target1
, DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
);
1460 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1462 mode
= IDWriteBitmapRenderTarget1_GetTextAntialiasMode(target1
);
1463 ok(mode
== DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
, "got %d\n", mode
);
1465 IDWriteBitmapRenderTarget1_Release(target1
);
1468 win_skip("IDWriteBitmapRenderTarget1 is not supported.\n");
1470 /* DrawGlyphRun() argument validation. */
1471 hr
= IDWriteBitmapRenderTarget_Resize(target
, 16, 16);
1472 ok(hr
== S_OK
, "Failed to resize target, hr %#lx.\n", hr
);
1474 fontface
= create_fontface(factory
);
1478 hr
= IDWriteFontFace_GetGlyphIndices(fontface
, &ch
, 1, glyphs
);
1479 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1480 ok(glyphs
[0] > 0, "got %u\n", glyphs
[0]);
1481 glyphs
[1] = glyphs
[0];
1483 memset(&run
, 0, sizeof(run
));
1484 run
.fontFace
= fontface
;
1485 run
.fontEmSize
= 12.0f
;
1487 run
.glyphIndices
= glyphs
;
1489 hr
= IDWriteFactory_CreateCustomRenderingParams(factory
, 1.0f
, 0.0f
, 0.0f
, DWRITE_PIXEL_GEOMETRY_FLAT
,
1490 DWRITE_RENDERING_MODE_DEFAULT
, ¶ms
);
1491 ok(hr
== S_OK
, "Failed to create rendering params, hr %#lx.\n", hr
);
1493 hr
= IDWriteBitmapRenderTarget_DrawGlyphRun(target
, 0.0f
, 0.0f
, DWRITE_MEASURING_MODE_NATURAL
,
1494 &run
, NULL
, RGB(255, 0, 0), NULL
);
1495 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
1497 hr
= IDWriteBitmapRenderTarget_DrawGlyphRun(target
, 0.0f
, 0.0f
, DWRITE_MEASURING_MODE_GDI_NATURAL
+ 1,
1498 &run
, NULL
, RGB(255, 0, 0), NULL
);
1499 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
1501 hr
= IDWriteBitmapRenderTarget_DrawGlyphRun(target
, 0.0f
, 0.0f
, DWRITE_MEASURING_MODE_GDI_NATURAL
+ 1,
1502 &run
, params
, RGB(255, 0, 0), NULL
);
1503 ok(hr
== E_INVALIDARG
|| broken(hr
== S_OK
) /* Vista */, "Unexpected hr %#lx.\n", hr
);
1505 hr
= IDWriteBitmapRenderTarget_DrawGlyphRun(target
, 0.0f
, 0.0f
, DWRITE_MEASURING_MODE_GDI_NATURAL
,
1506 &run
, params
, RGB(255, 0, 0), NULL
);
1507 ok(hr
== S_OK
, "Failed to draw a run, hr %#lx.\n", hr
);
1509 IDWriteRenderingParams_Release(params
);
1511 /* Zero sized target returns earlier. */
1512 hr
= IDWriteBitmapRenderTarget_Resize(target
, 0, 16);
1513 ok(hr
== S_OK
, "Failed to resize target, hr %#lx.\n", hr
);
1515 hr
= IDWriteBitmapRenderTarget_DrawGlyphRun(target
, 0.0f
, 0.0f
, DWRITE_MEASURING_MODE_NATURAL
,
1516 &run
, NULL
, RGB(255, 0, 0), NULL
);
1517 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1519 hr
= IDWriteBitmapRenderTarget_DrawGlyphRun(target
, 0.0f
, 0.0f
, DWRITE_MEASURING_MODE_GDI_NATURAL
+ 1,
1520 &run
, params
, RGB(255, 0, 0), NULL
);
1521 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1523 IDWriteFontFace_Release(fontface
);
1525 ref
= IDWriteBitmapRenderTarget_Release(target
);
1526 ok(ref
== 0, "render target not released, %lu\n", ref
);
1527 ref
= IDWriteGdiInterop_Release(interop
);
1528 ok(ref
== 0, "interop not released, %lu\n", ref
);
1529 ref
= IDWriteFactory_Release(factory
);
1530 ok(ref
== 0, "factory not released, %lu\n", ref
);
1533 static void test_GetFontFamily(void)
1535 IDWriteFontCollection
*collection
, *collection2
;
1536 IDWriteFontCollection
*syscoll
;
1537 IDWriteFontCollection2
*coll2
;
1538 IDWriteFontFamily
*family
, *family2
;
1539 IDWriteFontFamily1
*family1
;
1540 IDWriteGdiInterop
*interop
;
1541 IDWriteFont
*font
, *font2
;
1542 IDWriteFactory
*factory
;
1547 factory
= create_factory();
1549 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop
);
1550 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1552 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &syscoll
, FALSE
);
1553 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1555 memset(&logfont
, 0, sizeof(logfont
));
1556 logfont
.lfHeight
= 12;
1557 logfont
.lfWidth
= 12;
1558 logfont
.lfWeight
= FW_NORMAL
;
1559 logfont
.lfItalic
= 1;
1560 lstrcpyW(logfont
.lfFaceName
, L
"Tahoma");
1562 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font
);
1563 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1565 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font2
);
1566 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1567 ok(font2
!= font
, "got %p, %p\n", font2
, font
);
1569 if (0) /* crashes on native */
1570 hr
= IDWriteFont_GetFontFamily(font
, NULL
);
1572 EXPECT_REF(font
, 1);
1573 hr
= IDWriteFont_GetFontFamily(font
, &family
);
1574 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1575 EXPECT_REF(font
, 1);
1576 EXPECT_REF(family
, 2);
1578 hr
= IDWriteFont_GetFontFamily(font
, &family2
);
1579 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1580 ok(family2
== family
, "got %p, previous %p\n", family2
, family
);
1581 EXPECT_REF(font
, 1);
1582 EXPECT_REF(family
, 3);
1583 IDWriteFontFamily_Release(family2
);
1585 hr
= IDWriteFont_QueryInterface(font
, &IID_IDWriteFontFamily
, (void**)&family2
);
1586 ok(hr
== E_NOINTERFACE
, "Unexpected hr %#lx.\n", hr
);
1587 ok(family2
== NULL
, "got %p\n", family2
);
1589 hr
= IDWriteFont_GetFontFamily(font2
, &family2
);
1590 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1591 ok(family2
!= family
, "got %p, %p\n", family2
, family
);
1594 hr
= IDWriteFontFamily_GetFontCollection(family
, &collection
);
1595 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1598 hr
= IDWriteFontFamily_GetFontCollection(family2
, &collection2
);
1599 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1600 ok(collection
== collection2
, "got %p, %p\n", collection
, collection2
);
1601 ok(collection
== syscoll
, "got %p, %p\n", collection
, syscoll
);
1603 IDWriteFont_Release(font
);
1604 IDWriteFont_Release(font2
);
1606 hr
= IDWriteFontFamily_QueryInterface(family
, &IID_IDWriteFontFamily1
, (void**)&family1
);
1608 IDWriteFontFaceReference
*ref
, *ref1
;
1609 IDWriteFontList1
*fontlist1
;
1610 IDWriteFontList2
*fontlist2
;
1611 IDWriteFontList
*fontlist
;
1612 IDWriteFont3
*font3
;
1613 IDWriteFont1
*font1
;
1615 font3
= (void*)0xdeadbeef;
1616 hr
= IDWriteFontFamily1_GetFont(family1
, ~0u, &font3
);
1617 ok(hr
== E_FAIL
, "Unexpected hr %#lx.\n", hr
);
1618 ok(font3
== NULL
, "got %p\n", font3
);
1620 hr
= IDWriteFontFamily1_GetFont(family1
, 0, &font3
);
1621 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1623 hr
= IDWriteFont3_QueryInterface(font3
, &IID_IDWriteFont
, (void**)&font
);
1624 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1625 IDWriteFont_Release(font
);
1627 hr
= IDWriteFont3_QueryInterface(font3
, &IID_IDWriteFont1
, (void**)&font1
);
1628 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1629 IDWriteFont1_Release(font1
);
1631 hr
= IDWriteFontFamily1_QueryInterface(family1
, &IID_IDWriteFontList1
, (void **)&fontlist1
);
1632 ok(hr
== S_OK
|| broken(hr
== E_NOINTERFACE
), "Failed to get interface, hr %#lx.\n", hr
);
1634 hr
= IDWriteFontFamily1_QueryInterface(family1
, &IID_IDWriteFontList
, (void **)&fontlist
);
1635 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1636 ok(fontlist
== (IDWriteFontList
*)fontlist1
, "Unexpected interface pointer.\n");
1637 ok(fontlist
!= (IDWriteFontList
*)family1
, "Unexpected interface pointer.\n");
1638 ok(fontlist
!= (IDWriteFontList
*)family
, "Unexpected interface pointer.\n");
1640 if (SUCCEEDED(IDWriteFontFamily1_QueryInterface(family1
, &IID_IDWriteFontList2
, (void **)&fontlist2
)))
1642 IDWriteFontSet1
*fontset
= NULL
, *fontset2
= NULL
;
1644 ok(fontlist
== (IDWriteFontList
*)fontlist2
, "Unexpected interface pointer.\n");
1646 hr
= IDWriteFontList2_GetFontSet(fontlist2
, &fontset
);
1647 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1649 hr
= IDWriteFontList2_GetFontSet(fontlist2
, &fontset2
);
1650 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1651 ok(fontset
!= fontset2
, "Unexpected instance.\n");
1653 IDWriteFontSet1_Release(fontset2
);
1654 IDWriteFontSet1_Release(fontset
);
1656 IDWriteFontList2_Release(fontlist2
);
1659 win_skip("IDWriteFontList2 is not supported.\n");
1661 IDWriteFontList1_Release(fontlist1
);
1662 IDWriteFontList_Release(fontlist
);
1665 hr
= IDWriteFontFamily1_QueryInterface(family1
, &IID_IDWriteFontList
, (void**)&fontlist
);
1666 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1667 IDWriteFontList_Release(fontlist
);
1669 IDWriteFont3_Release(font3
);
1671 hr
= IDWriteFontFamily1_GetFontFaceReference(family1
, 0, &ref
);
1672 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1674 hr
= IDWriteFontFamily1_GetFontFaceReference(family1
, 0, &ref1
);
1675 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1676 ok(ref
!= ref1
, "got %p, %p\n", ref
, ref1
);
1678 IDWriteFontFaceReference_Release(ref
);
1679 IDWriteFontFaceReference_Release(ref1
);
1681 IDWriteFontFamily1_Release(family1
);
1684 win_skip("IDWriteFontFamily1 is not supported.\n");
1686 /* IDWriteFontCollection2::GetFontFamily() */
1687 if (SUCCEEDED(IDWriteFontCollection_QueryInterface(syscoll
, &IID_IDWriteFontCollection2
, (void **)&coll2
)))
1689 IDWriteFontFamily2
*family2
;
1691 count
= IDWriteFontCollection2_GetFontFamilyCount(coll2
);
1692 ok(!!count
, "Unexpected family count.\n");
1694 family2
= (void *)0xdeadbeef;
1695 hr
= IDWriteFontCollection2_GetFontFamily(coll2
, count
, &family2
);
1696 ok(hr
== E_FAIL
, "Unexpected hr %#lx.\n", hr
);
1697 ok(!family2
, "Unexpected pointer.\n");
1699 hr
= IDWriteFontCollection2_GetFontFamily(coll2
, 0, &family2
);
1700 ok(hr
== S_OK
, "Failed to get family, hr %#lx.\n", hr
);
1701 IDWriteFontFamily2_Release(family2
);
1703 IDWriteFontCollection2_Release(coll2
);
1706 win_skip("IDWriteFontCollection2 is not supported.\n");
1708 IDWriteFontCollection_Release(syscoll
);
1709 IDWriteFontCollection_Release(collection2
);
1710 IDWriteFontCollection_Release(collection
);
1711 IDWriteFontFamily_Release(family2
);
1712 IDWriteFontFamily_Release(family
);
1713 IDWriteGdiInterop_Release(interop
);
1714 ref
= IDWriteFactory_Release(factory
);
1715 ok(ref
== 0, "factory not released, %lu\n", ref
);
1718 static void test_GetFamilyNames(void)
1720 IDWriteLocalizedStrings
*names
, *names2
;
1721 IDWriteFontFace3
*fontface3
;
1722 IDWriteGdiInterop
*interop
;
1723 IDWriteFontFamily
*family
;
1724 IDWriteFontFace
*fontface
;
1725 IDWriteFactory
*factory
;
1733 factory
= create_factory();
1735 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop
);
1736 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1738 memset(&logfont
, 0, sizeof(logfont
));
1739 logfont
.lfHeight
= 12;
1740 logfont
.lfWidth
= 12;
1741 logfont
.lfWeight
= FW_NORMAL
;
1742 logfont
.lfItalic
= 1;
1743 lstrcpyW(logfont
.lfFaceName
, L
"Tahoma");
1745 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font
);
1746 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1748 hr
= IDWriteFont_GetFontFamily(font
, &family
);
1749 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1751 if (0) /* crashes on native */
1752 hr
= IDWriteFontFamily_GetFamilyNames(family
, NULL
);
1754 hr
= IDWriteFontFamily_GetFamilyNames(family
, &names
);
1755 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1756 EXPECT_REF(names
, 1);
1758 hr
= IDWriteFontFamily_GetFamilyNames(family
, &names2
);
1759 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1760 EXPECT_REF(names2
, 1);
1761 ok(names
!= names2
, "got %p, was %p\n", names2
, names
);
1763 IDWriteLocalizedStrings_Release(names2
);
1765 /* GetStringLength */
1766 if (0) /* crashes on native */
1767 hr
= IDWriteLocalizedStrings_GetStringLength(names
, 0, NULL
);
1770 hr
= IDWriteLocalizedStrings_GetStringLength(names
, 10, &len
);
1771 ok(hr
== E_FAIL
, "Unexpected hr %#lx.\n", hr
);
1772 ok(len
== (UINT32
)-1, "got %u\n", len
);
1775 hr
= IDWriteLocalizedStrings_GetStringLength(names
, 0, &len
);
1776 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1777 ok(len
> 0, "got %u\n", len
);
1780 hr
= IDWriteLocalizedStrings_GetString(names
, 0, NULL
, 0);
1781 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "Unexpected hr %#lx.\n", hr
);
1783 hr
= IDWriteLocalizedStrings_GetString(names
, 10, NULL
, 0);
1784 ok(FAILED(hr
), "Unexpected hr %#lx.\n", hr
);
1787 hr
= IDWriteLocalizedStrings_GetString(names
, 0, NULL
, 100);
1790 hr
= IDWriteLocalizedStrings_GetString(names
, 10, buffer
, 100);
1791 ok(hr
== E_FAIL
, "Unexpected hr %#lx.\n", hr
);
1792 ok(buffer
[0] == 0, "got %x\n", buffer
[0]);
1795 hr
= IDWriteLocalizedStrings_GetString(names
, 0, buffer
, len
-1);
1796 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "Unexpected hr %#lx.\n", hr
);
1797 ok(buffer
[0] == 0 || broken(buffer
[0] == 'T'), "Unexpected buffer contents, %#x.\n", buffer
[0]);
1800 hr
= IDWriteLocalizedStrings_GetString(names
, 0, buffer
, len
);
1801 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "Unexpected hr %#lx.\n", hr
);
1802 ok(buffer
[0] == 0 || broken(buffer
[0] == 'T'), "Unexpected buffer contents, %#x.\n", buffer
[0]);
1805 hr
= IDWriteLocalizedStrings_GetString(names
, 0, buffer
, len
+1);
1806 ok(hr
== S_OK
, "Failed to get a string, hr %#lx.\n", hr
);
1807 ok(!lstrcmpW(buffer
, L
"Tahoma"), "Unexpected family name %s.\n", wine_dbgstr_w(buffer
));
1809 IDWriteLocalizedStrings_Release(names
);
1811 /* GetFamilyNames() on font face */
1812 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
1813 ok(hr
== S_OK
, "Failed to create fontface, hr %#lx.\n", hr
);
1815 if (SUCCEEDED(IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace3
, (void **)&fontface3
)))
1817 hr
= IDWriteFontFace3_GetFamilyNames(fontface3
, &names
);
1818 ok(hr
== S_OK
, "Failed to get family names, hr %#lx.\n", hr
);
1821 hr
= IDWriteLocalizedStrings_GetString(names
, 0, buffer
, len
+1);
1822 ok(hr
== S_OK
, "Failed to get a string, hr %#lx.\n", hr
);
1823 ok(!lstrcmpW(buffer
, L
"Tahoma"), "Unexpected family name %s.\n", wine_dbgstr_w(buffer
));
1825 IDWriteLocalizedStrings_Release(names
);
1826 IDWriteFontFace3_Release(fontface3
);
1829 win_skip("IDWriteFontFace3::GetFamilyNames() is not supported.\n");
1831 IDWriteFontFace_Release(fontface
);
1833 IDWriteFontFamily_Release(family
);
1834 IDWriteFont_Release(font
);
1835 IDWriteGdiInterop_Release(interop
);
1836 ref
= IDWriteFactory_Release(factory
);
1837 ok(ref
== 0, "factory not released, %lu\n", ref
);
1840 static void test_CreateFontFace(void)
1842 IDWriteFontFace
*fontface
, *fontface2
;
1843 IDWriteFontCollection
*collection
;
1844 DWRITE_FONT_FILE_TYPE file_type
;
1845 DWRITE_FONT_FACE_TYPE face_type
;
1846 IDWriteFontFace5
*fontface5
;
1847 IDWriteGdiInterop
*interop
;
1848 IDWriteFont
*font
, *font2
;
1849 IDWriteFontFamily
*family
;
1850 IDWriteFactory
*factory
;
1851 IDWriteFontFile
*file
;
1852 BOOL supported
, ret
;
1859 factory
= create_factory();
1861 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop
);
1862 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1864 memset(&logfont
, 0, sizeof(logfont
));
1865 logfont
.lfHeight
= 12;
1866 logfont
.lfWidth
= 12;
1867 logfont
.lfWeight
= FW_NORMAL
;
1868 logfont
.lfItalic
= 1;
1869 lstrcpyW(logfont
.lfFaceName
, L
"Tahoma");
1872 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font
);
1873 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1876 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font2
);
1877 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1878 ok(font
!= font2
, "got %p, %p\n", font
, font2
);
1880 hr
= IDWriteFont_QueryInterface(font
, &IID_IDWriteFontFace
, (void**)&fontface
);
1881 ok(hr
== E_NOINTERFACE
, "Unexpected hr %#lx.\n", hr
);
1883 if (0) /* crashes on native */
1884 hr
= IDWriteFont_CreateFontFace(font
, NULL
);
1887 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
1888 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1891 hr
= IDWriteFont_CreateFontFace(font
, &fontface2
);
1892 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1893 ok(fontface
== fontface2
, "got %p, was %p\n", fontface2
, fontface
);
1894 IDWriteFontFace_Release(fontface2
);
1897 hr
= IDWriteFont_CreateFontFace(font2
, &fontface2
);
1898 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1899 ok(fontface
== fontface2
, "got %p, was %p\n", fontface2
, fontface
);
1900 IDWriteFontFace_Release(fontface2
);
1902 IDWriteFont_Release(font2
);
1903 IDWriteFont_Release(font
);
1905 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFont
, (void**)&font
);
1906 ok(hr
== E_NOINTERFACE
|| broken(hr
== E_NOTIMPL
), "Unexpected hr %#lx.\n", hr
);
1908 IDWriteFontFace_Release(fontface
);
1909 IDWriteGdiInterop_Release(interop
);
1911 /* Create from system collection */
1912 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &collection
, FALSE
);
1913 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1915 hr
= IDWriteFontCollection_GetFontFamily(collection
, 0, &family
);
1916 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1919 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
,
1920 DWRITE_FONT_STRETCH_NORMAL
, DWRITE_FONT_STYLE_NORMAL
, &font
);
1921 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1924 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
,
1925 DWRITE_FONT_STRETCH_NORMAL
, DWRITE_FONT_STYLE_NORMAL
, &font2
);
1926 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1927 ok(font
!= font2
, "got %p, %p\n", font
, font2
);
1930 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
1931 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1934 hr
= IDWriteFont_CreateFontFace(font2
, &fontface2
);
1935 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1936 ok(fontface
== fontface2
, "got %p, was %p\n", fontface2
, fontface
);
1938 /* Trivial equality test */
1939 if (SUCCEEDED(IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace5
, (void **)&fontface5
)))
1941 ret
= IDWriteFontFace5_Equals(fontface5
, fontface2
);
1942 ok(ret
, "Unexpected result %d.\n", ret
);
1943 IDWriteFontFace5_Release(fontface5
);
1946 IDWriteFontFace_Release(fontface
);
1947 IDWriteFontFace_Release(fontface2
);
1948 IDWriteFont_Release(font2
);
1949 IDWriteFont_Release(font
);
1950 IDWriteFontFamily_Release(family
);
1951 IDWriteFontCollection_Release(collection
);
1952 ref
= IDWriteFactory_Release(factory
);
1953 ok(ref
== 0, "factory not released, %lu.\n", ref
);
1955 /* IDWriteFactory::CreateFontFace() */
1956 path
= create_testfontfile(test_fontfile
);
1957 factory
= create_factory();
1959 hr
= IDWriteFactory_CreateFontFileReference(factory
, path
, NULL
, &file
);
1960 ok(hr
== S_OK
, "Unexpected hr %#lx.\n",hr
);
1963 file_type
= DWRITE_FONT_FILE_TYPE_UNKNOWN
;
1964 face_type
= DWRITE_FONT_FACE_TYPE_CFF
;
1966 hr
= IDWriteFontFile_Analyze(file
, &supported
, &file_type
, &face_type
, &count
);
1967 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1968 ok(supported
== TRUE
, "got %i\n", supported
);
1969 ok(file_type
== DWRITE_FONT_FILE_TYPE_TRUETYPE
, "got %i\n", file_type
);
1970 ok(face_type
== DWRITE_FONT_FACE_TYPE_TRUETYPE
, "got %i\n", face_type
);
1971 ok(count
== 1, "got %i\n", count
);
1973 /* invalid simulation flags */
1974 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_CFF
, 1, &file
, 0, ~0u, &fontface
);
1975 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
1977 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_CFF
, 1, &file
, 0, 0xf, &fontface
);
1978 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
1980 /* try mismatching face type, the one that's not supported */
1981 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_CFF
, 1, &file
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &fontface
);
1982 ok(hr
== DWRITE_E_FILEFORMAT
, "Unexpected hr %#lx.\n", hr
);
1984 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_OPENTYPE_COLLECTION
, 1, &file
, 0,
1985 DWRITE_FONT_SIMULATIONS_NONE
, &fontface
);
1986 ok(hr
== DWRITE_E_FILEFORMAT
|| broken(hr
== E_FAIL
) /* < win10 */, "Unexpected hr %#lx.\n", hr
);
1988 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_RAW_CFF
, 1, &file
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &fontface
);
1990 ok(hr
== DWRITE_E_UNSUPPORTEDOPERATION
|| broken(hr
== E_INVALIDARG
) /* older versions */, "Unexpected hr %#lx.\n", hr
);
1992 fontface
= (void*)0xdeadbeef;
1993 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_TYPE1
, 1, &file
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &fontface
);
1994 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
1995 ok(fontface
== NULL
, "got %p\n", fontface
);
1997 fontface
= (void*)0xdeadbeef;
1998 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_VECTOR
, 1, &file
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &fontface
);
1999 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
2000 ok(fontface
== NULL
, "got %p\n", fontface
);
2002 fontface
= (void*)0xdeadbeef;
2003 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_BITMAP
, 1, &file
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &fontface
);
2004 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
2005 ok(fontface
== NULL
, "got %p\n", fontface
);
2008 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_UNKNOWN
, 1, &file
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &fontface
);
2010 ok(hr
== S_OK
|| broken(hr
== E_INVALIDARG
) /* < win10 */, "Unexpected hr %#lx.\n", hr
);
2012 ok(fontface
!= NULL
, "got %p\n", fontface
);
2013 face_type
= IDWriteFontFace_GetType(fontface
);
2014 ok(face_type
== DWRITE_FONT_FACE_TYPE_TRUETYPE
, "got %d\n", face_type
);
2015 IDWriteFontFace_Release(fontface
);
2018 IDWriteFontFile_Release(file
);
2019 ref
= IDWriteFactory_Release(factory
);
2020 ok(ref
== 0, "factory not released, %lu.\n", ref
);
2021 DELETE_FONTFILE(path
);
2024 static void get_expected_font_metrics(IDWriteFontFace
*fontface
, DWRITE_FONT_METRICS1
*metrics
)
2026 void *os2_context
, *head_context
, *post_context
, *hhea_context
;
2027 const TT_OS2_V2
*tt_os2
;
2028 const TT_HEAD
*tt_head
;
2029 const TT_POST
*tt_post
;
2030 const TT_HHEA
*tt_hhea
;
2035 memset(metrics
, 0, sizeof(*metrics
));
2037 hr
= IDWriteFontFace_TryGetFontTable(fontface
, MS_OS2_TAG
, (const void **)&tt_os2
, &size
, &os2_context
, &exists
);
2038 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2039 hr
= IDWriteFontFace_TryGetFontTable(fontface
, MS_HEAD_TAG
, (const void**)&tt_head
, &size
, &head_context
, &exists
);
2040 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2041 hr
= IDWriteFontFace_TryGetFontTable(fontface
, MS_HHEA_TAG
, (const void**)&tt_hhea
, &size
, &hhea_context
, &exists
);
2042 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2043 hr
= IDWriteFontFace_TryGetFontTable(fontface
, MS_POST_TAG
, (const void**)&tt_post
, &size
, &post_context
, &exists
);
2044 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2047 metrics
->designUnitsPerEm
= GET_BE_WORD(tt_head
->unitsPerEm
);
2048 metrics
->glyphBoxLeft
= GET_BE_WORD(tt_head
->xMin
);
2049 metrics
->glyphBoxTop
= GET_BE_WORD(tt_head
->yMax
);
2050 metrics
->glyphBoxRight
= GET_BE_WORD(tt_head
->xMax
);
2051 metrics
->glyphBoxBottom
= GET_BE_WORD(tt_head
->yMin
);
2055 if (GET_BE_WORD(tt_os2
->fsSelection
) & OS2_FSSELECTION_USE_TYPO_METRICS
) {
2056 SHORT descent
= GET_BE_WORD(tt_os2
->sTypoDescender
);
2057 metrics
->ascent
= GET_BE_WORD(tt_os2
->sTypoAscender
);
2058 metrics
->descent
= descent
< 0 ? -descent
: 0;
2059 metrics
->lineGap
= GET_BE_WORD(tt_os2
->sTypoLineGap
);
2060 metrics
->hasTypographicMetrics
= TRUE
;
2063 metrics
->ascent
= GET_BE_WORD(tt_os2
->usWinAscent
);
2064 /* Some fonts have usWinDescent value stored as signed short, which could be wrongly
2065 interpreted as large unsigned value. */
2066 metrics
->descent
= abs((SHORT
)GET_BE_WORD(tt_os2
->usWinDescent
));
2069 SHORT descender
= (SHORT
)GET_BE_WORD(tt_hhea
->descender
);
2072 linegap
= GET_BE_WORD(tt_hhea
->ascender
) + abs(descender
) + GET_BE_WORD(tt_hhea
->linegap
) -
2073 metrics
->ascent
- metrics
->descent
;
2074 metrics
->lineGap
= linegap
> 0 ? linegap
: 0;
2078 metrics
->strikethroughPosition
= GET_BE_WORD(tt_os2
->yStrikeoutPosition
);
2079 metrics
->strikethroughThickness
= GET_BE_WORD(tt_os2
->yStrikeoutSize
);
2081 metrics
->subscriptPositionX
= GET_BE_WORD(tt_os2
->ySubscriptXOffset
);
2082 metrics
->subscriptPositionY
= -GET_BE_WORD(tt_os2
->ySubscriptYOffset
);
2083 metrics
->subscriptSizeX
= GET_BE_WORD(tt_os2
->ySubscriptXSize
);
2084 metrics
->subscriptSizeY
= GET_BE_WORD(tt_os2
->ySubscriptYSize
);
2085 metrics
->superscriptPositionX
= GET_BE_WORD(tt_os2
->ySuperscriptXOffset
);
2086 metrics
->superscriptPositionY
= GET_BE_WORD(tt_os2
->ySuperscriptYOffset
);
2087 metrics
->superscriptSizeX
= GET_BE_WORD(tt_os2
->ySuperscriptXSize
);
2088 metrics
->superscriptSizeY
= GET_BE_WORD(tt_os2
->ySuperscriptYSize
);
2091 metrics
->strikethroughPosition
= metrics
->designUnitsPerEm
/ 3;
2093 metrics
->ascent
= GET_BE_WORD(tt_hhea
->ascender
);
2094 metrics
->descent
= abs((SHORT
)GET_BE_WORD(tt_hhea
->descender
));
2099 metrics
->underlinePosition
= GET_BE_WORD(tt_post
->underlinePosition
);
2100 metrics
->underlineThickness
= GET_BE_WORD(tt_post
->underlineThickness
);
2103 if (metrics
->underlineThickness
== 0)
2104 metrics
->underlineThickness
= metrics
->designUnitsPerEm
/ 14;
2105 if (metrics
->strikethroughThickness
== 0)
2106 metrics
->strikethroughThickness
= metrics
->underlineThickness
;
2109 IDWriteFontFace_ReleaseFontTable(fontface
, os2_context
);
2111 IDWriteFontFace_ReleaseFontTable(fontface
, head_context
);
2113 IDWriteFontFace_ReleaseFontTable(fontface
, hhea_context
);
2115 IDWriteFontFace_ReleaseFontTable(fontface
, post_context
);
2118 static void check_font_metrics(const WCHAR
*nameW
, IDWriteFontFace
*fontface
, const DWRITE_FONT_METRICS1
*expected
)
2120 IDWriteFontFace1
*fontface1
= NULL
;
2121 DWRITE_FONT_METRICS1 metrics
;
2125 has_metrics1
= SUCCEEDED(IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void **)&fontface1
));
2126 simulations
= IDWriteFontFace_GetSimulations(fontface
);
2129 IDWriteFontFace1_GetMetrics(fontface1
, &metrics
);
2130 IDWriteFontFace1_Release(fontface1
);
2133 IDWriteFontFace_GetMetrics(fontface
, (DWRITE_FONT_METRICS
*)&metrics
);
2135 winetest_push_context("Font %s", wine_dbgstr_w(nameW
));
2137 ok(metrics
.designUnitsPerEm
== expected
->designUnitsPerEm
, "designUnitsPerEm %u, expected %u.\n",
2138 metrics
.designUnitsPerEm
, expected
->designUnitsPerEm
);
2139 ok(metrics
.ascent
== expected
->ascent
, "ascent %u, expected %u.\n", metrics
.ascent
, expected
->ascent
);
2140 ok(metrics
.descent
== expected
->descent
, "descent %u, expected %u.\n", metrics
.descent
, expected
->descent
);
2141 ok(metrics
.lineGap
== expected
->lineGap
, "lineGap %d, expected %d.\n", metrics
.lineGap
, expected
->lineGap
);
2142 ok(metrics
.underlinePosition
== expected
->underlinePosition
, "underlinePosition %d, expected %d.\n",
2143 metrics
.underlinePosition
, expected
->underlinePosition
);
2144 ok(metrics
.underlineThickness
== expected
->underlineThickness
, "underlineThickness %u, expected %u.\n",
2145 metrics
.underlineThickness
, expected
->underlineThickness
);
2146 ok(metrics
.strikethroughPosition
== expected
->strikethroughPosition
, "strikethroughPosition %d, expected %d.\n",
2147 metrics
.strikethroughPosition
, expected
->strikethroughPosition
);
2148 ok(metrics
.strikethroughThickness
== expected
->strikethroughThickness
, "strikethroughThickness %u, "
2149 "expected %u.\n", metrics
.strikethroughThickness
, expected
->strikethroughThickness
);
2153 /* For simulated faces metrics are adjusted. Enable tests when exact pattern is understood. */
2154 if (simulations
& DWRITE_FONT_SIMULATIONS_OBLIQUE
)
2156 winetest_pop_context();
2160 ok(metrics
.hasTypographicMetrics
== expected
->hasTypographicMetrics
, "hasTypographicMetrics %d, "
2161 "expected %d.\n", metrics
.hasTypographicMetrics
, expected
->hasTypographicMetrics
);
2162 ok(metrics
.glyphBoxLeft
== expected
->glyphBoxLeft
, "glyphBoxLeft %d, expected %d.\n",
2163 metrics
.glyphBoxLeft
, expected
->glyphBoxLeft
);
2164 ok(metrics
.glyphBoxTop
== expected
->glyphBoxTop
, "glyphBoxTop %d, expected %d.\n",
2165 metrics
.glyphBoxTop
, expected
->glyphBoxTop
);
2166 ok(metrics
.glyphBoxRight
== expected
->glyphBoxRight
, "glyphBoxRight %d, expected %d.\n",
2167 metrics
.glyphBoxRight
, expected
->glyphBoxRight
);
2168 ok(metrics
.glyphBoxBottom
== expected
->glyphBoxBottom
, "glyphBoxBottom %d, expected %d.\n",
2169 metrics
.glyphBoxBottom
, expected
->glyphBoxBottom
);
2171 ok(metrics
.subscriptPositionX
== expected
->subscriptPositionX
, "subscriptPositionX %d, expected %d.\n",
2172 metrics
.subscriptPositionX
, expected
->subscriptPositionX
);
2173 ok(metrics
.subscriptPositionY
== expected
->subscriptPositionY
, "subscriptPositionY %d, expected %d.\n",
2174 metrics
.subscriptPositionY
, expected
->subscriptPositionY
);
2175 ok(metrics
.subscriptSizeX
== expected
->subscriptSizeX
, "subscriptSizeX %d, expected %d.\n",
2176 metrics
.subscriptSizeX
, expected
->subscriptSizeX
);
2177 ok(metrics
.subscriptSizeY
== expected
->subscriptSizeY
, "subscriptSizeY %d, expected %d.\n",
2178 metrics
.subscriptSizeY
, expected
->subscriptSizeY
);
2179 ok(metrics
.superscriptPositionX
== expected
->superscriptPositionX
, "superscriptPositionX %d, expected %d.\n",
2180 metrics
.superscriptPositionX
, expected
->superscriptPositionX
);
2181 ok(metrics
.superscriptPositionY
== expected
->superscriptPositionY
, "superscriptPositionY %d, expected %d.\n",
2182 metrics
.superscriptPositionY
, expected
->superscriptPositionY
);
2183 ok(metrics
.superscriptSizeX
== expected
->superscriptSizeX
, "superscriptSizeX %d, expected %d.\n",
2184 metrics
.superscriptSizeX
, expected
->superscriptSizeX
);
2185 ok(metrics
.superscriptSizeY
== expected
->superscriptSizeY
, "superscriptSizeY %d, expected %d.\n",
2186 metrics
.superscriptSizeY
, expected
->superscriptSizeY
);
2189 winetest_pop_context();
2192 static void get_enus_string(IDWriteLocalizedStrings
*strings
, WCHAR
*buff
, UINT32 size
)
2194 BOOL exists
= FALSE
;
2198 hr
= IDWriteLocalizedStrings_FindLocaleName(strings
, L
"en-us", &index
, &exists
);
2199 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2202 hr
= IDWriteLocalizedStrings_GetString(strings
, index
, buff
, size
);
2203 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2206 static void test_GetMetrics(void)
2208 DWRITE_FONT_METRICS metrics
, metrics2
;
2209 IDWriteFontCollection
*syscollection
;
2210 IDWriteGdiInterop
*interop
;
2211 IDWriteFontFace
*fontface
;
2212 IDWriteFactory
*factory
;
2213 OUTLINETEXTMETRICW otm
;
2214 IDWriteFontFile
*file
;
2215 IDWriteFont1
*font1
;
2225 factory
= create_factory();
2227 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop
);
2228 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2230 memset(&logfont
, 0, sizeof(logfont
));
2231 logfont
.lfHeight
= 12;
2232 logfont
.lfWidth
= 12;
2233 logfont
.lfWeight
= FW_NORMAL
;
2234 logfont
.lfItalic
= 1;
2235 lstrcpyW(logfont
.lfFaceName
, L
"Tahoma");
2237 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font
);
2238 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2240 hfont
= CreateFontIndirectW(&logfont
);
2241 hdc
= CreateCompatibleDC(0);
2242 SelectObject(hdc
, hfont
);
2244 otm
.otmSize
= sizeof(otm
);
2245 ret
= GetOutlineTextMetricsW(hdc
, otm
.otmSize
, &otm
);
2246 ok(ret
, "got %d\n", ret
);
2248 DeleteObject(hfont
);
2250 if (0) /* crashes on native */
2251 IDWriteFont_GetMetrics(font
, NULL
);
2253 memset(&metrics
, 0, sizeof(metrics
));
2254 IDWriteFont_GetMetrics(font
, &metrics
);
2256 ok(metrics
.designUnitsPerEm
!= 0, "designUnitsPerEm %u\n", metrics
.designUnitsPerEm
);
2257 ok(metrics
.ascent
!= 0, "ascent %u\n", metrics
.ascent
);
2258 ok(metrics
.descent
!= 0, "descent %u\n", metrics
.descent
);
2259 ok(metrics
.lineGap
== 0, "lineGap %d\n", metrics
.lineGap
);
2260 ok(metrics
.capHeight
, "capHeight %u\n", metrics
.capHeight
);
2261 ok(metrics
.xHeight
!= 0, "xHeight %u\n", metrics
.xHeight
);
2262 ok(metrics
.underlinePosition
< 0, "underlinePosition %d\n", metrics
.underlinePosition
);
2263 ok(metrics
.underlineThickness
!= 0, "underlineThickness %u\n", metrics
.underlineThickness
);
2264 ok(metrics
.strikethroughPosition
> 0, "strikethroughPosition %d\n", metrics
.strikethroughPosition
);
2265 ok(metrics
.strikethroughThickness
!= 0, "strikethroughThickness %u\n", metrics
.strikethroughThickness
);
2267 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
2268 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2270 memset(&metrics
, 0, sizeof(metrics
));
2271 IDWriteFontFace_GetMetrics(fontface
, &metrics
);
2273 ok(metrics
.designUnitsPerEm
!= 0, "designUnitsPerEm %u\n", metrics
.designUnitsPerEm
);
2274 ok(metrics
.ascent
!= 0, "ascent %u\n", metrics
.ascent
);
2275 ok(metrics
.descent
!= 0, "descent %u\n", metrics
.descent
);
2276 ok(metrics
.lineGap
== 0, "lineGap %d\n", metrics
.lineGap
);
2277 ok(metrics
.capHeight
, "capHeight %u\n", metrics
.capHeight
);
2278 ok(metrics
.xHeight
!= 0, "xHeight %u\n", metrics
.xHeight
);
2279 ok(metrics
.underlinePosition
< 0, "underlinePosition %d\n", metrics
.underlinePosition
);
2280 ok(metrics
.underlineThickness
!= 0, "underlineThickness %u\n", metrics
.underlineThickness
);
2281 ok(metrics
.strikethroughPosition
> 0, "strikethroughPosition %d\n", metrics
.strikethroughPosition
);
2282 ok(metrics
.strikethroughThickness
!= 0, "strikethroughThickness %u\n", metrics
.strikethroughThickness
);
2284 hr
= IDWriteFont_QueryInterface(font
, &IID_IDWriteFont1
, (void**)&font1
);
2286 DWRITE_FONT_METRICS1 metrics1
;
2287 IDWriteFontFace1
*fontface1
;
2289 memset(&metrics1
, 0, sizeof(metrics1
));
2290 IDWriteFont1_GetMetrics(font1
, &metrics1
);
2292 ok(metrics1
.designUnitsPerEm
!= 0, "designUnitsPerEm %u\n", metrics1
.designUnitsPerEm
);
2293 ok(metrics1
.ascent
!= 0, "ascent %u\n", metrics1
.ascent
);
2294 ok(metrics1
.descent
!= 0, "descent %u\n", metrics1
.descent
);
2295 ok(metrics1
.lineGap
== 0, "lineGap %d\n", metrics1
.lineGap
);
2296 ok(metrics1
.capHeight
, "capHeight %u\n", metrics1
.capHeight
);
2297 ok(metrics1
.xHeight
!= 0, "xHeight %u\n", metrics1
.xHeight
);
2298 ok(metrics1
.underlinePosition
< 0, "underlinePosition %d\n", metrics1
.underlinePosition
);
2299 ok(metrics1
.underlineThickness
!= 0, "underlineThickness %u\n", metrics1
.underlineThickness
);
2300 ok(metrics1
.strikethroughPosition
> 0, "strikethroughPosition %d\n", metrics1
.strikethroughPosition
);
2301 ok(metrics1
.strikethroughThickness
!= 0, "strikethroughThickness %u\n", metrics1
.strikethroughThickness
);
2302 ok(metrics1
.glyphBoxLeft
< 0, "glyphBoxLeft %d\n", metrics1
.glyphBoxLeft
);
2303 ok(metrics1
.glyphBoxTop
> 0, "glyphBoxTop %d\n", metrics1
.glyphBoxTop
);
2304 ok(metrics1
.glyphBoxRight
> 0, "glyphBoxRight %d\n", metrics1
.glyphBoxRight
);
2305 ok(metrics1
.glyphBoxBottom
< 0, "glyphBoxBottom %d\n", metrics1
.glyphBoxBottom
);
2306 ok(metrics1
.subscriptPositionY
< 0, "subscriptPositionY %d\n", metrics1
.subscriptPositionY
);
2307 ok(metrics1
.subscriptSizeX
> 0, "subscriptSizeX %d\n", metrics1
.subscriptSizeX
);
2308 ok(metrics1
.subscriptSizeY
> 0, "subscriptSizeY %d\n", metrics1
.subscriptSizeY
);
2309 ok(metrics1
.superscriptPositionY
> 0, "superscriptPositionY %d\n", metrics1
.superscriptPositionY
);
2310 ok(metrics1
.superscriptSizeX
> 0, "superscriptSizeX %d\n", metrics1
.superscriptSizeX
);
2311 ok(metrics1
.superscriptSizeY
> 0, "superscriptSizeY %d\n", metrics1
.superscriptSizeY
);
2312 ok(!metrics1
.hasTypographicMetrics
, "hasTypographicMetrics %d\n", metrics1
.hasTypographicMetrics
);
2314 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void**)&fontface1
);
2315 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2317 memset(&metrics1
, 0, sizeof(metrics1
));
2318 IDWriteFontFace1_GetMetrics(fontface1
, &metrics1
);
2320 ok(metrics1
.designUnitsPerEm
!= 0, "designUnitsPerEm %u\n", metrics1
.designUnitsPerEm
);
2321 ok(metrics1
.ascent
!= 0, "ascent %u\n", metrics1
.ascent
);
2322 ok(metrics1
.descent
!= 0, "descent %u\n", metrics1
.descent
);
2323 ok(metrics1
.lineGap
== 0, "lineGap %d\n", metrics1
.lineGap
);
2324 ok(metrics1
.capHeight
, "capHeight %u\n", metrics1
.capHeight
);
2325 ok(metrics1
.xHeight
!= 0, "xHeight %u\n", metrics1
.xHeight
);
2326 ok(metrics1
.underlinePosition
< 0, "underlinePosition %d\n", metrics1
.underlinePosition
);
2327 ok(metrics1
.underlineThickness
!= 0, "underlineThickness %u\n", metrics1
.underlineThickness
);
2328 ok(metrics1
.strikethroughPosition
> 0, "strikethroughPosition %d\n", metrics1
.strikethroughPosition
);
2329 ok(metrics1
.strikethroughThickness
!= 0, "strikethroughThickness %u\n", metrics1
.strikethroughThickness
);
2330 ok(metrics1
.glyphBoxLeft
< 0, "glyphBoxLeft %d\n", metrics1
.glyphBoxLeft
);
2331 ok(metrics1
.glyphBoxTop
> 0, "glyphBoxTop %d\n", metrics1
.glyphBoxTop
);
2332 ok(metrics1
.glyphBoxRight
> 0, "glyphBoxRight %d\n", metrics1
.glyphBoxRight
);
2333 ok(metrics1
.glyphBoxBottom
< 0, "glyphBoxBottom %d\n", metrics1
.glyphBoxBottom
);
2334 ok(metrics1
.subscriptPositionY
< 0, "subscriptPositionY %d\n", metrics1
.subscriptPositionY
);
2335 ok(metrics1
.subscriptSizeX
> 0, "subscriptSizeX %d\n", metrics1
.subscriptSizeX
);
2336 ok(metrics1
.subscriptSizeY
> 0, "subscriptSizeY %d\n", metrics1
.subscriptSizeY
);
2337 ok(metrics1
.superscriptPositionY
> 0, "superscriptPositionY %d\n", metrics1
.superscriptPositionY
);
2338 ok(metrics1
.superscriptSizeX
> 0, "superscriptSizeX %d\n", metrics1
.superscriptSizeX
);
2339 ok(metrics1
.superscriptSizeY
> 0, "superscriptSizeY %d\n", metrics1
.superscriptSizeY
);
2340 ok(!metrics1
.hasTypographicMetrics
, "hasTypographicMetrics %d\n", metrics1
.hasTypographicMetrics
);
2342 IDWriteFontFace1_Release(fontface1
);
2343 IDWriteFont1_Release(font1
);
2346 win_skip("DWRITE_FONT_METRICS1 is not supported.\n");
2348 IDWriteFontFace_Release(fontface
);
2349 IDWriteFont_Release(font
);
2350 IDWriteGdiInterop_Release(interop
);
2352 /* bold simulation affects returned font metrics */
2353 font
= get_tahoma_instance(factory
, DWRITE_FONT_STYLE_NORMAL
);
2355 /* create regulat Tahoma with bold simulation */
2356 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
2357 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2360 hr
= IDWriteFontFace_GetFiles(fontface
, &count
, &file
);
2361 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2363 IDWriteFontFace_GetMetrics(fontface
, &metrics
);
2364 ok(IDWriteFontFace_GetSimulations(fontface
) == 0, "wrong simulations flags\n");
2365 IDWriteFontFace_Release(fontface
);
2367 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_TRUETYPE
, 1, &file
,
2368 0, DWRITE_FONT_SIMULATIONS_BOLD
, &fontface
);
2369 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2370 IDWriteFontFace_GetMetrics(fontface
, &metrics2
);
2371 ok(IDWriteFontFace_GetSimulations(fontface
) == DWRITE_FONT_SIMULATIONS_BOLD
, "wrong simulations flags\n");
2373 ok(metrics
.ascent
== metrics2
.ascent
, "got %u, %u\n", metrics2
.ascent
, metrics
.ascent
);
2374 ok(metrics
.descent
== metrics2
.descent
, "got %u, %u\n", metrics2
.descent
, metrics
.descent
);
2375 ok(metrics
.lineGap
== metrics2
.lineGap
, "got %d, %d\n", metrics2
.lineGap
, metrics
.lineGap
);
2376 ok(metrics
.capHeight
== metrics2
.capHeight
, "got %u, %u\n", metrics2
.capHeight
, metrics
.capHeight
);
2377 ok(metrics
.xHeight
== metrics2
.xHeight
, "got %u, %u\n", metrics2
.xHeight
, metrics
.xHeight
);
2378 ok(metrics
.underlinePosition
== metrics2
.underlinePosition
, "got %d, %d\n", metrics2
.underlinePosition
,
2379 metrics
.underlinePosition
);
2380 ok(metrics
.underlineThickness
== metrics2
.underlineThickness
, "got %u, %u\n", metrics2
.underlineThickness
,
2381 metrics
.underlineThickness
);
2382 ok(metrics
.strikethroughPosition
== metrics2
.strikethroughPosition
, "got %d, %d\n", metrics2
.strikethroughPosition
,
2383 metrics
.strikethroughPosition
);
2384 ok(metrics
.strikethroughThickness
== metrics2
.strikethroughThickness
, "got %u, %u\n", metrics2
.strikethroughThickness
,
2385 metrics
.strikethroughThickness
);
2387 IDWriteFontFile_Release(file
);
2388 IDWriteFontFace_Release(fontface
);
2389 IDWriteFont_Release(font
);
2391 /* test metrics for whole system collection */
2392 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &syscollection
, FALSE
);
2393 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2394 count
= IDWriteFontCollection_GetFontFamilyCount(syscollection
);
2396 for (i
= 0; i
< count
; i
++) {
2397 DWRITE_FONT_METRICS1 expected_metrics
;
2398 WCHAR familyW
[256], faceW
[256];
2399 IDWriteLocalizedStrings
*names
;
2400 IDWriteFontFamily
*family
;
2401 UINT32 fontcount
, j
;
2404 hr
= IDWriteFontCollection_GetFontFamily(syscollection
, i
, &family
);
2405 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2407 fontcount
= IDWriteFontFamily_GetFontCount(family
);
2409 hr
= IDWriteFontFamily_GetFamilyNames(family
, &names
);
2410 ok(hr
== S_OK
, "Failed to get family names, hr %#lx.\n", hr
);
2411 get_enus_string(names
, familyW
, ARRAY_SIZE(familyW
));
2412 IDWriteLocalizedStrings_Release(names
);
2414 for (j
= 0; j
< fontcount
; j
++) {
2417 hr
= IDWriteFontFamily_GetFont(family
, j
, &font
);
2418 ok(hr
== S_OK
, "Failed to get a font, hr %#lx.\n", hr
);
2420 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
2421 ok(hr
== S_OK
, "Failed to create face instance, hr %#lx.\n", hr
);
2423 hr
= IDWriteFont_GetFaceNames(font
, &names
);
2424 ok(hr
== S_OK
, "Failed to get face names, hr %#lx.\n", hr
);
2425 get_enus_string(names
, faceW
, ARRAY_SIZE(faceW
));
2426 IDWriteLocalizedStrings_Release(names
);
2428 IDWriteFont_Release(font
);
2430 get_combined_font_name(familyW
, faceW
, nameW
);
2432 if (has_face_variations(fontface
))
2436 skip("GetMetrics() test does not support variable fonts.\n");
2437 IDWriteFontFace_Release(fontface
);
2441 get_expected_font_metrics(fontface
, &expected_metrics
);
2442 check_font_metrics(nameW
, fontface
, &expected_metrics
);
2444 IDWriteFontFace_Release(fontface
);
2447 IDWriteFontFamily_Release(family
);
2449 IDWriteFontCollection_Release(syscollection
);
2450 ref
= IDWriteFactory_Release(factory
);
2451 ok(ref
== 0, "factory not released, %lu\n", ref
);
2454 static void test_system_fontcollection(void)
2456 IDWriteFontCollection
*collection
, *coll2
;
2457 IDWriteLocalFontFileLoader
*localloader
;
2458 IDWriteFontCollection1
*collection1
;
2459 IDWriteFontCollection2
*collection2
;
2460 IDWriteFontCollection3
*collection3
;
2461 IDWriteFactory
*factory
, *factory2
;
2462 IDWriteFontFileLoader
*loader
;
2463 IDWriteFontFamily
*family
;
2464 IDWriteFontFace
*fontface
;
2465 IDWriteFactory6
*factory6
;
2466 IDWriteFontFile
*file
;
2473 factory
= create_factory();
2475 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &collection
, FALSE
);
2476 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2478 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &coll2
, FALSE
);
2479 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2480 ok(coll2
== collection
, "got %p, was %p\n", coll2
, collection
);
2481 IDWriteFontCollection_Release(coll2
);
2483 factory2
= create_factory();
2484 hr
= IDWriteFactory_GetSystemFontCollection(factory2
, &coll2
, FALSE
);
2485 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2486 ok(coll2
!= collection
, "got %p, was %p\n", coll2
, collection
);
2487 IDWriteFontCollection_Release(coll2
);
2488 IDWriteFactory_Release(factory2
);
2490 i
= IDWriteFontCollection_GetFontFamilyCount(collection
);
2491 ok(i
, "got %u\n", i
);
2494 family
= (void*)0xdeadbeef;
2495 hr
= IDWriteFontCollection_GetFontFamily(collection
, i
, &family
);
2496 ok(hr
== E_FAIL
, "Unexpected hr %#lx.\n", hr
);
2497 ok(family
== NULL
, "got %p\n", family
);
2501 hr
= IDWriteFontCollection_FindFamilyName(collection
, L
"Tahoma", &i
, &ret
);
2502 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2503 ok(ret
, "got %d\n", ret
);
2504 ok(i
!= (UINT32
)-1, "got %u\n", i
);
2508 hr
= IDWriteFontCollection_FindFamilyName(collection
, L
"TAHOMA", &i
, &ret
);
2509 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2510 ok(ret
, "got %d\n", ret
);
2511 ok(i
!= (UINT32
)-1, "got %u\n", i
);
2515 hr
= IDWriteFontCollection_FindFamilyName(collection
, L
"tAhOmA", &i
, &ret
);
2516 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2517 ok(ret
, "got %d\n", ret
);
2518 ok(i
!= (UINT32
)-1, "got %u\n", i
);
2520 /* get back local file loader */
2521 hr
= IDWriteFontCollection_GetFontFamily(collection
, i
, &family
);
2522 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2524 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
,
2525 DWRITE_FONT_STRETCH_NORMAL
, DWRITE_FONT_STYLE_NORMAL
, &font
);
2526 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2527 IDWriteFontFamily_Release(family
);
2529 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
2530 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2531 IDWriteFont_Release(font
);
2535 hr
= IDWriteFontFace_GetFiles(fontface
, &i
, &file
);
2536 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2537 ok(file
!= NULL
, "got %p\n", file
);
2538 IDWriteFontFace_Release(fontface
);
2540 hr
= IDWriteFontFile_GetLoader(file
, &loader
);
2541 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2542 IDWriteFontFile_Release(file
);
2544 hr
= IDWriteFontFileLoader_QueryInterface(loader
, &IID_IDWriteLocalFontFileLoader
, (void**)&localloader
);
2545 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2546 IDWriteLocalFontFileLoader_Release(localloader
);
2548 /* local loader is not registered by default */
2549 hr
= IDWriteFactory_RegisterFontFileLoader(factory
, loader
);
2550 ok(hr
== S_OK
|| broken(hr
== DWRITE_E_ALREADYREGISTERED
), "Unexpected hr %#lx.\n", hr
);
2551 hr
= IDWriteFactory_UnregisterFontFileLoader(factory
, loader
);
2552 ok(hr
== S_OK
|| broken(hr
== E_INVALIDARG
), "Unexpected hr %#lx.\n", hr
);
2554 /* try with a different factory */
2555 factory2
= create_factory();
2556 hr
= IDWriteFactory_RegisterFontFileLoader(factory2
, loader
);
2557 ok(hr
== S_OK
|| broken(hr
== DWRITE_E_ALREADYREGISTERED
), "Unexpected hr %#lx.\n", hr
);
2558 hr
= IDWriteFactory_RegisterFontFileLoader(factory2
, loader
);
2559 ok(hr
== DWRITE_E_ALREADYREGISTERED
, "Unexpected hr %#lx.\n", hr
);
2560 hr
= IDWriteFactory_UnregisterFontFileLoader(factory2
, loader
);
2561 ok(hr
== S_OK
|| broken(hr
== E_INVALIDARG
), "Unexpected hr %#lx.\n", hr
);
2562 hr
= IDWriteFactory_UnregisterFontFileLoader(factory2
, loader
);
2563 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
2564 IDWriteFactory_Release(factory2
);
2566 IDWriteFontFileLoader_Release(loader
);
2570 hr
= IDWriteFontCollection_FindFamilyName(collection
, L
"Blah!", &i
, &ret
);
2571 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2572 ok(!ret
, "got %d\n", ret
);
2573 ok(i
== (UINT32
)-1, "got %u\n", i
);
2575 hr
= IDWriteFontCollection_QueryInterface(collection
, &IID_IDWriteFontCollection1
, (void**)&collection1
);
2577 IDWriteFontSet
*fontset
, *fontset2
;
2578 IDWriteFontFamily1
*family1
;
2579 IDWriteFactory3
*factory3
;
2581 hr
= IDWriteFontCollection1_QueryInterface(collection1
, &IID_IDWriteFontCollection
, (void**)&coll2
);
2582 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2583 ok(coll2
== collection
, "got %p, %p\n", collection
, coll2
);
2584 IDWriteFontCollection_Release(coll2
);
2586 family1
= (void*)0xdeadbeef;
2587 hr
= IDWriteFontCollection1_GetFontFamily(collection1
, ~0u, &family1
);
2588 ok(hr
== E_FAIL
, "Unexpected hr %#lx.\n", hr
);
2589 ok(family1
== NULL
, "got %p\n", family1
);
2591 hr
= IDWriteFontCollection1_GetFontFamily(collection1
, 0, &family1
);
2592 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2593 IDWriteFontFamily1_Release(family1
);
2595 /* system fontset */
2596 EXPECT_REF(collection1
, 2);
2597 EXPECT_REF(factory
, 2);
2598 hr
= IDWriteFontCollection1_GetFontSet(collection1
, &fontset
);
2600 ok(hr
== S_OK
, "Failed to get fontset, hr %#lx.\n", hr
);
2602 EXPECT_REF(collection1
, 2);
2603 EXPECT_REF(factory
, 2);
2604 EXPECT_REF(fontset
, 1);
2606 hr
= IDWriteFontCollection1_GetFontSet(collection1
, &fontset2
);
2607 ok(hr
== S_OK
, "Failed to get fontset, hr %#lx.\n", hr
);
2608 ok(fontset
!= fontset2
, "Expected new fontset instance.\n");
2609 EXPECT_REF(fontset2
, 1);
2610 IDWriteFontSet_Release(fontset2
);
2612 hr
= IDWriteFactory_QueryInterface(factory
, &IID_IDWriteFactory3
, (void **)&factory3
);
2613 ok(hr
== S_OK
, "Failed to get IDWriteFactory3 interface, hr %#lx.\n", hr
);
2615 EXPECT_REF(factory
, 3);
2616 hr
= IDWriteFactory3_GetSystemFontSet(factory3
, &fontset2
);
2617 ok(hr
== S_OK
, "Failed to get system font set, hr %#lx.\n", hr
);
2618 ok(fontset
!= fontset2
, "Expected new fontset instance.\n");
2619 EXPECT_REF(fontset2
, 1);
2620 EXPECT_REF(factory
, 4);
2622 IDWriteFontSet_Release(fontset2
);
2623 IDWriteFontSet_Release(fontset
);
2625 IDWriteFactory3_Release(factory3
);
2627 IDWriteFontCollection1_Release(collection1
);
2630 win_skip("IDWriteFontCollection1 is not supported.\n");
2632 hr
= IDWriteFontCollection_QueryInterface(collection
, &IID_IDWriteFontCollection3
, (void **)&collection3
);
2637 event
= IDWriteFontCollection3_GetExpirationEvent(collection3
);
2639 ok(!!event
, "Expected event handle.\n");
2641 check_familymodel(collection3
, DWRITE_FONT_FAMILY_MODEL_WEIGHT_STRETCH_STYLE
);
2643 IDWriteFontCollection3_Release(collection3
);
2646 win_skip("IDWriteFontCollection3 is not supported.\n");
2648 /* With specified family model. */
2649 hr
= IDWriteFactory_QueryInterface(factory
, &IID_IDWriteFactory6
, (void **)&factory6
);
2652 IDWriteFontCollection2
*c2
;
2654 hr
= IDWriteFactory6_GetSystemFontCollection(factory6
, FALSE
, DWRITE_FONT_FAMILY_MODEL_TYPOGRAPHIC
,
2657 ok(hr
== S_OK
, "Failed to get collection, hr %#lx.\n", hr
);
2660 hr
= IDWriteFactory6_GetSystemFontCollection(factory6
, FALSE
, DWRITE_FONT_FAMILY_MODEL_TYPOGRAPHIC
, &c2
);
2661 ok(hr
== S_OK
, "Failed to get collection, hr %#lx.\n", hr
);
2662 ok(c2
== collection2
&& collection
!= (IDWriteFontCollection
*)c2
, "Unexpected collection instance.\n");
2663 IDWriteFontCollection2_Release(c2
);
2664 IDWriteFontCollection2_Release(collection2
);
2666 hr
= IDWriteFactory6_GetSystemFontCollection(factory6
, FALSE
, DWRITE_FONT_FAMILY_MODEL_WEIGHT_STRETCH_STYLE
,
2668 ok(hr
== S_OK
, "Failed to get collection, hr %#lx.\n", hr
);
2669 IDWriteFontCollection2_Release(collection2
);
2671 IDWriteFactory6_Release(factory6
);
2674 win_skip("IDWriteFactory6 is not supported.\n");
2676 ref
= IDWriteFontCollection_Release(collection
);
2677 ok(!ref
, "Collection wasn't released, %lu.\n", ref
);
2678 ref
= IDWriteFactory_Release(factory
);
2679 ok(!ref
, "Factory wasn't released, %lu.\n", ref
);
2682 static void get_logfont_from_font(IDWriteFont
*font
, LOGFONTW
*logfont
)
2684 void *os2_context
, *head_context
;
2685 IDWriteLocalizedStrings
*names
;
2686 DWRITE_FONT_SIMULATIONS sim
;
2687 IDWriteFontFace
*fontface
;
2688 const TT_OS2_V2
*tt_os2
;
2689 DWRITE_FONT_STYLE style
;
2690 const TT_HEAD
*tt_head
;
2696 /* These are rendering time properties. */
2697 logfont
->lfHeight
= 0;
2698 logfont
->lfWidth
= 0;
2699 logfont
->lfEscapement
= 0;
2700 logfont
->lfOrientation
= 0;
2701 logfont
->lfUnderline
= 0;
2702 logfont
->lfStrikeOut
= 0;
2704 logfont
->lfWeight
= 0;
2705 logfont
->lfItalic
= 0;
2707 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
2708 ok(hr
== S_OK
, "Failed to create font face, %#lx\n", hr
);
2710 hr
= IDWriteFontFace_TryGetFontTable(fontface
, MS_OS2_TAG
, (const void **)&tt_os2
, &size
,
2711 &os2_context
, &exists
);
2712 ok(hr
== S_OK
, "Failed to get OS/2 table, %#lx\n", hr
);
2714 hr
= IDWriteFontFace_TryGetFontTable(fontface
, MS_HEAD_TAG
, (const void **)&tt_head
, &size
,
2715 &head_context
, &exists
);
2716 ok(hr
== S_OK
, "Failed to get head table, %#lx\n", hr
);
2718 sim
= IDWriteFont_GetSimulations(font
);
2721 weight
= FW_REGULAR
;
2723 USHORT usWeightClass
= GET_BE_WORD(tt_os2
->usWeightClass
);
2725 if (usWeightClass
>= 1 && usWeightClass
<= 9)
2726 usWeightClass
*= 100;
2728 if (usWeightClass
> DWRITE_FONT_WEIGHT_ULTRA_BLACK
)
2729 weight
= DWRITE_FONT_WEIGHT_ULTRA_BLACK
;
2730 else if (usWeightClass
> 0)
2731 weight
= usWeightClass
;
2734 USHORT macStyle
= GET_BE_WORD(tt_head
->macStyle
);
2735 if (macStyle
& TT_HEAD_MACSTYLE_BOLD
)
2736 weight
= DWRITE_FONT_WEIGHT_BOLD
;
2738 if (sim
& DWRITE_FONT_SIMULATIONS_BOLD
)
2739 weight
+= (FW_BOLD
- FW_REGULAR
) / 2 + 1;
2740 logfont
->lfWeight
= weight
;
2743 if (IDWriteFont_GetSimulations(font
) & DWRITE_FONT_SIMULATIONS_OBLIQUE
)
2744 logfont
->lfItalic
= 1;
2746 style
= IDWriteFont_GetStyle(font
);
2747 if (!logfont
->lfItalic
&& ((style
== DWRITE_FONT_STYLE_ITALIC
) || (style
== DWRITE_FONT_STYLE_OBLIQUE
))) {
2749 USHORT fsSelection
= GET_BE_WORD(tt_os2
->fsSelection
);
2750 logfont
->lfItalic
= !!(fsSelection
& OS2_FSSELECTION_ITALIC
);
2753 USHORT macStyle
= GET_BE_WORD(tt_head
->macStyle
);
2754 logfont
->lfItalic
= !!(macStyle
& TT_HEAD_MACSTYLE_ITALIC
);
2760 logfont
->lfFaceName
[0] = 0;
2761 hr
= IDWriteFont_GetInformationalStrings(font
, DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES
, &names
, &exists
);
2766 WCHAR localeW
[LOCALE_NAME_MAX_LENGTH
];
2770 /* Fallback to en-us if there's no string for user locale. */
2772 if (GetSystemDefaultLocaleName(localeW
, ARRAY_SIZE(localeW
)))
2773 IDWriteLocalizedStrings_FindLocaleName(names
, localeW
, &index
, &exists
);
2776 IDWriteLocalizedStrings_FindLocaleName(names
, L
"en-us", &index
, &exists
);
2780 hr
= IDWriteLocalizedStrings_GetString(names
, index
, nameW
, ARRAY_SIZE(nameW
));
2781 ok(hr
== S_OK
, "Failed to get name string, hr %#lx.\n", hr
);
2782 lstrcpynW(logfont
->lfFaceName
, nameW
, ARRAY_SIZE(logfont
->lfFaceName
));
2786 IDWriteLocalizedStrings_Release(names
);
2790 IDWriteFontFace_ReleaseFontTable(fontface
, os2_context
);
2792 IDWriteFontFace_ReleaseFontTable(fontface
, head_context
);
2793 IDWriteFontFace_Release(fontface
);
2796 static void test_ConvertFontFaceToLOGFONT(void)
2798 IDWriteFontCollection
*collection
;
2799 IDWriteGdiInterop
*interop
;
2800 IDWriteFontFace
*fontface
;
2801 IDWriteFactory
*factory
;
2807 factory
= create_factory();
2809 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop
);
2810 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2812 if (0) /* crashes on native */
2814 hr
= IDWriteGdiInterop_ConvertFontFaceToLOGFONT(interop
, NULL
, NULL
);
2815 hr
= IDWriteGdiInterop_ConvertFontFaceToLOGFONT(interop
, fontface
, NULL
);
2817 memset(&logfont
, 0xcc, sizeof(logfont
));
2818 hr
= IDWriteGdiInterop_ConvertFontFaceToLOGFONT(interop
, NULL
, &logfont
);
2819 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
2820 ok(logfont
.lfFaceName
[0] == 0, "got face name %s\n", wine_dbgstr_w(logfont
.lfFaceName
));
2822 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &collection
, FALSE
);
2823 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2825 count
= IDWriteFontCollection_GetFontFamilyCount(collection
);
2826 for (i
= 0; i
< count
; i
++) {
2827 WCHAR nameW
[128], familynameW
[64], facenameW
[64];
2828 IDWriteLocalizedStrings
*names
;
2829 DWRITE_FONT_SIMULATIONS sim
;
2830 IDWriteFontFamily
*family
;
2831 UINT32 font_count
, j
;
2835 hr
= IDWriteFontCollection_GetFontFamily(collection
, i
, &family
);
2836 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2838 hr
= IDWriteFontFamily_GetFamilyNames(family
, &names
);
2839 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2841 get_enus_string(names
, familynameW
, ARRAY_SIZE(familynameW
));
2842 IDWriteLocalizedStrings_Release(names
);
2844 font_count
= IDWriteFontFamily_GetFontCount(family
);
2846 for (j
= 0; j
< font_count
; j
++) {
2847 IDWriteFontFace
*fontface
;
2849 hr
= IDWriteFontFamily_GetFont(family
, j
, &font
);
2850 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2852 hr
= IDWriteFont_GetFaceNames(font
, &names
);
2853 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2855 get_enus_string(names
, facenameW
, ARRAY_SIZE(facenameW
));
2856 IDWriteLocalizedStrings_Release(names
);
2858 get_combined_font_name(familynameW
, facenameW
, nameW
);
2860 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
2861 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2863 if (has_face_variations(fontface
))
2867 skip("ConvertFontFaceToLOGFONT() test does not support variable fonts.\n");
2868 IDWriteFontFace_Release(fontface
);
2869 IDWriteFont_Release(font
);
2873 memset(&logfont
, 0xcc, sizeof(logfont
));
2874 hr
= IDWriteGdiInterop_ConvertFontFaceToLOGFONT(interop
, fontface
, &logfont
);
2875 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2877 sim
= IDWriteFontFace_GetSimulations(fontface
);
2878 get_logfont_from_font(font
, &lf
);
2880 winetest_push_context("Font %s", wine_dbgstr_w(nameW
));
2882 ok(logfont
.lfWeight
== lf
.lfWeight
, "Unexpected lfWeight %ld, expected lfWeight %ld, font weight %d, "
2883 "bold simulation %s.\n", logfont
.lfWeight
, lf
.lfWeight
, IDWriteFont_GetWeight(font
),
2884 sim
& DWRITE_FONT_SIMULATIONS_BOLD
? "yes" : "no");
2885 ok(logfont
.lfItalic
== lf
.lfItalic
, "Unexpected italic flag %d, oblique simulation %s.\n",
2886 logfont
.lfItalic
, sim
& DWRITE_FONT_SIMULATIONS_OBLIQUE
? "yes" : "no");
2887 ok(!lstrcmpW(logfont
.lfFaceName
, lf
.lfFaceName
), "Unexpected facename %s, expected %s\n",
2888 wine_dbgstr_w(logfont
.lfFaceName
), wine_dbgstr_w(lf
.lfFaceName
));
2890 ok(logfont
.lfOutPrecision
== OUT_OUTLINE_PRECIS
, "Unexpected output precision %d.\n", logfont
.lfOutPrecision
);
2891 ok(logfont
.lfClipPrecision
== CLIP_DEFAULT_PRECIS
, "Unexpected clipping precision %d.\n", logfont
.lfClipPrecision
);
2892 ok(logfont
.lfQuality
== DEFAULT_QUALITY
, "Unexpected quality %d.\n", logfont
.lfQuality
);
2893 ok(logfont
.lfPitchAndFamily
== DEFAULT_PITCH
, "Unexpected pitch %d.\n", logfont
.lfPitchAndFamily
);
2895 winetest_pop_context();
2897 IDWriteFontFace_Release(fontface
);
2898 IDWriteFont_Release(font
);
2901 IDWriteFontFamily_Release(family
);
2904 IDWriteFontCollection_Release(collection
);
2905 IDWriteGdiInterop_Release(interop
);
2906 ref
= IDWriteFactory_Release(factory
);
2907 ok(ref
== 0, "factory not released, %lu\n", ref
);
2910 static HRESULT WINAPI
fontfileenumerator_QueryInterface(IDWriteFontFileEnumerator
*iface
, REFIID riid
, void **obj
)
2912 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFontFileEnumerator
))
2915 IDWriteFontFileEnumerator_AddRef(iface
);
2918 return E_NOINTERFACE
;
2921 static ULONG WINAPI
fontfileenumerator_AddRef(IDWriteFontFileEnumerator
*iface
)
2926 static ULONG WINAPI
fontfileenumerator_Release(IDWriteFontFileEnumerator
*iface
)
2931 static HRESULT WINAPI
fontfileenumerator_GetCurrentFontFile(IDWriteFontFileEnumerator
*iface
, IDWriteFontFile
**file
)
2937 static HRESULT WINAPI
fontfileenumerator_MoveNext(IDWriteFontFileEnumerator
*iface
, BOOL
*current
)
2943 static const struct IDWriteFontFileEnumeratorVtbl dwritefontfileenumeratorvtbl
=
2945 fontfileenumerator_QueryInterface
,
2946 fontfileenumerator_AddRef
,
2947 fontfileenumerator_Release
,
2948 fontfileenumerator_MoveNext
,
2949 fontfileenumerator_GetCurrentFontFile
,
2952 struct collection_loader
2954 IDWriteFontCollectionLoader IDWriteFontCollectionLoader_iface
;
2958 static inline struct collection_loader
*impl_from_IDWriteFontCollectionLoader(IDWriteFontCollectionLoader
*iface
)
2960 return CONTAINING_RECORD(iface
, struct collection_loader
, IDWriteFontCollectionLoader_iface
);
2963 static HRESULT WINAPI
fontcollectionloader_QueryInterface(IDWriteFontCollectionLoader
*iface
, REFIID riid
, void **obj
)
2965 struct collection_loader
*loader
= impl_from_IDWriteFontCollectionLoader(iface
);
2967 if (IsEqualIID(&IID_IDWriteFontCollectionLoader
, riid
) ||
2968 IsEqualIID(&IID_IUnknown
, riid
))
2970 *obj
= &loader
->IDWriteFontCollectionLoader_iface
;
2971 IDWriteFontCollectionLoader_AddRef(iface
);
2976 return E_NOINTERFACE
;
2979 static ULONG WINAPI
fontcollectionloader_AddRef(IDWriteFontCollectionLoader
*iface
)
2981 struct collection_loader
*loader
= impl_from_IDWriteFontCollectionLoader(iface
);
2982 return InterlockedIncrement(&loader
->ref
);
2985 static ULONG WINAPI
fontcollectionloader_Release(IDWriteFontCollectionLoader
*iface
)
2987 struct collection_loader
*loader
= impl_from_IDWriteFontCollectionLoader(iface
);
2988 ULONG ref
= InterlockedDecrement(&loader
->ref
);
2996 static HRESULT WINAPI
fontcollectionloader_CreateEnumeratorFromKey(IDWriteFontCollectionLoader
*iface
, IDWriteFactory
*factory
, const void *key
,
2997 UINT32 key_size
, IDWriteFontFileEnumerator
**ret
)
2999 static IDWriteFontFileEnumerator enumerator
= { &dwritefontfileenumeratorvtbl
};
3004 static const struct IDWriteFontCollectionLoaderVtbl dwritefontcollectionloadervtbl
= {
3005 fontcollectionloader_QueryInterface
,
3006 fontcollectionloader_AddRef
,
3007 fontcollectionloader_Release
,
3008 fontcollectionloader_CreateEnumeratorFromKey
3011 static IDWriteFontCollectionLoader
*create_collection_loader(void)
3013 struct collection_loader
*loader
= malloc(sizeof(*loader
));
3015 loader
->IDWriteFontCollectionLoader_iface
.lpVtbl
= &dwritefontcollectionloadervtbl
;
3018 return &loader
->IDWriteFontCollectionLoader_iface
;
3021 static void test_CustomFontCollection(void)
3023 IDWriteFontCollectionLoader
*loader
, *loader2
, *loader3
;
3024 IDWriteFontCollection
*font_collection
= NULL
;
3025 static IDWriteFontFileLoader rloader
= { &resourcefontfileloadervtbl
};
3026 struct test_fontcollectionloader resource_collection
= { { &resourcecollectionloadervtbl
}, &rloader
};
3027 IDWriteFontFamily
*family
, *family2
, *family3
;
3028 IDWriteFontFace
*idfontface
, *idfontface2
;
3029 IDWriteFontFile
*fontfile
, *fontfile2
;
3030 IDWriteLocalizedStrings
*string
;
3031 IDWriteFont
*idfont
, *idfont2
;
3032 IDWriteFactory
*factory
;
3033 UINT32 index
, count
;
3039 factory
= create_factory();
3041 loader
= create_collection_loader();
3042 loader2
= create_collection_loader();
3043 loader3
= create_collection_loader();
3045 hr
= IDWriteFactory_RegisterFontCollectionLoader(factory
, NULL
);
3046 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
3048 hr
= IDWriteFactory_UnregisterFontCollectionLoader(factory
, NULL
);
3049 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
3051 EXPECT_REF(loader
, 1);
3052 EXPECT_REF(loader2
, 1);
3054 hr
= IDWriteFactory_RegisterFontCollectionLoader(factory
, loader
);
3055 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3056 hr
= IDWriteFactory_RegisterFontCollectionLoader(factory
, loader2
);
3057 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3058 hr
= IDWriteFactory_RegisterFontCollectionLoader(factory
, loader
);
3059 ok(hr
== DWRITE_E_ALREADYREGISTERED
, "Unexpected hr %#lx.\n", hr
);
3061 EXPECT_REF(loader
, 2);
3062 EXPECT_REF(loader2
, 2);
3064 hr
= IDWriteFactory_RegisterFontFileLoader(factory
, &rloader
);
3065 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3066 hr
= IDWriteFactory_RegisterFontCollectionLoader(factory
, &resource_collection
.IDWriteFontFileCollectionLoader_iface
);
3067 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3069 /* Loader wasn't registered. */
3070 font_collection
= (void*)0xdeadbeef;
3071 hr
= IDWriteFactory_CreateCustomFontCollection(factory
, loader3
, "Billy", 6, &font_collection
);
3072 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
3073 ok(font_collection
== NULL
, "got %p\n", font_collection
);
3075 EXPECT_REF(factory
, 1);
3076 hr
= IDWriteFactory_CreateCustomFontCollection(factory
, loader
, "Billy", 6, &font_collection
);
3077 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3079 EXPECT_REF(factory
, 1);
3080 EXPECT_REF(loader
, 2);
3081 IDWriteFontCollection_Release(font_collection
);
3083 hr
= IDWriteFactory_CreateCustomFontCollection(factory
, loader2
, "Billy", 6, &font_collection
);
3084 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3085 IDWriteFontCollection_Release(font_collection
);
3087 font_collection
= (void*)0xdeadbeef;
3088 hr
= IDWriteFactory_CreateCustomFontCollection(factory
, (IDWriteFontCollectionLoader
*)0xdeadbeef, "Billy", 6, &font_collection
);
3089 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
3090 ok(font_collection
== NULL
, "got %p\n", font_collection
);
3092 font
= FindResourceA(GetModuleHandleA(NULL
), (LPCSTR
)MAKEINTRESOURCE(1), (LPCSTR
)RT_RCDATA
);
3093 ok(font
!= NULL
, "Failed to find font resource\n");
3095 hr
= IDWriteFactory_CreateCustomFontCollection(factory
, &resource_collection
.IDWriteFontFileCollectionLoader_iface
,
3096 &font
, sizeof(HRSRC
), &font_collection
);
3097 ok(hr
== S_OK
, "Unexpected hr %#lx.\n",hr
);
3098 EXPECT_REF(font_collection
, 1);
3102 hr
= IDWriteFontCollection_FindFamilyName(font_collection
, L
"wine_test", &index
, &exists
);
3103 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3104 ok(index
== 0, "got index %i\n", index
);
3105 ok(exists
, "got exists %i\n", exists
);
3107 count
= IDWriteFontCollection_GetFontFamilyCount(font_collection
);
3108 ok(count
== 1, "got %u\n", count
);
3111 hr
= IDWriteFontCollection_GetFontFamily(font_collection
, 0, &family
);
3112 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3113 EXPECT_REF(family
, 1);
3116 hr
= IDWriteFontCollection_GetFontFamily(font_collection
, 0, &family2
);
3117 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3118 EXPECT_REF(family2
, 1);
3119 ok(family
!= family2
, "got %p, %p\n", family
, family2
);
3121 hr
= IDWriteFontFamily_GetFont(family
, 0, &idfont
);
3122 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3123 EXPECT_REF(idfont
, 1);
3124 EXPECT_REF(family
, 2);
3125 hr
= IDWriteFontFamily_GetFont(family
, 0, &idfont2
);
3126 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3127 EXPECT_REF(idfont2
, 1);
3128 EXPECT_REF(family
, 3);
3129 ok(idfont
!= idfont2
, "got %p, %p\n", idfont
, idfont2
);
3130 IDWriteFont_Release(idfont2
);
3132 hr
= IDWriteFont_GetInformationalStrings(idfont
, DWRITE_INFORMATIONAL_STRING_COPYRIGHT_NOTICE
, &string
, &exists
);
3133 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3134 ok(exists
, "got %d\n", exists
);
3135 EXPECT_REF(string
, 1);
3136 IDWriteLocalizedStrings_Release(string
);
3139 hr
= IDWriteFont_GetFontFamily(idfont
, &family3
);
3140 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3141 EXPECT_REF(family
, 3);
3142 ok(family
== family3
, "got %p, %p\n", family
, family3
);
3143 IDWriteFontFamily_Release(family3
);
3146 hr
= IDWriteFont_CreateFontFace(idfont
, &idfontface
);
3147 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3148 EXPECT_REF(idfont
, 1);
3151 hr
= IDWriteFontFamily_GetFont(family2
, 0, &idfont2
);
3152 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3153 EXPECT_REF(idfont2
, 1);
3154 EXPECT_REF(idfont
, 1);
3155 ok(idfont2
!= idfont
, "Font instances should not match\n");
3158 hr
= IDWriteFont_CreateFontFace(idfont2
, &idfontface2
);
3159 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3160 ok(idfontface2
== idfontface
, "fontfaces should match\n");
3164 hr
= IDWriteFontFace_GetFiles(idfontface
, &index
, &fontfile
);
3165 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3169 hr
= IDWriteFontFace_GetFiles(idfontface2
, &index
, &fontfile2
);
3170 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3171 ok(fontfile
== fontfile2
, "fontfiles should match\n");
3173 IDWriteFont_Release(idfont
);
3174 IDWriteFont_Release(idfont2
);
3175 IDWriteFontFile_Release(fontfile
);
3176 IDWriteFontFile_Release(fontfile2
);
3177 IDWriteFontFace_Release(idfontface
);
3178 IDWriteFontFace_Release(idfontface2
);
3179 IDWriteFontFamily_Release(family2
);
3180 IDWriteFontFamily_Release(family
);
3181 IDWriteFontCollection_Release(font_collection
);
3183 hr
= IDWriteFactory_UnregisterFontCollectionLoader(factory
, loader
);
3184 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3185 hr
= IDWriteFactory_UnregisterFontCollectionLoader(factory
, loader
);
3186 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
3187 hr
= IDWriteFactory_UnregisterFontCollectionLoader(factory
, loader2
);
3188 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3189 hr
= IDWriteFactory_UnregisterFontCollectionLoader(factory
, &resource_collection
.IDWriteFontFileCollectionLoader_iface
);
3190 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3191 hr
= IDWriteFactory_UnregisterFontFileLoader(factory
, &rloader
);
3192 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3194 IDWriteFontCollectionLoader_Release(loader
);
3195 IDWriteFontCollectionLoader_Release(loader2
);
3196 IDWriteFontCollectionLoader_Release(loader3
);
3198 ref
= IDWriteFactory_Release(factory
);
3199 ok(ref
== 0, "factory not released, %lu\n", ref
);
3202 static HRESULT WINAPI
fontfileloader_QueryInterface(IDWriteFontFileLoader
*iface
, REFIID riid
, void **obj
)
3204 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFontFileLoader
))
3207 IDWriteFontFileLoader_AddRef(iface
);
3212 return E_NOINTERFACE
;
3215 static ULONG WINAPI
fontfileloader_AddRef(IDWriteFontFileLoader
*iface
)
3220 static ULONG WINAPI
fontfileloader_Release(IDWriteFontFileLoader
*iface
)
3225 static HRESULT WINAPI
fontfileloader_CreateStreamFromKey(IDWriteFontFileLoader
*iface
, const void *ref_key
, UINT32 key_size
,
3226 IDWriteFontFileStream
**stream
)
3231 static const struct IDWriteFontFileLoaderVtbl dwritefontfileloadervtbl
= {
3232 fontfileloader_QueryInterface
,
3233 fontfileloader_AddRef
,
3234 fontfileloader_Release
,
3235 fontfileloader_CreateStreamFromKey
3238 static void test_CreateCustomFontFileReference(void)
3240 IDWriteFontFileLoader floader
= { &dwritefontfileloadervtbl
};
3241 IDWriteFontFileLoader floader2
= { &dwritefontfileloadervtbl
};
3242 IDWriteFontFileLoader floader3
= { &dwritefontfileloadervtbl
};
3243 IDWriteFactory
*factory
, *factory2
;
3244 IDWriteFontFileLoader
*loader
;
3245 IDWriteFontFile
*file
, *file2
;
3247 DWRITE_FONT_FILE_TYPE file_type
;
3248 DWRITE_FONT_FACE_TYPE face_type
;
3250 IDWriteFontFace
*face
, *face2
;
3253 UINT32 codePoints
[1] = {0xa8};
3260 path
= create_testfontfile(test_fontfile
);
3262 factory
= create_factory();
3263 factory2
= create_factory();
3265 if (0) { /* crashes on win10 */
3266 hr
= IDWriteFactory_RegisterFontFileLoader(factory
, NULL
);
3267 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
3269 /* local loader is accepted too */
3270 hr
= IDWriteFactory_CreateFontFileReference(factory
, path
, NULL
, &file
);
3271 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3273 hr
= IDWriteFontFile_GetLoader(file
, &loader
);
3274 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3276 hr
= IDWriteFontFile_GetReferenceKey(file
, &key
, &key_size
);
3277 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3279 hr
= IDWriteFactory_CreateCustomFontFileReference(factory
, key
, key_size
, loader
, &file2
);
3280 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3282 IDWriteFontFile_Release(file2
);
3283 IDWriteFontFile_Release(file
);
3284 IDWriteFontFileLoader_Release(loader
);
3286 hr
= IDWriteFactory_RegisterFontFileLoader(factory
, &floader
);
3287 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3288 hr
= IDWriteFactory_RegisterFontFileLoader(factory
, &floader2
);
3289 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3290 hr
= IDWriteFactory_RegisterFontFileLoader(factory
, &floader
);
3291 ok(hr
== DWRITE_E_ALREADYREGISTERED
, "Unexpected hr %#lx.\n", hr
);
3292 hr
= IDWriteFactory_RegisterFontFileLoader(factory
, &rloader
);
3293 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3296 hr
= IDWriteFactory_CreateCustomFontFileReference(factory
, "test", 4, &floader
, &file
);
3297 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3298 IDWriteFontFile_Release(file
);
3300 file
= (void*)0xdeadbeef;
3301 hr
= IDWriteFactory_CreateCustomFontFileReference(factory
, "test", 4, &floader3
, &file
);
3302 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
3303 ok(file
== NULL
, "got %p\n", file
);
3305 file
= (void*)0xdeadbeef;
3306 hr
= IDWriteFactory_CreateCustomFontFileReference(factory
, "test", 4, NULL
, &file
);
3307 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
3308 ok(file
== NULL
, "got %p\n", file
);
3311 hr
= IDWriteFactory_CreateCustomFontFileReference(factory
, "test", 4, &floader
, &file
);
3312 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3314 file_type
= DWRITE_FONT_FILE_TYPE_TRUETYPE
;
3315 face_type
= DWRITE_FONT_FACE_TYPE_TRUETYPE
;
3318 hr
= IDWriteFontFile_Analyze(file
, &support
, &file_type
, &face_type
, &count
);
3319 ok(hr
== 0x8faecafe, "Unexpected hr %#lx.\n", hr
);
3320 ok(support
== FALSE
, "got %i\n", support
);
3321 ok(file_type
== DWRITE_FONT_FILE_TYPE_UNKNOWN
, "got %i\n", file_type
);
3322 ok(face_type
== DWRITE_FONT_FACE_TYPE_UNKNOWN
, "got %i\n", face_type
);
3323 ok(count
== 0, "got %i\n", count
);
3325 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_CFF
, 1, &file
, 0, 0, &face
);
3326 ok(hr
== 0x8faecafe, "Unexpected hr %#lx.\n", hr
);
3327 IDWriteFontFile_Release(file
);
3329 fontrsrc
= FindResourceA(GetModuleHandleA(NULL
), (LPCSTR
)MAKEINTRESOURCE(1), (LPCSTR
)RT_RCDATA
);
3330 ok(fontrsrc
!= NULL
, "Failed to find font resource\n");
3332 hr
= IDWriteFactory_CreateCustomFontFileReference(factory
, &fontrsrc
, sizeof(HRSRC
), &rloader
, &file
);
3333 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3335 file_type
= DWRITE_FONT_FILE_TYPE_UNKNOWN
;
3336 face_type
= DWRITE_FONT_FACE_TYPE_UNKNOWN
;
3339 hr
= IDWriteFontFile_Analyze(file
, &support
, &file_type
, &face_type
, &count
);
3340 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3341 ok(support
== TRUE
, "got %i\n", support
);
3342 ok(file_type
== DWRITE_FONT_FILE_TYPE_TRUETYPE
, "got %i\n", file_type
);
3343 ok(face_type
== DWRITE_FONT_FACE_TYPE_TRUETYPE
, "got %i\n", face_type
);
3344 ok(count
== 1, "got %i\n", count
);
3347 face
= (void*)0xdeadbeef;
3348 hr
= IDWriteFactory_CreateFontFace(factory
, face_type
, 1, &file
, 1, DWRITE_FONT_SIMULATIONS_NONE
, &face
);
3349 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
3350 ok(face
== NULL
, "got %p\n", face
);
3352 hr
= IDWriteFactory_CreateFontFace(factory
, face_type
, 1, &file
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &face
);
3353 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3355 hr
= IDWriteFactory_CreateFontFace(factory
, face_type
, 1, &file
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &face2
);
3356 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3357 /* fontface instances are reused starting with win7 */
3358 ok(face
== face2
|| broken(face
!= face2
), "got %p, %p\n", face
, face2
);
3359 IDWriteFontFace_Release(face2
);
3361 /* file was created with different factory */
3363 hr
= IDWriteFactory_CreateFontFace(factory2
, face_type
, 1, &file
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &face2
);
3365 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3367 IDWriteFontFace_Release(face2
);
3370 hr
= IDWriteFactory_CreateCustomFontFileReference(factory
, &fontrsrc
, sizeof(HRSRC
), &rloader
, &file2
);
3371 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3372 ok(file
!= file2
, "got %p, %p\n", file
, file2
);
3374 hr
= IDWriteFactory_CreateFontFace(factory
, face_type
, 1, &file2
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &face2
);
3375 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3376 /* fontface instances are reused starting with win7 */
3377 ok(face
== face2
|| broken(face
!= face2
), "got %p, %p\n", face
, face2
);
3378 IDWriteFontFace_Release(face2
);
3379 IDWriteFontFile_Release(file2
);
3381 hr
= IDWriteFontFace_GetGlyphIndices(face
, NULL
, 0, NULL
);
3382 ok(hr
== E_INVALIDARG
|| broken(hr
== S_OK
) /* win8 */, "Unexpected hr %#lx.\n", hr
);
3384 hr
= IDWriteFontFace_GetGlyphIndices(face
, codePoints
, 0, NULL
);
3385 ok(hr
== E_INVALIDARG
|| broken(hr
== S_OK
) /* win8 */, "Unexpected hr %#lx.\n", hr
);
3387 hr
= IDWriteFontFace_GetGlyphIndices(face
, codePoints
, 0, indices
);
3388 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3390 hr
= IDWriteFontFace_GetGlyphIndices(face
, NULL
, 0, indices
);
3391 ok(hr
== E_INVALIDARG
|| broken(hr
== S_OK
) /* win8 */, "Unexpected hr %#lx.\n", hr
);
3393 indices
[0] = indices
[1] = 11;
3394 hr
= IDWriteFontFace_GetGlyphIndices(face
, NULL
, 1, indices
);
3395 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
3396 ok(indices
[0] == 0, "got index %i\n", indices
[0]);
3397 ok(indices
[1] == 11, "got index %i\n", indices
[1]);
3399 if (0) /* crashes on native */
3400 hr
= IDWriteFontFace_GetGlyphIndices(face
, NULL
, 1, NULL
);
3402 hr
= IDWriteFontFace_GetGlyphIndices(face
, codePoints
, 1, indices
);
3403 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3404 ok(indices
[0] == 7, "Unexpected glyph index, %u.\n", indices
[0]);
3405 IDWriteFontFace_Release(face
);
3406 IDWriteFontFile_Release(file
);
3408 hr
= IDWriteFactory_UnregisterFontFileLoader(factory
, &floader
);
3409 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3410 hr
= IDWriteFactory_UnregisterFontFileLoader(factory
, &floader
);
3411 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
3412 hr
= IDWriteFactory_UnregisterFontFileLoader(factory
, &floader2
);
3413 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3414 hr
= IDWriteFactory_UnregisterFontFileLoader(factory
, &rloader
);
3415 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3417 ref
= IDWriteFactory_Release(factory2
);
3418 ok(ref
== 0, "factory not released, %lu\n", ref
);
3419 ref
= IDWriteFactory_Release(factory
);
3420 ok(ref
== 0, "factory not released, %lu\n", ref
);
3421 DELETE_FONTFILE(path
);
3424 static void test_CreateFontFileReference(void)
3427 IDWriteFontFile
*ffile
= NULL
;
3429 DWRITE_FONT_FILE_TYPE type
;
3430 DWRITE_FONT_FACE_TYPE face
;
3432 IDWriteFontFace
*fface
= NULL
;
3433 IDWriteFactory
*factory
;
3437 path
= create_testfontfile(test_fontfile
);
3438 factory
= create_factory();
3440 ffile
= (void*)0xdeadbeef;
3441 hr
= IDWriteFactory_CreateFontFileReference(factory
, NULL
, NULL
, &ffile
);
3442 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n",hr
);
3443 ok(ffile
== NULL
, "got %p\n", ffile
);
3445 hr
= IDWriteFactory_CreateFontFileReference(factory
, path
, NULL
, &ffile
);
3446 ok(hr
== S_OK
, "Unexpected hr %#lx.\n",hr
);
3449 type
= DWRITE_FONT_FILE_TYPE_UNKNOWN
;
3450 face
= DWRITE_FONT_FACE_TYPE_CFF
;
3452 hr
= IDWriteFontFile_Analyze(ffile
, &support
, &type
, &face
, &count
);
3453 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3454 ok(support
== TRUE
, "got %i\n", support
);
3455 ok(type
== DWRITE_FONT_FILE_TYPE_TRUETYPE
, "got %i\n", type
);
3456 ok(face
== DWRITE_FONT_FACE_TYPE_TRUETYPE
, "got %i\n", face
);
3457 ok(count
== 1, "got %i\n", count
);
3459 hr
= IDWriteFactory_CreateFontFace(factory
, face
, 1, &ffile
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &fface
);
3460 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3462 IDWriteFontFace_Release(fface
);
3463 IDWriteFontFile_Release(ffile
);
3464 ref
= IDWriteFactory_Release(factory
);
3465 ok(ref
== 0, "factory not released, %lu\n", ref
);
3467 DELETE_FONTFILE(path
);
3470 static void test_shared_isolated(void)
3472 IDWriteFactory
*isolated
, *isolated2
;
3473 IDWriteFactory
*shared
, *shared2
;
3479 hr
= DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED
+1, &IID_IDWriteFactory
, (IUnknown
**)&shared
);
3480 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3481 ok(shared
!= NULL
, "got %p\n", shared
);
3482 IDWriteFactory_Release(shared
);
3484 hr
= DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED
, &IID_IDWriteFactory
, (IUnknown
**)&shared
);
3485 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3487 hr
= DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED
, &IID_IDWriteFactory
, (IUnknown
**)&shared2
);
3488 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3489 ok(shared
== shared2
, "got %p, and %p\n", shared
, shared2
);
3490 IDWriteFactory_Release(shared2
);
3492 IDWriteFactory_Release(shared
);
3494 /* we got 2 references, released 2 - still same pointer is returned */
3495 hr
= DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED
, &IID_IDWriteFactory
, (IUnknown
**)&shared2
);
3496 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3497 ok(shared
== shared2
, "got %p, and %p\n", shared
, shared2
);
3498 IDWriteFactory_Release(shared2
);
3500 hr
= DWriteCreateFactory(DWRITE_FACTORY_TYPE_ISOLATED
, &IID_IDWriteFactory
, (IUnknown
**)&isolated
);
3501 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3503 hr
= DWriteCreateFactory(DWRITE_FACTORY_TYPE_ISOLATED
, &IID_IDWriteFactory
, (IUnknown
**)&isolated2
);
3504 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3505 ok(isolated
!= isolated2
, "got %p, and %p\n", isolated
, isolated2
);
3506 IDWriteFactory_Release(isolated2
);
3508 hr
= DWriteCreateFactory(DWRITE_FACTORY_TYPE_ISOLATED
, &IID_IUnknown
, (IUnknown
**)&isolated2
);
3509 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3510 IDWriteFactory_Release(isolated2
);
3512 hr
= DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED
+1, &IID_IDWriteFactory
, (IUnknown
**)&isolated2
);
3513 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3514 ok(shared
!= isolated2
, "got %p, and %p\n", shared
, isolated2
);
3516 ref
= IDWriteFactory_Release(isolated
);
3517 ok(ref
== 0, "factory not released, %lu\n", ref
);
3518 ref
= IDWriteFactory_Release(isolated2
);
3519 ok(ref
== 0, "factory not released, %lu\n", ref
);
3522 struct dwrite_fonttable
3529 static WORD
table_read_be_word(const struct dwrite_fonttable
*table
, void *ptr
, DWORD offset
)
3534 if ((BYTE
*)ptr
< table
->data
|| (BYTE
*)ptr
- table
->data
>= table
->size
)
3537 if (offset
> table
->size
- sizeof(WORD
))
3540 return GET_BE_WORD(*(WORD
*)((BYTE
*)ptr
+ offset
));
3543 static DWORD
table_read_be_dword(const struct dwrite_fonttable
*table
, void *ptr
, DWORD offset
)
3548 if ((BYTE
*)ptr
< table
->data
|| (BYTE
*)ptr
- table
->data
>= table
->size
)
3551 if (offset
> table
->size
- sizeof(WORD
))
3554 return GET_BE_DWORD(*(DWORD
*)((BYTE
*)ptr
+ offset
));
3557 static void array_reserve(void **elements
, size_t *capacity
, size_t count
, size_t size
)
3559 size_t new_capacity
, max_capacity
;
3562 if (count
<= *capacity
)
3565 max_capacity
= ~(SIZE_T
)0 / size
;
3566 if (count
> max_capacity
)
3569 new_capacity
= max(4, *capacity
);
3570 while (new_capacity
< count
&& new_capacity
<= max_capacity
/ 2)
3572 if (new_capacity
< count
)
3573 new_capacity
= max_capacity
;
3575 if (!(new_elements
= realloc(*elements
, new_capacity
* size
)))
3578 *elements
= new_elements
;
3579 *capacity
= new_capacity
;
3582 static void opentype_cmap_read_table(const struct dwrite_fonttable
*table
, UINT16 cmap_index
, UINT32
*count
,
3583 size_t *capacity
, DWRITE_UNICODE_RANGE
**ranges
)
3585 const BYTE
*tables
= table
->data
+ FIELD_OFFSET(struct cmap_header
, tables
);
3586 struct cmap_encoding_record
*record
;
3591 record
= (struct cmap_encoding_record
*)(tables
+ cmap_index
* sizeof(*record
));
3593 if (!(table_offset
= table_read_be_dword(table
, record
, FIELD_OFFSET(struct cmap_encoding_record
, offset
))))
3596 format
= table_read_be_word(table
, NULL
, table_offset
);
3599 case OPENTYPE_CMAP_TABLE_SEGMENT_MAPPING
:
3601 UINT16 segment_count
= table_read_be_word(table
, NULL
, table_offset
+
3602 FIELD_OFFSET(struct cmap_segmented_mapping_0
, segCountX2
)) / 2;
3603 DWORD start_code_offset
= table_offset
+ sizeof(struct cmap_segmented_mapping_0
) +
3604 sizeof(WORD
) * segment_count
;
3606 for (j
= 0; j
< segment_count
; ++j
) {
3607 WORD endcode
= table_read_be_word(table
, NULL
, table_offset
+
3608 FIELD_OFFSET(struct cmap_segmented_mapping_0
, endCode
) + j
* sizeof(WORD
));
3611 if (endcode
== 0xffff)
3614 first
= table_read_be_word(table
, NULL
, start_code_offset
+ j
* sizeof(WORD
));
3616 array_reserve((void **)ranges
, capacity
, *count
+ 1, sizeof(**ranges
));
3617 (*ranges
)[*count
].first
= first
;
3618 (*ranges
)[*count
].last
= endcode
;
3623 case OPENTYPE_CMAP_TABLE_SEGMENTED_COVERAGE
:
3625 DWORD num_groups
= table_read_be_dword(table
, NULL
, table_offset
+
3626 FIELD_OFFSET(struct cmap_segmented_coverage
, nGroups
));
3628 for (j
= 0; j
< num_groups
; ++j
) {
3629 DWORD group_offset
= table_offset
+ FIELD_OFFSET(struct cmap_segmented_coverage
, groups
) +
3630 j
* sizeof(struct cmap_segmented_coverage_group
);
3631 DWORD first
= table_read_be_dword(table
, NULL
, group_offset
+
3632 FIELD_OFFSET(struct cmap_segmented_coverage_group
, startCharCode
));
3633 DWORD last
= table_read_be_dword(table
, NULL
, group_offset
+
3634 FIELD_OFFSET(struct cmap_segmented_coverage_group
, endCharCode
));
3636 array_reserve((void **)ranges
, capacity
, *count
+ 1, sizeof(**ranges
));
3637 (*ranges
)[*count
].first
= first
;
3638 (*ranges
)[*count
].last
= last
;
3644 ok(0, "%u table format %#x unhandled.\n", cmap_index
, format
);
3648 static UINT32
opentype_cmap_get_unicode_ranges(const struct dwrite_fonttable
*table
, DWRITE_UNICODE_RANGE
**ranges
)
3650 int index_full
= -1, index_bmp
= -1;
3651 unsigned int i
, count
= 0;
3652 size_t capacity
= 0;
3658 num_tables
= table_read_be_word(table
, 0, FIELD_OFFSET(struct cmap_header
, num_tables
));
3659 tables
= table
->data
+ FIELD_OFFSET(struct cmap_header
, tables
);
3661 for (i
= 0; i
< num_tables
; ++i
)
3663 struct cmap_encoding_record
*record
= (struct cmap_encoding_record
*)(tables
+ i
* sizeof(*record
));
3664 WORD platform
, encoding
;
3666 platform
= table_read_be_word(table
, record
, FIELD_OFFSET(struct cmap_encoding_record
, platformID
));
3667 encoding
= table_read_be_word(table
, record
, FIELD_OFFSET(struct cmap_encoding_record
, encodingID
));
3669 if (platform
== OPENTYPE_CMAP_TABLE_PLATFORM_WIN
)
3671 if (encoding
== OPENTYPE_CMAP_TABLE_ENCODING_UNICODE_FULL
)
3676 else if (encoding
== OPENTYPE_CMAP_TABLE_ENCODING_UNICODE_BMP
)
3681 if (index_full
!= -1)
3682 opentype_cmap_read_table(table
, index_full
, &count
, &capacity
, ranges
);
3683 else if (index_bmp
!= -1)
3684 opentype_cmap_read_table(table
, index_bmp
, &count
, &capacity
, ranges
);
3689 static UINT32
fontface_get_expected_unicode_ranges(IDWriteFontFace1
*fontface
, DWRITE_UNICODE_RANGE
**out
)
3691 struct dwrite_fonttable cmap
;
3692 DWRITE_UNICODE_RANGE
*ranges
;
3699 hr
= IDWriteFontFace1_TryGetFontTable(fontface
, MS_CMAP_TAG
, (const void **)&cmap
.data
,
3700 &cmap
.size
, &cmap
.context
, &exists
);
3701 if (FAILED(hr
) || !exists
)
3704 count
= opentype_cmap_get_unicode_ranges(&cmap
, &ranges
);
3705 IDWriteFontFace1_ReleaseFontTable(fontface
, cmap
.context
);
3707 *out
= malloc(count
* sizeof(**out
));
3709 /* Eliminate duplicates and merge ranges together. */
3710 for (i
= 0, j
= 0; i
< count
; ++i
) {
3712 DWRITE_UNICODE_RANGE
*prev
= &(*out
)[j
-1];
3713 /* Merge adjacent ranges. */
3714 if (ranges
[i
].first
== prev
->last
+ 1) {
3715 prev
->last
= ranges
[i
].last
;
3719 (*out
)[j
++] = ranges
[i
];
3727 static void test_GetUnicodeRanges(void)
3729 IDWriteFontCollection
*syscollection
;
3730 DWRITE_UNICODE_RANGE
*ranges
, r
;
3731 IDWriteFontFile
*ffile
= NULL
;
3732 IDWriteFontFace1
*fontface1
;
3733 IDWriteFontFace
*fontface
;
3734 IDWriteFactory
*factory
;
3740 factory
= create_factory();
3742 hr
= IDWriteFactory_RegisterFontFileLoader(factory
, &rloader
);
3743 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3745 font
= FindResourceA(GetModuleHandleA(NULL
), (LPCSTR
)MAKEINTRESOURCE(1), (LPCSTR
)RT_RCDATA
);
3746 ok(font
!= NULL
, "Failed to find font resource\n");
3748 hr
= IDWriteFactory_CreateCustomFontFileReference(factory
, &font
, sizeof(HRSRC
), &rloader
, &ffile
);
3749 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3751 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_TRUETYPE
, 1, &ffile
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &fontface
);
3752 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3753 IDWriteFontFile_Release(ffile
);
3755 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void**)&fontface1
);
3756 IDWriteFontFace_Release(fontface
);
3758 win_skip("GetUnicodeRanges() is not supported.\n");
3759 IDWriteFactory_Release(factory
);
3764 hr
= IDWriteFontFace1_GetUnicodeRanges(fontface1
, 0, NULL
, &count
);
3765 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "Unexpected hr %#lx.\n", hr
);
3766 ok(count
> 0, "got %u\n", count
);
3769 hr
= IDWriteFontFace1_GetUnicodeRanges(fontface1
, 1, NULL
, &count
);
3770 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
3771 ok(count
== 0, "got %u\n", count
);
3774 hr
= IDWriteFontFace1_GetUnicodeRanges(fontface1
, 1, &r
, &count
);
3775 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "Unexpected hr %#lx.\n", hr
);
3776 ok(count
> 1, "got %u\n", count
);
3778 ranges
= malloc(count
*sizeof(DWRITE_UNICODE_RANGE
));
3779 hr
= IDWriteFontFace1_GetUnicodeRanges(fontface1
, count
, ranges
, &count
);
3780 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3782 ranges
[0].first
= ranges
[0].last
= 0;
3783 hr
= IDWriteFontFace1_GetUnicodeRanges(fontface1
, 1, ranges
, &count
);
3784 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "Unexpected hr %#lx.\n", hr
);
3785 ok(ranges
[0].first
!= 0 && ranges
[0].last
!= 0, "got 0x%x-0x%0x\n", ranges
[0].first
, ranges
[0].last
);
3789 hr
= IDWriteFactory_UnregisterFontFileLoader(factory
, &rloader
);
3790 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3792 IDWriteFontFace1_Release(fontface1
);
3794 if (strcmp(winetest_platform
, "wine")) {
3796 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &syscollection
, FALSE
);
3797 ok(hr
== S_OK
, "Failed to get system collection, hr %#lx.\n", hr
);
3799 count
= IDWriteFontCollection_GetFontFamilyCount(syscollection
);
3801 for (i
= 0; i
< count
; i
++) {
3802 WCHAR familynameW
[256], facenameW
[128];
3803 IDWriteLocalizedStrings
*names
;
3804 IDWriteFontFamily
*family
;
3805 UINT32 j
, k
, fontcount
;
3808 hr
= IDWriteFontCollection_GetFontFamily(syscollection
, i
, &family
);
3809 ok(hr
== S_OK
, "Failed to get font family, hr %#lx.\n", hr
);
3811 hr
= IDWriteFontFamily_GetFamilyNames(family
, &names
);
3812 ok(hr
== S_OK
, "Failed to get family names, hr %#lx.\n", hr
);
3814 get_enus_string(names
, familynameW
, ARRAY_SIZE(familynameW
));
3815 IDWriteLocalizedStrings_Release(names
);
3817 fontcount
= IDWriteFontFamily_GetFontCount(family
);
3818 for (j
= 0; j
< fontcount
; j
++) {
3819 DWRITE_UNICODE_RANGE
*expected_ranges
= NULL
;
3820 UINT32 range_count
, expected_count
;
3822 hr
= IDWriteFontFamily_GetFont(family
, j
, &font
);
3823 ok(hr
== S_OK
, "Failed to get font, hr %#lx.\n", hr
);
3825 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
3826 ok(hr
== S_OK
, "Failed to create fontface, hr %#lx.\n", hr
);
3828 hr
= IDWriteFont_GetFaceNames(font
, &names
);
3829 ok(hr
== S_OK
, "Failed to get face names, hr %#lx.\n", hr
);
3830 IDWriteFont_Release(font
);
3832 get_enus_string(names
, facenameW
, ARRAY_SIZE(facenameW
));
3834 IDWriteLocalizedStrings_Release(names
);
3836 if (IDWriteFontFace_IsSymbolFont(fontface
))
3840 skip("GetUnicodeRanges() test does not support symbol fonts.\n");
3841 IDWriteFontFace_Release(fontface
);
3845 IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void **)&fontface1
);
3847 hr
= IDWriteFontFace1_GetUnicodeRanges(fontface1
, 0, NULL
, &range_count
);
3848 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "Unexpected hr %#lx.\n", hr
);
3850 ranges
= malloc(range_count
* sizeof(*ranges
));
3852 hr
= IDWriteFontFace1_GetUnicodeRanges(fontface1
, range_count
, ranges
, &range_count
);
3853 ok(hr
== S_OK
, "Failed to get ranges, hr %#lx.\n", hr
);
3855 expected_count
= fontface_get_expected_unicode_ranges(fontface1
, &expected_ranges
);
3856 ok(expected_count
== range_count
, "%s - %s: unexpected range count %u, expected %u.\n",
3857 wine_dbgstr_w(familynameW
), wine_dbgstr_w(facenameW
), range_count
, expected_count
);
3859 if (expected_count
== range_count
) {
3860 if (memcmp(expected_ranges
, ranges
, expected_count
* sizeof(*ranges
))) {
3861 for (k
= 0; k
< expected_count
; ++k
) {
3862 BOOL failed
= memcmp(&expected_ranges
[k
], &ranges
[k
], sizeof(*ranges
));
3863 ok(!failed
, "%u: %s - %s mismatching range [%#x, %#x] vs [%#x, %#x].\n", k
,
3864 wine_dbgstr_w(familynameW
), wine_dbgstr_w(facenameW
), ranges
[k
].first
, ranges
[k
].last
,
3865 expected_ranges
[k
].first
, expected_ranges
[k
].last
);
3872 free(expected_ranges
);
3875 IDWriteFontFace1_Release(fontface1
);
3876 IDWriteFontFace_Release(fontface
);
3879 IDWriteFontFamily_Release(family
);
3882 IDWriteFontCollection_Release(syscollection
);
3884 ref
= IDWriteFactory_Release(factory
);
3885 ok(ref
== 0, "factory not released, %lu\n", ref
);
3888 static void test_GetFontFromFontFace(void)
3890 IDWriteFontFace
*fontface
, *fontface2
;
3891 IDWriteFontCollection
*collection
;
3892 IDWriteFont
*font
, *font2
, *font3
;
3893 IDWriteFontFamily
*family
;
3894 IDWriteFactory
*factory
;
3895 IDWriteFontFile
*file
;
3900 factory
= create_factory();
3902 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &collection
, FALSE
);
3903 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3905 hr
= IDWriteFontCollection_GetFontFamily(collection
, 0, &family
);
3906 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3908 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
,
3909 DWRITE_FONT_STRETCH_NORMAL
, DWRITE_FONT_STYLE_NORMAL
, &font
);
3910 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3912 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
3913 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3916 hr
= IDWriteFontCollection_GetFontFromFontFace(collection
, fontface
, &font2
);
3917 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3918 ok(font2
!= font
, "got %p, %p\n", font2
, font
);
3921 hr
= IDWriteFontCollection_GetFontFromFontFace(collection
, fontface
, &font3
);
3922 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3923 ok(font3
!= font
&& font3
!= font2
, "got %p, %p, %p\n", font3
, font2
, font
);
3925 hr
= IDWriteFont_CreateFontFace(font2
, &fontface2
);
3926 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3927 ok(fontface2
== fontface
, "got %p, %p\n", fontface2
, fontface
);
3928 IDWriteFontFace_Release(fontface2
);
3930 hr
= IDWriteFont_CreateFontFace(font3
, &fontface2
);
3931 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3932 ok(fontface2
== fontface
, "got %p, %p\n", fontface2
, fontface
);
3933 IDWriteFontFace_Release(fontface2
);
3934 IDWriteFontFace_Release(fontface
);
3935 IDWriteFont_Release(font3
);
3936 IDWriteFactory_Release(factory
);
3938 /* fontface that wasn't created from this collection */
3939 factory
= create_factory();
3940 path
= create_testfontfile(test_fontfile
);
3942 hr
= IDWriteFactory_CreateFontFileReference(factory
, path
, NULL
, &file
);
3943 ok(hr
== S_OK
, "Unexpected hr %#lx.\n",hr
);
3945 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_TRUETYPE
, 1, &file
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &fontface
);
3946 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3947 IDWriteFontFile_Release(file
);
3949 hr
= IDWriteFontCollection_GetFontFromFontFace(collection
, fontface
, &font3
);
3950 ok(hr
== DWRITE_E_NOFONT
, "Unexpected hr %#lx.\n", hr
);
3951 ok(font3
== NULL
, "got %p\n", font3
);
3952 IDWriteFontFace_Release(fontface
);
3954 IDWriteFont_Release(font
);
3955 IDWriteFont_Release(font2
);
3956 IDWriteFontFamily_Release(family
);
3957 IDWriteFontCollection_Release(collection
);
3958 ref
= IDWriteFactory_Release(factory
);
3959 ok(ref
== 0, "factory not released, %lu\n", ref
);
3960 DELETE_FONTFILE(path
);
3963 static void test_GetFirstMatchingFont(void)
3965 DWRITE_FONT_SIMULATIONS simulations
;
3966 IDWriteFontCollection
*collection
;
3967 IDWriteFontFamily
*family
;
3968 IDWriteFont
*font
, *font2
;
3969 IDWriteFactory
*factory
;
3973 factory
= create_factory();
3975 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &collection
, FALSE
);
3976 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3978 hr
= IDWriteFontCollection_GetFontFamily(collection
, 0, &family
);
3979 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3981 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
,
3982 DWRITE_FONT_STRETCH_NORMAL
, DWRITE_FONT_STYLE_NORMAL
, &font
);
3983 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3985 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
,
3986 DWRITE_FONT_STRETCH_NORMAL
, DWRITE_FONT_STYLE_NORMAL
, &font2
);
3987 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3988 ok(font
!= font2
, "got %p, %p\n", font
, font2
);
3989 IDWriteFont_Release(font
);
3990 IDWriteFont_Release(font2
);
3992 /* out-of-range font props are allowed */
3993 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, 1000, DWRITE_FONT_STRETCH_NORMAL
, DWRITE_FONT_STYLE_NORMAL
, &font
);
3994 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3995 IDWriteFont_Release(font
);
3997 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
, 10, DWRITE_FONT_STYLE_NORMAL
, &font
);
3998 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3999 IDWriteFont_Release(font
);
4001 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STRETCH_NORMAL
,
4003 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4004 IDWriteFont_Release(font
);
4006 IDWriteFontFamily_Release(family
);
4008 font
= get_tahoma_instance(factory
, DWRITE_FONT_STYLE_ITALIC
);
4009 simulations
= IDWriteFont_GetSimulations(font
);
4010 ok(simulations
== DWRITE_FONT_SIMULATIONS_OBLIQUE
, "%d\n", simulations
);
4011 IDWriteFont_Release(font
);
4013 IDWriteFontCollection_Release(collection
);
4014 ref
= IDWriteFactory_Release(factory
);
4015 ok(ref
== 0, "factory not released, %lu\n", ref
);
4018 static void test_GetMatchingFonts(void)
4020 IDWriteFontCollection
*collection
;
4021 IDWriteFontFamily
*family
;
4022 IDWriteFactory
*factory
;
4023 IDWriteFontList
*fontlist
, *fontlist2
;
4024 IDWriteFontList1
*fontlist1
;
4025 IDWriteFontList2
*fontlist3
;
4029 factory
= create_factory();
4031 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &collection
, FALSE
);
4032 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4034 hr
= IDWriteFontCollection_GetFontFamily(collection
, 0, &family
);
4035 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4037 /* out-of-range font props are allowed */
4038 hr
= IDWriteFontFamily_GetMatchingFonts(family
, 1000, DWRITE_FONT_STRETCH_NORMAL
,
4039 DWRITE_FONT_STYLE_NORMAL
, &fontlist
);
4040 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4041 IDWriteFontList_Release(fontlist
);
4043 hr
= IDWriteFontFamily_GetMatchingFonts(family
, DWRITE_FONT_WEIGHT_NORMAL
, 10,
4044 DWRITE_FONT_STYLE_NORMAL
, &fontlist
);
4045 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4046 IDWriteFontList_Release(fontlist
);
4048 hr
= IDWriteFontFamily_GetMatchingFonts(family
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STRETCH_NORMAL
,
4050 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4051 IDWriteFontList_Release(fontlist
);
4053 hr
= IDWriteFontFamily_GetMatchingFonts(family
, DWRITE_FONT_WEIGHT_NORMAL
,
4054 DWRITE_FONT_STRETCH_NORMAL
, DWRITE_FONT_STYLE_NORMAL
, &fontlist
);
4055 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4057 hr
= IDWriteFontFamily_GetMatchingFonts(family
, DWRITE_FONT_WEIGHT_NORMAL
,
4058 DWRITE_FONT_STRETCH_NORMAL
, DWRITE_FONT_STYLE_NORMAL
, &fontlist2
);
4059 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4060 ok(fontlist
!= fontlist2
, "got %p, %p\n", fontlist
, fontlist2
);
4061 IDWriteFontList_Release(fontlist2
);
4063 hr
= IDWriteFontList_QueryInterface(fontlist
, &IID_IDWriteFontList1
, (void**)&fontlist1
);
4065 IDWriteFontFaceReference
*ref
, *ref1
;
4069 count
= IDWriteFontList1_GetFontCount(fontlist1
);
4070 ok(count
> 0, "got %u\n", count
);
4072 font
= (void*)0xdeadbeef;
4073 hr
= IDWriteFontList1_GetFont(fontlist1
, ~0u, &font
);
4074 ok(hr
== E_FAIL
, "Unexpected hr %#lx.\n", hr
);
4075 ok(font
== NULL
, "got %p\n", font
);
4077 font
= (void*)0xdeadbeef;
4078 hr
= IDWriteFontList1_GetFont(fontlist1
, count
, &font
);
4079 ok(hr
== E_FAIL
, "Unexpected hr %#lx.\n", hr
);
4080 ok(font
== NULL
, "got %p\n", font
);
4082 hr
= IDWriteFontList1_GetFont(fontlist1
, 0, &font
);
4083 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4084 IDWriteFont3_Release(font
);
4086 hr
= IDWriteFontList1_GetFontFaceReference(fontlist1
, 0, &ref
);
4087 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4089 hr
= IDWriteFontList1_GetFontFaceReference(fontlist1
, 0, &ref1
);
4090 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4091 ok(ref
!= ref1
, "got %p, %p\n", ref
, ref1
);
4093 IDWriteFontFaceReference_Release(ref1
);
4094 IDWriteFontFaceReference_Release(ref
);
4095 IDWriteFontList1_Release(fontlist1
);
4098 win_skip("IDWriteFontList1 is not supported.\n");
4100 if (SUCCEEDED(IDWriteFontList_QueryInterface(fontlist
, &IID_IDWriteFontList2
, (void **)&fontlist3
)))
4102 IDWriteFontSet1
*fontset
, *fontset2
;
4104 hr
= IDWriteFontList2_GetFontSet(fontlist3
, &fontset
);
4105 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4107 hr
= IDWriteFontList2_GetFontSet(fontlist3
, &fontset2
);
4108 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4109 ok(fontset
!= fontset2
, "Unexpected instance.\n");
4111 IDWriteFontSet1_Release(fontset2
);
4112 IDWriteFontSet1_Release(fontset
);
4114 IDWriteFontList2_Release(fontlist3
);
4117 win_skip("IDWriteFontList2 is not supported.\n");
4119 IDWriteFontList_Release(fontlist
);
4120 IDWriteFontFamily_Release(family
);
4122 IDWriteFontCollection_Release(collection
);
4123 ref
= IDWriteFactory_Release(factory
);
4124 ok(ref
== 0, "factory not released, %lu\n", ref
);
4127 static void test_GetInformationalStrings(void)
4129 IDWriteLocalizedStrings
*strings
, *strings2
;
4130 IDWriteFontCollection
*collection
;
4131 IDWriteFontFace3
*fontface3
;
4132 IDWriteFontFace
*fontface
;
4133 IDWriteFontFamily
*family
;
4134 IDWriteFactory
*factory
;
4140 factory
= create_factory();
4142 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &collection
, FALSE
);
4143 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4145 hr
= IDWriteFontCollection_GetFontFamily(collection
, 0, &family
);
4146 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4148 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
,
4149 DWRITE_FONT_STRETCH_NORMAL
, DWRITE_FONT_STYLE_NORMAL
, &font
);
4150 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4153 strings
= (void *)0xdeadbeef;
4154 hr
= IDWriteFont_GetInformationalStrings(font
, 0xdead, &strings
, &exists
);
4155 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4156 ok(exists
== FALSE
, "got %d\n", exists
);
4157 ok(strings
== NULL
, "got %p\n", strings
);
4161 hr
= IDWriteFont_GetInformationalStrings(font
, DWRITE_INFORMATIONAL_STRING_NONE
, &strings
, &exists
);
4162 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4163 ok(exists
== FALSE
, "got %d\n", exists
);
4167 hr
= IDWriteFont_GetInformationalStrings(font
, DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES
, &strings
, &exists
);
4168 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4169 ok(exists
== TRUE
, "got %d\n", exists
);
4171 /* strings instance is not reused */
4173 hr
= IDWriteFont_GetInformationalStrings(font
, DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES
, &strings2
, &exists
);
4174 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4175 ok(strings2
!= strings
, "got %p, %p\n", strings2
, strings
);
4177 IDWriteLocalizedStrings_Release(strings
);
4178 IDWriteLocalizedStrings_Release(strings2
);
4180 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
4181 ok(hr
== S_OK
, "Failed to create fontface, hr %#lx.\n", hr
);
4183 if (SUCCEEDED(hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace3
, (void **)&fontface3
)))
4185 hr
= IDWriteFontFace3_GetInformationalStrings(fontface3
, DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES
,
4187 ok(hr
== S_OK
, "Failed to get info strings, hr %#lx.\n", hr
);
4188 IDWriteLocalizedStrings_Release(strings
);
4190 IDWriteFontFace3_Release(fontface3
);
4193 win_skip("IDWriteFontFace3::GetInformationalStrings() is not supported.\n");
4195 IDWriteFontFace_Release(fontface
);
4197 IDWriteFont_Release(font
);
4198 IDWriteFontFamily_Release(family
);
4199 IDWriteFontCollection_Release(collection
);
4200 ref
= IDWriteFactory_Release(factory
);
4201 ok(ref
== 0, "factory not released, %lu\n", ref
);
4204 static void test_GetGdiInterop(void)
4206 IDWriteGdiInterop
*interop
, *interop2
;
4207 IDWriteFactory
*factory
, *factory2
;
4213 factory
= create_factory();
4216 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop
);
4217 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4220 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop2
);
4221 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4222 ok(interop
== interop2
, "got %p, %p\n", interop
, interop2
);
4223 IDWriteGdiInterop_Release(interop2
);
4225 hr
= DWriteCreateFactory(DWRITE_FACTORY_TYPE_ISOLATED
, &IID_IDWriteFactory
, (IUnknown
**)&factory2
);
4226 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4228 /* each factory gets its own interop */
4230 hr
= IDWriteFactory_GetGdiInterop(factory2
, &interop2
);
4231 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4232 ok(interop
!= interop2
, "got %p, %p\n", interop
, interop2
);
4234 /* release factory - interop still works */
4235 IDWriteFactory_Release(factory2
);
4237 memset(&logfont
, 0, sizeof(logfont
));
4238 logfont
.lfHeight
= 12;
4239 logfont
.lfWidth
= 12;
4240 logfont
.lfWeight
= FW_NORMAL
;
4241 logfont
.lfItalic
= 1;
4242 lstrcpyW(logfont
.lfFaceName
, L
"Tahoma");
4244 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop2
, &logfont
, &font
);
4245 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4246 IDWriteFont_Release(font
);
4248 IDWriteGdiInterop_Release(interop2
);
4249 IDWriteGdiInterop_Release(interop
);
4250 ref
= IDWriteFactory_Release(factory
);
4251 ok(ref
== 0, "factory not released, %lu\n", ref
);
4254 static void *map_font_file(const WCHAR
*filename
, DWORD
*file_size
)
4256 HANDLE file
, mapping
;
4259 file
= CreateFileW(filename
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
, 0, 0);
4260 if (file
== INVALID_HANDLE_VALUE
) return NULL
;
4262 *file_size
= GetFileSize(file
, NULL
);
4264 mapping
= CreateFileMappingA(file
, NULL
, PAGE_READONLY
, 0, 0, NULL
);
4271 ptr
= MapViewOfFile(mapping
, FILE_MAP_READ
, 0, 0, 0);
4274 CloseHandle(mapping
);
4278 struct font_realization_info
4289 static void test_CreateFontFaceFromHdc(void)
4291 IDWriteFontFileStream
*stream
, *stream2
;
4292 void *font_data
, *fragment_context
;
4293 struct font_realization_info info
;
4294 const void *refkey
, *fragment
;
4295 IDWriteFontFileLoader
*loader
;
4296 DWORD data_size
, num_fonts
;
4297 IDWriteGdiInterop
*interop
;
4298 IDWriteFontFace
*fontface
;
4299 IDWriteFactory
*factory
;
4300 UINT64 size
, writetime
;
4301 IDWriteFontFile
*file
;
4302 HFONT hfont
, oldhfont
;
4303 UINT32 count
, dummy
;
4314 factory
= create_factory();
4316 pGetFontRealizationInfo
= (void *)GetProcAddress(GetModuleHandleA("gdi32"), "GetFontRealizationInfo");
4319 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop
);
4320 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4323 fontface
= (void*)0xdeadbeef;
4324 hr
= IDWriteGdiInterop_CreateFontFaceFromHdc(interop
, NULL
, &fontface
);
4325 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
4326 ok(fontface
== NULL
, "got %p\n", fontface
);
4328 fontface
= (void *)0xdeadbeef;
4329 hr
= IDWriteGdiInterop_CreateFontFaceFromHdc(interop
, (HDC
)0xdeadbeef, &fontface
);
4330 ok(hr
== E_FAIL
, "Unexpected hr %#lx.\n", hr
);
4331 ok(fontface
== NULL
, "got %p\n", fontface
);
4333 memset(&logfont
, 0, sizeof(logfont
));
4334 logfont
.lfHeight
= 12;
4335 logfont
.lfWidth
= 12;
4336 logfont
.lfWeight
= FW_NORMAL
;
4337 logfont
.lfItalic
= 1;
4338 lstrcpyW(logfont
.lfFaceName
, L
"Tahoma");
4340 hfont
= CreateFontIndirectW(&logfont
);
4341 hdc
= CreateCompatibleDC(0);
4342 oldhfont
= SelectObject(hdc
, hfont
);
4345 hr
= IDWriteGdiInterop_CreateFontFaceFromHdc(interop
, hdc
, &fontface
);
4346 ok(hr
== S_OK
, "Failed to create font face, hr %#lx.\n", hr
);
4349 hr
= IDWriteFontFace_GetFiles(fontface
, &count
, &file
);
4350 ok(hr
== S_OK
, "Failed to get font files, hr %#lx.\n", hr
);
4352 hr
= IDWriteFontFile_GetLoader(file
, &loader
);
4353 ok(hr
== S_OK
, "Failed to get file loader, hr %#lx.\n", hr
);
4355 hr
= IDWriteFontFileLoader_QueryInterface(loader
, &IID_IDWriteLocalFontFileLoader
, (void **)&unk
);
4356 ok(hr
== S_OK
|| broken(hr
== E_NOINTERFACE
) /* Vista */, "Expected local loader, hr %#lx.\n", hr
);
4358 IUnknown_Release(unk
);
4360 IDWriteFontFileLoader_Release(loader
);
4361 IDWriteFontFile_Release(file
);
4363 IDWriteFontFace_Release(fontface
);
4364 DeleteObject(SelectObject(hdc
, oldhfont
));
4366 /* Select bitmap font MS Sans Serif, format that's not supported by DirectWrite. */
4367 memset(&lf
, 0, sizeof(lf
));
4369 strcpy(lf
.lfFaceName
, "MS Sans Serif");
4371 hfont
= CreateFontIndirectA(&lf
);
4372 oldhfont
= SelectObject(hdc
, hfont
);
4374 fontface
= (void *)0xdeadbeef;
4375 hr
= IDWriteGdiInterop_CreateFontFaceFromHdc(interop
, hdc
, &fontface
);
4376 ok(hr
== DWRITE_E_FILEFORMAT
|| broken(hr
== E_FAIL
) /* Vista */, "Unexpected hr %#lx.\n", hr
);
4377 ok(fontface
== NULL
, "got %p\n", fontface
);
4379 DeleteObject(SelectObject(hdc
, oldhfont
));
4381 /* Memory resource font */
4382 path
= create_testfontfile(test_fontfile
);
4385 font_data
= map_font_file(path
, &data_size
);
4388 resource
= AddFontMemResourceEx(font_data
, data_size
, NULL
, &num_fonts
);
4389 ok(resource
!= NULL
, "Failed to add memory resource font, %ld.\n", GetLastError());
4390 ok(num_fonts
== 1, "Unexpected number of fonts.\n");
4392 memset(&lf
, 0, sizeof(lf
));
4394 strcpy(lf
.lfFaceName
, "wine_test");
4396 hfont
= CreateFontIndirectA(&lf
);
4397 ok(hfont
!= NULL
, "Failed to create a font.\n");
4398 oldhfont
= SelectObject(hdc
, hfont
);
4400 hr
= IDWriteGdiInterop_CreateFontFaceFromHdc(interop
, hdc
, &fontface
);
4401 ok(hr
== S_OK
, "Failed to create fontface, hr %#lx.\n", hr
);
4404 hr
= IDWriteFontFace_GetFiles(fontface
, &count
, &file
);
4405 ok(hr
== S_OK
, "Failed to get font files, hr %#lx.\n", hr
);
4407 hr
= IDWriteFontFile_GetLoader(file
, &loader
);
4408 ok(hr
== S_OK
, "Failed to get file loader, hr %#lx.\n", hr
);
4410 hr
= IDWriteFactory_RegisterFontFileLoader(factory
, loader
);
4411 ok(hr
== DWRITE_E_ALREADYREGISTERED
, "Unexpected hr %#lx.\n", hr
);
4413 hr
= IDWriteFontFileLoader_QueryInterface(loader
, &IID_IDWriteInMemoryFontFileLoader
, (void **)&unk
);
4414 ok(hr
== E_NOINTERFACE
, "Unexpected hr %#lx.\n", hr
);
4416 hr
= IDWriteFontFileLoader_QueryInterface(loader
, &IID_IDWriteLocalFontFileLoader
, (void **)&unk
);
4417 ok(hr
== E_NOINTERFACE
, "Unexpected hr %#lx.\n", hr
);
4420 hr
= IDWriteFontFile_GetReferenceKey(file
, &refkey
, &count
);
4421 ok(hr
== S_OK
, "Failed to get ref key, hr %#lx.\n", hr
);
4422 ok(count
> 0, "Unexpected key length %u.\n", count
);
4424 if (pGetFontRealizationInfo
)
4426 info
.size
= sizeof(info
);
4427 ret
= pGetFontRealizationInfo(hdc
, &info
);
4428 ok(ret
, "Failed to get realization info.\n");
4429 ok(count
== sizeof(info
.instance_id
), "Unexpected key size.\n");
4430 ok(*(DWORD
*)refkey
== info
.instance_id
, "Unexpected stream key.\n");
4433 win_skip("GetFontRealizationInfo() is not available.\n");
4435 hr
= IDWriteFontFileLoader_CreateStreamFromKey(loader
, refkey
, count
, &stream
);
4436 ok(hr
== S_OK
, "Failed to create file stream, hr %#lx.\n", hr
);
4438 hr
= IDWriteFontFileLoader_CreateStreamFromKey(loader
, refkey
, count
, &stream2
);
4439 ok(hr
== S_OK
, "Failed to create file stream, hr %#lx.\n", hr
);
4440 ok(stream2
!= stream
, "Unexpected stream instance.\n");
4441 IDWriteFontFileStream_Release(stream2
);
4444 hr
= IDWriteFontFileLoader_CreateStreamFromKey(loader
, &dummy
, count
, &stream2
);
4445 ok(hr
== S_OK
, "Failed to create file stream, hr %#lx.\n", hr
);
4448 hr
= IDWriteFontFileStream_GetLastWriteTime(stream2
, &writetime
);
4449 ok(hr
== E_NOTIMPL
, "Unexpected hr %#lx.\n", hr
);
4450 ok(writetime
== 1, "Unexpected write time.\n");
4452 IDWriteFontFileStream_Release(stream2
);
4454 hr
= IDWriteFontFileStream_GetFileSize(stream
, &size
);
4455 ok(hr
== S_OK
, "Failed to get stream size, hr %#lx.\n", hr
);
4456 ok(size
== data_size
, "Unexpected stream size.\n");
4458 hr
= IDWriteFontFileStream_GetLastWriteTime(stream
, &writetime
);
4459 ok(hr
== E_NOTIMPL
, "Unexpected hr %#lx.\n", hr
);
4461 fragment_context
= NULL
;
4462 hr
= IDWriteFontFileStream_ReadFileFragment(stream
, &fragment
, 0, size
, &fragment_context
);
4463 ok(hr
== S_OK
, "Failed to read fragment, hr %#lx.\n", hr
);
4464 ok(fragment_context
!= NULL
, "Unexpected context %p.\n", fragment_context
);
4465 ok(fragment
== fragment_context
, "Unexpected data pointer %p, context %p.\n", fragment
, fragment_context
);
4466 IDWriteFontFileStream_ReleaseFileFragment(stream
, fragment_context
);
4468 hr
= IDWriteFontFileStream_ReadFileFragment(stream
, &fragment
, 0, size
+ 1, &fragment_context
);
4469 ok(FAILED(hr
), "Unexpected hr %#lx.\n", hr
);
4471 hr
= IDWriteFontFileStream_ReadFileFragment(stream
, &fragment
, size
- 1, size
/ 2, &fragment_context
);
4472 ok(FAILED(hr
), "Unexpected hr %#lx.\n", hr
);
4474 IDWriteFontFileStream_Release(stream
);
4476 IDWriteFontFileLoader_Release(loader
);
4477 IDWriteFontFile_Release(file
);
4479 IDWriteFontFace_Release(fontface
);
4481 ret
= RemoveFontMemResourceEx(resource
);
4482 ok(ret
, "Failed to remove memory resource font, %ld.\n", GetLastError());
4484 UnmapViewOfFile(font_data
);
4486 DELETE_FONTFILE(path
);
4488 DeleteObject(SelectObject(hdc
, oldhfont
));
4490 IDWriteGdiInterop_Release(interop
);
4491 ref
= IDWriteFactory_Release(factory
);
4492 ok(ref
== 0, "factory not released, %lu\n", ref
);
4495 static void test_GetSimulations(void)
4497 DWRITE_FONT_SIMULATIONS simulations
;
4498 IDWriteGdiInterop
*interop
;
4499 IDWriteFontFace
*fontface
;
4500 IDWriteFactory
*factory
;
4506 factory
= create_factory();
4508 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop
);
4509 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4511 memset(&logfont
, 0, sizeof(logfont
));
4512 logfont
.lfHeight
= 12;
4513 logfont
.lfWidth
= 12;
4514 logfont
.lfWeight
= FW_NORMAL
;
4515 logfont
.lfItalic
= 1;
4516 lstrcpyW(logfont
.lfFaceName
, L
"Tahoma");
4518 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font
);
4519 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4521 simulations
= IDWriteFont_GetSimulations(font
);
4522 ok(simulations
== DWRITE_FONT_SIMULATIONS_OBLIQUE
, "got %d\n", simulations
);
4523 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
4524 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4525 simulations
= IDWriteFontFace_GetSimulations(fontface
);
4526 ok(simulations
== DWRITE_FONT_SIMULATIONS_OBLIQUE
, "got %d\n", simulations
);
4527 IDWriteFontFace_Release(fontface
);
4528 IDWriteFont_Release(font
);
4530 memset(&logfont
, 0, sizeof(logfont
));
4531 logfont
.lfHeight
= 12;
4532 logfont
.lfWidth
= 12;
4533 logfont
.lfWeight
= FW_NORMAL
;
4534 logfont
.lfItalic
= 0;
4535 lstrcpyW(logfont
.lfFaceName
, L
"Tahoma");
4537 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font
);
4538 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4540 simulations
= IDWriteFont_GetSimulations(font
);
4541 ok(simulations
== DWRITE_FONT_SIMULATIONS_NONE
, "got %d\n", simulations
);
4542 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
4543 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4544 simulations
= IDWriteFontFace_GetSimulations(fontface
);
4545 ok(simulations
== DWRITE_FONT_SIMULATIONS_NONE
, "got %d\n", simulations
);
4546 IDWriteFontFace_Release(fontface
);
4547 IDWriteFont_Release(font
);
4549 IDWriteGdiInterop_Release(interop
);
4550 ref
= IDWriteFactory_Release(factory
);
4551 ok(ref
== 0, "factory not released, %lu\n", ref
);
4554 static void test_GetFaceNames(void)
4556 IDWriteLocalizedStrings
*strings
, *strings2
, *strings3
;
4557 IDWriteFontFace3
*fontface3
;
4558 IDWriteGdiInterop
*interop
;
4559 IDWriteFontFace
*fontface
;
4560 IDWriteFactory
*factory
;
4561 UINT32 count
, index
;
4569 factory
= create_factory();
4571 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop
);
4572 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4574 memset(&logfont
, 0, sizeof(logfont
));
4575 logfont
.lfHeight
= 12;
4576 logfont
.lfWidth
= 12;
4577 logfont
.lfWeight
= FW_NORMAL
;
4578 logfont
.lfItalic
= 1;
4579 lstrcpyW(logfont
.lfFaceName
, L
"Tahoma");
4581 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font
);
4582 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4584 hr
= IDWriteFont_GetFaceNames(font
, &strings
);
4585 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4587 hr
= IDWriteFont_GetFaceNames(font
, &strings2
);
4588 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4589 ok(strings
!= strings2
, "got %p, %p\n", strings2
, strings
);
4590 IDWriteLocalizedStrings_Release(strings2
);
4592 count
= IDWriteLocalizedStrings_GetCount(strings
);
4593 ok(count
== 1, "got %d\n", count
);
4597 hr
= IDWriteLocalizedStrings_FindLocaleName(strings
, L
"en-Us", &index
, &exists
);
4598 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4599 ok(index
== 0 && exists
, "got %d, %d\n", index
, exists
);
4602 hr
= IDWriteLocalizedStrings_GetLocaleNameLength(strings
, 1, &count
);
4603 ok(hr
== E_FAIL
, "Unexpected hr %#lx.\n", hr
);
4604 ok(count
== ~0, "got %d\n", count
);
4606 /* for simulated faces names are also simulated */
4608 hr
= IDWriteLocalizedStrings_GetLocaleName(strings
, 0, buffW
, ARRAY_SIZE(buffW
));
4609 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4610 ok(!lstrcmpW(buffW
, L
"en-us"), "Unexpected locale name %s.\n", wine_dbgstr_w(buffW
));
4613 hr
= IDWriteLocalizedStrings_GetString(strings
, 0, buffW
, ARRAY_SIZE(buffW
));
4614 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4615 ok(!lstrcmpW(buffW
, L
"Oblique"), "got %s\n", wine_dbgstr_w(buffW
));
4616 IDWriteLocalizedStrings_Release(strings
);
4618 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
4619 ok(hr
== S_OK
, "Failed to create a font face, hr %#lx.\n", hr
);
4621 if (SUCCEEDED(IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace3
, (void **)&fontface3
)))
4623 hr
= IDWriteFontFace3_GetFaceNames(fontface3
, &strings2
);
4624 ok(hr
== S_OK
, "Failed to get face names, hr %#lx.\n", hr
);
4626 hr
= IDWriteFontFace3_GetFaceNames(fontface3
, &strings3
);
4627 ok(hr
== S_OK
, "Failed to get face names, hr %#lx.\n", hr
);
4628 ok(strings2
!= strings3
, "Unexpected instance.\n");
4629 IDWriteLocalizedStrings_Release(strings3
);
4632 hr
= IDWriteLocalizedStrings_GetString(strings2
, 0, buffW
, ARRAY_SIZE(buffW
));
4633 ok(hr
== S_OK
, "Failed to get a string, hr %#lx.\n", hr
);
4634 ok(!lstrcmpW(buffW
, L
"Oblique"), "Unexpected name %s.\n", wine_dbgstr_w(buffW
));
4635 IDWriteLocalizedStrings_Release(strings2
);
4637 IDWriteFontFace3_Release(fontface3
);
4640 win_skip("GetFaceNames() is not supported.\n");
4642 IDWriteFontFace_Release(fontface
);
4644 IDWriteFont_Release(font
);
4645 IDWriteGdiInterop_Release(interop
);
4646 ref
= IDWriteFactory_Release(factory
);
4647 ok(ref
== 0, "factory not released, %lu\n", ref
);
4656 static void test_TryGetFontTable(void)
4658 IDWriteLocalFontFileLoader
*localloader
;
4659 WIN32_FILE_ATTRIBUTE_DATA info
;
4660 const struct local_refkey
*key
;
4661 IDWriteFontFileLoader
*loader
;
4662 const void *table
, *table2
;
4663 IDWriteFontFace
*fontface
;
4664 void *context
, *context2
;
4665 IDWriteFactory
*factory
;
4666 IDWriteFontFile
*file
;
4667 WCHAR buffW
[MAX_PATH
];
4674 path
= create_testfontfile(test_fontfile
);
4676 factory
= create_factory();
4678 hr
= IDWriteFactory_CreateFontFileReference(factory
, path
, NULL
, &file
);
4679 ok(hr
== S_OK
, "Unexpected hr %#lx.\n",hr
);
4683 hr
= IDWriteFontFile_GetReferenceKey(file
, (const void**)&key
, &size
);
4684 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4685 ok(size
!= 0, "got %u\n", size
);
4687 ret
= GetFileAttributesExW(path
, GetFileExInfoStandard
, &info
);
4688 ok(ret
, "got %d\n", ret
);
4689 ok(!memcmp(&info
.ftLastWriteTime
, &key
->writetime
, sizeof(key
->writetime
)), "got wrong write time\n");
4691 hr
= IDWriteFontFile_GetLoader(file
, &loader
);
4692 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4693 IDWriteFontFileLoader_QueryInterface(loader
, &IID_IDWriteLocalFontFileLoader
, (void**)&localloader
);
4694 IDWriteFontFileLoader_Release(loader
);
4696 hr
= IDWriteLocalFontFileLoader_GetFilePathLengthFromKey(localloader
, key
, size
, &len
);
4697 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4698 ok(lstrlenW(key
->name
) == len
, "path length %d\n", len
);
4700 hr
= IDWriteLocalFontFileLoader_GetFilePathFromKey(localloader
, key
, size
, buffW
, ARRAY_SIZE(buffW
));
4701 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4702 ok(!lstrcmpW(buffW
, key
->name
), "got %s, expected %s\n", wine_dbgstr_w(buffW
), wine_dbgstr_w(key
->name
));
4703 IDWriteLocalFontFileLoader_Release(localloader
);
4705 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_TRUETYPE
, 1, &file
, 0, 0, &fontface
);
4706 ok(hr
== S_OK
, "Unexpected hr %#lx.\n",hr
);
4709 context
= (void*)0xdeadbeef;
4711 hr
= IDWriteFontFace_TryGetFontTable(fontface
, MS_CMAP_TAG
, &table
, &size
, &context
, &exists
);
4712 ok(hr
== S_OK
, "Unexpected hr %#lx.\n",hr
);
4713 ok(exists
== TRUE
, "got %d\n", exists
);
4714 ok(context
== NULL
&& table
!= NULL
, "cmap: context %p, table %p\n", context
, table
);
4717 context2
= (void*)0xdeadbeef;
4719 hr
= IDWriteFontFace_TryGetFontTable(fontface
, MS_CMAP_TAG
, &table2
, &size
, &context2
, &exists
);
4720 ok(hr
== S_OK
, "Unexpected hr %#lx.\n",hr
);
4721 ok(exists
== TRUE
, "got %d\n", exists
);
4722 ok(context2
== context
&& table2
== table
, "cmap: context2 %p, table2 %p\n", context2
, table2
);
4724 IDWriteFontFace_ReleaseFontTable(fontface
, context2
);
4725 IDWriteFontFace_ReleaseFontTable(fontface
, context
);
4727 /* table does not exist */
4729 context
= (void*)0xdeadbeef;
4730 table
= (void*)0xdeadbeef;
4731 hr
= IDWriteFontFace_TryGetFontTable(fontface
, 0xabababab, &table
, &size
, &context
, &exists
);
4732 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4733 ok(exists
== FALSE
, "got %d\n", exists
);
4734 ok(context
== NULL
&& table
== NULL
, "got context %p, table pointer %p\n", context
, table
);
4736 IDWriteFontFace_Release(fontface
);
4737 IDWriteFontFile_Release(file
);
4738 ref
= IDWriteFactory_Release(factory
);
4739 ok(ref
== 0, "factory not released, %lu\n", ref
);
4740 DELETE_FONTFILE(path
);
4743 static void test_ConvertFontToLOGFONT(void)
4745 IDWriteFactory
*factory
, *factory2
;
4746 IDWriteFontCollection
*collection
;
4747 IDWriteGdiInterop
*interop
;
4748 IDWriteFontFamily
*family
;
4756 factory
= create_factory();
4757 factory2
= create_factory();
4760 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop
);
4761 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4763 hr
= IDWriteFactory_GetSystemFontCollection(factory2
, &collection
, FALSE
);
4764 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4766 hr
= IDWriteFontCollection_GetFontFamily(collection
, 0, &family
);
4767 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4769 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
,
4770 DWRITE_FONT_STRETCH_NORMAL
, DWRITE_FONT_STYLE_NORMAL
, &font
);
4771 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4773 if (0) { /* crashes on native */
4774 IDWriteGdiInterop_ConvertFontToLOGFONT(interop
, NULL
, NULL
, NULL
);
4775 IDWriteGdiInterop_ConvertFontToLOGFONT(interop
, NULL
, &logfont
, NULL
);
4776 IDWriteGdiInterop_ConvertFontToLOGFONT(interop
, font
, NULL
, &system
);
4779 memset(&logfont
, 0xcc, sizeof(logfont
));
4781 hr
= IDWriteGdiInterop_ConvertFontToLOGFONT(interop
, NULL
, &logfont
, &system
);
4782 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
4783 ok(!system
, "got %d\n", system
);
4784 ok(logfont
.lfFaceName
[0] == 0, "got face name %s\n", wine_dbgstr_w(logfont
.lfFaceName
));
4786 count
= IDWriteFontCollection_GetFontFamilyCount(collection
);
4787 for (i
= 0; i
< count
; i
++) {
4788 WCHAR nameW
[128], familynameW
[64], facenameW
[64];
4789 IDWriteLocalizedStrings
*names
;
4790 DWRITE_FONT_SIMULATIONS sim
;
4791 IDWriteFontFamily
*family
;
4792 UINT32 font_count
, j
;
4796 hr
= IDWriteFontCollection_GetFontFamily(collection
, i
, &family
);
4797 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4799 hr
= IDWriteFontFamily_GetFamilyNames(family
, &names
);
4800 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4802 get_enus_string(names
, familynameW
, ARRAY_SIZE(familynameW
));
4803 IDWriteLocalizedStrings_Release(names
);
4805 font_count
= IDWriteFontFamily_GetFontCount(family
);
4807 for (j
= 0; j
< font_count
; ++j
)
4809 IDWriteFontFace
*fontface
;
4810 BOOL has_variations
;
4812 hr
= IDWriteFontFamily_GetFont(family
, j
, &font
);
4813 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4815 hr
= IDWriteFont_GetFaceNames(font
, &names
);
4816 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4818 get_enus_string(names
, facenameW
, ARRAY_SIZE(facenameW
));
4819 IDWriteLocalizedStrings_Release(names
);
4821 lstrcpyW(nameW
, familynameW
);
4822 lstrcatW(nameW
, L
" ");
4823 lstrcatW(nameW
, facenameW
);
4825 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
4826 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4828 has_variations
= has_face_variations(fontface
);
4829 IDWriteFontFace_Release(fontface
);
4835 skip("ConvertFontToLOGFONT() test does not support variable fonts.\n");
4836 IDWriteFont_Release(font
);
4841 memset(&logfont
, 0xcc, sizeof(logfont
));
4842 hr
= IDWriteGdiInterop_ConvertFontToLOGFONT(interop
, font
, &logfont
, &system
);
4843 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4844 ok(system
, "got %d\n", system
);
4846 sim
= IDWriteFont_GetSimulations(font
);
4848 winetest_push_context("Font %s", wine_dbgstr_w(nameW
));
4850 get_logfont_from_font(font
, &lf
);
4851 ok(logfont
.lfWeight
== lf
.lfWeight
, "Unexpected lfWeight %ld, expected lfWeight %ld, font weight %d, "
4852 "bold simulation %s.\n", logfont
.lfWeight
, lf
.lfWeight
, IDWriteFont_GetWeight(font
),
4853 sim
& DWRITE_FONT_SIMULATIONS_BOLD
? "yes" : "no");
4854 ok(logfont
.lfItalic
== lf
.lfItalic
, "Unexpected italic flag %d, oblique simulation %s.\n",
4855 logfont
.lfItalic
, sim
& DWRITE_FONT_SIMULATIONS_OBLIQUE
? "yes" : "no");
4856 ok(!lstrcmpW(logfont
.lfFaceName
, lf
.lfFaceName
), "Unexpected facename %s, expected %s.\n",
4857 wine_dbgstr_w(logfont
.lfFaceName
), wine_dbgstr_w(lf
.lfFaceName
));
4859 ok(logfont
.lfOutPrecision
== OUT_OUTLINE_PRECIS
, "Unexpected output precision %d.\n", logfont
.lfOutPrecision
);
4860 ok(logfont
.lfClipPrecision
== CLIP_DEFAULT_PRECIS
, "Unexpected clipping precision %d.\n", logfont
.lfClipPrecision
);
4861 ok(logfont
.lfQuality
== DEFAULT_QUALITY
, "Unexpected quality %d.\n", logfont
.lfQuality
);
4862 ok(logfont
.lfPitchAndFamily
== DEFAULT_PITCH
, "Unexpected pitch %d.\n", logfont
.lfPitchAndFamily
);
4864 winetest_pop_context();
4866 IDWriteFont_Release(font
);
4869 IDWriteFontFamily_Release(family
);
4872 IDWriteFactory_Release(factory2
);
4874 IDWriteFontCollection_Release(collection
);
4875 IDWriteFontFamily_Release(family
);
4876 IDWriteFont_Release(font
);
4877 IDWriteGdiInterop_Release(interop
);
4878 ref
= IDWriteFactory_Release(factory
);
4879 ok(ref
== 0, "factory not released, %lu\n", ref
);
4882 static void test_CreateStreamFromKey(void)
4884 IDWriteLocalFontFileLoader
*localloader
;
4885 IDWriteFontFileStream
*stream
, *stream2
;
4886 IDWriteFontFileLoader
*loader
;
4887 IDWriteFactory
*factory
;
4888 IDWriteFontFile
*file
;
4896 factory
= create_factory();
4898 path
= create_testfontfile(test_fontfile
);
4900 hr
= IDWriteFactory_CreateFontFileReference(factory
, path
, NULL
, &file
);
4901 ok(hr
== S_OK
, "Unexpected hr %#lx.\n",hr
);
4905 hr
= IDWriteFontFile_GetReferenceKey(file
, (const void**)&key
, &size
);
4906 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4907 ok(size
!= 0, "got %u\n", size
);
4909 hr
= IDWriteFontFile_GetLoader(file
, &loader
);
4910 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4911 IDWriteFontFileLoader_QueryInterface(loader
, &IID_IDWriteLocalFontFileLoader
, (void**)&localloader
);
4912 IDWriteFontFileLoader_Release(loader
);
4914 hr
= IDWriteLocalFontFileLoader_CreateStreamFromKey(localloader
, key
, size
, &stream
);
4915 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4916 EXPECT_REF(stream
, 1);
4918 hr
= IDWriteLocalFontFileLoader_CreateStreamFromKey(localloader
, key
, size
, &stream2
);
4919 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4920 ok(stream
== stream2
|| broken(stream
!= stream2
) /* Win7 SP0 */, "got %p, %p\n", stream
, stream2
);
4921 if (stream
== stream2
)
4922 EXPECT_REF(stream
, 2);
4923 IDWriteFontFileStream_Release(stream
);
4924 IDWriteFontFileStream_Release(stream2
);
4926 hr
= IDWriteLocalFontFileLoader_CreateStreamFromKey(localloader
, key
, size
, &stream
);
4927 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4928 EXPECT_REF(stream
, 1);
4931 hr
= IDWriteFontFileStream_GetLastWriteTime(stream
, &writetime
);
4932 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4933 ok(writetime
!= 0, "got %s\n", wine_dbgstr_longlong(writetime
));
4935 IDWriteFontFileStream_Release(stream
);
4936 IDWriteFontFile_Release(file
);
4938 IDWriteLocalFontFileLoader_Release(localloader
);
4939 ref
= IDWriteFactory_Release(factory
);
4940 ok(ref
== 0, "factory not released, %lu\n", ref
);
4941 DELETE_FONTFILE(path
);
4944 static void test_ReadFileFragment(void)
4946 IDWriteLocalFontFileLoader
*localloader
;
4947 IDWriteFontFileStream
*stream
;
4948 IDWriteFontFileLoader
*loader
;
4949 IDWriteFactory
*factory
;
4950 IDWriteFontFile
*file
;
4951 const void *fragment
, *fragment2
;
4952 void *key
, *context
, *context2
;
4959 factory
= create_factory();
4961 path
= create_testfontfile(test_fontfile
);
4963 hr
= IDWriteFactory_CreateFontFileReference(factory
, path
, NULL
, &file
);
4964 ok(hr
== S_OK
, "Unexpected hr %#lx.\n",hr
);
4968 hr
= IDWriteFontFile_GetReferenceKey(file
, (const void**)&key
, &size
);
4969 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4970 ok(size
!= 0, "got %u\n", size
);
4972 hr
= IDWriteFontFile_GetLoader(file
, &loader
);
4973 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4974 IDWriteFontFileLoader_QueryInterface(loader
, &IID_IDWriteLocalFontFileLoader
, (void**)&localloader
);
4975 IDWriteFontFileLoader_Release(loader
);
4977 hr
= IDWriteLocalFontFileLoader_CreateStreamFromKey(localloader
, key
, size
, &stream
);
4978 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4980 hr
= IDWriteFontFileStream_GetFileSize(stream
, &filesize
);
4981 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4983 /* reading past the end of the stream */
4984 fragment
= (void*)0xdeadbeef;
4985 context
= (void*)0xdeadbeef;
4986 hr
= IDWriteFontFileStream_ReadFileFragment(stream
, &fragment
, 0, filesize
+1, &context
);
4987 ok(hr
== E_FAIL
, "Unexpected hr %#lx.\n", hr
);
4988 ok(context
== NULL
, "got %p\n", context
);
4989 ok(fragment
== NULL
, "got %p\n", fragment
);
4991 fragment
= (void*)0xdeadbeef;
4992 context
= (void*)0xdeadbeef;
4993 hr
= IDWriteFontFileStream_ReadFileFragment(stream
, &fragment
, 0, filesize
, &context
);
4994 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4995 ok(context
== NULL
, "got %p\n", context
);
4996 ok(fragment
!= NULL
, "got %p\n", fragment
);
4998 fragment2
= (void*)0xdeadbeef;
4999 context2
= (void*)0xdeadbeef;
5000 hr
= IDWriteFontFileStream_ReadFileFragment(stream
, &fragment2
, 0, filesize
, &context2
);
5001 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5002 ok(context2
== NULL
, "got %p\n", context2
);
5003 ok(fragment
== fragment2
, "got %p, %p\n", fragment
, fragment2
);
5005 IDWriteFontFileStream_ReleaseFileFragment(stream
, context
);
5006 IDWriteFontFileStream_ReleaseFileFragment(stream
, context2
);
5008 /* fragment is released, try again */
5009 fragment
= (void*)0xdeadbeef;
5010 context
= (void*)0xdeadbeef;
5011 hr
= IDWriteFontFileStream_ReadFileFragment(stream
, &fragment
, 0, filesize
, &context
);
5012 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5013 ok(context
== NULL
, "got %p\n", context
);
5014 ok(fragment
== fragment2
, "got %p, %p\n", fragment
, fragment2
);
5015 IDWriteFontFileStream_ReleaseFileFragment(stream
, context
);
5017 IDWriteFontFile_Release(file
);
5018 IDWriteFontFileStream_Release(stream
);
5019 IDWriteLocalFontFileLoader_Release(localloader
);
5020 ref
= IDWriteFactory_Release(factory
);
5021 ok(ref
== 0, "factory not released, %lu\n", ref
);
5022 DELETE_FONTFILE(path
);
5025 static void test_GetDesignGlyphMetrics(void)
5027 DWRITE_GLYPH_METRICS metrics
[2];
5028 IDWriteFontFace
*fontface
;
5029 IDWriteFactory
*factory
;
5030 IDWriteFontFile
*file
;
5037 factory
= create_factory();
5039 path
= create_testfontfile(test_fontfile
);
5041 hr
= IDWriteFactory_CreateFontFileReference(factory
, path
, NULL
, &file
);
5042 ok(hr
== S_OK
, "Unexpected hr %#lx.\n",hr
);
5044 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_TRUETYPE
, 1, &file
,
5045 0, DWRITE_FONT_SIMULATIONS_NONE
, &fontface
);
5046 ok(hr
== S_OK
, "Unexpected hr %#lx.\n",hr
);
5047 IDWriteFontFile_Release(file
);
5051 hr
= IDWriteFontFace_GetGlyphIndices(fontface
, &codepoint
, 1, &indices
[0]);
5052 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5053 ok(indices
[0] > 0, "got %u\n", indices
[0]);
5055 hr
= IDWriteFontFace_GetDesignGlyphMetrics(fontface
, NULL
, 0, metrics
, FALSE
);
5056 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n",hr
);
5058 hr
= IDWriteFontFace_GetDesignGlyphMetrics(fontface
, NULL
, 1, metrics
, FALSE
);
5059 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n",hr
);
5061 hr
= IDWriteFontFace_GetDesignGlyphMetrics(fontface
, indices
, 0, metrics
, FALSE
);
5062 ok(hr
== S_OK
, "Unexpected hr %#lx.\n",hr
);
5064 /* missing glyphs are ignored */
5066 memset(metrics
, 0xcc, sizeof(metrics
));
5067 hr
= IDWriteFontFace_GetDesignGlyphMetrics(fontface
, indices
, 2, metrics
, FALSE
);
5068 ok(hr
== S_OK
, "Unexpected hr %#lx.\n",hr
);
5069 ok(metrics
[0].advanceWidth
== 1000, "got %d\n", metrics
[0].advanceWidth
);
5070 ok(metrics
[1].advanceWidth
== 0, "got %d\n", metrics
[1].advanceWidth
);
5072 IDWriteFontFace_Release(fontface
);
5073 ref
= IDWriteFactory_Release(factory
);
5074 ok(ref
== 0, "factory not released, %lu\n", ref
);
5075 DELETE_FONTFILE(path
);
5078 static BOOL
get_expected_is_monospaced(IDWriteFontFace1
*fontface
, const DWRITE_PANOSE
*panose
)
5080 BOOL exists
, is_monospaced
= FALSE
;
5081 const TT_POST
*tt_post
;
5086 hr
= IDWriteFontFace1_TryGetFontTable(fontface
, MS_POST_TAG
, (const void **)&tt_post
, &size
,
5087 &post_context
, &exists
);
5088 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5092 is_monospaced
= !!tt_post
->fixed_pitch
;
5093 IDWriteFontFace1_ReleaseFontTable(fontface
, post_context
);
5097 is_monospaced
|= panose
->text
.proportion
== DWRITE_PANOSE_PROPORTION_MONOSPACED
;
5099 return is_monospaced
;
5102 static void test_IsMonospacedFont(void)
5104 IDWriteFontCollection
*collection
;
5105 IDWriteFactory1
*factory
;
5110 factory
= create_factory_iid(&IID_IDWriteFactory1
);
5114 win_skip("IsMonospacedFont() is not supported.\n");
5118 hr
= IDWriteFactory1_GetSystemFontCollection(factory
, &collection
, FALSE
);
5119 ok(hr
== S_OK
, "Failed to get font collection, hr %#lx.\n", hr
);
5121 count
= IDWriteFontCollection_GetFontFamilyCount(collection
);
5122 for (i
= 0; i
< count
; ++i
)
5124 IDWriteLocalizedStrings
*names
;
5125 IDWriteFontFamily
*family
;
5126 UINT32 font_count
, j
;
5129 hr
= IDWriteFontCollection_GetFontFamily(collection
, i
, &family
);
5130 ok(hr
== S_OK
, "Failed to get family, hr %#lx.\n", hr
);
5132 hr
= IDWriteFontFamily_GetFamilyNames(family
, &names
);
5133 ok(hr
== S_OK
, "Failed to get names, hr %#lx.\n", hr
);
5134 get_enus_string(names
, nameW
, ARRAY_SIZE(nameW
));
5135 IDWriteLocalizedStrings_Release(names
);
5137 font_count
= IDWriteFontFamily_GetFontCount(family
);
5139 for (j
= 0; j
< font_count
; ++j
)
5141 BOOL is_monospaced_font
, is_monospaced_face
, is_monospaced_expected
;
5142 IDWriteFontFace1
*fontface1
;
5143 IDWriteFontFace
*fontface
;
5144 DWRITE_PANOSE panose
;
5145 IDWriteFont1
*font1
;
5148 hr
= IDWriteFontFamily_GetFont(family
, j
, &font
);
5149 ok(hr
== S_OK
, "Failed to get font, hr %#lx.\n", hr
);
5151 hr
= IDWriteFont_QueryInterface(font
, &IID_IDWriteFont1
, (void **)&font1
);
5152 ok(hr
== S_OK
, "Failed to get interface, hr %#lx.\n", hr
);
5153 IDWriteFont_Release(font
);
5155 hr
= IDWriteFont1_CreateFontFace(font1
, &fontface
);
5156 ok(hr
== S_OK
, "Failed to create fontface, hr %#lx.\n", hr
);
5158 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void **)&fontface1
);
5159 ok(hr
== S_OK
, "Failed to get interface, hr %#lx.\n", hr
);
5160 IDWriteFontFace_Release(fontface
);
5162 is_monospaced_font
= IDWriteFont1_IsMonospacedFont(font1
);
5163 is_monospaced_face
= IDWriteFontFace1_IsMonospacedFont(fontface1
);
5164 ok(is_monospaced_font
== is_monospaced_face
, "Unexpected monospaced flag.\n");
5166 IDWriteFont1_GetPanose(font1
, &panose
);
5168 is_monospaced_expected
= get_expected_is_monospaced(fontface1
, &panose
);
5169 ok(is_monospaced_expected
== is_monospaced_face
, "Unexpected is_monospaced flag %d for %s, font %d.\n",
5170 is_monospaced_face
, wine_dbgstr_w(nameW
), j
);
5172 IDWriteFontFace1_Release(fontface1
);
5173 IDWriteFont1_Release(font1
);
5176 IDWriteFontFamily_Release(family
);
5179 IDWriteFontCollection_Release(collection
);
5180 ref
= IDWriteFactory1_Release(factory
);
5181 ok(ref
== 0, "factory not released, %lu\n", ref
);
5184 static void test_GetDesignGlyphAdvances(void)
5186 IDWriteFontFace1
*fontface1
;
5187 IDWriteFontFace
*fontface
;
5188 IDWriteFactory
*factory
;
5189 IDWriteFontFile
*file
;
5194 factory
= create_factory();
5196 path
= create_testfontfile(test_fontfile
);
5198 hr
= IDWriteFactory_CreateFontFileReference(factory
, path
, NULL
, &file
);
5199 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5201 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_TRUETYPE
, 1, &file
,
5202 0, DWRITE_FONT_SIMULATIONS_NONE
, &fontface
);
5203 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5204 IDWriteFontFile_Release(file
);
5206 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void**)&fontface1
);
5214 hr
= IDWriteFontFace1_GetGlyphIndices(fontface1
, &codepoint
, 1, &index
);
5215 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5216 ok(index
> 0, "got %u\n", index
);
5219 hr
= IDWriteFontFace1_GetDesignGlyphAdvances(fontface1
, 1, &index
, &advance
, FALSE
);
5220 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5221 ok(advance
== 1000, "got %i\n", advance
);
5224 hr
= IDWriteFontFace1_GetDesignGlyphAdvances(fontface1
, 1, &index
, &advance
, TRUE
);
5225 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5227 ok(advance
== 2048, "got %i\n", advance
);
5229 IDWriteFontFace1_Release(fontface1
);
5232 win_skip("GetDesignGlyphAdvances() is not supported.\n");
5234 IDWriteFontFace_Release(fontface
);
5235 ref
= IDWriteFactory_Release(factory
);
5236 ok(ref
== 0, "factory not released, %lu\n", ref
);
5237 DELETE_FONTFILE(path
);
5240 static void test_GetGlyphRunOutline(void)
5242 DWRITE_GLYPH_OFFSET offsets
[2];
5243 IDWriteFactory
*factory
;
5244 IDWriteFontFile
*file
;
5245 IDWriteFontFace
*face
;
5253 path
= create_testfontfile(test_fontfile
);
5254 factory
= create_factory();
5256 hr
= IDWriteFactory_CreateFontFileReference(factory
, path
, NULL
, &file
);
5257 ok(hr
== S_OK
, "Unexpected hr %#lx.\n",hr
);
5259 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_TRUETYPE
, 1, &file
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &face
);
5260 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5261 IDWriteFontFile_Release(file
);
5265 hr
= IDWriteFontFace_GetGlyphIndices(face
, &codepoint
, 1, glyphs
);
5266 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5267 ok(glyphs
[0] > 0, "got %u\n", glyphs
[0]);
5268 glyphs
[1] = glyphs
[0];
5270 hr
= IDWriteFontFace_GetGlyphRunOutline(face
, 2048.0, glyphs
, advances
, offsets
, 1, FALSE
, FALSE
, NULL
);
5271 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
5273 hr
= IDWriteFontFace_GetGlyphRunOutline(face
, 2048.0, NULL
, NULL
, offsets
, 1, FALSE
, FALSE
, &test_geomsink
);
5274 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
5279 offsets
[0].advanceOffset
= 1.0;
5280 offsets
[0].ascenderOffset
= 1.0;
5281 offsets
[1].advanceOffset
= 0.0;
5282 offsets
[1].ascenderOffset
= 0.0;
5284 /* default advances, no offsets */
5285 memset(g_startpoints
, 0, sizeof(g_startpoints
));
5286 g_startpoint_count
= 0;
5287 SET_EXPECT(setfillmode
);
5288 hr
= IDWriteFontFace_GetGlyphRunOutline(face
, 1024.0, glyphs
, NULL
, NULL
, 2, FALSE
, FALSE
, &test_geomsink
);
5289 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5290 ok(g_startpoint_count
== 2, "got %d\n", g_startpoint_count
);
5291 if (g_startpoint_count
== 2) {
5292 /* glyph advance of 500 is applied */
5293 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
);
5294 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
);
5296 CHECK_CALLED(setfillmode
);
5298 /* default advances, no offsets, RTL */
5299 memset(g_startpoints
, 0, sizeof(g_startpoints
));
5300 g_startpoint_count
= 0;
5301 SET_EXPECT(setfillmode
);
5302 hr
= IDWriteFontFace_GetGlyphRunOutline(face
, 1024.0, glyphs
, NULL
, NULL
, 2, FALSE
, TRUE
, &test_geomsink
);
5303 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5304 ok(g_startpoint_count
== 2, "got %d\n", g_startpoint_count
);
5305 if (g_startpoint_count
== 2) {
5306 /* advance is -500 now */
5307 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
);
5308 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
);
5310 CHECK_CALLED(setfillmode
);
5312 /* default advances, additional offsets */
5313 memset(g_startpoints
, 0, sizeof(g_startpoints
));
5314 g_startpoint_count
= 0;
5315 SET_EXPECT(setfillmode
);
5316 hr
= IDWriteFontFace_GetGlyphRunOutline(face
, 1024.0, glyphs
, NULL
, offsets
, 2, FALSE
, FALSE
, &test_geomsink
);
5317 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5318 ok(g_startpoint_count
== 2, "got %d\n", g_startpoint_count
);
5319 if (g_startpoint_count
== 2) {
5320 /* offsets applied to first contour */
5321 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
);
5322 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
);
5324 CHECK_CALLED(setfillmode
);
5326 /* default advances, additional offsets, RTL */
5327 memset(g_startpoints
, 0, sizeof(g_startpoints
));
5328 g_startpoint_count
= 0;
5329 SET_EXPECT(setfillmode
);
5330 hr
= IDWriteFontFace_GetGlyphRunOutline(face
, 1024.0, glyphs
, NULL
, offsets
, 2, FALSE
, TRUE
, &test_geomsink
);
5331 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5332 ok(g_startpoint_count
== 2, "got %d\n", g_startpoint_count
);
5333 if (g_startpoint_count
== 2) {
5334 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
);
5335 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
);
5337 CHECK_CALLED(setfillmode
);
5339 /* custom advances and offsets, offset turns total advance value to zero */
5340 memset(g_startpoints
, 0, sizeof(g_startpoints
));
5341 g_startpoint_count
= 0;
5342 SET_EXPECT(setfillmode
);
5343 hr
= IDWriteFontFace_GetGlyphRunOutline(face
, 1024.0, glyphs
, advances
, offsets
, 2, FALSE
, FALSE
, &test_geomsink
);
5344 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5345 ok(g_startpoint_count
== 2, "got %d\n", g_startpoint_count
);
5346 if (g_startpoint_count
== 2) {
5347 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
);
5348 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
);
5350 CHECK_CALLED(setfillmode
);
5353 hr
= IDWriteFontFace_GetGlyphRunOutline(face
, 1024.0, glyphs
, NULL
, NULL
, 0, FALSE
, FALSE
, &test_geomsink2
);
5354 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5356 /* Glyph with open figure, single contour point. */
5359 hr
= IDWriteFontFace_GetGlyphIndices(face
, &codepoint
, 1, glyphs
);
5360 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5361 ok(glyphs
[0] > 0, "got %u\n", glyphs
[0]);
5363 SET_EXPECT(setfillmode
);
5364 hr
= IDWriteFontFace_GetGlyphRunOutline(face
, 1024.0, glyphs
, NULL
, NULL
, 1, FALSE
, FALSE
, &test_geomsink2
);
5365 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5366 CHECK_CALLED(setfillmode
);
5368 IDWriteFactory_Release(factory
);
5369 IDWriteFontFace_Release(face
);
5370 DELETE_FONTFILE(path
);
5373 factory
= create_factory();
5374 face
= create_fontface(factory
);
5378 hr
= IDWriteFontFace_GetGlyphIndices(face
, &codepoint
, 1, glyphs
);
5379 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5380 ok(glyphs
[0] > 0, "got %u\n", glyphs
[0]);
5382 SET_EXPECT(setfillmode
);
5383 hr
= IDWriteFontFace_GetGlyphRunOutline(face
, 1024.0, glyphs
, NULL
, NULL
, 1, FALSE
, FALSE
, &test_geomsink2
);
5384 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5385 CHECK_CALLED(setfillmode
);
5387 IDWriteFontFace_Release(face
);
5388 ref
= IDWriteFactory_Release(factory
);
5389 ok(ref
== 0, "factory not released, %lu\n", ref
);
5392 static void test_GetEudcFontCollection(void)
5394 IDWriteFontCollection
*coll
, *coll2
;
5395 IDWriteFactory1
*factory
;
5399 factory
= create_factory_iid(&IID_IDWriteFactory1
);
5401 win_skip("GetEudcFontCollection() is not supported.\n");
5405 EXPECT_REF(factory
, 1);
5406 hr
= IDWriteFactory1_GetEudcFontCollection(factory
, &coll
, FALSE
);
5407 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5408 EXPECT_REF(factory
, 2);
5409 hr
= IDWriteFactory1_GetEudcFontCollection(factory
, &coll2
, FALSE
);
5410 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5411 EXPECT_REF(factory
, 2);
5412 ok(coll
== coll2
, "got %p, %p\n", coll
, coll2
);
5413 IDWriteFontCollection_Release(coll
);
5414 IDWriteFontCollection_Release(coll2
);
5416 ref
= IDWriteFactory1_Release(factory
);
5417 ok(ref
== 0, "factory not released, %lu\n", ref
);
5420 static void test_GetCaretMetrics(void)
5422 DWRITE_FONT_METRICS1 metrics
;
5423 IDWriteFontFace1
*fontface1
;
5424 DWRITE_CARET_METRICS caret
;
5425 IDWriteFontFace
*fontface
;
5426 IDWriteFactory
*factory
;
5427 IDWriteFontFile
*file
;
5433 path
= create_testfontfile(test_fontfile
);
5434 factory
= create_factory();
5436 hr
= IDWriteFactory_CreateFontFileReference(factory
, path
, NULL
, &file
);
5437 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5439 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_TRUETYPE
, 1, &file
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &fontface
);
5440 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5441 IDWriteFontFile_Release(file
);
5443 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void**)&fontface1
);
5444 IDWriteFontFace_Release(fontface
);
5446 win_skip("GetCaretMetrics() is not supported.\n");
5447 ref
= IDWriteFactory_Release(factory
);
5448 ok(ref
== 0, "factory not released, %lu\n", ref
);
5449 DELETE_FONTFILE(path
);
5453 memset(&caret
, 0xcc, sizeof(caret
));
5454 IDWriteFontFace1_GetCaretMetrics(fontface1
, &caret
);
5455 ok(caret
.slopeRise
== 1, "got %d\n", caret
.slopeRise
);
5456 ok(caret
.slopeRun
== 0, "got %d\n", caret
.slopeRun
);
5457 ok(caret
.offset
== 0, "got %d\n", caret
.offset
);
5458 IDWriteFontFace1_Release(fontface1
);
5459 IDWriteFactory_Release(factory
);
5461 /* now with Tahoma Normal */
5462 factory
= create_factory();
5463 font
= get_tahoma_instance(factory
, DWRITE_FONT_STYLE_NORMAL
);
5464 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
5465 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5466 IDWriteFont_Release(font
);
5467 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void**)&fontface1
);
5468 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5469 IDWriteFontFace_Release(fontface
);
5471 memset(&caret
, 0xcc, sizeof(caret
));
5472 IDWriteFontFace1_GetCaretMetrics(fontface1
, &caret
);
5473 ok(caret
.slopeRise
== 1, "got %d\n", caret
.slopeRise
);
5474 ok(caret
.slopeRun
== 0, "got %d\n", caret
.slopeRun
);
5475 ok(caret
.offset
== 0, "got %d\n", caret
.offset
);
5476 IDWriteFontFace1_Release(fontface1
);
5478 /* simulated italic */
5479 font
= get_tahoma_instance(factory
, DWRITE_FONT_STYLE_ITALIC
);
5480 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
5481 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5482 IDWriteFont_Release(font
);
5483 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void**)&fontface1
);
5484 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5485 IDWriteFontFace_Release(fontface
);
5487 IDWriteFontFace1_GetMetrics(fontface1
, &metrics
);
5489 memset(&caret
, 0xcc, sizeof(caret
));
5490 IDWriteFontFace1_GetCaretMetrics(fontface1
, &caret
);
5491 ok(caret
.slopeRise
== metrics
.designUnitsPerEm
, "got %d\n", caret
.slopeRise
);
5492 ok(caret
.slopeRun
> 0, "got %d\n", caret
.slopeRun
);
5493 ok(caret
.offset
== 0, "got %d\n", caret
.offset
);
5494 IDWriteFontFace1_Release(fontface1
);
5496 ref
= IDWriteFactory_Release(factory
);
5497 ok(ref
== 0, "factory not released, %lu\n", ref
);
5498 DELETE_FONTFILE(path
);
5501 static void test_GetGlyphCount(void)
5503 IDWriteFontFace
*fontface
;
5504 IDWriteFactory
*factory
;
5505 IDWriteFontFile
*file
;
5511 path
= create_testfontfile(test_fontfile
);
5512 factory
= create_factory();
5514 hr
= IDWriteFactory_CreateFontFileReference(factory
, path
, NULL
, &file
);
5515 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5517 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_TRUETYPE
, 1, &file
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &fontface
);
5518 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5519 IDWriteFontFile_Release(file
);
5521 count
= IDWriteFontFace_GetGlyphCount(fontface
);
5522 ok(count
== 8, "got %u\n", count
);
5524 IDWriteFontFace_Release(fontface
);
5525 ref
= IDWriteFactory_Release(factory
);
5526 ok(ref
== 0, "factory not released, %lu\n", ref
);
5527 DELETE_FONTFILE(path
);
5530 static void test_GetKerningPairAdjustments(void)
5532 IDWriteFontFace1
*fontface1
;
5533 IDWriteFontFace
*fontface
;
5534 IDWriteFactory
*factory
;
5535 IDWriteFontFile
*file
;
5540 path
= create_testfontfile(test_fontfile
);
5541 factory
= create_factory();
5543 hr
= IDWriteFactory_CreateFontFileReference(factory
, path
, NULL
, &file
);
5544 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5546 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_TRUETYPE
, 1, &file
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &fontface
);
5547 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5548 IDWriteFontFile_Release(file
);
5550 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void**)&fontface1
);
5552 INT32 adjustments
[1];
5554 hr
= IDWriteFontFace1_GetKerningPairAdjustments(fontface1
, 0, NULL
, NULL
);
5555 ok(hr
== E_INVALIDARG
|| broken(hr
== S_OK
) /* win8 */, "Unexpected hr %#lx.\n", hr
);
5557 if (0) /* crashes on native */
5558 hr
= IDWriteFontFace1_GetKerningPairAdjustments(fontface1
, 1, NULL
, NULL
);
5561 hr
= IDWriteFontFace1_GetKerningPairAdjustments(fontface1
, 1, NULL
, adjustments
);
5562 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
5563 ok(adjustments
[0] == 0, "got %d\n", adjustments
[0]);
5565 IDWriteFontFace1_Release(fontface1
);
5568 win_skip("GetKerningPairAdjustments() is not supported.\n");
5570 IDWriteFontFace_Release(fontface
);
5571 ref
= IDWriteFactory_Release(factory
);
5572 ok(ref
== 0, "factory not released, %lu\n", ref
);
5573 DELETE_FONTFILE(path
);
5576 static void test_CreateRenderingParams(void)
5578 IDWriteRenderingParams2
*params2
;
5579 IDWriteRenderingParams1
*params1
;
5580 IDWriteRenderingParams
*params
;
5581 DWRITE_RENDERING_MODE mode
;
5582 IDWriteFactory3
*factory3
;
5583 IDWriteFactory
*factory
;
5587 factory
= create_factory();
5589 hr
= IDWriteFactory_CreateCustomRenderingParams(factory
, 1.0, 0.0, 0.0, DWRITE_PIXEL_GEOMETRY_FLAT
,
5590 DWRITE_RENDERING_MODE_DEFAULT
, ¶ms
);
5591 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5593 hr
= IDWriteRenderingParams_QueryInterface(params
, &IID_IDWriteRenderingParams1
, (void**)¶ms1
);
5597 /* test what enhanced contrast setting set by default to */
5598 enhcontrast
= IDWriteRenderingParams1_GetGrayscaleEnhancedContrast(params1
);
5599 ok(enhcontrast
== 1.0, "got %.2f\n", enhcontrast
);
5600 IDWriteRenderingParams1_Release(params1
);
5602 hr
= IDWriteRenderingParams_QueryInterface(params
, &IID_IDWriteRenderingParams2
, (void**)¶ms2
);
5604 DWRITE_GRID_FIT_MODE gridfit
;
5606 /* default gridfit mode */
5607 gridfit
= IDWriteRenderingParams2_GetGridFitMode(params2
);
5608 ok(gridfit
== DWRITE_GRID_FIT_MODE_DEFAULT
, "got %d\n", gridfit
);
5610 IDWriteRenderingParams2_Release(params2
);
5613 win_skip("IDWriteRenderingParams2 not supported.\n");
5616 win_skip("IDWriteRenderingParams1 not supported.\n");
5618 IDWriteRenderingParams_Release(params
);
5620 hr
= IDWriteFactory_CreateRenderingParams(factory
, ¶ms
);
5621 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5623 mode
= IDWriteRenderingParams_GetRenderingMode(params
);
5624 ok(mode
== DWRITE_RENDERING_MODE_DEFAULT
, "got %d\n", mode
);
5625 IDWriteRenderingParams_Release(params
);
5627 hr
= IDWriteFactory_QueryInterface(factory
, &IID_IDWriteFactory3
, (void**)&factory3
);
5629 IDWriteRenderingParams3
*params3
;
5631 hr
= IDWriteFactory3_CreateCustomRenderingParams(factory3
, 1.0f
, 0.0f
, 0.0f
, 1.0f
, DWRITE_PIXEL_GEOMETRY_FLAT
,
5632 DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC_DOWNSAMPLED
, DWRITE_GRID_FIT_MODE_DEFAULT
, ¶ms3
);
5633 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5635 hr
= IDWriteRenderingParams3_QueryInterface(params3
, &IID_IDWriteRenderingParams
, (void**)¶ms
);
5636 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5638 mode
= IDWriteRenderingParams_GetRenderingMode(params
);
5639 ok(mode
== DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
, "got %d\n", mode
);
5641 IDWriteRenderingParams_Release(params
);
5642 IDWriteRenderingParams3_Release(params3
);
5643 IDWriteFactory3_Release(factory3
);
5646 win_skip("IDWriteRenderingParams3 not supported.\n");
5648 ref
= IDWriteFactory_Release(factory
);
5649 ok(ref
== 0, "factory not released, %lu\n", ref
);
5652 static void test_CreateGlyphRunAnalysis(void)
5654 static const DWRITE_RENDERING_MODE rendermodes
[] = {
5655 DWRITE_RENDERING_MODE_ALIASED
,
5656 DWRITE_RENDERING_MODE_GDI_CLASSIC
,
5657 DWRITE_RENDERING_MODE_GDI_NATURAL
,
5658 DWRITE_RENDERING_MODE_NATURAL
,
5659 DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
,
5662 IDWriteGlyphRunAnalysis
*analysis
, *analysis2
;
5663 IDWriteRenderingParams
*params
;
5664 IDWriteFactory3
*factory3
;
5665 IDWriteFactory2
*factory2
;
5666 IDWriteFactory
*factory
;
5667 DWRITE_GLYPH_RUN run
;
5668 IDWriteFontFace
*face
;
5669 UINT16 glyph
, glyphs
[10];
5674 DWRITE_GLYPH_OFFSET offsets
[2];
5675 DWRITE_GLYPH_METRICS metrics
;
5676 DWRITE_FONT_METRICS fm
;
5683 factory
= create_factory();
5684 face
= create_fontface(factory
);
5688 hr
= IDWriteFontFace_GetGlyphIndices(face
, &ch
, 1, &glyph
);
5689 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5690 ok(glyph
> 0, "got %u\n", glyph
);
5692 hr
= IDWriteFontFace_GetDesignGlyphMetrics(face
, &glyph
, 1, &metrics
, FALSE
);
5693 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5694 advances
[0] = metrics
.advanceWidth
;
5696 offsets
[0].advanceOffset
= 0.0;
5697 offsets
[0].ascenderOffset
= 0.0;
5699 run
.fontFace
= face
;
5700 run
.fontEmSize
= 24.0;
5702 run
.glyphIndices
= &glyph
;
5703 run
.glyphAdvances
= advances
;
5704 run
.glyphOffsets
= offsets
;
5705 run
.isSideways
= FALSE
;
5709 analysis
= (void*)0xdeadbeef;
5710 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 0.0, NULL
,
5711 DWRITE_RENDERING_MODE_ALIASED
, DWRITE_MEASURING_MODE_NATURAL
,
5712 0.0, 0.0, &analysis
);
5713 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
5714 ok(analysis
== NULL
, "got %p\n", analysis
);
5716 /* negative ppdip */
5717 analysis
= (void*)0xdeadbeef;
5718 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, -1.0, NULL
,
5719 DWRITE_RENDERING_MODE_ALIASED
, DWRITE_MEASURING_MODE_NATURAL
,
5720 0.0, 0.0, &analysis
);
5721 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
5722 ok(analysis
== NULL
, "got %p\n", analysis
);
5724 /* default mode is not allowed */
5725 analysis
= (void*)0xdeadbeef;
5726 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 1.0, NULL
,
5727 DWRITE_RENDERING_MODE_DEFAULT
, DWRITE_MEASURING_MODE_NATURAL
,
5728 0.0, 0.0, &analysis
);
5729 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
5730 ok(analysis
== NULL
, "got %p\n", analysis
);
5733 analysis
= (void*)0xdeadbeef;
5734 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 1.0, NULL
,
5735 DWRITE_RENDERING_MODE_OUTLINE
, DWRITE_MEASURING_MODE_NATURAL
,
5736 0.0, 0.0, &analysis
);
5737 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
5738 ok(analysis
== NULL
, "got %p\n", analysis
);
5740 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 1.0, NULL
,
5741 DWRITE_RENDERING_MODE_ALIASED
, DWRITE_MEASURING_MODE_NATURAL
,
5742 0.0, 0.0, &analysis
);
5743 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5745 /* invalid texture type */
5746 memset(&rect
, 0xcc, sizeof(rect
));
5747 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_CLEARTYPE_3x1
+1, &rect
);
5748 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
5749 ok(rect
.left
== 0 && rect
.right
== 0 &&
5750 rect
.top
== 0 && rect
.bottom
== 0, "unexpected rect\n");
5752 /* check how origin affects bounds */
5753 SetRectEmpty(&rect
);
5754 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect
);
5755 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5756 ok(!IsRectEmpty(&rect
), "got empty rect\n");
5757 IDWriteGlyphRunAnalysis_Release(analysis
);
5760 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 2.0, NULL
,
5761 DWRITE_RENDERING_MODE_ALIASED
, DWRITE_MEASURING_MODE_NATURAL
,
5762 0.0, 0.0, &analysis
);
5763 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5764 SetRectEmpty(&rect2
);
5765 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect2
);
5766 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5767 ok(rect
.right
- rect
.left
< rect2
.right
- rect2
.left
, "expected wider rect\n");
5768 ok(rect
.bottom
- rect
.top
< rect2
.bottom
- rect2
.top
, "expected taller rect\n");
5769 IDWriteGlyphRunAnalysis_Release(analysis
);
5771 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 1.0, NULL
,
5772 DWRITE_RENDERING_MODE_ALIASED
, DWRITE_MEASURING_MODE_NATURAL
,
5773 10.0, -5.0, &analysis
);
5774 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5776 SetRectEmpty(&rect2
);
5777 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect2
);
5778 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5779 ok(!IsRectEmpty(&rect2
), "got empty rect\n");
5780 IDWriteGlyphRunAnalysis_Release(analysis
);
5782 ok(!EqualRect(&rect
, &rect2
), "got equal bounds\n");
5783 OffsetRect(&rect
, 10, -5);
5784 ok(EqualRect(&rect
, &rect2
), "got different bounds\n");
5786 for (i
= 0; i
< ARRAY_SIZE(rendermodes
); i
++) {
5787 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 1.0, NULL
,
5788 rendermodes
[i
], DWRITE_MEASURING_MODE_NATURAL
,
5789 0.0, 0.0, &analysis
);
5790 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5792 if (rendermodes
[i
] == DWRITE_RENDERING_MODE_ALIASED
) {
5793 SetRectEmpty(&rect
);
5794 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect
);
5795 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5796 ok(!IsRectEmpty(&rect
), "got empty rect\n");
5798 SetRect(&rect
, 0, 0, 1, 1);
5799 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_CLEARTYPE_3x1
, &rect
);
5800 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5801 ok(IsRectEmpty(&rect
), "unexpected empty rect\n");
5804 SetRect(&rect
, 0, 0, 1, 1);
5805 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect
);
5806 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5807 ok(IsRectEmpty(&rect
), "got empty rect\n");
5809 SetRectEmpty(&rect
);
5810 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_CLEARTYPE_3x1
, &rect
);
5811 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5812 ok(!IsRectEmpty(&rect
), "got empty rect\n");
5815 IDWriteGlyphRunAnalysis_Release(analysis
);
5818 IDWriteFontFace_GetMetrics(run
.fontFace
, &fm
);
5820 /* check bbox for a single glyph run */
5821 for (run
.fontEmSize
= 1.0; run
.fontEmSize
<= 100.0; run
.fontEmSize
+= 1.0) {
5822 DWRITE_GLYPH_METRICS gm
;
5825 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 1.0, NULL
,
5826 DWRITE_RENDERING_MODE_ALIASED
, DWRITE_MEASURING_MODE_GDI_CLASSIC
,
5827 0.0, 0.0, &analysis
);
5828 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5830 SetRectEmpty(&rect
);
5831 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect
);
5832 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5834 hr
= IDWriteFontFace_GetGdiCompatibleGlyphMetrics(run
.fontFace
, run
.fontEmSize
, 1.0, NULL
,
5835 DWRITE_MEASURING_MODE_GDI_CLASSIC
, run
.glyphIndices
, 1, &gm
, run
.isSideways
);
5836 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5838 /* metrics are in design units */
5839 bboxX
= (int)floorf((gm
.advanceWidth
- gm
.leftSideBearing
- gm
.rightSideBearing
) * run
.fontEmSize
/ fm
.designUnitsPerEm
+ 0.5f
);
5840 bboxY
= (int)floorf((gm
.advanceHeight
- gm
.topSideBearing
- gm
.bottomSideBearing
) * run
.fontEmSize
/ fm
.designUnitsPerEm
+ 0.5f
);
5842 rect
.right
-= rect
.left
;
5843 rect
.bottom
-= rect
.top
;
5844 ok(abs(bboxX
- rect
.right
) <= 2, "%.0f: bbox width %ld, from metrics %ld\n", run
.fontEmSize
, rect
.right
, bboxX
);
5845 ok(abs(bboxY
- rect
.bottom
) <= 2, "%.0f: bbox height %ld, from metrics %ld\n", run
.fontEmSize
, rect
.bottom
, bboxY
);
5847 IDWriteGlyphRunAnalysis_Release(analysis
);
5850 /* without offsets */
5851 run
.fontFace
= face
;
5852 run
.fontEmSize
= 24.0;
5854 run
.glyphIndices
= &glyph
;
5855 run
.glyphAdvances
= advances
;
5856 run
.glyphOffsets
= NULL
;
5857 run
.isSideways
= FALSE
;
5860 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 1.0, NULL
,
5861 DWRITE_RENDERING_MODE_ALIASED
, DWRITE_MEASURING_MODE_NATURAL
,
5862 0.0, 0.0, &analysis
);
5863 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5865 SetRectEmpty(&rect
);
5866 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect
);
5867 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5868 ok(!IsRectEmpty(&rect
), "got empty bounds\n");
5870 IDWriteGlyphRunAnalysis_Release(analysis
);
5872 /* without explicit advances */
5873 run
.fontFace
= face
;
5874 run
.fontEmSize
= 24.0;
5876 run
.glyphIndices
= &glyph
;
5877 run
.glyphAdvances
= NULL
;
5878 run
.glyphOffsets
= NULL
;
5879 run
.isSideways
= FALSE
;
5882 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 1.0, NULL
,
5883 DWRITE_RENDERING_MODE_ALIASED
, DWRITE_MEASURING_MODE_NATURAL
,
5884 0.0, 0.0, &analysis
);
5885 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5887 SetRectEmpty(&rect
);
5888 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect
);
5889 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5890 ok(!IsRectEmpty(&rect
), "got empty bounds\n");
5892 IDWriteGlyphRunAnalysis_Release(analysis
);
5894 /* test that advances are scaled according to ppdip too */
5895 glyphs
[0] = glyphs
[1] = glyph
;
5896 advances
[0] = advances
[1] = 100.0f
;
5897 run
.fontFace
= face
;
5898 run
.fontEmSize
= 24.0;
5900 run
.glyphIndices
= glyphs
;
5901 run
.glyphAdvances
= advances
;
5902 run
.glyphOffsets
= NULL
;
5903 run
.isSideways
= FALSE
;
5906 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 1.0, NULL
,
5907 DWRITE_RENDERING_MODE_ALIASED
, DWRITE_MEASURING_MODE_NATURAL
,
5908 0.0, 0.0, &analysis
);
5909 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5911 SetRectEmpty(&rect2
);
5912 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect2
);
5913 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5914 ok(!IsRectEmpty(&rect2
), "got empty bounds\n");
5915 ok(!EqualRect(&rect
, &rect2
), "got wrong rect2\n");
5916 ok((rect2
.right
- rect
.left
) > advances
[0], "got rect width %ld for advance %f\n", rect
.right
- rect
.left
, advances
[0]);
5917 IDWriteGlyphRunAnalysis_Release(analysis
);
5919 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 2.0, NULL
,
5920 DWRITE_RENDERING_MODE_ALIASED
, DWRITE_MEASURING_MODE_NATURAL
,
5921 0.0, 0.0, &analysis
);
5922 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5924 SetRectEmpty(&rect
);
5925 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect
);
5926 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5927 ok((rect
.right
- rect
.left
) > 2 * advances
[0], "got rect width %ld for advance %f\n", rect
.right
- rect
.left
, advances
[0]);
5928 IDWriteGlyphRunAnalysis_Release(analysis
);
5930 /* with scaling transform */
5931 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 1.0, NULL
,
5932 DWRITE_RENDERING_MODE_ALIASED
, DWRITE_MEASURING_MODE_NATURAL
,
5933 0.0, 0.0, &analysis
);
5934 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5936 SetRectEmpty(&rect
);
5937 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect
);
5938 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5939 ok(!IsRectEmpty(&rect
), "got rect width %ld\n", rect
.right
- rect
.left
);
5940 IDWriteGlyphRunAnalysis_Release(analysis
);
5942 memset(&m
, 0, sizeof(m
));
5945 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 1.0, &m
,
5946 DWRITE_RENDERING_MODE_ALIASED
, DWRITE_MEASURING_MODE_NATURAL
,
5947 0.0, 0.0, &analysis
);
5948 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5950 SetRectEmpty(&rect2
);
5951 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect2
);
5952 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5953 ok((rect2
.right
- rect2
.left
) > (rect
.right
- rect
.left
), "got rect width %ld\n", rect2
.right
- rect2
.left
);
5955 /* instances are not reused for same runs */
5956 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 1.0, &m
,
5957 DWRITE_RENDERING_MODE_ALIASED
, DWRITE_MEASURING_MODE_NATURAL
,
5958 0.0, 0.0, &analysis2
);
5959 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5960 ok(analysis2
!= analysis
, "got %p, previous instance %p\n", analysis2
, analysis
);
5961 IDWriteGlyphRunAnalysis_Release(analysis2
);
5963 IDWriteGlyphRunAnalysis_Release(analysis
);
5965 if (IDWriteFactory_QueryInterface(factory
, &IID_IDWriteFactory2
, (void **)&factory2
) == S_OK
) {
5966 FLOAT gamma
, contrast
, cleartype_level
;
5968 /* Invalid antialias mode. */
5969 hr
= IDWriteFactory2_CreateGlyphRunAnalysis(factory2
, &run
, NULL
, DWRITE_RENDERING_MODE_ALIASED
,
5970 DWRITE_MEASURING_MODE_NATURAL
, DWRITE_GRID_FIT_MODE_DEFAULT
, DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
+ 1,
5971 0.0f
, 0.0f
, &analysis
);
5972 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
5974 /* Invalid grid fit mode. */
5975 hr
= IDWriteFactory2_CreateGlyphRunAnalysis(factory2
, &run
, NULL
, DWRITE_RENDERING_MODE_ALIASED
,
5976 DWRITE_MEASURING_MODE_NATURAL
, DWRITE_GRID_FIT_MODE_ENABLED
+ 1, DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
,
5977 0.0f
, 0.0f
, &analysis
);
5978 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
5980 /* Invalid rendering mode. */
5981 hr
= IDWriteFactory2_CreateGlyphRunAnalysis(factory2
, &run
, NULL
, DWRITE_RENDERING_MODE_OUTLINE
,
5982 DWRITE_MEASURING_MODE_NATURAL
, DWRITE_GRID_FIT_MODE_ENABLED
, DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
,
5983 0.0f
, 0.0f
, &analysis
);
5984 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
5986 /* Invalid measuring mode. */
5987 hr
= IDWriteFactory2_CreateGlyphRunAnalysis(factory2
, &run
, NULL
, DWRITE_RENDERING_MODE_ALIASED
,
5988 DWRITE_MEASURING_MODE_GDI_NATURAL
+ 1, DWRITE_GRID_FIT_MODE_ENABLED
, DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
,
5989 0.0f
, 0.0f
, &analysis
);
5990 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
5992 /* Win8 does not accept default grid fitting mode. */
5993 hr
= IDWriteFactory2_CreateGlyphRunAnalysis(factory2
, &run
, NULL
, DWRITE_RENDERING_MODE_NATURAL
,
5994 DWRITE_MEASURING_MODE_NATURAL
, DWRITE_GRID_FIT_MODE_DEFAULT
, DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
,
5995 0.0f
, 0.0f
, &analysis
);
5996 ok(hr
== S_OK
|| broken(hr
== E_INVALIDARG
) /* Win8 */, "Failed to create analysis, hr %#lx.\n", hr
);
5998 IDWriteGlyphRunAnalysis_Release(analysis
);
6000 /* Natural mode, grayscale antialiased. */
6001 hr
= IDWriteFactory2_CreateGlyphRunAnalysis(factory2
, &run
, NULL
, DWRITE_RENDERING_MODE_NATURAL
,
6002 DWRITE_MEASURING_MODE_NATURAL
, DWRITE_GRID_FIT_MODE_DISABLED
, DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
,
6003 0.0f
, 0.0f
, &analysis
);
6004 ok(hr
== S_OK
, "Failed to create analysis, hr %#lx.\n", hr
);
6006 SetRect(&rect
, 0, 1, 0, 1);
6007 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_CLEARTYPE_3x1
, &rect
);
6008 ok(hr
== S_OK
, "Failed to get texture bounds, hr %#lx.\n", hr
);
6009 ok(IsRectEmpty(&rect
), "Expected empty bbox.\n");
6011 SetRectEmpty(&rect
);
6012 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect
);
6013 ok(hr
== S_OK
, "Failed to get texture bounds, hr %#lx.\n", hr
);
6014 ok(!IsRectEmpty(&rect
), "Unexpected empty bbox.\n");
6016 size
= (rect
.right
- rect
.left
) * (rect
.bottom
- rect
.top
);
6017 bits
= malloc(size
);
6019 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect
, bits
, size
);
6020 ok(hr
== S_OK
, "Failed to get alpha texture, hr %#lx.\n", hr
);
6022 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect
, bits
, size
- 1);
6023 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "Unexpected hr %#lx.\n", hr
);
6025 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_CLEARTYPE_3x1
, &rect
, bits
, size
);
6026 ok(hr
== DWRITE_E_UNSUPPORTEDOPERATION
, "Unexpected hr %#lx.\n", hr
);
6028 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_CLEARTYPE_3x1
, &rect
, bits
, size
- 1);
6030 ok(hr
== DWRITE_E_UNSUPPORTEDOPERATION
, "Unexpected hr %#lx.\n", hr
);
6034 hr
= IDWriteFactory_CreateCustomRenderingParams(factory
, 0.1f
, 0.0f
, 1.0f
, DWRITE_PIXEL_GEOMETRY_FLAT
,
6035 DWRITE_RENDERING_MODE_NATURAL
, ¶ms
);
6036 ok(hr
== S_OK
, "Failed to create custom parameters, hr %#lx.\n", hr
);
6038 hr
= IDWriteGlyphRunAnalysis_GetAlphaBlendParams(analysis
, params
, &gamma
, &contrast
, &cleartype_level
);
6039 ok(hr
== S_OK
, "Failed to get alpha blend params, hr %#lx.\n", hr
);
6041 ok(cleartype_level
== 0.0f
, "Unexpected cleartype level %f.\n", cleartype_level
);
6043 IDWriteRenderingParams_Release(params
);
6044 IDWriteGlyphRunAnalysis_Release(analysis
);
6046 IDWriteFactory2_Release(factory2
);
6049 if (IDWriteFactory_QueryInterface(factory
, &IID_IDWriteFactory3
, (void **)&factory3
) == S_OK
) {
6051 /* Invalid antialias mode. */
6052 hr
= IDWriteFactory3_CreateGlyphRunAnalysis(factory3
, &run
, NULL
, DWRITE_RENDERING_MODE1_ALIASED
,
6053 DWRITE_MEASURING_MODE_NATURAL
, DWRITE_GRID_FIT_MODE_DEFAULT
, DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
+ 1,
6054 0.0f
, 0.0f
, &analysis
);
6055 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
6057 /* Invalid grid fit mode. */
6058 hr
= IDWriteFactory3_CreateGlyphRunAnalysis(factory3
, &run
, NULL
, DWRITE_RENDERING_MODE1_ALIASED
,
6059 DWRITE_MEASURING_MODE_NATURAL
, DWRITE_GRID_FIT_MODE_ENABLED
+ 1, DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
,
6060 0.0f
, 0.0f
, &analysis
);
6061 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
6063 /* Invalid rendering mode. */
6064 hr
= IDWriteFactory3_CreateGlyphRunAnalysis(factory3
, &run
, NULL
, DWRITE_RENDERING_MODE1_OUTLINE
,
6065 DWRITE_MEASURING_MODE_NATURAL
, DWRITE_GRID_FIT_MODE_ENABLED
, DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
,
6066 0.0f
, 0.0f
, &analysis
);
6067 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
6069 /* Invalid measuring mode. */
6070 hr
= IDWriteFactory3_CreateGlyphRunAnalysis(factory3
, &run
, NULL
, DWRITE_RENDERING_MODE1_ALIASED
,
6071 DWRITE_MEASURING_MODE_GDI_NATURAL
+ 1, DWRITE_GRID_FIT_MODE_ENABLED
,
6072 DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
, 0.0f
, 0.0f
, &analysis
);
6073 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
6075 hr
= IDWriteFactory3_CreateGlyphRunAnalysis(factory3
, &run
, NULL
, DWRITE_RENDERING_MODE1_NATURAL
,
6076 DWRITE_MEASURING_MODE_NATURAL
, DWRITE_GRID_FIT_MODE_DEFAULT
, DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
,
6077 0.0f
, 0.0f
, &analysis
);
6078 ok(hr
== S_OK
, "Failed to create analysis, hr %#lx.\n", hr
);
6079 IDWriteGlyphRunAnalysis_Release(analysis
);
6081 /* Natural mode, grayscale antialiased. */
6082 hr
= IDWriteFactory3_CreateGlyphRunAnalysis(factory3
, &run
, NULL
, DWRITE_RENDERING_MODE1_NATURAL
,
6083 DWRITE_MEASURING_MODE_NATURAL
, DWRITE_GRID_FIT_MODE_DISABLED
, DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
,
6084 0.0f
, 0.0f
, &analysis
);
6085 ok(hr
== S_OK
, "Failed to create analysis, hr %#lx.\n", hr
);
6087 SetRect(&rect
, 0, 1, 0, 1);
6088 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_CLEARTYPE_3x1
, &rect
);
6089 ok(hr
== S_OK
, "Failed to get texture bounds, hr %#lx.\n", hr
);
6090 ok(IsRectEmpty(&rect
), "Expected empty bbox.\n");
6092 SetRectEmpty(&rect
);
6093 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect
);
6094 ok(hr
== S_OK
, "Failed to get texture bounds, hr %#lx.\n", hr
);
6095 ok(!IsRectEmpty(&rect
), "Unexpected empty bbox.\n");
6097 size
= (rect
.right
- rect
.left
) * (rect
.bottom
- rect
.top
);
6098 bits
= malloc(size
);
6100 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect
, bits
, size
);
6101 ok(hr
== S_OK
, "Failed to get alpha texture, hr %#lx.\n", hr
);
6103 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect
, bits
, size
- 1);
6104 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "Unexpected hr %#lx.\n", hr
);
6106 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_CLEARTYPE_3x1
, &rect
, bits
, size
);
6107 ok(hr
== DWRITE_E_UNSUPPORTEDOPERATION
, "Unexpected hr %#lx.\n", hr
);
6109 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_CLEARTYPE_3x1
, &rect
, bits
, size
- 1);
6111 ok(hr
== DWRITE_E_UNSUPPORTEDOPERATION
, "Unexpected hr %#lx.\n", hr
);
6115 IDWriteGlyphRunAnalysis_Release(analysis
);
6117 IDWriteFactory3_Release(factory3
);
6120 IDWriteFontFace_Release(face
);
6121 ref
= IDWriteFactory_Release(factory
);
6122 ok(ref
== 0, "factory not released, %lu\n", ref
);
6125 #define round(x) ((int)floor((x) + 0.5))
6156 static const struct VDMX_group
*find_vdmx_group(const struct VDMX_Header
*hdr
)
6158 WORD num_ratios
, i
, group_offset
= 0;
6159 struct VDMX_Ratio
*ratios
= (struct VDMX_Ratio
*)(hdr
+ 1);
6160 BYTE dev_x_ratio
= 1, dev_y_ratio
= 1;
6162 num_ratios
= GET_BE_WORD(hdr
->numRatios
);
6164 for (i
= 0; i
< num_ratios
; i
++)
6166 if (!ratios
[i
].bCharSet
) continue;
6168 if ((ratios
[i
].xRatio
== 0 && ratios
[i
].yStartRatio
== 0 &&
6169 ratios
[i
].yEndRatio
== 0) ||
6170 (ratios
[i
].xRatio
== dev_x_ratio
&& ratios
[i
].yStartRatio
<= dev_y_ratio
&&
6171 ratios
[i
].yEndRatio
>= dev_y_ratio
))
6173 group_offset
= GET_BE_WORD(*((WORD
*)(ratios
+ num_ratios
) + i
));
6178 return (const struct VDMX_group
*)((BYTE
*)hdr
+ group_offset
);
6182 static BOOL
get_vdmx_size(const struct VDMX_group
*group
, int emsize
, int *a
, int *d
)
6185 const struct VDMX_vTable
*tables
;
6187 if (!group
) return FALSE
;
6189 recs
= GET_BE_WORD(group
->recs
);
6190 if (emsize
< group
->startsz
|| emsize
>= group
->endsz
) return FALSE
;
6192 tables
= (const struct VDMX_vTable
*)(group
+ 1);
6193 for (i
= 0; i
< recs
; i
++)
6195 WORD ppem
= GET_BE_WORD(tables
[i
].yPelHeight
);
6198 /* FIXME: Supposed to interpolate */
6199 trace("FIXME interpolate %d\n", emsize
);
6205 *a
= (SHORT
)GET_BE_WORD(tables
[i
].yMax
);
6206 *d
= -(SHORT
)GET_BE_WORD(tables
[i
].yMin
);
6213 static void test_metrics_cmp(FLOAT emsize
, const DWRITE_FONT_METRICS
*metrics
, const DWRITE_FONT_METRICS1
*expected
)
6215 winetest_push_context("Size %.2f", emsize
);
6217 ok(metrics
->designUnitsPerEm
== expected
->designUnitsPerEm
, "got %u expect %u.\n",
6218 metrics
->designUnitsPerEm
, expected
->designUnitsPerEm
);
6219 ok(metrics
->ascent
== expected
->ascent
, "a: got %u expect %u.\n", metrics
->ascent
, expected
->ascent
);
6220 ok(metrics
->descent
== expected
->descent
, "d: got %u expect %u.\n", metrics
->descent
, expected
->descent
);
6221 ok(metrics
->lineGap
== expected
->lineGap
, "lg: got %d expect %d.\n", metrics
->lineGap
, expected
->lineGap
);
6222 ok(metrics
->capHeight
== expected
->capHeight
, "capH: got %u expect %u.\n", metrics
->capHeight
, expected
->capHeight
);
6223 ok(metrics
->xHeight
== expected
->xHeight
, "xH: got %u expect %u.\n", metrics
->xHeight
, expected
->xHeight
);
6224 ok(metrics
->underlinePosition
== expected
->underlinePosition
, "ulP: got %d expect %d.\n",
6225 metrics
->underlinePosition
, expected
->underlinePosition
);
6226 ok(metrics
->underlineThickness
== expected
->underlineThickness
, "ulTh: got %u expect %u.\n",
6227 metrics
->underlineThickness
, expected
->underlineThickness
);
6228 ok(metrics
->strikethroughPosition
== expected
->strikethroughPosition
, "stP: got %d expect %d.\n",
6229 metrics
->strikethroughPosition
, expected
->strikethroughPosition
);
6230 ok(metrics
->strikethroughThickness
== expected
->strikethroughThickness
, "stTh: got %u expect %u.\n",
6231 metrics
->strikethroughThickness
, expected
->strikethroughThickness
);
6233 winetest_pop_context();
6236 static void test_metrics1_cmp(FLOAT emsize
, const DWRITE_FONT_METRICS1
*metrics
, const DWRITE_FONT_METRICS1
*expected
)
6238 winetest_push_context("Size %.2f", emsize
);
6240 ok(metrics
->designUnitsPerEm
== expected
->designUnitsPerEm
, "got %u expect %u.\n",
6241 metrics
->designUnitsPerEm
, expected
->designUnitsPerEm
);
6242 ok(metrics
->ascent
== expected
->ascent
, "a: got %u expect %u.\n", metrics
->ascent
, expected
->ascent
);
6243 ok(metrics
->descent
== expected
->descent
, "d: got %u expect %u.\n", metrics
->descent
, expected
->descent
);
6244 ok(metrics
->lineGap
== expected
->lineGap
, "lg: got %d expect %d.\n", metrics
->lineGap
, expected
->lineGap
);
6245 ok(metrics
->capHeight
== expected
->capHeight
, "capH: got %u expect %u.\n", metrics
->capHeight
, expected
->capHeight
);
6246 ok(metrics
->xHeight
== expected
->xHeight
, "xH: got %u expect %u.\n", metrics
->xHeight
, expected
->xHeight
);
6247 ok(metrics
->underlinePosition
== expected
->underlinePosition
, "ulP: got %d expect %d.\n",
6248 metrics
->underlinePosition
, expected
->underlinePosition
);
6249 ok(metrics
->underlineThickness
== expected
->underlineThickness
, "ulTh: got %u expect %u.\n",
6250 metrics
->underlineThickness
, expected
->underlineThickness
);
6251 ok(metrics
->strikethroughPosition
== expected
->strikethroughPosition
, "stP: got %d expect %d.\n",
6252 metrics
->strikethroughPosition
, expected
->strikethroughPosition
);
6253 ok(metrics
->strikethroughThickness
== expected
->strikethroughThickness
, "stTh: got %u expect %u.\n",
6254 metrics
->strikethroughThickness
, expected
->strikethroughThickness
);
6255 ok(metrics
->glyphBoxLeft
== expected
->glyphBoxLeft
, "box left: got %d expect %d.\n",
6256 metrics
->glyphBoxLeft
, expected
->glyphBoxLeft
);
6257 if (0) { /* this is not consistent */
6258 ok(metrics
->glyphBoxTop
== expected
->glyphBoxTop
, "box top: got %d expect %d.\n",
6259 metrics
->glyphBoxTop
, expected
->glyphBoxTop
);
6260 ok(metrics
->glyphBoxRight
== expected
->glyphBoxRight
, "box right: got %d expect %d.\n",
6261 metrics
->glyphBoxRight
, expected
->glyphBoxRight
);
6263 ok(metrics
->glyphBoxBottom
== expected
->glyphBoxBottom
, "box bottom: got %d expect %d.\n",
6264 metrics
->glyphBoxBottom
, expected
->glyphBoxBottom
);
6265 ok(metrics
->subscriptPositionX
== expected
->subscriptPositionX
, "subX: got %d expect %d.\n",
6266 metrics
->subscriptPositionX
, expected
->subscriptPositionX
);
6267 ok(metrics
->subscriptPositionY
== expected
->subscriptPositionY
, "subY: got %d expect %d.\n",
6268 metrics
->subscriptPositionY
, expected
->subscriptPositionY
);
6269 ok(metrics
->subscriptSizeX
== expected
->subscriptSizeX
, "subsizeX: got %d expect %d.\n",
6270 metrics
->subscriptSizeX
, expected
->subscriptSizeX
);
6271 ok(metrics
->subscriptPositionY
== expected
->subscriptPositionY
, "subsizeY: got %d expect %d.\n",
6272 metrics
->subscriptSizeY
, expected
->subscriptSizeY
);
6273 ok(metrics
->superscriptPositionX
== expected
->superscriptPositionX
, "supX: got %d expect %d.\n",
6274 metrics
->superscriptPositionX
, expected
->superscriptPositionX
);
6276 ok(metrics
->superscriptPositionY
== expected
->superscriptPositionY
, "supY: got %d expect %d.\n",
6277 metrics
->superscriptPositionY
, expected
->superscriptPositionY
);
6278 ok(metrics
->superscriptSizeX
== expected
->superscriptSizeX
, "supsizeX: got %d expect %d.\n",
6279 metrics
->superscriptSizeX
, expected
->superscriptSizeX
);
6280 ok(metrics
->superscriptSizeY
== expected
->superscriptSizeY
, "supsizeY: got %d expect %d.\n",
6281 metrics
->superscriptSizeY
, expected
->superscriptSizeY
);
6282 ok(metrics
->hasTypographicMetrics
== expected
->hasTypographicMetrics
, "hastypo: got %d expect %d.\n",
6283 metrics
->hasTypographicMetrics
, expected
->hasTypographicMetrics
);
6285 winetest_pop_context();
6288 struct compatmetrics_test
{
6294 static struct compatmetrics_test compatmetrics_tests
[] = {
6295 { { 0.0, 0.0, 0.0, 1.0, 0.0, 0.0 }, 1.0, 5.0 },
6296 { { 0.0, 0.0, 0.0, -1.0, 0.0, 0.0 }, 1.0, 5.0 },
6297 { { 0.0, 0.0, 0.0, -1.0, 0.0, 0.0 }, 2.0, 5.0 },
6298 { { 0.0, 0.0, 0.0, 3.0, 0.0, 0.0 }, 2.0, 5.0 },
6299 { { 0.0, 0.0, 0.0, -3.0, 0.0, 0.0 }, 2.0, 5.0 },
6300 { { 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 }, 2.0, 5.0 },
6301 { { 1.0, 0.0, 0.0, 1.0, 5.0, 0.0 }, 2.0, 5.0 },
6302 { { 1.0, 0.0, 0.0, 1.0, 0.0, 5.0 }, 2.0, 5.0 },
6305 static void get_expected_metrics(IDWriteFontFace
*fontface
, struct compatmetrics_test
*ptr
,
6306 DWRITE_FONT_METRICS
*expected
)
6310 memset(expected
, 0, sizeof(*expected
));
6311 hr
= IDWriteFontFace_GetGdiCompatibleMetrics(fontface
, ptr
->ppdip
* fabsf(ptr
->m
.m22
) * ptr
->emsize
, 1.0, NULL
, expected
);
6312 ok(hr
== S_OK
, "got %08lx\n", hr
);
6315 static void test_gdicompat_metrics(IDWriteFontFace
*face
)
6317 IDWriteFontFace1
*fontface1
= NULL
;
6319 DWRITE_FONT_METRICS design_metrics
, comp_metrics
;
6320 DWRITE_FONT_METRICS1 design_metrics1
, expected
;
6321 FLOAT emsize
, scale
;
6322 int ascent
, descent
;
6323 const struct VDMX_Header
*vdmx
;
6327 const struct VDMX_group
*vdmx_group
= NULL
;
6330 hr
= IDWriteFontFace_QueryInterface(face
, &IID_IDWriteFontFace1
, (void**)&fontface1
);
6332 win_skip("gdi compatible DWRITE_FONT_METRICS1 are not supported.\n");
6335 IDWriteFontFace1_GetMetrics(fontface1
, &design_metrics1
);
6336 memcpy(&design_metrics
, &design_metrics1
, sizeof(design_metrics
));
6339 IDWriteFontFace_GetMetrics(face
, &design_metrics
);
6341 hr
= IDWriteFontFace_TryGetFontTable(face
, MS_VDMX_TAG
, (const void **)&vdmx
,
6342 &vdmx_len
, &vdmx_ctx
, &exists
);
6343 if (hr
!= S_OK
|| !exists
)
6346 vdmx_group
= find_vdmx_group(vdmx
);
6348 /* negative emsize */
6349 memset(&comp_metrics
, 0xcc, sizeof(comp_metrics
));
6350 memset(&expected
, 0, sizeof(expected
));
6351 hr
= IDWriteFontFace_GetGdiCompatibleMetrics(face
, -10.0, 1.0, NULL
, &comp_metrics
);
6352 ok(hr
== E_INVALIDARG
, "got %08lx\n", hr
);
6353 test_metrics_cmp(0.0, &comp_metrics
, &expected
);
6356 memset(&comp_metrics
, 0xcc, sizeof(comp_metrics
));
6357 memset(&expected
, 0, sizeof(expected
));
6358 hr
= IDWriteFontFace_GetGdiCompatibleMetrics(face
, 0.0, 1.0, NULL
, &comp_metrics
);
6359 ok(hr
== E_INVALIDARG
, "got %08lx\n", hr
);
6360 test_metrics_cmp(0.0, &comp_metrics
, &expected
);
6362 /* zero pixels per dip */
6363 memset(&comp_metrics
, 0xcc, sizeof(comp_metrics
));
6364 memset(&expected
, 0, sizeof(expected
));
6365 hr
= IDWriteFontFace_GetGdiCompatibleMetrics(face
, 5.0, 0.0, NULL
, &comp_metrics
);
6366 ok(hr
== E_INVALIDARG
, "got %08lx\n", hr
);
6367 test_metrics_cmp(5.0, &comp_metrics
, &expected
);
6369 memset(&comp_metrics
, 0xcc, sizeof(comp_metrics
));
6370 hr
= IDWriteFontFace_GetGdiCompatibleMetrics(face
, 5.0, -1.0, NULL
, &comp_metrics
);
6371 ok(hr
== E_INVALIDARG
, "got %08lx\n", hr
);
6372 test_metrics_cmp(5.0, &comp_metrics
, &expected
);
6374 for (i
= 0; i
< ARRAY_SIZE(compatmetrics_tests
); i
++) {
6375 struct compatmetrics_test
*ptr
= &compatmetrics_tests
[i
];
6377 get_expected_metrics(face
, ptr
, (DWRITE_FONT_METRICS
*)&expected
);
6378 hr
= IDWriteFontFace_GetGdiCompatibleMetrics(face
, ptr
->emsize
, ptr
->ppdip
, &ptr
->m
, &comp_metrics
);
6379 ok(hr
== S_OK
, "got %08lx\n", hr
);
6380 test_metrics_cmp(ptr
->emsize
, &comp_metrics
, &expected
);
6383 for (emsize
= 5; emsize
<= design_metrics
.designUnitsPerEm
; emsize
++)
6385 DWRITE_FONT_METRICS1 comp_metrics1
, expected
;
6388 hr
= IDWriteFontFace1_GetGdiCompatibleMetrics(fontface1
, emsize
, 1.0, NULL
, &comp_metrics1
);
6389 ok(hr
== S_OK
, "got %08lx\n", hr
);
6392 hr
= IDWriteFontFace_GetGdiCompatibleMetrics(face
, emsize
, 1.0, NULL
, &comp_metrics
);
6393 ok(hr
== S_OK
, "got %08lx\n", hr
);
6396 scale
= emsize
/ design_metrics
.designUnitsPerEm
;
6397 if (!get_vdmx_size(vdmx_group
, emsize
, &ascent
, &descent
))
6399 ascent
= round(design_metrics
.ascent
* scale
);
6400 descent
= round(design_metrics
.descent
* scale
);
6403 expected
.designUnitsPerEm
= design_metrics
.designUnitsPerEm
;
6404 expected
.ascent
= round(ascent
/ scale
);
6405 expected
.descent
= round(descent
/ scale
);
6406 expected
.lineGap
= round(round(design_metrics
.lineGap
* scale
) / scale
);
6407 expected
.capHeight
= round(round(design_metrics
.capHeight
* scale
) / scale
);
6408 expected
.xHeight
= round(round(design_metrics
.xHeight
* scale
) / scale
);
6409 expected
.underlinePosition
= round(round(design_metrics
.underlinePosition
* scale
) / scale
);
6410 expected
.underlineThickness
= round(round(design_metrics
.underlineThickness
* scale
) / scale
);
6411 expected
.strikethroughPosition
= round(round(design_metrics
.strikethroughPosition
* scale
) / scale
);
6412 expected
.strikethroughThickness
= round(round(design_metrics
.strikethroughThickness
* scale
) / scale
);
6415 expected
.glyphBoxLeft
= round(round(design_metrics1
.glyphBoxLeft
* scale
) / scale
);
6417 if (0) { /* those two fail on Tahoma and Win7 */
6418 expected
.glyphBoxTop
= round(round(design_metrics1
.glyphBoxTop
* scale
) / scale
);
6419 expected
.glyphBoxRight
= round(round(design_metrics1
.glyphBoxRight
* scale
) / scale
);
6421 expected
.glyphBoxBottom
= round(round(design_metrics1
.glyphBoxBottom
* scale
) / scale
);
6422 expected
.subscriptPositionX
= round(round(design_metrics1
.subscriptPositionX
* scale
) / scale
);
6423 expected
.subscriptPositionY
= round(round(design_metrics1
.subscriptPositionY
* scale
) / scale
);
6424 expected
.subscriptSizeX
= round(round(design_metrics1
.subscriptSizeX
* scale
) / scale
);
6425 expected
.subscriptSizeY
= round(round(design_metrics1
.subscriptSizeY
* scale
) / scale
);
6426 expected
.superscriptPositionX
= round(round(design_metrics1
.superscriptPositionX
* scale
) / scale
);
6427 if (0) /* this fails for 3 emsizes, Tahoma from [5, 2048] range */ {
6428 expected
.superscriptPositionY
= round(round(design_metrics1
.superscriptPositionY
* scale
) / scale
);
6430 expected
.superscriptSizeX
= round(round(design_metrics1
.superscriptSizeX
* scale
) / scale
);
6431 expected
.superscriptSizeY
= round(round(design_metrics1
.superscriptSizeY
* scale
) / scale
);
6432 expected
.hasTypographicMetrics
= design_metrics1
.hasTypographicMetrics
;
6434 test_metrics1_cmp(emsize
, &comp_metrics1
, &expected
);
6437 test_metrics_cmp(emsize
, &comp_metrics
, &expected
);
6442 IDWriteFontFace1_Release(fontface1
);
6443 if (vdmx
) IDWriteFontFace_ReleaseFontTable(face
, vdmx_ctx
);
6446 static void test_GetGdiCompatibleMetrics(void)
6448 IDWriteFactory
*factory
;
6450 IDWriteFontFace
*fontface
;
6454 factory
= create_factory();
6456 font
= get_font(factory
, L
"Tahoma", DWRITE_FONT_STYLE_NORMAL
);
6457 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
6458 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6459 IDWriteFont_Release(font
);
6460 test_gdicompat_metrics(fontface
);
6461 IDWriteFontFace_Release(fontface
);
6463 font
= get_font(factory
, L
"Arial", DWRITE_FONT_STYLE_NORMAL
);
6465 skip("Skipping tests with Arial\n");
6468 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
6469 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6470 IDWriteFont_Release(font
);
6472 test_gdicompat_metrics(fontface
);
6473 IDWriteFontFace_Release(fontface
);
6476 ref
= IDWriteFactory_Release(factory
);
6477 ok(ref
== 0, "factory not released, %lu\n", ref
);
6480 static void get_expected_panose(IDWriteFont1
*font
, DWRITE_PANOSE
*panose
)
6482 IDWriteFontFace
*fontface
;
6483 const TT_OS2_V2
*tt_os2
;
6489 memset(panose
, 0, sizeof(*panose
));
6491 hr
= IDWriteFont1_CreateFontFace(font
, &fontface
);
6492 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6494 hr
= IDWriteFontFace_TryGetFontTable(fontface
, MS_OS2_TAG
, (const void **)&tt_os2
, &size
, &os2_context
, &exists
);
6495 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6498 memcpy(panose
, &tt_os2
->panose
, sizeof(*panose
));
6499 IDWriteFontFace_ReleaseFontTable(fontface
, os2_context
);
6502 IDWriteFontFace_Release(fontface
);
6505 static void test_GetPanose(void)
6507 IDWriteFontCollection
*syscollection
;
6508 IDWriteFactory
*factory
;
6509 IDWriteFont1
*font1
;
6515 factory
= create_factory();
6516 font
= get_tahoma_instance(factory
, DWRITE_FONT_STYLE_NORMAL
);
6518 hr
= IDWriteFont_QueryInterface(font
, &IID_IDWriteFont1
, (void **)&font1
);
6519 IDWriteFont_Release(font
);
6522 ref
= IDWriteFactory_Release(factory
);
6523 ok(ref
== 0, "factory not released, %lu\n", ref
);
6524 win_skip("GetPanose() is not supported.\n");
6527 IDWriteFont1_Release(font1
);
6529 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &syscollection
, FALSE
);
6530 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6531 count
= IDWriteFontCollection_GetFontFamilyCount(syscollection
);
6533 for (i
= 0; i
< count
; i
++) {
6534 DWRITE_PANOSE panose
, expected_panose
;
6535 IDWriteLocalizedStrings
*names
;
6536 IDWriteFontFace3
*fontface3
;
6537 IDWriteFontFace
*fontface
;
6538 IDWriteFontFamily
*family
;
6539 IDWriteFont1
*font1
;
6543 hr
= IDWriteFontCollection_GetFontFamily(syscollection
, i
, &family
);
6544 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6546 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STRETCH_NORMAL
,
6547 DWRITE_FONT_STYLE_NORMAL
, &font
);
6548 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6550 hr
= IDWriteFont_QueryInterface(font
, &IID_IDWriteFont1
, (void **)&font1
);
6551 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6552 IDWriteFont_Release(font
);
6554 hr
= IDWriteFontFamily_GetFamilyNames(family
, &names
);
6555 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6557 get_enus_string(names
, nameW
, ARRAY_SIZE(nameW
));
6559 IDWriteLocalizedStrings_Release(names
);
6561 IDWriteFont1_GetPanose(font1
, &panose
);
6562 get_expected_panose(font1
, &expected_panose
);
6564 winetest_push_context("Font %s", wine_dbgstr_w(nameW
));
6566 ok(panose
.values
[0] == expected_panose
.values
[0], "values[0] %#x, expected %#x.\n",
6567 panose
.values
[0], expected_panose
.values
[0]);
6568 ok(panose
.values
[1] == expected_panose
.values
[1], "values[1] %#x, expected %#x.\n",
6569 panose
.values
[1], expected_panose
.values
[1]);
6570 ok(panose
.values
[2] == expected_panose
.values
[2], "values[2] %#x, expected %#x.\n",
6571 panose
.values
[2], expected_panose
.values
[2]);
6572 ok(panose
.values
[3] == expected_panose
.values
[3], "values[3] %#x, expected %#x.\n",
6573 panose
.values
[3], expected_panose
.values
[3]);
6574 ok(panose
.values
[4] == expected_panose
.values
[4], "values[4] %#x, expected %#x.\n",
6575 panose
.values
[4], expected_panose
.values
[4]);
6576 ok(panose
.values
[5] == expected_panose
.values
[5], "values[5] %#x, expected %#x.\n",
6577 panose
.values
[5], expected_panose
.values
[5]);
6578 ok(panose
.values
[6] == expected_panose
.values
[6], "values[6] %#x, expected %#x.\n",
6579 panose
.values
[6], expected_panose
.values
[6]);
6580 ok(panose
.values
[7] == expected_panose
.values
[7], "values[7] %#x, expected %#x.\n",
6581 panose
.values
[7], expected_panose
.values
[7]);
6582 ok(panose
.values
[8] == expected_panose
.values
[8], "values[8] %#x, expected %#x.\n",
6583 panose
.values
[8], expected_panose
.values
[8]);
6584 ok(panose
.values
[9] == expected_panose
.values
[9], "values[9] %#x, expected %#x.\n",
6585 panose
.values
[9], expected_panose
.values
[9]);
6587 winetest_pop_context();
6589 hr
= IDWriteFont1_CreateFontFace(font1
, &fontface
);
6590 ok(hr
== S_OK
, "Failed to create a font face, %#lx.\n", hr
);
6591 if (IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace3
, (void **)&fontface3
) == S_OK
) {
6592 ok(!memcmp(&panose
, &expected_panose
, sizeof(panose
)), "%s: Unexpected panose from font face.\n",
6593 wine_dbgstr_w(nameW
));
6594 IDWriteFontFace3_Release(fontface3
);
6596 IDWriteFontFace_Release(fontface
);
6598 IDWriteFont1_Release(font1
);
6599 IDWriteFontFamily_Release(family
);
6602 IDWriteFontCollection_Release(syscollection
);
6603 ref
= IDWriteFactory_Release(factory
);
6604 ok(ref
== 0, "factory not released, %lu\n", ref
);
6607 static INT32
get_gdi_font_advance(HDC hdc
, FLOAT emsize
)
6614 memset(&logfont
, 0, sizeof(logfont
));
6615 logfont
.lfHeight
= (LONG
)-emsize
;
6616 logfont
.lfWeight
= FW_NORMAL
;
6617 logfont
.lfQuality
= CLEARTYPE_QUALITY
;
6618 lstrcpyW(logfont
.lfFaceName
, L
"Tahoma");
6620 hfont
= CreateFontIndirectW(&logfont
);
6621 SelectObject(hdc
, hfont
);
6623 ret
= GetCharABCWidthsW(hdc
, 'A', 'A', &abc
);
6624 ok(ret
, "got %d\n", ret
);
6626 DeleteObject(hfont
);
6628 return abc
.abcA
+ abc
.abcB
+ abc
.abcC
;
6631 static void test_GetGdiCompatibleGlyphAdvances(void)
6633 IDWriteFontFace1
*fontface1
;
6634 IDWriteFontFace
*fontface
;
6635 IDWriteFactory
*factory
;
6642 DWRITE_FONT_METRICS1 fm
;
6646 factory
= create_factory();
6647 font
= get_tahoma_instance(factory
, DWRITE_FONT_STYLE_NORMAL
);
6649 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
6650 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6651 IDWriteFont_Release(font
);
6653 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void **)&fontface1
);
6654 IDWriteFontFace_Release(fontface
);
6657 ref
= IDWriteFactory_Release(factory
);
6658 ok(ref
== 0, "factory not released, %lu\n", ref
);
6659 win_skip("GetGdiCompatibleGlyphAdvances() is not supported\n");
6665 hr
= IDWriteFontFace1_GetGlyphIndices(fontface1
, &codepoint
, 1, &glyph
);
6666 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6667 ok(glyph
> 0, "got %u\n", glyph
);
6671 hr
= IDWriteFontFace1_GetGdiCompatibleGlyphAdvances(fontface1
, 0.0,
6672 1.0, NULL
, FALSE
, FALSE
, 1, &glyph
, &advance
);
6673 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6674 ok(advance
== 0, "got %d\n", advance
);
6676 /* negative emsize */
6678 hr
= IDWriteFontFace1_GetGdiCompatibleGlyphAdvances(fontface1
, -1.0,
6679 1.0, NULL
, FALSE
, FALSE
, 1, &glyph
, &advance
);
6680 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
6681 ok(advance
== 0, "got %d\n", advance
);
6685 hr
= IDWriteFontFace1_GetGdiCompatibleGlyphAdvances(fontface1
, 1.0,
6686 0.0, NULL
, FALSE
, FALSE
, 1, &glyph
, &advance
);
6687 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
6688 ok(advance
== 0, "got %d\n", advance
);
6690 /* negative ppdip */
6692 hr
= IDWriteFontFace1_GetGdiCompatibleGlyphAdvances(fontface1
, 1.0,
6693 -1.0, NULL
, FALSE
, FALSE
, 1, &glyph
, &advance
);
6694 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
6695 ok(advance
== 0, "got %d\n", advance
);
6697 IDWriteFontFace1_GetMetrics(fontface1
, &fm
);
6699 hdc
= CreateCompatibleDC(0);
6701 for (emsize
= 1.0; emsize
<= fm
.designUnitsPerEm
; emsize
+= 1.0) {
6704 gdi_advance
= get_gdi_font_advance(hdc
, emsize
);
6705 hr
= IDWriteFontFace1_GetGdiCompatibleGlyphAdvances(fontface1
, emsize
,
6706 1.0, NULL
, FALSE
, FALSE
, 1, &glyph
, &advance
);
6707 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6709 /* advance is in design units */
6710 advance
= (int)floorf(emsize
* advance
/ fm
.designUnitsPerEm
+ 0.5f
);
6711 ok((advance
- gdi_advance
) <= 2, "%.0f: got advance %d, expected %d\n", emsize
, advance
, gdi_advance
);
6716 IDWriteFontFace1_Release(fontface1
);
6717 ref
= IDWriteFactory_Release(factory
);
6718 ok(ref
== 0, "factory not released, %lu\n", ref
);
6721 static WORD
get_gasp_flags(IDWriteFontFace
*fontface
, FLOAT emsize
, FLOAT ppdip
)
6723 WORD num_recs
, version
;
6734 hr
= IDWriteFontFace_TryGetFontTable(fontface
, MS_GASP_TAG
,
6735 (const void**)&ptr
, &size
, &ctxt
, &exists
);
6736 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6741 version
= GET_BE_WORD( *ptr
++ );
6742 num_recs
= GET_BE_WORD( *ptr
++ );
6743 if (version
> 1 || size
< (num_recs
* 2 + 2) * sizeof(WORD
)) {
6744 ok(0, "unsupported gasp table: ver %d size %d recs %d\n", version
, size
, num_recs
);
6750 flags
= GET_BE_WORD( *(ptr
+ 1) );
6751 if (emsize
<= GET_BE_WORD( *ptr
)) break;
6756 IDWriteFontFace_ReleaseFontTable(fontface
, ctxt
);
6760 #define GASP_GRIDFIT 0x0001
6761 #define GASP_DOGRAY 0x0002
6762 #define GASP_SYMMETRIC_GRIDFIT 0x0004
6763 #define GASP_SYMMETRIC_SMOOTHING 0x0008
6765 static BOOL g_is_vista
;
6766 static DWRITE_RENDERING_MODE
get_expected_rendering_mode(FLOAT emsize
, WORD gasp
, DWRITE_MEASURING_MODE mode
,
6767 DWRITE_OUTLINE_THRESHOLD threshold
)
6769 static const FLOAT aa_threshold
= 100.0f
;
6770 static const FLOAT a_threshold
= 350.0f
;
6771 static const FLOAT naturalemsize
= 20.0f
;
6774 /* outline threshold */
6776 v
= mode
== DWRITE_MEASURING_MODE_NATURAL
? aa_threshold
: a_threshold
;
6778 v
= threshold
== DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
? aa_threshold
: a_threshold
;
6781 return DWRITE_RENDERING_MODE_OUTLINE
;
6785 case DWRITE_MEASURING_MODE_NATURAL
:
6786 if (!(gasp
& GASP_SYMMETRIC_SMOOTHING
) && (emsize
<= naturalemsize
))
6787 return DWRITE_RENDERING_MODE_NATURAL
;
6789 return DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
;
6790 case DWRITE_MEASURING_MODE_GDI_CLASSIC
:
6791 return DWRITE_RENDERING_MODE_GDI_CLASSIC
;
6792 case DWRITE_MEASURING_MODE_GDI_NATURAL
:
6793 return DWRITE_RENDERING_MODE_GDI_NATURAL
;
6798 /* should be unreachable */
6799 return DWRITE_RENDERING_MODE_DEFAULT
;
6802 static DWRITE_GRID_FIT_MODE
get_expected_gridfit_mode(FLOAT emsize
, WORD gasp
, DWRITE_MEASURING_MODE mode
,
6803 DWRITE_OUTLINE_THRESHOLD threshold
)
6805 static const FLOAT aa_threshold
= 100.0f
;
6806 static const FLOAT a_threshold
= 350.0f
;
6809 v
= threshold
== DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
? aa_threshold
: a_threshold
;
6811 return DWRITE_GRID_FIT_MODE_DISABLED
;
6813 if (mode
== DWRITE_MEASURING_MODE_GDI_CLASSIC
|| mode
== DWRITE_MEASURING_MODE_GDI_NATURAL
)
6814 return DWRITE_GRID_FIT_MODE_ENABLED
;
6816 return (gasp
& (GASP_GRIDFIT
|GASP_SYMMETRIC_GRIDFIT
)) ? DWRITE_GRID_FIT_MODE_ENABLED
: DWRITE_GRID_FIT_MODE_DISABLED
;
6819 struct recommendedmode_test
6821 DWRITE_MEASURING_MODE measuring
;
6822 DWRITE_OUTLINE_THRESHOLD threshold
;
6825 static const struct recommendedmode_test recmode_tests
[] = {
6826 { DWRITE_MEASURING_MODE_NATURAL
, DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
},
6827 { DWRITE_MEASURING_MODE_GDI_CLASSIC
, DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
},
6828 { DWRITE_MEASURING_MODE_GDI_NATURAL
, DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
},
6831 static const struct recommendedmode_test recmode_tests1
[] = {
6832 { DWRITE_MEASURING_MODE_NATURAL
, DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
},
6833 { DWRITE_MEASURING_MODE_GDI_CLASSIC
, DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
},
6834 { DWRITE_MEASURING_MODE_GDI_NATURAL
, DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
},
6835 { DWRITE_MEASURING_MODE_NATURAL
, DWRITE_OUTLINE_THRESHOLD_ALIASED
},
6836 { DWRITE_MEASURING_MODE_GDI_CLASSIC
, DWRITE_OUTLINE_THRESHOLD_ALIASED
},
6837 { DWRITE_MEASURING_MODE_GDI_NATURAL
, DWRITE_OUTLINE_THRESHOLD_ALIASED
},
6840 static void test_GetRecommendedRenderingMode(void)
6842 IDWriteRenderingParams
*params
;
6843 IDWriteFontFace3
*fontface3
;
6844 IDWriteFontFace2
*fontface2
;
6845 IDWriteFontFace1
*fontface1
;
6846 IDWriteFontFace
*fontface
;
6847 DWRITE_RENDERING_MODE mode
;
6848 IDWriteFactory
*factory
;
6853 factory
= create_factory();
6854 fontface
= create_fontface(factory
);
6857 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void**)&fontface1
);
6859 win_skip("IDWriteFontFace1::GetRecommendedRenderingMode() is not supported.\n");
6862 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace2
, (void**)&fontface2
);
6864 win_skip("IDWriteFontFace2::GetRecommendedRenderingMode() is not supported.\n");
6867 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace3
, (void**)&fontface3
);
6869 win_skip("IDWriteFontFace3::GetRecommendedRenderingMode() is not supported.\n");
6871 if (0) /* crashes on native */
6872 hr
= IDWriteFontFace_GetRecommendedRenderingMode(fontface
, 3.0, 1.0,
6873 DWRITE_MEASURING_MODE_GDI_CLASSIC
, NULL
, NULL
);
6876 hr
= IDWriteFontFace_GetRecommendedRenderingMode(fontface
, 3.0, 1.0,
6877 DWRITE_MEASURING_MODE_GDI_CLASSIC
, NULL
, &mode
);
6878 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
6879 ok(mode
== DWRITE_RENDERING_MODE_DEFAULT
, "got %d\n", mode
);
6881 hr
= IDWriteFactory_CreateRenderingParams(factory
, ¶ms
);
6882 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6884 /* detect old dwrite version, that is using higher threshold value */
6885 g_is_vista
= fontface1
== NULL
;
6887 for (emsize
= 1.0; emsize
< 500.0; emsize
+= 1.0)
6889 DWRITE_RENDERING_MODE expected
;
6894 winetest_push_context("Size %.2f", emsize
);
6896 for (i
= 0; i
< ARRAY_SIZE(recmode_tests
); ++i
)
6898 winetest_push_context("%u", i
);
6902 gasp
= get_gasp_flags(fontface
, emsize
, ppdip
);
6903 expected
= get_expected_rendering_mode(emsize
* ppdip
, gasp
, recmode_tests
[i
].measuring
, recmode_tests
[i
].threshold
);
6904 hr
= IDWriteFontFace_GetRecommendedRenderingMode(fontface
, emsize
, ppdip
, recmode_tests
[i
].measuring
, params
, &mode
);
6905 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6906 ok(mode
== expected
, "got %d, ppdip %f, flags 0x%04x, expected %d.\n", mode
, ppdip
, gasp
, expected
);
6908 /* some ppdip variants */
6911 gasp
= get_gasp_flags(fontface
, emsize
, ppdip
);
6912 expected
= get_expected_rendering_mode(emsize
* ppdip
, gasp
, recmode_tests
[i
].measuring
, recmode_tests
[i
].threshold
);
6913 hr
= IDWriteFontFace_GetRecommendedRenderingMode(fontface
, emsize
, ppdip
, recmode_tests
[i
].measuring
, params
, &mode
);
6914 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6915 ok(mode
== expected
, "got %d, ppdip %f, flags 0x%04x, expected %d.\n", mode
, ppdip
, gasp
, expected
);
6917 /* Only test larger sizes to workaround Win7 differences, where unscaled natural emsize threshold is used;
6918 Win8 and Win10 handle this as expected. */
6923 gasp
= get_gasp_flags(fontface
, emsize
, ppdip
);
6924 expected
= get_expected_rendering_mode(emsize
* ppdip
, gasp
, recmode_tests
[i
].measuring
, recmode_tests
[i
].threshold
);
6925 hr
= IDWriteFontFace_GetRecommendedRenderingMode(fontface
, emsize
, ppdip
, recmode_tests
[i
].measuring
, params
, &mode
);
6926 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6927 ok(mode
== expected
, "got %d, ppdip %f, flags 0x%04x, expected %d.\n", mode
, ppdip
, gasp
, expected
);
6931 gasp
= get_gasp_flags(fontface
, emsize
, ppdip
);
6932 expected
= get_expected_rendering_mode(emsize
* ppdip
, gasp
, recmode_tests
[i
].measuring
, recmode_tests
[i
].threshold
);
6933 hr
= IDWriteFontFace_GetRecommendedRenderingMode(fontface
, emsize
, ppdip
, recmode_tests
[i
].measuring
, params
, &mode
);
6934 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6935 ok(mode
== expected
, "got %d, ppdip %f, flags 0x%04x, expected %d.\n", mode
, ppdip
, gasp
, expected
);
6938 winetest_pop_context();
6941 /* IDWriteFontFace1 offers another variant of this method */
6944 for (i
= 0; i
< ARRAY_SIZE(recmode_tests1
); ++i
)
6948 winetest_push_context("%u", i
);
6951 dpi
= 96.0f
* ppdip
;
6953 gasp
= get_gasp_flags(fontface
, emsize
, ppdip
);
6954 expected
= get_expected_rendering_mode(emsize
* ppdip
, gasp
, recmode_tests1
[i
].measuring
, recmode_tests1
[i
].threshold
);
6955 hr
= IDWriteFontFace1_GetRecommendedRenderingMode(fontface1
, emsize
, dpi
, dpi
,
6956 NULL
, FALSE
, recmode_tests1
[i
].threshold
, recmode_tests1
[i
].measuring
, &mode
);
6957 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6958 ok(mode
== expected
, "got %d, dpi %f, flags 0x%04x, expected %d.\n", mode
, dpi
, gasp
, expected
);
6960 /* Only test larger sizes to workaround Win7 differences, where unscaled natural emsize threshold is used;
6961 Win8 and Win10 handle this as expected. */
6965 dpi
= 96.0f
* ppdip
;
6967 gasp
= get_gasp_flags(fontface
, emsize
, ppdip
);
6968 expected
= get_expected_rendering_mode(emsize
* ppdip
, gasp
, recmode_tests1
[i
].measuring
, recmode_tests1
[i
].threshold
);
6969 hr
= IDWriteFontFace1_GetRecommendedRenderingMode(fontface1
, emsize
, dpi
, dpi
,
6970 NULL
, FALSE
, recmode_tests1
[i
].threshold
, recmode_tests1
[i
].measuring
, &mode
);
6971 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6972 ok(mode
== expected
, "got %d, dpi %f, flags 0x%04x, expected %d.\n", mode
, dpi
, gasp
, expected
);
6975 dpi
= 96.0f
* ppdip
;
6977 gasp
= get_gasp_flags(fontface
, emsize
, ppdip
);
6978 expected
= get_expected_rendering_mode(emsize
* ppdip
, gasp
, recmode_tests1
[i
].measuring
, recmode_tests1
[i
].threshold
);
6979 hr
= IDWriteFontFace1_GetRecommendedRenderingMode(fontface1
, emsize
, dpi
, dpi
,
6980 NULL
, FALSE
, recmode_tests1
[i
].threshold
, recmode_tests1
[i
].measuring
, &mode
);
6981 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6982 ok(mode
== expected
, "got %d, dpi %f, flags 0x%04x, expected %d.\n", mode
, dpi
, gasp
, expected
);
6984 /* try different dpis for X and Y direction */
6986 dpi
= 96.0f
* ppdip
;
6988 gasp
= get_gasp_flags(fontface
, emsize
, ppdip
);
6989 expected
= get_expected_rendering_mode(emsize
* ppdip
, gasp
, recmode_tests1
[i
].measuring
, recmode_tests1
[i
].threshold
);
6990 hr
= IDWriteFontFace1_GetRecommendedRenderingMode(fontface1
, emsize
, dpi
* 0.5f
, dpi
,
6991 NULL
, FALSE
, recmode_tests1
[i
].threshold
, recmode_tests1
[i
].measuring
, &mode
);
6992 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6993 ok(mode
== expected
, "got %d, dpi %f, flags 0x%04x, expected %d.\n", mode
, dpi
, gasp
, expected
);
6996 dpi
= 96.0f
* ppdip
;
6998 gasp
= get_gasp_flags(fontface
, emsize
, ppdip
);
6999 expected
= get_expected_rendering_mode(emsize
* ppdip
, gasp
, recmode_tests1
[i
].measuring
, recmode_tests1
[i
].threshold
);
7000 hr
= IDWriteFontFace1_GetRecommendedRenderingMode(fontface1
, emsize
, dpi
, dpi
* 0.5f
,
7001 NULL
, FALSE
, recmode_tests1
[i
].threshold
, recmode_tests1
[i
].measuring
, &mode
);
7002 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7003 ok(mode
== expected
, "got %d, dpi %f, flags 0x%04x, expected %d.\n", mode
, dpi
, gasp
, expected
);
7006 dpi
= 96.0f
* ppdip
;
7008 gasp
= get_gasp_flags(fontface
, emsize
, ppdip
);
7009 expected
= get_expected_rendering_mode(emsize
* ppdip
, gasp
, recmode_tests1
[i
].measuring
, recmode_tests1
[i
].threshold
);
7010 hr
= IDWriteFontFace1_GetRecommendedRenderingMode(fontface1
, emsize
, dpi
* 0.5f
, dpi
,
7011 NULL
, FALSE
, recmode_tests1
[i
].threshold
, recmode_tests1
[i
].measuring
, &mode
);
7012 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7013 ok(mode
== expected
, "got %d, dpi %f, flags 0x%04x, expected %d.\n", mode
, dpi
, gasp
, expected
);
7016 dpi
= 96.0f
* ppdip
;
7018 gasp
= get_gasp_flags(fontface
, emsize
, ppdip
);
7019 expected
= get_expected_rendering_mode(emsize
* ppdip
, gasp
, recmode_tests1
[i
].measuring
, recmode_tests1
[i
].threshold
);
7020 hr
= IDWriteFontFace1_GetRecommendedRenderingMode(fontface1
, emsize
, dpi
, dpi
* 0.5f
,
7021 NULL
, FALSE
, recmode_tests1
[i
].threshold
, recmode_tests1
[i
].measuring
, &mode
);
7022 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7023 ok(mode
== expected
, "got %d, dpi %f, flags 0x%04x, expected %d.\n", mode
, dpi
, gasp
, expected
);
7026 winetest_pop_context();
7030 /* IDWriteFontFace2 - another one */
7032 DWRITE_GRID_FIT_MODE gridfit
, expected_gridfit
;
7034 gasp
= get_gasp_flags(fontface
, emsize
, 1.0f
);
7035 for (i
= 0; i
< ARRAY_SIZE(recmode_tests1
); ++i
)
7037 winetest_push_context("%u", i
);
7040 expected
= get_expected_rendering_mode(emsize
, gasp
, recmode_tests1
[i
].measuring
, recmode_tests1
[i
].threshold
);
7041 expected_gridfit
= get_expected_gridfit_mode(emsize
, gasp
, recmode_tests1
[i
].measuring
, recmode_tests1
[i
].threshold
);
7042 hr
= IDWriteFontFace2_GetRecommendedRenderingMode(fontface2
, emsize
, 96.0f
, 96.0f
,
7043 NULL
, FALSE
, recmode_tests1
[i
].threshold
, recmode_tests1
[i
].measuring
, params
, &mode
, &gridfit
);
7044 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7045 ok(mode
== expected
, "got %d, flags 0x%04x, expected %d.\n", mode
, gasp
, expected
);
7046 ok(gridfit
== expected_gridfit
, "gridfit: got %d, flags 0x%04x, expected %d.\n", gridfit
, gasp
, expected_gridfit
);
7048 winetest_pop_context();
7052 /* IDWriteFontFace3 - and another one */
7054 DWRITE_GRID_FIT_MODE gridfit
, expected_gridfit
;
7055 DWRITE_RENDERING_MODE1 mode1
, expected1
;
7057 gasp
= get_gasp_flags(fontface
, emsize
, 1.0f
);
7058 for (i
= 0; i
< ARRAY_SIZE(recmode_tests1
); ++i
)
7060 winetest_push_context("%u", i
);
7063 expected1
= get_expected_rendering_mode(emsize
, gasp
, recmode_tests1
[i
].measuring
, recmode_tests1
[i
].threshold
);
7064 expected_gridfit
= get_expected_gridfit_mode(emsize
, gasp
, recmode_tests1
[i
].measuring
, recmode_tests1
[i
].threshold
);
7065 hr
= IDWriteFontFace3_GetRecommendedRenderingMode(fontface3
, emsize
, 96.0f
, 96.0f
,
7066 NULL
, FALSE
, recmode_tests1
[i
].threshold
, recmode_tests1
[i
].measuring
, params
, &mode1
, &gridfit
);
7067 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7068 ok(mode1
== expected1
, "got %d, flags 0x%04x, expected %d.\n", mode1
, gasp
, expected1
);
7069 ok(gridfit
== expected_gridfit
, "gridfit: got %d, flags 0x%04x, expected %d.\n", gridfit
, gasp
, expected_gridfit
);
7071 winetest_pop_context();
7075 winetest_pop_context();
7078 IDWriteRenderingParams_Release(params
);
7080 /* test how parameters override returned modes */
7081 hr
= IDWriteFactory_CreateCustomRenderingParams(factory
, 1.0, 0.0, 0.0, DWRITE_PIXEL_GEOMETRY_FLAT
,
7082 DWRITE_RENDERING_MODE_GDI_CLASSIC
, ¶ms
);
7083 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7086 hr
= IDWriteFontFace_GetRecommendedRenderingMode(fontface
, 500.0, 1.0, DWRITE_MEASURING_MODE_NATURAL
, params
, &mode
);
7087 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7088 ok(mode
== DWRITE_RENDERING_MODE_GDI_CLASSIC
, "got %d\n", mode
);
7090 IDWriteRenderingParams_Release(params
);
7093 IDWriteRenderingParams2
*params2
;
7094 IDWriteFactory2
*factory2
;
7095 DWRITE_GRID_FIT_MODE gridfit
;
7097 hr
= IDWriteFactory_QueryInterface(factory
, &IID_IDWriteFactory2
, (void**)&factory2
);
7098 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7100 hr
= IDWriteFactory2_CreateCustomRenderingParams(factory2
, 1.0, 0.0, 0.0, 0.5, DWRITE_PIXEL_GEOMETRY_FLAT
,
7101 DWRITE_RENDERING_MODE_OUTLINE
, DWRITE_GRID_FIT_MODE_ENABLED
, ¶ms2
);
7102 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7106 hr
= IDWriteFontFace2_GetRecommendedRenderingMode(fontface2
, 5.0, 96.0, 96.0,
7107 NULL
, FALSE
, DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
, DWRITE_MEASURING_MODE_GDI_CLASSIC
,
7108 NULL
, &mode
, &gridfit
);
7109 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7110 ok(mode
== DWRITE_RENDERING_MODE_GDI_CLASSIC
, "got %d\n", mode
);
7111 ok(gridfit
== DWRITE_GRID_FIT_MODE_ENABLED
, "got %d\n", gridfit
);
7115 hr
= IDWriteFontFace2_GetRecommendedRenderingMode(fontface2
, 5.0, 96.0, 96.0,
7116 NULL
, FALSE
, DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
, DWRITE_MEASURING_MODE_GDI_CLASSIC
,
7117 (IDWriteRenderingParams
*)params2
, &mode
, &gridfit
);
7118 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7119 ok(mode
== DWRITE_RENDERING_MODE_OUTLINE
, "got %d\n", mode
);
7120 ok(gridfit
== DWRITE_GRID_FIT_MODE_ENABLED
, "got %d\n", gridfit
);
7122 IDWriteRenderingParams2_Release(params2
);
7123 IDWriteFactory2_Release(factory2
);
7127 IDWriteRenderingParams3
*params3
;
7128 IDWriteRenderingParams2
*params2
;
7129 IDWriteRenderingParams
*params
;
7130 IDWriteFactory3
*factory3
;
7131 DWRITE_GRID_FIT_MODE gridfit
;
7132 DWRITE_RENDERING_MODE1 mode1
;
7134 hr
= IDWriteFactory_QueryInterface(factory
, &IID_IDWriteFactory3
, (void**)&factory3
);
7135 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7137 hr
= IDWriteFactory3_CreateCustomRenderingParams(factory3
, 1.0f
, 0.0f
, 0.0f
, 0.5f
, DWRITE_PIXEL_GEOMETRY_FLAT
,
7138 DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC_DOWNSAMPLED
, DWRITE_GRID_FIT_MODE_ENABLED
, ¶ms3
);
7139 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7141 mode1
= IDWriteRenderingParams3_GetRenderingMode1(params3
);
7142 ok(mode1
== DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC_DOWNSAMPLED
, "got %d\n", mode1
);
7144 mode
= IDWriteRenderingParams3_GetRenderingMode(params3
);
7145 ok(mode
== DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
, "got %d\n", mode
);
7147 hr
= IDWriteRenderingParams3_QueryInterface(params3
, &IID_IDWriteRenderingParams
, (void**)¶ms
);
7148 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7149 ok(params
== (IDWriteRenderingParams
*)params3
, "got %p, %p\n", params3
, params
);
7150 mode
= IDWriteRenderingParams_GetRenderingMode(params
);
7151 ok(mode
== DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
, "got %d\n", mode
);
7152 IDWriteRenderingParams_Release(params
);
7154 hr
= IDWriteRenderingParams3_QueryInterface(params3
, &IID_IDWriteRenderingParams2
, (void**)¶ms2
);
7155 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7156 ok(params2
== (IDWriteRenderingParams2
*)params3
, "got %p, %p\n", params3
, params2
);
7157 mode
= IDWriteRenderingParams2_GetRenderingMode(params2
);
7158 ok(mode
== DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
, "got %d\n", mode
);
7159 IDWriteRenderingParams2_Release(params2
);
7163 hr
= IDWriteFontFace2_GetRecommendedRenderingMode(fontface2
, 5.0f
, 96.0f
, 96.0f
,
7164 NULL
, FALSE
, DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
, DWRITE_MEASURING_MODE_GDI_CLASSIC
,
7165 NULL
, &mode
, &gridfit
);
7166 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7167 ok(mode
== DWRITE_RENDERING_MODE_GDI_CLASSIC
, "got %d\n", mode
);
7168 ok(gridfit
== DWRITE_GRID_FIT_MODE_ENABLED
, "got %d\n", gridfit
);
7172 hr
= IDWriteFontFace2_GetRecommendedRenderingMode(fontface2
, 5.0f
, 96.0f
, 96.0f
,
7173 NULL
, FALSE
, DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
, DWRITE_MEASURING_MODE_GDI_CLASSIC
,
7174 (IDWriteRenderingParams
*)params3
, &mode
, &gridfit
);
7175 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7176 ok(mode
== DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
, "got %d\n", mode
);
7177 ok(gridfit
== DWRITE_GRID_FIT_MODE_ENABLED
, "got %d\n", gridfit
);
7179 IDWriteRenderingParams3_Release(params3
);
7180 IDWriteFactory3_Release(factory3
);
7184 IDWriteFontFace3_Release(fontface3
);
7186 IDWriteFontFace2_Release(fontface2
);
7188 IDWriteFontFace1_Release(fontface1
);
7189 IDWriteFontFace_Release(fontface
);
7190 ref
= IDWriteFactory_Release(factory
);
7191 ok(ref
== 0, "factory not released, %lu\n", ref
);
7194 static inline BOOL
float_eq(FLOAT left
, FLOAT right
)
7196 int x
= *(int *)&left
;
7197 int y
= *(int *)&right
;
7204 return abs(x
- y
) <= 8;
7207 static void test_GetAlphaBlendParams(void)
7209 static const DWRITE_RENDERING_MODE rendermodes
[] = {
7210 DWRITE_RENDERING_MODE_ALIASED
,
7211 DWRITE_RENDERING_MODE_GDI_CLASSIC
,
7212 DWRITE_RENDERING_MODE_GDI_NATURAL
,
7213 DWRITE_RENDERING_MODE_NATURAL
,
7214 DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
,
7217 IDWriteGlyphRunAnalysis
*analysis
;
7218 FLOAT gamma
, contrast
, ctlevel
;
7219 IDWriteRenderingParams
*params
;
7220 DWRITE_GLYPH_METRICS metrics
;
7221 DWRITE_GLYPH_OFFSET offset
;
7222 IDWriteFontFace
*fontface
;
7223 IDWriteFactory
*factory
;
7224 DWRITE_GLYPH_RUN run
;
7225 FLOAT advance
, expected_gdi_gamma
;
7233 factory
= create_factory();
7234 fontface
= create_fontface(factory
);
7238 hr
= IDWriteFontFace_GetGlyphIndices(fontface
, &ch
, 1, &glyph
);
7239 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7240 ok(glyph
> 0, "got %u\n", glyph
);
7242 hr
= IDWriteFontFace_GetDesignGlyphMetrics(fontface
, &glyph
, 1, &metrics
, FALSE
);
7243 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7244 advance
= metrics
.advanceWidth
;
7246 offset
.advanceOffset
= 0.0;
7247 offset
.ascenderOffset
= 0.0;
7249 run
.fontFace
= fontface
;
7250 run
.fontEmSize
= 24.0;
7252 run
.glyphIndices
= &glyph
;
7253 run
.glyphAdvances
= &advance
;
7254 run
.glyphOffsets
= &offset
;
7255 run
.isSideways
= FALSE
;
7258 hr
= IDWriteFactory_CreateCustomRenderingParams(factory
, 0.9, 0.3, 0.1, DWRITE_PIXEL_GEOMETRY_RGB
,
7259 DWRITE_RENDERING_MODE_DEFAULT
, ¶ms
);
7260 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7263 ret
= SystemParametersInfoW(SPI_GETFONTSMOOTHINGCONTRAST
, 0, &value
, 0);
7264 ok(ret
, "got %d\n", ret
);
7265 expected_gdi_gamma
= (FLOAT
)(value
/ 1000.0);
7267 for (i
= 0; i
< ARRAY_SIZE(rendermodes
); i
++) {
7268 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 1.0, NULL
,
7269 rendermodes
[i
], DWRITE_MEASURING_MODE_NATURAL
,
7270 0.0, 0.0, &analysis
);
7271 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7273 gamma
= contrast
= ctlevel
= -1.0;
7274 hr
= IDWriteGlyphRunAnalysis_GetAlphaBlendParams(analysis
, NULL
, &gamma
, &contrast
, &ctlevel
);
7275 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
7276 ok(gamma
== -1.0, "got %.2f\n", gamma
);
7277 ok(contrast
== -1.0, "got %.2f\n", contrast
);
7278 ok(ctlevel
== -1.0, "got %.2f\n", ctlevel
);
7280 gamma
= contrast
= ctlevel
= -1.0;
7281 hr
= IDWriteGlyphRunAnalysis_GetAlphaBlendParams(analysis
, params
, &gamma
, &contrast
, &ctlevel
);
7282 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7284 if (rendermodes
[i
] == DWRITE_RENDERING_MODE_GDI_CLASSIC
|| rendermodes
[i
] == DWRITE_RENDERING_MODE_GDI_NATURAL
) {
7285 ok(float_eq(gamma
, expected_gdi_gamma
), "got %.2f, expected %.2f\n", gamma
, expected_gdi_gamma
);
7286 ok(contrast
== 0.0f
, "got %.2f\n", contrast
);
7287 ok(ctlevel
== 1.0f
, "got %.2f\n", ctlevel
);
7290 ok(gamma
== 0.9f
, "got %.2f\n", gamma
);
7291 ok(contrast
== 0.3f
, "got %.2f\n", contrast
);
7292 ok(ctlevel
== 0.1f
, "got %.2f\n", ctlevel
);
7295 IDWriteGlyphRunAnalysis_Release(analysis
);
7298 IDWriteRenderingParams_Release(params
);
7299 IDWriteFontFace_Release(fontface
);
7300 ref
= IDWriteFactory_Release(factory
);
7301 ok(ref
== 0, "factory not released, %lu\n", ref
);
7304 static void test_CreateAlphaTexture(void)
7306 IDWriteGlyphRunAnalysis
*analysis
;
7307 DWRITE_GLYPH_METRICS metrics
;
7308 DWRITE_GLYPH_OFFSET offset
;
7309 IDWriteFontFace
*fontface
;
7310 IDWriteFactory
*factory
;
7311 DWRITE_GLYPH_RUN run
;
7320 factory
= create_factory();
7321 fontface
= create_fontface(factory
);
7325 hr
= IDWriteFontFace_GetGlyphIndices(fontface
, &ch
, 1, &glyph
);
7326 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7327 ok(glyph
> 0, "got %u\n", glyph
);
7329 hr
= IDWriteFontFace_GetDesignGlyphMetrics(fontface
, &glyph
, 1, &metrics
, FALSE
);
7330 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7331 advance
= metrics
.advanceWidth
;
7333 offset
.advanceOffset
= 0.0;
7334 offset
.ascenderOffset
= 0.0;
7336 run
.fontFace
= fontface
;
7337 run
.fontEmSize
= 24.0;
7339 run
.glyphIndices
= &glyph
;
7340 run
.glyphAdvances
= &advance
;
7341 run
.glyphOffsets
= &offset
;
7342 run
.isSideways
= FALSE
;
7345 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 1.0, NULL
,
7346 DWRITE_RENDERING_MODE_NATURAL
, DWRITE_MEASURING_MODE_NATURAL
,
7347 0.0, 0.0, &analysis
);
7348 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7350 SetRectEmpty(&bounds
);
7351 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_CLEARTYPE_3x1
, &bounds
);
7352 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7353 ok(!IsRectEmpty(&bounds
), "got empty rect\n");
7354 size
= (bounds
.right
- bounds
.left
)*(bounds
.bottom
- bounds
.top
)*3;
7355 ok(sizeof(buff
) >= size
, "required %u\n", size
);
7357 /* invalid type value */
7358 memset(buff
, 0xcf, sizeof(buff
));
7359 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_CLEARTYPE_3x1
+1, &bounds
, buff
, sizeof(buff
));
7360 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
7361 ok(buff
[0] == 0xcf, "got %1x\n", buff
[0]);
7363 memset(buff
, 0xcf, sizeof(buff
));
7364 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &bounds
, buff
, 2);
7365 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "Unexpected hr %#lx.\n", hr
);
7366 ok(buff
[0] == 0xcf, "got %1x\n", buff
[0]);
7368 /* vista version allows texture type mismatch, mark it broken for now */
7369 memset(buff
, 0xcf, sizeof(buff
));
7370 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &bounds
, buff
, sizeof(buff
));
7371 ok(hr
== DWRITE_E_UNSUPPORTEDOPERATION
|| broken(hr
== S_OK
), "Unexpected hr %#lx.\n", hr
);
7372 ok(buff
[0] == 0xcf || broken(buff
[0] == 0), "got %1x\n", buff
[0]);
7374 memset(buff
, 0xcf, sizeof(buff
));
7375 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_CLEARTYPE_3x1
, &bounds
, buff
, size
-1);
7376 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "Unexpected hr %#lx.\n", hr
);
7377 ok(buff
[0] == 0xcf, "got %1x\n", buff
[0]);
7379 IDWriteGlyphRunAnalysis_Release(analysis
);
7381 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 1.0, NULL
,
7382 DWRITE_RENDERING_MODE_ALIASED
, DWRITE_MEASURING_MODE_GDI_CLASSIC
,
7383 0.0, 0.0, &analysis
);
7384 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7386 SetRectEmpty(&bounds
);
7387 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &bounds
);
7388 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7389 ok(!IsRectEmpty(&bounds
), "got empty rect\n");
7390 size
= (bounds
.right
- bounds
.left
)*(bounds
.bottom
- bounds
.top
);
7391 ok(sizeof(buff
) >= size
, "required %u\n", size
);
7393 memset(buff
, 0xcf, sizeof(buff
));
7394 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, NULL
, buff
, sizeof(buff
));
7395 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
7396 ok(buff
[0] == 0xcf, "got %1x\n", buff
[0]);
7398 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, NULL
, NULL
, sizeof(buff
));
7399 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
7401 memset(buff
, 0xcf, sizeof(buff
));
7402 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, NULL
, buff
, 0);
7403 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
7404 ok(buff
[0] == 0xcf, "got %1x\n", buff
[0]);
7406 /* buffer size is not enough */
7407 memset(buff
, 0xcf, sizeof(buff
));
7408 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &bounds
, buff
, size
-1);
7409 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "Unexpected hr %#lx.\n", hr
);
7410 ok(buff
[0] == 0xcf, "got %1x\n", buff
[0]);
7412 /* request texture for rectangle that doesn't intersect */
7413 memset(buff
, 0xcf, sizeof(buff
));
7415 OffsetRect(&r
, (bounds
.right
- bounds
.left
)*2, 0);
7416 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &r
, buff
, sizeof(buff
));
7417 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7418 ok(buff
[0] == 0, "got %1x\n", buff
[0]);
7420 memset(buff
, 0xcf, sizeof(buff
));
7422 OffsetRect(&r
, (bounds
.right
- bounds
.left
)*2, 0);
7423 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &r
, buff
, sizeof(buff
));
7424 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7425 ok(buff
[0] == 0, "got %1x\n", buff
[0]);
7427 /* request texture for rectangle that doesn't intersect, small buffer */
7428 memset(buff
, 0xcf, sizeof(buff
));
7430 OffsetRect(&r
, (bounds
.right
- bounds
.left
)*2, 0);
7431 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &r
, buff
, size
-1);
7432 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "Unexpected hr %#lx.\n", hr
);
7433 ok(buff
[0] == 0xcf, "got %1x\n", buff
[0]);
7435 /* vista version allows texture type mismatch, mark it broken for now */
7436 memset(buff
, 0xcf, sizeof(buff
));
7437 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_CLEARTYPE_3x1
, &bounds
, buff
, sizeof(buff
));
7438 ok(hr
== DWRITE_E_UNSUPPORTEDOPERATION
|| broken(hr
== S_OK
), "Unexpected hr %#lx.\n", hr
);
7439 ok(buff
[0] == 0xcf || broken(buff
[0] == 0), "got %1x\n", buff
[0]);
7441 IDWriteGlyphRunAnalysis_Release(analysis
);
7442 IDWriteFontFace_Release(fontface
);
7443 ref
= IDWriteFactory_Release(factory
);
7444 ok(ref
== 0, "factory not released, %lu\n", ref
);
7447 static BOOL
get_expected_is_symbol(IDWriteFontFace
*fontface
)
7449 BOOL exists
, is_symbol
= FALSE
;
7450 struct dwrite_fonttable cmap
;
7451 const TT_OS2_V2
*tt_os2
;
7459 hr
= IDWriteFontFace_TryGetFontTable(fontface
, MS_OS2_TAG
, (const void **)&tt_os2
, &size
, &os2_context
, &exists
);
7460 ok(hr
== S_OK
, "Failed to get OS/2 table, hr %#lx.\n", hr
);
7464 is_symbol
= tt_os2
->panose
.bFamilyType
== PAN_FAMILY_PICTORIAL
;
7465 IDWriteFontFace_ReleaseFontTable(fontface
, os2_context
);
7471 hr
= IDWriteFontFace_TryGetFontTable(fontface
, MS_CMAP_TAG
, (const void **)&cmap
.data
,
7472 &cmap
.size
, &cmap
.context
, &exists
);
7473 if (FAILED(hr
) || !exists
)
7476 num_tables
= table_read_be_word(&cmap
, 0, FIELD_OFFSET(struct cmap_header
, num_tables
));
7477 tables
= cmap
.data
+ FIELD_OFFSET(struct cmap_header
, tables
);
7479 for (i
= 0; i
< num_tables
; ++i
)
7481 struct cmap_encoding_record
*record
= (struct cmap_encoding_record
*)(tables
+ i
* sizeof(*record
));
7482 WORD platform
, encoding
;
7484 platform
= table_read_be_word(&cmap
, record
, FIELD_OFFSET(struct cmap_encoding_record
, platformID
));
7485 encoding
= table_read_be_word(&cmap
, record
, FIELD_OFFSET(struct cmap_encoding_record
, encodingID
));
7487 if (platform
== OPENTYPE_CMAP_TABLE_PLATFORM_WIN
&& encoding
== OPENTYPE_CMAP_TABLE_ENCODING_SYMBOL
)
7494 IDWriteFontFace_ReleaseFontTable(fontface
, cmap
.context
);
7499 static void test_IsSymbolFont(void)
7501 IDWriteFontCollection
*collection
;
7502 IDWriteFontFace
*fontface
;
7503 IDWriteFactory
*factory
;
7509 factory
= create_factory();
7511 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &collection
, FALSE
);
7512 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7514 count
= IDWriteFontCollection_GetFontFamilyCount(collection
);
7515 for (i
= 0; i
< count
; ++i
)
7517 IDWriteLocalizedStrings
*names
;
7518 IDWriteFontFamily
*family
;
7519 UINT32 font_count
, j
;
7522 hr
= IDWriteFontCollection_GetFontFamily(collection
, i
, &family
);
7523 ok(hr
== S_OK
, "Failed to get family, hr %#lx.\n", hr
);
7525 hr
= IDWriteFontFamily_GetFamilyNames(family
, &names
);
7526 ok(hr
== S_OK
, "Failed to get names, hr %#lx.\n", hr
);
7527 get_enus_string(names
, nameW
, ARRAY_SIZE(nameW
));
7528 IDWriteLocalizedStrings_Release(names
);
7530 font_count
= IDWriteFontFamily_GetFontCount(family
);
7532 for (j
= 0; j
< font_count
; ++j
)
7534 BOOL is_symbol_font
, is_symbol_face
, is_symbol_expected
;
7536 hr
= IDWriteFontFamily_GetFont(family
, j
, &font
);
7537 ok(hr
== S_OK
, "Failed to get font, hr %#lx.\n", hr
);
7539 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
7540 ok(hr
== S_OK
, "Failed to create fontface, hr %#lx.\n", hr
);
7542 is_symbol_font
= IDWriteFont_IsSymbolFont(font
);
7543 is_symbol_face
= IDWriteFontFace_IsSymbolFont(fontface
);
7544 ok(is_symbol_font
== is_symbol_face
, "Unexpected symbol flag.\n");
7546 is_symbol_expected
= get_expected_is_symbol(fontface
);
7547 ok(is_symbol_expected
== is_symbol_face
, "Unexpected is_symbol flag %d for %s, font %d.\n",
7548 is_symbol_face
, wine_dbgstr_w(nameW
), j
);
7550 IDWriteFontFace_Release(fontface
);
7551 IDWriteFont_Release(font
);
7554 IDWriteFontFamily_Release(family
);
7557 IDWriteFontCollection_Release(collection
);
7559 ref
= IDWriteFactory_Release(factory
);
7560 ok(ref
== 0, "factory not released, %lu\n", ref
);
7563 struct CPAL_Header_0
7566 USHORT numPaletteEntries
;
7568 USHORT numColorRecords
;
7569 ULONG offsetFirstColorRecord
;
7570 USHORT colorRecordIndices
[1];
7573 static void test_GetPaletteEntries(void)
7575 IDWriteFontFace2
*fontface2
;
7576 IDWriteFontFace
*fontface
;
7577 IDWriteFactory
*factory
;
7579 DWRITE_COLOR_F color
;
7580 UINT32 palettecount
, entrycount
, size
, colorrecords
;
7582 const struct CPAL_Header_0
*cpal_header
;
7587 factory
= create_factory();
7589 /* Tahoma, no color support */
7590 fontface
= create_fontface(factory
);
7591 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace2
, (void**)&fontface2
);
7592 IDWriteFontFace_Release(fontface
);
7594 ref
= IDWriteFactory_Release(factory
);
7595 ok(ref
== 0, "factory not released, %lu\n", ref
);
7596 win_skip("GetPaletteEntries() is not supported.\n");
7600 hr
= IDWriteFontFace2_GetPaletteEntries(fontface2
, 0, 0, 1, &color
);
7601 ok(hr
== DWRITE_E_NOCOLOR
, "Unexpected hr %#lx.\n", hr
);
7602 IDWriteFontFace2_Release(fontface2
);
7604 /* Segoe UI Emoji, with color support */
7605 font
= get_font(factory
, L
"Segoe UI Emoji", DWRITE_FONT_STYLE_NORMAL
);
7607 ref
= IDWriteFactory_Release(factory
);
7608 ok(ref
== 0, "factory not released, %lu\n", ref
);
7609 skip("Segoe UI Emoji font not found.\n");
7613 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
7614 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7615 IDWriteFont_Release(font
);
7617 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace2
, (void**)&fontface2
);
7618 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7619 IDWriteFontFace_Release(fontface
);
7621 palettecount
= IDWriteFontFace2_GetColorPaletteCount(fontface2
);
7622 ok(palettecount
>= 1, "got %u\n", palettecount
);
7624 entrycount
= IDWriteFontFace2_GetPaletteEntryCount(fontface2
);
7625 ok(entrycount
>= 1, "got %u\n", entrycount
);
7628 hr
= IDWriteFontFace2_TryGetFontTable(fontface2
, MS_CPAL_TAG
, (const void**)&cpal_header
, &size
, &ctxt
, &exists
);
7629 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7630 ok(exists
, "got %d\n", exists
);
7631 colorrecords
= GET_BE_WORD(cpal_header
->numColorRecords
);
7632 ok(colorrecords
>= 1, "got %u\n", colorrecords
);
7634 /* invalid palette index */
7635 color
.r
= color
.g
= color
.b
= color
.a
= 123.0;
7636 hr
= IDWriteFontFace2_GetPaletteEntries(fontface2
, palettecount
, 0, 1, &color
);
7637 ok(hr
== DWRITE_E_NOCOLOR
, "Unexpected hr %#lx.\n", hr
);
7638 ok(color
.r
== 123.0 && color
.g
== 123.0 && color
.b
== 123.0 && color
.a
== 123.0,
7639 "got wrong color %.2fx%.2fx%.2fx%.2f\n", color
.r
, color
.g
, color
.b
, color
.a
);
7641 /* invalid entry index */
7642 color
.r
= color
.g
= color
.b
= color
.a
= 123.0;
7643 hr
= IDWriteFontFace2_GetPaletteEntries(fontface2
, 0, entrycount
, 1, &color
);
7644 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
7645 ok(color
.r
== 123.0 && color
.g
== 123.0 && color
.b
== 123.0 && color
.a
== 123.0,
7646 "got wrong color %.2fx%.2fx%.2fx%.2f\n", color
.r
, color
.g
, color
.b
, color
.a
);
7648 color
.r
= color
.g
= color
.b
= color
.a
= 123.0;
7649 hr
= IDWriteFontFace2_GetPaletteEntries(fontface2
, 0, entrycount
- 1, 1, &color
);
7650 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7651 ok(color
.r
!= 123.0 && color
.g
!= 123.0 && color
.b
!= 123.0 && color
.a
!= 123.0,
7652 "got wrong color %.2fx%.2fx%.2fx%.2f\n", color
.r
, color
.g
, color
.b
, color
.a
);
7654 /* zero return length */
7655 color
.r
= color
.g
= color
.b
= color
.a
= 123.0;
7656 hr
= IDWriteFontFace2_GetPaletteEntries(fontface2
, 0, 0, 0, &color
);
7657 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7658 ok(color
.r
== 123.0 && color
.g
== 123.0 && color
.b
== 123.0 && color
.a
== 123.0,
7659 "got wrong color %.2fx%.2fx%.2fx%.2f\n", color
.r
, color
.g
, color
.b
, color
.a
);
7661 IDWriteFontFace2_Release(fontface2
);
7662 ref
= IDWriteFactory_Release(factory
);
7663 ok(ref
== 0, "factory not released, %lu\n", ref
);
7666 static void test_TranslateColorGlyphRun(void)
7668 IDWriteColorGlyphRunEnumerator1
*layers1
;
7669 IDWriteColorGlyphRunEnumerator
*layers
;
7670 const DWRITE_COLOR_GLYPH_RUN1
*colorrun1
;
7671 const DWRITE_COLOR_GLYPH_RUN
*colorrun
;
7672 IDWriteFontFace2
*fontface2
;
7673 IDWriteFontFace
*fontface
;
7674 IDWriteFactory4
*factory4
;
7675 IDWriteFactory2
*factory
;
7676 DWRITE_GLYPH_RUN run
;
7677 UINT32 codepoints
[2];
7684 factory
= create_factory_iid(&IID_IDWriteFactory2
);
7686 win_skip("TranslateColorGlyphRun() is not supported.\n");
7690 /* Tahoma, no color support */
7691 fontface
= create_fontface((IDWriteFactory
*)factory
);
7693 codepoints
[0] = 'A';
7694 hr
= IDWriteFontFace_GetGlyphIndices(fontface
, codepoints
, 1, glyphs
);
7695 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7697 run
.fontFace
= fontface
;
7698 run
.fontEmSize
= 20.0f
;
7700 run
.glyphIndices
= glyphs
;
7701 run
.glyphAdvances
= NULL
;
7702 run
.glyphOffsets
= NULL
;
7703 run
.isSideways
= FALSE
;
7706 layers
= (void*)0xdeadbeef;
7707 hr
= IDWriteFactory2_TranslateColorGlyphRun(factory
, 0.0f
, 0.0f
, &run
, NULL
,
7708 DWRITE_MEASURING_MODE_NATURAL
, NULL
, 0, &layers
);
7709 ok(hr
== DWRITE_E_NOCOLOR
, "Unexpected hr %#lx.\n", hr
);
7710 ok(layers
== NULL
, "got %p\n", layers
);
7711 IDWriteFontFace_Release(fontface
);
7713 /* Segoe UI Emoji, with color support */
7714 font
= get_font((IDWriteFactory
*)factory
, L
"Segoe UI Emoji", DWRITE_FONT_STYLE_NORMAL
);
7716 IDWriteFactory2_Release(factory
);
7717 skip("Segoe UI Emoji font not found.\n");
7721 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
7722 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7723 IDWriteFont_Release(font
);
7725 codepoints
[0] = 0x26c4;
7726 hr
= IDWriteFontFace_GetGlyphIndices(fontface
, codepoints
, 1, glyphs
);
7727 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7729 run
.fontFace
= fontface
;
7732 hr
= IDWriteFactory2_TranslateColorGlyphRun(factory
, 0.0f
, 0.0f
, &run
, NULL
,
7733 DWRITE_MEASURING_MODE_NATURAL
, NULL
, 0, &layers
);
7734 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7735 ok(layers
!= NULL
, "got %p\n", layers
);
7737 hr
= IDWriteColorGlyphRunEnumerator_QueryInterface(layers
, &IID_IDWriteColorGlyphRunEnumerator1
, (void **)&layers1
);
7741 win_skip("IDWriteColorGlyphRunEnumerator1 is not supported.\n");
7747 hr
= IDWriteColorGlyphRunEnumerator_MoveNext(layers
, &hasrun
);
7748 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7753 hr
= IDWriteColorGlyphRunEnumerator_GetCurrentRun(layers
, &colorrun
);
7754 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7755 ok(colorrun
->glyphRun
.fontFace
== fontface
, "Unexpected fontface %p.\n", colorrun
->glyphRun
.fontFace
);
7756 ok(colorrun
->glyphRun
.fontEmSize
== 20.0f
, "got wrong font size %f\n", colorrun
->glyphRun
.fontEmSize
);
7757 ok(colorrun
->glyphRun
.glyphCount
== 1, "Unexpected glyph count %u.\n", colorrun
->glyphRun
.glyphCount
);
7758 ok(colorrun
->glyphRun
.glyphIndices
!= NULL
, "got null glyph indices %p\n", colorrun
->glyphRun
.glyphIndices
);
7759 ok(colorrun
->glyphRun
.glyphAdvances
!= NULL
, "got null glyph advances %p\n", colorrun
->glyphRun
.glyphAdvances
);
7760 ok(!colorrun
->glyphRunDescription
, "Unexpected description pointer.\n");
7764 hr
= IDWriteColorGlyphRunEnumerator1_GetCurrentRun(layers1
, &colorrun1
);
7765 ok(hr
== S_OK
, "Failed to get color runt, hr %#lx.\n", hr
);
7766 ok((const DWRITE_COLOR_GLYPH_RUN
*)colorrun1
== colorrun
, "Unexpected pointer.\n");
7767 ok(colorrun1
->glyphImageFormat
== (DWRITE_GLYPH_IMAGE_FORMATS_TRUETYPE
| DWRITE_GLYPH_IMAGE_FORMATS_COLR
) ||
7768 colorrun1
->glyphImageFormat
== DWRITE_GLYPH_IMAGE_FORMATS_NONE
,
7769 "Unexpected glyph image format %#x.\n", colorrun1
->glyphImageFormat
);
7770 ok(colorrun1
->measuringMode
== DWRITE_MEASURING_MODE_NATURAL
, "Unexpected measuring mode %d.\n",
7771 colorrun1
->measuringMode
);
7775 /* iterated all way through */
7776 hr
= IDWriteColorGlyphRunEnumerator_GetCurrentRun(layers
, &colorrun
);
7777 ok(hr
== E_NOT_VALID_STATE
, "Unexpected hr %#lx.\n", hr
);
7781 hr
= IDWriteColorGlyphRunEnumerator1_GetCurrentRun(layers1
, &colorrun1
);
7782 ok(hr
== E_NOT_VALID_STATE
, "Unexpected hr %#lx.\n", hr
);
7785 IDWriteColorGlyphRunEnumerator_Release(layers
);
7787 IDWriteColorGlyphRunEnumerator1_Release(layers1
);
7789 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace2
, (void**)&fontface2
);
7790 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7792 /* invalid palette index */
7793 layers
= (void*)0xdeadbeef;
7794 hr
= IDWriteFactory2_TranslateColorGlyphRun(factory
, 0.0f
, 0.0f
, &run
, NULL
,
7795 DWRITE_MEASURING_MODE_NATURAL
, NULL
, IDWriteFontFace2_GetColorPaletteCount(fontface2
),
7797 ok(hr
== DWRITE_E_NOCOLOR
, "Unexpected hr %#lx.\n", hr
);
7798 ok(layers
== NULL
, "got %p\n", layers
);
7801 hr
= IDWriteFactory2_TranslateColorGlyphRun(factory
, 0.0f
, 0.0f
, &run
, NULL
,
7802 DWRITE_MEASURING_MODE_NATURAL
, NULL
, IDWriteFontFace2_GetColorPaletteCount(fontface2
) - 1,
7804 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7805 IDWriteColorGlyphRunEnumerator_Release(layers
);
7807 /* color font, glyph without color info */
7808 codepoints
[0] = 'A';
7809 hr
= IDWriteFontFace_GetGlyphIndices(fontface
, codepoints
, 1, glyphs
);
7810 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7811 ok(!!*glyphs
, "Unexpected glyph.\n");
7813 layers
= (void*)0xdeadbeef;
7814 hr
= IDWriteFactory2_TranslateColorGlyphRun(factory
, 0.0f
, 0.0f
, &run
, NULL
,
7815 DWRITE_MEASURING_MODE_NATURAL
, NULL
, 0, &layers
);
7816 ok(hr
== DWRITE_E_NOCOLOR
, "Unexpected hr %#lx.\n", hr
);
7817 ok(layers
== NULL
, "got %p\n", layers
);
7819 /* one glyph with, one without */
7820 codepoints
[0] = 'A';
7821 codepoints
[1] = 0x26c4;
7823 hr
= IDWriteFontFace_GetGlyphIndices(fontface
, codepoints
, 2, glyphs
);
7824 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7829 hr
= IDWriteFactory2_TranslateColorGlyphRun(factory
, 0.0f
, 0.0f
, &run
, NULL
,
7830 DWRITE_MEASURING_MODE_NATURAL
, NULL
, 0, &layers
);
7831 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7832 ok(layers
!= NULL
, "got %p\n", layers
);
7834 hr
= IDWriteColorGlyphRunEnumerator_QueryInterface(layers
, &IID_IDWriteColorGlyphRunEnumerator1
, (void **)&layers1
);
7840 hr
= IDWriteColorGlyphRunEnumerator1_MoveNext(layers1
, &hasrun
);
7841 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7846 hr
= IDWriteColorGlyphRunEnumerator1_GetCurrentRun(layers1
, &colorrun1
);
7847 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7848 ok(!!colorrun1
->glyphRun
.fontFace
, "Unexpected fontface %p.\n", colorrun1
->glyphRun
.fontFace
);
7849 ok(colorrun1
->glyphRun
.fontEmSize
== 20.0f
, "got wrong font size %f\n", colorrun1
->glyphRun
.fontEmSize
);
7850 ok(colorrun1
->glyphRun
.glyphCount
> 0, "Unexpected glyph count %u.\n", colorrun1
->glyphRun
.glyphCount
);
7851 ok(!!colorrun1
->glyphRun
.glyphIndices
, "Unexpected indices %p.\n", colorrun1
->glyphRun
.glyphIndices
);
7852 ok(!!colorrun1
->glyphRun
.glyphAdvances
, "Unexpected advances %p.\n", colorrun1
->glyphRun
.glyphAdvances
);
7853 ok(!colorrun1
->glyphRunDescription
, "Unexpected description pointer.\n");
7855 ok(colorrun1
->glyphImageFormat
== (DWRITE_GLYPH_IMAGE_FORMATS_TRUETYPE
| DWRITE_GLYPH_IMAGE_FORMATS_COLR
) ||
7856 colorrun1
->glyphImageFormat
== DWRITE_GLYPH_IMAGE_FORMATS_TRUETYPE
, "Unexpected glyph image format %#x.\n",
7857 colorrun1
->glyphImageFormat
);
7858 ok(colorrun1
->measuringMode
== DWRITE_MEASURING_MODE_NATURAL
, "Unexpected measuring mode %d.\n",
7859 colorrun1
->measuringMode
);
7862 IDWriteColorGlyphRunEnumerator1_Release(layers1
);
7864 IDWriteColorGlyphRunEnumerator_Release(layers
);
7866 if (SUCCEEDED(IDWriteFactory2_QueryInterface(factory
, &IID_IDWriteFactory4
, (void **)&factory4
)))
7868 D2D1_POINT_2F origin
;
7870 origin
.x
= origin
.y
= 0.0f
;
7871 hr
= IDWriteFactory4_TranslateColorGlyphRun(factory4
, origin
, &run
, NULL
,
7872 DWRITE_GLYPH_IMAGE_FORMATS_NONE
, DWRITE_MEASURING_MODE_NATURAL
, NULL
, 0, &layers1
);
7873 ok(hr
== DWRITE_E_NOCOLOR
, "Unexpected hr %#lx.\n", hr
);
7875 hr
= IDWriteFactory4_TranslateColorGlyphRun(factory4
, origin
, &run
, NULL
,
7876 DWRITE_GLYPH_IMAGE_FORMATS_TRUETYPE
, DWRITE_MEASURING_MODE_NATURAL
, NULL
, 0, &layers1
);
7877 ok(hr
== DWRITE_E_NOCOLOR
, "Unexpected hr %#lx.\n", hr
);
7879 hr
= IDWriteFactory4_TranslateColorGlyphRun(factory4
, origin
, &run
, NULL
,
7880 DWRITE_GLYPH_IMAGE_FORMATS_CFF
, DWRITE_MEASURING_MODE_NATURAL
, NULL
, 0, &layers1
);
7881 ok(hr
== DWRITE_E_NOCOLOR
, "Unexpected hr %#lx.\n", hr
);
7883 hr
= IDWriteFactory4_TranslateColorGlyphRun(factory4
, origin
, &run
, NULL
,
7884 DWRITE_GLYPH_IMAGE_FORMATS_COLR
, DWRITE_MEASURING_MODE_NATURAL
, NULL
, 0, &layers1
);
7885 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7890 hr
= IDWriteColorGlyphRunEnumerator1_MoveNext(layers1
, &hasrun
);
7891 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7896 hr
= IDWriteColorGlyphRunEnumerator1_GetCurrentRun(layers1
, &colorrun1
);
7897 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7898 ok(!!colorrun1
->glyphRun
.fontFace
, "Unexpected fontface %p.\n", colorrun1
->glyphRun
.fontFace
);
7899 ok(colorrun1
->glyphRun
.fontEmSize
== 20.0f
, "got wrong font size %f\n", colorrun1
->glyphRun
.fontEmSize
);
7900 ok(colorrun1
->glyphRun
.glyphCount
> 0, "Unexpected glyph count %u.\n", colorrun1
->glyphRun
.glyphCount
);
7901 ok(!!colorrun1
->glyphRun
.glyphIndices
, "Unexpected indices %p.\n", colorrun1
->glyphRun
.glyphIndices
);
7902 ok(!!colorrun1
->glyphRun
.glyphAdvances
, "Unexpected advances %p.\n", colorrun1
->glyphRun
.glyphAdvances
);
7903 ok(!colorrun1
->glyphRunDescription
, "Unexpected description pointer.\n");
7904 ok(colorrun1
->glyphImageFormat
== DWRITE_GLYPH_IMAGE_FORMATS_COLR
||
7905 colorrun1
->glyphImageFormat
== DWRITE_GLYPH_IMAGE_FORMATS_NONE
, "Unexpected glyph image format %#x.\n",
7906 colorrun1
->glyphImageFormat
);
7907 ok(colorrun1
->measuringMode
== DWRITE_MEASURING_MODE_NATURAL
, "Unexpected measuring mode %d.\n",
7908 colorrun1
->measuringMode
);
7911 IDWriteColorGlyphRunEnumerator1_Release(layers1
);
7913 IDWriteFactory4_Release(factory4
);
7916 win_skip("IDWriteFactory4::TranslateColorGlyphRun() is not supported.\n");
7918 IDWriteFontFace2_Release(fontface2
);
7919 IDWriteFontFace_Release(fontface
);
7920 ref
= IDWriteFactory2_Release(factory
);
7921 ok(ref
== 0, "factory not released, %lu\n", ref
);
7924 static void test_HasCharacter(void)
7926 IDWriteFactory3
*factory3
;
7927 IDWriteFactory
*factory
;
7928 IDWriteFont3
*font3
;
7934 factory
= create_factory();
7936 font
= get_tahoma_instance(factory
, DWRITE_FONT_STYLE_NORMAL
);
7937 ok(font
!= NULL
, "failed to create font\n");
7939 /* Win8 is broken, QI claims to support IDWriteFont3, but in fact it does not */
7940 hr
= IDWriteFactory_QueryInterface(factory
, &IID_IDWriteFactory3
, (void**)&factory3
);
7942 hr
= IDWriteFont_QueryInterface(font
, &IID_IDWriteFont3
, (void**)&font3
);
7943 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7945 ret
= IDWriteFont3_HasCharacter(font3
, 'A');
7946 ok(ret
, "got %d\n", ret
);
7948 IDWriteFont3_Release(font3
);
7949 IDWriteFactory3_Release(factory3
);
7952 win_skip("IDWriteFont3 is not supported.\n");
7954 IDWriteFont_Release(font
);
7955 ref
= IDWriteFactory_Release(factory
);
7956 ok(ref
== 0, "factory not released, %lu\n", ref
);
7959 static BOOL
has_main_axis_values(const DWRITE_FONT_AXIS_VALUE
*values
, unsigned int count
)
7961 BOOL has_wght
= FALSE
, has_wdth
= FALSE
, has_ital
= FALSE
, has_slnt
= FALSE
;
7964 for (i
= 0; i
< count
; ++i
)
7966 if (values
[i
].axisTag
== DWRITE_FONT_AXIS_TAG_WEIGHT
)
7968 else if (values
[i
].axisTag
== DWRITE_FONT_AXIS_TAG_WIDTH
)
7970 else if (values
[i
].axisTag
== DWRITE_FONT_AXIS_TAG_ITALIC
)
7972 else if (values
[i
].axisTag
== DWRITE_FONT_AXIS_TAG_SLANT
)
7976 return has_wght
&& has_wdth
&& has_ital
&& has_slnt
;
7979 static void test_CreateFontFaceReference(void)
7981 IDWriteFontFaceReference
*ref
, *ref1
, *ref3
;
7982 IDWriteFontFace3
*fontface
, *fontface1
;
7983 DWRITE_FONT_AXIS_VALUE axis_values
[16];
7984 IDWriteFontCollection1
*collection
;
7985 IDWriteFontFile
*file
, *file1
;
7986 IDWriteFactory3
*factory
;
7987 UINT32 index
, count
, i
;
7988 IDWriteFont3
*font3
;
7994 factory
= create_factory_iid(&IID_IDWriteFactory3
);
7996 win_skip("CreateFontFaceReference() is not supported.\n");
8000 path
= create_testfontfile(test_fontfile
);
8002 hr
= IDWriteFactory3_CreateFontFaceReference(factory
, NULL
, NULL
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &ref
);
8003 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
8005 /* out of range simulation flags */
8006 hr
= IDWriteFactory3_CreateFontFaceReference(factory
, path
, NULL
, 0, ~0u, &ref
);
8007 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
8009 /* test file is not a collection, but reference could still be created with non-zero face index */
8010 hr
= IDWriteFactory3_CreateFontFaceReference(factory
, path
, NULL
, 1, DWRITE_FONT_SIMULATIONS_NONE
, &ref
);
8011 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8013 index
= IDWriteFontFaceReference_GetFontFaceIndex(ref
);
8014 ok(index
== 1, "got %u\n", index
);
8016 hr
= IDWriteFontFaceReference_GetFontFile(ref
, &file
);
8017 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8018 IDWriteFontFile_Release(file
);
8020 hr
= IDWriteFontFaceReference_CreateFontFace(ref
, &fontface
);
8022 ok(hr
== DWRITE_E_FILEFORMAT
, "Unexpected hr %#lx.\n", hr
);
8024 IDWriteFontFaceReference_Release(ref
);
8026 /* path however has to be valid */
8027 hr
= IDWriteFactory3_CreateFontFaceReference(factory
, L
"dummy", NULL
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &ref
);
8029 ok(hr
== DWRITE_E_FILENOTFOUND
, "Unexpected hr %#lx.\n", hr
);
8031 IDWriteFontFaceReference_Release(ref
);
8033 EXPECT_REF(factory
, 1);
8034 hr
= IDWriteFactory3_CreateFontFaceReference(factory
, path
, NULL
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &ref
);
8035 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8036 EXPECT_REF(factory
, 2);
8038 /* new file is returned */
8039 hr
= IDWriteFontFaceReference_GetFontFile(ref
, &file
);
8040 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8042 hr
= IDWriteFontFaceReference_GetFontFile(ref
, &file1
);
8043 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8044 ok(file
!= file1
, "got %p, previous file %p\n", file1
, file
);
8046 IDWriteFontFile_Release(file
);
8047 IDWriteFontFile_Release(file1
);
8049 /* references are not reused */
8050 hr
= IDWriteFactory3_CreateFontFaceReference(factory
, path
, NULL
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &ref1
);
8051 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8052 ok(ref1
!= ref
, "got %p, previous ref %p\n", ref1
, ref
);
8054 /* created fontfaces are cached */
8055 hr
= IDWriteFontFaceReference_CreateFontFace(ref
, &fontface
);
8056 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8058 hr
= IDWriteFontFaceReference_CreateFontFace(ref1
, &fontface1
);
8059 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8060 ok(fontface
== fontface1
, "got %p, expected %p\n", fontface1
, fontface
);
8061 IDWriteFontFace3_Release(fontface
);
8062 IDWriteFontFace3_Release(fontface1
);
8064 /* reference equality */
8065 ret
= IDWriteFontFaceReference_Equals(ref
, ref1
);
8066 ok(ret
, "got %d\n", ret
);
8067 IDWriteFontFaceReference_Release(ref1
);
8069 hr
= IDWriteFactory3_CreateFontFaceReference(factory
, path
, NULL
, 1, DWRITE_FONT_SIMULATIONS_NONE
, &ref1
);
8070 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8071 ret
= IDWriteFontFaceReference_Equals(ref
, ref1
);
8072 ok(!ret
, "got %d\n", ret
);
8073 IDWriteFontFaceReference_Release(ref1
);
8075 hr
= IDWriteFactory3_CreateFontFaceReference(factory
, path
, NULL
, 0, DWRITE_FONT_SIMULATIONS_BOLD
, &ref1
);
8076 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8077 ret
= IDWriteFontFaceReference_Equals(ref
, ref1
);
8078 ok(!ret
, "got %d\n", ret
);
8079 IDWriteFontFaceReference_Release(ref1
);
8081 IDWriteFontFaceReference_Release(ref
);
8083 /* create reference from a file */
8084 hr
= IDWriteFactory3_CreateFontFileReference(factory
, path
, NULL
, &file
);
8085 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8087 hr
= IDWriteFactory3_CreateFontFaceReference_(factory
, file
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &ref
);
8088 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8090 hr
= IDWriteFontFaceReference_GetFontFile(ref
, &file1
);
8091 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8092 ok(file
!= file1
, "got %p, previous file %p\n", file1
, file
);
8094 IDWriteFontFaceReference_Release(ref
);
8095 IDWriteFontFile_Release(file
);
8096 IDWriteFontFile_Release(file1
);
8098 /* References returned from IDWriteFont3/IDWriteFontFace3. */
8099 hr
= IDWriteFactory3_GetSystemFontCollection(factory
, FALSE
, &collection
, FALSE
);
8100 ok(hr
== S_OK
, "Failed to get system collection, hr %#lx.\n", hr
);
8102 count
= IDWriteFontCollection1_GetFontFamilyCount(collection
);
8103 for (i
= 0; i
< count
; i
++)
8105 IDWriteFontFamily1
*family
;
8106 UINT32 font_count
, j
;
8108 hr
= IDWriteFontCollection1_GetFontFamily(collection
, i
, &family
);
8109 ok(hr
== S_OK
, "Failed to get family, hr %#lx.\n", hr
);
8111 font_count
= IDWriteFontFamily1_GetFontCount(family
);
8113 for (j
= 0; j
< font_count
; j
++)
8115 IDWriteFontFaceReference1
*ref2
;
8117 hr
= IDWriteFontFamily1_GetFont(family
, j
, &font3
);
8118 ok(hr
== S_OK
, "Failed to get font, hr %#lx.\n", hr
);
8120 hr
= IDWriteFont3_GetFontFaceReference(font3
, &ref
);
8121 ok(hr
== S_OK
, "Failed to get reference object, hr %#lx.\n", hr
);
8123 hr
= IDWriteFont3_GetFontFaceReference(font3
, &ref1
);
8124 ok(hr
== S_OK
, "Failed to get reference object, hr %#lx.\n", hr
);
8125 ok(ref
!= ref1
, "Unexpected reference object %p, %p.\n", ref1
, ref
);
8127 hr
= IDWriteFont3_CreateFontFace(font3
, &fontface
);
8128 ok(hr
== S_OK
, "Failed to create a fontface, hr %#lx.\n", hr
);
8130 /* Fonts present regular properties as axis values, for non-variable fonts too.
8131 Normally it would include weight/width/slant/italic, but could also contain optical size axis. */
8132 if (SUCCEEDED(hr
= IDWriteFontFaceReference_QueryInterface(ref
, &IID_IDWriteFontFaceReference1
,
8135 UINT32 axis_count
= IDWriteFontFaceReference1_GetFontAxisValueCount(ref2
);
8137 ok(axis_count
>= 4, "Unexpected axis value count.\n");
8139 hr
= IDWriteFontFaceReference1_GetFontAxisValues(ref2
, axis_values
, ARRAY_SIZE(axis_values
));
8140 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8143 ok(has_main_axis_values(axis_values
, axis_count
), "Unexpected axis returned.\n");
8145 IDWriteFontFaceReference1_Release(ref2
);
8148 IDWriteFontFaceReference_Release(ref
);
8149 IDWriteFontFaceReference_Release(ref1
);
8151 hr
= IDWriteFontFace3_GetFontFaceReference(fontface
, &ref
);
8152 ok(hr
== S_OK
, "Failed to get a reference, hr %#lx.\n", hr
);
8153 EXPECT_REF(fontface
, 2);
8155 hr
= IDWriteFontFace3_GetFontFaceReference(fontface
, &ref1
);
8156 ok(hr
== S_OK
, "Failed to get a reference, hr %#lx.\n", hr
);
8157 ok(ref
== ref1
, "Unexpected reference %p, %p.\n", ref1
, ref
);
8158 EXPECT_REF(fontface
, 3);
8160 hr
= IDWriteFontFace3_QueryInterface(fontface
, &IID_IDWriteFontFaceReference
, (void **)&ref3
);
8161 ok(hr
== S_OK
|| broken(FAILED(hr
)), "Failed to get interface, hr %#lx.\n", hr
);
8164 ok(ref
== ref3
, "Unexpected reference %p.\n", ref3
);
8165 IDWriteFontFaceReference_Release(ref3
);
8168 hr
= IDWriteFontFaceReference_CreateFontFace(ref
, &fontface1
);
8169 ok(hr
== S_OK
, "Failed to create fontface, hr %#lx.\n", hr
);
8170 ok(fontface1
== fontface
, "Unexpected fontface %p, %p.\n", fontface1
, fontface
);
8171 IDWriteFontFace3_Release(fontface1
);
8173 IDWriteFontFaceReference_Release(ref
);
8174 IDWriteFontFaceReference_Release(ref1
);
8176 IDWriteFontFace3_Release(fontface
);
8177 IDWriteFont3_Release(font3
);
8180 IDWriteFontFamily1_Release(family
);
8182 IDWriteFontCollection1_Release(collection
);
8184 refcount
= IDWriteFactory3_Release(factory
);
8185 ok(refcount
== 0, "factory not released, %lu\n", refcount
);
8186 DELETE_FONTFILE(path
);
8189 static void get_expected_fontsig(IDWriteFont
*font
, FONTSIGNATURE
*fontsig
)
8192 IDWriteFontFace
*fontface
;
8193 const TT_OS2_V2
*tt_os2
;
8198 memset(fontsig
, 0, sizeof(*fontsig
));
8200 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
8201 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8203 hr
= IDWriteFontFace_TryGetFontTable(fontface
, MS_OS2_TAG
, (const void **)&tt_os2
, &size
, &os2_context
, &exists
);
8204 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8207 fontsig
->fsUsb
[0] = GET_BE_DWORD(tt_os2
->ulUnicodeRange1
);
8208 fontsig
->fsUsb
[1] = GET_BE_DWORD(tt_os2
->ulUnicodeRange2
);
8209 fontsig
->fsUsb
[2] = GET_BE_DWORD(tt_os2
->ulUnicodeRange3
);
8210 fontsig
->fsUsb
[3] = GET_BE_DWORD(tt_os2
->ulUnicodeRange4
);
8212 if (GET_BE_WORD(tt_os2
->version
) == 0) {
8213 fontsig
->fsCsb
[0] = 0;
8214 fontsig
->fsCsb
[1] = 0;
8217 fontsig
->fsCsb
[0] = GET_BE_DWORD(tt_os2
->ulCodePageRange1
);
8218 fontsig
->fsCsb
[1] = GET_BE_DWORD(tt_os2
->ulCodePageRange2
);
8221 IDWriteFontFace_ReleaseFontTable(fontface
, os2_context
);
8224 IDWriteFontFace_Release(fontface
);
8227 static void test_GetFontSignature(void)
8229 IDWriteFontCollection
*syscollection
;
8230 IDWriteGdiInterop1
*interop1
;
8231 IDWriteGdiInterop
*interop
;
8232 IDWriteFactory
*factory
;
8233 FONTSIGNATURE fontsig
;
8238 factory
= create_factory();
8240 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop
);
8241 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8243 hr
= IDWriteGdiInterop_QueryInterface(interop
, &IID_IDWriteGdiInterop1
, (void**)&interop1
);
8244 IDWriteGdiInterop_Release(interop
);
8246 win_skip("GetFontSignature() is not supported.\n");
8247 IDWriteGdiInterop_Release(interop
);
8248 IDWriteFactory_Release(factory
);
8251 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8253 hr
= IDWriteGdiInterop1_GetFontSignature(interop1
, NULL
, &fontsig
);
8254 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
8256 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &syscollection
, FALSE
);
8257 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8258 count
= IDWriteFontCollection_GetFontFamilyCount(syscollection
);
8260 for (i
= 0; i
< count
; i
++) {
8261 FONTSIGNATURE expected_signature
;
8262 IDWriteLocalizedStrings
*names
;
8263 IDWriteFontFamily
*family
;
8267 hr
= IDWriteFontCollection_GetFontFamily(syscollection
, i
, &family
);
8268 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8270 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STRETCH_NORMAL
,
8271 DWRITE_FONT_STYLE_NORMAL
, &font
);
8272 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8274 hr
= IDWriteFontFamily_GetFamilyNames(family
, &names
);
8275 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8277 get_enus_string(names
, nameW
, ARRAY_SIZE(nameW
));
8279 IDWriteLocalizedStrings_Release(names
);
8281 hr
= IDWriteGdiInterop1_GetFontSignature(interop1
, font
, &fontsig
);
8282 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8284 get_expected_fontsig(font
, &expected_signature
);
8286 winetest_push_context("Font %s\n", wine_dbgstr_w(nameW
));
8288 ok(fontsig
.fsUsb
[0] == expected_signature
.fsUsb
[0], "fsUsb[0] %#lx, expected %#lx.\n",
8289 fontsig
.fsUsb
[0], expected_signature
.fsUsb
[0]);
8290 ok(fontsig
.fsUsb
[1] == expected_signature
.fsUsb
[1], "fsUsb[1] %#lx, expected %#lx.\n",
8291 fontsig
.fsUsb
[1], expected_signature
.fsUsb
[1]);
8292 ok(fontsig
.fsUsb
[2] == expected_signature
.fsUsb
[2], "fsUsb[2] %#lx, expected %#lx.\n",
8293 fontsig
.fsUsb
[2], expected_signature
.fsUsb
[2]);
8294 ok(fontsig
.fsUsb
[3] == expected_signature
.fsUsb
[3], "fsUsb[3] %#lx, expected %#lx.\n",
8295 fontsig
.fsUsb
[3], expected_signature
.fsUsb
[3]);
8297 ok(fontsig
.fsCsb
[0] == expected_signature
.fsCsb
[0], "fsCsb[0] %#lx, expected %#lx.\n",
8298 fontsig
.fsCsb
[0], expected_signature
.fsCsb
[0]);
8299 ok(fontsig
.fsCsb
[1] == expected_signature
.fsCsb
[1], "fsCsb[1] %#lx, expected %#lx.\n",
8300 fontsig
.fsCsb
[1], expected_signature
.fsCsb
[1]);
8302 winetest_pop_context();
8304 IDWriteFont_Release(font
);
8305 IDWriteFontFamily_Release(family
);
8308 IDWriteGdiInterop1_Release(interop1
);
8309 IDWriteFontCollection_Release(syscollection
);
8310 ref
= IDWriteFactory_Release(factory
);
8311 ok(ref
== 0, "factory not released, %lu\n", ref
);
8314 static void test_font_properties(void)
8316 IDWriteFontFace3
*fontface3
;
8317 IDWriteFontFace
*fontface
;
8318 IDWriteFactory
*factory
;
8319 DWRITE_FONT_STYLE style
;
8324 factory
= create_factory();
8326 /* this creates simulated font */
8327 font
= get_tahoma_instance(factory
, DWRITE_FONT_STYLE_ITALIC
);
8329 style
= IDWriteFont_GetStyle(font
);
8330 ok(style
== DWRITE_FONT_STYLE_OBLIQUE
, "got %u\n", style
);
8332 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
8333 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8335 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace3
, (void**)&fontface3
);
8336 IDWriteFontFace_Release(fontface
);
8338 style
= IDWriteFontFace3_GetStyle(fontface3
);
8339 ok(style
== DWRITE_FONT_STYLE_OBLIQUE
, "got %u\n", style
);
8341 IDWriteFontFace3_Release(fontface3
);
8344 IDWriteFont_Release(font
);
8345 ref
= IDWriteFactory_Release(factory
);
8346 ok(ref
== 0, "factory not released, %lu\n", ref
);
8349 static BOOL
has_vertical_glyph_variants(IDWriteFontFace1
*fontface
)
8351 const OT_FeatureList
*featurelist
;
8352 const OT_LookupList
*lookup_list
;
8353 BOOL exists
= FALSE
, ret
= FALSE
;
8354 const GSUB_Header
*header
;
8361 hr
= IDWriteFontFace1_TryGetFontTable(fontface
, MS_GSUB_TAG
, &data
, &size
, &context
, &exists
);
8362 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8368 featurelist
= (OT_FeatureList
*)((BYTE
*)header
+ GET_BE_WORD(header
->FeatureList
));
8369 lookup_list
= (const OT_LookupList
*)((BYTE
*)header
+ GET_BE_WORD(header
->LookupList
));
8371 for (i
= 0; i
< GET_BE_WORD(featurelist
->FeatureCount
); i
++) {
8372 if (*(UINT32
*)featurelist
->FeatureRecord
[i
].FeatureTag
== DWRITE_FONT_FEATURE_TAG_VERTICAL_WRITING
) {
8373 const OT_Feature
*feature
= (const OT_Feature
*)((BYTE
*)featurelist
+ GET_BE_WORD(featurelist
->FeatureRecord
[i
].Feature
));
8374 UINT16 lookup_count
= GET_BE_WORD(feature
->LookupCount
), i
, index
, count
, type
;
8375 const GSUB_SingleSubstFormat2
*subst2
;
8376 const OT_LookupTable
*lookup_table
;
8379 if (lookup_count
== 0)
8382 for (i
= 0; i
< lookup_count
; i
++) {
8383 /* check if lookup is empty */
8384 index
= GET_BE_WORD(feature
->LookupListIndex
[i
]);
8385 lookup_table
= (const OT_LookupTable
*)((BYTE
*)lookup_list
+ GET_BE_WORD(lookup_list
->Lookup
[index
]));
8387 type
= GET_BE_WORD(lookup_table
->LookupType
);
8388 ok(type
== 1 || type
== 7, "got unexpected lookup type %u\n", type
);
8390 count
= GET_BE_WORD(lookup_table
->SubTableCount
);
8394 ok(count
> 0, "got unexpected subtable count %u\n", count
);
8396 offset
= GET_BE_WORD(lookup_table
->SubTable
[0]);
8398 const GSUB_ExtensionPosFormat1
*ext
= (const GSUB_ExtensionPosFormat1
*)((const BYTE
*)lookup_table
+ offset
);
8399 if (GET_BE_WORD(ext
->SubstFormat
) == 1)
8400 offset
+= GET_BE_DWORD(ext
->ExtensionOffset
);
8402 ok(0, "Unhandled Extension Substitution Format %u\n", GET_BE_WORD(ext
->SubstFormat
));
8405 subst2
= (const GSUB_SingleSubstFormat2
*)((BYTE
*)lookup_table
+ offset
);
8406 index
= GET_BE_WORD(subst2
->SubstFormat
);
8409 else if (index
== 2) {
8410 /* SimSun-ExtB has 0 glyph count for this substitution */
8411 if (GET_BE_WORD(subst2
->GlyphCount
) > 0)
8415 ok(0, "unknown Single Substitution Format, %u\n", index
);
8423 IDWriteFontFace1_ReleaseFontTable(fontface
, context
);
8428 static void test_HasVerticalGlyphVariants(void)
8430 IDWriteFontCollection
*syscollection
;
8431 IDWriteFontFace1
*fontface1
;
8432 IDWriteFontFace
*fontface
;
8433 IDWriteFactory
*factory
;
8438 factory
= create_factory();
8439 fontface
= create_fontface(factory
);
8441 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void**)&fontface1
);
8442 IDWriteFontFace_Release(fontface
);
8444 win_skip("HasVerticalGlyphVariants() is not supported.\n");
8445 IDWriteFactory_Release(factory
);
8448 IDWriteFontFace1_Release(fontface1
);
8450 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &syscollection
, FALSE
);
8451 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8452 count
= IDWriteFontCollection_GetFontFamilyCount(syscollection
);
8454 for (i
= 0; i
< count
; i
++) {
8455 IDWriteLocalizedStrings
*names
;
8456 BOOL expected_vert
, has_vert
;
8457 IDWriteFontFamily
*family
;
8461 hr
= IDWriteFontCollection_GetFontFamily(syscollection
, i
, &family
);
8462 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8464 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STRETCH_NORMAL
,
8465 DWRITE_FONT_STYLE_NORMAL
, &font
);
8466 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8468 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
8469 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8471 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void**)&fontface1
);
8472 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8474 hr
= IDWriteFontFamily_GetFamilyNames(family
, &names
);
8475 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8477 get_enus_string(names
, nameW
, ARRAY_SIZE(nameW
));
8479 expected_vert
= has_vertical_glyph_variants(fontface1
);
8480 has_vert
= IDWriteFontFace1_HasVerticalGlyphVariants(fontface1
);
8482 ok(expected_vert
== has_vert
, "%s: expected vertical feature %d, got %d\n",
8483 wine_dbgstr_w(nameW
), expected_vert
, has_vert
);
8485 IDWriteLocalizedStrings_Release(names
);
8486 IDWriteFont_Release(font
);
8488 IDWriteFontFace1_Release(fontface1
);
8489 IDWriteFontFace_Release(fontface
);
8490 IDWriteFontFamily_Release(family
);
8493 IDWriteFontCollection_Release(syscollection
);
8494 ref
= IDWriteFactory_Release(factory
);
8495 ok(ref
== 0, "factory not released, %lu\n", ref
);
8498 static void test_HasKerningPairs(void)
8500 IDWriteFontCollection
*syscollection
;
8501 IDWriteFontFace1
*fontface1
;
8502 IDWriteFontFace
*fontface
;
8503 IDWriteFactory
*factory
;
8508 factory
= create_factory();
8509 fontface
= create_fontface(factory
);
8511 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void**)&fontface1
);
8512 IDWriteFontFace_Release(fontface
);
8514 win_skip("HasKerningPairs() is not supported.\n");
8515 IDWriteFactory_Release(factory
);
8518 IDWriteFontFace1_Release(fontface1
);
8520 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &syscollection
, FALSE
);
8521 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8522 count
= IDWriteFontCollection_GetFontFamilyCount(syscollection
);
8524 for (i
= 0; i
< count
; i
++) {
8525 IDWriteLocalizedStrings
*names
;
8526 BOOL exists
, has_kerningpairs
;
8527 IDWriteFontFamily
*family
;
8534 hr
= IDWriteFontCollection_GetFontFamily(syscollection
, i
, &family
);
8535 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8537 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STRETCH_NORMAL
,
8538 DWRITE_FONT_STYLE_NORMAL
, &font
);
8539 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8541 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
8542 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8544 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void **)&fontface1
);
8545 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8547 hr
= IDWriteFontFamily_GetFamilyNames(family
, &names
);
8548 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8550 get_enus_string(names
, nameW
, ARRAY_SIZE(nameW
));
8553 hr
= IDWriteFontFace1_TryGetFontTable(fontface1
, MS_KERN_TAG
, &data
, &size
, &context
, &exists
);
8554 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8555 IDWriteFontFace1_ReleaseFontTable(fontface1
, context
);
8557 has_kerningpairs
= IDWriteFontFace1_HasKerningPairs(fontface1
);
8559 ok(!has_kerningpairs
, "%s: expected %d, got %d\n", wine_dbgstr_w(nameW
), exists
, has_kerningpairs
);
8561 IDWriteLocalizedStrings_Release(names
);
8562 IDWriteFont_Release(font
);
8564 IDWriteFontFace1_Release(fontface1
);
8565 IDWriteFontFace_Release(fontface
);
8566 IDWriteFontFamily_Release(family
);
8569 IDWriteFontCollection_Release(syscollection
);
8570 ref
= IDWriteFactory_Release(factory
);
8571 ok(ref
== 0, "factory not released, %lu\n", ref
);
8574 static float get_scaled_metric(const DWRITE_GLYPH_RUN
*run
, float metric
, const DWRITE_FONT_METRICS
*m
)
8576 return run
->fontEmSize
* metric
/ m
->designUnitsPerEm
;
8579 static void get_expected_glyph_origins(D2D1_POINT_2F baseline_origin
, const DWRITE_GLYPH_RUN
*run
,
8580 D2D1_POINT_2F
*origins
)
8582 DWRITE_GLYPH_METRICS glyph_metrics
[2];
8583 DWRITE_FONT_METRICS metrics
;
8587 IDWriteFontFace_GetMetrics(run
->fontFace
, &metrics
);
8589 hr
= IDWriteFontFace_GetDesignGlyphMetrics(run
->fontFace
, run
->glyphIndices
, run
->glyphCount
, glyph_metrics
,
8591 ok(hr
== S_OK
, "Failed to get glyph metrics, hr %#lx.\n", hr
);
8593 if (run
->bidiLevel
& 1)
8597 advance
= get_scaled_metric(run
, run
->isSideways
? glyph_metrics
[0].advanceHeight
:
8598 glyph_metrics
[0].advanceWidth
, &metrics
);
8600 baseline_origin
.x
-= advance
;
8602 for (i
= 0; i
< run
->glyphCount
; ++i
)
8604 origins
[i
] = baseline_origin
;
8606 if (run
->isSideways
)
8608 origins
[i
].x
+= get_scaled_metric(run
, glyph_metrics
[i
].verticalOriginY
, &metrics
);
8609 origins
[i
].y
+= metrics
.designUnitsPerEm
/ (4.0f
* run
->fontEmSize
);
8612 origins
[i
].x
-= run
->glyphOffsets
[i
].advanceOffset
;
8613 origins
[i
].y
-= run
->glyphOffsets
[i
].ascenderOffset
;
8615 baseline_origin
.x
-= run
->glyphAdvances
[i
];
8620 for (i
= 0; i
< run
->glyphCount
; ++i
)
8622 origins
[i
] = baseline_origin
;
8624 if (run
->isSideways
)
8626 origins
[i
].x
+= get_scaled_metric(run
, glyph_metrics
[i
].verticalOriginY
, &metrics
);
8627 origins
[i
].y
+= metrics
.designUnitsPerEm
/ (4.0f
* run
->fontEmSize
);
8630 origins
[i
].x
+= run
->glyphOffsets
[i
].advanceOffset
;
8631 origins
[i
].y
-= run
->glyphOffsets
[i
].ascenderOffset
;
8633 baseline_origin
.x
+= run
->glyphAdvances
[i
];
8638 static void test_ComputeGlyphOrigins(void)
8640 static const struct origins_test
8642 D2D1_POINT_2F baseline_origin
;
8644 DWRITE_GLYPH_OFFSET offsets
[2];
8645 unsigned int bidi_level
;
8646 unsigned int sideways
;
8650 { { 123.0f
, 321.0f
}, { 10.0f
, 20.0f
}, { { 0 } } },
8651 { { 123.0f
, 321.0f
}, { 10.0f
, 20.0f
}, { { 0.3f
, 0.5f
}, { -0.1f
, 0.9f
} } },
8652 { { 123.0f
, 321.0f
}, { 10.0f
, 20.0f
}, { { 0 } }, 1 },
8654 { { 123.0f
, 321.0f
}, { 10.0f
, 20.0f
}, { { 0 } }, 0, 1 },
8655 { { 123.0f
, 321.0f
}, { 10.0f
, 20.0f
}, { { 0.3f
, 0.5f
}, { -0.1f
, 0.9f
} }, 0, 1 },
8656 { { 123.0f
, 321.0f
}, { 10.0f
, 20.0f
}, { { 0 } }, 1, 1 },
8657 { { 123.0f
, 321.0f
}, { 10.0f
, 20.0f
}, { { 0.3f
, 0.5f
}, { -0.1f
, 0.9f
} }, 1, 1 },
8659 IDWriteFactory4
*factory
;
8660 DWRITE_GLYPH_RUN run
;
8662 D2D1_POINT_2F origins
[2], expected_origins
[2];
8663 D2D1_POINT_2F baseline_origin
;
8664 UINT16 glyphs
[2] = { 0 };
8669 IDWriteFontFace
*fontface
;
8671 factory
= create_factory_iid(&IID_IDWriteFactory4
);
8673 win_skip("ComputeGlyphOrigins() is not supported.\n");
8677 fontface
= create_fontface((IDWriteFactory
*)factory
);
8679 for (i
= 0; i
< ARRAY_SIZE(origins_tests
); ++i
)
8681 run
.fontFace
= fontface
;
8682 run
.fontEmSize
= 32.0f
;
8684 run
.glyphIndices
= glyphs
;
8685 run
.glyphAdvances
= origins_tests
[i
].advances
;
8686 run
.glyphOffsets
= origins_tests
[i
].offsets
;
8687 run
.isSideways
= !!origins_tests
[i
].sideways
;
8688 run
.bidiLevel
= origins_tests
[i
].bidi_level
;
8690 get_expected_glyph_origins(origins_tests
[i
].baseline_origin
, &run
, expected_origins
);
8692 memset(origins
, 0, sizeof(origins
));
8693 hr
= IDWriteFactory4_ComputeGlyphOrigins_(factory
, &run
, origins_tests
[i
].baseline_origin
, origins
);
8694 ok(hr
== S_OK
, "%u: failed to compute glyph origins, hr %#lx.\n", i
, hr
);
8695 for (j
= 0; j
< run
.glyphCount
; ++j
)
8697 todo_wine_if(run
.isSideways
)
8698 ok(!memcmp(&origins
[j
], &expected_origins
[j
], sizeof(origins
[j
])),
8699 "%u: unexpected origin[%u] (%f, %f) - (%f, %f).\n", i
, j
, origins
[j
].x
, origins
[j
].y
,
8700 expected_origins
[j
].x
, expected_origins
[j
].y
);
8704 IDWriteFontFace_Release(fontface
);
8706 advances
[0] = 10.0f
;
8707 advances
[1] = 20.0f
;
8709 run
.fontFace
= NULL
;
8710 run
.fontEmSize
= 16.0f
;
8712 run
.glyphIndices
= glyphs
;
8713 run
.glyphAdvances
= advances
;
8714 run
.glyphOffsets
= NULL
;
8715 run
.isSideways
= FALSE
;
8718 baseline_origin
.x
= 123.0f
;
8719 baseline_origin
.y
= 321.0f
;
8721 memset(origins
, 0, sizeof(origins
));
8722 hr
= IDWriteFactory4_ComputeGlyphOrigins_(factory
, &run
, baseline_origin
, origins
);
8723 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8724 ok(origins
[0].x
== 123.0f
&& origins
[0].y
== 321.0f
, "origins[0] %f,%f\n", origins
[0].x
, origins
[0].y
);
8725 ok(origins
[1].x
== 133.0f
&& origins
[1].y
== 321.0f
, "origins[1] %f,%f\n", origins
[1].x
, origins
[1].y
);
8727 memset(origins
, 0, sizeof(origins
));
8728 hr
= IDWriteFactory4_ComputeGlyphOrigins(factory
, &run
, DWRITE_MEASURING_MODE_NATURAL
, baseline_origin
,
8730 ok(origins
[0].x
== 123.0f
&& origins
[0].y
== 321.0f
, "origins[0] %f,%f\n", origins
[0].x
, origins
[0].y
);
8731 ok(origins
[1].x
== 133.0f
&& origins
[1].y
== 321.0f
, "origins[1] %f,%f\n", origins
[1].x
, origins
[1].y
);
8733 /* transform is not applied to returned origins */
8741 memset(origins
, 0, sizeof(origins
));
8742 hr
= IDWriteFactory4_ComputeGlyphOrigins(factory
, &run
, DWRITE_MEASURING_MODE_NATURAL
, baseline_origin
,
8744 ok(origins
[0].x
== 123.0f
&& origins
[0].y
== 321.0f
, "origins[0] %f,%f\n", origins
[0].x
, origins
[0].y
);
8745 ok(origins
[1].x
== 133.0f
&& origins
[1].y
== 321.0f
, "origins[1] %f,%f\n", origins
[1].x
, origins
[1].y
);
8747 ref
= IDWriteFactory4_Release(factory
);
8748 ok(ref
== 0, "factory not released, %lu\n", ref
);
8751 static void test_object_lifetime(void)
8753 IDWriteFontCollection
*collection
, *collection2
;
8754 IDWriteFontList
*fontlist
, *fontlist2
;
8755 IDWriteGdiInterop
*interop
, *interop2
;
8756 IDWriteFontFamily
*family
, *family2
;
8757 IDWriteFontFace
*fontface
;
8758 IDWriteFont
*font
, *font2
;
8759 IDWriteFactory
*factory
;
8763 factory
= create_factory();
8764 EXPECT_REF(factory
, 1);
8766 /* system collection takes factory reference */
8767 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &collection
, FALSE
);
8768 ok(hr
== S_OK
, "got %#lx\n", hr
);
8770 EXPECT_REF(collection
, 1);
8771 EXPECT_REF(factory
, 2);
8773 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &collection2
, FALSE
);
8774 ok(hr
== S_OK
, "got %#lx\n", hr
);
8775 ok(collection2
== collection
, "expected same collection\n");
8777 EXPECT_REF(collection
, 2);
8778 EXPECT_REF(factory
, 2);
8780 IDWriteFontCollection_Release(collection2
);
8782 IDWriteFontCollection_AddRef(collection
);
8783 EXPECT_REF(collection
, 2);
8784 EXPECT_REF(factory
, 2);
8785 IDWriteFontCollection_Release(collection
);
8787 EXPECT_REF(collection
, 1);
8789 /* family takes collection reference */
8790 hr
= IDWriteFontCollection_GetFontFamily(collection
, 0, &family
);
8791 ok(hr
== S_OK
, "got %#lx\n", hr
);
8793 EXPECT_REF(family
, 1);
8794 EXPECT_REF(collection
, 2);
8795 EXPECT_REF(factory
, 2);
8797 hr
= IDWriteFontCollection_GetFontFamily(collection
, 0, &family2
);
8798 ok(hr
== S_OK
, "got %#lx\n", hr
);
8800 EXPECT_REF(family2
, 1);
8801 EXPECT_REF(collection
, 3);
8802 EXPECT_REF(factory
, 2);
8804 IDWriteFontFamily_Release(family2
);
8806 EXPECT_REF(family
, 1);
8807 EXPECT_REF(collection
, 2);
8808 EXPECT_REF(factory
, 2);
8810 /* font takes family reference */
8811 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
,
8812 DWRITE_FONT_STRETCH_NORMAL
, DWRITE_FONT_STYLE_NORMAL
, &font
);
8813 ok(hr
== S_OK
, "got %#lx\n", hr
);
8815 EXPECT_REF(family
, 2);
8816 EXPECT_REF(collection
, 2);
8817 EXPECT_REF(factory
, 2);
8819 hr
= IDWriteFont_GetFontFamily(font
, &family2
);
8820 ok(hr
== S_OK
, "got %#lx\n", hr
);
8821 ok(family2
== family
, "unexpected family pointer\n");
8822 IDWriteFontFamily_Release(family2
);
8824 EXPECT_REF(font
, 1);
8825 EXPECT_REF(factory
, 2);
8827 /* Fontface takes factory reference and nothing else. */
8828 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
8829 ok(hr
== S_OK
, "got %#lx\n", hr
);
8831 EXPECT_REF(font
, 1);
8832 EXPECT_REF_BROKEN(fontface
, 1, 2);
8833 EXPECT_REF(family
, 2);
8834 EXPECT_REF(collection
, 2);
8835 EXPECT_REF_BROKEN(factory
, 3, 2);
8837 /* get font from fontface */
8838 hr
= IDWriteFontCollection_GetFontFromFontFace(collection
, fontface
, &font2
);
8839 ok(hr
== S_OK
, "got %#lx\n", hr
);
8841 EXPECT_REF(font
, 1);
8842 EXPECT_REF(font2
, 1);
8843 EXPECT_REF_BROKEN(fontface
, 1, 2);
8844 EXPECT_REF(family
, 2);
8845 EXPECT_REF(collection
, 3);
8846 EXPECT_REF_BROKEN(factory
, 3, 2);
8848 IDWriteFont_Release(font2
);
8849 IDWriteFontFace_Release(fontface
);
8851 EXPECT_REF(font
, 1);
8852 EXPECT_REF(family
, 2);
8853 EXPECT_REF(collection
, 2);
8854 EXPECT_REF(factory
, 2);
8856 IDWriteFont_Release(font
);
8858 EXPECT_REF(family
, 1);
8859 EXPECT_REF(collection
, 2);
8860 EXPECT_REF(factory
, 2);
8862 /* Matching fonts list takes family reference. */
8863 hr
= IDWriteFontFamily_GetMatchingFonts(family
, DWRITE_FONT_WEIGHT_NORMAL
,
8864 DWRITE_FONT_STRETCH_NORMAL
, DWRITE_FONT_STYLE_NORMAL
, &fontlist
);
8865 ok(hr
== S_OK
, "got %#lx\n", hr
);
8867 EXPECT_REF(family
, 2);
8868 EXPECT_REF(collection
, 2);
8869 EXPECT_REF(factory
, 2);
8871 hr
= IDWriteFontFamily_GetMatchingFonts(family
, DWRITE_FONT_WEIGHT_NORMAL
,
8872 DWRITE_FONT_STRETCH_NORMAL
, DWRITE_FONT_STYLE_NORMAL
, &fontlist2
);
8873 ok(hr
== S_OK
, "got %#lx\n", hr
);
8874 ok(fontlist2
!= fontlist
, "unexpected font list\n");
8875 IDWriteFontList_Release(fontlist2
);
8877 IDWriteFontList_Release(fontlist
);
8879 IDWriteFontFamily_Release(family
);
8880 EXPECT_REF(collection
, 1);
8882 EXPECT_REF(factory
, 2);
8883 ref
= IDWriteFontCollection_Release(collection
);
8884 ok(ref
== 0, "collection not released, %lu\n", ref
);
8885 EXPECT_REF(factory
, 1);
8887 /* GDI interop object takes factory reference */
8888 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop
);
8889 ok(hr
== S_OK
, "got %#lx\n", hr
);
8890 EXPECT_REF(interop
, 1);
8891 EXPECT_REF(factory
, 2);
8893 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop2
);
8894 ok(hr
== S_OK
, "got %#lx\n", hr
);
8895 ok(interop
== interop2
, "got unexpected interop pointer\n");
8897 EXPECT_REF(interop
, 2);
8898 EXPECT_REF(factory
, 2);
8900 IDWriteGdiInterop_Release(interop2
);
8901 ref
= IDWriteGdiInterop_Release(interop
);
8902 ok(ref
== 0, "interop not released, %lu\n", ref
);
8904 ref
= IDWriteFactory_Release(factory
);
8905 ok(ref
== 0, "factory not released, %lu\n", ref
);
8908 struct testowner_object
8910 IUnknown IUnknown_iface
;
8914 static inline struct testowner_object
*impl_from_IUnknown(IUnknown
*iface
)
8916 return CONTAINING_RECORD(iface
, struct testowner_object
, IUnknown_iface
);
8919 static HRESULT WINAPI
testowner_QueryInterface(IUnknown
*iface
, REFIID riid
, void **obj
)
8921 if (IsEqualIID(riid
, &IID_IUnknown
)) {
8923 IUnknown_AddRef(iface
);
8928 return E_NOINTERFACE
;
8931 static ULONG WINAPI
testowner_AddRef(IUnknown
*iface
)
8933 struct testowner_object
*object
= impl_from_IUnknown(iface
);
8934 return InterlockedIncrement(&object
->ref
);
8937 static ULONG WINAPI
testowner_Release(IUnknown
*iface
)
8939 struct testowner_object
*object
= impl_from_IUnknown(iface
);
8940 return InterlockedDecrement(&object
->ref
);
8943 static const IUnknownVtbl testownervtbl
= {
8944 testowner_QueryInterface
,
8949 static void testowner_init(struct testowner_object
*object
)
8951 object
->IUnknown_iface
.lpVtbl
= &testownervtbl
;
8955 static void test_inmemory_file_loader(void)
8957 IDWriteFontFileStream
*stream
, *stream2
, *stream3
;
8958 IDWriteInMemoryFontFileLoader
*loader
, *loader2
;
8959 IDWriteInMemoryFontFileLoader
*inmemory
;
8960 IDWriteFontFileLoader
*fileloader
;
8961 struct testowner_object ownerobject
;
8962 const void *key
, *data
, *frag_start
;
8963 UINT64 file_size
, size
, writetime
;
8964 IDWriteFontFile
*file
, *file2
;
8965 IDWriteFontFace
*fontface
;
8966 void *context
, *context2
;
8967 IDWriteFactory5
*factory
;
8968 UINT32 count
, key_size
;
8973 factory
= create_factory_iid(&IID_IDWriteFactory5
);
8975 win_skip("CreateInMemoryFontFileLoader() is not supported\n");
8979 EXPECT_REF(factory
, 1);
8980 hr
= IDWriteFactory5_CreateInMemoryFontFileLoader(factory
, &loader
);
8981 ok(hr
== S_OK
, "got %#lx\n", hr
);
8982 EXPECT_REF(factory
, 1);
8984 testowner_init(&ownerobject
);
8985 fontface
= create_fontface((IDWriteFactory
*)factory
);
8987 hr
= IDWriteFactory5_CreateInMemoryFontFileLoader(factory
, &loader2
);
8988 ok(hr
== S_OK
, "got %#lx\n", hr
);
8989 ok(loader
!= loader2
, "unexpected pointer\n");
8990 IDWriteInMemoryFontFileLoader_Release(loader2
);
8994 count
= IDWriteInMemoryFontFileLoader_GetFileCount(inmemory
);
8995 ok(!count
, "Unexpected file count %u.\n", count
);
8997 /* Use whole font blob to construct in-memory file. */
8999 hr
= IDWriteFontFace_GetFiles(fontface
, &count
, &file
);
9000 ok(hr
== S_OK
, "got %#lx\n", hr
);
9002 hr
= IDWriteFontFile_GetLoader(file
, &fileloader
);
9003 ok(hr
== S_OK
, "got %#lx\n", hr
);
9005 hr
= IDWriteFontFile_GetReferenceKey(file
, &key
, &key_size
);
9006 ok(hr
== S_OK
, "got %#lx\n", hr
);
9008 hr
= IDWriteFontFileLoader_CreateStreamFromKey(fileloader
, key
, key_size
, &stream
);
9009 ok(hr
== S_OK
, "got %#lx\n", hr
);
9010 IDWriteFontFileLoader_Release(fileloader
);
9011 IDWriteFontFile_Release(file
);
9013 hr
= IDWriteFontFileStream_GetFileSize(stream
, &file_size
);
9014 ok(hr
== S_OK
, "got %#lx\n", hr
);
9016 hr
= IDWriteFontFileStream_ReadFileFragment(stream
, &data
, 0, file_size
, &context
);
9017 ok(hr
== S_OK
, "got %#lx\n", hr
);
9019 /* Not registered yet. */
9020 hr
= IDWriteInMemoryFontFileLoader_CreateInMemoryFontFileReference(inmemory
, (IDWriteFactory
*)factory
, data
,
9021 file_size
, NULL
, &file
);
9022 ok(hr
== E_INVALIDARG
, "got %#lx\n", hr
);
9024 count
= IDWriteInMemoryFontFileLoader_GetFileCount(inmemory
);
9025 ok(count
== 1, "Unexpected file count %u.\n", count
);
9027 hr
= IDWriteFactory5_RegisterFontFileLoader(factory
, (IDWriteFontFileLoader
*)inmemory
);
9028 ok(hr
== S_OK
, "got %#lx\n", hr
);
9029 EXPECT_REF(inmemory
, 2);
9031 EXPECT_REF(&ownerobject
.IUnknown_iface
, 1);
9032 hr
= IDWriteInMemoryFontFileLoader_CreateInMemoryFontFileReference(inmemory
, (IDWriteFactory
*)factory
, data
,
9033 file_size
, &ownerobject
.IUnknown_iface
, &file
);
9034 ok(hr
== S_OK
, "got %#lx\n", hr
);
9035 EXPECT_REF(&ownerobject
.IUnknown_iface
, 2);
9036 EXPECT_REF(inmemory
, 3);
9038 count
= IDWriteInMemoryFontFileLoader_GetFileCount(inmemory
);
9039 ok(count
== 2, "Unexpected file count %u.\n", count
);
9041 hr
= IDWriteInMemoryFontFileLoader_CreateInMemoryFontFileReference(inmemory
, (IDWriteFactory
*)factory
, data
,
9042 file_size
, &ownerobject
.IUnknown_iface
, &file2
);
9043 ok(hr
== S_OK
, "got %#lx\n", hr
);
9044 ok(file2
!= file
, "got unexpected file\n");
9045 EXPECT_REF(&ownerobject
.IUnknown_iface
, 3);
9046 EXPECT_REF(inmemory
, 4);
9048 count
= IDWriteInMemoryFontFileLoader_GetFileCount(inmemory
);
9049 ok(count
== 3, "Unexpected file count %u.\n", count
);
9051 /* Check in-memory reference key format. */
9052 hr
= IDWriteFontFile_GetReferenceKey(file
, &key
, &key_size
);
9053 ok(hr
== S_OK
, "got %#lx\n", hr
);
9055 ok(key
&& *(DWORD
*)key
== 1, "got wrong ref key\n");
9056 ok(key_size
== 4, "ref key size %u\n", key_size
);
9058 hr
= IDWriteFontFile_GetReferenceKey(file2
, &key
, &key_size
);
9059 ok(hr
== S_OK
, "got %#lx\n", hr
);
9061 ok(key
&& *(DWORD
*)key
== 2, "got wrong ref key\n");
9062 ok(key_size
== 4, "ref key size %u\n", key_size
);
9064 EXPECT_REF(inmemory
, 4);
9065 hr
= IDWriteInMemoryFontFileLoader_CreateStreamFromKey(inmemory
, key
, key_size
, &stream2
);
9066 ok(hr
== S_OK
, "Failed to create a stream, hr %#lx.\n", hr
);
9067 EXPECT_REF(stream2
, 1);
9068 EXPECT_REF(inmemory
, 4);
9070 hr
= IDWriteInMemoryFontFileLoader_CreateStreamFromKey(inmemory
, key
, key_size
, &stream3
);
9071 ok(hr
== S_OK
, "Failed to create a stream, hr %#lx.\n", hr
);
9073 ok(stream2
!= stream3
, "Unexpected stream.\n");
9075 IDWriteFontFileStream_Release(stream2
);
9076 IDWriteFontFileStream_Release(stream3
);
9078 /* Release file at index 1, create new one to see if index is reused. */
9079 EXPECT_REF(&ownerobject
.IUnknown_iface
, 3);
9080 ref
= IDWriteFontFile_Release(file
);
9081 ok(ref
== 0, "File object not released, %lu.\n", ref
);
9082 EXPECT_REF(&ownerobject
.IUnknown_iface
, 3);
9084 count
= IDWriteInMemoryFontFileLoader_GetFileCount(inmemory
);
9085 ok(count
== 3, "Unexpected file count %u.\n", count
);
9087 EXPECT_REF(&ownerobject
.IUnknown_iface
, 3);
9088 ref
= IDWriteFontFile_Release(file2
);
9089 ok(ref
== 0, "File object not released, %lu.\n", ref
);
9090 EXPECT_REF(&ownerobject
.IUnknown_iface
, 3);
9092 count
= IDWriteInMemoryFontFileLoader_GetFileCount(inmemory
);
9093 ok(count
== 3, "Unexpected file count %u.\n", count
);
9095 hr
= IDWriteFactory5_UnregisterFontFileLoader(factory
, (IDWriteFontFileLoader
*)inmemory
);
9096 ok(hr
== S_OK
, "got %#lx\n", hr
);
9097 EXPECT_REF(&ownerobject
.IUnknown_iface
, 3);
9099 EXPECT_REF(&ownerobject
.IUnknown_iface
, 3);
9100 ref
= IDWriteInMemoryFontFileLoader_Release(inmemory
);
9101 ok(ref
== 0, "loader not released, %lu.\n", ref
);
9102 EXPECT_REF(&ownerobject
.IUnknown_iface
, 1);
9104 /* Test reference key for first added file. */
9105 hr
= IDWriteFactory5_CreateInMemoryFontFileLoader(factory
, &loader
);
9106 ok(hr
== S_OK
, "Failed to create loader, hr %#lx.\n", hr
);
9110 hr
= IDWriteFactory5_RegisterFontFileLoader(factory
, (IDWriteFontFileLoader
*)inmemory
);
9111 ok(hr
== S_OK
, "Failed to register loader, hr %#lx.\n", hr
);
9114 hr
= IDWriteInMemoryFontFileLoader_CreateStreamFromKey(inmemory
, &ref_key
, sizeof(ref_key
), &stream2
);
9115 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
9117 /* With owner object. */
9118 hr
= IDWriteInMemoryFontFileLoader_CreateInMemoryFontFileReference(inmemory
, (IDWriteFactory
*)factory
, data
,
9119 file_size
, &ownerobject
.IUnknown_iface
, &file
);
9120 ok(hr
== S_OK
, "Failed to create in-memory file reference, hr %#lx.\n", hr
);
9123 hr
= IDWriteInMemoryFontFileLoader_CreateStreamFromKey(inmemory
, &ref_key
, sizeof(ref_key
), &stream2
);
9124 ok(hr
== S_OK
, "Failed to create a stream, hr %#lx.\n", hr
);
9126 context2
= (void *)0xdeadbeef;
9127 hr
= IDWriteFontFileStream_ReadFileFragment(stream2
, &frag_start
, 0, file_size
, &context2
);
9128 ok(hr
== S_OK
, "Failed to read a fragment, hr %#lx.\n", hr
);
9129 ok(context2
== NULL
, "Unexpected context %p.\n", context2
);
9130 ok(frag_start
== data
, "Unexpected fragment pointer %p.\n", frag_start
);
9132 hr
= IDWriteFontFileStream_GetFileSize(stream2
, &size
);
9133 ok(hr
== S_OK
, "Failed to get file size, hr %#lx.\n", hr
);
9134 ok(size
== file_size
, "Unexpected file size.\n");
9136 IDWriteFontFileStream_ReleaseFileFragment(stream2
, context2
);
9139 hr
= IDWriteFontFileStream_GetLastWriteTime(stream2
, &writetime
);
9140 ok(hr
== E_NOTIMPL
, "Unexpected hr %#lx.\n", hr
);
9141 ok(writetime
== 0, "Unexpected writetime.\n");
9143 IDWriteFontFileStream_Release(stream2
);
9145 /* Without owner object. */
9146 hr
= IDWriteInMemoryFontFileLoader_CreateInMemoryFontFileReference(inmemory
, (IDWriteFactory
*)factory
, data
,
9147 file_size
, NULL
, &file2
);
9148 ok(hr
== S_OK
, "Failed to create in-memory file reference, hr %#lx.\n", hr
);
9151 hr
= IDWriteInMemoryFontFileLoader_CreateStreamFromKey(inmemory
, &ref_key
, sizeof(ref_key
), &stream2
);
9152 ok(hr
== S_OK
, "Failed to create a stream, hr %#lx.\n", hr
);
9154 context2
= (void *)0xdeadbeef;
9155 hr
= IDWriteFontFileStream_ReadFileFragment(stream2
, &frag_start
, 0, file_size
, &context2
);
9156 ok(hr
== S_OK
, "Failed to read a fragment, hr %#lx.\n", hr
);
9157 ok(context2
== NULL
, "Unexpected context %p.\n", context2
);
9158 ok(frag_start
!= data
, "Unexpected fragment pointer %p.\n", frag_start
);
9160 hr
= IDWriteFontFileStream_GetFileSize(stream2
, &size
);
9161 ok(hr
== S_OK
, "Failed to get file size, hr %#lx.\n", hr
);
9162 ok(size
== file_size
, "Unexpected file size.\n");
9164 IDWriteFontFileStream_ReleaseFileFragment(stream2
, context2
);
9167 hr
= IDWriteFontFileStream_GetLastWriteTime(stream2
, &writetime
);
9168 ok(hr
== E_NOTIMPL
, "Unexpected hr %#lx.\n", hr
);
9169 ok(writetime
== 0, "Unexpected writetime.\n");
9171 IDWriteFontFileStream_Release(stream2
);
9172 IDWriteFontFile_Release(file2
);
9174 /* Key size validation. */
9176 hr
= IDWriteInMemoryFontFileLoader_CreateStreamFromKey(inmemory
, NULL
, sizeof(ref_key
) - 1, &stream2
);
9177 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
9180 hr
= IDWriteInMemoryFontFileLoader_CreateStreamFromKey(inmemory
, &ref_key
, sizeof(ref_key
) - 1, &stream2
);
9181 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
9184 hr
= IDWriteInMemoryFontFileLoader_CreateStreamFromKey(inmemory
, &ref_key
, sizeof(ref_key
) + 1, &stream2
);
9185 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
9187 count
= IDWriteInMemoryFontFileLoader_GetFileCount(inmemory
);
9188 ok(count
== 2, "Unexpected file count %u.\n", count
);
9190 hr
= IDWriteFontFile_GetReferenceKey(file
, &key
, &key_size
);
9191 ok(hr
== S_OK
, "Failed to get reference key, hr %#lx.\n", hr
);
9193 ok(key
&& *(DWORD
*)key
== 0, "Unexpected reference key.\n");
9194 ok(key_size
== 4, "Unexpected key size %u.\n", key_size
);
9196 IDWriteFontFile_Release(file
);
9198 count
= IDWriteInMemoryFontFileLoader_GetFileCount(inmemory
);
9199 ok(count
== 2, "Unexpected file count %u.\n", count
);
9201 hr
= IDWriteFactory5_UnregisterFontFileLoader(factory
, (IDWriteFontFileLoader
*)inmemory
);
9202 ok(hr
== S_OK
, "Failed to unregister loader, hr %#lx.\n", hr
);
9204 IDWriteFontFileStream_ReleaseFileFragment(stream
, context
);
9205 IDWriteFontFileStream_Release(stream
);
9206 IDWriteFontFace_Release(fontface
);
9208 ref
= IDWriteInMemoryFontFileLoader_Release(inmemory
);
9209 ok(ref
== 0, "loader not released, %lu.\n", ref
);
9211 ref
= IDWriteFactory5_Release(factory
);
9212 ok(ref
== 0, "factory not released, %lu\n", ref
);
9215 static BOOL
face_has_table(IDWriteFontFace4
*fontface
, UINT32 tag
)
9217 BOOL exists
= FALSE
;
9223 hr
= IDWriteFontFace4_TryGetFontTable(fontface
, tag
, &data
, &size
, &context
, &exists
);
9224 ok(hr
== S_OK
, "TryGetFontTable() failed, %#lx\n", hr
);
9226 IDWriteFontFace4_ReleaseFontTable(fontface
, context
);
9231 static DWORD
get_sbix_formats(IDWriteFontFace4
*fontface
)
9233 UINT32 size
, s
, num_strikes
;
9234 const sbix_header
*header
;
9235 UINT16 g
, num_glyphs
;
9236 BOOL exists
= FALSE
;
9243 hr
= IDWriteFontFace4_TryGetFontTable(fontface
, MS_MAXP_TAG
, &data
, &size
, &context
, &exists
);
9244 ok(hr
== S_OK
, "TryGetFontTable() failed, %#lx\n", hr
);
9245 ok(exists
, "Expected maxp table\n");
9251 num_glyphs
= GET_BE_WORD(maxp
->numGlyphs
);
9253 hr
= IDWriteFontFace4_TryGetFontTable(fontface
, MS_SBIX_TAG
, &data
, &size
, &context
, &exists
);
9254 ok(hr
== S_OK
, "TryGetFontTable() failed, %#lx\n", hr
);
9255 ok(exists
, "Expected sbix table\n");
9258 num_strikes
= GET_BE_DWORD(header
->numStrikes
);
9260 for (s
= 0; s
< num_strikes
; s
++) {
9261 sbix_strike
*strike
= (sbix_strike
*)((BYTE
*)header
+ GET_BE_DWORD(header
->strikeOffset
[s
]));
9263 for (g
= 0; g
< num_glyphs
; g
++) {
9264 DWORD offset
= GET_BE_DWORD(strike
->glyphDataOffsets
[g
]);
9265 DWORD offset_next
= GET_BE_DWORD(strike
->glyphDataOffsets
[g
+ 1]);
9266 sbix_glyph_data
*glyph_data
;
9269 if (offset
== offset_next
)
9272 glyph_data
= (sbix_glyph_data
*)((BYTE
*)strike
+ offset
);
9273 switch (format
= glyph_data
->graphicType
)
9276 ret
|= DWRITE_GLYPH_IMAGE_FORMATS_PNG
;
9279 ret
|= DWRITE_GLYPH_IMAGE_FORMATS_JPEG
;
9282 ret
|= DWRITE_GLYPH_IMAGE_FORMATS_TIFF
;
9285 ok(0, "unexpected format, %#lx\n", GET_BE_DWORD(format
));
9290 IDWriteFontFace4_ReleaseFontTable(fontface
, context
);
9295 static DWORD
get_cblc_formats(IDWriteFontFace4
*fontface
)
9297 CBLCBitmapSizeTable
*sizes
;
9298 UINT32 num_sizes
, size
, s
;
9299 BOOL exists
= FALSE
;
9305 hr
= IDWriteFontFace4_TryGetFontTable(fontface
, MS_CBLC_TAG
, (const void **)&header
, &size
, &context
, &exists
);
9306 ok(hr
== S_OK
, "TryGetFontTable() failed, %#lx\n", hr
);
9307 ok(exists
, "Expected CBLC table\n");
9312 num_sizes
= GET_BE_DWORD(header
->numSizes
);
9313 sizes
= (CBLCBitmapSizeTable
*)(header
+ 1);
9315 for (s
= 0; s
< num_sizes
; s
++) {
9316 BYTE bpp
= sizes
[s
].bitDepth
;
9318 if (bpp
== 1 || bpp
== 2 || bpp
== 4 || bpp
== 8)
9319 ret
|= DWRITE_GLYPH_IMAGE_FORMATS_PNG
;
9321 ret
|= DWRITE_GLYPH_IMAGE_FORMATS_PREMULTIPLIED_B8G8R8A8
;
9324 IDWriteFontFace4_ReleaseFontTable(fontface
, context
);
9329 static DWORD
get_face_glyph_image_formats(IDWriteFontFace4
*fontface
)
9331 DWORD ret
= DWRITE_GLYPH_IMAGE_FORMATS_NONE
;
9333 if (face_has_table(fontface
, MS_GLYF_TAG
))
9334 ret
|= DWRITE_GLYPH_IMAGE_FORMATS_TRUETYPE
;
9336 if (face_has_table(fontface
, MS_CFF__TAG
) ||
9337 face_has_table(fontface
, MS_CFF2_TAG
))
9338 ret
|= DWRITE_GLYPH_IMAGE_FORMATS_CFF
;
9340 if (face_has_table(fontface
, MS_COLR_TAG
))
9341 ret
|= DWRITE_GLYPH_IMAGE_FORMATS_COLR
;
9343 if (face_has_table(fontface
, MS_SVG__TAG
))
9344 ret
|= DWRITE_GLYPH_IMAGE_FORMATS_SVG
;
9346 if (face_has_table(fontface
, MS_SBIX_TAG
))
9347 ret
|= get_sbix_formats(fontface
);
9349 if (face_has_table(fontface
, MS_CBLC_TAG
))
9350 ret
|= get_cblc_formats(fontface
);
9355 static void test_GetGlyphImageFormats(void)
9357 IDWriteFontCollection
*syscollection
;
9358 IDWriteFactory
*factory
;
9362 IDWriteFontFace
*fontface
;
9363 IDWriteFontFace4
*fontface4
;
9365 factory
= create_factory();
9367 fontface
= create_fontface(factory
);
9368 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace4
, (void **)&fontface4
);
9369 IDWriteFontFace_Release(fontface
);
9371 win_skip("GetGlyphImageFormats() is not supported\n");
9372 IDWriteFactory_Release(factory
);
9375 IDWriteFontFace4_Release(fontface4
);
9377 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &syscollection
, FALSE
);
9378 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
9379 count
= IDWriteFontCollection_GetFontFamilyCount(syscollection
);
9381 for (i
= 0; i
< count
; i
++) {
9382 WCHAR familynameW
[256], facenameW
[128];
9383 IDWriteLocalizedStrings
*names
;
9384 IDWriteFontFamily
*family
;
9385 UINT32 j
, fontcount
;
9388 hr
= IDWriteFontCollection_GetFontFamily(syscollection
, i
, &family
);
9389 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
9391 hr
= IDWriteFontFamily_GetFamilyNames(family
, &names
);
9392 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
9394 get_enus_string(names
, familynameW
, ARRAY_SIZE(familynameW
));
9395 IDWriteLocalizedStrings_Release(names
);
9397 fontcount
= IDWriteFontFamily_GetFontCount(family
);
9398 for (j
= 0; j
< fontcount
; j
++) {
9399 DWORD formats
, expected_formats
;
9401 hr
= IDWriteFontFamily_GetFont(family
, j
, &font
);
9402 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
9404 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
9405 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
9407 hr
= IDWriteFont_GetFaceNames(font
, &names
);
9408 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
9410 get_enus_string(names
, facenameW
, ARRAY_SIZE(facenameW
));
9412 IDWriteLocalizedStrings_Release(names
);
9414 IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace4
, (void **)&fontface4
);
9416 /* Mask describes font as a whole. */
9417 formats
= IDWriteFontFace4_GetGlyphImageFormats(fontface4
);
9418 expected_formats
= get_face_glyph_image_formats(fontface4
);
9419 ok(formats
== expected_formats
, "%s - %s, expected formats %#lx, got formats %#lx.\n",
9420 wine_dbgstr_w(familynameW
), wine_dbgstr_w(facenameW
), expected_formats
, formats
);
9422 IDWriteFontFace4_Release(fontface4
);
9423 IDWriteFontFace_Release(fontface
);
9424 IDWriteFont_Release(font
);
9427 IDWriteFontFamily_Release(family
);
9430 IDWriteFontCollection_Release(syscollection
);
9431 ref
= IDWriteFactory_Release(factory
);
9432 ok(ref
== 0, "factory not released, %lu\n", ref
);
9435 static void test_CreateCustomRenderingParams(void)
9437 static const struct custom_params_test
9441 FLOAT cleartype_level
;
9442 DWRITE_PIXEL_GEOMETRY geometry
;
9443 DWRITE_RENDERING_MODE rendering_mode
;
9447 { 0.0f
, 0.0f
, 0.0f
, DWRITE_PIXEL_GEOMETRY_FLAT
, DWRITE_RENDERING_MODE_NATURAL
, E_INVALIDARG
},
9448 { 0.0f
, 0.1f
, 0.0f
, DWRITE_PIXEL_GEOMETRY_FLAT
, DWRITE_RENDERING_MODE_NATURAL
, E_INVALIDARG
},
9449 { 0.0f
, 0.0f
, 0.1f
, DWRITE_PIXEL_GEOMETRY_FLAT
, DWRITE_RENDERING_MODE_NATURAL
, E_INVALIDARG
},
9450 { -0.1f
, 0.0f
, 0.0f
, DWRITE_PIXEL_GEOMETRY_FLAT
, DWRITE_RENDERING_MODE_NATURAL
, E_INVALIDARG
},
9451 { 0.1f
, -0.1f
, 0.0f
, DWRITE_PIXEL_GEOMETRY_FLAT
, DWRITE_RENDERING_MODE_NATURAL
, E_INVALIDARG
},
9452 { 0.1f
, 0.0f
, -0.1f
, DWRITE_PIXEL_GEOMETRY_FLAT
, DWRITE_RENDERING_MODE_NATURAL
, E_INVALIDARG
},
9453 { 0.1f
, 0.0f
, 0.0f
, DWRITE_PIXEL_GEOMETRY_FLAT
, DWRITE_RENDERING_MODE_NATURAL
},
9454 { 0.01f
, 0.0f
, 0.0f
, DWRITE_PIXEL_GEOMETRY_FLAT
, DWRITE_RENDERING_MODE_NATURAL
},
9455 { 0.1f
, 0.0f
, 0.0f
, DWRITE_PIXEL_GEOMETRY_BGR
+ 1, DWRITE_RENDERING_MODE_NATURAL
, E_INVALIDARG
},
9456 { 0.1f
, 0.0f
, 0.0f
, DWRITE_PIXEL_GEOMETRY_BGR
, DWRITE_RENDERING_MODE_OUTLINE
+ 1, E_INVALIDARG
},
9457 { 0.1f
, 0.0f
, 2.0f
, DWRITE_PIXEL_GEOMETRY_BGR
, DWRITE_RENDERING_MODE_NATURAL
},
9459 IDWriteFactory
*factory
;
9464 factory
= create_factory();
9466 for (i
= 0; i
< ARRAY_SIZE(params_tests
); i
++) {
9467 IDWriteRenderingParams
*params
;
9469 winetest_push_context("%u", i
);
9471 params
= (void *)0xdeadbeef;
9472 hr
= IDWriteFactory_CreateCustomRenderingParams(factory
, params_tests
[i
].gamma
, params_tests
[i
].contrast
,
9473 params_tests
[i
].cleartype_level
, params_tests
[i
].geometry
, params_tests
[i
].rendering_mode
, ¶ms
);
9474 ok(hr
== params_tests
[i
].hr
, "unexpected hr %#lx, expected %#lx.\n", hr
, params_tests
[i
].hr
);
9477 ok(params_tests
[i
].gamma
== IDWriteRenderingParams_GetGamma(params
), "unexpected gamma %f, expected %f.\n",
9478 IDWriteRenderingParams_GetGamma(params
), params_tests
[i
].gamma
);
9479 ok(params_tests
[i
].contrast
== IDWriteRenderingParams_GetEnhancedContrast(params
),
9480 "unexpected contrast %f, expected %f.\n",
9481 IDWriteRenderingParams_GetEnhancedContrast(params
), params_tests
[i
].contrast
);
9482 ok(params_tests
[i
].cleartype_level
== IDWriteRenderingParams_GetClearTypeLevel(params
),
9483 "unexpected ClearType level %f, expected %f.\n",
9484 IDWriteRenderingParams_GetClearTypeLevel(params
), params_tests
[i
].cleartype_level
);
9485 ok(params_tests
[i
].geometry
== IDWriteRenderingParams_GetPixelGeometry(params
),
9486 "unexpected pixel geometry %u, expected %u.\n", IDWriteRenderingParams_GetPixelGeometry(params
),
9487 params_tests
[i
].geometry
);
9488 ok(params_tests
[i
].rendering_mode
== IDWriteRenderingParams_GetRenderingMode(params
),
9489 "unexpected rendering mode %u, expected %u.\n", IDWriteRenderingParams_GetRenderingMode(params
),
9490 params_tests
[i
].rendering_mode
);
9491 IDWriteRenderingParams_Release(params
);
9494 ok(params
== NULL
, "%u: expected NULL interface pointer on failure.\n", i
);
9496 winetest_pop_context();
9499 ref
= IDWriteFactory_Release(factory
);
9500 ok(ref
== 0, "factory not released, %lu\n", ref
);
9503 static void test_localfontfileloader(void)
9505 IDWriteFontFileLoader
*loader
, *loader2
;
9506 IDWriteFactory
*factory
, *factory2
;
9507 IDWriteFontFile
*file
, *file2
;
9512 factory
= create_factory();
9513 factory2
= create_factory();
9515 path
= create_testfontfile(test_fontfile
);
9517 hr
= IDWriteFactory_CreateFontFileReference(factory
, path
, NULL
, &file
);
9518 ok(hr
== S_OK
, "Failed to create file reference, hr %#lx.\n", hr
);
9520 hr
= IDWriteFactory_CreateFontFileReference(factory2
, path
, NULL
, &file2
);
9521 ok(hr
== S_OK
, "Failed to create file reference, hr %#lx.\n", hr
);
9522 ok(file
!= file2
, "Unexpected file instance.\n");
9524 hr
= IDWriteFontFile_GetLoader(file
, &loader
);
9525 ok(hr
== S_OK
, "Failed to get loader, hr %#lx.\n", hr
);
9527 hr
= IDWriteFontFile_GetLoader(file2
, &loader2
);
9528 ok(hr
== S_OK
, "Failed to get loader, hr %#lx.\n", hr
);
9529 ok(loader
== loader2
, "Unexpected loader instance\n");
9531 IDWriteFontFile_Release(file
);
9532 IDWriteFontFile_Release(file2
);
9533 IDWriteFontFileLoader_Release(loader
);
9534 IDWriteFontFileLoader_Release(loader2
);
9535 ref
= IDWriteFactory_Release(factory
);
9536 ok(ref
== 0, "factory not released, %lu\n", ref
);
9537 ref
= IDWriteFactory_Release(factory2
);
9538 ok(ref
== 0, "factory not released, %lu\n", ref
);
9539 DELETE_FONTFILE(path
);
9542 static void test_AnalyzeContainerType(void)
9544 struct WOFFHeader2 woff2_header
;
9545 struct WOFFHeader woff_header
;
9546 DWRITE_CONTAINER_TYPE type
;
9547 IDWriteFactory5
*factory
;
9549 factory
= create_factory_iid(&IID_IDWriteFactory5
);
9551 win_skip("AnalyzeContainerType() is not supported.\n");
9555 type
= IDWriteFactory5_AnalyzeContainerType(factory
, NULL
, 0);
9556 ok(type
== DWRITE_CONTAINER_TYPE_UNKNOWN
, "Unexpected container type %u.\n", type
);
9558 type
= IDWriteFactory5_AnalyzeContainerType(factory
, (void const *)0xdeadbeef, 0);
9559 ok(type
== DWRITE_CONTAINER_TYPE_UNKNOWN
, "Unexpected container type %u.\n", type
);
9561 memset(&woff_header
, 0xff, sizeof(woff_header
));
9562 woff_header
.signature
= GET_LE_DWORD(MS_WOFF_TAG
);
9563 woff_header
.length
= 0;
9564 type
= IDWriteFactory5_AnalyzeContainerType(factory
, &woff_header
, sizeof(woff_header
));
9565 ok(type
== DWRITE_CONTAINER_TYPE_WOFF
, "Unexpected container type %u.\n", type
);
9567 memset(&woff_header
, 0xff, sizeof(woff_header
));
9568 woff_header
.signature
= GET_LE_DWORD(MS_WOFF_TAG
);
9569 type
= IDWriteFactory5_AnalyzeContainerType(factory
, &woff_header
, sizeof(woff_header
.signature
));
9570 ok(type
== DWRITE_CONTAINER_TYPE_WOFF
, "Unexpected container type %u.\n", type
);
9572 memset(&woff_header
, 0xff, sizeof(woff_header
));
9573 woff_header
.signature
= GET_LE_DWORD(MS_WOFF_TAG
);
9574 type
= IDWriteFactory5_AnalyzeContainerType(factory
, &woff_header
, sizeof(woff_header
.signature
) - 1);
9575 ok(type
== DWRITE_CONTAINER_TYPE_UNKNOWN
, "Unexpected container type %u.\n", type
);
9577 memset(&woff2_header
, 0xff, sizeof(woff2_header
));
9578 woff2_header
.signature
= GET_LE_DWORD(MS_WOF2_TAG
);
9579 type
= IDWriteFactory5_AnalyzeContainerType(factory
, &woff2_header
, sizeof(woff2_header
));
9580 ok(type
== DWRITE_CONTAINER_TYPE_WOFF2
, "Unexpected container type %u.\n", type
);
9582 memset(&woff2_header
, 0xff, sizeof(woff2_header
));
9583 woff2_header
.signature
= GET_LE_DWORD(MS_WOF2_TAG
);
9584 type
= IDWriteFactory5_AnalyzeContainerType(factory
, &woff2_header
, sizeof(woff2_header
.signature
));
9585 ok(type
== DWRITE_CONTAINER_TYPE_WOFF2
, "Unexpected container type %u.\n", type
);
9587 memset(&woff2_header
, 0xff, sizeof(woff2_header
));
9588 woff2_header
.signature
= GET_LE_DWORD(MS_WOF2_TAG
);
9589 type
= IDWriteFactory5_AnalyzeContainerType(factory
, &woff2_header
, sizeof(woff2_header
.signature
) - 1);
9590 ok(type
== DWRITE_CONTAINER_TYPE_UNKNOWN
, "Unexpected container type %u.\n", type
);
9592 IDWriteFactory5_Release(factory
);
9595 static void test_fontsetbuilder(void)
9597 IDWriteFontFaceReference
*ref
, *ref2
, *ref3
;
9598 IDWriteFontCollection1
*collection
;
9599 IDWriteFontFaceReference1
*ref1
;
9600 IDWriteFontSetBuilder1
*builder1
;
9601 IDWriteFontSetBuilder
*builder
;
9602 DWRITE_FONT_AXIS_VALUE axis_values
[4];
9603 IDWriteFactory3
*factory
;
9604 UINT32 count
, i
, refcount
;
9605 IDWriteFontSet
*fontset
;
9606 IDWriteFontFile
*file
;
9610 factory
= create_factory_iid(&IID_IDWriteFactory3
);
9613 win_skip("IDWriteFontSetBuilder is not supported.\n");
9617 EXPECT_REF(factory
, 1);
9618 hr
= IDWriteFactory3_CreateFontSetBuilder(factory
, &builder
);
9619 ok(hr
== S_OK
, "Failed to create font set builder, hr %#lx.\n", hr
);
9620 EXPECT_REF(factory
, 2);
9622 if (SUCCEEDED(hr
= IDWriteFontSetBuilder_QueryInterface(builder
, &IID_IDWriteFontSetBuilder1
, (void **)&builder1
)))
9624 path
= create_testfontfile(test_fontfile
);
9626 hr
= IDWriteFactory3_CreateFontFileReference(factory
, path
, NULL
, &file
);
9627 ok(hr
== S_OK
, "Unexpected hr %#lx.\n",hr
);
9629 hr
= IDWriteFontSetBuilder1_AddFontFile(builder1
, file
);
9630 ok(hr
== S_OK
, "Unexpected hr %#lx.\n",hr
);
9632 hr
= IDWriteFontSetBuilder1_CreateFontSet(builder1
, &fontset
);
9633 ok(hr
== S_OK
, "Unexpected hr %#lx.\n",hr
);
9634 hr
= IDWriteFactory3_CreateFontCollectionFromFontSet(factory
, fontset
, &collection
);
9636 ok(hr
== S_OK
, "Unexpected hr %#lx.\n",hr
);
9639 count
= IDWriteFontCollection1_GetFontFamilyCount(collection
);
9640 ok(count
== 1, "Unexpected family count %u.\n", count
);
9641 IDWriteFontCollection1_Release(collection
);
9643 IDWriteFontSet_Release(fontset
);
9645 hr
= IDWriteFontSetBuilder1_AddFontFile(builder1
, file
);
9646 ok(hr
== S_OK
, "Unexpected hr %#lx.\n",hr
);
9648 hr
= IDWriteFontSetBuilder1_CreateFontSet(builder1
, &fontset
);
9649 ok(hr
== S_OK
, "Unexpected hr %#lx.\n",hr
);
9651 hr
= IDWriteFactory3_CreateFontCollectionFromFontSet(factory
, fontset
, &collection
);
9653 ok(hr
== S_OK
, "Unexpected hr %#lx.\n",hr
);
9656 check_familymodel(collection
, DWRITE_FONT_FAMILY_MODEL_WEIGHT_STRETCH_STYLE
);
9657 count
= IDWriteFontCollection1_GetFontFamilyCount(collection
);
9658 ok(count
== 1, "Unexpected family count %u.\n", count
);
9659 IDWriteFontCollection1_Release(collection
);
9662 /* No attempt to eliminate duplicates. */
9663 count
= IDWriteFontSet_GetFontCount(fontset
);
9664 ok(count
== 2, "Unexpected font count %u.\n", count
);
9666 hr
= IDWriteFontSet_GetFontFaceReference(fontset
, 0, &ref
);
9667 ok(hr
== S_OK
, "Unexpected hr %#lx.\n",hr
);
9669 hr
= IDWriteFontFaceReference_QueryInterface(ref
, &IID_IDWriteFontFaceReference1
, (void **)&ref1
);
9670 ok(hr
== S_OK
, "Unexpected hr %#lx.\n",hr
);
9672 count
= IDWriteFontFaceReference1_GetFontAxisValueCount(ref1
);
9674 ok(count
== 4, "Unexpected axis count %u.\n", count
);
9678 hr
= IDWriteFontFaceReference1_GetFontAxisValues(ref1
, axis_values
, ARRAY_SIZE(axis_values
));
9679 ok(hr
== S_OK
, "Unexpected hr %#lx.\n",hr
);
9681 ok(axis_values
[0].axisTag
== DWRITE_FONT_AXIS_TAG_WEIGHT
, "Unexpected tag[0] %s.\n",
9682 wine_dbgstr_an((char *)&axis_values
[0].axisTag
, 4));
9683 ok(axis_values
[0].value
== 500.0f
, "Unexpected value[0] %f.\n", axis_values
[0].value
);
9684 ok(axis_values
[1].axisTag
== DWRITE_FONT_AXIS_TAG_WIDTH
, "Unexpected tag[1] %s.\n",
9685 wine_dbgstr_an((char *)&axis_values
[1].axisTag
, 4));
9686 ok(axis_values
[1].value
== 100.0f
, "Unexpected value[1] %f.\n", axis_values
[1].value
);
9687 ok(axis_values
[2].axisTag
== DWRITE_FONT_AXIS_TAG_ITALIC
, "Unexpected tag[2] %s.\n",
9688 wine_dbgstr_an((char *)&axis_values
[2].axisTag
, 4));
9689 ok(axis_values
[2].value
== 0.0f
, "Unexpected value[2] %f.\n", axis_values
[2].value
);
9690 ok(axis_values
[3].axisTag
== DWRITE_FONT_AXIS_TAG_SLANT
, "Unexpected tag[3] %s.\n",
9691 wine_dbgstr_an((char *)&axis_values
[3].axisTag
, 4));
9692 ok(axis_values
[3].value
== 0.0f
, "Unexpected value[3] %f.\n", axis_values
[3].value
);
9695 IDWriteFontFaceReference1_Release(ref1
);
9697 IDWriteFontFaceReference_Release(ref
);
9699 IDWriteFontSet_Release(fontset
);
9701 IDWriteFontFile_Release(file
);
9702 IDWriteFontSetBuilder1_Release(builder1
);
9705 win_skip("IDWriteFontSetBuilder1 is not available.\n");
9706 IDWriteFontSetBuilder_Release(builder
);
9708 hr
= IDWriteFactory3_GetSystemFontCollection(factory
, FALSE
, &collection
, FALSE
);
9709 ok(hr
== S_OK
, "Failed to get system collection, hr %#lx.\n", hr
);
9710 count
= IDWriteFontCollection1_GetFontFamilyCount(collection
);
9712 for (i
= 0; i
< count
; i
++) {
9713 IDWriteFontFamily1
*family
;
9714 UINT32 j
, fontcount
;
9717 hr
= IDWriteFontCollection1_GetFontFamily(collection
, i
, &family
);
9718 ok(hr
== S_OK
, "Failed to get family, hr %#lx.\n", hr
);
9720 fontcount
= IDWriteFontFamily1_GetFontCount(family
);
9721 for (j
= 0; j
< fontcount
; ++j
)
9723 IDWriteFontSet
*fontset
;
9724 UINT32 setcount
, id
;
9726 hr
= IDWriteFontFamily1_GetFont(family
, j
, &font
);
9727 ok(hr
== S_OK
, "Failed to get font, hr %#lx.\n", hr
);
9729 /* Create a set with a single font reference, test set properties. */
9730 hr
= IDWriteFactory3_CreateFontSetBuilder(factory
, &builder
);
9731 ok(hr
== S_OK
, "Failed to create font set builder, hr %#lx.\n", hr
);
9733 hr
= IDWriteFont3_GetFontFaceReference(font
, &ref
);
9734 ok(hr
== S_OK
, "Failed to get fontface reference, hr %#lx.\n", hr
);
9737 hr
= IDWriteFontSetBuilder_AddFontFaceReference(builder
, ref
);
9738 ok(hr
== S_OK
, "Failed to add fontface reference, hr %#lx.\n", hr
);
9741 hr
= IDWriteFontSetBuilder_CreateFontSet(builder
, &fontset
);
9742 ok(hr
== S_OK
, "Failed to create a font set, hr %#lx.\n", hr
);
9744 setcount
= IDWriteFontSet_GetFontCount(fontset
);
9745 ok(setcount
== 1, "Unexpected font count %u.\n", setcount
);
9747 ref2
= (void *)0xdeadbeef;
9748 hr
= IDWriteFontSet_GetFontFaceReference(fontset
, setcount
, &ref2
);
9749 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
9750 ok(!ref2
, "Unexpected pointer.\n");
9753 hr
= IDWriteFontSet_GetFontFaceReference(fontset
, 0, &ref2
);
9754 ok(hr
== S_OK
, "Failed to get font face reference, hr %#lx.\n", hr
);
9755 ok(ref2
!= ref
, "Unexpected reference.\n");
9758 hr
= IDWriteFontSet_GetFontFaceReference(fontset
, 0, &ref3
);
9759 ok(hr
== S_OK
, "Failed to get font face reference, hr %#lx.\n", hr
);
9760 ok(ref2
!= ref3
, "Unexpected reference.\n");
9762 IDWriteFontFaceReference_Release(ref3
);
9763 IDWriteFontFaceReference_Release(ref2
);
9765 for (id
= DWRITE_FONT_PROPERTY_ID_FAMILY_NAME
; id
< DWRITE_FONT_PROPERTY_ID_TOTAL
; ++id
)
9767 IDWriteLocalizedStrings
*values
;
9768 WCHAR buffW
[255], buff2W
[255];
9769 UINT32 c
, ivalue
= 0;
9770 BOOL exists
= FALSE
;
9772 hr
= IDWriteFontSet_GetPropertyValues(fontset
, 0, id
, &exists
, &values
);
9773 ok(hr
== S_OK
, "Failed to get property value, hr %#lx.\n", hr
);
9775 if (id
== DWRITE_FONT_PROPERTY_ID_WEIGHT
|| id
== DWRITE_FONT_PROPERTY_ID_STRETCH
9776 || id
== DWRITE_FONT_PROPERTY_ID_STYLE
)
9779 ok(exists
, "Property %u expected to exist.\n", id
);
9787 case DWRITE_FONT_PROPERTY_ID_WEIGHT
:
9788 ivalue
= IDWriteFont3_GetWeight(font
);
9790 case DWRITE_FONT_PROPERTY_ID_STRETCH
:
9791 ivalue
= IDWriteFont3_GetStretch(font
);
9793 case DWRITE_FONT_PROPERTY_ID_STYLE
:
9794 ivalue
= IDWriteFont3_GetStyle(font
);
9802 case DWRITE_FONT_PROPERTY_ID_WEIGHT
:
9803 case DWRITE_FONT_PROPERTY_ID_STRETCH
:
9804 case DWRITE_FONT_PROPERTY_ID_STYLE
:
9805 c
= IDWriteLocalizedStrings_GetCount(values
);
9806 ok(c
== 1, "Unexpected string count %u.\n", c
);
9809 hr
= IDWriteLocalizedStrings_GetLocaleName(values
, 0, buffW
, ARRAY_SIZE(buffW
));
9810 ok(hr
== S_OK
, "Failed to get locale name, hr %#lx.\n", hr
);
9811 ok(!*buffW
, "Unexpected locale %s.\n", wine_dbgstr_w(buffW
));
9814 hr
= IDWriteLocalizedStrings_GetString(values
, 0, buff2W
, ARRAY_SIZE(buff2W
));
9815 ok(hr
== S_OK
, "Failed to get property string, hr %#lx.\n", hr
);
9817 wsprintfW(buffW
, L
"%u", ivalue
);
9818 ok(!lstrcmpW(buffW
, buff2W
), "Unexpected property value %s, expected %s.\n", wine_dbgstr_w(buff2W
),
9819 wine_dbgstr_w(buffW
));
9825 IDWriteLocalizedStrings_Release(values
);
9828 IDWriteFontSet_Release(fontset
);
9829 IDWriteFontFaceReference_Release(ref
);
9830 IDWriteFontSetBuilder_Release(builder
);
9832 IDWriteFont3_Release(font
);
9835 IDWriteFontFamily1_Release(family
);
9838 IDWriteFontCollection1_Release(collection
);
9840 refcount
= IDWriteFactory3_Release(factory
);
9841 ok(!refcount
, "Factory not released, %u.\n", refcount
);
9844 static void test_font_resource(void)
9846 IDWriteFontFaceReference1
*reference
, *reference2
;
9847 IDWriteFontResource
*resource
, *resource2
;
9848 IDWriteFontFile
*fontfile
, *fontfile2
;
9849 DWRITE_FONT_AXIS_VALUE axis_values
[2];
9850 IDWriteFontFace5
*fontface5
;
9851 IDWriteFontFace
*fontface
;
9852 IDWriteFactory6
*factory
;
9853 UINT32 count
, index
;
9858 if (!(factory
= create_factory_iid(&IID_IDWriteFactory6
)))
9860 win_skip("IDWriteFactory6 is not supported.\n");
9864 fontface
= create_fontface((IDWriteFactory
*)factory
);
9867 hr
= IDWriteFontFace_GetFiles(fontface
, &count
, &fontfile
);
9868 ok(hr
== S_OK
, "Failed to get file object, hr %#lx.\n", hr
);
9870 hr
= IDWriteFactory6_CreateFontResource(factory
, fontfile
, 0, &resource
);
9871 ok(hr
== S_OK
, "Failed to create font resource, hr %#lx.\n", hr
);
9873 hr
= IDWriteFactory6_CreateFontResource(factory
, fontfile
, 0, &resource2
);
9874 ok(hr
== S_OK
, "Failed to create font resource, hr %#lx.\n", hr
);
9875 ok(resource
!= resource2
, "Unexpected instance.\n");
9876 IDWriteFontResource_Release(resource2
);
9878 hr
= IDWriteFontResource_GetFontFile(resource
, &fontfile2
);
9879 ok(hr
== S_OK
, "Failed to get font file, hr %#lx.\n", hr
);
9880 ok(fontfile2
== fontfile
, "Unexpected file instance.\n");
9881 IDWriteFontFile_Release(fontfile2
);
9883 index
= IDWriteFontResource_GetFontFaceIndex(resource
);
9884 ok(!index
, "Unexpected index %u.\n", index
);
9886 /* Specify axis value, font has no variations. */
9887 axis_values
[0].axisTag
= DWRITE_FONT_AXIS_TAG_WEIGHT
;
9888 axis_values
[0].value
= 400.0f
;
9889 hr
= IDWriteFontResource_CreateFontFaceReference(resource
, DWRITE_FONT_SIMULATIONS_NONE
, axis_values
, 1, &reference
);
9890 ok(hr
== S_OK
, "Failed to create reference object, hr %#lx.\n", hr
);
9892 count
= IDWriteFontFaceReference1_GetFontAxisValueCount(reference
);
9893 ok(count
== 1, "Unexpected axis value count.\n");
9895 IDWriteFontFaceReference1_Release(reference
);
9897 hr
= IDWriteFactory6_CreateFontFaceReference(factory
, fontfile
, 0, DWRITE_FONT_SIMULATIONS_NONE
, axis_values
, 1,
9899 count
= IDWriteFontFaceReference1_GetFontAxisValueCount(reference
);
9900 ok(count
== 1, "Unexpected axis value count.\n");
9901 IDWriteFontFaceReference1_Release(reference
);
9903 EXPECT_REF(resource
, 1);
9904 hr
= IDWriteFontResource_CreateFontFaceReference(resource
, DWRITE_FONT_SIMULATIONS_NONE
, NULL
, 0, &reference
);
9905 ok(hr
== S_OK
, "Failed to create reference object, hr %#lx.\n", hr
);
9906 EXPECT_REF(resource
, 1);
9908 hr
= IDWriteFontResource_CreateFontFaceReference(resource
, DWRITE_FONT_SIMULATIONS_NONE
, NULL
, 0, &reference2
);
9909 ok(hr
== S_OK
, "Failed to create reference object, hr %#lx.\n", hr
);
9910 ok(reference
!= reference2
, "Unexpected reference instance.\n");
9911 IDWriteFontFaceReference1_Release(reference2
);
9912 IDWriteFontFaceReference1_Release(reference
);
9914 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace5
, (void **)&fontface5
);
9915 ok(hr
== S_OK
, "Failed to get interface, hr %#lx.\n", hr
);
9917 hr
= IDWriteFontFace5_GetFontResource(fontface5
, &resource2
);
9918 ok(hr
== S_OK
, "Failed to get font resource, hr %#lx.\n", hr
);
9919 ok(resource
!= resource2
, "Unexpected resource instance.\n");
9920 IDWriteFontResource_Release(resource
);
9922 hr
= IDWriteFontFace5_GetFontResource(fontface5
, &resource
);
9923 ok(hr
== S_OK
, "Failed to get font resource, hr %#lx.\n", hr
);
9924 ok(resource
!= resource2
, "Unexpected resource instance.\n");
9925 EXPECT_REF(resource
, 1);
9926 IDWriteFontResource_Release(resource
);
9927 IDWriteFontResource_Release(resource2
);
9929 IDWriteFontFace5_Release(fontface5
);
9931 /* Reference equality regarding set axis values. */
9932 axis_values
[0].axisTag
= DWRITE_FONT_AXIS_TAG_WEIGHT
;
9933 axis_values
[0].value
= 400.0f
;
9934 axis_values
[1].axisTag
= DWRITE_FONT_AXIS_TAG_ITALIC
;
9935 axis_values
[1].value
= 1.0f
;
9936 hr
= IDWriteFactory6_CreateFontFaceReference(factory
, fontfile
, 0, DWRITE_FONT_SIMULATIONS_NONE
, axis_values
, 2,
9938 count
= IDWriteFontFaceReference1_GetFontAxisValueCount(reference
);
9939 ok(count
== 2, "Unexpected axis value count.\n");
9941 hr
= IDWriteFactory6_CreateFontFaceReference(factory
, fontfile
, 0, DWRITE_FONT_SIMULATIONS_NONE
, NULL
, 0,
9943 count
= IDWriteFontFaceReference1_GetFontAxisValueCount(reference2
);
9944 ok(!count
, "Unexpected axis value count.\n");
9946 ret
= IDWriteFontFaceReference1_Equals(reference
, (IDWriteFontFaceReference
*)reference2
);
9947 ok(!ret
, "Unexpected result.\n");
9948 IDWriteFontFaceReference1_Release(reference2
);
9950 /* Different values order. */
9951 axis_values
[0].axisTag
= DWRITE_FONT_AXIS_TAG_ITALIC
;
9952 axis_values
[0].value
= 1.0f
;
9953 axis_values
[1].axisTag
= DWRITE_FONT_AXIS_TAG_WEIGHT
;
9954 axis_values
[1].value
= 400.0f
;
9955 hr
= IDWriteFactory6_CreateFontFaceReference(factory
, fontfile
, 0, DWRITE_FONT_SIMULATIONS_NONE
, axis_values
, 2,
9957 count
= IDWriteFontFaceReference1_GetFontAxisValueCount(reference2
);
9958 ok(count
== 2, "Unexpected axis value count.\n");
9960 ret
= IDWriteFontFaceReference1_Equals(reference
, (IDWriteFontFaceReference
*)reference2
);
9961 ok(!ret
, "Unexpected result.\n");
9962 IDWriteFontFaceReference1_Release(reference2
);
9964 /* Different axis values. */
9965 axis_values
[0].axisTag
= DWRITE_FONT_AXIS_TAG_ITALIC
;
9966 axis_values
[0].value
= 1.0f
;
9967 axis_values
[1].axisTag
= DWRITE_FONT_AXIS_TAG_WEIGHT
;
9968 axis_values
[1].value
= 401.0f
;
9969 hr
= IDWriteFactory6_CreateFontFaceReference(factory
, fontfile
, 0, DWRITE_FONT_SIMULATIONS_NONE
, axis_values
, 2,
9971 count
= IDWriteFontFaceReference1_GetFontAxisValueCount(reference2
);
9972 ok(count
== 2, "Unexpected axis value count.\n");
9974 ret
= IDWriteFontFaceReference1_Equals(reference
, (IDWriteFontFaceReference
*)reference2
);
9975 ok(!ret
, "Unexpected result.\n");
9976 IDWriteFontFaceReference1_Release(reference2
);
9978 memset(axis_values
, 0, sizeof(axis_values
));
9979 hr
= IDWriteFontFaceReference1_GetFontAxisValues(reference
, axis_values
, 1);
9980 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "Unexpected hr %#lx.\n", hr
);
9981 ok(!axis_values
[0].axisTag
, "Unexpected axis tag.\n");
9983 memset(axis_values
, 0, sizeof(axis_values
));
9984 hr
= IDWriteFontFaceReference1_GetFontAxisValues(reference
, axis_values
, 2);
9985 ok(hr
== S_OK
, "Failed to get axis values, hr %#lx.\n", hr
);
9986 ok(axis_values
[0].axisTag
== DWRITE_FONT_AXIS_TAG_WEIGHT
, "Unexpected axis tag.\n");
9988 hr
= IDWriteFontFaceReference1_CreateFontFace(reference
, &fontface5
);
9989 ok(hr
== S_OK
, "Failed to create a font face, hr %#lx.\n", hr
);
9990 IDWriteFontFace5_Release(fontface5
);
9992 IDWriteFontFaceReference1_Release(reference
);
9994 IDWriteFontFile_Release(fontfile
);
9996 IDWriteFontFace_Release(fontface
);
9997 ref
= IDWriteFactory6_Release(factory
);
9998 ok(ref
== 0, "Factory wasn't released, %lu.\n", ref
);
10001 static BOOL
get_expected_is_color(IDWriteFontFace2
*fontface
)
10009 hr
= IDWriteFontFace2_TryGetFontTable(fontface
, MS_CPAL_TAG
, (const void **)&data
, &size
, &context
, &exists
);
10010 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
10012 IDWriteFontFace2_ReleaseFontTable(fontface
, context
);
10016 hr
= IDWriteFontFace2_TryGetFontTable(fontface
, MS_COLR_TAG
, (const void **)&data
, &size
, &context
, &exists
);
10017 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
10019 IDWriteFontFace2_ReleaseFontTable(fontface
, context
);
10025 static void test_IsColorFont(void)
10027 IDWriteFontCollection
*collection
;
10028 IDWriteFactory2
*factory
;
10033 factory
= create_factory_iid(&IID_IDWriteFactory2
);
10037 win_skip("IsColorFont() is not supported.\n");
10041 hr
= IDWriteFactory2_GetSystemFontCollection(factory
, &collection
, FALSE
);
10042 ok(hr
== S_OK
, "Failed to get font collection, hr %#lx.\n", hr
);
10044 count
= IDWriteFontCollection_GetFontFamilyCount(collection
);
10045 for (i
= 0; i
< count
; ++i
)
10047 IDWriteLocalizedStrings
*names
;
10048 IDWriteFontFamily
*family
;
10049 UINT32 font_count
, j
;
10052 hr
= IDWriteFontCollection_GetFontFamily(collection
, i
, &family
);
10053 ok(hr
== S_OK
, "Failed to get family, hr %#lx.\n", hr
);
10055 hr
= IDWriteFontFamily_GetFamilyNames(family
, &names
);
10056 ok(hr
== S_OK
, "Failed to get names, hr %#lx.\n", hr
);
10057 get_enus_string(names
, nameW
, ARRAY_SIZE(nameW
));
10058 IDWriteLocalizedStrings_Release(names
);
10060 font_count
= IDWriteFontFamily_GetFontCount(family
);
10062 for (j
= 0; j
< font_count
; ++j
)
10064 BOOL is_color_font
, is_color_face
, is_color_expected
;
10065 IDWriteFontFace2
*fontface2
;
10066 IDWriteFontFace
*fontface
;
10067 IDWriteFont2
*font2
;
10070 hr
= IDWriteFontFamily_GetFont(family
, j
, &font
);
10071 ok(hr
== S_OK
, "Failed to get font, hr %#lx.\n", hr
);
10073 hr
= IDWriteFont_QueryInterface(font
, &IID_IDWriteFont2
, (void **)&font2
);
10074 ok(hr
== S_OK
, "Failed to get interface, hr %#lx.\n", hr
);
10075 IDWriteFont_Release(font
);
10077 hr
= IDWriteFont2_CreateFontFace(font2
, &fontface
);
10078 ok(hr
== S_OK
, "Failed to create fontface, hr %#lx.\n", hr
);
10080 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace2
, (void **)&fontface2
);
10081 ok(hr
== S_OK
, "Failed to get interface, hr %#lx.\n", hr
);
10082 IDWriteFontFace_Release(fontface
);
10084 is_color_font
= IDWriteFont2_IsColorFont(font2
);
10085 is_color_face
= IDWriteFontFace2_IsColorFont(fontface2
);
10086 ok(is_color_font
== is_color_face
, "Unexpected color flag.\n");
10088 is_color_expected
= get_expected_is_color(fontface2
);
10089 ok(is_color_expected
== is_color_face
, "Unexpected is_color flag %d for %s, font %d.\n",
10090 is_color_face
, wine_dbgstr_w(nameW
), j
);
10092 IDWriteFontFace2_Release(fontface2
);
10093 IDWriteFont2_Release(font2
);
10096 IDWriteFontFamily_Release(family
);
10099 IDWriteFontCollection_Release(collection
);
10100 refcount
= IDWriteFactory2_Release(factory
);
10101 ok(refcount
== 0, "Factory not released, refcount %lu.\n", refcount
);
10104 static void test_GetVerticalGlyphVariants(void)
10106 UINT16 glyphs
[1], glyph_variants
[1];
10107 IDWriteFontFace1
*fontface1
;
10108 IDWriteFontFace
*fontface
;
10109 IDWriteFactory
*factory
;
10115 factory
= create_factory();
10117 fontface
= create_fontface(factory
);
10118 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void **)&fontface1
);
10119 IDWriteFontFace_Release(fontface
);
10122 win_skip("GetVerticalGlyphVariants() is not supported.\n");
10123 IDWriteFactory_Release(factory
);
10129 hr
= IDWriteFontFace1_GetGlyphIndices(fontface1
, &ch
, 1, glyphs
);
10130 ok(hr
== S_OK
, "Failed to get glyph, hr %#lx.\n", hr
);
10131 ok(!!*glyphs
, "Unexpected glyph %u.\n", glyphs
[0]);
10133 memset(glyph_variants
, 0, sizeof(glyph_variants
));
10134 hr
= IDWriteFontFace1_GetVerticalGlyphVariants(fontface1
, 1, glyphs
, glyph_variants
);
10135 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
10136 ok(glyphs
[0] == glyph_variants
[0], "Unexpected glyph.\n");
10138 ret
= IDWriteFontFace1_HasVerticalGlyphVariants(fontface1
);
10139 ok(!ret
, "Unexpected flag.\n");
10141 IDWriteFontFace1_Release(fontface1
);
10142 refcount
= IDWriteFactory_Release(factory
);
10143 ok(!refcount
, "Factory not released, refcount %lu.\n", refcount
);
10146 static HANDLE
get_collection_expiration_event(IDWriteFontCollection
*collection
)
10148 IDWriteFontCollection3
*collection3
;
10152 hr
= IDWriteFontCollection_QueryInterface(collection
, &IID_IDWriteFontCollection3
, (void **)&collection3
);
10153 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
10154 event
= IDWriteFontCollection3_GetExpirationEvent(collection3
);
10155 IDWriteFontCollection3_Release(collection3
);
10160 static void test_expiration_event(void)
10162 IDWriteFontCollection
*collection
, *collection2
;
10163 IDWriteFontCollection3
*collection3
;
10164 IDWriteFactory
*factory
, *factory2
;
10165 unsigned int refcount
;
10166 HANDLE event
, event2
;
10169 factory
= create_factory();
10171 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &collection
, FALSE
);
10172 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
10174 hr
= IDWriteFontCollection_QueryInterface(collection
, &IID_IDWriteFontCollection3
, (void **)&collection3
);
10177 win_skip("Expiration events are not supported.\n");
10178 IDWriteFontCollection_Release(collection
);
10179 IDWriteFactory_Release(factory
);
10182 IDWriteFontCollection3_Release(collection3
);
10184 event
= get_collection_expiration_event(collection
);
10186 ok(!!event
, "Unexpected event handle.\n");
10188 /* Compare handles with another isolated factory. */
10189 factory2
= create_factory();
10191 hr
= IDWriteFactory_GetSystemFontCollection(factory2
, &collection2
, FALSE
);
10192 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
10193 event2
= get_collection_expiration_event(collection2
);
10195 ok(!!event2
, "Unexpected event handle.\n");
10196 ok(event
!= event2
, "Unexpected event handle.\n");
10198 IDWriteFontCollection_Release(collection2
);
10200 IDWriteFontCollection_Release(collection
);
10202 refcount
= IDWriteFactory_Release(factory2
);
10203 ok(!refcount
, "Unexpected factory refcount %u.\n", refcount
);
10204 refcount
= IDWriteFactory_Release(factory
);
10205 ok(!refcount
, "Unexpected factory refcount %u.\n", refcount
);
10208 static void test_family_font_set(void)
10210 IDWriteFontCollection
*collection
;
10211 IDWriteFontFamily2
*family2
;
10212 IDWriteFontFamily
*family
;
10213 IDWriteFactory
*factory
;
10214 unsigned int count
, refcount
;
10215 IDWriteFontSet1
*fontset
, *fontset2
;
10216 IDWriteLocalizedStrings
*values
;
10217 IDWriteFontResource
*resource
;
10222 factory
= create_factory();
10224 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &collection
, FALSE
);
10225 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
10227 hr
= IDWriteFontCollection_GetFontFamily(collection
, 0, &family
);
10228 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
10230 if (SUCCEEDED(IDWriteFontFamily_QueryInterface(family
, &IID_IDWriteFontFamily2
, (void **)&family2
)))
10232 hr
= IDWriteFontFamily2_GetFontSet(family2
, &fontset
);
10233 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
10234 hr
= IDWriteFontFamily2_GetFontSet(family2
, &fontset2
);
10235 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
10236 ok(fontset
!= fontset2
, "Unexpected fontset instance.\n");
10238 count
= IDWriteFontSet1_GetFontCount(fontset
);
10240 /* Invalid property id. */
10242 values
= (void *)0xdeadbeef;
10243 hr
= IDWriteFontSet1_GetPropertyValues(fontset
, 0, 100, &exists
, &values
);
10244 ok(FAILED(hr
), "Unexpected hr %#lx.\n", hr
);
10245 ok(!exists
&& !values
, "Unexpected return value.\n");
10247 /* Invalid index. */
10249 values
= (void *)0xdeadbeef;
10250 hr
= IDWriteFontSet1_GetPropertyValues(fontset
, count
, DWRITE_FONT_PROPERTY_ID_POSTSCRIPT_NAME
, &exists
, &values
);
10251 ok(FAILED(hr
), "Unexpected hr %#lx.\n", hr
);
10252 ok(!exists
&& !values
, "Unexpected return value.\n");
10255 values
= (void *)0xdeadbeef;
10256 hr
= IDWriteFontSet1_GetPropertyValues(fontset
, count
, 100, &exists
, &values
);
10257 ok(FAILED(hr
), "Unexpected hr %#lx.\n", hr
);
10258 ok(!exists
&& !values
, "Unexpected return value.\n");
10260 hr
= IDWriteFontSet1_GetPropertyValues(fontset
, 0, DWRITE_FONT_PROPERTY_ID_POSTSCRIPT_NAME
, &exists
, &values
);
10261 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
10262 ok(exists
== !!values
, "Unexpected return value.\n");
10265 hr
= IDWriteLocalizedStrings_GetString(values
, 0, buffW
, ARRAY_SIZE(buffW
));
10266 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
10267 IDWriteLocalizedStrings_Release(values
);
10270 hr
= IDWriteFontSet1_CreateFontResource(fontset
, 100, &resource
);
10271 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
10273 hr
= IDWriteFontSet1_CreateFontResource(fontset
, 0, &resource
);
10274 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
10275 IDWriteFontResource_Release(resource
);
10277 IDWriteFontSet1_Release(fontset2
);
10278 IDWriteFontSet1_Release(fontset
);
10280 IDWriteFontFamily2_Release(family2
);
10283 win_skip("IDWriteFontFamily2 is not supported.\n");
10285 IDWriteFontFamily_Release(family
);
10286 IDWriteFontCollection_Release(collection
);
10288 refcount
= IDWriteFactory_Release(factory
);
10289 ok(!refcount
, "Unexpected factory refcount %u.\n", refcount
);
10292 static void test_system_font_set(void)
10294 IDWriteFontSet
*fontset
, *filtered_set
;
10295 IDWriteFontFaceReference
*ref
;
10296 IDWriteFontFace3
*fontface
;
10297 IDWriteFactory3
*factory
;
10298 DWRITE_FONT_PROPERTY p
;
10299 unsigned int count
;
10302 if (!(factory
= create_factory_iid(&IID_IDWriteFactory3
)))
10304 win_skip("System font set is not supported.\n");
10308 hr
= IDWriteFactory3_GetSystemFontSet(factory
, &fontset
);
10309 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
10311 count
= IDWriteFontSet_GetFontCount(fontset
);
10312 ok(!!count
, "Unexpected font count %u.\n", count
);
10314 p
.propertyId
= DWRITE_FONT_PROPERTY_ID_FULL_NAME
;
10315 p
.propertyValue
= L
"Tahoma";
10316 p
.localeName
= L
"";
10317 hr
= IDWriteFontSet_GetMatchingFonts(fontset
, &p
, 1, &filtered_set
);
10318 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
10319 count
= IDWriteFontSet_GetFontCount(filtered_set
);
10320 ok(!!count
, "Unexpected font count %u.\n", count
);
10322 hr
= IDWriteFontSet_GetFontFaceReference(filtered_set
, 0, &ref
);
10323 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
10325 hr
= IDWriteFontFaceReference_CreateFontFace(ref
, &fontface
);
10326 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
10328 IDWriteFontFace3_Release(fontface
);
10329 IDWriteFontFaceReference_Release(ref
);
10331 IDWriteFontSet_Release(filtered_set
);
10333 IDWriteFontSet_Release(fontset
);
10335 IDWriteFactory3_Release(factory
);
10338 static void test_CreateFontCollectionFromFontSet(void)
10340 unsigned int index
, count
, refcount
;
10341 IDWriteFontCollection1
*collection
;
10342 IDWriteFontSetBuilder1
*builder
;
10343 DWRITE_FONT_PROPERTY props
[1];
10344 IDWriteFontFaceReference
*ref
;
10345 IDWriteFactory5
*factory
;
10346 IDWriteFontSet
*fontset
;
10347 IDWriteFontFile
*file
;
10352 if (!(factory
= create_factory_iid(&IID_IDWriteFactory5
)))
10354 win_skip("_CreateFontCollectionFromFontSet() is not available.\n");
10358 hr
= IDWriteFactory5_CreateFontSetBuilder(factory
, &builder
);
10359 ok(hr
== S_OK
, "Failed to create font set builder, hr %#lx.\n", hr
);
10361 path
= create_testfontfile(test_fontfile
);
10363 hr
= IDWriteFactory5_CreateFontFileReference(factory
, path
, NULL
, &file
);
10364 ok(hr
== S_OK
, "Unexpected hr %#lx.\n",hr
);
10366 hr
= IDWriteFontSetBuilder1_AddFontFile(builder
, file
);
10367 ok(hr
== S_OK
, "Unexpected hr %#lx.\n",hr
);
10369 /* Add same file, with explicit properties. */
10370 hr
= IDWriteFactory5_CreateFontFaceReference_(factory
, file
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &ref
);
10371 ok(hr
== S_OK
, "Unexpected hr %#lx.\n",hr
);
10372 props
[0].propertyId
= DWRITE_FONT_PROPERTY_ID_WEIGHT_STRETCH_STYLE_FAMILY_NAME
;
10373 props
[0].propertyValue
= L
"Another Font";
10374 props
[0].localeName
= L
"en-US";
10375 hr
= IDWriteFontSetBuilder1_AddFontFaceReference_(builder
, ref
, props
, 1);
10377 ok(hr
== S_OK
, "Unexpected hr %#lx.\n",hr
);
10378 IDWriteFontFaceReference_Release(ref
);
10380 hr
= IDWriteFontSetBuilder1_CreateFontSet(builder
, &fontset
);
10381 ok(hr
== S_OK
, "Unexpected hr %#lx.\n",hr
);
10383 hr
= IDWriteFactory5_CreateFontCollectionFromFontSet(factory
, fontset
, &collection
);
10385 ok(hr
== S_OK
, "Unexpected hr %#lx.\n",hr
);
10389 count
= IDWriteFontCollection1_GetFontFamilyCount(collection
);
10390 ok(count
== 2, "Unexpected family count %u.\n", count
);
10392 /* Explicit fontset properties are prioritized and not replaced by actual properties from a file. */
10394 hr
= IDWriteFontCollection1_FindFamilyName(collection
, L
"Another Font", &index
, &exists
);
10395 ok(hr
== S_OK
, "Unexpected hr %#lx.\n",hr
);
10396 ok(!!exists
, "Unexpected return value %d.\n", exists
);
10398 IDWriteFontCollection1_Release(collection
);
10400 IDWriteFontSet_Release(fontset
);
10402 IDWriteFontSetBuilder1_Release(builder
);
10404 IDWriteFontFile_Release(file
);
10405 refcount
= IDWriteFactory5_Release(factory
);
10406 ok(!refcount
, "Unexpected factory refcount %u.\n", refcount
);
10407 DELETE_FONTFILE(path
);
10410 static void test_GetMatchingFontsByLOGFONT(void)
10412 IDWriteFontSet
*systemset
, *set
;
10413 IDWriteGdiInterop1
*interop
;
10414 IDWriteGdiInterop
*interop0
;
10415 IDWriteFactory3
*factory
;
10416 ULONG refcount
, count
;
10420 factory
= create_factory_iid(&IID_IDWriteFactory3
);
10423 win_skip("Skipping GetMatchingFontsByLOGFONT() tests.\n");
10427 hr
= IDWriteFactory3_GetSystemFontSet(factory
, &systemset
);
10428 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
10431 hr
= IDWriteFactory3_GetGdiInterop(factory
, &interop0
);
10432 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
10434 hr
= IDWriteGdiInterop_QueryInterface(interop0
, &IID_IDWriteGdiInterop1
, (void **)&interop
);
10435 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
10436 IDWriteGdiInterop_Release(interop0
);
10438 memset(&logfont
, 0, sizeof(logfont
));
10439 logfont
.lfHeight
= 12;
10440 logfont
.lfWidth
= 12;
10441 logfont
.lfWeight
= FW_BOLD
;
10442 logfont
.lfItalic
= 1;
10443 lstrcpyW(logfont
.lfFaceName
, L
"tahoma");
10445 hr
= IDWriteGdiInterop1_GetMatchingFontsByLOGFONT(interop
, NULL
, systemset
, &set
);
10446 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
10448 hr
= IDWriteGdiInterop1_GetMatchingFontsByLOGFONT(interop
, &logfont
, NULL
, &set
);
10449 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
10451 hr
= IDWriteGdiInterop1_GetMatchingFontsByLOGFONT(interop
, &logfont
, systemset
, &set
);
10452 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
10454 count
= IDWriteFontSet_GetFontCount(set
);
10455 ok(count
> 0, "Unexpected count %lu.\n", count
);
10457 IDWriteFontSet_Release(set
);
10459 IDWriteGdiInterop1_Release(interop
);
10460 IDWriteFontSet_Release(systemset
);
10462 refcount
= IDWriteFactory3_Release(factory
);
10463 ok(!refcount
, "Factory wasn't released, %lu.\n", refcount
);
10468 IDWriteFactory
*factory
;
10470 if (!(factory
= create_factory())) {
10471 win_skip("failed to create factory\n");
10475 test_object_lifetime();
10476 test_CreateFontFromLOGFONT();
10477 test_CreateBitmapRenderTarget();
10478 test_GetFontFamily();
10479 test_GetFamilyNames();
10480 test_CreateFontFace();
10482 test_system_fontcollection();
10483 test_ConvertFontFaceToLOGFONT();
10484 test_CustomFontCollection();
10485 test_CreateCustomFontFileReference();
10486 test_CreateFontFileReference();
10487 test_shared_isolated();
10488 test_GetUnicodeRanges();
10489 test_GetFontFromFontFace();
10490 test_GetFirstMatchingFont();
10491 test_GetMatchingFonts();
10492 test_GetInformationalStrings();
10493 test_GetGdiInterop();
10494 test_CreateFontFaceFromHdc();
10495 test_GetSimulations();
10496 test_GetFaceNames();
10497 test_TryGetFontTable();
10498 test_ConvertFontToLOGFONT();
10499 test_CreateStreamFromKey();
10500 test_ReadFileFragment();
10501 test_GetDesignGlyphMetrics();
10502 test_GetDesignGlyphAdvances();
10503 test_IsMonospacedFont();
10504 test_GetGlyphRunOutline();
10505 test_GetEudcFontCollection();
10506 test_GetCaretMetrics();
10507 test_GetGlyphCount();
10508 test_GetKerningPairAdjustments();
10509 test_CreateRenderingParams();
10510 test_CreateGlyphRunAnalysis();
10511 test_GetGdiCompatibleMetrics();
10513 test_GetGdiCompatibleGlyphAdvances();
10514 test_GetRecommendedRenderingMode();
10515 test_GetAlphaBlendParams();
10516 test_CreateAlphaTexture();
10517 test_IsSymbolFont();
10518 test_GetPaletteEntries();
10519 test_TranslateColorGlyphRun();
10520 test_HasCharacter();
10521 test_CreateFontFaceReference();
10522 test_GetFontSignature();
10523 test_font_properties();
10524 test_HasVerticalGlyphVariants();
10525 test_HasKerningPairs();
10526 test_ComputeGlyphOrigins();
10527 test_inmemory_file_loader();
10528 test_GetGlyphImageFormats();
10529 test_CreateCustomRenderingParams();
10530 test_localfontfileloader();
10531 test_AnalyzeContainerType();
10532 test_fontsetbuilder();
10533 test_font_resource();
10534 test_IsColorFont();
10535 test_GetVerticalGlyphVariants();
10536 test_expiration_event();
10537 test_family_font_set();
10538 test_system_font_set();
10539 test_CreateFontCollectionFromFontSet();
10540 test_GetMatchingFontsByLOGFONT();
10542 IDWriteFactory_Release(factory
);