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