[WIN32K]
[reactos.git] / reactos / win32ss / gdi / ntgdi / brush.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS win32 subsystem
4 * PURPOSE: Functions for brushes
5 * FILE: subsystem/win32/win32k/objects/brush.c
6 * PROGRAMER:
7 */
8
9 #include <win32k.h>
10
11 #define NDEBUG
12 #include <debug.h>
13
14 #define GDIOBJATTRFREE 170
15
16 typedef struct _GDI_OBJ_ATTR_FREELIST
17 {
18 LIST_ENTRY Entry;
19 DWORD nEntries;
20 PVOID AttrList[GDIOBJATTRFREE];
21 } GDI_OBJ_ATTR_FREELIST, *PGDI_OBJ_ATTR_FREELIST;
22
23 typedef struct _GDI_OBJ_ATTR_ENTRY
24 {
25 RGN_ATTR Attr[GDIOBJATTRFREE];
26 } GDI_OBJ_ATTR_ENTRY, *PGDI_OBJ_ATTR_ENTRY;
27
28 BOOL
29 FASTCALL
30 IntGdiSetBrushOwner(PBRUSH pbr, ULONG ulOwner)
31 {
32 // FIXME:
33 if (pbr->flAttrs & BR_IS_GLOBAL) return TRUE;
34
35 if ((ulOwner == GDI_OBJ_HMGR_PUBLIC) || ulOwner == GDI_OBJ_HMGR_NONE)
36 {
37 // Deny user access to User Data.
38 GDIOBJ_vSetObjectAttr(&pbr->BaseObject, NULL);
39 // FIXME: deallocate brush attr
40 }
41
42 if (ulOwner == GDI_OBJ_HMGR_POWNED)
43 {
44 // Allow user access to User Data.
45 GDIOBJ_vSetObjectAttr(&pbr->BaseObject, pbr->pBrushAttr);
46 // FIXME: Allocate brush attr
47 }
48
49 GDIOBJ_vSetObjectOwner(&pbr->BaseObject, ulOwner);
50
51 return TRUE;
52 }
53
54 BOOL
55 FASTCALL
56 GreSetBrushOwner(HBRUSH hBrush, ULONG ulOwner)
57 {
58 BOOL Ret;
59 PBRUSH pbrush;
60
61 pbrush = BRUSH_ShareLockBrush(hBrush);
62 Ret = IntGdiSetBrushOwner(pbrush, ulOwner);
63 BRUSH_ShareUnlockBrush(pbrush);
64 return Ret;
65 }
66
67 BOOL
68 NTAPI
69 BRUSH_bAllocBrushAttr(PBRUSH pbr)
70 {
71 PPROCESSINFO ppi;
72 BRUSH_ATTR *pBrushAttr;
73
74 ppi = PsGetCurrentProcessWin32Process();
75 ASSERT(ppi);
76
77 pBrushAttr = GdiPoolAllocate(ppi->pPoolDcAttr);
78 if (!pBrushAttr)
79 {
80 DPRINT1("Could not allocate brush attr\n");
81 return FALSE;
82 }
83
84 /* Copy the content from the kernel mode dc attr */
85 pbr->pBrushAttr = pBrushAttr;
86 *pbr->pBrushAttr = pbr->BrushAttr;
87
88 /* Set the object attribute in the handle table */
89 GDIOBJ_vSetObjectAttr(&pbr->BaseObject, pBrushAttr);
90
91 DPRINT("BRUSH_bAllocBrushAttr: pbr=%p, pbr->pdcattr=%p\n", pbr, pbr->pBrushAttr);
92 return TRUE;
93 }
94
95
96 VOID
97 NTAPI
98 BRUSH_vFreeBrushAttr(PBRUSH pbr)
99 {
100 #if 0
101 PPROCESSINFO ppi;
102
103 if (pbrush->pBrushAttr == &pbrush->BrushAttr) return;
104
105 /* Reset the object attribute in the handle table */
106 GDIOBJ_vSetObjectAttr(&pbr->BaseObject, NULL);
107
108 /* Free memory from the process gdi pool */
109 ppi = PsGetCurrentProcessWin32Process();
110 ASSERT(ppi);
111 GdiPoolFree(ppi->pPoolBrushAttr, pbr->pBrushAttr);
112 #endif
113 /* Reset to kmode brush attribute */
114 pbr->pBrushAttr = &pbr->BrushAttr;
115 }
116
117 BOOL
118 NTAPI
119 BRUSH_Cleanup(PVOID ObjectBody)
120 {
121 PBRUSH pbrush = (PBRUSH)ObjectBody;
122 if (pbrush->hbmPattern)
123 {
124 GreSetObjectOwner(pbrush->hbmPattern, GDI_OBJ_HMGR_POWNED);
125 GreDeleteObject(pbrush->hbmPattern);
126 }
127
128 /* Check if there is a usermode attribute */
129 if (pbrush->pBrushAttr != &pbrush->BrushAttr)
130 {
131 BRUSH_vFreeBrushAttr(pbrush);
132 }
133
134 /* Free the kmode styles array of EXTPENS */
135 if (pbrush->pStyle)
136 {
137 ExFreePool(pbrush->pStyle);
138 }
139
140 return TRUE;
141 }
142
143 INT
144 FASTCALL
145 BRUSH_GetObject(PBRUSH pbrush, INT cjSize, LPLOGBRUSH plogbrush)
146 {
147 /* Check if only size is requested */
148 if (plogbrush == NULL) return sizeof(LOGBRUSH);
149
150 /* Check if size is ok */
151 if (cjSize == 0) return 0;
152
153 /* Set colour */
154 plogbrush->lbColor = pbrush->BrushAttr.lbColor;
155
156 /* Default to 0 */
157 plogbrush->lbHatch = 0;
158
159 /* Get the type of style */
160 if (pbrush->flAttrs & BR_IS_SOLID)
161 {
162 plogbrush->lbStyle = BS_SOLID;
163 }
164 else if (pbrush->flAttrs & BR_IS_NULL)
165 {
166 plogbrush->lbStyle = BS_NULL; // BS_HOLLOW
167 }
168 else if (pbrush->flAttrs & BR_IS_HATCH)
169 {
170 plogbrush->lbStyle = BS_HATCHED;
171 plogbrush->lbHatch = pbrush->ulStyle;
172 }
173 else if (pbrush->flAttrs & BR_IS_DIB)
174 {
175 plogbrush->lbStyle = BS_DIBPATTERN;
176 plogbrush->lbHatch = (ULONG_PTR)pbrush->hbmClient;
177 }
178 else if (pbrush->flAttrs & BR_IS_BITMAP)
179 {
180 plogbrush->lbStyle = BS_PATTERN;
181 }
182 else
183 {
184 plogbrush->lbStyle = 0; // ???
185 }
186
187 /* FIXME
188 else if (pbrush->flAttrs & )
189 {
190 plogbrush->lbStyle = BS_INDEXED;
191 }
192 else if (pbrush->flAttrs & )
193 {
194 plogbrush->lbStyle = BS_DIBPATTERNPT;
195 }
196 */
197
198 /* FIXME */
199 return sizeof(LOGBRUSH);
200 }
201
202 HBRUSH
203 APIENTRY
204 IntGdiCreateDIBBrush(
205 CONST BITMAPINFO *BitmapInfo,
206 UINT ColorSpec,
207 UINT BitmapInfoSize,
208 CONST VOID *PackedDIB)
209 {
210 HBRUSH hBrush;
211 PBRUSH pbrush;
212 HBITMAP hPattern;
213 ULONG_PTR DataPtr;
214 PVOID pvDIBits;
215
216 if (BitmapInfo->bmiHeader.biSize < sizeof(BITMAPINFOHEADER))
217 {
218 EngSetLastError(ERROR_INVALID_PARAMETER);
219 return NULL;
220 }
221
222 DataPtr = (ULONG_PTR)BitmapInfo + DIB_BitmapInfoSize(BitmapInfo, ColorSpec);
223
224 hPattern = DIB_CreateDIBSection(NULL, BitmapInfo, ColorSpec, &pvDIBits, NULL, 0, 0);
225 if (hPattern == NULL)
226 {
227 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
228 return NULL;
229 }
230 RtlCopyMemory(pvDIBits,
231 (PVOID)DataPtr,
232 DIB_GetDIBImageBytes(BitmapInfo->bmiHeader.biWidth,
233 BitmapInfo->bmiHeader.biHeight,
234 BitmapInfo->bmiHeader.biBitCount * BitmapInfo->bmiHeader.biPlanes));
235
236 pbrush = BRUSH_AllocBrushWithHandle();
237 if (pbrush == NULL)
238 {
239 GreDeleteObject(hPattern);
240 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
241 return NULL;
242 }
243 hBrush = pbrush->BaseObject.hHmgr;
244
245 pbrush->flAttrs |= BR_IS_BITMAP | BR_IS_DIB;
246 pbrush->hbmPattern = hPattern;
247 pbrush->hbmClient = (HBITMAP)PackedDIB;
248 /* FIXME: Fill in the rest of fields!!! */
249
250 GreSetObjectOwner(hPattern, GDI_OBJ_HMGR_PUBLIC);
251
252 GDIOBJ_vUnlockObject(&pbrush->BaseObject);
253
254 return hBrush;
255 }
256
257 HBRUSH
258 APIENTRY
259 IntGdiCreateHatchBrush(
260 INT Style,
261 COLORREF Color)
262 {
263 HBRUSH hBrush;
264 PBRUSH pbrush;
265
266 if (Style < 0 || Style >= NB_HATCH_STYLES)
267 {
268 return 0;
269 }
270
271 pbrush = BRUSH_AllocBrushWithHandle();
272 if (pbrush == NULL)
273 {
274 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
275 return NULL;
276 }
277 hBrush = pbrush->BaseObject.hHmgr;
278
279 pbrush->flAttrs |= BR_IS_HATCH;
280 pbrush->BrushAttr.lbColor = Color & 0xFFFFFF;
281 pbrush->ulStyle = Style;
282
283 GDIOBJ_vUnlockObject(&pbrush->BaseObject);
284
285 return hBrush;
286 }
287
288 HBRUSH
289 APIENTRY
290 IntGdiCreatePatternBrush(
291 HBITMAP hBitmap)
292 {
293 HBRUSH hBrush;
294 PBRUSH pbrush;
295 HBITMAP hPattern;
296
297 hPattern = BITMAP_CopyBitmap(hBitmap);
298 if (hPattern == NULL)
299 {
300 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
301 return NULL;
302 }
303
304 pbrush = BRUSH_AllocBrushWithHandle();
305 if (pbrush == NULL)
306 {
307 GreDeleteObject(hPattern);
308 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
309 return NULL;
310 }
311 hBrush = pbrush->BaseObject.hHmgr;
312
313 pbrush->flAttrs |= BR_IS_BITMAP;
314 pbrush->hbmPattern = hPattern;
315 /* FIXME: Fill in the rest of fields!!! */
316
317 GreSetObjectOwner(hPattern, GDI_OBJ_HMGR_PUBLIC);
318
319 GDIOBJ_vUnlockObject(&pbrush->BaseObject);
320
321 return hBrush;
322 }
323
324 HBRUSH
325 APIENTRY
326 IntGdiCreateSolidBrush(
327 COLORREF Color)
328 {
329 HBRUSH hBrush;
330 PBRUSH pbrush;
331
332 pbrush = BRUSH_AllocBrushWithHandle();
333 if (pbrush == NULL)
334 {
335 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
336 return NULL;
337 }
338 hBrush = pbrush->BaseObject.hHmgr;
339
340 pbrush->flAttrs |= BR_IS_SOLID;
341
342 pbrush->BrushAttr.lbColor = Color & 0x00FFFFFF;
343 /* FIXME: Fill in the rest of fields!!! */
344
345 GDIOBJ_vUnlockObject(&pbrush->BaseObject);
346
347 return hBrush;
348 }
349
350 HBRUSH
351 APIENTRY
352 IntGdiCreateNullBrush(VOID)
353 {
354 HBRUSH hBrush;
355 PBRUSH pbrush;
356
357 pbrush = BRUSH_AllocBrushWithHandle();
358 if (pbrush == NULL)
359 {
360 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
361 return NULL;
362 }
363 hBrush = pbrush->BaseObject.hHmgr;
364
365 pbrush->flAttrs |= BR_IS_NULL;
366 GDIOBJ_vUnlockObject(&pbrush->BaseObject);
367
368 return hBrush;
369 }
370
371 VOID
372 FASTCALL
373 IntGdiSetSolidBrushColor(HBRUSH hBrush, COLORREF Color)
374 {
375 PBRUSH pbrush;
376
377 pbrush = BRUSH_ShareLockBrush(hBrush);
378 if (pbrush->flAttrs & BR_IS_SOLID)
379 {
380 pbrush->BrushAttr.lbColor = Color & 0xFFFFFF;
381 }
382 BRUSH_ShareUnlockBrush(pbrush);
383 }
384
385
386 /* PUBLIC FUNCTIONS ***********************************************************/
387
388 HBRUSH
389 APIENTRY
390 NtGdiCreateDIBBrush(
391 IN PVOID BitmapInfoAndData,
392 IN FLONG ColorSpec,
393 IN UINT BitmapInfoSize,
394 IN BOOL b8X8,
395 IN BOOL bPen,
396 IN PVOID PackedDIB)
397 {
398 BITMAPINFO *SafeBitmapInfoAndData;
399 NTSTATUS Status = STATUS_SUCCESS;
400 HBRUSH hBrush;
401
402 SafeBitmapInfoAndData = EngAllocMem(FL_ZERO_MEMORY, BitmapInfoSize, TAG_DIB);
403 if (SafeBitmapInfoAndData == NULL)
404 {
405 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
406 return NULL;
407 }
408
409 _SEH2_TRY
410 {
411 ProbeForRead(BitmapInfoAndData, BitmapInfoSize, 1);
412 RtlCopyMemory(SafeBitmapInfoAndData, BitmapInfoAndData, BitmapInfoSize);
413 }
414 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
415 {
416 Status = _SEH2_GetExceptionCode();
417 }
418 _SEH2_END;
419
420 if (!NT_SUCCESS(Status))
421 {
422 EngFreeMem(SafeBitmapInfoAndData);
423 SetLastNtError(Status);
424 return 0;
425 }
426
427 hBrush = IntGdiCreateDIBBrush(SafeBitmapInfoAndData,
428 ColorSpec,
429 BitmapInfoSize,
430 PackedDIB);
431
432 EngFreeMem(SafeBitmapInfoAndData);
433
434 return hBrush;
435 }
436
437 HBRUSH
438 APIENTRY
439 NtGdiCreateHatchBrushInternal(
440 ULONG Style,
441 COLORREF Color,
442 BOOL bPen)
443 {
444 return IntGdiCreateHatchBrush(Style, Color);
445 }
446
447 HBRUSH
448 APIENTRY
449 NtGdiCreatePatternBrushInternal(
450 HBITMAP hBitmap,
451 BOOL bPen,
452 BOOL b8x8)
453 {
454 return IntGdiCreatePatternBrush(hBitmap);
455 }
456
457 HBRUSH
458 APIENTRY
459 NtGdiCreateSolidBrush(COLORREF Color,
460 IN OPTIONAL HBRUSH hbr)
461 {
462 return IntGdiCreateSolidBrush(Color);
463 }
464
465
466 /* EOF */