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