- Update FONTGDI and TEXTOBJ. Added support for FT WinFNT. Fixed FillTM so it can...
[reactos.git] / reactos / subsystems / win32 / win32k / objects / font.c
1 /*
2 * PROJECT: ReactOS win32 kernel mode subsystem
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: subsystems/win32/win32k/objects/font.c
5 * PURPOSE: Font
6 * PROGRAMMER:
7 */
8
9 /** Includes ******************************************************************/
10
11 #include <w32k.h>
12
13 #define NDEBUG
14 #include <debug.h>
15
16 /** Functions ******************************************************************/
17
18 INT
19 APIENTRY
20 NtGdiAddFontResourceW(
21 IN WCHAR *pwszFiles,
22 IN ULONG cwc,
23 IN ULONG cFiles,
24 IN FLONG fl,
25 IN DWORD dwPidTid,
26 IN OPTIONAL DESIGNVECTOR *pdv)
27 {
28 UNICODE_STRING SafeFileName;
29 PWSTR src;
30 NTSTATUS Status;
31 int Ret;
32
33 /* FIXME - Protect with SEH? */
34 RtlInitUnicodeString(&SafeFileName, pwszFiles);
35
36 /* Reserve for prepending '\??\' */
37 SafeFileName.Length += 4 * sizeof(WCHAR);
38 SafeFileName.MaximumLength += 4 * sizeof(WCHAR);
39
40 src = SafeFileName.Buffer;
41 SafeFileName.Buffer = (PWSTR)ExAllocatePoolWithTag(PagedPool, SafeFileName.MaximumLength, TAG_STRING);
42 if(!SafeFileName.Buffer)
43 {
44 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
45 return 0;
46 }
47
48 /* Prepend '\??\' */
49 RtlCopyMemory(SafeFileName.Buffer, L"\\??\\", 4 * sizeof(WCHAR));
50
51 Status = MmCopyFromCaller(SafeFileName.Buffer + 4, src, SafeFileName.MaximumLength - (4 * sizeof(WCHAR)));
52 if(!NT_SUCCESS(Status))
53 {
54 ExFreePool(SafeFileName.Buffer);
55 SetLastNtError(Status);
56 return 0;
57 }
58
59 Ret = IntGdiAddFontResource(&SafeFileName, (DWORD)fl);
60
61 ExFreePool(SafeFileName.Buffer);
62 return Ret;
63 }
64
65 /*
66 * @implemented
67 */
68 DWORD
69 APIENTRY
70 NtGdiGetFontUnicodeRanges(
71 IN HDC hdc,
72 OUT OPTIONAL LPGLYPHSET pgs)
73 {
74 PDC pDc;
75 PDC_ATTR Dc_Attr;
76 HFONT hFont;
77 PTEXTOBJ TextObj;
78 PFONTGDI FontGdi;
79 DWORD Size = 0;
80 PGLYPHSET pgsSafe;
81 NTSTATUS Status = STATUS_SUCCESS;
82
83 pDc = DC_LockDc(hdc);
84 if (!pDc)
85 {
86 SetLastWin32Error(ERROR_INVALID_HANDLE);
87 return 0;
88 }
89
90 Dc_Attr = pDc->pDc_Attr;
91 if(!Dc_Attr) Dc_Attr = &pDc->Dc_Attr;
92
93 hFont = Dc_Attr->hlfntNew;
94 TextObj = TEXTOBJ_LockText(hFont);
95
96 if ( TextObj == NULL)
97 {
98 SetLastWin32Error(ERROR_INVALID_HANDLE);
99 goto Exit;
100 }
101 FontGdi = ObjToGDI(TextObj->Font, FONT);
102
103
104 Size = ftGetFontUnicodeRanges( FontGdi, NULL);
105 if (Size && pgs)
106 {
107 pgsSafe = ExAllocatePoolWithTag(PagedPool, Size, TAG_GDITEXT);
108 if (!pgsSafe)
109 {
110 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
111 Size = 0;
112 goto Exit;
113 }
114
115 Size = ftGetFontUnicodeRanges( FontGdi, pgsSafe);
116
117 if (Size)
118 {
119 _SEH_TRY
120 {
121 ProbeForWrite(pgsSafe, Size, 1);
122 RtlCopyMemory(pgs, pgsSafe, Size);
123 }
124 _SEH_HANDLE
125 {
126 Status = _SEH_GetExceptionCode();
127 }
128 _SEH_END
129
130 if (!NT_SUCCESS(Status)) Size = 0;
131 }
132 ExFreePoolWithTag(pgsSafe, TAG_GDITEXT);
133 }
134 Exit:
135 TEXTOBJ_UnlockText(TextObj);
136 DC_UnlockDc(pDc);
137 return Size;
138 }
139
140 ULONG
141 APIENTRY
142 NtGdiGetGlyphOutline(
143 IN HDC hdc,
144 IN WCHAR wch,
145 IN UINT iFormat,
146 OUT LPGLYPHMETRICS pgm,
147 IN ULONG cjBuf,
148 OUT OPTIONAL PVOID UnsafeBuf,
149 IN LPMAT2 pmat2,
150 IN BOOL bIgnoreRotation)
151 {
152 ULONG Ret = GDI_ERROR;
153 PDC dc;
154 PVOID pvBuf = NULL;
155 GLYPHMETRICS gm;
156 NTSTATUS Status = STATUS_SUCCESS;
157
158 dc = DC_LockDc(hdc);
159 if (!dc)
160 {
161 SetLastWin32Error(ERROR_INVALID_HANDLE);
162 return GDI_ERROR;
163 }
164
165 if (UnsafeBuf && cjBuf)
166 {
167 pvBuf = ExAllocatePoolWithTag(PagedPool, cjBuf, TAG_GDITEXT);
168 if (!pvBuf)
169 {
170 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
171 goto Exit;
172 }
173 }
174
175 Ret = ftGdiGetGlyphOutline( dc,
176 wch,
177 iFormat,
178 pgm ? &gm : NULL,
179 cjBuf,
180 pvBuf,
181 pmat2,
182 bIgnoreRotation);
183
184 if (pvBuf)
185 {
186 _SEH_TRY
187 {
188 ProbeForWrite(UnsafeBuf, cjBuf, 1);
189 RtlCopyMemory(UnsafeBuf, pvBuf, cjBuf);
190 }
191 _SEH_HANDLE
192 {
193 Status = _SEH_GetExceptionCode();
194 }
195 _SEH_END
196
197 ExFreePoolWithTag(pvBuf, TAG_GDITEXT);
198 }
199
200 if (pgm)
201 {
202 _SEH_TRY
203 {
204 ProbeForWrite(pgm, sizeof(GLYPHMETRICS), 1);
205 RtlCopyMemory(pgm, &gm, sizeof(GLYPHMETRICS));
206 }
207 _SEH_HANDLE
208 {
209 Status = _SEH_GetExceptionCode();
210 }
211 _SEH_END
212 }
213
214 if (! NT_SUCCESS(Status))
215 {
216 SetLastWin32Error(ERROR_INVALID_PARAMETER);
217 Ret = GDI_ERROR;
218 }
219
220 Exit:
221 DC_UnlockDc(dc);
222 return Ret;
223 }
224
225 DWORD
226 STDCALL
227 NtGdiGetKerningPairs(HDC hDC,
228 ULONG NumPairs,
229 LPKERNINGPAIR krnpair)
230 {
231 UNIMPLEMENTED;
232 return 0;
233 }
234
235 /*
236 From "Undocumented Windows 2000 Secrets" Appendix B, Table B-2, page
237 472, this is NtGdiGetOutlineTextMetricsInternalW.
238 */
239 ULONG
240 STDCALL
241 NtGdiGetOutlineTextMetricsInternalW (HDC hDC,
242 ULONG Data,
243 OUTLINETEXTMETRICW *otm,
244 TMDIFF *Tmd)
245 {
246 PDC dc;
247 PDC_ATTR Dc_Attr;
248 PTEXTOBJ TextObj;
249 PFONTGDI FontGDI;
250 HFONT hFont = 0;
251 ULONG Size;
252 OUTLINETEXTMETRICW *potm;
253 NTSTATUS Status;
254
255 dc = DC_LockDc(hDC);
256 if (dc == NULL)
257 {
258 SetLastWin32Error(ERROR_INVALID_HANDLE);
259 return 0;
260 }
261 Dc_Attr = dc->pDc_Attr;
262 if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
263 hFont = Dc_Attr->hlfntNew;
264 TextObj = TEXTOBJ_LockText(hFont);
265 DC_UnlockDc(dc);
266 if (TextObj == NULL)
267 {
268 SetLastWin32Error(ERROR_INVALID_HANDLE);
269 return 0;
270 }
271 FontGDI = ObjToGDI(TextObj->Font, FONT);
272 TEXTOBJ_UnlockText(TextObj);
273 Size = IntGetOutlineTextMetrics(FontGDI, 0, NULL);
274 if (!otm) return Size;
275 if (Size > Data)
276 {
277 SetLastWin32Error(ERROR_INSUFFICIENT_BUFFER);
278 return 0;
279 }
280 potm = ExAllocatePoolWithTag(PagedPool, Size, TAG_GDITEXT);
281 if (NULL == potm)
282 {
283 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
284 return 0;
285 }
286 IntGetOutlineTextMetrics(FontGDI, Size, potm);
287 if (otm)
288 {
289 Status = MmCopyToCaller(otm, potm, Size);
290 if (! NT_SUCCESS(Status))
291 {
292 SetLastWin32Error(ERROR_INVALID_PARAMETER);
293 ExFreePool(potm);
294 return 0;
295 }
296 }
297 ExFreePool(potm);
298 return Size;
299 }
300
301 HFONT
302 STDCALL
303 NtGdiHfontCreate(
304 IN PENUMLOGFONTEXDVW pelfw,
305 IN ULONG cjElfw,
306 IN LFTYPE lft,
307 IN FLONG fl,
308 IN PVOID pvCliData )
309 {
310 ENUMLOGFONTEXDVW SafeLogfont;
311 HFONT hNewFont;
312 PTEXTOBJ TextObj;
313 NTSTATUS Status = STATUS_SUCCESS;
314
315 if (!pelfw)
316 {
317 return NULL;
318 }
319
320 _SEH_TRY
321 {
322 ProbeForRead(pelfw, sizeof(ENUMLOGFONTEXDVW), 1);
323 RtlCopyMemory(&SafeLogfont, pelfw, sizeof(ENUMLOGFONTEXDVW));
324 }
325 _SEH_HANDLE
326 {
327 Status = _SEH_GetExceptionCode();
328 }
329 _SEH_END
330
331 if (!NT_SUCCESS(Status))
332 {
333 return NULL;
334 }
335
336 TextObj = TEXTOBJ_AllocTextWithHandle();
337 if (!TextObj)
338 {
339 return NULL;
340 }
341 hNewFont = TextObj->BaseObject.hHmgr;
342
343 TextObj->lft = cjElfw;
344 TextObj->fl = fl;
345 RtlCopyMemory (&TextObj->logfont, &SafeLogfont, sizeof(ENUMLOGFONTEXDVW));
346
347 if (SafeLogfont.elfEnumLogfontEx.elfLogFont.lfEscapement !=
348 SafeLogfont.elfEnumLogfontEx.elfLogFont.lfOrientation)
349 {
350 /* this should really depend on whether GM_ADVANCED is set */
351 TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfOrientation =
352 TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfEscapement;
353 }
354 TEXTOBJ_UnlockText(TextObj);
355
356 return hNewFont;
357 }
358
359
360 /* EOF */