- Compile Win32k, GDI, USER32 and CSRSS using W32API.
[reactos.git] / reactos / lib / gdi32 / objects / font.c
1 /* $Id: font.c,v 1.3 2004/04/09 20:03:13 navaraf Exp $
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 #ifdef UNICODE
12 #undef UNICODE
13 #endif
14
15 #include <windows.h>
16 #include <rosrtl/logfont.h>
17 #include <ddk/ntddk.h>
18 #define NTOS_MODE_USER
19 #include <ntos.h>
20 #include <win32k/font.h>
21 #include <win32k/text.h>
22 #include <internal/font.h>
23
24 #define NDEBUG
25 #include <debug.h>
26
27 #define INITIAL_FAMILY_COUNT 64
28
29 static BOOL FASTCALL
30 MetricsCharConvert(WCHAR w, CHAR *b)
31 {
32 UNICODE_STRING WString;
33 WCHAR WBuf[2];
34 ANSI_STRING AString;
35 CHAR ABuf[2];
36 NTSTATUS Status;
37
38 if (L'\0' == w)
39 {
40 *b = '\0';
41 }
42 else
43 {
44 WBuf[0] = w;
45 WBuf[1] = L'\0';
46 RtlInitUnicodeString(&WString, WBuf);
47 ABuf[0] = '*';
48 ABuf[1] = L'\0';
49 RtlInitAnsiString(&AString, ABuf);
50
51 Status = RtlUnicodeStringToAnsiString(&AString, &WString, FALSE);
52 if (! NT_SUCCESS(Status))
53 {
54 SetLastError(RtlNtStatusToDosError(Status));
55 return FALSE;
56 }
57 *b = ABuf[0];
58 }
59
60 return TRUE;
61 }
62
63 BOOL FASTCALL
64 TextMetricW2A(TEXTMETRICA *tma, TEXTMETRICW *tmw)
65 {
66 UNICODE_STRING WString;
67 WCHAR WBuf[256];
68 ANSI_STRING AString;
69 CHAR ABuf[256];
70 UINT Letter;
71 NTSTATUS Status;
72
73 tma->tmHeight = tmw->tmHeight;
74 tma->tmAscent = tmw->tmAscent;
75 tma->tmDescent = tmw->tmDescent;
76 tma->tmInternalLeading = tmw->tmInternalLeading;
77 tma->tmExternalLeading = tmw->tmExternalLeading;
78 tma->tmAveCharWidth = tmw->tmAveCharWidth;
79 tma->tmMaxCharWidth = tmw->tmMaxCharWidth;
80 tma->tmWeight = tmw->tmWeight;
81 tma->tmOverhang = tmw->tmOverhang;
82 tma->tmDigitizedAspectX = tmw->tmDigitizedAspectX;
83 tma->tmDigitizedAspectY = tmw->tmDigitizedAspectY;
84
85 /* The Unicode FirstChar/LastChar need not correspond to the ANSI
86 FirstChar/LastChar. For example, if the font contains glyphs for
87 letters A-Z and an accented version of the letter e, the Unicode
88 FirstChar would be A and the Unicode LastChar would be the accented
89 e. If you just translate those to ANSI, the range would become
90 letters A-E instead of A-Z.
91 We translate all possible ANSI chars to Unicode and find the first
92 and last translated character which fall into the Unicode FirstChar/
93 LastChar range and return the corresponding ANSI char. */
94
95 /* Setup an Ansi string containing all possible letters (note: skip '\0' at
96 the beginning since that would be interpreted as end-of-string, handle
97 '\0' special later */
98 for (Letter = 1; Letter < 256; Letter++)
99 {
100 ABuf[Letter - 1] = (CHAR) Letter;
101 WBuf[Letter - 1] = L' ';
102 }
103 ABuf[255] = '\0';
104 WBuf[255] = L'\0';
105 RtlInitAnsiString(&AString, ABuf);
106 RtlInitUnicodeString(&WString, WBuf);
107
108 /* Find the corresponding Unicode characters */
109 Status = RtlAnsiStringToUnicodeString(&WString, &AString, FALSE);
110 if (! NT_SUCCESS(Status))
111 {
112 SetLastError(RtlNtStatusToDosError(Status));
113 return FALSE;
114 }
115
116 /* Scan for the first ANSI character which maps to an Unicode character
117 in the range */
118 tma->tmFirstChar = '\0';
119 if (L'\0' != tmw->tmFirstChar)
120 {
121 for (Letter = 1; Letter < 256; Letter++)
122 {
123 if (tmw->tmFirstChar <= WBuf[Letter - 1] &&
124 WBuf[Letter - 1] <= tmw->tmLastChar)
125 {
126 tma->tmFirstChar = (CHAR) Letter;
127 break;
128 }
129 }
130 }
131
132 /* Scan for the last ANSI character which maps to an Unicode character
133 in the range */
134 tma->tmLastChar = '\0';
135 if (L'\0' != tmw->tmLastChar)
136 {
137 for (Letter = 255; 0 < Letter; Letter--)
138 {
139 if (tmw->tmFirstChar <= WBuf[Letter - 1] &&
140 WBuf[Letter - 1] <= tmw->tmLastChar)
141 {
142 tma->tmLastChar = (CHAR) Letter;
143 break;
144 }
145 }
146 }
147
148 if (! MetricsCharConvert(tmw->tmDefaultChar, &tma->tmDefaultChar) ||
149 ! MetricsCharConvert(tmw->tmBreakChar, &tma->tmBreakChar))
150 {
151 return FALSE;
152 }
153
154 tma->tmItalic = tmw->tmItalic;
155 tma->tmUnderlined = tmw->tmUnderlined;
156 tma->tmStruckOut = tmw->tmStruckOut;
157 tma->tmPitchAndFamily = tmw->tmPitchAndFamily;
158 tma->tmCharSet = tmw->tmCharSet;
159
160 return TRUE;
161 }
162
163 BOOL FASTCALL
164 NewTextMetricW2A(NEWTEXTMETRICA *tma, NEWTEXTMETRICW *tmw)
165 {
166 if (! TextMetricW2A((TEXTMETRICA *) tma, (TEXTMETRICW *) tmw))
167 {
168 return FALSE;
169 }
170
171 tma->ntmFlags = tmw->ntmFlags;
172 tma->ntmSizeEM = tmw->ntmSizeEM;
173 tma->ntmCellHeight = tmw->ntmCellHeight;
174 tma->ntmAvgWidth = tmw->ntmAvgWidth;
175
176 return TRUE;
177 }
178
179 BOOL FASTCALL
180 NewTextMetricExW2A(NEWTEXTMETRICEXA *tma, NEWTEXTMETRICEXW *tmw)
181 {
182 if (! NewTextMetricW2A(&tma->ntmTm, &tmw->ntmTm))
183 {
184 return FALSE;
185 }
186
187 tma->ntmFontSig = tmw->ntmFontSig;
188
189 return TRUE;
190 }
191
192 /*
193 * @implemented
194 */
195 BOOL
196 STDCALL
197 TranslateCharsetInfo(DWORD *Src, LPCHARSETINFO Cs, DWORD Flags)
198 {
199 return NtGdiTranslateCharsetInfo(Src, Cs, Flags);
200 }
201
202 static int FASTCALL
203 IntEnumFontFamilies(HDC Dc, LPLOGFONTW LogFont, PVOID EnumProc, LPARAM lParam,
204 BOOL Unicode)
205 {
206 int FontFamilyCount;
207 unsigned FontFamilySize;
208 PFONTFAMILYINFO Info;
209 int Ret;
210 unsigned i;
211 ENUMLOGFONTEXA EnumLogFontExA;
212 NEWTEXTMETRICEXA NewTextMetricExA;
213
214 Info = RtlAllocateHeap(GetProcessHeap(), 0,
215 INITIAL_FAMILY_COUNT * sizeof(FONTFAMILYINFO));
216 if (NULL == Info)
217 {
218 return 0;
219 }
220 FontFamilyCount = NtGdiGetFontFamilyInfo(Dc, LogFont, Info, INITIAL_FAMILY_COUNT);
221 if (FontFamilyCount < 0)
222 {
223 RtlFreeHeap(GetProcessHeap(), 0, Info);
224 return 0;
225 }
226 if (INITIAL_FAMILY_COUNT < FontFamilyCount)
227 {
228 FontFamilySize = FontFamilyCount;
229 RtlFreeHeap(GetProcessHeap(), 0, Info);
230 Info = RtlAllocateHeap(GetProcessHeap(), 0,
231 FontFamilyCount * sizeof(FONTFAMILYINFO));
232 if (NULL == Info)
233 {
234 return 0;
235 }
236 FontFamilyCount = NtGdiGetFontFamilyInfo(Dc, LogFont, Info, FontFamilySize);
237 if (FontFamilyCount < 0 || FontFamilySize < FontFamilyCount)
238 {
239 RtlFreeHeap(GetProcessHeap(), 0, Info);
240 return 0;
241 }
242 }
243
244 for (i = 0; i < FontFamilyCount; i++)
245 {
246 if (Unicode)
247 {
248 Ret = ((FONTENUMPROCW) EnumProc)(
249 (LPLOGFONTW)&Info[i].EnumLogFontEx,
250 (LPTEXTMETRICW)&Info[i].NewTextMetricEx,
251 Info[i].FontType, lParam);
252 }
253 else
254 {
255 RosRtlLogFontW2A(&EnumLogFontExA.elfLogFont, &Info[i].EnumLogFontEx.elfLogFont);
256 WideCharToMultiByte(CP_THREAD_ACP, 0, Info[i].EnumLogFontEx.elfFullName, -1,
257 EnumLogFontExA.elfFullName, LF_FULLFACESIZE, NULL, NULL);
258 WideCharToMultiByte(CP_THREAD_ACP, 0, Info[i].EnumLogFontEx.elfStyle, -1,
259 EnumLogFontExA.elfStyle, LF_FACESIZE, NULL, NULL);
260 WideCharToMultiByte(CP_THREAD_ACP, 0, Info[i].EnumLogFontEx.elfScript, -1,
261 EnumLogFontExA.elfScript, LF_FACESIZE, NULL, NULL);
262 NewTextMetricExW2A(&NewTextMetricExA,
263 &Info[i].NewTextMetricEx);
264 Ret = ((FONTENUMPROCA) EnumProc)(
265 (LPLOGFONTA)&EnumLogFontExA,
266 (LPTEXTMETRICA)&NewTextMetricExA,
267 Info[i].FontType, lParam);
268 }
269 }
270
271 RtlFreeHeap(GetProcessHeap(), 0, Info);
272
273 return Ret;
274 }
275
276 /*
277 * @implemented
278 */
279 int STDCALL
280 EnumFontFamiliesExW(HDC Dc, LPLOGFONTW LogFont, FONTENUMPROCW EnumFontFamProc,
281 LPARAM lParam, DWORD Flags)
282 {
283 return IntEnumFontFamilies(Dc, LogFont, EnumFontFamProc, lParam, TRUE);
284 }
285
286
287 /*
288 * @implemented
289 */
290 int STDCALL
291 EnumFontFamiliesW(HDC Dc, LPCWSTR Family, FONTENUMPROCW EnumFontFamProc,
292 LPARAM lParam)
293 {
294 LOGFONTW LogFont;
295
296 ZeroMemory(&LogFont, sizeof(LOGFONTW));
297 LogFont.lfCharSet = DEFAULT_CHARSET;
298 if (NULL != Family)
299 {
300 lstrcpynW(LogFont.lfFaceName, Family, LF_FACESIZE);
301 }
302
303 return IntEnumFontFamilies(Dc, &LogFont, EnumFontFamProc, lParam, TRUE);
304 }
305
306
307 /*
308 * @implemented
309 */
310 int STDCALL
311 EnumFontFamiliesExA (HDC Dc, LPLOGFONTA LogFont, FONTENUMPROCA EnumFontFamProc,
312 LPARAM lParam, DWORD dwFlags)
313 {
314 LOGFONTW LogFontW;
315
316 RosRtlLogFontA2W(&LogFontW, LogFont);
317
318 /* no need to convert LogFontW back to lpLogFont b/c it's an [in] parameter only */
319 return IntEnumFontFamilies(Dc, &LogFontW, EnumFontFamProc, lParam, FALSE);
320 }
321
322
323 /*
324 * @implemented
325 */
326 int STDCALL
327 EnumFontFamiliesA(HDC Dc, LPCSTR Family, FONTENUMPROCA EnumFontFamProc,
328 LPARAM lParam)
329 {
330 LOGFONTW LogFont;
331
332 ZeroMemory(&LogFont, sizeof(LOGFONTW));
333 LogFont.lfCharSet = DEFAULT_CHARSET;
334 if (NULL != Family)
335 {
336 MultiByteToWideChar(CP_THREAD_ACP, 0, Family, -1, LogFont.lfFaceName, LF_FACESIZE);
337 }
338
339 return IntEnumFontFamilies(Dc, &LogFont, EnumFontFamProc, lParam, FALSE);
340 }
341
342
343 /*
344 * @implemented
345 */
346 BOOL
347 STDCALL
348 GetCharWidthA (
349 HDC hdc,
350 UINT iFirstChar,
351 UINT iLastChar,
352 LPINT lpBuffer
353 )
354 {
355 /* FIXME what to do with iFirstChar and iLastChar ??? */
356 return NtGdiGetCharWidth32 ( hdc, iFirstChar, iLastChar, lpBuffer );
357 }
358
359
360 /*
361 * @implemented
362 */
363 BOOL
364 STDCALL
365 GetCharWidth32A(
366 HDC hdc,
367 UINT iFirstChar,
368 UINT iLastChar,
369 LPINT lpBuffer
370 )
371 {
372 /* FIXME what to do with iFirstChar and iLastChar ??? */
373 return NtGdiGetCharWidth32 ( hdc, iFirstChar, iLastChar, lpBuffer );
374 }
375
376
377 /*
378 * @implemented
379 */
380 BOOL
381 STDCALL
382 GetCharWidthW (
383 HDC hdc,
384 UINT iFirstChar,
385 UINT iLastChar,
386 LPINT lpBuffer
387 )
388 {
389 return NtGdiGetCharWidth32 ( hdc, iFirstChar, iLastChar, lpBuffer );
390 }
391
392
393 /*
394 * @implemented
395 */
396 BOOL
397 STDCALL
398 GetCharWidth32W(
399 HDC hdc,
400 UINT iFirstChar,
401 UINT iLastChar,
402 LPINT lpBuffer
403 )
404 {
405 return NtGdiGetCharWidth32 ( hdc, iFirstChar, iLastChar, lpBuffer );
406 }