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/heap.h"
34 #include "wine/test.h"
36 #define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0]))
38 #define MS_CMAP_TAG DWRITE_MAKE_OPENTYPE_TAG('c','m','a','p')
39 #define MS_VDMX_TAG DWRITE_MAKE_OPENTYPE_TAG('V','D','M','X')
40 #define MS_GASP_TAG DWRITE_MAKE_OPENTYPE_TAG('g','a','s','p')
41 #define MS_CPAL_TAG DWRITE_MAKE_OPENTYPE_TAG('C','P','A','L')
42 #define MS_0S2_TAG DWRITE_MAKE_OPENTYPE_TAG('O','S','/','2')
43 #define MS_HEAD_TAG DWRITE_MAKE_OPENTYPE_TAG('h','e','a','d')
44 #define MS_HHEA_TAG DWRITE_MAKE_OPENTYPE_TAG('h','h','e','a')
45 #define MS_POST_TAG DWRITE_MAKE_OPENTYPE_TAG('p','o','s','t')
46 #define MS_GSUB_TAG DWRITE_MAKE_OPENTYPE_TAG('G','S','U','B')
47 #define MS_KERN_TAG DWRITE_MAKE_OPENTYPE_TAG('k','e','r','n')
48 #define MS_GLYF_TAG DWRITE_MAKE_OPENTYPE_TAG('g','l','y','f')
49 #define MS_CFF__TAG DWRITE_MAKE_OPENTYPE_TAG('C','F','F',' ')
50 #define MS_CFF2_TAG DWRITE_MAKE_OPENTYPE_TAG('C','F','F','2')
51 #define MS_COLR_TAG DWRITE_MAKE_OPENTYPE_TAG('C','O','L','R')
52 #define MS_SVG__TAG DWRITE_MAKE_OPENTYPE_TAG('S','V','G',' ')
53 #define MS_SBIX_TAG DWRITE_MAKE_OPENTYPE_TAG('s','b','i','x')
54 #define MS_MAXP_TAG DWRITE_MAKE_OPENTYPE_TAG('m','a','x','p')
55 #define MS_CBLC_TAG DWRITE_MAKE_OPENTYPE_TAG('C','B','L','C')
58 #define MS_PNG__TAG DWRITE_MAKE_OPENTYPE_TAG('p','n','g',' ')
59 #define MS_JPG__TAG DWRITE_MAKE_OPENTYPE_TAG('j','p','g',' ')
60 #define MS_TIFF_TAG DWRITE_MAKE_OPENTYPE_TAG('t','i','f','f')
62 #define MS_WOFF_TAG DWRITE_MAKE_OPENTYPE_TAG('w','O','F','F')
63 #define MS_WOF2_TAG DWRITE_MAKE_OPENTYPE_TAG('w','O','F','2')
65 #ifdef WORDS_BIGENDIAN
66 #define GET_BE_WORD(x) (x)
67 #define GET_BE_DWORD(x) (x)
68 #define GET_LE_WORD(x) RtlUshortByteSwap(x)
69 #define GET_LE_DWORD(x) RtlUlongByteSwap(x)
71 #define GET_BE_WORD(x) RtlUshortByteSwap(x)
72 #define GET_BE_DWORD(x) RtlUlongByteSwap(x)
73 #define GET_LE_WORD(x) (x)
74 #define GET_LE_DWORD(x) (x)
77 #define EXPECT_HR(hr,hr_exp) \
78 ok(hr == hr_exp, "got 0x%08x, expected 0x%08x\n", hr, hr_exp)
80 #define DEFINE_EXPECT(func) \
81 static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
83 #define SET_EXPECT(func) \
84 do { called_ ## func = FALSE; expect_ ## func = TRUE; } while(0)
86 #define CHECK_EXPECT2(func) \
88 ok(expect_ ##func, "unexpected call " #func "\n"); \
89 called_ ## func = TRUE; \
92 #define CHECK_EXPECT(func) \
94 CHECK_EXPECT2(func); \
95 expect_ ## func = FALSE; \
98 #define CHECK_CALLED(func) \
100 ok(called_ ## func, "expected " #func "\n"); \
101 expect_ ## func = called_ ## func = FALSE; \
104 #define CLEAR_CALLED(func) \
105 expect_ ## func = called_ ## func = FALSE
107 DEFINE_EXPECT(setfillmode
);
109 #define EXPECT_REF(obj,ref) _expect_ref((IUnknown*)obj, ref, __LINE__)
110 static void _expect_ref(IUnknown
* obj
, ULONG ref
, int line
)
113 IUnknown_AddRef(obj
);
114 rc
= IUnknown_Release(obj
);
115 ok_(__FILE__
,line
)(rc
== ref
, "expected refcount %d, got %d\n", ref
, rc
);
118 #define EXPECT_REF_BROKEN(obj,ref,brokenref) _expect_ref_broken((IUnknown*)obj, ref, brokenref, __LINE__)
119 static void _expect_ref_broken(IUnknown
* obj
, ULONG ref
, ULONG brokenref
, int line
)
122 IUnknown_AddRef(obj
);
123 rc
= IUnknown_Release(obj
);
124 ok_(__FILE__
,line
)(rc
== ref
|| broken(rc
== brokenref
), "expected refcount %d, got %d\n", ref
, rc
);
127 static const WCHAR test_fontfile
[] = {'w','i','n','e','_','t','e','s','t','_','f','o','n','t','.','t','t','f',0};
128 static const WCHAR tahomaW
[] = {'T','a','h','o','m','a',0};
129 static const WCHAR arialW
[] = {'A','r','i','a','l',0};
130 static const WCHAR tahomaUppercaseW
[] = {'T','A','H','O','M','A',0};
131 static const WCHAR tahomaStrangecaseW
[] = {'t','A','h','O','m','A',0};
132 static const WCHAR blahW
[] = {'B','l','a','h','!',0};
133 static const WCHAR emojiW
[] = {'S','e','g','o','e',' ','U','I',' ','E','m','o','j','i',0};
135 /* PANOSE is 10 bytes in size, need to pack the structure properly */
136 #include "pshpack2.h"
153 USHORT lowestRecPPEM
;
154 SHORT direction_hint
;
156 SHORT glyphdata_format
;
159 enum TT_HEAD_MACSTYLE
161 TT_HEAD_MACSTYLE_BOLD
= 1 << 0,
162 TT_HEAD_MACSTYLE_ITALIC
= 1 << 1,
163 TT_HEAD_MACSTYLE_UNDERLINE
= 1 << 2,
164 TT_HEAD_MACSTYLE_OUTLINE
= 1 << 3,
165 TT_HEAD_MACSTYLE_SHADOW
= 1 << 4,
166 TT_HEAD_MACSTYLE_CONDENSED
= 1 << 5,
167 TT_HEAD_MACSTYLE_EXTENDED
= 1 << 6,
174 USHORT usWeightClass
;
177 SHORT ySubscriptXSize
;
178 SHORT ySubscriptYSize
;
179 SHORT ySubscriptXOffset
;
180 SHORT ySubscriptYOffset
;
181 SHORT ySuperscriptXSize
;
182 SHORT ySuperscriptYSize
;
183 SHORT ySuperscriptXOffset
;
184 SHORT ySuperscriptYOffset
;
185 SHORT yStrikeoutSize
;
186 SHORT yStrikeoutPosition
;
189 ULONG ulUnicodeRange1
;
190 ULONG ulUnicodeRange2
;
191 ULONG ulUnicodeRange3
;
192 ULONG ulUnicodeRange4
;
195 USHORT usFirstCharIndex
;
196 USHORT usLastCharIndex
;
197 /* According to the Apple spec, original version didn't have the below fields,
198 * version numbers were taken from the OpenType spec.
200 /* version 0 (TrueType 1.5) */
201 USHORT sTypoAscender
;
202 USHORT sTypoDescender
;
206 /* version 1 (TrueType 1.66) */
207 ULONG ulCodePageRange1
;
208 ULONG ulCodePageRange2
;
209 /* version 2 (OpenType 1.2) */
212 USHORT usDefaultChar
;
217 enum OS2_FSSELECTION
{
218 OS2_FSSELECTION_ITALIC
= 1 << 0,
219 OS2_FSSELECTION_UNDERSCORE
= 1 << 1,
220 OS2_FSSELECTION_NEGATIVE
= 1 << 2,
221 OS2_FSSELECTION_OUTLINED
= 1 << 3,
222 OS2_FSSELECTION_STRIKEOUT
= 1 << 4,
223 OS2_FSSELECTION_BOLD
= 1 << 5,
224 OS2_FSSELECTION_REGULAR
= 1 << 6,
225 OS2_FSSELECTION_USE_TYPO_METRICS
= 1 << 7,
226 OS2_FSSELECTION_WWS
= 1 << 8,
227 OS2_FSSELECTION_OBLIQUE
= 1 << 9
233 SHORT underlinePosition
;
234 SHORT underlineThickness
;
248 USHORT advanceWidthMax
;
249 SHORT minLeftSideBearing
;
250 SHORT minRightSideBearing
;
252 SHORT caretSlopeRise
;
256 SHORT metricDataFormat
;
257 USHORT numberOfHMetrics
;
274 OT_FeatureRecord FeatureRecord
[1];
280 WORD LookupListIndex
[1];
299 } GSUB_SingleSubstFormat1
;
306 } GSUB_SingleSubstFormat2
;
310 WORD ExtensionLookupType
;
311 DWORD ExtensionOffset
;
312 } GSUB_ExtensionPosFormat1
;
318 DWORD strikeOffset
[1];
324 DWORD glyphDataOffsets
[1];
345 DWORD indexSubTableArrayOffset
;
346 DWORD indexTablesSize
;
347 DWORD numberofIndexSubTables
;
349 sbitLineMetrics hori
;
350 sbitLineMetrics vert
;
351 WORD startGlyphIndex
;
357 } CBLCBitmapSizeTable
;
376 ULONG metaOrigLength
;
389 ULONG totalCompressedSize
;
394 ULONG metaOrigLength
;
401 static void *create_factory_iid(REFIID riid
)
403 IUnknown
*factory
= NULL
;
404 DWriteCreateFactory(DWRITE_FACTORY_TYPE_ISOLATED
, riid
, &factory
);
408 static IDWriteFactory
*create_factory(void)
410 IDWriteFactory
*factory
= create_factory_iid(&IID_IDWriteFactory
);
411 ok(factory
!= NULL
, "Failed to create factory.\n");
415 static IDWriteFontFace
*create_fontface(IDWriteFactory
*factory
)
417 static const WCHAR tahomaW
[] = {'T','a','h','o','m','a',0};
418 IDWriteGdiInterop
*interop
;
419 IDWriteFontFace
*fontface
;
424 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop
);
425 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
427 memset(&logfont
, 0, sizeof(logfont
));
428 logfont
.lfHeight
= 12;
429 logfont
.lfWidth
= 12;
430 logfont
.lfWeight
= FW_NORMAL
;
431 logfont
.lfItalic
= 1;
432 lstrcpyW(logfont
.lfFaceName
, tahomaW
);
434 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font
);
435 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
437 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
438 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
440 IDWriteFont_Release(font
);
441 IDWriteGdiInterop_Release(interop
);
446 static IDWriteFont
*get_font(IDWriteFactory
*factory
, const WCHAR
*name
, DWRITE_FONT_STYLE style
)
448 IDWriteFontCollection
*collection
;
449 IDWriteFontFamily
*family
;
450 IDWriteFont
*font
= NULL
;
455 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &collection
, FALSE
);
456 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
460 hr
= IDWriteFontCollection_FindFamilyName(collection
, name
, &index
, &exists
);
461 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
462 if (!exists
) goto not_found
;
464 hr
= IDWriteFontCollection_GetFontFamily(collection
, index
, &family
);
465 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
467 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
,
468 DWRITE_FONT_STRETCH_NORMAL
, style
, &font
);
469 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
471 IDWriteFontFamily_Release(family
);
473 IDWriteFontCollection_Release(collection
);
477 static IDWriteFont
*get_tahoma_instance(IDWriteFactory
*factory
, DWRITE_FONT_STYLE style
)
479 IDWriteFont
*font
= get_font(factory
, tahomaW
, style
);
480 ok(font
!= NULL
, "failed to get Tahoma\n");
484 static WCHAR
*create_testfontfile(const WCHAR
*filename
)
486 static WCHAR pathW
[MAX_PATH
];
492 GetTempPathW(ARRAY_SIZE(pathW
), pathW
);
493 lstrcatW(pathW
, filename
);
495 file
= CreateFileW(pathW
, GENERIC_READ
|GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, 0);
496 ok(file
!= INVALID_HANDLE_VALUE
, "file creation failed, at %s, error %d\n", wine_dbgstr_w(pathW
),
499 res
= FindResourceA(GetModuleHandleA(NULL
), (LPCSTR
)MAKEINTRESOURCE(1), (LPCSTR
)RT_RCDATA
);
500 ok( res
!= 0, "couldn't find resource\n" );
501 ptr
= LockResource( LoadResource( GetModuleHandleA(NULL
), res
));
502 WriteFile( file
, ptr
, SizeofResource( GetModuleHandleA(NULL
), res
), &written
, NULL
);
503 ok( written
== SizeofResource( GetModuleHandleA(NULL
), res
), "couldn't write resource\n" );
509 #define DELETE_FONTFILE(filename) _delete_testfontfile(filename, __LINE__)
510 static void _delete_testfontfile(const WCHAR
*filename
, int line
)
512 BOOL ret
= DeleteFileW(filename
);
513 ok_(__FILE__
,line
)(ret
, "failed to delete file %s, error %d\n", wine_dbgstr_w(filename
), GetLastError());
516 struct test_fontenumerator
518 IDWriteFontFileEnumerator IDWriteFontFileEnumerator_iface
;
522 IDWriteFontFile
*font_file
;
525 static inline struct test_fontenumerator
*impl_from_IDWriteFontFileEnumerator(IDWriteFontFileEnumerator
* iface
)
527 return CONTAINING_RECORD(iface
, struct test_fontenumerator
, IDWriteFontFileEnumerator_iface
);
530 static HRESULT WINAPI
singlefontfileenumerator_QueryInterface(IDWriteFontFileEnumerator
*iface
, REFIID riid
, void **obj
)
532 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFontFileEnumerator
))
535 IDWriteFontFileEnumerator_AddRef(iface
);
538 return E_NOINTERFACE
;
541 static ULONG WINAPI
singlefontfileenumerator_AddRef(IDWriteFontFileEnumerator
*iface
)
543 struct test_fontenumerator
*This
= impl_from_IDWriteFontFileEnumerator(iface
);
544 return InterlockedIncrement(&This
->ref
);
547 static ULONG WINAPI
singlefontfileenumerator_Release(IDWriteFontFileEnumerator
*iface
)
549 struct test_fontenumerator
*This
= impl_from_IDWriteFontFileEnumerator(iface
);
550 ULONG ref
= InterlockedDecrement(&This
->ref
);
552 IDWriteFontFile_Release(This
->font_file
);
558 static HRESULT WINAPI
singlefontfileenumerator_GetCurrentFontFile(IDWriteFontFileEnumerator
*iface
, IDWriteFontFile
**font_file
)
560 struct test_fontenumerator
*This
= impl_from_IDWriteFontFileEnumerator(iface
);
561 IDWriteFontFile_AddRef(This
->font_file
);
562 *font_file
= This
->font_file
;
566 static HRESULT WINAPI
singlefontfileenumerator_MoveNext(IDWriteFontFileEnumerator
*iface
, BOOL
*current
)
568 struct test_fontenumerator
*This
= impl_from_IDWriteFontFileEnumerator(iface
);
570 if (This
->index
> 1) {
580 static const struct IDWriteFontFileEnumeratorVtbl singlefontfileenumeratorvtbl
=
582 singlefontfileenumerator_QueryInterface
,
583 singlefontfileenumerator_AddRef
,
584 singlefontfileenumerator_Release
,
585 singlefontfileenumerator_MoveNext
,
586 singlefontfileenumerator_GetCurrentFontFile
589 static HRESULT
create_enumerator(IDWriteFontFile
*font_file
, IDWriteFontFileEnumerator
**ret
)
591 struct test_fontenumerator
*enumerator
;
593 enumerator
= heap_alloc(sizeof(struct test_fontenumerator
));
595 return E_OUTOFMEMORY
;
597 enumerator
->IDWriteFontFileEnumerator_iface
.lpVtbl
= &singlefontfileenumeratorvtbl
;
599 enumerator
->index
= 0;
600 enumerator
->font_file
= font_file
;
601 IDWriteFontFile_AddRef(font_file
);
603 *ret
= &enumerator
->IDWriteFontFileEnumerator_iface
;
607 struct test_fontcollectionloader
609 IDWriteFontCollectionLoader IDWriteFontFileCollectionLoader_iface
;
610 IDWriteFontFileLoader
*loader
;
613 static inline struct test_fontcollectionloader
*impl_from_IDWriteFontFileCollectionLoader(IDWriteFontCollectionLoader
* iface
)
615 return CONTAINING_RECORD(iface
, struct test_fontcollectionloader
, IDWriteFontFileCollectionLoader_iface
);
618 static HRESULT WINAPI
resourcecollectionloader_QueryInterface(IDWriteFontCollectionLoader
*iface
, REFIID riid
, void **obj
)
620 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFontCollectionLoader
))
623 IDWriteFontCollectionLoader_AddRef(iface
);
626 return E_NOINTERFACE
;
629 static ULONG WINAPI
resourcecollectionloader_AddRef(IDWriteFontCollectionLoader
*iface
)
634 static ULONG WINAPI
resourcecollectionloader_Release(IDWriteFontCollectionLoader
*iface
)
639 static HRESULT WINAPI
resourcecollectionloader_CreateEnumeratorFromKey(IDWriteFontCollectionLoader
*iface
, IDWriteFactory
*factory
,
640 const void * collectionKey
, UINT32 collectionKeySize
, IDWriteFontFileEnumerator
** fontFileEnumerator
)
642 struct test_fontcollectionloader
*This
= impl_from_IDWriteFontFileCollectionLoader(iface
);
643 IDWriteFontFile
*font_file
;
646 hr
= IDWriteFactory_CreateCustomFontFileReference(factory
, collectionKey
, collectionKeySize
, This
->loader
, &font_file
);
647 ok(hr
== S_OK
, "Failed to create custom file reference, hr %#x.\n", hr
);
649 hr
= create_enumerator(font_file
, fontFileEnumerator
);
650 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
652 IDWriteFontFile_Release(font_file
);
656 static const struct IDWriteFontCollectionLoaderVtbl resourcecollectionloadervtbl
= {
657 resourcecollectionloader_QueryInterface
,
658 resourcecollectionloader_AddRef
,
659 resourcecollectionloader_Release
,
660 resourcecollectionloader_CreateEnumeratorFromKey
663 /* Here is a functional custom font set of interfaces */
664 struct test_fontdatastream
666 IDWriteFontFileStream IDWriteFontFileStream_iface
;
673 static inline struct test_fontdatastream
*impl_from_IDWriteFontFileStream(IDWriteFontFileStream
* iface
)
675 return CONTAINING_RECORD(iface
, struct test_fontdatastream
, IDWriteFontFileStream_iface
);
678 static HRESULT WINAPI
fontdatastream_QueryInterface(IDWriteFontFileStream
*iface
, REFIID riid
, void **obj
)
680 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFontFileStream
))
683 IDWriteFontFileStream_AddRef(iface
);
687 return E_NOINTERFACE
;
690 static ULONG WINAPI
fontdatastream_AddRef(IDWriteFontFileStream
*iface
)
692 struct test_fontdatastream
*This
= impl_from_IDWriteFontFileStream(iface
);
693 ULONG ref
= InterlockedIncrement(&This
->ref
);
697 static ULONG WINAPI
fontdatastream_Release(IDWriteFontFileStream
*iface
)
699 struct test_fontdatastream
*This
= impl_from_IDWriteFontFileStream(iface
);
700 ULONG ref
= InterlockedDecrement(&This
->ref
);
702 HeapFree(GetProcessHeap(), 0, This
);
706 static HRESULT WINAPI
fontdatastream_ReadFileFragment(IDWriteFontFileStream
*iface
, void const **fragment_start
, UINT64 offset
, UINT64 fragment_size
, void **fragment_context
)
708 struct test_fontdatastream
*This
= impl_from_IDWriteFontFileStream(iface
);
709 *fragment_context
= NULL
;
710 if (offset
+fragment_size
> This
->size
)
712 *fragment_start
= NULL
;
717 *fragment_start
= (BYTE
*)This
->data
+ offset
;
722 static void WINAPI
fontdatastream_ReleaseFileFragment(IDWriteFontFileStream
*iface
, void *fragment_context
)
727 static HRESULT WINAPI
fontdatastream_GetFileSize(IDWriteFontFileStream
*iface
, UINT64
*size
)
729 struct test_fontdatastream
*This
= impl_from_IDWriteFontFileStream(iface
);
734 static HRESULT WINAPI
fontdatastream_GetLastWriteTime(IDWriteFontFileStream
*iface
, UINT64
*last_writetime
)
739 static const IDWriteFontFileStreamVtbl fontdatastreamvtbl
=
741 fontdatastream_QueryInterface
,
742 fontdatastream_AddRef
,
743 fontdatastream_Release
,
744 fontdatastream_ReadFileFragment
,
745 fontdatastream_ReleaseFileFragment
,
746 fontdatastream_GetFileSize
,
747 fontdatastream_GetLastWriteTime
750 static HRESULT
create_fontdatastream(LPVOID data
, UINT size
, IDWriteFontFileStream
** iface
)
752 struct test_fontdatastream
*This
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct test_fontdatastream
));
754 return E_OUTOFMEMORY
;
759 This
->IDWriteFontFileStream_iface
.lpVtbl
= &fontdatastreamvtbl
;
761 *iface
= &This
->IDWriteFontFileStream_iface
;
765 static HRESULT WINAPI
resourcefontfileloader_QueryInterface(IDWriteFontFileLoader
*iface
, REFIID riid
, void **obj
)
767 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFontFileLoader
))
773 return E_NOINTERFACE
;
776 static ULONG WINAPI
resourcefontfileloader_AddRef(IDWriteFontFileLoader
*iface
)
781 static ULONG WINAPI
resourcefontfileloader_Release(IDWriteFontFileLoader
*iface
)
786 static HRESULT WINAPI
resourcefontfileloader_CreateStreamFromKey(IDWriteFontFileLoader
*iface
, const void *ref_key
, UINT32 key_size
,
787 IDWriteFontFileStream
**stream
)
793 mem
= LoadResource(GetModuleHandleA(NULL
), *(HRSRC
*)ref_key
);
794 ok(mem
!= NULL
, "Failed to lock font resource\n");
797 size
= SizeofResource(GetModuleHandleA(NULL
), *(HRSRC
*)ref_key
);
798 data
= LockResource(mem
);
799 return create_fontdatastream(data
, size
, stream
);
804 static const struct IDWriteFontFileLoaderVtbl resourcefontfileloadervtbl
= {
805 resourcefontfileloader_QueryInterface
,
806 resourcefontfileloader_AddRef
,
807 resourcefontfileloader_Release
,
808 resourcefontfileloader_CreateStreamFromKey
811 static IDWriteFontFileLoader rloader
= { &resourcefontfileloadervtbl
};
813 static D2D1_POINT_2F g_startpoints
[2];
814 static int g_startpoint_count
;
816 static HRESULT WINAPI
test_geometrysink_QueryInterface(ID2D1SimplifiedGeometrySink
*iface
, REFIID riid
, void **ret
)
818 if (IsEqualIID(riid
, &IID_ID2D1SimplifiedGeometrySink
) ||
819 IsEqualIID(riid
, &IID_IUnknown
))
822 ID2D1SimplifiedGeometrySink_AddRef(iface
);
827 return E_NOINTERFACE
;
830 static ULONG WINAPI
test_geometrysink_AddRef(ID2D1SimplifiedGeometrySink
*iface
)
835 static ULONG WINAPI
test_geometrysink_Release(ID2D1SimplifiedGeometrySink
*iface
)
840 static void WINAPI
test_geometrysink_SetFillMode(ID2D1SimplifiedGeometrySink
*iface
, D2D1_FILL_MODE mode
)
842 CHECK_EXPECT(setfillmode
);
843 ok(mode
== D2D1_FILL_MODE_WINDING
, "fill mode %d\n", mode
);
846 static void WINAPI
test_geometrysink_SetSegmentFlags(ID2D1SimplifiedGeometrySink
*iface
, D2D1_PATH_SEGMENT flags
)
848 ok(0, "unexpected SetSegmentFlags() - flags %d\n", flags
);
851 static void WINAPI
test_geometrysink_BeginFigure(ID2D1SimplifiedGeometrySink
*iface
,
852 D2D1_POINT_2F startPoint
, D2D1_FIGURE_BEGIN figureBegin
)
854 ok(figureBegin
== D2D1_FIGURE_BEGIN_FILLED
, "begin figure %d\n", figureBegin
);
855 if (g_startpoint_count
< ARRAY_SIZE(g_startpoints
))
856 g_startpoints
[g_startpoint_count
] = startPoint
;
857 g_startpoint_count
++;
860 static void WINAPI
test_geometrysink_AddLines(ID2D1SimplifiedGeometrySink
*iface
,
861 const D2D1_POINT_2F
*points
, UINT32 count
)
865 static void WINAPI
test_geometrysink_AddBeziers(ID2D1SimplifiedGeometrySink
*iface
,
866 const D2D1_BEZIER_SEGMENT
*beziers
, UINT32 count
)
870 static void WINAPI
test_geometrysink_EndFigure(ID2D1SimplifiedGeometrySink
*iface
, D2D1_FIGURE_END figureEnd
)
872 ok(figureEnd
== D2D1_FIGURE_END_CLOSED
, "end figure %d\n", figureEnd
);
875 static HRESULT WINAPI
test_geometrysink_Close(ID2D1SimplifiedGeometrySink
*iface
)
877 ok(0, "unexpected Close()\n");
881 static const ID2D1SimplifiedGeometrySinkVtbl test_geometrysink_vtbl
= {
882 test_geometrysink_QueryInterface
,
883 test_geometrysink_AddRef
,
884 test_geometrysink_Release
,
885 test_geometrysink_SetFillMode
,
886 test_geometrysink_SetSegmentFlags
,
887 test_geometrysink_BeginFigure
,
888 test_geometrysink_AddLines
,
889 test_geometrysink_AddBeziers
,
890 test_geometrysink_EndFigure
,
891 test_geometrysink_Close
894 static void WINAPI
test_geometrysink2_BeginFigure(ID2D1SimplifiedGeometrySink
*iface
,
895 D2D1_POINT_2F startPoint
, D2D1_FIGURE_BEGIN figureBegin
)
897 ok(0, "unexpected call\n");
900 static void WINAPI
test_geometrysink2_AddLines(ID2D1SimplifiedGeometrySink
*iface
,
901 const D2D1_POINT_2F
*points
, UINT32 count
)
903 ok(0, "unexpected call\n");
906 static void WINAPI
test_geometrysink2_AddBeziers(ID2D1SimplifiedGeometrySink
*iface
,
907 const D2D1_BEZIER_SEGMENT
*beziers
, UINT32 count
)
909 ok(0, "unexpected call\n");
912 static void WINAPI
test_geometrysink2_EndFigure(ID2D1SimplifiedGeometrySink
*iface
, D2D1_FIGURE_END figureEnd
)
914 ok(0, "unexpected call\n");
917 static const ID2D1SimplifiedGeometrySinkVtbl test_geometrysink2_vtbl
= {
918 test_geometrysink_QueryInterface
,
919 test_geometrysink_AddRef
,
920 test_geometrysink_Release
,
921 test_geometrysink_SetFillMode
,
922 test_geometrysink_SetSegmentFlags
,
923 test_geometrysink2_BeginFigure
,
924 test_geometrysink2_AddLines
,
925 test_geometrysink2_AddBeziers
,
926 test_geometrysink2_EndFigure
,
927 test_geometrysink_Close
930 static ID2D1SimplifiedGeometrySink test_geomsink
= { &test_geometrysink_vtbl
};
931 static ID2D1SimplifiedGeometrySink test_geomsink2
= { &test_geometrysink2_vtbl
};
933 static void test_CreateFontFromLOGFONT(void)
935 static const WCHAR tahomaspW
[] = {'T','a','h','o','m','a',' ',0};
936 IDWriteGdiInterop1
*interop1
;
937 IDWriteGdiInterop
*interop
;
938 DWRITE_FONT_WEIGHT weight
;
939 DWRITE_FONT_STYLE style
;
942 LONG weights
[][2] = {
943 {FW_NORMAL
, DWRITE_FONT_WEIGHT_NORMAL
},
944 {FW_BOLD
, DWRITE_FONT_WEIGHT_BOLD
},
945 { 0, DWRITE_FONT_WEIGHT_NORMAL
},
946 { 50, DWRITE_FONT_WEIGHT_NORMAL
},
947 {150, DWRITE_FONT_WEIGHT_NORMAL
},
948 {250, DWRITE_FONT_WEIGHT_NORMAL
},
949 {350, DWRITE_FONT_WEIGHT_NORMAL
},
950 {450, DWRITE_FONT_WEIGHT_NORMAL
},
951 {650, DWRITE_FONT_WEIGHT_BOLD
},
952 {750, DWRITE_FONT_WEIGHT_BOLD
},
953 {850, DWRITE_FONT_WEIGHT_BOLD
},
954 {950, DWRITE_FONT_WEIGHT_BOLD
},
955 {960, DWRITE_FONT_WEIGHT_BOLD
},
957 OUTLINETEXTMETRICW otm
;
958 IDWriteFactory
*factory
;
968 factory
= create_factory();
970 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop
);
971 ok(hr
== S_OK
, "got %#x\n", hr
);
974 /* null out parameter crashes this call */
975 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, NULL
, NULL
);
977 font
= (void*)0xdeadbeef;
978 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, NULL
, &font
);
979 EXPECT_HR(hr
, E_INVALIDARG
);
980 ok(font
== NULL
, "got %p\n", font
);
982 memset(&logfont
, 0, sizeof(logfont
));
983 logfont
.lfHeight
= 12;
984 logfont
.lfWidth
= 12;
985 logfont
.lfWeight
= FW_NORMAL
;
986 logfont
.lfItalic
= 1;
987 lstrcpyW(logfont
.lfFaceName
, tahomaW
);
989 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font
);
992 hfont
= CreateFontIndirectW(&logfont
);
993 hdc
= CreateCompatibleDC(0);
994 SelectObject(hdc
, hfont
);
996 otm
.otmSize
= sizeof(otm
);
997 r
= GetOutlineTextMetricsW(hdc
, otm
.otmSize
, &otm
);
998 ok(r
, "got %d\n", r
);
1000 DeleteObject(hfont
);
1003 hr
= IDWriteFont_HasCharacter(font
, 0xd800, &exists
);
1004 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1005 ok(exists
== FALSE
, "got %d\n", exists
);
1008 hr
= IDWriteFont_HasCharacter(font
, 0x20, &exists
);
1009 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1010 ok(exists
== TRUE
, "got %d\n", exists
);
1012 /* now check properties */
1013 weight
= IDWriteFont_GetWeight(font
);
1014 ok(weight
== DWRITE_FONT_WEIGHT_NORMAL
, "got %d\n", weight
);
1016 style
= IDWriteFont_GetStyle(font
);
1017 ok(style
== DWRITE_FONT_STYLE_OBLIQUE
, "got %d\n", style
);
1018 ok(otm
.otmfsSelection
& 1, "got 0x%08x\n", otm
.otmfsSelection
);
1020 ret
= IDWriteFont_IsSymbolFont(font
);
1021 ok(!ret
, "got %d\n", ret
);
1023 IDWriteFont_Release(font
);
1026 for (i
= 0; i
< ARRAY_SIZE(weights
); i
++)
1028 memset(&logfont
, 0, sizeof(logfont
));
1029 logfont
.lfHeight
= 12;
1030 logfont
.lfWidth
= 12;
1031 logfont
.lfWeight
= weights
[i
][0];
1032 lstrcpyW(logfont
.lfFaceName
, tahomaW
);
1034 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font
);
1035 EXPECT_HR(hr
, S_OK
);
1037 weight
= IDWriteFont_GetWeight(font
);
1038 ok(weight
== weights
[i
][1],
1039 "%d: got %d, expected %d\n", i
, weight
, weights
[i
][1]);
1041 IDWriteFont_Release(font
);
1044 /* weight not from enum */
1045 memset(&logfont
, 0, sizeof(logfont
));
1046 logfont
.lfHeight
= 12;
1047 logfont
.lfWidth
= 12;
1048 logfont
.lfWeight
= 550;
1049 lstrcpyW(logfont
.lfFaceName
, tahomaW
);
1052 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font
);
1053 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1055 weight
= IDWriteFont_GetWeight(font
);
1056 ok(weight
== DWRITE_FONT_WEIGHT_NORMAL
|| weight
== DWRITE_FONT_WEIGHT_BOLD
,
1057 "got %d\n", weight
);
1059 IDWriteFont_Release(font
);
1061 /* empty or nonexistent face name */
1062 memset(&logfont
, 0, sizeof(logfont
));
1063 logfont
.lfHeight
= 12;
1064 logfont
.lfWidth
= 12;
1065 logfont
.lfWeight
= FW_NORMAL
;
1066 lstrcpyW(logfont
.lfFaceName
, blahW
);
1068 font
= (void*)0xdeadbeef;
1069 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font
);
1070 ok(hr
== DWRITE_E_NOFONT
, "got 0x%08x\n", hr
);
1071 ok(font
== NULL
, "got %p\n", font
);
1073 /* Try with name 'Tahoma ' */
1074 memset(&logfont
, 0, sizeof(logfont
));
1075 logfont
.lfHeight
= 12;
1076 logfont
.lfWidth
= 12;
1077 logfont
.lfWeight
= FW_NORMAL
;
1078 lstrcpyW(logfont
.lfFaceName
, tahomaspW
);
1080 font
= (void*)0xdeadbeef;
1081 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font
);
1082 ok(hr
== DWRITE_E_NOFONT
, "got 0x%08x\n", hr
);
1083 ok(font
== NULL
, "got %p\n", font
);
1085 /* empty string as a facename */
1086 memset(&logfont
, 0, sizeof(logfont
));
1087 logfont
.lfHeight
= 12;
1088 logfont
.lfWidth
= 12;
1089 logfont
.lfWeight
= FW_NORMAL
;
1091 font
= (void*)0xdeadbeef;
1092 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font
);
1093 ok(hr
== DWRITE_E_NOFONT
, "got 0x%08x\n", hr
);
1094 ok(font
== NULL
, "got %p\n", font
);
1096 /* IDWriteGdiInterop1::CreateFontFromLOGFONT() */
1097 hr
= IDWriteGdiInterop_QueryInterface(interop
, &IID_IDWriteGdiInterop1
, (void**)&interop1
);
1099 memset(&logfont
, 0, sizeof(logfont
));
1100 logfont
.lfHeight
= 12;
1101 logfont
.lfWidth
= 12;
1102 logfont
.lfWeight
= FW_NORMAL
;
1103 logfont
.lfItalic
= 1;
1104 lstrcpyW(logfont
.lfFaceName
, tahomaW
);
1106 hr
= IDWriteGdiInterop1_CreateFontFromLOGFONT(interop1
, &logfont
, NULL
, &font
);
1107 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1109 IDWriteFont_Release(font
);
1110 IDWriteGdiInterop1_Release(interop1
);
1113 win_skip("IDWriteGdiInterop1 is not supported, skipping CreateFontFromLOGFONT() tests.\n");
1115 ref
= IDWriteGdiInterop_Release(interop
);
1116 ok(ref
== 0, "interop is not released, %u\n", ref
);
1117 ref
= IDWriteFactory_Release(factory
);
1118 ok(ref
== 0, "factory is not released, %u\n", ref
);
1121 static void test_CreateBitmapRenderTarget(void)
1123 IDWriteBitmapRenderTarget
*target
, *target2
;
1124 IDWriteBitmapRenderTarget1
*target1
;
1125 IDWriteRenderingParams
*params
;
1126 IDWriteGdiInterop
*interop
;
1127 IDWriteFontFace
*fontface
;
1128 IDWriteFactory
*factory
;
1129 DWRITE_GLYPH_RUN run
;
1144 factory
= create_factory();
1146 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop
);
1147 EXPECT_HR(hr
, S_OK
);
1150 hr
= IDWriteGdiInterop_CreateBitmapRenderTarget(interop
, NULL
, 0, 0, &target
);
1151 EXPECT_HR(hr
, S_OK
);
1153 if (0) /* crashes on native */
1154 hr
= IDWriteBitmapRenderTarget_GetSize(target
, NULL
);
1156 size
.cx
= size
.cy
= -1;
1157 hr
= IDWriteBitmapRenderTarget_GetSize(target
, &size
);
1158 EXPECT_HR(hr
, S_OK
);
1159 ok(size
.cx
== 0, "got %d\n", size
.cx
);
1160 ok(size
.cy
== 0, "got %d\n", size
.cy
);
1163 hr
= IDWriteGdiInterop_CreateBitmapRenderTarget(interop
, NULL
, 0, 0, &target2
);
1164 EXPECT_HR(hr
, S_OK
);
1165 ok(target
!= target2
, "got %p, %p\n", target2
, target
);
1166 IDWriteBitmapRenderTarget_Release(target2
);
1168 hdc
= IDWriteBitmapRenderTarget_GetMemoryDC(target
);
1169 ok(hdc
!= NULL
, "got %p\n", hdc
);
1172 ret
= GetGraphicsMode(hdc
);
1173 ok(ret
== GM_ADVANCED
, "got %d\n", ret
);
1175 hbm
= GetCurrentObject(hdc
, OBJ_BITMAP
);
1176 ok(hbm
!= NULL
, "got %p\n", hbm
);
1178 /* check DIB properties */
1179 ret
= GetObjectW(hbm
, sizeof(ds
), &ds
);
1180 ok(ret
== sizeof(BITMAP
), "got %d\n", ret
);
1181 ok(ds
.dsBm
.bmWidth
== 1, "got %d\n", ds
.dsBm
.bmWidth
);
1182 ok(ds
.dsBm
.bmHeight
== 1, "got %d\n", ds
.dsBm
.bmHeight
);
1183 ok(ds
.dsBm
.bmPlanes
== 1, "got %d\n", ds
.dsBm
.bmPlanes
);
1184 ok(ds
.dsBm
.bmBitsPixel
== 1, "got %d\n", ds
.dsBm
.bmBitsPixel
);
1185 ok(!ds
.dsBm
.bmBits
, "got %p\n", ds
.dsBm
.bmBits
);
1187 IDWriteBitmapRenderTarget_Release(target
);
1189 hbm
= GetCurrentObject(hdc
, OBJ_BITMAP
);
1190 ok(!hbm
, "got %p\n", hbm
);
1193 hr
= IDWriteGdiInterop_CreateBitmapRenderTarget(interop
, NULL
, 10, 5, &target
);
1194 EXPECT_HR(hr
, S_OK
);
1196 hdc
= IDWriteBitmapRenderTarget_GetMemoryDC(target
);
1197 ok(hdc
!= NULL
, "got %p\n", hdc
);
1199 /* test context settings */
1200 c
= GetTextColor(hdc
);
1201 ok(c
== RGB(0, 0, 0), "got 0x%08x\n", c
);
1202 ret
= GetBkMode(hdc
);
1203 ok(ret
== OPAQUE
, "got %d\n", ret
);
1204 c
= GetBkColor(hdc
);
1205 ok(c
== RGB(255, 255, 255), "got 0x%08x\n", c
);
1207 hbm
= GetCurrentObject(hdc
, OBJ_BITMAP
);
1208 ok(hbm
!= NULL
, "got %p\n", hbm
);
1210 /* check DIB properties */
1211 ret
= GetObjectW(hbm
, sizeof(ds
), &ds
);
1212 ok(ret
== sizeof(ds
), "got %d\n", ret
);
1213 ok(ds
.dsBm
.bmWidth
== 10, "got %d\n", ds
.dsBm
.bmWidth
);
1214 ok(ds
.dsBm
.bmHeight
== 5, "got %d\n", ds
.dsBm
.bmHeight
);
1215 ok(ds
.dsBm
.bmPlanes
== 1, "got %d\n", ds
.dsBm
.bmPlanes
);
1216 ok(ds
.dsBm
.bmBitsPixel
== 32, "got %d\n", ds
.dsBm
.bmBitsPixel
);
1217 ok(ds
.dsBm
.bmBits
!= NULL
, "got %p\n", ds
.dsBm
.bmBits
);
1219 size
.cx
= size
.cy
= -1;
1220 hr
= IDWriteBitmapRenderTarget_GetSize(target
, &size
);
1221 EXPECT_HR(hr
, S_OK
);
1222 ok(size
.cx
== 10, "got %d\n", size
.cx
);
1223 ok(size
.cy
== 5, "got %d\n", size
.cy
);
1225 /* resize to same size */
1226 hr
= IDWriteBitmapRenderTarget_Resize(target
, 10, 5);
1227 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1229 hbm2
= GetCurrentObject(hdc
, OBJ_BITMAP
);
1230 ok(hbm2
== hbm
, "got %p, %p\n", hbm2
, hbm
);
1233 hr
= IDWriteBitmapRenderTarget_Resize(target
, 5, 5);
1234 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1236 size
.cx
= size
.cy
= -1;
1237 hr
= IDWriteBitmapRenderTarget_GetSize(target
, &size
);
1238 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1239 ok(size
.cx
== 5, "got %d\n", size
.cx
);
1240 ok(size
.cy
== 5, "got %d\n", size
.cy
);
1242 hbm2
= GetCurrentObject(hdc
, OBJ_BITMAP
);
1243 ok(hbm2
!= hbm
, "got %p, %p\n", hbm2
, hbm
);
1245 hr
= IDWriteBitmapRenderTarget_Resize(target
, 20, 5);
1246 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1248 size
.cx
= size
.cy
= -1;
1249 hr
= IDWriteBitmapRenderTarget_GetSize(target
, &size
);
1250 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1251 ok(size
.cx
== 20, "got %d\n", size
.cx
);
1252 ok(size
.cy
== 5, "got %d\n", size
.cy
);
1254 hbm2
= GetCurrentObject(hdc
, OBJ_BITMAP
);
1255 ok(hbm2
!= hbm
, "got %p, %p\n", hbm2
, hbm
);
1257 hr
= IDWriteBitmapRenderTarget_Resize(target
, 1, 5);
1258 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1260 size
.cx
= size
.cy
= -1;
1261 hr
= IDWriteBitmapRenderTarget_GetSize(target
, &size
);
1262 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1263 ok(size
.cx
== 1, "got %d\n", size
.cx
);
1264 ok(size
.cy
== 5, "got %d\n", size
.cy
);
1266 hbm2
= GetCurrentObject(hdc
, OBJ_BITMAP
);
1267 ok(hbm2
!= hbm
, "got %p, %p\n", hbm2
, hbm
);
1269 ret
= GetObjectW(hbm2
, sizeof(ds
), &ds
);
1270 ok(ret
== sizeof(ds
), "got %d\n", ret
);
1271 ok(ds
.dsBm
.bmWidth
== 1, "got %d\n", ds
.dsBm
.bmWidth
);
1272 ok(ds
.dsBm
.bmHeight
== 5, "got %d\n", ds
.dsBm
.bmHeight
);
1273 ok(ds
.dsBm
.bmPlanes
== 1, "got %d\n", ds
.dsBm
.bmPlanes
);
1274 ok(ds
.dsBm
.bmBitsPixel
== 32, "got %d\n", ds
.dsBm
.bmBitsPixel
);
1275 ok(ds
.dsBm
.bmBits
!= NULL
, "got %p\n", ds
.dsBm
.bmBits
);
1277 /* empty rectangle */
1278 hr
= IDWriteBitmapRenderTarget_Resize(target
, 0, 5);
1279 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1281 size
.cx
= size
.cy
= -1;
1282 hr
= IDWriteBitmapRenderTarget_GetSize(target
, &size
);
1283 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1284 ok(size
.cx
== 0, "got %d\n", size
.cx
);
1285 ok(size
.cy
== 5, "got %d\n", size
.cy
);
1287 hbm2
= GetCurrentObject(hdc
, OBJ_BITMAP
);
1288 ok(hbm2
!= hbm
, "got %p, %p\n", hbm2
, hbm
);
1290 ret
= GetObjectW(hbm2
, sizeof(ds
), &ds
);
1291 ok(ret
== sizeof(BITMAP
), "got %d\n", ret
);
1292 ok(ds
.dsBm
.bmWidth
== 1, "got %d\n", ds
.dsBm
.bmWidth
);
1293 ok(ds
.dsBm
.bmHeight
== 1, "got %d\n", ds
.dsBm
.bmHeight
);
1294 ok(ds
.dsBm
.bmPlanes
== 1, "got %d\n", ds
.dsBm
.bmPlanes
);
1295 ok(ds
.dsBm
.bmBitsPixel
== 1, "got %d\n", ds
.dsBm
.bmBitsPixel
);
1296 ok(!ds
.dsBm
.bmBits
, "got %p\n", ds
.dsBm
.bmBits
);
1298 /* transform tests, current hdc transform is not immediately affected */
1299 if (0) /* crashes on native */
1300 hr
= IDWriteBitmapRenderTarget_GetCurrentTransform(target
, NULL
);
1302 memset(&m
, 0xcc, sizeof(m
));
1303 hr
= IDWriteBitmapRenderTarget_GetCurrentTransform(target
, &m
);
1304 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1305 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
);
1306 ok(m
.dx
== 0.0 && m
.dy
== 0.0, "got %.1f,%.1f\n", m
.dx
, m
.dy
);
1307 ret
= GetWorldTransform(hdc
, &xform
);
1308 ok(ret
, "got %d\n", ret
);
1309 ok(xform
.eM11
== 1.0 && xform
.eM22
== 1.0 && xform
.eM12
== 0.0 && xform
.eM21
== 0.0, "got wrong transform\n");
1310 ok(xform
.eDx
== 0.0 && xform
.eDy
== 0.0, "got %.1f,%.1f\n", xform
.eDx
, xform
.eDy
);
1312 memset(&m
, 0, sizeof(m
));
1313 hr
= IDWriteBitmapRenderTarget_SetCurrentTransform(target
, &m
);
1314 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1316 memset(&m
, 0xcc, sizeof(m
));
1317 hr
= IDWriteBitmapRenderTarget_GetCurrentTransform(target
, &m
);
1318 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1319 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
);
1320 ok(m
.dx
== 0.0 && m
.dy
== 0.0, "got %.1f,%.1f\n", m
.dx
, m
.dy
);
1321 ret
= GetWorldTransform(hdc
, &xform
);
1322 ok(ret
, "got %d\n", ret
);
1323 ok(xform
.eM11
== 1.0 && xform
.eM22
== 1.0 && xform
.eM12
== 0.0 && xform
.eM21
== 0.0, "got wrong transform\n");
1324 ok(xform
.eDx
== 0.0 && xform
.eDy
== 0.0, "got %.1f,%.1f\n", xform
.eDx
, xform
.eDy
);
1326 memset(&m
, 0, sizeof(m
));
1327 m
.m11
= 2.0; m
.m22
= 1.0;
1328 hr
= IDWriteBitmapRenderTarget_SetCurrentTransform(target
, &m
);
1329 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1330 ret
= GetWorldTransform(hdc
, &xform
);
1331 ok(ret
, "got %d\n", ret
);
1332 ok(xform
.eM11
== 1.0 && xform
.eM22
== 1.0 && xform
.eM12
== 0.0 && xform
.eM21
== 0.0, "got wrong transform\n");
1333 ok(xform
.eDx
== 0.0 && xform
.eDy
== 0.0, "got %.1f,%.1f\n", xform
.eDx
, xform
.eDy
);
1335 hr
= IDWriteBitmapRenderTarget_SetCurrentTransform(target
, NULL
);
1336 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1338 memset(&m
, 0xcc, sizeof(m
));
1339 hr
= IDWriteBitmapRenderTarget_GetCurrentTransform(target
, &m
);
1340 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1341 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
);
1342 ok(m
.dx
== 0.0 && m
.dy
== 0.0, "got %.1f,%.1f\n", m
.dx
, m
.dy
);
1344 /* pixels per dip */
1345 pdip
= IDWriteBitmapRenderTarget_GetPixelsPerDip(target
);
1346 ok(pdip
== 1.0, "got %.2f\n", pdip
);
1348 hr
= IDWriteBitmapRenderTarget_SetPixelsPerDip(target
, 2.0);
1349 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1351 hr
= IDWriteBitmapRenderTarget_SetPixelsPerDip(target
, -1.0);
1352 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1354 hr
= IDWriteBitmapRenderTarget_SetPixelsPerDip(target
, 0.0);
1355 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1357 pdip
= IDWriteBitmapRenderTarget_GetPixelsPerDip(target
);
1358 ok(pdip
== 2.0, "got %.2f\n", pdip
);
1360 hr
= IDWriteBitmapRenderTarget_QueryInterface(target
, &IID_IDWriteBitmapRenderTarget1
, (void**)&target1
);
1362 DWRITE_TEXT_ANTIALIAS_MODE mode
;
1364 mode
= IDWriteBitmapRenderTarget1_GetTextAntialiasMode(target1
);
1365 ok(mode
== DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE
, "got %d\n", mode
);
1367 hr
= IDWriteBitmapRenderTarget1_SetTextAntialiasMode(target1
, DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
+1);
1368 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1370 mode
= IDWriteBitmapRenderTarget1_GetTextAntialiasMode(target1
);
1371 ok(mode
== DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE
, "got %d\n", mode
);
1373 hr
= IDWriteBitmapRenderTarget1_SetTextAntialiasMode(target1
, DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
);
1374 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1376 mode
= IDWriteBitmapRenderTarget1_GetTextAntialiasMode(target1
);
1377 ok(mode
== DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
, "got %d\n", mode
);
1379 IDWriteBitmapRenderTarget1_Release(target1
);
1382 win_skip("IDWriteBitmapRenderTarget1 is not supported.\n");
1384 /* DrawGlyphRun() argument validation. */
1385 hr
= IDWriteBitmapRenderTarget_Resize(target
, 16, 16);
1386 ok(hr
== S_OK
, "Failed to resize target, hr %#x.\n", hr
);
1388 fontface
= create_fontface(factory
);
1392 hr
= IDWriteFontFace_GetGlyphIndices(fontface
, &ch
, 1, glyphs
);
1393 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1394 ok(glyphs
[0] > 0, "got %u\n", glyphs
[0]);
1395 glyphs
[1] = glyphs
[0];
1397 memset(&run
, 0, sizeof(run
));
1398 run
.fontFace
= fontface
;
1399 run
.fontEmSize
= 12.0f
;
1401 run
.glyphIndices
= glyphs
;
1403 hr
= IDWriteFactory_CreateCustomRenderingParams(factory
, 1.0f
, 0.0f
, 0.0f
, DWRITE_PIXEL_GEOMETRY_FLAT
,
1404 DWRITE_RENDERING_MODE_DEFAULT
, ¶ms
);
1405 ok(hr
== S_OK
, "Failed to create rendering params, hr %#x.\n", hr
);
1407 hr
= IDWriteBitmapRenderTarget_DrawGlyphRun(target
, 0.0f
, 0.0f
, DWRITE_MEASURING_MODE_NATURAL
,
1408 &run
, NULL
, RGB(255, 0, 0), NULL
);
1409 ok(hr
== E_INVALIDARG
, "Unexpected hr %#x.\n", hr
);
1411 hr
= IDWriteBitmapRenderTarget_DrawGlyphRun(target
, 0.0f
, 0.0f
, DWRITE_MEASURING_MODE_GDI_NATURAL
+ 1,
1412 &run
, NULL
, RGB(255, 0, 0), NULL
);
1413 ok(hr
== E_INVALIDARG
, "Unexpected hr %#x.\n", hr
);
1415 hr
= IDWriteBitmapRenderTarget_DrawGlyphRun(target
, 0.0f
, 0.0f
, DWRITE_MEASURING_MODE_GDI_NATURAL
+ 1,
1416 &run
, params
, RGB(255, 0, 0), NULL
);
1417 ok(hr
== E_INVALIDARG
|| broken(hr
== S_OK
) /* Vista */, "Unexpected hr %#x.\n", hr
);
1419 hr
= IDWriteBitmapRenderTarget_DrawGlyphRun(target
, 0.0f
, 0.0f
, DWRITE_MEASURING_MODE_GDI_NATURAL
,
1420 &run
, params
, RGB(255, 0, 0), NULL
);
1421 ok(hr
== S_OK
, "Failed to draw a run, hr %#x.\n", hr
);
1423 IDWriteRenderingParams_Release(params
);
1425 /* Zero sized target returns earlier. */
1426 hr
= IDWriteBitmapRenderTarget_Resize(target
, 0, 16);
1427 ok(hr
== S_OK
, "Failed to resize target, hr %#x.\n", hr
);
1429 hr
= IDWriteBitmapRenderTarget_DrawGlyphRun(target
, 0.0f
, 0.0f
, DWRITE_MEASURING_MODE_NATURAL
,
1430 &run
, NULL
, RGB(255, 0, 0), NULL
);
1431 ok(hr
== S_OK
, "Unexpected hr %#x.\n", hr
);
1433 hr
= IDWriteBitmapRenderTarget_DrawGlyphRun(target
, 0.0f
, 0.0f
, DWRITE_MEASURING_MODE_GDI_NATURAL
+ 1,
1434 &run
, params
, RGB(255, 0, 0), NULL
);
1435 ok(hr
== S_OK
, "Unexpected hr %#x.\n", hr
);
1437 IDWriteFontFace_Release(fontface
);
1439 ref
= IDWriteBitmapRenderTarget_Release(target
);
1440 ok(ref
== 0, "render target not released, %u\n", ref
);
1441 ref
= IDWriteGdiInterop_Release(interop
);
1442 ok(ref
== 0, "interop not released, %u\n", ref
);
1443 ref
= IDWriteFactory_Release(factory
);
1444 ok(ref
== 0, "factory not released, %u\n", ref
);
1447 static void test_GetFontFamily(void)
1449 IDWriteFontCollection
*collection
, *collection2
;
1450 IDWriteFontCollection
*syscoll
;
1451 IDWriteFontFamily
*family
, *family2
;
1452 IDWriteFontFamily1
*family1
;
1453 IDWriteGdiInterop
*interop
;
1454 IDWriteFont
*font
, *font2
;
1455 IDWriteFactory
*factory
;
1460 factory
= create_factory();
1462 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop
);
1463 EXPECT_HR(hr
, S_OK
);
1465 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &syscoll
, FALSE
);
1466 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1468 memset(&logfont
, 0, sizeof(logfont
));
1469 logfont
.lfHeight
= 12;
1470 logfont
.lfWidth
= 12;
1471 logfont
.lfWeight
= FW_NORMAL
;
1472 logfont
.lfItalic
= 1;
1473 lstrcpyW(logfont
.lfFaceName
, tahomaW
);
1475 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font
);
1476 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1478 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font2
);
1479 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1480 ok(font2
!= font
, "got %p, %p\n", font2
, font
);
1482 if (0) /* crashes on native */
1483 hr
= IDWriteFont_GetFontFamily(font
, NULL
);
1485 EXPECT_REF(font
, 1);
1486 hr
= IDWriteFont_GetFontFamily(font
, &family
);
1487 EXPECT_HR(hr
, S_OK
);
1488 EXPECT_REF(font
, 1);
1489 EXPECT_REF(family
, 2);
1491 hr
= IDWriteFont_GetFontFamily(font
, &family2
);
1492 EXPECT_HR(hr
, S_OK
);
1493 ok(family2
== family
, "got %p, previous %p\n", family2
, family
);
1494 EXPECT_REF(font
, 1);
1495 EXPECT_REF(family
, 3);
1496 IDWriteFontFamily_Release(family2
);
1498 hr
= IDWriteFont_QueryInterface(font
, &IID_IDWriteFontFamily
, (void**)&family2
);
1499 EXPECT_HR(hr
, E_NOINTERFACE
);
1500 ok(family2
== NULL
, "got %p\n", family2
);
1502 hr
= IDWriteFont_GetFontFamily(font2
, &family2
);
1503 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1504 ok(family2
!= family
, "got %p, %p\n", family2
, family
);
1507 hr
= IDWriteFontFamily_GetFontCollection(family
, &collection
);
1508 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1511 hr
= IDWriteFontFamily_GetFontCollection(family2
, &collection2
);
1512 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1513 ok(collection
== collection2
, "got %p, %p\n", collection
, collection2
);
1514 ok(collection
== syscoll
, "got %p, %p\n", collection
, syscoll
);
1516 IDWriteFont_Release(font
);
1517 IDWriteFont_Release(font2
);
1519 hr
= IDWriteFontFamily_QueryInterface(family
, &IID_IDWriteFontFamily1
, (void**)&family1
);
1521 IDWriteFontFaceReference
*ref
, *ref1
;
1522 IDWriteFontList1
*fontlist1
;
1523 IDWriteFontList
*fontlist
;
1524 IDWriteFont3
*font3
;
1525 IDWriteFont1
*font1
;
1527 font3
= (void*)0xdeadbeef;
1528 hr
= IDWriteFontFamily1_GetFont(family1
, ~0u, &font3
);
1529 ok(hr
== E_FAIL
, "got 0x%08x\n", hr
);
1530 ok(font3
== NULL
, "got %p\n", font3
);
1532 hr
= IDWriteFontFamily1_GetFont(family1
, 0, &font3
);
1533 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1535 hr
= IDWriteFont3_QueryInterface(font3
, &IID_IDWriteFont
, (void**)&font
);
1536 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1537 IDWriteFont_Release(font
);
1539 hr
= IDWriteFont3_QueryInterface(font3
, &IID_IDWriteFont1
, (void**)&font1
);
1540 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1541 IDWriteFont1_Release(font1
);
1543 hr
= IDWriteFontFamily1_QueryInterface(family1
, &IID_IDWriteFontList1
, (void **)&fontlist1
);
1544 ok(hr
== S_OK
|| broken(hr
== E_NOINTERFACE
), "Failed to get interface, hr %#x.\n", hr
);
1546 hr
= IDWriteFontFamily1_QueryInterface(family1
, &IID_IDWriteFontList
, (void **)&fontlist
);
1547 ok(hr
== S_OK
, "Unexpected hr %#x.\n", hr
);
1548 ok(fontlist
== (IDWriteFontList
*)fontlist1
, "Unexpected interface pointer.\n");
1549 ok(fontlist
!= (IDWriteFontList
*)family1
, "Unexpected interface pointer.\n");
1550 ok(fontlist
!= (IDWriteFontList
*)family
, "Unexpected interface pointer.\n");
1551 IDWriteFontList1_Release(fontlist1
);
1552 IDWriteFontList_Release(fontlist
);
1555 hr
= IDWriteFontFamily1_QueryInterface(family1
, &IID_IDWriteFontList
, (void**)&fontlist
);
1556 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1557 IDWriteFontList_Release(fontlist
);
1559 IDWriteFont3_Release(font3
);
1561 hr
= IDWriteFontFamily1_GetFontFaceReference(family1
, 0, &ref
);
1562 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1564 hr
= IDWriteFontFamily1_GetFontFaceReference(family1
, 0, &ref1
);
1565 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1566 ok(ref
!= ref1
, "got %p, %p\n", ref
, ref1
);
1568 IDWriteFontFaceReference_Release(ref
);
1569 IDWriteFontFaceReference_Release(ref1
);
1571 IDWriteFontFamily1_Release(family1
);
1574 win_skip("IDWriteFontFamily1 is not supported.\n");
1576 IDWriteFontCollection_Release(syscoll
);
1577 IDWriteFontCollection_Release(collection2
);
1578 IDWriteFontCollection_Release(collection
);
1579 IDWriteFontFamily_Release(family2
);
1580 IDWriteFontFamily_Release(family
);
1581 IDWriteGdiInterop_Release(interop
);
1582 ref
= IDWriteFactory_Release(factory
);
1583 ok(ref
== 0, "factory not released, %u\n", ref
);
1586 static void test_GetFamilyNames(void)
1588 IDWriteFontFamily
*family
;
1589 IDWriteLocalizedStrings
*names
, *names2
;
1590 IDWriteGdiInterop
*interop
;
1591 IDWriteFactory
*factory
;
1599 factory
= create_factory();
1601 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop
);
1602 EXPECT_HR(hr
, S_OK
);
1604 memset(&logfont
, 0, sizeof(logfont
));
1605 logfont
.lfHeight
= 12;
1606 logfont
.lfWidth
= 12;
1607 logfont
.lfWeight
= FW_NORMAL
;
1608 logfont
.lfItalic
= 1;
1609 lstrcpyW(logfont
.lfFaceName
, tahomaW
);
1611 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font
);
1612 EXPECT_HR(hr
, S_OK
);
1614 hr
= IDWriteFont_GetFontFamily(font
, &family
);
1615 EXPECT_HR(hr
, S_OK
);
1617 if (0) /* crashes on native */
1618 hr
= IDWriteFontFamily_GetFamilyNames(family
, NULL
);
1620 hr
= IDWriteFontFamily_GetFamilyNames(family
, &names
);
1621 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1622 EXPECT_REF(names
, 1);
1624 hr
= IDWriteFontFamily_GetFamilyNames(family
, &names2
);
1625 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1626 EXPECT_REF(names2
, 1);
1627 ok(names
!= names2
, "got %p, was %p\n", names2
, names
);
1629 IDWriteLocalizedStrings_Release(names2
);
1631 /* GetStringLength */
1632 if (0) /* crashes on native */
1633 hr
= IDWriteLocalizedStrings_GetStringLength(names
, 0, NULL
);
1636 hr
= IDWriteLocalizedStrings_GetStringLength(names
, 10, &len
);
1637 ok(hr
== E_FAIL
, "got 0x%08x\n", hr
);
1638 ok(len
== (UINT32
)-1, "got %u\n", len
);
1641 hr
= IDWriteLocalizedStrings_GetStringLength(names
, 0, &len
);
1642 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1643 ok(len
> 0, "got %u\n", len
);
1646 hr
= IDWriteLocalizedStrings_GetString(names
, 0, NULL
, 0);
1647 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
1649 hr
= IDWriteLocalizedStrings_GetString(names
, 10, NULL
, 0);
1650 ok(hr
== E_FAIL
, "got 0x%08x\n", hr
);
1653 hr
= IDWriteLocalizedStrings_GetString(names
, 0, NULL
, 100);
1656 hr
= IDWriteLocalizedStrings_GetString(names
, 10, buffer
, 100);
1657 ok(hr
== E_FAIL
, "got 0x%08x\n", hr
);
1658 ok(buffer
[0] == 0, "got %x\n", buffer
[0]);
1661 hr
= IDWriteLocalizedStrings_GetString(names
, 0, buffer
, len
-1);
1662 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
1663 ok(buffer
[0] == 0, "got %x\n", buffer
[0]);
1666 hr
= IDWriteLocalizedStrings_GetString(names
, 0, buffer
, len
);
1667 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
1668 ok(buffer
[0] == 0, "got %x\n", buffer
[0]);
1671 hr
= IDWriteLocalizedStrings_GetString(names
, 0, buffer
, len
+1);
1672 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1673 ok(buffer
[0] != 0, "got %x\n", buffer
[0]);
1675 IDWriteLocalizedStrings_Release(names
);
1677 IDWriteFontFamily_Release(family
);
1678 IDWriteFont_Release(font
);
1679 IDWriteGdiInterop_Release(interop
);
1680 ref
= IDWriteFactory_Release(factory
);
1681 ok(ref
== 0, "factory not released, %u\n", ref
);
1684 static void test_CreateFontFace(void)
1686 IDWriteFontFace
*fontface
, *fontface2
;
1687 IDWriteFontCollection
*collection
;
1688 DWRITE_FONT_FILE_TYPE file_type
;
1689 DWRITE_FONT_FACE_TYPE face_type
;
1690 IDWriteGdiInterop
*interop
;
1691 IDWriteFont
*font
, *font2
;
1692 IDWriteFontFamily
*family
;
1693 IDWriteFactory
*factory
;
1694 IDWriteFontFile
*file
;
1701 factory
= create_factory();
1703 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop
);
1704 EXPECT_HR(hr
, S_OK
);
1706 memset(&logfont
, 0, sizeof(logfont
));
1707 logfont
.lfHeight
= 12;
1708 logfont
.lfWidth
= 12;
1709 logfont
.lfWeight
= FW_NORMAL
;
1710 logfont
.lfItalic
= 1;
1711 lstrcpyW(logfont
.lfFaceName
, tahomaW
);
1714 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font
);
1715 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1718 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font2
);
1719 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1720 ok(font
!= font2
, "got %p, %p\n", font
, font2
);
1722 hr
= IDWriteFont_QueryInterface(font
, &IID_IDWriteFontFace
, (void**)&fontface
);
1723 ok(hr
== E_NOINTERFACE
, "got 0x%08x\n", hr
);
1725 if (0) /* crashes on native */
1726 hr
= IDWriteFont_CreateFontFace(font
, NULL
);
1729 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
1730 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1733 hr
= IDWriteFont_CreateFontFace(font
, &fontface2
);
1734 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1735 ok(fontface
== fontface2
, "got %p, was %p\n", fontface2
, fontface
);
1736 IDWriteFontFace_Release(fontface2
);
1739 hr
= IDWriteFont_CreateFontFace(font2
, &fontface2
);
1740 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1741 ok(fontface
== fontface2
, "got %p, was %p\n", fontface2
, fontface
);
1742 IDWriteFontFace_Release(fontface2
);
1744 IDWriteFont_Release(font2
);
1745 IDWriteFont_Release(font
);
1747 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFont
, (void**)&font
);
1748 ok(hr
== E_NOINTERFACE
|| broken(hr
== E_NOTIMPL
), "got 0x%08x\n", hr
);
1750 IDWriteFontFace_Release(fontface
);
1751 IDWriteGdiInterop_Release(interop
);
1753 /* Create from system collection */
1754 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &collection
, FALSE
);
1755 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1757 hr
= IDWriteFontCollection_GetFontFamily(collection
, 0, &family
);
1758 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1761 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
,
1762 DWRITE_FONT_STRETCH_NORMAL
, DWRITE_FONT_STYLE_NORMAL
, &font
);
1763 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1766 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
,
1767 DWRITE_FONT_STRETCH_NORMAL
, DWRITE_FONT_STYLE_NORMAL
, &font2
);
1768 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1769 ok(font
!= font2
, "got %p, %p\n", font
, font2
);
1772 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
1773 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1776 hr
= IDWriteFont_CreateFontFace(font2
, &fontface2
);
1777 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1778 ok(fontface
== fontface2
, "got %p, was %p\n", fontface2
, fontface
);
1780 IDWriteFontFace_Release(fontface
);
1781 IDWriteFontFace_Release(fontface2
);
1782 IDWriteFont_Release(font2
);
1783 IDWriteFont_Release(font
);
1784 IDWriteFontFamily_Release(family
);
1785 IDWriteFontCollection_Release(collection
);
1787 /* IDWriteFactory::CreateFontFace() */
1788 path
= create_testfontfile(test_fontfile
);
1789 factory
= create_factory();
1791 hr
= IDWriteFactory_CreateFontFileReference(factory
, path
, NULL
, &file
);
1792 ok(hr
== S_OK
, "got 0x%08x\n",hr
);
1795 file_type
= DWRITE_FONT_FILE_TYPE_UNKNOWN
;
1796 face_type
= DWRITE_FONT_FACE_TYPE_CFF
;
1798 hr
= IDWriteFontFile_Analyze(file
, &supported
, &file_type
, &face_type
, &count
);
1799 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1800 ok(supported
== TRUE
, "got %i\n", supported
);
1801 ok(file_type
== DWRITE_FONT_FILE_TYPE_TRUETYPE
, "got %i\n", file_type
);
1802 ok(face_type
== DWRITE_FONT_FACE_TYPE_TRUETYPE
, "got %i\n", face_type
);
1803 ok(count
== 1, "got %i\n", count
);
1805 /* invalid simulation flags */
1806 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_CFF
, 1, &file
, 0, ~0u, &fontface
);
1807 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1809 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_CFF
, 1, &file
, 0, 0xf, &fontface
);
1810 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1812 /* try mismatching face type, the one that's not supported */
1813 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_CFF
, 1, &file
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &fontface
);
1814 ok(hr
== DWRITE_E_FILEFORMAT
, "got 0x%08x\n", hr
);
1816 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_OPENTYPE_COLLECTION
, 1, &file
, 0,
1817 DWRITE_FONT_SIMULATIONS_NONE
, &fontface
);
1818 ok(hr
== DWRITE_E_FILEFORMAT
|| broken(hr
== E_FAIL
) /* < win10 */, "got 0x%08x\n", hr
);
1820 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_RAW_CFF
, 1, &file
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &fontface
);
1822 ok(hr
== DWRITE_E_UNSUPPORTEDOPERATION
|| broken(hr
== E_INVALIDARG
) /* older versions */, "got 0x%08x\n", hr
);
1824 fontface
= (void*)0xdeadbeef;
1825 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_TYPE1
, 1, &file
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &fontface
);
1826 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1827 ok(fontface
== NULL
, "got %p\n", fontface
);
1829 fontface
= (void*)0xdeadbeef;
1830 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_VECTOR
, 1, &file
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &fontface
);
1831 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1832 ok(fontface
== NULL
, "got %p\n", fontface
);
1834 fontface
= (void*)0xdeadbeef;
1835 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_BITMAP
, 1, &file
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &fontface
);
1836 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1837 ok(fontface
== NULL
, "got %p\n", fontface
);
1840 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_UNKNOWN
, 1, &file
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &fontface
);
1842 ok(hr
== S_OK
|| broken(hr
== E_INVALIDARG
) /* < win10 */, "got 0x%08x\n", hr
);
1844 ok(fontface
!= NULL
, "got %p\n", fontface
);
1845 face_type
= IDWriteFontFace_GetType(fontface
);
1846 ok(face_type
== DWRITE_FONT_FACE_TYPE_TRUETYPE
, "got %d\n", face_type
);
1847 IDWriteFontFace_Release(fontface
);
1850 IDWriteFontFile_Release(file
);
1851 IDWriteFactory_Release(factory
);
1852 DELETE_FONTFILE(path
);
1855 static void get_expected_font_metrics(IDWriteFontFace
*fontface
, DWRITE_FONT_METRICS1
*metrics
)
1857 void *os2_context
, *head_context
, *post_context
, *hhea_context
;
1858 const TT_OS2_V2
*tt_os2
;
1859 const TT_HEAD
*tt_head
;
1860 const TT_POST
*tt_post
;
1861 const TT_HHEA
*tt_hhea
;
1866 memset(metrics
, 0, sizeof(*metrics
));
1868 hr
= IDWriteFontFace_TryGetFontTable(fontface
, MS_0S2_TAG
, (const void**)&tt_os2
, &size
, &os2_context
, &exists
);
1869 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1870 hr
= IDWriteFontFace_TryGetFontTable(fontface
, MS_HEAD_TAG
, (const void**)&tt_head
, &size
, &head_context
, &exists
);
1871 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1872 hr
= IDWriteFontFace_TryGetFontTable(fontface
, MS_HHEA_TAG
, (const void**)&tt_hhea
, &size
, &hhea_context
, &exists
);
1873 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1874 hr
= IDWriteFontFace_TryGetFontTable(fontface
, MS_POST_TAG
, (const void**)&tt_post
, &size
, &post_context
, &exists
);
1875 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1878 metrics
->designUnitsPerEm
= GET_BE_WORD(tt_head
->unitsPerEm
);
1879 metrics
->glyphBoxLeft
= GET_BE_WORD(tt_head
->xMin
);
1880 metrics
->glyphBoxTop
= GET_BE_WORD(tt_head
->yMax
);
1881 metrics
->glyphBoxRight
= GET_BE_WORD(tt_head
->xMax
);
1882 metrics
->glyphBoxBottom
= GET_BE_WORD(tt_head
->yMin
);
1886 if (GET_BE_WORD(tt_os2
->fsSelection
) & OS2_FSSELECTION_USE_TYPO_METRICS
) {
1887 SHORT descent
= GET_BE_WORD(tt_os2
->sTypoDescender
);
1888 metrics
->ascent
= GET_BE_WORD(tt_os2
->sTypoAscender
);
1889 metrics
->descent
= descent
< 0 ? -descent
: 0;
1890 metrics
->lineGap
= GET_BE_WORD(tt_os2
->sTypoLineGap
);
1891 metrics
->hasTypographicMetrics
= TRUE
;
1894 metrics
->ascent
= GET_BE_WORD(tt_os2
->usWinAscent
);
1895 /* Some fonts have usWinDescent value stored as signed short, which could be wrongly
1896 interpreted as large unsigned value. */
1897 metrics
->descent
= abs((SHORT
)GET_BE_WORD(tt_os2
->usWinDescent
));
1900 SHORT descender
= (SHORT
)GET_BE_WORD(tt_hhea
->descender
);
1903 linegap
= GET_BE_WORD(tt_hhea
->ascender
) + abs(descender
) + GET_BE_WORD(tt_hhea
->linegap
) -
1904 metrics
->ascent
- metrics
->descent
;
1905 metrics
->lineGap
= linegap
> 0 ? linegap
: 0;
1909 metrics
->strikethroughPosition
= GET_BE_WORD(tt_os2
->yStrikeoutPosition
);
1910 metrics
->strikethroughThickness
= GET_BE_WORD(tt_os2
->yStrikeoutSize
);
1912 metrics
->subscriptPositionX
= GET_BE_WORD(tt_os2
->ySubscriptXOffset
);
1913 metrics
->subscriptPositionY
= -GET_BE_WORD(tt_os2
->ySubscriptYOffset
);
1914 metrics
->subscriptSizeX
= GET_BE_WORD(tt_os2
->ySubscriptXSize
);
1915 metrics
->subscriptSizeY
= GET_BE_WORD(tt_os2
->ySubscriptYSize
);
1916 metrics
->superscriptPositionX
= GET_BE_WORD(tt_os2
->ySuperscriptXOffset
);
1917 metrics
->superscriptPositionY
= GET_BE_WORD(tt_os2
->ySuperscriptYOffset
);
1918 metrics
->superscriptSizeX
= GET_BE_WORD(tt_os2
->ySuperscriptXSize
);
1919 metrics
->superscriptSizeY
= GET_BE_WORD(tt_os2
->ySuperscriptYSize
);
1923 metrics
->underlinePosition
= GET_BE_WORD(tt_post
->underlinePosition
);
1924 metrics
->underlineThickness
= GET_BE_WORD(tt_post
->underlineThickness
);
1927 if (metrics
->underlineThickness
== 0)
1928 metrics
->underlineThickness
= metrics
->designUnitsPerEm
/ 14;
1929 if (metrics
->strikethroughThickness
== 0)
1930 metrics
->strikethroughThickness
= metrics
->underlineThickness
;
1933 IDWriteFontFace_ReleaseFontTable(fontface
, os2_context
);
1935 IDWriteFontFace_ReleaseFontTable(fontface
, head_context
);
1937 IDWriteFontFace_ReleaseFontTable(fontface
, hhea_context
);
1939 IDWriteFontFace_ReleaseFontTable(fontface
, post_context
);
1942 static void check_font_metrics(const WCHAR
*nameW
, BOOL has_metrics1
, const DWRITE_FONT_METRICS
*got
,
1943 const DWRITE_FONT_METRICS1
*expected
)
1945 ok(got
->designUnitsPerEm
== expected
->designUnitsPerEm
, "font %s: designUnitsPerEm %u, expected %u\n",
1946 wine_dbgstr_w(nameW
), got
->designUnitsPerEm
, expected
->designUnitsPerEm
);
1947 ok(got
->ascent
== expected
->ascent
, "font %s: ascent %u, expected %u\n", wine_dbgstr_w(nameW
), got
->ascent
,
1949 ok(got
->descent
== expected
->descent
, "font %s: descent %u, expected %u\n", wine_dbgstr_w(nameW
), got
->descent
,
1951 ok(got
->lineGap
== expected
->lineGap
, "font %s: lineGap %d, expected %d\n", wine_dbgstr_w(nameW
), got
->lineGap
,
1953 ok(got
->underlinePosition
== expected
->underlinePosition
, "font %s: underlinePosition %d, expected %d\n",
1954 wine_dbgstr_w(nameW
), got
->underlinePosition
, expected
->underlinePosition
);
1955 ok(got
->underlineThickness
== expected
->underlineThickness
, "font %s: underlineThickness %u, "
1956 "expected %u\n", wine_dbgstr_w(nameW
), got
->underlineThickness
, expected
->underlineThickness
);
1957 ok(got
->strikethroughPosition
== expected
->strikethroughPosition
, "font %s: strikethroughPosition %d, expected %d\n",
1958 wine_dbgstr_w(nameW
), got
->strikethroughPosition
, expected
->strikethroughPosition
);
1959 ok(got
->strikethroughThickness
== expected
->strikethroughThickness
, "font %s: strikethroughThickness %u, "
1960 "expected %u\n", wine_dbgstr_w(nameW
), got
->strikethroughThickness
, expected
->strikethroughThickness
);
1963 const DWRITE_FONT_METRICS1
*m1
= (const DWRITE_FONT_METRICS1
*)got
;
1964 ok(m1
->hasTypographicMetrics
== expected
->hasTypographicMetrics
, "font %s: hasTypographicMetrics %d, "
1965 "expected %d\n", wine_dbgstr_w(nameW
), m1
->hasTypographicMetrics
, expected
->hasTypographicMetrics
);
1966 ok(m1
->glyphBoxLeft
== expected
->glyphBoxLeft
, "font %s: glyphBoxLeft %d, expected %d\n", wine_dbgstr_w(nameW
),
1967 m1
->glyphBoxLeft
, expected
->glyphBoxLeft
);
1968 ok(m1
->glyphBoxTop
== expected
->glyphBoxTop
, "font %s: glyphBoxTop %d, expected %d\n", wine_dbgstr_w(nameW
),
1969 m1
->glyphBoxTop
, expected
->glyphBoxTop
);
1970 ok(m1
->glyphBoxRight
== expected
->glyphBoxRight
, "font %s: glyphBoxRight %d, expected %d\n", wine_dbgstr_w(nameW
),
1971 m1
->glyphBoxRight
, expected
->glyphBoxRight
);
1972 ok(m1
->glyphBoxBottom
== expected
->glyphBoxBottom
, "font %s: glyphBoxBottom %d, expected %d\n", wine_dbgstr_w(nameW
),
1973 m1
->glyphBoxBottom
, expected
->glyphBoxBottom
);
1975 ok(m1
->subscriptPositionX
== expected
->subscriptPositionX
, "font %s: subscriptPositionX %d, expected %d\n",
1976 wine_dbgstr_w(nameW
), m1
->subscriptPositionX
, expected
->subscriptPositionX
);
1977 ok(m1
->subscriptPositionY
== expected
->subscriptPositionY
, "font %s: subscriptPositionY %d, expected %d\n",
1978 wine_dbgstr_w(nameW
), m1
->subscriptPositionY
, expected
->subscriptPositionY
);
1979 ok(m1
->subscriptSizeX
== expected
->subscriptSizeX
, "font %s: subscriptSizeX %d, expected %d\n",
1980 wine_dbgstr_w(nameW
), m1
->subscriptSizeX
, expected
->subscriptSizeX
);
1981 ok(m1
->subscriptSizeY
== expected
->subscriptSizeY
, "font %s: subscriptSizeY %d, expected %d\n",
1982 wine_dbgstr_w(nameW
), m1
->subscriptSizeY
, expected
->subscriptSizeY
);
1983 ok(m1
->superscriptPositionX
== expected
->superscriptPositionX
, "font %s: superscriptPositionX %d, expected %d\n",
1984 wine_dbgstr_w(nameW
), m1
->superscriptPositionX
, expected
->superscriptPositionX
);
1985 ok(m1
->superscriptPositionY
== expected
->superscriptPositionY
, "font %s: superscriptPositionY %d, expected %d\n",
1986 wine_dbgstr_w(nameW
), m1
->superscriptPositionY
, expected
->superscriptPositionY
);
1987 ok(m1
->superscriptSizeX
== expected
->superscriptSizeX
, "font %s: superscriptSizeX %d, expected %d\n",
1988 wine_dbgstr_w(nameW
), m1
->superscriptSizeX
, expected
->superscriptSizeX
);
1989 ok(m1
->superscriptSizeY
== expected
->superscriptSizeY
, "font %s: superscriptSizeY %d, expected %d\n",
1990 wine_dbgstr_w(nameW
), m1
->superscriptSizeY
, expected
->superscriptSizeY
);
1994 static void get_enus_string(IDWriteLocalizedStrings
*strings
, WCHAR
*buff
, UINT32 size
)
1996 static const WCHAR enusW
[] = {'e','n','-','u','s',0};
1997 BOOL exists
= FALSE
;
2001 hr
= IDWriteLocalizedStrings_FindLocaleName(strings
, enusW
, &index
, &exists
);
2002 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2003 ok(exists
, "got %d\n", exists
);
2005 hr
= IDWriteLocalizedStrings_GetString(strings
, index
, buff
, size
);
2006 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2009 static void test_GetMetrics(void)
2011 DWRITE_FONT_METRICS metrics
, metrics2
;
2012 IDWriteFontCollection
*syscollection
;
2013 IDWriteGdiInterop
*interop
;
2014 IDWriteFontFace
*fontface
;
2015 IDWriteFactory
*factory
;
2016 OUTLINETEXTMETRICW otm
;
2017 IDWriteFontFile
*file
;
2018 IDWriteFont1
*font1
;
2028 factory
= create_factory();
2030 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop
);
2031 EXPECT_HR(hr
, S_OK
);
2033 memset(&logfont
, 0, sizeof(logfont
));
2034 logfont
.lfHeight
= 12;
2035 logfont
.lfWidth
= 12;
2036 logfont
.lfWeight
= FW_NORMAL
;
2037 logfont
.lfItalic
= 1;
2038 lstrcpyW(logfont
.lfFaceName
, tahomaW
);
2040 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font
);
2041 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2043 hfont
= CreateFontIndirectW(&logfont
);
2044 hdc
= CreateCompatibleDC(0);
2045 SelectObject(hdc
, hfont
);
2047 otm
.otmSize
= sizeof(otm
);
2048 ret
= GetOutlineTextMetricsW(hdc
, otm
.otmSize
, &otm
);
2049 ok(ret
, "got %d\n", ret
);
2051 DeleteObject(hfont
);
2053 if (0) /* crashes on native */
2054 IDWriteFont_GetMetrics(font
, NULL
);
2056 memset(&metrics
, 0, sizeof(metrics
));
2057 IDWriteFont_GetMetrics(font
, &metrics
);
2059 ok(metrics
.designUnitsPerEm
!= 0, "designUnitsPerEm %u\n", metrics
.designUnitsPerEm
);
2060 ok(metrics
.ascent
!= 0, "ascent %u\n", metrics
.ascent
);
2061 ok(metrics
.descent
!= 0, "descent %u\n", metrics
.descent
);
2062 ok(metrics
.lineGap
== 0, "lineGap %d\n", metrics
.lineGap
);
2063 ok(metrics
.capHeight
, "capHeight %u\n", metrics
.capHeight
);
2064 ok(metrics
.xHeight
!= 0, "xHeight %u\n", metrics
.xHeight
);
2065 ok(metrics
.underlinePosition
< 0, "underlinePosition %d\n", metrics
.underlinePosition
);
2066 ok(metrics
.underlineThickness
!= 0, "underlineThickness %u\n", metrics
.underlineThickness
);
2067 ok(metrics
.strikethroughPosition
> 0, "strikethroughPosition %d\n", metrics
.strikethroughPosition
);
2068 ok(metrics
.strikethroughThickness
!= 0, "strikethroughThickness %u\n", metrics
.strikethroughThickness
);
2070 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
2071 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2073 memset(&metrics
, 0, sizeof(metrics
));
2074 IDWriteFontFace_GetMetrics(fontface
, &metrics
);
2076 ok(metrics
.designUnitsPerEm
!= 0, "designUnitsPerEm %u\n", metrics
.designUnitsPerEm
);
2077 ok(metrics
.ascent
!= 0, "ascent %u\n", metrics
.ascent
);
2078 ok(metrics
.descent
!= 0, "descent %u\n", metrics
.descent
);
2079 ok(metrics
.lineGap
== 0, "lineGap %d\n", metrics
.lineGap
);
2080 ok(metrics
.capHeight
, "capHeight %u\n", metrics
.capHeight
);
2081 ok(metrics
.xHeight
!= 0, "xHeight %u\n", metrics
.xHeight
);
2082 ok(metrics
.underlinePosition
< 0, "underlinePosition %d\n", metrics
.underlinePosition
);
2083 ok(metrics
.underlineThickness
!= 0, "underlineThickness %u\n", metrics
.underlineThickness
);
2084 ok(metrics
.strikethroughPosition
> 0, "strikethroughPosition %d\n", metrics
.strikethroughPosition
);
2085 ok(metrics
.strikethroughThickness
!= 0, "strikethroughThickness %u\n", metrics
.strikethroughThickness
);
2087 hr
= IDWriteFont_QueryInterface(font
, &IID_IDWriteFont1
, (void**)&font1
);
2089 DWRITE_FONT_METRICS1 metrics1
;
2090 IDWriteFontFace1
*fontface1
;
2092 memset(&metrics1
, 0, sizeof(metrics1
));
2093 IDWriteFont1_GetMetrics(font1
, &metrics1
);
2095 ok(metrics1
.designUnitsPerEm
!= 0, "designUnitsPerEm %u\n", metrics1
.designUnitsPerEm
);
2096 ok(metrics1
.ascent
!= 0, "ascent %u\n", metrics1
.ascent
);
2097 ok(metrics1
.descent
!= 0, "descent %u\n", metrics1
.descent
);
2098 ok(metrics1
.lineGap
== 0, "lineGap %d\n", metrics1
.lineGap
);
2099 ok(metrics1
.capHeight
, "capHeight %u\n", metrics1
.capHeight
);
2100 ok(metrics1
.xHeight
!= 0, "xHeight %u\n", metrics1
.xHeight
);
2101 ok(metrics1
.underlinePosition
< 0, "underlinePosition %d\n", metrics1
.underlinePosition
);
2102 ok(metrics1
.underlineThickness
!= 0, "underlineThickness %u\n", metrics1
.underlineThickness
);
2103 ok(metrics1
.strikethroughPosition
> 0, "strikethroughPosition %d\n", metrics1
.strikethroughPosition
);
2104 ok(metrics1
.strikethroughThickness
!= 0, "strikethroughThickness %u\n", metrics1
.strikethroughThickness
);
2105 ok(metrics1
.glyphBoxLeft
< 0, "glyphBoxLeft %d\n", metrics1
.glyphBoxLeft
);
2106 ok(metrics1
.glyphBoxTop
> 0, "glyphBoxTop %d\n", metrics1
.glyphBoxTop
);
2107 ok(metrics1
.glyphBoxRight
> 0, "glyphBoxRight %d\n", metrics1
.glyphBoxRight
);
2108 ok(metrics1
.glyphBoxBottom
< 0, "glyphBoxBottom %d\n", metrics1
.glyphBoxBottom
);
2109 ok(metrics1
.subscriptPositionY
< 0, "subscriptPositionY %d\n", metrics1
.subscriptPositionY
);
2110 ok(metrics1
.subscriptSizeX
> 0, "subscriptSizeX %d\n", metrics1
.subscriptSizeX
);
2111 ok(metrics1
.subscriptSizeY
> 0, "subscriptSizeY %d\n", metrics1
.subscriptSizeY
);
2112 ok(metrics1
.superscriptPositionY
> 0, "superscriptPositionY %d\n", metrics1
.superscriptPositionY
);
2113 ok(metrics1
.superscriptSizeX
> 0, "superscriptSizeX %d\n", metrics1
.superscriptSizeX
);
2114 ok(metrics1
.superscriptSizeY
> 0, "superscriptSizeY %d\n", metrics1
.superscriptSizeY
);
2115 ok(!metrics1
.hasTypographicMetrics
, "hasTypographicMetrics %d\n", metrics1
.hasTypographicMetrics
);
2117 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void**)&fontface1
);
2118 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2120 memset(&metrics1
, 0, sizeof(metrics1
));
2121 IDWriteFontFace1_GetMetrics(fontface1
, &metrics1
);
2123 ok(metrics1
.designUnitsPerEm
!= 0, "designUnitsPerEm %u\n", metrics1
.designUnitsPerEm
);
2124 ok(metrics1
.ascent
!= 0, "ascent %u\n", metrics1
.ascent
);
2125 ok(metrics1
.descent
!= 0, "descent %u\n", metrics1
.descent
);
2126 ok(metrics1
.lineGap
== 0, "lineGap %d\n", metrics1
.lineGap
);
2127 ok(metrics1
.capHeight
, "capHeight %u\n", metrics1
.capHeight
);
2128 ok(metrics1
.xHeight
!= 0, "xHeight %u\n", metrics1
.xHeight
);
2129 ok(metrics1
.underlinePosition
< 0, "underlinePosition %d\n", metrics1
.underlinePosition
);
2130 ok(metrics1
.underlineThickness
!= 0, "underlineThickness %u\n", metrics1
.underlineThickness
);
2131 ok(metrics1
.strikethroughPosition
> 0, "strikethroughPosition %d\n", metrics1
.strikethroughPosition
);
2132 ok(metrics1
.strikethroughThickness
!= 0, "strikethroughThickness %u\n", metrics1
.strikethroughThickness
);
2133 ok(metrics1
.glyphBoxLeft
< 0, "glyphBoxLeft %d\n", metrics1
.glyphBoxLeft
);
2134 ok(metrics1
.glyphBoxTop
> 0, "glyphBoxTop %d\n", metrics1
.glyphBoxTop
);
2135 ok(metrics1
.glyphBoxRight
> 0, "glyphBoxRight %d\n", metrics1
.glyphBoxRight
);
2136 ok(metrics1
.glyphBoxBottom
< 0, "glyphBoxBottom %d\n", metrics1
.glyphBoxBottom
);
2137 ok(metrics1
.subscriptPositionY
< 0, "subscriptPositionY %d\n", metrics1
.subscriptPositionY
);
2138 ok(metrics1
.subscriptSizeX
> 0, "subscriptSizeX %d\n", metrics1
.subscriptSizeX
);
2139 ok(metrics1
.subscriptSizeY
> 0, "subscriptSizeY %d\n", metrics1
.subscriptSizeY
);
2140 ok(metrics1
.superscriptPositionY
> 0, "superscriptPositionY %d\n", metrics1
.superscriptPositionY
);
2141 ok(metrics1
.superscriptSizeX
> 0, "superscriptSizeX %d\n", metrics1
.superscriptSizeX
);
2142 ok(metrics1
.superscriptSizeY
> 0, "superscriptSizeY %d\n", metrics1
.superscriptSizeY
);
2143 ok(!metrics1
.hasTypographicMetrics
, "hasTypographicMetrics %d\n", metrics1
.hasTypographicMetrics
);
2145 IDWriteFontFace1_Release(fontface1
);
2146 IDWriteFont1_Release(font1
);
2149 win_skip("DWRITE_FONT_METRICS1 is not supported.\n");
2151 IDWriteFontFace_Release(fontface
);
2152 IDWriteFont_Release(font
);
2153 IDWriteGdiInterop_Release(interop
);
2155 /* bold simulation affects returned font metrics */
2156 font
= get_tahoma_instance(factory
, DWRITE_FONT_STYLE_NORMAL
);
2158 /* create regulat Tahoma with bold simulation */
2159 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
2160 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2163 hr
= IDWriteFontFace_GetFiles(fontface
, &count
, &file
);
2164 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2166 IDWriteFontFace_GetMetrics(fontface
, &metrics
);
2167 ok(IDWriteFontFace_GetSimulations(fontface
) == 0, "wrong simulations flags\n");
2168 IDWriteFontFace_Release(fontface
);
2170 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_TRUETYPE
, 1, &file
,
2171 0, DWRITE_FONT_SIMULATIONS_BOLD
, &fontface
);
2172 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2173 IDWriteFontFace_GetMetrics(fontface
, &metrics2
);
2174 ok(IDWriteFontFace_GetSimulations(fontface
) == DWRITE_FONT_SIMULATIONS_BOLD
, "wrong simulations flags\n");
2176 ok(metrics
.ascent
== metrics2
.ascent
, "got %u, %u\n", metrics2
.ascent
, metrics
.ascent
);
2177 ok(metrics
.descent
== metrics2
.descent
, "got %u, %u\n", metrics2
.descent
, metrics
.descent
);
2178 ok(metrics
.lineGap
== metrics2
.lineGap
, "got %d, %d\n", metrics2
.lineGap
, metrics
.lineGap
);
2179 ok(metrics
.capHeight
== metrics2
.capHeight
, "got %u, %u\n", metrics2
.capHeight
, metrics
.capHeight
);
2180 ok(metrics
.xHeight
== metrics2
.xHeight
, "got %u, %u\n", metrics2
.xHeight
, metrics
.xHeight
);
2181 ok(metrics
.underlinePosition
== metrics2
.underlinePosition
, "got %d, %d\n", metrics2
.underlinePosition
,
2182 metrics
.underlinePosition
);
2183 ok(metrics
.underlineThickness
== metrics2
.underlineThickness
, "got %u, %u\n", metrics2
.underlineThickness
,
2184 metrics
.underlineThickness
);
2185 ok(metrics
.strikethroughPosition
== metrics2
.strikethroughPosition
, "got %d, %d\n", metrics2
.strikethroughPosition
,
2186 metrics
.strikethroughPosition
);
2187 ok(metrics
.strikethroughThickness
== metrics2
.strikethroughThickness
, "got %u, %u\n", metrics2
.strikethroughThickness
,
2188 metrics
.strikethroughThickness
);
2190 IDWriteFontFile_Release(file
);
2191 IDWriteFontFace_Release(fontface
);
2192 IDWriteFont_Release(font
);
2194 /* test metrics for whole system collection */
2195 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &syscollection
, FALSE
);
2196 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2197 count
= IDWriteFontCollection_GetFontFamilyCount(syscollection
);
2199 for (i
= 0; i
< count
; i
++) {
2200 DWRITE_FONT_METRICS1 expected_metrics
, metrics1
;
2201 IDWriteLocalizedStrings
*names
;
2202 IDWriteFontFace1
*fontface1
;
2203 IDWriteFontFamily
*family
;
2207 hr
= IDWriteFontCollection_GetFontFamily(syscollection
, i
, &family
);
2208 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2210 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STRETCH_NORMAL
,
2211 DWRITE_FONT_STYLE_NORMAL
, &font
);
2212 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2214 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
2215 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2218 IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void**)&fontface1
);
2220 hr
= IDWriteFontFamily_GetFamilyNames(family
, &names
);
2221 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2223 get_enus_string(names
, nameW
, ARRAY_SIZE(nameW
));
2225 IDWriteLocalizedStrings_Release(names
);
2226 IDWriteFont_Release(font
);
2228 get_expected_font_metrics(fontface
, &expected_metrics
);
2230 IDWriteFontFace1_GetMetrics(fontface1
, &metrics1
);
2231 check_font_metrics(nameW
, TRUE
, (const DWRITE_FONT_METRICS
*)&metrics1
, &expected_metrics
);
2234 IDWriteFontFace_GetMetrics(fontface
, &metrics
);
2235 check_font_metrics(nameW
, FALSE
, &metrics
, &expected_metrics
);
2239 IDWriteFontFace1_Release(fontface1
);
2240 IDWriteFontFace_Release(fontface
);
2241 IDWriteFontFamily_Release(family
);
2243 IDWriteFontCollection_Release(syscollection
);
2244 ref
= IDWriteFactory_Release(factory
);
2245 ok(ref
== 0, "factory not released, %u\n", ref
);
2248 static void test_system_fontcollection(void)
2250 IDWriteFontCollection
*collection
, *coll2
;
2251 IDWriteLocalFontFileLoader
*localloader
;
2252 IDWriteFontCollection1
*collection1
;
2253 IDWriteFactory
*factory
, *factory2
;
2254 IDWriteFontFileLoader
*loader
;
2255 IDWriteFontFamily
*family
;
2256 IDWriteFontFace
*fontface
;
2257 IDWriteFontFile
*file
;
2264 factory
= create_factory();
2266 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &collection
, FALSE
);
2267 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2269 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &coll2
, FALSE
);
2270 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2271 ok(coll2
== collection
, "got %p, was %p\n", coll2
, collection
);
2272 IDWriteFontCollection_Release(coll2
);
2274 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &coll2
, TRUE
);
2275 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2276 ok(coll2
== collection
, "got %p, was %p\n", coll2
, collection
);
2277 IDWriteFontCollection_Release(coll2
);
2279 factory2
= create_factory();
2280 hr
= IDWriteFactory_GetSystemFontCollection(factory2
, &coll2
, FALSE
);
2281 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2282 ok(coll2
!= collection
, "got %p, was %p\n", coll2
, collection
);
2283 IDWriteFontCollection_Release(coll2
);
2284 IDWriteFactory_Release(factory2
);
2286 i
= IDWriteFontCollection_GetFontFamilyCount(collection
);
2287 ok(i
, "got %u\n", i
);
2290 family
= (void*)0xdeadbeef;
2291 hr
= IDWriteFontCollection_GetFontFamily(collection
, i
, &family
);
2292 ok(hr
== E_FAIL
, "got 0x%08x\n", hr
);
2293 ok(family
== NULL
, "got %p\n", family
);
2297 hr
= IDWriteFontCollection_FindFamilyName(collection
, tahomaW
, &i
, &ret
);
2298 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2299 ok(ret
, "got %d\n", ret
);
2300 ok(i
!= (UINT32
)-1, "got %u\n", i
);
2304 hr
= IDWriteFontCollection_FindFamilyName(collection
, tahomaUppercaseW
, &i
, &ret
);
2305 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2306 ok(ret
, "got %d\n", ret
);
2307 ok(i
!= (UINT32
)-1, "got %u\n", i
);
2311 hr
= IDWriteFontCollection_FindFamilyName(collection
, tahomaStrangecaseW
, &i
, &ret
);
2312 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2313 ok(ret
, "got %d\n", ret
);
2314 ok(i
!= (UINT32
)-1, "got %u\n", i
);
2316 /* get back local file loader */
2317 hr
= IDWriteFontCollection_GetFontFamily(collection
, i
, &family
);
2318 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2320 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
,
2321 DWRITE_FONT_STRETCH_NORMAL
, DWRITE_FONT_STYLE_NORMAL
, &font
);
2322 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2323 IDWriteFontFamily_Release(family
);
2325 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
2326 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2327 IDWriteFont_Release(font
);
2331 hr
= IDWriteFontFace_GetFiles(fontface
, &i
, &file
);
2332 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2333 ok(file
!= NULL
, "got %p\n", file
);
2334 IDWriteFontFace_Release(fontface
);
2336 hr
= IDWriteFontFile_GetLoader(file
, &loader
);
2337 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2338 IDWriteFontFile_Release(file
);
2340 hr
= IDWriteFontFileLoader_QueryInterface(loader
, &IID_IDWriteLocalFontFileLoader
, (void**)&localloader
);
2341 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2342 IDWriteLocalFontFileLoader_Release(localloader
);
2344 /* local loader is not registered by default */
2345 hr
= IDWriteFactory_RegisterFontFileLoader(factory
, loader
);
2346 ok(hr
== S_OK
|| broken(hr
== DWRITE_E_ALREADYREGISTERED
), "got 0x%08x\n", hr
);
2347 hr
= IDWriteFactory_UnregisterFontFileLoader(factory
, loader
);
2348 ok(hr
== S_OK
|| broken(hr
== E_INVALIDARG
), "got 0x%08x\n", hr
);
2350 /* try with a different factory */
2351 factory2
= create_factory();
2352 hr
= IDWriteFactory_RegisterFontFileLoader(factory2
, loader
);
2353 ok(hr
== S_OK
|| broken(hr
== DWRITE_E_ALREADYREGISTERED
), "got 0x%08x\n", hr
);
2354 hr
= IDWriteFactory_RegisterFontFileLoader(factory2
, loader
);
2355 ok(hr
== DWRITE_E_ALREADYREGISTERED
, "got 0x%08x\n", hr
);
2356 hr
= IDWriteFactory_UnregisterFontFileLoader(factory2
, loader
);
2357 ok(hr
== S_OK
|| broken(hr
== E_INVALIDARG
), "got 0x%08x\n", hr
);
2358 hr
= IDWriteFactory_UnregisterFontFileLoader(factory2
, loader
);
2359 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
2360 IDWriteFactory_Release(factory2
);
2362 IDWriteFontFileLoader_Release(loader
);
2366 hr
= IDWriteFontCollection_FindFamilyName(collection
, blahW
, &i
, &ret
);
2367 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2368 ok(!ret
, "got %d\n", ret
);
2369 ok(i
== (UINT32
)-1, "got %u\n", i
);
2371 hr
= IDWriteFontCollection_QueryInterface(collection
, &IID_IDWriteFontCollection1
, (void**)&collection1
);
2373 IDWriteFontSet
*fontset
, *fontset2
;
2374 IDWriteFontFamily1
*family1
;
2375 IDWriteFactory3
*factory3
;
2377 hr
= IDWriteFontCollection1_QueryInterface(collection1
, &IID_IDWriteFontCollection
, (void**)&coll2
);
2378 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2379 ok(coll2
== collection
, "got %p, %p\n", collection
, coll2
);
2380 IDWriteFontCollection_Release(coll2
);
2382 family1
= (void*)0xdeadbeef;
2383 hr
= IDWriteFontCollection1_GetFontFamily(collection1
, ~0u, &family1
);
2384 ok(hr
== E_FAIL
, "got 0x%08x\n", hr
);
2385 ok(family1
== NULL
, "got %p\n", family1
);
2387 hr
= IDWriteFontCollection1_GetFontFamily(collection1
, 0, &family1
);
2388 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2389 IDWriteFontFamily1_Release(family1
);
2391 /* system fontset */
2392 EXPECT_REF(collection1
, 2);
2393 EXPECT_REF(factory
, 2);
2394 hr
= IDWriteFontCollection1_GetFontSet(collection1
, &fontset
);
2396 ok(hr
== S_OK
, "Failed to get fontset, hr %#x.\n", hr
);
2398 EXPECT_REF(collection1
, 2);
2399 EXPECT_REF(factory
, 2);
2400 EXPECT_REF(fontset
, 1);
2402 hr
= IDWriteFontCollection1_GetFontSet(collection1
, &fontset2
);
2403 ok(hr
== S_OK
, "Failed to get fontset, hr %#x.\n", hr
);
2404 ok(fontset
!= fontset2
, "Expected new fontset instance.\n");
2405 EXPECT_REF(fontset2
, 1);
2406 IDWriteFontSet_Release(fontset2
);
2408 hr
= IDWriteFactory_QueryInterface(factory
, &IID_IDWriteFactory3
, (void **)&factory3
);
2409 ok(hr
== S_OK
, "Failed to get IDWriteFactory3 interface, hr %#x.\n", hr
);
2411 EXPECT_REF(factory
, 3);
2412 hr
= IDWriteFactory3_GetSystemFontSet(factory3
, &fontset2
);
2413 ok(hr
== S_OK
, "Failed to get system font set, hr %#x.\n", hr
);
2414 ok(fontset
!= fontset2
, "Expected new fontset instance.\n");
2415 EXPECT_REF(fontset2
, 1);
2416 EXPECT_REF(factory
, 4);
2418 IDWriteFontSet_Release(fontset2
);
2419 IDWriteFontSet_Release(fontset
);
2421 IDWriteFactory3_Release(factory3
);
2423 IDWriteFontCollection1_Release(collection1
);
2426 win_skip("IDWriteFontCollection1 is not supported.\n");
2428 ref
= IDWriteFontCollection_Release(collection
);
2429 ok(ref
== 0, "collection not released, %u\n", ref
);
2430 ref
= IDWriteFactory_Release(factory
);
2431 ok(ref
== 0, "factory not released, %u\n", ref
);
2434 static void get_logfont_from_font(IDWriteFont
*font
, LOGFONTW
*logfont
)
2436 void *os2_context
, *head_context
;
2437 IDWriteLocalizedStrings
*names
;
2438 DWRITE_FONT_SIMULATIONS sim
;
2439 IDWriteFontFace
*fontface
;
2440 const TT_OS2_V2
*tt_os2
;
2441 DWRITE_FONT_STYLE style
;
2442 const TT_HEAD
*tt_head
;
2448 /* These are rendering time properties. */
2449 logfont
->lfHeight
= 0;
2450 logfont
->lfWidth
= 0;
2451 logfont
->lfEscapement
= 0;
2452 logfont
->lfOrientation
= 0;
2453 logfont
->lfUnderline
= 0;
2454 logfont
->lfStrikeOut
= 0;
2456 logfont
->lfWeight
= 0;
2457 logfont
->lfItalic
= 0;
2459 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
2460 ok(hr
== S_OK
, "Failed to create font face, %#x\n", hr
);
2462 hr
= IDWriteFontFace_TryGetFontTable(fontface
, MS_0S2_TAG
, (const void **)&tt_os2
, &size
,
2463 &os2_context
, &exists
);
2464 ok(hr
== S_OK
, "Failed to get OS/2 table, %#x\n", hr
);
2466 hr
= IDWriteFontFace_TryGetFontTable(fontface
, MS_HEAD_TAG
, (const void **)&tt_head
, &size
,
2467 &head_context
, &exists
);
2468 ok(hr
== S_OK
, "Failed to get head table, %#x\n", hr
);
2470 sim
= IDWriteFont_GetSimulations(font
);
2473 weight
= FW_REGULAR
;
2475 USHORT usWeightClass
= GET_BE_WORD(tt_os2
->usWeightClass
);
2477 if (usWeightClass
>= 1 && usWeightClass
<= 9)
2478 usWeightClass
*= 100;
2480 if (usWeightClass
> DWRITE_FONT_WEIGHT_ULTRA_BLACK
)
2481 weight
= DWRITE_FONT_WEIGHT_ULTRA_BLACK
;
2482 else if (usWeightClass
> 0)
2483 weight
= usWeightClass
;
2486 USHORT macStyle
= GET_BE_WORD(tt_head
->macStyle
);
2487 if (macStyle
& TT_HEAD_MACSTYLE_BOLD
)
2488 weight
= DWRITE_FONT_WEIGHT_BOLD
;
2490 if (sim
& DWRITE_FONT_SIMULATIONS_BOLD
)
2491 weight
+= (FW_BOLD
- FW_REGULAR
) / 2 + 1;
2492 logfont
->lfWeight
= weight
;
2495 if (IDWriteFont_GetSimulations(font
) & DWRITE_FONT_SIMULATIONS_OBLIQUE
)
2496 logfont
->lfItalic
= 1;
2498 style
= IDWriteFont_GetStyle(font
);
2499 if (!logfont
->lfItalic
&& ((style
== DWRITE_FONT_STYLE_ITALIC
) || (style
== DWRITE_FONT_STYLE_OBLIQUE
))) {
2501 USHORT fsSelection
= GET_BE_WORD(tt_os2
->fsSelection
);
2502 logfont
->lfItalic
= !!(fsSelection
& OS2_FSSELECTION_ITALIC
);
2505 USHORT macStyle
= GET_BE_WORD(tt_head
->macStyle
);
2506 logfont
->lfItalic
= !!(macStyle
& TT_HEAD_MACSTYLE_ITALIC
);
2512 logfont
->lfFaceName
[0] = 0;
2513 hr
= IDWriteFont_GetInformationalStrings(font
, DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES
, &names
, &exists
);
2514 if (SUCCEEDED(hr
)) {
2516 static const WCHAR enusW
[] = {'e','n','-','u','s',0};
2517 WCHAR localeW
[LOCALE_NAME_MAX_LENGTH
];
2520 /* Fallback to en-us if there's no string for user locale. */
2522 if (GetSystemDefaultLocaleName(localeW
, ARRAY_SIZE(localeW
)))
2523 IDWriteLocalizedStrings_FindLocaleName(names
, localeW
, &index
, &exists
);
2526 IDWriteLocalizedStrings_FindLocaleName(names
, enusW
, &index
, &exists
);
2529 IDWriteLocalizedStrings_GetString(names
, index
, logfont
->lfFaceName
, ARRAY_SIZE(logfont
->lfFaceName
));
2532 IDWriteLocalizedStrings_Release(names
);
2536 IDWriteFontFace_ReleaseFontTable(fontface
, os2_context
);
2538 IDWriteFontFace_ReleaseFontTable(fontface
, head_context
);
2539 IDWriteFontFace_Release(fontface
);
2542 static void test_ConvertFontFaceToLOGFONT(void)
2544 IDWriteFontCollection
*collection
;
2545 IDWriteGdiInterop
*interop
;
2546 IDWriteFontFace
*fontface
;
2547 IDWriteFactory
*factory
;
2553 factory
= create_factory();
2555 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop
);
2556 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2558 if (0) /* crashes on native */
2560 hr
= IDWriteGdiInterop_ConvertFontFaceToLOGFONT(interop
, NULL
, NULL
);
2561 hr
= IDWriteGdiInterop_ConvertFontFaceToLOGFONT(interop
, fontface
, NULL
);
2563 memset(&logfont
, 0xcc, sizeof(logfont
));
2564 hr
= IDWriteGdiInterop_ConvertFontFaceToLOGFONT(interop
, NULL
, &logfont
);
2565 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
2566 ok(logfont
.lfFaceName
[0] == 0, "got face name %s\n", wine_dbgstr_w(logfont
.lfFaceName
));
2568 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &collection
, FALSE
);
2569 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2571 count
= IDWriteFontCollection_GetFontFamilyCount(collection
);
2572 for (i
= 0; i
< count
; i
++) {
2573 WCHAR nameW
[128], familynameW
[64], facenameW
[64];
2574 IDWriteLocalizedStrings
*names
;
2575 DWRITE_FONT_SIMULATIONS sim
;
2576 IDWriteFontFamily
*family
;
2577 UINT32 font_count
, j
;
2581 hr
= IDWriteFontCollection_GetFontFamily(collection
, i
, &family
);
2582 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2584 hr
= IDWriteFontFamily_GetFamilyNames(family
, &names
);
2585 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2587 get_enus_string(names
, familynameW
, ARRAY_SIZE(familynameW
));
2588 IDWriteLocalizedStrings_Release(names
);
2590 font_count
= IDWriteFontFamily_GetFontCount(family
);
2592 for (j
= 0; j
< font_count
; j
++) {
2593 static const WCHAR spaceW
[] = {' ', 0};
2594 IDWriteFontFace
*fontface
;
2596 hr
= IDWriteFontFamily_GetFont(family
, j
, &font
);
2597 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2599 hr
= IDWriteFont_GetFaceNames(font
, &names
);
2600 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2602 get_enus_string(names
, facenameW
, ARRAY_SIZE(facenameW
));
2603 IDWriteLocalizedStrings_Release(names
);
2605 lstrcpyW(nameW
, familynameW
);
2606 lstrcatW(nameW
, spaceW
);
2607 lstrcatW(nameW
, facenameW
);
2609 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
2610 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2612 memset(&logfont
, 0xcc, sizeof(logfont
));
2613 hr
= IDWriteGdiInterop_ConvertFontFaceToLOGFONT(interop
, fontface
, &logfont
);
2614 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2616 sim
= IDWriteFontFace_GetSimulations(fontface
);
2617 get_logfont_from_font(font
, &lf
);
2619 ok(logfont
.lfWeight
== lf
.lfWeight
, "%s: unexpected lfWeight %d, expected lfWeight %d, font weight %d, "
2620 "bold simulation %s\n", wine_dbgstr_w(nameW
), logfont
.lfWeight
, lf
.lfWeight
, IDWriteFont_GetWeight(font
),
2621 sim
& DWRITE_FONT_SIMULATIONS_BOLD
? "yes" : "no");
2622 ok(logfont
.lfItalic
== lf
.lfItalic
, "%s: unexpected italic flag %d, oblique simulation %s\n",
2623 wine_dbgstr_w(nameW
), logfont
.lfItalic
, sim
& DWRITE_FONT_SIMULATIONS_OBLIQUE
? "yes" : "no");
2624 ok(!lstrcmpW(logfont
.lfFaceName
, lf
.lfFaceName
), "%s: unexpected facename %s, expected %s\n",
2625 wine_dbgstr_w(nameW
), wine_dbgstr_w(logfont
.lfFaceName
), wine_dbgstr_w(lf
.lfFaceName
));
2627 ok(logfont
.lfOutPrecision
== OUT_OUTLINE_PRECIS
, "%s: unexpected output precision %d\n", wine_dbgstr_w(nameW
),
2628 logfont
.lfOutPrecision
);
2629 ok(logfont
.lfClipPrecision
== CLIP_DEFAULT_PRECIS
, "%s: unexpected clipping precision %d\n", wine_dbgstr_w(nameW
),
2630 logfont
.lfClipPrecision
);
2631 ok(logfont
.lfQuality
== DEFAULT_QUALITY
, "%s: unexpected quality %d\n", wine_dbgstr_w(nameW
), logfont
.lfQuality
);
2632 ok(logfont
.lfPitchAndFamily
== DEFAULT_PITCH
, "%s: unexpected pitch %d\n", wine_dbgstr_w(nameW
),
2633 logfont
.lfPitchAndFamily
);
2635 IDWriteFontFace_Release(fontface
);
2636 IDWriteFont_Release(font
);
2639 IDWriteFontFamily_Release(family
);
2642 IDWriteFontCollection_Release(collection
);
2643 IDWriteGdiInterop_Release(interop
);
2644 ref
= IDWriteFactory_Release(factory
);
2645 ok(ref
== 0, "factory not released, %u\n", ref
);
2648 static HRESULT WINAPI
fontfileenumerator_QueryInterface(IDWriteFontFileEnumerator
*iface
, REFIID riid
, void **obj
)
2650 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFontFileEnumerator
))
2653 IDWriteFontFileEnumerator_AddRef(iface
);
2656 return E_NOINTERFACE
;
2659 static ULONG WINAPI
fontfileenumerator_AddRef(IDWriteFontFileEnumerator
*iface
)
2664 static ULONG WINAPI
fontfileenumerator_Release(IDWriteFontFileEnumerator
*iface
)
2669 static HRESULT WINAPI
fontfileenumerator_GetCurrentFontFile(IDWriteFontFileEnumerator
*iface
, IDWriteFontFile
**file
)
2675 static HRESULT WINAPI
fontfileenumerator_MoveNext(IDWriteFontFileEnumerator
*iface
, BOOL
*current
)
2681 static const struct IDWriteFontFileEnumeratorVtbl dwritefontfileenumeratorvtbl
=
2683 fontfileenumerator_QueryInterface
,
2684 fontfileenumerator_AddRef
,
2685 fontfileenumerator_Release
,
2686 fontfileenumerator_MoveNext
,
2687 fontfileenumerator_GetCurrentFontFile
,
2690 struct collection_loader
2692 IDWriteFontCollectionLoader IDWriteFontCollectionLoader_iface
;
2696 static inline struct collection_loader
*impl_from_IDWriteFontCollectionLoader(IDWriteFontCollectionLoader
*iface
)
2698 return CONTAINING_RECORD(iface
, struct collection_loader
, IDWriteFontCollectionLoader_iface
);
2701 static HRESULT WINAPI
fontcollectionloader_QueryInterface(IDWriteFontCollectionLoader
*iface
, REFIID riid
, void **obj
)
2703 struct collection_loader
*loader
= impl_from_IDWriteFontCollectionLoader(iface
);
2705 if (IsEqualIID(&IID_IDWriteFontCollectionLoader
, riid
) ||
2706 IsEqualIID(&IID_IUnknown
, riid
))
2708 *obj
= &loader
->IDWriteFontCollectionLoader_iface
;
2709 IDWriteFontCollectionLoader_AddRef(iface
);
2714 return E_NOINTERFACE
;
2717 static ULONG WINAPI
fontcollectionloader_AddRef(IDWriteFontCollectionLoader
*iface
)
2719 struct collection_loader
*loader
= impl_from_IDWriteFontCollectionLoader(iface
);
2720 return InterlockedIncrement(&loader
->ref
);
2723 static ULONG WINAPI
fontcollectionloader_Release(IDWriteFontCollectionLoader
*iface
)
2725 struct collection_loader
*loader
= impl_from_IDWriteFontCollectionLoader(iface
);
2726 ULONG ref
= InterlockedDecrement(&loader
->ref
);
2734 static HRESULT WINAPI
fontcollectionloader_CreateEnumeratorFromKey(IDWriteFontCollectionLoader
*iface
, IDWriteFactory
*factory
, const void *key
,
2735 UINT32 key_size
, IDWriteFontFileEnumerator
**ret
)
2737 static IDWriteFontFileEnumerator enumerator
= { &dwritefontfileenumeratorvtbl
};
2742 static const struct IDWriteFontCollectionLoaderVtbl dwritefontcollectionloadervtbl
= {
2743 fontcollectionloader_QueryInterface
,
2744 fontcollectionloader_AddRef
,
2745 fontcollectionloader_Release
,
2746 fontcollectionloader_CreateEnumeratorFromKey
2749 static IDWriteFontCollectionLoader
*create_collection_loader(void)
2751 struct collection_loader
*loader
= heap_alloc(sizeof(*loader
));
2753 loader
->IDWriteFontCollectionLoader_iface
.lpVtbl
= &dwritefontcollectionloadervtbl
;
2756 return &loader
->IDWriteFontCollectionLoader_iface
;
2759 static void test_CustomFontCollection(void)
2761 static const WCHAR fontnameW
[] = {'w','i','n','e','_','t','e','s','t',0};
2762 IDWriteFontCollectionLoader
*loader
, *loader2
, *loader3
;
2763 IDWriteFontCollection
*font_collection
= NULL
;
2764 static IDWriteFontFileLoader rloader
= { &resourcefontfileloadervtbl
};
2765 struct test_fontcollectionloader resource_collection
= { { &resourcecollectionloadervtbl
}, &rloader
};
2766 IDWriteFontFamily
*family
, *family2
, *family3
;
2767 IDWriteFontFace
*idfontface
, *idfontface2
;
2768 IDWriteFontFile
*fontfile
, *fontfile2
;
2769 IDWriteLocalizedStrings
*string
;
2770 IDWriteFont
*idfont
, *idfont2
;
2771 IDWriteFactory
*factory
;
2772 UINT32 index
, count
;
2778 factory
= create_factory();
2780 loader
= create_collection_loader();
2781 loader2
= create_collection_loader();
2782 loader3
= create_collection_loader();
2784 hr
= IDWriteFactory_RegisterFontCollectionLoader(factory
, NULL
);
2785 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
2787 hr
= IDWriteFactory_UnregisterFontCollectionLoader(factory
, NULL
);
2788 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
2790 EXPECT_REF(loader
, 1);
2791 EXPECT_REF(loader2
, 1);
2793 hr
= IDWriteFactory_RegisterFontCollectionLoader(factory
, loader
);
2794 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2795 hr
= IDWriteFactory_RegisterFontCollectionLoader(factory
, loader2
);
2796 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2797 hr
= IDWriteFactory_RegisterFontCollectionLoader(factory
, loader
);
2798 ok(hr
== DWRITE_E_ALREADYREGISTERED
, "got 0x%08x\n", hr
);
2800 EXPECT_REF(loader
, 2);
2801 EXPECT_REF(loader2
, 2);
2803 hr
= IDWriteFactory_RegisterFontFileLoader(factory
, &rloader
);
2804 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2805 hr
= IDWriteFactory_RegisterFontCollectionLoader(factory
, &resource_collection
.IDWriteFontFileCollectionLoader_iface
);
2806 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2808 /* Loader wasn't registered. */
2809 font_collection
= (void*)0xdeadbeef;
2810 hr
= IDWriteFactory_CreateCustomFontCollection(factory
, loader3
, "Billy", 6, &font_collection
);
2811 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
2812 ok(font_collection
== NULL
, "got %p\n", font_collection
);
2814 EXPECT_REF(factory
, 1);
2815 hr
= IDWriteFactory_CreateCustomFontCollection(factory
, loader
, "Billy", 6, &font_collection
);
2816 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2818 EXPECT_REF(factory
, 1);
2819 EXPECT_REF(loader
, 2);
2820 IDWriteFontCollection_Release(font_collection
);
2822 hr
= IDWriteFactory_CreateCustomFontCollection(factory
, loader2
, "Billy", 6, &font_collection
);
2823 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2824 IDWriteFontCollection_Release(font_collection
);
2826 font_collection
= (void*)0xdeadbeef;
2827 hr
= IDWriteFactory_CreateCustomFontCollection(factory
, (IDWriteFontCollectionLoader
*)0xdeadbeef, "Billy", 6, &font_collection
);
2828 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
2829 ok(font_collection
== NULL
, "got %p\n", font_collection
);
2831 font
= FindResourceA(GetModuleHandleA(NULL
), (LPCSTR
)MAKEINTRESOURCE(1), (LPCSTR
)RT_RCDATA
);
2832 ok(font
!= NULL
, "Failed to find font resource\n");
2834 hr
= IDWriteFactory_CreateCustomFontCollection(factory
, &resource_collection
.IDWriteFontFileCollectionLoader_iface
,
2835 &font
, sizeof(HRSRC
), &font_collection
);
2836 ok(hr
== S_OK
, "got 0x%08x\n",hr
);
2837 EXPECT_REF(font_collection
, 1);
2841 hr
= IDWriteFontCollection_FindFamilyName(font_collection
, fontnameW
, &index
, &exists
);
2842 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2843 ok(index
== 0, "got index %i\n", index
);
2844 ok(exists
, "got exists %i\n", exists
);
2846 count
= IDWriteFontCollection_GetFontFamilyCount(font_collection
);
2847 ok(count
== 1, "got %u\n", count
);
2850 hr
= IDWriteFontCollection_GetFontFamily(font_collection
, 0, &family
);
2851 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2852 EXPECT_REF(family
, 1);
2855 hr
= IDWriteFontCollection_GetFontFamily(font_collection
, 0, &family2
);
2856 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2857 EXPECT_REF(family2
, 1);
2858 ok(family
!= family2
, "got %p, %p\n", family
, family2
);
2860 hr
= IDWriteFontFamily_GetFont(family
, 0, &idfont
);
2861 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2862 EXPECT_REF(idfont
, 1);
2863 EXPECT_REF(family
, 2);
2864 hr
= IDWriteFontFamily_GetFont(family
, 0, &idfont2
);
2865 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2866 EXPECT_REF(idfont2
, 1);
2867 EXPECT_REF(family
, 3);
2868 ok(idfont
!= idfont2
, "got %p, %p\n", idfont
, idfont2
);
2869 IDWriteFont_Release(idfont2
);
2871 hr
= IDWriteFont_GetInformationalStrings(idfont
, DWRITE_INFORMATIONAL_STRING_COPYRIGHT_NOTICE
, &string
, &exists
);
2872 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2873 ok(exists
, "got %d\n", exists
);
2874 EXPECT_REF(string
, 1);
2875 IDWriteLocalizedStrings_Release(string
);
2878 hr
= IDWriteFont_GetFontFamily(idfont
, &family3
);
2879 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2880 EXPECT_REF(family
, 3);
2881 ok(family
== family3
, "got %p, %p\n", family
, family3
);
2882 IDWriteFontFamily_Release(family3
);
2885 hr
= IDWriteFont_CreateFontFace(idfont
, &idfontface
);
2886 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2887 EXPECT_REF(idfont
, 1);
2890 hr
= IDWriteFontFamily_GetFont(family2
, 0, &idfont2
);
2891 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2892 EXPECT_REF(idfont2
, 1);
2893 EXPECT_REF(idfont
, 1);
2894 ok(idfont2
!= idfont
, "Font instances should not match\n");
2897 hr
= IDWriteFont_CreateFontFace(idfont2
, &idfontface2
);
2898 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2899 ok(idfontface2
== idfontface
, "fontfaces should match\n");
2903 hr
= IDWriteFontFace_GetFiles(idfontface
, &index
, &fontfile
);
2904 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2908 hr
= IDWriteFontFace_GetFiles(idfontface2
, &index
, &fontfile2
);
2909 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2910 ok(fontfile
== fontfile2
, "fontfiles should match\n");
2912 IDWriteFont_Release(idfont
);
2913 IDWriteFont_Release(idfont2
);
2914 IDWriteFontFile_Release(fontfile
);
2915 IDWriteFontFile_Release(fontfile2
);
2916 IDWriteFontFace_Release(idfontface
);
2917 IDWriteFontFace_Release(idfontface2
);
2918 IDWriteFontFamily_Release(family2
);
2919 IDWriteFontFamily_Release(family
);
2920 IDWriteFontCollection_Release(font_collection
);
2922 hr
= IDWriteFactory_UnregisterFontCollectionLoader(factory
, loader
);
2923 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2924 hr
= IDWriteFactory_UnregisterFontCollectionLoader(factory
, loader
);
2925 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
2926 hr
= IDWriteFactory_UnregisterFontCollectionLoader(factory
, loader2
);
2927 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2928 hr
= IDWriteFactory_UnregisterFontCollectionLoader(factory
, &resource_collection
.IDWriteFontFileCollectionLoader_iface
);
2929 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2930 hr
= IDWriteFactory_UnregisterFontFileLoader(factory
, &rloader
);
2931 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2933 IDWriteFontCollectionLoader_Release(loader
);
2934 IDWriteFontCollectionLoader_Release(loader2
);
2935 IDWriteFontCollectionLoader_Release(loader3
);
2937 ref
= IDWriteFactory_Release(factory
);
2938 ok(ref
== 0, "factory not released, %u\n", ref
);
2941 static HRESULT WINAPI
fontfileloader_QueryInterface(IDWriteFontFileLoader
*iface
, REFIID riid
, void **obj
)
2943 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFontFileLoader
))
2946 IDWriteFontFileLoader_AddRef(iface
);
2951 return E_NOINTERFACE
;
2954 static ULONG WINAPI
fontfileloader_AddRef(IDWriteFontFileLoader
*iface
)
2959 static ULONG WINAPI
fontfileloader_Release(IDWriteFontFileLoader
*iface
)
2964 static HRESULT WINAPI
fontfileloader_CreateStreamFromKey(IDWriteFontFileLoader
*iface
, const void *ref_key
, UINT32 key_size
,
2965 IDWriteFontFileStream
**stream
)
2970 static const struct IDWriteFontFileLoaderVtbl dwritefontfileloadervtbl
= {
2971 fontfileloader_QueryInterface
,
2972 fontfileloader_AddRef
,
2973 fontfileloader_Release
,
2974 fontfileloader_CreateStreamFromKey
2977 static void test_CreateCustomFontFileReference(void)
2979 IDWriteFontFileLoader floader
= { &dwritefontfileloadervtbl
};
2980 IDWriteFontFileLoader floader2
= { &dwritefontfileloadervtbl
};
2981 IDWriteFontFileLoader floader3
= { &dwritefontfileloadervtbl
};
2982 IDWriteFactory
*factory
, *factory2
;
2983 IDWriteFontFileLoader
*loader
;
2984 IDWriteFontFile
*file
, *file2
;
2986 DWRITE_FONT_FILE_TYPE file_type
;
2987 DWRITE_FONT_FACE_TYPE face_type
;
2989 IDWriteFontFace
*face
, *face2
;
2992 UINT32 codePoints
[1] = {0xa8};
2999 path
= create_testfontfile(test_fontfile
);
3001 factory
= create_factory();
3002 factory2
= create_factory();
3004 if (0) { /* crashes on win10 */
3005 hr
= IDWriteFactory_RegisterFontFileLoader(factory
, NULL
);
3006 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
3008 /* local loader is accepted too */
3009 hr
= IDWriteFactory_CreateFontFileReference(factory
, path
, NULL
, &file
);
3010 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3012 hr
= IDWriteFontFile_GetLoader(file
, &loader
);
3013 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3015 hr
= IDWriteFontFile_GetReferenceKey(file
, &key
, &key_size
);
3016 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3018 hr
= IDWriteFactory_CreateCustomFontFileReference(factory
, key
, key_size
, loader
, &file2
);
3019 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3021 IDWriteFontFile_Release(file2
);
3022 IDWriteFontFile_Release(file
);
3023 IDWriteFontFileLoader_Release(loader
);
3025 hr
= IDWriteFactory_RegisterFontFileLoader(factory
, &floader
);
3026 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3027 hr
= IDWriteFactory_RegisterFontFileLoader(factory
, &floader2
);
3028 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3029 hr
= IDWriteFactory_RegisterFontFileLoader(factory
, &floader
);
3030 ok(hr
== DWRITE_E_ALREADYREGISTERED
, "got 0x%08x\n", hr
);
3031 hr
= IDWriteFactory_RegisterFontFileLoader(factory
, &rloader
);
3032 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3035 hr
= IDWriteFactory_CreateCustomFontFileReference(factory
, "test", 4, &floader
, &file
);
3036 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3037 IDWriteFontFile_Release(file
);
3039 file
= (void*)0xdeadbeef;
3040 hr
= IDWriteFactory_CreateCustomFontFileReference(factory
, "test", 4, &floader3
, &file
);
3041 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
3042 ok(file
== NULL
, "got %p\n", file
);
3044 file
= (void*)0xdeadbeef;
3045 hr
= IDWriteFactory_CreateCustomFontFileReference(factory
, "test", 4, NULL
, &file
);
3046 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
3047 ok(file
== NULL
, "got %p\n", file
);
3050 hr
= IDWriteFactory_CreateCustomFontFileReference(factory
, "test", 4, &floader
, &file
);
3051 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3053 file_type
= DWRITE_FONT_FILE_TYPE_TRUETYPE
;
3054 face_type
= DWRITE_FONT_FACE_TYPE_TRUETYPE
;
3057 hr
= IDWriteFontFile_Analyze(file
, &support
, &file_type
, &face_type
, &count
);
3058 ok(hr
== 0x8faecafe, "got 0x%08x\n", hr
);
3059 ok(support
== FALSE
, "got %i\n", support
);
3060 ok(file_type
== DWRITE_FONT_FILE_TYPE_UNKNOWN
, "got %i\n", file_type
);
3061 ok(face_type
== DWRITE_FONT_FACE_TYPE_UNKNOWN
, "got %i\n", face_type
);
3062 ok(count
== 0, "got %i\n", count
);
3064 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_CFF
, 1, &file
, 0, 0, &face
);
3065 ok(hr
== 0x8faecafe, "got 0x%08x\n", hr
);
3066 IDWriteFontFile_Release(file
);
3068 fontrsrc
= FindResourceA(GetModuleHandleA(NULL
), (LPCSTR
)MAKEINTRESOURCE(1), (LPCSTR
)RT_RCDATA
);
3069 ok(fontrsrc
!= NULL
, "Failed to find font resource\n");
3071 hr
= IDWriteFactory_CreateCustomFontFileReference(factory
, &fontrsrc
, sizeof(HRSRC
), &rloader
, &file
);
3072 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3074 file_type
= DWRITE_FONT_FILE_TYPE_UNKNOWN
;
3075 face_type
= DWRITE_FONT_FACE_TYPE_UNKNOWN
;
3078 hr
= IDWriteFontFile_Analyze(file
, &support
, &file_type
, &face_type
, &count
);
3079 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3080 ok(support
== TRUE
, "got %i\n", support
);
3081 ok(file_type
== DWRITE_FONT_FILE_TYPE_TRUETYPE
, "got %i\n", file_type
);
3082 ok(face_type
== DWRITE_FONT_FACE_TYPE_TRUETYPE
, "got %i\n", face_type
);
3083 ok(count
== 1, "got %i\n", count
);
3086 face
= (void*)0xdeadbeef;
3087 hr
= IDWriteFactory_CreateFontFace(factory
, face_type
, 1, &file
, 1, DWRITE_FONT_SIMULATIONS_NONE
, &face
);
3088 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
3089 ok(face
== NULL
, "got %p\n", face
);
3091 hr
= IDWriteFactory_CreateFontFace(factory
, face_type
, 1, &file
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &face
);
3092 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3094 hr
= IDWriteFactory_CreateFontFace(factory
, face_type
, 1, &file
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &face2
);
3095 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3096 /* fontface instances are reused starting with win7 */
3097 ok(face
== face2
|| broken(face
!= face2
), "got %p, %p\n", face
, face2
);
3098 IDWriteFontFace_Release(face2
);
3100 /* file was created with different factory */
3102 hr
= IDWriteFactory_CreateFontFace(factory2
, face_type
, 1, &file
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &face2
);
3104 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3106 IDWriteFontFace_Release(face2
);
3109 hr
= IDWriteFactory_CreateCustomFontFileReference(factory
, &fontrsrc
, sizeof(HRSRC
), &rloader
, &file2
);
3110 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3111 ok(file
!= file2
, "got %p, %p\n", file
, file2
);
3113 hr
= IDWriteFactory_CreateFontFace(factory
, face_type
, 1, &file2
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &face2
);
3114 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3115 /* fontface instances are reused starting with win7 */
3116 ok(face
== face2
|| broken(face
!= face2
), "got %p, %p\n", face
, face2
);
3117 IDWriteFontFace_Release(face2
);
3118 IDWriteFontFile_Release(file2
);
3120 hr
= IDWriteFontFace_GetGlyphIndices(face
, NULL
, 0, NULL
);
3121 ok(hr
== E_INVALIDARG
|| broken(hr
== S_OK
) /* win8 */, "got 0x%08x\n", hr
);
3123 hr
= IDWriteFontFace_GetGlyphIndices(face
, codePoints
, 0, NULL
);
3124 ok(hr
== E_INVALIDARG
|| broken(hr
== S_OK
) /* win8 */, "got 0x%08x\n", hr
);
3126 hr
= IDWriteFontFace_GetGlyphIndices(face
, codePoints
, 0, indices
);
3127 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3129 hr
= IDWriteFontFace_GetGlyphIndices(face
, NULL
, 0, indices
);
3130 ok(hr
== E_INVALIDARG
|| broken(hr
== S_OK
) /* win8 */, "got 0x%08x\n", hr
);
3132 indices
[0] = indices
[1] = 11;
3133 hr
= IDWriteFontFace_GetGlyphIndices(face
, NULL
, 1, indices
);
3134 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
3135 ok(indices
[0] == 0, "got index %i\n", indices
[0]);
3136 ok(indices
[1] == 11, "got index %i\n", indices
[1]);
3138 if (0) /* crashes on native */
3139 hr
= IDWriteFontFace_GetGlyphIndices(face
, NULL
, 1, NULL
);
3141 hr
= IDWriteFontFace_GetGlyphIndices(face
, codePoints
, 1, indices
);
3142 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3143 ok(indices
[0] == 7, "Unexpected glyph index, %u.\n", indices
[0]);
3144 IDWriteFontFace_Release(face
);
3145 IDWriteFontFile_Release(file
);
3147 hr
= IDWriteFactory_UnregisterFontFileLoader(factory
, &floader
);
3148 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3149 hr
= IDWriteFactory_UnregisterFontFileLoader(factory
, &floader
);
3150 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
3151 hr
= IDWriteFactory_UnregisterFontFileLoader(factory
, &floader2
);
3152 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3153 hr
= IDWriteFactory_UnregisterFontFileLoader(factory
, &rloader
);
3154 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3156 ref
= IDWriteFactory_Release(factory2
);
3157 ok(ref
== 0, "factory not released, %u\n", ref
);
3158 ref
= IDWriteFactory_Release(factory
);
3159 ok(ref
== 0, "factory not released, %u\n", ref
);
3160 DELETE_FONTFILE(path
);
3163 static void test_CreateFontFileReference(void)
3166 IDWriteFontFile
*ffile
= NULL
;
3168 DWRITE_FONT_FILE_TYPE type
;
3169 DWRITE_FONT_FACE_TYPE face
;
3171 IDWriteFontFace
*fface
= NULL
;
3172 IDWriteFactory
*factory
;
3176 path
= create_testfontfile(test_fontfile
);
3177 factory
= create_factory();
3179 ffile
= (void*)0xdeadbeef;
3180 hr
= IDWriteFactory_CreateFontFileReference(factory
, NULL
, NULL
, &ffile
);
3181 ok(hr
== E_INVALIDARG
, "got 0x%08x\n",hr
);
3182 ok(ffile
== NULL
, "got %p\n", ffile
);
3184 hr
= IDWriteFactory_CreateFontFileReference(factory
, path
, NULL
, &ffile
);
3185 ok(hr
== S_OK
, "got 0x%08x\n",hr
);
3188 type
= DWRITE_FONT_FILE_TYPE_UNKNOWN
;
3189 face
= DWRITE_FONT_FACE_TYPE_CFF
;
3191 hr
= IDWriteFontFile_Analyze(ffile
, &support
, &type
, &face
, &count
);
3192 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3193 ok(support
== TRUE
, "got %i\n", support
);
3194 ok(type
== DWRITE_FONT_FILE_TYPE_TRUETYPE
, "got %i\n", type
);
3195 ok(face
== DWRITE_FONT_FACE_TYPE_TRUETYPE
, "got %i\n", face
);
3196 ok(count
== 1, "got %i\n", count
);
3198 hr
= IDWriteFactory_CreateFontFace(factory
, face
, 1, &ffile
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &fface
);
3199 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3201 IDWriteFontFace_Release(fface
);
3202 IDWriteFontFile_Release(ffile
);
3203 ref
= IDWriteFactory_Release(factory
);
3204 ok(ref
== 0, "factory not released, %u\n", ref
);
3206 DELETE_FONTFILE(path
);
3209 static void test_shared_isolated(void)
3211 IDWriteFactory
*isolated
, *isolated2
;
3212 IDWriteFactory
*shared
, *shared2
;
3218 hr
= DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED
+1, &IID_IDWriteFactory
, (IUnknown
**)&shared
);
3219 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3220 ok(shared
!= NULL
, "got %p\n", shared
);
3221 IDWriteFactory_Release(shared
);
3223 hr
= DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED
, &IID_IDWriteFactory
, (IUnknown
**)&shared
);
3224 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3226 hr
= DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED
, &IID_IDWriteFactory
, (IUnknown
**)&shared2
);
3227 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3228 ok(shared
== shared2
, "got %p, and %p\n", shared
, shared2
);
3229 IDWriteFactory_Release(shared2
);
3231 hr
= DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED
, &IID_IUnknown
, (IUnknown
**)&shared2
);
3232 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3233 ok(shared
== shared2
, "got %p, and %p\n", shared
, shared2
);
3235 IDWriteFactory_Release(shared
);
3236 IDWriteFactory_Release(shared2
);
3238 /* we got 2 references, released 2 - still same pointer is returned */
3239 hr
= DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED
, &IID_IDWriteFactory
, (IUnknown
**)&shared2
);
3240 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3241 ok(shared
== shared2
, "got %p, and %p\n", shared
, shared2
);
3242 IDWriteFactory_Release(shared2
);
3244 hr
= DWriteCreateFactory(DWRITE_FACTORY_TYPE_ISOLATED
, &IID_IDWriteFactory
, (IUnknown
**)&isolated
);
3245 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3247 hr
= DWriteCreateFactory(DWRITE_FACTORY_TYPE_ISOLATED
, &IID_IDWriteFactory
, (IUnknown
**)&isolated2
);
3248 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3249 ok(isolated
!= isolated2
, "got %p, and %p\n", isolated
, isolated2
);
3250 IDWriteFactory_Release(isolated2
);
3252 hr
= DWriteCreateFactory(DWRITE_FACTORY_TYPE_ISOLATED
, &IID_IUnknown
, (IUnknown
**)&isolated2
);
3253 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3254 IDWriteFactory_Release(isolated2
);
3256 hr
= DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED
+1, &IID_IDWriteFactory
, (IUnknown
**)&isolated2
);
3257 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3258 ok(shared
!= isolated2
, "got %p, and %p\n", shared
, isolated2
);
3260 ref
= IDWriteFactory_Release(isolated
);
3261 ok(ref
== 0, "factory not released, %u\n", ref
);
3262 ref
= IDWriteFactory_Release(isolated2
);
3263 ok(ref
== 0, "factory not released, %u\n", ref
);
3266 static void test_GetUnicodeRanges(void)
3268 DWRITE_UNICODE_RANGE
*ranges
, r
;
3269 IDWriteFontFile
*ffile
= NULL
;
3270 IDWriteFontFace1
*fontface1
;
3271 IDWriteFontFace
*fontface
;
3272 IDWriteFactory
*factory
;
3278 factory
= create_factory();
3280 hr
= IDWriteFactory_RegisterFontFileLoader(factory
, &rloader
);
3281 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3283 font
= FindResourceA(GetModuleHandleA(NULL
), (LPCSTR
)MAKEINTRESOURCE(1), (LPCSTR
)RT_RCDATA
);
3284 ok(font
!= NULL
, "Failed to find font resource\n");
3286 hr
= IDWriteFactory_CreateCustomFontFileReference(factory
, &font
, sizeof(HRSRC
), &rloader
, &ffile
);
3287 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3289 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_TRUETYPE
, 1, &ffile
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &fontface
);
3290 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3291 IDWriteFontFile_Release(ffile
);
3293 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void**)&fontface1
);
3294 IDWriteFontFace_Release(fontface
);
3296 win_skip("GetUnicodeRanges() is not supported.\n");
3297 IDWriteFactory_Release(factory
);
3302 hr
= IDWriteFontFace1_GetUnicodeRanges(fontface1
, 0, NULL
, &count
);
3303 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
3304 ok(count
> 0, "got %u\n", count
);
3307 hr
= IDWriteFontFace1_GetUnicodeRanges(fontface1
, 1, NULL
, &count
);
3308 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
3309 ok(count
== 0, "got %u\n", count
);
3312 hr
= IDWriteFontFace1_GetUnicodeRanges(fontface1
, 1, &r
, &count
);
3313 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
3314 ok(count
> 1, "got %u\n", count
);
3316 ranges
= heap_alloc(count
*sizeof(DWRITE_UNICODE_RANGE
));
3317 hr
= IDWriteFontFace1_GetUnicodeRanges(fontface1
, count
, ranges
, &count
);
3318 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3320 ranges
[0].first
= ranges
[0].last
= 0;
3321 hr
= IDWriteFontFace1_GetUnicodeRanges(fontface1
, 1, ranges
, &count
);
3322 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
3323 ok(ranges
[0].first
!= 0 && ranges
[0].last
!= 0, "got 0x%x-0x%0x\n", ranges
[0].first
, ranges
[0].last
);
3327 hr
= IDWriteFactory_UnregisterFontFileLoader(factory
, &rloader
);
3328 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3330 IDWriteFontFace1_Release(fontface1
);
3331 ref
= IDWriteFactory_Release(factory
);
3332 ok(ref
== 0, "factory not released, %u\n", ref
);
3335 static void test_GetFontFromFontFace(void)
3337 IDWriteFontFace
*fontface
, *fontface2
;
3338 IDWriteFontCollection
*collection
;
3339 IDWriteFont
*font
, *font2
, *font3
;
3340 IDWriteFontFamily
*family
;
3341 IDWriteFactory
*factory
;
3342 IDWriteFontFile
*file
;
3347 factory
= create_factory();
3349 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &collection
, FALSE
);
3350 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3352 hr
= IDWriteFontCollection_GetFontFamily(collection
, 0, &family
);
3353 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3355 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
,
3356 DWRITE_FONT_STRETCH_NORMAL
, DWRITE_FONT_STYLE_NORMAL
, &font
);
3357 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3359 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
3360 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3363 hr
= IDWriteFontCollection_GetFontFromFontFace(collection
, fontface
, &font2
);
3364 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3365 ok(font2
!= font
, "got %p, %p\n", font2
, font
);
3368 hr
= IDWriteFontCollection_GetFontFromFontFace(collection
, fontface
, &font3
);
3369 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3370 ok(font3
!= font
&& font3
!= font2
, "got %p, %p, %p\n", font3
, font2
, font
);
3372 hr
= IDWriteFont_CreateFontFace(font2
, &fontface2
);
3373 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3374 ok(fontface2
== fontface
, "got %p, %p\n", fontface2
, fontface
);
3375 IDWriteFontFace_Release(fontface2
);
3377 hr
= IDWriteFont_CreateFontFace(font3
, &fontface2
);
3378 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3379 ok(fontface2
== fontface
, "got %p, %p\n", fontface2
, fontface
);
3380 IDWriteFontFace_Release(fontface2
);
3381 IDWriteFontFace_Release(fontface
);
3382 IDWriteFont_Release(font3
);
3383 IDWriteFactory_Release(factory
);
3385 /* fontface that wasn't created from this collection */
3386 factory
= create_factory();
3387 path
= create_testfontfile(test_fontfile
);
3389 hr
= IDWriteFactory_CreateFontFileReference(factory
, path
, NULL
, &file
);
3390 ok(hr
== S_OK
, "got 0x%08x\n",hr
);
3392 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_TRUETYPE
, 1, &file
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &fontface
);
3393 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3394 IDWriteFontFile_Release(file
);
3396 hr
= IDWriteFontCollection_GetFontFromFontFace(collection
, fontface
, &font3
);
3397 ok(hr
== DWRITE_E_NOFONT
, "got 0x%08x\n", hr
);
3398 ok(font3
== NULL
, "got %p\n", font3
);
3399 IDWriteFontFace_Release(fontface
);
3401 IDWriteFont_Release(font
);
3402 IDWriteFont_Release(font2
);
3403 IDWriteFontFamily_Release(family
);
3404 IDWriteFontCollection_Release(collection
);
3405 ref
= IDWriteFactory_Release(factory
);
3406 ok(ref
== 0, "factory not released, %u\n", ref
);
3407 DELETE_FONTFILE(path
);
3410 static void test_GetFirstMatchingFont(void)
3412 DWRITE_FONT_SIMULATIONS simulations
;
3413 IDWriteFontCollection
*collection
;
3414 IDWriteFontFamily
*family
;
3415 IDWriteFont
*font
, *font2
;
3416 IDWriteFactory
*factory
;
3420 factory
= create_factory();
3422 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &collection
, FALSE
);
3423 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3425 hr
= IDWriteFontCollection_GetFontFamily(collection
, 0, &family
);
3426 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3428 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
,
3429 DWRITE_FONT_STRETCH_NORMAL
, DWRITE_FONT_STYLE_NORMAL
, &font
);
3430 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3432 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
,
3433 DWRITE_FONT_STRETCH_NORMAL
, DWRITE_FONT_STYLE_NORMAL
, &font2
);
3434 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3435 ok(font
!= font2
, "got %p, %p\n", font
, font2
);
3436 IDWriteFont_Release(font
);
3437 IDWriteFont_Release(font2
);
3439 /* out-of-range font props are allowed */
3440 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, 1000, DWRITE_FONT_STRETCH_NORMAL
, DWRITE_FONT_STYLE_NORMAL
, &font
);
3441 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3442 IDWriteFont_Release(font
);
3444 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
, 10, DWRITE_FONT_STYLE_NORMAL
, &font
);
3445 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3446 IDWriteFont_Release(font
);
3448 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STRETCH_NORMAL
,
3450 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3451 IDWriteFont_Release(font
);
3453 IDWriteFontFamily_Release(family
);
3455 font
= get_tahoma_instance(factory
, DWRITE_FONT_STYLE_ITALIC
);
3456 simulations
= IDWriteFont_GetSimulations(font
);
3457 ok(simulations
== DWRITE_FONT_SIMULATIONS_OBLIQUE
, "%d\n", simulations
);
3458 IDWriteFont_Release(font
);
3460 IDWriteFontCollection_Release(collection
);
3461 ref
= IDWriteFactory_Release(factory
);
3462 ok(ref
== 0, "factory not released, %u\n", ref
);
3465 static void test_GetMatchingFonts(void)
3467 IDWriteFontCollection
*collection
;
3468 IDWriteFontFamily
*family
;
3469 IDWriteFactory
*factory
;
3470 IDWriteFontList
*fontlist
, *fontlist2
;
3471 IDWriteFontList1
*fontlist1
;
3475 factory
= create_factory();
3477 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &collection
, FALSE
);
3478 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3480 hr
= IDWriteFontCollection_GetFontFamily(collection
, 0, &family
);
3481 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3483 /* out-of-range font props are allowed */
3484 hr
= IDWriteFontFamily_GetMatchingFonts(family
, 1000, DWRITE_FONT_STRETCH_NORMAL
,
3485 DWRITE_FONT_STYLE_NORMAL
, &fontlist
);
3486 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3487 IDWriteFontList_Release(fontlist
);
3489 hr
= IDWriteFontFamily_GetMatchingFonts(family
, DWRITE_FONT_WEIGHT_NORMAL
, 10,
3490 DWRITE_FONT_STYLE_NORMAL
, &fontlist
);
3491 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3492 IDWriteFontList_Release(fontlist
);
3494 hr
= IDWriteFontFamily_GetMatchingFonts(family
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STRETCH_NORMAL
,
3496 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3497 IDWriteFontList_Release(fontlist
);
3499 hr
= IDWriteFontFamily_GetMatchingFonts(family
, DWRITE_FONT_WEIGHT_NORMAL
,
3500 DWRITE_FONT_STRETCH_NORMAL
, DWRITE_FONT_STYLE_NORMAL
, &fontlist
);
3501 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3503 hr
= IDWriteFontFamily_GetMatchingFonts(family
, DWRITE_FONT_WEIGHT_NORMAL
,
3504 DWRITE_FONT_STRETCH_NORMAL
, DWRITE_FONT_STYLE_NORMAL
, &fontlist2
);
3505 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3506 ok(fontlist
!= fontlist2
, "got %p, %p\n", fontlist
, fontlist2
);
3507 IDWriteFontList_Release(fontlist2
);
3509 hr
= IDWriteFontList_QueryInterface(fontlist
, &IID_IDWriteFontList1
, (void**)&fontlist1
);
3511 IDWriteFontFaceReference
*ref
, *ref1
;
3515 count
= IDWriteFontList1_GetFontCount(fontlist1
);
3516 ok(count
> 0, "got %u\n", count
);
3518 font
= (void*)0xdeadbeef;
3519 hr
= IDWriteFontList1_GetFont(fontlist1
, ~0u, &font
);
3520 ok(hr
== E_FAIL
, "got 0x%08x\n", hr
);
3521 ok(font
== NULL
, "got %p\n", font
);
3523 font
= (void*)0xdeadbeef;
3524 hr
= IDWriteFontList1_GetFont(fontlist1
, count
, &font
);
3525 ok(hr
== E_FAIL
, "got 0x%08x\n", hr
);
3526 ok(font
== NULL
, "got %p\n", font
);
3528 hr
= IDWriteFontList1_GetFont(fontlist1
, 0, &font
);
3529 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3530 IDWriteFont3_Release(font
);
3532 hr
= IDWriteFontList1_GetFontFaceReference(fontlist1
, 0, &ref
);
3533 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3535 hr
= IDWriteFontList1_GetFontFaceReference(fontlist1
, 0, &ref1
);
3536 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3537 ok(ref
!= ref1
, "got %p, %p\n", ref
, ref1
);
3539 IDWriteFontFaceReference_Release(ref1
);
3540 IDWriteFontFaceReference_Release(ref
);
3541 IDWriteFontList1_Release(fontlist1
);
3544 win_skip("IDWriteFontList1 is not supported.\n");
3546 IDWriteFontList_Release(fontlist
);
3547 IDWriteFontFamily_Release(family
);
3549 IDWriteFontCollection_Release(collection
);
3550 ref
= IDWriteFactory_Release(factory
);
3551 ok(ref
== 0, "factory not released, %u\n", ref
);
3554 static void test_GetInformationalStrings(void)
3556 IDWriteLocalizedStrings
*strings
, *strings2
;
3557 IDWriteFontCollection
*collection
;
3558 IDWriteFontFamily
*family
;
3559 IDWriteFactory
*factory
;
3565 factory
= create_factory();
3567 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &collection
, FALSE
);
3568 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3570 hr
= IDWriteFontCollection_GetFontFamily(collection
, 0, &family
);
3571 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3573 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
,
3574 DWRITE_FONT_STRETCH_NORMAL
, DWRITE_FONT_STYLE_NORMAL
, &font
);
3575 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3578 strings
= (void*)0xdeadbeef;
3579 hr
= IDWriteFont_GetInformationalStrings(font
, DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_CID_NAME
+1, &strings
, &exists
);
3580 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3581 ok(exists
== FALSE
, "got %d\n", exists
);
3582 ok(strings
== NULL
, "got %p\n", strings
);
3586 hr
= IDWriteFont_GetInformationalStrings(font
, DWRITE_INFORMATIONAL_STRING_NONE
, &strings
, &exists
);
3587 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3588 ok(exists
== FALSE
, "got %d\n", exists
);
3592 hr
= IDWriteFont_GetInformationalStrings(font
, DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES
, &strings
, &exists
);
3593 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3594 ok(exists
== TRUE
, "got %d\n", exists
);
3596 /* strings instance is not reused */
3598 hr
= IDWriteFont_GetInformationalStrings(font
, DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES
, &strings2
, &exists
);
3599 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3600 ok(strings2
!= strings
, "got %p, %p\n", strings2
, strings
);
3602 IDWriteLocalizedStrings_Release(strings
);
3603 IDWriteLocalizedStrings_Release(strings2
);
3604 IDWriteFont_Release(font
);
3605 IDWriteFontFamily_Release(family
);
3606 IDWriteFontCollection_Release(collection
);
3607 ref
= IDWriteFactory_Release(factory
);
3608 ok(ref
== 0, "factory not released, %u\n", ref
);
3611 static void test_GetGdiInterop(void)
3613 IDWriteGdiInterop
*interop
, *interop2
;
3614 IDWriteFactory
*factory
, *factory2
;
3620 factory
= create_factory();
3623 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop
);
3624 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3627 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop2
);
3628 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3629 ok(interop
== interop2
, "got %p, %p\n", interop
, interop2
);
3630 IDWriteGdiInterop_Release(interop2
);
3632 hr
= DWriteCreateFactory(DWRITE_FACTORY_TYPE_ISOLATED
, &IID_IDWriteFactory
, (IUnknown
**)&factory2
);
3633 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3635 /* each factory gets its own interop */
3637 hr
= IDWriteFactory_GetGdiInterop(factory2
, &interop2
);
3638 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3639 ok(interop
!= interop2
, "got %p, %p\n", interop
, interop2
);
3641 /* release factory - interop still works */
3642 IDWriteFactory_Release(factory2
);
3644 memset(&logfont
, 0, sizeof(logfont
));
3645 logfont
.lfHeight
= 12;
3646 logfont
.lfWidth
= 12;
3647 logfont
.lfWeight
= FW_NORMAL
;
3648 logfont
.lfItalic
= 1;
3649 lstrcpyW(logfont
.lfFaceName
, tahomaW
);
3651 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop2
, &logfont
, &font
);
3652 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3653 IDWriteFont_Release(font
);
3655 IDWriteGdiInterop_Release(interop2
);
3656 IDWriteGdiInterop_Release(interop
);
3657 ref
= IDWriteFactory_Release(factory
);
3658 ok(ref
== 0, "factory not released, %u\n", ref
);
3661 static void test_CreateFontFaceFromHdc(void)
3663 IDWriteGdiInterop
*interop
;
3664 IDWriteFontFace
*fontface
;
3665 IDWriteFactory
*factory
;
3666 HFONT hfont
, oldhfont
;
3673 factory
= create_factory();
3676 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop
);
3677 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3680 fontface
= (void*)0xdeadbeef;
3681 hr
= IDWriteGdiInterop_CreateFontFaceFromHdc(interop
, NULL
, &fontface
);
3682 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
3683 ok(fontface
== NULL
, "got %p\n", fontface
);
3685 fontface
= (void *)0xdeadbeef;
3686 hr
= IDWriteGdiInterop_CreateFontFaceFromHdc(interop
, (HDC
)0xdeadbeef, &fontface
);
3687 ok(hr
== E_FAIL
, "got 0x%08x\n", hr
);
3688 ok(fontface
== NULL
, "got %p\n", fontface
);
3690 memset(&logfont
, 0, sizeof(logfont
));
3691 logfont
.lfHeight
= 12;
3692 logfont
.lfWidth
= 12;
3693 logfont
.lfWeight
= FW_NORMAL
;
3694 logfont
.lfItalic
= 1;
3695 lstrcpyW(logfont
.lfFaceName
, tahomaW
);
3697 hfont
= CreateFontIndirectW(&logfont
);
3698 hdc
= CreateCompatibleDC(0);
3699 oldhfont
= SelectObject(hdc
, hfont
);
3702 hr
= IDWriteGdiInterop_CreateFontFaceFromHdc(interop
, hdc
, &fontface
);
3703 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3704 IDWriteFontFace_Release(fontface
);
3705 DeleteObject(SelectObject(hdc
, oldhfont
));
3707 /* Select bitmap font MS Sans Serif, format that's not supported by DirectWrite. */
3708 memset(&lf
, 0, sizeof(lf
));
3710 strcpy(lf
.lfFaceName
, "MS Sans Serif");
3712 hfont
= CreateFontIndirectA(&lf
);
3713 oldhfont
= SelectObject(hdc
, hfont
);
3715 fontface
= (void *)0xdeadbeef;
3716 hr
= IDWriteGdiInterop_CreateFontFaceFromHdc(interop
, hdc
, &fontface
);
3717 ok(hr
== DWRITE_E_FILEFORMAT
|| broken(hr
== E_FAIL
) /* Vista */, "got 0x%08x\n", hr
);
3718 ok(fontface
== NULL
, "got %p\n", fontface
);
3720 DeleteObject(SelectObject(hdc
, oldhfont
));
3723 IDWriteGdiInterop_Release(interop
);
3724 ref
= IDWriteFactory_Release(factory
);
3725 ok(ref
== 0, "factory not released, %u\n", ref
);
3728 static void test_GetSimulations(void)
3730 DWRITE_FONT_SIMULATIONS simulations
;
3731 IDWriteGdiInterop
*interop
;
3732 IDWriteFontFace
*fontface
;
3733 IDWriteFactory
*factory
;
3739 factory
= create_factory();
3741 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop
);
3742 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3744 memset(&logfont
, 0, sizeof(logfont
));
3745 logfont
.lfHeight
= 12;
3746 logfont
.lfWidth
= 12;
3747 logfont
.lfWeight
= FW_NORMAL
;
3748 logfont
.lfItalic
= 1;
3749 lstrcpyW(logfont
.lfFaceName
, tahomaW
);
3751 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font
);
3752 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3754 simulations
= IDWriteFont_GetSimulations(font
);
3755 ok(simulations
== DWRITE_FONT_SIMULATIONS_OBLIQUE
, "got %d\n", simulations
);
3756 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
3757 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3758 simulations
= IDWriteFontFace_GetSimulations(fontface
);
3759 ok(simulations
== DWRITE_FONT_SIMULATIONS_OBLIQUE
, "got %d\n", simulations
);
3760 IDWriteFontFace_Release(fontface
);
3761 IDWriteFont_Release(font
);
3763 memset(&logfont
, 0, sizeof(logfont
));
3764 logfont
.lfHeight
= 12;
3765 logfont
.lfWidth
= 12;
3766 logfont
.lfWeight
= FW_NORMAL
;
3767 logfont
.lfItalic
= 0;
3768 lstrcpyW(logfont
.lfFaceName
, tahomaW
);
3770 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font
);
3771 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3773 simulations
= IDWriteFont_GetSimulations(font
);
3774 ok(simulations
== DWRITE_FONT_SIMULATIONS_NONE
, "got %d\n", simulations
);
3775 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
3776 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3777 simulations
= IDWriteFontFace_GetSimulations(fontface
);
3778 ok(simulations
== DWRITE_FONT_SIMULATIONS_NONE
, "got %d\n", simulations
);
3779 IDWriteFontFace_Release(fontface
);
3780 IDWriteFont_Release(font
);
3782 IDWriteGdiInterop_Release(interop
);
3783 ref
= IDWriteFactory_Release(factory
);
3784 ok(ref
== 0, "factory not released, %u\n", ref
);
3787 static void test_GetFaceNames(void)
3789 static const WCHAR obliqueW
[] = {'O','b','l','i','q','u','e',0};
3790 static const WCHAR enus2W
[] = {'e','n','-','U','s',0};
3791 static const WCHAR enusW
[] = {'e','n','-','u','s',0};
3792 IDWriteLocalizedStrings
*strings
, *strings2
;
3793 IDWriteGdiInterop
*interop
;
3794 IDWriteFactory
*factory
;
3795 UINT32 count
, index
;
3803 factory
= create_factory();
3805 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop
);
3806 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3808 memset(&logfont
, 0, sizeof(logfont
));
3809 logfont
.lfHeight
= 12;
3810 logfont
.lfWidth
= 12;
3811 logfont
.lfWeight
= FW_NORMAL
;
3812 logfont
.lfItalic
= 1;
3813 lstrcpyW(logfont
.lfFaceName
, tahomaW
);
3815 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(interop
, &logfont
, &font
);
3816 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3818 hr
= IDWriteFont_GetFaceNames(font
, &strings
);
3819 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3821 hr
= IDWriteFont_GetFaceNames(font
, &strings2
);
3822 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3823 ok(strings
!= strings2
, "got %p, %p\n", strings2
, strings
);
3824 IDWriteLocalizedStrings_Release(strings2
);
3826 count
= IDWriteLocalizedStrings_GetCount(strings
);
3827 ok(count
== 1, "got %d\n", count
);
3831 hr
= IDWriteLocalizedStrings_FindLocaleName(strings
, enus2W
, &index
, &exists
);
3832 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3833 ok(index
== 0 && exists
, "got %d, %d\n", index
, exists
);
3836 hr
= IDWriteLocalizedStrings_GetLocaleNameLength(strings
, 1, &count
);
3837 ok(hr
== E_FAIL
, "got 0x%08x\n", hr
);
3838 ok(count
== ~0, "got %d\n", count
);
3840 /* for simulated faces names are also simulated */
3842 hr
= IDWriteLocalizedStrings_GetLocaleName(strings
, 0, buffW
, ARRAY_SIZE(buffW
));
3843 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3844 ok(!lstrcmpW(buffW
, enusW
), "got %s\n", wine_dbgstr_w(buffW
));
3847 hr
= IDWriteLocalizedStrings_GetString(strings
, 0, buffW
, ARRAY_SIZE(buffW
));
3848 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3849 ok(!lstrcmpW(buffW
, obliqueW
), "got %s\n", wine_dbgstr_w(buffW
));
3850 IDWriteLocalizedStrings_Release(strings
);
3852 IDWriteFont_Release(font
);
3853 IDWriteGdiInterop_Release(interop
);
3854 ref
= IDWriteFactory_Release(factory
);
3855 ok(ref
== 0, "factory not released, %u\n", ref
);
3864 static void test_TryGetFontTable(void)
3866 IDWriteLocalFontFileLoader
*localloader
;
3867 WIN32_FILE_ATTRIBUTE_DATA info
;
3868 const struct local_refkey
*key
;
3869 IDWriteFontFileLoader
*loader
;
3870 const void *table
, *table2
;
3871 IDWriteFontFace
*fontface
;
3872 void *context
, *context2
;
3873 IDWriteFactory
*factory
;
3874 IDWriteFontFile
*file
;
3875 WCHAR buffW
[MAX_PATH
];
3882 path
= create_testfontfile(test_fontfile
);
3884 factory
= create_factory();
3886 hr
= IDWriteFactory_CreateFontFileReference(factory
, path
, NULL
, &file
);
3887 ok(hr
== S_OK
, "got 0x%08x\n",hr
);
3891 hr
= IDWriteFontFile_GetReferenceKey(file
, (const void**)&key
, &size
);
3892 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3893 ok(size
!= 0, "got %u\n", size
);
3895 ret
= GetFileAttributesExW(path
, GetFileExInfoStandard
, &info
);
3896 ok(ret
, "got %d\n", ret
);
3897 ok(!memcmp(&info
.ftLastWriteTime
, &key
->writetime
, sizeof(key
->writetime
)), "got wrong write time\n");
3899 hr
= IDWriteFontFile_GetLoader(file
, &loader
);
3900 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3901 IDWriteFontFileLoader_QueryInterface(loader
, &IID_IDWriteLocalFontFileLoader
, (void**)&localloader
);
3902 IDWriteFontFileLoader_Release(loader
);
3904 hr
= IDWriteLocalFontFileLoader_GetFilePathLengthFromKey(localloader
, key
, size
, &len
);
3905 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3906 ok(lstrlenW(key
->name
) == len
, "path length %d\n", len
);
3908 hr
= IDWriteLocalFontFileLoader_GetFilePathFromKey(localloader
, key
, size
, buffW
, ARRAY_SIZE(buffW
));
3909 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3910 ok(!lstrcmpW(buffW
, key
->name
), "got %s, expected %s\n", wine_dbgstr_w(buffW
), wine_dbgstr_w(key
->name
));
3911 IDWriteLocalFontFileLoader_Release(localloader
);
3913 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_TRUETYPE
, 1, &file
, 0, 0, &fontface
);
3914 ok(hr
== S_OK
, "got 0x%08x\n",hr
);
3917 context
= (void*)0xdeadbeef;
3919 hr
= IDWriteFontFace_TryGetFontTable(fontface
, MS_CMAP_TAG
, &table
, &size
, &context
, &exists
);
3920 ok(hr
== S_OK
, "got 0x%08x\n",hr
);
3921 ok(exists
== TRUE
, "got %d\n", exists
);
3922 ok(context
== NULL
&& table
!= NULL
, "cmap: context %p, table %p\n", context
, table
);
3925 context2
= (void*)0xdeadbeef;
3927 hr
= IDWriteFontFace_TryGetFontTable(fontface
, MS_CMAP_TAG
, &table2
, &size
, &context2
, &exists
);
3928 ok(hr
== S_OK
, "got 0x%08x\n",hr
);
3929 ok(exists
== TRUE
, "got %d\n", exists
);
3930 ok(context2
== context
&& table2
== table
, "cmap: context2 %p, table2 %p\n", context2
, table2
);
3932 IDWriteFontFace_ReleaseFontTable(fontface
, context2
);
3933 IDWriteFontFace_ReleaseFontTable(fontface
, context
);
3935 /* table does not exist */
3937 context
= (void*)0xdeadbeef;
3938 table
= (void*)0xdeadbeef;
3939 hr
= IDWriteFontFace_TryGetFontTable(fontface
, 0xabababab, &table
, &size
, &context
, &exists
);
3940 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3941 ok(exists
== FALSE
, "got %d\n", exists
);
3942 ok(context
== NULL
&& table
== NULL
, "got context %p, table pointer %p\n", context
, table
);
3944 IDWriteFontFace_Release(fontface
);
3945 IDWriteFontFile_Release(file
);
3946 ref
= IDWriteFactory_Release(factory
);
3947 ok(ref
== 0, "factory not released, %u\n", ref
);
3948 DELETE_FONTFILE(path
);
3951 static void test_ConvertFontToLOGFONT(void)
3953 IDWriteFactory
*factory
, *factory2
;
3954 IDWriteFontCollection
*collection
;
3955 IDWriteGdiInterop
*interop
;
3956 IDWriteFontFamily
*family
;
3964 factory
= create_factory();
3965 factory2
= create_factory();
3968 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop
);
3969 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3971 hr
= IDWriteFactory_GetSystemFontCollection(factory2
, &collection
, FALSE
);
3972 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3974 hr
= IDWriteFontCollection_GetFontFamily(collection
, 0, &family
);
3975 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3977 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
,
3978 DWRITE_FONT_STRETCH_NORMAL
, DWRITE_FONT_STYLE_NORMAL
, &font
);
3979 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3981 if (0) { /* crashes on native */
3982 IDWriteGdiInterop_ConvertFontToLOGFONT(interop
, NULL
, NULL
, NULL
);
3983 IDWriteGdiInterop_ConvertFontToLOGFONT(interop
, NULL
, &logfont
, NULL
);
3984 IDWriteGdiInterop_ConvertFontToLOGFONT(interop
, font
, NULL
, &system
);
3987 memset(&logfont
, 0xcc, sizeof(logfont
));
3989 hr
= IDWriteGdiInterop_ConvertFontToLOGFONT(interop
, NULL
, &logfont
, &system
);
3990 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
3991 ok(!system
, "got %d\n", system
);
3992 ok(logfont
.lfFaceName
[0] == 0, "got face name %s\n", wine_dbgstr_w(logfont
.lfFaceName
));
3994 count
= IDWriteFontCollection_GetFontFamilyCount(collection
);
3995 for (i
= 0; i
< count
; i
++) {
3996 WCHAR nameW
[128], familynameW
[64], facenameW
[64];
3997 IDWriteLocalizedStrings
*names
;
3998 DWRITE_FONT_SIMULATIONS sim
;
3999 IDWriteFontFamily
*family
;
4000 UINT32 font_count
, j
;
4004 hr
= IDWriteFontCollection_GetFontFamily(collection
, i
, &family
);
4005 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4007 hr
= IDWriteFontFamily_GetFamilyNames(family
, &names
);
4008 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4010 get_enus_string(names
, familynameW
, ARRAY_SIZE(familynameW
));
4011 IDWriteLocalizedStrings_Release(names
);
4013 font_count
= IDWriteFontFamily_GetFontCount(family
);
4015 for (j
= 0; j
< font_count
; j
++) {
4016 static const WCHAR spaceW
[] = {' ', 0};
4018 hr
= IDWriteFontFamily_GetFont(family
, j
, &font
);
4019 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4021 hr
= IDWriteFont_GetFaceNames(font
, &names
);
4022 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4024 get_enus_string(names
, facenameW
, ARRAY_SIZE(facenameW
));
4025 IDWriteLocalizedStrings_Release(names
);
4027 lstrcpyW(nameW
, familynameW
);
4028 lstrcatW(nameW
, spaceW
);
4029 lstrcatW(nameW
, facenameW
);
4032 memset(&logfont
, 0xcc, sizeof(logfont
));
4033 hr
= IDWriteGdiInterop_ConvertFontToLOGFONT(interop
, font
, &logfont
, &system
);
4034 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4035 ok(system
, "got %d\n", system
);
4037 sim
= IDWriteFont_GetSimulations(font
);
4039 get_logfont_from_font(font
, &lf
);
4040 ok(logfont
.lfWeight
== lf
.lfWeight
, "%s: unexpected lfWeight %d, expected lfWeight %d, font weight %d, "
4041 "bold simulation %s\n", wine_dbgstr_w(nameW
), logfont
.lfWeight
, lf
.lfWeight
, IDWriteFont_GetWeight(font
),
4042 sim
& DWRITE_FONT_SIMULATIONS_BOLD
? "yes" : "no");
4043 ok(logfont
.lfItalic
== lf
.lfItalic
, "%s: unexpected italic flag %d, oblique simulation %s\n",
4044 wine_dbgstr_w(nameW
), logfont
.lfItalic
, sim
& DWRITE_FONT_SIMULATIONS_OBLIQUE
? "yes" : "no");
4045 ok(!lstrcmpW(logfont
.lfFaceName
, lf
.lfFaceName
), "%s: unexpected facename %s, expected %s\n",
4046 wine_dbgstr_w(nameW
), wine_dbgstr_w(logfont
.lfFaceName
), wine_dbgstr_w(lf
.lfFaceName
));
4048 ok(logfont
.lfOutPrecision
== OUT_OUTLINE_PRECIS
, "%s: unexpected output precision %d\n", wine_dbgstr_w(nameW
),
4049 logfont
.lfOutPrecision
);
4050 ok(logfont
.lfClipPrecision
== CLIP_DEFAULT_PRECIS
, "%s: unexpected clipping precision %d\n", wine_dbgstr_w(nameW
),
4051 logfont
.lfClipPrecision
);
4052 ok(logfont
.lfQuality
== DEFAULT_QUALITY
, "%s: unexpected quality %d\n", wine_dbgstr_w(nameW
), logfont
.lfQuality
);
4053 ok(logfont
.lfPitchAndFamily
== DEFAULT_PITCH
, "%s: unexpected pitch %d\n", wine_dbgstr_w(nameW
),
4054 logfont
.lfPitchAndFamily
);
4056 IDWriteFont_Release(font
);
4059 IDWriteFontFamily_Release(family
);
4062 IDWriteFactory_Release(factory2
);
4064 IDWriteFontCollection_Release(collection
);
4065 IDWriteFontFamily_Release(family
);
4066 IDWriteFont_Release(font
);
4067 IDWriteGdiInterop_Release(interop
);
4068 ref
= IDWriteFactory_Release(factory
);
4069 ok(ref
== 0, "factory not released, %u\n", ref
);
4072 static void test_CreateStreamFromKey(void)
4074 IDWriteLocalFontFileLoader
*localloader
;
4075 IDWriteFontFileStream
*stream
, *stream2
;
4076 IDWriteFontFileLoader
*loader
;
4077 IDWriteFactory
*factory
;
4078 IDWriteFontFile
*file
;
4086 factory
= create_factory();
4088 path
= create_testfontfile(test_fontfile
);
4090 hr
= IDWriteFactory_CreateFontFileReference(factory
, path
, NULL
, &file
);
4091 ok(hr
== S_OK
, "got 0x%08x\n",hr
);
4095 hr
= IDWriteFontFile_GetReferenceKey(file
, (const void**)&key
, &size
);
4096 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4097 ok(size
!= 0, "got %u\n", size
);
4099 hr
= IDWriteFontFile_GetLoader(file
, &loader
);
4100 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4101 IDWriteFontFileLoader_QueryInterface(loader
, &IID_IDWriteLocalFontFileLoader
, (void**)&localloader
);
4102 IDWriteFontFileLoader_Release(loader
);
4104 hr
= IDWriteLocalFontFileLoader_CreateStreamFromKey(localloader
, key
, size
, &stream
);
4105 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4106 EXPECT_REF(stream
, 1);
4108 hr
= IDWriteLocalFontFileLoader_CreateStreamFromKey(localloader
, key
, size
, &stream2
);
4109 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4110 ok(stream
== stream2
|| broken(stream
!= stream2
) /* Win7 SP0 */, "got %p, %p\n", stream
, stream2
);
4111 if (stream
== stream2
)
4112 EXPECT_REF(stream
, 2);
4113 IDWriteFontFileStream_Release(stream
);
4114 IDWriteFontFileStream_Release(stream2
);
4116 hr
= IDWriteLocalFontFileLoader_CreateStreamFromKey(localloader
, key
, size
, &stream
);
4117 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4118 EXPECT_REF(stream
, 1);
4121 hr
= IDWriteFontFileStream_GetLastWriteTime(stream
, &writetime
);
4122 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4123 ok(writetime
!= 0, "got %s\n", wine_dbgstr_longlong(writetime
));
4125 IDWriteFontFileStream_Release(stream
);
4126 IDWriteFontFile_Release(file
);
4128 IDWriteLocalFontFileLoader_Release(localloader
);
4129 ref
= IDWriteFactory_Release(factory
);
4130 ok(ref
== 0, "factory not released, %u\n", ref
);
4131 DELETE_FONTFILE(path
);
4134 static void test_ReadFileFragment(void)
4136 IDWriteLocalFontFileLoader
*localloader
;
4137 IDWriteFontFileStream
*stream
;
4138 IDWriteFontFileLoader
*loader
;
4139 IDWriteFactory
*factory
;
4140 IDWriteFontFile
*file
;
4141 const void *fragment
, *fragment2
;
4142 void *key
, *context
, *context2
;
4149 factory
= create_factory();
4151 path
= create_testfontfile(test_fontfile
);
4153 hr
= IDWriteFactory_CreateFontFileReference(factory
, path
, NULL
, &file
);
4154 ok(hr
== S_OK
, "got 0x%08x\n",hr
);
4158 hr
= IDWriteFontFile_GetReferenceKey(file
, (const void**)&key
, &size
);
4159 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4160 ok(size
!= 0, "got %u\n", size
);
4162 hr
= IDWriteFontFile_GetLoader(file
, &loader
);
4163 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4164 IDWriteFontFileLoader_QueryInterface(loader
, &IID_IDWriteLocalFontFileLoader
, (void**)&localloader
);
4165 IDWriteFontFileLoader_Release(loader
);
4167 hr
= IDWriteLocalFontFileLoader_CreateStreamFromKey(localloader
, key
, size
, &stream
);
4168 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4170 hr
= IDWriteFontFileStream_GetFileSize(stream
, &filesize
);
4171 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4173 /* reading past the end of the stream */
4174 fragment
= (void*)0xdeadbeef;
4175 context
= (void*)0xdeadbeef;
4176 hr
= IDWriteFontFileStream_ReadFileFragment(stream
, &fragment
, 0, filesize
+1, &context
);
4177 ok(hr
== E_FAIL
, "got 0x%08x\n", hr
);
4178 ok(context
== NULL
, "got %p\n", context
);
4179 ok(fragment
== NULL
, "got %p\n", fragment
);
4181 fragment
= (void*)0xdeadbeef;
4182 context
= (void*)0xdeadbeef;
4183 hr
= IDWriteFontFileStream_ReadFileFragment(stream
, &fragment
, 0, filesize
, &context
);
4184 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4185 ok(context
== NULL
, "got %p\n", context
);
4186 ok(fragment
!= NULL
, "got %p\n", fragment
);
4188 fragment2
= (void*)0xdeadbeef;
4189 context2
= (void*)0xdeadbeef;
4190 hr
= IDWriteFontFileStream_ReadFileFragment(stream
, &fragment2
, 0, filesize
, &context2
);
4191 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4192 ok(context2
== NULL
, "got %p\n", context2
);
4193 ok(fragment
== fragment2
, "got %p, %p\n", fragment
, fragment2
);
4195 IDWriteFontFileStream_ReleaseFileFragment(stream
, context
);
4196 IDWriteFontFileStream_ReleaseFileFragment(stream
, context2
);
4198 /* fragment is released, try again */
4199 fragment
= (void*)0xdeadbeef;
4200 context
= (void*)0xdeadbeef;
4201 hr
= IDWriteFontFileStream_ReadFileFragment(stream
, &fragment
, 0, filesize
, &context
);
4202 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4203 ok(context
== NULL
, "got %p\n", context
);
4204 ok(fragment
== fragment2
, "got %p, %p\n", fragment
, fragment2
);
4205 IDWriteFontFileStream_ReleaseFileFragment(stream
, context
);
4207 IDWriteFontFile_Release(file
);
4208 IDWriteFontFileStream_Release(stream
);
4209 IDWriteLocalFontFileLoader_Release(localloader
);
4210 ref
= IDWriteFactory_Release(factory
);
4211 ok(ref
== 0, "factory not released, %u\n", ref
);
4212 DELETE_FONTFILE(path
);
4215 static void test_GetDesignGlyphMetrics(void)
4217 DWRITE_GLYPH_METRICS metrics
[2];
4218 IDWriteFontFace
*fontface
;
4219 IDWriteFactory
*factory
;
4220 IDWriteFontFile
*file
;
4227 factory
= create_factory();
4229 path
= create_testfontfile(test_fontfile
);
4231 hr
= IDWriteFactory_CreateFontFileReference(factory
, path
, NULL
, &file
);
4232 ok(hr
== S_OK
, "got 0x%08x\n",hr
);
4234 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_TRUETYPE
, 1, &file
,
4235 0, DWRITE_FONT_SIMULATIONS_NONE
, &fontface
);
4236 ok(hr
== S_OK
, "got 0x%08x\n",hr
);
4237 IDWriteFontFile_Release(file
);
4241 hr
= IDWriteFontFace_GetGlyphIndices(fontface
, &codepoint
, 1, &indices
[0]);
4242 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4243 ok(indices
[0] > 0, "got %u\n", indices
[0]);
4245 hr
= IDWriteFontFace_GetDesignGlyphMetrics(fontface
, NULL
, 0, metrics
, FALSE
);
4246 ok(hr
== E_INVALIDARG
, "got 0x%08x\n",hr
);
4248 hr
= IDWriteFontFace_GetDesignGlyphMetrics(fontface
, NULL
, 1, metrics
, FALSE
);
4249 ok(hr
== E_INVALIDARG
, "got 0x%08x\n",hr
);
4251 hr
= IDWriteFontFace_GetDesignGlyphMetrics(fontface
, indices
, 0, metrics
, FALSE
);
4252 ok(hr
== S_OK
, "got 0x%08x\n",hr
);
4254 /* missing glyphs are ignored */
4256 memset(metrics
, 0xcc, sizeof(metrics
));
4257 hr
= IDWriteFontFace_GetDesignGlyphMetrics(fontface
, indices
, 2, metrics
, FALSE
);
4258 ok(hr
== S_OK
, "got 0x%08x\n",hr
);
4259 ok(metrics
[0].advanceWidth
== 1000, "got %d\n", metrics
[0].advanceWidth
);
4260 ok(metrics
[1].advanceWidth
== 0, "got %d\n", metrics
[1].advanceWidth
);
4262 IDWriteFontFace_Release(fontface
);
4263 ref
= IDWriteFactory_Release(factory
);
4264 ok(ref
== 0, "factory not released, %u\n", ref
);
4265 DELETE_FONTFILE(path
);
4268 static void test_IsMonospacedFont(void)
4270 static const WCHAR courierW
[] = {'C','o','u','r','i','e','r',' ','N','e','w',0};
4271 IDWriteFontCollection
*collection
;
4272 IDWriteFactory
*factory
;
4278 factory
= create_factory();
4279 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &collection
, FALSE
);
4280 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4283 hr
= IDWriteFontCollection_FindFamilyName(collection
, courierW
, &index
, &exists
);
4284 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4286 IDWriteFontFamily
*family
;
4287 IDWriteFont1
*font1
;
4290 hr
= IDWriteFontCollection_GetFontFamily(collection
, index
, &family
);
4291 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4293 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
,
4294 DWRITE_FONT_STRETCH_NORMAL
, DWRITE_FONT_STYLE_NORMAL
, &font
);
4295 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4296 IDWriteFontFamily_Release(family
);
4298 hr
= IDWriteFont_QueryInterface(font
, &IID_IDWriteFont1
, (void**)&font1
);
4300 IDWriteFontFace1
*fontface1
;
4301 IDWriteFontFace
*fontface
;
4304 is_monospaced
= IDWriteFont1_IsMonospacedFont(font1
);
4305 ok(is_monospaced
, "got %d\n", is_monospaced
);
4307 hr
= IDWriteFont1_CreateFontFace(font1
, &fontface
);
4308 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4309 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void**)&fontface1
);
4310 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4311 is_monospaced
= IDWriteFontFace1_IsMonospacedFont(fontface1
);
4312 ok(is_monospaced
, "got %d\n", is_monospaced
);
4313 IDWriteFontFace1_Release(fontface1
);
4315 IDWriteFontFace_Release(fontface
);
4316 IDWriteFont1_Release(font1
);
4319 win_skip("IsMonospacedFont() is not supported.\n");
4321 IDWriteFont_Release(font
);
4324 skip("Courier New font not found.\n");
4326 ref
= IDWriteFontCollection_Release(collection
);
4327 ok(ref
== 0, "factory not released, %u\n", ref
);
4330 static void test_GetDesignGlyphAdvances(void)
4332 IDWriteFontFace1
*fontface1
;
4333 IDWriteFontFace
*fontface
;
4334 IDWriteFactory
*factory
;
4335 IDWriteFontFile
*file
;
4340 factory
= create_factory();
4342 path
= create_testfontfile(test_fontfile
);
4344 hr
= IDWriteFactory_CreateFontFileReference(factory
, path
, NULL
, &file
);
4345 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4347 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_TRUETYPE
, 1, &file
,
4348 0, DWRITE_FONT_SIMULATIONS_NONE
, &fontface
);
4349 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4350 IDWriteFontFile_Release(file
);
4352 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void**)&fontface1
);
4360 hr
= IDWriteFontFace1_GetGlyphIndices(fontface1
, &codepoint
, 1, &index
);
4361 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4362 ok(index
> 0, "got %u\n", index
);
4365 hr
= IDWriteFontFace1_GetDesignGlyphAdvances(fontface1
, 1, &index
, &advance
, FALSE
);
4366 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4367 ok(advance
== 1000, "got %i\n", advance
);
4370 hr
= IDWriteFontFace1_GetDesignGlyphAdvances(fontface1
, 1, &index
, &advance
, TRUE
);
4371 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4373 ok(advance
== 2048, "got %i\n", advance
);
4375 IDWriteFontFace1_Release(fontface1
);
4378 win_skip("GetDesignGlyphAdvances() is not supported.\n");
4380 IDWriteFontFace_Release(fontface
);
4381 ref
= IDWriteFactory_Release(factory
);
4382 ok(ref
== 0, "factory not released, %u\n", ref
);
4383 DELETE_FONTFILE(path
);
4386 static void test_GetGlyphRunOutline(void)
4388 DWRITE_GLYPH_OFFSET offsets
[2];
4389 IDWriteFactory
*factory
;
4390 IDWriteFontFile
*file
;
4391 IDWriteFontFace
*face
;
4399 path
= create_testfontfile(test_fontfile
);
4400 factory
= create_factory();
4402 hr
= IDWriteFactory_CreateFontFileReference(factory
, path
, NULL
, &file
);
4403 ok(hr
== S_OK
, "got 0x%08x\n",hr
);
4405 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_TRUETYPE
, 1, &file
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &face
);
4406 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4407 IDWriteFontFile_Release(file
);
4411 hr
= IDWriteFontFace_GetGlyphIndices(face
, &codepoint
, 1, glyphs
);
4412 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4413 ok(glyphs
[0] > 0, "got %u\n", glyphs
[0]);
4414 glyphs
[1] = glyphs
[0];
4416 hr
= IDWriteFontFace_GetGlyphRunOutline(face
, 2048.0, glyphs
, advances
, offsets
, 1, FALSE
, FALSE
, NULL
);
4417 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
4419 hr
= IDWriteFontFace_GetGlyphRunOutline(face
, 2048.0, NULL
, NULL
, offsets
, 1, FALSE
, FALSE
, &test_geomsink
);
4420 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
4425 offsets
[0].advanceOffset
= 1.0;
4426 offsets
[0].ascenderOffset
= 1.0;
4427 offsets
[1].advanceOffset
= 0.0;
4428 offsets
[1].ascenderOffset
= 0.0;
4430 /* default advances, no offsets */
4431 memset(g_startpoints
, 0, sizeof(g_startpoints
));
4432 g_startpoint_count
= 0;
4433 SET_EXPECT(setfillmode
);
4434 hr
= IDWriteFontFace_GetGlyphRunOutline(face
, 1024.0, glyphs
, NULL
, NULL
, 2, FALSE
, FALSE
, &test_geomsink
);
4435 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4436 ok(g_startpoint_count
== 2, "got %d\n", g_startpoint_count
);
4437 if (g_startpoint_count
== 2) {
4438 /* glyph advance of 500 is applied */
4439 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
);
4440 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
);
4442 CHECK_CALLED(setfillmode
);
4444 /* default advances, no offsets, RTL */
4445 memset(g_startpoints
, 0, sizeof(g_startpoints
));
4446 g_startpoint_count
= 0;
4447 SET_EXPECT(setfillmode
);
4448 hr
= IDWriteFontFace_GetGlyphRunOutline(face
, 1024.0, glyphs
, NULL
, NULL
, 2, FALSE
, TRUE
, &test_geomsink
);
4449 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4450 ok(g_startpoint_count
== 2, "got %d\n", g_startpoint_count
);
4451 if (g_startpoint_count
== 2) {
4452 /* advance is -500 now */
4453 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
);
4454 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
);
4456 CHECK_CALLED(setfillmode
);
4458 /* default advances, additional offsets */
4459 memset(g_startpoints
, 0, sizeof(g_startpoints
));
4460 g_startpoint_count
= 0;
4461 SET_EXPECT(setfillmode
);
4462 hr
= IDWriteFontFace_GetGlyphRunOutline(face
, 1024.0, glyphs
, NULL
, offsets
, 2, FALSE
, FALSE
, &test_geomsink
);
4463 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4464 ok(g_startpoint_count
== 2, "got %d\n", g_startpoint_count
);
4465 if (g_startpoint_count
== 2) {
4466 /* offsets applied to first contour */
4467 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
);
4468 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
);
4470 CHECK_CALLED(setfillmode
);
4472 /* default advances, additional offsets, RTL */
4473 memset(g_startpoints
, 0, sizeof(g_startpoints
));
4474 g_startpoint_count
= 0;
4475 SET_EXPECT(setfillmode
);
4476 hr
= IDWriteFontFace_GetGlyphRunOutline(face
, 1024.0, glyphs
, NULL
, offsets
, 2, FALSE
, TRUE
, &test_geomsink
);
4477 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4478 ok(g_startpoint_count
== 2, "got %d\n", g_startpoint_count
);
4479 if (g_startpoint_count
== 2) {
4480 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
);
4481 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
);
4483 CHECK_CALLED(setfillmode
);
4485 /* custom advances and offsets, offset turns total advance value to zero */
4486 memset(g_startpoints
, 0, sizeof(g_startpoints
));
4487 g_startpoint_count
= 0;
4488 SET_EXPECT(setfillmode
);
4489 hr
= IDWriteFontFace_GetGlyphRunOutline(face
, 1024.0, glyphs
, advances
, offsets
, 2, FALSE
, FALSE
, &test_geomsink
);
4490 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4491 ok(g_startpoint_count
== 2, "got %d\n", g_startpoint_count
);
4492 if (g_startpoint_count
== 2) {
4493 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
);
4494 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
);
4496 CHECK_CALLED(setfillmode
);
4499 hr
= IDWriteFontFace_GetGlyphRunOutline(face
, 1024.0, glyphs
, NULL
, NULL
, 0, FALSE
, FALSE
, &test_geomsink2
);
4500 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4502 /* Glyph with open figure, single contour point. */
4505 hr
= IDWriteFontFace_GetGlyphIndices(face
, &codepoint
, 1, glyphs
);
4506 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4507 ok(glyphs
[0] > 0, "got %u\n", glyphs
[0]);
4509 SET_EXPECT(setfillmode
);
4510 hr
= IDWriteFontFace_GetGlyphRunOutline(face
, 1024.0, glyphs
, NULL
, NULL
, 1, FALSE
, FALSE
, &test_geomsink2
);
4511 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4512 CHECK_CALLED(setfillmode
);
4514 IDWriteFactory_Release(factory
);
4515 IDWriteFontFace_Release(face
);
4516 DELETE_FONTFILE(path
);
4519 factory
= create_factory();
4520 face
= create_fontface(factory
);
4524 hr
= IDWriteFontFace_GetGlyphIndices(face
, &codepoint
, 1, glyphs
);
4525 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4526 ok(glyphs
[0] > 0, "got %u\n", glyphs
[0]);
4528 SET_EXPECT(setfillmode
);
4529 hr
= IDWriteFontFace_GetGlyphRunOutline(face
, 1024.0, glyphs
, NULL
, NULL
, 1, FALSE
, FALSE
, &test_geomsink2
);
4530 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4531 CHECK_CALLED(setfillmode
);
4533 IDWriteFontFace_Release(face
);
4534 ref
= IDWriteFactory_Release(factory
);
4535 ok(ref
== 0, "factory not released, %u\n", ref
);
4538 static void test_GetEudcFontCollection(void)
4540 IDWriteFontCollection
*coll
, *coll2
;
4541 IDWriteFactory1
*factory
;
4545 factory
= create_factory_iid(&IID_IDWriteFactory1
);
4547 win_skip("GetEudcFontCollection() is not supported.\n");
4551 EXPECT_REF(factory
, 1);
4552 hr
= IDWriteFactory1_GetEudcFontCollection(factory
, &coll
, FALSE
);
4553 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4554 EXPECT_REF(factory
, 2);
4555 hr
= IDWriteFactory1_GetEudcFontCollection(factory
, &coll2
, FALSE
);
4556 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4557 EXPECT_REF(factory
, 2);
4558 ok(coll
== coll2
, "got %p, %p\n", coll
, coll2
);
4559 IDWriteFontCollection_Release(coll
);
4560 IDWriteFontCollection_Release(coll2
);
4562 ref
= IDWriteFactory1_Release(factory
);
4563 ok(ref
== 0, "factory not released, %u\n", ref
);
4566 static void test_GetCaretMetrics(void)
4568 DWRITE_FONT_METRICS1 metrics
;
4569 IDWriteFontFace1
*fontface1
;
4570 DWRITE_CARET_METRICS caret
;
4571 IDWriteFontFace
*fontface
;
4572 IDWriteFactory
*factory
;
4573 IDWriteFontFile
*file
;
4579 path
= create_testfontfile(test_fontfile
);
4580 factory
= create_factory();
4582 hr
= IDWriteFactory_CreateFontFileReference(factory
, path
, NULL
, &file
);
4583 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4585 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_TRUETYPE
, 1, &file
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &fontface
);
4586 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4587 IDWriteFontFile_Release(file
);
4589 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void**)&fontface1
);
4590 IDWriteFontFace_Release(fontface
);
4592 win_skip("GetCaretMetrics() is not supported.\n");
4593 ref
= IDWriteFactory_Release(factory
);
4594 ok(ref
== 0, "factory not released, %u\n", ref
);
4595 DELETE_FONTFILE(path
);
4599 memset(&caret
, 0xcc, sizeof(caret
));
4600 IDWriteFontFace1_GetCaretMetrics(fontface1
, &caret
);
4601 ok(caret
.slopeRise
== 1, "got %d\n", caret
.slopeRise
);
4602 ok(caret
.slopeRun
== 0, "got %d\n", caret
.slopeRun
);
4603 ok(caret
.offset
== 0, "got %d\n", caret
.offset
);
4604 IDWriteFontFace1_Release(fontface1
);
4605 IDWriteFactory_Release(factory
);
4607 /* now with Tahoma Normal */
4608 factory
= create_factory();
4609 font
= get_tahoma_instance(factory
, DWRITE_FONT_STYLE_NORMAL
);
4610 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
4611 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4612 IDWriteFont_Release(font
);
4613 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void**)&fontface1
);
4614 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4615 IDWriteFontFace_Release(fontface
);
4617 memset(&caret
, 0xcc, sizeof(caret
));
4618 IDWriteFontFace1_GetCaretMetrics(fontface1
, &caret
);
4619 ok(caret
.slopeRise
== 1, "got %d\n", caret
.slopeRise
);
4620 ok(caret
.slopeRun
== 0, "got %d\n", caret
.slopeRun
);
4621 ok(caret
.offset
== 0, "got %d\n", caret
.offset
);
4622 IDWriteFontFace1_Release(fontface1
);
4624 /* simulated italic */
4625 font
= get_tahoma_instance(factory
, DWRITE_FONT_STYLE_ITALIC
);
4626 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
4627 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4628 IDWriteFont_Release(font
);
4629 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void**)&fontface1
);
4630 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4631 IDWriteFontFace_Release(fontface
);
4633 IDWriteFontFace1_GetMetrics(fontface1
, &metrics
);
4635 memset(&caret
, 0xcc, sizeof(caret
));
4636 IDWriteFontFace1_GetCaretMetrics(fontface1
, &caret
);
4637 ok(caret
.slopeRise
== metrics
.designUnitsPerEm
, "got %d\n", caret
.slopeRise
);
4638 ok(caret
.slopeRun
> 0, "got %d\n", caret
.slopeRun
);
4639 ok(caret
.offset
== 0, "got %d\n", caret
.offset
);
4640 IDWriteFontFace1_Release(fontface1
);
4642 ref
= IDWriteFactory_Release(factory
);
4643 ok(ref
== 0, "factory not released, %u\n", ref
);
4644 DELETE_FONTFILE(path
);
4647 static void test_GetGlyphCount(void)
4649 IDWriteFontFace
*fontface
;
4650 IDWriteFactory
*factory
;
4651 IDWriteFontFile
*file
;
4657 path
= create_testfontfile(test_fontfile
);
4658 factory
= create_factory();
4660 hr
= IDWriteFactory_CreateFontFileReference(factory
, path
, NULL
, &file
);
4661 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4663 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_TRUETYPE
, 1, &file
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &fontface
);
4664 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4665 IDWriteFontFile_Release(file
);
4667 count
= IDWriteFontFace_GetGlyphCount(fontface
);
4668 ok(count
== 8, "got %u\n", count
);
4670 IDWriteFontFace_Release(fontface
);
4671 ref
= IDWriteFactory_Release(factory
);
4672 ok(ref
== 0, "factory not released, %u\n", ref
);
4673 DELETE_FONTFILE(path
);
4676 static void test_GetKerningPairAdjustments(void)
4678 IDWriteFontFace1
*fontface1
;
4679 IDWriteFontFace
*fontface
;
4680 IDWriteFactory
*factory
;
4681 IDWriteFontFile
*file
;
4686 path
= create_testfontfile(test_fontfile
);
4687 factory
= create_factory();
4689 hr
= IDWriteFactory_CreateFontFileReference(factory
, path
, NULL
, &file
);
4690 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4692 hr
= IDWriteFactory_CreateFontFace(factory
, DWRITE_FONT_FACE_TYPE_TRUETYPE
, 1, &file
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &fontface
);
4693 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4694 IDWriteFontFile_Release(file
);
4696 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void**)&fontface1
);
4698 INT32 adjustments
[1];
4700 hr
= IDWriteFontFace1_GetKerningPairAdjustments(fontface1
, 0, NULL
, NULL
);
4701 ok(hr
== E_INVALIDARG
|| broken(hr
== S_OK
) /* win8 */, "got 0x%08x\n", hr
);
4703 if (0) /* crashes on native */
4704 hr
= IDWriteFontFace1_GetKerningPairAdjustments(fontface1
, 1, NULL
, NULL
);
4707 hr
= IDWriteFontFace1_GetKerningPairAdjustments(fontface1
, 1, NULL
, adjustments
);
4708 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
4709 ok(adjustments
[0] == 0, "got %d\n", adjustments
[0]);
4711 IDWriteFontFace1_Release(fontface1
);
4714 win_skip("GetKerningPairAdjustments() is not supported.\n");
4716 IDWriteFontFace_Release(fontface
);
4717 ref
= IDWriteFactory_Release(factory
);
4718 ok(ref
== 0, "factory not released, %u\n", ref
);
4719 DELETE_FONTFILE(path
);
4722 static void test_CreateRenderingParams(void)
4724 IDWriteRenderingParams2
*params2
;
4725 IDWriteRenderingParams1
*params1
;
4726 IDWriteRenderingParams
*params
;
4727 DWRITE_RENDERING_MODE mode
;
4728 IDWriteFactory3
*factory3
;
4729 IDWriteFactory
*factory
;
4733 factory
= create_factory();
4735 hr
= IDWriteFactory_CreateCustomRenderingParams(factory
, 1.0, 0.0, 0.0, DWRITE_PIXEL_GEOMETRY_FLAT
,
4736 DWRITE_RENDERING_MODE_DEFAULT
, ¶ms
);
4737 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4739 hr
= IDWriteRenderingParams_QueryInterface(params
, &IID_IDWriteRenderingParams1
, (void**)¶ms1
);
4743 /* test what enhanced contrast setting set by default to */
4744 enhcontrast
= IDWriteRenderingParams1_GetGrayscaleEnhancedContrast(params1
);
4745 ok(enhcontrast
== 1.0, "got %.2f\n", enhcontrast
);
4746 IDWriteRenderingParams1_Release(params1
);
4748 hr
= IDWriteRenderingParams_QueryInterface(params
, &IID_IDWriteRenderingParams2
, (void**)¶ms2
);
4750 DWRITE_GRID_FIT_MODE gridfit
;
4752 /* default gridfit mode */
4753 gridfit
= IDWriteRenderingParams2_GetGridFitMode(params2
);
4754 ok(gridfit
== DWRITE_GRID_FIT_MODE_DEFAULT
, "got %d\n", gridfit
);
4756 IDWriteRenderingParams2_Release(params2
);
4759 win_skip("IDWriteRenderingParams2 not supported.\n");
4762 win_skip("IDWriteRenderingParams1 not supported.\n");
4764 IDWriteRenderingParams_Release(params
);
4766 hr
= IDWriteFactory_CreateRenderingParams(factory
, ¶ms
);
4767 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4769 mode
= IDWriteRenderingParams_GetRenderingMode(params
);
4770 ok(mode
== DWRITE_RENDERING_MODE_DEFAULT
, "got %d\n", mode
);
4771 IDWriteRenderingParams_Release(params
);
4773 hr
= IDWriteFactory_QueryInterface(factory
, &IID_IDWriteFactory3
, (void**)&factory3
);
4775 IDWriteRenderingParams3
*params3
;
4777 hr
= IDWriteFactory3_CreateCustomRenderingParams(factory3
, 1.0f
, 0.0f
, 0.0f
, 1.0f
, DWRITE_PIXEL_GEOMETRY_FLAT
,
4778 DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC_DOWNSAMPLED
, DWRITE_GRID_FIT_MODE_DEFAULT
, ¶ms3
);
4779 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4781 hr
= IDWriteRenderingParams3_QueryInterface(params3
, &IID_IDWriteRenderingParams
, (void**)¶ms
);
4782 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4784 mode
= IDWriteRenderingParams_GetRenderingMode(params
);
4785 ok(mode
== DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
, "got %d\n", mode
);
4787 IDWriteRenderingParams_Release(params
);
4788 IDWriteRenderingParams3_Release(params3
);
4789 IDWriteFactory3_Release(factory3
);
4792 win_skip("IDWriteRenderingParams3 not supported.\n");
4794 ref
= IDWriteFactory_Release(factory
);
4795 ok(ref
== 0, "factory not released, %u\n", ref
);
4798 static void test_CreateGlyphRunAnalysis(void)
4800 static const DWRITE_RENDERING_MODE rendermodes
[] = {
4801 DWRITE_RENDERING_MODE_ALIASED
,
4802 DWRITE_RENDERING_MODE_GDI_CLASSIC
,
4803 DWRITE_RENDERING_MODE_GDI_NATURAL
,
4804 DWRITE_RENDERING_MODE_NATURAL
,
4805 DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
,
4808 IDWriteGlyphRunAnalysis
*analysis
, *analysis2
;
4809 IDWriteRenderingParams
*params
;
4810 IDWriteFactory3
*factory3
;
4811 IDWriteFactory2
*factory2
;
4812 IDWriteFactory
*factory
;
4813 DWRITE_GLYPH_RUN run
;
4814 IDWriteFontFace
*face
;
4815 UINT16 glyph
, glyphs
[10];
4820 DWRITE_GLYPH_OFFSET offsets
[2];
4821 DWRITE_GLYPH_METRICS metrics
;
4822 DWRITE_FONT_METRICS fm
;
4829 factory
= create_factory();
4830 face
= create_fontface(factory
);
4834 hr
= IDWriteFontFace_GetGlyphIndices(face
, &ch
, 1, &glyph
);
4835 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4836 ok(glyph
> 0, "got %u\n", glyph
);
4838 hr
= IDWriteFontFace_GetDesignGlyphMetrics(face
, &glyph
, 1, &metrics
, FALSE
);
4839 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4840 advances
[0] = metrics
.advanceWidth
;
4842 offsets
[0].advanceOffset
= 0.0;
4843 offsets
[0].ascenderOffset
= 0.0;
4845 run
.fontFace
= face
;
4846 run
.fontEmSize
= 24.0;
4848 run
.glyphIndices
= &glyph
;
4849 run
.glyphAdvances
= advances
;
4850 run
.glyphOffsets
= offsets
;
4851 run
.isSideways
= FALSE
;
4855 analysis
= (void*)0xdeadbeef;
4856 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 0.0, NULL
,
4857 DWRITE_RENDERING_MODE_ALIASED
, DWRITE_MEASURING_MODE_NATURAL
,
4858 0.0, 0.0, &analysis
);
4859 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
4860 ok(analysis
== NULL
, "got %p\n", analysis
);
4862 /* negative ppdip */
4863 analysis
= (void*)0xdeadbeef;
4864 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, -1.0, NULL
,
4865 DWRITE_RENDERING_MODE_ALIASED
, DWRITE_MEASURING_MODE_NATURAL
,
4866 0.0, 0.0, &analysis
);
4867 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
4868 ok(analysis
== NULL
, "got %p\n", analysis
);
4870 /* default mode is not allowed */
4871 analysis
= (void*)0xdeadbeef;
4872 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 1.0, NULL
,
4873 DWRITE_RENDERING_MODE_DEFAULT
, DWRITE_MEASURING_MODE_NATURAL
,
4874 0.0, 0.0, &analysis
);
4875 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
4876 ok(analysis
== NULL
, "got %p\n", analysis
);
4879 analysis
= (void*)0xdeadbeef;
4880 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 1.0, NULL
,
4881 DWRITE_RENDERING_MODE_OUTLINE
, DWRITE_MEASURING_MODE_NATURAL
,
4882 0.0, 0.0, &analysis
);
4883 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
4884 ok(analysis
== NULL
, "got %p\n", analysis
);
4886 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 1.0, NULL
,
4887 DWRITE_RENDERING_MODE_ALIASED
, DWRITE_MEASURING_MODE_NATURAL
,
4888 0.0, 0.0, &analysis
);
4889 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4891 /* invalid texture type */
4892 memset(&rect
, 0xcc, sizeof(rect
));
4893 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_CLEARTYPE_3x1
+1, &rect
);
4894 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
4895 ok(rect
.left
== 0 && rect
.right
== 0 &&
4896 rect
.top
== 0 && rect
.bottom
== 0, "unexpected rect\n");
4898 /* check how origin affects bounds */
4899 SetRectEmpty(&rect
);
4900 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect
);
4901 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4902 ok(!IsRectEmpty(&rect
), "got empty rect\n");
4903 IDWriteGlyphRunAnalysis_Release(analysis
);
4906 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 2.0, NULL
,
4907 DWRITE_RENDERING_MODE_ALIASED
, DWRITE_MEASURING_MODE_NATURAL
,
4908 0.0, 0.0, &analysis
);
4909 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4910 SetRectEmpty(&rect2
);
4911 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect2
);
4912 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4913 ok(rect
.right
- rect
.left
< rect2
.right
- rect2
.left
, "expected wider rect\n");
4914 ok(rect
.bottom
- rect
.top
< rect2
.bottom
- rect2
.top
, "expected taller rect\n");
4915 IDWriteGlyphRunAnalysis_Release(analysis
);
4917 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 1.0, NULL
,
4918 DWRITE_RENDERING_MODE_ALIASED
, DWRITE_MEASURING_MODE_NATURAL
,
4919 10.0, -5.0, &analysis
);
4920 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4922 SetRectEmpty(&rect2
);
4923 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect2
);
4924 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4925 ok(!IsRectEmpty(&rect2
), "got empty rect\n");
4926 IDWriteGlyphRunAnalysis_Release(analysis
);
4928 ok(!EqualRect(&rect
, &rect2
), "got equal bounds\n");
4929 OffsetRect(&rect
, 10, -5);
4930 ok(EqualRect(&rect
, &rect2
), "got different bounds\n");
4932 for (i
= 0; i
< ARRAY_SIZE(rendermodes
); i
++) {
4933 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 1.0, NULL
,
4934 rendermodes
[i
], DWRITE_MEASURING_MODE_NATURAL
,
4935 0.0, 0.0, &analysis
);
4936 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4938 if (rendermodes
[i
] == DWRITE_RENDERING_MODE_ALIASED
) {
4939 SetRectEmpty(&rect
);
4940 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect
);
4941 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4942 ok(!IsRectEmpty(&rect
), "got empty rect\n");
4944 SetRect(&rect
, 0, 0, 1, 1);
4945 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_CLEARTYPE_3x1
, &rect
);
4946 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4947 ok(IsRectEmpty(&rect
), "unexpected empty rect\n");
4950 SetRect(&rect
, 0, 0, 1, 1);
4951 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect
);
4952 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4953 ok(IsRectEmpty(&rect
), "got empty rect\n");
4955 SetRectEmpty(&rect
);
4956 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_CLEARTYPE_3x1
, &rect
);
4957 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4958 ok(!IsRectEmpty(&rect
), "got empty rect\n");
4961 IDWriteGlyphRunAnalysis_Release(analysis
);
4964 IDWriteFontFace_GetMetrics(run
.fontFace
, &fm
);
4966 /* check bbox for a single glyph run */
4967 for (run
.fontEmSize
= 1.0; run
.fontEmSize
<= 100.0; run
.fontEmSize
+= 1.0) {
4968 DWRITE_GLYPH_METRICS gm
;
4971 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 1.0, NULL
,
4972 DWRITE_RENDERING_MODE_ALIASED
, DWRITE_MEASURING_MODE_GDI_CLASSIC
,
4973 0.0, 0.0, &analysis
);
4974 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4976 SetRectEmpty(&rect
);
4977 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect
);
4978 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4980 hr
= IDWriteFontFace_GetGdiCompatibleGlyphMetrics(run
.fontFace
, run
.fontEmSize
, 1.0, NULL
,
4981 DWRITE_MEASURING_MODE_GDI_CLASSIC
, run
.glyphIndices
, 1, &gm
, run
.isSideways
);
4982 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4984 /* metrics are in design units */
4985 bboxX
= (int)floorf((gm
.advanceWidth
- gm
.leftSideBearing
- gm
.rightSideBearing
) * run
.fontEmSize
/ fm
.designUnitsPerEm
+ 0.5f
);
4986 bboxY
= (int)floorf((gm
.advanceHeight
- gm
.topSideBearing
- gm
.bottomSideBearing
) * run
.fontEmSize
/ fm
.designUnitsPerEm
+ 0.5f
);
4988 rect
.right
-= rect
.left
;
4989 rect
.bottom
-= rect
.top
;
4990 ok(abs(bboxX
- rect
.right
) <= 2, "%.0f: bbox width %d, from metrics %d\n", run
.fontEmSize
, rect
.right
, bboxX
);
4991 ok(abs(bboxY
- rect
.bottom
) <= 2, "%.0f: bbox height %d, from metrics %d\n", run
.fontEmSize
, rect
.bottom
, bboxY
);
4993 IDWriteGlyphRunAnalysis_Release(analysis
);
4996 /* without offsets */
4997 run
.fontFace
= face
;
4998 run
.fontEmSize
= 24.0;
5000 run
.glyphIndices
= &glyph
;
5001 run
.glyphAdvances
= advances
;
5002 run
.glyphOffsets
= NULL
;
5003 run
.isSideways
= FALSE
;
5006 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 1.0, NULL
,
5007 DWRITE_RENDERING_MODE_ALIASED
, DWRITE_MEASURING_MODE_NATURAL
,
5008 0.0, 0.0, &analysis
);
5009 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5011 SetRectEmpty(&rect
);
5012 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect
);
5013 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5014 ok(!IsRectEmpty(&rect
), "got empty bounds\n");
5016 IDWriteGlyphRunAnalysis_Release(analysis
);
5018 /* without explicit advances */
5019 run
.fontFace
= face
;
5020 run
.fontEmSize
= 24.0;
5022 run
.glyphIndices
= &glyph
;
5023 run
.glyphAdvances
= NULL
;
5024 run
.glyphOffsets
= NULL
;
5025 run
.isSideways
= FALSE
;
5028 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 1.0, NULL
,
5029 DWRITE_RENDERING_MODE_ALIASED
, DWRITE_MEASURING_MODE_NATURAL
,
5030 0.0, 0.0, &analysis
);
5031 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5033 SetRectEmpty(&rect
);
5034 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect
);
5035 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5036 ok(!IsRectEmpty(&rect
), "got empty bounds\n");
5038 IDWriteGlyphRunAnalysis_Release(analysis
);
5040 /* test that advances are scaled according to ppdip too */
5041 glyphs
[0] = glyphs
[1] = glyph
;
5042 advances
[0] = advances
[1] = 100.0f
;
5043 run
.fontFace
= face
;
5044 run
.fontEmSize
= 24.0;
5046 run
.glyphIndices
= glyphs
;
5047 run
.glyphAdvances
= advances
;
5048 run
.glyphOffsets
= NULL
;
5049 run
.isSideways
= FALSE
;
5052 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 1.0, NULL
,
5053 DWRITE_RENDERING_MODE_ALIASED
, DWRITE_MEASURING_MODE_NATURAL
,
5054 0.0, 0.0, &analysis
);
5055 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5057 SetRectEmpty(&rect2
);
5058 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect2
);
5059 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5060 ok(!IsRectEmpty(&rect2
), "got empty bounds\n");
5061 ok(!EqualRect(&rect
, &rect2
), "got wrong rect2\n");
5062 ok((rect2
.right
- rect
.left
) > advances
[0], "got rect width %d for advance %f\n", rect
.right
- rect
.left
, advances
[0]);
5063 IDWriteGlyphRunAnalysis_Release(analysis
);
5065 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 2.0, NULL
,
5066 DWRITE_RENDERING_MODE_ALIASED
, DWRITE_MEASURING_MODE_NATURAL
,
5067 0.0, 0.0, &analysis
);
5068 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5070 SetRectEmpty(&rect
);
5071 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect
);
5072 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5073 ok((rect
.right
- rect
.left
) > 2 * advances
[0], "got rect width %d for advance %f\n", rect
.right
- rect
.left
, advances
[0]);
5074 IDWriteGlyphRunAnalysis_Release(analysis
);
5076 /* with scaling transform */
5077 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 1.0, NULL
,
5078 DWRITE_RENDERING_MODE_ALIASED
, DWRITE_MEASURING_MODE_NATURAL
,
5079 0.0, 0.0, &analysis
);
5080 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5082 SetRectEmpty(&rect
);
5083 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect
);
5084 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5085 ok(!IsRectEmpty(&rect
), "got rect width %d\n", rect
.right
- rect
.left
);
5086 IDWriteGlyphRunAnalysis_Release(analysis
);
5088 memset(&m
, 0, sizeof(m
));
5091 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 1.0, &m
,
5092 DWRITE_RENDERING_MODE_ALIASED
, DWRITE_MEASURING_MODE_NATURAL
,
5093 0.0, 0.0, &analysis
);
5094 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5096 SetRectEmpty(&rect2
);
5097 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect2
);
5098 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5099 ok((rect2
.right
- rect2
.left
) > (rect
.right
- rect
.left
), "got rect width %d\n", rect2
.right
- rect2
.left
);
5101 /* instances are not reused for same runs */
5102 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 1.0, &m
,
5103 DWRITE_RENDERING_MODE_ALIASED
, DWRITE_MEASURING_MODE_NATURAL
,
5104 0.0, 0.0, &analysis2
);
5105 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5106 ok(analysis2
!= analysis
, "got %p, previous instance %p\n", analysis2
, analysis
);
5107 IDWriteGlyphRunAnalysis_Release(analysis2
);
5109 IDWriteGlyphRunAnalysis_Release(analysis
);
5111 if (IDWriteFactory_QueryInterface(factory
, &IID_IDWriteFactory2
, (void **)&factory2
) == S_OK
) {
5112 FLOAT gamma
, contrast
, cleartype_level
;
5114 /* Invalid antialias mode. */
5115 hr
= IDWriteFactory2_CreateGlyphRunAnalysis(factory2
, &run
, NULL
, DWRITE_RENDERING_MODE_ALIASED
,
5116 DWRITE_MEASURING_MODE_NATURAL
, DWRITE_GRID_FIT_MODE_DEFAULT
, DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
+ 1,
5117 0.0f
, 0.0f
, &analysis
);
5118 ok(hr
== E_INVALIDARG
, "Unexpected hr %#x.\n", hr
);
5120 /* Invalid grid fit mode. */
5121 hr
= IDWriteFactory2_CreateGlyphRunAnalysis(factory2
, &run
, NULL
, DWRITE_RENDERING_MODE_ALIASED
,
5122 DWRITE_MEASURING_MODE_NATURAL
, DWRITE_GRID_FIT_MODE_ENABLED
+ 1, DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
,
5123 0.0f
, 0.0f
, &analysis
);
5124 ok(hr
== E_INVALIDARG
, "Unexpected hr %#x.\n", hr
);
5126 /* Invalid rendering mode. */
5127 hr
= IDWriteFactory2_CreateGlyphRunAnalysis(factory2
, &run
, NULL
, DWRITE_RENDERING_MODE_OUTLINE
,
5128 DWRITE_MEASURING_MODE_NATURAL
, DWRITE_GRID_FIT_MODE_ENABLED
, DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
,
5129 0.0f
, 0.0f
, &analysis
);
5130 ok(hr
== E_INVALIDARG
, "Unexpected hr %#x.\n", hr
);
5132 /* Invalid measuring mode. */
5133 hr
= IDWriteFactory2_CreateGlyphRunAnalysis(factory2
, &run
, NULL
, DWRITE_RENDERING_MODE_ALIASED
,
5134 DWRITE_MEASURING_MODE_GDI_NATURAL
+ 1, DWRITE_GRID_FIT_MODE_ENABLED
, DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
,
5135 0.0f
, 0.0f
, &analysis
);
5136 ok(hr
== E_INVALIDARG
, "Unexpected hr %#x.\n", hr
);
5138 /* Win8 does not accept default grid fitting mode. */
5139 hr
= IDWriteFactory2_CreateGlyphRunAnalysis(factory2
, &run
, NULL
, DWRITE_RENDERING_MODE_NATURAL
,
5140 DWRITE_MEASURING_MODE_NATURAL
, DWRITE_GRID_FIT_MODE_DEFAULT
, DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
,
5141 0.0f
, 0.0f
, &analysis
);
5142 ok(hr
== S_OK
|| broken(hr
== E_INVALIDARG
) /* Win8 */, "Failed to create analysis, hr %#x.\n", hr
);
5144 IDWriteGlyphRunAnalysis_Release(analysis
);
5146 /* Natural mode, grayscale antialiased. */
5147 hr
= IDWriteFactory2_CreateGlyphRunAnalysis(factory2
, &run
, NULL
, DWRITE_RENDERING_MODE_NATURAL
,
5148 DWRITE_MEASURING_MODE_NATURAL
, DWRITE_GRID_FIT_MODE_DISABLED
, DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
,
5149 0.0f
, 0.0f
, &analysis
);
5150 ok(hr
== S_OK
, "Failed to create analysis, hr %#x.\n", hr
);
5152 SetRect(&rect
, 0, 1, 0, 1);
5153 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_CLEARTYPE_3x1
, &rect
);
5154 ok(hr
== S_OK
, "Failed to get texture bounds, hr %#x.\n", hr
);
5155 ok(IsRectEmpty(&rect
), "Expected empty bbox.\n");
5157 SetRectEmpty(&rect
);
5158 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect
);
5159 ok(hr
== S_OK
, "Failed to get texture bounds, hr %#x.\n", hr
);
5160 ok(!IsRectEmpty(&rect
), "Unexpected empty bbox.\n");
5162 size
= (rect
.right
- rect
.left
) * (rect
.bottom
- rect
.top
);
5163 bits
= HeapAlloc(GetProcessHeap(), 0, size
);
5165 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect
, bits
, size
);
5166 ok(hr
== S_OK
, "Failed to get alpha texture, hr %#x.\n", hr
);
5168 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect
, bits
, size
- 1);
5169 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "Unexpected hr %#x.\n", hr
);
5171 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_CLEARTYPE_3x1
, &rect
, bits
, size
);
5172 ok(hr
== DWRITE_E_UNSUPPORTEDOPERATION
, "Unexpected hr %#x.\n", hr
);
5174 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_CLEARTYPE_3x1
, &rect
, bits
, size
- 1);
5176 ok(hr
== DWRITE_E_UNSUPPORTEDOPERATION
, "Unexpected hr %#x.\n", hr
);
5178 HeapFree(GetProcessHeap(), 0, bits
);
5180 hr
= IDWriteFactory_CreateCustomRenderingParams(factory
, 0.1f
, 0.0f
, 1.0f
, DWRITE_PIXEL_GEOMETRY_FLAT
,
5181 DWRITE_RENDERING_MODE_NATURAL
, ¶ms
);
5182 ok(hr
== S_OK
, "Failed to create custom parameters, hr %#x.\n", hr
);
5184 hr
= IDWriteGlyphRunAnalysis_GetAlphaBlendParams(analysis
, params
, &gamma
, &contrast
, &cleartype_level
);
5185 ok(hr
== S_OK
, "Failed to get alpha blend params, hr %#x.\n", hr
);
5187 ok(cleartype_level
== 0.0f
, "Unexpected cleartype level %f.\n", cleartype_level
);
5189 IDWriteRenderingParams_Release(params
);
5190 IDWriteGlyphRunAnalysis_Release(analysis
);
5192 IDWriteFactory2_Release(factory2
);
5195 if (IDWriteFactory_QueryInterface(factory
, &IID_IDWriteFactory3
, (void **)&factory3
) == S_OK
) {
5197 /* Invalid antialias mode. */
5198 hr
= IDWriteFactory3_CreateGlyphRunAnalysis(factory3
, &run
, NULL
, DWRITE_RENDERING_MODE1_ALIASED
,
5199 DWRITE_MEASURING_MODE_NATURAL
, DWRITE_GRID_FIT_MODE_DEFAULT
, DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
+ 1,
5200 0.0f
, 0.0f
, &analysis
);
5201 ok(hr
== E_INVALIDARG
, "Unexpected hr %#x.\n", hr
);
5203 /* Invalid grid fit mode. */
5204 hr
= IDWriteFactory3_CreateGlyphRunAnalysis(factory3
, &run
, NULL
, DWRITE_RENDERING_MODE1_ALIASED
,
5205 DWRITE_MEASURING_MODE_NATURAL
, DWRITE_GRID_FIT_MODE_ENABLED
+ 1, DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
,
5206 0.0f
, 0.0f
, &analysis
);
5207 ok(hr
== E_INVALIDARG
, "Unexpected hr %#x.\n", hr
);
5209 /* Invalid rendering mode. */
5210 hr
= IDWriteFactory3_CreateGlyphRunAnalysis(factory3
, &run
, NULL
, DWRITE_RENDERING_MODE1_OUTLINE
,
5211 DWRITE_MEASURING_MODE_NATURAL
, DWRITE_GRID_FIT_MODE_ENABLED
, DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
,
5212 0.0f
, 0.0f
, &analysis
);
5213 ok(hr
== E_INVALIDARG
, "Unexpected hr %#x.\n", hr
);
5215 /* Invalid measuring mode. */
5216 hr
= IDWriteFactory3_CreateGlyphRunAnalysis(factory3
, &run
, NULL
, DWRITE_RENDERING_MODE1_ALIASED
,
5217 DWRITE_MEASURING_MODE_GDI_NATURAL
+ 1, DWRITE_GRID_FIT_MODE_ENABLED
,
5218 DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
, 0.0f
, 0.0f
, &analysis
);
5219 ok(hr
== E_INVALIDARG
, "Unexpected hr %#x.\n", hr
);
5221 hr
= IDWriteFactory3_CreateGlyphRunAnalysis(factory3
, &run
, NULL
, DWRITE_RENDERING_MODE1_NATURAL
,
5222 DWRITE_MEASURING_MODE_NATURAL
, DWRITE_GRID_FIT_MODE_DEFAULT
, DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
,
5223 0.0f
, 0.0f
, &analysis
);
5224 ok(hr
== S_OK
, "Failed to create analysis, hr %#x.\n", hr
);
5225 IDWriteGlyphRunAnalysis_Release(analysis
);
5227 /* Natural mode, grayscale antialiased. */
5228 hr
= IDWriteFactory3_CreateGlyphRunAnalysis(factory3
, &run
, NULL
, DWRITE_RENDERING_MODE1_NATURAL
,
5229 DWRITE_MEASURING_MODE_NATURAL
, DWRITE_GRID_FIT_MODE_DISABLED
, DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
,
5230 0.0f
, 0.0f
, &analysis
);
5231 ok(hr
== S_OK
, "Failed to create analysis, hr %#x.\n", hr
);
5233 SetRect(&rect
, 0, 1, 0, 1);
5234 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_CLEARTYPE_3x1
, &rect
);
5235 ok(hr
== S_OK
, "Failed to get texture bounds, hr %#x.\n", hr
);
5236 ok(IsRectEmpty(&rect
), "Expected empty bbox.\n");
5238 SetRectEmpty(&rect
);
5239 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect
);
5240 ok(hr
== S_OK
, "Failed to get texture bounds, hr %#x.\n", hr
);
5241 ok(!IsRectEmpty(&rect
), "Unexpected empty bbox.\n");
5243 size
= (rect
.right
- rect
.left
) * (rect
.bottom
- rect
.top
);
5244 bits
= HeapAlloc(GetProcessHeap(), 0, size
);
5246 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect
, bits
, size
);
5247 ok(hr
== S_OK
, "Failed to get alpha texture, hr %#x.\n", hr
);
5249 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &rect
, bits
, size
- 1);
5250 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "Unexpected hr %#x.\n", hr
);
5252 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_CLEARTYPE_3x1
, &rect
, bits
, size
);
5253 ok(hr
== DWRITE_E_UNSUPPORTEDOPERATION
, "Unexpected hr %#x.\n", hr
);
5255 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_CLEARTYPE_3x1
, &rect
, bits
, size
- 1);
5257 ok(hr
== DWRITE_E_UNSUPPORTEDOPERATION
, "Unexpected hr %#x.\n", hr
);
5259 HeapFree(GetProcessHeap(), 0, bits
);
5261 IDWriteGlyphRunAnalysis_Release(analysis
);
5263 IDWriteFactory3_Release(factory3
);
5266 IDWriteFontFace_Release(face
);
5267 ref
= IDWriteFactory_Release(factory
);
5268 ok(ref
== 0, "factory not released, %u\n", ref
);
5271 #define round(x) ((int)floor((x) + 0.5))
5302 static const struct VDMX_group
*find_vdmx_group(const struct VDMX_Header
*hdr
)
5304 WORD num_ratios
, i
, group_offset
= 0;
5305 struct VDMX_Ratio
*ratios
= (struct VDMX_Ratio
*)(hdr
+ 1);
5306 BYTE dev_x_ratio
= 1, dev_y_ratio
= 1;
5308 num_ratios
= GET_BE_WORD(hdr
->numRatios
);
5310 for (i
= 0; i
< num_ratios
; i
++)
5312 if (!ratios
[i
].bCharSet
) continue;
5314 if ((ratios
[i
].xRatio
== 0 && ratios
[i
].yStartRatio
== 0 &&
5315 ratios
[i
].yEndRatio
== 0) ||
5316 (ratios
[i
].xRatio
== dev_x_ratio
&& ratios
[i
].yStartRatio
<= dev_y_ratio
&&
5317 ratios
[i
].yEndRatio
>= dev_y_ratio
))
5319 group_offset
= GET_BE_WORD(*((WORD
*)(ratios
+ num_ratios
) + i
));
5324 return (const struct VDMX_group
*)((BYTE
*)hdr
+ group_offset
);
5328 static BOOL
get_vdmx_size(const struct VDMX_group
*group
, int emsize
, int *a
, int *d
)
5331 const struct VDMX_vTable
*tables
;
5333 if (!group
) return FALSE
;
5335 recs
= GET_BE_WORD(group
->recs
);
5336 if (emsize
< group
->startsz
|| emsize
>= group
->endsz
) return FALSE
;
5338 tables
= (const struct VDMX_vTable
*)(group
+ 1);
5339 for (i
= 0; i
< recs
; i
++)
5341 WORD ppem
= GET_BE_WORD(tables
[i
].yPelHeight
);
5344 /* FIXME: Supposed to interpolate */
5345 trace("FIXME interpolate %d\n", emsize
);
5351 *a
= (SHORT
)GET_BE_WORD(tables
[i
].yMax
);
5352 *d
= -(SHORT
)GET_BE_WORD(tables
[i
].yMin
);
5359 static void test_metrics_cmp(FLOAT emsize
, const DWRITE_FONT_METRICS
*metrics
, const DWRITE_FONT_METRICS1
*expected
)
5361 ok(metrics
->designUnitsPerEm
== expected
->designUnitsPerEm
, "%.2f: emsize: got %u expect %u\n",
5362 emsize
, metrics
->designUnitsPerEm
, expected
->designUnitsPerEm
);
5363 ok(metrics
->ascent
== expected
->ascent
, "%.2f a: got %u expect %u\n",
5364 emsize
, metrics
->ascent
, expected
->ascent
);
5365 ok(metrics
->descent
== expected
->descent
, "%.2f d: got %u expect %u\n",
5366 emsize
, metrics
->descent
, expected
->descent
);
5367 ok(metrics
->lineGap
== expected
->lineGap
, "%.2f lg: got %d expect %d\n",
5368 emsize
, metrics
->lineGap
, expected
->lineGap
);
5369 ok(metrics
->capHeight
== expected
->capHeight
, "%.2f capH: got %u expect %u\n",
5370 emsize
, metrics
->capHeight
, expected
->capHeight
);
5371 ok(metrics
->xHeight
== expected
->xHeight
, "%.2f xH: got %u expect %u\n",
5372 emsize
, metrics
->xHeight
, expected
->xHeight
);
5373 ok(metrics
->underlinePosition
== expected
->underlinePosition
, "%.2f ulP: got %d expect %d\n",
5374 emsize
, metrics
->underlinePosition
, expected
->underlinePosition
);
5375 ok(metrics
->underlineThickness
== expected
->underlineThickness
, "%.2f ulTh: got %u expect %u\n",
5376 emsize
, metrics
->underlineThickness
, expected
->underlineThickness
);
5377 ok(metrics
->strikethroughPosition
== expected
->strikethroughPosition
, "%.2f stP: got %d expect %d\n",
5378 emsize
, metrics
->strikethroughPosition
, expected
->strikethroughPosition
);
5379 ok(metrics
->strikethroughThickness
== expected
->strikethroughThickness
, "%.2f stTh: got %u expect %u\n",
5380 emsize
, metrics
->strikethroughThickness
, expected
->strikethroughThickness
);
5383 static void test_metrics1_cmp(FLOAT emsize
, const DWRITE_FONT_METRICS1
*metrics
, const DWRITE_FONT_METRICS1
*expected
)
5385 ok(metrics
->designUnitsPerEm
== expected
->designUnitsPerEm
, "%.2f: emsize: got %u expect %u\n",
5386 emsize
, metrics
->designUnitsPerEm
, expected
->designUnitsPerEm
);
5387 ok(metrics
->ascent
== expected
->ascent
, "%.2f a: got %u expect %u\n",
5388 emsize
, metrics
->ascent
, expected
->ascent
);
5389 ok(metrics
->descent
== expected
->descent
, "%.2f d: got %u expect %u\n",
5390 emsize
, metrics
->descent
, expected
->descent
);
5391 ok(metrics
->lineGap
== expected
->lineGap
, "%.2f lg: got %d expect %d\n",
5392 emsize
, metrics
->lineGap
, expected
->lineGap
);
5393 ok(metrics
->capHeight
== expected
->capHeight
, "%.2f capH: got %u expect %u\n",
5394 emsize
, metrics
->capHeight
, expected
->capHeight
);
5395 ok(metrics
->xHeight
== expected
->xHeight
, "%.2f xH: got %u expect %u\n",
5396 emsize
, metrics
->xHeight
, expected
->xHeight
);
5397 ok(metrics
->underlinePosition
== expected
->underlinePosition
, "%.2f ulP: got %d expect %d\n",
5398 emsize
, metrics
->underlinePosition
, expected
->underlinePosition
);
5399 ok(metrics
->underlineThickness
== expected
->underlineThickness
, "%.2f ulTh: got %u expect %u\n",
5400 emsize
, metrics
->underlineThickness
, expected
->underlineThickness
);
5401 ok(metrics
->strikethroughPosition
== expected
->strikethroughPosition
, "%.2f stP: got %d expect %d\n",
5402 emsize
, metrics
->strikethroughPosition
, expected
->strikethroughPosition
);
5403 ok(metrics
->strikethroughThickness
== expected
->strikethroughThickness
, "%.2f stTh: got %u expect %u\n",
5404 emsize
, metrics
->strikethroughThickness
, expected
->strikethroughThickness
);
5405 ok(metrics
->glyphBoxLeft
== expected
->glyphBoxLeft
, "%.2f box left: got %d expect %d\n",
5406 emsize
, metrics
->glyphBoxLeft
, expected
->glyphBoxLeft
);
5407 if (0) { /* this is not consistent */
5408 ok(metrics
->glyphBoxTop
== expected
->glyphBoxTop
, "%.2f box top: got %d expect %d\n",
5409 emsize
, metrics
->glyphBoxTop
, expected
->glyphBoxTop
);
5410 ok(metrics
->glyphBoxRight
== expected
->glyphBoxRight
, "%.2f box right: got %d expect %d\n",
5411 emsize
, metrics
->glyphBoxRight
, expected
->glyphBoxRight
);
5413 ok(metrics
->glyphBoxBottom
== expected
->glyphBoxBottom
, "%.2f box bottom: got %d expect %d\n",
5414 emsize
, metrics
->glyphBoxBottom
, expected
->glyphBoxBottom
);
5415 ok(metrics
->subscriptPositionX
== expected
->subscriptPositionX
, "%.2f subX: got %d expect %d\n",
5416 emsize
, metrics
->subscriptPositionX
, expected
->subscriptPositionX
);
5417 ok(metrics
->subscriptPositionY
== expected
->subscriptPositionY
, "%.2f subY: got %d expect %d\n",
5418 emsize
, metrics
->subscriptPositionY
, expected
->subscriptPositionY
);
5419 ok(metrics
->subscriptSizeX
== expected
->subscriptSizeX
, "%.2f subsizeX: got %d expect %d\n",
5420 emsize
, metrics
->subscriptSizeX
, expected
->subscriptSizeX
);
5421 ok(metrics
->subscriptPositionY
== expected
->subscriptPositionY
, "%.2f subsizeY: got %d expect %d\n",
5422 emsize
, metrics
->subscriptSizeY
, expected
->subscriptSizeY
);
5423 ok(metrics
->superscriptPositionX
== expected
->superscriptPositionX
, "%.2f supX: got %d expect %d\n",
5424 emsize
, metrics
->superscriptPositionX
, expected
->superscriptPositionX
);
5426 ok(metrics
->superscriptPositionY
== expected
->superscriptPositionY
, "%.2f supY: got %d expect %d\n",
5427 emsize
, metrics
->superscriptPositionY
, expected
->superscriptPositionY
);
5428 ok(metrics
->superscriptSizeX
== expected
->superscriptSizeX
, "%.2f supsizeX: got %d expect %d\n",
5429 emsize
, metrics
->superscriptSizeX
, expected
->superscriptSizeX
);
5430 ok(metrics
->superscriptSizeY
== expected
->superscriptSizeY
, "%.2f supsizeY: got %d expect %d\n",
5431 emsize
, metrics
->superscriptSizeY
, expected
->superscriptSizeY
);
5432 ok(metrics
->hasTypographicMetrics
== expected
->hasTypographicMetrics
, "%.2f hastypo: got %d expect %d\n",
5433 emsize
, metrics
->hasTypographicMetrics
, expected
->hasTypographicMetrics
);
5436 struct compatmetrics_test
{
5442 static struct compatmetrics_test compatmetrics_tests
[] = {
5443 { { 0.0, 0.0, 0.0, 1.0, 0.0, 0.0 }, 1.0, 5.0 },
5444 { { 0.0, 0.0, 0.0, -1.0, 0.0, 0.0 }, 1.0, 5.0 },
5445 { { 0.0, 0.0, 0.0, -1.0, 0.0, 0.0 }, 2.0, 5.0 },
5446 { { 0.0, 0.0, 0.0, 3.0, 0.0, 0.0 }, 2.0, 5.0 },
5447 { { 0.0, 0.0, 0.0, -3.0, 0.0, 0.0 }, 2.0, 5.0 },
5448 { { 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 }, 2.0, 5.0 },
5449 { { 1.0, 0.0, 0.0, 1.0, 5.0, 0.0 }, 2.0, 5.0 },
5450 { { 1.0, 0.0, 0.0, 1.0, 0.0, 5.0 }, 2.0, 5.0 },
5453 static void get_expected_metrics(IDWriteFontFace
*fontface
, struct compatmetrics_test
*ptr
,
5454 DWRITE_FONT_METRICS
*expected
)
5458 memset(expected
, 0, sizeof(*expected
));
5459 hr
= IDWriteFontFace_GetGdiCompatibleMetrics(fontface
, ptr
->ppdip
* fabsf(ptr
->m
.m22
) * ptr
->emsize
, 1.0, NULL
, expected
);
5460 ok(hr
== S_OK
, "got %08x\n", hr
);
5463 static void test_gdicompat_metrics(IDWriteFontFace
*face
)
5465 IDWriteFontFace1
*fontface1
= NULL
;
5467 DWRITE_FONT_METRICS design_metrics
, comp_metrics
;
5468 DWRITE_FONT_METRICS1 design_metrics1
, expected
;
5469 FLOAT emsize
, scale
;
5470 int ascent
, descent
;
5471 const struct VDMX_Header
*vdmx
;
5475 const struct VDMX_group
*vdmx_group
= NULL
;
5478 hr
= IDWriteFontFace_QueryInterface(face
, &IID_IDWriteFontFace1
, (void**)&fontface1
);
5480 win_skip("gdi compatible DWRITE_FONT_METRICS1 are not supported.\n");
5483 IDWriteFontFace1_GetMetrics(fontface1
, &design_metrics1
);
5484 memcpy(&design_metrics
, &design_metrics1
, sizeof(design_metrics
));
5487 IDWriteFontFace_GetMetrics(face
, &design_metrics
);
5489 hr
= IDWriteFontFace_TryGetFontTable(face
, MS_VDMX_TAG
, (const void **)&vdmx
,
5490 &vdmx_len
, &vdmx_ctx
, &exists
);
5491 if (hr
!= S_OK
|| !exists
)
5494 vdmx_group
= find_vdmx_group(vdmx
);
5496 /* negative emsize */
5497 memset(&comp_metrics
, 0xcc, sizeof(comp_metrics
));
5498 memset(&expected
, 0, sizeof(expected
));
5499 hr
= IDWriteFontFace_GetGdiCompatibleMetrics(face
, -10.0, 1.0, NULL
, &comp_metrics
);
5500 ok(hr
== E_INVALIDARG
, "got %08x\n", hr
);
5501 test_metrics_cmp(0.0, &comp_metrics
, &expected
);
5504 memset(&comp_metrics
, 0xcc, sizeof(comp_metrics
));
5505 memset(&expected
, 0, sizeof(expected
));
5506 hr
= IDWriteFontFace_GetGdiCompatibleMetrics(face
, 0.0, 1.0, NULL
, &comp_metrics
);
5507 ok(hr
== E_INVALIDARG
, "got %08x\n", hr
);
5508 test_metrics_cmp(0.0, &comp_metrics
, &expected
);
5510 /* zero pixels per dip */
5511 memset(&comp_metrics
, 0xcc, sizeof(comp_metrics
));
5512 memset(&expected
, 0, sizeof(expected
));
5513 hr
= IDWriteFontFace_GetGdiCompatibleMetrics(face
, 5.0, 0.0, NULL
, &comp_metrics
);
5514 ok(hr
== E_INVALIDARG
, "got %08x\n", hr
);
5515 test_metrics_cmp(5.0, &comp_metrics
, &expected
);
5517 memset(&comp_metrics
, 0xcc, sizeof(comp_metrics
));
5518 hr
= IDWriteFontFace_GetGdiCompatibleMetrics(face
, 5.0, -1.0, NULL
, &comp_metrics
);
5519 ok(hr
== E_INVALIDARG
, "got %08x\n", hr
);
5520 test_metrics_cmp(5.0, &comp_metrics
, &expected
);
5522 for (i
= 0; i
< ARRAY_SIZE(compatmetrics_tests
); i
++) {
5523 struct compatmetrics_test
*ptr
= &compatmetrics_tests
[i
];
5525 get_expected_metrics(face
, ptr
, (DWRITE_FONT_METRICS
*)&expected
);
5526 hr
= IDWriteFontFace_GetGdiCompatibleMetrics(face
, ptr
->emsize
, ptr
->ppdip
, &ptr
->m
, &comp_metrics
);
5527 ok(hr
== S_OK
, "got %08x\n", hr
);
5528 test_metrics_cmp(ptr
->emsize
, &comp_metrics
, &expected
);
5531 for (emsize
= 5; emsize
<= design_metrics
.designUnitsPerEm
; emsize
++)
5533 DWRITE_FONT_METRICS1 comp_metrics1
, expected
;
5536 hr
= IDWriteFontFace1_GetGdiCompatibleMetrics(fontface1
, emsize
, 1.0, NULL
, &comp_metrics1
);
5537 ok(hr
== S_OK
, "got %08x\n", hr
);
5540 hr
= IDWriteFontFace_GetGdiCompatibleMetrics(face
, emsize
, 1.0, NULL
, &comp_metrics
);
5541 ok(hr
== S_OK
, "got %08x\n", hr
);
5544 scale
= emsize
/ design_metrics
.designUnitsPerEm
;
5545 if (!get_vdmx_size(vdmx_group
, emsize
, &ascent
, &descent
))
5547 ascent
= round(design_metrics
.ascent
* scale
);
5548 descent
= round(design_metrics
.descent
* scale
);
5551 expected
.designUnitsPerEm
= design_metrics
.designUnitsPerEm
;
5552 expected
.ascent
= round(ascent
/ scale
);
5553 expected
.descent
= round(descent
/ scale
);
5554 expected
.lineGap
= round(round(design_metrics
.lineGap
* scale
) / scale
);
5555 expected
.capHeight
= round(round(design_metrics
.capHeight
* scale
) / scale
);
5556 expected
.xHeight
= round(round(design_metrics
.xHeight
* scale
) / scale
);
5557 expected
.underlinePosition
= round(round(design_metrics
.underlinePosition
* scale
) / scale
);
5558 expected
.underlineThickness
= round(round(design_metrics
.underlineThickness
* scale
) / scale
);
5559 expected
.strikethroughPosition
= round(round(design_metrics
.strikethroughPosition
* scale
) / scale
);
5560 expected
.strikethroughThickness
= round(round(design_metrics
.strikethroughThickness
* scale
) / scale
);
5563 expected
.glyphBoxLeft
= round(round(design_metrics1
.glyphBoxLeft
* scale
) / scale
);
5565 if (0) { /* those two fail on Tahoma and Win7 */
5566 expected
.glyphBoxTop
= round(round(design_metrics1
.glyphBoxTop
* scale
) / scale
);
5567 expected
.glyphBoxRight
= round(round(design_metrics1
.glyphBoxRight
* scale
) / scale
);
5569 expected
.glyphBoxBottom
= round(round(design_metrics1
.glyphBoxBottom
* scale
) / scale
);
5570 expected
.subscriptPositionX
= round(round(design_metrics1
.subscriptPositionX
* scale
) / scale
);
5571 expected
.subscriptPositionY
= round(round(design_metrics1
.subscriptPositionY
* scale
) / scale
);
5572 expected
.subscriptSizeX
= round(round(design_metrics1
.subscriptSizeX
* scale
) / scale
);
5573 expected
.subscriptSizeY
= round(round(design_metrics1
.subscriptSizeY
* scale
) / scale
);
5574 expected
.superscriptPositionX
= round(round(design_metrics1
.superscriptPositionX
* scale
) / scale
);
5575 if (0) /* this fails for 3 emsizes, Tahoma from [5, 2048] range */ {
5576 expected
.superscriptPositionY
= round(round(design_metrics1
.superscriptPositionY
* scale
) / scale
);
5578 expected
.superscriptSizeX
= round(round(design_metrics1
.superscriptSizeX
* scale
) / scale
);
5579 expected
.superscriptSizeY
= round(round(design_metrics1
.superscriptSizeY
* scale
) / scale
);
5580 expected
.hasTypographicMetrics
= design_metrics1
.hasTypographicMetrics
;
5582 test_metrics1_cmp(emsize
, &comp_metrics1
, &expected
);
5585 test_metrics_cmp(emsize
, &comp_metrics
, &expected
);
5590 IDWriteFontFace1_Release(fontface1
);
5591 if (vdmx
) IDWriteFontFace_ReleaseFontTable(face
, vdmx_ctx
);
5594 static void test_GetGdiCompatibleMetrics(void)
5596 IDWriteFactory
*factory
;
5598 IDWriteFontFace
*fontface
;
5602 factory
= create_factory();
5604 font
= get_font(factory
, tahomaW
, DWRITE_FONT_STYLE_NORMAL
);
5605 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
5606 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5607 IDWriteFont_Release(font
);
5608 test_gdicompat_metrics(fontface
);
5609 IDWriteFontFace_Release(fontface
);
5611 font
= get_font(factory
, arialW
, DWRITE_FONT_STYLE_NORMAL
);
5613 skip("Skipping tests with Arial\n");
5616 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
5617 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5618 IDWriteFont_Release(font
);
5620 test_gdicompat_metrics(fontface
);
5621 IDWriteFontFace_Release(fontface
);
5624 ref
= IDWriteFactory_Release(factory
);
5625 ok(ref
== 0, "factory not released, %u\n", ref
);
5628 static void get_expected_panose(IDWriteFont1
*font
, DWRITE_PANOSE
*panose
)
5630 IDWriteFontFace
*fontface
;
5631 const TT_OS2_V2
*tt_os2
;
5637 memset(panose
, 0, sizeof(*panose
));
5639 hr
= IDWriteFont1_CreateFontFace(font
, &fontface
);
5640 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5642 hr
= IDWriteFontFace_TryGetFontTable(fontface
, MS_0S2_TAG
, (const void **)&tt_os2
, &size
, &os2_context
, &exists
);
5643 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5646 memcpy(panose
, &tt_os2
->panose
, sizeof(*panose
));
5647 IDWriteFontFace_ReleaseFontTable(fontface
, os2_context
);
5650 IDWriteFontFace_Release(fontface
);
5653 static void test_GetPanose(void)
5655 IDWriteFontCollection
*syscollection
;
5656 IDWriteFactory
*factory
;
5657 IDWriteFont1
*font1
;
5663 factory
= create_factory();
5664 font
= get_tahoma_instance(factory
, DWRITE_FONT_STYLE_NORMAL
);
5666 hr
= IDWriteFont_QueryInterface(font
, &IID_IDWriteFont1
, (void **)&font1
);
5667 IDWriteFont_Release(font
);
5670 ref
= IDWriteFactory_Release(factory
);
5671 ok(ref
== 0, "factory not released, %u\n", ref
);
5672 win_skip("GetPanose() is not supported.\n");
5675 IDWriteFont1_Release(font1
);
5677 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &syscollection
, FALSE
);
5678 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5679 count
= IDWriteFontCollection_GetFontFamilyCount(syscollection
);
5681 for (i
= 0; i
< count
; i
++) {
5682 DWRITE_PANOSE panose
, expected_panose
;
5683 IDWriteLocalizedStrings
*names
;
5684 IDWriteFontFace3
*fontface3
;
5685 IDWriteFontFace
*fontface
;
5686 IDWriteFontFamily
*family
;
5687 IDWriteFont1
*font1
;
5691 hr
= IDWriteFontCollection_GetFontFamily(syscollection
, i
, &family
);
5692 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5694 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STRETCH_NORMAL
,
5695 DWRITE_FONT_STYLE_NORMAL
, &font
);
5696 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5698 hr
= IDWriteFont_QueryInterface(font
, &IID_IDWriteFont1
, (void **)&font1
);
5699 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5700 IDWriteFont_Release(font
);
5702 hr
= IDWriteFontFamily_GetFamilyNames(family
, &names
);
5703 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5705 get_enus_string(names
, nameW
, ARRAY_SIZE(nameW
));
5707 IDWriteLocalizedStrings_Release(names
);
5709 IDWriteFont1_GetPanose(font1
, &panose
);
5710 get_expected_panose(font1
, &expected_panose
);
5712 ok(panose
.values
[0] == expected_panose
.values
[0], "%s: values[0] %#x, expected %#x.\n", wine_dbgstr_w(nameW
),
5713 panose
.values
[0], expected_panose
.values
[0]);
5714 ok(panose
.values
[1] == expected_panose
.values
[1], "%s: values[1] %#x, expected %#x.\n", wine_dbgstr_w(nameW
),
5715 panose
.values
[1], expected_panose
.values
[1]);
5716 ok(panose
.values
[2] == expected_panose
.values
[2], "%s: values[2] %#x, expected %#x.\n", wine_dbgstr_w(nameW
),
5717 panose
.values
[2], expected_panose
.values
[2]);
5718 ok(panose
.values
[3] == expected_panose
.values
[3], "%s: values[3] %#x, expected %#x.\n", wine_dbgstr_w(nameW
),
5719 panose
.values
[3], expected_panose
.values
[3]);
5720 ok(panose
.values
[4] == expected_panose
.values
[4], "%s: values[4] %#x, expected %#x.\n", wine_dbgstr_w(nameW
),
5721 panose
.values
[4], expected_panose
.values
[4]);
5722 ok(panose
.values
[5] == expected_panose
.values
[5], "%s: values[5] %#x, expected %#x.\n", wine_dbgstr_w(nameW
),
5723 panose
.values
[5], expected_panose
.values
[5]);
5724 ok(panose
.values
[6] == expected_panose
.values
[6], "%s: values[6] %#x, expected %#x.\n", wine_dbgstr_w(nameW
),
5725 panose
.values
[6], expected_panose
.values
[6]);
5726 ok(panose
.values
[7] == expected_panose
.values
[7], "%s: values[7] %#x, expected %#x.\n", wine_dbgstr_w(nameW
),
5727 panose
.values
[7], expected_panose
.values
[7]);
5728 ok(panose
.values
[8] == expected_panose
.values
[8], "%s: values[8] %#x, expected %#x.\n", wine_dbgstr_w(nameW
),
5729 panose
.values
[8], expected_panose
.values
[8]);
5730 ok(panose
.values
[9] == expected_panose
.values
[9], "%s: values[9] %#x, expected %#x.\n", wine_dbgstr_w(nameW
),
5731 panose
.values
[9], expected_panose
.values
[9]);
5733 hr
= IDWriteFont1_CreateFontFace(font1
, &fontface
);
5734 ok(hr
== S_OK
, "Failed to create a font face, %#x.\n", hr
);
5735 if (IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace3
, (void **)&fontface3
) == S_OK
) {
5736 ok(!memcmp(&panose
, &expected_panose
, sizeof(panose
)), "%s: Unexpected panose from font face.\n",
5737 wine_dbgstr_w(nameW
));
5738 IDWriteFontFace3_Release(fontface3
);
5740 IDWriteFontFace_Release(fontface
);
5742 IDWriteFont1_Release(font1
);
5743 IDWriteFontFamily_Release(family
);
5746 IDWriteFontCollection_Release(syscollection
);
5747 ref
= IDWriteFactory_Release(factory
);
5748 ok(ref
== 0, "factory not released, %u\n", ref
);
5751 static INT32
get_gdi_font_advance(HDC hdc
, FLOAT emsize
)
5758 memset(&logfont
, 0, sizeof(logfont
));
5759 logfont
.lfHeight
= (LONG
)-emsize
;
5760 logfont
.lfWeight
= FW_NORMAL
;
5761 logfont
.lfQuality
= CLEARTYPE_QUALITY
;
5762 lstrcpyW(logfont
.lfFaceName
, tahomaW
);
5764 hfont
= CreateFontIndirectW(&logfont
);
5765 SelectObject(hdc
, hfont
);
5767 ret
= GetCharABCWidthsW(hdc
, 'A', 'A', &abc
);
5768 ok(ret
, "got %d\n", ret
);
5770 DeleteObject(hfont
);
5772 return abc
.abcA
+ abc
.abcB
+ abc
.abcC
;
5775 static void test_GetGdiCompatibleGlyphAdvances(void)
5777 IDWriteFontFace1
*fontface1
;
5778 IDWriteFontFace
*fontface
;
5779 IDWriteFactory
*factory
;
5786 DWRITE_FONT_METRICS1 fm
;
5790 factory
= create_factory();
5791 font
= get_tahoma_instance(factory
, DWRITE_FONT_STYLE_NORMAL
);
5793 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
5794 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5795 IDWriteFont_Release(font
);
5797 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void **)&fontface1
);
5798 IDWriteFontFace_Release(fontface
);
5801 ref
= IDWriteFactory_Release(factory
);
5802 ok(ref
== 0, "factory not released, %u\n", ref
);
5803 win_skip("GetGdiCompatibleGlyphAdvances() is not supported\n");
5809 hr
= IDWriteFontFace1_GetGlyphIndices(fontface1
, &codepoint
, 1, &glyph
);
5810 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5811 ok(glyph
> 0, "got %u\n", glyph
);
5815 hr
= IDWriteFontFace1_GetGdiCompatibleGlyphAdvances(fontface1
, 0.0,
5816 1.0, NULL
, FALSE
, FALSE
, 1, &glyph
, &advance
);
5817 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5818 ok(advance
== 0, "got %d\n", advance
);
5820 /* negative emsize */
5822 hr
= IDWriteFontFace1_GetGdiCompatibleGlyphAdvances(fontface1
, -1.0,
5823 1.0, NULL
, FALSE
, FALSE
, 1, &glyph
, &advance
);
5824 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5825 ok(advance
== 0, "got %d\n", advance
);
5829 hr
= IDWriteFontFace1_GetGdiCompatibleGlyphAdvances(fontface1
, 1.0,
5830 0.0, NULL
, FALSE
, FALSE
, 1, &glyph
, &advance
);
5831 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5832 ok(advance
== 0, "got %d\n", advance
);
5834 /* negative ppdip */
5836 hr
= IDWriteFontFace1_GetGdiCompatibleGlyphAdvances(fontface1
, 1.0,
5837 -1.0, NULL
, FALSE
, FALSE
, 1, &glyph
, &advance
);
5838 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5839 ok(advance
== 0, "got %d\n", advance
);
5841 IDWriteFontFace1_GetMetrics(fontface1
, &fm
);
5843 hdc
= CreateCompatibleDC(0);
5845 for (emsize
= 1.0; emsize
<= fm
.designUnitsPerEm
; emsize
+= 1.0) {
5848 gdi_advance
= get_gdi_font_advance(hdc
, emsize
);
5849 hr
= IDWriteFontFace1_GetGdiCompatibleGlyphAdvances(fontface1
, emsize
,
5850 1.0, NULL
, FALSE
, FALSE
, 1, &glyph
, &advance
);
5851 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5853 /* advance is in design units */
5854 advance
= (int)floorf(emsize
* advance
/ fm
.designUnitsPerEm
+ 0.5f
);
5855 ok((advance
- gdi_advance
) <= 2, "%.0f: got advance %d, expected %d\n", emsize
, advance
, gdi_advance
);
5860 IDWriteFontFace1_Release(fontface1
);
5861 ref
= IDWriteFactory_Release(factory
);
5862 ok(ref
== 0, "factory not released, %u\n", ref
);
5865 static WORD
get_gasp_flags(IDWriteFontFace
*fontface
, FLOAT emsize
, FLOAT ppdip
)
5867 WORD num_recs
, version
;
5878 hr
= IDWriteFontFace_TryGetFontTable(fontface
, MS_GASP_TAG
,
5879 (const void**)&ptr
, &size
, &ctxt
, &exists
);
5880 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5885 version
= GET_BE_WORD( *ptr
++ );
5886 num_recs
= GET_BE_WORD( *ptr
++ );
5887 if (version
> 1 || size
< (num_recs
* 2 + 2) * sizeof(WORD
)) {
5888 ok(0, "unsupported gasp table: ver %d size %d recs %d\n", version
, size
, num_recs
);
5894 flags
= GET_BE_WORD( *(ptr
+ 1) );
5895 if (emsize
<= GET_BE_WORD( *ptr
)) break;
5900 IDWriteFontFace_ReleaseFontTable(fontface
, ctxt
);
5904 #define GASP_GRIDFIT 0x0001
5905 #define GASP_DOGRAY 0x0002
5906 #define GASP_SYMMETRIC_GRIDFIT 0x0004
5907 #define GASP_SYMMETRIC_SMOOTHING 0x0008
5909 static BOOL g_is_vista
;
5910 static DWRITE_RENDERING_MODE
get_expected_rendering_mode(FLOAT emsize
, WORD gasp
, DWRITE_MEASURING_MODE mode
,
5911 DWRITE_OUTLINE_THRESHOLD threshold
)
5913 static const FLOAT aa_threshold
= 100.0f
;
5914 static const FLOAT a_threshold
= 350.0f
;
5915 static const FLOAT naturalemsize
= 20.0f
;
5918 /* outline threshold */
5920 v
= mode
== DWRITE_MEASURING_MODE_NATURAL
? aa_threshold
: a_threshold
;
5922 v
= threshold
== DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
? aa_threshold
: a_threshold
;
5925 return DWRITE_RENDERING_MODE_OUTLINE
;
5929 case DWRITE_MEASURING_MODE_NATURAL
:
5930 if (!(gasp
& GASP_SYMMETRIC_SMOOTHING
) && (emsize
<= naturalemsize
))
5931 return DWRITE_RENDERING_MODE_NATURAL
;
5933 return DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
;
5934 case DWRITE_MEASURING_MODE_GDI_CLASSIC
:
5935 return DWRITE_RENDERING_MODE_GDI_CLASSIC
;
5936 case DWRITE_MEASURING_MODE_GDI_NATURAL
:
5937 return DWRITE_RENDERING_MODE_GDI_NATURAL
;
5942 /* should be unreachable */
5943 return DWRITE_RENDERING_MODE_DEFAULT
;
5946 static DWRITE_GRID_FIT_MODE
get_expected_gridfit_mode(FLOAT emsize
, WORD gasp
, DWRITE_MEASURING_MODE mode
,
5947 DWRITE_OUTLINE_THRESHOLD threshold
)
5949 static const FLOAT aa_threshold
= 100.0f
;
5950 static const FLOAT a_threshold
= 350.0f
;
5953 v
= threshold
== DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
? aa_threshold
: a_threshold
;
5955 return DWRITE_GRID_FIT_MODE_DISABLED
;
5957 if (mode
== DWRITE_MEASURING_MODE_GDI_CLASSIC
|| mode
== DWRITE_MEASURING_MODE_GDI_NATURAL
)
5958 return DWRITE_GRID_FIT_MODE_ENABLED
;
5960 return (gasp
& (GASP_GRIDFIT
|GASP_SYMMETRIC_GRIDFIT
)) ? DWRITE_GRID_FIT_MODE_ENABLED
: DWRITE_GRID_FIT_MODE_DISABLED
;
5963 struct recommendedmode_test
5965 DWRITE_MEASURING_MODE measuring
;
5966 DWRITE_OUTLINE_THRESHOLD threshold
;
5969 static const struct recommendedmode_test recmode_tests
[] = {
5970 { DWRITE_MEASURING_MODE_NATURAL
, DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
},
5971 { DWRITE_MEASURING_MODE_GDI_CLASSIC
, DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
},
5972 { DWRITE_MEASURING_MODE_GDI_NATURAL
, DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
},
5975 static const struct recommendedmode_test recmode_tests1
[] = {
5976 { DWRITE_MEASURING_MODE_NATURAL
, DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
},
5977 { DWRITE_MEASURING_MODE_GDI_CLASSIC
, DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
},
5978 { DWRITE_MEASURING_MODE_GDI_NATURAL
, DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
},
5979 { DWRITE_MEASURING_MODE_NATURAL
, DWRITE_OUTLINE_THRESHOLD_ALIASED
},
5980 { DWRITE_MEASURING_MODE_GDI_CLASSIC
, DWRITE_OUTLINE_THRESHOLD_ALIASED
},
5981 { DWRITE_MEASURING_MODE_GDI_NATURAL
, DWRITE_OUTLINE_THRESHOLD_ALIASED
},
5984 static void test_GetRecommendedRenderingMode(void)
5986 IDWriteRenderingParams
*params
;
5987 IDWriteFontFace3
*fontface3
;
5988 IDWriteFontFace2
*fontface2
;
5989 IDWriteFontFace1
*fontface1
;
5990 IDWriteFontFace
*fontface
;
5991 DWRITE_RENDERING_MODE mode
;
5992 IDWriteFactory
*factory
;
5997 factory
= create_factory();
5998 fontface
= create_fontface(factory
);
6001 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void**)&fontface1
);
6003 win_skip("IDWriteFontFace1::GetRecommendedRenderingMode() is not supported.\n");
6006 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace2
, (void**)&fontface2
);
6008 win_skip("IDWriteFontFace2::GetRecommendedRenderingMode() is not supported.\n");
6011 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace3
, (void**)&fontface3
);
6013 win_skip("IDWriteFontFace3::GetRecommendedRenderingMode() is not supported.\n");
6015 if (0) /* crashes on native */
6016 hr
= IDWriteFontFace_GetRecommendedRenderingMode(fontface
, 3.0, 1.0,
6017 DWRITE_MEASURING_MODE_GDI_CLASSIC
, NULL
, NULL
);
6020 hr
= IDWriteFontFace_GetRecommendedRenderingMode(fontface
, 3.0, 1.0,
6021 DWRITE_MEASURING_MODE_GDI_CLASSIC
, NULL
, &mode
);
6022 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
6023 ok(mode
== DWRITE_RENDERING_MODE_DEFAULT
, "got %d\n", mode
);
6025 hr
= IDWriteFactory_CreateRenderingParams(factory
, ¶ms
);
6026 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6028 /* detect old dwrite version, that is using higher threshold value */
6029 g_is_vista
= fontface1
== NULL
;
6031 for (emsize
= 1.0; emsize
< 500.0; emsize
+= 1.0) {
6032 DWRITE_RENDERING_MODE expected
;
6037 for (i
= 0; i
< ARRAY_SIZE(recmode_tests
); i
++) {
6040 gasp
= get_gasp_flags(fontface
, emsize
, ppdip
);
6041 expected
= get_expected_rendering_mode(emsize
* ppdip
, gasp
, recmode_tests
[i
].measuring
, recmode_tests
[i
].threshold
);
6042 hr
= IDWriteFontFace_GetRecommendedRenderingMode(fontface
, emsize
, ppdip
, recmode_tests
[i
].measuring
, params
, &mode
);
6043 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6044 ok(mode
== expected
, "%.2f/%d: got %d, ppdip %f, flags 0x%04x, expected %d\n", emsize
, i
, mode
, ppdip
, gasp
, expected
);
6046 /* some ppdip variants */
6049 gasp
= get_gasp_flags(fontface
, emsize
, ppdip
);
6050 expected
= get_expected_rendering_mode(emsize
* ppdip
, gasp
, recmode_tests
[i
].measuring
, recmode_tests
[i
].threshold
);
6051 hr
= IDWriteFontFace_GetRecommendedRenderingMode(fontface
, emsize
, ppdip
, recmode_tests
[i
].measuring
, params
, &mode
);
6052 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6053 ok(mode
== expected
, "%.2f/%d: got %d, ppdip %f, flags 0x%04x, expected %d\n", emsize
, i
, mode
, ppdip
, gasp
, expected
);
6055 /* Only test larger sizes to workaround Win7 differences, where unscaled natural emsize threshold is used;
6056 Win8 and Win10 handle this as expected. */
6057 if (emsize
> 20.0f
) {
6060 gasp
= get_gasp_flags(fontface
, emsize
, ppdip
);
6061 expected
= get_expected_rendering_mode(emsize
* ppdip
, gasp
, recmode_tests
[i
].measuring
, recmode_tests
[i
].threshold
);
6062 hr
= IDWriteFontFace_GetRecommendedRenderingMode(fontface
, emsize
, ppdip
, recmode_tests
[i
].measuring
, params
, &mode
);
6063 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6064 ok(mode
== expected
, "%.2f/%d: got %d, ppdip %f, flags 0x%04x, expected %d\n", emsize
, i
, mode
, ppdip
, gasp
, expected
);
6068 gasp
= get_gasp_flags(fontface
, emsize
, ppdip
);
6069 expected
= get_expected_rendering_mode(emsize
* ppdip
, gasp
, recmode_tests
[i
].measuring
, recmode_tests
[i
].threshold
);
6070 hr
= IDWriteFontFace_GetRecommendedRenderingMode(fontface
, emsize
, ppdip
, recmode_tests
[i
].measuring
, params
, &mode
);
6071 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6072 ok(mode
== expected
, "%.2f/%d: got %d, ppdip %f, flags 0x%04x, expected %d\n", emsize
, i
, mode
, ppdip
, gasp
, expected
);
6076 /* IDWriteFontFace1 offers another variant of this method */
6078 for (i
= 0; i
< ARRAY_SIZE(recmode_tests1
); i
++) {
6082 dpi
= 96.0f
* ppdip
;
6084 gasp
= get_gasp_flags(fontface
, emsize
, ppdip
);
6085 expected
= get_expected_rendering_mode(emsize
* ppdip
, gasp
, recmode_tests1
[i
].measuring
, recmode_tests1
[i
].threshold
);
6086 hr
= IDWriteFontFace1_GetRecommendedRenderingMode(fontface1
, emsize
, dpi
, dpi
,
6087 NULL
, FALSE
, recmode_tests1
[i
].threshold
, recmode_tests1
[i
].measuring
, &mode
);
6088 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6089 ok(mode
== expected
, "%.2f/%d: got %d, dpi %f, flags 0x%04x, expected %d\n", emsize
, i
, mode
, dpi
, gasp
, expected
);
6091 /* Only test larger sizes to workaround Win7 differences, where unscaled natural emsize threshold is used;
6092 Win8 and Win10 handle this as expected. */
6093 if (emsize
> 20.0f
) {
6095 dpi
= 96.0f
* ppdip
;
6097 gasp
= get_gasp_flags(fontface
, emsize
, ppdip
);
6098 expected
= get_expected_rendering_mode(emsize
* ppdip
, gasp
, recmode_tests1
[i
].measuring
, recmode_tests1
[i
].threshold
);
6099 hr
= IDWriteFontFace1_GetRecommendedRenderingMode(fontface1
, emsize
, dpi
, dpi
,
6100 NULL
, FALSE
, recmode_tests1
[i
].threshold
, recmode_tests1
[i
].measuring
, &mode
);
6101 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6102 ok(mode
== expected
, "%.2f/%d: got %d, dpi %f, flags 0x%04x, expected %d\n", emsize
, i
, mode
, dpi
, gasp
, expected
);
6105 dpi
= 96.0f
* ppdip
;
6107 gasp
= get_gasp_flags(fontface
, emsize
, ppdip
);
6108 expected
= get_expected_rendering_mode(emsize
* ppdip
, gasp
, recmode_tests1
[i
].measuring
, recmode_tests1
[i
].threshold
);
6109 hr
= IDWriteFontFace1_GetRecommendedRenderingMode(fontface1
, emsize
, dpi
, dpi
,
6110 NULL
, FALSE
, recmode_tests1
[i
].threshold
, recmode_tests1
[i
].measuring
, &mode
);
6111 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6112 ok(mode
== expected
, "%.2f/%d: got %d, dpi %f, flags 0x%04x, expected %d\n", emsize
, i
, mode
, dpi
, gasp
, expected
);
6114 /* try different dpis for X and Y direction */
6116 dpi
= 96.0f
* ppdip
;
6118 gasp
= get_gasp_flags(fontface
, emsize
, ppdip
);
6119 expected
= get_expected_rendering_mode(emsize
* ppdip
, gasp
, recmode_tests1
[i
].measuring
, recmode_tests1
[i
].threshold
);
6120 hr
= IDWriteFontFace1_GetRecommendedRenderingMode(fontface1
, emsize
, dpi
* 0.5f
, dpi
,
6121 NULL
, FALSE
, recmode_tests1
[i
].threshold
, recmode_tests1
[i
].measuring
, &mode
);
6122 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6123 ok(mode
== expected
, "%.2f/%d: got %d, dpi %f, flags 0x%04x, expected %d\n", emsize
, i
, mode
, dpi
, gasp
, expected
);
6126 dpi
= 96.0f
* ppdip
;
6128 gasp
= get_gasp_flags(fontface
, emsize
, ppdip
);
6129 expected
= get_expected_rendering_mode(emsize
* ppdip
, gasp
, recmode_tests1
[i
].measuring
, recmode_tests1
[i
].threshold
);
6130 hr
= IDWriteFontFace1_GetRecommendedRenderingMode(fontface1
, emsize
, dpi
, dpi
* 0.5f
,
6131 NULL
, FALSE
, recmode_tests1
[i
].threshold
, recmode_tests1
[i
].measuring
, &mode
);
6132 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6133 ok(mode
== expected
, "%.2f/%d: got %d, dpi %f, flags 0x%04x, expected %d\n", emsize
, i
, mode
, dpi
, gasp
, expected
);
6136 dpi
= 96.0f
* ppdip
;
6138 gasp
= get_gasp_flags(fontface
, emsize
, ppdip
);
6139 expected
= get_expected_rendering_mode(emsize
* ppdip
, gasp
, recmode_tests1
[i
].measuring
, recmode_tests1
[i
].threshold
);
6140 hr
= IDWriteFontFace1_GetRecommendedRenderingMode(fontface1
, emsize
, dpi
* 0.5f
, dpi
,
6141 NULL
, FALSE
, recmode_tests1
[i
].threshold
, recmode_tests1
[i
].measuring
, &mode
);
6142 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6143 ok(mode
== expected
, "%.2f/%d: got %d, dpi %f, flags 0x%04x, expected %d\n", emsize
, i
, mode
, dpi
, gasp
, expected
);
6146 dpi
= 96.0f
* ppdip
;
6148 gasp
= get_gasp_flags(fontface
, emsize
, ppdip
);
6149 expected
= get_expected_rendering_mode(emsize
* ppdip
, gasp
, recmode_tests1
[i
].measuring
, recmode_tests1
[i
].threshold
);
6150 hr
= IDWriteFontFace1_GetRecommendedRenderingMode(fontface1
, emsize
, dpi
, dpi
* 0.5f
,
6151 NULL
, FALSE
, recmode_tests1
[i
].threshold
, recmode_tests1
[i
].measuring
, &mode
);
6152 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6153 ok(mode
== expected
, "%.2f/%d: got %d, dpi %f, flags 0x%04x, expected %d\n", emsize
, i
, mode
, dpi
, gasp
, expected
);
6158 /* IDWriteFontFace2 - another one */
6160 DWRITE_GRID_FIT_MODE gridfit
, expected_gridfit
;
6162 gasp
= get_gasp_flags(fontface
, emsize
, 1.0f
);
6163 for (i
= 0; i
< ARRAY_SIZE(recmode_tests1
); i
++) {
6165 expected
= get_expected_rendering_mode(emsize
, gasp
, recmode_tests1
[i
].measuring
, recmode_tests1
[i
].threshold
);
6166 expected_gridfit
= get_expected_gridfit_mode(emsize
, gasp
, recmode_tests1
[i
].measuring
, recmode_tests1
[i
].threshold
);
6167 hr
= IDWriteFontFace2_GetRecommendedRenderingMode(fontface2
, emsize
, 96.0f
, 96.0f
,
6168 NULL
, FALSE
, recmode_tests1
[i
].threshold
, recmode_tests1
[i
].measuring
, params
, &mode
, &gridfit
);
6169 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6170 ok(mode
== expected
, "%.2f: got %d, flags 0x%04x, expected %d\n", emsize
, mode
, gasp
, expected
);
6171 ok(gridfit
== expected_gridfit
, "%.2f/%d: gridfit: got %d, flags 0x%04x, expected %d\n", emsize
, i
, gridfit
,
6172 gasp
, expected_gridfit
);
6176 /* IDWriteFontFace3 - and another one */
6178 DWRITE_GRID_FIT_MODE gridfit
, expected_gridfit
;
6179 DWRITE_RENDERING_MODE1 mode1
, expected1
;
6181 gasp
= get_gasp_flags(fontface
, emsize
, 1.0f
);
6182 for (i
= 0; i
< ARRAY_SIZE(recmode_tests1
); i
++) {
6184 expected1
= get_expected_rendering_mode(emsize
, gasp
, recmode_tests1
[i
].measuring
, recmode_tests1
[i
].threshold
);
6185 expected_gridfit
= get_expected_gridfit_mode(emsize
, gasp
, recmode_tests1
[i
].measuring
, recmode_tests1
[i
].threshold
);
6186 hr
= IDWriteFontFace3_GetRecommendedRenderingMode(fontface3
, emsize
, 96.0f
, 96.0f
,
6187 NULL
, FALSE
, recmode_tests1
[i
].threshold
, recmode_tests1
[i
].measuring
, params
, &mode1
, &gridfit
);
6188 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6189 ok(mode1
== expected1
, "%.2f: got %d, flags 0x%04x, expected %d\n", emsize
, mode1
, gasp
, expected1
);
6190 ok(gridfit
== expected_gridfit
, "%.2f/%d: gridfit: got %d, flags 0x%04x, expected %d\n", emsize
, i
, gridfit
,
6191 gasp
, expected_gridfit
);
6196 IDWriteRenderingParams_Release(params
);
6198 /* test how parameters override returned modes */
6199 hr
= IDWriteFactory_CreateCustomRenderingParams(factory
, 1.0, 0.0, 0.0, DWRITE_PIXEL_GEOMETRY_FLAT
,
6200 DWRITE_RENDERING_MODE_GDI_CLASSIC
, ¶ms
);
6201 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6204 hr
= IDWriteFontFace_GetRecommendedRenderingMode(fontface
, 500.0, 1.0, DWRITE_MEASURING_MODE_NATURAL
, params
, &mode
);
6205 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6206 ok(mode
== DWRITE_RENDERING_MODE_GDI_CLASSIC
, "got %d\n", mode
);
6208 IDWriteRenderingParams_Release(params
);
6211 IDWriteRenderingParams2
*params2
;
6212 IDWriteFactory2
*factory2
;
6213 DWRITE_GRID_FIT_MODE gridfit
;
6215 hr
= IDWriteFactory_QueryInterface(factory
, &IID_IDWriteFactory2
, (void**)&factory2
);
6216 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6218 hr
= IDWriteFactory2_CreateCustomRenderingParams(factory2
, 1.0, 0.0, 0.0, 0.5, DWRITE_PIXEL_GEOMETRY_FLAT
,
6219 DWRITE_RENDERING_MODE_OUTLINE
, DWRITE_GRID_FIT_MODE_ENABLED
, ¶ms2
);
6220 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6224 hr
= IDWriteFontFace2_GetRecommendedRenderingMode(fontface2
, 5.0, 96.0, 96.0,
6225 NULL
, FALSE
, DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
, DWRITE_MEASURING_MODE_GDI_CLASSIC
,
6226 NULL
, &mode
, &gridfit
);
6227 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6228 ok(mode
== DWRITE_RENDERING_MODE_GDI_CLASSIC
, "got %d\n", mode
);
6229 ok(gridfit
== DWRITE_GRID_FIT_MODE_ENABLED
, "got %d\n", gridfit
);
6233 hr
= IDWriteFontFace2_GetRecommendedRenderingMode(fontface2
, 5.0, 96.0, 96.0,
6234 NULL
, FALSE
, DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
, DWRITE_MEASURING_MODE_GDI_CLASSIC
,
6235 (IDWriteRenderingParams
*)params2
, &mode
, &gridfit
);
6236 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6237 ok(mode
== DWRITE_RENDERING_MODE_OUTLINE
, "got %d\n", mode
);
6238 ok(gridfit
== DWRITE_GRID_FIT_MODE_ENABLED
, "got %d\n", gridfit
);
6240 IDWriteRenderingParams2_Release(params2
);
6241 IDWriteFactory2_Release(factory2
);
6245 IDWriteRenderingParams3
*params3
;
6246 IDWriteRenderingParams2
*params2
;
6247 IDWriteRenderingParams
*params
;
6248 IDWriteFactory3
*factory3
;
6249 DWRITE_GRID_FIT_MODE gridfit
;
6250 DWRITE_RENDERING_MODE1 mode1
;
6252 hr
= IDWriteFactory_QueryInterface(factory
, &IID_IDWriteFactory3
, (void**)&factory3
);
6253 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6255 hr
= IDWriteFactory3_CreateCustomRenderingParams(factory3
, 1.0f
, 0.0f
, 0.0f
, 0.5f
, DWRITE_PIXEL_GEOMETRY_FLAT
,
6256 DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC_DOWNSAMPLED
, DWRITE_GRID_FIT_MODE_ENABLED
, ¶ms3
);
6257 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6259 mode1
= IDWriteRenderingParams3_GetRenderingMode1(params3
);
6260 ok(mode1
== DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC_DOWNSAMPLED
, "got %d\n", mode1
);
6262 mode
= IDWriteRenderingParams3_GetRenderingMode(params3
);
6263 ok(mode
== DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
, "got %d\n", mode
);
6265 hr
= IDWriteRenderingParams3_QueryInterface(params3
, &IID_IDWriteRenderingParams
, (void**)¶ms
);
6266 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6267 ok(params
== (IDWriteRenderingParams
*)params3
, "got %p, %p\n", params3
, params
);
6268 mode
= IDWriteRenderingParams_GetRenderingMode(params
);
6269 ok(mode
== DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
, "got %d\n", mode
);
6270 IDWriteRenderingParams_Release(params
);
6272 hr
= IDWriteRenderingParams3_QueryInterface(params3
, &IID_IDWriteRenderingParams2
, (void**)¶ms2
);
6273 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6274 ok(params2
== (IDWriteRenderingParams2
*)params3
, "got %p, %p\n", params3
, params2
);
6275 mode
= IDWriteRenderingParams2_GetRenderingMode(params2
);
6276 ok(mode
== DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
, "got %d\n", mode
);
6277 IDWriteRenderingParams2_Release(params2
);
6281 hr
= IDWriteFontFace2_GetRecommendedRenderingMode(fontface2
, 5.0f
, 96.0f
, 96.0f
,
6282 NULL
, FALSE
, DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
, DWRITE_MEASURING_MODE_GDI_CLASSIC
,
6283 NULL
, &mode
, &gridfit
);
6284 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6285 ok(mode
== DWRITE_RENDERING_MODE_GDI_CLASSIC
, "got %d\n", mode
);
6286 ok(gridfit
== DWRITE_GRID_FIT_MODE_ENABLED
, "got %d\n", gridfit
);
6290 hr
= IDWriteFontFace2_GetRecommendedRenderingMode(fontface2
, 5.0f
, 96.0f
, 96.0f
,
6291 NULL
, FALSE
, DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
, DWRITE_MEASURING_MODE_GDI_CLASSIC
,
6292 (IDWriteRenderingParams
*)params3
, &mode
, &gridfit
);
6293 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6294 ok(mode
== DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
, "got %d\n", mode
);
6295 ok(gridfit
== DWRITE_GRID_FIT_MODE_ENABLED
, "got %d\n", gridfit
);
6297 IDWriteRenderingParams3_Release(params3
);
6298 IDWriteFactory3_Release(factory3
);
6302 IDWriteFontFace3_Release(fontface3
);
6304 IDWriteFontFace2_Release(fontface2
);
6306 IDWriteFontFace1_Release(fontface1
);
6307 IDWriteFontFace_Release(fontface
);
6308 ref
= IDWriteFactory_Release(factory
);
6309 ok(ref
== 0, "factory not released, %u\n", ref
);
6312 static inline BOOL
float_eq(FLOAT left
, FLOAT right
)
6314 int x
= *(int *)&left
;
6315 int y
= *(int *)&right
;
6322 return abs(x
- y
) <= 8;
6325 static void test_GetAlphaBlendParams(void)
6327 static const DWRITE_RENDERING_MODE rendermodes
[] = {
6328 DWRITE_RENDERING_MODE_ALIASED
,
6329 DWRITE_RENDERING_MODE_GDI_CLASSIC
,
6330 DWRITE_RENDERING_MODE_GDI_NATURAL
,
6331 DWRITE_RENDERING_MODE_NATURAL
,
6332 DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
,
6335 IDWriteGlyphRunAnalysis
*analysis
;
6336 FLOAT gamma
, contrast
, ctlevel
;
6337 IDWriteRenderingParams
*params
;
6338 DWRITE_GLYPH_METRICS metrics
;
6339 DWRITE_GLYPH_OFFSET offset
;
6340 IDWriteFontFace
*fontface
;
6341 IDWriteFactory
*factory
;
6342 DWRITE_GLYPH_RUN run
;
6343 FLOAT advance
, expected_gdi_gamma
;
6351 factory
= create_factory();
6352 fontface
= create_fontface(factory
);
6356 hr
= IDWriteFontFace_GetGlyphIndices(fontface
, &ch
, 1, &glyph
);
6357 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6358 ok(glyph
> 0, "got %u\n", glyph
);
6360 hr
= IDWriteFontFace_GetDesignGlyphMetrics(fontface
, &glyph
, 1, &metrics
, FALSE
);
6361 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6362 advance
= metrics
.advanceWidth
;
6364 offset
.advanceOffset
= 0.0;
6365 offset
.ascenderOffset
= 0.0;
6367 run
.fontFace
= fontface
;
6368 run
.fontEmSize
= 24.0;
6370 run
.glyphIndices
= &glyph
;
6371 run
.glyphAdvances
= &advance
;
6372 run
.glyphOffsets
= &offset
;
6373 run
.isSideways
= FALSE
;
6376 hr
= IDWriteFactory_CreateCustomRenderingParams(factory
, 0.9, 0.3, 0.1, DWRITE_PIXEL_GEOMETRY_RGB
,
6377 DWRITE_RENDERING_MODE_DEFAULT
, ¶ms
);
6378 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6381 ret
= SystemParametersInfoW(SPI_GETFONTSMOOTHINGCONTRAST
, 0, &value
, 0);
6382 ok(ret
, "got %d\n", ret
);
6383 expected_gdi_gamma
= (FLOAT
)(value
/ 1000.0);
6385 for (i
= 0; i
< ARRAY_SIZE(rendermodes
); i
++) {
6386 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 1.0, NULL
,
6387 rendermodes
[i
], DWRITE_MEASURING_MODE_NATURAL
,
6388 0.0, 0.0, &analysis
);
6389 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6391 gamma
= contrast
= ctlevel
= -1.0;
6392 hr
= IDWriteGlyphRunAnalysis_GetAlphaBlendParams(analysis
, NULL
, &gamma
, &contrast
, &ctlevel
);
6393 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
6394 ok(gamma
== -1.0, "got %.2f\n", gamma
);
6395 ok(contrast
== -1.0, "got %.2f\n", contrast
);
6396 ok(ctlevel
== -1.0, "got %.2f\n", ctlevel
);
6398 gamma
= contrast
= ctlevel
= -1.0;
6399 hr
= IDWriteGlyphRunAnalysis_GetAlphaBlendParams(analysis
, params
, &gamma
, &contrast
, &ctlevel
);
6400 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6402 if (rendermodes
[i
] == DWRITE_RENDERING_MODE_GDI_CLASSIC
|| rendermodes
[i
] == DWRITE_RENDERING_MODE_GDI_NATURAL
) {
6403 ok(float_eq(gamma
, expected_gdi_gamma
), "got %.2f, expected %.2f\n", gamma
, expected_gdi_gamma
);
6404 ok(contrast
== 0.0f
, "got %.2f\n", contrast
);
6405 ok(ctlevel
== 1.0f
, "got %.2f\n", ctlevel
);
6408 ok(gamma
== 0.9f
, "got %.2f\n", gamma
);
6409 ok(contrast
== 0.3f
, "got %.2f\n", contrast
);
6410 ok(ctlevel
== 0.1f
, "got %.2f\n", ctlevel
);
6413 IDWriteGlyphRunAnalysis_Release(analysis
);
6416 IDWriteRenderingParams_Release(params
);
6417 IDWriteFontFace_Release(fontface
);
6418 ref
= IDWriteFactory_Release(factory
);
6419 ok(ref
== 0, "factory not released, %u\n", ref
);
6422 static void test_CreateAlphaTexture(void)
6424 IDWriteGlyphRunAnalysis
*analysis
;
6425 DWRITE_GLYPH_METRICS metrics
;
6426 DWRITE_GLYPH_OFFSET offset
;
6427 IDWriteFontFace
*fontface
;
6428 IDWriteFactory
*factory
;
6429 DWRITE_GLYPH_RUN run
;
6438 factory
= create_factory();
6439 fontface
= create_fontface(factory
);
6443 hr
= IDWriteFontFace_GetGlyphIndices(fontface
, &ch
, 1, &glyph
);
6444 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6445 ok(glyph
> 0, "got %u\n", glyph
);
6447 hr
= IDWriteFontFace_GetDesignGlyphMetrics(fontface
, &glyph
, 1, &metrics
, FALSE
);
6448 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6449 advance
= metrics
.advanceWidth
;
6451 offset
.advanceOffset
= 0.0;
6452 offset
.ascenderOffset
= 0.0;
6454 run
.fontFace
= fontface
;
6455 run
.fontEmSize
= 24.0;
6457 run
.glyphIndices
= &glyph
;
6458 run
.glyphAdvances
= &advance
;
6459 run
.glyphOffsets
= &offset
;
6460 run
.isSideways
= FALSE
;
6463 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 1.0, NULL
,
6464 DWRITE_RENDERING_MODE_NATURAL
, DWRITE_MEASURING_MODE_NATURAL
,
6465 0.0, 0.0, &analysis
);
6466 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6468 SetRectEmpty(&bounds
);
6469 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_CLEARTYPE_3x1
, &bounds
);
6470 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6471 ok(!IsRectEmpty(&bounds
), "got empty rect\n");
6472 size
= (bounds
.right
- bounds
.left
)*(bounds
.bottom
- bounds
.top
)*3;
6473 ok(sizeof(buff
) >= size
, "required %u\n", size
);
6475 /* invalid type value */
6476 memset(buff
, 0xcf, sizeof(buff
));
6477 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_CLEARTYPE_3x1
+1, &bounds
, buff
, sizeof(buff
));
6478 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
6479 ok(buff
[0] == 0xcf, "got %1x\n", buff
[0]);
6481 memset(buff
, 0xcf, sizeof(buff
));
6482 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &bounds
, buff
, 2);
6483 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
6484 ok(buff
[0] == 0xcf, "got %1x\n", buff
[0]);
6486 /* vista version allows texture type mismatch, mark it broken for now */
6487 memset(buff
, 0xcf, sizeof(buff
));
6488 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &bounds
, buff
, sizeof(buff
));
6489 ok(hr
== DWRITE_E_UNSUPPORTEDOPERATION
|| broken(hr
== S_OK
), "got 0x%08x\n", hr
);
6490 ok(buff
[0] == 0xcf || broken(buff
[0] == 0), "got %1x\n", buff
[0]);
6492 memset(buff
, 0xcf, sizeof(buff
));
6493 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_CLEARTYPE_3x1
, &bounds
, buff
, size
-1);
6494 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
6495 ok(buff
[0] == 0xcf, "got %1x\n", buff
[0]);
6497 IDWriteGlyphRunAnalysis_Release(analysis
);
6499 hr
= IDWriteFactory_CreateGlyphRunAnalysis(factory
, &run
, 1.0, NULL
,
6500 DWRITE_RENDERING_MODE_ALIASED
, DWRITE_MEASURING_MODE_GDI_CLASSIC
,
6501 0.0, 0.0, &analysis
);
6502 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6504 SetRectEmpty(&bounds
);
6505 hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &bounds
);
6506 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6507 ok(!IsRectEmpty(&bounds
), "got empty rect\n");
6508 size
= (bounds
.right
- bounds
.left
)*(bounds
.bottom
- bounds
.top
);
6509 ok(sizeof(buff
) >= size
, "required %u\n", size
);
6511 memset(buff
, 0xcf, sizeof(buff
));
6512 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, NULL
, buff
, sizeof(buff
));
6513 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
6514 ok(buff
[0] == 0xcf, "got %1x\n", buff
[0]);
6516 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, NULL
, NULL
, sizeof(buff
));
6517 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
6519 memset(buff
, 0xcf, sizeof(buff
));
6520 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, NULL
, buff
, 0);
6521 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
6522 ok(buff
[0] == 0xcf, "got %1x\n", buff
[0]);
6524 /* buffer size is not enough */
6525 memset(buff
, 0xcf, sizeof(buff
));
6526 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &bounds
, buff
, size
-1);
6527 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
6528 ok(buff
[0] == 0xcf, "got %1x\n", buff
[0]);
6530 /* request texture for rectangle that doesn't intersect */
6531 memset(buff
, 0xcf, sizeof(buff
));
6533 OffsetRect(&r
, (bounds
.right
- bounds
.left
)*2, 0);
6534 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &r
, buff
, sizeof(buff
));
6535 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6536 ok(buff
[0] == 0, "got %1x\n", buff
[0]);
6538 memset(buff
, 0xcf, sizeof(buff
));
6540 OffsetRect(&r
, (bounds
.right
- bounds
.left
)*2, 0);
6541 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &r
, buff
, sizeof(buff
));
6542 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6543 ok(buff
[0] == 0, "got %1x\n", buff
[0]);
6545 /* request texture for rectangle that doesn't intersect, small buffer */
6546 memset(buff
, 0xcf, sizeof(buff
));
6548 OffsetRect(&r
, (bounds
.right
- bounds
.left
)*2, 0);
6549 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_ALIASED_1x1
, &r
, buff
, size
-1);
6550 ok(hr
== E_NOT_SUFFICIENT_BUFFER
, "got 0x%08x\n", hr
);
6551 ok(buff
[0] == 0xcf, "got %1x\n", buff
[0]);
6553 /* vista version allows texture type mismatch, mark it broken for now */
6554 memset(buff
, 0xcf, sizeof(buff
));
6555 hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
, DWRITE_TEXTURE_CLEARTYPE_3x1
, &bounds
, buff
, sizeof(buff
));
6556 ok(hr
== DWRITE_E_UNSUPPORTEDOPERATION
|| broken(hr
== S_OK
), "got 0x%08x\n", hr
);
6557 ok(buff
[0] == 0xcf || broken(buff
[0] == 0), "got %1x\n", buff
[0]);
6559 IDWriteGlyphRunAnalysis_Release(analysis
);
6560 IDWriteFontFace_Release(fontface
);
6561 ref
= IDWriteFactory_Release(factory
);
6562 ok(ref
== 0, "factory not released, %u\n", ref
);
6565 static void test_IsSymbolFont(void)
6567 static const WCHAR symbolW
[] = {'S','y','m','b','o','l',0};
6568 IDWriteFontCollection
*collection
;
6569 IDWriteFontFace
*fontface
;
6570 IDWriteFactory
*factory
;
6576 factory
= create_factory();
6579 fontface
= create_fontface(factory
);
6580 ret
= IDWriteFontFace_IsSymbolFont(fontface
);
6581 ok(!ret
, "got %d\n", ret
);
6583 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &collection
, FALSE
);
6584 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6586 hr
= IDWriteFontCollection_GetFontFromFontFace(collection
, fontface
, &font
);
6587 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6589 ret
= IDWriteFont_IsSymbolFont(font
);
6590 ok(!ret
, "got %d\n", ret
);
6592 IDWriteFontCollection_Release(collection
);
6593 IDWriteFont_Release(font
);
6594 IDWriteFontFace_Release(fontface
);
6597 font
= get_font(factory
, symbolW
, DWRITE_FONT_STYLE_NORMAL
);
6598 ret
= IDWriteFont_IsSymbolFont(font
);
6599 ok(ret
, "got %d\n", ret
);
6601 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
6602 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6603 ret
= IDWriteFontFace_IsSymbolFont(fontface
);
6604 ok(ret
, "got %d\n", ret
);
6605 IDWriteFontFace_Release(fontface
);
6606 IDWriteFont_Release(font
);
6608 ref
= IDWriteFactory_Release(factory
);
6609 ok(ref
== 0, "factory not released, %u\n", ref
);
6612 struct CPAL_Header_0
6615 USHORT numPaletteEntries
;
6617 USHORT numColorRecords
;
6618 ULONG offsetFirstColorRecord
;
6619 USHORT colorRecordIndices
[1];
6622 static void test_GetPaletteEntries(void)
6624 IDWriteFontFace2
*fontface2
;
6625 IDWriteFontFace
*fontface
;
6626 IDWriteFactory
*factory
;
6628 DWRITE_COLOR_F color
;
6629 UINT32 palettecount
, entrycount
, size
, colorrecords
;
6631 const struct CPAL_Header_0
*cpal_header
;
6636 factory
= create_factory();
6638 /* Tahoma, no color support */
6639 fontface
= create_fontface(factory
);
6640 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace2
, (void**)&fontface2
);
6641 IDWriteFontFace_Release(fontface
);
6643 ref
= IDWriteFactory_Release(factory
);
6644 ok(ref
== 0, "factory not released, %u\n", ref
);
6645 win_skip("GetPaletteEntries() is not supported.\n");
6649 hr
= IDWriteFontFace2_GetPaletteEntries(fontface2
, 0, 0, 1, &color
);
6650 ok(hr
== DWRITE_E_NOCOLOR
, "got 0x%08x\n", hr
);
6651 IDWriteFontFace2_Release(fontface2
);
6653 /* Segoe UI Emoji, with color support */
6654 font
= get_font(factory
, emojiW
, DWRITE_FONT_STYLE_NORMAL
);
6656 ref
= IDWriteFactory_Release(factory
);
6657 ok(ref
== 0, "factory not released, %u\n", ref
);
6658 skip("Segoe UI Emoji font not found.\n");
6662 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
6663 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6664 IDWriteFont_Release(font
);
6666 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace2
, (void**)&fontface2
);
6667 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6668 IDWriteFontFace_Release(fontface
);
6670 palettecount
= IDWriteFontFace2_GetColorPaletteCount(fontface2
);
6671 ok(palettecount
>= 1, "got %u\n", palettecount
);
6673 entrycount
= IDWriteFontFace2_GetPaletteEntryCount(fontface2
);
6674 ok(entrycount
>= 1, "got %u\n", entrycount
);
6677 hr
= IDWriteFontFace2_TryGetFontTable(fontface2
, MS_CPAL_TAG
, (const void**)&cpal_header
, &size
, &ctxt
, &exists
);
6678 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6679 ok(exists
, "got %d\n", exists
);
6680 colorrecords
= GET_BE_WORD(cpal_header
->numColorRecords
);
6681 ok(colorrecords
>= 1, "got %u\n", colorrecords
);
6683 /* invalid palette index */
6684 color
.r
= color
.g
= color
.b
= color
.a
= 123.0;
6685 hr
= IDWriteFontFace2_GetPaletteEntries(fontface2
, palettecount
, 0, 1, &color
);
6686 ok(hr
== DWRITE_E_NOCOLOR
, "got 0x%08x\n", hr
);
6687 ok(color
.r
== 123.0 && color
.g
== 123.0 && color
.b
== 123.0 && color
.a
== 123.0,
6688 "got wrong color %.2fx%.2fx%.2fx%.2f\n", color
.r
, color
.g
, color
.b
, color
.a
);
6690 /* invalid entry index */
6691 color
.r
= color
.g
= color
.b
= color
.a
= 123.0;
6692 hr
= IDWriteFontFace2_GetPaletteEntries(fontface2
, 0, entrycount
, 1, &color
);
6693 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
6694 ok(color
.r
== 123.0 && color
.g
== 123.0 && color
.b
== 123.0 && color
.a
== 123.0,
6695 "got wrong color %.2fx%.2fx%.2fx%.2f\n", color
.r
, color
.g
, color
.b
, color
.a
);
6697 color
.r
= color
.g
= color
.b
= color
.a
= 123.0;
6698 hr
= IDWriteFontFace2_GetPaletteEntries(fontface2
, 0, entrycount
- 1, 1, &color
);
6699 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6700 ok(color
.r
!= 123.0 && color
.g
!= 123.0 && color
.b
!= 123.0 && color
.a
!= 123.0,
6701 "got wrong color %.2fx%.2fx%.2fx%.2f\n", color
.r
, color
.g
, color
.b
, color
.a
);
6703 /* zero return length */
6704 color
.r
= color
.g
= color
.b
= color
.a
= 123.0;
6705 hr
= IDWriteFontFace2_GetPaletteEntries(fontface2
, 0, 0, 0, &color
);
6706 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6707 ok(color
.r
== 123.0 && color
.g
== 123.0 && color
.b
== 123.0 && color
.a
== 123.0,
6708 "got wrong color %.2fx%.2fx%.2fx%.2f\n", color
.r
, color
.g
, color
.b
, color
.a
);
6710 IDWriteFontFace2_Release(fontface2
);
6711 ref
= IDWriteFactory_Release(factory
);
6712 ok(ref
== 0, "factory not released, %u\n", ref
);
6715 static void test_TranslateColorGlyphRun(void)
6717 IDWriteColorGlyphRunEnumerator
*layers
;
6718 const DWRITE_COLOR_GLYPH_RUN
*colorrun
;
6719 IDWriteFontFace2
*fontface2
;
6720 IDWriteFontFace
*fontface
;
6721 IDWriteFactory2
*factory
;
6722 DWRITE_GLYPH_RUN run
;
6723 UINT32 codepoints
[2];
6730 factory
= create_factory_iid(&IID_IDWriteFactory2
);
6732 win_skip("TranslateColorGlyphRun() is not supported.\n");
6736 /* Tahoma, no color support */
6737 fontface
= create_fontface((IDWriteFactory
*)factory
);
6739 codepoints
[0] = 'A';
6740 hr
= IDWriteFontFace_GetGlyphIndices(fontface
, codepoints
, 1, glyphs
);
6741 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6743 run
.fontFace
= fontface
;
6744 run
.fontEmSize
= 20.0f
;
6746 run
.glyphIndices
= glyphs
;
6747 run
.glyphAdvances
= NULL
;
6748 run
.glyphOffsets
= NULL
;
6749 run
.isSideways
= FALSE
;
6752 layers
= (void*)0xdeadbeef;
6753 hr
= IDWriteFactory2_TranslateColorGlyphRun(factory
, 0.0f
, 0.0f
, &run
, NULL
,
6754 DWRITE_MEASURING_MODE_NATURAL
, NULL
, 0, &layers
);
6755 ok(hr
== DWRITE_E_NOCOLOR
, "got 0x%08x\n", hr
);
6756 ok(layers
== NULL
, "got %p\n", layers
);
6757 IDWriteFontFace_Release(fontface
);
6759 /* Segoe UI Emoji, with color support */
6760 font
= get_font((IDWriteFactory
*)factory
, emojiW
, DWRITE_FONT_STYLE_NORMAL
);
6762 IDWriteFactory2_Release(factory
);
6763 skip("Segoe UI Emoji font not found.\n");
6767 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
6768 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6769 IDWriteFont_Release(font
);
6771 codepoints
[0] = 0x26c4;
6772 hr
= IDWriteFontFace_GetGlyphIndices(fontface
, codepoints
, 1, glyphs
);
6773 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6775 run
.fontFace
= fontface
;
6778 hr
= IDWriteFactory2_TranslateColorGlyphRun(factory
, 0.0f
, 0.0f
, &run
, NULL
,
6779 DWRITE_MEASURING_MODE_NATURAL
, NULL
, 0, &layers
);
6780 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6781 ok(layers
!= NULL
, "got %p\n", layers
);
6785 hr
= IDWriteColorGlyphRunEnumerator_MoveNext(layers
, &hasrun
);
6786 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6791 hr
= IDWriteColorGlyphRunEnumerator_GetCurrentRun(layers
, &colorrun
);
6792 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6793 ok(colorrun
->glyphRun
.fontFace
!= NULL
, "got fontface %p\n", colorrun
->glyphRun
.fontFace
);
6794 ok(colorrun
->glyphRun
.fontEmSize
== 20.0f
, "got wrong font size %f\n", colorrun
->glyphRun
.fontEmSize
);
6795 ok(colorrun
->glyphRun
.glyphCount
> 0, "got wrong glyph count %u\n", colorrun
->glyphRun
.glyphCount
);
6796 ok(colorrun
->glyphRun
.glyphIndices
!= NULL
, "got null glyph indices %p\n", colorrun
->glyphRun
.glyphIndices
);
6797 ok(colorrun
->glyphRun
.glyphAdvances
!= NULL
, "got null glyph advances %p\n", colorrun
->glyphRun
.glyphAdvances
);
6800 /* iterated all way through */
6801 hr
= IDWriteColorGlyphRunEnumerator_GetCurrentRun(layers
, &colorrun
);
6802 ok(hr
== E_NOT_VALID_STATE
, "got 0x%08x\n", hr
);
6804 IDWriteColorGlyphRunEnumerator_Release(layers
);
6806 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace2
, (void**)&fontface2
);
6807 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6809 /* invalid palette index */
6810 layers
= (void*)0xdeadbeef;
6811 hr
= IDWriteFactory2_TranslateColorGlyphRun(factory
, 0.0f
, 0.0f
, &run
, NULL
,
6812 DWRITE_MEASURING_MODE_NATURAL
, NULL
, IDWriteFontFace2_GetColorPaletteCount(fontface2
),
6814 ok(hr
== DWRITE_E_NOCOLOR
, "got 0x%08x\n", hr
);
6815 ok(layers
== NULL
, "got %p\n", layers
);
6818 hr
= IDWriteFactory2_TranslateColorGlyphRun(factory
, 0.0f
, 0.0f
, &run
, NULL
,
6819 DWRITE_MEASURING_MODE_NATURAL
, NULL
, IDWriteFontFace2_GetColorPaletteCount(fontface2
) - 1,
6821 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6822 IDWriteColorGlyphRunEnumerator_Release(layers
);
6824 /* color font, glyph without color info */
6825 codepoints
[0] = 'A';
6826 hr
= IDWriteFontFace_GetGlyphIndices(fontface
, codepoints
, 1, glyphs
);
6827 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6829 layers
= (void*)0xdeadbeef;
6830 hr
= IDWriteFactory2_TranslateColorGlyphRun(factory
, 0.0f
, 0.0f
, &run
, NULL
,
6831 DWRITE_MEASURING_MODE_NATURAL
, NULL
, 0, &layers
);
6832 ok(hr
== DWRITE_E_NOCOLOR
, "got 0x%08x\n", hr
);
6833 ok(layers
== NULL
, "got %p\n", layers
);
6835 /* one glyph with, one without */
6836 codepoints
[0] = 'A';
6837 codepoints
[1] = 0x26c4;
6839 hr
= IDWriteFontFace_GetGlyphIndices(fontface
, codepoints
, 2, glyphs
);
6840 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6845 hr
= IDWriteFactory2_TranslateColorGlyphRun(factory
, 0.0f
, 0.0f
, &run
, NULL
,
6846 DWRITE_MEASURING_MODE_NATURAL
, NULL
, 0, &layers
);
6847 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6848 ok(layers
!= NULL
, "got %p\n", layers
);
6849 IDWriteColorGlyphRunEnumerator_Release(layers
);
6851 IDWriteFontFace2_Release(fontface2
);
6852 IDWriteFontFace_Release(fontface
);
6853 ref
= IDWriteFactory2_Release(factory
);
6854 ok(ref
== 0, "factory not released, %u\n", ref
);
6857 static void test_HasCharacter(void)
6859 IDWriteFactory3
*factory3
;
6860 IDWriteFactory
*factory
;
6861 IDWriteFont3
*font3
;
6867 factory
= create_factory();
6869 font
= get_tahoma_instance(factory
, DWRITE_FONT_STYLE_NORMAL
);
6870 ok(font
!= NULL
, "failed to create font\n");
6872 /* Win8 is broken, QI claims to support IDWriteFont3, but in fact it does not */
6873 hr
= IDWriteFactory_QueryInterface(factory
, &IID_IDWriteFactory3
, (void**)&factory3
);
6875 hr
= IDWriteFont_QueryInterface(font
, &IID_IDWriteFont3
, (void**)&font3
);
6876 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6878 ret
= IDWriteFont3_HasCharacter(font3
, 'A');
6879 ok(ret
, "got %d\n", ret
);
6881 IDWriteFont3_Release(font3
);
6882 IDWriteFactory3_Release(factory3
);
6885 win_skip("IDWriteFont3 is not supported.\n");
6887 IDWriteFont_Release(font
);
6888 ref
= IDWriteFactory_Release(factory
);
6889 ok(ref
== 0, "factory not released, %u\n", ref
);
6892 static void test_CreateFontFaceReference(void)
6894 static const WCHAR dummyW
[] = {'d','u','m','m','y',0};
6895 IDWriteFontFace3
*fontface
, *fontface1
;
6896 IDWriteFontFaceReference
*ref
, *ref1
;
6897 IDWriteFontFile
*file
, *file1
;
6898 IDWriteFactory3
*factory
;
6899 IDWriteFont3
*font3
;
6907 factory
= create_factory_iid(&IID_IDWriteFactory3
);
6909 win_skip("CreateFontFaceReference() is not supported.\n");
6913 path
= create_testfontfile(test_fontfile
);
6915 hr
= IDWriteFactory3_CreateFontFaceReference(factory
, NULL
, NULL
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &ref
);
6916 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
6918 /* out of range simulation flags */
6919 hr
= IDWriteFactory3_CreateFontFaceReference(factory
, path
, NULL
, 0, ~0u, &ref
);
6920 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
6922 /* test file is not a collection, but reference could still be created with non-zero face index */
6923 hr
= IDWriteFactory3_CreateFontFaceReference(factory
, path
, NULL
, 1, DWRITE_FONT_SIMULATIONS_NONE
, &ref
);
6924 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6926 index
= IDWriteFontFaceReference_GetFontFaceIndex(ref
);
6927 ok(index
== 1, "got %u\n", index
);
6929 hr
= IDWriteFontFaceReference_GetFontFile(ref
, &file
);
6930 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6931 IDWriteFontFile_Release(file
);
6933 hr
= IDWriteFontFaceReference_CreateFontFace(ref
, &fontface
);
6935 ok(hr
== DWRITE_E_FILEFORMAT
, "got 0x%08x\n", hr
);
6937 IDWriteFontFaceReference_Release(ref
);
6939 /* path however has to be valid */
6940 hr
= IDWriteFactory3_CreateFontFaceReference(factory
, dummyW
, NULL
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &ref
);
6942 ok(hr
== DWRITE_E_FILENOTFOUND
, "got 0x%08x\n", hr
);
6944 IDWriteFontFaceReference_Release(ref
);
6946 EXPECT_REF(factory
, 1);
6947 hr
= IDWriteFactory3_CreateFontFaceReference(factory
, path
, NULL
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &ref
);
6948 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6949 EXPECT_REF(factory
, 2);
6951 /* new file is returned */
6952 hr
= IDWriteFontFaceReference_GetFontFile(ref
, &file
);
6953 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6955 hr
= IDWriteFontFaceReference_GetFontFile(ref
, &file1
);
6956 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6957 ok(file
!= file1
, "got %p, previous file %p\n", file1
, file
);
6959 IDWriteFontFile_Release(file
);
6960 IDWriteFontFile_Release(file1
);
6962 /* references are not reused */
6963 hr
= IDWriteFactory3_CreateFontFaceReference(factory
, path
, NULL
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &ref1
);
6964 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6965 ok(ref1
!= ref
, "got %p, previous ref %p\n", ref1
, ref
);
6967 /* created fontfaces are cached */
6968 hr
= IDWriteFontFaceReference_CreateFontFace(ref
, &fontface
);
6969 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6971 hr
= IDWriteFontFaceReference_CreateFontFace(ref1
, &fontface1
);
6972 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6973 ok(fontface
== fontface1
, "got %p, expected %p\n", fontface1
, fontface
);
6974 IDWriteFontFace3_Release(fontface
);
6975 IDWriteFontFace3_Release(fontface1
);
6977 /* reference equality */
6978 ret
= IDWriteFontFaceReference_Equals(ref
, ref1
);
6979 ok(ret
, "got %d\n", ret
);
6980 IDWriteFontFaceReference_Release(ref1
);
6982 hr
= IDWriteFactory3_CreateFontFaceReference(factory
, path
, NULL
, 1, DWRITE_FONT_SIMULATIONS_NONE
, &ref1
);
6983 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6984 ret
= IDWriteFontFaceReference_Equals(ref
, ref1
);
6985 ok(!ret
, "got %d\n", ret
);
6986 IDWriteFontFaceReference_Release(ref1
);
6988 hr
= IDWriteFactory3_CreateFontFaceReference(factory
, path
, NULL
, 0, DWRITE_FONT_SIMULATIONS_BOLD
, &ref1
);
6989 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
6990 ret
= IDWriteFontFaceReference_Equals(ref
, ref1
);
6991 ok(!ret
, "got %d\n", ret
);
6992 IDWriteFontFaceReference_Release(ref1
);
6994 IDWriteFontFaceReference_Release(ref
);
6996 /* create reference from a file */
6997 hr
= IDWriteFactory3_CreateFontFileReference(factory
, path
, NULL
, &file
);
6998 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7000 hr
= IDWriteFactory3_CreateFontFaceReference_(factory
, file
, 0, DWRITE_FONT_SIMULATIONS_NONE
, &ref
);
7001 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7003 hr
= IDWriteFontFaceReference_GetFontFile(ref
, &file1
);
7004 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7005 ok(file
!= file1
, "got %p, previous file %p\n", file1
, file
);
7007 IDWriteFontFaceReference_Release(ref
);
7008 IDWriteFontFile_Release(file
);
7009 IDWriteFontFile_Release(file1
);
7011 /* references returned from IDWriteFont3 */
7012 font
= get_tahoma_instance((IDWriteFactory
*)factory
, DWRITE_FONT_STYLE_NORMAL
);
7013 hr
= IDWriteFont_QueryInterface(font
, &IID_IDWriteFont3
, (void**)&font3
);
7014 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7015 IDWriteFont_Release(font
);
7017 hr
= IDWriteFont3_GetFontFaceReference(font3
, &ref
);
7018 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7020 hr
= IDWriteFont3_GetFontFaceReference(font3
, &ref1
);
7021 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7022 ok(ref
!= ref1
, "got %p, %p\n", ref1
, ref
);
7024 IDWriteFontFaceReference_Release(ref
);
7025 IDWriteFontFaceReference_Release(ref1
);
7027 /* references returned from IDWriteFontFace3 */
7028 hr
= IDWriteFont3_CreateFontFace(font3
, &fontface
);
7029 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7031 hr
= IDWriteFontFace3_GetFontFaceReference(fontface
, &ref
);
7033 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7035 hr
= IDWriteFontFace3_GetFontFaceReference(fontface
, &ref1
);
7037 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7039 ok(ref
== ref1
, "got %p, %p\n", ref1
, ref
);
7042 hr
= IDWriteFontFaceReference_CreateFontFace(ref
, &fontface1
);
7043 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7044 ok(fontface1
== fontface
, "got %p, %p\n", fontface1
, fontface
);
7045 IDWriteFontFace3_Release(fontface1
);
7047 IDWriteFontFaceReference_Release(ref
);
7048 IDWriteFontFaceReference_Release(ref1
);
7050 IDWriteFontFace3_Release(fontface
);
7051 IDWriteFont3_Release(font3
);
7053 refcount
= IDWriteFactory3_Release(factory
);
7054 ok(refcount
== 0, "factory not released, %u\n", refcount
);
7055 DELETE_FONTFILE(path
);
7058 static void get_expected_fontsig(IDWriteFont
*font
, FONTSIGNATURE
*fontsig
)
7061 IDWriteFontFace
*fontface
;
7062 const TT_OS2_V2
*tt_os2
;
7067 memset(fontsig
, 0, sizeof(*fontsig
));
7069 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
7070 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7072 hr
= IDWriteFontFace_TryGetFontTable(fontface
, MS_0S2_TAG
, (const void**)&tt_os2
, &size
, &os2_context
, &exists
);
7073 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7076 fontsig
->fsUsb
[0] = GET_BE_DWORD(tt_os2
->ulUnicodeRange1
);
7077 fontsig
->fsUsb
[1] = GET_BE_DWORD(tt_os2
->ulUnicodeRange2
);
7078 fontsig
->fsUsb
[2] = GET_BE_DWORD(tt_os2
->ulUnicodeRange3
);
7079 fontsig
->fsUsb
[3] = GET_BE_DWORD(tt_os2
->ulUnicodeRange4
);
7081 if (GET_BE_WORD(tt_os2
->version
) == 0) {
7082 fontsig
->fsCsb
[0] = 0;
7083 fontsig
->fsCsb
[1] = 0;
7086 fontsig
->fsCsb
[0] = GET_BE_DWORD(tt_os2
->ulCodePageRange1
);
7087 fontsig
->fsCsb
[1] = GET_BE_DWORD(tt_os2
->ulCodePageRange2
);
7090 IDWriteFontFace_ReleaseFontTable(fontface
, os2_context
);
7093 IDWriteFontFace_Release(fontface
);
7096 static void test_GetFontSignature(void)
7098 IDWriteFontCollection
*syscollection
;
7099 IDWriteGdiInterop1
*interop1
;
7100 IDWriteGdiInterop
*interop
;
7101 IDWriteFactory
*factory
;
7102 FONTSIGNATURE fontsig
;
7107 factory
= create_factory();
7109 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop
);
7110 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7112 hr
= IDWriteGdiInterop_QueryInterface(interop
, &IID_IDWriteGdiInterop1
, (void**)&interop1
);
7113 IDWriteGdiInterop_Release(interop
);
7115 win_skip("GetFontSignature() is not supported.\n");
7116 IDWriteGdiInterop_Release(interop
);
7117 IDWriteFactory_Release(factory
);
7120 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7122 hr
= IDWriteGdiInterop1_GetFontSignature(interop1
, NULL
, &fontsig
);
7123 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
7125 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &syscollection
, FALSE
);
7126 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7127 count
= IDWriteFontCollection_GetFontFamilyCount(syscollection
);
7129 for (i
= 0; i
< count
; i
++) {
7130 FONTSIGNATURE expected_signature
;
7131 IDWriteLocalizedStrings
*names
;
7132 IDWriteFontFamily
*family
;
7136 hr
= IDWriteFontCollection_GetFontFamily(syscollection
, i
, &family
);
7137 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7139 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STRETCH_NORMAL
,
7140 DWRITE_FONT_STYLE_NORMAL
, &font
);
7141 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7143 hr
= IDWriteFontFamily_GetFamilyNames(family
, &names
);
7144 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7146 get_enus_string(names
, nameW
, ARRAY_SIZE(nameW
));
7148 IDWriteLocalizedStrings_Release(names
);
7150 hr
= IDWriteGdiInterop1_GetFontSignature(interop1
, font
, &fontsig
);
7151 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7153 get_expected_fontsig(font
, &expected_signature
);
7155 ok(fontsig
.fsUsb
[0] == expected_signature
.fsUsb
[0], "%s: fsUsb[0] %#x, expected %#x\n", wine_dbgstr_w(nameW
),
7156 fontsig
.fsUsb
[0], expected_signature
.fsUsb
[0]);
7157 ok(fontsig
.fsUsb
[1] == expected_signature
.fsUsb
[1], "%s: fsUsb[1] %#x, expected %#x\n", wine_dbgstr_w(nameW
),
7158 fontsig
.fsUsb
[1], expected_signature
.fsUsb
[1]);
7159 ok(fontsig
.fsUsb
[2] == expected_signature
.fsUsb
[2], "%s: fsUsb[2] %#x, expected %#x\n", wine_dbgstr_w(nameW
),
7160 fontsig
.fsUsb
[2], expected_signature
.fsUsb
[2]);
7161 ok(fontsig
.fsUsb
[3] == expected_signature
.fsUsb
[3], "%s: fsUsb[3] %#x, expected %#x\n", wine_dbgstr_w(nameW
),
7162 fontsig
.fsUsb
[3], expected_signature
.fsUsb
[3]);
7164 ok(fontsig
.fsCsb
[0] == expected_signature
.fsCsb
[0], "%s: fsCsb[0] %#x, expected %#x\n", wine_dbgstr_w(nameW
),
7165 fontsig
.fsCsb
[0], expected_signature
.fsCsb
[0]);
7166 ok(fontsig
.fsCsb
[1] == expected_signature
.fsCsb
[1], "%s: fsCsb[1] %#x, expected %#x\n", wine_dbgstr_w(nameW
),
7167 fontsig
.fsCsb
[1], expected_signature
.fsCsb
[1]);
7169 IDWriteFont_Release(font
);
7170 IDWriteFontFamily_Release(family
);
7173 IDWriteGdiInterop1_Release(interop1
);
7174 IDWriteFontCollection_Release(syscollection
);
7175 ref
= IDWriteFactory_Release(factory
);
7176 ok(ref
== 0, "factory not released, %u\n", ref
);
7179 static void test_font_properties(void)
7181 IDWriteFontFace3
*fontface3
;
7182 IDWriteFontFace
*fontface
;
7183 IDWriteFactory
*factory
;
7184 DWRITE_FONT_STYLE style
;
7189 factory
= create_factory();
7191 /* this creates simulated font */
7192 font
= get_tahoma_instance(factory
, DWRITE_FONT_STYLE_ITALIC
);
7194 style
= IDWriteFont_GetStyle(font
);
7195 ok(style
== DWRITE_FONT_STYLE_OBLIQUE
, "got %u\n", style
);
7197 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
7198 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7200 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace3
, (void**)&fontface3
);
7201 IDWriteFontFace_Release(fontface
);
7203 style
= IDWriteFontFace3_GetStyle(fontface3
);
7204 ok(style
== DWRITE_FONT_STYLE_OBLIQUE
, "got %u\n", style
);
7206 IDWriteFontFace3_Release(fontface3
);
7209 IDWriteFont_Release(font
);
7210 ref
= IDWriteFactory_Release(factory
);
7211 ok(ref
== 0, "factory not released, %u\n", ref
);
7214 static BOOL
has_vertical_glyph_variants(IDWriteFontFace1
*fontface
)
7216 const OT_FeatureList
*featurelist
;
7217 const OT_LookupList
*lookup_list
;
7218 BOOL exists
= FALSE
, ret
= FALSE
;
7219 const GSUB_Header
*header
;
7226 hr
= IDWriteFontFace1_TryGetFontTable(fontface
, MS_GSUB_TAG
, &data
, &size
, &context
, &exists
);
7227 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7233 featurelist
= (OT_FeatureList
*)((BYTE
*)header
+ GET_BE_WORD(header
->FeatureList
));
7234 lookup_list
= (const OT_LookupList
*)((BYTE
*)header
+ GET_BE_WORD(header
->LookupList
));
7236 for (i
= 0; i
< GET_BE_WORD(featurelist
->FeatureCount
); i
++) {
7237 if (*(UINT32
*)featurelist
->FeatureRecord
[i
].FeatureTag
== DWRITE_FONT_FEATURE_TAG_VERTICAL_WRITING
) {
7238 const OT_Feature
*feature
= (const OT_Feature
*)((BYTE
*)featurelist
+ GET_BE_WORD(featurelist
->FeatureRecord
[i
].Feature
));
7239 UINT16 lookup_count
= GET_BE_WORD(feature
->LookupCount
), i
, index
, count
, type
;
7240 const GSUB_SingleSubstFormat2
*subst2
;
7241 const OT_LookupTable
*lookup_table
;
7244 if (lookup_count
== 0)
7247 for (i
= 0; i
< lookup_count
; i
++) {
7248 /* check if lookup is empty */
7249 index
= GET_BE_WORD(feature
->LookupListIndex
[i
]);
7250 lookup_table
= (const OT_LookupTable
*)((BYTE
*)lookup_list
+ GET_BE_WORD(lookup_list
->Lookup
[index
]));
7252 type
= GET_BE_WORD(lookup_table
->LookupType
);
7253 ok(type
== 1 || type
== 7, "got unexpected lookup type %u\n", type
);
7255 count
= GET_BE_WORD(lookup_table
->SubTableCount
);
7259 ok(count
> 0, "got unexpected subtable count %u\n", count
);
7261 offset
= GET_BE_WORD(lookup_table
->SubTable
[0]);
7263 const GSUB_ExtensionPosFormat1
*ext
= (const GSUB_ExtensionPosFormat1
*)((const BYTE
*)lookup_table
+ offset
);
7264 if (GET_BE_WORD(ext
->SubstFormat
) == 1)
7265 offset
+= GET_BE_DWORD(ext
->ExtensionOffset
);
7267 ok(0, "Unhandled Extension Substitution Format %u\n", GET_BE_WORD(ext
->SubstFormat
));
7270 subst2
= (const GSUB_SingleSubstFormat2
*)((BYTE
*)lookup_table
+ offset
);
7271 index
= GET_BE_WORD(subst2
->SubstFormat
);
7273 ok(0, "validate Single Substitution Format 1\n");
7274 else if (index
== 2) {
7275 /* SimSun-ExtB has 0 glyph count for this substitution */
7276 if (GET_BE_WORD(subst2
->GlyphCount
) > 0) {
7282 ok(0, "unknown Single Substitution Format, %u\n", index
);
7287 IDWriteFontFace1_ReleaseFontTable(fontface
, context
);
7292 static void test_HasVerticalGlyphVariants(void)
7294 IDWriteFontCollection
*syscollection
;
7295 IDWriteFontFace1
*fontface1
;
7296 IDWriteFontFace
*fontface
;
7297 IDWriteFactory
*factory
;
7302 factory
= create_factory();
7303 fontface
= create_fontface(factory
);
7305 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void**)&fontface1
);
7306 IDWriteFontFace_Release(fontface
);
7308 win_skip("HasVerticalGlyphVariants() is not supported.\n");
7309 IDWriteFactory_Release(factory
);
7312 IDWriteFontFace1_Release(fontface1
);
7314 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &syscollection
, FALSE
);
7315 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7316 count
= IDWriteFontCollection_GetFontFamilyCount(syscollection
);
7318 for (i
= 0; i
< count
; i
++) {
7319 IDWriteLocalizedStrings
*names
;
7320 BOOL expected_vert
, has_vert
;
7321 IDWriteFontFamily
*family
;
7325 hr
= IDWriteFontCollection_GetFontFamily(syscollection
, i
, &family
);
7326 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7328 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STRETCH_NORMAL
,
7329 DWRITE_FONT_STYLE_NORMAL
, &font
);
7330 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7332 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
7333 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7335 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void**)&fontface1
);
7336 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7338 hr
= IDWriteFontFamily_GetFamilyNames(family
, &names
);
7339 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7341 get_enus_string(names
, nameW
, ARRAY_SIZE(nameW
));
7343 expected_vert
= has_vertical_glyph_variants(fontface1
);
7344 has_vert
= IDWriteFontFace1_HasVerticalGlyphVariants(fontface1
);
7346 ok(expected_vert
== has_vert
, "%s: expected vertical feature %d, got %d\n",
7347 wine_dbgstr_w(nameW
), expected_vert
, has_vert
);
7349 IDWriteLocalizedStrings_Release(names
);
7350 IDWriteFont_Release(font
);
7352 IDWriteFontFace1_Release(fontface1
);
7353 IDWriteFontFace_Release(fontface
);
7354 IDWriteFontFamily_Release(family
);
7357 IDWriteFontCollection_Release(syscollection
);
7358 ref
= IDWriteFactory_Release(factory
);
7359 ok(ref
== 0, "factory not released, %u\n", ref
);
7362 static void test_HasKerningPairs(void)
7364 IDWriteFontCollection
*syscollection
;
7365 IDWriteFontFace1
*fontface1
;
7366 IDWriteFontFace
*fontface
;
7367 IDWriteFactory
*factory
;
7372 factory
= create_factory();
7373 fontface
= create_fontface(factory
);
7375 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void**)&fontface1
);
7376 IDWriteFontFace_Release(fontface
);
7378 win_skip("HasKerningPairs() is not supported.\n");
7379 IDWriteFactory_Release(factory
);
7382 IDWriteFontFace1_Release(fontface1
);
7384 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &syscollection
, FALSE
);
7385 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7386 count
= IDWriteFontCollection_GetFontFamilyCount(syscollection
);
7388 for (i
= 0; i
< count
; i
++) {
7389 IDWriteLocalizedStrings
*names
;
7390 BOOL exists
, has_kerningpairs
;
7391 IDWriteFontFamily
*family
;
7398 hr
= IDWriteFontCollection_GetFontFamily(syscollection
, i
, &family
);
7399 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7401 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STRETCH_NORMAL
,
7402 DWRITE_FONT_STYLE_NORMAL
, &font
);
7403 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7405 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
7406 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7408 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace1
, (void **)&fontface1
);
7409 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7411 hr
= IDWriteFontFamily_GetFamilyNames(family
, &names
);
7412 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7414 get_enus_string(names
, nameW
, ARRAY_SIZE(nameW
));
7417 hr
= IDWriteFontFace1_TryGetFontTable(fontface1
, MS_KERN_TAG
, &data
, &size
, &context
, &exists
);
7418 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7419 IDWriteFontFace1_ReleaseFontTable(fontface1
, context
);
7421 has_kerningpairs
= IDWriteFontFace1_HasKerningPairs(fontface1
);
7423 ok(!has_kerningpairs
, "%s: expected %d, got %d\n", wine_dbgstr_w(nameW
), exists
, has_kerningpairs
);
7425 IDWriteLocalizedStrings_Release(names
);
7426 IDWriteFont_Release(font
);
7428 IDWriteFontFace1_Release(fontface1
);
7429 IDWriteFontFace_Release(fontface
);
7430 IDWriteFontFamily_Release(family
);
7433 IDWriteFontCollection_Release(syscollection
);
7434 ref
= IDWriteFactory_Release(factory
);
7435 ok(ref
== 0, "factory not released, %u\n", ref
);
7438 static void test_ComputeGlyphOrigins(void)
7440 IDWriteFactory4
*factory
;
7441 DWRITE_GLYPH_RUN run
;
7443 D2D1_POINT_2F origins
[2];
7444 D2D1_POINT_2F baseline_origin
;
7450 factory
= create_factory_iid(&IID_IDWriteFactory4
);
7452 win_skip("ComputeGlyphOrigins() is not supported.\n");
7456 advances
[0] = 10.0f
;
7457 advances
[1] = 20.0f
;
7459 run
.fontFace
= NULL
;
7460 run
.fontEmSize
= 16.0f
;
7462 run
.glyphIndices
= glyphs
;
7463 run
.glyphAdvances
= advances
;
7464 run
.glyphOffsets
= NULL
;
7465 run
.isSideways
= FALSE
;
7468 baseline_origin
.x
= 123.0f
;
7469 baseline_origin
.y
= 321.0f
;
7471 memset(origins
, 0, sizeof(origins
));
7472 hr
= IDWriteFactory4_ComputeGlyphOrigins_(factory
, &run
, baseline_origin
, origins
);
7473 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
7474 ok(origins
[0].x
== 123.0f
&& origins
[0].y
== 321.0f
, "origins[0] %f,%f\n", origins
[0].x
, origins
[0].y
);
7475 ok(origins
[1].x
== 133.0f
&& origins
[1].y
== 321.0f
, "origins[1] %f,%f\n", origins
[1].x
, origins
[1].y
);
7477 memset(origins
, 0, sizeof(origins
));
7478 hr
= IDWriteFactory4_ComputeGlyphOrigins(factory
, &run
, DWRITE_MEASURING_MODE_NATURAL
, baseline_origin
,
7480 ok(origins
[0].x
== 123.0f
&& origins
[0].y
== 321.0f
, "origins[0] %f,%f\n", origins
[0].x
, origins
[0].y
);
7481 ok(origins
[1].x
== 133.0f
&& origins
[1].y
== 321.0f
, "origins[1] %f,%f\n", origins
[1].x
, origins
[1].y
);
7483 /* transform is not applied to returned origins */
7491 memset(origins
, 0, sizeof(origins
));
7492 hr
= IDWriteFactory4_ComputeGlyphOrigins(factory
, &run
, DWRITE_MEASURING_MODE_NATURAL
, baseline_origin
,
7494 ok(origins
[0].x
== 123.0f
&& origins
[0].y
== 321.0f
, "origins[0] %f,%f\n", origins
[0].x
, origins
[0].y
);
7495 ok(origins
[1].x
== 133.0f
&& origins
[1].y
== 321.0f
, "origins[1] %f,%f\n", origins
[1].x
, origins
[1].y
);
7497 ref
= IDWriteFactory4_Release(factory
);
7498 ok(ref
== 0, "factory not released, %u\n", ref
);
7501 static void test_object_lifetime(void)
7503 IDWriteFontCollection
*collection
, *collection2
;
7504 IDWriteFontList
*fontlist
, *fontlist2
;
7505 IDWriteGdiInterop
*interop
, *interop2
;
7506 IDWriteFontFamily
*family
, *family2
;
7507 IDWriteFontFace
*fontface
;
7508 IDWriteFont
*font
, *font2
;
7509 IDWriteFactory
*factory
;
7513 factory
= create_factory();
7514 EXPECT_REF(factory
, 1);
7516 /* system collection takes factory reference */
7517 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &collection
, FALSE
);
7518 ok(hr
== S_OK
, "got %#x\n", hr
);
7520 EXPECT_REF(collection
, 1);
7521 EXPECT_REF(factory
, 2);
7523 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &collection2
, FALSE
);
7524 ok(hr
== S_OK
, "got %#x\n", hr
);
7525 ok(collection2
== collection
, "expected same collection\n");
7527 EXPECT_REF(collection
, 2);
7528 EXPECT_REF(factory
, 2);
7530 IDWriteFontCollection_Release(collection2
);
7532 IDWriteFontCollection_AddRef(collection
);
7533 EXPECT_REF(collection
, 2);
7534 EXPECT_REF(factory
, 2);
7535 IDWriteFontCollection_Release(collection
);
7537 EXPECT_REF(collection
, 1);
7539 /* family takes collection reference */
7540 hr
= IDWriteFontCollection_GetFontFamily(collection
, 0, &family
);
7541 ok(hr
== S_OK
, "got %#x\n", hr
);
7543 EXPECT_REF(family
, 1);
7544 EXPECT_REF(collection
, 2);
7545 EXPECT_REF(factory
, 2);
7547 hr
= IDWriteFontCollection_GetFontFamily(collection
, 0, &family2
);
7548 ok(hr
== S_OK
, "got %#x\n", hr
);
7550 EXPECT_REF(family2
, 1);
7551 EXPECT_REF(collection
, 3);
7552 EXPECT_REF(factory
, 2);
7554 IDWriteFontFamily_Release(family2
);
7556 EXPECT_REF(family
, 1);
7557 EXPECT_REF(collection
, 2);
7558 EXPECT_REF(factory
, 2);
7560 /* font takes family reference */
7561 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, DWRITE_FONT_WEIGHT_NORMAL
,
7562 DWRITE_FONT_STRETCH_NORMAL
, DWRITE_FONT_STYLE_NORMAL
, &font
);
7563 ok(hr
== S_OK
, "got %#x\n", hr
);
7565 EXPECT_REF(family
, 2);
7566 EXPECT_REF(collection
, 2);
7567 EXPECT_REF(factory
, 2);
7569 hr
= IDWriteFont_GetFontFamily(font
, &family2
);
7570 ok(hr
== S_OK
, "got %#x\n", hr
);
7571 ok(family2
== family
, "unexpected family pointer\n");
7572 IDWriteFontFamily_Release(family2
);
7574 EXPECT_REF(font
, 1);
7575 EXPECT_REF(factory
, 2);
7577 /* Fontface takes factory reference and nothing else. */
7578 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
7579 ok(hr
== S_OK
, "got %#x\n", hr
);
7581 EXPECT_REF(font
, 1);
7582 EXPECT_REF_BROKEN(fontface
, 1, 2);
7583 EXPECT_REF(family
, 2);
7584 EXPECT_REF(collection
, 2);
7585 EXPECT_REF_BROKEN(factory
, 3, 2);
7587 /* get font from fontface */
7588 hr
= IDWriteFontCollection_GetFontFromFontFace(collection
, fontface
, &font2
);
7589 ok(hr
== S_OK
, "got %#x\n", hr
);
7591 EXPECT_REF(font
, 1);
7592 EXPECT_REF(font2
, 1);
7593 EXPECT_REF_BROKEN(fontface
, 1, 2);
7594 EXPECT_REF(family
, 2);
7595 EXPECT_REF(collection
, 3);
7596 EXPECT_REF_BROKEN(factory
, 3, 2);
7598 IDWriteFont_Release(font2
);
7599 IDWriteFontFace_Release(fontface
);
7601 EXPECT_REF(font
, 1);
7602 EXPECT_REF(family
, 2);
7603 EXPECT_REF(collection
, 2);
7604 EXPECT_REF(factory
, 2);
7606 IDWriteFont_Release(font
);
7608 EXPECT_REF(family
, 1);
7609 EXPECT_REF(collection
, 2);
7610 EXPECT_REF(factory
, 2);
7612 /* Matching fonts list takes family reference. */
7613 hr
= IDWriteFontFamily_GetMatchingFonts(family
, DWRITE_FONT_WEIGHT_NORMAL
,
7614 DWRITE_FONT_STRETCH_NORMAL
, DWRITE_FONT_STYLE_NORMAL
, &fontlist
);
7615 ok(hr
== S_OK
, "got %#x\n", hr
);
7617 EXPECT_REF(family
, 2);
7618 EXPECT_REF(collection
, 2);
7619 EXPECT_REF(factory
, 2);
7621 hr
= IDWriteFontFamily_GetMatchingFonts(family
, DWRITE_FONT_WEIGHT_NORMAL
,
7622 DWRITE_FONT_STRETCH_NORMAL
, DWRITE_FONT_STYLE_NORMAL
, &fontlist2
);
7623 ok(hr
== S_OK
, "got %#x\n", hr
);
7624 ok(fontlist2
!= fontlist
, "unexpected font list\n");
7625 IDWriteFontList_Release(fontlist2
);
7627 IDWriteFontList_Release(fontlist
);
7629 IDWriteFontFamily_Release(family
);
7630 EXPECT_REF(collection
, 1);
7632 EXPECT_REF(factory
, 2);
7633 ref
= IDWriteFontCollection_Release(collection
);
7634 ok(ref
== 0, "collection not released, %u\n", ref
);
7635 EXPECT_REF(factory
, 1);
7637 /* GDI interop object takes factory reference */
7638 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop
);
7639 ok(hr
== S_OK
, "got %#x\n", hr
);
7640 EXPECT_REF(interop
, 1);
7641 EXPECT_REF(factory
, 2);
7643 hr
= IDWriteFactory_GetGdiInterop(factory
, &interop2
);
7644 ok(hr
== S_OK
, "got %#x\n", hr
);
7645 ok(interop
== interop2
, "got unexpected interop pointer\n");
7647 EXPECT_REF(interop
, 2);
7648 EXPECT_REF(factory
, 2);
7650 IDWriteGdiInterop_Release(interop2
);
7651 ref
= IDWriteGdiInterop_Release(interop
);
7652 ok(ref
== 0, "interop not released, %u\n", ref
);
7654 ref
= IDWriteFactory_Release(factory
);
7655 ok(ref
== 0, "factory not released, %u\n", ref
);
7658 struct testowner_object
7660 IUnknown IUnknown_iface
;
7664 static inline struct testowner_object
*impl_from_IUnknown(IUnknown
*iface
)
7666 return CONTAINING_RECORD(iface
, struct testowner_object
, IUnknown_iface
);
7669 static HRESULT WINAPI
testowner_QueryInterface(IUnknown
*iface
, REFIID riid
, void **obj
)
7671 if (IsEqualIID(riid
, &IID_IUnknown
)) {
7673 IUnknown_AddRef(iface
);
7678 return E_NOINTERFACE
;
7681 static ULONG WINAPI
testowner_AddRef(IUnknown
*iface
)
7683 struct testowner_object
*object
= impl_from_IUnknown(iface
);
7684 return InterlockedIncrement(&object
->ref
);
7687 static ULONG WINAPI
testowner_Release(IUnknown
*iface
)
7689 struct testowner_object
*object
= impl_from_IUnknown(iface
);
7690 return InterlockedDecrement(&object
->ref
);
7693 static const IUnknownVtbl testownervtbl
= {
7694 testowner_QueryInterface
,
7699 static void testowner_init(struct testowner_object
*object
)
7701 object
->IUnknown_iface
.lpVtbl
= &testownervtbl
;
7705 static void test_inmemory_file_loader(void)
7707 IDWriteFontFileStream
*stream
, *stream2
, *stream3
;
7708 IDWriteFontFileLoader
*loader
, *loader2
;
7709 IDWriteInMemoryFontFileLoader
*inmemory
;
7710 struct testowner_object ownerobject
;
7711 const void *key
, *data
, *frag_start
;
7712 UINT64 file_size
, size
, writetime
;
7713 IDWriteFontFile
*file
, *file2
;
7714 IDWriteFontFace
*fontface
;
7715 void *context
, *context2
;
7716 IDWriteFactory5
*factory
;
7717 UINT32 count
, key_size
;
7722 factory
= create_factory_iid(&IID_IDWriteFactory5
);
7724 win_skip("CreateInMemoryFontFileLoader() is not supported\n");
7728 EXPECT_REF(factory
, 1);
7729 hr
= IDWriteFactory5_CreateInMemoryFontFileLoader(factory
, &loader
);
7730 ok(hr
== S_OK
, "got %#x\n", hr
);
7731 EXPECT_REF(factory
, 1);
7733 testowner_init(&ownerobject
);
7734 fontface
= create_fontface((IDWriteFactory
*)factory
);
7736 hr
= IDWriteFactory5_CreateInMemoryFontFileLoader(factory
, &loader2
);
7737 ok(hr
== S_OK
, "got %#x\n", hr
);
7738 ok(loader
!= loader2
, "unexpected pointer\n");
7739 IDWriteFontFileLoader_Release(loader2
);
7741 hr
= IDWriteFontFileLoader_QueryInterface(loader
, &IID_IDWriteInMemoryFontFileLoader
, (void **)&inmemory
);
7742 ok(hr
== S_OK
, "got %#x\n", hr
);
7743 IDWriteFontFileLoader_Release(loader
);
7744 EXPECT_REF(inmemory
, 1);
7746 count
= IDWriteInMemoryFontFileLoader_GetFileCount(inmemory
);
7747 ok(!count
, "Unexpected file count %u.\n", count
);
7749 /* Use whole font blob to construct in-memory file. */
7751 hr
= IDWriteFontFace_GetFiles(fontface
, &count
, &file
);
7752 ok(hr
== S_OK
, "got %#x\n", hr
);
7754 hr
= IDWriteFontFile_GetLoader(file
, &loader
);
7755 ok(hr
== S_OK
, "got %#x\n", hr
);
7757 hr
= IDWriteFontFile_GetReferenceKey(file
, &key
, &key_size
);
7758 ok(hr
== S_OK
, "got %#x\n", hr
);
7760 hr
= IDWriteFontFileLoader_CreateStreamFromKey(loader
, key
, key_size
, &stream
);
7761 ok(hr
== S_OK
, "got %#x\n", hr
);
7762 IDWriteFontFileLoader_Release(loader
);
7763 IDWriteFontFile_Release(file
);
7765 hr
= IDWriteFontFileStream_GetFileSize(stream
, &file_size
);
7766 ok(hr
== S_OK
, "got %#x\n", hr
);
7768 hr
= IDWriteFontFileStream_ReadFileFragment(stream
, &data
, 0, file_size
, &context
);
7769 ok(hr
== S_OK
, "got %#x\n", hr
);
7771 /* Not registered yet. */
7772 hr
= IDWriteInMemoryFontFileLoader_CreateInMemoryFontFileReference(inmemory
, (IDWriteFactory
*)factory
, data
,
7773 file_size
, NULL
, &file
);
7774 ok(hr
== E_INVALIDARG
, "got %#x\n", hr
);
7776 count
= IDWriteInMemoryFontFileLoader_GetFileCount(inmemory
);
7777 ok(count
== 1, "Unexpected file count %u.\n", count
);
7779 hr
= IDWriteFactory5_RegisterFontFileLoader(factory
, (IDWriteFontFileLoader
*)inmemory
);
7780 ok(hr
== S_OK
, "got %#x\n", hr
);
7781 EXPECT_REF(inmemory
, 2);
7783 EXPECT_REF(&ownerobject
.IUnknown_iface
, 1);
7784 hr
= IDWriteInMemoryFontFileLoader_CreateInMemoryFontFileReference(inmemory
, (IDWriteFactory
*)factory
, data
,
7785 file_size
, &ownerobject
.IUnknown_iface
, &file
);
7786 ok(hr
== S_OK
, "got %#x\n", hr
);
7787 EXPECT_REF(&ownerobject
.IUnknown_iface
, 2);
7788 EXPECT_REF(inmemory
, 3);
7790 count
= IDWriteInMemoryFontFileLoader_GetFileCount(inmemory
);
7791 ok(count
== 2, "Unexpected file count %u.\n", count
);
7793 hr
= IDWriteInMemoryFontFileLoader_CreateInMemoryFontFileReference(inmemory
, (IDWriteFactory
*)factory
, data
,
7794 file_size
, &ownerobject
.IUnknown_iface
, &file2
);
7795 ok(hr
== S_OK
, "got %#x\n", hr
);
7796 ok(file2
!= file
, "got unexpected file\n");
7797 EXPECT_REF(&ownerobject
.IUnknown_iface
, 3);
7798 EXPECT_REF(inmemory
, 4);
7800 count
= IDWriteInMemoryFontFileLoader_GetFileCount(inmemory
);
7801 ok(count
== 3, "Unexpected file count %u.\n", count
);
7803 /* Check in-memory reference key format. */
7804 hr
= IDWriteFontFile_GetReferenceKey(file
, &key
, &key_size
);
7805 ok(hr
== S_OK
, "got %#x\n", hr
);
7807 ok(key
&& *(DWORD
*)key
== 1, "got wrong ref key\n");
7808 ok(key_size
== 4, "ref key size %u\n", key_size
);
7810 hr
= IDWriteFontFile_GetReferenceKey(file2
, &key
, &key_size
);
7811 ok(hr
== S_OK
, "got %#x\n", hr
);
7813 ok(key
&& *(DWORD
*)key
== 2, "got wrong ref key\n");
7814 ok(key_size
== 4, "ref key size %u\n", key_size
);
7816 EXPECT_REF(inmemory
, 4);
7817 hr
= IDWriteInMemoryFontFileLoader_CreateStreamFromKey(inmemory
, key
, key_size
, &stream2
);
7818 ok(hr
== S_OK
, "Failed to create a stream, hr %#x.\n", hr
);
7819 EXPECT_REF(stream2
, 1);
7820 EXPECT_REF(inmemory
, 4);
7822 hr
= IDWriteInMemoryFontFileLoader_CreateStreamFromKey(inmemory
, key
, key_size
, &stream3
);
7823 ok(hr
== S_OK
, "Failed to create a stream, hr %#x.\n", hr
);
7825 ok(stream2
!= stream3
, "Unexpected stream.\n");
7827 IDWriteFontFileStream_Release(stream2
);
7828 IDWriteFontFileStream_Release(stream3
);
7830 /* Release file at index 1, create new one to see if index is reused. */
7831 EXPECT_REF(&ownerobject
.IUnknown_iface
, 3);
7832 ref
= IDWriteFontFile_Release(file
);
7833 ok(ref
== 0, "File object not released, %u.\n", ref
);
7834 EXPECT_REF(&ownerobject
.IUnknown_iface
, 3);
7836 count
= IDWriteInMemoryFontFileLoader_GetFileCount(inmemory
);
7837 ok(count
== 3, "Unexpected file count %u.\n", count
);
7839 EXPECT_REF(&ownerobject
.IUnknown_iface
, 3);
7840 ref
= IDWriteFontFile_Release(file2
);
7841 ok(ref
== 0, "File object not released, %u.\n", ref
);
7842 EXPECT_REF(&ownerobject
.IUnknown_iface
, 3);
7844 count
= IDWriteInMemoryFontFileLoader_GetFileCount(inmemory
);
7845 ok(count
== 3, "Unexpected file count %u.\n", count
);
7847 hr
= IDWriteFactory5_UnregisterFontFileLoader(factory
, (IDWriteFontFileLoader
*)inmemory
);
7848 ok(hr
== S_OK
, "got %#x\n", hr
);
7849 EXPECT_REF(&ownerobject
.IUnknown_iface
, 3);
7851 EXPECT_REF(&ownerobject
.IUnknown_iface
, 3);
7852 ref
= IDWriteInMemoryFontFileLoader_Release(inmemory
);
7853 ok(ref
== 0, "loader not released, %u.\n", ref
);
7854 EXPECT_REF(&ownerobject
.IUnknown_iface
, 1);
7856 /* Test reference key for first added file. */
7857 hr
= IDWriteFactory5_CreateInMemoryFontFileLoader(factory
, &loader
);
7858 ok(hr
== S_OK
, "Failed to create loader, hr %#x.\n", hr
);
7860 hr
= IDWriteFontFileLoader_QueryInterface(loader
, &IID_IDWriteInMemoryFontFileLoader
, (void **)&inmemory
);
7861 ok(hr
== S_OK
, "Failed to get in-memory interface, hr %#x.\n", hr
);
7862 IDWriteFontFileLoader_Release(loader
);
7864 hr
= IDWriteFactory5_RegisterFontFileLoader(factory
, (IDWriteFontFileLoader
*)inmemory
);
7865 ok(hr
== S_OK
, "Failed to register loader, hr %#x.\n", hr
);
7868 hr
= IDWriteInMemoryFontFileLoader_CreateStreamFromKey(inmemory
, &ref_key
, sizeof(ref_key
), &stream2
);
7869 ok(hr
== E_INVALIDARG
, "Unexpected hr %#x.\n", hr
);
7871 hr
= IDWriteInMemoryFontFileLoader_CreateInMemoryFontFileReference(inmemory
, (IDWriteFactory
*)factory
, data
,
7872 file_size
, &ownerobject
.IUnknown_iface
, &file
);
7873 ok(hr
== S_OK
, "Failed to create in-memory file reference, hr %#x.\n", hr
);
7876 hr
= IDWriteInMemoryFontFileLoader_CreateStreamFromKey(inmemory
, &ref_key
, sizeof(ref_key
), &stream2
);
7877 ok(hr
== S_OK
, "Failed to create a stream, hr %#x.\n", hr
);
7879 context2
= (void *)0xdeadbeef;
7880 hr
= IDWriteFontFileStream_ReadFileFragment(stream2
, &frag_start
, 0, file_size
, &context2
);
7881 ok(hr
== S_OK
, "Failed to read a fragment, hr %#x.\n", hr
);
7882 ok(context
== NULL
, "Unexpected context %p.\n", context2
);
7883 ok(frag_start
== data
, "Unexpected fragment pointer %p.\n", frag_start
);
7885 hr
= IDWriteFontFileStream_GetFileSize(stream2
, &size
);
7886 ok(hr
== S_OK
, "Failed to get file size, hr %#x.\n", hr
);
7887 ok(size
== file_size
, "Unexpected file size.\n");
7889 IDWriteFontFileStream_ReleaseFileFragment(stream2
, context2
);
7892 hr
= IDWriteFontFileStream_GetLastWriteTime(stream2
, &writetime
);
7893 ok(hr
== E_NOTIMPL
, "Unexpected hr %#x.\n", hr
);
7894 ok(writetime
== 0, "Unexpected writetime.\n");
7896 IDWriteFontFileStream_Release(stream2
);
7899 hr
= IDWriteInMemoryFontFileLoader_CreateStreamFromKey(inmemory
, NULL
, sizeof(ref_key
) - 1, &stream2
);
7900 ok(hr
== E_INVALIDARG
, "Unexpected hr %#x.\n", hr
);
7903 hr
= IDWriteInMemoryFontFileLoader_CreateStreamFromKey(inmemory
, &ref_key
, sizeof(ref_key
) - 1, &stream2
);
7904 ok(hr
== E_INVALIDARG
, "Unexpected hr %#x.\n", hr
);
7907 hr
= IDWriteInMemoryFontFileLoader_CreateStreamFromKey(inmemory
, &ref_key
, sizeof(ref_key
) + 1, &stream2
);
7908 ok(hr
== E_INVALIDARG
, "Unexpected hr %#x.\n", hr
);
7910 count
= IDWriteInMemoryFontFileLoader_GetFileCount(inmemory
);
7911 ok(count
== 1, "Unexpected file count %u.\n", count
);
7913 hr
= IDWriteFontFile_GetReferenceKey(file
, &key
, &key_size
);
7914 ok(hr
== S_OK
, "Failed to get reference key, hr %#x.\n", hr
);
7916 ok(key
&& *(DWORD
*)key
== 0, "Unexpected reference key.\n");
7917 ok(key_size
== 4, "Unexpected key size %u.\n", key_size
);
7919 IDWriteFontFile_Release(file
);
7921 count
= IDWriteInMemoryFontFileLoader_GetFileCount(inmemory
);
7922 ok(count
== 1, "Unexpected file count %u.\n", count
);
7924 hr
= IDWriteFactory5_UnregisterFontFileLoader(factory
, (IDWriteFontFileLoader
*)inmemory
);
7925 ok(hr
== S_OK
, "Failed to unregister loader, hr %#x.\n", hr
);
7927 IDWriteFontFileStream_ReleaseFileFragment(stream
, context
);
7928 IDWriteFontFileStream_Release(stream
);
7929 IDWriteFontFace_Release(fontface
);
7931 ref
= IDWriteInMemoryFontFileLoader_Release(inmemory
);
7932 ok(ref
== 0, "loader not released, %u.\n", ref
);
7934 ref
= IDWriteFactory5_Release(factory
);
7935 ok(ref
== 0, "factory not released, %u\n", ref
);
7938 static BOOL
face_has_table(IDWriteFontFace4
*fontface
, UINT32 tag
)
7940 BOOL exists
= FALSE
;
7946 hr
= IDWriteFontFace4_TryGetFontTable(fontface
, tag
, &data
, &size
, &context
, &exists
);
7947 ok(hr
== S_OK
, "TryGetFontTable() failed, %#x\n", hr
);
7949 IDWriteFontFace4_ReleaseFontTable(fontface
, context
);
7954 static DWORD
get_sbix_formats(IDWriteFontFace4
*fontface
)
7956 UINT32 size
, s
, num_strikes
;
7957 const sbix_header
*header
;
7958 UINT16 g
, num_glyphs
;
7959 BOOL exists
= FALSE
;
7966 hr
= IDWriteFontFace4_TryGetFontTable(fontface
, MS_MAXP_TAG
, &data
, &size
, &context
, &exists
);
7967 ok(hr
== S_OK
, "TryGetFontTable() failed, %#x\n", hr
);
7968 ok(exists
, "Expected maxp table\n");
7974 num_glyphs
= GET_BE_WORD(maxp
->numGlyphs
);
7976 hr
= IDWriteFontFace4_TryGetFontTable(fontface
, MS_SBIX_TAG
, &data
, &size
, &context
, &exists
);
7977 ok(hr
== S_OK
, "TryGetFontTable() failed, %#x\n", hr
);
7978 ok(exists
, "Expected sbix table\n");
7981 num_strikes
= GET_BE_DWORD(header
->numStrikes
);
7983 for (s
= 0; s
< num_strikes
; s
++) {
7984 sbix_strike
*strike
= (sbix_strike
*)((BYTE
*)header
+ GET_BE_DWORD(header
->strikeOffset
[s
]));
7986 for (g
= 0; g
< num_glyphs
; g
++) {
7987 DWORD offset
= GET_BE_DWORD(strike
->glyphDataOffsets
[g
]);
7988 DWORD offset_next
= GET_BE_DWORD(strike
->glyphDataOffsets
[g
+ 1]);
7989 sbix_glyph_data
*glyph_data
;
7992 if (offset
== offset_next
)
7995 glyph_data
= (sbix_glyph_data
*)((BYTE
*)strike
+ offset
);
7996 switch (format
= glyph_data
->graphicType
)
7999 ret
|= DWRITE_GLYPH_IMAGE_FORMATS_PNG
;
8002 ret
|= DWRITE_GLYPH_IMAGE_FORMATS_JPEG
;
8005 ret
|= DWRITE_GLYPH_IMAGE_FORMATS_TIFF
;
8008 ok(0, "unexpected format, %#x\n", GET_BE_DWORD(format
));
8013 IDWriteFontFace4_ReleaseFontTable(fontface
, context
);
8018 static DWORD
get_cblc_formats(IDWriteFontFace4
*fontface
)
8020 CBLCBitmapSizeTable
*sizes
;
8021 UINT32 num_sizes
, size
, s
;
8022 BOOL exists
= FALSE
;
8028 hr
= IDWriteFontFace4_TryGetFontTable(fontface
, MS_CBLC_TAG
, (const void **)&header
, &size
, &context
, &exists
);
8029 ok(hr
== S_OK
, "TryGetFontTable() failed, %#x\n", hr
);
8030 ok(exists
, "Expected CBLC table\n");
8035 num_sizes
= GET_BE_DWORD(header
->numSizes
);
8036 sizes
= (CBLCBitmapSizeTable
*)(header
+ 1);
8038 for (s
= 0; s
< num_sizes
; s
++) {
8039 BYTE bpp
= sizes
->bitDepth
;
8041 if (bpp
== 1 || bpp
== 2 || bpp
== 4 || bpp
== 8)
8042 ret
|= DWRITE_GLYPH_IMAGE_FORMATS_PNG
;
8044 ret
|= DWRITE_GLYPH_IMAGE_FORMATS_PREMULTIPLIED_B8G8R8A8
;
8047 IDWriteFontFace4_ReleaseFontTable(fontface
, context
);
8052 static DWORD
get_face_glyph_image_formats(IDWriteFontFace4
*fontface
)
8054 DWORD ret
= DWRITE_GLYPH_IMAGE_FORMATS_NONE
;
8056 if (face_has_table(fontface
, MS_GLYF_TAG
))
8057 ret
|= DWRITE_GLYPH_IMAGE_FORMATS_TRUETYPE
;
8059 if (face_has_table(fontface
, MS_CFF__TAG
) ||
8060 face_has_table(fontface
, MS_CFF2_TAG
))
8061 ret
|= DWRITE_GLYPH_IMAGE_FORMATS_CFF
;
8063 if (face_has_table(fontface
, MS_COLR_TAG
))
8064 ret
|= DWRITE_GLYPH_IMAGE_FORMATS_COLR
;
8066 if (face_has_table(fontface
, MS_SVG__TAG
))
8067 ret
|= DWRITE_GLYPH_IMAGE_FORMATS_SVG
;
8069 if (face_has_table(fontface
, MS_SBIX_TAG
))
8070 ret
|= get_sbix_formats(fontface
);
8072 if (face_has_table(fontface
, MS_CBLC_TAG
))
8073 ret
|= get_cblc_formats(fontface
);
8078 static void test_GetGlyphImageFormats(void)
8080 IDWriteFontCollection
*syscollection
;
8081 IDWriteFactory
*factory
;
8085 IDWriteFontFace
*fontface
;
8086 IDWriteFontFace4
*fontface4
;
8088 factory
= create_factory();
8090 fontface
= create_fontface(factory
);
8091 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace4
, (void **)&fontface4
);
8092 IDWriteFontFace_Release(fontface
);
8094 win_skip("GetGlyphImageFormats() is not supported\n");
8095 IDWriteFactory_Release(factory
);
8098 IDWriteFontFace4_Release(fontface4
);
8100 hr
= IDWriteFactory_GetSystemFontCollection(factory
, &syscollection
, FALSE
);
8101 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
8102 count
= IDWriteFontCollection_GetFontFamilyCount(syscollection
);
8104 for (i
= 0; i
< count
; i
++) {
8105 WCHAR familynameW
[256], facenameW
[128];
8106 IDWriteLocalizedStrings
*names
;
8107 IDWriteFontFamily
*family
;
8108 UINT32 j
, fontcount
;
8111 hr
= IDWriteFontCollection_GetFontFamily(syscollection
, i
, &family
);
8112 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
8114 hr
= IDWriteFontFamily_GetFamilyNames(family
, &names
);
8115 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
8117 get_enus_string(names
, familynameW
, ARRAY_SIZE(familynameW
));
8118 IDWriteLocalizedStrings_Release(names
);
8120 fontcount
= IDWriteFontFamily_GetFontCount(family
);
8121 for (j
= 0; j
< fontcount
; j
++) {
8122 DWORD formats
, expected_formats
;
8124 hr
= IDWriteFontFamily_GetFont(family
, j
, &font
);
8125 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
8127 hr
= IDWriteFont_CreateFontFace(font
, &fontface
);
8128 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
8130 hr
= IDWriteFont_GetFaceNames(font
, &names
);
8131 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
8133 get_enus_string(names
, facenameW
, ARRAY_SIZE(facenameW
));
8135 IDWriteLocalizedStrings_Release(names
);
8137 IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace4
, (void **)&fontface4
);
8139 /* Mask describes font as a whole. */
8140 formats
= IDWriteFontFace4_GetGlyphImageFormats(fontface4
);
8141 expected_formats
= get_face_glyph_image_formats(fontface4
);
8142 ok(formats
== expected_formats
, "%s - %s, expected formats %#x, got formats %#x.\n",
8143 wine_dbgstr_w(familynameW
), wine_dbgstr_w(facenameW
), expected_formats
, formats
);
8145 IDWriteFontFace4_Release(fontface4
);
8146 IDWriteFontFace_Release(fontface
);
8147 IDWriteFont_Release(font
);
8150 IDWriteFontFamily_Release(family
);
8153 IDWriteFontCollection_Release(syscollection
);
8154 ref
= IDWriteFactory_Release(factory
);
8155 ok(ref
== 0, "factory not released, %u\n", ref
);
8158 static void test_CreateCustomRenderingParams(void)
8160 static const struct custom_params_test
8164 FLOAT cleartype_level
;
8165 DWRITE_PIXEL_GEOMETRY geometry
;
8166 DWRITE_RENDERING_MODE rendering_mode
;
8170 { 0.0f
, 0.0f
, 0.0f
, DWRITE_PIXEL_GEOMETRY_FLAT
, DWRITE_RENDERING_MODE_NATURAL
, E_INVALIDARG
},
8171 { 0.0f
, 0.1f
, 0.0f
, DWRITE_PIXEL_GEOMETRY_FLAT
, DWRITE_RENDERING_MODE_NATURAL
, E_INVALIDARG
},
8172 { 0.0f
, 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
, E_INVALIDARG
},
8174 { 0.1f
, -0.1f
, 0.0f
, DWRITE_PIXEL_GEOMETRY_FLAT
, DWRITE_RENDERING_MODE_NATURAL
, E_INVALIDARG
},
8175 { 0.1f
, 0.0f
, -0.1f
, DWRITE_PIXEL_GEOMETRY_FLAT
, DWRITE_RENDERING_MODE_NATURAL
, E_INVALIDARG
},
8176 { 0.1f
, 0.0f
, 0.0f
, DWRITE_PIXEL_GEOMETRY_FLAT
, DWRITE_RENDERING_MODE_NATURAL
},
8177 { 0.01f
, 0.0f
, 0.0f
, DWRITE_PIXEL_GEOMETRY_FLAT
, DWRITE_RENDERING_MODE_NATURAL
},
8178 { 0.1f
, 0.0f
, 0.0f
, DWRITE_PIXEL_GEOMETRY_BGR
+ 1, DWRITE_RENDERING_MODE_NATURAL
, E_INVALIDARG
},
8179 { 0.1f
, 0.0f
, 0.0f
, DWRITE_PIXEL_GEOMETRY_BGR
, DWRITE_RENDERING_MODE_OUTLINE
+ 1, E_INVALIDARG
},
8180 { 0.1f
, 0.0f
, 2.0f
, DWRITE_PIXEL_GEOMETRY_BGR
, DWRITE_RENDERING_MODE_NATURAL
},
8182 IDWriteFactory
*factory
;
8187 factory
= create_factory();
8189 for (i
= 0; i
< ARRAY_SIZE(params_tests
); i
++) {
8190 IDWriteRenderingParams
*params
;
8192 params
= (void *)0xdeadbeef;
8193 hr
= IDWriteFactory_CreateCustomRenderingParams(factory
, params_tests
[i
].gamma
, params_tests
[i
].contrast
,
8194 params_tests
[i
].cleartype_level
, params_tests
[i
].geometry
, params_tests
[i
].rendering_mode
, ¶ms
);
8195 ok(hr
== params_tests
[i
].hr
, "%u: unexpected hr %#x, expected %#x.\n", i
, hr
, params_tests
[i
].hr
);
8198 ok(params_tests
[i
].gamma
== IDWriteRenderingParams_GetGamma(params
), "%u: unexpected gamma %f, expected %f.\n",
8199 i
, IDWriteRenderingParams_GetGamma(params
), params_tests
[i
].gamma
);
8200 ok(params_tests
[i
].contrast
== IDWriteRenderingParams_GetEnhancedContrast(params
),
8201 "%u: unexpected contrast %f, expected %f.\n",
8202 i
, IDWriteRenderingParams_GetEnhancedContrast(params
), params_tests
[i
].contrast
);
8203 ok(params_tests
[i
].cleartype_level
== IDWriteRenderingParams_GetClearTypeLevel(params
),
8204 "%u: unexpected ClearType level %f, expected %f.\n",
8205 i
, IDWriteRenderingParams_GetClearTypeLevel(params
), params_tests
[i
].cleartype_level
);
8206 ok(params_tests
[i
].geometry
== IDWriteRenderingParams_GetPixelGeometry(params
),
8207 "%u: unexpected pixel geometry %u, expected %u.\n", i
, IDWriteRenderingParams_GetPixelGeometry(params
),
8208 params_tests
[i
].geometry
);
8209 ok(params_tests
[i
].rendering_mode
== IDWriteRenderingParams_GetRenderingMode(params
),
8210 "%u: unexpected rendering mode %u, expected %u.\n", i
, IDWriteRenderingParams_GetRenderingMode(params
),
8211 params_tests
[i
].rendering_mode
);
8212 IDWriteRenderingParams_Release(params
);
8215 ok(params
== NULL
, "%u: expected NULL interface pointer on failure.\n", i
);
8218 ref
= IDWriteFactory_Release(factory
);
8219 ok(ref
== 0, "factory not released, %u\n", ref
);
8222 static void test_localfontfileloader(void)
8224 IDWriteFontFileLoader
*loader
, *loader2
;
8225 IDWriteFactory
*factory
, *factory2
;
8226 IDWriteFontFile
*file
, *file2
;
8231 factory
= create_factory();
8232 factory2
= create_factory();
8234 path
= create_testfontfile(test_fontfile
);
8236 hr
= IDWriteFactory_CreateFontFileReference(factory
, path
, NULL
, &file
);
8237 ok(hr
== S_OK
, "Failed to create file reference, hr %#x.\n", hr
);
8239 hr
= IDWriteFactory_CreateFontFileReference(factory2
, path
, NULL
, &file2
);
8240 ok(hr
== S_OK
, "Failed to create file reference, hr %#x.\n", hr
);
8241 ok(file
!= file2
, "Unexpected file instance.\n");
8243 hr
= IDWriteFontFile_GetLoader(file
, &loader
);
8244 ok(hr
== S_OK
, "Failed to get loader, hr %#x.\n", hr
);
8246 hr
= IDWriteFontFile_GetLoader(file2
, &loader2
);
8247 ok(hr
== S_OK
, "Failed to get loader, hr %#x.\n", hr
);
8248 ok(loader
== loader2
, "Unexpected loader instance\n");
8250 IDWriteFontFile_Release(file
);
8251 IDWriteFontFile_Release(file2
);
8252 IDWriteFontFileLoader_Release(loader
);
8253 IDWriteFontFileLoader_Release(loader2
);
8254 ref
= IDWriteFactory_Release(factory
);
8255 ok(ref
== 0, "factory not released, %u\n", ref
);
8256 DELETE_FONTFILE(path
);
8259 static void test_AnalyzeContainerType(void)
8261 struct WOFFHeader2 woff2_header
;
8262 struct WOFFHeader woff_header
;
8263 DWRITE_CONTAINER_TYPE type
;
8264 IDWriteFactory5
*factory
;
8266 factory
= create_factory_iid(&IID_IDWriteFactory5
);
8268 win_skip("AnalyzeContainerType() is not supported.\n");
8272 type
= IDWriteFactory5_AnalyzeContainerType(factory
, NULL
, 0);
8273 ok(type
== DWRITE_CONTAINER_TYPE_UNKNOWN
, "Unexpected container type %u.\n", type
);
8275 type
= IDWriteFactory5_AnalyzeContainerType(factory
, (void const *)0xdeadbeef, 0);
8276 ok(type
== DWRITE_CONTAINER_TYPE_UNKNOWN
, "Unexpected container type %u.\n", type
);
8278 memset(&woff_header
, 0xff, sizeof(woff_header
));
8279 woff_header
.signature
= GET_LE_DWORD(MS_WOFF_TAG
);
8280 woff_header
.length
= 0;
8281 type
= IDWriteFactory5_AnalyzeContainerType(factory
, &woff_header
, sizeof(woff_header
));
8282 ok(type
== DWRITE_CONTAINER_TYPE_WOFF
, "Unexpected container type %u.\n", type
);
8284 memset(&woff_header
, 0xff, sizeof(woff_header
));
8285 woff_header
.signature
= GET_LE_DWORD(MS_WOFF_TAG
);
8286 type
= IDWriteFactory5_AnalyzeContainerType(factory
, &woff_header
, sizeof(woff_header
.signature
));
8287 ok(type
== DWRITE_CONTAINER_TYPE_WOFF
, "Unexpected container type %u.\n", type
);
8289 memset(&woff_header
, 0xff, sizeof(woff_header
));
8290 woff_header
.signature
= GET_LE_DWORD(MS_WOFF_TAG
);
8291 type
= IDWriteFactory5_AnalyzeContainerType(factory
, &woff_header
, sizeof(woff_header
.signature
) - 1);
8292 ok(type
== DWRITE_CONTAINER_TYPE_UNKNOWN
, "Unexpected container type %u.\n", type
);
8294 memset(&woff2_header
, 0xff, sizeof(woff2_header
));
8295 woff2_header
.signature
= GET_LE_DWORD(MS_WOF2_TAG
);
8296 type
= IDWriteFactory5_AnalyzeContainerType(factory
, &woff2_header
, sizeof(woff2_header
));
8297 ok(type
== DWRITE_CONTAINER_TYPE_WOFF2
, "Unexpected container type %u.\n", type
);
8299 memset(&woff2_header
, 0xff, sizeof(woff2_header
));
8300 woff2_header
.signature
= GET_LE_DWORD(MS_WOF2_TAG
);
8301 type
= IDWriteFactory5_AnalyzeContainerType(factory
, &woff2_header
, sizeof(woff2_header
.signature
));
8302 ok(type
== DWRITE_CONTAINER_TYPE_WOFF2
, "Unexpected container type %u.\n", type
);
8304 memset(&woff2_header
, 0xff, sizeof(woff2_header
));
8305 woff2_header
.signature
= GET_LE_DWORD(MS_WOF2_TAG
);
8306 type
= IDWriteFactory5_AnalyzeContainerType(factory
, &woff2_header
, sizeof(woff2_header
.signature
) - 1);
8307 ok(type
== DWRITE_CONTAINER_TYPE_UNKNOWN
, "Unexpected container type %u.\n", type
);
8309 IDWriteFactory5_Release(factory
);
8312 static void test_fontsetbuilder(void)
8314 IDWriteFontCollection1
*collection
;
8315 IDWriteFontSetBuilder
*builder
;
8316 IDWriteFactory3
*factory
;
8317 UINT32 count
, i
, ref
;
8320 factory
= create_factory_iid(&IID_IDWriteFactory3
);
8322 skip("IDWriteFontSetBuilder is not supported.\n");
8326 EXPECT_REF(factory
, 1);
8327 hr
= IDWriteFactory3_CreateFontSetBuilder(factory
, &builder
);
8329 ok(hr
== S_OK
, "Failed to create font set builder, hr %#x.\n", hr
);
8332 IDWriteFactory3_Release(factory
);
8336 EXPECT_REF(factory
, 2);
8337 IDWriteFontSetBuilder_Release(builder
);
8339 hr
= IDWriteFactory3_GetSystemFontCollection(factory
, FALSE
, &collection
, FALSE
);
8340 ok(hr
== S_OK
, "Failed to get system collection, hr %#x.\n", hr
);
8341 count
= IDWriteFontCollection1_GetFontFamilyCount(collection
);
8343 for (i
= 0; i
< count
; i
++) {
8344 IDWriteFontFamily1
*family
;
8345 UINT32 j
, fontcount
;
8348 hr
= IDWriteFontCollection1_GetFontFamily(collection
, i
, &family
);
8349 ok(hr
== S_OK
, "Failed to get family, hr %#x.\n", hr
);
8351 fontcount
= IDWriteFontFamily1_GetFontCount(family
);
8352 for (j
= 0; j
< fontcount
; j
++) {
8353 IDWriteFontFaceReference
*ref
, *ref2
;
8354 IDWriteFontSet
*fontset
;
8355 UINT32 setcount
, id
;
8357 hr
= IDWriteFontFamily1_GetFont(family
, j
, &font
);
8358 ok(hr
== S_OK
, "Failed to get font, hr %#x.\n", hr
);
8360 /* Create a set with a single font reference, test set properties. */
8361 hr
= IDWriteFactory3_CreateFontSetBuilder(factory
, &builder
);
8362 ok(hr
== S_OK
, "Failed to create font set builder, hr %#x.\n", hr
);
8364 hr
= IDWriteFont3_GetFontFaceReference(font
, &ref
);
8365 ok(hr
== S_OK
, "Failed to get fontface reference, hr %#x.\n", hr
);
8368 hr
= IDWriteFontSetBuilder_AddFontFaceReference(builder
, ref
);
8369 ok(hr
== S_OK
, "Failed to add fontface reference, hr %#x.\n", hr
);
8372 hr
= IDWriteFontSetBuilder_CreateFontSet(builder
, &fontset
);
8373 ok(hr
== S_OK
, "Failed to create a font set, hr %#x.\n", hr
);
8375 setcount
= IDWriteFontSet_GetFontCount(fontset
);
8376 ok(setcount
== 1, "Unexpected font count %u.\n", setcount
);
8378 hr
= IDWriteFontSet_GetFontFaceReference(fontset
, 0, &ref2
);
8379 ok(hr
== S_OK
, "Failed to get font face reference, hr %#x.\n", hr
);
8380 ok(ref2
!= ref
, "Unexpected reference.\n");
8381 IDWriteFontFaceReference_Release(ref2
);
8383 for (id
= DWRITE_FONT_PROPERTY_ID_FAMILY_NAME
; id
< DWRITE_FONT_PROPERTY_ID_TOTAL
; id
++) {
8384 static const WCHAR fmtW
[] = {'%','u',0};
8385 IDWriteLocalizedStrings
*values
;
8386 WCHAR buffW
[255], buff2W
[255];
8390 hr
= IDWriteFontSet_GetPropertyValues(fontset
, 0, id
, &exists
, &values
);
8391 ok(hr
== S_OK
, "Failed to get property value, hr %#x.\n", hr
);
8398 case DWRITE_FONT_PROPERTY_ID_WEIGHT
:
8399 ivalue
= IDWriteFont3_GetWeight(font
);
8401 case DWRITE_FONT_PROPERTY_ID_STRETCH
:
8402 ivalue
= IDWriteFont3_GetStretch(font
);
8404 case DWRITE_FONT_PROPERTY_ID_STYLE
:
8405 ivalue
= IDWriteFont3_GetStyle(font
);
8413 case DWRITE_FONT_PROPERTY_ID_WEIGHT
:
8414 case DWRITE_FONT_PROPERTY_ID_STRETCH
:
8415 case DWRITE_FONT_PROPERTY_ID_STYLE
:
8416 c
= IDWriteLocalizedStrings_GetCount(values
);
8417 ok(c
== 1, "Unexpected string count %u.\n", c
);
8420 hr
= IDWriteLocalizedStrings_GetLocaleName(values
, 0, buffW
, ARRAY_SIZE(buffW
));
8421 ok(hr
== S_OK
, "Failed to get locale name, hr %#x.\n", hr
);
8422 ok(!*buffW
, "Unexpected locale %s.\n", wine_dbgstr_w(buffW
));
8425 hr
= IDWriteLocalizedStrings_GetString(values
, 0, buff2W
, ARRAY_SIZE(buff2W
));
8426 ok(hr
== S_OK
, "Failed to get property string, hr %#x.\n", hr
);
8428 wsprintfW(buffW
, fmtW
, ivalue
);
8429 ok(!lstrcmpW(buffW
, buff2W
), "Unexpected property value %s, expected %s.\n", wine_dbgstr_w(buff2W
),
8430 wine_dbgstr_w(buffW
));
8436 IDWriteLocalizedStrings_Release(values
);
8439 IDWriteFontSet_Release(fontset
);
8440 IDWriteFontFaceReference_Release(ref
);
8441 IDWriteFontSetBuilder_Release(builder
);
8443 IDWriteFont3_Release(font
);
8446 IDWriteFontFamily1_Release(family
);
8449 IDWriteFontCollection1_Release(collection
);
8451 ref
= IDWriteFactory3_Release(factory
);
8452 ok(ref
== 0, "factory not released, %u\n", ref
);
8457 IDWriteFactory
*factory
;
8459 if (!(factory
= create_factory())) {
8460 win_skip("failed to create factory\n");
8464 test_object_lifetime();
8465 test_CreateFontFromLOGFONT();
8466 test_CreateBitmapRenderTarget();
8467 test_GetFontFamily();
8468 test_GetFamilyNames();
8469 test_CreateFontFace();
8471 test_system_fontcollection();
8472 test_ConvertFontFaceToLOGFONT();
8473 test_CustomFontCollection();
8474 test_CreateCustomFontFileReference();
8475 test_CreateFontFileReference();
8476 test_shared_isolated();
8477 test_GetUnicodeRanges();
8478 test_GetFontFromFontFace();
8479 test_GetFirstMatchingFont();
8480 test_GetMatchingFonts();
8481 test_GetInformationalStrings();
8482 test_GetGdiInterop();
8483 test_CreateFontFaceFromHdc();
8484 test_GetSimulations();
8485 test_GetFaceNames();
8486 test_TryGetFontTable();
8487 test_ConvertFontToLOGFONT();
8488 test_CreateStreamFromKey();
8489 test_ReadFileFragment();
8490 test_GetDesignGlyphMetrics();
8491 test_GetDesignGlyphAdvances();
8492 test_IsMonospacedFont();
8493 test_GetGlyphRunOutline();
8494 test_GetEudcFontCollection();
8495 test_GetCaretMetrics();
8496 test_GetGlyphCount();
8497 test_GetKerningPairAdjustments();
8498 test_CreateRenderingParams();
8499 test_CreateGlyphRunAnalysis();
8500 test_GetGdiCompatibleMetrics();
8502 test_GetGdiCompatibleGlyphAdvances();
8503 test_GetRecommendedRenderingMode();
8504 test_GetAlphaBlendParams();
8505 test_CreateAlphaTexture();
8506 test_IsSymbolFont();
8507 test_GetPaletteEntries();
8508 test_TranslateColorGlyphRun();
8509 test_HasCharacter();
8510 test_CreateFontFaceReference();
8511 test_GetFontSignature();
8512 test_font_properties();
8513 test_HasVerticalGlyphVariants();
8514 test_HasKerningPairs();
8515 test_ComputeGlyphOrigins();
8516 test_inmemory_file_loader();
8517 test_GetGlyphImageFormats();
8518 test_CreateCustomRenderingParams();
8519 test_localfontfileloader();
8520 test_AnalyzeContainerType();
8521 test_fontsetbuilder();
8523 IDWriteFactory_Release(factory
);