[GDI32][LPK] BiDi support for ExtTextOut and GetCharacterPlacement (#534)
[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: win32ss/gdi/gdi32/objects/font.c
5 * PURPOSE:
6 * PROGRAMMER:
7 *
8 */
9
10 #include <precomp.h>
11
12 #include <math.h>
13 #include <strsafe.h>
14
15 #define NDEBUG
16 #include <debug.h>
17
18 /* Rounds a floating point number to integer. The world-to-viewport
19 * transformation process is done in floating point internally. This function
20 * is then used to round these coordinates to integer values.
21 */
22 static __inline INT GDI_ROUND(FLOAT val)
23 {
24 return (int)floor(val + 0.5);
25 }
26
27 /*
28 * For TranslateCharsetInfo
29 */
30 #define MAXTCIINDEX 32
31 static const CHARSETINFO FONT_tci[MAXTCIINDEX] =
32 {
33 /* ANSI */
34 { ANSI_CHARSET, 1252, {{0,0,0,0},{FS_LATIN1,0}} },
35 { EASTEUROPE_CHARSET, 1250, {{0,0,0,0},{FS_LATIN2,0}} },
36 { RUSSIAN_CHARSET, 1251, {{0,0,0,0},{FS_CYRILLIC,0}} },
37 { GREEK_CHARSET, 1253, {{0,0,0,0},{FS_GREEK,0}} },
38 { TURKISH_CHARSET, 1254, {{0,0,0,0},{FS_TURKISH,0}} },
39 { HEBREW_CHARSET, 1255, {{0,0,0,0},{FS_HEBREW,0}} },
40 { ARABIC_CHARSET, 1256, {{0,0,0,0},{FS_ARABIC,0}} },
41 { BALTIC_CHARSET, 1257, {{0,0,0,0},{FS_BALTIC,0}} },
42 { VIETNAMESE_CHARSET, 1258, {{0,0,0,0},{FS_VIETNAMESE,0}} },
43 /* reserved by ANSI */
44 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
45 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
46 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
47 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
48 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
49 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
50 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
51 /* ANSI and OEM */
52 { THAI_CHARSET, 874, {{0,0,0,0},{FS_THAI,0}} },
53 { SHIFTJIS_CHARSET, 932, {{0,0,0,0},{FS_JISJAPAN,0}} },
54 { GB2312_CHARSET, 936, {{0,0,0,0},{FS_CHINESESIMP,0}} },
55 { HANGEUL_CHARSET, 949, {{0,0,0,0},{FS_WANSUNG,0}} },
56 { CHINESEBIG5_CHARSET, 950, {{0,0,0,0},{FS_CHINESETRAD,0}} },
57 { JOHAB_CHARSET, 1361, {{0,0,0,0},{FS_JOHAB,0}} },
58 /* reserved for alternate ANSI and OEM */
59 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
60 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
61 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
62 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
63 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
64 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
65 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
66 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
67 /* reserved for system */
68 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
69 { SYMBOL_CHARSET, CP_SYMBOL, {{0,0,0,0},{FS_SYMBOL,0}} }
70 };
71
72 #define INITIAL_FAMILY_COUNT 64
73
74 /***********************************************************************
75 * TEXTMETRIC conversion functions.
76 */
77 VOID
78 FASTCALL
79 FONT_TextMetricWToA(const TEXTMETRICW *ptmW, LPTEXTMETRICA ptmA )
80 {
81 ptmA->tmHeight = ptmW->tmHeight;
82 ptmA->tmAscent = ptmW->tmAscent;
83 ptmA->tmDescent = ptmW->tmDescent;
84 ptmA->tmInternalLeading = ptmW->tmInternalLeading;
85 ptmA->tmExternalLeading = ptmW->tmExternalLeading;
86 ptmA->tmAveCharWidth = ptmW->tmAveCharWidth;
87 ptmA->tmMaxCharWidth = ptmW->tmMaxCharWidth;
88 ptmA->tmWeight = ptmW->tmWeight;
89 ptmA->tmOverhang = ptmW->tmOverhang;
90 ptmA->tmDigitizedAspectX = ptmW->tmDigitizedAspectX;
91 ptmA->tmDigitizedAspectY = ptmW->tmDigitizedAspectY;
92 ptmA->tmFirstChar = min(ptmW->tmFirstChar, 255);
93 if (ptmW->tmCharSet == SYMBOL_CHARSET)
94 {
95 ptmA->tmFirstChar = 0x1e;
96 ptmA->tmLastChar = 0xff; /* win9x behaviour - we need the OS2 table data to calculate correctly */
97 }
98 else
99 {
100 ptmA->tmFirstChar = ptmW->tmDefaultChar - 1;
101 ptmA->tmLastChar = min(ptmW->tmLastChar, 0xff);
102 }
103 ptmA->tmDefaultChar = (CHAR)ptmW->tmDefaultChar;
104 ptmA->tmBreakChar = (CHAR)ptmW->tmBreakChar;
105 ptmA->tmItalic = ptmW->tmItalic;
106 ptmA->tmUnderlined = ptmW->tmUnderlined;
107 ptmA->tmStruckOut = ptmW->tmStruckOut;
108 ptmA->tmPitchAndFamily = ptmW->tmPitchAndFamily;
109 ptmA->tmCharSet = ptmW->tmCharSet;
110 }
111
112 /***********************************************************************
113 * FONT_mbtowc
114 *
115 * Returns a Unicode translation of str using the charset of the
116 * currently selected font in hdc. If count is -1 then str is assumed
117 * to be '\0' terminated, otherwise it contains the number of bytes to
118 * convert. If plenW is non-NULL, on return it will point to the
119 * number of WCHARs that have been written. If pCP is non-NULL, on
120 * return it will point to the codepage used in the conversion. The
121 * caller should free the returned LPWSTR from the process heap
122 * itself.
123 */
124 static LPWSTR FONT_mbtowc(HDC hdc, LPCSTR str, INT count, INT *plenW, UINT *pCP)
125 {
126 UINT cp = GdiGetCodePage( hdc );
127 INT lenW;
128 LPWSTR strW;
129
130 if(count == -1) count = strlen(str);
131 lenW = MultiByteToWideChar(cp, 0, str, count, NULL, 0);
132 strW = HeapAlloc(GetProcessHeap(), 0, lenW*sizeof(WCHAR));
133 if (!strW)
134 return NULL;
135 if(!MultiByteToWideChar(cp, 0, str, count, strW, lenW))
136 {
137 HeapFree(GetProcessHeap(), 0, strW);
138 return NULL;
139 }
140 DPRINT("mapped %s -> %S\n", str, strW);
141 if(plenW) *plenW = lenW;
142 if(pCP) *pCP = cp;
143 return strW;
144 }
145
146 static LPSTR FONT_GetCharsByRangeA(HDC hdc, UINT firstChar, UINT lastChar, PINT pByteLen)
147 {
148 INT i, count = lastChar - firstChar + 1;
149 UINT c;
150 LPSTR str;
151
152 if (count <= 0)
153 return NULL;
154
155 switch (GdiGetCodePage(hdc))
156 {
157 case 932:
158 case 936:
159 case 949:
160 case 950:
161 case 1361:
162 if (lastChar > 0xffff)
163 return NULL;
164 if ((firstChar ^ lastChar) > 0xff)
165 return NULL;
166 break;
167 default:
168 if (lastChar > 0xff)
169 return NULL;
170 break;
171 }
172
173 str = HeapAlloc(GetProcessHeap(), 0, count * 2 + 1);
174 if (str == NULL)
175 return NULL;
176
177 for(i = 0, c = firstChar; c <= lastChar; i++, c++)
178 {
179 if (c > 0xff)
180 str[i++] = (BYTE)(c >> 8);
181 str[i] = (BYTE)c;
182 }
183 str[i] = '\0';
184
185 *pByteLen = i;
186
187 return str;
188 }
189
190 VOID FASTCALL
191 NewTextMetricW2A(NEWTEXTMETRICA *tma, NEWTEXTMETRICW *tmw)
192 {
193 FONT_TextMetricWToA((TEXTMETRICW *) tmw, (TEXTMETRICA *) tma);
194 tma->ntmFlags = tmw->ntmFlags;
195 tma->ntmSizeEM = tmw->ntmSizeEM;
196 tma->ntmCellHeight = tmw->ntmCellHeight;
197 tma->ntmAvgWidth = tmw->ntmAvgWidth;
198 }
199
200 VOID FASTCALL
201 NewTextMetricExW2A(NEWTEXTMETRICEXA *tma, NEWTEXTMETRICEXW *tmw)
202 {
203 NewTextMetricW2A(&tma->ntmTm, &tmw->ntmTm);
204 tma->ntmFontSig = tmw->ntmFontSig;
205 }
206
207 static int FASTCALL
208 IntEnumFontFamilies(HDC Dc, LPLOGFONTW LogFont, PVOID EnumProc, LPARAM lParam,
209 BOOL Unicode)
210 {
211 int FontFamilyCount;
212 int FontFamilySize;
213 PFONTFAMILYINFO Info;
214 int Ret = 1;
215 int i;
216 ENUMLOGFONTEXA EnumLogFontExA;
217 NEWTEXTMETRICEXA NewTextMetricExA;
218 LOGFONTW lfW;
219
220 Info = RtlAllocateHeap(GetProcessHeap(), 0,
221 INITIAL_FAMILY_COUNT * sizeof(FONTFAMILYINFO));
222 if (NULL == Info)
223 {
224 return 1;
225 }
226
227 if (!LogFont)
228 {
229 lfW.lfCharSet = DEFAULT_CHARSET;
230 lfW.lfPitchAndFamily = 0;
231 lfW.lfFaceName[0] = 0;
232 LogFont = &lfW;
233 }
234
235 FontFamilyCount = NtGdiGetFontFamilyInfo(Dc, LogFont, Info, INITIAL_FAMILY_COUNT);
236 if (FontFamilyCount < 0)
237 {
238 RtlFreeHeap(GetProcessHeap(), 0, Info);
239 return 1;
240 }
241 if (INITIAL_FAMILY_COUNT < FontFamilyCount)
242 {
243 FontFamilySize = FontFamilyCount;
244 RtlFreeHeap(GetProcessHeap(), 0, Info);
245 Info = RtlAllocateHeap(GetProcessHeap(), 0,
246 FontFamilyCount * sizeof(FONTFAMILYINFO));
247 if (NULL == Info)
248 {
249 return 1;
250 }
251 FontFamilyCount = NtGdiGetFontFamilyInfo(Dc, LogFont, Info, FontFamilySize);
252 if (FontFamilyCount < 0 || FontFamilySize < FontFamilyCount)
253 {
254 RtlFreeHeap(GetProcessHeap(), 0, Info);
255 return 1;
256 }
257 }
258
259 for (i = 0; i < FontFamilyCount; i++)
260 {
261 if (Unicode)
262 {
263 Ret = ((FONTENUMPROCW) EnumProc)(
264 (VOID*)&Info[i].EnumLogFontEx,
265 (VOID*)&Info[i].NewTextMetricEx,
266 Info[i].FontType, lParam);
267 }
268 else
269 {
270 // Could use EnumLogFontExW2A here?
271 LogFontW2A(&EnumLogFontExA.elfLogFont, &Info[i].EnumLogFontEx.elfLogFont);
272 WideCharToMultiByte(CP_THREAD_ACP, 0, Info[i].EnumLogFontEx.elfFullName, -1,
273 (LPSTR)EnumLogFontExA.elfFullName, LF_FULLFACESIZE, NULL, NULL);
274 WideCharToMultiByte(CP_THREAD_ACP, 0, Info[i].EnumLogFontEx.elfStyle, -1,
275 (LPSTR)EnumLogFontExA.elfStyle, LF_FACESIZE, NULL, NULL);
276 WideCharToMultiByte(CP_THREAD_ACP, 0, Info[i].EnumLogFontEx.elfScript, -1,
277 (LPSTR)EnumLogFontExA.elfScript, LF_FACESIZE, NULL, NULL);
278 NewTextMetricExW2A(&NewTextMetricExA,
279 &Info[i].NewTextMetricEx);
280 Ret = ((FONTENUMPROCA) EnumProc)(
281 (VOID*)&EnumLogFontExA,
282 (VOID*)&NewTextMetricExA,
283 Info[i].FontType, lParam);
284 }
285
286 if(Ret == 0)
287 break;
288 }
289
290 RtlFreeHeap(GetProcessHeap(), 0, Info);
291
292 return Ret;
293 }
294
295 /*
296 * @implemented
297 */
298 int WINAPI
299 EnumFontFamiliesExW(HDC hdc, LPLOGFONTW lpLogfont, FONTENUMPROCW lpEnumFontFamExProc,
300 LPARAM lParam, DWORD dwFlags)
301 {
302 return IntEnumFontFamilies(hdc, lpLogfont, lpEnumFontFamExProc, lParam, TRUE);
303 }
304
305
306 /*
307 * @implemented
308 */
309 int WINAPI
310 EnumFontFamiliesW(HDC hdc, LPCWSTR lpszFamily, FONTENUMPROCW lpEnumFontFamProc,
311 LPARAM lParam)
312 {
313 LOGFONTW LogFont;
314
315 ZeroMemory(&LogFont, sizeof(LOGFONTW));
316 LogFont.lfCharSet = DEFAULT_CHARSET;
317 if (NULL != lpszFamily)
318 {
319 if (!*lpszFamily) return 1;
320 lstrcpynW(LogFont.lfFaceName, lpszFamily, LF_FACESIZE);
321 }
322
323 return IntEnumFontFamilies(hdc, &LogFont, lpEnumFontFamProc, lParam, TRUE);
324 }
325
326
327 /*
328 * @implemented
329 */
330 int WINAPI
331 EnumFontFamiliesExA (HDC hdc, LPLOGFONTA lpLogfont, FONTENUMPROCA lpEnumFontFamExProc,
332 LPARAM lParam, DWORD dwFlags)
333 {
334 LOGFONTW LogFontW, *pLogFontW;
335
336 if (lpLogfont)
337 {
338 LogFontA2W(&LogFontW,lpLogfont);
339 pLogFontW = &LogFontW;
340 }
341 else pLogFontW = NULL;
342
343 /* no need to convert LogFontW back to lpLogFont b/c it's an [in] parameter only */
344 return IntEnumFontFamilies(hdc, pLogFontW, lpEnumFontFamExProc, lParam, FALSE);
345 }
346
347
348 /*
349 * @implemented
350 */
351 int WINAPI
352 EnumFontFamiliesA(HDC hdc, LPCSTR lpszFamily, FONTENUMPROCA lpEnumFontFamProc,
353 LPARAM lParam)
354 {
355 LOGFONTW LogFont;
356
357 ZeroMemory(&LogFont, sizeof(LOGFONTW));
358 LogFont.lfCharSet = DEFAULT_CHARSET;
359 if (NULL != lpszFamily)
360 {
361 if (!*lpszFamily) return 1;
362 MultiByteToWideChar(CP_THREAD_ACP, 0, lpszFamily, -1, LogFont.lfFaceName, LF_FACESIZE);
363 }
364
365 return IntEnumFontFamilies(hdc, &LogFont, lpEnumFontFamProc, lParam, FALSE);
366 }
367
368
369 /*
370 * @implemented
371 */
372 DWORD
373 WINAPI
374 GetCharacterPlacementA(
375 HDC hdc,
376 LPCSTR lpString,
377 INT uCount,
378 INT nMaxExtent,
379 GCP_RESULTSA *lpResults,
380 DWORD dwFlags)
381 {
382 WCHAR *lpStringW;
383 INT uCountW;
384 GCP_RESULTSW resultsW;
385 DWORD ret;
386 UINT font_cp;
387
388 if ( !lpString || uCount <= 0 || !lpResults || (nMaxExtent < 0 && nMaxExtent != -1 ) )
389 {
390 SetLastError(ERROR_INVALID_PARAMETER);
391 return 0;
392 }
393 /* TRACE("%s, %d, %d, 0x%08x\n",
394 debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
395 */
396 /* both structs are equal in size */
397 memcpy(&resultsW, lpResults, sizeof(resultsW));
398
399 lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
400 if (lpStringW == NULL)
401 {
402 return 0;
403 }
404 if(lpResults->lpOutString)
405 {
406 resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
407 if (resultsW.lpOutString == NULL)
408 {
409 HeapFree(GetProcessHeap(), 0, lpStringW);
410 return 0;
411 }
412 }
413
414 ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
415
416 lpResults->nGlyphs = resultsW.nGlyphs;
417 lpResults->nMaxFit = resultsW.nMaxFit;
418
419 if(lpResults->lpOutString)
420 {
421 WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
422 lpResults->lpOutString, uCount, NULL, NULL );
423 }
424
425 HeapFree(GetProcessHeap(), 0, lpStringW);
426 HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
427
428 return ret;
429 }
430
431
432 /*
433 * @implemented
434 */
435 DWORD
436 WINAPI
437 GetCharacterPlacementW(
438 HDC hdc,
439 LPCWSTR lpString,
440 INT uCount,
441 INT nMaxExtent,
442 GCP_RESULTSW *lpResults,
443 DWORD dwFlags
444 )
445 {
446 DWORD ret=0;
447 SIZE size;
448 UINT i, nSet;
449 DPRINT("GetCharacterPlacementW\n");
450
451 if (dwFlags&(~GCP_REORDER)) DPRINT("flags 0x%08lx ignored\n", dwFlags);
452 if (lpResults->lpClass) DPRINT("classes not implemented\n");
453 if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
454 DPRINT("Caret positions for complex scripts not implemented\n");
455
456 nSet = (UINT)uCount;
457 if (nSet > lpResults->nGlyphs)
458 nSet = lpResults->nGlyphs;
459
460 /* return number of initialized fields */
461 lpResults->nGlyphs = nSet;
462
463 if (dwFlags & GCP_REORDER)
464 {
465 if (LoadLPK(LPK_GCP))
466 return LpkGetCharacterPlacement(hdc, lpString, uCount, nMaxExtent, lpResults, dwFlags, 0);
467 }
468
469 /* Treat the case where no special handling was requested in a fastpath way */
470 /* copy will do if the GCP_REORDER flag is not set */
471 if (lpResults->lpOutString)
472 lstrcpynW( lpResults->lpOutString, lpString, nSet );
473
474 if (lpResults->lpOrder)
475 {
476 for (i = 0; i < nSet; i++)
477 lpResults->lpOrder[i] = i;
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 DWORD
511 WINAPI
512 NewGetCharacterPlacementW(
513 HDC hdc,
514 LPCWSTR lpString,
515 INT uCount,
516 INT nMaxExtent,
517 GCP_RESULTSW *lpResults,
518 DWORD dwFlags
519 )
520 {
521 ULONG nSet;
522 SIZE Size = {0,0};
523
524 if ( !lpString || uCount <= 0 || (nMaxExtent < 0 && nMaxExtent != -1 ) )
525 {
526 SetLastError(ERROR_INVALID_PARAMETER);
527 return 0;
528 }
529
530 if ( !lpResults )
531 {
532 if ( GetTextExtentPointW(hdc, lpString, uCount, &Size) )
533 {
534 return MAKELONG(Size.cx, Size.cy);
535 }
536 return 0;
537 }
538
539 nSet = uCount;
540 if ( nSet > lpResults->nGlyphs )
541 nSet = lpResults->nGlyphs;
542
543 return NtGdiGetCharacterPlacementW( hdc,
544 (LPWSTR)lpString,
545 nSet,
546 nMaxExtent,
547 lpResults,
548 dwFlags);
549 }
550
551 /*
552 * @implemented
553 *
554 */
555 BOOL
556 WINAPI
557 GetCharABCWidthsFloatW(HDC hdc,
558 UINT FirstChar,
559 UINT LastChar,
560 LPABCFLOAT abcF)
561 {
562 DPRINT("GetCharABCWidthsFloatW\n");
563 if ((!abcF) || (FirstChar > LastChar))
564 {
565 SetLastError(ERROR_INVALID_PARAMETER);
566 return FALSE;
567 }
568 return NtGdiGetCharABCWidthsW( hdc,
569 FirstChar,
570 (ULONG)(LastChar - FirstChar + 1),
571 (PWCHAR) NULL,
572 0,
573 (PVOID)abcF);
574 }
575
576 /*
577 * @implemented
578 *
579 */
580 BOOL
581 WINAPI
582 GetCharWidthFloatW(HDC hdc,
583 UINT iFirstChar,
584 UINT iLastChar,
585 PFLOAT pxBuffer)
586 {
587 DPRINT("GetCharWidthsFloatW\n");
588 if ((!pxBuffer) || (iFirstChar > iLastChar))
589 {
590 SetLastError(ERROR_INVALID_PARAMETER);
591 return FALSE;
592 }
593 return NtGdiGetCharWidthW( hdc,
594 iFirstChar,
595 (ULONG)(iLastChar - iFirstChar + 1),
596 (PWCHAR) NULL,
597 0,
598 (PVOID) pxBuffer);
599 }
600
601 /*
602 * @implemented
603 *
604 */
605 BOOL
606 WINAPI
607 GetCharWidthW(HDC hdc,
608 UINT iFirstChar,
609 UINT iLastChar,
610 LPINT lpBuffer)
611 {
612 DPRINT("GetCharWidthsW\n");
613 if ((!lpBuffer) || (iFirstChar > iLastChar))
614 {
615 SetLastError(ERROR_INVALID_PARAMETER);
616 return FALSE;
617 }
618 return NtGdiGetCharWidthW( hdc,
619 iFirstChar,
620 (ULONG)(iLastChar - iFirstChar + 1),
621 (PWCHAR) NULL,
622 GCW_NOFLOAT,
623 (PVOID) lpBuffer);
624 }
625
626 /*
627 * @implemented
628 *
629 */
630 BOOL
631 WINAPI
632 GetCharWidth32W(HDC hdc,
633 UINT iFirstChar,
634 UINT iLastChar,
635 LPINT lpBuffer)
636 {
637 DPRINT("GetCharWidths32W\n");
638 if ((!lpBuffer) || (iFirstChar > iLastChar))
639 {
640 SetLastError(ERROR_INVALID_PARAMETER);
641 return FALSE;
642 }
643 return NtGdiGetCharWidthW( hdc,
644 iFirstChar,
645 (ULONG)(iLastChar - iFirstChar + 1),
646 (PWCHAR) NULL,
647 GCW_NOFLOAT|GCW_WIN32,
648 (PVOID) lpBuffer);
649 }
650
651
652 /*
653 * @implemented
654 *
655 */
656 BOOL
657 WINAPI
658 GetCharABCWidthsW(HDC hdc,
659 UINT FirstChar,
660 UINT LastChar,
661 LPABC lpabc)
662 {
663 DPRINT("GetCharABCWidthsW\n");
664 if ((!lpabc) || (FirstChar > LastChar))
665 {
666 SetLastError(ERROR_INVALID_PARAMETER);
667 return FALSE;
668 }
669 return NtGdiGetCharABCWidthsW( hdc,
670 FirstChar,
671 (ULONG)(LastChar - FirstChar + 1),
672 (PWCHAR) NULL,
673 GCABCW_NOFLOAT,
674 (PVOID)lpabc);
675 }
676
677 /*
678 * @implemented
679 */
680 BOOL
681 WINAPI
682 GetCharWidthA(
683 HDC hdc,
684 UINT iFirstChar,
685 UINT iLastChar,
686 LPINT lpBuffer
687 )
688 {
689 INT wlen, count = 0;
690 LPSTR str;
691 LPWSTR wstr;
692 BOOL ret = TRUE;
693
694 DPRINT("GetCharWidthsA\n");
695
696 str = FONT_GetCharsByRangeA(hdc, iFirstChar, iLastChar, &count);
697 if (!str)
698 return FALSE;
699
700 wstr = FONT_mbtowc(hdc, str, count+1, &wlen, NULL);
701 if (!wstr)
702 {
703 HeapFree(GetProcessHeap(), 0, str);
704 return FALSE;
705 }
706
707 ret = NtGdiGetCharWidthW( hdc,
708 wstr[0],
709 (ULONG) count,
710 (PWCHAR) wstr,
711 GCW_NOFLOAT,
712 (PVOID) lpBuffer);
713
714 HeapFree(GetProcessHeap(), 0, str);
715 HeapFree(GetProcessHeap(), 0, wstr);
716
717 return ret;
718 }
719
720 /*
721 * @implemented
722 */
723 BOOL
724 WINAPI
725 GetCharWidth32A(
726 HDC hdc,
727 UINT iFirstChar,
728 UINT iLastChar,
729 LPINT lpBuffer
730 )
731 {
732 INT wlen, count = 0;
733 LPSTR str;
734 LPWSTR wstr;
735 BOOL ret = TRUE;
736
737 DPRINT("GetCharWidths32A\n");
738
739 str = FONT_GetCharsByRangeA(hdc, iFirstChar, iLastChar, &count);
740 if (!str)
741 return FALSE;
742
743 wstr = FONT_mbtowc(hdc, str, count+1, &wlen, NULL);
744 if (!wstr)
745 {
746 HeapFree(GetProcessHeap(), 0, str);
747 return FALSE;
748 }
749
750 ret = NtGdiGetCharWidthW( hdc,
751 wstr[0],
752 (ULONG) count,
753 (PWCHAR) wstr,
754 GCW_NOFLOAT|GCW_WIN32,
755 (PVOID) lpBuffer);
756
757 HeapFree(GetProcessHeap(), 0, str);
758 HeapFree(GetProcessHeap(), 0, wstr);
759
760 return ret;
761 }
762
763 /*
764 * @implemented
765 */
766 BOOL
767 APIENTRY
768 GetCharWidthFloatA(
769 HDC hdc,
770 UINT iFirstChar,
771 UINT iLastChar,
772 PFLOAT pxBuffer
773 )
774 {
775 INT wlen, count = 0;
776 LPSTR str;
777 LPWSTR wstr;
778 BOOL ret = TRUE;
779
780 DPRINT("GetCharWidthsFloatA\n");
781
782 str = FONT_GetCharsByRangeA(hdc, iFirstChar, iLastChar, &count);
783 if (!str)
784 return FALSE;
785
786 wstr = FONT_mbtowc(hdc, str, count+1, &wlen, NULL);
787 if (!wstr)
788 {
789 HeapFree(GetProcessHeap(), 0, str);
790 return FALSE;
791 }
792 ret = NtGdiGetCharWidthW( hdc, wstr[0], (ULONG) count, (PWCHAR) wstr, 0, (PVOID) pxBuffer);
793
794 HeapFree(GetProcessHeap(), 0, str);
795 HeapFree(GetProcessHeap(), 0, wstr);
796
797 return ret;
798 }
799
800 /*
801 * @implemented
802 */
803 BOOL
804 APIENTRY
805 GetCharABCWidthsA(
806 HDC hdc,
807 UINT iFirstChar,
808 UINT iLastChar,
809 LPABC lpabc
810 )
811 {
812 INT wlen, count = 0;
813 LPSTR str;
814 LPWSTR wstr;
815 BOOL ret = TRUE;
816
817 DPRINT("GetCharABCWidthsA\n");
818
819 str = FONT_GetCharsByRangeA(hdc, iFirstChar, iLastChar, &count);
820 if (!str)
821 return FALSE;
822
823 wstr = FONT_mbtowc(hdc, str, count+1, &wlen, NULL);
824 if (!wstr)
825 {
826 HeapFree(GetProcessHeap(), 0, str);
827 return FALSE;
828 }
829
830 ret = NtGdiGetCharABCWidthsW( hdc,
831 wstr[0],
832 wlen - 1,
833 (PWCHAR)wstr,
834 GCABCW_NOFLOAT,
835 (PVOID)lpabc);
836
837 HeapFree(GetProcessHeap(), 0, str);
838 HeapFree(GetProcessHeap(), 0, wstr);
839
840 return ret;
841 }
842
843 /*
844 * @implemented
845 */
846 BOOL
847 APIENTRY
848 GetCharABCWidthsFloatA(
849 HDC hdc,
850 UINT iFirstChar,
851 UINT iLastChar,
852 LPABCFLOAT lpABCF
853 )
854 {
855 INT wlen, count = 0;
856 LPSTR str;
857 LPWSTR wstr;
858 BOOL ret = TRUE;
859
860 DPRINT("GetCharABCWidthsFloatA\n");
861
862 str = FONT_GetCharsByRangeA(hdc, iFirstChar, iLastChar, &count);
863 if (!str)
864 return FALSE;
865
866 wstr = FONT_mbtowc( hdc, str, count+1, &wlen, NULL );
867 if (!wstr)
868 {
869 HeapFree( GetProcessHeap(), 0, str );
870 return FALSE;
871 }
872 ret = NtGdiGetCharABCWidthsW( hdc,wstr[0],(ULONG)count, (PWCHAR)wstr, 0, (PVOID)lpABCF);
873
874 HeapFree( GetProcessHeap(), 0, str );
875 HeapFree( GetProcessHeap(), 0, wstr );
876
877 return ret;
878 }
879
880 /*
881 * @implemented
882 */
883 BOOL
884 WINAPI
885 GetCharABCWidthsI(HDC hdc,
886 UINT giFirst,
887 UINT cgi,
888 LPWORD pgi,
889 LPABC lpabc)
890 {
891 DPRINT("GetCharABCWidthsI\n");
892 return NtGdiGetCharABCWidthsW( hdc,
893 giFirst,
894 (ULONG) cgi,
895 (PWCHAR) pgi,
896 GCABCW_NOFLOAT|GCABCW_INDICES,
897 (PVOID)lpabc);
898 }
899
900 /*
901 * @implemented
902 */
903 BOOL
904 WINAPI
905 GetCharWidthI(HDC hdc,
906 UINT giFirst,
907 UINT cgi,
908 LPWORD pgi,
909 LPINT lpBuffer
910 )
911 {
912 DPRINT("GetCharWidthsI\n");
913 if (!lpBuffer || (!pgi && (giFirst == MAXUSHORT))) // Cannot be at max.
914 {
915 SetLastError(ERROR_INVALID_PARAMETER);
916 return FALSE;
917 }
918 if (!cgi) return TRUE;
919 return NtGdiGetCharWidthW( hdc,
920 giFirst,
921 cgi,
922 (PWCHAR) pgi,
923 GCW_INDICES|GCW_NOFLOAT|GCW_WIN32,
924 (PVOID) lpBuffer );
925 }
926
927 /*
928 * @implemented
929 */
930 DWORD
931 WINAPI
932 GetFontLanguageInfo(
933 HDC hDc
934 )
935 {
936 DWORD Gcp = 0, Ret = 0;
937 if (gbLpk)
938 {
939 Ret = NtGdiGetTextCharsetInfo(hDc, NULL, 0);
940 if ((Ret == ARABIC_CHARSET) || (Ret == HEBREW_CHARSET))
941 Ret = (GCP_KASHIDA|GCP_DIACRITIC|GCP_LIGATE|GCP_GLYPHSHAPE|GCP_REORDER);
942 }
943 Gcp = GetDCDWord(hDc, GdiGetFontLanguageInfo, GCP_ERROR);
944 if ( Gcp == GCP_ERROR)
945 return Gcp;
946 else
947 Ret = Gcp | Ret;
948 return Ret;
949 }
950
951 /*
952 * @implemented
953 */
954 DWORD
955 WINAPI
956 GetGlyphIndicesA(
957 HDC hdc,
958 LPCSTR lpstr,
959 INT count,
960 LPWORD pgi,
961 DWORD flags
962 )
963 {
964 DWORD Ret;
965 WCHAR *lpstrW;
966 INT countW;
967
968 lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
969
970 if (lpstrW == NULL)
971 return GDI_ERROR;
972
973 Ret = NtGdiGetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
974 HeapFree(GetProcessHeap(), 0, lpstrW);
975 return Ret;
976 }
977
978 /*
979 * @implemented
980 */
981 DWORD
982 WINAPI
983 GetGlyphOutlineA(
984 HDC hdc,
985 UINT uChar,
986 UINT uFormat,
987 LPGLYPHMETRICS lpgm,
988 DWORD cbBuffer,
989 LPVOID lpvBuffer,
990 CONST MAT2 *lpmat2
991 )
992 {
993
994 LPWSTR p = NULL;
995 DWORD ret;
996 UINT c;
997 DPRINT("GetGlyphOutlineA uChar %x\n", uChar);
998 if (!lpgm || !lpmat2) return GDI_ERROR;
999 if(!(uFormat & GGO_GLYPH_INDEX))
1000 {
1001 int len;
1002 char mbchs[2];
1003 if(uChar > 0xff) /* but, 2 bytes character only */
1004 {
1005 len = 2;
1006 mbchs[0] = (uChar & 0xff00) >> 8;
1007 mbchs[1] = (uChar & 0xff);
1008 }
1009 else
1010 {
1011 len = 1;
1012 mbchs[0] = (uChar & 0xff);
1013 }
1014 p = FONT_mbtowc(hdc, mbchs, len, NULL, NULL);
1015 if(!p)
1016 return GDI_ERROR;
1017 c = p[0];
1018 }
1019 else
1020 c = uChar;
1021 ret = NtGdiGetGlyphOutline(hdc, c, uFormat, lpgm, cbBuffer, lpvBuffer, (CONST LPMAT2)lpmat2, TRUE);
1022 HeapFree(GetProcessHeap(), 0, p);
1023 return ret;
1024 }
1025
1026
1027 /*
1028 * @implemented
1029 */
1030 DWORD
1031 WINAPI
1032 GetGlyphOutlineW(
1033 HDC hdc,
1034 UINT uChar,
1035 UINT uFormat,
1036 LPGLYPHMETRICS lpgm,
1037 DWORD cbBuffer,
1038 LPVOID lpvBuffer,
1039 CONST MAT2 *lpmat2
1040 )
1041 {
1042 DPRINT("GetGlyphOutlineW uChar %x\n", uChar);
1043 if (!lpgm || !lpmat2) return GDI_ERROR;
1044 if (!lpvBuffer) cbBuffer = 0;
1045 return NtGdiGetGlyphOutline ( hdc, uChar, uFormat, lpgm, cbBuffer, lpvBuffer, (CONST LPMAT2)lpmat2, TRUE);
1046 }
1047
1048 /*
1049 * @unimplemented
1050 */
1051 DWORD
1052 WINAPI
1053 GetGlyphOutlineWow(
1054 DWORD a0,
1055 DWORD a1,
1056 DWORD a2,
1057 DWORD a3,
1058 DWORD a4,
1059 DWORD a5,
1060 DWORD a6
1061 )
1062 {
1063 UNIMPLEMENTED;
1064 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1065 return 0;
1066 }
1067
1068 /*
1069 * @implemented
1070 */
1071 UINT
1072 APIENTRY
1073 GetOutlineTextMetricsA(
1074 HDC hdc,
1075 UINT cbData,
1076 LPOUTLINETEXTMETRICA lpOTM
1077 )
1078 {
1079 char buf[512], *ptr;
1080 UINT ret, needed;
1081 OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1082 OUTLINETEXTMETRICA *output = lpOTM;
1083 INT left, len;
1084
1085 if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1086 return 0;
1087 if(ret > sizeof(buf))
1088 {
1089 lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1090 if (lpOTMW == NULL)
1091 {
1092 return 0;
1093 }
1094 }
1095 GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1096
1097 needed = sizeof(OUTLINETEXTMETRICA);
1098 if(lpOTMW->otmpFamilyName)
1099 needed += WideCharToMultiByte(CP_ACP, 0,
1100 (WCHAR*)((char*)lpOTMW + (int)lpOTMW->otmpFamilyName), -1,
1101 NULL, 0, NULL, NULL);
1102 if(lpOTMW->otmpFaceName)
1103 needed += WideCharToMultiByte(CP_ACP, 0,
1104 (WCHAR*)((char*)lpOTMW + (int)lpOTMW->otmpFaceName), -1,
1105 NULL, 0, NULL, NULL);
1106 if(lpOTMW->otmpStyleName)
1107 needed += WideCharToMultiByte(CP_ACP, 0,
1108 (WCHAR*)((char*)lpOTMW + (int)lpOTMW->otmpStyleName), -1,
1109 NULL, 0, NULL, NULL);
1110 if(lpOTMW->otmpFullName)
1111 needed += WideCharToMultiByte(CP_ACP, 0,
1112 (WCHAR*)((char*)lpOTMW + (int)lpOTMW->otmpFullName), -1,
1113 NULL, 0, NULL, NULL);
1114
1115 if(!lpOTM)
1116 {
1117 ret = needed;
1118 goto end;
1119 }
1120
1121 DPRINT("needed = %u\n", needed);
1122 if(needed > cbData)
1123 {
1124 /* Since the supplied buffer isn't big enough, we'll alloc one
1125 that is and memcpy the first cbData bytes into the lpOTM at
1126 the end. */
1127 output = HeapAlloc(GetProcessHeap(), 0, needed);
1128 if (output == NULL)
1129 {
1130 goto end;
1131 }
1132 }
1133
1134 ret = output->otmSize = min(needed, cbData);
1135 FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1136 output->otmFiller = 0;
1137 output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1138 output->otmfsSelection = lpOTMW->otmfsSelection;
1139 output->otmfsType = lpOTMW->otmfsType;
1140 output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1141 output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1142 output->otmItalicAngle = lpOTMW->otmItalicAngle;
1143 output->otmEMSquare = lpOTMW->otmEMSquare;
1144 output->otmAscent = lpOTMW->otmAscent;
1145 output->otmDescent = lpOTMW->otmDescent;
1146 output->otmLineGap = lpOTMW->otmLineGap;
1147 output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1148 output->otmsXHeight = lpOTMW->otmsXHeight;
1149 output->otmrcFontBox = lpOTMW->otmrcFontBox;
1150 output->otmMacAscent = lpOTMW->otmMacAscent;
1151 output->otmMacDescent = lpOTMW->otmMacDescent;
1152 output->otmMacLineGap = lpOTMW->otmMacLineGap;
1153 output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1154 output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1155 output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1156 output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1157 output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1158 output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1159 output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1160 output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1161 output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1162
1163
1164 ptr = (char*)(output + 1);
1165 left = needed - sizeof(*output);
1166
1167 if(lpOTMW->otmpFamilyName)
1168 {
1169 output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1170 len = WideCharToMultiByte(CP_ACP, 0,
1171 (WCHAR*)((char*)lpOTMW + (int)lpOTMW->otmpFamilyName), -1,
1172 ptr, left, NULL, NULL);
1173 left -= len;
1174 ptr += len;
1175 }
1176 else
1177 output->otmpFamilyName = 0;
1178
1179 if(lpOTMW->otmpFaceName)
1180 {
1181 output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1182 len = WideCharToMultiByte(CP_ACP, 0,
1183 (WCHAR*)((char*)lpOTMW + (int)lpOTMW->otmpFaceName), -1,
1184 ptr, left, NULL, NULL);
1185 left -= len;
1186 ptr += len;
1187 }
1188 else
1189 output->otmpFaceName = 0;
1190
1191 if(lpOTMW->otmpStyleName)
1192 {
1193 output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1194 len = WideCharToMultiByte(CP_ACP, 0,
1195 (WCHAR*)((char*)lpOTMW + (int)lpOTMW->otmpStyleName), -1,
1196 ptr, left, NULL, NULL);
1197 left -= len;
1198 ptr += len;
1199 }
1200 else
1201 output->otmpStyleName = 0;
1202
1203 if(lpOTMW->otmpFullName)
1204 {
1205 output->otmpFullName = (LPSTR)(ptr - (char*)output);
1206 len = WideCharToMultiByte(CP_ACP, 0,
1207 (WCHAR*)((char*)lpOTMW + (int)lpOTMW->otmpFullName), -1,
1208 ptr, left, NULL, NULL);
1209 left -= len;
1210 }
1211 else
1212 output->otmpFullName = 0;
1213
1214 assert(left == 0);
1215
1216 if(output != lpOTM)
1217 {
1218 memcpy(lpOTM, output, cbData);
1219 HeapFree(GetProcessHeap(), 0, output);
1220
1221 /* check if the string offsets really fit into the provided size */
1222 /* FIXME: should we check string length as well? */
1223 if ((UINT_PTR)lpOTM->otmpFamilyName >= lpOTM->otmSize)
1224 lpOTM->otmpFamilyName = 0; /* doesn't fit */
1225
1226 if ((UINT_PTR)lpOTM->otmpFaceName >= lpOTM->otmSize)
1227 lpOTM->otmpFaceName = 0; /* doesn't fit */
1228
1229 if ((UINT_PTR)lpOTM->otmpStyleName >= lpOTM->otmSize)
1230 lpOTM->otmpStyleName = 0; /* doesn't fit */
1231
1232 if ((UINT_PTR)lpOTM->otmpFullName >= lpOTM->otmSize)
1233 lpOTM->otmpFullName = 0; /* doesn't fit */
1234 }
1235
1236 end:
1237 if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1238 HeapFree(GetProcessHeap(), 0, lpOTMW);
1239
1240 return ret;
1241 }
1242
1243 /* Performs a device to world transformation on the specified size (which
1244 * is in integer format).
1245 */
1246 static inline INT INTERNAL_YDSTOWS(XFORM *xForm, INT height)
1247 {
1248 double floatHeight;
1249
1250 /* Perform operation with floating point */
1251 floatHeight = (double)height * xForm->eM22;
1252 /* Round to integers */
1253 return GDI_ROUND(floatHeight);
1254 }
1255
1256 /* scale width and height but don't mirror them */
1257 static inline INT width_to_LP( XFORM *xForm, INT width )
1258 {
1259 return GDI_ROUND( (double)width * fabs( xForm->eM11));
1260 }
1261
1262 static inline INT height_to_LP( XFORM *xForm, INT height )
1263 {
1264 return GDI_ROUND( (double)height * fabs( xForm->eM22 ));
1265 }
1266
1267 /*
1268 * @implemented
1269 */
1270 UINT
1271 APIENTRY
1272 GetOutlineTextMetricsW(
1273 HDC hdc,
1274 UINT cbData,
1275 LPOUTLINETEXTMETRICW lpOTM
1276 )
1277 {
1278 TMDIFF Tmd; // Should not be zero.
1279 UINT Size, AvailableSize = 0, StringSize;
1280 XFORM DevToWorld;
1281 OUTLINETEXTMETRICW* LocalOTM;
1282 WCHAR* Str;
1283 BYTE* Ptr;
1284
1285 /* Get the structure */
1286 Size = NtGdiGetOutlineTextMetricsInternalW(hdc, 0, NULL, &Tmd);
1287 if (!Size)
1288 return 0;
1289 if (!lpOTM || (cbData < sizeof(*lpOTM)))
1290 return Size;
1291
1292 LocalOTM = HeapAlloc(GetProcessHeap(), 0, Size);
1293 LocalOTM->otmSize = Size;
1294 Size = NtGdiGetOutlineTextMetricsInternalW(hdc, Size, LocalOTM, &Tmd);
1295 if (!Size)
1296 {
1297 HeapFree(GetProcessHeap(), 0, LocalOTM);
1298 return 0;
1299 }
1300
1301 if (!NtGdiGetTransform(hdc, GdiDeviceSpaceToWorldSpace, &DevToWorld))
1302 {
1303 DPRINT1("NtGdiGetTransform failed!\n");
1304 HeapFree(GetProcessHeap(), 0, LocalOTM);
1305 SetLastError(ERROR_INVALID_HANDLE);
1306 return 0;
1307 }
1308
1309 /* Fill in DC specific data */
1310 LocalOTM->otmTextMetrics.tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1311 LocalOTM->otmTextMetrics.tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1312 LocalOTM->otmTextMetrics.tmHeight = height_to_LP( &DevToWorld, LocalOTM->otmTextMetrics.tmHeight );
1313 LocalOTM->otmTextMetrics.tmAscent = height_to_LP( &DevToWorld, LocalOTM->otmTextMetrics.tmAscent );
1314 LocalOTM->otmTextMetrics.tmDescent = height_to_LP( &DevToWorld, LocalOTM->otmTextMetrics.tmDescent );
1315 LocalOTM->otmTextMetrics.tmInternalLeading = height_to_LP( &DevToWorld, LocalOTM->otmTextMetrics.tmInternalLeading );
1316 LocalOTM->otmTextMetrics.tmExternalLeading = height_to_LP( &DevToWorld, LocalOTM->otmTextMetrics.tmExternalLeading );
1317 LocalOTM->otmTextMetrics.tmAveCharWidth = width_to_LP( &DevToWorld, LocalOTM->otmTextMetrics.tmAveCharWidth );
1318 LocalOTM->otmTextMetrics.tmMaxCharWidth = width_to_LP( &DevToWorld, LocalOTM->otmTextMetrics.tmMaxCharWidth );
1319 LocalOTM->otmTextMetrics.tmOverhang = width_to_LP( &DevToWorld, LocalOTM->otmTextMetrics.tmOverhang );
1320 LocalOTM->otmAscent = height_to_LP( &DevToWorld, LocalOTM->otmAscent);
1321 LocalOTM->otmDescent = height_to_LP( &DevToWorld, LocalOTM->otmDescent);
1322 LocalOTM->otmLineGap = abs(INTERNAL_YDSTOWS(&DevToWorld,LocalOTM->otmLineGap));
1323 LocalOTM->otmsCapEmHeight = abs(INTERNAL_YDSTOWS(&DevToWorld,LocalOTM->otmsCapEmHeight));
1324 LocalOTM->otmsXHeight = abs(INTERNAL_YDSTOWS(&DevToWorld,LocalOTM->otmsXHeight));
1325 LocalOTM->otmrcFontBox.top = height_to_LP( &DevToWorld, LocalOTM->otmrcFontBox.top);
1326 LocalOTM->otmrcFontBox.bottom = height_to_LP( &DevToWorld, LocalOTM->otmrcFontBox.bottom);
1327 LocalOTM->otmrcFontBox.left = width_to_LP( &DevToWorld, LocalOTM->otmrcFontBox.left);
1328 LocalOTM->otmrcFontBox.right = width_to_LP( &DevToWorld, LocalOTM->otmrcFontBox.right);
1329 LocalOTM->otmMacAscent = height_to_LP( &DevToWorld, LocalOTM->otmMacAscent);
1330 LocalOTM->otmMacDescent = height_to_LP( &DevToWorld, LocalOTM->otmMacDescent);
1331 LocalOTM->otmMacLineGap = abs(INTERNAL_YDSTOWS(&DevToWorld,LocalOTM->otmMacLineGap));
1332 LocalOTM->otmptSubscriptSize.x = width_to_LP( &DevToWorld, LocalOTM->otmptSubscriptSize.x);
1333 LocalOTM->otmptSubscriptSize.y = height_to_LP( &DevToWorld, LocalOTM->otmptSubscriptSize.y);
1334 LocalOTM->otmptSubscriptOffset.x = width_to_LP( &DevToWorld, LocalOTM->otmptSubscriptOffset.x);
1335 LocalOTM->otmptSubscriptOffset.y = height_to_LP( &DevToWorld, LocalOTM->otmptSubscriptOffset.y);
1336 LocalOTM->otmptSuperscriptSize.x = width_to_LP( &DevToWorld, LocalOTM->otmptSuperscriptSize.x);
1337 LocalOTM->otmptSuperscriptSize.y = height_to_LP( &DevToWorld, LocalOTM->otmptSuperscriptSize.y);
1338 LocalOTM->otmptSuperscriptOffset.x = width_to_LP( &DevToWorld, LocalOTM->otmptSuperscriptOffset.x);
1339 LocalOTM->otmptSuperscriptOffset.y = height_to_LP( &DevToWorld, LocalOTM->otmptSuperscriptOffset.y);
1340 LocalOTM->otmsStrikeoutSize = abs(INTERNAL_YDSTOWS(&DevToWorld,LocalOTM->otmsStrikeoutSize));
1341 LocalOTM->otmsStrikeoutPosition = height_to_LP( &DevToWorld, LocalOTM->otmsStrikeoutPosition);
1342 LocalOTM->otmsUnderscoreSize = height_to_LP( &DevToWorld, LocalOTM->otmsUnderscoreSize);
1343 LocalOTM->otmsUnderscorePosition = height_to_LP( &DevToWorld, LocalOTM->otmsUnderscorePosition);
1344
1345 /* Copy what we can */
1346 CopyMemory(lpOTM, LocalOTM, min(Size, cbData));
1347
1348 lpOTM->otmpFamilyName = NULL;
1349 lpOTM->otmpFaceName = NULL;
1350 lpOTM->otmpStyleName = NULL;
1351 lpOTM->otmpFullName = NULL;
1352
1353 Size = sizeof(*lpOTM);
1354 AvailableSize = cbData - Size;
1355 Ptr = (BYTE*)lpOTM + sizeof(*lpOTM);
1356
1357 /* Fix string values up */
1358 if (LocalOTM->otmpFamilyName)
1359 {
1360 Str = (WCHAR*)((char*)LocalOTM + (ptrdiff_t)LocalOTM->otmpFamilyName);
1361 StringSize = (wcslen(Str) + 1) * sizeof(WCHAR);
1362 if (AvailableSize >= StringSize)
1363 {
1364 CopyMemory(Ptr, Str, StringSize);
1365 lpOTM->otmpFamilyName = (PSTR)(Ptr - (BYTE*)lpOTM);
1366 Ptr += StringSize;
1367 AvailableSize -= StringSize;
1368 Size += StringSize;
1369 }
1370 }
1371
1372 if (LocalOTM->otmpFaceName)
1373 {
1374 Str = (WCHAR*)((char*)LocalOTM + (ptrdiff_t)LocalOTM->otmpFaceName);
1375 StringSize = (wcslen(Str) + 1) * sizeof(WCHAR);
1376 if (AvailableSize >= StringSize)
1377 {
1378 CopyMemory(Ptr, Str, StringSize);
1379 lpOTM->otmpFaceName = (PSTR)(Ptr - (BYTE*)lpOTM);
1380 Ptr += StringSize;
1381 AvailableSize -= StringSize;
1382 Size += StringSize;
1383 }
1384 }
1385
1386 if (LocalOTM->otmpStyleName)
1387 {
1388 Str = (WCHAR*)((char*)LocalOTM + (ptrdiff_t)LocalOTM->otmpStyleName);
1389 StringSize = (wcslen(Str) + 1) * sizeof(WCHAR);
1390 if (AvailableSize >= StringSize)
1391 {
1392 CopyMemory(Ptr, Str, StringSize);
1393 lpOTM->otmpStyleName = (PSTR)(Ptr - (BYTE*)lpOTM);
1394 Ptr += StringSize;
1395 AvailableSize -= StringSize;
1396 Size += StringSize;
1397 }
1398 }
1399
1400 if (LocalOTM->otmpFullName)
1401 {
1402 Str = (WCHAR*)((char*)LocalOTM + (ptrdiff_t)LocalOTM->otmpFullName);
1403 StringSize = (wcslen(Str) + 1) * sizeof(WCHAR);
1404 if (AvailableSize >= StringSize)
1405 {
1406 CopyMemory(Ptr, Str, StringSize);
1407 lpOTM->otmpFullName = (PSTR)(Ptr - (BYTE*)lpOTM);
1408 Ptr += StringSize;
1409 AvailableSize -= StringSize;
1410 Size += StringSize;
1411 }
1412 }
1413
1414 lpOTM->otmSize = Size;
1415
1416 HeapFree(GetProcessHeap(), 0, LocalOTM);
1417
1418 return Size;
1419 }
1420
1421 /*
1422 * @implemented
1423 */
1424 DWORD
1425 WINAPI
1426 GetKerningPairsW(HDC hdc,
1427 ULONG cPairs,
1428 LPKERNINGPAIR pkpDst)
1429 {
1430 if ((cPairs != 0) || (pkpDst == 0))
1431 {
1432 return NtGdiGetKerningPairs(hdc,cPairs,pkpDst);
1433 }
1434 else
1435 {
1436 SetLastError(ERROR_INVALID_PARAMETER);
1437 return 0;
1438 }
1439 }
1440
1441 /*
1442 * @implemented
1443 */
1444 DWORD
1445 WINAPI
1446 GetKerningPairsA( HDC hDC,
1447 DWORD cPairs,
1448 LPKERNINGPAIR kern_pairA )
1449 {
1450 INT charset;
1451 CHARSETINFO csi;
1452 CPINFO cpi;
1453 DWORD i, total_kern_pairs, kern_pairs_copied = 0;
1454 KERNINGPAIR *kern_pairW;
1455
1456 if (!cPairs && kern_pairA)
1457 {
1458 SetLastError(ERROR_INVALID_PARAMETER);
1459 return 0;
1460 }
1461
1462 charset = GetTextCharset(hDC);
1463 if (!TranslateCharsetInfo(ULongToPtr(charset), &csi, TCI_SRCCHARSET))
1464 {
1465 DPRINT1("Can't find codepage for charset %d\n", charset);
1466 return 0;
1467 }
1468 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
1469 * to fail on an invalid character for CP_SYMBOL.
1470 */
1471 cpi.DefaultChar[0] = 0;
1472 if (csi.ciACP != CP_SYMBOL && !GetCPInfo(csi.ciACP, &cpi))
1473 {
1474 DPRINT1("Can't find codepage %u info\n", csi.ciACP);
1475 return 0;
1476 }
1477 DPRINT("charset %d => codepage %u\n", charset, csi.ciACP);
1478
1479 total_kern_pairs = NtGdiGetKerningPairs(hDC, 0, NULL);
1480 if (!total_kern_pairs) return 0;
1481
1482 if (!cPairs && !kern_pairA) return total_kern_pairs;
1483
1484 kern_pairW = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW));
1485 if (kern_pairW == NULL)
1486 {
1487 return 0;
1488 }
1489 GetKerningPairsW(hDC, total_kern_pairs, kern_pairW);
1490
1491 for (i = 0; i < total_kern_pairs; i++)
1492 {
1493 char first, second;
1494
1495 if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL))
1496 continue;
1497
1498 if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL))
1499 continue;
1500
1501 if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0])
1502 continue;
1503
1504 if (kern_pairA)
1505 {
1506 if (kern_pairs_copied >= cPairs) break;
1507
1508 kern_pairA->wFirst = (BYTE)first;
1509 kern_pairA->wSecond = (BYTE)second;
1510 kern_pairA->iKernAmount = kern_pairW[i].iKernAmount;
1511 kern_pairA++;
1512 }
1513 kern_pairs_copied++;
1514 }
1515
1516 HeapFree(GetProcessHeap(), 0, kern_pairW);
1517
1518 return kern_pairs_copied;
1519 }
1520
1521
1522
1523 /*
1524 * @implemented
1525 */
1526 HFONT
1527 WINAPI
1528 CreateFontIndirectExA(const ENUMLOGFONTEXDVA *elfexd)
1529 {
1530 if (elfexd)
1531 {
1532 ENUMLOGFONTEXDVW Logfont;
1533
1534 EnumLogFontExW2A( (LPENUMLOGFONTEXA) elfexd,
1535 &Logfont.elfEnumLogfontEx );
1536
1537 RtlCopyMemory( &Logfont.elfDesignVector,
1538 (PVOID) &elfexd->elfDesignVector,
1539 sizeof(DESIGNVECTOR));
1540
1541 return NtGdiHfontCreate( &Logfont, 0, 0, 0, NULL);
1542 }
1543 else return NULL;
1544 }
1545
1546
1547 /*
1548 * @implemented
1549 */
1550 HFONT
1551 WINAPI
1552 CreateFontIndirectExW(const ENUMLOGFONTEXDVW *elfexd)
1553 {
1554 /* Msdn: Note, this function ignores the elfDesignVector member in
1555 ENUMLOGFONTEXDV.
1556 */
1557 if ( elfexd )
1558 {
1559 return NtGdiHfontCreate((PENUMLOGFONTEXDVW) elfexd, 0, 0, 0, NULL );
1560 }
1561 else return NULL;
1562 }
1563
1564
1565 /*
1566 * @implemented
1567 */
1568 HFONT
1569 WINAPI
1570 CreateFontIndirectA(
1571 CONST LOGFONTA *lplf
1572 )
1573 {
1574 if (lplf)
1575 {
1576 LOGFONTW tlf;
1577
1578 LogFontA2W(&tlf, lplf);
1579 return CreateFontIndirectW(&tlf);
1580 }
1581 else return NULL;
1582 }
1583
1584
1585 /*
1586 * @implemented
1587 */
1588 HFONT
1589 WINAPI
1590 CreateFontIndirectW(
1591 CONST LOGFONTW *lplf
1592 )
1593 {
1594 if (lplf)
1595 {
1596 ENUMLOGFONTEXDVW Logfont;
1597
1598 RtlCopyMemory( &Logfont.elfEnumLogfontEx.elfLogFont, lplf, sizeof(LOGFONTW));
1599 // Need something other than just cleaning memory here.
1600 // Guess? Use caller data to determine the rest.
1601 RtlZeroMemory( &Logfont.elfEnumLogfontEx.elfFullName,
1602 sizeof(Logfont.elfEnumLogfontEx.elfFullName));
1603 RtlZeroMemory( &Logfont.elfEnumLogfontEx.elfStyle,
1604 sizeof(Logfont.elfEnumLogfontEx.elfStyle));
1605 RtlZeroMemory( &Logfont.elfEnumLogfontEx.elfScript,
1606 sizeof(Logfont.elfEnumLogfontEx.elfScript));
1607
1608 Logfont.elfDesignVector.dvNumAxes = 0; // No more than MM_MAX_NUMAXES
1609
1610 RtlZeroMemory( &Logfont.elfDesignVector, sizeof(DESIGNVECTOR));
1611
1612 return CreateFontIndirectExW(&Logfont);
1613 }
1614 else return NULL;
1615 }
1616
1617
1618 /*
1619 * @implemented
1620 */
1621 HFONT
1622 WINAPI
1623 CreateFontA(
1624 int nHeight,
1625 int nWidth,
1626 int nEscapement,
1627 int nOrientation,
1628 int fnWeight,
1629 DWORD fdwItalic,
1630 DWORD fdwUnderline,
1631 DWORD fdwStrikeOut,
1632 DWORD fdwCharSet,
1633 DWORD fdwOutputPrecision,
1634 DWORD fdwClipPrecision,
1635 DWORD fdwQuality,
1636 DWORD fdwPitchAndFamily,
1637 LPCSTR lpszFace
1638 )
1639 {
1640 ANSI_STRING StringA;
1641 UNICODE_STRING StringU;
1642 HFONT ret;
1643
1644 RtlInitAnsiString(&StringA, (LPSTR)lpszFace);
1645 RtlAnsiStringToUnicodeString(&StringU, &StringA, TRUE);
1646
1647 ret = CreateFontW(nHeight,
1648 nWidth,
1649 nEscapement,
1650 nOrientation,
1651 fnWeight,
1652 fdwItalic,
1653 fdwUnderline,
1654 fdwStrikeOut,
1655 fdwCharSet,
1656 fdwOutputPrecision,
1657 fdwClipPrecision,
1658 fdwQuality,
1659 fdwPitchAndFamily,
1660 StringU.Buffer);
1661
1662 RtlFreeUnicodeString(&StringU);
1663
1664 return ret;
1665 }
1666
1667
1668 /*
1669 * @implemented
1670 */
1671 HFONT
1672 WINAPI
1673 CreateFontW(
1674 int nHeight,
1675 int nWidth,
1676 int nEscapement,
1677 int nOrientation,
1678 int nWeight,
1679 DWORD fnItalic,
1680 DWORD fdwUnderline,
1681 DWORD fdwStrikeOut,
1682 DWORD fdwCharSet,
1683 DWORD fdwOutputPrecision,
1684 DWORD fdwClipPrecision,
1685 DWORD fdwQuality,
1686 DWORD fdwPitchAndFamily,
1687 LPCWSTR lpszFace
1688 )
1689 {
1690 LOGFONTW logfont;
1691
1692 logfont.lfHeight = nHeight;
1693 logfont.lfWidth = nWidth;
1694 logfont.lfEscapement = nEscapement;
1695 logfont.lfOrientation = nOrientation;
1696 logfont.lfWeight = nWeight;
1697 logfont.lfItalic = (BYTE)fnItalic;
1698 logfont.lfUnderline = (BYTE)fdwUnderline;
1699 logfont.lfStrikeOut = (BYTE)fdwStrikeOut;
1700 logfont.lfCharSet = (BYTE)fdwCharSet;
1701 logfont.lfOutPrecision = (BYTE)fdwOutputPrecision;
1702 logfont.lfClipPrecision = (BYTE)fdwClipPrecision;
1703 logfont.lfQuality = (BYTE)fdwQuality;
1704 logfont.lfPitchAndFamily = (BYTE)fdwPitchAndFamily;
1705
1706 if (NULL != lpszFace)
1707 {
1708 int Size = sizeof(logfont.lfFaceName) / sizeof(WCHAR);
1709 wcsncpy((wchar_t *)logfont.lfFaceName, lpszFace, Size - 1);
1710 /* Be 101% sure to have '\0' at end of string */
1711 logfont.lfFaceName[Size - 1] = '\0';
1712 }
1713 else
1714 {
1715 logfont.lfFaceName[0] = L'\0';
1716 }
1717
1718 return CreateFontIndirectW(&logfont);
1719 }
1720
1721
1722 /*
1723 * @unimplemented
1724 */
1725 BOOL
1726 WINAPI
1727 CreateScalableFontResourceA(
1728 DWORD fdwHidden,
1729 LPCSTR lpszFontRes,
1730 LPCSTR lpszFontFile,
1731 LPCSTR lpszCurrentPath
1732 )
1733 {
1734 return FALSE;
1735 }
1736
1737
1738 /*
1739 * @implemented
1740 */
1741 int
1742 WINAPI
1743 AddFontResourceExW ( LPCWSTR lpszFilename, DWORD fl, PVOID pvReserved )
1744 {
1745 if (fl & ~(FR_PRIVATE | FR_NOT_ENUM))
1746 {
1747 SetLastError( ERROR_INVALID_PARAMETER );
1748 return 0;
1749 }
1750
1751 return GdiAddFontResourceW(lpszFilename, fl,0);
1752 }
1753
1754
1755 /*
1756 * @implemented
1757 */
1758 int
1759 WINAPI
1760 AddFontResourceExA ( LPCSTR lpszFilename, DWORD fl, PVOID pvReserved )
1761 {
1762 NTSTATUS Status;
1763 PWSTR FilenameW;
1764 int rc;
1765
1766 if (fl & ~(FR_PRIVATE | FR_NOT_ENUM))
1767 {
1768 SetLastError( ERROR_INVALID_PARAMETER );
1769 return 0;
1770 }
1771
1772 Status = HEAP_strdupA2W ( &FilenameW, lpszFilename );
1773 if ( !NT_SUCCESS (Status) )
1774 {
1775 SetLastError (RtlNtStatusToDosError(Status));
1776 return 0;
1777 }
1778
1779 rc = GdiAddFontResourceW ( FilenameW, fl, 0 );
1780 HEAP_free ( FilenameW );
1781 return rc;
1782 }
1783
1784
1785 /*
1786 * @implemented
1787 */
1788 int
1789 WINAPI
1790 AddFontResourceA ( LPCSTR lpszFilename )
1791 {
1792 NTSTATUS Status;
1793 PWSTR FilenameW;
1794 int rc = 0;
1795
1796 Status = HEAP_strdupA2W ( &FilenameW, lpszFilename );
1797 if ( !NT_SUCCESS (Status) )
1798 {
1799 SetLastError (RtlNtStatusToDosError(Status));
1800 }
1801 else
1802 {
1803 rc = GdiAddFontResourceW ( FilenameW, 0, 0);
1804
1805 HEAP_free ( FilenameW );
1806 }
1807 return rc;
1808 }
1809
1810
1811 /*
1812 * @implemented
1813 */
1814 int
1815 WINAPI
1816 AddFontResourceW ( LPCWSTR lpszFilename )
1817 {
1818 return GdiAddFontResourceW ( lpszFilename, 0, 0 );
1819 }
1820
1821
1822 /*
1823 * @implemented
1824 */
1825 BOOL
1826 WINAPI
1827 RemoveFontResourceW(LPCWSTR lpFileName)
1828 {
1829 return RemoveFontResourceExW(lpFileName,0,0);
1830 }
1831
1832
1833 /*
1834 * @implemented
1835 */
1836 BOOL
1837 WINAPI
1838 RemoveFontResourceA(LPCSTR lpFileName)
1839 {
1840 return RemoveFontResourceExA(lpFileName,0,0);
1841 }
1842
1843 /*
1844 * @unimplemented
1845 */
1846 BOOL
1847 WINAPI
1848 RemoveFontResourceExA(LPCSTR lpFileName,
1849 DWORD fl,
1850 PVOID pdv
1851 )
1852 {
1853 NTSTATUS Status;
1854 LPWSTR lpFileNameW;
1855
1856 /* FIXME the flags */
1857 /* FIXME the pdv */
1858 /* FIXME NtGdiRemoveFontResource handle flags and pdv */
1859
1860 Status = HEAP_strdupA2W ( &lpFileNameW, lpFileName );
1861 if (!NT_SUCCESS (Status))
1862 SetLastError (RtlNtStatusToDosError(Status));
1863 else
1864 {
1865
1866 HEAP_free ( lpFileNameW );
1867 }
1868
1869 return 0;
1870 }
1871
1872 /*
1873 * @unimplemented
1874 */
1875 BOOL
1876 WINAPI
1877 RemoveFontResourceExW(LPCWSTR lpFileName,
1878 DWORD fl,
1879 PVOID pdv)
1880 {
1881 /* FIXME the flags */
1882 /* FIXME the pdv */
1883 /* FIXME NtGdiRemoveFontResource handle flags and pdv */
1884 DPRINT("RemoveFontResourceExW\n");
1885 return 0;
1886 }
1887
1888
1889 /***********************************************************************
1890 * GdiGetCharDimensions
1891 *
1892 * Gets the average width of the characters in the English alphabet.
1893 *
1894 * PARAMS
1895 * hdc [I] Handle to the device context to measure on.
1896 * lptm [O] Pointer to memory to store the text metrics into.
1897 * height [O] On exit, the maximum height of characters in the English alphabet.
1898 *
1899 * RETURNS
1900 * The average width of characters in the English alphabet.
1901 *
1902 * NOTES
1903 * This function is used by the dialog manager to get the size of a dialog
1904 * unit. It should also be used by other pieces of code that need to know
1905 * the size of a dialog unit in logical units without having access to the
1906 * window handle of the dialog.
1907 * Windows caches the font metrics from this function, but we don't and
1908 * there doesn't appear to be an immediate advantage to do so.
1909 *
1910 * SEE ALSO
1911 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
1912 *
1913 * Despite most of MSDN insisting that the horizontal base unit is
1914 * tmAveCharWidth it isn't. Knowledge base article Q145994
1915 * "HOWTO: Calculate Dialog Units When Not Using the System Font",
1916 * says that we should take the average of the 52 English upper and lower
1917 * case characters.
1918 */
1919 /*
1920 * @implemented
1921 */
1922 LONG
1923 WINAPI
1924 GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
1925 {
1926 SIZE sz;
1927 TEXTMETRICW tm;
1928 static const WCHAR alphabet[] =
1929 {
1930 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
1931 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
1932 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0
1933 };
1934
1935 if(!GetTextMetricsW(hdc, &tm)) return 0;
1936
1937 if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
1938
1939 if (lptm) *lptm = tm;
1940 if (height) *height = tm.tmHeight;
1941
1942 return (sz.cx / 26 + 1) / 2;
1943 }
1944
1945 /*************************************************************************
1946 * TranslateCharsetInfo [GDI32.@]
1947 *
1948 * Fills a CHARSETINFO structure for a character set, code page, or
1949 * font. This allows making the correspondance between different labelings
1950 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
1951 * of the same encoding.
1952 *
1953 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
1954 * only one codepage should be set in *lpSrc.
1955 *
1956 * RETURNS
1957 * TRUE on success, FALSE on failure.
1958 *
1959 */
1960 /*
1961 * @implemented
1962 */
1963 BOOL
1964 WINAPI
1965 TranslateCharsetInfo(
1966 LPDWORD lpSrc, /* [in]
1967 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
1968 if flags == TCI_SRCCHARSET: a character set value
1969 if flags == TCI_SRCCODEPAGE: a code page value
1970 */
1971 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
1972 DWORD flags /* [in] determines interpretation of lpSrc */)
1973 {
1974 int index = 0;
1975 switch (flags)
1976 {
1977 case TCI_SRCFONTSIG:
1978 while (index < MAXTCIINDEX && !(*lpSrc>>index & 0x0001)) index++;
1979 break;
1980 case TCI_SRCCODEPAGE:
1981 while (index < MAXTCIINDEX && PtrToUlong(lpSrc) != FONT_tci[index].ciACP) index++;
1982 break;
1983 case TCI_SRCCHARSET:
1984 while (index < MAXTCIINDEX && PtrToUlong(lpSrc) != FONT_tci[index].ciCharset) index++;
1985 break;
1986 case TCI_SRCLOCALE:
1987 {
1988 LCID lCid = (LCID)PtrToUlong(lpSrc);
1989 LOCALESIGNATURE LocSig;
1990 INT Ret = GetLocaleInfoW(lCid, LOCALE_FONTSIGNATURE, (LPWSTR)&LocSig, 0);
1991 if ( GetLocaleInfoW(lCid, LOCALE_FONTSIGNATURE, (LPWSTR)&LocSig, Ret))
1992 {
1993 while (index < MAXTCIINDEX && !(LocSig.lsCsbDefault[0]>>index & 0x0001)) index++;
1994 break;
1995 }
1996 }
1997 default:
1998 GdiSetLastError(ERROR_INVALID_PARAMETER);
1999 return FALSE;
2000 }
2001 if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
2002 DPRINT("Index %d Charset %u CodePage %u FontSig %lu\n",
2003 index,FONT_tci[index].ciCharset,FONT_tci[index].ciACP,FONT_tci[index].fs.fsCsb[0]);
2004 memcpy(lpCs, &FONT_tci[index], sizeof(CHARSETINFO));
2005 return TRUE;
2006 }
2007
2008
2009 /*
2010 * @implemented
2011 */
2012 DWORD
2013 WINAPI
2014 SetMapperFlags(
2015 HDC hDC,
2016 DWORD flags
2017 )
2018 {
2019 DWORD Ret = GDI_ERROR;
2020 PDC_ATTR Dc_Attr;
2021 #if 0
2022 if (GDI_HANDLE_GET_TYPE(hDC) != GDI_OBJECT_TYPE_DC)
2023 {
2024 if (GDI_HANDLE_GET_TYPE(hDC) == GDI_OBJECT_TYPE_METADC)
2025 return MFDRV_SetMapperFlags( hDC, flags);
2026 else
2027 {
2028 PLDC pLDC = Dc_Attr->pvLDC;
2029 if ( !pLDC )
2030 {
2031 SetLastError(ERROR_INVALID_HANDLE);
2032 return GDI_ERROR;
2033 }
2034 if (pLDC->iType == LDC_EMFLDC)
2035 {
2036 return EMFDRV_SetMapperFlags( hDC, flags);
2037 }
2038 }
2039 }
2040 #endif
2041 if (!GdiGetHandleUserData((HGDIOBJ) hDC, GDI_OBJECT_TYPE_DC, (PVOID) &Dc_Attr)) return GDI_ERROR;
2042
2043 if (NtCurrentTeb()->GdiTebBatch.HDC == hDC)
2044 {
2045 if (Dc_Attr->ulDirty_ & DC_FONTTEXT_DIRTY)
2046 {
2047 NtGdiFlush();
2048 Dc_Attr->ulDirty_ &= ~(DC_MODE_DIRTY|DC_FONTTEXT_DIRTY);
2049 }
2050 }
2051
2052 if ( flags & ~1 )
2053 SetLastError(ERROR_INVALID_PARAMETER);
2054 else
2055 {
2056 Ret = Dc_Attr->flFontMapper;
2057 Dc_Attr->flFontMapper = flags;
2058 }
2059 return Ret;
2060 }
2061
2062
2063 /*
2064 * @unimplemented
2065 */
2066 int
2067 WINAPI
2068 EnumFontsW(
2069 HDC hDC,
2070 LPCWSTR lpFaceName,
2071 FONTENUMPROCW FontFunc,
2072 LPARAM lParam
2073 )
2074 {
2075 #if 0
2076 return NtGdiEnumFonts ( hDC, lpFaceName, FontFunc, lParam );
2077 #else
2078 return EnumFontFamiliesW( hDC, lpFaceName, FontFunc, lParam );
2079 #endif
2080 }
2081
2082 /*
2083 * @unimplemented
2084 */
2085 int
2086 WINAPI
2087 EnumFontsA (
2088 HDC hDC,
2089 LPCSTR lpFaceName,
2090 FONTENUMPROCA FontFunc,
2091 LPARAM lParam
2092 )
2093 {
2094 #if 0
2095 NTSTATUS Status;
2096 LPWSTR lpFaceNameW;
2097 int rc = 0;
2098
2099 Status = HEAP_strdupA2W ( &lpFaceNameW, lpFaceName );
2100 if (!NT_SUCCESS (Status))
2101 SetLastError (RtlNtStatusToDosError(Status));
2102 else
2103 {
2104 rc = NtGdiEnumFonts ( hDC, lpFaceNameW, FontFunc, lParam );
2105
2106 HEAP_free ( lpFaceNameW );
2107 }
2108 return rc;
2109 #else
2110 return EnumFontFamiliesA( hDC, lpFaceName, FontFunc, lParam );
2111 #endif
2112 }
2113
2114 #define EfdFontFamilies 3
2115
2116 INT
2117 WINAPI
2118 NewEnumFontFamiliesExW(
2119 HDC hDC,
2120 LPLOGFONTW lpLogfont,
2121 FONTENUMPROCW lpEnumFontFamExProcW,
2122 LPARAM lParam,
2123 DWORD dwFlags)
2124 {
2125 ULONG_PTR idEnum, cbDataSize, cbRetSize;
2126 PENUMFONTDATAW pEfdw;
2127 PBYTE pBuffer;
2128 PBYTE pMax;
2129 INT ret = 1;
2130
2131 /* Open enumeration handle and find out how much memory we need */
2132 idEnum = NtGdiEnumFontOpen(hDC,
2133 EfdFontFamilies,
2134 0,
2135 LF_FACESIZE,
2136 (lpLogfont && lpLogfont->lfFaceName[0])? lpLogfont->lfFaceName : NULL,
2137 lpLogfont? lpLogfont->lfCharSet : DEFAULT_CHARSET,
2138 &cbDataSize);
2139 if (idEnum == 0)
2140 {
2141 return 0;
2142 }
2143 if (cbDataSize == 0)
2144 {
2145 NtGdiEnumFontClose(idEnum);
2146 return 0;
2147 }
2148
2149 /* Allocate memory */
2150 pBuffer = HeapAlloc(GetProcessHeap(), 0, cbDataSize);
2151 if (pBuffer == NULL)
2152 {
2153 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2154 NtGdiEnumFontClose(idEnum);
2155 return 0;
2156 }
2157
2158 /* Do the enumeration */
2159 if (!NtGdiEnumFontChunk(hDC, idEnum, cbDataSize, &cbRetSize, (PVOID)pBuffer))
2160 {
2161 HeapFree(GetProcessHeap(), 0, pBuffer);
2162 NtGdiEnumFontClose(idEnum);
2163 return 0;
2164 }
2165
2166 /* Get start and end address */
2167 pEfdw = (PENUMFONTDATAW)pBuffer;
2168 pMax = pBuffer + cbDataSize;
2169
2170 /* Iterate through the structures */
2171 while ((PBYTE)pEfdw < pMax && ret)
2172 {
2173 PNTMW_INTERNAL pNtmwi = (PNTMW_INTERNAL)((ULONG_PTR)pEfdw + pEfdw->ulNtmwiOffset);
2174
2175 ret = lpEnumFontFamExProcW((VOID*)&pEfdw->elfexdv.elfEnumLogfontEx,
2176 (VOID*)&pNtmwi->ntmw,
2177 pEfdw->dwFontType,
2178 lParam);
2179
2180 pEfdw = (PENUMFONTDATAW)((ULONG_PTR)pEfdw + pEfdw->cbSize);
2181 }
2182
2183 /* Release the memory and close handle */
2184 HeapFree(GetProcessHeap(), 0, pBuffer);
2185 NtGdiEnumFontClose(idEnum);
2186
2187 return ret;
2188 }
2189
2190 /*
2191 * @implemented
2192 */
2193 int
2194 WINAPI
2195 GdiAddFontResourceW(
2196 LPCWSTR lpszFilename,
2197 FLONG fl,
2198 DESIGNVECTOR *pdv)
2199 {
2200 INT Ret;
2201 WCHAR lpszBuffer[MAX_PATH];
2202 WCHAR lpszAbsPath[MAX_PATH];
2203 UNICODE_STRING NtAbsPath;
2204
2205 /* FIXME: We don't support multiple files passed in lpszFilename
2206 * as L"abcxxxxx.pfm|abcxxxxx.pfb"
2207 */
2208
2209 /* Does the file exist in CurrentDirectory or in the Absolute Path passed? */
2210 GetCurrentDirectoryW(MAX_PATH, lpszBuffer);
2211
2212 if (!SearchPathW(lpszBuffer, lpszFilename, NULL, MAX_PATH, lpszAbsPath, NULL))
2213 {
2214 /* Nope. Then let's check Fonts folder */
2215 GetWindowsDirectoryW(lpszBuffer, MAX_PATH);
2216 StringCbCatW(lpszBuffer, sizeof(lpszBuffer), L"\\Fonts");
2217
2218 if (!SearchPathW(lpszBuffer, lpszFilename, NULL, MAX_PATH, lpszAbsPath, NULL))
2219 {
2220 DPRINT1("Font not found. The Buffer is: %ls, the FileName is: %S\n", lpszBuffer, lpszFilename);
2221 return 0;
2222 }
2223 }
2224
2225 /* We found the font file so: */
2226 if (!RtlDosPathNameToNtPathName_U(lpszAbsPath, &NtAbsPath, NULL, NULL))
2227 {
2228 DPRINT1("Can't convert Path! Path: %ls\n", lpszAbsPath);
2229 return 0;
2230 }
2231
2232 /* The Nt call expects a null-terminator included in cwc param. */
2233 ASSERT(NtAbsPath.Buffer[NtAbsPath.Length / sizeof(WCHAR)] == UNICODE_NULL);
2234 Ret = NtGdiAddFontResourceW(NtAbsPath.Buffer, NtAbsPath.Length / sizeof(WCHAR) + 1, 1, fl, 0, pdv);
2235
2236 RtlFreeUnicodeString(&NtAbsPath);
2237
2238 return Ret;
2239 }
2240
2241 /*
2242 * @implemented
2243 */
2244 HANDLE
2245 WINAPI
2246 AddFontMemResourceEx(
2247 PVOID pbFont,
2248 DWORD cbFont,
2249 PVOID pdv,
2250 DWORD *pcFonts
2251 )
2252 {
2253 if ( pbFont && cbFont && pcFonts)
2254 {
2255 return NtGdiAddFontMemResourceEx(pbFont, cbFont, NULL, 0, pcFonts);
2256 }
2257 SetLastError(ERROR_INVALID_PARAMETER);
2258 return NULL;
2259 }
2260
2261 /*
2262 * @implemented
2263 */
2264 BOOL
2265 WINAPI
2266 RemoveFontMemResourceEx(HANDLE fh)
2267 {
2268 if (fh)
2269 {
2270 return NtGdiRemoveFontMemResourceEx(fh);
2271 }
2272 SetLastError(ERROR_INVALID_PARAMETER);
2273 return FALSE;
2274 }
2275
2276
2277 /*
2278 * @unimplemented
2279 */
2280 int
2281 WINAPI
2282 AddFontResourceTracking(
2283 LPCSTR lpString,
2284 int unknown
2285 )
2286 {
2287 UNIMPLEMENTED;
2288 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2289 return 0;
2290 }
2291
2292 /*
2293 * @unimplemented
2294 */
2295 int
2296 WINAPI
2297 RemoveFontResourceTracking(LPCSTR lpString,int unknown)
2298 {
2299 UNIMPLEMENTED;
2300 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2301 return 0;
2302 }
2303
2304 BOOL
2305 WINAPI
2306 CreateScalableFontResourceW(
2307 DWORD fdwHidden,
2308 LPCWSTR lpszFontRes,
2309 LPCWSTR lpszFontFile,
2310 LPCWSTR lpszCurrentPath
2311 )
2312 {
2313 HANDLE f;
2314
2315 UNIMPLEMENTED;
2316
2317 /* fHidden=1 - only visible for the calling app, read-only, not
2318 * enumerated with EnumFonts/EnumFontFamilies
2319 * lpszCurrentPath can be NULL
2320 */
2321
2322 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2323 if ((f = CreateFileW(lpszFontRes, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE)
2324 {
2325 CloseHandle(f);
2326 SetLastError(ERROR_FILE_EXISTS);
2327 return FALSE;
2328 }
2329 return FALSE; /* create failed */
2330 }
2331
2332 /*
2333 * @unimplemented
2334 */
2335 BOOL
2336 WINAPI
2337 bInitSystemAndFontsDirectoriesW(LPWSTR *SystemDir,LPWSTR *FontsDir)
2338 {
2339 UNIMPLEMENTED;
2340 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2341 return 0;
2342 }
2343
2344 /*
2345 * @unimplemented
2346 */
2347 BOOL
2348 WINAPI
2349 EudcLoadLinkW(LPCWSTR pBaseFaceName,LPCWSTR pEudcFontPath,INT iPriority,INT iFontLinkType)
2350 {
2351 UNIMPLEMENTED;
2352 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2353 return 0;
2354 }
2355
2356 /*
2357 * @unimplemented
2358 */
2359 BOOL
2360 WINAPI
2361 EudcUnloadLinkW(LPCWSTR pBaseFaceName,LPCWSTR pEudcFontPath)
2362 {
2363 UNIMPLEMENTED;
2364 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2365 return 0;
2366 }
2367
2368 /*
2369 * @implemented
2370 */
2371 ULONG
2372 WINAPI
2373 GetEUDCTimeStamp(VOID)
2374 {
2375 return NtGdiGetEudcTimeStampEx(NULL,0,TRUE);
2376 }
2377
2378 /*
2379 * @implemented
2380 */
2381 DWORD
2382 WINAPI
2383 GetEUDCTimeStampExW(LPWSTR lpBaseFaceName)
2384 {
2385 DWORD retValue = 0;
2386
2387 if (!lpBaseFaceName)
2388 {
2389 retValue = NtGdiGetEudcTimeStampEx(NULL,0,FALSE);
2390 }
2391 else
2392 {
2393 retValue = NtGdiGetEudcTimeStampEx(lpBaseFaceName, wcslen(lpBaseFaceName), FALSE);
2394 }
2395
2396 return retValue;
2397 }
2398
2399 /*
2400 * @implemented
2401 */
2402 ULONG
2403 WINAPI
2404 GetFontAssocStatus(HDC hdc)
2405 {
2406 ULONG retValue = 0;
2407
2408 if (hdc)
2409 {
2410 retValue = NtGdiQueryFontAssocInfo(hdc);
2411 }
2412
2413 return retValue;
2414 }
2415
2416 /*
2417 * @unimplemented
2418 */
2419 DWORD
2420 WINAPI
2421 QueryFontAssocStatus(VOID)
2422 {
2423 UNIMPLEMENTED;
2424 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2425 return 0;
2426 }
2427
2428 /*
2429 * @unimplemented
2430 */
2431 VOID
2432 WINAPI
2433 UnloadNetworkFonts(DWORD unknown)
2434 {
2435 UNIMPLEMENTED;
2436 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2437 }
2438
2439 /*
2440 * @implemented
2441 *
2442 */
2443 DWORD
2444 WINAPI
2445 GetFontData(HDC hdc,
2446 DWORD dwTable,
2447 DWORD dwOffset,
2448 LPVOID lpvBuffer,
2449 DWORD cbData)
2450 {
2451 if (!lpvBuffer)
2452 {
2453 cbData = 0;
2454 }
2455 return NtGdiGetFontData(hdc, dwTable, dwOffset, lpvBuffer, cbData);
2456 }
2457
2458 DWORD
2459 WINAPI
2460 cGetTTFFromFOT(DWORD x1 ,DWORD x2 ,DWORD x3, DWORD x4, DWORD x5, DWORD x6, DWORD x7)
2461 {
2462 UNIMPLEMENTED;
2463 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2464 return 0;
2465 }
2466