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
14 #define GDIOBJATTRFREE 170
16 typedef struct _GDI_OBJ_ATTR_FREELIST
20 PVOID AttrList
[GDIOBJATTRFREE
];
21 } GDI_OBJ_ATTR_FREELIST
, *PGDI_OBJ_ATTR_FREELIST
;
23 typedef struct _GDI_OBJ_ATTR_ENTRY
25 RGN_ATTR Attr
[GDIOBJATTRFREE
];
26 } GDI_OBJ_ATTR_ENTRY
, *PGDI_OBJ_ATTR_ENTRY
;
28 static const ULONG HatchBrushes
[NB_HATCH_STYLES
][8] =
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 */
41 AllocateObjectAttr(VOID
)
46 PGDI_OBJ_ATTR_FREELIST pGdiObjAttrFreeList
;
47 PGDI_OBJ_ATTR_ENTRY pGdiObjAttrEntry
;
50 pti
= PsGetCurrentThreadWin32Thread();
51 if (pti
->pgdiBrushAttr
)
53 pAttr
= pti
->pgdiBrushAttr
; // Get the free one.
54 pti
->pgdiBrushAttr
= NULL
;
58 ppi
= PsGetCurrentProcessWin32Process();
60 if (!ppi
->pBrushAttrList
) // If set point is null, allocate new group.
62 pGdiObjAttrEntry
= EngAllocUserMem(sizeof(GDI_OBJ_ATTR_ENTRY
), 0);
64 if (!pGdiObjAttrEntry
)
66 DPRINT1("Attr Failed User Allocation!\n");
70 DPRINT("AllocObjectAttr User 0x%x\n",pGdiObjAttrEntry
);
72 pGdiObjAttrFreeList
= ExAllocatePoolWithTag( PagedPool
,
73 sizeof(GDI_OBJ_ATTR_FREELIST
),
74 GDITAG_BRUSH_FREELIST
);
75 if ( !pGdiObjAttrFreeList
)
77 EngFreeUserMem(pGdiObjAttrEntry
);
81 RtlZeroMemory(pGdiObjAttrFreeList
, sizeof(GDI_OBJ_ATTR_FREELIST
));
83 DPRINT("AllocObjectAttr Ex 0x%x\n",pGdiObjAttrFreeList
);
85 InsertHeadList( &ppi
->GDIBrushAttrFreeList
, &pGdiObjAttrFreeList
->Entry
);
87 pGdiObjAttrFreeList
->nEntries
= GDIOBJATTRFREE
;
88 // Start at the bottom up and set end of free list point.
89 ppi
->pBrushAttrList
= &pGdiObjAttrEntry
->Attr
[GDIOBJATTRFREE
-1];
90 // Build the free attr list.
91 for ( i
= 0; i
< GDIOBJATTRFREE
; i
++)
93 pGdiObjAttrFreeList
->AttrList
[i
] = &pGdiObjAttrEntry
->Attr
[i
];
97 pAttr
= ppi
->pBrushAttrList
;
98 pGdiObjAttrFreeList
= (PGDI_OBJ_ATTR_FREELIST
)ppi
->GDIBrushAttrFreeList
.Flink
;
100 // Free the list when it is full!
101 if ( pGdiObjAttrFreeList
->nEntries
-- == 1)
102 { // No more free entries, so yank the list.
103 RemoveEntryList( &pGdiObjAttrFreeList
->Entry
);
105 ExFreePoolWithTag( pGdiObjAttrFreeList
, GDITAG_BRUSH_FREELIST
);
107 if ( IsListEmpty( &ppi
->GDIBrushAttrFreeList
) )
109 ppi
->pBrushAttrList
= NULL
;
113 pGdiObjAttrFreeList
= (PGDI_OBJ_ATTR_FREELIST
)ppi
->GDIBrushAttrFreeList
.Flink
;
116 ppi
->pBrushAttrList
= pGdiObjAttrFreeList
->AttrList
[pGdiObjAttrFreeList
->nEntries
-1];
123 FreeObjectAttr(PVOID pAttr
)
127 PGDI_OBJ_ATTR_FREELIST pGdiObjAttrFreeList
;
129 pti
= PsGetCurrentThreadWin32Thread();
133 if (!pti
->pgdiBrushAttr
)
134 { // If it is null, just cache it for the next time.
135 pti
->pgdiBrushAttr
= pAttr
;
139 ppi
= PsGetCurrentProcessWin32Process();
141 pGdiObjAttrFreeList
= (PGDI_OBJ_ATTR_FREELIST
)ppi
->GDIBrushAttrFreeList
.Flink
;
143 // We add to the list of free entries, so this will grows!
144 if ( IsListEmpty(&ppi
->GDIBrushAttrFreeList
) ||
145 pGdiObjAttrFreeList
->nEntries
== GDIOBJATTRFREE
)
147 pGdiObjAttrFreeList
= ExAllocatePoolWithTag( PagedPool
,
148 sizeof(GDI_OBJ_ATTR_FREELIST
),
149 GDITAG_BRUSH_FREELIST
);
150 if ( !pGdiObjAttrFreeList
)
154 InsertHeadList( &ppi
->GDIBrushAttrFreeList
, &pGdiObjAttrFreeList
->Entry
);
155 pGdiObjAttrFreeList
->nEntries
= 0;
157 // Up count, save the entry and set end of free list point.
158 ++pGdiObjAttrFreeList
->nEntries
; // Top Down...
159 pGdiObjAttrFreeList
->AttrList
[pGdiObjAttrFreeList
->nEntries
-1] = pAttr
;
160 ppi
->pBrushAttrList
= pAttr
;
168 BRUSH_Cleanup(PVOID ObjectBody
)
170 PBRUSH pbrush
= (PBRUSH
)ObjectBody
;
171 if (pbrush
->flAttrs
& (GDIBRUSH_IS_HATCH
| GDIBRUSH_IS_BITMAP
))
173 ASSERT(pbrush
->hbmPattern
);
174 GDIOBJ_SetOwnership(pbrush
->hbmPattern
, PsGetCurrentProcess());
175 GreDeleteObject(pbrush
->hbmPattern
);
178 /* Free the kmode styles array of EXTPENS */
181 ExFreePool(pbrush
->pStyle
);
189 BRUSH_GetObject(PBRUSH pbrush
, INT Count
, LPLOGBRUSH Buffer
)
191 if (Buffer
== NULL
) return sizeof(LOGBRUSH
);
192 if (Count
== 0) return 0;
195 Buffer
->lbColor
= pbrush
->BrushAttr
.lbColor
;
198 if ((pbrush
->flAttrs
& GDIBRUSH_IS_HATCH
)!=0)
200 /* FIXME : this is not the right value */
201 Buffer
->lbHatch
= (LONG
)pbrush
->hbmPattern
;
210 /* Get the type of style */
211 if ((pbrush
->flAttrs
& GDIBRUSH_IS_SOLID
)!=0)
213 Buffer
->lbStyle
= BS_SOLID
;
215 else if ((pbrush
->flAttrs
& GDIBRUSH_IS_NULL
)!=0)
217 Buffer
->lbStyle
= BS_NULL
; // BS_HOLLOW
219 else if ((pbrush
->flAttrs
& GDIBRUSH_IS_HATCH
)!=0)
221 Buffer
->lbStyle
= BS_HATCHED
;
223 else if ((pbrush
->flAttrs
& GDIBRUSH_IS_BITMAP
)!=0)
225 Buffer
->lbStyle
= BS_PATTERN
;
227 else if ((pbrush
->flAttrs
& GDIBRUSH_IS_DIB
)!=0)
229 Buffer
->lbStyle
= BS_DIBPATTERN
;
233 else if ((pbrush->flAttrs & )!=0)
235 Buffer->lbStyle = BS_INDEXED;
237 else if ((pbrush->flAttrs & )!=0)
239 Buffer->lbStyle = BS_DIBPATTERNPT;
244 return sizeof(LOGBRUSH
);
249 IntGdiCreateDIBBrush(
250 CONST BITMAPINFO
*BitmapInfo
,
253 CONST VOID
*PackedDIB
)
261 if (BitmapInfo
->bmiHeader
.biSize
< sizeof(BITMAPINFOHEADER
))
263 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
267 DataPtr
= (ULONG_PTR
)BitmapInfo
+ DIB_BitmapInfoSize(BitmapInfo
, ColorSpec
);
269 hPattern
= DIB_CreateDIBSection(NULL
, BitmapInfo
, ColorSpec
, &pvDIBits
, NULL
, 0, 0);
270 if (hPattern
== NULL
)
272 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
275 RtlCopyMemory(pvDIBits
,
277 DIB_GetDIBImageBytes(BitmapInfo
->bmiHeader
.biWidth
,
278 BitmapInfo
->bmiHeader
.biHeight
,
279 BitmapInfo
->bmiHeader
.biBitCount
* BitmapInfo
->bmiHeader
.biPlanes
));
281 pbrush
= BRUSH_AllocBrushWithHandle();
284 GreDeleteObject(hPattern
);
285 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
288 hBrush
= pbrush
->BaseObject
.hHmgr
;
290 pbrush
->flAttrs
|= GDIBRUSH_IS_BITMAP
| GDIBRUSH_IS_DIB
;
291 pbrush
->hbmPattern
= hPattern
;
292 /* FIXME: Fill in the rest of fields!!! */
294 GDIOBJ_SetOwnership(hPattern
, NULL
);
296 BRUSH_UnlockBrush(pbrush
);
303 IntGdiCreateHatchBrush(
311 if (Style
< 0 || Style
>= NB_HATCH_STYLES
)
316 hPattern
= GreCreateBitmap(8, 8, 1, 1, (LPBYTE
)HatchBrushes
[Style
]);
317 if (hPattern
== NULL
)
319 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
323 pbrush
= BRUSH_AllocBrushWithHandle();
326 GreDeleteObject(hPattern
);
327 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
330 hBrush
= pbrush
->BaseObject
.hHmgr
;
332 pbrush
->flAttrs
|= GDIBRUSH_IS_HATCH
;
333 pbrush
->hbmPattern
= hPattern
;
334 pbrush
->BrushAttr
.lbColor
= Color
& 0xFFFFFF;
336 GDIOBJ_SetOwnership(hPattern
, NULL
);
338 BRUSH_UnlockBrush(pbrush
);
345 IntGdiCreatePatternBrush(
352 hPattern
= BITMAP_CopyBitmap(hBitmap
);
353 if (hPattern
== NULL
)
355 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
359 pbrush
= BRUSH_AllocBrushWithHandle();
362 GreDeleteObject(hPattern
);
363 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
366 hBrush
= pbrush
->BaseObject
.hHmgr
;
368 pbrush
->flAttrs
|= GDIBRUSH_IS_BITMAP
;
369 pbrush
->hbmPattern
= hPattern
;
370 /* FIXME: Fill in the rest of fields!!! */
372 GDIOBJ_SetOwnership(hPattern
, NULL
);
374 BRUSH_UnlockBrush(pbrush
);
381 IntGdiCreateSolidBrush(
387 pbrush
= BRUSH_AllocBrushWithHandle();
390 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
393 hBrush
= pbrush
->BaseObject
.hHmgr
;
395 pbrush
->flAttrs
|= GDIBRUSH_IS_SOLID
;
397 pbrush
->BrushAttr
.lbColor
= Color
;
398 /* FIXME: Fill in the rest of fields!!! */
400 BRUSH_UnlockBrush(pbrush
);
407 IntGdiCreateNullBrush(VOID
)
412 pbrush
= BRUSH_AllocBrushWithHandle();
415 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
418 hBrush
= pbrush
->BaseObject
.hHmgr
;
420 pbrush
->flAttrs
|= GDIBRUSH_IS_NULL
;
421 BRUSH_UnlockBrush(pbrush
);
428 IntGdiSetSolidBrushColor(HBRUSH hBrush
, COLORREF Color
)
432 pbrush
= BRUSH_LockBrush(hBrush
);
433 if (pbrush
->flAttrs
& GDIBRUSH_IS_SOLID
)
435 pbrush
->BrushAttr
.lbColor
= Color
& 0xFFFFFF;
437 BRUSH_UnlockBrush(pbrush
);
441 /* PUBLIC FUNCTIONS ***********************************************************/
446 IN PVOID BitmapInfoAndData
,
448 IN UINT BitmapInfoSize
,
453 BITMAPINFO
*SafeBitmapInfoAndData
;
454 NTSTATUS Status
= STATUS_SUCCESS
;
457 SafeBitmapInfoAndData
= EngAllocMem(FL_ZERO_MEMORY
, BitmapInfoSize
, TAG_DIB
);
458 if (SafeBitmapInfoAndData
== NULL
)
460 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
466 ProbeForRead(BitmapInfoAndData
, BitmapInfoSize
, 1);
467 RtlCopyMemory(SafeBitmapInfoAndData
, BitmapInfoAndData
, BitmapInfoSize
);
469 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
471 Status
= _SEH2_GetExceptionCode();
475 if (!NT_SUCCESS(Status
))
477 EngFreeMem(SafeBitmapInfoAndData
);
478 SetLastNtError(Status
);
482 hBrush
= IntGdiCreateDIBBrush(SafeBitmapInfoAndData
,
487 EngFreeMem(SafeBitmapInfoAndData
);
494 NtGdiCreateHatchBrushInternal(
499 return IntGdiCreateHatchBrush(Style
, Color
);
504 NtGdiCreatePatternBrushInternal(
509 return IntGdiCreatePatternBrush(hBitmap
);
514 NtGdiCreateSolidBrush(COLORREF Color
,
515 IN OPTIONAL HBRUSH hbr
)
517 return IntGdiCreateSolidBrush(Color
);
521 * \name NtGdiSetBrushOrg
523 * \brief Sets the brush origin that GDI assigns to
524 * the next brush an application selects into the specified device context.
530 NtGdiSetBrushOrg(HDC hDC
, INT XOrg
, INT YOrg
, LPPOINT Point
)
538 SetLastWin32Error(ERROR_INVALID_HANDLE
);
541 pdcattr
= dc
->pdcattr
;
545 NTSTATUS Status
= STATUS_SUCCESS
;
547 SafePoint
.x
= pdcattr
->ptlBrushOrigin
.x
;
548 SafePoint
.y
= pdcattr
->ptlBrushOrigin
.y
;
551 ProbeForWrite(Point
, sizeof(POINT
), 1);
554 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
556 Status
= _SEH2_GetExceptionCode();
560 if (!NT_SUCCESS(Status
))
563 SetLastNtError(Status
);
568 pdcattr
->ptlBrushOrigin
.x
= XOrg
;
569 pdcattr
->ptlBrushOrigin
.y
= YOrg
;
570 IntptlBrushOrigin(dc
, XOrg
, YOrg
);