- Plugged in region attribute support and added the PEB cache for it as well.

[Gdi32]
- Using CreateRectRgn only with attribute and PEB cache support.

[Testing]
- Wine tests: gdi32; clipping and dc. gdiplus; region. user32; dce. Same results.
- Applications, AbiWord 2.6.8, FF 3.5, miranda 0.7.19 unicode, putty, SeaMonkey 2.0, WinMerge 2.12.4 and winamp 2.95 rc std. Same results.

svn path=/trunk/; revision=44817
This commit is contained in:
James Tabor 2009-12-30 22:56:09 +00:00
parent a7b546562e
commit 098407e9ce
4 changed files with 171 additions and 104 deletions

View file

@ -16,10 +16,9 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/* $Id$
*
/*
* PROJECT: ReactOS gdi32.dll
* FILE: lib/gdi32/misc/misc.c
* FILE: dll/win32/gdi32/misc/misc.c
* PURPOSE: Miscellaneous functions
* PROGRAMMER: Thomas Weidenmueller <w3seek@reactos.com>
* UPDATE HISTORY:
@ -284,10 +283,46 @@ GdiAddGlsBounds(HDC hdc,LPRECT prc)
return NtGdiSetBoundsRect(hdc, prc, 0x8000 | DCB_ACCUMULATE ) ? TRUE : FALSE;
}
extern PGDIHANDLECACHE GdiHandleCache;
HGDIOBJ
FASTCALL
hGetPEBHandle(HANDLECACHETYPE Type, COLORREF cr)
{
return NULL;
int Number;
HANDLE Lock;
HGDIOBJ Handle = NULL;
Lock = InterlockedCompareExchangePointer( (PVOID*)&GdiHandleCache->ulLock,
NtCurrentTeb(),
NULL );
if (Lock) return Handle;
Number = GdiHandleCache->ulNumHandles[Type];
if ( Number && Number <= CACHE_REGION_ENTRIES )
{
if ( Type == hctRegionHandle)
{
PRGN_ATTR pRgn_Attr;
HGDIOBJ *hPtr;
hPtr = GdiHandleCache->Handle + CACHE_BRUSH_ENTRIES+CACHE_PEN_ENTRIES;
Handle = hPtr[Number - 1];
if (GdiGetHandleUserData( Handle, GDI_OBJECT_TYPE_REGION, (PVOID) &pRgn_Attr))
{
if (pRgn_Attr->AttrFlags & ATTR_CACHED)
{
DPRINT("Get Handle! Count %d\n", GdiHandleCache->ulNumHandles[Type]);
pRgn_Attr->AttrFlags &= ~ATTR_CACHED;
hPtr[Number - 1] = NULL;
GdiHandleCache->ulNumHandles[Type]--;
}
}
}
}
(void)InterlockedExchangePointer((PVOID*)&GdiHandleCache->ulLock, Lock);
return Handle;
}

View file

@ -438,39 +438,35 @@ CreateRectRgn(int x1, int y1, int x2, int y2)
{
PRGN_ATTR pRgn_Attr;
HRGN hrgn;
int x, y;
//// Remove when Brush/Pen/Rgn Attr is ready!
return NtGdiCreateRectRgn(x1,y1,x2,y2);
////
int tmp;
/* Normalize points */
x = x1;
tmp = x1;
if ( x1 > x2 )
{
x1 = x2;
x2 = x;
x2 = tmp;
}
y = y1;
tmp = y1;
if ( y1 > y2 )
{
y1 = y2;
y2 = y;
y2 = tmp;
}
if ( (UINT)x1 < 0x80000000 ||
(UINT)y1 < 0x80000000 ||
(UINT)x2 > 0x7FFFFFFF ||
(UINT)y2 > 0x7FFFFFFF )
/* Check outside 24 bit limit for universal set. Chp 9 Areas, pg 560.*/
if ( x1 < -(1<<27) ||
y1 < -(1<<27) ||
x2 > (1<<27)-1 ||
y2 > (1<<27)-1 )
{
SetLastError(ERROR_INVALID_PARAMETER);
return NULL;
}
// hrgn = hGetPEBHandle(hctRegionHandle, 0);
hrgn = hGetPEBHandle(hctRegionHandle, 0);
// if (!hrgn)
if (!hrgn)
hrgn = NtGdiCreateRectRgn(0, 0, 1, 1);
if (!hrgn)
@ -478,6 +474,7 @@ CreateRectRgn(int x1, int y1, int x2, int y2)
if (!GdiGetHandleUserData((HGDIOBJ) hrgn, GDI_OBJECT_TYPE_REGION, (PVOID) &pRgn_Attr))
{
DPRINT1("No Attr for Region handle!!!\n");
DeleteRegion(hrgn);
return NULL;
}
@ -778,15 +775,11 @@ OffsetRgn( HRGN hrgn,
nRightRect = nXOffset + nRightRect;
nBottomRect = nYOffset + nBottomRect;
/* Mask and bit test. */
if ( ( nLeftRect & 0xF8000000 &&
(nLeftRect & 0xF8000000) != 0x80000000 ) ||
( nTopRect & 0xF8000000 &&
(nTopRect & 0xF8000000) != 0x80000000 ) ||
( nRightRect & 0xF8000000 &&
(nRightRect & 0xF8000000) != 0x80000000 ) ||
( nBottomRect & 0xF8000000 &&
(nBottomRect & 0xF8000000) != 0x80000000 ) )
/* Check 28 bit limit. Chp 9 Areas, pg 560. */
if ( nLeftRect < -(1<<27) ||
nTopRect < -(1<<27) ||
nRightRect > (1<<27)-1 ||
nBottomRect > (1<<27)-1 )
{
return ERROR;
}

View file

@ -654,6 +654,69 @@ IsObjectDead(HGDIOBJ hObject)
}
BOOL
FASTCALL
bPEBCacheHandle(HGDIOBJ Handle, int oType, PVOID pAttr)
{
PGDIHANDLECACHE GdiHandleCache;
HGDIOBJ *hPtr;
BOOL Ret = FALSE;
int Offset = 0, Number;
HANDLE Lock;
GdiHandleCache = (PGDIHANDLECACHE)NtCurrentTeb()->ProcessEnvironmentBlock->GdiHandleBuffer;
switch (oType)
{
case hctBrushHandle:
Offset = 0;
break;
case hctPenHandle:
Offset = CACHE_BRUSH_ENTRIES;
break;
case hctRegionHandle:
Offset = CACHE_BRUSH_ENTRIES+CACHE_PEN_ENTRIES;
break;
default:
return FALSE;
}
Lock = InterlockedCompareExchangePointer( (PVOID*)&GdiHandleCache->ulLock,
NtCurrentTeb(),
NULL );
if (Lock) return FALSE;
_SEH2_TRY
{
Number = GdiHandleCache->ulNumHandles[oType];
hPtr = GdiHandleCache->Handle + Offset;
if ( oType == hctRegionHandle)
{
if ( Number < CACHE_REGION_ENTRIES )
{
((PRGN_ATTR)pAttr)->AttrFlags |= ATTR_CACHED;
hPtr[Number] = Handle;
GdiHandleCache->ulNumHandles[oType]++;
DPRINT("Put Handle Count %d\n", GdiHandleCache->ulNumHandles[oType]);
Ret = TRUE;
}
}
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
Ret = FALSE;
}
_SEH2_END;
(void)InterlockedExchangePointer((PVOID*)&GdiHandleCache->ulLock, Lock);
return Ret;
}
/*!
* Delete GDI object
* \param hObject object handle
@ -676,11 +739,17 @@ GreDeleteObject(HGDIOBJ hObject)
Index = GDI_HANDLE_GET_INDEX(hObject);
Entry = &GdiHandleTable->Entries[Index];
pAttr = Entry->UserData;
switch (dwObjectType)
{
// case GDI_OBJECT_TYPE_BRUSH:
case GDI_OBJECT_TYPE_BRUSH:
break;
case GDI_OBJECT_TYPE_REGION:
if (bPEBCacheHandle(hObject, hctRegionHandle, pAttr))
{
return TRUE;
}
if (pAttr) FreeObjectAttr(pAttr);
break;
@ -1485,58 +1554,6 @@ GDI_MapHandleTable(PSECTION_OBJECT SectionObject, PEPROCESS Process)
/** PUBLIC FUNCTIONS **********************************************************/
/*
Since Brush/Pen and Region objects are sharable,,, we can just use
UserHeapAlloc to allocate the small attribute objects.
Example Allocating:
// Save Kernel Space Pointer
(PBRUSH)->pBrushAttr = IntGdiAllocObjAttr(GDIObjType_BRUSH_TYPE);
// Kernel Space to User Space Pointer
(PGDI_TABLE_ENTRY)->UserData = pBrushAttr;
// Gdi will adjust for heap delta.
Example Freeing:
(PGDI_TABLE_ENTRY)->UserData = NULL; // Zero the user ptr.
UserHeapFree((PBRUSH)->pBrushAttr); // Free from kernel ptr.
(PBRUSH)->pBrushAttr = NULL;
Notes:
Testing with DC_ATTR works but has drawing difficulties.
Base on observation, (Over looking the obvious) we need to supply heap delta
to user space gdi. Now, with testing, looks all normal.
*/
PVOID
FASTCALL
IntGdiAllocObjAttr(GDIOBJTYPE Type)
{
PVOID pMemAttr = NULL;
switch( Type )
{
case GDIObjType_DC_TYPE:
pMemAttr = UserHeapAlloc(sizeof(DC_ATTR));
if (pMemAttr) RtlZeroMemory(pMemAttr, sizeof(DC_ATTR));
break;
case GDIObjType_RGN_TYPE:
pMemAttr = UserHeapAlloc(sizeof(RGN_ATTR));
if (pMemAttr) RtlZeroMemory(pMemAttr, sizeof(RGN_ATTR));
break;
case GDIObjType_BRUSH_TYPE:
pMemAttr = UserHeapAlloc(sizeof(BRUSH_ATTR));
if (pMemAttr) RtlZeroMemory(pMemAttr, sizeof(BRUSH_ATTR));
break;
default:
break;
}
return pMemAttr;
}
BOOL
FASTCALL
IntGdiSetBrushOwner(PBRUSH pbr, DWORD OwnerMask)

