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