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