- Fix code page and charector set support. More miscellaneous changes and fixes.
[reactos.git] / reactos / dll / win32 / gdi32 / objects / font.c
1 /* $Id$
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS system libraries
5 * FILE: lib/gdi32/object/font.c
6 * PURPOSE:
7 * PROGRAMMER:
8 *
9 */
10
11 #include "precomp.h"
12
13 #define NDEBUG
14 #include <debug.h>
15
16 /*
17 * For TranslateCharsetInfo
18 */
19 #define MAXTCIINDEX 32
20 static const CHARSETINFO FONT_tci[MAXTCIINDEX] = {
21 /* ANSI */
22 { ANSI_CHARSET, 1252, {{0,0,0,0},{FS_LATIN1,0}} },
23 { EASTEUROPE_CHARSET, 1250, {{0,0,0,0},{FS_LATIN2,0}} },
24 { RUSSIAN_CHARSET, 1251, {{0,0,0,0},{FS_CYRILLIC,0}} },
25 { GREEK_CHARSET, 1253, {{0,0,0,0},{FS_GREEK,0}} },
26 { TURKISH_CHARSET, 1254, {{0,0,0,0},{FS_TURKISH,0}} },
27 { HEBREW_CHARSET, 1255, {{0,0,0,0},{FS_HEBREW,0}} },
28 { ARABIC_CHARSET, 1256, {{0,0,0,0},{FS_ARABIC,0}} },
29 { BALTIC_CHARSET, 1257, {{0,0,0,0},{FS_BALTIC,0}} },
30 { VIETNAMESE_CHARSET, 1258, {{0,0,0,0},{FS_VIETNAMESE,0}} },
31 /* reserved by ANSI */
32 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
33 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
34 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
35 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
36 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
37 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
38 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
39 /* ANSI and OEM */
40 { THAI_CHARSET, 874, {{0,0,0,0},{FS_THAI,0}} },
41 { SHIFTJIS_CHARSET, 932, {{0,0,0,0},{FS_JISJAPAN,0}} },
42 { GB2312_CHARSET, 936, {{0,0,0,0},{FS_CHINESESIMP,0}} },
43 { HANGEUL_CHARSET, 949, {{0,0,0,0},{FS_WANSUNG,0}} },
44 { CHINESEBIG5_CHARSET, 950, {{0,0,0,0},{FS_CHINESETRAD,0}} },
45 { JOHAB_CHARSET, 1361, {{0,0,0,0},{FS_JOHAB,0}} },
46 /* reserved for alternate ANSI and OEM */
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 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
52 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
53 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
54 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
55 /* reserved for system */
56 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
57 { SYMBOL_CHARSET, CP_SYMBOL, {{0,0,0,0},{FS_SYMBOL,0}} }
58 };
59
60 #define INITIAL_FAMILY_COUNT 64
61
62 /***********************************************************************
63 * TEXTMETRIC conversion functions.
64 */
65 static void FONT_TextMetricWToA(const TEXTMETRICW *ptmW, LPTEXTMETRICA ptmA )
66 {
67 ptmA->tmHeight = ptmW->tmHeight;
68 ptmA->tmAscent = ptmW->tmAscent;
69 ptmA->tmDescent = ptmW->tmDescent;
70 ptmA->tmInternalLeading = ptmW->tmInternalLeading;
71 ptmA->tmExternalLeading = ptmW->tmExternalLeading;
72 ptmA->tmAveCharWidth = ptmW->tmAveCharWidth;
73 ptmA->tmMaxCharWidth = ptmW->tmMaxCharWidth;
74 ptmA->tmWeight = ptmW->tmWeight;
75 ptmA->tmOverhang = ptmW->tmOverhang;
76 ptmA->tmDigitizedAspectX = ptmW->tmDigitizedAspectX;
77 ptmA->tmDigitizedAspectY = ptmW->tmDigitizedAspectY;
78 ptmA->tmFirstChar = ptmW->tmFirstChar > 255 ? 255 : ptmW->tmFirstChar;
79 ptmA->tmLastChar = ptmW->tmLastChar > 255 ? 255 : ptmW->tmLastChar;
80 ptmA->tmDefaultChar = ptmW->tmDefaultChar > 255 ? 255 : ptmW->tmDefaultChar;
81 ptmA->tmBreakChar = ptmW->tmBreakChar > 255 ? 255 : ptmW->tmBreakChar;
82 ptmA->tmItalic = ptmW->tmItalic;
83 ptmA->tmUnderlined = ptmW->tmUnderlined;
84 ptmA->tmStruckOut = ptmW->tmStruckOut;
85 ptmA->tmPitchAndFamily = ptmW->tmPitchAndFamily;
86 ptmA->tmCharSet = ptmW->tmCharSet;
87 }
88
89 /***********************************************************************
90 * FONT_mbtowc
91 *
92 * Returns a Unicode translation of str using the charset of the
93 * currently selected font in hdc. If count is -1 then str is assumed
94 * to be '\0' terminated, otherwise it contains the number of bytes to
95 * convert. If plenW is non-NULL, on return it will point to the
96 * number of WCHARs that have been written. If pCP is non-NULL, on
97 * return it will point to the codepage used in the conversion. The
98 * caller should free the returned LPWSTR from the process heap
99 * itself.
100 */
101 static LPWSTR FONT_mbtowc(HDC hdc, LPCSTR str, INT count, INT *plenW, UINT *pCP)
102 {
103 UINT cp = GdiGetCodePage( hdc );
104 INT lenW;
105 LPWSTR strW;
106
107 if(count == -1) count = strlen(str);
108 lenW = MultiByteToWideChar(cp, 0, str, count, NULL, 0);
109 strW = HeapAlloc(GetProcessHeap(), 0, lenW*sizeof(WCHAR));
110 MultiByteToWideChar(cp, 0, str, count, strW, lenW);
111 DPRINT1("mapped %s -> %S\n", str, strW);
112 if(plenW) *plenW = lenW;
113 if(pCP) *pCP = cp;
114 return strW;
115 }
116
117
118 static BOOL FASTCALL
119 MetricsCharConvert(WCHAR w, UCHAR *b)
120 {
121 UNICODE_STRING WString;
122 WCHAR WBuf[2];
123 ANSI_STRING AString;
124 CHAR ABuf[2];
125 NTSTATUS Status;
126
127 if (L'\0' == w)
128 {
129 *b = '\0';
130 }
131 else
132 {
133 WBuf[0] = w;
134 WBuf[1] = L'\0';
135 RtlInitUnicodeString(&WString, WBuf);
136 ABuf[0] = '*';
137 ABuf[1] = L'\0';
138 RtlInitAnsiString(&AString, ABuf);
139
140 Status = RtlUnicodeStringToAnsiString(&AString, &WString, FALSE);
141 if (! NT_SUCCESS(Status))
142 {
143 SetLastError(RtlNtStatusToDosError(Status));
144 return FALSE;
145 }
146 *b = ABuf[0];
147 }
148
149 return TRUE;
150 }
151
152 BOOL FASTCALL
153 TextMetricW2A(TEXTMETRICA *tma, TEXTMETRICW *tmw)
154 {
155 UNICODE_STRING WString;
156 WCHAR WBuf[256];
157 ANSI_STRING AString;
158 CHAR ABuf[256];
159 UINT Letter;
160 NTSTATUS Status;
161
162 tma->tmHeight = tmw->tmHeight;
163 tma->tmAscent = tmw->tmAscent;
164 tma->tmDescent = tmw->tmDescent;
165 tma->tmInternalLeading = tmw->tmInternalLeading;
166 tma->tmExternalLeading = tmw->tmExternalLeading;
167 tma->tmAveCharWidth = tmw->tmAveCharWidth;
168 tma->tmMaxCharWidth = tmw->tmMaxCharWidth;
169 tma->tmWeight = tmw->tmWeight;
170 tma->tmOverhang = tmw->tmOverhang;
171 tma->tmDigitizedAspectX = tmw->tmDigitizedAspectX;
172 tma->tmDigitizedAspectY = tmw->tmDigitizedAspectY;
173
174 /* The Unicode FirstChar/LastChar need not correspond to the ANSI
175 FirstChar/LastChar. For example, if the font contains glyphs for
176 letters A-Z and an accented version of the letter e, the Unicode
177 FirstChar would be A and the Unicode LastChar would be the accented
178 e. If you just translate those to ANSI, the range would become
179 letters A-E instead of A-Z.
180 We translate all possible ANSI chars to Unicode and find the first
181 and last translated character which fall into the Unicode FirstChar/
182 LastChar range and return the corresponding ANSI char. */
183
184 /* Setup an Ansi string containing all possible letters (note: skip '\0' at
185 the beginning since that would be interpreted as end-of-string, handle
186 '\0' special later */
187 for (Letter = 1; Letter < 256; Letter++)
188 {
189 ABuf[Letter - 1] = (CHAR) Letter;
190 WBuf[Letter - 1] = L' ';
191 }
192 ABuf[255] = '\0';
193 WBuf[255] = L'\0';
194 RtlInitAnsiString(&AString, ABuf);
195 RtlInitUnicodeString(&WString, WBuf);
196
197 /* Find the corresponding Unicode characters */
198 Status = RtlAnsiStringToUnicodeString(&WString, &AString, FALSE);
199 if (! NT_SUCCESS(Status))
200 {
201 SetLastError(RtlNtStatusToDosError(Status));
202 return FALSE;
203 }
204
205 /* Scan for the first ANSI character which maps to an Unicode character
206 in the range */
207 tma->tmFirstChar = '\0';
208 if (L'\0' != tmw->tmFirstChar)
209 {
210 for (Letter = 1; Letter < 256; Letter++)
211 {
212 if (tmw->tmFirstChar <= WBuf[Letter - 1] &&
213 WBuf[Letter - 1] <= tmw->tmLastChar)
214 {
215 tma->tmFirstChar = (CHAR) Letter;
216 break;
217 }
218 }
219 }
220
221 /* Scan for the last ANSI character which maps to an Unicode character
222 in the range */
223 tma->tmLastChar = '\0';
224 if (L'\0' != tmw->tmLastChar)
225 {
226 for (Letter = 255; 0 < Letter; Letter--)
227 {
228 if (tmw->tmFirstChar <= WBuf[Letter - 1] &&
229 WBuf[Letter - 1] <= tmw->tmLastChar)
230 {
231 tma->tmLastChar = (CHAR) Letter;
232 break;
233 }
234 }
235 }
236
237 if (! MetricsCharConvert(tmw->tmDefaultChar, &tma->tmDefaultChar) ||
238 ! MetricsCharConvert(tmw->tmBreakChar, &tma->tmBreakChar))
239 {
240 return FALSE;
241 }
242
243 tma->tmItalic = tmw->tmItalic;
244 tma->tmUnderlined = tmw->tmUnderlined;
245 tma->tmStruckOut = tmw->tmStruckOut;
246 tma->tmPitchAndFamily = tmw->tmPitchAndFamily;
247 tma->tmCharSet = tmw->tmCharSet;
248
249 return TRUE;
250 }
251
252 BOOL FASTCALL
253 NewTextMetricW2A(NEWTEXTMETRICA *tma, NEWTEXTMETRICW *tmw)
254 {
255 if (! TextMetricW2A((TEXTMETRICA *) tma, (TEXTMETRICW *) tmw))
256 {
257 return FALSE;
258 }
259
260 tma->ntmFlags = tmw->ntmFlags;
261 tma->ntmSizeEM = tmw->ntmSizeEM;
262 tma->ntmCellHeight = tmw->ntmCellHeight;
263 tma->ntmAvgWidth = tmw->ntmAvgWidth;
264
265 return TRUE;
266 }
267
268 BOOL FASTCALL
269 NewTextMetricExW2A(NEWTEXTMETRICEXA *tma, NEWTEXTMETRICEXW *tmw)
270 {
271 if (! NewTextMetricW2A(&tma->ntmTm, &tmw->ntmTm))
272 {
273 return FALSE;
274 }
275
276 tma->ntmFontSig = tmw->ntmFontSig;
277
278 return TRUE;
279 }
280
281 static int FASTCALL
282 IntEnumFontFamilies(HDC Dc, LPLOGFONTW LogFont, PVOID EnumProc, LPARAM lParam,
283 BOOL Unicode)
284 {
285 int FontFamilyCount;
286 int FontFamilySize;
287 PFONTFAMILYINFO Info;
288 int Ret = 0;
289 int i;
290 ENUMLOGFONTEXA EnumLogFontExA;
291 NEWTEXTMETRICEXA NewTextMetricExA;
292
293 Info = RtlAllocateHeap(GetProcessHeap(), 0,
294 INITIAL_FAMILY_COUNT * sizeof(FONTFAMILYINFO));
295 if (NULL == Info)
296 {
297 return 0;
298 }
299 FontFamilyCount = NtGdiGetFontFamilyInfo(Dc, LogFont, Info, INITIAL_FAMILY_COUNT);
300 if (FontFamilyCount < 0)
301 {
302 RtlFreeHeap(GetProcessHeap(), 0, Info);
303 return 0;
304 }
305 if (INITIAL_FAMILY_COUNT < FontFamilyCount)
306 {
307 FontFamilySize = FontFamilyCount;
308 RtlFreeHeap(GetProcessHeap(), 0, Info);
309 Info = RtlAllocateHeap(GetProcessHeap(), 0,
310 FontFamilyCount * sizeof(FONTFAMILYINFO));
311 if (NULL == Info)
312 {
313 return 0;
314 }
315 FontFamilyCount = NtGdiGetFontFamilyInfo(Dc, LogFont, Info, FontFamilySize);
316 if (FontFamilyCount < 0 || FontFamilySize < FontFamilyCount)
317 {
318 RtlFreeHeap(GetProcessHeap(), 0, Info);
319 return 0;
320 }
321 }
322
323 for (i = 0; i < FontFamilyCount; i++)
324 {
325 if (Unicode)
326 {
327 Ret = ((FONTENUMPROCW) EnumProc)(
328 &Info[i].EnumLogFontEx,
329 &Info[i].NewTextMetricEx,
330 Info[i].FontType, lParam);
331 }
332 else
333 { // Could use EnumLogFontExW2A here?
334 LogFontW2A(&EnumLogFontExA.elfLogFont, &Info[i].EnumLogFontEx.elfLogFont);
335 WideCharToMultiByte(CP_THREAD_ACP, 0, Info[i].EnumLogFontEx.elfFullName, -1,
336 (LPSTR)EnumLogFontExA.elfFullName, LF_FULLFACESIZE, NULL, NULL);
337 WideCharToMultiByte(CP_THREAD_ACP, 0, Info[i].EnumLogFontEx.elfStyle, -1,
338 (LPSTR)EnumLogFontExA.elfStyle, LF_FACESIZE, NULL, NULL);
339 WideCharToMultiByte(CP_THREAD_ACP, 0, Info[i].EnumLogFontEx.elfScript, -1,
340 (LPSTR)EnumLogFontExA.elfScript, LF_FACESIZE, NULL, NULL);
341 NewTextMetricExW2A(&NewTextMetricExA,
342 &Info[i].NewTextMetricEx);
343 Ret = ((FONTENUMPROCA) EnumProc)(
344 &EnumLogFontExA,
345 &NewTextMetricExA,
346 Info[i].FontType, lParam);
347 }
348 }
349
350 RtlFreeHeap(GetProcessHeap(), 0, Info);
351
352 return Ret;
353 }
354
355 /*
356 * @implemented
357 */
358 int STDCALL
359 EnumFontFamiliesExW(HDC hdc, LPLOGFONTW lpLogfont, FONTENUMPROCW lpEnumFontFamExProc,
360 LPARAM lParam, DWORD dwFlags)
361 {
362 return IntEnumFontFamilies(hdc, lpLogfont, lpEnumFontFamExProc, lParam, TRUE);
363 }
364
365
366 /*
367 * @implemented
368 */
369 int STDCALL
370 EnumFontFamiliesW(HDC hdc, LPCWSTR lpszFamily, FONTENUMPROCW lpEnumFontFamProc,
371 LPARAM lParam)
372 {
373 LOGFONTW LogFont;
374
375 ZeroMemory(&LogFont, sizeof(LOGFONTW));
376 LogFont.lfCharSet = DEFAULT_CHARSET;
377 if (NULL != lpszFamily)
378 {
379 lstrcpynW(LogFont.lfFaceName, lpszFamily, LF_FACESIZE);
380 }
381
382 return IntEnumFontFamilies(hdc, &LogFont, lpEnumFontFamProc, lParam, TRUE);
383 }
384
385
386 /*
387 * @implemented
388 */
389 int STDCALL
390 EnumFontFamiliesExA (HDC hdc, LPLOGFONTA lpLogfont, FONTENUMPROCA lpEnumFontFamExProc,
391 LPARAM lParam, DWORD dwFlags)
392 {
393 LOGFONTW LogFontW, *pLogFontW;
394
395 if (lpLogfont)
396 {
397 LogFontA2W(&LogFontW,lpLogfont);
398 pLogFontW = &LogFontW;
399 }
400 else pLogFontW = NULL;
401
402 /* no need to convert LogFontW back to lpLogFont b/c it's an [in] parameter only */
403 return IntEnumFontFamilies(hdc, pLogFontW, lpEnumFontFamExProc, lParam, FALSE);
404 }
405
406
407 /*
408 * @implemented
409 */
410 int STDCALL
411 EnumFontFamiliesA(HDC hdc, LPCSTR lpszFamily, FONTENUMPROCA lpEnumFontFamProc,
412 LPARAM lParam)
413 {
414 LOGFONTW LogFont;
415
416 ZeroMemory(&LogFont, sizeof(LOGFONTW));
417 LogFont.lfCharSet = DEFAULT_CHARSET;
418 if (NULL != lpszFamily)
419 {
420 MultiByteToWideChar(CP_THREAD_ACP, 0, lpszFamily, -1, LogFont.lfFaceName, LF_FACESIZE);
421 }
422
423 return IntEnumFontFamilies(hdc, &LogFont, lpEnumFontFamProc, lParam, FALSE);
424 }
425
426 /*
427 * @implemented
428 */
429 DWORD
430 STDCALL
431 GetCharacterPlacementW(
432 HDC hdc,
433 LPCWSTR lpString,
434 INT uCount,
435 INT nMaxExtent,
436 GCP_RESULTSW *lpResults,
437 DWORD dwFlags
438 )
439 {
440 DWORD ret=0;
441 SIZE size;
442 UINT i, nSet;
443 DPRINT("GetCharacterPlacementW\n");
444
445 if(dwFlags&(~GCP_REORDER)) DPRINT("flags 0x%08lx ignored\n", dwFlags);
446 if(lpResults->lpClass) DPRINT("classes not implemented\n");
447 if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
448 DPRINT("Caret positions for complex scripts not implemented\n");
449
450 nSet = (UINT)uCount;
451 if(nSet > lpResults->nGlyphs)
452 nSet = lpResults->nGlyphs;
453
454 /* return number of initialized fields */
455 lpResults->nGlyphs = nSet;
456
457 /*if((dwFlags&GCP_REORDER)==0 || !BidiAvail)
458 {*/
459 /* Treat the case where no special handling was requested in a fastpath way */
460 /* copy will do if the GCP_REORDER flag is not set */
461 if(lpResults->lpOutString)
462 lstrcpynW( lpResults->lpOutString, lpString, nSet );
463
464 if(lpResults->lpGlyphs)
465 lstrcpynW( lpResults->lpGlyphs, lpString, nSet );
466
467 if(lpResults->lpOrder)
468 {
469 for(i = 0; i < nSet; i++)
470 lpResults->lpOrder[i] = i;
471 }
472 /*} else
473 {
474 BIDI_Reorder( lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
475 nSet, lpResults->lpOrder );
476 }*/
477
478 /* FIXME: Will use the placement chars */
479 if (lpResults->lpDx)
480 {
481 int c;
482 for (i = 0; i < nSet; i++)
483 {
484 if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
485 lpResults->lpDx[i]= c;
486 }
487 }
488
489 if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
490 {
491 int pos = 0;
492
493 lpResults->lpCaretPos[0] = 0;
494 for (i = 1; i < nSet; i++)
495 if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
496 lpResults->lpCaretPos[i] = (pos += size.cx);
497 }
498
499 /*if(lpResults->lpGlyphs)
500 NtGdiGetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);*/
501
502 if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
503 ret = MAKELONG(size.cx, size.cy);
504
505 return ret;
506 }
507
508 /*
509 * @implemented
510 *
511 */
512 BOOL
513 STDCALL
514 GetCharABCWidthsFloatW(HDC hdc,
515 UINT FirstChar,
516 UINT LastChar,
517 LPABCFLOAT abcF)
518 {
519 DPRINT("GetCharABCWidthsFloatW\n");
520 if ((!abcF) || (FirstChar > LastChar))
521 {
522 SetLastError(ERROR_INVALID_PARAMETER);
523 return FALSE;
524 }
525 return NtGdiGetCharABCWidthsW( hdc,
526 FirstChar,
527 (ULONG)(LastChar - FirstChar + 1),
528 (PWCHAR) NULL,
529 0,
530 (PVOID)abcF);
531 }
532
533 /*
534 * @implemented
535 *
536 */
537 BOOL
538 STDCALL
539 GetCharWidthFloatW(HDC hdc,
540 UINT iFirstChar,
541 UINT iLastChar,
542 PFLOAT pxBuffer)
543 {
544 DPRINT("GetCharWidthsFloatW\n");
545 if ((!pxBuffer) || (iFirstChar > iLastChar))
546 {
547 SetLastError(ERROR_INVALID_PARAMETER);
548 return FALSE;
549 }
550 return NtGdiGetCharWidthW( hdc,
551 iFirstChar,
552 (ULONG)(iLastChar - iFirstChar + 1),
553 (PWCHAR) NULL,
554 0,
555 (PVOID) pxBuffer);
556 }
557
558 /*
559 * @implemented
560 *
561 */
562 BOOL
563 STDCALL
564 GetCharWidthW(HDC hdc,
565 UINT iFirstChar,
566 UINT iLastChar,
567 LPINT lpBuffer)
568 {
569 DPRINT("GetCharWidthsW\n");
570 if ((!lpBuffer) || (iFirstChar > iLastChar))
571 {
572 SetLastError(ERROR_INVALID_PARAMETER);
573 return FALSE;
574 }
575 return NtGdiGetCharWidthW( hdc,
576 iFirstChar,
577 (ULONG)(iLastChar - iFirstChar + 1),
578 (PWCHAR) NULL,
579 GCW_NOFLOAT,
580 (PVOID) lpBuffer);
581 }
582
583 /*
584 * @implemented
585 *
586 */
587 BOOL
588 STDCALL
589 GetCharWidth32W(HDC hdc,
590 UINT iFirstChar,
591 UINT iLastChar,
592 LPINT lpBuffer)
593 {
594 DPRINT("GetCharWidths32W\n");
595 if ((!lpBuffer) || (iFirstChar > iLastChar))
596 {
597 SetLastError(ERROR_INVALID_PARAMETER);
598 return FALSE;
599 }
600 return NtGdiGetCharWidthW( hdc,
601 iFirstChar,
602 (ULONG)(iLastChar - iFirstChar + 1),
603 (PWCHAR) NULL,
604 GCW_NOFLOAT|GCW_WIN32,
605 (PVOID) lpBuffer);
606 }
607
608
609 /*
610 * @implemented
611 *
612 */
613 BOOL
614 STDCALL
615 GetCharABCWidthsW(HDC hdc,
616 UINT FirstChar,
617 UINT LastChar,
618 LPABC lpabc)
619 {
620 DPRINT("GetCharABCWidthsW\n");
621 if ((!lpabc) || (FirstChar > LastChar))
622 {
623 SetLastError(ERROR_INVALID_PARAMETER);
624 return FALSE;
625 }
626 return NtGdiGetCharABCWidthsW( hdc,
627 FirstChar,
628 (ULONG)(LastChar - FirstChar + 1),
629 (PWCHAR) NULL,
630 GCABCW_NOFLOAT,
631 (PVOID)lpabc);
632 }
633
634 /*
635 * @implemented
636 */
637 BOOL
638 STDCALL
639 GetCharWidthA(
640 HDC hdc,
641 UINT iFirstChar,
642 UINT iLastChar,
643 LPINT lpBuffer
644 )
645 {
646 INT i, wlen, count = (INT)(iLastChar - iFirstChar + 1);
647 LPSTR str;
648 LPWSTR wstr;
649 BOOL ret = TRUE;
650
651 DPRINT("GetCharWidthsA\n");
652 if(count <= 0) return FALSE;
653
654 str = HeapAlloc(GetProcessHeap(), 0, count+1);
655 if (!str)
656 return FALSE;
657
658 for(i = 0; i < count; i++)
659 str[i] = (BYTE)(iFirstChar + i);
660 str[i] = '\0';
661
662 wstr = FONT_mbtowc(hdc, str, count+1, &wlen, NULL);
663 if (!wstr)
664 {
665 HeapFree(GetProcessHeap(), 0, str);
666 return FALSE;
667 }
668
669 ret = NtGdiGetCharWidthW( hdc,
670 wstr[0],
671 (ULONG) count,
672 (PWCHAR) wstr,
673 GCW_NOFLOAT,
674 (PVOID) lpBuffer);
675
676 HeapFree(GetProcessHeap(), 0, str);
677 HeapFree(GetProcessHeap(), 0, wstr);
678
679 return ret;
680 }
681
682 /*
683 * @implemented
684 */
685 BOOL
686 STDCALL
687 GetCharWidth32A(
688 HDC hdc,
689 UINT iFirstChar,
690 UINT iLastChar,
691 LPINT lpBuffer
692 )
693 {
694 INT i, wlen, count = (INT)(iLastChar - iFirstChar + 1);
695 LPSTR str;
696 LPWSTR wstr;
697 BOOL ret = TRUE;
698
699 DPRINT("GetCharWidths32A\n");
700 if(count <= 0) return FALSE;
701
702 str = HeapAlloc(GetProcessHeap(), 0, count+1);
703 if (!str)
704 return FALSE;
705 for(i = 0; i < count; i++)
706 str[i] = (BYTE)(iFirstChar + i);
707 str[i] = '\0';
708
709 wstr = FONT_mbtowc(hdc, str, count+1, &wlen, NULL);
710 if (!wstr)
711 {
712 HeapFree(GetProcessHeap(), 0, str);
713 return FALSE;
714 }
715
716 ret = NtGdiGetCharWidthW( hdc,
717 wstr[0],
718 (ULONG) count,
719 (PWCHAR) wstr,
720 GCW_NOFLOAT|GCW_WIN32,
721 (PVOID) lpBuffer);
722
723 HeapFree(GetProcessHeap(), 0, str);
724 HeapFree(GetProcessHeap(), 0, wstr);
725
726 return ret;
727 }
728
729 /*
730 * @implemented
731 */
732 BOOL
733 APIENTRY
734 GetCharWidthFloatA(
735 HDC hdc,
736 UINT iFirstChar,
737 UINT iLastChar,
738 PFLOAT pxBuffer
739 )
740 {
741 INT i, wlen, count = (INT)(iLastChar - iFirstChar + 1);
742 LPSTR str;
743 LPWSTR wstr;
744 BOOL ret = TRUE;
745
746 DPRINT("GetCharWidthsFloatA\n");
747 if(count <= 0) return FALSE;
748
749 str = HeapAlloc(GetProcessHeap(), 0, count+1);
750 if (!str)
751 return FALSE;
752 for(i = 0; i < count; i++)
753 str[i] = (BYTE)(iFirstChar + i);
754 str[i] = '\0';
755
756 wstr = FONT_mbtowc(hdc, str, count+1, &wlen, NULL);
757 if (!wstr)
758 {
759 HeapFree(GetProcessHeap(), 0, str);
760 return FALSE;
761 }
762 ret = NtGdiGetCharWidthW( hdc, wstr[0], (ULONG) count, (PWCHAR) wstr, 0, (PVOID) pxBuffer);
763
764 HeapFree(GetProcessHeap(), 0, str);
765 HeapFree(GetProcessHeap(), 0, wstr);
766
767 return ret;
768 }
769
770 /*
771 * @implemented
772 */
773 BOOL
774 APIENTRY
775 GetCharABCWidthsA(
776 HDC hdc,
777 UINT uFirstChar,
778 UINT uLastChar,
779 LPABC lpabc
780 )
781 {
782 INT i, wlen, count = (INT)(uLastChar - uFirstChar + 1);
783 LPSTR str;
784 LPWSTR wstr;
785 BOOL ret = TRUE;
786
787 DPRINT("GetCharABCWidthsA\n");
788 if(count <= 0) return FALSE;
789
790 str = HeapAlloc(GetProcessHeap(), 0, count+1);
791 if (!str)
792 return FALSE;
793 for(i = 0; i < count; i++)
794 str[i] = (BYTE)(uFirstChar + i);
795 str[i] = '\0';
796
797 wstr = FONT_mbtowc(hdc, str, count+1, &wlen, NULL);
798 if (!wstr)
799 {
800 HeapFree(GetProcessHeap(), 0, str);
801 return FALSE;
802 }
803
804 ret = NtGdiGetCharABCWidthsW( hdc,
805 wstr[0],
806 (ULONG)count,
807 (PWCHAR)wstr,
808 GCABCW_NOFLOAT,
809 (PVOID)lpabc);
810
811 HeapFree(GetProcessHeap(), 0, str);
812 HeapFree(GetProcessHeap(), 0, wstr);
813
814 return ret;
815 }
816
817 /*
818 * @implemented
819 */
820 BOOL
821 APIENTRY
822 GetCharABCWidthsFloatA(
823 HDC hdc,
824 UINT iFirstChar,
825 UINT iLastChar,
826 LPABCFLOAT lpABCF
827 )
828 {
829 INT i, wlen, count = (INT)(iLastChar - iFirstChar + 1);
830 LPSTR str;
831 LPWSTR wstr;
832 BOOL ret = TRUE;
833
834 DPRINT("GetCharABCWidthsFloatA\n");
835 if (count <= 0) return FALSE;
836
837 str = HeapAlloc(GetProcessHeap(), 0, count+1);
838 if (!str)
839 return FALSE;
840
841 for(i = 0; i < count; i++)
842 str[i] = (BYTE)(iFirstChar + i);
843 str[i] = '\0';
844
845 wstr = FONT_mbtowc( hdc, str, count+1, &wlen, NULL );
846 if (!wstr)
847 {
848 HeapFree( GetProcessHeap(), 0, str );
849 return FALSE;
850 }
851 ret = NtGdiGetCharABCWidthsW( hdc,wstr[0],(ULONG)count, (PWCHAR)wstr, 0, (PVOID)lpABCF);
852
853 HeapFree( GetProcessHeap(), 0, str );
854 HeapFree( GetProcessHeap(), 0, wstr );
855
856 return ret;
857 }
858
859 /*
860 * @implemented
861 */
862 BOOL
863 STDCALL
864 GetCharABCWidthsI(HDC hdc,
865 UINT giFirst,
866 UINT cgi,
867 LPWORD pgi,
868 LPABC lpabc)
869 {
870 DPRINT("GetCharABCWidthsI\n");
871 return NtGdiGetCharABCWidthsW( hdc,
872 giFirst,
873 (ULONG) cgi,
874 (PWCHAR) pgi,
875 GCABCW_NOFLOAT|GCABCW_INDICES,
876 (PVOID)lpabc);
877 }
878
879 /*
880 * @implemented
881 */
882 BOOL
883 STDCALL
884 GetCharWidthI(HDC hdc,
885 UINT giFirst,
886 UINT cgi,
887 LPWORD pgi,
888 LPINT lpBuffer
889 )
890 {
891 DPRINT("GetCharWidthsI\n");
892 if (!lpBuffer || (!pgi && (giFirst == MAXUSHORT))) // Cannot be at max.
893 {
894 SetLastError(ERROR_INVALID_PARAMETER);
895 return FALSE;
896 }
897 if (!cgi) return TRUE;
898 return NtGdiGetCharWidthW( hdc,
899 giFirst,
900 cgi,
901 (PWCHAR) pgi,
902 GCW_INDICES|GCW_NOFLOAT|GCW_WIN32,
903 (PVOID) lpBuffer );
904 }
905
906 /*
907 * @implemented
908 */
909 DWORD
910 STDCALL
911 GetFontLanguageInfo(
912 HDC hDc
913 )
914 {
915 return GetDCDWord(hDc, GdiGetFontLanguageInfo, GCP_ERROR);
916 }
917
918 /*
919 * @implemented
920 */
921 DWORD
922 STDCALL
923 GetGlyphIndicesA(
924 HDC hdc,
925 LPCSTR lpstr,
926 INT count,
927 LPWORD pgi,
928 DWORD flags
929 )
930 {
931 DWORD Ret;
932 WCHAR *lpstrW;
933 INT countW;
934
935 lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
936 Ret = NtGdiGetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
937 HeapFree(GetProcessHeap(), 0, lpstrW);
938 return Ret;
939 }
940
941 /*
942 * @implemented
943 */
944 DWORD
945 STDCALL
946 GetGlyphOutlineA(
947 HDC hdc,
948 UINT uChar,
949 UINT uFormat,
950 LPGLYPHMETRICS lpgm,
951 DWORD cbBuffer,
952 LPVOID lpvBuffer,
953 CONST MAT2 *lpmat2
954 )
955 {
956
957 LPWSTR p = NULL;
958 DWORD ret;
959 UINT c;
960 DPRINT1("GetGlyphOutlineA uChar %x\n", uChar);
961 if(!(uFormat & GGO_GLYPH_INDEX)) {
962 int len;
963 char mbchs[2];
964 if(uChar > 0xff) { /* but, 2 bytes character only */
965 len = 2;
966 mbchs[0] = (uChar & 0xff00) >> 8;
967 mbchs[1] = (uChar & 0xff);
968 } else {
969 len = 1;
970 mbchs[0] = (uChar & 0xff);
971 }
972 p = FONT_mbtowc(hdc, mbchs, len, NULL, NULL);
973 c = p[0];
974 } else
975 c = uChar;
976 ret = NtGdiGetGlyphOutline(hdc, c, uFormat, lpgm, cbBuffer, lpvBuffer, (CONST LPMAT2)lpmat2, TRUE);
977 HeapFree(GetProcessHeap(), 0, p);
978 return ret;
979 }
980
981
982 /*
983 * @implemented
984 */
985 DWORD
986 STDCALL
987 GetGlyphOutlineW(
988 HDC hdc,
989 UINT uChar,
990 UINT uFormat,
991 LPGLYPHMETRICS lpgm,
992 DWORD cbBuffer,
993 LPVOID lpvBuffer,
994 CONST MAT2 *lpmat2
995 )
996 {
997 DPRINT("GetGlyphOutlineW uChar %x\n", uChar);
998 if (!lpgm & !lpmat2) return GDI_ERROR;
999 if (!lpvBuffer) cbBuffer = 0;
1000 return NtGdiGetGlyphOutline ( hdc, uChar, uFormat, lpgm, cbBuffer, lpvBuffer, (CONST LPMAT2)lpmat2, TRUE);
1001 }
1002
1003
1004 /*
1005 * @implemented
1006 */
1007 UINT
1008 APIENTRY
1009 GetOutlineTextMetricsA(
1010 HDC hdc,
1011 UINT cbData,
1012 LPOUTLINETEXTMETRICA lpOTM
1013 )
1014 {
1015 char buf[512], *ptr;
1016 UINT ret, needed;
1017 OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1018 OUTLINETEXTMETRICA *output = lpOTM;
1019 INT left, len;
1020
1021 if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1022 return 0;
1023 if(ret > sizeof(buf))
1024 lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1025 GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1026
1027 needed = sizeof(OUTLINETEXTMETRICA);
1028 if(lpOTMW->otmpFamilyName)
1029 needed += WideCharToMultiByte(CP_ACP, 0,
1030 (WCHAR*)((char*)lpOTMW + (int)lpOTMW->otmpFamilyName), -1,
1031 NULL, 0, NULL, NULL);
1032 if(lpOTMW->otmpFaceName)
1033 needed += WideCharToMultiByte(CP_ACP, 0,
1034 (WCHAR*)((char*)lpOTMW + (int)lpOTMW->otmpFaceName), -1,
1035 NULL, 0, NULL, NULL);
1036 if(lpOTMW->otmpStyleName)
1037 needed += WideCharToMultiByte(CP_ACP, 0,
1038 (WCHAR*)((char*)lpOTMW + (int)lpOTMW->otmpStyleName), -1,
1039 NULL, 0, NULL, NULL);
1040 if(lpOTMW->otmpFullName)
1041 needed += WideCharToMultiByte(CP_ACP, 0,
1042 (WCHAR*)((char*)lpOTMW + (int)lpOTMW->otmpFullName), -1,
1043 NULL, 0, NULL, NULL);
1044
1045 if(!lpOTM) {
1046 ret = needed;
1047 goto end;
1048 }
1049
1050 DPRINT("needed = %d\n", needed);
1051 if(needed > cbData)
1052 /* Since the supplied buffer isn't big enough, we'll alloc one
1053 that is and memcpy the first cbData bytes into the lpOTM at
1054 the end. */
1055 output = HeapAlloc(GetProcessHeap(), 0, needed);
1056
1057 ret = output->otmSize = min(needed, cbData);
1058 FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1059 output->otmFiller = 0;
1060 output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1061 output->otmfsSelection = lpOTMW->otmfsSelection;
1062 output->otmfsType = lpOTMW->otmfsType;
1063 output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1064 output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1065 output->otmItalicAngle = lpOTMW->otmItalicAngle;
1066 output->otmEMSquare = lpOTMW->otmEMSquare;
1067 output->otmAscent = lpOTMW->otmAscent;
1068 output->otmDescent = lpOTMW->otmDescent;
1069 output->otmLineGap = lpOTMW->otmLineGap;
1070 output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1071 output->otmsXHeight = lpOTMW->otmsXHeight;
1072 output->otmrcFontBox = lpOTMW->otmrcFontBox;
1073 output->otmMacAscent = lpOTMW->otmMacAscent;
1074 output->otmMacDescent = lpOTMW->otmMacDescent;
1075 output->otmMacLineGap = lpOTMW->otmMacLineGap;
1076 output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1077 output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1078 output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1079 output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1080 output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1081 output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1082 output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1083 output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1084 output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1085
1086
1087 ptr = (char*)(output + 1);
1088 left = needed - sizeof(*output);
1089
1090 if(lpOTMW->otmpFamilyName) {
1091 output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1092 len = WideCharToMultiByte(CP_ACP, 0,
1093 (WCHAR*)((char*)lpOTMW + (int)lpOTMW->otmpFamilyName), -1,
1094 ptr, left, NULL, NULL);
1095 left -= len;
1096 ptr += len;
1097 } else
1098 output->otmpFamilyName = 0;
1099
1100 if(lpOTMW->otmpFaceName) {
1101 output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1102 len = WideCharToMultiByte(CP_ACP, 0,
1103 (WCHAR*)((char*)lpOTMW + (int)lpOTMW->otmpFaceName), -1,
1104 ptr, left, NULL, NULL);
1105 left -= len;
1106 ptr += len;
1107 } else
1108 output->otmpFaceName = 0;
1109
1110 if(lpOTMW->otmpStyleName) {
1111 output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1112 len = WideCharToMultiByte(CP_ACP, 0,
1113 (WCHAR*)((char*)lpOTMW + (int)lpOTMW->otmpStyleName), -1,
1114 ptr, left, NULL, NULL);
1115 left -= len;
1116 ptr += len;
1117 } else
1118 output->otmpStyleName = 0;
1119
1120 if(lpOTMW->otmpFullName) {
1121 output->otmpFullName = (LPSTR)(ptr - (char*)output);
1122 len = WideCharToMultiByte(CP_ACP, 0,
1123 (WCHAR*)((char*)lpOTMW + (int)lpOTMW->otmpFullName), -1,
1124 ptr, left, NULL, NULL);
1125 left -= len;
1126 } else
1127 output->otmpFullName = 0;
1128
1129 assert(left == 0);
1130
1131 if(output != lpOTM) {
1132 memcpy(lpOTM, output, cbData);
1133 HeapFree(GetProcessHeap(), 0, output);
1134
1135 /* check if the string offsets really fit into the provided size */
1136 /* FIXME: should we check string length as well? */
1137 if ((UINT_PTR)lpOTM->otmpFamilyName >= lpOTM->otmSize)
1138 lpOTM->otmpFamilyName = 0; /* doesn't fit */
1139
1140 if ((UINT_PTR)lpOTM->otmpFaceName >= lpOTM->otmSize)
1141 lpOTM->otmpFaceName = 0; /* doesn't fit */
1142
1143 if ((UINT_PTR)lpOTM->otmpStyleName >= lpOTM->otmSize)
1144 lpOTM->otmpStyleName = 0; /* doesn't fit */
1145
1146 if ((UINT_PTR)lpOTM->otmpFullName >= lpOTM->otmSize)
1147 lpOTM->otmpFullName = 0; /* doesn't fit */
1148 }
1149
1150 end:
1151 if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1152 HeapFree(GetProcessHeap(), 0, lpOTMW);
1153
1154 return ret;
1155 }
1156
1157
1158 /*
1159 * @implemented
1160 */
1161 UINT
1162 APIENTRY
1163 GetOutlineTextMetricsW(
1164 HDC hdc,
1165 UINT cbData,
1166 LPOUTLINETEXTMETRICW lpOTM
1167 )
1168 {
1169 TMDIFF Tmd; // Should not be zero.
1170
1171 return NtGdiGetOutlineTextMetricsInternalW(hdc, cbData, lpOTM, &Tmd);
1172 }
1173
1174 /*
1175 * @implemented
1176 */
1177 DWORD
1178 STDCALL
1179 GetKerningPairsW(HDC hdc,
1180 ULONG cPairs,
1181 LPKERNINGPAIR pkpDst)
1182 {
1183 if ((cPairs != 0) || (pkpDst == 0))
1184 {
1185 return NtGdiGetKerningPairs(hdc,cPairs,pkpDst);
1186 }
1187 else
1188 {
1189 SetLastError(ERROR_INVALID_PARAMETER);
1190 return 0;
1191 }
1192 }
1193
1194 /*
1195 * @implemented
1196 */
1197 DWORD
1198 STDCALL
1199 GetKerningPairsA( HDC hDC,
1200 DWORD cPairs,
1201 LPKERNINGPAIR kern_pairA )
1202 {
1203 INT charset;
1204 CHARSETINFO csi;
1205 CPINFO cpi;
1206 DWORD i, total_kern_pairs, kern_pairs_copied = 0;
1207 KERNINGPAIR *kern_pairW;
1208
1209 if (!cPairs && kern_pairA)
1210 {
1211 SetLastError(ERROR_INVALID_PARAMETER);
1212 return 0;
1213 }
1214
1215 charset = GetTextCharset(hDC);
1216 if (!TranslateCharsetInfo(ULongToPtr(charset), &csi, TCI_SRCCHARSET))
1217 {
1218 DPRINT1("Can't find codepage for charset %d\n", charset);
1219 return 0;
1220 }
1221 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
1222 * to fail on an invalid character for CP_SYMBOL.
1223 */
1224 cpi.DefaultChar[0] = 0;
1225 if (csi.ciACP != CP_SYMBOL && !GetCPInfo(csi.ciACP, &cpi))
1226 {
1227 DPRINT1("Can't find codepage %u info\n", csi.ciACP);
1228 return 0;
1229 }
1230 DPRINT("charset %d => codepage %u\n", charset, csi.ciACP);
1231
1232 total_kern_pairs = NtGdiGetKerningPairs(hDC, 0, NULL);
1233 if (!total_kern_pairs) return 0;
1234
1235 if (!cPairs && !kern_pairA) return total_kern_pairs;
1236
1237 kern_pairW = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW));
1238 GetKerningPairsW(hDC, total_kern_pairs, kern_pairW);
1239
1240 for (i = 0; i < total_kern_pairs; i++)
1241 {
1242 char first, second;
1243
1244 if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL))
1245 continue;
1246
1247 if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL))
1248 continue;
1249
1250 if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0])
1251 continue;
1252
1253 if (kern_pairA)
1254 {
1255 if (kern_pairs_copied >= cPairs) break;
1256
1257 kern_pairA->wFirst = (BYTE)first;
1258 kern_pairA->wSecond = (BYTE)second;
1259 kern_pairA->iKernAmount = kern_pairW[i].iKernAmount;
1260 kern_pairA++;
1261 }
1262 kern_pairs_copied++;
1263 }
1264
1265 HeapFree(GetProcessHeap(), 0, kern_pairW);
1266
1267 return kern_pairs_copied;
1268 }
1269
1270
1271
1272 /*
1273 * @implemented
1274 */
1275 HFONT
1276 STDCALL
1277 CreateFontIndirectExA(const ENUMLOGFONTEXDVA *elfexd)
1278 {
1279 if (elfexd)
1280 {
1281 ENUMLOGFONTEXDVW Logfont;
1282
1283 EnumLogFontExW2A( (LPENUMLOGFONTEXA) elfexd,
1284 &Logfont.elfEnumLogfontEx );
1285
1286 RtlCopyMemory( &Logfont.elfDesignVector,
1287 (PVOID) &elfexd->elfDesignVector,
1288 sizeof(DESIGNVECTOR));
1289
1290 return NtGdiHfontCreate( &Logfont, 0, 0, 0, NULL);
1291 }
1292 else return NULL;
1293 }
1294
1295
1296 /*
1297 * @implemented
1298 */
1299 HFONT
1300 STDCALL
1301 CreateFontIndirectExW(const ENUMLOGFONTEXDVW *elfexd)
1302 {
1303 /* Msdn: Note, this function ignores the elfDesignVector member in
1304 ENUMLOGFONTEXDV.
1305 */
1306 if ( elfexd )
1307 {
1308 return NtGdiHfontCreate((PENUMLOGFONTEXDVW) elfexd, 0, 0, 0, NULL );
1309 }
1310 else return NULL;
1311 }
1312
1313
1314 /*
1315 * @implemented
1316 */
1317 HFONT
1318 STDCALL
1319 CreateFontIndirectA(
1320 CONST LOGFONTA *lplf
1321 )
1322 {
1323 if (lplf)
1324 {
1325 LOGFONTW tlf;
1326
1327 LogFontA2W(&tlf, lplf);
1328 return CreateFontIndirectW(&tlf);
1329 }
1330 else return NULL;
1331 }
1332
1333
1334 /*
1335 * @implemented
1336 */
1337 HFONT
1338 STDCALL
1339 CreateFontIndirectW(
1340 CONST LOGFONTW *lplf
1341 )
1342 {
1343 if (lplf)
1344 {
1345 ENUMLOGFONTEXDVW Logfont;
1346
1347 RtlCopyMemory( &Logfont.elfEnumLogfontEx.elfLogFont, lplf, sizeof(LOGFONTW));
1348 // Need something other than just cleaning memory here.
1349 // Guess? Use caller data to determine the rest.
1350 RtlZeroMemory( &Logfont.elfEnumLogfontEx.elfFullName,
1351 sizeof(Logfont.elfEnumLogfontEx.elfFullName));
1352 RtlZeroMemory( &Logfont.elfEnumLogfontEx.elfStyle,
1353 sizeof(Logfont.elfEnumLogfontEx.elfStyle));
1354 RtlZeroMemory( &Logfont.elfEnumLogfontEx.elfScript,
1355 sizeof(Logfont.elfEnumLogfontEx.elfScript));
1356
1357 Logfont.elfDesignVector.dvNumAxes = 0; // No more than MM_MAX_NUMAXES
1358
1359 RtlZeroMemory( &Logfont.elfDesignVector, sizeof(DESIGNVECTOR));
1360
1361 return CreateFontIndirectExW(&Logfont);
1362 }
1363 else return NULL;
1364 }
1365
1366
1367 /*
1368 * @implemented
1369 */
1370 HFONT
1371 STDCALL
1372 CreateFontA(
1373 int nHeight,
1374 int nWidth,
1375 int nEscapement,
1376 int nOrientation,
1377 int fnWeight,
1378 DWORD fdwItalic,
1379 DWORD fdwUnderline,
1380 DWORD fdwStrikeOut,
1381 DWORD fdwCharSet,
1382 DWORD fdwOutputPrecision,
1383 DWORD fdwClipPrecision,
1384 DWORD fdwQuality,
1385 DWORD fdwPitchAndFamily,
1386 LPCSTR lpszFace
1387 )
1388 {
1389 ANSI_STRING StringA;
1390 UNICODE_STRING StringU;
1391 HFONT ret;
1392
1393 RtlInitAnsiString(&StringA, (LPSTR)lpszFace);
1394 RtlAnsiStringToUnicodeString(&StringU, &StringA, TRUE);
1395
1396 ret = CreateFontW(nHeight,
1397 nWidth,
1398 nEscapement,
1399 nOrientation,
1400 fnWeight,
1401 fdwItalic,
1402 fdwUnderline,
1403 fdwStrikeOut,
1404 fdwCharSet,
1405 fdwOutputPrecision,
1406 fdwClipPrecision,
1407 fdwQuality,
1408 fdwPitchAndFamily,
1409 StringU.Buffer);
1410
1411 RtlFreeUnicodeString(&StringU);
1412
1413 return ret;
1414 }
1415
1416
1417 /*
1418 * @implemented
1419 */
1420 HFONT
1421 STDCALL
1422 CreateFontW(
1423 int nHeight,
1424 int nWidth,
1425 int nEscapement,
1426 int nOrientation,
1427 int nWeight,
1428 DWORD fnItalic,
1429 DWORD fdwUnderline,
1430 DWORD fdwStrikeOut,
1431 DWORD fdwCharSet,
1432 DWORD fdwOutputPrecision,
1433 DWORD fdwClipPrecision,
1434 DWORD fdwQuality,
1435 DWORD fdwPitchAndFamily,
1436 LPCWSTR lpszFace
1437 )
1438 {
1439 LOGFONTW logfont;
1440
1441 logfont.lfHeight = nHeight;
1442 logfont.lfWidth = nWidth;
1443 logfont.lfEscapement = nEscapement;
1444 logfont.lfOrientation = nOrientation;
1445 logfont.lfWeight = nWeight;
1446 logfont.lfItalic = fnItalic;
1447 logfont.lfUnderline = fdwUnderline;
1448 logfont.lfStrikeOut = fdwStrikeOut;
1449 logfont.lfCharSet = fdwCharSet;
1450 logfont.lfOutPrecision = fdwOutputPrecision;
1451 logfont.lfClipPrecision = fdwClipPrecision;
1452 logfont.lfQuality = fdwQuality;
1453 logfont.lfPitchAndFamily = fdwPitchAndFamily;
1454
1455 if (NULL != lpszFace)
1456 {
1457 int Size = sizeof(logfont.lfFaceName) / sizeof(WCHAR);
1458 wcsncpy((wchar_t *)logfont.lfFaceName, lpszFace, Size - 1);
1459 /* Be 101% sure to have '\0' at end of string */
1460 logfont.lfFaceName[Size - 1] = '\0';
1461 }
1462 else
1463 {
1464 logfont.lfFaceName[0] = L'\0';
1465 }
1466
1467 return CreateFontIndirectW(&logfont);
1468 }
1469
1470
1471 /*
1472 * @unimplemented
1473 */
1474 BOOL
1475 STDCALL
1476 CreateScalableFontResourceA(
1477 DWORD fdwHidden,
1478 LPCSTR lpszFontRes,
1479 LPCSTR lpszFontFile,
1480 LPCSTR lpszCurrentPath
1481 )
1482 {
1483 return FALSE;
1484 }
1485
1486
1487 /*
1488 * @implemented
1489 */
1490 int
1491 STDCALL
1492 AddFontResourceExW ( LPCWSTR lpszFilename, DWORD fl, PVOID pvReserved )
1493 {
1494 if (fl & ~(FR_PRIVATE | FR_NOT_ENUM))
1495 {
1496 SetLastError( ERROR_INVALID_PARAMETER );
1497 return 0;
1498 }
1499
1500 return GdiAddFontResourceW(lpszFilename, fl,0);
1501 }
1502
1503
1504 /*
1505 * @implemented
1506 */
1507 int
1508 STDCALL
1509 AddFontResourceExA ( LPCSTR lpszFilename, DWORD fl, PVOID pvReserved )
1510 {
1511 NTSTATUS Status;
1512 PWSTR FilenameW;
1513 int rc;
1514
1515 if (fl & ~(FR_PRIVATE | FR_NOT_ENUM))
1516 {
1517 SetLastError( ERROR_INVALID_PARAMETER );
1518 return 0;
1519 }
1520
1521 Status = HEAP_strdupA2W ( &FilenameW, lpszFilename );
1522 if ( !NT_SUCCESS (Status) )
1523 {
1524 SetLastError (RtlNtStatusToDosError(Status));
1525 return 0;
1526 }
1527
1528 rc = GdiAddFontResourceW ( FilenameW, fl, 0 );
1529 HEAP_free ( FilenameW );
1530 return rc;
1531 }
1532
1533
1534 /*
1535 * @implemented
1536 */
1537 int
1538 STDCALL
1539 AddFontResourceA ( LPCSTR lpszFilename )
1540 {
1541 NTSTATUS Status;
1542 PWSTR FilenameW;
1543 int rc = 0;
1544
1545 Status = HEAP_strdupA2W ( &FilenameW, lpszFilename );
1546 if ( !NT_SUCCESS (Status) )
1547 {
1548 SetLastError (RtlNtStatusToDosError(Status));
1549 }
1550 else
1551 {
1552 rc = GdiAddFontResourceW ( FilenameW, 0, 0);
1553
1554 HEAP_free ( FilenameW );
1555 }
1556 return rc;
1557 }
1558
1559
1560 /*
1561 * @implemented
1562 */
1563 int
1564 STDCALL
1565 AddFontResourceW ( LPCWSTR lpszFilename )
1566 {
1567 return GdiAddFontResourceW ( lpszFilename, 0, 0 );
1568 }
1569
1570
1571 /*
1572 * @implemented
1573 */
1574 BOOL
1575 STDCALL
1576 RemoveFontResourceW(LPCWSTR lpFileName)
1577 {
1578 return RemoveFontResourceExW(lpFileName,0,0);
1579 }
1580
1581
1582 /*
1583 * @implemented
1584 */
1585 BOOL
1586 STDCALL
1587 RemoveFontResourceA(LPCSTR lpFileName)
1588 {
1589 return RemoveFontResourceExA(lpFileName,0,0);
1590 }
1591
1592 /*
1593 * @unimplemented
1594 */
1595 BOOL
1596 STDCALL
1597 RemoveFontResourceExA(LPCSTR lpFileName,
1598 DWORD fl,
1599 PVOID pdv
1600 )
1601 {
1602 NTSTATUS Status;
1603 LPWSTR lpFileNameW;
1604
1605 /* FIXME the flags */
1606 /* FIXME the pdv */
1607 /* FIXME NtGdiRemoveFontResource handle flags and pdv */
1608
1609 Status = HEAP_strdupA2W ( &lpFileNameW, lpFileName );
1610 if (!NT_SUCCESS (Status))
1611 SetLastError (RtlNtStatusToDosError(Status));
1612 else
1613 {
1614
1615 HEAP_free ( lpFileNameW );
1616 }
1617
1618 return 0;
1619 }
1620
1621 /*
1622 * @unimplemented
1623 */
1624 BOOL
1625 STDCALL
1626 RemoveFontResourceExW(LPCWSTR lpFileName,
1627 DWORD fl,
1628 PVOID pdv)
1629 {
1630 /* FIXME the flags */
1631 /* FIXME the pdv */
1632 /* FIXME NtGdiRemoveFontResource handle flags and pdv */
1633 return 0;
1634 }
1635
1636
1637 /***********************************************************************
1638 * GdiGetCharDimensions
1639 *
1640 * Gets the average width of the characters in the English alphabet.
1641 *
1642 * PARAMS
1643 * hdc [I] Handle to the device context to measure on.
1644 * lptm [O] Pointer to memory to store the text metrics into.
1645 * height [O] On exit, the maximum height of characters in the English alphabet.
1646 *
1647 * RETURNS
1648 * The average width of characters in the English alphabet.
1649 *
1650 * NOTES
1651 * This function is used by the dialog manager to get the size of a dialog
1652 * unit. It should also be used by other pieces of code that need to know
1653 * the size of a dialog unit in logical units without having access to the
1654 * window handle of the dialog.
1655 * Windows caches the font metrics from this function, but we don't and
1656 * there doesn't appear to be an immediate advantage to do so.
1657 *
1658 * SEE ALSO
1659 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
1660 *
1661 * Despite most of MSDN insisting that the horizontal base unit is
1662 * tmAveCharWidth it isn't. Knowledge base article Q145994
1663 * "HOWTO: Calculate Dialog Units When Not Using the System Font",
1664 * says that we should take the average of the 52 English upper and lower
1665 * case characters.
1666 */
1667 /*
1668 * @implemented
1669 */
1670 DWORD
1671 STDCALL
1672 GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
1673 {
1674 SIZE sz;
1675 TEXTMETRICW tm;
1676 static const WCHAR alphabet[] = {
1677 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
1678 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
1679 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
1680
1681 if(!GetTextMetricsW(hdc, &tm)) return 0;
1682
1683 if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
1684
1685 if (lptm) *lptm = tm;
1686 if (height) *height = tm.tmHeight;
1687
1688 return (sz.cx / 26 + 1) / 2;
1689 }
1690
1691 /*************************************************************************
1692 * TranslateCharsetInfo [GDI32.@]
1693 *
1694 * Fills a CHARSETINFO structure for a character set, code page, or
1695 * font. This allows making the correspondance between different labelings
1696 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
1697 * of the same encoding.
1698 *
1699 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
1700 * only one codepage should be set in *lpSrc.
1701 *
1702 * RETURNS
1703 * TRUE on success, FALSE on failure.
1704 *
1705 */
1706 /*
1707 * @unimplemented
1708 */
1709 BOOL
1710 STDCALL
1711 TranslateCharsetInfo(
1712 LPDWORD lpSrc, /* [in]
1713 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
1714 if flags == TCI_SRCCHARSET: a character set value
1715 if flags == TCI_SRCCODEPAGE: a code page value
1716 */
1717 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
1718 DWORD flags /* [in] determines interpretation of lpSrc */)
1719 {
1720 int index = 0;
1721 switch (flags) {
1722 case TCI_SRCFONTSIG:
1723 while (!(*lpSrc>>index & 0x0001) && index<MAXTCIINDEX) index++;
1724 break;
1725 case TCI_SRCCODEPAGE:
1726 while (PtrToUlong(lpSrc) != FONT_tci[index].ciACP && index < MAXTCIINDEX) index++;
1727 break;
1728 case TCI_SRCCHARSET:
1729 while (PtrToUlong(lpSrc) != FONT_tci[index].ciCharset && index < MAXTCIINDEX) index++;
1730 break;
1731 default:
1732 return FALSE;
1733 }
1734 if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
1735 memcpy(lpCs, &FONT_tci[index], sizeof(CHARSETINFO));
1736 return TRUE;
1737 }
1738
1739
1740 /*
1741 * @implemented
1742 */
1743 DWORD
1744 STDCALL
1745 SetMapperFlags(
1746 HDC hDC,
1747 DWORD flags
1748 )
1749 {
1750 DWORD Ret = GDI_ERROR;
1751 PDC_ATTR Dc_Attr;
1752 #if 0
1753 if (GDI_HANDLE_GET_TYPE(hDC) != GDI_OBJECT_TYPE_DC)
1754 {
1755 if (GDI_HANDLE_GET_TYPE(hDC) == GDI_OBJECT_TYPE_METADC)
1756 return MFDRV_SetMapperFlags( hDC, flags);
1757 else
1758 {
1759 PLDC pLDC = Dc_Attr->pvLDC;
1760 if ( !pLDC )
1761 {
1762 SetLastError(ERROR_INVALID_HANDLE);
1763 return GDI_ERROR;
1764 }
1765 if (pLDC->iType == LDC_EMFLDC)
1766 {
1767 return EMFDRV_SetMapperFlags( hDC, flags);
1768 }
1769 }
1770 }
1771 #endif
1772 if (!GdiGetHandleUserData((HGDIOBJ) hDC, GDI_OBJECT_TYPE_DC, (PVOID) &Dc_Attr)) return GDI_ERROR;
1773
1774 if (NtCurrentTeb()->GdiTebBatch.HDC == hDC)
1775 {
1776 if (Dc_Attr->ulDirty_ & DC_FONTTEXT_DIRTY)
1777 {
1778 NtGdiFlush();
1779 Dc_Attr->ulDirty_ &= ~(DC_MODE_DIRTY|DC_FONTTEXT_DIRTY);
1780 }
1781 }
1782
1783 if ( flags & ~1 )
1784 SetLastError(ERROR_INVALID_PARAMETER);
1785 else
1786 {
1787 Ret = Dc_Attr->flFontMapper;
1788 Dc_Attr->flFontMapper = flags;
1789 }
1790 return Ret;
1791 }
1792
1793
1794 /*
1795 * @unimplemented
1796 */
1797 int
1798 STDCALL
1799 EnumFontsW(
1800 HDC hDC,
1801 LPCWSTR lpFaceName,
1802 FONTENUMPROCW FontFunc,
1803 LPARAM lParam
1804 )
1805 {
1806 #if 0
1807 return NtGdiEnumFonts ( hDC, lpFaceName, FontFunc, lParam );
1808 #else
1809 return EnumFontFamiliesW( hDC, lpFaceName, FontFunc, lParam );
1810 #endif
1811 }
1812
1813 /*
1814 * @unimplemented
1815 */
1816 int
1817 STDCALL
1818 EnumFontsA (
1819 HDC hDC,
1820 LPCSTR lpFaceName,
1821 FONTENUMPROCA FontFunc,
1822 LPARAM lParam
1823 )
1824 {
1825 #if 0
1826 NTSTATUS Status;
1827 LPWSTR lpFaceNameW;
1828 int rc = 0;
1829
1830 Status = HEAP_strdupA2W ( &lpFaceNameW, lpFaceName );
1831 if (!NT_SUCCESS (Status))
1832 SetLastError (RtlNtStatusToDosError(Status));
1833 else
1834 {
1835 rc = NtGdiEnumFonts ( hDC, lpFaceNameW, FontFunc, lParam );
1836
1837 HEAP_free ( lpFaceNameW );
1838 }
1839 return rc;
1840 #else
1841 return EnumFontFamiliesA( hDC, lpFaceName, FontFunc, lParam );
1842 #endif
1843 }
1844
1845 #define EfdFontFamilies 3
1846
1847 INT
1848 STDCALL
1849 NewEnumFontFamiliesExW(
1850 HDC hDC,
1851 LPLOGFONTW lpLogfont,
1852 FONTENUMPROCW lpEnumFontFamExProcW,
1853 LPARAM lParam,
1854 DWORD dwFlags)
1855 {
1856 ULONG_PTR idEnum, cbDataSize, cbRetSize;
1857 PENUMFONTDATAW pEfdw;
1858 PBYTE pBuffer;
1859 PBYTE pMax;
1860 INT ret = 1;
1861
1862 /* Open enumeration handle and find out how much memory we need */
1863 idEnum = NtGdiEnumFontOpen(hDC,
1864 EfdFontFamilies,
1865 0,
1866 LF_FACESIZE,
1867 (lpLogfont && lpLogfont->lfFaceName[0])? lpLogfont->lfFaceName : NULL,
1868 lpLogfont? lpLogfont->lfCharSet : DEFAULT_CHARSET,
1869 &cbDataSize);
1870 if (idEnum == 0)
1871 {
1872 return 0;
1873 }
1874 if (cbDataSize == 0)
1875 {
1876 NtGdiEnumFontClose(idEnum);
1877 return 0;
1878 }
1879
1880 /* Allocate memory */
1881 pBuffer = HeapAlloc(GetProcessHeap(), 0, cbDataSize);
1882 if (pBuffer == NULL)
1883 {
1884 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1885 NtGdiEnumFontClose(idEnum);
1886 return 0;
1887 }
1888
1889 /* Do the enumeration */
1890 if (!NtGdiEnumFontChunk(hDC, idEnum, cbDataSize, &cbRetSize, (PVOID)pBuffer))
1891 {
1892 HeapFree(GetProcessHeap(), 0, pBuffer);
1893 NtGdiEnumFontClose(idEnum);
1894 return 0;
1895 }
1896
1897 /* Get start and end address */
1898 pEfdw = (PENUMFONTDATAW)pBuffer;
1899 pMax = pBuffer + cbDataSize;
1900
1901 /* Iterate through the structures */
1902 while ((PBYTE)pEfdw < pMax && ret)
1903 {
1904 PNTMW_INTERNAL pNtmwi = (PNTMW_INTERNAL)((ULONG_PTR)pEfdw + pEfdw->ulNtmwiOffset);
1905
1906 ret = lpEnumFontFamExProcW(&pEfdw->elfexdv.elfEnumLogfontEx,
1907 &pNtmwi->ntmw,
1908 pEfdw->dwFontType,
1909 lParam);
1910
1911 pEfdw = (PENUMFONTDATAW)((ULONG_PTR)pEfdw + pEfdw->cbSize);
1912 }
1913
1914 /* Release the memory and close handle */
1915 HeapFree(GetProcessHeap(), 0, pBuffer);
1916 NtGdiEnumFontClose(idEnum);
1917
1918 return ret;
1919 }