-/*
+/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS win32 subsystem
* PURPOSE: Functions for brushes
* FILE: subsystem/win32/win32k/objects/brush.c
- * PROGRAMER:
+ * PROGRAMER:
*/
-#include <w32k.h>
+#include <win32k.h>
#define NDEBUG
#include <debug.h>
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;
-static const USHORT HatchBrushes[NB_HATCH_STYLES][8] =
+static const ULONG HatchBrushes[NB_HATCH_STYLES][8] =
{
{0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF}, /* HS_HORIZONTAL */
{0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7}, /* HS_VERTICAL */
{0x7E, 0xBD, 0xDB, 0xE7, 0xE7, 0xDB, 0xBD, 0x7E} /* HS_DIAGCROSS */
};
-
-PVOID
+BOOL
FASTCALL
-AllocateObjectAttr(VOID)
+IntGdiSetBrushOwner(PBRUSH pbr, ULONG ulOwner)
{
- PTHREADINFO pti;
- PPROCESSINFO ppi;
- PVOID pAttr;
- PGDI_OBJ_ATTR_FREELIST pGdiObjAttrFreeList;
- PGDI_OBJ_ATTR_ENTRY pGdiObjAttrEntry;
- int i;
-
- pti = PsGetCurrentThreadWin32Thread();
- if (pti->pgdiBrushAttr)
- {
- pAttr = pti->pgdiBrushAttr; // Get the free one.
- pti->pgdiBrushAttr = NULL;
- return pAttr;
- }
-
- ppi = PsGetCurrentProcessWin32Process();
-
- if (!ppi->pBrushAttrList) // If set point is null, allocate new group.
- {
- pGdiObjAttrEntry = EngAllocUserMem(sizeof(GDI_OBJ_ATTR_ENTRY), 0);
-
- if (!pGdiObjAttrEntry)
- {
- DPRINT1("Attr Failed User Allocation!\n");
- return NULL;
- }
-
- DPRINT("AllocObjectAttr User 0x%x\n",pGdiObjAttrEntry);
-
- pGdiObjAttrFreeList = ExAllocatePoolWithTag( PagedPool,
- sizeof(GDI_OBJ_ATTR_FREELIST),
- GDITAG_BRUSH_FREELIST);
- if ( !pGdiObjAttrFreeList )
- {
- EngFreeUserMem(pGdiObjAttrEntry);
- return NULL;
- }
-
- RtlZeroMemory(pGdiObjAttrFreeList, sizeof(GDI_OBJ_ATTR_FREELIST));
+ // FIXME:
+ if (pbr->flAttrs & GDIBRUSH_IS_GLOBAL) return TRUE;
- DPRINT("AllocObjectAttr Ex 0x%x\n",pGdiObjAttrFreeList);
+ 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
+ }
- InsertHeadList( &ppi->GDIBrushAttrFreeList, &pGdiObjAttrFreeList->Entry);
+ if (ulOwner == GDI_OBJ_HMGR_POWNED)
+ {
+ // Allow user access to User Data.
+ GDIOBJ_vSetObjectAttr(&pbr->BaseObject, pbr->pBrushAttr);
+ // FIXME: allocate brush attr
+ }
- pGdiObjAttrFreeList->nEntries = GDIOBJATTRFREE;
- // Start at the bottom up and set end of free list point.
- ppi->pBrushAttrList = &pGdiObjAttrEntry->Attr[GDIOBJATTRFREE-1];
- // Build the free attr list.
- for ( i = 0; i < GDIOBJATTRFREE; i++)
- {
- pGdiObjAttrFreeList->AttrList[i] = &pGdiObjAttrEntry->Attr[i];
- }
- }
+ GDIOBJ_vSetObjectOwner(&pbr->BaseObject, ulOwner);
- pAttr = ppi->pBrushAttrList;
- pGdiObjAttrFreeList = (PGDI_OBJ_ATTR_FREELIST)ppi->GDIBrushAttrFreeList.Flink;
+ return TRUE;
+}
- // Free the list when it is full!
- if ( pGdiObjAttrFreeList->nEntries-- == 1)
- { // No more free entries, so yank the list.
- RemoveEntryList( &pGdiObjAttrFreeList->Entry );
+BOOL
+NTAPI
+BRUSH_bAllocBrushAttr(PBRUSH pbr)
+{
+ PPROCESSINFO ppi;
+ BRUSH_ATTR *pBrushAttr;
- ExFreePoolWithTag( pGdiObjAttrFreeList, GDITAG_BRUSH_FREELIST );
+ ppi = PsGetCurrentProcessWin32Process();
+ ASSERT(ppi);
- if ( IsListEmpty( &ppi->GDIBrushAttrFreeList ) )
- {
- ppi->pBrushAttrList = NULL;
- return pAttr;
- }
+ pBrushAttr = GdiPoolAllocate(ppi->pPoolDcAttr);
+ if (!pBrushAttr)
+ {
+ DPRINT1("Could not allocate brush attr\n");
+ return FALSE;
+ }
- pGdiObjAttrFreeList = (PGDI_OBJ_ATTR_FREELIST)ppi->GDIBrushAttrFreeList.Flink;
- }
+ /* Copy the content from the kernel mode dc attr */
+ pbr->pBrushAttr = pBrushAttr;
+ *pbr->pBrushAttr = pbr->BrushAttr;
- ppi->pBrushAttrList = pGdiObjAttrFreeList->AttrList[pGdiObjAttrFreeList->nEntries-1];
+ /* Set the object attribute in the handle table */
+ GDIOBJ_vSetObjectAttr(&pbr->BaseObject, pBrushAttr);
- return pAttr;
+ DPRINT("BRUSH_bAllocBrushAttr: pbr=%p, pbr->pdcattr=%p\n", pbr, pbr->pBrushAttr);
+ return TRUE;
}
+
VOID
-FASTCALL
-FreeObjectAttr(PVOID pAttr)
+NTAPI
+BRUSH_vFreeBrushAttr(PBRUSH pbr)
{
- PTHREADINFO pti;
- PPROCESSINFO ppi;
- PGDI_OBJ_ATTR_FREELIST pGdiObjAttrFreeList;
-
- pti = PsGetCurrentThreadWin32Thread();
-
- if (!pti) return;
-
- if (!pti->pgdiBrushAttr)
- { // If it is null, just cache it for the next time.
- pti->pgdiBrushAttr = pAttr;
- return;
- }
-
- ppi = PsGetCurrentProcessWin32Process();
-
- pGdiObjAttrFreeList = (PGDI_OBJ_ATTR_FREELIST)ppi->GDIBrushAttrFreeList.Flink;
-
- // We add to the list of free entries, so this will grows!
- if ( IsListEmpty(&ppi->GDIBrushAttrFreeList) ||
- pGdiObjAttrFreeList->nEntries == GDIOBJATTRFREE )
- {
- pGdiObjAttrFreeList = ExAllocatePoolWithTag( PagedPool,
- sizeof(GDI_OBJ_ATTR_FREELIST),
- GDITAG_BRUSH_FREELIST);
- if ( !pGdiObjAttrFreeList )
- {
- return;
- }
- InsertHeadList( &ppi->GDIBrushAttrFreeList, &pGdiObjAttrFreeList->Entry);
- pGdiObjAttrFreeList->nEntries = 0;
- }
- // Up count, save the entry and set end of free list point.
- ++pGdiObjAttrFreeList->nEntries; // Top Down...
- pGdiObjAttrFreeList->AttrList[pGdiObjAttrFreeList->nEntries-1] = pAttr;
- ppi->pBrushAttrList = pAttr;
-
- return;
-}
+#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;
+}
BOOL
INTERNAL_CALL
if (pbrush->flAttrs & (GDIBRUSH_IS_HATCH | GDIBRUSH_IS_BITMAP))
{
ASSERT(pbrush->hbmPattern);
- GDIOBJ_SetOwnership(pbrush->hbmPattern, PsGetCurrentProcess());
+ 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)
{
return sizeof(LOGBRUSH);
}
-/**
- * @name CalculateColorTableSize
- *
- * Internal routine to calculate the number of color table entries.
- *
- * @param BitmapInfoHeader
- * Input bitmap information header, can be any version of
- * BITMAPINFOHEADER or BITMAPCOREHEADER.
- *
- * @param ColorSpec
- * Pointer to variable which specifiing the color mode (DIB_RGB_COLORS
- * or DIB_RGB_COLORS). On successful return this value is normalized
- * according to the bitmap info.
- *
- * @param ColorTableSize
- * On successful return this variable is filled with number of
- * entries in color table for the image with specified parameters.
- *
- * @return
- * TRUE if the input values together form a valid image, FALSE otherwise.
- */
-BOOL
-APIENTRY
-CalculateColorTableSize(
- CONST BITMAPINFOHEADER *BitmapInfoHeader,
- UINT *ColorSpec,
- UINT *ColorTableSize)
-{
- WORD BitCount;
- DWORD ClrUsed;
- DWORD Compression;
-
- /*
- * At first get some basic parameters from the passed BitmapInfoHeader
- * structure. It can have one of the following formats:
- * - BITMAPCOREHEADER (the oldest one with totally different layout
- * from the others)
- * - BITMAPINFOHEADER (the standard and most common header)
- * - BITMAPV4HEADER (extension of BITMAPINFOHEADER)
- * - BITMAPV5HEADER (extension of BITMAPV4HEADER)
- */
- if (BitmapInfoHeader->biSize == sizeof(BITMAPCOREHEADER))
- {
- BitCount = ((LPBITMAPCOREHEADER)BitmapInfoHeader)->bcBitCount;
- ClrUsed = 0;
- Compression = BI_RGB;
- }
- else
- {
- BitCount = BitmapInfoHeader->biBitCount;
- ClrUsed = BitmapInfoHeader->biClrUsed;
- Compression = BitmapInfoHeader->biCompression;
- }
-
- switch (Compression)
- {
- case BI_BITFIELDS:
- if (*ColorSpec == DIB_PAL_COLORS)
- *ColorSpec = DIB_RGB_COLORS;
-
- if (BitCount != 16 && BitCount != 32)
- return FALSE;
-
- /* For BITMAPV4HEADER/BITMAPV5HEADER the masks are included in
- * the structure itself (bV4RedMask, bV4GreenMask, and bV4BlueMask).
- * For BITMAPINFOHEADER the color masks are stored in the palette. */
- if (BitmapInfoHeader->biSize > sizeof(BITMAPINFOHEADER))
- *ColorTableSize = 0;
- else
- *ColorTableSize = 3;
-
- return TRUE;
-
- case BI_RGB:
- switch (BitCount)
- {
- case 1:
- *ColorTableSize = ClrUsed ? min(ClrUsed, 2) : 2;
- return TRUE;
-
- case 4:
- *ColorTableSize = ClrUsed ? min(ClrUsed, 16) : 16;
- return TRUE;
-
- case 8:
- *ColorTableSize = ClrUsed ? min(ClrUsed, 256) : 256;
- return TRUE;
-
- default:
- if (*ColorSpec == DIB_PAL_COLORS)
- *ColorSpec = DIB_RGB_COLORS;
- if (BitCount != 16 && BitCount != 24 && BitCount != 32)
- return FALSE;
- *ColorTableSize = ClrUsed;
- return TRUE;
- }
-
- case BI_RLE4:
- if (BitCount == 4)
- {
- *ColorTableSize = ClrUsed ? min(ClrUsed, 16) : 16;
- return TRUE;
- }
- return FALSE;
-
- case BI_RLE8:
- if (BitCount == 8)
- {
- *ColorTableSize = ClrUsed ? min(ClrUsed, 256) : 256;
- return TRUE;
- }
- return FALSE;
-
- case BI_JPEG:
- case BI_PNG:
- *ColorTableSize = ClrUsed;
- return TRUE;
-
- default:
- return FALSE;
- }
-}
-
HBRUSH
APIENTRY
IntGdiCreateDIBBrush(
PBRUSH pbrush;
HBITMAP hPattern;
ULONG_PTR DataPtr;
- UINT PaletteEntryCount;
- PSURFACE psurfPattern;
- INT PaletteType;
+ PVOID pvDIBits;
if (BitmapInfo->bmiHeader.biSize < sizeof(BITMAPINFOHEADER))
{
- SetLastWin32Error(ERROR_INVALID_PARAMETER);
+ EngSetLastError(ERROR_INVALID_PARAMETER);
return NULL;
}
- if (!CalculateColorTableSize(&BitmapInfo->bmiHeader,
- &ColorSpec,
- &PaletteEntryCount))
- {
- SetLastWin32Error(ERROR_INVALID_PARAMETER);
- return NULL;
- }
+ DataPtr = (ULONG_PTR)BitmapInfo + DIB_BitmapInfoSize(BitmapInfo, ColorSpec);
- // FIXME: What about BI_BITFIELDS
- DataPtr = (ULONG_PTR)BitmapInfo + BitmapInfo->bmiHeader.biSize;
- if (ColorSpec == DIB_RGB_COLORS)
- DataPtr += PaletteEntryCount * sizeof(RGBQUAD);
- else
- DataPtr += PaletteEntryCount * sizeof(USHORT);
-
- hPattern = IntGdiCreateBitmap(BitmapInfo->bmiHeader.biWidth,
- BitmapInfo->bmiHeader.biHeight,
- BitmapInfo->bmiHeader.biPlanes,
- BitmapInfo->bmiHeader.biBitCount,
- (PVOID)DataPtr);
+ hPattern = DIB_CreateDIBSection(NULL, BitmapInfo, ColorSpec, &pvDIBits, NULL, 0, 0);
if (hPattern == NULL)
{
- SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+ EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
return NULL;
}
-
- psurfPattern = SURFACE_LockSurface(hPattern);
- ASSERT(psurfPattern != NULL);
- psurfPattern->hDIBPalette = BuildDIBPalette(BitmapInfo, &PaletteType);
- SURFACE_UnlockSurface(psurfPattern);
+ 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);
- SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+ EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
return NULL;
}
hBrush = pbrush->BaseObject.hHmgr;
pbrush->hbmPattern = hPattern;
/* FIXME: Fill in the rest of fields!!! */
- GDIOBJ_SetOwnership(hPattern, NULL);
+ GreSetObjectOwner(hPattern, GDI_OBJ_HMGR_PUBLIC);
- BRUSH_UnlockBrush(pbrush);
+ GDIOBJ_vUnlockObject(&pbrush->BaseObject);
return hBrush;
}
return 0;
}
- hPattern = IntGdiCreateBitmap(8, 8, 1, 1, (LPBYTE)HatchBrushes[Style]);
+ hPattern = GreCreateBitmap(8, 8, 1, 1, (LPBYTE)HatchBrushes[Style]);
if (hPattern == NULL)
{
- SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+ EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
return NULL;
}
if (pbrush == NULL)
{
GreDeleteObject(hPattern);
- SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+ EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
return NULL;
}
hBrush = pbrush->BaseObject.hHmgr;
pbrush->hbmPattern = hPattern;
pbrush->BrushAttr.lbColor = Color & 0xFFFFFF;
- GDIOBJ_SetOwnership(hPattern, NULL);
+ GreSetObjectOwner(hPattern, GDI_OBJ_HMGR_PUBLIC);
- BRUSH_UnlockBrush(pbrush);
+ GDIOBJ_vUnlockObject(&pbrush->BaseObject);
return hBrush;
}
hPattern = BITMAP_CopyBitmap(hBitmap);
if (hPattern == NULL)
{
- SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+ EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
return NULL;
}
if (pbrush == NULL)
{
GreDeleteObject(hPattern);
- SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+ EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
return NULL;
}
hBrush = pbrush->BaseObject.hHmgr;
pbrush->hbmPattern = hPattern;
/* FIXME: Fill in the rest of fields!!! */
- GDIOBJ_SetOwnership(hPattern, NULL);
+ GreSetObjectOwner(hPattern, GDI_OBJ_HMGR_PUBLIC);
- BRUSH_UnlockBrush(pbrush);
+ GDIOBJ_vUnlockObject(&pbrush->BaseObject);
return hBrush;
}
pbrush = BRUSH_AllocBrushWithHandle();
if (pbrush == NULL)
{
- SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+ EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
return NULL;
}
hBrush = pbrush->BaseObject.hHmgr;
pbrush->flAttrs |= GDIBRUSH_IS_SOLID;
- pbrush->BrushAttr.lbColor = Color;
+ pbrush->BrushAttr.lbColor = Color & 0x00FFFFFF;
/* FIXME: Fill in the rest of fields!!! */
- BRUSH_UnlockBrush(pbrush);
+ GDIOBJ_vUnlockObject(&pbrush->BaseObject);
return hBrush;
}
pbrush = BRUSH_AllocBrushWithHandle();
if (pbrush == NULL)
{
- SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+ EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
return NULL;
}
hBrush = pbrush->BaseObject.hHmgr;
pbrush->flAttrs |= GDIBRUSH_IS_NULL;
- BRUSH_UnlockBrush(pbrush);
+ GDIOBJ_vUnlockObject(&pbrush->BaseObject);
return hBrush;
}
{
PBRUSH pbrush;
- pbrush = BRUSH_LockBrush(hBrush);
+ pbrush = BRUSH_ShareLockBrush(hBrush);
if (pbrush->flAttrs & GDIBRUSH_IS_SOLID)
{
pbrush->BrushAttr.lbColor = Color & 0xFFFFFF;
}
- BRUSH_UnlockBrush(pbrush);
+ BRUSH_ShareUnlockBrush(pbrush);
}
SafeBitmapInfoAndData = EngAllocMem(FL_ZERO_MEMORY, BitmapInfoSize, TAG_DIB);
if (SafeBitmapInfoAndData == NULL)
{
- SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+ EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
return NULL;
}
dc = DC_LockDc(hDC);
if (dc == NULL)
{
- SetLastWin32Error(ERROR_INVALID_HANDLE);
+ EngSetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
pdcattr = dc->pdcattr;
pdcattr->ptlBrushOrigin.x = XOrg;
pdcattr->ptlBrushOrigin.y = YOrg;
+ IntptlBrushOrigin(dc, XOrg, YOrg );
DC_UnlockDc(dc);
return TRUE;