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