* Sync up to trunk head (r65074).
[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 /*
1044 * @implemented
1045 */
1046 UINT
1047 APIENTRY
1048 GetOutlineTextMetricsA(
1049 HDC hdc,
1050 UINT cbData,
1051 LPOUTLINETEXTMETRICA lpOTM
1052 )
1053 {
1054 char buf[512], *ptr;
1055 UINT ret, needed;
1056 OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1057 OUTLINETEXTMETRICA *output = lpOTM;
1058 INT left, len;
1059
1060 if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1061 return 0;
1062 if(ret > sizeof(buf))
1063 {
1064 lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1065 if (lpOTMW == NULL)
1066 {
1067 return 0;
1068 }
1069 }
1070 GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1071
1072 needed = sizeof(OUTLINETEXTMETRICA);
1073 if(lpOTMW->otmpFamilyName)
1074 needed += WideCharToMultiByte(CP_ACP, 0,
1075 (WCHAR*)((char*)lpOTMW + (int)lpOTMW->otmpFamilyName), -1,
1076 NULL, 0, NULL, NULL);
1077 if(lpOTMW->otmpFaceName)
1078 needed += WideCharToMultiByte(CP_ACP, 0,
1079 (WCHAR*)((char*)lpOTMW + (int)lpOTMW->otmpFaceName), -1,
1080 NULL, 0, NULL, NULL);
1081 if(lpOTMW->otmpStyleName)
1082 needed += WideCharToMultiByte(CP_ACP, 0,
1083 (WCHAR*)((char*)lpOTMW + (int)lpOTMW->otmpStyleName), -1,
1084 NULL, 0, NULL, NULL);
1085 if(lpOTMW->otmpFullName)
1086 needed += WideCharToMultiByte(CP_ACP, 0,
1087 (WCHAR*)((char*)lpOTMW + (int)lpOTMW->otmpFullName), -1,
1088 NULL, 0, NULL, NULL);
1089
1090 if(!lpOTM)
1091 {
1092 ret = needed;
1093 goto end;
1094 }
1095
1096 DPRINT("needed = %u\n", needed);
1097 if(needed > cbData)
1098 {
1099 /* Since the supplied buffer isn't big enough, we'll alloc one
1100 that is and memcpy the first cbData bytes into the lpOTM at
1101 the end. */
1102 output = HeapAlloc(GetProcessHeap(), 0, needed);
1103 if (output == NULL)
1104 {
1105 goto end;
1106 }
1107 }
1108
1109 ret = output->otmSize = min(needed, cbData);
1110 FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1111 output->otmFiller = 0;
1112 output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1113 output->otmfsSelection = lpOTMW->otmfsSelection;
1114 output->otmfsType = lpOTMW->otmfsType;
1115 output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1116 output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1117 output->otmItalicAngle = lpOTMW->otmItalicAngle;
1118 output->otmEMSquare = lpOTMW->otmEMSquare;
1119 output->otmAscent = lpOTMW->otmAscent;
1120 output->otmDescent = lpOTMW->otmDescent;
1121 output->otmLineGap = lpOTMW->otmLineGap;
1122 output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1123 output->otmsXHeight = lpOTMW->otmsXHeight;
1124 output->otmrcFontBox = lpOTMW->otmrcFontBox;
1125 output->otmMacAscent = lpOTMW->otmMacAscent;
1126 output->otmMacDescent = lpOTMW->otmMacDescent;
1127 output->otmMacLineGap = lpOTMW->otmMacLineGap;
1128 output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1129 output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1130 output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1131 output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1132 output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1133 output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1134 output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1135 output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1136 output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1137
1138
1139 ptr = (char*)(output + 1);
1140 left = needed - sizeof(*output);
1141
1142 if(lpOTMW->otmpFamilyName)
1143 {
1144 output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1145 len = WideCharToMultiByte(CP_ACP, 0,
1146 (WCHAR*)((char*)lpOTMW + (int)lpOTMW->otmpFamilyName), -1,
1147 ptr, left, NULL, NULL);
1148 left -= len;
1149 ptr += len;
1150 }
1151 else
1152 output->otmpFamilyName = 0;
1153
1154 if(lpOTMW->otmpFaceName)
1155 {
1156 output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1157 len = WideCharToMultiByte(CP_ACP, 0,
1158 (WCHAR*)((char*)lpOTMW + (int)lpOTMW->otmpFaceName), -1,
1159 ptr, left, NULL, NULL);
1160 left -= len;
1161 ptr += len;
1162 }
1163 else
1164 output->otmpFaceName = 0;
1165
1166 if(lpOTMW->otmpStyleName)
1167 {
1168 output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1169 len = WideCharToMultiByte(CP_ACP, 0,
1170 (WCHAR*)((char*)lpOTMW + (int)lpOTMW->otmpStyleName), -1,
1171 ptr, left, NULL, NULL);
1172 left -= len;
1173 ptr += len;
1174 }
1175 else
1176 output->otmpStyleName = 0;
1177
1178 if(lpOTMW->otmpFullName)
1179 {
1180 output->otmpFullName = (LPSTR)(ptr - (char*)output);
1181 len = WideCharToMultiByte(CP_ACP, 0,
1182 (WCHAR*)((char*)lpOTMW + (int)lpOTMW->otmpFullName), -1,
1183 ptr, left, NULL, NULL);
1184 left -= len;
1185 }
1186 else
1187 output->otmpFullName = 0;
1188
1189 assert(left == 0);
1190
1191 if(output != lpOTM)
1192 {
1193 memcpy(lpOTM, output, cbData);
1194 HeapFree(GetProcessHeap(), 0, output);
1195
1196 /* check if the string offsets really fit into the provided size */
1197 /* FIXME: should we check string length as well? */
1198 if ((UINT_PTR)lpOTM->otmpFamilyName >= lpOTM->otmSize)
1199 lpOTM->otmpFamilyName = 0; /* doesn't fit */
1200
1201 if ((UINT_PTR)lpOTM->otmpFaceName >= lpOTM->otmSize)
1202 lpOTM->otmpFaceName = 0; /* doesn't fit */
1203
1204 if ((UINT_PTR)lpOTM->otmpStyleName >= lpOTM->otmSize)
1205 lpOTM->otmpStyleName = 0; /* doesn't fit */
1206
1207 if ((UINT_PTR)lpOTM->otmpFullName >= lpOTM->otmSize)
1208 lpOTM->otmpFullName = 0; /* doesn't fit */
1209 }
1210
1211 end:
1212 if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1213 HeapFree(GetProcessHeap(), 0, lpOTMW);
1214
1215 return ret;
1216 }
1217
1218 /* Performs a device to world transformation on the specified size (which
1219 * is in integer format).
1220 */
1221 static inline INT INTERNAL_YDSTOWS(XFORM *xForm, INT height)
1222 {
1223 double floatHeight;
1224
1225 /* Perform operation with floating point */
1226 floatHeight = (double)height * xForm->eM22;
1227 /* Round to integers */
1228 return GDI_ROUND(floatHeight);
1229 }
1230
1231 /* scale width and height but don't mirror them */
1232 static inline INT width_to_LP( XFORM *xForm, INT width )
1233 {
1234 return GDI_ROUND( (double)width * fabs( xForm->eM11));
1235 }
1236
1237 static inline INT height_to_LP( XFORM *xForm, INT height )
1238 {
1239 return GDI_ROUND( (double)height * fabs( xForm->eM22 ));
1240 }
1241
1242 /*
1243 * @implemented
1244 */
1245 UINT
1246 APIENTRY
1247 GetOutlineTextMetricsW(
1248 HDC hdc,
1249 UINT cbData,
1250 LPOUTLINETEXTMETRICW lpOTM
1251 )
1252 {
1253 TMDIFF Tmd; // Should not be zero.
1254 UINT Size, AvailableSize = 0, StringSize;
1255 XFORM DevToWorld;
1256 OUTLINETEXTMETRICW* LocalOTM;
1257 WCHAR* Str;
1258 BYTE* Ptr;
1259
1260 /* Get the structure */
1261 Size = NtGdiGetOutlineTextMetricsInternalW(hdc, 0, NULL, &Tmd);
1262 if (!Size)
1263 return 0;
1264 if (!lpOTM || (cbData < sizeof(*lpOTM)))
1265 return Size;
1266
1267 LocalOTM = HeapAlloc(GetProcessHeap(), 0, Size);
1268 LocalOTM->otmSize = Size;
1269 Size = NtGdiGetOutlineTextMetricsInternalW(hdc, Size, LocalOTM, &Tmd);
1270 if (!Size)
1271 {
1272 HeapFree(GetProcessHeap(), 0, LocalOTM);
1273 return 0;
1274 }
1275
1276 if (!NtGdiGetTransform(hdc, GdiDeviceSpaceToWorldSpace, &DevToWorld))
1277 {
1278 DPRINT1("NtGdiGetTransform failed!\n");
1279 HeapFree(GetProcessHeap(), 0, LocalOTM);
1280 SetLastError(ERROR_INVALID_HANDLE);
1281 return 0;
1282 }
1283
1284 /* Fill in DC specific data */
1285 LocalOTM->otmTextMetrics.tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1286 LocalOTM->otmTextMetrics.tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1287 LocalOTM->otmTextMetrics.tmHeight = height_to_LP( &DevToWorld, LocalOTM->otmTextMetrics.tmHeight );
1288 LocalOTM->otmTextMetrics.tmAscent = height_to_LP( &DevToWorld, LocalOTM->otmTextMetrics.tmAscent );
1289 LocalOTM->otmTextMetrics.tmDescent = height_to_LP( &DevToWorld, LocalOTM->otmTextMetrics.tmDescent );
1290 LocalOTM->otmTextMetrics.tmInternalLeading = height_to_LP( &DevToWorld, LocalOTM->otmTextMetrics.tmInternalLeading );
1291 LocalOTM->otmTextMetrics.tmExternalLeading = height_to_LP( &DevToWorld, LocalOTM->otmTextMetrics.tmExternalLeading );
1292 LocalOTM->otmTextMetrics.tmAveCharWidth = width_to_LP( &DevToWorld, LocalOTM->otmTextMetrics.tmAveCharWidth );
1293 LocalOTM->otmTextMetrics.tmMaxCharWidth = width_to_LP( &DevToWorld, LocalOTM->otmTextMetrics.tmMaxCharWidth );
1294 LocalOTM->otmTextMetrics.tmOverhang = width_to_LP( &DevToWorld, LocalOTM->otmTextMetrics.tmOverhang );
1295 LocalOTM->otmAscent = height_to_LP( &DevToWorld, LocalOTM->otmAscent);
1296 LocalOTM->otmDescent = height_to_LP( &DevToWorld, LocalOTM->otmDescent);
1297 LocalOTM->otmLineGap = abs(INTERNAL_YDSTOWS(&DevToWorld,LocalOTM->otmLineGap));
1298 LocalOTM->otmsCapEmHeight = abs(INTERNAL_YDSTOWS(&DevToWorld,LocalOTM->otmsCapEmHeight));
1299 LocalOTM->otmsXHeight = abs(INTERNAL_YDSTOWS(&DevToWorld,LocalOTM->otmsXHeight));
1300 LocalOTM->otmrcFontBox.top = height_to_LP( &DevToWorld, LocalOTM->otmrcFontBox.top);
1301 LocalOTM->otmrcFontBox.bottom = height_to_LP( &DevToWorld, LocalOTM->otmrcFontBox.bottom);
1302 LocalOTM->otmrcFontBox.left = width_to_LP( &DevToWorld, LocalOTM->otmrcFontBox.left);
1303 LocalOTM->otmrcFontBox.right = width_to_LP( &DevToWorld, LocalOTM->otmrcFontBox.right);
1304 LocalOTM->otmMacAscent = height_to_LP( &DevToWorld, LocalOTM->otmMacAscent);
1305 LocalOTM->otmMacDescent = height_to_LP( &DevToWorld, LocalOTM->otmMacDescent);
1306 LocalOTM->otmMacLineGap = abs(INTERNAL_YDSTOWS(&DevToWorld,LocalOTM->otmMacLineGap));
1307 LocalOTM->otmptSubscriptSize.x = width_to_LP( &DevToWorld, LocalOTM->otmptSubscriptSize.x);
1308 LocalOTM->otmptSubscriptSize.y = height_to_LP( &DevToWorld, LocalOTM->otmptSubscriptSize.y);
1309 LocalOTM->otmptSubscriptOffset.x = width_to_LP( &DevToWorld, LocalOTM->otmptSubscriptOffset.x);
1310 LocalOTM->otmptSubscriptOffset.y = height_to_LP( &DevToWorld, LocalOTM->otmptSubscriptOffset.y);
1311 LocalOTM->otmptSuperscriptSize.x = width_to_LP( &DevToWorld, LocalOTM->otmptSuperscriptSize.x);
1312 LocalOTM->otmptSuperscriptSize.y = height_to_LP( &DevToWorld, LocalOTM->otmptSuperscriptSize.y);
1313 LocalOTM->otmptSuperscriptOffset.x = width_to_LP( &DevToWorld, LocalOTM->otmptSuperscriptOffset.x);
1314 LocalOTM->otmptSuperscriptOffset.y = height_to_LP( &DevToWorld, LocalOTM->otmptSuperscriptOffset.y);
1315 LocalOTM->otmsStrikeoutSize = abs(INTERNAL_YDSTOWS(&DevToWorld,LocalOTM->otmsStrikeoutSize));
1316 LocalOTM->otmsStrikeoutPosition = height_to_LP( &DevToWorld, LocalOTM->otmsStrikeoutPosition);
1317 LocalOTM->otmsUnderscoreSize = height_to_LP( &DevToWorld, LocalOTM->otmsUnderscoreSize);
1318 LocalOTM->otmsUnderscorePosition = height_to_LP( &DevToWorld, LocalOTM->otmsUnderscorePosition);
1319
1320 /* Copy what we can */
1321 CopyMemory(lpOTM, LocalOTM, min(Size, cbData));
1322
1323 lpOTM->otmpFamilyName = NULL;
1324 lpOTM->otmpFaceName = NULL;
1325 lpOTM->otmpStyleName = NULL;
1326 lpOTM->otmpFullName = NULL;
1327
1328 Size = sizeof(*lpOTM);
1329 AvailableSize = cbData - Size;
1330 Ptr = (BYTE*)lpOTM + sizeof(*lpOTM);
1331
1332 /* Fix string values up */
1333 if (LocalOTM->otmpFamilyName)
1334 {
1335 Str = (WCHAR*)((char*)LocalOTM + (ptrdiff_t)LocalOTM->otmpFamilyName);
1336 StringSize = (wcslen(Str) + 1) * sizeof(WCHAR);
1337 if (AvailableSize >= StringSize)
1338 {
1339 CopyMemory(Ptr, Str, StringSize);
1340 lpOTM->otmpFamilyName = (PSTR)(Ptr - (BYTE*)lpOTM);
1341 Ptr += StringSize;
1342 AvailableSize -= StringSize;
1343 Size += StringSize;
1344 }
1345 }
1346
1347 if (LocalOTM->otmpFaceName)
1348 {
1349 Str = (WCHAR*)((char*)LocalOTM + (ptrdiff_t)LocalOTM->otmpFaceName);
1350 StringSize = (wcslen(Str) + 1) * sizeof(WCHAR);
1351 if (AvailableSize >= StringSize)
1352 {
1353 CopyMemory(Ptr, Str, StringSize);
1354 lpOTM->otmpFaceName = (PSTR)(Ptr - (BYTE*)lpOTM);
1355 Ptr += StringSize;
1356 AvailableSize -= StringSize;
1357 Size += StringSize;
1358 }
1359 }
1360
1361 if (LocalOTM->otmpStyleName)
1362 {
1363 Str = (WCHAR*)((char*)LocalOTM + (ptrdiff_t)LocalOTM->otmpStyleName);
1364 StringSize = (wcslen(Str) + 1) * sizeof(WCHAR);
1365 if (AvailableSize >= StringSize)
1366 {
1367 CopyMemory(Ptr, Str, StringSize);
1368 lpOTM->otmpStyleName = (PSTR)(Ptr - (BYTE*)lpOTM);
1369 Ptr += StringSize;
1370 AvailableSize -= StringSize;
1371 Size += StringSize;
1372 }
1373 }
1374
1375 if (LocalOTM->otmpFullName)
1376 {
1377 Str = (WCHAR*)((char*)LocalOTM + (ptrdiff_t)LocalOTM->otmpFullName);
1378 StringSize = (wcslen(Str) + 1) * sizeof(WCHAR);
1379 if (AvailableSize >= StringSize)
1380 {
1381 CopyMemory(Ptr, Str, StringSize);
1382 lpOTM->otmpFullName = (PSTR)(Ptr - (BYTE*)lpOTM);
1383 Ptr += StringSize;
1384 AvailableSize -= StringSize;
1385 Size += StringSize;
1386 }
1387 }
1388
1389 lpOTM->otmSize = Size;
1390
1391 HeapFree(GetProcessHeap(), 0, LocalOTM);
1392
1393 return Size;
1394 }
1395
1396 /*
1397 * @implemented
1398 */
1399 DWORD
1400 WINAPI
1401 GetKerningPairsW(HDC hdc,
1402 ULONG cPairs,
1403 LPKERNINGPAIR pkpDst)
1404 {
1405 if ((cPairs != 0) || (pkpDst == 0))
1406 {
1407 return NtGdiGetKerningPairs(hdc,cPairs,pkpDst);
1408 }
1409 else
1410 {
1411 SetLastError(ERROR_INVALID_PARAMETER);
1412 return 0;
1413 }
1414 }
1415
1416 /*
1417 * @implemented
1418 */
1419 DWORD
1420 WINAPI
1421 GetKerningPairsA( HDC hDC,
1422 DWORD cPairs,
1423 LPKERNINGPAIR kern_pairA )
1424 {
1425 INT charset;
1426 CHARSETINFO csi;
1427 CPINFO cpi;
1428 DWORD i, total_kern_pairs, kern_pairs_copied = 0;
1429 KERNINGPAIR *kern_pairW;
1430
1431 if (!cPairs && kern_pairA)
1432 {
1433 SetLastError(ERROR_INVALID_PARAMETER);
1434 return 0;
1435 }
1436
1437 charset = GetTextCharset(hDC);
1438 if (!TranslateCharsetInfo(ULongToPtr(charset), &csi, TCI_SRCCHARSET))
1439 {
1440 DPRINT1("Can't find codepage for charset %d\n", charset);
1441 return 0;
1442 }
1443 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
1444 * to fail on an invalid character for CP_SYMBOL.
1445 */
1446 cpi.DefaultChar[0] = 0;
1447 if (csi.ciACP != CP_SYMBOL && !GetCPInfo(csi.ciACP, &cpi))
1448 {
1449 DPRINT1("Can't find codepage %u info\n", csi.ciACP);
1450 return 0;
1451 }
1452 DPRINT("charset %d => codepage %u\n", charset, csi.ciACP);
1453
1454 total_kern_pairs = NtGdiGetKerningPairs(hDC, 0, NULL);
1455 if (!total_kern_pairs) return 0;
1456
1457 if (!cPairs && !kern_pairA) return total_kern_pairs;
1458
1459 kern_pairW = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW));
1460 if (kern_pairW == NULL)
1461 {
1462 return 0;
1463 }
1464 GetKerningPairsW(hDC, total_kern_pairs, kern_pairW);
1465
1466 for (i = 0; i < total_kern_pairs; i++)
1467 {
1468 char first, second;
1469
1470 if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL))
1471 continue;
1472
1473 if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL))
1474 continue;
1475
1476 if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0])
1477 continue;
1478
1479 if (kern_pairA)
1480 {
1481 if (kern_pairs_copied >= cPairs) break;
1482
1483 kern_pairA->wFirst = (BYTE)first;
1484 kern_pairA->wSecond = (BYTE)second;
1485 kern_pairA->iKernAmount = kern_pairW[i].iKernAmount;
1486 kern_pairA++;
1487 }
1488 kern_pairs_copied++;
1489 }
1490
1491 HeapFree(GetProcessHeap(), 0, kern_pairW);
1492
1493 return kern_pairs_copied;
1494 }
1495
1496
1497
1498 /*
1499 * @implemented
1500 */
1501 HFONT
1502 WINAPI
1503 CreateFontIndirectExA(const ENUMLOGFONTEXDVA *elfexd)
1504 {
1505 if (elfexd)
1506 {
1507 ENUMLOGFONTEXDVW Logfont;
1508
1509 EnumLogFontExW2A( (LPENUMLOGFONTEXA) elfexd,
1510 &Logfont.elfEnumLogfontEx );
1511
1512 RtlCopyMemory( &Logfont.elfDesignVector,
1513 (PVOID) &elfexd->elfDesignVector,
1514 sizeof(DESIGNVECTOR));
1515
1516 return NtGdiHfontCreate( &Logfont, 0, 0, 0, NULL);
1517 }
1518 else return NULL;
1519 }
1520
1521
1522 /*
1523 * @implemented
1524 */
1525 HFONT
1526 WINAPI
1527 CreateFontIndirectExW(const ENUMLOGFONTEXDVW *elfexd)
1528 {
1529 /* Msdn: Note, this function ignores the elfDesignVector member in
1530 ENUMLOGFONTEXDV.
1531 */
1532 if ( elfexd )
1533 {
1534 return NtGdiHfontCreate((PENUMLOGFONTEXDVW) elfexd, 0, 0, 0, NULL );
1535 }
1536 else return NULL;
1537 }
1538
1539
1540 /*
1541 * @implemented
1542 */
1543 HFONT
1544 WINAPI
1545 CreateFontIndirectA(
1546 CONST LOGFONTA *lplf
1547 )
1548 {
1549 if (lplf)
1550 {
1551 LOGFONTW tlf;
1552
1553 LogFontA2W(&tlf, lplf);
1554 return CreateFontIndirectW(&tlf);
1555 }
1556 else return NULL;
1557 }
1558
1559
1560 /*
1561 * @implemented
1562 */
1563 HFONT
1564 WINAPI
1565 CreateFontIndirectW(
1566 CONST LOGFONTW *lplf
1567 )
1568 {
1569 if (lplf)
1570 {
1571 ENUMLOGFONTEXDVW Logfont;
1572
1573 RtlCopyMemory( &Logfont.elfEnumLogfontEx.elfLogFont, lplf, sizeof(LOGFONTW));
1574 // Need something other than just cleaning memory here.
1575 // Guess? Use caller data to determine the rest.
1576 RtlZeroMemory( &Logfont.elfEnumLogfontEx.elfFullName,
1577 sizeof(Logfont.elfEnumLogfontEx.elfFullName));
1578 RtlZeroMemory( &Logfont.elfEnumLogfontEx.elfStyle,
1579 sizeof(Logfont.elfEnumLogfontEx.elfStyle));
1580 RtlZeroMemory( &Logfont.elfEnumLogfontEx.elfScript,
1581 sizeof(Logfont.elfEnumLogfontEx.elfScript));
1582
1583 Logfont.elfDesignVector.dvNumAxes = 0; // No more than MM_MAX_NUMAXES
1584
1585 RtlZeroMemory( &Logfont.elfDesignVector, sizeof(DESIGNVECTOR));
1586
1587 return CreateFontIndirectExW(&Logfont);
1588 }
1589 else return NULL;
1590 }
1591
1592
1593 /*
1594 * @implemented
1595 */
1596 HFONT
1597 WINAPI
1598 CreateFontA(
1599 int nHeight,
1600 int nWidth,
1601 int nEscapement,
1602 int nOrientation,
1603 int fnWeight,
1604 DWORD fdwItalic,
1605 DWORD fdwUnderline,
1606 DWORD fdwStrikeOut,
1607 DWORD fdwCharSet,
1608 DWORD fdwOutputPrecision,
1609 DWORD fdwClipPrecision,
1610 DWORD fdwQuality,
1611 DWORD fdwPitchAndFamily,
1612 LPCSTR lpszFace
1613 )
1614 {
1615 ANSI_STRING StringA;
1616 UNICODE_STRING StringU;
1617 HFONT ret;
1618
1619 RtlInitAnsiString(&StringA, (LPSTR)lpszFace);
1620 RtlAnsiStringToUnicodeString(&StringU, &StringA, TRUE);
1621
1622 ret = CreateFontW(nHeight,
1623 nWidth,
1624 nEscapement,
1625 nOrientation,
1626 fnWeight,
1627 fdwItalic,
1628 fdwUnderline,
1629 fdwStrikeOut,
1630 fdwCharSet,
1631 fdwOutputPrecision,
1632 fdwClipPrecision,
1633 fdwQuality,
1634 fdwPitchAndFamily,
1635 StringU.Buffer);
1636
1637 RtlFreeUnicodeString(&StringU);
1638
1639 return ret;
1640 }
1641
1642
1643 /*
1644 * @implemented
1645 */
1646 HFONT
1647 WINAPI
1648 CreateFontW(
1649 int nHeight,
1650 int nWidth,
1651 int nEscapement,
1652 int nOrientation,
1653 int nWeight,
1654 DWORD fnItalic,
1655 DWORD fdwUnderline,
1656 DWORD fdwStrikeOut,
1657 DWORD fdwCharSet,
1658 DWORD fdwOutputPrecision,
1659 DWORD fdwClipPrecision,
1660 DWORD fdwQuality,
1661 DWORD fdwPitchAndFamily,
1662 LPCWSTR lpszFace
1663 )
1664 {
1665 LOGFONTW logfont;
1666
1667 logfont.lfHeight = nHeight;
1668 logfont.lfWidth = nWidth;
1669 logfont.lfEscapement = nEscapement;
1670 logfont.lfOrientation = nOrientation;
1671 logfont.lfWeight = nWeight;
1672 logfont.lfItalic = (BYTE)fnItalic;
1673 logfont.lfUnderline = (BYTE)fdwUnderline;
1674 logfont.lfStrikeOut = (BYTE)fdwStrikeOut;
1675 logfont.lfCharSet = (BYTE)fdwCharSet;
1676 logfont.lfOutPrecision = (BYTE)fdwOutputPrecision;
1677 logfont.lfClipPrecision = (BYTE)fdwClipPrecision;
1678 logfont.lfQuality = (BYTE)fdwQuality;
1679 logfont.lfPitchAndFamily = (BYTE)fdwPitchAndFamily;
1680
1681 if (NULL != lpszFace)
1682 {
1683 int Size = sizeof(logfont.lfFaceName) / sizeof(WCHAR);
1684 wcsncpy((wchar_t *)logfont.lfFaceName, lpszFace, Size - 1);
1685 /* Be 101% sure to have '\0' at end of string */
1686 logfont.lfFaceName[Size - 1] = '\0';
1687 }
1688 else
1689 {
1690 logfont.lfFaceName[0] = L'\0';
1691 }
1692
1693 return CreateFontIndirectW(&logfont);
1694 }
1695
1696
1697 /*
1698 * @unimplemented
1699 */
1700 BOOL
1701 WINAPI
1702 CreateScalableFontResourceA(
1703 DWORD fdwHidden,
1704 LPCSTR lpszFontRes,
1705 LPCSTR lpszFontFile,
1706 LPCSTR lpszCurrentPath
1707 )
1708 {
1709 return FALSE;
1710 }
1711
1712
1713 /*
1714 * @implemented
1715 */
1716 int
1717 WINAPI
1718 AddFontResourceExW ( LPCWSTR lpszFilename, DWORD fl, PVOID pvReserved )
1719 {
1720 if (fl & ~(FR_PRIVATE | FR_NOT_ENUM))
1721 {
1722 SetLastError( ERROR_INVALID_PARAMETER );
1723 return 0;
1724 }
1725
1726 return GdiAddFontResourceW(lpszFilename, fl,0);
1727 }
1728
1729
1730 /*
1731 * @implemented
1732 */
1733 int
1734 WINAPI
1735 AddFontResourceExA ( LPCSTR lpszFilename, DWORD fl, PVOID pvReserved )
1736 {
1737 NTSTATUS Status;
1738 PWSTR FilenameW;
1739 int rc;
1740
1741 if (fl & ~(FR_PRIVATE | FR_NOT_ENUM))
1742 {
1743 SetLastError( ERROR_INVALID_PARAMETER );
1744 return 0;
1745 }
1746
1747 Status = HEAP_strdupA2W ( &FilenameW, lpszFilename );
1748 if ( !NT_SUCCESS (Status) )
1749 {
1750 SetLastError (RtlNtStatusToDosError(Status));
1751 return 0;
1752 }
1753
1754 rc = GdiAddFontResourceW ( FilenameW, fl, 0 );
1755 HEAP_free ( FilenameW );
1756 return rc;
1757 }
1758
1759
1760 /*
1761 * @implemented
1762 */
1763 int
1764 WINAPI
1765 AddFontResourceA ( LPCSTR lpszFilename )
1766 {
1767 NTSTATUS Status;
1768 PWSTR FilenameW;
1769 int rc = 0;
1770
1771 Status = HEAP_strdupA2W ( &FilenameW, lpszFilename );
1772 if ( !NT_SUCCESS (Status) )
1773 {
1774 SetLastError (RtlNtStatusToDosError(Status));
1775 }
1776 else
1777 {
1778 rc = GdiAddFontResourceW ( FilenameW, 0, 0);
1779
1780 HEAP_free ( FilenameW );
1781 }
1782 return rc;
1783 }
1784
1785
1786 /*
1787 * @implemented
1788 */
1789 int
1790 WINAPI
1791 AddFontResourceW ( LPCWSTR lpszFilename )
1792 {
1793 return GdiAddFontResourceW ( lpszFilename, 0, 0 );
1794 }
1795
1796
1797 /*
1798 * @implemented
1799 */
1800 BOOL
1801 WINAPI
1802 RemoveFontResourceW(LPCWSTR lpFileName)
1803 {
1804 return RemoveFontResourceExW(lpFileName,0,0);
1805 }
1806
1807
1808 /*
1809 * @implemented
1810 */
1811 BOOL
1812 WINAPI
1813 RemoveFontResourceA(LPCSTR lpFileName)
1814 {
1815 return RemoveFontResourceExA(lpFileName,0,0);
1816 }
1817
1818 /*
1819 * @unimplemented
1820 */
1821 BOOL
1822 WINAPI
1823 RemoveFontResourceExA(LPCSTR lpFileName,
1824 DWORD fl,
1825 PVOID pdv
1826 )
1827 {
1828 NTSTATUS Status;
1829 LPWSTR lpFileNameW;
1830
1831 /* FIXME the flags */
1832 /* FIXME the pdv */
1833 /* FIXME NtGdiRemoveFontResource handle flags and pdv */
1834
1835 Status = HEAP_strdupA2W ( &lpFileNameW, lpFileName );
1836 if (!NT_SUCCESS (Status))
1837 SetLastError (RtlNtStatusToDosError(Status));
1838 else
1839 {
1840
1841 HEAP_free ( lpFileNameW );
1842 }
1843
1844 return 0;
1845 }
1846
1847 /*
1848 * @unimplemented
1849 */
1850 BOOL
1851 WINAPI
1852 RemoveFontResourceExW(LPCWSTR lpFileName,
1853 DWORD fl,
1854 PVOID pdv)
1855 {
1856 /* FIXME the flags */
1857 /* FIXME the pdv */
1858 /* FIXME NtGdiRemoveFontResource handle flags and pdv */
1859 return 0;
1860 }
1861
1862
1863 /***********************************************************************
1864 * GdiGetCharDimensions
1865 *
1866 * Gets the average width of the characters in the English alphabet.
1867 *
1868 * PARAMS
1869 * hdc [I] Handle to the device context to measure on.
1870 * lptm [O] Pointer to memory to store the text metrics into.
1871 * height [O] On exit, the maximum height of characters in the English alphabet.
1872 *
1873 * RETURNS
1874 * The average width of characters in the English alphabet.
1875 *
1876 * NOTES
1877 * This function is used by the dialog manager to get the size of a dialog
1878 * unit. It should also be used by other pieces of code that need to know
1879 * the size of a dialog unit in logical units without having access to the
1880 * window handle of the dialog.
1881 * Windows caches the font metrics from this function, but we don't and
1882 * there doesn't appear to be an immediate advantage to do so.
1883 *
1884 * SEE ALSO
1885 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
1886 *
1887 * Despite most of MSDN insisting that the horizontal base unit is
1888 * tmAveCharWidth it isn't. Knowledge base article Q145994
1889 * "HOWTO: Calculate Dialog Units When Not Using the System Font",
1890 * says that we should take the average of the 52 English upper and lower
1891 * case characters.
1892 */
1893 /*
1894 * @implemented
1895 */
1896 LONG
1897 WINAPI
1898 GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
1899 {
1900 SIZE sz;
1901 TEXTMETRICW tm;
1902 static const WCHAR alphabet[] =
1903 {
1904 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
1905 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
1906 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0
1907 };
1908
1909 if(!GetTextMetricsW(hdc, &tm)) return 0;
1910
1911 if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
1912
1913 if (lptm) *lptm = tm;
1914 if (height) *height = tm.tmHeight;
1915
1916 return (sz.cx / 26 + 1) / 2;
1917 }
1918
1919 /*************************************************************************
1920 * TranslateCharsetInfo [GDI32.@]
1921 *
1922 * Fills a CHARSETINFO structure for a character set, code page, or
1923 * font. This allows making the correspondance between different labelings
1924 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
1925 * of the same encoding.
1926 *
1927 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
1928 * only one codepage should be set in *lpSrc.
1929 *
1930 * RETURNS
1931 * TRUE on success, FALSE on failure.
1932 *
1933 */
1934 /*
1935 * @implemented
1936 */
1937 BOOL
1938 WINAPI
1939 TranslateCharsetInfo(
1940 LPDWORD lpSrc, /* [in]
1941 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
1942 if flags == TCI_SRCCHARSET: a character set value
1943 if flags == TCI_SRCCODEPAGE: a code page value
1944 */
1945 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
1946 DWORD flags /* [in] determines interpretation of lpSrc */)
1947 {
1948 int index = 0;
1949 switch (flags)
1950 {
1951 case TCI_SRCFONTSIG:
1952 while (index < MAXTCIINDEX && !(*lpSrc>>index & 0x0001)) index++;
1953 break;
1954 case TCI_SRCCODEPAGE:
1955 while (index < MAXTCIINDEX && PtrToUlong(lpSrc) != FONT_tci[index].ciACP) index++;
1956 break;
1957 case TCI_SRCCHARSET:
1958 while (index < MAXTCIINDEX && PtrToUlong(lpSrc) != FONT_tci[index].ciCharset) index++;
1959 break;
1960 case TCI_SRCLOCALE:
1961 {
1962 LCID lCid = (LCID)PtrToUlong(lpSrc);
1963 LOCALESIGNATURE LocSig;
1964 INT Ret = GetLocaleInfoW(lCid, LOCALE_FONTSIGNATURE, (LPWSTR)&LocSig, 0);
1965 if ( GetLocaleInfoW(lCid, LOCALE_FONTSIGNATURE, (LPWSTR)&LocSig, Ret))
1966 {
1967 while (index < MAXTCIINDEX && !(LocSig.lsCsbDefault[0]>>index & 0x0001)) index++;
1968 break;
1969 }
1970 }
1971 default:
1972 GdiSetLastError(ERROR_INVALID_PARAMETER);
1973 return FALSE;
1974 }
1975 if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
1976 DPRINT("Index %d Charset %u CodePage %u FontSig %lu\n",
1977 index,FONT_tci[index].ciCharset,FONT_tci[index].ciACP,FONT_tci[index].fs.fsCsb[0]);
1978 memcpy(lpCs, &FONT_tci[index], sizeof(CHARSETINFO));
1979 return TRUE;
1980 }
1981
1982
1983 /*
1984 * @implemented
1985 */
1986 DWORD
1987 WINAPI
1988 SetMapperFlags(
1989 HDC hDC,
1990 DWORD flags
1991 )
1992 {
1993 DWORD Ret = GDI_ERROR;
1994 PDC_ATTR Dc_Attr;
1995 #if 0
1996 if (GDI_HANDLE_GET_TYPE(hDC) != GDI_OBJECT_TYPE_DC)
1997 {
1998 if (GDI_HANDLE_GET_TYPE(hDC) == GDI_OBJECT_TYPE_METADC)
1999 return MFDRV_SetMapperFlags( hDC, flags);
2000 else
2001 {
2002 PLDC pLDC = Dc_Attr->pvLDC;
2003 if ( !pLDC )
2004 {
2005 SetLastError(ERROR_INVALID_HANDLE);
2006 return GDI_ERROR;
2007 }
2008 if (pLDC->iType == LDC_EMFLDC)
2009 {
2010 return EMFDRV_SetMapperFlags( hDC, flags);
2011 }
2012 }
2013 }
2014 #endif
2015 if (!GdiGetHandleUserData((HGDIOBJ) hDC, GDI_OBJECT_TYPE_DC, (PVOID) &Dc_Attr)) return GDI_ERROR;
2016
2017 if (NtCurrentTeb()->GdiTebBatch.HDC == hDC)
2018 {
2019 if (Dc_Attr->ulDirty_ & DC_FONTTEXT_DIRTY)
2020 {
2021 NtGdiFlush();
2022 Dc_Attr->ulDirty_ &= ~(DC_MODE_DIRTY|DC_FONTTEXT_DIRTY);
2023 }
2024 }
2025
2026 if ( flags & ~1 )
2027 SetLastError(ERROR_INVALID_PARAMETER);
2028 else
2029 {
2030 Ret = Dc_Attr->flFontMapper;
2031 Dc_Attr->flFontMapper = flags;
2032 }
2033 return Ret;
2034 }
2035
2036
2037 /*
2038 * @unimplemented
2039 */
2040 int
2041 WINAPI
2042 EnumFontsW(
2043 HDC hDC,
2044 LPCWSTR lpFaceName,
2045 FONTENUMPROCW FontFunc,
2046 LPARAM lParam
2047 )
2048 {
2049 #if 0
2050 return NtGdiEnumFonts ( hDC, lpFaceName, FontFunc, lParam );
2051 #else
2052 return EnumFontFamiliesW( hDC, lpFaceName, FontFunc, lParam );
2053 #endif
2054 }
2055
2056 /*
2057 * @unimplemented
2058 */
2059 int
2060 WINAPI
2061 EnumFontsA (
2062 HDC hDC,
2063 LPCSTR lpFaceName,
2064 FONTENUMPROCA FontFunc,
2065 LPARAM lParam
2066 )
2067 {
2068 #if 0
2069 NTSTATUS Status;
2070 LPWSTR lpFaceNameW;
2071 int rc = 0;
2072
2073 Status = HEAP_strdupA2W ( &lpFaceNameW, lpFaceName );
2074 if (!NT_SUCCESS (Status))
2075 SetLastError (RtlNtStatusToDosError(Status));
2076 else
2077 {
2078 rc = NtGdiEnumFonts ( hDC, lpFaceNameW, FontFunc, lParam );
2079
2080 HEAP_free ( lpFaceNameW );
2081 }
2082 return rc;
2083 #else
2084 return EnumFontFamiliesA( hDC, lpFaceName, FontFunc, lParam );
2085 #endif
2086 }
2087
2088 #define EfdFontFamilies 3
2089
2090 INT
2091 WINAPI
2092 NewEnumFontFamiliesExW(
2093 HDC hDC,
2094 LPLOGFONTW lpLogfont,
2095 FONTENUMPROCW lpEnumFontFamExProcW,
2096 LPARAM lParam,
2097 DWORD dwFlags)
2098 {
2099 ULONG_PTR idEnum, cbDataSize, cbRetSize;
2100 PENUMFONTDATAW pEfdw;
2101 PBYTE pBuffer;
2102 PBYTE pMax;
2103 INT ret = 1;
2104
2105 /* Open enumeration handle and find out how much memory we need */
2106 idEnum = NtGdiEnumFontOpen(hDC,
2107 EfdFontFamilies,
2108 0,
2109 LF_FACESIZE,
2110 (lpLogfont && lpLogfont->lfFaceName[0])? lpLogfont->lfFaceName : NULL,
2111 lpLogfont? lpLogfont->lfCharSet : DEFAULT_CHARSET,
2112 &cbDataSize);
2113 if (idEnum == 0)
2114 {
2115 return 0;
2116 }
2117 if (cbDataSize == 0)
2118 {
2119 NtGdiEnumFontClose(idEnum);
2120 return 0;
2121 }
2122
2123 /* Allocate memory */
2124 pBuffer = HeapAlloc(GetProcessHeap(), 0, cbDataSize);
2125 if (pBuffer == NULL)
2126 {
2127 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2128 NtGdiEnumFontClose(idEnum);
2129 return 0;
2130 }
2131
2132 /* Do the enumeration */
2133 if (!NtGdiEnumFontChunk(hDC, idEnum, cbDataSize, &cbRetSize, (PVOID)pBuffer))
2134 {
2135 HeapFree(GetProcessHeap(), 0, pBuffer);
2136 NtGdiEnumFontClose(idEnum);
2137 return 0;
2138 }
2139
2140 /* Get start and end address */
2141 pEfdw = (PENUMFONTDATAW)pBuffer;
2142 pMax = pBuffer + cbDataSize;
2143
2144 /* Iterate through the structures */
2145 while ((PBYTE)pEfdw < pMax && ret)
2146 {
2147 PNTMW_INTERNAL pNtmwi = (PNTMW_INTERNAL)((ULONG_PTR)pEfdw + pEfdw->ulNtmwiOffset);
2148
2149 ret = lpEnumFontFamExProcW((VOID*)&pEfdw->elfexdv.elfEnumLogfontEx,
2150 (VOID*)&pNtmwi->ntmw,
2151 pEfdw->dwFontType,
2152 lParam);
2153
2154 pEfdw = (PENUMFONTDATAW)((ULONG_PTR)pEfdw + pEfdw->cbSize);
2155 }
2156
2157 /* Release the memory and close handle */
2158 HeapFree(GetProcessHeap(), 0, pBuffer);
2159 NtGdiEnumFontClose(idEnum);
2160
2161 return ret;
2162 }