ReactOS 0.4.17-dev-218-g5635d24
font.c
Go to the documentation of this file.
1/*
2 * Unit test suite for fonts
3 *
4 * Copyright 2002 Mike McCormack
5 * Copyright 2004 Dmitry Timoshkov
6 *
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.
11 *
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.
16 *
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
20 */
21
22#include <stdarg.h>
23#include <stdio.h>
24#include <assert.h>
25
26#include "windef.h"
27#include "winbase.h"
28#include "wingdi.h"
29#include "winuser.h"
30#include "winnls.h"
31
32#include "wine/test.h"
33
34static inline BOOL match_off_by_n(int a, int b, unsigned int n)
35{
36 return abs(a - b) <= n;
37}
38#define match_off_by_1(a, b, exact) match_off_by_n((a), (b), (exact) ? 0 : 1)
39#define near_match(a, b) match_off_by_n((a), (b), 6)
40#define expect(expected, got) ok(got == expected, "Expected %.8x, got %.8x\n", expected, got)
41
42static LONG (WINAPI *pGdiGetCharDimensions)(HDC hdc, LPTEXTMETRICW lptm, LONG *height);
43static DWORD (WINAPI *pGdiGetCodePage)(HDC hdc);
44static BOOL (WINAPI *pGetCharWidthInfo)(HDC hdc, void *);
45static BOOL (WINAPI *pGdiRealizationInfo)(HDC hdc, DWORD *);
46static BOOL (WINAPI *pGetFontRealizationInfo)(HDC hdc, DWORD *);
47static BOOL (WINAPI *pGetFontFileInfo)(DWORD, DWORD, void *, SIZE_T, SIZE_T *);
48static BOOL (WINAPI *pGetFontFileData)(DWORD, DWORD, UINT64, void *, SIZE_T);
49
50static HMODULE hgdi32 = 0;
51static const MAT2 mat = { {0,1}, {0,0}, {0,0}, {0,1} };
53
54#ifdef WORDS_BIGENDIAN
55#define GET_BE_WORD(x) (x)
56#define GET_BE_DWORD(x) (x)
57#else
58#define GET_BE_WORD(x) MAKEWORD(HIBYTE(x), LOBYTE(x))
59#define GET_BE_DWORD(x) MAKELONG(GET_BE_WORD(HIWORD(x)), GET_BE_WORD(LOWORD(x)));
60#endif
61
62#define MS_MAKE_TAG(ch0, ch1, ch2, ch3) \
63 ((DWORD)(BYTE)(ch0) | ((DWORD)(BYTE)(ch1) << 8) | \
64 ((DWORD)(BYTE)(ch2) << 16) | ((DWORD)(BYTE)(ch3) << 24))
65#define MS_OS2_TAG MS_MAKE_TAG('O','S','/','2')
66#define MS_CMAP_TAG MS_MAKE_TAG('c','m','a','p')
67#define MS_NAME_TAG MS_MAKE_TAG('n','a','m','e')
68
69static void init(void)
70{
71 hgdi32 = GetModuleHandleA("gdi32.dll");
72
73 pGdiGetCharDimensions = (void *)GetProcAddress(hgdi32, "GdiGetCharDimensions");
74 pGdiGetCodePage = (void *) GetProcAddress(hgdi32,"GdiGetCodePage");
75 pGetCharWidthInfo = (void *)GetProcAddress(hgdi32, "GetCharWidthInfo");
76 pGdiRealizationInfo = (void *)GetProcAddress(hgdi32, "GdiRealizationInfo");
77 pGetFontRealizationInfo = (void *)GetProcAddress(hgdi32, "GetFontRealizationInfo");
78 pGetFontFileInfo = (void *)GetProcAddress(hgdi32, "GetFontFileInfo");
79 pGetFontFileData = (void *)GetProcAddress(hgdi32, "GetFontFileData");
80
82}
83
85{
86 if (type != TRUETYPE_FONTTYPE) return 1;
87
88 return 0;
89}
90
92{
93 HDC hdc = GetDC(0);
94 BOOL ret = FALSE;
95
97 ret = TRUE;
98
99 ReleaseDC(0, hdc);
100 return ret;
101}
102
104{
105 return 0;
106}
107
108static BOOL is_font_installed(const char *name)
109{
110 HDC hdc = GetDC(0);
111 BOOL ret = FALSE;
112
114 ret = TRUE;
115
116 ReleaseDC(0, hdc);
117 return ret;
118}
119
120static void *get_res_data(const char *fontname, DWORD *rsrc_size)
121{
122 HRSRC rsrc;
123 void *rsrc_data;
124
126 if (!rsrc) return NULL;
127
128 rsrc_data = LockResource(LoadResource(GetModuleHandleA(NULL), rsrc));
129 if (!rsrc_data) return NULL;
130
131 *rsrc_size = SizeofResource(GetModuleHandleA(NULL), rsrc);
132 if (!*rsrc_size) return NULL;
133
134 return rsrc_data;
135}
136
137static BOOL write_tmp_file( const void *data, DWORD *size, char *tmp_name )
138{
139 char tmp_path[MAX_PATH];
140 HANDLE hfile;
141 BOOL ret;
142
143 GetTempPathA(MAX_PATH, tmp_path);
144 GetTempFileNameA(tmp_path, "ttf", 0, tmp_name);
145
147 if (hfile == INVALID_HANDLE_VALUE) return FALSE;
148
149 ret = WriteFile(hfile, data, *size, size, NULL);
150
151 CloseHandle(hfile);
152 return ret;
153}
154
155static BOOL write_ttf_file(const char *fontname, char *tmp_name)
156{
157 void *rsrc_data;
158 DWORD rsrc_size;
159
160 rsrc_data = get_res_data( fontname, &rsrc_size );
161 if (!rsrc_data) return FALSE;
162
163 return write_tmp_file( rsrc_data, &rsrc_size, tmp_name );
164}
165
166static void check_font(const char* test, const LOGFONTA* lf, HFONT hfont)
167{
168 LOGFONTA getobj_lf;
169 int ret;
170
171 if (!hfont)
172 return;
173
174 ret = GetObjectA(hfont, sizeof(getobj_lf), &getobj_lf);
175 ok(ret == sizeof(LOGFONTA), "%s: GetObject returned %d\n", test, ret);
176 ok(lf->lfHeight == getobj_lf.lfHeight, "lfHeight: expect %08lx got %08lx\n", lf->lfHeight, getobj_lf.lfHeight);
177 ok(lf->lfWidth == getobj_lf.lfWidth, "lfWidth: expect %08lx got %08lx\n", lf->lfWidth, getobj_lf.lfWidth);
178 ok(lf->lfEscapement == getobj_lf.lfEscapement, "lfEscapement: expect %08lx got %08lx\n", lf->lfEscapement, getobj_lf.lfEscapement);
179 ok(lf->lfOrientation == getobj_lf.lfOrientation, "lfOrientation: expect %08lx got %08lx\n", lf->lfOrientation, getobj_lf.lfOrientation);
180 ok(lf->lfWeight == getobj_lf.lfWeight, "lfWeight: expect %08lx got %08lx\n", lf->lfWeight, getobj_lf.lfWeight);
181 ok(lf->lfItalic == getobj_lf.lfItalic, "lfItalic: expect %02x got %02x\n", lf->lfItalic, getobj_lf.lfItalic);
182 ok(lf->lfUnderline == getobj_lf.lfUnderline, "lfUnderline: expect %02x got %02x\n", lf->lfUnderline, getobj_lf.lfUnderline);
183 ok(lf->lfStrikeOut == getobj_lf.lfStrikeOut, "lfStrikeOut: expect %02x got %02x\n", lf->lfStrikeOut, getobj_lf.lfStrikeOut);
184 ok(lf->lfCharSet == getobj_lf.lfCharSet, "lfCharSet: expect %02x got %02x\n", lf->lfCharSet, getobj_lf.lfCharSet);
185 ok(lf->lfOutPrecision == getobj_lf.lfOutPrecision, "lfOutPrecision: expect %02x got %02x\n", lf->lfOutPrecision, getobj_lf.lfOutPrecision);
186 ok(lf->lfClipPrecision == getobj_lf.lfClipPrecision, "lfClipPrecision: expect %02x got %02x\n", lf->lfClipPrecision, getobj_lf.lfClipPrecision);
187 ok(lf->lfQuality == getobj_lf.lfQuality, "lfQuality: expect %02x got %02x\n", lf->lfQuality, getobj_lf.lfQuality);
188 ok(lf->lfPitchAndFamily == getobj_lf.lfPitchAndFamily, "lfPitchAndFamily: expect %02x got %02x\n", lf->lfPitchAndFamily, getobj_lf.lfPitchAndFamily);
189 ok(!lstrcmpA(lf->lfFaceName, getobj_lf.lfFaceName), "%s: font names don't match: %s != %s\n", test, lf->lfFaceName, getobj_lf.lfFaceName);
190}
191
192static HFONT create_font(const char* test, const LOGFONTA* lf)
193{
194 HFONT hfont = CreateFontIndirectA(lf);
195 ok(hfont != 0, "%s: CreateFontIndirect failed\n", test);
196 if (hfont)
197 check_font(test, lf, hfont);
198 return hfont;
199}
200
201static void test_logfont(void)
202{
203 LOGFONTA lf;
204 HFONT hfont;
205
206 memset(&lf, 0, sizeof lf);
207
211 lf.lfHeight = 16;
212 lf.lfWidth = 16;
214
215 lstrcpyA(lf.lfFaceName, "Arial");
216 hfont = create_font("Arial", &lf);
218
219 memset(&lf, 'A', sizeof(lf));
221 ok(hfont != 0, "CreateFontIndirectA with strange LOGFONT failed\n");
222
223 lf.lfFaceName[LF_FACESIZE - 1] = 0;
224 check_font("AAA...", &lf, hfont);
226}
227
229{
230 if (type & RASTER_FONTTYPE)
231 {
232 LOGFONTA *lf = (LOGFONTA *)lParam;
233 *lf = *elf;
234 return 0; /* stop enumeration */
235 }
236
237 return 1; /* continue enumeration */
238}
239
240static void compare_tm(const TEXTMETRICA *tm, const TEXTMETRICA *otm)
241{
242 ok(tm->tmHeight == otm->tmHeight, "tmHeight %ld != %ld\n", tm->tmHeight, otm->tmHeight);
243 ok(tm->tmAscent == otm->tmAscent, "tmAscent %ld != %ld\n", tm->tmAscent, otm->tmAscent);
244 ok(tm->tmDescent == otm->tmDescent, "tmDescent %ld != %ld\n", tm->tmDescent, otm->tmDescent);
245 ok(tm->tmInternalLeading == otm->tmInternalLeading, "tmInternalLeading %ld != %ld\n", tm->tmInternalLeading, otm->tmInternalLeading);
246 ok(tm->tmExternalLeading == otm->tmExternalLeading, "tmExternalLeading %ld != %ld\n", tm->tmExternalLeading, otm->tmExternalLeading);
247 ok(tm->tmAveCharWidth == otm->tmAveCharWidth, "tmAveCharWidth %ld != %ld\n", tm->tmAveCharWidth, otm->tmAveCharWidth);
248 ok(tm->tmMaxCharWidth == otm->tmMaxCharWidth, "tmMaxCharWidth %ld != %ld\n", tm->tmMaxCharWidth, otm->tmMaxCharWidth);
249 ok(tm->tmWeight == otm->tmWeight, "tmWeight %ld != %ld\n", tm->tmWeight, otm->tmWeight);
250 ok(tm->tmOverhang == otm->tmOverhang, "tmOverhang %ld != %ld\n", tm->tmOverhang, otm->tmOverhang);
251 ok(tm->tmDigitizedAspectX == otm->tmDigitizedAspectX, "tmDigitizedAspectX %ld != %ld\n", tm->tmDigitizedAspectX, otm->tmDigitizedAspectX);
252 ok(tm->tmDigitizedAspectY == otm->tmDigitizedAspectY, "tmDigitizedAspectY %ld != %ld\n", tm->tmDigitizedAspectY, otm->tmDigitizedAspectY);
253 ok(tm->tmFirstChar == otm->tmFirstChar, "tmFirstChar %d != %d\n", tm->tmFirstChar, otm->tmFirstChar);
254 ok(tm->tmLastChar == otm->tmLastChar, "tmLastChar %d != %d\n", tm->tmLastChar, otm->tmLastChar);
255 ok(tm->tmDefaultChar == otm->tmDefaultChar, "tmDefaultChar %d != %d\n", tm->tmDefaultChar, otm->tmDefaultChar);
256 ok(tm->tmBreakChar == otm->tmBreakChar, "tmBreakChar %d != %d\n", tm->tmBreakChar, otm->tmBreakChar);
257 ok(tm->tmItalic == otm->tmItalic, "tmItalic %d != %d\n", tm->tmItalic, otm->tmItalic);
258 ok(tm->tmUnderlined == otm->tmUnderlined, "tmUnderlined %d != %d\n", tm->tmUnderlined, otm->tmUnderlined);
259 ok(tm->tmStruckOut == otm->tmStruckOut, "tmStruckOut %d != %d\n", tm->tmStruckOut, otm->tmStruckOut);
260 ok(tm->tmPitchAndFamily == otm->tmPitchAndFamily, "tmPitchAndFamily %d != %d\n", tm->tmPitchAndFamily, otm->tmPitchAndFamily);
261 ok(tm->tmCharSet == otm->tmCharSet, "tmCharSet %d != %d\n", tm->tmCharSet, otm->tmCharSet);
262}
263
264static void test_font_metrics(const char *context,
265 HDC hdc, HFONT hfont, LONG lfHeight,
266 LONG lfWidth, const char *test_str,
267 INT test_str_len, const TEXTMETRICA *tm_orig,
268 const SIZE *size_orig, INT width_of_A_orig,
269 INT scale_x, INT scale_y)
270{
271 LOGFONTA lf;
274 SIZE size;
275 INT width_of_A, cx, cy;
276 UINT ret;
277
278 if (!hfont)
279 return;
280
282 ok(GetCurrentObject(hdc, OBJ_FONT) == hfont, "hfont should be selected\n");
283
284 GetObjectA(hfont, sizeof(lf), &lf);
285
287 {
288 otm.otmSize = sizeof(otm) / 2;
290 ok(ret == sizeof(otm)/2, "expected sizeof(otm)/2, got %u\n", ret);
291
292 memset(&otm, 0x1, sizeof(otm));
293 otm.otmSize = sizeof(otm);
295 ok(ret == sizeof(otm), "expected sizeof(otm), got %u\n", ret);
296
297 memset(&tm, 0x2, sizeof(tm));
299 ok(ret, "GetTextMetricsA failed\n");
300 /* the structure size is aligned */
301 if (memcmp(&tm, &otm.otmTextMetrics, FIELD_OFFSET(TEXTMETRICA, tmCharSet) + 1))
302 {
303 ok(0, "tm != otm\n");
305 }
306
307 tm = otm.otmTextMetrics;
308if (0) /* these metrics are scaled too, but with rounding errors */
309{
310 ok(otm.otmAscent == tm.tmAscent, "ascent %d != %ld\n", otm.otmAscent, tm.tmAscent);
311 ok(otm.otmDescent == -tm.tmDescent, "descent %d != %ld\n", otm.otmDescent, -tm.tmDescent);
312}
313 ok(otm.otmMacAscent == tm.tmAscent, "ascent %d != %ld\n", otm.otmMacAscent, tm.tmAscent);
314 ok(otm.otmDescent < 0, "otm.otmDescent should be < 0\n");
315 ok(otm.otmMacDescent < 0, "otm.otmMacDescent should be < 0\n");
316 ok(tm.tmDescent > 0, "tm.tmDescent should be > 0\n");
317 ok(otm.otmMacDescent == -tm.tmDescent, "descent %d != %ld\n", otm.otmMacDescent, -tm.tmDescent);
319 ok(otm.otmEMSquare == 2048, "expected 2048, got %d\n", otm.otmEMSquare);
320 }
321 else
322 {
324 ok(ret, "GetTextMetricsA failed\n");
325 }
326
327 cx = tm.tmAveCharWidth / tm_orig->tmAveCharWidth;
328 cy = tm.tmHeight / tm_orig->tmHeight;
329 ok(cx == scale_x && cy == scale_y, "height %ld: expected scale_x %d, scale_y %d, got cx %d, cy %d\n",
330 lfHeight, scale_x, scale_y, cx, cy);
331 ok(tm.tmHeight == tm_orig->tmHeight * scale_y, "height %ld != %ld\n", tm.tmHeight, tm_orig->tmHeight * scale_y);
332 ok(tm.tmAscent == tm_orig->tmAscent * scale_y, "ascent %ld != %ld\n", tm.tmAscent, tm_orig->tmAscent * scale_y);
333 ok(tm.tmDescent == tm_orig->tmDescent * scale_y, "descent %ld != %ld\n", tm.tmDescent, tm_orig->tmDescent * scale_y);
334 ok(near_match(tm.tmAveCharWidth, tm_orig->tmAveCharWidth * scale_x), "ave width %ld != %ld\n", tm.tmAveCharWidth, tm_orig->tmAveCharWidth * scale_x);
335 ok(near_match(tm.tmMaxCharWidth, tm_orig->tmMaxCharWidth * scale_x), "max width %ld != %ld\n", tm.tmMaxCharWidth, tm_orig->tmMaxCharWidth * scale_x);
336
337 ok(lf.lfHeight == lfHeight, "lfHeight %ld != %ld\n", lf.lfHeight, lfHeight);
338 if (lf.lfHeight)
339 {
340 if (lf.lfWidth)
341 ok(lf.lfWidth == tm.tmAveCharWidth, "lfWidth %ld != tm %ld\n", lf.lfWidth, tm.tmAveCharWidth);
342 }
343 else
344 ok(lf.lfWidth == lfWidth, "lfWidth %ld != %ld\n", lf.lfWidth, lfWidth);
345
346 GetTextExtentPoint32A(hdc, test_str, test_str_len, &size);
347
348 ok(near_match(size.cx, size_orig->cx * scale_x), "cx %ld != %ld\n", size.cx, size_orig->cx * scale_x);
349 ok(size.cy == size_orig->cy * scale_y, "cy %ld != %ld\n", size.cy, size_orig->cy * scale_y);
350
351 GetCharWidthA(hdc, 'A', 'A', &width_of_A);
352
353 ok(near_match(width_of_A, width_of_A_orig * scale_x), "width A %d != %d\n", width_of_A, width_of_A_orig * scale_x);
355}
356
357/* Test how GDI scales bitmap font metrics */
358static void test_bitmap_font(void)
359{
360 static const char test_str[11] = "Test String";
361 HDC hdc;
362 LOGFONTA bitmap_lf;
363 HFONT hfont, old_hfont;
364 TEXTMETRICA tm_orig;
365 SIZE size_orig;
366 INT ret, i, width_orig, height_orig, scale, lfWidth;
367
369
370 /* "System" has only 1 pixel size defined, otherwise the test breaks */
371 ret = EnumFontFamiliesA(hdc, "System", font_enum_proc, (LPARAM)&bitmap_lf);
372 if (ret)
373 {
374 ReleaseDC(0, hdc);
375 skip("no bitmap fonts were found, skipping the test\n");
376 return;
377 }
378
379 trace("found bitmap font %s, height %ld\n", bitmap_lf.lfFaceName, bitmap_lf.lfHeight);
380
381 height_orig = bitmap_lf.lfHeight;
382 lfWidth = bitmap_lf.lfWidth;
383
384 hfont = create_font("bitmap", &bitmap_lf);
385 old_hfont = SelectObject(hdc, hfont);
386 ok(GetTextMetricsA(hdc, &tm_orig), "GetTextMetricsA failed\n");
387 ok(GetTextExtentPoint32A(hdc, test_str, sizeof(test_str), &size_orig), "GetTextExtentPoint32A failed\n");
388 ok(GetCharWidthA(hdc, 'A', 'A', &width_orig), "GetCharWidthA failed\n");
389 SelectObject(hdc, old_hfont);
391
392 bitmap_lf.lfHeight = 0;
393 bitmap_lf.lfWidth = 4;
394 hfont = create_font("bitmap", &bitmap_lf);
395 old_hfont = SelectObject(hdc, hfont);
396 test_font_metrics("bitmap", hdc, hfont, 0, 4, test_str, sizeof(test_str), &tm_orig, &size_orig, width_orig, 1, 1);
397 SelectObject(hdc, old_hfont);
399
400 bitmap_lf.lfHeight = height_orig;
401 bitmap_lf.lfWidth = lfWidth;
402
403 /* test fractional scaling */
404 for (i = 1; i <= height_orig * 6; i++)
405 {
406 INT nearest_height;
407
408 bitmap_lf.lfHeight = i;
409 hfont = create_font("fractional", &bitmap_lf);
410 scale = (i + height_orig - 1) / height_orig;
411 nearest_height = scale * height_orig;
412 /* Only jump to the next height if the difference <= 25% original height */
413 if (scale > 2 && nearest_height - i > height_orig / 4) scale--;
414 /* The jump between unscaled and doubled is delayed by 1 in winnt+ but not in win9x,
415 so we'll not test this particular height. */
416 else if(scale == 2 && nearest_height - i == (height_orig / 4)) continue;
417 else if(scale == 2 && nearest_height - i > (height_orig / 4 - 1)) scale--;
418 old_hfont = SelectObject(hdc, hfont);
419 winetest_push_context("height %i", i);
420 test_font_metrics(NULL, hdc, hfont, bitmap_lf.lfHeight, 0, test_str, sizeof(test_str), &tm_orig, &size_orig, width_orig, 1, scale);
422 SelectObject(hdc, old_hfont);
424 }
425
426 /* test integer scaling 3x2 */
427 bitmap_lf.lfHeight = height_orig * 2;
428 bitmap_lf.lfWidth *= 3;
429 hfont = create_font("3x2", &bitmap_lf);
430 old_hfont = SelectObject(hdc, hfont);
431 test_font_metrics("bitmap 3x2", hdc, hfont, bitmap_lf.lfHeight, 0, test_str, sizeof(test_str), &tm_orig, &size_orig, width_orig, 3, 2);
432 SelectObject(hdc, old_hfont);
434
435 /* test integer scaling 3x3 */
436 bitmap_lf.lfHeight = height_orig * 3;
437 bitmap_lf.lfWidth = 0;
438 hfont = create_font("3x3", &bitmap_lf);
439 old_hfont = SelectObject(hdc, hfont);
440 test_font_metrics("bitmap 3x3", hdc, hfont, bitmap_lf.lfHeight, 0, test_str, sizeof(test_str), &tm_orig, &size_orig, width_orig, 3, 3);
441 SelectObject(hdc, old_hfont);
443
444 DeleteDC(hdc);
445}
446
447/* Test how GDI scales outline font metrics */
448static void test_outline_font(void)
449{
450 static const char test_str[11] = "Test String";
451 HDC hdc, hdc_2;
452 LOGFONTA lf;
453 HFONT hfont, old_hfont, old_hfont_2;
455 SIZE size_orig;
456 INT width_orig, height_orig, lfWidth;
457 XFORM xform;
458 GLYPHMETRICS gm;
459 MAT2 mat2 = { {0x8000,0}, {0,0}, {0,0}, {0x8000,0} };
460 POINT pt;
461 INT ret;
462
463 if (!is_truetype_font_installed("Arial"))
464 {
465 skip("Arial is not installed\n");
466 return;
467 }
468
470
471 memset(&lf, 0, sizeof(lf));
472 strcpy(lf.lfFaceName, "Arial");
473 lf.lfHeight = 72;
474 hfont = create_font("outline", &lf);
475 old_hfont = SelectObject(hdc, hfont);
476 otm.otmSize = sizeof(otm);
477 ok(GetOutlineTextMetricsA(hdc, sizeof(otm), &otm), "GetTextMetricsA failed\n");
478 ok(GetTextExtentPoint32A(hdc, test_str, sizeof(test_str), &size_orig), "GetTextExtentPoint32A failed\n");
479 ok(GetCharWidthA(hdc, 'A', 'A', &width_orig), "GetCharWidthA failed\n");
480
481 test_font_metrics("outline", hdc, hfont, lf.lfHeight, otm.otmTextMetrics.tmAveCharWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
482 SelectObject(hdc, old_hfont);
484
485 /* font of otmEMSquare height helps to avoid a lot of rounding errors */
486 lf.lfHeight = otm.otmEMSquare;
487 lf.lfHeight = -lf.lfHeight;
488 hfont = create_font("outline", &lf);
489 old_hfont = SelectObject(hdc, hfont);
490 otm.otmSize = sizeof(otm);
491 ok(GetOutlineTextMetricsA(hdc, sizeof(otm), &otm), "GetTextMetricsA failed\n");
492 ok(GetTextExtentPoint32A(hdc, test_str, sizeof(test_str), &size_orig), "GetTextExtentPoint32A failed\n");
493 ok(GetCharWidthA(hdc, 'A', 'A', &width_orig), "GetCharWidthA failed\n");
494 SelectObject(hdc, old_hfont);
496
497 height_orig = otm.otmTextMetrics.tmHeight;
498 lfWidth = otm.otmTextMetrics.tmAveCharWidth;
499
500 /* test integer scaling 3x2 */
501 lf.lfHeight = height_orig * 2;
502 lf.lfWidth = lfWidth * 3;
503 hfont = create_font("3x2", &lf);
504 old_hfont = SelectObject(hdc, hfont);
505 test_font_metrics("outline 3x2", hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 3, 2);
506 SelectObject(hdc, old_hfont);
508
509 /* test integer scaling 3x3 */
510 lf.lfHeight = height_orig * 3;
511 lf.lfWidth = lfWidth * 3;
512 hfont = create_font("3x3", &lf);
513 old_hfont = SelectObject(hdc, hfont);
514 test_font_metrics("outline 3x3", hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 3, 3);
515 SelectObject(hdc, old_hfont);
517
518 /* test integer scaling 1x1 */
519 lf.lfHeight = height_orig * 1;
520 lf.lfWidth = lfWidth * 1;
521 hfont = create_font("1x1", &lf);
522 old_hfont = SelectObject(hdc, hfont);
523 test_font_metrics("outline 1x1", hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
524 SelectObject(hdc, old_hfont);
526
527 /* test integer scaling 1x1 */
528 lf.lfHeight = height_orig;
529 lf.lfWidth = 0;
530 hfont = create_font("1x1", &lf);
531 old_hfont = SelectObject(hdc, hfont);
532 test_font_metrics("outline 1x0", hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
533
534 /* with an identity matrix */
535 memset(&gm, 0, sizeof(gm));
536 SetLastError(0xdeadbeef);
537 ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
538 ok(ret != GDI_ERROR, "GetGlyphOutlineA error %ld\n", GetLastError());
539 ok(gm.gmCellIncX == width_orig, "incX %d != %d\n", gm.gmCellIncX, width_orig);
540 ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
541 /* with a custom matrix */
542 memset(&gm, 0, sizeof(gm));
543 SetLastError(0xdeadbeef);
544 ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat2);
545 ok(ret != GDI_ERROR, "GetGlyphOutlineA error %ld\n", GetLastError());
546 ok(gm.gmCellIncX == width_orig/2, "incX %d != %d\n", gm.gmCellIncX, width_orig/2);
547 ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
548
549 /* Test that changing the DC transformation affects only the font
550 * selected on this DC and doesn't affect the same font selected on
551 * another DC.
552 */
553 hdc_2 = CreateCompatibleDC(0);
554 old_hfont_2 = SelectObject(hdc_2, hfont);
555 test_font_metrics("dc2.base", hdc_2, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
556
558
559 /* font metrics on another DC should be unchanged */
560 test_font_metrics("dc2.aniso", hdc_2, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
561
562 /* test restrictions of compatibility mode GM_COMPATIBLE */
563 /* part 1: rescaling only X should not change font scaling on screen.
564 So compressing the X axis by 2 is not done, and this
565 appears as X scaling of 2 that no one requested. */
566 SetWindowExtEx(hdc, 100, 100, NULL);
567 SetViewportExtEx(hdc, 50, 100, NULL);
568 test_font_metrics("xscaling", hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 2, 1);
569 /* font metrics on another DC should be unchanged */
570 test_font_metrics("dc2.xscaling", hdc_2, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
571
572 /* part 2: rescaling only Y should change font scaling.
573 As also X is scaled by a factor of 2, but this is not
574 requested by the DC transformation, we get a scaling factor
575 of 2 in the X coordinate. */
576 SetViewportExtEx(hdc, 100, 200, NULL);
577 test_font_metrics("yscaling", hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 2, 1);
578 /* font metrics on another DC should be unchanged */
579 test_font_metrics("dc2.yscaling", hdc_2, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
580
581 /* restore scaling */
583
584 /* font metrics on another DC should be unchanged */
585 test_font_metrics("dc2.text", hdc_2, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
586
587 SelectObject(hdc_2, old_hfont_2);
588 DeleteDC(hdc_2);
589
591 {
592 SelectObject(hdc, old_hfont);
594 DeleteDC(hdc);
595 skip("GM_ADVANCED is not supported on this platform\n");
596 return;
597 }
598
599 xform.eM11 = 20.0f;
600 xform.eM12 = 0.0f;
601 xform.eM21 = 0.0f;
602 xform.eM22 = 20.0f;
603 xform.eDx = 0.0f;
604 xform.eDy = 0.0f;
605
606 SetLastError(0xdeadbeef);
607 ret = SetWorldTransform(hdc, &xform);
608 ok(ret, "SetWorldTransform error %lu\n", GetLastError());
609
610 test_font_metrics("xform", hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
611
612 /* with an identity matrix */
613 memset(&gm, 0, sizeof(gm));
614 SetLastError(0xdeadbeef);
615 ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
616 ok(ret != GDI_ERROR, "GetGlyphOutlineA error %ld\n", GetLastError());
617 pt.x = width_orig; pt.y = 0;
618 LPtoDP(hdc, &pt, 1);
619 ok(gm.gmCellIncX == pt.x, "incX %d != %ld\n", gm.gmCellIncX, pt.x);
620 ok(gm.gmCellIncX == 20 * width_orig, "incX %d != %d\n", gm.gmCellIncX, 20 * width_orig);
621 ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
622 /* with a custom matrix */
623 memset(&gm, 0, sizeof(gm));
624 SetLastError(0xdeadbeef);
625 ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat2);
626 ok(ret != GDI_ERROR, "GetGlyphOutlineA error %ld\n", GetLastError());
627 pt.x = width_orig; pt.y = 0;
628 LPtoDP(hdc, &pt, 1);
629 ok(gm.gmCellIncX == pt.x/2, "incX %d != %ld\n", gm.gmCellIncX, pt.x/2);
630 ok(near_match(gm.gmCellIncX, 10 * width_orig), "incX %d != %d\n", gm.gmCellIncX, 10 * width_orig);
631 ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
632
633 SetLastError(0xdeadbeef);
635 ok(ret == MM_TEXT, "expected MM_TEXT, got %d, error %lu\n", ret, GetLastError());
636
637 test_font_metrics("lometric", hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
638
639 /* with an identity matrix */
640 memset(&gm, 0, sizeof(gm));
641 SetLastError(0xdeadbeef);
642 ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
643 ok(ret != GDI_ERROR, "GetGlyphOutlineA error %ld\n", GetLastError());
644 pt.x = width_orig; pt.y = 0;
645 LPtoDP(hdc, &pt, 1);
646 ok(near_match(gm.gmCellIncX, pt.x), "incX %d != %ld\n", gm.gmCellIncX, pt.x);
647 ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
648 /* with a custom matrix */
649 memset(&gm, 0, sizeof(gm));
650 SetLastError(0xdeadbeef);
651 ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat2);
652 ok(ret != GDI_ERROR, "GetGlyphOutlineA error %ld\n", GetLastError());
653 pt.x = width_orig; pt.y = 0;
654 LPtoDP(hdc, &pt, 1);
655 ok(near_match(gm.gmCellIncX, (pt.x + 1)/2), "incX %d != %ld\n", gm.gmCellIncX, (pt.x + 1)/2);
656 ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
657
658 SetLastError(0xdeadbeef);
660 ok(ret == MM_LOMETRIC, "expected MM_LOMETRIC, got %d, error %lu\n", ret, GetLastError());
661
662 test_font_metrics("text", hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
663
664 /* with an identity matrix */
665 memset(&gm, 0, sizeof(gm));
666 SetLastError(0xdeadbeef);
667 ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
668 ok(ret != GDI_ERROR, "GetGlyphOutlineA error %ld\n", GetLastError());
669 pt.x = width_orig; pt.y = 0;
670 LPtoDP(hdc, &pt, 1);
671 ok(gm.gmCellIncX == pt.x, "incX %d != %ld\n", gm.gmCellIncX, pt.x);
672 ok(gm.gmCellIncX == 20 * width_orig, "incX %d != %d\n", gm.gmCellIncX, 20 * width_orig);
673 ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
674 /* with a custom matrix */
675 memset(&gm, 0, sizeof(gm));
676 SetLastError(0xdeadbeef);
677 ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat2);
678 ok(ret != GDI_ERROR, "GetGlyphOutlineA error %ld\n", GetLastError());
679 pt.x = width_orig; pt.y = 0;
680 LPtoDP(hdc, &pt, 1);
681 ok(gm.gmCellIncX == pt.x/2, "incX %d != %ld\n", gm.gmCellIncX, pt.x/2);
682 ok(gm.gmCellIncX == 10 * width_orig, "incX %d != %d\n", gm.gmCellIncX, 10 * width_orig);
683 ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
684
685 SelectObject(hdc, old_hfont);
687 DeleteDC(hdc);
688}
689
691{
692 LOGFONTA *lf = (LOGFONTA *)lParam;
693
694 if (elf->lfHeight == lf->lfHeight && !strcmp(elf->lfFaceName, lf->lfFaceName))
695 {
696 *lf = *elf;
697 return 0; /* stop enumeration */
698 }
699 return 1; /* continue enumeration */
700}
701
702static BOOL is_CJK(void)
703{
705}
706
707#define FH_SCALE 0x80000000
709{
710 static const WORD skip_rtl[] = {LANG_ARABIC, LANG_HEBREW, 0};
711 static const struct font_data
712 {
713 const char face_name[LF_FACESIZE];
715 int ave_char_width, max_char_width, dpi;
716 BYTE first_char, last_char, def_char, break_char;
717 DWORD ansi_bitfield;
718 const WORD *skip_lang_id;
719 int scaled_height;
720 } fd[] =
721 {
722 { "MS Sans Serif", FW_NORMAL, FH_SCALE | 6, 11, 2, 2, 0, 5, 11, 96, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 | FS_LATIN2, skip_rtl, 13 },
723 { "MS Sans Serif", FW_NORMAL, FH_SCALE | 6, 11, 2, 2, 0, 5, 11, 96, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC, 0, 13 },
724 { "MS Sans Serif", FW_NORMAL, FH_SCALE | 8, 11, 2, 2, 0, 5, 11, 96, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 | FS_LATIN2, skip_rtl, 13 },
725 { "MS Sans Serif", FW_NORMAL, FH_SCALE | 8, 11, 2, 2, 0, 5, 11, 96, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC, 0, 13 },
726 { "MS Sans Serif", FW_NORMAL, FH_SCALE | 10, 11, 2, 2, 0, 5, 11, 96, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 | FS_LATIN2, skip_rtl, 13 },
727 { "MS Sans Serif", FW_NORMAL, FH_SCALE | 10, 11, 2, 2, 0, 5, 11, 96, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC, 0, 13 },
728 { "MS Sans Serif", FW_NORMAL, FH_SCALE | 14, 11, 2, 2, 0, 5, 11, 96, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 | FS_LATIN2, skip_rtl, 13 },
729 { "MS Sans Serif", FW_NORMAL, FH_SCALE | 14, 11, 2, 2, 0, 5, 11, 96, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC, 0, 13 },
730 { "MS Sans Serif", FW_NORMAL, FH_SCALE | 18, 13, 3, 3, 0, 7, 14, 96, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 | FS_LATIN2, skip_rtl, 16 },
731 { "MS Sans Serif", FW_NORMAL, FH_SCALE | 18, 13, 3, 3, 0, 7, 14, 96, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC, 0, 16 },
732
733 { "MS Sans Serif", FW_NORMAL, FH_SCALE | 6, 13, 3, 3, 0, 7, 14, 120, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 | FS_LATIN2, 0, 16 },
734 { "MS Sans Serif", FW_NORMAL, FH_SCALE | 6, 13, 3, 3, 0, 7, 14, 120, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC, 0, 16 },
735 { "MS Sans Serif", FW_NORMAL, FH_SCALE | 8, 13, 3, 3, 0, 7, 14, 120, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 | FS_LATIN2, 0, 16 },
736 { "MS Sans Serif", FW_NORMAL, FH_SCALE | 8, 13, 3, 3, 0, 7, 14, 120, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC, 0, 16 },
737 { "MS Sans Serif", FW_NORMAL, FH_SCALE | 10, 13, 3, 3, 0, 7, 14, 120, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 | FS_LATIN2, 0, 16 },
738 { "MS Sans Serif", FW_NORMAL, FH_SCALE | 10, 13, 3, 3, 0, 7, 14, 120, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC, 0, 16 },
739 { "MS Sans Serif", FW_NORMAL, FH_SCALE | 14, 13, 3, 3, 0, 7, 14, 120, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 | FS_LATIN2, 0, 16 },
740 { "MS Sans Serif", FW_NORMAL, FH_SCALE | 14, 13, 3, 3, 0, 7, 14, 120, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC, 0, 16 },
741 { "MS Sans Serif", FW_NORMAL, FH_SCALE | 18, 13, 3, 3, 0, 7, 14, 120, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 | FS_LATIN2, 0, 16 },
742 { "MS Sans Serif", FW_NORMAL, FH_SCALE | 18, 13, 3, 3, 0, 7, 14, 120, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC, 0, 16 },
743
744 { "MS Sans Serif", FW_NORMAL, 13, 11, 2, 2, 0, 5, 11, 96, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 | FS_LATIN2 },
745 { "MS Sans Serif", FW_NORMAL, 13, 11, 2, 2, 0, 5, 11, 96, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC },
746 { "MS Sans Serif", FW_NORMAL, 16, 13, 3, 3, 0, 7, 14, 96, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 | FS_LATIN2 },
747 { "MS Sans Serif", FW_NORMAL, 16, 13, 3, 3, 0, 7, 14, 96, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC },
748 { "MS Sans Serif", FW_NORMAL, 20, 16, 4, 4, 0, 8, 16, 96, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 },
749 { "MS Sans Serif", FW_NORMAL, 20, 16, 4, 4, 0, 8, 18, 96, 0x20, 0xff, 0x81, 0x20, FS_LATIN2 },
750 { "MS Sans Serif", FW_NORMAL, 20, 16, 4, 4, 0, 8, 16, 96, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC },
751 { "MS Sans Serif", FW_NORMAL, 24, 19, 5, 6, 0, 9, 19, 96, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 },
752 { "MS Sans Serif", FW_NORMAL, 24, 19, 5, 6, 0, 9, 24, 96, 0x20, 0xff, 0x81, 0x40, FS_LATIN2 },
753 { "MS Sans Serif", FW_NORMAL, 24, 19, 5, 6, 0, 9, 20, 96, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC },
754 { "MS Sans Serif", FW_NORMAL, 29, 23, 6, 5, 0, 12, 24, 96, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 },
755 { "MS Sans Serif", FW_NORMAL, 29, 23, 6, 6, 0, 12, 24, 96, 0x20, 0xff, 0x81, 0x20, FS_LATIN2 },
756 { "MS Sans Serif", FW_NORMAL, 29, 23, 6, 5, 0, 12, 25, 96, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC },
757 { "MS Sans Serif", FW_NORMAL, 37, 29, 8, 5, 0, 16, 32, 96, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 },
758 { "MS Sans Serif", FW_NORMAL, 37, 29, 8, 5, 0, 16, 32, 96, 0x20, 0xff, 0x81, 0x40, FS_LATIN2 },
759 { "MS Sans Serif", FW_NORMAL, 37, 29, 8, 5, 0, 16, 32, 96, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC },
760
761 { "MS Sans Serif", FW_NORMAL, 16, 13, 3, 3, 0, 7, 14, 120, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 | FS_LATIN2 },
762 { "MS Sans Serif", FW_NORMAL, 16, 13, 3, 3, 0, 7, 14, 120, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC },
763 { "MS Sans Serif", FW_NORMAL, 20, 16, 4, 4, 0, 8, 18, 120, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 | FS_LATIN2 },
764 { "MS Sans Serif", FW_NORMAL, 20, 16, 4, 4, 0, 8, 17, 120, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC },
765 { "MS Sans Serif", FW_NORMAL, 25, 20, 5, 5, 0, 10, 21, 120, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 | FS_LATIN2 },
766 { "MS Sans Serif", FW_NORMAL, 25, 20, 5, 5, 0, 10, 21, 120, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC },
767 { "MS Sans Serif", FW_NORMAL, 29, 23, 6, 6, 0, 12, 24, 120, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 | FS_LATIN2 },
768 { "MS Sans Serif", FW_NORMAL, 29, 23, 6, 5, 0, 12, 24, 120, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC },
769 { "MS Sans Serif", FW_NORMAL, 36, 29, 7, 6, 0, 15, 30, 120, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 | FS_LATIN2 },
770 { "MS Sans Serif", FW_NORMAL, 36, 29, 7, 6, 0, 15, 30, 120, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC },
771 { "MS Sans Serif", FW_NORMAL, 46, 37, 9, 6, 0, 20, 40, 120, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 | FS_LATIN2 },
772 { "MS Sans Serif", FW_NORMAL, 46, 37, 9, 6, 0, 20, 40, 120, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC },
773
774 { "MS Serif", FW_NORMAL, 10, 8, 2, 2, 0, 4, 8, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 },
775 { "MS Serif", FW_NORMAL, 10, 8, 2, 2, 0, 5, 8, 96, 0x20, 0xff, 0x80, 0x20, FS_CYRILLIC },
776 { "MS Serif", FW_NORMAL, 11, 9, 2, 2, 0, 5, 9, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
777 { "MS Serif", FW_NORMAL, 13, 11, 2, 2, 0, 5, 11, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 },
778 { "MS Serif", FW_NORMAL, 13, 11, 2, 2, 0, 5, 12, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN2 | FS_CYRILLIC },
779 { "MS Serif", FW_NORMAL, 16, 13, 3, 3, 0, 6, 14, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 },
780 { "MS Serif", FW_NORMAL, 16, 13, 3, 3, 0, 6, 16, 96, 0x20, 0xff, 0x80, 0x20, FS_CYRILLIC },
781 { "MS Serif", FW_NORMAL, 19, 15, 4, 3, 0, 8, 18, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 },
782 { "MS Serif", FW_NORMAL, 19, 15, 4, 3, 0, 8, 19, 96, 0x20, 0xff, 0x80, 0x20, FS_CYRILLIC },
783 { "MS Serif", FW_NORMAL, 21, 16, 5, 3, 0, 9, 17, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 },
784 { "MS Serif", FW_NORMAL, 21, 16, 5, 3, 0, 9, 22, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN2 },
785 { "MS Serif", FW_NORMAL, 21, 16, 5, 3, 0, 9, 23, 96, 0x20, 0xff, 0x80, 0x20, FS_CYRILLIC },
786 { "MS Serif", FW_NORMAL, 27, 21, 6, 3, 0, 12, 23, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 },
787 { "MS Serif", FW_NORMAL, 27, 21, 6, 3, 0, 12, 26, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN2 },
788 { "MS Serif", FW_NORMAL, 27, 21, 6, 3, 0, 12, 27, 96, 0x20, 0xff, 0x80, 0x20, FS_CYRILLIC },
789 { "MS Serif", FW_NORMAL, 35, 27, 8, 3, 0, 16, 33, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 },
790 { "MS Serif", FW_NORMAL, 35, 27, 8, 3, 0, 16, 34, 96, 0x20, 0xff, 0x80, 0x20, FS_CYRILLIC },
791
792 { "MS Serif", FW_NORMAL, 16, 13, 3, 3, 0, 6, 14, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_CYRILLIC },
793 { "MS Serif", FW_NORMAL, 16, 13, 3, 3, 0, 6, 13, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN2 },
794 { "MS Serif", FW_NORMAL, 20, 16, 4, 4, 0, 8, 18, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_CYRILLIC },
795 { "MS Serif", FW_NORMAL, 20, 16, 4, 4, 0, 8, 15, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN2 },
796 { "MS Serif", FW_NORMAL, 23, 18, 5, 3, 0, 10, 21, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_CYRILLIC },
797 { "MS Serif", FW_NORMAL, 23, 18, 5, 3, 0, 10, 19, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN2 },
798 { "MS Serif", FW_NORMAL, 27, 21, 6, 4, 0, 12, 23, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 },
799 { "MS Serif", FW_MEDIUM, 27, 22, 5, 2, 0, 12, 30, 120, 0x20, 0xff, 0x80, 0x20, FS_CYRILLIC },
800 { "MS Serif", FW_NORMAL, 33, 26, 7, 3, 0, 14, 30, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 },
801 { "MS Serif", FW_MEDIUM, 32, 25, 7, 2, 0, 14, 32, 120, 0x20, 0xff, 0x80, 0x20, FS_CYRILLIC },
802 { "MS Serif", FW_NORMAL, 43, 34, 9, 3, 0, 19, 39, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
803
804 { "Courier", FW_NORMAL, 13, 11, 2, 0, 0, 8, 8, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
805 { "Courier", FW_NORMAL, 16, 13, 3, 0, 0, 9, 9, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
806 { "Courier", FW_NORMAL, 20, 16, 4, 0, 0, 12, 12, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
807
808 { "Courier", FW_NORMAL, 16, 13, 3, 0, 0, 9, 9, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
809 { "Courier", FW_NORMAL, 20, 16, 4, 0, 0, 12, 12, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
810 { "Courier", FW_NORMAL, 25, 20, 5, 0, 0, 15, 15, 120, 0x20, 0xff, 0x40, 0x20, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
811
812 { "System", FW_BOLD, 16, 13, 3, 3, 0, 7, 14, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 },
813 { "System", FW_BOLD, 16, 13, 3, 3, 0, 7, 15, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN2 | FS_CYRILLIC },
814 { "System", FW_NORMAL, 18, 16, 2, 0, 2, 8, 16, 96, 0x20, 0xff, 0x80, 0x20, FS_JISJAPAN },
815
816 { "System", FW_BOLD, 20, 16, 4, 4, 0, 9, 14, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 },
817 { "System", FW_BOLD, 20, 16, 4, 4, 0, 9, 17, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN2 | FS_CYRILLIC },
818
819 { "Small Fonts", FW_NORMAL, 3, 2, 1, 0, 0, 1, 2, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 },
820 { "Small Fonts", FW_NORMAL, 3, 2, 1, 0, 0, 1, 8, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN2 | FS_CYRILLIC },
821 { "Small Fonts", FW_NORMAL, 3, 2, 1, 0, 0, 2, 4, 96, 0x20, 0xff, 0x80, 0x20, FS_JISJAPAN },
822 { "Small Fonts", FW_NORMAL, 5, 4, 1, 1, 0, 3, 4, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1, skip_rtl},
823 { "Small Fonts", FW_NORMAL, 5, 4, 1, 1, 0, 2, 8, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN2 | FS_CYRILLIC },
824 { "Small Fonts", FW_NORMAL, 5, 4, 1, 0, 0, 3, 6, 96, 0x20, 0xff, 0x80, 0x20, FS_JISJAPAN },
825 { "Small Fonts", FW_NORMAL, 6, 5, 1, 1, 0, 3, 13, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1, skip_rtl},
826 { "Small Fonts", FW_NORMAL, 6, 5, 1, 1, 0, 3, 8, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN2 | FS_CYRILLIC },
827 { "Small Fonts", FW_NORMAL, 6, 5, 1, 1, 0, 3, 8, 96, 0x00, 0xff, 0x60, 0x00, FS_ARABIC },
828 { "Small Fonts", FW_NORMAL, 6, 5, 1, 0, 0, 4, 8, 96, 0x20, 0xff, 0x80, 0x20, FS_JISJAPAN },
829 { "Small Fonts", FW_NORMAL, 8, 7, 1, 1, 0, 4, 7, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1, skip_rtl},
830 { "Small Fonts", FW_NORMAL, 8, 7, 1, 1, 0, 4, 8, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN2 | FS_CYRILLIC },
831 { "Small Fonts", FW_NORMAL, 8, 7, 1, 1, 0, 4, 8, 96, 0x00, 0xff, 0x60, 0x00, FS_ARABIC },
832 { "Small Fonts", FW_NORMAL, 8, 7, 1, 0, 0, 5, 10, 96, 0x20, 0xff, 0x80, 0x20, FS_JISJAPAN },
833 { "Small Fonts", FW_NORMAL, 10, 8, 2, 2, 0, 4, 8, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2, skip_rtl},
834 { "Small Fonts", FW_NORMAL, 10, 8, 2, 2, 0, 5, 8, 96, 0x20, 0xff, 0x80, 0x20, FS_CYRILLIC },
835 { "Small Fonts", FW_NORMAL, 10, 8, 2, 2, 0, 4, 9, 96, 0x00, 0xff, 0x60, 0x00, FS_ARABIC },
836 { "Small Fonts", FW_NORMAL, 10, 8, 2, 0, 0, 6, 12, 96, 0x20, 0xff, 0x80, 0x20, FS_JISJAPAN },
837 { "Small Fonts", FW_NORMAL, 11, 9, 2, 2, 0, 5, 9, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC, skip_rtl},
838 { "Small Fonts", FW_NORMAL, 11, 9, 2, 2, 0, 4, 10, 96, 0x00, 0xff, 0x60, 0x00, FS_ARABIC },
839 { "Small Fonts", FW_NORMAL, 11, 9, 2, 0, 0, 7, 14, 96, 0x20, 0xff, 0x80, 0x20, FS_JISJAPAN },
840
841 { "Small Fonts", FW_NORMAL, 3, 2, 1, 0, 0, 1, 2, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_JISJAPAN },
842 { "Small Fonts", FW_NORMAL, 3, 2, 1, 0, 0, 1, 8, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN2 | FS_CYRILLIC },
843 { "Small Fonts", FW_NORMAL, 6, 5, 1, 1, 0, 3, 5, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_JISJAPAN },
844 { "Small Fonts", FW_NORMAL, 6, 5, 1, 1, 0, 3, 8, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN2 | FS_CYRILLIC },
845 { "Small Fonts", FW_NORMAL, 8, 7, 1, 1, 0, 4, 7, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_JISJAPAN },
846 { "Small Fonts", FW_NORMAL, 8, 7, 1, 1, 0, 4, 8, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN2 | FS_CYRILLIC },
847 { "Small Fonts", FW_NORMAL, 10, 8, 2, 2, 0, 5, 9, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 | FS_JISJAPAN },
848 { "Small Fonts", FW_NORMAL, 10, 8, 2, 2, 0, 5, 8, 120, 0x20, 0xff, 0x80, 0x20, FS_CYRILLIC },
849 { "Small Fonts", FW_NORMAL, 12, 10, 2, 2, 0, 5, 10, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 | FS_JISJAPAN },
850 { "Small Fonts", FW_NORMAL, 12, 10, 2, 2, 0, 6, 10, 120, 0x20, 0xff, 0x80, 0x20, FS_CYRILLIC },
851 { "Small Fonts", FW_NORMAL, 13, 11, 2, 2, 0, 6, 12, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 | FS_JISJAPAN },
852 { "Small Fonts", FW_NORMAL, 13, 11, 2, 2, 0, 6, 11, 120, 0x20, 0xff, 0x80, 0x20, FS_CYRILLIC },
853
854 { "Fixedsys", FW_NORMAL, 15, 12, 3, 3, 0, 8, 8, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 },
855 { "Fixedsys", FW_NORMAL, 16, 12, 4, 3, 0, 8, 8, 96, 0x20, 0xff, 0x80, 0x20, FS_CYRILLIC },
856 { "FixedSys", FW_NORMAL, 18, 16, 2, 0, 0, 8, 16, 96, 0x20, 0xff, 0xa0, 0x20, FS_JISJAPAN },
857
858 { "Fixedsys", FW_NORMAL, 20, 16, 4, 2, 0, 10, 10, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC }
859
860 /* FIXME: add "Terminal" */
861 };
862 static const int font_log_pixels[] = { 96, 120 };
863 HDC hdc;
864 LOGFONTA lf;
865 HFONT hfont, old_hfont;
867 INT ret, i, expected_cs, screen_log_pixels, diff, font_res;
868 char face_name[LF_FACESIZE];
869 CHARSETINFO csi;
870
871 trace("system language id %04x\n", system_lang_id);
872
873 expected_cs = GetACP();
874 if (!TranslateCharsetInfo(ULongToPtr(expected_cs), &csi, TCI_SRCCODEPAGE))
875 {
876 skip("TranslateCharsetInfo failed for code page %d\n", expected_cs);
877 return;
878 }
879 expected_cs = csi.ciCharset;
880 trace("ACP %d -> charset %d\n", GetACP(), expected_cs);
881
883 ok(hdc != NULL, "failed to create hdc\n");
884
885 trace("logpixelsX %d, logpixelsY %d\n", GetDeviceCaps(hdc, LOGPIXELSX),
887
888 screen_log_pixels = GetDeviceCaps(hdc, LOGPIXELSY);
889 diff = 32768;
890 font_res = 0;
891 for (i = 0; i < ARRAY_SIZE(font_log_pixels); i++)
892 {
893 int new_diff = abs(font_log_pixels[i] - screen_log_pixels);
894 if (new_diff < diff)
895 {
896 diff = new_diff;
897 font_res = font_log_pixels[i];
898 }
899 }
900 trace("best font resolution is %d\n", font_res);
901
902 for (i = 0; i < ARRAY_SIZE(fd); i++)
903 {
904 int bit, height;
905
906 memset(&lf, 0, sizeof(lf));
907
908 height = fd[i].height & ~FH_SCALE;
909 lf.lfHeight = height;
910 strcpy(lf.lfFaceName, fd[i].face_name);
911
912 for(bit = 0; bit < 32; bit++)
913 {
914 GLYPHMETRICS gm;
915 DWORD fs[2];
916 BOOL bRet;
917
918 fs[0] = 1L << bit;
919 fs[1] = 0;
920 if((fd[i].ansi_bitfield & fs[0]) == 0) continue;
921 if(!TranslateCharsetInfo( fs, &csi, TCI_SRCFONTSIG )) continue;
922
923 lf.lfCharSet = csi.ciCharset;
925 if (fd[i].height & FH_SCALE)
926 ok(ret, "scaled font height %d should not be enumerated\n", height);
927 else
928 {
929 if (font_res == fd[i].dpi && lf.lfCharSet == expected_cs)
930 {
931 todo_wine_if (ret) /* FIXME: Remove once Wine is fixed */
932 ok(!ret, "%s height %ld charset %d dpi %d should be enumerated\n", lf.lfFaceName, lf.lfHeight, lf.lfCharSet, fd[i].dpi);
933 }
934 }
935 if (ret && !(fd[i].height & FH_SCALE))
936 continue;
937
938 hfont = create_font(lf.lfFaceName, &lf);
939 old_hfont = SelectObject(hdc, hfont);
940
941 SetLastError(0xdeadbeef);
942 ret = GetTextFaceA(hdc, sizeof(face_name), face_name);
943 ok(ret, "GetTextFace error %lu\n", GetLastError());
944
945 if (strcmp(face_name, fd[i].face_name) != 0)
946 {
947 ok(ret != ANSI_CHARSET, "font charset should not be ANSI_CHARSET\n");
948 ok(ret != expected_cs, "font charset %d should not be %d\n", ret, expected_cs);
949 SelectObject(hdc, old_hfont);
951 continue;
952 }
953
954 memset(&gm, 0, sizeof(gm));
955 SetLastError(0xdeadbeef);
956 ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
958 ok(ret == GDI_ERROR, "GetGlyphOutline should fail for a bitmap font\n");
959 ret = GetLastError();
960 ok(ret == ERROR_CAN_NOT_COMPLETE || ret == 0xdeadbeef /* Win10 */, "Unexpected error %d.\n", ret);
961
962 bRet = GetTextMetricsA(hdc, &tm);
963 ok(bRet, "GetTextMetrics error %ld\n", GetLastError());
964
965 SetLastError(0xdeadbeef);
967 if ((is_CJK() || expected_cs == 254) && lf.lfCharSet == ANSI_CHARSET)
968 ok(ret == ANSI_CHARSET, "got charset %d, expected ANSI_CHARSETd\n", ret);
969 else
970 ok(ret == expected_cs, "got charset %d, expected %d\n", ret, expected_cs);
971
972 if(fd[i].dpi == tm.tmDigitizedAspectX)
973 {
974 int skipme = 0;
975 if (fd[i].skip_lang_id)
976 {
977 int si = 0;
978 skipme = 0;
979 while(!skipme && fd[i].skip_lang_id[si])
980 if (fd[i].skip_lang_id[si++] == system_lang_id)
981 skipme = 1;
982 }
983 if (!skipme)
984 {
985 ok(tm.tmWeight == fd[i].weight, "%s(%d): tm.tmWeight %ld != %d\n", fd[i].face_name, height, tm.tmWeight, fd[i].weight);
986 if (fd[i].height & FH_SCALE)
987 ok(tm.tmHeight == fd[i].scaled_height, "%s(%d): tm.tmHeight %ld != %d\n", fd[i].face_name, height, tm.tmHeight, fd[i].scaled_height);
988 else
989 ok(tm.tmHeight == fd[i].height, "%s(%d): tm.tmHeight %ld != %d\n", fd[i].face_name, fd[i].height, tm.tmHeight, fd[i].height);
990 ok(tm.tmAscent == fd[i].ascent, "%s(%d): tm.tmAscent %ld != %d\n", fd[i].face_name, height, tm.tmAscent, fd[i].ascent);
991 ok(tm.tmDescent == fd[i].descent, "%s(%d): tm.tmDescent %ld != %d\n", fd[i].face_name, height, tm.tmDescent, fd[i].descent);
992 ok(tm.tmInternalLeading == fd[i].int_leading, "%s(%d): tm.tmInternalLeading %ld != %d\n", fd[i].face_name, height, tm.tmInternalLeading, fd[i].int_leading);
993 ok(tm.tmExternalLeading == fd[i].ext_leading, "%s(%d): tm.tmExternalLeading %ld != %d\n", fd[i].face_name, height, tm.tmExternalLeading, fd[i].ext_leading);
994 ok(tm.tmAveCharWidth == fd[i].ave_char_width, "%s(%d): tm.tmAveCharWidth %ld != %d\n", fd[i].face_name, height, tm.tmAveCharWidth, fd[i].ave_char_width);
995 ok(tm.tmFirstChar == fd[i].first_char, "%s(%d): tm.tmFirstChar = %02x\n", fd[i].face_name, height, tm.tmFirstChar);
996 ok(tm.tmLastChar == fd[i].last_char, "%s(%d): tm.tmLastChar = %02x\n", fd[i].face_name, height, tm.tmLastChar);
997 /* Substitutions like MS Sans Serif,0=MS Sans Serif,204
998 make default char test fail */
999 if (tm.tmCharSet == lf.lfCharSet)
1000 ok(tm.tmDefaultChar == fd[i].def_char, "%s(%d): tm.tmDefaultChar = %02x\n", fd[i].face_name, height, tm.tmDefaultChar);
1001 ok(tm.tmBreakChar == fd[i].break_char, "%s(%d): tm.tmBreakChar = %02x\n", fd[i].face_name, height, tm.tmBreakChar);
1002 ok(tm.tmCharSet == expected_cs || tm.tmCharSet == ANSI_CHARSET, "%s(%d): tm.tmCharSet %d != %d\n", fd[i].face_name, height, tm.tmCharSet, expected_cs);
1003
1004 /* Don't run the max char width test on System/ANSI_CHARSET. We have extra characters in our font
1005 that make the max width bigger */
1006 if ((strcmp(lf.lfFaceName, "System") || lf.lfCharSet != ANSI_CHARSET) && tm.tmDigitizedAspectX == 96)
1007 ok(tm.tmMaxCharWidth == fd[i].max_char_width, "%s(%d): tm.tmMaxCharWidth %ld != %d\n", fd[i].face_name, height, tm.tmMaxCharWidth, fd[i].max_char_width);
1008 }
1009 else
1010 skip("Skipping font metrics test for system langid 0x%x\n",
1012 }
1013 SelectObject(hdc, old_hfont);
1015 }
1016 }
1017
1018 DeleteDC(hdc);
1019}
1020
1022{
1023 HDC hdc;
1025 LONG ret;
1026 SIZE size;
1027 LONG avgwidth, height;
1028 static const char szAlphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
1029
1030 if (!pGdiGetCharDimensions)
1031 {
1032 win_skip("GdiGetCharDimensions not available on this platform\n");
1033 return;
1034 }
1035
1037
1038 GetTextExtentPointA(hdc, szAlphabet, strlen(szAlphabet), &size);
1039 avgwidth = ((size.cx / 26) + 1) / 2;
1040
1041 ret = pGdiGetCharDimensions(hdc, &tm, &height);
1042 ok(ret == avgwidth, "GdiGetCharDimensions should have returned width of %ld instead of %ld\n", avgwidth, ret);
1043 ok(height == tm.tmHeight, "GdiGetCharDimensions should have set height to %ld instead of %ld\n", tm.tmHeight, height);
1044
1045 ret = pGdiGetCharDimensions(hdc, &tm, NULL);
1046 ok(ret == avgwidth, "GdiGetCharDimensions should have returned width of %ld instead of %ld\n", avgwidth, ret);
1047
1048 ret = pGdiGetCharDimensions(hdc, NULL, NULL);
1049 ok(ret == avgwidth, "GdiGetCharDimensions should have returned width of %ld instead of %ld\n", avgwidth, ret);
1050
1051 height = 0;
1052 ret = pGdiGetCharDimensions(hdc, NULL, &height);
1053 ok(ret == avgwidth, "GdiGetCharDimensions should have returned width of %ld instead of %ld\n", avgwidth, ret);
1054 ok(height == size.cy, "GdiGetCharDimensions should have set height to %ld instead of %ld\n", size.cy, height);
1055
1056 DeleteDC(hdc);
1057}
1058
1059static int CALLBACK create_font_proc(const LOGFONTA *lpelfe,
1060 const TEXTMETRICA *lpntme,
1061 DWORD FontType, LPARAM lParam)
1062{
1063 if (FontType & TRUETYPE_FONTTYPE)
1064 {
1065 HFONT hfont;
1066
1067 hfont = CreateFontIndirectA(lpelfe);
1068 if (hfont)
1069 {
1070 *(HFONT *)lParam = hfont;
1071 return 0;
1072 }
1073 }
1074
1075 return 1;
1076}
1077
1078static void ABCWidths_helper(const char* description, HDC hdc, WORD *glyphs, const ABC *base_abci, const ABC *base_abcw, const ABCFLOAT *base_abcf)
1079{
1080 ABC abc[1];
1081 ABCFLOAT abcf[1];
1082 BOOL ret = FALSE;
1083
1084 ret = GetCharABCWidthsI(hdc, 0, 1, glyphs, abc);
1085 ok(ret, "%s: GetCharABCWidthsI should have succeeded\n", description);
1086 ok ((INT)abc->abcB > 0, "%s: abcB should be positive\n", description);
1087 ok(abc->abcA * base_abci->abcA >= 0, "%s: abcA's sign should be unchanged\n", description);
1088 ok(abc->abcC * base_abci->abcC >= 0, "%s: abcC's sign should be unchanged\n", description);
1089
1090 ret = GetCharABCWidthsI(hdc, glyphs[0], 1, NULL, abc);
1091 ok(ret, "%s: GetCharABCWidthsI should have succeeded\n", description);
1092 ok ((INT)abc->abcB > 0, "%s: abcB should be positive\n", description);
1093 ok(abc->abcA * base_abci->abcA >= 0, "%s: abcA's sign should be unchanged\n", description);
1094 ok(abc->abcC * base_abci->abcC >= 0, "%s: abcC's sign should be unchanged\n", description);
1095
1096 ret = GetCharABCWidthsW(hdc, 'i', 'i', abc);
1097 ok(ret, "%s: GetCharABCWidthsW should have succeeded\n", description);
1098 ok ((INT)abc->abcB > 0, "%s: abcB should be positive\n", description);
1099 ok(abc->abcA * base_abcw->abcA >= 0, "%s: abcA's sign should be unchanged\n", description);
1100 ok(abc->abcC * base_abcw->abcC >= 0, "%s: abcC's sign should be unchanged\n", description);
1101
1102 ret = GetCharABCWidthsFloatW(hdc, 'i', 'i', abcf);
1103 ok(ret, "%s: GetCharABCWidthsFloatW should have succeeded\n", description);
1104 ok (abcf->abcfB > 0.0, "%s: abcfB should be positive\n", description);
1105 ok(abcf->abcfA * base_abcf->abcfA >= 0.0, "%s: abcfA's sign should be unchanged\n", description);
1106 ok(abcf->abcfC * base_abcf->abcfC >= 0.0, "%s: abcfC's sign should be unchanged\n", description);
1107}
1108
1109static void test_GetCharABCWidths(void)
1110{
1111 BOOL ret;
1112 HDC hdc;
1113 LOGFONTA lf;
1114 HFONT hfont;
1115 ABC abc[1];
1116 ABC abcw[1];
1117 ABCFLOAT abcf[1];
1118 WORD glyphs[1];
1119 DWORD nb;
1120 HWND hwnd;
1121 static const struct
1122 {
1123 UINT first;
1124 UINT last;
1125 } range[] =
1126 {
1127 {0xff, 0xff},
1128 {0x100, 0x100},
1129 {0xff, 0x100},
1130 {0x1ff, 0xff00},
1131 {0xffff, 0xffff},
1132 {0x10000, 0x10000},
1133 {0xffff, 0x10000},
1134 {0xffffff, 0xffffff},
1135 {0x1000000, 0x1000000},
1136 {0xffffff, 0x1000000},
1137 {0xffffffff, 0xffffffff},
1138 {0x00, 0xff}
1139 };
1140 static const struct
1141 {
1142 UINT cs;
1143 UINT a;
1144 UINT w;
1146 } c[] =
1147 {
1148 {ANSI_CHARSET, 0x30, 0x30,
1150 {SHIFTJIS_CHARSET, 0x82a0, 0x3042,
1152 {HANGEUL_CHARSET, 0x8141, 0xac02,
1154 {GB2312_CHARSET, 0x8141, 0x4e04,
1156 {CHINESEBIG5_CHARSET, 0xa142, 0x3001,
1158 };
1159 UINT i;
1160
1161 memset(&lf, 0, sizeof(lf));
1162 strcpy(lf.lfFaceName, "System");
1163 lf.lfHeight = 20;
1164
1166 hdc = GetDC(0);
1168
1169 nb = GetGlyphIndicesW(hdc, L"i", 1, glyphs, 0);
1170 ok(nb == 1, "GetGlyphIndicesW should have returned 1\n");
1171
1172 ret = GetCharABCWidthsI(NULL, 0, 1, glyphs, abc);
1173 ok(!ret, "GetCharABCWidthsI should have failed\n");
1174
1175 ret = GetCharABCWidthsI(hdc, 0, 1, glyphs, NULL);
1176 ok(!ret, "GetCharABCWidthsI should have failed\n");
1177
1178 ret = GetCharABCWidthsI(hdc, 0, 1, glyphs, abc);
1179 ok(ret, "GetCharABCWidthsI should have succeeded\n");
1180
1181 ret = GetCharABCWidthsW(NULL, 'a', 'a', abc);
1182 ok(!ret, "GetCharABCWidthsW should have failed\n");
1183
1184 ret = GetCharABCWidthsW(hdc, 'a', 'a', NULL);
1185 ok(!ret, "GetCharABCWidthsW should have failed\n");
1186
1187 ret = GetCharABCWidthsW(hdc, 'a', 'a', abc);
1188 ok(ret || broken(!ret) /* < win10 */, "GetCharABCWidthsW should have succeeded\n");
1189
1190 ret = GetCharABCWidthsFloatW(NULL, 'a', 'a', abcf);
1191 ok(!ret, "GetCharABCWidthsFloatW should have failed\n");
1192
1193 ret = GetCharABCWidthsFloatW(hdc, 'a', 'a', NULL);
1194 ok(!ret, "GetCharABCWidthsFloatW should have failed\n");
1195
1196 ret = GetCharABCWidthsFloatW(hdc, 'a', 'a', abcf);
1197 ok(ret, "GetCharABCWidthsFloatW should have succeeded\n");
1198
1201
1202 for (i = 0; i < ARRAY_SIZE(c); ++i)
1203 {
1204 ABC a[2], w[2];
1205 ABC full[256];
1206 UINT code = 0x41, j;
1207
1208 lf.lfFaceName[0] = '\0';
1209 lf.lfCharSet = c[i].cs;
1210 lf.lfPitchAndFamily = 0;
1212 {
1213 skip("TrueType font for charset %u is not installed\n", c[i].cs);
1214 continue;
1215 }
1216
1217 memset(a, 0, sizeof a);
1218 memset(w, 0, sizeof w);
1220 ok(GetCharABCWidthsA(hdc, c[i].a, c[i].a + 1, a) && GetCharABCWidthsW(hdc, c[i].w, c[i].w + 1, w)
1221 && !memcmp(a, w, sizeof(a)),
1222 "GetCharABCWidthsA and GetCharABCWidthsW should return same widths. charset = %u\n", c[i].cs);
1223
1224 memset(a, 0xbb, sizeof a);
1226 ok(ret, "GetCharABCWidthsA should have succeeded\n");
1227 memset(full, 0xcc, sizeof full);
1228 ret = GetCharABCWidthsA(hdc, 0x00, code, full);
1229 ok(ret, "GetCharABCWidthsA should have succeeded\n");
1230 ok(memcmp(&a[0], &full[code], sizeof(ABC)) == 0,
1231 "GetCharABCWidthsA info should match. codepage = %u\n", c[i].cs);
1232
1233 for (j = 0; j < ARRAY_SIZE(range); ++j)
1234 {
1235 memset(full, 0xdd, sizeof full);
1237 ok(ret == c[i].r[j], "GetCharABCWidthsA %x - %x should have %s\n",
1238 range[j].first, range[j].last, c[i].r[j] ? "succeeded" : "failed");
1239 if (ret)
1240 {
1241 UINT last = range[j].last - range[j].first;
1243 ok(ret && memcmp(&full[last], &a[0], sizeof(ABC)) == 0,
1244 "GetCharABCWidthsA %x should match. codepage = %u\n",
1245 range[j].last, c[i].cs);
1246 }
1247 }
1248
1251 }
1252
1253 memset(&lf, 0, sizeof(lf));
1254 strcpy(lf.lfFaceName, "Tahoma");
1255 lf.lfHeight = 200;
1257
1258 /* test empty glyph's metrics */
1260 ret = GetCharABCWidthsFloatW(hdc, ' ', ' ', abcf);
1261 ok(ret, "GetCharABCWidthsFloatW should have succeeded\n");
1262 ok(abcf[0].abcfB == 1.0, "got %f\n", abcf[0].abcfB);
1263 ret = GetCharABCWidthsW(hdc, ' ', ' ', abcw);
1264 ok(ret, "GetCharABCWidthsW should have succeeded\n");
1265 ok(abcw[0].abcB == 1, "got %u\n", abcw[0].abcB);
1266
1267 /* 1) prepare unrotated font metrics */
1268 ret = GetCharABCWidthsW(hdc, 'a', 'a', abcw);
1269 ok(ret, "GetCharABCWidthsW should have succeeded\n");
1271
1272 /* 2) get rotated font metrics */
1273 lf.lfEscapement = lf.lfOrientation = 900;
1276 ret = GetCharABCWidthsW(hdc, 'a', 'a', abc);
1277 ok(ret, "GetCharABCWidthsW should have succeeded\n");
1278
1279 /* 3) compare ABC results */
1280 ok(match_off_by_1(abcw[0].abcA, abc[0].abcA, FALSE),
1281 "got %d, expected %d (A)\n", abc[0].abcA, abcw[0].abcA);
1282 ok(match_off_by_1(abcw[0].abcB, abc[0].abcB, FALSE),
1283 "got %d, expected %d (B)\n", abc[0].abcB, abcw[0].abcB);
1284 ok(match_off_by_1(abcw[0].abcC, abc[0].abcC, FALSE),
1285 "got %d, expected %d (C)\n", abc[0].abcC, abcw[0].abcC);
1286
1288
1289 /* test abcA == gmptGlyphOrigin.x && abcB == gmBlackBoxX
1290 in various widths. */
1291 for (i = 1; i <= 2; i++)
1292 {
1293 UINT j;
1294 UINT code;
1295
1296 memset(&lf, 0, sizeof(lf));
1297 lf.lfHeight = 20;
1298 if (i == 1)
1299 {
1300 strcpy(lf.lfFaceName, "Tahoma");
1301 code = 'a';
1302 }
1303 else
1304 {
1305 strcpy(lf.lfFaceName, "Times New Roman");
1306 lf.lfItalic = TRUE;
1307 code = 'f';
1308 }
1310 {
1311 skip("%s is not installed\n", lf.lfFaceName);
1312 continue;
1313 }
1314 for (j = 1; j <= 80; j++)
1315 {
1316 GLYPHMETRICS gm;
1317
1318 lf.lfWidth = j;
1321
1322 nb = GetGlyphOutlineA(hdc, code, GGO_METRICS, &gm, 0, NULL, &mat);
1323 ok(nb, "GetGlyphOutlineA should have succeeded at width %d\n", i);
1324
1325 ret = GetCharABCWidthsA(hdc, code, code, abc);
1326 ok(ret, "GetCharABCWidthsA should have succeeded at width %d\n", i);
1327
1328 ok(abc[0].abcA == gm.gmptGlyphOrigin.x,
1329 "abcA(%d) and gmptGlyphOrigin.x(%ld) values are different at width %d\n",
1330 abc[0].abcA, gm.gmptGlyphOrigin.x, i);
1331 ok(abc[0].abcB == gm.gmBlackBoxX,
1332 "abcB(%d) and gmBlackBoxX(%d) values are different at width %d\n",
1333 abc[0].abcB, gm.gmBlackBoxX, i);
1335 }
1336 }
1337 ReleaseDC(NULL, hdc);
1338
1339 /* ABC sign test for a variety of transforms */
1340 memset(&lf, 0, sizeof(lf));
1341 strcpy(lf.lfFaceName, "Tahoma");
1342 lf.lfHeight = 20;
1344 hwnd = CreateWindowExA(0, "static", "", WS_POPUP, 0,0,100,100,
1345 0, 0, 0, NULL);
1346 hdc = GetDC(hwnd);
1349
1350 nb = GetGlyphIndicesW(hdc, L"i", 1, glyphs, 0);
1351 ok(nb == 1, "GetGlyphIndicesW should have returned 1\n");
1352
1353 ret = GetCharABCWidthsI(hdc, 0, 1, glyphs, abc);
1354 ok(ret, "GetCharABCWidthsI should have succeeded\n");
1355 ret = GetCharABCWidthsW(hdc, 'i', 'i', abcw);
1356 ok(ret, "GetCharABCWidthsW should have succeeded\n");
1357 ret = GetCharABCWidthsFloatW(hdc, 'i', 'i', abcf);
1358 ok(ret, "GetCharABCWidthsFloatW should have succeeded\n");
1359
1360 ABCWidths_helper("LTR", hdc, glyphs, abc, abcw, abcf);
1361 SetWindowExtEx(hdc, -1, -1, NULL);
1363 ABCWidths_helper("LTR -1 compatible", hdc, glyphs, abc, abcw, abcf);
1365 ABCWidths_helper("LTR -1 advanced", hdc, glyphs, abc, abcw, abcf);
1366 SetWindowExtEx(hdc, 1, 1, NULL);
1368 ABCWidths_helper("LTR 1 compatible", hdc, glyphs, abc, abcw, abcf);
1370 ABCWidths_helper("LTR 1 advanced", hdc, glyphs, abc, abcw, abcf);
1371
1372 ReleaseDC(hwnd, hdc);
1374
1375 /* RTL layout */
1376 hwnd = CreateWindowExA(WS_EX_LAYOUTRTL, "static", "", WS_POPUP, 0,0,100,100,
1377 0, 0, 0, NULL);
1378 hdc = GetDC(hwnd);
1381
1382 ABCWidths_helper("RTL", hdc, glyphs, abc, abcw, abcf);
1383 SetWindowExtEx(hdc, -1, -1, NULL);
1385 ABCWidths_helper("RTL -1 compatible", hdc, glyphs, abc, abcw, abcf);
1387 ABCWidths_helper("RTL -1 advanced", hdc, glyphs, abc, abcw, abcf);
1388 SetWindowExtEx(hdc, 1, 1, NULL);
1390 ABCWidths_helper("RTL 1 compatible", hdc, glyphs, abc, abcw, abcf);
1392 ABCWidths_helper("RTL 1 advanced", hdc, glyphs, abc, abcw, abcf);
1393
1394 ReleaseDC(hwnd, hdc);
1397}
1398
1399static void test_text_extents(void)
1400{
1401 static const WCHAR wt[] = L"One\ntwo 3";
1402 LPINT extents;
1403 INT i, len, fit1, fit2, extents2[3];
1404 LOGFONTA lf;
1406 HDC hdc;
1407 HFONT hfont;
1408 SIZE sz;
1409 SIZE sz1, sz2;
1410 BOOL ret;
1411
1412 memset(&lf, 0, sizeof(lf));
1413 strcpy(lf.lfFaceName, "Arial");
1414 lf.lfHeight = 20;
1415
1417 hdc = GetDC(0);
1420 ret = GetTextExtentPointA(hdc, "o", 1, &sz);
1421 ok(ret, "got %d\n", ret);
1422 ok(sz.cy == tm.tmHeight, "cy %ld tmHeight %ld\n", sz.cy, tm.tmHeight);
1423
1424 memset(&sz, 0xcc, sizeof(sz));
1425 ret = GetTextExtentPointA(hdc, "o", 0, &sz);
1426 ok(ret, "got %d\n", ret);
1427 ok(sz.cx == 0 && sz.cy == 0, "cx %ld, cy %ld\n", sz.cx, sz.cy);
1428
1429 memset(&sz, 0xcc, sizeof(sz));
1430 ret = GetTextExtentPointA(hdc, "", 0, &sz);
1431 ok(ret, "got %d\n", ret);
1432 ok(sz.cx == 0 && sz.cy == 0, "cx %ld, cy %ld\n", sz.cx, sz.cy);
1433
1434 memset(&sz, 0xcc, sizeof(sz));
1435 ret = GetTextExtentPointW(hdc, wt, 0, &sz);
1436 ok(ret, "got %d\n", ret);
1437 ok(sz.cx == 0 && sz.cy == 0, "cx %ld, cy %ld\n", sz.cx, sz.cy);
1438
1439 memset(&sz, 0xcc, sizeof(sz));
1440 ret = GetTextExtentPointW(hdc, L"", 0, &sz);
1441 ok(ret, "got %d\n", ret);
1442 ok(sz.cx == 0 && sz.cy == 0, "cx %ld, cy %ld\n", sz.cx, sz.cy);
1443
1444 len = lstrlenW(wt);
1445 extents = calloc(len, sizeof extents[0]);
1446 extents[0] = 1; /* So that the increasing sequence test will fail
1447 if the extents array is untouched. */
1448 GetTextExtentExPointW(hdc, wt, len, 32767, &fit1, extents, &sz1);
1449 GetTextExtentPointW(hdc, wt, len, &sz2);
1450 ok(sz1.cy == sz2.cy,
1451 "cy from GetTextExtentExPointW (%ld) and GetTextExtentPointW (%ld) differ\n", sz1.cy, sz2.cy);
1452 /* Because of the '\n' in the string GetTextExtentExPoint and
1453 GetTextExtentPoint return different widths under Win2k, but
1454 under WinXP they return the same width. So we don't test that
1455 here. */
1456
1457 for (i = 1; i < len; ++i)
1458 ok(extents[i-1] <= extents[i],
1459 "GetTextExtentExPointW generated a non-increasing sequence of partial extents (at position %d)\n",
1460 i);
1461 ok(extents[len-1] == sz1.cx, "GetTextExtentExPointW extents and size don't match\n");
1462 ok(0 <= fit1 && fit1 <= len, "GetTextExtentExPointW generated illegal value %d for fit\n", fit1);
1463 ok(0 < fit1, "GetTextExtentExPointW says we can't even fit one letter in 32767 logical units\n");
1464 GetTextExtentExPointW(hdc, wt, len, extents[2], &fit2, NULL, &sz2);
1465 ok(sz1.cx == sz2.cx && sz1.cy == sz2.cy, "GetTextExtentExPointW returned different sizes for the same string\n");
1466 ok(fit2 == 3, "GetTextExtentExPointW extents isn't consistent with fit\n");
1467 GetTextExtentExPointW(hdc, wt, len, extents[2]-1, &fit2, NULL, &sz2);
1468 ok(fit2 == 2, "GetTextExtentExPointW extents isn't consistent with fit\n");
1469 GetTextExtentExPointW(hdc, wt, 2, 0, NULL, extents + 2, &sz2);
1470 ok(extents[0] == extents[2] && extents[1] == extents[3],
1471 "GetTextExtentExPointW with lpnFit == NULL returns incorrect results\n");
1472 GetTextExtentExPointW(hdc, wt, 2, 0, NULL, NULL, &sz1);
1473 ok(sz1.cx == sz2.cx && sz1.cy == sz2.cy,
1474 "GetTextExtentExPointW with lpnFit and alpDx both NULL returns incorrect results\n");
1475
1476 /* extents functions fail with -ve counts (the interesting case being -1) */
1477 ret = GetTextExtentPointA(hdc, "o", -1, &sz);
1478 ok(ret == FALSE, "got %d\n", ret);
1479 ret = GetTextExtentExPointA(hdc, "o", -1, 0, NULL, NULL, &sz);
1480 ok(ret == FALSE, "got %d\n", ret);
1481 ret = GetTextExtentExPointW(hdc, wt, -1, 0, NULL, NULL, &sz1);
1482 ok(ret == FALSE, "got %d\n", ret);
1483
1484 /* max_extent = 0 succeeds and returns zero */
1485 fit1 = fit2 = -215;
1486 ret = GetTextExtentExPointA(hdc, NULL, 0, 0, &fit1, NULL, &sz);
1487 ok(ret == TRUE, "got %d\n", ret);
1488 ok(fit1 == 0, "fit = %d\n", fit1);
1489 ret = GetTextExtentExPointW(hdc, NULL, 0, 0, &fit2, NULL, &sz1);
1490 ok(ret == TRUE, "got %d\n", ret);
1491 ok(fit2 == 0, "fit = %d\n", fit2);
1492
1493 /* max_extent = -1 is interpreted as a very large width that will
1494 * definitely fit our three characters */
1495 fit1 = fit2 = -215;
1496 ret = GetTextExtentExPointA(hdc, "One", 3, -1, &fit1, NULL, &sz);
1497 ok(ret == TRUE, "got %d\n", ret);
1498 ok(fit1 == 3, "fit = %d\n", fit1);
1499 ret = GetTextExtentExPointW(hdc, wt, 3, -1, &fit2, NULL, &sz);
1500 ok(ret == TRUE, "got %d\n", ret);
1501 ok(fit2 == 3, "fit = %d\n", fit2);
1502
1503 /* max_extent = -2 is interpreted similarly, but the Ansi version
1504 * rejects it while the Unicode one accepts it */
1505 fit1 = fit2 = -215;
1506 ret = GetTextExtentExPointA(hdc, "One", 3, -2, &fit1, NULL, &sz);
1507 ok(ret == FALSE, "got %d\n", ret);
1508 ok(fit1 == -215, "fit = %d\n", fit1);
1509 ret = GetTextExtentExPointW(hdc, wt, 3, -2, &fit2, NULL, &sz);
1510 ok(ret == TRUE, "got %d\n", ret);
1511 ok(fit2 == 3, "fit = %d\n", fit2);
1512
1515
1516 /* non-MM_TEXT mapping mode */
1517 lf.lfHeight = 2000;
1520
1522 ret = GetTextExtentExPointW(hdc, wt, 3, 0, NULL, extents, &sz);
1523 ok(ret, "got %d\n", ret);
1524 ok(sz.cx == extents[2], "got %ld vs %d\n", sz.cx, extents[2]);
1525
1526 ret = GetTextExtentExPointW(hdc, wt, 3, extents[1], &fit1, extents2, &sz2);
1527 ok(ret, "got %d\n", ret);
1528 ok(fit1 == 2, "got %d\n", fit1);
1529 ok(sz2.cx == sz.cx, "got %ld vs %ld\n", sz2.cx, sz.cx);
1530 for(i = 0; i < 2; i++)
1531 ok(extents2[i] == extents[i], "%d: %d, %d\n", i, extents2[i], extents[i]);
1532
1535 free(extents);
1536 ReleaseDC(NULL, hdc);
1537}
1538
1539static void free_font(void *font)
1540{
1542}
1543
1544static void *load_font(const char *font_name, DWORD *font_size)
1545{
1546 char file_name[MAX_PATH];
1548 void *font;
1549
1550 if (font_name[1] == ':')
1551 strcpy(file_name, font_name);
1552 else
1553 {
1554 if (!GetWindowsDirectoryA(file_name, sizeof(file_name))) return NULL;
1555 strcat(file_name, "\\fonts\\");
1556 strcat(file_name, font_name);
1557 }
1558
1560 if (file == INVALID_HANDLE_VALUE) return NULL;
1561
1562 *font_size = GetFileSize(file, NULL);
1563
1565 if (!mapping)
1566 {
1568 return NULL;
1569 }
1570
1572
1575 return font;
1576}
1577
1578static void test_GetGlyphIndices(void)
1579{
1580 HDC hdc;
1581 HFONT hfont;
1582 DWORD charcount;
1583 LOGFONTA lf;
1584 DWORD flags = 0;
1585 WCHAR testtext[] = L"Test\xffff";
1586 WCHAR c[] = { 0x25bc /* Black Down-Pointing Triangle */, 0x212a /* Kelvin Sign */ };
1587 WORD glyphs[(sizeof(testtext)/2)-1];
1588 TEXTMETRICA textm;
1589 HFONT hOldFont;
1590 HANDLE rsrc;
1591 DWORD ret, font_size, num_fonts;
1592 void *font;
1593 char ttf_name[MAX_PATH];
1594
1595 hdc = GetDC(0);
1596
1597 memset(&lf, 0, sizeof(lf));
1598 strcpy(lf.lfFaceName, "System");
1599 lf.lfHeight = 16;
1601
1603 ok(hfont != 0, "CreateFontIndirect failed\n");
1604 hOldFont = SelectObject(hdc, hfont);
1605 ok(GetTextMetricsA(hdc, &textm), "GetTextMetrics failed\n");
1606 if (textm.tmCharSet == ANSI_CHARSET)
1607 {
1609 charcount = GetGlyphIndicesW(hdc, testtext, (sizeof(testtext)/2)-1, glyphs, flags);
1610 ok(charcount == 5, "GetGlyphIndicesW count of glyphs should = 5 not %ld\n", charcount);
1611 ok((glyphs[4] == 0x001f || glyphs[4] == 0xffff /* Vista */), "GetGlyphIndicesW should have returned a nonexistent char not %04x\n", glyphs[4]);
1612 flags = 0;
1613 charcount = GetGlyphIndicesW(hdc, testtext, (sizeof(testtext)/2)-1, glyphs, flags);
1614 ok(charcount == 5, "GetGlyphIndicesW count of glyphs should = 5 not %ld\n", charcount);
1615 ok(glyphs[4] == textm.tmDefaultChar || glyphs[4] == 0x20 /* CJK Windows */,
1616 "GetGlyphIndicesW should have returned a %04x not %04x\n", textm.tmDefaultChar, glyphs[4]);
1617 }
1618 else
1619 /* FIXME: Write tests for non-ANSI charsets. */
1620 skip("GetGlyphIndices System font tests only for ANSI_CHARSET\n");
1621
1622 DeleteObject(SelectObject(hdc, hOldFont));
1623
1624 memset(&lf, 0, sizeof(lf));
1625 strcpy(lf.lfFaceName, "MS Sans Serif");
1626 lf.lfHeight = -13;
1629 ok(hfont != 0, "CreateFontIndirect failed\n");
1630 hOldFont = SelectObject(hdc, hfont);
1631 ok(GetTextMetricsA(hdc, &textm), "GetTextMetrics failed\n");
1632
1633 glyphs[0] = glyphs[1] = 0;
1635 ok(charcount == ARRAY_SIZE(c), "got %lu\n", charcount);
1636 ok(glyphs[0] == 0x001f || glyphs[0] == 0xffff /* Vista */, "got %#x\n", glyphs[0]);
1637 ok(glyphs[1] == 0x001f || glyphs[1] == 0xffff /* Vista */, "got %#x\n", glyphs[1]);
1638
1639 glyphs[0] = glyphs[1] = 0;
1640 charcount = GetGlyphIndicesW(hdc, c, ARRAY_SIZE(c), glyphs, 0);
1641 ok(charcount == ARRAY_SIZE(c), "got %lu\n", charcount);
1642 ok(glyphs[0] == textm.tmDefaultChar || glyphs[0] == 0x20 /* CJK Windows */, "got %#x\n", glyphs[0]);
1643 ok(glyphs[1] == textm.tmDefaultChar || glyphs[1] == 0x20 /* CJK Windows */, "got %#x\n", glyphs[1]);
1644
1645 DeleteObject(SelectObject(hdc, hOldFont));
1646
1647 if(!is_font_installed("Tahoma"))
1648 {
1649 skip("Tahoma is not installed so skipping this test\n");
1650 ReleaseDC(0, hdc);
1651 return;
1652 }
1653 memset(&lf, 0, sizeof(lf));
1654 strcpy(lf.lfFaceName, "Tahoma");
1655 lf.lfHeight = 20;
1656
1658 hOldFont = SelectObject(hdc, hfont);
1659 ok(GetTextMetricsA(hdc, &textm), "GetTextMetric failed\n");
1661 charcount = GetGlyphIndicesW(hdc, testtext, (sizeof(testtext)/2)-1, glyphs, flags);
1662 ok(charcount == 5, "GetGlyphIndicesW count of glyphs should = 5 not %ld\n", charcount);
1663 ok(glyphs[4] == 0xffff, "GetGlyphIndicesW should have returned 0xffff char not %04x\n", glyphs[4]);
1664 flags = 0;
1665 testtext[0] = textm.tmDefaultChar;
1666 charcount = GetGlyphIndicesW(hdc, testtext, (sizeof(testtext)/2)-1, glyphs, flags);
1667 ok(charcount == 5, "GetGlyphIndicesW count of glyphs should = 5 not %ld\n", charcount);
1668 ok(glyphs[0] == 0, "GetGlyphIndicesW for tmDefaultChar should be 0 not %04x\n", glyphs[0]);
1669 ok(glyphs[4] == 0, "GetGlyphIndicesW should have returned 0 not %04x\n", glyphs[4]);
1670 DeleteObject(SelectObject(hdc, hOldFont));
1671
1672 ret = write_ttf_file("wine_nul.ttf", ttf_name);
1673 ok(ret, "Failed to create test font file.\n");
1674 font = load_font(ttf_name, &font_size);
1675 ok(font != NULL, "Failed to map font file.\n");
1676 num_fonts = 0;
1677 rsrc = AddFontMemResourceEx(font, font_size, NULL, &num_fonts);
1678 ok(ret != 0, "Failed to add resource, %ld.\n", GetLastError());
1679 ok(num_fonts == 1, "Unexpected number of fonts %lu.\n", num_fonts);
1680
1681 memset(&lf, 0, sizeof(lf));
1682 strcpy(lf.lfFaceName, "wine_nul");
1683 lf.lfHeight = 20;
1684 flags = 0;
1686 hOldFont = SelectObject(hdc, hfont);
1687 ok(GetTextMetricsA(hdc, &textm), "GetTextMetric failed\n");
1688 testtext[0] = 'T';
1689 charcount = GetGlyphIndicesW(hdc, testtext, (sizeof(testtext)/2)-1, glyphs, flags);
1690 ok(charcount == 5, "GetGlyphIndicesW count of glyphs should = 5 not %ld\n", charcount);
1691 ok(glyphs[0] == 0, "GetGlyphIndicesW for tmDefaultChar should be 0 not %04x\n", glyphs[0]);
1692 ok(glyphs[4] == 0, "GetGlyphIndicesW should have returned 0 not %04x\n", glyphs[4]);
1693 DeleteObject(SelectObject(hdc, hOldFont));
1694
1695 ReleaseDC(0, hdc);
1696
1698 ok(ret, "RemoveFontMemResourceEx error %ld\n", GetLastError());
1699 free_font(font);
1700 ret = DeleteFileA(ttf_name);
1701 ok(ret, "Failed to delete font file, %ld.\n", GetLastError());
1702}
1703
1704static void test_GetKerningPairs(void)
1705{
1706 static const struct kerning_data
1707 {
1708 const char face_name[LF_FACESIZE];
1709 LONG height;
1710 /* some interesting fields from OUTLINETEXTMETRIC */
1711 LONG tmHeight, tmAscent, tmDescent;
1712 UINT otmEMSquare;
1713 INT otmAscent;
1714 INT otmDescent;
1715 UINT otmLineGap;
1716 UINT otmsCapEmHeight;
1717 UINT otmsXHeight;
1718 INT otmMacAscent;
1719 INT otmMacDescent;
1720 UINT otmMacLineGap;
1721 UINT otmusMinimumPPEM;
1722 /* small subset of kerning pairs to test */
1723 DWORD total_kern_pairs;
1724 const KERNINGPAIR kern_pair[26];
1725 } kd[] =
1726 {
1727 {"Arial", 12, 12, 9, 3,
1728 2048, 7, -2, 1, 5, 2, 8, -2, 0, 9,
1729 26,
1730 {
1731 {' ','A',-1},{' ','T',0},{' ','Y',0},{'1','1',-1},
1732 {'A',' ',-1},{'A','T',-1},{'A','V',-1},{'A','W',0},
1733 {'A','Y',-1},{'A','v',0},{'A','w',0},{'A','y',0},
1734 {'F',',',-1},{'F','.',-1},{'F','A',-1},{'L',' ',0},
1735 {'L','T',-1},{'L','V',-1},{'L','W',-1},{'L','Y',-1},
1736 {915,912,+1},{915,913,-1},{910,912,+1},{910,913,-1},
1737 {933,970,+1},{933,972,-1}
1738 }
1739 },
1740 {"Arial", -34, 39, 32, 7,
1741 2048, 25, -7, 5, 17, 9, 31, -7, 1, 9,
1742 26,
1743 {
1744 {' ','A',-2},{' ','T',-1},{' ','Y',-1},{'1','1',-3},
1745 {'A',' ',-2},{'A','T',-3},{'A','V',-3},{'A','W',-1},
1746 {'A','Y',-3},{'A','v',-1},{'A','w',-1},{'A','y',-1},
1747 {'F',',',-4},{'F','.',-4},{'F','A',-2},{'L',' ',-1},
1748 {'L','T',-3},{'L','V',-3},{'L','W',-3},{'L','Y',-3},
1749 {915,912,+3},{915,913,-3},{910,912,+3},{910,913,-3},
1750 {933,970,+2},{933,972,-3}
1751 }
1752 },
1753 { "Arial", 120, 120, 97, 23,
1754 2048, 79, -23, 16, 54, 27, 98, -23, 4, 9,
1755 26,
1756 {
1757 {' ','A',-6},{' ','T',-2},{' ','Y',-2},{'1','1',-8},
1758 {'A',' ',-6},{'A','T',-8},{'A','V',-8},{'A','W',-4},
1759 {'A','Y',-8},{'A','v',-2},{'A','w',-2},{'A','y',-2},
1760 {'F',',',-12},{'F','.',-12},{'F','A',-6},{'L',' ',-4},
1761 {'L','T',-8},{'L','V',-8},{'L','W',-8},{'L','Y',-8},
1762 {915,912,+9},{915,913,-10},{910,912,+9},{910,913,-8},
1763 {933,970,+6},{933,972,-10}
1764 }
1765 },
1766#if 0 /* this set fails due to +1/-1 errors (rounding bug?), needs investigation. */
1767 { "Arial", 1024 /* usually 1/2 of EM Square */, 1024, 830, 194,
1768 2048, 668, -193, 137, 459, 229, 830, -194, 30, 9,
1769 26,
1770 {
1771 {' ','A',-51},{' ','T',-17},{' ','Y',-17},{'1','1',-68},
1772 {'A',' ',-51},{'A','T',-68},{'A','V',-68},{'A','W',-34},
1773 {'A','Y',-68},{'A','v',-17},{'A','w',-17},{'A','y',-17},
1774 {'F',',',-102},{'F','.',-102},{'F','A',-51},{'L',' ',-34},
1775 {'L','T',-68},{'L','V',-68},{'L','W',-68},{'L','Y',-68},
1776 {915,912,+73},{915,913,-84},{910,912,+76},{910,913,-68},
1777 {933,970,+54},{933,972,-83}
1778 }
1779 }
1780#endif
1781 };
1782 LOGFONTA lf;
1783 HFONT hfont, hfont_old;
1784 KERNINGPAIR *kern_pair;
1785 HDC hdc;
1786 DWORD total_kern_pairs, ret, i, n, matches;
1787
1788 hdc = GetDC(0);
1789
1790 for (i = 0; i < ARRAY_SIZE(kd); i++)
1791 {
1793 UINT uiRet;
1794
1795 if (!is_font_installed(kd[i].face_name))
1796 {
1797 skip("%s is not installed so skipping this test\n", kd[i].face_name);
1798 continue;
1799 }
1800
1801 memset(&lf, 0, sizeof(lf));
1802 strcpy(lf.lfFaceName, kd[i].face_name);
1803 lf.lfHeight = kd[i].height;
1805 ok(hfont != NULL, "failed to create a font, name %s\n", kd[i].face_name);
1806
1807 hfont_old = SelectObject(hdc, hfont);
1808
1809 SetLastError(0xdeadbeef);
1810 uiRet = GetOutlineTextMetricsW(hdc, sizeof(otm), &otm);
1811 ok(uiRet == sizeof(otm), "GetOutlineTextMetricsW error %ld\n", GetLastError());
1812
1813 ok(match_off_by_1(kd[i].tmHeight, otm.otmTextMetrics.tmHeight, FALSE), "expected %ld, got %ld\n",
1814 kd[i].tmHeight, otm.otmTextMetrics.tmHeight);
1815 ok(match_off_by_1(kd[i].tmAscent, otm.otmTextMetrics.tmAscent, FALSE), "expected %ld, got %ld\n",
1816 kd[i].tmAscent, otm.otmTextMetrics.tmAscent);
1817 ok(kd[i].tmDescent == otm.otmTextMetrics.tmDescent, "expected %ld, got %ld\n",
1818 kd[i].tmDescent, otm.otmTextMetrics.tmDescent);
1819
1820 ok(kd[i].otmEMSquare == otm.otmEMSquare, "expected %u, got %u\n",
1821 kd[i].otmEMSquare, otm.otmEMSquare);
1822 ok(kd[i].otmAscent == otm.otmAscent, "expected %d, got %d\n",
1823 kd[i].otmAscent, otm.otmAscent);
1824 ok(kd[i].otmDescent == otm.otmDescent, "expected %d, got %d\n",
1825 kd[i].otmDescent, otm.otmDescent);
1826 ok(kd[i].otmLineGap == otm.otmLineGap, "expected %u, got %u\n",
1827 kd[i].otmLineGap, otm.otmLineGap);
1828 ok(near_match(kd[i].otmMacDescent, otm.otmMacDescent), "expected %d, got %d\n",
1829 kd[i].otmMacDescent, otm.otmMacDescent);
1830 ok(near_match(kd[i].otmMacAscent, otm.otmMacAscent), "expected %d, got %d\n",
1831 kd[i].otmMacAscent, otm.otmMacAscent);
1832 todo_wine
1833 ok(kd[i].otmsCapEmHeight == otm.otmsCapEmHeight, "expected %u, got %u\n",
1834 kd[i].otmsCapEmHeight, otm.otmsCapEmHeight);
1835 todo_wine
1836 ok(kd[i].otmsXHeight == otm.otmsXHeight, "expected %u, got %u\n",
1837 kd[i].otmsXHeight, otm.otmsXHeight);
1838 ok(kd[i].otmMacLineGap == otm.otmMacLineGap, "expected %u, got %u\n",
1839 kd[i].otmMacLineGap, otm.otmMacLineGap);
1840 todo_wine
1841 ok(kd[i].otmusMinimumPPEM == otm.otmusMinimumPPEM, "expected %u, got %u\n",
1842 kd[i].otmusMinimumPPEM, otm.otmusMinimumPPEM);
1843
1844 total_kern_pairs = GetKerningPairsW(hdc, 0, NULL);
1845 kern_pair = malloc(total_kern_pairs * sizeof(*kern_pair));
1846
1847 /* Win98 (GetKerningPairsA) and XP behave differently here, the test
1848 * passes on XP.
1849 */
1850 SetLastError(0xdeadbeef);
1851 ret = GetKerningPairsW(hdc, 0, kern_pair);
1853 "got error %lu, expected ERROR_INVALID_PARAMETER\n", GetLastError());
1854 ok(ret == 0, "got %lu, expected 0\n", ret);
1855
1856 ret = GetKerningPairsW(hdc, 100, NULL);
1857 ok(ret == total_kern_pairs, "got %lu, expected %lu\n", ret, total_kern_pairs);
1858
1859 ret = GetKerningPairsW(hdc, total_kern_pairs/2, kern_pair);
1860 ok(ret == total_kern_pairs/2, "got %lu, expected %lu\n", ret, total_kern_pairs/2);
1861
1862 ret = GetKerningPairsW(hdc, total_kern_pairs, kern_pair);
1863 ok(ret == total_kern_pairs, "got %lu, expected %lu\n", ret, total_kern_pairs);
1864
1865 matches = 0;
1866
1867 for (n = 0; n < ret; n++)
1868 {
1869 DWORD j;
1870
1871 for (j = 0; j < kd[i].total_kern_pairs; j++)
1872 {
1873 if (kern_pair[n].wFirst == kd[i].kern_pair[j].wFirst &&
1874 kern_pair[n].wSecond == kd[i].kern_pair[j].wSecond)
1875 {
1876 ok(kern_pair[n].iKernAmount == kd[i].kern_pair[j].iKernAmount,
1877 "pair %d:%d got %d, expected %d\n",
1878 kern_pair[n].wFirst, kern_pair[n].wSecond,
1879 kern_pair[n].iKernAmount, kd[i].kern_pair[j].iKernAmount);
1880 matches++;
1881 }
1882 }
1883 }
1884
1885 ok(matches == kd[i].total_kern_pairs, "got matches %lu, expected %lu\n",
1886 matches, kd[i].total_kern_pairs);
1887
1888 free(kern_pair);
1889
1890 SelectObject(hdc, hfont_old);
1892 }
1893
1894 ReleaseDC(0, hdc);
1895}
1896
1898{
1903};
1904
1905static void test_height( HDC hdc, const struct font_data *fd )
1906{
1907 LOGFONTA lf;
1908 HFONT hfont, old_hfont;
1910 INT ret, i;
1911
1912 for (i = 0; fd[i].face_name[0]; i++)
1913 {
1914 if (!is_truetype_font_installed(fd[i].face_name))
1915 {
1916 skip("%s is not installed\n", fd[i].face_name);
1917 continue;
1918 }
1919
1920 memset(&lf, 0, sizeof(lf));
1921 lf.lfHeight = fd[i].requested_height;
1922 lf.lfWeight = fd[i].weight;
1923 strcpy(lf.lfFaceName, fd[i].face_name);
1924
1926 ok(hfont != NULL, "failed to create a font, name %s\n", fd[i].face_name);
1927
1928 old_hfont = SelectObject(hdc, hfont);
1930 ok(ret, "GetTextMetrics error %ld\n", GetLastError());
1931 if(fd[i].dpi == tm.tmDigitizedAspectX)
1932 {
1933 ok(tm.tmWeight == fd[i].weight, "%s(%d): tm.tmWeight %ld != %d\n", fd[i].face_name, fd[i].requested_height, tm.tmWeight, fd[i].weight);
1934 ok(match_off_by_1(tm.tmHeight, fd[i].height, fd[i].exact), "%s(%d): tm.tmHeight %ld != %d\n", fd[i].face_name, fd[i].requested_height, tm.tmHeight, fd[i].height);
1935 ok(match_off_by_1(tm.tmAscent, fd[i].ascent, fd[i].exact), "%s(%d): tm.tmAscent %ld != %d\n", fd[i].face_name, fd[i].requested_height, tm.tmAscent, fd[i].ascent);
1936 ok(match_off_by_1(tm.tmDescent, fd[i].descent, fd[i].exact), "%s(%d): tm.tmDescent %ld != %d\n", fd[i].face_name, fd[i].requested_height, tm.tmDescent, fd[i].descent);
1937 ok(match_off_by_1(tm.tmInternalLeading, fd[i].int_leading, fd[i].exact), "%s(%d): tm.tmInternalLeading %ld != %d\n", fd[i].face_name, fd[i].requested_height, tm.tmInternalLeading, fd[i].int_leading);
1938 ok(tm.tmExternalLeading == fd[i].ext_leading, "%s(%d): tm.tmExternalLeading %ld != %d\n", fd[i].face_name, fd[i].requested_height, tm.tmExternalLeading, fd[i].ext_leading);
1939 }
1940
1941 SelectObject(hdc, old_hfont);
1942 /* force GDI to use new font, otherwise Windows leaks the font reference */
1945 }
1946}
1947
1948static void *find_ttf_table( void *ttf, DWORD size, DWORD tag )
1949{
1950 WORD i, num_tables = GET_BE_WORD(*((WORD *)ttf + 2));
1951 DWORD *table = (DWORD *)ttf + 3;
1952
1953 for (i = 0; i < num_tables; i++)
1954 {
1955 if (table[0] == tag)
1956 return (BYTE *)ttf + GET_BE_DWORD(table[2]);
1957 table += 4;
1958 }
1959 return NULL;
1960}
1961
1963{
1964 static const struct font_data charset_0[] = /* doesn't use VDMX */
1965 {
1966 { "wine_vdmx", 10, FW_NORMAL, 10, 8, 2, 2, 0, 96, TRUE },
1967 { "wine_vdmx", 11, FW_NORMAL, 11, 9, 2, 2, 0, 96, TRUE },
1968 { "wine_vdmx", 12, FW_NORMAL, 12, 10, 2, 2, 0, 96, TRUE },
1969 { "wine_vdmx", 13, FW_NORMAL, 13, 11, 2, 2, 0, 96, TRUE },
1970 { "wine_vdmx", 14, FW_NORMAL, 14, 12, 2, 2, 0, 96, TRUE },
1971 { "wine_vdmx", 15, FW_NORMAL, 15, 12, 3, 3, 0, 96, FALSE },
1972 { "wine_vdmx", 16, FW_NORMAL, 16, 13, 3, 3, 0, 96, TRUE },
1973 { "wine_vdmx", 17, FW_NORMAL, 17, 14, 3, 3, 0, 96, TRUE },
1974 { "wine_vdmx", 18, FW_NORMAL, 18, 15, 3, 3, 0, 96, TRUE },
1975 { "wine_vdmx", 19, FW_NORMAL, 19, 16, 3, 3, 0, 96, TRUE },
1976 { "wine_vdmx", 20, FW_NORMAL, 20, 17, 3, 4, 0, 96, FALSE },
1977 { "wine_vdmx", 21, FW_NORMAL, 21, 17, 4, 4, 0, 96, TRUE },
1978 { "wine_vdmx", 22, FW_NORMAL, 22, 18, 4, 4, 0, 96, TRUE },
1979 { "wine_vdmx", 23, FW_NORMAL, 23, 19, 4, 4, 0, 96, TRUE },
1980 { "wine_vdmx", 24, FW_NORMAL, 24, 20, 4, 4, 0, 96, TRUE },
1981 { "wine_vdmx", 25, FW_NORMAL, 25, 21, 4, 4, 0, 96, TRUE },
1982 { "wine_vdmx", 26, FW_NORMAL, 26, 22, 4, 5, 0, 96, FALSE },
1983 { "wine_vdmx", 27, FW_NORMAL, 27, 22, 5, 5, 0, 96, TRUE },
1984 { "wine_vdmx", 28, FW_NORMAL, 28, 23, 5, 5, 0, 96, TRUE },
1985 { "wine_vdmx", 29, FW_NORMAL, 29, 24, 5, 5, 0, 96, TRUE },
1986 { "wine_vdmx", 30, FW_NORMAL, 30, 25, 5, 5, 0, 96, TRUE },
1987 { "wine_vdmx", 31, FW_NORMAL, 31, 26, 5, 5, 0, 96, TRUE },
1988 { "wine_vdmx", 32, FW_NORMAL, 32, 27, 5, 6, 0, 96, FALSE },
1989 { "wine_vdmx", 48, FW_NORMAL, 48, 40, 8, 8, 0, 96, TRUE },
1990 { "wine_vdmx", 64, FW_NORMAL, 64, 53, 11, 11, 0, 96, TRUE },
1991 { "wine_vdmx", 96, FW_NORMAL, 96, 80, 16, 17, 0, 96, FALSE },
1992 { "wine_vdmx", -10, FW_NORMAL, 12, 10, 2, 2, 0, 96, TRUE },
1993 { "wine_vdmx", -11, FW_NORMAL, 13, 11, 2, 2, 0, 96, TRUE },
1994 { "wine_vdmx", -12, FW_NORMAL, 14, 12, 2, 2, 0, 96, TRUE },
1995 { "wine_vdmx", -13, FW_NORMAL, 16, 13, 3, 3, 0, 96, TRUE },
1996 { "wine_vdmx", -14, FW_NORMAL, 17, 14, 3, 3, 0, 96, TRUE },
1997 { "wine_vdmx", -15, FW_NORMAL, 18, 15, 3, 3, 0, 96, TRUE },
1998 { "wine_vdmx", -16, FW_NORMAL, 19, 16, 3, 3, 0, 96, TRUE },
1999 { "wine_vdmx", -17, FW_NORMAL, 21, 17, 4, 4, 0, 96, TRUE },
2000 { "wine_vdmx", -18, FW_NORMAL, 22, 18, 4, 4, 0, 96, TRUE },
2001 { "wine_vdmx", -19, FW_NORMAL, 23, 19, 4, 4, 0, 96, TRUE },
2002 { "wine_vdmx", -20, FW_NORMAL, 24, 20, 4, 4, 0, 96, TRUE },
2003 { "wine_vdmx", -21, FW_NORMAL, 25, 21, 4, 4, 0, 96, TRUE },
2004 { "wine_vdmx", -22, FW_NORMAL, 27, 22, 5, 5, 0, 96, TRUE },
2005 { "wine_vdmx", -23, FW_NORMAL, 28, 23, 5, 5, 0, 96, TRUE },
2006 { "wine_vdmx", -24, FW_NORMAL, 29, 24, 5, 5, 0, 96, TRUE },
2007 { "wine_vdmx", -25, FW_NORMAL, 30, 25, 5, 5, 0, 96, TRUE },
2008 { "wine_vdmx", -26, FW_NORMAL, 31, 26, 5, 5, 0, 96, TRUE },
2009 { "wine_vdmx", -27, FW_NORMAL, 33, 27, 6, 6, 0, 96, TRUE },
2010 { "wine_vdmx", -28, FW_NORMAL, 34, 28, 6, 6, 0, 96, TRUE },
2011 { "wine_vdmx", -29, FW_NORMAL, 35, 29, 6, 6, 0, 96, TRUE },
2012 { "wine_vdmx", -30, FW_NORMAL, 36, 30, 6, 6, 0, 96, TRUE },
2013 { "wine_vdmx", -31, FW_NORMAL, 37, 31, 6, 6, 0, 96, TRUE },
2014 { "wine_vdmx", -32, FW_NORMAL, 39, 32, 7, 7, 0, 96, TRUE },
2015 { "wine_vdmx", -48, FW_NORMAL, 58, 48, 10, 10, 0, 96, TRUE },
2016 { "wine_vdmx", -64, FW_NORMAL, 77, 64, 13, 13, 0, 96, TRUE },
2017 { "wine_vdmx", -96, FW_NORMAL, 116, 96, 20, 20, 0, 96, TRUE },
2018 { "", 0, 0, 0, 0, 0, 0, 0, 0, 0 }
2019 };
2020
2021 static const struct font_data charset_1[] = /* Uses VDMX */
2022 {
2023 { "wine_vdmx", 10, FW_NORMAL, 10, 8, 2, 2, 0, 96, TRUE },
2024 { "wine_vdmx", 11, FW_NORMAL, 11, 9, 2, 2, 0, 96, TRUE },
2025 { "wine_vdmx", 12, FW_NORMAL, 12, 10, 2, 2, 0, 96, TRUE },
2026 { "wine_vdmx", 13, FW_NORMAL, 13, 11, 2, 2, 0, 96, TRUE },
2027 { "wine_vdmx", 14, FW_NORMAL, 13, 11, 2, 2, 0, 96, TRUE },
2028 { "wine_vdmx", 15, FW_NORMAL, 13, 11, 2, 2, 0, 96, TRUE },
2029 { "wine_vdmx", 16, FW_NORMAL, 16, 13, 3, 4, 0, 96, TRUE },
2030 { "wine_vdmx", 17, FW_NORMAL, 16, 13, 3, 3, 0, 96, TRUE },
2031 { "wine_vdmx", 18, FW_NORMAL, 16, 13, 3, 3, 0, 96, TRUE },
2032 { "wine_vdmx", 19, FW_NORMAL, 19, 15, 4, 5, 0, 96, TRUE },
2033 { "wine_vdmx", 20, FW_NORMAL, 20, 16, 4, 5, 0, 96, TRUE },
2034 { "wine_vdmx", 21, FW_NORMAL, 21, 17, 4, 5, 0, 96, TRUE },
2035 { "wine_vdmx", 22, FW_NORMAL, 22, 18, 4, 5, 0, 96, TRUE },
2036 { "wine_vdmx", 23, FW_NORMAL, 23, 19, 4, 5, 0, 96, TRUE },
2037 { "wine_vdmx", 24, FW_NORMAL, 23, 19, 4, 5, 0, 96, TRUE },
2038 { "wine_vdmx", 25, FW_NORMAL, 25, 21, 4, 6, 0, 96, TRUE },
2039 { "wine_vdmx", 26, FW_NORMAL, 26, 22, 4, 6, 0, 96, TRUE },
2040 { "wine_vdmx", 27, FW_NORMAL, 27, 23, 4, 6, 0, 96, TRUE },
2041 { "wine_vdmx", 28, FW_NORMAL, 27, 23, 4, 5, 0, 96, TRUE },
2042 { "wine_vdmx", 29, FW_NORMAL, 29, 24, 5, 6, 0, 96, TRUE },
2043 { "wine_vdmx", 30, FW_NORMAL, 29, 24, 5, 6, 0, 96, TRUE },
2044 { "wine_vdmx", 31, FW_NORMAL, 29, 24, 5, 6, 0, 96, TRUE },
2045 { "wine_vdmx", 32, FW_NORMAL, 32, 26, 6, 8, 0, 96, TRUE },
2046 { "wine_vdmx", 48, FW_NORMAL, 48, 40, 8, 10, 0, 96, TRUE },
2047 { "wine_vdmx", 64, FW_NORMAL, 64, 54, 10, 13, 0, 96, TRUE },
2048 { "wine_vdmx", 96, FW_NORMAL, 95, 79, 16, 18, 0, 96, TRUE },
2049 { "wine_vdmx", -10, FW_NORMAL, 12, 10, 2, 2, 0, 96, TRUE },
2050 { "wine_vdmx", -11, FW_NORMAL, 13, 11, 2, 2, 0, 96, TRUE },
2051 { "wine_vdmx", -12, FW_NORMAL, 16, 13, 3, 4, 0, 96, TRUE },
2052 { "wine_vdmx", -13, FW_NORMAL, 16, 13, 3, 3, 0, 96, TRUE },
2053 { "wine_vdmx", -14, FW_NORMAL, 19, 15, 4, 5, 0, 96, TRUE },
2054 { "wine_vdmx", -15, FW_NORMAL, 20, 16, 4, 5, 0, 96, TRUE },
2055 { "wine_vdmx", -16, FW_NORMAL, 21, 17, 4, 5, 0, 96, TRUE },
2056 { "wine_vdmx", -17, FW_NORMAL, 22, 18, 4, 5, 0, 96, TRUE },
2057 { "wine_vdmx", -18, FW_NORMAL, 23, 19, 4, 5, 0, 96, TRUE },
2058 { "wine_vdmx", -19, FW_NORMAL, 25, 21, 4, 6, 0, 96, TRUE },
2059 { "wine_vdmx", -20, FW_NORMAL, 26, 22, 4, 6, 0, 96, TRUE },
2060 { "wine_vdmx", -21, FW_NORMAL, 27, 23, 4, 6, 0, 96, TRUE },
2061 { "wine_vdmx", -22, FW_NORMAL, 27, 23, 4, 5, 0, 96, TRUE },
2062 { "wine_vdmx", -23, FW_NORMAL, 29, 24, 5, 6, 0, 96, TRUE },
2063 { "wine_vdmx", -24, FW_NORMAL, 32, 26, 6, 8, 0, 96, TRUE },
2064 { "wine_vdmx", -25, FW_NORMAL, 32, 26, 6, 7, 0, 96, TRUE },
2065 { "wine_vdmx", -26, FW_NORMAL, 33, 27, 6, 7, 0, 96, TRUE },
2066 { "wine_vdmx", -27, FW_NORMAL, 35, 29, 6, 8, 0, 96, TRUE },
2067 { "wine_vdmx", -28, FW_NORMAL, 36, 30, 6, 8, 0, 96, TRUE },
2068 { "wine_vdmx", -29, FW_NORMAL, 36, 30, 6, 7, 0, 96, TRUE },
2069 { "wine_vdmx", -30, FW_NORMAL, 38, 32, 6, 8, 0, 96, TRUE },
2070 { "wine_vdmx", -31, FW_NORMAL, 39, 33, 6, 8, 0, 96, TRUE },
2071 { "wine_vdmx", -32, FW_NORMAL, 40, 33, 7, 8, 0, 96, TRUE },
2072 { "wine_vdmx", -48, FW_NORMAL, 60, 50, 10, 12, 0, 96, TRUE },
2073 { "wine_vdmx", -64, FW_NORMAL, 81, 67, 14, 17, 0, 96, TRUE },
2074 { "wine_vdmx", -96, FW_NORMAL, 119, 99, 20, 23, 0, 96, TRUE },
2075 { "", 0, 0, 0, 0, 0, 0, 0, 0, 0 }
2076 };
2077
2078 static const struct vdmx_data
2079 {
2080 WORD version;
2081 BYTE bCharSet;
2082 const struct font_data *fd;
2083 } data[] =
2084 {
2085 { 0, 0, charset_0 },
2086 { 0, 1, charset_1 },
2087 { 1, 0, charset_0 },
2088 { 1, 1, charset_1 }
2089 };
2090 int i;
2091 DWORD size, num;
2092 WORD *vdmx_header;
2093 BYTE *ratio_rec;
2094 char ttf_name[MAX_PATH];
2095 void *res, *copy;
2096 BOOL ret;
2097
2098 for (i = 0; i < ARRAY_SIZE(data); i++)
2099 {
2100 res = get_res_data( "wine_vdmx.ttf", &size );
2101
2102 copy = malloc( size );
2103 memcpy( copy, res, size );
2104 vdmx_header = find_ttf_table( copy, size, MS_MAKE_TAG('V','D','M','X') );
2105 vdmx_header[0] = GET_BE_WORD( data[i].version );
2106 ok( GET_BE_WORD( vdmx_header[1] ) == 1, "got %04x\n", GET_BE_WORD( vdmx_header[1] ) );
2107 ok( GET_BE_WORD( vdmx_header[2] ) == 1, "got %04x\n", GET_BE_WORD( vdmx_header[2] ) );
2108 ratio_rec = (BYTE *)&vdmx_header[3];
2109 ratio_rec[0] = data[i].bCharSet;
2110
2111 write_tmp_file( copy, &size, ttf_name );
2112 free( copy );
2113
2114 ok( !is_truetype_font_installed("wine_vdmx"), "Already installed\n" );
2115 num = AddFontResourceExA( ttf_name, FR_PRIVATE, 0 );
2116 if (!num) win_skip("Unable to add ttf font resource\n");
2117 else
2118 {
2119 ok( is_truetype_font_installed("wine_vdmx"), "Not installed\n" );
2120 test_height( hdc, data[i].fd );
2121 RemoveFontResourceExA( ttf_name, FR_PRIVATE, 0 );
2122 }
2123 ret = DeleteFileA( ttf_name );
2125 "DeleteFile error %ld\n", GetLastError());
2126 }
2127}
2128
2129static void test_height_selection(void)
2130{
2131 static const struct font_data tahoma[] =
2132 {
2133 {"Tahoma", -12, FW_NORMAL, 14, 12, 2, 2, 0, 96, TRUE },
2134 {"Tahoma", -24, FW_NORMAL, 29, 24, 5, 5, 0, 96, TRUE },
2135 {"Tahoma", -48, FW_NORMAL, 58, 48, 10, 10, 0, 96, TRUE },
2136 {"Tahoma", -96, FW_NORMAL, 116, 96, 20, 20, 0, 96, TRUE },
2137 {"Tahoma", -192, FW_NORMAL, 232, 192, 40, 40, 0, 96, TRUE },
2138 {"Tahoma", 12, FW_NORMAL, 12, 10, 2, 2, 0, 96, TRUE },
2139 {"Tahoma", 24, FW_NORMAL, 24, 20, 4, 4, 0, 96, TRUE },
2140 {"Tahoma", 48, FW_NORMAL, 48, 40, 8, 8, 0, 96, TRUE },
2141 {"Tahoma", 96, FW_NORMAL, 96, 80, 16, 17, 0, 96, FALSE },
2142 {"Tahoma", 192, FW_NORMAL, 192, 159, 33, 33, 0, 96, TRUE },
2143 {"", 0, 0, 0, 0, 0, 0, 0, 0, 0 }
2144 };
2146 ok(hdc != NULL, "failed to create hdc\n");
2147
2148 test_height( hdc, tahoma );
2150
2151 DeleteDC(hdc);
2152}
2153
2155{
2156 OUTLINETEXTMETRICA *otm;
2157 HFONT hfont, hfont_old;
2158 DWORD ret, otm_size;
2159 UINT fsSelection;
2160 HDC hdc;
2161
2162 hdc = GetDC(0);
2164 ok(hfont != NULL, "failed to create a font\n");
2165
2166 hfont_old = SelectObject(hdc, hfont);
2167
2168 otm_size = GetOutlineTextMetricsA(hdc, 0, NULL);
2169 otm = malloc(otm_size);
2170 otm->otmSize = sizeof(*otm);
2171 ret = GetOutlineTextMetricsA(hdc, otm->otmSize, otm);
2172 ok(ret == otm->otmSize, "expected %u, got %lu, error %ld\n", otm->otmSize, ret, GetLastError());
2173 fsSelection = otm->otmfsSelection;
2174 free(otm);
2175 SelectObject(hdc, hfont_old);
2177 ReleaseDC(0, hdc);
2178
2179 return fsSelection;
2180}
2181
2183{
2184 OUTLINETEXTMETRICA *otm;
2185 LOGFONTA lf;
2186 HFONT hfont, hfont_old;
2187 HDC hdc;
2188 DWORD ret, otm_size;
2189 LPSTR unset_ptr;
2190 UINT fsSelection;
2191
2192 /* check fsSelection field with bold simulation */
2193 memset(&lf, 0, sizeof(lf));
2194 strcpy(lf.lfFaceName, "Wingdings");
2196
2197 /* regular face */
2198 fsSelection = get_font_fsselection(&lf);
2199 ok((fsSelection & (1 << 5)) == 0, "got 0x%x\n", fsSelection);
2200
2201 /* face with bold simulation */
2202 lf.lfWeight = FW_BOLD;
2203 fsSelection = get_font_fsselection(&lf);
2204 ok((fsSelection & (1 << 5)) != 0, "got 0x%x\n", fsSelection);
2205
2206 /* check fsSelection field with oblique simulation */
2207 memset(&lf, 0, sizeof(lf));
2208 strcpy(lf.lfFaceName, "Tahoma");
2209 lf.lfHeight = -13;
2210 lf.lfWeight = FW_NORMAL;
2213
2214 /* regular face */
2215 fsSelection = get_font_fsselection(&lf);
2216 ok((fsSelection & 1) == 0, "got 0x%x\n", fsSelection);
2217
2218 lf.lfItalic = 1;
2219 /* face with oblique simulation */
2220 fsSelection = get_font_fsselection(&lf);
2221 ok((fsSelection & 1) == 1, "got 0x%x\n", fsSelection);
2222
2223 if (!is_font_installed("Arial"))
2224 {
2225 skip("Arial is not installed\n");
2226 return;
2227 }
2228
2229 hdc = GetDC(0);
2230
2231 memset(&lf, 0, sizeof(lf));
2232 strcpy(lf.lfFaceName, "Arial");
2233 lf.lfHeight = -13;
2234 lf.lfWeight = FW_NORMAL;
2238 ok(hfont != NULL, "failed to create a font\n");
2239
2240 hfont_old = SelectObject(hdc, hfont);
2241 otm_size = GetOutlineTextMetricsA(hdc, 0, NULL);
2242
2243 otm = malloc(otm_size);
2244
2245 memset(otm, 0xAA, otm_size);
2246 SetLastError(0xdeadbeef);
2247 otm->otmSize = sizeof(*otm);
2248 ret = GetOutlineTextMetricsA(hdc, otm->otmSize, otm);
2249 ok(ret == otm->otmSize, "expected %u, got %lu, error %ld\n", otm->otmSize, ret, GetLastError());
2250 ok(otm->otmpFamilyName == NULL, "expected NULL got %p\n", otm->otmpFamilyName);
2251 ok(otm->otmpFaceName == NULL, "expected NULL got %p\n", otm->otmpFaceName);
2252 ok(otm->otmpStyleName == NULL, "expected NULL got %p\n", otm->otmpStyleName);
2253 ok(otm->otmpFullName == NULL, "expected NULL got %p\n", otm->otmpFullName);
2254
2255 memset(otm, 0xAA, otm_size);
2256 SetLastError(0xdeadbeef);
2257 ret = GetOutlineTextMetricsA(hdc, otm->otmSize, otm);
2258 ok(ret == otm->otmSize, "expected %u, got %lu, error %ld\n", otm->otmSize, ret, GetLastError());
2259 ok(otm->otmpFamilyName != NULL, "expected not NULL got %p\n", otm->otmpFamilyName);
2260 ok(otm->otmpFaceName != NULL, "expected not NULL got %p\n", otm->otmpFaceName);
2261 ok(otm->otmpStyleName != NULL, "expected not NULL got %p\n", otm->otmpStyleName);
2262 ok(otm->otmpFullName != NULL, "expected not NULL got %p\n", otm->otmpFullName);
2263
2264 /* ask about truncated data */
2265 memset(otm, 0xAA, otm_size);
2266 memset(&unset_ptr, 0xAA, sizeof(unset_ptr));
2267 SetLastError(0xdeadbeef);
2268 otm->otmSize = sizeof(*otm) - sizeof(char*);
2269 ret = GetOutlineTextMetricsA(hdc, otm->otmSize, otm);
2270 ok(ret == otm->otmSize, "expected %u, got %lu, error %ld\n", otm->otmSize, ret, GetLastError());
2271 ok(otm->otmpFamilyName == NULL, "expected NULL got %p\n", otm->otmpFamilyName);
2272 ok(otm->otmpFaceName == NULL, "expected NULL got %p\n", otm->otmpFaceName);
2273 ok(otm->otmpStyleName == NULL, "expected NULL got %p\n", otm->otmpStyleName);
2274 ok(otm->otmpFullName == unset_ptr, "expected %p got %p\n", unset_ptr, otm->otmpFullName);
2275
2276 /* check handling of NULL pointer */
2277 SetLastError(0xdeadbeef);
2278 ret = GetOutlineTextMetricsA(hdc, otm_size, NULL);
2279 ok(ret == otm_size, "expected %lu, got %lu, error %ld\n", otm_size, ret, GetLastError());
2280
2281 free(otm);
2282
2283 SelectObject(hdc, hfont_old);
2285
2286 ReleaseDC(0, hdc);
2287}
2288
2289static void testJustification(const char *context, HDC hdc, PCSTR str, RECT *clientArea)
2290{
2291 INT y,
2292 breakCount,
2293 areaWidth = clientArea->right - clientArea->left,
2294 nErrors = 0, e;
2295 const char *pFirstChar, *pLastChar;
2296 SIZE size;
2298 struct err
2299 {
2300 const char *start;
2301 int len;
2302 int GetTextExtentExPointWWidth;
2303 } error[20];
2304
2306 y = clientArea->top;
2307 do {
2308 breakCount = 0;
2309 while (*str == tm.tmBreakChar) str++; /* skip leading break chars */
2310 pFirstChar = str;
2311
2312 do {
2313 pLastChar = str;
2314
2315 /* if not at the end of the string, ... */
2316 if (*str == '\0') break;
2317 /* ... add the next word to the current extent */
2318 while (*str != '\0' && *str++ != tm.tmBreakChar);
2319 breakCount++;
2321 GetTextExtentPoint32A(hdc, pFirstChar, str - pFirstChar - 1, &size);
2322 } while ((int) size.cx < areaWidth);
2323
2324 /* ignore trailing break chars */
2325 breakCount--;
2326 while (*(pLastChar - 1) == tm.tmBreakChar)
2327 {
2328 pLastChar--;
2329 breakCount--;
2330 }
2331
2332 if (*str == '\0' || breakCount <= 0) pLastChar = str;
2333
2335 GetTextExtentPoint32A(hdc, pFirstChar, pLastChar - pFirstChar, &size);
2336
2337 /* do not justify the last extent */
2338 if (*str != '\0' && breakCount > 0)
2339 {
2340 SetTextJustification(hdc, areaWidth - size.cx, breakCount);
2341 GetTextExtentPoint32A(hdc, pFirstChar, pLastChar - pFirstChar, &size);
2342 if (size.cx != areaWidth && nErrors < ARRAY_SIZE(error) - 1)
2343 {
2344 error[nErrors].start = pFirstChar;
2345 error[nErrors].len = pLastChar - pFirstChar;
2346 error[nErrors].GetTextExtentExPointWWidth = size.cx;
2347 nErrors++;
2348 }
2349 }
2350
2351 y += size.cy;
2352 str = pLastChar;
2353 } while (*str && y < clientArea->bottom);
2354
2355 for (e = 0; e < nErrors; e++)
2356 {
2357 /* The width returned by GetTextExtentPoint32() is exactly the same
2358 returned by GetTextExtentExPointW() - see dlls/gdi32/font.c */
2359 ok(error[e].GetTextExtentExPointWWidth == areaWidth ||
2360 broken(abs(areaWidth - error[e].GetTextExtentExPointWWidth) <= 2) /* win10 */,
2361 "%s: GetTextExtentPointW() for \"%.*s\" should have returned a width of %d, not %d.\n",
2362 context, error[e].len, error[e].start, areaWidth, error[e].GetTextExtentExPointWWidth);
2363 }
2364}
2365
2367{
2368 HDC hdc;
2369 RECT clientArea;
2370 LOGFONTA lf;
2371 HFONT hfont;
2372 HWND hwnd;
2373 SIZE size, expect;
2374 int i;
2375 WORD indices[2];
2376 static const char testText[] =
2377 "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do "
2378 "eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut "
2379 "enim ad minim veniam, quis nostrud exercitation ullamco laboris "
2380 "nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in "
2381 "reprehenderit in voluptate velit esse cillum dolore eu fugiat "
2382 "nulla pariatur. Excepteur sint occaecat cupidatat non proident, "
2383 "sunt in culpa qui officia deserunt mollit anim id est laborum.";
2384
2385 hwnd = CreateWindowExA(0, "static", "", WS_POPUP, 0,0, 400,400, 0, 0, 0, NULL);
2386 GetClientRect( hwnd, &clientArea );
2387 hdc = GetDC( hwnd );
2388
2389 if (!is_font_installed("Times New Roman"))
2390 {
2391 skip("Times New Roman is not installed\n");
2392 return;
2393 }
2394
2395 memset(&lf, 0, sizeof lf);
2398 lf.lfWeight = FW_DONTCARE;
2399 lf.lfHeight = 20;
2401 lstrcpyA(lf.lfFaceName, "Times New Roman");
2402 hfont = create_font("Times New Roman", &lf);
2404
2405 testJustification("default", hdc, testText, &clientArea);
2406
2407 GetGlyphIndicesA( hdc, "A ", 2, indices, 0 );
2408
2410 GetTextExtentPoint32A(hdc, " ", 1, &expect);
2411 GetTextExtentPoint32A(hdc, " ", 3, &size);
2412 ok( size.cx == 3 * expect.cx, "wrong size %ld/%ld\n", size.cx, expect.cx );
2414 GetTextExtentPoint32A(hdc, " ", 1, &size);
2415 ok( size.cx == expect.cx + 4, "wrong size %ld/%ld\n", size.cx, expect.cx );
2417 GetTextExtentPoint32A(hdc, " ", 2, &size);
2418 ok( size.cx == 2 * expect.cx + 9, "wrong size %ld/%ld\n", size.cx, expect.cx );
2420 GetTextExtentPoint32A(hdc, " ", 3, &size);
2421 ok( size.cx == 3 * expect.cx + 7, "wrong size %ld/%ld\n", size.cx, expect.cx );
2424 GetTextExtentPoint32A(hdc, " ", 3, &size);
2425 ok( size.cx == 3 * (expect.cx + 2) + 7, "wrong size %ld/%ld\n", size.cx, expect.cx );
2428 size.cx = size.cy = 1234;
2429 GetTextExtentPoint32A(hdc, " ", 0, &size);
2430 ok( size.cx == 0 && size.cy == 0, "wrong size %ld,%ld\n", size.cx, size.cy );
2434 ok( size.cx == expect.cx + 5, "wrong size %ld/%ld\n", size.cx, expect.cx );
2436
2438 SetWindowExtEx( hdc, 2, 2, NULL );
2439 GetClientRect( hwnd, &clientArea );
2440 DPtoLP( hdc, (POINT *)&clientArea, 2 );
2441 testJustification("2x2", hdc, testText, &clientArea);
2442
2443 GetTextExtentPoint32A(hdc, "A", 1, &expect);
2444 for (i = 0; i < 10; i++)
2445 {
2447 GetTextExtentPoint32A(hdc, "A", 1, &size);
2448 ok( size.cx == expect.cx + i, "wrong size %ld/%ld+%d\n", size.cx, expect.cx, i );
2449 }
2452 for (i = 0; i < 10; i++)
2453 {
2456 ok( size.cx == expect.cx + i, "wrong size %ld/%ld+%d\n", size.cx, expect.cx, i );
2457 }
2459
2460 SetViewportExtEx( hdc, 3, 3, NULL );
2461 GetClientRect( hwnd, &clientArea );
2462 DPtoLP( hdc, (POINT *)&clientArea, 2 );
2463 testJustification("3x3", hdc, testText, &clientArea);
2464
2465 GetTextExtentPoint32A(hdc, "A", 1, &expect);
2466 for (i = 0; i < 10; i++)
2467 {
2469 GetTextExtentPoint32A(hdc, "A", 1, &size);
2470 ok( size.cx == expect.cx + i, "wrong size %ld/%ld+%d\n", size.cx, expect.cx, i );
2471 }
2472
2474 ReleaseDC(hwnd, hdc);
2476}
2477
2479{
2480 HDC hdc;
2481 LOGFONTA lf;
2482 HFONT hfont, hfont_old;
2483 CHARSETINFO csi;
2485 INT cs;
2486 DWORD i, ret;
2487 char name[64];
2488
2489 assert(count <= 128);
2490
2491 memset(&lf, 0, sizeof(lf));
2492
2493 lf.lfCharSet = charset;
2494 lf.lfHeight = 10;
2495 lstrcpyA(lf.lfFaceName, "Arial");
2496 SetLastError(0xdeadbeef);
2498 ok(hfont != 0, "CreateFontIndirectA error %lu\n", GetLastError());
2499
2500 hdc = GetDC(0);
2501 hfont_old = SelectObject(hdc, hfont);
2502
2503 cs = GetTextCharsetInfo(hdc, &fs, 0);
2504 ok(cs == charset, "expected %d, got %d\n", charset, cs);
2505
2506 SetLastError(0xdeadbeef);
2507 ret = GetTextFaceA(hdc, sizeof(name), name);
2508 ok(ret, "GetTextFaceA error %lu\n", GetLastError());
2509
2510 if (charset == SYMBOL_CHARSET)
2511 {
2512 ok(strcmp("Arial", name), "face name should NOT be Arial\n");
2513 ok(fs.fsCsb[0] & (1u << 31), "symbol encoding should be available\n");
2514 }
2515 else
2516 {
2517 ok(!strcmp("Arial", name), "face name should be Arial, not %s\n", name);
2518 ok(!(fs.fsCsb[0] & (1u << 31)), "symbol encoding should NOT be available\n");
2519 }
2520
2522 {
2523 trace("Can't find codepage for charset %d\n", cs);
2524 ReleaseDC(0, hdc);
2525 return FALSE;
2526 }
2527 ok(csi.ciACP == code_page, "expected %d, got %d\n", code_page, csi.ciACP);
2528
2529 if (pGdiGetCodePage != NULL && pGdiGetCodePage(hdc) != code_page)
2530 {
2531 skip("Font code page %ld, looking for code page %d\n",
2532 pGdiGetCodePage(hdc), code_page);
2533 ReleaseDC(0, hdc);
2534 return FALSE;
2535 }
2536
2537 if (unicode)
2538 {
2539 char ansi_buf[128];
2540 WCHAR unicode_buf[128];
2541
2542 for (i = 0; i < count; i++) ansi_buf[i] = (BYTE)(i + 128);
2543
2544 MultiByteToWideChar(code_page, 0, ansi_buf, count, unicode_buf, count);
2545
2546 SetLastError(0xdeadbeef);
2547 ret = GetGlyphIndicesW(hdc, unicode_buf, count, idx, 0);
2548 ok(ret == count, "GetGlyphIndicesW expected %d got %ld, error %lu\n",
2549 count, ret, GetLastError());
2550 }
2551 else
2552 {
2553 char ansi_buf[128];
2554
2555 for (i = 0; i < count; i++) ansi_buf[i] = (BYTE)(i + 128);
2556
2557 SetLastError(0xdeadbeef);
2558 ret = GetGlyphIndicesA(hdc, ansi_buf, count, idx, 0);
2559 ok(ret == count, "GetGlyphIndicesA expected %d got %ld, error %lu\n",
2560 count, ret, GetLastError());
2561 }
2562
2563 SelectObject(hdc, hfont_old);
2565
2566 ReleaseDC(0, hdc);
2567
2568 return TRUE;
2569}
2570
2572{
2573 static CHARSETINFO tests[] =
2574 {
2575 { ANSI_CHARSET, 1252, { {0}, { FS_LATIN1 }}},
2576 { EASTEUROPE_CHARSET, 1250, { {0}, { FS_LATIN2 }}},
2577 { RUSSIAN_CHARSET, 1251, { {0}, { FS_CYRILLIC }}},
2578 { GREEK_CHARSET, 1253, { {0}, { FS_GREEK }}},
2579 { TURKISH_CHARSET, 1254, { {0}, { FS_TURKISH }}},
2580 { HEBREW_CHARSET, 1255, { {0}, { FS_HEBREW }}},
2581 { ARABIC_CHARSET, 1256, { {0}, { FS_ARABIC }}},
2582 { BALTIC_CHARSET, 1257, { {0}, { FS_BALTIC }}},
2583 { VIETNAMESE_CHARSET, 1258, { {0}, { FS_VIETNAMESE }}},
2584 { THAI_CHARSET, 874, { {0}, { FS_THAI }}},
2585 { SHIFTJIS_CHARSET, 932, { {0}, { FS_JISJAPAN }}},
2586 { GB2312_CHARSET, 936, { {0}, { FS_CHINESESIMP }}},
2587 { HANGEUL_CHARSET, 949, { {0}, { FS_WANSUNG }}},
2588 { CHINESEBIG5_CHARSET, 950, { {0}, { FS_CHINESETRAD }}},
2589 { JOHAB_CHARSET, 1361, { {0}, { FS_JOHAB }}},
2590 { 254, CP_UTF8, { {0}, { 0x04000000 }}},
2591 { SYMBOL_CHARSET, CP_SYMBOL, { {0}, { FS_SYMBOL }}}
2592 };
2593 CHARSETINFO csi;
2594 DWORD i, j;
2595 BOOL ret;
2596
2597 /* try all codepages */
2598 for (i = 0; i < 65536; i++)
2599 {
2600 memset( &csi, 0xcc, sizeof(csi) );
2602 if (ret)
2603 {
2604 for (j = 0; j < ARRAY_SIZE(tests); j++)
2605 {
2606 if (tests[j].ciACP != i) continue;
2607 ok( !memcmp( &csi, &tests[j], sizeof(csi) ),
2608 "%lu: wrong info %u %u %08lx %08lx %08lx %08lx %08lx %08lx\n", i,
2609 csi.ciCharset, csi.ciACP, csi.fs.fsUsb[0], csi.fs.fsUsb[1],
2610 csi.fs.fsUsb[2], csi.fs.fsUsb[3], csi.fs.fsCsb[0], csi.fs.fsCsb[1] );
2611 break;
2612 }
2613 ok( j < ARRAY_SIZE(tests), "%lu: TranslateCharsetInfo succeeded\n", i );
2614 }
2615 else ok( !ret, "%lu: TranslateCharsetInfo succeeded\n", i );
2616 }
2617
2618 /* try all charsets */
2619 for (i = 0; i < 256; i++)
2620 {
2621 memset( &csi, 0xcc, sizeof(csi) );
2623 if (ret)
2624 {
2625 for (j = 0; j < ARRAY_SIZE(tests); j++)
2626 {
2627 if (tests[j].ciCharset != i) continue;
2628 ok( !memcmp( &csi, &tests[j], sizeof(csi) ),
2629 "%lu: wrong info %u %u %08lx %08lx %08lx %08lx %08lx %08lx\n", i,
2630 csi.ciCharset, csi.ciACP, csi.fs.fsUsb[0], csi.fs.fsUsb[1],
2631 csi.fs.fsUsb[2], csi.fs.fsUsb[3], csi.fs.fsCsb[0], csi.fs.fsCsb[1] );
2632 break;
2633 }
2634 ok( j < ARRAY_SIZE(tests), "%lu: TranslateCharsetInfo succeeded\n", i );
2635 }
2636 else ok( !ret, "%lu: TranslateCharsetInfo succeeded\n", i );
2637 }
2638
2639 /* try all fontsigs */
2640 for (i = 0; i < 64; i++)
2641 {
2642 DWORD csb[2] = { 0, 0 };
2643 csb[i / 32] = 1 << (i % 32);
2644 memset( &csi, 0xcc, sizeof(csi) );
2645 ret = TranslateCharsetInfo( csb, &csi, TCI_SRCFONTSIG );
2646 if (ret)
2647 {
2648 for (j = 0; j < ARRAY_SIZE(tests); j++)
2649 {
2650 if (tests[j].fs.fsCsb[0] != csb[0]) continue;
2651 ok( !memcmp( &csi, &tests[j], sizeof(csi) ),
2652 "%lu: wrong info %u %u %08lx %08lx %08lx %08lx %08lx %08lx\n", i,
2653 csi.ciCharset, csi.ciACP, csi.fs.fsUsb[0], csi.fs.fsUsb[1],
2654 csi.fs.fsUsb[2], csi.fs.fsUsb[3], csi.fs.fsCsb[0], csi.fs.fsCsb[1] );
2655 break;
2656 }
2657 ok( j < ARRAY_SIZE(tests), "%lu: TranslateCharsetInfo succeeded\n", i );
2658 }
2659 else ok( !ret, "%lu: TranslateCharsetInfo succeeded\n", i );
2660 }
2661}
2662
2663static void test_font_charset(void)
2664{
2665 static struct charset_data
2666 {
2667 INT charset;
2669 WORD font_idxA[128], font_idxW[128];
2670 } cd[] =
2671 {
2672 { ANSI_CHARSET, 1252 },
2673 { RUSSIAN_CHARSET, 1251 },
2674 { SYMBOL_CHARSET, CP_SYMBOL } /* keep it as the last one */
2675 };
2676 int i;
2677
2678 if (!is_font_installed("Arial"))
2679 {
2680 skip("Arial is not installed\n");
2681 return;
2682 }
2683
2684 for (i = 0; i < ARRAY_SIZE(cd); i++)
2685 {
2686 if (cd[i].charset == SYMBOL_CHARSET)
2687 {
2688 if (!is_font_installed("Symbol") && !is_font_installed("Wingdings"))
2689 {
2690 skip("Symbol or Wingdings is not installed\n");
2691 break;
2692 }
2693 }
2694 if (get_glyph_indices(cd[i].charset, cd[i].code_page, cd[i].font_idxA, 128, FALSE) &&
2695 get_glyph_indices(cd[i].charset, cd[i].code_page, cd[i].font_idxW, 128, TRUE))
2696 ok(!memcmp(cd[i].font_idxA, cd[i].font_idxW, 128*sizeof(WORD)), "%d: indices don't match\n", i);
2697 }
2698
2699 ok(memcmp(cd[0].font_idxW, cd[1].font_idxW, 128*sizeof(WORD)), "0 vs 1: indices shouldn't match\n");
2700 if (i > 2)
2701 {
2702 ok(memcmp(cd[0].font_idxW, cd[2].font_idxW, 128*sizeof(WORD)), "0 vs 2: indices shouldn't match\n");
2703 ok(memcmp(cd[1].font_idxW, cd[2].font_idxW, 128*sizeof(WORD)), "1 vs 2: indices shouldn't match\n");
2704 }
2705 else
2706 skip("Symbol or Wingdings is not installed\n");
2707}
2708
2709static void test_GdiGetCodePage(void)
2710{
2711 static const struct _matching_data
2712 {
2713 UINT current_codepage;
2714 LPCSTR lfFaceName;
2715 UCHAR lfCharSet;
2716 UINT expected_codepage;
2717 } matching_data[] = {
2718 {1251, "Arial", ANSI_CHARSET, 1252},
2719 {1251, "Tahoma", ANSI_CHARSET, 1252},
2720
2721 {1252, "Arial", ANSI_CHARSET, 1252},
2722 {1252, "Tahoma", ANSI_CHARSET, 1252},
2723
2724 {1253, "Arial", ANSI_CHARSET, 1252},
2725 {1253, "Tahoma", ANSI_CHARSET, 1252},
2726
2727 { 932, "Arial", ANSI_CHARSET, 1252}, /* Japanese Windows returns 1252, not 932 */
2728 { 932, "Tahoma", ANSI_CHARSET, 1252},
2729 { 932, "MS UI Gothic", ANSI_CHARSET, 1252},
2730
2731 { 936, "Arial", ANSI_CHARSET, 936},
2732 { 936, "Tahoma", ANSI_CHARSET, 936},
2733 { 936, "Simsun", ANSI_CHARSET, 936},
2734
2735 { 949, "Arial", ANSI_CHARSET, 949},
2736 { 949, "Tahoma", ANSI_CHARSET, 949},
2737 { 949, "Gulim", ANSI_CHARSET, 949},
2738
2739 { 950, "Arial", ANSI_CHARSET, 950},
2740 { 950, "Tahoma", ANSI_CHARSET, 950},
2741 { 950, "PMingLiU", ANSI_CHARSET, 950},
2742 };
2743 HDC hdc;
2744 LOGFONTA lf;
2745 HFONT hfont;
2746 UINT acp;
2748 int i;
2749
2750 if (!pGdiGetCodePage)
2751 {
2752 win_skip("GdiGetCodePage not available on this platform\n");
2753 return;
2754 }
2755
2756 acp = GetACP();
2757
2758 for (i = 0; i < ARRAY_SIZE(matching_data); i++)
2759 {
2760 /* only test data matched current locale codepage */
2761 if (matching_data[i].current_codepage != acp)
2762 continue;
2763
2764 if (!is_font_installed(matching_data[i].lfFaceName))
2765 {
2766 skip("%s is not installed\n", matching_data[i].lfFaceName);
2767 continue;
2768 }
2769
2770 hdc = GetDC(0);
2771
2772 memset(&lf, 0, sizeof(lf));
2773 lf.lfHeight = -16;
2774 lf.lfCharSet = matching_data[i].lfCharSet;
2775 lstrcpyA(lf.lfFaceName, matching_data[i].lfFaceName);
2777 ok(hfont != 0, "CreateFontIndirectA error %lu\n", GetLastError());
2778
2780 codepage = pGdiGetCodePage(hdc);
2781 ok(codepage == matching_data[i].expected_codepage,
2782 "GdiGetCodePage should have returned %d, got %ld\n", matching_data[i].expected_codepage, codepage);
2783
2786
2787 /* CLIP_DFA_DISABLE turns off the font association */
2790 ok(hfont != 0, "CreateFontIndirectA error %lu\n", GetLastError());
2791
2793 codepage = pGdiGetCodePage(hdc);
2794 ok(codepage == 1252, "GdiGetCodePage returned %ld\n", codepage);
2795
2798
2799 ReleaseDC(NULL, hdc);
2800 }
2801}
2802
2804{
2805 LOGFONTA lf;
2806 HDC hdc;
2807 HFONT hfont, hfont_old;
2808 DWORD size;
2809 GLYPHSET *gs;
2810
2811 memset(&lf, 0, sizeof(lf));
2812 lstrcpyA(lf.lfFaceName, "Arial");
2813 hfont = create_font("Arial", &lf);
2814
2815 hdc = GetDC(0);
2816 hfont_old = SelectObject(hdc, hfont);
2817
2818 size = GetFontUnicodeRanges(NULL, NULL);
2819 ok(!size, "GetFontUnicodeRanges succeeded unexpectedly\n");
2820
2821 size = GetFontUnicodeRanges(hdc, NULL);
2822 ok(size, "GetFontUnicodeRanges failed unexpectedly\n");
2823
2824 gs = calloc(1, size);
2825
2826 size = GetFontUnicodeRanges(hdc, gs);
2827 ok(size, "GetFontUnicodeRanges failed\n");
2828 ok(gs->cRanges, "Unexpected ranges count.\n");
2829
2830 free(gs);
2831
2832 SelectObject(hdc, hfont_old);
2834 ReleaseDC(NULL, hdc);
2835}
2836
2838{
2841};
2842
2844{
2847};
2848
2850{
2853};
2854
2856{
2859};
2860
2862{
2863 struct enum_font_data *efd = (struct enum_font_data *)lParam;
2864 const NEWTEXTMETRICA *ntm = (const NEWTEXTMETRICA *)tm;
2865
2866 ok(lf->lfHeight == tm->tmHeight, "lfHeight %ld != tmHeight %ld\n", lf->lfHeight, tm->tmHeight);
2867
2868 if (type != TRUETYPE_FONTTYPE) return 1;
2869
2870 ok(ntm->ntmCellHeight + ntm->ntmCellHeight/5 >= ntm->ntmSizeEM, "ntmCellHeight %d should be close to ntmSizeEM %d\n", ntm->ntmCellHeight, ntm->ntmSizeEM);
2871
2872 if (efd->total >= efd->size)
2873 {
2874 efd->size = max( (efd->total + 1) * 2, 256 );
2875 efd->lf = realloc( efd->lf, efd->size * sizeof(*efd->lf) );
2876 if (!efd->lf) return 0;
2877 }
2878 efd->lf[efd->total++] = *lf;
2879
2880 return 1;
2881}
2882
2884{
2885 struct enum_font_dataW *efd = (struct enum_font_dataW *)lParam;
2886 const NEWTEXTMETRICW *ntm = (const NEWTEXTMETRICW *)tm;
2887
2888 ok(lf->lfHeight == tm->tmHeight, "lfHeight %ld != tmHeight %ld\n", lf->lfHeight, tm->tmHeight);
2889
2890 if (type != TRUETYPE_FONTTYPE) return 1;
2891
2892 ok(ntm->ntmCellHeight + ntm->ntmCellHeight/5 >= ntm->ntmSizeEM, "ntmCellHeight %d should be close to ntmSizeEM %d\n", ntm->ntmCellHeight, ntm->ntmSizeEM);
2893
2894 if (efd->total >= efd->size)
2895 {
2896 efd->size = max( (efd->total + 1) * 2, 256 );
2897 efd->lf = realloc( efd->lf, efd->size * sizeof(*efd->lf) );
2898 if (!efd->lf) return 0;
2899 }
2900 efd->lf[efd->total++] = *lf;
2901
2902 return 1;
2903}
2904
2905static void get_charset_stats(struct enum_font_data *efd,
2906 int *ansi_charset, int *symbol_charset,
2907 int *russian_charset)
2908{
2909 int i;
2910
2911 *ansi_charset = 0;
2912 *symbol_charset = 0;
2913 *russian_charset = 0;
2914
2915 for (i = 0; i < efd->total; i++)
2916 {
2917 switch (efd->lf[i].lfCharSet)
2918 {
2919 case ANSI_CHARSET:
2920 (*ansi_charset)++;
2921 break;
2922 case SYMBOL_CHARSET:
2923 (*symbol_charset)++;
2924 break;
2925 case RUSSIAN_CHARSET:
2926 (*russian_charset)++;
2927 break;
2928 }
2929 }
2930}
2931
2932static void get_charset_statsW(struct enum_font_dataW *efd,
2933 int *ansi_charset, int *symbol_charset,
2934 int *russian_charset)
2935{
2936 int i;
2937
2938 *ansi_charset = 0;
2939 *symbol_charset = 0;
2940 *russian_charset = 0;
2941
2942 for (i = 0; i < efd->total; i++)
2943 {
2944 switch (efd->lf[i].lfCharSet)
2945 {
2946 case ANSI_CHARSET:
2947 (*ansi_charset)++;
2948 break;
2949 case SYMBOL_CHARSET:
2950 (*symbol_charset)++;
2951 break;
2952 case RUSSIAN_CHARSET:
2953 (*russian_charset)++;
2954 break;
2955 }
2956 }
2957}
2958
2959static void test_EnumFontFamilies(const char *font_name, INT font_charset)
2960{
2961 struct enum_font_data efd;
2962 struct enum_font_dataW efdw;
2963 LOGFONTA lf;
2964 HDC hdc;
2965 int i, ret, ansi_charset, symbol_charset, russian_charset;
2966
2967 if (*font_name && !is_truetype_font_installed(font_name))
2968 {
2969 skip("%s is not installed\n", font_name);
2970 return;
2971 }
2972 memset( &efd, 0, sizeof(efd) );
2973 memset( &efdw, 0, sizeof(efdw) );
2974
2975 hdc = GetDC(0);
2976
2977 /* Observed behaviour: EnumFontFamilies enumerates aliases like "Arial Cyr"
2978 * while EnumFontFamiliesEx doesn't.
2979 */
2980 if (!*font_name && font_charset == DEFAULT_CHARSET) /* do it only once */
2981 {
2982 /*
2983 * Use EnumFontFamiliesW since win98 crashes when the
2984 * second parameter is NULL using EnumFontFamilies
2985 */
2986 efdw.total = 0;
2987 SetLastError(0xdeadbeef);
2989 ok(ret || GetLastError() == ERROR_CALL_NOT_IMPLEMENTED, "EnumFontFamiliesW error %lu\n", GetLastError());
2990 if(ret)
2991 {
2992 get_charset_statsW(&efdw, &ansi_charset, &symbol_charset, &russian_charset);
2993 ok(efdw.total > 0, "fonts enumerated: NULL\n");
2994 ok(ansi_charset > 0, "NULL family should enumerate ANSI_CHARSET\n");
2995 ok(symbol_charset > 0, "NULL family should enumerate SYMBOL_CHARSET\n");
2996 ok(russian_charset > 0, "NULL family should enumerate RUSSIAN_CHARSET\n");
2997 }
2998
2999 efdw.total = 0;
3000 SetLastError(0xdeadbeef);
3002 ok(ret || GetLastError() == ERROR_CALL_NOT_IMPLEMENTED, "EnumFontFamiliesExW error %lu\n", GetLastError());
3003 if(ret)
3004 {
3005 get_charset_statsW(&efdw, &ansi_charset, &symbol_charset, &russian_charset);
3006 ok(efdw.total > 0, "fonts enumerated: NULL\n");
3007 ok(ansi_charset > 0, "NULL family should enumerate ANSI_CHARSET\n");
3008 ok(symbol_charset > 0, "NULL family should enumerate SYMBOL_CHARSET\n");
3009 ok(russian_charset > 0, "NULL family should enumerate RUSSIAN_CHARSET\n");
3010 }
3011 }
3012
3013 efd.total = 0;
3014 SetLastError(0xdeadbeef);
3015 ret = EnumFontFamiliesA(hdc, font_name, arial_enum_proc, (LPARAM)&efd);
3016 ok(ret, "EnumFontFamilies error %lu\n", GetLastError());
3017 get_charset_stats(&efd, &ansi_charset, &symbol_charset, &russian_charset);
3018 if (*font_name)
3019 ok(efd.total > 0, "no fonts enumerated: %s\n", font_name);
3020 else
3021 ok(!efd.total, "no fonts should be enumerated for empty font_name\n");
3022 for (i = 0; i < efd.total; i++)
3023 {
3024 /* FIXME: remove completely once Wine is fixed */
3025 todo_wine_if(efd.lf[i].lfCharSet != font_charset)
3026 ok(efd.lf[i].lfCharSet == font_charset, "%d: got charset %d\n", i, efd.lf[i].lfCharSet);
3027 ok(!strcmp(efd.lf[i].lfFaceName, font_name), "expected %s, got %s\n",
3028 font_name, efd.lf[i].lfFaceName);
3029 }
3030
3031 memset(&lf, 0, sizeof(lf));
3033 strcpy(lf.lfFaceName, font_name);
3034 efd.total = 0;
3035 SetLastError(0xdeadbeef);
3037 ok(ret, "EnumFontFamiliesEx error %lu\n", GetLastError());
3038 get_charset_stats(&efd, &ansi_charset, &symbol_charset, &russian_charset);
3039 if (font_charset == SYMBOL_CHARSET)
3040 {
3041 if (*font_name)
3042 ok(efd.total == 0, "no fonts should be enumerated: %s ANSI_CHARSET\n", font_name);
3043 else
3044 ok(efd.total > 0, "no fonts enumerated: %s\n", font_name);
3045 }
3046 else
3047 {
3048 ok(efd.total > 0, "no fonts enumerated: %s ANSI_CHARSET\n", font_name);
3049 for (i = 0; i < efd.total; i++)
3050 {
3051 ok(efd.lf[i].lfCharSet == ANSI_CHARSET, "%d: got charset %d\n", i, efd.lf[i].lfCharSet);
3052 if (*font_name)
3053 ok(!strcmp(efd.lf[i].lfFaceName, font_name), "expected %s, got %s\n",
3054 font_name, efd.lf[i].lfFaceName);
3055 }
3056 }
3057
3058 /* DEFAULT_CHARSET should enumerate all available charsets */
3059 memset(&lf, 0, sizeof(lf));
3061 strcpy(lf.lfFaceName, font_name);
3062 efd.total = 0;
3063 SetLastError(0xdeadbeef);
3065 ok(ret, "EnumFontFamiliesEx error %lu\n", GetLastError());
3066 get_charset_stats(&efd, &ansi_charset, &symbol_charset, &russian_charset);
3067 ok(efd.total > 0, "no fonts enumerated: %s DEFAULT_CHARSET\n", font_name);
3068 for (i = 0; i < efd.total; i++)
3069 {
3070 if (*font_name)
3071 ok(!strcmp(efd.lf[i].lfFaceName, font_name), "expected %s, got %s\n",
3072 font_name, efd.lf[i].lfFaceName);
3073 }
3074 if (*font_name)
3075 {
3076 switch (font_charset)
3077 {
3078 case ANSI_CHARSET:
3079 ok(ansi_charset > 0,
3080 "ANSI_CHARSET should enumerate ANSI_CHARSET for %s\n", font_name);
3081 ok(!symbol_charset,
3082 "ANSI_CHARSET should NOT enumerate SYMBOL_CHARSET for %s\n", font_name);
3083 ok(russian_charset > 0,
3084 "ANSI_CHARSET should enumerate RUSSIAN_CHARSET for %s\n", font_name);
3085 break;
3086 case SYMBOL_CHARSET:
3087 ok(!ansi_charset,
3088 "SYMBOL_CHARSET should NOT enumerate ANSI_CHARSET for %s\n", font_name);
3089 ok(symbol_charset,
3090 "SYMBOL_CHARSET should enumerate SYMBOL_CHARSET for %s\n", font_name);
3091 ok(!russian_charset,
3092 "SYMBOL_CHARSET should NOT enumerate RUSSIAN_CHARSET for %s\n", font_name);
3093 break;
3094 case DEFAULT_CHARSET:
3095 ok(ansi_charset > 0,
3096 "DEFAULT_CHARSET should enumerate ANSI_CHARSET for %s\n", font_name);
3097 ok(symbol_charset > 0,
3098 "DEFAULT_CHARSET should enumerate SYMBOL_CHARSET for %s\n", font_name);
3099 ok(russian_charset > 0,
3100 "DEFAULT_CHARSET should enumerate RUSSIAN_CHARSET for %s\n", font_name);
3101 break;
3102 }
3103 }
3104 else
3105 {
3106 ok(ansi_charset > 0,
3107 "DEFAULT_CHARSET should enumerate ANSI_CHARSET for %s\n", *font_name ? font_name : "<empty>");
3108 ok(symbol_charset > 0,
3109 "DEFAULT_CHARSET should enumerate SYMBOL_CHARSET for %s\n", *font_name ? font_name : "<empty>");
3110 ok(russian_charset > 0,
3111 "DEFAULT_CHARSET should enumerate RUSSIAN_CHARSET for %s\n", *font_name ? font_name : "<empty>");
3112 }
3113
3114 memset(&lf, 0, sizeof(lf));
3116 strcpy(lf.lfFaceName, font_name);
3117 efd.total = 0;
3118 SetLastError(0xdeadbeef);
3120 ok(ret, "EnumFontFamiliesEx error %lu\n", GetLastError());
3121 get_charset_stats(&efd, &ansi_charset, &symbol_charset, &russian_charset);
3122 if (*font_name && font_charset == ANSI_CHARSET)
3123 ok(efd.total == 0, "no fonts should be enumerated: %s SYMBOL_CHARSET\n", font_name);
3124 else
3125 {
3126 ok(efd.total > 0, "no fonts enumerated: %s SYMBOL_CHARSET\n", font_name);
3127 for (i = 0; i < efd.total; i++)
3128 {
3129 ok(efd.lf[i].lfCharSet == SYMBOL_CHARSET, "%d: got charset %d\n", i, efd.lf[i].lfCharSet);
3130 if (*font_name)
3131 ok(!strcmp(efd.lf[i].lfFaceName, font_name), "expected %s, got %s\n",
3132 font_name, efd.lf[i].lfFaceName);
3133 }
3134
3135 ok(!ansi_charset,
3136 "SYMBOL_CHARSET should NOT enumerate ANSI_CHARSET for %s\n", *font_name ? font_name : "<empty>");
3137 ok(symbol_charset > 0,
3138 "SYMBOL_CHARSET should enumerate SYMBOL_CHARSET for %s\n", *font_name ? font_name : "<empty>");
3139 ok(!russian_charset,
3140 "SYMBOL_CHARSET should NOT enumerate RUSSIAN_CHARSET for %s\n", *font_name ? font_name : "<empty>");
3141 }
3142
3143 ReleaseDC(0, hdc);
3144
3145 free(efd.lf);
3146 free(efdw.lf);
3147}
3148
3150{
3151 const NEWTEXTMETRICEXA *ntm = (const NEWTEXTMETRICEXA *)tm;
3153 const DWORD valid_bits = 0x003f01ff;
3154 CHARSETINFO csi;
3155 DWORD fs;
3156
3157 if (type != TRUETYPE_FONTTYPE) return TRUE;
3158
3159 if (TranslateCharsetInfo(ULongToPtr(target->lfCharSet), &csi, TCI_SRCCHARSET)) {
3160 fs = ntm->ntmFontSig.fsCsb[0] & valid_bits;
3161 if ((fs & csi.fs.fsCsb[0]) && (fs & ~csi.fs.fsCsb[0]) && (fs & FS_LATIN1)) {
3162 *target = *lf;
3163 return FALSE;
3164 }
3165 }
3166
3167 return TRUE;
3168}
3169
3171{
3172 struct enum_font_data *efd = (struct enum_font_data *)lParam;
3173
3174 if (type != TRUETYPE_FONTTYPE) return 1;
3175
3176 if (efd->total >= efd->size)
3177 {
3178 efd->size = max( (efd->total + 1) * 2, 256 );
3179 efd->lf = realloc( efd->lf, efd->size * sizeof(*efd->lf) );
3180 if (!efd->lf) return 0;
3181 }
3182 efd->lf[efd->total++] = *lf;
3183
3184 return 1;
3185}
3186
3188{
3189 struct enum_fullname_data *efnd = (struct enum_fullname_data *)lParam;
3190
3191 if (type != TRUETYPE_FONTTYPE) return 1;
3192
3193 if (efnd->total >= efnd->size)
3194 {
3195 efnd->size = max( (efnd->total + 1) * 2, 256 );
3196 efnd->elf = realloc( efnd->elf, efnd->size * sizeof(*efnd->elf) );
3197 if (!efnd->elf) return 0;
3198 }
3199 efnd->elf[efnd->total++] = *(ENUMLOGFONTA *)lf;
3200
3201 return 1;
3202}
3203
3205{
3206 struct enum_fullname_data_w *efnd = (struct enum_fullname_data_w *)lParam;
3207
3208 if (type != TRUETYPE_FONTTYPE) return 1;
3209
3210 if (efnd->total >= efnd->size)
3211 {
3212 efnd->size = max( (efnd->total + 1) * 2, 256 );
3213 efnd->elf = realloc( efnd->elf, efnd->size * sizeof(*efnd->elf) );
3214 if (!efnd->elf) return 0;
3215 }
3216 efnd->elf[efnd->total++] = *(ENUMLOGFONTW *)lf;
3217
3218 return 1;
3219}
3220
3222{
3223 struct enum_font_data efd;
3224 LOGFONTA target, enum_font;
3225 UINT acp;
3226 HDC hdc;
3227 CHARSETINFO csi;
3228
3229 acp = GetACP();
3231 skip("TranslateCharsetInfo failed for code page %u.\n", acp);
3232 return;
3233 }
3234
3235 hdc = GetDC(0);
3236 memset(&enum_font, 0, sizeof(enum_font));
3237 enum_font.lfCharSet = csi.ciCharset;
3238 target.lfFaceName[0] = '\0';
3239 target.lfCharSet = csi.ciCharset;
3241 if (target.lfFaceName[0] == '\0') {
3242 skip("suitable font isn't found for charset %d.\n", enum_font.lfCharSet);
3243 return;
3244 }
3245 if (acp == 874 || acp == 1255 || acp == 1256) {
3246 /* these codepage use complex script, expecting ANSI_CHARSET here. */
3247 target.lfCharSet = ANSI_CHARSET;
3248 }
3249
3250 memset(&efd, 0, sizeof(efd));
3251 memset(&enum_font, 0, sizeof(enum_font));
3252 strcpy(enum_font.lfFaceName, target.lfFaceName);
3253 enum_font.lfCharSet = DEFAULT_CHARSET;
3254 EnumFontFamiliesExA(hdc, &enum_font, enum_font_data_proc, (LPARAM)&efd, 0);
3255 ReleaseDC(0, hdc);
3256
3257 if (efd.total < 2)
3258 ok(0, "EnumFontFamilies is broken. Expected >= 2, got %d.\n", efd.total);
3259 else
3260 ok(efd.lf[0].lfCharSet == target.lfCharSet,
3261 "(%s) got charset %d expected %d\n",
3262 efd.lf[0].lfFaceName, efd.lf[0].lfCharSet, target.lfCharSet);
3263
3264 free(efd.lf);
3265 return;
3266}
3267
3269{
3270 HFONT hfont, hfont_prev;
3271 DWORD ret;
3272 GLYPHMETRICS gm1, gm2;
3273 LOGFONTA lf2 = *lf;
3274 WORD idx;
3275
3276 /* negative widths are handled just as positive ones */
3277 lf2.lfWidth = -lf->lfWidth;
3278
3279 SetLastError(0xdeadbeef);
3281 ok(hfont != 0, "CreateFontIndirect error %lu\n", GetLastError());
3282 check_font("original", lf, hfont);
3283
3284 hfont_prev = SelectObject(hdc, hfont);
3285
3287 if (ret == GDI_ERROR || idx == 0xffff)
3288 {
3289 SelectObject(hdc, hfont_prev);
3291 skip("Font %s doesn't contain 'x', skipping the test\n", lf->lfFaceName);
3292 return;
3293 }
3294
3295 /* filling with 0xaa causes false pass under WINEDEBUG=warn+heap */
3296 memset(&gm1, 0xab, sizeof(gm1));
3297 SetLastError(0xdeadbeef);
3298 ret = GetGlyphOutlineA(hdc, 'x', GGO_METRICS, &gm1, 0, NULL, &mat);
3299 ok(ret != GDI_ERROR, "GetGlyphOutline error 0x%lx\n", GetLastError());
3300
3301 SelectObject(hdc, hfont_prev);
3303
3304 SetLastError(0xdeadbeef);
3305 hfont = CreateFontIndirectA(&lf2);
3306 ok(hfont != 0, "CreateFontIndirect error %lu\n", GetLastError());
3307 check_font("negative width", &lf2, hfont);
3308
3309 hfont_prev = SelectObject(hdc, hfont);
3310
3311 memset(&gm2, 0xbb, sizeof(gm2));
3312 SetLastError(0xdeadbeef);
3313 ret = GetGlyphOutlineA(hdc, 'x', GGO_METRICS, &gm2, 0, NULL, &mat);
3314 ok(ret != GDI_ERROR, "GetGlyphOutline error 0x%lx\n", GetLastError());
3315
3316 SelectObject(hdc, hfont_prev);
3318
3319 ok(gm1.gmBlackBoxX == gm2.gmBlackBoxX &&
3320 gm1.gmBlackBoxY == gm2.gmBlackBoxY &&
3321 gm1.gmptGlyphOrigin.x == gm2.gmptGlyphOrigin.x &&
3322 gm1.gmptGlyphOrigin.y == gm2.gmptGlyphOrigin.y &&
3323 gm1.gmCellIncX == gm2.gmCellIncX &&
3324 gm1.gmCellIncY == gm2.gmCellIncY,
3325 "gm1=%d,%d,%ld,%ld,%d,%d gm2=%d,%d,%ld,%ld,%d,%d\n",
3327 gm1.gmptGlyphOrigin.y, gm1.gmCellIncX, gm1.gmCellIncY,
3329 gm2.gmptGlyphOrigin.y, gm2.gmCellIncX, gm2.gmCellIncY);
3330}
3331
3332/* PANOSE is 10 bytes in size, need to pack the structure properly */
3333#include "pshpack2.h"
3334typedef struct
3335{
3357 CHAR achVendID[4];
3361 /* According to the Apple spec, original version didn't have the below fields,
3362 * version numbers were taken from the OpenType spec.
3363 */
3364 /* version 0 (TrueType 1.5) */
3370 /* version 1 (TrueType 1.66) */
3373 /* version 2 (OpenType 1.2) */
3379 /* version 4 (OpenType 1.6) */
3382} TT_OS2_V4;
3383#include "poppack.h"
3384
3385#define TT_OS2_V0_SIZE (FIELD_OFFSET(TT_OS2_V4, ulCodePageRange1))
3386
3387typedef struct
3388{
3391} cmap_header;
3392
3393typedef struct
3394{
3399
3400typedef struct
3401{
3405
3406 BYTE glyph_ids[256];
3408
3409typedef struct
3410{
3414
3419
3420 USHORT end_count[1]; /* this is a variable-sized array of length seg_countx2 / 2 */
3421/* Then follows:
3422 USHORT pad;
3423 USHORT start_count[seg_countx2 / 2];
3424 USHORT id_delta[seg_countx2 / 2];
3425 USHORT id_range_offset[seg_countx2 / 2];
3426 USHORT glyph_ids[];
3427*/
3429
3430typedef struct
3431{
3437
3438static void expect_ff(const TEXTMETRICA *tmA, const TT_OS2_V4 *os2, WORD family, const char *name)
3439{
3440 ok((tmA->tmPitchAndFamily & 0xf0) == family ||
3442 "%s: expected family %02x got %02x. panose %d-%d-%d-%d-...\n",
3443 name, family, tmA->tmPitchAndFamily, os2->panose.bFamilyType, os2->panose.bSerifStyle,
3444 os2->panose.bWeight, os2->panose.bProportion);
3445}
3446
3448{
3449 int i;
3451
3452 *first = 256;
3453
3454 for(i = 0; i < 256; i++)
3455 {
3456 if(cmap->glyph_ids[i] == 0) continue;
3457 *last = i;
3458 if(*first == 256) *first = i;
3459 }
3460 if(*first == 256) return FALSE;
3461 return TRUE;
3462}
3463
3464static void get_seg4(cmap_format_4 *cmap, USHORT seg_num, cmap_format_4_seg *seg)
3465{
3466 USHORT segs = GET_BE_WORD(cmap->seg_countx2) / 2;
3467 seg->end_count = GET_BE_WORD(cmap->end_count[seg_num]);
3468 seg->start_count = GET_BE_WORD(cmap->end_count[segs + 1 + seg_num]);
3469 seg->id_delta = GET_BE_WORD(cmap->end_count[2 * segs + 1 + seg_num]);
3470 seg->id_range_offset = GET_BE_WORD(cmap->end_count[3 * segs + 1 + seg_num]);
3471}
3472
3474{
3475 int i;
3477 USHORT seg_count = GET_BE_WORD(cmap->seg_countx2) / 2;
3478
3479 *first = 0x10000;
3480
3481 for(i = 0; i < seg_count; i++)
3482 {
3484
3485 get_seg4(cmap, i, &seg);
3486
3487 if(seg.start_count > 0xfffe) break;
3488
3489 if(*first == 0x10000) *first = seg.start_count;
3490
3491 *last = min(seg.end_count, 0xfffe);
3492 }
3493
3494 if(*first == 0x10000) return FALSE;
3495 return TRUE;
3496}
3497
3498static void *get_cmap(cmap_header *header, USHORT plat_id, USHORT enc_id)
3499{
3500 USHORT i;
3502
3503 for(i = 0; i < GET_BE_WORD(header->num_tables); i++)
3504 {
3505 if(GET_BE_WORD(record->plat_id) == plat_id && GET_BE_WORD(record->enc_id) == enc_id)
3506 return (BYTE *)header + GET_BE_DWORD(record->offset);
3507 record++;
3508 }
3509 return NULL;
3510}
3511
3512typedef enum
3513{
3518
3520{
3521 LONG size, ret;
3523 void *cmap;
3524 BOOL r = FALSE;
3525 WORD format;
3526
3527 size = GetFontData(hdc, MS_CMAP_TAG, 0, NULL, 0);
3528 ok(size != GDI_ERROR, "no cmap table found\n");
3529 if(size == GDI_ERROR) return FALSE;
3530
3531 header = malloc(size);
3533 ok(ret == size, "GetFontData should return %lu not %lu\n", size, ret);
3534 ok(GET_BE_WORD(header->version) == 0, "got cmap version %d\n", GET_BE_WORD(header->version));
3535
3536 cmap = get_cmap(header, 3, 1);
3537 if(cmap)
3539 else
3540 {
3541 cmap = get_cmap(header, 3, 0);
3542 if(cmap) *cmap_type = cmap_ms_symbol;
3543 }
3544 if(!cmap)
3545 {
3547 goto end;
3548 }
3549
3550 format = GET_BE_WORD(*(WORD *)cmap);
3551 switch(format)
3552 {
3553 case 0:
3555 break;
3556 case 4:
3558 break;
3559 default:
3560 skip("unhandled cmap format %d\n", format);
3561 break;
3562 }
3563
3564end:
3565 free(header);
3566 return r;
3567}
3568
3569#define TT_PLATFORM_APPLE_UNICODE 0
3570#define TT_PLATFORM_MACINTOSH 1
3571#define TT_PLATFORM_MICROSOFT 3
3572#define TT_APPLE_ID_DEFAULT 0
3573#define TT_APPLE_ID_ISO_10646 2
3574#define TT_APPLE_ID_UNICODE_2_0 3
3575#define TT_MS_ID_SYMBOL_CS 0
3576#define TT_MS_ID_UNICODE_CS 1
3577#define TT_MS_LANGID_ENGLISH_UNITED_STATES 0x0409
3578#define TT_NAME_ID_FONT_FAMILY 1
3579#define TT_NAME_ID_FONT_SUBFAMILY 2
3580#define TT_NAME_ID_UNIQUE_ID 3
3581#define TT_NAME_ID_FULL_NAME 4
3582#define TT_MAC_ID_SIMPLIFIED_CHINESE 25
3583
3584typedef struct sfnt_name
3585{
3593
3594static const LANGID mac_langid_table[] =
3595{
3596 MAKELANGID(LANG_ENGLISH,SUBLANG_DEFAULT), /* TT_MAC_LANGID_ENGLISH */
3597 MAKELANGID(LANG_FRENCH,SUBLANG_DEFAULT), /* TT_MAC_LANGID_FRENCH */
3598 MAKELANGID(LANG_GERMAN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_GERMAN */
3599 MAKELANGID(LANG_ITALIAN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_ITALIAN */
3600 MAKELANGID(LANG_DUTCH,SUBLANG_DEFAULT), /* TT_MAC_LANGID_DUTCH */
3601 MAKELANGID(LANG_SWEDISH,SUBLANG_DEFAULT), /* TT_MAC_LANGID_SWEDISH */
3602 MAKELANGID(LANG_SPANISH,SUBLANG_DEFAULT), /* TT_MAC_LANGID_SPANISH */
3603 MAKELANGID(LANG_DANISH,SUBLANG_DEFAULT), /* TT_MAC_LANGID_DANISH */
3604 MAKELANGID(LANG_PORTUGUESE,SUBLANG_DEFAULT), /* TT_MAC_LANGID_PORTUGUESE */
3605 MAKELANGID(LANG_NORWEGIAN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_NORWEGIAN */
3606 MAKELANGID(LANG_HEBREW,SUBLANG_DEFAULT), /* TT_MAC_LANGID_HEBREW */
3607 MAKELANGID(LANG_JAPANESE,SUBLANG_DEFAULT), /* TT_MAC_LANGID_JAPANESE */
3608 MAKELANGID(LANG_ARABIC,SUBLANG_DEFAULT), /* TT_MAC_LANGID_ARABIC */
3609 MAKELANGID(LANG_FINNISH,SUBLANG_DEFAULT), /* TT_MAC_LANGID_FINNISH */
3610 MAKELANGID(LANG_GREEK,SUBLANG_DEFAULT), /* TT_MAC_LANGID_GREEK */
3611 MAKELANGID(LANG_ICELANDIC,SUBLANG_DEFAULT), /* TT_MAC_LANGID_ICELANDIC */
3612 MAKELANGID(LANG_MALTESE,SUBLANG_DEFAULT), /* TT_MAC_LANGID_MALTESE */
3613 MAKELANGID(LANG_TURKISH,SUBLANG_DEFAULT), /* TT_MAC_LANGID_TURKISH */
3614 MAKELANGID(LANG_CROATIAN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_CROATIAN */
3615 MAKELANGID(LANG_CHINESE_TRADITIONAL,SUBLANG_DEFAULT), /* TT_MAC_LANGID_CHINESE_TRADITIONAL */
3616 MAKELANGID(LANG_URDU,SUBLANG_DEFAULT), /* TT_MAC_LANGID_URDU */
3617 MAKELANGID(LANG_HINDI,SUBLANG_DEFAULT), /* TT_MAC_LANGID_HINDI */
3618 MAKELANGID(LANG_THAI,SUBLANG_DEFAULT), /* TT_MAC_LANGID_THAI */
3619 MAKELANGID(LANG_KOREAN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_KOREAN */
3620 MAKELANGID(LANG_LITHUANIAN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_LITHUANIAN */
3621 MAKELANGID(LANG_POLISH,SUBLANG_DEFAULT), /* TT_MAC_LANGID_POLISH */
3622 MAKELANGID(LANG_HUNGARIAN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_HUNGARIAN */
3623 MAKELANGID(LANG_ESTONIAN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_ESTONIAN */
3624 MAKELANGID(LANG_LATVIAN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_LETTISH */
3625 MAKELANGID(LANG_SAMI,SUBLANG_DEFAULT), /* TT_MAC_LANGID_SAAMISK */
3626 MAKELANGID(LANG_FAEROESE,SUBLANG_DEFAULT), /* TT_MAC_LANGID_FAEROESE */
3627 MAKELANGID(LANG_FARSI,SUBLANG_DEFAULT), /* TT_MAC_LANGID_FARSI */
3628 MAKELANGID(LANG_RUSSIAN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_RUSSIAN */
3629 MAKELANGID(LANG_CHINESE_SIMPLIFIED,SUBLANG_DEFAULT), /* TT_MAC_LANGID_CHINESE_SIMPLIFIED */
3630 MAKELANGID(LANG_DUTCH,SUBLANG_DUTCH_BELGIAN), /* TT_MAC_LANGID_FLEMISH */
3631 MAKELANGID(LANG_IRISH,SUBLANG_DEFAULT), /* TT_MAC_LANGID_IRISH */
3632 MAKELANGID(LANG_ALBANIAN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_ALBANIAN */
3633 MAKELANGID(LANG_ROMANIAN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_ROMANIAN */
3634 MAKELANGID(LANG_CZECH,SUBLANG_DEFAULT), /* TT_MAC_LANGID_CZECH */
3635 MAKELANGID(LANG_SLOVAK,SUBLANG_DEFAULT), /* TT_MAC_LANGID_SLOVAK */
3636 MAKELANGID(LANG_SLOVENIAN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_SLOVENIAN */
3637 0, /* TT_MAC_LANGID_YIDDISH */
3638 MAKELANGID(LANG_SERBIAN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_SERBIAN */
3639 MAKELANGID(LANG_MACEDONIAN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_MACEDONIAN */
3640 MAKELANGID(LANG_BULGARIAN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_BULGARIAN */
3641 MAKELANGID(LANG_UKRAINIAN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_UKRAINIAN */
3642 MAKELANGID(LANG_BELARUSIAN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_BYELORUSSIAN */
3643 MAKELANGID(LANG_UZBEK,SUBLANG_DEFAULT), /* TT_MAC_LANGID_UZBEK */
3644 MAKELANGID(LANG_KAZAK,SUBLANG_DEFAULT), /* TT_MAC_LANGID_KAZAKH */
3645 MAKELANGID(LANG_AZERI,SUBLANG_AZERI_CYRILLIC), /* TT_MAC_LANGID_AZERBAIJANI */
3646 0, /* TT_MAC_LANGID_AZERBAIJANI_ARABIC_SCRIPT */
3647 MAKELANGID(LANG_ARMENIAN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_ARMENIAN */
3648 MAKELANGID(LANG_GEORGIAN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_GEORGIAN */
3649 0, /* TT_MAC_LANGID_MOLDAVIAN */
3650 MAKELANGID(LANG_KYRGYZ,SUBLANG_DEFAULT), /* TT_MAC_LANGID_KIRGHIZ */
3651 MAKELANGID(LANG_TAJIK,SUBLANG_DEFAULT), /* TT_MAC_LANGID_TAJIKI */
3652 MAKELANGID(LANG_TURKMEN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_TURKMEN */
3653 MAKELANGID(LANG_MONGOLIAN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_MONGOLIAN */
3654 MAKELANGID(LANG_MONGOLIAN,SUBLANG_MONGOLIAN_CYRILLIC_MONGOLIA), /* TT_MAC_LANGID_MONGOLIAN_CYRILLIC_SCRIPT */
3655 MAKELANGID(LANG_PASHTO,SUBLANG_DEFAULT), /* TT_MAC_LANGID_PASHTO */
3656 0, /* TT_MAC_LANGID_KURDISH */
3657 MAKELANGID(LANG_KASHMIRI,SUBLANG_DEFAULT), /* TT_MAC_LANGID_KASHMIRI */
3658 MAKELANGID(LANG_SINDHI,SUBLANG_DEFAULT), /* TT_MAC_LANGID_SINDHI */
3659 MAKELANGID(LANG_TIBETAN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_TIBETAN */
3660 MAKELANGID(LANG_NEPALI,SUBLANG_DEFAULT), /* TT_MAC_LANGID_NEPALI */
3661 MAKELANGID(LANG_SANSKRIT,SUBLANG_DEFAULT), /* TT_MAC_LANGID_SANSKRIT */
3662 MAKELANGID(LANG_MARATHI,SUBLANG_DEFAULT), /* TT_MAC_LANGID_MARATHI */
3663 MAKELANGID(LANG_BENGALI,SUBLANG_DEFAULT), /* TT_MAC_LANGID_BENGALI */
3664 MAKELANGID(LANG_ASSAMESE,SUBLANG_DEFAULT), /* TT_MAC_LANGID_ASSAMESE */
3665 MAKELANGID(LANG_GUJARATI,SUBLANG_DEFAULT), /* TT_MAC_LANGID_GUJARATI */
3666 MAKELANGID(LANG_PUNJABI,SUBLANG_DEFAULT), /* TT_MAC_LANGID_PUNJABI */
3667 MAKELANGID(LANG_ORIYA,SUBLANG_DEFAULT), /* TT_MAC_LANGID_ORIYA */
3668 MAKELANGID(LANG_MALAYALAM,SUBLANG_DEFAULT), /* TT_MAC_LANGID_MALAYALAM */
3669 MAKELANGID(LANG_KANNADA,SUBLANG_DEFAULT), /* TT_MAC_LANGID_KANNADA */
3670 MAKELANGID(LANG_TAMIL,SUBLANG_DEFAULT), /* TT_MAC_LANGID_TAMIL */
3671 MAKELANGID(LANG_TELUGU,SUBLANG_DEFAULT), /* TT_MAC_LANGID_TELUGU */
3672 MAKELANGID(LANG_SINHALESE,SUBLANG_DEFAULT), /* TT_MAC_LANGID_SINHALESE */
3673 0, /* TT_MAC_LANGID_BURMESE */
3674 MAKELANGID(LANG_KHMER,SUBLANG_DEFAULT), /* TT_MAC_LANGID_KHMER */
3675 MAKELANGID(LANG_LAO,SUBLANG_DEFAULT), /* TT_MAC_LANGID_LAO */
3676 MAKELANGID(LANG_VIETNAMESE,SUBLANG_DEFAULT), /* TT_MAC_LANGID_VIETNAMESE */
3677 MAKELANGID(LANG_INDONESIAN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_INDONESIAN */
3678 0, /* TT_MAC_LANGID_TAGALOG */
3679 MAKELANGID(LANG_MALAY,SUBLANG_DEFAULT), /* TT_MAC_LANGID_MALAY_ROMAN_SCRIPT */
3680 0, /* TT_MAC_LANGID_MALAY_ARABIC_SCRIPT */
3681 MAKELANGID(LANG_AMHARIC,SUBLANG_DEFAULT), /* TT_MAC_LANGID_AMHARIC */
3682 MAKELANGID(LANG_TIGRIGNA,SUBLANG_DEFAULT), /* TT_MAC_LANGID_TIGRINYA */
3683 0, /* TT_MAC_LANGID_GALLA */
3684 0, /* TT_MAC_LANGID_SOMALI */
3685 MAKELANGID(LANG_SWAHILI,SUBLANG_DEFAULT), /* TT_MAC_LANGID_SWAHILI */
3686 0, /* TT_MAC_LANGID_RUANDA */
3687 0, /* TT_MAC_LANGID_RUNDI */
3688 0, /* TT_MAC_LANGID_CHEWA */
3689 0, /* TT_MAC_LANGID_MALAGASY */
3690 0, /* TT_MAC_LANGID_ESPERANTO */
3691 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 95-111 */
3692 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 112-127 */
3693 MAKELANGID(LANG_WELSH,SUBLANG_DEFAULT), /* TT_MAC_LANGID_WELSH */
3694 MAKELANGID(LANG_BASQUE,SUBLANG_DEFAULT), /* TT_MAC_LANGID_BASQUE */
3695 MAKELANGID(LANG_CATALAN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_CATALAN */
3696 0, /* TT_MAC_LANGID_LATIN */
3697 MAKELANGID(LANG_QUECHUA,SUBLANG_DEFAULT), /* TT_MAC_LANGID_QUECHUA */
3698 0, /* TT_MAC_LANGID_GUARANI */
3699 0, /* TT_MAC_LANGID_AYMARA */
3700 MAKELANGID(LANG_TATAR,SUBLANG_DEFAULT), /* TT_MAC_LANGID_TATAR */
3701 MAKELANGID(LANG_UIGHUR,SUBLANG_DEFAULT), /* TT_MAC_LANGID_UIGHUR */
3702 0, /* TT_MAC_LANGID_DZONGKHA */
3703 0, /* TT_MAC_LANGID_JAVANESE */
3704 0, /* TT_MAC_LANGID_SUNDANESE */
3705 MAKELANGID(LANG_GALICIAN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_GALICIAN */
3706 MAKELANGID(LANG_AFRIKAANS,SUBLANG_DEFAULT), /* TT_MAC_LANGID_AFRIKAANS */
3707 MAKELANGID(LANG_BRETON,SUBLANG_DEFAULT), /* TT_MAC_LANGID_BRETON */
3708 MAKELANGID(LANG_INUKTITUT,SUBLANG_DEFAULT), /* TT_MAC_LANGID_INUKTITUT */
3709 MAKELANGID(LANG_SCOTTISH_GAELIC,SUBLANG_DEFAULT), /* TT_MAC_LANGID_SCOTTISH_GAELIC */
3710 0, /* TT_MAC_LANGID_MANX_GAELIC */
3711 MAKELANGID(LANG_IRISH,SUBLANG_IRISH_IRELAND), /* TT_MAC_LANGID_IRISH_GAELIC */
3712 0, /* TT_MAC_LANGID_TONGAN */
3713 0, /* TT_MAC_LANGID_GREEK_POLYTONIC */
3714 MAKELANGID(LANG_GREENLANDIC,SUBLANG_DEFAULT), /* TT_MAC_LANGID_GREELANDIC */
3715 MAKELANGID(LANG_AZERI,SUBLANG_AZERI_LATIN), /* TT_MAC_LANGID_AZERBAIJANI_ROMAN_SCRIPT */
3716};
3717
3718static inline WORD get_mac_code_page( const sfnt_name *name )
3719{
3720 if (GET_BE_WORD(name->encoding_id) == TT_MAC_ID_SIMPLIFIED_CHINESE) return 10008; /* special case */
3721 return 10000 + GET_BE_WORD(name->encoding_id);
3722}
3723
3725{
3726 LANGID name_lang;
3727 int res = 0;
3728
3729 switch (GET_BE_WORD(name->platform_id))
3730 {
3732 res += 5; /* prefer the Microsoft name */
3733 switch (GET_BE_WORD(name->encoding_id))
3734 {
3736 case TT_MS_ID_SYMBOL_CS:
3737 name_lang = GET_BE_WORD(name->language_id);
3738 break;
3739 default:
3740 return 0;
3741 }
3742 break;
3744 if (!IsValidCodePage( get_mac_code_page( name ))) return 0;
3745 if (GET_BE_WORD(name->language_id) >= ARRAY_SIZE(mac_langid_table)) return 0;
3746 name_lang = mac_langid_table[GET_BE_WORD(name->language_id)];
3747 break;
3749 res += 2; /* prefer Unicode encodings */
3750 switch (GET_BE_WORD(name->encoding_id))
3751 {
3755 if (GET_BE_WORD(name->language_id) >= ARRAY_SIZE(mac_langid_table)) return 0;
3756 name_lang = mac_langid_table[GET_BE_WORD(name->language_id)];
3757 break;
3758 default:
3759 return 0;
3760 }
3761 break;
3762 default:
3763 return 0;
3764 }
3765 if (name_lang == lang) res += 30;
3766 else if (PRIMARYLANGID( name_lang ) == PRIMARYLANGID( lang )) res += 20;
3767 else if (name_lang == MAKELANGID( LANG_ENGLISH, SUBLANG_DEFAULT )) res += 10;
3768 return res;
3769}
3770
3771static BOOL get_ttf_nametable_entry(HDC hdc, WORD name_id, WCHAR *out_buf, SIZE_T out_size, LCID language_id)
3772{
3773 struct sfnt_name_header
3774 {
3775 USHORT format;
3776 USHORT number_of_record;
3777 USHORT storage_offset;
3778 } *header;
3780 BOOL r = FALSE;
3782 LONG c, ret;
3783 WCHAR *name;
3784 BYTE *data;
3785 USHORT i;
3786 int res, best_lang = 0, best_index = -1;
3787
3788 size = GetFontData(hdc, MS_NAME_TAG, 0, NULL, 0);
3789 ok(size != GDI_ERROR, "no name table found\n");
3790 if(size == GDI_ERROR) return FALSE;
3791
3792 data = malloc(size);
3794 ok(ret == size, "GetFontData should return %lu not %lu\n", size, ret);
3795
3796 header = (void *)data;
3797 header->format = GET_BE_WORD(header->format);
3798 header->number_of_record = GET_BE_WORD(header->number_of_record);
3799 header->storage_offset = GET_BE_WORD(header->storage_offset);
3800 if (header->format != 0)
3801 {
3802 skip("got format %u\n", header->format);
3803 goto out;
3804 }
3805 if (header->number_of_record == 0 || sizeof(*header) + header->number_of_record * sizeof(*entry) > size)
3806 {
3807 skip("number records out of range: %d\n", header->number_of_record);
3808 goto out;
3809 }
3810 if (header->storage_offset >= size)
3811 {
3812 skip("storage_offset %u > size %lu\n", header->storage_offset, size);
3813 goto out;
3814 }
3815
3816 entry = (void *)&header[1];
3817 for (i = 0; i < header->number_of_record; i++)
3818 {
3819 if (GET_BE_WORD(entry[i].name_id) != name_id) continue;
3820 res = match_name_table_language( &entry[i], language_id);
3821 if (res > best_lang)
3822 {
3823 best_lang = res;
3824 best_index = i;
3825 }
3826 }
3827
3828 offset = header->storage_offset + GET_BE_WORD(entry[best_index].offset);
3829 length = GET_BE_WORD(entry[best_index].length);
3830 if (offset + length > size)
3831 {
3832 skip("entry %d is out of range\n", best_index);
3833 goto out;
3834 }
3835 if (length >= out_size)
3836 {
3837 skip("buffer too small for entry %d\n", best_index);
3838 goto out;
3839 }
3840
3841 name = (WCHAR *)(data + offset);
3842 for (c = 0; c < length / 2; c++)
3843 out_buf[c] = GET_BE_WORD(name[c]);
3844 out_buf[c] = 0;
3845
3846 r = TRUE;
3847
3848out:
3849 free(data);
3850 return r;
3851}
3852
3853static void test_text_metrics(const LOGFONTA *lf, const NEWTEXTMETRICA *ntm)
3854{
3855 HDC hdc;
3856 HFONT hfont, hfont_old;
3857 TEXTMETRICA tmA;
3858 TT_OS2_V4 tt_os2;
3859 LONG size, ret;
3860 const char *font_name = lf->lfFaceName;
3861 DWORD cmap_first = 0, cmap_last = 0;
3862 UINT ascent, descent, cell_height;
3864 BOOL sys_lang_non_english;
3865
3866 sys_lang_non_english = PRIMARYLANGID(GetSystemDefaultLangID()) != LANG_ENGLISH;
3867 hdc = GetDC(0);
3868
3869 SetLastError(0xdeadbeef);
3871 ok(hfont != 0, "CreateFontIndirect error %lu\n", GetLastError());
3872
3873 hfont_old = SelectObject(hdc, hfont);
3874
3875 size = GetFontData(hdc, MS_OS2_TAG, 0, NULL, 0);
3876 if (size == GDI_ERROR)
3877 {
3878 trace("OS/2 chunk was not found\n");
3879 goto end_of_test;
3880 }
3881 if (size > sizeof(tt_os2))
3882 {
3883 trace("got too large OS/2 chunk of size %lu\n", size);
3884 size = sizeof(tt_os2);
3885 }
3886
3887 memset(&tt_os2, 0, sizeof(tt_os2));
3888 ret = GetFontData(hdc, MS_OS2_TAG, 0, &tt_os2, size);
3889 ok(ret >= TT_OS2_V0_SIZE && ret <= size, "GetFontData should return size from [%lu,%lu] not %lu\n", TT_OS2_V0_SIZE,
3890 size, ret);
3891
3892 SetLastError(0xdeadbeef);
3893 ret = GetTextMetricsA(hdc, &tmA);
3894 ok(ret, "GetTextMetricsA error %lu\n", GetLastError());
3895
3896 if(!get_first_last_from_cmap(hdc, &cmap_first, &cmap_last, &cmap_type))
3897 {
3898 skip("%s is not a Windows font, OS/2 metrics may be invalid.\n",font_name);
3899 }
3900 else
3901 {
3902 USHORT expect_first_A, expect_last_A, expect_break_A, expect_default_A;
3903 USHORT expect_first_W, expect_last_W, expect_break_W, expect_default_W;
3904 UINT os2_first_char, os2_last_char, default_char, break_char;
3906 TEXTMETRICW tmW;
3907
3908 ascent = GET_BE_WORD(tt_os2.usWinAscent);
3909 descent = abs((SHORT)GET_BE_WORD(tt_os2.usWinDescent));
3910 cell_height = ascent + descent;
3911 ok(ntm->ntmCellHeight == cell_height, "%s: ntmCellHeight %u != %u, os2.usWinAscent/os2.usWinDescent %u/%u\n",
3912 font_name, ntm->ntmCellHeight, cell_height, ascent, descent);
3913
3914 /* NEWTEXTMETRIC's scaling method is different from TEXTMETRIC's */
3915#define SCALE_NTM(value) (MulDiv(ntm->tmHeight, (value), cell_height))
3916 size = MulDiv(32, ntm->ntmCellHeight, ntm->ntmSizeEM);
3917 ok(ntm->tmHeight == size, "%s: ntm->tmHeight %ld != %ld (%u/%u)\n",
3918 font_name, ntm->tmHeight, size, ntm->ntmCellHeight, ntm->ntmSizeEM);
3919 size = SCALE_NTM(ntm->ntmAvgWidth);
3920 ok(ntm->tmAveCharWidth == size, "%s: ntm->tmAveCharWidth %ld != %ld (%u/%u,%ld)\n",
3921 font_name, ntm->tmAveCharWidth, size, ntm->ntmAvgWidth, cell_height, ntm->tmHeight);
3922 size = SCALE_NTM(ascent);
3923 ok(ntm->tmAscent == size, "%s: ntm->tmAscent %ld != %ld (%u/%u,%ld)\n",
3924 font_name, ntm->tmAscent, size, ascent, cell_height, ntm->tmHeight);
3925 size = ntm->tmHeight - ntm->tmAscent;
3926 ok(ntm->tmDescent == size, "%s: ntm->tmDescent %ld != %ld (%u/%u,%ld)\n",
3927 font_name, ntm->tmDescent, size, descent, cell_height, ntm->tmHeight);
3928 size = SCALE_NTM(cell_height - ntm->ntmSizeEM);
3929 ok(ntm->tmInternalLeading == size, "%s: ntm->tmInternalLeading %ld != %ld (%u/%u,%ld)\n",
3930 font_name, ntm->tmInternalLeading, size, cell_height - ntm->ntmSizeEM, cell_height, ntm->tmHeight);
3931#undef SCALE_NTM
3932
3933 version = GET_BE_WORD(tt_os2.version);
3934
3935 os2_first_char = GET_BE_WORD(tt_os2.usFirstCharIndex);
3936 os2_last_char = GET_BE_WORD(tt_os2.usLastCharIndex);
3937 default_char = GET_BE_WORD(tt_os2.usDefaultChar);
3938 break_char = GET_BE_WORD(tt_os2.usBreakChar);
3939
3940 if (winetest_debug > 1)
3941 trace("font %s charset %u: %x-%x (%lx-%lx) default %x break %x OS/2 version %u vendor %4.4s\n",
3942 font_name, lf->lfCharSet, os2_first_char, os2_last_char, cmap_first, cmap_last,
3943 default_char, break_char, version, (LPCSTR)&tt_os2.achVendID);
3944
3945 if (cmap_type == cmap_ms_symbol || (cmap_first >= 0xf000 && cmap_first < 0xf100))
3946 {
3947 expect_first_W = 0;
3948 switch(GetACP())
3949 {
3950 case 1255: /* Hebrew */
3951 expect_last_W = 0xf896;
3952 break;
3953 case 1257: /* Baltic */
3954 expect_last_W = 0xf8fd;
3955 break;
3956 default:
3957 expect_last_W = 0xf0ff;
3958 }
3959 expect_break_W = 0x20;
3960 expect_default_W = expect_break_W - 1;
3961 expect_first_A = 0x1e;
3962 expect_last_A = min(os2_last_char - os2_first_char + 0x20, 0xff);
3963 }
3964 else
3965 {
3966 expect_first_W = cmap_first;
3967 expect_last_W = cmap_last;
3968 if(os2_first_char <= 1)
3969 expect_break_W = os2_first_char + 2;
3970 else if(os2_first_char > 0xff)
3971 expect_break_W = 0x20;
3972 else
3973 expect_break_W = os2_first_char;
3974 expect_default_W = expect_break_W - 1;
3975 expect_first_A = expect_default_W - 1;
3976 expect_last_A = min(os2_last_char, 0xff);
3977 }
3978 expect_break_A = expect_break_W;
3979 expect_default_A = expect_default_W;
3980
3981 /* Wine currently uses SYMBOL_CHARSET to identify whether the ANSI metrics need special handling */
3982 todo_wine_if(cmap_type != cmap_ms_symbol && tmA.tmCharSet == SYMBOL_CHARSET && expect_first_A != 0x1e)
3983 ok(tmA.tmFirstChar == expect_first_A,
3984 "A: tmFirstChar for %s got %02x expected %02x\n", font_name, tmA.tmFirstChar, expect_first_A);
3985 if (pGdiGetCodePage == NULL || ! IsDBCSLeadByteEx(pGdiGetCodePage(hdc), tmA.tmLastChar))
3986 todo_wine_if(expect_last_A != 0 && expect_last_A != 0xff) ok(tmA.tmLastChar == expect_last_A,
3987 "A: tmLastChar for %s got %02x expected %02x\n", font_name, tmA.tmLastChar, expect_last_A);
3988 else
3989 skip("tmLastChar is DBCS lead byte\n");
3990 ok(tmA.tmBreakChar == expect_break_A, "A: tmBreakChar for %s got %02x expected %02x\n",
3991 font_name, tmA.tmBreakChar, expect_break_A);
3992 ok(tmA.tmDefaultChar == expect_default_A || broken(sys_lang_non_english),
3993 "A: tmDefaultChar for %s got %02x expected %02x\n",
3994 font_name, tmA.tmDefaultChar, expect_default_A);
3995
3996
3997 SetLastError(0xdeadbeef);
3998 ret = GetTextMetricsW(hdc, &tmW);
4000 "GetTextMetricsW error %lu\n", GetLastError());
4001 if (ret)
4002 {
4003 /* Wine uses the os2 first char */
4004 todo_wine_if(cmap_first != os2_first_char && cmap_type != cmap_ms_symbol)
4005 ok(tmW.tmFirstChar == expect_first_W, "W: tmFirstChar for %s got %02x expected %02x\n",
4006 font_name, tmW.tmFirstChar, expect_first_W);
4007
4008 /* Wine uses the os2 last char */
4009 todo_wine_if(expect_last_W != os2_last_char && cmap_type != cmap_ms_symbol)
4010 ok(tmW.tmLastChar == expect_last_W, "W: tmLastChar for %s got %02x expected %02x\n",
4011 font_name, tmW.tmLastChar, expect_last_W);
4012 ok(tmW.tmBreakChar == expect_break_W, "W: tmBreakChar for %s got %02x expected %02x\n",
4013 font_name, tmW.tmBreakChar, expect_break_W);
4014 ok(tmW.tmDefaultChar == expect_default_W || broken(sys_lang_non_english),
4015 "W: tmDefaultChar for %s got %02x expected %02x\n",
4016 font_name, tmW.tmDefaultChar, expect_default_W);
4017
4018 /* Test the aspect ratio while we have tmW */
4020 ok(tmW.tmDigitizedAspectX == ret, "W: tmDigitizedAspectX %lu != %lu\n",
4021 tmW.tmDigitizedAspectX, ret);
4023 ok(tmW.tmDigitizedAspectX == ret, "W: tmDigitizedAspectY %lu != %lu\n",
4024 tmW.tmDigitizedAspectX, ret);
4025 }
4026 }
4027
4028 /* test FF_ values */
4029 switch(tt_os2.panose.bFamilyType)
4030 {
4031 case PAN_ANY:
4032 case PAN_NO_FIT:
4035 default:
4036 if((tmA.tmPitchAndFamily & 1) == 0 || /* fixed */
4038 {
4039 expect_ff(&tmA, &tt_os2, FF_MODERN, font_name);
4040 break;
4041 }
4042 switch(tt_os2.panose.bSerifStyle)
4043 {
4044 case PAN_ANY:
4045 case PAN_NO_FIT:
4046 default:
4047 expect_ff(&tmA, &tt_os2, FF_DONTCARE, font_name);
4048 break;
4049
4050 case PAN_SERIF_COVE:
4054 case PAN_SERIF_SQUARE:
4055 case PAN_SERIF_THIN:
4056 case PAN_SERIF_BONE:
4058 case PAN_SERIF_TRIANGLE:
4059 expect_ff(&tmA, &tt_os2, FF_ROMAN, font_name);
4060 break;
4061
4065 case PAN_SERIF_FLARED:
4066 case PAN_SERIF_ROUNDED:
4067 expect_ff(&tmA, &tt_os2, FF_SWISS, font_name);
4068 break;
4069 }
4070 break;
4071
4072 case PAN_FAMILY_SCRIPT:
4073 expect_ff(&tmA, &tt_os2, FF_SCRIPT, font_name);
4074 break;
4075
4077 expect_ff(&tmA, &tt_os2, FF_DECORATIVE, font_name);
4078 break;
4079 }
4080
4082
4083end_of_test:
4084 SelectObject(hdc, hfont_old);
4086
4087 ReleaseDC(0, hdc);
4088}
4089
4091{
4092 INT *enumed = (INT *)lParam;
4093
4094 if (type == TRUETYPE_FONTTYPE)
4095 {
4096 (*enumed)++;
4097 test_text_metrics(lf, (const NEWTEXTMETRICA *)ntm);
4098 }
4099 return 1;
4100}
4101
4102static void test_GetTextMetrics(void)
4103{
4104 HFONT old_hf, hf;
4106 LOGFONTA lf;
4107 BOOL ret;
4108 HDC hdc;
4109 INT enumed;
4110
4111 hdc = GetDC(0);
4112
4113 memset(&lf, 0, sizeof(lf));
4115 enumed = 0;
4117
4118 /* Test a bug triggered by rounding up FreeType ppem */
4119 hf = CreateFontA(20, 0, 0, 0, FW_REGULAR, FALSE, FALSE, FALSE, DEFAULT_CHARSET,
4121 "Tahoma");
4122 ok(hf != NULL, "CreateFontA failed, error %lu\n", GetLastError());
4123 old_hf = SelectObject(hdc, hf);
4125 ok(ret, "GetTextMetricsA failed, error %lu\n", GetLastError());
4126 ok(tm.tmHeight <= 20, "Got unexpected tmHeight %ld\n", tm.tmHeight);
4127 SelectObject(hdc, old_hf);
4128 DeleteObject(hf);
4129
4130 ReleaseDC(0, hdc);
4131}
4132
4133static void test_nonexistent_font(void)
4134{
4135 static const struct
4136 {
4137 const char *name;
4138 int charset;
4139 } font_subst[] =
4140 {
4141 { "Times New Roman Baltic", 186 },
4142 { "Times New Roman CE", 238 },
4143 { "Times New Roman CYR", 204 },
4144 { "Times New Roman Greek", 161 },
4145 { "Times New Roman TUR", 162 }
4146 };
4147 static const struct
4148 {
4149 const char *name;
4150 int charset;
4151 } shell_subst[] =
4152 {
4153 { "MS Shell Dlg", 186 },
4154 { "MS Shell Dlg", 238 },
4155 { "MS Shell Dlg", 204 },
4156 { "MS Shell Dlg", 161 },
4157 { "MS Shell Dlg", 162 }
4158 };
4159 LOGFONTA lf;
4160 HDC hdc;
4161 HFONT hfont;
4162 CHARSETINFO csi;
4163 INT cs, expected_cs, i, ret;
4164 char buf[LF_FACESIZE];
4165
4166 expected_cs = GetACP();
4167 if (!TranslateCharsetInfo(ULongToPtr(expected_cs), &csi, TCI_SRCCODEPAGE))
4168 {
4169 skip("TranslateCharsetInfo failed for code page %d\n", expected_cs);
4170 return;
4171 }
4172 expected_cs = csi.ciCharset;
4173 trace("ACP %d -> charset %d\n", GetACP(), expected_cs);
4174
4176
4177 for (i = 0; i < ARRAY_SIZE(shell_subst); i++)
4178 {
4179 ret = is_font_installed(shell_subst[i].name);
4180 ok(ret, "%s should be enumerated\n", shell_subst[i].name);
4181 ret = is_truetype_font_installed(shell_subst[i].name);
4182 ok(ret, "%s should be enumerated\n", shell_subst[i].name);
4183
4184 memset(&lf, 0, sizeof(lf));
4185 lf.lfHeight = -13;
4186 lf.lfWeight = FW_REGULAR;
4187 strcpy(lf.lfFaceName, shell_subst[i].name);
4190 GetTextFaceA(hdc, sizeof(buf), buf);
4191 ok(!lstrcmpiA(buf, shell_subst[i].name), "expected %s, got %s\n", shell_subst[i].name, buf);
4193 ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d for font %s\n", cs, shell_subst[i].name);
4194
4196
4197 memset(&lf, 0, sizeof(lf));
4198 lf.lfHeight = -13;
4199 lf.lfWeight = FW_DONTCARE;
4200 strcpy(lf.lfFaceName, shell_subst[i].name);
4203 GetTextFaceA(hdc, sizeof(buf), buf);
4204 ok(!lstrcmpiA(buf, shell_subst[i].name), "expected %s, got %s\n", shell_subst[i].name, buf);
4206 ok(cs == expected_cs || cs == ANSI_CHARSET, "expected %d, got %d for font %s\n", expected_cs, cs, shell_subst[i].name);
4208 }
4209
4210 if (!is_truetype_font_installed("Arial") ||
4211 !is_truetype_font_installed("Times New Roman"))
4212 {
4213 DeleteDC(hdc);
4214 skip("Arial or Times New Roman not installed\n");
4215 return;
4216 }
4217
4218 memset(&lf, 0, sizeof(lf));
4219 lf.lfHeight = 100;
4220 lf.lfWeight = FW_REGULAR;
4223 strcpy(lf.lfFaceName, "Nonexistent font");
4226 GetTextFaceA(hdc, sizeof(buf), buf);
4227 ok(!lstrcmpiA(buf, "Arial"), "Got %s\n", buf);
4229 ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d\n", cs);
4231
4232 memset(&lf, 0, sizeof(lf));
4233 lf.lfHeight = -13;
4234 lf.lfWeight = FW_DONTCARE;
4235 strcpy(lf.lfFaceName, "Nonexistent font");
4238 GetTextFaceA(hdc, sizeof(buf), buf);
4239 todo_wine /* Wine uses Arial for all substitutions */
4240 ok(!lstrcmpiA(buf, "Nonexistent font") /* XP, Vista */ ||
4241 !lstrcmpiA(buf, "MS Sans Serif"), /* win2k3 */
4242 "Got %s\n", buf);
4244 ok(cs == expected_cs || cs == ANSI_CHARSET, "expected %d, got %d\n", expected_cs, cs);
4246
4247 memset(&lf, 0, sizeof(lf));
4248 lf.lfHeight = -13;
4249 lf.lfWeight = FW_REGULAR;
4250 strcpy(lf.lfFaceName, "Nonexistent font");
4253 GetTextFaceA(hdc, sizeof(buf), buf);
4254 ok(!lstrcmpiA(buf, "Arial"), "Got %s\n", buf);
4256 ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d\n", cs);
4258
4259 memset(&lf, 0, sizeof(lf));
4260 lf.lfHeight = -13;
4261 lf.lfWeight = FW_DONTCARE;
4262 strcpy(lf.lfFaceName, "Times New Roman");
4265 GetTextFaceA(hdc, sizeof(buf), buf);
4266 ok(!lstrcmpiA(buf, "Times New Roman"), "Got %s\n", buf);
4268 ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d\n", cs);
4270
4271 for (i = 0; i < ARRAY_SIZE(font_subst); i++)
4272 {
4273 ret = is_font_installed(font_subst[i].name);
4274 todo_wine
4275 ok(ret, "%s should be enumerated\n", font_subst[i].name);
4276 ret = is_truetype_font_installed(font_subst[i].name);
4277 todo_wine
4278 ok(ret, "%s should be enumerated\n", font_subst[i].name);
4279
4280 memset(&lf, 0, sizeof(lf));
4281 lf.lfHeight = -13;
4282 lf.lfWeight = FW_REGULAR;
4283 strcpy(lf.lfFaceName, font_subst[i].name);
4287 if (font_subst[i].charset == expected_cs)
4288 {
4289 ok(cs == expected_cs, "expected %d, got %d for font %s\n", expected_cs, cs, font_subst[i].name);
4290 GetTextFaceA(hdc, sizeof(buf), buf);
4291 ok(!lstrcmpiA(buf, font_subst[i].name), "expected %s, got %s\n", font_subst[i].name, buf);
4292 }
4293 else
4294 {
4295 ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d for font %s\n", cs, font_subst[i].name);
4296 GetTextFaceA(hdc, sizeof(buf), buf);
4297 ok(!lstrcmpiA(buf, "Arial"), "got %s for font %s\n", buf, font_subst[i].name);
4298 }
4300
4301 memset(&lf, 0, sizeof(lf));
4302 lf.lfHeight = -13;
4303 lf.lfWeight = FW_DONTCARE;
4304 strcpy(lf.lfFaceName, font_subst[i].name);
4307 GetTextFaceA(hdc, sizeof(buf), buf);
4308 ok(!lstrcmpiA(buf, "Arial") /* Wine */ ||
4309 !lstrcmpiA(buf, font_subst[i].name) /* XP, Vista */ ||
4310 !lstrcmpiA(buf, "MS Sans Serif"), /* win2k3 */
4311 "got %s for font %s\n", buf, font_subst[i].name);
4313 ok(cs == expected_cs || cs == ANSI_CHARSET, "expected %d, got %d for font %s\n", expected_cs, cs, font_subst[i].name);
4315 }
4316
4317 DeleteDC(hdc);
4318}
4319
4321{
4329};
4330
4332{
4336};
4337
4338static void test_RealizationInfo(void)
4339{
4340 struct realization_info_t
4341 {
4342 DWORD flags;
4343 DWORD cache_num;
4344 DWORD instance_id;
4345 };
4346
4347 struct file_info file_info;
4348 HDC hdc;
4349 DWORD info[4], info2[32], read;
4350 HFONT hfont, hfont_old;
4351 SIZE_T needed;
4352 LOGFONTA lf;
4353 HANDLE h;
4354 BYTE file[16], data[14];
4355 FILETIME time;
4357 BOOL r;
4358
4359 if(!pGdiRealizationInfo)
4360 {
4361 win_skip("GdiRealizationInfo not available\n");
4362 return;
4363 }
4364
4365 hdc = GetDC(0);
4366
4367 memset(info, 0xcc, sizeof(info));
4368 r = pGdiRealizationInfo(hdc, info);
4369 ok(r != 0, "ret 0\n");
4370 ok((info[0] & 0xf) == 1, "info[0] = %lx for the system font\n", info[0]);
4371 ok(info[3] == 0xcccccccc, "structure longer than 3 dwords\n");
4372
4373 if (!is_truetype_font_installed("Tahoma"))
4374 {
4375 skip("skipping GdiRealizationInfo with truetype font\n");
4376 goto end;
4377 }
4378
4379 memset(&lf, 0, sizeof(lf));
4380 strcpy(lf.lfFaceName, "Tahoma");
4381 lf.lfHeight = 20;
4382 lf.lfWeight = FW_BOLD;
4383 lf.lfItalic = 1;
4385 hfont_old = SelectObject(hdc, hfont);
4386
4387 memset(info, 0xcc, sizeof(info));
4388 r = pGdiRealizationInfo(hdc, info);
4389 ok(r != 0, "ret 0\n");
4390 ok((info[0] & 0xf) == 3, "info[0] = %lx for arial\n", info[0]);
4391 ok(info[3] == 0xcccccccc, "structure longer than 3 dwords\n");
4392
4393 if (pGetFontRealizationInfo)
4394 {
4395 struct font_realization_info *fri = (struct font_realization_info*)info2;
4396 struct realization_info_t *ri = (struct realization_info_t*)info;
4397
4398 /* The first DWORD represents a struct size. On a
4399 newly rebooted system setting this to < 16 results
4400 in GetFontRealizationInfo failing. However there
4401 appears to be some caching going on which results
4402 in calls after a successful call also succeeding even
4403 if the size < 16. This means we can't reliably test
4404 this behaviour. */
4405
4406 memset(info2, 0xcc, sizeof(info2));
4407 info2[0] = 16;
4408 r = pGetFontRealizationInfo(hdc, info2);
4409 ok(r != 0, "ret 0\n");
4410 /* We may get the '24' version here if that has been previously
4411 requested. */
4412 ok(fri->size == 16 || fri->size == 24, "got %ld\n", info2[0]);
4413 ok(fri->flags == ri->flags, "flags mismatch\n");
4414 ok(fri->cache_num == ri->cache_num, "cache_num mismatch\n");
4415 ok(fri->instance_id == ri->instance_id, "instance id mismatch\n");
4416 ok(info2[6] == 0xcccccccc, "got wrong dword 6, 0x%08lx\n", info2[6]);
4417
4418 memset(info2, 0xcc, sizeof(info2));
4419 info2[0] = 28;
4420 r = pGetFontRealizationInfo(hdc, info2);
4421 ok(r == FALSE, "got %d\n", r);
4422
4423 memset(info2, 0xcc, sizeof(info2));
4424 info2[0] = 24;
4425 r = pGetFontRealizationInfo(hdc, info2);
4426 ok(r != 0, "ret 0\n");
4427 ok(fri->size == 24, "got %ld\n", fri->size);
4428 ok(fri->flags == ri->flags, "flags mismatch\n");
4429 ok(fri->cache_num == ri->cache_num, "cache_num mismatch\n");
4430 ok(fri->instance_id == ri->instance_id, "instance id mismatch\n");
4431 ok(fri->simulations == 0x2, "got simulations flags 0x%04x\n", fri->simulations);
4432 ok(fri->face_index == 0, "got wrong face index %u\n", fri->face_index);
4433 ok(info2[6] == 0xcccccccc, "structure longer than 6 dwords\n");
4434
4435 /* Test GetFontFileInfo() */
4436 /* invalid font id */
4437 SetLastError(0xdeadbeef);
4438 r = pGetFontFileInfo(0xabababab, 0, &file_info, sizeof(file_info), &needed);
4439 ok(r == 0 && GetLastError() == ERROR_INVALID_PARAMETER, "ret %d gle %ld\n", r, GetLastError());
4440
4441 needed = 0;
4442 r = pGetFontFileInfo(fri->instance_id, 0, &file_info, sizeof(file_info), &needed);
4443 ok(r != 0, "Failed to get font file info, error %ld.\n", GetLastError());
4444
4445 if (r)
4446 {
4447 ok(needed > 0 && needed < sizeof(file_info), "Unexpected required size.\n");
4448
4450 ok(h != INVALID_HANDLE_VALUE, "Unable to open file %ld\n", GetLastError());
4451
4452 GetFileTime(h, NULL, NULL, &time);
4453 ok(!CompareFileTime(&file_info.time, &time), "time mismatch\n");
4454 GetFileSizeEx(h, &size);
4455 ok(file_info.size.QuadPart == size.QuadPart, "size mismatch\n");
4456
4457 /* Read first 16 bytes from the file */
4458 ReadFile(h, file, sizeof(file), &read, NULL);
4459 CloseHandle(h);
4460
4461 /* shorter buffer */
4462 SetLastError(0xdeadbeef);
4463 r = pGetFontFileInfo(fri->instance_id, 0, &file_info, needed - 1, &needed);
4464 ok(r == 0 && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "ret %d gle %ld\n", r, GetLastError());
4465 }
4466
4467 /* Get bytes 2 - 16 using GetFontFileData */
4468 r = pGetFontFileData(fri->instance_id, 0, 2, data, sizeof(data));
4469 ok(r != 0, "ret 0 gle %ld\n", GetLastError());
4470
4471 ok(!memcmp(data, file + 2, sizeof(data)), "mismatch\n");
4472 }
4473
4474 DeleteObject(SelectObject(hdc, hfont_old));
4475
4476 end:
4477 ReleaseDC(0, hdc);
4478}
4479
4480/* Tests on XP SP2 show that the ANSI version of GetTextFace does NOT include
4481 the nul in the count of characters copied when the face name buffer is not
4482 NULL, whereas it does if the buffer is NULL. Further, the Unicode version
4483 always includes it. */
4484static void test_GetTextFace(void)
4485{
4486 static const char faceA[] = "Tahoma";
4487 static const WCHAR faceW[] = L"Tahoma";
4488 LOGFONTA fA = {0};
4489 LOGFONTW fW = {0};
4490 char bufA[LF_FACESIZE];
4491 WCHAR bufW[LF_FACESIZE];
4492 HFONT f, g;
4493 HDC dc;
4494 int n;
4495
4496 if(!is_font_installed("Tahoma"))
4497 {
4498 skip("Tahoma is not installed so skipping this test\n");
4499 return;
4500 }
4501
4502 /* 'A' case. */
4503 memcpy(fA.lfFaceName, faceA, sizeof faceA);
4504 f = CreateFontIndirectA(&fA);
4505 ok(f != NULL, "CreateFontIndirectA failed\n");
4506
4507 dc = GetDC(NULL);
4508 g = SelectObject(dc, f);
4509 n = GetTextFaceA(dc, sizeof bufA, bufA);
4510 ok(n == sizeof faceA - 1, "GetTextFaceA returned %d\n", n);
4511 ok(lstrcmpA(faceA, bufA) == 0, "GetTextFaceA\n");
4512
4513 /* Play with the count arg. */
4514 bufA[0] = 'x';
4515 n = GetTextFaceA(dc, 0, bufA);
4516 ok(n == 0, "GetTextFaceA returned %d\n", n);
4517 ok(bufA[0] == 'x', "GetTextFaceA buf[0] == %d\n", bufA[0]);
4518
4519 bufA[0] = 'x';
4520 n = GetTextFaceA(dc, 1, bufA);
4521 ok(n == 0, "GetTextFaceA returned %d\n", n);
4522 ok(bufA[0] == '\0', "GetTextFaceA buf[0] == %d\n", bufA[0]);
4523
4524 bufA[0] = 'x'; bufA[1] = 'y';
4525 n = GetTextFaceA(dc, 2, bufA);
4526 ok(n == 1, "GetTextFaceA returned %d\n", n);
4527 ok(bufA[0] == faceA[0] && bufA[1] == '\0', "GetTextFaceA didn't copy\n");
4528
4529 n = GetTextFaceA(dc, 0, NULL);
4530 ok(n == sizeof faceA, "GetTextFaceA returned %d\n", n);
4531
4533 ReleaseDC(NULL, dc);
4534
4535 /* 'W' case. */
4536 memcpy(fW.lfFaceName, faceW, sizeof faceW);
4537 SetLastError(0xdeadbeef);
4538 f = CreateFontIndirectW(&fW);
4540 {
4541 win_skip("CreateFontIndirectW is not implemented\n");
4542 return;
4543 }
4544 ok(f != NULL, "CreateFontIndirectW failed\n");
4545
4546 dc = GetDC(NULL);
4547 g = SelectObject(dc, f);
4548 n = GetTextFaceW(dc, ARRAY_SIZE(bufW), bufW);
4549 ok(n == ARRAY_SIZE(faceW), "GetTextFaceW returned %d\n", n);
4550 ok(lstrcmpW(faceW, bufW) == 0, "GetTextFaceW\n");
4551
4552 /* Play with the count arg. */
4553 bufW[0] = 'x';
4554 n = GetTextFaceW(dc, 0, bufW);
4555 ok(n == 0, "GetTextFaceW returned %d\n", n);
4556 ok(bufW[0] == 'x', "GetTextFaceW buf[0] == %d\n", bufW[0]);
4557
4558 bufW[0] = 'x';
4559 n = GetTextFaceW(dc, 1, bufW);
4560 ok(n == 1, "GetTextFaceW returned %d\n", n);
4561 ok(bufW[0] == '\0', "GetTextFaceW buf[0] == %d\n", bufW[0]);
4562
4563 bufW[0] = 'x'; bufW[1] = 'y';
4564 n = GetTextFaceW(dc, 2, bufW);
4565 ok(n == 2, "GetTextFaceW returned %d\n", n);
4566 ok(bufW[0] == faceW[0] && bufW[1] == '\0', "GetTextFaceW didn't copy\n");
4567
4568 n = GetTextFaceW(dc, 0, NULL);
4569 ok(n == ARRAY_SIZE(faceW), "GetTextFaceW returned %d\n", n);
4570
4572 ReleaseDC(NULL, dc);
4573}
4574
4575static void test_orientation(void)
4576{
4577 static const char test_str[11] = "Test String";
4578 HDC hdc;
4579 LOGFONTA lf;
4580 HFONT hfont, old_hfont;
4581 SIZE size;
4582
4583 if (!is_truetype_font_installed("Arial"))
4584 {
4585 skip("Arial is not installed\n");
4586 return;
4587 }
4588
4590 memset(&lf, 0, sizeof(lf));
4591 lstrcpyA(lf.lfFaceName, "Arial");
4592 lf.lfHeight = 72;
4593 lf.lfOrientation = lf.lfEscapement = 900;
4594 hfont = create_font("orientation", &lf);
4595 old_hfont = SelectObject(hdc, hfont);
4596 ok(GetTextExtentExPointA(hdc, test_str, sizeof(test_str), 32767, NULL, NULL, &size), "GetTextExtentExPointA failed\n");
4597 ok(near_match(311, size.cx), "cx should be about 311, got %ld\n", size.cx);
4598 ok(near_match(75, size.cy), "cy should be about 75, got %ld\n", size.cy);
4599 SelectObject(hdc, old_hfont);
4601 DeleteDC(hdc);
4602}
4603
4604static void test_oemcharset(void)
4605{
4606 HDC hdc;
4607 LOGFONTA lf, clf;
4608 HFONT hfont, old_hfont;
4609 int charset;
4610
4612 ZeroMemory(&lf, sizeof(lf));
4613 lf.lfHeight = 12;
4616 lstrcpyA(lf.lfFaceName, "Terminal");
4618 old_hfont = SelectObject(hdc, hfont);
4620 todo_wine
4621 ok(charset == OEM_CHARSET, "expected %d charset, got %d\n", OEM_CHARSET, charset);
4622 hfont = SelectObject(hdc, old_hfont);
4623 GetObjectA(hfont, sizeof(clf), &clf);
4624 ok(!lstrcmpA(clf.lfFaceName, lf.lfFaceName), "expected %s face name, got %s\n", lf.lfFaceName, clf.lfFaceName);
4625 ok(clf.lfPitchAndFamily == lf.lfPitchAndFamily, "expected %x family, got %x\n", lf.lfPitchAndFamily, clf.lfPitchAndFamily);
4626 ok(clf.lfCharSet == lf.lfCharSet, "expected %d charset, got %d\n", lf.lfCharSet, clf.lfCharSet);
4627 ok(clf.lfHeight == lf.lfHeight, "expected %ld height, got %ld\n", lf.lfHeight, clf.lfHeight);
4629 DeleteDC(hdc);
4630}
4631
4633 const TEXTMETRICA *lpntme,
4634 DWORD FontType, LPARAM lParam)
4635{
4636 const NEWTEXTMETRICEXA *lpntmex = (const NEWTEXTMETRICEXA *)lpntme;
4637 CHARSETINFO csi;
4638 LOGFONTA lf = *lpelfe;
4639 HFONT hfont;
4640 DWORD found_subset;
4641
4642 /* skip bitmap, proportional or vertical font */
4643 if ((FontType & TRUETYPE_FONTTYPE) == 0 ||
4644 (lf.lfPitchAndFamily & 0xf) != FIXED_PITCH ||
4645 lf.lfFaceName[0] == '@')
4646 return 1;
4647
4648 /* skip linked font */
4649 if (!TranslateCharsetInfo((DWORD*)(INT_PTR)lpelfe->lfCharSet, &csi, TCI_SRCCHARSET) ||
4650 (lpntmex->ntmFontSig.fsCsb[0] & csi.fs.fsCsb[0]) == 0)
4651 return 1;
4652
4653 /* skip linked font, like SimSun-ExtB */
4654 switch (lpelfe->lfCharSet) {
4655 case SHIFTJIS_CHARSET:
4656 found_subset = lpntmex->ntmFontSig.fsUsb[1] & (1 << 17); /* Hiragana */
4657 break;
4658 case GB2312_CHARSET:
4660 found_subset = lpntmex->ntmFontSig.fsUsb[1] & (1 << 16); /* CJK Symbols And Punctuation */
4661 break;
4662 case HANGEUL_CHARSET:
4663 found_subset = lpntmex->ntmFontSig.fsUsb[1] & (1 << 24); /* Hangul Syllables */
4664 break;
4665 default:
4666 found_subset = lpntmex->ntmFontSig.fsUsb[0] & (1 << 0); /* Basic Latin */
4667 break;
4668 }
4669 if (!found_subset)
4670 return 1;
4671
4672 /* test with an odd height */
4673 lf.lfHeight = -19;
4674 lf.lfWidth = 0;
4676 if (hfont)
4677 {
4678 *(HFONT *)lParam = hfont;
4679 return 0;
4680 }
4681 return 1;
4682}
4683
4684static void test_GetGlyphOutline(void)
4685{
4686 HDC hdc;
4687 GLYPHMETRICS gm, gm2;
4688 LOGFONTA lf;
4689 HFONT hfont, old_hfont;
4690 INT ret, ret2;
4693 static const struct
4694 {
4695 UINT cs;
4696 UINT a;
4697 UINT w;
4698 } c[] =
4699 {
4700 {ANSI_CHARSET, 0x30, 0x30},
4701 {SHIFTJIS_CHARSET, 0x82a0, 0x3042},
4702 {HANGEUL_CHARSET, 0x8141, 0xac02},
4703 {GB2312_CHARSET, 0x8141, 0x4e04},
4704 {CHINESEBIG5_CHARSET, 0xa142, 0x3001}
4705 };
4706 UINT i;
4707
4708 if (!is_truetype_font_installed("Tahoma"))
4709 {
4710 skip("Tahoma is not installed\n");
4711 return;
4712 }
4713
4715 memset(&lf, 0, sizeof(lf));
4716 lf.lfHeight = 72;
4717 lstrcpyA(lf.lfFaceName, "Tahoma");
4718 SetLastError(0xdeadbeef);
4720 ok(hfont != 0, "CreateFontIndirectA error %lu\n", GetLastError());
4721 old_hfont = SelectObject(hdc, hfont);
4722
4723 memset(&gm, 0, sizeof(gm));
4724 SetLastError(0xdeadbeef);
4725 ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
4726 ok(ret != GDI_ERROR, "GetGlyphOutlineA error %lu\n", GetLastError());
4727
4728 memset(&gm, 0, sizeof(gm));
4729 SetLastError(0xdeadbeef);
4730 ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, NULL);
4731 ok(ret == GDI_ERROR, "GetGlyphOutlineA should fail\n");
4732 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", GetLastError());
4733
4734 memset(&gm, 0, sizeof(gm));
4735 SetLastError(0xdeadbeef);
4736 ret = GetGlyphOutlineW(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
4738 ok(ret != GDI_ERROR, "GetGlyphOutlineW error %lu\n", GetLastError());
4739
4740 memset(&gm, 0, sizeof(gm));
4741 SetLastError(0xdeadbeef);
4742 ret = GetGlyphOutlineW(hdc, 'A', GGO_METRICS, &gm, 0, NULL, NULL);
4744 {
4745 ok(ret == GDI_ERROR, "GetGlyphOutlineW should fail\n");
4746 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", GetLastError());
4747 }
4748
4749 /* test for needed buffer size request on space char */
4750 memset(&gm, 0, sizeof(gm));
4751 SetLastError(0xdeadbeef);
4752 ret = GetGlyphOutlineW(hdc, ' ', GGO_NATIVE, &gm, 0, NULL, &mat);
4754 {
4755 ok(ret == 0, "GetGlyphOutlineW should return 0 buffer size for space char\n");
4756 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", GetLastError());
4757 ok(gm.gmBlackBoxX == 1, "Expected 1, got %u\n", gm.gmBlackBoxX);
4758 ok(gm.gmBlackBoxY == 1, "Expected 1, got %u\n", gm.gmBlackBoxY);
4759 }
4760
4761 /* requesting buffer size for space char + error */
4762 memset(&gm, 0, sizeof(gm));
4763 SetLastError(0xdeadbeef);
4764 ret = GetGlyphOutlineW(0, ' ', GGO_NATIVE, &gm, 0, NULL, NULL);
4766 {
4767 ok(ret == GDI_ERROR, "GetGlyphOutlineW should return GDI_ERROR\n");
4768 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", GetLastError());
4769 ok(gm.gmBlackBoxX == 0, "Expected 0, got %u\n", gm.gmBlackBoxX);
4770 ok(gm.gmBlackBoxY == 0, "Expected 0, got %u\n", gm.gmBlackBoxY);
4771 }
4772
4773 /* test GetGlyphOutline with a buffer too small */
4774 SetLastError(0xdeadbeef);
4775 ret = GetGlyphOutlineA(hdc, 'A', GGO_NATIVE, &gm, sizeof(i), &i, &mat);
4777 ok(ret == GDI_ERROR, "GetGlyphOutlineW should return an error when the buffer size is too small.\n");
4778
4779 for (i = 0; i < ARRAY_SIZE(fmt); ++i)
4780 {
4781 DWORD dummy;
4782
4783 memset(&gm, 0xab, sizeof(gm));
4784 SetLastError(0xdeadbeef);
4785 ret = GetGlyphOutlineW(hdc, ' ', fmt[i], &gm, 0, NULL, &mat);
4787 {
4788 if (fmt[i] == GGO_METRICS)
4789 ok(ret != GDI_ERROR, "%2d:GetGlyphOutlineW should succeed, got %d\n", fmt[i], ret);
4790 else
4791 ok(ret == 0, "%2d:GetGlyphOutlineW should return 0, got %d\n", fmt[i], ret);
4792 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", GetLastError());
4793 ok(gm.gmBlackBoxX == 1, "%2d:expected 1, got %u\n", fmt[i], gm.gmBlackBoxX);
4794 ok(gm.gmBlackBoxY == 1, "%2d:expected 1, got %u\n", fmt[i], gm.gmBlackBoxY);
4795 }
4796
4797 memset(&gm, 0xab, sizeof(gm));
4798 SetLastError(0xdeadbeef);
4799 ret = GetGlyphOutlineW(hdc, ' ', fmt[i], &gm, 0, &dummy, &mat);
4801 {
4802 if (fmt[i] == GGO_METRICS)
4803 ok(ret != GDI_ERROR, "%2d:GetGlyphOutlineW should succeed, got %d\n", fmt[i], ret);
4804 else
4805 ok(ret == 0, "%2d:GetGlyphOutlineW should return 0, got %d\n", fmt[i], ret);
4806 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", GetLastError());
4807 ok(gm.gmBlackBoxX == 1, "%2d:expected 1, got %u\n", fmt[i], gm.gmBlackBoxX);
4808 ok(gm.gmBlackBoxY == 1, "%2d:expected 1, got %u\n", fmt[i], gm.gmBlackBoxY);
4809 }
4810
4811 memset(&gm, 0xab, sizeof(gm));
4812 SetLastError(0xdeadbeef);
4813 ret = GetGlyphOutlineW(hdc, ' ', fmt[i], &gm, sizeof(dummy), NULL, &mat);
4815 {
4816 if (fmt[i] == GGO_METRICS)
4817 ok(ret != GDI_ERROR, "%2d:GetGlyphOutlineW should succeed, got %d\n", fmt[i], ret);
4818 else
4819 ok(ret == 0, "%2d:GetGlyphOutlineW should return 0, got %d\n", fmt[i], ret);
4820 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", GetLastError());
4821 ok(gm.gmBlackBoxX == 1, "%2d:expected 1, got %u\n", fmt[i], gm.gmBlackBoxX);
4822 ok(gm.gmBlackBoxY == 1, "%2d:expected 1, got %u\n", fmt[i], gm.gmBlackBoxY);
4823 }
4824
4825 memset(&gm, 0xab, sizeof(gm));
4826 SetLastError(0xdeadbeef);
4827 ret = GetGlyphOutlineW(hdc, ' ', fmt[i], &gm, sizeof(dummy), &dummy, &mat);
4829 {
4830 if (fmt[i] == GGO_METRICS) {
4831 ok(ret != GDI_ERROR, "%2d:GetGlyphOutlineW should succeed, got %d\n", fmt[i], ret);
4832 ok(gm.gmBlackBoxX == 1, "%2d:expected 1, got %u\n", fmt[i], gm.gmBlackBoxX);
4833 ok(gm.gmBlackBoxY == 1, "%2d:expected 1, got %u\n", fmt[i], gm.gmBlackBoxY);
4834 }
4835 else
4836 {
4837 ok(ret == GDI_ERROR, "%2d:GetGlyphOutlineW should return GDI_ERROR, got %d\n", fmt[i], ret);
4838 memset(&gm2, 0xab, sizeof(gm2));
4839 ok(memcmp(&gm, &gm2, sizeof(GLYPHMETRICS)) == 0,
4840 "%2d:GLYPHMETRICS shouldn't be touched on error\n", fmt[i]);
4841 }
4842 }
4843 }
4844
4845 SelectObject(hdc, old_hfont);
4847
4848 for (i = 0; i < ARRAY_SIZE(c); ++i)
4849 {
4850 static const MAT2 rotate_mat = {{0, 0}, {0, -1}, {0, 1}, {0, 0}};
4852
4853 lf.lfFaceName[0] = '\0';
4854 lf.lfCharSet = c[i].cs;
4855 lf.lfPitchAndFamily = 0;
4857 {
4858 skip("TrueType font for charset %u is not installed\n", c[i].cs);
4859 continue;
4860 }
4861
4862 old_hfont = SelectObject(hdc, hfont);
4863
4864 /* expected to ignore superfluous bytes (single-byte character) */
4865 ret = GetGlyphOutlineA(hdc, 0x8041, GGO_BITMAP, &gm, 0, NULL, &mat);
4866 ret2 = GetGlyphOutlineA(hdc, 0x41, GGO_BITMAP, &gm2, 0, NULL, &mat);
4867 ok(ret == ret2 && memcmp(&gm, &gm2, sizeof gm) == 0, "%d %d\n", ret, ret2);
4868
4869 ret = GetGlyphOutlineA(hdc, 0xcc8041, GGO_BITMAP, &gm, 0, NULL, &mat);
4870 ok(ret == ret2 && memcmp(&gm, &gm2, sizeof gm) == 0,
4871 "Expected to ignore superfluous bytes, got %d %d\n", ret, ret2);
4872
4873 /* expected to ignore superfluous bytes (double-byte character) */
4874 ret = GetGlyphOutlineA(hdc, c[i].a, GGO_BITMAP, &gm, 0, NULL, &mat);
4875 ret2 = GetGlyphOutlineA(hdc, c[i].a | 0xdead0000, GGO_BITMAP, &gm2, 0, NULL, &mat);
4876 ok(ret == ret2 && memcmp(&gm, &gm2, sizeof gm) == 0,
4877 "Expected to ignore superfluous bytes, got %d %d\n", ret, ret2);
4878
4879 /* expected to match wide-char version results */
4880 ret2 = GetGlyphOutlineW(hdc, c[i].w, GGO_BITMAP, &gm2, 0, NULL, &mat);
4881 ok(ret == ret2 && memcmp(&gm, &gm2, sizeof gm) == 0, "%d %d\n", ret, ret2);
4882
4884 {
4885 skip("Fixed-pitch TrueType font for charset %u is not available\n", c[i].cs);
4886 continue;
4887 }
4889 if (c[i].a <= 0xff)
4890 {
4891 DeleteObject(SelectObject(hdc, old_hfont));
4892 continue;
4893 }
4894
4895 ret = GetObjectA(hfont, sizeof lf, &lf);
4896 ok(ret > 0, "GetObject error %lu\n", GetLastError());
4897
4899 ok(ret, "GetTextMetrics error %lu\n", GetLastError());
4900 ret = GetGlyphOutlineA(hdc, c[i].a, GGO_METRICS, &gm2, 0, NULL, &mat);
4901 ok(ret != GDI_ERROR, "GetGlyphOutlineA error %lu\n", GetLastError());
4902 ok(gm2.gmCellIncX == tm.tmAveCharWidth * 2 || broken(gm2.gmCellIncX == -lf.lfHeight),
4903 "expected %ld, got %d (%s:%d)\n",
4904 tm.tmAveCharWidth * 2, gm2.gmCellIncX, lf.lfFaceName, lf.lfCharSet);
4905
4906 ret = GetGlyphOutlineA(hdc, c[i].a, GGO_METRICS, &gm2, 0, NULL, &rotate_mat);
4907 ok(ret != GDI_ERROR, "GetGlyphOutlineA error %lu\n", GetLastError());
4908 ok(gm2.gmCellIncY == -lf.lfHeight,
4909 "expected %ld, got %d (%s:%d)\n",
4910 -lf.lfHeight, gm2.gmCellIncY, lf.lfFaceName, lf.lfCharSet);
4911
4912 lf.lfItalic = TRUE;
4914 ok(hfont != NULL, "CreateFontIndirect error %lu\n", GetLastError());
4917 ok(ret, "GetTextMetrics error %lu\n", GetLastError());
4918 ret = GetGlyphOutlineA(hdc, c[i].a, GGO_METRICS, &gm2, 0, NULL, &mat);
4919 ok(ret != GDI_ERROR, "GetGlyphOutlineA error %lu\n", GetLastError());
4920 ok(gm2.gmCellIncX == tm.tmAveCharWidth * 2 || broken(gm2.gmCellIncX == -lf.lfHeight),
4921 "expected %ld, got %d (%s:%d)\n",
4922 tm.tmAveCharWidth * 2, gm2.gmCellIncX, lf.lfFaceName, lf.lfCharSet);
4923
4924 lf.lfItalic = FALSE;
4925 lf.lfEscapement = lf.lfOrientation = 2700;
4927 ok(hfont != NULL, "CreateFontIndirect error %lu\n", GetLastError());
4929 ret = GetGlyphOutlineA(hdc, c[i].a, GGO_METRICS, &gm2, 0, NULL, &mat);
4930 ok(ret != GDI_ERROR, "GetGlyphOutlineA error %lu\n", GetLastError());
4931 ok(gm2.gmCellIncY == -lf.lfHeight,
4932 "expected %ld, got %d (%s:%d)\n",
4933 -lf.lfHeight, gm2.gmCellIncY, lf.lfFaceName, lf.lfCharSet);
4934
4935 hfont = SelectObject(hdc, old_hfont);
4937 }
4938
4939 DeleteDC(hdc);
4940}
4941
4942/* bug #9995: there is a limit to the character width that can be specified */
4943static void test_GetTextMetrics2(const char *fontname, int font_height)
4944{
4945 HFONT of, hf;
4946 HDC hdc;
4948 BOOL ret;
4949 int ave_width, height, width, ratio;
4950
4951 if (!is_truetype_font_installed( fontname)) {
4952 skip("%s is not installed\n", fontname);
4953 return;
4954 }
4956 ok( hdc != NULL, "CreateCompatibleDC failed\n");
4957 /* select width = 0 */
4958 hf = CreateFontA(font_height, 0, 0, 0, FW_REGULAR, FALSE, FALSE, FALSE,
4961 fontname);
4962 ok( hf != NULL, "CreateFontA(%s, %d) failed\n", fontname, font_height);
4963 of = SelectObject( hdc, hf);
4964 ret = GetTextMetricsA( hdc, &tm);
4965 ok(ret, "GetTextMetricsA error %lu\n", GetLastError());
4966 height = tm.tmHeight;
4967 ave_width = tm.tmAveCharWidth;
4968 SelectObject( hdc, of);
4969 DeleteObject( hf);
4970
4971 for (width = ave_width * 2; /* nothing*/; width += ave_width)
4972 {
4975 DEFAULT_QUALITY, VARIABLE_PITCH, fontname);
4976 ok(hf != 0, "CreateFont failed\n");
4977 of = SelectObject(hdc, hf);
4979 ok(ret, "GetTextMetrics error %lu\n", GetLastError());
4980 SelectObject(hdc, of);
4981 DeleteObject(hf);
4982
4983 if (match_off_by_1(tm.tmAveCharWidth, ave_width, FALSE) || width / height > 200)
4984 break;
4985 }
4986
4987 DeleteDC(hdc);
4988
4989 ratio = width / height;
4990
4991 ok(ratio >= 90 && ratio <= 110, "expected width/height ratio 90-110, got %d\n", ratio);
4992}
4993
4995{
4997 DWORD size, size2;
4998 WCHAR glyphs[20];
4999 int pos[20];
5000 HDC hdc;
5001
5003 ok(!!hdc, "CreateCompatibleDC failed\n");
5004
5005 memset(&result, 0, sizeof(result));
5006 result.lStructSize = sizeof(result);
5007 result.lpCaretPos = pos;
5008 result.lpGlyphs = glyphs;
5009 result.nGlyphs = 20;
5010
5011 pos[0] = -1;
5012 glyphs[0] = '!';
5013 size = GetCharacterPlacementA(hdc, "Wine Test", 9, 0, &result, 0);
5014 ok(size, "GetCharacterPlacementA failed!\n");
5015 ok(result.nGlyphs == 9, "Unexpected number of glyphs %u\n", result.nGlyphs);
5016 ok(glyphs[0] == 'W', "Unexpected first glyph %s\n", wine_dbgstr_wn(glyphs, 1));
5017 ok(pos[0] == 0, "Unexpected caret position %d\n", pos[0]);
5018
5019 pos[0] = -1;
5020 glyphs[0] = '!';
5021 result.nGlyphs = 20;
5022 size2 = GetCharacterPlacementA(hdc, "Wine Test", 0, 0, &result, 0);
5023 ok(!size2, "Expected GetCharacterPlacementA to fail\n");
5024 ok(result.nGlyphs == 20, "Unexpected number of glyphs %u\n", result.nGlyphs);
5025 ok(glyphs[0] == '!', "Unexpected first glyph %s\n", wine_dbgstr_wn(glyphs, 1));
5026 ok(pos[0] == -1, "Unexpected caret position %d\n", pos[0]);
5027
5028 size2 = GetCharacterPlacementA(hdc, "Wine Test", 9, 0, NULL, 0);
5029 ok(size2, "GetCharacterPlacementA failed!\n");
5030 ok(size == size2, "GetCharacterPlacementA returned different result: %lu vs %lu\n", size2, size);
5031
5032 size2 = GetCharacterPlacementA(hdc, "Wine Test", 9, 1024, NULL, GCP_REORDER);
5033 ok(size2, "GetCharacterPlacementA failed!\n");
5034 ok(size == size2, "GetCharacterPlacementA returned different result: %lu vs %lu\n", size2, size);
5035
5036 pos[0] = -1;
5037 glyphs[0] = '!';
5038 result.nGlyphs = 20;
5039 size = GetCharacterPlacementA(hdc, "Wine Test", 9, 1024, &result, GCP_REORDER);
5040 ok(size, "GetCharacterPlacementA failed!\n");
5041 ok(size == size2, "GetCharacterPlacementA returned different result: %lu vs %lu\n", size2, size);
5042 ok(result.nGlyphs == 9, "Unexpected number of glyphs %u\n", result.nGlyphs);
5043 ok(glyphs[0] == 'W', "Unexpected first glyph %s\n", wine_dbgstr_wn(glyphs, 1));
5044 todo_wine ok(pos[0] == 0, "Unexpected caret position %d\n", pos[0]);
5045
5046 DeleteDC(hdc);
5047}
5048
5050{
5051 LOGFONTA lf, getobj_lf;
5052 int ret, i;
5053 HFONT hfont;
5054 char TestName[][16] = {"Arial", "Arial Bold", "Arial Italic", "Arial Baltic"};
5055
5056 memset(&lf, 0, sizeof(lf));
5059 lf.lfHeight = 16;
5060 lf.lfWidth = 16;
5062 lf.lfItalic = FALSE;
5063 lf.lfWeight = FW_DONTCARE;
5064
5065 for (i = 0; i < ARRAY_SIZE(TestName); i++)
5066 {
5069 ok(hfont != 0, "CreateFontIndirectA failed\n");
5070 SetLastError(0xdeadbeef);
5071 ret = GetObjectA(hfont, sizeof(getobj_lf), &getobj_lf);
5072 ok(ret, "GetObject failed: %ld\n", GetLastError());
5073 ok(lf.lfItalic == getobj_lf.lfItalic, "lfItalic: expect %02x got %02x\n", lf.lfItalic, getobj_lf.lfItalic);
5074 ok(lf.lfWeight == getobj_lf.lfWeight, "lfWeight: expect %08lx got %08lx\n", lf.lfWeight, getobj_lf.lfWeight);
5075 ok(!lstrcmpA(lf.lfFaceName, getobj_lf.lfFaceName), "font names don't match: %s != %s\n", lf.lfFaceName, getobj_lf.lfFaceName);
5077 }
5078}
5079
5081{
5082 ENUMLOGFONTEXDVA lfex;
5083 HFONT hfont;
5084
5085 if (!is_truetype_font_installed("Arial"))
5086 {
5087 skip("Arial is not installed\n");
5088 return;
5089 }
5090
5091 SetLastError(0xdeadbeef);
5093 ok(hfont == NULL, "got %p\n", hfont);
5094 ok(GetLastError() == 0xdeadbeef, "got error %ld\n", GetLastError());
5095
5096 memset(&lfex, 0, sizeof(lfex));
5099 ok(hfont != 0, "CreateFontIndirectEx failed\n");
5100 if (hfont)
5103}
5104
5105static void test_realization_info(const char *name, DWORD size, BOOL is_memory_resource)
5106{
5108 struct file_info file_info;
5109 HFONT hfont, hfont_prev;
5110 SIZE_T needed;
5111 LOGFONTA lf;
5112 BYTE *data;
5113 BOOL ret;
5114 HDC hdc;
5115
5116 if (!pGetFontRealizationInfo)
5117 return;
5118
5119 memset(&lf, 0, sizeof(lf));
5120 lf.lfHeight = 72;
5121 strcpy(lf.lfFaceName, name);
5122
5124 ok(hfont != 0, "Failed to create a font, %lu.\n", GetLastError());
5125
5126 hdc = GetDC(NULL);
5127
5128 hfont_prev = SelectObject(hdc, hfont);
5129 ok(hfont_prev != NULL, "Failed to select font.\n");
5130
5131 memset(&info, 0xcc, sizeof(info));
5132 info.size = sizeof(info);
5133 ret = pGetFontRealizationInfo(hdc, (DWORD *)&info);
5134 ok(ret != 0, "Unexpected return value %d.\n", ret);
5135
5136 ok((info.flags & 0xf) == 0x3, "Unexpected flags %#lx.\n", info.flags);
5137 ok(info.cache_num != 0, "Unexpected cache num %lu.\n", info.cache_num);
5138 ok(info.instance_id != 0, "Unexpected instance id %lu.\n", info.instance_id);
5139 ok(info.simulations == 0, "Unexpected simulations %#x.\n", info.simulations);
5140 ok(info.face_index == 0, "Unexpected face index %u.\n", info.face_index);
5141
5142 ret = pGetFontFileInfo(info.instance_id, 0, NULL, 0, NULL);
5143 ok(ret == 0 && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Unexpected return value %d, error %ld.\n",
5144 ret, GetLastError());
5145
5146 needed = 0;
5147 ret = pGetFontFileInfo(info.instance_id, 0, NULL, 0, &needed);
5148 ok(ret == 0 && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Unexpected return value %d, error %ld.\n",
5149 ret, GetLastError());
5150
5151 ret = pGetFontFileInfo(info.instance_id, 0, &file_info, 0, NULL);
5152 ok(ret == 0 && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Unexpected return value %d, error %ld.\n",
5153 ret, GetLastError());
5154
5155 ret = pGetFontFileInfo(info.instance_id, 0, &file_info, needed - 1, NULL);
5156 ok(ret == 0 && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Unexpected return value %d, error %ld.\n",
5157 ret, GetLastError());
5158
5159 ret = pGetFontFileInfo(info.instance_id, 0, &file_info, needed, NULL);
5160 ok(ret != 0, "Failed to get font file info, ret %d gle %ld.\n", ret, GetLastError());
5161
5162 memset(&file_info, 0xcc, sizeof(file_info));
5163 ret = pGetFontFileInfo(info.instance_id, 0, &file_info, sizeof(file_info), NULL);
5164 ok(ret != 0, "Failed to get font file info, ret %d gle %ld.\n", ret, GetLastError());
5165 if (ret)
5166 {
5167 ok(is_memory_resource ? file_info.size.QuadPart == size : file_info.size.QuadPart > 0, "Unexpected file size.\n");
5168 ok(is_memory_resource ? !file_info.path[0] : file_info.path[0], "Unexpected file path %s.\n",
5170 }
5171
5173 data = malloc(size + 16);
5174
5175 memset(data, 0xcc, size);
5176 ret = pGetFontFileData(info.instance_id, 0, 0, data, size);
5177 ok(ret != 0, "Failed to get font file data, %ld\n", GetLastError());
5178 ok(*(DWORD *)data == 0x00000100, "Unexpected sfnt header version %#lx.\n", *(DWORD *)data);
5179 ok(*(WORD *)(data + 4) == 0x0e00, "Unexpected table count %#x.\n", *(WORD *)(data + 4));
5180
5181 /* Larger than font data size. */
5182 memset(data, 0xcc, size);
5183 ret = pGetFontFileData(info.instance_id, 0, 0, data, size + 16);
5184 ok(ret == 0 && GetLastError() == ERROR_INVALID_PARAMETER, "Unexpected return value %d, error %ld\n",
5185 ret, GetLastError());
5186 ok(*(DWORD *)data == 0xcccccccc, "Unexpected buffer contents %#lx.\n", *(DWORD *)data);
5187
5188 /* With offset. */
5189 memset(data, 0xcc, size);
5190 ret = pGetFontFileData(info.instance_id, 0, 16, data, size - 16);
5191 ok(ret != 0, "Failed to get font file data, %ld\n", GetLastError());
5192 ok(*(DWORD *)data == 0x1000000, "Unexpected buffer contents %#lx.\n", *(DWORD *)data);
5193
5194 memset(data, 0xcc, size);
5195 ret = pGetFontFileData(info.instance_id, 0, 16, data, size);
5196 ok(ret == 0 && GetLastError() == ERROR_INVALID_PARAMETER, "Unexpected return value %d, error %ld\n",
5197 ret, GetLastError());
5198 ok(*(DWORD *)data == 0xcccccccc, "Unexpected buffer contents %#lx.\n", *(DWORD *)data);
5199
5200 /* Zero buffer size. */
5201 memset(data, 0xcc, size);
5202 ret = pGetFontFileData(info.instance_id, 0, 16, data, 0);
5203 todo_wine
5204 ok(ret == 0 && GetLastError() == ERROR_NOACCESS, "Unexpected return value %d, error %ld\n", ret, GetLastError());
5205 ok(*(DWORD *)data == 0xcccccccc, "Unexpected buffer contents %#lx.\n", *(DWORD *)data);
5206
5207 free(data);
5208
5209 SelectObject(hdc, hfont_prev);
5211 ReleaseDC(NULL, hdc);
5212}
5213
5215{
5216 char ttf_name[MAX_PATH];
5217 void *font;
5218 DWORD font_size, num_fonts;
5219 HANDLE ret;
5220 BOOL bRet;
5221
5222 SetLastError(0xdeadbeef);
5224 ok(!ret, "AddFontMemResourceEx should fail\n");
5226 "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %lu\n",
5227 GetLastError());
5228
5229 SetLastError(0xdeadbeef);
5231 ok(!ret, "AddFontMemResourceEx should fail\n");
5233 "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %lu\n",
5234 GetLastError());
5235
5236 SetLastError(0xdeadbeef);
5237 ret = AddFontMemResourceEx(NULL, 0, NULL, &num_fonts);
5238 ok(!ret, "AddFontMemResourceEx should fail\n");
5240 "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %lu\n",
5241 GetLastError());
5242
5243 SetLastError(0xdeadbeef);
5244 ret = AddFontMemResourceEx(NULL, 10, NULL, &num_fonts);
5245 ok(!ret, "AddFontMemResourceEx should fail\n");
5247 "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %lu\n",
5248 GetLastError());
5249
5250 /* Now with scalable font */
5251 bRet = write_ttf_file("wine_test.ttf", ttf_name);
5252 ok(bRet, "Failed to create test font file.\n");
5253
5254 font = load_font(ttf_name, &font_size);
5255 ok(font != NULL, "Failed to map font file.\n");
5256
5257 bRet = is_truetype_font_installed("wine_test");
5258 ok(!bRet, "Font wine_test should not be enumerated.\n");
5259
5260 num_fonts = 0;
5261 ret = AddFontMemResourceEx(font, font_size, NULL, &num_fonts);
5262 ok(ret != 0, "Failed to add resource, %ld.\n", GetLastError());
5263 ok(num_fonts == 1, "Unexpected number of fonts %lu.\n", num_fonts);
5264
5265 bRet = is_truetype_font_installed("wine_test");
5266 todo_wine
5267 ok(!bRet, "Font wine_test should not be enumerated.\n");
5268
5269 test_realization_info("wine_test", font_size, TRUE);
5270
5272 ok(bRet, "RemoveFontMemResourceEx error %ld\n", GetLastError());
5273
5274 free_font(font);
5275
5276 bRet = DeleteFileA(ttf_name);
5277 ok(bRet, "Failed to delete font file, %ld.\n", GetLastError());
5278
5279 font = load_font("sserife.fon", &font_size);
5280 if (!font)
5281 {
5282 skip("Unable to locate and load font sserife.fon\n");
5283 return;
5284 }
5285
5286 SetLastError(0xdeadbeef);
5288 ok(!ret, "AddFontMemResourceEx should fail\n");
5290 "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %lu\n",
5291 GetLastError());
5292
5293 SetLastError(0xdeadbeef);
5295 ok(!ret, "AddFontMemResourceEx should fail\n");
5297 "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %lu\n",
5298 GetLastError());
5299
5300 num_fonts = 0xdeadbeef;
5301 SetLastError(0xdeadbeef);
5302 ret = AddFontMemResourceEx(font, 0, NULL, &num_fonts);
5303 ok(!ret, "AddFontMemResourceEx should fail\n");
5305 "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %lu\n",
5306 GetLastError());
5307 ok(num_fonts == 0xdeadbeef, "number of loaded fonts should be 0xdeadbeef\n");
5308
5309 num_fonts = 0xdeadbeef;
5310 SetLastError(0xdeadbeef);
5311 ret = AddFontMemResourceEx(font, 10, NULL, &num_fonts);
5312 ok(!ret, "AddFontMemResourceEx should fail\n");
5313 ok(GetLastError() == 0xdeadbeef,
5314 "Expected GetLastError() to return 0xdeadbeef, got %lu\n",
5315 GetLastError());
5316 ok(num_fonts == 0xdeadbeef, "number of loaded fonts should be 0xdeadbeef\n");
5317
5318 num_fonts = 0xdeadbeef;
5319 SetLastError(0xdeadbeef);
5320 ret = AddFontMemResourceEx(font, font_size, NULL, &num_fonts);
5321 ok(ret != 0, "AddFontMemResourceEx error %ld\n", GetLastError());
5322 ok(num_fonts != 0xdeadbeef, "number of loaded fonts should not be 0xdeadbeef\n");
5323 ok(num_fonts != 0, "number of loaded fonts should not be 0\n");
5324
5325 free_font(font);
5326
5327 SetLastError(0xdeadbeef);
5329 ok(bRet, "RemoveFontMemResourceEx error %ld\n", GetLastError());
5330
5331 /* test invalid pointer to number of loaded fonts */
5332 font = load_font("sserife.fon", &font_size);
5333 ok(font != NULL, "Unable to locate and load font sserife.fon\n");
5334
5335 SetLastError(0xdeadbeef);
5336 ret = AddFontMemResourceEx(font, font_size, NULL, (void *)0xdeadbeef);
5337 ok(!ret, "AddFontMemResourceEx should fail\n");
5338 ok(GetLastError() == 0xdeadbeef,
5339 "Expected GetLastError() to return 0xdeadbeef, got %lu\n",
5340 GetLastError());
5341
5342 SetLastError(0xdeadbeef);
5343 ret = AddFontMemResourceEx(font, font_size, NULL, NULL);
5344 ok(!ret, "AddFontMemResourceEx should fail\n");
5346 "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %lu\n",
5347 GetLastError());
5348
5349 free_font(font);
5350}
5351
5353{
5354 LOGFONTA *lf;
5355
5356 if (type != TRUETYPE_FONTTYPE) return 1;
5357
5358 ok(ntm->tmWeight == elf->lfWeight, "expected %ld got %ld\n", ntm->tmWeight, elf->lfWeight);
5359
5360 lf = (LOGFONTA *)lparam;
5361 *lf = *elf;
5362 return 0;
5363}
5364
5366{
5367 int ret;
5368 LOGFONTA *lf;
5369
5370 if (type != TRUETYPE_FONTTYPE) return 1;
5371
5372 lf = (LOGFONTA *)lparam;
5373 ret = strcmp(lf->lfFaceName, elf->lfFaceName);
5374 if(ret == 0)
5375 {
5376 ok(ntm->tmWeight == elf->lfWeight, "expected %ld got %ld\n", ntm->tmWeight, elf->lfWeight);
5377 *lf = *elf;
5378 return 0;
5379 }
5380 return 1;
5381}
5382
5384{
5385 return lparam;
5386}
5387
5388static void test_EnumFonts(void)
5389{
5390 int ret;
5391 LOGFONTA lf;
5392 HDC hdc;
5393
5394 if (!is_truetype_font_installed("Arial"))
5395 {
5396 skip("Arial is not installed\n");
5397 return;
5398 }
5399
5400 /* Windows uses localized font face names, so Arial Bold won't be found */
5402 {
5403 skip("User locale is not English, skipping the test\n");
5404 return;
5405 }
5406
5408
5409 /* check that the enumproc's retval is returned */
5411 ok(ret == 0xcafe, "got %08x\n", ret);
5412
5413 ret = EnumFontFamiliesA(hdc, "Arial", enum_fonts_proc, (LPARAM)&lf);
5414 ok(!ret, "font Arial is not enumerated\n");
5415 ret = strcmp(lf.lfFaceName, "Arial");
5416 ok(!ret, "expected Arial got %s\n", lf.lfFaceName);
5417 ok(lf.lfWeight == FW_NORMAL, "expected FW_NORMAL got %ld\n", lf.lfWeight);
5418
5419 strcpy(lf.lfFaceName, "Arial");
5421 ok(!ret, "font Arial is not enumerated\n");
5422 ret = strcmp(lf.lfFaceName, "Arial");
5423 ok(!ret, "expected Arial got %s\n", lf.lfFaceName);
5424 ok(lf.lfWeight == FW_NORMAL, "expected FW_NORMAL got %ld\n", lf.lfWeight);
5425
5426 ret = EnumFontFamiliesA(hdc, "Arial Bold", enum_fonts_proc, (LPARAM)&lf);
5427 ok(!ret, "font Arial Bold is not enumerated\n");
5428 ret = strcmp(lf.lfFaceName, "Arial");
5429 ok(!ret, "expected Arial got %s\n", lf.lfFaceName);
5430 ok(lf.lfWeight == FW_BOLD, "expected FW_BOLD got %ld\n", lf.lfWeight);
5431
5432 strcpy(lf.lfFaceName, "Arial Bold");
5434 ok(ret, "font Arial Bold should not be enumerated\n");
5435
5436 ret = EnumFontFamiliesA(hdc, "Arial Bold Italic", enum_fonts_proc, (LPARAM)&lf);
5437 ok(!ret, "font Arial Bold Italic is not enumerated\n");
5438 ret = strcmp(lf.lfFaceName, "Arial");
5439 ok(!ret, "expected Arial got %s\n", lf.lfFaceName);
5440 ok(lf.lfWeight == FW_BOLD, "expected FW_BOLD got %ld\n", lf.lfWeight);
5441
5442 strcpy(lf.lfFaceName, "Arial Bold Italic");
5444 ok(ret, "font Arial Bold Italic should not be enumerated\n");
5445
5446 ret = EnumFontFamiliesA(hdc, "Arial Italic Bold", enum_fonts_proc, (LPARAM)&lf);
5447 ok(ret, "font Arial Italic Bold should not be enumerated\n");
5448
5449 strcpy(lf.lfFaceName, "Arial Italic Bold");
5451 ok(ret, "font Arial Italic Bold should not be enumerated\n");
5452
5453 DeleteDC(hdc);
5454}
5455
5457{
5458 struct enum_fullname_data *efnd = (struct enum_fullname_data *)lParam;
5459
5460 if (winetest_debug > 2)
5461 trace("enumed font \"%s\", charset %d, height %ld, weight %ld, italic %d\n",
5462 lf->lfFaceName, lf->lfCharSet, lf->lfHeight, lf->lfWeight, lf->lfItalic);
5463
5464 if (type != TRUETYPE_FONTTYPE) return 1;
5465 if (strcmp(lf->lfFaceName, "MS Shell Dlg") != 0) return 1;
5466
5467 if (efnd->total >= efnd->size)
5468 {
5469 efnd->size = max( (efnd->total + 1) * 2, 256 );
5470 efnd->elf = realloc( efnd->elf, efnd->size * sizeof(*efnd->elf) );
5471 if (!efnd->elf) return 0;
5472 }
5473 efnd->elf[efnd->total++] = *(ENUMLOGFONTA *)lf;
5474 return 0;
5475}
5476
5478{
5479 struct enum_fullname_data *efnd = (struct enum_fullname_data *)lParam;
5480
5481 if (winetest_debug > 2)
5482 trace("enumed font \"%s\", charset %d, height %ld, weight %ld, italic %d\n",
5483 lf->lfFaceName, lf->lfCharSet, lf->lfHeight, lf->lfWeight, lf->lfItalic);
5484
5485 if (type != TRUETYPE_FONTTYPE) return 1;
5486 if (strcmp(lf->lfFaceName, "MS Shell Dlg 2") != 0) return 1;
5487
5488 if (efnd->total >= efnd->size)
5489 {
5490 efnd->size = max( (efnd->total + 1) * 2, 256 );
5491 efnd->elf = realloc( efnd->elf, efnd->size * sizeof(*efnd->elf) );
5492 if (!efnd->elf) return 0;
5493 }
5494 efnd->elf[efnd->total++] = *(ENUMLOGFONTA *)lf;
5495 return 0;
5496}
5497
5498static void test_EnumFonts_subst(void)
5499{
5500 int ret;
5501 LOGFONTA lf;
5502 HDC hdc;
5503 struct enum_fullname_data efnd;
5504
5505 ret = is_font_installed("MS Shell Dlg");
5506 ok(ret, "MS Shell Dlg should be enumerated\n");
5507 ret = is_truetype_font_installed("MS Shell Dlg");
5508 ok(ret, "MS Shell Dlg should be enumerated as a TrueType font\n");
5509
5510 ret = is_font_installed("MS Shell Dlg 2");
5511 ok(ret, "MS Shell Dlg 2 should be enumerated\n");
5512 ret = is_truetype_font_installed("MS Shell Dlg 2");
5513 ok(ret, "MS Shell Dlg 2 should be enumerated as a TrueType font\n");
5514
5516
5517 memset(&efnd, 0, sizeof(efnd));
5519 ok(ret, "MS Shell Dlg should not be enumerated\n");
5520 ok(!efnd.total, "MS Shell Dlg should not be enumerated\n");
5521
5522 memset(&lf, 0, sizeof(lf));
5524
5525 efnd.total = 0;
5526 strcpy(lf.lfFaceName, "MS Shell Dlg");
5528 ok(!ret, "MS Shell Dlg should be enumerated\n");
5529 ok(efnd.total > 0, "MS Shell Dlg should be enumerated\n");
5530 if (efnd.total)
5531 {
5532 ret = strcmp((const char *)efnd.elf[0].elfLogFont.lfFaceName, "MS Shell Dlg");
5533 ok(!ret, "expected MS Shell Dlg, got %s\n", efnd.elf[0].elfLogFont.lfFaceName);
5534 ret = strcmp((const char *)efnd.elf[0].elfFullName, "MS Shell Dlg");
5535 ok(ret, "did not expect MS Shell Dlg\n");
5536 }
5537
5538 efnd.total = 0;
5540 ok(ret, "MS Shell Dlg 2 should not be enumerated\n");
5541 ok(!efnd.total, "MS Shell Dlg 2 should not be enumerated\n");
5542
5543 efnd.total = 0;
5544 strcpy(lf.lfFaceName, "MS Shell Dlg 2");
5546 ok(!ret, "MS Shell Dlg 2 should be enumerated\n");
5547 ok(efnd.total > 0, "MS Shell Dlg 2 should be enumerated\n");
5548 if (efnd.total)
5549 {
5550 ret = strcmp((const char *)efnd.elf[0].elfLogFont.lfFaceName, "MS Shell Dlg 2");
5551 ok(!ret, "expected MS Shell Dlg 2, got %s\n", efnd.elf[0].elfLogFont.lfFaceName);
5552 ret = strcmp((const char *)efnd.elf[0].elfFullName, "MS Shell Dlg 2");
5553 ok(ret, "did not expect MS Shell Dlg 2\n");
5554 }
5555
5556 free(efnd.elf);
5557 DeleteDC(hdc);
5558}
5559
5561{
5562 const ENUMLOGFONTA *elf = (const ENUMLOGFONTA *)lf;
5563 const char *fullname = (const char *)lParam;
5564
5565 if (!strcmp((const char *)elf->elfFullName, fullname)) return 0;
5566
5567 return 1;
5568}
5569
5570static BOOL is_font_installed_fullname(const char *family, const char *fullname)
5571{
5572 HDC hdc = GetDC(0);
5573 BOOL ret = FALSE;
5574
5576 ret = TRUE;
5577
5578 ReleaseDC(0, hdc);
5579 return ret;
5580}
5581
5582static void test_fullname(void)
5583{
5584 static const char *TestName[] = {"Lucida Sans Demibold Roman", "Lucida Sans Italic", "Lucida Sans Regular"};
5585 WCHAR bufW[LF_FULLFACESIZE];
5586 char bufA[LF_FULLFACESIZE];
5587 HFONT hfont, of;
5588 LOGFONTA lf;
5589 HDC hdc;
5590 int i;
5591 DWORD ret;
5592
5594 ok(hdc != NULL, "CreateCompatibleDC failed\n");
5595
5596 memset(&lf, 0, sizeof(lf));
5599 lf.lfHeight = 16;
5600 lf.lfWidth = 16;
5602 lf.lfItalic = FALSE;
5603 lf.lfWeight = FW_DONTCARE;
5604
5605 for (i = 0; i < ARRAY_SIZE(TestName); i++)
5606 {
5607 if (!is_font_installed_fullname("Lucida Sans", TestName[i]))
5608 {
5609 skip("%s is not installed\n", TestName[i]);
5610 continue;
5611 }
5612
5615 ok(hfont != 0, "CreateFontIndirectA failed\n");
5616
5617 of = SelectObject(hdc, hfont);
5618 bufW[0] = 0;
5619 bufA[0] = 0;
5621 ok(ret, "face full name could not be read\n");
5622 WideCharToMultiByte(CP_ACP, 0, bufW, -1, bufA, sizeof(bufA), NULL, FALSE);
5623 ok(!lstrcmpA(bufA, TestName[i]), "font full names don't match: %s != %s\n", TestName[i], bufA);
5624 SelectObject(hdc, of);
5626 }
5627 DeleteDC(hdc);
5628}
5629
5630static WCHAR *prepend_at(WCHAR *family)
5631{
5632 if (!family)
5633 return NULL;
5634
5635 memmove(family + 1, family, (lstrlenW(family) + 1) * sizeof(WCHAR));
5636 family[0] = '@';
5637 return family;
5638}
5639
5640static void test_fullname2_helper(const char *Family)
5641{
5642 char *FamilyName, *FaceName, *StyleName, *otmStr;
5643 struct enum_fullname_data efnd;
5644 WCHAR *bufW;
5645 char *bufA;
5646 HFONT hfont, of;
5647 LOGFONTA lf;
5648 HDC hdc;
5649 int i;
5650 DWORD otm_size, ret, buf_size;
5651 OUTLINETEXTMETRICA *otm;
5652 BOOL want_vertical, get_vertical;
5653 want_vertical = ( Family[0] == '@' );
5654
5656 ok(hdc != NULL, "CreateCompatibleDC failed\n");
5657
5658 memset(&lf, 0, sizeof(lf));
5661 lf.lfHeight = 16;
5662 lf.lfWidth = 16;
5664 lf.lfItalic = FALSE;
5665 lf.lfWeight = FW_DONTCARE;
5667 memset(&efnd, 0, sizeof(efnd));
5669 if (efnd.total == 0)
5670 skip("%s is not installed\n", lf.lfFaceName);
5671
5672 for (i = 0; i < efnd.total; i++)
5673 {
5674 FamilyName = (char *)efnd.elf[i].elfLogFont.lfFaceName;
5675 FaceName = (char *)efnd.elf[i].elfFullName;
5676 StyleName = (char *)efnd.elf[i].elfStyle;
5677
5678 get_vertical = ( FamilyName[0] == '@' );
5679 ok(get_vertical == want_vertical, "Vertical flags don't match: %s %s\n", Family, FamilyName);
5680
5681 lstrcpyA(lf.lfFaceName, FaceName);
5683 ok(hfont != 0, "CreateFontIndirectA failed\n");
5684
5685 of = SelectObject(hdc, hfont);
5686 buf_size = GetFontData(hdc, MS_NAME_TAG, 0, NULL, 0);
5687 ok(buf_size != GDI_ERROR, "no name table found\n");
5688 if (buf_size == GDI_ERROR) continue;
5689
5690 bufW = malloc(buf_size);
5691 bufA = malloc(buf_size);
5692
5693 otm_size = GetOutlineTextMetricsA(hdc, 0, NULL);
5694 otm = malloc(otm_size);
5695 memset(otm, 0, otm_size);
5696 ret = GetOutlineTextMetricsA(hdc, otm_size, otm);
5697 ok(ret != 0, "GetOutlineTextMetrics fails!\n");
5698 if (ret == 0) continue;
5699
5700 bufW[0] = 0;
5701 bufA[0] = 0;
5704 ok(ret, "%s: FAMILY (family name) could not be read\n", FamilyName);
5705 if (want_vertical) bufW = prepend_at(bufW);
5706 WideCharToMultiByte(CP_ACP, 0, bufW, -1, bufA, buf_size, NULL, FALSE);
5707 ok(!lstrcmpA(FamilyName, bufA), "font family names don't match: returned %s, expect %s\n", FamilyName, bufA);
5708 otmStr = (LPSTR)otm + (UINT_PTR)otm->otmpFamilyName;
5709 ok(!lstrcmpA(FamilyName, otmStr), "FamilyName %s doesn't match otmpFamilyName %s\n", FamilyName, otmStr);
5710
5711 bufW[0] = 0;
5712 bufA[0] = 0;
5715 ok(ret, "FULL_NAME (face name) could not be read\n");
5716 if (want_vertical) bufW = prepend_at(bufW);
5717 WideCharToMultiByte(CP_ACP, 0, bufW, -1, bufA, buf_size, NULL, FALSE);
5718 ok(!lstrcmpA(FaceName, bufA), "%s: font face names don't match: returned %s, expect %s\n", FamilyName, FaceName, bufA);
5719 otmStr = (LPSTR)otm + (UINT_PTR)otm->otmpFaceName;
5720 ok(!lstrcmpA(FaceName, otmStr), "%s: FaceName %s doesn't match otmpFaceName %s\n", FamilyName, FaceName, otmStr);
5721
5722 bufW[0] = 0;
5723 bufA[0] = 0;
5726 ok(ret, "%s: SUBFAMILY (style name) could not be read\n", FamilyName);
5727 WideCharToMultiByte(CP_ACP, 0, bufW, -1, bufA, buf_size, NULL, FALSE);
5728 ok(!lstrcmpA(StyleName, bufA), "%s: style names don't match: returned %s, expect %s\n", FamilyName, StyleName, bufA);
5729 otmStr = (LPSTR)otm + (UINT_PTR)otm->otmpStyleName;
5730 ok(!lstrcmpA(StyleName, otmStr), "%s: StyleName %s doesn't match otmpStyleName %s\n", FamilyName, StyleName, otmStr);
5731
5732 bufW[0] = 0;
5733 bufA[0] = 0;
5736 ok(ret, "%s: UNIQUE_ID (full name) could not be read\n", FamilyName);
5737 WideCharToMultiByte(CP_ACP, 0, bufW, -1, bufA, buf_size, NULL, FALSE);
5738 otmStr = (LPSTR)otm + (UINT_PTR)otm->otmpFullName;
5739 ok(!lstrcmpA(otmStr, bufA), "%s: UNIQUE ID (full name) doesn't match: returned %s, expect %s\n", FamilyName, otmStr, bufA);
5740
5741 SelectObject(hdc, of);
5743
5744 free(otm);
5745 free(bufW);
5746 free(bufA);
5747 }
5748 free(efnd.elf);
5749 DeleteDC(hdc);
5750}
5751
5752static void test_fullname2(void)
5753{
5754 test_fullname2_helper("Arial");
5755 test_fullname2_helper("DejaVu Sans");
5756 test_fullname2_helper("Lucida Sans");
5757 test_fullname2_helper("Tahoma");
5758 test_fullname2_helper("Webdings");
5759 test_fullname2_helper("Wingdings");
5760 test_fullname2_helper("SimSun");
5761 test_fullname2_helper("NSimSun");
5762 test_fullname2_helper("MingLiu");
5763 test_fullname2_helper("PMingLiu");
5764 test_fullname2_helper("WenQuanYi Micro Hei");
5765 test_fullname2_helper("MS UI Gothic");
5766 test_fullname2_helper("Ume UI Gothic");
5767 test_fullname2_helper("MS Gothic");
5768 test_fullname2_helper("Ume Gothic");
5769 test_fullname2_helper("MS PGothic");
5770 test_fullname2_helper("Ume P Gothic");
5771 test_fullname2_helper("Gulim");
5772 test_fullname2_helper("Batang");
5773 test_fullname2_helper("UnBatang");
5774 test_fullname2_helper("UnDotum");
5775 test_fullname2_helper("@SimSun");
5776 test_fullname2_helper("@NSimSun");
5777 test_fullname2_helper("@MingLiu");
5778 test_fullname2_helper("@PMingLiu");
5779 test_fullname2_helper("@WenQuanYi Micro Hei");
5780 test_fullname2_helper("@MS UI Gothic");
5781 test_fullname2_helper("@Ume UI Gothic");
5782 test_fullname2_helper("@MS Gothic");
5783 test_fullname2_helper("@Ume Gothic");
5784 test_fullname2_helper("@MS PGothic");
5785 test_fullname2_helper("@Ume P Gothic");
5786 test_fullname2_helper("@Gulim");
5787 test_fullname2_helper("@Batang");
5788 test_fullname2_helper("@UnBatang");
5789 test_fullname2_helper("@UnDotum");
5790
5791}
5792
5794{
5795 HDC hdc;
5796 LOGFONTA lf;
5797 HFONT hfont, hfont_prev;
5799 GLYPHMETRICS gm;
5800 char buf[1024];
5801 DWORD ret;
5802
5803 memset(&lf, 0, sizeof(lf));
5804 lf.lfHeight = 72;
5805 lstrcpyA(lf.lfFaceName, "wine_test");
5806
5808 ok(hfont != 0, "CreateFontIndirectA error %lu\n", GetLastError());
5809
5810 hdc = GetDC(NULL);
5811
5812 hfont_prev = SelectObject(hdc, hfont);
5813 ok(hfont_prev != NULL, "SelectObject failed\n");
5814
5815 ret = GetGlyphOutlineW(hdc, 0xa8, GGO_NATIVE, &gm, 0, NULL, &mat);
5816 ok(ret == 228, "GetGlyphOutline returned %ld, expected 228\n", ret);
5817
5819 ret = GetGlyphOutlineW(hdc, 0xa8, GGO_NATIVE, &gm, sizeof(buf), buf, &mat);
5820 ok(ret == 228, "GetGlyphOutline returned %ld, expected 228\n", ret);
5821 ok(header->cb == 36, "header->cb = %ld, expected 36\n", header->cb);
5822 ok(header->dwType == TT_POLYGON_TYPE, "header->dwType = %ld, expected TT_POLYGON_TYPE\n", header->dwType);
5823 header = (TTPOLYGONHEADER*)((char*)header+header->cb);
5824 ok(header->cb == 96, "header->cb = %ld, expected 96\n", header->cb);
5825 header = (TTPOLYGONHEADER*)((char*)header+header->cb);
5826 ok(header->cb == 96, "header->cb = %ld, expected 96\n", header->cb);
5827
5828 SelectObject(hdc, hfont_prev);
5830 ReleaseDC(NULL, hdc);
5831}
5832
5834{
5835 HDC hdc;
5836 LOGFONTA lf;
5837 HFONT hfont, hfont_prev;
5838 GLYPHMETRICS gm;
5840 TEXTMETRICW tmW;
5841 DWORD ret;
5842
5843 memset(&lf, 0, sizeof(lf));
5844 lf.lfHeight = 72;
5845 lstrcpyA(lf.lfFaceName, "wine_test");
5846
5847 SetLastError(0xdeadbeef);
5849 ok(hfont != 0, "CreateFontIndirectA error %lu\n", GetLastError());
5850
5851 hdc = GetDC(NULL);
5852
5853 hfont_prev = SelectObject(hdc, hfont);
5854 ok(hfont_prev != NULL, "SelectObject failed\n");
5855
5856 SetLastError(0xdeadbeef);
5858 ok(ret, "GetTextMetrics error %lu\n", GetLastError());
5859
5860 GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
5861 ok(gm.gmptGlyphOrigin.y <= tm.tmAscent,
5862 "Glyph top(%ld) exceeds ascent(%ld)\n",
5863 gm.gmptGlyphOrigin.y, tm.tmAscent);
5864 GetGlyphOutlineA(hdc, 'D', GGO_METRICS, &gm, 0, NULL, &mat);
5865 ok(gm.gmptGlyphOrigin.y - gm.gmBlackBoxY >= -tm.tmDescent,
5866 "Glyph bottom(%ld) exceeds descent(%ld)\n",
5867 gm.gmptGlyphOrigin.y - gm.gmBlackBoxY, -tm.tmDescent);
5868
5869 /* Test tmLastChar - wine_test has code points fffb-fffe mapped to glyph 0 */
5870 GetTextMetricsW(hdc, &tmW);
5871 todo_wine
5872 ok( tmW.tmLastChar == 0xfffe, "got %04x\n", tmW.tmLastChar);
5873
5874 SelectObject(hdc, hfont_prev);
5876 ReleaseDC(NULL, hdc);
5877}
5878
5880{
5881 HFONT hfont, hfont_old;
5882 LOGFONTA lf;
5883 HDC hdc;
5884 DWORD ret;
5885 GLYPHMETRICS gm1, gm2, gmn;
5886 char test_chars[] = { 'A', 'D', '!', '\0' };
5887 char *current_char;
5888
5889 memset(&lf, 0, sizeof(lf));
5890 lf.lfHeight = 72;
5891 lstrcpyA(lf.lfFaceName, "wine_test");
5892
5894 ok(hfont != 0, "CreateFontIndirectA error %lu\n", GetLastError());
5895
5896 hdc = GetDC(NULL);
5897
5898 hfont_old = SelectObject(hdc, hfont);
5899 ok(hfont_old != NULL, "SelectObject failed\n");
5900
5901 ret = GetGlyphOutlineW(hdc, 'Z', GGO_METRICS, &gmn, 0, NULL, &mat);
5902 ok(ret != GDI_ERROR, "GetGlyphOutlineW failed to default to .notdef for character 'Z'\n");
5903
5904 for (current_char = test_chars; *current_char != '\0'; current_char++)
5905 {
5906 ret = GetGlyphOutlineW(hdc, *current_char, GGO_METRICS, &gm1, 0, NULL, &mat);
5907 ok(ret != GDI_ERROR, "GetGlyphOutlineW failed for '%c'\n", *current_char);
5908 ok(memcmp(&gm1, &gmn, sizeof(gmn)) != 0, "the test character '%c' matches .notdef\n", *current_char);
5909
5910 ret = GetGlyphOutlineW(hdc, 0x10000 + *current_char, GGO_METRICS, &gm2, 0, NULL, &mat);
5911 ok(ret != GDI_ERROR, "GetGlyphOutlineW failed for 0x10000 + '%c'\n", *current_char);
5912 ok(memcmp(&gm1, &gm2, sizeof(gmn)) == 0, "GetGlyphOutlineW returned wrong metrics for character 0x10000 + '%c'\n", *current_char);
5913 }
5914
5916 ok(ret != GDI_ERROR, "GetGlyphOutlineW failed for glyph index 0x3\n");
5917
5918 ret = GetGlyphOutlineW(hdc, 0xFFFF, GGO_METRICS|GGO_GLYPH_INDEX, &gm2, 0, NULL, &mat);
5919 ok(ret == GDI_ERROR, "GetGlyphOutlineW for nonexistent glyph index 0xFFFF has succeeded\n");
5920
5921 ret = GetGlyphOutlineW(hdc, 0x10003, GGO_METRICS|GGO_GLYPH_INDEX, &gm2, 0, NULL, &mat);
5922 ok(ret != GDI_ERROR, "GetGlyphOutlineW for index 0x10003 has failed\n");
5923 ok(memcmp(&gm1, &gm2, sizeof(gmn)) == 0, "GetGlyphOutlineW returned wrong metrics for glyph 0x10003\n");
5924
5925 SelectObject(hdc, hfont_old);
5927 ReleaseDC(NULL, hdc);
5928}
5929
5930static void test_fstype_fixup(void)
5931{
5932 HDC hdc;
5933 LOGFONTA lf;
5934 HFONT hfont, hfont_prev;
5935 DWORD ret;
5936 OUTLINETEXTMETRICA *otm;
5937 DWORD otm_size;
5938
5939 memset(&lf, 0, sizeof(lf));
5940 lf.lfHeight = 72;
5941 lstrcpyA(lf.lfFaceName, "wine_test");
5942
5943 SetLastError(0xdeadbeef);
5945 ok(hfont != 0, "CreateFontIndirectA error %lu\n", GetLastError());
5946
5947 hdc = GetDC(NULL);
5948
5949 hfont_prev = SelectObject(hdc, hfont);
5950 ok(hfont_prev != NULL, "SelectObject failed\n");
5951
5952 otm_size = GetOutlineTextMetricsA(hdc, 0, NULL);
5953 otm = malloc(otm_size);
5954 otm->otmSize = sizeof(*otm);
5955 ret = GetOutlineTextMetricsA(hdc, otm->otmSize, otm);
5956 ok(ret == otm->otmSize, "expected %u, got %lu, error %ld\n", otm->otmSize, ret, GetLastError());
5957
5958 /* Test font has fsType set to 0x7fff, test that reserved bits are filtered out,
5959 valid bits are 1, 2, 3, 8, 9. */
5960 ok((otm->otmfsType & ~0x30e) == 0, "fsType %#x\n", otm->otmfsType);
5961
5962 free(otm);
5963
5964 SelectObject(hdc, hfont_prev);
5966 ReleaseDC(NULL, hdc);
5967}
5968
5970{
5971 char ttf_name[MAX_PATH];
5972 char tmp_path[MAX_PATH];
5973 char fot_name[MAX_PATH];
5974 char *file_part;
5975 DWORD ret;
5976 int i;
5977
5978 if (!write_ttf_file("wine_test.ttf", ttf_name))
5979 {
5980 skip("Failed to create ttf file for testing\n");
5981 return;
5982 }
5983
5984 trace("created %s\n", ttf_name);
5985
5986 ret = is_truetype_font_installed("wine_test");
5987 ok(!ret, "font wine_test should not be enumerated\n");
5988
5989 ret = GetTempPathA(MAX_PATH, tmp_path);
5990 ok(ret, "GetTempPath() error %ld\n", GetLastError());
5991 ret = GetTempFileNameA(tmp_path, "fot", 0, fot_name);
5992 ok(ret, "GetTempFileName() error %ld\n", GetLastError());
5993
5994 ret = GetFileAttributesA(fot_name);
5995 ok(ret != INVALID_FILE_ATTRIBUTES, "file %s does not exist\n", fot_name);
5996
5997 SetLastError(0xdeadbeef);
5998 ret = CreateScalableFontResourceA(0, fot_name, ttf_name, NULL);
5999 ok(!ret, "CreateScalableFontResource() should fail\n");
6000 ok(GetLastError() == ERROR_FILE_EXISTS, "not expected error %ld\n", GetLastError());
6001
6002 SetLastError(0xdeadbeef);
6003 ret = CreateScalableFontResourceA(0, fot_name, ttf_name, "");
6004 ok(!ret, "CreateScalableFontResource() should fail\n");
6005 ok(GetLastError() == ERROR_FILE_EXISTS, "not expected error %ld\n", GetLastError());
6006
6007 file_part = strrchr(ttf_name, '\\');
6008 SetLastError(0xdeadbeef);
6009 ret = CreateScalableFontResourceA(0, fot_name, file_part, tmp_path);
6010 ok(!ret, "CreateScalableFontResource() should fail\n");
6011 ok(GetLastError() == ERROR_FILE_EXISTS, "not expected error %ld\n", GetLastError());
6012
6013 SetLastError(0xdeadbeef);
6014 ret = CreateScalableFontResourceA(0, fot_name, "random file name", tmp_path);
6015 ok(!ret, "CreateScalableFontResource() should fail\n");
6016 ok(GetLastError() == ERROR_INVALID_PARAMETER, "not expected error %ld\n", GetLastError());
6017
6018 SetLastError(0xdeadbeef);
6019 ret = CreateScalableFontResourceA(0, fot_name, NULL, ttf_name);
6020 ok(!ret, "CreateScalableFontResource() should fail\n");
6021 ok(GetLastError() == ERROR_INVALID_PARAMETER, "not expected error %ld\n", GetLastError());
6022
6023 ret = DeleteFileA(fot_name);
6024 ok(ret, "DeleteFile() error %ld\n", GetLastError());
6025
6026 ret = RemoveFontResourceExA(fot_name, 0, 0);
6027 ok(!ret, "RemoveFontResourceEx() should fail\n");
6028
6029 /* test public font resource */
6030 SetLastError(0xdeadbeef);
6031 ret = CreateScalableFontResourceA(0, fot_name, ttf_name, NULL);
6032 ok(ret, "CreateScalableFontResource() error %ld\n", GetLastError());
6033
6034 ret = is_truetype_font_installed("wine_test");
6035 ok(!ret, "font wine_test should not be enumerated\n");
6036
6037 SetLastError(0xdeadbeef);
6038 ret = AddFontResourceExA(fot_name, 0, 0);
6039 ok(ret, "AddFontResourceEx() error %ld\n", GetLastError());
6040
6041 ret = is_truetype_font_installed("wine_test");
6042 ok(ret, "font wine_test should be enumerated\n");
6043
6048
6049 ret = RemoveFontResourceExA(fot_name, FR_PRIVATE, 0);
6050 ok(!ret, "RemoveFontResourceEx() with not matching flags should fail\n");
6051
6052 SetLastError(0xdeadbeef);
6053 ret = RemoveFontResourceExA(fot_name, 0, 0);
6054 ok(ret, "RemoveFontResourceEx() error %ld\n", GetLastError());
6055
6056 ret = is_truetype_font_installed("wine_test");
6057 ok(!ret, "font wine_test should not be enumerated\n");
6058
6059 ret = RemoveFontResourceExA(fot_name, 0, 0);
6060 ok(!ret, "RemoveFontResourceEx() should fail\n");
6061
6062 /* test refcounting */
6063 for (i = 0; i < 5; i++)
6064 {
6065 SetLastError(0xdeadbeef);
6066 ret = AddFontResourceExA(fot_name, 0, 0);
6067 ok(ret, "AddFontResourceEx() error %ld\n", GetLastError());
6068 }
6069 for (i = 0; i < 5; i++)
6070 {
6071 SetLastError(0xdeadbeef);
6072 ret = RemoveFontResourceExA(fot_name, 0, 0);
6073 ok(ret, "RemoveFontResourceEx() error %ld\n", GetLastError());
6074 }
6075 ret = RemoveFontResourceExA(fot_name, 0, 0);
6076 ok(!ret, "RemoveFontResourceEx() should fail\n");
6077
6078 DeleteFileA(fot_name);
6079
6080 /* test hidden font resource */
6081 SetLastError(0xdeadbeef);
6082 ret = CreateScalableFontResourceA(1, fot_name, ttf_name, NULL);
6083 ok(ret, "CreateScalableFontResource() error %ld\n", GetLastError());
6084
6085 ret = is_truetype_font_installed("wine_test");
6086 ok(!ret, "font wine_test should not be enumerated\n");
6087
6088 SetLastError(0xdeadbeef);
6089 ret = AddFontResourceExA(fot_name, 0, 0);
6090 ok(ret, "AddFontResourceEx() error %ld\n", GetLastError());
6091
6092 ret = is_truetype_font_installed("wine_test");
6093 todo_wine
6094 ok(!ret, "font wine_test should not be enumerated\n");
6095
6096 /* XP allows removing a private font added with 0 flags */
6097 SetLastError(0xdeadbeef);
6098 ret = RemoveFontResourceExA(fot_name, FR_PRIVATE, 0);
6099 ok(ret, "RemoveFontResourceEx() error %ld\n", GetLastError());
6100
6101 ret = is_truetype_font_installed("wine_test");
6102 ok(!ret, "font wine_test should not be enumerated\n");
6103
6104 ret = RemoveFontResourceExA(fot_name, 0, 0);
6105 ok(!ret, "RemoveFontResourceEx() should fail\n");
6106
6107 DeleteFileA(fot_name);
6108 DeleteFileA(ttf_name);
6109}
6110
6111static void check_vertical_font(const char *name, BOOL *installed, BOOL *selected, GLYPHMETRICS *gm, WORD *gi)
6112{
6113 LOGFONTA lf;
6114 HFONT hfont, hfont_prev;
6115 HDC hdc;
6116 char facename[100];
6117 DWORD ret;
6118 static const WCHAR str[] = { 0x2025 };
6119
6120 *installed = is_truetype_font_installed(name);
6121
6122 lf.lfHeight = -18;
6123 lf.lfWidth = 0;
6124 lf.lfEscapement = 0;
6125 lf.lfOrientation = 0;
6126 lf.lfWeight = FW_DONTCARE;
6127 lf.lfItalic = 0;
6128 lf.lfUnderline = 0;
6129 lf.lfStrikeOut = 0;
6135 strcpy(lf.lfFaceName, name);
6136
6138 ok(hfont != NULL, "CreateFontIndirectA failed\n");
6139
6140 hdc = GetDC(NULL);
6141
6142 hfont_prev = SelectObject(hdc, hfont);
6143 ok(hfont_prev != NULL, "SelectObject failed\n");
6144
6145 ret = GetTextFaceA(hdc, sizeof facename, facename);
6146 ok(ret, "GetTextFaceA failed\n");
6147 *selected = !strcmp(facename, name);
6148
6149 ret = GetGlyphOutlineW(hdc, 0x2025, GGO_METRICS, gm, 0, NULL, &mat);
6150 ok(ret != GDI_ERROR, "GetGlyphOutlineW failed\n");
6151 if (!*selected)
6152 memset(gm, 0, sizeof *gm);
6153
6154 ret = GetGlyphIndicesW(hdc, str, 1, gi, 0);
6155 ok(ret != GDI_ERROR, "GetGlyphIndicesW failed\n");
6156
6157 SelectObject(hdc, hfont_prev);
6159 ReleaseDC(NULL, hdc);
6160}
6161
6162static void check_vertical_metrics(const char *face)
6163{
6164 LOGFONTA lf;
6165 HFONT hfont, hfont_prev;
6166 HDC hdc;
6167 DWORD ret;
6168 GLYPHMETRICS rgm, vgm;
6169 const UINT code = 0x5EAD, height = 1000;
6170 WORD idx;
6171 ABC abc, vabc;
6173 USHORT numOfLongVerMetrics;
6174
6175 hdc = GetDC(NULL);
6176
6177 memset(&lf, 0, sizeof(lf));
6178 strcpy(lf.lfFaceName, face);
6179 lf.lfHeight = -height;
6181 lf.lfEscapement = lf.lfOrientation = 900;
6183 hfont_prev = SelectObject(hdc, hfont);
6184 ret = GetGlyphOutlineW(hdc, code, GGO_METRICS, &rgm, 0, NULL, &mat);
6185 ok(ret != GDI_ERROR, "GetGlyphOutlineW failed\n");
6186 ret = GetCharABCWidthsW(hdc, code, code, &abc);
6187 ok(ret, "GetCharABCWidthsW failed\n");
6188 DeleteObject(SelectObject(hdc, hfont_prev));
6189
6190 memset(&lf, 0, sizeof(lf));
6191 strcpy(lf.lfFaceName, "@");
6192 strcat(lf.lfFaceName, face);
6193 lf.lfHeight = -height;
6196 hfont_prev = SelectObject(hdc, hfont);
6197 ret = GetGlyphOutlineW(hdc, code, GGO_METRICS, &vgm, 0, NULL, &mat);
6198 ok(ret != GDI_ERROR, "GetGlyphOutlineW failed\n");
6199 ret = GetCharABCWidthsW(hdc, code, code, &vabc);
6200 ok(ret, "GetCharABCWidthsW failed\n");
6201 ok(vabc.abcA == vgm.gmptGlyphOrigin.x, "expected %d, got %ld\n",
6202 vabc.abcA, vgm.gmptGlyphOrigin.x);
6203 ok(vabc.abcB == vgm.gmBlackBoxX, "expected %d, got %d\n",
6204 vabc.abcB, vgm.gmBlackBoxX);
6205 ok(vabc.abcA + vabc.abcB + vabc.abcC == vgm.gmCellIncX,
6206 "expected %d, got %d\n",
6207 vabc.abcA + vabc.abcB + vabc.abcC, vgm.gmCellIncX);
6208
6209 memset(&otm, 0, sizeof(otm));
6210 otm.otmSize = sizeof(otm);
6211 ret = GetOutlineTextMetricsA(hdc, sizeof(otm), &otm);
6212 ok(ret != 0, "GetOutlineTextMetricsA failed\n");
6213
6214 if (GetFontData(hdc, MS_MAKE_TAG('v','h','e','a'), sizeof(SHORT) * 17,
6215 &numOfLongVerMetrics, sizeof(numOfLongVerMetrics)) != GDI_ERROR) {
6216 int offset;
6217 SHORT topSideBearing;
6218
6219 ret = GetGlyphIndicesW(hdc, (LPCWSTR)&code, 1, &idx, 0);
6220 ok(ret != 0, "GetGlyphIndicesW failed\n");
6221 numOfLongVerMetrics = GET_BE_WORD(numOfLongVerMetrics);
6222 if (numOfLongVerMetrics > idx)
6223 offset = idx * 2 + 1;
6224 else
6225 offset = numOfLongVerMetrics * 2 + (idx - numOfLongVerMetrics);
6226 ret = GetFontData(hdc, MS_MAKE_TAG('v','m','t','x'), offset * sizeof(SHORT),
6227 &topSideBearing, sizeof(SHORT));
6228 ok(ret != GDI_ERROR, "GetFontData(vmtx) failed\n");
6229 topSideBearing = GET_BE_WORD(topSideBearing);
6231 MulDiv(topSideBearing, height, otm.otmEMSquare), FALSE),
6232 "expected %d, got %ld\n",
6233 MulDiv(topSideBearing, height, otm.otmEMSquare), vgm.gmptGlyphOrigin.x);
6234 }
6235 else
6236 {
6237 ok(vgm.gmptGlyphOrigin.x == rgm.gmptGlyphOrigin.x + vgm.gmCellIncX + otm.otmDescent,
6238 "got %ld, expected rgm.origin.x(%ld) + vgm.cellIncX(%d) + descent(%d)\n",
6240 }
6241
6242 ok(vgm.gmptGlyphOrigin.y == abc.abcA + abc.abcB + otm.otmDescent,
6243 "got %d, expected abcA(%d) + abcB(%u) + descent(%d)\n",
6244 (INT)vgm.gmptGlyphOrigin.y, abc.abcA, abc.abcB, otm.otmDescent);
6245
6246 DeleteObject(SelectObject(hdc, hfont_prev));
6247 ReleaseDC(NULL, hdc);
6248}
6249
6250static void test_vertical_font(void)
6251{
6252 char ttf_name[MAX_PATH];
6253 int num, i;
6254 BOOL ret, installed, selected;
6255 GLYPHMETRICS gm;
6256 WORD hgi, vgi;
6257 const char* face_list[] = {
6258 "@WineTestVertical", /* has vmtx table */
6259 "@Ume Gothic", /* doesn't have vmtx table */
6260 "@MS UI Gothic", /* has vmtx table, available on native */
6261 };
6262
6263 if (!write_ttf_file("vertical.ttf", ttf_name))
6264 {
6265 skip("Failed to create ttf file for testing\n");
6266 return;
6267 }
6268
6269 num = AddFontResourceExA(ttf_name, FR_PRIVATE, 0);
6270 ok(num == 2, "AddFontResourceExA should add 2 fonts from vertical.ttf\n");
6271
6272 check_vertical_font("WineTestVertical", &installed, &selected, &gm, &hgi);
6273 ok(installed, "WineTestVertical is not installed\n");
6274 ok(selected, "WineTestVertical is not selected\n");
6275 ok(gm.gmBlackBoxX > gm.gmBlackBoxY,
6276 "gmBlackBoxX(%u) should be greater than gmBlackBoxY(%u) if horizontal\n",
6277 gm.gmBlackBoxX, gm.gmBlackBoxY);
6278
6279 check_vertical_font("@WineTestVertical", &installed, &selected, &gm, &vgi);
6280 ok(installed, "@WineTestVertical is not installed\n");
6281 ok(selected, "@WineTestVertical is not selected\n");
6282 ok(gm.gmBlackBoxX > gm.gmBlackBoxY,
6283 "gmBlackBoxX(%u) should be less than gmBlackBoxY(%u) if vertical\n",
6284 gm.gmBlackBoxX, gm.gmBlackBoxY);
6285
6286 ok(hgi != vgi, "same glyph h:%u v:%u\n", hgi, vgi);
6287
6288 for (i = 0; i < ARRAY_SIZE(face_list); i++) {
6289 const char* face = face_list[i];
6291 skip("%s is not installed\n", face);
6292 continue;
6293 }
6295 }
6296
6297 ret = RemoveFontResourceExA(ttf_name, FR_PRIVATE, 0);
6298 ok(ret, "RemoveFontResourceEx() error %ld\n", GetLastError());
6299
6300 DeleteFileA(ttf_name);
6301}
6302
6305{
6306 if (lf->lfFaceName[0] == '@') {
6307 return 0;
6308 }
6309 return 1;
6310}
6311
6313{
6314 HDC hdc;
6317 size_t i;
6318
6319 hdc = GetDC(NULL);
6320
6321 for (i = 0; i < ARRAY_SIZE(charset); i++)
6322 {
6323 LOGFONTA lf;
6324 HFONT hfont;
6325 char face_name[LF_FACESIZE];
6326 int ret;
6327
6328 memset(&lf, 0, sizeof lf);
6329 lf.lfFaceName[0] = '\0';
6330 lf.lfCharSet = charset[i];
6331
6333 {
6334 skip("Vertical font for charset %u is not installed\n", charset[i]);
6335 continue;
6336 }
6337
6340 memset(face_name, 0, sizeof face_name);
6341 ret = GetTextFaceA(hdc, sizeof face_name, face_name);
6342 ok(ret && face_name[0] != '@',
6343 "expected non-vertical face for charset %u, got %s\n", charset[i], face_name);
6345
6346 memset(&lf, 0, sizeof lf);
6347 strcpy(lf.lfFaceName, "@");
6348 lf.lfCharSet = charset[i];
6351 memset(face_name, 0, sizeof face_name);
6352 ret = GetTextFaceA(hdc, sizeof face_name, face_name);
6353 ok(ret && face_name[0] == '@',
6354 "expected vertical face for charset %u, got %s\n", charset[i], face_name);
6356 }
6357 ReleaseDC(NULL, hdc);
6358}
6359
6360static int get_font_dpi(const LOGFONTA *lf, int *height)
6361{
6363 HFONT hfont;
6365 int ret;
6366
6368 ok(hfont != 0, "CreateFontIndirect failed\n");
6369
6372 ok(ret, "GetTextMetrics failed\n");
6373 ret = tm.tmDigitizedAspectX;
6374 if (height) *height = tm.tmHeight;
6375
6376 DeleteDC(hdc);
6378
6379 return ret;
6380}
6381
6382static void test_stock_fonts(void)
6383{
6384 static const int font[] =
6385 {
6387 /* SYSTEM_FIXED_FONT, OEM_FIXED_FONT */
6388 };
6389 static const struct test_data
6390 {
6391 int charset, weight, height, height_pixels, dpi;
6392 const char face_name[LF_FACESIZE];
6393 WORD lang_id;
6394 } td[][17] =
6395 {
6396 { /* ANSI_FIXED_FONT */
6397 { ANSI_CHARSET, FW_NORMAL, 12, 12, 96, "Courier", LANG_ARABIC },
6398 { ANSI_CHARSET, FW_NORMAL, 12, 12, 96, "Courier", LANG_HEBREW},
6399 { DEFAULT_CHARSET, FW_NORMAL, 12, 13, 96, "Courier" },
6400 { DEFAULT_CHARSET, FW_NORMAL, 12, 13, 120, "Courier" },
6401 { 0 }
6402 },
6403 { /* ANSI_VAR_FONT */
6404 { DEFAULT_CHARSET, FW_NORMAL, 12, 13, 96, "MS Sans Serif" },
6405 { DEFAULT_CHARSET, FW_NORMAL, 12, 13, 120, "MS Sans Serif" },
6406 { 0 }
6407 },
6408 { /* SYSTEM_FONT */
6409 { SHIFTJIS_CHARSET, FW_NORMAL, 18, 18, 96, "System" },
6410 { SHIFTJIS_CHARSET, FW_NORMAL, 22, 22, 120, "System" },
6411 { HANGEUL_CHARSET, FW_NORMAL, 16, 16, 96, "System" },
6412 { HANGEUL_CHARSET, FW_NORMAL, 20, 20, 120, "System" },
6413 { DEFAULT_CHARSET, FW_BOLD, 16, 16, 96, "System" },
6414 { DEFAULT_CHARSET, FW_BOLD, 20, 20, 120, "System" },
6415 { 0 }
6416 },
6417 { /* DEVICE_DEFAULT_FONT */
6418 { SHIFTJIS_CHARSET, FW_NORMAL, 18, 18, 96, "System" },
6419 { SHIFTJIS_CHARSET, FW_NORMAL, 22, 22, 120, "System" },
6420 { HANGEUL_CHARSET, FW_NORMAL, 16, 16, 96, "System" },
6421 { HANGEUL_CHARSET, FW_NORMAL, 20, 20, 120, "System" },
6422 { DEFAULT_CHARSET, FW_BOLD, 16, 16, 96, "System" },
6423 { DEFAULT_CHARSET, FW_BOLD, 20, 20, 120, "System" },
6424 { 0 }
6425 },
6426 { /* DEFAULT_GUI_FONT */
6427 { SHIFTJIS_CHARSET, FW_NORMAL, -11, 13, 96, "MS Shell Dlg" },
6428 { SHIFTJIS_CHARSET, FW_NORMAL, -13, 16, 120, "MS Shell Dlg" },
6429 { SHIFTJIS_CHARSET, FW_NORMAL, -12, 15, 96, "?MS UI Gothic" },
6430 { SHIFTJIS_CHARSET, FW_NORMAL, -15, 18, 120, "?MS UI Gothic" },
6431 { HANGEUL_CHARSET, FW_NORMAL, -11, 13, 96, "MS Shell Dlg" },
6432 { HANGEUL_CHARSET, FW_NORMAL, -13, 16, 120, "MS Shell Dlg" },
6433 { HANGEUL_CHARSET, FW_NORMAL, -12, 15, 96, "?Gulim" },
6434 { HANGEUL_CHARSET, FW_NORMAL, -15, 18, 120, "?Gulim" },
6435 { GB2312_CHARSET, FW_NORMAL, -11, 13, 96, "MS Shell Dlg" },
6436 { GB2312_CHARSET, FW_NORMAL, -13, 16, 120, "MS Shell Dlg" },
6437 { GB2312_CHARSET, FW_NORMAL, -12, 15, 96, "?SimHei" },
6438 { GB2312_CHARSET, FW_NORMAL, -15, 18, 120, "?SimHei" },
6439 { CHINESEBIG5_CHARSET, FW_NORMAL, -12, 15, 96, "?MingLiU" },
6440 { CHINESEBIG5_CHARSET, FW_NORMAL, -15, 18, 120, "?MingLiU" },
6441 { DEFAULT_CHARSET, FW_NORMAL, -11, 13, 96, "MS Shell Dlg" },
6442 { DEFAULT_CHARSET, FW_NORMAL, -13, 16, 120, "MS Shell Dlg" },
6443 { 0 }
6444 }
6445 };
6446 int i, j;
6447
6448 for (i = 0; i < ARRAY_SIZE(font); i++)
6449 {
6450 HFONT hfont;
6451 LOGFONTA lf;
6452 int ret, height;
6453
6455 ok(hfont != 0, "%d: GetStockObject(%d) failed\n", i, font[i]);
6456
6457 ret = GetObjectA(hfont, sizeof(lf), &lf);
6458 ok(ret == sizeof(lf), "%d: GetObject returned %d instead of sizeof(LOGFONT)\n", i, ret);
6459
6460 for (j = 0; td[i][j].face_name[0] != 0; j++)
6461 {
6462 if ((lf.lfCharSet != td[i][j].charset && td[i][j].charset != DEFAULT_CHARSET) ||
6463 (system_lang_id != td[i][j].lang_id && td[i][j].lang_id != LANG_NEUTRAL) ||
6464 (td[i][j].face_name[0] != '?' && strcmp(lf.lfFaceName, td[i][j].face_name)))
6465 {
6466 continue;
6467 }
6468
6469 ret = get_font_dpi(&lf, &height);
6470 if (ret != td[i][j].dpi)
6471 {
6472 trace("%d(%d): font %s %d dpi doesn't match test data %d\n",
6473 i, j, lf.lfFaceName, ret, td[i][j].dpi);
6474 continue;
6475 }
6476
6477 /* FIXME: Remove once Wine is fixed */
6478 todo_wine_if (td[i][j].dpi != 96 &&
6479 /* MS Sans Serif for 120 dpi and higher should include 12 pixel bitmap set */
6480 ((!strcmp(td[i][j].face_name, "MS Sans Serif") && td[i][j].height == 12) ||
6481 /* System for 120 dpi and higher should include 20 pixel bitmap set */
6482 (!strcmp(td[i][j].face_name, "System") && td[i][j].height > 16)))
6483 ok(height == td[i][j].height_pixels, "%d(%d): expected height %d, got %d\n", i, j, td[i][j].height_pixels, height);
6484
6485 ok(td[i][j].weight == lf.lfWeight, "%d(%d): expected lfWeight %d, got %ld\n", i, j, td[i][j].weight, lf.lfWeight);
6486 ok(td[i][j].height == lf.lfHeight, "%d(%d): expected lfHeight %d, got %ld\n", i, j, td[i][j].height, lf.lfHeight);
6487 if (td[i][j].face_name[0] == '?')
6488 {
6489 /* Wine doesn't have this font, skip this case for now.
6490 Actually, the face name is localized on Windows and varies
6491 dpending on Windows versions (e.g. Japanese NT4 vs win2k). */
6492 trace("%d(%d): default gui font is %s\n", i, j, lf.lfFaceName);
6493 }
6494 else
6495 {
6496 ok(!strcmp(td[i][j].face_name, lf.lfFaceName), "%d(%d): expected lfFaceName %s, got %s\n", i, j, td[i][j].face_name, lf.lfFaceName);
6497 }
6498 break;
6499 }
6500 }
6501}
6502
6503static void test_max_height(void)
6504{
6505 HDC hdc;
6506 LOGFONTA lf;
6507 HFONT hfont, hfont_old;
6508 TEXTMETRICA tm1, tm;
6509 BOOL r;
6510 LONG invalid_height[] = { -65536, -123456, 123456 };
6511 size_t i;
6512
6513 memset(&tm1, 0, sizeof(tm1));
6514 memset(&lf, 0, sizeof(lf));
6515 strcpy(lf.lfFaceName, "Tahoma");
6516 lf.lfHeight = -1;
6517
6518 hdc = GetDC(NULL);
6519
6520 /* get 1 ppem value */
6522 hfont_old = SelectObject(hdc, hfont);
6523 r = GetTextMetricsA(hdc, &tm1);
6524 ok(r, "GetTextMetrics failed\n");
6525 ok(tm1.tmHeight > 0, "expected a positive value, got %ld\n", tm1.tmHeight);
6526 ok(tm1.tmAveCharWidth > 0, "expected a positive value, got %ld\n", tm1.tmAveCharWidth);
6527 DeleteObject(SelectObject(hdc, hfont_old));
6528
6529 /* test the largest value */
6530 lf.lfHeight = -((1 << 14) - 1);
6532 hfont_old = SelectObject(hdc, hfont);
6533 memset(&tm, 0, sizeof(tm));
6534 r = GetTextMetricsA(hdc, &tm);
6535 ok(r, "GetTextMetrics failed\n");
6536 ok(tm.tmHeight > tm1.tmHeight,
6537 "expected greater than 1 ppem value (%ld), got %ld\n", tm1.tmHeight, tm.tmHeight);
6538 ok(tm.tmAveCharWidth > tm1.tmAveCharWidth,
6539 "expected greater than 1 ppem value (%ld), got %ld\n", tm1.tmAveCharWidth, tm.tmAveCharWidth);
6540 DeleteObject(SelectObject(hdc, hfont_old));
6541
6542 /* test an invalid value */
6543 for (i = 0; i < ARRAY_SIZE(invalid_height); i++) {
6544 winetest_push_context("height=%ld", invalid_height[i]);
6545 lf.lfHeight = invalid_height[i];
6547 hfont_old = SelectObject(hdc, hfont);
6548 memset(&tm, 0, sizeof(tm));
6549 r = GetTextMetricsA(hdc, &tm);
6550 if (r)
6551 {
6552 ok(r, "GetTextMetrics failed\n");
6553 ok(tm.tmHeight == tm1.tmHeight,
6554 "expected 1 ppem value (%ld), got %ld\n", tm1.tmHeight, tm.tmHeight);
6555 ok(tm.tmAveCharWidth == tm1.tmAveCharWidth,
6556 "expected 1 ppem value (%ld), got %ld\n", tm1.tmAveCharWidth, tm.tmAveCharWidth);
6557 DeleteObject(SelectObject(hdc, hfont_old));
6558 }
6560 }
6561
6562 ReleaseDC(NULL, hdc);
6563 return;
6564}
6565
6566static void test_vertical_order(void)
6567{
6568 struct enum_font_data efd;
6569 LOGFONTA lf;
6570 HDC hdc;
6571 int i, j;
6572
6574 ok(hdc != NULL, "CreateCompatibleDC failed\n");
6575
6576 memset(&lf, 0, sizeof(lf));
6579 lf.lfHeight = 16;
6580 lf.lfWidth = 16;
6582 lf.lfItalic = FALSE;
6584 memset( &efd, 0, sizeof(efd) );
6586 for (i = 0; i < efd.total; i++)
6587 {
6588 if (efd.lf[i].lfFaceName[0] != '@') continue;
6589 for (j = 0; j < efd.total; j++)
6590 {
6591 if (!strcmp(efd.lf[i].lfFaceName + 1, efd.lf[j].lfFaceName))
6592 {
6593 ok(i > j,"Found vertical font %s before its horizontal version\n", efd.lf[i].lfFaceName);
6594 break;
6595 }
6596 }
6597 }
6598 free( efd.lf );
6599 DeleteDC( hdc );
6600}
6601
6602static void test_GetCharWidth32(void)
6603{
6604 BOOL ret;
6605 HDC hdc;
6606 LOGFONTA lf;
6607 HFONT hfont;
6608 INT bufferA;
6609 INT bufferW;
6610 HWND hwnd;
6611
6612 memset(&lf, 0, sizeof(lf));
6613 strcpy(lf.lfFaceName, "System");
6614 lf.lfHeight = 20;
6615
6617 hdc = GetDC(0);
6619
6620 ret = GetCharWidth32W(hdc, 'a', 'a', &bufferW);
6621 ok(ret, "GetCharWidth32W should have succeeded\n");
6622 ret = GetCharWidth32A(hdc, 'a', 'a', &bufferA);
6623 ok(ret, "GetCharWidth32A should have succeeded\n");
6624 ok (bufferA == bufferW, "Widths should be the same\n");
6625 ok (bufferA > 0," Width should be greater than zero\n");
6626
6629 ReleaseDC(NULL, hdc);
6630
6631 memset(&lf, 0, sizeof(lf));
6632 strcpy(lf.lfFaceName, "Tahoma");
6633 lf.lfHeight = 20;
6634
6636 hwnd = CreateWindowExA(0, "static", "", WS_POPUP, 0,0,100,100,
6637 0, 0, 0, NULL);
6638 hdc = GetDC(hwnd);
6641
6642 ret = GetCharWidth32W(hdc, 'a', 'a', &bufferW);
6643 ok(ret, "GetCharWidth32W should have succeeded\n");
6644 ok (bufferW > 0," Width should be greater than zero\n");
6645 SetWindowExtEx(hdc, -1,-1,NULL);
6647 ret = GetCharWidth32W(hdc, 'a', 'a', &bufferW);
6648 ok(ret, "GetCharWidth32W should have succeeded\n");
6649 ok (bufferW > 0," Width should be greater than zero\n");
6651 ret = GetCharWidth32W(hdc, 'a', 'a', &bufferW);
6652 ok(ret, "GetCharWidth32W should have succeeded\n");
6653 ok (bufferW > 0," Width should be greater than zero\n");
6654 SetWindowExtEx(hdc, 1,1,NULL);
6656 ret = GetCharWidth32W(hdc, 'a', 'a', &bufferW);
6657 ok(ret, "GetCharWidth32W should have succeeded\n");
6658 ok (bufferW > 0," Width should be greater than zero\n");
6660 ret = GetCharWidth32W(hdc, 'a', 'a', &bufferW);
6661 ok(ret, "GetCharWidth32W should have succeeded\n");
6662 ok (bufferW > 0," Width should be greater than zero\n");
6663
6664 ReleaseDC(hwnd, hdc);
6666
6667 hwnd = CreateWindowExA(WS_EX_LAYOUTRTL, "static", "", WS_POPUP, 0,0,100,100,
6668 0, 0, 0, NULL);
6669 hdc = GetDC(hwnd);
6672
6673 ret = GetCharWidth32W(hdc, 'a', 'a', &bufferW);
6674 ok(ret, "GetCharWidth32W should have succeeded\n");
6675 ok (bufferW > 0," Width should be greater than zero\n");
6676 SetWindowExtEx(hdc, -1,-1,NULL);
6678 ret = GetCharWidth32W(hdc, 'a', 'a', &bufferW);
6679 ok(ret, "GetCharWidth32W should have succeeded\n");
6680 ok (bufferW > 0," Width should be greater than zero\n");
6682 ret = GetCharWidth32W(hdc, 'a', 'a', &bufferW);
6683 ok(ret, "GetCharWidth32W should have succeeded\n");
6684 ok (bufferW > 0," Width should be greater than zero\n");
6685 SetWindowExtEx(hdc, 1,1,NULL);
6687 ret = GetCharWidth32W(hdc, 'a', 'a', &bufferW);
6688 ok(ret, "GetCharWidth32W should have succeeded\n");
6689 ok (bufferW > 0," Width should be greater than zero\n");
6691 ret = GetCharWidth32W(hdc, 'a', 'a', &bufferW);
6692 ok(ret, "GetCharWidth32W should have succeeded\n");
6693 ok (bufferW > 0," Width should be greater than zero\n");
6694
6695 ReleaseDC(hwnd, hdc);
6698}
6699
6700static void test_fake_bold_font(void)
6701{
6702 static const MAT2 x2_mat = { {0,2}, {0,0}, {0,0}, {0,2} };
6703 HDC hdc;
6704 LOGFONTA lf;
6705 BOOL ret;
6706 struct glyph_data {
6708 ABC abc;
6709 INT w;
6710 GLYPHMETRICS gm;
6711 } data[4];
6712 int i;
6713 DWORD r;
6714
6715 /* Test outline font */
6716 memset(&lf, 0, sizeof(lf));
6717 strcpy(lf.lfFaceName, "Wingdings");
6719
6720 hdc = GetDC(NULL);
6721
6722 for (i = 0; i <= 1; i++)
6723 {
6724 HFONT hfont, hfont_old;
6725
6726 lf.lfWeight = i ? FW_BOLD : FW_NORMAL;
6728 hfont_old = SelectObject(hdc, hfont);
6729
6731 ok(ret, "got %d\n", ret);
6732 ret = GetCharABCWidthsA(hdc, 0x76, 0x76, &data[i].abc);
6733 ok(ret, "got %d\n", ret);
6734 data[i].w = data[i].abc.abcA + data[i].abc.abcB + data[i].abc.abcC;
6735 r = GetGlyphOutlineA(hdc, 0x76, GGO_METRICS, &data[i].gm, 0, NULL, &x2_mat);
6736 ok(r != GDI_ERROR, "got %d\n", ret);
6737
6738 SelectObject(hdc, hfont_old);
6740 }
6741 ReleaseDC(NULL, hdc);
6742
6743 /* compare results (outline) */
6744 ok(data[0].tm.tmHeight == data[1].tm.tmHeight,
6745 "expected %ld, got %ld\n", data[0].tm.tmHeight, data[1].tm.tmHeight);
6746 ok(data[0].tm.tmAscent == data[1].tm.tmAscent,
6747 "expected %ld, got %ld\n", data[0].tm.tmAscent, data[1].tm.tmAscent);
6748 ok(data[0].tm.tmDescent == data[1].tm.tmDescent,
6749 "expected %ld, got %ld\n", data[0].tm.tmDescent, data[1].tm.tmDescent);
6750 ok(data[0].tm.tmAveCharWidth + 1 == data[1].tm.tmAveCharWidth,
6751 "expected %ld, got %ld\n", data[0].tm.tmAveCharWidth + 1, data[1].tm.tmAveCharWidth);
6752 ok(data[0].tm.tmMaxCharWidth + 1 == data[1].tm.tmMaxCharWidth,
6753 "expected %ld, got %ld\n", data[0].tm.tmMaxCharWidth + 1, data[1].tm.tmMaxCharWidth);
6754 ok(data[0].tm.tmOverhang == data[1].tm.tmOverhang,
6755 "expected %ld, got %ld\n", data[0].tm.tmOverhang, data[1].tm.tmOverhang);
6756 ok(data[0].w + 1 == data[1].w,
6757 "expected %d, got %d\n", data[0].w + 1, data[1].w);
6758
6759 ok(data[0].gm.gmCellIncX + 1 == data[1].gm.gmCellIncX,
6760 "expected %d, got %d\n", data[0].gm.gmCellIncX + 1, data[1].gm.gmCellIncX);
6761 ok(data[0].gm.gmCellIncY == data[1].gm.gmCellIncY,
6762 "expected %d, got %d\n", data[0].gm.gmCellIncY, data[1].gm.gmCellIncY);
6763
6764 /* Test bitmap font */
6765 memset(&data, 0xaa, sizeof(data));
6766 memset(&lf, 0, sizeof(lf));
6767 strcpy(lf.lfFaceName, "Courier");
6769
6770 hdc = GetDC(NULL);
6771
6772 for (i = 0; i < 4; i++)
6773 {
6774 HFONT hfont, hfont_old;
6775
6776 lf.lfWeight = (i % 2) ? FW_BOLD : FW_NORMAL;
6777 lf.lfHeight = (i > 1) ? data[0].tm.tmHeight * x2_mat.eM11.value : 0;
6779 hfont_old = SelectObject(hdc, hfont);
6780
6782 ok(ret, "got %d\n", ret);
6783 ret = GetCharWidth32A(hdc, 0x76, 0x76, &data[i].w);
6784 ok(ret, "got %d\n", ret);
6785
6786 SelectObject(hdc, hfont_old);
6788 }
6789 ReleaseDC(NULL, hdc);
6790
6791 /* compare results (bitmap) */
6792 for (i = 0; i < 4; i+=2)
6793 {
6794 int diff = (i > 1) ? x2_mat.eM11.value : 1;
6795 if (data[i].tm.tmPitchAndFamily & TMPF_TRUETYPE)
6796 {
6797 skip("TrueType font is selected (expected a bitmap one)\n");
6798 continue;
6799 }
6800 ok(data[i].tm.tmHeight == data[i+1].tm.tmHeight,
6801 "expected %ld, got %ld\n", data[i].tm.tmHeight, data[i+1].tm.tmHeight);
6802 ok(data[i].tm.tmAscent == data[i+1].tm.tmAscent,
6803 "expected %ld, got %ld\n", data[i].tm.tmAscent, data[i+1].tm.tmAscent);
6804 ok(data[i].tm.tmDescent == data[i+1].tm.tmDescent,
6805 "expected %ld, got %ld\n", data[i].tm.tmDescent, data[i+1].tm.tmDescent);
6806 ok(data[i+1].tm.tmAveCharWidth - data[i].tm.tmAveCharWidth == diff,
6807 "expected %d, got %ld\n", diff, data[i+1].tm.tmAveCharWidth - data[i].tm.tmAveCharWidth);
6808 ok(data[i+1].tm.tmMaxCharWidth - data[i].tm.tmMaxCharWidth == diff,
6809 "expected %d, got %ld\n", diff, data[i+1].tm.tmMaxCharWidth - data[i].tm.tmMaxCharWidth);
6810 ok(data[i].tm.tmOverhang == 0,
6811 "expected 0, got %ld\n", data[i].tm.tmOverhang);
6812 ok(data[i+1].tm.tmOverhang == 1,
6813 "expected 1, got %ld\n", data[i+1].tm.tmOverhang);
6814 ok(data[i].w + 1 == data[i+1].w,
6815 "expected %d, got %d\n", data[i].w + 1, data[i+1].w);
6816 }
6817}
6818
6820{
6821 const WCHAR text[] = L"#!/bin/sh";
6822 const struct {
6823 LPCSTR face;
6824 BYTE charset;
6825 } bitmap_font_list[] = {
6826 { "Courier", ANSI_CHARSET },
6827 { "Small Fonts", ANSI_CHARSET },
6828 { "Fixedsys", DEFAULT_CHARSET },
6829 { "System", DEFAULT_CHARSET }
6830 };
6831 HDC hdc;
6832 LOGFONTA lf;
6833 HFONT hFont;
6834 CHAR facename[LF_FACESIZE];
6835 BITMAPINFO bmi;
6836 HBITMAP hBmp[2];
6837 void *pixels[2];
6838 int i, j;
6839 DWORD ret;
6840 BITMAP bmp;
6842 CHARSETINFO ci;
6843 BYTE chr = '\xA9';
6844
6846 ok(hdc != NULL, "CreateCompatibleDC failed\n");
6847
6848 memset(&bmi, 0, sizeof(bmi));
6849 bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
6850 bmi.bmiHeader.biBitCount = 32;
6851 bmi.bmiHeader.biPlanes = 1;
6852 bmi.bmiHeader.biWidth = 128;
6853 bmi.bmiHeader.biHeight = 32;
6855
6856 for (i = 0; i < ARRAY_SIZE(bitmap_font_list); i++) {
6857 memset(&lf, 0, sizeof(lf));
6858 lf.lfCharSet = bitmap_font_list[i].charset;
6859 strcpy(lf.lfFaceName, bitmap_font_list[i].face);
6861 ok(hFont != NULL, "Can't create font (%s:%d)\n", lf.lfFaceName, lf.lfCharSet);
6864 ok(ret, "GetTextMetric failed\n");
6865 ret = GetTextFaceA(hdc, sizeof(facename), facename);
6866 ok(ret, "GetTextFace failed\n");
6867 if (tm.tmPitchAndFamily & TMPF_TRUETYPE) {
6868 skip("TrueType font (%s) was selected for \"%s\"\n", facename, bitmap_font_list[i].face);
6869 continue;
6870 }
6871 if (lstrcmpiA(facename, lf.lfFaceName) != 0) {
6872 skip("expected %s, got %s\n", lf.lfFaceName, facename);
6873 continue;
6874 }
6875
6876 for (j = 0; j < 2; j++) {
6877 HBITMAP hBmpPrev;
6878 hBmp[j] = CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS, &pixels[j], NULL, 0);
6879 ok(hBmp[j] != NULL, "Can't create DIB\n");
6880 hBmpPrev = SelectObject(hdc, hBmp[j]);
6881 switch (j) {
6882 case 0:
6883 ret = ExtTextOutW(hdc, 0, 0, 0, NULL, text, lstrlenW(text), NULL);
6884 break;
6885 case 1:
6886 {
6887 int len = lstrlenW(text);
6888 WORD *indices = malloc(len * sizeof(WORD));
6890 ok(ret, "GetGlyphIndices failed\n");
6891 ok(memcmp(indices, text, sizeof(WORD) * len) == 0,
6892 "Glyph indices and text are different for %s:%d\n", lf.lfFaceName, tm.tmCharSet);
6893 ret = ExtTextOutW(hdc, 0, 0, ETO_GLYPH_INDEX, NULL, indices, len, NULL);
6894 free(indices);
6895 break;
6896 }
6897 }
6898 ok(ret, "ExtTextOutW failed\n");
6899 SelectObject(hdc, hBmpPrev);
6900 }
6901
6902 GetObjectA(hBmp[0], sizeof(bmp), &bmp);
6904 "Images are different (%s:%d)\n", lf.lfFaceName, tm.tmCharSet);
6905
6907 if (!ret) {
6908 skip("Can't get charset info for (%s:%d)\n", lf.lfFaceName, tm.tmCharSet);
6909 goto next;
6910 }
6911 if (IsDBCSLeadByteEx(ci.ciACP, chr)) {
6912 skip("High-ascii character is not defined in codepage %d\n", ci.ciACP);
6913 goto next;
6914 }
6915
6916 for (j = 0; j < 2; j++) {
6917 HBITMAP hBmpPrev;
6918 WORD code;
6919 hBmpPrev = SelectObject(hdc, hBmp[j]);
6920 switch (j) {
6921 case 0:
6922 ret = ExtTextOutA(hdc, 100, 0, 0, NULL, (LPCSTR)&chr, 1, NULL);
6923 break;
6924 case 1:
6925 ret = GetGlyphIndicesA(hdc, (LPCSTR)&chr, 1, &code, 0);
6926 ok(ret, "GetGlyphIndices failed\n");
6927 ok(code == chr, "expected %02x, got %02x (%s:%d)\n", chr, code, lf.lfFaceName, tm.tmCharSet);
6928 ret = ExtTextOutA(hdc, 100, 0, ETO_GLYPH_INDEX, NULL, (LPCSTR)&code, 1, NULL);
6929 break;
6930 }
6931 ok(ret, "ExtTextOutA failed\n");
6932 SelectObject(hdc, hBmpPrev);
6933 }
6934
6936 "Images are different (%s:%d)\n", lf.lfFaceName, tm.tmCharSet);
6937 next:
6938 for (j = 0; j < 2; j++)
6939 DeleteObject(hBmp[j]);
6942 }
6943
6944 DeleteDC(hdc);
6945}
6946
6947static void test_GetCharWidthI(void)
6948{
6949 static const char *teststr = "wine ";
6950 HFONT hfont, prev_hfont;
6951 WORD glyphs[5];
6952 INT widths[5];
6953 INT width;
6954 LOGFONTA lf;
6955 ABC abc[5], abc1;
6956 int len, i;
6957 DWORD nb;
6958 BOOL ret;
6959 HDC hdc;
6960
6961 memset(&lf, 0, sizeof(lf));
6962 strcpy(lf.lfFaceName, "Tahoma");
6963 lf.lfHeight = -20;
6964
6965 hdc = GetDC(0);
6966
6968 prev_hfont = SelectObject(hdc, hfont);
6969
6970 len = strlen(teststr);
6971 nb = GetGlyphIndicesA(hdc, teststr, len, glyphs, 0);
6972 ok(nb == len, "\n");
6973
6974 memset(abc, 0xcc, sizeof(abc));
6975 ret = GetCharABCWidthsI(hdc, 0, len, glyphs, abc);
6976 ok(ret, "GetCharABCWidthsI failed\n");
6977
6978 memset(&abc1, 0xcc, sizeof(abc1));
6979 ret = GetCharABCWidthsI(hdc, glyphs[0], 1, NULL, &abc1);
6980 ok(ret, "GetCharABCWidthsI failed\n");
6981 ok(!memcmp(&abc1, abc, sizeof(abc1)), "unexpected abc1\n");
6982
6983 memset(widths, 0xcc, sizeof(widths));
6984 ret = GetCharWidthI(hdc, 0, len, glyphs, widths);
6985 ok(ret, "GetCharWidthI failed\n");
6986
6987 width = 0xdeadbeef;
6988 ret = GetCharWidthI(hdc, glyphs[0], 1, NULL, &width);
6989 ok(ret, "GetCharWidthI failed\n");
6990 ok(width == widths[0], "unexpected width %u\n", width);
6991
6992 for (i = 0; i < len; i++)
6993 ok(widths[i] == abc[i].abcA + abc[i].abcB + abc[i].abcC, "%u, glyph %u, got width %d\n",
6994 i, glyphs[i], widths[i]);
6995
6996 DeleteObject(SelectObject(hdc, prev_hfont));
6997 ReleaseDC(0, hdc);
6998}
6999
7001{
7002 BOOL *found_font = (BOOL *)lparam;
7003 *found_font = TRUE;
7004 return 1;
7005}
7006
7007static void test_long_names(void)
7008{
7009 char ttf_name[MAX_PATH];
7010 LOGFONTA font = {0};
7011 HFONT handle_font;
7012 BOOL found_font;
7013 int ret;
7014 HDC dc;
7015
7016 if (!write_ttf_file("wine_longname.ttf", ttf_name))
7017 {
7018 skip("Failed to create ttf file for testing\n");
7019 return;
7020 }
7021
7022 dc = GetDC(NULL);
7023
7024 ret = AddFontResourceExA(ttf_name, FR_PRIVATE, 0);
7025 ok(ret, "AddFontResourceEx() failed\n");
7026
7027 strcpy(font.lfFaceName, "wine_3_this_is_a_very_long_name");
7028 found_font = FALSE;
7029 EnumFontFamiliesExA(dc, &font, long_enum_proc, (LPARAM)&found_font, 0);
7030 ok(found_font == TRUE, "EnumFontFamiliesExA didn't find font.\n");
7031
7032 strcpy(font.lfFaceName, "wine_2_this_is_a_very_long_name");
7033 found_font = FALSE;
7034 EnumFontFamiliesExA(dc, &font, long_enum_proc, (LPARAM)&found_font, 0);
7035 ok(found_font == TRUE, "EnumFontFamiliesExA didn't find font.\n");
7036
7037 strcpy(font.lfFaceName, "wine_1_this_is_a_very_long_name");
7038 found_font = FALSE;
7039 EnumFontFamiliesExA(dc, &font, long_enum_proc, (LPARAM)&found_font, 0);
7040 ok(found_font == FALSE, "EnumFontFamiliesExA must not find font.\n");
7041
7042 handle_font = CreateFontIndirectA(&font);
7043 ok(handle_font != NULL, "CreateFontIndirectA failed\n");
7044 DeleteObject(handle_font);
7045
7046 ret = RemoveFontResourceExA(ttf_name, FR_PRIVATE, 0);
7047 ok(ret, "RemoveFontResourceEx() failed\n");
7048
7049 DeleteFileA(ttf_name);
7050 ReleaseDC(NULL, dc);
7051}
7052
7053static void test_ttf_names(void)
7054{
7055 struct enum_fullname_data efnd;
7056 char ttf_name[MAX_PATH], ttf_name_bold[MAX_PATH];
7057 LOGFONTA font = {0};
7058 HFONT handle_font;
7059 int ret;
7060 HDC dc;
7061
7062 if (!write_ttf_file("wine_ttfnames.ttf", ttf_name))
7063 {
7064 skip("Failed to create ttf file for testing\n");
7065 return;
7066 }
7067
7068 if (!write_ttf_file("wine_ttfnames_bold.ttf", ttf_name_bold))
7069 {
7070 skip("Failed to create ttf file for testing\n");
7071 DeleteFileA(ttf_name);
7072 return;
7073 }
7074
7075 ret = AddFontResourceExA(ttf_name, FR_PRIVATE, 0);
7076 ok(ret, "AddFontResourceEx() failed\n");
7077
7078 ret = AddFontResourceExA(ttf_name_bold, FR_PRIVATE, 0);
7079 ok(ret, "AddFontResourceEx() failed\n");
7080
7081 dc = GetDC(NULL);
7082
7083 strcpy(font.lfFaceName, "Wine_TTF_Names_Long_Family1_Con");
7084 memset(&efnd, 0, sizeof(efnd));
7086 ok(efnd.total == 0, "EnumFontFamiliesExA must not find font.\n");
7087
7088 /* Windows doesn't match with Typographic/Preferred Family tags */
7089 strcpy(font.lfFaceName, "Wine TTF Names Long Family1");
7090 memset(&efnd, 0, sizeof(efnd));
7092 ok(efnd.total == 0, "EnumFontFamiliesExA must not find font.\n");
7093
7094 strcpy(font.lfFaceName, "Wine TTF Names Long Family1 Ext");
7095 memset(&efnd, 0, sizeof(efnd));
7097 ok(efnd.total == 2, "EnumFontFamiliesExA found %d fonts, expected 2.\n", efnd.total);
7098
7099 strcpy(font.lfFaceName, "Wine TTF Names Long Family1 Con");
7100 memset(&efnd, 0, sizeof(efnd));
7102 ok(efnd.total == 2, "EnumFontFamiliesExA found %d fonts, expected 2.\n", efnd.total);
7103
7104 handle_font = CreateFontIndirectA(&font);
7105 ok(handle_font != NULL, "CreateFontIndirectA failed\n");
7106 DeleteObject(handle_font);
7107
7108 ret = RemoveFontResourceExA(ttf_name_bold, FR_PRIVATE, 0);
7109 ok(ret, "RemoveFontResourceEx() failed\n");
7110
7111 DeleteFileA(ttf_name_bold);
7112
7113 ret = RemoveFontResourceExA(ttf_name, FR_PRIVATE, 0);
7114 ok(ret, "RemoveFontResourceEx() failed\n");
7115
7116 DeleteFileA(ttf_name);
7117 ReleaseDC(NULL, dc);
7118}
7119
7120static void test_lang_names(void)
7121{
7122 static const WCHAR name_cond_ja_w[] = L"\x30d5\x30a9\x30f3\x30c8\x540d Cond (ja)";
7123 static const WCHAR name_cond_ja_reg_w[] = L"\x30d5\x30a9\x30f3\x30c8\x540d Cond (ja) Reg";
7124 static const WCHAR name_cond_ja_reg_ja_w[] = L"\x30d5\x30a9\x30f3\x30c8\x540d Cond (ja) Reg (ja)";
7125 static const WCHAR name_wws_ja_w[] = L"\x30d5\x30a9\x30f3\x30c8\x540d WWS (ja)";
7126
7127 struct enum_fullname_data efnd;
7128 struct enum_fullname_data_w efnd_w;
7129 char ttf_name[MAX_PATH], ttf_name2[MAX_PATH], ttf_name3[MAX_PATH];
7130 LOGFONTA font = {0};
7131 LOGFONTW font_w = {0};
7132 int ret, i;
7133 HDC dc;
7134 const WCHAR *primary_family, *primary_fullname;
7135
7137 {
7138 skip( "Primary language is neither English nor Japanese, skipping test\n" );
7139 return;
7140 }
7141
7142 if (!write_ttf_file( "wine_langnames.ttf", ttf_name ))
7143 {
7144 skip( "Failed to create ttf file for testing\n" );
7145 return;
7146 }
7147
7148 if (!write_ttf_file( "wine_langnames2.ttf", ttf_name2 ))
7149 {
7150 skip( "Failed to create ttf file for testing\n" );
7151 DeleteFileA( ttf_name );
7152 return;
7153 }
7154
7155 if (!write_ttf_file( "wine_langnames3.ttf", ttf_name3 ))
7156 {
7157 skip( "Failed to create ttf file for testing\n" );
7158 DeleteFileA( ttf_name2 );
7159 DeleteFileA( ttf_name );
7160 return;
7161 }
7162
7163 ret = AddFontResourceExA( ttf_name, FR_PRIVATE, 0 );
7164 ok( ret, "AddFontResourceEx() failed\n" );
7165
7166 dc = GetDC( NULL );
7167
7169 {
7170 primary_family = L"Wine Lang Cond (en)";
7171 primary_fullname = L"Wine Lang Cond Reg (en)";
7172 }
7173 else
7174 {
7175 primary_family = name_cond_ja_w;
7176 primary_fullname = name_cond_ja_reg_w;
7177 }
7178
7179 for (i = 0; i < 3; ++i)
7180 {
7181 /* check that lookup by preferred or WWS family / full names or postscript FontName doesn't work */
7182
7183 strcpy( font.lfFaceName, "Wine Lang (en)" );
7184 memset( &efnd, 0, sizeof(efnd) );
7186 ok( efnd.total == 0, "%d: EnumFontFamiliesExA unexpected count %u.\n", i, efnd.total );
7187
7188 strcpy( font.lfFaceName, "Wine Lang Condensed Bold (ko)" );
7189 memset( &efnd, 0, sizeof(efnd) );
7191 ok( efnd.total == 0, "%d: EnumFontFamiliesExA unexpected count %u.\n", i, efnd.total );
7192
7193 wcscpy( font_w.lfFaceName, name_wws_ja_w );
7194 memset( &efnd_w, 0, sizeof(efnd_w) );
7195 EnumFontFamiliesExW( dc, &font_w, enum_fullname_data_proc_w, (LPARAM)&efnd_w, 0 );
7196 ok( efnd_w.total == 0, "%d: EnumFontFamiliesExA unexpected count %u.\n", i, efnd_w.total );
7197
7198 strcpy( font.lfFaceName, "Reg WWS (zh-tw)" );
7199 memset( &efnd, 0, sizeof(efnd) );
7201 ok( efnd.total == 0, "%d: EnumFontFamiliesExA unexpected count %u.\n", i, efnd.total );
7202
7203 strcpy( font.lfFaceName, "Wine Lang (en) Reg WWS (en)" );
7204 memset( &efnd, 0, sizeof(efnd) );
7206 ok( efnd.total == 0, "%d: EnumFontFamiliesExA unexpected count %u.\n", i, efnd.total );
7207
7208 strcpy( font.lfFaceName, "WineLangNamesRegular" );
7209 memset( &efnd, 0, sizeof(efnd) );
7211 ok( efnd.total == 0, "%d: EnumFontFamiliesExA unexpected count %u.\n", i, efnd.total );
7212
7213 /* then, the primary ttf family name always works */
7214
7215 wcscpy( font_w.lfFaceName, primary_family );
7216 memset( &efnd_w, 0, sizeof(efnd_w) );
7217 EnumFontFamiliesExW( dc, &font_w, enum_fullname_data_proc_w, (LPARAM)&efnd_w, 0 );
7218 ok( efnd_w.total == min( 2, i + 1 ), "%d: EnumFontFamiliesExA unexpected count %u.\n", i, efnd_w.total );
7219
7221 {
7222 wcscpy( font_w.lfFaceName, name_cond_ja_w );
7223 memset( &efnd_w, 0, sizeof(efnd_w) );
7224 EnumFontFamiliesExW( dc, &font_w, enum_fullname_data_proc_w, (LPARAM)&efnd_w, 0 );
7225 ok( efnd_w.total == 0, "%d: EnumFontFamiliesExA unexpected count %u.\n", i, efnd_w.total );
7226 }
7227
7228 /* if there is no primary ttf family name, the english ttf name, or postscript FamilyName are used instead */
7229
7230 strcpy( font.lfFaceName, "Wine_Lang_Names" );
7231 memset( &efnd, 0, sizeof(efnd) );
7233 if (i == 2)
7234 ok( efnd.total == 1, "%d: EnumFontFamiliesExA unexpected count %u.\n", i, efnd.total );
7235 else
7236 ok( efnd.total == 0, "%d: EnumFontFamiliesExA unexpected count %u.\n", i, efnd.total );
7237
7238 /* same goes for ttf full names */
7239
7240 wcscpy( font_w.lfFaceName, primary_fullname );
7241 memset( &efnd_w, 0, sizeof(efnd_w) );
7242 EnumFontFamiliesExW( dc, &font_w, enum_fullname_data_proc_w, (LPARAM)&efnd_w, 0 );
7243 ok( efnd_w.total == 1, "%d: EnumFontFamiliesExW unexpected count %u.\n", i, efnd_w.total );
7244
7245 if (efnd_w.total >= 1)
7246 {
7247 ok( !wcscmp( (WCHAR *)efnd_w.elf[0].elfLogFont.lfFaceName, primary_family ),
7248 "%d: (%d) unexpected lfFaceName %s\n", i, efnd_w.total, debugstr_w((WCHAR *)efnd_w.elf[0].elfLogFont.lfFaceName) );
7249 ok( !wcscmp( (WCHAR *)efnd_w.elf[0].elfFullName, primary_fullname ),
7250 "%d: (%d) unexpected elfFullName %s\n", i, efnd_w.total, debugstr_w((WCHAR *)efnd_w.elf[0].elfFullName) );
7251 ok( !wcscmp( (WCHAR *)efnd_w.elf[0].elfStyle, PRIMARYLANGID(GetSystemDefaultLangID()) == LANG_ENGLISH ? L"Reg (en)" : L"Reg (ja)" ),
7252 "%d: (%d) unexpected elfStyle %s\n", i, efnd_w.total, debugstr_w((WCHAR *)efnd_w.elf[0].elfStyle) );
7253 }
7254
7256 {
7257 wcscpy( font_w.lfFaceName, name_cond_ja_reg_w );
7258 memset( &efnd_w, 0, sizeof(efnd_w) );
7259 EnumFontFamiliesExW( dc, &font_w, enum_fullname_data_proc_w, (LPARAM)&efnd_w, 0 );
7260 ok( efnd_w.total == 0, "%d: EnumFontFamiliesExA unexpected count %u.\n", i, efnd_w.total );
7261 }
7262
7263 wcscpy( font_w.lfFaceName, L"Wine_Lang_Names_Regular" );
7264 memset( &efnd_w, 0, sizeof(efnd_w) );
7265 EnumFontFamiliesExW( dc, &font_w, enum_fullname_data_proc_w, (LPARAM)&efnd_w, 0 );
7266 ok( efnd_w.total == i, "%d: EnumFontFamiliesExW unexpected count %u.\n", i, efnd_w.total );
7267
7268 while (efnd_w.total--)
7269 {
7270 ok( !wcscmp( (WCHAR *)efnd_w.elf[efnd_w.total].elfLogFont.lfFaceName, efnd_w.total == 1 ? L"Wine_Lang_Names" : primary_family ),
7271 "%d: (%d) unexpected lfFaceName %s\n", i, efnd_w.total, debugstr_w((WCHAR *)efnd_w.elf[efnd_w.total].elfLogFont.lfFaceName) );
7272 ok( !wcscmp( (WCHAR *)efnd_w.elf[efnd_w.total].elfFullName, L"Wine_Lang_Names_Regular" ),
7273 "%d: (%d) unexpected elfFullName %s\n", i, efnd_w.total, debugstr_w((WCHAR *)efnd_w.elf[efnd_w.total].elfFullName) );
7275 ok( !wcscmp( (WCHAR *)efnd_w.elf[efnd_w.total].elfStyle, efnd_w.total == 1 ? L"Regular" : L"Reg (en)" ),
7276 "%d: (%d) unexpected elfStyle %s\n", i, efnd_w.total, debugstr_w((WCHAR *)efnd_w.elf[efnd_w.total].elfStyle) );
7277 else
7278 ok( !wcscmp( (WCHAR *)efnd_w.elf[0].elfStyle, L"Reg (ja)" ),
7279 "%d: (%d) unexpected elfStyle %s\n", i, efnd_w.total, debugstr_w((WCHAR *)efnd_w.elf[0].elfStyle) );
7280 }
7281
7283 {
7284 wcscpy( font_w.lfFaceName, name_cond_ja_reg_ja_w );
7285 memset( &efnd_w, 0, sizeof(efnd_w) );
7286 EnumFontFamiliesExW( dc, &font_w, enum_fullname_data_proc_w, (LPARAM)&efnd_w, 0 );
7287 ok( efnd_w.total == 0, "%d: EnumFontFamiliesExA unexpected count %u.\n", i, efnd_w.total );
7288 }
7289
7290 /* another language can also be used for lookup, if the primary langid isn't english, then
7291 english seems to have priority, otherwise or if english is already the primary langid,
7292 the family name with the smallest langid is used as secondary lookup language. */
7293
7294 strcpy( font.lfFaceName, "Wine Lang Cond (zh-tw)" );
7295 memset( &efnd, 0, sizeof(efnd) );
7298 ok( efnd.total == min( 2, i + 1 ), "%d: EnumFontFamiliesExA unexpected count %u.\n", i, efnd.total );
7299 else /* (zh-tw) doesn't match here probably because there's an (en) name too */
7300 ok( efnd.total == 0, "%d: EnumFontFamiliesExA unexpected count %u.\n", i, efnd.total );
7301
7302 strcpy( font.lfFaceName, "Wine Lang Cond (en)" );
7303 memset( &efnd, 0, sizeof(efnd) );
7305 /* either because it's the primary language, or because it's a secondary */
7306 ok( efnd.total == min( 2, i + 1 ), "%d: EnumFontFamiliesExA unexpected count %u.\n", i, efnd.total );
7307
7308 wcscpy( font_w.lfFaceName, L"Wine Police d'\xe9" "criture (fr)" );
7309 memset( &efnd_w, 0, sizeof(efnd_w) );
7310 EnumFontFamiliesExW( dc, &font_w, enum_fullname_data_proc_w, (LPARAM)&efnd_w, 0 );
7311 /* as wine_langnames3.sfd does not specify (en) name, (fr) is preferred */
7312 if (i == 2) ok( efnd_w.total == 1, "%d: EnumFontFamiliesExW unexpected count %u.\n", i, efnd_w.total );
7313 else ok( efnd_w.total == 0, "%d: EnumFontFamiliesExW unexpected count %u.\n", i, efnd_w.total );
7314
7315 /* case matching should not depend on the current locale */
7316 if (i == 2)
7317 {
7318 wcscpy( font_w.lfFaceName, L"Wine POLICE D'\xc9" "CRITURE (fr)" );
7319 memset( &efnd_w, 0, sizeof(efnd_w) );
7320 EnumFontFamiliesExW( dc, &font_w, enum_fullname_data_proc_w, (LPARAM)&efnd_w, 0 );
7321 ok( efnd_w.total == 1, "%d: EnumFontFamiliesExW unexpected count %u.\n", i, efnd_w.total );
7322 }
7323
7324 strcpy( font.lfFaceName, "Wine Lang Cond (ko)" );
7325 memset( &efnd, 0, sizeof(efnd) );
7327 ok( efnd.total == 0, "%d: EnumFontFamiliesExA unexpected count %u.\n", i, efnd.total );
7328
7329 /* that doesn't apply to full names */
7330
7331 strcpy( font.lfFaceName, "Wine Lang Cond Reg (zh-tw)" );
7332 memset( &efnd, 0, sizeof(efnd) );
7334 ok( efnd.total == 0, "%d: EnumFontFamiliesExA unexpected count %u.\n", i, efnd.total );
7335
7336 strcpy( font.lfFaceName, "Wine Lang Cond Reg (fr)" );
7337 memset( &efnd, 0, sizeof(efnd) );
7339 ok( efnd.total == 0, "%d: EnumFontFamiliesExA unexpected count %u.\n", i, efnd.total );
7340
7341 if (i == 0)
7342 {
7343 ret = AddFontResourceExA( ttf_name2, FR_PRIVATE, 0 );
7344 ok( ret, "AddFontResourceEx() failed\n" );
7345 }
7346 else if (i == 1)
7347 {
7348 ret = AddFontResourceExA( ttf_name3, FR_PRIVATE, 0 );
7349 ok( ret, "AddFontResourceEx() failed\n" );
7350 }
7351 }
7352
7353 ret = RemoveFontResourceExA( ttf_name3, FR_PRIVATE, 0 );
7354 ok( ret, "RemoveFontResourceEx() failed\n" );
7355
7356 DeleteFileA( ttf_name3 );
7357
7358 ret = RemoveFontResourceExA( ttf_name2, FR_PRIVATE, 0 );
7359 ok( ret, "RemoveFontResourceEx() failed\n" );
7360
7361 DeleteFileA( ttf_name2 );
7362
7363 ret = RemoveFontResourceExA( ttf_name, FR_PRIVATE, 0 );
7364 ok( ret, "RemoveFontResourceEx() failed\n" );
7365
7366 DeleteFileA( ttf_name );
7367 ReleaseDC( NULL, dc );
7368}
7369
7370typedef struct
7371{
7388
7389static void test_GetCharWidthInfo(void)
7390{
7391 HDC hdc;
7392 HFONT hfont, hfont_prev;
7393 LOGFONTA lf;
7394 BOOL r;
7395 DWORD ret, i;
7397 TT_Hori_Header hhea;
7398 struct char_width_info
7399 {
7400 INT lsb, rsb, unk;
7401 } info, info2;
7402 SHORT minLeftSideBearing, minRightSideBearing;
7403 POINT pt[2];
7404 const char* face_list[] = { "Symbol", "Ume Gothic", "MS Gothic" };
7405
7406 if (!pGetCharWidthInfo)
7407 {
7408 win_skip("GetCharWidthInfo is unavailable\n");
7409 return;
7410 }
7411
7412 hdc = GetDC(NULL);
7413
7414 /* test default (System) font */
7415 memset(&info, 0xaa, sizeof(info));
7416 r = pGetCharWidthInfo(hdc, &info);
7417 if (r) /* win10 1803 succeeds */
7418 {
7419 ok(info.lsb == 0, "expected 0, got %d\n", info.lsb);
7420 ok(info.rsb == 0, "expected 0, got %d\n", info.rsb);
7421 ok(info.unk == 0, "expected 0, got %d\n", info.unk);
7422 }
7423
7424 memset(&lf, 0, sizeof(lf));
7425 lf.lfWeight = FW_NORMAL;
7427 strcpy(lf.lfFaceName, "Tahoma");
7429 hfont_prev = SelectObject(hdc, hfont);
7430 ok(hfont_prev != NULL, "SelectObject failed\n");
7431
7432 ret = GetOutlineTextMetricsA(hdc, sizeof(otm), &otm);
7433 ok(ret != 0, "GetOutlineTextMetricsA failed\n");
7434 DeleteObject(SelectObject(hdc, hfont_prev));
7435
7436 /* test Tahoma at the em square size */
7437 lf.lfHeight = -(int)otm.otmEMSquare;
7439 hfont_prev = SelectObject(hdc, hfont);
7440 ok(hfont_prev != NULL, "SelectObject failed\n");
7441
7442 ret = GetFontData(hdc, MS_MAKE_TAG('h','h','e','a'), 0, &hhea, sizeof(hhea));
7443 ok(ret == sizeof(hhea), "got %lu\n", ret);
7444 minLeftSideBearing = GET_BE_WORD(hhea.minLeftSideBearing);
7445 minRightSideBearing = GET_BE_WORD(hhea.minRightSideBearing);
7446
7447 memset(&info, 0xaa, sizeof(info));
7448 r = pGetCharWidthInfo(hdc, &info);
7449 ok(r, "GetCharWidthInfo failed\n");
7450 ok(info.lsb == minLeftSideBearing, "expected %d, got %d\n", minLeftSideBearing, info.lsb);
7451 ok(info.rsb == minRightSideBearing, "expected %d, got %d\n", minRightSideBearing, info.rsb);
7452
7453 DeleteObject(SelectObject(hdc, hfont_prev));
7454
7455 /* these values are scaled, try with smaller size */
7456 lf.lfHeight /= 3;
7458 hfont_prev = SelectObject(hdc, hfont);
7459 ok(hfont_prev != NULL, "SelectObject failed\n");
7460
7461 memset(&info2, 0xaa, sizeof(info2));
7462 r = pGetCharWidthInfo(hdc, &info2);
7463 ok(r, "pGetCharWidthInfo failed\n");
7464 ok(info2.lsb == info.lsb/3, "expected %d, got %d\n", info.lsb/3, info2.lsb);
7465 ok(info2.rsb == info.rsb/3, "expected %d, got %d\n", info.rsb/3, info2.rsb);
7466
7467 DeleteObject(SelectObject(hdc, hfont_prev));
7468 ReleaseDC(NULL, hdc);
7469
7470 /* test with another mapping mode */
7471 hdc = GetDC(NULL);
7473 SetWindowExtEx(hdc, 2, 2, NULL);
7474 SetViewportExtEx(hdc, 1, 1, NULL);
7475
7476 memset(pt, 0, sizeof(pt));
7477 pt[0].y = otm.otmEMSquare;
7478 DPtoLP(hdc, pt, 1);
7479
7480 memset(&lf, 0, sizeof(lf));
7481 lf.lfWeight = FW_NORMAL;
7483 lf.lfHeight = -abs(pt[0].y);
7484 strcpy(lf.lfFaceName, "Tahoma");
7486 hfont_prev = SelectObject(hdc, hfont);
7487 ok(hfont_prev != NULL, "SelectObject failed\n");
7488
7489 memset(&info2, 0xaa, sizeof(info2));
7490 r = pGetCharWidthInfo(hdc, &info2);
7491 ok(r, "GetCharWidthInfo failed\n");
7492 pt[0].x = info.lsb; pt[0].y = 0;
7493 pt[1].x = info.rsb; pt[1].y = 0;
7494 DPtoLP(hdc, pt, 2);
7495 ok(pt[0].x == info2.lsb, "expected %ld, got %d\n", pt[0].x, info2.lsb);
7496 ok(pt[1].x == info2.rsb, "expected %ld, got %d\n", pt[1].x, info2.rsb);
7497
7498 DeleteObject(SelectObject(hdc, hfont_prev));
7499 ReleaseDC(NULL, hdc);
7500
7501 /* test with synthetic fonts */
7502 hdc = GetDC(NULL);
7503 for (i = 0; i < ARRAY_SIZE(face_list); i++)
7504 {
7505 const char* face = face_list[i];
7507 {
7508 skip("%s is not installed\n", face);
7509 continue;
7510 }
7511 memset(&lf, 0, sizeof(lf));
7512 lf.lfWeight = FW_NORMAL;
7513 lf.lfItalic = FALSE;
7515 lf.lfHeight = -256;
7516 strcpy(lf.lfFaceName, face);
7518 hfont_prev = SelectObject(hdc, hfont);
7519
7520 memset(&info, 0xaa, sizeof(info));
7521 r = pGetCharWidthInfo(hdc, &info);
7522 ok(r, "%s: GetCharWidthInfo failed\n", face);
7523
7524 /* test with synthetic bold */
7525 lf.lfWeight = FW_BOLD;
7526 lf.lfItalic = FALSE;
7529
7530 memset(&info2, 0xaa, sizeof(info2));
7531 r = pGetCharWidthInfo(hdc, &info2);
7532 ok(r, "%s: GetCharWidthInfo failed\n", face);
7533 ok(info.lsb == info2.lsb, "%s: expected %d, got %d\n", face, info.lsb, info2.lsb);
7534 ok(info.rsb == info2.rsb, "%s: expected %d, got %d\n", face, info.rsb, info2.rsb);
7535
7536 /* test with synthetic italic */
7537 lf.lfWeight = FW_NORMAL;
7538 lf.lfItalic = TRUE;
7541
7542 memset(&info2, 0xaa, sizeof(info2));
7543 r = pGetCharWidthInfo(hdc, &info2);
7544 ok(r, "%s: GetCharWidthInfo failed\n", face);
7545 todo_wine ok(info.lsb > info2.lsb, "%s: expected less than %d, got %d\n", face, info.lsb, info2.lsb);
7546 todo_wine ok(info.rsb > info2.rsb, "%s: expected less than %d, got %d\n", face, info.rsb, info2.rsb);
7547 DeleteObject(SelectObject(hdc, hfont_prev));
7548 }
7549
7550 ReleaseDC(NULL, hdc);
7551}
7552
7554 const TEXTMETRICA *tm, DWORD type, LPARAM ctx)
7555{
7556 HFONT font = CreateFontIndirectA(lf);
7557 HDC dc = GetDC(NULL);
7558 const char c = 'm';
7559 ABCFLOAT abcf;
7560 int i, i32;
7561 BOOL ret;
7562 float f;
7563 ABC abc;
7564
7565#ifdef __REACTOS__
7566 if (!strcmp(lf->lfFaceName, "Segoe UI Emoji ")) // Fails on Vista x64 testbot
7567 {
7568 win_skip("broken font: %s\n", lf->lfFaceName);
7569 return 1;
7570 }
7571#endif
7572
7574
7575 ret = GetCharWidthFloatA(dc, c, c, &f);
7576 ok(ret, "%s: GetCharWidthFloat() failed\n", lf->lfFaceName);
7577 ret = GetCharWidth32A(dc, c, c, &i32);
7578 ok(ret, "%s: GetCharWidth32A() failed\n", lf->lfFaceName);
7579 ret = GetCharWidthA(dc, c, c, &i);
7580 ok(ret, "%s: GetCharWidthA() failed\n", lf->lfFaceName);
7581 ok(i == i32, "%s: mismatched widths %d/%d\n", lf->lfFaceName, i, i32);
7582 ok((float)i / 16.0f == f, "%s: mismatched widths %d/%.8e\n", lf->lfFaceName, i, f);
7583
7584 ret = GetCharABCWidthsFloatA(dc, c, c, &abcf);
7585 ok(ret, "%s: GetCharABCWidths() failed\n", lf->lfFaceName);
7586 if (!strcmp(lf->lfFaceName, "Noto Color Emoji"))
7587 skip("broken Noto Color Emoji font");
7588 else if (GetCharABCWidthsA(dc, c, c, &abc))
7589 ok((float)abc.abcB == abcf.abcfB, "%s: mismatched widths %d/%.8e\n", lf->lfFaceName, abc.abcB, abcf.abcfB);
7590
7591 ReleaseDC(NULL, dc);
7593 return 1;
7594}
7595
7596static void test_char_width(void)
7597{
7598 HDC dc = GetDC(NULL);
7599 LOGFONTA lf = {0};
7600
7603
7604 ReleaseDC(NULL, dc);
7605}
7606
7608{
7609 LOGFONTA lf;
7610 HFONT hfont, hfont_old;
7611 KERNINGPAIR *kp;
7612 HDC hdc;
7613 DWORD count, ret, i, size, width, width_kern, idx;
7614 WCHAR str[30];
7616 int kern[30], pos[30], pos_kern[30], dx[30], dx_kern[30], kern_amount;
7617
7618 if (!is_font_installed("Arial"))
7619 {
7620 skip("Arial is not installed, skipping the test\n");
7621 return;
7622 }
7623
7624 hdc = GetDC(0);
7625
7626 memset(&lf, 0, sizeof(lf));
7627 strcpy(lf.lfFaceName, "Arial");
7628 lf.lfHeight = 120;
7630 ok(hfont != NULL, "CreateFontIndirect failed\n");
7631
7632 hfont_old = SelectObject(hdc, hfont);
7633
7635 kp = malloc(count * sizeof(*kp));
7636
7637 ret = GetKerningPairsW(hdc, count, kp);
7638 ok(ret == count, "got %lu, expected %lu\n", ret, count);
7639
7640 size = kern_amount = idx = 0;
7641 for (i = 0; i < count; i++)
7642 {
7643 if (kp[i].wFirst >= 'A' && kp[i].wFirst <= 'z' &&
7644 kp[i].wSecond >= 'A' && kp[i].wSecond <= 'z')
7645 {
7646 str[size++] = kp[i].wFirst;
7647 str[size++] = kp[i].wSecond;
7648 str[size++] = 0;
7649 kern[idx] = kp[i].iKernAmount;
7650 idx++;
7651 kern_amount += kp[i].iKernAmount;
7652 if (size >= ARRAY_SIZE(str)) break;
7653 }
7654 }
7655
7656 free(kp);
7657
7658 count = size;
7659
7660 memset(&result, 0, sizeof(result));
7661 result.lStructSize = sizeof(result);
7662 result.lpCaretPos = pos;
7663 result.lpDx = dx;
7664 result.nGlyphs = count;
7666 ok(ret, "GetCharacterPlacement failed\n");
7667 ok(result.nGlyphs == count, "got %u\n", result.nGlyphs);
7668 width = LOWORD(ret);
7669
7670 memset(&result, 0, sizeof(result));
7671 result.lStructSize = sizeof(result);
7672 result.lpCaretPos = pos_kern;
7673 result.lpDx = dx_kern;
7674 result.nGlyphs = count;
7676 ok(ret, "GetCharacterPlacement failed\n");
7677 ok(result.nGlyphs == count, "got %u\n", result.nGlyphs);
7678 width_kern = LOWORD(ret);
7679
7680 if (width == width_kern)
7681 {
7682 win_skip("GCP_USEKERNING is broken on this platform\n");
7683 goto done;
7684 }
7685
7686 ok(width + kern_amount == width_kern, "%ld + %d != %ld\n", width, kern_amount, width_kern);
7687
7688 kern_amount = idx = 0;
7689 for (i = 0; i < count; i += 3, idx++)
7690 {
7691 ok(pos[i] + kern_amount == pos_kern[i], "%ld: %d + %d != %d\n", i, pos[i], kern_amount, pos_kern[i]);
7692 kern_amount += kern[idx];
7693 ok(pos[i+1] + kern_amount == pos_kern[i+1], "%ld: %d + %d != %d\n", i, pos[i+1], kern_amount, pos_kern[i+1]);
7694 ok(pos[i+2] + kern_amount == pos_kern[i+2], "%ld: %d + %d != %d\n", i, pos[i+2], kern_amount, pos_kern[i+2]);
7695
7696 ok(dx[i] + kern[idx] == dx_kern[i], "%ld: %d + %d != %d\n", i, dx[i], kern[idx], dx_kern[i]);
7697 ok(dx[i+1] == dx_kern[i+1], "%ld: %d != %d\n", i, dx[i+1], dx_kern[i+1]);
7698 ok(dx[i+2] == dx_kern[i+2], "%ld: %d != %d\n", i, dx[i+2], dx_kern[i+2]);
7699 }
7700
7701done:
7702 SelectObject(hdc, hfont_old);
7704 ReleaseDC(0, hdc);
7705}
7706
7707static void test_select_object(void)
7708{
7709 HFONT hfont, old_font;
7710 LOGFONTA lf;
7711
7712 memset(&lf, 0, sizeof lf);
7713
7716 lf.lfWeight = FW_DONTCARE;
7717 lf.lfHeight = 16;
7718 lf.lfWidth = 16;
7720
7721 lstrcpyA(lf.lfFaceName, "Arial");
7722 hfont = create_font("Arial", &lf);
7723
7724 SetLastError(0xdeadbeef);
7725 old_font = SelectObject(NULL, hfont);
7726 ok(!old_font, "SelectObject returned %p\n", old_font);
7727 ok(GetLastError() == ERROR_INVALID_HANDLE, "GetLastError() = %lu\n",
7728 GetLastError());
7729
7731}
7732
7734{
7735 OUTLINETEXTMETRICA *otm;
7736 LOGFONTA lf;
7737 HFONT hfont, hfont_old;
7738 HDC hdc;
7739 DWORD ret;
7740 char face_name[LF_FACESIZE];
7741 const char* family_name;
7742
7743 if (!is_font_installed("MS SHELL DLG"))
7744 {
7745 skip("MS Shell Dlg is not installed\n");
7746 return;
7747 }
7748
7749 hdc = GetDC(0);
7750 memset(&lf, 0, sizeof(lf));
7751 strcpy(lf.lfFaceName, "MS SHELL DLG");
7754 ok(hfont != NULL, "failed to create a font\n");
7755 hfont_old = SelectObject(hdc, hfont);
7756
7757 /* face name */
7758 ret = GetTextFaceA(hdc, sizeof(face_name), face_name);
7759 ok(ret, "GetTextFace failed\n");
7760 ok(!lstrcmpiA(lf.lfFaceName, face_name), "expected %s, got %s\n", lf.lfFaceName, face_name);
7761
7763 otm = calloc(1, ret);
7765 ok(ret != 0, "GetOutlineTextMetrics failed\n");
7766
7767 /* family name */
7768 family_name = (const char*)otm + (UINT_PTR)otm->otmpFamilyName;
7769 ok(lstrcmpiA(lf.lfFaceName, family_name), "expected a real family name (e.g. Tahoma), got %s\n", family_name);
7770
7771 free(otm);
7772 SelectObject(hdc, hfont_old);
7774
7775 ReleaseDC(0, hdc);
7776}
7777
7779)
7780{
7781 const NEWTEXTMETRICW *ntm = (const NEWTEXTMETRICW *)tm;
7782 int *called = (int *)lparam;
7783
7784 if (type != TRUETYPE_FONTTYPE) return 1;
7785 ok(!wcscmp(lf->lfFaceName, L"wine_heavy"), "got %s.\n", debugstr_w(lf->lfFaceName));
7786 ok((ntm->ntmFlags & (NTM_REGULAR | NTM_BOLD)) == NTM_REGULAR, "got %#lx.\n", ntm->ntmFlags);
7787 ok(ntm->tmWeight == 700, "got %ld.\n", ntm->tmWeight);
7788 *called = 1;
7789
7790 return 1;
7791}
7792
7793static void test_font_weight(void)
7794{
7795 HFONT hfont1, hfont2, old;
7796 char ttf_name[MAX_PATH];
7797 TEXTMETRICW tm1, tm2;
7798 int enum_called;
7799 LOGFONTW lf;
7800 DWORD count;
7801 BOOL bret;
7802 HDC hdc;
7803
7804 bret = write_ttf_file("wine_heavy.ttf", ttf_name);
7805 ok(bret, "Failed to create test font file.\n");
7806
7807 count = AddFontResourceExA(ttf_name, 0, NULL);
7808 ok(count == 1, "got %lu.\n", count);
7809
7810 hdc = GetDC(NULL);
7811
7812 memset(&lf, 0, sizeof(lf));
7813 wcscpy(lf.lfFaceName, L"wine_heavy");
7814 lf.lfHeight = 90;
7815 lf.lfWeight = FW_BOLD;
7817
7818 enum_called = 0;
7819 EnumFontFamiliesExW(hdc, &lf, test_font_weight_enum, (LPARAM)&enum_called, 0);
7820 ok(enum_called, "font not found.\n");
7821
7822 enum_called = 0;
7823 lf.lfWeight = FW_REGULAR;
7824 EnumFontFamiliesExW(hdc, &lf, test_font_weight_enum, (LPARAM)&enum_called, 0);
7825 ok(enum_called, "font not found.\n");
7826
7827 lf.lfWeight = FW_REGULAR;
7828 hfont1 = CreateFontIndirectW(&lf);
7829 lf.lfWeight = FW_BOLD;
7830 hfont2 = CreateFontIndirectW(&lf);
7831
7832 old = SelectObject(hdc, hfont1);
7833 memset(&tm1, 0, sizeof(tm1));
7834 GetTextMetricsW(hdc, &tm1);
7835 SelectObject(hdc, hfont2);
7836 memset(&tm2, 0, sizeof(tm2));
7837 GetTextMetricsW(hdc, &tm2);
7838 ok(tm1.tmMaxCharWidth == tm2.tmMaxCharWidth, "got %ld, %ld.\n", tm1.tmMaxCharWidth, tm2.tmMaxCharWidth);
7839
7840 SelectObject(hdc, old);
7841 ReleaseDC(NULL, hdc);
7842 DeleteObject(hfont1);
7843 DeleteObject(hfont2);
7844 bret = RemoveFontResourceExA(ttf_name, 0, NULL);
7845 ok(bret, "got error %ld\n", GetLastError());
7846}
7847
7849{
7850 static const char *test_names[] =
7851 {
7852 "AddFontMemResource",
7853 };
7854 char path_name[MAX_PATH];
7856 char **argv;
7857 int argc, i;
7858
7859 init();
7860
7862 if (argc >= 3)
7863 {
7864 if (!strcmp(argv[2], "AddFontMemResource"))
7866 return;
7867 }
7868
7870 test_logfont();
7873#ifdef __REACTOS__
7874 if (is_reactos())
7875 skip("FIXME: ReactOS does not support bitmap (raster) fonts at this time\n");
7876 else
7878#else
7880#endif
7898
7899 /* On Windows Arial has a lot of default charset aliases such as Arial Cyr,
7900 * I'd like to avoid them in this test.
7901 */
7902 test_EnumFontFamilies("Arial Black", ANSI_CHARSET);
7904 if (is_truetype_font_installed("Arial Black") &&
7905 (is_truetype_font_installed("Symbol") || is_truetype_font_installed("Wingdings")))
7906 {
7910 }
7911 else
7912 skip("Arial Black or Symbol/Wingdings is not installed\n");
7918 test_GetTextMetrics2("Tahoma", -11);
7919 test_GetTextMetrics2("Tahoma", -55);
7920 test_GetTextMetrics2("Tahoma", -110);
7921 test_GetTextMetrics2("Arial", -11);
7922 test_GetTextMetrics2("Arial", -55);
7923 test_GetTextMetrics2("Arial", -110);
7930 test_fullname();
7945
7946 /* These tests should be last test until RemoveFontResource
7947 * is properly implemented.
7948 */
7951
7953 for (i = 0; i < ARRAY_SIZE(test_names); ++i)
7954 {
7956
7957 memset(&startup, 0, sizeof(startup));
7958 startup.cb = sizeof(startup);
7959 sprintf(path_name, "%s font %s", argv[0], test_names[i]);
7961 "CreateProcess failed.\n");
7962 wait_child_process(info.hProcess);
7963 CloseHandle(info.hProcess);
7964 CloseHandle(info.hThread);
7965 }
7966}
static HFONT hfont
InitDirComponents & cd
@ lparam
Definition: SystemMenu.c:31
#define read
Definition: acwin.h:97
static void startup(void)
#define trace
Definition: atltest.h:70
#define ok(value,...)
Definition: atltest.h:57
#define skip(...)
Definition: atltest.h:64
#define broken(x)
Definition: atltest.h:178
#define START_TEST(x)
Definition: atltest.h:75
HFONT hFont
Definition: main.c:53
#define ARRAY_SIZE(A)
Definition: main.h:20
INT copy(TCHAR source[MAX_PATH], TCHAR dest[MAX_PATH], INT append, DWORD lpdwFlags, BOOL bTouch)
Definition: copy.c:51
#define ULongToPtr(ul)
Definition: basetsd.h:86
CFF_Charset charset
Definition: cffcmap.c:137
LPARAM lParam
Definition: combotst.c:139
_Out_opt_ UINT * code_page
HDC dc
Definition: cylfrac.c:34
#define ERROR_INSUFFICIENT_BUFFER
Definition: dderror.h:10
#define realloc
Definition: debug_ros.c:6
#define free
Definition: debug_ros.c:5
#define malloc
Definition: debug_ros.c:4
#define LF_FACESIZE
Definition: dimm.idl:39
static char selected[MAX_PATH+1]
Definition: dirdlg.c:7
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
WORD face[3]
Definition: mesh.c:4747
unsigned int idx
Definition: utils.c:41
#define CloseHandle
Definition: compat.h:739
#define ERROR_CALL_NOT_IMPLEMENTED
Definition: compat.h:102
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define PAGE_READONLY
Definition: compat.h:138
#define UnmapViewOfFile
Definition: compat.h:746
#define CP_ACP
Definition: compat.h:109
#define OPEN_EXISTING
Definition: compat.h:775
#define ReadFile(a, b, c, d, e)
Definition: compat.h:742
#define SetLastError(x)
Definition: compat.h:752
#define GetProcAddress(x, y)
Definition: compat.h:753
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define CreateFileA(a, b, c, d, e, f, g)
Definition: compat.h:740
#define GENERIC_READ
Definition: compat.h:135
#define MAX_PATH
Definition: compat.h:34
#define ERROR_INVALID_HANDLE
Definition: compat.h:98
#define CreateFileW
Definition: compat.h:741
#define FILE_MAP_READ
Definition: compat.h:776
#define GetFileSizeEx
Definition: compat.h:757
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:137
#define CALLBACK
Definition: compat.h:35
#define WideCharToMultiByte
Definition: compat.h:111
#define MapViewOfFile
Definition: compat.h:745
#define MultiByteToWideChar
Definition: compat.h:110
#define ERROR_ACCESS_DENIED
Definition: compat.h:97
#define FILE_SHARE_READ
Definition: compat.h:136
#define lstrlenW
Definition: compat.h:750
static const WCHAR version[]
Definition: asmname.c:66
#define TT_APPLE_ID_ISO_10646
Definition: font.c:1135
#define MS_OS2_TAG
Definition: font.c:115
static WORD get_mac_code_page(const tt_name_record *name)
Definition: font.c:1304
#define TT_MAC_ID_SIMPLIFIED_CHINESE
Definition: font.c:1141
#define TT_MS_ID_UNICODE_CS
Definition: font.c:1139
#define TT_PLATFORM_MICROSOFT
Definition: font.c:1132
#define TT_APPLE_ID_DEFAULT
Definition: font.c:1134
#define TT_APPLE_ID_UNICODE_2_0
Definition: font.c:1136
#define TT_PLATFORM_MACINTOSH
Definition: font.c:1131
#define TT_MS_ID_SYMBOL_CS
Definition: font.c:1138
static INT CALLBACK is_font_installed_proc(const LOGFONTW *elf, const TEXTMETRICW *ntm, DWORD type, LPARAM lParam)
Definition: font.c:610
static int match_name_table_language(const tt_name_record *name, LANGID lang)
Definition: font.c:1311
#define TT_PLATFORM_APPLE_UNICODE
Definition: font.c:1130
#define GET_BE_WORD(x)
Definition: font.c:108
#define GET_BE_DWORD(x)
Definition: font.c:109
static const LANGID mac_langid_table[]
Definition: font.c:1180
BOOL WINAPI DeleteFileA(IN LPCSTR lpFileName)
Definition: delete.c:24
DWORD WINAPI GetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh)
Definition: fileinfo.c:331
BOOL WINAPI GetFileTime(IN HANDLE hFile, OUT LPFILETIME lpCreationTime OPTIONAL, OUT LPFILETIME lpLastAccessTime OPTIONAL, OUT LPFILETIME lpLastWriteTime OPTIONAL)
Definition: fileinfo.c:880
DWORD WINAPI GetFileAttributesA(LPCSTR lpFileName)
Definition: fileinfo.c:620
BOOL WINAPI WriteFile(_In_ HANDLE hFile, _In_reads_bytes_opt_(nNumberOfBytesToWrite) LPCVOID lpBuffer, _In_ DWORD nNumberOfBytesToWrite, _Out_opt_ LPDWORD lpNumberOfBytesWritten, _Inout_opt_ LPOVERLAPPED lpOverlapped)
Definition: rw.c:25
HMODULE WINAPI DECLSPEC_HOTPATCH GetModuleHandleA(LPCSTR lpModuleName)
Definition: loader.c:812
UINT WINAPI GetWindowsDirectoryA(OUT LPSTR lpBuffer, IN UINT uSize)
Definition: path.c:2256
DWORD WINAPI GetTempPathA(IN DWORD nBufferLength, OUT LPSTR lpBuffer)
Definition: path.c:1973
LONG WINAPI CompareFileTime(IN CONST FILETIME *lpFileTime1, IN CONST FILETIME *lpFileTime2)
Definition: time.c:106
HRSRC WINAPI FindResourceA(HMODULE hModule, LPCSTR name, LPCSTR type)
Definition: res.c:155
DWORD WINAPI SizeofResource(HINSTANCE hModule, HRSRC hRsrc)
Definition: res.c:568
LPVOID WINAPI LockResource(HGLOBAL handle)
Definition: res.c:550
HGLOBAL WINAPI LoadResource(HINSTANCE hModule, HRSRC hRsrc)
Definition: res.c:532
UINT WINAPI GetACP(void)
Definition: locale.c:2023
LANGID WINAPI GetSystemDefaultLangID(void)
Definition: locale.c:1199
BOOL WINAPI IsValidCodePage(UINT codepage)
Definition: locale.c:2081
int WINAPI lstrcmpW(LPCWSTR str1, LPCWSTR str2)
Definition: locale.c:4152
int WINAPI lstrcmpA(LPCSTR str1, LPCSTR str2)
Definition: locale.c:4104
int WINAPI lstrcmpiA(LPCSTR str1, LPCSTR str2)
Definition: locale.c:4133
BOOL WINAPI IsDBCSLeadByteEx(UINT codepage, BYTE testchar)
Definition: locale.c:2106
LANGID WINAPI GetUserDefaultLangID(void)
Definition: locale.c:1182
BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessA(const char *app_name, char *cmd_line, SECURITY_ATTRIBUTES *process_attr, SECURITY_ATTRIBUTES *thread_attr, BOOL inherit, DWORD flags, void *env, const char *cur_dir, STARTUPINFOA *startup_info, PROCESS_INFORMATION *info)
Definition: process.c:686
MonoAssembly int argc
Definition: metahost.c:107
const WCHAR * text
Definition: package.c:1794
#define assert(_expr)
Definition: assert.h:32
_ACRTIMP int __cdecl wcscmp(const wchar_t *, const wchar_t *)
Definition: wcs.c:1972
_ACRTIMP int __cdecl memcmp(const void *, const void *, size_t)
Definition: string.c:2802
_ACRTIMP size_t __cdecl strlen(const char *)
Definition: string.c:1592
_ACRTIMP int __cdecl strcmp(const char *, const char *)
Definition: string.c:3319
_ACRTIMP char *__cdecl strrchr(const char *, int)
Definition: string.c:3298
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
#define pt(x, y)
Definition: drawing.c:79
return ret
Definition: mutex.c:146
#define L(x)
Definition: resources.c:13
r reserved
Definition: btrfs.c:3006
#define abs(i)
Definition: fconv.c:206
HANDLE NTAPI CreateFileMappingA(IN HANDLE hFile, IN LPSECURITY_ATTRIBUTES lpFileMappingAttributes, IN DWORD flProtect, IN DWORD dwMaximumSizeHigh, IN DWORD dwMaximumSizeLow, IN LPCSTR lpName)
Definition: filemap.c:23
UINT WINAPI GetTempFileNameA(IN LPCSTR lpPathName, IN LPCSTR lpPrefixString, IN UINT uUnique, OUT LPSTR lpTempFileName)
Definition: filename.c:26
unsigned short WORD
Definition: ntddk_ex.h:93
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
static char * path_name(DOS_FILE *file)
Definition: check.c:208
pKey DeleteObject()
GLuint start
Definition: gl.h:1545
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLint GLint GLsizei GLsizei GLsizei GLint GLenum GLenum const GLvoid * pixels
Definition: gl.h:1546
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548
GLuint GLuint end
Definition: gl.h:1545
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLint GLint GLsizei GLsizei height
Definition: gl.h:1546
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
GLint GLint GLsizei width
Definition: gl.h:1546
GLuint GLuint GLsizei GLenum const GLvoid * indices
Definition: gl.h:1545
GLdouble n
Definition: glext.h:7729
GLuint res
Definition: glext.h:9613
GLenum GLenum GLenum GLenum GLenum scale
Definition: glext.h:9032
GLsizeiptr size
Definition: glext.h:5919
GLintptr offset
Definition: glext.h:5920
const GLubyte * c
Definition: glext.h:8905
GLenum GLuint GLint GLenum face
Definition: glext.h:7025
GLfloat f
Definition: glext.h:7540
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
GLint limit
Definition: glext.h:10326
GLenum GLint * range
Definition: glext.h:7539
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLbitfield flags
Definition: glext.h:7161
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
GLint GLint bottom
Definition: glext.h:7726
const GLint * first
Definition: glext.h:5794
GLboolean GLboolean g
Definition: glext.h:6204
GLuint64EXT * result
Definition: glext.h:11304
GLenum GLenum GLenum GLenum mapping
Definition: glext.h:9031
GLuint GLuint num
Definition: glext.h:9618
GLenum GLsizei len
Definition: glext.h:6722
GLboolean GLboolean GLboolean GLboolean a
Definition: glext.h:6204
GLubyte GLubyte GLubyte GLubyte w
Definition: glext.h:6102
GLfloat GLfloat GLfloat GLfloat h
Definition: glext.h:7723
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
#define fs
Definition: i386-dis.c:444
#define cs
Definition: i386-dis.c:442
#define gs
Definition: i386-dis.c:445
uint32_t entry
Definition: isohybrid.c:63
#define e
Definition: ke_i.h:82
#define f
Definition: ke_i.h:83
#define a
Definition: ke_i.h:78
#define c
Definition: ke_i.h:80
#define debugstr_w
Definition: kernel32.h:32
#define wine_dbgstr_w
Definition: kernel32.h:34
USHORT LANGID
Definition: mui.h:9
if(dx< 0)
Definition: linetemp.h:194
GLint dx
Definition: linetemp.h:97
LPSTR WINAPI lstrcpyA(LPSTR lpString1, LPCSTR lpString2)
Definition: lstring.c:100
int winetest_debug
#define win_skip
Definition: minitest.h:67
#define todo_wine_if(is_todo)
Definition: minitest.h:81
void __cdecl void __cdecl void __cdecl void __cdecl void __cdecl void winetest_pop_context(void)
void __cdecl void __cdecl void __cdecl void __cdecl void __cdecl winetest_push_context(const char *fmt,...) __WINE_PRINTF_ATTR(1
Definition: test.h:537
#define todo_wine
Definition: minitest.h:80
#define ZeroMemory
Definition: minwinbase.h:31
LONG_PTR LPARAM
Definition: minwindef.h:175
int * LPINT
Definition: minwindef.h:151
__u16 time
Definition: mkdosfs.c:8
#define error(str)
Definition: mkdosfs.c:1605
#define matches(FN)
Definition: match.h:70
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define memmove(s1, s2, n)
Definition: mkisofs.h:881
#define CREATE_ALWAYS
Definition: disk.h:72
static PVOID ptr
Definition: dispmode.c:27
static struct test_info tests[]
#define sprintf
Definition: sprintf.c:45
BITMAP bmp
Definition: alphablend.c:62
WCHAR TestName[MAX_PATH]
Definition: main.cpp:13
HDC hdc
Definition: main.c:9
static HBITMAP
Definition: button.c:44
static HDC
Definition: imagelist.c:88
static void test_height(void)
Definition: status.c:168
const char * fullname
Definition: shader.c:1766
static void get_charset_stats(struct enum_font_data *efd, int *ansi_charset, int *symbol_charset, int *russian_charset)
Definition: font.c:2905
static void test_GetGlyphOutline(void)
Definition: font.c:4684
static void test_GetCharacterPlacement_kerning(void)
Definition: font.c:7607
#define MS_NAME_TAG
Definition: font.c:67
static void test_lang_names(void)
Definition: font.c:7120
static void test_nonexistent_font(void)
Definition: font.c:4133
static INT CALLBACK arial_enum_proc(const LOGFONTA *lf, const TEXTMETRICA *tm, DWORD type, LPARAM lParam)
Definition: font.c:2861
#define TT_NAME_ID_FULL_NAME
Definition: font.c:3581
static void test_GetTextFace(void)
Definition: font.c:4484
static WCHAR * prepend_at(WCHAR *family)
Definition: font.c:5630
static void test_east_asian_font_selection(void)
Definition: font.c:6312
#define MS_CMAP_TAG
Definition: font.c:66
static void init(void)
Definition: font.c:69
static void test_GetGlyphOutline_character(void)
Definition: font.c:5879
static void test_GdiGetCharDimensions(void)
Definition: font.c:1021
static void test_GetTextMetrics(void)
Definition: font.c:4102
static void test_font_weight(void)
Definition: font.c:7793
static void test_GetGlyphOutline_empty_contour(void)
Definition: font.c:5793
static INT CALLBACK is_truetype_font_installed_proc(const LOGFONTA *elf, const TEXTMETRICA *ntm, DWORD type, LPARAM lParam)
Definition: font.c:84
static HMODULE hgdi32
Definition: font.c:50
#define near_match(a, b)
Definition: font.c:39
#define TT_MS_LANGID_ENGLISH_UNITED_STATES
Definition: font.c:3577
static INT CALLBACK enum_font_data_proc(const LOGFONTA *lf, const TEXTMETRICA *ntm, DWORD type, LPARAM lParam)
Definition: font.c:3170
static void * get_res_data(const char *fontname, DWORD *rsrc_size)
Definition: font.c:120
static void *static DWORD *static DWORD *static void SIZE_T *static UINT64
Definition: font.c:48
static void test_text_metrics(const LOGFONTA *lf, const NEWTEXTMETRICA *ntm)
Definition: font.c:3853
static void test_GetGlyphIndices(void)
Definition: font.c:1578
static void test_GetCharWidthInfo(void)
Definition: font.c:7389
static INT CALLBACK has_vertical_font_proc(const LOGFONTA *lf, const TEXTMETRICA *ntm, DWORD type, LPARAM lParam)
Definition: font.c:6303
static void test_fstype_fixup(void)
Definition: font.c:5930
static void * load_font(const char *font_name, DWORD *font_size)
Definition: font.c:1544
static int CALLBACK get_char_width_proc(const LOGFONTA *lf, const TEXTMETRICA *tm, DWORD type, LPARAM ctx)
Definition: font.c:7553
static void check_font(const char *test, const LOGFONTA *lf, HFONT hfont)
Definition: font.c:166
static void test_GetCharacterPlacement(void)
Definition: font.c:4994
static BOOL write_ttf_file(const char *fontname, char *tmp_name)
Definition: font.c:155
static void test_font_charset(void)
Definition: font.c:2663
static void * get_cmap(cmap_header *header, USHORT plat_id, USHORT enc_id)
Definition: font.c:3498
static void get_seg4(cmap_format_4 *cmap, USHORT seg_num, cmap_format_4_seg *seg)
Definition: font.c:3464
static WORD system_lang_id
Definition: font.c:52
static INT CALLBACK enum_fullname_data_proc(const LOGFONTA *lf, const TEXTMETRICA *ntm, DWORD type, LPARAM lParam)
Definition: font.c:3187
static INT CALLBACK enum_fullname_data_proc_w(const LOGFONTW *lf, const TEXTMETRICW *ntm, DWORD type, LPARAM lParam)
Definition: font.c:3204
static void test_EnumFontFamilies(const char *font_name, INT font_charset)
Definition: font.c:2959
static void test_logfont(void)
Definition: font.c:201
static BOOL is_font_installed_fullname(const char *family, const char *fullname)
Definition: font.c:5570
static void get_charset_statsW(struct enum_font_dataW *efd, int *ansi_charset, int *symbol_charset, int *russian_charset)
Definition: font.c:2932
static INT CALLBACK enum_truetype_font_proc(const LOGFONTA *lf, const TEXTMETRICA *ntm, DWORD type, LPARAM lParam)
Definition: font.c:4090
static HFONT create_font(const char *test, const LOGFONTA *lf)
Definition: font.c:192
static BOOL get_first_last_from_cmap4(void *ptr, DWORD *first, DWORD *last, DWORD limit)
Definition: font.c:3473
static BOOL get_ttf_nametable_entry(HDC hdc, WORD name_id, WCHAR *out_buf, SIZE_T out_size, LCID language_id)
Definition: font.c:3771
static LPTEXTMETRICW lptm
Definition: font.c:42
static void test_select_object(void)
Definition: font.c:7707
static void test_orientation(void)
Definition: font.c:4575
static void test_GetOutlineTextMetrics_subst(void)
Definition: font.c:7733
static INT CALLBACK enum_with_magic_retval_proc(const LOGFONTA *elf, const TEXTMETRICA *ntm, DWORD type, LPARAM lparam)
Definition: font.c:5383
static void test_max_height(void)
Definition: font.c:6503
static void test_fake_bold_font(void)
Definition: font.c:6700
static void test_CreateFontIndirect(void)
Definition: font.c:5049
static void test_height_selection_vdmx(HDC hdc)
Definition: font.c:1962
static void test_GdiGetCodePage(void)
Definition: font.c:2709
static INT CALLBACK long_enum_proc(const LOGFONTA *lf, const TEXTMETRICA *tm, DWORD type, LPARAM lparam)
Definition: font.c:7000
static void test_GetFontUnicodeRanges(void)
Definition: font.c:2803
static void *static DWORD *static DWORD *static void SIZE_T
Definition: font.c:47
static void test_EnumFonts_subst(void)
Definition: font.c:5498
static void test_ttf_names(void)
Definition: font.c:7053
static void test_RealizationInfo(void)
Definition: font.c:4338
static void test_EnumFonts(void)
Definition: font.c:5388
static const MAT2 mat
Definition: font.c:51
static INT CALLBACK enum_ms_shell_dlg_proc(const LOGFONTA *lf, const TEXTMETRICA *ntm, DWORD type, LPARAM lParam)
Definition: font.c:5456
static void test_fullname2_helper(const char *Family)
Definition: font.c:5640
static void * find_ttf_table(void *ttf, DWORD size, DWORD tag)
Definition: font.c:1948
static void test_TranslateCharsetInfo(void)
Definition: font.c:2571
static void test_AddFontMemResource(void)
Definition: font.c:5214
static void test_GetGlyphOutline_metric_clipping(void)
Definition: font.c:5833
#define match_off_by_1(a, b, exact)
Definition: font.c:38
static void test_negative_width(HDC hdc, const LOGFONTA *lf)
Definition: font.c:3268
static void test_outline_font(void)
Definition: font.c:448
static void test_height_selection(void)
Definition: font.c:2129
static int CALLBACK create_fixed_pitch_font_proc(const LOGFONTA *lpelfe, const TEXTMETRICA *lpntme, DWORD FontType, LPARAM lParam)
Definition: font.c:4632
static void check_vertical_metrics(const char *face)
Definition: font.c:6162
#define TT_NAME_ID_UNIQUE_ID
Definition: font.c:3580
static int CALLBACK create_font_proc(const LOGFONTA *lpelfe, const TEXTMETRICA *lpntme, DWORD FontType, LPARAM lParam)
Definition: font.c:1059
static void test_CreateFontIndirectEx(void)
Definition: font.c:5080
#define SCALE_NTM(value)
static INT CALLBACK enum_ms_shell_dlg2_proc(const LOGFONTA *lf, const TEXTMETRICA *ntm, DWORD type, LPARAM lParam)
Definition: font.c:5477
static void test_GetCharWidthI(void)
Definition: font.c:6947
static void testJustification(const char *context, HDC hdc, PCSTR str, RECT *clientArea)
Definition: font.c:2289
#define expect(expected, got)
Definition: font.c:40
static INT CALLBACK test_font_weight_enum(const LOGFONTW *lf, const TEXTMETRICW *tm, DWORD type, LPARAM lparam)
Definition: font.c:7778
static INT CALLBACK font_enum_proc(const LOGFONTA *elf, const TEXTMETRICA *ntm, DWORD type, LPARAM lParam)
Definition: font.c:228
static INT CALLBACK find_font_proc(const LOGFONTA *elf, const TEXTMETRICA *ntm, DWORD type, LPARAM lParam)
Definition: font.c:690
#define TT_NAME_ID_FONT_FAMILY
Definition: font.c:3578
static INT CALLBACK arial_enum_procw(const LOGFONTW *lf, const TEXTMETRICW *tm, DWORD type, LPARAM lParam)
Definition: font.c:2883
static INT CALLBACK enum_fonts_proc(const LOGFONTA *elf, const TEXTMETRICA *ntm, DWORD type, LPARAM lparam)
Definition: font.c:5352
#define FH_SCALE
Definition: font.c:707
static void test_oemcharset(void)
Definition: font.c:4604
static void expect_ff(const TEXTMETRICA *tmA, const TT_OS2_V4 *os2, WORD family, const char *name)
Definition: font.c:3438
#define TT_OS2_V0_SIZE
Definition: font.c:3385
static void ABCWidths_helper(const char *description, HDC hdc, WORD *glyphs, const ABC *base_abci, const ABC *base_abcw, const ABCFLOAT *base_abcf)
Definition: font.c:1078
static INT CALLBACK is_font_installed_fullname_proc(const LOGFONTA *lf, const TEXTMETRICA *ntm, DWORD type, LPARAM lParam)
Definition: font.c:5560
static void test_fullname2(void)
Definition: font.c:5752
static void test_GetOutlineTextMetrics(void)
Definition: font.c:2182
static BOOL is_CJK(void)
Definition: font.c:702
static BOOL is_truetype_font_installed(const char *name)
Definition: font.c:91
static BOOL get_glyph_indices(INT charset, UINT code_page, WORD *idx, UINT count, BOOL unicode)
Definition: font.c:2478
static void free_font(void *font)
Definition: font.c:1539
static void test_bitmap_font_metrics(void)
Definition: font.c:708
static void test_SetTextJustification(void)
Definition: font.c:2366
static void test_text_extents(void)
Definition: font.c:1399
static BOOL get_first_last_from_cmap(HDC hdc, DWORD *first, DWORD *last, cmap_type *cmap_type)
Definition: font.c:3519
static void test_realization_info(const char *name, DWORD size, BOOL is_memory_resource)
Definition: font.c:5105
static void test_stock_fonts(void)
Definition: font.c:6382
static BOOL get_first_last_from_cmap0(void *ptr, DWORD *first, DWORD *last)
Definition: font.c:3447
static UINT get_font_fsselection(LOGFONTA *lf)
Definition: font.c:2154
static void check_vertical_font(const char *name, BOOL *installed, BOOL *selected, GLYPHMETRICS *gm, WORD *gi)
Definition: font.c:6111
static INT CALLBACK enum_all_fonts_proc(const LOGFONTA *elf, const TEXTMETRICA *ntm, DWORD type, LPARAM lparam)
Definition: font.c:5365
static void test_long_names(void)
Definition: font.c:7007
static void compare_tm(const TEXTMETRICA *tm, const TEXTMETRICA *otm)
Definition: font.c:240
static BOOL match_off_by_n(int a, int b, unsigned int n)
Definition: font.c:34
static void test_bitmap_font(void)
Definition: font.c:358
static void test_GetTextMetrics2(const char *fontname, int font_height)
Definition: font.c:4943
static void test_EnumFontFamiliesEx_default_charset(void)
Definition: font.c:3221
static BOOL is_font_installed(const char *name)
Definition: font.c:108
static void test_GetCharABCWidths(void)
Definition: font.c:1109
static INT CALLBACK enum_multi_charset_font_proc(const LOGFONTA *lf, const TEXTMETRICA *tm, DWORD type, LPARAM lParam)
Definition: font.c:3149
#define MS_MAKE_TAG(ch0, ch1, ch2, ch3)
Definition: font.c:62
cmap_type
Definition: font.c:3513
@ cmap_ms_unicode
Definition: font.c:3515
@ cmap_none
Definition: font.c:3514
@ cmap_ms_symbol
Definition: font.c:3516
static void test_bitmap_font_glyph_index(void)
Definition: font.c:6819
static void test_vertical_order(void)
Definition: font.c:6566
static void test_fullname(void)
Definition: font.c:5582
static void test_CreateScalableFontResource(void)
Definition: font.c:5969
static void test_char_width(void)
Definition: font.c:7596
static void test_GetCharWidth32(void)
Definition: font.c:6602
static int get_font_dpi(const LOGFONTA *lf, int *height)
Definition: font.c:6360
static void test_vertical_font(void)
Definition: font.c:6250
static BOOL write_tmp_file(const void *data, DWORD *size, char *tmp_name)
Definition: font.c:137
static void test_GetKerningPairs(void)
Definition: font.c:1704
#define TT_NAME_ID_FONT_SUBFAMILY
Definition: font.c:3579
static void test_font_metrics(void)
Definition: font.c:827
static const LARGE_INTEGER *static const HANDLE const LARGE_INTEGER *static PSLIST_ENTRY PSLIST_ENTRY last
Definition: sync.c:64
static SYSTEM_INFO si
Definition: virtual.c:39
static HANDLE PIO_APC_ROUTINE PVOID PIO_STATUS_BLOCK ULONG PVOID ULONG PVOID ULONG out_size
Definition: file.c:72
static LPCWSTR file_name
Definition: protocol.c:147
static const char * testtext
Definition: dialog.c:1459
#define min(a, b)
Definition: monoChain.cc:55
#define argv
Definition: mplay32.c:18
unsigned __int3264 UINT_PTR
Definition: mstsclib_h.h:274
INT WINAPI MulDiv(INT nNumber, INT nNumerator, INT nDenominator)
Definition: muldiv.c:25
Definition: mk_font.cpp:20
unsigned int UINT
Definition: ndis.h:50
#define BOOL
Definition: nt_native.h:43
#define DWORD
Definition: nt_native.h:44
#define GENERIC_WRITE
Definition: nt_native.h:90
#define LANG_SCOTTISH_GAELIC
#define OBJ_FONT
Definition: objidl.idl:1019
#define LOWORD(l)
Definition: pedump.c:82
short WCHAR
Definition: pedump.c:58
#define WS_POPUP
Definition: pedump.c:616
#define RT_RCDATA
Definition: pedump.c:372
short SHORT
Definition: pedump.c:59
long LONG
Definition: pedump.c:60
unsigned short USHORT
Definition: pedump.c:61
char CHAR
Definition: pedump.c:57
static int Family
Definition: ping.c:62
_Out_opt_ int _Out_opt_ int * cy
Definition: commctrl.h:586
_Out_opt_ int * cx
Definition: commctrl.h:585
static unsigned __int64 next
Definition: rand_nt.c:6
#define err(...)
#define calloc
Definition: rosglue.h:14
#define test
Definition: rosglue.h:37
#define wine_dbgstr_wn
Definition: testlist.c:2
const WCHAR * str
#define LANG_TATAR
Definition: nls.h:130
#define SUBLANG_DUTCH_BELGIAN
Definition: nls.h:221
#define LANG_CROATIAN
Definition: nls.h:46
#define LANG_MALAYALAM
Definition: nls.h:93
#define LANG_TIGRIGNA
Definition: nls.h:134
#define LANG_HINDI
Definition: nls.h:68
#define LANG_TAMIL
Definition: nls.h:129
#define LANG_MALTESE
Definition: nls.h:94
#define LANG_FARSI
Definition: nls.h:55
#define LANG_NEUTRAL
Definition: nls.h:22
#define LANG_THAI
Definition: nls.h:132
#define LANG_LITHUANIAN
Definition: nls.h:88
#define MAKELANGID(p, s)
Definition: nls.h:15
#define LANG_LAO
Definition: nls.h:86
#define LANG_ASSAMESE
Definition: nls.h:31
#define LANG_NORWEGIAN
Definition: nls.h:102
#define LANG_CHINESE_SIMPLIFIED
Definition: nls.h:43
#define LANG_ALBANIAN
Definition: nls.h:26
#define LANG_TURKISH
Definition: nls.h:136
#define LANG_SANSKRIT
Definition: nls.h:115
#define LANG_KASHMIRI
Definition: nls.h:78
#define LANG_DANISH
Definition: nls.h:48
#define LANG_AMHARIC
Definition: nls.h:28
#define LANG_INUKTITUT
Definition: nls.h:73
#define LANG_SPANISH
Definition: nls.h:123
#define LANG_POLISH
Definition: nls.h:107
#define LANG_AZERI
Definition: nls.h:32
#define LANG_NEPALI
Definition: nls.h:101
#define LANG_QUECHUA
Definition: nls.h:110
#define LANG_GALICIAN
Definition: nls.h:60
#define LANG_INDONESIAN
Definition: nls.h:72
#define LANG_GERMAN
Definition: nls.h:62
#define LANG_ESTONIAN
Definition: nls.h:53
#define LANG_HEBREW
Definition: nls.h:67
#define LANG_KANNADA
Definition: nls.h:77
#define LANG_ORIYA
Definition: nls.h:104
#define LANG_CHINESE_TRADITIONAL
Definition: nls.h:44
#define LANG_UKRAINIAN
Definition: nls.h:139
#define SUBLANG_MONGOLIAN_CYRILLIC_MONGOLIA
Definition: nls.h:296
#define LANG_URDU
Definition: nls.h:141
#define LANG_BULGARIAN
Definition: nls.h:40
#define LANG_FINNISH
Definition: nls.h:57
#define LANG_BELARUSIAN
Definition: nls.h:35
#define LANG_GEORGIAN
Definition: nls.h:61
#define LANG_GREEK
Definition: nls.h:63
#define LANG_BASQUE
Definition: nls.h:34
#define LANG_PASHTO
Definition: nls.h:105
#define LANG_MACEDONIAN
Definition: nls.h:91
#define LANG_ENGLISH
Definition: nls.h:52
#define LANG_SINHALESE
Definition: nls.h:119
#define LANG_ROMANIAN
Definition: nls.h:111
#define LANG_MALAY
Definition: nls.h:92
#define LANG_BENGALI
Definition: nls.h:36
#define LANG_DUTCH
Definition: nls.h:51
#define LANG_TURKMEN
Definition: nls.h:137
#define SUBLANG_DEFAULT
Definition: nls.h:168
#define LANG_RUSSIAN
Definition: nls.h:113
#define LANG_VIETNAMESE
Definition: nls.h:143
#define LANG_PUNJABI
Definition: nls.h:109
#define LANG_CZECH
Definition: nls.h:47
#define LANG_HUNGARIAN
Definition: nls.h:69
#define LANG_SWEDISH
Definition: nls.h:125
#define LANG_ARABIC
Definition: nls.h:29
#define LANG_KYRGYZ
Definition: nls.h:85
#define LANG_GREENLANDIC
Definition: nls.h:64
#define LANG_CHINESE
Definition: nls.h:42
#define LANG_SERBIAN
Definition: nls.h:116
#define SUBLANG_AZERI_CYRILLIC
Definition: nls.h:197
DWORD LCID
Definition: nls.h:13
#define CP_UTF8
Definition: nls.h:20
#define LANG_JAPANESE
Definition: nls.h:76
#define LANG_SAMI
Definition: nls.h:114
#define PRIMARYLANGID(l)
Definition: nls.h:16
#define LANG_LATVIAN
Definition: nls.h:87
#define LANG_BRETON
Definition: nls.h:39
#define LANG_TIBETAN
Definition: nls.h:133
#define LANG_ICELANDIC
Definition: nls.h:70
#define LANG_SINDHI
Definition: nls.h:118
#define LANG_UIGHUR
Definition: nls.h:138
#define LANG_SLOVAK
Definition: nls.h:120
#define LANG_KOREAN
Definition: nls.h:84
#define LANG_AFRIKAANS
Definition: nls.h:25
#define LANG_SLOVENIAN
Definition: nls.h:121
#define LANG_TAJIK
Definition: nls.h:127
#define LANG_GUJARATI
Definition: nls.h:65
#define LANG_WELSH
Definition: nls.h:144
#define LANG_MARATHI
Definition: nls.h:98
#define LANG_SWAHILI
Definition: nls.h:124
#define LANG_FRENCH
Definition: nls.h:58
#define LANG_UZBEK
Definition: nls.h:142
#define LANG_TELUGU
Definition: nls.h:131
#define LANG_ITALIAN
Definition: nls.h:75
#define LANG_ARMENIAN
Definition: nls.h:30
#define LANG_KHMER
Definition: nls.h:80
#define LANG_PORTUGUESE
Definition: nls.h:108
#define LANG_CATALAN
Definition: nls.h:41
#define LANG_KAZAK
Definition: nls.h:79
#define SUBLANG_IRISH_IRELAND
Definition: nls.h:268
#define LANG_MONGOLIAN
Definition: nls.h:100
#define LANG_IRISH
Definition: nls.h:74
#define SUBLANG_AZERI_LATIN
Definition: nls.h:196
#define LANG_FAEROESE
Definition: nls.h:54
wcscpy
strcat
Definition: string.h:92
strcpy
Definition: string.h:131
int winetest_get_mainargs(char ***pargv)
#define wait_child_process
Definition: test.h:159
static int fd
Definition: io.c:51
#define memset(x, y, z)
Definition: compat.h:39
static char * tmp_name
Definition: cache.c:24
weight
Definition: sortkey.c:157
BYTE lfStrikeOut
Definition: dimm.idl:49
BYTE lfClipPrecision
Definition: dimm.idl:52
BYTE lfUnderline
Definition: dimm.idl:48
BYTE lfQuality
Definition: dimm.idl:53
BYTE lfOutPrecision
Definition: dimm.idl:51
LONG lfOrientation
Definition: dimm.idl:45
BYTE lfItalic
Definition: dimm.idl:47
BYTE lfPitchAndFamily
Definition: dimm.idl:54
LONG lfHeight
Definition: dimm.idl:42
LONG lfEscapement
Definition: dimm.idl:44
BYTE lfCharSet
Definition: dimm.idl:50
LONG lfWeight
Definition: dimm.idl:46
CHAR lfFaceName[LF_FACESIZE]
Definition: dimm.idl:55
LONG lfWidth
Definition: dimm.idl:43
LONG lfHeight
Definition: dimm.idl:59
LONG lfWeight
Definition: dimm.idl:63
WCHAR lfFaceName[LF_FACESIZE]
Definition: dimm.idl:72
BYTE lfCharSet
Definition: dimm.idl:67
USHORT majorVersion
Definition: font.c:7372
SHORT xMaxExtent
Definition: font.c:7380
USHORT advanceWidthMax
Definition: font.c:7377
SHORT metricDataFormat
Definition: font.c:7385
SHORT caretOffset
Definition: font.c:7383
SHORT minLeftSideBearing
Definition: font.c:7378
SHORT descender
Definition: font.c:7375
SHORT lineGap
Definition: font.c:7376
SHORT numberOfHMetrics
Definition: font.c:7386
SHORT caretSlopeRun
Definition: font.c:7382
SHORT minRightSideBearing
Definition: font.c:7379
USHORT minorVersion
Definition: font.c:7373
SHORT ascender
Definition: font.c:7374
SHORT caretSlopeRise
Definition: font.c:7381
USHORT usMaxContext
Definition: font.c:3378
USHORT usLastCharIndex
Definition: font.c:3360
USHORT version
Definition: font.c:3336
SHORT ySubscriptYOffset
Definition: font.c:3344
ULONG ulUnicodeRange4
Definition: font.c:3356
ULONG ulCodePageRange1
Definition: font.c:3371
PANOSE panose
Definition: font.c:3352
SHORT xAvgCharWidth
Definition: font.c:3337
USHORT usDefaultChar
Definition: font.c:3376
ULONG ulUnicodeRange2
Definition: font.c:3354
SHORT ySuperscriptXSize
Definition: font.c:3345
USHORT usWinDescent
Definition: font.c:3369
SHORT ySubscriptXSize
Definition: font.c:3341
SHORT sFamilyClass
Definition: font.c:3351
SHORT ySubscriptXOffset
Definition: font.c:3343
ULONG ulUnicodeRange3
Definition: font.c:3355
USHORT usWeightClass
Definition: font.c:3338
USHORT sTypoAscender
Definition: font.c:3365
USHORT sTypoDescender
Definition: font.c:3366
SHORT sxHeight
Definition: font.c:3374
USHORT usLowerOpticalPointSize
Definition: font.c:3380
SHORT ySuperscriptXOffset
Definition: font.c:3347
USHORT usFirstCharIndex
Definition: font.c:3359
SHORT ySubscriptYSize
Definition: font.c:3342
SHORT sCapHeight
Definition: font.c:3375
ULONG ulCodePageRange2
Definition: font.c:3372
USHORT usWidthClass
Definition: font.c:3339
ULONG ulUnicodeRange1
Definition: font.c:3353
USHORT usWinAscent
Definition: font.c:3368
SHORT yStrikeoutSize
Definition: font.c:3349
SHORT ySuperscriptYOffset
Definition: font.c:3348
USHORT usBreakChar
Definition: font.c:3377
CHAR achVendID[4]
Definition: font.c:3357
USHORT fsSelection
Definition: font.c:3358
SHORT yStrikeoutPosition
Definition: font.c:3350
SHORT ySuperscriptYSize
Definition: font.c:3346
USHORT usUpperOpticalPointSize
Definition: font.c:3381
USHORT sTypoLineGap
Definition: font.c:3367
SHORT fsType
Definition: font.c:3340
FLOAT abcfA
Definition: wingdi.h:1862
FLOAT abcfC
Definition: wingdi.h:1864
FLOAT abcfB
Definition: wingdi.h:1863
Definition: wingdi.h:1856
int abcA
Definition: wingdi.h:1857
UINT abcB
Definition: wingdi.h:1858
int abcC
Definition: wingdi.h:1859
short value
Definition: wingdi.h:2916
short gmCellIncX
Definition: wingdi.h:2891
UINT gmBlackBoxY
Definition: wingdi.h:2889
UINT gmBlackBoxX
Definition: wingdi.h:2888
short gmCellIncY
Definition: wingdi.h:2892
POINT gmptGlyphOrigin
Definition: wingdi.h:2890
Definition: wingdi.h:2918
FIXED eM11
Definition: wingdi.h:2919
TEXTMETRICA otmTextMetrics
Definition: wingdi.h:2926
TEXTMETRICW otmTextMetrics
Definition: wingdi.h:2960
LONG cx
Definition: kdterminal.h:27
LONG cy
Definition: kdterminal.h:28
FLOAT eDy
Definition: wingdi.h:2172
FLOAT eM11
Definition: wingdi.h:2167
FLOAT eM21
Definition: wingdi.h:2169
FLOAT eM22
Definition: wingdi.h:2170
FLOAT eM12
Definition: wingdi.h:2168
FLOAT eDx
Definition: wingdi.h:2171
BYTE glyph_ids[256]
Definition: font.c:3406
USHORT language
Definition: font.c:3404
USHORT length
Definition: font.c:3403
USHORT format
Definition: font.c:3402
USHORT id_delta
Definition: font.c:3434
USHORT id_range_offset
Definition: font.c:3435
USHORT start_count
Definition: font.c:3433
USHORT end_count
Definition: font.c:3432
USHORT search_range
Definition: font.c:3416
USHORT end_count[1]
Definition: font.c:3420
USHORT language
Definition: font.c:3413
USHORT seg_countx2
Definition: font.c:3415
USHORT format
Definition: font.c:3411
USHORT range_shift
Definition: font.c:3418
USHORT entry_selector
Definition: font.c:3417
USHORT length
Definition: font.c:3412
USHORT num_tables
Definition: font.c:3390
USHORT version
Definition: font.c:3389
Definition: inflate.c:139
Definition: http.c:7252
LOGFONTW * lf
Definition: font.c:2858
LOGFONTA * lf
Definition: font.c:2840
ENUMLOGFONTW * elf
Definition: font.c:2852
ENUMLOGFONTA * elf
Definition: font.c:2846
FILETIME time
Definition: font.c:4333
LARGE_INTEGER size
Definition: font.c:4334
WCHAR * info
Definition: actctx.c:140
WCHAR path[MAX_PATH]
Definition: font.c:4335
Definition: fci.c:127
Definition: dsound.c:943
int weight
Definition: font.c:1901
BOOL exact
Definition: font.c:1902
int dpi
Definition: font.c:1901
int requested_height
Definition: font.c:1900
int descent
Definition: font.c:1901
int int_leading
Definition: font.c:1901
int height
Definition: font.c:1901
int ext_leading
Definition: font.c:1901
const char face_name[LF_FACESIZE]
Definition: font.c:1899
int ascent
Definition: font.c:1901
Definition: format.c:58
Definition: ffs.h:70
Definition: name.c:39
USHORT platform_id
Definition: font.c:3586
USHORT offset
Definition: font.c:3591
USHORT encoding_id
Definition: font.c:3587
USHORT length
Definition: font.c:3590
USHORT language_id
Definition: font.c:3588
USHORT name_id
Definition: font.c:3589
USHORT biBitCount
Definition: precomp.h:34
ULONG biCompression
Definition: precomp.h:35
BITMAPINFOHEADER bmiHeader
Definition: wingdi.h:1922
LONG bmHeight
Definition: wingdi.h:1869
LONG bmWidthBytes
Definition: wingdi.h:1870
FONTSIGNATURE fs
Definition: wingdi.h:1994
UINT ciCharset
Definition: wingdi.h:1992
BYTE elfStyle[LF_FACESIZE]
Definition: wingdi.h:3134
LOGFONTA elfLogFont
Definition: wingdi.h:3132
BYTE elfFullName[LF_FULLFACESIZE]
Definition: wingdi.h:3133
LOGFONTA elfLogFont
Definition: wingdi.h:3142
ENUMLOGFONTEXA elfEnumLogfontEx
Definition: wingdi.h:3220
DWORD fsUsb[4]
Definition: wingdi.h:1988
DWORD fsCsb[2]
Definition: wingdi.h:1989
WORD wSecond
Definition: wingdi.h:2911
int iKernAmount
Definition: wingdi.h:2912
CHAR lfFaceName[LF_FACESIZE]
Definition: wingdi.h:2340
LONG tmInternalLeading
Definition: wingdi.h:3067
LONG tmAveCharWidth
Definition: wingdi.h:3069
UINT ntmCellHeight
Definition: wingdi.h:3086
FONTSIGNATURE ntmFontSig
Definition: wingdi.h:3118
UINT ntmCellHeight
Definition: wingdi.h:3112
BYTE bSerifStyle
Definition: wingdi.h:2316
BYTE bProportion
Definition: wingdi.h:2318
BYTE bWeight
Definition: wingdi.h:2317
BYTE bFamilyType
Definition: wingdi.h:2315
long y
Definition: polytest.cpp:48
long x
Definition: polytest.cpp:48
LONG right
Definition: windef.h:108
LONG top
Definition: windef.h:107
LONG left
Definition: windef.h:106
BYTE tmStruckOut
Definition: wingdi.h:2824
BYTE tmPitchAndFamily
Definition: wingdi.h:2825
BYTE tmCharSet
Definition: wingdi.h:2826
LONG tmDescent
Definition: wingdi.h:2809
LONG tmDigitizedAspectX
Definition: wingdi.h:2816
BYTE tmFirstChar
Definition: wingdi.h:2818
LONG tmExternalLeading
Definition: wingdi.h:2811
LONG tmWeight
Definition: wingdi.h:2814
BYTE tmBreakChar
Definition: wingdi.h:2821
LONG tmInternalLeading
Definition: wingdi.h:2810
BYTE tmLastChar
Definition: wingdi.h:2819
BYTE tmUnderlined
Definition: wingdi.h:2823
LONG tmMaxCharWidth
Definition: wingdi.h:2813
LONG tmAveCharWidth
Definition: wingdi.h:2812
BYTE tmDefaultChar
Definition: wingdi.h:2820
LONG tmAscent
Definition: wingdi.h:2808
LONG tmOverhang
Definition: wingdi.h:2815
LONG tmHeight
Definition: wingdi.h:2807
BYTE tmItalic
Definition: wingdi.h:2822
LONG tmDigitizedAspectY
Definition: wingdi.h:2817
WCHAR tmFirstChar
Definition: wingdi.h:2840
LONG tmDigitizedAspectX
Definition: wingdi.h:2838
LONG tmAscent
Definition: wingdi.h:2830
LONG tmMaxCharWidth
Definition: wingdi.h:2835
WCHAR tmBreakChar
Definition: wingdi.h:2843
WCHAR tmDefaultChar
Definition: wingdi.h:2842
WCHAR tmLastChar
Definition: wingdi.h:2841
LONG tmHeight
Definition: wingdi.h:2829
LONG tmDescent
Definition: wingdi.h:2831
Definition: ecma_167.h:138
Definition: tools.h:99
#define max(a, b)
Definition: svc.c:63
T1_FIELD_DICT_FONTDICT family_name
Definition: t1tokens.h:30
const char * LPCSTR
Definition: typedefs.h:52
int32_t INT_PTR
Definition: typedefs.h:64
const uint16_t * LPCWSTR
Definition: typedefs.h:57
unsigned char UCHAR
Definition: typedefs.h:53
uint32_t DWORD_PTR
Definition: typedefs.h:65
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
ULONG_PTR SIZE_T
Definition: typedefs.h:80
uint32_t * LPDWORD
Definition: typedefs.h:59
char * LPSTR
Definition: typedefs.h:51
int32_t INT
Definition: typedefs.h:58
const char * PCSTR
Definition: typedefs.h:52
uint32_t ULONG
Definition: typedefs.h:59
#define BI_RGB
Definition: uefivid.c:46
LONGLONG QuadPart
Definition: typedefs.h:114
ULONG LowPart
Definition: typedefs.h:106
#define INVALID_FILE_ATTRIBUTES
Definition: vfdcmd.c:23
static const WCHAR lang[]
Definition: wbemdisp.c:287
wchar_t tm const _CrtWcstime_Writes_and_advances_ptr_ count wchar_t ** out
Definition: wcsftime.cpp:383
HBITMAP WINAPI CreateDIBSection(HDC hDC, CONST BITMAPINFO *BitmapInfo, UINT Usage, VOID **Bits, HANDLE hSection, DWORD dwOffset)
Definition: bitmap.c:245
DWORD WINAPI GetFontData(HDC hdc, DWORD dwTable, DWORD dwOffset, LPVOID lpvBuffer, DWORD cbData)
Definition: font.c:2801
BOOL WINAPI RemoveFontResourceExA(_In_ LPCSTR lpFileName, _In_ DWORD fl, _In_opt_ PVOID pdv)
Definition: font.c:2212
BOOL WINAPI RemoveFontMemResourceEx(HANDLE fh)
Definition: font.c:2622
#define dpi
Definition: sysparams.c:23
int codepage
Definition: win_iconv.c:156
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
_In_ LONG _In_ HWND hwnd
Definition: winddi.h:4023
#define WINAPI
Definition: msvc.h:6
const char * description
Definition: directx.c:2497
#define ERROR_FILE_EXISTS
Definition: winerror.h:287
#define ERROR_CAN_NOT_COMPLETE
Definition: winerror.h:906
#define ERROR_NOACCESS
Definition: winerror.h:902
#define FS_TURKISH
Definition: wingdi.h:564
BOOL WINAPI GetTextExtentExPointI(_In_ HDC hdc, _In_reads_(cwchString) LPWORD lpwszString, _In_ int cwchString, _In_ int nMaxExtent, _Out_opt_ LPINT lpnFit, _Out_writes_to_opt_(cwchString, *lpnFit) LPINT lpnDx, _Out_ LPSIZE lpSize)
#define FIXED_PITCH
Definition: wingdi.h:444
int WINAPI SetMapMode(_In_ HDC, _In_ int)
#define GM_COMPATIBLE
Definition: wingdi.h:864
#define DEFAULT_PITCH
Definition: wingdi.h:443
#define FW_REGULAR
Definition: wingdi.h:374
#define PAN_SERIF_THIN
Definition: wingdi.h:476
#define VARIABLE_PITCH
Definition: wingdi.h:445
BOOL WINAPI GetCharABCWidthsFloatA(_In_ HDC hdc, _In_ UINT iFirst, _In_ UINT iLast, _Out_writes_(iLast+1 - iFirst) LPABCFLOAT lpABC)
#define DIB_RGB_COLORS
Definition: wingdi.h:367
BOOL WINAPI GetTextMetricsW(_In_ HDC, _Out_ LPTEXTMETRICW)
Definition: text.c:221
#define PAN_FAMILY_TEXT_DISPLAY
Definition: wingdi.h:467
#define ANSI_FIXED_FONT
Definition: wingdi.h:906
#define PAN_PROP_MONOSPACED
Definition: wingdi.h:502
#define RUSSIAN_CHARSET
Definition: wingdi.h:396
HGDIOBJ WINAPI GetStockObject(_In_ int)
#define FS_JOHAB
Definition: wingdi.h:574
#define FW_DONTCARE
Definition: wingdi.h:368
#define FF_MODERN
Definition: wingdi.h:449
BOOL WINAPI GetCharABCWidthsA(_In_ HDC hdc, _In_ UINT wFirst, _In_ UINT wLast, _Out_writes_(wLast - wFirst+1) LPABC lpABC)
BOOL WINAPI GetCharWidthFloatA(_In_ HDC hdc, _In_ UINT iFirst, _In_ UINT iLast, _Out_writes_(iLast+1 - iFirst) PFLOAT lpBuffer)
DWORD WINAPI GetGlyphIndicesW(_In_ HDC hdc, _In_reads_(c) LPCWSTR lpstr, _In_ int c, _Out_writes_(c) LPWORD pgi, _In_ DWORD fl)
UINT WINAPI GetOutlineTextMetricsA(_In_ HDC hdc, _In_ UINT cjCopy, _Out_writes_bytes_opt_(cjCopy) LPOUTLINETEXTMETRICA potm)
int WINAPI GetTextCharsetInfo(_In_ HDC, _Out_opt_ LPFONTSIGNATURE, _In_ DWORD)
#define FF_DECORATIVE
Definition: wingdi.h:447
#define PAN_SERIF_NORMAL_SANS
Definition: wingdi.h:480
BOOL WINAPI GetCharWidthI(_In_ HDC hdc, _In_ UINT giFirst, _In_ UINT cgi, _In_reads_opt_(cgi) LPWORD pgi, _Out_writes_(cgi) LPINT piWidths)
#define FS_THAI
Definition: wingdi.h:569
#define GGO_GRAY2_BITMAP
Definition: wingdi.h:852
int WINAPI GetDeviceCaps(_In_opt_ HDC, _In_ int)
int WINAPI SetGraphicsMode(_In_ HDC, _In_ int)
Definition: dc.c:1233
#define FS_ARABIC
Definition: wingdi.h:566
#define FF_SCRIPT
Definition: wingdi.h:451
#define OUT_TT_ONLY_PRECIS
Definition: wingdi.h:422
#define FS_WANSUNG
Definition: wingdi.h:572
#define GM_ADVANCED
Definition: wingdi.h:865
#define PAN_SERIF_BONE
Definition: wingdi.h:477
HFONT WINAPI CreateFontIndirectA(_In_ const LOGFONTA *)
int WINAPI GetObjectA(_In_ HANDLE h, _In_ int c, _Out_writes_bytes_opt_(c) LPVOID pv)
#define FF_ROMAN
Definition: wingdi.h:450
BOOL WINAPI GetCharABCWidthsFloatW(_In_ HDC hdc, _In_ UINT iFirst, _In_ UINT iLast, _Out_writes_(iLast+1 - iFirst) LPABCFLOAT lpABC)
DWORD WINAPI GetCharacterPlacementW(_In_ HDC hdc, _In_reads_(nCount) LPCWSTR lpString, _In_ int nCount, _In_ int nMexExtent, _Inout_ LPGCP_RESULTSW lpResults, _In_ DWORD dwFlags)
#define MM_HIMETRIC
Definition: wingdi.h:869
int WINAPI EnumFontFamiliesExW(_In_ HDC, _In_ PLOGFONTW, _In_ FONTENUMPROCW, _In_ LPARAM, _In_ DWORD)
#define PAN_SERIF_OBTUSE_SANS
Definition: wingdi.h:481
#define DEFAULT_QUALITY
Definition: wingdi.h:436
BOOL WINAPI GetTextExtentExPointA(_In_ HDC hdc, _In_reads_(cchString) LPCSTR lpszString, _In_ int cchString, _In_ int nMaxExtent, _Out_opt_ LPINT lpnFit, _Out_writes_to_opt_(cchString, *lpnFit) LPINT lpnDx, _Out_ LPSIZE lpSize)
#define PAN_FAMILY_PICTORIAL
Definition: wingdi.h:470
BOOL WINAPI SetViewportExtEx(_In_ HDC, _In_ int, _In_ int, _Out_opt_ LPSIZE)
Definition: coord.c:465
#define FW_BOLD
Definition: wingdi.h:378
#define FF_DONTCARE
Definition: wingdi.h:448
#define TRUETYPE_FONTTYPE
Definition: wingdi.h:1109
#define LOGPIXELSY
Definition: wingdi.h:719
#define FS_LATIN2
Definition: wingdi.h:561
#define PAN_SERIF_TRIANGLE
Definition: wingdi.h:479
#define ANSI_VAR_FONT
Definition: wingdi.h:907
BOOL WINAPI DPtoLP(_In_ HDC hdc, _Inout_updates_(c) LPPOINT lppt, _In_ int c)
BOOL WINAPI LPtoDP(_In_ HDC hdc, _Inout_updates_(c) LPPOINT lppt, _In_ int c)
#define FS_VIETNAMESE
Definition: wingdi.h:568
#define ARABIC_CHARSET
Definition: wingdi.h:394
#define HANGEUL_CHARSET
Definition: wingdi.h:387
BOOL WINAPI GetTextExtentPointW(_In_ HDC hdc, _In_reads_(c) LPCWSTR lpString, _In_ int c, _Out_ LPSIZE lpsz)
HGDIOBJ WINAPI GetCurrentObject(_In_ HDC, _In_ UINT)
Definition: dc.c:428
#define DEFAULT_GUI_FONT
Definition: wingdi.h:909
int WINAPI EnumFontFamiliesExA(_In_ HDC, _In_ PLOGFONTA, _In_ FONTENUMPROCA, _In_ LPARAM, _In_ DWORD)
HGDIOBJ WINAPI SelectObject(_In_ HDC, _In_ HGDIOBJ)
Definition: dc.c:1546
#define GCP_USEKERNING
Definition: wingdi.h:845
#define MM_ANISOTROPIC
Definition: wingdi.h:867
HDC WINAPI CreateCompatibleDC(_In_opt_ HDC hdc)
#define FS_GREEK
Definition: wingdi.h:563
int WINAPI SetTextCharacterExtra(_In_ HDC, _In_ int)
#define TT_POLYGON_TYPE
Definition: wingdi.h:1318
int WINAPI GetTextFaceA(_In_ HDC hdc, _In_ int c, _Out_writes_to_opt_(c, return) LPSTR lpName)
#define DEFAULT_CHARSET
Definition: wingdi.h:384
#define THAI_CHARSET
Definition: wingdi.h:397
int WINAPI EnumFontFamiliesW(_In_ HDC, _In_opt_ LPCWSTR, _In_ FONTENUMPROCW, _In_ LPARAM)
int WINAPI GetTextFaceW(_In_ HDC hdc, _In_ int c, _Out_writes_to_opt_(c, return) LPWSTR lpName)
BOOL WINAPI SetWindowExtEx(_In_ HDC, _In_ int, _In_ int, _Out_opt_ LPSIZE)
#define TMPF_TRUETYPE
Definition: wingdi.h:1313
int WINAPI GetTextCharset(_In_ HDC)
Definition: text.c:187
#define RASTER_FONTTYPE
Definition: wingdi.h:1107
#define CLIP_LH_ANGLES
Definition: wingdi.h:430
BOOL WINAPI SetTextJustification(_In_ HDC, _In_ int, _In_ int)
#define PAN_NO_FIT
Definition: wingdi.h:466
#define GREEK_CHARSET
Definition: wingdi.h:391
#define PAN_SERIF_SQUARE_COVE
Definition: wingdi.h:473
BOOL WINAPI ExtTextOutA(_In_ HDC hdc, _In_ int x, _In_ int y, _In_ UINT options, _In_opt_ const RECT *lprect, _In_reads_opt_(c) LPCSTR lpString, _In_ UINT c, _In_reads_opt_(c) const INT *lpDx)
#define PAN_SERIF_SQUARE
Definition: wingdi.h:475
#define JOHAB_CHARSET
Definition: wingdi.h:401
#define FS_HEBREW
Definition: wingdi.h:565
#define FS_SYMBOL
Definition: wingdi.h:575
#define CLIP_DFA_DISABLE
Definition: wingdi.h:433
#define PAN_SERIF_OBTUSE_SQUARE_COVE
Definition: wingdi.h:474
int WINAPI EnumFontFamiliesA(_In_ HDC, _In_opt_ LPCSTR, _In_ FONTENUMPROCA, _In_ LPARAM)
#define MM_LOMETRIC
Definition: wingdi.h:872
#define PAN_SERIF_COVE
Definition: wingdi.h:471
#define CHINESEBIG5_CHARSET
Definition: wingdi.h:390
#define PAN_SERIF_EXAGGERATED
Definition: wingdi.h:478
#define OUT_DEFAULT_PRECIS
Definition: wingdi.h:415
BOOL WINAPI ExtTextOutW(_In_ HDC hdc, _In_ int x, _In_ int y, _In_ UINT options, _In_opt_ const RECT *lprect, _In_reads_opt_(c) LPCWSTR lpString, _In_ UINT c, _In_reads_opt_(c) const INT *lpDx)
#define GGO_GLYPH_INDEX
Definition: wingdi.h:855
#define MM_ISOTROPIC
Definition: wingdi.h:870
#define NTM_REGULAR
Definition: wingdi.h:1317
#define PAN_SERIF_ROUNDED
Definition: wingdi.h:484
#define ANSI_CHARSET
Definition: wingdi.h:383
#define PROOF_QUALITY
Definition: wingdi.h:438
BOOL WINAPI GetCharABCWidthsI(_In_ HDC hdc, _In_ UINT giFirst, _In_ UINT cgi, _In_reads_opt_(cgi) LPWORD pgi, _Out_writes_(cgi) LPABC pabc)
#define OUT_TT_PRECIS
Definition: wingdi.h:419
#define FS_LATIN1
Definition: wingdi.h:560
#define GDI_ERROR
Definition: wingdi.h:1309
#define TCI_SRCCHARSET
Definition: wingdi.h:961
#define MM_TEXT
Definition: wingdi.h:873
#define FS_JISJAPAN
Definition: wingdi.h:570
#define FS_CHINESETRAD
Definition: wingdi.h:573
#define FS_CHINESESIMP
Definition: wingdi.h:571
#define GGO_GRAY8_BITMAP
Definition: wingdi.h:854
#define CLIP_DEFAULT_PRECIS
Definition: wingdi.h:426
#define OEM_CHARSET
Definition: wingdi.h:400
UINT WINAPI GetOutlineTextMetricsW(_In_ HDC hdc, _In_ UINT cjCopy, _Out_writes_bytes_opt_(cjCopy) LPOUTLINETEXTMETRICW potm)
BOOL WINAPI GetCharWidth32A(_In_ HDC hdc, _In_ UINT iFirst, _In_ UINT iLast, _Out_writes_(iLast+1 - iFirst) LPINT lpBuffer)
#define PAN_FAMILY_DECORATIVE
Definition: wingdi.h:469
#define PAN_SERIF_PERP_SANS
Definition: wingdi.h:482
#define FW_NORMAL
Definition: wingdi.h:373
#define SYSTEM_FONT
Definition: wingdi.h:911
BOOL WINAPI GetTextExtentExPointW(_In_ HDC hdc, _In_reads_(cchString) LPCWSTR lpszString, _In_ int cchString, _In_ int nMaxExtent, _Out_opt_ LPINT lpnFit, _Out_writes_to_opt_(cchString, *lpnFit) LPINT lpnDx, _Out_ LPSIZE lpSize)
#define LOGPIXELSX
Definition: wingdi.h:718
#define VIETNAMESE_CHARSET
Definition: wingdi.h:402
DWORD WINAPI GetGlyphIndicesA(_In_ HDC hdc, _In_reads_(c) LPCSTR lpstr, _In_ int c, _Out_writes_(c) LPWORD pgi, _In_ DWORD fl)
#define GGO_BITMAP
Definition: wingdi.h:849
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)
BOOL WINAPI GetTextMetricsA(_In_ HDC, _Out_ LPTEXTMETRICA)
Definition: text.c:200
DWORD WINAPI GetKerningPairsW(_In_ HDC hdc, _In_ DWORD nPairs, _Out_writes_to_opt_(nPairs, return) LPKERNINGPAIR lpKernPair)
HFONT WINAPI CreateFontIndirectW(_In_ const LOGFONTW *)
#define GCP_REORDER
Definition: wingdi.h:843
#define GGO_GRAY4_BITMAP
Definition: wingdi.h:853
#define NTM_BOLD
Definition: wingdi.h:1316
BOOL WINAPI SetWorldTransform(_In_ HDC, _In_ const XFORM *)
#define PAN_SERIF_FLARED
Definition: wingdi.h:483
BOOL WINAPI CreateScalableFontResourceA(_In_ DWORD, _In_ LPCSTR, _In_ LPCSTR, _In_opt_ LPCSTR)
#define PAN_FAMILY_SCRIPT
Definition: wingdi.h:468
DWORD WINAPI GetCharacterPlacementA(_In_ HDC hdc, _In_reads_(nCount) LPCSTR lpString, _In_ int nCount, _In_ int nMexExtent, _Inout_ LPGCP_RESULTSA lpResults, _In_ DWORD dwFlags)
BOOL WINAPI DeleteDC(_In_ HDC)
#define GGO_NATIVE
Definition: wingdi.h:850
INT WINAPI AddFontResourceExA(_In_ LPCSTR pszFilename, _In_ DWORD fl, _Reserved_ PVOID pvReserved)
#define PAN_SERIF_OBTUSE_COVE
Definition: wingdi.h:472
#define HEBREW_CHARSET
Definition: wingdi.h:393
BOOL WINAPI GetTextExtentPointA(_In_ HDC hdc, _In_reads_(c) LPCSTR lpString, _In_ int c, _Out_ LPSIZE lpsz)
#define SHIFTJIS_CHARSET
Definition: wingdi.h:386
BOOL WINAPI GetCharWidth32W(_In_ HDC hdc, _In_ UINT iFirst, _In_ UINT iLast, _Out_writes_(iLast+1 - iFirst) LPINT lpBuffer)
#define DEVICE_DEFAULT_FONT
Definition: wingdi.h:908
#define PAN_ANY
Definition: wingdi.h:465
BOOL WINAPI GetTextExtentPoint32A(_In_ HDC hdc, _In_reads_(c) LPCSTR lpString, _In_ int c, _Out_ LPSIZE psizl)
#define FS_BALTIC
Definition: wingdi.h:567
BOOL WINAPI TranslateCharsetInfo(_Inout_ PDWORD, _Out_ LPCHARSETINFO, _In_ DWORD)
#define GGO_METRICS
Definition: wingdi.h:848
DWORD WINAPI GetGlyphOutlineW(_In_ HDC hdc, _In_ UINT uChar, _In_ UINT fuFormat, _Out_ LPGLYPHMETRICS lpgm, _In_ DWORD cjBuffer, _Out_writes_bytes_opt_(cjBuffer) LPVOID pvBuffer, _In_ CONST MAT2 *lpmat2)
#define FF_SWISS
Definition: wingdi.h:452
#define SYMBOL_CHARSET
Definition: wingdi.h:385
#define GGI_MARK_NONEXISTING_GLYPHS
Definition: wingdi.h:1085
#define EASTEUROPE_CHARSET
Definition: wingdi.h:399
BOOL WINAPI GetCharWidthA(_In_ HDC hdc, _In_ UINT iFirst, _In_ UINT iLast, _Out_writes_(iLast+1 - iFirst) LPINT lpBuffer)
#define GB2312_CHARSET
Definition: wingdi.h:389
#define LF_FULLFACESIZE
Definition: wingdi.h:41
HFONT WINAPI CreateFontIndirectExA(const ENUMLOGFONTEXDVA *)
Definition: font.c:1680
#define TCI_SRCFONTSIG
Definition: wingdi.h:963
#define FS_CYRILLIC
Definition: wingdi.h:562
DWORD WINAPI GetGlyphOutlineA(_In_ HDC hdc, _In_ UINT uChar, _In_ UINT fuFormat, _Out_ LPGLYPHMETRICS lpgm, _In_ DWORD cjBuffer, _Out_writes_bytes_opt_(cjBuffer) LPVOID pvBuffer, _In_ CONST MAT2 *lpmat2)
#define BALTIC_CHARSET
Definition: wingdi.h:395
#define FW_MEDIUM
Definition: wingdi.h:375
BOOL WINAPI GetCharABCWidthsW(_In_ HDC hdc, _In_ UINT wFirst, _In_ UINT wLast, _Out_writes_(wLast - wFirst+1) LPABC lpABC)
#define TCI_SRCCODEPAGE
Definition: wingdi.h:962
#define TURKISH_CHARSET
Definition: wingdi.h:392
HANDLE WINAPI AddFontMemResourceEx(_In_reads_bytes_(cjSize) PVOID pvFileView, _In_ DWORD cjSize, _Reserved_ PVOID pvResrved, _In_ DWORD *pNumFonts)
#define CP_SYMBOL
Definition: winnls.h:252
#define WS_EX_LAYOUTRTL
Definition: winuser.h:390
int WINAPI ReleaseDC(_In_opt_ HWND, _In_ HDC)
HWND WINAPI CreateWindowExA(_In_ DWORD dwExStyle, _In_opt_ LPCSTR lpClassName, _In_opt_ LPCSTR lpWindowName, _In_ DWORD dwStyle, _In_ int X, _In_ int Y, _In_ int nWidth, _In_ int nHeight, _In_opt_ HWND hWndParent, _In_opt_ HMENU hMenu, _In_opt_ HINSTANCE hInstance, _In_opt_ LPVOID lpParam)
BOOL WINAPI GetClientRect(_In_ HWND, _Out_ LPRECT)
HDC WINAPI GetDC(_In_opt_ HWND)
BOOL WINAPI DestroyWindow(_In_ HWND)
unsigned char BYTE
Definition: xxhash.c:193