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