View file

@ -2034,6 +2034,8 @@ REGION_AllocRgnWithHandle(INT nReg)
{
HRGN hReg;
PROSRGNDATA pReg;
INT Index;
PGDI_TABLE_ENTRY Entry;
pReg = (PROSRGNDATA)GDIOBJ_AllocObjWithHandle(GDI_OBJECT_TYPE_REGION);
if(!pReg)
@ -2060,6 +2062,10 @@ REGION_AllocRgnWithHandle(INT nReg)
}
}
Index = GDI_HANDLE_GET_INDEX(hReg);
Entry = &GdiHandleTable->Entries[Index];
Entry->UserData = AllocateObjectAttr();
EMPTY_REGION(pReg);
pReg->rdh.dwSize = sizeof(RGNDATAHEADER);
pReg->rdh.nCount = nReg;
@ -2085,27 +2091,35 @@ RGNOBJAPI_Lock(HRGN hRgn, PRGN_ATTR *ppRgn_Attr)
Entry = &GdiHandleTable->Entries[Index];
pRgn_Attr = Entry->UserData;
if (pRgn_Attr)
{
if ( pRgn_Attr->AttrFlags & (ATTR_RGN_VALID|ATTR_RGN_DIRTY) )
_SEH2_TRY
{
switch (pRgn_Attr->Flags)
if ( pRgn_Attr->AttrFlags & (ATTR_RGN_VALID|ATTR_RGN_DIRTY) )
{
case NULLREGION:
EMPTY_REGION( pRgn );
pRgn_Attr->AttrFlags &= ~ATTR_RGN_DIRTY; // Clear flag in these cases,
break;
switch (pRgn_Attr->Flags)
{
case NULLREGION:
EMPTY_REGION( pRgn );
break;
case SIMPLEREGION:
REGION_SetRectRgn( pRgn,
pRgn_Attr->Rect.left,
pRgn_Attr->Rect.top,
pRgn_Attr->Rect.right,
pRgn_Attr->Rect.bottom );
pRgn_Attr->AttrFlags &= ~ATTR_RGN_DIRTY; // just incase, force a redraw.
break;
case SIMPLEREGION:
REGION_SetRectRgn( pRgn,
pRgn_Attr->Rect.left,
pRgn_Attr->Rect.top,
pRgn_Attr->Rect.right,
pRgn_Attr->Rect.bottom );
break;
}
pRgn_Attr->AttrFlags &= ~ATTR_RGN_DIRTY;
}
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
}
_SEH2_END;
if (ppRgn_Attr)
*ppRgn_Attr = pRgn_Attr;
}
@ -2132,17 +2146,25 @@ RGNOBJAPI_Unlock(PROSRGNDATA pRgn)
Entry = &GdiHandleTable->Entries[Index];
pRgn_Attr = Entry->UserData;
if ( pRgn_Attr )
_SEH2_TRY
{
if ( pRgn_Attr->AttrFlags & ATTR_RGN_VALID )
if ( pRgn_Attr )
{
pRgn_Attr->Flags = REGION_Complexity( pRgn );
pRgn_Attr->Rect.left = pRgn->rdh.rcBound.left;
pRgn_Attr->Rect.top = pRgn->rdh.rcBound.top;
pRgn_Attr->Rect.right = pRgn->rdh.rcBound.right;
pRgn_Attr->Rect.bottom = pRgn->rdh.rcBound.bottom;
if ( pRgn_Attr->AttrFlags & ATTR_RGN_VALID )
{
pRgn_Attr->Flags = REGION_Complexity( pRgn );
pRgn_Attr->Rect.left = pRgn->rdh.rcBound.left;
pRgn_Attr->Rect.top = pRgn->rdh.rcBound.top;
pRgn_Attr->Rect.right = pRgn->rdh.rcBound.right;
pRgn_Attr->Rect.bottom = pRgn->rdh.rcBound.bottom;
}
}
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
}
_SEH2_END;
}
REGION_UnlockRgn(pRgn);
}