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