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