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