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",
44 .tm
.tmInternalLeading
= -5,
45 .tm
.tmExternalLeading
= 1,
46 .tm
.tmAveCharWidth
= 8,
47 .tm
.tmMaxCharWidth
= 11,
48 .tm
.tmWeight
= FW_NORMAL
,
50 .tm
.tmDigitizedAspectX
= 96,
51 .tm
.tmDigitizedAspectY
= 96,
54 .tm
.tmDefaultChar
= 165,
59 .tm
.tmPitchAndFamily
= TMPF_TRUETYPE
| TMPF_VECTOR
,
60 .tm
.tmCharSet
= SHIFTJIS_CHARSET
,
63 .FontName
= "@PanosePitchTest",
67 .tm
.tmInternalLeading
= -5,
68 .tm
.tmExternalLeading
= 1,
69 .tm
.tmAveCharWidth
= 8,
70 .tm
.tmMaxCharWidth
= 11,
71 .tm
.tmWeight
= FW_NORMAL
,
73 .tm
.tmDigitizedAspectX
= 96,
74 .tm
.tmDigitizedAspectY
= 96,
77 .tm
.tmDefaultChar
= 165,
82 .tm
.tmPitchAndFamily
= TMPF_TRUETYPE
| TMPF_VECTOR
,
83 .tm
.tmCharSet
= SHIFTJIS_CHARSET
,
88 .ResourceName
= "TTCTestV.ttc",
93 .FontName
= "No1Of3in1",
97 .tm
.tmInternalLeading
= -4,
98 .tm
.tmExternalLeading
= 1,
99 .tm
.tmAveCharWidth
= -525,
100 .tm
.tmMaxCharWidth
= 6,
101 .tm
.tmWeight
= FW_NORMAL
,
103 .tm
.tmDigitizedAspectX
= 96,
104 .tm
.tmDigitizedAspectY
= 96,
105 .tm
.tmFirstChar
= 63,
107 .tm
.tmDefaultChar
= 64,
108 .tm
.tmBreakChar
= 65,
110 .tm
.tmUnderlined
= 0,
112 .tm
.tmPitchAndFamily
= TMPF_TRUETYPE
| TMPF_VECTOR
| TMPF_FIXED_PITCH
,
113 .tm
.tmCharSet
= ANSI_CHARSET
,
116 .FontName
= "No2Of3in1",
120 .tm
.tmInternalLeading
= -4,
121 .tm
.tmExternalLeading
= 1,
122 .tm
.tmAveCharWidth
= 8,
123 .tm
.tmMaxCharWidth
= 7,
124 .tm
.tmWeight
= FW_NORMAL
,
126 .tm
.tmDigitizedAspectX
= 96,
127 .tm
.tmDigitizedAspectY
= 96,
128 .tm
.tmFirstChar
= 63,
130 .tm
.tmDefaultChar
= 64,
131 .tm
.tmBreakChar
= 65,
133 .tm
.tmUnderlined
= 0,
135 .tm
.tmPitchAndFamily
= TMPF_TRUETYPE
| TMPF_VECTOR
| TMPF_FIXED_PITCH
,
136 .tm
.tmCharSet
= ANSI_CHARSET
,
139 .FontName
= "No3Of3in1V",
143 .tm
.tmInternalLeading
= -4,
144 .tm
.tmExternalLeading
= 1,
145 .tm
.tmAveCharWidth
= 8,
146 .tm
.tmMaxCharWidth
= 13,
147 .tm
.tmWeight
= FW_NORMAL
,
149 .tm
.tmDigitizedAspectX
= 96,
150 .tm
.tmDigitizedAspectY
= 96,
151 .tm
.tmFirstChar
= 63,
153 .tm
.tmDefaultChar
= 64,
154 .tm
.tmBreakChar
= 65,
156 .tm
.tmUnderlined
= 0,
158 .tm
.tmPitchAndFamily
= FF_MODERN
| TMPF_TRUETYPE
| TMPF_VECTOR
,
159 .tm
.tmCharSet
= ANSI_CHARSET
,
164 .ResourceName
= "Shadows_Into_Light.ttf",
169 .FontName
= "ufaXaAlLOxCUGYJ7KN51UP2Q==",
173 .tm
.tmInternalLeading
= 10,
174 .tm
.tmExternalLeading
= 0,
175 .tm
.tmAveCharWidth
= 7,
176 .tm
.tmMaxCharWidth
= 23,
177 .tm
.tmWeight
= FW_NORMAL
,
179 .tm
.tmDigitizedAspectX
= 96,
180 .tm
.tmDigitizedAspectY
= 96,
181 .tm
.tmFirstChar
= 30,
182 .tm
.tmLastChar
= 255,
183 .tm
.tmDefaultChar
= 31,
184 .tm
.tmBreakChar
= 32,
186 .tm
.tmUnderlined
= 0,
188 .tm
.tmPitchAndFamily
= TMPF_TRUETYPE
| TMPF_VECTOR
| TMPF_FIXED_PITCH
,
189 .tm
.tmCharSet
= ANSI_CHARSET
,
196 #define ok_int2(expression) \
198 int _value = (expression); \
199 ok(_value == (res->expression), "Wrong value for '%s', expected: %d, got: %d for %s/%s\n", \
200 #expression, (int)(res->expression), _value, test_name, res->FontName); \
203 #define ok_hex2(expression) \
205 int _value = (expression); \
206 ok(_value == (res->expression), "Wrong value for '%s', expected: 0x%x, got: 0x%x for %s/%s\n", \
207 #expression, (int)(res->expression), _value, test_name, res->FontName); \
211 static void test_font_caps(HDC hdc
, int test_index
)
214 TEXTMETRICA tm
= { 0 };
219 const char* test_name
= test_data
[test_index
].ResourceName
;
221 for (n
= 0; test_data
[test_index
].res
[n
].FontName
; ++n
)
223 fnt_res
* res
= test_data
[test_index
].res
+ n
;
224 font
= CreateFontA(0, 0, 0, 0, FW_DONTCARE
, FALSE
, FALSE
, FALSE
, DEFAULT_CHARSET
,
225 OUT_DEFAULT_PRECIS
, CLIP_DEFAULT_PRECIS
, DEFAULT_QUALITY
, DEFAULT_PITCH
, res
->FontName
);
229 old
= SelectObject(hdc
, font
);
231 memset(&tm
, 0xaa, sizeof(tm
));
232 ret
= GetTextMetricsA(hdc
, &tm
);
233 ok(ret
, "GetTextMetricsA() for %s/%s\n", test_name
, res
->FontName
);
235 SetLastError(0xdeadbeef);
236 ret
= GetTextFaceA(hdc
, sizeof(name
), name
);
237 ok(ret
, "GetTextFaceA error %lu for %s/%s\n", GetLastError(), test_name
, res
->FontName
);
240 ok(!strcmp(name
, res
->FontName
), "FontName was %s, expected %s for %s/%s", name
, res
->FontName
, test_name
, res
->FontName
);
243 ok_int2(tm
.tmHeight
);
244 ok_int2(tm
.tmAscent
);
245 ok_int2(tm
.tmDescent
);
246 ok_int2(tm
.tmInternalLeading
);
247 ok_int2(tm
.tmExternalLeading
);
248 ok_int2(tm
.tmAveCharWidth
);
249 ok_int2(tm
.tmMaxCharWidth
);
250 ok_int2(tm
.tmWeight
);
251 ok_int2(tm
.tmOverhang
);
252 ok_int2(tm
.tmDigitizedAspectX
);
253 ok_int2(tm
.tmDigitizedAspectY
);
254 ok_int2(tm
.tmFirstChar
);
255 ok_int2(tm
.tmLastChar
);
256 ok_int2(tm
.tmDefaultChar
);
257 ok_int2(tm
.tmBreakChar
);
258 ok_int2(tm
.tmItalic
);
259 ok_int2(tm
.tmUnderlined
);
260 ok_int2(tm
.tmStruckOut
);
261 ok_hex2(tm
.tmPitchAndFamily
);
262 ok_int2(tm
.tmCharSet
);
264 SelectObject(hdc
, old
);
271 /* Not working as of 2017-04-08 on ReactOS */
272 static BOOL
is_font_available(HDC hdc
, const char* fontName
)
277 HFONT font
= CreateFontA(0, 0, 0, 0, FW_DONTCARE
, FALSE
, FALSE
, FALSE
, DEFAULT_CHARSET
,
278 OUT_DEFAULT_PRECIS
, CLIP_DEFAULT_PRECIS
, DEFAULT_QUALITY
, DEFAULT_PITCH
, fontName
);
279 HGDIOBJ old
= SelectObject(hdc
, font
);
282 SetLastError(0xdeadbeef);
284 ret
= GetTextFaceA(hdc
, sizeof(name
), name
);
285 ok(ret
, "GetTextFaceA error %lu for %s\n", GetLastError(), fontName
);
286 SelectObject(hdc
, old
);
291 return !_strcmpi(name
, fontName
);
298 START_TEST(AddFontMemResourceEx
)
304 DWORD dwSize
, dwNumFonts
;
311 HDC hdc
= CreateCompatibleDC(NULL
);
312 BOOL is_font_available_broken
= is_font_available(hdc
, "Nonexisting font name here");
314 ok(!is_font_available_broken
, "Validating font is broken! (CORE-13053)!\n");
316 for (n
= 0; n
< _countof(test_data
); ++n
)
318 data
= test_data
+ n
;
320 mod
= GetModuleHandle(NULL
);
321 hRsrc
= FindResourceA(mod
, data
->ResourceName
, MAKEINTRESOURCE(RT_RCDATA
));
323 hTemplate
= LoadResource(mod
, hRsrc
);
324 dwSize
= SizeofResource(mod
, hRsrc
);
325 pFont
= LockResource(hTemplate
);
328 hFont
= AddFontMemResourceEx(pFont
, dwSize
, NULL
, &dwNumFonts
);
329 ok(dwNumFonts
== data
->NumFaces
, "dwNumFonts was %lu, expected %d for %s\n", dwNumFonts
, data
->NumFaces
, data
->ResourceName
);
330 ok(hFont
!= NULL
, "Expected valid handle for %s\n", data
->ResourceName
);
334 test_font_caps(hdc
, n
);
335 RemoveFontMemResourceEx(hFont
);
336 if (!is_font_available_broken
)
338 ok (!is_font_available(hdc
, data
->ResourceName
), "Expected font to be unregistered again for %s\n", data
->ResourceName
);
342 skip("Font unregister test for %s\n", data
->ResourceName
);
346 UnlockResource(hTemplate
);
347 FreeResource(hTemplate
);