ReactOS  0.4.14-dev-384-g5b37caa
AddFontMemResourceEx.c
Go to the documentation of this file.
1 /*
2  * PROJECT: ReactOS api tests
3  * LICENSE: GPL - See COPYING in the top level directory
4  * PURPOSE: Test for AddFontMemResourceEx
5  * PROGRAMMERS: Mark Jansen
6  *
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
10  */
11 
12 #include "precomp.h"
13 
14 typedef struct _fnt_res
15 {
16  const char* FontName;
18 } fnt_res;
19 
20 typedef struct _fnt_test
21 {
22  const char* ResourceName;
23  int NumFaces;
25 } fnt_test;
26 
27 
28 
29 static fnt_test test_data[] =
30 {
31  {
32  /* .ResourceName = */ "PanosePitchTest.ttf",
33  /* .NumFaces = */ 2,
34  /* .res = */
35  {
36  {
37  /* .FontName = */ "PanosePitchTest",
38  {
39  /* .tm.tmHeight = */ 11,
40  /* .tm.tmAscent = */ 11,
41  /* .tm.tmDescent = */ 0,
42  /* .tm.tmInternalLeading = */ -5,
43  /* .tm.tmExternalLeading = */ 1,
44  /* .tm.tmAveCharWidth = */ 8,
45  /* .tm.tmMaxCharWidth = */ 11,
46  /* .tm.tmWeight = */ FW_NORMAL,
47  /* .tm.tmOverhang = */ 0,
48  /* .tm.tmDigitizedAspectX = */ 96,
49  /* .tm.tmDigitizedAspectY = */ 96,
50  /* .tm.tmFirstChar = */ 63,
51  /* .tm.tmLastChar = */ 65,
52  /* .tm.tmDefaultChar = */ 165,
53  /* .tm.tmBreakChar = */ 65,
54  /* .tm.tmItalic = */ 0,
55  /* .tm.tmUnderlined = */ 0,
56  /* .tm.tmStruckOut = */ 0,
57  /* .tm.tmPitchAndFamily = */ TMPF_TRUETYPE | TMPF_VECTOR,
58  /* .tm.tmCharSet = */ SHIFTJIS_CHARSET,
59  }
60  },
61  {
62  /* .FontName = */ "@PanosePitchTest",
63  {
64  /* .tm.tmHeight = */ 11,
65  /* .tm.tmAscent = */ 11,
66  /* .tm.tmDescent = */ 0,
67  /* .tm.tmInternalLeading = */ -5,
68  /* .tm.tmExternalLeading = */ 1,
69  /* .tm.tmAveCharWidth = */ 8,
70  /* .tm.tmMaxCharWidth = */ 11,
71  /* .tm.tmWeight = */ FW_NORMAL,
72  /* .tm.tmOverhang = */ 0,
73  /* .tm.tmDigitizedAspectX = */ 96,
74  /* .tm.tmDigitizedAspectY = */ 96,
75  /* .tm.tmFirstChar = */ 63,
76  /* .tm.tmLastChar = */ 65,
77  /* .tm.tmDefaultChar = */ 165,
78  /* .tm.tmBreakChar = */ 65,
79  /* .tm.tmItalic = */ 0,
80  /* .tm.tmUnderlined = */ 0,
81  /* .tm.tmStruckOut = */ 0,
82  /* .tm.tmPitchAndFamily = */ TMPF_TRUETYPE | TMPF_VECTOR,
83  /* .tm.tmCharSet = */ SHIFTJIS_CHARSET,
84  }
85  },
86  },
87  },
88  {
89  /* .ResourceName = */ "TTCTestV.ttc",
90  /* .NumFaces = */ 3,
91  /* .res = */
92  {
93  {
94  /* .FontName = */ "No1Of3in1",
95  {
96  /* .tm.tmHeight = */ 12,
97  /* .tm.tmAscent = */ 12,
98  /* .tm.tmDescent = */ 0,
99  /* .tm.tmInternalLeading = */ -4,
100  /* .tm.tmExternalLeading = */ 1,
101  /* .tm.tmAveCharWidth = */ -525,
102  /* .tm.tmMaxCharWidth = */ 6,
103  /* .tm.tmWeight = */ FW_NORMAL,
104  /* .tm.tmOverhang = */ 0,
105  /* .tm.tmDigitizedAspectX = */ 96,
106  /* .tm.tmDigitizedAspectY = */ 96,
107  /* .tm.tmFirstChar = */ 63,
108  /* .tm.tmLastChar = */ 65,
109  /* .tm.tmDefaultChar = */ 64,
110  /* .tm.tmBreakChar = */ 65,
111  /* .tm.tmItalic = */ 0,
112  /* .tm.tmUnderlined = */ 0,
113  /* .tm.tmStruckOut = */ 0,
114  /* .tm.tmPitchAndFamily = */ TMPF_TRUETYPE | TMPF_VECTOR | TMPF_FIXED_PITCH,
115  /* .tm.tmCharSet = */ ANSI_CHARSET,
116  }
117  },
118  {
119  /* .FontName = */ "No2Of3in1",
120  {
121  /* .tm.tmHeight = */ 12,
122  /* .tm.tmAscent = */ 12,
123  /* .tm.tmDescent = */ 0,
124  /* .tm.tmInternalLeading = */ -4,
125  /* .tm.tmExternalLeading = */ 1,
126  /* .tm.tmAveCharWidth = */ 8,
127  /* .tm.tmMaxCharWidth = */ 7,
128  /* .tm.tmWeight = */ FW_NORMAL,
129  /* .tm.tmOverhang = */ 0,
130  /* .tm.tmDigitizedAspectX = */ 96,
131  /* .tm.tmDigitizedAspectY = */ 96,
132  /* .tm.tmFirstChar = */ 63,
133  /* .tm.tmLastChar = */ 65,
134  /* .tm.tmDefaultChar = */ 64,
135  /* .tm.tmBreakChar = */ 65,
136  /* .tm.tmItalic = */ 0,
137  /* .tm.tmUnderlined = */ 0,
138  /* .tm.tmStruckOut = */ 0,
139  /* .tm.tmPitchAndFamily = */ TMPF_TRUETYPE | TMPF_VECTOR | TMPF_FIXED_PITCH,
140  /* .tm.tmCharSet = */ ANSI_CHARSET,
141  }
142  },
143  {
144  /* .FontName = */ "No3Of3in1V",
145  {
146  /* .tm.tmHeight = */ 12,
147  /* .tm.tmAscent = */ 12,
148  /* .tm.tmDescent = */ 0,
149  /* .tm.tmInternalLeading = */ -4,
150  /* .tm.tmExternalLeading = */ 1,
151  /* .tm.tmAveCharWidth = */ 8,
152  /* .tm.tmMaxCharWidth = */ 13,
153  /* .tm.tmWeight = */ FW_NORMAL,
154  /* .tm.tmOverhang = */ 0,
155  /* .tm.tmDigitizedAspectX = */ 96,
156  /* .tm.tmDigitizedAspectY = */ 96,
157  /* .tm.tmFirstChar = */ 63,
158  /* .tm.tmLastChar = */ 65,
159  /* .tm.tmDefaultChar = */ 64,
160  /* .tm.tmBreakChar = */ 65,
161  /* .tm.tmItalic = */ 0,
162  /* .tm.tmUnderlined = */ 0,
163  /* .tm.tmStruckOut = */ 0,
164  /* .tm.tmPitchAndFamily = */ FF_MODERN | TMPF_TRUETYPE | TMPF_VECTOR,
165  /* .tm.tmCharSet = */ ANSI_CHARSET,
166  }
167  },
168  },
169  },
170  {
171  /* .ResourceName = */ "Shadows_Into_Light.ttf",
172  /* .NumFaces = */ 1,
173  /* .res = */
174  {
175  {
176  /* .FontName = */ "ufaXaAlLOxCUGYJ7KN51UP2Q==",
177  {
178  /* .tm.tmHeight = */ 26,
179  /* .tm.tmAscent = */ 19,
180  /* .tm.tmDescent = */ 7,
181  /* .tm.tmInternalLeading = */ 10,
182  /* .tm.tmExternalLeading = */ 0,
183  /* .tm.tmAveCharWidth = */ 7,
184  /* .tm.tmMaxCharWidth = */ 23,
185  /* .tm.tmWeight = */ FW_NORMAL,
186  /* .tm.tmOverhang = */ 0,
187  /* .tm.tmDigitizedAspectX = */ 96,
188  /* .tm.tmDigitizedAspectY = */ 96,
189  /* .tm.tmFirstChar = */ 30,
190  /* .tm.tmLastChar = */ 255,
191  /* .tm.tmDefaultChar = */ 31,
192  /* .tm.tmBreakChar = */ 32,
193  /* .tm.tmItalic = */ 0,
194  /* .tm.tmUnderlined = */ 0,
195  /* .tm.tmStruckOut = */ 0,
196  /* .tm.tmPitchAndFamily = */ TMPF_TRUETYPE | TMPF_VECTOR | TMPF_FIXED_PITCH,
197  /* .tm.tmCharSet = */ ANSI_CHARSET,
198  }
199  },
200  },
201  },
202 };
203 
204 
205 #define ok_int2(expression) \
206  do { \
207  int _value = (expression); \
208  ok(_value == (res->expression), "Wrong value for '%s', expected: %d, got: %d for %s/%s\n", \
209  #expression, (int)(res->expression), _value, test_name, res->FontName); \
210  } while (0)
211 
212 #define ok_hex2(expression) \
213  do { \
214  int _value = (expression); \
215  ok(_value == (res->expression), "Wrong value for '%s', expected: 0x%x, got: 0x%x for %s/%s\n", \
216  #expression, (int)(res->expression), _value, test_name, res->FontName); \
217  } while (0)
218 
219 
220 static void test_font_caps(HDC hdc, int test_index)
221 {
222  HGDIOBJ old;
223  TEXTMETRICA tm = { 0 };
224  char name[64];
225  BOOL ret;
226  HFONT font;
227  int n;
228  const char* test_name = test_data[test_index].ResourceName;
229 
230  for (n = 0; test_data[test_index].res[n].FontName; ++n)
231  {
232  fnt_res* res = test_data[test_index].res + n;
235 
236  if (font)
237  {
238  old = SelectObject(hdc, font);
239 
240  memset(&tm, 0xaa, sizeof(tm));
241  ret = GetTextMetricsA(hdc, &tm);
242  ok(ret, "GetTextMetricsA() for %s/%s\n", test_name, res->FontName);
243 
244  SetLastError(0xdeadbeef);
245  ret = GetTextFaceA(hdc, sizeof(name), name);
246  ok(ret, "GetTextFaceA error %lu for %s/%s\n", GetLastError(), test_name, res->FontName);
247  if (ret)
248  {
249  ok(!strcmp(name, res->FontName), "FontName was %s, expected %s for %s/%s", name, res->FontName, test_name, res->FontName);
250  }
251 
252  ok_int2(tm.tmHeight);
253  ok_int2(tm.tmAscent);
254  ok_int2(tm.tmDescent);
255  ok_int2(tm.tmInternalLeading);
256  ok_int2(tm.tmExternalLeading);
257  ok_int2(tm.tmAveCharWidth);
258  ok_int2(tm.tmMaxCharWidth);
259  ok_int2(tm.tmWeight);
260  ok_int2(tm.tmOverhang);
261  ok_int2(tm.tmDigitizedAspectX);
262  ok_int2(tm.tmDigitizedAspectY);
263  ok_int2(tm.tmFirstChar);
264  ok_int2(tm.tmLastChar);
265  ok_int2(tm.tmDefaultChar);
266  ok_int2(tm.tmBreakChar);
267  ok_int2(tm.tmItalic);
268  ok_int2(tm.tmUnderlined);
269  ok_int2(tm.tmStruckOut);
270  ok_hex2(tm.tmPitchAndFamily);
271  ok_int2(tm.tmCharSet);
272 
273  SelectObject(hdc, old);
275  }
276  }
277 }
278 
279 
280 /* Not working as of 2017-04-08 on ReactOS */
281 static BOOL is_font_available(HDC hdc, const char* fontName)
282 {
283  char name[64];
284  BOOL ret;
285 
288  HGDIOBJ old = SelectObject(hdc, font);
289 
290 
291  SetLastError(0xdeadbeef);
292 
293  ret = GetTextFaceA(hdc, sizeof(name), name);
294  ok(ret, "GetTextFaceA error %lu for %s\n", GetLastError(), fontName);
295  SelectObject(hdc, old);
297 
298  if (ret)
299  {
300  return !_strcmpi(name, fontName);
301  }
302  return FALSE;
303 }
304 
305 
306 
308 {
309  HMODULE mod;
310  HRSRC hRsrc;
311 
312  HGLOBAL hTemplate;
313  DWORD dwSize, dwNumFonts;
314  LPVOID pFont;
315 
316  HANDLE hFont;
317  fnt_test* data;
318  int n;
319 
321  BOOL is_font_available_broken = is_font_available(hdc, "Nonexisting font name here");
322 
323  ok(!is_font_available_broken, "Validating font is broken! (CORE-13053)!\n");
324 
325  for (n = 0; n < _countof(test_data); ++n)
326  {
327  data = test_data + n;
328 
330  hRsrc = FindResourceA(mod, data->ResourceName, MAKEINTRESOURCE(RT_RCDATA));
331 
332  hTemplate = LoadResource(mod, hRsrc);
333  dwSize = SizeofResource(mod, hRsrc);
334  pFont = LockResource(hTemplate);
335 
336  dwNumFonts = 0;
337  hFont = AddFontMemResourceEx(pFont, dwSize, NULL, &dwNumFonts);
338  ok(dwNumFonts == data->NumFaces, "dwNumFonts was %lu, expected %d for %s\n", dwNumFonts, data->NumFaces, data->ResourceName);
339  ok(hFont != NULL, "Expected valid handle for %s\n", data->ResourceName);
340 
341  if (hFont)
342  {
343  test_font_caps(hdc, n);
345  if (!is_font_available_broken)
346  {
347  ok (!is_font_available(hdc, data->ResourceName), "Expected font to be unregistered again for %s\n", data->ResourceName);
348  }
349  else
350  {
351  skip("Font unregister test for %s\n", data->ResourceName);
352  }
353  }
354 
355  UnlockResource(hTemplate);
356  FreeResource(hTemplate);
357  }
358 
359  DeleteDC(hdc);
360 }
361 
#define MAKEINTRESOURCE
Definition: winuser.h:591
#define DEFAULT_QUALITY
Definition: wingdi.h:435
Definition: mk_font.cpp:20
#define _countof(array)
Definition: fontsub.cpp:30
struct _fnt_res fnt_res
HRSRC WINAPI FindResourceA(HMODULE hModule, LPCSTR name, LPCSTR type)
Definition: res.c:155
static HDC
Definition: imagelist.c:92
GLdouble n
Definition: glext.h:7729
HGDIOBJ WINAPI SelectObject(_In_ HDC, _In_ HGDIOBJ)
Definition: dc.c:1497
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
BOOL WINAPI DeleteObject(_In_ HGDIOBJ)
LPVOID WINAPI LockResource(HGLOBAL handle)
Definition: res.c:550
HDC WINAPI CreateCompatibleDC(_In_opt_ HDC hdc)
HANDLE WINAPI AddFontMemResourceEx(_In_reads_bytes_(cjSize) PVOID pvFileView, _In_ DWORD cjSize, _Reserved_ PVOID pvResrved, _In_ DWORD *pNumFonts)
#define DEFAULT_CHARSET
Definition: wingdi.h:383
HFONT hFont
Definition: main.c:53
GLenum const GLvoid * fontName
Definition: glext.h:11715
#define UnlockResource(h)
Definition: winbase.h:3196
#define ok_int2(expression)
TEXTMETRICA tm
unsigned int BOOL
Definition: ntddk_ex.h:94
#define TMPF_TRUETYPE
Definition: wingdi.h:1312
#define CLIP_DEFAULT_PRECIS
Definition: wingdi.h:425
BOOL WINAPI FreeResource(HGLOBAL handle)
Definition: res.c:559
HGLOBAL WINAPI LoadResource(HINSTANCE hModule, HRSRC hRsrc)
Definition: res.c:532
struct _fnt_test fnt_test
smooth NULL
Definition: ftsmooth.c:416
BOOL WINAPI GetTextMetricsA(_In_ HDC, _Out_ LPTEXTMETRICA)
Definition: text.c:200
const char * ResourceName
#define DEFAULT_PITCH
Definition: wingdi.h:442
static void test_font_caps(HDC hdc, int test_index)
#define ok_hex2(expression)
#define SHIFTJIS_CHARSET
Definition: wingdi.h:385
#define OUT_DEFAULT_PRECIS
Definition: wingdi.h:414
unsigned long DWORD
Definition: ntddk_ex.h:95
#define SetLastError(x)
Definition: compat.h:417
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
#define RT_RCDATA
Definition: pedump.c:372
int ret
const char * FontName
HDC hdc
Definition: main.c:9
BOOL WINAPI RemoveFontMemResourceEx(HANDLE fh)
Definition: font.c:2475
Definition: time.h:76
HFONT WINAPI CreateFontA(_In_ int, _In_ int, _In_ int, _In_ int, _In_ int, _In_ DWORD, _In_ DWORD, _In_ DWORD, _In_ DWORD, _In_ DWORD, _In_ DWORD, _In_ DWORD, _In_ DWORD, _In_opt_ LPCSTR)
#define TMPF_VECTOR
Definition: wingdi.h:1311
static const char * test_name
Definition: run.c:177
#define FW_DONTCARE
Definition: wingdi.h:367
#define GetModuleHandle
Definition: winbase.h:3651
BOOL WINAPI DeleteDC(_In_ HDC)
#define ok(value,...)
Definition: atltest.h:57
#define FF_MODERN
Definition: wingdi.h:448
DWORD WINAPI SizeofResource(HINSTANCE hModule, HRSRC hRsrc)
Definition: res.c:568
START_TEST(AddFontMemResourceEx)
#define FW_NORMAL
Definition: wingdi.h:372
static DWORD *static HFONT(WINAPI *pCreateFontIndirectExA)(const ENUMLOGFONTEXDVA *)
#define skip(...)
Definition: atltest.h:64
Definition: name.c:36
int WINAPI GetTextFaceA(_In_ HDC hdc, _In_ int c, _Out_writes_to_opt_(c, return) LPSTR lpName)
GLuint res
Definition: glext.h:9613
static BOOL is_font_available(HDC hdc, const char *fontName)
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
#define TMPF_FIXED_PITCH
Definition: wingdi.h:1310
#define ANSI_CHARSET
Definition: wingdi.h:382
_Check_return_ _CRTIMP int __cdecl _strcmpi(_In_z_ const char *_Str1, _In_z_ const char *_Str2)
#define memset(x, y, z)
Definition: compat.h:39
PSDBQUERYRESULT_VISTA PVOID DWORD * dwSize
Definition: env.c:54
static int mod
Definition: i386-dis.c:1273