set GetLastErrorMsg if CreateFontIndirectA(NULL) are use as inputparam . it make...
[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 #define INITIAL_FAMILY_COUNT 64
17
18 /***********************************************************************
19 * TEXTMETRIC conversion functions.
20 */
21 static void FONT_TextMetricWToA(const TEXTMETRICW *ptmW, LPTEXTMETRICA ptmA )
22 {
23 ptmA->tmHeight = ptmW->tmHeight;
24 ptmA->tmAscent = ptmW->tmAscent;
25 ptmA->tmDescent = ptmW->tmDescent;
26 ptmA->tmInternalLeading = ptmW->tmInternalLeading;
27 ptmA->tmExternalLeading = ptmW->tmExternalLeading;
28 ptmA->tmAveCharWidth = ptmW->tmAveCharWidth;
29 ptmA->tmMaxCharWidth = ptmW->tmMaxCharWidth;
30 ptmA->tmWeight = ptmW->tmWeight;
31 ptmA->tmOverhang = ptmW->tmOverhang;
32 ptmA->tmDigitizedAspectX = ptmW->tmDigitizedAspectX;
33 ptmA->tmDigitizedAspectY = ptmW->tmDigitizedAspectY;
34 ptmA->tmFirstChar = ptmW->tmFirstChar > 255 ? 255 : ptmW->tmFirstChar;
35 ptmA->tmLastChar = ptmW->tmLastChar > 255 ? 255 : ptmW->tmLastChar;
36 ptmA->tmDefaultChar = ptmW->tmDefaultChar > 255 ? 255 : ptmW->tmDefaultChar;
37 ptmA->tmBreakChar = ptmW->tmBreakChar > 255 ? 255 : ptmW->tmBreakChar;
38 ptmA->tmItalic = ptmW->tmItalic;
39 ptmA->tmUnderlined = ptmW->tmUnderlined;
40 ptmA->tmStruckOut = ptmW->tmStruckOut;
41 ptmA->tmPitchAndFamily = ptmW->tmPitchAndFamily;
42 ptmA->tmCharSet = ptmW->tmCharSet;
43 }
44
45 /***********************************************************************
46 * FONT_mbtowc
47 *
48 * Returns a Unicode translation of str. If count is -1 then str is
49 * assumed to be '\0' terminated, otherwise it contains the number of
50 * bytes to convert. If plenW is non-NULL, on return it will point to
51 * the number of WCHARs that have been written. The caller should free
52 * the returned LPWSTR from the process heap itself.
53 */
54 static LPWSTR FONT_mbtowc(LPCSTR str, INT count, INT *plenW)
55 {
56 UINT cp = CP_ACP;
57 INT lenW;
58 LPWSTR strW;
59
60 if(count == -1) count = strlen(str);
61 lenW = MultiByteToWideChar(cp, 0, str, count, NULL, 0);
62 strW = HeapAlloc(GetProcessHeap(), 0, lenW*sizeof(WCHAR));
63 MultiByteToWideChar(cp, 0, str, count, strW, lenW);
64 DPRINT1("mapped %s -> %s \n", str, strW);
65 if(plenW) *plenW = lenW;
66 return strW;
67 }
68
69
70 static BOOL FASTCALL
71 MetricsCharConvert(WCHAR w, UCHAR *b)
72 {
73 UNICODE_STRING WString;
74 WCHAR WBuf[2];
75 ANSI_STRING AString;
76 CHAR ABuf[2];
77 NTSTATUS Status;
78
79 if (L'\0' == w)
80 {
81 *b = '\0';
82 }
83 else
84 {
85 WBuf[0] = w;
86 WBuf[1] = L'\0';
87 RtlInitUnicodeString(&WString, WBuf);
88 ABuf[0] = '*';
89 ABuf[1] = L'\0';
90 RtlInitAnsiString(&AString, ABuf);
91
92 Status = RtlUnicodeStringToAnsiString(&AString, &WString, FALSE);
93 if (! NT_SUCCESS(Status))
94 {
95 SetLastError(RtlNtStatusToDosError(Status));
96 return FALSE;
97 }
98 *b = ABuf[0];
99 }
100
101 return TRUE;
102 }
103
104 BOOL FASTCALL
105 TextMetricW2A(TEXTMETRICA *tma, TEXTMETRICW *tmw)
106 {
107 UNICODE_STRING WString;
108 WCHAR WBuf[256];
109 ANSI_STRING AString;
110 CHAR ABuf[256];
111 UINT Letter;
112 NTSTATUS Status;
113
114 tma->tmHeight = tmw->tmHeight;
115 tma->tmAscent = tmw->tmAscent;
116 tma->tmDescent = tmw->tmDescent;
117 tma->tmInternalLeading = tmw->tmInternalLeading;
118 tma->tmExternalLeading = tmw->tmExternalLeading;
119 tma->tmAveCharWidth = tmw->tmAveCharWidth;
120 tma->tmMaxCharWidth = tmw->tmMaxCharWidth;
121 tma->tmWeight = tmw->tmWeight;
122 tma->tmOverhang = tmw->tmOverhang;
123 tma->tmDigitizedAspectX = tmw->tmDigitizedAspectX;
124 tma->tmDigitizedAspectY = tmw->tmDigitizedAspectY;
125
126 /* The Unicode FirstChar/LastChar need not correspond to the ANSI
127 FirstChar/LastChar. For example, if the font contains glyphs for
128 letters A-Z and an accented version of the letter e, the Unicode
129 FirstChar would be A and the Unicode LastChar would be the accented
130 e. If you just translate those to ANSI, the range would become
131 letters A-E instead of A-Z.
132 We translate all possible ANSI chars to Unicode and find the first
133 and last translated character which fall into the Unicode FirstChar/
134 LastChar range and return the corresponding ANSI char. */
135
136 /* Setup an Ansi string containing all possible letters (note: skip '\0' at
137 the beginning since that would be interpreted as end-of-string, handle
138 '\0' special later */
139 for (Letter = 1; Letter < 256; Letter++)
140 {
141 ABuf[Letter - 1] = (CHAR) Letter;
142 WBuf[Letter - 1] = L' ';
143 }
144 ABuf[255] = '\0';
145 WBuf[255] = L'\0';
146 RtlInitAnsiString(&AString, ABuf);
147 RtlInitUnicodeString(&WString, WBuf);
148
149 /* Find the corresponding Unicode characters */
150 Status = RtlAnsiStringToUnicodeString(&WString, &AString, FALSE);
151 if (! NT_SUCCESS(Status))
152 {
153 SetLastError(RtlNtStatusToDosError(Status));
154 return FALSE;
155 }
156
157 /* Scan for the first ANSI character which maps to an Unicode character
158 in the range */
159 tma->tmFirstChar = '\0';
160 if (L'\0' != tmw->tmFirstChar)
161 {
162 for (Letter = 1; Letter < 256; Letter++)
163 {
164 if (tmw->tmFirstChar <= WBuf[Letter - 1] &&
165 WBuf[Letter - 1] <= tmw->tmLastChar)
166 {
167 tma->tmFirstChar = (CHAR) Letter;
168 break;
169 }
170 }
171 }
172
173 /* Scan for the last ANSI character which maps to an Unicode character
174 in the range */
175 tma->tmLastChar = '\0';
176 if (L'\0' != tmw->tmLastChar)
177 {
178 for (Letter = 255; 0 < Letter; Letter--)
179 {
180 if (tmw->tmFirstChar <= WBuf[Letter - 1] &&
181 WBuf[Letter - 1] <= tmw->tmLastChar)
182 {
183 tma->tmLastChar = (CHAR) Letter;
184 break;
185 }
186 }
187 }
188
189 if (! MetricsCharConvert(tmw->tmDefaultChar, &tma->tmDefaultChar) ||
190 ! MetricsCharConvert(tmw->tmBreakChar, &tma->tmBreakChar))
191 {
192 return FALSE;
193 }
194
195 tma->tmItalic = tmw->tmItalic;
196 tma->tmUnderlined = tmw->tmUnderlined;
197 tma->tmStruckOut = tmw->tmStruckOut;
198 tma->tmPitchAndFamily = tmw->tmPitchAndFamily;
199 tma->tmCharSet = tmw->tmCharSet;
200
201 return TRUE;
202 }
203
204 BOOL FASTCALL
205 NewTextMetricW2A(NEWTEXTMETRICA *tma, NEWTEXTMETRICW *tmw)
206 {
207 if (! TextMetricW2A((TEXTMETRICA *) tma, (TEXTMETRICW *) tmw))
208 {
209 return FALSE;
210 }
211
212 tma->ntmFlags = tmw->ntmFlags;
213 tma->ntmSizeEM = tmw->ntmSizeEM;
214 tma->ntmCellHeight = tmw->ntmCellHeight;
215 tma->ntmAvgWidth = tmw->ntmAvgWidth;
216
217 return TRUE;
218 }
219
220 BOOL FASTCALL
221 NewTextMetricExW2A(NEWTEXTMETRICEXA *tma, NEWTEXTMETRICEXW *tmw)
222 {
223 if (! NewTextMetricW2A(&tma->ntmTm, &tmw->ntmTm))
224 {
225 return FALSE;
226 }
227
228 tma->ntmFontSig = tmw->ntmFontSig;
229
230 return TRUE;
231 }
232
233 static int FASTCALL
234 IntEnumFontFamilies(HDC Dc, LPLOGFONTW LogFont, PVOID EnumProc, LPARAM lParam,
235 BOOL Unicode)
236 {
237 int FontFamilyCount;
238 int FontFamilySize;
239 PFONTFAMILYINFO Info;
240 int Ret = 0;
241 int i;
242 ENUMLOGFONTEXA EnumLogFontExA;
243 NEWTEXTMETRICEXA NewTextMetricExA;
244
245 Info = RtlAllocateHeap(GetProcessHeap(), 0,
246 INITIAL_FAMILY_COUNT * sizeof(FONTFAMILYINFO));
247 if (NULL == Info)
248 {
249 return 0;
250 }
251 FontFamilyCount = NtGdiGetFontFamilyInfo(Dc, LogFont, Info, INITIAL_FAMILY_COUNT);
252 if (FontFamilyCount < 0)
253 {
254 RtlFreeHeap(GetProcessHeap(), 0, Info);
255 return 0;
256 }
257 if (INITIAL_FAMILY_COUNT < FontFamilyCount)
258 {
259 FontFamilySize = FontFamilyCount;
260 RtlFreeHeap(GetProcessHeap(), 0, Info);
261 Info = RtlAllocateHeap(GetProcessHeap(), 0,
262 FontFamilyCount * sizeof(FONTFAMILYINFO));
263 if (NULL == Info)
264 {
265 return 0;
266 }
267 FontFamilyCount = NtGdiGetFontFamilyInfo(Dc, LogFont, Info, FontFamilySize);
268 if (FontFamilyCount < 0 || FontFamilySize < FontFamilyCount)
269 {
270 RtlFreeHeap(GetProcessHeap(), 0, Info);
271 return 0;
272 }
273 }
274
275 for (i = 0; i < FontFamilyCount; i++)
276 {
277 if (Unicode)
278 {
279 Ret = ((FONTENUMPROCW) EnumProc)(
280 &Info[i].EnumLogFontEx,
281 &Info[i].NewTextMetricEx,
282 Info[i].FontType, lParam);
283 }
284 else
285 {
286 LogFontW2A(&EnumLogFontExA.elfLogFont, &Info[i].EnumLogFontEx.elfLogFont);
287 WideCharToMultiByte(CP_THREAD_ACP, 0, Info[i].EnumLogFontEx.elfFullName, -1,
288 (LPSTR)EnumLogFontExA.elfFullName, LF_FULLFACESIZE, NULL, NULL);
289 WideCharToMultiByte(CP_THREAD_ACP, 0, Info[i].EnumLogFontEx.elfStyle, -1,
290 (LPSTR)EnumLogFontExA.elfStyle, LF_FACESIZE, NULL, NULL);
291 WideCharToMultiByte(CP_THREAD_ACP, 0, Info[i].EnumLogFontEx.elfScript, -1,
292 (LPSTR)EnumLogFontExA.elfScript, LF_FACESIZE, NULL, NULL);
293 NewTextMetricExW2A(&NewTextMetricExA,
294 &Info[i].NewTextMetricEx);
295 Ret = ((FONTENUMPROCA) EnumProc)(
296 &EnumLogFontExA,
297 &NewTextMetricExA,
298 Info[i].FontType, lParam);
299 }
300 }
301
302 RtlFreeHeap(GetProcessHeap(), 0, Info);
303
304 return Ret;
305 }
306
307 /*
308 * @implemented
309 */
310 int STDCALL
311 EnumFontFamiliesExW(HDC hdc, LPLOGFONTW lpLogfont, FONTENUMPROCW lpEnumFontFamExProc,
312 LPARAM lParam, DWORD dwFlags)
313 {
314 return IntEnumFontFamilies(hdc, lpLogfont, lpEnumFontFamExProc, lParam, TRUE);
315 }
316
317
318 /*
319 * @implemented
320 */
321 int STDCALL
322 EnumFontFamiliesW(HDC hdc, LPCWSTR lpszFamily, FONTENUMPROCW lpEnumFontFamProc,
323 LPARAM lParam)
324 {
325 LOGFONTW LogFont;
326
327 ZeroMemory(&LogFont, sizeof(LOGFONTW));
328 LogFont.lfCharSet = DEFAULT_CHARSET;
329 if (NULL != lpszFamily)
330 {
331 lstrcpynW(LogFont.lfFaceName, lpszFamily, LF_FACESIZE);
332 }
333
334 return IntEnumFontFamilies(hdc, &LogFont, lpEnumFontFamProc, lParam, TRUE);
335 }
336
337
338 /*
339 * @implemented
340 */
341 int STDCALL
342 EnumFontFamiliesExA (HDC hdc, LPLOGFONTA lpLogfont, FONTENUMPROCA lpEnumFontFamExProc,
343 LPARAM lParam, DWORD dwFlags)
344 {
345 LOGFONTW LogFontW;
346
347 LogFontA2W(&LogFontW, lpLogfont);
348
349 /* no need to convert LogFontW back to lpLogFont b/c it's an [in] parameter only */
350 return IntEnumFontFamilies(hdc, &LogFontW, lpEnumFontFamExProc, lParam, FALSE);
351 }
352
353
354 /*
355 * @implemented
356 */
357 int STDCALL
358 EnumFontFamiliesA(HDC hdc, LPCSTR lpszFamily, FONTENUMPROCA lpEnumFontFamProc,
359 LPARAM lParam)
360 {
361 LOGFONTW LogFont;
362
363 ZeroMemory(&LogFont, sizeof(LOGFONTW));
364 LogFont.lfCharSet = DEFAULT_CHARSET;
365 if (NULL != lpszFamily)
366 {
367 MultiByteToWideChar(CP_THREAD_ACP, 0, lpszFamily, -1, LogFont.lfFaceName, LF_FACESIZE);
368 }
369
370 return IntEnumFontFamilies(hdc, &LogFont, lpEnumFontFamProc, lParam, FALSE);
371 }
372
373
374 /*
375 * @implemented
376 */
377 BOOL
378 STDCALL
379 GetCharWidthA (
380 HDC hdc,
381 UINT iFirstChar,
382 UINT iLastChar,
383 LPINT lpBuffer
384 )
385 {
386 DPRINT1("GCWA iFirstChar %x\n",iFirstChar);
387
388 return GetCharWidth32A ( hdc, iFirstChar, iLastChar, lpBuffer );
389 }
390
391
392 /*
393 * @implemented
394 */
395 BOOL
396 STDCALL
397 GetCharWidth32A(
398 HDC hdc,
399 UINT iFirstChar,
400 UINT iLastChar,
401 LPINT lpBuffer
402 )
403 {
404 INT i, wlen, count = (INT)(iLastChar - iFirstChar + 1);
405 LPSTR str;
406 LPWSTR wstr;
407 BOOL ret = TRUE;
408 DPRINT1("GCW32A iFirstChar %x\n",iFirstChar);
409
410 if(count <= 0) return FALSE;
411
412 str = HeapAlloc(GetProcessHeap(), 0, count);
413 for(i = 0; i < count; i++)
414 str[i] = (BYTE)(iFirstChar + i);
415
416 wstr = FONT_mbtowc(str, count, &wlen);
417
418 for(i = 0; i < wlen; i++)
419 {
420 /* FIXME should be NtGdiGetCharWidthW */
421 if(!NtGdiGetCharWidth32 (hdc, wstr[i], wstr[i], lpBuffer))
422 {
423 ret = FALSE;
424 break;
425 }
426 lpBuffer++;
427 }
428
429 HeapFree(GetProcessHeap(), 0, str);
430 HeapFree(GetProcessHeap(), 0, wstr);
431
432 return ret;
433 }
434
435
436 /*
437 * @implemented
438 */
439 BOOL
440 STDCALL
441 GetCharWidthW (
442 HDC hdc,
443 UINT iFirstChar,
444 UINT iLastChar,
445 LPINT lpBuffer
446 )
447 {
448 DPRINT1("GCW32w uFirstChar %x\n",iFirstChar);
449
450 /* FIXME should be NtGdiGetCharWidthW */
451 return NtGdiGetCharWidth32 ( hdc, iFirstChar, iLastChar, lpBuffer );
452 }
453
454
455 /*
456 * @implemented
457 */
458 DWORD
459 STDCALL
460 GetCharacterPlacementW(
461 HDC hdc,
462 LPCWSTR lpString,
463 INT uCount,
464 INT nMaxExtent,
465 GCP_RESULTSW *lpResults,
466 DWORD dwFlags
467 )
468 {
469 DWORD ret=0;
470 SIZE size;
471 UINT i, nSet;
472
473 if(dwFlags&(~GCP_REORDER)) DPRINT("flags 0x%08lx ignored\n", dwFlags);
474 if(lpResults->lpClass) DPRINT("classes not implemented\n");
475 if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
476 DPRINT("Caret positions for complex scripts not implemented\n");
477
478 nSet = (UINT)uCount;
479 if(nSet > lpResults->nGlyphs)
480 nSet = lpResults->nGlyphs;
481
482 /* return number of initialized fields */
483 lpResults->nGlyphs = nSet;
484
485 /*if((dwFlags&GCP_REORDER)==0 || !BidiAvail)
486 {*/
487 /* Treat the case where no special handling was requested in a fastpath way */
488 /* copy will do if the GCP_REORDER flag is not set */
489 if(lpResults->lpOutString)
490 lstrcpynW( lpResults->lpOutString, lpString, nSet );
491
492 if(lpResults->lpGlyphs)
493 lstrcpynW( lpResults->lpGlyphs, lpString, nSet );
494
495 if(lpResults->lpOrder)
496 {
497 for(i = 0; i < nSet; i++)
498 lpResults->lpOrder[i] = i;
499 }
500 /*} else
501 {
502 BIDI_Reorder( lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
503 nSet, lpResults->lpOrder );
504 }*/
505
506 /* FIXME: Will use the placement chars */
507 if (lpResults->lpDx)
508 {
509 int c;
510 for (i = 0; i < nSet; i++)
511 {
512 if (NtGdiGetCharWidth32(hdc, lpString[i], lpString[i], &c))
513 lpResults->lpDx[i]= c;
514 }
515 }
516
517 if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
518 {
519 int pos = 0;
520
521 lpResults->lpCaretPos[0] = 0;
522 for (i = 1; i < nSet; i++)
523 if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
524 lpResults->lpCaretPos[i] = (pos += size.cx);
525 }
526
527 /*if(lpResults->lpGlyphs)
528 GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);*/
529
530 if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
531 ret = MAKELONG(size.cx, size.cy);
532
533 return ret;
534 }
535
536
537 /*
538 * @unimplemented
539 */
540 BOOL
541 APIENTRY
542 GetCharWidthFloatA(
543 HDC hdc,
544 UINT iFirstChar,
545 UINT iLastChar,
546 PFLOAT pxBuffer
547 )
548 {
549 /* FIXME what to do with iFirstChar and iLastChar ??? */
550 return NtGdiGetCharWidthFloat ( hdc, iFirstChar, iLastChar, pxBuffer );
551 }
552
553
554 /*
555 * @implemented
556 */
557 BOOL
558 APIENTRY
559 GetCharABCWidthsA(
560 HDC hdc,
561 UINT uFirstChar,
562 UINT uLastChar,
563 LPABC lpabc
564 )
565 {
566 DPRINT1("GCABCWA uFirstChar %x\n",uFirstChar);
567
568 return NtGdiGetCharABCWidths(hdc, uFirstChar, uLastChar, lpabc);
569 }
570
571
572 /*
573 * @unimplemented
574 */
575 BOOL
576 APIENTRY
577 GetCharABCWidthsFloatA(
578 HDC hdc,
579 UINT iFirstChar,
580 UINT iLastChar,
581 LPABCFLOAT lpABCF
582 )
583 {
584 DPRINT1("GCABCWFA iFirstChar %x\n",iFirstChar);
585
586 /* FIXME what to do with iFirstChar and iLastChar ??? */
587 return NtGdiGetCharABCWidthsFloat ( hdc, iFirstChar, iLastChar, lpABCF );
588 }
589
590
591 /*
592 * @implemented
593 */
594 DWORD
595 STDCALL
596 GetGlyphOutlineA(
597 HDC hdc,
598 UINT uChar,
599 UINT uFormat,
600 LPGLYPHMETRICS lpgm,
601 DWORD cbBuffer,
602 LPVOID lpvBuffer,
603 CONST MAT2 *lpmat2
604 )
605 {
606
607 LPWSTR p = NULL;
608 DWORD ret;
609 UINT c;
610 DPRINT1("GetGlyphOutlineA uChar %x\n", uChar);
611 if(!(uFormat & GGO_GLYPH_INDEX)) {
612 int len;
613 char mbchs[2];
614 if(uChar > 0xff) { /* but, 2 bytes character only */
615 len = 2;
616 mbchs[0] = (uChar & 0xff00) >> 8;
617 mbchs[1] = (uChar & 0xff);
618 } else {
619 len = 1;
620 mbchs[0] = (uChar & 0xff);
621 }
622 p = FONT_mbtowc(mbchs, len, NULL);
623 c = p[0];
624 } else
625 c = uChar;
626 ret = NtGdiGetGlyphOutline(hdc, c, uFormat, lpgm, cbBuffer, lpvBuffer, (CONST LPMAT2)lpmat2, TRUE);
627 HeapFree(GetProcessHeap(), 0, p);
628 return ret;
629 }
630
631
632 /*
633 * @implemented
634 */
635 DWORD
636 STDCALL
637 GetGlyphOutlineW(
638 HDC hdc,
639 UINT uChar,
640 UINT uFormat,
641 LPGLYPHMETRICS lpgm,
642 DWORD cbBuffer,
643 LPVOID lpvBuffer,
644 CONST MAT2 *lpmat2
645 )
646 {
647 DPRINT1("GetGlyphOutlineW uChar %x\n", uChar);
648 return NtGdiGetGlyphOutline ( hdc, uChar, uFormat, lpgm, cbBuffer, lpvBuffer, (CONST LPMAT2)lpmat2, TRUE);
649 }
650
651
652 /*
653 * @implemented
654 */
655 UINT
656 APIENTRY
657 GetOutlineTextMetricsA(
658 HDC hdc,
659 UINT cbData,
660 LPOUTLINETEXTMETRICA lpOTM
661 )
662 {
663 char buf[512], *ptr;
664 UINT ret, needed;
665 OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
666 OUTLINETEXTMETRICA *output = lpOTM;
667 INT left, len;
668
669 if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
670 return 0;
671 if(ret > sizeof(buf))
672 lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
673 GetOutlineTextMetricsW(hdc, ret, lpOTMW);
674
675 needed = sizeof(OUTLINETEXTMETRICA);
676 if(lpOTMW->otmpFamilyName)
677 needed += WideCharToMultiByte(CP_ACP, 0,
678 (WCHAR*)((char*)lpOTMW + (int)lpOTMW->otmpFamilyName), -1,
679 NULL, 0, NULL, NULL);
680 if(lpOTMW->otmpFaceName)
681 needed += WideCharToMultiByte(CP_ACP, 0,
682 (WCHAR*)((char*)lpOTMW + (int)lpOTMW->otmpFaceName), -1,
683 NULL, 0, NULL, NULL);
684 if(lpOTMW->otmpStyleName)
685 needed += WideCharToMultiByte(CP_ACP, 0,
686 (WCHAR*)((char*)lpOTMW + (int)lpOTMW->otmpStyleName), -1,
687 NULL, 0, NULL, NULL);
688 if(lpOTMW->otmpFullName)
689 needed += WideCharToMultiByte(CP_ACP, 0,
690 (WCHAR*)((char*)lpOTMW + (int)lpOTMW->otmpFullName), -1,
691 NULL, 0, NULL, NULL);
692
693 if(!lpOTM) {
694 ret = needed;
695 goto end;
696 }
697
698 DPRINT("needed = %d\n", needed);
699 if(needed > cbData)
700 /* Since the supplied buffer isn't big enough, we'll alloc one
701 that is and memcpy the first cbData bytes into the lpOTM at
702 the end. */
703 output = HeapAlloc(GetProcessHeap(), 0, needed);
704
705 ret = output->otmSize = min(needed, cbData);
706 FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
707 output->otmFiller = 0;
708 output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
709 output->otmfsSelection = lpOTMW->otmfsSelection;
710 output->otmfsType = lpOTMW->otmfsType;
711 output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
712 output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
713 output->otmItalicAngle = lpOTMW->otmItalicAngle;
714 output->otmEMSquare = lpOTMW->otmEMSquare;
715 output->otmAscent = lpOTMW->otmAscent;
716 output->otmDescent = lpOTMW->otmDescent;
717 output->otmLineGap = lpOTMW->otmLineGap;
718 output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
719 output->otmsXHeight = lpOTMW->otmsXHeight;
720 output->otmrcFontBox = lpOTMW->otmrcFontBox;
721 output->otmMacAscent = lpOTMW->otmMacAscent;
722 output->otmMacDescent = lpOTMW->otmMacDescent;
723 output->otmMacLineGap = lpOTMW->otmMacLineGap;
724 output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
725 output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
726 output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
727 output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
728 output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
729 output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
730 output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
731 output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
732 output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
733
734
735 ptr = (char*)(output + 1);
736 left = needed - sizeof(*output);
737
738 if(lpOTMW->otmpFamilyName) {
739 output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
740 len = WideCharToMultiByte(CP_ACP, 0,
741 (WCHAR*)((char*)lpOTMW + (int)lpOTMW->otmpFamilyName), -1,
742 ptr, left, NULL, NULL);
743 left -= len;
744 ptr += len;
745 } else
746 output->otmpFamilyName = 0;
747
748 if(lpOTMW->otmpFaceName) {
749 output->otmpFaceName = (LPSTR)(ptr - (char*)output);
750 len = WideCharToMultiByte(CP_ACP, 0,
751 (WCHAR*)((char*)lpOTMW + (int)lpOTMW->otmpFaceName), -1,
752 ptr, left, NULL, NULL);
753 left -= len;
754 ptr += len;
755 } else
756 output->otmpFaceName = 0;
757
758 if(lpOTMW->otmpStyleName) {
759 output->otmpStyleName = (LPSTR)(ptr - (char*)output);
760 len = WideCharToMultiByte(CP_ACP, 0,
761 (WCHAR*)((char*)lpOTMW + (int)lpOTMW->otmpStyleName), -1,
762 ptr, left, NULL, NULL);
763 left -= len;
764 ptr += len;
765 } else
766 output->otmpStyleName = 0;
767
768 if(lpOTMW->otmpFullName) {
769 output->otmpFullName = (LPSTR)(ptr - (char*)output);
770 len = WideCharToMultiByte(CP_ACP, 0,
771 (WCHAR*)((char*)lpOTMW + (int)lpOTMW->otmpFullName), -1,
772 ptr, left, NULL, NULL);
773 left -= len;
774 } else
775 output->otmpFullName = 0;
776
777 assert(left == 0);
778
779 if(output != lpOTM) {
780 memcpy(lpOTM, output, cbData);
781 HeapFree(GetProcessHeap(), 0, output);
782
783 /* check if the string offsets really fit into the provided size */
784 /* FIXME: should we check string length as well? */
785 if ((UINT_PTR)lpOTM->otmpFamilyName >= lpOTM->otmSize)
786 lpOTM->otmpFamilyName = 0; /* doesn't fit */
787
788 if ((UINT_PTR)lpOTM->otmpFaceName >= lpOTM->otmSize)
789 lpOTM->otmpFaceName = 0; /* doesn't fit */
790
791 if ((UINT_PTR)lpOTM->otmpStyleName >= lpOTM->otmSize)
792 lpOTM->otmpStyleName = 0; /* doesn't fit */
793
794 if ((UINT_PTR)lpOTM->otmpFullName >= lpOTM->otmSize)
795 lpOTM->otmpFullName = 0; /* doesn't fit */
796 }
797
798 end:
799 if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
800 HeapFree(GetProcessHeap(), 0, lpOTMW);
801
802 return ret;
803 }
804
805
806 /*
807 * @implemented
808 */
809 UINT
810 APIENTRY
811 GetOutlineTextMetricsW(
812 HDC hdc,
813 UINT cbData,
814 LPOUTLINETEXTMETRICW lpOTM
815 )
816 {
817 return NtGdiGetOutlineTextMetrics(hdc, cbData, lpOTM);
818 }
819
820
821 /*
822 * @implemented
823 */
824 HFONT
825 STDCALL
826 CreateFontIndirectA(
827 CONST LOGFONTA *lplf
828 )
829 {
830 LOGFONTW tlf;
831
832 if (lplf)
833 {
834 LogFontA2W(&tlf, lplf);
835 return NtGdiCreateFontIndirect(&tlf);
836 }
837 else return NtGdiCreateFontIndirect(NULL);
838 }
839
840
841 /*
842 * @implemented
843 */
844 HFONT
845 STDCALL
846 CreateFontIndirectW(
847 CONST LOGFONTW *lplf
848 )
849 {
850 return NtGdiCreateFontIndirect((CONST LPLOGFONTW)lplf);
851 }
852
853
854 /*
855 * @implemented
856 */
857 HFONT
858 STDCALL
859 CreateFontA(
860 int nHeight,
861 int nWidth,
862 int nEscapement,
863 int nOrientation,
864 int fnWeight,
865 DWORD fdwItalic,
866 DWORD fdwUnderline,
867 DWORD fdwStrikeOut,
868 DWORD fdwCharSet,
869 DWORD fdwOutputPrecision,
870 DWORD fdwClipPrecision,
871 DWORD fdwQuality,
872 DWORD fdwPitchAndFamily,
873 LPCSTR lpszFace
874 )
875 {
876 ANSI_STRING StringA;
877 UNICODE_STRING StringU;
878 HFONT ret;
879
880 RtlInitAnsiString(&StringA, (LPSTR)lpszFace);
881 RtlAnsiStringToUnicodeString(&StringU, &StringA, TRUE);
882
883 ret = CreateFontW(nHeight, nWidth, nEscapement, nOrientation, fnWeight, fdwItalic, fdwUnderline, fdwStrikeOut,
884 fdwCharSet, fdwOutputPrecision, fdwClipPrecision, fdwQuality, fdwPitchAndFamily, StringU.Buffer);
885
886 RtlFreeUnicodeString(&StringU);
887
888 return ret;
889 }
890
891
892 /*
893 * @implemented
894 */
895 HFONT
896 STDCALL
897 CreateFontW(
898 int nHeight,
899 int nWidth,
900 int nEscapement,
901 int nOrientation,
902 int nWeight,
903 DWORD fnItalic,
904 DWORD fdwUnderline,
905 DWORD fdwStrikeOut,
906 DWORD fdwCharSet,
907 DWORD fdwOutputPrecision,
908 DWORD fdwClipPrecision,
909 DWORD fdwQuality,
910 DWORD fdwPitchAndFamily,
911 LPCWSTR lpszFace
912 )
913 {
914 return NtGdiCreateFont(nHeight, nWidth, nEscapement, nOrientation, nWeight, fnItalic, fdwUnderline, fdwStrikeOut,
915 fdwCharSet, fdwOutputPrecision, fdwClipPrecision, fdwQuality, fdwPitchAndFamily, lpszFace);
916 }
917
918
919 /*
920 * @implemented
921 */
922 BOOL
923 STDCALL
924 CreateScalableFontResourceW(
925 DWORD fdwHidden,
926 LPCWSTR lpszFontRes,
927 LPCWSTR lpszFontFile,
928 LPCWSTR lpszCurrentPath
929 )
930 {
931 return NtGdiCreateScalableFontResource ( fdwHidden,
932 lpszFontRes,
933 lpszFontFile,
934 lpszCurrentPath );
935 }
936
937
938 /*
939 * @implemented
940 */
941 BOOL
942 STDCALL
943 CreateScalableFontResourceA(
944 DWORD fdwHidden,
945 LPCSTR lpszFontRes,
946 LPCSTR lpszFontFile,
947 LPCSTR lpszCurrentPath
948 )
949 {
950 NTSTATUS Status;
951 LPWSTR lpszFontResW, lpszFontFileW, lpszCurrentPathW;
952 BOOL rc = FALSE;
953
954 Status = HEAP_strdupA2W ( &lpszFontResW, lpszFontRes );
955 if (!NT_SUCCESS (Status))
956 SetLastError (RtlNtStatusToDosError(Status));
957 else
958 {
959 Status = HEAP_strdupA2W ( &lpszFontFileW, lpszFontFile );
960 if (!NT_SUCCESS (Status))
961 SetLastError (RtlNtStatusToDosError(Status));
962 else
963 {
964 Status = HEAP_strdupA2W ( &lpszCurrentPathW, lpszCurrentPath );
965 if (!NT_SUCCESS (Status))
966 SetLastError (RtlNtStatusToDosError(Status));
967 else
968 {
969 rc = NtGdiCreateScalableFontResource ( fdwHidden,
970 lpszFontResW,
971 lpszFontFileW,
972 lpszCurrentPathW );
973
974 HEAP_free ( lpszCurrentPathW );
975 }
976
977 HEAP_free ( lpszFontFileW );
978 }
979
980 HEAP_free ( lpszFontResW );
981 }
982 return rc;
983 }
984
985
986 /*
987 * @implemented
988 */
989 int
990 STDCALL
991 AddFontResourceExW ( LPCWSTR lpszFilename, DWORD fl, PVOID pvReserved )
992 {
993 UNICODE_STRING Filename;
994
995 /* FIXME handle fl parameter */
996 RtlInitUnicodeString(&Filename, lpszFilename);
997 return NtGdiAddFontResource ( &Filename, fl );
998 }
999
1000
1001 /*
1002 * @implemented
1003 */
1004 int
1005 STDCALL
1006 AddFontResourceExA ( LPCSTR lpszFilename, DWORD fl, PVOID pvReserved )
1007 {
1008 NTSTATUS Status;
1009 PWSTR FilenameW;
1010 int rc = 0;
1011
1012 Status = HEAP_strdupA2W ( &FilenameW, lpszFilename );
1013 if ( !NT_SUCCESS (Status) )
1014 SetLastError (RtlNtStatusToDosError(Status));
1015 else
1016 {
1017 rc = AddFontResourceExW ( FilenameW, fl, pvReserved );
1018
1019 HEAP_free ( FilenameW );
1020 }
1021 return rc;
1022 }
1023
1024
1025 /*
1026 * @implemented
1027 */
1028 int
1029 STDCALL
1030 AddFontResourceA ( LPCSTR lpszFilename )
1031 {
1032 return AddFontResourceExA ( lpszFilename, 0, 0 );
1033 }
1034
1035
1036 /*
1037 * @implemented
1038 */
1039 int
1040 STDCALL
1041 AddFontResourceW ( LPCWSTR lpszFilename )
1042 {
1043 return AddFontResourceExW ( lpszFilename, 0, 0 );
1044 }
1045
1046
1047 /*
1048 * @implemented
1049 */
1050 BOOL
1051 STDCALL
1052 RemoveFontResourceW(
1053 LPCWSTR lpFileName
1054 )
1055 {
1056 return NtGdiRemoveFontResource ( lpFileName );
1057 }
1058
1059
1060 /*
1061 * @implemented
1062 */
1063 BOOL
1064 STDCALL
1065 RemoveFontResourceA(
1066 LPCSTR lpFileName
1067 )
1068 {
1069 NTSTATUS Status;
1070 LPWSTR lpFileNameW;
1071 BOOL rc = 0;
1072
1073 Status = HEAP_strdupA2W ( &lpFileNameW, lpFileName );
1074 if (!NT_SUCCESS (Status))
1075 SetLastError (RtlNtStatusToDosError(Status));
1076 else
1077 {
1078 rc = NtGdiRemoveFontResource ( lpFileNameW );
1079
1080 HEAP_free ( lpFileNameW );
1081 }
1082
1083 return rc;
1084 }
1085
1086 /***********************************************************************
1087 * GdiGetCharDimensions
1088 *
1089 * Gets the average width of the characters in the English alphabet.
1090 *
1091 * PARAMS
1092 * hdc [I] Handle to the device context to measure on.
1093 * lptm [O] Pointer to memory to store the text metrics into.
1094 * height [O] On exit, the maximum height of characters in the English alphabet.
1095 *
1096 * RETURNS
1097 * The average width of characters in the English alphabet.
1098 *
1099 * NOTES
1100 * This function is used by the dialog manager to get the size of a dialog
1101 * unit. It should also be used by other pieces of code that need to know
1102 * the size of a dialog unit in logical units without having access to the
1103 * window handle of the dialog.
1104 * Windows caches the font metrics from this function, but we don't and
1105 * there doesn't appear to be an immediate advantage to do so.
1106 *
1107 * SEE ALSO
1108 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
1109 *
1110 * Despite most of MSDN insisting that the horizontal base unit is
1111 * tmAveCharWidth it isn't. Knowledge base article Q145994
1112 * "HOWTO: Calculate Dialog Units When Not Using the System Font",
1113 * says that we should take the average of the 52 English upper and lower
1114 * case characters.
1115 */
1116 /*
1117 * @implemented
1118 */
1119 DWORD
1120 STDCALL
1121 GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
1122 {
1123 SIZE sz;
1124 static const WCHAR alphabet[] = {
1125 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
1126 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
1127 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
1128
1129 if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
1130
1131 if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
1132
1133 if (height) *height = sz.cy;
1134 return (sz.cx / 26 + 1) / 2;
1135 }
1136
1137
1138 /*
1139 * @unimplemented
1140 */
1141 int
1142 STDCALL
1143 EnumFontsW(
1144 HDC hDC,
1145 LPCWSTR lpFaceName,
1146 FONTENUMPROCW FontFunc,
1147 LPARAM lParam
1148 )
1149 {
1150 #if 0
1151 return NtGdiEnumFonts ( hDC, lpFaceName, FontFunc, lParam );
1152 #else
1153 return EnumFontFamiliesW( hDC, lpFaceName, FontFunc, lParam );
1154 #endif
1155 }
1156
1157 /*
1158 * @unimplemented
1159 */
1160 int
1161 STDCALL
1162 EnumFontsA (
1163 HDC hDC,
1164 LPCSTR lpFaceName,
1165 FONTENUMPROCA FontFunc,
1166 LPARAM lParam
1167 )
1168 {
1169 #if 0
1170 NTSTATUS Status;
1171 LPWSTR lpFaceNameW;
1172 int rc = 0;
1173
1174 Status = HEAP_strdupA2W ( &lpFaceNameW, lpFaceName );
1175 if (!NT_SUCCESS (Status))
1176 SetLastError (RtlNtStatusToDosError(Status));
1177 else
1178 {
1179 rc = NtGdiEnumFonts ( hDC, lpFaceNameW, FontFunc, lParam );
1180
1181 HEAP_free ( lpFaceNameW );
1182 }
1183 return rc;
1184 #else
1185 return EnumFontFamiliesA( hDC, lpFaceName, FontFunc, lParam );
1186 #endif
1187 }
1188
1189
1190
1191