mirror of
https://github.com/reactos/reactos.git
synced 2025-08-03 04:26:00 +00:00
[Win32k]
- 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:
parent
a7b546562e
commit
098407e9ce
4 changed files with 171 additions and 104 deletions
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue