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