4 * Copyright 2012, 2014-2017 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_0S2_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 EXPECT_HR(hr,hr_exp) \
75 ok(hr == hr_exp, "got 0x%08x, expected 0x%08x\n", hr, hr_exp)
77 #define DEFINE_EXPECT(func) \
78 static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
80 #define SET_EXPECT(func) \
81 do { called_ ## func = FALSE; expect_ ## func = TRUE; } while(0)
83 #define CHECK_EXPECT2(func) \
85 ok(expect_ ##func, "unexpected call " #func "\n"); \
86 called_ ## func = TRUE; \
89 #define CHECK_EXPECT(func) \
91 CHECK_EXPECT2(func); \
92 expect_ ## func = FALSE; \
95 #define CHECK_CALLED(func) \
97 ok(called_ ## func, "expected " #func "\n"); \
98 expect_ ## func = called_ ## func = FALSE; \
101 #define CLEAR_CALLED(func) \
102 expect_ ## func = called_ ## func = FALSE
104 DEFINE_EXPECT(setfillmode
);
106 #define EXPECT_REF(obj,ref) _expect_ref((IUnknown*)obj, ref, __LINE__)
107 static void _expect_ref(IUnknown
* obj
, ULONG ref
, int line
)
110 IUnknown_AddRef(obj
);
111 rc
= IUnknown_Release(obj
);
112 ok_(__FILE__
,line
)(rc
== ref
, "expected refcount %d, got %d\n", ref
, rc
);
115 #define EXPECT_REF_BROKEN(obj,ref,brokenref) _expect_ref_broken((IUnknown*)obj, ref, brokenref, __LINE__)
116 static void _expect_ref_broken(IUnknown
* obj
, ULONG ref
, ULONG brokenref
, int line
)
119 IUnknown_AddRef(obj
);
120 rc
= IUnknown_Release(obj
);
121 ok_(__FILE__
,line
)(rc
== ref
|| broken(rc
== brokenref
), "expected refcount %d, got %d\n", ref
, rc
);
124 static inline void* __WINE_ALLOC_SIZE(1) heap_alloc(size_t size
)
126 return HeapAlloc(GetProcessHeap(), 0, size
);
129 static inline BOOL
heap_free(void *mem
)
131 return HeapFree(GetProcessHeap(), 0, mem
);
134 static const WCHAR test_fontfile
[] = {'w','i','n','e','_','t','e','s','t','_','f','o','n','t','.','t','t','f',0};
135 static const WCHAR tahomaW
[] = {'T','a','h','o','m','a',0};
136 static const WCHAR arialW
[] = {'A','r','i','a','l',0};
137 static const WCHAR tahomaUppercaseW
[] = {'T','A','H','O','M','A',0};
138 static const WCHAR tahomaStrangecaseW
[] = {'t','A','h','O','m','A',0};
139 static const WCHAR blahW
[] = {'B','l','a','h','!',0};
140 static const WCHAR emojiW
[] = {'S','e','g','o','e',' ','U','I',' ','E','m','o','j','i',0};
142 /* PANOSE is 10 bytes in size, need to pack the structure properly */
143 #include "pshpack2.h"
160 USHORT lowestRecPPEM
;
161 SHORT direction_hint
;
163 SHORT glyphdata_format
;
166 enum TT_HEAD_MACSTYLE
168 TT_HEAD_MACSTYLE_BOLD
= 1 << 0,
169 TT_HEAD_MACSTYLE_ITALIC
= 1 << 1,
170 TT_HEAD_MACSTYLE_UNDERLINE
= 1 << 2,
171 TT_HEAD_MACSTYLE_OUTLINE
= 1 << 3,
172 TT_HEAD_MACSTYLE_SHADOW
= 1 << 4,
173 TT_HEAD_MACSTYLE_CONDENSED
= 1 << 5,
174 TT_HEAD_MACSTYLE_EXTENDED
= 1 << 6,
181 USHORT usWeightClass
;
184 SHORT ySubscriptXSize
;
185 SHORT ySubscriptYSize
;
186 SHORT ySubscriptXOffset
;
187 SHORT ySubscriptYOffset
;
188 SHORT ySuperscriptXSize
;
189 SHORT ySuperscriptYSize
;
190 SHORT ySuperscriptXOffset
;
191 SHORT ySuperscriptYOffset
;
192 SHORT yStrikeoutSize
;
193 SHORT yStrikeoutPosition
;
196 ULONG ulUnicodeRange1
;
197 ULONG ulUnicodeRange2
;
198 ULONG ulUnicodeRange3
;
199 ULONG ulUnicodeRange4
;
202 USHORT usFirstCharIndex
;
203 USHORT usLastCharIndex
;
204 /* According to the Apple spec, original version didn't have the below fields,
205 * version numbers were taken from the OpenType spec.
207 /* version 0 (TrueType 1.5) */
208 USHORT sTypoAscender
;
209 USHORT sTypoDescender
;
213 /* version 1 (TrueType 1.66) */
214 ULONG ulCodePageRange1
;
215 ULONG ulCodePageRange2
;
216 /* version 2 (OpenType 1.2) */
219 USHORT usDefaultChar
;
224 enum OS2_FSSELECTION
{
225 OS2_FSSELECTION_ITALIC
= 1 << 0,
226 OS2_FSSELECTION_UNDERSCORE
= 1 << 1,
227 OS2_FSSELECTION_NEGATIVE
= 1 << 2,
228 OS2_FSSELECTION_OUTLINED
= 1 << 3,
229 OS2_FSSELECTION_STRIKEOUT
= 1 << 4,
230 OS2_FSSELECTION_BOLD
= 1 << 5,
231 OS2_FSSELECTION_REGULAR
= 1 << 6,
232 OS2_FSSELECTION_USE_TYPO_METRICS
= 1 << 7,
233 OS2_FSSELECTION_WWS
= 1 << 8,
234 OS2_FSSELECTION_OBLIQUE
= 1 << 9
240 SHORT underlinePosition
;
241 SHORT underlineThickness
;
255 USHORT advanceWidthMax
;
256 SHORT minLeftSideBearing
;
257 SHORT minRightSideBearing
;
259 SHORT caretSlopeRise
;
263 SHORT metricDataFormat
;
264 USHORT numberOfHMetrics
;
281 OT_FeatureRecord FeatureRecord
[1];
287 WORD LookupListIndex
[1];
306 } GSUB_SingleSubstFormat1
;
313 } GSUB_SingleSubstFormat2
;
317 WORD ExtensionLookupType
;
318 DWORD ExtensionOffset
;
319 } GSUB_ExtensionPosFormat1
;
325 DWORD strikeOffset
[1];
331 DWORD glyphDataOffsets
[1];
352 DWORD indexSubTableArrayOffset
;
353 DWORD indexTablesSize
;
354 DWORD numberofIndexSubTables
;
356 sbitLineMetrics hori
;
357 sbitLineMetrics vert
;
358 WORD startGlyphIndex
;
364 } CBLCBitmapSizeTable
;
383 ULONG metaOrigLength
;
396 ULONG totalCompressedSize
;
401 ULONG metaOrigLength
;
408 static void *create_factory_iid(REFIID riid
)
410 IUnknown
*factory
= NULL
;
411 DWriteCreateFactory(DWRITE_FACTORY_TYPE_ISOLATED
, riid
, &factory
);
415 static IDWriteFactory
*create_factory(void)
417 IDWriteFactory
*factory
= create_factory_iid(&IID_IDWriteFactory
);
418 ok(factory
!= NULL
, "Failed to create factory.\n");
422 static IDWriteFontFace
*create_fontface(IDWriteFactory
*factory
)
424 static const WCHAR tahomaW
[] = {'T','a','h','o','m','a',0};
425 IDWriteGdiInterop
*interop
;
426 IDWriteFontFace
*fontface
;
431 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop
);
432 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
434 memset(&logfont
, 0, sizeof(logfont
));
435 logfont
.lfHeight
= 12;
436 logfont
.lfWidth
= 12;
437 logfont
.lfWeight
= FW_NORMAL
;
438 logfont
.lfItalic
= 1;
439 lstrcpyW(logfont
.lfFaceName
, tahomaW
);
441 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font
);
442 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
444 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
445 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
447 IDWriteFont_Release(font
);
448 IDWriteGdiInterop_Release(interop
);
453 static IDWriteFont
*get_font(IDWriteFactory
*factory
, const WCHAR
*name
, DWRITE_FONT_STYLE style
)
455 IDWriteFontCollection
*collection
;
456 IDWriteFontFamily
*family
;
457 IDWriteFont
*font
= NULL
;
462 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &collection
, FALSE
);
463 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
467 hr
= IDWriteFontCollection_FindFamilyName(collection
, name
, &index
, &exists
);
468 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
469 if (!exists
) goto not_found
;
471 hr
= IDWriteFontCollection_GetFontFamily(collection
, index
, &family
);
472 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
474 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
,
475 DWRITE_FONT_STRETCH_NORMAL
, style
, &font
);
476 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
478 IDWriteFontFamily_Release(family
);
480 IDWriteFontCollection_Release(collection
);
484 static IDWriteFont
*get_tahoma_instance(IDWriteFactory
*factory
, DWRITE_FONT_STYLE style
)
486 IDWriteFont
*font
= get_font(factory
, tahomaW
, style
);
487 ok(font
!= NULL
, "failed to get Tahoma\n");
491 static WCHAR
*create_testfontfile(const WCHAR
*filename
)
493 static WCHAR pathW
[MAX_PATH
];
499 GetTempPathW(sizeof(pathW
)/sizeof(WCHAR
), pathW
);
500 lstrcatW(pathW
, filename
);
502 file
= CreateFileW(pathW
, GENERIC_READ
|GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, 0);
503 ok(file
!= INVALID_HANDLE_VALUE
, "file creation failed, at %s, error %d\n", wine_dbgstr_w(pathW
),
506 res
= FindResourceA(GetModuleHandleA(NULL
), (LPCSTR
)MAKEINTRESOURCE(1), (LPCSTR
)RT_RCDATA
);
507 ok( res
!= 0, "couldn't find resource\n" );
508 ptr
= LockResource( LoadResource( GetModuleHandleA(NULL
), res
));
509 WriteFile( file
, ptr
, SizeofResource( GetModuleHandleA(NULL
), res
), &written
, NULL
);
510 ok( written
== SizeofResource( GetModuleHandleA(NULL
), res
), "couldn't write resource\n" );
516 #define DELETE_FONTFILE(filename) _delete_testfontfile(filename, __LINE__)
517 static void _delete_testfontfile(const WCHAR
*filename
, int line
)
519 BOOL ret
= DeleteFileW(filename
);
520 ok_(__FILE__
,line
)(ret
, "failed to delete file %s, error %d\n", wine_dbgstr_w(filename
), GetLastError());
523 struct test_fontenumerator
525 IDWriteFontFileEnumerator IDWriteFontFileEnumerator_iface
;
529 IDWriteFontFile
*font_file
;
532 static inline struct test_fontenumerator
*impl_from_IDWriteFontFileEnumerator(IDWriteFontFileEnumerator
* iface
)
534 return CONTAINING_RECORD(iface
, struct test_fontenumerator
, IDWriteFontFileEnumerator_iface
);
537 static HRESULT WINAPI
singlefontfileenumerator_QueryInterface(IDWriteFontFileEnumerator
*iface
, REFIID riid
, void **obj
)
539 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFontFileEnumerator
))
542 IDWriteFontFileEnumerator_AddRef(iface
);
545 return E_NOINTERFACE
;
548 static ULONG WINAPI
singlefontfileenumerator_AddRef(IDWriteFontFileEnumerator
*iface
)
550 struct test_fontenumerator
*This
= impl_from_IDWriteFontFileEnumerator(iface
);
551 return InterlockedIncrement(&This
->ref
);
554 static ULONG WINAPI
singlefontfileenumerator_Release(IDWriteFontFileEnumerator
*iface
)
556 struct test_fontenumerator
*This
= impl_from_IDWriteFontFileEnumerator(iface
);
557 ULONG ref
= InterlockedDecrement(&This
->ref
);
559 IDWriteFontFile_Release(This
->font_file
);
565 static HRESULT WINAPI
singlefontfileenumerator_GetCurrentFontFile(IDWriteFontFileEnumerator
*iface
, IDWriteFontFile
**font_file
)
567 struct test_fontenumerator
*This
= impl_from_IDWriteFontFileEnumerator(iface
);
568 IDWriteFontFile_AddRef(This
->font_file
);
569 *font_file
= This
->font_file
;
573 static HRESULT WINAPI
singlefontfileenumerator_MoveNext(IDWriteFontFileEnumerator
*iface
, BOOL
*current
)
575 struct test_fontenumerator
*This
= impl_from_IDWriteFontFileEnumerator(iface
);
577 if (This
->index
> 1) {
587 static const struct IDWriteFontFileEnumeratorVtbl singlefontfileenumeratorvtbl
=
589 singlefontfileenumerator_QueryInterface
,
590 singlefontfileenumerator_AddRef
,
591 singlefontfileenumerator_Release
,
592 singlefontfileenumerator_MoveNext
,
593 singlefontfileenumerator_GetCurrentFontFile
596 static HRESULT
create_enumerator(IDWriteFontFile
*font_file
, IDWriteFontFileEnumerator
**ret
)
598 struct test_fontenumerator
*enumerator
;
600 enumerator
= heap_alloc(sizeof(struct test_fontenumerator
));
602 return E_OUTOFMEMORY
;
604 enumerator
->IDWriteFontFileEnumerator_iface
.lpVtbl
= &singlefontfileenumeratorvtbl
;
606 enumerator
->index
= 0;
607 enumerator
->font_file
= font_file
;
608 IDWriteFontFile_AddRef(font_file
);
610 *ret
= &enumerator
->IDWriteFontFileEnumerator_iface
;
614 struct test_fontcollectionloader
616 IDWriteFontCollectionLoader IDWriteFontFileCollectionLoader_iface
;
617 IDWriteFontFileLoader
*loader
;
620 static inline struct test_fontcollectionloader
*impl_from_IDWriteFontFileCollectionLoader(IDWriteFontCollectionLoader
* iface
)
622 return CONTAINING_RECORD(iface
, struct test_fontcollectionloader
, IDWriteFontFileCollectionLoader_iface
);
625 static HRESULT WINAPI
resourcecollectionloader_QueryInterface(IDWriteFontCollectionLoader
*iface
, REFIID riid
, void **obj
)
627 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFontCollectionLoader
))
630 IDWriteFontCollectionLoader_AddRef(iface
);
633 return E_NOINTERFACE
;
636 static ULONG WINAPI
resourcecollectionloader_AddRef(IDWriteFontCollectionLoader
*iface
)
641 static ULONG WINAPI
resourcecollectionloader_Release(IDWriteFontCollectionLoader
*iface
)
646 static HRESULT WINAPI
resourcecollectionloader_CreateEnumeratorFromKey(IDWriteFontCollectionLoader
*iface
, IDWriteFactory
*factory
,
647 const void * collectionKey
, UINT32 collectionKeySize
, IDWriteFontFileEnumerator
** fontFileEnumerator
)
649 struct test_fontcollectionloader
*This
= impl_from_IDWriteFontFileCollectionLoader(iface
);
650 IDWriteFontFile
*font_file
;
653 hr
= IDWriteFactory_CreateCustomFontFileReference(factory
, collectionKey
, collectionKeySize
, This
->loader
, &font_file
);
654 ok(hr
== S_OK
, "Failed to create custom file reference, hr %#x.\n", hr
);
656 hr
= create_enumerator(font_file
, fontFileEnumerator
);
657 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
659 IDWriteFontFile_Release(font_file
);
663 static const struct IDWriteFontCollectionLoaderVtbl resourcecollectionloadervtbl
= {
664 resourcecollectionloader_QueryInterface
,
665 resourcecollectionloader_AddRef
,
666 resourcecollectionloader_Release
,
667 resourcecollectionloader_CreateEnumeratorFromKey
670 /* Here is a functional custom font set of interfaces */
671 struct test_fontdatastream
673 IDWriteFontFileStream IDWriteFontFileStream_iface
;
680 static inline struct test_fontdatastream
*impl_from_IDWriteFontFileStream(IDWriteFontFileStream
* iface
)
682 return CONTAINING_RECORD(iface
, struct test_fontdatastream
, IDWriteFontFileStream_iface
);
685 static HRESULT WINAPI
fontdatastream_QueryInterface(IDWriteFontFileStream
*iface
, REFIID riid
, void **obj
)
687 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFontFileStream
))
690 IDWriteFontFileStream_AddRef(iface
);
694 return E_NOINTERFACE
;
697 static ULONG WINAPI
fontdatastream_AddRef(IDWriteFontFileStream
*iface
)
699 struct test_fontdatastream
*This
= impl_from_IDWriteFontFileStream(iface
);
700 ULONG ref
= InterlockedIncrement(&This
->ref
);
704 static ULONG WINAPI
fontdatastream_Release(IDWriteFontFileStream
*iface
)
706 struct test_fontdatastream
*This
= impl_from_IDWriteFontFileStream(iface
);
707 ULONG ref
= InterlockedDecrement(&This
->ref
);
709 HeapFree(GetProcessHeap(), 0, This
);
713 static HRESULT WINAPI
fontdatastream_ReadFileFragment(IDWriteFontFileStream
*iface
, void const **fragment_start
, UINT64 offset
, UINT64 fragment_size
, void **fragment_context
)
715 struct test_fontdatastream
*This
= impl_from_IDWriteFontFileStream(iface
);
716 *fragment_context
= NULL
;
717 if (offset
+fragment_size
> This
->size
)
719 *fragment_start
= NULL
;
724 *fragment_start
= (BYTE
*)This
->data
+ offset
;
729 static void WINAPI
fontdatastream_ReleaseFileFragment(IDWriteFontFileStream
*iface
, void *fragment_context
)
734 static HRESULT WINAPI
fontdatastream_GetFileSize(IDWriteFontFileStream
*iface
, UINT64
*size
)
736 struct test_fontdatastream
*This
= impl_from_IDWriteFontFileStream(iface
);
741 static HRESULT WINAPI
fontdatastream_GetLastWriteTime(IDWriteFontFileStream
*iface
, UINT64
*last_writetime
)
746 static const IDWriteFontFileStreamVtbl fontdatastreamvtbl
=
748 fontdatastream_QueryInterface
,
749 fontdatastream_AddRef
,
750 fontdatastream_Release
,
751 fontdatastream_ReadFileFragment
,
752 fontdatastream_ReleaseFileFragment
,
753 fontdatastream_GetFileSize
,
754 fontdatastream_GetLastWriteTime
757 static HRESULT
create_fontdatastream(LPVOID data
, UINT size
, IDWriteFontFileStream
** iface
)
759 struct test_fontdatastream
*This
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct test_fontdatastream
));
761 return E_OUTOFMEMORY
;
766 This
->IDWriteFontFileStream_iface
.lpVtbl
= &fontdatastreamvtbl
;
768 *iface
= &This
->IDWriteFontFileStream_iface
;
772 static HRESULT WINAPI
resourcefontfileloader_QueryInterface(IDWriteFontFileLoader
*iface
, REFIID riid
, void **obj
)
774 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFontFileLoader
))
780 return E_NOINTERFACE
;
783 static ULONG WINAPI
resourcefontfileloader_AddRef(IDWriteFontFileLoader
*iface
)
788 static ULONG WINAPI
resourcefontfileloader_Release(IDWriteFontFileLoader
*iface
)
793 static HRESULT WINAPI
resourcefontfileloader_CreateStreamFromKey(IDWriteFontFileLoader
*iface
, const void *ref_key
, UINT32 key_size
,
794 IDWriteFontFileStream
**stream
)
800 mem
= LoadResource(GetModuleHandleA(NULL
), *(HRSRC
*)ref_key
);
801 ok(mem
!= NULL
, "Failed to lock font resource\n");
804 size
= SizeofResource(GetModuleHandleA(NULL
), *(HRSRC
*)ref_key
);
805 data
= LockResource(mem
);
806 return create_fontdatastream(data
, size
, stream
);
811 static const struct IDWriteFontFileLoaderVtbl resourcefontfileloadervtbl
= {
812 resourcefontfileloader_QueryInterface
,
813 resourcefontfileloader_AddRef
,
814 resourcefontfileloader_Release
,
815 resourcefontfileloader_CreateStreamFromKey
818 static IDWriteFontFileLoader rloader
= { &resourcefontfileloadervtbl
};
820 static D2D1_POINT_2F g_startpoints
[2];
821 static int g_startpoint_count
;
823 static HRESULT WINAPI
test_geometrysink_QueryInterface(ID2D1SimplifiedGeometrySink
*iface
, REFIID riid
, void **ret
)
825 if (IsEqualIID(riid
, &IID_ID2D1SimplifiedGeometrySink
) ||
826 IsEqualIID(riid
, &IID_IUnknown
))
829 ID2D1SimplifiedGeometrySink_AddRef(iface
);
834 return E_NOINTERFACE
;
837 static ULONG WINAPI
test_geometrysink_AddRef(ID2D1SimplifiedGeometrySink
*iface
)
842 static ULONG WINAPI
test_geometrysink_Release(ID2D1SimplifiedGeometrySink
*iface
)
847 static void WINAPI
test_geometrysink_SetFillMode(ID2D1SimplifiedGeometrySink
*iface
, D2D1_FILL_MODE mode
)
849 CHECK_EXPECT(setfillmode
);
850 ok(mode
== D2D1_FILL_MODE_WINDING
, "fill mode %d\n", mode
);
853 static void WINAPI
test_geometrysink_SetSegmentFlags(ID2D1SimplifiedGeometrySink
*iface
, D2D1_PATH_SEGMENT flags
)
855 ok(0, "unexpected SetSegmentFlags() - flags %d\n", flags
);
858 static void WINAPI
test_geometrysink_BeginFigure(ID2D1SimplifiedGeometrySink
*iface
,
859 D2D1_POINT_2F startPoint
, D2D1_FIGURE_BEGIN figureBegin
)
861 ok(figureBegin
== D2D1_FIGURE_BEGIN_FILLED
, "begin figure %d\n", figureBegin
);
862 if (g_startpoint_count
< sizeof(g_startpoints
)/sizeof(g_startpoints
[0]))
863 g_startpoints
[g_startpoint_count
] = startPoint
;
864 g_startpoint_count
++;
867 static void WINAPI
test_geometrysink_AddLines(ID2D1SimplifiedGeometrySink
*iface
,
868 const D2D1_POINT_2F
*points
, UINT32 count
)
872 static void WINAPI
test_geometrysink_AddBeziers(ID2D1SimplifiedGeometrySink
*iface
,
873 const D2D1_BEZIER_SEGMENT
*beziers
, UINT32 count
)
877 static void WINAPI
test_geometrysink_EndFigure(ID2D1SimplifiedGeometrySink
*iface
, D2D1_FIGURE_END figureEnd
)
879 ok(figureEnd
== D2D1_FIGURE_END_CLOSED
, "end figure %d\n", figureEnd
);
882 static HRESULT WINAPI
test_geometrysink_Close(ID2D1SimplifiedGeometrySink
*iface
)
884 ok(0, "unexpected Close()\n");
888 static const ID2D1SimplifiedGeometrySinkVtbl test_geometrysink_vtbl
= {
889 test_geometrysink_QueryInterface
,
890 test_geometrysink_AddRef
,
891 test_geometrysink_Release
,
892 test_geometrysink_SetFillMode
,
893 test_geometrysink_SetSegmentFlags
,
894 test_geometrysink_BeginFigure
,
895 test_geometrysink_AddLines
,
896 test_geometrysink_AddBeziers
,
897 test_geometrysink_EndFigure
,
898 test_geometrysink_Close
901 static void WINAPI
test_geometrysink2_BeginFigure(ID2D1SimplifiedGeometrySink
*iface
,
902 D2D1_POINT_2F startPoint
, D2D1_FIGURE_BEGIN figureBegin
)
904 ok(0, "unexpected call\n");
907 static void WINAPI
test_geometrysink2_AddLines(ID2D1SimplifiedGeometrySink
*iface
,
908 const D2D1_POINT_2F
*points
, UINT32 count
)
910 ok(0, "unexpected call\n");
913 static void WINAPI
test_geometrysink2_AddBeziers(ID2D1SimplifiedGeometrySink
*iface
,
914 const D2D1_BEZIER_SEGMENT
*beziers
, UINT32 count
)
916 ok(0, "unexpected call\n");
919 static void WINAPI
test_geometrysink2_EndFigure(ID2D1SimplifiedGeometrySink
*iface
, D2D1_FIGURE_END figureEnd
)
921 ok(0, "unexpected call\n");
924 static const ID2D1SimplifiedGeometrySinkVtbl test_geometrysink2_vtbl
= {
925 test_geometrysink_QueryInterface
,
926 test_geometrysink_AddRef
,
927 test_geometrysink_Release
,
928 test_geometrysink_SetFillMode
,
929 test_geometrysink_SetSegmentFlags
,
930 test_geometrysink2_BeginFigure
,
931 test_geometrysink2_AddLines
,
932 test_geometrysink2_AddBeziers
,
933 test_geometrysink2_EndFigure
,
934 test_geometrysink_Close
937 static ID2D1SimplifiedGeometrySink test_geomsink
= { &test_geometrysink_vtbl
};
938 static ID2D1SimplifiedGeometrySink test_geomsink2
= { &test_geometrysink2_vtbl
};
940 static void test_CreateFontFromLOGFONT(void)
942 static const WCHAR tahomaspW
[] = {'T','a','h','o','m','a',' ',0};
943 IDWriteGdiInterop1
*interop1
;
944 IDWriteGdiInterop
*interop
;
945 DWRITE_FONT_WEIGHT weight
;
946 DWRITE_FONT_STYLE style
;
949 LONG weights
[][2] = {
950 {FW_NORMAL
, DWRITE_FONT_WEIGHT_NORMAL
},
951 {FW_BOLD
, DWRITE_FONT_WEIGHT_BOLD
},
952 { 0, DWRITE_FONT_WEIGHT_NORMAL
},
953 { 50, DWRITE_FONT_WEIGHT_NORMAL
},
954 {150, DWRITE_FONT_WEIGHT_NORMAL
},
955 {250, DWRITE_FONT_WEIGHT_NORMAL
},
956 {350, DWRITE_FONT_WEIGHT_NORMAL
},
957 {450, DWRITE_FONT_WEIGHT_NORMAL
},
958 {650, DWRITE_FONT_WEIGHT_BOLD
},
959 {750, DWRITE_FONT_WEIGHT_BOLD
},
960 {850, DWRITE_FONT_WEIGHT_BOLD
},
961 {950, DWRITE_FONT_WEIGHT_BOLD
},
962 {960, DWRITE_FONT_WEIGHT_BOLD
},
964 OUTLINETEXTMETRICW otm
;
965 IDWriteFactory
*factory
;
975 factory
= create_factory();
977 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop
);
978 ok(hr
== S_OK
, "got %#x\n", hr
);
981 /* null out parameter crashes this call */
982 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, NULL
, NULL
);
984 font
= (void*)0xdeadbeef;
985 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, NULL
, &font
);
986 EXPECT_HR(hr
, E_INVALIDARG
);
987 ok(font
== NULL
, "got %p\n", font
);
989 memset(&logfont
, 0, sizeof(logfont
));
990 logfont
.lfHeight
= 12;
991 logfont
.lfWidth
= 12;
992 logfont
.lfWeight
= FW_NORMAL
;
993 logfont
.lfItalic
= 1;
994 lstrcpyW(logfont
.lfFaceName
, tahomaW
);
996 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font
);
999 hfont
= CreateFontIndirectW(&logfont
);
1000 hdc
= CreateCompatibleDC(0);
1001 SelectObject(hdc
, hfont
);
1003 otm
.otmSize
= sizeof(otm
);
1004 r
= GetOutlineTextMetricsW(hdc
, otm
.otmSize
, &otm
);
1005 ok(r
, "got %d\n", r
);
1007 DeleteObject(hfont
);
1010 hr
= IDWriteFont_HasCharacter(font
, 0xd800, &exists
);
1011 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1012 ok(exists
== FALSE
, "got %d\n", exists
);
1015 hr
= IDWriteFont_HasCharacter(font
, 0x20, &exists
);
1016 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1017 ok(exists
== TRUE
, "got %d\n", exists
);
1019 /* now check properties */
1020 weight
= IDWriteFont_GetWeight(font
);
1021 ok(weight
== DWRITE_FONT_WEIGHT_NORMAL
, "got %d\n", weight
);
1023 style
= IDWriteFont_GetStyle(font
);
1024 ok(style
== DWRITE_FONT_STYLE_OBLIQUE
, "got %d\n", style
);
1025 ok(otm
.otmfsSelection
& 1, "got 0x%08x\n", otm
.otmfsSelection
);
1027 ret
= IDWriteFont_IsSymbolFont(font
);
1028 ok(!ret
, "got %d\n", ret
);
1030 IDWriteFont_Release(font
);
1033 for (i
= 0; i
< sizeof(weights
)/(2*sizeof(LONG
)); i
++)
1035 memset(&logfont
, 0, sizeof(logfont
));
1036 logfont
.lfHeight
= 12;
1037 logfont
.lfWidth
= 12;
1038 logfont
.lfWeight
= weights
[i
][0];
1039 lstrcpyW(logfont
.lfFaceName
, tahomaW
);
1041 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font
);
1042 EXPECT_HR(hr
, S_OK
);
1044 weight
= IDWriteFont_GetWeight(font
);
1045 ok(weight
== weights
[i
][1],
1046 "%d: got %d, expected %d\n", i
, weight
, weights
[i
][1]);
1048 IDWriteFont_Release(font
);
1051 /* weight not from enum */
1052 memset(&logfont
, 0, sizeof(logfont
));
1053 logfont
.lfHeight
= 12;
1054 logfont
.lfWidth
= 12;
1055 logfont
.lfWeight
= 550;
1056 lstrcpyW(logfont
.lfFaceName
, tahomaW
);
1059 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font
);
1060 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1062 weight
= IDWriteFont_GetWeight(font
);
1063 ok(weight
== DWRITE_FONT_WEIGHT_NORMAL
|| weight
== DWRITE_FONT_WEIGHT_BOLD
,
1064 "got %d\n", weight
);
1066 IDWriteFont_Release(font
);
1068 /* empty or nonexistent face name */
1069 memset(&logfont
, 0, sizeof(logfont
));
1070 logfont
.lfHeight
= 12;
1071 logfont
.lfWidth
= 12;
1072 logfont
.lfWeight
= FW_NORMAL
;
1073 lstrcpyW(logfont
.lfFaceName
, blahW
);
1075 font
= (void*)0xdeadbeef;
1076 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font
);
1077 ok(hr
== DWRITE_E_NOFONT
, "got 0x%08x\n", hr
);
1078 ok(font
== NULL
, "got %p\n", font
);
1080 /* Try with name 'Tahoma ' */
1081 memset(&logfont
, 0, sizeof(logfont
));
1082 logfont
.lfHeight
= 12;
1083 logfont
.lfWidth
= 12;
1084 logfont
.lfWeight
= FW_NORMAL
;
1085 lstrcpyW(logfont
.lfFaceName
, tahomaspW
);
1087 font
= (void*)0xdeadbeef;
1088 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font
);
1089 ok(hr
== DWRITE_E_NOFONT
, "got 0x%08x\n", hr
);
1090 ok(font
== NULL
, "got %p\n", font
);
1092 /* empty string as a facename */
1093 memset(&logfont
, 0, sizeof(logfont
));
1094 logfont
.lfHeight
= 12;
1095 logfont
.lfWidth
= 12;
1096 logfont
.lfWeight
= FW_NORMAL
;
1098 font
= (void*)0xdeadbeef;
1099 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font
);
1100 ok(hr
== DWRITE_E_NOFONT
, "got 0x%08x\n", hr
);
1101 ok(font
== NULL
, "got %p\n", font
);
1103 /* IDWriteGdiInterop1::CreateFontFromLOGFONT() */
1104 hr
= IDWriteGdiInterop_QueryInterface(interop
, &IID_IDWriteGdiInterop1
, (void**)&interop1
);
1106 memset(&logfont
, 0, sizeof(logfont
));
1107 logfont
.lfHeight
= 12;
1108 logfont
.lfWidth
= 12;
1109 logfont
.lfWeight
= FW_NORMAL
;
1110 logfont
.lfItalic
= 1;
1111 lstrcpyW(logfont
.lfFaceName
, tahomaW
);
1113 hr
= IDWriteGdiInterop1_CreateFontFromLOGFONT(interop1
, &logfont
, NULL
, &font
);
1114 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1116 IDWriteFont_Release(font
);
1117 IDWriteGdiInterop1_Release(interop1
);
1120 win_skip("IDWriteGdiInterop1 is not supported, skipping CreateFontFromLOGFONT() tests.\n");
1122 ref
= IDWriteGdiInterop_Release(interop
);
1123 ok(ref
== 0, "interop is not released, %u\n", ref
);
1124 ref
= IDWriteFactory_Release(factory
);
1125 ok(ref
== 0, "factory is not released, %u\n", ref
);
1128 static void test_CreateBitmapRenderTarget(void)
1130 IDWriteBitmapRenderTarget
*target
, *target2
;
1131 IDWriteBitmapRenderTarget1
*target1
;
1132 IDWriteRenderingParams
*params
;
1133 IDWriteGdiInterop
*interop
;
1134 IDWriteFontFace
*fontface
;
1135 IDWriteFactory
*factory
;
1136 DWRITE_GLYPH_RUN run
;
1151 factory
= create_factory();
1153 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop
);
1154 EXPECT_HR(hr
, S_OK
);
1157 hr
= IDWriteGdiInterop_CreateBitmapRenderTarget(interop
, NULL
, 0, 0, &target
);
1158 EXPECT_HR(hr
, S_OK
);
1160 if (0) /* crashes on native */
1161 hr
= IDWriteBitmapRenderTarget_GetSize(target
, NULL
);
1163 size
.cx
= size
.cy
= -1;
1164 hr
= IDWriteBitmapRenderTarget_GetSize(target
, &size
);
1165 EXPECT_HR(hr
, S_OK
);
1166 ok(size
.cx
== 0, "got %d\n", size
.cx
);
1167 ok(size
.cy
== 0, "got %d\n", size
.cy
);
1170 hr
= IDWriteGdiInterop_CreateBitmapRenderTarget(interop
, NULL
, 0, 0, &target2
);
1171 EXPECT_HR(hr
, S_OK
);
1172 ok(target
!= target2
, "got %p, %p\n", target2
, target
);
1173 IDWriteBitmapRenderTarget_Release(target2
);
1175 hdc
= IDWriteBitmapRenderTarget_GetMemoryDC(target
);
1176 ok(hdc
!= NULL
, "got %p\n", hdc
);
1179 ret
= GetGraphicsMode(hdc
);
1180 ok(ret
== GM_ADVANCED
, "got %d\n", ret
);
1182 hbm
= GetCurrentObject(hdc
, OBJ_BITMAP
);
1183 ok(hbm
!= NULL
, "got %p\n", hbm
);
1185 /* check DIB properties */
1186 ret
= GetObjectW(hbm
, sizeof(ds
), &ds
);
1187 ok(ret
== sizeof(BITMAP
), "got %d\n", ret
);
1188 ok(ds
.dsBm
.bmWidth
== 1, "got %d\n", ds
.dsBm
.bmWidth
);
1189 ok(ds
.dsBm
.bmHeight
== 1, "got %d\n", ds
.dsBm
.bmHeight
);
1190 ok(ds
.dsBm
.bmPlanes
== 1, "got %d\n", ds
.dsBm
.bmPlanes
);
1191 ok(ds
.dsBm
.bmBitsPixel
== 1, "got %d\n", ds
.dsBm
.bmBitsPixel
);
1192 ok(!ds
.dsBm
.bmBits
, "got %p\n", ds
.dsBm
.bmBits
);
1194 IDWriteBitmapRenderTarget_Release(target
);
1196 hbm
= GetCurrentObject(hdc
, OBJ_BITMAP
);
1197 ok(!hbm
, "got %p\n", hbm
);
1200 hr
= IDWriteGdiInterop_CreateBitmapRenderTarget(interop
, NULL
, 10, 5, &target
);
1201 EXPECT_HR(hr
, S_OK
);
1203 hdc
= IDWriteBitmapRenderTarget_GetMemoryDC(target
);
1204 ok(hdc
!= NULL
, "got %p\n", hdc
);
1206 /* test context settings */
1207 c
= GetTextColor(hdc
);
1208 ok(c
== RGB(0, 0, 0), "got 0x%08x\n", c
);
1209 ret
= GetBkMode(hdc
);
1210 ok(ret
== OPAQUE
, "got %d\n", ret
);
1211 c
= GetBkColor(hdc
);
1212 ok(c
== RGB(255, 255, 255), "got 0x%08x\n", c
);
1214 hbm
= GetCurrentObject(hdc
, OBJ_BITMAP
);
1215 ok(hbm
!= NULL
, "got %p\n", hbm
);
1217 /* check DIB properties */
1218 ret
= GetObjectW(hbm
, sizeof(ds
), &ds
);
1219 ok(ret
== sizeof(ds
), "got %d\n", ret
);
1220 ok(ds
.dsBm
.bmWidth
== 10, "got %d\n", ds
.dsBm
.bmWidth
);
1221 ok(ds
.dsBm
.bmHeight
== 5, "got %d\n", ds
.dsBm
.bmHeight
);
1222 ok(ds
.dsBm
.bmPlanes
== 1, "got %d\n", ds
.dsBm
.bmPlanes
);
1223 ok(ds
.dsBm
.bmBitsPixel
== 32, "got %d\n", ds
.dsBm
.bmBitsPixel
);
1224 ok(ds
.dsBm
.bmBits
!= NULL
, "got %p\n", ds
.dsBm
.bmBits
);
1226 size
.cx
= size
.cy
= -1;
1227 hr
= IDWriteBitmapRenderTarget_GetSize(target
, &size
);
1228 EXPECT_HR(hr
, S_OK
);
1229 ok(size
.cx
== 10, "got %d\n", size
.cx
);
1230 ok(size
.cy
== 5, "got %d\n", size
.cy
);
1232 /* resize to same size */
1233 hr
= IDWriteBitmapRenderTarget_Resize(target
, 10, 5);
1234 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1236 hbm2
= GetCurrentObject(hdc
, OBJ_BITMAP
);
1237 ok(hbm2
== hbm
, "got %p, %p\n", hbm2
, hbm
);
1240 hr
= IDWriteBitmapRenderTarget_Resize(target
, 5, 5);
1241 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1243 size
.cx
= size
.cy
= -1;
1244 hr
= IDWriteBitmapRenderTarget_GetSize(target
, &size
);
1245 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1246 ok(size
.cx
== 5, "got %d\n", size
.cx
);
1247 ok(size
.cy
== 5, "got %d\n", size
.cy
);
1249 hbm2
= GetCurrentObject(hdc
, OBJ_BITMAP
);
1250 ok(hbm2
!= hbm
, "got %p, %p\n", hbm2
, hbm
);
1252 hr
= IDWriteBitmapRenderTarget_Resize(target
, 20, 5);
1253 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1255 size
.cx
= size
.cy
= -1;
1256 hr
= IDWriteBitmapRenderTarget_GetSize(target
, &size
);
1257 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1258 ok(size
.cx
== 20, "got %d\n", size
.cx
);
1259 ok(size
.cy
== 5, "got %d\n", size
.cy
);
1261 hbm2
= GetCurrentObject(hdc
, OBJ_BITMAP
);
1262 ok(hbm2
!= hbm
, "got %p, %p\n", hbm2
, hbm
);
1264 hr
= IDWriteBitmapRenderTarget_Resize(target
, 1, 5);
1265 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1267 size
.cx
= size
.cy
= -1;
1268 hr
= IDWriteBitmapRenderTarget_GetSize(target
, &size
);
1269 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1270 ok(size
.cx
== 1, "got %d\n", size
.cx
);
1271 ok(size
.cy
== 5, "got %d\n", size
.cy
);
1273 hbm2
= GetCurrentObject(hdc
, OBJ_BITMAP
);
1274 ok(hbm2
!= hbm
, "got %p, %p\n", hbm2
, hbm
);
1276 ret
= GetObjectW(hbm2
, sizeof(ds
), &ds
);
1277 ok(ret
== sizeof(ds
), "got %d\n", ret
);
1278 ok(ds
.dsBm
.bmWidth
== 1, "got %d\n", ds
.dsBm
.bmWidth
);
1279 ok(ds
.dsBm
.bmHeight
== 5, "got %d\n", ds
.dsBm
.bmHeight
);
1280 ok(ds
.dsBm
.bmPlanes
== 1, "got %d\n", ds
.dsBm
.bmPlanes
);
1281 ok(ds
.dsBm
.bmBitsPixel
== 32, "got %d\n", ds
.dsBm
.bmBitsPixel
);
1282 ok(ds
.dsBm
.bmBits
!= NULL
, "got %p\n", ds
.dsBm
.bmBits
);
1284 /* empty rectangle */
1285 hr
= IDWriteBitmapRenderTarget_Resize(target
, 0, 5);
1286 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1288 size
.cx
= size
.cy
= -1;
1289 hr
= IDWriteBitmapRenderTarget_GetSize(target
, &size
);
1290 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1291 ok(size
.cx
== 0, "got %d\n", size
.cx
);
1292 ok(size
.cy
== 5, "got %d\n", size
.cy
);
1294 hbm2
= GetCurrentObject(hdc
, OBJ_BITMAP
);
1295 ok(hbm2
!= hbm
, "got %p, %p\n", hbm2
, hbm
);
1297 ret
= GetObjectW(hbm2
, sizeof(ds
), &ds
);
1298 ok(ret
== sizeof(BITMAP
), "got %d\n", ret
);
1299 ok(ds
.dsBm
.bmWidth
== 1, "got %d\n", ds
.dsBm
.bmWidth
);
1300 ok(ds
.dsBm
.bmHeight
== 1, "got %d\n", ds
.dsBm
.bmHeight
);
1301 ok(ds
.dsBm
.bmPlanes
== 1, "got %d\n", ds
.dsBm
.bmPlanes
);
1302 ok(ds
.dsBm
.bmBitsPixel
== 1, "got %d\n", ds
.dsBm
.bmBitsPixel
);
1303 ok(!ds
.dsBm
.bmBits
, "got %p\n", ds
.dsBm
.bmBits
);
1305 /* transform tests, current hdc transform is not immediately affected */
1306 if (0) /* crashes on native */
1307 hr
= IDWriteBitmapRenderTarget_GetCurrentTransform(target
, NULL
);
1309 memset(&m
, 0xcc, sizeof(m
));
1310 hr
= IDWriteBitmapRenderTarget_GetCurrentTransform(target
, &m
);
1311 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1312 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
);
1313 ok(m
.dx
== 0.0 && m
.dy
== 0.0, "got %.1f,%.1f\n", m
.dx
, m
.dy
);
1314 ret
= GetWorldTransform(hdc
, &xform
);
1315 ok(ret
, "got %d\n", ret
);
1316 ok(xform
.eM11
== 1.0 && xform
.eM22
== 1.0 && xform
.eM12
== 0.0 && xform
.eM21
== 0.0, "got wrong transform\n");
1317 ok(xform
.eDx
== 0.0 && xform
.eDy
== 0.0, "got %.1f,%.1f\n", xform
.eDx
, xform
.eDy
);
1319 memset(&m
, 0, sizeof(m
));
1320 hr
= IDWriteBitmapRenderTarget_SetCurrentTransform(target
, &m
);
1321 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1323 memset(&m
, 0xcc, sizeof(m
));
1324 hr
= IDWriteBitmapRenderTarget_GetCurrentTransform(target
, &m
);
1325 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1326 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
);
1327 ok(m
.dx
== 0.0 && m
.dy
== 0.0, "got %.1f,%.1f\n", m
.dx
, m
.dy
);
1328 ret
= GetWorldTransform(hdc
, &xform
);
1329 ok(ret
, "got %d\n", ret
);
1330 ok(xform
.eM11
== 1.0 && xform
.eM22
== 1.0 && xform
.eM12
== 0.0 && xform
.eM21
== 0.0, "got wrong transform\n");
1331 ok(xform
.eDx
== 0.0 && xform
.eDy
== 0.0, "got %.1f,%.1f\n", xform
.eDx
, xform
.eDy
);
1333 memset(&m
, 0, sizeof(m
));
1334 m
.m11
= 2.0; m
.m22
= 1.0;
1335 hr
= IDWriteBitmapRenderTarget_SetCurrentTransform(target
, &m
);
1336 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1337 ret
= GetWorldTransform(hdc
, &xform
);
1338 ok(ret
, "got %d\n", ret
);
1339 ok(xform
.eM11
== 1.0 && xform
.eM22
== 1.0 && xform
.eM12
== 0.0 && xform
.eM21
== 0.0, "got wrong transform\n");
1340 ok(xform
.eDx
== 0.0 && xform
.eDy
== 0.0, "got %.1f,%.1f\n", xform
.eDx
, xform
.eDy
);
1342 hr
= IDWriteBitmapRenderTarget_SetCurrentTransform(target
, NULL
);
1343 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1345 memset(&m
, 0xcc, sizeof(m
));
1346 hr
= IDWriteBitmapRenderTarget_GetCurrentTransform(target
, &m
);
1347 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1348 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
);
1349 ok(m
.dx
== 0.0 && m
.dy
== 0.0, "got %.1f,%.1f\n", m
.dx
, m
.dy
);
1351 /* pixels per dip */
1352 pdip
= IDWriteBitmapRenderTarget_GetPixelsPerDip(target
);
1353 ok(pdip
== 1.0, "got %.2f\n", pdip
);
1355 hr
= IDWriteBitmapRenderTarget_SetPixelsPerDip(target
, 2.0);
1356 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1358 hr
= IDWriteBitmapRenderTarget_SetPixelsPerDip(target
, -1.0);
1359 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1361 hr
= IDWriteBitmapRenderTarget_SetPixelsPerDip(target
, 0.0);
1362 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1364 pdip
= IDWriteBitmapRenderTarget_GetPixelsPerDip(target
);
1365 ok(pdip
== 2.0, "got %.2f\n", pdip
);
1367 hr
= IDWriteBitmapRenderTarget_QueryInterface(target
, &IID_IDWriteBitmapRenderTarget1
, (void**)&target1
);
1369 DWRITE_TEXT_ANTIALIAS_MODE mode
;
1371 mode
= IDWriteBitmapRenderTarget1_GetTextAntialiasMode(target1
);
1372 ok(mode
== DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE
, "got %d\n", mode
);
1374 hr
= IDWriteBitmapRenderTarget1_SetTextAntialiasMode(target1
, DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
+1);
1375 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1377 mode
= IDWriteBitmapRenderTarget1_GetTextAntialiasMode(target1
);
1378 ok(mode
== DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE
, "got %d\n", mode
);
1380 hr
= IDWriteBitmapRenderTarget1_SetTextAntialiasMode(target1
, DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
);
1381 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1383 mode
= IDWriteBitmapRenderTarget1_GetTextAntialiasMode(target1
);
1384 ok(mode
== DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
, "got %d\n", mode
);
1386 IDWriteBitmapRenderTarget1_Release(target1
);
1389 win_skip("IDWriteBitmapRenderTarget1 is not supported.\n");
1391 /* DrawGlyphRun() argument validation. */
1392 hr
= IDWriteBitmapRenderTarget_Resize(target
, 16, 16);
1393 ok(hr
== S_OK
, "Failed to resize target, hr %#x.\n", hr
);
1395 fontface
= create_fontface(factory
);
1399 hr
= IDWriteFontFace_GetGlyphIndices(fontface
, &ch
, 1, glyphs
);
1400 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1401 ok(glyphs
[0] > 0, "got %u\n", glyphs
[0]);
1402 glyphs
[1] = glyphs
[0];
1404 memset(&run
, 0, sizeof(run
));
1405 run
.fontFace
= fontface
;
1406 run
.fontEmSize
= 12.0f
;
1408 run
.glyphIndices
= glyphs
;
1410 hr
= IDWriteFactory_CreateCustomRenderingParams(factory
, 1.0f
, 0.0f
, 0.0f
, DWRITE_PIXEL_GEOMETRY_FLAT
,
1411 DWRITE_RENDERING_MODE_DEFAULT
, ¶ms
);
1412 ok(hr
== S_OK
, "Failed to create rendering params, hr %#x.\n", hr
);
1414 hr
= IDWriteBitmapRenderTarget_DrawGlyphRun(target
, 0.0f
, 0.0f
, DWRITE_MEASURING_MODE_NATURAL
,
1415 &run
, NULL
, RGB(255, 0, 0), NULL
);
1416 ok(hr
== E_INVALIDARG
, "Unexpected hr %#x.\n", hr
);
1418 hr
= IDWriteBitmapRenderTarget_DrawGlyphRun(target
, 0.0f
, 0.0f
, DWRITE_MEASURING_MODE_GDI_NATURAL
+ 1,
1419 &run
, NULL
, RGB(255, 0, 0), NULL
);
1420 ok(hr
== E_INVALIDARG
, "Unexpected hr %#x.\n", hr
);
1422 hr
= IDWriteBitmapRenderTarget_DrawGlyphRun(target
, 0.0f
, 0.0f
, DWRITE_MEASURING_MODE_GDI_NATURAL
+ 1,
1423 &run
, params
, RGB(255, 0, 0), NULL
);
1424 ok(hr
== E_INVALIDARG
|| broken(hr
== S_OK
) /* Vista */, "Unexpected hr %#x.\n", hr
);
1426 hr
= IDWriteBitmapRenderTarget_DrawGlyphRun(target
, 0.0f
, 0.0f
, DWRITE_MEASURING_MODE_GDI_NATURAL
,
1427 &run
, params
, RGB(255, 0, 0), NULL
);
1428 ok(hr
== S_OK
, "Failed to draw a run, hr %#x.\n", hr
);
1430 IDWriteRenderingParams_Release(params
);
1432 /* Zero sized target returns earlier. */
1433 hr
= IDWriteBitmapRenderTarget_Resize(target
, 0, 16);
1434 ok(hr
== S_OK
, "Failed to resize target, hr %#x.\n", hr
);
1436 hr
= IDWriteBitmapRenderTarget_DrawGlyphRun(target
, 0.0f
, 0.0f
, DWRITE_MEASURING_MODE_NATURAL
,
1437 &run
, NULL
, RGB(255, 0, 0), NULL
);
1438 ok(hr
== S_OK
, "Unexpected hr %#x.\n", hr
);
1440 hr
= IDWriteBitmapRenderTarget_DrawGlyphRun(target
, 0.0f
, 0.0f
, DWRITE_MEASURING_MODE_GDI_NATURAL
+ 1,
1441 &run
, params
, RGB(255, 0, 0), NULL
);
1442 ok(hr
== S_OK
, "Unexpected hr %#x.\n", hr
);
1444 IDWriteFontFace_Release(fontface
);
1446 ref
= IDWriteBitmapRenderTarget_Release(target
);
1447 ok(ref
== 0, "render target not released, %u\n", ref
);
1448 ref
= IDWriteGdiInterop_Release(interop
);
1449 ok(ref
== 0, "interop not released, %u\n", ref
);
1450 ref
= IDWriteFactory_Release(factory
);
1451 ok(ref
== 0, "factory not released, %u\n", ref
);
1454 static void test_GetFontFamily(void)
1456 IDWriteFontCollection
*collection
, *collection2
;
1457 IDWriteFontCollection
*syscoll
;
1458 IDWriteFontFamily
*family
, *family2
;
1459 IDWriteFontFamily1
*family1
;
1460 IDWriteGdiInterop
*interop
;
1461 IDWriteFont
*font
, *font2
;
1462 IDWriteFactory
*factory
;
1467 factory
= create_factory();
1469 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop
);
1470 EXPECT_HR(hr
, S_OK
);
1472 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &syscoll
, FALSE
);
1473 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1475 memset(&logfont
, 0, sizeof(logfont
));
1476 logfont
.lfHeight
= 12;
1477 logfont
.lfWidth
= 12;
1478 logfont
.lfWeight
= FW_NORMAL
;
1479 logfont
.lfItalic
= 1;
1480 lstrcpyW(logfont
.lfFaceName
, tahomaW
);
1482 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font
);
1483 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1485 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font2
);
1486 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1487 ok(font2
!= font
, "got %p, %p\n", font2
, font
);
1489 if (0) /* crashes on native */
1490 hr
= IDWriteFont_GetFontFamily(font
, NULL
);
1492 EXPECT_REF(font
, 1);
1493 hr
= IDWriteFont_GetFontFamily(font
, &family
);
1494 EXPECT_HR(hr
, S_OK
);
1495 EXPECT_REF(font
, 1);
1496 EXPECT_REF(family
, 2);
1498 hr
= IDWriteFont_GetFontFamily(font
, &family2
);
1499 EXPECT_HR(hr
, S_OK
);
1500 ok(family2
== family
, "got %p, previous %p\n", family2
, family
);
1501 EXPECT_REF(font
, 1);
1502 EXPECT_REF(family
, 3);
1503 IDWriteFontFamily_Release(family2
);
1505 hr
= IDWriteFont_QueryInterface(font
, &IID_IDWriteFontFamily
, (void**)&family2
);
1506 EXPECT_HR(hr
, E_NOINTERFACE
);
1507 ok(family2
== NULL
, "got %p\n", family2
);
1509 hr
= IDWriteFont_GetFontFamily(font2
, &family2
);
1510 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1511 ok(family2
!= family
, "got %p, %p\n", family2
, family
);
1514 hr
= IDWriteFontFamily_GetFontCollection(family
, &collection
);
1515 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1518 hr
= IDWriteFontFamily_GetFontCollection(family2
, &collection2
);
1519 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1520 ok(collection
== collection2
, "got %p, %p\n", collection
, collection2
);
1521 ok(collection
== syscoll
, "got %p, %p\n", collection
, syscoll
);
1523 IDWriteFont_Release(font
);
1524 IDWriteFont_Release(font2
);
1526 hr
= IDWriteFontFamily_QueryInterface(family
, &IID_IDWriteFontFamily1
, (void**)&family1
);
1528 IDWriteFontFaceReference
*ref
, *ref1
;
1529 IDWriteFontList
*fontlist
;
1530 IDWriteFont3
*font3
;
1531 IDWriteFont1
*font1
;
1533 font3
= (void*)0xdeadbeef;
1534 hr
= IDWriteFontFamily1_GetFont(family1
, ~0u, &font3
);
1535 ok(hr
== E_FAIL
, "got 0x%08x\n", hr
);
1536 ok(font3
== NULL
, "got %p\n", font3
);
1538 hr
= IDWriteFontFamily1_GetFont(family1
, 0, &font3
);
1539 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1541 hr
= IDWriteFont3_QueryInterface(font3
, &IID_IDWriteFont
, (void**)&font
);
1542 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1543 IDWriteFont_Release(font
);
1545 hr
= IDWriteFont3_QueryInterface(font3
, &IID_IDWriteFont1
, (void**)&font1
);
1546 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1547 IDWriteFont1_Release(font1
);
1549 hr
= IDWriteFontFamily1_QueryInterface(family1
, &IID_IDWriteFontList1
, (void**)&fontlist
);
1550 ok(hr
== E_NOINTERFACE
, "got 0x%08x\n", hr
);
1552 hr
= IDWriteFontFamily1_QueryInterface(family1
, &IID_IDWriteFontList
, (void**)&fontlist
);
1553 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1554 IDWriteFontList_Release(fontlist
);
1556 IDWriteFont3_Release(font3
);
1558 hr
= IDWriteFontFamily1_GetFontFaceReference(family1
, 0, &ref
);
1559 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1561 hr
= IDWriteFontFamily1_GetFontFaceReference(family1
, 0, &ref1
);
1562 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1563 ok(ref
!= ref1
, "got %p, %p\n", ref
, ref1
);
1565 IDWriteFontFaceReference_Release(ref
);
1566 IDWriteFontFaceReference_Release(ref1
);
1568 IDWriteFontFamily1_Release(family1
);
1571 win_skip("IDWriteFontFamily1 is not supported.\n");
1573 IDWriteFontCollection_Release(syscoll
);
1574 IDWriteFontCollection_Release(collection2
);
1575 IDWriteFontCollection_Release(collection
);
1576 IDWriteFontFamily_Release(family2
);
1577 IDWriteFontFamily_Release(family
);
1578 IDWriteGdiInterop_Release(interop
);
1579 ref
= IDWriteFactory_Release(factory
);
1580 ok(ref
== 0, "factory not released, %u\n", ref
);
1583 static void test_GetFamilyNames(void)
1585 IDWriteFontFamily
*family
;
1586 IDWriteLocalizedStrings
*names
, *names2
;
1587 IDWriteGdiInterop
*interop
;
1588 IDWriteFactory
*factory
;
1596 factory
= create_factory();
1598 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop
);
1599 EXPECT_HR(hr
, S_OK
);
1601 memset(&logfont
, 0, sizeof(logfont
));
1602 logfont
.lfHeight
= 12;
1603 logfont
.lfWidth
= 12;
1604 logfont
.lfWeight
= FW_NORMAL
;
1605 logfont
.lfItalic
= 1;
1606 lstrcpyW(logfont
.lfFaceName
, tahomaW
);
1608 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font
);
1609 EXPECT_HR(hr
, S_OK
);
1611 hr
= IDWriteFont_GetFontFamily(font
, &family
);
1612 EXPECT_HR(hr
, S_OK
);
1614 if (0) /* crashes on native */
1615 hr
= IDWriteFontFamily_GetFamilyNames(family
, NULL
);
1617 hr
= IDWriteFontFamily_GetFamilyNames(family
, &names
);
1618 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1619 EXPECT_REF(names
, 1);
1621 hr
= IDWriteFontFamily_GetFamilyNames(family
, &names2
);
1622 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1623 EXPECT_REF(names2
, 1);
1624 ok(names
!= names2
, "got %p, was %p\n", names2
, names
);
1626 IDWriteLocalizedStrings_Release(names2
);
1628 /* GetStringLength */
1629 if (0) /* crashes on native */
1630 hr
= IDWriteLocalizedStrings_GetStringLength(names
, 0, NULL
);
1633 hr
= IDWriteLocalizedStrings_GetStringLength(names
, 10, &len
);
1634 ok(hr
== E_FAIL
, "got 0x%08x\n", hr
);
1635 ok(len
== (UINT32
)-1, "got %u\n", len
);
1638 hr
= IDWriteLocalizedStrings_GetStringLength(names
, 0, &len
);
1639 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1640 ok(len
> 0, "got %u\n", len
);
1643 hr
= IDWriteLocalizedStrings_GetString(names
, 0, NULL
, 0);
1644 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
1646 hr
= IDWriteLocalizedStrings_GetString(names
, 10, NULL
, 0);
1647 ok(hr
== E_FAIL
, "got 0x%08x\n", hr
);
1650 hr
= IDWriteLocalizedStrings_GetString(names
, 0, NULL
, 100);
1653 hr
= IDWriteLocalizedStrings_GetString(names
, 10, buffer
, 100);
1654 ok(hr
== E_FAIL
, "got 0x%08x\n", hr
);
1655 ok(buffer
[0] == 0, "got %x\n", buffer
[0]);
1658 hr
= IDWriteLocalizedStrings_GetString(names
, 0, buffer
, len
-1);
1659 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
1660 ok(buffer
[0] == 0, "got %x\n", buffer
[0]);
1663 hr
= IDWriteLocalizedStrings_GetString(names
, 0, buffer
, len
);
1664 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
1665 ok(buffer
[0] == 0, "got %x\n", buffer
[0]);
1668 hr
= IDWriteLocalizedStrings_GetString(names
, 0, buffer
, len
+1);
1669 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1670 ok(buffer
[0] != 0, "got %x\n", buffer
[0]);
1672 IDWriteLocalizedStrings_Release(names
);
1674 IDWriteFontFamily_Release(family
);
1675 IDWriteFont_Release(font
);
1676 IDWriteGdiInterop_Release(interop
);
1677 ref
= IDWriteFactory_Release(factory
);
1678 ok(ref
== 0, "factory not released, %u\n", ref
);
1681 static void test_CreateFontFace(void)
1683 IDWriteFontFace
*fontface
, *fontface2
;
1684 IDWriteFontCollection
*collection
;
1685 DWRITE_FONT_FILE_TYPE file_type
;
1686 DWRITE_FONT_FACE_TYPE face_type
;
1687 IDWriteGdiInterop
*interop
;
1688 IDWriteFont
*font
, *font2
;
1689 IDWriteFontFamily
*family
;
1690 IDWriteFactory
*factory
;
1691 IDWriteFontFile
*file
;
1698 factory
= create_factory();
1700 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop
);
1701 EXPECT_HR(hr
, S_OK
);
1703 memset(&logfont
, 0, sizeof(logfont
));
1704 logfont
.lfHeight
= 12;
1705 logfont
.lfWidth
= 12;
1706 logfont
.lfWeight
= FW_NORMAL
;
1707 logfont
.lfItalic
= 1;
1708 lstrcpyW(logfont
.lfFaceName
, tahomaW
);
1711 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font
);
1712 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1715 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font2
);
1716 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1717 ok(font
!= font2
, "got %p, %p\n", font
, font2
);
1719 hr
= IDWriteFont_QueryInterface(font
, &IID_IDWriteFontFace
, (void**)&fontface
);
1720 ok(hr
== E_NOINTERFACE
, "got 0x%08x\n", hr
);
1722 if (0) /* crashes on native */
1723 hr
= IDWriteFont_CreateFontFace(font
, NULL
);
1726 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
1727 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1730 hr
= IDWriteFont_CreateFontFace(font
, &fontface2
);
1731 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1732 ok(fontface
== fontface2
, "got %p, was %p\n", fontface2
, fontface
);
1733 IDWriteFontFace_Release(fontface2
);
1736 hr
= IDWriteFont_CreateFontFace(font2
, &fontface2
);
1737 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1738 ok(fontface
== fontface2
, "got %p, was %p\n", fontface2
, fontface
);
1739 IDWriteFontFace_Release(fontface2
);
1741 IDWriteFont_Release(font2
);
1742 IDWriteFont_Release(font
);
1744 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFont
, (void**)&font
);
1745 ok(hr
== E_NOINTERFACE
|| broken(hr
== E_NOTIMPL
), "got 0x%08x\n", hr
);
1747 IDWriteFontFace_Release(fontface
);
1748 IDWriteGdiInterop_Release(interop
);
1750 /* Create from system collection */
1751 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &collection
, FALSE
);
1752 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1754 hr
= IDWriteFontCollection_GetFontFamily(collection
, 0, &family
);
1755 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1758 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
,
1759 DWRITE_FONT_STRETCH_NORMAL
, DWRITE_FONT_STYLE_NORMAL
, &font
);
1760 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1763 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
,
1764 DWRITE_FONT_STRETCH_NORMAL
, DWRITE_FONT_STYLE_NORMAL
, &font2
);
1765 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1766 ok(font
!= font2
, "got %p, %p\n", font
, font2
);
1769 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
1770 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1773 hr
= IDWriteFont_CreateFontFace(font2
, &fontface2
);
1774 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1775 ok(fontface
== fontface2
, "got %p, was %p\n", fontface2
, fontface
);
1777 IDWriteFontFace_Release(fontface
);
1778 IDWriteFontFace_Release(fontface2
);
1779 IDWriteFont_Release(font2
);
1780 IDWriteFont_Release(font
);
1781 IDWriteFontFamily_Release(family
);
1782 IDWriteFontCollection_Release(collection
);
1784 /* IDWriteFactory::CreateFontFace() */
1785 path
= create_testfontfile(test_fontfile
);
1786 factory
= create_factory();
1788 hr
= IDWriteFactory_CreateFontFileReference(factory
, path
, NULL
, &file
);
1789 ok(hr
== S_OK
, "got 0x%08x\n",hr
);
1792 file_type
= DWRITE_FONT_FILE_TYPE_UNKNOWN
;
1793 face_type
= DWRITE_FONT_FACE_TYPE_CFF
;
1795 hr
= IDWriteFontFile_Analyze(file
, &supported
, &file_type
, &face_type
, &count
);
1796 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1797 ok(supported
== TRUE
, "got %i\n", supported
);
1798 ok(file_type
== DWRITE_FONT_FILE_TYPE_TRUETYPE
, "got %i\n", file_type
);
1799 ok(face_type
== DWRITE_FONT_FACE_TYPE_TRUETYPE
, "got %i\n", face_type
);
1800 ok(count
== 1, "got %i\n", count
);
1802 /* invalid simulation flags */
1803 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_CFF
, 1, &file
, 0, ~0u, &fontface
);
1804 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1806 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_CFF
, 1, &file
, 0, 0xf, &fontface
);
1807 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1809 /* try mismatching face type, the one that's not supported */
1810 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_CFF
, 1, &file
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &fontface
);
1811 ok(hr
== DWRITE_E_FILEFORMAT
, "got 0x%08x\n", hr
);
1813 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_OPENTYPE_COLLECTION
, 1, &file
, 0,
1814 DWRITE_FONT_SIMULATIONS_NONE
, &fontface
);
1815 ok(hr
== DWRITE_E_FILEFORMAT
|| broken(hr
== E_FAIL
) /* < win10 */, "got 0x%08x\n", hr
);
1817 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_RAW_CFF
, 1, &file
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &fontface
);
1819 ok(hr
== DWRITE_E_UNSUPPORTEDOPERATION
|| broken(hr
== E_INVALIDARG
) /* older versions */, "got 0x%08x\n", hr
);
1821 fontface
= (void*)0xdeadbeef;
1822 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_TYPE1
, 1, &file
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &fontface
);
1823 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1824 ok(fontface
== NULL
, "got %p\n", fontface
);
1826 fontface
= (void*)0xdeadbeef;
1827 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_VECTOR
, 1, &file
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &fontface
);
1828 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1829 ok(fontface
== NULL
, "got %p\n", fontface
);
1831 fontface
= (void*)0xdeadbeef;
1832 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_BITMAP
, 1, &file
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &fontface
);
1833 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1834 ok(fontface
== NULL
, "got %p\n", fontface
);
1837 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_UNKNOWN
, 1, &file
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &fontface
);
1839 ok(hr
== S_OK
|| broken(hr
== E_INVALIDARG
) /* < win10 */, "got 0x%08x\n", hr
);
1841 ok(fontface
!= NULL
, "got %p\n", fontface
);
1842 face_type
= IDWriteFontFace_GetType(fontface
);
1843 ok(face_type
== DWRITE_FONT_FACE_TYPE_TRUETYPE
, "got %d\n", face_type
);
1844 IDWriteFontFace_Release(fontface
);
1847 IDWriteFontFile_Release(file
);
1848 IDWriteFactory_Release(factory
);
1849 DELETE_FONTFILE(path
);
1852 static void get_expected_font_metrics(IDWriteFontFace
*fontface
, DWRITE_FONT_METRICS1
*metrics
)
1854 void *os2_context
, *head_context
, *post_context
, *hhea_context
;
1855 const TT_OS2_V2
*tt_os2
;
1856 const TT_HEAD
*tt_head
;
1857 const TT_POST
*tt_post
;
1858 const TT_HHEA
*tt_hhea
;
1863 memset(metrics
, 0, sizeof(*metrics
));
1865 hr
= IDWriteFontFace_TryGetFontTable(fontface
, MS_0S2_TAG
, (const void**)&tt_os2
, &size
, &os2_context
, &exists
);
1866 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1867 hr
= IDWriteFontFace_TryGetFontTable(fontface
, MS_HEAD_TAG
, (const void**)&tt_head
, &size
, &head_context
, &exists
);
1868 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1869 hr
= IDWriteFontFace_TryGetFontTable(fontface
, MS_HHEA_TAG
, (const void**)&tt_hhea
, &size
, &hhea_context
, &exists
);
1870 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1871 hr
= IDWriteFontFace_TryGetFontTable(fontface
, MS_POST_TAG
, (const void**)&tt_post
, &size
, &post_context
, &exists
);
1872 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1875 metrics
->designUnitsPerEm
= GET_BE_WORD(tt_head
->unitsPerEm
);
1876 metrics
->glyphBoxLeft
= GET_BE_WORD(tt_head
->xMin
);
1877 metrics
->glyphBoxTop
= GET_BE_WORD(tt_head
->yMax
);
1878 metrics
->glyphBoxRight
= GET_BE_WORD(tt_head
->xMax
);
1879 metrics
->glyphBoxBottom
= GET_BE_WORD(tt_head
->yMin
);
1883 if (GET_BE_WORD(tt_os2
->fsSelection
) & OS2_FSSELECTION_USE_TYPO_METRICS
) {
1884 SHORT descent
= GET_BE_WORD(tt_os2
->sTypoDescender
);
1885 metrics
->ascent
= GET_BE_WORD(tt_os2
->sTypoAscender
);
1886 metrics
->descent
= descent
< 0 ? -descent
: 0;
1887 metrics
->lineGap
= GET_BE_WORD(tt_os2
->sTypoLineGap
);
1888 metrics
->hasTypographicMetrics
= TRUE
;
1891 metrics
->ascent
= GET_BE_WORD(tt_os2
->usWinAscent
);
1892 /* Some fonts have usWinDescent value stored as signed short, which could be wrongly
1893 interpreted as large unsigned value. */
1894 metrics
->descent
= abs((SHORT
)GET_BE_WORD(tt_os2
->usWinDescent
));
1897 SHORT descender
= (SHORT
)GET_BE_WORD(tt_hhea
->descender
);
1900 linegap
= GET_BE_WORD(tt_hhea
->ascender
) + abs(descender
) + GET_BE_WORD(tt_hhea
->linegap
) -
1901 metrics
->ascent
- metrics
->descent
;
1902 metrics
->lineGap
= linegap
> 0 ? linegap
: 0;
1906 metrics
->strikethroughPosition
= GET_BE_WORD(tt_os2
->yStrikeoutPosition
);
1907 metrics
->strikethroughThickness
= GET_BE_WORD(tt_os2
->yStrikeoutSize
);
1909 metrics
->subscriptPositionX
= GET_BE_WORD(tt_os2
->ySubscriptXOffset
);
1910 metrics
->subscriptPositionY
= -GET_BE_WORD(tt_os2
->ySubscriptYOffset
);
1911 metrics
->subscriptSizeX
= GET_BE_WORD(tt_os2
->ySubscriptXSize
);
1912 metrics
->subscriptSizeY
= GET_BE_WORD(tt_os2
->ySubscriptYSize
);
1913 metrics
->superscriptPositionX
= GET_BE_WORD(tt_os2
->ySuperscriptXOffset
);
1914 metrics
->superscriptPositionY
= GET_BE_WORD(tt_os2
->ySuperscriptYOffset
);
1915 metrics
->superscriptSizeX
= GET_BE_WORD(tt_os2
->ySuperscriptXSize
);
1916 metrics
->superscriptSizeY
= GET_BE_WORD(tt_os2
->ySuperscriptYSize
);
1920 metrics
->underlinePosition
= GET_BE_WORD(tt_post
->underlinePosition
);
1921 metrics
->underlineThickness
= GET_BE_WORD(tt_post
->underlineThickness
);
1924 if (metrics
->underlineThickness
== 0)
1925 metrics
->underlineThickness
= metrics
->designUnitsPerEm
/ 14;
1926 if (metrics
->strikethroughThickness
== 0)
1927 metrics
->strikethroughThickness
= metrics
->underlineThickness
;
1930 IDWriteFontFace_ReleaseFontTable(fontface
, os2_context
);
1932 IDWriteFontFace_ReleaseFontTable(fontface
, head_context
);
1934 IDWriteFontFace_ReleaseFontTable(fontface
, hhea_context
);
1936 IDWriteFontFace_ReleaseFontTable(fontface
, post_context
);
1939 static void check_font_metrics(const WCHAR
*nameW
, BOOL has_metrics1
, const DWRITE_FONT_METRICS
*got
,
1940 const DWRITE_FONT_METRICS1
*expected
)
1942 ok(got
->designUnitsPerEm
== expected
->designUnitsPerEm
, "font %s: designUnitsPerEm %u, expected %u\n",
1943 wine_dbgstr_w(nameW
), got
->designUnitsPerEm
, expected
->designUnitsPerEm
);
1944 ok(got
->ascent
== expected
->ascent
, "font %s: ascent %u, expected %u\n", wine_dbgstr_w(nameW
), got
->ascent
,
1946 ok(got
->descent
== expected
->descent
, "font %s: descent %u, expected %u\n", wine_dbgstr_w(nameW
), got
->descent
,
1948 ok(got
->lineGap
== expected
->lineGap
, "font %s: lineGap %d, expected %d\n", wine_dbgstr_w(nameW
), got
->lineGap
,
1950 ok(got
->underlinePosition
== expected
->underlinePosition
, "font %s: underlinePosition %d, expected %d\n",
1951 wine_dbgstr_w(nameW
), got
->underlinePosition
, expected
->underlinePosition
);
1952 ok(got
->underlineThickness
== expected
->underlineThickness
, "font %s: underlineThickness %u, "
1953 "expected %u\n", wine_dbgstr_w(nameW
), got
->underlineThickness
, expected
->underlineThickness
);
1954 ok(got
->strikethroughPosition
== expected
->strikethroughPosition
, "font %s: strikethroughPosition %d, expected %d\n",
1955 wine_dbgstr_w(nameW
), got
->strikethroughPosition
, expected
->strikethroughPosition
);
1956 ok(got
->strikethroughThickness
== expected
->strikethroughThickness
, "font %s: strikethroughThickness %u, "
1957 "expected %u\n", wine_dbgstr_w(nameW
), got
->strikethroughThickness
, expected
->strikethroughThickness
);
1960 const DWRITE_FONT_METRICS1
*m1
= (const DWRITE_FONT_METRICS1
*)got
;
1961 ok(m1
->hasTypographicMetrics
== expected
->hasTypographicMetrics
, "font %s: hasTypographicMetrics %d, "
1962 "expected %d\n", wine_dbgstr_w(nameW
), m1
->hasTypographicMetrics
, expected
->hasTypographicMetrics
);
1963 ok(m1
->glyphBoxLeft
== expected
->glyphBoxLeft
, "font %s: glyphBoxLeft %d, expected %d\n", wine_dbgstr_w(nameW
),
1964 m1
->glyphBoxLeft
, expected
->glyphBoxLeft
);
1965 ok(m1
->glyphBoxTop
== expected
->glyphBoxTop
, "font %s: glyphBoxTop %d, expected %d\n", wine_dbgstr_w(nameW
),
1966 m1
->glyphBoxTop
, expected
->glyphBoxTop
);
1967 ok(m1
->glyphBoxRight
== expected
->glyphBoxRight
, "font %s: glyphBoxRight %d, expected %d\n", wine_dbgstr_w(nameW
),
1968 m1
->glyphBoxRight
, expected
->glyphBoxRight
);
1969 ok(m1
->glyphBoxBottom
== expected
->glyphBoxBottom
, "font %s: glyphBoxBottom %d, expected %d\n", wine_dbgstr_w(nameW
),
1970 m1
->glyphBoxBottom
, expected
->glyphBoxBottom
);
1972 ok(m1
->subscriptPositionX
== expected
->subscriptPositionX
, "font %s: subscriptPositionX %d, expected %d\n",
1973 wine_dbgstr_w(nameW
), m1
->subscriptPositionX
, expected
->subscriptPositionX
);
1974 ok(m1
->subscriptPositionY
== expected
->subscriptPositionY
, "font %s: subscriptPositionY %d, expected %d\n",
1975 wine_dbgstr_w(nameW
), m1
->subscriptPositionY
, expected
->subscriptPositionY
);
1976 ok(m1
->subscriptSizeX
== expected
->subscriptSizeX
, "font %s: subscriptSizeX %d, expected %d\n",
1977 wine_dbgstr_w(nameW
), m1
->subscriptSizeX
, expected
->subscriptSizeX
);
1978 ok(m1
->subscriptSizeY
== expected
->subscriptSizeY
, "font %s: subscriptSizeY %d, expected %d\n",
1979 wine_dbgstr_w(nameW
), m1
->subscriptSizeY
, expected
->subscriptSizeY
);
1980 ok(m1
->superscriptPositionX
== expected
->superscriptPositionX
, "font %s: superscriptPositionX %d, expected %d\n",
1981 wine_dbgstr_w(nameW
), m1
->superscriptPositionX
, expected
->superscriptPositionX
);
1982 ok(m1
->superscriptPositionY
== expected
->superscriptPositionY
, "font %s: superscriptPositionY %d, expected %d\n",
1983 wine_dbgstr_w(nameW
), m1
->superscriptPositionY
, expected
->superscriptPositionY
);
1984 ok(m1
->superscriptSizeX
== expected
->superscriptSizeX
, "font %s: superscriptSizeX %d, expected %d\n",
1985 wine_dbgstr_w(nameW
), m1
->superscriptSizeX
, expected
->superscriptSizeX
);
1986 ok(m1
->superscriptSizeY
== expected
->superscriptSizeY
, "font %s: superscriptSizeY %d, expected %d\n",
1987 wine_dbgstr_w(nameW
), m1
->superscriptSizeY
, expected
->superscriptSizeY
);
1991 static void get_enus_string(IDWriteLocalizedStrings
*strings
, WCHAR
*buff
, UINT32 size
)
1993 static const WCHAR enusW
[] = {'e','n','-','u','s',0};
1994 BOOL exists
= FALSE
;
1998 hr
= IDWriteLocalizedStrings_FindLocaleName(strings
, enusW
, &index
, &exists
);
1999 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2000 ok(exists
, "got %d\n", exists
);
2002 hr
= IDWriteLocalizedStrings_GetString(strings
, index
, buff
, size
);
2003 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2006 static void test_GetMetrics(void)
2008 DWRITE_FONT_METRICS metrics
, metrics2
;
2009 IDWriteFontCollection
*syscollection
;
2010 IDWriteGdiInterop
*interop
;
2011 IDWriteFontFace
*fontface
;
2012 IDWriteFactory
*factory
;
2013 OUTLINETEXTMETRICW otm
;
2014 IDWriteFontFile
*file
;
2015 IDWriteFont1
*font1
;
2025 factory
= create_factory();
2027 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop
);
2028 EXPECT_HR(hr
, S_OK
);
2030 memset(&logfont
, 0, sizeof(logfont
));
2031 logfont
.lfHeight
= 12;
2032 logfont
.lfWidth
= 12;
2033 logfont
.lfWeight
= FW_NORMAL
;
2034 logfont
.lfItalic
= 1;
2035 lstrcpyW(logfont
.lfFaceName
, tahomaW
);
2037 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font
);
2038 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2040 hfont
= CreateFontIndirectW(&logfont
);
2041 hdc
= CreateCompatibleDC(0);
2042 SelectObject(hdc
, hfont
);
2044 otm
.otmSize
= sizeof(otm
);
2045 ret
= GetOutlineTextMetricsW(hdc
, otm
.otmSize
, &otm
);
2046 ok(ret
, "got %d\n", ret
);
2048 DeleteObject(hfont
);
2050 if (0) /* crashes on native */
2051 IDWriteFont_GetMetrics(font
, NULL
);
2053 memset(&metrics
, 0, sizeof(metrics
));
2054 IDWriteFont_GetMetrics(font
, &metrics
);
2056 ok(metrics
.designUnitsPerEm
!= 0, "designUnitsPerEm %u\n", metrics
.designUnitsPerEm
);
2057 ok(metrics
.ascent
!= 0, "ascent %u\n", metrics
.ascent
);
2058 ok(metrics
.descent
!= 0, "descent %u\n", metrics
.descent
);
2059 ok(metrics
.lineGap
== 0, "lineGap %d\n", metrics
.lineGap
);
2060 ok(metrics
.capHeight
, "capHeight %u\n", metrics
.capHeight
);
2061 ok(metrics
.xHeight
!= 0, "xHeight %u\n", metrics
.xHeight
);
2062 ok(metrics
.underlinePosition
< 0, "underlinePosition %d\n", metrics
.underlinePosition
);
2063 ok(metrics
.underlineThickness
!= 0, "underlineThickness %u\n", metrics
.underlineThickness
);
2064 ok(metrics
.strikethroughPosition
> 0, "strikethroughPosition %d\n", metrics
.strikethroughPosition
);
2065 ok(metrics
.strikethroughThickness
!= 0, "strikethroughThickness %u\n", metrics
.strikethroughThickness
);
2067 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
2068 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2070 memset(&metrics
, 0, sizeof(metrics
));
2071 IDWriteFontFace_GetMetrics(fontface
, &metrics
);
2073 ok(metrics
.designUnitsPerEm
!= 0, "designUnitsPerEm %u\n", metrics
.designUnitsPerEm
);
2074 ok(metrics
.ascent
!= 0, "ascent %u\n", metrics
.ascent
);
2075 ok(metrics
.descent
!= 0, "descent %u\n", metrics
.descent
);
2076 ok(metrics
.lineGap
== 0, "lineGap %d\n", metrics
.lineGap
);
2077 ok(metrics
.capHeight
, "capHeight %u\n", metrics
.capHeight
);
2078 ok(metrics
.xHeight
!= 0, "xHeight %u\n", metrics
.xHeight
);
2079 ok(metrics
.underlinePosition
< 0, "underlinePosition %d\n", metrics
.underlinePosition
);
2080 ok(metrics
.underlineThickness
!= 0, "underlineThickness %u\n", metrics
.underlineThickness
);
2081 ok(metrics
.strikethroughPosition
> 0, "strikethroughPosition %d\n", metrics
.strikethroughPosition
);
2082 ok(metrics
.strikethroughThickness
!= 0, "strikethroughThickness %u\n", metrics
.strikethroughThickness
);
2084 hr
= IDWriteFont_QueryInterface(font
, &IID_IDWriteFont1
, (void**)&font1
);
2086 DWRITE_FONT_METRICS1 metrics1
;
2087 IDWriteFontFace1
*fontface1
;
2089 memset(&metrics1
, 0, sizeof(metrics1
));
2090 IDWriteFont1_GetMetrics(font1
, &metrics1
);
2092 ok(metrics1
.designUnitsPerEm
!= 0, "designUnitsPerEm %u\n", metrics1
.designUnitsPerEm
);
2093 ok(metrics1
.ascent
!= 0, "ascent %u\n", metrics1
.ascent
);
2094 ok(metrics1
.descent
!= 0, "descent %u\n", metrics1
.descent
);
2095 ok(metrics1
.lineGap
== 0, "lineGap %d\n", metrics1
.lineGap
);
2096 ok(metrics1
.capHeight
, "capHeight %u\n", metrics1
.capHeight
);
2097 ok(metrics1
.xHeight
!= 0, "xHeight %u\n", metrics1
.xHeight
);
2098 ok(metrics1
.underlinePosition
< 0, "underlinePosition %d\n", metrics1
.underlinePosition
);
2099 ok(metrics1
.underlineThickness
!= 0, "underlineThickness %u\n", metrics1
.underlineThickness
);
2100 ok(metrics1
.strikethroughPosition
> 0, "strikethroughPosition %d\n", metrics1
.strikethroughPosition
);
2101 ok(metrics1
.strikethroughThickness
!= 0, "strikethroughThickness %u\n", metrics1
.strikethroughThickness
);
2102 ok(metrics1
.glyphBoxLeft
< 0, "glyphBoxLeft %d\n", metrics1
.glyphBoxLeft
);
2103 ok(metrics1
.glyphBoxTop
> 0, "glyphBoxTop %d\n", metrics1
.glyphBoxTop
);
2104 ok(metrics1
.glyphBoxRight
> 0, "glyphBoxRight %d\n", metrics1
.glyphBoxRight
);
2105 ok(metrics1
.glyphBoxBottom
< 0, "glyphBoxBottom %d\n", metrics1
.glyphBoxBottom
);
2106 ok(metrics1
.subscriptPositionY
< 0, "subscriptPositionY %d\n", metrics1
.subscriptPositionY
);
2107 ok(metrics1
.subscriptSizeX
> 0, "subscriptSizeX %d\n", metrics1
.subscriptSizeX
);
2108 ok(metrics1
.subscriptSizeY
> 0, "subscriptSizeY %d\n", metrics1
.subscriptSizeY
);
2109 ok(metrics1
.superscriptPositionY
> 0, "superscriptPositionY %d\n", metrics1
.superscriptPositionY
);
2110 ok(metrics1
.superscriptSizeX
> 0, "superscriptSizeX %d\n", metrics1
.superscriptSizeX
);
2111 ok(metrics1
.superscriptSizeY
> 0, "superscriptSizeY %d\n", metrics1
.superscriptSizeY
);
2112 ok(!metrics1
.hasTypographicMetrics
, "hasTypographicMetrics %d\n", metrics1
.hasTypographicMetrics
);
2114 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void**)&fontface1
);
2115 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2117 memset(&metrics1
, 0, sizeof(metrics1
));
2118 IDWriteFontFace1_GetMetrics(fontface1
, &metrics1
);
2120 ok(metrics1
.designUnitsPerEm
!= 0, "designUnitsPerEm %u\n", metrics1
.designUnitsPerEm
);
2121 ok(metrics1
.ascent
!= 0, "ascent %u\n", metrics1
.ascent
);
2122 ok(metrics1
.descent
!= 0, "descent %u\n", metrics1
.descent
);
2123 ok(metrics1
.lineGap
== 0, "lineGap %d\n", metrics1
.lineGap
);
2124 ok(metrics1
.capHeight
, "capHeight %u\n", metrics1
.capHeight
);
2125 ok(metrics1
.xHeight
!= 0, "xHeight %u\n", metrics1
.xHeight
);
2126 ok(metrics1
.underlinePosition
< 0, "underlinePosition %d\n", metrics1
.underlinePosition
);
2127 ok(metrics1
.underlineThickness
!= 0, "underlineThickness %u\n", metrics1
.underlineThickness
);
2128 ok(metrics1
.strikethroughPosition
> 0, "strikethroughPosition %d\n", metrics1
.strikethroughPosition
);
2129 ok(metrics1
.strikethroughThickness
!= 0, "strikethroughThickness %u\n", metrics1
.strikethroughThickness
);
2130 ok(metrics1
.glyphBoxLeft
< 0, "glyphBoxLeft %d\n", metrics1
.glyphBoxLeft
);
2131 ok(metrics1
.glyphBoxTop
> 0, "glyphBoxTop %d\n", metrics1
.glyphBoxTop
);
2132 ok(metrics1
.glyphBoxRight
> 0, "glyphBoxRight %d\n", metrics1
.glyphBoxRight
);
2133 ok(metrics1
.glyphBoxBottom
< 0, "glyphBoxBottom %d\n", metrics1
.glyphBoxBottom
);
2134 ok(metrics1
.subscriptPositionY
< 0, "subscriptPositionY %d\n", metrics1
.subscriptPositionY
);
2135 ok(metrics1
.subscriptSizeX
> 0, "subscriptSizeX %d\n", metrics1
.subscriptSizeX
);
2136 ok(metrics1
.subscriptSizeY
> 0, "subscriptSizeY %d\n", metrics1
.subscriptSizeY
);
2137 ok(metrics1
.superscriptPositionY
> 0, "superscriptPositionY %d\n", metrics1
.superscriptPositionY
);
2138 ok(metrics1
.superscriptSizeX
> 0, "superscriptSizeX %d\n", metrics1
.superscriptSizeX
);
2139 ok(metrics1
.superscriptSizeY
> 0, "superscriptSizeY %d\n", metrics1
.superscriptSizeY
);
2140 ok(!metrics1
.hasTypographicMetrics
, "hasTypographicMetrics %d\n", metrics1
.hasTypographicMetrics
);
2142 IDWriteFontFace1_Release(fontface1
);
2143 IDWriteFont1_Release(font1
);
2146 win_skip("DWRITE_FONT_METRICS1 is not supported.\n");
2148 IDWriteFontFace_Release(fontface
);
2149 IDWriteFont_Release(font
);
2150 IDWriteGdiInterop_Release(interop
);
2152 /* bold simulation affects returned font metrics */
2153 font
= get_tahoma_instance(factory
, DWRITE_FONT_STYLE_NORMAL
);
2155 /* create regulat Tahoma with bold simulation */
2156 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
2157 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2160 hr
= IDWriteFontFace_GetFiles(fontface
, &count
, &file
);
2161 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2163 IDWriteFontFace_GetMetrics(fontface
, &metrics
);
2164 ok(IDWriteFontFace_GetSimulations(fontface
) == 0, "wrong simulations flags\n");
2165 IDWriteFontFace_Release(fontface
);
2167 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_TRUETYPE
, 1, &file
,
2168 0, DWRITE_FONT_SIMULATIONS_BOLD
, &fontface
);
2169 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2170 IDWriteFontFace_GetMetrics(fontface
, &metrics2
);
2171 ok(IDWriteFontFace_GetSimulations(fontface
) == DWRITE_FONT_SIMULATIONS_BOLD
, "wrong simulations flags\n");
2173 ok(metrics
.ascent
== metrics2
.ascent
, "got %u, %u\n", metrics2
.ascent
, metrics
.ascent
);
2174 ok(metrics
.descent
== metrics2
.descent
, "got %u, %u\n", metrics2
.descent
, metrics
.descent
);
2175 ok(metrics
.lineGap
== metrics2
.lineGap
, "got %d, %d\n", metrics2
.lineGap
, metrics
.lineGap
);
2176 ok(metrics
.capHeight
== metrics2
.capHeight
, "got %u, %u\n", metrics2
.capHeight
, metrics
.capHeight
);
2177 ok(metrics
.xHeight
== metrics2
.xHeight
, "got %u, %u\n", metrics2
.xHeight
, metrics
.xHeight
);
2178 ok(metrics
.underlinePosition
== metrics2
.underlinePosition
, "got %d, %d\n", metrics2
.underlinePosition
,
2179 metrics
.underlinePosition
);
2180 ok(metrics
.underlineThickness
== metrics2
.underlineThickness
, "got %u, %u\n", metrics2
.underlineThickness
,
2181 metrics
.underlineThickness
);
2182 ok(metrics
.strikethroughPosition
== metrics2
.strikethroughPosition
, "got %d, %d\n", metrics2
.strikethroughPosition
,
2183 metrics
.strikethroughPosition
);
2184 ok(metrics
.strikethroughThickness
== metrics2
.strikethroughThickness
, "got %u, %u\n", metrics2
.strikethroughThickness
,
2185 metrics
.strikethroughThickness
);
2187 IDWriteFontFile_Release(file
);
2188 IDWriteFontFace_Release(fontface
);
2189 IDWriteFont_Release(font
);
2191 /* test metrics for whole system collection */
2192 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &syscollection
, FALSE
);
2193 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2194 count
= IDWriteFontCollection_GetFontFamilyCount(syscollection
);
2196 for (i
= 0; i
< count
; i
++) {
2197 DWRITE_FONT_METRICS1 expected_metrics
, metrics1
;
2198 IDWriteLocalizedStrings
*names
;
2199 IDWriteFontFace1
*fontface1
;
2200 IDWriteFontFamily
*family
;
2204 hr
= IDWriteFontCollection_GetFontFamily(syscollection
, i
, &family
);
2205 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2207 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STRETCH_NORMAL
,
2208 DWRITE_FONT_STYLE_NORMAL
, &font
);
2209 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2211 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
2212 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2215 IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void**)&fontface1
);
2217 hr
= IDWriteFontFamily_GetFamilyNames(family
, &names
);
2218 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2220 get_enus_string(names
, nameW
, sizeof(nameW
)/sizeof(nameW
[0]));
2222 IDWriteLocalizedStrings_Release(names
);
2223 IDWriteFont_Release(font
);
2225 get_expected_font_metrics(fontface
, &expected_metrics
);
2227 IDWriteFontFace1_GetMetrics(fontface1
, &metrics1
);
2228 check_font_metrics(nameW
, TRUE
, (const DWRITE_FONT_METRICS
*)&metrics1
, &expected_metrics
);
2231 IDWriteFontFace_GetMetrics(fontface
, &metrics
);
2232 check_font_metrics(nameW
, FALSE
, &metrics
, &expected_metrics
);
2236 IDWriteFontFace1_Release(fontface1
);
2237 IDWriteFontFace_Release(fontface
);
2238 IDWriteFontFamily_Release(family
);
2240 IDWriteFontCollection_Release(syscollection
);
2241 ref
= IDWriteFactory_Release(factory
);
2242 ok(ref
== 0, "factory not released, %u\n", ref
);
2245 static void test_system_fontcollection(void)
2247 IDWriteFontCollection
*collection
, *coll2
;
2248 IDWriteLocalFontFileLoader
*localloader
;
2249 IDWriteFontCollection1
*collection1
;
2250 IDWriteFactory
*factory
, *factory2
;
2251 IDWriteFontFileLoader
*loader
;
2252 IDWriteFontFamily
*family
;
2253 IDWriteFontFace
*fontface
;
2254 IDWriteFontFile
*file
;
2261 factory
= create_factory();
2263 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &collection
, FALSE
);
2264 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2266 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &coll2
, FALSE
);
2267 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2268 ok(coll2
== collection
, "got %p, was %p\n", coll2
, collection
);
2269 IDWriteFontCollection_Release(coll2
);
2271 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &coll2
, TRUE
);
2272 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2273 ok(coll2
== collection
, "got %p, was %p\n", coll2
, collection
);
2274 IDWriteFontCollection_Release(coll2
);
2276 factory2
= create_factory();
2277 hr
= IDWriteFactory_GetSystemFontCollection(factory2
, &coll2
, FALSE
);
2278 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2279 ok(coll2
!= collection
, "got %p, was %p\n", coll2
, collection
);
2280 IDWriteFontCollection_Release(coll2
);
2281 IDWriteFactory_Release(factory2
);
2283 i
= IDWriteFontCollection_GetFontFamilyCount(collection
);
2284 ok(i
, "got %u\n", i
);
2287 family
= (void*)0xdeadbeef;
2288 hr
= IDWriteFontCollection_GetFontFamily(collection
, i
, &family
);
2289 ok(hr
== E_FAIL
, "got 0x%08x\n", hr
);
2290 ok(family
== NULL
, "got %p\n", family
);
2294 hr
= IDWriteFontCollection_FindFamilyName(collection
, tahomaW
, &i
, &ret
);
2295 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2296 ok(ret
, "got %d\n", ret
);
2297 ok(i
!= (UINT32
)-1, "got %u\n", i
);
2301 hr
= IDWriteFontCollection_FindFamilyName(collection
, tahomaUppercaseW
, &i
, &ret
);
2302 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2303 ok(ret
, "got %d\n", ret
);
2304 ok(i
!= (UINT32
)-1, "got %u\n", i
);
2308 hr
= IDWriteFontCollection_FindFamilyName(collection
, tahomaStrangecaseW
, &i
, &ret
);
2309 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2310 ok(ret
, "got %d\n", ret
);
2311 ok(i
!= (UINT32
)-1, "got %u\n", i
);
2313 /* get back local file loader */
2314 hr
= IDWriteFontCollection_GetFontFamily(collection
, i
, &family
);
2315 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2317 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
,
2318 DWRITE_FONT_STRETCH_NORMAL
, DWRITE_FONT_STYLE_NORMAL
, &font
);
2319 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2320 IDWriteFontFamily_Release(family
);
2322 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
2323 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2324 IDWriteFont_Release(font
);
2328 hr
= IDWriteFontFace_GetFiles(fontface
, &i
, &file
);
2329 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2330 ok(file
!= NULL
, "got %p\n", file
);
2331 IDWriteFontFace_Release(fontface
);
2333 hr
= IDWriteFontFile_GetLoader(file
, &loader
);
2334 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2335 IDWriteFontFile_Release(file
);
2337 hr
= IDWriteFontFileLoader_QueryInterface(loader
, &IID_IDWriteLocalFontFileLoader
, (void**)&localloader
);
2338 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2339 IDWriteLocalFontFileLoader_Release(localloader
);
2341 /* local loader is not registered by default */
2342 hr
= IDWriteFactory_RegisterFontFileLoader(factory
, loader
);
2343 ok(hr
== S_OK
|| broken(hr
== DWRITE_E_ALREADYREGISTERED
), "got 0x%08x\n", hr
);
2344 hr
= IDWriteFactory_UnregisterFontFileLoader(factory
, loader
);
2345 ok(hr
== S_OK
|| broken(hr
== E_INVALIDARG
), "got 0x%08x\n", hr
);
2347 /* try with a different factory */
2348 factory2
= create_factory();
2349 hr
= IDWriteFactory_RegisterFontFileLoader(factory2
, loader
);
2350 ok(hr
== S_OK
|| broken(hr
== DWRITE_E_ALREADYREGISTERED
), "got 0x%08x\n", hr
);
2351 hr
= IDWriteFactory_RegisterFontFileLoader(factory2
, loader
);
2352 ok(hr
== DWRITE_E_ALREADYREGISTERED
, "got 0x%08x\n", hr
);
2353 hr
= IDWriteFactory_UnregisterFontFileLoader(factory2
, loader
);
2354 ok(hr
== S_OK
|| broken(hr
== E_INVALIDARG
), "got 0x%08x\n", hr
);
2355 hr
= IDWriteFactory_UnregisterFontFileLoader(factory2
, loader
);
2356 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
2357 IDWriteFactory_Release(factory2
);
2359 IDWriteFontFileLoader_Release(loader
);
2363 hr
= IDWriteFontCollection_FindFamilyName(collection
, blahW
, &i
, &ret
);
2364 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2365 ok(!ret
, "got %d\n", ret
);
2366 ok(i
== (UINT32
)-1, "got %u\n", i
);
2368 hr
= IDWriteFontCollection_QueryInterface(collection
, &IID_IDWriteFontCollection1
, (void**)&collection1
);
2370 IDWriteFontSet
*fontset
, *fontset2
;
2371 IDWriteFontFamily1
*family1
;
2372 IDWriteFactory3
*factory3
;
2374 hr
= IDWriteFontCollection1_QueryInterface(collection1
, &IID_IDWriteFontCollection
, (void**)&coll2
);
2375 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2376 ok(coll2
== collection
, "got %p, %p\n", collection
, coll2
);
2377 IDWriteFontCollection_Release(coll2
);
2379 family1
= (void*)0xdeadbeef;
2380 hr
= IDWriteFontCollection1_GetFontFamily(collection1
, ~0u, &family1
);
2381 ok(hr
== E_FAIL
, "got 0x%08x\n", hr
);
2382 ok(family1
== NULL
, "got %p\n", family1
);
2384 hr
= IDWriteFontCollection1_GetFontFamily(collection1
, 0, &family1
);
2385 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2386 IDWriteFontFamily1_Release(family1
);
2388 /* system fontset */
2389 EXPECT_REF(collection1
, 2);
2390 EXPECT_REF(factory
, 2);
2391 hr
= IDWriteFontCollection1_GetFontSet(collection1
, &fontset
);
2393 ok(hr
== S_OK
, "Failed to get fontset, hr %#x.\n", hr
);
2395 EXPECT_REF(collection1
, 2);
2396 EXPECT_REF(factory
, 2);
2397 EXPECT_REF(fontset
, 1);
2399 hr
= IDWriteFontCollection1_GetFontSet(collection1
, &fontset2
);
2400 ok(hr
== S_OK
, "Failed to get fontset, hr %#x.\n", hr
);
2401 ok(fontset
!= fontset2
, "Expected new fontset instance.\n");
2402 EXPECT_REF(fontset2
, 1);
2403 IDWriteFontSet_Release(fontset2
);
2405 hr
= IDWriteFactory_QueryInterface(factory
, &IID_IDWriteFactory3
, (void **)&factory3
);
2406 ok(hr
== S_OK
, "Failed to get IDWriteFactory3 interface, hr %#x.\n", hr
);
2408 EXPECT_REF(factory
, 3);
2409 hr
= IDWriteFactory3_GetSystemFontSet(factory3
, &fontset2
);
2410 ok(hr
== S_OK
, "Failed to get system font set, hr %#x.\n", hr
);
2411 ok(fontset
!= fontset2
, "Expected new fontset instance.\n");
2412 EXPECT_REF(fontset2
, 1);
2413 EXPECT_REF(factory
, 4);
2415 IDWriteFontSet_Release(fontset2
);
2416 IDWriteFontSet_Release(fontset
);
2418 IDWriteFactory3_Release(factory3
);
2420 IDWriteFontCollection1_Release(collection1
);
2423 win_skip("IDWriteFontCollection1 is not supported.\n");
2425 ref
= IDWriteFontCollection_Release(collection
);
2426 ok(ref
== 0, "collection not released, %u\n", ref
);
2427 ref
= IDWriteFactory_Release(factory
);
2428 ok(ref
== 0, "factory not released, %u\n", ref
);
2431 static void get_logfont_from_font(IDWriteFont
*font
, LOGFONTW
*logfont
)
2433 void *os2_context
, *head_context
;
2434 IDWriteLocalizedStrings
*names
;
2435 DWRITE_FONT_SIMULATIONS sim
;
2436 IDWriteFontFace
*fontface
;
2437 const TT_OS2_V2
*tt_os2
;
2438 DWRITE_FONT_STYLE style
;
2439 const TT_HEAD
*tt_head
;
2445 /* These are rendering time properties. */
2446 logfont
->lfHeight
= 0;
2447 logfont
->lfWidth
= 0;
2448 logfont
->lfEscapement
= 0;
2449 logfont
->lfOrientation
= 0;
2450 logfont
->lfUnderline
= 0;
2451 logfont
->lfStrikeOut
= 0;
2453 logfont
->lfWeight
= 0;
2454 logfont
->lfItalic
= 0;
2456 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
2457 ok(hr
== S_OK
, "Failed to create font face, %#x\n", hr
);
2459 hr
= IDWriteFontFace_TryGetFontTable(fontface
, MS_0S2_TAG
, (const void **)&tt_os2
, &size
,
2460 &os2_context
, &exists
);
2461 ok(hr
== S_OK
, "Failed to get OS/2 table, %#x\n", hr
);
2463 hr
= IDWriteFontFace_TryGetFontTable(fontface
, MS_HEAD_TAG
, (const void **)&tt_head
, &size
,
2464 &head_context
, &exists
);
2465 ok(hr
== S_OK
, "Failed to get head table, %#x\n", hr
);
2467 sim
= IDWriteFont_GetSimulations(font
);
2470 weight
= FW_REGULAR
;
2472 USHORT usWeightClass
= GET_BE_WORD(tt_os2
->usWeightClass
);
2474 if (usWeightClass
>= 1 && usWeightClass
<= 9)
2475 usWeightClass
*= 100;
2477 if (usWeightClass
> DWRITE_FONT_WEIGHT_ULTRA_BLACK
)
2478 weight
= DWRITE_FONT_WEIGHT_ULTRA_BLACK
;
2479 else if (usWeightClass
> 0)
2480 weight
= usWeightClass
;
2483 USHORT macStyle
= GET_BE_WORD(tt_head
->macStyle
);
2484 if (macStyle
& TT_HEAD_MACSTYLE_BOLD
)
2485 weight
= DWRITE_FONT_WEIGHT_BOLD
;
2487 if (sim
& DWRITE_FONT_SIMULATIONS_BOLD
)
2488 weight
+= (FW_BOLD
- FW_REGULAR
) / 2 + 1;
2489 logfont
->lfWeight
= weight
;
2492 if (IDWriteFont_GetSimulations(font
) & DWRITE_FONT_SIMULATIONS_OBLIQUE
)
2493 logfont
->lfItalic
= 1;
2495 style
= IDWriteFont_GetStyle(font
);
2496 if (!logfont
->lfItalic
&& ((style
== DWRITE_FONT_STYLE_ITALIC
) || (style
== DWRITE_FONT_STYLE_OBLIQUE
))) {
2498 USHORT fsSelection
= GET_BE_WORD(tt_os2
->fsSelection
);
2499 logfont
->lfItalic
= !!(fsSelection
& OS2_FSSELECTION_ITALIC
);
2502 USHORT macStyle
= GET_BE_WORD(tt_head
->macStyle
);
2503 logfont
->lfItalic
= !!(macStyle
& TT_HEAD_MACSTYLE_ITALIC
);
2509 logfont
->lfFaceName
[0] = 0;
2510 hr
= IDWriteFont_GetInformationalStrings(font
, DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES
, &names
, &exists
);
2511 if (SUCCEEDED(hr
)) {
2513 static const WCHAR enusW
[] = {'e','n','-','u','s',0};
2514 WCHAR localeW
[LOCALE_NAME_MAX_LENGTH
];
2517 /* Fallback to en-us if there's no string for user locale. */
2519 if (GetSystemDefaultLocaleName(localeW
, sizeof(localeW
)/sizeof(WCHAR
)))
2520 IDWriteLocalizedStrings_FindLocaleName(names
, localeW
, &index
, &exists
);
2523 IDWriteLocalizedStrings_FindLocaleName(names
, enusW
, &index
, &exists
);
2526 IDWriteLocalizedStrings_GetString(names
, index
, logfont
->lfFaceName
, sizeof(logfont
->lfFaceName
)/sizeof(WCHAR
));
2529 IDWriteLocalizedStrings_Release(names
);
2533 IDWriteFontFace_ReleaseFontTable(fontface
, os2_context
);
2535 IDWriteFontFace_ReleaseFontTable(fontface
, head_context
);
2536 IDWriteFontFace_Release(fontface
);
2539 static void test_ConvertFontFaceToLOGFONT(void)
2541 IDWriteFontCollection
*collection
;
2542 IDWriteGdiInterop
*interop
;
2543 IDWriteFontFace
*fontface
;
2544 IDWriteFactory
*factory
;
2550 factory
= create_factory();
2552 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop
);
2553 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2555 if (0) /* crashes on native */
2557 hr
= IDWriteGdiInterop_ConvertFontFaceToLOGFONT(interop
, NULL
, NULL
);
2558 hr
= IDWriteGdiInterop_ConvertFontFaceToLOGFONT(interop
, fontface
, NULL
);
2560 memset(&logfont
, 0xcc, sizeof(logfont
));
2561 hr
= IDWriteGdiInterop_ConvertFontFaceToLOGFONT(interop
, NULL
, &logfont
);
2562 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
2563 ok(logfont
.lfFaceName
[0] == 0, "got face name %s\n", wine_dbgstr_w(logfont
.lfFaceName
));
2565 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &collection
, FALSE
);
2566 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2568 count
= IDWriteFontCollection_GetFontFamilyCount(collection
);
2569 for (i
= 0; i
< count
; i
++) {
2570 WCHAR nameW
[128], familynameW
[64], facenameW
[64];
2571 IDWriteLocalizedStrings
*names
;
2572 DWRITE_FONT_SIMULATIONS sim
;
2573 IDWriteFontFamily
*family
;
2574 UINT32 font_count
, j
;
2578 hr
= IDWriteFontCollection_GetFontFamily(collection
, i
, &family
);
2579 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2581 hr
= IDWriteFontFamily_GetFamilyNames(family
, &names
);
2582 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2584 get_enus_string(names
, familynameW
, sizeof(familynameW
)/sizeof(familynameW
[0]));
2585 IDWriteLocalizedStrings_Release(names
);
2587 font_count
= IDWriteFontFamily_GetFontCount(family
);
2589 for (j
= 0; j
< font_count
; j
++) {
2590 static const WCHAR spaceW
[] = {' ', 0};
2591 IDWriteFontFace
*fontface
;
2593 hr
= IDWriteFontFamily_GetFont(family
, j
, &font
);
2594 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2596 hr
= IDWriteFont_GetFaceNames(font
, &names
);
2597 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2599 get_enus_string(names
, facenameW
, sizeof(facenameW
)/sizeof(facenameW
[0]));
2600 IDWriteLocalizedStrings_Release(names
);
2602 lstrcpyW(nameW
, familynameW
);
2603 lstrcatW(nameW
, spaceW
);
2604 lstrcatW(nameW
, facenameW
);
2606 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
2607 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2609 memset(&logfont
, 0xcc, sizeof(logfont
));
2610 hr
= IDWriteGdiInterop_ConvertFontFaceToLOGFONT(interop
, fontface
, &logfont
);
2611 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2613 sim
= IDWriteFontFace_GetSimulations(fontface
);
2614 get_logfont_from_font(font
, &lf
);
2616 ok(logfont
.lfWeight
== lf
.lfWeight
, "%s: unexpected lfWeight %d, expected lfWeight %d, font weight %d, "
2617 "bold simulation %s\n", wine_dbgstr_w(nameW
), logfont
.lfWeight
, lf
.lfWeight
, IDWriteFont_GetWeight(font
),
2618 sim
& DWRITE_FONT_SIMULATIONS_BOLD
? "yes" : "no");
2619 ok(logfont
.lfItalic
== lf
.lfItalic
, "%s: unexpected italic flag %d, oblique simulation %s\n",
2620 wine_dbgstr_w(nameW
), logfont
.lfItalic
, sim
& DWRITE_FONT_SIMULATIONS_OBLIQUE
? "yes" : "no");
2621 ok(!lstrcmpW(logfont
.lfFaceName
, lf
.lfFaceName
), "%s: unexpected facename %s, expected %s\n",
2622 wine_dbgstr_w(nameW
), wine_dbgstr_w(logfont
.lfFaceName
), wine_dbgstr_w(lf
.lfFaceName
));
2624 ok(logfont
.lfOutPrecision
== OUT_OUTLINE_PRECIS
, "%s: unexpected output precision %d\n", wine_dbgstr_w(nameW
),
2625 logfont
.lfOutPrecision
);
2626 ok(logfont
.lfClipPrecision
== CLIP_DEFAULT_PRECIS
, "%s: unexpected clipping precision %d\n", wine_dbgstr_w(nameW
),
2627 logfont
.lfClipPrecision
);
2628 ok(logfont
.lfQuality
== DEFAULT_QUALITY
, "%s: unexpected quality %d\n", wine_dbgstr_w(nameW
), logfont
.lfQuality
);
2629 ok(logfont
.lfPitchAndFamily
== DEFAULT_PITCH
, "%s: unexpected pitch %d\n", wine_dbgstr_w(nameW
),
2630 logfont
.lfPitchAndFamily
);
2632 IDWriteFontFace_Release(fontface
);
2633 IDWriteFont_Release(font
);
2636 IDWriteFontFamily_Release(family
);
2639 IDWriteFontCollection_Release(collection
);
2640 IDWriteGdiInterop_Release(interop
);
2641 ref
= IDWriteFactory_Release(factory
);
2642 ok(ref
== 0, "factory not released, %u\n", ref
);
2645 static HRESULT WINAPI
fontfileenumerator_QueryInterface(IDWriteFontFileEnumerator
*iface
, REFIID riid
, void **obj
)
2647 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFontFileEnumerator
))
2650 IDWriteFontFileEnumerator_AddRef(iface
);
2653 return E_NOINTERFACE
;
2656 static ULONG WINAPI
fontfileenumerator_AddRef(IDWriteFontFileEnumerator
*iface
)
2661 static ULONG WINAPI
fontfileenumerator_Release(IDWriteFontFileEnumerator
*iface
)
2666 static HRESULT WINAPI
fontfileenumerator_GetCurrentFontFile(IDWriteFontFileEnumerator
*iface
, IDWriteFontFile
**file
)
2672 static HRESULT WINAPI
fontfileenumerator_MoveNext(IDWriteFontFileEnumerator
*iface
, BOOL
*current
)
2678 static const struct IDWriteFontFileEnumeratorVtbl dwritefontfileenumeratorvtbl
=
2680 fontfileenumerator_QueryInterface
,
2681 fontfileenumerator_AddRef
,
2682 fontfileenumerator_Release
,
2683 fontfileenumerator_MoveNext
,
2684 fontfileenumerator_GetCurrentFontFile
,
2687 struct collection_loader
2689 IDWriteFontCollectionLoader IDWriteFontCollectionLoader_iface
;
2693 static inline struct collection_loader
*impl_from_IDWriteFontCollectionLoader(IDWriteFontCollectionLoader
*iface
)
2695 return CONTAINING_RECORD(iface
, struct collection_loader
, IDWriteFontCollectionLoader_iface
);
2698 static HRESULT WINAPI
fontcollectionloader_QueryInterface(IDWriteFontCollectionLoader
*iface
, REFIID riid
, void **obj
)
2700 struct collection_loader
*loader
= impl_from_IDWriteFontCollectionLoader(iface
);
2702 if (IsEqualIID(&IID_IDWriteFontCollectionLoader
, riid
) ||
2703 IsEqualIID(&IID_IUnknown
, riid
))
2705 *obj
= &loader
->IDWriteFontCollectionLoader_iface
;
2706 IDWriteFontCollectionLoader_AddRef(iface
);
2711 return E_NOINTERFACE
;
2714 static ULONG WINAPI
fontcollectionloader_AddRef(IDWriteFontCollectionLoader
*iface
)
2716 struct collection_loader
*loader
= impl_from_IDWriteFontCollectionLoader(iface
);
2717 return InterlockedIncrement(&loader
->ref
);
2720 static ULONG WINAPI
fontcollectionloader_Release(IDWriteFontCollectionLoader
*iface
)
2722 struct collection_loader
*loader
= impl_from_IDWriteFontCollectionLoader(iface
);
2723 ULONG ref
= InterlockedDecrement(&loader
->ref
);
2731 static HRESULT WINAPI
fontcollectionloader_CreateEnumeratorFromKey(IDWriteFontCollectionLoader
*iface
, IDWriteFactory
*factory
, const void *key
,
2732 UINT32 key_size
, IDWriteFontFileEnumerator
**ret
)
2734 static IDWriteFontFileEnumerator enumerator
= { &dwritefontfileenumeratorvtbl
};
2739 static const struct IDWriteFontCollectionLoaderVtbl dwritefontcollectionloadervtbl
= {
2740 fontcollectionloader_QueryInterface
,
2741 fontcollectionloader_AddRef
,
2742 fontcollectionloader_Release
,
2743 fontcollectionloader_CreateEnumeratorFromKey
2746 static IDWriteFontCollectionLoader
*create_collection_loader(void)
2748 struct collection_loader
*loader
= heap_alloc(sizeof(*loader
));
2750 loader
->IDWriteFontCollectionLoader_iface
.lpVtbl
= &dwritefontcollectionloadervtbl
;
2753 return &loader
->IDWriteFontCollectionLoader_iface
;
2756 static void test_CustomFontCollection(void)
2758 static const WCHAR fontnameW
[] = {'w','i','n','e','_','t','e','s','t',0};
2759 IDWriteFontCollectionLoader
*loader
, *loader2
, *loader3
;
2760 IDWriteFontCollection
*font_collection
= NULL
;
2761 static IDWriteFontFileLoader rloader
= { &resourcefontfileloadervtbl
};
2762 struct test_fontcollectionloader resource_collection
= { { &resourcecollectionloadervtbl
}, &rloader
};
2763 IDWriteFontFamily
*family
, *family2
, *family3
;
2764 IDWriteFontFace
*idfontface
, *idfontface2
;
2765 IDWriteFontFile
*fontfile
, *fontfile2
;
2766 IDWriteLocalizedStrings
*string
;
2767 IDWriteFont
*idfont
, *idfont2
;
2768 IDWriteFactory
*factory
;
2769 UINT32 index
, count
;
2775 factory
= create_factory();
2777 loader
= create_collection_loader();
2778 loader2
= create_collection_loader();
2779 loader3
= create_collection_loader();
2781 hr
= IDWriteFactory_RegisterFontCollectionLoader(factory
, NULL
);
2782 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
2784 hr
= IDWriteFactory_UnregisterFontCollectionLoader(factory
, NULL
);
2785 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
2787 EXPECT_REF(loader
, 1);
2788 EXPECT_REF(loader2
, 1);
2790 hr
= IDWriteFactory_RegisterFontCollectionLoader(factory
, loader
);
2791 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2792 hr
= IDWriteFactory_RegisterFontCollectionLoader(factory
, loader2
);
2793 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2794 hr
= IDWriteFactory_RegisterFontCollectionLoader(factory
, loader
);
2795 ok(hr
== DWRITE_E_ALREADYREGISTERED
, "got 0x%08x\n", hr
);
2797 EXPECT_REF(loader
, 2);
2798 EXPECT_REF(loader2
, 2);
2800 hr
= IDWriteFactory_RegisterFontFileLoader(factory
, &rloader
);
2801 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2802 hr
= IDWriteFactory_RegisterFontCollectionLoader(factory
, &resource_collection
.IDWriteFontFileCollectionLoader_iface
);
2803 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2805 /* Loader wasn't registered. */
2806 font_collection
= (void*)0xdeadbeef;
2807 hr
= IDWriteFactory_CreateCustomFontCollection(factory
, loader3
, "Billy", 6, &font_collection
);
2808 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
2809 ok(font_collection
== NULL
, "got %p\n", font_collection
);
2811 EXPECT_REF(factory
, 1);
2812 hr
= IDWriteFactory_CreateCustomFontCollection(factory
, loader
, "Billy", 6, &font_collection
);
2813 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2815 EXPECT_REF(factory
, 1);
2816 EXPECT_REF(loader
, 2);
2817 IDWriteFontCollection_Release(font_collection
);
2819 hr
= IDWriteFactory_CreateCustomFontCollection(factory
, loader2
, "Billy", 6, &font_collection
);
2820 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2821 IDWriteFontCollection_Release(font_collection
);
2823 font_collection
= (void*)0xdeadbeef;
2824 hr
= IDWriteFactory_CreateCustomFontCollection(factory
, (IDWriteFontCollectionLoader
*)0xdeadbeef, "Billy", 6, &font_collection
);
2825 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
2826 ok(font_collection
== NULL
, "got %p\n", font_collection
);
2828 font
= FindResourceA(GetModuleHandleA(NULL
), (LPCSTR
)MAKEINTRESOURCE(1), (LPCSTR
)RT_RCDATA
);
2829 ok(font
!= NULL
, "Failed to find font resource\n");
2831 hr
= IDWriteFactory_CreateCustomFontCollection(factory
, &resource_collection
.IDWriteFontFileCollectionLoader_iface
,
2832 &font
, sizeof(HRSRC
), &font_collection
);
2833 ok(hr
== S_OK
, "got 0x%08x\n",hr
);
2834 EXPECT_REF(font_collection
, 1);
2838 hr
= IDWriteFontCollection_FindFamilyName(font_collection
, fontnameW
, &index
, &exists
);
2839 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2840 ok(index
== 0, "got index %i\n", index
);
2841 ok(exists
, "got exists %i\n", exists
);
2843 count
= IDWriteFontCollection_GetFontFamilyCount(font_collection
);
2844 ok(count
== 1, "got %u\n", count
);
2847 hr
= IDWriteFontCollection_GetFontFamily(font_collection
, 0, &family
);
2848 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2849 EXPECT_REF(family
, 1);
2852 hr
= IDWriteFontCollection_GetFontFamily(font_collection
, 0, &family2
);
2853 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2854 EXPECT_REF(family2
, 1);
2855 ok(family
!= family2
, "got %p, %p\n", family
, family2
);
2857 hr
= IDWriteFontFamily_GetFont(family
, 0, &idfont
);
2858 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2859 EXPECT_REF(idfont
, 1);
2860 EXPECT_REF(family
, 2);
2861 hr
= IDWriteFontFamily_GetFont(family
, 0, &idfont2
);
2862 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2863 EXPECT_REF(idfont2
, 1);
2864 EXPECT_REF(family
, 3);
2865 ok(idfont
!= idfont2
, "got %p, %p\n", idfont
, idfont2
);
2866 IDWriteFont_Release(idfont2
);
2868 hr
= IDWriteFont_GetInformationalStrings(idfont
, DWRITE_INFORMATIONAL_STRING_COPYRIGHT_NOTICE
, &string
, &exists
);
2869 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2870 ok(exists
, "got %d\n", exists
);
2871 EXPECT_REF(string
, 1);
2872 IDWriteLocalizedStrings_Release(string
);
2875 hr
= IDWriteFont_GetFontFamily(idfont
, &family3
);
2876 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2877 EXPECT_REF(family
, 3);
2878 ok(family
== family3
, "got %p, %p\n", family
, family3
);
2879 IDWriteFontFamily_Release(family3
);
2882 hr
= IDWriteFont_CreateFontFace(idfont
, &idfontface
);
2883 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2884 EXPECT_REF(idfont
, 1);
2887 hr
= IDWriteFontFamily_GetFont(family2
, 0, &idfont2
);
2888 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2889 EXPECT_REF(idfont2
, 1);
2890 EXPECT_REF(idfont
, 1);
2891 ok(idfont2
!= idfont
, "Font instances should not match\n");
2894 hr
= IDWriteFont_CreateFontFace(idfont2
, &idfontface2
);
2895 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2896 ok(idfontface2
== idfontface
, "fontfaces should match\n");
2900 hr
= IDWriteFontFace_GetFiles(idfontface
, &index
, &fontfile
);
2901 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2905 hr
= IDWriteFontFace_GetFiles(idfontface2
, &index
, &fontfile2
);
2906 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2907 ok(fontfile
== fontfile2
, "fontfiles should match\n");
2909 IDWriteFont_Release(idfont
);
2910 IDWriteFont_Release(idfont2
);
2911 IDWriteFontFile_Release(fontfile
);
2912 IDWriteFontFile_Release(fontfile2
);
2913 IDWriteFontFace_Release(idfontface
);
2914 IDWriteFontFace_Release(idfontface2
);
2915 IDWriteFontFamily_Release(family2
);
2916 IDWriteFontFamily_Release(family
);
2917 IDWriteFontCollection_Release(font_collection
);
2919 hr
= IDWriteFactory_UnregisterFontCollectionLoader(factory
, loader
);
2920 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2921 hr
= IDWriteFactory_UnregisterFontCollectionLoader(factory
, loader
);
2922 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
2923 hr
= IDWriteFactory_UnregisterFontCollectionLoader(factory
, loader2
);
2924 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2925 hr
= IDWriteFactory_UnregisterFontCollectionLoader(factory
, &resource_collection
.IDWriteFontFileCollectionLoader_iface
);
2926 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2927 hr
= IDWriteFactory_UnregisterFontFileLoader(factory
, &rloader
);
2928 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2930 IDWriteFontCollectionLoader_Release(loader
);
2931 IDWriteFontCollectionLoader_Release(loader2
);
2932 IDWriteFontCollectionLoader_Release(loader3
);
2934 ref
= IDWriteFactory_Release(factory
);
2935 ok(ref
== 0, "factory not released, %u\n", ref
);
2938 static HRESULT WINAPI
fontfileloader_QueryInterface(IDWriteFontFileLoader
*iface
, REFIID riid
, void **obj
)
2940 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFontFileLoader
))
2943 IDWriteFontFileLoader_AddRef(iface
);
2948 return E_NOINTERFACE
;
2951 static ULONG WINAPI
fontfileloader_AddRef(IDWriteFontFileLoader
*iface
)
2956 static ULONG WINAPI
fontfileloader_Release(IDWriteFontFileLoader
*iface
)
2961 static HRESULT WINAPI
fontfileloader_CreateStreamFromKey(IDWriteFontFileLoader
*iface
, const void *ref_key
, UINT32 key_size
,
2962 IDWriteFontFileStream
**stream
)
2967 static const struct IDWriteFontFileLoaderVtbl dwritefontfileloadervtbl
= {
2968 fontfileloader_QueryInterface
,
2969 fontfileloader_AddRef
,
2970 fontfileloader_Release
,
2971 fontfileloader_CreateStreamFromKey
2974 static void test_CreateCustomFontFileReference(void)
2976 IDWriteFontFileLoader floader
= { &dwritefontfileloadervtbl
};
2977 IDWriteFontFileLoader floader2
= { &dwritefontfileloadervtbl
};
2978 IDWriteFontFileLoader floader3
= { &dwritefontfileloadervtbl
};
2979 IDWriteFactory
*factory
, *factory2
;
2980 IDWriteFontFileLoader
*loader
;
2981 IDWriteFontFile
*file
, *file2
;
2983 DWRITE_FONT_FILE_TYPE file_type
;
2984 DWRITE_FONT_FACE_TYPE face_type
;
2986 IDWriteFontFace
*face
, *face2
;
2989 UINT32 codePoints
[1] = {0xa8};
2996 path
= create_testfontfile(test_fontfile
);
2998 factory
= create_factory();
2999 factory2
= create_factory();
3001 if (0) { /* crashes on win10 */
3002 hr
= IDWriteFactory_RegisterFontFileLoader(factory
, NULL
);
3003 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
3005 /* local loader is accepted too */
3006 hr
= IDWriteFactory_CreateFontFileReference(factory
, path
, NULL
, &file
);
3007 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3009 hr
= IDWriteFontFile_GetLoader(file
, &loader
);
3010 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3012 hr
= IDWriteFontFile_GetReferenceKey(file
, &key
, &key_size
);
3013 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3015 hr
= IDWriteFactory_CreateCustomFontFileReference(factory
, key
, key_size
, loader
, &file2
);
3016 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3018 IDWriteFontFile_Release(file2
);
3019 IDWriteFontFile_Release(file
);
3020 IDWriteFontFileLoader_Release(loader
);
3022 hr
= IDWriteFactory_RegisterFontFileLoader(factory
, &floader
);
3023 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3024 hr
= IDWriteFactory_RegisterFontFileLoader(factory
, &floader2
);
3025 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3026 hr
= IDWriteFactory_RegisterFontFileLoader(factory
, &floader
);
3027 ok(hr
== DWRITE_E_ALREADYREGISTERED
, "got 0x%08x\n", hr
);
3028 hr
= IDWriteFactory_RegisterFontFileLoader(factory
, &rloader
);
3029 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3032 hr
= IDWriteFactory_CreateCustomFontFileReference(factory
, "test", 4, &floader
, &file
);
3033 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3034 IDWriteFontFile_Release(file
);
3036 file
= (void*)0xdeadbeef;
3037 hr
= IDWriteFactory_CreateCustomFontFileReference(factory
, "test", 4, &floader3
, &file
);
3038 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
3039 ok(file
== NULL
, "got %p\n", file
);
3041 file
= (void*)0xdeadbeef;
3042 hr
= IDWriteFactory_CreateCustomFontFileReference(factory
, "test", 4, NULL
, &file
);
3043 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
3044 ok(file
== NULL
, "got %p\n", file
);
3047 hr
= IDWriteFactory_CreateCustomFontFileReference(factory
, "test", 4, &floader
, &file
);
3048 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3050 file_type
= DWRITE_FONT_FILE_TYPE_TRUETYPE
;
3051 face_type
= DWRITE_FONT_FACE_TYPE_TRUETYPE
;
3054 hr
= IDWriteFontFile_Analyze(file
, &support
, &file_type
, &face_type
, &count
);
3055 ok(hr
== 0x8faecafe, "got 0x%08x\n", hr
);
3056 ok(support
== FALSE
, "got %i\n", support
);
3057 ok(file_type
== DWRITE_FONT_FILE_TYPE_UNKNOWN
, "got %i\n", file_type
);
3058 ok(face_type
== DWRITE_FONT_FACE_TYPE_UNKNOWN
, "got %i\n", face_type
);
3059 ok(count
== 0, "got %i\n", count
);
3061 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_CFF
, 1, &file
, 0, 0, &face
);
3062 ok(hr
== 0x8faecafe, "got 0x%08x\n", hr
);
3063 IDWriteFontFile_Release(file
);
3065 fontrsrc
= FindResourceA(GetModuleHandleA(NULL
), (LPCSTR
)MAKEINTRESOURCE(1), (LPCSTR
)RT_RCDATA
);
3066 ok(fontrsrc
!= NULL
, "Failed to find font resource\n");
3068 hr
= IDWriteFactory_CreateCustomFontFileReference(factory
, &fontrsrc
, sizeof(HRSRC
), &rloader
, &file
);
3069 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3071 file_type
= DWRITE_FONT_FILE_TYPE_UNKNOWN
;
3072 face_type
= DWRITE_FONT_FACE_TYPE_UNKNOWN
;
3075 hr
= IDWriteFontFile_Analyze(file
, &support
, &file_type
, &face_type
, &count
);
3076 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3077 ok(support
== TRUE
, "got %i\n", support
);
3078 ok(file_type
== DWRITE_FONT_FILE_TYPE_TRUETYPE
, "got %i\n", file_type
);
3079 ok(face_type
== DWRITE_FONT_FACE_TYPE_TRUETYPE
, "got %i\n", face_type
);
3080 ok(count
== 1, "got %i\n", count
);
3083 face
= (void*)0xdeadbeef;
3084 hr
= IDWriteFactory_CreateFontFace(factory
, face_type
, 1, &file
, 1, DWRITE_FONT_SIMULATIONS_NONE
, &face
);
3085 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
3086 ok(face
== NULL
, "got %p\n", face
);
3088 hr
= IDWriteFactory_CreateFontFace(factory
, face_type
, 1, &file
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &face
);
3089 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3091 hr
= IDWriteFactory_CreateFontFace(factory
, face_type
, 1, &file
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &face2
);
3092 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3093 /* fontface instances are reused starting with win7 */
3094 ok(face
== face2
|| broken(face
!= face2
), "got %p, %p\n", face
, face2
);
3095 IDWriteFontFace_Release(face2
);
3097 /* file was created with different factory */
3099 hr
= IDWriteFactory_CreateFontFace(factory2
, face_type
, 1, &file
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &face2
);
3101 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3103 IDWriteFontFace_Release(face2
);
3106 hr
= IDWriteFactory_CreateCustomFontFileReference(factory
, &fontrsrc
, sizeof(HRSRC
), &rloader
, &file2
);
3107 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3108 ok(file
!= file2
, "got %p, %p\n", file
, file2
);
3110 hr
= IDWriteFactory_CreateFontFace(factory
, face_type
, 1, &file2
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &face2
);
3111 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3112 /* fontface instances are reused starting with win7 */
3113 ok(face
== face2
|| broken(face
!= face2
), "got %p, %p\n", face
, face2
);
3114 IDWriteFontFace_Release(face2
);
3115 IDWriteFontFile_Release(file2
);
3117 hr
= IDWriteFontFace_GetGlyphIndices(face
, NULL
, 0, NULL
);
3118 ok(hr
== E_INVALIDARG
|| broken(hr
== S_OK
) /* win8 */, "got 0x%08x\n", hr
);
3120 hr
= IDWriteFontFace_GetGlyphIndices(face
, codePoints
, 0, NULL
);
3121 ok(hr
== E_INVALIDARG
|| broken(hr
== S_OK
) /* win8 */, "got 0x%08x\n", hr
);
3123 hr
= IDWriteFontFace_GetGlyphIndices(face
, codePoints
, 0, indices
);
3124 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3126 hr
= IDWriteFontFace_GetGlyphIndices(face
, NULL
, 0, indices
);
3127 ok(hr
== E_INVALIDARG
|| broken(hr
== S_OK
) /* win8 */, "got 0x%08x\n", hr
);
3129 indices
[0] = indices
[1] = 11;
3130 hr
= IDWriteFontFace_GetGlyphIndices(face
, NULL
, 1, indices
);
3131 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
3132 ok(indices
[0] == 0, "got index %i\n", indices
[0]);
3133 ok(indices
[1] == 11, "got index %i\n", indices
[1]);
3135 if (0) /* crashes on native */
3136 hr
= IDWriteFontFace_GetGlyphIndices(face
, NULL
, 1, NULL
);
3138 hr
= IDWriteFontFace_GetGlyphIndices(face
, codePoints
, 1, indices
);
3139 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3140 ok(indices
[0] == 7, "Unexpected glyph index, %u.\n", indices
[0]);
3141 IDWriteFontFace_Release(face
);
3142 IDWriteFontFile_Release(file
);
3144 hr
= IDWriteFactory_UnregisterFontFileLoader(factory
, &floader
);
3145 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3146 hr
= IDWriteFactory_UnregisterFontFileLoader(factory
, &floader
);
3147 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
3148 hr
= IDWriteFactory_UnregisterFontFileLoader(factory
, &floader2
);
3149 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3150 hr
= IDWriteFactory_UnregisterFontFileLoader(factory
, &rloader
);
3151 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3153 ref
= IDWriteFactory_Release(factory2
);
3154 ok(ref
== 0, "factory not released, %u\n", ref
);
3155 ref
= IDWriteFactory_Release(factory
);
3156 ok(ref
== 0, "factory not released, %u\n", ref
);
3157 DELETE_FONTFILE(path
);
3160 static void test_CreateFontFileReference(void)
3163 IDWriteFontFile
*ffile
= NULL
;
3165 DWRITE_FONT_FILE_TYPE type
;
3166 DWRITE_FONT_FACE_TYPE face
;
3168 IDWriteFontFace
*fface
= NULL
;
3169 IDWriteFactory
*factory
;
3173 path
= create_testfontfile(test_fontfile
);
3174 factory
= create_factory();
3176 ffile
= (void*)0xdeadbeef;
3177 hr
= IDWriteFactory_CreateFontFileReference(factory
, NULL
, NULL
, &ffile
);
3178 ok(hr
== E_INVALIDARG
, "got 0x%08x\n",hr
);
3179 ok(ffile
== NULL
, "got %p\n", ffile
);
3181 hr
= IDWriteFactory_CreateFontFileReference(factory
, path
, NULL
, &ffile
);
3182 ok(hr
== S_OK
, "got 0x%08x\n",hr
);
3185 type
= DWRITE_FONT_FILE_TYPE_UNKNOWN
;
3186 face
= DWRITE_FONT_FACE_TYPE_CFF
;
3188 hr
= IDWriteFontFile_Analyze(ffile
, &support
, &type
, &face
, &count
);
3189 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3190 ok(support
== TRUE
, "got %i\n", support
);
3191 ok(type
== DWRITE_FONT_FILE_TYPE_TRUETYPE
, "got %i\n", type
);
3192 ok(face
== DWRITE_FONT_FACE_TYPE_TRUETYPE
, "got %i\n", face
);
3193 ok(count
== 1, "got %i\n", count
);
3195 hr
= IDWriteFactory_CreateFontFace(factory
, face
, 1, &ffile
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &fface
);
3196 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3198 IDWriteFontFace_Release(fface
);
3199 IDWriteFontFile_Release(ffile
);
3200 ref
= IDWriteFactory_Release(factory
);
3201 ok(ref
== 0, "factory not released, %u\n", ref
);
3203 DELETE_FONTFILE(path
);
3206 static void test_shared_isolated(void)
3208 IDWriteFactory
*isolated
, *isolated2
;
3209 IDWriteFactory
*shared
, *shared2
;
3215 hr
= DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED
+1, &IID_IDWriteFactory
, (IUnknown
**)&shared
);
3216 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3217 ok(shared
!= NULL
, "got %p\n", shared
);
3218 IDWriteFactory_Release(shared
);
3220 hr
= DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED
, &IID_IDWriteFactory
, (IUnknown
**)&shared
);
3221 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3223 hr
= DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED
, &IID_IDWriteFactory
, (IUnknown
**)&shared2
);
3224 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3225 ok(shared
== shared2
, "got %p, and %p\n", shared
, shared2
);
3226 IDWriteFactory_Release(shared2
);
3228 hr
= DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED
, &IID_IUnknown
, (IUnknown
**)&shared2
);
3229 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3230 ok(shared
== shared2
, "got %p, and %p\n", shared
, shared2
);
3232 IDWriteFactory_Release(shared
);
3233 IDWriteFactory_Release(shared2
);
3235 /* we got 2 references, released 2 - still same pointer is returned */
3236 hr
= DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED
, &IID_IDWriteFactory
, (IUnknown
**)&shared2
);
3237 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3238 ok(shared
== shared2
, "got %p, and %p\n", shared
, shared2
);
3239 IDWriteFactory_Release(shared2
);
3241 hr
= DWriteCreateFactory(DWRITE_FACTORY_TYPE_ISOLATED
, &IID_IDWriteFactory
, (IUnknown
**)&isolated
);
3242 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3244 hr
= DWriteCreateFactory(DWRITE_FACTORY_TYPE_ISOLATED
, &IID_IDWriteFactory
, (IUnknown
**)&isolated2
);
3245 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3246 ok(isolated
!= isolated2
, "got %p, and %p\n", isolated
, isolated2
);
3247 IDWriteFactory_Release(isolated2
);
3249 hr
= DWriteCreateFactory(DWRITE_FACTORY_TYPE_ISOLATED
, &IID_IUnknown
, (IUnknown
**)&isolated2
);
3250 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3251 IDWriteFactory_Release(isolated2
);
3253 hr
= DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED
+1, &IID_IDWriteFactory
, (IUnknown
**)&isolated2
);
3254 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3255 ok(shared
!= isolated2
, "got %p, and %p\n", shared
, isolated2
);
3257 ref
= IDWriteFactory_Release(isolated
);
3258 ok(ref
== 0, "factory not released, %u\n", ref
);
3259 ref
= IDWriteFactory_Release(isolated2
);
3260 ok(ref
== 0, "factory not released, %u\n", ref
);
3263 static void test_GetUnicodeRanges(void)
3265 DWRITE_UNICODE_RANGE
*ranges
, r
;
3266 IDWriteFontFile
*ffile
= NULL
;
3267 IDWriteFontFace1
*fontface1
;
3268 IDWriteFontFace
*fontface
;
3269 IDWriteFactory
*factory
;
3275 factory
= create_factory();
3277 hr
= IDWriteFactory_RegisterFontFileLoader(factory
, &rloader
);
3278 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3280 font
= FindResourceA(GetModuleHandleA(NULL
), (LPCSTR
)MAKEINTRESOURCE(1), (LPCSTR
)RT_RCDATA
);
3281 ok(font
!= NULL
, "Failed to find font resource\n");
3283 hr
= IDWriteFactory_CreateCustomFontFileReference(factory
, &font
, sizeof(HRSRC
), &rloader
, &ffile
);
3284 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3286 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_TRUETYPE
, 1, &ffile
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &fontface
);
3287 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3288 IDWriteFontFile_Release(ffile
);
3290 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void**)&fontface1
);
3291 IDWriteFontFace_Release(fontface
);
3293 win_skip("GetUnicodeRanges() is not supported.\n");
3294 IDWriteFactory_Release(factory
);
3299 hr
= IDWriteFontFace1_GetUnicodeRanges(fontface1
, 0, NULL
, &count
);
3300 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
3301 ok(count
> 0, "got %u\n", count
);
3304 hr
= IDWriteFontFace1_GetUnicodeRanges(fontface1
, 1, NULL
, &count
);
3305 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
3306 ok(count
== 0, "got %u\n", count
);
3309 hr
= IDWriteFontFace1_GetUnicodeRanges(fontface1
, 1, &r
, &count
);
3310 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
3311 ok(count
> 1, "got %u\n", count
);
3313 ranges
= heap_alloc(count
*sizeof(DWRITE_UNICODE_RANGE
));
3314 hr
= IDWriteFontFace1_GetUnicodeRanges(fontface1
, count
, ranges
, &count
);
3315 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3317 ranges
[0].first
= ranges
[0].last
= 0;
3318 hr
= IDWriteFontFace1_GetUnicodeRanges(fontface1
, 1, ranges
, &count
);
3319 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
3320 ok(ranges
[0].first
!= 0 && ranges
[0].last
!= 0, "got 0x%x-0x%0x\n", ranges
[0].first
, ranges
[0].last
);
3324 hr
= IDWriteFactory_UnregisterFontFileLoader(factory
, &rloader
);
3325 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3327 IDWriteFontFace1_Release(fontface1
);
3328 ref
= IDWriteFactory_Release(factory
);
3329 ok(ref
== 0, "factory not released, %u\n", ref
);
3332 static void test_GetFontFromFontFace(void)
3334 IDWriteFontFace
*fontface
, *fontface2
;
3335 IDWriteFontCollection
*collection
;
3336 IDWriteFont
*font
, *font2
, *font3
;
3337 IDWriteFontFamily
*family
;
3338 IDWriteFactory
*factory
;
3339 IDWriteFontFile
*file
;
3344 factory
= create_factory();
3346 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &collection
, FALSE
);
3347 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3349 hr
= IDWriteFontCollection_GetFontFamily(collection
, 0, &family
);
3350 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3352 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
,
3353 DWRITE_FONT_STRETCH_NORMAL
, DWRITE_FONT_STYLE_NORMAL
, &font
);
3354 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3356 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
3357 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3360 hr
= IDWriteFontCollection_GetFontFromFontFace(collection
, fontface
, &font2
);
3361 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3362 ok(font2
!= font
, "got %p, %p\n", font2
, font
);
3365 hr
= IDWriteFontCollection_GetFontFromFontFace(collection
, fontface
, &font3
);
3366 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3367 ok(font3
!= font
&& font3
!= font2
, "got %p, %p, %p\n", font3
, font2
, font
);
3369 hr
= IDWriteFont_CreateFontFace(font2
, &fontface2
);
3370 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3371 ok(fontface2
== fontface
, "got %p, %p\n", fontface2
, fontface
);
3372 IDWriteFontFace_Release(fontface2
);
3374 hr
= IDWriteFont_CreateFontFace(font3
, &fontface2
);
3375 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3376 ok(fontface2
== fontface
, "got %p, %p\n", fontface2
, fontface
);
3377 IDWriteFontFace_Release(fontface2
);
3378 IDWriteFontFace_Release(fontface
);
3379 IDWriteFont_Release(font3
);
3380 IDWriteFactory_Release(factory
);
3382 /* fontface that wasn't created from this collection */
3383 factory
= create_factory();
3384 path
= create_testfontfile(test_fontfile
);
3386 hr
= IDWriteFactory_CreateFontFileReference(factory
, path
, NULL
, &file
);
3387 ok(hr
== S_OK
, "got 0x%08x\n",hr
);
3389 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_TRUETYPE
, 1, &file
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &fontface
);
3390 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3391 IDWriteFontFile_Release(file
);
3393 hr
= IDWriteFontCollection_GetFontFromFontFace(collection
, fontface
, &font3
);
3394 ok(hr
== DWRITE_E_NOFONT
, "got 0x%08x\n", hr
);
3395 ok(font3
== NULL
, "got %p\n", font3
);
3396 IDWriteFontFace_Release(fontface
);
3398 IDWriteFont_Release(font
);
3399 IDWriteFont_Release(font2
);
3400 IDWriteFontFamily_Release(family
);
3401 IDWriteFontCollection_Release(collection
);
3402 ref
= IDWriteFactory_Release(factory
);
3403 ok(ref
== 0, "factory not released, %u\n", ref
);
3404 DELETE_FONTFILE(path
);
3407 static void test_GetFirstMatchingFont(void)
3409 DWRITE_FONT_SIMULATIONS simulations
;
3410 IDWriteFontCollection
*collection
;
3411 IDWriteFontFamily
*family
;
3412 IDWriteFont
*font
, *font2
;
3413 IDWriteFactory
*factory
;
3417 factory
= create_factory();
3419 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &collection
, FALSE
);
3420 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3422 hr
= IDWriteFontCollection_GetFontFamily(collection
, 0, &family
);
3423 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3425 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
,
3426 DWRITE_FONT_STRETCH_NORMAL
, DWRITE_FONT_STYLE_NORMAL
, &font
);
3427 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3429 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
,
3430 DWRITE_FONT_STRETCH_NORMAL
, DWRITE_FONT_STYLE_NORMAL
, &font2
);
3431 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3432 ok(font
!= font2
, "got %p, %p\n", font
, font2
);
3433 IDWriteFont_Release(font
);
3434 IDWriteFont_Release(font2
);
3436 /* out-of-range font props are allowed */
3437 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, 1000, DWRITE_FONT_STRETCH_NORMAL
, DWRITE_FONT_STYLE_NORMAL
, &font
);
3438 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3439 IDWriteFont_Release(font
);
3441 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
, 10, DWRITE_FONT_STYLE_NORMAL
, &font
);
3442 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3443 IDWriteFont_Release(font
);
3445 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STRETCH_NORMAL
,
3447 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3448 IDWriteFont_Release(font
);
3450 IDWriteFontFamily_Release(family
);
3452 font
= get_tahoma_instance(factory
, DWRITE_FONT_STYLE_ITALIC
);
3453 simulations
= IDWriteFont_GetSimulations(font
);
3454 ok(simulations
== DWRITE_FONT_SIMULATIONS_OBLIQUE
, "%d\n", simulations
);
3455 IDWriteFont_Release(font
);
3457 IDWriteFontCollection_Release(collection
);
3458 ref
= IDWriteFactory_Release(factory
);
3459 ok(ref
== 0, "factory not released, %u\n", ref
);
3462 static void test_GetMatchingFonts(void)
3464 IDWriteFontCollection
*collection
;
3465 IDWriteFontFamily
*family
;
3466 IDWriteFactory
*factory
;
3467 IDWriteFontList
*fontlist
, *fontlist2
;
3468 IDWriteFontList1
*fontlist1
;
3472 factory
= create_factory();
3474 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &collection
, FALSE
);
3475 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3477 hr
= IDWriteFontCollection_GetFontFamily(collection
, 0, &family
);
3478 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3480 /* out-of-range font props are allowed */
3481 hr
= IDWriteFontFamily_GetMatchingFonts(family
, 1000, DWRITE_FONT_STRETCH_NORMAL
,
3482 DWRITE_FONT_STYLE_NORMAL
, &fontlist
);
3483 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3484 IDWriteFontList_Release(fontlist
);
3486 hr
= IDWriteFontFamily_GetMatchingFonts(family
, DWRITE_FONT_WEIGHT_NORMAL
, 10,
3487 DWRITE_FONT_STYLE_NORMAL
, &fontlist
);
3488 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3489 IDWriteFontList_Release(fontlist
);
3491 hr
= IDWriteFontFamily_GetMatchingFonts(family
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STRETCH_NORMAL
,
3493 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3494 IDWriteFontList_Release(fontlist
);
3496 hr
= IDWriteFontFamily_GetMatchingFonts(family
, DWRITE_FONT_WEIGHT_NORMAL
,
3497 DWRITE_FONT_STRETCH_NORMAL
, DWRITE_FONT_STYLE_NORMAL
, &fontlist
);
3498 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3500 hr
= IDWriteFontFamily_GetMatchingFonts(family
, DWRITE_FONT_WEIGHT_NORMAL
,
3501 DWRITE_FONT_STRETCH_NORMAL
, DWRITE_FONT_STYLE_NORMAL
, &fontlist2
);
3502 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3503 ok(fontlist
!= fontlist2
, "got %p, %p\n", fontlist
, fontlist2
);
3504 IDWriteFontList_Release(fontlist2
);
3506 hr
= IDWriteFontList_QueryInterface(fontlist
, &IID_IDWriteFontList1
, (void**)&fontlist1
);
3508 IDWriteFontFaceReference
*ref
, *ref1
;
3512 count
= IDWriteFontList1_GetFontCount(fontlist1
);
3513 ok(count
> 0, "got %u\n", count
);
3515 font
= (void*)0xdeadbeef;
3516 hr
= IDWriteFontList1_GetFont(fontlist1
, ~0u, &font
);
3517 ok(hr
== E_FAIL
, "got 0x%08x\n", hr
);
3518 ok(font
== NULL
, "got %p\n", font
);
3520 font
= (void*)0xdeadbeef;
3521 hr
= IDWriteFontList1_GetFont(fontlist1
, count
, &font
);
3522 ok(hr
== E_FAIL
, "got 0x%08x\n", hr
);
3523 ok(font
== NULL
, "got %p\n", font
);
3525 hr
= IDWriteFontList1_GetFont(fontlist1
, 0, &font
);
3526 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3527 IDWriteFont3_Release(font
);
3529 hr
= IDWriteFontList1_GetFontFaceReference(fontlist1
, 0, &ref
);
3530 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3532 hr
= IDWriteFontList1_GetFontFaceReference(fontlist1
, 0, &ref1
);
3533 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3534 ok(ref
!= ref1
, "got %p, %p\n", ref
, ref1
);
3536 IDWriteFontFaceReference_Release(ref1
);
3537 IDWriteFontFaceReference_Release(ref
);
3538 IDWriteFontList1_Release(fontlist1
);
3541 win_skip("IDWriteFontList1 is not supported.\n");
3543 IDWriteFontList_Release(fontlist
);
3544 IDWriteFontFamily_Release(family
);
3546 IDWriteFontCollection_Release(collection
);
3547 ref
= IDWriteFactory_Release(factory
);
3548 ok(ref
== 0, "factory not released, %u\n", ref
);
3551 static void test_GetInformationalStrings(void)
3553 IDWriteLocalizedStrings
*strings
, *strings2
;
3554 IDWriteFontCollection
*collection
;
3555 IDWriteFontFamily
*family
;
3556 IDWriteFactory
*factory
;
3562 factory
= create_factory();
3564 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &collection
, FALSE
);
3565 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3567 hr
= IDWriteFontCollection_GetFontFamily(collection
, 0, &family
);
3568 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3570 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
,
3571 DWRITE_FONT_STRETCH_NORMAL
, DWRITE_FONT_STYLE_NORMAL
, &font
);
3572 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3575 strings
= (void*)0xdeadbeef;
3576 hr
= IDWriteFont_GetInformationalStrings(font
, DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_CID_NAME
+1, &strings
, &exists
);
3577 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3578 ok(exists
== FALSE
, "got %d\n", exists
);
3579 ok(strings
== NULL
, "got %p\n", strings
);
3583 hr
= IDWriteFont_GetInformationalStrings(font
, DWRITE_INFORMATIONAL_STRING_NONE
, &strings
, &exists
);
3584 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3585 ok(exists
== FALSE
, "got %d\n", exists
);
3589 hr
= IDWriteFont_GetInformationalStrings(font
, DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES
, &strings
, &exists
);
3590 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3591 ok(exists
== TRUE
, "got %d\n", exists
);
3593 /* strings instance is not reused */
3595 hr
= IDWriteFont_GetInformationalStrings(font
, DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES
, &strings2
, &exists
);
3596 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3597 ok(strings2
!= strings
, "got %p, %p\n", strings2
, strings
);
3599 IDWriteLocalizedStrings_Release(strings
);
3600 IDWriteLocalizedStrings_Release(strings2
);
3601 IDWriteFont_Release(font
);
3602 IDWriteFontFamily_Release(family
);
3603 IDWriteFontCollection_Release(collection
);
3604 ref
= IDWriteFactory_Release(factory
);
3605 ok(ref
== 0, "factory not released, %u\n", ref
);
3608 static void test_GetGdiInterop(void)
3610 IDWriteGdiInterop
*interop
, *interop2
;
3611 IDWriteFactory
*factory
, *factory2
;
3617 factory
= create_factory();
3620 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop
);
3621 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3624 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop2
);
3625 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3626 ok(interop
== interop2
, "got %p, %p\n", interop
, interop2
);
3627 IDWriteGdiInterop_Release(interop2
);
3629 hr
= DWriteCreateFactory(DWRITE_FACTORY_TYPE_ISOLATED
, &IID_IDWriteFactory
, (IUnknown
**)&factory2
);
3630 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3632 /* each factory gets its own interop */
3634 hr
= IDWriteFactory_GetGdiInterop(factory2
, &interop2
);
3635 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3636 ok(interop
!= interop2
, "got %p, %p\n", interop
, interop2
);
3638 /* release factory - interop still works */
3639 IDWriteFactory_Release(factory2
);
3641 memset(&logfont
, 0, sizeof(logfont
));
3642 logfont
.lfHeight
= 12;
3643 logfont
.lfWidth
= 12;
3644 logfont
.lfWeight
= FW_NORMAL
;
3645 logfont
.lfItalic
= 1;
3646 lstrcpyW(logfont
.lfFaceName
, tahomaW
);
3648 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop2
, &logfont
, &font
);
3649 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3650 IDWriteFont_Release(font
);
3652 IDWriteGdiInterop_Release(interop2
);
3653 IDWriteGdiInterop_Release(interop
);
3654 ref
= IDWriteFactory_Release(factory
);
3655 ok(ref
== 0, "factory not released, %u\n", ref
);
3658 static void test_CreateFontFaceFromHdc(void)
3660 IDWriteGdiInterop
*interop
;
3661 IDWriteFontFace
*fontface
;
3662 IDWriteFactory
*factory
;
3663 HFONT hfont
, oldhfont
;
3670 factory
= create_factory();
3673 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop
);
3674 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3677 fontface
= (void*)0xdeadbeef;
3678 hr
= IDWriteGdiInterop_CreateFontFaceFromHdc(interop
, NULL
, &fontface
);
3679 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
3680 ok(fontface
== NULL
, "got %p\n", fontface
);
3682 fontface
= (void *)0xdeadbeef;
3683 hr
= IDWriteGdiInterop_CreateFontFaceFromHdc(interop
, (HDC
)0xdeadbeef, &fontface
);
3684 ok(hr
== E_FAIL
, "got 0x%08x\n", hr
);
3685 ok(fontface
== NULL
, "got %p\n", fontface
);
3687 memset(&logfont
, 0, sizeof(logfont
));
3688 logfont
.lfHeight
= 12;
3689 logfont
.lfWidth
= 12;
3690 logfont
.lfWeight
= FW_NORMAL
;
3691 logfont
.lfItalic
= 1;
3692 lstrcpyW(logfont
.lfFaceName
, tahomaW
);
3694 hfont
= CreateFontIndirectW(&logfont
);
3695 hdc
= CreateCompatibleDC(0);
3696 oldhfont
= SelectObject(hdc
, hfont
);
3699 hr
= IDWriteGdiInterop_CreateFontFaceFromHdc(interop
, hdc
, &fontface
);
3700 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3701 IDWriteFontFace_Release(fontface
);
3702 DeleteObject(SelectObject(hdc
, oldhfont
));
3704 /* Select bitmap font MS Sans Serif, format that's not supported by DirectWrite. */
3705 memset(&lf
, 0, sizeof(lf
));
3707 strcpy(lf
.lfFaceName
, "MS Sans Serif");
3709 hfont
= CreateFontIndirectA(&lf
);
3710 oldhfont
= SelectObject(hdc
, hfont
);
3712 fontface
= (void *)0xdeadbeef;
3713 hr
= IDWriteGdiInterop_CreateFontFaceFromHdc(interop
, hdc
, &fontface
);
3714 ok(hr
== DWRITE_E_FILEFORMAT
|| broken(hr
== E_FAIL
) /* Vista */, "got 0x%08x\n", hr
);
3715 ok(fontface
== NULL
, "got %p\n", fontface
);
3717 DeleteObject(SelectObject(hdc
, oldhfont
));
3720 IDWriteGdiInterop_Release(interop
);
3721 ref
= IDWriteFactory_Release(factory
);
3722 ok(ref
== 0, "factory not released, %u\n", ref
);
3725 static void test_GetSimulations(void)
3727 DWRITE_FONT_SIMULATIONS simulations
;
3728 IDWriteGdiInterop
*interop
;
3729 IDWriteFontFace
*fontface
;
3730 IDWriteFactory
*factory
;
3736 factory
= create_factory();
3738 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop
);
3739 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3741 memset(&logfont
, 0, sizeof(logfont
));
3742 logfont
.lfHeight
= 12;
3743 logfont
.lfWidth
= 12;
3744 logfont
.lfWeight
= FW_NORMAL
;
3745 logfont
.lfItalic
= 1;
3746 lstrcpyW(logfont
.lfFaceName
, tahomaW
);
3748 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font
);
3749 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3751 simulations
= IDWriteFont_GetSimulations(font
);
3752 ok(simulations
== DWRITE_FONT_SIMULATIONS_OBLIQUE
, "got %d\n", simulations
);
3753 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
3754 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3755 simulations
= IDWriteFontFace_GetSimulations(fontface
);
3756 ok(simulations
== DWRITE_FONT_SIMULATIONS_OBLIQUE
, "got %d\n", simulations
);
3757 IDWriteFontFace_Release(fontface
);
3758 IDWriteFont_Release(font
);
3760 memset(&logfont
, 0, sizeof(logfont
));
3761 logfont
.lfHeight
= 12;
3762 logfont
.lfWidth
= 12;
3763 logfont
.lfWeight
= FW_NORMAL
;
3764 logfont
.lfItalic
= 0;
3765 lstrcpyW(logfont
.lfFaceName
, tahomaW
);
3767 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font
);
3768 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3770 simulations
= IDWriteFont_GetSimulations(font
);
3771 ok(simulations
== DWRITE_FONT_SIMULATIONS_NONE
, "got %d\n", simulations
);
3772 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
3773 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3774 simulations
= IDWriteFontFace_GetSimulations(fontface
);
3775 ok(simulations
== DWRITE_FONT_SIMULATIONS_NONE
, "got %d\n", simulations
);
3776 IDWriteFontFace_Release(fontface
);
3777 IDWriteFont_Release(font
);
3779 IDWriteGdiInterop_Release(interop
);
3780 ref
= IDWriteFactory_Release(factory
);
3781 ok(ref
== 0, "factory not released, %u\n", ref
);
3784 static void test_GetFaceNames(void)
3786 static const WCHAR obliqueW
[] = {'O','b','l','i','q','u','e',0};
3787 static const WCHAR enus2W
[] = {'e','n','-','U','s',0};
3788 static const WCHAR enusW
[] = {'e','n','-','u','s',0};
3789 IDWriteLocalizedStrings
*strings
, *strings2
;
3790 IDWriteGdiInterop
*interop
;
3791 IDWriteFactory
*factory
;
3792 UINT32 count
, index
;
3800 factory
= create_factory();
3802 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop
);
3803 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3805 memset(&logfont
, 0, sizeof(logfont
));
3806 logfont
.lfHeight
= 12;
3807 logfont
.lfWidth
= 12;
3808 logfont
.lfWeight
= FW_NORMAL
;
3809 logfont
.lfItalic
= 1;
3810 lstrcpyW(logfont
.lfFaceName
, tahomaW
);
3812 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font
);
3813 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3815 hr
= IDWriteFont_GetFaceNames(font
, &strings
);
3816 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3818 hr
= IDWriteFont_GetFaceNames(font
, &strings2
);
3819 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3820 ok(strings
!= strings2
, "got %p, %p\n", strings2
, strings
);
3821 IDWriteLocalizedStrings_Release(strings2
);
3823 count
= IDWriteLocalizedStrings_GetCount(strings
);
3824 ok(count
== 1, "got %d\n", count
);
3828 hr
= IDWriteLocalizedStrings_FindLocaleName(strings
, enus2W
, &index
, &exists
);
3829 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3830 ok(index
== 0 && exists
, "got %d, %d\n", index
, exists
);
3833 hr
= IDWriteLocalizedStrings_GetLocaleNameLength(strings
, 1, &count
);
3834 ok(hr
== E_FAIL
, "got 0x%08x\n", hr
);
3835 ok(count
== ~0, "got %d\n", count
);
3837 /* for simulated faces names are also simulated */
3839 hr
= IDWriteLocalizedStrings_GetLocaleName(strings
, 0, buffW
, sizeof(buffW
)/sizeof(WCHAR
));
3840 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3841 ok(!lstrcmpW(buffW
, enusW
), "got %s\n", wine_dbgstr_w(buffW
));
3844 hr
= IDWriteLocalizedStrings_GetString(strings
, 0, buffW
, sizeof(buffW
)/sizeof(WCHAR
));
3845 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3846 ok(!lstrcmpW(buffW
, obliqueW
), "got %s\n", wine_dbgstr_w(buffW
));
3847 IDWriteLocalizedStrings_Release(strings
);
3849 IDWriteFont_Release(font
);
3850 IDWriteGdiInterop_Release(interop
);
3851 ref
= IDWriteFactory_Release(factory
);
3852 ok(ref
== 0, "factory not released, %u\n", ref
);
3861 static void test_TryGetFontTable(void)
3863 IDWriteLocalFontFileLoader
*localloader
;
3864 WIN32_FILE_ATTRIBUTE_DATA info
;
3865 const struct local_refkey
*key
;
3866 IDWriteFontFileLoader
*loader
;
3867 const void *table
, *table2
;
3868 IDWriteFontFace
*fontface
;
3869 void *context
, *context2
;
3870 IDWriteFactory
*factory
;
3871 IDWriteFontFile
*file
;
3872 WCHAR buffW
[MAX_PATH
];
3879 path
= create_testfontfile(test_fontfile
);
3881 factory
= create_factory();
3883 hr
= IDWriteFactory_CreateFontFileReference(factory
, path
, NULL
, &file
);
3884 ok(hr
== S_OK
, "got 0x%08x\n",hr
);
3888 hr
= IDWriteFontFile_GetReferenceKey(file
, (const void**)&key
, &size
);
3889 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3890 ok(size
!= 0, "got %u\n", size
);
3892 ret
= GetFileAttributesExW(path
, GetFileExInfoStandard
, &info
);
3893 ok(ret
, "got %d\n", ret
);
3894 ok(!memcmp(&info
.ftLastWriteTime
, &key
->writetime
, sizeof(key
->writetime
)), "got wrong write time\n");
3896 hr
= IDWriteFontFile_GetLoader(file
, &loader
);
3897 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3898 IDWriteFontFileLoader_QueryInterface(loader
, &IID_IDWriteLocalFontFileLoader
, (void**)&localloader
);
3899 IDWriteFontFileLoader_Release(loader
);
3901 hr
= IDWriteLocalFontFileLoader_GetFilePathLengthFromKey(localloader
, key
, size
, &len
);
3902 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3903 ok(lstrlenW(key
->name
) == len
, "path length %d\n", len
);
3905 hr
= IDWriteLocalFontFileLoader_GetFilePathFromKey(localloader
, key
, size
, buffW
, sizeof(buffW
)/sizeof(WCHAR
));
3906 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3907 ok(!lstrcmpW(buffW
, key
->name
), "got %s, expected %s\n", wine_dbgstr_w(buffW
), wine_dbgstr_w(key
->name
));
3908 IDWriteLocalFontFileLoader_Release(localloader
);
3910 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_TRUETYPE
, 1, &file
, 0, 0, &fontface
);
3911 ok(hr
== S_OK
, "got 0x%08x\n",hr
);
3914 context
= (void*)0xdeadbeef;
3916 hr
= IDWriteFontFace_TryGetFontTable(fontface
, MS_CMAP_TAG
, &table
, &size
, &context
, &exists
);
3917 ok(hr
== S_OK
, "got 0x%08x\n",hr
);
3918 ok(exists
== TRUE
, "got %d\n", exists
);
3919 ok(context
== NULL
&& table
!= NULL
, "cmap: context %p, table %p\n", context
, table
);
3922 context2
= (void*)0xdeadbeef;
3924 hr
= IDWriteFontFace_TryGetFontTable(fontface
, MS_CMAP_TAG
, &table2
, &size
, &context2
, &exists
);
3925 ok(hr
== S_OK
, "got 0x%08x\n",hr
);
3926 ok(exists
== TRUE
, "got %d\n", exists
);
3927 ok(context2
== context
&& table2
== table
, "cmap: context2 %p, table2 %p\n", context2
, table2
);
3929 IDWriteFontFace_ReleaseFontTable(fontface
, context2
);
3930 IDWriteFontFace_ReleaseFontTable(fontface
, context
);
3932 /* table does not exist */
3934 context
= (void*)0xdeadbeef;
3935 table
= (void*)0xdeadbeef;
3936 hr
= IDWriteFontFace_TryGetFontTable(fontface
, 0xabababab, &table
, &size
, &context
, &exists
);
3937 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3938 ok(exists
== FALSE
, "got %d\n", exists
);
3939 ok(context
== NULL
&& table
== NULL
, "got context %p, table pointer %p\n", context
, table
);
3941 IDWriteFontFace_Release(fontface
);
3942 IDWriteFontFile_Release(file
);
3943 ref
= IDWriteFactory_Release(factory
);
3944 ok(ref
== 0, "factory not released, %u\n", ref
);
3945 DELETE_FONTFILE(path
);
3948 static void test_ConvertFontToLOGFONT(void)
3950 IDWriteFactory
*factory
, *factory2
;
3951 IDWriteFontCollection
*collection
;
3952 IDWriteGdiInterop
*interop
;
3953 IDWriteFontFamily
*family
;
3961 factory
= create_factory();
3962 factory2
= create_factory();
3965 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop
);
3966 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3968 hr
= IDWriteFactory_GetSystemFontCollection(factory2
, &collection
, FALSE
);
3969 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3971 hr
= IDWriteFontCollection_GetFontFamily(collection
, 0, &family
);
3972 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3974 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
,
3975 DWRITE_FONT_STRETCH_NORMAL
, DWRITE_FONT_STYLE_NORMAL
, &font
);
3976 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3978 if (0) { /* crashes on native */
3979 IDWriteGdiInterop_ConvertFontToLOGFONT(interop
, NULL
, NULL
, NULL
);
3980 IDWriteGdiInterop_ConvertFontToLOGFONT(interop
, NULL
, &logfont
, NULL
);
3981 IDWriteGdiInterop_ConvertFontToLOGFONT(interop
, font
, NULL
, &system
);
3984 memset(&logfont
, 0xcc, sizeof(logfont
));
3986 hr
= IDWriteGdiInterop_ConvertFontToLOGFONT(interop
, NULL
, &logfont
, &system
);
3987 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
3988 ok(!system
, "got %d\n", system
);
3989 ok(logfont
.lfFaceName
[0] == 0, "got face name %s\n", wine_dbgstr_w(logfont
.lfFaceName
));
3991 count
= IDWriteFontCollection_GetFontFamilyCount(collection
);
3992 for (i
= 0; i
< count
; i
++) {
3993 WCHAR nameW
[128], familynameW
[64], facenameW
[64];
3994 IDWriteLocalizedStrings
*names
;
3995 DWRITE_FONT_SIMULATIONS sim
;
3996 IDWriteFontFamily
*family
;
3997 UINT32 font_count
, j
;
4001 hr
= IDWriteFontCollection_GetFontFamily(collection
, i
, &family
);
4002 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4004 hr
= IDWriteFontFamily_GetFamilyNames(family
, &names
);
4005 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4007 get_enus_string(names
, familynameW
, sizeof(familynameW
)/sizeof(familynameW
[0]));
4008 IDWriteLocalizedStrings_Release(names
);
4010 font_count
= IDWriteFontFamily_GetFontCount(family
);
4012 for (j
= 0; j
< font_count
; j
++) {
4013 static const WCHAR spaceW
[] = {' ', 0};
4015 hr
= IDWriteFontFamily_GetFont(family
, j
, &font
);
4016 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4018 hr
= IDWriteFont_GetFaceNames(font
, &names
);
4019 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4021 get_enus_string(names
, facenameW
, sizeof(facenameW
)/sizeof(facenameW
[0]));
4022 IDWriteLocalizedStrings_Release(names
);
4024 lstrcpyW(nameW
, familynameW
);
4025 lstrcatW(nameW
, spaceW
);
4026 lstrcatW(nameW
, facenameW
);
4029 memset(&logfont
, 0xcc, sizeof(logfont
));
4030 hr
= IDWriteGdiInterop_ConvertFontToLOGFONT(interop
, font
, &logfont
, &system
);
4031 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4032 ok(system
, "got %d\n", system
);
4034 sim
= IDWriteFont_GetSimulations(font
);
4036 get_logfont_from_font(font
, &lf
);
4037 ok(logfont
.lfWeight
== lf
.lfWeight
, "%s: unexpected lfWeight %d, expected lfWeight %d, font weight %d, "
4038 "bold simulation %s\n", wine_dbgstr_w(nameW
), logfont
.lfWeight
, lf
.lfWeight
, IDWriteFont_GetWeight(font
),
4039 sim
& DWRITE_FONT_SIMULATIONS_BOLD
? "yes" : "no");
4040 ok(logfont
.lfItalic
== lf
.lfItalic
, "%s: unexpected italic flag %d, oblique simulation %s\n",
4041 wine_dbgstr_w(nameW
), logfont
.lfItalic
, sim
& DWRITE_FONT_SIMULATIONS_OBLIQUE
? "yes" : "no");
4042 ok(!lstrcmpW(logfont
.lfFaceName
, lf
.lfFaceName
), "%s: unexpected facename %s, expected %s\n",
4043 wine_dbgstr_w(nameW
), wine_dbgstr_w(logfont
.lfFaceName
), wine_dbgstr_w(lf
.lfFaceName
));
4045 ok(logfont
.lfOutPrecision
== OUT_OUTLINE_PRECIS
, "%s: unexpected output precision %d\n", wine_dbgstr_w(nameW
),
4046 logfont
.lfOutPrecision
);
4047 ok(logfont
.lfClipPrecision
== CLIP_DEFAULT_PRECIS
, "%s: unexpected clipping precision %d\n", wine_dbgstr_w(nameW
),
4048 logfont
.lfClipPrecision
);
4049 ok(logfont
.lfQuality
== DEFAULT_QUALITY
, "%s: unexpected quality %d\n", wine_dbgstr_w(nameW
), logfont
.lfQuality
);
4050 ok(logfont
.lfPitchAndFamily
== DEFAULT_PITCH
, "%s: unexpected pitch %d\n", wine_dbgstr_w(nameW
),
4051 logfont
.lfPitchAndFamily
);
4053 IDWriteFont_Release(font
);
4056 IDWriteFontFamily_Release(family
);
4059 IDWriteFactory_Release(factory2
);
4061 IDWriteFontCollection_Release(collection
);
4062 IDWriteFontFamily_Release(family
);
4063 IDWriteFont_Release(font
);
4064 IDWriteGdiInterop_Release(interop
);
4065 ref
= IDWriteFactory_Release(factory
);
4066 ok(ref
== 0, "factory not released, %u\n", ref
);
4069 static void test_CreateStreamFromKey(void)
4071 IDWriteLocalFontFileLoader
*localloader
;
4072 IDWriteFontFileStream
*stream
, *stream2
;
4073 IDWriteFontFileLoader
*loader
;
4074 IDWriteFactory
*factory
;
4075 IDWriteFontFile
*file
;
4083 factory
= create_factory();
4085 path
= create_testfontfile(test_fontfile
);
4087 hr
= IDWriteFactory_CreateFontFileReference(factory
, path
, NULL
, &file
);
4088 ok(hr
== S_OK
, "got 0x%08x\n",hr
);
4092 hr
= IDWriteFontFile_GetReferenceKey(file
, (const void**)&key
, &size
);
4093 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4094 ok(size
!= 0, "got %u\n", size
);
4096 hr
= IDWriteFontFile_GetLoader(file
, &loader
);
4097 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4098 IDWriteFontFileLoader_QueryInterface(loader
, &IID_IDWriteLocalFontFileLoader
, (void**)&localloader
);
4099 IDWriteFontFileLoader_Release(loader
);
4101 hr
= IDWriteLocalFontFileLoader_CreateStreamFromKey(localloader
, key
, size
, &stream
);
4102 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4103 EXPECT_REF(stream
, 1);
4105 hr
= IDWriteLocalFontFileLoader_CreateStreamFromKey(localloader
, key
, size
, &stream2
);
4106 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4107 ok(stream
== stream2
|| broken(stream
!= stream2
) /* Win7 SP0 */, "got %p, %p\n", stream
, stream2
);
4108 if (stream
== stream2
)
4109 EXPECT_REF(stream
, 2);
4110 IDWriteFontFileStream_Release(stream
);
4111 IDWriteFontFileStream_Release(stream2
);
4113 hr
= IDWriteLocalFontFileLoader_CreateStreamFromKey(localloader
, key
, size
, &stream
);
4114 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4115 EXPECT_REF(stream
, 1);
4118 hr
= IDWriteFontFileStream_GetLastWriteTime(stream
, &writetime
);
4119 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4120 ok(writetime
!= 0, "got %s\n", wine_dbgstr_longlong(writetime
));
4122 IDWriteFontFileStream_Release(stream
);
4123 IDWriteFontFile_Release(file
);
4125 IDWriteLocalFontFileLoader_Release(localloader
);
4126 ref
= IDWriteFactory_Release(factory
);
4127 ok(ref
== 0, "factory not released, %u\n", ref
);
4128 DELETE_FONTFILE(path
);
4131 static void test_ReadFileFragment(void)
4133 IDWriteLocalFontFileLoader
*localloader
;
4134 IDWriteFontFileStream
*stream
;
4135 IDWriteFontFileLoader
*loader
;
4136 IDWriteFactory
*factory
;
4137 IDWriteFontFile
*file
;
4138 const void *fragment
, *fragment2
;
4139 void *key
, *context
, *context2
;
4146 factory
= create_factory();
4148 path
= create_testfontfile(test_fontfile
);
4150 hr
= IDWriteFactory_CreateFontFileReference(factory
, path
, NULL
, &file
);
4151 ok(hr
== S_OK
, "got 0x%08x\n",hr
);
4155 hr
= IDWriteFontFile_GetReferenceKey(file
, (const void**)&key
, &size
);
4156 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4157 ok(size
!= 0, "got %u\n", size
);
4159 hr
= IDWriteFontFile_GetLoader(file
, &loader
);
4160 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4161 IDWriteFontFileLoader_QueryInterface(loader
, &IID_IDWriteLocalFontFileLoader
, (void**)&localloader
);
4162 IDWriteFontFileLoader_Release(loader
);
4164 hr
= IDWriteLocalFontFileLoader_CreateStreamFromKey(localloader
, key
, size
, &stream
);
4165 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4167 hr
= IDWriteFontFileStream_GetFileSize(stream
, &filesize
);
4168 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4170 /* reading past the end of the stream */
4171 fragment
= (void*)0xdeadbeef;
4172 context
= (void*)0xdeadbeef;
4173 hr
= IDWriteFontFileStream_ReadFileFragment(stream
, &fragment
, 0, filesize
+1, &context
);
4174 ok(hr
== E_FAIL
, "got 0x%08x\n", hr
);
4175 ok(context
== NULL
, "got %p\n", context
);
4176 ok(fragment
== NULL
, "got %p\n", fragment
);
4178 fragment
= (void*)0xdeadbeef;
4179 context
= (void*)0xdeadbeef;
4180 hr
= IDWriteFontFileStream_ReadFileFragment(stream
, &fragment
, 0, filesize
, &context
);
4181 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4182 ok(context
== NULL
, "got %p\n", context
);
4183 ok(fragment
!= NULL
, "got %p\n", fragment
);
4185 fragment2
= (void*)0xdeadbeef;
4186 context2
= (void*)0xdeadbeef;
4187 hr
= IDWriteFontFileStream_ReadFileFragment(stream
, &fragment2
, 0, filesize
, &context2
);
4188 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4189 ok(context2
== NULL
, "got %p\n", context2
);
4190 ok(fragment
== fragment2
, "got %p, %p\n", fragment
, fragment2
);
4192 IDWriteFontFileStream_ReleaseFileFragment(stream
, context
);
4193 IDWriteFontFileStream_ReleaseFileFragment(stream
, context2
);
4195 /* fragment is released, try again */
4196 fragment
= (void*)0xdeadbeef;
4197 context
= (void*)0xdeadbeef;
4198 hr
= IDWriteFontFileStream_ReadFileFragment(stream
, &fragment
, 0, filesize
, &context
);
4199 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4200 ok(context
== NULL
, "got %p\n", context
);
4201 ok(fragment
== fragment2
, "got %p, %p\n", fragment
, fragment2
);
4202 IDWriteFontFileStream_ReleaseFileFragment(stream
, context
);
4204 IDWriteFontFile_Release(file
);
4205 IDWriteFontFileStream_Release(stream
);
4206 IDWriteLocalFontFileLoader_Release(localloader
);
4207 ref
= IDWriteFactory_Release(factory
);
4208 ok(ref
== 0, "factory not released, %u\n", ref
);
4209 DELETE_FONTFILE(path
);
4212 static void test_GetDesignGlyphMetrics(void)
4214 DWRITE_GLYPH_METRICS metrics
[2];
4215 IDWriteFontFace
*fontface
;
4216 IDWriteFactory
*factory
;
4217 IDWriteFontFile
*file
;
4224 factory
= create_factory();
4226 path
= create_testfontfile(test_fontfile
);
4228 hr
= IDWriteFactory_CreateFontFileReference(factory
, path
, NULL
, &file
);
4229 ok(hr
== S_OK
, "got 0x%08x\n",hr
);
4231 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_TRUETYPE
, 1, &file
,
4232 0, DWRITE_FONT_SIMULATIONS_NONE
, &fontface
);
4233 ok(hr
== S_OK
, "got 0x%08x\n",hr
);
4234 IDWriteFontFile_Release(file
);
4238 hr
= IDWriteFontFace_GetGlyphIndices(fontface
, &codepoint
, 1, &indices
[0]);
4239 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4240 ok(indices
[0] > 0, "got %u\n", indices
[0]);
4242 hr
= IDWriteFontFace_GetDesignGlyphMetrics(fontface
, NULL
, 0, metrics
, FALSE
);
4243 ok(hr
== E_INVALIDARG
, "got 0x%08x\n",hr
);
4245 hr
= IDWriteFontFace_GetDesignGlyphMetrics(fontface
, NULL
, 1, metrics
, FALSE
);
4246 ok(hr
== E_INVALIDARG
, "got 0x%08x\n",hr
);
4248 hr
= IDWriteFontFace_GetDesignGlyphMetrics(fontface
, indices
, 0, metrics
, FALSE
);
4249 ok(hr
== S_OK
, "got 0x%08x\n",hr
);
4251 /* missing glyphs are ignored */
4253 memset(metrics
, 0xcc, sizeof(metrics
));
4254 hr
= IDWriteFontFace_GetDesignGlyphMetrics(fontface
, indices
, 2, metrics
, FALSE
);
4255 ok(hr
== S_OK
, "got 0x%08x\n",hr
);
4256 ok(metrics
[0].advanceWidth
== 1000, "got %d\n", metrics
[0].advanceWidth
);
4257 ok(metrics
[1].advanceWidth
== 0, "got %d\n", metrics
[1].advanceWidth
);
4259 IDWriteFontFace_Release(fontface
);
4260 ref
= IDWriteFactory_Release(factory
);
4261 ok(ref
== 0, "factory not released, %u\n", ref
);
4262 DELETE_FONTFILE(path
);
4265 static void test_IsMonospacedFont(void)
4267 static const WCHAR courierW
[] = {'C','o','u','r','i','e','r',' ','N','e','w',0};
4268 IDWriteFontCollection
*collection
;
4269 IDWriteFactory
*factory
;
4275 factory
= create_factory();
4276 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &collection
, FALSE
);
4277 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4280 hr
= IDWriteFontCollection_FindFamilyName(collection
, courierW
, &index
, &exists
);
4281 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4283 IDWriteFontFamily
*family
;
4284 IDWriteFont1
*font1
;
4287 hr
= IDWriteFontCollection_GetFontFamily(collection
, index
, &family
);
4288 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4290 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
,
4291 DWRITE_FONT_STRETCH_NORMAL
, DWRITE_FONT_STYLE_NORMAL
, &font
);
4292 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4293 IDWriteFontFamily_Release(family
);
4295 hr
= IDWriteFont_QueryInterface(font
, &IID_IDWriteFont1
, (void**)&font1
);
4297 IDWriteFontFace1
*fontface1
;
4298 IDWriteFontFace
*fontface
;
4301 is_monospaced
= IDWriteFont1_IsMonospacedFont(font1
);
4302 ok(is_monospaced
, "got %d\n", is_monospaced
);
4304 hr
= IDWriteFont1_CreateFontFace(font1
, &fontface
);
4305 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4306 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void**)&fontface1
);
4307 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4308 is_monospaced
= IDWriteFontFace1_IsMonospacedFont(fontface1
);
4309 ok(is_monospaced
, "got %d\n", is_monospaced
);
4310 IDWriteFontFace1_Release(fontface1
);
4312 IDWriteFontFace_Release(fontface
);
4313 IDWriteFont1_Release(font1
);
4316 win_skip("IsMonospacedFont() is not supported.\n");
4318 IDWriteFont_Release(font
);
4321 skip("Courier New font not found.\n");
4323 ref
= IDWriteFontCollection_Release(collection
);
4324 ok(ref
== 0, "factory not released, %u\n", ref
);
4327 static void test_GetDesignGlyphAdvances(void)
4329 IDWriteFontFace1
*fontface1
;
4330 IDWriteFontFace
*fontface
;
4331 IDWriteFactory
*factory
;
4332 IDWriteFontFile
*file
;
4337 factory
= create_factory();
4339 path
= create_testfontfile(test_fontfile
);
4341 hr
= IDWriteFactory_CreateFontFileReference(factory
, path
, NULL
, &file
);
4342 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4344 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_TRUETYPE
, 1, &file
,
4345 0, DWRITE_FONT_SIMULATIONS_NONE
, &fontface
);
4346 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4347 IDWriteFontFile_Release(file
);
4349 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void**)&fontface1
);
4357 hr
= IDWriteFontFace1_GetGlyphIndices(fontface1
, &codepoint
, 1, &index
);
4358 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4359 ok(index
> 0, "got %u\n", index
);
4362 hr
= IDWriteFontFace1_GetDesignGlyphAdvances(fontface1
, 1, &index
, &advance
, FALSE
);
4363 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4364 ok(advance
== 1000, "got %i\n", advance
);
4367 hr
= IDWriteFontFace1_GetDesignGlyphAdvances(fontface1
, 1, &index
, &advance
, TRUE
);
4368 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4370 ok(advance
== 2048, "got %i\n", advance
);
4372 IDWriteFontFace1_Release(fontface1
);
4375 win_skip("GetDesignGlyphAdvances() is not supported.\n");
4377 IDWriteFontFace_Release(fontface
);
4378 ref
= IDWriteFactory_Release(factory
);
4379 ok(ref
== 0, "factory not released, %u\n", ref
);
4380 DELETE_FONTFILE(path
);
4383 static void test_GetGlyphRunOutline(void)
4385 DWRITE_GLYPH_OFFSET offsets
[2];
4386 IDWriteFactory
*factory
;
4387 IDWriteFontFile
*file
;
4388 IDWriteFontFace
*face
;
4396 path
= create_testfontfile(test_fontfile
);
4397 factory
= create_factory();
4399 hr
= IDWriteFactory_CreateFontFileReference(factory
, path
, NULL
, &file
);
4400 ok(hr
== S_OK
, "got 0x%08x\n",hr
);
4402 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_TRUETYPE
, 1, &file
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &face
);
4403 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4404 IDWriteFontFile_Release(file
);
4408 hr
= IDWriteFontFace_GetGlyphIndices(face
, &codepoint
, 1, glyphs
);
4409 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4410 ok(glyphs
[0] > 0, "got %u\n", glyphs
[0]);
4411 glyphs
[1] = glyphs
[0];
4413 hr
= IDWriteFontFace_GetGlyphRunOutline(face
, 2048.0, glyphs
, advances
, offsets
, 1, FALSE
, FALSE
, NULL
);
4414 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
4416 hr
= IDWriteFontFace_GetGlyphRunOutline(face
, 2048.0, NULL
, NULL
, offsets
, 1, FALSE
, FALSE
, &test_geomsink
);
4417 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
4422 offsets
[0].advanceOffset
= 1.0;
4423 offsets
[0].ascenderOffset
= 1.0;
4424 offsets
[1].advanceOffset
= 0.0;
4425 offsets
[1].ascenderOffset
= 0.0;
4427 /* default advances, no offsets */
4428 memset(g_startpoints
, 0, sizeof(g_startpoints
));
4429 g_startpoint_count
= 0;
4430 SET_EXPECT(setfillmode
);
4431 hr
= IDWriteFontFace_GetGlyphRunOutline(face
, 1024.0, glyphs
, NULL
, NULL
, 2, FALSE
, FALSE
, &test_geomsink
);
4432 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4433 ok(g_startpoint_count
== 2, "got %d\n", g_startpoint_count
);
4434 if (g_startpoint_count
== 2) {
4435 /* glyph advance of 500 is applied */
4436 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
);
4437 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
);
4439 CHECK_CALLED(setfillmode
);
4441 /* default advances, no offsets, RTL */
4442 memset(g_startpoints
, 0, sizeof(g_startpoints
));
4443 g_startpoint_count
= 0;
4444 SET_EXPECT(setfillmode
);
4445 hr
= IDWriteFontFace_GetGlyphRunOutline(face
, 1024.0, glyphs
, NULL
, NULL
, 2, FALSE
, TRUE
, &test_geomsink
);
4446 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4447 ok(g_startpoint_count
== 2, "got %d\n", g_startpoint_count
);
4448 if (g_startpoint_count
== 2) {
4449 /* advance is -500 now */
4450 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
);
4451 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
);
4453 CHECK_CALLED(setfillmode
);
4455 /* default advances, additional offsets */
4456 memset(g_startpoints
, 0, sizeof(g_startpoints
));
4457 g_startpoint_count
= 0;
4458 SET_EXPECT(setfillmode
);
4459 hr
= IDWriteFontFace_GetGlyphRunOutline(face
, 1024.0, glyphs
, NULL
, offsets
, 2, FALSE
, FALSE
, &test_geomsink
);
4460 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4461 ok(g_startpoint_count
== 2, "got %d\n", g_startpoint_count
);
4462 if (g_startpoint_count
== 2) {
4463 /* offsets applied to first contour */
4464 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
);
4465 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
);
4467 CHECK_CALLED(setfillmode
);
4469 /* default advances, additional offsets, RTL */
4470 memset(g_startpoints
, 0, sizeof(g_startpoints
));
4471 g_startpoint_count
= 0;
4472 SET_EXPECT(setfillmode
);
4473 hr
= IDWriteFontFace_GetGlyphRunOutline(face
, 1024.0, glyphs
, NULL
, offsets
, 2, FALSE
, TRUE
, &test_geomsink
);
4474 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4475 ok(g_startpoint_count
== 2, "got %d\n", g_startpoint_count
);
4476 if (g_startpoint_count
== 2) {
4477 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
);
4478 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
);
4480 CHECK_CALLED(setfillmode
);
4482 /* custom advances and offsets, offset turns total advance value to zero */
4483 memset(g_startpoints
, 0, sizeof(g_startpoints
));
4484 g_startpoint_count
= 0;
4485 SET_EXPECT(setfillmode
);
4486 hr
= IDWriteFontFace_GetGlyphRunOutline(face
, 1024.0, glyphs
, advances
, offsets
, 2, FALSE
, FALSE
, &test_geomsink
);
4487 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4488 ok(g_startpoint_count
== 2, "got %d\n", g_startpoint_count
);
4489 if (g_startpoint_count
== 2) {
4490 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
);
4491 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
);
4493 CHECK_CALLED(setfillmode
);
4496 hr
= IDWriteFontFace_GetGlyphRunOutline(face
, 1024.0, glyphs
, NULL
, NULL
, 0, FALSE
, FALSE
, &test_geomsink2
);
4497 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4499 /* Glyph with open figure, single contour point. */
4502 hr
= IDWriteFontFace_GetGlyphIndices(face
, &codepoint
, 1, glyphs
);
4503 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4504 ok(glyphs
[0] > 0, "got %u\n", glyphs
[0]);
4506 SET_EXPECT(setfillmode
);
4507 hr
= IDWriteFontFace_GetGlyphRunOutline(face
, 1024.0, glyphs
, NULL
, NULL
, 1, FALSE
, FALSE
, &test_geomsink2
);
4508 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4509 CHECK_CALLED(setfillmode
);
4511 IDWriteFactory_Release(factory
);
4512 IDWriteFontFace_Release(face
);
4513 DELETE_FONTFILE(path
);
4516 factory
= create_factory();
4517 face
= create_fontface(factory
);
4521 hr
= IDWriteFontFace_GetGlyphIndices(face
, &codepoint
, 1, glyphs
);
4522 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4523 ok(glyphs
[0] > 0, "got %u\n", glyphs
[0]);
4525 SET_EXPECT(setfillmode
);
4526 hr
= IDWriteFontFace_GetGlyphRunOutline(face
, 1024.0, glyphs
, NULL
, NULL
, 1, FALSE
, FALSE
, &test_geomsink2
);
4527 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4528 CHECK_CALLED(setfillmode
);
4530 IDWriteFontFace_Release(face
);
4531 ref
= IDWriteFactory_Release(factory
);
4532 ok(ref
== 0, "factory not released, %u\n", ref
);
4535 static void test_GetEudcFontCollection(void)
4537 IDWriteFontCollection
*coll
, *coll2
;
4538 IDWriteFactory1
*factory
;
4542 factory
= create_factory_iid(&IID_IDWriteFactory1
);
4544 win_skip("GetEudcFontCollection() is not supported.\n");
4548 EXPECT_REF(factory
, 1);
4549 hr
= IDWriteFactory1_GetEudcFontCollection(factory
, &coll
, FALSE
);
4550 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4551 EXPECT_REF(factory
, 2);
4552 hr
= IDWriteFactory1_GetEudcFontCollection(factory
, &coll2
, FALSE
);
4553 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4554 EXPECT_REF(factory
, 2);
4555 ok(coll
== coll2
, "got %p, %p\n", coll
, coll2
);
4556 IDWriteFontCollection_Release(coll
);
4557 IDWriteFontCollection_Release(coll2
);
4559 ref
= IDWriteFactory1_Release(factory
);
4560 ok(ref
== 0, "factory not released, %u\n", ref
);
4563 static void test_GetCaretMetrics(void)
4565 DWRITE_FONT_METRICS1 metrics
;
4566 IDWriteFontFace1
*fontface1
;
4567 DWRITE_CARET_METRICS caret
;
4568 IDWriteFontFace
*fontface
;
4569 IDWriteFactory
*factory
;
4570 IDWriteFontFile
*file
;
4576 path
= create_testfontfile(test_fontfile
);
4577 factory
= create_factory();
4579 hr
= IDWriteFactory_CreateFontFileReference(factory
, path
, NULL
, &file
);
4580 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4582 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_TRUETYPE
, 1, &file
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &fontface
);
4583 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4584 IDWriteFontFile_Release(file
);
4586 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void**)&fontface1
);
4587 IDWriteFontFace_Release(fontface
);
4589 win_skip("GetCaretMetrics() is not supported.\n");
4590 ref
= IDWriteFactory_Release(factory
);
4591 ok(ref
== 0, "factory not released, %u\n", ref
);
4592 DELETE_FONTFILE(path
);
4596 memset(&caret
, 0xcc, sizeof(caret
));
4597 IDWriteFontFace1_GetCaretMetrics(fontface1
, &caret
);
4598 ok(caret
.slopeRise
== 1, "got %d\n", caret
.slopeRise
);
4599 ok(caret
.slopeRun
== 0, "got %d\n", caret
.slopeRun
);
4600 ok(caret
.offset
== 0, "got %d\n", caret
.offset
);
4601 IDWriteFontFace1_Release(fontface1
);
4602 IDWriteFactory_Release(factory
);
4604 /* now with Tahoma Normal */
4605 factory
= create_factory();
4606 font
= get_tahoma_instance(factory
, DWRITE_FONT_STYLE_NORMAL
);
4607 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
4608 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4609 IDWriteFont_Release(font
);
4610 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void**)&fontface1
);
4611 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4612 IDWriteFontFace_Release(fontface
);
4614 memset(&caret
, 0xcc, sizeof(caret
));
4615 IDWriteFontFace1_GetCaretMetrics(fontface1
, &caret
);
4616 ok(caret
.slopeRise
== 1, "got %d\n", caret
.slopeRise
);
4617 ok(caret
.slopeRun
== 0, "got %d\n", caret
.slopeRun
);
4618 ok(caret
.offset
== 0, "got %d\n", caret
.offset
);
4619 IDWriteFontFace1_Release(fontface1
);
4621 /* simulated italic */
4622 font
= get_tahoma_instance(factory
, DWRITE_FONT_STYLE_ITALIC
);
4623 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
4624 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4625 IDWriteFont_Release(font
);
4626 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void**)&fontface1
);
4627 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4628 IDWriteFontFace_Release(fontface
);
4630 IDWriteFontFace1_GetMetrics(fontface1
, &metrics
);
4632 memset(&caret
, 0xcc, sizeof(caret
));
4633 IDWriteFontFace1_GetCaretMetrics(fontface1
, &caret
);
4634 ok(caret
.slopeRise
== metrics
.designUnitsPerEm
, "got %d\n", caret
.slopeRise
);
4635 ok(caret
.slopeRun
> 0, "got %d\n", caret
.slopeRun
);
4636 ok(caret
.offset
== 0, "got %d\n", caret
.offset
);
4637 IDWriteFontFace1_Release(fontface1
);
4639 ref
= IDWriteFactory_Release(factory
);
4640 ok(ref
== 0, "factory not released, %u\n", ref
);
4641 DELETE_FONTFILE(path
);
4644 static void test_GetGlyphCount(void)
4646 IDWriteFontFace
*fontface
;
4647 IDWriteFactory
*factory
;
4648 IDWriteFontFile
*file
;
4654 path
= create_testfontfile(test_fontfile
);
4655 factory
= create_factory();
4657 hr
= IDWriteFactory_CreateFontFileReference(factory
, path
, NULL
, &file
);
4658 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4660 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_TRUETYPE
, 1, &file
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &fontface
);
4661 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4662 IDWriteFontFile_Release(file
);
4664 count
= IDWriteFontFace_GetGlyphCount(fontface
);
4665 ok(count
== 8, "got %u\n", count
);
4667 IDWriteFontFace_Release(fontface
);
4668 ref
= IDWriteFactory_Release(factory
);
4669 ok(ref
== 0, "factory not released, %u\n", ref
);
4670 DELETE_FONTFILE(path
);
4673 static void test_GetKerningPairAdjustments(void)
4675 IDWriteFontFace1
*fontface1
;
4676 IDWriteFontFace
*fontface
;
4677 IDWriteFactory
*factory
;
4678 IDWriteFontFile
*file
;
4683 path
= create_testfontfile(test_fontfile
);
4684 factory
= create_factory();
4686 hr
= IDWriteFactory_CreateFontFileReference(factory
, path
, NULL
, &file
);
4687 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4689 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_TRUETYPE
, 1, &file
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &fontface
);
4690 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4691 IDWriteFontFile_Release(file
);
4693 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void**)&fontface1
);
4695 INT32 adjustments
[1];
4697 hr
= IDWriteFontFace1_GetKerningPairAdjustments(fontface1
, 0, NULL
, NULL
);
4698 ok(hr
== E_INVALIDARG
|| broken(hr
== S_OK
) /* win8 */, "got 0x%08x\n", hr
);
4700 if (0) /* crashes on native */
4701 hr
= IDWriteFontFace1_GetKerningPairAdjustments(fontface1
, 1, NULL
, NULL
);
4704 hr
= IDWriteFontFace1_GetKerningPairAdjustments(fontface1
, 1, NULL
, adjustments
);
4705 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
4706 ok(adjustments
[0] == 0, "got %d\n", adjustments
[0]);
4708 IDWriteFontFace1_Release(fontface1
);
4711 win_skip("GetKerningPairAdjustments() is not supported.\n");
4713 IDWriteFontFace_Release(fontface
);
4714 ref
= IDWriteFactory_Release(factory
);
4715 ok(ref
== 0, "factory not released, %u\n", ref
);
4716 DELETE_FONTFILE(path
);
4719 static void test_CreateRenderingParams(void)
4721 IDWriteRenderingParams2
*params2
;
4722 IDWriteRenderingParams1
*params1
;
4723 IDWriteRenderingParams
*params
;
4724 DWRITE_RENDERING_MODE mode
;
4725 IDWriteFactory3
*factory3
;
4726 IDWriteFactory
*factory
;
4730 factory
= create_factory();
4732 hr
= IDWriteFactory_CreateCustomRenderingParams(factory
, 1.0, 0.0, 0.0, DWRITE_PIXEL_GEOMETRY_FLAT
,
4733 DWRITE_RENDERING_MODE_DEFAULT
, ¶ms
);
4734 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4736 hr
= IDWriteRenderingParams_QueryInterface(params
, &IID_IDWriteRenderingParams1
, (void**)¶ms1
);
4740 /* test what enhanced contrast setting set by default to */
4741 enhcontrast
= IDWriteRenderingParams1_GetGrayscaleEnhancedContrast(params1
);
4742 ok(enhcontrast
== 1.0, "got %.2f\n", enhcontrast
);
4743 IDWriteRenderingParams1_Release(params1
);
4745 hr
= IDWriteRenderingParams_QueryInterface(params
, &IID_IDWriteRenderingParams2
, (void**)¶ms2
);
4747 DWRITE_GRID_FIT_MODE gridfit
;
4749 /* default gridfit mode */
4750 gridfit
= IDWriteRenderingParams2_GetGridFitMode(params2
);
4751 ok(gridfit
== DWRITE_GRID_FIT_MODE_DEFAULT
, "got %d\n", gridfit
);
4753 IDWriteRenderingParams2_Release(params2
);
4756 win_skip("IDWriteRenderingParams2 not supported.\n");
4759 win_skip("IDWriteRenderingParams1 not supported.\n");
4761 IDWriteRenderingParams_Release(params
);
4763 hr
= IDWriteFactory_CreateRenderingParams(factory
, ¶ms
);
4764 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4766 mode
= IDWriteRenderingParams_GetRenderingMode(params
);
4767 ok(mode
== DWRITE_RENDERING_MODE_DEFAULT
, "got %d\n", mode
);
4768 IDWriteRenderingParams_Release(params
);
4770 hr
= IDWriteFactory_QueryInterface(factory
, &IID_IDWriteFactory3
, (void**)&factory3
);
4772 IDWriteRenderingParams3
*params3
;
4774 hr
= IDWriteFactory3_CreateCustomRenderingParams(factory3
, 1.0f
, 0.0f
, 0.0f
, 1.0f
, DWRITE_PIXEL_GEOMETRY_FLAT
,
4775 DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC_DOWNSAMPLED
, DWRITE_GRID_FIT_MODE_DEFAULT
, ¶ms3
);
4776 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4778 hr
= IDWriteRenderingParams3_QueryInterface(params3
, &IID_IDWriteRenderingParams
, (void**)¶ms
);
4779 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4781 mode
= IDWriteRenderingParams_GetRenderingMode(params
);
4782 ok(mode
== DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
, "got %d\n", mode
);
4784 IDWriteRenderingParams_Release(params
);
4785 IDWriteRenderingParams3_Release(params3
);
4786 IDWriteFactory3_Release(factory3
);
4789 win_skip("IDWriteRenderingParams3 not supported.\n");
4791 ref
= IDWriteFactory_Release(factory
);
4792 ok(ref
== 0, "factory not released, %u\n", ref
);
4795 static void test_CreateGlyphRunAnalysis(void)
4797 static const DWRITE_RENDERING_MODE rendermodes
[] = {
4798 DWRITE_RENDERING_MODE_ALIASED
,
4799 DWRITE_RENDERING_MODE_GDI_CLASSIC
,
4800 DWRITE_RENDERING_MODE_GDI_NATURAL
,
4801 DWRITE_RENDERING_MODE_NATURAL
,
4802 DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
,
4805 IDWriteGlyphRunAnalysis
*analysis
, *analysis2
;
4806 IDWriteRenderingParams
*params
;
4807 IDWriteFactory3
*factory3
;
4808 IDWriteFactory2
*factory2
;
4809 IDWriteFactory
*factory
;
4810 DWRITE_GLYPH_RUN run
;
4811 IDWriteFontFace
*face
;
4812 UINT16 glyph
, glyphs
[10];
4817 DWRITE_GLYPH_OFFSET offsets
[2];
4818 DWRITE_GLYPH_METRICS metrics
;
4819 DWRITE_FONT_METRICS fm
;
4826 factory
= create_factory();
4827 face
= create_fontface(factory
);
4831 hr
= IDWriteFontFace_GetGlyphIndices(face
, &ch
, 1, &glyph
);
4832 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4833 ok(glyph
> 0, "got %u\n", glyph
);
4835 hr
= IDWriteFontFace_GetDesignGlyphMetrics(face
, &glyph
, 1, &metrics
, FALSE
);
4836 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4837 advances
[0] = metrics
.advanceWidth
;
4839 offsets
[0].advanceOffset
= 0.0;
4840 offsets
[0].ascenderOffset
= 0.0;
4842 run
.fontFace
= face
;
4843 run
.fontEmSize
= 24.0;
4845 run
.glyphIndices
= &glyph
;
4846 run
.glyphAdvances
= advances
;
4847 run
.glyphOffsets
= offsets
;
4848 run
.isSideways
= FALSE
;
4852 analysis
= (void*)0xdeadbeef;
4853 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 0.0, NULL
,
4854 DWRITE_RENDERING_MODE_ALIASED
, DWRITE_MEASURING_MODE_NATURAL
,
4855 0.0, 0.0, &analysis
);
4856 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
4857 ok(analysis
== NULL
, "got %p\n", analysis
);
4859 /* negative ppdip */
4860 analysis
= (void*)0xdeadbeef;
4861 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, -1.0, NULL
,
4862 DWRITE_RENDERING_MODE_ALIASED
, DWRITE_MEASURING_MODE_NATURAL
,
4863 0.0, 0.0, &analysis
);
4864 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
4865 ok(analysis
== NULL
, "got %p\n", analysis
);
4867 /* default mode is not allowed */
4868 analysis
= (void*)0xdeadbeef;
4869 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 1.0, NULL
,
4870 DWRITE_RENDERING_MODE_DEFAULT
, DWRITE_MEASURING_MODE_NATURAL
,
4871 0.0, 0.0, &analysis
);
4872 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
4873 ok(analysis
== NULL
, "got %p\n", analysis
);
4876 analysis
= (void*)0xdeadbeef;
4877 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 1.0, NULL
,
4878 DWRITE_RENDERING_MODE_OUTLINE
, DWRITE_MEASURING_MODE_NATURAL
,
4879 0.0, 0.0, &analysis
);
4880 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
4881 ok(analysis
== NULL
, "got %p\n", analysis
);
4883 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 1.0, NULL
,
4884 DWRITE_RENDERING_MODE_ALIASED
, DWRITE_MEASURING_MODE_NATURAL
,
4885 0.0, 0.0, &analysis
);
4886 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4888 /* invalid texture type */
4889 memset(&rect
, 0xcc, sizeof(rect
));
4890 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_CLEARTYPE_3x1
+1, &rect
);
4891 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
4892 ok(rect
.left
== 0 && rect
.right
== 0 &&
4893 rect
.top
== 0 && rect
.bottom
== 0, "unexpected rect\n");
4895 /* check how origin affects bounds */
4896 SetRectEmpty(&rect
);
4897 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect
);
4898 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4899 ok(!IsRectEmpty(&rect
), "got empty rect\n");
4900 IDWriteGlyphRunAnalysis_Release(analysis
);
4903 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 2.0, NULL
,
4904 DWRITE_RENDERING_MODE_ALIASED
, DWRITE_MEASURING_MODE_NATURAL
,
4905 0.0, 0.0, &analysis
);
4906 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4907 SetRectEmpty(&rect2
);
4908 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect2
);
4909 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4910 ok(rect
.right
- rect
.left
< rect2
.right
- rect2
.left
, "expected wider rect\n");
4911 ok(rect
.bottom
- rect
.top
< rect2
.bottom
- rect2
.top
, "expected taller rect\n");
4912 IDWriteGlyphRunAnalysis_Release(analysis
);
4914 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 1.0, NULL
,
4915 DWRITE_RENDERING_MODE_ALIASED
, DWRITE_MEASURING_MODE_NATURAL
,
4916 10.0, -5.0, &analysis
);
4917 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4919 SetRectEmpty(&rect2
);
4920 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect2
);
4921 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4922 ok(!IsRectEmpty(&rect2
), "got empty rect\n");
4923 IDWriteGlyphRunAnalysis_Release(analysis
);
4925 ok(!EqualRect(&rect
, &rect2
), "got equal bounds\n");
4926 OffsetRect(&rect
, 10, -5);
4927 ok(EqualRect(&rect
, &rect2
), "got different bounds\n");
4929 for (i
= 0; i
< sizeof(rendermodes
)/sizeof(rendermodes
[0]); i
++) {
4930 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 1.0, NULL
,
4931 rendermodes
[i
], DWRITE_MEASURING_MODE_NATURAL
,
4932 0.0, 0.0, &analysis
);
4933 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4935 if (rendermodes
[i
] == DWRITE_RENDERING_MODE_ALIASED
) {
4936 SetRectEmpty(&rect
);
4937 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect
);
4938 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4939 ok(!IsRectEmpty(&rect
), "got empty rect\n");
4941 SetRect(&rect
, 0, 0, 1, 1);
4942 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_CLEARTYPE_3x1
, &rect
);
4943 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4944 ok(IsRectEmpty(&rect
), "unexpected empty rect\n");
4947 SetRect(&rect
, 0, 0, 1, 1);
4948 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect
);
4949 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4950 ok(IsRectEmpty(&rect
), "got empty rect\n");
4952 SetRectEmpty(&rect
);
4953 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_CLEARTYPE_3x1
, &rect
);
4954 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4955 ok(!IsRectEmpty(&rect
), "got empty rect\n");
4958 IDWriteGlyphRunAnalysis_Release(analysis
);
4961 IDWriteFontFace_GetMetrics(run
.fontFace
, &fm
);
4963 /* check bbox for a single glyph run */
4964 for (run
.fontEmSize
= 1.0; run
.fontEmSize
<= 100.0; run
.fontEmSize
+= 1.0) {
4965 DWRITE_GLYPH_METRICS gm
;
4968 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 1.0, NULL
,
4969 DWRITE_RENDERING_MODE_ALIASED
, DWRITE_MEASURING_MODE_GDI_CLASSIC
,
4970 0.0, 0.0, &analysis
);
4971 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4973 SetRectEmpty(&rect
);
4974 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect
);
4975 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4977 hr
= IDWriteFontFace_GetGdiCompatibleGlyphMetrics(run
.fontFace
, run
.fontEmSize
, 1.0, NULL
,
4978 DWRITE_MEASURING_MODE_GDI_CLASSIC
, run
.glyphIndices
, 1, &gm
, run
.isSideways
);
4979 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4981 /* metrics are in design units */
4982 bboxX
= (int)floorf((gm
.advanceWidth
- gm
.leftSideBearing
- gm
.rightSideBearing
) * run
.fontEmSize
/ fm
.designUnitsPerEm
+ 0.5f
);
4983 bboxY
= (int)floorf((gm
.advanceHeight
- gm
.topSideBearing
- gm
.bottomSideBearing
) * run
.fontEmSize
/ fm
.designUnitsPerEm
+ 0.5f
);
4985 rect
.right
-= rect
.left
;
4986 rect
.bottom
-= rect
.top
;
4987 ok(abs(bboxX
- rect
.right
) <= 2, "%.0f: bbox width %d, from metrics %d\n", run
.fontEmSize
, rect
.right
, bboxX
);
4988 ok(abs(bboxY
- rect
.bottom
) <= 2, "%.0f: bbox height %d, from metrics %d\n", run
.fontEmSize
, rect
.bottom
, bboxY
);
4990 IDWriteGlyphRunAnalysis_Release(analysis
);
4993 /* without offsets */
4994 run
.fontFace
= face
;
4995 run
.fontEmSize
= 24.0;
4997 run
.glyphIndices
= &glyph
;
4998 run
.glyphAdvances
= advances
;
4999 run
.glyphOffsets
= NULL
;
5000 run
.isSideways
= FALSE
;
5003 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 1.0, NULL
,
5004 DWRITE_RENDERING_MODE_ALIASED
, DWRITE_MEASURING_MODE_NATURAL
,
5005 0.0, 0.0, &analysis
);
5006 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5008 SetRectEmpty(&rect
);
5009 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect
);
5010 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5011 ok(!IsRectEmpty(&rect
), "got empty bounds\n");
5013 IDWriteGlyphRunAnalysis_Release(analysis
);
5015 /* without explicit advances */
5016 run
.fontFace
= face
;
5017 run
.fontEmSize
= 24.0;
5019 run
.glyphIndices
= &glyph
;
5020 run
.glyphAdvances
= NULL
;
5021 run
.glyphOffsets
= NULL
;
5022 run
.isSideways
= FALSE
;
5025 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 1.0, NULL
,
5026 DWRITE_RENDERING_MODE_ALIASED
, DWRITE_MEASURING_MODE_NATURAL
,
5027 0.0, 0.0, &analysis
);
5028 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5030 SetRectEmpty(&rect
);
5031 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect
);
5032 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5033 ok(!IsRectEmpty(&rect
), "got empty bounds\n");
5035 IDWriteGlyphRunAnalysis_Release(analysis
);
5037 /* test that advances are scaled according to ppdip too */
5038 glyphs
[0] = glyphs
[1] = glyph
;
5039 advances
[0] = advances
[1] = 100.0f
;
5040 run
.fontFace
= face
;
5041 run
.fontEmSize
= 24.0;
5043 run
.glyphIndices
= glyphs
;
5044 run
.glyphAdvances
= advances
;
5045 run
.glyphOffsets
= NULL
;
5046 run
.isSideways
= FALSE
;
5049 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 1.0, NULL
,
5050 DWRITE_RENDERING_MODE_ALIASED
, DWRITE_MEASURING_MODE_NATURAL
,
5051 0.0, 0.0, &analysis
);
5052 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5054 SetRectEmpty(&rect2
);
5055 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect2
);
5056 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5057 ok(!IsRectEmpty(&rect2
), "got empty bounds\n");
5058 ok(!EqualRect(&rect
, &rect2
), "got wrong rect2\n");
5059 ok((rect2
.right
- rect
.left
) > advances
[0], "got rect width %d for advance %f\n", rect
.right
- rect
.left
, advances
[0]);
5060 IDWriteGlyphRunAnalysis_Release(analysis
);
5062 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 2.0, NULL
,
5063 DWRITE_RENDERING_MODE_ALIASED
, DWRITE_MEASURING_MODE_NATURAL
,
5064 0.0, 0.0, &analysis
);
5065 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5067 SetRectEmpty(&rect
);
5068 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect
);
5069 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5070 ok((rect
.right
- rect
.left
) > 2 * advances
[0], "got rect width %d for advance %f\n", rect
.right
- rect
.left
, advances
[0]);
5071 IDWriteGlyphRunAnalysis_Release(analysis
);
5073 /* with scaling transform */
5074 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 1.0, NULL
,
5075 DWRITE_RENDERING_MODE_ALIASED
, DWRITE_MEASURING_MODE_NATURAL
,
5076 0.0, 0.0, &analysis
);
5077 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5079 SetRectEmpty(&rect
);
5080 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect
);
5081 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5082 ok(!IsRectEmpty(&rect
), "got rect width %d\n", rect
.right
- rect
.left
);
5083 IDWriteGlyphRunAnalysis_Release(analysis
);
5085 memset(&m
, 0, sizeof(m
));
5088 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 1.0, &m
,
5089 DWRITE_RENDERING_MODE_ALIASED
, DWRITE_MEASURING_MODE_NATURAL
,
5090 0.0, 0.0, &analysis
);
5091 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5093 SetRectEmpty(&rect2
);
5094 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect2
);
5095 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5096 ok((rect2
.right
- rect2
.left
) > (rect
.right
- rect
.left
), "got rect width %d\n", rect2
.right
- rect2
.left
);
5098 /* instances are not reused for same runs */
5099 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 1.0, &m
,
5100 DWRITE_RENDERING_MODE_ALIASED
, DWRITE_MEASURING_MODE_NATURAL
,
5101 0.0, 0.0, &analysis2
);
5102 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5103 ok(analysis2
!= analysis
, "got %p, previous instance %p\n", analysis2
, analysis
);
5104 IDWriteGlyphRunAnalysis_Release(analysis2
);
5106 IDWriteGlyphRunAnalysis_Release(analysis
);
5108 if (IDWriteFactory_QueryInterface(factory
, &IID_IDWriteFactory2
, (void **)&factory2
) == S_OK
) {
5109 FLOAT gamma
, contrast
, cleartype_level
;
5111 /* Invalid antialias mode. */
5112 hr
= IDWriteFactory2_CreateGlyphRunAnalysis(factory2
, &run
, NULL
, DWRITE_RENDERING_MODE_ALIASED
,
5113 DWRITE_MEASURING_MODE_NATURAL
, DWRITE_GRID_FIT_MODE_DEFAULT
, DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
+ 1,
5114 0.0f
, 0.0f
, &analysis
);
5115 ok(hr
== E_INVALIDARG
, "Unexpected hr %#x.\n", hr
);
5117 /* Invalid grid fit mode. */
5118 hr
= IDWriteFactory2_CreateGlyphRunAnalysis(factory2
, &run
, NULL
, DWRITE_RENDERING_MODE_ALIASED
,
5119 DWRITE_MEASURING_MODE_NATURAL
, DWRITE_GRID_FIT_MODE_ENABLED
+ 1, DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
,
5120 0.0f
, 0.0f
, &analysis
);
5121 ok(hr
== E_INVALIDARG
, "Unexpected hr %#x.\n", hr
);
5123 /* Invalid rendering mode. */
5124 hr
= IDWriteFactory2_CreateGlyphRunAnalysis(factory2
, &run
, NULL
, DWRITE_RENDERING_MODE_OUTLINE
,
5125 DWRITE_MEASURING_MODE_NATURAL
, DWRITE_GRID_FIT_MODE_ENABLED
, DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
,
5126 0.0f
, 0.0f
, &analysis
);
5127 ok(hr
== E_INVALIDARG
, "Unexpected hr %#x.\n", hr
);
5129 /* Invalid measuring mode. */
5130 hr
= IDWriteFactory2_CreateGlyphRunAnalysis(factory2
, &run
, NULL
, DWRITE_RENDERING_MODE_ALIASED
,
5131 DWRITE_MEASURING_MODE_GDI_NATURAL
+ 1, DWRITE_GRID_FIT_MODE_ENABLED
, DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
,
5132 0.0f
, 0.0f
, &analysis
);
5133 ok(hr
== E_INVALIDARG
, "Unexpected hr %#x.\n", hr
);
5135 /* Win8 does not accept default grid fitting mode. */
5136 hr
= IDWriteFactory2_CreateGlyphRunAnalysis(factory2
, &run
, NULL
, DWRITE_RENDERING_MODE_NATURAL
,
5137 DWRITE_MEASURING_MODE_NATURAL
, DWRITE_GRID_FIT_MODE_DEFAULT
, DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
,
5138 0.0f
, 0.0f
, &analysis
);
5139 ok(hr
== S_OK
|| broken(hr
== E_INVALIDARG
) /* Win8 */, "Failed to create analysis, hr %#x.\n", hr
);
5141 IDWriteGlyphRunAnalysis_Release(analysis
);
5143 /* Natural mode, grayscale antialiased. */
5144 hr
= IDWriteFactory2_CreateGlyphRunAnalysis(factory2
, &run
, NULL
, DWRITE_RENDERING_MODE_NATURAL
,
5145 DWRITE_MEASURING_MODE_NATURAL
, DWRITE_GRID_FIT_MODE_DISABLED
, DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
,
5146 0.0f
, 0.0f
, &analysis
);
5147 ok(hr
== S_OK
, "Failed to create analysis, hr %#x.\n", hr
);
5149 SetRect(&rect
, 0, 1, 0, 1);
5150 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_CLEARTYPE_3x1
, &rect
);
5151 ok(hr
== S_OK
, "Failed to get texture bounds, hr %#x.\n", hr
);
5152 ok(IsRectEmpty(&rect
), "Expected empty bbox.\n");
5154 SetRectEmpty(&rect
);
5155 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect
);
5156 ok(hr
== S_OK
, "Failed to get texture bounds, hr %#x.\n", hr
);
5157 ok(!IsRectEmpty(&rect
), "Unexpected empty bbox.\n");
5159 size
= (rect
.right
- rect
.left
) * (rect
.bottom
- rect
.top
);
5160 bits
= HeapAlloc(GetProcessHeap(), 0, size
);
5162 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect
, bits
, size
);
5163 ok(hr
== S_OK
, "Failed to get alpha texture, hr %#x.\n", hr
);
5165 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect
, bits
, size
- 1);
5166 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "Unexpected hr %#x.\n", hr
);
5168 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_CLEARTYPE_3x1
, &rect
, bits
, size
);
5169 ok(hr
== DWRITE_E_UNSUPPORTEDOPERATION
, "Unexpected hr %#x.\n", hr
);
5171 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_CLEARTYPE_3x1
, &rect
, bits
, size
- 1);
5173 ok(hr
== DWRITE_E_UNSUPPORTEDOPERATION
, "Unexpected hr %#x.\n", hr
);
5175 HeapFree(GetProcessHeap(), 0, bits
);
5177 hr
= IDWriteFactory_CreateCustomRenderingParams(factory
, 0.1f
, 0.0f
, 1.0f
, DWRITE_PIXEL_GEOMETRY_FLAT
,
5178 DWRITE_RENDERING_MODE_NATURAL
, ¶ms
);
5179 ok(hr
== S_OK
, "Failed to create custom parameters, hr %#x.\n", hr
);
5181 hr
= IDWriteGlyphRunAnalysis_GetAlphaBlendParams(analysis
, params
, &gamma
, &contrast
, &cleartype_level
);
5182 ok(hr
== S_OK
, "Failed to get alpha blend params, hr %#x.\n", hr
);
5184 ok(cleartype_level
== 0.0f
, "Unexpected cleartype level %f.\n", cleartype_level
);
5186 IDWriteRenderingParams_Release(params
);
5187 IDWriteGlyphRunAnalysis_Release(analysis
);
5189 IDWriteFactory2_Release(factory2
);
5192 if (IDWriteFactory_QueryInterface(factory
, &IID_IDWriteFactory3
, (void **)&factory3
) == S_OK
) {
5194 /* Invalid antialias mode. */
5195 hr
= IDWriteFactory3_CreateGlyphRunAnalysis(factory3
, &run
, NULL
, DWRITE_RENDERING_MODE1_ALIASED
,
5196 DWRITE_MEASURING_MODE_NATURAL
, DWRITE_GRID_FIT_MODE_DEFAULT
, DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
+ 1,
5197 0.0f
, 0.0f
, &analysis
);
5198 ok(hr
== E_INVALIDARG
, "Unexpected hr %#x.\n", hr
);
5200 /* Invalid grid fit mode. */
5201 hr
= IDWriteFactory3_CreateGlyphRunAnalysis(factory3
, &run
, NULL
, DWRITE_RENDERING_MODE1_ALIASED
,
5202 DWRITE_MEASURING_MODE_NATURAL
, DWRITE_GRID_FIT_MODE_ENABLED
+ 1, DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
,
5203 0.0f
, 0.0f
, &analysis
);
5204 ok(hr
== E_INVALIDARG
, "Unexpected hr %#x.\n", hr
);
5206 /* Invalid rendering mode. */
5207 hr
= IDWriteFactory3_CreateGlyphRunAnalysis(factory3
, &run
, NULL
, DWRITE_RENDERING_MODE1_OUTLINE
,
5208 DWRITE_MEASURING_MODE_NATURAL
, DWRITE_GRID_FIT_MODE_ENABLED
, DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
,
5209 0.0f
, 0.0f
, &analysis
);
5210 ok(hr
== E_INVALIDARG
, "Unexpected hr %#x.\n", hr
);
5212 /* Invalid measuring mode. */
5213 hr
= IDWriteFactory3_CreateGlyphRunAnalysis(factory3
, &run
, NULL
, DWRITE_RENDERING_MODE1_ALIASED
,
5214 DWRITE_MEASURING_MODE_GDI_NATURAL
+ 1, DWRITE_GRID_FIT_MODE_ENABLED
,
5215 DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
, 0.0f
, 0.0f
, &analysis
);
5216 ok(hr
== E_INVALIDARG
, "Unexpected hr %#x.\n", hr
);
5218 hr
= IDWriteFactory3_CreateGlyphRunAnalysis(factory3
, &run
, NULL
, DWRITE_RENDERING_MODE1_NATURAL
,
5219 DWRITE_MEASURING_MODE_NATURAL
, DWRITE_GRID_FIT_MODE_DEFAULT
, DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
,
5220 0.0f
, 0.0f
, &analysis
);
5221 ok(hr
== S_OK
, "Failed to create analysis, hr %#x.\n", hr
);
5222 IDWriteGlyphRunAnalysis_Release(analysis
);
5224 /* Natural mode, grayscale antialiased. */
5225 hr
= IDWriteFactory3_CreateGlyphRunAnalysis(factory3
, &run
, NULL
, DWRITE_RENDERING_MODE1_NATURAL
,
5226 DWRITE_MEASURING_MODE_NATURAL
, DWRITE_GRID_FIT_MODE_DISABLED
, DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
,
5227 0.0f
, 0.0f
, &analysis
);
5228 ok(hr
== S_OK
, "Failed to create analysis, hr %#x.\n", hr
);
5230 SetRect(&rect
, 0, 1, 0, 1);
5231 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_CLEARTYPE_3x1
, &rect
);
5232 ok(hr
== S_OK
, "Failed to get texture bounds, hr %#x.\n", hr
);
5233 ok(IsRectEmpty(&rect
), "Expected empty bbox.\n");
5235 SetRectEmpty(&rect
);
5236 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect
);
5237 ok(hr
== S_OK
, "Failed to get texture bounds, hr %#x.\n", hr
);
5238 ok(!IsRectEmpty(&rect
), "Unexpected empty bbox.\n");
5240 size
= (rect
.right
- rect
.left
) * (rect
.bottom
- rect
.top
);
5241 bits
= HeapAlloc(GetProcessHeap(), 0, size
);
5243 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect
, bits
, size
);
5244 ok(hr
== S_OK
, "Failed to get alpha texture, hr %#x.\n", hr
);
5246 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect
, bits
, size
- 1);
5247 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "Unexpected hr %#x.\n", hr
);
5249 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_CLEARTYPE_3x1
, &rect
, bits
, size
);
5250 ok(hr
== DWRITE_E_UNSUPPORTEDOPERATION
, "Unexpected hr %#x.\n", hr
);
5252 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_CLEARTYPE_3x1
, &rect
, bits
, size
- 1);
5254 ok(hr
== DWRITE_E_UNSUPPORTEDOPERATION
, "Unexpected hr %#x.\n", hr
);
5256 HeapFree(GetProcessHeap(), 0, bits
);
5258 IDWriteGlyphRunAnalysis_Release(analysis
);
5260 IDWriteFactory3_Release(factory3
);
5263 IDWriteFontFace_Release(face
);
5264 ref
= IDWriteFactory_Release(factory
);
5265 ok(ref
== 0, "factory not released, %u\n", ref
);
5268 #define round(x) ((int)floor((x) + 0.5))
5299 static const struct VDMX_group
*find_vdmx_group(const struct VDMX_Header
*hdr
)
5301 WORD num_ratios
, i
, group_offset
= 0;
5302 struct VDMX_Ratio
*ratios
= (struct VDMX_Ratio
*)(hdr
+ 1);
5303 BYTE dev_x_ratio
= 1, dev_y_ratio
= 1;
5305 num_ratios
= GET_BE_WORD(hdr
->numRatios
);
5307 for (i
= 0; i
< num_ratios
; i
++)
5309 if (!ratios
[i
].bCharSet
) continue;
5311 if ((ratios
[i
].xRatio
== 0 && ratios
[i
].yStartRatio
== 0 &&
5312 ratios
[i
].yEndRatio
== 0) ||
5313 (ratios
[i
].xRatio
== dev_x_ratio
&& ratios
[i
].yStartRatio
<= dev_y_ratio
&&
5314 ratios
[i
].yEndRatio
>= dev_y_ratio
))
5316 group_offset
= GET_BE_WORD(*((WORD
*)(ratios
+ num_ratios
) + i
));
5321 return (const struct VDMX_group
*)((BYTE
*)hdr
+ group_offset
);
5325 static BOOL
get_vdmx_size(const struct VDMX_group
*group
, int emsize
, int *a
, int *d
)
5328 const struct VDMX_vTable
*tables
;
5330 if (!group
) return FALSE
;
5332 recs
= GET_BE_WORD(group
->recs
);
5333 if (emsize
< group
->startsz
|| emsize
>= group
->endsz
) return FALSE
;
5335 tables
= (const struct VDMX_vTable
*)(group
+ 1);
5336 for (i
= 0; i
< recs
; i
++)
5338 WORD ppem
= GET_BE_WORD(tables
[i
].yPelHeight
);
5341 /* FIXME: Supposed to interpolate */
5342 trace("FIXME interpolate %d\n", emsize
);
5348 *a
= (SHORT
)GET_BE_WORD(tables
[i
].yMax
);
5349 *d
= -(SHORT
)GET_BE_WORD(tables
[i
].yMin
);
5356 static void test_metrics_cmp(FLOAT emsize
, const DWRITE_FONT_METRICS
*metrics
, const DWRITE_FONT_METRICS1
*expected
)
5358 ok(metrics
->designUnitsPerEm
== expected
->designUnitsPerEm
, "%.2f: emsize: got %u expect %u\n",
5359 emsize
, metrics
->designUnitsPerEm
, expected
->designUnitsPerEm
);
5360 ok(metrics
->ascent
== expected
->ascent
, "%.2f a: got %u expect %u\n",
5361 emsize
, metrics
->ascent
, expected
->ascent
);
5362 ok(metrics
->descent
== expected
->descent
, "%.2f d: got %u expect %u\n",
5363 emsize
, metrics
->descent
, expected
->descent
);
5364 ok(metrics
->lineGap
== expected
->lineGap
, "%.2f lg: got %d expect %d\n",
5365 emsize
, metrics
->lineGap
, expected
->lineGap
);
5366 ok(metrics
->capHeight
== expected
->capHeight
, "%.2f capH: got %u expect %u\n",
5367 emsize
, metrics
->capHeight
, expected
->capHeight
);
5368 ok(metrics
->xHeight
== expected
->xHeight
, "%.2f xH: got %u expect %u\n",
5369 emsize
, metrics
->xHeight
, expected
->xHeight
);
5370 ok(metrics
->underlinePosition
== expected
->underlinePosition
, "%.2f ulP: got %d expect %d\n",
5371 emsize
, metrics
->underlinePosition
, expected
->underlinePosition
);
5372 ok(metrics
->underlineThickness
== expected
->underlineThickness
, "%.2f ulTh: got %u expect %u\n",
5373 emsize
, metrics
->underlineThickness
, expected
->underlineThickness
);
5374 ok(metrics
->strikethroughPosition
== expected
->strikethroughPosition
, "%.2f stP: got %d expect %d\n",
5375 emsize
, metrics
->strikethroughPosition
, expected
->strikethroughPosition
);
5376 ok(metrics
->strikethroughThickness
== expected
->strikethroughThickness
, "%.2f stTh: got %u expect %u\n",
5377 emsize
, metrics
->strikethroughThickness
, expected
->strikethroughThickness
);
5380 static void test_metrics1_cmp(FLOAT emsize
, const DWRITE_FONT_METRICS1
*metrics
, const DWRITE_FONT_METRICS1
*expected
)
5382 ok(metrics
->designUnitsPerEm
== expected
->designUnitsPerEm
, "%.2f: emsize: got %u expect %u\n",
5383 emsize
, metrics
->designUnitsPerEm
, expected
->designUnitsPerEm
);
5384 ok(metrics
->ascent
== expected
->ascent
, "%.2f a: got %u expect %u\n",
5385 emsize
, metrics
->ascent
, expected
->ascent
);
5386 ok(metrics
->descent
== expected
->descent
, "%.2f d: got %u expect %u\n",
5387 emsize
, metrics
->descent
, expected
->descent
);
5388 ok(metrics
->lineGap
== expected
->lineGap
, "%.2f lg: got %d expect %d\n",
5389 emsize
, metrics
->lineGap
, expected
->lineGap
);
5390 ok(metrics
->capHeight
== expected
->capHeight
, "%.2f capH: got %u expect %u\n",
5391 emsize
, metrics
->capHeight
, expected
->capHeight
);
5392 ok(metrics
->xHeight
== expected
->xHeight
, "%.2f xH: got %u expect %u\n",
5393 emsize
, metrics
->xHeight
, expected
->xHeight
);
5394 ok(metrics
->underlinePosition
== expected
->underlinePosition
, "%.2f ulP: got %d expect %d\n",
5395 emsize
, metrics
->underlinePosition
, expected
->underlinePosition
);
5396 ok(metrics
->underlineThickness
== expected
->underlineThickness
, "%.2f ulTh: got %u expect %u\n",
5397 emsize
, metrics
->underlineThickness
, expected
->underlineThickness
);
5398 ok(metrics
->strikethroughPosition
== expected
->strikethroughPosition
, "%.2f stP: got %d expect %d\n",
5399 emsize
, metrics
->strikethroughPosition
, expected
->strikethroughPosition
);
5400 ok(metrics
->strikethroughThickness
== expected
->strikethroughThickness
, "%.2f stTh: got %u expect %u\n",
5401 emsize
, metrics
->strikethroughThickness
, expected
->strikethroughThickness
);
5402 ok(metrics
->glyphBoxLeft
== expected
->glyphBoxLeft
, "%.2f box left: got %d expect %d\n",
5403 emsize
, metrics
->glyphBoxLeft
, expected
->glyphBoxLeft
);
5404 if (0) { /* this is not consistent */
5405 ok(metrics
->glyphBoxTop
== expected
->glyphBoxTop
, "%.2f box top: got %d expect %d\n",
5406 emsize
, metrics
->glyphBoxTop
, expected
->glyphBoxTop
);
5407 ok(metrics
->glyphBoxRight
== expected
->glyphBoxRight
, "%.2f box right: got %d expect %d\n",
5408 emsize
, metrics
->glyphBoxRight
, expected
->glyphBoxRight
);
5410 ok(metrics
->glyphBoxBottom
== expected
->glyphBoxBottom
, "%.2f box bottom: got %d expect %d\n",
5411 emsize
, metrics
->glyphBoxBottom
, expected
->glyphBoxBottom
);
5412 ok(metrics
->subscriptPositionX
== expected
->subscriptPositionX
, "%.2f subX: got %d expect %d\n",
5413 emsize
, metrics
->subscriptPositionX
, expected
->subscriptPositionX
);
5414 ok(metrics
->subscriptPositionY
== expected
->subscriptPositionY
, "%.2f subY: got %d expect %d\n",
5415 emsize
, metrics
->subscriptPositionY
, expected
->subscriptPositionY
);
5416 ok(metrics
->subscriptSizeX
== expected
->subscriptSizeX
, "%.2f subsizeX: got %d expect %d\n",
5417 emsize
, metrics
->subscriptSizeX
, expected
->subscriptSizeX
);
5418 ok(metrics
->subscriptPositionY
== expected
->subscriptPositionY
, "%.2f subsizeY: got %d expect %d\n",
5419 emsize
, metrics
->subscriptSizeY
, expected
->subscriptSizeY
);
5420 ok(metrics
->superscriptPositionX
== expected
->superscriptPositionX
, "%.2f supX: got %d expect %d\n",
5421 emsize
, metrics
->superscriptPositionX
, expected
->superscriptPositionX
);
5423 ok(metrics
->superscriptPositionY
== expected
->superscriptPositionY
, "%.2f supY: got %d expect %d\n",
5424 emsize
, metrics
->superscriptPositionY
, expected
->superscriptPositionY
);
5425 ok(metrics
->superscriptSizeX
== expected
->superscriptSizeX
, "%.2f supsizeX: got %d expect %d\n",
5426 emsize
, metrics
->superscriptSizeX
, expected
->superscriptSizeX
);
5427 ok(metrics
->superscriptSizeY
== expected
->superscriptSizeY
, "%.2f supsizeY: got %d expect %d\n",
5428 emsize
, metrics
->superscriptSizeY
, expected
->superscriptSizeY
);
5429 ok(metrics
->hasTypographicMetrics
== expected
->hasTypographicMetrics
, "%.2f hastypo: got %d expect %d\n",
5430 emsize
, metrics
->hasTypographicMetrics
, expected
->hasTypographicMetrics
);
5433 struct compatmetrics_test
{
5439 static struct compatmetrics_test compatmetrics_tests
[] = {
5440 { { 0.0, 0.0, 0.0, 1.0, 0.0, 0.0 }, 1.0, 5.0 },
5441 { { 0.0, 0.0, 0.0, -1.0, 0.0, 0.0 }, 1.0, 5.0 },
5442 { { 0.0, 0.0, 0.0, -1.0, 0.0, 0.0 }, 2.0, 5.0 },
5443 { { 0.0, 0.0, 0.0, 3.0, 0.0, 0.0 }, 2.0, 5.0 },
5444 { { 0.0, 0.0, 0.0, -3.0, 0.0, 0.0 }, 2.0, 5.0 },
5445 { { 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 }, 2.0, 5.0 },
5446 { { 1.0, 0.0, 0.0, 1.0, 5.0, 0.0 }, 2.0, 5.0 },
5447 { { 1.0, 0.0, 0.0, 1.0, 0.0, 5.0 }, 2.0, 5.0 },
5450 static void get_expected_metrics(IDWriteFontFace
*fontface
, struct compatmetrics_test
*ptr
,
5451 DWRITE_FONT_METRICS
*expected
)
5455 memset(expected
, 0, sizeof(*expected
));
5456 hr
= IDWriteFontFace_GetGdiCompatibleMetrics(fontface
, ptr
->ppdip
* fabsf(ptr
->m
.m22
) * ptr
->emsize
, 1.0, NULL
, expected
);
5457 ok(hr
== S_OK
, "got %08x\n", hr
);
5460 static void test_gdicompat_metrics(IDWriteFontFace
*face
)
5462 IDWriteFontFace1
*fontface1
= NULL
;
5464 DWRITE_FONT_METRICS design_metrics
, comp_metrics
;
5465 DWRITE_FONT_METRICS1 design_metrics1
, expected
;
5466 FLOAT emsize
, scale
;
5467 int ascent
, descent
;
5468 const struct VDMX_Header
*vdmx
;
5472 const struct VDMX_group
*vdmx_group
= NULL
;
5475 hr
= IDWriteFontFace_QueryInterface(face
, &IID_IDWriteFontFace1
, (void**)&fontface1
);
5477 win_skip("gdi compatible DWRITE_FONT_METRICS1 are not supported.\n");
5480 IDWriteFontFace1_GetMetrics(fontface1
, &design_metrics1
);
5481 memcpy(&design_metrics
, &design_metrics1
, sizeof(design_metrics
));
5484 IDWriteFontFace_GetMetrics(face
, &design_metrics
);
5486 hr
= IDWriteFontFace_TryGetFontTable(face
, MS_VDMX_TAG
, (const void **)&vdmx
,
5487 &vdmx_len
, &vdmx_ctx
, &exists
);
5488 if (hr
!= S_OK
|| !exists
)
5491 vdmx_group
= find_vdmx_group(vdmx
);
5493 /* negative emsize */
5494 memset(&comp_metrics
, 0xcc, sizeof(comp_metrics
));
5495 memset(&expected
, 0, sizeof(expected
));
5496 hr
= IDWriteFontFace_GetGdiCompatibleMetrics(face
, -10.0, 1.0, NULL
, &comp_metrics
);
5497 ok(hr
== E_INVALIDARG
, "got %08x\n", hr
);
5498 test_metrics_cmp(0.0, &comp_metrics
, &expected
);
5501 memset(&comp_metrics
, 0xcc, sizeof(comp_metrics
));
5502 memset(&expected
, 0, sizeof(expected
));
5503 hr
= IDWriteFontFace_GetGdiCompatibleMetrics(face
, 0.0, 1.0, NULL
, &comp_metrics
);
5504 ok(hr
== E_INVALIDARG
, "got %08x\n", hr
);
5505 test_metrics_cmp(0.0, &comp_metrics
, &expected
);
5507 /* zero pixels per dip */
5508 memset(&comp_metrics
, 0xcc, sizeof(comp_metrics
));
5509 memset(&expected
, 0, sizeof(expected
));
5510 hr
= IDWriteFontFace_GetGdiCompatibleMetrics(face
, 5.0, 0.0, NULL
, &comp_metrics
);
5511 ok(hr
== E_INVALIDARG
, "got %08x\n", hr
);
5512 test_metrics_cmp(5.0, &comp_metrics
, &expected
);
5514 memset(&comp_metrics
, 0xcc, sizeof(comp_metrics
));
5515 hr
= IDWriteFontFace_GetGdiCompatibleMetrics(face
, 5.0, -1.0, NULL
, &comp_metrics
);
5516 ok(hr
== E_INVALIDARG
, "got %08x\n", hr
);
5517 test_metrics_cmp(5.0, &comp_metrics
, &expected
);
5519 for (i
= 0; i
< sizeof(compatmetrics_tests
)/sizeof(compatmetrics_tests
[0]); i
++) {
5520 struct compatmetrics_test
*ptr
= &compatmetrics_tests
[i
];
5522 get_expected_metrics(face
, ptr
, (DWRITE_FONT_METRICS
*)&expected
);
5523 hr
= IDWriteFontFace_GetGdiCompatibleMetrics(face
, ptr
->emsize
, ptr
->ppdip
, &ptr
->m
, &comp_metrics
);
5524 ok(hr
== S_OK
, "got %08x\n", hr
);
5525 test_metrics_cmp(ptr
->emsize
, &comp_metrics
, &expected
);
5528 for (emsize
= 5; emsize
<= design_metrics
.designUnitsPerEm
; emsize
++)
5530 DWRITE_FONT_METRICS1 comp_metrics1
, expected
;
5533 hr
= IDWriteFontFace1_GetGdiCompatibleMetrics(fontface1
, emsize
, 1.0, NULL
, &comp_metrics1
);
5534 ok(hr
== S_OK
, "got %08x\n", hr
);
5537 hr
= IDWriteFontFace_GetGdiCompatibleMetrics(face
, emsize
, 1.0, NULL
, &comp_metrics
);
5538 ok(hr
== S_OK
, "got %08x\n", hr
);
5541 scale
= emsize
/ design_metrics
.designUnitsPerEm
;
5542 if (!get_vdmx_size(vdmx_group
, emsize
, &ascent
, &descent
))
5544 ascent
= round(design_metrics
.ascent
* scale
);
5545 descent
= round(design_metrics
.descent
* scale
);
5548 expected
.designUnitsPerEm
= design_metrics
.designUnitsPerEm
;
5549 expected
.ascent
= round(ascent
/ scale
);
5550 expected
.descent
= round(descent
/ scale
);
5551 expected
.lineGap
= round(round(design_metrics
.lineGap
* scale
) / scale
);
5552 expected
.capHeight
= round(round(design_metrics
.capHeight
* scale
) / scale
);
5553 expected
.xHeight
= round(round(design_metrics
.xHeight
* scale
) / scale
);
5554 expected
.underlinePosition
= round(round(design_metrics
.underlinePosition
* scale
) / scale
);
5555 expected
.underlineThickness
= round(round(design_metrics
.underlineThickness
* scale
) / scale
);
5556 expected
.strikethroughPosition
= round(round(design_metrics
.strikethroughPosition
* scale
) / scale
);
5557 expected
.strikethroughThickness
= round(round(design_metrics
.strikethroughThickness
* scale
) / scale
);
5560 expected
.glyphBoxLeft
= round(round(design_metrics1
.glyphBoxLeft
* scale
) / scale
);
5562 if (0) { /* those two fail on Tahoma and Win7 */
5563 expected
.glyphBoxTop
= round(round(design_metrics1
.glyphBoxTop
* scale
) / scale
);
5564 expected
.glyphBoxRight
= round(round(design_metrics1
.glyphBoxRight
* scale
) / scale
);
5566 expected
.glyphBoxBottom
= round(round(design_metrics1
.glyphBoxBottom
* scale
) / scale
);
5567 expected
.subscriptPositionX
= round(round(design_metrics1
.subscriptPositionX
* scale
) / scale
);
5568 expected
.subscriptPositionY
= round(round(design_metrics1
.subscriptPositionY
* scale
) / scale
);
5569 expected
.subscriptSizeX
= round(round(design_metrics1
.subscriptSizeX
* scale
) / scale
);
5570 expected
.subscriptSizeY
= round(round(design_metrics1
.subscriptSizeY
* scale
) / scale
);
5571 expected
.superscriptPositionX
= round(round(design_metrics1
.superscriptPositionX
* scale
) / scale
);
5572 if (0) /* this fails for 3 emsizes, Tahoma from [5, 2048] range */ {
5573 expected
.superscriptPositionY
= round(round(design_metrics1
.superscriptPositionY
* scale
) / scale
);
5575 expected
.superscriptSizeX
= round(round(design_metrics1
.superscriptSizeX
* scale
) / scale
);
5576 expected
.superscriptSizeY
= round(round(design_metrics1
.superscriptSizeY
* scale
) / scale
);
5577 expected
.hasTypographicMetrics
= design_metrics1
.hasTypographicMetrics
;
5579 test_metrics1_cmp(emsize
, &comp_metrics1
, &expected
);
5582 test_metrics_cmp(emsize
, &comp_metrics
, &expected
);
5587 IDWriteFontFace1_Release(fontface1
);
5588 if (vdmx
) IDWriteFontFace_ReleaseFontTable(face
, vdmx_ctx
);
5591 static void test_GetGdiCompatibleMetrics(void)
5593 IDWriteFactory
*factory
;
5595 IDWriteFontFace
*fontface
;
5599 factory
= create_factory();
5601 font
= get_font(factory
, tahomaW
, DWRITE_FONT_STYLE_NORMAL
);
5602 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
5603 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5604 IDWriteFont_Release(font
);
5605 test_gdicompat_metrics(fontface
);
5606 IDWriteFontFace_Release(fontface
);
5608 font
= get_font(factory
, arialW
, DWRITE_FONT_STYLE_NORMAL
);
5610 skip("Skipping tests with Arial\n");
5613 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
5614 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5615 IDWriteFont_Release(font
);
5617 test_gdicompat_metrics(fontface
);
5618 IDWriteFontFace_Release(fontface
);
5621 ref
= IDWriteFactory_Release(factory
);
5622 ok(ref
== 0, "factory not released, %u\n", ref
);
5625 static void get_expected_panose(IDWriteFont1
*font
, DWRITE_PANOSE
*panose
)
5627 IDWriteFontFace
*fontface
;
5628 const TT_OS2_V2
*tt_os2
;
5634 memset(panose
, 0, sizeof(*panose
));
5636 hr
= IDWriteFont1_CreateFontFace(font
, &fontface
);
5637 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5639 hr
= IDWriteFontFace_TryGetFontTable(fontface
, MS_0S2_TAG
, (const void **)&tt_os2
, &size
, &os2_context
, &exists
);
5640 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5643 memcpy(panose
, &tt_os2
->panose
, sizeof(*panose
));
5644 IDWriteFontFace_ReleaseFontTable(fontface
, os2_context
);
5647 IDWriteFontFace_Release(fontface
);
5650 static void test_GetPanose(void)
5652 IDWriteFontCollection
*syscollection
;
5653 IDWriteFactory
*factory
;
5654 IDWriteFont1
*font1
;
5660 factory
= create_factory();
5661 font
= get_tahoma_instance(factory
, DWRITE_FONT_STYLE_NORMAL
);
5663 hr
= IDWriteFont_QueryInterface(font
, &IID_IDWriteFont1
, (void **)&font1
);
5664 IDWriteFont_Release(font
);
5667 ref
= IDWriteFactory_Release(factory
);
5668 ok(ref
== 0, "factory not released, %u\n", ref
);
5669 win_skip("GetPanose() is not supported.\n");
5672 IDWriteFont1_Release(font1
);
5674 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &syscollection
, FALSE
);
5675 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5676 count
= IDWriteFontCollection_GetFontFamilyCount(syscollection
);
5678 for (i
= 0; i
< count
; i
++) {
5679 DWRITE_PANOSE panose
, expected_panose
;
5680 IDWriteLocalizedStrings
*names
;
5681 IDWriteFontFace3
*fontface3
;
5682 IDWriteFontFace
*fontface
;
5683 IDWriteFontFamily
*family
;
5684 IDWriteFont1
*font1
;
5688 hr
= IDWriteFontCollection_GetFontFamily(syscollection
, i
, &family
);
5689 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5691 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STRETCH_NORMAL
,
5692 DWRITE_FONT_STYLE_NORMAL
, &font
);
5693 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5695 hr
= IDWriteFont_QueryInterface(font
, &IID_IDWriteFont1
, (void **)&font1
);
5696 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5697 IDWriteFont_Release(font
);
5699 hr
= IDWriteFontFamily_GetFamilyNames(family
, &names
);
5700 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5702 get_enus_string(names
, nameW
, sizeof(nameW
)/sizeof(nameW
[0]));
5704 IDWriteLocalizedStrings_Release(names
);
5706 IDWriteFont1_GetPanose(font1
, &panose
);
5707 get_expected_panose(font1
, &expected_panose
);
5709 ok(panose
.values
[0] == expected_panose
.values
[0], "%s: values[0] %#x, expected %#x.\n", wine_dbgstr_w(nameW
),
5710 panose
.values
[0], expected_panose
.values
[0]);
5711 ok(panose
.values
[1] == expected_panose
.values
[1], "%s: values[1] %#x, expected %#x.\n", wine_dbgstr_w(nameW
),
5712 panose
.values
[1], expected_panose
.values
[1]);
5713 ok(panose
.values
[2] == expected_panose
.values
[2], "%s: values[2] %#x, expected %#x.\n", wine_dbgstr_w(nameW
),
5714 panose
.values
[2], expected_panose
.values
[2]);
5715 ok(panose
.values
[3] == expected_panose
.values
[3], "%s: values[3] %#x, expected %#x.\n", wine_dbgstr_w(nameW
),
5716 panose
.values
[3], expected_panose
.values
[3]);
5717 ok(panose
.values
[4] == expected_panose
.values
[4], "%s: values[4] %#x, expected %#x.\n", wine_dbgstr_w(nameW
),
5718 panose
.values
[4], expected_panose
.values
[4]);
5719 ok(panose
.values
[5] == expected_panose
.values
[5], "%s: values[5] %#x, expected %#x.\n", wine_dbgstr_w(nameW
),
5720 panose
.values
[5], expected_panose
.values
[5]);
5721 ok(panose
.values
[6] == expected_panose
.values
[6], "%s: values[6] %#x, expected %#x.\n", wine_dbgstr_w(nameW
),
5722 panose
.values
[6], expected_panose
.values
[6]);
5723 ok(panose
.values
[7] == expected_panose
.values
[7], "%s: values[7] %#x, expected %#x.\n", wine_dbgstr_w(nameW
),
5724 panose
.values
[7], expected_panose
.values
[7]);
5725 ok(panose
.values
[8] == expected_panose
.values
[8], "%s: values[8] %#x, expected %#x.\n", wine_dbgstr_w(nameW
),
5726 panose
.values
[8], expected_panose
.values
[8]);
5727 ok(panose
.values
[9] == expected_panose
.values
[9], "%s: values[9] %#x, expected %#x.\n", wine_dbgstr_w(nameW
),
5728 panose
.values
[9], expected_panose
.values
[9]);
5730 hr
= IDWriteFont1_CreateFontFace(font1
, &fontface
);
5731 ok(hr
== S_OK
, "Failed to create a font face, %#x.\n", hr
);
5732 if (IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace3
, (void **)&fontface3
) == S_OK
) {
5733 ok(!memcmp(&panose
, &expected_panose
, sizeof(panose
)), "%s: Unexpected panose from font face.\n",
5734 wine_dbgstr_w(nameW
));
5735 IDWriteFontFace3_Release(fontface3
);
5737 IDWriteFontFace_Release(fontface
);
5739 IDWriteFont1_Release(font1
);
5740 IDWriteFontFamily_Release(family
);
5743 IDWriteFontCollection_Release(syscollection
);
5744 ref
= IDWriteFactory_Release(factory
);
5745 ok(ref
== 0, "factory not released, %u\n", ref
);
5748 static INT32
get_gdi_font_advance(HDC hdc
, FLOAT emsize
)
5755 memset(&logfont
, 0, sizeof(logfont
));
5756 logfont
.lfHeight
= (LONG
)-emsize
;
5757 logfont
.lfWeight
= FW_NORMAL
;
5758 logfont
.lfQuality
= CLEARTYPE_QUALITY
;
5759 lstrcpyW(logfont
.lfFaceName
, tahomaW
);
5761 hfont
= CreateFontIndirectW(&logfont
);
5762 SelectObject(hdc
, hfont
);
5764 ret
= GetCharABCWidthsW(hdc
, 'A', 'A', &abc
);
5765 ok(ret
, "got %d\n", ret
);
5767 DeleteObject(hfont
);
5769 return abc
.abcA
+ abc
.abcB
+ abc
.abcC
;
5772 static void test_GetGdiCompatibleGlyphAdvances(void)
5774 IDWriteFontFace1
*fontface1
;
5775 IDWriteFontFace
*fontface
;
5776 IDWriteFactory
*factory
;
5783 DWRITE_FONT_METRICS1 fm
;
5787 factory
= create_factory();
5788 font
= get_tahoma_instance(factory
, DWRITE_FONT_STYLE_NORMAL
);
5790 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
5791 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5792 IDWriteFont_Release(font
);
5794 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void **)&fontface1
);
5795 IDWriteFontFace_Release(fontface
);
5798 ref
= IDWriteFactory_Release(factory
);
5799 ok(ref
== 0, "factory not released, %u\n", ref
);
5800 win_skip("GetGdiCompatibleGlyphAdvances() is not supported\n");
5806 hr
= IDWriteFontFace1_GetGlyphIndices(fontface1
, &codepoint
, 1, &glyph
);
5807 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5808 ok(glyph
> 0, "got %u\n", glyph
);
5812 hr
= IDWriteFontFace1_GetGdiCompatibleGlyphAdvances(fontface1
, 0.0,
5813 1.0, NULL
, FALSE
, FALSE
, 1, &glyph
, &advance
);
5814 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5815 ok(advance
== 0, "got %d\n", advance
);
5817 /* negative emsize */
5819 hr
= IDWriteFontFace1_GetGdiCompatibleGlyphAdvances(fontface1
, -1.0,
5820 1.0, NULL
, FALSE
, FALSE
, 1, &glyph
, &advance
);
5821 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5822 ok(advance
== 0, "got %d\n", advance
);
5826 hr
= IDWriteFontFace1_GetGdiCompatibleGlyphAdvances(fontface1
, 1.0,
5827 0.0, NULL
, FALSE
, FALSE
, 1, &glyph
, &advance
);
5828 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5829 ok(advance
== 0, "got %d\n", advance
);
5831 /* negative ppdip */
5833 hr
= IDWriteFontFace1_GetGdiCompatibleGlyphAdvances(fontface1
, 1.0,
5834 -1.0, NULL
, FALSE
, FALSE
, 1, &glyph
, &advance
);
5835 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5836 ok(advance
== 0, "got %d\n", advance
);
5838 IDWriteFontFace1_GetMetrics(fontface1
, &fm
);
5840 hdc
= CreateCompatibleDC(0);
5842 for (emsize
= 1.0; emsize
<= fm
.designUnitsPerEm
; emsize
+= 1.0) {
5845 gdi_advance
= get_gdi_font_advance(hdc
, emsize
);
5846 hr
= IDWriteFontFace1_GetGdiCompatibleGlyphAdvances(fontface1
, emsize
,
5847 1.0, NULL
, FALSE
, FALSE
, 1, &glyph
, &advance
);
5848 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5850 /* advance is in design units */
5851 advance
= (int)floorf(emsize
* advance
/ fm
.designUnitsPerEm
+ 0.5f
);
5852 ok((advance
- gdi_advance
) <= 2, "%.0f: got advance %d, expected %d\n", emsize
, advance
, gdi_advance
);
5857 IDWriteFontFace1_Release(fontface1
);
5858 ref
= IDWriteFactory_Release(factory
);
5859 ok(ref
== 0, "factory not released, %u\n", ref
);
5862 static WORD
get_gasp_flags(IDWriteFontFace
*fontface
, FLOAT emsize
, FLOAT ppdip
)
5864 WORD num_recs
, version
;
5875 hr
= IDWriteFontFace_TryGetFontTable(fontface
, MS_GASP_TAG
,
5876 (const void**)&ptr
, &size
, &ctxt
, &exists
);
5877 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5882 version
= GET_BE_WORD( *ptr
++ );
5883 num_recs
= GET_BE_WORD( *ptr
++ );
5884 if (version
> 1 || size
< (num_recs
* 2 + 2) * sizeof(WORD
)) {
5885 ok(0, "unsupported gasp table: ver %d size %d recs %d\n", version
, size
, num_recs
);
5891 flags
= GET_BE_WORD( *(ptr
+ 1) );
5892 if (emsize
<= GET_BE_WORD( *ptr
)) break;
5897 IDWriteFontFace_ReleaseFontTable(fontface
, ctxt
);
5901 #define GASP_GRIDFIT 0x0001
5902 #define GASP_DOGRAY 0x0002
5903 #define GASP_SYMMETRIC_GRIDFIT 0x0004
5904 #define GASP_SYMMETRIC_SMOOTHING 0x0008
5906 static BOOL g_is_vista
;
5907 static DWRITE_RENDERING_MODE
get_expected_rendering_mode(FLOAT emsize
, WORD gasp
, DWRITE_MEASURING_MODE mode
,
5908 DWRITE_OUTLINE_THRESHOLD threshold
)
5910 static const FLOAT aa_threshold
= 100.0f
;
5911 static const FLOAT a_threshold
= 350.0f
;
5912 static const FLOAT naturalemsize
= 20.0f
;
5915 /* outline threshold */
5917 v
= mode
== DWRITE_MEASURING_MODE_NATURAL
? aa_threshold
: a_threshold
;
5919 v
= threshold
== DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
? aa_threshold
: a_threshold
;
5922 return DWRITE_RENDERING_MODE_OUTLINE
;
5926 case DWRITE_MEASURING_MODE_NATURAL
:
5927 if (!(gasp
& GASP_SYMMETRIC_SMOOTHING
) && (emsize
<= naturalemsize
))
5928 return DWRITE_RENDERING_MODE_NATURAL
;
5930 return DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
;
5931 case DWRITE_MEASURING_MODE_GDI_CLASSIC
:
5932 return DWRITE_RENDERING_MODE_GDI_CLASSIC
;
5933 case DWRITE_MEASURING_MODE_GDI_NATURAL
:
5934 return DWRITE_RENDERING_MODE_GDI_NATURAL
;
5939 /* should be unreachable */
5940 return DWRITE_RENDERING_MODE_DEFAULT
;
5943 static DWRITE_GRID_FIT_MODE
get_expected_gridfit_mode(FLOAT emsize
, WORD gasp
, DWRITE_MEASURING_MODE mode
,
5944 DWRITE_OUTLINE_THRESHOLD threshold
)
5946 static const FLOAT aa_threshold
= 100.0f
;
5947 static const FLOAT a_threshold
= 350.0f
;
5950 v
= threshold
== DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
? aa_threshold
: a_threshold
;
5952 return DWRITE_GRID_FIT_MODE_DISABLED
;
5954 if (mode
== DWRITE_MEASURING_MODE_GDI_CLASSIC
|| mode
== DWRITE_MEASURING_MODE_GDI_NATURAL
)
5955 return DWRITE_GRID_FIT_MODE_ENABLED
;
5957 return (gasp
& (GASP_GRIDFIT
|GASP_SYMMETRIC_GRIDFIT
)) ? DWRITE_GRID_FIT_MODE_ENABLED
: DWRITE_GRID_FIT_MODE_DISABLED
;
5960 struct recommendedmode_test
5962 DWRITE_MEASURING_MODE measuring
;
5963 DWRITE_OUTLINE_THRESHOLD threshold
;
5966 static const struct recommendedmode_test recmode_tests
[] = {
5967 { DWRITE_MEASURING_MODE_NATURAL
, DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
},
5968 { DWRITE_MEASURING_MODE_GDI_CLASSIC
, DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
},
5969 { DWRITE_MEASURING_MODE_GDI_NATURAL
, DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
},
5972 static const struct recommendedmode_test recmode_tests1
[] = {
5973 { DWRITE_MEASURING_MODE_NATURAL
, DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
},
5974 { DWRITE_MEASURING_MODE_GDI_CLASSIC
, DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
},
5975 { DWRITE_MEASURING_MODE_GDI_NATURAL
, DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
},
5976 { DWRITE_MEASURING_MODE_NATURAL
, DWRITE_OUTLINE_THRESHOLD_ALIASED
},
5977 { DWRITE_MEASURING_MODE_GDI_CLASSIC
, DWRITE_OUTLINE_THRESHOLD_ALIASED
},
5978 { DWRITE_MEASURING_MODE_GDI_NATURAL
, DWRITE_OUTLINE_THRESHOLD_ALIASED
},
5981 static void test_GetRecommendedRenderingMode(void)
5983 IDWriteRenderingParams
*params
;
5984 IDWriteFontFace3
*fontface3
;
5985 IDWriteFontFace2
*fontface2
;
5986 IDWriteFontFace1
*fontface1
;
5987 IDWriteFontFace
*fontface
;
5988 DWRITE_RENDERING_MODE mode
;
5989 IDWriteFactory
*factory
;
5994 factory
= create_factory();
5995 fontface
= create_fontface(factory
);
5998 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void**)&fontface1
);
6000 win_skip("IDWriteFontFace1::GetRecommendedRenderingMode() is not supported.\n");
6003 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace2
, (void**)&fontface2
);
6005 win_skip("IDWriteFontFace2::GetRecommendedRenderingMode() is not supported.\n");
6008 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace3
, (void**)&fontface3
);
6010 win_skip("IDWriteFontFace3::GetRecommendedRenderingMode() is not supported.\n");
6012 if (0) /* crashes on native */
6013 hr
= IDWriteFontFace_GetRecommendedRenderingMode(fontface
, 3.0, 1.0,
6014 DWRITE_MEASURING_MODE_GDI_CLASSIC
, NULL
, NULL
);
6017 hr
= IDWriteFontFace_GetRecommendedRenderingMode(fontface
, 3.0, 1.0,
6018 DWRITE_MEASURING_MODE_GDI_CLASSIC
, NULL
, &mode
);
6019 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
6020 ok(mode
== DWRITE_RENDERING_MODE_DEFAULT
, "got %d\n", mode
);
6022 hr
= IDWriteFactory_CreateRenderingParams(factory
, ¶ms
);
6023 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6025 /* detect old dwrite version, that is using higher threshold value */
6026 g_is_vista
= fontface1
== NULL
;
6028 for (emsize
= 1.0; emsize
< 500.0; emsize
+= 1.0) {
6029 DWRITE_RENDERING_MODE expected
;
6034 for (i
= 0; i
< sizeof(recmode_tests
)/sizeof(recmode_tests
[0]); i
++) {
6037 gasp
= get_gasp_flags(fontface
, emsize
, ppdip
);
6038 expected
= get_expected_rendering_mode(emsize
* ppdip
, gasp
, recmode_tests
[i
].measuring
, recmode_tests
[i
].threshold
);
6039 hr
= IDWriteFontFace_GetRecommendedRenderingMode(fontface
, emsize
, ppdip
, recmode_tests
[i
].measuring
, params
, &mode
);
6040 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6041 ok(mode
== expected
, "%.2f/%d: got %d, ppdip %f, flags 0x%04x, expected %d\n", emsize
, i
, mode
, ppdip
, gasp
, expected
);
6043 /* some ppdip variants */
6046 gasp
= get_gasp_flags(fontface
, emsize
, ppdip
);
6047 expected
= get_expected_rendering_mode(emsize
* ppdip
, gasp
, recmode_tests
[i
].measuring
, recmode_tests
[i
].threshold
);
6048 hr
= IDWriteFontFace_GetRecommendedRenderingMode(fontface
, emsize
, ppdip
, recmode_tests
[i
].measuring
, params
, &mode
);
6049 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6050 ok(mode
== expected
, "%.2f/%d: got %d, ppdip %f, flags 0x%04x, expected %d\n", emsize
, i
, mode
, ppdip
, gasp
, expected
);
6052 /* Only test larger sizes to workaround Win7 differences, where unscaled natural emsize threshold is used;
6053 Win8 and Win10 handle this as expected. */
6054 if (emsize
> 20.0f
) {
6057 gasp
= get_gasp_flags(fontface
, emsize
, ppdip
);
6058 expected
= get_expected_rendering_mode(emsize
* ppdip
, gasp
, recmode_tests
[i
].measuring
, recmode_tests
[i
].threshold
);
6059 hr
= IDWriteFontFace_GetRecommendedRenderingMode(fontface
, emsize
, ppdip
, recmode_tests
[i
].measuring
, params
, &mode
);
6060 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6061 ok(mode
== expected
, "%.2f/%d: got %d, ppdip %f, flags 0x%04x, expected %d\n", emsize
, i
, mode
, ppdip
, gasp
, expected
);
6065 gasp
= get_gasp_flags(fontface
, emsize
, ppdip
);
6066 expected
= get_expected_rendering_mode(emsize
* ppdip
, gasp
, recmode_tests
[i
].measuring
, recmode_tests
[i
].threshold
);
6067 hr
= IDWriteFontFace_GetRecommendedRenderingMode(fontface
, emsize
, ppdip
, recmode_tests
[i
].measuring
, params
, &mode
);
6068 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6069 ok(mode
== expected
, "%.2f/%d: got %d, ppdip %f, flags 0x%04x, expected %d\n", emsize
, i
, mode
, ppdip
, gasp
, expected
);
6073 /* IDWriteFontFace1 offers another variant of this method */
6075 for (i
= 0; i
< sizeof(recmode_tests1
)/sizeof(recmode_tests1
[0]); i
++) {
6079 dpi
= 96.0f
* ppdip
;
6081 gasp
= get_gasp_flags(fontface
, emsize
, ppdip
);
6082 expected
= get_expected_rendering_mode(emsize
* ppdip
, gasp
, recmode_tests1
[i
].measuring
, recmode_tests1
[i
].threshold
);
6083 hr
= IDWriteFontFace1_GetRecommendedRenderingMode(fontface1
, emsize
, dpi
, dpi
,
6084 NULL
, FALSE
, recmode_tests1
[i
].threshold
, recmode_tests1
[i
].measuring
, &mode
);
6085 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6086 ok(mode
== expected
, "%.2f/%d: got %d, dpi %f, flags 0x%04x, expected %d\n", emsize
, i
, mode
, dpi
, gasp
, expected
);
6088 /* Only test larger sizes to workaround Win7 differences, where unscaled natural emsize threshold is used;
6089 Win8 and Win10 handle this as expected. */
6090 if (emsize
> 20.0f
) {
6092 dpi
= 96.0f
* ppdip
;
6094 gasp
= get_gasp_flags(fontface
, emsize
, ppdip
);
6095 expected
= get_expected_rendering_mode(emsize
* ppdip
, gasp
, recmode_tests1
[i
].measuring
, recmode_tests1
[i
].threshold
);
6096 hr
= IDWriteFontFace1_GetRecommendedRenderingMode(fontface1
, emsize
, dpi
, dpi
,
6097 NULL
, FALSE
, recmode_tests1
[i
].threshold
, recmode_tests1
[i
].measuring
, &mode
);
6098 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6099 ok(mode
== expected
, "%.2f/%d: got %d, dpi %f, flags 0x%04x, expected %d\n", emsize
, i
, mode
, dpi
, gasp
, expected
);
6102 dpi
= 96.0f
* ppdip
;
6104 gasp
= get_gasp_flags(fontface
, emsize
, ppdip
);
6105 expected
= get_expected_rendering_mode(emsize
* ppdip
, gasp
, recmode_tests1
[i
].measuring
, recmode_tests1
[i
].threshold
);
6106 hr
= IDWriteFontFace1_GetRecommendedRenderingMode(fontface1
, emsize
, dpi
, dpi
,
6107 NULL
, FALSE
, recmode_tests1
[i
].threshold
, recmode_tests1
[i
].measuring
, &mode
);
6108 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6109 ok(mode
== expected
, "%.2f/%d: got %d, dpi %f, flags 0x%04x, expected %d\n", emsize
, i
, mode
, dpi
, gasp
, expected
);
6111 /* try different dpis for X and Y direction */
6113 dpi
= 96.0f
* ppdip
;
6115 gasp
= get_gasp_flags(fontface
, emsize
, ppdip
);
6116 expected
= get_expected_rendering_mode(emsize
* ppdip
, gasp
, recmode_tests1
[i
].measuring
, recmode_tests1
[i
].threshold
);
6117 hr
= IDWriteFontFace1_GetRecommendedRenderingMode(fontface1
, emsize
, dpi
* 0.5f
, dpi
,
6118 NULL
, FALSE
, recmode_tests1
[i
].threshold
, recmode_tests1
[i
].measuring
, &mode
);
6119 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6120 ok(mode
== expected
, "%.2f/%d: got %d, dpi %f, flags 0x%04x, expected %d\n", emsize
, i
, mode
, dpi
, gasp
, expected
);
6123 dpi
= 96.0f
* ppdip
;
6125 gasp
= get_gasp_flags(fontface
, emsize
, ppdip
);
6126 expected
= get_expected_rendering_mode(emsize
* ppdip
, gasp
, recmode_tests1
[i
].measuring
, recmode_tests1
[i
].threshold
);
6127 hr
= IDWriteFontFace1_GetRecommendedRenderingMode(fontface1
, emsize
, dpi
, dpi
* 0.5f
,
6128 NULL
, FALSE
, recmode_tests1
[i
].threshold
, recmode_tests1
[i
].measuring
, &mode
);
6129 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6130 ok(mode
== expected
, "%.2f/%d: got %d, dpi %f, flags 0x%04x, expected %d\n", emsize
, i
, mode
, dpi
, gasp
, expected
);
6133 dpi
= 96.0f
* ppdip
;
6135 gasp
= get_gasp_flags(fontface
, emsize
, ppdip
);
6136 expected
= get_expected_rendering_mode(emsize
* ppdip
, gasp
, recmode_tests1
[i
].measuring
, recmode_tests1
[i
].threshold
);
6137 hr
= IDWriteFontFace1_GetRecommendedRenderingMode(fontface1
, emsize
, dpi
* 0.5f
, dpi
,
6138 NULL
, FALSE
, recmode_tests1
[i
].threshold
, recmode_tests1
[i
].measuring
, &mode
);
6139 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6140 ok(mode
== expected
, "%.2f/%d: got %d, dpi %f, flags 0x%04x, expected %d\n", emsize
, i
, mode
, dpi
, gasp
, expected
);
6143 dpi
= 96.0f
* ppdip
;
6145 gasp
= get_gasp_flags(fontface
, emsize
, ppdip
);
6146 expected
= get_expected_rendering_mode(emsize
* ppdip
, gasp
, recmode_tests1
[i
].measuring
, recmode_tests1
[i
].threshold
);
6147 hr
= IDWriteFontFace1_GetRecommendedRenderingMode(fontface1
, emsize
, dpi
, dpi
* 0.5f
,
6148 NULL
, FALSE
, recmode_tests1
[i
].threshold
, recmode_tests1
[i
].measuring
, &mode
);
6149 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6150 ok(mode
== expected
, "%.2f/%d: got %d, dpi %f, flags 0x%04x, expected %d\n", emsize
, i
, mode
, dpi
, gasp
, expected
);
6155 /* IDWriteFontFace2 - another one */
6157 DWRITE_GRID_FIT_MODE gridfit
, expected_gridfit
;
6159 gasp
= get_gasp_flags(fontface
, emsize
, 1.0f
);
6160 for (i
= 0; i
< sizeof(recmode_tests1
)/sizeof(recmode_tests1
[0]); i
++) {
6162 expected
= get_expected_rendering_mode(emsize
, gasp
, recmode_tests1
[i
].measuring
, recmode_tests1
[i
].threshold
);
6163 expected_gridfit
= get_expected_gridfit_mode(emsize
, gasp
, recmode_tests1
[i
].measuring
, recmode_tests1
[i
].threshold
);
6164 hr
= IDWriteFontFace2_GetRecommendedRenderingMode(fontface2
, emsize
, 96.0f
, 96.0f
,
6165 NULL
, FALSE
, recmode_tests1
[i
].threshold
, recmode_tests1
[i
].measuring
, params
, &mode
, &gridfit
);
6166 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6167 ok(mode
== expected
, "%.2f: got %d, flags 0x%04x, expected %d\n", emsize
, mode
, gasp
, expected
);
6168 ok(gridfit
== expected_gridfit
, "%.2f/%d: gridfit: got %d, flags 0x%04x, expected %d\n", emsize
, i
, gridfit
,
6169 gasp
, expected_gridfit
);
6173 /* IDWriteFontFace3 - and another one */
6175 DWRITE_GRID_FIT_MODE gridfit
, expected_gridfit
;
6176 DWRITE_RENDERING_MODE1 mode1
, expected1
;
6178 gasp
= get_gasp_flags(fontface
, emsize
, 1.0f
);
6179 for (i
= 0; i
< sizeof(recmode_tests1
)/sizeof(recmode_tests1
[0]); i
++) {
6181 expected1
= get_expected_rendering_mode(emsize
, gasp
, recmode_tests1
[i
].measuring
, recmode_tests1
[i
].threshold
);
6182 expected_gridfit
= get_expected_gridfit_mode(emsize
, gasp
, recmode_tests1
[i
].measuring
, recmode_tests1
[i
].threshold
);
6183 hr
= IDWriteFontFace3_GetRecommendedRenderingMode(fontface3
, emsize
, 96.0f
, 96.0f
,
6184 NULL
, FALSE
, recmode_tests1
[i
].threshold
, recmode_tests1
[i
].measuring
, params
, &mode1
, &gridfit
);
6185 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6186 ok(mode1
== expected1
, "%.2f: got %d, flags 0x%04x, expected %d\n", emsize
, mode1
, gasp
, expected1
);
6187 ok(gridfit
== expected_gridfit
, "%.2f/%d: gridfit: got %d, flags 0x%04x, expected %d\n", emsize
, i
, gridfit
,
6188 gasp
, expected_gridfit
);
6193 IDWriteRenderingParams_Release(params
);
6195 /* test how parameters override returned modes */
6196 hr
= IDWriteFactory_CreateCustomRenderingParams(factory
, 1.0, 0.0, 0.0, DWRITE_PIXEL_GEOMETRY_FLAT
,
6197 DWRITE_RENDERING_MODE_GDI_CLASSIC
, ¶ms
);
6198 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6201 hr
= IDWriteFontFace_GetRecommendedRenderingMode(fontface
, 500.0, 1.0, DWRITE_MEASURING_MODE_NATURAL
, params
, &mode
);
6202 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6203 ok(mode
== DWRITE_RENDERING_MODE_GDI_CLASSIC
, "got %d\n", mode
);
6205 IDWriteRenderingParams_Release(params
);
6208 IDWriteRenderingParams2
*params2
;
6209 IDWriteFactory2
*factory2
;
6210 DWRITE_GRID_FIT_MODE gridfit
;
6212 hr
= IDWriteFactory_QueryInterface(factory
, &IID_IDWriteFactory2
, (void**)&factory2
);
6213 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6215 hr
= IDWriteFactory2_CreateCustomRenderingParams(factory2
, 1.0, 0.0, 0.0, 0.5, DWRITE_PIXEL_GEOMETRY_FLAT
,
6216 DWRITE_RENDERING_MODE_OUTLINE
, DWRITE_GRID_FIT_MODE_ENABLED
, ¶ms2
);
6217 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6221 hr
= IDWriteFontFace2_GetRecommendedRenderingMode(fontface2
, 5.0, 96.0, 96.0,
6222 NULL
, FALSE
, DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
, DWRITE_MEASURING_MODE_GDI_CLASSIC
,
6223 NULL
, &mode
, &gridfit
);
6224 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6225 ok(mode
== DWRITE_RENDERING_MODE_GDI_CLASSIC
, "got %d\n", mode
);
6226 ok(gridfit
== DWRITE_GRID_FIT_MODE_ENABLED
, "got %d\n", gridfit
);
6230 hr
= IDWriteFontFace2_GetRecommendedRenderingMode(fontface2
, 5.0, 96.0, 96.0,
6231 NULL
, FALSE
, DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
, DWRITE_MEASURING_MODE_GDI_CLASSIC
,
6232 (IDWriteRenderingParams
*)params2
, &mode
, &gridfit
);
6233 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6234 ok(mode
== DWRITE_RENDERING_MODE_OUTLINE
, "got %d\n", mode
);
6235 ok(gridfit
== DWRITE_GRID_FIT_MODE_ENABLED
, "got %d\n", gridfit
);
6237 IDWriteRenderingParams2_Release(params2
);
6238 IDWriteFactory2_Release(factory2
);
6242 IDWriteRenderingParams3
*params3
;
6243 IDWriteRenderingParams2
*params2
;
6244 IDWriteRenderingParams
*params
;
6245 IDWriteFactory3
*factory3
;
6246 DWRITE_GRID_FIT_MODE gridfit
;
6247 DWRITE_RENDERING_MODE1 mode1
;
6249 hr
= IDWriteFactory_QueryInterface(factory
, &IID_IDWriteFactory3
, (void**)&factory3
);
6250 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6252 hr
= IDWriteFactory3_CreateCustomRenderingParams(factory3
, 1.0f
, 0.0f
, 0.0f
, 0.5f
, DWRITE_PIXEL_GEOMETRY_FLAT
,
6253 DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC_DOWNSAMPLED
, DWRITE_GRID_FIT_MODE_ENABLED
, ¶ms3
);
6254 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6256 mode1
= IDWriteRenderingParams3_GetRenderingMode1(params3
);
6257 ok(mode1
== DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC_DOWNSAMPLED
, "got %d\n", mode1
);
6259 mode
= IDWriteRenderingParams3_GetRenderingMode(params3
);
6260 ok(mode
== DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
, "got %d\n", mode
);
6262 hr
= IDWriteRenderingParams3_QueryInterface(params3
, &IID_IDWriteRenderingParams
, (void**)¶ms
);
6263 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6264 ok(params
== (IDWriteRenderingParams
*)params3
, "got %p, %p\n", params3
, params
);
6265 mode
= IDWriteRenderingParams_GetRenderingMode(params
);
6266 ok(mode
== DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
, "got %d\n", mode
);
6267 IDWriteRenderingParams_Release(params
);
6269 hr
= IDWriteRenderingParams3_QueryInterface(params3
, &IID_IDWriteRenderingParams2
, (void**)¶ms2
);
6270 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6271 ok(params2
== (IDWriteRenderingParams2
*)params3
, "got %p, %p\n", params3
, params2
);
6272 mode
= IDWriteRenderingParams2_GetRenderingMode(params2
);
6273 ok(mode
== DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
, "got %d\n", mode
);
6274 IDWriteRenderingParams2_Release(params2
);
6278 hr
= IDWriteFontFace2_GetRecommendedRenderingMode(fontface2
, 5.0f
, 96.0f
, 96.0f
,
6279 NULL
, FALSE
, DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
, DWRITE_MEASURING_MODE_GDI_CLASSIC
,
6280 NULL
, &mode
, &gridfit
);
6281 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6282 ok(mode
== DWRITE_RENDERING_MODE_GDI_CLASSIC
, "got %d\n", mode
);
6283 ok(gridfit
== DWRITE_GRID_FIT_MODE_ENABLED
, "got %d\n", gridfit
);
6287 hr
= IDWriteFontFace2_GetRecommendedRenderingMode(fontface2
, 5.0f
, 96.0f
, 96.0f
,
6288 NULL
, FALSE
, DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
, DWRITE_MEASURING_MODE_GDI_CLASSIC
,
6289 (IDWriteRenderingParams
*)params3
, &mode
, &gridfit
);
6290 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6291 ok(mode
== DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
, "got %d\n", mode
);
6292 ok(gridfit
== DWRITE_GRID_FIT_MODE_ENABLED
, "got %d\n", gridfit
);
6294 IDWriteRenderingParams3_Release(params3
);
6295 IDWriteFactory3_Release(factory3
);
6299 IDWriteFontFace3_Release(fontface3
);
6301 IDWriteFontFace2_Release(fontface2
);
6303 IDWriteFontFace1_Release(fontface1
);
6304 IDWriteFontFace_Release(fontface
);
6305 ref
= IDWriteFactory_Release(factory
);
6306 ok(ref
== 0, "factory not released, %u\n", ref
);
6309 static inline BOOL
float_eq(FLOAT left
, FLOAT right
)
6311 int x
= *(int *)&left
;
6312 int y
= *(int *)&right
;
6319 return abs(x
- y
) <= 8;
6322 static void test_GetAlphaBlendParams(void)
6324 static const DWRITE_RENDERING_MODE rendermodes
[] = {
6325 DWRITE_RENDERING_MODE_ALIASED
,
6326 DWRITE_RENDERING_MODE_GDI_CLASSIC
,
6327 DWRITE_RENDERING_MODE_GDI_NATURAL
,
6328 DWRITE_RENDERING_MODE_NATURAL
,
6329 DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
,
6332 IDWriteGlyphRunAnalysis
*analysis
;
6333 FLOAT gamma
, contrast
, ctlevel
;
6334 IDWriteRenderingParams
*params
;
6335 DWRITE_GLYPH_METRICS metrics
;
6336 DWRITE_GLYPH_OFFSET offset
;
6337 IDWriteFontFace
*fontface
;
6338 IDWriteFactory
*factory
;
6339 DWRITE_GLYPH_RUN run
;
6340 FLOAT advance
, expected_gdi_gamma
;
6348 factory
= create_factory();
6349 fontface
= create_fontface(factory
);
6353 hr
= IDWriteFontFace_GetGlyphIndices(fontface
, &ch
, 1, &glyph
);
6354 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6355 ok(glyph
> 0, "got %u\n", glyph
);
6357 hr
= IDWriteFontFace_GetDesignGlyphMetrics(fontface
, &glyph
, 1, &metrics
, FALSE
);
6358 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6359 advance
= metrics
.advanceWidth
;
6361 offset
.advanceOffset
= 0.0;
6362 offset
.ascenderOffset
= 0.0;
6364 run
.fontFace
= fontface
;
6365 run
.fontEmSize
= 24.0;
6367 run
.glyphIndices
= &glyph
;
6368 run
.glyphAdvances
= &advance
;
6369 run
.glyphOffsets
= &offset
;
6370 run
.isSideways
= FALSE
;
6373 hr
= IDWriteFactory_CreateCustomRenderingParams(factory
, 0.9, 0.3, 0.1, DWRITE_PIXEL_GEOMETRY_RGB
,
6374 DWRITE_RENDERING_MODE_DEFAULT
, ¶ms
);
6375 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6378 ret
= SystemParametersInfoW(SPI_GETFONTSMOOTHINGCONTRAST
, 0, &value
, 0);
6379 ok(ret
, "got %d\n", ret
);
6380 expected_gdi_gamma
= (FLOAT
)(value
/ 1000.0);
6382 for (i
= 0; i
< sizeof(rendermodes
)/sizeof(rendermodes
[0]); i
++) {
6383 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 1.0, NULL
,
6384 rendermodes
[i
], DWRITE_MEASURING_MODE_NATURAL
,
6385 0.0, 0.0, &analysis
);
6386 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6388 gamma
= contrast
= ctlevel
= -1.0;
6389 hr
= IDWriteGlyphRunAnalysis_GetAlphaBlendParams(analysis
, NULL
, &gamma
, &contrast
, &ctlevel
);
6390 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
6391 ok(gamma
== -1.0, "got %.2f\n", gamma
);
6392 ok(contrast
== -1.0, "got %.2f\n", contrast
);
6393 ok(ctlevel
== -1.0, "got %.2f\n", ctlevel
);
6395 gamma
= contrast
= ctlevel
= -1.0;
6396 hr
= IDWriteGlyphRunAnalysis_GetAlphaBlendParams(analysis
, params
, &gamma
, &contrast
, &ctlevel
);
6397 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6399 if (rendermodes
[i
] == DWRITE_RENDERING_MODE_GDI_CLASSIC
|| rendermodes
[i
] == DWRITE_RENDERING_MODE_GDI_NATURAL
) {
6400 ok(float_eq(gamma
, expected_gdi_gamma
), "got %.2f, expected %.2f\n", gamma
, expected_gdi_gamma
);
6401 ok(contrast
== 0.0f
, "got %.2f\n", contrast
);
6402 ok(ctlevel
== 1.0f
, "got %.2f\n", ctlevel
);
6405 ok(gamma
== 0.9f
, "got %.2f\n", gamma
);
6406 ok(contrast
== 0.3f
, "got %.2f\n", contrast
);
6407 ok(ctlevel
== 0.1f
, "got %.2f\n", ctlevel
);
6410 IDWriteGlyphRunAnalysis_Release(analysis
);
6413 IDWriteRenderingParams_Release(params
);
6414 IDWriteFontFace_Release(fontface
);
6415 ref
= IDWriteFactory_Release(factory
);
6416 ok(ref
== 0, "factory not released, %u\n", ref
);
6419 static void test_CreateAlphaTexture(void)
6421 IDWriteGlyphRunAnalysis
*analysis
;
6422 DWRITE_GLYPH_METRICS metrics
;
6423 DWRITE_GLYPH_OFFSET offset
;
6424 IDWriteFontFace
*fontface
;
6425 IDWriteFactory
*factory
;
6426 DWRITE_GLYPH_RUN run
;
6435 factory
= create_factory();
6436 fontface
= create_fontface(factory
);
6440 hr
= IDWriteFontFace_GetGlyphIndices(fontface
, &ch
, 1, &glyph
);
6441 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6442 ok(glyph
> 0, "got %u\n", glyph
);
6444 hr
= IDWriteFontFace_GetDesignGlyphMetrics(fontface
, &glyph
, 1, &metrics
, FALSE
);
6445 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6446 advance
= metrics
.advanceWidth
;
6448 offset
.advanceOffset
= 0.0;
6449 offset
.ascenderOffset
= 0.0;
6451 run
.fontFace
= fontface
;
6452 run
.fontEmSize
= 24.0;
6454 run
.glyphIndices
= &glyph
;
6455 run
.glyphAdvances
= &advance
;
6456 run
.glyphOffsets
= &offset
;
6457 run
.isSideways
= FALSE
;
6460 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 1.0, NULL
,
6461 DWRITE_RENDERING_MODE_NATURAL
, DWRITE_MEASURING_MODE_NATURAL
,
6462 0.0, 0.0, &analysis
);
6463 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6465 SetRectEmpty(&bounds
);
6466 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_CLEARTYPE_3x1
, &bounds
);
6467 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6468 ok(!IsRectEmpty(&bounds
), "got empty rect\n");
6469 size
= (bounds
.right
- bounds
.left
)*(bounds
.bottom
- bounds
.top
)*3;
6470 ok(sizeof(buff
) >= size
, "required %u\n", size
);
6472 /* invalid type value */
6473 memset(buff
, 0xcf, sizeof(buff
));
6474 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_CLEARTYPE_3x1
+1, &bounds
, buff
, sizeof(buff
));
6475 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
6476 ok(buff
[0] == 0xcf, "got %1x\n", buff
[0]);
6478 memset(buff
, 0xcf, sizeof(buff
));
6479 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &bounds
, buff
, 2);
6480 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
6481 ok(buff
[0] == 0xcf, "got %1x\n", buff
[0]);
6483 /* vista version allows texture type mismatch, mark it broken for now */
6484 memset(buff
, 0xcf, sizeof(buff
));
6485 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &bounds
, buff
, sizeof(buff
));
6486 ok(hr
== DWRITE_E_UNSUPPORTEDOPERATION
|| broken(hr
== S_OK
), "got 0x%08x\n", hr
);
6487 ok(buff
[0] == 0xcf || broken(buff
[0] == 0), "got %1x\n", buff
[0]);
6489 memset(buff
, 0xcf, sizeof(buff
));
6490 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_CLEARTYPE_3x1
, &bounds
, buff
, size
-1);
6491 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
6492 ok(buff
[0] == 0xcf, "got %1x\n", buff
[0]);
6494 IDWriteGlyphRunAnalysis_Release(analysis
);
6496 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 1.0, NULL
,
6497 DWRITE_RENDERING_MODE_ALIASED
, DWRITE_MEASURING_MODE_GDI_CLASSIC
,
6498 0.0, 0.0, &analysis
);
6499 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6501 SetRectEmpty(&bounds
);
6502 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &bounds
);
6503 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6504 ok(!IsRectEmpty(&bounds
), "got empty rect\n");
6505 size
= (bounds
.right
- bounds
.left
)*(bounds
.bottom
- bounds
.top
);
6506 ok(sizeof(buff
) >= size
, "required %u\n", size
);
6508 memset(buff
, 0xcf, sizeof(buff
));
6509 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, NULL
, buff
, sizeof(buff
));
6510 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
6511 ok(buff
[0] == 0xcf, "got %1x\n", buff
[0]);
6513 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, NULL
, NULL
, sizeof(buff
));
6514 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
6516 memset(buff
, 0xcf, sizeof(buff
));
6517 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, NULL
, buff
, 0);
6518 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
6519 ok(buff
[0] == 0xcf, "got %1x\n", buff
[0]);
6521 /* buffer size is not enough */
6522 memset(buff
, 0xcf, sizeof(buff
));
6523 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &bounds
, buff
, size
-1);
6524 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
6525 ok(buff
[0] == 0xcf, "got %1x\n", buff
[0]);
6527 /* request texture for rectangle that doesn't intersect */
6528 memset(buff
, 0xcf, sizeof(buff
));
6530 OffsetRect(&r
, (bounds
.right
- bounds
.left
)*2, 0);
6531 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &r
, buff
, sizeof(buff
));
6532 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6533 ok(buff
[0] == 0, "got %1x\n", buff
[0]);
6535 memset(buff
, 0xcf, sizeof(buff
));
6537 OffsetRect(&r
, (bounds
.right
- bounds
.left
)*2, 0);
6538 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &r
, buff
, sizeof(buff
));
6539 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6540 ok(buff
[0] == 0, "got %1x\n", buff
[0]);
6542 /* request texture for rectangle that doesn't intersect, small buffer */
6543 memset(buff
, 0xcf, sizeof(buff
));
6545 OffsetRect(&r
, (bounds
.right
- bounds
.left
)*2, 0);
6546 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &r
, buff
, size
-1);
6547 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
6548 ok(buff
[0] == 0xcf, "got %1x\n", buff
[0]);
6550 /* vista version allows texture type mismatch, mark it broken for now */
6551 memset(buff
, 0xcf, sizeof(buff
));
6552 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_CLEARTYPE_3x1
, &bounds
, buff
, sizeof(buff
));
6553 ok(hr
== DWRITE_E_UNSUPPORTEDOPERATION
|| broken(hr
== S_OK
), "got 0x%08x\n", hr
);
6554 ok(buff
[0] == 0xcf || broken(buff
[0] == 0), "got %1x\n", buff
[0]);
6556 IDWriteGlyphRunAnalysis_Release(analysis
);
6557 IDWriteFontFace_Release(fontface
);
6558 ref
= IDWriteFactory_Release(factory
);
6559 ok(ref
== 0, "factory not released, %u\n", ref
);
6562 static void test_IsSymbolFont(void)
6564 static const WCHAR symbolW
[] = {'S','y','m','b','o','l',0};
6565 IDWriteFontCollection
*collection
;
6566 IDWriteFontFace
*fontface
;
6567 IDWriteFactory
*factory
;
6573 factory
= create_factory();
6576 fontface
= create_fontface(factory
);
6577 ret
= IDWriteFontFace_IsSymbolFont(fontface
);
6578 ok(!ret
, "got %d\n", ret
);
6580 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &collection
, FALSE
);
6581 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6583 hr
= IDWriteFontCollection_GetFontFromFontFace(collection
, fontface
, &font
);
6584 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6586 ret
= IDWriteFont_IsSymbolFont(font
);
6587 ok(!ret
, "got %d\n", ret
);
6589 IDWriteFontCollection_Release(collection
);
6590 IDWriteFont_Release(font
);
6591 IDWriteFontFace_Release(fontface
);
6594 font
= get_font(factory
, symbolW
, DWRITE_FONT_STYLE_NORMAL
);
6595 ret
= IDWriteFont_IsSymbolFont(font
);
6596 ok(ret
, "got %d\n", ret
);
6598 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
6599 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6600 ret
= IDWriteFontFace_IsSymbolFont(fontface
);
6601 ok(ret
, "got %d\n", ret
);
6602 IDWriteFontFace_Release(fontface
);
6603 IDWriteFont_Release(font
);
6605 ref
= IDWriteFactory_Release(factory
);
6606 ok(ref
== 0, "factory not released, %u\n", ref
);
6609 struct CPAL_Header_0
6612 USHORT numPaletteEntries
;
6614 USHORT numColorRecords
;
6615 ULONG offsetFirstColorRecord
;
6616 USHORT colorRecordIndices
[1];
6619 static void test_GetPaletteEntries(void)
6621 IDWriteFontFace2
*fontface2
;
6622 IDWriteFontFace
*fontface
;
6623 IDWriteFactory
*factory
;
6625 DWRITE_COLOR_F color
;
6626 UINT32 palettecount
, entrycount
, size
, colorrecords
;
6628 const struct CPAL_Header_0
*cpal_header
;
6633 factory
= create_factory();
6635 /* Tahoma, no color support */
6636 fontface
= create_fontface(factory
);
6637 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace2
, (void**)&fontface2
);
6638 IDWriteFontFace_Release(fontface
);
6640 ref
= IDWriteFactory_Release(factory
);
6641 ok(ref
== 0, "factory not released, %u\n", ref
);
6642 win_skip("GetPaletteEntries() is not supported.\n");
6646 hr
= IDWriteFontFace2_GetPaletteEntries(fontface2
, 0, 0, 1, &color
);
6647 ok(hr
== DWRITE_E_NOCOLOR
, "got 0x%08x\n", hr
);
6648 IDWriteFontFace2_Release(fontface2
);
6650 /* Segoe UI Emoji, with color support */
6651 font
= get_font(factory
, emojiW
, DWRITE_FONT_STYLE_NORMAL
);
6653 ref
= IDWriteFactory_Release(factory
);
6654 ok(ref
== 0, "factory not released, %u\n", ref
);
6655 skip("Segoe UI Emoji font not found.\n");
6659 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
6660 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6661 IDWriteFont_Release(font
);
6663 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace2
, (void**)&fontface2
);
6664 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6665 IDWriteFontFace_Release(fontface
);
6667 palettecount
= IDWriteFontFace2_GetColorPaletteCount(fontface2
);
6668 ok(palettecount
>= 1, "got %u\n", palettecount
);
6670 entrycount
= IDWriteFontFace2_GetPaletteEntryCount(fontface2
);
6671 ok(entrycount
>= 1, "got %u\n", entrycount
);
6674 hr
= IDWriteFontFace2_TryGetFontTable(fontface2
, MS_CPAL_TAG
, (const void**)&cpal_header
, &size
, &ctxt
, &exists
);
6675 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6676 ok(exists
, "got %d\n", exists
);
6677 colorrecords
= GET_BE_WORD(cpal_header
->numColorRecords
);
6678 ok(colorrecords
>= 1, "got %u\n", colorrecords
);
6680 /* invalid palette index */
6681 color
.r
= color
.g
= color
.b
= color
.a
= 123.0;
6682 hr
= IDWriteFontFace2_GetPaletteEntries(fontface2
, palettecount
, 0, 1, &color
);
6683 ok(hr
== DWRITE_E_NOCOLOR
, "got 0x%08x\n", hr
);
6684 ok(color
.r
== 123.0 && color
.g
== 123.0 && color
.b
== 123.0 && color
.a
== 123.0,
6685 "got wrong color %.2fx%.2fx%.2fx%.2f\n", color
.r
, color
.g
, color
.b
, color
.a
);
6687 /* invalid entry index */
6688 color
.r
= color
.g
= color
.b
= color
.a
= 123.0;
6689 hr
= IDWriteFontFace2_GetPaletteEntries(fontface2
, 0, entrycount
, 1, &color
);
6690 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
6691 ok(color
.r
== 123.0 && color
.g
== 123.0 && color
.b
== 123.0 && color
.a
== 123.0,
6692 "got wrong color %.2fx%.2fx%.2fx%.2f\n", color
.r
, color
.g
, color
.b
, color
.a
);
6694 color
.r
= color
.g
= color
.b
= color
.a
= 123.0;
6695 hr
= IDWriteFontFace2_GetPaletteEntries(fontface2
, 0, entrycount
- 1, 1, &color
);
6696 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6697 ok(color
.r
!= 123.0 && color
.g
!= 123.0 && color
.b
!= 123.0 && color
.a
!= 123.0,
6698 "got wrong color %.2fx%.2fx%.2fx%.2f\n", color
.r
, color
.g
, color
.b
, color
.a
);
6700 /* zero return length */
6701 color
.r
= color
.g
= color
.b
= color
.a
= 123.0;
6702 hr
= IDWriteFontFace2_GetPaletteEntries(fontface2
, 0, 0, 0, &color
);
6703 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6704 ok(color
.r
== 123.0 && color
.g
== 123.0 && color
.b
== 123.0 && color
.a
== 123.0,
6705 "got wrong color %.2fx%.2fx%.2fx%.2f\n", color
.r
, color
.g
, color
.b
, color
.a
);
6707 IDWriteFontFace2_Release(fontface2
);
6708 ref
= IDWriteFactory_Release(factory
);
6709 ok(ref
== 0, "factory not released, %u\n", ref
);
6712 static void test_TranslateColorGlyphRun(void)
6714 IDWriteColorGlyphRunEnumerator
*layers
;
6715 const DWRITE_COLOR_GLYPH_RUN
*colorrun
;
6716 IDWriteFontFace2
*fontface2
;
6717 IDWriteFontFace
*fontface
;
6718 IDWriteFactory2
*factory
;
6719 DWRITE_GLYPH_RUN run
;
6720 UINT32 codepoints
[2];
6727 factory
= create_factory_iid(&IID_IDWriteFactory2
);
6729 win_skip("TranslateColorGlyphRun() is not supported.\n");
6733 /* Tahoma, no color support */
6734 fontface
= create_fontface((IDWriteFactory
*)factory
);
6736 codepoints
[0] = 'A';
6737 hr
= IDWriteFontFace_GetGlyphIndices(fontface
, codepoints
, 1, glyphs
);
6738 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6740 run
.fontFace
= fontface
;
6741 run
.fontEmSize
= 20.0f
;
6743 run
.glyphIndices
= glyphs
;
6744 run
.glyphAdvances
= NULL
;
6745 run
.glyphOffsets
= NULL
;
6746 run
.isSideways
= FALSE
;
6749 layers
= (void*)0xdeadbeef;
6750 hr
= IDWriteFactory2_TranslateColorGlyphRun(factory
, 0.0f
, 0.0f
, &run
, NULL
,
6751 DWRITE_MEASURING_MODE_NATURAL
, NULL
, 0, &layers
);
6752 ok(hr
== DWRITE_E_NOCOLOR
, "got 0x%08x\n", hr
);
6753 ok(layers
== NULL
, "got %p\n", layers
);
6754 IDWriteFontFace_Release(fontface
);
6756 /* Segoe UI Emoji, with color support */
6757 font
= get_font((IDWriteFactory
*)factory
, emojiW
, DWRITE_FONT_STYLE_NORMAL
);
6759 IDWriteFactory2_Release(factory
);
6760 skip("Segoe UI Emoji font not found.\n");
6764 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
6765 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6766 IDWriteFont_Release(font
);
6768 codepoints
[0] = 0x26c4;
6769 hr
= IDWriteFontFace_GetGlyphIndices(fontface
, codepoints
, 1, glyphs
);
6770 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6772 run
.fontFace
= fontface
;
6775 hr
= IDWriteFactory2_TranslateColorGlyphRun(factory
, 0.0f
, 0.0f
, &run
, NULL
,
6776 DWRITE_MEASURING_MODE_NATURAL
, NULL
, 0, &layers
);
6777 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6778 ok(layers
!= NULL
, "got %p\n", layers
);
6782 hr
= IDWriteColorGlyphRunEnumerator_MoveNext(layers
, &hasrun
);
6783 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6788 hr
= IDWriteColorGlyphRunEnumerator_GetCurrentRun(layers
, &colorrun
);
6789 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6790 ok(colorrun
->glyphRun
.fontFace
!= NULL
, "got fontface %p\n", colorrun
->glyphRun
.fontFace
);
6791 ok(colorrun
->glyphRun
.fontEmSize
== 20.0f
, "got wrong font size %f\n", colorrun
->glyphRun
.fontEmSize
);
6792 ok(colorrun
->glyphRun
.glyphCount
> 0, "got wrong glyph count %u\n", colorrun
->glyphRun
.glyphCount
);
6793 ok(colorrun
->glyphRun
.glyphIndices
!= NULL
, "got null glyph indices %p\n", colorrun
->glyphRun
.glyphIndices
);
6794 ok(colorrun
->glyphRun
.glyphAdvances
!= NULL
, "got null glyph advances %p\n", colorrun
->glyphRun
.glyphAdvances
);
6797 /* iterated all way through */
6798 hr
= IDWriteColorGlyphRunEnumerator_GetCurrentRun(layers
, &colorrun
);
6799 ok(hr
== E_NOT_VALID_STATE
, "got 0x%08x\n", hr
);
6801 IDWriteColorGlyphRunEnumerator_Release(layers
);
6803 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace2
, (void**)&fontface2
);
6804 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6806 /* invalid palette index */
6807 layers
= (void*)0xdeadbeef;
6808 hr
= IDWriteFactory2_TranslateColorGlyphRun(factory
, 0.0f
, 0.0f
, &run
, NULL
,
6809 DWRITE_MEASURING_MODE_NATURAL
, NULL
, IDWriteFontFace2_GetColorPaletteCount(fontface2
),
6811 ok(hr
== DWRITE_E_NOCOLOR
, "got 0x%08x\n", hr
);
6812 ok(layers
== NULL
, "got %p\n", layers
);
6815 hr
= IDWriteFactory2_TranslateColorGlyphRun(factory
, 0.0f
, 0.0f
, &run
, NULL
,
6816 DWRITE_MEASURING_MODE_NATURAL
, NULL
, IDWriteFontFace2_GetColorPaletteCount(fontface2
) - 1,
6818 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6819 IDWriteColorGlyphRunEnumerator_Release(layers
);
6821 /* color font, glyph without color info */
6822 codepoints
[0] = 'A';
6823 hr
= IDWriteFontFace_GetGlyphIndices(fontface
, codepoints
, 1, glyphs
);
6824 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6826 layers
= (void*)0xdeadbeef;
6827 hr
= IDWriteFactory2_TranslateColorGlyphRun(factory
, 0.0f
, 0.0f
, &run
, NULL
,
6828 DWRITE_MEASURING_MODE_NATURAL
, NULL
, 0, &layers
);
6829 ok(hr
== DWRITE_E_NOCOLOR
, "got 0x%08x\n", hr
);
6830 ok(layers
== NULL
, "got %p\n", layers
);
6832 /* one glyph with, one without */
6833 codepoints
[0] = 'A';
6834 codepoints
[1] = 0x26c4;
6836 hr
= IDWriteFontFace_GetGlyphIndices(fontface
, codepoints
, 2, glyphs
);
6837 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6842 hr
= IDWriteFactory2_TranslateColorGlyphRun(factory
, 0.0f
, 0.0f
, &run
, NULL
,
6843 DWRITE_MEASURING_MODE_NATURAL
, NULL
, 0, &layers
);
6844 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6845 ok(layers
!= NULL
, "got %p\n", layers
);
6846 IDWriteColorGlyphRunEnumerator_Release(layers
);
6848 IDWriteFontFace2_Release(fontface2
);
6849 IDWriteFontFace_Release(fontface
);
6850 ref
= IDWriteFactory2_Release(factory
);
6851 ok(ref
== 0, "factory not released, %u\n", ref
);
6854 static void test_HasCharacter(void)
6856 IDWriteFactory3
*factory3
;
6857 IDWriteFactory
*factory
;
6858 IDWriteFont3
*font3
;
6864 factory
= create_factory();
6866 font
= get_tahoma_instance(factory
, DWRITE_FONT_STYLE_NORMAL
);
6867 ok(font
!= NULL
, "failed to create font\n");
6869 /* Win8 is broken, QI claims to support IDWriteFont3, but in fact it does not */
6870 hr
= IDWriteFactory_QueryInterface(factory
, &IID_IDWriteFactory3
, (void**)&factory3
);
6872 hr
= IDWriteFont_QueryInterface(font
, &IID_IDWriteFont3
, (void**)&font3
);
6873 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6875 ret
= IDWriteFont3_HasCharacter(font3
, 'A');
6876 ok(ret
, "got %d\n", ret
);
6878 IDWriteFont3_Release(font3
);
6879 IDWriteFactory3_Release(factory3
);
6882 win_skip("IDWriteFont3 is not supported.\n");
6884 IDWriteFont_Release(font
);
6885 ref
= IDWriteFactory_Release(factory
);
6886 ok(ref
== 0, "factory not released, %u\n", ref
);
6889 static void test_CreateFontFaceReference(void)
6891 static const WCHAR dummyW
[] = {'d','u','m','m','y',0};
6892 IDWriteFontFace3
*fontface
, *fontface1
;
6893 IDWriteFontFaceReference
*ref
, *ref1
;
6894 IDWriteFontFile
*file
, *file1
;
6895 IDWriteFactory3
*factory
;
6896 IDWriteFont3
*font3
;
6904 factory
= create_factory_iid(&IID_IDWriteFactory3
);
6906 win_skip("CreateFontFaceReference() is not supported.\n");
6910 path
= create_testfontfile(test_fontfile
);
6912 hr
= IDWriteFactory3_CreateFontFaceReference(factory
, NULL
, NULL
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &ref
);
6913 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
6915 /* out of range simulation flags */
6916 hr
= IDWriteFactory3_CreateFontFaceReference(factory
, path
, NULL
, 0, ~0u, &ref
);
6917 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
6919 /* test file is not a collection, but reference could still be created with non-zero face index */
6920 hr
= IDWriteFactory3_CreateFontFaceReference(factory
, path
, NULL
, 1, DWRITE_FONT_SIMULATIONS_NONE
, &ref
);
6921 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6923 index
= IDWriteFontFaceReference_GetFontFaceIndex(ref
);
6924 ok(index
== 1, "got %u\n", index
);
6926 hr
= IDWriteFontFaceReference_GetFontFile(ref
, &file
);
6927 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6928 IDWriteFontFile_Release(file
);
6930 hr
= IDWriteFontFaceReference_CreateFontFace(ref
, &fontface
);
6932 ok(hr
== DWRITE_E_FILEFORMAT
, "got 0x%08x\n", hr
);
6934 IDWriteFontFaceReference_Release(ref
);
6936 /* path however has to be valid */
6937 hr
= IDWriteFactory3_CreateFontFaceReference(factory
, dummyW
, NULL
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &ref
);
6939 ok(hr
== DWRITE_E_FILENOTFOUND
, "got 0x%08x\n", hr
);
6941 IDWriteFontFaceReference_Release(ref
);
6943 EXPECT_REF(factory
, 1);
6944 hr
= IDWriteFactory3_CreateFontFaceReference(factory
, path
, NULL
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &ref
);
6945 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6946 EXPECT_REF(factory
, 2);
6948 /* new file is returned */
6949 hr
= IDWriteFontFaceReference_GetFontFile(ref
, &file
);
6950 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6952 hr
= IDWriteFontFaceReference_GetFontFile(ref
, &file1
);
6953 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6954 ok(file
!= file1
, "got %p, previous file %p\n", file1
, file
);
6956 IDWriteFontFile_Release(file
);
6957 IDWriteFontFile_Release(file1
);
6959 /* references are not reused */
6960 hr
= IDWriteFactory3_CreateFontFaceReference(factory
, path
, NULL
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &ref1
);
6961 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6962 ok(ref1
!= ref
, "got %p, previous ref %p\n", ref1
, ref
);
6964 /* created fontfaces are cached */
6965 hr
= IDWriteFontFaceReference_CreateFontFace(ref
, &fontface
);
6966 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6968 hr
= IDWriteFontFaceReference_CreateFontFace(ref1
, &fontface1
);
6969 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6970 ok(fontface
== fontface1
, "got %p, expected %p\n", fontface1
, fontface
);
6971 IDWriteFontFace3_Release(fontface
);
6972 IDWriteFontFace3_Release(fontface1
);
6974 /* reference equality */
6975 ret
= IDWriteFontFaceReference_Equals(ref
, ref1
);
6976 ok(ret
, "got %d\n", ret
);
6977 IDWriteFontFaceReference_Release(ref1
);
6979 hr
= IDWriteFactory3_CreateFontFaceReference(factory
, path
, NULL
, 1, DWRITE_FONT_SIMULATIONS_NONE
, &ref1
);
6980 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6981 ret
= IDWriteFontFaceReference_Equals(ref
, ref1
);
6982 ok(!ret
, "got %d\n", ret
);
6983 IDWriteFontFaceReference_Release(ref1
);
6985 hr
= IDWriteFactory3_CreateFontFaceReference(factory
, path
, NULL
, 0, DWRITE_FONT_SIMULATIONS_BOLD
, &ref1
);
6986 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6987 ret
= IDWriteFontFaceReference_Equals(ref
, ref1
);
6988 ok(!ret
, "got %d\n", ret
);
6989 IDWriteFontFaceReference_Release(ref1
);
6991 IDWriteFontFaceReference_Release(ref
);
6993 /* create reference from a file */
6994 hr
= IDWriteFactory3_CreateFontFileReference(factory
, path
, NULL
, &file
);
6995 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6997 hr
= IDWriteFactory3_CreateFontFaceReference_(factory
, file
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &ref
);
6998 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7000 hr
= IDWriteFontFaceReference_GetFontFile(ref
, &file1
);
7001 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7002 ok(file
!= file1
, "got %p, previous file %p\n", file1
, file
);
7004 IDWriteFontFaceReference_Release(ref
);
7005 IDWriteFontFile_Release(file
);
7006 IDWriteFontFile_Release(file1
);
7008 /* references returned from IDWriteFont3 */
7009 font
= get_tahoma_instance((IDWriteFactory
*)factory
, DWRITE_FONT_STYLE_NORMAL
);
7010 hr
= IDWriteFont_QueryInterface(font
, &IID_IDWriteFont3
, (void**)&font3
);
7011 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7012 IDWriteFont_Release(font
);
7014 hr
= IDWriteFont3_GetFontFaceReference(font3
, &ref
);
7015 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7017 hr
= IDWriteFont3_GetFontFaceReference(font3
, &ref1
);
7018 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7019 ok(ref
!= ref1
, "got %p, %p\n", ref1
, ref
);
7021 IDWriteFontFaceReference_Release(ref
);
7022 IDWriteFontFaceReference_Release(ref1
);
7024 /* references returned from IDWriteFontFace3 */
7025 hr
= IDWriteFont3_CreateFontFace(font3
, &fontface
);
7026 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7028 hr
= IDWriteFontFace3_GetFontFaceReference(fontface
, &ref
);
7030 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7032 hr
= IDWriteFontFace3_GetFontFaceReference(fontface
, &ref1
);
7034 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7036 ok(ref
== ref1
, "got %p, %p\n", ref1
, ref
);
7039 hr
= IDWriteFontFaceReference_CreateFontFace(ref
, &fontface1
);
7040 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7041 ok(fontface1
== fontface
, "got %p, %p\n", fontface1
, fontface
);
7042 IDWriteFontFace3_Release(fontface1
);
7044 IDWriteFontFaceReference_Release(ref
);
7045 IDWriteFontFaceReference_Release(ref1
);
7047 IDWriteFontFace3_Release(fontface
);
7048 IDWriteFont3_Release(font3
);
7050 refcount
= IDWriteFactory3_Release(factory
);
7051 ok(refcount
== 0, "factory not released, %u\n", refcount
);
7052 DELETE_FONTFILE(path
);
7055 static void get_expected_fontsig(IDWriteFont
*font
, FONTSIGNATURE
*fontsig
)
7058 IDWriteFontFace
*fontface
;
7059 const TT_OS2_V2
*tt_os2
;
7064 memset(fontsig
, 0, sizeof(*fontsig
));
7066 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
7067 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7069 hr
= IDWriteFontFace_TryGetFontTable(fontface
, MS_0S2_TAG
, (const void**)&tt_os2
, &size
, &os2_context
, &exists
);
7070 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7073 fontsig
->fsUsb
[0] = GET_BE_DWORD(tt_os2
->ulUnicodeRange1
);
7074 fontsig
->fsUsb
[1] = GET_BE_DWORD(tt_os2
->ulUnicodeRange2
);
7075 fontsig
->fsUsb
[2] = GET_BE_DWORD(tt_os2
->ulUnicodeRange3
);
7076 fontsig
->fsUsb
[3] = GET_BE_DWORD(tt_os2
->ulUnicodeRange4
);
7078 if (GET_BE_WORD(tt_os2
->version
) == 0) {
7079 fontsig
->fsCsb
[0] = 0;
7080 fontsig
->fsCsb
[1] = 0;
7083 fontsig
->fsCsb
[0] = GET_BE_DWORD(tt_os2
->ulCodePageRange1
);
7084 fontsig
->fsCsb
[1] = GET_BE_DWORD(tt_os2
->ulCodePageRange2
);
7087 IDWriteFontFace_ReleaseFontTable(fontface
, os2_context
);
7090 IDWriteFontFace_Release(fontface
);
7093 static void test_GetFontSignature(void)
7095 IDWriteFontCollection
*syscollection
;
7096 IDWriteGdiInterop1
*interop1
;
7097 IDWriteGdiInterop
*interop
;
7098 IDWriteFactory
*factory
;
7099 FONTSIGNATURE fontsig
;
7104 factory
= create_factory();
7106 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop
);
7107 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7109 hr
= IDWriteGdiInterop_QueryInterface(interop
, &IID_IDWriteGdiInterop1
, (void**)&interop1
);
7110 IDWriteGdiInterop_Release(interop
);
7112 win_skip("GetFontSignature() is not supported.\n");
7113 IDWriteGdiInterop_Release(interop
);
7114 IDWriteFactory_Release(factory
);
7117 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7119 hr
= IDWriteGdiInterop1_GetFontSignature(interop1
, NULL
, &fontsig
);
7120 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
7122 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &syscollection
, FALSE
);
7123 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7124 count
= IDWriteFontCollection_GetFontFamilyCount(syscollection
);
7126 for (i
= 0; i
< count
; i
++) {
7127 FONTSIGNATURE expected_signature
;
7128 IDWriteLocalizedStrings
*names
;
7129 IDWriteFontFamily
*family
;
7133 hr
= IDWriteFontCollection_GetFontFamily(syscollection
, i
, &family
);
7134 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7136 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STRETCH_NORMAL
,
7137 DWRITE_FONT_STYLE_NORMAL
, &font
);
7138 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7140 hr
= IDWriteFontFamily_GetFamilyNames(family
, &names
);
7141 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7143 get_enus_string(names
, nameW
, sizeof(nameW
)/sizeof(nameW
[0]));
7145 IDWriteLocalizedStrings_Release(names
);
7147 hr
= IDWriteGdiInterop1_GetFontSignature(interop1
, font
, &fontsig
);
7148 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7150 get_expected_fontsig(font
, &expected_signature
);
7152 ok(fontsig
.fsUsb
[0] == expected_signature
.fsUsb
[0], "%s: fsUsb[0] %#x, expected %#x\n", wine_dbgstr_w(nameW
),
7153 fontsig
.fsUsb
[0], expected_signature
.fsUsb
[0]);
7154 ok(fontsig
.fsUsb
[1] == expected_signature
.fsUsb
[1], "%s: fsUsb[1] %#x, expected %#x\n", wine_dbgstr_w(nameW
),
7155 fontsig
.fsUsb
[1], expected_signature
.fsUsb
[1]);
7156 ok(fontsig
.fsUsb
[2] == expected_signature
.fsUsb
[2], "%s: fsUsb[2] %#x, expected %#x\n", wine_dbgstr_w(nameW
),
7157 fontsig
.fsUsb
[2], expected_signature
.fsUsb
[2]);
7158 ok(fontsig
.fsUsb
[3] == expected_signature
.fsUsb
[3], "%s: fsUsb[3] %#x, expected %#x\n", wine_dbgstr_w(nameW
),
7159 fontsig
.fsUsb
[3], expected_signature
.fsUsb
[3]);
7161 ok(fontsig
.fsCsb
[0] == expected_signature
.fsCsb
[0], "%s: fsCsb[0] %#x, expected %#x\n", wine_dbgstr_w(nameW
),
7162 fontsig
.fsCsb
[0], expected_signature
.fsCsb
[0]);
7163 ok(fontsig
.fsCsb
[1] == expected_signature
.fsCsb
[1], "%s: fsCsb[1] %#x, expected %#x\n", wine_dbgstr_w(nameW
),
7164 fontsig
.fsCsb
[1], expected_signature
.fsCsb
[1]);
7166 IDWriteFont_Release(font
);
7167 IDWriteFontFamily_Release(family
);
7170 IDWriteGdiInterop1_Release(interop1
);
7171 IDWriteFontCollection_Release(syscollection
);
7172 ref
= IDWriteFactory_Release(factory
);
7173 ok(ref
== 0, "factory not released, %u\n", ref
);
7176 static void test_font_properties(void)
7178 IDWriteFontFace3
*fontface3
;
7179 IDWriteFontFace
*fontface
;
7180 IDWriteFactory
*factory
;
7181 DWRITE_FONT_STYLE style
;
7186 factory
= create_factory();
7188 /* this creates simulated font */
7189 font
= get_tahoma_instance(factory
, DWRITE_FONT_STYLE_ITALIC
);
7191 style
= IDWriteFont_GetStyle(font
);
7192 ok(style
== DWRITE_FONT_STYLE_OBLIQUE
, "got %u\n", style
);
7194 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
7195 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7197 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace3
, (void**)&fontface3
);
7198 IDWriteFontFace_Release(fontface
);
7200 style
= IDWriteFontFace3_GetStyle(fontface3
);
7201 ok(style
== DWRITE_FONT_STYLE_OBLIQUE
, "got %u\n", style
);
7203 IDWriteFontFace3_Release(fontface3
);
7206 IDWriteFont_Release(font
);
7207 ref
= IDWriteFactory_Release(factory
);
7208 ok(ref
== 0, "factory not released, %u\n", ref
);
7211 static BOOL
has_vertical_glyph_variants(IDWriteFontFace1
*fontface
)
7213 const OT_FeatureList
*featurelist
;
7214 const OT_LookupList
*lookup_list
;
7215 BOOL exists
= FALSE
, ret
= FALSE
;
7216 const GSUB_Header
*header
;
7223 hr
= IDWriteFontFace1_TryGetFontTable(fontface
, MS_GSUB_TAG
, &data
, &size
, &context
, &exists
);
7224 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7230 featurelist
= (OT_FeatureList
*)((BYTE
*)header
+ GET_BE_WORD(header
->FeatureList
));
7231 lookup_list
= (const OT_LookupList
*)((BYTE
*)header
+ GET_BE_WORD(header
->LookupList
));
7233 for (i
= 0; i
< GET_BE_WORD(featurelist
->FeatureCount
); i
++) {
7234 if (*(UINT32
*)featurelist
->FeatureRecord
[i
].FeatureTag
== DWRITE_FONT_FEATURE_TAG_VERTICAL_WRITING
) {
7235 const OT_Feature
*feature
= (const OT_Feature
*)((BYTE
*)featurelist
+ GET_BE_WORD(featurelist
->FeatureRecord
[i
].Feature
));
7236 UINT16 lookup_count
= GET_BE_WORD(feature
->LookupCount
), i
, index
, count
, type
;
7237 const GSUB_SingleSubstFormat2
*subst2
;
7238 const OT_LookupTable
*lookup_table
;
7241 if (lookup_count
== 0)
7244 for (i
= 0; i
< lookup_count
; i
++) {
7245 /* check if lookup is empty */
7246 index
= GET_BE_WORD(feature
->LookupListIndex
[i
]);
7247 lookup_table
= (const OT_LookupTable
*)((BYTE
*)lookup_list
+ GET_BE_WORD(lookup_list
->Lookup
[index
]));
7249 type
= GET_BE_WORD(lookup_table
->LookupType
);
7250 ok(type
== 1 || type
== 7, "got unexpected lookup type %u\n", type
);
7252 count
= GET_BE_WORD(lookup_table
->SubTableCount
);
7256 ok(count
> 0, "got unexpected subtable count %u\n", count
);
7258 offset
= GET_BE_WORD(lookup_table
->SubTable
[0]);
7260 const GSUB_ExtensionPosFormat1
*ext
= (const GSUB_ExtensionPosFormat1
*)((const BYTE
*)lookup_table
+ offset
);
7261 if (GET_BE_WORD(ext
->SubstFormat
) == 1)
7262 offset
+= GET_BE_DWORD(ext
->ExtensionOffset
);
7264 ok(0, "Unhandled Extension Substitution Format %u\n", GET_BE_WORD(ext
->SubstFormat
));
7267 subst2
= (const GSUB_SingleSubstFormat2
*)((BYTE
*)lookup_table
+ offset
);
7268 index
= GET_BE_WORD(subst2
->SubstFormat
);
7270 ok(0, "validate Single Substitution Format 1\n");
7271 else if (index
== 2) {
7272 /* SimSun-ExtB has 0 glyph count for this substitution */
7273 if (GET_BE_WORD(subst2
->GlyphCount
) > 0) {
7279 ok(0, "unknown Single Substitution Format, %u\n", index
);
7284 IDWriteFontFace1_ReleaseFontTable(fontface
, context
);
7289 static void test_HasVerticalGlyphVariants(void)
7291 IDWriteFontCollection
*syscollection
;
7292 IDWriteFontFace1
*fontface1
;
7293 IDWriteFontFace
*fontface
;
7294 IDWriteFactory
*factory
;
7299 factory
= create_factory();
7300 fontface
= create_fontface(factory
);
7302 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void**)&fontface1
);
7303 IDWriteFontFace_Release(fontface
);
7305 win_skip("HasVerticalGlyphVariants() is not supported.\n");
7306 IDWriteFactory_Release(factory
);
7309 IDWriteFontFace1_Release(fontface1
);
7311 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &syscollection
, FALSE
);
7312 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7313 count
= IDWriteFontCollection_GetFontFamilyCount(syscollection
);
7315 for (i
= 0; i
< count
; i
++) {
7316 IDWriteLocalizedStrings
*names
;
7317 BOOL expected_vert
, has_vert
;
7318 IDWriteFontFamily
*family
;
7322 hr
= IDWriteFontCollection_GetFontFamily(syscollection
, i
, &family
);
7323 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7325 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STRETCH_NORMAL
,
7326 DWRITE_FONT_STYLE_NORMAL
, &font
);
7327 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7329 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
7330 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7332 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void**)&fontface1
);
7333 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7335 hr
= IDWriteFontFamily_GetFamilyNames(family
, &names
);
7336 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7338 get_enus_string(names
, nameW
, sizeof(nameW
)/sizeof(nameW
[0]));
7340 expected_vert
= has_vertical_glyph_variants(fontface1
);
7341 has_vert
= IDWriteFontFace1_HasVerticalGlyphVariants(fontface1
);
7343 ok(expected_vert
== has_vert
, "%s: expected vertical feature %d, got %d\n",
7344 wine_dbgstr_w(nameW
), expected_vert
, has_vert
);
7346 IDWriteLocalizedStrings_Release(names
);
7347 IDWriteFont_Release(font
);
7349 IDWriteFontFace1_Release(fontface1
);
7350 IDWriteFontFace_Release(fontface
);
7351 IDWriteFontFamily_Release(family
);
7354 IDWriteFontCollection_Release(syscollection
);
7355 ref
= IDWriteFactory_Release(factory
);
7356 ok(ref
== 0, "factory not released, %u\n", ref
);
7359 static void test_HasKerningPairs(void)
7361 IDWriteFontCollection
*syscollection
;
7362 IDWriteFontFace1
*fontface1
;
7363 IDWriteFontFace
*fontface
;
7364 IDWriteFactory
*factory
;
7369 factory
= create_factory();
7370 fontface
= create_fontface(factory
);
7372 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void**)&fontface1
);
7373 IDWriteFontFace_Release(fontface
);
7375 win_skip("HasKerningPairs() is not supported.\n");
7376 IDWriteFactory_Release(factory
);
7379 IDWriteFontFace1_Release(fontface1
);
7381 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &syscollection
, FALSE
);
7382 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7383 count
= IDWriteFontCollection_GetFontFamilyCount(syscollection
);
7385 for (i
= 0; i
< count
; i
++) {
7386 IDWriteLocalizedStrings
*names
;
7387 BOOL exists
, has_kerningpairs
;
7388 IDWriteFontFamily
*family
;
7395 hr
= IDWriteFontCollection_GetFontFamily(syscollection
, i
, &family
);
7396 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7398 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STRETCH_NORMAL
,
7399 DWRITE_FONT_STYLE_NORMAL
, &font
);
7400 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7402 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
7403 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7405 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void **)&fontface1
);
7406 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7408 hr
= IDWriteFontFamily_GetFamilyNames(family
, &names
);
7409 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7411 get_enus_string(names
, nameW
, sizeof(nameW
)/sizeof(nameW
[0]));
7414 hr
= IDWriteFontFace1_TryGetFontTable(fontface1
, MS_KERN_TAG
, &data
, &size
, &context
, &exists
);
7415 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7416 IDWriteFontFace1_ReleaseFontTable(fontface1
, context
);
7418 has_kerningpairs
= IDWriteFontFace1_HasKerningPairs(fontface1
);
7420 ok(!has_kerningpairs
, "%s: expected %d, got %d\n", wine_dbgstr_w(nameW
), exists
, has_kerningpairs
);
7422 IDWriteLocalizedStrings_Release(names
);
7423 IDWriteFont_Release(font
);
7425 IDWriteFontFace1_Release(fontface1
);
7426 IDWriteFontFace_Release(fontface
);
7427 IDWriteFontFamily_Release(family
);
7430 IDWriteFontCollection_Release(syscollection
);
7431 ref
= IDWriteFactory_Release(factory
);
7432 ok(ref
== 0, "factory not released, %u\n", ref
);
7435 static void test_ComputeGlyphOrigins(void)
7437 IDWriteFactory4
*factory
;
7438 DWRITE_GLYPH_RUN run
;
7440 D2D1_POINT_2F origins
[2];
7441 D2D1_POINT_2F baseline_origin
;
7447 factory
= create_factory_iid(&IID_IDWriteFactory4
);
7449 win_skip("ComputeGlyphOrigins() is not supported.\n");
7453 advances
[0] = 10.0f
;
7454 advances
[1] = 20.0f
;
7456 run
.fontFace
= NULL
;
7457 run
.fontEmSize
= 16.0f
;
7459 run
.glyphIndices
= glyphs
;
7460 run
.glyphAdvances
= advances
;
7461 run
.glyphOffsets
= NULL
;
7462 run
.isSideways
= FALSE
;
7465 baseline_origin
.x
= 123.0f
;
7466 baseline_origin
.y
= 321.0f
;
7468 memset(origins
, 0, sizeof(origins
));
7469 hr
= IDWriteFactory4_ComputeGlyphOrigins_(factory
, &run
, baseline_origin
, origins
);
7470 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7471 ok(origins
[0].x
== 123.0f
&& origins
[0].y
== 321.0f
, "origins[0] %f,%f\n", origins
[0].x
, origins
[0].y
);
7472 ok(origins
[1].x
== 133.0f
&& origins
[1].y
== 321.0f
, "origins[1] %f,%f\n", origins
[1].x
, origins
[1].y
);
7474 memset(origins
, 0, sizeof(origins
));
7475 hr
= IDWriteFactory4_ComputeGlyphOrigins(factory
, &run
, DWRITE_MEASURING_MODE_NATURAL
, baseline_origin
,
7477 ok(origins
[0].x
== 123.0f
&& origins
[0].y
== 321.0f
, "origins[0] %f,%f\n", origins
[0].x
, origins
[0].y
);
7478 ok(origins
[1].x
== 133.0f
&& origins
[1].y
== 321.0f
, "origins[1] %f,%f\n", origins
[1].x
, origins
[1].y
);
7480 /* transform is not applied to returned origins */
7488 memset(origins
, 0, sizeof(origins
));
7489 hr
= IDWriteFactory4_ComputeGlyphOrigins(factory
, &run
, DWRITE_MEASURING_MODE_NATURAL
, baseline_origin
,
7491 ok(origins
[0].x
== 123.0f
&& origins
[0].y
== 321.0f
, "origins[0] %f,%f\n", origins
[0].x
, origins
[0].y
);
7492 ok(origins
[1].x
== 133.0f
&& origins
[1].y
== 321.0f
, "origins[1] %f,%f\n", origins
[1].x
, origins
[1].y
);
7494 ref
= IDWriteFactory4_Release(factory
);
7495 ok(ref
== 0, "factory not released, %u\n", ref
);
7498 static void test_object_lifetime(void)
7500 IDWriteFontCollection
*collection
, *collection2
;
7501 IDWriteFontList
*fontlist
, *fontlist2
;
7502 IDWriteGdiInterop
*interop
, *interop2
;
7503 IDWriteFontFamily
*family
, *family2
;
7504 IDWriteFontFace
*fontface
;
7505 IDWriteFont
*font
, *font2
;
7506 IDWriteFactory
*factory
;
7510 factory
= create_factory();
7511 EXPECT_REF(factory
, 1);
7513 /* system collection takes factory reference */
7514 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &collection
, FALSE
);
7515 ok(hr
== S_OK
, "got %#x\n", hr
);
7517 EXPECT_REF(collection
, 1);
7518 EXPECT_REF(factory
, 2);
7520 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &collection2
, FALSE
);
7521 ok(hr
== S_OK
, "got %#x\n", hr
);
7522 ok(collection2
== collection
, "expected same collection\n");
7524 EXPECT_REF(collection
, 2);
7525 EXPECT_REF(factory
, 2);
7527 IDWriteFontCollection_Release(collection2
);
7529 IDWriteFontCollection_AddRef(collection
);
7530 EXPECT_REF(collection
, 2);
7531 EXPECT_REF(factory
, 2);
7532 IDWriteFontCollection_Release(collection
);
7534 EXPECT_REF(collection
, 1);
7536 /* family takes collection reference */
7537 hr
= IDWriteFontCollection_GetFontFamily(collection
, 0, &family
);
7538 ok(hr
== S_OK
, "got %#x\n", hr
);
7540 EXPECT_REF(family
, 1);
7541 EXPECT_REF(collection
, 2);
7542 EXPECT_REF(factory
, 2);
7544 hr
= IDWriteFontCollection_GetFontFamily(collection
, 0, &family2
);
7545 ok(hr
== S_OK
, "got %#x\n", hr
);
7547 EXPECT_REF(family2
, 1);
7548 EXPECT_REF(collection
, 3);
7549 EXPECT_REF(factory
, 2);
7551 IDWriteFontFamily_Release(family2
);
7553 EXPECT_REF(family
, 1);
7554 EXPECT_REF(collection
, 2);
7555 EXPECT_REF(factory
, 2);
7557 /* font takes family reference */
7558 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
,
7559 DWRITE_FONT_STRETCH_NORMAL
, DWRITE_FONT_STYLE_NORMAL
, &font
);
7560 ok(hr
== S_OK
, "got %#x\n", hr
);
7562 EXPECT_REF(family
, 2);
7563 EXPECT_REF(collection
, 2);
7564 EXPECT_REF(factory
, 2);
7566 hr
= IDWriteFont_GetFontFamily(font
, &family2
);
7567 ok(hr
== S_OK
, "got %#x\n", hr
);
7568 ok(family2
== family
, "unexpected family pointer\n");
7569 IDWriteFontFamily_Release(family2
);
7571 EXPECT_REF(font
, 1);
7572 EXPECT_REF(factory
, 2);
7574 /* Fontface takes factory reference and nothing else. */
7575 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
7576 ok(hr
== S_OK
, "got %#x\n", hr
);
7578 EXPECT_REF(font
, 1);
7579 EXPECT_REF_BROKEN(fontface
, 1, 2);
7580 EXPECT_REF(family
, 2);
7581 EXPECT_REF(collection
, 2);
7582 EXPECT_REF_BROKEN(factory
, 3, 2);
7584 /* get font from fontface */
7585 hr
= IDWriteFontCollection_GetFontFromFontFace(collection
, fontface
, &font2
);
7586 ok(hr
== S_OK
, "got %#x\n", hr
);
7588 EXPECT_REF(font
, 1);
7589 EXPECT_REF(font2
, 1);
7590 EXPECT_REF_BROKEN(fontface
, 1, 2);
7591 EXPECT_REF(family
, 2);
7592 EXPECT_REF(collection
, 3);
7593 EXPECT_REF_BROKEN(factory
, 3, 2);
7595 IDWriteFont_Release(font2
);
7596 IDWriteFontFace_Release(fontface
);
7598 EXPECT_REF(font
, 1);
7599 EXPECT_REF(family
, 2);
7600 EXPECT_REF(collection
, 2);
7601 EXPECT_REF(factory
, 2);
7603 IDWriteFont_Release(font
);
7605 EXPECT_REF(family
, 1);
7606 EXPECT_REF(collection
, 2);
7607 EXPECT_REF(factory
, 2);
7609 /* Matching fonts list takes family reference. */
7610 hr
= IDWriteFontFamily_GetMatchingFonts(family
, DWRITE_FONT_WEIGHT_NORMAL
,
7611 DWRITE_FONT_STRETCH_NORMAL
, DWRITE_FONT_STYLE_NORMAL
, &fontlist
);
7612 ok(hr
== S_OK
, "got %#x\n", hr
);
7614 EXPECT_REF(family
, 2);
7615 EXPECT_REF(collection
, 2);
7616 EXPECT_REF(factory
, 2);
7618 hr
= IDWriteFontFamily_GetMatchingFonts(family
, DWRITE_FONT_WEIGHT_NORMAL
,
7619 DWRITE_FONT_STRETCH_NORMAL
, DWRITE_FONT_STYLE_NORMAL
, &fontlist2
);
7620 ok(hr
== S_OK
, "got %#x\n", hr
);
7621 ok(fontlist2
!= fontlist
, "unexpected font list\n");
7622 IDWriteFontList_Release(fontlist2
);
7624 IDWriteFontList_Release(fontlist
);
7626 IDWriteFontFamily_Release(family
);
7627 EXPECT_REF(collection
, 1);
7629 EXPECT_REF(factory
, 2);
7630 ref
= IDWriteFontCollection_Release(collection
);
7631 ok(ref
== 0, "collection not released, %u\n", ref
);
7632 EXPECT_REF(factory
, 1);
7634 /* GDI interop object takes factory reference */
7635 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop
);
7636 ok(hr
== S_OK
, "got %#x\n", hr
);
7637 EXPECT_REF(interop
, 1);
7638 EXPECT_REF(factory
, 2);
7640 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop2
);
7641 ok(hr
== S_OK
, "got %#x\n", hr
);
7642 ok(interop
== interop2
, "got unexpected interop pointer\n");
7644 EXPECT_REF(interop
, 2);
7645 EXPECT_REF(factory
, 2);
7647 IDWriteGdiInterop_Release(interop2
);
7648 ref
= IDWriteGdiInterop_Release(interop
);
7649 ok(ref
== 0, "interop not released, %u\n", ref
);
7651 ref
= IDWriteFactory_Release(factory
);
7652 ok(ref
== 0, "factory not released, %u\n", ref
);
7655 struct testowner_object
7657 IUnknown IUnknown_iface
;
7661 static inline struct testowner_object
*impl_from_IUnknown(IUnknown
*iface
)
7663 return CONTAINING_RECORD(iface
, struct testowner_object
, IUnknown_iface
);
7666 static HRESULT WINAPI
testowner_QueryInterface(IUnknown
*iface
, REFIID riid
, void **obj
)
7668 if (IsEqualIID(riid
, &IID_IUnknown
)) {
7670 IUnknown_AddRef(iface
);
7675 return E_NOINTERFACE
;
7678 static ULONG WINAPI
testowner_AddRef(IUnknown
*iface
)
7680 struct testowner_object
*object
= impl_from_IUnknown(iface
);
7681 return InterlockedIncrement(&object
->ref
);
7684 static ULONG WINAPI
testowner_Release(IUnknown
*iface
)
7686 struct testowner_object
*object
= impl_from_IUnknown(iface
);
7687 return InterlockedDecrement(&object
->ref
);
7690 static const IUnknownVtbl testownervtbl
= {
7691 testowner_QueryInterface
,
7696 static void testowner_init(struct testowner_object
*object
)
7698 object
->IUnknown_iface
.lpVtbl
= &testownervtbl
;
7702 static void test_inmemory_file_loader(void)
7704 IDWriteFontFileStream
*stream
, *stream2
, *stream3
;
7705 IDWriteFontFileLoader
*loader
, *loader2
;
7706 IDWriteInMemoryFontFileLoader
*inmemory
;
7707 struct testowner_object ownerobject
;
7708 const void *key
, *data
, *frag_start
;
7709 UINT64 file_size
, size
, writetime
;
7710 IDWriteFontFile
*file
, *file2
;
7711 IDWriteFontFace
*fontface
;
7712 void *context
, *context2
;
7713 IDWriteFactory5
*factory
;
7714 UINT32 count
, key_size
;
7719 factory
= create_factory_iid(&IID_IDWriteFactory5
);
7721 win_skip("CreateInMemoryFontFileLoader() is not supported\n");
7725 EXPECT_REF(factory
, 1);
7726 hr
= IDWriteFactory5_CreateInMemoryFontFileLoader(factory
, &loader
);
7727 ok(hr
== S_OK
, "got %#x\n", hr
);
7728 EXPECT_REF(factory
, 1);
7730 testowner_init(&ownerobject
);
7731 fontface
= create_fontface((IDWriteFactory
*)factory
);
7733 hr
= IDWriteFactory5_CreateInMemoryFontFileLoader(factory
, &loader2
);
7734 ok(hr
== S_OK
, "got %#x\n", hr
);
7735 ok(loader
!= loader2
, "unexpected pointer\n");
7736 IDWriteFontFileLoader_Release(loader2
);
7738 hr
= IDWriteFontFileLoader_QueryInterface(loader
, &IID_IDWriteInMemoryFontFileLoader
, (void **)&inmemory
);
7739 ok(hr
== S_OK
, "got %#x\n", hr
);
7740 IDWriteFontFileLoader_Release(loader
);
7741 EXPECT_REF(inmemory
, 1);
7743 count
= IDWriteInMemoryFontFileLoader_GetFileCount(inmemory
);
7744 ok(!count
, "Unexpected file count %u.\n", count
);
7746 /* Use whole font blob to construct in-memory file. */
7748 hr
= IDWriteFontFace_GetFiles(fontface
, &count
, &file
);
7749 ok(hr
== S_OK
, "got %#x\n", hr
);
7751 hr
= IDWriteFontFile_GetLoader(file
, &loader
);
7752 ok(hr
== S_OK
, "got %#x\n", hr
);
7754 hr
= IDWriteFontFile_GetReferenceKey(file
, &key
, &key_size
);
7755 ok(hr
== S_OK
, "got %#x\n", hr
);
7757 hr
= IDWriteFontFileLoader_CreateStreamFromKey(loader
, key
, key_size
, &stream
);
7758 ok(hr
== S_OK
, "got %#x\n", hr
);
7759 IDWriteFontFileLoader_Release(loader
);
7760 IDWriteFontFile_Release(file
);
7762 hr
= IDWriteFontFileStream_GetFileSize(stream
, &file_size
);
7763 ok(hr
== S_OK
, "got %#x\n", hr
);
7765 hr
= IDWriteFontFileStream_ReadFileFragment(stream
, &data
, 0, file_size
, &context
);
7766 ok(hr
== S_OK
, "got %#x\n", hr
);
7768 /* Not registered yet. */
7769 hr
= IDWriteInMemoryFontFileLoader_CreateInMemoryFontFileReference(inmemory
, (IDWriteFactory
*)factory
, data
,
7770 file_size
, NULL
, &file
);
7771 ok(hr
== E_INVALIDARG
, "got %#x\n", hr
);
7773 count
= IDWriteInMemoryFontFileLoader_GetFileCount(inmemory
);
7774 ok(count
== 1, "Unexpected file count %u.\n", count
);
7776 hr
= IDWriteFactory5_RegisterFontFileLoader(factory
, (IDWriteFontFileLoader
*)inmemory
);
7777 ok(hr
== S_OK
, "got %#x\n", hr
);
7778 EXPECT_REF(inmemory
, 2);
7780 EXPECT_REF(&ownerobject
.IUnknown_iface
, 1);
7781 hr
= IDWriteInMemoryFontFileLoader_CreateInMemoryFontFileReference(inmemory
, (IDWriteFactory
*)factory
, data
,
7782 file_size
, &ownerobject
.IUnknown_iface
, &file
);
7783 ok(hr
== S_OK
, "got %#x\n", hr
);
7784 EXPECT_REF(&ownerobject
.IUnknown_iface
, 2);
7785 EXPECT_REF(inmemory
, 3);
7787 count
= IDWriteInMemoryFontFileLoader_GetFileCount(inmemory
);
7788 ok(count
== 2, "Unexpected file count %u.\n", count
);
7790 hr
= IDWriteInMemoryFontFileLoader_CreateInMemoryFontFileReference(inmemory
, (IDWriteFactory
*)factory
, data
,
7791 file_size
, &ownerobject
.IUnknown_iface
, &file2
);
7792 ok(hr
== S_OK
, "got %#x\n", hr
);
7793 ok(file2
!= file
, "got unexpected file\n");
7794 EXPECT_REF(&ownerobject
.IUnknown_iface
, 3);
7795 EXPECT_REF(inmemory
, 4);
7797 count
= IDWriteInMemoryFontFileLoader_GetFileCount(inmemory
);
7798 ok(count
== 3, "Unexpected file count %u.\n", count
);
7800 /* Check in-memory reference key format. */
7801 hr
= IDWriteFontFile_GetReferenceKey(file
, &key
, &key_size
);
7802 ok(hr
== S_OK
, "got %#x\n", hr
);
7804 ok(key
&& *(DWORD
*)key
== 1, "got wrong ref key\n");
7805 ok(key_size
== 4, "ref key size %u\n", key_size
);
7807 hr
= IDWriteFontFile_GetReferenceKey(file2
, &key
, &key_size
);
7808 ok(hr
== S_OK
, "got %#x\n", hr
);
7810 ok(key
&& *(DWORD
*)key
== 2, "got wrong ref key\n");
7811 ok(key_size
== 4, "ref key size %u\n", key_size
);
7813 EXPECT_REF(inmemory
, 4);
7814 hr
= IDWriteInMemoryFontFileLoader_CreateStreamFromKey(inmemory
, key
, key_size
, &stream2
);
7815 ok(hr
== S_OK
, "Failed to create a stream, hr %#x.\n", hr
);
7816 EXPECT_REF(stream2
, 1);
7817 EXPECT_REF(inmemory
, 4);
7819 hr
= IDWriteInMemoryFontFileLoader_CreateStreamFromKey(inmemory
, key
, key_size
, &stream3
);
7820 ok(hr
== S_OK
, "Failed to create a stream, hr %#x.\n", hr
);
7822 ok(stream2
!= stream3
, "Unexpected stream.\n");
7824 IDWriteFontFileStream_Release(stream2
);
7825 IDWriteFontFileStream_Release(stream3
);
7827 /* Release file at index 1, create new one to see if index is reused. */
7828 EXPECT_REF(&ownerobject
.IUnknown_iface
, 3);
7829 ref
= IDWriteFontFile_Release(file
);
7830 ok(ref
== 0, "File object not released, %u.\n", ref
);
7831 EXPECT_REF(&ownerobject
.IUnknown_iface
, 3);
7833 count
= IDWriteInMemoryFontFileLoader_GetFileCount(inmemory
);
7834 ok(count
== 3, "Unexpected file count %u.\n", count
);
7836 EXPECT_REF(&ownerobject
.IUnknown_iface
, 3);
7837 ref
= IDWriteFontFile_Release(file2
);
7838 ok(ref
== 0, "File object not released, %u.\n", ref
);
7839 EXPECT_REF(&ownerobject
.IUnknown_iface
, 3);
7841 count
= IDWriteInMemoryFontFileLoader_GetFileCount(inmemory
);
7842 ok(count
== 3, "Unexpected file count %u.\n", count
);
7844 hr
= IDWriteFactory5_UnregisterFontFileLoader(factory
, (IDWriteFontFileLoader
*)inmemory
);
7845 ok(hr
== S_OK
, "got %#x\n", hr
);
7846 EXPECT_REF(&ownerobject
.IUnknown_iface
, 3);
7848 EXPECT_REF(&ownerobject
.IUnknown_iface
, 3);
7849 ref
= IDWriteInMemoryFontFileLoader_Release(inmemory
);
7850 ok(ref
== 0, "loader not released, %u.\n", ref
);
7851 EXPECT_REF(&ownerobject
.IUnknown_iface
, 1);
7853 /* Test reference key for first added file. */
7854 hr
= IDWriteFactory5_CreateInMemoryFontFileLoader(factory
, &loader
);
7855 ok(hr
== S_OK
, "Failed to create loader, hr %#x.\n", hr
);
7857 hr
= IDWriteFontFileLoader_QueryInterface(loader
, &IID_IDWriteInMemoryFontFileLoader
, (void **)&inmemory
);
7858 ok(hr
== S_OK
, "Failed to get in-memory interface, hr %#x.\n", hr
);
7859 IDWriteFontFileLoader_Release(loader
);
7861 hr
= IDWriteFactory5_RegisterFontFileLoader(factory
, (IDWriteFontFileLoader
*)inmemory
);
7862 ok(hr
== S_OK
, "Failed to register loader, hr %#x.\n", hr
);
7865 hr
= IDWriteInMemoryFontFileLoader_CreateStreamFromKey(inmemory
, &ref_key
, sizeof(ref_key
), &stream2
);
7866 ok(hr
== E_INVALIDARG
, "Unexpected hr %#x.\n", hr
);
7868 hr
= IDWriteInMemoryFontFileLoader_CreateInMemoryFontFileReference(inmemory
, (IDWriteFactory
*)factory
, data
,
7869 file_size
, &ownerobject
.IUnknown_iface
, &file
);
7870 ok(hr
== S_OK
, "Failed to create in-memory file reference, hr %#x.\n", hr
);
7873 hr
= IDWriteInMemoryFontFileLoader_CreateStreamFromKey(inmemory
, &ref_key
, sizeof(ref_key
), &stream2
);
7874 ok(hr
== S_OK
, "Failed to create a stream, hr %#x.\n", hr
);
7876 context2
= (void *)0xdeadbeef;
7877 hr
= IDWriteFontFileStream_ReadFileFragment(stream2
, &frag_start
, 0, file_size
, &context2
);
7878 ok(hr
== S_OK
, "Failed to read a fragment, hr %#x.\n", hr
);
7879 ok(context
== NULL
, "Unexpected context %p.\n", context2
);
7880 ok(frag_start
== data
, "Unexpected fragment pointer %p.\n", frag_start
);
7882 hr
= IDWriteFontFileStream_GetFileSize(stream2
, &size
);
7883 ok(hr
== S_OK
, "Failed to get file size, hr %#x.\n", hr
);
7884 ok(size
== file_size
, "Unexpected file size.\n");
7886 IDWriteFontFileStream_ReleaseFileFragment(stream2
, context2
);
7889 hr
= IDWriteFontFileStream_GetLastWriteTime(stream2
, &writetime
);
7890 ok(hr
== E_NOTIMPL
, "Unexpected hr %#x.\n", hr
);
7891 ok(writetime
== 0, "Unexpected writetime.\n");
7893 IDWriteFontFileStream_Release(stream2
);
7896 hr
= IDWriteInMemoryFontFileLoader_CreateStreamFromKey(inmemory
, NULL
, sizeof(ref_key
) - 1, &stream2
);
7897 ok(hr
== E_INVALIDARG
, "Unexpected hr %#x.\n", hr
);
7900 hr
= IDWriteInMemoryFontFileLoader_CreateStreamFromKey(inmemory
, &ref_key
, sizeof(ref_key
) - 1, &stream2
);
7901 ok(hr
== E_INVALIDARG
, "Unexpected hr %#x.\n", hr
);
7904 hr
= IDWriteInMemoryFontFileLoader_CreateStreamFromKey(inmemory
, &ref_key
, sizeof(ref_key
) + 1, &stream2
);
7905 ok(hr
== E_INVALIDARG
, "Unexpected hr %#x.\n", hr
);
7907 count
= IDWriteInMemoryFontFileLoader_GetFileCount(inmemory
);
7908 ok(count
== 1, "Unexpected file count %u.\n", count
);
7910 hr
= IDWriteFontFile_GetReferenceKey(file
, &key
, &key_size
);
7911 ok(hr
== S_OK
, "Failed to get reference key, hr %#x.\n", hr
);
7913 ok(key
&& *(DWORD
*)key
== 0, "Unexpected reference key.\n");
7914 ok(key_size
== 4, "Unexpected key size %u.\n", key_size
);
7916 IDWriteFontFile_Release(file
);
7918 count
= IDWriteInMemoryFontFileLoader_GetFileCount(inmemory
);
7919 ok(count
== 1, "Unexpected file count %u.\n", count
);
7921 hr
= IDWriteFactory5_UnregisterFontFileLoader(factory
, (IDWriteFontFileLoader
*)inmemory
);
7922 ok(hr
== S_OK
, "Failed to unregister loader, hr %#x.\n", hr
);
7924 IDWriteFontFileStream_ReleaseFileFragment(stream
, context
);
7925 IDWriteFontFileStream_Release(stream
);
7926 IDWriteFontFace_Release(fontface
);
7928 ref
= IDWriteInMemoryFontFileLoader_Release(inmemory
);
7929 ok(ref
== 0, "loader not released, %u.\n", ref
);
7931 ref
= IDWriteFactory5_Release(factory
);
7932 ok(ref
== 0, "factory not released, %u\n", ref
);
7935 static BOOL
face_has_table(IDWriteFontFace4
*fontface
, UINT32 tag
)
7937 BOOL exists
= FALSE
;
7943 hr
= IDWriteFontFace4_TryGetFontTable(fontface
, tag
, &data
, &size
, &context
, &exists
);
7944 ok(hr
== S_OK
, "TryGetFontTable() failed, %#x\n", hr
);
7946 IDWriteFontFace4_ReleaseFontTable(fontface
, context
);
7951 static DWORD
get_sbix_formats(IDWriteFontFace4
*fontface
)
7953 UINT32 size
, s
, num_strikes
;
7954 const sbix_header
*header
;
7955 UINT16 g
, num_glyphs
;
7956 BOOL exists
= FALSE
;
7963 hr
= IDWriteFontFace4_TryGetFontTable(fontface
, MS_MAXP_TAG
, &data
, &size
, &context
, &exists
);
7964 ok(hr
== S_OK
, "TryGetFontTable() failed, %#x\n", hr
);
7965 ok(exists
, "Expected maxp table\n");
7971 num_glyphs
= GET_BE_WORD(maxp
->numGlyphs
);
7973 hr
= IDWriteFontFace4_TryGetFontTable(fontface
, MS_SBIX_TAG
, &data
, &size
, &context
, &exists
);
7974 ok(hr
== S_OK
, "TryGetFontTable() failed, %#x\n", hr
);
7975 ok(exists
, "Expected sbix table\n");
7978 num_strikes
= GET_BE_DWORD(header
->numStrikes
);
7980 for (s
= 0; s
< num_strikes
; s
++) {
7981 sbix_strike
*strike
= (sbix_strike
*)((BYTE
*)header
+ GET_BE_DWORD(header
->strikeOffset
[s
]));
7983 for (g
= 0; g
< num_glyphs
; g
++) {
7984 DWORD offset
= GET_BE_DWORD(strike
->glyphDataOffsets
[g
]);
7985 DWORD offset_next
= GET_BE_DWORD(strike
->glyphDataOffsets
[g
+ 1]);
7986 sbix_glyph_data
*glyph_data
;
7989 if (offset
== offset_next
)
7992 glyph_data
= (sbix_glyph_data
*)((BYTE
*)strike
+ offset
);
7993 switch (format
= glyph_data
->graphicType
)
7996 ret
|= DWRITE_GLYPH_IMAGE_FORMATS_PNG
;
7999 ret
|= DWRITE_GLYPH_IMAGE_FORMATS_JPEG
;
8002 ret
|= DWRITE_GLYPH_IMAGE_FORMATS_TIFF
;
8005 ok(0, "unexpected format, %#x\n", GET_BE_DWORD(format
));
8010 IDWriteFontFace4_ReleaseFontTable(fontface
, context
);
8015 static DWORD
get_cblc_formats(IDWriteFontFace4
*fontface
)
8017 CBLCBitmapSizeTable
*sizes
;
8018 UINT32 num_sizes
, size
, s
;
8019 BOOL exists
= FALSE
;
8025 hr
= IDWriteFontFace4_TryGetFontTable(fontface
, MS_CBLC_TAG
, (const void **)&header
, &size
, &context
, &exists
);
8026 ok(hr
== S_OK
, "TryGetFontTable() failed, %#x\n", hr
);
8027 ok(exists
, "Expected CBLC table\n");
8032 num_sizes
= GET_BE_DWORD(header
->numSizes
);
8033 sizes
= (CBLCBitmapSizeTable
*)(header
+ 1);
8035 for (s
= 0; s
< num_sizes
; s
++) {
8036 BYTE bpp
= sizes
->bitDepth
;
8038 if (bpp
== 1 || bpp
== 2 || bpp
== 4 || bpp
== 8)
8039 ret
|= DWRITE_GLYPH_IMAGE_FORMATS_PNG
;
8041 ret
|= DWRITE_GLYPH_IMAGE_FORMATS_PREMULTIPLIED_B8G8R8A8
;
8044 IDWriteFontFace4_ReleaseFontTable(fontface
, context
);
8049 static DWORD
get_face_glyph_image_formats(IDWriteFontFace4
*fontface
)
8051 DWORD ret
= DWRITE_GLYPH_IMAGE_FORMATS_NONE
;
8053 if (face_has_table(fontface
, MS_GLYF_TAG
))
8054 ret
|= DWRITE_GLYPH_IMAGE_FORMATS_TRUETYPE
;
8056 if (face_has_table(fontface
, MS_CFF__TAG
) ||
8057 face_has_table(fontface
, MS_CFF2_TAG
))
8058 ret
|= DWRITE_GLYPH_IMAGE_FORMATS_CFF
;
8060 if (face_has_table(fontface
, MS_COLR_TAG
))
8061 ret
|= DWRITE_GLYPH_IMAGE_FORMATS_COLR
;
8063 if (face_has_table(fontface
, MS_SVG__TAG
))
8064 ret
|= DWRITE_GLYPH_IMAGE_FORMATS_SVG
;
8066 if (face_has_table(fontface
, MS_SBIX_TAG
))
8067 ret
|= get_sbix_formats(fontface
);
8069 if (face_has_table(fontface
, MS_CBLC_TAG
))
8070 ret
|= get_cblc_formats(fontface
);
8075 static void test_GetGlyphImageFormats(void)
8077 IDWriteFontCollection
*syscollection
;
8078 IDWriteFactory
*factory
;
8082 IDWriteFontFace
*fontface
;
8083 IDWriteFontFace4
*fontface4
;
8085 factory
= create_factory();
8087 fontface
= create_fontface(factory
);
8088 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace4
, (void **)&fontface4
);
8089 IDWriteFontFace_Release(fontface
);
8091 win_skip("GetGlyphImageFormats() is not supported\n");
8092 IDWriteFactory_Release(factory
);
8095 IDWriteFontFace4_Release(fontface4
);
8097 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &syscollection
, FALSE
);
8098 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
8099 count
= IDWriteFontCollection_GetFontFamilyCount(syscollection
);
8101 for (i
= 0; i
< count
; i
++) {
8102 WCHAR familynameW
[256], facenameW
[128];
8103 IDWriteLocalizedStrings
*names
;
8104 IDWriteFontFamily
*family
;
8105 UINT32 j
, fontcount
;
8108 hr
= IDWriteFontCollection_GetFontFamily(syscollection
, i
, &family
);
8109 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
8111 hr
= IDWriteFontFamily_GetFamilyNames(family
, &names
);
8112 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
8114 get_enus_string(names
, familynameW
, sizeof(familynameW
)/sizeof(*familynameW
));
8115 IDWriteLocalizedStrings_Release(names
);
8117 fontcount
= IDWriteFontFamily_GetFontCount(family
);
8118 for (j
= 0; j
< fontcount
; j
++) {
8119 DWORD formats
, expected_formats
;
8121 hr
= IDWriteFontFamily_GetFont(family
, j
, &font
);
8122 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
8124 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
8125 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
8127 hr
= IDWriteFont_GetFaceNames(font
, &names
);
8128 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
8130 get_enus_string(names
, facenameW
, sizeof(facenameW
)/sizeof(*facenameW
));
8132 IDWriteLocalizedStrings_Release(names
);
8134 IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace4
, (void **)&fontface4
);
8136 /* Mask describes font as a whole. */
8137 formats
= IDWriteFontFace4_GetGlyphImageFormats(fontface4
);
8138 expected_formats
= get_face_glyph_image_formats(fontface4
);
8139 ok(formats
== expected_formats
, "%s - %s, expected formats %#x, got formats %#x.\n",
8140 wine_dbgstr_w(familynameW
), wine_dbgstr_w(facenameW
), expected_formats
, formats
);
8142 IDWriteFontFace4_Release(fontface4
);
8143 IDWriteFontFace_Release(fontface
);
8144 IDWriteFont_Release(font
);
8147 IDWriteFontFamily_Release(family
);
8150 IDWriteFontCollection_Release(syscollection
);
8151 ref
= IDWriteFactory_Release(factory
);
8152 ok(ref
== 0, "factory not released, %u\n", ref
);
8155 static void test_CreateCustomRenderingParams(void)
8157 static const struct custom_params_test
8161 FLOAT cleartype_level
;
8162 DWRITE_PIXEL_GEOMETRY geometry
;
8163 DWRITE_RENDERING_MODE rendering_mode
;
8167 { 0.0f
, 0.0f
, 0.0f
, DWRITE_PIXEL_GEOMETRY_FLAT
, DWRITE_RENDERING_MODE_NATURAL
, E_INVALIDARG
},
8168 { 0.0f
, 0.1f
, 0.0f
, DWRITE_PIXEL_GEOMETRY_FLAT
, DWRITE_RENDERING_MODE_NATURAL
, E_INVALIDARG
},
8169 { 0.0f
, 0.0f
, 0.1f
, DWRITE_PIXEL_GEOMETRY_FLAT
, DWRITE_RENDERING_MODE_NATURAL
, E_INVALIDARG
},
8170 { -0.1f
, 0.0f
, 0.0f
, DWRITE_PIXEL_GEOMETRY_FLAT
, DWRITE_RENDERING_MODE_NATURAL
, E_INVALIDARG
},
8171 { 0.1f
, -0.1f
, 0.0f
, DWRITE_PIXEL_GEOMETRY_FLAT
, DWRITE_RENDERING_MODE_NATURAL
, E_INVALIDARG
},
8172 { 0.1f
, 0.0f
, -0.1f
, DWRITE_PIXEL_GEOMETRY_FLAT
, DWRITE_RENDERING_MODE_NATURAL
, E_INVALIDARG
},
8173 { 0.1f
, 0.0f
, 0.0f
, DWRITE_PIXEL_GEOMETRY_FLAT
, DWRITE_RENDERING_MODE_NATURAL
},
8174 { 0.01f
, 0.0f
, 0.0f
, DWRITE_PIXEL_GEOMETRY_FLAT
, DWRITE_RENDERING_MODE_NATURAL
},
8175 { 0.1f
, 0.0f
, 0.0f
, DWRITE_PIXEL_GEOMETRY_BGR
+ 1, DWRITE_RENDERING_MODE_NATURAL
, E_INVALIDARG
},
8176 { 0.1f
, 0.0f
, 0.0f
, DWRITE_PIXEL_GEOMETRY_BGR
, DWRITE_RENDERING_MODE_OUTLINE
+ 1, E_INVALIDARG
},
8177 { 0.1f
, 0.0f
, 2.0f
, DWRITE_PIXEL_GEOMETRY_BGR
, DWRITE_RENDERING_MODE_NATURAL
},
8179 IDWriteFactory
*factory
;
8184 factory
= create_factory();
8186 for (i
= 0; i
< sizeof(params_tests
)/sizeof(*params_tests
); i
++) {
8187 IDWriteRenderingParams
*params
;
8189 params
= (void *)0xdeadbeef;
8190 hr
= IDWriteFactory_CreateCustomRenderingParams(factory
, params_tests
[i
].gamma
, params_tests
[i
].contrast
,
8191 params_tests
[i
].cleartype_level
, params_tests
[i
].geometry
, params_tests
[i
].rendering_mode
, ¶ms
);
8192 ok(hr
== params_tests
[i
].hr
, "%u: unexpected hr %#x, expected %#x.\n", i
, hr
, params_tests
[i
].hr
);
8195 ok(params_tests
[i
].gamma
== IDWriteRenderingParams_GetGamma(params
), "%u: unexpected gamma %f, expected %f.\n",
8196 i
, IDWriteRenderingParams_GetGamma(params
), params_tests
[i
].gamma
);
8197 ok(params_tests
[i
].contrast
== IDWriteRenderingParams_GetEnhancedContrast(params
),
8198 "%u: unexpected contrast %f, expected %f.\n",
8199 i
, IDWriteRenderingParams_GetEnhancedContrast(params
), params_tests
[i
].contrast
);
8200 ok(params_tests
[i
].cleartype_level
== IDWriteRenderingParams_GetClearTypeLevel(params
),
8201 "%u: unexpected ClearType level %f, expected %f.\n",
8202 i
, IDWriteRenderingParams_GetClearTypeLevel(params
), params_tests
[i
].cleartype_level
);
8203 ok(params_tests
[i
].geometry
== IDWriteRenderingParams_GetPixelGeometry(params
),
8204 "%u: unexpected pixel geometry %u, expected %u.\n", i
, IDWriteRenderingParams_GetPixelGeometry(params
),
8205 params_tests
[i
].geometry
);
8206 ok(params_tests
[i
].rendering_mode
== IDWriteRenderingParams_GetRenderingMode(params
),
8207 "%u: unexpected rendering mode %u, expected %u.\n", i
, IDWriteRenderingParams_GetRenderingMode(params
),
8208 params_tests
[i
].rendering_mode
);
8209 IDWriteRenderingParams_Release(params
);
8212 ok(params
== NULL
, "%u: expected NULL interface pointer on failure.\n", i
);
8215 ref
= IDWriteFactory_Release(factory
);
8216 ok(ref
== 0, "factory not released, %u\n", ref
);
8219 static void test_localfontfileloader(void)
8221 IDWriteFontFileLoader
*loader
, *loader2
;
8222 IDWriteFactory
*factory
, *factory2
;
8223 IDWriteFontFile
*file
, *file2
;
8228 factory
= create_factory();
8229 factory2
= create_factory();
8231 path
= create_testfontfile(test_fontfile
);
8233 hr
= IDWriteFactory_CreateFontFileReference(factory
, path
, NULL
, &file
);
8234 ok(hr
== S_OK
, "Failed to create file reference, hr %#x.\n", hr
);
8236 hr
= IDWriteFactory_CreateFontFileReference(factory2
, path
, NULL
, &file2
);
8237 ok(hr
== S_OK
, "Failed to create file reference, hr %#x.\n", hr
);
8238 ok(file
!= file2
, "Unexpected file instance.\n");
8240 hr
= IDWriteFontFile_GetLoader(file
, &loader
);
8241 ok(hr
== S_OK
, "Failed to get loader, hr %#x.\n", hr
);
8243 hr
= IDWriteFontFile_GetLoader(file2
, &loader2
);
8244 ok(hr
== S_OK
, "Failed to get loader, hr %#x.\n", hr
);
8245 ok(loader
== loader2
, "Unexpected loader instance\n");
8247 IDWriteFontFile_Release(file
);
8248 IDWriteFontFile_Release(file2
);
8249 IDWriteFontFileLoader_Release(loader
);
8250 IDWriteFontFileLoader_Release(loader2
);
8251 ref
= IDWriteFactory_Release(factory
);
8252 ok(ref
== 0, "factory not released, %u\n", ref
);
8253 DELETE_FONTFILE(path
);
8256 static void test_AnalyzeContainerType(void)
8258 struct WOFFHeader2 woff2_header
;
8259 struct WOFFHeader woff_header
;
8260 DWRITE_CONTAINER_TYPE type
;
8261 IDWriteFactory5
*factory
;
8263 factory
= create_factory_iid(&IID_IDWriteFactory5
);
8265 win_skip("AnalyzeContainerType() is not supported.\n");
8269 type
= IDWriteFactory5_AnalyzeContainerType(factory
, NULL
, 0);
8270 ok(type
== DWRITE_CONTAINER_TYPE_UNKNOWN
, "Unexpected container type %u.\n", type
);
8272 type
= IDWriteFactory5_AnalyzeContainerType(factory
, (void const *)0xdeadbeef, 0);
8273 ok(type
== DWRITE_CONTAINER_TYPE_UNKNOWN
, "Unexpected container type %u.\n", type
);
8275 memset(&woff_header
, 0xff, sizeof(woff_header
));
8276 woff_header
.signature
= GET_LE_DWORD(MS_WOFF_TAG
);
8277 woff_header
.length
= 0;
8278 type
= IDWriteFactory5_AnalyzeContainerType(factory
, &woff_header
, sizeof(woff_header
));
8279 ok(type
== DWRITE_CONTAINER_TYPE_WOFF
, "Unexpected container type %u.\n", type
);
8281 memset(&woff_header
, 0xff, sizeof(woff_header
));
8282 woff_header
.signature
= GET_LE_DWORD(MS_WOFF_TAG
);
8283 type
= IDWriteFactory5_AnalyzeContainerType(factory
, &woff_header
, sizeof(woff_header
.signature
));
8284 ok(type
== DWRITE_CONTAINER_TYPE_WOFF
, "Unexpected container type %u.\n", type
);
8286 memset(&woff_header
, 0xff, sizeof(woff_header
));
8287 woff_header
.signature
= GET_LE_DWORD(MS_WOFF_TAG
);
8288 type
= IDWriteFactory5_AnalyzeContainerType(factory
, &woff_header
, sizeof(woff_header
.signature
) - 1);
8289 ok(type
== DWRITE_CONTAINER_TYPE_UNKNOWN
, "Unexpected container type %u.\n", type
);
8291 memset(&woff2_header
, 0xff, sizeof(woff2_header
));
8292 woff2_header
.signature
= GET_LE_DWORD(MS_WOF2_TAG
);
8293 type
= IDWriteFactory5_AnalyzeContainerType(factory
, &woff2_header
, sizeof(woff2_header
));
8294 ok(type
== DWRITE_CONTAINER_TYPE_WOFF2
, "Unexpected container type %u.\n", type
);
8296 memset(&woff2_header
, 0xff, sizeof(woff2_header
));
8297 woff2_header
.signature
= GET_LE_DWORD(MS_WOF2_TAG
);
8298 type
= IDWriteFactory5_AnalyzeContainerType(factory
, &woff2_header
, sizeof(woff2_header
.signature
));
8299 ok(type
== DWRITE_CONTAINER_TYPE_WOFF2
, "Unexpected container type %u.\n", type
);
8301 memset(&woff2_header
, 0xff, sizeof(woff2_header
));
8302 woff2_header
.signature
= GET_LE_DWORD(MS_WOF2_TAG
);
8303 type
= IDWriteFactory5_AnalyzeContainerType(factory
, &woff2_header
, sizeof(woff2_header
.signature
) - 1);
8304 ok(type
== DWRITE_CONTAINER_TYPE_UNKNOWN
, "Unexpected container type %u.\n", type
);
8306 IDWriteFactory5_Release(factory
);
8309 static void test_fontsetbuilder(void)
8311 IDWriteFontCollection1
*collection
;
8312 IDWriteFontSetBuilder
*builder
;
8313 IDWriteFactory3
*factory
;
8314 UINT32 count
, i
, ref
;
8317 factory
= create_factory_iid(&IID_IDWriteFactory3
);
8319 skip("IDWriteFontSetBuilder is not supported.\n");
8323 EXPECT_REF(factory
, 1);
8324 hr
= IDWriteFactory3_CreateFontSetBuilder(factory
, &builder
);
8326 ok(hr
== S_OK
, "Failed to create font set builder, hr %#x.\n", hr
);
8329 IDWriteFactory3_Release(factory
);
8333 EXPECT_REF(factory
, 2);
8334 IDWriteFontSetBuilder_Release(builder
);
8336 hr
= IDWriteFactory3_GetSystemFontCollection(factory
, FALSE
, &collection
, FALSE
);
8337 ok(hr
== S_OK
, "Failed to get system collection, hr %#x.\n", hr
);
8338 count
= IDWriteFontCollection1_GetFontFamilyCount(collection
);
8340 for (i
= 0; i
< count
; i
++) {
8341 IDWriteFontFamily1
*family
;
8342 UINT32 j
, fontcount
;
8345 hr
= IDWriteFontCollection1_GetFontFamily(collection
, i
, &family
);
8346 ok(hr
== S_OK
, "Failed to get family, hr %#x.\n", hr
);
8348 fontcount
= IDWriteFontFamily1_GetFontCount(family
);
8349 for (j
= 0; j
< fontcount
; j
++) {
8350 IDWriteFontFaceReference
*ref
, *ref2
;
8351 IDWriteFontSet
*fontset
;
8352 UINT32 setcount
, id
;
8354 hr
= IDWriteFontFamily1_GetFont(family
, j
, &font
);
8355 ok(hr
== S_OK
, "Failed to get font, hr %#x.\n", hr
);
8357 /* Create a set with a single font reference, test set properties. */
8358 hr
= IDWriteFactory3_CreateFontSetBuilder(factory
, &builder
);
8359 ok(hr
== S_OK
, "Failed to create font set builder, hr %#x.\n", hr
);
8361 hr
= IDWriteFont3_GetFontFaceReference(font
, &ref
);
8362 ok(hr
== S_OK
, "Failed to get fontface reference, hr %#x.\n", hr
);
8365 hr
= IDWriteFontSetBuilder_AddFontFaceReference(builder
, ref
);
8366 ok(hr
== S_OK
, "Failed to add fontface reference, hr %#x.\n", hr
);
8369 hr
= IDWriteFontSetBuilder_CreateFontSet(builder
, &fontset
);
8370 ok(hr
== S_OK
, "Failed to create a font set, hr %#x.\n", hr
);
8372 setcount
= IDWriteFontSet_GetFontCount(fontset
);
8373 ok(setcount
== 1, "Unexpected font count %u.\n", setcount
);
8375 hr
= IDWriteFontSet_GetFontFaceReference(fontset
, 0, &ref2
);
8376 ok(hr
== S_OK
, "Failed to get font face reference, hr %#x.\n", hr
);
8377 ok(ref2
!= ref
, "Unexpected reference.\n");
8378 IDWriteFontFaceReference_Release(ref2
);
8380 for (id
= DWRITE_FONT_PROPERTY_ID_FAMILY_NAME
; id
< DWRITE_FONT_PROPERTY_ID_TOTAL
; id
++) {
8381 static const WCHAR fmtW
[] = {'%','u',0};
8382 IDWriteLocalizedStrings
*values
;
8383 WCHAR buffW
[255], buff2W
[255];
8387 hr
= IDWriteFontSet_GetPropertyValues(fontset
, 0, id
, &exists
, &values
);
8388 ok(hr
== S_OK
, "Failed to get property value, hr %#x.\n", hr
);
8395 case DWRITE_FONT_PROPERTY_ID_WEIGHT
:
8396 ivalue
= IDWriteFont3_GetWeight(font
);
8398 case DWRITE_FONT_PROPERTY_ID_STRETCH
:
8399 ivalue
= IDWriteFont3_GetStretch(font
);
8401 case DWRITE_FONT_PROPERTY_ID_STYLE
:
8402 ivalue
= IDWriteFont3_GetStyle(font
);
8410 case DWRITE_FONT_PROPERTY_ID_WEIGHT
:
8411 case DWRITE_FONT_PROPERTY_ID_STRETCH
:
8412 case DWRITE_FONT_PROPERTY_ID_STYLE
:
8413 c
= IDWriteLocalizedStrings_GetCount(values
);
8414 ok(c
== 1, "Unexpected string count %u.\n", c
);
8417 hr
= IDWriteLocalizedStrings_GetLocaleName(values
, 0, buffW
, sizeof(buffW
)/sizeof(buffW
[0]));
8418 ok(hr
== S_OK
, "Failed to get locale name, hr %#x.\n", hr
);
8419 ok(!*buffW
, "Unexpected locale %s.\n", wine_dbgstr_w(buffW
));
8422 hr
= IDWriteLocalizedStrings_GetString(values
, 0, buff2W
, sizeof(buff2W
)/sizeof(buff2W
[0]));
8423 ok(hr
== S_OK
, "Failed to get property string, hr %#x.\n", hr
);
8425 wsprintfW(buffW
, fmtW
, ivalue
);
8426 ok(!lstrcmpW(buffW
, buff2W
), "Unexpected property value %s, expected %s.\n", wine_dbgstr_w(buff2W
),
8427 wine_dbgstr_w(buffW
));
8433 IDWriteLocalizedStrings_Release(values
);
8436 IDWriteFontSet_Release(fontset
);
8437 IDWriteFontFaceReference_Release(ref
);
8438 IDWriteFontSetBuilder_Release(builder
);
8440 IDWriteFont3_Release(font
);
8443 IDWriteFontFamily1_Release(family
);
8446 IDWriteFontCollection1_Release(collection
);
8448 ref
= IDWriteFactory3_Release(factory
);
8449 ok(ref
== 0, "factory not released, %u\n", ref
);
8454 IDWriteFactory
*factory
;
8456 if (!(factory
= create_factory())) {
8457 win_skip("failed to create factory\n");
8461 test_object_lifetime();
8462 test_CreateFontFromLOGFONT();
8463 test_CreateBitmapRenderTarget();
8464 test_GetFontFamily();
8465 test_GetFamilyNames();
8466 test_CreateFontFace();
8468 test_system_fontcollection();
8469 test_ConvertFontFaceToLOGFONT();
8470 test_CustomFontCollection();
8471 test_CreateCustomFontFileReference();
8472 test_CreateFontFileReference();
8473 test_shared_isolated();
8474 test_GetUnicodeRanges();
8475 test_GetFontFromFontFace();
8476 test_GetFirstMatchingFont();
8477 test_GetMatchingFonts();
8478 test_GetInformationalStrings();
8479 test_GetGdiInterop();
8480 test_CreateFontFaceFromHdc();
8481 test_GetSimulations();
8482 test_GetFaceNames();
8483 test_TryGetFontTable();
8484 test_ConvertFontToLOGFONT();
8485 test_CreateStreamFromKey();
8486 test_ReadFileFragment();
8487 test_GetDesignGlyphMetrics();
8488 test_GetDesignGlyphAdvances();
8489 test_IsMonospacedFont();
8490 test_GetGlyphRunOutline();
8491 test_GetEudcFontCollection();
8492 test_GetCaretMetrics();
8493 test_GetGlyphCount();
8494 test_GetKerningPairAdjustments();
8495 test_CreateRenderingParams();
8496 test_CreateGlyphRunAnalysis();
8497 test_GetGdiCompatibleMetrics();
8499 test_GetGdiCompatibleGlyphAdvances();
8500 test_GetRecommendedRenderingMode();
8501 test_GetAlphaBlendParams();
8502 test_CreateAlphaTexture();
8503 test_IsSymbolFont();
8504 test_GetPaletteEntries();
8505 test_TranslateColorGlyphRun();
8506 test_HasCharacter();
8507 test_CreateFontFaceReference();
8508 test_GetFontSignature();
8509 test_font_properties();
8510 test_HasVerticalGlyphVariants();
8511 test_HasKerningPairs();
8512 test_ComputeGlyphOrigins();
8513 test_inmemory_file_loader();
8514 test_GetGlyphImageFormats();
8515 test_CreateCustomRenderingParams();
8516 test_localfontfileloader();
8517 test_AnalyzeContainerType();
8518 test_fontsetbuilder();
8520 IDWriteFactory_Release(factory
);