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