- Removed NtGdiGetCharWidthFloat, NtGdiGetCharABCWidthsFloat and NtGdiGetCharacterPla...
[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 /*
424 * @implemented
425 */
426 BOOL
427 STDCALL
428 GetCharWidthA (
429 HDC hdc,
430 UINT iFirstChar,
431 UINT iLastChar,
432 LPINT lpBuffer
433 )
434 {
435 DPRINT1("GCWA iFirstChar %x\n",iFirstChar);
436
437 return GetCharWidth32A ( hdc, iFirstChar, iLastChar, lpBuffer );
438 }
439
440
441 /*
442 * @implemented
443 */
444 BOOL
445 STDCALL
446 GetCharWidth32A(
447 HDC hdc,
448 UINT iFirstChar,
449 UINT iLastChar,
450 LPINT lpBuffer
451 )
452 {
453 INT i, wlen, count = (INT)(iLastChar - iFirstChar + 1);
454 LPSTR str;
455 LPWSTR wstr;
456 BOOL ret = TRUE;
457 DPRINT1("GCW32A iFirstChar %x\n",iFirstChar);
458
459 if(count <= 0) return FALSE;
460
461 str = HeapAlloc(GetProcessHeap(), 0, count);
462 for(i = 0; i < count; i++)
463 str[i] = (BYTE)(iFirstChar + i);
464
465 wstr = FONT_mbtowc(NULL, str, count, &wlen, NULL);
466
467 for(i = 0; i < wlen; i++)
468 {
469 /* FIXME should be NtGdiGetCharWidthW */
470 if(!NtGdiGetCharWidth32 (hdc, wstr[i], wstr[i], lpBuffer))
471 {
472 ret = FALSE;
473 break;
474 }
475 lpBuffer++;
476 }
477
478 HeapFree(GetProcessHeap(), 0, str);
479 HeapFree(GetProcessHeap(), 0, wstr);
480
481 return ret;
482 }
483
484
485 /*
486 * @implemented
487 */
488 BOOL
489 STDCALL
490 GetCharWidthW (
491 HDC hdc,
492 UINT iFirstChar,
493 UINT iLastChar,
494 LPINT lpBuffer
495 )
496 {
497 DPRINT1("GCW32w uFirstChar %x\n",iFirstChar);
498
499 /* FIXME should be NtGdiGetCharWidthW */
500 return NtGdiGetCharWidth32 ( hdc, iFirstChar, iLastChar, lpBuffer );
501 }
502
503
504 /*
505 * @implemented
506 */
507 DWORD
508 STDCALL
509 GetCharacterPlacementW(
510 HDC hdc,
511 LPCWSTR lpString,
512 INT uCount,
513 INT nMaxExtent,
514 GCP_RESULTSW *lpResults,
515 DWORD dwFlags
516 )
517 {
518 DWORD ret=0;
519 SIZE size;
520 UINT i, nSet;
521
522 if(dwFlags&(~GCP_REORDER)) DPRINT("flags 0x%08lx ignored\n", dwFlags);
523 if(lpResults->lpClass) DPRINT("classes not implemented\n");
524 if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
525 DPRINT("Caret positions for complex scripts not implemented\n");
526
527 nSet = (UINT)uCount;
528 if(nSet > lpResults->nGlyphs)
529 nSet = lpResults->nGlyphs;
530
531 /* return number of initialized fields */
532 lpResults->nGlyphs = nSet;
533
534 /*if((dwFlags&GCP_REORDER)==0 || !BidiAvail)
535 {*/
536 /* Treat the case where no special handling was requested in a fastpath way */
537 /* copy will do if the GCP_REORDER flag is not set */
538 if(lpResults->lpOutString)
539 lstrcpynW( lpResults->lpOutString, lpString, nSet );
540
541 if(lpResults->lpGlyphs)
542 lstrcpynW( lpResults->lpGlyphs, lpString, nSet );
543
544 if(lpResults->lpOrder)
545 {
546 for(i = 0; i < nSet; i++)
547 lpResults->lpOrder[i] = i;
548 }
549 /*} else
550 {
551 BIDI_Reorder( lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
552 nSet, lpResults->lpOrder );
553 }*/
554
555 /* FIXME: Will use the placement chars */
556 if (lpResults->lpDx)
557 {
558 int c;
559 for (i = 0; i < nSet; i++)
560 {
561 if (NtGdiGetCharWidth32(hdc, lpString[i], lpString[i], &c))
562 lpResults->lpDx[i]= c;
563 }
564 }
565
566 if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
567 {
568 int pos = 0;
569
570 lpResults->lpCaretPos[0] = 0;
571 for (i = 1; i < nSet; i++)
572 if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
573 lpResults->lpCaretPos[i] = (pos += size.cx);
574 }
575
576 /*if(lpResults->lpGlyphs)
577 NtGdiGetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);*/
578
579 if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
580 ret = MAKELONG(size.cx, size.cy);
581
582 return ret;
583 }
584
585
586 /*
587 * @unimplemented
588 */
589 BOOL
590 APIENTRY
591 GetCharWidthFloatA(
592 HDC hdc,
593 UINT iFirstChar,
594 UINT iLastChar,
595 PFLOAT pxBuffer
596 )
597 {
598 /* FIXME what to do with iFirstChar and iLastChar ??? */
599 return FALSE;
600 }
601
602
603 /*
604 * @implemented
605 */
606 BOOL
607 APIENTRY
608 GetCharABCWidthsA(
609 HDC hdc,
610 UINT uFirstChar,
611 UINT uLastChar,
612 LPABC lpabc
613 )
614 {
615 DPRINT1("GCABCWA uFirstChar %x\n",uFirstChar);
616
617 return NtGdiGetCharABCWidths(hdc, uFirstChar, uLastChar, lpabc);
618 }
619
620
621 /*
622 * @unimplemented
623 */
624 BOOL
625 APIENTRY
626 GetCharABCWidthsFloatA(
627 HDC hdc,
628 UINT iFirstChar,
629 UINT iLastChar,
630 LPABCFLOAT lpABCF
631 )
632 {
633 DPRINT1("GCABCWFA iFirstChar %x\n",iFirstChar);
634
635 /* FIXME what to do with iFirstChar and iLastChar ??? */
636 return FALSE;
637 }
638
639 /*
640 * @implemented
641 */
642 BOOL
643 STDCALL
644 GetCharABCWidthsI(HDC hdc,
645 UINT giFirst,
646 UINT cgi,
647 LPWORD pgi,
648 LPABC lpabc
649 )
650 {
651 return NtGdiGetCharABCWidthsW( hdc, giFirst, (ULONG) cgi, (PWCHAR) pgi, 3, (PVOID)lpabc);
652 }
653
654 /*
655 * @implemented
656 */
657 DWORD
658 STDCALL
659 GetGlyphIndicesA(
660 HDC hdc,
661 LPCSTR lpstr,
662 INT count,
663 LPWORD pgi,
664 DWORD flags
665 )
666 {
667 DWORD Ret;
668 WCHAR *lpstrW;
669 INT countW;
670
671 lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
672 Ret = NtGdiGetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
673 HeapFree(GetProcessHeap(), 0, lpstrW);
674 return Ret;
675 }
676
677 /*
678 * @implemented
679 */
680 DWORD
681 STDCALL
682 GetGlyphOutlineA(
683 HDC hdc,
684 UINT uChar,
685 UINT uFormat,
686 LPGLYPHMETRICS lpgm,
687 DWORD cbBuffer,
688 LPVOID lpvBuffer,
689 CONST MAT2 *lpmat2
690 )
691 {
692
693 LPWSTR p = NULL;
694 DWORD ret;
695 UINT c;
696 DPRINT1("GetGlyphOutlineA uChar %x\n", uChar);
697 if(!(uFormat & GGO_GLYPH_INDEX)) {
698 int len;
699 char mbchs[2];
700 if(uChar > 0xff) { /* but, 2 bytes character only */
701 len = 2;
702 mbchs[0] = (uChar & 0xff00) >> 8;
703 mbchs[1] = (uChar & 0xff);
704 } else {
705 len = 1;
706 mbchs[0] = (uChar & 0xff);
707 }
708 p = FONT_mbtowc(NULL, mbchs, len, NULL, NULL);
709 c = p[0];
710 } else
711 c = uChar;
712 ret = NtGdiGetGlyphOutline(hdc, c, uFormat, lpgm, cbBuffer, lpvBuffer, (CONST LPMAT2)lpmat2, TRUE);
713 HeapFree(GetProcessHeap(), 0, p);
714 return ret;
715 }
716
717
718 /*
719 * @implemented
720 */
721 DWORD
722 STDCALL
723 GetGlyphOutlineW(
724 HDC hdc,
725 UINT uChar,
726 UINT uFormat,
727 LPGLYPHMETRICS lpgm,
728 DWORD cbBuffer,
729 LPVOID lpvBuffer,
730 CONST MAT2 *lpmat2
731 )
732 {
733 DPRINT1("GetGlyphOutlineW uChar %x\n", uChar);
734 return NtGdiGetGlyphOutline ( hdc, uChar, uFormat, lpgm, cbBuffer, lpvBuffer, (CONST LPMAT2)lpmat2, TRUE);
735 }
736
737
738 /*
739 * @implemented
740 */
741 UINT
742 APIENTRY
743 GetOutlineTextMetricsA(
744 HDC hdc,
745 UINT cbData,
746 LPOUTLINETEXTMETRICA lpOTM
747 )
748 {
749 char buf[512], *ptr;
750 UINT ret, needed;
751 OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
752 OUTLINETEXTMETRICA *output = lpOTM;
753 INT left, len;
754
755 if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
756 return 0;
757 if(ret > sizeof(buf))
758 lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
759 GetOutlineTextMetricsW(hdc, ret, lpOTMW);
760
761 needed = sizeof(OUTLINETEXTMETRICA);
762 if(lpOTMW->otmpFamilyName)
763 needed += WideCharToMultiByte(CP_ACP, 0,
764 (WCHAR*)((char*)lpOTMW + (int)lpOTMW->otmpFamilyName), -1,
765 NULL, 0, NULL, NULL);
766 if(lpOTMW->otmpFaceName)
767 needed += WideCharToMultiByte(CP_ACP, 0,
768 (WCHAR*)((char*)lpOTMW + (int)lpOTMW->otmpFaceName), -1,
769 NULL, 0, NULL, NULL);
770 if(lpOTMW->otmpStyleName)
771 needed += WideCharToMultiByte(CP_ACP, 0,
772 (WCHAR*)((char*)lpOTMW + (int)lpOTMW->otmpStyleName), -1,
773 NULL, 0, NULL, NULL);
774 if(lpOTMW->otmpFullName)
775 needed += WideCharToMultiByte(CP_ACP, 0,
776 (WCHAR*)((char*)lpOTMW + (int)lpOTMW->otmpFullName), -1,
777 NULL, 0, NULL, NULL);
778
779 if(!lpOTM) {
780 ret = needed;
781 goto end;
782 }
783
784 DPRINT("needed = %d\n", needed);
785 if(needed > cbData)
786 /* Since the supplied buffer isn't big enough, we'll alloc one
787 that is and memcpy the first cbData bytes into the lpOTM at
788 the end. */
789 output = HeapAlloc(GetProcessHeap(), 0, needed);
790
791 ret = output->otmSize = min(needed, cbData);
792 FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
793 output->otmFiller = 0;
794 output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
795 output->otmfsSelection = lpOTMW->otmfsSelection;
796 output->otmfsType = lpOTMW->otmfsType;
797 output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
798 output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
799 output->otmItalicAngle = lpOTMW->otmItalicAngle;
800 output->otmEMSquare = lpOTMW->otmEMSquare;
801 output->otmAscent = lpOTMW->otmAscent;
802 output->otmDescent = lpOTMW->otmDescent;
803 output->otmLineGap = lpOTMW->otmLineGap;
804 output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
805 output->otmsXHeight = lpOTMW->otmsXHeight;
806 output->otmrcFontBox = lpOTMW->otmrcFontBox;
807 output->otmMacAscent = lpOTMW->otmMacAscent;
808 output->otmMacDescent = lpOTMW->otmMacDescent;
809 output->otmMacLineGap = lpOTMW->otmMacLineGap;
810 output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
811 output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
812 output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
813 output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
814 output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
815 output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
816 output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
817 output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
818 output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
819
820
821 ptr = (char*)(output + 1);
822 left = needed - sizeof(*output);
823
824 if(lpOTMW->otmpFamilyName) {
825 output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
826 len = WideCharToMultiByte(CP_ACP, 0,
827 (WCHAR*)((char*)lpOTMW + (int)lpOTMW->otmpFamilyName), -1,
828 ptr, left, NULL, NULL);
829 left -= len;
830 ptr += len;
831 } else
832 output->otmpFamilyName = 0;
833
834 if(lpOTMW->otmpFaceName) {
835 output->otmpFaceName = (LPSTR)(ptr - (char*)output);
836 len = WideCharToMultiByte(CP_ACP, 0,
837 (WCHAR*)((char*)lpOTMW + (int)lpOTMW->otmpFaceName), -1,
838 ptr, left, NULL, NULL);
839 left -= len;
840 ptr += len;
841 } else
842 output->otmpFaceName = 0;
843
844 if(lpOTMW->otmpStyleName) {
845 output->otmpStyleName = (LPSTR)(ptr - (char*)output);
846 len = WideCharToMultiByte(CP_ACP, 0,
847 (WCHAR*)((char*)lpOTMW + (int)lpOTMW->otmpStyleName), -1,
848 ptr, left, NULL, NULL);
849 left -= len;
850 ptr += len;
851 } else
852 output->otmpStyleName = 0;
853
854 if(lpOTMW->otmpFullName) {
855 output->otmpFullName = (LPSTR)(ptr - (char*)output);
856 len = WideCharToMultiByte(CP_ACP, 0,
857 (WCHAR*)((char*)lpOTMW + (int)lpOTMW->otmpFullName), -1,
858 ptr, left, NULL, NULL);
859 left -= len;
860 } else
861 output->otmpFullName = 0;
862
863 assert(left == 0);
864
865 if(output != lpOTM) {
866 memcpy(lpOTM, output, cbData);
867 HeapFree(GetProcessHeap(), 0, output);
868
869 /* check if the string offsets really fit into the provided size */
870 /* FIXME: should we check string length as well? */
871 if ((UINT_PTR)lpOTM->otmpFamilyName >= lpOTM->otmSize)
872 lpOTM->otmpFamilyName = 0; /* doesn't fit */
873
874 if ((UINT_PTR)lpOTM->otmpFaceName >= lpOTM->otmSize)
875 lpOTM->otmpFaceName = 0; /* doesn't fit */
876
877 if ((UINT_PTR)lpOTM->otmpStyleName >= lpOTM->otmSize)
878 lpOTM->otmpStyleName = 0; /* doesn't fit */
879
880 if ((UINT_PTR)lpOTM->otmpFullName >= lpOTM->otmSize)
881 lpOTM->otmpFullName = 0; /* doesn't fit */
882 }
883
884 end:
885 if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
886 HeapFree(GetProcessHeap(), 0, lpOTMW);
887
888 return ret;
889 }
890
891
892 /*
893 * @implemented
894 */
895 UINT
896 APIENTRY
897 GetOutlineTextMetricsW(
898 HDC hdc,
899 UINT cbData,
900 LPOUTLINETEXTMETRICW lpOTM
901 )
902 {
903 TMDIFF Tmd; // Should not be zero.
904
905 return NtGdiGetOutlineTextMetricsInternalW(hdc, cbData, lpOTM, &Tmd);
906 }
907
908
909 /*
910 * @implemented
911 */
912 HFONT
913 STDCALL
914 CreateFontIndirectExA(const ENUMLOGFONTEXDVA *elfexd)
915 {
916 if (elfexd)
917 {
918 ENUMLOGFONTEXDVW Logfont;
919
920 EnumLogFontExW2A( (LPENUMLOGFONTEXA) elfexd,
921 &Logfont.elfEnumLogfontEx );
922
923 RtlCopyMemory( &Logfont.elfDesignVector,
924 (PVOID) &elfexd->elfDesignVector,
925 sizeof(DESIGNVECTOR));
926
927 return NtGdiHfontCreate( &Logfont, 0, 0, 0, NULL);
928 }
929 else return NULL;
930 }
931
932
933 /*
934 * @implemented
935 */
936 HFONT
937 STDCALL
938 CreateFontIndirectExW(const ENUMLOGFONTEXDVW *elfexd)
939 {
940 /* Msdn: Note, this function ignores the elfDesignVector member in
941 ENUMLOGFONTEXDV.
942 */
943 if ( elfexd )
944 {
945 return NtGdiHfontCreate((PENUMLOGFONTEXDVW) elfexd, 0, 0, 0, NULL );
946 }
947 else return NULL;
948 }
949
950
951 /*
952 * @implemented
953 */
954 HFONT
955 STDCALL
956 CreateFontIndirectA(
957 CONST LOGFONTA *lplf
958 )
959 {
960 if (lplf)
961 {
962 LOGFONTW tlf;
963
964 LogFontA2W(&tlf, lplf);
965 return CreateFontIndirectW(&tlf);
966 }
967 else return NULL;
968 }
969
970
971 /*
972 * @implemented
973 */
974 HFONT
975 STDCALL
976 CreateFontIndirectW(
977 CONST LOGFONTW *lplf
978 )
979 {
980 if (lplf)
981 {
982 ENUMLOGFONTEXDVW Logfont;
983
984 RtlCopyMemory( &Logfont.elfEnumLogfontEx.elfLogFont, lplf, sizeof(LOGFONTW));
985 // Need something other than just cleaning memory here.
986 // Guess? Use caller data to determine the rest.
987 RtlZeroMemory( &Logfont.elfEnumLogfontEx.elfFullName,
988 sizeof(Logfont.elfEnumLogfontEx.elfFullName));
989 RtlZeroMemory( &Logfont.elfEnumLogfontEx.elfStyle,
990 sizeof(Logfont.elfEnumLogfontEx.elfStyle));
991 RtlZeroMemory( &Logfont.elfEnumLogfontEx.elfScript,
992 sizeof(Logfont.elfEnumLogfontEx.elfScript));
993
994 RtlZeroMemory( &Logfont.elfDesignVector, sizeof(DESIGNVECTOR));
995
996 return CreateFontIndirectExW(&Logfont);
997 }
998 else return NULL;
999 }
1000
1001
1002 /*
1003 * @implemented
1004 */
1005 HFONT
1006 STDCALL
1007 CreateFontA(
1008 int nHeight,
1009 int nWidth,
1010 int nEscapement,
1011 int nOrientation,
1012 int fnWeight,
1013 DWORD fdwItalic,
1014 DWORD fdwUnderline,
1015 DWORD fdwStrikeOut,
1016 DWORD fdwCharSet,
1017 DWORD fdwOutputPrecision,
1018 DWORD fdwClipPrecision,
1019 DWORD fdwQuality,
1020 DWORD fdwPitchAndFamily,
1021 LPCSTR lpszFace
1022 )
1023 {
1024 ANSI_STRING StringA;
1025 UNICODE_STRING StringU;
1026 HFONT ret;
1027
1028 RtlInitAnsiString(&StringA, (LPSTR)lpszFace);
1029 RtlAnsiStringToUnicodeString(&StringU, &StringA, TRUE);
1030
1031 ret = CreateFontW(nHeight,
1032 nWidth,
1033 nEscapement,
1034 nOrientation,
1035 fnWeight,
1036 fdwItalic,
1037 fdwUnderline,
1038 fdwStrikeOut,
1039 fdwCharSet,
1040 fdwOutputPrecision,
1041 fdwClipPrecision,
1042 fdwQuality,
1043 fdwPitchAndFamily,
1044 StringU.Buffer);
1045
1046 RtlFreeUnicodeString(&StringU);
1047
1048 return ret;
1049 }
1050
1051
1052 /*
1053 * @implemented
1054 */
1055 HFONT
1056 STDCALL
1057 CreateFontW(
1058 int nHeight,
1059 int nWidth,
1060 int nEscapement,
1061 int nOrientation,
1062 int nWeight,
1063 DWORD fnItalic,
1064 DWORD fdwUnderline,
1065 DWORD fdwStrikeOut,
1066 DWORD fdwCharSet,
1067 DWORD fdwOutputPrecision,
1068 DWORD fdwClipPrecision,
1069 DWORD fdwQuality,
1070 DWORD fdwPitchAndFamily,
1071 LPCWSTR lpszFace
1072 )
1073 {
1074 LOGFONTW logfont;
1075
1076 logfont.lfHeight = nHeight;
1077 logfont.lfWidth = nWidth;
1078 logfont.lfEscapement = nEscapement;
1079 logfont.lfOrientation = nOrientation;
1080 logfont.lfWeight = nWeight;
1081 logfont.lfItalic = fnItalic;
1082 logfont.lfUnderline = fdwUnderline;
1083 logfont.lfStrikeOut = fdwStrikeOut;
1084 logfont.lfCharSet = fdwCharSet;
1085 logfont.lfOutPrecision = fdwOutputPrecision;
1086 logfont.lfClipPrecision = fdwClipPrecision;
1087 logfont.lfQuality = fdwQuality;
1088 logfont.lfPitchAndFamily = fdwPitchAndFamily;
1089
1090 if (NULL != lpszFace)
1091 {
1092 int Size = sizeof(logfont.lfFaceName) / sizeof(WCHAR);
1093 wcsncpy((wchar_t *)logfont.lfFaceName, lpszFace, Size - 1);
1094 /* Be 101% sure to have '\0' at end of string */
1095 logfont.lfFaceName[Size - 1] = '\0';
1096 }
1097 else
1098 {
1099 logfont.lfFaceName[0] = L'\0';
1100 }
1101
1102 return CreateFontIndirectW(&logfont);
1103 }
1104
1105
1106 /*
1107 * @implemented
1108 */
1109 BOOL
1110 STDCALL
1111 CreateScalableFontResourceW(
1112 DWORD fdwHidden,
1113 LPCWSTR lpszFontRes,
1114 LPCWSTR lpszFontFile,
1115 LPCWSTR lpszCurrentPath
1116 )
1117 {
1118 return NtGdiCreateScalableFontResource ( fdwHidden,
1119 lpszFontRes,
1120 lpszFontFile,
1121 lpszCurrentPath );
1122 }
1123
1124
1125 /*
1126 * @implemented
1127 */
1128 BOOL
1129 STDCALL
1130 CreateScalableFontResourceA(
1131 DWORD fdwHidden,
1132 LPCSTR lpszFontRes,
1133 LPCSTR lpszFontFile,
1134 LPCSTR lpszCurrentPath
1135 )
1136 {
1137 NTSTATUS Status;
1138 LPWSTR lpszFontResW, lpszFontFileW, lpszCurrentPathW;
1139 BOOL rc = FALSE;
1140
1141 Status = HEAP_strdupA2W ( &lpszFontResW, lpszFontRes );
1142 if (!NT_SUCCESS (Status))
1143 SetLastError (RtlNtStatusToDosError(Status));
1144 else
1145 {
1146 Status = HEAP_strdupA2W ( &lpszFontFileW, lpszFontFile );
1147 if (!NT_SUCCESS (Status))
1148 SetLastError (RtlNtStatusToDosError(Status));
1149 else
1150 {
1151 Status = HEAP_strdupA2W ( &lpszCurrentPathW, lpszCurrentPath );
1152 if (!NT_SUCCESS (Status))
1153 SetLastError (RtlNtStatusToDosError(Status));
1154 else
1155 {
1156 rc = NtGdiCreateScalableFontResource ( fdwHidden,
1157 lpszFontResW,
1158 lpszFontFileW,
1159 lpszCurrentPathW );
1160
1161 HEAP_free ( lpszCurrentPathW );
1162 }
1163
1164 HEAP_free ( lpszFontFileW );
1165 }
1166
1167 HEAP_free ( lpszFontResW );
1168 }
1169 return rc;
1170 }
1171
1172
1173 /*
1174 * @implemented
1175 */
1176 int
1177 STDCALL
1178 AddFontResourceExW ( LPCWSTR lpszFilename, DWORD fl, PVOID pvReserved )
1179 {
1180 if (fl & ~(FR_PRIVATE | FR_NOT_ENUM))
1181 {
1182 SetLastError( ERROR_INVALID_PARAMETER );
1183 return 0;
1184 }
1185
1186 return GdiAddFontResourceW(lpszFilename, fl,0);
1187 }
1188
1189
1190 /*
1191 * @implemented
1192 */
1193 int
1194 STDCALL
1195 AddFontResourceExA ( LPCSTR lpszFilename, DWORD fl, PVOID pvReserved )
1196 {
1197 NTSTATUS Status;
1198 PWSTR FilenameW;
1199 int rc;
1200
1201 if (fl & ~(FR_PRIVATE | FR_NOT_ENUM))
1202 {
1203 SetLastError( ERROR_INVALID_PARAMETER );
1204 return 0;
1205 }
1206
1207 Status = HEAP_strdupA2W ( &FilenameW, lpszFilename );
1208 if ( !NT_SUCCESS (Status) )
1209 {
1210 SetLastError (RtlNtStatusToDosError(Status));
1211 return 0;
1212 }
1213
1214 rc = GdiAddFontResourceW ( FilenameW, fl, 0 );
1215 HEAP_free ( FilenameW );
1216 return rc;
1217 }
1218
1219
1220 /*
1221 * @implemented
1222 */
1223 int
1224 STDCALL
1225 AddFontResourceA ( LPCSTR lpszFilename )
1226 {
1227 NTSTATUS Status;
1228 PWSTR FilenameW;
1229 int rc = 0;
1230
1231 Status = HEAP_strdupA2W ( &FilenameW, lpszFilename );
1232 if ( !NT_SUCCESS (Status) )
1233 {
1234 SetLastError (RtlNtStatusToDosError(Status));
1235 }
1236 else
1237 {
1238 rc = GdiAddFontResourceW ( FilenameW, 0, 0);
1239
1240 HEAP_free ( FilenameW );
1241 }
1242 return rc;
1243 }
1244
1245
1246 /*
1247 * @implemented
1248 */
1249 int
1250 STDCALL
1251 AddFontResourceW ( LPCWSTR lpszFilename )
1252 {
1253 return GdiAddFontResourceW ( lpszFilename, 0, 0 );
1254 }
1255
1256
1257 /*
1258 * @implemented
1259 */
1260 BOOL
1261 STDCALL
1262 RemoveFontResourceW(LPCWSTR lpFileName)
1263 {
1264 return RemoveFontResourceExW(lpFileName,0,0);
1265 }
1266
1267
1268 /*
1269 * @implemented
1270 */
1271 BOOL
1272 STDCALL
1273 RemoveFontResourceA(LPCSTR lpFileName)
1274 {
1275 return RemoveFontResourceExA(lpFileName,0,0);
1276 }
1277
1278 /*
1279 * @implemented
1280 */
1281 BOOL
1282 STDCALL
1283 RemoveFontResourceExA(LPCSTR lpFileName,
1284 DWORD fl,
1285 PVOID pdv
1286 )
1287 {
1288 NTSTATUS Status;
1289 LPWSTR lpFileNameW;
1290 BOOL rc = 0;
1291
1292 /* FIXME the flags */
1293 /* FIXME the pdv */
1294 /* FIXME NtGdiRemoveFontResource handle flags and pdv */
1295
1296 Status = HEAP_strdupA2W ( &lpFileNameW, lpFileName );
1297 if (!NT_SUCCESS (Status))
1298 SetLastError (RtlNtStatusToDosError(Status));
1299 else
1300 {
1301 rc = NtGdiRemoveFontResource ( lpFileNameW );
1302
1303 HEAP_free ( lpFileNameW );
1304 }
1305
1306 return rc;
1307 }
1308
1309 /*
1310 * @unimplemented
1311 */
1312 BOOL
1313 STDCALL
1314 RemoveFontResourceExW(LPCWSTR lpFileName,
1315 DWORD fl,
1316 PVOID pdv)
1317 {
1318 /* FIXME the flags */
1319 /* FIXME the pdv */
1320 /* FIXME NtGdiRemoveFontResource handle flags and pdv */
1321 return NtGdiRemoveFontResource ( lpFileName);
1322 }
1323
1324
1325 /***********************************************************************
1326 * GdiGetCharDimensions
1327 *
1328 * Gets the average width of the characters in the English alphabet.
1329 *
1330 * PARAMS
1331 * hdc [I] Handle to the device context to measure on.
1332 * lptm [O] Pointer to memory to store the text metrics into.
1333 * height [O] On exit, the maximum height of characters in the English alphabet.
1334 *
1335 * RETURNS
1336 * The average width of characters in the English alphabet.
1337 *
1338 * NOTES
1339 * This function is used by the dialog manager to get the size of a dialog
1340 * unit. It should also be used by other pieces of code that need to know
1341 * the size of a dialog unit in logical units without having access to the
1342 * window handle of the dialog.
1343 * Windows caches the font metrics from this function, but we don't and
1344 * there doesn't appear to be an immediate advantage to do so.
1345 *
1346 * SEE ALSO
1347 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
1348 *
1349 * Despite most of MSDN insisting that the horizontal base unit is
1350 * tmAveCharWidth it isn't. Knowledge base article Q145994
1351 * "HOWTO: Calculate Dialog Units When Not Using the System Font",
1352 * says that we should take the average of the 52 English upper and lower
1353 * case characters.
1354 */
1355 /*
1356 * @implemented
1357 */
1358 DWORD
1359 STDCALL
1360 GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
1361 {
1362 SIZE sz;
1363 static const WCHAR alphabet[] = {
1364 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
1365 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
1366 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
1367
1368 if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
1369
1370 if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
1371
1372 if (height) *height = sz.cy;
1373 return (sz.cx / 26 + 1) / 2;
1374 }
1375
1376 /*************************************************************************
1377 * TranslateCharsetInfo [GDI32.@]
1378 *
1379 * Fills a CHARSETINFO structure for a character set, code page, or
1380 * font. This allows making the correspondance between different labelings
1381 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
1382 * of the same encoding.
1383 *
1384 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
1385 * only one codepage should be set in *lpSrc.
1386 *
1387 * RETURNS
1388 * TRUE on success, FALSE on failure.
1389 *
1390 */
1391 /*
1392 * @unimplemented
1393 */
1394 BOOL
1395 STDCALL
1396 TranslateCharsetInfo(
1397 LPDWORD lpSrc, /* [in]
1398 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
1399 if flags == TCI_SRCCHARSET: a character set value
1400 if flags == TCI_SRCCODEPAGE: a code page value
1401 */
1402 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
1403 DWORD flags /* [in] determines interpretation of lpSrc */)
1404 {
1405 int index = 0;
1406 switch (flags) {
1407 case TCI_SRCFONTSIG:
1408 while (!(*lpSrc>>index & 0x0001) && index<MAXTCIINDEX) index++;
1409 break;
1410 case TCI_SRCCODEPAGE:
1411 while (PtrToUlong(lpSrc) != FONT_tci[index].ciACP && index < MAXTCIINDEX) index++;
1412 break;
1413 case TCI_SRCCHARSET:
1414 while (PtrToUlong(lpSrc) != FONT_tci[index].ciCharset && index < MAXTCIINDEX) index++;
1415 break;
1416 default:
1417 return FALSE;
1418 }
1419 if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
1420 memcpy(lpCs, &FONT_tci[index], sizeof(CHARSETINFO));
1421 return TRUE;
1422 }
1423
1424
1425 /*
1426 * @unimplemented
1427 */
1428 int
1429 STDCALL
1430 EnumFontsW(
1431 HDC hDC,
1432 LPCWSTR lpFaceName,
1433 FONTENUMPROCW FontFunc,
1434 LPARAM lParam
1435 )
1436 {
1437 #if 0
1438 return NtGdiEnumFonts ( hDC, lpFaceName, FontFunc, lParam );
1439 #else
1440 return EnumFontFamiliesW( hDC, lpFaceName, FontFunc, lParam );
1441 #endif
1442 }
1443
1444 /*
1445 * @unimplemented
1446 */
1447 int
1448 STDCALL
1449 EnumFontsA (
1450 HDC hDC,
1451 LPCSTR lpFaceName,
1452 FONTENUMPROCA FontFunc,
1453 LPARAM lParam
1454 )
1455 {
1456 #if 0
1457 NTSTATUS Status;
1458 LPWSTR lpFaceNameW;
1459 int rc = 0;
1460
1461 Status = HEAP_strdupA2W ( &lpFaceNameW, lpFaceName );
1462 if (!NT_SUCCESS (Status))
1463 SetLastError (RtlNtStatusToDosError(Status));
1464 else
1465 {
1466 rc = NtGdiEnumFonts ( hDC, lpFaceNameW, FontFunc, lParam );
1467
1468 HEAP_free ( lpFaceNameW );
1469 }
1470 return rc;
1471 #else
1472 return EnumFontFamiliesA( hDC, lpFaceName, FontFunc, lParam );
1473 #endif
1474 }
1475
1476 #define EfdFontFamilies 3
1477
1478 INT
1479 STDCALL
1480 NewEnumFontFamiliesExW(
1481 HDC hDC,
1482 LPLOGFONTW lpLogfont,
1483 FONTENUMPROCW lpEnumFontFamExProcW,
1484 LPARAM lParam,
1485 DWORD dwFlags)
1486 {
1487 ULONG_PTR idEnum, cbDataSize, cbRetSize;
1488 PENUMFONTDATAW pEfdw;
1489 PBYTE pBuffer;
1490 PBYTE pMax;
1491 INT ret = 1;
1492
1493 /* Open enumeration handle and find out how much memory we need */
1494 idEnum = NtGdiEnumFontOpen(hDC,
1495 EfdFontFamilies,
1496 0,
1497 LF_FACESIZE,
1498 (lpLogfont && lpLogfont->lfFaceName[0])? lpLogfont->lfFaceName : NULL,
1499 lpLogfont? lpLogfont->lfCharSet : DEFAULT_CHARSET,
1500 &cbDataSize);
1501 if (idEnum == 0)
1502 {
1503 return 0;
1504 }
1505 if (cbDataSize == 0)
1506 {
1507 NtGdiEnumFontClose(idEnum);
1508 return 0;
1509 }
1510
1511 /* Allocate memory */
1512 pBuffer = HeapAlloc(GetProcessHeap(), 0, cbDataSize);
1513 if (pBuffer == NULL)
1514 {
1515 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1516 NtGdiEnumFontClose(idEnum);
1517 return 0;
1518 }
1519
1520 /* Do the enumeration */
1521 if (!NtGdiEnumFontChunk(hDC, idEnum, cbDataSize, &cbRetSize, (PVOID)pBuffer))
1522 {
1523 HeapFree(GetProcessHeap(), 0, pBuffer);
1524 NtGdiEnumFontClose(idEnum);
1525 return 0;
1526 }
1527
1528 /* Get start and end address */
1529 pEfdw = (PENUMFONTDATAW)pBuffer;
1530 pMax = pBuffer + cbDataSize;
1531
1532 /* Iterate through the structures */
1533 while ((PBYTE)pEfdw < pMax && ret)
1534 {
1535 PNTMW_INTERNAL pNtmwi = (PNTMW_INTERNAL)((ULONG_PTR)pEfdw + pEfdw->ulNtmwiOffset);
1536
1537 ret = lpEnumFontFamExProcW(&pEfdw->elfexdv.elfEnumLogfontEx,
1538 &pNtmwi->ntmw,
1539 pEfdw->dwFontType,
1540 lParam);
1541
1542 pEfdw = (PENUMFONTDATAW)((ULONG_PTR)pEfdw + pEfdw->cbSize);
1543 }
1544
1545 /* Release the memory and close handle */
1546 HeapFree(GetProcessHeap(), 0, pBuffer);
1547 NtGdiEnumFontClose(idEnum);
1548
1549 return ret;
1550 }