2 * PROJECT: ReactOS api tests
3 * LICENSE: GPL - See COPYING in the top level directory
4 * PURPOSE: Test for AddFontMemResourceEx
5 * PROGRAMMERS: Mark Jansen
7 * PanosePitchTest + TTCTestV by Katayama Hirofumi MZ, licensed under CC BY
8 * Shadows_Into_Light by Kimberly Geswein, licensed under OFL
9 * Captured from firefox, embedded on reactos.org
17 typedef struct _fnt_res
23 typedef struct _fnt_test
25 const char* ResourceName
;
32 static fnt_test test_data
[] =
35 /* .ResourceName = */ "PanosePitchTest.ttf",
40 /* .FontName = */ "PanosePitchTest",
42 /* .tm.tmHeight = */ 11,
43 /* .tm.tmAscent = */ 11,
44 /* .tm.tmDescent = */ 0,
45 /* .tm.tmInternalLeading = */ -5,
46 /* .tm.tmExternalLeading = */ 1,
47 /* .tm.tmAveCharWidth = */ 8,
48 /* .tm.tmMaxCharWidth = */ 11,
49 /* .tm.tmWeight = */ FW_NORMAL
,
50 /* .tm.tmOverhang = */ 0,
51 /* .tm.tmDigitizedAspectX = */ 96,
52 /* .tm.tmDigitizedAspectY = */ 96,
53 /* .tm.tmFirstChar = */ 63,
54 /* .tm.tmLastChar = */ 65,
55 /* .tm.tmDefaultChar = */ 165,
56 /* .tm.tmBreakChar = */ 65,
57 /* .tm.tmItalic = */ 0,
58 /* .tm.tmUnderlined = */ 0,
59 /* .tm.tmStruckOut = */ 0,
60 /* .tm.tmPitchAndFamily = */ TMPF_TRUETYPE
| TMPF_VECTOR
,
61 /* .tm.tmCharSet = */ SHIFTJIS_CHARSET
,
65 /* .FontName = */ "@PanosePitchTest",
67 /* .tm.tmHeight = */ 11,
68 /* .tm.tmAscent = */ 11,
69 /* .tm.tmDescent = */ 0,
70 /* .tm.tmInternalLeading = */ -5,
71 /* .tm.tmExternalLeading = */ 1,
72 /* .tm.tmAveCharWidth = */ 8,
73 /* .tm.tmMaxCharWidth = */ 11,
74 /* .tm.tmWeight = */ FW_NORMAL
,
75 /* .tm.tmOverhang = */ 0,
76 /* .tm.tmDigitizedAspectX = */ 96,
77 /* .tm.tmDigitizedAspectY = */ 96,
78 /* .tm.tmFirstChar = */ 63,
79 /* .tm.tmLastChar = */ 65,
80 /* .tm.tmDefaultChar = */ 165,
81 /* .tm.tmBreakChar = */ 65,
82 /* .tm.tmItalic = */ 0,
83 /* .tm.tmUnderlined = */ 0,
84 /* .tm.tmStruckOut = */ 0,
85 /* .tm.tmPitchAndFamily = */ TMPF_TRUETYPE
| TMPF_VECTOR
,
86 /* .tm.tmCharSet = */ SHIFTJIS_CHARSET
,
92 /* .ResourceName = */ "TTCTestV.ttc",
97 /* .FontName = */ "No1Of3in1",
99 /* .tm.tmHeight = */ 12,
100 /* .tm.tmAscent = */ 12,
101 /* .tm.tmDescent = */ 0,
102 /* .tm.tmInternalLeading = */ -4,
103 /* .tm.tmExternalLeading = */ 1,
104 /* .tm.tmAveCharWidth = */ -525,
105 /* .tm.tmMaxCharWidth = */ 6,
106 /* .tm.tmWeight = */ FW_NORMAL
,
107 /* .tm.tmOverhang = */ 0,
108 /* .tm.tmDigitizedAspectX = */ 96,
109 /* .tm.tmDigitizedAspectY = */ 96,
110 /* .tm.tmFirstChar = */ 63,
111 /* .tm.tmLastChar = */ 65,
112 /* .tm.tmDefaultChar = */ 64,
113 /* .tm.tmBreakChar = */ 65,
114 /* .tm.tmItalic = */ 0,
115 /* .tm.tmUnderlined = */ 0,
116 /* .tm.tmStruckOut = */ 0,
117 /* .tm.tmPitchAndFamily = */ TMPF_TRUETYPE
| TMPF_VECTOR
| TMPF_FIXED_PITCH
,
118 /* .tm.tmCharSet = */ ANSI_CHARSET
,
122 /* .FontName = */ "No2Of3in1",
124 /* .tm.tmHeight = */ 12,
125 /* .tm.tmAscent = */ 12,
126 /* .tm.tmDescent = */ 0,
127 /* .tm.tmInternalLeading = */ -4,
128 /* .tm.tmExternalLeading = */ 1,
129 /* .tm.tmAveCharWidth = */ 8,
130 /* .tm.tmMaxCharWidth = */ 7,
131 /* .tm.tmWeight = */ FW_NORMAL
,
132 /* .tm.tmOverhang = */ 0,
133 /* .tm.tmDigitizedAspectX = */ 96,
134 /* .tm.tmDigitizedAspectY = */ 96,
135 /* .tm.tmFirstChar = */ 63,
136 /* .tm.tmLastChar = */ 65,
137 /* .tm.tmDefaultChar = */ 64,
138 /* .tm.tmBreakChar = */ 65,
139 /* .tm.tmItalic = */ 0,
140 /* .tm.tmUnderlined = */ 0,
141 /* .tm.tmStruckOut = */ 0,
142 /* .tm.tmPitchAndFamily = */ TMPF_TRUETYPE
| TMPF_VECTOR
| TMPF_FIXED_PITCH
,
143 /* .tm.tmCharSet = */ ANSI_CHARSET
,
147 /* .FontName = */ "No3Of3in1V",
149 /* .tm.tmHeight = */ 12,
150 /* .tm.tmAscent = */ 12,
151 /* .tm.tmDescent = */ 0,
152 /* .tm.tmInternalLeading = */ -4,
153 /* .tm.tmExternalLeading = */ 1,
154 /* .tm.tmAveCharWidth = */ 8,
155 /* .tm.tmMaxCharWidth = */ 13,
156 /* .tm.tmWeight = */ FW_NORMAL
,
157 /* .tm.tmOverhang = */ 0,
158 /* .tm.tmDigitizedAspectX = */ 96,
159 /* .tm.tmDigitizedAspectY = */ 96,
160 /* .tm.tmFirstChar = */ 63,
161 /* .tm.tmLastChar = */ 65,
162 /* .tm.tmDefaultChar = */ 64,
163 /* .tm.tmBreakChar = */ 65,
164 /* .tm.tmItalic = */ 0,
165 /* .tm.tmUnderlined = */ 0,
166 /* .tm.tmStruckOut = */ 0,
167 /* .tm.tmPitchAndFamily = */ FF_MODERN
| TMPF_TRUETYPE
| TMPF_VECTOR
,
168 /* .tm.tmCharSet = */ ANSI_CHARSET
,
174 /* .ResourceName = */ "Shadows_Into_Light.ttf",
179 /* .FontName = */ "ufaXaAlLOxCUGYJ7KN51UP2Q==",
181 /* .tm.tmHeight = */ 26,
182 /* .tm.tmAscent = */ 19,
183 /* .tm.tmDescent = */ 7,
184 /* .tm.tmInternalLeading = */ 10,
185 /* .tm.tmExternalLeading = */ 0,
186 /* .tm.tmAveCharWidth = */ 7,
187 /* .tm.tmMaxCharWidth = */ 23,
188 /* .tm.tmWeight = */ FW_NORMAL
,
189 /* .tm.tmOverhang = */ 0,
190 /* .tm.tmDigitizedAspectX = */ 96,
191 /* .tm.tmDigitizedAspectY = */ 96,
192 /* .tm.tmFirstChar = */ 30,
193 /* .tm.tmLastChar = */ 255,
194 /* .tm.tmDefaultChar = */ 31,
195 /* .tm.tmBreakChar = */ 32,
196 /* .tm.tmItalic = */ 0,
197 /* .tm.tmUnderlined = */ 0,
198 /* .tm.tmStruckOut = */ 0,
199 /* .tm.tmPitchAndFamily = */ TMPF_TRUETYPE
| TMPF_VECTOR
| TMPF_FIXED_PITCH
,
200 /* .tm.tmCharSet = */ ANSI_CHARSET
,
208 #define ok_int2(expression) \
210 int _value = (expression); \
211 ok(_value == (res->expression), "Wrong value for '%s', expected: %d, got: %d for %s/%s\n", \
212 #expression, (int)(res->expression), _value, test_name, res->FontName); \
215 #define ok_hex2(expression) \
217 int _value = (expression); \
218 ok(_value == (res->expression), "Wrong value for '%s', expected: 0x%x, got: 0x%x for %s/%s\n", \
219 #expression, (int)(res->expression), _value, test_name, res->FontName); \
223 static void test_font_caps(HDC hdc
, int test_index
)
226 TEXTMETRICA tm
= { 0 };
231 const char* test_name
= test_data
[test_index
].ResourceName
;
233 for (n
= 0; test_data
[test_index
].res
[n
].FontName
; ++n
)
235 fnt_res
* res
= test_data
[test_index
].res
+ n
;
236 font
= CreateFontA(0, 0, 0, 0, FW_DONTCARE
, FALSE
, FALSE
, FALSE
, DEFAULT_CHARSET
,
237 OUT_DEFAULT_PRECIS
, CLIP_DEFAULT_PRECIS
, DEFAULT_QUALITY
, DEFAULT_PITCH
, res
->FontName
);
241 old
= SelectObject(hdc
, font
);
243 memset(&tm
, 0xaa, sizeof(tm
));
244 ret
= GetTextMetricsA(hdc
, &tm
);
245 ok(ret
, "GetTextMetricsA() for %s/%s\n", test_name
, res
->FontName
);
247 SetLastError(0xdeadbeef);
248 ret
= GetTextFaceA(hdc
, sizeof(name
), name
);
249 ok(ret
, "GetTextFaceA error %lu for %s/%s\n", GetLastError(), test_name
, res
->FontName
);
252 ok(!strcmp(name
, res
->FontName
), "FontName was %s, expected %s for %s/%s", name
, res
->FontName
, test_name
, res
->FontName
);
255 ok_int2(tm
.tmHeight
);
256 ok_int2(tm
.tmAscent
);
257 ok_int2(tm
.tmDescent
);
258 ok_int2(tm
.tmInternalLeading
);
259 ok_int2(tm
.tmExternalLeading
);
260 ok_int2(tm
.tmAveCharWidth
);
261 ok_int2(tm
.tmMaxCharWidth
);
262 ok_int2(tm
.tmWeight
);
263 ok_int2(tm
.tmOverhang
);
264 ok_int2(tm
.tmDigitizedAspectX
);
265 ok_int2(tm
.tmDigitizedAspectY
);
266 ok_int2(tm
.tmFirstChar
);
267 ok_int2(tm
.tmLastChar
);
268 ok_int2(tm
.tmDefaultChar
);
269 ok_int2(tm
.tmBreakChar
);
270 ok_int2(tm
.tmItalic
);
271 ok_int2(tm
.tmUnderlined
);
272 ok_int2(tm
.tmStruckOut
);
273 ok_hex2(tm
.tmPitchAndFamily
);
274 ok_int2(tm
.tmCharSet
);
276 SelectObject(hdc
, old
);
283 /* Not working as of 2017-04-08 on ReactOS */
284 static BOOL
is_font_available(HDC hdc
, const char* fontName
)
289 HFONT font
= CreateFontA(0, 0, 0, 0, FW_DONTCARE
, FALSE
, FALSE
, FALSE
, DEFAULT_CHARSET
,
290 OUT_DEFAULT_PRECIS
, CLIP_DEFAULT_PRECIS
, DEFAULT_QUALITY
, DEFAULT_PITCH
, fontName
);
291 HGDIOBJ old
= SelectObject(hdc
, font
);
294 SetLastError(0xdeadbeef);
296 ret
= GetTextFaceA(hdc
, sizeof(name
), name
);
297 ok(ret
, "GetTextFaceA error %lu for %s\n", GetLastError(), fontName
);
298 SelectObject(hdc
, old
);
303 return !_strcmpi(name
, fontName
);
310 START_TEST(AddFontMemResourceEx
)
316 DWORD dwSize
, dwNumFonts
;
323 HDC hdc
= CreateCompatibleDC(NULL
);
324 BOOL is_font_available_broken
= is_font_available(hdc
, "Nonexisting font name here");
326 ok(!is_font_available_broken
, "Validating font is broken! (CORE-13053)!\n");
328 for (n
= 0; n
< _countof(test_data
); ++n
)
330 data
= test_data
+ n
;
332 mod
= GetModuleHandle(NULL
);
333 hRsrc
= FindResourceA(mod
, data
->ResourceName
, MAKEINTRESOURCE(RT_RCDATA
));
335 hTemplate
= LoadResource(mod
, hRsrc
);
336 dwSize
= SizeofResource(mod
, hRsrc
);
337 pFont
= LockResource(hTemplate
);
340 hFont
= AddFontMemResourceEx(pFont
, dwSize
, NULL
, &dwNumFonts
);
341 ok(dwNumFonts
== data
->NumFaces
, "dwNumFonts was %lu, expected %d for %s\n", dwNumFonts
, data
->NumFaces
, data
->ResourceName
);
342 ok(hFont
!= NULL
, "Expected valid handle for %s\n", data
->ResourceName
);
346 test_font_caps(hdc
, n
);
347 RemoveFontMemResourceEx(hFont
);
348 if (!is_font_available_broken
)
350 ok (!is_font_available(hdc
, data
->ResourceName
), "Expected font to be unregistered again for %s\n", data
->ResourceName
);
354 skip("Font unregister test for %s\n", data
->ResourceName
);
358 UnlockResource(hTemplate
);
359 FreeResource(hTemplate
);