mirror of
https://github.com/reactos/reactos.git
synced 2025-08-04 17:05:45 +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.,
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
*/
|
*/
|
||||||
/* $Id$
|
/*
|
||||||
*
|
|
||||||
* PROJECT: ReactOS gdi32.dll
|
* PROJECT: ReactOS gdi32.dll
|
||||||
* FILE: lib/gdi32/misc/misc.c
|
* FILE: dll/win32/gdi32/misc/misc.c
|
||||||
* PURPOSE: Miscellaneous functions
|
* PURPOSE: Miscellaneous functions
|
||||||
* PROGRAMMER: Thomas Weidenmueller <w3seek@reactos.com>
|
* PROGRAMMER: Thomas Weidenmueller <w3seek@reactos.com>
|
||||||
* UPDATE HISTORY:
|
* UPDATE HISTORY:
|
||||||
|
@ -284,10 +283,46 @@ GdiAddGlsBounds(HDC hdc,LPRECT prc)
|
||||||
return NtGdiSetBoundsRect(hdc, prc, 0x8000 | DCB_ACCUMULATE ) ? TRUE : FALSE;
|
return NtGdiSetBoundsRect(hdc, prc, 0x8000 | DCB_ACCUMULATE ) ? TRUE : FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern PGDIHANDLECACHE GdiHandleCache;
|
||||||
|
|
||||||
HGDIOBJ
|
HGDIOBJ
|
||||||
FASTCALL
|
FASTCALL
|
||||||
hGetPEBHandle(HANDLECACHETYPE Type, COLORREF cr)
|
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;
|
PRGN_ATTR pRgn_Attr;
|
||||||
HRGN hrgn;
|
HRGN hrgn;
|
||||||
int x, y;
|
int tmp;
|
||||||
|
|
||||||
//// Remove when Brush/Pen/Rgn Attr is ready!
|
|
||||||
return NtGdiCreateRectRgn(x1,y1,x2,y2);
|
|
||||||
////
|
|
||||||
|
|
||||||
/* Normalize points */
|
/* Normalize points */
|
||||||
x = x1;
|
tmp = x1;
|
||||||
if ( x1 > x2 )
|
if ( x1 > x2 )
|
||||||
{
|
{
|
||||||
x1 = x2;
|
x1 = x2;
|
||||||
x2 = x;
|
x2 = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
y = y1;
|
tmp = y1;
|
||||||
if ( y1 > y2 )
|
if ( y1 > y2 )
|
||||||
{
|
{
|
||||||
y1 = y2;
|
y1 = y2;
|
||||||
y2 = y;
|
y2 = tmp;
|
||||||
}
|
}
|
||||||
|
/* Check outside 24 bit limit for universal set. Chp 9 Areas, pg 560.*/
|
||||||
if ( (UINT)x1 < 0x80000000 ||
|
if ( x1 < -(1<<27) ||
|
||||||
(UINT)y1 < 0x80000000 ||
|
y1 < -(1<<27) ||
|
||||||
(UINT)x2 > 0x7FFFFFFF ||
|
x2 > (1<<27)-1 ||
|
||||||
(UINT)y2 > 0x7FFFFFFF )
|
y2 > (1<<27)-1 )
|
||||||
{
|
{
|
||||||
SetLastError(ERROR_INVALID_PARAMETER);
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// hrgn = hGetPEBHandle(hctRegionHandle, 0);
|
hrgn = hGetPEBHandle(hctRegionHandle, 0);
|
||||||
|
|
||||||
// if (!hrgn)
|
if (!hrgn)
|
||||||
hrgn = NtGdiCreateRectRgn(0, 0, 1, 1);
|
hrgn = NtGdiCreateRectRgn(0, 0, 1, 1);
|
||||||
|
|
||||||
if (!hrgn)
|
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))
|
if (!GdiGetHandleUserData((HGDIOBJ) hrgn, GDI_OBJECT_TYPE_REGION, (PVOID) &pRgn_Attr))
|
||||||
{
|
{
|
||||||
|
DPRINT1("No Attr for Region handle!!!\n");
|
||||||
DeleteRegion(hrgn);
|
DeleteRegion(hrgn);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -778,15 +775,11 @@ OffsetRgn( HRGN hrgn,
|
||||||
nRightRect = nXOffset + nRightRect;
|
nRightRect = nXOffset + nRightRect;
|
||||||
nBottomRect = nYOffset + nBottomRect;
|
nBottomRect = nYOffset + nBottomRect;
|
||||||
|
|
||||||
/* Mask and bit test. */
|
/* Check 28 bit limit. Chp 9 Areas, pg 560. */
|
||||||
if ( ( nLeftRect & 0xF8000000 &&
|
if ( nLeftRect < -(1<<27) ||
|
||||||
(nLeftRect & 0xF8000000) != 0x80000000 ) ||
|
nTopRect < -(1<<27) ||
|
||||||
( nTopRect & 0xF8000000 &&
|
nRightRect > (1<<27)-1 ||
|
||||||
(nTopRect & 0xF8000000) != 0x80000000 ) ||
|
nBottomRect > (1<<27)-1 )
|
||||||
( nRightRect & 0xF8000000 &&
|
|
||||||
(nRightRect & 0xF8000000) != 0x80000000 ) ||
|
|
||||||
( nBottomRect & 0xF8000000 &&
|
|
||||||
(nBottomRect & 0xF8000000) != 0x80000000 ) )
|
|
||||||
{
|
{
|
||||||
return ERROR;
|
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
|
* Delete GDI object
|
||||||
* \param hObject object handle
|
* \param hObject object handle
|
||||||
|
@ -679,8 +742,14 @@ GreDeleteObject(HGDIOBJ hObject)
|
||||||
|
|
||||||
switch (dwObjectType)
|
switch (dwObjectType)
|
||||||
{
|
{
|
||||||
// case GDI_OBJECT_TYPE_BRUSH:
|
case GDI_OBJECT_TYPE_BRUSH:
|
||||||
|
break;
|
||||||
|
|
||||||
case GDI_OBJECT_TYPE_REGION:
|
case GDI_OBJECT_TYPE_REGION:
|
||||||
|
if (bPEBCacheHandle(hObject, hctRegionHandle, pAttr))
|
||||||
|
{
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
if (pAttr) FreeObjectAttr(pAttr);
|
if (pAttr) FreeObjectAttr(pAttr);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -1485,58 +1554,6 @@ GDI_MapHandleTable(PSECTION_OBJECT SectionObject, PEPROCESS Process)
|
||||||
|
|
||||||
/** PUBLIC FUNCTIONS **********************************************************/
|
/** 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
|
BOOL
|
||||||
FASTCALL
|
FASTCALL
|
||||||
IntGdiSetBrushOwner(PBRUSH pbr, DWORD OwnerMask)
|
IntGdiSetBrushOwner(PBRUSH pbr, DWORD OwnerMask)
|
||||||
|
|
|
@ -2034,6 +2034,8 @@ REGION_AllocRgnWithHandle(INT nReg)
|
||||||
{
|
{
|
||||||
HRGN hReg;
|
HRGN hReg;
|
||||||
PROSRGNDATA pReg;
|
PROSRGNDATA pReg;
|
||||||
|
INT Index;
|
||||||
|
PGDI_TABLE_ENTRY Entry;
|
||||||
|
|
||||||
pReg = (PROSRGNDATA)GDIOBJ_AllocObjWithHandle(GDI_OBJECT_TYPE_REGION);
|
pReg = (PROSRGNDATA)GDIOBJ_AllocObjWithHandle(GDI_OBJECT_TYPE_REGION);
|
||||||
if(!pReg)
|
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);
|
EMPTY_REGION(pReg);
|
||||||
pReg->rdh.dwSize = sizeof(RGNDATAHEADER);
|
pReg->rdh.dwSize = sizeof(RGNDATAHEADER);
|
||||||
pReg->rdh.nCount = nReg;
|
pReg->rdh.nCount = nReg;
|
||||||
|
@ -2085,27 +2091,35 @@ RGNOBJAPI_Lock(HRGN hRgn, PRGN_ATTR *ppRgn_Attr)
|
||||||
Entry = &GdiHandleTable->Entries[Index];
|
Entry = &GdiHandleTable->Entries[Index];
|
||||||
|
|
||||||
pRgn_Attr = Entry->UserData;
|
pRgn_Attr = Entry->UserData;
|
||||||
|
|
||||||
if (pRgn_Attr)
|
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:
|
switch (pRgn_Attr->Flags)
|
||||||
EMPTY_REGION( pRgn );
|
{
|
||||||
pRgn_Attr->AttrFlags &= ~ATTR_RGN_DIRTY; // Clear flag in these cases,
|
case NULLREGION:
|
||||||
break;
|
EMPTY_REGION( pRgn );
|
||||||
|
break;
|
||||||
|
|
||||||
case SIMPLEREGION:
|
case SIMPLEREGION:
|
||||||
REGION_SetRectRgn( pRgn,
|
REGION_SetRectRgn( pRgn,
|
||||||
pRgn_Attr->Rect.left,
|
pRgn_Attr->Rect.left,
|
||||||
pRgn_Attr->Rect.top,
|
pRgn_Attr->Rect.top,
|
||||||
pRgn_Attr->Rect.right,
|
pRgn_Attr->Rect.right,
|
||||||
pRgn_Attr->Rect.bottom );
|
pRgn_Attr->Rect.bottom );
|
||||||
pRgn_Attr->AttrFlags &= ~ATTR_RGN_DIRTY; // just incase, force a redraw.
|
break;
|
||||||
break;
|
}
|
||||||
|
pRgn_Attr->AttrFlags &= ~ATTR_RGN_DIRTY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
_SEH2_END;
|
||||||
|
|
||||||
if (ppRgn_Attr)
|
if (ppRgn_Attr)
|
||||||
*ppRgn_Attr = pRgn_Attr;
|
*ppRgn_Attr = pRgn_Attr;
|
||||||
}
|
}
|
||||||
|
@ -2132,17 +2146,25 @@ RGNOBJAPI_Unlock(PROSRGNDATA pRgn)
|
||||||
Entry = &GdiHandleTable->Entries[Index];
|
Entry = &GdiHandleTable->Entries[Index];
|
||||||
|
|
||||||
pRgn_Attr = Entry->UserData;
|
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 );
|
if ( pRgn_Attr->AttrFlags & ATTR_RGN_VALID )
|
||||||
pRgn_Attr->Rect.left = pRgn->rdh.rcBound.left;
|
{
|
||||||
pRgn_Attr->Rect.top = pRgn->rdh.rcBound.top;
|
pRgn_Attr->Flags = REGION_Complexity( pRgn );
|
||||||
pRgn_Attr->Rect.right = pRgn->rdh.rcBound.right;
|
pRgn_Attr->Rect.left = pRgn->rdh.rcBound.left;
|
||||||
pRgn_Attr->Rect.bottom = pRgn->rdh.rcBound.bottom;
|
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);
|
REGION_UnlockRgn(pRgn);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue