- Major Win32k Header Cleanup: Add ntgdi.h based on latest Platform SDK Public header...
[reactos.git] / reactos / lib / 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 static BOOL FASTCALL
19 MetricsCharConvert(WCHAR w, UCHAR *b)
20 {
21 UNICODE_STRING WString;
22 WCHAR WBuf[2];
23 ANSI_STRING AString;
24 CHAR ABuf[2];
25 NTSTATUS Status;
26
27 if (L'\0' == w)
28 {
29 *b = '\0';
30 }
31 else
32 {
33 WBuf[0] = w;
34 WBuf[1] = L'\0';
35 RtlInitUnicodeString(&WString, WBuf);
36 ABuf[0] = '*';
37 ABuf[1] = L'\0';
38 RtlInitAnsiString(&AString, ABuf);
39
40 Status = RtlUnicodeStringToAnsiString(&AString, &WString, FALSE);
41 if (! NT_SUCCESS(Status))
42 {
43 SetLastError(RtlNtStatusToDosError(Status));
44 return FALSE;
45 }
46 *b = ABuf[0];
47 }
48
49 return TRUE;
50 }
51
52 BOOL FASTCALL
53 TextMetricW2A(TEXTMETRICA *tma, TEXTMETRICW *tmw)
54 {
55 UNICODE_STRING WString;
56 WCHAR WBuf[256];
57 ANSI_STRING AString;
58 CHAR ABuf[256];
59 UINT Letter;
60 NTSTATUS Status;
61
62 tma->tmHeight = tmw->tmHeight;
63 tma->tmAscent = tmw->tmAscent;
64 tma->tmDescent = tmw->tmDescent;
65 tma->tmInternalLeading = tmw->tmInternalLeading;
66 tma->tmExternalLeading = tmw->tmExternalLeading;
67 tma->tmAveCharWidth = tmw->tmAveCharWidth;
68 tma->tmMaxCharWidth = tmw->tmMaxCharWidth;
69 tma->tmWeight = tmw->tmWeight;
70 tma->tmOverhang = tmw->tmOverhang;
71 tma->tmDigitizedAspectX = tmw->tmDigitizedAspectX;
72 tma->tmDigitizedAspectY = tmw->tmDigitizedAspectY;
73
74 /* The Unicode FirstChar/LastChar need not correspond to the ANSI
75 FirstChar/LastChar. For example, if the font contains glyphs for
76 letters A-Z and an accented version of the letter e, the Unicode
77 FirstChar would be A and the Unicode LastChar would be the accented
78 e. If you just translate those to ANSI, the range would become
79 letters A-E instead of A-Z.
80 We translate all possible ANSI chars to Unicode and find the first
81 and last translated character which fall into the Unicode FirstChar/
82 LastChar range and return the corresponding ANSI char. */
83
84 /* Setup an Ansi string containing all possible letters (note: skip '\0' at
85 the beginning since that would be interpreted as end-of-string, handle
86 '\0' special later */
87 for (Letter = 1; Letter < 256; Letter++)
88 {
89 ABuf[Letter - 1] = (CHAR) Letter;
90 WBuf[Letter - 1] = L' ';
91 }
92 ABuf[255] = '\0';
93 WBuf[255] = L'\0';
94 RtlInitAnsiString(&AString, ABuf);
95 RtlInitUnicodeString(&WString, WBuf);
96
97 /* Find the corresponding Unicode characters */
98 Status = RtlAnsiStringToUnicodeString(&WString, &AString, FALSE);
99 if (! NT_SUCCESS(Status))
100 {
101 SetLastError(RtlNtStatusToDosError(Status));
102 return FALSE;
103 }
104
105 /* Scan for the first ANSI character which maps to an Unicode character
106 in the range */
107 tma->tmFirstChar = '\0';
108 if (L'\0' != tmw->tmFirstChar)
109 {
110 for (Letter = 1; Letter < 256; Letter++)
111 {
112 if (tmw->tmFirstChar <= WBuf[Letter - 1] &&
113 WBuf[Letter - 1] <= tmw->tmLastChar)
114 {
115 tma->tmFirstChar = (CHAR) Letter;
116 break;
117 }
118 }
119 }
120
121 /* Scan for the last ANSI character which maps to an Unicode character
122 in the range */
123 tma->tmLastChar = '\0';
124 if (L'\0' != tmw->tmLastChar)
125 {
126 for (Letter = 255; 0 < Letter; Letter--)
127 {
128 if (tmw->tmFirstChar <= WBuf[Letter - 1] &&
129 WBuf[Letter - 1] <= tmw->tmLastChar)
130 {
131 tma->tmLastChar = (CHAR) Letter;
132 break;
133 }
134 }
135 }
136
137 if (! MetricsCharConvert(tmw->tmDefaultChar, &tma->tmDefaultChar) ||
138 ! MetricsCharConvert(tmw->tmBreakChar, &tma->tmBreakChar))
139 {
140 return FALSE;
141 }
142
143 tma->tmItalic = tmw->tmItalic;
144 tma->tmUnderlined = tmw->tmUnderlined;
145 tma->tmStruckOut = tmw->tmStruckOut;
146 tma->tmPitchAndFamily = tmw->tmPitchAndFamily;
147 tma->tmCharSet = tmw->tmCharSet;
148
149 return TRUE;
150 }
151
152 BOOL FASTCALL
153 NewTextMetricW2A(NEWTEXTMETRICA *tma, NEWTEXTMETRICW *tmw)
154 {
155 if (! TextMetricW2A((TEXTMETRICA *) tma, (TEXTMETRICW *) tmw))
156 {
157 return FALSE;
158 }
159
160 tma->ntmFlags = tmw->ntmFlags;
161 tma->ntmSizeEM = tmw->ntmSizeEM;
162 tma->ntmCellHeight = tmw->ntmCellHeight;
163 tma->ntmAvgWidth = tmw->ntmAvgWidth;
164
165 return TRUE;
166 }
167
168 BOOL FASTCALL
169 NewTextMetricExW2A(NEWTEXTMETRICEXA *tma, NEWTEXTMETRICEXW *tmw)
170 {
171 if (! NewTextMetricW2A(&tma->ntmTm, &tmw->ntmTm))
172 {
173 return FALSE;
174 }
175
176 tma->ntmFontSig = tmw->ntmFontSig;
177
178 return TRUE;
179 }
180
181 static int FASTCALL
182 IntEnumFontFamilies(HDC Dc, LPLOGFONTW LogFont, PVOID EnumProc, LPARAM lParam,
183 BOOL Unicode)
184 {
185 int FontFamilyCount;
186 int FontFamilySize;
187 PFONTFAMILYINFO Info;
188 int Ret = 0;
189 int i;
190 ENUMLOGFONTEXA EnumLogFontExA;
191 NEWTEXTMETRICEXA NewTextMetricExA;
192
193 Info = RtlAllocateHeap(GetProcessHeap(), 0,
194 INITIAL_FAMILY_COUNT * sizeof(FONTFAMILYINFO));
195 if (NULL == Info)
196 {
197 return 0;
198 }
199 FontFamilyCount = NtGdiGetFontFamilyInfo(Dc, LogFont, Info, INITIAL_FAMILY_COUNT);
200 if (FontFamilyCount < 0)
201 {
202 RtlFreeHeap(GetProcessHeap(), 0, Info);
203 return 0;
204 }
205 if (INITIAL_FAMILY_COUNT < FontFamilyCount)
206 {
207 FontFamilySize = FontFamilyCount;
208 RtlFreeHeap(GetProcessHeap(), 0, Info);
209 Info = RtlAllocateHeap(GetProcessHeap(), 0,
210 FontFamilyCount * sizeof(FONTFAMILYINFO));
211 if (NULL == Info)
212 {
213 return 0;
214 }
215 FontFamilyCount = NtGdiGetFontFamilyInfo(Dc, LogFont, Info, FontFamilySize);
216 if (FontFamilyCount < 0 || FontFamilySize < FontFamilyCount)
217 {
218 RtlFreeHeap(GetProcessHeap(), 0, Info);
219 return 0;
220 }
221 }
222
223 for (i = 0; i < FontFamilyCount; i++)
224 {
225 if (Unicode)
226 {
227 Ret = ((FONTENUMPROCW) EnumProc)(
228 (LPLOGFONTW)&Info[i].EnumLogFontEx,
229 (LPTEXTMETRICW)&Info[i].NewTextMetricEx,
230 Info[i].FontType, lParam);
231 }
232 else
233 {
234 LogFontW2A(&EnumLogFontExA.elfLogFont, &Info[i].EnumLogFontEx.elfLogFont);
235 WideCharToMultiByte(CP_THREAD_ACP, 0, Info[i].EnumLogFontEx.elfFullName, -1,
236 (LPSTR)EnumLogFontExA.elfFullName, LF_FULLFACESIZE, NULL, NULL);
237 WideCharToMultiByte(CP_THREAD_ACP, 0, Info[i].EnumLogFontEx.elfStyle, -1,
238 (LPSTR)EnumLogFontExA.elfStyle, LF_FACESIZE, NULL, NULL);
239 WideCharToMultiByte(CP_THREAD_ACP, 0, Info[i].EnumLogFontEx.elfScript, -1,
240 (LPSTR)EnumLogFontExA.elfScript, LF_FACESIZE, NULL, NULL);
241 NewTextMetricExW2A(&NewTextMetricExA,
242 &Info[i].NewTextMetricEx);
243 Ret = ((FONTENUMPROCA) EnumProc)(
244 (LPLOGFONTA)&EnumLogFontExA,
245 (LPTEXTMETRICA)&NewTextMetricExA,
246 Info[i].FontType, lParam);
247 }
248 }
249
250 RtlFreeHeap(GetProcessHeap(), 0, Info);
251
252 return Ret;
253 }
254
255 /*
256 * @implemented
257 */
258 int STDCALL
259 EnumFontFamiliesExW(HDC hdc, LPLOGFONTW lpLogfont, FONTENUMPROCW lpEnumFontFamExProc,
260 LPARAM lParam, DWORD dwFlags)
261 {
262 return IntEnumFontFamilies(hdc, lpLogfont, lpEnumFontFamExProc, lParam, TRUE);
263 }
264
265
266 /*
267 * @implemented
268 */
269 int STDCALL
270 EnumFontFamiliesW(HDC hdc, LPCWSTR lpszFamily, FONTENUMPROCW lpEnumFontFamProc,
271 LPARAM lParam)
272 {
273 LOGFONTW LogFont;
274
275 ZeroMemory(&LogFont, sizeof(LOGFONTW));
276 LogFont.lfCharSet = DEFAULT_CHARSET;
277 if (NULL != lpszFamily)
278 {
279 lstrcpynW(LogFont.lfFaceName, lpszFamily, LF_FACESIZE);
280 }
281
282 return IntEnumFontFamilies(hdc, &LogFont, lpEnumFontFamProc, lParam, TRUE);
283 }
284
285
286 /*
287 * @implemented
288 */
289 int STDCALL
290 EnumFontFamiliesExA (HDC hdc, LPLOGFONTA lpLogfont, FONTENUMPROCA lpEnumFontFamExProc,
291 LPARAM lParam, DWORD dwFlags)
292 {
293 LOGFONTW LogFontW;
294
295 LogFontA2W(&LogFontW, lpLogfont);
296
297 /* no need to convert LogFontW back to lpLogFont b/c it's an [in] parameter only */
298 return IntEnumFontFamilies(hdc, &LogFontW, lpEnumFontFamExProc, lParam, FALSE);
299 }
300
301
302 /*
303 * @implemented
304 */
305 int STDCALL
306 EnumFontFamiliesA(HDC hdc, LPCSTR lpszFamily, FONTENUMPROCA lpEnumFontFamProc,
307 LPARAM lParam)
308 {
309 LOGFONTW LogFont;
310
311 ZeroMemory(&LogFont, sizeof(LOGFONTW));
312 LogFont.lfCharSet = DEFAULT_CHARSET;
313 if (NULL != lpszFamily)
314 {
315 MultiByteToWideChar(CP_THREAD_ACP, 0, lpszFamily, -1, LogFont.lfFaceName, LF_FACESIZE);
316 }
317
318 return IntEnumFontFamilies(hdc, &LogFont, lpEnumFontFamProc, lParam, FALSE);
319 }
320
321
322 /*
323 * @implemented
324 */
325 BOOL
326 STDCALL
327 GetCharWidthA (
328 HDC hdc,
329 UINT iFirstChar,
330 UINT iLastChar,
331 LPINT lpBuffer
332 )
333 {
334 /* FIXME what to do with iFirstChar and iLastChar ??? */
335 return NtGdiGetCharWidth32 ( hdc, iFirstChar, iLastChar, lpBuffer );
336 }
337
338
339 /*
340 * @implemented
341 */
342 BOOL
343 STDCALL
344 GetCharWidth32A(
345 HDC hdc,
346 UINT iFirstChar,
347 UINT iLastChar,
348 LPINT lpBuffer
349 )
350 {
351 /* FIXME what to do with iFirstChar and iLastChar ??? */
352 return NtGdiGetCharWidth32 ( hdc, iFirstChar, iLastChar, lpBuffer );
353 }
354
355
356 /*
357 * @implemented
358 */
359 BOOL
360 STDCALL
361 GetCharWidthW (
362 HDC hdc,
363 UINT iFirstChar,
364 UINT iLastChar,
365 LPINT lpBuffer
366 )
367 {
368 return NtGdiGetCharWidth32 ( hdc, iFirstChar, iLastChar, lpBuffer );
369 }
370
371
372 /*
373 * @implemented
374 */
375 DWORD
376 STDCALL
377 GetCharacterPlacementW(
378 HDC hdc,
379 LPCWSTR lpString,
380 INT uCount,
381 INT nMaxExtent,
382 GCP_RESULTSW *lpResults,
383 DWORD dwFlags
384 )
385 {
386 DWORD ret=0;
387 SIZE size;
388 UINT i, nSet;
389
390 if(dwFlags&(~GCP_REORDER)) DPRINT("flags 0x%08lx ignored\n", dwFlags);
391 if(lpResults->lpClass) DPRINT("classes not implemented\n");
392 if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
393 DPRINT("Caret positions for complex scripts not implemented\n");
394
395 nSet = (UINT)uCount;
396 if(nSet > lpResults->nGlyphs)
397 nSet = lpResults->nGlyphs;
398
399 /* return number of initialized fields */
400 lpResults->nGlyphs = nSet;
401
402 /*if((dwFlags&GCP_REORDER)==0 || !BidiAvail)
403 {*/
404 /* Treat the case where no special handling was requested in a fastpath way */
405 /* copy will do if the GCP_REORDER flag is not set */
406 if(lpResults->lpOutString)
407 lstrcpynW( lpResults->lpOutString, lpString, nSet );
408
409 if(lpResults->lpGlyphs)
410 lstrcpynW( lpResults->lpGlyphs, lpString, nSet );
411
412 if(lpResults->lpOrder)
413 {
414 for(i = 0; i < nSet; i++)
415 lpResults->lpOrder[i] = i;
416 }
417 /*} else
418 {
419 BIDI_Reorder( lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
420 nSet, lpResults->lpOrder );
421 }*/
422
423 /* FIXME: Will use the placement chars */
424 if (lpResults->lpDx)
425 {
426 int c;
427 for (i = 0; i < nSet; i++)
428 {
429 if (NtGdiGetCharWidth32(hdc, lpString[i], lpString[i], &c))
430 lpResults->lpDx[i]= c;
431 }
432 }
433
434 if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
435 {
436 int pos = 0;
437
438 lpResults->lpCaretPos[0] = 0;
439 for (i = 1; i < nSet; i++)
440 if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
441 lpResults->lpCaretPos[i] = (pos += size.cx);
442 }
443
444 /*if(lpResults->lpGlyphs)
445 GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);*/
446
447 if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
448 ret = MAKELONG(size.cx, size.cy);
449
450 return ret;
451 }
452
453
454 /*
455 * @unimplemented
456 */
457 BOOL
458 APIENTRY
459 GetCharWidthFloatA(
460 HDC hdc,
461 UINT iFirstChar,
462 UINT iLastChar,
463 PFLOAT pxBuffer
464 )
465 {
466 /* FIXME what to do with iFirstChar and iLastChar ??? */
467 return NtGdiGetCharWidthFloat ( hdc, iFirstChar, iLastChar, pxBuffer );
468 }
469
470
471 /*
472 * @unimplemented
473 */
474 BOOL
475 APIENTRY
476 GetCharABCWidthsA(
477 HDC hdc,
478 UINT uFirstChar,
479 UINT uLastChar,
480 LPABC lpabc
481 )
482 {
483 /* FIXME what to do with uFirstChar and uLastChar ??? */
484 return NtGdiGetCharABCWidths ( hdc, uFirstChar, uLastChar, lpabc );
485 }
486
487
488 /*
489 * @unimplemented
490 */
491 BOOL
492 APIENTRY
493 GetCharABCWidthsFloatA(
494 HDC hdc,
495 UINT iFirstChar,
496 UINT iLastChar,
497 LPABCFLOAT lpABCF
498 )
499 {
500 /* FIXME what to do with iFirstChar and iLastChar ??? */
501 return NtGdiGetCharABCWidthsFloat ( hdc, iFirstChar, iLastChar, lpABCF );
502 }
503
504
505 /*
506 * @implemented
507 */
508 DWORD
509 STDCALL
510 GetGlyphOutlineA(
511 HDC hdc,
512 UINT uChar,
513 UINT uFormat,
514 LPGLYPHMETRICS lpgm,
515 DWORD cbBuffer,
516 LPVOID lpvBuffer,
517 CONST MAT2 *lpmat2
518 )
519 {
520 return NtGdiGetGlyphOutline ( hdc, uChar, uFormat, lpgm, cbBuffer, lpvBuffer, (CONST LPMAT2)lpmat2, TRUE);
521 }
522
523 /*
524 * @implemented
525 */
526 DWORD
527 STDCALL
528 GetGlyphOutlineW(
529 HDC hdc,
530 UINT uChar,
531 UINT uFormat,
532 LPGLYPHMETRICS lpgm,
533 DWORD cbBuffer,
534 LPVOID lpvBuffer,
535 CONST MAT2 *lpmat2
536 )
537 {
538 return NtGdiGetGlyphOutline ( hdc, uChar, uFormat, lpgm, cbBuffer, lpvBuffer, (CONST LPMAT2)lpmat2, TRUE);
539 }
540
541
542
543 /*
544 * @implemented
545 */
546 HFONT
547 STDCALL
548 CreateFontIndirectA(
549 CONST LOGFONTA *lplf
550 )
551 {
552 LOGFONTW tlf;
553
554 LogFontA2W(&tlf, lplf);
555
556 return NtGdiCreateFontIndirect(&tlf);
557 }
558
559
560 /*
561 * @implemented
562 */
563 HFONT
564 STDCALL
565 CreateFontIndirectW(
566 CONST LOGFONTW *lplf
567 )
568 {
569 return NtGdiCreateFontIndirect((CONST LPLOGFONTW)lplf);
570 }
571
572
573 /*
574 * @implemented
575 */
576 HFONT
577 STDCALL
578 CreateFontA(
579 int nHeight,
580 int nWidth,
581 int nEscapement,
582 int nOrientation,
583 int fnWeight,
584 DWORD fdwItalic,
585 DWORD fdwUnderline,
586 DWORD fdwStrikeOut,
587 DWORD fdwCharSet,
588 DWORD fdwOutputPrecision,
589 DWORD fdwClipPrecision,
590 DWORD fdwQuality,
591 DWORD fdwPitchAndFamily,
592 LPCSTR lpszFace
593 )
594 {
595 ANSI_STRING StringA;
596 UNICODE_STRING StringU;
597 HFONT ret;
598
599 RtlInitAnsiString(&StringA, (LPSTR)lpszFace);
600 RtlAnsiStringToUnicodeString(&StringU, &StringA, TRUE);
601
602 ret = CreateFontW(nHeight, nWidth, nEscapement, nOrientation, fnWeight, fdwItalic, fdwUnderline, fdwStrikeOut,
603 fdwCharSet, fdwOutputPrecision, fdwClipPrecision, fdwQuality, fdwPitchAndFamily, StringU.Buffer);
604
605 RtlFreeUnicodeString(&StringU);
606
607 return ret;
608 }
609
610
611 /*
612 * @implemented
613 */
614 HFONT
615 STDCALL
616 CreateFontW(
617 int nHeight,
618 int nWidth,
619 int nEscapement,
620 int nOrientation,
621 int nWeight,
622 DWORD fnItalic,
623 DWORD fdwUnderline,
624 DWORD fdwStrikeOut,
625 DWORD fdwCharSet,
626 DWORD fdwOutputPrecision,
627 DWORD fdwClipPrecision,
628 DWORD fdwQuality,
629 DWORD fdwPitchAndFamily,
630 LPCWSTR lpszFace
631 )
632 {
633 return NtGdiCreateFont(nHeight, nWidth, nEscapement, nOrientation, nWeight, fnItalic, fdwUnderline, fdwStrikeOut,
634 fdwCharSet, fdwOutputPrecision, fdwClipPrecision, fdwQuality, fdwPitchAndFamily, lpszFace);
635 }
636
637
638 /*
639 * @implemented
640 */
641 BOOL
642 STDCALL
643 CreateScalableFontResourceW(
644 DWORD fdwHidden,
645 LPCWSTR lpszFontRes,
646 LPCWSTR lpszFontFile,
647 LPCWSTR lpszCurrentPath
648 )
649 {
650 return NtGdiCreateScalableFontResource ( fdwHidden,
651 lpszFontRes,
652 lpszFontFile,
653 lpszCurrentPath );
654 }
655
656
657 /*
658 * @implemented
659 */
660 BOOL
661 STDCALL
662 CreateScalableFontResourceA(
663 DWORD fdwHidden,
664 LPCSTR lpszFontRes,
665 LPCSTR lpszFontFile,
666 LPCSTR lpszCurrentPath
667 )
668 {
669 NTSTATUS Status;
670 LPWSTR lpszFontResW, lpszFontFileW, lpszCurrentPathW;
671 BOOL rc = FALSE;
672
673 Status = HEAP_strdupA2W ( &lpszFontResW, lpszFontRes );
674 if (!NT_SUCCESS (Status))
675 SetLastError (RtlNtStatusToDosError(Status));
676 else
677 {
678 Status = HEAP_strdupA2W ( &lpszFontFileW, lpszFontFile );
679 if (!NT_SUCCESS (Status))
680 SetLastError (RtlNtStatusToDosError(Status));
681 else
682 {
683 Status = HEAP_strdupA2W ( &lpszCurrentPathW, lpszCurrentPath );
684 if (!NT_SUCCESS (Status))
685 SetLastError (RtlNtStatusToDosError(Status));
686 else
687 {
688 rc = NtGdiCreateScalableFontResource ( fdwHidden,
689 lpszFontResW,
690 lpszFontFileW,
691 lpszCurrentPathW );
692
693 HEAP_free ( lpszCurrentPathW );
694 }
695
696 HEAP_free ( lpszFontFileW );
697 }
698
699 HEAP_free ( lpszFontResW );
700 }
701 return rc;
702 }
703
704
705 /*
706 * @implemented
707 */
708 int
709 STDCALL
710 AddFontResourceExW ( LPCWSTR lpszFilename, DWORD fl, PVOID pvReserved )
711 {
712 UNICODE_STRING Filename;
713
714 /* FIXME handle fl parameter */
715 RtlInitUnicodeString(&Filename, lpszFilename);
716 return NtGdiAddFontResource ( &Filename, fl );
717 }
718
719
720 /*
721 * @implemented
722 */
723 int
724 STDCALL
725 AddFontResourceExA ( LPCSTR lpszFilename, DWORD fl, PVOID pvReserved )
726 {
727 NTSTATUS Status;
728 PWSTR FilenameW;
729 int rc = 0;
730
731 Status = HEAP_strdupA2W ( &FilenameW, lpszFilename );
732 if ( !NT_SUCCESS (Status) )
733 SetLastError (RtlNtStatusToDosError(Status));
734 else
735 {
736 rc = AddFontResourceExW ( FilenameW, fl, pvReserved );
737
738 HEAP_free ( FilenameW );
739 }
740 return rc;
741 }
742
743
744 /*
745 * @implemented
746 */
747 int
748 STDCALL
749 AddFontResourceA ( LPCSTR lpszFilename )
750 {
751 return AddFontResourceExA ( lpszFilename, 0, 0 );
752 }
753
754
755 /*
756 * @implemented
757 */
758 int
759 STDCALL
760 AddFontResourceW ( LPCWSTR lpszFilename )
761 {
762 return AddFontResourceExW ( lpszFilename, 0, 0 );
763 }
764
765
766 /*
767 * @implemented
768 */
769 BOOL
770 STDCALL
771 RemoveFontResourceW(
772 LPCWSTR lpFileName
773 )
774 {
775 return NtGdiRemoveFontResource ( lpFileName );
776 }
777
778
779 /*
780 * @implemented
781 */
782 BOOL
783 STDCALL
784 RemoveFontResourceA(
785 LPCSTR lpFileName
786 )
787 {
788 NTSTATUS Status;
789 LPWSTR lpFileNameW;
790 BOOL rc = 0;
791
792 Status = HEAP_strdupA2W ( &lpFileNameW, lpFileName );
793 if (!NT_SUCCESS (Status))
794 SetLastError (RtlNtStatusToDosError(Status));
795 else
796 {
797 rc = NtGdiRemoveFontResource ( lpFileNameW );
798
799 HEAP_free ( lpFileNameW );
800 }
801
802 return rc;
803 }
804
805 /***********************************************************************
806 * GdiGetCharDimensions
807 *
808 * Gets the average width of the characters in the English alphabet.
809 *
810 * PARAMS
811 * hdc [I] Handle to the device context to measure on.
812 * lptm [O] Pointer to memory to store the text metrics into.
813 * height [O] On exit, the maximum height of characters in the English alphabet.
814 *
815 * RETURNS
816 * The average width of characters in the English alphabet.
817 *
818 * NOTES
819 * This function is used by the dialog manager to get the size of a dialog
820 * unit. It should also be used by other pieces of code that need to know
821 * the size of a dialog unit in logical units without having access to the
822 * window handle of the dialog.
823 * Windows caches the font metrics from this function, but we don't and
824 * there doesn't appear to be an immediate advantage to do so.
825 *
826 * SEE ALSO
827 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
828 *
829 * Despite most of MSDN insisting that the horizontal base unit is
830 * tmAveCharWidth it isn't. Knowledge base article Q145994
831 * "HOWTO: Calculate Dialog Units When Not Using the System Font",
832 * says that we should take the average of the 52 English upper and lower
833 * case characters.
834 */
835 /*
836 * @implemented
837 */
838 DWORD
839 STDCALL
840 GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
841 {
842 SIZE sz;
843 static const WCHAR alphabet[] = {
844 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
845 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
846 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
847
848 if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
849
850 if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
851
852 if (height) *height = sz.cy;
853 return (sz.cx / 26 + 1) / 2;
854 }
855
856
857 /*
858 * @unimplemented
859 */
860 int
861 STDCALL
862 EnumFontsW(
863 HDC hDC,
864 LPCWSTR lpFaceName,
865 FONTENUMPROCW FontFunc,
866 LPARAM lParam
867 )
868 {
869 #if 0
870 return NtGdiEnumFonts ( hDC, lpFaceName, FontFunc, lParam );
871 #else
872 return EnumFontFamiliesW( hDC, lpFaceName, FontFunc, lParam );
873 #endif
874 }
875
876 /*
877 * @unimplemented
878 */
879 int
880 STDCALL
881 EnumFontsA (
882 HDC hDC,
883 LPCSTR lpFaceName,
884 FONTENUMPROCA FontFunc,
885 LPARAM lParam
886 )
887 {
888 #if 0
889 NTSTATUS Status;
890 LPWSTR lpFaceNameW;
891 int rc = 0;
892
893 Status = HEAP_strdupA2W ( &lpFaceNameW, lpFaceName );
894 if (!NT_SUCCESS (Status))
895 SetLastError (RtlNtStatusToDosError(Status));
896 else
897 {
898 rc = NtGdiEnumFonts ( hDC, lpFaceNameW, FontFunc, lParam );
899
900 HEAP_free ( lpFaceNameW );
901 }
902 return rc;
903 #else
904 return EnumFontFamiliesA( hDC, lpFaceName, FontFunc, lParam );
905 #endif
906 }
907
908
909
910