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
19 MetricsCharConvert(WCHAR w
, UCHAR
*b
)
21 UNICODE_STRING WString
;
35 RtlInitUnicodeString(&WString
, WBuf
);
38 RtlInitAnsiString(&AString
, ABuf
);
40 Status
= RtlUnicodeStringToAnsiString(&AString
, &WString
, FALSE
);
41 if (! NT_SUCCESS(Status
))
43 SetLastError(RtlNtStatusToDosError(Status
));
53 TextMetricW2A(TEXTMETRICA
*tma
, TEXTMETRICW
*tmw
)
55 UNICODE_STRING WString
;
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
;
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. */
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
87 for (Letter
= 1; Letter
< 256; Letter
++)
89 ABuf
[Letter
- 1] = (CHAR
) Letter
;
90 WBuf
[Letter
- 1] = L
' ';
94 RtlInitAnsiString(&AString
, ABuf
);
95 RtlInitUnicodeString(&WString
, WBuf
);
97 /* Find the corresponding Unicode characters */
98 Status
= RtlAnsiStringToUnicodeString(&WString
, &AString
, FALSE
);
99 if (! NT_SUCCESS(Status
))
101 SetLastError(RtlNtStatusToDosError(Status
));
105 /* Scan for the first ANSI character which maps to an Unicode character
107 tma
->tmFirstChar
= '\0';
108 if (L
'\0' != tmw
->tmFirstChar
)
110 for (Letter
= 1; Letter
< 256; Letter
++)
112 if (tmw
->tmFirstChar
<= WBuf
[Letter
- 1] &&
113 WBuf
[Letter
- 1] <= tmw
->tmLastChar
)
115 tma
->tmFirstChar
= (CHAR
) Letter
;
121 /* Scan for the last ANSI character which maps to an Unicode character
123 tma
->tmLastChar
= '\0';
124 if (L
'\0' != tmw
->tmLastChar
)
126 for (Letter
= 255; 0 < Letter
; Letter
--)
128 if (tmw
->tmFirstChar
<= WBuf
[Letter
- 1] &&
129 WBuf
[Letter
- 1] <= tmw
->tmLastChar
)
131 tma
->tmLastChar
= (CHAR
) Letter
;
137 if (! MetricsCharConvert(tmw
->tmDefaultChar
, &tma
->tmDefaultChar
) ||
138 ! MetricsCharConvert(tmw
->tmBreakChar
, &tma
->tmBreakChar
))
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
;
153 NewTextMetricW2A(NEWTEXTMETRICA
*tma
, NEWTEXTMETRICW
*tmw
)
155 if (! TextMetricW2A((TEXTMETRICA
*) tma
, (TEXTMETRICW
*) tmw
))
160 tma
->ntmFlags
= tmw
->ntmFlags
;
161 tma
->ntmSizeEM
= tmw
->ntmSizeEM
;
162 tma
->ntmCellHeight
= tmw
->ntmCellHeight
;
163 tma
->ntmAvgWidth
= tmw
->ntmAvgWidth
;
169 NewTextMetricExW2A(NEWTEXTMETRICEXA
*tma
, NEWTEXTMETRICEXW
*tmw
)
171 if (! NewTextMetricW2A(&tma
->ntmTm
, &tmw
->ntmTm
))
176 tma
->ntmFontSig
= tmw
->ntmFontSig
;
182 IntEnumFontFamilies(HDC Dc
, LPLOGFONTW LogFont
, PVOID EnumProc
, LPARAM lParam
,
186 unsigned FontFamilySize
;
187 PFONTFAMILYINFO Info
;
190 ENUMLOGFONTEXA EnumLogFontExA
;
191 NEWTEXTMETRICEXA NewTextMetricExA
;
193 Info
= RtlAllocateHeap(GetProcessHeap(), 0,
194 INITIAL_FAMILY_COUNT
* sizeof(FONTFAMILYINFO
));
199 FontFamilyCount
= NtGdiGetFontFamilyInfo(Dc
, LogFont
, Info
, INITIAL_FAMILY_COUNT
);
200 if (FontFamilyCount
< 0)
202 RtlFreeHeap(GetProcessHeap(), 0, Info
);
205 if (INITIAL_FAMILY_COUNT
< FontFamilyCount
)
207 FontFamilySize
= FontFamilyCount
;
208 RtlFreeHeap(GetProcessHeap(), 0, Info
);
209 Info
= RtlAllocateHeap(GetProcessHeap(), 0,
210 FontFamilyCount
* sizeof(FONTFAMILYINFO
));
215 FontFamilyCount
= NtGdiGetFontFamilyInfo(Dc
, LogFont
, Info
, FontFamilySize
);
216 if (FontFamilyCount
< 0 || FontFamilySize
< FontFamilyCount
)
218 RtlFreeHeap(GetProcessHeap(), 0, Info
);
223 for (i
= 0; i
< FontFamilyCount
; i
++)
227 Ret
= ((FONTENUMPROCW
) EnumProc
)(
228 (LPLOGFONTW
)&Info
[i
].EnumLogFontEx
,
229 (LPTEXTMETRICW
)&Info
[i
].NewTextMetricEx
,
230 Info
[i
].FontType
, lParam
);
234 RosRtlLogFontW2A(&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
);
250 RtlFreeHeap(GetProcessHeap(), 0, Info
);
259 EnumFontFamiliesExW(HDC hdc
, LPLOGFONTW lpLogfont
, FONTENUMPROCW lpEnumFontFamExProc
,
260 LPARAM lParam
, DWORD dwFlags
)
262 return IntEnumFontFamilies(hdc
, lpLogfont
, lpEnumFontFamExProc
, lParam
, TRUE
);
270 EnumFontFamiliesW(HDC hdc
, LPCWSTR lpszFamily
, FONTENUMPROCW lpEnumFontFamProc
,
275 ZeroMemory(&LogFont
, sizeof(LOGFONTW
));
276 LogFont
.lfCharSet
= DEFAULT_CHARSET
;
277 if (NULL
!= lpszFamily
)
279 lstrcpynW(LogFont
.lfFaceName
, lpszFamily
, LF_FACESIZE
);
282 return IntEnumFontFamilies(hdc
, &LogFont
, lpEnumFontFamProc
, lParam
, TRUE
);
290 EnumFontFamiliesExA (HDC hdc
, LPLOGFONTA lpLogfont
, FONTENUMPROCA lpEnumFontFamExProc
,
291 LPARAM lParam
, DWORD dwFlags
)
295 RosRtlLogFontA2W(&LogFontW
, lpLogfont
);
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
);
306 EnumFontFamiliesA(HDC hdc
, LPCSTR lpszFamily
, FONTENUMPROCA lpEnumFontFamProc
,
311 ZeroMemory(&LogFont
, sizeof(LOGFONTW
));
312 LogFont
.lfCharSet
= DEFAULT_CHARSET
;
313 if (NULL
!= lpszFamily
)
315 MultiByteToWideChar(CP_THREAD_ACP
, 0, lpszFamily
, -1, LogFont
.lfFaceName
, LF_FACESIZE
);
318 return IntEnumFontFamilies(hdc
, &LogFont
, lpEnumFontFamProc
, lParam
, FALSE
);
334 /* FIXME what to do with iFirstChar and iLastChar ??? */
335 return NtGdiGetCharWidth32 ( hdc
, iFirstChar
, iLastChar
, lpBuffer
);
351 /* FIXME what to do with iFirstChar and iLastChar ??? */
352 return NtGdiGetCharWidth32 ( hdc
, iFirstChar
, iLastChar
, lpBuffer
);
368 return NtGdiGetCharWidth32 ( hdc
, iFirstChar
, iLastChar
, lpBuffer
);
377 GetCharacterPlacementW(
382 GCP_RESULTSW
*lpResults
,
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");
396 if(nSet
> lpResults
->nGlyphs
)
397 nSet
= lpResults
->nGlyphs
;
399 /* return number of initialized fields */
400 lpResults
->nGlyphs
= nSet
;
402 /*if((dwFlags&GCP_REORDER)==0 || !BidiAvail)
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 strncpyW( lpResults
->lpOutString
, lpString
, nSet
);
409 if(lpResults
->lpGlyphs
)
410 strncpyW( lpResults
->lpGlyphs
, lpString
, nSet
);
412 if(lpResults
->lpOrder
)
414 for(i
= 0; i
< nSet
; i
++)
415 lpResults
->lpOrder
[i
] = i
;
419 BIDI_Reorder( lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
420 nSet, lpResults->lpOrder );
423 /* FIXME: Will use the placement chars */
427 for (i
= 0; i
< nSet
; i
++)
429 if (NtGdiGetCharWidth32(hdc
, lpString
[i
], lpString
[i
], &c
))
430 lpResults
->lpDx
[i
]= c
;
434 if (lpResults
->lpCaretPos
&& !(dwFlags
& GCP_REORDER
))
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
);
444 /*if(lpResults->lpGlyphs)
445 GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);*/
447 if (GetTextExtentPoint32W(hdc
, lpString
, uCount
, &size
))
448 ret
= MAKELONG(size
.cx
, size
.cy
);
466 /* FIXME what to do with iFirstChar and iLastChar ??? */
467 return NtGdiGetCharWidthFloat ( hdc
, iFirstChar
, iLastChar
, pxBuffer
);
483 /* FIXME what to do with uFirstChar and uLastChar ??? */
484 return NtGdiGetCharABCWidths ( hdc
, uFirstChar
, uLastChar
, lpabc
);
493 GetCharABCWidthsFloatA(
500 /* FIXME what to do with iFirstChar and iLastChar ??? */
501 return NtGdiGetCharABCWidthsFloat ( hdc
, iFirstChar
, iLastChar
, lpABCF
);
520 return NtGdiGetGlyphOutline ( hdc
, uChar
, uFormat
, lpgm
, cbBuffer
, lpvBuffer
, (CONST LPMAT2
)lpmat2
);
535 RosRtlLogFontA2W(&tlf
, lplf
);
537 return NtGdiCreateFontIndirect(&tlf
);
550 return NtGdiCreateFontIndirect((CONST LPLOGFONTW
)lplf
);
569 DWORD fdwOutputPrecision
,
570 DWORD fdwClipPrecision
,
572 DWORD fdwPitchAndFamily
,
577 UNICODE_STRING StringU
;
580 RtlInitAnsiString(&StringA
, (LPSTR
)lpszFace
);
581 RtlAnsiStringToUnicodeString(&StringU
, &StringA
, TRUE
);
583 ret
= CreateFontW(nHeight
, nWidth
, nEscapement
, nOrientation
, fnWeight
, fdwItalic
, fdwUnderline
, fdwStrikeOut
,
584 fdwCharSet
, fdwOutputPrecision
, fdwClipPrecision
, fdwQuality
, fdwPitchAndFamily
, StringU
.Buffer
);
586 RtlFreeUnicodeString(&StringU
);
607 DWORD fdwOutputPrecision
,
608 DWORD fdwClipPrecision
,
610 DWORD fdwPitchAndFamily
,
614 return NtGdiCreateFont(nHeight
, nWidth
, nEscapement
, nOrientation
, nWeight
, fnItalic
, fdwUnderline
, fdwStrikeOut
,
615 fdwCharSet
, fdwOutputPrecision
, fdwClipPrecision
, fdwQuality
, fdwPitchAndFamily
, lpszFace
);
624 CreateScalableFontResourceW(
627 LPCWSTR lpszFontFile
,
628 LPCWSTR lpszCurrentPath
631 return NtGdiCreateScalableFontResource ( fdwHidden
,
643 CreateScalableFontResourceA(
647 LPCSTR lpszCurrentPath
651 LPWSTR lpszFontResW
, lpszFontFileW
, lpszCurrentPathW
;
654 Status
= HEAP_strdupA2W ( &lpszFontResW
, lpszFontRes
);
655 if (!NT_SUCCESS (Status
))
656 SetLastError (RtlNtStatusToDosError(Status
));
659 Status
= HEAP_strdupA2W ( &lpszFontFileW
, lpszFontFile
);
660 if (!NT_SUCCESS (Status
))
661 SetLastError (RtlNtStatusToDosError(Status
));
664 Status
= HEAP_strdupA2W ( &lpszCurrentPathW
, lpszCurrentPath
);
665 if (!NT_SUCCESS (Status
))
666 SetLastError (RtlNtStatusToDosError(Status
));
669 rc
= NtGdiCreateScalableFontResource ( fdwHidden
,
674 HEAP_free ( lpszCurrentPathW
);
677 HEAP_free ( lpszFontFileW
);
680 HEAP_free ( lpszFontResW
);
691 AddFontResourceExW ( LPCWSTR lpszFilename
, DWORD fl
, PVOID pvReserved
)
693 UNICODE_STRING Filename
;
695 /* FIXME handle fl parameter */
696 RtlInitUnicodeString(&Filename
, lpszFilename
);
697 return NtGdiAddFontResource ( &Filename
, fl
);
706 AddFontResourceExA ( LPCSTR lpszFilename
, DWORD fl
, PVOID pvReserved
)
712 Status
= HEAP_strdupA2W ( &FilenameW
, lpszFilename
);
713 if ( !NT_SUCCESS (Status
) )
714 SetLastError (RtlNtStatusToDosError(Status
));
717 rc
= AddFontResourceExW ( FilenameW
, fl
, pvReserved
);
719 HEAP_free ( &FilenameW
);
730 AddFontResourceA ( LPCSTR lpszFilename
)
732 return AddFontResourceExA ( lpszFilename
, 0, 0 );
741 AddFontResourceW ( LPCWSTR lpszFilename
)
743 return AddFontResourceExW ( lpszFilename
, 0, 0 );
756 return NtGdiRemoveFontResource ( lpFileName
);
773 Status
= HEAP_strdupA2W ( &lpFileNameW
, lpFileName
);
774 if (!NT_SUCCESS (Status
))
775 SetLastError (RtlNtStatusToDosError(Status
));
778 rc
= NtGdiRemoveFontResource ( lpFileNameW
);
780 HEAP_free ( lpFileNameW
);