mirror of
https://github.com/reactos/reactos.git
synced 2024-08-28 14:18:41 +00:00
465 lines
9.9 KiB
C
465 lines
9.9 KiB
C
/*
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
* PROJECT: ReactOS win32 subsystem
|
|
* PURPOSE: Functions for brushes
|
|
* FILE: subsystem/win32/win32k/objects/brush.c
|
|
* PROGRAMER:
|
|
*/
|
|
|
|
#include <win32k.h>
|
|
|
|
#define NDEBUG
|
|
#include <debug.h>
|
|
|
|
#define GDIOBJATTRFREE 170
|
|
|
|
typedef struct _GDI_OBJ_ATTR_FREELIST
|
|
{
|
|
LIST_ENTRY Entry;
|
|
DWORD nEntries;
|
|
PVOID AttrList[GDIOBJATTRFREE];
|
|
} GDI_OBJ_ATTR_FREELIST, *PGDI_OBJ_ATTR_FREELIST;
|
|
|
|
typedef struct _GDI_OBJ_ATTR_ENTRY
|
|
{
|
|
RGN_ATTR Attr[GDIOBJATTRFREE];
|
|
} GDI_OBJ_ATTR_ENTRY, *PGDI_OBJ_ATTR_ENTRY;
|
|
|
|
BOOL
|
|
FASTCALL
|
|
IntGdiSetBrushOwner(PBRUSH pbr, ULONG ulOwner)
|
|
{
|
|
// FIXME:
|
|
if (pbr->flAttrs & BR_IS_GLOBAL) return TRUE;
|
|
|
|
if ((ulOwner == GDI_OBJ_HMGR_PUBLIC) || ulOwner == GDI_OBJ_HMGR_NONE)
|
|
{
|
|
// Deny user access to User Data.
|
|
GDIOBJ_vSetObjectAttr(&pbr->BaseObject, NULL);
|
|
// FIXME: deallocate brush attr
|
|
}
|
|
|
|
if (ulOwner == GDI_OBJ_HMGR_POWNED)
|
|
{
|
|
// Allow user access to User Data.
|
|
GDIOBJ_vSetObjectAttr(&pbr->BaseObject, pbr->pBrushAttr);
|
|
// FIXME: Allocate brush attr
|
|
}
|
|
|
|
GDIOBJ_vSetObjectOwner(&pbr->BaseObject, ulOwner);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
FASTCALL
|
|
GreSetBrushOwner(HBRUSH hBrush, ULONG ulOwner)
|
|
{
|
|
BOOL Ret;
|
|
PBRUSH pbrush;
|
|
|
|
pbrush = BRUSH_ShareLockBrush(hBrush);
|
|
Ret = IntGdiSetBrushOwner(pbrush, ulOwner);
|
|
BRUSH_ShareUnlockBrush(pbrush);
|
|
return Ret;
|
|
}
|
|
|
|
BOOL
|
|
NTAPI
|
|
BRUSH_bAllocBrushAttr(PBRUSH pbr)
|
|
{
|
|
PPROCESSINFO ppi;
|
|
BRUSH_ATTR *pBrushAttr;
|
|
|
|
ppi = PsGetCurrentProcessWin32Process();
|
|
ASSERT(ppi);
|
|
|
|
pBrushAttr = GdiPoolAllocate(ppi->pPoolDcAttr);
|
|
if (!pBrushAttr)
|
|
{
|
|
DPRINT1("Could not allocate brush attr\n");
|
|
return FALSE;
|
|
}
|
|
|
|
/* Copy the content from the kernel mode dc attr */
|
|
pbr->pBrushAttr = pBrushAttr;
|
|
*pbr->pBrushAttr = pbr->BrushAttr;
|
|
|
|
/* Set the object attribute in the handle table */
|
|
GDIOBJ_vSetObjectAttr(&pbr->BaseObject, pBrushAttr);
|
|
|
|
DPRINT("BRUSH_bAllocBrushAttr: pbr=%p, pbr->pdcattr=%p\n", pbr, pbr->pBrushAttr);
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
VOID
|
|
NTAPI
|
|
BRUSH_vFreeBrushAttr(PBRUSH pbr)
|
|
{
|
|
#if 0
|
|
PPROCESSINFO ppi;
|
|
|
|
if (pbrush->pBrushAttr == &pbrush->BrushAttr) return;
|
|
|
|
/* Reset the object attribute in the handle table */
|
|
GDIOBJ_vSetObjectAttr(&pbr->BaseObject, NULL);
|
|
|
|
/* Free memory from the process gdi pool */
|
|
ppi = PsGetCurrentProcessWin32Process();
|
|
ASSERT(ppi);
|
|
GdiPoolFree(ppi->pPoolBrushAttr, pbr->pBrushAttr);
|
|
#endif
|
|
/* Reset to kmode brush attribute */
|
|
pbr->pBrushAttr = &pbr->BrushAttr;
|
|
}
|
|
|
|
VOID
|
|
NTAPI
|
|
BRUSH_vCleanup(PVOID ObjectBody)
|
|
{
|
|
PBRUSH pbrush = (PBRUSH)ObjectBody;
|
|
if (pbrush->hbmPattern)
|
|
{
|
|
GreSetObjectOwner(pbrush->hbmPattern, GDI_OBJ_HMGR_POWNED);
|
|
GreDeleteObject(pbrush->hbmPattern);
|
|
}
|
|
|
|
/* Check if there is a usermode attribute */
|
|
if (pbrush->pBrushAttr != &pbrush->BrushAttr)
|
|
{
|
|
BRUSH_vFreeBrushAttr(pbrush);
|
|
}
|
|
|
|
/* Free the kmode styles array of EXTPENS */
|
|
if (pbrush->pStyle)
|
|
{
|
|
ExFreePool(pbrush->pStyle);
|
|
}
|
|
}
|
|
|
|
INT
|
|
FASTCALL
|
|
BRUSH_GetObject(PBRUSH pbrush, INT cjSize, LPLOGBRUSH plogbrush)
|
|
{
|
|
/* Check if only size is requested */
|
|
if (plogbrush == NULL) return sizeof(LOGBRUSH);
|
|
|
|
/* Check if size is ok */
|
|
if (cjSize == 0) return 0;
|
|
|
|
/* Set colour */
|
|
plogbrush->lbColor = pbrush->BrushAttr.lbColor;
|
|
|
|
/* Default to 0 */
|
|
plogbrush->lbHatch = 0;
|
|
|
|
/* Get the type of style */
|
|
if (pbrush->flAttrs & BR_IS_SOLID)
|
|
{
|
|
plogbrush->lbStyle = BS_SOLID;
|
|
}
|
|
else if (pbrush->flAttrs & BR_IS_NULL)
|
|
{
|
|
plogbrush->lbStyle = BS_NULL; // BS_HOLLOW
|
|
}
|
|
else if (pbrush->flAttrs & BR_IS_HATCH)
|
|
{
|
|
plogbrush->lbStyle = BS_HATCHED;
|
|
plogbrush->lbHatch = pbrush->ulStyle;
|
|
}
|
|
else if (pbrush->flAttrs & BR_IS_DIB)
|
|
{
|
|
plogbrush->lbStyle = BS_DIBPATTERN;
|
|
plogbrush->lbHatch = (ULONG_PTR)pbrush->hbmClient;
|
|
}
|
|
else if (pbrush->flAttrs & BR_IS_BITMAP)
|
|
{
|
|
plogbrush->lbStyle = BS_PATTERN;
|
|
}
|
|
else
|
|
{
|
|
plogbrush->lbStyle = 0; // ???
|
|
}
|
|
|
|
/* FIXME
|
|
else if (pbrush->flAttrs & )
|
|
{
|
|
plogbrush->lbStyle = BS_INDEXED;
|
|
}
|
|
else if (pbrush->flAttrs & )
|
|
{
|
|
plogbrush->lbStyle = BS_DIBPATTERNPT;
|
|
}
|
|
*/
|
|
|
|
/* FIXME */
|
|
return sizeof(LOGBRUSH);
|
|
}
|
|
|
|
HBRUSH
|
|
APIENTRY
|
|
IntGdiCreateDIBBrush(
|
|
CONST BITMAPINFO *BitmapInfo,
|
|
UINT ColorSpec,
|
|
UINT BitmapInfoSize,
|
|
CONST VOID *PackedDIB)
|
|
{
|
|
HBRUSH hBrush;
|
|
PBRUSH pbrush;
|
|
HBITMAP hPattern;
|
|
ULONG_PTR DataPtr;
|
|
PVOID pvDIBits;
|
|
|
|
if (BitmapInfo->bmiHeader.biSize < sizeof(BITMAPINFOHEADER))
|
|
{
|
|
EngSetLastError(ERROR_INVALID_PARAMETER);
|
|
return NULL;
|
|
}
|
|
|
|
DataPtr = (ULONG_PTR)BitmapInfo + DIB_BitmapInfoSize(BitmapInfo, ColorSpec);
|
|
|
|
hPattern = DIB_CreateDIBSection(NULL, BitmapInfo, ColorSpec, &pvDIBits, NULL, 0, 0);
|
|
if (hPattern == NULL)
|
|
{
|
|
EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
return NULL;
|
|
}
|
|
RtlCopyMemory(pvDIBits,
|
|
(PVOID)DataPtr,
|
|
DIB_GetDIBImageBytes(BitmapInfo->bmiHeader.biWidth,
|
|
BitmapInfo->bmiHeader.biHeight,
|
|
BitmapInfo->bmiHeader.biBitCount * BitmapInfo->bmiHeader.biPlanes));
|
|
|
|
pbrush = BRUSH_AllocBrushWithHandle();
|
|
if (pbrush == NULL)
|
|
{
|
|
GreDeleteObject(hPattern);
|
|
EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
return NULL;
|
|
}
|
|
hBrush = pbrush->BaseObject.hHmgr;
|
|
|
|
pbrush->flAttrs |= BR_IS_BITMAP | BR_IS_DIB;
|
|
pbrush->hbmPattern = hPattern;
|
|
pbrush->hbmClient = (HBITMAP)PackedDIB;
|
|
/* FIXME: Fill in the rest of fields!!! */
|
|
|
|
GreSetObjectOwner(hPattern, GDI_OBJ_HMGR_PUBLIC);
|
|
|
|
GDIOBJ_vUnlockObject(&pbrush->BaseObject);
|
|
|
|
return hBrush;
|
|
}
|
|
|
|
HBRUSH
|
|
APIENTRY
|
|
IntGdiCreateHatchBrush(
|
|
INT Style,
|
|
COLORREF Color)
|
|
{
|
|
HBRUSH hBrush;
|
|
PBRUSH pbrush;
|
|
|
|
if (Style < 0 || Style >= NB_HATCH_STYLES)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
pbrush = BRUSH_AllocBrushWithHandle();
|
|
if (pbrush == NULL)
|
|
{
|
|
EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
return NULL;
|
|
}
|
|
hBrush = pbrush->BaseObject.hHmgr;
|
|
|
|
pbrush->flAttrs |= BR_IS_HATCH;
|
|
pbrush->BrushAttr.lbColor = Color & 0xFFFFFF;
|
|
pbrush->ulStyle = Style;
|
|
|
|
GDIOBJ_vUnlockObject(&pbrush->BaseObject);
|
|
|
|
return hBrush;
|
|
}
|
|
|
|
HBRUSH
|
|
APIENTRY
|
|
IntGdiCreatePatternBrush(
|
|
HBITMAP hBitmap)
|
|
{
|
|
HBRUSH hBrush;
|
|
PBRUSH pbrush;
|
|
HBITMAP hPattern;
|
|
|
|
hPattern = BITMAP_CopyBitmap(hBitmap);
|
|
if (hPattern == NULL)
|
|
{
|
|
EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
return NULL;
|
|
}
|
|
|
|
pbrush = BRUSH_AllocBrushWithHandle();
|
|
if (pbrush == NULL)
|
|
{
|
|
GreDeleteObject(hPattern);
|
|
EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
return NULL;
|
|
}
|
|
hBrush = pbrush->BaseObject.hHmgr;
|
|
|
|
pbrush->flAttrs |= BR_IS_BITMAP;
|
|
pbrush->hbmPattern = hPattern;
|
|
/* FIXME: Fill in the rest of fields!!! */
|
|
|
|
GreSetObjectOwner(hPattern, GDI_OBJ_HMGR_PUBLIC);
|
|
|
|
GDIOBJ_vUnlockObject(&pbrush->BaseObject);
|
|
|
|
return hBrush;
|
|
}
|
|
|
|
HBRUSH
|
|
APIENTRY
|
|
IntGdiCreateSolidBrush(
|
|
COLORREF Color)
|
|
{
|
|
HBRUSH hBrush;
|
|
PBRUSH pbrush;
|
|
|
|
pbrush = BRUSH_AllocBrushWithHandle();
|
|
if (pbrush == NULL)
|
|
{
|
|
EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
return NULL;
|
|
}
|
|
hBrush = pbrush->BaseObject.hHmgr;
|
|
|
|
pbrush->flAttrs |= BR_IS_SOLID;
|
|
|
|
pbrush->BrushAttr.lbColor = Color & 0x00FFFFFF;
|
|
/* FIXME: Fill in the rest of fields!!! */
|
|
|
|
GDIOBJ_vUnlockObject(&pbrush->BaseObject);
|
|
|
|
return hBrush;
|
|
}
|
|
|
|
HBRUSH
|
|
APIENTRY
|
|
IntGdiCreateNullBrush(VOID)
|
|
{
|
|
HBRUSH hBrush;
|
|
PBRUSH pbrush;
|
|
|
|
pbrush = BRUSH_AllocBrushWithHandle();
|
|
if (pbrush == NULL)
|
|
{
|
|
EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
return NULL;
|
|
}
|
|
hBrush = pbrush->BaseObject.hHmgr;
|
|
|
|
pbrush->flAttrs |= BR_IS_NULL;
|
|
GDIOBJ_vUnlockObject(&pbrush->BaseObject);
|
|
|
|
return hBrush;
|
|
}
|
|
|
|
VOID
|
|
FASTCALL
|
|
IntGdiSetSolidBrushColor(HBRUSH hBrush, COLORREF Color)
|
|
{
|
|
PBRUSH pbrush;
|
|
|
|
pbrush = BRUSH_ShareLockBrush(hBrush);
|
|
if (pbrush->flAttrs & BR_IS_SOLID)
|
|
{
|
|
pbrush->BrushAttr.lbColor = Color & 0xFFFFFF;
|
|
}
|
|
BRUSH_ShareUnlockBrush(pbrush);
|
|
}
|
|
|
|
|
|
/* PUBLIC FUNCTIONS ***********************************************************/
|
|
|
|
HBRUSH
|
|
APIENTRY
|
|
NtGdiCreateDIBBrush(
|
|
IN PVOID BitmapInfoAndData,
|
|
IN FLONG ColorSpec,
|
|
IN UINT BitmapInfoSize,
|
|
IN BOOL b8X8,
|
|
IN BOOL bPen,
|
|
IN PVOID PackedDIB)
|
|
{
|
|
BITMAPINFO *SafeBitmapInfoAndData;
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
HBRUSH hBrush;
|
|
|
|
SafeBitmapInfoAndData = EngAllocMem(FL_ZERO_MEMORY, BitmapInfoSize, TAG_DIB);
|
|
if (SafeBitmapInfoAndData == NULL)
|
|
{
|
|
EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
return NULL;
|
|
}
|
|
|
|
_SEH2_TRY
|
|
{
|
|
ProbeForRead(BitmapInfoAndData, BitmapInfoSize, 1);
|
|
RtlCopyMemory(SafeBitmapInfoAndData, BitmapInfoAndData, BitmapInfoSize);
|
|
}
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
Status = _SEH2_GetExceptionCode();
|
|
}
|
|
_SEH2_END;
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
EngFreeMem(SafeBitmapInfoAndData);
|
|
SetLastNtError(Status);
|
|
return 0;
|
|
}
|
|
|
|
hBrush = IntGdiCreateDIBBrush(SafeBitmapInfoAndData,
|
|
ColorSpec,
|
|
BitmapInfoSize,
|
|
PackedDIB);
|
|
|
|
EngFreeMem(SafeBitmapInfoAndData);
|
|
|
|
return hBrush;
|
|
}
|
|
|
|
HBRUSH
|
|
APIENTRY
|
|
NtGdiCreateHatchBrushInternal(
|
|
ULONG Style,
|
|
COLORREF Color,
|
|
BOOL bPen)
|
|
{
|
|
return IntGdiCreateHatchBrush(Style, Color);
|
|
}
|
|
|
|
HBRUSH
|
|
APIENTRY
|
|
NtGdiCreatePatternBrushInternal(
|
|
HBITMAP hBitmap,
|
|
BOOL bPen,
|
|
BOOL b8x8)
|
|
{
|
|
return IntGdiCreatePatternBrush(hBitmap);
|
|
}
|
|
|
|
HBRUSH
|
|
APIENTRY
|
|
NtGdiCreateSolidBrush(COLORREF Color,
|
|
IN OPTIONAL HBRUSH hbr)
|
|
{
|
|
return IntGdiCreateSolidBrush(Color);
|
|
}
|
|
|
|
|
|
/* EOF */
|