Move CreateFontIndirectEx from stubs to font.c.
[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 { // Could use EnumLogFontExW2A here?
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 TMDIFF Tmd; // Should not be zero.
818
819 return NtGdiGetOutlineTextMetricsInternalW(hdc, cbData, lpOTM, &Tmd);
820 }
821
822
823 /*
824 * @implemented
825 */
826 HFONT
827 STDCALL
828 CreateFontIndirectExA(const ENUMLOGFONTEXDVA *elfexd)
829 {
830 if (elfexd)
831 {
832 ENUMLOGFONTEXDVW Logfont;
833
834 EnumLogFontExW2A( (LPENUMLOGFONTEXA) elfexd,
835 &Logfont.elfEnumLogfontEx );
836
837 RtlCopyMemory( &Logfont.elfDesignVector,
838 (PVOID) &elfexd->elfDesignVector,
839 sizeof(DESIGNVECTOR));
840
841 return NtGdiHfontCreate( &Logfont, 0, 0, 0, NULL);
842 }
843 else return NULL;
844 }
845
846
847 /*
848 * @implemented
849 */
850 HFONT
851 STDCALL
852 CreateFontIndirectExW(const ENUMLOGFONTEXDVW *elfexd)
853 {
854 /* Msdn: Note, this function ignores the elfDesignVector member in
855 ENUMLOGFONTEXDV.
856 */
857 if ( elfexd )
858 {
859 return NtGdiHfontCreate((PENUMLOGFONTEXDVW) elfexd, 0, 0, 0, NULL );
860 }
861 else return NULL;
862 }
863
864
865 /*
866 * @implemented
867 */
868 HFONT
869 STDCALL
870 CreateFontIndirectA(
871 CONST LOGFONTA *lplf
872 )
873 {
874 if (lplf)
875 {
876 LOGFONTW tlf;
877
878 LogFontA2W(&tlf, lplf);
879 return CreateFontIndirectW(&tlf);
880 }
881 else return NULL;
882 }
883
884
885 /*
886 * @implemented
887 */
888 HFONT
889 STDCALL
890 CreateFontIndirectW(
891 CONST LOGFONTW *lplf
892 )
893 {
894 if (lplf)
895 {
896 ENUMLOGFONTEXDVW Logfont;
897
898 RtlCopyMemory( &Logfont.elfEnumLogfontEx.elfLogFont, lplf, sizeof(LOGFONTW));
899 // Need something other than just cleaning memory here.
900 // Guess? Use caller data to determine the rest.
901 RtlZeroMemory( &Logfont.elfEnumLogfontEx.elfFullName,
902 sizeof(Logfont.elfEnumLogfontEx.elfFullName));
903 RtlZeroMemory( &Logfont.elfEnumLogfontEx.elfStyle,
904 sizeof(Logfont.elfEnumLogfontEx.elfStyle));
905 RtlZeroMemory( &Logfont.elfEnumLogfontEx.elfScript,
906 sizeof(Logfont.elfEnumLogfontEx.elfScript));
907
908 RtlZeroMemory( &Logfont.elfDesignVector, sizeof(DESIGNVECTOR));
909
910 return CreateFontIndirectExW(&Logfont);
911 }
912 else return NULL;
913 }
914
915
916 /*
917 * @implemented
918 */
919 HFONT
920 STDCALL
921 CreateFontA(
922 int nHeight,
923 int nWidth,
924 int nEscapement,
925 int nOrientation,
926 int fnWeight,
927 DWORD fdwItalic,
928 DWORD fdwUnderline,
929 DWORD fdwStrikeOut,
930 DWORD fdwCharSet,
931 DWORD fdwOutputPrecision,
932 DWORD fdwClipPrecision,
933 DWORD fdwQuality,
934 DWORD fdwPitchAndFamily,
935 LPCSTR lpszFace
936 )
937 {
938 ANSI_STRING StringA;
939 UNICODE_STRING StringU;
940 HFONT ret;
941
942 RtlInitAnsiString(&StringA, (LPSTR)lpszFace);
943 RtlAnsiStringToUnicodeString(&StringU, &StringA, TRUE);
944
945 ret = CreateFontW(nHeight,
946 nWidth,
947 nEscapement,
948 nOrientation,
949 fnWeight,
950 fdwItalic,
951 fdwUnderline,
952 fdwStrikeOut,
953 fdwCharSet,
954 fdwOutputPrecision,
955 fdwClipPrecision,
956 fdwQuality,
957 fdwPitchAndFamily,
958 StringU.Buffer);
959
960 RtlFreeUnicodeString(&StringU);
961
962 return ret;
963 }
964
965
966 /*
967 * @implemented
968 */
969 HFONT
970 STDCALL
971 CreateFontW(
972 int nHeight,
973 int nWidth,
974 int nEscapement,
975 int nOrientation,
976 int nWeight,
977 DWORD fnItalic,
978 DWORD fdwUnderline,
979 DWORD fdwStrikeOut,
980 DWORD fdwCharSet,
981 DWORD fdwOutputPrecision,
982 DWORD fdwClipPrecision,
983 DWORD fdwQuality,
984 DWORD fdwPitchAndFamily,
985 LPCWSTR lpszFace
986 )
987 {
988 LOGFONTW logfont;
989
990 logfont.lfHeight = nHeight;
991 logfont.lfWidth = nWidth;
992 logfont.lfEscapement = nEscapement;
993 logfont.lfOrientation = nOrientation;
994 logfont.lfWeight = nWeight;
995 logfont.lfItalic = fnItalic;
996 logfont.lfUnderline = fdwUnderline;
997 logfont.lfStrikeOut = fdwStrikeOut;
998 logfont.lfCharSet = fdwCharSet;
999 logfont.lfOutPrecision = fdwOutputPrecision;
1000 logfont.lfClipPrecision = fdwClipPrecision;
1001 logfont.lfQuality = fdwQuality;
1002 logfont.lfPitchAndFamily = fdwPitchAndFamily;
1003
1004 if (NULL != lpszFace)
1005 {
1006 int Size = sizeof(logfont.lfFaceName) / sizeof(WCHAR);
1007 wcsncpy((wchar_t *)logfont.lfFaceName, lpszFace, Size - 1);
1008 /* Be 101% sure to have '\0' at end of string */
1009 logfont.lfFaceName[Size - 1] = '\0';
1010 }
1011 else
1012 {
1013 logfont.lfFaceName[0] = L'\0';
1014 }
1015
1016 return CreateFontIndirectW(&logfont);
1017 }
1018
1019
1020 /*
1021 * @implemented
1022 */
1023 BOOL
1024 STDCALL
1025 CreateScalableFontResourceW(
1026 DWORD fdwHidden,
1027 LPCWSTR lpszFontRes,
1028 LPCWSTR lpszFontFile,
1029 LPCWSTR lpszCurrentPath
1030 )
1031 {
1032 return NtGdiCreateScalableFontResource ( fdwHidden,
1033 lpszFontRes,
1034 lpszFontFile,
1035 lpszCurrentPath );
1036 }
1037
1038
1039 /*
1040 * @implemented
1041 */
1042 BOOL
1043 STDCALL
1044 CreateScalableFontResourceA(
1045 DWORD fdwHidden,
1046 LPCSTR lpszFontRes,
1047 LPCSTR lpszFontFile,
1048 LPCSTR lpszCurrentPath
1049 )
1050 {
1051 NTSTATUS Status;
1052 LPWSTR lpszFontResW, lpszFontFileW, lpszCurrentPathW;
1053 BOOL rc = FALSE;
1054
1055 Status = HEAP_strdupA2W ( &lpszFontResW, lpszFontRes );
1056 if (!NT_SUCCESS (Status))
1057 SetLastError (RtlNtStatusToDosError(Status));
1058 else
1059 {
1060 Status = HEAP_strdupA2W ( &lpszFontFileW, lpszFontFile );
1061 if (!NT_SUCCESS (Status))
1062 SetLastError (RtlNtStatusToDosError(Status));
1063 else
1064 {
1065 Status = HEAP_strdupA2W ( &lpszCurrentPathW, lpszCurrentPath );
1066 if (!NT_SUCCESS (Status))
1067 SetLastError (RtlNtStatusToDosError(Status));
1068 else
1069 {
1070 rc = NtGdiCreateScalableFontResource ( fdwHidden,
1071 lpszFontResW,
1072 lpszFontFileW,
1073 lpszCurrentPathW );
1074
1075 HEAP_free ( lpszCurrentPathW );
1076 }
1077
1078 HEAP_free ( lpszFontFileW );
1079 }
1080
1081 HEAP_free ( lpszFontResW );
1082 }
1083 return rc;
1084 }
1085
1086
1087 /*
1088 * @implemented
1089 */
1090 int
1091 STDCALL
1092 AddFontResourceExW ( LPCWSTR lpszFilename, DWORD fl, PVOID pvReserved )
1093 {
1094 UNICODE_STRING Filename;
1095
1096 /* FIXME handle fl parameter */
1097 RtlInitUnicodeString(&Filename, lpszFilename);
1098 return NtGdiAddFontResource ( &Filename, fl );
1099 }
1100
1101
1102 /*
1103 * @implemented
1104 */
1105 int
1106 STDCALL
1107 AddFontResourceExA ( LPCSTR lpszFilename, DWORD fl, PVOID pvReserved )
1108 {
1109 NTSTATUS Status;
1110 PWSTR FilenameW;
1111 int rc = 0;
1112
1113 Status = HEAP_strdupA2W ( &FilenameW, lpszFilename );
1114 if ( !NT_SUCCESS (Status) )
1115 SetLastError (RtlNtStatusToDosError(Status));
1116 else
1117 {
1118 rc = AddFontResourceExW ( FilenameW, fl, pvReserved );
1119
1120 HEAP_free ( FilenameW );
1121 }
1122 return rc;
1123 }
1124
1125
1126 /*
1127 * @implemented
1128 */
1129 int
1130 STDCALL
1131 AddFontResourceA ( LPCSTR lpszFilename )
1132 {
1133 return AddFontResourceExA ( lpszFilename, 0, 0 );
1134 }
1135
1136
1137 /*
1138 * @implemented
1139 */
1140 int
1141 STDCALL
1142 AddFontResourceW ( LPCWSTR lpszFilename )
1143 {
1144 return AddFontResourceExW ( lpszFilename, 0, 0 );
1145 }
1146
1147
1148 /*
1149 * @implemented
1150 */
1151 BOOL
1152 STDCALL
1153 RemoveFontResourceW(
1154 LPCWSTR lpFileName
1155 )
1156 {
1157 return NtGdiRemoveFontResource ( lpFileName );
1158 }
1159
1160
1161 /*
1162 * @implemented
1163 */
1164 BOOL
1165 STDCALL
1166 RemoveFontResourceA(
1167 LPCSTR lpFileName
1168 )
1169 {
1170 NTSTATUS Status;
1171 LPWSTR lpFileNameW;
1172 BOOL rc = 0;
1173
1174 Status = HEAP_strdupA2W ( &lpFileNameW, lpFileName );
1175 if (!NT_SUCCESS (Status))
1176 SetLastError (RtlNtStatusToDosError(Status));
1177 else
1178 {
1179 rc = NtGdiRemoveFontResource ( lpFileNameW );
1180
1181 HEAP_free ( lpFileNameW );
1182 }
1183
1184 return rc;
1185 }
1186
1187 /***********************************************************************
1188 * GdiGetCharDimensions
1189 *
1190 * Gets the average width of the characters in the English alphabet.
1191 *
1192 * PARAMS
1193 * hdc [I] Handle to the device context to measure on.
1194 * lptm [O] Pointer to memory to store the text metrics into.
1195 * height [O] On exit, the maximum height of characters in the English alphabet.
1196 *
1197 * RETURNS
1198 * The average width of characters in the English alphabet.
1199 *
1200 * NOTES
1201 * This function is used by the dialog manager to get the size of a dialog
1202 * unit. It should also be used by other pieces of code that need to know
1203 * the size of a dialog unit in logical units without having access to the
1204 * window handle of the dialog.
1205 * Windows caches the font metrics from this function, but we don't and
1206 * there doesn't appear to be an immediate advantage to do so.
1207 *
1208 * SEE ALSO
1209 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
1210 *
1211 * Despite most of MSDN insisting that the horizontal base unit is
1212 * tmAveCharWidth it isn't. Knowledge base article Q145994
1213 * "HOWTO: Calculate Dialog Units When Not Using the System Font",
1214 * says that we should take the average of the 52 English upper and lower
1215 * case characters.
1216 */
1217 /*
1218 * @implemented
1219 */
1220 DWORD
1221 STDCALL
1222 GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
1223 {
1224 SIZE sz;
1225 static const WCHAR alphabet[] = {
1226 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
1227 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
1228 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
1229
1230 if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
1231
1232 if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
1233
1234 if (height) *height = sz.cy;
1235 return (sz.cx / 26 + 1) / 2;
1236 }
1237
1238
1239 /*
1240 * @unimplemented
1241 */
1242 int
1243 STDCALL
1244 EnumFontsW(
1245 HDC hDC,
1246 LPCWSTR lpFaceName,
1247 FONTENUMPROCW FontFunc,
1248 LPARAM lParam
1249 )
1250 {
1251 #if 0
1252 return NtGdiEnumFonts ( hDC, lpFaceName, FontFunc, lParam );
1253 #else
1254 return EnumFontFamiliesW( hDC, lpFaceName, FontFunc, lParam );
1255 #endif
1256 }
1257
1258 /*
1259 * @unimplemented
1260 */
1261 int
1262 STDCALL
1263 EnumFontsA (
1264 HDC hDC,
1265 LPCSTR lpFaceName,
1266 FONTENUMPROCA FontFunc,
1267 LPARAM lParam
1268 )
1269 {
1270 #if 0
1271 NTSTATUS Status;
1272 LPWSTR lpFaceNameW;
1273 int rc = 0;
1274
1275 Status = HEAP_strdupA2W ( &lpFaceNameW, lpFaceName );
1276 if (!NT_SUCCESS (Status))
1277 SetLastError (RtlNtStatusToDosError(Status));
1278 else
1279 {
1280 rc = NtGdiEnumFonts ( hDC, lpFaceNameW, FontFunc, lParam );
1281
1282 HEAP_free ( lpFaceNameW );
1283 }
1284 return rc;
1285 #else
1286 return EnumFontFamiliesA( hDC, lpFaceName, FontFunc, lParam );
1287 #endif
1288 }
1289
1290
1291
1292