1 /*
2 * PROJECT: ReactOS api tests
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: Test for GetTextMetrics and GetTextExtentPoint32
5 * COPYRIGHT: Copyright 2018 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
6 */
7
8 #include "precomp.h"
9
10 /* #define EMIT_TESTCASES */
11
12 typedef struct TEST_ENTRY
13 {
14 int line;
15 LONG lfHeight;
16 LONG lfWidth;
17 LONG cxText;
18 LONG cyText;
19 LONG tmHeight;
20 LONG tmAscent;
21 LONG tmDescent;
22 LONG tmInternalLeading;
23 LONG tmExternalLeading;
24 } TEST_ENTRY;
25
26 #ifdef EMIT_TESTCASES
27 static const TEST_ENTRY g_test_entries[] =
28 {
29 { __LINE__, 400, 0 },
30 { __LINE__, 300, 0 },
31 { __LINE__, 200, 0 },
32 { __LINE__, 100, 0 },
33 { __LINE__, 64, 0 },
34 { __LINE__, 32, 0 },
35 { __LINE__, 16, 0 },
36 { __LINE__, 15, 0 },
37 { __LINE__, 14, 0 },
38 { __LINE__, 13, 0 },
39 { __LINE__, 12, 0 },
40 { __LINE__, 11, 0 },
41 { __LINE__, 10, 0 },
42 { __LINE__, 9, 0 },
43 { __LINE__, 8, 0 },
44 { __LINE__, 7, 0 },
45 { __LINE__, 6, 0 },
46 { __LINE__, 5, 0 },
47 { __LINE__, 4, 0 },
48 { __LINE__, 3, 0 },
49 { __LINE__, 2, 0 },
50 { __LINE__, 1, 0 },
51 { __LINE__, 0, 0 },
52 { __LINE__, -1, 0 },
53 { __LINE__, -2, 0 },
54 { __LINE__, -3, 0 },
55 { __LINE__, -4, 0 },
56 { __LINE__, -5, 0 },
57 { __LINE__, -6, 0 },
58 { __LINE__, -7, 0 },
59 { __LINE__, -8, 0 },
60 { __LINE__, -9, 0 },
61 { __LINE__, -10, 0 },
62 { __LINE__, -11, 0 },
63 { __LINE__, -12, 0 },
64 { __LINE__, -13, 0 },
65 { __LINE__, -14, 0 },
66 { __LINE__, -15, 0 },
67 { __LINE__, -16, 0 },
68 { __LINE__, -32, 0 },
69 { __LINE__, -64, 0 },
70 { __LINE__, -100, 0 },
71 { __LINE__, -200, 0 },
72 { __LINE__, -300, 0 },
73 { __LINE__, -400, 0 },
74 };
75 #define g_test_entry_count _countof(g_test_entries)
76 #else
77 static const TEST_ENTRY g_MSGOTHIC[] =
78 {
79 { __LINE__, 400, 0, 3000, 400, 400, 344, 56, 0, 0 },
80 { __LINE__, 300, 0, 2250, 300, 300, 258, 42, 0, 0 },
81 { __LINE__, 200, 0, 1500, 200, 200, 172, 28, 0, 0 },
82 { __LINE__, 100, 0, 750, 100, 100, 86, 14, 0, 0 },
83 { __LINE__, 64, 0, 480, 64, 64, 55, 9, 0, 0 },
84 { __LINE__, 32, 0, 240, 33, 33, 28, 5, 1, 0 },
85 { __LINE__, 16, 0, 120, 16, 16, 14, 2, 0, 0 },
86 { __LINE__, 15, 0, 120, 15, 15, 13, 2, 0, 0 },
87 { __LINE__, 14, 0, 105, 14, 14, 12, 2, 0, 0 },
88 { __LINE__, 13, 0, 105, 13, 13, 11, 2, 0, 0 },
89 { __LINE__, 12, 0, 90, 12, 12, 10, 2, 0, 0 },
90 { __LINE__, 11, 0, 90, 11, 11, 9, 2, 0, 0 },
91 { __LINE__, 10, 0, 75, 10, 10, 9, 1, 0, 0 },
92 { __LINE__, 9, 0, 75, 9, 9, 8, 1, 0, 0 },
93 { __LINE__, 8, 0, 60, 8, 8, 7, 1, 0, 0 },
94 { __LINE__, 7, 0, 60, 7, 7, 6, 1, 0, 0 },
95 { __LINE__, 6, 0, 45, 6, 6, 5, 1, 0, 0 },
96 { __LINE__, 5, 0, 45, 5, 5, 4, 1, 0, 0 },
97 { __LINE__, 4, 0, 30, 4, 4, 3, 1, 0, 0 },
98 { __LINE__, 3, 0, 30, 3, 3, 3, 0, 0, 0 },
99 { __LINE__, 2, 0, 15, 2, 2, 2, 0, 0, 0 },
100 { __LINE__, 1, 0, 15, 2, 2, 2, 0, 0, 0 },
101 { __LINE__, 0, 0, -135, -18, -18, -15, -3, 0, 0 },
102 { __LINE__, -1, 0, 15, 2, 2, 2, 0, 0, 0 },
103 { __LINE__, -2, 0, 15, 2, 2, 2, 0, 0, 0 },
104 { __LINE__, -3, 0, 30, 3, 3, 3, 0, 0, 0 },
105 { __LINE__, -4, 0, 30, 4, 4, 3, 1, 0, 0 },
106 { __LINE__, -5, 0, 45, 5, 5, 4, 1, 0, 0 },
107 { __LINE__, -6, 0, 45, 6, 6, 5, 1, 0, 0 },
108 { __LINE__, -7, 0, 60, 7, 7, 6, 1, 0, 0 },
109 { __LINE__, -8, 0, 60, 8, 8, 7, 1, 0, 0 },
110 { __LINE__, -9, 0, 75, 9, 9, 8, 1, 0, 0 },
111 { __LINE__, -10, 0, 75, 10, 10, 9, 1, 0, 0 },
112 { __LINE__, -11, 0, 90, 11, 11, 9, 2, 0, 0 },
113 { __LINE__, -12, 0, 90, 12, 12, 10, 2, 0, 0 },
114 { __LINE__, -13, 0, 105, 13, 13, 11, 2, 0, 0 },
115 { __LINE__, -14, 0, 105, 14, 14, 12, 2, 0, 0 },
116 { __LINE__, -15, 0, 120, 15, 15, 13, 2, 0, 0 },
117 { __LINE__, -16, 0, 120, 16, 16, 14, 2, 0, 0 },
118 { __LINE__, -32, 0, 240, 33, 33, 28, 5, 1, 0 },
119 { __LINE__, -64, 0, 480, 64, 64, 55, 9, 0, 0 },
120 { __LINE__, -100, 0, 750, 100, 100, 86, 14, 0, 0 },
121 { __LINE__, -200, 0, 1500, 200, 200, 172, 28, 0, 0 },
122 { __LINE__, -300, 0, 2250, 300, 300, 258, 42, 0, 0 },
123 { __LINE__, -400, 0, 3000, 400, 400, 344, 56, 0, 0 },
124 };
125 #define g_MSGOTHIC_count _countof(g_MSGOTHIC)
126
127 static const TEST_ENTRY g_MSMINCHO[] =
128 {
129 { __LINE__, 400, 0, 3000, 400, 400, 344, 56, 0, 0 },
130 { __LINE__, 300, 0, 2250, 300, 300, 258, 42, 0, 0 },
131 { __LINE__, 200, 0, 1500, 200, 200, 172, 28, 0, 0 },
132 { __LINE__, 100, 0, 750, 100, 100, 86, 14, 0, 0 },
133 { __LINE__, 64, 0, 480, 64, 64, 55, 9, 0, 0 },
134 { __LINE__, 32, 0, 240, 33, 33, 28, 5, 1, 0 },
135 { __LINE__, 16, 0, 120, 16, 16, 14, 2, 0, 0 },
136 { __LINE__, 15, 0, 120, 15, 15, 13, 2, 0, 0 },
137 { __LINE__, 14, 0, 105, 14, 14, 12, 2, 0, 0 },
138 { __LINE__, 13, 0, 105, 13, 13, 11, 2, 0, 0 },
139 { __LINE__, 12, 0, 90, 12, 12, 10, 2, 0, 0 },
140 { __LINE__, 11, 0, 90, 11, 11, 9, 2, 0, 0 },
141 { __LINE__, 10, 0, 75, 10, 10, 9, 1, 0, 0 },
142 { __LINE__, 9, 0, 75, 9, 9, 8, 1, 0, 0 },
143 { __LINE__, 8, 0, 60, 8, 8, 7, 1, 0, 0 },
144 { __LINE__, 7, 0, 60, 7, 7, 6, 1, 0, 0 },
145 { __LINE__, 6, 0, 45, 6, 6, 5, 1, 0, 0 },
146 { __LINE__, 5, 0, 45, 5, 5, 4, 1, 0, 0 },
147 { __LINE__, 4, 0, 30, 4, 4, 3, 1, 0, 0 },
148 { __LINE__, 3, 0, 30, 3, 3, 3, 0, 0, 0 },
149 { __LINE__, 2, 0, 15, 2, 2, 2, 0, 0, 0 },
150 { __LINE__, 1, 0, 15, 2, 2, 2, 0, 0, 0 },
151 { __LINE__, 0, 0, -135, -18, -18, -15, -3, 0, 0 },
152 { __LINE__, -1, 0, 15, 2, 2, 2, 0, 0, 0 },
153 { __LINE__, -2, 0, 15, 2, 2, 2, 0, 0, 0 },
154 { __LINE__, -3, 0, 30, 3, 3, 3, 0, 0, 0 },
155 { __LINE__, -4, 0, 30, 4, 4, 3, 1, 0, 0 },
156 { __LINE__, -5, 0, 45, 5, 5, 4, 1, 0, 0 },
157 { __LINE__, -6, 0, 45, 6, 6, 5, 1, 0, 0 },
158 { __LINE__, -7, 0, 60, 7, 7, 6, 1, 0, 0 },
159 { __LINE__, -8, 0, 60, 8, 8, 7, 1, 0, 0 },
160 { __LINE__, -9, 0, 75, 9, 9, 8, 1, 0, 0 },
161 { __LINE__, -10, 0, 75, 10, 10, 9, 1, 0, 0 },
162 { __LINE__, -11, 0, 90, 11, 11, 9, 2, 0, 0 },
163 { __LINE__, -12, 0, 90, 12, 12, 10, 2, 0, 0 },
164 { __LINE__, -13, 0, 105, 13, 13, 11, 2, 0, 0 },
165 { __LINE__, -14, 0, 105, 14, 14, 12, 2, 0, 0 },
166 { __LINE__, -15, 0, 120, 15, 15, 13, 2, 0, 0 },
167 { __LINE__, -16, 0, 120, 16, 16, 14, 2, 0, 0 },
168 { __LINE__, -32, 0, 240, 33, 33, 28, 5, 1, 0 },
169 { __LINE__, -64, 0, 480, 64, 64, 55, 9, 0, 0 },
170 { __LINE__, -100, 0, 750, 100, 100, 86, 14, 0, 0 },
171 { __LINE__, -200, 0, 1500, 200, 200, 172, 28, 0, 0 },
172 { __LINE__, -300, 0, 2250, 300, 300, 258, 42, 0, 0 },
173 { __LINE__, -400, 0, 3000, 400, 400, 344, 56, 0, 0 },
174 };
175 #define g_MSMINCHO_count _countof(g_MSMINCHO)
176
177 static const TEST_ENTRY g_TAHOMA[] =
178 {
179 { __LINE__, 400, 0, 1953, 400, 400, 332, 68, 0, 0 },
180 { __LINE__, 300, 0, 1466, 300, 300, 249, 51, 0, 0 },
181 { __LINE__, 200, 0, 980, 200, 200, 166, 34, 0, 0 },
182 { __LINE__, 100, 0, 490, 100, 100, 83, 17, 0, 0 },
183 { __LINE__, 64, 0, 316, 64, 64, 53, 11, 0, 0 },
184 { __LINE__, 32, 0, 156, 32, 32, 27, 5, 6, 0 },
185 { __LINE__, 16, 0, 77, 16, 16, 13, 3, 0, 0 },
186 { __LINE__, 15, 0, 73, 15, 15, 12, 3, 0, 0 },
187 { __LINE__, 14, 0, 73, 14, 14, 12, 2, 0, 0 },
188 { __LINE__, 13, 0, 64, 13, 13, 11, 2, 0, 0 },
189 { __LINE__, 12, 0, 56, 12, 12, 10, 2, 0, 0 },
190 { __LINE__, 11, 0, 55, 11, 11, 9, 2, 0, 0 },
191 { __LINE__, 10, 0, 50, 10, 10, 8, 2, 0, 0 },
192 { __LINE__, 9, 0, 41, 9, 9, 7, 2, 0, 0 },
193 { __LINE__, 8, 0, 41, 8, 8, 7, 1, 0, 0 },
194 { __LINE__, 7, 0, 36, 7, 7, 6, 1, 0, 0 },
195 { __LINE__, 6, 0, 32, 6, 6, 5, 1, 0, 0 },
196 { __LINE__, 5, 0, 22, 5, 5, 4, 1, 0, 0 },
197 { __LINE__, 4, 0, 19, 4, 4, 3, 1, 0, 0 },
198 { __LINE__, 3, 0, 13, 4, 4, 3, 0, 0, 0 },
199 { __LINE__, 2, 0, 13, 2, 2, 2, 0, 0, 0 },
200 { __LINE__, 1, 0, 13, 2, 2, 2, 0, 0, 0 },
201 { __LINE__, 0, 0, -135, -18, -18, -15, -3, 0, 0 },
202 { __LINE__, -1, 0, 13, 2, 2, 2, 0, 0, 0 },
203 { __LINE__, -2, 0, 13, 2, 2, 2, 0, 0, 0 },
204 { __LINE__, -3, 0, 19, 4, 4, 3, 0, 0, 0 },
205 { __LINE__, -4, 0, 22, 5, 5, 4, 1, 0, 0 },
206 { __LINE__, -5, 0, 32, 6, 6, 5, 1, 0, 0 },
207 { __LINE__, -6, 0, 36, 7, 7, 6, 1, 0, 0 },
208 { __LINE__, -7, 0, 41, 8, 8, 7, 1, 0, 0 },
209 { __LINE__, -8, 0, 50, 10, 10, 8, 2, 0, 0 },
210 { __LINE__, -9, 0, 55, 11, 11, 9, 2, 0, 0 },
211 { __LINE__, -10, 0, 56, 12, 12, 10, 2, 0, 0 },
212 { __LINE__, -11, 0, 64, 13, 13, 11, 2, 0, 0 },
213 { __LINE__, -12, 0, 73, 14, 14, 12, 2, 0, 0 },
214 { __LINE__, -13, 0, 77, 16, 16, 13, 3, 0, 0 },
215 { __LINE__, -14, 0, 78, 17, 17, 14, 3, 0, 0 },
216 { __LINE__, -15, 0, 89, 18, 18, 15, 3, 0, 0 },
217 { __LINE__, -16, 0, 94, 19, 19, 16, 3, 0, 0 },
218 { __LINE__, -32, 0, 189, 39, 39, 32, 7, 7, 0 },
219 { __LINE__, -64, 0, 379, 77, 77, 64, 13, 0, 0 },
220 { __LINE__, -100, 0, 589, 121, 121, 100, 21, 0, 0 },
221 { __LINE__, -200, 0, 1182, 241, 241, 200, 41, 0, 0 },
222 { __LINE__, -300, 0, 1770, 362, 362, 300, 62, 0, 0 },
223 { __LINE__, -400, 0, 2361, 483, 483, 400, 83, 0, 0 },
224 };
225 #define g_TAHOMA_count _countof(g_TAHOMA)
226
227 #endif
228
229 typedef struct FONT_ENTRY
230 {
231 const char *entry_name;
232 const char *font_name;
233 const char *font_file;
234 size_t test_count;
235 const TEST_ENTRY *tests;
236 } FONT_ENTRY;
237
238 static FONT_ENTRY g_font_entries[] =
239 {
240 #ifdef EMIT_TESTCASES
241 { "MSGOTHIC", "MS Gothic", "msgothic.ttc" },
242 { "MSMINCHO", "MS Mincho", "msmincho.ttc" },
243 { "TAHOMA", "Tahoma", "tahoma.ttf" },
244 #else
245 { "MSGOTHIC", "MS Gothic", "msgothic.ttc", g_MSGOTHIC_count, g_MSGOTHIC },
246 { "MSMINCHO", "MS Mincho", "msmincho.ttc", g_MSMINCHO_count, g_MSMINCHO },
247 { "TAHOMA", "Tahoma", "Tahoma.ttf", g_TAHOMA_count, g_TAHOMA },
248 #endif
249 };
250 static size_t g_font_entry_count = _countof(g_font_entries);
251
START_TEST(GetTextMetrics)252 START_TEST(GetTextMetrics)
253 {
254 size_t i, k;
255 LOGFONTA lf;
256 HFONT hFont;
257 HDC hDC;
258 HGDIOBJ hFontOld;
259 SIZE siz;
260 TEXTMETRIC tm;
261 char szPath[MAX_PATH];
262 static const char *text = "This is a test.";
263
264 hDC = CreateCompatibleDC(NULL);
265 for (i = 0; i < g_font_entry_count; ++i)
266 {
267 FONT_ENTRY *font = &g_font_entries[i];
268 ZeroMemory(&lf, sizeof(lf));
269 lf.lfCharSet = DEFAULT_CHARSET;
270 lstrcpyA(lf.lfFaceName, font->font_name);
271
272 GetWindowsDirectoryA(szPath, MAX_PATH);
273 lstrcatA(szPath, "\\Fonts\\");
274 lstrcatA(szPath, font->font_file);
275 if (GetFileAttributesA(szPath) == 0xFFFFFFFF)
276 {
277 skip("Font file '%s' doesn't exists\n", font->font_file);
278 continue;
279 }
280
281 trace("Testing '%s'.\n", font->font_file);
282
283 #ifdef EMIT_TESTCASES
284 printf("static const TEST_ENTRY g_%s[] =\n", font->entry_name);
285 printf("{\n");
286 for (k = 0; k < g_test_entry_count; ++k)
287 {
288 const TEST_ENTRY *test = &g_test_entries[k];
289
290 lf.lfHeight = test->lfHeight;
291 lf.lfWidth = test->lfWidth;
292
293 hFont = CreateFontIndirectA(&lf);
294 hFontOld = SelectObject(hDC, hFont);
295 {
296 GetTextExtentPoint32A(hDC, text, lstrlenA(text), &siz);
297 GetTextMetrics(hDC, &tm);
298 }
299 SelectObject(hDC, hFontOld);
300 DeleteObject(hFont);
301
302 printf(" { __LINE__, %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld },\n",
303 lf.lfHeight, lf.lfWidth,
304 siz.cx, siz.cy,
305 tm.tmHeight, tm.tmAscent, tm.tmDescent, tm.tmInternalLeading, tm.tmExternalLeading);
306 }
307 printf("};\n");
308 printf("#define g_%s_count _countof(g_%s)\n\n", font->entry_name, font->entry_name);
309 #else
310 for (k = 0; k < font->test_count; ++k)
311 {
312 const TEST_ENTRY *test = &font->tests[k];
313
314 lf.lfHeight = test->lfHeight;
315 lf.lfWidth = test->lfWidth;
316
317 hFont = CreateFontIndirectA(&lf);
318 hFontOld = SelectObject(hDC, hFont);
319 {
320 GetTextExtentPoint32A(hDC, text, lstrlenA(text), &siz);
321 GetTextMetrics(hDC, &tm);
322 }
323 SelectObject(hDC, hFontOld);
324 DeleteObject(hFont);
325
326 if (test->cxText > 0)
327 {
328 ok_(__FILE__, test->line)(labs(test->cxText - siz.cx) <= 1, "%s (%ld): cxText: labs(%ld - %ld) > 1\n", font->entry_name, test->lfHeight, test->cxText, siz.cx);
329 ok_(__FILE__, test->line)(labs(test->cxText - siz.cx) == 0, "%s (%ld): cxText: labs(%ld - %ld) != 0\n", font->entry_name, test->lfHeight, test->cxText, siz.cx);
330 }
331 if (test->cyText > 0)
332 {
333 ok_(__FILE__, test->line)(labs(test->cyText - siz.cy) <= 1, "%s (%ld): cyText: labs(%ld - %ld) > 1\n", font->entry_name, test->lfHeight, test->cyText, siz.cy);
334 ok_(__FILE__, test->line)(labs(test->cyText - siz.cy) == 0, "%s (%ld): cyText: labs(%ld - %ld) != 0\n", font->entry_name, test->lfHeight, test->cyText, siz.cy);
335 }
336 if (test->tmHeight > 0)
337 {
338 ok_(__FILE__, test->line)(labs(test->tmHeight - tm.tmHeight) <= 1, "%s (%ld): tmHeight: labs(%ld - %ld) > 1\n", font->entry_name, test->lfHeight, test->tmHeight, tm.tmHeight);
339 ok_(__FILE__, test->line)(labs(test->tmHeight - tm.tmHeight) == 0, "%s (%ld): tmHeight: labs(%ld - %ld) != 0\n", font->entry_name, test->lfHeight, test->tmHeight, tm.tmHeight);
340 }
341 if (test->tmAscent > 0)
342 {
343 ok_(__FILE__, test->line)(labs(test->tmAscent - tm.tmAscent) <= 1, "%s (%ld): tmAscent: labs(%ld - %ld) > 1\n", font->entry_name, test->lfHeight, test->tmAscent, tm.tmAscent);
344 ok_(__FILE__, test->line)(labs(test->tmAscent - tm.tmAscent) == 0, "%s (%ld): tmAscent: labs(%ld - %ld) != 0\n", font->entry_name, test->lfHeight, test->tmAscent, tm.tmAscent);
345 }
346 if (test->tmDescent > 0)
347 {
348 ok_(__FILE__, test->line)(labs(test->tmDescent - tm.tmDescent) <= 1, "%s (%ld): tmDescent: labs(%ld - %ld) > 1\n", font->entry_name, test->lfHeight, test->tmDescent, tm.tmDescent);
349 ok_(__FILE__, test->line)(labs(test->tmDescent - tm.tmDescent) == 0, "%s (%ld): tmDescent: labs(%ld - %ld) != 0\n", font->entry_name, test->lfHeight, test->tmDescent, tm.tmDescent);
350 }
351 if (test->tmInternalLeading > 0)
352 {
353 ok_(__FILE__, test->line)(labs(test->tmInternalLeading - tm.tmInternalLeading) <= 1, "%s (%ld): tmInternalLeading: labs(%ld - %ld) > 1\n", font->entry_name, test->lfHeight, test->tmInternalLeading, tm.tmInternalLeading);
354 ok_(__FILE__, test->line)(labs(test->tmInternalLeading - tm.tmInternalLeading) == 0, "%s (%ld): tmInternalLeading: labs(%ld - %ld) != 0\n", font->entry_name, test->lfHeight, test->tmInternalLeading, tm.tmInternalLeading);
355 }
356 if (test->tmExternalLeading > 0)
357 {
358 ok_(__FILE__, test->line)(labs(test->tmExternalLeading - tm.tmExternalLeading) <= 1, "%s (%ld): tmExternalLeading: labs(%ld - %ld) > 1\n", font->entry_name, test->lfHeight, test->tmExternalLeading, tm.tmExternalLeading);
359 ok_(__FILE__, test->line)(labs(test->tmExternalLeading - tm.tmExternalLeading) == 0, "%s (%ld): tmExternalLeading: labs(%ld - %ld) != 0\n", font->entry_name, test->lfHeight, test->tmExternalLeading, tm.tmExternalLeading);
360 }
361 }
362 #endif
363 }
364 DeleteDC(hDC);
365 }
366