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