[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 VOID
118 NTAPI
119 BRUSH_vCleanup(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
141 INT
142 FASTCALL
143 BRUSH_GetObject(PBRUSH pbrush, INT cjSize, LPLOGBRUSH plogbrush)
144 {
145 /* Check if only size is requested */
146 if (plogbrush == NULL) return sizeof(LOGBRUSH);
147
148 /* Check if size is ok */
149 if (cjSize == 0) return 0;
150
151 /* Set colour */
152 plogbrush->lbColor = pbrush->BrushAttr.lbColor;
153
154 /* Default to 0 */
155 plogbrush->lbHatch = 0;
156
157 /* Get the type of style */
158 if (pbrush->flAttrs & BR_IS_SOLID)
159 {
160 plogbrush->lbStyle = BS_SOLID;
161 }
162 else if (pbrush->flAttrs & BR_IS_NULL)
163 {
164 plogbrush->lbStyle = BS_NULL; // BS_HOLLOW
165 }
166 else if (pbrush->flAttrs & BR_IS_HATCH)
167 {
168 plogbrush->lbStyle = BS_HATCHED;
169 plogbrush->lbHatch = pbrush->ulStyle;
170 }
171 else if (pbrush->flAttrs & BR_IS_DIB)
172 {
173 plogbrush->lbStyle = BS_DIBPATTERN;
174 plogbrush->lbHatch = (ULONG_PTR)pbrush->hbmClient;
175 }
176 else if (pbrush->flAttrs & BR_IS_BITMAP)
177 {
178 plogbrush->lbStyle = BS_PATTERN;
179 }
180 else
181 {
182 plogbrush->lbStyle = 0; // ???
183 }
184
185 /* FIXME
186 else if (pbrush->flAttrs & )
187 {
188 plogbrush->lbStyle = BS_INDEXED;
189 }
190 else if (pbrush->flAttrs & )
191 {
192 plogbrush->lbStyle = BS_DIBPATTERNPT;
193 }
194 */
195
196 /* FIXME */
197 return sizeof(LOGBRUSH);
198 }
199
200 HBRUSH
201 APIENTRY
202 IntGdiCreateDIBBrush(
203 CONST BITMAPINFO *BitmapInfo,
204 UINT ColorSpec,
205 UINT BitmapInfoSize,
206 CONST VOID *PackedDIB)
207 {
208 HBRUSH hBrush;
209 PBRUSH pbrush;
210 HBITMAP hPattern;
211 ULONG_PTR DataPtr;
212 PVOID pvDIBits;
213
214 if (BitmapInfo->bmiHeader.biSize < sizeof(BITMAPINFOHEADER))
215 {
216 EngSetLastError(ERROR_INVALID_PARAMETER);
217 return NULL;
218 }
219
220 DataPtr = (ULONG_PTR)BitmapInfo + DIB_BitmapInfoSize(BitmapInfo, ColorSpec);
221
222 hPattern = DIB_CreateDIBSection(NULL, BitmapInfo, ColorSpec, &pvDIBits, NULL, 0, 0);
223 if (hPattern == NULL)
224 {
225 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
226 return NULL;
227 }
228 RtlCopyMemory(pvDIBits,
229 (PVOID)DataPtr,
230 DIB_GetDIBImageBytes(BitmapInfo->bmiHeader.biWidth,
231 BitmapInfo->bmiHeader.biHeight,
232 BitmapInfo->bmiHeader.biBitCount * BitmapInfo->bmiHeader.biPlanes));
233
234 pbrush = BRUSH_AllocBrushWithHandle();
235 if (pbrush == NULL)
236 {
237 GreDeleteObject(hPattern);
238 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
239 return NULL;
240 }
241 hBrush = pbrush->BaseObject.hHmgr;
242
243 pbrush->flAttrs |= BR_IS_BITMAP | BR_IS_DIB;
244 pbrush->hbmPattern = hPattern;
245 pbrush->hbmClient = (HBITMAP)PackedDIB;
246 /* FIXME: Fill in the rest of fields!!! */
247
248 GreSetObjectOwner(hPattern, GDI_OBJ_HMGR_PUBLIC);
249
250 GDIOBJ_vUnlockObject(&pbrush->BaseObject);
251
252 return hBrush;
253 }
254
255 HBRUSH
256 APIENTRY
257 IntGdiCreateHatchBrush(
258 INT Style,
259 COLORREF Color)
260 {
261 HBRUSH hBrush;
262 PBRUSH pbrush;
263
264 if (Style < 0 || Style >= NB_HATCH_STYLES)
265 {
266 return 0;
267 }
268
269 pbrush = BRUSH_AllocBrushWithHandle();
270 if (pbrush == NULL)
271 {
272 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
273 return NULL;
274 }
275 hBrush = pbrush->BaseObject.hHmgr;
276
277 pbrush->flAttrs |= BR_IS_HATCH;
278 pbrush->BrushAttr.lbColor = Color & 0xFFFFFF;
279 pbrush->ulStyle = Style;
280
281 GDIOBJ_vUnlockObject(&pbrush->BaseObject);
282
283 return hBrush;
284 }
285
286 HBRUSH
287 APIENTRY
288 IntGdiCreatePatternBrush(
289 HBITMAP hBitmap)
290 {
291 HBRUSH hBrush;
292 PBRUSH pbrush;
293 HBITMAP hPattern;
294
295 hPattern = BITMAP_CopyBitmap(hBitmap);
296 if (hPattern == NULL)
297 {
298 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
299 return NULL;
300 }
301
302 pbrush = BRUSH_AllocBrushWithHandle();
303 if (pbrush == NULL)
304 {
305 GreDeleteObject(hPattern);
306 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
307 return NULL;
308 }
309 hBrush = pbrush->BaseObject.hHmgr;
310
311 pbrush->flAttrs |= BR_IS_BITMAP;
312 pbrush->hbmPattern = hPattern;
313 /* FIXME: Fill in the rest of fields!!! */
314
315 GreSetObjectOwner(hPattern, GDI_OBJ_HMGR_PUBLIC);
316
317 GDIOBJ_vUnlockObject(&pbrush->BaseObject);
318
319 return hBrush;
320 }
321
322 HBRUSH
323 APIENTRY
324 IntGdiCreateSolidBrush(
325 COLORREF Color)
326 {
327 HBRUSH hBrush;
328 PBRUSH pbrush;
329
330 pbrush = BRUSH_AllocBrushWithHandle();
331 if (pbrush == NULL)
332 {
333 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
334 return NULL;
335 }
336 hBrush = pbrush->BaseObject.hHmgr;
337
338 pbrush->flAttrs |= BR_IS_SOLID;
339
340 pbrush->BrushAttr.lbColor = Color & 0x00FFFFFF;
341 /* FIXME: Fill in the rest of fields!!! */
342
343 GDIOBJ_vUnlockObject(&pbrush->BaseObject);
344
345 return hBrush;
346 }
347
348 HBRUSH
349 APIENTRY
350 IntGdiCreateNullBrush(VOID)
351 {
352 HBRUSH hBrush;
353 PBRUSH pbrush;
354
355 pbrush = BRUSH_AllocBrushWithHandle();
356 if (pbrush == NULL)
357 {
358 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
359 return NULL;
360 }
361 hBrush = pbrush->BaseObject.hHmgr;
362
363 pbrush->flAttrs |= BR_IS_NULL;
364 GDIOBJ_vUnlockObject(&pbrush->BaseObject);
365
366 return hBrush;
367 }
368
369 VOID
370 FASTCALL
371 IntGdiSetSolidBrushColor(HBRUSH hBrush, COLORREF Color)
372 {
373 PBRUSH pbrush;
374
375 pbrush = BRUSH_ShareLockBrush(hBrush);
376 if (pbrush->flAttrs & BR_IS_SOLID)
377 {
378 pbrush->BrushAttr.lbColor = Color & 0xFFFFFF;
379 }
380 BRUSH_ShareUnlockBrush(pbrush);
381 }
382
383
384 /* PUBLIC FUNCTIONS ***********************************************************/
385
386 HBRUSH
387 APIENTRY
388 NtGdiCreateDIBBrush(
389 IN PVOID BitmapInfoAndData,
390 IN FLONG ColorSpec,
391 IN UINT BitmapInfoSize,
392 IN BOOL b8X8,
393 IN BOOL bPen,
394 IN PVOID PackedDIB)
395 {
396 BITMAPINFO *SafeBitmapInfoAndData;
397 NTSTATUS Status = STATUS_SUCCESS;
398 HBRUSH hBrush;
399
400 SafeBitmapInfoAndData = EngAllocMem(FL_ZERO_MEMORY, BitmapInfoSize, TAG_DIB);
401 if (SafeBitmapInfoAndData == NULL)
402 {
403 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
404 return NULL;
405 }
406
407 _SEH2_TRY
408 {
409 ProbeForRead(BitmapInfoAndData, BitmapInfoSize, 1);
410 RtlCopyMemory(SafeBitmapInfoAndData, BitmapInfoAndData, BitmapInfoSize);
411 }
412 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
413 {
414 Status = _SEH2_GetExceptionCode();
415 }
416 _SEH2_END;
417
418 if (!NT_SUCCESS(Status))
419 {
420 EngFreeMem(SafeBitmapInfoAndData);
421 SetLastNtError(Status);
422 return 0;
423 }
424
425 hBrush = IntGdiCreateDIBBrush(SafeBitmapInfoAndData,
426 ColorSpec,
427 BitmapInfoSize,
428 PackedDIB);
429
430 EngFreeMem(SafeBitmapInfoAndData);
431
432 return hBrush;
433 }
434
435 HBRUSH
436 APIENTRY
437 NtGdiCreateHatchBrushInternal(
438 ULONG Style,
439 COLORREF Color,
440 BOOL bPen)
441 {
442 return IntGdiCreateHatchBrush(Style, Color);
443 }
444
445 HBRUSH
446 APIENTRY
447 NtGdiCreatePatternBrushInternal(
448 HBITMAP hBitmap,
449 BOOL bPen,
450 BOOL b8x8)
451 {
452 return IntGdiCreatePatternBrush(hBitmap);
453 }
454
455 HBRUSH
456 APIENTRY
457 NtGdiCreateSolidBrush(COLORREF Color,
458 IN OPTIONAL HBRUSH hbr)
459 {
460 return IntGdiCreateSolidBrush(Color);
461 }
462
463
464 /* EOF */