Implement GdiGetCharDimensions by Robert Shearman rob@codeweavers.com.
[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 );
521 }
522
523
524 /*
525 * @implemented
526 */
527 HFONT
528 STDCALL
529 CreateFontIndirectA(
530 CONST LOGFONTA *lplf
531 )
532 {
533 LOGFONTW tlf;
534
535 LogFontA2W(&tlf, lplf);
536
537 return NtGdiCreateFontIndirect(&tlf);
538 }
539
540
541 /*
542 * @implemented
543 */
544 HFONT
545 STDCALL
546 CreateFontIndirectW(
547 CONST LOGFONTW *lplf
548 )
549 {
550 return NtGdiCreateFontIndirect((CONST LPLOGFONTW)lplf);
551 }
552
553
554 /*
555 * @implemented
556 */
557 HFONT
558 STDCALL
559 CreateFontA(
560 int nHeight,
561 int nWidth,
562 int nEscapement,
563 int nOrientation,
564 int fnWeight,
565 DWORD fdwItalic,
566 DWORD fdwUnderline,
567 DWORD fdwStrikeOut,
568 DWORD fdwCharSet,
569 DWORD fdwOutputPrecision,
570 DWORD fdwClipPrecision,
571 DWORD fdwQuality,
572 DWORD fdwPitchAndFamily,
573 LPCSTR lpszFace
574 )
575 {
576 ANSI_STRING StringA;
577 UNICODE_STRING StringU;
578 HFONT ret;
579
580 RtlInitAnsiString(&StringA, (LPSTR)lpszFace);
581 RtlAnsiStringToUnicodeString(&StringU, &StringA, TRUE);
582
583 ret = CreateFontW(nHeight, nWidth, nEscapement, nOrientation, fnWeight, fdwItalic, fdwUnderline, fdwStrikeOut,
584 fdwCharSet, fdwOutputPrecision, fdwClipPrecision, fdwQuality, fdwPitchAndFamily, StringU.Buffer);
585
586 RtlFreeUnicodeString(&StringU);
587
588 return ret;
589 }
590
591
592 /*
593 * @implemented
594 */
595 HFONT
596 STDCALL
597 CreateFontW(
598 int nHeight,
599 int nWidth,
600 int nEscapement,
601 int nOrientation,
602 int nWeight,
603 DWORD fnItalic,
604 DWORD fdwUnderline,
605 DWORD fdwStrikeOut,
606 DWORD fdwCharSet,
607 DWORD fdwOutputPrecision,
608 DWORD fdwClipPrecision,
609 DWORD fdwQuality,
610 DWORD fdwPitchAndFamily,
611 LPCWSTR lpszFace
612 )
613 {
614 return NtGdiCreateFont(nHeight, nWidth, nEscapement, nOrientation, nWeight, fnItalic, fdwUnderline, fdwStrikeOut,
615 fdwCharSet, fdwOutputPrecision, fdwClipPrecision, fdwQuality, fdwPitchAndFamily, lpszFace);
616 }
617
618
619 /*
620 * @implemented
621 */
622 BOOL
623 STDCALL
624 CreateScalableFontResourceW(
625 DWORD fdwHidden,
626 LPCWSTR lpszFontRes,
627 LPCWSTR lpszFontFile,
628 LPCWSTR lpszCurrentPath
629 )
630 {
631 return NtGdiCreateScalableFontResource ( fdwHidden,
632 lpszFontRes,
633 lpszFontFile,
634 lpszCurrentPath );
635 }
636
637
638 /*
639 * @implemented
640 */
641 BOOL
642 STDCALL
643 CreateScalableFontResourceA(
644 DWORD fdwHidden,
645 LPCSTR lpszFontRes,
646 LPCSTR lpszFontFile,
647 LPCSTR lpszCurrentPath
648 )
649 {
650 NTSTATUS Status;
651 LPWSTR lpszFontResW, lpszFontFileW, lpszCurrentPathW;
652 BOOL rc = FALSE;
653
654 Status = HEAP_strdupA2W ( &lpszFontResW, lpszFontRes );
655 if (!NT_SUCCESS (Status))
656 SetLastError (RtlNtStatusToDosError(Status));
657 else
658 {
659 Status = HEAP_strdupA2W ( &lpszFontFileW, lpszFontFile );
660 if (!NT_SUCCESS (Status))
661 SetLastError (RtlNtStatusToDosError(Status));
662 else
663 {
664 Status = HEAP_strdupA2W ( &lpszCurrentPathW, lpszCurrentPath );
665 if (!NT_SUCCESS (Status))
666 SetLastError (RtlNtStatusToDosError(Status));
667 else
668 {
669 rc = NtGdiCreateScalableFontResource ( fdwHidden,
670 lpszFontResW,
671 lpszFontFileW,
672 lpszCurrentPathW );
673
674 HEAP_free ( lpszCurrentPathW );
675 }
676
677 HEAP_free ( lpszFontFileW );
678 }
679
680 HEAP_free ( lpszFontResW );
681 }
682 return rc;
683 }
684
685
686 /*
687 * @implemented
688 */
689 int
690 STDCALL
691 AddFontResourceExW ( LPCWSTR lpszFilename, DWORD fl, PVOID pvReserved )
692 {
693 UNICODE_STRING Filename;
694
695 /* FIXME handle fl parameter */
696 RtlInitUnicodeString(&Filename, lpszFilename);
697 return NtGdiAddFontResource ( &Filename, fl );
698 }
699
700
701 /*
702 * @implemented
703 */
704 int
705 STDCALL
706 AddFontResourceExA ( LPCSTR lpszFilename, DWORD fl, PVOID pvReserved )
707 {
708 NTSTATUS Status;
709 PWSTR FilenameW;
710 int rc = 0;
711
712 Status = HEAP_strdupA2W ( &FilenameW, lpszFilename );
713 if ( !NT_SUCCESS (Status) )
714 SetLastError (RtlNtStatusToDosError(Status));
715 else
716 {
717 rc = AddFontResourceExW ( FilenameW, fl, pvReserved );
718
719 HEAP_free ( FilenameW );
720 }
721 return rc;
722 }
723
724
725 /*
726 * @implemented
727 */
728 int
729 STDCALL
730 AddFontResourceA ( LPCSTR lpszFilename )
731 {
732 return AddFontResourceExA ( lpszFilename, 0, 0 );
733 }
734
735
736 /*
737 * @implemented
738 */
739 int
740 STDCALL
741 AddFontResourceW ( LPCWSTR lpszFilename )
742 {
743 return AddFontResourceExW ( lpszFilename, 0, 0 );
744 }
745
746
747 /*
748 * @implemented
749 */
750 BOOL
751 STDCALL
752 RemoveFontResourceW(
753 LPCWSTR lpFileName
754 )
755 {
756 return NtGdiRemoveFontResource ( lpFileName );
757 }
758
759
760 /*
761 * @implemented
762 */
763 BOOL
764 STDCALL
765 RemoveFontResourceA(
766 LPCSTR lpFileName
767 )
768 {
769 NTSTATUS Status;
770 LPWSTR lpFileNameW;
771 BOOL rc = 0;
772
773 Status = HEAP_strdupA2W ( &lpFileNameW, lpFileName );
774 if (!NT_SUCCESS (Status))
775 SetLastError (RtlNtStatusToDosError(Status));
776 else
777 {
778 rc = NtGdiRemoveFontResource ( lpFileNameW );
779
780 HEAP_free ( lpFileNameW );
781 }
782
783 return rc;
784 }
785
786 /***********************************************************************
787 * GdiGetCharDimensions
788 *
789 * Gets the average width of the characters in the English alphabet.
790 *
791 * PARAMS
792 * hdc [I] Handle to the device context to measure on.
793 * lptm [O] Pointer to memory to store the text metrics into.
794 * height [O] On exit, the maximum height of characters in the English alphabet.
795 *
796 * RETURNS
797 * The average width of characters in the English alphabet.
798 *
799 * NOTES
800 * This function is used by the dialog manager to get the size of a dialog
801 * unit. It should also be used by other pieces of code that need to know
802 * the size of a dialog unit in logical units without having access to the
803 * window handle of the dialog.
804 * Windows caches the font metrics from this function, but we don't and
805 * there doesn't appear to be an immediate advantage to do so.
806 *
807 * SEE ALSO
808 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
809 */
810 /*
811 * @implemented
812 */
813 DWORD
814 STDCALL
815 GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, DWORD *height)
816 {
817 SIZE sz;
818 static const WCHAR alphabet[] = {
819 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
820 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
821 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
822
823 if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
824
825 if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
826
827 if (height) *height = sz.cy;
828 return (sz.cx / 26 + 1) / 2;
829 }
830