fix some gdi32 font winetests
[reactos.git] / reactos / dll / win32 / gdi32 / objects / font.c
1 /* $Id$
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS system libraries
5 * FILE: lib/gdi32/object/font.c
6 * PURPOSE:
7 * PROGRAMMER:
8 *
9 */
10
11 #include "precomp.h"
12
13 #define NDEBUG
14 #include <debug.h>
15
16 /*
17 * For TranslateCharsetInfo
18 */
19 #define MAXTCIINDEX 32
20 static const CHARSETINFO FONT_tci[MAXTCIINDEX] = {
21 /* ANSI */
22 { ANSI_CHARSET, 1252, {{0,0,0,0},{FS_LATIN1,0}} },
23 { EASTEUROPE_CHARSET, 1250, {{0,0,0,0},{FS_LATIN2,0}} },
24 { RUSSIAN_CHARSET, 1251, {{0,0,0,0},{FS_CYRILLIC,0}} },
25 { GREEK_CHARSET, 1253, {{0,0,0,0},{FS_GREEK,0}} },
26 { TURKISH_CHARSET, 1254, {{0,0,0,0},{FS_TURKISH,0}} },
27 { HEBREW_CHARSET, 1255, {{0,0,0,0},{FS_HEBREW,0}} },
28 { ARABIC_CHARSET, 1256, {{0,0,0,0},{FS_ARABIC,0}} },
29 { BALTIC_CHARSET, 1257, {{0,0,0,0},{FS_BALTIC,0}} },
30 { VIETNAMESE_CHARSET, 1258, {{0,0,0,0},{FS_VIETNAMESE,0}} },
31 /* reserved by ANSI */
32 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
33 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
34 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
35 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
36 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
37 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
38 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
39 /* ANSI and OEM */
40 { THAI_CHARSET, 874, {{0,0,0,0},{FS_THAI,0}} },
41 { SHIFTJIS_CHARSET, 932, {{0,0,0,0},{FS_JISJAPAN,0}} },
42 { GB2312_CHARSET, 936, {{0,0,0,0},{FS_CHINESESIMP,0}} },
43 { HANGEUL_CHARSET, 949, {{0,0,0,0},{FS_WANSUNG,0}} },
44 { CHINESEBIG5_CHARSET, 950, {{0,0,0,0},{FS_CHINESETRAD,0}} },
45 { JOHAB_CHARSET, 1361, {{0,0,0,0},{FS_JOHAB,0}} },
46 /* reserved for alternate ANSI and OEM */
47 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
48 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
49 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
50 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
51 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
52 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
53 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
54 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
55 /* reserved for system */
56 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
57 { SYMBOL_CHARSET, CP_SYMBOL, {{0,0,0,0},{FS_SYMBOL,0}} }
58 };
59
60 #define INITIAL_FAMILY_COUNT 64
61
62 /***********************************************************************
63 * TEXTMETRIC conversion functions.
64 */
65 static void FONT_TextMetricWToA(const TEXTMETRICW *ptmW, LPTEXTMETRICA ptmA )
66 {
67 ptmA->tmHeight = ptmW->tmHeight;
68 ptmA->tmAscent = ptmW->tmAscent;
69 ptmA->tmDescent = ptmW->tmDescent;
70 ptmA->tmInternalLeading = ptmW->tmInternalLeading;
71 ptmA->tmExternalLeading = ptmW->tmExternalLeading;
72 ptmA->tmAveCharWidth = ptmW->tmAveCharWidth;
73 ptmA->tmMaxCharWidth = ptmW->tmMaxCharWidth;
74 ptmA->tmWeight = ptmW->tmWeight;
75 ptmA->tmOverhang = ptmW->tmOverhang;
76 ptmA->tmDigitizedAspectX = ptmW->tmDigitizedAspectX;
77 ptmA->tmDigitizedAspectY = ptmW->tmDigitizedAspectY;
78 ptmA->tmFirstChar = ptmW->tmFirstChar > 255 ? 255 : ptmW->tmFirstChar;
79 ptmA->tmLastChar = ptmW->tmLastChar > 255 ? 255 : ptmW->tmLastChar;
80 ptmA->tmDefaultChar = ptmW->tmDefaultChar > 255 ? 255 : ptmW->tmDefaultChar;
81 ptmA->tmBreakChar = ptmW->tmBreakChar > 255 ? 255 : ptmW->tmBreakChar;
82 ptmA->tmItalic = ptmW->tmItalic;
83 ptmA->tmUnderlined = ptmW->tmUnderlined;
84 ptmA->tmStruckOut = ptmW->tmStruckOut;
85 ptmA->tmPitchAndFamily = ptmW->tmPitchAndFamily;
86 ptmA->tmCharSet = ptmW->tmCharSet;
87 }
88
89 /***********************************************************************
90 * FONT_mbtowc
91 *
92 * Returns a Unicode translation of str using the charset of the
93 * currently selected font in hdc. If count is -1 then str is assumed
94 * to be '\0' terminated, otherwise it contains the number of bytes to
95 * convert. If plenW is non-NULL, on return it will point to the
96 * number of WCHARs that have been written. If pCP is non-NULL, on
97 * return it will point to the codepage used in the conversion. The
98 * caller should free the returned LPWSTR from the process heap
99 * itself.
100 */
101 static LPWSTR FONT_mbtowc(HDC hdc, LPCSTR str, INT count, INT *plenW, UINT *pCP)
102 {
103 UINT cp = GdiGetCodePage( hdc );
104 INT lenW;
105 LPWSTR strW;
106
107 if(count == -1) count = strlen(str);
108 lenW = MultiByteToWideChar(cp, 0, str, count, NULL, 0);
109 strW = HeapAlloc(GetProcessHeap(), 0, lenW*sizeof(WCHAR));
110 MultiByteToWideChar(cp, 0, str, count, strW, lenW);
111 DPRINT("mapped %s -> %S\n", str, strW);
112 if(plenW) *plenW = lenW;
113 if(pCP) *pCP = cp;
114 return strW;
115 }
116
117
118 static BOOL FASTCALL
119 MetricsCharConvert(WCHAR w, UCHAR *b)
120 {
121 UNICODE_STRING WString;
122 WCHAR WBuf[2];
123 ANSI_STRING AString;
124 CHAR ABuf[2];
125 NTSTATUS Status;
126
127 if (L'\0' == w)
128 {
129 *b = '\0';
130 }
131 else
132 {
133 WBuf[0] = w;
134 WBuf[1] = L'\0';
135 RtlInitUnicodeString(&WString, WBuf);
136 ABuf[0] = '*';
137 ABuf[1] = L'\0';
138 RtlInitAnsiString(&AString, ABuf);
139
140 Status = RtlUnicodeStringToAnsiString(&AString, &WString, FALSE);
141 if (! NT_SUCCESS(Status))
142 {
143 SetLastError(RtlNtStatusToDosError(Status));
144 return FALSE;
145 }
146 *b = ABuf[0];
147 }
148
149 return TRUE;
150 }
151
152 BOOL FASTCALL
153 TextMetricW2A(TEXTMETRICA *tma, TEXTMETRICW *tmw)
154 {
155 UNICODE_STRING WString;
156 WCHAR WBuf[256];
157 ANSI_STRING AString;
158 CHAR ABuf[256];
159 UINT Letter;
160 NTSTATUS Status;
161
162 tma->tmHeight = tmw->tmHeight;
163 tma->tmAscent = tmw->tmAscent;
164 tma->tmDescent = tmw->tmDescent;
165 tma->tmInternalLeading = tmw->tmInternalLeading;
166 tma->tmExternalLeading = tmw->tmExternalLeading;
167 tma->tmAveCharWidth = tmw->tmAveCharWidth;
168 tma->tmMaxCharWidth = tmw->tmMaxCharWidth;
169 tma->tmWeight = tmw->tmWeight;
170 tma->tmOverhang = tmw->tmOverhang;
171 tma->tmDigitizedAspectX = tmw->tmDigitizedAspectX;
172 tma->tmDigitizedAspectY = tmw->tmDigitizedAspectY;
173
174 /* The Unicode FirstChar/LastChar need not correspond to the ANSI
175 FirstChar/LastChar. For example, if the font contains glyphs for
176 letters A-Z and an accented version of the letter e, the Unicode
177 FirstChar would be A and the Unicode LastChar would be the accented
178 e. If you just translate those to ANSI, the range would become
179 letters A-E instead of A-Z.
180 We translate all possible ANSI chars to Unicode and find the first
181 and last translated character which fall into the Unicode FirstChar/
182 LastChar range and return the corresponding ANSI char. */
183
184 /* Setup an Ansi string containing all possible letters (note: skip '\0' at
185 the beginning since that would be interpreted as end-of-string, handle
186 '\0' special later */
187 for (Letter = 1; Letter < 256; Letter++)
188 {
189 ABuf[Letter - 1] = (CHAR) Letter;
190 WBuf[Letter - 1] = L' ';
191 }
192 ABuf[255] = '\0';
193 WBuf[255] = L'\0';
194 RtlInitAnsiString(&AString, ABuf);
195 RtlInitUnicodeString(&WString, WBuf);
196
197 /* Find the corresponding Unicode characters */
198 Status = RtlAnsiStringToUnicodeString(&WString, &AString, FALSE);
199 if (! NT_SUCCESS(Status))
200 {
201 SetLastError(RtlNtStatusToDosError(Status));
202 return FALSE;
203 }
204
205 /* Scan for the first ANSI character which maps to an Unicode character
206 in the range */
207 tma->tmFirstChar = '\0';
208 if (L'\0' != tmw->tmFirstChar)
209 {
210 for (Letter = 1; Letter < 256; Letter++)
211 {
212 if (tmw->tmFirstChar <= WBuf[Letter - 1] &&
213 WBuf[Letter - 1] <= tmw->tmLastChar)
214 {
215 tma->tmFirstChar = (CHAR) Letter;
216 break;
217 }
218 }
219 }
220
221 /* Scan for the last ANSI character which maps to an Unicode character
222 in the range */
223 tma->tmLastChar = '\0';
224 if (L'\0' != tmw->tmLastChar)
225 {
226 for (Letter = 255; 0 < Letter; Letter--)
227 {
228 if (tmw->tmFirstChar <= WBuf[Letter - 1] &&
229 WBuf[Letter - 1] <= tmw->tmLastChar)
230 {
231 tma->tmLastChar = (CHAR) Letter;
232 break;
233 }
234 }
235 }
236
237 if (! MetricsCharConvert(tmw->tmDefaultChar, &tma->tmDefaultChar) ||
238 ! MetricsCharConvert(tmw->tmBreakChar, &tma->tmBreakChar))
239 {
240 return FALSE;
241 }
242
243 tma->tmItalic = tmw->tmItalic;
244 tma->tmUnderlined = tmw->tmUnderlined;
245 tma->tmStruckOut = tmw->tmStruckOut;
246 tma->tmPitchAndFamily = tmw->tmPitchAndFamily;
247 tma->tmCharSet = tmw->tmCharSet;
248
249 return TRUE;
250 }
251
252 BOOL FASTCALL
253 NewTextMetricW2A(NEWTEXTMETRICA *tma, NEWTEXTMETRICW *tmw)
254 {
255 if (! TextMetricW2A((TEXTMETRICA *) tma, (TEXTMETRICW *) tmw))
256 {
257 return FALSE;
258 }
259
260 tma->ntmFlags = tmw->ntmFlags;
261 tma->ntmSizeEM = tmw->ntmSizeEM;
262 tma->ntmCellHeight = tmw->ntmCellHeight;
263 tma->ntmAvgWidth = tmw->ntmAvgWidth;
264
265 return TRUE;
266 }
267
268 BOOL FASTCALL
269 NewTextMetricExW2A(NEWTEXTMETRICEXA *tma, NEWTEXTMETRICEXW *tmw)
270 {
271 if (! NewTextMetricW2A(&tma->ntmTm, &tmw->ntmTm))
272 {
273 return FALSE;
274 }
275
276 tma->ntmFontSig = tmw->ntmFontSig;
277
278 return TRUE;
279 }
280
281 static int FASTCALL
282 IntEnumFontFamilies(HDC Dc, LPLOGFONTW LogFont, PVOID EnumProc, LPARAM lParam,
283 BOOL Unicode)
284 {
285 int FontFamilyCount;
286 int FontFamilySize;
287 PFONTFAMILYINFO Info;
288 int Ret = 0;
289 int i;
290 ENUMLOGFONTEXA EnumLogFontExA;
291 NEWTEXTMETRICEXA NewTextMetricExA;
292
293 Info = RtlAllocateHeap(GetProcessHeap(), 0,
294 INITIAL_FAMILY_COUNT * sizeof(FONTFAMILYINFO));
295 if (NULL == Info)
296 {
297 return 0;
298 }
299 FontFamilyCount = NtGdiGetFontFamilyInfo(Dc, LogFont, Info, INITIAL_FAMILY_COUNT);
300 if (FontFamilyCount < 0)
301 {
302 RtlFreeHeap(GetProcessHeap(), 0, Info);
303 return 0;
304 }
305 if (INITIAL_FAMILY_COUNT < FontFamilyCount)
306 {
307 FontFamilySize = FontFamilyCount;
308 RtlFreeHeap(GetProcessHeap(), 0, Info);
309 Info = RtlAllocateHeap(GetProcessHeap(), 0,
310 FontFamilyCount * sizeof(FONTFAMILYINFO));
311 if (NULL == Info)
312 {
313 return 0;
314 }
315 FontFamilyCount = NtGdiGetFontFamilyInfo(Dc, LogFont, Info, FontFamilySize);
316 if (FontFamilyCount < 0 || FontFamilySize < FontFamilyCount)
317 {
318 RtlFreeHeap(GetProcessHeap(), 0, Info);
319 return 0;
320 }
321 }
322
323 for (i = 0; i < FontFamilyCount; i++)
324 {
325 if (Unicode)
326 {
327 Ret = ((FONTENUMPROCW) EnumProc)(
328 (VOID*)&Info[i].EnumLogFontEx,
329 (VOID*)&Info[i].NewTextMetricEx,
330 Info[i].FontType, lParam);
331 }
332 else
333 { // Could use EnumLogFontExW2A here?
334 LogFontW2A(&EnumLogFontExA.elfLogFont, &Info[i].EnumLogFontEx.elfLogFont);
335 WideCharToMultiByte(CP_THREAD_ACP, 0, Info[i].EnumLogFontEx.elfFullName, -1,
336 (LPSTR)EnumLogFontExA.elfFullName, LF_FULLFACESIZE, NULL, NULL);
337 WideCharToMultiByte(CP_THREAD_ACP, 0, Info[i].EnumLogFontEx.elfStyle, -1,
338 (LPSTR)EnumLogFontExA.elfStyle, LF_FACESIZE, NULL, NULL);
339 WideCharToMultiByte(CP_THREAD_ACP, 0, Info[i].EnumLogFontEx.elfScript, -1,
340 (LPSTR)EnumLogFontExA.elfScript, LF_FACESIZE, NULL, NULL);
341 NewTextMetricExW2A(&NewTextMetricExA,
342 &Info[i].NewTextMetricEx);
343 Ret = ((FONTENUMPROCA) EnumProc)(
344 (VOID*)&EnumLogFontExA,
345 (VOID*)&NewTextMetricExA,
346 Info[i].FontType, lParam);
347 }
348 }
349
350 RtlFreeHeap(GetProcessHeap(), 0, Info);
351
352 return Ret;
353 }
354
355 /*
356 * @implemented
357 */
358 int WINAPI
359 EnumFontFamiliesExW(HDC hdc, LPLOGFONTW lpLogfont, FONTENUMPROCW lpEnumFontFamExProc,
360 LPARAM lParam, DWORD dwFlags)
361 {
362 return IntEnumFontFamilies(hdc, lpLogfont, lpEnumFontFamExProc, lParam, TRUE);
363 }
364
365
366 /*
367 * @implemented
368 */
369 int WINAPI
370 EnumFontFamiliesW(HDC hdc, LPCWSTR lpszFamily, FONTENUMPROCW lpEnumFontFamProc,
371 LPARAM lParam)
372 {
373 LOGFONTW LogFont;
374
375 ZeroMemory(&LogFont, sizeof(LOGFONTW));
376 LogFont.lfCharSet = DEFAULT_CHARSET;
377 if (NULL != lpszFamily)
378 {
379 if (!*lpszFamily) return 1;
380 lstrcpynW(LogFont.lfFaceName, lpszFamily, LF_FACESIZE);
381 }
382
383 return IntEnumFontFamilies(hdc, &LogFont, lpEnumFontFamProc, lParam, TRUE);
384 }
385
386
387 /*
388 * @implemented
389 */
390 int WINAPI
391 EnumFontFamiliesExA (HDC hdc, LPLOGFONTA lpLogfont, FONTENUMPROCA lpEnumFontFamExProc,
392 LPARAM lParam, DWORD dwFlags)
393 {
394 LOGFONTW LogFontW, *pLogFontW;
395
396 if (lpLogfont)
397 {
398 LogFontA2W(&LogFontW,lpLogfont);
399 pLogFontW = &LogFontW;
400 }
401 else pLogFontW = NULL;
402
403 /* no need to convert LogFontW back to lpLogFont b/c it's an [in] parameter only */
404 return IntEnumFontFamilies(hdc, pLogFontW, lpEnumFontFamExProc, lParam, FALSE);
405 }
406
407
408 /*
409 * @implemented
410 */
411 int WINAPI
412 EnumFontFamiliesA(HDC hdc, LPCSTR lpszFamily, FONTENUMPROCA lpEnumFontFamProc,
413 LPARAM lParam)
414 {
415 LOGFONTW LogFont;
416
417 ZeroMemory(&LogFont, sizeof(LOGFONTW));
418 LogFont.lfCharSet = DEFAULT_CHARSET;
419 if (NULL != lpszFamily)
420 {
421 if (!*lpszFamily) return 1;
422 MultiByteToWideChar(CP_THREAD_ACP, 0, lpszFamily, -1, LogFont.lfFaceName, LF_FACESIZE);
423 }
424
425 return IntEnumFontFamilies(hdc, &LogFont, lpEnumFontFamProc, lParam, FALSE);
426 }
427
428 /*
429 * @implemented
430 */
431 DWORD
432 WINAPI
433 GetCharacterPlacementW(
434 HDC hdc,
435 LPCWSTR lpString,
436 INT uCount,
437 INT nMaxExtent,
438 GCP_RESULTSW *lpResults,
439 DWORD dwFlags
440 )
441 {
442 DWORD ret=0;
443 SIZE size;
444 UINT i, nSet;
445 DPRINT("GetCharacterPlacementW\n");
446
447 if(dwFlags&(~GCP_REORDER)) DPRINT("flags 0x%08lx ignored\n", dwFlags);
448 if(lpResults->lpClass) DPRINT("classes not implemented\n");
449 if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
450 DPRINT("Caret positions for complex scripts not implemented\n");
451
452 nSet = (UINT)uCount;
453 if(nSet > lpResults->nGlyphs)
454 nSet = lpResults->nGlyphs;
455
456 /* return number of initialized fields */
457 lpResults->nGlyphs = nSet;
458
459 /*if((dwFlags&GCP_REORDER)==0 || !BidiAvail)
460 {*/
461 /* Treat the case where no special handling was requested in a fastpath way */
462 /* copy will do if the GCP_REORDER flag is not set */
463 if(lpResults->lpOutString)
464 lstrcpynW( lpResults->lpOutString, lpString, nSet );
465
466 if(lpResults->lpGlyphs)
467 lstrcpynW( lpResults->lpGlyphs, lpString, nSet );
468
469 if(lpResults->lpOrder)
470 {
471 for(i = 0; i < nSet; i++)
472 lpResults->lpOrder[i] = i;
473 }
474 /*} else
475 {
476 BIDI_Reorder( lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
477 nSet, lpResults->lpOrder );
478 }*/
479
480 /* FIXME: Will use the placement chars */
481 if (lpResults->lpDx)
482 {
483 int c;
484 for (i = 0; i < nSet; i++)
485 {
486 if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
487 lpResults->lpDx[i]= c;
488 }
489 }
490
491 if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
492 {
493 int pos = 0;
494
495 lpResults->lpCaretPos[0] = 0;
496 for (i = 1; i < nSet; i++)
497 if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
498 lpResults->lpCaretPos[i] = (pos += size.cx);
499 }
500
501 /*if(lpResults->lpGlyphs)
502 NtGdiGetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);*/
503
504 if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
505 ret = MAKELONG(size.cx, size.cy);
506
507 return ret;
508 }
509
510 /*
511 * @implemented
512 *
513 */
514 BOOL
515 WINAPI
516 GetCharABCWidthsFloatW(HDC hdc,
517 UINT FirstChar,
518 UINT LastChar,
519 LPABCFLOAT abcF)
520 {
521 DPRINT("GetCharABCWidthsFloatW\n");
522 if ((!abcF) || (FirstChar > LastChar))
523 {
524 SetLastError(ERROR_INVALID_PARAMETER);
525 return FALSE;
526 }
527 return NtGdiGetCharABCWidthsW( hdc,
528 FirstChar,
529 (ULONG)(LastChar - FirstChar + 1),
530 (PWCHAR) NULL,
531 0,
532 (PVOID)abcF);
533 }
534
535 /*
536 * @implemented
537 *
538 */
539 BOOL
540 WINAPI
541 GetCharWidthFloatW(HDC hdc,
542 UINT iFirstChar,
543 UINT iLastChar,
544 PFLOAT pxBuffer)
545 {
546 DPRINT("GetCharWidthsFloatW\n");
547 if ((!pxBuffer) || (iFirstChar > iLastChar))
548 {
549 SetLastError(ERROR_INVALID_PARAMETER);
550 return FALSE;
551 }
552 return NtGdiGetCharWidthW( hdc,
553 iFirstChar,
554 (ULONG)(iLastChar - iFirstChar + 1),
555 (PWCHAR) NULL,
556 0,
557 (PVOID) pxBuffer);
558 }
559
560 /*
561 * @implemented
562 *
563 */
564 BOOL
565 WINAPI
566 GetCharWidthW(HDC hdc,
567 UINT iFirstChar,
568 UINT iLastChar,
569 LPINT lpBuffer)
570 {
571 DPRINT("GetCharWidthsW\n");
572 if ((!lpBuffer) || (iFirstChar > iLastChar))
573 {
574 SetLastError(ERROR_INVALID_PARAMETER);
575 return FALSE;
576 }
577 return NtGdiGetCharWidthW( hdc,
578 iFirstChar,
579 (ULONG)(iLastChar - iFirstChar + 1),
580 (PWCHAR) NULL,
581 GCW_NOFLOAT,
582 (PVOID) lpBuffer);
583 }
584
585 /*
586 * @implemented
587 *
588 */
589 BOOL
590 WINAPI
591 GetCharWidth32W(HDC hdc,
592 UINT iFirstChar,
593 UINT iLastChar,
594 LPINT lpBuffer)
595 {
596 DPRINT("GetCharWidths32W\n");
597 if ((!lpBuffer) || (iFirstChar > iLastChar))
598 {
599 SetLastError(ERROR_INVALID_PARAMETER);
600 return FALSE;
601 }
602 return NtGdiGetCharWidthW( hdc,
603 iFirstChar,
604 (ULONG)(iLastChar - iFirstChar + 1),
605 (PWCHAR) NULL,
606 GCW_NOFLOAT|GCW_WIN32,
607 (PVOID) lpBuffer);
608 }
609
610
611 /*
612 * @implemented
613 *
614 */
615 BOOL
616 WINAPI
617 GetCharABCWidthsW(HDC hdc,
618 UINT FirstChar,
619 UINT LastChar,
620 LPABC lpabc)
621 {
622 DPRINT("GetCharABCWidthsW\n");
623 if ((!lpabc) || (FirstChar > LastChar))
624 {
625 SetLastError(ERROR_INVALID_PARAMETER);
626 return FALSE;
627 }
628 return NtGdiGetCharABCWidthsW( hdc,
629 FirstChar,
630 (ULONG)(LastChar - FirstChar + 1),
631 (PWCHAR) NULL,
632 GCABCW_NOFLOAT,
633 (PVOID)lpabc);
634 }
635
636 /*
637 * @implemented
638 */
639 BOOL
640 WINAPI
641 GetCharWidthA(
642 HDC hdc,
643 UINT iFirstChar,
644 UINT iLastChar,
645 LPINT lpBuffer
646 )
647 {
648 INT i, wlen, count = (INT)(iLastChar - iFirstChar + 1);
649 LPSTR str;
650 LPWSTR wstr;
651 BOOL ret = TRUE;
652
653 DPRINT("GetCharWidthsA\n");
654 if(count <= 0) return FALSE;
655
656 str = HeapAlloc(GetProcessHeap(), 0, count+1);
657 if (!str)
658 return FALSE;
659
660 for(i = 0; i < count; i++)
661 str[i] = (BYTE)(iFirstChar + i);
662 str[i] = '\0';
663
664 wstr = FONT_mbtowc(hdc, str, count+1, &wlen, NULL);
665 if (!wstr)
666 {
667 HeapFree(GetProcessHeap(), 0, str);
668 return FALSE;
669 }
670
671 ret = NtGdiGetCharWidthW( hdc,
672 wstr[0],
673 (ULONG) count,
674 (PWCHAR) wstr,
675 GCW_NOFLOAT,
676 (PVOID) lpBuffer);
677
678 HeapFree(GetProcessHeap(), 0, str);
679 HeapFree(GetProcessHeap(), 0, wstr);
680
681 return ret;
682 }
683
684 /*
685 * @implemented
686 */
687 BOOL
688 WINAPI
689 GetCharWidth32A(
690 HDC hdc,
691 UINT iFirstChar,
692 UINT iLastChar,
693 LPINT lpBuffer
694 )
695 {
696 INT i, wlen, count = (INT)(iLastChar - iFirstChar + 1);
697 LPSTR str;
698 LPWSTR wstr;
699 BOOL ret = TRUE;
700
701 DPRINT("GetCharWidths32A\n");
702 if(count <= 0) return FALSE;
703
704 str = HeapAlloc(GetProcessHeap(), 0, count+1);
705 if (!str)
706 return FALSE;
707 for(i = 0; i < count; i++)
708 str[i] = (BYTE)(iFirstChar + i);
709 str[i] = '\0';
710
711 wstr = FONT_mbtowc(hdc, str, count+1, &wlen, NULL);
712 if (!wstr)
713 {
714 HeapFree(GetProcessHeap(), 0, str);
715 return FALSE;
716 }
717
718 ret = NtGdiGetCharWidthW( hdc,
719 wstr[0],
720 (ULONG) count,
721 (PWCHAR) wstr,
722 GCW_NOFLOAT|GCW_WIN32,
723 (PVOID) lpBuffer);
724
725 HeapFree(GetProcessHeap(), 0, str);
726 HeapFree(GetProcessHeap(), 0, wstr);
727
728 return ret;
729 }
730
731 /*
732 * @implemented
733 */
734 BOOL
735 APIENTRY
736 GetCharWidthFloatA(
737 HDC hdc,
738 UINT iFirstChar,
739 UINT iLastChar,
740 PFLOAT pxBuffer
741 )
742 {
743 INT i, wlen, count = (INT)(iLastChar - iFirstChar + 1);
744 LPSTR str;
745 LPWSTR wstr;
746 BOOL ret = TRUE;
747
748 DPRINT("GetCharWidthsFloatA\n");
749 if(count <= 0) return FALSE;
750
751 str = HeapAlloc(GetProcessHeap(), 0, count+1);
752 if (!str)
753 return FALSE;
754 for(i = 0; i < count; i++)
755 str[i] = (BYTE)(iFirstChar + i);
756 str[i] = '\0';
757
758 wstr = FONT_mbtowc(hdc, str, count+1, &wlen, NULL);
759 if (!wstr)
760 {
761 HeapFree(GetProcessHeap(), 0, str);
762 return FALSE;
763 }
764 ret = NtGdiGetCharWidthW( hdc, wstr[0], (ULONG) count, (PWCHAR) wstr, 0, (PVOID) pxBuffer);
765
766 HeapFree(GetProcessHeap(), 0, str);
767 HeapFree(GetProcessHeap(), 0, wstr);
768
769 return ret;
770 }
771
772 /*
773 * @implemented
774 */
775 BOOL
776 APIENTRY
777 GetCharABCWidthsA(
778 HDC hdc,
779 UINT uFirstChar,
780 UINT uLastChar,
781 LPABC lpabc
782 )
783 {
784 INT i, wlen, count = (INT)(uLastChar - uFirstChar + 1);
785 LPSTR str;
786 LPWSTR wstr;
787 BOOL ret = TRUE;
788
789 DPRINT("GetCharABCWidthsA\n");
790 if(count <= 0) return FALSE;
791
792 str = HeapAlloc(GetProcessHeap(), 0, count+1);
793 if (!str)
794 return FALSE;
795 for(i = 0; i < count; i++)
796 str[i] = (BYTE)(uFirstChar + i);
797 str[i] = '\0';
798
799 wstr = FONT_mbtowc(hdc, str, count+1, &wlen, NULL);
800 if (!wstr)
801 {
802 HeapFree(GetProcessHeap(), 0, str);
803 return FALSE;
804 }
805
806 ret = NtGdiGetCharABCWidthsW( hdc,
807 wstr[0],
808 (ULONG)count,
809 (PWCHAR)wstr,
810 GCABCW_NOFLOAT,
811 (PVOID)lpabc);
812
813 HeapFree(GetProcessHeap(), 0, str);
814 HeapFree(GetProcessHeap(), 0, wstr);
815
816 return ret;
817 }
818
819 /*
820 * @implemented
821 */
822 BOOL
823 APIENTRY
824 GetCharABCWidthsFloatA(
825 HDC hdc,
826 UINT iFirstChar,
827 UINT iLastChar,
828 LPABCFLOAT lpABCF
829 )
830 {
831 INT i, wlen, count = (INT)(iLastChar - iFirstChar + 1);
832 LPSTR str;
833 LPWSTR wstr;
834 BOOL ret = TRUE;
835
836 DPRINT("GetCharABCWidthsFloatA\n");
837 if (count <= 0) return FALSE;
838
839 str = HeapAlloc(GetProcessHeap(), 0, count+1);
840 if (!str)
841 return FALSE;
842
843 for(i = 0; i < count; i++)
844 str[i] = (BYTE)(iFirstChar + i);
845 str[i] = '\0';
846
847 wstr = FONT_mbtowc( hdc, str, count+1, &wlen, NULL );
848 if (!wstr)
849 {
850 HeapFree( GetProcessHeap(), 0, str );
851 return FALSE;
852 }
853 ret = NtGdiGetCharABCWidthsW( hdc,wstr[0],(ULONG)count, (PWCHAR)wstr, 0, (PVOID)lpABCF);
854
855 HeapFree( GetProcessHeap(), 0, str );
856 HeapFree( GetProcessHeap(), 0, wstr );
857
858 return ret;
859 }
860
861 /*
862 * @implemented
863 */
864 BOOL
865 WINAPI
866 GetCharABCWidthsI(HDC hdc,
867 UINT giFirst,
868 UINT cgi,
869 LPWORD pgi,
870 LPABC lpabc)
871 {
872 DPRINT("GetCharABCWidthsI\n");
873 return NtGdiGetCharABCWidthsW( hdc,
874 giFirst,
875 (ULONG) cgi,
876 (PWCHAR) pgi,
877 GCABCW_NOFLOAT|GCABCW_INDICES,
878 (PVOID)lpabc);
879 }
880
881 /*
882 * @implemented
883 */
884 BOOL
885 WINAPI
886 GetCharWidthI(HDC hdc,
887 UINT giFirst,
888 UINT cgi,
889 LPWORD pgi,
890 LPINT lpBuffer
891 )
892 {
893 DPRINT("GetCharWidthsI\n");
894 if (!lpBuffer || (!pgi && (giFirst == MAXUSHORT))) // Cannot be at max.
895 {
896 SetLastError(ERROR_INVALID_PARAMETER);
897 return FALSE;
898 }
899 if (!cgi) return TRUE;
900 return NtGdiGetCharWidthW( hdc,
901 giFirst,
902 cgi,
903 (PWCHAR) pgi,
904 GCW_INDICES|GCW_NOFLOAT|GCW_WIN32,
905 (PVOID) lpBuffer );
906 }
907
908 /*
909 * @implemented
910 */
911 DWORD
912 WINAPI
913 GetFontLanguageInfo(
914 HDC hDc
915 )
916 {
917 return GetDCDWord(hDc, GdiGetFontLanguageInfo, GCP_ERROR);
918 }
919
920 /*
921 * @implemented
922 */
923 DWORD
924 WINAPI
925 GetGlyphIndicesA(
926 HDC hdc,
927 LPCSTR lpstr,
928 INT count,
929 LPWORD pgi,
930 DWORD flags
931 )
932 {
933 DWORD Ret;
934 WCHAR *lpstrW;
935 INT countW;
936
937 lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
938 Ret = NtGdiGetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
939 HeapFree(GetProcessHeap(), 0, lpstrW);
940 return Ret;
941 }
942
943 /*
944 * @implemented
945 */
946 DWORD
947 WINAPI
948 GetGlyphOutlineA(
949 HDC hdc,
950 UINT uChar,
951 UINT uFormat,
952 LPGLYPHMETRICS lpgm,
953 DWORD cbBuffer,
954 LPVOID lpvBuffer,
955 CONST MAT2 *lpmat2
956 )
957 {
958
959 LPWSTR p = NULL;
960 DWORD ret;
961 UINT c;
962 DPRINT1("GetGlyphOutlineA uChar %x\n", uChar);
963 if(!(uFormat & GGO_GLYPH_INDEX)) {
964 int len;
965 char mbchs[2];
966 if(uChar > 0xff) { /* but, 2 bytes character only */
967 len = 2;
968 mbchs[0] = (uChar & 0xff00) >> 8;
969 mbchs[1] = (uChar & 0xff);
970 } else {
971 len = 1;
972 mbchs[0] = (uChar & 0xff);
973 }
974 p = FONT_mbtowc(hdc, mbchs, len, NULL, NULL);
975 c = p[0];
976 } else
977 c = uChar;
978 ret = NtGdiGetGlyphOutline(hdc, c, uFormat, lpgm, cbBuffer, lpvBuffer, (CONST LPMAT2)lpmat2, TRUE);
979 HeapFree(GetProcessHeap(), 0, p);
980 return ret;
981 }
982
983
984 /*
985 * @implemented
986 */
987 DWORD
988 WINAPI
989 GetGlyphOutlineW(
990 HDC hdc,
991 UINT uChar,
992 UINT uFormat,
993 LPGLYPHMETRICS lpgm,
994 DWORD cbBuffer,
995 LPVOID lpvBuffer,
996 CONST MAT2 *lpmat2
997 )
998 {
999 DPRINT("GetGlyphOutlineW uChar %x\n", uChar);
1000 if (!lpgm & !lpmat2) return GDI_ERROR;
1001 if (!lpvBuffer) cbBuffer = 0;
1002 return NtGdiGetGlyphOutline ( hdc, uChar, uFormat, lpgm, cbBuffer, lpvBuffer, (CONST LPMAT2)lpmat2, TRUE);
1003 }
1004
1005
1006 /*
1007 * @implemented
1008 */
1009 UINT
1010 APIENTRY
1011 GetOutlineTextMetricsA(
1012 HDC hdc,
1013 UINT cbData,
1014 LPOUTLINETEXTMETRICA lpOTM
1015 )
1016 {
1017 char buf[512], *ptr;
1018 UINT ret, needed;
1019 OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1020 OUTLINETEXTMETRICA *output = lpOTM;
1021 INT left, len;
1022
1023 if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1024 return 0;
1025 if(ret > sizeof(buf))
1026 lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1027 GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1028
1029 needed = sizeof(OUTLINETEXTMETRICA);
1030 if(lpOTMW->otmpFamilyName)
1031 needed += WideCharToMultiByte(CP_ACP, 0,
1032 (WCHAR*)((char*)lpOTMW + (int)lpOTMW->otmpFamilyName), -1,
1033 NULL, 0, NULL, NULL);
1034 if(lpOTMW->otmpFaceName)
1035 needed += WideCharToMultiByte(CP_ACP, 0,
1036 (WCHAR*)((char*)lpOTMW + (int)lpOTMW->otmpFaceName), -1,
1037 NULL, 0, NULL, NULL);
1038 if(lpOTMW->otmpStyleName)
1039 needed += WideCharToMultiByte(CP_ACP, 0,
1040 (WCHAR*)((char*)lpOTMW + (int)lpOTMW->otmpStyleName), -1,
1041 NULL, 0, NULL, NULL);
1042 if(lpOTMW->otmpFullName)
1043 needed += WideCharToMultiByte(CP_ACP, 0,
1044 (WCHAR*)((char*)lpOTMW + (int)lpOTMW->otmpFullName), -1,
1045 NULL, 0, NULL, NULL);
1046
1047 if(!lpOTM) {
1048 ret = needed;
1049 goto end;
1050 }
1051
1052 DPRINT("needed = %d\n", needed);
1053 if(needed > cbData)
1054 /* Since the supplied buffer isn't big enough, we'll alloc one
1055 that is and memcpy the first cbData bytes into the lpOTM at
1056 the end. */
1057 output = HeapAlloc(GetProcessHeap(), 0, needed);
1058
1059 ret = output->otmSize = min(needed, cbData);
1060 FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1061 output->otmFiller = 0;
1062 output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1063 output->otmfsSelection = lpOTMW->otmfsSelection;
1064 output->otmfsType = lpOTMW->otmfsType;
1065 output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1066 output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1067 output->otmItalicAngle = lpOTMW->otmItalicAngle;
1068 output->otmEMSquare = lpOTMW->otmEMSquare;
1069 output->otmAscent = lpOTMW->otmAscent;
1070 output->otmDescent = lpOTMW->otmDescent;
1071 output->otmLineGap = lpOTMW->otmLineGap;
1072 output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1073 output->otmsXHeight = lpOTMW->otmsXHeight;
1074 output->otmrcFontBox = lpOTMW->otmrcFontBox;
1075 output->otmMacAscent = lpOTMW->otmMacAscent;
1076 output->otmMacDescent = lpOTMW->otmMacDescent;
1077 output->otmMacLineGap = lpOTMW->otmMacLineGap;
1078 output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1079 output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1080 output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1081 output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1082 output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1083 output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1084 output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1085 output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1086 output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1087
1088
1089 ptr = (char*)(output + 1);
1090 left = needed - sizeof(*output);
1091
1092 if(lpOTMW->otmpFamilyName) {
1093 output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1094 len = WideCharToMultiByte(CP_ACP, 0,
1095 (WCHAR*)((char*)lpOTMW + (int)lpOTMW->otmpFamilyName), -1,
1096 ptr, left, NULL, NULL);
1097 left -= len;
1098 ptr += len;
1099 } else
1100 output->otmpFamilyName = 0;
1101
1102 if(lpOTMW->otmpFaceName) {
1103 output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1104 len = WideCharToMultiByte(CP_ACP, 0,
1105 (WCHAR*)((char*)lpOTMW + (int)lpOTMW->otmpFaceName), -1,
1106 ptr, left, NULL, NULL);
1107 left -= len;
1108 ptr += len;
1109 } else
1110 output->otmpFaceName = 0;
1111
1112 if(lpOTMW->otmpStyleName) {
1113 output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1114 len = WideCharToMultiByte(CP_ACP, 0,
1115 (WCHAR*)((char*)lpOTMW + (int)lpOTMW->otmpStyleName), -1,
1116 ptr, left, NULL, NULL);
1117 left -= len;
1118 ptr += len;
1119 } else
1120 output->otmpStyleName = 0;
1121
1122 if(lpOTMW->otmpFullName) {
1123 output->otmpFullName = (LPSTR)(ptr - (char*)output);
1124 len = WideCharToMultiByte(CP_ACP, 0,
1125 (WCHAR*)((char*)lpOTMW + (int)lpOTMW->otmpFullName), -1,
1126 ptr, left, NULL, NULL);
1127 left -= len;
1128 } else
1129 output->otmpFullName = 0;
1130
1131 assert(left == 0);
1132
1133 if(output != lpOTM) {
1134 memcpy(lpOTM, output, cbData);
1135 HeapFree(GetProcessHeap(), 0, output);
1136
1137 /* check if the string offsets really fit into the provided size */
1138 /* FIXME: should we check string length as well? */
1139 if ((UINT_PTR)lpOTM->otmpFamilyName >= lpOTM->otmSize)
1140 lpOTM->otmpFamilyName = 0; /* doesn't fit */
1141
1142 if ((UINT_PTR)lpOTM->otmpFaceName >= lpOTM->otmSize)
1143 lpOTM->otmpFaceName = 0; /* doesn't fit */
1144
1145 if ((UINT_PTR)lpOTM->otmpStyleName >= lpOTM->otmSize)
1146 lpOTM->otmpStyleName = 0; /* doesn't fit */
1147
1148 if ((UINT_PTR)lpOTM->otmpFullName >= lpOTM->otmSize)
1149 lpOTM->otmpFullName = 0; /* doesn't fit */
1150 }
1151
1152 end:
1153 if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1154 HeapFree(GetProcessHeap(), 0, lpOTMW);
1155
1156 return ret;
1157 }
1158
1159
1160 /*
1161 * @implemented
1162 */
1163 UINT
1164 APIENTRY
1165 GetOutlineTextMetricsW(
1166 HDC hdc,
1167 UINT cbData,
1168 LPOUTLINETEXTMETRICW lpOTM
1169 )
1170 {
1171 TMDIFF Tmd; // Should not be zero.
1172
1173 return NtGdiGetOutlineTextMetricsInternalW(hdc, cbData, lpOTM, &Tmd);
1174 }
1175
1176 /*
1177 * @implemented
1178 */
1179 DWORD
1180 WINAPI
1181 GetKerningPairsW(HDC hdc,
1182 ULONG cPairs,
1183 LPKERNINGPAIR pkpDst)
1184 {
1185 if ((cPairs != 0) || (pkpDst == 0))
1186 {
1187 return NtGdiGetKerningPairs(hdc,cPairs,pkpDst);
1188 }
1189 else
1190 {
1191 SetLastError(ERROR_INVALID_PARAMETER);
1192 return 0;
1193 }
1194 }
1195
1196 /*
1197 * @implemented
1198 */
1199 DWORD
1200 WINAPI
1201 GetKerningPairsA( HDC hDC,
1202 DWORD cPairs,
1203 LPKERNINGPAIR kern_pairA )
1204 {
1205 INT charset;
1206 CHARSETINFO csi;
1207 CPINFO cpi;
1208 DWORD i, total_kern_pairs, kern_pairs_copied = 0;
1209 KERNINGPAIR *kern_pairW;
1210
1211 if (!cPairs && kern_pairA)
1212 {
1213 SetLastError(ERROR_INVALID_PARAMETER);
1214 return 0;
1215 }
1216
1217 charset = GetTextCharset(hDC);
1218 if (!TranslateCharsetInfo(ULongToPtr(charset), &csi, TCI_SRCCHARSET))
1219 {
1220 DPRINT1("Can't find codepage for charset %d\n", charset);
1221 return 0;
1222 }
1223 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
1224 * to fail on an invalid character for CP_SYMBOL.
1225 */
1226 cpi.DefaultChar[0] = 0;
1227 if (csi.ciACP != CP_SYMBOL && !GetCPInfo(csi.ciACP, &cpi))
1228 {
1229 DPRINT1("Can't find codepage %u info\n", csi.ciACP);
1230 return 0;
1231 }
1232 DPRINT("charset %d => codepage %u\n", charset, csi.ciACP);
1233
1234 total_kern_pairs = NtGdiGetKerningPairs(hDC, 0, NULL);
1235 if (!total_kern_pairs) return 0;
1236
1237 if (!cPairs && !kern_pairA) return total_kern_pairs;
1238
1239 kern_pairW = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW));
1240 GetKerningPairsW(hDC, total_kern_pairs, kern_pairW);
1241
1242 for (i = 0; i < total_kern_pairs; i++)
1243 {
1244 char first, second;
1245
1246 if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL))
1247 continue;
1248
1249 if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL))
1250 continue;
1251
1252 if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0])
1253 continue;
1254
1255 if (kern_pairA)
1256 {
1257 if (kern_pairs_copied >= cPairs) break;
1258
1259 kern_pairA->wFirst = (BYTE)first;
1260 kern_pairA->wSecond = (BYTE)second;
1261 kern_pairA->iKernAmount = kern_pairW[i].iKernAmount;
1262 kern_pairA++;
1263 }
1264 kern_pairs_copied++;
1265 }
1266
1267 HeapFree(GetProcessHeap(), 0, kern_pairW);
1268
1269 return kern_pairs_copied;
1270 }
1271
1272
1273
1274 /*
1275 * @implemented
1276 */
1277 HFONT
1278 WINAPI
1279 CreateFontIndirectExA(const ENUMLOGFONTEXDVA *elfexd)
1280 {
1281 if (elfexd)
1282 {
1283 ENUMLOGFONTEXDVW Logfont;
1284
1285 EnumLogFontExW2A( (LPENUMLOGFONTEXA) elfexd,
1286 &Logfont.elfEnumLogfontEx );
1287
1288 RtlCopyMemory( &Logfont.elfDesignVector,
1289 (PVOID) &elfexd->elfDesignVector,
1290 sizeof(DESIGNVECTOR));
1291
1292 return NtGdiHfontCreate( &Logfont, 0, 0, 0, NULL);
1293 }
1294 else return NULL;
1295 }
1296
1297
1298 /*
1299 * @implemented
1300 */
1301 HFONT
1302 WINAPI
1303 CreateFontIndirectExW(const ENUMLOGFONTEXDVW *elfexd)
1304 {
1305 /* Msdn: Note, this function ignores the elfDesignVector member in
1306 ENUMLOGFONTEXDV.
1307 */
1308 if ( elfexd )
1309 {
1310 return NtGdiHfontCreate((PENUMLOGFONTEXDVW) elfexd, 0, 0, 0, NULL );
1311 }
1312 else return NULL;
1313 }
1314
1315
1316 /*
1317 * @implemented
1318 */
1319 HFONT
1320 WINAPI
1321 CreateFontIndirectA(
1322 CONST LOGFONTA *lplf
1323 )
1324 {
1325 if (lplf)
1326 {
1327 LOGFONTW tlf;
1328
1329 LogFontA2W(&tlf, lplf);
1330 return CreateFontIndirectW(&tlf);
1331 }
1332 else return NULL;
1333 }
1334
1335
1336 /*
1337 * @implemented
1338 */
1339 HFONT
1340 WINAPI
1341 CreateFontIndirectW(
1342 CONST LOGFONTW *lplf
1343 )
1344 {
1345 if (lplf)
1346 {
1347 ENUMLOGFONTEXDVW Logfont;
1348
1349 RtlCopyMemory( &Logfont.elfEnumLogfontEx.elfLogFont, lplf, sizeof(LOGFONTW));
1350 // Need something other than just cleaning memory here.
1351 // Guess? Use caller data to determine the rest.
1352 RtlZeroMemory( &Logfont.elfEnumLogfontEx.elfFullName,
1353 sizeof(Logfont.elfEnumLogfontEx.elfFullName));
1354 RtlZeroMemory( &Logfont.elfEnumLogfontEx.elfStyle,
1355 sizeof(Logfont.elfEnumLogfontEx.elfStyle));
1356 RtlZeroMemory( &Logfont.elfEnumLogfontEx.elfScript,
1357 sizeof(Logfont.elfEnumLogfontEx.elfScript));
1358
1359 Logfont.elfDesignVector.dvNumAxes = 0; // No more than MM_MAX_NUMAXES
1360
1361 RtlZeroMemory( &Logfont.elfDesignVector, sizeof(DESIGNVECTOR));
1362
1363 return CreateFontIndirectExW(&Logfont);
1364 }
1365 else return NULL;
1366 }
1367
1368
1369 /*
1370 * @implemented
1371 */
1372 HFONT
1373 WINAPI
1374 CreateFontA(
1375 int nHeight,
1376 int nWidth,
1377 int nEscapement,
1378 int nOrientation,
1379 int fnWeight,
1380 DWORD fdwItalic,
1381 DWORD fdwUnderline,
1382 DWORD fdwStrikeOut,
1383 DWORD fdwCharSet,
1384 DWORD fdwOutputPrecision,
1385 DWORD fdwClipPrecision,
1386 DWORD fdwQuality,
1387 DWORD fdwPitchAndFamily,
1388 LPCSTR lpszFace
1389 )
1390 {
1391 ANSI_STRING StringA;
1392 UNICODE_STRING StringU;
1393 HFONT ret;
1394
1395 RtlInitAnsiString(&StringA, (LPSTR)lpszFace);
1396 RtlAnsiStringToUnicodeString(&StringU, &StringA, TRUE);
1397
1398 ret = CreateFontW(nHeight,
1399 nWidth,
1400 nEscapement,
1401 nOrientation,
1402 fnWeight,
1403 fdwItalic,
1404 fdwUnderline,
1405 fdwStrikeOut,
1406 fdwCharSet,
1407 fdwOutputPrecision,
1408 fdwClipPrecision,
1409 fdwQuality,
1410 fdwPitchAndFamily,
1411 StringU.Buffer);
1412
1413 RtlFreeUnicodeString(&StringU);
1414
1415 return ret;
1416 }
1417
1418
1419 /*
1420 * @implemented
1421 */
1422 HFONT
1423 WINAPI
1424 CreateFontW(
1425 int nHeight,
1426 int nWidth,
1427 int nEscapement,
1428 int nOrientation,
1429 int nWeight,
1430 DWORD fnItalic,
1431 DWORD fdwUnderline,
1432 DWORD fdwStrikeOut,
1433 DWORD fdwCharSet,
1434 DWORD fdwOutputPrecision,
1435 DWORD fdwClipPrecision,
1436 DWORD fdwQuality,
1437 DWORD fdwPitchAndFamily,
1438 LPCWSTR lpszFace
1439 )
1440 {
1441 LOGFONTW logfont;
1442
1443 logfont.lfHeight = nHeight;
1444 logfont.lfWidth = nWidth;
1445 logfont.lfEscapement = nEscapement;
1446 logfont.lfOrientation = nOrientation;
1447 logfont.lfWeight = nWeight;
1448 logfont.lfItalic = fnItalic;
1449 logfont.lfUnderline = fdwUnderline;
1450 logfont.lfStrikeOut = fdwStrikeOut;
1451 logfont.lfCharSet = fdwCharSet;
1452 logfont.lfOutPrecision = fdwOutputPrecision;
1453 logfont.lfClipPrecision = fdwClipPrecision;
1454 logfont.lfQuality = fdwQuality;
1455 logfont.lfPitchAndFamily = fdwPitchAndFamily;
1456
1457 if (NULL != lpszFace)
1458 {
1459 int Size = sizeof(logfont.lfFaceName) / sizeof(WCHAR);
1460 wcsncpy((wchar_t *)logfont.lfFaceName, lpszFace, Size - 1);
1461 /* Be 101% sure to have '\0' at end of string */
1462 logfont.lfFaceName[Size - 1] = '\0';
1463 }
1464 else
1465 {
1466 logfont.lfFaceName[0] = L'\0';
1467 }
1468
1469 return CreateFontIndirectW(&logfont);
1470 }
1471
1472
1473 /*
1474 * @unimplemented
1475 */
1476 BOOL
1477 WINAPI
1478 CreateScalableFontResourceA(
1479 DWORD fdwHidden,
1480 LPCSTR lpszFontRes,
1481 LPCSTR lpszFontFile,
1482 LPCSTR lpszCurrentPath
1483 )
1484 {
1485 return FALSE;
1486 }
1487
1488
1489 /*
1490 * @implemented
1491 */
1492 int
1493 WINAPI
1494 AddFontResourceExW ( LPCWSTR lpszFilename, DWORD fl, PVOID pvReserved )
1495 {
1496 if (fl & ~(FR_PRIVATE | FR_NOT_ENUM))
1497 {
1498 SetLastError( ERROR_INVALID_PARAMETER );
1499 return 0;
1500 }
1501
1502 return GdiAddFontResourceW(lpszFilename, fl,0);
1503 }
1504
1505
1506 /*
1507 * @implemented
1508 */
1509 int
1510 WINAPI
1511 AddFontResourceExA ( LPCSTR lpszFilename, DWORD fl, PVOID pvReserved )
1512 {
1513 NTSTATUS Status;
1514 PWSTR FilenameW;
1515 int rc;
1516
1517 if (fl & ~(FR_PRIVATE | FR_NOT_ENUM))
1518 {
1519 SetLastError( ERROR_INVALID_PARAMETER );
1520 return 0;
1521 }
1522
1523 Status = HEAP_strdupA2W ( &FilenameW, lpszFilename );
1524 if ( !NT_SUCCESS (Status) )
1525 {
1526 SetLastError (RtlNtStatusToDosError(Status));
1527 return 0;
1528 }
1529
1530 rc = GdiAddFontResourceW ( FilenameW, fl, 0 );
1531 HEAP_free ( FilenameW );
1532 return rc;
1533 }
1534
1535
1536 /*
1537 * @implemented
1538 */
1539 int
1540 WINAPI
1541 AddFontResourceA ( LPCSTR lpszFilename )
1542 {
1543 NTSTATUS Status;
1544 PWSTR FilenameW;
1545 int rc = 0;
1546
1547 Status = HEAP_strdupA2W ( &FilenameW, lpszFilename );
1548 if ( !NT_SUCCESS (Status) )
1549 {
1550 SetLastError (RtlNtStatusToDosError(Status));
1551 }
1552 else
1553 {
1554 rc = GdiAddFontResourceW ( FilenameW, 0, 0);
1555
1556 HEAP_free ( FilenameW );
1557 }
1558 return rc;
1559 }
1560
1561
1562 /*
1563 * @implemented
1564 */
1565 int
1566 WINAPI
1567 AddFontResourceW ( LPCWSTR lpszFilename )
1568 {
1569 return GdiAddFontResourceW ( lpszFilename, 0, 0 );
1570 }
1571
1572
1573 /*
1574 * @implemented
1575 */
1576 BOOL
1577 WINAPI
1578 RemoveFontResourceW(LPCWSTR lpFileName)
1579 {
1580 return RemoveFontResourceExW(lpFileName,0,0);
1581 }
1582
1583
1584 /*
1585 * @implemented
1586 */
1587 BOOL
1588 WINAPI
1589 RemoveFontResourceA(LPCSTR lpFileName)
1590 {
1591 return RemoveFontResourceExA(lpFileName,0,0);
1592 }
1593
1594 /*
1595 * @unimplemented
1596 */
1597 BOOL
1598 WINAPI
1599 RemoveFontResourceExA(LPCSTR lpFileName,
1600 DWORD fl,
1601 PVOID pdv
1602 )
1603 {
1604 NTSTATUS Status;
1605 LPWSTR lpFileNameW;
1606
1607 /* FIXME the flags */
1608 /* FIXME the pdv */
1609 /* FIXME NtGdiRemoveFontResource handle flags and pdv */
1610
1611 Status = HEAP_strdupA2W ( &lpFileNameW, lpFileName );
1612 if (!NT_SUCCESS (Status))
1613 SetLastError (RtlNtStatusToDosError(Status));
1614 else
1615 {
1616
1617 HEAP_free ( lpFileNameW );
1618 }
1619
1620 return 0;
1621 }
1622
1623 /*
1624 * @unimplemented
1625 */
1626 BOOL
1627 WINAPI
1628 RemoveFontResourceExW(LPCWSTR lpFileName,
1629 DWORD fl,
1630 PVOID pdv)
1631 {
1632 /* FIXME the flags */
1633 /* FIXME the pdv */
1634 /* FIXME NtGdiRemoveFontResource handle flags and pdv */
1635 return 0;
1636 }
1637
1638
1639 /***********************************************************************
1640 * GdiGetCharDimensions
1641 *
1642 * Gets the average width of the characters in the English alphabet.
1643 *
1644 * PARAMS
1645 * hdc [I] Handle to the device context to measure on.
1646 * lptm [O] Pointer to memory to store the text metrics into.
1647 * height [O] On exit, the maximum height of characters in the English alphabet.
1648 *
1649 * RETURNS
1650 * The average width of characters in the English alphabet.
1651 *
1652 * NOTES
1653 * This function is used by the dialog manager to get the size of a dialog
1654 * unit. It should also be used by other pieces of code that need to know
1655 * the size of a dialog unit in logical units without having access to the
1656 * window handle of the dialog.
1657 * Windows caches the font metrics from this function, but we don't and
1658 * there doesn't appear to be an immediate advantage to do so.
1659 *
1660 * SEE ALSO
1661 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
1662 *
1663 * Despite most of MSDN insisting that the horizontal base unit is
1664 * tmAveCharWidth it isn't. Knowledge base article Q145994
1665 * "HOWTO: Calculate Dialog Units When Not Using the System Font",
1666 * says that we should take the average of the 52 English upper and lower
1667 * case characters.
1668 */
1669 /*
1670 * @implemented
1671 */
1672 DWORD
1673 WINAPI
1674 GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
1675 {
1676 SIZE sz;
1677 TEXTMETRICW tm;
1678 static const WCHAR alphabet[] = {
1679 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
1680 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
1681 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
1682
1683 if(!GetTextMetricsW(hdc, &tm)) return 0;
1684
1685 if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
1686
1687 if (lptm) *lptm = tm;
1688 if (height) *height = tm.tmHeight;
1689
1690 return (sz.cx / 26 + 1) / 2;
1691 }
1692
1693 /*************************************************************************
1694 * TranslateCharsetInfo [GDI32.@]
1695 *
1696 * Fills a CHARSETINFO structure for a character set, code page, or
1697 * font. This allows making the correspondance between different labelings
1698 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
1699 * of the same encoding.
1700 *
1701 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
1702 * only one codepage should be set in *lpSrc.
1703 *
1704 * RETURNS
1705 * TRUE on success, FALSE on failure.
1706 *
1707 */
1708 /*
1709 * @unimplemented
1710 */
1711 BOOL
1712 WINAPI
1713 TranslateCharsetInfo(
1714 LPDWORD lpSrc, /* [in]
1715 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
1716 if flags == TCI_SRCCHARSET: a character set value
1717 if flags == TCI_SRCCODEPAGE: a code page value
1718 */
1719 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
1720 DWORD flags /* [in] determines interpretation of lpSrc */)
1721 {
1722 int index = 0;
1723 switch (flags) {
1724 case TCI_SRCFONTSIG:
1725 while (!(*lpSrc>>index & 0x0001) && index<MAXTCIINDEX) index++;
1726 break;
1727 case TCI_SRCCODEPAGE:
1728 while (PtrToUlong(lpSrc) != FONT_tci[index].ciACP && index < MAXTCIINDEX) index++;
1729 break;
1730 case TCI_SRCCHARSET:
1731 while (PtrToUlong(lpSrc) != FONT_tci[index].ciCharset && index < MAXTCIINDEX) index++;
1732 break;
1733 default:
1734 return FALSE;
1735 }
1736 if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
1737 memcpy(lpCs, &FONT_tci[index], sizeof(CHARSETINFO));
1738 return TRUE;
1739 }
1740
1741
1742 /*
1743 * @implemented
1744 */
1745 DWORD
1746 WINAPI
1747 SetMapperFlags(
1748 HDC hDC,
1749 DWORD flags
1750 )
1751 {
1752 DWORD Ret = GDI_ERROR;
1753 PDC_ATTR Dc_Attr;
1754 #if 0
1755 if (GDI_HANDLE_GET_TYPE(hDC) != GDI_OBJECT_TYPE_DC)
1756 {
1757 if (GDI_HANDLE_GET_TYPE(hDC) == GDI_OBJECT_TYPE_METADC)
1758 return MFDRV_SetMapperFlags( hDC, flags);
1759 else
1760 {
1761 PLDC pLDC = Dc_Attr->pvLDC;
1762 if ( !pLDC )
1763 {
1764 SetLastError(ERROR_INVALID_HANDLE);
1765 return GDI_ERROR;
1766 }
1767 if (pLDC->iType == LDC_EMFLDC)
1768 {
1769 return EMFDRV_SetMapperFlags( hDC, flags);
1770 }
1771 }
1772 }
1773 #endif
1774 if (!GdiGetHandleUserData((HGDIOBJ) hDC, GDI_OBJECT_TYPE_DC, (PVOID) &Dc_Attr)) return GDI_ERROR;
1775
1776 if (NtCurrentTeb()->GdiTebBatch.HDC == hDC)
1777 {
1778 if (Dc_Attr->ulDirty_ & DC_FONTTEXT_DIRTY)
1779 {
1780 NtGdiFlush();
1781 Dc_Attr->ulDirty_ &= ~(DC_MODE_DIRTY|DC_FONTTEXT_DIRTY);
1782 }
1783 }
1784
1785 if ( flags & ~1 )
1786 SetLastError(ERROR_INVALID_PARAMETER);
1787 else
1788 {
1789 Ret = Dc_Attr->flFontMapper;
1790 Dc_Attr->flFontMapper = flags;
1791 }
1792 return Ret;
1793 }
1794
1795
1796 /*
1797 * @unimplemented
1798 */
1799 int
1800 WINAPI
1801 EnumFontsW(
1802 HDC hDC,
1803 LPCWSTR lpFaceName,
1804 FONTENUMPROCW FontFunc,
1805 LPARAM lParam
1806 )
1807 {
1808 #if 0
1809 return NtGdiEnumFonts ( hDC, lpFaceName, FontFunc, lParam );
1810 #else
1811 return EnumFontFamiliesW( hDC, lpFaceName, FontFunc, lParam );
1812 #endif
1813 }
1814
1815 /*
1816 * @unimplemented
1817 */
1818 int
1819 WINAPI
1820 EnumFontsA (
1821 HDC hDC,
1822 LPCSTR lpFaceName,
1823 FONTENUMPROCA FontFunc,
1824 LPARAM lParam
1825 )
1826 {
1827 #if 0
1828 NTSTATUS Status;
1829 LPWSTR lpFaceNameW;
1830 int rc = 0;
1831
1832 Status = HEAP_strdupA2W ( &lpFaceNameW, lpFaceName );
1833 if (!NT_SUCCESS (Status))
1834 SetLastError (RtlNtStatusToDosError(Status));
1835 else
1836 {
1837 rc = NtGdiEnumFonts ( hDC, lpFaceNameW, FontFunc, lParam );
1838
1839 HEAP_free ( lpFaceNameW );
1840 }
1841 return rc;
1842 #else
1843 return EnumFontFamiliesA( hDC, lpFaceName, FontFunc, lParam );
1844 #endif
1845 }
1846
1847 #define EfdFontFamilies 3
1848
1849 INT
1850 WINAPI
1851 NewEnumFontFamiliesExW(
1852 HDC hDC,
1853 LPLOGFONTW lpLogfont,
1854 FONTENUMPROCW lpEnumFontFamExProcW,
1855 LPARAM lParam,
1856 DWORD dwFlags)
1857 {
1858 ULONG_PTR idEnum, cbDataSize, cbRetSize;
1859 PENUMFONTDATAW pEfdw;
1860 PBYTE pBuffer;
1861 PBYTE pMax;
1862 INT ret = 1;
1863
1864 /* Open enumeration handle and find out how much memory we need */
1865 idEnum = NtGdiEnumFontOpen(hDC,
1866 EfdFontFamilies,
1867 0,
1868 LF_FACESIZE,
1869 (lpLogfont && lpLogfont->lfFaceName[0])? lpLogfont->lfFaceName : NULL,
1870 lpLogfont? lpLogfont->lfCharSet : DEFAULT_CHARSET,
1871 &cbDataSize);
1872 if (idEnum == 0)
1873 {
1874 return 0;
1875 }
1876 if (cbDataSize == 0)
1877 {
1878 NtGdiEnumFontClose(idEnum);
1879 return 0;
1880 }
1881
1882 /* Allocate memory */
1883 pBuffer = HeapAlloc(GetProcessHeap(), 0, cbDataSize);
1884 if (pBuffer == NULL)
1885 {
1886 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1887 NtGdiEnumFontClose(idEnum);
1888 return 0;
1889 }
1890
1891 /* Do the enumeration */
1892 if (!NtGdiEnumFontChunk(hDC, idEnum, cbDataSize, &cbRetSize, (PVOID)pBuffer))
1893 {
1894 HeapFree(GetProcessHeap(), 0, pBuffer);
1895 NtGdiEnumFontClose(idEnum);
1896 return 0;
1897 }
1898
1899 /* Get start and end address */
1900 pEfdw = (PENUMFONTDATAW)pBuffer;
1901 pMax = pBuffer + cbDataSize;
1902
1903 /* Iterate through the structures */
1904 while ((PBYTE)pEfdw < pMax && ret)
1905 {
1906 PNTMW_INTERNAL pNtmwi = (PNTMW_INTERNAL)((ULONG_PTR)pEfdw + pEfdw->ulNtmwiOffset);
1907
1908 ret = lpEnumFontFamExProcW((VOID*)&pEfdw->elfexdv.elfEnumLogfontEx,
1909 (VOID*)&pNtmwi->ntmw,
1910 pEfdw->dwFontType,
1911 lParam);
1912
1913 pEfdw = (PENUMFONTDATAW)((ULONG_PTR)pEfdw + pEfdw->cbSize);
1914 }
1915
1916 /* Release the memory and close handle */
1917 HeapFree(GetProcessHeap(), 0, pBuffer);
1918 NtGdiEnumFontClose(idEnum);
1919
1920 return ret;
1921 }