1 /* $Id: font.c,v 1.10 2004/12/25 11:18:50 navaraf Exp $
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
;
186 TranslateCharsetInfo(DWORD
*pSrc
, LPCHARSETINFO lpCs
, DWORD dwFlags
)
188 return NtGdiTranslateCharsetInfo(pSrc
, lpCs
, dwFlags
);
192 IntEnumFontFamilies(HDC Dc
, LPLOGFONTW LogFont
, PVOID EnumProc
, LPARAM lParam
,
196 unsigned FontFamilySize
;
197 PFONTFAMILYINFO Info
;
200 ENUMLOGFONTEXA EnumLogFontExA
;
201 NEWTEXTMETRICEXA NewTextMetricExA
;
203 Info
= RtlAllocateHeap(GetProcessHeap(), 0,
204 INITIAL_FAMILY_COUNT
* sizeof(FONTFAMILYINFO
));
209 FontFamilyCount
= NtGdiGetFontFamilyInfo(Dc
, LogFont
, Info
, INITIAL_FAMILY_COUNT
);
210 if (FontFamilyCount
< 0)
212 RtlFreeHeap(GetProcessHeap(), 0, Info
);
215 if (INITIAL_FAMILY_COUNT
< FontFamilyCount
)
217 FontFamilySize
= FontFamilyCount
;
218 RtlFreeHeap(GetProcessHeap(), 0, Info
);
219 Info
= RtlAllocateHeap(GetProcessHeap(), 0,
220 FontFamilyCount
* sizeof(FONTFAMILYINFO
));
225 FontFamilyCount
= NtGdiGetFontFamilyInfo(Dc
, LogFont
, Info
, FontFamilySize
);
226 if (FontFamilyCount
< 0 || FontFamilySize
< FontFamilyCount
)
228 RtlFreeHeap(GetProcessHeap(), 0, Info
);
233 for (i
= 0; i
< FontFamilyCount
; i
++)
237 Ret
= ((FONTENUMPROCW
) EnumProc
)(
238 (LPLOGFONTW
)&Info
[i
].EnumLogFontEx
,
239 (LPTEXTMETRICW
)&Info
[i
].NewTextMetricEx
,
240 Info
[i
].FontType
, lParam
);
244 RosRtlLogFontW2A(&EnumLogFontExA
.elfLogFont
, &Info
[i
].EnumLogFontEx
.elfLogFont
);
245 WideCharToMultiByte(CP_THREAD_ACP
, 0, Info
[i
].EnumLogFontEx
.elfFullName
, -1,
246 (LPSTR
)EnumLogFontExA
.elfFullName
, LF_FULLFACESIZE
, NULL
, NULL
);
247 WideCharToMultiByte(CP_THREAD_ACP
, 0, Info
[i
].EnumLogFontEx
.elfStyle
, -1,
248 (LPSTR
)EnumLogFontExA
.elfStyle
, LF_FACESIZE
, NULL
, NULL
);
249 WideCharToMultiByte(CP_THREAD_ACP
, 0, Info
[i
].EnumLogFontEx
.elfScript
, -1,
250 (LPSTR
)EnumLogFontExA
.elfScript
, LF_FACESIZE
, NULL
, NULL
);
251 NewTextMetricExW2A(&NewTextMetricExA
,
252 &Info
[i
].NewTextMetricEx
);
253 Ret
= ((FONTENUMPROCA
) EnumProc
)(
254 (LPLOGFONTA
)&EnumLogFontExA
,
255 (LPTEXTMETRICA
)&NewTextMetricExA
,
256 Info
[i
].FontType
, lParam
);
260 RtlFreeHeap(GetProcessHeap(), 0, Info
);
269 EnumFontFamiliesExW(HDC hdc
, LPLOGFONTW lpLogfont
, FONTENUMPROCW lpEnumFontFamExProc
,
270 LPARAM lParam
, DWORD dwFlags
)
272 return IntEnumFontFamilies(hdc
, lpLogfont
, lpEnumFontFamExProc
, lParam
, TRUE
);
280 EnumFontFamiliesW(HDC hdc
, LPCWSTR lpszFamily
, FONTENUMPROCW lpEnumFontFamProc
,
285 ZeroMemory(&LogFont
, sizeof(LOGFONTW
));
286 LogFont
.lfCharSet
= DEFAULT_CHARSET
;
287 if (NULL
!= lpszFamily
)
289 lstrcpynW(LogFont
.lfFaceName
, lpszFamily
, LF_FACESIZE
);
292 return IntEnumFontFamilies(hdc
, &LogFont
, lpEnumFontFamProc
, lParam
, TRUE
);
300 EnumFontFamiliesExA (HDC hdc
, LPLOGFONTA lpLogfont
, FONTENUMPROCA lpEnumFontFamExProc
,
301 LPARAM lParam
, DWORD dwFlags
)
305 RosRtlLogFontA2W(&LogFontW
, lpLogfont
);
307 /* no need to convert LogFontW back to lpLogFont b/c it's an [in] parameter only */
308 return IntEnumFontFamilies(hdc
, &LogFontW
, lpEnumFontFamExProc
, lParam
, FALSE
);
316 EnumFontFamiliesA(HDC hdc
, LPCSTR lpszFamily
, FONTENUMPROCA lpEnumFontFamProc
,
321 ZeroMemory(&LogFont
, sizeof(LOGFONTW
));
322 LogFont
.lfCharSet
= DEFAULT_CHARSET
;
323 if (NULL
!= lpszFamily
)
325 MultiByteToWideChar(CP_THREAD_ACP
, 0, lpszFamily
, -1, LogFont
.lfFaceName
, LF_FACESIZE
);
328 return IntEnumFontFamilies(hdc
, &LogFont
, lpEnumFontFamProc
, lParam
, FALSE
);
344 /* FIXME what to do with iFirstChar and iLastChar ??? */
345 return NtGdiGetCharWidth32 ( hdc
, iFirstChar
, iLastChar
, lpBuffer
);
361 /* FIXME what to do with iFirstChar and iLastChar ??? */
362 return NtGdiGetCharWidth32 ( hdc
, iFirstChar
, iLastChar
, lpBuffer
);
378 return NtGdiGetCharWidth32 ( hdc
, iFirstChar
, iLastChar
, lpBuffer
);
394 return NtGdiGetCharWidth32 ( hdc
, iFirstChar
, iLastChar
, lpBuffer
);
411 return NtGdiGetFontData(a0
, a1
, a2
, a3
, a4
);
420 GetCharacterPlacementW(
425 GCP_RESULTSW
*lpResults
,
433 if(dwFlags
&(~GCP_REORDER
)) DPRINT("flags 0x%08lx ignored\n", dwFlags
);
434 if(lpResults
->lpClass
) DPRINT("classes not implemented\n");
435 if (lpResults
->lpCaretPos
&& (dwFlags
& GCP_REORDER
))
436 DPRINT("Caret positions for complex scripts not implemented\n");
439 if(nSet
> lpResults
->nGlyphs
)
440 nSet
= lpResults
->nGlyphs
;
442 /* return number of initialized fields */
443 lpResults
->nGlyphs
= nSet
;
445 /*if((dwFlags&GCP_REORDER)==0 || !BidiAvail)
447 /* Treat the case where no special handling was requested in a fastpath way */
448 /* copy will do if the GCP_REORDER flag is not set */
449 if(lpResults
->lpOutString
)
450 strncpyW( lpResults
->lpOutString
, lpString
, nSet
);
452 if(lpResults
->lpGlyphs
)
453 strncpyW( lpResults
->lpGlyphs
, lpString
, nSet
);
455 if(lpResults
->lpOrder
)
457 for(i
= 0; i
< nSet
; i
++)
458 lpResults
->lpOrder
[i
] = i
;
462 BIDI_Reorder( lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
463 nSet, lpResults->lpOrder );
466 /* FIXME: Will use the placement chars */
470 for (i
= 0; i
< nSet
; i
++)
472 if (GetCharWidth32W(hdc
, lpString
[i
], lpString
[i
], &c
))
473 lpResults
->lpDx
[i
]= c
;
477 if (lpResults
->lpCaretPos
&& !(dwFlags
& GCP_REORDER
))
481 lpResults
->lpCaretPos
[0] = 0;
482 for (i
= 1; i
< nSet
; i
++)
483 if (GetTextExtentPoint32W(hdc
, &(lpString
[i
- 1]), 1, &size
))
484 lpResults
->lpCaretPos
[i
] = (pos
+= size
.cx
);
487 /*if(lpResults->lpGlyphs)
488 GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);*/
490 if (GetTextExtentPoint32W(hdc
, lpString
, uCount
, &size
))
491 ret
= MAKELONG(size
.cx
, size
.cy
);