3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS system libraries
5 * FILE: lib/gdi32/object/font.c
16 #define INITIAL_FAMILY_COUNT 64
18 /***********************************************************************
19 * TEXTMETRIC conversion functions.
21 static void FONT_TextMetricWToA(const TEXTMETRICW
*ptmW
, LPTEXTMETRICA ptmA
)
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
;
45 /***********************************************************************
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.
54 static LPWSTR
FONT_mbtowc(LPCSTR str
, INT count
, INT
*plenW
)
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
;
71 MetricsCharConvert(WCHAR w
, UCHAR
*b
)
73 UNICODE_STRING WString
;
87 RtlInitUnicodeString(&WString
, WBuf
);
90 RtlInitAnsiString(&AString
, ABuf
);
92 Status
= RtlUnicodeStringToAnsiString(&AString
, &WString
, FALSE
);
93 if (! NT_SUCCESS(Status
))
95 SetLastError(RtlNtStatusToDosError(Status
));
105 TextMetricW2A(TEXTMETRICA
*tma
, TEXTMETRICW
*tmw
)
107 UNICODE_STRING WString
;
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
;
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. */
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
++)
141 ABuf
[Letter
- 1] = (CHAR
) Letter
;
142 WBuf
[Letter
- 1] = L
' ';
146 RtlInitAnsiString(&AString
, ABuf
);
147 RtlInitUnicodeString(&WString
, WBuf
);
149 /* Find the corresponding Unicode characters */
150 Status
= RtlAnsiStringToUnicodeString(&WString
, &AString
, FALSE
);
151 if (! NT_SUCCESS(Status
))
153 SetLastError(RtlNtStatusToDosError(Status
));
157 /* Scan for the first ANSI character which maps to an Unicode character
159 tma
->tmFirstChar
= '\0';
160 if (L
'\0' != tmw
->tmFirstChar
)
162 for (Letter
= 1; Letter
< 256; Letter
++)
164 if (tmw
->tmFirstChar
<= WBuf
[Letter
- 1] &&
165 WBuf
[Letter
- 1] <= tmw
->tmLastChar
)
167 tma
->tmFirstChar
= (CHAR
) Letter
;
173 /* Scan for the last ANSI character which maps to an Unicode character
175 tma
->tmLastChar
= '\0';
176 if (L
'\0' != tmw
->tmLastChar
)
178 for (Letter
= 255; 0 < Letter
; Letter
--)
180 if (tmw
->tmFirstChar
<= WBuf
[Letter
- 1] &&
181 WBuf
[Letter
- 1] <= tmw
->tmLastChar
)
183 tma
->tmLastChar
= (CHAR
) Letter
;
189 if (! MetricsCharConvert(tmw
->tmDefaultChar
, &tma
->tmDefaultChar
) ||
190 ! MetricsCharConvert(tmw
->tmBreakChar
, &tma
->tmBreakChar
))
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
;
205 NewTextMetricW2A(NEWTEXTMETRICA
*tma
, NEWTEXTMETRICW
*tmw
)
207 if (! TextMetricW2A((TEXTMETRICA
*) tma
, (TEXTMETRICW
*) tmw
))
212 tma
->ntmFlags
= tmw
->ntmFlags
;
213 tma
->ntmSizeEM
= tmw
->ntmSizeEM
;
214 tma
->ntmCellHeight
= tmw
->ntmCellHeight
;
215 tma
->ntmAvgWidth
= tmw
->ntmAvgWidth
;
221 NewTextMetricExW2A(NEWTEXTMETRICEXA
*tma
, NEWTEXTMETRICEXW
*tmw
)
223 if (! NewTextMetricW2A(&tma
->ntmTm
, &tmw
->ntmTm
))
228 tma
->ntmFontSig
= tmw
->ntmFontSig
;
234 IntEnumFontFamilies(HDC Dc
, LPLOGFONTW LogFont
, PVOID EnumProc
, LPARAM lParam
,
239 PFONTFAMILYINFO Info
;
242 ENUMLOGFONTEXA EnumLogFontExA
;
243 NEWTEXTMETRICEXA NewTextMetricExA
;
245 Info
= RtlAllocateHeap(GetProcessHeap(), 0,
246 INITIAL_FAMILY_COUNT
* sizeof(FONTFAMILYINFO
));
251 FontFamilyCount
= NtGdiGetFontFamilyInfo(Dc
, LogFont
, Info
, INITIAL_FAMILY_COUNT
);
252 if (FontFamilyCount
< 0)
254 RtlFreeHeap(GetProcessHeap(), 0, Info
);
257 if (INITIAL_FAMILY_COUNT
< FontFamilyCount
)
259 FontFamilySize
= FontFamilyCount
;
260 RtlFreeHeap(GetProcessHeap(), 0, Info
);
261 Info
= RtlAllocateHeap(GetProcessHeap(), 0,
262 FontFamilyCount
* sizeof(FONTFAMILYINFO
));
267 FontFamilyCount
= NtGdiGetFontFamilyInfo(Dc
, LogFont
, Info
, FontFamilySize
);
268 if (FontFamilyCount
< 0 || FontFamilySize
< FontFamilyCount
)
270 RtlFreeHeap(GetProcessHeap(), 0, Info
);
275 for (i
= 0; i
< FontFamilyCount
; i
++)
279 Ret
= ((FONTENUMPROCW
) EnumProc
)(
280 &Info
[i
].EnumLogFontEx
,
281 &Info
[i
].NewTextMetricEx
,
282 Info
[i
].FontType
, lParam
);
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
)(
298 Info
[i
].FontType
, lParam
);
302 RtlFreeHeap(GetProcessHeap(), 0, Info
);
311 EnumFontFamiliesExW(HDC hdc
, LPLOGFONTW lpLogfont
, FONTENUMPROCW lpEnumFontFamExProc
,
312 LPARAM lParam
, DWORD dwFlags
)
314 return IntEnumFontFamilies(hdc
, lpLogfont
, lpEnumFontFamExProc
, lParam
, TRUE
);
322 EnumFontFamiliesW(HDC hdc
, LPCWSTR lpszFamily
, FONTENUMPROCW lpEnumFontFamProc
,
327 ZeroMemory(&LogFont
, sizeof(LOGFONTW
));
328 LogFont
.lfCharSet
= DEFAULT_CHARSET
;
329 if (NULL
!= lpszFamily
)
331 lstrcpynW(LogFont
.lfFaceName
, lpszFamily
, LF_FACESIZE
);
334 return IntEnumFontFamilies(hdc
, &LogFont
, lpEnumFontFamProc
, lParam
, TRUE
);
342 EnumFontFamiliesExA (HDC hdc
, LPLOGFONTA lpLogfont
, FONTENUMPROCA lpEnumFontFamExProc
,
343 LPARAM lParam
, DWORD dwFlags
)
347 LogFontA2W(&LogFontW
, lpLogfont
);
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
);
358 EnumFontFamiliesA(HDC hdc
, LPCSTR lpszFamily
, FONTENUMPROCA lpEnumFontFamProc
,
363 ZeroMemory(&LogFont
, sizeof(LOGFONTW
));
364 LogFont
.lfCharSet
= DEFAULT_CHARSET
;
365 if (NULL
!= lpszFamily
)
367 MultiByteToWideChar(CP_THREAD_ACP
, 0, lpszFamily
, -1, LogFont
.lfFaceName
, LF_FACESIZE
);
370 return IntEnumFontFamilies(hdc
, &LogFont
, lpEnumFontFamProc
, lParam
, FALSE
);
386 DPRINT1("GCWA iFirstChar %x\n",iFirstChar
);
388 return GetCharWidth32A ( hdc
, iFirstChar
, iLastChar
, lpBuffer
);
404 INT i
, wlen
, count
= (INT
)(iLastChar
- iFirstChar
+ 1);
408 DPRINT1("GCW32A iFirstChar %x\n",iFirstChar
);
410 if(count
<= 0) return FALSE
;
412 str
= HeapAlloc(GetProcessHeap(), 0, count
);
413 for(i
= 0; i
< count
; i
++)
414 str
[i
] = (BYTE
)(iFirstChar
+ i
);
416 wstr
= FONT_mbtowc(str
, count
, &wlen
);
418 for(i
= 0; i
< wlen
; i
++)
420 /* FIXME should be NtGdiGetCharWidthW */
421 if(!NtGdiGetCharWidth32 (hdc
, wstr
[i
], wstr
[i
], lpBuffer
))
429 HeapFree(GetProcessHeap(), 0, str
);
430 HeapFree(GetProcessHeap(), 0, wstr
);
448 DPRINT1("GCW32w uFirstChar %x\n",iFirstChar
);
450 /* FIXME should be NtGdiGetCharWidthW */
451 return NtGdiGetCharWidth32 ( hdc
, iFirstChar
, iLastChar
, lpBuffer
);
460 GetCharacterPlacementW(
465 GCP_RESULTSW
*lpResults
,
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");
479 if(nSet
> lpResults
->nGlyphs
)
480 nSet
= lpResults
->nGlyphs
;
482 /* return number of initialized fields */
483 lpResults
->nGlyphs
= nSet
;
485 /*if((dwFlags&GCP_REORDER)==0 || !BidiAvail)
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
);
492 if(lpResults
->lpGlyphs
)
493 lstrcpynW( lpResults
->lpGlyphs
, lpString
, nSet
);
495 if(lpResults
->lpOrder
)
497 for(i
= 0; i
< nSet
; i
++)
498 lpResults
->lpOrder
[i
] = i
;
502 BIDI_Reorder( lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
503 nSet, lpResults->lpOrder );
506 /* FIXME: Will use the placement chars */
510 for (i
= 0; i
< nSet
; i
++)
512 if (NtGdiGetCharWidth32(hdc
, lpString
[i
], lpString
[i
], &c
))
513 lpResults
->lpDx
[i
]= c
;
517 if (lpResults
->lpCaretPos
&& !(dwFlags
& GCP_REORDER
))
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
);
527 /*if(lpResults->lpGlyphs)
528 GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);*/
530 if (GetTextExtentPoint32W(hdc
, lpString
, uCount
, &size
))
531 ret
= MAKELONG(size
.cx
, size
.cy
);
549 /* FIXME what to do with iFirstChar and iLastChar ??? */
550 return NtGdiGetCharWidthFloat ( hdc
, iFirstChar
, iLastChar
, pxBuffer
);
566 DPRINT1("GCABCWA uFirstChar %x\n",uFirstChar
);
568 return NtGdiGetCharABCWidths(hdc
, uFirstChar
, uLastChar
, lpabc
);
577 GetCharABCWidthsFloatA(
584 DPRINT1("GCABCWFA iFirstChar %x\n",iFirstChar
);
586 /* FIXME what to do with iFirstChar and iLastChar ??? */
587 return NtGdiGetCharABCWidthsFloat ( hdc
, iFirstChar
, iLastChar
, lpABCF
);
610 DPRINT1("GetGlyphOutlineA uChar %x\n", uChar
);
611 if(!(uFormat
& GGO_GLYPH_INDEX
)) {
614 if(uChar
> 0xff) { /* but, 2 bytes character only */
616 mbchs
[0] = (uChar
& 0xff00) >> 8;
617 mbchs
[1] = (uChar
& 0xff);
620 mbchs
[0] = (uChar
& 0xff);
622 p
= FONT_mbtowc(mbchs
, len
, NULL
);
626 ret
= NtGdiGetGlyphOutline(hdc
, c
, uFormat
, lpgm
, cbBuffer
, lpvBuffer
, (CONST LPMAT2
)lpmat2
, TRUE
);
627 HeapFree(GetProcessHeap(), 0, p
);
647 DPRINT1("GetGlyphOutlineW uChar %x\n", uChar
);
648 return NtGdiGetGlyphOutline ( hdc
, uChar
, uFormat
, lpgm
, cbBuffer
, lpvBuffer
, (CONST LPMAT2
)lpmat2
, TRUE
);
657 GetOutlineTextMetricsA(
660 LPOUTLINETEXTMETRICA lpOTM
665 OUTLINETEXTMETRICW
*lpOTMW
= (OUTLINETEXTMETRICW
*)buf
;
666 OUTLINETEXTMETRICA
*output
= lpOTM
;
669 if((ret
= GetOutlineTextMetricsW(hdc
, 0, NULL
)) == 0)
671 if(ret
> sizeof(buf
))
672 lpOTMW
= HeapAlloc(GetProcessHeap(), 0, ret
);
673 GetOutlineTextMetricsW(hdc
, ret
, lpOTMW
);
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
);
698 DPRINT("needed = %d\n", needed
);
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
703 output
= HeapAlloc(GetProcessHeap(), 0, needed
);
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
;
735 ptr
= (char*)(output
+ 1);
736 left
= needed
- sizeof(*output
);
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
);
746 output
->otmpFamilyName
= 0;
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
);
756 output
->otmpFaceName
= 0;
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
);
766 output
->otmpStyleName
= 0;
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
);
775 output
->otmpFullName
= 0;
779 if(output
!= lpOTM
) {
780 memcpy(lpOTM
, output
, cbData
);
781 HeapFree(GetProcessHeap(), 0, output
);
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 */
788 if ((UINT_PTR
)lpOTM
->otmpFaceName
>= lpOTM
->otmSize
)
789 lpOTM
->otmpFaceName
= 0; /* doesn't fit */
791 if ((UINT_PTR
)lpOTM
->otmpStyleName
>= lpOTM
->otmSize
)
792 lpOTM
->otmpStyleName
= 0; /* doesn't fit */
794 if ((UINT_PTR
)lpOTM
->otmpFullName
>= lpOTM
->otmSize
)
795 lpOTM
->otmpFullName
= 0; /* doesn't fit */
799 if(lpOTMW
!= (OUTLINETEXTMETRICW
*)buf
)
800 HeapFree(GetProcessHeap(), 0, lpOTMW
);
811 GetOutlineTextMetricsW(
814 LPOUTLINETEXTMETRICW lpOTM
817 TMDIFF Tmd
; // Should not be zero.
819 return NtGdiGetOutlineTextMetricsInternalW(hdc
, cbData
, lpOTM
, &Tmd
);
828 CreateFontIndirectExA(const ENUMLOGFONTEXDVA
*elfexd
)
832 ENUMLOGFONTEXDVW Logfont
;
834 EnumLogFontExW2A( (LPENUMLOGFONTEXA
) elfexd
,
835 &Logfont
.elfEnumLogfontEx
);
837 RtlCopyMemory( &Logfont
.elfDesignVector
,
838 (PVOID
) &elfexd
->elfDesignVector
,
839 sizeof(DESIGNVECTOR
));
841 return NtGdiHfontCreate( &Logfont
, 0, 0, 0, NULL
);
852 CreateFontIndirectExW(const ENUMLOGFONTEXDVW
*elfexd
)
854 /* Msdn: Note, this function ignores the elfDesignVector member in
859 return NtGdiHfontCreate((PENUMLOGFONTEXDVW
) elfexd
, 0, 0, 0, NULL
);
878 LogFontA2W(&tlf
, lplf
);
879 return CreateFontIndirectW(&tlf
);
896 ENUMLOGFONTEXDVW Logfont
;
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
));
908 RtlZeroMemory( &Logfont
.elfDesignVector
, sizeof(DESIGNVECTOR
));
910 return CreateFontIndirectExW(&Logfont
);
931 DWORD fdwOutputPrecision
,
932 DWORD fdwClipPrecision
,
934 DWORD fdwPitchAndFamily
,
939 UNICODE_STRING StringU
;
942 RtlInitAnsiString(&StringA
, (LPSTR
)lpszFace
);
943 RtlAnsiStringToUnicodeString(&StringU
, &StringA
, TRUE
);
945 ret
= CreateFontW(nHeight
,
960 RtlFreeUnicodeString(&StringU
);
981 DWORD fdwOutputPrecision
,
982 DWORD fdwClipPrecision
,
984 DWORD fdwPitchAndFamily
,
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
;
1004 if (NULL
!= lpszFace
)
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';
1013 logfont
.lfFaceName
[0] = L
'\0';
1016 return CreateFontIndirectW(&logfont
);
1025 CreateScalableFontResourceW(
1027 LPCWSTR lpszFontRes
,
1028 LPCWSTR lpszFontFile
,
1029 LPCWSTR lpszCurrentPath
1032 return NtGdiCreateScalableFontResource ( fdwHidden
,
1044 CreateScalableFontResourceA(
1047 LPCSTR lpszFontFile
,
1048 LPCSTR lpszCurrentPath
1052 LPWSTR lpszFontResW
, lpszFontFileW
, lpszCurrentPathW
;
1055 Status
= HEAP_strdupA2W ( &lpszFontResW
, lpszFontRes
);
1056 if (!NT_SUCCESS (Status
))
1057 SetLastError (RtlNtStatusToDosError(Status
));
1060 Status
= HEAP_strdupA2W ( &lpszFontFileW
, lpszFontFile
);
1061 if (!NT_SUCCESS (Status
))
1062 SetLastError (RtlNtStatusToDosError(Status
));
1065 Status
= HEAP_strdupA2W ( &lpszCurrentPathW
, lpszCurrentPath
);
1066 if (!NT_SUCCESS (Status
))
1067 SetLastError (RtlNtStatusToDosError(Status
));
1070 rc
= NtGdiCreateScalableFontResource ( fdwHidden
,
1075 HEAP_free ( lpszCurrentPathW
);
1078 HEAP_free ( lpszFontFileW
);
1081 HEAP_free ( lpszFontResW
);
1092 AddFontResourceExW ( LPCWSTR lpszFilename
, DWORD fl
, PVOID pvReserved
)
1096 if (!(fl
& (FR_PRIVATE
| FR_NOT_ENUM
)))
1098 retVal
= GdiAddFontResourceW(lpszFilename
, fl
,0);
1102 SetLastError( ERROR_INVALID_PARAMETER
);
1113 AddFontResourceExA ( LPCSTR lpszFilename
, DWORD fl
, PVOID pvReserved
)
1119 if (!(fl
& (FR_PRIVATE
| FR_NOT_ENUM
)))
1121 SetLastError( ERROR_INVALID_PARAMETER
);
1125 Status
= HEAP_strdupA2W ( &FilenameW
, lpszFilename
);
1126 if ( !NT_SUCCESS (Status
) )
1128 SetLastError (RtlNtStatusToDosError(Status
));
1132 rc
= GdiAddFontResourceW ( FilenameW
, fl
, 0 );
1133 HEAP_free ( FilenameW
);
1145 AddFontResourceA ( LPCSTR lpszFilename
)
1151 Status
= HEAP_strdupA2W ( &FilenameW
, lpszFilename
);
1152 if ( !NT_SUCCESS (Status
) )
1154 SetLastError (RtlNtStatusToDosError(Status
));
1158 rc
= GdiAddFontResourceW ( FilenameW
, 0, 0);
1160 HEAP_free ( FilenameW
);
1171 AddFontResourceW ( LPCWSTR lpszFilename
)
1173 return GdiAddFontResourceW ( lpszFilename
, 0, 0 );
1182 RemoveFontResourceW(
1186 return NtGdiRemoveFontResource ( lpFileName
);
1195 RemoveFontResourceA(
1203 Status
= HEAP_strdupA2W ( &lpFileNameW
, lpFileName
);
1204 if (!NT_SUCCESS (Status
))
1205 SetLastError (RtlNtStatusToDosError(Status
));
1208 rc
= NtGdiRemoveFontResource ( lpFileNameW
);
1210 HEAP_free ( lpFileNameW
);
1216 /***********************************************************************
1217 * GdiGetCharDimensions
1219 * Gets the average width of the characters in the English alphabet.
1222 * hdc [I] Handle to the device context to measure on.
1223 * lptm [O] Pointer to memory to store the text metrics into.
1224 * height [O] On exit, the maximum height of characters in the English alphabet.
1227 * The average width of characters in the English alphabet.
1230 * This function is used by the dialog manager to get the size of a dialog
1231 * unit. It should also be used by other pieces of code that need to know
1232 * the size of a dialog unit in logical units without having access to the
1233 * window handle of the dialog.
1234 * Windows caches the font metrics from this function, but we don't and
1235 * there doesn't appear to be an immediate advantage to do so.
1238 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
1240 * Despite most of MSDN insisting that the horizontal base unit is
1241 * tmAveCharWidth it isn't. Knowledge base article Q145994
1242 * "HOWTO: Calculate Dialog Units When Not Using the System Font",
1243 * says that we should take the average of the 52 English upper and lower
1251 GdiGetCharDimensions(HDC hdc
, LPTEXTMETRICW lptm
, LONG
*height
)
1254 static const WCHAR alphabet
[] = {
1255 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
1256 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
1257 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
1259 if(lptm
&& !GetTextMetricsW(hdc
, lptm
)) return 0;
1261 if(!GetTextExtentPointW(hdc
, alphabet
, 52, &sz
)) return 0;
1263 if (height
) *height
= sz
.cy
;
1264 return (sz
.cx
/ 26 + 1) / 2;
1276 FONTENUMPROCW FontFunc
,
1281 return NtGdiEnumFonts ( hDC
, lpFaceName
, FontFunc
, lParam
);
1283 return EnumFontFamiliesW( hDC
, lpFaceName
, FontFunc
, lParam
);
1295 FONTENUMPROCA FontFunc
,
1304 Status
= HEAP_strdupA2W ( &lpFaceNameW
, lpFaceName
);
1305 if (!NT_SUCCESS (Status
))
1306 SetLastError (RtlNtStatusToDosError(Status
));
1309 rc
= NtGdiEnumFonts ( hDC
, lpFaceNameW
, FontFunc
, lParam
);
1311 HEAP_free ( lpFaceNameW
);
1315 return EnumFontFamiliesA( hDC
, lpFaceName
, FontFunc
, lParam
);