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