ReactOS 0.4.15-dev-7788-g1ad9096
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 <assert.h>
24
25#include "windef.h"
26#include "winbase.h"
27#include "wingdi.h"
28#include "winuser.h"
29#include "winnls.h"
30
31#include "wine/heap.h"
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 *pGetCharABCWidthsI)(HDC hdc, UINT first, UINT count, LPWORD glyphs, LPABC abc);
45static BOOL (WINAPI *pGetCharABCWidthsA)(HDC hdc, UINT first, UINT last, LPABC abc);
46static BOOL (WINAPI *pGetCharABCWidthsW)(HDC hdc, UINT first, UINT last, LPABC abc);
47static BOOL (WINAPI *pGetCharABCWidthsFloatW)(HDC hdc, UINT first, UINT last, LPABCFLOAT abc);
48static BOOL (WINAPI *pGetCharWidth32A)(HDC hdc, UINT first, UINT last, LPINT buffer);
49static BOOL (WINAPI *pGetCharWidth32W)(HDC hdc, UINT first, UINT last, LPINT buffer);
50static DWORD (WINAPI *pGetFontUnicodeRanges)(HDC hdc, LPGLYPHSET lpgs);
51static DWORD (WINAPI *pGetGlyphIndicesA)(HDC hdc, LPCSTR lpstr, INT count, LPWORD pgi, DWORD flags);
52static DWORD (WINAPI *pGetGlyphIndicesW)(HDC hdc, LPCWSTR lpstr, INT count, LPWORD pgi, DWORD flags);
53static BOOL (WINAPI *pGetTextExtentExPointI)(HDC hdc, const WORD *indices, INT count, INT max_ext,
55static BOOL (WINAPI *pGdiRealizationInfo)(HDC hdc, DWORD *);
56static HFONT (WINAPI *pCreateFontIndirectExA)(const ENUMLOGFONTEXDVA *);
57static HANDLE (WINAPI *pAddFontMemResourceEx)(PVOID, DWORD, PVOID, DWORD *);
58static BOOL (WINAPI *pRemoveFontMemResourceEx)(HANDLE);
59static INT (WINAPI *pAddFontResourceExA)(LPCSTR, DWORD, PVOID);
60static BOOL (WINAPI *pRemoveFontResourceExA)(LPCSTR, DWORD, PVOID);
61static BOOL (WINAPI *pGetFontRealizationInfo)(HDC hdc, DWORD *);
62static BOOL (WINAPI *pGetFontFileInfo)(DWORD, DWORD, void *, DWORD, DWORD *);
63static BOOL (WINAPI *pGetFontFileData)(DWORD, DWORD, ULONGLONG, void *, DWORD);
64
65static HMODULE hgdi32 = 0;
66static const MAT2 mat = { {0,1}, {0,0}, {0,0}, {0,1} };
68
69#ifdef WORDS_BIGENDIAN
70#define GET_BE_WORD(x) (x)
71#define GET_BE_DWORD(x) (x)
72#else
73#define GET_BE_WORD(x) MAKEWORD(HIBYTE(x), LOBYTE(x))
74#define GET_BE_DWORD(x) MAKELONG(GET_BE_WORD(HIWORD(x)), GET_BE_WORD(LOWORD(x)));
75#endif
76
77#define MS_MAKE_TAG(ch0, ch1, ch2, ch3) \
78 ((DWORD)(BYTE)(ch0) | ((DWORD)(BYTE)(ch1) << 8) | \
79 ((DWORD)(BYTE)(ch2) << 16) | ((DWORD)(BYTE)(ch3) << 24))
80#define MS_OS2_TAG MS_MAKE_TAG('O','S','/','2')
81#define MS_CMAP_TAG MS_MAKE_TAG('c','m','a','p')
82#define MS_NAME_TAG MS_MAKE_TAG('n','a','m','e')
83
84static void init(void)
85{
86 hgdi32 = GetModuleHandleA("gdi32.dll");
87
88 pGdiGetCharDimensions = (void *)GetProcAddress(hgdi32, "GdiGetCharDimensions");
89 pGdiGetCodePage = (void *) GetProcAddress(hgdi32,"GdiGetCodePage");
90 pGetCharABCWidthsI = (void *)GetProcAddress(hgdi32, "GetCharABCWidthsI");
91 pGetCharABCWidthsA = (void *)GetProcAddress(hgdi32, "GetCharABCWidthsA");
92 pGetCharABCWidthsW = (void *)GetProcAddress(hgdi32, "GetCharABCWidthsW");
93 pGetCharABCWidthsFloatW = (void *)GetProcAddress(hgdi32, "GetCharABCWidthsFloatW");
94 pGetCharWidth32A = (void *)GetProcAddress(hgdi32, "GetCharWidth32A");
95 pGetCharWidth32W = (void *)GetProcAddress(hgdi32, "GetCharWidth32W");
96 pGetFontUnicodeRanges = (void *)GetProcAddress(hgdi32, "GetFontUnicodeRanges");
97 pGetGlyphIndicesA = (void *)GetProcAddress(hgdi32, "GetGlyphIndicesA");
98 pGetGlyphIndicesW = (void *)GetProcAddress(hgdi32, "GetGlyphIndicesW");
99 pGetTextExtentExPointI = (void *)GetProcAddress(hgdi32, "GetTextExtentExPointI");
100 pGdiRealizationInfo = (void *)GetProcAddress(hgdi32, "GdiRealizationInfo");
101 pCreateFontIndirectExA = (void *)GetProcAddress(hgdi32, "CreateFontIndirectExA");
102 pAddFontMemResourceEx = (void *)GetProcAddress(hgdi32, "AddFontMemResourceEx");
103 pRemoveFontMemResourceEx = (void *)GetProcAddress(hgdi32, "RemoveFontMemResourceEx");
104 pAddFontResourceExA = (void *)GetProcAddress(hgdi32, "AddFontResourceExA");
105 pRemoveFontResourceExA = (void *)GetProcAddress(hgdi32, "RemoveFontResourceExA");
106 pGetFontRealizationInfo = (void *)GetProcAddress(hgdi32, "GetFontRealizationInfo");
107 pGetFontFileInfo = (void *)GetProcAddress(hgdi32, "GetFontFileInfo");
108 pGetFontFileData = (void *)GetProcAddress(hgdi32, "GetFontFileData");
109
111}
112
114{
115 if (type != TRUETYPE_FONTTYPE) return 1;
116
117 return 0;
118}
119
121{
122 HDC hdc = GetDC(0);
123 BOOL ret = FALSE;
124
126 ret = TRUE;
127
128 ReleaseDC(0, hdc);
129 return ret;
130}
131
133{
134 return 0;
135}
136
137static BOOL is_font_installed(const char *name)
138{
139 HDC hdc = GetDC(0);
140 BOOL ret = FALSE;
141
143 ret = TRUE;
144
145 ReleaseDC(0, hdc);
146 return ret;
147}
148
149static void *get_res_data(const char *fontname, DWORD *rsrc_size)
150{
151 HRSRC rsrc;
152 void *rsrc_data;
153
155 if (!rsrc) return NULL;
156
157 rsrc_data = LockResource(LoadResource(GetModuleHandleA(NULL), rsrc));
158 if (!rsrc_data) return NULL;
159
160 *rsrc_size = SizeofResource(GetModuleHandleA(NULL), rsrc);
161 if (!*rsrc_size) return NULL;
162
163 return rsrc_data;
164}
165
166static BOOL write_tmp_file( const void *data, DWORD *size, char *tmp_name )
167{
168 char tmp_path[MAX_PATH];
169 HANDLE hfile;
170 BOOL ret;
171
172 GetTempPathA(MAX_PATH, tmp_path);
173 GetTempFileNameA(tmp_path, "ttf", 0, tmp_name);
174
176 if (hfile == INVALID_HANDLE_VALUE) return FALSE;
177
178 ret = WriteFile(hfile, data, *size, size, NULL);
179
180 CloseHandle(hfile);
181 return ret;
182}
183
184static BOOL write_ttf_file(const char *fontname, char *tmp_name)
185{
186 void *rsrc_data;
187 DWORD rsrc_size;
188
189 rsrc_data = get_res_data( fontname, &rsrc_size );
190 if (!rsrc_data) return FALSE;
191
192 return write_tmp_file( rsrc_data, &rsrc_size, tmp_name );
193}
194
195static void check_font(const char* test, const LOGFONTA* lf, HFONT hfont)
196{
197 LOGFONTA getobj_lf;
198 int ret, minlen = 0;
199
200 if (!hfont)
201 return;
202
203 ret = GetObjectA(hfont, sizeof(getobj_lf), &getobj_lf);
204 /* NT4 tries to be clever and only returns the minimum length */
205 while (lf->lfFaceName[minlen] && minlen < LF_FACESIZE-1)
206 minlen++;
207 minlen += FIELD_OFFSET(LOGFONTA, lfFaceName) + 1;
208 ok(ret == sizeof(LOGFONTA) || ret == minlen, "%s: GetObject returned %d\n", test, ret);
209 ok(lf->lfHeight == getobj_lf.lfHeight ||
210 broken((SHORT)lf->lfHeight == getobj_lf.lfHeight), /* win9x */
211 "lfHeight: expect %08x got %08x\n", lf->lfHeight, getobj_lf.lfHeight);
212 ok(lf->lfWidth == getobj_lf.lfWidth ||
213 broken((SHORT)lf->lfWidth == getobj_lf.lfWidth), /* win9x */
214 "lfWidth: expect %08x got %08x\n", lf->lfWidth, getobj_lf.lfWidth);
215 ok(lf->lfEscapement == getobj_lf.lfEscapement ||
216 broken((SHORT)lf->lfEscapement == getobj_lf.lfEscapement), /* win9x */
217 "lfEscapement: expect %08x got %08x\n", lf->lfEscapement, getobj_lf.lfEscapement);
218 ok(lf->lfOrientation == getobj_lf.lfOrientation ||
219 broken((SHORT)lf->lfOrientation == getobj_lf.lfOrientation), /* win9x */
220 "lfOrientation: expect %08x got %08x\n", lf->lfOrientation, getobj_lf.lfOrientation);
221 ok(lf->lfWeight == getobj_lf.lfWeight ||
222 broken((SHORT)lf->lfWeight == getobj_lf.lfWeight), /* win9x */
223 "lfWeight: expect %08x got %08x\n", lf->lfWeight, getobj_lf.lfWeight);
224 ok(lf->lfItalic == getobj_lf.lfItalic, "lfItalic: expect %02x got %02x\n", lf->lfItalic, getobj_lf.lfItalic);
225 ok(lf->lfUnderline == getobj_lf.lfUnderline, "lfUnderline: expect %02x got %02x\n", lf->lfUnderline, getobj_lf.lfUnderline);
226 ok(lf->lfStrikeOut == getobj_lf.lfStrikeOut, "lfStrikeOut: expect %02x got %02x\n", lf->lfStrikeOut, getobj_lf.lfStrikeOut);
227 ok(lf->lfCharSet == getobj_lf.lfCharSet, "lfCharSet: expect %02x got %02x\n", lf->lfCharSet, getobj_lf.lfCharSet);
228 ok(lf->lfOutPrecision == getobj_lf.lfOutPrecision, "lfOutPrecision: expect %02x got %02x\n", lf->lfOutPrecision, getobj_lf.lfOutPrecision);
229 ok(lf->lfClipPrecision == getobj_lf.lfClipPrecision, "lfClipPrecision: expect %02x got %02x\n", lf->lfClipPrecision, getobj_lf.lfClipPrecision);
230 ok(lf->lfQuality == getobj_lf.lfQuality, "lfQuality: expect %02x got %02x\n", lf->lfQuality, getobj_lf.lfQuality);
231 ok(lf->lfPitchAndFamily == getobj_lf.lfPitchAndFamily, "lfPitchAndFamily: expect %02x got %02x\n", lf->lfPitchAndFamily, getobj_lf.lfPitchAndFamily);
232 ok(!lstrcmpA(lf->lfFaceName, getobj_lf.lfFaceName) ||
233 broken(!memcmp(lf->lfFaceName, getobj_lf.lfFaceName, LF_FACESIZE-1)), /* win9x doesn't ensure '\0' termination */
234 "%s: font names don't match: %s != %s\n", test, lf->lfFaceName, getobj_lf.lfFaceName);
235}
236
237static HFONT create_font(const char* test, const LOGFONTA* lf)
238{
240 ok(hfont != 0, "%s: CreateFontIndirect failed\n", test);
241 if (hfont)
242 check_font(test, lf, hfont);
243 return hfont;
244}
245
246static void test_logfont(void)
247{
248 LOGFONTA lf;
249 HFONT hfont;
250
251 memset(&lf, 0, sizeof lf);
252
256 lf.lfHeight = 16;
257 lf.lfWidth = 16;
259
260 lstrcpyA(lf.lfFaceName, "Arial");
261 hfont = create_font("Arial", &lf);
263
264 memset(&lf, 'A', sizeof(lf));
266 ok(hfont != 0, "CreateFontIndirectA with strange LOGFONT failed\n");
267
268 lf.lfFaceName[LF_FACESIZE - 1] = 0;
269 check_font("AAA...", &lf, hfont);
271}
272
274{
275 if (type & RASTER_FONTTYPE)
276 {
277 LOGFONTA *lf = (LOGFONTA *)lParam;
278 *lf = *elf;
279 return 0; /* stop enumeration */
280 }
281
282 return 1; /* continue enumeration */
283}
284
285static void compare_tm(const TEXTMETRICA *tm, const TEXTMETRICA *otm)
286{
287 ok(tm->tmHeight == otm->tmHeight, "tmHeight %d != %d\n", tm->tmHeight, otm->tmHeight);
288 ok(tm->tmAscent == otm->tmAscent, "tmAscent %d != %d\n", tm->tmAscent, otm->tmAscent);
289 ok(tm->tmDescent == otm->tmDescent, "tmDescent %d != %d\n", tm->tmDescent, otm->tmDescent);
290 ok(tm->tmInternalLeading == otm->tmInternalLeading, "tmInternalLeading %d != %d\n", tm->tmInternalLeading, otm->tmInternalLeading);
291 ok(tm->tmExternalLeading == otm->tmExternalLeading, "tmExternalLeading %d != %d\n", tm->tmExternalLeading, otm->tmExternalLeading);
292 ok(tm->tmAveCharWidth == otm->tmAveCharWidth, "tmAveCharWidth %d != %d\n", tm->tmAveCharWidth, otm->tmAveCharWidth);
293 ok(tm->tmMaxCharWidth == otm->tmMaxCharWidth, "tmMaxCharWidth %d != %d\n", tm->tmMaxCharWidth, otm->tmMaxCharWidth);
294 ok(tm->tmWeight == otm->tmWeight, "tmWeight %d != %d\n", tm->tmWeight, otm->tmWeight);
295 ok(tm->tmOverhang == otm->tmOverhang, "tmOverhang %d != %d\n", tm->tmOverhang, otm->tmOverhang);
296 ok(tm->tmDigitizedAspectX == otm->tmDigitizedAspectX, "tmDigitizedAspectX %d != %d\n", tm->tmDigitizedAspectX, otm->tmDigitizedAspectX);
297 ok(tm->tmDigitizedAspectY == otm->tmDigitizedAspectY, "tmDigitizedAspectY %d != %d\n", tm->tmDigitizedAspectY, otm->tmDigitizedAspectY);
298 ok(tm->tmFirstChar == otm->tmFirstChar, "tmFirstChar %d != %d\n", tm->tmFirstChar, otm->tmFirstChar);
299 ok(tm->tmLastChar == otm->tmLastChar, "tmLastChar %d != %d\n", tm->tmLastChar, otm->tmLastChar);
300 ok(tm->tmDefaultChar == otm->tmDefaultChar, "tmDefaultChar %d != %d\n", tm->tmDefaultChar, otm->tmDefaultChar);
301 ok(tm->tmBreakChar == otm->tmBreakChar, "tmBreakChar %d != %d\n", tm->tmBreakChar, otm->tmBreakChar);
302 ok(tm->tmItalic == otm->tmItalic, "tmItalic %d != %d\n", tm->tmItalic, otm->tmItalic);
303 ok(tm->tmUnderlined == otm->tmUnderlined, "tmUnderlined %d != %d\n", tm->tmUnderlined, otm->tmUnderlined);
304 ok(tm->tmStruckOut == otm->tmStruckOut, "tmStruckOut %d != %d\n", tm->tmStruckOut, otm->tmStruckOut);
305 ok(tm->tmPitchAndFamily == otm->tmPitchAndFamily, "tmPitchAndFamily %d != %d\n", tm->tmPitchAndFamily, otm->tmPitchAndFamily);
306 ok(tm->tmCharSet == otm->tmCharSet, "tmCharSet %d != %d\n", tm->tmCharSet, otm->tmCharSet);
307}
308
309static void test_font_metrics(HDC hdc, HFONT hfont, LONG lfHeight,
310 LONG lfWidth, const char *test_str,
311 INT test_str_len, const TEXTMETRICA *tm_orig,
312 const SIZE *size_orig, INT width_of_A_orig,
313 INT scale_x, INT scale_y)
314{
315 LOGFONTA lf;
318 SIZE size;
319 INT width_of_A, cx, cy;
320 UINT ret;
321
322 if (!hfont)
323 return;
324
325 ok(GetCurrentObject(hdc, OBJ_FONT) == hfont, "hfont should be selected\n");
326
327 GetObjectA(hfont, sizeof(lf), &lf);
328
330 {
331 otm.otmSize = sizeof(otm) / 2;
333 ok(ret == sizeof(otm)/2 /* XP */ ||
334 ret == 1 /* Win9x */, "expected sizeof(otm)/2, got %u\n", ret);
335
336 memset(&otm, 0x1, sizeof(otm));
337 otm.otmSize = sizeof(otm);
339 ok(ret == sizeof(otm) /* XP */ ||
340 ret == 1 /* Win9x */, "expected sizeof(otm), got %u\n", ret);
341
342 memset(&tm, 0x2, sizeof(tm));
344 ok(ret, "GetTextMetricsA failed\n");
345 /* the structure size is aligned */
346 if (memcmp(&tm, &otm.otmTextMetrics, FIELD_OFFSET(TEXTMETRICA, tmCharSet) + 1))
347 {
348 ok(0, "tm != otm\n");
350 }
351
352 tm = otm.otmTextMetrics;
353if (0) /* these metrics are scaled too, but with rounding errors */
354{
355 ok(otm.otmAscent == tm.tmAscent, "ascent %d != %d\n", otm.otmAscent, tm.tmAscent);
356 ok(otm.otmDescent == -tm.tmDescent, "descent %d != %d\n", otm.otmDescent, -tm.tmDescent);
357}
358 ok(otm.otmMacAscent == tm.tmAscent, "ascent %d != %d\n", otm.otmMacAscent, tm.tmAscent);
359 ok(otm.otmDescent < 0, "otm.otmDescent should be < 0\n");
360 ok(otm.otmMacDescent < 0, "otm.otmMacDescent should be < 0\n");
361 ok(tm.tmDescent > 0, "tm.tmDescent should be > 0\n");
362 ok(otm.otmMacDescent == -tm.tmDescent, "descent %d != %d\n", otm.otmMacDescent, -tm.tmDescent);
363 ok(otm.otmEMSquare == 2048, "expected 2048, got %d\n", otm.otmEMSquare);
364 }
365 else
366 {
368 ok(ret, "GetTextMetricsA failed\n");
369 }
370
371 cx = tm.tmAveCharWidth / tm_orig->tmAveCharWidth;
372 cy = tm.tmHeight / tm_orig->tmHeight;
373 ok(cx == scale_x && cy == scale_y, "height %d: expected scale_x %d, scale_y %d, got cx %d, cy %d\n",
374 lfHeight, scale_x, scale_y, cx, cy);
375 ok(tm.tmHeight == tm_orig->tmHeight * scale_y, "height %d != %d\n", tm.tmHeight, tm_orig->tmHeight * scale_y);
376 ok(tm.tmAscent == tm_orig->tmAscent * scale_y, "ascent %d != %d\n", tm.tmAscent, tm_orig->tmAscent * scale_y);
377 ok(tm.tmDescent == tm_orig->tmDescent * scale_y, "descent %d != %d\n", tm.tmDescent, tm_orig->tmDescent * scale_y);
378 ok(near_match(tm.tmAveCharWidth, tm_orig->tmAveCharWidth * scale_x), "ave width %d != %d\n", tm.tmAveCharWidth, tm_orig->tmAveCharWidth * scale_x);
379 ok(near_match(tm.tmMaxCharWidth, tm_orig->tmMaxCharWidth * scale_x), "max width %d != %d\n", tm.tmMaxCharWidth, tm_orig->tmMaxCharWidth * scale_x);
380
381 ok(lf.lfHeight == lfHeight, "lfHeight %d != %d\n", lf.lfHeight, lfHeight);
382 if (lf.lfHeight)
383 {
384 if (lf.lfWidth)
385 ok(lf.lfWidth == tm.tmAveCharWidth, "lfWidth %d != tm %d\n", lf.lfWidth, tm.tmAveCharWidth);
386 }
387 else
388 ok(lf.lfWidth == lfWidth, "lfWidth %d != %d\n", lf.lfWidth, lfWidth);
389
390 GetTextExtentPoint32A(hdc, test_str, test_str_len, &size);
391
392 ok(near_match(size.cx, size_orig->cx * scale_x), "cx %d != %d\n", size.cx, size_orig->cx * scale_x);
393 ok(size.cy == size_orig->cy * scale_y, "cy %d != %d\n", size.cy, size_orig->cy * scale_y);
394
395 GetCharWidthA(hdc, 'A', 'A', &width_of_A);
396
397 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);
398}
399
400/* Test how GDI scales bitmap font metrics */
401static void test_bitmap_font(void)
402{
403 static const char test_str[11] = "Test String";
404 HDC hdc;
405 LOGFONTA bitmap_lf;
406 HFONT hfont, old_hfont;
407 TEXTMETRICA tm_orig;
408 SIZE size_orig;
409 INT ret, i, width_orig, height_orig, scale, lfWidth;
410
412
413 /* "System" has only 1 pixel size defined, otherwise the test breaks */
414 ret = EnumFontFamiliesA(hdc, "System", font_enum_proc, (LPARAM)&bitmap_lf);
415 if (ret)
416 {
417 ReleaseDC(0, hdc);
418 trace("no bitmap fonts were found, skipping the test\n");
419 return;
420 }
421
422 trace("found bitmap font %s, height %d\n", bitmap_lf.lfFaceName, bitmap_lf.lfHeight);
423
424 height_orig = bitmap_lf.lfHeight;
425 lfWidth = bitmap_lf.lfWidth;
426
427 hfont = create_font("bitmap", &bitmap_lf);
428 old_hfont = SelectObject(hdc, hfont);
429 ok(GetTextMetricsA(hdc, &tm_orig), "GetTextMetricsA failed\n");
430 ok(GetTextExtentPoint32A(hdc, test_str, sizeof(test_str), &size_orig), "GetTextExtentPoint32A failed\n");
431 ok(GetCharWidthA(hdc, 'A', 'A', &width_orig), "GetCharWidthA failed\n");
432 SelectObject(hdc, old_hfont);
434
435 bitmap_lf.lfHeight = 0;
436 bitmap_lf.lfWidth = 4;
437 hfont = create_font("bitmap", &bitmap_lf);
438 old_hfont = SelectObject(hdc, hfont);
439 test_font_metrics(hdc, hfont, 0, 4, test_str, sizeof(test_str), &tm_orig, &size_orig, width_orig, 1, 1);
440 SelectObject(hdc, old_hfont);
442
443 bitmap_lf.lfHeight = height_orig;
444 bitmap_lf.lfWidth = lfWidth;
445
446 /* test fractional scaling */
447 for (i = 1; i <= height_orig * 6; i++)
448 {
449 INT nearest_height;
450
451 bitmap_lf.lfHeight = i;
452 hfont = create_font("fractional", &bitmap_lf);
453 scale = (i + height_orig - 1) / height_orig;
454 nearest_height = scale * height_orig;
455 /* Only jump to the next height if the difference <= 25% original height */
456 if (scale > 2 && nearest_height - i > height_orig / 4) scale--;
457 /* The jump between unscaled and doubled is delayed by 1 in winnt+ but not in win9x,
458 so we'll not test this particular height. */
459 else if(scale == 2 && nearest_height - i == (height_orig / 4)) continue;
460 else if(scale == 2 && nearest_height - i > (height_orig / 4 - 1)) scale--;
461 old_hfont = SelectObject(hdc, hfont);
462 test_font_metrics(hdc, hfont, bitmap_lf.lfHeight, 0, test_str, sizeof(test_str), &tm_orig, &size_orig, width_orig, 1, scale);
463 SelectObject(hdc, old_hfont);
465 }
466
467 /* test integer scaling 3x2 */
468 bitmap_lf.lfHeight = height_orig * 2;
469 bitmap_lf.lfWidth *= 3;
470 hfont = create_font("3x2", &bitmap_lf);
471 old_hfont = SelectObject(hdc, hfont);
472 test_font_metrics(hdc, hfont, bitmap_lf.lfHeight, 0, test_str, sizeof(test_str), &tm_orig, &size_orig, width_orig, 3, 2);
473 SelectObject(hdc, old_hfont);
475
476 /* test integer scaling 3x3 */
477 bitmap_lf.lfHeight = height_orig * 3;
478 bitmap_lf.lfWidth = 0;
479 hfont = create_font("3x3", &bitmap_lf);
480 old_hfont = SelectObject(hdc, hfont);
481 test_font_metrics(hdc, hfont, bitmap_lf.lfHeight, 0, test_str, sizeof(test_str), &tm_orig, &size_orig, width_orig, 3, 3);
482 SelectObject(hdc, old_hfont);
484
485 DeleteDC(hdc);
486}
487
488/* Test how GDI scales outline font metrics */
489static void test_outline_font(void)
490{
491 static const char test_str[11] = "Test String";
492 HDC hdc, hdc_2;
493 LOGFONTA lf;
494 HFONT hfont, old_hfont, old_hfont_2;
496 SIZE size_orig;
497 INT width_orig, height_orig, lfWidth;
498 XFORM xform;
499 GLYPHMETRICS gm;
500 MAT2 mat2 = { {0x8000,0}, {0,0}, {0,0}, {0x8000,0} };
501 POINT pt;
502 INT ret;
503
504 if (!is_truetype_font_installed("Arial"))
505 {
506 skip("Arial is not installed\n");
507 return;
508 }
509
511
512 memset(&lf, 0, sizeof(lf));
513 strcpy(lf.lfFaceName, "Arial");
514 lf.lfHeight = 72;
515 hfont = create_font("outline", &lf);
516 old_hfont = SelectObject(hdc, hfont);
517 otm.otmSize = sizeof(otm);
518 ok(GetOutlineTextMetricsA(hdc, sizeof(otm), &otm), "GetTextMetricsA failed\n");
519 ok(GetTextExtentPoint32A(hdc, test_str, sizeof(test_str), &size_orig), "GetTextExtentPoint32A failed\n");
520 ok(GetCharWidthA(hdc, 'A', 'A', &width_orig), "GetCharWidthA failed\n");
521
522 test_font_metrics(hdc, hfont, lf.lfHeight, otm.otmTextMetrics.tmAveCharWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
523 SelectObject(hdc, old_hfont);
525
526 /* font of otmEMSquare height helps to avoid a lot of rounding errors */
527 lf.lfHeight = otm.otmEMSquare;
528 lf.lfHeight = -lf.lfHeight;
529 hfont = create_font("outline", &lf);
530 old_hfont = SelectObject(hdc, hfont);
531 otm.otmSize = sizeof(otm);
532 ok(GetOutlineTextMetricsA(hdc, sizeof(otm), &otm), "GetTextMetricsA failed\n");
533 ok(GetTextExtentPoint32A(hdc, test_str, sizeof(test_str), &size_orig), "GetTextExtentPoint32A failed\n");
534 ok(GetCharWidthA(hdc, 'A', 'A', &width_orig), "GetCharWidthA failed\n");
535 SelectObject(hdc, old_hfont);
537
538 height_orig = otm.otmTextMetrics.tmHeight;
539 lfWidth = otm.otmTextMetrics.tmAveCharWidth;
540
541 /* test integer scaling 3x2 */
542 lf.lfHeight = height_orig * 2;
543 lf.lfWidth = lfWidth * 3;
544 hfont = create_font("3x2", &lf);
545 old_hfont = SelectObject(hdc, hfont);
546 test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 3, 2);
547 SelectObject(hdc, old_hfont);
549
550 /* test integer scaling 3x3 */
551 lf.lfHeight = height_orig * 3;
552 lf.lfWidth = lfWidth * 3;
553 hfont = create_font("3x3", &lf);
554 old_hfont = SelectObject(hdc, hfont);
555 test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 3, 3);
556 SelectObject(hdc, old_hfont);
558
559 /* test integer scaling 1x1 */
560 lf.lfHeight = height_orig * 1;
561 lf.lfWidth = lfWidth * 1;
562 hfont = create_font("1x1", &lf);
563 old_hfont = SelectObject(hdc, hfont);
564 test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
565 SelectObject(hdc, old_hfont);
567
568 /* test integer scaling 1x1 */
569 lf.lfHeight = height_orig;
570 lf.lfWidth = 0;
571 hfont = create_font("1x1", &lf);
572 old_hfont = SelectObject(hdc, hfont);
573 test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
574
575 /* with an identity matrix */
576 memset(&gm, 0, sizeof(gm));
577 SetLastError(0xdeadbeef);
578 ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
579 ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError());
580 trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig);
581 ok(gm.gmCellIncX == width_orig, "incX %d != %d\n", gm.gmCellIncX, width_orig);
582 ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
583 /* with a custom matrix */
584 memset(&gm, 0, sizeof(gm));
585 SetLastError(0xdeadbeef);
586 ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat2);
587 ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError());
588 trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig);
589 ok(gm.gmCellIncX == width_orig/2, "incX %d != %d\n", gm.gmCellIncX, width_orig/2);
590 ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
591
592 /* Test that changing the DC transformation affects only the font
593 * selected on this DC and doesn't affect the same font selected on
594 * another DC.
595 */
596 hdc_2 = CreateCompatibleDC(0);
597 old_hfont_2 = SelectObject(hdc_2, hfont);
598 test_font_metrics(hdc_2, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
599
601
602 /* font metrics on another DC should be unchanged */
603 test_font_metrics(hdc_2, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
604
605 /* test restrictions of compatibility mode GM_COMPATIBLE */
606 /* part 1: rescaling only X should not change font scaling on screen.
607 So compressing the X axis by 2 is not done, and this
608 appears as X scaling of 2 that no one requested. */
609 SetWindowExtEx(hdc, 100, 100, NULL);
610 SetViewportExtEx(hdc, 50, 100, NULL);
611 test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 2, 1);
612 /* font metrics on another DC should be unchanged */
613 test_font_metrics(hdc_2, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
614
615 /* part 2: rescaling only Y should change font scaling.
616 As also X is scaled by a factor of 2, but this is not
617 requested by the DC transformation, we get a scaling factor
618 of 2 in the X coordinate. */
619 SetViewportExtEx(hdc, 100, 200, NULL);
620 test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 2, 1);
621 /* font metrics on another DC should be unchanged */
622 test_font_metrics(hdc_2, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
623
624 /* restore scaling */
626
627 /* font metrics on another DC should be unchanged */
628 test_font_metrics(hdc_2, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
629
630 SelectObject(hdc_2, old_hfont_2);
631 DeleteDC(hdc_2);
632
634 {
635 SelectObject(hdc, old_hfont);
637 DeleteDC(hdc);
638 skip("GM_ADVANCED is not supported on this platform\n");
639 return;
640 }
641
642 xform.eM11 = 20.0f;
643 xform.eM12 = 0.0f;
644 xform.eM21 = 0.0f;
645 xform.eM22 = 20.0f;
646 xform.eDx = 0.0f;
647 xform.eDy = 0.0f;
648
649 SetLastError(0xdeadbeef);
650 ret = SetWorldTransform(hdc, &xform);
651 ok(ret, "SetWorldTransform error %u\n", GetLastError());
652
653 test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
654
655 /* with an identity matrix */
656 memset(&gm, 0, sizeof(gm));
657 SetLastError(0xdeadbeef);
658 ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
659 ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError());
660 trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig);
661 pt.x = width_orig; pt.y = 0;
662 LPtoDP(hdc, &pt, 1);
663 ok(gm.gmCellIncX == pt.x, "incX %d != %d\n", gm.gmCellIncX, pt.x);
664 ok(gm.gmCellIncX == 20 * width_orig, "incX %d != %d\n", gm.gmCellIncX, 20 * width_orig);
665 ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
666 /* with a custom matrix */
667 memset(&gm, 0, sizeof(gm));
668 SetLastError(0xdeadbeef);
669 ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat2);
670 ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError());
671 trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig);
672 pt.x = width_orig; pt.y = 0;
673 LPtoDP(hdc, &pt, 1);
674 ok(gm.gmCellIncX == pt.x/2, "incX %d != %d\n", gm.gmCellIncX, pt.x/2);
675 ok(near_match(gm.gmCellIncX, 10 * width_orig), "incX %d != %d\n", gm.gmCellIncX, 10 * width_orig);
676 ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
677
678 SetLastError(0xdeadbeef);
680 ok(ret == MM_TEXT, "expected MM_TEXT, got %d, error %u\n", ret, GetLastError());
681
682 test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
683
684 /* with an identity matrix */
685 memset(&gm, 0, sizeof(gm));
686 SetLastError(0xdeadbeef);
687 ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
688 ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError());
689 trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig);
690 pt.x = width_orig; pt.y = 0;
691 LPtoDP(hdc, &pt, 1);
692 ok(near_match(gm.gmCellIncX, pt.x), "incX %d != %d\n", gm.gmCellIncX, pt.x);
693 ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
694 /* with a custom matrix */
695 memset(&gm, 0, sizeof(gm));
696 SetLastError(0xdeadbeef);
697 ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat2);
698 ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError());
699 trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig);
700 pt.x = width_orig; pt.y = 0;
701 LPtoDP(hdc, &pt, 1);
702 ok(near_match(gm.gmCellIncX, (pt.x + 1)/2), "incX %d != %d\n", gm.gmCellIncX, (pt.x + 1)/2);
703 ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
704
705 SetLastError(0xdeadbeef);
707 ok(ret == MM_LOMETRIC, "expected MM_LOMETRIC, got %d, error %u\n", ret, GetLastError());
708
709 test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
710
711 /* with an identity matrix */
712 memset(&gm, 0, sizeof(gm));
713 SetLastError(0xdeadbeef);
714 ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
715 ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError());
716 trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig);
717 pt.x = width_orig; pt.y = 0;
718 LPtoDP(hdc, &pt, 1);
719 ok(gm.gmCellIncX == pt.x, "incX %d != %d\n", gm.gmCellIncX, pt.x);
720 ok(gm.gmCellIncX == 20 * width_orig, "incX %d != %d\n", gm.gmCellIncX, 20 * width_orig);
721 ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
722 /* with a custom matrix */
723 memset(&gm, 0, sizeof(gm));
724 SetLastError(0xdeadbeef);
725 ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat2);
726 ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError());
727 trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig);
728 pt.x = width_orig; pt.y = 0;
729 LPtoDP(hdc, &pt, 1);
730 ok(gm.gmCellIncX == pt.x/2, "incX %d != %d\n", gm.gmCellIncX, pt.x/2);
731 ok(gm.gmCellIncX == 10 * width_orig, "incX %d != %d\n", gm.gmCellIncX, 10 * width_orig);
732 ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
733
734 SelectObject(hdc, old_hfont);
736 DeleteDC(hdc);
737}
738
740{
741 LOGFONTA *lf = (LOGFONTA *)lParam;
742
743 if (elf->lfHeight == lf->lfHeight && !strcmp(elf->lfFaceName, lf->lfFaceName))
744 {
745 *lf = *elf;
746 return 0; /* stop enumeration */
747 }
748 return 1; /* continue enumeration */
749}
750
751static BOOL is_CJK(void)
752{
754}
755
756#define FH_SCALE 0x80000000
758{
759 static const WORD skip_rtl[] = {LANG_ARABIC, LANG_HEBREW, 0};
760 static const struct font_data
761 {
762 const char face_name[LF_FACESIZE];
764 int ave_char_width, max_char_width, dpi;
765 BYTE first_char, last_char, def_char, break_char;
766 DWORD ansi_bitfield;
767 const WORD *skip_lang_id;
768 int scaled_height;
769 } fd[] =
770 {
771 { "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 },
772 { "MS Sans Serif", FW_NORMAL, FH_SCALE | 6, 11, 2, 2, 0, 5, 11, 96, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC, 0, 13 },
773 { "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 },
774 { "MS Sans Serif", FW_NORMAL, FH_SCALE | 8, 11, 2, 2, 0, 5, 11, 96, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC, 0, 13 },
775 { "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 },
776 { "MS Sans Serif", FW_NORMAL, FH_SCALE | 10, 11, 2, 2, 0, 5, 11, 96, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC, 0, 13 },
777 { "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 },
778 { "MS Sans Serif", FW_NORMAL, FH_SCALE | 14, 11, 2, 2, 0, 5, 11, 96, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC, 0, 13 },
779 { "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 },
780 { "MS Sans Serif", FW_NORMAL, FH_SCALE | 18, 13, 3, 3, 0, 7, 14, 96, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC, 0, 16 },
781
782 { "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 },
783 { "MS Sans Serif", FW_NORMAL, FH_SCALE | 6, 13, 3, 3, 0, 7, 14, 120, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC, 0, 16 },
784 { "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 },
785 { "MS Sans Serif", FW_NORMAL, FH_SCALE | 8, 13, 3, 3, 0, 7, 14, 120, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC, 0, 16 },
786 { "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 },
787 { "MS Sans Serif", FW_NORMAL, FH_SCALE | 10, 13, 3, 3, 0, 7, 14, 120, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC, 0, 16 },
788 { "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 },
789 { "MS Sans Serif", FW_NORMAL, FH_SCALE | 14, 13, 3, 3, 0, 7, 14, 120, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC, 0, 16 },
790 { "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 },
791 { "MS Sans Serif", FW_NORMAL, FH_SCALE | 18, 13, 3, 3, 0, 7, 14, 120, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC, 0, 16 },
792
793 { "MS Sans Serif", FW_NORMAL, 13, 11, 2, 2, 0, 5, 11, 96, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 | FS_LATIN2 },
794 { "MS Sans Serif", FW_NORMAL, 13, 11, 2, 2, 0, 5, 11, 96, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC },
795 { "MS Sans Serif", FW_NORMAL, 16, 13, 3, 3, 0, 7, 14, 96, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 | FS_LATIN2 },
796 { "MS Sans Serif", FW_NORMAL, 16, 13, 3, 3, 0, 7, 14, 96, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC },
797 { "MS Sans Serif", FW_NORMAL, 20, 16, 4, 4, 0, 8, 16, 96, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 },
798 { "MS Sans Serif", FW_NORMAL, 20, 16, 4, 4, 0, 8, 18, 96, 0x20, 0xff, 0x81, 0x20, FS_LATIN2 },
799 { "MS Sans Serif", FW_NORMAL, 20, 16, 4, 4, 0, 8, 16, 96, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC },
800 { "MS Sans Serif", FW_NORMAL, 24, 19, 5, 6, 0, 9, 19, 96, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 },
801 { "MS Sans Serif", FW_NORMAL, 24, 19, 5, 6, 0, 9, 24, 96, 0x20, 0xff, 0x81, 0x40, FS_LATIN2 },
802 { "MS Sans Serif", FW_NORMAL, 24, 19, 5, 6, 0, 9, 20, 96, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC },
803 { "MS Sans Serif", FW_NORMAL, 29, 23, 6, 5, 0, 12, 24, 96, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 },
804 { "MS Sans Serif", FW_NORMAL, 29, 23, 6, 6, 0, 12, 24, 96, 0x20, 0xff, 0x81, 0x20, FS_LATIN2 },
805 { "MS Sans Serif", FW_NORMAL, 29, 23, 6, 5, 0, 12, 25, 96, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC },
806 { "MS Sans Serif", FW_NORMAL, 37, 29, 8, 5, 0, 16, 32, 96, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 },
807 { "MS Sans Serif", FW_NORMAL, 37, 29, 8, 5, 0, 16, 32, 96, 0x20, 0xff, 0x81, 0x40, FS_LATIN2 },
808 { "MS Sans Serif", FW_NORMAL, 37, 29, 8, 5, 0, 16, 32, 96, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC },
809
810 { "MS Sans Serif", FW_NORMAL, 16, 13, 3, 3, 0, 7, 14, 120, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 | FS_LATIN2 },
811 { "MS Sans Serif", FW_NORMAL, 16, 13, 3, 3, 0, 7, 14, 120, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC },
812 { "MS Sans Serif", FW_NORMAL, 20, 16, 4, 4, 0, 8, 18, 120, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 | FS_LATIN2 },
813 { "MS Sans Serif", FW_NORMAL, 20, 16, 4, 4, 0, 8, 17, 120, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC },
814 { "MS Sans Serif", FW_NORMAL, 25, 20, 5, 5, 0, 10, 21, 120, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 | FS_LATIN2 },
815 { "MS Sans Serif", FW_NORMAL, 25, 20, 5, 5, 0, 10, 21, 120, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC },
816 { "MS Sans Serif", FW_NORMAL, 29, 23, 6, 6, 0, 12, 24, 120, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 | FS_LATIN2 },
817 { "MS Sans Serif", FW_NORMAL, 29, 23, 6, 5, 0, 12, 24, 120, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC },
818 { "MS Sans Serif", FW_NORMAL, 36, 29, 7, 6, 0, 15, 30, 120, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 | FS_LATIN2 },
819 { "MS Sans Serif", FW_NORMAL, 36, 29, 7, 6, 0, 15, 30, 120, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC },
820 { "MS Sans Serif", FW_NORMAL, 46, 37, 9, 6, 0, 20, 40, 120, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 | FS_LATIN2 },
821 { "MS Sans Serif", FW_NORMAL, 46, 37, 9, 6, 0, 20, 40, 120, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC },
822
823 { "MS Serif", FW_NORMAL, 10, 8, 2, 2, 0, 4, 8, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 },
824 { "MS Serif", FW_NORMAL, 10, 8, 2, 2, 0, 5, 8, 96, 0x20, 0xff, 0x80, 0x20, FS_CYRILLIC },
825 { "MS Serif", FW_NORMAL, 11, 9, 2, 2, 0, 5, 9, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
826 { "MS Serif", FW_NORMAL, 13, 11, 2, 2, 0, 5, 11, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 },
827 { "MS Serif", FW_NORMAL, 13, 11, 2, 2, 0, 5, 12, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN2 | FS_CYRILLIC },
828 { "MS Serif", FW_NORMAL, 16, 13, 3, 3, 0, 6, 14, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 },
829 { "MS Serif", FW_NORMAL, 16, 13, 3, 3, 0, 6, 16, 96, 0x20, 0xff, 0x80, 0x20, FS_CYRILLIC },
830 { "MS Serif", FW_NORMAL, 19, 15, 4, 3, 0, 8, 18, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 },
831 { "MS Serif", FW_NORMAL, 19, 15, 4, 3, 0, 8, 19, 96, 0x20, 0xff, 0x80, 0x20, FS_CYRILLIC },
832 { "MS Serif", FW_NORMAL, 21, 16, 5, 3, 0, 9, 17, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 },
833 { "MS Serif", FW_NORMAL, 21, 16, 5, 3, 0, 9, 22, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN2 },
834 { "MS Serif", FW_NORMAL, 21, 16, 5, 3, 0, 9, 23, 96, 0x20, 0xff, 0x80, 0x20, FS_CYRILLIC },
835 { "MS Serif", FW_NORMAL, 27, 21, 6, 3, 0, 12, 23, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 },
836 { "MS Serif", FW_NORMAL, 27, 21, 6, 3, 0, 12, 26, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN2 },
837 { "MS Serif", FW_NORMAL, 27, 21, 6, 3, 0, 12, 27, 96, 0x20, 0xff, 0x80, 0x20, FS_CYRILLIC },
838 { "MS Serif", FW_NORMAL, 35, 27, 8, 3, 0, 16, 33, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 },
839 { "MS Serif", FW_NORMAL, 35, 27, 8, 3, 0, 16, 34, 96, 0x20, 0xff, 0x80, 0x20, FS_CYRILLIC },
840
841 { "MS Serif", FW_NORMAL, 16, 13, 3, 3, 0, 6, 14, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_CYRILLIC },
842 { "MS Serif", FW_NORMAL, 16, 13, 3, 3, 0, 6, 13, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN2 },
843 { "MS Serif", FW_NORMAL, 20, 16, 4, 4, 0, 8, 18, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_CYRILLIC },
844 { "MS Serif", FW_NORMAL, 20, 16, 4, 4, 0, 8, 15, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN2 },
845 { "MS Serif", FW_NORMAL, 23, 18, 5, 3, 0, 10, 21, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_CYRILLIC },
846 { "MS Serif", FW_NORMAL, 23, 18, 5, 3, 0, 10, 19, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN2 },
847 { "MS Serif", FW_NORMAL, 27, 21, 6, 4, 0, 12, 23, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 },
848 { "MS Serif", FW_MEDIUM, 27, 22, 5, 2, 0, 12, 30, 120, 0x20, 0xff, 0x80, 0x20, FS_CYRILLIC },
849 { "MS Serif", FW_NORMAL, 33, 26, 7, 3, 0, 14, 30, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 },
850 { "MS Serif", FW_MEDIUM, 32, 25, 7, 2, 0, 14, 32, 120, 0x20, 0xff, 0x80, 0x20, FS_CYRILLIC },
851 { "MS Serif", FW_NORMAL, 43, 34, 9, 3, 0, 19, 39, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
852
853 { "Courier", FW_NORMAL, 13, 11, 2, 0, 0, 8, 8, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
854 { "Courier", FW_NORMAL, 16, 13, 3, 0, 0, 9, 9, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
855 { "Courier", FW_NORMAL, 20, 16, 4, 0, 0, 12, 12, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
856
857 { "Courier", FW_NORMAL, 16, 13, 3, 0, 0, 9, 9, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
858 { "Courier", FW_NORMAL, 20, 16, 4, 0, 0, 12, 12, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
859 { "Courier", FW_NORMAL, 25, 20, 5, 0, 0, 15, 15, 120, 0x20, 0xff, 0x40, 0x20, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
860
861 { "System", FW_BOLD, 16, 13, 3, 3, 0, 7, 14, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 },
862 { "System", FW_BOLD, 16, 13, 3, 3, 0, 7, 15, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN2 | FS_CYRILLIC },
863 { "System", FW_NORMAL, 18, 16, 2, 0, 2, 8, 16, 96, 0x20, 0xff, 0x80, 0x20, FS_JISJAPAN },
864
865 { "System", FW_BOLD, 20, 16, 4, 4, 0, 9, 14, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 },
866 { "System", FW_BOLD, 20, 16, 4, 4, 0, 9, 17, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN2 | FS_CYRILLIC },
867
868 { "Small Fonts", FW_NORMAL, 3, 2, 1, 0, 0, 1, 2, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 },
869 { "Small Fonts", FW_NORMAL, 3, 2, 1, 0, 0, 1, 8, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN2 | FS_CYRILLIC },
870 { "Small Fonts", FW_NORMAL, 3, 2, 1, 0, 0, 2, 4, 96, 0x20, 0xff, 0x80, 0x20, FS_JISJAPAN },
871 { "Small Fonts", FW_NORMAL, 5, 4, 1, 1, 0, 3, 4, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1, skip_rtl},
872 { "Small Fonts", FW_NORMAL, 5, 4, 1, 1, 0, 2, 8, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN2 | FS_CYRILLIC },
873 { "Small Fonts", FW_NORMAL, 5, 4, 1, 0, 0, 3, 6, 96, 0x20, 0xff, 0x80, 0x20, FS_JISJAPAN },
874 { "Small Fonts", FW_NORMAL, 6, 5, 1, 1, 0, 3, 13, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1, skip_rtl},
875 { "Small Fonts", FW_NORMAL, 6, 5, 1, 1, 0, 3, 8, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN2 | FS_CYRILLIC },
876 { "Small Fonts", FW_NORMAL, 6, 5, 1, 1, 0, 3, 8, 96, 0x00, 0xff, 0x60, 0x00, FS_ARABIC },
877 { "Small Fonts", FW_NORMAL, 6, 5, 1, 0, 0, 4, 8, 96, 0x20, 0xff, 0x80, 0x20, FS_JISJAPAN },
878 { "Small Fonts", FW_NORMAL, 8, 7, 1, 1, 0, 4, 7, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1, skip_rtl},
879 { "Small Fonts", FW_NORMAL, 8, 7, 1, 1, 0, 4, 8, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN2 | FS_CYRILLIC },
880 { "Small Fonts", FW_NORMAL, 8, 7, 1, 1, 0, 4, 8, 96, 0x00, 0xff, 0x60, 0x00, FS_ARABIC },
881 { "Small Fonts", FW_NORMAL, 8, 7, 1, 0, 0, 5, 10, 96, 0x20, 0xff, 0x80, 0x20, FS_JISJAPAN },
882 { "Small Fonts", FW_NORMAL, 10, 8, 2, 2, 0, 4, 8, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2, skip_rtl},
883 { "Small Fonts", FW_NORMAL, 10, 8, 2, 2, 0, 5, 8, 96, 0x20, 0xff, 0x80, 0x20, FS_CYRILLIC },
884 { "Small Fonts", FW_NORMAL, 10, 8, 2, 2, 0, 4, 9, 96, 0x00, 0xff, 0x60, 0x00, FS_ARABIC },
885 { "Small Fonts", FW_NORMAL, 10, 8, 2, 0, 0, 6, 12, 96, 0x20, 0xff, 0x80, 0x20, FS_JISJAPAN },
886 { "Small Fonts", FW_NORMAL, 11, 9, 2, 2, 0, 5, 9, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC, skip_rtl},
887 { "Small Fonts", FW_NORMAL, 11, 9, 2, 2, 0, 4, 10, 96, 0x00, 0xff, 0x60, 0x00, FS_ARABIC },
888 { "Small Fonts", FW_NORMAL, 11, 9, 2, 0, 0, 7, 14, 96, 0x20, 0xff, 0x80, 0x20, FS_JISJAPAN },
889
890 { "Small Fonts", FW_NORMAL, 3, 2, 1, 0, 0, 1, 2, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_JISJAPAN },
891 { "Small Fonts", FW_NORMAL, 3, 2, 1, 0, 0, 1, 8, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN2 | FS_CYRILLIC },
892 { "Small Fonts", FW_NORMAL, 6, 5, 1, 1, 0, 3, 5, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_JISJAPAN },
893 { "Small Fonts", FW_NORMAL, 6, 5, 1, 1, 0, 3, 8, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN2 | FS_CYRILLIC },
894 { "Small Fonts", FW_NORMAL, 8, 7, 1, 1, 0, 4, 7, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_JISJAPAN },
895 { "Small Fonts", FW_NORMAL, 8, 7, 1, 1, 0, 4, 8, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN2 | FS_CYRILLIC },
896 { "Small Fonts", FW_NORMAL, 10, 8, 2, 2, 0, 5, 9, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 | FS_JISJAPAN },
897 { "Small Fonts", FW_NORMAL, 10, 8, 2, 2, 0, 5, 8, 120, 0x20, 0xff, 0x80, 0x20, FS_CYRILLIC },
898 { "Small Fonts", FW_NORMAL, 12, 10, 2, 2, 0, 5, 10, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 | FS_JISJAPAN },
899 { "Small Fonts", FW_NORMAL, 12, 10, 2, 2, 0, 6, 10, 120, 0x20, 0xff, 0x80, 0x20, FS_CYRILLIC },
900 { "Small Fonts", FW_NORMAL, 13, 11, 2, 2, 0, 6, 12, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 | FS_JISJAPAN },
901 { "Small Fonts", FW_NORMAL, 13, 11, 2, 2, 0, 6, 11, 120, 0x20, 0xff, 0x80, 0x20, FS_CYRILLIC },
902
903 { "Fixedsys", FW_NORMAL, 15, 12, 3, 3, 0, 8, 8, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 },
904 { "Fixedsys", FW_NORMAL, 16, 12, 4, 3, 0, 8, 8, 96, 0x20, 0xff, 0x80, 0x20, FS_CYRILLIC },
905 { "FixedSys", FW_NORMAL, 18, 16, 2, 0, 0, 8, 16, 96, 0x20, 0xff, 0xa0, 0x20, FS_JISJAPAN },
906
907 { "Fixedsys", FW_NORMAL, 20, 16, 4, 2, 0, 10, 10, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC }
908
909 /* FIXME: add "Terminal" */
910 };
911 static const int font_log_pixels[] = { 96, 120 };
912 HDC hdc;
913 LOGFONTA lf;
914 HFONT hfont, old_hfont;
916 INT ret, i, expected_cs, screen_log_pixels, diff, font_res;
917 char face_name[LF_FACESIZE];
918 CHARSETINFO csi;
919
920 trace("system language id %04x\n", system_lang_id);
921
922 expected_cs = GetACP();
923 if (!TranslateCharsetInfo(ULongToPtr(expected_cs), &csi, TCI_SRCCODEPAGE))
924 {
925 skip("TranslateCharsetInfo failed for code page %d\n", expected_cs);
926 return;
927 }
928 expected_cs = csi.ciCharset;
929 trace("ACP %d -> charset %d\n", GetACP(), expected_cs);
930
932 ok(hdc != NULL, "failed to create hdc\n");
933
934 trace("logpixelsX %d, logpixelsY %d\n", GetDeviceCaps(hdc, LOGPIXELSX),
936
937 screen_log_pixels = GetDeviceCaps(hdc, LOGPIXELSY);
938 diff = 32768;
939 font_res = 0;
940 for (i = 0; i < sizeof(font_log_pixels)/sizeof(font_log_pixels[0]); i++)
941 {
942 int new_diff = abs(font_log_pixels[i] - screen_log_pixels);
943 if (new_diff < diff)
944 {
945 diff = new_diff;
946 font_res = font_log_pixels[i];
947 }
948 }
949 trace("best font resolution is %d\n", font_res);
950
951 for (i = 0; i < sizeof(fd)/sizeof(fd[0]); i++)
952 {
953 int bit, height;
954
955 memset(&lf, 0, sizeof(lf));
956
957 height = fd[i].height & ~FH_SCALE;
958 lf.lfHeight = height;
959 strcpy(lf.lfFaceName, fd[i].face_name);
960
961 for(bit = 0; bit < 32; bit++)
962 {
963 GLYPHMETRICS gm;
964 DWORD fs[2];
965 BOOL bRet;
966
967 fs[0] = 1L << bit;
968 fs[1] = 0;
969 if((fd[i].ansi_bitfield & fs[0]) == 0) continue;
970 if(!TranslateCharsetInfo( fs, &csi, TCI_SRCFONTSIG )) continue;
971
972 lf.lfCharSet = csi.ciCharset;
974 if (fd[i].height & FH_SCALE)
975 ok(ret, "scaled font height %d should not be enumerated\n", height);
976 else
977 {
978 if (font_res == fd[i].dpi && lf.lfCharSet == expected_cs)
979 {
980 todo_wine_if (ret) /* FIXME: Remove once Wine is fixed */
981 ok(!ret, "%s height %d charset %d dpi %d should be enumerated\n", lf.lfFaceName, lf.lfHeight, lf.lfCharSet, fd[i].dpi);
982 }
983 }
984 if (ret && !(fd[i].height & FH_SCALE))
985 continue;
986
987 hfont = create_font(lf.lfFaceName, &lf);
988 old_hfont = SelectObject(hdc, hfont);
989
990 SetLastError(0xdeadbeef);
991 ret = GetTextFaceA(hdc, sizeof(face_name), face_name);
992 ok(ret, "GetTextFace error %u\n", GetLastError());
993
994 if (strcmp(face_name, fd[i].face_name) != 0)
995 {
996 ok(ret != ANSI_CHARSET, "font charset should not be ANSI_CHARSET\n");
997 ok(ret != expected_cs, "font charset %d should not be %d\n", ret, expected_cs);
998 SelectObject(hdc, old_hfont);
1000 continue;
1001 }
1002
1003 memset(&gm, 0, sizeof(gm));
1004 SetLastError(0xdeadbeef);
1005 ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
1006 todo_wine {
1007 ok(ret == GDI_ERROR, "GetGlyphOutline should fail for a bitmap font\n");
1008 ok(GetLastError() == ERROR_CAN_NOT_COMPLETE, "expected ERROR_CAN_NOT_COMPLETE, got %u\n", GetLastError());
1009 }
1010
1011 bRet = GetTextMetricsA(hdc, &tm);
1012 ok(bRet, "GetTextMetrics error %d\n", GetLastError());
1013
1014 SetLastError(0xdeadbeef);
1016 if (is_CJK() && lf.lfCharSet == ANSI_CHARSET)
1017 ok(ret == ANSI_CHARSET, "got charset %d, expected ANSI_CHARSETd\n", ret);
1018 else
1019 ok(ret == expected_cs, "got charset %d, expected %d\n", ret, expected_cs);
1020
1021 trace("created %s, height %d charset %x dpi %d\n", face_name, tm.tmHeight, tm.tmCharSet, tm.tmDigitizedAspectX);
1022 trace("expected %s, height %d scaled_height %d, dpi %d\n", fd[i].face_name, height, fd[i].scaled_height, fd[i].dpi);
1023
1024 if(fd[i].dpi == tm.tmDigitizedAspectX)
1025 {
1026 int skipme = 0;
1027 trace("matched %s, height %d charset %x dpi %d\n", lf.lfFaceName, lf.lfHeight, lf.lfCharSet, fd[i].dpi);
1028 if (fd[i].skip_lang_id)
1029 {
1030 int si = 0;
1031 skipme = 0;
1032 while(!skipme && fd[i].skip_lang_id[si])
1033 if (fd[i].skip_lang_id[si++] == system_lang_id)
1034 skipme = 1;
1035 }
1036 if (!skipme)
1037 {
1038 ok(tm.tmWeight == fd[i].weight, "%s(%d): tm.tmWeight %d != %d\n", fd[i].face_name, height, tm.tmWeight, fd[i].weight);
1039 if (fd[i].height & FH_SCALE)
1040 ok(tm.tmHeight == fd[i].scaled_height, "%s(%d): tm.tmHeight %d != %d\n", fd[i].face_name, height, tm.tmHeight, fd[i].scaled_height);
1041 else
1042 ok(tm.tmHeight == fd[i].height, "%s(%d): tm.tmHeight %d != %d\n", fd[i].face_name, fd[i].height, tm.tmHeight, fd[i].height);
1043 ok(tm.tmAscent == fd[i].ascent, "%s(%d): tm.tmAscent %d != %d\n", fd[i].face_name, height, tm.tmAscent, fd[i].ascent);
1044 ok(tm.tmDescent == fd[i].descent, "%s(%d): tm.tmDescent %d != %d\n", fd[i].face_name, height, tm.tmDescent, fd[i].descent);
1045 ok(tm.tmInternalLeading == fd[i].int_leading, "%s(%d): tm.tmInternalLeading %d != %d\n", fd[i].face_name, height, tm.tmInternalLeading, fd[i].int_leading);
1046 ok(tm.tmExternalLeading == fd[i].ext_leading, "%s(%d): tm.tmExternalLeading %d != %d\n", fd[i].face_name, height, tm.tmExternalLeading, fd[i].ext_leading);
1047 ok(tm.tmAveCharWidth == fd[i].ave_char_width, "%s(%d): tm.tmAveCharWidth %d != %d\n", fd[i].face_name, height, tm.tmAveCharWidth, fd[i].ave_char_width);
1048 ok(tm.tmFirstChar == fd[i].first_char, "%s(%d): tm.tmFirstChar = %02x\n", fd[i].face_name, height, tm.tmFirstChar);
1049 ok(tm.tmLastChar == fd[i].last_char, "%s(%d): tm.tmLastChar = %02x\n", fd[i].face_name, height, tm.tmLastChar);
1050 /* Substitutions like MS Sans Serif,0=MS Sans Serif,204
1051 make default char test fail */
1052 if (tm.tmCharSet == lf.lfCharSet)
1053 ok(tm.tmDefaultChar == fd[i].def_char, "%s(%d): tm.tmDefaultChar = %02x\n", fd[i].face_name, height, tm.tmDefaultChar);
1054 ok(tm.tmBreakChar == fd[i].break_char, "%s(%d): tm.tmBreakChar = %02x\n", fd[i].face_name, height, tm.tmBreakChar);
1055 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);
1056
1057 /* Don't run the max char width test on System/ANSI_CHARSET. We have extra characters in our font
1058 that make the max width bigger */
1059 if ((strcmp(lf.lfFaceName, "System") || lf.lfCharSet != ANSI_CHARSET) && tm.tmDigitizedAspectX == 96)
1060 ok(tm.tmMaxCharWidth == fd[i].max_char_width, "%s(%d): tm.tmMaxCharWidth %d != %d\n", fd[i].face_name, height, tm.tmMaxCharWidth, fd[i].max_char_width);
1061 }
1062 else
1063 skip("Skipping font metrics test for system langid 0x%x\n",
1065 }
1066 SelectObject(hdc, old_hfont);
1068 }
1069 }
1070
1071 DeleteDC(hdc);
1072}
1073
1075{
1076 HDC hdc;
1078 LONG ret;
1079 SIZE size;
1080 LONG avgwidth, height;
1081 static const char szAlphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
1082
1083 if (!pGdiGetCharDimensions)
1084 {
1085 win_skip("GdiGetCharDimensions not available on this platform\n");
1086 return;
1087 }
1088
1090
1091 GetTextExtentPointA(hdc, szAlphabet, strlen(szAlphabet), &size);
1092 avgwidth = ((size.cx / 26) + 1) / 2;
1093
1094 ret = pGdiGetCharDimensions(hdc, &tm, &height);
1095 ok(ret == avgwidth, "GdiGetCharDimensions should have returned width of %d instead of %d\n", avgwidth, ret);
1096 ok(height == tm.tmHeight, "GdiGetCharDimensions should have set height to %d instead of %d\n", tm.tmHeight, height);
1097
1098 ret = pGdiGetCharDimensions(hdc, &tm, NULL);
1099 ok(ret == avgwidth, "GdiGetCharDimensions should have returned width of %d instead of %d\n", avgwidth, ret);
1100
1101 ret = pGdiGetCharDimensions(hdc, NULL, NULL);
1102 ok(ret == avgwidth, "GdiGetCharDimensions should have returned width of %d instead of %d\n", avgwidth, ret);
1103
1104 height = 0;
1105 ret = pGdiGetCharDimensions(hdc, NULL, &height);
1106 ok(ret == avgwidth, "GdiGetCharDimensions should have returned width of %d instead of %d\n", avgwidth, ret);
1107 ok(height == size.cy, "GdiGetCharDimensions should have set height to %d instead of %d\n", size.cy, height);
1108
1109 DeleteDC(hdc);
1110}
1111
1112static int CALLBACK create_font_proc(const LOGFONTA *lpelfe,
1113 const TEXTMETRICA *lpntme,
1114 DWORD FontType, LPARAM lParam)
1115{
1116 if (FontType & TRUETYPE_FONTTYPE)
1117 {
1118 HFONT hfont;
1119
1120 hfont = CreateFontIndirectA(lpelfe);
1121 if (hfont)
1122 {
1123 *(HFONT *)lParam = hfont;
1124 return 0;
1125 }
1126 }
1127
1128 return 1;
1129}
1130
1131static void ABCWidths_helper(const char* description, HDC hdc, WORD *glyphs, const ABC *base_abci, const ABC *base_abcw, const ABCFLOAT *base_abcf)
1132{
1133 ABC abc[1];
1134 ABCFLOAT abcf[1];
1135 BOOL ret = FALSE;
1136
1137 ret = pGetCharABCWidthsI(hdc, 0, 1, glyphs, abc);
1138 ok(ret, "%s: GetCharABCWidthsI should have succeeded\n", description);
1139 ok ((INT)abc->abcB > 0, "%s: abcB should be positive\n", description);
1140 ok(abc->abcA * base_abci->abcA >= 0, "%s: abcA's sign should be unchanged\n", description);
1141 ok(abc->abcC * base_abci->abcC >= 0, "%s: abcC's sign should be unchanged\n", description);
1142
1143 ret = pGetCharABCWidthsW(hdc, 'i', 'i', abc);
1144 ok(ret, "%s: GetCharABCWidthsW should have succeeded\n", description);
1145 ok ((INT)abc->abcB > 0, "%s: abcB should be positive\n", description);
1146 ok(abc->abcA * base_abcw->abcA >= 0, "%s: abcA's sign should be unchanged\n", description);
1147 ok(abc->abcC * base_abcw->abcC >= 0, "%s: abcC's sign should be unchanged\n", description);
1148
1149 ret = pGetCharABCWidthsFloatW(hdc, 'i', 'i', abcf);
1150 ok(ret, "%s: GetCharABCWidthsFloatW should have succeeded\n", description);
1151 ok (abcf->abcfB > 0.0, "%s: abcfB should be positive\n", description);
1152 ok(abcf->abcfA * base_abcf->abcfA >= 0.0, "%s: abcfA's sign should be unchanged\n", description);
1153 ok(abcf->abcfC * base_abcf->abcfC >= 0.0, "%s: abcfC's sign should be unchanged\n", description);
1154}
1155
1156static void test_GetCharABCWidths(void)
1157{
1158 static const WCHAR str[] = {'i',0};
1159 BOOL ret;
1160 HDC hdc;
1161 LOGFONTA lf;
1162 HFONT hfont;
1163 ABC abc[1];
1164 ABC abcw[1];
1165 ABCFLOAT abcf[1];
1166 WORD glyphs[1];
1167 DWORD nb;
1168 HWND hwnd;
1169 static const struct
1170 {
1171 UINT first;
1172 UINT last;
1173 } range[] =
1174 {
1175 {0xff, 0xff},
1176 {0x100, 0x100},
1177 {0xff, 0x100},
1178 {0x1ff, 0xff00},
1179 {0xffff, 0xffff},
1180 {0x10000, 0x10000},
1181 {0xffff, 0x10000},
1182 {0xffffff, 0xffffff},
1183 {0x1000000, 0x1000000},
1184 {0xffffff, 0x1000000},
1185 {0xffffffff, 0xffffffff},
1186 {0x00, 0xff}
1187 };
1188 static const struct
1189 {
1190 UINT cs;
1191 UINT a;
1192 UINT w;
1193 BOOL r[sizeof range / sizeof range[0]];
1194 } c[] =
1195 {
1196 {ANSI_CHARSET, 0x30, 0x30,
1198 {SHIFTJIS_CHARSET, 0x82a0, 0x3042,
1200 {HANGEUL_CHARSET, 0x8141, 0xac02,
1202 {GB2312_CHARSET, 0x8141, 0x4e04,
1204 {CHINESEBIG5_CHARSET, 0xa142, 0x3001,
1206 };
1207 UINT i;
1208
1209 if (!pGetCharABCWidthsA || !pGetCharABCWidthsW || !pGetCharABCWidthsFloatW || !pGetCharABCWidthsI)
1210 {
1211 win_skip("GetCharABCWidthsA/W/I not available on this platform\n");
1212 return;
1213 }
1214
1215 memset(&lf, 0, sizeof(lf));
1216 strcpy(lf.lfFaceName, "System");
1217 lf.lfHeight = 20;
1218
1220 hdc = GetDC(0);
1222
1223 nb = pGetGlyphIndicesW(hdc, str, 1, glyphs, 0);
1224 ok(nb == 1, "GetGlyphIndicesW should have returned 1\n");
1225
1226 ret = pGetCharABCWidthsI(NULL, 0, 1, glyphs, abc);
1227 ok(!ret, "GetCharABCWidthsI should have failed\n");
1228
1229 ret = pGetCharABCWidthsI(hdc, 0, 1, glyphs, NULL);
1230 ok(!ret, "GetCharABCWidthsI should have failed\n");
1231
1232 ret = pGetCharABCWidthsI(hdc, 0, 1, glyphs, abc);
1233 ok(ret, "GetCharABCWidthsI should have succeeded\n");
1234
1235 ret = pGetCharABCWidthsW(NULL, 'a', 'a', abc);
1236 ok(!ret, "GetCharABCWidthsW should have failed\n");
1237
1238 ret = pGetCharABCWidthsW(hdc, 'a', 'a', NULL);
1239 ok(!ret, "GetCharABCWidthsW should have failed\n");
1240
1241 ret = pGetCharABCWidthsW(hdc, 'a', 'a', abc);
1242 ok(!ret, "GetCharABCWidthsW should have failed\n");
1243
1244 ret = pGetCharABCWidthsFloatW(NULL, 'a', 'a', abcf);
1245 ok(!ret, "GetCharABCWidthsFloatW should have failed\n");
1246
1247 ret = pGetCharABCWidthsFloatW(hdc, 'a', 'a', NULL);
1248 ok(!ret, "GetCharABCWidthsFloatW should have failed\n");
1249
1250 ret = pGetCharABCWidthsFloatW(hdc, 'a', 'a', abcf);
1251 ok(ret, "GetCharABCWidthsFloatW should have succeeded\n");
1252
1255
1256 for (i = 0; i < sizeof c / sizeof c[0]; ++i)
1257 {
1258 ABC a[2], w[2];
1259 ABC full[256];
1260 UINT code = 0x41, j;
1261
1262 lf.lfFaceName[0] = '\0';
1263 lf.lfCharSet = c[i].cs;
1264 lf.lfPitchAndFamily = 0;
1266 {
1267 skip("TrueType font for charset %u is not installed\n", c[i].cs);
1268 continue;
1269 }
1270
1271 memset(a, 0, sizeof a);
1272 memset(w, 0, sizeof w);
1274 ok(pGetCharABCWidthsA(hdc, c[i].a, c[i].a + 1, a) &&
1275 pGetCharABCWidthsW(hdc, c[i].w, c[i].w + 1, w) &&
1276 memcmp(a, w, sizeof a) == 0,
1277 "GetCharABCWidthsA and GetCharABCWidthsW should return same widths. charset = %u\n", c[i].cs);
1278
1279 memset(a, 0xbb, sizeof a);
1280 ret = pGetCharABCWidthsA(hdc, code, code, a);
1281 ok(ret, "GetCharABCWidthsA should have succeeded\n");
1282 memset(full, 0xcc, sizeof full);
1283 ret = pGetCharABCWidthsA(hdc, 0x00, code, full);
1284 ok(ret, "GetCharABCWidthsA should have succeeded\n");
1285 ok(memcmp(&a[0], &full[code], sizeof(ABC)) == 0,
1286 "GetCharABCWidthsA info should match. codepage = %u\n", c[i].cs);
1287
1288 for (j = 0; j < sizeof range / sizeof range[0]; ++j)
1289 {
1290 memset(full, 0xdd, sizeof full);
1291 ret = pGetCharABCWidthsA(hdc, range[j].first, range[j].last, full);
1292 ok(ret == c[i].r[j], "GetCharABCWidthsA %x - %x should have %s\n",
1293 range[j].first, range[j].last, c[i].r[j] ? "succeeded" : "failed");
1294 if (ret)
1295 {
1296 UINT last = range[j].last - range[j].first;
1297 ret = pGetCharABCWidthsA(hdc, range[j].last, range[j].last, a);
1298 ok(ret && memcmp(&full[last], &a[0], sizeof(ABC)) == 0,
1299 "GetCharABCWidthsA %x should match. codepage = %u\n",
1300 range[j].last, c[i].cs);
1301 }
1302 }
1303
1306 }
1307
1308 memset(&lf, 0, sizeof(lf));
1309 strcpy(lf.lfFaceName, "Tahoma");
1310 lf.lfHeight = 200;
1312
1313 /* test empty glyph's metrics */
1315 ret = pGetCharABCWidthsFloatW(hdc, ' ', ' ', abcf);
1316 ok(ret, "GetCharABCWidthsFloatW should have succeeded\n");
1317 ok(abcf[0].abcfB == 1.0, "got %f\n", abcf[0].abcfB);
1318 ret = pGetCharABCWidthsW(hdc, ' ', ' ', abcw);
1319 ok(ret, "GetCharABCWidthsW should have succeeded\n");
1320 ok(abcw[0].abcB == 1, "got %u\n", abcw[0].abcB);
1321
1322 /* 1) prepare unrotated font metrics */
1323 ret = pGetCharABCWidthsW(hdc, 'a', 'a', abcw);
1324 ok(ret, "GetCharABCWidthsW should have succeeded\n");
1326
1327 /* 2) get rotated font metrics */
1328 lf.lfEscapement = lf.lfOrientation = 900;
1331 ret = pGetCharABCWidthsW(hdc, 'a', 'a', abc);
1332 ok(ret, "GetCharABCWidthsW should have succeeded\n");
1333
1334 /* 3) compare ABC results */
1335 ok(match_off_by_1(abcw[0].abcA, abc[0].abcA, FALSE),
1336 "got %d, expected %d (A)\n", abc[0].abcA, abcw[0].abcA);
1337 ok(match_off_by_1(abcw[0].abcB, abc[0].abcB, FALSE),
1338 "got %d, expected %d (B)\n", abc[0].abcB, abcw[0].abcB);
1339 ok(match_off_by_1(abcw[0].abcC, abc[0].abcC, FALSE),
1340 "got %d, expected %d (C)\n", abc[0].abcC, abcw[0].abcC);
1341
1343
1344 /* test abcA == gmptGlyphOrigin.x && abcB == gmBlackBoxX
1345 in various widths. */
1346 for (i = 1; i <= 2; i++)
1347 {
1348 UINT j;
1349 UINT code;
1350
1351 memset(&lf, 0, sizeof(lf));
1352 lf.lfHeight = 20;
1353 switch(i)
1354 {
1355 case 1:
1356 strcpy(lf.lfFaceName, "Tahoma");
1357 code = 'a';
1358 break;
1359 case 2:
1360 strcpy(lf.lfFaceName, "Times New Roman");
1361 lf.lfItalic = TRUE;
1362 code = 'f';
1363 break;
1364 }
1366 {
1367 skip("%s is not installed\n", lf.lfFaceName);
1368 continue;
1369 }
1370 for (j = 1; j <= 80; j++)
1371 {
1372 GLYPHMETRICS gm;
1373
1374 lf.lfWidth = j;
1377
1378 nb = GetGlyphOutlineA(hdc, code, GGO_METRICS, &gm, 0, NULL, &mat);
1379 ok(nb, "GetGlyphOutlineA should have succeeded at width %d\n", i);
1380
1382 ok(ret, "GetCharABCWidthsA should have succeeded at width %d\n", i);
1383
1384 ok(abc[0].abcA == gm.gmptGlyphOrigin.x,
1385 "abcA(%d) and gmptGlyphOrigin.x(%d) values are different at width %d\n",
1386 abc[0].abcA, gm.gmptGlyphOrigin.x, i);
1387 ok(abc[0].abcB == gm.gmBlackBoxX,
1388 "abcB(%d) and gmBlackBoxX(%d) values are different at width %d\n",
1389 abc[0].abcB, gm.gmBlackBoxX, i);
1391 }
1392 }
1393 ReleaseDC(NULL, hdc);
1394
1395 trace("ABC sign test for a variety of transforms:\n");
1396 memset(&lf, 0, sizeof(lf));
1397 strcpy(lf.lfFaceName, "Tahoma");
1398 lf.lfHeight = 20;
1400 hwnd = CreateWindowExA(0, "static", "", WS_POPUP, 0,0,100,100,
1401 0, 0, 0, NULL);
1402 hdc = GetDC(hwnd);
1405
1406 nb = pGetGlyphIndicesW(hdc, str, 1, glyphs, 0);
1407 ok(nb == 1, "GetGlyphIndicesW should have returned 1\n");
1408
1409 ret = pGetCharABCWidthsI(hdc, 0, 1, glyphs, abc);
1410 ok(ret, "GetCharABCWidthsI should have succeeded\n");
1411 ret = pGetCharABCWidthsW(hdc, 'i', 'i', abcw);
1412 ok(ret, "GetCharABCWidthsW should have succeeded\n");
1413 ret = pGetCharABCWidthsFloatW(hdc, 'i', 'i', abcf);
1414 ok(ret, "GetCharABCWidthsFloatW should have succeeded\n");
1415
1416 ABCWidths_helper("LTR", hdc, glyphs, abc, abcw, abcf);
1417 SetWindowExtEx(hdc, -1, -1, NULL);
1419 ABCWidths_helper("LTR -1 compatible", hdc, glyphs, abc, abcw, abcf);
1421 ABCWidths_helper("LTR -1 advanced", hdc, glyphs, abc, abcw, abcf);
1422 SetWindowExtEx(hdc, 1, 1, NULL);
1424 ABCWidths_helper("LTR 1 compatible", hdc, glyphs, abc, abcw, abcf);
1426 ABCWidths_helper("LTR 1 advanced", hdc, glyphs, abc, abcw, abcf);
1427
1428 ReleaseDC(hwnd, hdc);
1430
1431 trace("RTL layout\n");
1432 hwnd = CreateWindowExA(WS_EX_LAYOUTRTL, "static", "", WS_POPUP, 0,0,100,100,
1433 0, 0, 0, NULL);
1434 hdc = GetDC(hwnd);
1437
1438 ABCWidths_helper("RTL", hdc, glyphs, abc, abcw, abcf);
1439 SetWindowExtEx(hdc, -1, -1, NULL);
1441 ABCWidths_helper("RTL -1 compatible", hdc, glyphs, abc, abcw, abcf);
1443 ABCWidths_helper("RTL -1 advanced", hdc, glyphs, abc, abcw, abcf);
1444 SetWindowExtEx(hdc, 1, 1, NULL);
1446 ABCWidths_helper("RTL 1 compatible", hdc, glyphs, abc, abcw, abcf);
1448 ABCWidths_helper("RTL 1 advanced", hdc, glyphs, abc, abcw, abcf);
1449
1450 ReleaseDC(hwnd, hdc);
1453}
1454
1455static void test_text_extents(void)
1456{
1457 static const WCHAR wt[] = {'O','n','e','\n','t','w','o',' ','3',0};
1458 static const WCHAR emptyW[] = {0};
1459 LPINT extents;
1460 INT i, len, fit1, fit2, extents2[3];
1461 LOGFONTA lf;
1463 HDC hdc;
1464 HFONT hfont;
1465 SIZE sz;
1466 SIZE sz1, sz2;
1467 BOOL ret;
1468
1469 memset(&lf, 0, sizeof(lf));
1470 strcpy(lf.lfFaceName, "Arial");
1471 lf.lfHeight = 20;
1472
1474 hdc = GetDC(0);
1477 ret = GetTextExtentPointA(hdc, "o", 1, &sz);
1478 ok(ret, "got %d\n", ret);
1479 ok(sz.cy == tm.tmHeight, "cy %d tmHeight %d\n", sz.cy, tm.tmHeight);
1480
1481 memset(&sz, 0xcc, sizeof(sz));
1482 ret = GetTextExtentPointA(hdc, "o", 0, &sz);
1483 ok(ret, "got %d\n", ret);
1484 ok(sz.cx == 0 && sz.cy == 0, "cx %d, cy %d\n", sz.cx, sz.cy);
1485
1486 memset(&sz, 0xcc, sizeof(sz));
1487 ret = GetTextExtentPointA(hdc, "", 0, &sz);
1488 ok(ret, "got %d\n", ret);
1489 ok(sz.cx == 0 && sz.cy == 0, "cx %d, cy %d\n", sz.cx, sz.cy);
1490
1491 SetLastError(0xdeadbeef);
1492 GetTextExtentExPointW(hdc, wt, 1, 1, &fit1, &fit2, &sz1);
1494 {
1495 win_skip("Skipping remainder of text extents test on a Win9x platform\n");
1498 ReleaseDC(0, hdc);
1499 return;
1500 }
1501
1502 memset(&sz, 0xcc, sizeof(sz));
1503 ret = GetTextExtentPointW(hdc, wt, 0, &sz);
1504 ok(ret, "got %d\n", ret);
1505 ok(sz.cx == 0 && sz.cy == 0, "cx %d, cy %d\n", sz.cx, sz.cy);
1506
1507 memset(&sz, 0xcc, sizeof(sz));
1508 ret = GetTextExtentPointW(hdc, emptyW, 0, &sz);
1509 ok(ret, "got %d\n", ret);
1510 ok(sz.cx == 0 && sz.cy == 0, "cx %d, cy %d\n", sz.cx, sz.cy);
1511
1512 len = lstrlenW(wt);
1513 extents = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len * sizeof extents[0]);
1514 extents[0] = 1; /* So that the increasing sequence test will fail
1515 if the extents array is untouched. */
1516 GetTextExtentExPointW(hdc, wt, len, 32767, &fit1, extents, &sz1);
1517 GetTextExtentPointW(hdc, wt, len, &sz2);
1518 ok(sz1.cy == sz2.cy,
1519 "cy from GetTextExtentExPointW (%d) and GetTextExtentPointW (%d) differ\n", sz1.cy, sz2.cy);
1520 /* Because of the '\n' in the string GetTextExtentExPoint and
1521 GetTextExtentPoint return different widths under Win2k, but
1522 under WinXP they return the same width. So we don't test that
1523 here. */
1524
1525 for (i = 1; i < len; ++i)
1526 ok(extents[i-1] <= extents[i],
1527 "GetTextExtentExPointW generated a non-increasing sequence of partial extents (at position %d)\n",
1528 i);
1529 ok(extents[len-1] == sz1.cx, "GetTextExtentExPointW extents and size don't match\n");
1530 ok(0 <= fit1 && fit1 <= len, "GetTextExtentExPointW generated illegal value %d for fit\n", fit1);
1531 ok(0 < fit1, "GetTextExtentExPointW says we can't even fit one letter in 32767 logical units\n");
1532 GetTextExtentExPointW(hdc, wt, len, extents[2], &fit2, NULL, &sz2);
1533 ok(sz1.cx == sz2.cx && sz1.cy == sz2.cy, "GetTextExtentExPointW returned different sizes for the same string\n");
1534 ok(fit2 == 3, "GetTextExtentExPointW extents isn't consistent with fit\n");
1535 GetTextExtentExPointW(hdc, wt, len, extents[2]-1, &fit2, NULL, &sz2);
1536 ok(fit2 == 2, "GetTextExtentExPointW extents isn't consistent with fit\n");
1537 GetTextExtentExPointW(hdc, wt, 2, 0, NULL, extents + 2, &sz2);
1538 ok(extents[0] == extents[2] && extents[1] == extents[3],
1539 "GetTextExtentExPointW with lpnFit == NULL returns incorrect results\n");
1540 GetTextExtentExPointW(hdc, wt, 2, 0, NULL, NULL, &sz1);
1541 ok(sz1.cx == sz2.cx && sz1.cy == sz2.cy,
1542 "GetTextExtentExPointW with lpnFit and alpDx both NULL returns incorrect results\n");
1543
1544 /* extents functions fail with -ve counts (the interesting case being -1) */
1545 ret = GetTextExtentPointA(hdc, "o", -1, &sz);
1546 ok(ret == FALSE, "got %d\n", ret);
1547 ret = GetTextExtentExPointA(hdc, "o", -1, 0, NULL, NULL, &sz);
1548 ok(ret == FALSE, "got %d\n", ret);
1549 ret = GetTextExtentExPointW(hdc, wt, -1, 0, NULL, NULL, &sz1);
1550 ok(ret == FALSE, "got %d\n", ret);
1551
1552 /* max_extent = 0 succeeds and returns zero */
1553 fit1 = fit2 = -215;
1554 ret = GetTextExtentExPointA(hdc, NULL, 0, 0, &fit1, NULL, &sz);
1555 ok(ret == TRUE ||
1556 broken(ret == FALSE), /* NT4, 2k */
1557 "got %d\n", ret);
1558 ok(fit1 == 0 ||
1559 broken(fit1 == -215), /* NT4, 2k */
1560 "fit = %d\n", fit1);
1561 ret = GetTextExtentExPointW(hdc, NULL, 0, 0, &fit2, NULL, &sz1);
1562 ok(ret == TRUE, "got %d\n", ret);
1563 ok(fit2 == 0, "fit = %d\n", fit2);
1564
1565 /* max_extent = -1 is interpreted as a very large width that will
1566 * definitely fit our three characters */
1567 fit1 = fit2 = -215;
1568 ret = GetTextExtentExPointA(hdc, "One", 3, -1, &fit1, NULL, &sz);
1569 ok(ret == TRUE, "got %d\n", ret);
1570 ok(fit1 == 3, "fit = %d\n", fit1);
1571 ret = GetTextExtentExPointW(hdc, wt, 3, -1, &fit2, NULL, &sz);
1572 ok(ret == TRUE, "got %d\n", ret);
1573 ok(fit2 == 3, "fit = %d\n", fit2);
1574
1575 /* max_extent = -2 is interpreted similarly, but the Ansi version
1576 * rejects it while the Unicode one accepts it */
1577 fit1 = fit2 = -215;
1578 ret = GetTextExtentExPointA(hdc, "One", 3, -2, &fit1, NULL, &sz);
1579 ok(ret == FALSE, "got %d\n", ret);
1580 ok(fit1 == -215, "fit = %d\n", fit1);
1581 ret = GetTextExtentExPointW(hdc, wt, 3, -2, &fit2, NULL, &sz);
1582 ok(ret == TRUE, "got %d\n", ret);
1583 ok(fit2 == 3, "fit = %d\n", fit2);
1584
1587
1588 /* non-MM_TEXT mapping mode */
1589 lf.lfHeight = 2000;
1592
1594 ret = GetTextExtentExPointW(hdc, wt, 3, 0, NULL, extents, &sz);
1595 ok(ret, "got %d\n", ret);
1596 ok(sz.cx == extents[2], "got %d vs %d\n", sz.cx, extents[2]);
1597
1598 ret = GetTextExtentExPointW(hdc, wt, 3, extents[1], &fit1, extents2, &sz2);
1599 ok(ret, "got %d\n", ret);
1600 ok(fit1 == 2, "got %d\n", fit1);
1601 ok(sz2.cx == sz.cx, "got %d vs %d\n", sz2.cx, sz.cx);
1602 for(i = 0; i < 2; i++)
1603 ok(extents2[i] == extents[i], "%d: %d, %d\n", i, extents2[i], extents[i]);
1604
1607 HeapFree(GetProcessHeap(), 0, extents);
1608 ReleaseDC(NULL, hdc);
1609}
1610
1611static void test_GetGlyphIndices(void)
1612{
1613 HDC hdc;
1614 HFONT hfont;
1615 DWORD charcount;
1616 LOGFONTA lf;
1617 DWORD flags = 0;
1618 WCHAR testtext[] = {'T','e','s','t',0xffff,0};
1619 WORD glyphs[(sizeof(testtext)/2)-1];
1620 TEXTMETRICA textm;
1621 HFONT hOldFont;
1622
1623 if (!pGetGlyphIndicesW) {
1624 win_skip("GetGlyphIndicesW not available on platform\n");
1625 return;
1626 }
1627
1628 hdc = GetDC(0);
1629
1630 memset(&lf, 0, sizeof(lf));
1631 strcpy(lf.lfFaceName, "System");
1632 lf.lfHeight = 16;
1634
1636 ok(hfont != 0, "CreateFontIndirectEx failed\n");
1637 ok(GetTextMetricsA(hdc, &textm), "GetTextMetric failed\n");
1638 if (textm.tmCharSet == ANSI_CHARSET)
1639 {
1641 charcount = pGetGlyphIndicesW(hdc, testtext, (sizeof(testtext)/2)-1, glyphs, flags);
1642 ok(charcount == 5, "GetGlyphIndicesW count of glyphs should = 5 not %d\n", charcount);
1643 ok((glyphs[4] == 0x001f || glyphs[4] == 0xffff /* Vista */), "GetGlyphIndicesW should have returned a nonexistent char not %04x\n", glyphs[4]);
1644 flags = 0;
1645 charcount = pGetGlyphIndicesW(hdc, testtext, (sizeof(testtext)/2)-1, glyphs, flags);
1646 ok(charcount == 5, "GetGlyphIndicesW count of glyphs should = 5 not %d\n", charcount);
1647 ok(glyphs[4] == textm.tmDefaultChar, "GetGlyphIndicesW should have returned a %04x not %04x\n",
1648 textm.tmDefaultChar, glyphs[4]);
1649 }
1650 else
1651 /* FIXME: Write tests for non-ANSI charsets. */
1652 skip("GetGlyphIndices System font tests only for ANSI_CHARSET\n");
1653
1654 if(!is_font_installed("Tahoma"))
1655 {
1656 skip("Tahoma is not installed so skipping this test\n");
1657 return;
1658 }
1659 memset(&lf, 0, sizeof(lf));
1660 strcpy(lf.lfFaceName, "Tahoma");
1661 lf.lfHeight = 20;
1662
1664 hOldFont = SelectObject(hdc, hfont);
1665 ok(GetTextMetricsA(hdc, &textm), "GetTextMetric failed\n");
1667 charcount = pGetGlyphIndicesW(hdc, testtext, (sizeof(testtext)/2)-1, glyphs, flags);
1668 ok(charcount == 5, "GetGlyphIndicesW count of glyphs should = 5 not %d\n", charcount);
1669 ok(glyphs[4] == 0xffff, "GetGlyphIndicesW should have returned 0xffff char not %04x\n", glyphs[4]);
1670 flags = 0;
1671 testtext[0] = textm.tmDefaultChar;
1672 charcount = pGetGlyphIndicesW(hdc, testtext, (sizeof(testtext)/2)-1, glyphs, flags);
1673 ok(charcount == 5, "GetGlyphIndicesW count of glyphs should = 5 not %d\n", charcount);
1674 ok(glyphs[0] == 0, "GetGlyphIndicesW for tmDefaultChar should be 0 not %04x\n", glyphs[0]);
1675 ok(glyphs[4] == 0, "GetGlyphIndicesW should have returned 0 not %04x\n", glyphs[4]);
1676 DeleteObject(SelectObject(hdc, hOldFont));
1677}
1678
1679static void test_GetKerningPairs(void)
1680{
1681 static const struct kerning_data
1682 {
1683 const char face_name[LF_FACESIZE];
1684 LONG height;
1685 /* some interesting fields from OUTLINETEXTMETRIC */
1686 LONG tmHeight, tmAscent, tmDescent;
1687 UINT otmEMSquare;
1688 INT otmAscent;
1689 INT otmDescent;
1690 UINT otmLineGap;
1691 UINT otmsCapEmHeight;
1692 UINT otmsXHeight;
1693 INT otmMacAscent;
1694 INT otmMacDescent;
1695 UINT otmMacLineGap;
1696 UINT otmusMinimumPPEM;
1697 /* small subset of kerning pairs to test */
1698 DWORD total_kern_pairs;
1699 const KERNINGPAIR kern_pair[26];
1700 } kd[] =
1701 {
1702 {"Arial", 12, 12, 9, 3,
1703 2048, 7, -2, 1, 5, 2, 8, -2, 0, 9,
1704 26,
1705 {
1706 {' ','A',-1},{' ','T',0},{' ','Y',0},{'1','1',-1},
1707 {'A',' ',-1},{'A','T',-1},{'A','V',-1},{'A','W',0},
1708 {'A','Y',-1},{'A','v',0},{'A','w',0},{'A','y',0},
1709 {'F',',',-1},{'F','.',-1},{'F','A',-1},{'L',' ',0},
1710 {'L','T',-1},{'L','V',-1},{'L','W',-1},{'L','Y',-1},
1711 {915,912,+1},{915,913,-1},{910,912,+1},{910,913,-1},
1712 {933,970,+1},{933,972,-1}
1713 }
1714 },
1715 {"Arial", -34, 39, 32, 7,
1716 2048, 25, -7, 5, 17, 9, 31, -7, 1, 9,
1717 26,
1718 {
1719 {' ','A',-2},{' ','T',-1},{' ','Y',-1},{'1','1',-3},
1720 {'A',' ',-2},{'A','T',-3},{'A','V',-3},{'A','W',-1},
1721 {'A','Y',-3},{'A','v',-1},{'A','w',-1},{'A','y',-1},
1722 {'F',',',-4},{'F','.',-4},{'F','A',-2},{'L',' ',-1},
1723 {'L','T',-3},{'L','V',-3},{'L','W',-3},{'L','Y',-3},
1724 {915,912,+3},{915,913,-3},{910,912,+3},{910,913,-3},
1725 {933,970,+2},{933,972,-3}
1726 }
1727 },
1728 { "Arial", 120, 120, 97, 23,
1729 2048, 79, -23, 16, 54, 27, 98, -23, 4, 9,
1730 26,
1731 {
1732 {' ','A',-6},{' ','T',-2},{' ','Y',-2},{'1','1',-8},
1733 {'A',' ',-6},{'A','T',-8},{'A','V',-8},{'A','W',-4},
1734 {'A','Y',-8},{'A','v',-2},{'A','w',-2},{'A','y',-2},
1735 {'F',',',-12},{'F','.',-12},{'F','A',-6},{'L',' ',-4},
1736 {'L','T',-8},{'L','V',-8},{'L','W',-8},{'L','Y',-8},
1737 {915,912,+9},{915,913,-10},{910,912,+9},{910,913,-8},
1738 {933,970,+6},{933,972,-10}
1739 }
1740 },
1741#if 0 /* this set fails due to +1/-1 errors (rounding bug?), needs investigation. */
1742 { "Arial", 1024 /* usually 1/2 of EM Square */, 1024, 830, 194,
1743 2048, 668, -193, 137, 459, 229, 830, -194, 30, 9,
1744 26,
1745 {
1746 {' ','A',-51},{' ','T',-17},{' ','Y',-17},{'1','1',-68},
1747 {'A',' ',-51},{'A','T',-68},{'A','V',-68},{'A','W',-34},
1748 {'A','Y',-68},{'A','v',-17},{'A','w',-17},{'A','y',-17},
1749 {'F',',',-102},{'F','.',-102},{'F','A',-51},{'L',' ',-34},
1750 {'L','T',-68},{'L','V',-68},{'L','W',-68},{'L','Y',-68},
1751 {915,912,+73},{915,913,-84},{910,912,+76},{910,913,-68},
1752 {933,970,+54},{933,972,-83}
1753 }
1754 }
1755#endif
1756 };
1757 LOGFONTA lf;
1758 HFONT hfont, hfont_old;
1759 KERNINGPAIR *kern_pair;
1760 HDC hdc;
1761 DWORD total_kern_pairs, ret, i, n, matches;
1762
1763 hdc = GetDC(0);
1764
1765 /* GetKerningPairsA maps unicode set of kerning pairs to current code page
1766 * which may render this test unusable, so we're trying to avoid that.
1767 */
1768 SetLastError(0xdeadbeef);
1771 {
1772 win_skip("Skipping the GetKerningPairs test on a Win9x platform\n");
1773 ReleaseDC(0, hdc);
1774 return;
1775 }
1776
1777 for (i = 0; i < sizeof(kd)/sizeof(kd[0]); i++)
1778 {
1780 UINT uiRet;
1781
1782 if (!is_font_installed(kd[i].face_name))
1783 {
1784 trace("%s is not installed so skipping this test\n", kd[i].face_name);
1785 continue;
1786 }
1787
1788 trace("testing font %s, height %d\n", kd[i].face_name, kd[i].height);
1789
1790 memset(&lf, 0, sizeof(lf));
1791 strcpy(lf.lfFaceName, kd[i].face_name);
1792 lf.lfHeight = kd[i].height;
1794 ok(hfont != NULL, "failed to create a font, name %s\n", kd[i].face_name);
1795
1796 hfont_old = SelectObject(hdc, hfont);
1797
1798 SetLastError(0xdeadbeef);
1799 otm.otmSize = sizeof(otm); /* just in case for Win9x compatibility */
1800 uiRet = GetOutlineTextMetricsW(hdc, sizeof(otm), &otm);
1801 ok(uiRet == sizeof(otm), "GetOutlineTextMetricsW error %d\n", GetLastError());
1802
1803 ok(match_off_by_1(kd[i].tmHeight, otm.otmTextMetrics.tmHeight, FALSE), "expected %d, got %d\n",
1804 kd[i].tmHeight, otm.otmTextMetrics.tmHeight);
1805 ok(match_off_by_1(kd[i].tmAscent, otm.otmTextMetrics.tmAscent, FALSE), "expected %d, got %d\n",
1806 kd[i].tmAscent, otm.otmTextMetrics.tmAscent);
1807 ok(kd[i].tmDescent == otm.otmTextMetrics.tmDescent, "expected %d, got %d\n",
1808 kd[i].tmDescent, otm.otmTextMetrics.tmDescent);
1809
1810 ok(kd[i].otmEMSquare == otm.otmEMSquare, "expected %u, got %u\n",
1811 kd[i].otmEMSquare, otm.otmEMSquare);
1812 ok(kd[i].otmAscent == otm.otmAscent, "expected %d, got %d\n",
1813 kd[i].otmAscent, otm.otmAscent);
1814 ok(kd[i].otmDescent == otm.otmDescent, "expected %d, got %d\n",
1815 kd[i].otmDescent, otm.otmDescent);
1816 ok(kd[i].otmLineGap == otm.otmLineGap, "expected %u, got %u\n",
1817 kd[i].otmLineGap, otm.otmLineGap);
1818 ok(near_match(kd[i].otmMacDescent, otm.otmMacDescent), "expected %d, got %d\n",
1819 kd[i].otmMacDescent, otm.otmMacDescent);
1820 ok(near_match(kd[i].otmMacAscent, otm.otmMacAscent), "expected %d, got %d\n",
1821 kd[i].otmMacAscent, otm.otmMacAscent);
1823 ok(kd[i].otmsCapEmHeight == otm.otmsCapEmHeight, "expected %u, got %u\n",
1824 kd[i].otmsCapEmHeight, otm.otmsCapEmHeight);
1826 ok(kd[i].otmsXHeight == otm.otmsXHeight, "expected %u, got %u\n",
1827 kd[i].otmsXHeight, otm.otmsXHeight);
1828 ok(kd[i].otmMacLineGap == otm.otmMacLineGap, "expected %u, got %u\n",
1829 kd[i].otmMacLineGap, otm.otmMacLineGap);
1831 ok(kd[i].otmusMinimumPPEM == otm.otmusMinimumPPEM, "expected %u, got %u\n",
1832 kd[i].otmusMinimumPPEM, otm.otmusMinimumPPEM);
1833
1834 total_kern_pairs = GetKerningPairsW(hdc, 0, NULL);
1835 trace("total_kern_pairs %u\n", total_kern_pairs);
1836 kern_pair = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pair));
1837
1838 /* Win98 (GetKerningPairsA) and XP behave differently here, the test
1839 * passes on XP.
1840 */
1841 SetLastError(0xdeadbeef);
1842 ret = GetKerningPairsW(hdc, 0, kern_pair);
1844 "got error %u, expected ERROR_INVALID_PARAMETER\n", GetLastError());
1845 ok(ret == 0, "got %u, expected 0\n", ret);
1846
1847 ret = GetKerningPairsW(hdc, 100, NULL);
1848 ok(ret == total_kern_pairs, "got %u, expected %u\n", ret, total_kern_pairs);
1849
1850 ret = GetKerningPairsW(hdc, total_kern_pairs/2, kern_pair);
1851 ok(ret == total_kern_pairs/2, "got %u, expected %u\n", ret, total_kern_pairs/2);
1852
1853 ret = GetKerningPairsW(hdc, total_kern_pairs, kern_pair);
1854 ok(ret == total_kern_pairs, "got %u, expected %u\n", ret, total_kern_pairs);
1855
1856 matches = 0;
1857
1858 for (n = 0; n < ret; n++)
1859 {
1860 DWORD j;
1861 /* Disabled to limit console spam */
1862 if (0 && kern_pair[n].wFirst < 127 && kern_pair[n].wSecond < 127)
1863 trace("{'%c','%c',%d},\n",
1864 kern_pair[n].wFirst, kern_pair[n].wSecond, kern_pair[n].iKernAmount);
1865 for (j = 0; j < kd[i].total_kern_pairs; j++)
1866 {
1867 if (kern_pair[n].wFirst == kd[i].kern_pair[j].wFirst &&
1868 kern_pair[n].wSecond == kd[i].kern_pair[j].wSecond)
1869 {
1870 ok(kern_pair[n].iKernAmount == kd[i].kern_pair[j].iKernAmount,
1871 "pair %d:%d got %d, expected %d\n",
1872 kern_pair[n].wFirst, kern_pair[n].wSecond,
1873 kern_pair[n].iKernAmount, kd[i].kern_pair[j].iKernAmount);
1874 matches++;
1875 }
1876 }
1877 }
1878
1879 ok(matches == kd[i].total_kern_pairs, "got matches %u, expected %u\n",
1880 matches, kd[i].total_kern_pairs);
1881
1882 HeapFree(GetProcessHeap(), 0, kern_pair);
1883
1884 SelectObject(hdc, hfont_old);
1886 }
1887
1888 ReleaseDC(0, hdc);
1889}
1890
1892{
1897};
1898
1899static void test_height( HDC hdc, const struct font_data *fd )
1900{
1901 LOGFONTA lf;
1902 HFONT hfont, old_hfont;
1904 INT ret, i;
1905
1906 for (i = 0; fd[i].face_name[0]; i++)
1907 {
1908 if (!is_truetype_font_installed(fd[i].face_name))
1909 {
1910 skip("%s is not installed\n", fd[i].face_name);
1911 continue;
1912 }
1913
1914 memset(&lf, 0, sizeof(lf));
1915 lf.lfHeight = fd[i].requested_height;
1916 lf.lfWeight = fd[i].weight;
1917 strcpy(lf.lfFaceName, fd[i].face_name);
1918
1920 ok(hfont != NULL, "failed to create a font, name %s\n", fd[i].face_name);
1921
1922 old_hfont = SelectObject(hdc, hfont);
1924 ok(ret, "GetTextMetrics error %d\n", GetLastError());
1925 if(fd[i].dpi == tm.tmDigitizedAspectX)
1926 {
1927 ok(tm.tmWeight == fd[i].weight, "%s(%d): tm.tmWeight %d != %d\n", fd[i].face_name, fd[i].requested_height, tm.tmWeight, fd[i].weight);
1928 ok(match_off_by_1(tm.tmHeight, fd[i].height, fd[i].exact), "%s(%d): tm.tmHeight %d != %d\n", fd[i].face_name, fd[i].requested_height, tm.tmHeight, fd[i].height);
1929 ok(match_off_by_1(tm.tmAscent, fd[i].ascent, fd[i].exact), "%s(%d): tm.tmAscent %d != %d\n", fd[i].face_name, fd[i].requested_height, tm.tmAscent, fd[i].ascent);
1930 ok(match_off_by_1(tm.tmDescent, fd[i].descent, fd[i].exact), "%s(%d): tm.tmDescent %d != %d\n", fd[i].face_name, fd[i].requested_height, tm.tmDescent, fd[i].descent);
1931 ok(match_off_by_1(tm.tmInternalLeading, fd[i].int_leading, fd[i].exact), "%s(%d): tm.tmInternalLeading %d != %d\n", fd[i].face_name, fd[i].requested_height, tm.tmInternalLeading, fd[i].int_leading);
1932 ok(tm.tmExternalLeading == fd[i].ext_leading, "%s(%d): tm.tmExternalLeading %d != %d\n", fd[i].face_name, fd[i].requested_height, tm.tmExternalLeading, fd[i].ext_leading);
1933 }
1934
1935 SelectObject(hdc, old_hfont);
1936 /* force GDI to use new font, otherwise Windows leaks the font reference */
1939 }
1940}
1941
1942static void *find_ttf_table( void *ttf, DWORD size, DWORD tag )
1943{
1944 WORD i, num_tables = GET_BE_WORD(*((WORD *)ttf + 2));
1945 DWORD *table = (DWORD *)ttf + 3;
1946
1947 for (i = 0; i < num_tables; i++)
1948 {
1949 if (table[0] == tag)
1950 return (BYTE *)ttf + GET_BE_DWORD(table[2]);
1951 table += 4;
1952 }
1953 return NULL;
1954}
1955
1957{
1958 static const struct font_data charset_0[] = /* doesn't use VDMX */
1959 {
1960 { "wine_vdmx", 10, FW_NORMAL, 10, 8, 2, 2, 0, 96, TRUE },
1961 { "wine_vdmx", 11, FW_NORMAL, 11, 9, 2, 2, 0, 96, TRUE },
1962 { "wine_vdmx", 12, FW_NORMAL, 12, 10, 2, 2, 0, 96, TRUE },
1963 { "wine_vdmx", 13, FW_NORMAL, 13, 11, 2, 2, 0, 96, TRUE },
1964 { "wine_vdmx", 14, FW_NORMAL, 14, 12, 2, 2, 0, 96, TRUE },
1965 { "wine_vdmx", 15, FW_NORMAL, 15, 12, 3, 3, 0, 96, FALSE },
1966 { "wine_vdmx", 16, FW_NORMAL, 16, 13, 3, 3, 0, 96, TRUE },
1967 { "wine_vdmx", 17, FW_NORMAL, 17, 14, 3, 3, 0, 96, TRUE },
1968 { "wine_vdmx", 18, FW_NORMAL, 18, 15, 3, 3, 0, 96, TRUE },
1969 { "wine_vdmx", 19, FW_NORMAL, 19, 16, 3, 3, 0, 96, TRUE },
1970 { "wine_vdmx", 20, FW_NORMAL, 20, 17, 3, 4, 0, 96, FALSE },
1971 { "wine_vdmx", 21, FW_NORMAL, 21, 17, 4, 4, 0, 96, TRUE },
1972 { "wine_vdmx", 22, FW_NORMAL, 22, 18, 4, 4, 0, 96, TRUE },
1973 { "wine_vdmx", 23, FW_NORMAL, 23, 19, 4, 4, 0, 96, TRUE },
1974 { "wine_vdmx", 24, FW_NORMAL, 24, 20, 4, 4, 0, 96, TRUE },
1975 { "wine_vdmx", 25, FW_NORMAL, 25, 21, 4, 4, 0, 96, TRUE },
1976 { "wine_vdmx", 26, FW_NORMAL, 26, 22, 4, 5, 0, 96, FALSE },
1977 { "wine_vdmx", 27, FW_NORMAL, 27, 22, 5, 5, 0, 96, TRUE },
1978 { "wine_vdmx", 28, FW_NORMAL, 28, 23, 5, 5, 0, 96, TRUE },
1979 { "wine_vdmx", 29, FW_NORMAL, 29, 24, 5, 5, 0, 96, TRUE },
1980 { "wine_vdmx", 30, FW_NORMAL, 30, 25, 5, 5, 0, 96, TRUE },
1981 { "wine_vdmx", 31, FW_NORMAL, 31, 26, 5, 5, 0, 96, TRUE },
1982 { "wine_vdmx", 32, FW_NORMAL, 32, 27, 5, 6, 0, 96, FALSE },
1983 { "wine_vdmx", 48, FW_NORMAL, 48, 40, 8, 8, 0, 96, TRUE },
1984 { "wine_vdmx", 64, FW_NORMAL, 64, 53, 11, 11, 0, 96, TRUE },
1985 { "wine_vdmx", 96, FW_NORMAL, 96, 80, 16, 17, 0, 96, FALSE },
1986 { "wine_vdmx", -10, FW_NORMAL, 12, 10, 2, 2, 0, 96, TRUE },
1987 { "wine_vdmx", -11, FW_NORMAL, 13, 11, 2, 2, 0, 96, TRUE },
1988 { "wine_vdmx", -12, FW_NORMAL, 14, 12, 2, 2, 0, 96, TRUE },
1989 { "wine_vdmx", -13, FW_NORMAL, 16, 13, 3, 3, 0, 96, TRUE },
1990 { "wine_vdmx", -14, FW_NORMAL, 17, 14, 3, 3, 0, 96, TRUE },
1991 { "wine_vdmx", -15, FW_NORMAL, 18, 15, 3, 3, 0, 96, TRUE },
1992 { "wine_vdmx", -16, FW_NORMAL, 19, 16, 3, 3, 0, 96, TRUE },
1993 { "wine_vdmx", -17, FW_NORMAL, 21, 17, 4, 4, 0, 96, TRUE },
1994 { "wine_vdmx", -18, FW_NORMAL, 22, 18, 4, 4, 0, 96, TRUE },
1995 { "wine_vdmx", -19, FW_NORMAL, 23, 19, 4, 4, 0, 96, TRUE },
1996 { "wine_vdmx", -20, FW_NORMAL, 24, 20, 4, 4, 0, 96, TRUE },
1997 { "wine_vdmx", -21, FW_NORMAL, 25, 21, 4, 4, 0, 96, TRUE },
1998 { "wine_vdmx", -22, FW_NORMAL, 27, 22, 5, 5, 0, 96, TRUE },
1999 { "wine_vdmx", -23, FW_NORMAL, 28, 23, 5, 5, 0, 96, TRUE },
2000 { "wine_vdmx", -24, FW_NORMAL, 29, 24, 5, 5, 0, 96, TRUE },
2001 { "wine_vdmx", -25, FW_NORMAL, 30, 25, 5, 5, 0, 96, TRUE },
2002 { "wine_vdmx", -26, FW_NORMAL, 31, 26, 5, 5, 0, 96, TRUE },
2003 { "wine_vdmx", -27, FW_NORMAL, 33, 27, 6, 6, 0, 96, TRUE },
2004 { "wine_vdmx", -28, FW_NORMAL, 34, 28, 6, 6, 0, 96, TRUE },
2005 { "wine_vdmx", -29, FW_NORMAL, 35, 29, 6, 6, 0, 96, TRUE },
2006 { "wine_vdmx", -30, FW_NORMAL, 36, 30, 6, 6, 0, 96, TRUE },
2007 { "wine_vdmx", -31, FW_NORMAL, 37, 31, 6, 6, 0, 96, TRUE },
2008 { "wine_vdmx", -32, FW_NORMAL, 39, 32, 7, 7, 0, 96, TRUE },
2009 { "wine_vdmx", -48, FW_NORMAL, 58, 48, 10, 10, 0, 96, TRUE },
2010 { "wine_vdmx", -64, FW_NORMAL, 77, 64, 13, 13, 0, 96, TRUE },
2011 { "wine_vdmx", -96, FW_NORMAL, 116, 96, 20, 20, 0, 96, TRUE },
2012 { "", 0, 0, 0, 0, 0, 0, 0, 0, 0 }
2013 };
2014
2015 static const struct font_data charset_1[] = /* Uses VDMX */
2016 {
2017 { "wine_vdmx", 10, FW_NORMAL, 10, 8, 2, 2, 0, 96, TRUE },
2018 { "wine_vdmx", 11, FW_NORMAL, 11, 9, 2, 2, 0, 96, TRUE },
2019 { "wine_vdmx", 12, FW_NORMAL, 12, 10, 2, 2, 0, 96, TRUE },
2020 { "wine_vdmx", 13, FW_NORMAL, 13, 11, 2, 2, 0, 96, TRUE },
2021 { "wine_vdmx", 14, FW_NORMAL, 13, 11, 2, 2, 0, 96, TRUE },
2022 { "wine_vdmx", 15, FW_NORMAL, 13, 11, 2, 2, 0, 96, TRUE },
2023 { "wine_vdmx", 16, FW_NORMAL, 16, 13, 3, 4, 0, 96, TRUE },
2024 { "wine_vdmx", 17, FW_NORMAL, 16, 13, 3, 3, 0, 96, TRUE },
2025 { "wine_vdmx", 18, FW_NORMAL, 16, 13, 3, 3, 0, 96, TRUE },
2026 { "wine_vdmx", 19, FW_NORMAL, 19, 15, 4, 5, 0, 96, TRUE },
2027 { "wine_vdmx", 20, FW_NORMAL, 20, 16, 4, 5, 0, 96, TRUE },
2028 { "wine_vdmx", 21, FW_NORMAL, 21, 17, 4, 5, 0, 96, TRUE },
2029 { "wine_vdmx", 22, FW_NORMAL, 22, 18, 4, 5, 0, 96, TRUE },
2030 { "wine_vdmx", 23, FW_NORMAL, 23, 19, 4, 5, 0, 96, TRUE },
2031 { "wine_vdmx", 24, FW_NORMAL, 23, 19, 4, 5, 0, 96, TRUE },
2032 { "wine_vdmx", 25, FW_NORMAL, 25, 21, 4, 6, 0, 96, TRUE },
2033 { "wine_vdmx", 26, FW_NORMAL, 26, 22, 4, 6, 0, 96, TRUE },
2034 { "wine_vdmx", 27, FW_NORMAL, 27, 23, 4, 6, 0, 96, TRUE },
2035 { "wine_vdmx", 28, FW_NORMAL, 27, 23, 4, 5, 0, 96, TRUE },
2036 { "wine_vdmx", 29, FW_NORMAL, 29, 24, 5, 6, 0, 96, TRUE },
2037 { "wine_vdmx", 30, FW_NORMAL, 29, 24, 5, 6, 0, 96, TRUE },
2038 { "wine_vdmx", 31, FW_NORMAL, 29, 24, 5, 6, 0, 96, TRUE },
2039 { "wine_vdmx", 32, FW_NORMAL, 32, 26, 6, 8, 0, 96, TRUE },
2040 { "wine_vdmx", 48, FW_NORMAL, 48, 40, 8, 10, 0, 96, TRUE },
2041 { "wine_vdmx", 64, FW_NORMAL, 64, 54, 10, 13, 0, 96, TRUE },
2042 { "wine_vdmx", 96, FW_NORMAL, 95, 79, 16, 18, 0, 96, TRUE },
2043 { "wine_vdmx", -10, FW_NORMAL, 12, 10, 2, 2, 0, 96, TRUE },
2044 { "wine_vdmx", -11, FW_NORMAL, 13, 11, 2, 2, 0, 96, TRUE },
2045 { "wine_vdmx", -12, FW_NORMAL, 16, 13, 3, 4, 0, 96, TRUE },
2046 { "wine_vdmx", -13, FW_NORMAL, 16, 13, 3, 3, 0, 96, TRUE },
2047 { "wine_vdmx", -14, FW_NORMAL, 19, 15, 4, 5, 0, 96, TRUE },
2048 { "wine_vdmx", -15, FW_NORMAL, 20, 16, 4, 5, 0, 96, TRUE },
2049 { "wine_vdmx", -16, FW_NORMAL, 21, 17, 4, 5, 0, 96, TRUE },
2050 { "wine_vdmx", -17, FW_NORMAL, 22, 18, 4, 5, 0, 96, TRUE },
2051 { "wine_vdmx", -18, FW_NORMAL, 23, 19, 4, 5, 0, 96, TRUE },
2052 { "wine_vdmx", -19, FW_NORMAL, 25, 21, 4, 6, 0, 96, TRUE },
2053 { "wine_vdmx", -20, FW_NORMAL, 26, 22, 4, 6, 0, 96, TRUE },
2054 { "wine_vdmx", -21, FW_NORMAL, 27, 23, 4, 6, 0, 96, TRUE },
2055 { "wine_vdmx", -22, FW_NORMAL, 27, 23, 4, 5, 0, 96, TRUE },
2056 { "wine_vdmx", -23, FW_NORMAL, 29, 24, 5, 6, 0, 96, TRUE },
2057 { "wine_vdmx", -24, FW_NORMAL, 32, 26, 6, 8, 0, 96, TRUE },
2058 { "wine_vdmx", -25, FW_NORMAL, 32, 26, 6, 7, 0, 96, TRUE },
2059 { "wine_vdmx", -26, FW_NORMAL, 33, 27, 6, 7, 0, 96, TRUE },
2060 { "wine_vdmx", -27, FW_NORMAL, 35, 29, 6, 8, 0, 96, TRUE },
2061 { "wine_vdmx", -28, FW_NORMAL, 36, 30, 6, 8, 0, 96, TRUE },
2062 { "wine_vdmx", -29, FW_NORMAL, 36, 30, 6, 7, 0, 96, TRUE },
2063 { "wine_vdmx", -30, FW_NORMAL, 38, 32, 6, 8, 0, 96, TRUE },
2064 { "wine_vdmx", -31, FW_NORMAL, 39, 33, 6, 8, 0, 96, TRUE },
2065 { "wine_vdmx", -32, FW_NORMAL, 40, 33, 7, 8, 0, 96, TRUE },
2066 { "wine_vdmx", -48, FW_NORMAL, 60, 50, 10, 12, 0, 96, TRUE },
2067 { "wine_vdmx", -64, FW_NORMAL, 81, 67, 14, 17, 0, 96, TRUE },
2068 { "wine_vdmx", -96, FW_NORMAL, 119, 99, 20, 23, 0, 96, TRUE },
2069 { "", 0, 0, 0, 0, 0, 0, 0, 0, 0 }
2070 };
2071
2072 static const struct vdmx_data
2073 {
2074 WORD version;
2075 BYTE bCharSet;
2076 const struct font_data *fd;
2077 } data[] =
2078 {
2079 { 0, 0, charset_0 },
2080 { 0, 1, charset_1 },
2081 { 1, 0, charset_0 },
2082 { 1, 1, charset_1 }
2083 };
2084 int i;
2085 DWORD size, num;
2086 WORD *vdmx_header;
2087 BYTE *ratio_rec;
2088 char ttf_name[MAX_PATH];
2089 void *res, *copy;
2090 BOOL ret;
2091
2092 if (!pAddFontResourceExA)
2093 {
2094 win_skip("AddFontResourceExA unavailable\n");
2095 return;
2096 }
2097
2098 for (i = 0; i < sizeof(data) / sizeof(data[0]); i++)
2099 {
2100 res = get_res_data( "wine_vdmx.ttf", &size );
2101
2102 copy = HeapAlloc( GetProcessHeap(), 0, 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 HeapFree( GetProcessHeap(), 0, copy );
2113
2114 ok( !is_truetype_font_installed("wine_vdmx"), "Already installed\n" );
2115 num = pAddFontResourceExA( 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 pRemoveFontResourceExA( ttf_name, FR_PRIVATE, 0 );
2122 }
2123 ret = DeleteFileA( ttf_name );
2125 "DeleteFile error %d\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 = HeapAlloc(GetProcessHeap(), 0, otm_size);
2170 otm->otmSize = sizeof(*otm);
2171 ret = GetOutlineTextMetricsA(hdc, otm->otmSize, otm);
2172 ok(ret == otm->otmSize, "expected %u, got %u, error %d\n", otm->otmSize, ret, GetLastError());
2173 fsSelection = otm->otmfsSelection;
2174 HeapFree(GetProcessHeap(), 0, 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 trace("otm buffer size %u (0x%x)\n", otm_size, otm_size);
2243
2244 otm = HeapAlloc(GetProcessHeap(), 0, otm_size);
2245
2246 memset(otm, 0xAA, otm_size);
2247 SetLastError(0xdeadbeef);
2248 otm->otmSize = sizeof(*otm); /* just in case for Win9x compatibility */
2249 ret = GetOutlineTextMetricsA(hdc, otm->otmSize, otm);
2250 ok(ret == 1 /* Win9x */ ||
2251 ret == otm->otmSize /* XP*/,
2252 "expected %u, got %u, error %d\n", otm->otmSize, ret, GetLastError());
2253 if (ret != 1) /* Win9x doesn't care about pointing beyond of the buffer */
2254 {
2255 ok(otm->otmpFamilyName == NULL, "expected NULL got %p\n", otm->otmpFamilyName);
2256 ok(otm->otmpFaceName == NULL, "expected NULL got %p\n", otm->otmpFaceName);
2257 ok(otm->otmpStyleName == NULL, "expected NULL got %p\n", otm->otmpStyleName);
2258 ok(otm->otmpFullName == NULL, "expected NULL got %p\n", otm->otmpFullName);
2259 }
2260
2261 memset(otm, 0xAA, otm_size);
2262 SetLastError(0xdeadbeef);
2263 otm->otmSize = otm_size; /* just in case for Win9x compatibility */
2264 ret = GetOutlineTextMetricsA(hdc, otm->otmSize, otm);
2265 ok(ret == 1 /* Win9x */ ||
2266 ret == otm->otmSize /* XP*/,
2267 "expected %u, got %u, error %d\n", otm->otmSize, ret, GetLastError());
2268 if (ret != 1) /* Win9x doesn't care about pointing beyond of the buffer */
2269 {
2270 ok(otm->otmpFamilyName != NULL, "expected not NULL got %p\n", otm->otmpFamilyName);
2271 ok(otm->otmpFaceName != NULL, "expected not NULL got %p\n", otm->otmpFaceName);
2272 ok(otm->otmpStyleName != NULL, "expected not NULL got %p\n", otm->otmpStyleName);
2273 ok(otm->otmpFullName != NULL, "expected not NULL got %p\n", otm->otmpFullName);
2274 }
2275
2276 /* ask about truncated data */
2277 memset(otm, 0xAA, otm_size);
2278 memset(&unset_ptr, 0xAA, sizeof(unset_ptr));
2279 SetLastError(0xdeadbeef);
2280 otm->otmSize = sizeof(*otm) - sizeof(LPSTR); /* just in case for Win9x compatibility */
2281 ret = GetOutlineTextMetricsA(hdc, otm->otmSize, otm);
2282 ok(ret == 1 /* Win9x */ ||
2283 ret == otm->otmSize /* XP*/,
2284 "expected %u, got %u, error %d\n", otm->otmSize, ret, GetLastError());
2285 if (ret != 1) /* Win9x doesn't care about pointing beyond of the buffer */
2286 {
2287 ok(otm->otmpFamilyName == NULL, "expected NULL got %p\n", otm->otmpFamilyName);
2288 ok(otm->otmpFaceName == NULL, "expected NULL got %p\n", otm->otmpFaceName);
2289 ok(otm->otmpStyleName == NULL, "expected NULL got %p\n", otm->otmpStyleName);
2290 }
2291 ok(otm->otmpFullName == unset_ptr, "expected %p got %p\n", unset_ptr, otm->otmpFullName);
2292
2293 /* check handling of NULL pointer */
2294 SetLastError(0xdeadbeef);
2295 ret = GetOutlineTextMetricsA(hdc, otm_size, NULL);
2296 ok(ret == otm_size, "expected %u, got %u, error %d\n", otm_size, ret, GetLastError());
2297
2298 HeapFree(GetProcessHeap(), 0, otm);
2299
2300 SelectObject(hdc, hfont_old);
2302
2303 ReleaseDC(0, hdc);
2304}
2305
2306static void testJustification(HDC hdc, PCSTR str, RECT *clientArea)
2307{
2308 INT y,
2309 breakCount,
2310 areaWidth = clientArea->right - clientArea->left,
2311 nErrors = 0, e;
2312 const char *pFirstChar, *pLastChar;
2313 SIZE size;
2315 struct err
2316 {
2317 const char *start;
2318 int len;
2319 int GetTextExtentExPointWWidth;
2320 } error[20];
2321
2323 y = clientArea->top;
2324 do {
2325 breakCount = 0;
2326 while (*str == tm.tmBreakChar) str++; /* skip leading break chars */
2327 pFirstChar = str;
2328
2329 do {
2330 pLastChar = str;
2331
2332 /* if not at the end of the string, ... */
2333 if (*str == '\0') break;
2334 /* ... add the next word to the current extent */
2335 while (*str != '\0' && *str++ != tm.tmBreakChar);
2336 breakCount++;
2338 GetTextExtentPoint32A(hdc, pFirstChar, str - pFirstChar - 1, &size);
2339 } while ((int) size.cx < areaWidth);
2340
2341 /* ignore trailing break chars */
2342 breakCount--;
2343 while (*(pLastChar - 1) == tm.tmBreakChar)
2344 {
2345 pLastChar--;
2346 breakCount--;
2347 }
2348
2349 if (*str == '\0' || breakCount <= 0) pLastChar = str;
2350
2352 GetTextExtentPoint32A(hdc, pFirstChar, pLastChar - pFirstChar, &size);
2353
2354 /* do not justify the last extent */
2355 if (*str != '\0' && breakCount > 0)
2356 {
2357 SetTextJustification(hdc, areaWidth - size.cx, breakCount);
2358 GetTextExtentPoint32A(hdc, pFirstChar, pLastChar - pFirstChar, &size);
2359 if (size.cx != areaWidth && nErrors < sizeof(error)/sizeof(error[0]) - 1)
2360 {
2361 error[nErrors].start = pFirstChar;
2362 error[nErrors].len = pLastChar - pFirstChar;
2363 error[nErrors].GetTextExtentExPointWWidth = size.cx;
2364 nErrors++;
2365 }
2366 }
2367
2368 y += size.cy;
2369 str = pLastChar;
2370 } while (*str && y < clientArea->bottom);
2371
2372 for (e = 0; e < nErrors; e++)
2373 {
2374 /* The width returned by GetTextExtentPoint32() is exactly the same
2375 returned by GetTextExtentExPointW() - see dlls/gdi32/font.c */
2376 ok(error[e].GetTextExtentExPointWWidth == areaWidth,
2377 "GetTextExtentPointW() for \"%.*s\" should have returned a width of %d, not %d.\n",
2378 error[e].len, error[e].start, areaWidth, error[e].GetTextExtentExPointWWidth);
2379 }
2380}
2381
2383{
2384 HDC hdc;
2385 RECT clientArea;
2386 LOGFONTA lf;
2387 HFONT hfont;
2388 HWND hwnd;
2389 SIZE size, expect;
2390 int i;
2391 WORD indices[2];
2392 static const char testText[] =
2393 "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do "
2394 "eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut "
2395 "enim ad minim veniam, quis nostrud exercitation ullamco laboris "
2396 "nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in "
2397 "reprehenderit in voluptate velit esse cillum dolore eu fugiat "
2398 "nulla pariatur. Excepteur sint occaecat cupidatat non proident, "
2399 "sunt in culpa qui officia deserunt mollit anim id est laborum.";
2400
2401 hwnd = CreateWindowExA(0, "static", "", WS_POPUP, 0,0, 400,400, 0, 0, 0, NULL);
2402 GetClientRect( hwnd, &clientArea );
2403 hdc = GetDC( hwnd );
2404
2405 if (!is_font_installed("Times New Roman"))
2406 {
2407 skip("Times New Roman is not installed\n");
2408 return;
2409 }
2410
2411 memset(&lf, 0, sizeof lf);
2414 lf.lfWeight = FW_DONTCARE;
2415 lf.lfHeight = 20;
2417 lstrcpyA(lf.lfFaceName, "Times New Roman");
2418 hfont = create_font("Times New Roman", &lf);
2420
2421 testJustification(hdc, testText, &clientArea);
2422
2423 if (!pGetGlyphIndicesA || !pGetTextExtentExPointI) goto done;
2424 pGetGlyphIndicesA( hdc, "A ", 2, indices, 0 );
2425
2427 GetTextExtentPoint32A(hdc, " ", 1, &expect);
2428 GetTextExtentPoint32A(hdc, " ", 3, &size);
2429 ok( size.cx == 3 * expect.cx, "wrong size %d/%d\n", size.cx, expect.cx );
2431 GetTextExtentPoint32A(hdc, " ", 1, &size);
2432 ok( size.cx == expect.cx + 4, "wrong size %d/%d\n", size.cx, expect.cx );
2434 GetTextExtentPoint32A(hdc, " ", 2, &size);
2435 ok( size.cx == 2 * expect.cx + 9, "wrong size %d/%d\n", size.cx, expect.cx );
2437 GetTextExtentPoint32A(hdc, " ", 3, &size);
2438 ok( size.cx == 3 * expect.cx + 7, "wrong size %d/%d\n", size.cx, expect.cx );
2441 GetTextExtentPoint32A(hdc, " ", 3, &size);
2442 ok( size.cx == 3 * (expect.cx + 2) + 7, "wrong size %d/%d\n", size.cx, expect.cx );
2445 size.cx = size.cy = 1234;
2446 GetTextExtentPoint32A(hdc, " ", 0, &size);
2447 ok( size.cx == 0 && size.cy == 0, "wrong size %d,%d\n", size.cx, size.cy );
2448 pGetTextExtentExPointI(hdc, indices, 2, -1, NULL, NULL, &expect);
2450 pGetTextExtentExPointI(hdc, indices, 2, -1, NULL, NULL, &size);
2451 ok( size.cx == expect.cx + 5, "wrong size %d/%d\n", size.cx, expect.cx );
2453
2455 SetWindowExtEx( hdc, 2, 2, NULL );
2456 GetClientRect( hwnd, &clientArea );
2457 DPtoLP( hdc, (POINT *)&clientArea, 2 );
2458 testJustification(hdc, testText, &clientArea);
2459
2460 GetTextExtentPoint32A(hdc, "A", 1, &expect);
2461 for (i = 0; i < 10; i++)
2462 {
2464 GetTextExtentPoint32A(hdc, "A", 1, &size);
2465 ok( size.cx == expect.cx + i, "wrong size %d/%d+%d\n", size.cx, expect.cx, i );
2466 }
2468 pGetTextExtentExPointI(hdc, indices, 1, -1, NULL, NULL, &expect);
2469 for (i = 0; i < 10; i++)
2470 {
2472 pGetTextExtentExPointI(hdc, indices, 1, -1, NULL, NULL, &size);
2473 ok( size.cx == expect.cx + i, "wrong size %d/%d+%d\n", size.cx, expect.cx, i );
2474 }
2476
2477 SetViewportExtEx( hdc, 3, 3, NULL );
2478 GetClientRect( hwnd, &clientArea );
2479 DPtoLP( hdc, (POINT *)&clientArea, 2 );
2480 testJustification(hdc, testText, &clientArea);
2481
2482 GetTextExtentPoint32A(hdc, "A", 1, &expect);
2483 for (i = 0; i < 10; i++)
2484 {
2486 GetTextExtentPoint32A(hdc, "A", 1, &size);
2487 ok( size.cx == expect.cx + i, "wrong size %d/%d+%d\n", size.cx, expect.cx, i );
2488 }
2489
2490done:
2492 ReleaseDC(hwnd, hdc);
2494}
2495
2496static BOOL get_glyph_indices(INT charset, UINT code_page, WORD *idx, UINT count, BOOL unicode)
2497{
2498 HDC hdc;
2499 LOGFONTA lf;
2500 HFONT hfont, hfont_old;
2501 CHARSETINFO csi;
2503 INT cs;
2504 DWORD i, ret;
2505 char name[64];
2506
2507 assert(count <= 128);
2508
2509 memset(&lf, 0, sizeof(lf));
2510
2511 lf.lfCharSet = charset;
2512 lf.lfHeight = 10;
2513 lstrcpyA(lf.lfFaceName, "Arial");
2514 SetLastError(0xdeadbeef);
2516 ok(hfont != 0, "CreateFontIndirectA error %u\n", GetLastError());
2517
2518 hdc = GetDC(0);
2519 hfont_old = SelectObject(hdc, hfont);
2520
2521 cs = GetTextCharsetInfo(hdc, &fs, 0);
2522 ok(cs == charset, "expected %d, got %d\n", charset, cs);
2523
2524 SetLastError(0xdeadbeef);
2525 ret = GetTextFaceA(hdc, sizeof(name), name);
2526 ok(ret, "GetTextFaceA error %u\n", GetLastError());
2527
2528 if (charset == SYMBOL_CHARSET)
2529 {
2530 ok(strcmp("Arial", name), "face name should NOT be Arial\n");
2531 ok(fs.fsCsb[0] & (1u << 31), "symbol encoding should be available\n");
2532 }
2533 else
2534 {
2535 ok(!strcmp("Arial", name), "face name should be Arial, not %s\n", name);
2536 ok(!(fs.fsCsb[0] & (1u << 31)), "symbol encoding should NOT be available\n");
2537 }
2538
2540 {
2541 trace("Can't find codepage for charset %d\n", cs);
2542 ReleaseDC(0, hdc);
2543 return FALSE;
2544 }
2545 ok(csi.ciACP == code_page, "expected %d, got %d\n", code_page, csi.ciACP);
2546
2547 if (pGdiGetCodePage != NULL && pGdiGetCodePage(hdc) != code_page)
2548 {
2549 skip("Font code page %d, looking for code page %d\n",
2550 pGdiGetCodePage(hdc), code_page);
2551 ReleaseDC(0, hdc);
2552 return FALSE;
2553 }
2554
2555 if (unicode)
2556 {
2557 char ansi_buf[128];
2558 WCHAR unicode_buf[128];
2559
2560 for (i = 0; i < count; i++) ansi_buf[i] = (BYTE)(i + 128);
2561
2562 MultiByteToWideChar(code_page, 0, ansi_buf, count, unicode_buf, count);
2563
2564 SetLastError(0xdeadbeef);
2565 ret = pGetGlyphIndicesW(hdc, unicode_buf, count, idx, 0);
2566 ok(ret == count, "GetGlyphIndicesW expected %d got %d, error %u\n",
2567 count, ret, GetLastError());
2568 }
2569 else
2570 {
2571 char ansi_buf[128];
2572
2573 for (i = 0; i < count; i++) ansi_buf[i] = (BYTE)(i + 128);
2574
2575 SetLastError(0xdeadbeef);
2576 ret = pGetGlyphIndicesA(hdc, ansi_buf, count, idx, 0);
2577 ok(ret == count, "GetGlyphIndicesA expected %d got %d, error %u\n",
2578 count, ret, GetLastError());
2579 }
2580
2581 SelectObject(hdc, hfont_old);
2583
2584 ReleaseDC(0, hdc);
2585
2586 return TRUE;
2587}
2588
2589static void test_font_charset(void)
2590{
2591 static struct charset_data
2592 {
2593 INT charset;
2594 UINT code_page;
2595 WORD font_idxA[128], font_idxW[128];
2596 } cd[] =
2597 {
2598 { ANSI_CHARSET, 1252 },
2599 { RUSSIAN_CHARSET, 1251 },
2600 { SYMBOL_CHARSET, CP_SYMBOL } /* keep it as the last one */
2601 };
2602 int i;
2603
2604 if (!pGetGlyphIndicesA || !pGetGlyphIndicesW)
2605 {
2606 win_skip("Skipping the font charset test on a Win9x platform\n");
2607 return;
2608 }
2609
2610 if (!is_font_installed("Arial"))
2611 {
2612 skip("Arial is not installed\n");
2613 return;
2614 }
2615
2616 for (i = 0; i < sizeof(cd)/sizeof(cd[0]); i++)
2617 {
2618 if (cd[i].charset == SYMBOL_CHARSET)
2619 {
2620 if (!is_font_installed("Symbol") && !is_font_installed("Wingdings"))
2621 {
2622 skip("Symbol or Wingdings is not installed\n");
2623 break;
2624 }
2625 }
2626 if (get_glyph_indices(cd[i].charset, cd[i].code_page, cd[i].font_idxA, 128, FALSE) &&
2627 get_glyph_indices(cd[i].charset, cd[i].code_page, cd[i].font_idxW, 128, TRUE))
2628 ok(!memcmp(cd[i].font_idxA, cd[i].font_idxW, 128*sizeof(WORD)), "%d: indices don't match\n", i);
2629 }
2630
2631 ok(memcmp(cd[0].font_idxW, cd[1].font_idxW, 128*sizeof(WORD)), "0 vs 1: indices shouldn't match\n");
2632 if (i > 2)
2633 {
2634 ok(memcmp(cd[0].font_idxW, cd[2].font_idxW, 128*sizeof(WORD)), "0 vs 2: indices shouldn't match\n");
2635 ok(memcmp(cd[1].font_idxW, cd[2].font_idxW, 128*sizeof(WORD)), "1 vs 2: indices shouldn't match\n");
2636 }
2637 else
2638 skip("Symbol or Wingdings is not installed\n");
2639}
2640
2641static void test_GdiGetCodePage(void)
2642{
2643 static const struct _matching_data
2644 {
2645 UINT current_codepage;
2646 LPCSTR lfFaceName;
2647 UCHAR lfCharSet;
2648 UINT expected_codepage;
2649 } matching_data[] = {
2650 {1251, "Arial", ANSI_CHARSET, 1252},
2651 {1251, "Tahoma", ANSI_CHARSET, 1252},
2652
2653 {1252, "Arial", ANSI_CHARSET, 1252},
2654 {1252, "Tahoma", ANSI_CHARSET, 1252},
2655
2656 {1253, "Arial", ANSI_CHARSET, 1252},
2657 {1253, "Tahoma", ANSI_CHARSET, 1252},
2658
2659 { 932, "Arial", ANSI_CHARSET, 1252}, /* Japanese Windows returns 1252, not 932 */
2660 { 932, "Tahoma", ANSI_CHARSET, 1252},
2661 { 932, "MS UI Gothic", ANSI_CHARSET, 1252},
2662
2663 { 936, "Arial", ANSI_CHARSET, 936},
2664 { 936, "Tahoma", ANSI_CHARSET, 936},
2665 { 936, "Simsun", ANSI_CHARSET, 936},
2666
2667 { 949, "Arial", ANSI_CHARSET, 949},
2668 { 949, "Tahoma", ANSI_CHARSET, 949},
2669 { 949, "Gulim", ANSI_CHARSET, 949},
2670
2671 { 950, "Arial", ANSI_CHARSET, 950},
2672 { 950, "Tahoma", ANSI_CHARSET, 950},
2673 { 950, "PMingLiU", ANSI_CHARSET, 950},
2674 };
2675 HDC hdc;
2676 LOGFONTA lf;
2677 HFONT hfont;
2678 UINT charset, acp;
2680 int i;
2681
2682 if (!pGdiGetCodePage)
2683 {
2684 skip("GdiGetCodePage not available on this platform\n");
2685 return;
2686 }
2687
2688 acp = GetACP();
2689
2690 for (i = 0; i < sizeof(matching_data) / sizeof(struct _matching_data); i++)
2691 {
2692 /* only test data matched current locale codepage */
2693 if (matching_data[i].current_codepage != acp)
2694 continue;
2695
2696 if (!is_font_installed(matching_data[i].lfFaceName))
2697 {
2698 skip("%s is not installed\n", matching_data[i].lfFaceName);
2699 continue;
2700 }
2701
2702 hdc = GetDC(0);
2703
2704 memset(&lf, 0, sizeof(lf));
2705 lf.lfHeight = -16;
2706 lf.lfCharSet = matching_data[i].lfCharSet;
2707 lstrcpyA(lf.lfFaceName, matching_data[i].lfFaceName);
2709 ok(hfont != 0, "CreateFontIndirectA error %u\n", GetLastError());
2710
2713 codepage = pGdiGetCodePage(hdc);
2714 trace("acp=%d, lfFaceName=%s, lfCharSet=%d, GetTextCharset=%d, GdiGetCodePage=%d, expected codepage=%d\n",
2715 acp, lf.lfFaceName, lf.lfCharSet, charset, codepage, matching_data[i].expected_codepage);
2716 ok(codepage == matching_data[i].expected_codepage,
2717 "GdiGetCodePage should have returned %d, got %d\n", matching_data[i].expected_codepage, codepage);
2718
2721
2722 /* CLIP_DFA_DISABLE turns off the font association */
2725 ok(hfont != 0, "CreateFontIndirectA error %u\n", GetLastError());
2726
2729 codepage = pGdiGetCodePage(hdc);
2730 trace("acp=%d, lfFaceName=%s, lfCharSet=%d, GetTextCharset=%d, GdiGetCodePage=%d\n",
2731 acp, lf.lfFaceName, lf.lfCharSet, charset, codepage);
2732 ok(codepage == 1252, "GdiGetCodePage returned %d\n", codepage);
2733
2736
2737 ReleaseDC(NULL, hdc);
2738 }
2739}
2740
2742{
2743 LOGFONTA lf;
2744 HDC hdc;
2745 HFONT hfont, hfont_old;
2746 DWORD size;
2747 GLYPHSET *gs;
2748 DWORD i;
2749
2750 if (!pGetFontUnicodeRanges)
2751 {
2752 win_skip("GetFontUnicodeRanges not available before W2K\n");
2753 return;
2754 }
2755
2756 memset(&lf, 0, sizeof(lf));
2757 lstrcpyA(lf.lfFaceName, "Arial");
2758 hfont = create_font("Arial", &lf);
2759
2760 hdc = GetDC(0);
2761 hfont_old = SelectObject(hdc, hfont);
2762
2763 size = pGetFontUnicodeRanges(NULL, NULL);
2764 ok(!size, "GetFontUnicodeRanges succeeded unexpectedly\n");
2765
2766 size = pGetFontUnicodeRanges(hdc, NULL);
2767 ok(size, "GetFontUnicodeRanges failed unexpectedly\n");
2768
2770
2771 size = pGetFontUnicodeRanges(hdc, gs);
2772 ok(size, "GetFontUnicodeRanges failed\n");
2773
2774 if (0) /* Disabled to limit console spam */
2775 for (i = 0; i < gs->cRanges; i++)
2776 trace("%03d wcLow %04x cGlyphs %u\n", i, gs->ranges[i].wcLow, gs->ranges[i].cGlyphs);
2777 trace("found %u ranges\n", gs->cRanges);
2778
2779 HeapFree(GetProcessHeap(), 0, gs);
2780
2781 SelectObject(hdc, hfont_old);
2783 ReleaseDC(NULL, hdc);
2784}
2785
2787{
2790};
2791
2793{
2796};
2797
2799{
2802};
2803
2805{
2806 struct enum_font_data *efd = (struct enum_font_data *)lParam;
2807 const NEWTEXTMETRICA *ntm = (const NEWTEXTMETRICA *)tm;
2808
2809 ok(lf->lfHeight == tm->tmHeight, "lfHeight %d != tmHeight %d\n", lf->lfHeight, tm->tmHeight);
2810 ok(lf->lfHeight > 0 && lf->lfHeight < 200, "enumerated font height %d\n", lf->lfHeight);
2811
2812 if (type != TRUETYPE_FONTTYPE) return 1;
2813
2814 ok(ntm->ntmCellHeight + ntm->ntmCellHeight/5 >= ntm->ntmSizeEM, "ntmCellHeight %d should be close to ntmSizeEM %d\n", ntm->ntmCellHeight, ntm->ntmSizeEM);
2815
2816 if (0) /* Disabled to limit console spam */
2817 trace("enumed font \"%s\", charset %d, height %d, weight %d, italic %d\n",
2819 if (efd->total >= efd->size)
2820 {
2821 efd->size = max( (efd->total + 1) * 2, 256 );
2822 efd->lf = heap_realloc( efd->lf, efd->size * sizeof(*efd->lf) );
2823 if (!efd->lf) return 0;
2824 }
2825 efd->lf[efd->total++] = *lf;
2826
2827 return 1;
2828}
2829
2831{
2832 struct enum_font_dataW *efd = (struct enum_font_dataW *)lParam;
2833 const NEWTEXTMETRICW *ntm = (const NEWTEXTMETRICW *)tm;
2834
2835 ok(lf->lfHeight == tm->tmHeight, "lfHeight %d != tmHeight %d\n", lf->lfHeight, tm->tmHeight);
2836 ok(lf->lfHeight > 0 && lf->lfHeight < 200, "enumerated font height %d\n", lf->lfHeight);
2837
2838 if (type != TRUETYPE_FONTTYPE) return 1;
2839
2840 ok(ntm->ntmCellHeight + ntm->ntmCellHeight/5 >= ntm->ntmSizeEM, "ntmCellHeight %d should be close to ntmSizeEM %d\n", ntm->ntmCellHeight, ntm->ntmSizeEM);
2841
2842 if (0) /* Disabled to limit console spam */
2843 trace("enumed font %s, charset %d, height %d, weight %d, italic %d\n",
2845 if (efd->total >= efd->size)
2846 {
2847 efd->size = max( (efd->total + 1) * 2, 256 );
2848 efd->lf = heap_realloc( efd->lf, efd->size * sizeof(*efd->lf) );
2849 if (!efd->lf) return 0;
2850 }
2851 efd->lf[efd->total++] = *lf;
2852
2853 return 1;
2854}
2855
2856static void get_charset_stats(struct enum_font_data *efd,
2857 int *ansi_charset, int *symbol_charset,
2858 int *russian_charset)
2859{
2860 int i;
2861
2862 *ansi_charset = 0;
2863 *symbol_charset = 0;
2864 *russian_charset = 0;
2865
2866 for (i = 0; i < efd->total; i++)
2867 {
2868 switch (efd->lf[i].lfCharSet)
2869 {
2870 case ANSI_CHARSET:
2871 (*ansi_charset)++;
2872 break;
2873 case SYMBOL_CHARSET:
2874 (*symbol_charset)++;
2875 break;
2876 case RUSSIAN_CHARSET:
2877 (*russian_charset)++;
2878 break;
2879 }
2880 }
2881}
2882
2883static void get_charset_statsW(struct enum_font_dataW *efd,
2884 int *ansi_charset, int *symbol_charset,
2885 int *russian_charset)
2886{
2887 int i;
2888
2889 *ansi_charset = 0;
2890 *symbol_charset = 0;
2891 *russian_charset = 0;
2892
2893 for (i = 0; i < efd->total; i++)
2894 {
2895 switch (efd->lf[i].lfCharSet)
2896 {
2897 case ANSI_CHARSET:
2898 (*ansi_charset)++;
2899 break;
2900 case SYMBOL_CHARSET:
2901 (*symbol_charset)++;
2902 break;
2903 case RUSSIAN_CHARSET:
2904 (*russian_charset)++;
2905 break;
2906 }
2907 }
2908}
2909
2910static void test_EnumFontFamilies(const char *font_name, INT font_charset)
2911{
2912 struct enum_font_data efd;
2913 struct enum_font_dataW efdw;
2914 LOGFONTA lf;
2915 HDC hdc;
2916 int i, ret, ansi_charset, symbol_charset, russian_charset;
2917
2918 trace("Testing font %s, charset %d\n", *font_name ? font_name : "<empty>", font_charset);
2919
2920 if (*font_name && !is_truetype_font_installed(font_name))
2921 {
2922 skip("%s is not installed\n", font_name);
2923 return;
2924 }
2925 memset( &efd, 0, sizeof(efd) );
2926 memset( &efdw, 0, sizeof(efdw) );
2927
2928 hdc = GetDC(0);
2929
2930 /* Observed behaviour: EnumFontFamilies enumerates aliases like "Arial Cyr"
2931 * while EnumFontFamiliesEx doesn't.
2932 */
2933 if (!*font_name && font_charset == DEFAULT_CHARSET) /* do it only once */
2934 {
2935 /*
2936 * Use EnumFontFamiliesW since win98 crashes when the
2937 * second parameter is NULL using EnumFontFamilies
2938 */
2939 efdw.total = 0;
2940 SetLastError(0xdeadbeef);
2942 ok(ret || GetLastError() == ERROR_CALL_NOT_IMPLEMENTED, "EnumFontFamiliesW error %u\n", GetLastError());
2943 if(ret)
2944 {
2945 get_charset_statsW(&efdw, &ansi_charset, &symbol_charset, &russian_charset);
2946 trace("enumerated ansi %d, symbol %d, russian %d fonts for NULL\n",
2947 ansi_charset, symbol_charset, russian_charset);
2948 ok(efdw.total > 0, "fonts enumerated: NULL\n");
2949 ok(ansi_charset > 0, "NULL family should enumerate ANSI_CHARSET\n");
2950 ok(symbol_charset > 0, "NULL family should enumerate SYMBOL_CHARSET\n");
2951 ok(russian_charset > 0 ||
2952 broken(russian_charset == 0), /* NT4 */
2953 "NULL family should enumerate RUSSIAN_CHARSET\n");
2954 }
2955
2956 efdw.total = 0;
2957 SetLastError(0xdeadbeef);
2959 ok(ret || GetLastError() == ERROR_CALL_NOT_IMPLEMENTED, "EnumFontFamiliesExW error %u\n", GetLastError());
2960 if(ret)
2961 {
2962 get_charset_statsW(&efdw, &ansi_charset, &symbol_charset, &russian_charset);
2963 trace("enumerated ansi %d, symbol %d, russian %d fonts for NULL\n",
2964 ansi_charset, symbol_charset, russian_charset);
2965 ok(efdw.total > 0, "fonts enumerated: NULL\n");
2966 ok(ansi_charset > 0, "NULL family should enumerate ANSI_CHARSET\n");
2967 ok(symbol_charset > 0, "NULL family should enumerate SYMBOL_CHARSET\n");
2968 ok(russian_charset > 0, "NULL family should enumerate RUSSIAN_CHARSET\n");
2969 }
2970 }
2971
2972 efd.total = 0;
2973 SetLastError(0xdeadbeef);
2974 ret = EnumFontFamiliesA(hdc, font_name, arial_enum_proc, (LPARAM)&efd);
2975 ok(ret, "EnumFontFamilies error %u\n", GetLastError());
2976 get_charset_stats(&efd, &ansi_charset, &symbol_charset, &russian_charset);
2977 trace("enumerated ansi %d, symbol %d, russian %d fonts for %s\n",
2978 ansi_charset, symbol_charset, russian_charset,
2979 *font_name ? font_name : "<empty>");
2980 if (*font_name)
2981 ok(efd.total > 0, "no fonts enumerated: %s\n", font_name);
2982 else
2983 ok(!efd.total, "no fonts should be enumerated for empty font_name\n");
2984 for (i = 0; i < efd.total; i++)
2985 {
2986 /* FIXME: remove completely once Wine is fixed */
2987 todo_wine_if(efd.lf[i].lfCharSet != font_charset)
2988 ok(efd.lf[i].lfCharSet == font_charset, "%d: got charset %d\n", i, efd.lf[i].lfCharSet);
2989 ok(!strcmp(efd.lf[i].lfFaceName, font_name), "expected %s, got %s\n",
2990 font_name, efd.lf[i].lfFaceName);
2991 }
2992
2993 memset(&lf, 0, sizeof(lf));
2995 strcpy(lf.lfFaceName, font_name);
2996 efd.total = 0;
2997 SetLastError(0xdeadbeef);
2999 ok(ret, "EnumFontFamiliesEx error %u\n", GetLastError());
3000 get_charset_stats(&efd, &ansi_charset, &symbol_charset, &russian_charset);
3001 trace("enumerated ansi %d, symbol %d, russian %d fonts for %s ANSI_CHARSET\n",
3002 ansi_charset, symbol_charset, russian_charset,
3003 *font_name ? font_name : "<empty>");
3004 if (font_charset == SYMBOL_CHARSET)
3005 {
3006 if (*font_name)
3007 ok(efd.total == 0, "no fonts should be enumerated: %s ANSI_CHARSET\n", font_name);
3008 else
3009 ok(efd.total > 0, "no fonts enumerated: %s\n", font_name);
3010 }
3011 else
3012 {
3013 ok(efd.total > 0, "no fonts enumerated: %s ANSI_CHARSET\n", font_name);
3014 for (i = 0; i < efd.total; i++)
3015 {
3016 ok(efd.lf[i].lfCharSet == ANSI_CHARSET, "%d: got charset %d\n", i, efd.lf[i].lfCharSet);
3017 if (*font_name)
3018 ok(!strcmp(efd.lf[i].lfFaceName, font_name), "expected %s, got %s\n",
3019 font_name, efd.lf[i].lfFaceName);
3020 }
3021 }
3022
3023 /* DEFAULT_CHARSET should enumerate all available charsets */
3024 memset(&lf, 0, sizeof(lf));
3026 strcpy(lf.lfFaceName, font_name);
3027 efd.total = 0;
3028 SetLastError(0xdeadbeef);
3030 ok(ret, "EnumFontFamiliesEx error %u\n", GetLastError());
3031 get_charset_stats(&efd, &ansi_charset, &symbol_charset, &russian_charset);
3032 trace("enumerated ansi %d, symbol %d, russian %d fonts for %s DEFAULT_CHARSET\n",
3033 ansi_charset, symbol_charset, russian_charset,
3034 *font_name ? font_name : "<empty>");
3035 ok(efd.total > 0, "no fonts enumerated: %s DEFAULT_CHARSET\n", font_name);
3036 for (i = 0; i < efd.total; i++)
3037 {
3038 if (*font_name)
3039 ok(!strcmp(efd.lf[i].lfFaceName, font_name), "expected %s, got %s\n",
3040 font_name, efd.lf[i].lfFaceName);
3041 }
3042 if (*font_name)
3043 {
3044 switch (font_charset)
3045 {
3046 case ANSI_CHARSET:
3047 ok(ansi_charset > 0,
3048 "ANSI_CHARSET should enumerate ANSI_CHARSET for %s\n", font_name);
3049 ok(!symbol_charset,
3050 "ANSI_CHARSET should NOT enumerate SYMBOL_CHARSET for %s\n", font_name);
3051 ok(russian_charset > 0,
3052 "ANSI_CHARSET should enumerate RUSSIAN_CHARSET for %s\n", font_name);
3053 break;
3054 case SYMBOL_CHARSET:
3055 ok(!ansi_charset,
3056 "SYMBOL_CHARSET should NOT enumerate ANSI_CHARSET for %s\n", font_name);
3057 ok(symbol_charset,
3058 "SYMBOL_CHARSET should enumerate SYMBOL_CHARSET for %s\n", font_name);
3059 ok(!russian_charset,
3060 "SYMBOL_CHARSET should NOT enumerate RUSSIAN_CHARSET for %s\n", font_name);
3061 break;
3062 case DEFAULT_CHARSET:
3063 ok(ansi_charset > 0,
3064 "DEFAULT_CHARSET should enumerate ANSI_CHARSET for %s\n", font_name);
3065 ok(symbol_charset > 0,
3066 "DEFAULT_CHARSET should enumerate SYMBOL_CHARSET for %s\n", font_name);
3067 ok(russian_charset > 0,
3068 "DEFAULT_CHARSET should enumerate RUSSIAN_CHARSET for %s\n", font_name);
3069 break;
3070 }
3071 }
3072 else
3073 {
3074 ok(ansi_charset > 0,
3075 "DEFAULT_CHARSET should enumerate ANSI_CHARSET for %s\n", *font_name ? font_name : "<empty>");
3076 ok(symbol_charset > 0,
3077 "DEFAULT_CHARSET should enumerate SYMBOL_CHARSET for %s\n", *font_name ? font_name : "<empty>");
3078 ok(russian_charset > 0,
3079 "DEFAULT_CHARSET should enumerate RUSSIAN_CHARSET for %s\n", *font_name ? font_name : "<empty>");
3080 }
3081
3082 memset(&lf, 0, sizeof(lf));
3084 strcpy(lf.lfFaceName, font_name);
3085 efd.total = 0;
3086 SetLastError(0xdeadbeef);
3088 ok(ret, "EnumFontFamiliesEx error %u\n", GetLastError());
3089 get_charset_stats(&efd, &ansi_charset, &symbol_charset, &russian_charset);
3090 trace("enumerated ansi %d, symbol %d, russian %d fonts for %s SYMBOL_CHARSET\n",
3091 ansi_charset, symbol_charset, russian_charset,
3092 *font_name ? font_name : "<empty>");
3093 if (*font_name && font_charset == ANSI_CHARSET)
3094 ok(efd.total == 0, "no fonts should be enumerated: %s SYMBOL_CHARSET\n", font_name);
3095 else
3096 {
3097 ok(efd.total > 0, "no fonts enumerated: %s SYMBOL_CHARSET\n", font_name);
3098 for (i = 0; i < efd.total; i++)
3099 {
3100 ok(efd.lf[i].lfCharSet == SYMBOL_CHARSET, "%d: got charset %d\n", i, efd.lf[i].lfCharSet);
3101 if (*font_name)
3102 ok(!strcmp(efd.lf[i].lfFaceName, font_name), "expected %s, got %s\n",
3103 font_name, efd.lf[i].lfFaceName);
3104 }
3105
3106 ok(!ansi_charset,
3107 "SYMBOL_CHARSET should NOT enumerate ANSI_CHARSET for %s\n", *font_name ? font_name : "<empty>");
3108 ok(symbol_charset > 0,
3109 "SYMBOL_CHARSET should enumerate SYMBOL_CHARSET for %s\n", *font_name ? font_name : "<empty>");
3110 ok(!russian_charset,
3111 "SYMBOL_CHARSET should NOT enumerate RUSSIAN_CHARSET for %s\n", *font_name ? font_name : "<empty>");
3112 }
3113
3114 ReleaseDC(0, hdc);
3115
3116 heap_free( efd.lf );
3117 heap_free( efdw.lf );
3118}
3119
3121{
3122 const NEWTEXTMETRICEXA *ntm = (const NEWTEXTMETRICEXA *)tm;
3124 const DWORD valid_bits = 0x003f01ff;
3125 CHARSETINFO csi;
3126 DWORD fs;
3127
3128 if (type != TRUETYPE_FONTTYPE) return TRUE;
3129
3130 if (TranslateCharsetInfo(ULongToPtr(target->lfCharSet), &csi, TCI_SRCCHARSET)) {
3131 fs = ntm->ntmFontSig.fsCsb[0] & valid_bits;
3132 if ((fs & csi.fs.fsCsb[0]) && (fs & ~csi.fs.fsCsb[0]) && (fs & FS_LATIN1)) {
3133 *target = *lf;
3134 return FALSE;
3135 }
3136 }
3137
3138 return TRUE;
3139}
3140
3142{
3143 struct enum_font_data *efd = (struct enum_font_data *)lParam;
3144
3145 if (type != TRUETYPE_FONTTYPE) return 1;
3146
3147 if (efd->total >= efd->size)
3148 {
3149 efd->size = max( (efd->total + 1) * 2, 256 );
3150 efd->lf = heap_realloc( efd->lf, efd->size * sizeof(*efd->lf) );
3151 if (!efd->lf) return 0;
3152 }
3153 efd->lf[efd->total++] = *lf;
3154
3155 return 1;
3156}
3157
3159{
3160 struct enum_fullname_data *efnd = (struct enum_fullname_data *)lParam;
3161
3162 if (type != TRUETYPE_FONTTYPE) return 1;
3163
3164 if (efnd->total >= efnd->size)
3165 {
3166 efnd->size = max( (efnd->total + 1) * 2, 256 );
3167 efnd->elf = heap_realloc( efnd->elf, efnd->size * sizeof(*efnd->elf) );
3168 if (!efnd->elf) return 0;
3169 }
3170 efnd->elf[efnd->total++] = *(ENUMLOGFONTA *)lf;
3171
3172 return 1;
3173}
3174
3176{
3177 struct enum_font_data efd;
3178 LOGFONTA target, enum_font;
3179 UINT acp;
3180 HDC hdc;
3181 CHARSETINFO csi;
3182
3183 acp = GetACP();
3185 skip("TranslateCharsetInfo failed for code page %u.\n", acp);
3186 return;
3187 }
3188
3189 hdc = GetDC(0);
3190 memset(&enum_font, 0, sizeof(enum_font));
3191 enum_font.lfCharSet = csi.ciCharset;
3192 target.lfFaceName[0] = '\0';
3193 target.lfCharSet = csi.ciCharset;
3195 if (target.lfFaceName[0] == '\0') {
3196 skip("suitable font isn't found for charset %d.\n", enum_font.lfCharSet);
3197 return;
3198 }
3199 if (acp == 874 || acp == 1255 || acp == 1256) {
3200 /* these codepage use complex script, expecting ANSI_CHARSET here. */
3201 target.lfCharSet = ANSI_CHARSET;
3202 }
3203
3204 memset(&efd, 0, sizeof(efd));
3205 memset(&enum_font, 0, sizeof(enum_font));
3206 strcpy(enum_font.lfFaceName, target.lfFaceName);
3207 enum_font.lfCharSet = DEFAULT_CHARSET;
3208 EnumFontFamiliesExA(hdc, &enum_font, enum_font_data_proc, (LPARAM)&efd, 0);
3209 ReleaseDC(0, hdc);
3210
3211 trace("'%s' has %d charsets.\n", target.lfFaceName, efd.total);
3212 if (efd.total < 2)
3213 ok(0, "EnumFontFamilies is broken. Expected >= 2, got %d.\n", efd.total);
3214 else
3215 ok(efd.lf[0].lfCharSet == target.lfCharSet,
3216 "(%s) got charset %d expected %d\n",
3217 efd.lf[0].lfFaceName, efd.lf[0].lfCharSet, target.lfCharSet);
3218
3219 heap_free(efd.lf);
3220 return;
3221}
3222
3224{
3225 HFONT hfont, hfont_prev;
3226 DWORD ret;
3227 GLYPHMETRICS gm1, gm2;
3228 LOGFONTA lf2 = *lf;
3229 WORD idx;
3230
3231 if(!pGetGlyphIndicesA)
3232 return;
3233
3234 /* negative widths are handled just as positive ones */
3235 lf2.lfWidth = -lf->lfWidth;
3236
3237 SetLastError(0xdeadbeef);
3239 ok(hfont != 0, "CreateFontIndirect error %u\n", GetLastError());
3240 check_font("original", lf, hfont);
3241
3242 hfont_prev = SelectObject(hdc, hfont);
3243
3244 ret = pGetGlyphIndicesA(hdc, "x", 1, &idx, GGI_MARK_NONEXISTING_GLYPHS);
3245 if (ret == GDI_ERROR || idx == 0xffff)
3246 {
3247 SelectObject(hdc, hfont_prev);
3249 skip("Font %s doesn't contain 'x', skipping the test\n", lf->lfFaceName);
3250 return;
3251 }
3252
3253 /* filling with 0xaa causes false pass under WINEDEBUG=warn+heap */
3254 memset(&gm1, 0xab, sizeof(gm1));
3255 SetLastError(0xdeadbeef);
3256 ret = GetGlyphOutlineA(hdc, 'x', GGO_METRICS, &gm1, 0, NULL, &mat);
3257 ok(ret != GDI_ERROR, "GetGlyphOutline error 0x%x\n", GetLastError());
3258
3259 SelectObject(hdc, hfont_prev);
3261
3262 SetLastError(0xdeadbeef);
3263 hfont = CreateFontIndirectA(&lf2);
3264 ok(hfont != 0, "CreateFontIndirect error %u\n", GetLastError());
3265 check_font("negative width", &lf2, hfont);
3266
3267 hfont_prev = SelectObject(hdc, hfont);
3268
3269 memset(&gm2, 0xbb, sizeof(gm2));
3270 SetLastError(0xdeadbeef);
3271 ret = GetGlyphOutlineA(hdc, 'x', GGO_METRICS, &gm2, 0, NULL, &mat);
3272 ok(ret != GDI_ERROR, "GetGlyphOutline error 0x%x\n", GetLastError());
3273
3274 SelectObject(hdc, hfont_prev);
3276
3277 ok(gm1.gmBlackBoxX == gm2.gmBlackBoxX &&
3278 gm1.gmBlackBoxY == gm2.gmBlackBoxY &&
3279 gm1.gmptGlyphOrigin.x == gm2.gmptGlyphOrigin.x &&
3280 gm1.gmptGlyphOrigin.y == gm2.gmptGlyphOrigin.y &&
3281 gm1.gmCellIncX == gm2.gmCellIncX &&
3282 gm1.gmCellIncY == gm2.gmCellIncY,
3283 "gm1=%d,%d,%d,%d,%d,%d gm2=%d,%d,%d,%d,%d,%d\n",
3285 gm1.gmptGlyphOrigin.y, gm1.gmCellIncX, gm1.gmCellIncY,
3287 gm2.gmptGlyphOrigin.y, gm2.gmCellIncX, gm2.gmCellIncY);
3288}
3289
3290/* PANOSE is 10 bytes in size, need to pack the structure properly */
3291#include "pshpack2.h"
3292typedef struct
3293{
3315 CHAR achVendID[4];
3319 /* According to the Apple spec, original version didn't have the below fields,
3320 * version numbers were taken from the OpenType spec.
3321 */
3322 /* version 0 (TrueType 1.5) */
3328 /* version 1 (TrueType 1.66) */
3331 /* version 2 (OpenType 1.2) */
3337 /* version 4 (OpenType 1.6) */
3340} TT_OS2_V4;
3341#include "poppack.h"
3342
3343#define TT_OS2_V0_SIZE (FIELD_OFFSET(TT_OS2_V4, ulCodePageRange1))
3344
3345typedef struct
3346{
3349} cmap_header;
3350
3351typedef struct
3352{
3357
3358typedef struct
3359{
3363
3364 BYTE glyph_ids[256];
3366
3367typedef struct
3368{
3372
3377
3378 USHORT end_count[1]; /* this is a variable-sized array of length seg_countx2 / 2 */
3379/* Then follows:
3380 USHORT pad;
3381 USHORT start_count[seg_countx2 / 2];
3382 USHORT id_delta[seg_countx2 / 2];
3383 USHORT id_range_offset[seg_countx2 / 2];
3384 USHORT glyph_ids[];
3385*/
3387
3388typedef struct
3389{
3395
3396static void expect_ff(const TEXTMETRICA *tmA, const TT_OS2_V4 *os2, WORD family, const char *name)
3397{
3398 ok((tmA->tmPitchAndFamily & 0xf0) == family ||
3400 "%s: expected family %02x got %02x. panose %d-%d-%d-%d-...\n",
3401 name, family, tmA->tmPitchAndFamily, os2->panose.bFamilyType, os2->panose.bSerifStyle,
3402 os2->panose.bWeight, os2->panose.bProportion);
3403}
3404
3406{
3407 int i;
3409
3410 *first = 256;
3411
3412 for(i = 0; i < 256; i++)
3413 {
3414 if(cmap->glyph_ids[i] == 0) continue;
3415 *last = i;
3416 if(*first == 256) *first = i;
3417 }
3418 if(*first == 256) return FALSE;
3419 return TRUE;
3420}
3421
3422static void get_seg4(cmap_format_4 *cmap, USHORT seg_num, cmap_format_4_seg *seg)
3423{
3424 USHORT segs = GET_BE_WORD(cmap->seg_countx2) / 2;
3425 seg->end_count = GET_BE_WORD(cmap->end_count[seg_num]);
3426 seg->start_count = GET_BE_WORD(cmap->end_count[segs + 1 + seg_num]);
3427 seg->id_delta = GET_BE_WORD(cmap->end_count[2 * segs + 1 + seg_num]);
3428 seg->id_range_offset = GET_BE_WORD(cmap->end_count[3 * segs + 1 + seg_num]);
3429}
3430
3432{
3433 int i;
3435 USHORT seg_count = GET_BE_WORD(cmap->seg_countx2) / 2;
3436
3437 *first = 0x10000;
3438
3439 for(i = 0; i < seg_count; i++)
3440 {
3442
3443 get_seg4(cmap, i, &seg);
3444
3445 if(seg.start_count > 0xfffe) break;
3446
3447 if(*first == 0x10000) *first = seg.start_count;
3448
3449 *last = min(seg.end_count, 0xfffe);
3450 }
3451
3452 if(*first == 0x10000) return FALSE;
3453 return TRUE;
3454}
3455
3456static void *get_cmap(cmap_header *header, USHORT plat_id, USHORT enc_id)
3457{
3458 USHORT i;
3460
3461 for(i = 0; i < GET_BE_WORD(header->num_tables); i++)
3462 {
3463 if(GET_BE_WORD(record->plat_id) == plat_id && GET_BE_WORD(record->enc_id) == enc_id)
3464 return (BYTE *)header + GET_BE_DWORD(record->offset);
3465 record++;
3466 }
3467 return NULL;
3468}
3469
3470typedef enum
3471{
3476
3478{
3479 LONG size, ret;
3481 void *cmap;
3482 BOOL r = FALSE;
3483 WORD format;
3484
3485 size = GetFontData(hdc, MS_CMAP_TAG, 0, NULL, 0);
3486 ok(size != GDI_ERROR, "no cmap table found\n");
3487 if(size == GDI_ERROR) return FALSE;
3488
3491 ok(ret == size, "GetFontData should return %u not %u\n", size, ret);
3492 ok(GET_BE_WORD(header->version) == 0, "got cmap version %d\n", GET_BE_WORD(header->version));
3493
3494 cmap = get_cmap(header, 3, 1);
3495 if(cmap)
3497 else
3498 {
3499 cmap = get_cmap(header, 3, 0);
3500 if(cmap) *cmap_type = cmap_ms_symbol;
3501 }
3502 if(!cmap)
3503 {
3505 goto end;
3506 }
3507
3508 format = GET_BE_WORD(*(WORD *)cmap);
3509 switch(format)
3510 {
3511 case 0:
3513 break;
3514 case 4:
3516 break;
3517 default:
3518 trace("unhandled cmap format %d\n", format);
3519 break;
3520 }
3521
3522end:
3524 return r;
3525}
3526
3527#define TT_PLATFORM_APPLE_UNICODE 0
3528#define TT_PLATFORM_MACINTOSH 1
3529#define TT_PLATFORM_MICROSOFT 3
3530#define TT_APPLE_ID_DEFAULT 0
3531#define TT_APPLE_ID_ISO_10646 2
3532#define TT_APPLE_ID_UNICODE_2_0 3
3533#define TT_MS_ID_SYMBOL_CS 0
3534#define TT_MS_ID_UNICODE_CS 1
3535#define TT_MS_LANGID_ENGLISH_UNITED_STATES 0x0409
3536#define TT_NAME_ID_FONT_FAMILY 1
3537#define TT_NAME_ID_FONT_SUBFAMILY 2
3538#define TT_NAME_ID_UNIQUE_ID 3
3539#define TT_NAME_ID_FULL_NAME 4
3540#define TT_MAC_ID_SIMPLIFIED_CHINESE 25
3541
3542typedef struct sfnt_name
3543{
3551
3552static const LANGID mac_langid_table[] =
3553{
3554 MAKELANGID(LANG_ENGLISH,SUBLANG_DEFAULT), /* TT_MAC_LANGID_ENGLISH */
3555 MAKELANGID(LANG_FRENCH,SUBLANG_DEFAULT), /* TT_MAC_LANGID_FRENCH */
3556 MAKELANGID(LANG_GERMAN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_GERMAN */
3557 MAKELANGID(LANG_ITALIAN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_ITALIAN */
3558 MAKELANGID(LANG_DUTCH,SUBLANG_DEFAULT), /* TT_MAC_LANGID_DUTCH */
3559 MAKELANGID(LANG_SWEDISH,SUBLANG_DEFAULT), /* TT_MAC_LANGID_SWEDISH */
3560 MAKELANGID(LANG_SPANISH,SUBLANG_DEFAULT), /* TT_MAC_LANGID_SPANISH */
3561 MAKELANGID(LANG_DANISH,SUBLANG_DEFAULT), /* TT_MAC_LANGID_DANISH */
3562 MAKELANGID(LANG_PORTUGUESE,SUBLANG_DEFAULT), /* TT_MAC_LANGID_PORTUGUESE */
3563 MAKELANGID(LANG_NORWEGIAN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_NORWEGIAN */
3564 MAKELANGID(LANG_HEBREW,SUBLANG_DEFAULT), /* TT_MAC_LANGID_HEBREW */
3565 MAKELANGID(LANG_JAPANESE,SUBLANG_DEFAULT), /* TT_MAC_LANGID_JAPANESE */
3566 MAKELANGID(LANG_ARABIC,SUBLANG_DEFAULT), /* TT_MAC_LANGID_ARABIC */
3567 MAKELANGID(LANG_FINNISH,SUBLANG_DEFAULT), /* TT_MAC_LANGID_FINNISH */
3568 MAKELANGID(LANG_GREEK,SUBLANG_DEFAULT), /* TT_MAC_LANGID_GREEK */
3569 MAKELANGID(LANG_ICELANDIC,SUBLANG_DEFAULT), /* TT_MAC_LANGID_ICELANDIC */
3570 MAKELANGID(LANG_MALTESE,SUBLANG_DEFAULT), /* TT_MAC_LANGID_MALTESE */
3571 MAKELANGID(LANG_TURKISH,SUBLANG_DEFAULT), /* TT_MAC_LANGID_TURKISH */
3572 MAKELANGID(LANG_CROATIAN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_CROATIAN */
3573 MAKELANGID(LANG_CHINESE_TRADITIONAL,SUBLANG_DEFAULT), /* TT_MAC_LANGID_CHINESE_TRADITIONAL */
3574 MAKELANGID(LANG_URDU,SUBLANG_DEFAULT), /* TT_MAC_LANGID_URDU */
3575 MAKELANGID(LANG_HINDI,SUBLANG_DEFAULT), /* TT_MAC_LANGID_HINDI */
3576 MAKELANGID(LANG_THAI,SUBLANG_DEFAULT), /* TT_MAC_LANGID_THAI */
3577 MAKELANGID(LANG_KOREAN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_KOREAN */
3578 MAKELANGID(LANG_LITHUANIAN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_LITHUANIAN */
3579 MAKELANGID(LANG_POLISH,SUBLANG_DEFAULT), /* TT_MAC_LANGID_POLISH */
3580 MAKELANGID(LANG_HUNGARIAN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_HUNGARIAN */
3581 MAKELANGID(LANG_ESTONIAN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_ESTONIAN */
3582 MAKELANGID(LANG_LATVIAN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_LETTISH */
3583 MAKELANGID(LANG_SAMI,SUBLANG_DEFAULT), /* TT_MAC_LANGID_SAAMISK */
3584 MAKELANGID(LANG_FAEROESE,SUBLANG_DEFAULT), /* TT_MAC_LANGID_FAEROESE */
3585 MAKELANGID(LANG_FARSI,SUBLANG_DEFAULT), /* TT_MAC_LANGID_FARSI */
3586 MAKELANGID(LANG_RUSSIAN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_RUSSIAN */
3587 MAKELANGID(LANG_CHINESE_SIMPLIFIED,SUBLANG_DEFAULT), /* TT_MAC_LANGID_CHINESE_SIMPLIFIED */
3588 MAKELANGID(LANG_DUTCH,SUBLANG_DUTCH_BELGIAN), /* TT_MAC_LANGID_FLEMISH */
3589 MAKELANGID(LANG_IRISH,SUBLANG_DEFAULT), /* TT_MAC_LANGID_IRISH */
3590 MAKELANGID(LANG_ALBANIAN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_ALBANIAN */
3591 MAKELANGID(LANG_ROMANIAN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_ROMANIAN */
3592 MAKELANGID(LANG_CZECH,SUBLANG_DEFAULT), /* TT_MAC_LANGID_CZECH */
3593 MAKELANGID(LANG_SLOVAK,SUBLANG_DEFAULT), /* TT_MAC_LANGID_SLOVAK */
3594 MAKELANGID(LANG_SLOVENIAN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_SLOVENIAN */
3595 0, /* TT_MAC_LANGID_YIDDISH */
3596 MAKELANGID(LANG_SERBIAN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_SERBIAN */
3597 MAKELANGID(LANG_MACEDONIAN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_MACEDONIAN */
3598 MAKELANGID(LANG_BULGARIAN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_BULGARIAN */
3599 MAKELANGID(LANG_UKRAINIAN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_UKRAINIAN */
3600 MAKELANGID(LANG_BELARUSIAN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_BYELORUSSIAN */
3601 MAKELANGID(LANG_UZBEK,SUBLANG_DEFAULT), /* TT_MAC_LANGID_UZBEK */
3602 MAKELANGID(LANG_KAZAK,SUBLANG_DEFAULT), /* TT_MAC_LANGID_KAZAKH */
3603 MAKELANGID(LANG_AZERI,SUBLANG_AZERI_CYRILLIC), /* TT_MAC_LANGID_AZERBAIJANI */
3604 0, /* TT_MAC_LANGID_AZERBAIJANI_ARABIC_SCRIPT */
3605 MAKELANGID(LANG_ARMENIAN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_ARMENIAN */
3606 MAKELANGID(LANG_GEORGIAN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_GEORGIAN */
3607 0, /* TT_MAC_LANGID_MOLDAVIAN */
3608 MAKELANGID(LANG_KYRGYZ,SUBLANG_DEFAULT), /* TT_MAC_LANGID_KIRGHIZ */
3609 MAKELANGID(LANG_TAJIK,SUBLANG_DEFAULT), /* TT_MAC_LANGID_TAJIKI */
3610 MAKELANGID(LANG_TURKMEN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_TURKMEN */
3611 MAKELANGID(LANG_MONGOLIAN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_MONGOLIAN */
3612 MAKELANGID(LANG_MONGOLIAN,SUBLANG_MONGOLIAN_CYRILLIC_MONGOLIA), /* TT_MAC_LANGID_MONGOLIAN_CYRILLIC_SCRIPT */
3613 MAKELANGID(LANG_PASHTO,SUBLANG_DEFAULT), /* TT_MAC_LANGID_PASHTO */
3614 0, /* TT_MAC_LANGID_KURDISH */
3615 MAKELANGID(LANG_KASHMIRI,SUBLANG_DEFAULT), /* TT_MAC_LANGID_KASHMIRI */
3616 MAKELANGID(LANG_SINDHI,SUBLANG_DEFAULT), /* TT_MAC_LANGID_SINDHI */
3617 MAKELANGID(LANG_TIBETAN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_TIBETAN */
3618 MAKELANGID(LANG_NEPALI,SUBLANG_DEFAULT), /* TT_MAC_LANGID_NEPALI */
3619 MAKELANGID(LANG_SANSKRIT,SUBLANG_DEFAULT), /* TT_MAC_LANGID_SANSKRIT */
3620 MAKELANGID(LANG_MARATHI,SUBLANG_DEFAULT), /* TT_MAC_LANGID_MARATHI */
3621 MAKELANGID(LANG_BENGALI,SUBLANG_DEFAULT), /* TT_MAC_LANGID_BENGALI */
3622 MAKELANGID(LANG_ASSAMESE,SUBLANG_DEFAULT), /* TT_MAC_LANGID_ASSAMESE */
3623 MAKELANGID(LANG_GUJARATI,SUBLANG_DEFAULT), /* TT_MAC_LANGID_GUJARATI */
3624 MAKELANGID(LANG_PUNJABI,SUBLANG_DEFAULT), /* TT_MAC_LANGID_PUNJABI */
3625 MAKELANGID(LANG_ORIYA,SUBLANG_DEFAULT), /* TT_MAC_LANGID_ORIYA */
3626 MAKELANGID(LANG_MALAYALAM,SUBLANG_DEFAULT), /* TT_MAC_LANGID_MALAYALAM */
3627 MAKELANGID(LANG_KANNADA,SUBLANG_DEFAULT), /* TT_MAC_LANGID_KANNADA */
3628 MAKELANGID(LANG_TAMIL,SUBLANG_DEFAULT), /* TT_MAC_LANGID_TAMIL */
3629 MAKELANGID(LANG_TELUGU,SUBLANG_DEFAULT), /* TT_MAC_LANGID_TELUGU */
3630 MAKELANGID(LANG_SINHALESE,SUBLANG_DEFAULT), /* TT_MAC_LANGID_SINHALESE */
3631 0, /* TT_MAC_LANGID_BURMESE */
3632 MAKELANGID(LANG_KHMER,SUBLANG_DEFAULT), /* TT_MAC_LANGID_KHMER */
3633 MAKELANGID(LANG_LAO,SUBLANG_DEFAULT), /* TT_MAC_LANGID_LAO */
3634 MAKELANGID(LANG_VIETNAMESE,SUBLANG_DEFAULT), /* TT_MAC_LANGID_VIETNAMESE */
3635 MAKELANGID(LANG_INDONESIAN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_INDONESIAN */
3636 0, /* TT_MAC_LANGID_TAGALOG */
3637 MAKELANGID(LANG_MALAY,SUBLANG_DEFAULT), /* TT_MAC_LANGID_MALAY_ROMAN_SCRIPT */
3638 0, /* TT_MAC_LANGID_MALAY_ARABIC_SCRIPT */
3639 MAKELANGID(LANG_AMHARIC,SUBLANG_DEFAULT), /* TT_MAC_LANGID_AMHARIC */
3640 MAKELANGID(LANG_TIGRIGNA,SUBLANG_DEFAULT), /* TT_MAC_LANGID_TIGRINYA */
3641 0, /* TT_MAC_LANGID_GALLA */
3642 0, /* TT_MAC_LANGID_SOMALI */
3643 MAKELANGID(LANG_SWAHILI,SUBLANG_DEFAULT), /* TT_MAC_LANGID_SWAHILI */
3644 0, /* TT_MAC_LANGID_RUANDA */
3645 0, /* TT_MAC_LANGID_RUNDI */
3646 0, /* TT_MAC_LANGID_CHEWA */
3647 MAKELANGID(LANG_MALAGASY,SUBLANG_DEFAULT), /* TT_MAC_LANGID_MALAGASY */
3648 MAKELANGID(LANG_ESPERANTO,SUBLANG_DEFAULT), /* TT_MAC_LANGID_ESPERANTO */
3649 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 95-111 */
3650 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 112-127 */
3651 MAKELANGID(LANG_WELSH,SUBLANG_DEFAULT), /* TT_MAC_LANGID_WELSH */
3652 MAKELANGID(LANG_BASQUE,SUBLANG_DEFAULT), /* TT_MAC_LANGID_BASQUE */
3653 MAKELANGID(LANG_CATALAN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_CATALAN */
3654 0, /* TT_MAC_LANGID_LATIN */
3655 MAKELANGID(LANG_QUECHUA,SUBLANG_DEFAULT), /* TT_MAC_LANGID_QUECHUA */
3656 0, /* TT_MAC_LANGID_GUARANI */
3657 0, /* TT_MAC_LANGID_AYMARA */
3658 MAKELANGID(LANG_TATAR,SUBLANG_DEFAULT), /* TT_MAC_LANGID_TATAR */
3659 MAKELANGID(LANG_UIGHUR,SUBLANG_DEFAULT), /* TT_MAC_LANGID_UIGHUR */
3660 0, /* TT_MAC_LANGID_DZONGKHA */
3661 0, /* TT_MAC_LANGID_JAVANESE */
3662 0, /* TT_MAC_LANGID_SUNDANESE */
3663 MAKELANGID(LANG_GALICIAN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_GALICIAN */
3664 MAKELANGID(LANG_AFRIKAANS,SUBLANG_DEFAULT), /* TT_MAC_LANGID_AFRIKAANS */
3665 MAKELANGID(LANG_BRETON,SUBLANG_DEFAULT), /* TT_MAC_LANGID_BRETON */
3666 MAKELANGID(LANG_INUKTITUT,SUBLANG_DEFAULT), /* TT_MAC_LANGID_INUKTITUT */
3667 MAKELANGID(LANG_SCOTTISH_GAELIC,SUBLANG_DEFAULT), /* TT_MAC_LANGID_SCOTTISH_GAELIC */
3668 MAKELANGID(LANG_MANX_GAELIC,SUBLANG_DEFAULT), /* TT_MAC_LANGID_MANX_GAELIC */
3669 MAKELANGID(LANG_IRISH,SUBLANG_IRISH_IRELAND), /* TT_MAC_LANGID_IRISH_GAELIC */
3670 0, /* TT_MAC_LANGID_TONGAN */
3671 0, /* TT_MAC_LANGID_GREEK_POLYTONIC */
3672 MAKELANGID(LANG_GREENLANDIC,SUBLANG_DEFAULT), /* TT_MAC_LANGID_GREELANDIC */
3673 MAKELANGID(LANG_AZERI,SUBLANG_AZERI_LATIN), /* TT_MAC_LANGID_AZERBAIJANI_ROMAN_SCRIPT */
3674};
3675
3676static inline WORD get_mac_code_page( const sfnt_name *name )
3677{
3678 if (GET_BE_WORD(name->encoding_id) == TT_MAC_ID_SIMPLIFIED_CHINESE) return 10008; /* special case */
3679 return 10000 + GET_BE_WORD(name->encoding_id);
3680}
3681
3683{
3684 LANGID name_lang;
3685 int res = 0;
3686
3687 switch (GET_BE_WORD(name->platform_id))
3688 {
3690 res += 5; /* prefer the Microsoft name */
3691 switch (GET_BE_WORD(name->encoding_id))
3692 {
3694 case TT_MS_ID_SYMBOL_CS:
3695 name_lang = GET_BE_WORD(name->language_id);
3696 break;
3697 default:
3698 return 0;
3699 }
3700 break;
3702 if (!IsValidCodePage( get_mac_code_page( name ))) return 0;
3703 if (GET_BE_WORD(name->language_id) >= sizeof(mac_langid_table)/sizeof(mac_langid_table[0])) return 0;
3704 name_lang = mac_langid_table[GET_BE_WORD(name->language_id)];
3705 break;
3707 res += 2; /* prefer Unicode encodings */
3708 switch (GET_BE_WORD(name->encoding_id))
3709 {
3713 if (GET_BE_WORD(name->language_id) >= sizeof(mac_langid_table)/sizeof(mac_langid_table[0])) return 0;
3714 name_lang = mac_langid_table[GET_BE_WORD(name->language_id)];
3715 break;
3716 default:
3717 return 0;
3718 }
3719 break;
3720 default:
3721 return 0;
3722 }
3723 if (name_lang == lang) res += 30;
3724 else if (PRIMARYLANGID( name_lang ) == PRIMARYLANGID( lang )) res += 20;
3725 else if (name_lang == MAKELANGID( LANG_ENGLISH, SUBLANG_DEFAULT )) res += 10;
3726 return res;
3727}
3728
3729static BOOL get_ttf_nametable_entry(HDC hdc, WORD name_id, WCHAR *out_buf, SIZE_T out_size, LCID language_id)
3730{
3731 struct sfnt_name_header
3732 {
3733 USHORT format;
3734 USHORT number_of_record;
3735 USHORT storage_offset;
3736 } *header;
3738 BOOL r = FALSE;
3740 LONG c, ret;
3741 WCHAR *name;
3742 BYTE *data;
3743 USHORT i;
3744 int res, best_lang = 0, best_index = -1;
3745
3746 size = GetFontData(hdc, MS_NAME_TAG, 0, NULL, 0);
3747 ok(size != GDI_ERROR, "no name table found\n");
3748 if(size == GDI_ERROR) return FALSE;
3749
3752 ok(ret == size, "GetFontData should return %u not %u\n", size, ret);
3753
3754 header = (void *)data;
3755 header->format = GET_BE_WORD(header->format);
3756 header->number_of_record = GET_BE_WORD(header->number_of_record);
3757 header->storage_offset = GET_BE_WORD(header->storage_offset);
3758 if (header->format != 0)
3759 {
3760 trace("got format %u\n", header->format);
3761 goto out;
3762 }
3763 if (header->number_of_record == 0 || sizeof(*header) + header->number_of_record * sizeof(*entry) > size)
3764 {
3765 trace("number records out of range: %d\n", header->number_of_record);
3766 goto out;
3767 }
3768 if (header->storage_offset >= size)
3769 {
3770 trace("storage_offset %u > size %u\n", header->storage_offset, size);
3771 goto out;
3772 }
3773
3774 entry = (void *)&header[1];
3775 for (i = 0; i < header->number_of_record; i++)
3776 {
3777 if (GET_BE_WORD(entry[i].name_id) != name_id) continue;
3778 res = match_name_table_language( &entry[i], language_id);
3779 if (res > best_lang)
3780 {
3781 best_lang = res;
3782 best_index = i;
3783 }
3784 }
3785
3786 offset = header->storage_offset + GET_BE_WORD(entry[best_index].offset);
3787 length = GET_BE_WORD(entry[best_index].length);
3788 if (offset + length > size)
3789 {
3790 trace("entry %d is out of range\n", best_index);
3791 goto out;
3792 }
3793 if (length >= out_size)
3794 {
3795 trace("buffer too small for entry %d\n", best_index);
3796 goto out;
3797 }
3798
3799 name = (WCHAR *)(data + offset);
3800 for (c = 0; c < length / 2; c++)
3801 out_buf[c] = GET_BE_WORD(name[c]);
3802 out_buf[c] = 0;
3803
3804 r = TRUE;
3805
3806out:
3808 return r;
3809}
3810
3811static void test_text_metrics(const LOGFONTA *lf, const NEWTEXTMETRICA *ntm)
3812{
3813 HDC hdc;
3814 HFONT hfont, hfont_old;
3815 TEXTMETRICA tmA;
3816 TT_OS2_V4 tt_os2;
3817 LONG size, ret;
3818 const char *font_name = lf->lfFaceName;
3819 DWORD cmap_first = 0, cmap_last = 0;
3820 UINT ascent, descent, cell_height;
3822 BOOL sys_lang_non_english;
3823
3824 sys_lang_non_english = PRIMARYLANGID(GetSystemDefaultLangID()) != LANG_ENGLISH;
3825 hdc = GetDC(0);
3826
3827 SetLastError(0xdeadbeef);
3829 ok(hfont != 0, "CreateFontIndirect error %u\n", GetLastError());
3830
3831 hfont_old = SelectObject(hdc, hfont);
3832
3833 size = GetFontData(hdc, MS_OS2_TAG, 0, NULL, 0);
3834 if (size == GDI_ERROR)
3835 {
3836 trace("OS/2 chunk was not found\n");
3837 goto end_of_test;
3838 }
3839 if (size > sizeof(tt_os2))
3840 {
3841 trace("got too large OS/2 chunk of size %u\n", size);
3842 size = sizeof(tt_os2);
3843 }
3844
3845 memset(&tt_os2, 0, sizeof(tt_os2));
3846 ret = GetFontData(hdc, MS_OS2_TAG, 0, &tt_os2, size);
3847 ok(ret >= TT_OS2_V0_SIZE && ret <= size, "GetFontData should return size from [%u,%u] not %u\n", TT_OS2_V0_SIZE,
3848 size, ret);
3849
3850 SetLastError(0xdeadbeef);
3851 ret = GetTextMetricsA(hdc, &tmA);
3852 ok(ret, "GetTextMetricsA error %u\n", GetLastError());
3853
3854 if(!get_first_last_from_cmap(hdc, &cmap_first, &cmap_last, &cmap_type))
3855 {
3856 skip("%s is not a Windows font, OS/2 metrics may be invalid.\n",font_name);
3857 }
3858 else
3859 {
3860 USHORT expect_first_A, expect_last_A, expect_break_A, expect_default_A;
3861 USHORT expect_first_W, expect_last_W, expect_break_W, expect_default_W;
3862 UINT os2_first_char, os2_last_char, default_char, break_char;
3864 TEXTMETRICW tmW;
3865
3866 ascent = GET_BE_WORD(tt_os2.usWinAscent);
3867 descent = abs((SHORT)GET_BE_WORD(tt_os2.usWinDescent));
3868 cell_height = ascent + descent;
3869 ok(ntm->ntmCellHeight == cell_height, "%s: ntmCellHeight %u != %u, os2.usWinAscent/os2.usWinDescent %u/%u\n",
3870 font_name, ntm->ntmCellHeight, cell_height, ascent, descent);
3871
3872 version = GET_BE_WORD(tt_os2.version);
3873
3874 os2_first_char = GET_BE_WORD(tt_os2.usFirstCharIndex);
3875 os2_last_char = GET_BE_WORD(tt_os2.usLastCharIndex);
3876 default_char = GET_BE_WORD(tt_os2.usDefaultChar);
3877 break_char = GET_BE_WORD(tt_os2.usBreakChar);
3878
3879 if (winetest_debug > 1)
3880 trace("font %s charset %u: %x-%x (%x-%x) default %x break %x OS/2 version %u vendor %4.4s\n",
3881 font_name, lf->lfCharSet, os2_first_char, os2_last_char, cmap_first, cmap_last,
3882 default_char, break_char, version, (LPCSTR)&tt_os2.achVendID);
3883
3884 if (cmap_type == cmap_ms_symbol || (cmap_first >= 0xf000 && cmap_first < 0xf100))
3885 {
3886 expect_first_W = 0;
3887 switch(GetACP())
3888 {
3889 case 1255: /* Hebrew */
3890 expect_last_W = 0xf896;
3891 break;
3892 case 1257: /* Baltic */
3893 expect_last_W = 0xf8fd;
3894 break;
3895 default:
3896 expect_last_W = 0xf0ff;
3897 }
3898 expect_break_W = 0x20;
3899 expect_default_W = expect_break_W - 1;
3900 expect_first_A = 0x1e;
3901 expect_last_A = min(os2_last_char - os2_first_char + 0x20, 0xff);
3902 }
3903 else
3904 {
3905 expect_first_W = cmap_first;
3906 expect_last_W = cmap_last;
3907 if(os2_first_char <= 1)
3908 expect_break_W = os2_first_char + 2;
3909 else if(os2_first_char > 0xff)
3910 expect_break_W = 0x20;
3911 else
3912 expect_break_W = os2_first_char;
3913 expect_default_W = expect_break_W - 1;
3914 expect_first_A = expect_default_W - 1;
3915 expect_last_A = min(expect_last_W, 0xff);
3916 }
3917 expect_break_A = expect_break_W;
3918 expect_default_A = expect_default_W;
3919
3920 /* Wine currently uses SYMBOL_CHARSET to identify whether the ANSI metrics need special handling */
3921 todo_wine_if(cmap_type != cmap_ms_symbol && tmA.tmCharSet == SYMBOL_CHARSET && expect_first_A != 0x1e)
3922 ok(tmA.tmFirstChar == expect_first_A ||
3923 tmA.tmFirstChar == expect_first_A + 1 /* win9x */,
3924 "A: tmFirstChar for %s got %02x expected %02x\n", font_name, tmA.tmFirstChar, expect_first_A);
3925 if (pGdiGetCodePage == NULL || ! IsDBCSLeadByteEx(pGdiGetCodePage(hdc), tmA.tmLastChar))
3926 ok(tmA.tmLastChar == expect_last_A ||
3927 tmA.tmLastChar == 0xff /* win9x */,
3928 "A: tmLastChar for %s got %02x expected %02x\n", font_name, tmA.tmLastChar, expect_last_A);
3929 else
3930 skip("tmLastChar is DBCS lead byte\n");
3931 ok(tmA.tmBreakChar == expect_break_A, "A: tmBreakChar for %s got %02x expected %02x\n",
3932 font_name, tmA.tmBreakChar, expect_break_A);
3933 ok(tmA.tmDefaultChar == expect_default_A || broken(sys_lang_non_english),
3934 "A: tmDefaultChar for %s got %02x expected %02x\n",
3935 font_name, tmA.tmDefaultChar, expect_default_A);
3936
3937
3938 SetLastError(0xdeadbeef);
3939 ret = GetTextMetricsW(hdc, &tmW);
3941 "GetTextMetricsW error %u\n", GetLastError());
3942 if (ret)
3943 {
3944 /* Wine uses the os2 first char */
3945 todo_wine_if(cmap_first != os2_first_char && cmap_type != cmap_ms_symbol)
3946 ok(tmW.tmFirstChar == expect_first_W, "W: tmFirstChar for %s got %02x expected %02x\n",
3947 font_name, tmW.tmFirstChar, expect_first_W);
3948
3949 /* Wine uses the os2 last char */
3950 todo_wine_if(expect_last_W != os2_last_char && cmap_type != cmap_ms_symbol)
3951 ok(tmW.tmLastChar == expect_last_W, "W: tmLastChar for %s got %02x expected %02x\n",
3952 font_name, tmW.tmLastChar, expect_last_W);
3953 ok(tmW.tmBreakChar == expect_break_W, "W: tmBreakChar for %s got %02x expected %02x\n",
3954 font_name, tmW.tmBreakChar, expect_break_W);
3955 ok(tmW.tmDefaultChar == expect_default_W || broken(sys_lang_non_english),
3956 "W: tmDefaultChar for %s got %02x expected %02x\n",
3957 font_name, tmW.tmDefaultChar, expect_default_W);
3958
3959 /* Test the aspect ratio while we have tmW */
3961 ok(tmW.tmDigitizedAspectX == ret, "W: tmDigitizedAspectX %u != %u\n",
3962 tmW.tmDigitizedAspectX, ret);
3964 ok(tmW.tmDigitizedAspectX == ret, "W: tmDigitizedAspectY %u != %u\n",
3965 tmW.tmDigitizedAspectX, ret);
3966 }
3967 }
3968
3969 /* test FF_ values */
3970 switch(tt_os2.panose.bFamilyType)
3971 {
3972 case PAN_ANY:
3973 case PAN_NO_FIT:
3976 default:
3977 if((tmA.tmPitchAndFamily & 1) == 0 || /* fixed */
3979 {
3980 expect_ff(&tmA, &tt_os2, FF_MODERN, font_name);
3981 break;
3982 }
3983 switch(tt_os2.panose.bSerifStyle)
3984 {
3985 case PAN_ANY:
3986 case PAN_NO_FIT:
3987 default:
3988 expect_ff(&tmA, &tt_os2, FF_DONTCARE, font_name);
3989 break;
3990
3991 case PAN_SERIF_COVE:
3995 case PAN_SERIF_SQUARE:
3996 case PAN_SERIF_THIN:
3997 case PAN_SERIF_BONE:
3999 case PAN_SERIF_TRIANGLE:
4000 expect_ff(&tmA, &tt_os2, FF_ROMAN, font_name);
4001 break;
4002
4006 case PAN_SERIF_FLARED:
4007 case PAN_SERIF_ROUNDED:
4008 expect_ff(&tmA, &tt_os2, FF_SWISS, font_name);
4009 break;
4010 }
4011 break;
4012
4013 case PAN_FAMILY_SCRIPT:
4014 expect_ff(&tmA, &tt_os2, FF_SCRIPT, font_name);
4015 break;
4016
4018 expect_ff(&tmA, &tt_os2, FF_DECORATIVE, font_name);
4019 break;
4020 }
4021
4023
4024end_of_test:
4025 SelectObject(hdc, hfont_old);
4027
4028 ReleaseDC(0, hdc);
4029}
4030
4032{
4033 INT *enumed = (INT *)lParam;
4034
4035 if (type == TRUETYPE_FONTTYPE)
4036 {
4037 (*enumed)++;
4038 test_text_metrics(lf, (const NEWTEXTMETRICA *)ntm);
4039 }
4040 return 1;
4041}
4042
4043static void test_GetTextMetrics(void)
4044{
4045 LOGFONTA lf;
4046 HDC hdc;
4047 INT enumed;
4048
4049 /* Report only once */
4050 if(!pGetGlyphIndicesA)
4051 win_skip("GetGlyphIndicesA is unavailable, negative width will not be checked\n");
4052
4053 hdc = GetDC(0);
4054
4055 memset(&lf, 0, sizeof(lf));
4057 enumed = 0;
4059 trace("Tested metrics of %d truetype fonts\n", enumed);
4060
4061 ReleaseDC(0, hdc);
4062}
4063
4064static void test_nonexistent_font(void)
4065{
4066 static const struct
4067 {
4068 const char *name;
4069 int charset;
4070 } font_subst[] =
4071 {
4072 { "Times New Roman Baltic", 186 },
4073 { "Times New Roman CE", 238 },
4074 { "Times New Roman CYR", 204 },
4075 { "Times New Roman Greek", 161 },
4076 { "Times New Roman TUR", 162 }
4077 };
4078 static const struct
4079 {
4080 const char *name;
4081 int charset;
4082 } shell_subst[] =
4083 {
4084 { "MS Shell Dlg", 186 },
4085 { "MS Shell Dlg", 238 },
4086 { "MS Shell Dlg", 204 },
4087 { "MS Shell Dlg", 161 },
4088 { "MS Shell Dlg", 162 }
4089 };
4090 LOGFONTA lf;
4091 HDC hdc;
4092 HFONT hfont;
4093 CHARSETINFO csi;
4094 INT cs, expected_cs, i, ret;
4095 char buf[LF_FACESIZE];
4096
4097 expected_cs = GetACP();
4098 if (!TranslateCharsetInfo(ULongToPtr(expected_cs), &csi, TCI_SRCCODEPAGE))
4099 {
4100 skip("TranslateCharsetInfo failed for code page %d\n", expected_cs);
4101 return;
4102 }
4103 expected_cs = csi.ciCharset;
4104 trace("ACP %d -> charset %d\n", GetACP(), expected_cs);
4105
4107
4108 for (i = 0; i < sizeof(shell_subst)/sizeof(shell_subst[0]); i++)
4109 {
4110 ret = is_font_installed(shell_subst[i].name);
4111 ok(ret || broken(!ret) /* win2000 */, "%s should be enumerated\n", shell_subst[i].name);
4112 ret = is_truetype_font_installed(shell_subst[i].name);
4113 ok(ret || broken(!ret) /* win2000 */, "%s should be enumerated\n", shell_subst[i].name);
4114
4115 memset(&lf, 0, sizeof(lf));
4116 lf.lfHeight = -13;
4117 lf.lfWeight = FW_REGULAR;
4118 strcpy(lf.lfFaceName, shell_subst[i].name);
4121 GetTextFaceA(hdc, sizeof(buf), buf);
4122 ok(!lstrcmpiA(buf, shell_subst[i].name), "expected %s, got %s\n", shell_subst[i].name, buf);
4124 ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d for font %s\n", cs, shell_subst[i].name);
4125
4127
4128 memset(&lf, 0, sizeof(lf));
4129 lf.lfHeight = -13;
4130 lf.lfWeight = FW_DONTCARE;
4131 strcpy(lf.lfFaceName, shell_subst[i].name);
4134 GetTextFaceA(hdc, sizeof(buf), buf);
4135 ok(!lstrcmpiA(buf, shell_subst[i].name), "expected %s, got %s\n", shell_subst[i].name, buf);
4137 ok(cs == expected_cs || cs == ANSI_CHARSET, "expected %d, got %d for font %s\n", expected_cs, cs, shell_subst[i].name);
4139 }
4140
4141 if (!is_truetype_font_installed("Arial") ||
4142 !is_truetype_font_installed("Times New Roman"))
4143 {
4144 DeleteDC(hdc);
4145 skip("Arial or Times New Roman not installed\n");
4146 return;
4147 }
4148
4149 memset(&lf, 0, sizeof(lf));
4150 lf.lfHeight = 100;
4151 lf.lfWeight = FW_REGULAR;
4154 strcpy(lf.lfFaceName, "Nonexistent font");
4157 GetTextFaceA(hdc, sizeof(buf), buf);
4158 ok(!lstrcmpiA(buf, "Arial"), "Got %s\n", buf);
4160 ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d\n", cs);
4162
4163 memset(&lf, 0, sizeof(lf));
4164 lf.lfHeight = -13;
4165 lf.lfWeight = FW_DONTCARE;
4166 strcpy(lf.lfFaceName, "Nonexistent font");
4169 GetTextFaceA(hdc, sizeof(buf), buf);
4170todo_wine /* Wine uses Arial for all substitutions */
4171 ok(!lstrcmpiA(buf, "Nonexistent font") /* XP, Vista */ ||
4172 !lstrcmpiA(buf, "MS Serif") || /* Win9x */
4173 !lstrcmpiA(buf, "MS Sans Serif"), /* win2k3 */
4174 "Got %s\n", buf);
4176 ok(cs == expected_cs || cs == ANSI_CHARSET, "expected %d, got %d\n", expected_cs, cs);
4178
4179 memset(&lf, 0, sizeof(lf));
4180 lf.lfHeight = -13;
4181 lf.lfWeight = FW_REGULAR;
4182 strcpy(lf.lfFaceName, "Nonexistent font");
4185 GetTextFaceA(hdc, sizeof(buf), buf);
4186 ok(!lstrcmpiA(buf, "Arial") /* XP, Vista */ ||
4187 !lstrcmpiA(buf, "Times New Roman") /* Win9x */, "Got %s\n", buf);
4189 ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d\n", cs);
4191
4192 memset(&lf, 0, sizeof(lf));
4193 lf.lfHeight = -13;
4194 lf.lfWeight = FW_DONTCARE;
4195 strcpy(lf.lfFaceName, "Times New Roman");
4198 GetTextFaceA(hdc, sizeof(buf), buf);
4199 ok(!lstrcmpiA(buf, "Times New Roman"), "Got %s\n", buf);
4201 ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d\n", cs);
4203
4204 for (i = 0; i < sizeof(font_subst)/sizeof(font_subst[0]); i++)
4205 {
4206 ret = is_font_installed(font_subst[i].name);
4208 ok(ret || broken(!ret && !i) /* win2000 doesn't have Times New Roman Baltic substitution */,
4209 "%s should be enumerated\n", font_subst[i].name);
4210 ret = is_truetype_font_installed(font_subst[i].name);
4212 ok(ret || broken(!ret && !i) /* win2000 doesn't have Times New Roman Baltic substitution */,
4213 "%s should be enumerated\n", font_subst[i].name);
4214
4215 memset(&lf, 0, sizeof(lf));
4216 lf.lfHeight = -13;
4217 lf.lfWeight = FW_REGULAR;
4218 strcpy(lf.lfFaceName, font_subst[i].name);
4222 if (font_subst[i].charset == expected_cs)
4223 {
4224 ok(cs == expected_cs, "expected %d, got %d for font %s\n", expected_cs, cs, font_subst[i].name);
4225 GetTextFaceA(hdc, sizeof(buf), buf);
4226 ok(!lstrcmpiA(buf, font_subst[i].name), "expected %s, got %s\n", font_subst[i].name, buf);
4227 }
4228 else
4229 {
4230 ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d for font %s\n", cs, font_subst[i].name);
4231 GetTextFaceA(hdc, sizeof(buf), buf);
4232 ok(!lstrcmpiA(buf, "Arial") /* XP, Vista */ ||
4233 !lstrcmpiA(buf, "Times New Roman") /* Win9x */, "got %s for font %s\n", buf, font_subst[i].name);
4234 }
4236
4237 memset(&lf, 0, sizeof(lf));
4238 lf.lfHeight = -13;
4239 lf.lfWeight = FW_DONTCARE;
4240 strcpy(lf.lfFaceName, font_subst[i].name);
4243 GetTextFaceA(hdc, sizeof(buf), buf);
4244 ok(!lstrcmpiA(buf, "Arial") /* Wine */ ||
4245 !lstrcmpiA(buf, font_subst[i].name) /* XP, Vista */ ||
4246 !lstrcmpiA(buf, "MS Serif") /* Win9x */ ||
4247 !lstrcmpiA(buf, "MS Sans Serif"), /* win2k3 */
4248 "got %s for font %s\n", buf, font_subst[i].name);
4250 ok(cs == expected_cs || cs == ANSI_CHARSET, "expected %d, got %d for font %s\n", expected_cs, cs, font_subst[i].name);
4252 }
4253
4254 DeleteDC(hdc);
4255}
4256
4257static void test_RealizationInfo(void)
4258{
4259 struct font_realization_info {
4260 DWORD size;
4261 DWORD flags;
4262 DWORD cache_num;
4263 DWORD instance_id;
4264 DWORD unk;
4265 WORD face_index;
4266 WORD simulations;
4267 };
4268
4269 struct realization_info_t
4270 {
4271 DWORD flags;
4272 DWORD cache_num;
4273 DWORD instance_id;
4274 };
4275
4276 HDC hdc;
4277 DWORD info[4], info2[10];
4278 BOOL r, have_file = FALSE;
4279 HFONT hfont, hfont_old;
4280 LOGFONTA lf;
4281 DWORD needed, read;
4282 HANDLE h;
4283 BYTE file[16], data[14];
4284 struct file_info
4285 {
4286 FILETIME time;
4289 } file_info;
4290 FILETIME time;
4292
4293 if(!pGdiRealizationInfo)
4294 {
4295 win_skip("GdiRealizationInfo not available\n");
4296 return;
4297 }
4298
4299 hdc = GetDC(0);
4300
4301 memset(info, 0xcc, sizeof(info));
4302 r = pGdiRealizationInfo(hdc, info);
4303 ok(r != 0, "ret 0\n");
4304 ok((info[0] & 0xf) == 1, "info[0] = %x for the system font\n", info[0]);
4305 ok(info[3] == 0xcccccccc, "structure longer than 3 dwords\n");
4306
4307 if (!is_truetype_font_installed("Tahoma"))
4308 {
4309 skip("skipping GdiRealizationInfo with truetype font\n");
4310 goto end;
4311 }
4312
4313 memset(&lf, 0, sizeof(lf));
4314 strcpy(lf.lfFaceName, "Tahoma");
4315 lf.lfHeight = 20;
4316 lf.lfWeight = FW_BOLD;
4317 lf.lfItalic = 1;
4319 hfont_old = SelectObject(hdc, hfont);
4320
4321 memset(info, 0xcc, sizeof(info));
4322 r = pGdiRealizationInfo(hdc, info);
4323 ok(r != 0, "ret 0\n");
4324 ok((info[0] & 0xf) == 3, "info[0] = %x for arial\n", info[0]);
4325 ok(info[3] == 0xcccccccc, "structure longer than 3 dwords\n");
4326
4327 if (pGetFontRealizationInfo)
4328 {
4329 struct font_realization_info *fri = (struct font_realization_info*)info2;
4330 struct realization_info_t *ri = (struct realization_info_t*)info;
4331
4332 /* The first DWORD represents a struct size. On a
4333 newly rebooted system setting this to < 16 results
4334 in GetFontRealizationInfo failing. However there
4335 appears to be some caching going on which results
4336 in calls after a successful call also succeeding even
4337 if the size < 16. This means we can't reliably test
4338 this behaviour. */
4339
4340 memset(info2, 0xcc, sizeof(info2));
4341 info2[0] = 16;
4342 r = pGetFontRealizationInfo(hdc, info2);
4343 ok(r != 0, "ret 0\n");
4344 /* We may get the '24' version here if that has been previously
4345 requested. */
4346 ok(fri->size == 16 || fri->size == 24, "got %d\n", info2[0]);
4347 ok(fri->flags == ri->flags, "flags mismatch\n");
4348 ok(fri->cache_num == ri->cache_num, "cache_num mismatch\n");
4349 ok(fri->instance_id == ri->instance_id, "instance id mismatch\n");
4350 ok(info2[6] == 0xcccccccc, "got wrong dword 6, 0x%08x\n", info2[6]);
4351
4352 memset(info2, 0xcc, sizeof(info2));
4353 info2[0] = 28;
4354 r = pGetFontRealizationInfo(hdc, info2);
4355 ok(r == FALSE, "got %d\n", r);
4356
4357 memset(info2, 0xcc, sizeof(info2));
4358 info2[0] = 24;
4359 r = pGetFontRealizationInfo(hdc, info2);
4360 ok(r != 0, "ret 0\n");
4361 ok(fri->size == 24, "got %d\n", fri->size);
4362 ok(fri->flags == ri->flags, "flags mismatch\n");
4363 ok(fri->cache_num == ri->cache_num, "cache_num mismatch\n");
4364 ok(fri->instance_id == ri->instance_id, "instance id mismatch\n");
4365 ok(fri->simulations == 0x2, "got simulations flags 0x%04x\n", fri->simulations);
4366 ok(fri->face_index == 0, "got wrong face index %u\n", fri->face_index);
4367 ok(info2[6] == 0xcccccccc, "structure longer than 6 dwords\n");
4368
4369 /* Test GetFontFileInfo() */
4370 /* invalid font id */
4371 SetLastError(0xdeadbeef);
4372 r = pGetFontFileInfo(0xabababab, 0, &file_info, sizeof(file_info), &needed);
4373 ok(r == 0 && GetLastError() == ERROR_INVALID_PARAMETER, "ret %d gle %d\n", r, GetLastError());
4374
4375 needed = 0;
4376 r = pGetFontFileInfo(fri->instance_id, 0, &file_info, sizeof(file_info), &needed);
4377 ok(r != 0 || GetLastError() == ERROR_NOACCESS, "ret %d gle %d\n", r, GetLastError());
4378
4379 if (r)
4380 {
4381 ok(needed > 0 && needed < sizeof(file_info), "got needed size %u\n", needed);
4382
4384 ok(h != INVALID_HANDLE_VALUE, "Unable to open file %d\n", GetLastError());
4385
4386 GetFileTime(h, NULL, NULL, &time);
4387 ok(!CompareFileTime(&file_info.time, &time), "time mismatch\n");
4388 GetFileSizeEx(h, &size);
4389 ok(file_info.size.QuadPart == size.QuadPart, "size mismatch\n");
4390
4391 /* Read first 16 bytes from the file */
4392 ReadFile(h, file, sizeof(file), &read, NULL);
4393 CloseHandle(h);
4394 have_file = TRUE;
4395
4396 /* shorter buffer */
4397 SetLastError(0xdeadbeef);
4398 r = pGetFontFileInfo(fri->instance_id, 0, &file_info, needed - 1, &needed);
4399 ok(r == 0 && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "ret %d gle %d\n", r, GetLastError());
4400 }
4401
4402 if (pGetFontFileData) {
4403 /* Get bytes 2 - 16 using GetFontFileData */
4404 r = pGetFontFileData(fri->instance_id, 0, 2, data, sizeof(data));
4405 ok(r != 0, "ret 0 gle %d\n", GetLastError());
4406
4407 if (have_file)
4408 ok(!memcmp(data, file + 2, sizeof(data)), "mismatch\n");
4409 else
4410 win_skip("GetFontFileInfo() failed, skipping\n");
4411 }
4412 }
4413
4414 DeleteObject(SelectObject(hdc, hfont_old));
4415
4416 end:
4417 ReleaseDC(0, hdc);
4418}
4419
4420/* Tests on XP SP2 show that the ANSI version of GetTextFace does NOT include
4421 the nul in the count of characters copied when the face name buffer is not
4422 NULL, whereas it does if the buffer is NULL. Further, the Unicode version
4423 always includes it. */
4424static void test_GetTextFace(void)
4425{
4426 static const char faceA[] = "Tahoma";
4427 static const WCHAR faceW[] = {'T','a','h','o','m','a', 0};
4428 LOGFONTA fA = {0};
4429 LOGFONTW fW = {0};
4430 char bufA[LF_FACESIZE];
4431 WCHAR bufW[LF_FACESIZE];
4432 HFONT f, g;
4433 HDC dc;
4434 int n;
4435
4436 if(!is_font_installed("Tahoma"))
4437 {
4438 skip("Tahoma is not installed so skipping this test\n");
4439 return;
4440 }
4441
4442 /* 'A' case. */
4443 memcpy(fA.lfFaceName, faceA, sizeof faceA);
4444 f = CreateFontIndirectA(&fA);
4445 ok(f != NULL, "CreateFontIndirectA failed\n");
4446
4447 dc = GetDC(NULL);
4448 g = SelectObject(dc, f);
4449 n = GetTextFaceA(dc, sizeof bufA, bufA);
4450 ok(n == sizeof faceA - 1, "GetTextFaceA returned %d\n", n);
4451 ok(lstrcmpA(faceA, bufA) == 0, "GetTextFaceA\n");
4452
4453 /* Play with the count arg. */
4454 bufA[0] = 'x';
4455 n = GetTextFaceA(dc, 0, bufA);
4456 ok(n == 0, "GetTextFaceA returned %d\n", n);
4457 ok(bufA[0] == 'x', "GetTextFaceA buf[0] == %d\n", bufA[0]);
4458
4459 bufA[0] = 'x';
4460 n = GetTextFaceA(dc, 1, bufA);
4461 ok(n == 0, "GetTextFaceA returned %d\n", n);
4462 ok(bufA[0] == '\0', "GetTextFaceA buf[0] == %d\n", bufA[0]);
4463
4464 bufA[0] = 'x'; bufA[1] = 'y';
4465 n = GetTextFaceA(dc, 2, bufA);
4466 ok(n == 1, "GetTextFaceA returned %d\n", n);
4467 ok(bufA[0] == faceA[0] && bufA[1] == '\0', "GetTextFaceA didn't copy\n");
4468
4469 n = GetTextFaceA(dc, 0, NULL);
4470 ok(n == sizeof faceA ||
4471 broken(n == 0), /* win98, winMe */
4472 "GetTextFaceA returned %d\n", n);
4473
4475 ReleaseDC(NULL, dc);
4476
4477 /* 'W' case. */
4478 memcpy(fW.lfFaceName, faceW, sizeof faceW);
4479 SetLastError(0xdeadbeef);
4480 f = CreateFontIndirectW(&fW);
4482 {
4483 win_skip("CreateFontIndirectW is not implemented\n");
4484 return;
4485 }
4486 ok(f != NULL, "CreateFontIndirectW failed\n");
4487
4488 dc = GetDC(NULL);
4489 g = SelectObject(dc, f);
4490 n = GetTextFaceW(dc, sizeof bufW / sizeof bufW[0], bufW);
4491 ok(n == sizeof faceW / sizeof faceW[0], "GetTextFaceW returned %d\n", n);
4492 ok(lstrcmpW(faceW, bufW) == 0, "GetTextFaceW\n");
4493
4494 /* Play with the count arg. */
4495 bufW[0] = 'x';
4496 n = GetTextFaceW(dc, 0, bufW);
4497 ok(n == 0, "GetTextFaceW returned %d\n", n);
4498 ok(bufW[0] == 'x', "GetTextFaceW buf[0] == %d\n", bufW[0]);
4499
4500 bufW[0] = 'x';
4501 n = GetTextFaceW(dc, 1, bufW);
4502 ok(n == 1, "GetTextFaceW returned %d\n", n);
4503 ok(bufW[0] == '\0', "GetTextFaceW buf[0] == %d\n", bufW[0]);
4504
4505 bufW[0] = 'x'; bufW[1] = 'y';
4506 n = GetTextFaceW(dc, 2, bufW);
4507 ok(n == 2, "GetTextFaceW returned %d\n", n);
4508 ok(bufW[0] == faceW[0] && bufW[1] == '\0', "GetTextFaceW didn't copy\n");
4509
4510 n = GetTextFaceW(dc, 0, NULL);
4511 ok(n == sizeof faceW / sizeof faceW[0], "GetTextFaceW returned %d\n", n);
4512
4514 ReleaseDC(NULL, dc);
4515}
4516
4517static void test_orientation(void)
4518{
4519 static const char test_str[11] = "Test String";
4520 HDC hdc;
4521 LOGFONTA lf;
4522 HFONT hfont, old_hfont;
4523 SIZE size;
4524
4525 if (!is_truetype_font_installed("Arial"))
4526 {
4527 skip("Arial is not installed\n");
4528 return;
4529 }
4530
4532 memset(&lf, 0, sizeof(lf));
4533 lstrcpyA(lf.lfFaceName, "Arial");
4534 lf.lfHeight = 72;
4535 lf.lfOrientation = lf.lfEscapement = 900;
4536 hfont = create_font("orientation", &lf);
4537 old_hfont = SelectObject(hdc, hfont);
4538 ok(GetTextExtentExPointA(hdc, test_str, sizeof(test_str), 32767, NULL, NULL, &size), "GetTextExtentExPointA failed\n");
4539 ok(near_match(311, size.cx), "cx should be about 311, got %d\n", size.cx);
4540 ok(near_match(75, size.cy), "cy should be about 75, got %d\n", size.cy);
4541 SelectObject(hdc, old_hfont);
4543 DeleteDC(hdc);
4544}
4545
4546static void test_oemcharset(void)
4547{
4548 HDC hdc;
4549 LOGFONTA lf, clf;
4550 HFONT hfont, old_hfont;
4551 int charset;
4552
4554 ZeroMemory(&lf, sizeof(lf));
4555 lf.lfHeight = 12;
4558 lstrcpyA(lf.lfFaceName, "Terminal");
4560 old_hfont = SelectObject(hdc, hfont);
4563 ok(charset == OEM_CHARSET, "expected %d charset, got %d\n", OEM_CHARSET, charset);
4564 hfont = SelectObject(hdc, old_hfont);
4565 GetObjectA(hfont, sizeof(clf), &clf);
4566 ok(!lstrcmpA(clf.lfFaceName, lf.lfFaceName), "expected %s face name, got %s\n", lf.lfFaceName, clf.lfFaceName);
4567 ok(clf.lfPitchAndFamily == lf.lfPitchAndFamily, "expected %x family, got %x\n", lf.lfPitchAndFamily, clf.lfPitchAndFamily);
4568 ok(clf.lfCharSet == lf.lfCharSet, "expected %d charset, got %d\n", lf.lfCharSet, clf.lfCharSet);
4569 ok(clf.lfHeight == lf.lfHeight, "expected %d height, got %d\n", lf.lfHeight, clf.lfHeight);
4571 DeleteDC(hdc);
4572}
4573
4575 const TEXTMETRICA *lpntme,
4576 DWORD FontType, LPARAM lParam)
4577{
4578 const NEWTEXTMETRICEXA *lpntmex = (const NEWTEXTMETRICEXA *)lpntme;
4579 CHARSETINFO csi;
4580 LOGFONTA lf = *lpelfe;
4581 HFONT hfont;
4582 DWORD found_subset;
4583
4584 /* skip bitmap, proportional or vertical font */
4585 if ((FontType & TRUETYPE_FONTTYPE) == 0 ||
4586 (lf.lfPitchAndFamily & 0xf) != FIXED_PITCH ||
4587 lf.lfFaceName[0] == '@')
4588 return 1;
4589
4590 /* skip linked font */
4591 if (!TranslateCharsetInfo((DWORD*)(INT_PTR)lpelfe->lfCharSet, &csi, TCI_SRCCHARSET) ||
4592 (lpntmex->ntmFontSig.fsCsb[0] & csi.fs.fsCsb[0]) == 0)
4593 return 1;
4594
4595 /* skip linked font, like SimSun-ExtB */
4596 switch (lpelfe->lfCharSet) {
4597 case SHIFTJIS_CHARSET:
4598 found_subset = lpntmex->ntmFontSig.fsUsb[1] & (1 << 17); /* Hiragana */
4599 break;
4600 case GB2312_CHARSET:
4602 found_subset = lpntmex->ntmFontSig.fsUsb[1] & (1 << 16); /* CJK Symbols And Punctuation */
4603 break;
4604 case HANGEUL_CHARSET:
4605 found_subset = lpntmex->ntmFontSig.fsUsb[1] & (1 << 24); /* Hangul Syllables */
4606 break;
4607 default:
4608 found_subset = lpntmex->ntmFontSig.fsUsb[0] & (1 << 0); /* Basic Latin */
4609 break;
4610 }
4611 if (!found_subset)
4612 return 1;
4613
4614 /* test with an odd height */
4615 lf.lfHeight = -19;
4616 lf.lfWidth = 0;
4618 if (hfont)
4619 {
4620 *(HFONT *)lParam = hfont;
4621 return 0;
4622 }
4623 return 1;
4624}
4625
4626static void test_GetGlyphOutline(void)
4627{
4628 HDC hdc;
4629 GLYPHMETRICS gm, gm2;
4630 LOGFONTA lf;
4631 HFONT hfont, old_hfont;
4632 INT ret, ret2;
4635 static const struct
4636 {
4637 UINT cs;
4638 UINT a;
4639 UINT w;
4640 } c[] =
4641 {
4642 {ANSI_CHARSET, 0x30, 0x30},
4643 {SHIFTJIS_CHARSET, 0x82a0, 0x3042},
4644 {HANGEUL_CHARSET, 0x8141, 0xac02},
4645 {GB2312_CHARSET, 0x8141, 0x4e04},
4646 {CHINESEBIG5_CHARSET, 0xa142, 0x3001}
4647 };
4648 UINT i;
4649
4650 if (!is_truetype_font_installed("Tahoma"))
4651 {
4652 skip("Tahoma is not installed\n");
4653 return;
4654 }
4655
4657 memset(&lf, 0, sizeof(lf));
4658 lf.lfHeight = 72;
4659 lstrcpyA(lf.lfFaceName, "Tahoma");
4660 SetLastError(0xdeadbeef);
4662 ok(hfont != 0, "CreateFontIndirectA error %u\n", GetLastError());
4663 old_hfont = SelectObject(hdc, hfont);
4664
4665 memset(&gm, 0, sizeof(gm));
4666 SetLastError(0xdeadbeef);
4667 ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
4668 ok(ret != GDI_ERROR, "GetGlyphOutlineA error %u\n", GetLastError());
4669
4670 memset(&gm, 0, sizeof(gm));
4671 SetLastError(0xdeadbeef);
4672 ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, NULL);
4673 ok(ret == GDI_ERROR, "GetGlyphOutlineA should fail\n");
4674 ok(GetLastError() == 0xdeadbeef ||
4675 GetLastError() == ERROR_INVALID_PARAMETER, /* win98, winMe */
4676 "expected 0xdeadbeef, got %u\n", GetLastError());
4677
4678 memset(&gm, 0, sizeof(gm));
4679 SetLastError(0xdeadbeef);
4680 ret = GetGlyphOutlineW(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
4682 ok(ret != GDI_ERROR, "GetGlyphOutlineW error %u\n", GetLastError());
4683
4684 memset(&gm, 0, sizeof(gm));
4685 SetLastError(0xdeadbeef);
4686 ret = GetGlyphOutlineW(hdc, 'A', GGO_METRICS, &gm, 0, NULL, NULL);
4688 {
4689 ok(ret == GDI_ERROR, "GetGlyphOutlineW should fail\n");
4690 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", GetLastError());
4691 }
4692
4693 /* test for needed buffer size request on space char */
4694 memset(&gm, 0, sizeof(gm));
4695 SetLastError(0xdeadbeef);
4696 ret = GetGlyphOutlineW(hdc, ' ', GGO_NATIVE, &gm, 0, NULL, &mat);
4698 {
4699 ok(ret == 0, "GetGlyphOutlineW should return 0 buffer size for space char\n");
4700 ok(gm.gmBlackBoxX == 1, "Expected 1, got %u\n", gm.gmBlackBoxX);
4701 ok(gm.gmBlackBoxY == 1, "Expected 1, got %u\n", gm.gmBlackBoxY);
4702 }
4703
4704 /* requesting buffer size for space char + error */
4705 memset(&gm, 0, sizeof(gm));
4706 SetLastError(0xdeadbeef);
4707 ret = GetGlyphOutlineW(0, ' ', GGO_NATIVE, &gm, 0, NULL, NULL);
4709 {
4710 ok(ret == GDI_ERROR, "GetGlyphOutlineW should return GDI_ERROR\n");
4711 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", GetLastError());
4712 ok(gm.gmBlackBoxX == 0, "Expected 0, got %u\n", gm.gmBlackBoxX);
4713 ok(gm.gmBlackBoxY == 0, "Expected 0, got %u\n", gm.gmBlackBoxY);
4714 }
4715
4716 /* test GetGlyphOutline with a buffer too small */
4717 SetLastError(0xdeadbeef);
4718 ret = GetGlyphOutlineA(hdc, 'A', GGO_NATIVE, &gm, sizeof(i), &i, &mat);
4720 ok(ret == GDI_ERROR, "GetGlyphOutlineW should return an error when the buffer size is too small.\n");
4721
4722 for (i = 0; i < sizeof(fmt) / sizeof(fmt[0]); ++i)
4723 {
4724 DWORD dummy;
4725
4726 memset(&gm, 0xab, sizeof(gm));
4727 SetLastError(0xdeadbeef);
4728 ret = GetGlyphOutlineW(hdc, ' ', fmt[i], &gm, 0, NULL, &mat);
4730 {
4731 if (fmt[i] == GGO_METRICS)
4732 ok(ret != GDI_ERROR, "%2d:GetGlyphOutlineW should succeed, got %d\n", fmt[i], ret);
4733 else
4734 ok(ret == 0, "%2d:GetGlyphOutlineW should return 0, got %d\n", fmt[i], ret);
4735 ok(gm.gmBlackBoxX == 1, "%2d:expected 1, got %u\n", fmt[i], gm.gmBlackBoxX);
4736 ok(gm.gmBlackBoxY == 1, "%2d:expected 1, got %u\n", fmt[i], gm.gmBlackBoxY);
4737 }
4738
4739 memset(&gm, 0xab, sizeof(gm));
4740 SetLastError(0xdeadbeef);
4741 ret = GetGlyphOutlineW(hdc, ' ', fmt[i], &gm, 0, &dummy, &mat);
4743 {
4744 if (fmt[i] == GGO_METRICS)
4745 ok(ret != GDI_ERROR, "%2d:GetGlyphOutlineW should succeed, got %d\n", fmt[i], ret);
4746 else
4747 ok(ret == 0, "%2d:GetGlyphOutlineW should return 0, got %d\n", fmt[i], ret);
4748 ok(gm.gmBlackBoxX == 1, "%2d:expected 1, got %u\n", fmt[i], gm.gmBlackBoxX);
4749 ok(gm.gmBlackBoxY == 1, "%2d:expected 1, got %u\n", fmt[i], gm.gmBlackBoxY);
4750 }
4751
4752 memset(&gm, 0xab, sizeof(gm));
4753 SetLastError(0xdeadbeef);
4754 ret = GetGlyphOutlineW(hdc, ' ', fmt[i], &gm, sizeof(dummy), NULL, &mat);
4756 {
4757 if (fmt[i] == GGO_METRICS)
4758 ok(ret != GDI_ERROR, "%2d:GetGlyphOutlineW should succeed, got %d\n", fmt[i], ret);
4759 else
4760 ok(ret == 0, "%2d:GetGlyphOutlineW should return 0, got %d\n", fmt[i], ret);
4761 ok(gm.gmBlackBoxX == 1, "%2d:expected 1, got %u\n", fmt[i], gm.gmBlackBoxX);
4762 ok(gm.gmBlackBoxY == 1, "%2d:expected 1, got %u\n", fmt[i], gm.gmBlackBoxY);
4763 }
4764
4765 memset(&gm, 0xab, sizeof(gm));
4766 SetLastError(0xdeadbeef);
4767 ret = GetGlyphOutlineW(hdc, ' ', fmt[i], &gm, sizeof(dummy), &dummy, &mat);
4769 {
4770 if (fmt[i] == GGO_METRICS) {
4771 ok(ret != GDI_ERROR, "%2d:GetGlyphOutlineW should succeed, got %d\n", fmt[i], ret);
4772 ok(gm.gmBlackBoxX == 1, "%2d:expected 1, got %u\n", fmt[i], gm.gmBlackBoxX);
4773 ok(gm.gmBlackBoxY == 1, "%2d:expected 1, got %u\n", fmt[i], gm.gmBlackBoxY);
4774 }
4775 else
4776 {
4777 ok(ret == GDI_ERROR, "%2d:GetGlyphOutlineW should return GDI_ERROR, got %d\n", fmt[i], ret);
4778 memset(&gm2, 0xab, sizeof(gm2));
4779 ok(memcmp(&gm, &gm2, sizeof(GLYPHMETRICS)) == 0,
4780 "%2d:GLYPHMETRICS shouldn't be touched on error\n", fmt[i]);
4781 }
4782 }
4783 }
4784
4785 SelectObject(hdc, old_hfont);
4787
4788 for (i = 0; i < sizeof c / sizeof c[0]; ++i)
4789 {
4790 static const MAT2 rotate_mat = {{0, 0}, {0, -1}, {0, 1}, {0, 0}};
4792
4793 lf.lfFaceName[0] = '\0';
4794 lf.lfCharSet = c[i].cs;
4795 lf.lfPitchAndFamily = 0;
4797 {
4798 skip("TrueType font for charset %u is not installed\n", c[i].cs);
4799 continue;
4800 }
4801
4802 old_hfont = SelectObject(hdc, hfont);
4803
4804 /* expected to ignore superfluous bytes (sigle-byte character) */
4805 ret = GetGlyphOutlineA(hdc, 0x8041, GGO_BITMAP, &gm, 0, NULL, &mat);
4806 ret2 = GetGlyphOutlineA(hdc, 0x41, GGO_BITMAP, &gm2, 0, NULL, &mat);
4807 ok(ret == ret2 && memcmp(&gm, &gm2, sizeof gm) == 0, "%d %d\n", ret, ret2);
4808
4809 ret = GetGlyphOutlineA(hdc, 0xcc8041, GGO_BITMAP, &gm, 0, NULL, &mat);
4810 ok(ret == ret2 && memcmp(&gm, &gm2, sizeof gm) == 0,
4811 "Expected to ignore superfluous bytes, got %d %d\n", ret, ret2);
4812
4813 /* expected to ignore superfluous bytes (double-byte character) */
4814 ret = GetGlyphOutlineA(hdc, c[i].a, GGO_BITMAP, &gm, 0, NULL, &mat);
4815 ret2 = GetGlyphOutlineA(hdc, c[i].a | 0xdead0000, GGO_BITMAP, &gm2, 0, NULL, &mat);
4816 ok(ret == ret2 && memcmp(&gm, &gm2, sizeof gm) == 0,
4817 "Expected to ignore superfluous bytes, got %d %d\n", ret, ret2);
4818
4819 /* expected to match wide-char version results */
4820 ret2 = GetGlyphOutlineW(hdc, c[i].w, GGO_BITMAP, &gm2, 0, NULL, &mat);
4821 ok(ret == ret2 && memcmp(&gm, &gm2, sizeof gm) == 0, "%d %d\n", ret, ret2);
4822
4824 {
4825 skip("Fixed-pitch TrueType font for charset %u is not available\n", c[i].cs);
4826 continue;
4827 }
4829 if (c[i].a <= 0xff)
4830 {
4831 DeleteObject(SelectObject(hdc, old_hfont));
4832 continue;
4833 }
4834
4835 ret = GetObjectA(hfont, sizeof lf, &lf);
4836 ok(ret > 0, "GetObject error %u\n", GetLastError());
4837
4839 ok(ret, "GetTextMetrics error %u\n", GetLastError());
4840 ret = GetGlyphOutlineA(hdc, c[i].a, GGO_METRICS, &gm2, 0, NULL, &mat);
4841 ok(ret != GDI_ERROR, "GetGlyphOutlineA error %u\n", GetLastError());
4842 trace("Tests with height=%d,avg=%d,full=%d,face=%s,charset=%d\n",
4843 -lf.lfHeight, tm.tmAveCharWidth, gm2.gmCellIncX, lf.lfFaceName, lf.lfCharSet);
4844 ok(gm2.gmCellIncX == tm.tmAveCharWidth * 2 || broken(gm2.gmCellIncX == -lf.lfHeight),
4845 "expected %d, got %d (%s:%d)\n",
4846 tm.tmAveCharWidth * 2, gm2.gmCellIncX, lf.lfFaceName, lf.lfCharSet);
4847
4848 ret = GetGlyphOutlineA(hdc, c[i].a, GGO_METRICS, &gm2, 0, NULL, &rotate_mat);
4849 ok(ret != GDI_ERROR, "GetGlyphOutlineA error %u\n", GetLastError());
4850 ok(gm2.gmCellIncY == -lf.lfHeight,
4851 "expected %d, got %d (%s:%d)\n",
4852 -lf.lfHeight, gm2.gmCellIncY, lf.lfFaceName, lf.lfCharSet);
4853
4854 lf.lfItalic = TRUE;
4856 ok(hfont != NULL, "CreateFontIndirect error %u\n", GetLastError());
4859 ok(ret, "GetTextMetrics error %u\n", GetLastError());
4860 ret = GetGlyphOutlineA(hdc, c[i].a, GGO_METRICS, &gm2, 0, NULL, &mat);
4861 ok(ret != GDI_ERROR, "GetGlyphOutlineA error %u\n", GetLastError());
4862 ok(gm2.gmCellIncX == tm.tmAveCharWidth * 2 || broken(gm2.gmCellIncX == -lf.lfHeight),
4863 "expected %d, got %d (%s:%d)\n",
4864 tm.tmAveCharWidth * 2, gm2.gmCellIncX, lf.lfFaceName, lf.lfCharSet);
4865
4866 lf.lfItalic = FALSE;
4867 lf.lfEscapement = lf.lfOrientation = 2700;
4869 ok(hfont != NULL, "CreateFontIndirect error %u\n", GetLastError());
4871 ret = GetGlyphOutlineA(hdc, c[i].a, GGO_METRICS, &gm2, 0, NULL, &mat);
4872 ok(ret != GDI_ERROR, "GetGlyphOutlineA error %u\n", GetLastError());
4873 ok(gm2.gmCellIncY == -lf.lfHeight,
4874 "expected %d, got %d (%s:%d)\n",
4875 -lf.lfHeight, gm2.gmCellIncY, lf.lfFaceName, lf.lfCharSet);
4876
4877 hfont = SelectObject(hdc, old_hfont);
4879 }
4880
4881 DeleteDC(hdc);
4882}
4883
4884/* bug #9995: there is a limit to the character width that can be specified */
4885static void test_GetTextMetrics2(const char *fontname, int font_height)
4886{
4887 HFONT of, hf;
4888 HDC hdc;
4890 BOOL ret;
4891 int ave_width, height, width, ratio, scale;
4892
4893 if (!is_truetype_font_installed( fontname)) {
4894 skip("%s is not installed\n", fontname);
4895 return;
4896 }
4898 ok( hdc != NULL, "CreateCompatibleDC failed\n");
4899 /* select width = 0 */
4903 fontname);
4904 ok( hf != NULL, "CreateFontA(%s, %d) failed\n", fontname, font_height);
4905 of = SelectObject( hdc, hf);
4906 ret = GetTextMetricsA( hdc, &tm);
4907 ok(ret, "GetTextMetricsA error %u\n", GetLastError());
4908 height = tm.tmHeight;
4909 ave_width = tm.tmAveCharWidth;
4910 SelectObject( hdc, of);
4911 DeleteObject( hf);
4912
4913 trace("height %d, ave width %d\n", height, ave_width);
4914
4915 for (width = ave_width * 2; /* nothing*/; width += ave_width)
4916 {
4919 DEFAULT_QUALITY, VARIABLE_PITCH, fontname);
4920 ok(hf != 0, "CreateFont failed\n");
4921 of = SelectObject(hdc, hf);
4923 ok(ret, "GetTextMetrics error %u\n", GetLastError());
4924 SelectObject(hdc, of);
4925 DeleteObject(hf);
4926
4927 if (match_off_by_1(tm.tmAveCharWidth, ave_width, FALSE) || width / height > 200)
4928 break;
4929 }
4930
4931 DeleteDC(hdc);
4932
4933 ratio = width / height;
4934 scale = width / ave_width;
4935
4936 trace("max width/height ratio (%d / %d) %d, max width scale (%d / %d) %d\n",
4937 width, height, ratio, width, ave_width, scale);
4938
4939 ok(ratio >= 90 && ratio <= 110, "expected width/height ratio 90-110, got %d\n", ratio);
4940}
4941
4943{
4945 DWORD size, size2;
4946 WCHAR glyphs[20];
4947 HDC hdc;
4948
4950 ok(!!hdc, "CreateCompatibleDC failed\n");
4951
4952 memset(&result, 0, sizeof(result));
4953 result.lStructSize = sizeof(result);
4954 result.lpGlyphs = glyphs;
4955 result.nGlyphs = 20;
4956
4957 size = GetCharacterPlacementA(hdc, "Wine Test", 9, 0, &result, 0);
4958 ok(size, "GetCharacterPlacementA failed!\n");
4959
4960 size2 = GetCharacterPlacementA(hdc, "Wine Test", 9, 0, NULL, 0);
4961 ok(size2, "GetCharacterPlacementA failed!\n");
4962 ok(size == size2, "GetCharacterPlacementA returned different result: %u vs %u\n", size2, size);
4963
4964 size2 = GetCharacterPlacementA(hdc, "Wine Test", 9, 1024, NULL, GCP_REORDER);
4965 ok(size2, "GetCharacterPlacementA failed!\n");
4966 ok(size == size2, "GetCharacterPlacementA returned different result: %u vs %u\n", size2, size);
4967
4968 size = GetCharacterPlacementA(hdc, "Wine Test", 9, 1024, &result, GCP_REORDER);
4969 ok(size, "GetCharacterPlacementA failed!\n");
4970 ok(size == size2, "GetCharacterPlacementA returned different result: %u vs %u\n", size2, size);
4971}
4972
4974{
4975 LOGFONTA lf, getobj_lf;
4976 int ret, i;
4977 HFONT hfont;
4978 char TestName[][16] = {"Arial", "Arial Bold", "Arial Italic", "Arial Baltic"};
4979
4980 memset(&lf, 0, sizeof(lf));
4983 lf.lfHeight = 16;
4984 lf.lfWidth = 16;
4986 lf.lfItalic = FALSE;
4987 lf.lfWeight = FW_DONTCARE;
4988
4989 for (i = 0; i < sizeof(TestName)/sizeof(TestName[0]); i++)
4990 {
4991 lstrcpyA(lf.lfFaceName, TestName[i]);
4993 ok(hfont != 0, "CreateFontIndirectA failed\n");
4994 SetLastError(0xdeadbeef);
4995 ret = GetObjectA(hfont, sizeof(getobj_lf), &getobj_lf);
4996 ok(ret, "GetObject failed: %d\n", GetLastError());
4997 ok(lf.lfItalic == getobj_lf.lfItalic, "lfItalic: expect %02x got %02x\n", lf.lfItalic, getobj_lf.lfItalic);
4998 ok(lf.lfWeight == getobj_lf.lfWeight ||
4999 broken((SHORT)lf.lfWeight == getobj_lf.lfWeight), /* win9x */
5000 "lfWeight: expect %08x got %08x\n", lf.lfWeight, getobj_lf.lfWeight);
5001 ok(!lstrcmpA(lf.lfFaceName, getobj_lf.lfFaceName) ||
5002 broken(!memcmp(lf.lfFaceName, getobj_lf.lfFaceName, LF_FACESIZE-1)), /* win9x doesn't ensure '\0' termination */
5003 "font names don't match: %s != %s\n", lf.lfFaceName, getobj_lf.lfFaceName);
5005 }
5006}
5007
5009{
5010 ENUMLOGFONTEXDVA lfex;
5011 HFONT hfont;
5012
5013 if (!pCreateFontIndirectExA)
5014 {
5015 win_skip("CreateFontIndirectExA is not available\n");
5016 return;
5017 }
5018
5019 if (!is_truetype_font_installed("Arial"))
5020 {
5021 skip("Arial is not installed\n");
5022 return;
5023 }
5024
5025 SetLastError(0xdeadbeef);
5026 hfont = pCreateFontIndirectExA(NULL);
5027 ok(hfont == NULL, "got %p\n", hfont);
5028 ok(GetLastError() == 0xdeadbeef, "got error %d\n", GetLastError());
5029
5030 memset(&lfex, 0, sizeof(lfex));
5032 hfont = pCreateFontIndirectExA(&lfex);
5033 ok(hfont != 0, "CreateFontIndirectEx failed\n");
5034 if (hfont)
5037}
5038
5039static void free_font(void *font)
5040{
5042}
5043
5044static void *load_font(const char *font_name, DWORD *font_size)
5045{
5046 char file_name[MAX_PATH];
5048 void *font;
5049
5050 if (!GetWindowsDirectoryA(file_name, sizeof(file_name))) return NULL;
5051 strcat(file_name, "\\fonts\\");
5052 strcat(file_name, font_name);
5053
5055 if (file == INVALID_HANDLE_VALUE) return NULL;
5056
5058
5060 if (!mapping)
5061 {
5063 return NULL;
5064 }
5065
5067
5070 return font;
5071}
5072
5074{
5075 void *font;
5076 DWORD font_size, num_fonts;
5077 HANDLE ret;
5078 BOOL bRet;
5079
5080 if (!pAddFontMemResourceEx || !pRemoveFontMemResourceEx)
5081 {
5082 win_skip("AddFontMemResourceEx is not available on this platform\n");
5083 return;
5084 }
5085
5086 font = load_font("sserife.fon", &font_size);
5087 if (!font)
5088 {
5089 skip("Unable to locate and load font sserife.fon\n");
5090 return;
5091 }
5092
5093 SetLastError(0xdeadbeef);
5094 ret = pAddFontMemResourceEx(NULL, 0, NULL, NULL);
5095 ok(!ret, "AddFontMemResourceEx should fail\n");
5097 "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
5098 GetLastError());
5099
5100 SetLastError(0xdeadbeef);
5101 ret = pAddFontMemResourceEx(NULL, 10, NULL, NULL);
5102 ok(!ret, "AddFontMemResourceEx should fail\n");
5104 "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
5105 GetLastError());
5106
5107 SetLastError(0xdeadbeef);
5108 ret = pAddFontMemResourceEx(NULL, 0, NULL, &num_fonts);
5109 ok(!ret, "AddFontMemResourceEx should fail\n");
5111 "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
5112 GetLastError());
5113
5114 SetLastError(0xdeadbeef);
5115 ret = pAddFontMemResourceEx(NULL, 10, NULL, &num_fonts);
5116 ok(!ret, "AddFontMemResourceEx should fail\n");
5118 "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
5119 GetLastError());
5120
5121 SetLastError(0xdeadbeef);
5122 ret = pAddFontMemResourceEx(font, 0, NULL, NULL);
5123 ok(!ret, "AddFontMemResourceEx should fail\n");
5125 "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
5126 GetLastError());
5127
5128 SetLastError(0xdeadbeef);
5129 ret = pAddFontMemResourceEx(font, 10, NULL, NULL);
5130 ok(!ret, "AddFontMemResourceEx should fail\n");
5132 "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
5133 GetLastError());
5134
5135 num_fonts = 0xdeadbeef;
5136 SetLastError(0xdeadbeef);
5137 ret = pAddFontMemResourceEx(font, 0, NULL, &num_fonts);
5138 ok(!ret, "AddFontMemResourceEx should fail\n");
5140 "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
5141 GetLastError());
5142 ok(num_fonts == 0xdeadbeef, "number of loaded fonts should be 0xdeadbeef\n");
5143
5144 if (0) /* hangs under windows 2000 */
5145 {
5146 num_fonts = 0xdeadbeef;
5147 SetLastError(0xdeadbeef);
5148 ret = pAddFontMemResourceEx(font, 10, NULL, &num_fonts);
5149 ok(!ret, "AddFontMemResourceEx should fail\n");
5150 ok(GetLastError() == 0xdeadbeef,
5151 "Expected GetLastError() to return 0xdeadbeef, got %u\n",
5152 GetLastError());
5153 ok(num_fonts == 0xdeadbeef, "number of loaded fonts should be 0xdeadbeef\n");
5154 }
5155
5156 num_fonts = 0xdeadbeef;
5157 SetLastError(0xdeadbeef);
5158 ret = pAddFontMemResourceEx(font, font_size, NULL, &num_fonts);
5159 ok(ret != 0, "AddFontMemResourceEx error %d\n", GetLastError());
5160 ok(num_fonts != 0xdeadbeef, "number of loaded fonts should not be 0xdeadbeef\n");
5161 ok(num_fonts != 0, "number of loaded fonts should not be 0\n");
5162
5163 free_font(font);
5164
5165 SetLastError(0xdeadbeef);
5166 bRet = pRemoveFontMemResourceEx(ret);
5167 ok(bRet, "RemoveFontMemResourceEx error %d\n", GetLastError());
5168
5169 /* test invalid pointer to number of loaded fonts */
5170 font = load_font("sserife.fon", &font_size);
5171 ok(font != NULL, "Unable to locate and load font sserife.fon\n");
5172
5173 SetLastError(0xdeadbeef);
5174 ret = pAddFontMemResourceEx(font, font_size, NULL, (void *)0xdeadbeef);
5175 ok(!ret, "AddFontMemResourceEx should fail\n");
5176 ok(GetLastError() == 0xdeadbeef,
5177 "Expected GetLastError() to return 0xdeadbeef, got %u\n",
5178 GetLastError());
5179
5180 SetLastError(0xdeadbeef);
5181 ret = pAddFontMemResourceEx(font, font_size, NULL, NULL);
5182 ok(!ret, "AddFontMemResourceEx should fail\n");
5184 "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
5185 GetLastError());
5186
5187 free_font(font);
5188}
5189
5191{
5192 LOGFONTA *lf;
5193
5194 if (type != TRUETYPE_FONTTYPE) return 1;
5195
5196 ok(ntm->tmWeight == elf->lfWeight, "expected %d got %d\n", ntm->tmWeight, elf->lfWeight);
5197
5198 lf = (LOGFONTA *)lparam;
5199 *lf = *elf;
5200 return 0;
5201}
5202
5204{
5205 int ret;
5206 LOGFONTA *lf;
5207
5208 if (type != TRUETYPE_FONTTYPE) return 1;
5209
5210 lf = (LOGFONTA *)lparam;
5211 ret = strcmp(lf->lfFaceName, elf->lfFaceName);
5212 if(ret == 0)
5213 {
5214 ok(ntm->tmWeight == elf->lfWeight, "expected %d got %d\n", ntm->tmWeight, elf->lfWeight);
5215 *lf = *elf;
5216 return 0;
5217 }
5218 return 1;
5219}
5220
5222{
5223 return lparam;
5224}
5225
5226static void test_EnumFonts(void)
5227{
5228 int ret;
5229 LOGFONTA lf;
5230 HDC hdc;
5231
5232 if (!is_truetype_font_installed("Arial"))
5233 {
5234 skip("Arial is not installed\n");
5235 return;
5236 }
5237
5238 /* Windows uses localized font face names, so Arial Bold won't be found */
5240 {
5241 skip("User locale is not English, skipping the test\n");
5242 return;
5243 }
5244
5246
5247 /* check that the enumproc's retval is returned */
5249 ok(ret == 0xcafe, "got %08x\n", ret);
5250
5251 ret = EnumFontFamiliesA(hdc, "Arial", enum_fonts_proc, (LPARAM)&lf);
5252 ok(!ret, "font Arial is not enumerated\n");
5253 ret = strcmp(lf.lfFaceName, "Arial");
5254 ok(!ret, "expected Arial got %s\n", lf.lfFaceName);
5255 ok(lf.lfWeight == FW_NORMAL, "expected FW_NORMAL got %d\n", lf.lfWeight);
5256
5257 strcpy(lf.lfFaceName, "Arial");
5259 ok(!ret, "font Arial is not enumerated\n");
5260 ret = strcmp(lf.lfFaceName, "Arial");
5261 ok(!ret, "expected Arial got %s\n", lf.lfFaceName);
5262 ok(lf.lfWeight == FW_NORMAL, "expected FW_NORMAL got %d\n", lf.lfWeight);
5263
5264 ret = EnumFontFamiliesA(hdc, "Arial Bold", enum_fonts_proc, (LPARAM)&lf);
5265 ok(!ret, "font Arial Bold is not enumerated\n");
5266 ret = strcmp(lf.lfFaceName, "Arial");
5267 ok(!ret, "expected Arial got %s\n", lf.lfFaceName);
5268 ok(lf.lfWeight == FW_BOLD, "expected FW_BOLD got %d\n", lf.lfWeight);
5269
5270 strcpy(lf.lfFaceName, "Arial Bold");
5272 ok(ret, "font Arial Bold should not be enumerated\n");
5273
5274 ret = EnumFontFamiliesA(hdc, "Arial Bold Italic", enum_fonts_proc, (LPARAM)&lf);
5275 ok(!ret, "font Arial Bold Italic is not enumerated\n");
5276 ret = strcmp(lf.lfFaceName, "Arial");
5277 ok(!ret, "expected Arial got %s\n", lf.lfFaceName);
5278 ok(lf.lfWeight == FW_BOLD, "expected FW_BOLD got %d\n", lf.lfWeight);
5279
5280 strcpy(lf.lfFaceName, "Arial Bold Italic");
5282 ok(ret, "font Arial Bold Italic should not be enumerated\n");
5283
5284 ret = EnumFontFamiliesA(hdc, "Arial Italic Bold", enum_fonts_proc, (LPARAM)&lf);
5285 ok(ret, "font Arial Italic Bold should not be enumerated\n");
5286
5287 strcpy(lf.lfFaceName, "Arial Italic Bold");
5289 ok(ret, "font Arial Italic Bold should not be enumerated\n");
5290
5291 DeleteDC(hdc);
5292}
5293
5295{
5296 struct enum_fullname_data *efnd = (struct enum_fullname_data *)lParam;
5297
5298if (0) /* Disabled to limit console spam */
5299 trace("enumed font \"%s\", charset %d, height %d, weight %d, italic %d\n",
5300 lf->lfFaceName, lf->lfCharSet, lf->lfHeight, lf->lfWeight, lf->lfItalic);
5301
5302 if (type != TRUETYPE_FONTTYPE) return 1;
5303 if (strcmp(lf->lfFaceName, "MS Shell Dlg") != 0) return 1;
5304
5305 if (efnd->total >= efnd->size)
5306 {
5307 efnd->size = max( (efnd->total + 1) * 2, 256 );
5308 efnd->elf = heap_realloc( efnd->elf, efnd->size * sizeof(*efnd->elf) );
5309 if (!efnd->elf) return 0;
5310 }
5311 efnd->elf[efnd->total++] = *(ENUMLOGFONTA *)lf;
5312 return 0;
5313}
5314
5316{
5317 struct enum_fullname_data *efnd = (struct enum_fullname_data *)lParam;
5318
5319if (0) /* Disabled to limit console spam */
5320 trace("enumed font \"%s\", charset %d, height %d, weight %d, italic %d\n",
5321 lf->lfFaceName, lf->lfCharSet, lf->lfHeight, lf->lfWeight, lf->lfItalic);
5322
5323 if (type != TRUETYPE_FONTTYPE) return 1;
5324 if (strcmp(lf->lfFaceName, "MS Shell Dlg 2") != 0) return 1;
5325
5326 if (efnd->total >= efnd->size)
5327 {
5328 efnd->size = max( (efnd->total + 1) * 2, 256 );
5329 efnd->elf = heap_realloc( efnd->elf, efnd->size * sizeof(*efnd->elf) );
5330 if (!efnd->elf) return 0;
5331 }
5332 efnd->elf[efnd->total++] = *(ENUMLOGFONTA *)lf;
5333 return 0;
5334}
5335
5336static void test_EnumFonts_subst(void)
5337{
5338 int ret;
5339 LOGFONTA lf;
5340 HDC hdc;
5341 struct enum_fullname_data efnd;
5342
5343 ret = is_font_installed("MS Shell Dlg");
5344 ok(ret, "MS Shell Dlg should be enumerated\n");
5345 ret = is_truetype_font_installed("MS Shell Dlg");
5346 ok(ret, "MS Shell Dlg should be enumerated as a TrueType font\n");
5347
5348 ret = is_font_installed("MS Shell Dlg 2");
5349 ok(ret, "MS Shell Dlg 2 should be enumerated\n");
5350 ret = is_truetype_font_installed("MS Shell Dlg 2");
5351 ok(ret, "MS Shell Dlg 2 should be enumerated as a TrueType font\n");
5352
5354
5355 memset(&efnd, 0, sizeof(efnd));
5357 ok(ret, "MS Shell Dlg should not be enumerated\n");
5358 ok(!efnd.total, "MS Shell Dlg should not be enumerated\n");
5359
5360 memset(&lf, 0, sizeof(lf));
5362
5363 efnd.total = 0;
5364 strcpy(lf.lfFaceName, "MS Shell Dlg");
5366 ok(!ret, "MS Shell Dlg should be enumerated\n");
5367 ok(efnd.total > 0, "MS Shell Dlg should be enumerated\n");
5368 if (efnd.total)
5369 {
5370 ret = strcmp((const char *)efnd.elf[0].elfLogFont.lfFaceName, "MS Shell Dlg");
5371 ok(!ret, "expected MS Shell Dlg, got %s\n", efnd.elf[0].elfLogFont.lfFaceName);
5372 ret = strcmp((const char *)efnd.elf[0].elfFullName, "MS Shell Dlg");
5373 ok(ret, "did not expect MS Shell Dlg\n");
5374 }
5375
5376 efnd.total = 0;
5378 ok(ret, "MS Shell Dlg 2 should not be enumerated\n");
5379 ok(!efnd.total, "MS Shell Dlg 2 should not be enumerated\n");
5380
5381 efnd.total = 0;
5382 strcpy(lf.lfFaceName, "MS Shell Dlg 2");
5384 ok(!ret, "MS Shell Dlg 2 should be enumerated\n");
5385 ok(efnd.total > 0, "MS Shell Dlg 2 should be enumerated\n");
5386 if (efnd.total)
5387 {
5388 ret = strcmp((const char *)efnd.elf[0].elfLogFont.lfFaceName, "MS Shell Dlg 2");
5389 ok(!ret, "expected MS Shell Dlg 2, got %s\n", efnd.elf[0].elfLogFont.lfFaceName);
5390 ret = strcmp((const char *)efnd.elf[0].elfFullName, "MS Shell Dlg 2");
5391 ok(ret, "did not expect MS Shell Dlg 2\n");
5392 }
5393
5394 heap_free(efnd.elf);
5395 DeleteDC(hdc);
5396}
5397
5399{
5400 const ENUMLOGFONTA *elf = (const ENUMLOGFONTA *)lf;
5401 const char *fullname = (const char *)lParam;
5402
5403 if (!strcmp((const char *)elf->elfFullName, fullname)) return 0;
5404
5405 return 1;
5406}
5407
5408static BOOL is_font_installed_fullname(const char *family, const char *fullname)
5409{
5410 HDC hdc = GetDC(0);
5411 BOOL ret = FALSE;
5412
5414 ret = TRUE;
5415
5416 ReleaseDC(0, hdc);
5417 return ret;
5418}
5419
5420static void test_fullname(void)
5421{
5422 static const char *TestName[] = {"Lucida Sans Demibold Roman", "Lucida Sans Italic", "Lucida Sans Regular"};
5423 WCHAR bufW[LF_FULLFACESIZE];
5424 char bufA[LF_FULLFACESIZE];
5425 HFONT hfont, of;
5426 LOGFONTA lf;
5427 HDC hdc;
5428 int i;
5429 DWORD ret;
5430
5432 ok(hdc != NULL, "CreateCompatibleDC failed\n");
5433
5434 memset(&lf, 0, sizeof(lf));
5437 lf.lfHeight = 16;
5438 lf.lfWidth = 16;
5440 lf.lfItalic = FALSE;
5441 lf.lfWeight = FW_DONTCARE;
5442
5443 for (i = 0; i < sizeof(TestName) / sizeof(TestName[0]); i++)
5444 {
5445 if (!is_font_installed_fullname("Lucida Sans", TestName[i]))
5446 {
5447 skip("%s is not installed\n", TestName[i]);
5448 continue;
5449 }
5450
5451 lstrcpyA(lf.lfFaceName, TestName[i]);
5453 ok(hfont != 0, "CreateFontIndirectA failed\n");
5454
5455 of = SelectObject(hdc, hfont);
5456 bufW[0] = 0;
5457 bufA[0] = 0;
5459 ok(ret, "face full name could not be read\n");
5460 WideCharToMultiByte(CP_ACP, 0, bufW, -1, bufA, sizeof(bufA), NULL, FALSE);
5461 ok(!lstrcmpA(bufA, TestName[i]), "font full names don't match: %s != %s\n", TestName[i], bufA);
5462 SelectObject(hdc, of);
5464 }
5465 DeleteDC(hdc);
5466}
5467
5468static WCHAR *prepend_at(WCHAR *family)
5469{
5470 if (!family)
5471 return NULL;
5472
5473 memmove(family + 1, family, (lstrlenW(family) + 1) * sizeof(WCHAR));
5474 family[0] = '@';
5475 return family;
5476}
5477
5478static void test_fullname2_helper(const char *Family)
5479{
5480 char *FamilyName, *FaceName, *StyleName, *otmStr;
5481 struct enum_fullname_data efnd;
5482 WCHAR *bufW;
5483 char *bufA;
5484 HFONT hfont, of;
5485 LOGFONTA lf;
5486 HDC hdc;
5487 int i;
5488 DWORD otm_size, ret, buf_size;
5489 OUTLINETEXTMETRICA *otm;
5490 BOOL want_vertical, get_vertical;
5491 want_vertical = ( Family[0] == '@' );
5492
5494 ok(hdc != NULL, "CreateCompatibleDC failed\n");
5495
5496 memset(&lf, 0, sizeof(lf));
5499 lf.lfHeight = 16;
5500 lf.lfWidth = 16;
5502 lf.lfItalic = FALSE;
5503 lf.lfWeight = FW_DONTCARE;
5505 memset(&efnd, 0, sizeof(efnd));
5507 if (efnd.total == 0)
5508 skip("%s is not installed\n", lf.lfFaceName);
5509
5510 for (i = 0; i < efnd.total; i++)
5511 {
5512 FamilyName = (char *)efnd.elf[i].elfLogFont.lfFaceName;
5513 FaceName = (char *)efnd.elf[i].elfFullName;
5514 StyleName = (char *)efnd.elf[i].elfStyle;
5515
5516 get_vertical = ( FamilyName[0] == '@' );
5517 ok(get_vertical == want_vertical, "Vertical flags don't match: %s %s\n", Family, FamilyName);
5518
5519 lstrcpyA(lf.lfFaceName, FaceName);
5521 ok(hfont != 0, "CreateFontIndirectA failed\n");
5522
5523 of = SelectObject(hdc, hfont);
5524 buf_size = GetFontData(hdc, MS_NAME_TAG, 0, NULL, 0);
5525 ok(buf_size != GDI_ERROR, "no name table found\n");
5526 if (buf_size == GDI_ERROR) continue;
5527
5528 bufW = HeapAlloc(GetProcessHeap(), 0, buf_size);
5529 bufA = HeapAlloc(GetProcessHeap(), 0, buf_size);
5530
5531 otm_size = GetOutlineTextMetricsA(hdc, 0, NULL);
5532 otm = HeapAlloc(GetProcessHeap(), 0, otm_size);
5533 memset(otm, 0, otm_size);
5534 ret = GetOutlineTextMetricsA(hdc, otm_size, otm);
5535 ok(ret != 0, "GetOutlineTextMetrics fails!\n");
5536 if (ret == 0) continue;
5537
5538 bufW[0] = 0;
5539 bufA[0] = 0;
5542 ok(ret, "%s: FAMILY (family name) could not be read\n", FamilyName);
5543 if (want_vertical) bufW = prepend_at(bufW);
5544 WideCharToMultiByte(CP_ACP, 0, bufW, -1, bufA, buf_size, NULL, FALSE);
5545 ok(!lstrcmpA(FamilyName, bufA), "font family names don't match: returned %s, expect %s\n", FamilyName, bufA);
5546 otmStr = (LPSTR)otm + (UINT_PTR)otm->otmpFamilyName;
5547 ok(!lstrcmpA(FamilyName, otmStr), "FamilyName %s doesn't match otmpFamilyName %s\n", FamilyName, otmStr);
5548
5549 bufW[0] = 0;
5550 bufA[0] = 0;
5553 ok(ret, "FULL_NAME (face name) could not be read\n");
5554 if (want_vertical) bufW = prepend_at(bufW);
5555 WideCharToMultiByte(CP_ACP, 0, bufW, -1, bufA, buf_size, NULL, FALSE);
5556 ok(!lstrcmpA(FaceName, bufA), "%s: font face names don't match: returned %s, expect %s\n", FamilyName, FaceName, bufA);
5557 otmStr = (LPSTR)otm + (UINT_PTR)otm->otmpFaceName;
5558 ok(!lstrcmpA(FaceName, otmStr), "%s: FaceName %s doesn't match otmpFaceName %s\n", FamilyName, FaceName, otmStr);
5559
5560 bufW[0] = 0;
5561 bufA[0] = 0;
5564 ok(ret, "%s: SUBFAMILY (style name) could not be read\n", FamilyName);
5565 WideCharToMultiByte(CP_ACP, 0, bufW, -1, bufA, buf_size, NULL, FALSE);
5566 ok(!lstrcmpA(StyleName, bufA), "%s: style names don't match: returned %s, expect %s\n", FamilyName, StyleName, bufA);
5567 otmStr = (LPSTR)otm + (UINT_PTR)otm->otmpStyleName;
5568 ok(!lstrcmpA(StyleName, otmStr), "%s: StyleName %s doesn't match otmpStyleName %s\n", FamilyName, StyleName, otmStr);
5569
5570 bufW[0] = 0;
5571 bufA[0] = 0;
5574 ok(ret, "%s: UNIQUE_ID (full name) could not be read\n", FamilyName);
5575 WideCharToMultiByte(CP_ACP, 0, bufW, -1, bufA, buf_size, NULL, FALSE);
5576 otmStr = (LPSTR)otm + (UINT_PTR)otm->otmpFullName;
5577 ok(!lstrcmpA(otmStr, bufA), "%s: UNIQUE ID (full name) doesn't match: returned %s, expect %s\n", FamilyName, otmStr, bufA);
5578
5579 SelectObject(hdc, of);
5581
5582 HeapFree(GetProcessHeap(), 0, otm);
5583 HeapFree(GetProcessHeap(), 0, bufW);
5584 HeapFree(GetProcessHeap(), 0, bufA);
5585 }
5586 heap_free(efnd.elf);
5587 DeleteDC(hdc);
5588}
5589
5590static void test_fullname2(void)
5591{
5592 test_fullname2_helper("Arial");
5593 test_fullname2_helper("Lucida Sans");
5594 test_fullname2_helper("Tahoma");
5595 test_fullname2_helper("Webdings");
5596 test_fullname2_helper("Wingdings");
5597 test_fullname2_helper("SimSun");
5598 test_fullname2_helper("NSimSun");
5599 test_fullname2_helper("MingLiu");
5600 test_fullname2_helper("PMingLiu");
5601 test_fullname2_helper("WenQuanYi Micro Hei");
5602 test_fullname2_helper("MS UI Gothic");
5603 test_fullname2_helper("Ume UI Gothic");
5604 test_fullname2_helper("MS Gothic");
5605 test_fullname2_helper("Ume Gothic");
5606 test_fullname2_helper("MS PGothic");
5607 test_fullname2_helper("Ume P Gothic");
5608 test_fullname2_helper("Gulim");
5609 test_fullname2_helper("Batang");
5610 test_fullname2_helper("UnBatang");
5611 test_fullname2_helper("UnDotum");
5612 test_fullname2_helper("@SimSun");
5613 test_fullname2_helper("@NSimSun");
5614 test_fullname2_helper("@MingLiu");
5615 test_fullname2_helper("@PMingLiu");
5616 test_fullname2_helper("@WenQuanYi Micro Hei");
5617 test_fullname2_helper("@MS UI Gothic");
5618 test_fullname2_helper("@Ume UI Gothic");
5619 test_fullname2_helper("@MS Gothic");
5620 test_fullname2_helper("@Ume Gothic");
5621 test_fullname2_helper("@MS PGothic");
5622 test_fullname2_helper("@Ume P Gothic");
5623 test_fullname2_helper("@Gulim");
5624 test_fullname2_helper("@Batang");
5625 test_fullname2_helper("@UnBatang");
5626 test_fullname2_helper("@UnDotum");
5627
5628}
5629
5631{
5632 HDC hdc;
5633 LOGFONTA lf;
5634 HFONT hfont, hfont_prev;
5636 GLYPHMETRICS gm;
5637 char buf[1024];
5638 DWORD ret;
5639
5640 memset(&lf, 0, sizeof(lf));
5641 lf.lfHeight = 72;
5642 lstrcpyA(lf.lfFaceName, "wine_test");
5643
5645 ok(hfont != 0, "CreateFontIndirectA error %u\n", GetLastError());
5646
5647 hdc = GetDC(NULL);
5648
5649 hfont_prev = SelectObject(hdc, hfont);
5650 ok(hfont_prev != NULL, "SelectObject failed\n");
5651
5652 ret = GetGlyphOutlineW(hdc, 0xa8, GGO_NATIVE, &gm, 0, NULL, &mat);
5653 ok(ret == 228, "GetGlyphOutline returned %d, expected 228\n", ret);
5654
5656 ret = GetGlyphOutlineW(hdc, 0xa8, GGO_NATIVE, &gm, sizeof(buf), buf, &mat);
5657 ok(ret == 228, "GetGlyphOutline returned %d, expected 228\n", ret);
5658 ok(header->cb == 36, "header->cb = %d, expected 36\n", header->cb);
5659 ok(header->dwType == TT_POLYGON_TYPE, "header->dwType = %d, expected TT_POLYGON_TYPE\n", header->dwType);
5660 header = (TTPOLYGONHEADER*)((char*)header+header->cb);
5661 ok(header->cb == 96, "header->cb = %d, expected 96\n", header->cb);
5662 header = (TTPOLYGONHEADER*)((char*)header+header->cb);
5663 ok(header->cb == 96, "header->cb = %d, expected 96\n", header->cb);
5664
5665 SelectObject(hdc, hfont_prev);
5667 ReleaseDC(NULL, hdc);
5668}
5669
5671{
5672 HDC hdc;
5673 LOGFONTA lf;
5674 HFONT hfont, hfont_prev;
5675 GLYPHMETRICS gm;
5677 TEXTMETRICW tmW;
5678 DWORD ret;
5679
5680 memset(&lf, 0, sizeof(lf));
5681 lf.lfHeight = 72;
5682 lstrcpyA(lf.lfFaceName, "wine_test");
5683
5684 SetLastError(0xdeadbeef);
5686 ok(hfont != 0, "CreateFontIndirectA error %u\n", GetLastError());
5687
5688 hdc = GetDC(NULL);
5689
5690 hfont_prev = SelectObject(hdc, hfont);
5691 ok(hfont_prev != NULL, "SelectObject failed\n");
5692
5693 SetLastError(0xdeadbeef);
5695 ok(ret, "GetTextMetrics error %u\n", GetLastError());
5696
5697 GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
5698 ok(gm.gmptGlyphOrigin.y <= tm.tmAscent,
5699 "Glyph top(%d) exceeds ascent(%d)\n",
5700 gm.gmptGlyphOrigin.y, tm.tmAscent);
5701 GetGlyphOutlineA(hdc, 'D', GGO_METRICS, &gm, 0, NULL, &mat);
5702 ok(gm.gmptGlyphOrigin.y - gm.gmBlackBoxY >= -tm.tmDescent,
5703 "Glyph bottom(%d) exceeds descent(%d)\n",
5704 gm.gmptGlyphOrigin.y - gm.gmBlackBoxY, -tm.tmDescent);
5705
5706 /* Test tmLastChar - wine_test has code points fffb-fffe mapped to glyph 0 */
5707 GetTextMetricsW(hdc, &tmW);
5709 ok( tmW.tmLastChar == 0xfffe, "got %04x\n", tmW.tmLastChar);
5710
5711 SelectObject(hdc, hfont_prev);
5713 ReleaseDC(NULL, hdc);
5714}
5715
5716static void test_fstype_fixup(void)
5717{
5718 HDC hdc;
5719 LOGFONTA lf;
5720 HFONT hfont, hfont_prev;
5721 DWORD ret;
5722 OUTLINETEXTMETRICA *otm;
5723 DWORD otm_size;
5724
5725 memset(&lf, 0, sizeof(lf));
5726 lf.lfHeight = 72;
5727 lstrcpyA(lf.lfFaceName, "wine_test");
5728
5729 SetLastError(0xdeadbeef);
5731 ok(hfont != 0, "CreateFontIndirectA error %u\n", GetLastError());
5732
5733 hdc = GetDC(NULL);
5734
5735 hfont_prev = SelectObject(hdc, hfont);
5736 ok(hfont_prev != NULL, "SelectObject failed\n");
5737
5738 otm_size = GetOutlineTextMetricsA(hdc, 0, NULL);
5739 otm = HeapAlloc(GetProcessHeap(), 0, otm_size);
5740 otm->otmSize = sizeof(*otm);
5741 ret = GetOutlineTextMetricsA(hdc, otm->otmSize, otm);
5742 ok(ret == otm->otmSize, "expected %u, got %u, error %d\n", otm->otmSize, ret, GetLastError());
5743
5744 /* Test font has fsType set to 0x7fff, test that reserved bits are filtered out,
5745 valid bits are 1, 2, 3, 8, 9. */
5746 ok((otm->otmfsType & ~0x30e) == 0, "fsType %#x\n", otm->otmfsType);
5747
5748 HeapFree(GetProcessHeap(), 0, otm);
5749
5750 SelectObject(hdc, hfont_prev);
5752 ReleaseDC(NULL, hdc);
5753}
5754
5756{
5757 char ttf_name[MAX_PATH];
5758 char tmp_path[MAX_PATH];
5759 char fot_name[MAX_PATH];
5760 char *file_part;
5761 DWORD ret;
5762 int i;
5763
5764 if (!pAddFontResourceExA || !pRemoveFontResourceExA)
5765 {
5766 win_skip("AddFontResourceExA is not available on this platform\n");
5767 return;
5768 }
5769
5770 if (!write_ttf_file("wine_test.ttf", ttf_name))
5771 {
5772 skip("Failed to create ttf file for testing\n");
5773 return;
5774 }
5775
5776 trace("created %s\n", ttf_name);
5777
5778 ret = is_truetype_font_installed("wine_test");
5779 ok(!ret, "font wine_test should not be enumerated\n");
5780
5781 ret = GetTempPathA(MAX_PATH, tmp_path);
5782 ok(ret, "GetTempPath() error %d\n", GetLastError());
5783 ret = GetTempFileNameA(tmp_path, "fot", 0, fot_name);
5784 ok(ret, "GetTempFileName() error %d\n", GetLastError());
5785
5786 ret = GetFileAttributesA(fot_name);
5787 ok(ret != INVALID_FILE_ATTRIBUTES, "file %s does not exist\n", fot_name);
5788
5789 SetLastError(0xdeadbeef);
5790 ret = CreateScalableFontResourceA(0, fot_name, ttf_name, NULL);
5791 ok(!ret, "CreateScalableFontResource() should fail\n");
5792 ok(GetLastError() == ERROR_FILE_EXISTS, "not expected error %d\n", GetLastError());
5793
5794 SetLastError(0xdeadbeef);
5795 ret = CreateScalableFontResourceA(0, fot_name, ttf_name, "");
5796 ok(!ret, "CreateScalableFontResource() should fail\n");
5797 ok(GetLastError() == ERROR_FILE_EXISTS, "not expected error %d\n", GetLastError());
5798
5799 file_part = strrchr(ttf_name, '\\');
5800 SetLastError(0xdeadbeef);
5801 ret = CreateScalableFontResourceA(0, fot_name, file_part, tmp_path);
5802 ok(!ret, "CreateScalableFontResource() should fail\n");
5803 ok(GetLastError() == ERROR_FILE_EXISTS, "not expected error %d\n", GetLastError());
5804
5805 SetLastError(0xdeadbeef);
5806 ret = CreateScalableFontResourceA(0, fot_name, "random file name", tmp_path);
5807 ok(!ret, "CreateScalableFontResource() should fail\n");
5808 ok(GetLastError() == ERROR_INVALID_PARAMETER, "not expected error %d\n", GetLastError());
5809
5810 SetLastError(0xdeadbeef);
5811 ret = CreateScalableFontResourceA(0, fot_name, NULL, ttf_name);
5812 ok(!ret, "CreateScalableFontResource() should fail\n");
5813 ok(GetLastError() == ERROR_INVALID_PARAMETER, "not expected error %d\n", GetLastError());
5814
5815 ret = DeleteFileA(fot_name);
5816 ok(ret, "DeleteFile() error %d\n", GetLastError());
5817
5818 ret = pRemoveFontResourceExA(fot_name, 0, 0);
5819 ok(!ret, "RemoveFontResourceEx() should fail\n");
5820
5821 /* test public font resource */
5822 SetLastError(0xdeadbeef);
5823 ret = CreateScalableFontResourceA(0, fot_name, ttf_name, NULL);
5824 ok(ret, "CreateScalableFontResource() error %d\n", GetLastError());
5825
5826 ret = is_truetype_font_installed("wine_test");
5827 ok(!ret, "font wine_test should not be enumerated\n");
5828
5829 SetLastError(0xdeadbeef);
5830 ret = pAddFontResourceExA(fot_name, 0, 0);
5831 ok(ret, "AddFontResourceEx() error %d\n", GetLastError());
5832
5833 ret = is_truetype_font_installed("wine_test");
5834 ok(ret, "font wine_test should be enumerated\n");
5835
5839
5840 ret = pRemoveFontResourceExA(fot_name, FR_PRIVATE, 0);
5841 ok(!ret, "RemoveFontResourceEx() with not matching flags should fail\n");
5842
5843 SetLastError(0xdeadbeef);
5844 ret = pRemoveFontResourceExA(fot_name, 0, 0);
5845 ok(ret, "RemoveFontResourceEx() error %d\n", GetLastError());
5846
5847 ret = is_truetype_font_installed("wine_test");
5848 ok(!ret, "font wine_test should not be enumerated\n");
5849
5850 ret = pRemoveFontResourceExA(fot_name, 0, 0);
5851 ok(!ret, "RemoveFontResourceEx() should fail\n");
5852
5853 /* test refcounting */
5854 for (i = 0; i < 5; i++)
5855 {
5856 SetLastError(0xdeadbeef);
5857 ret = pAddFontResourceExA(fot_name, 0, 0);
5858 ok(ret, "AddFontResourceEx() error %d\n", GetLastError());
5859 }
5860 for (i = 0; i < 5; i++)
5861 {
5862 SetLastError(0xdeadbeef);
5863 ret = pRemoveFontResourceExA(fot_name, 0, 0);
5864 ok(ret, "RemoveFontResourceEx() error %d\n", GetLastError());
5865 }
5866 ret = pRemoveFontResourceExA(fot_name, 0, 0);
5867 ok(!ret, "RemoveFontResourceEx() should fail\n");
5868
5869 DeleteFileA(fot_name);
5870
5871 /* test hidden font resource */
5872 SetLastError(0xdeadbeef);
5873 ret = CreateScalableFontResourceA(1, fot_name, ttf_name, NULL);
5874 ok(ret, "CreateScalableFontResource() error %d\n", GetLastError());
5875
5876 ret = is_truetype_font_installed("wine_test");
5877 ok(!ret, "font wine_test should not be enumerated\n");
5878
5879 SetLastError(0xdeadbeef);
5880 ret = pAddFontResourceExA(fot_name, 0, 0);
5881 ok(ret, "AddFontResourceEx() error %d\n", GetLastError());
5882
5883 ret = is_truetype_font_installed("wine_test");
5884 todo_wine
5885 ok(!ret, "font wine_test should not be enumerated\n");
5886
5887 /* XP allows removing a private font added with 0 flags */
5888 SetLastError(0xdeadbeef);
5889 ret = pRemoveFontResourceExA(fot_name, FR_PRIVATE, 0);
5890 ok(ret, "RemoveFontResourceEx() error %d\n", GetLastError());
5891
5892 ret = is_truetype_font_installed("wine_test");
5893 ok(!ret, "font wine_test should not be enumerated\n");
5894
5895 ret = pRemoveFontResourceExA(fot_name, 0, 0);
5896 ok(!ret, "RemoveFontResourceEx() should fail\n");
5897
5898 DeleteFileA(fot_name);
5899 DeleteFileA(ttf_name);
5900}
5901
5902static void check_vertical_font(const char *name, BOOL *installed, BOOL *selected, GLYPHMETRICS *gm, WORD *gi)
5903{
5904 LOGFONTA lf;
5905 HFONT hfont, hfont_prev;
5906 HDC hdc;
5907 char facename[100];
5908 DWORD ret;
5909 static const WCHAR str[] = { 0x2025 };
5910
5911 *installed = is_truetype_font_installed(name);
5912
5913 lf.lfHeight = -18;
5914 lf.lfWidth = 0;
5915 lf.lfEscapement = 0;
5916 lf.lfOrientation = 0;
5917 lf.lfWeight = FW_DONTCARE;
5918 lf.lfItalic = 0;
5919 lf.lfUnderline = 0;
5920 lf.lfStrikeOut = 0;
5926 strcpy(lf.lfFaceName, name);
5927
5929 ok(hfont != NULL, "CreateFontIndirectA failed\n");
5930
5931 hdc = GetDC(NULL);
5932
5933 hfont_prev = SelectObject(hdc, hfont);
5934 ok(hfont_prev != NULL, "SelectObject failed\n");
5935
5936 ret = GetTextFaceA(hdc, sizeof facename, facename);
5937 ok(ret, "GetTextFaceA failed\n");
5938 *selected = !strcmp(facename, name);
5939
5940 ret = GetGlyphOutlineW(hdc, 0x2025, GGO_METRICS, gm, 0, NULL, &mat);
5941 ok(ret != GDI_ERROR, "GetGlyphOutlineW failed\n");
5942 if (!*selected)
5943 memset(gm, 0, sizeof *gm);
5944
5945 ret = pGetGlyphIndicesW(hdc, str, 1, gi, 0);
5946 ok(ret != GDI_ERROR, "GetGlyphIndicesW failed\n");
5947
5948 SelectObject(hdc, hfont_prev);
5950 ReleaseDC(NULL, hdc);
5951}
5952
5953static void check_vertical_metrics(const char *face)
5954{
5955 LOGFONTA lf;
5956 HFONT hfont, hfont_prev;
5957 HDC hdc;
5958 DWORD ret;
5959 GLYPHMETRICS rgm, vgm;
5960 const UINT code = 0x5EAD, height = 1000;
5961 WORD idx;
5962 ABC abc, vabc;
5964 USHORT numOfLongVerMetrics;
5965
5966 hdc = GetDC(NULL);
5967
5968 memset(&lf, 0, sizeof(lf));
5969 strcpy(lf.lfFaceName, face);
5970 lf.lfHeight = -height;
5972 lf.lfEscapement = lf.lfOrientation = 900;
5974 hfont_prev = SelectObject(hdc, hfont);
5975 ret = GetGlyphOutlineW(hdc, code, GGO_METRICS, &rgm, 0, NULL, &mat);
5976 ok(ret != GDI_ERROR, "GetGlyphOutlineW failed\n");
5978 ok(ret, "GetCharABCWidthsW failed\n");
5979 DeleteObject(SelectObject(hdc, hfont_prev));
5980
5981 memset(&lf, 0, sizeof(lf));
5982 strcpy(lf.lfFaceName, "@");
5983 strcat(lf.lfFaceName, face);
5984 lf.lfHeight = -height;
5987 hfont_prev = SelectObject(hdc, hfont);
5988 ret = GetGlyphOutlineW(hdc, code, GGO_METRICS, &vgm, 0, NULL, &mat);
5989 ok(ret != GDI_ERROR, "GetGlyphOutlineW failed\n");
5990 ret = GetCharABCWidthsW(hdc, code, code, &vabc);
5991 ok(ret, "GetCharABCWidthsW failed\n");
5992 ok(vabc.abcA == vgm.gmptGlyphOrigin.x, "expected %d, got %d\n",
5993 vabc.abcA, vgm.gmptGlyphOrigin.x);
5994 ok(vabc.abcB == vgm.gmBlackBoxX, "expected %d, got %d\n",
5995 vabc.abcB, vgm.gmBlackBoxX);
5996 ok(vabc.abcA + vabc.abcB + vabc.abcC == vgm.gmCellIncX,
5997 "expected %d, got %d\n",
5998 vabc.abcA + vabc.abcB + vabc.abcC, vgm.gmCellIncX);
5999
6000 memset(&otm, 0, sizeof(otm));
6001 otm.otmSize = sizeof(otm);
6002 ret = GetOutlineTextMetricsA(hdc, sizeof(otm), &otm);
6003 ok(ret != 0, "GetOutlineTextMetricsA failed\n");
6004
6005 if (GetFontData(hdc, MS_MAKE_TAG('v','h','e','a'), sizeof(SHORT) * 17,
6006 &numOfLongVerMetrics, sizeof(numOfLongVerMetrics)) != GDI_ERROR) {
6007 int offset;
6008 SHORT topSideBearing;
6009
6010 if (!pGetGlyphIndicesW) {
6011 win_skip("GetGlyphIndices is not available on this platform\n");
6012 }
6013 else {
6014 ret = pGetGlyphIndicesW(hdc, (LPCWSTR)&code, 1, &idx, 0);
6015 ok(ret != 0, "GetGlyphIndicesW failed\n");
6016 numOfLongVerMetrics = GET_BE_WORD(numOfLongVerMetrics);
6017 if (numOfLongVerMetrics > idx)
6018 offset = idx * 2 + 1;
6019 else
6020 offset = numOfLongVerMetrics * 2 + (idx - numOfLongVerMetrics);
6021 ret = GetFontData(hdc, MS_MAKE_TAG('v','m','t','x'), offset * sizeof(SHORT),
6022 &topSideBearing, sizeof(SHORT));
6023 ok(ret != GDI_ERROR, "GetFontData(vmtx) failed\n");
6024 topSideBearing = GET_BE_WORD(topSideBearing);
6026 MulDiv(topSideBearing, height, otm.otmEMSquare), FALSE),
6027 "expected %d, got %d\n",
6028 MulDiv(topSideBearing, height, otm.otmEMSquare), vgm.gmptGlyphOrigin.x);
6029 }
6030 }
6031 else
6032 {
6033 ok(vgm.gmptGlyphOrigin.x == rgm.gmptGlyphOrigin.x + vgm.gmCellIncX + otm.otmDescent,
6034 "got %d, expected rgm.origin.x(%d) + vgm.cellIncX(%d) + descent(%d)\n",
6036 }
6037
6038 ok(vgm.gmptGlyphOrigin.y == abc.abcA + abc.abcB + otm.otmDescent ||
6039 broken(vgm.gmptGlyphOrigin.y == abc.abcA + abc.abcB - otm.otmTextMetrics.tmDescent) /* win2k */,
6040 "got %d, expected abcA(%d) + abcB(%u) + descent(%d)\n",
6042
6043 DeleteObject(SelectObject(hdc, hfont_prev));
6044 ReleaseDC(NULL, hdc);
6045}
6046
6047static void test_vertical_font(void)
6048{
6049 char ttf_name[MAX_PATH];
6050 int num, i;
6051 BOOL ret, installed, selected;
6052 GLYPHMETRICS gm;
6053 WORD hgi, vgi;
6054 const char* face_list[] = {
6055 "@WineTestVertical", /* has vmtx table */
6056 "@Ume Gothic", /* doesn't have vmtx table */
6057 "@MS UI Gothic", /* has vmtx table, available on native */
6058 };
6059
6060 if (!pAddFontResourceExA || !pRemoveFontResourceExA || !pGetGlyphIndicesW)
6061 {
6062 win_skip("AddFontResourceExA or GetGlyphIndicesW is not available on this platform\n");
6063 return;
6064 }
6065
6066 if (!write_ttf_file("vertical.ttf", ttf_name))
6067 {
6068 skip("Failed to create ttf file for testing\n");
6069 return;
6070 }
6071
6072 num = pAddFontResourceExA(ttf_name, FR_PRIVATE, 0);
6073 ok(num == 2, "AddFontResourceExA should add 2 fonts from vertical.ttf\n");
6074
6075 check_vertical_font("WineTestVertical", &installed, &selected, &gm, &hgi);
6076 ok(installed, "WineTestVertical is not installed\n");
6077 ok(selected, "WineTestVertical is not selected\n");
6078 ok(gm.gmBlackBoxX > gm.gmBlackBoxY,
6079 "gmBlackBoxX(%u) should be greater than gmBlackBoxY(%u) if horizontal\n",
6080 gm.gmBlackBoxX, gm.gmBlackBoxY);
6081
6082 check_vertical_font("@WineTestVertical", &installed, &selected, &gm, &vgi);
6083 ok(installed, "@WineTestVertical is not installed\n");
6084 ok(selected, "@WineTestVertical is not selected\n");
6085 ok(gm.gmBlackBoxX > gm.gmBlackBoxY,
6086 "gmBlackBoxX(%u) should be less than gmBlackBoxY(%u) if vertical\n",
6087 gm.gmBlackBoxX, gm.gmBlackBoxY);
6088
6089 ok(hgi != vgi, "same glyph h:%u v:%u\n", hgi, vgi);
6090
6091 for (i = 0; i < sizeof(face_list)/sizeof(face_list[0]); i++) {
6092 const char* face = face_list[i];
6094 skip("%s is not installed\n", face);
6095 continue;
6096 }
6097 trace("Testing %s...\n", face);
6099 }
6100
6101 ret = pRemoveFontResourceExA(ttf_name, FR_PRIVATE, 0);
6102 ok(ret, "RemoveFontResourceEx() error %d\n", GetLastError());
6103
6104 DeleteFileA(ttf_name);
6105}
6106
6109{
6110 if (lf->lfFaceName[0] == '@') {
6111 return 0;
6112 }
6113 return 1;
6114}
6115
6117{
6118 HDC hdc;
6121 size_t i;
6122
6123 hdc = GetDC(NULL);
6124
6125 for (i = 0; i < sizeof(charset)/sizeof(charset[0]); i++)
6126 {
6127 LOGFONTA lf;
6128 HFONT hfont;
6129 char face_name[LF_FACESIZE];
6130 int ret;
6131
6132 memset(&lf, 0, sizeof lf);
6133 lf.lfFaceName[0] = '\0';
6134 lf.lfCharSet = charset[i];
6135
6137 {
6138 skip("Vertical font for charset %u is not installed\n", charset[i]);
6139 continue;
6140 }
6141
6144 memset(face_name, 0, sizeof face_name);
6145 ret = GetTextFaceA(hdc, sizeof face_name, face_name);
6146 ok(ret && face_name[0] != '@',
6147 "expected non-vertical face for charset %u, got %s\n", charset[i], face_name);
6149
6150 memset(&lf, 0, sizeof lf);
6151 strcpy(lf.lfFaceName, "@");
6152 lf.lfCharSet = charset[i];
6155 memset(face_name, 0, sizeof face_name);
6156 ret = GetTextFaceA(hdc, sizeof face_name, face_name);
6157 ok(ret && face_name[0] == '@',
6158 "expected vertical face for charset %u, got %s\n", charset[i], face_name);
6160 }
6161 ReleaseDC(NULL, hdc);
6162}
6163
6164static int get_font_dpi(const LOGFONTA *lf, int *height)
6165{
6167 HFONT hfont;
6169 int ret;
6170
6172 ok(hfont != 0, "CreateFontIndirect failed\n");
6173
6176 ok(ret, "GetTextMetrics failed\n");
6177 ret = tm.tmDigitizedAspectX;
6178 if (height) *height = tm.tmHeight;
6179
6180 DeleteDC(hdc);
6182
6183 return ret;
6184}
6185
6186static void test_stock_fonts(void)
6187{
6188 static const int font[] =
6189 {
6191 /* SYSTEM_FIXED_FONT, OEM_FIXED_FONT */
6192 };
6193 static const struct test_data
6194 {
6195 int charset, weight, height, height_pixels, dpi;
6196 const char face_name[LF_FACESIZE];
6197 WORD lang_id;
6198 } td[][12] =
6199 {
6200 { /* ANSI_FIXED_FONT */
6201 { ANSI_CHARSET, FW_NORMAL, 12, 12, 96, "Courier", LANG_ARABIC },
6202 { ANSI_CHARSET, FW_NORMAL, 12, 12, 96, "Courier", LANG_HEBREW},
6203 { DEFAULT_CHARSET, FW_NORMAL, 12, 13, 96, "Courier" },
6204 { DEFAULT_CHARSET, FW_NORMAL, 12, 13, 120, "Courier" },
6205 { 0 }
6206 },
6207 { /* ANSI_VAR_FONT */
6208 { DEFAULT_CHARSET, FW_NORMAL, 12, 13, 96, "MS Sans Serif" },
6209 { DEFAULT_CHARSET, FW_NORMAL, 12, 13, 120, "MS Sans Serif" },
6210 { 0 }
6211 },
6212 { /* SYSTEM_FONT */
6213 { SHIFTJIS_CHARSET, FW_NORMAL, 18, 18, 96, "System" },
6214 { SHIFTJIS_CHARSET, FW_NORMAL, 22, 22, 120, "System" },
6215 { HANGEUL_CHARSET, FW_NORMAL, 16, 16, 96, "System" },
6216 { HANGEUL_CHARSET, FW_NORMAL, 20, 20, 120, "System" },
6217 { DEFAULT_CHARSET, FW_BOLD, 16, 16, 96, "System" },
6218 { DEFAULT_CHARSET, FW_BOLD, 20, 20, 120, "System" },
6219 { 0 }
6220 },
6221 { /* DEVICE_DEFAULT_FONT */
6222 { SHIFTJIS_CHARSET, FW_NORMAL, 18, 18, 96, "System" },
6223 { SHIFTJIS_CHARSET, FW_NORMAL, 22, 22, 120, "System" },
6224 { HANGEUL_CHARSET, FW_NORMAL, 16, 16, 96, "System" },
6225 { HANGEUL_CHARSET, FW_NORMAL, 20, 20, 120, "System" },
6226 { DEFAULT_CHARSET, FW_BOLD, 16, 16, 96, "System" },
6227 { DEFAULT_CHARSET, FW_BOLD, 20, 20, 120, "System" },
6228 { 0 }
6229 },
6230 { /* DEFAULT_GUI_FONT */
6231 { SHIFTJIS_CHARSET, FW_NORMAL, -11, 13, 96, "MS Shell Dlg" },
6232 { SHIFTJIS_CHARSET, FW_NORMAL, -12, 15, 96, "?MS UI Gothic" },
6233 { SHIFTJIS_CHARSET, FW_NORMAL, -15, 18, 120, "?MS UI Gothic" },
6234 { HANGEUL_CHARSET, FW_NORMAL, -12, 15, 96, "?Gulim" },
6235 { HANGEUL_CHARSET, FW_NORMAL, -15, 18, 120, "?Gulim" },
6236 { GB2312_CHARSET, FW_NORMAL, -12, 15, 96, "?SimHei" },
6237 { GB2312_CHARSET, FW_NORMAL, -15, 18, 120, "?SimHei" },
6238 { CHINESEBIG5_CHARSET, FW_NORMAL, -12, 15, 96, "?MingLiU" },
6239 { CHINESEBIG5_CHARSET, FW_NORMAL, -15, 18, 120, "?MingLiU" },
6240 { DEFAULT_CHARSET, FW_NORMAL, -11, 13, 96, "MS Shell Dlg" },
6241 { DEFAULT_CHARSET, FW_NORMAL, -13, 16, 120, "MS Shell Dlg" },
6242 { 0 }
6243 }
6244 };
6245 int i, j;
6246
6247 for (i = 0; i < sizeof(font)/sizeof(font[0]); i++)
6248 {
6249 HFONT hfont;
6250 LOGFONTA lf;
6251 int ret, height;
6252
6254 ok(hfont != 0, "%d: GetStockObject(%d) failed\n", i, font[i]);
6255
6256 ret = GetObjectA(hfont, sizeof(lf), &lf);
6257 if (ret != sizeof(lf))
6258 {
6259 /* NT4 */
6260 win_skip("%d: GetObject returned %d instead of sizeof(LOGFONT)\n", i, ret);
6261 continue;
6262 }
6263
6264 for (j = 0; td[i][j].face_name[0] != 0; j++)
6265 {
6266 if ((lf.lfCharSet != td[i][j].charset && td[i][j].charset != DEFAULT_CHARSET) ||
6267 (system_lang_id != td[i][j].lang_id && td[i][j].lang_id != LANG_NEUTRAL) ||
6268 (td[i][j].face_name[0] != '?' && strcmp(lf.lfFaceName, td[i][j].face_name)))
6269 {
6270 continue;
6271 }
6272
6273 ret = get_font_dpi(&lf, &height);
6274 if (ret != td[i][j].dpi)
6275 {
6276 trace("%d(%d): font %s %d dpi doesn't match test data %d\n",
6277 i, j, lf.lfFaceName, ret, td[i][j].dpi);
6278 continue;
6279 }
6280
6281 /* FIXME: Remove once Wine is fixed */
6282 todo_wine_if (td[i][j].dpi != 96 &&
6283 /* MS Sans Serif for 120 dpi and higher should include 12 pixel bitmap set */
6284 ((!strcmp(td[i][j].face_name, "MS Sans Serif") && td[i][j].height == 12) ||
6285 /* System for 120 dpi and higher should include 20 pixel bitmap set */
6286 (!strcmp(td[i][j].face_name, "System") && td[i][j].height > 16)))
6287 ok(height == td[i][j].height_pixels, "%d(%d): expected height %d, got %d\n", i, j, td[i][j].height_pixels, height);
6288
6289 ok(td[i][j].weight == lf.lfWeight, "%d(%d): expected lfWeight %d, got %d\n", i, j, td[i][j].weight, lf.lfWeight);
6290 ok(td[i][j].height == lf.lfHeight, "%d(%d): expected lfHeight %d, got %d\n", i, j, td[i][j].height, lf.lfHeight);
6291 if (td[i][j].face_name[0] == '?')
6292 {
6293 /* Wine doesn't have this font, skip this case for now.
6294 Actually, the face name is localized on Windows and varies
6295 dpending on Windows versions (e.g. Japanese NT4 vs win2k). */
6296 trace("%d(%d): default gui font is %s\n", i, j, lf.lfFaceName);
6297 }
6298 else
6299 {
6300 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);
6301 }
6302 break;
6303 }
6304 }
6305}
6306
6307static void test_max_height(void)
6308{
6309 HDC hdc;
6310 LOGFONTA lf;
6311 HFONT hfont, hfont_old;
6312 TEXTMETRICA tm1, tm;
6313 BOOL r;
6314 LONG invalid_height[] = { -65536, -123456, 123456 };
6315 size_t i;
6316
6317 memset(&tm1, 0, sizeof(tm1));
6318 memset(&lf, 0, sizeof(lf));
6319 strcpy(lf.lfFaceName, "Tahoma");
6320 lf.lfHeight = -1;
6321
6322 hdc = GetDC(NULL);
6323
6324 /* get 1 ppem value */
6326 hfont_old = SelectObject(hdc, hfont);
6327 r = GetTextMetricsA(hdc, &tm1);
6328 ok(r, "GetTextMetrics failed\n");
6329 ok(tm1.tmHeight > 0, "expected a positive value, got %d\n", tm1.tmHeight);
6330 ok(tm1.tmAveCharWidth > 0, "expected a positive value, got %d\n", tm1.tmHeight);
6331 DeleteObject(SelectObject(hdc, hfont_old));
6332
6333 /* test the largest value */
6334 lf.lfHeight = -((1 << 16) - 1);
6336 hfont_old = SelectObject(hdc, hfont);
6337 memset(&tm, 0, sizeof(tm));
6338 r = GetTextMetricsA(hdc, &tm);
6339 ok(r, "GetTextMetrics failed\n");
6340 ok(tm.tmHeight > tm1.tmHeight,
6341 "expected greater than 1 ppem value (%d), got %d\n", tm1.tmHeight, tm.tmHeight);
6342 ok(tm.tmAveCharWidth > tm1.tmAveCharWidth,
6343 "expected greater than 1 ppem value (%d), got %d\n", tm1.tmAveCharWidth, tm.tmAveCharWidth);
6344 DeleteObject(SelectObject(hdc, hfont_old));
6345
6346 /* test an invalid value */
6347 for (i = 0; i < sizeof(invalid_height)/sizeof(invalid_height[0]); i++) {
6348 lf.lfHeight = invalid_height[i];
6350 hfont_old = SelectObject(hdc, hfont);
6351 memset(&tm, 0, sizeof(tm));
6352 r = GetTextMetricsA(hdc, &tm);
6353 ok(r, "GetTextMetrics failed\n");
6354 ok(tm.tmHeight == tm1.tmHeight,
6355 "expected 1 ppem value (%d), got %d\n", tm1.tmHeight, tm.tmHeight);
6356 ok(tm.tmAveCharWidth == tm1.tmAveCharWidth,
6357 "expected 1 ppem value (%d), got %d\n", tm1.tmAveCharWidth, tm.tmAveCharWidth);
6358 DeleteObject(SelectObject(hdc, hfont_old));
6359 }
6360
6361 ReleaseDC(NULL, hdc);
6362 return;
6363}
6364
6365static void test_vertical_order(void)
6366{
6367 struct enum_font_data efd;
6368 LOGFONTA lf;
6369 HDC hdc;
6370 int i, j;
6371
6373 ok(hdc != NULL, "CreateCompatibleDC failed\n");
6374
6375 memset(&lf, 0, sizeof(lf));
6378 lf.lfHeight = 16;
6379 lf.lfWidth = 16;
6381 lf.lfItalic = FALSE;
6383 memset( &efd, 0, sizeof(efd) );
6385 for (i = 0; i < efd.total; i++)
6386 {
6387 if (efd.lf[i].lfFaceName[0] != '@') continue;
6388 for (j = 0; j < efd.total; j++)
6389 {
6390 if (!strcmp(efd.lf[i].lfFaceName + 1, efd.lf[j].lfFaceName))
6391 {
6392 ok(i > j,"Found vertical font %s before its horizontal version\n", efd.lf[i].lfFaceName);
6393 break;
6394 }
6395 }
6396 }
6397 heap_free( efd.lf );
6398 DeleteDC( hdc );
6399}
6400
6401static void test_GetCharWidth32(void)
6402{
6403 BOOL ret;
6404 HDC hdc;
6405 LOGFONTA lf;
6406 HFONT hfont;
6407 INT bufferA;
6408 INT bufferW;
6409 HWND hwnd;
6410
6411 if (!pGetCharWidth32A || !pGetCharWidth32W)
6412 {
6413 win_skip("GetCharWidth32A/W not available on this platform\n");
6414 return;
6415 }
6416
6417 memset(&lf, 0, sizeof(lf));
6418 strcpy(lf.lfFaceName, "System");
6419 lf.lfHeight = 20;
6420
6422 hdc = GetDC(0);
6424
6425 ret = pGetCharWidth32W(hdc, 'a', 'a', &bufferW);
6426 ok(ret, "GetCharWidth32W should have succeeded\n");
6427 ret = pGetCharWidth32A(hdc, 'a', 'a', &bufferA);
6428 ok(ret, "GetCharWidth32A should have succeeded\n");
6429 ok (bufferA == bufferW, "Widths should be the same\n");
6430 ok (bufferA > 0," Width should be greater than zero\n");
6431
6434 ReleaseDC(NULL, hdc);
6435
6436 memset(&lf, 0, sizeof(lf));
6437 strcpy(lf.lfFaceName, "Tahoma");
6438 lf.lfHeight = 20;
6439
6441 hwnd = CreateWindowExA(0, "static", "", WS_POPUP, 0,0,100,100,
6442 0, 0, 0, NULL);
6443 hdc = GetDC(hwnd);
6446
6447 ret = pGetCharWidth32W(hdc, 'a', 'a', &bufferW);
6448 ok(ret, "GetCharWidth32W should have succeeded\n");
6449 ok (bufferW > 0," Width should be greater than zero\n");
6450 SetWindowExtEx(hdc, -1,-1,NULL);
6452 ret = pGetCharWidth32W(hdc, 'a', 'a', &bufferW);
6453 ok(ret, "GetCharWidth32W should have succeeded\n");
6454 ok (bufferW > 0," Width should be greater than zero\n");
6456 ret = pGetCharWidth32W(hdc, 'a', 'a', &bufferW);
6457 ok(ret, "GetCharWidth32W should have succeeded\n");
6458 ok (bufferW > 0," Width should be greater than zero\n");
6459 SetWindowExtEx(hdc, 1,1,NULL);
6461 ret = pGetCharWidth32W(hdc, 'a', 'a', &bufferW);
6462 ok(ret, "GetCharWidth32W should have succeeded\n");
6463 ok (bufferW > 0," Width should be greater than zero\n");
6465 ret = pGetCharWidth32W(hdc, 'a', 'a', &bufferW);
6466 ok(ret, "GetCharWidth32W should have succeeded\n");
6467 ok (bufferW > 0," Width should be greater than zero\n");
6468
6469 ReleaseDC(hwnd, hdc);
6471
6472 hwnd = CreateWindowExA(WS_EX_LAYOUTRTL, "static", "", WS_POPUP, 0,0,100,100,
6473 0, 0, 0, NULL);
6474 hdc = GetDC(hwnd);
6477
6478 ret = pGetCharWidth32W(hdc, 'a', 'a', &bufferW);
6479 ok(ret, "GetCharWidth32W should have succeeded\n");
6480 ok (bufferW > 0," Width should be greater than zero\n");
6481 SetWindowExtEx(hdc, -1,-1,NULL);
6483 ret = pGetCharWidth32W(hdc, 'a', 'a', &bufferW);
6484 ok(ret, "GetCharWidth32W should have succeeded\n");
6485 ok (bufferW > 0," Width should be greater than zero\n");
6487 ret = pGetCharWidth32W(hdc, 'a', 'a', &bufferW);
6488 ok(ret, "GetCharWidth32W should have succeeded\n");
6489 ok (bufferW > 0," Width should be greater than zero\n");
6490 SetWindowExtEx(hdc, 1,1,NULL);
6492 ret = pGetCharWidth32W(hdc, 'a', 'a', &bufferW);
6493 ok(ret, "GetCharWidth32W should have succeeded\n");
6494 ok (bufferW > 0," Width should be greater than zero\n");
6496 ret = pGetCharWidth32W(hdc, 'a', 'a', &bufferW);
6497 ok(ret, "GetCharWidth32W should have succeeded\n");
6498 ok (bufferW > 0," Width should be greater than zero\n");
6499
6500 ReleaseDC(hwnd, hdc);
6503}
6504
6505static void test_fake_bold_font(void)
6506{
6507 static const MAT2 x2_mat = { {0,2}, {0,0}, {0,0}, {0,2} };
6508 HDC hdc;
6509 LOGFONTA lf;
6510 BOOL ret;
6511 struct glyph_data {
6513 ABC abc;
6514 INT w;
6515 GLYPHMETRICS gm;
6516 } data[4];
6517 int i;
6518 DWORD r;
6519
6520 if (!pGetCharWidth32A || !pGetCharABCWidthsA) {
6521 win_skip("GetCharWidth32A/GetCharABCWidthA is not available on this platform\n");
6522 return;
6523 }
6524
6525 /* Test outline font */
6526 memset(&lf, 0, sizeof(lf));
6527 strcpy(lf.lfFaceName, "Wingdings");
6529
6530 hdc = GetDC(NULL);
6531
6532 for (i = 0; i <= 1; i++)
6533 {
6534 HFONT hfont, hfont_old;
6535
6536 lf.lfWeight = i ? FW_BOLD : FW_NORMAL;
6538 hfont_old = SelectObject(hdc, hfont);
6539
6541 ok(ret, "got %d\n", ret);
6542 ret = pGetCharABCWidthsA(hdc, 0x76, 0x76, &data[i].abc);
6543 ok(ret, "got %d\n", ret);
6544 data[i].w = data[i].abc.abcA + data[i].abc.abcB + data[i].abc.abcC;
6545 r = GetGlyphOutlineA(hdc, 0x76, GGO_METRICS, &data[i].gm, 0, NULL, &x2_mat);
6546 ok(r != GDI_ERROR, "got %d\n", ret);
6547
6548 SelectObject(hdc, hfont_old);
6550 }
6551 ReleaseDC(NULL, hdc);
6552
6553 /* compare results (outline) */
6554 ok(data[0].tm.tmHeight == data[1].tm.tmHeight,
6555 "expected %d, got %d\n", data[0].tm.tmHeight, data[1].tm.tmHeight);
6556 ok(data[0].tm.tmAscent == data[1].tm.tmAscent,
6557 "expected %d, got %d\n", data[0].tm.tmAscent, data[1].tm.tmAscent);
6558 ok(data[0].tm.tmDescent == data[1].tm.tmDescent,
6559 "expected %d, got %d\n", data[0].tm.tmDescent, data[1].tm.tmDescent);
6560 ok(data[0].tm.tmAveCharWidth + 1 == data[1].tm.tmAveCharWidth,
6561 "expected %d, got %d\n", data[0].tm.tmAveCharWidth + 1, data[1].tm.tmAveCharWidth);
6562 ok(data[0].tm.tmMaxCharWidth + 1 == data[1].tm.tmMaxCharWidth,
6563 "expected %d, got %d\n", data[0].tm.tmMaxCharWidth + 1, data[1].tm.tmMaxCharWidth);
6564 ok(data[0].tm.tmOverhang == data[1].tm.tmOverhang,
6565 "expected %d, got %d\n", data[0].tm.tmOverhang, data[1].tm.tmOverhang);
6566 ok(data[0].w + 1 == data[1].w,
6567 "expected %d, got %d\n", data[0].w + 1, data[1].w);
6568
6569 ok(data[0].gm.gmCellIncX + 1 == data[1].gm.gmCellIncX,
6570 "expected %d, got %d\n", data[0].gm.gmCellIncX + 1, data[1].gm.gmCellIncX);
6571 ok(data[0].gm.gmCellIncY == data[1].gm.gmCellIncY,
6572 "expected %d, got %d\n", data[0].gm.gmCellIncY, data[1].gm.gmCellIncY);
6573
6574 /* Test bitmap font */
6575 memset(&data, 0xaa, sizeof(data));
6576 memset(&lf, 0, sizeof(lf));
6577 strcpy(lf.lfFaceName, "Courier");
6579
6580 hdc = GetDC(NULL);
6581
6582 for (i = 0; i < 4; i++)
6583 {
6584 HFONT hfont, hfont_old;
6585
6586 lf.lfWeight = (i % 2) ? FW_BOLD : FW_NORMAL;
6587 lf.lfHeight = (i > 1) ? data[0].tm.tmHeight * x2_mat.eM11.value : 0;
6589 hfont_old = SelectObject(hdc, hfont);
6590
6592 ok(ret, "got %d\n", ret);
6593 ret = pGetCharWidth32A(hdc, 0x76, 0x76, &data[i].w);
6594 ok(ret, "got %d\n", ret);
6595
6596 SelectObject(hdc, hfont_old);
6598 }
6599 ReleaseDC(NULL, hdc);
6600
6601 /* compare results (bitmap) */
6602 for (i = 0; i < 4; i+=2)
6603 {
6604 int diff = (i > 1) ? x2_mat.eM11.value : 1;
6605 if (data[i].tm.tmPitchAndFamily & TMPF_TRUETYPE)
6606 {
6607 skip("TrueType font is selected (expected a bitmap one)\n");
6608 continue;
6609 }
6610 ok(data[i].tm.tmHeight == data[i+1].tm.tmHeight,
6611 "expected %d, got %d\n", data[i].tm.tmHeight, data[i+1].tm.tmHeight);
6612 ok(data[i].tm.tmAscent == data[i+1].tm.tmAscent,
6613 "expected %d, got %d\n", data[i].tm.tmAscent, data[i+1].tm.tmAscent);
6614 ok(data[i].tm.tmDescent == data[i+1].tm.tmDescent,
6615 "expected %d, got %d\n", data[i].tm.tmDescent, data[i+1].tm.tmDescent);
6616 ok(data[i+1].tm.tmAveCharWidth - data[i].tm.tmAveCharWidth == diff,
6617 "expected %d, got %d\n", diff, data[i+1].tm.tmAveCharWidth - data[i].tm.tmAveCharWidth);
6618 ok(data[i+1].tm.tmMaxCharWidth - data[i].tm.tmMaxCharWidth == diff,
6619 "expected %d, got %d\n", diff, data[i+1].tm.tmMaxCharWidth - data[i].tm.tmMaxCharWidth);
6620 ok(data[i].tm.tmOverhang == 0,
6621 "expected 0, got %d\n", data[i].tm.tmOverhang);
6622 ok(data[i+1].tm.tmOverhang == 1,
6623 "expected 1, got %d\n", data[i+1].tm.tmOverhang);
6624 ok(data[i].w + 1 == data[i+1].w,
6625 "expected %d, got %d\n", data[i].w + 1, data[i+1].w);
6626 }
6627}
6628
6630{
6631 const WCHAR text[] = {'#','!','/','b','i','n','/','s','h',0};
6632 const struct {
6633 LPCSTR face;
6634 BYTE charset;
6635 } bitmap_font_list[] = {
6636 { "Courier", ANSI_CHARSET },
6637 { "Small Fonts", ANSI_CHARSET },
6638 { "Fixedsys", DEFAULT_CHARSET },
6639 { "System", DEFAULT_CHARSET }
6640 };
6641 HDC hdc;
6642 LOGFONTA lf;
6643 HFONT hFont;
6644 CHAR facename[LF_FACESIZE];
6645 BITMAPINFO bmi;
6646 HBITMAP hBmp[2];
6647 void *pixels[2];
6648 int i, j;
6649 DWORD ret;
6650 BITMAP bmp;
6652 CHARSETINFO ci;
6653 BYTE chr = '\xA9';
6654
6655 if (!pGetGlyphIndicesW || !pGetGlyphIndicesA) {
6656 win_skip("GetGlyphIndices is unavailable\n");
6657 return;
6658 }
6659
6661 ok(hdc != NULL, "CreateCompatibleDC failed\n");
6662
6663 memset(&bmi, 0, sizeof(bmi));
6664 bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
6665 bmi.bmiHeader.biBitCount = 32;
6666 bmi.bmiHeader.biPlanes = 1;
6667 bmi.bmiHeader.biWidth = 128;
6668 bmi.bmiHeader.biHeight = 32;
6670
6671 for (i = 0; i < sizeof(bitmap_font_list)/sizeof(bitmap_font_list[0]); i++) {
6672 memset(&lf, 0, sizeof(lf));
6673 lf.lfCharSet = bitmap_font_list[i].charset;
6674 strcpy(lf.lfFaceName, bitmap_font_list[i].face);
6676 ok(hFont != NULL, "Can't create font (%s:%d)\n", lf.lfFaceName, lf.lfCharSet);
6679 ok(ret, "GetTextMetric failed\n");
6680 ret = GetTextFaceA(hdc, sizeof(facename), facename);
6681 ok(ret, "GetTextFace failed\n");
6682 if (tm.tmPitchAndFamily & TMPF_TRUETYPE) {
6683 skip("TrueType font (%s) was selected for \"%s\"\n", facename, bitmap_font_list[i].face);
6684 continue;
6685 }
6686 if (lstrcmpiA(facename, lf.lfFaceName) != 0) {
6687 skip("expected %s, got %s\n", lf.lfFaceName, facename);
6688 continue;
6689 }
6690
6691 for (j = 0; j < 2; j++) {
6692 HBITMAP hBmpPrev;
6693 hBmp[j] = CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS, &pixels[j], NULL, 0);
6694 ok(hBmp[j] != NULL, "Can't create DIB\n");
6695 hBmpPrev = SelectObject(hdc, hBmp[j]);
6696 switch (j) {
6697 case 0:
6698 ret = ExtTextOutW(hdc, 0, 0, 0, NULL, text, lstrlenW(text), NULL);
6699 break;
6700 case 1:
6701 {
6702 int len = lstrlenW(text);
6703 LPWORD indices = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WORD));
6704 ret = pGetGlyphIndicesW(hdc, text, len, indices, 0);
6705 ok(ret, "GetGlyphIndices failed\n");
6706 ok(memcmp(indices, text, sizeof(WORD) * len) == 0,
6707 "Glyph indices and text are different for %s:%d\n", lf.lfFaceName, tm.tmCharSet);
6708 ret = ExtTextOutW(hdc, 0, 0, ETO_GLYPH_INDEX, NULL, indices, len, NULL);
6710 break;
6711 }
6712 }
6713 ok(ret, "ExtTextOutW failed\n");
6714 SelectObject(hdc, hBmpPrev);
6715 }
6716
6717 GetObjectA(hBmp[0], sizeof(bmp), &bmp);
6718 ok(memcmp(pixels[0], pixels[1], bmp.bmHeight * bmp.bmWidthBytes) == 0,
6719 "Images are different (%s:%d)\n", lf.lfFaceName, tm.tmCharSet);
6720
6722 if (!ret) {
6723 skip("Can't get charset info for (%s:%d)\n", lf.lfFaceName, tm.tmCharSet);
6724 goto next;
6725 }
6726 if (IsDBCSLeadByteEx(ci.ciACP, chr)) {
6727 skip("High-ascii character is not defined in codepage %d\n", ci.ciACP);
6728 goto next;
6729 }
6730
6731 for (j = 0; j < 2; j++) {
6732 HBITMAP hBmpPrev;
6733 WORD code;
6734 hBmpPrev = SelectObject(hdc, hBmp[j]);
6735 switch (j) {
6736 case 0:
6737 ret = ExtTextOutA(hdc, 100, 0, 0, NULL, (LPCSTR)&chr, 1, NULL);
6738 break;
6739 case 1:
6740 ret = pGetGlyphIndicesA(hdc, (LPCSTR)&chr, 1, &code, 0);
6741 ok(ret, "GetGlyphIndices failed\n");
6742 ok(code == chr, "expected %02x, got %02x (%s:%d)\n", chr, code, lf.lfFaceName, tm.tmCharSet);
6743 ret = ExtTextOutA(hdc, 100, 0, ETO_GLYPH_INDEX, NULL, (LPCSTR)&code, 1, NULL);
6744 break;
6745 }
6746 ok(ret, "ExtTextOutA failed\n");
6747 SelectObject(hdc, hBmpPrev);
6748 }
6749
6750 ok(memcmp(pixels[0], pixels[1], bmp.bmHeight * bmp.bmWidthBytes) == 0,
6751 "Images are different (%s:%d)\n", lf.lfFaceName, tm.tmCharSet);
6752 next:
6753 for (j = 0; j < 2; j++)
6754 DeleteObject(hBmp[j]);
6757 }
6758
6759 DeleteDC(hdc);
6760}
6761
6762static void test_GetCharWidthI(void)
6763{
6764 static const char *teststr = "wine ";
6765 HFONT hfont, prev_hfont;
6766 WORD glyphs[5];
6767 INT widths[5];
6768 LOGFONTA lf;
6769 ABC abc[5];
6770 int len, i;
6771 DWORD nb;
6772 BOOL ret;
6773 HDC hdc;
6774
6775 memset(&lf, 0, sizeof(lf));
6776 strcpy(lf.lfFaceName, "Tahoma");
6777 lf.lfHeight = -20;
6778
6779 hdc = GetDC(0);
6780
6782 prev_hfont = SelectObject(hdc, hfont);
6783
6784 len = strlen(teststr);
6785 nb = GetGlyphIndicesA(hdc, teststr, len, glyphs, 0);
6786 ok(nb == len, "\n");
6787
6788 memset(abc, 0xcc, sizeof(abc));
6790 ok(ret, "GetCharABCWidthsI failed\n");
6791
6792 memset(widths, 0xcc, sizeof(widths));
6793 ret = GetCharWidthI(hdc, 0, len, glyphs, widths);
6794 ok(ret, "GetCharWidthI failed\n");
6795
6796 for (i = 0; i < len; i++)
6797 ok(widths[i] == abc[i].abcA + abc[i].abcB + abc[i].abcC, "%u, glyph %u, got width %d\n",
6798 i, glyphs[i], widths[i]);
6799
6800 DeleteObject(SelectObject(hdc, prev_hfont));
6801 ReleaseDC(0, hdc);
6802}
6803
6805{
6806 BOOL *found_font = (BOOL *)lparam;
6807 *found_font = TRUE;
6808 return 1;
6809}
6810
6811static void test_long_names(void)
6812{
6813 char ttf_name[MAX_PATH];
6814 LOGFONTA font = {0};
6815 HFONT handle_font;
6816 BOOL found_font;
6817 int ret;
6818 HDC dc;
6819
6820 if (!write_ttf_file("wine_longname.ttf", ttf_name))
6821 {
6822 skip("Failed to create ttf file for testing\n");
6823 return;
6824 }
6825
6826 dc = GetDC(NULL);
6827
6828 ret = AddFontResourceExA(ttf_name, FR_PRIVATE, 0);
6829 ok(ret, "AddFontResourceEx() failed\n");
6830
6831 strcpy(font.lfFaceName, "wine_3_this_is_a_very_long_name");
6832 found_font = FALSE;
6833 EnumFontFamiliesExA(dc, &font, long_enum_proc, (LPARAM)&found_font, 0);
6834 ok(found_font == TRUE, "EnumFontFamiliesExA didn't find font.\n");
6835
6836 strcpy(font.lfFaceName, "wine_2_this_is_a_very_long_name");
6837 found_font = FALSE;
6838 EnumFontFamiliesExA(dc, &font, long_enum_proc, (LPARAM)&found_font, 0);
6839 ok(found_font == TRUE, "EnumFontFamiliesExA didn't find font.\n");
6840
6841 strcpy(font.lfFaceName, "wine_1_this_is_a_very_long_name");
6842 found_font = FALSE;
6843 EnumFontFamiliesExA(dc, &font, long_enum_proc, (LPARAM)&found_font, 0);
6844 ok(found_font == FALSE, "EnumFontFamiliesExA must not find font.\n");
6845
6846 handle_font = CreateFontIndirectA(&font);
6847 ok(handle_font != NULL, "CreateFontIndirectA failed\n");
6848 DeleteObject(handle_font);
6849
6850 ret = RemoveFontResourceExA(ttf_name, FR_PRIVATE, 0);
6851 ok(ret, "RemoveFontResourceEx() failed\n");
6852
6853 DeleteFileA(ttf_name);
6854 ReleaseDC(NULL, dc);
6855}
6856
6858{
6859 init();
6860
6862 test_logfont();
6882
6883 /* On Windows Arial has a lot of default charset aliases such as Arial Cyr,
6884 * I'd like to avoid them in this test.
6885 */
6886 test_EnumFontFamilies("Arial Black", ANSI_CHARSET);
6888 if (is_truetype_font_installed("Arial Black") &&
6889 (is_truetype_font_installed("Symbol") || is_truetype_font_installed("Wingdings")))
6890 {
6894 }
6895 else
6896 skip("Arial Black or Symbol/Wingdings is not installed\n");
6902 test_GetTextMetrics2("Tahoma", -11);
6903 test_GetTextMetrics2("Tahoma", -55);
6904 test_GetTextMetrics2("Tahoma", -110);
6905 test_GetTextMetrics2("Arial", -11);
6906 test_GetTextMetrics2("Arial", -55);
6907 test_GetTextMetrics2("Arial", -110);
6912 test_fullname();
6922
6923 /* These tests should be last test until RemoveFontResource
6924 * is properly implemented.
6925 */
6928}
static HFONT hfont
InitDirComponents & cd
@ lparam
Definition: SystemMenu.c:31
#define broken(x)
Definition: _sntprintf.h:21
char * strcat(char *DstString, const char *SrcString)
Definition: utclib.c:568
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
#define read
Definition: acwin.h:96
static BOOL heap_free(void *mem)
Definition: appwiz.h:76
static void * heap_realloc(void *mem, size_t len)
Definition: appwiz.h:71
#define trace
Definition: atltest.h:70
#define ok(value,...)
Definition: atltest.h:57
#define skip(...)
Definition: atltest.h:64
#define START_TEST(x)
Definition: atltest.h:75
HFONT hFont
Definition: main.c:53
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:92
CFF_Charset charset
Definition: cffcmap.c:138
LPARAM lParam
Definition: combotst.c:139
#define ERROR_INSUFFICIENT_BUFFER
Definition: dderror.h:10
#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 GetProcessHeap()
Definition: compat.h:736
#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 HeapAlloc
Definition: compat.h:733
#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 HeapFree(x, y, z)
Definition: compat.h:735
#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 HEAP_ZERO_MEMORY
Definition: compat.h:134
#define lstrlenW
Definition: compat.h:750
static const WCHAR version[]
Definition: asmname.c:66
#define TT_APPLE_ID_ISO_10646
Definition: font.c:1177
#define MS_OS2_TAG
Definition: font.c:116
static WORD get_mac_code_page(const tt_name_record *name)
Definition: font.c:1344
#define TT_MAC_ID_SIMPLIFIED_CHINESE
Definition: font.c:1183
#define TT_MS_ID_UNICODE_CS
Definition: font.c:1181
#define TT_PLATFORM_MICROSOFT
Definition: font.c:1174
#define TT_APPLE_ID_DEFAULT
Definition: font.c:1176
#define TT_APPLE_ID_UNICODE_2_0
Definition: font.c:1178
#define TT_PLATFORM_MACINTOSH
Definition: font.c:1173
#define TT_MS_ID_SYMBOL_CS
Definition: font.c:1180
static INT CALLBACK is_font_installed_proc(const LOGFONTW *elf, const TEXTMETRICW *ntm, DWORD type, LPARAM lParam)
Definition: font.c:632
static int match_name_table_language(const tt_name_record *name, LANGID lang)
Definition: font.c:1351
#define TT_PLATFORM_APPLE_UNICODE
Definition: font.c:1172
#define GET_BE_WORD(x)
Definition: font.c:109
#define GET_BE_DWORD(x)
Definition: font.c:110
static const LANGID mac_langid_table[]
Definition: font.c:1220
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:896
DWORD WINAPI GetFileAttributesA(LPCSTR lpFileName)
Definition: fileinfo.c:636
BOOL WINAPI WriteFile(IN HANDLE hFile, IN LPCVOID lpBuffer, IN DWORD nNumberOfBytesToWrite OPTIONAL, OUT LPDWORD lpNumberOfBytesWritten, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: rw.c:24
HMODULE WINAPI DECLSPEC_HOTPATCH GetModuleHandleA(LPCSTR lpModuleName)
Definition: loader.c:812
UINT WINAPI GetWindowsDirectoryA(OUT LPSTR lpBuffer, IN UINT uSize)
Definition: path.c:2337
DWORD WINAPI GetTempPathA(IN DWORD nBufferLength, OUT LPSTR lpBuffer)
Definition: path.c:2054
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
BOOL WINAPI IsDBCSLeadByteEx(UINT CodePage, BYTE TestByte)
Definition: nls.c:2337
BOOL WINAPI IsValidCodePage(UINT CodePage)
Definition: nls.c:1604
const WCHAR * text
Definition: package.c:1799
#define assert(x)
Definition: debug.h:53
#define pt(x, y)
Definition: drawing.c:79
#define BI_RGB
Definition: precomp.h:47
#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 int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
unsigned short WORD
Definition: ntddk_ex.h:93
static FT_F26Dot6 font_size
Definition: ftrandom.c:89
pKey DeleteObject()
GLuint start
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
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: gl.h:1546
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
GLsizeiptr size
Definition: glext.h:5919
GLdouble n
Definition: glext.h:7729
GLuint res
Definition: glext.h:9613
GLenum GLenum GLenum GLenum GLenum scale
Definition: glext.h:9032
GLuint buffer
Definition: glext.h:5915
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
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
GLuint64EXT * result
Definition: glext.h:11304
GLintptr offset
Definition: glext.h:5920
GLenum target
Definition: glext.h:7315
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
static const WCHAR emptyW[]
Definition: navigate.c:40
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 wine_dbgstr_w
Definition: kernel32.h:34
LANGID WINAPI GetSystemDefaultLangID(void)
Definition: lang.c:761
LANGID WINAPI GetUserDefaultLangID(void)
Definition: lang.c:744
USHORT LANGID
Definition: mui.h:9
if(dx< 0)
Definition: linetemp.h:194
static WCHAR have_file[PORTNAME_MAXSIZE]
Definition: localmon.c:138
int WINAPI lstrcmpiA(LPCSTR lpString1, LPCSTR lpString2)
Definition: lstring.c:42
LPSTR WINAPI lstrcpyA(LPSTR lpString1, LPCSTR lpString2)
Definition: lstring.c:100
int WINAPI lstrcmpW(LPCWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:170
int WINAPI lstrcmpA(LPCSTR lpString1, LPCSTR lpString2)
Definition: lstring.c:18
static const WCHAR dc[]
__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
BITMAP bmp
Definition: alphablend.c:62
HDC hdc
Definition: main.c:9
static HBITMAP
Definition: button.c:44
static int font_height(HFONT hFont)
Definition: combo.c:612
static HDC
Definition: imagelist.c:92
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:2856
static void test_GetGlyphOutline(void)
Definition: font.c:4626
#define MS_NAME_TAG
Definition: font.c:82
static UINT UINT LPWORD LPABC abc
Definition: font.c:44
static void test_nonexistent_font(void)
Definition: font.c:4064
static INT CALLBACK arial_enum_proc(const LOGFONTA *lf, const TEXTMETRICA *tm, DWORD type, LPARAM lParam)
Definition: font.c:2804
#define TT_NAME_ID_FULL_NAME
Definition: font.c:3539
static void test_GetTextFace(void)
Definition: font.c:4424
static WCHAR * prepend_at(WCHAR *family)
Definition: font.c:5468
static void test_east_asian_font_selection(void)
Definition: font.c:6116
#define MS_CMAP_TAG
Definition: font.c:81
static void init(void)
Definition: font.c:84
static LPCSTR lpstr
Definition: font.c:51
static void test_GdiGetCharDimensions(void)
Definition: font.c:1074
static void test_GetTextMetrics(void)
Definition: font.c:4043
static UINT first
Definition: font.c:44
static void test_GetGlyphOutline_empty_contour(void)
Definition: font.c:5630
static INT CALLBACK is_truetype_font_installed_proc(const LOGFONTA *elf, const TEXTMETRICA *ntm, DWORD type, LPARAM lParam)
Definition: font.c:113
static HMODULE hgdi32
Definition: font.c:65
#define near_match(a, b)
Definition: font.c:39
#define TT_MS_LANGID_ENGLISH_UNITED_STATES
Definition: font.c:3535
static INT CALLBACK enum_font_data_proc(const LOGFONTA *lf, const TEXTMETRICA *ntm, DWORD type, LPARAM lParam)
Definition: font.c:3141
static void * get_res_data(const char *fontname, DWORD *rsrc_size)
Definition: font.c:149
static void test_text_metrics(const LOGFONTA *lf, const NEWTEXTMETRICA *ntm)
Definition: font.c:3811
static void test_GetGlyphIndices(void)
Definition: font.c:1611
static INT CALLBACK has_vertical_font_proc(const LOGFONTA *lf, const TEXTMETRICA *ntm, DWORD type, LPARAM lParam)
Definition: font.c:6107
static void test_fstype_fixup(void)
Definition: font.c:5716
static void * load_font(const char *font_name, DWORD *font_size)
Definition: font.c:5044
static void check_font(const char *test, const LOGFONTA *lf, HFONT hfont)
Definition: font.c:195
static void test_GetCharacterPlacement(void)
Definition: font.c:4942
static BOOL write_ttf_file(const char *fontname, char *tmp_name)
Definition: font.c:184
static void test_font_charset(void)
Definition: font.c:2589
static void * get_cmap(cmap_header *header, USHORT plat_id, USHORT enc_id)
Definition: font.c:3456
static void get_seg4(cmap_format_4 *cmap, USHORT seg_num, cmap_format_4_seg *seg)
Definition: font.c:3422
static WORD system_lang_id
Definition: font.c:67
static INT CALLBACK enum_fullname_data_proc(const LOGFONTA *lf, const TEXTMETRICA *ntm, DWORD type, LPARAM lParam)
Definition: font.c:3158
static void test_EnumFontFamilies(const char *font_name, INT font_charset)
Definition: font.c:2910
static void test_logfont(void)
Definition: font.c:246
static BOOL is_font_installed_fullname(const char *family, const char *fullname)
Definition: font.c:5408
static void get_charset_statsW(struct enum_font_dataW *efd, int *ansi_charset, int *symbol_charset, int *russian_charset)
Definition: font.c:2883
static INT CALLBACK enum_truetype_font_proc(const LOGFONTA *lf, const TEXTMETRICA *ntm, DWORD type, LPARAM lParam)
Definition: font.c:4031
static HFONT create_font(const char *test, const LOGFONTA *lf)
Definition: font.c:237
static BOOL get_first_last_from_cmap4(void *ptr, DWORD *first, DWORD *last, DWORD limit)
Definition: font.c:3431
static BOOL get_ttf_nametable_entry(HDC hdc, WORD name_id, WCHAR *out_buf, SIZE_T out_size, LCID language_id)
Definition: font.c:3729
static LPTEXTMETRICW lptm
Definition: font.c:42
static void test_orientation(void)
Definition: font.c:4517
static INT CALLBACK enum_with_magic_retval_proc(const LOGFONTA *elf, const TEXTMETRICA *ntm, DWORD type, LPARAM lparam)
Definition: font.c:5221
static void test_max_height(void)
Definition: font.c:6307
static void test_fake_bold_font(void)
Definition: font.c:6505
static void test_CreateFontIndirect(void)
Definition: font.c:4973
static void test_height_selection_vdmx(HDC hdc)
Definition: font.c:1956
static void test_GdiGetCodePage(void)
Definition: font.c:2641
static INT CALLBACK long_enum_proc(const LOGFONTA *lf, const TEXTMETRICA *tm, DWORD type, LPARAM lparam)
Definition: font.c:6804
static void test_GetFontUnicodeRanges(void)
Definition: font.c:2741
static void test_EnumFonts_subst(void)
Definition: font.c:5336
static void test_RealizationInfo(void)
Definition: font.c:4257
static void test_EnumFonts(void)
Definition: font.c:5226
static const MAT2 mat
Definition: font.c:66
static INT CALLBACK enum_ms_shell_dlg_proc(const LOGFONTA *lf, const TEXTMETRICA *ntm, DWORD type, LPARAM lParam)
Definition: font.c:5294
static void test_fullname2_helper(const char *Family)
Definition: font.c:5478
static void * find_ttf_table(void *ttf, DWORD size, DWORD tag)
Definition: font.c:1942
static void test_AddFontMemResource(void)
Definition: font.c:5073
static void test_GetGlyphOutline_metric_clipping(void)
Definition: font.c:5670
static const WORD INT INT LPINT nfit
Definition: font.c:54
#define match_off_by_1(a, b, exact)
Definition: font.c:38
static UINT UINT LPWORD glyphs
Definition: font.c:44
static UINT UINT last
Definition: font.c:45
static void test_negative_width(HDC hdc, const LOGFONTA *lf)
Definition: font.c:3223
static void test_outline_font(void)
Definition: font.c:489
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:4574
static void check_vertical_metrics(const char *face)
Definition: font.c:5953
#define TT_NAME_ID_UNIQUE_ID
Definition: font.c:3538
static int CALLBACK create_font_proc(const LOGFONTA *lpelfe, const TEXTMETRICA *lpntme, DWORD FontType, LPARAM lParam)
Definition: font.c:1112
static void test_CreateFontIndirectEx(void)
Definition: font.c:5008
static INT CALLBACK enum_ms_shell_dlg2_proc(const LOGFONTA *lf, const TEXTMETRICA *ntm, DWORD type, LPARAM lParam)
Definition: font.c:5315
static void test_GetCharWidthI(void)
Definition: font.c:6762
static LPCSTR INT LPWORD pgi
Definition: font.c:51
#define expect(expected, got)
Definition: font.c:40
static PVOID
Definition: font.c:57
static INT CALLBACK font_enum_proc(const LOGFONTA *elf, const TEXTMETRICA *ntm, DWORD type, LPARAM lParam)
Definition: font.c:273
static const WORD INT INT LPINT LPINT dxs
Definition: font.c:54
static INT CALLBACK find_font_proc(const LOGFONTA *elf, const TEXTMETRICA *ntm, DWORD type, LPARAM lParam)
Definition: font.c:739
#define TT_NAME_ID_FONT_FAMILY
Definition: font.c:3536
static INT CALLBACK arial_enum_procw(const LOGFONTW *lf, const TEXTMETRICW *tm, DWORD type, LPARAM lParam)
Definition: font.c:2830
static INT CALLBACK enum_fonts_proc(const LOGFONTA *elf, const TEXTMETRICA *ntm, DWORD type, LPARAM lparam)
Definition: font.c:5190
static LPCSTR INT LPWORD DWORD flags
Definition: font.c:51
#define FH_SCALE
Definition: font.c:756
static void test_oemcharset(void)
Definition: font.c:4546
static void expect_ff(const TEXTMETRICA *tmA, const TT_OS2_V4 *os2, WORD family, const char *name)
Definition: font.c:3396
#define TT_OS2_V0_SIZE
Definition: font.c:3343
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:1131
static INT CALLBACK is_font_installed_fullname_proc(const LOGFONTA *lf, const TEXTMETRICA *ntm, DWORD type, LPARAM lParam)
Definition: font.c:5398
static void test_fullname2(void)
Definition: font.c:5590
static void test_GetOutlineTextMetrics(void)
Definition: font.c:2182
static BOOL is_CJK(void)
Definition: font.c:751
static void testJustification(HDC hdc, PCSTR str, RECT *clientArea)
Definition: font.c:2306
static BOOL is_truetype_font_installed(const char *name)
Definition: font.c:120
static BOOL get_glyph_indices(INT charset, UINT code_page, WORD *idx, UINT count, BOOL unicode)
Definition: font.c:2496
static void free_font(void *font)
Definition: font.c:5039
static void test_bitmap_font_metrics(void)
Definition: font.c:757
static void test_SetTextJustification(void)
Definition: font.c:2382
static void test_text_extents(void)
Definition: font.c:1455
static BOOL get_first_last_from_cmap(HDC hdc, DWORD *first, DWORD *last, cmap_type *cmap_type)
Definition: font.c:3477
static void test_stock_fonts(void)
Definition: font.c:6186
static BOOL get_first_last_from_cmap0(void *ptr, DWORD *first, DWORD *last)
Definition: font.c:3405
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:5902
static INT CALLBACK enum_all_fonts_proc(const LOGFONTA *elf, const TEXTMETRICA *ntm, DWORD type, LPARAM lparam)
Definition: font.c:5203
static void test_long_names(void)
Definition: font.c:6811
static void compare_tm(const TEXTMETRICA *tm, const TEXTMETRICA *otm)
Definition: font.c:285
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:401
static void test_GetTextMetrics2(const char *fontname, int font_height)
Definition: font.c:4885
static void test_EnumFontFamiliesEx_default_charset(void)
Definition: font.c:3175
static BOOL is_font_installed(const char *name)
Definition: font.c:137
static void test_GetCharABCWidths(void)
Definition: font.c:1156
static INT CALLBACK enum_multi_charset_font_proc(const LOGFONTA *lf, const TEXTMETRICA *tm, DWORD type, LPARAM lParam)
Definition: font.c:3120
static const WORD INT INT max_ext
Definition: font.c:53
#define MS_MAKE_TAG(ch0, ch1, ch2, ch3)
Definition: font.c:77
static LPGLYPHSET lpgs
Definition: font.c:50
cmap_type
Definition: font.c:3471
@ cmap_ms_unicode
Definition: font.c:3473
@ cmap_none
Definition: font.c:3472
@ cmap_ms_symbol
Definition: font.c:3474
static void test_bitmap_font_glyph_index(void)
Definition: font.c:6629
static void test_vertical_order(void)
Definition: font.c:6365
static DWORD *static void DWORD *static ULONGLONG
Definition: font.c:63
static void test_fullname(void)
Definition: font.c:5420
static DWORD *static HFONT(WINAPI *pCreateFontIndirectExA)(const ENUMLOGFONTEXDVA *)
static void test_CreateScalableFontResource(void)
Definition: font.c:5755
static void test_GetCharWidth32(void)
Definition: font.c:6401
static int get_font_dpi(const LOGFONTA *lf, int *height)
Definition: font.c:6164
static void test_vertical_font(void)
Definition: font.c:6047
static BOOL write_tmp_file(const void *data, DWORD *size, char *tmp_name)
Definition: font.c:166
static void test_GetKerningPairs(void)
Definition: font.c:1679
#define TT_NAME_ID_FONT_SUBFAMILY
Definition: font.c:3537
static void test_font_metrics(void)
Definition: font.c:667
#define todo_wine_if(is_todo)
Definition: custom.c:76
#define todo_wine
Definition: custom.c:79
static HANDLE PIO_APC_ROUTINE PVOID PIO_STATUS_BLOCK ULONG PVOID ULONG PVOID ULONG out_size
Definition: file.c:100
static LPCWSTR file_name
Definition: protocol.c:147
static const char * testtext
Definition: dialog.c:1385
LONG last_char
Definition: input.c:71
#define min(a, b)
Definition: monoChain.cc:55
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:1414
#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
static int Family
Definition: ping.c:62
#define INT
Definition: polytest.cpp:20
_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(...)
static FILE * out
Definition: regtests2xml.c:44
#define test
Definition: rosglue.h:37
const WCHAR * str
_Check_return_ _CRTIMP _CONST_RETURN char *__cdecl strrchr(_In_z_ const char *_Str, _In_ int _Ch)
#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_ESPERANTO
Definition: nls.h:161
#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_MALAGASY
Definition: nls.h:153
#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 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
int winetest_debug
#define win_skip
Definition: test.h:160
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
BYTE lfItalic
Definition: dimm.idl:64
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 usMaxContext
Definition: font.c:3336
USHORT usLastCharIndex
Definition: font.c:3318
USHORT version
Definition: font.c:3294
SHORT ySubscriptYOffset
Definition: font.c:3302
ULONG ulUnicodeRange4
Definition: font.c:3314
ULONG ulCodePageRange1
Definition: font.c:3329
PANOSE panose
Definition: font.c:3310
SHORT xAvgCharWidth
Definition: font.c:3295
USHORT usDefaultChar
Definition: font.c:3334
ULONG ulUnicodeRange2
Definition: font.c:3312
SHORT ySuperscriptXSize
Definition: font.c:3303
USHORT usWinDescent
Definition: font.c:3327
SHORT ySubscriptXSize
Definition: font.c:3299
SHORT sFamilyClass
Definition: font.c:3309
SHORT ySubscriptXOffset
Definition: font.c:3301
ULONG ulUnicodeRange3
Definition: font.c:3313
USHORT usWeightClass
Definition: font.c:3296
USHORT sTypoAscender
Definition: font.c:3323
USHORT sTypoDescender
Definition: font.c:3324
SHORT sxHeight
Definition: font.c:3332
USHORT usLowerOpticalPointSize
Definition: font.c:3338
SHORT ySuperscriptXOffset
Definition: font.c:3305
USHORT usFirstCharIndex
Definition: font.c:3317
SHORT ySubscriptYSize
Definition: font.c:3300
SHORT sCapHeight
Definition: font.c:3333
ULONG ulCodePageRange2
Definition: font.c:3330
USHORT usWidthClass
Definition: font.c:3297
ULONG ulUnicodeRange1
Definition: font.c:3311
USHORT usWinAscent
Definition: font.c:3326
SHORT yStrikeoutSize
Definition: font.c:3307
SHORT ySuperscriptYOffset
Definition: font.c:3306
USHORT usBreakChar
Definition: font.c:3335
CHAR achVendID[4]
Definition: font.c:3315
USHORT fsSelection
Definition: font.c:3316
SHORT yStrikeoutPosition
Definition: font.c:3308
SHORT ySuperscriptYSize
Definition: font.c:3304
USHORT usUpperOpticalPointSize
Definition: font.c:3339
USHORT sTypoLineGap
Definition: font.c:3325
SHORT fsType
Definition: font.c:3298
FLOAT abcfA
Definition: wingdi.h:1416
FLOAT abcfC
Definition: wingdi.h:1418
FLOAT abcfB
Definition: wingdi.h:1417
Definition: wingdi.h:1410
int abcA
Definition: wingdi.h:1411
UINT abcB
Definition: wingdi.h:1412
int abcC
Definition: wingdi.h:1413
Definition: bl.h:1331
short value
Definition: wingdi.h:2470
short gmCellIncX
Definition: wingdi.h:2445
UINT gmBlackBoxY
Definition: wingdi.h:2443
UINT gmBlackBoxX
Definition: wingdi.h:2442
short gmCellIncY
Definition: wingdi.h:2446
POINT gmptGlyphOrigin
Definition: wingdi.h:2444
Definition: wingdi.h:2472
FIXED eM11
Definition: wingdi.h:2473
TEXTMETRICA otmTextMetrics
Definition: wingdi.h:2480
TEXTMETRICW otmTextMetrics
Definition: wingdi.h:2514
LONG cx
Definition: kdterminal.h:27
LONG cy
Definition: kdterminal.h:28
FLOAT eDy
Definition: wingdi.h:1726
FLOAT eM11
Definition: wingdi.h:1721
FLOAT eM21
Definition: wingdi.h:1723
FLOAT eM22
Definition: wingdi.h:1724
FLOAT eM12
Definition: wingdi.h:1722
FLOAT eDx
Definition: wingdi.h:1725
BYTE glyph_ids[256]
Definition: font.c:3364
USHORT language
Definition: font.c:3362
USHORT length
Definition: font.c:3361
USHORT format
Definition: font.c:3360
USHORT id_delta
Definition: font.c:3392
USHORT id_range_offset
Definition: font.c:3393
USHORT start_count
Definition: font.c:3391
USHORT end_count
Definition: font.c:3390
USHORT search_range
Definition: font.c:3374
USHORT end_count[1]
Definition: font.c:3378
USHORT language
Definition: font.c:3371
USHORT seg_countx2
Definition: font.c:3373
USHORT format
Definition: font.c:3369
USHORT range_shift
Definition: font.c:3376
USHORT entry_selector
Definition: font.c:3375
USHORT length
Definition: font.c:3370
USHORT num_tables
Definition: font.c:3348
USHORT version
Definition: font.c:3347
Definition: inflate.c:139
LOGFONTW * lf
Definition: font.c:2801
LOGFONTA * lf
Definition: font.c:2789
ENUMLOGFONTA * elf
Definition: font.c:2795
Definition: fci.c:127
Definition: dsound.c:943
int weight
Definition: font.c:1895
BOOL exact
Definition: font.c:1896
int dpi
Definition: font.c:1895
int requested_height
Definition: font.c:1894
int descent
Definition: font.c:1895
int int_leading
Definition: font.c:1895
int height
Definition: font.c:1895
int ext_leading
Definition: font.c:1895
const char face_name[LF_FACESIZE]
Definition: font.c:1893
int ascent
Definition: font.c:1895
Definition: ffs.h:70
Definition: name.c:39
USHORT platform_id
Definition: font.c:3544
USHORT offset
Definition: font.c:3549
USHORT encoding_id
Definition: font.c:3545
USHORT length
Definition: font.c:3548
USHORT language_id
Definition: font.c:3546
USHORT name_id
Definition: font.c:3547
USHORT biBitCount
Definition: precomp.h:37
ULONG biCompression
Definition: precomp.h:38
BITMAPINFOHEADER bmiHeader
Definition: wingdi.h:1476
FONTSIGNATURE fs
Definition: wingdi.h:1548
UINT ciCharset
Definition: wingdi.h:1546
BYTE elfStyle[LF_FACESIZE]
Definition: wingdi.h:2688
LOGFONTA elfLogFont
Definition: wingdi.h:2686
BYTE elfFullName[LF_FULLFACESIZE]
Definition: wingdi.h:2687
LOGFONTA elfLogFont
Definition: wingdi.h:2696
ENUMLOGFONTEXA elfEnumLogfontEx
Definition: wingdi.h:2774
DWORD fsUsb[4]
Definition: wingdi.h:1542
DWORD fsCsb[2]
Definition: wingdi.h:1543
CHAR lfFaceName[LF_FACESIZE]
Definition: wingdi.h:1894
UINT ntmCellHeight
Definition: wingdi.h:2640
FONTSIGNATURE ntmFontSig
Definition: wingdi.h:2672
UINT ntmCellHeight
Definition: wingdi.h:2666
BYTE bSerifStyle
Definition: wingdi.h:1870
BYTE bProportion
Definition: wingdi.h:1872
BYTE bWeight
Definition: wingdi.h:1871
BYTE bFamilyType
Definition: wingdi.h:1869
long y
Definition: polytest.cpp:48
long x
Definition: polytest.cpp:48
LONG right
Definition: windef.h:308
LONG top
Definition: windef.h:307
LONG left
Definition: windef.h:306
BYTE tmStruckOut
Definition: wingdi.h:2378
BYTE tmPitchAndFamily
Definition: wingdi.h:2379
BYTE tmCharSet
Definition: wingdi.h:2380
LONG tmDescent
Definition: wingdi.h:2363
LONG tmDigitizedAspectX
Definition: wingdi.h:2370
BYTE tmFirstChar
Definition: wingdi.h:2372
LONG tmExternalLeading
Definition: wingdi.h:2365
LONG tmWeight
Definition: wingdi.h:2368
BYTE tmBreakChar
Definition: wingdi.h:2375
LONG tmInternalLeading
Definition: wingdi.h:2364
BYTE tmLastChar
Definition: wingdi.h:2373
BYTE tmUnderlined
Definition: wingdi.h:2377
LONG tmMaxCharWidth
Definition: wingdi.h:2367
LONG tmAveCharWidth
Definition: wingdi.h:2366
BYTE tmDefaultChar
Definition: wingdi.h:2374
LONG tmAscent
Definition: wingdi.h:2362
LONG tmOverhang
Definition: wingdi.h:2369
LONG tmHeight
Definition: wingdi.h:2361
BYTE tmItalic
Definition: wingdi.h:2376
LONG tmDigitizedAspectY
Definition: wingdi.h:2371
WCHAR tmFirstChar
Definition: wingdi.h:2394
LONG tmDigitizedAspectX
Definition: wingdi.h:2392
LONG tmAscent
Definition: wingdi.h:2384
WCHAR tmBreakChar
Definition: wingdi.h:2397
WCHAR tmDefaultChar
Definition: wingdi.h:2396
WCHAR tmLastChar
Definition: wingdi.h:2395
LONG tmHeight
Definition: wingdi.h:2383
LONG tmDescent
Definition: wingdi.h:2385
Definition: ecma_167.h:138
Definition: time.h:68
#define max(a, b)
Definition: svc.c:63
int32_t INT_PTR
Definition: typedefs.h:64
uint32_t DWORD_PTR
Definition: typedefs.h:65
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
uint16_t * LPWORD
Definition: typedefs.h:56
PVOID HANDLE
Definition: typedefs.h:73
ULONG_PTR SIZE_T
Definition: typedefs.h:80
uint32_t * LPDWORD
Definition: typedefs.h:59
int32_t INT
Definition: typedefs.h:58
const char * PCSTR
Definition: typedefs.h:52
uint32_t ULONG
Definition: typedefs.h:59
#define INVALID_FILE_ATTRIBUTES
Definition: vfdcmd.c:23
static const WCHAR lang[]
Definition: wbemdisp.c:287
int ret
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:2654
BOOL WINAPI RemoveFontResourceExA(LPCSTR lpFileName, DWORD fl, PVOID pdv)
Definition: font.c:2069
#define dpi
Definition: sysparams.c:23
int codepage
Definition: win_iconv.c:156
#define ZeroMemory
Definition: winbase.h:1712
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
_In_ LONG _In_ HWND hwnd
Definition: winddi.h:4023
LONG_PTR LPARAM
Definition: windef.h:208
int * LPINT
Definition: windef.h:178
#define WINAPI
Definition: msvc.h:6
const char * description
Definition: directx.c:2497
#define ERROR_FILE_EXISTS
Definition: winerror.h:165
#define ERROR_CAN_NOT_COMPLETE
Definition: winerror.h:582
#define ERROR_NOACCESS
Definition: winerror.h:578
#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
#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 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)
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 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:1226
#define FS_ARABIC
Definition: wingdi.h:566
#define FF_SCRIPT
Definition: wingdi.h:451
#define OUT_TT_ONLY_PRECIS
Definition: wingdi.h:422
#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
#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 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:1539
#define MM_ANISOTROPIC
Definition: wingdi.h:867
HDC WINAPI CreateCompatibleDC(_In_opt_ HDC hdc)
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
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 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 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
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 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 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)
#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
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
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
BOOL WINAPI GetTextExtentPointA(_In_ HDC hdc, _In_reads_(c) LPCSTR lpString, _In_ int c, _Out_ LPSIZE lpsz)
#define SHIFTJIS_CHARSET
Definition: wingdi.h:386
#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)
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
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
#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 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
UINT WINAPI GetACP(void)
Definition: nls.c:2307
#define CP_SYMBOL
Definition: winnls.h:234
#define LANG_MANX_GAELIC
Definition: winnt_old.h:420
#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)
const char * LPCSTR
Definition: xmlstorage.h:183
char * LPSTR
Definition: xmlstorage.h:182
unsigned char UCHAR
Definition: xmlstorage.h:181
__wchar_t WCHAR
Definition: xmlstorage.h:180
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
char CHAR
Definition: xmlstorage.h:175
unsigned char BYTE
Definition: xxhash.c:193