- GetGlyphOutline: fail if output or transformation matrix buffers are not passed
[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 (!lpgm || !lpmat2) return GDI_ERROR;
933 if(!(uFormat & GGO_GLYPH_INDEX)) {
934 int len;
935 char mbchs[2];
936 if(uChar > 0xff) { /* but, 2 bytes character only */
937 len = 2;
938 mbchs[0] = (uChar & 0xff00) >> 8;
939 mbchs[1] = (uChar & 0xff);
940 } else {
941 len = 1;
942 mbchs[0] = (uChar & 0xff);
943 }
944 p = FONT_mbtowc(hdc, mbchs, len, NULL, NULL);
945 c = p[0];
946 } else
947 c = uChar;
948 ret = NtGdiGetGlyphOutline(hdc, c, uFormat, lpgm, cbBuffer, lpvBuffer, (CONST LPMAT2)lpmat2, TRUE);
949 HeapFree(GetProcessHeap(), 0, p);
950 return ret;
951 }
952
953
954 /*
955 * @implemented
956 */
957 DWORD
958 WINAPI
959 GetGlyphOutlineW(
960 HDC hdc,
961 UINT uChar,
962 UINT uFormat,
963 LPGLYPHMETRICS lpgm,
964 DWORD cbBuffer,
965 LPVOID lpvBuffer,
966 CONST MAT2 *lpmat2
967 )
968 {
969 DPRINT("GetGlyphOutlineW uChar %x\n", uChar);
970 if (!lpgm || !lpmat2) return GDI_ERROR;
971 if (!lpvBuffer) cbBuffer = 0;
972 return NtGdiGetGlyphOutline ( hdc, uChar, uFormat, lpgm, cbBuffer, lpvBuffer, (CONST LPMAT2)lpmat2, TRUE);
973 }
974
975
976 /*
977 * @implemented
978 */
979 UINT
980 APIENTRY
981 GetOutlineTextMetricsA(
982 HDC hdc,
983 UINT cbData,
984 LPOUTLINETEXTMETRICA lpOTM
985 )
986 {
987 char buf[512], *ptr;
988 UINT ret, needed;
989 OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
990 OUTLINETEXTMETRICA *output = lpOTM;
991 INT left, len;
992
993 if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
994 return 0;
995 if(ret > sizeof(buf))
996 lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
997 GetOutlineTextMetricsW(hdc, ret, lpOTMW);
998
999 needed = sizeof(OUTLINETEXTMETRICA);
1000 if(lpOTMW->otmpFamilyName)
1001 needed += WideCharToMultiByte(CP_ACP, 0,
1002 (WCHAR*)((char*)lpOTMW + (int)lpOTMW->otmpFamilyName), -1,
1003 NULL, 0, NULL, NULL);
1004 if(lpOTMW->otmpFaceName)
1005 needed += WideCharToMultiByte(CP_ACP, 0,
1006 (WCHAR*)((char*)lpOTMW + (int)lpOTMW->otmpFaceName), -1,
1007 NULL, 0, NULL, NULL);
1008 if(lpOTMW->otmpStyleName)
1009 needed += WideCharToMultiByte(CP_ACP, 0,
1010 (WCHAR*)((char*)lpOTMW + (int)lpOTMW->otmpStyleName), -1,
1011 NULL, 0, NULL, NULL);
1012 if(lpOTMW->otmpFullName)
1013 needed += WideCharToMultiByte(CP_ACP, 0,
1014 (WCHAR*)((char*)lpOTMW + (int)lpOTMW->otmpFullName), -1,
1015 NULL, 0, NULL, NULL);
1016
1017 if(!lpOTM) {
1018 ret = needed;
1019 goto end;
1020 }
1021
1022 DPRINT("needed = %d\n", needed);
1023 if(needed > cbData)
1024 /* Since the supplied buffer isn't big enough, we'll alloc one
1025 that is and memcpy the first cbData bytes into the lpOTM at
1026 the end. */
1027 output = HeapAlloc(GetProcessHeap(), 0, needed);
1028
1029 ret = output->otmSize = min(needed, cbData);
1030 FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1031 output->otmFiller = 0;
1032 output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1033 output->otmfsSelection = lpOTMW->otmfsSelection;
1034 output->otmfsType = lpOTMW->otmfsType;
1035 output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1036 output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1037 output->otmItalicAngle = lpOTMW->otmItalicAngle;
1038 output->otmEMSquare = lpOTMW->otmEMSquare;
1039 output->otmAscent = lpOTMW->otmAscent;
1040 output->otmDescent = lpOTMW->otmDescent;
1041 output->otmLineGap = lpOTMW->otmLineGap;
1042 output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1043 output->otmsXHeight = lpOTMW->otmsXHeight;
1044 output->otmrcFontBox = lpOTMW->otmrcFontBox;
1045 output->otmMacAscent = lpOTMW->otmMacAscent;
1046 output->otmMacDescent = lpOTMW->otmMacDescent;
1047 output->otmMacLineGap = lpOTMW->otmMacLineGap;
1048 output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1049 output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1050 output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1051 output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1052 output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1053 output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1054 output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1055 output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1056 output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1057
1058
1059 ptr = (char*)(output + 1);
1060 left = needed - sizeof(*output);
1061
1062 if(lpOTMW->otmpFamilyName) {
1063 output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1064 len = WideCharToMultiByte(CP_ACP, 0,
1065 (WCHAR*)((char*)lpOTMW + (int)lpOTMW->otmpFamilyName), -1,
1066 ptr, left, NULL, NULL);
1067 left -= len;
1068 ptr += len;
1069 } else
1070 output->otmpFamilyName = 0;
1071
1072 if(lpOTMW->otmpFaceName) {
1073 output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1074 len = WideCharToMultiByte(CP_ACP, 0,
1075 (WCHAR*)((char*)lpOTMW + (int)lpOTMW->otmpFaceName), -1,
1076 ptr, left, NULL, NULL);
1077 left -= len;
1078 ptr += len;
1079 } else
1080 output->otmpFaceName = 0;
1081
1082 if(lpOTMW->otmpStyleName) {
1083 output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1084 len = WideCharToMultiByte(CP_ACP, 0,
1085 (WCHAR*)((char*)lpOTMW + (int)lpOTMW->otmpStyleName), -1,
1086 ptr, left, NULL, NULL);
1087 left -= len;
1088 ptr += len;
1089 } else
1090 output->otmpStyleName = 0;
1091
1092 if(lpOTMW->otmpFullName) {
1093 output->otmpFullName = (LPSTR)(ptr - (char*)output);
1094 len = WideCharToMultiByte(CP_ACP, 0,
1095 (WCHAR*)((char*)lpOTMW + (int)lpOTMW->otmpFullName), -1,
1096 ptr, left, NULL, NULL);
1097 left -= len;
1098 } else
1099 output->otmpFullName = 0;
1100
1101 assert(left == 0);
1102
1103 if(output != lpOTM) {
1104 memcpy(lpOTM, output, cbData);
1105 HeapFree(GetProcessHeap(), 0, output);
1106
1107 /* check if the string offsets really fit into the provided size */
1108 /* FIXME: should we check string length as well? */
1109 if ((UINT_PTR)lpOTM->otmpFamilyName >= lpOTM->otmSize)
1110 lpOTM->otmpFamilyName = 0; /* doesn't fit */
1111
1112 if ((UINT_PTR)lpOTM->otmpFaceName >= lpOTM->otmSize)
1113 lpOTM->otmpFaceName = 0; /* doesn't fit */
1114
1115 if ((UINT_PTR)lpOTM->otmpStyleName >= lpOTM->otmSize)
1116 lpOTM->otmpStyleName = 0; /* doesn't fit */
1117
1118 if ((UINT_PTR)lpOTM->otmpFullName >= lpOTM->otmSize)
1119 lpOTM->otmpFullName = 0; /* doesn't fit */
1120 }
1121
1122 end:
1123 if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1124 HeapFree(GetProcessHeap(), 0, lpOTMW);
1125
1126 return ret;
1127 }
1128
1129
1130 /*
1131 * @implemented
1132 */
1133 UINT
1134 APIENTRY
1135 GetOutlineTextMetricsW(
1136 HDC hdc,
1137 UINT cbData,
1138 LPOUTLINETEXTMETRICW lpOTM
1139 )
1140 {
1141 TMDIFF Tmd; // Should not be zero.
1142
1143 return NtGdiGetOutlineTextMetricsInternalW(hdc, cbData, lpOTM, &Tmd);
1144 }
1145
1146 /*
1147 * @implemented
1148 */
1149 DWORD
1150 WINAPI
1151 GetKerningPairsW(HDC hdc,
1152 ULONG cPairs,
1153 LPKERNINGPAIR pkpDst)
1154 {
1155 if ((cPairs != 0) || (pkpDst == 0))
1156 {
1157 return NtGdiGetKerningPairs(hdc,cPairs,pkpDst);
1158 }
1159 else
1160 {
1161 SetLastError(ERROR_INVALID_PARAMETER);
1162 return 0;
1163 }
1164 }
1165
1166 /*
1167 * @implemented
1168 */
1169 DWORD
1170 WINAPI
1171 GetKerningPairsA( HDC hDC,
1172 DWORD cPairs,
1173 LPKERNINGPAIR kern_pairA )
1174 {
1175 INT charset;
1176 CHARSETINFO csi;
1177 CPINFO cpi;
1178 DWORD i, total_kern_pairs, kern_pairs_copied = 0;
1179 KERNINGPAIR *kern_pairW;
1180
1181 if (!cPairs && kern_pairA)
1182 {
1183 SetLastError(ERROR_INVALID_PARAMETER);
1184 return 0;
1185 }
1186
1187 charset = GetTextCharset(hDC);
1188 if (!TranslateCharsetInfo(ULongToPtr(charset), &csi, TCI_SRCCHARSET))
1189 {
1190 DPRINT1("Can't find codepage for charset %d\n", charset);
1191 return 0;
1192 }
1193 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
1194 * to fail on an invalid character for CP_SYMBOL.
1195 */
1196 cpi.DefaultChar[0] = 0;
1197 if (csi.ciACP != CP_SYMBOL && !GetCPInfo(csi.ciACP, &cpi))
1198 {
1199 DPRINT1("Can't find codepage %u info\n", csi.ciACP);
1200 return 0;
1201 }
1202 DPRINT("charset %d => codepage %u\n", charset, csi.ciACP);
1203
1204 total_kern_pairs = NtGdiGetKerningPairs(hDC, 0, NULL);
1205 if (!total_kern_pairs) return 0;
1206
1207 if (!cPairs && !kern_pairA) return total_kern_pairs;
1208
1209 kern_pairW = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW));
1210 GetKerningPairsW(hDC, total_kern_pairs, kern_pairW);
1211
1212 for (i = 0; i < total_kern_pairs; i++)
1213 {
1214 char first, second;
1215
1216 if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL))
1217 continue;
1218
1219 if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL))
1220 continue;
1221
1222 if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0])
1223 continue;
1224
1225 if (kern_pairA)
1226 {
1227 if (kern_pairs_copied >= cPairs) break;
1228
1229 kern_pairA->wFirst = (BYTE)first;
1230 kern_pairA->wSecond = (BYTE)second;
1231 kern_pairA->iKernAmount = kern_pairW[i].iKernAmount;
1232 kern_pairA++;
1233 }
1234 kern_pairs_copied++;
1235 }
1236
1237 HeapFree(GetProcessHeap(), 0, kern_pairW);
1238
1239 return kern_pairs_copied;
1240 }
1241
1242
1243
1244 /*
1245 * @implemented
1246 */
1247 HFONT
1248 WINAPI
1249 CreateFontIndirectExA(const ENUMLOGFONTEXDVA *elfexd)
1250 {
1251 if (elfexd)
1252 {
1253 ENUMLOGFONTEXDVW Logfont;
1254
1255 EnumLogFontExW2A( (LPENUMLOGFONTEXA) elfexd,
1256 &Logfont.elfEnumLogfontEx );
1257
1258 RtlCopyMemory( &Logfont.elfDesignVector,
1259 (PVOID) &elfexd->elfDesignVector,
1260 sizeof(DESIGNVECTOR));
1261
1262 return NtGdiHfontCreate( &Logfont, 0, 0, 0, NULL);
1263 }
1264 else return NULL;
1265 }
1266
1267
1268 /*
1269 * @implemented
1270 */
1271 HFONT
1272 WINAPI
1273 CreateFontIndirectExW(const ENUMLOGFONTEXDVW *elfexd)
1274 {
1275 /* Msdn: Note, this function ignores the elfDesignVector member in
1276 ENUMLOGFONTEXDV.
1277 */
1278 if ( elfexd )
1279 {
1280 return NtGdiHfontCreate((PENUMLOGFONTEXDVW) elfexd, 0, 0, 0, NULL );
1281 }
1282 else return NULL;
1283 }
1284
1285
1286 /*
1287 * @implemented
1288 */
1289 HFONT
1290 WINAPI
1291 CreateFontIndirectA(
1292 CONST LOGFONTA *lplf
1293 )
1294 {
1295 if (lplf)
1296 {
1297 LOGFONTW tlf;
1298
1299 LogFontA2W(&tlf, lplf);
1300 return CreateFontIndirectW(&tlf);
1301 }
1302 else return NULL;
1303 }
1304
1305
1306 /*
1307 * @implemented
1308 */
1309 HFONT
1310 WINAPI
1311 CreateFontIndirectW(
1312 CONST LOGFONTW *lplf
1313 )
1314 {
1315 if (lplf)
1316 {
1317 ENUMLOGFONTEXDVW Logfont;
1318
1319 RtlCopyMemory( &Logfont.elfEnumLogfontEx.elfLogFont, lplf, sizeof(LOGFONTW));
1320 // Need something other than just cleaning memory here.
1321 // Guess? Use caller data to determine the rest.
1322 RtlZeroMemory( &Logfont.elfEnumLogfontEx.elfFullName,
1323 sizeof(Logfont.elfEnumLogfontEx.elfFullName));
1324 RtlZeroMemory( &Logfont.elfEnumLogfontEx.elfStyle,
1325 sizeof(Logfont.elfEnumLogfontEx.elfStyle));
1326 RtlZeroMemory( &Logfont.elfEnumLogfontEx.elfScript,
1327 sizeof(Logfont.elfEnumLogfontEx.elfScript));
1328
1329 Logfont.elfDesignVector.dvNumAxes = 0; // No more than MM_MAX_NUMAXES
1330
1331 RtlZeroMemory( &Logfont.elfDesignVector, sizeof(DESIGNVECTOR));
1332
1333 return CreateFontIndirectExW(&Logfont);
1334 }
1335 else return NULL;
1336 }
1337
1338
1339 /*
1340 * @implemented
1341 */
1342 HFONT
1343 WINAPI
1344 CreateFontA(
1345 int nHeight,
1346 int nWidth,
1347 int nEscapement,
1348 int nOrientation,
1349 int fnWeight,
1350 DWORD fdwItalic,
1351 DWORD fdwUnderline,
1352 DWORD fdwStrikeOut,
1353 DWORD fdwCharSet,
1354 DWORD fdwOutputPrecision,
1355 DWORD fdwClipPrecision,
1356 DWORD fdwQuality,
1357 DWORD fdwPitchAndFamily,
1358 LPCSTR lpszFace
1359 )
1360 {
1361 ANSI_STRING StringA;
1362 UNICODE_STRING StringU;
1363 HFONT ret;
1364
1365 RtlInitAnsiString(&StringA, (LPSTR)lpszFace);
1366 RtlAnsiStringToUnicodeString(&StringU, &StringA, TRUE);
1367
1368 ret = CreateFontW(nHeight,
1369 nWidth,
1370 nEscapement,
1371 nOrientation,
1372 fnWeight,
1373 fdwItalic,
1374 fdwUnderline,
1375 fdwStrikeOut,
1376 fdwCharSet,
1377 fdwOutputPrecision,
1378 fdwClipPrecision,
1379 fdwQuality,
1380 fdwPitchAndFamily,
1381 StringU.Buffer);
1382
1383 RtlFreeUnicodeString(&StringU);
1384
1385 return ret;
1386 }
1387
1388
1389 /*
1390 * @implemented
1391 */
1392 HFONT
1393 WINAPI
1394 CreateFontW(
1395 int nHeight,
1396 int nWidth,
1397 int nEscapement,
1398 int nOrientation,
1399 int nWeight,
1400 DWORD fnItalic,
1401 DWORD fdwUnderline,
1402 DWORD fdwStrikeOut,
1403 DWORD fdwCharSet,
1404 DWORD fdwOutputPrecision,
1405 DWORD fdwClipPrecision,
1406 DWORD fdwQuality,
1407 DWORD fdwPitchAndFamily,
1408 LPCWSTR lpszFace
1409 )
1410 {
1411 LOGFONTW logfont;
1412
1413 logfont.lfHeight = nHeight;
1414 logfont.lfWidth = nWidth;
1415 logfont.lfEscapement = nEscapement;
1416 logfont.lfOrientation = nOrientation;
1417 logfont.lfWeight = nWeight;
1418 logfont.lfItalic = fnItalic;
1419 logfont.lfUnderline = fdwUnderline;
1420 logfont.lfStrikeOut = fdwStrikeOut;
1421 logfont.lfCharSet = fdwCharSet;
1422 logfont.lfOutPrecision = fdwOutputPrecision;
1423 logfont.lfClipPrecision = fdwClipPrecision;
1424 logfont.lfQuality = fdwQuality;
1425 logfont.lfPitchAndFamily = fdwPitchAndFamily;
1426
1427 if (NULL != lpszFace)
1428 {
1429 int Size = sizeof(logfont.lfFaceName) / sizeof(WCHAR);
1430 wcsncpy((wchar_t *)logfont.lfFaceName, lpszFace, Size - 1);
1431 /* Be 101% sure to have '\0' at end of string */
1432 logfont.lfFaceName[Size - 1] = '\0';
1433 }
1434 else
1435 {
1436 logfont.lfFaceName[0] = L'\0';
1437 }
1438
1439 return CreateFontIndirectW(&logfont);
1440 }
1441
1442
1443 /*
1444 * @unimplemented
1445 */
1446 BOOL
1447 WINAPI
1448 CreateScalableFontResourceA(
1449 DWORD fdwHidden,
1450 LPCSTR lpszFontRes,
1451 LPCSTR lpszFontFile,
1452 LPCSTR lpszCurrentPath
1453 )
1454 {
1455 return FALSE;
1456 }
1457
1458
1459 /*
1460 * @implemented
1461 */
1462 int
1463 WINAPI
1464 AddFontResourceExW ( LPCWSTR lpszFilename, DWORD fl, PVOID pvReserved )
1465 {
1466 if (fl & ~(FR_PRIVATE | FR_NOT_ENUM))
1467 {
1468 SetLastError( ERROR_INVALID_PARAMETER );
1469 return 0;
1470 }
1471
1472 return GdiAddFontResourceW(lpszFilename, fl,0);
1473 }
1474
1475
1476 /*
1477 * @implemented
1478 */
1479 int
1480 WINAPI
1481 AddFontResourceExA ( LPCSTR lpszFilename, DWORD fl, PVOID pvReserved )
1482 {
1483 NTSTATUS Status;
1484 PWSTR FilenameW;
1485 int rc;
1486
1487 if (fl & ~(FR_PRIVATE | FR_NOT_ENUM))
1488 {
1489 SetLastError( ERROR_INVALID_PARAMETER );
1490 return 0;
1491 }
1492
1493 Status = HEAP_strdupA2W ( &FilenameW, lpszFilename );
1494 if ( !NT_SUCCESS (Status) )
1495 {
1496 SetLastError (RtlNtStatusToDosError(Status));
1497 return 0;
1498 }
1499
1500 rc = GdiAddFontResourceW ( FilenameW, fl, 0 );
1501 HEAP_free ( FilenameW );
1502 return rc;
1503 }
1504
1505
1506 /*
1507 * @implemented
1508 */
1509 int
1510 WINAPI
1511 AddFontResourceA ( LPCSTR lpszFilename )
1512 {
1513 NTSTATUS Status;
1514 PWSTR FilenameW;
1515 int rc = 0;
1516
1517 Status = HEAP_strdupA2W ( &FilenameW, lpszFilename );
1518 if ( !NT_SUCCESS (Status) )
1519 {
1520 SetLastError (RtlNtStatusToDosError(Status));
1521 }
1522 else
1523 {
1524 rc = GdiAddFontResourceW ( FilenameW, 0, 0);
1525
1526 HEAP_free ( FilenameW );
1527 }
1528 return rc;
1529 }
1530
1531
1532 /*
1533 * @implemented
1534 */
1535 int
1536 WINAPI
1537 AddFontResourceW ( LPCWSTR lpszFilename )
1538 {
1539 return GdiAddFontResourceW ( lpszFilename, 0, 0 );
1540 }
1541
1542
1543 /*
1544 * @implemented
1545 */
1546 BOOL
1547 WINAPI
1548 RemoveFontResourceW(LPCWSTR lpFileName)
1549 {
1550 return RemoveFontResourceExW(lpFileName,0,0);
1551 }
1552
1553
1554 /*
1555 * @implemented
1556 */
1557 BOOL
1558 WINAPI
1559 RemoveFontResourceA(LPCSTR lpFileName)
1560 {
1561 return RemoveFontResourceExA(lpFileName,0,0);
1562 }
1563
1564 /*
1565 * @unimplemented
1566 */
1567 BOOL
1568 WINAPI
1569 RemoveFontResourceExA(LPCSTR lpFileName,
1570 DWORD fl,
1571 PVOID pdv
1572 )
1573 {
1574 NTSTATUS Status;
1575 LPWSTR lpFileNameW;
1576
1577 /* FIXME the flags */
1578 /* FIXME the pdv */
1579 /* FIXME NtGdiRemoveFontResource handle flags and pdv */
1580
1581 Status = HEAP_strdupA2W ( &lpFileNameW, lpFileName );
1582 if (!NT_SUCCESS (Status))
1583 SetLastError (RtlNtStatusToDosError(Status));
1584 else
1585 {
1586
1587 HEAP_free ( lpFileNameW );
1588 }
1589
1590 return 0;
1591 }
1592
1593 /*
1594 * @unimplemented
1595 */
1596 BOOL
1597 WINAPI
1598 RemoveFontResourceExW(LPCWSTR lpFileName,
1599 DWORD fl,
1600 PVOID pdv)
1601 {
1602 /* FIXME the flags */
1603 /* FIXME the pdv */
1604 /* FIXME NtGdiRemoveFontResource handle flags and pdv */
1605 return 0;
1606 }
1607
1608
1609 /***********************************************************************
1610 * GdiGetCharDimensions
1611 *
1612 * Gets the average width of the characters in the English alphabet.
1613 *
1614 * PARAMS
1615 * hdc [I] Handle to the device context to measure on.
1616 * lptm [O] Pointer to memory to store the text metrics into.
1617 * height [O] On exit, the maximum height of characters in the English alphabet.
1618 *
1619 * RETURNS
1620 * The average width of characters in the English alphabet.
1621 *
1622 * NOTES
1623 * This function is used by the dialog manager to get the size of a dialog
1624 * unit. It should also be used by other pieces of code that need to know
1625 * the size of a dialog unit in logical units without having access to the
1626 * window handle of the dialog.
1627 * Windows caches the font metrics from this function, but we don't and
1628 * there doesn't appear to be an immediate advantage to do so.
1629 *
1630 * SEE ALSO
1631 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
1632 *
1633 * Despite most of MSDN insisting that the horizontal base unit is
1634 * tmAveCharWidth it isn't. Knowledge base article Q145994
1635 * "HOWTO: Calculate Dialog Units When Not Using the System Font",
1636 * says that we should take the average of the 52 English upper and lower
1637 * case characters.
1638 */
1639 /*
1640 * @implemented
1641 */
1642 DWORD
1643 WINAPI
1644 GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
1645 {
1646 SIZE sz;
1647 TEXTMETRICW tm;
1648 static const WCHAR alphabet[] = {
1649 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
1650 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
1651 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
1652
1653 if(!GetTextMetricsW(hdc, &tm)) return 0;
1654
1655 if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
1656
1657 if (lptm) *lptm = tm;
1658 if (height) *height = tm.tmHeight;
1659
1660 return (sz.cx / 26 + 1) / 2;
1661 }
1662
1663 /*************************************************************************
1664 * TranslateCharsetInfo [GDI32.@]
1665 *
1666 * Fills a CHARSETINFO structure for a character set, code page, or
1667 * font. This allows making the correspondance between different labelings
1668 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
1669 * of the same encoding.
1670 *
1671 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
1672 * only one codepage should be set in *lpSrc.
1673 *
1674 * RETURNS
1675 * TRUE on success, FALSE on failure.
1676 *
1677 */
1678 /*
1679 * @unimplemented
1680 */
1681 BOOL
1682 WINAPI
1683 TranslateCharsetInfo(
1684 LPDWORD lpSrc, /* [in]
1685 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
1686 if flags == TCI_SRCCHARSET: a character set value
1687 if flags == TCI_SRCCODEPAGE: a code page value
1688 */
1689 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
1690 DWORD flags /* [in] determines interpretation of lpSrc */)
1691 {
1692 int index = 0;
1693 switch (flags) {
1694 case TCI_SRCFONTSIG:
1695 while (!(*lpSrc>>index & 0x0001) && index<MAXTCIINDEX) index++;
1696 break;
1697 case TCI_SRCCODEPAGE:
1698 while (PtrToUlong(lpSrc) != FONT_tci[index].ciACP && index < MAXTCIINDEX) index++;
1699 break;
1700 case TCI_SRCCHARSET:
1701 while (PtrToUlong(lpSrc) != FONT_tci[index].ciCharset && index < MAXTCIINDEX) index++;
1702 break;
1703 default:
1704 return FALSE;
1705 }
1706 if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
1707 memcpy(lpCs, &FONT_tci[index], sizeof(CHARSETINFO));
1708 return TRUE;
1709 }
1710
1711
1712 /*
1713 * @implemented
1714 */
1715 DWORD
1716 WINAPI
1717 SetMapperFlags(
1718 HDC hDC,
1719 DWORD flags
1720 )
1721 {
1722 DWORD Ret = GDI_ERROR;
1723 PDC_ATTR Dc_Attr;
1724 #if 0
1725 if (GDI_HANDLE_GET_TYPE(hDC) != GDI_OBJECT_TYPE_DC)
1726 {
1727 if (GDI_HANDLE_GET_TYPE(hDC) == GDI_OBJECT_TYPE_METADC)
1728 return MFDRV_SetMapperFlags( hDC, flags);
1729 else
1730 {
1731 PLDC pLDC = Dc_Attr->pvLDC;
1732 if ( !pLDC )
1733 {
1734 SetLastError(ERROR_INVALID_HANDLE);
1735 return GDI_ERROR;
1736 }
1737 if (pLDC->iType == LDC_EMFLDC)
1738 {
1739 return EMFDRV_SetMapperFlags( hDC, flags);
1740 }
1741 }
1742 }
1743 #endif
1744 if (!GdiGetHandleUserData((HGDIOBJ) hDC, GDI_OBJECT_TYPE_DC, (PVOID) &Dc_Attr)) return GDI_ERROR;
1745
1746 if (NtCurrentTeb()->GdiTebBatch.HDC == hDC)
1747 {
1748 if (Dc_Attr->ulDirty_ & DC_FONTTEXT_DIRTY)
1749 {
1750 NtGdiFlush();
1751 Dc_Attr->ulDirty_ &= ~(DC_MODE_DIRTY|DC_FONTTEXT_DIRTY);
1752 }
1753 }
1754
1755 if ( flags & ~1 )
1756 SetLastError(ERROR_INVALID_PARAMETER);
1757 else
1758 {
1759 Ret = Dc_Attr->flFontMapper;
1760 Dc_Attr->flFontMapper = flags;
1761 }
1762 return Ret;
1763 }
1764
1765
1766 /*
1767 * @unimplemented
1768 */
1769 int
1770 WINAPI
1771 EnumFontsW(
1772 HDC hDC,
1773 LPCWSTR lpFaceName,
1774 FONTENUMPROCW FontFunc,
1775 LPARAM lParam
1776 )
1777 {
1778 #if 0
1779 return NtGdiEnumFonts ( hDC, lpFaceName, FontFunc, lParam );
1780 #else
1781 return EnumFontFamiliesW( hDC, lpFaceName, FontFunc, lParam );
1782 #endif
1783 }
1784
1785 /*
1786 * @unimplemented
1787 */
1788 int
1789 WINAPI
1790 EnumFontsA (
1791 HDC hDC,
1792 LPCSTR lpFaceName,
1793 FONTENUMPROCA FontFunc,
1794 LPARAM lParam
1795 )
1796 {
1797 #if 0
1798 NTSTATUS Status;
1799 LPWSTR lpFaceNameW;
1800 int rc = 0;
1801
1802 Status = HEAP_strdupA2W ( &lpFaceNameW, lpFaceName );
1803 if (!NT_SUCCESS (Status))
1804 SetLastError (RtlNtStatusToDosError(Status));
1805 else
1806 {
1807 rc = NtGdiEnumFonts ( hDC, lpFaceNameW, FontFunc, lParam );
1808
1809 HEAP_free ( lpFaceNameW );
1810 }
1811 return rc;
1812 #else
1813 return EnumFontFamiliesA( hDC, lpFaceName, FontFunc, lParam );
1814 #endif
1815 }
1816
1817 #define EfdFontFamilies 3
1818
1819 INT
1820 WINAPI
1821 NewEnumFontFamiliesExW(
1822 HDC hDC,
1823 LPLOGFONTW lpLogfont,
1824 FONTENUMPROCW lpEnumFontFamExProcW,
1825 LPARAM lParam,
1826 DWORD dwFlags)
1827 {
1828 ULONG_PTR idEnum, cbDataSize, cbRetSize;
1829 PENUMFONTDATAW pEfdw;
1830 PBYTE pBuffer;
1831 PBYTE pMax;
1832 INT ret = 1;
1833
1834 /* Open enumeration handle and find out how much memory we need */
1835 idEnum = NtGdiEnumFontOpen(hDC,
1836 EfdFontFamilies,
1837 0,
1838 LF_FACESIZE,
1839 (lpLogfont && lpLogfont->lfFaceName[0])? lpLogfont->lfFaceName : NULL,
1840 lpLogfont? lpLogfont->lfCharSet : DEFAULT_CHARSET,
1841 &cbDataSize);
1842 if (idEnum == 0)
1843 {
1844 return 0;
1845 }
1846 if (cbDataSize == 0)
1847 {
1848 NtGdiEnumFontClose(idEnum);
1849 return 0;
1850 }
1851
1852 /* Allocate memory */
1853 pBuffer = HeapAlloc(GetProcessHeap(), 0, cbDataSize);
1854 if (pBuffer == NULL)
1855 {
1856 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1857 NtGdiEnumFontClose(idEnum);
1858 return 0;
1859 }
1860
1861 /* Do the enumeration */
1862 if (!NtGdiEnumFontChunk(hDC, idEnum, cbDataSize, &cbRetSize, (PVOID)pBuffer))
1863 {
1864 HeapFree(GetProcessHeap(), 0, pBuffer);
1865 NtGdiEnumFontClose(idEnum);
1866 return 0;
1867 }
1868
1869 /* Get start and end address */
1870 pEfdw = (PENUMFONTDATAW)pBuffer;
1871 pMax = pBuffer + cbDataSize;
1872
1873 /* Iterate through the structures */
1874 while ((PBYTE)pEfdw < pMax && ret)
1875 {
1876 PNTMW_INTERNAL pNtmwi = (PNTMW_INTERNAL)((ULONG_PTR)pEfdw + pEfdw->ulNtmwiOffset);
1877
1878 ret = lpEnumFontFamExProcW((VOID*)&pEfdw->elfexdv.elfEnumLogfontEx,
1879 (VOID*)&pNtmwi->ntmw,
1880 pEfdw->dwFontType,
1881 lParam);
1882
1883 pEfdw = (PENUMFONTDATAW)((ULONG_PTR)pEfdw + pEfdw->cbSize);
1884 }
1885
1886 /* Release the memory and close handle */
1887 HeapFree(GetProcessHeap(), 0, pBuffer);
1888 NtGdiEnumFontClose(idEnum);
1889
1890 return ret;
1891 }