mirror of
https://github.com/reactos/reactos.git
synced 2025-03-10 18:24:02 +00:00
1056 lines
26 KiB
C
1056 lines
26 KiB
C
#include "precomp.h"
|
|
|
|
#define NDEBUG
|
|
#include <debug.h>
|
|
|
|
#define INRECT(r, x, y) \
|
|
( ( ((r).right > x)) && \
|
|
( ((r).left <= x)) && \
|
|
( ((r).bottom > y)) && \
|
|
( ((r).top <= y)) )
|
|
|
|
#define OVERLAPPING_RGN 0
|
|
#define INVERTED_RGN 1
|
|
#define SAME_RGN 2
|
|
#define DIFF_RGN 3
|
|
/*
|
|
From tests, there are four results based on normalized coordinates.
|
|
If the rects are overlapping and normalized, it's OVERLAPPING_RGN.
|
|
If the rects are overlapping in anyway or same in dimension and one is inverted,
|
|
it's INVERTED_RGN.
|
|
If the rects are same in dimension or NULL, it's SAME_RGN.
|
|
If the rects are overlapping and not normalized or displace in different areas,
|
|
it's DIFF_RGN.
|
|
*/
|
|
INT
|
|
FASTCALL
|
|
ComplexityFromRects( PRECTL prc1, PRECTL prc2)
|
|
{
|
|
if ( prc2->left >= prc1->left )
|
|
{
|
|
if ( ( prc1->right >= prc2->right) &&
|
|
( prc1->top <= prc2->top ) &&
|
|
( prc1->bottom >= prc2->bottom ) )
|
|
return SAME_RGN;
|
|
|
|
if ( prc2->left > prc1->left )
|
|
{
|
|
if ( ( prc1->left >= prc2->right ) ||
|
|
( prc1->right <= prc2->left ) ||
|
|
( prc1->top >= prc2->bottom ) ||
|
|
( prc1->bottom <= prc2->top ) )
|
|
return DIFF_RGN;
|
|
}
|
|
}
|
|
|
|
if ( ( prc2->right < prc1->right ) ||
|
|
( prc2->top > prc1->top ) ||
|
|
( prc2->bottom < prc1->bottom ) )
|
|
{
|
|
if ( ( prc1->left >= prc2->right ) ||
|
|
( prc1->right <= prc2->left ) ||
|
|
( prc1->top >= prc2->bottom ) ||
|
|
( prc1->bottom <= prc2->top ) )
|
|
return DIFF_RGN;
|
|
}
|
|
else
|
|
{
|
|
return INVERTED_RGN;
|
|
}
|
|
return OVERLAPPING_RGN;
|
|
}
|
|
|
|
static
|
|
VOID
|
|
FASTCALL
|
|
SortRects(PRECT pRect, INT nCount)
|
|
{
|
|
INT i = 0, a = 0, b = 0, c, s;
|
|
RECT sRect;
|
|
|
|
if (nCount > 0)
|
|
{
|
|
i = 1; // set index point
|
|
c = nCount; // set inverse count
|
|
do
|
|
{
|
|
s = i; // set sort count
|
|
if ( i < nCount )
|
|
{
|
|
a = i - 1;
|
|
b = i;
|
|
do
|
|
{
|
|
if(pRect[b].top != pRect[i].bottom) break;
|
|
if(pRect[b].left < pRect[a].left)
|
|
{
|
|
sRect = pRect[a];
|
|
pRect[a] = pRect[b];
|
|
pRect[b] = sRect;
|
|
}
|
|
++s;
|
|
++b;
|
|
} while ( s < nCount );
|
|
}
|
|
++i;
|
|
} while ( c-- != 1 );
|
|
}
|
|
}
|
|
|
|
/*
|
|
* I thought it was okay to have this in DeleteObject but~ Speed. (jt)
|
|
*/
|
|
BOOL
|
|
FASTCALL
|
|
DeleteRegion( HRGN hRgn )
|
|
{
|
|
#if 0
|
|
PRGN_ATTR Rgn_Attr;
|
|
|
|
if ((GdiGetHandleUserData((HGDIOBJ) hRgn, GDI_OBJECT_TYPE_REGION, (PVOID) &Rgn_Attr)) &&
|
|
( Rgn_Attr != NULL ))
|
|
{
|
|
PGDIBSOBJECT pgO;
|
|
|
|
pgO = GdiAllocBatchCommand(NULL, GdiBCDelRgn);
|
|
if (pgO)
|
|
{
|
|
pgO->hgdiobj = (HGDIOBJ)hRgn;
|
|
return TRUE;
|
|
}
|
|
}
|
|
#endif
|
|
return NtGdiDeleteObjectApp((HGDIOBJ) hRgn);
|
|
}
|
|
|
|
INT
|
|
FASTCALL
|
|
MirrorRgnByWidth(HRGN hRgn, INT Width, HRGN *phRgn)
|
|
{
|
|
INT cRgnDSize, Ret = 0;
|
|
PRGNDATA pRgnData;
|
|
|
|
cRgnDSize = NtGdiGetRegionData(hRgn, 0, NULL);
|
|
|
|
if (cRgnDSize)
|
|
{
|
|
pRgnData = LocalAlloc(LMEM_FIXED, cRgnDSize * sizeof(LONG));
|
|
if (pRgnData)
|
|
{
|
|
if ( GetRegionData(hRgn, cRgnDSize, pRgnData) )
|
|
{
|
|
HRGN hRgnex;
|
|
UINT i;
|
|
INT SaveL = pRgnData->rdh.rcBound.left;
|
|
pRgnData->rdh.rcBound.left = Width - pRgnData->rdh.rcBound.right;
|
|
pRgnData->rdh.rcBound.right = Width - SaveL;
|
|
if (pRgnData->rdh.nCount > 0)
|
|
{
|
|
PRECT pRect = (PRECT)&pRgnData->Buffer;
|
|
for (i = 0; i < pRgnData->rdh.nCount; i++)
|
|
{
|
|
SaveL = pRect[i].left;
|
|
pRect[i].left = Width - pRect[i].right;
|
|
pRect[i].right = Width - SaveL;
|
|
}
|
|
}
|
|
SortRects((PRECT)&pRgnData->Buffer, pRgnData->rdh.nCount);
|
|
hRgnex = ExtCreateRegion(NULL, cRgnDSize , pRgnData);
|
|
if (hRgnex)
|
|
{
|
|
if (phRgn) phRgn = (HRGN *)hRgnex;
|
|
else
|
|
{
|
|
CombineRgn(hRgn, hRgnex, 0, RGN_COPY);
|
|
DeleteObject(hRgnex);
|
|
}
|
|
Ret = 1;
|
|
}
|
|
}
|
|
LocalFree(pRgnData);
|
|
}
|
|
}
|
|
return Ret;
|
|
}
|
|
|
|
INT
|
|
WINAPI
|
|
MirrorRgnDC(HDC hdc, HRGN hRgn, HRGN *phRgn)
|
|
{
|
|
if (!GdiIsHandleValid((HGDIOBJ) hdc) ||
|
|
(GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC)) return 0;
|
|
|
|
return MirrorRgnByWidth(hRgn, NtGdiGetDeviceWidth(hdc), phRgn);
|
|
}
|
|
|
|
/* FUNCTIONS *****************************************************************/
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
INT
|
|
WINAPI
|
|
CombineRgn(HRGN hDest,
|
|
HRGN hSrc1,
|
|
HRGN hSrc2,
|
|
INT CombineMode)
|
|
{
|
|
PRGN_ATTR pRgn_Attr_Dest = NULL;
|
|
PRGN_ATTR pRgn_Attr_Src1 = NULL;
|
|
PRGN_ATTR pRgn_Attr_Src2 = NULL;
|
|
INT Complexity;
|
|
BOOL Ret;
|
|
|
|
// HACK
|
|
return NtGdiCombineRgn(hDest, hSrc1, hSrc2, CombineMode);
|
|
|
|
Ret = GdiGetHandleUserData((HGDIOBJ) hDest, GDI_OBJECT_TYPE_REGION, (PVOID) &pRgn_Attr_Dest);
|
|
Ret = GdiGetHandleUserData((HGDIOBJ) hSrc1, GDI_OBJECT_TYPE_REGION, (PVOID) &pRgn_Attr_Src1);
|
|
|
|
if ( !Ret ||
|
|
!pRgn_Attr_Dest ||
|
|
!pRgn_Attr_Src1 ||
|
|
pRgn_Attr_Src1->Flags > SIMPLEREGION )
|
|
return NtGdiCombineRgn(hDest, hSrc1, hSrc2, CombineMode);
|
|
|
|
/* Handle COPY and use only src1. */
|
|
if ( CombineMode == RGN_COPY )
|
|
{
|
|
switch (pRgn_Attr_Src1->Flags)
|
|
{
|
|
case NULLREGION:
|
|
Ret = SetRectRgn( hDest, 0, 0, 0, 0);
|
|
if (Ret)
|
|
return NULLREGION;
|
|
goto ERROR_Exit;
|
|
|
|
case SIMPLEREGION:
|
|
Ret = SetRectRgn( hDest,
|
|
pRgn_Attr_Src1->Rect.left,
|
|
pRgn_Attr_Src1->Rect.top,
|
|
pRgn_Attr_Src1->Rect.right,
|
|
pRgn_Attr_Src1->Rect.bottom );
|
|
if (Ret)
|
|
return SIMPLEREGION;
|
|
goto ERROR_Exit;
|
|
|
|
case COMPLEXREGION:
|
|
default:
|
|
return NtGdiCombineRgn(hDest, hSrc1, hSrc2, CombineMode);
|
|
}
|
|
}
|
|
|
|
Ret = GdiGetHandleUserData((HGDIOBJ) hSrc2, GDI_OBJECT_TYPE_REGION, (PVOID) &pRgn_Attr_Src2);
|
|
if ( !Ret ||
|
|
!pRgn_Attr_Src2 ||
|
|
pRgn_Attr_Src2->Flags > SIMPLEREGION )
|
|
return NtGdiCombineRgn(hDest, hSrc1, hSrc2, CombineMode);
|
|
|
|
/* All but AND. */
|
|
if ( CombineMode != RGN_AND)
|
|
{
|
|
if ( CombineMode <= RGN_AND)
|
|
{
|
|
/*
|
|
There might be some type of junk in the call, so go K.
|
|
If this becomes a problem, need to setup parameter check at the top.
|
|
*/
|
|
DPRINT1("Might be junk! CombineMode %d\n",CombineMode);
|
|
return NtGdiCombineRgn(hDest, hSrc1, hSrc2, CombineMode);
|
|
}
|
|
|
|
if ( CombineMode > RGN_XOR) /* Handle DIFF. */
|
|
{
|
|
if ( CombineMode != RGN_DIFF)
|
|
{ /* Filter check! Well, must be junk?, so go K. */
|
|
DPRINT1("RGN_COPY was handled! CombineMode %d\n",CombineMode);
|
|
return NtGdiCombineRgn(hDest, hSrc1, hSrc2, CombineMode);
|
|
}
|
|
/* Now handle DIFF. */
|
|
if ( pRgn_Attr_Src1->Flags == NULLREGION )
|
|
{
|
|
if (SetRectRgn( hDest, 0, 0, 0, 0))
|
|
return NULLREGION;
|
|
goto ERROR_Exit;
|
|
}
|
|
|
|
if ( pRgn_Attr_Src2->Flags != NULLREGION )
|
|
{
|
|
Complexity = ComplexityFromRects( &pRgn_Attr_Src1->Rect, &pRgn_Attr_Src2->Rect);
|
|
|
|
if ( Complexity != DIFF_RGN )
|
|
{
|
|
if ( Complexity != INVERTED_RGN)
|
|
/* If same or overlapping and norm just go K. */
|
|
return NtGdiCombineRgn(hDest, hSrc1, hSrc2, CombineMode);
|
|
|
|
if (SetRectRgn( hDest, 0, 0, 0, 0))
|
|
return NULLREGION;
|
|
goto ERROR_Exit;
|
|
}
|
|
}
|
|
}
|
|
else /* Handle OR or XOR. */
|
|
{
|
|
if ( pRgn_Attr_Src1->Flags == NULLREGION )
|
|
{
|
|
if ( pRgn_Attr_Src2->Flags != NULLREGION )
|
|
{ /* Src1 null and not NULL, set from src2. */
|
|
Ret = SetRectRgn( hDest,
|
|
pRgn_Attr_Src2->Rect.left,
|
|
pRgn_Attr_Src2->Rect.top,
|
|
pRgn_Attr_Src2->Rect.right,
|
|
pRgn_Attr_Src2->Rect.bottom );
|
|
if (Ret)
|
|
return SIMPLEREGION;
|
|
goto ERROR_Exit;
|
|
}
|
|
/* Both are NULL. */
|
|
if (SetRectRgn( hDest, 0, 0, 0, 0))
|
|
return NULLREGION;
|
|
goto ERROR_Exit;
|
|
}
|
|
/* Src1 is not NULL. */
|
|
if ( pRgn_Attr_Src2->Flags != NULLREGION )
|
|
{
|
|
if ( CombineMode != RGN_OR ) /* Filter XOR, so go K. */
|
|
return NtGdiCombineRgn(hDest, hSrc1, hSrc2, CombineMode);
|
|
|
|
Complexity = ComplexityFromRects( &pRgn_Attr_Src1->Rect, &pRgn_Attr_Src2->Rect);
|
|
/* If inverted use Src2. */
|
|
if ( Complexity == INVERTED_RGN)
|
|
{
|
|
Ret = SetRectRgn( hDest,
|
|
pRgn_Attr_Src2->Rect.left,
|
|
pRgn_Attr_Src2->Rect.top,
|
|
pRgn_Attr_Src2->Rect.right,
|
|
pRgn_Attr_Src2->Rect.bottom );
|
|
if (Ret)
|
|
return SIMPLEREGION;
|
|
goto ERROR_Exit;
|
|
}
|
|
/* Not NULL or overlapping or differentiated, go to K. */
|
|
if ( Complexity != SAME_RGN)
|
|
return NtGdiCombineRgn(hDest, hSrc1, hSrc2, CombineMode);
|
|
/* If same, just fall through. */
|
|
}
|
|
}
|
|
Ret = SetRectRgn( hDest,
|
|
pRgn_Attr_Src1->Rect.left,
|
|
pRgn_Attr_Src1->Rect.top,
|
|
pRgn_Attr_Src1->Rect.right,
|
|
pRgn_Attr_Src1->Rect.bottom );
|
|
if (Ret)
|
|
return SIMPLEREGION;
|
|
goto ERROR_Exit;
|
|
}
|
|
|
|
/* Handle AND. */
|
|
if ( pRgn_Attr_Src1->Flags != NULLREGION &&
|
|
pRgn_Attr_Src2->Flags != NULLREGION )
|
|
{
|
|
Complexity = ComplexityFromRects( &pRgn_Attr_Src1->Rect, &pRgn_Attr_Src2->Rect);
|
|
|
|
if ( Complexity == DIFF_RGN ) /* Differentiated in anyway just NULL rgn. */
|
|
{
|
|
if (SetRectRgn( hDest, 0, 0, 0, 0))
|
|
return NULLREGION;
|
|
goto ERROR_Exit;
|
|
}
|
|
|
|
if ( Complexity != INVERTED_RGN) /* Not inverted and overlapping. */
|
|
{
|
|
if ( Complexity != SAME_RGN) /* Must be norm and overlapping. */
|
|
return NtGdiCombineRgn(hDest, hSrc1, hSrc2, CombineMode);
|
|
/* Merge from src2. */
|
|
Ret = SetRectRgn( hDest,
|
|
pRgn_Attr_Src2->Rect.left,
|
|
pRgn_Attr_Src2->Rect.top,
|
|
pRgn_Attr_Src2->Rect.right,
|
|
pRgn_Attr_Src2->Rect.bottom );
|
|
if (Ret)
|
|
return SIMPLEREGION;
|
|
goto ERROR_Exit;
|
|
}
|
|
/* Inverted so merge from src1. */
|
|
Ret = SetRectRgn( hDest,
|
|
pRgn_Attr_Src1->Rect.left,
|
|
pRgn_Attr_Src1->Rect.top,
|
|
pRgn_Attr_Src1->Rect.right,
|
|
pRgn_Attr_Src1->Rect.bottom );
|
|
if (Ret)
|
|
return SIMPLEREGION;
|
|
goto ERROR_Exit;
|
|
}
|
|
|
|
/* It's all NULL! */
|
|
if (SetRectRgn( hDest, 0, 0, 0, 0))
|
|
return NULLREGION;
|
|
|
|
ERROR_Exit:
|
|
/* Even on error the flag is set dirty and force server side to redraw. */
|
|
pRgn_Attr_Dest->AttrFlags |= ATTR_RGN_DIRTY;
|
|
return ERROR;
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
HRGN
|
|
WINAPI
|
|
CreateEllipticRgnIndirect(
|
|
const RECT *prc
|
|
)
|
|
{
|
|
/* Notes if prc is NULL it will crash on All Windows NT I checked 2000/XP/VISTA */
|
|
return NtGdiCreateEllipticRgn(prc->left, prc->top, prc->right, prc->bottom);
|
|
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
HRGN
|
|
WINAPI
|
|
CreatePolygonRgn( const POINT * lppt, int cPoints, int fnPolyFillMode)
|
|
{
|
|
return (HRGN) NtGdiPolyPolyDraw( (HDC) fnPolyFillMode, (PPOINT) lppt, (PULONG) &cPoints, 1, GdiPolyPolyRgn);
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
HRGN
|
|
WINAPI
|
|
CreatePolyPolygonRgn( const POINT* lppt,
|
|
const INT* lpPolyCounts,
|
|
int nCount,
|
|
int fnPolyFillMode)
|
|
{
|
|
return (HRGN) NtGdiPolyPolyDraw( (HDC) fnPolyFillMode, (PPOINT) lppt, (PULONG) lpPolyCounts, (ULONG) nCount, GdiPolyPolyRgn );
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
HRGN
|
|
WINAPI
|
|
CreateRectRgn(int x1, int y1, int x2, int y2)
|
|
{
|
|
PRGN_ATTR pRgn_Attr;
|
|
HRGN hrgn;
|
|
int tmp;
|
|
|
|
/// <-
|
|
//// Remove when Brush/Pen/Rgn Attr is ready!
|
|
return NtGdiCreateRectRgn(x1,y1,x2,y2);
|
|
////
|
|
|
|
/* Normalize points */
|
|
tmp = x1;
|
|
if ( x1 > x2 )
|
|
{
|
|
x1 = x2;
|
|
x2 = tmp;
|
|
}
|
|
|
|
tmp = y1;
|
|
if ( y1 > y2 )
|
|
{
|
|
y1 = y2;
|
|
y2 = tmp;
|
|
}
|
|
/* 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);
|
|
|
|
if (!hrgn)
|
|
hrgn = NtGdiCreateRectRgn(0, 0, 1, 1);
|
|
|
|
if (!hrgn)
|
|
return hrgn;
|
|
|
|
if (!GdiGetHandleUserData((HGDIOBJ) hrgn, GDI_OBJECT_TYPE_REGION, (PVOID) &pRgn_Attr))
|
|
{
|
|
DPRINT1("No Attr for Region handle!!!\n");
|
|
DeleteRegion(hrgn);
|
|
return NULL;
|
|
}
|
|
|
|
if (( x1 == x2) || (y1 == y2))
|
|
{
|
|
pRgn_Attr->Flags = NULLREGION;
|
|
pRgn_Attr->Rect.left = pRgn_Attr->Rect.top =
|
|
pRgn_Attr->Rect.right = pRgn_Attr->Rect.bottom = 0;
|
|
}
|
|
else
|
|
{
|
|
pRgn_Attr->Flags = SIMPLEREGION;
|
|
pRgn_Attr->Rect.left = x1;
|
|
pRgn_Attr->Rect.top = y1;
|
|
pRgn_Attr->Rect.right = x2;
|
|
pRgn_Attr->Rect.bottom = y2;
|
|
}
|
|
|
|
pRgn_Attr->AttrFlags = (ATTR_RGN_DIRTY|ATTR_RGN_VALID);
|
|
|
|
return hrgn;
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
HRGN
|
|
WINAPI
|
|
CreateRectRgnIndirect(
|
|
const RECT *prc
|
|
)
|
|
{
|
|
/* Notes if prc is NULL it will crash on All Windows NT I checked 2000/XP/VISTA */
|
|
return CreateRectRgn(prc->left, prc->top, prc->right, prc->bottom);
|
|
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
INT
|
|
WINAPI
|
|
ExcludeClipRect(IN HDC hdc, IN INT xLeft, IN INT yTop, IN INT xRight, IN INT yBottom)
|
|
{
|
|
#if 0
|
|
// Handle something other than a normal dc object.
|
|
if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC)
|
|
{
|
|
if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC)
|
|
return MFDRV_ExcludeClipRect( hdc, xLeft, yTop, xRight, yBottom);
|
|
else
|
|
{
|
|
PLDC pLDC = GdiGetLDC(hdc);
|
|
if ( pLDC )
|
|
{
|
|
if (pLDC->iType != LDC_EMFLDC || EMFDRV_ExcludeClipRect( hdc, xLeft, yTop, xRight, yBottom))
|
|
return NtGdiExcludeClipRect(hdc, xLeft, yTop, xRight, yBottom);
|
|
}
|
|
else
|
|
SetLastError(ERROR_INVALID_HANDLE);
|
|
return ERROR;
|
|
}
|
|
}
|
|
#endif
|
|
return NtGdiExcludeClipRect(hdc, xLeft, yTop, xRight, yBottom);
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
HRGN
|
|
WINAPI
|
|
ExtCreateRegion(
|
|
CONST XFORM * lpXform,
|
|
DWORD nCount,
|
|
CONST RGNDATA * lpRgnData
|
|
)
|
|
{
|
|
if (lpRgnData)
|
|
{
|
|
if ((!lpXform) && (lpRgnData->rdh.nCount == 1))
|
|
{
|
|
PRECT pRect = (PRECT)&lpRgnData->Buffer[0];
|
|
return CreateRectRgn(pRect->left, pRect->top, pRect->right, pRect->bottom);
|
|
}
|
|
return NtGdiExtCreateRegion((LPXFORM) lpXform, nCount,(LPRGNDATA) lpRgnData);
|
|
}
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
INT
|
|
WINAPI
|
|
ExtSelectClipRgn( IN HDC hdc, IN HRGN hrgn, IN INT iMode)
|
|
{
|
|
INT Ret;
|
|
HRGN NewRgn = NULL;
|
|
|
|
#if 0
|
|
// Handle something other than a normal dc object.
|
|
if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC)
|
|
{
|
|
if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC)
|
|
return MFDRV_ExtSelectClipRgn( hdc, );
|
|
else
|
|
{
|
|
PLDC pLDC = GdiGetLDC(hdc);
|
|
if ( pLDC )
|
|
{
|
|
if (pLDC->iType != LDC_EMFLDC || EMFDRV_ExtSelectClipRgn( hdc, ))
|
|
return NtGdiExtSelectClipRgn(hdc, );
|
|
}
|
|
else
|
|
SetLastError(ERROR_INVALID_HANDLE);
|
|
return ERROR;
|
|
}
|
|
}
|
|
#endif
|
|
#if 0
|
|
if ( hrgn )
|
|
{
|
|
if ( GetLayout(hdc) & LAYOUT_RTL )
|
|
{
|
|
if ( MirrorRgnDC(hdc, hrgn, &NewRgn) )
|
|
{
|
|
if ( NewRgn ) hrgn = NewRgn;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
/* Batch handles RGN_COPY only! */
|
|
if (iMode == RGN_COPY)
|
|
{
|
|
#if 0
|
|
PDC_ATTR pDc_Attr;
|
|
PRGN_ATTR pRgn_Attr = NULL;
|
|
|
|
/* hrgn can be NULL unless the RGN_COPY mode is specified. */
|
|
if (hrgn)
|
|
GdiGetHandleUserData((HGDIOBJ) hrgn, GDI_OBJECT_TYPE_REGION, (PVOID) &pRgn_Attr);
|
|
|
|
if ( GdiGetHandleUserData((HGDIOBJ) hdc, GDI_OBJECT_TYPE_DC, (PVOID) &pDc_Attr) &&
|
|
pDc_Attr )
|
|
{
|
|
PGDI_TABLE_ENTRY pEntry = GdiHandleTable + GDI_HANDLE_GET_INDEX(hdc);
|
|
PTEB pTeb = NtCurrentTeb();
|
|
|
|
if ( pTeb->Win32ThreadInfo != NULL &&
|
|
pTeb->GdiTebBatch.HDC == hdc &&
|
|
!(pDc_Attr->ulDirty_ & DC_DIBSECTION) &&
|
|
!(pEntry->Flags & GDI_ENTRY_VALIDATE_VIS) )
|
|
{
|
|
if (!hrgn ||
|
|
(hrgn && pRgn_Attr && pRgn_Attr->Flags <= SIMPLEREGION) )
|
|
{
|
|
if ((pTeb->GdiTebBatch.Offset + sizeof(GDIBSEXTSELCLPRGN)) <= GDIBATCHBUFSIZE)
|
|
{
|
|
PGDIBSEXTSELCLPRGN pgO = (PGDIBSEXTSELCLPRGN)(&pTeb->GdiTebBatch.Buffer[0] +
|
|
pTeb->GdiTebBatch.Offset);
|
|
pgO->gbHdr.Cmd = GdiBCExtSelClipRgn;
|
|
pgO->gbHdr.Size = sizeof(GDIBSEXTSELCLPRGN);
|
|
pgO->fnMode = iMode;
|
|
|
|
if ( hrgn && pRgn_Attr )
|
|
{
|
|
Ret = pRgn_Attr->Flags;
|
|
|
|
if ( pDc_Attr->VisRectRegion.Rect.left >= pRgn_Attr->Rect.right ||
|
|
pDc_Attr->VisRectRegion.Rect.top >= pRgn_Attr->Rect.bottom ||
|
|
pDc_Attr->VisRectRegion.Rect.right <= pRgn_Attr->Rect.left ||
|
|
pDc_Attr->VisRectRegion.Rect.bottom <= pRgn_Attr->Rect.top )
|
|
Ret = NULLREGION;
|
|
|
|
pgO->left = pRgn_Attr->Rect.left;
|
|
pgO->top = pRgn_Attr->Rect.top;
|
|
pgO->right = pRgn_Attr->Rect.right;
|
|
pgO->bottom = pRgn_Attr->Rect.bottom;
|
|
}
|
|
else
|
|
{
|
|
Ret = pDc_Attr->VisRectRegion.Flags;
|
|
pgO->fnMode |= 0x80000000; // Set no hrgn mode.
|
|
}
|
|
pTeb->GdiTebBatch.Offset += sizeof(GDIBSEXTSELCLPRGN);
|
|
pTeb->GdiBatchCount++;
|
|
if (pTeb->GdiBatchCount >= GDI_BatchLimit) NtGdiFlush();
|
|
if ( NewRgn ) DeleteObject(NewRgn);
|
|
return Ret;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
Ret = NtGdiExtSelectClipRgn(hdc, hrgn, iMode);
|
|
|
|
if ( NewRgn ) DeleteObject(NewRgn);
|
|
|
|
return Ret;
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
int
|
|
WINAPI
|
|
GetClipRgn(
|
|
HDC hdc,
|
|
HRGN hrgn
|
|
)
|
|
{
|
|
INT Ret = NtGdiGetRandomRgn(hdc, hrgn, CLIPRGN);
|
|
// if (Ret)
|
|
// {
|
|
// if(GetLayout(hdc) & LAYOUT_RTL) MirrorRgnDC(hdc,(HRGN)Ret, NULL);
|
|
// }
|
|
return Ret;
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
int
|
|
WINAPI
|
|
GetMetaRgn(HDC hdc,
|
|
HRGN hrgn)
|
|
{
|
|
return NtGdiGetRandomRgn(hdc, hrgn, METARGN);
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*
|
|
*/
|
|
DWORD
|
|
WINAPI
|
|
GetRegionData(HRGN hrgn,
|
|
DWORD nCount,
|
|
LPRGNDATA lpRgnData)
|
|
{
|
|
if (!lpRgnData)
|
|
{
|
|
nCount = 0;
|
|
}
|
|
|
|
return NtGdiGetRegionData(hrgn,nCount,lpRgnData);
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*
|
|
*/
|
|
INT
|
|
WINAPI
|
|
GetRgnBox(HRGN hrgn,
|
|
LPRECT prcOut)
|
|
{
|
|
PRGN_ATTR Rgn_Attr;
|
|
|
|
//if (!GdiGetHandleUserData((HGDIOBJ) hrgn, GDI_OBJECT_TYPE_REGION, (PVOID) &Rgn_Attr))
|
|
return NtGdiGetRgnBox(hrgn, prcOut);
|
|
|
|
if (Rgn_Attr->Flags == NULLREGION)
|
|
{
|
|
prcOut->left = 0;
|
|
prcOut->top = 0;
|
|
prcOut->right = 0;
|
|
prcOut->bottom = 0;
|
|
}
|
|
else
|
|
{
|
|
if (Rgn_Attr->Flags != SIMPLEREGION)
|
|
return NtGdiGetRgnBox(hrgn, prcOut);
|
|
/* WARNING! prcOut is never checked newbies! */
|
|
RtlCopyMemory( prcOut, &Rgn_Attr->Rect, sizeof(RECT));
|
|
}
|
|
return Rgn_Attr->Flags;
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
INT
|
|
WINAPI
|
|
IntersectClipRect(HDC hdc,
|
|
int nLeftRect,
|
|
int nTopRect,
|
|
int nRightRect,
|
|
int nBottomRect)
|
|
{
|
|
#if 0
|
|
// Handle something other than a normal dc object.
|
|
if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC)
|
|
{
|
|
if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC)
|
|
return MFDRV_IntersectClipRect( hdc, nLeftRect, nTopRect, nRightRect, nBottomRect);
|
|
else
|
|
{
|
|
PLDC pLDC = GdiGetLDC(hdc);
|
|
if ( pLDC )
|
|
{
|
|
if (pLDC->iType != LDC_EMFLDC || EMFDRV_IntersectClipRect( hdc, nLeftRect, nTopRect, nRightRect, nBottomRect))
|
|
return NtGdiIntersectClipRect(hdc, nLeftRect, nTopRect, nRightRect, nBottomRect);
|
|
}
|
|
else
|
|
SetLastError(ERROR_INVALID_HANDLE);
|
|
return ERROR;
|
|
}
|
|
}
|
|
#endif
|
|
return NtGdiIntersectClipRect(hdc, nLeftRect, nTopRect, nRightRect, nBottomRect);
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
BOOL
|
|
WINAPI
|
|
MirrorRgn(HWND hwnd, HRGN hrgn)
|
|
{
|
|
RECT Rect;
|
|
GetWindowRect(hwnd, &Rect);
|
|
return MirrorRgnByWidth(hrgn, Rect.right - Rect.left, NULL);
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
INT
|
|
WINAPI
|
|
OffsetClipRgn(HDC hdc,
|
|
int nXOffset,
|
|
int nYOffset)
|
|
{
|
|
#if 0
|
|
// Handle something other than a normal dc object.
|
|
if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC)
|
|
{
|
|
if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC)
|
|
return MFDRV_OffsetClipRgn( hdc, nXOffset, nYOffset );
|
|
else
|
|
{
|
|
PLDC pLDC = GdiGetLDC(hdc);
|
|
if ( !pLDC )
|
|
{
|
|
SetLastError(ERROR_INVALID_HANDLE);
|
|
return ERROR;
|
|
}
|
|
if (pLDC->iType == LDC_EMFLDC && !EMFDRV_OffsetClipRgn( hdc, nXOffset, nYOffset ))
|
|
return ERROR;
|
|
return NtGdiOffsetClipRgn( hdc, nXOffset, nYOffset);
|
|
}
|
|
}
|
|
#endif
|
|
return NtGdiOffsetClipRgn( hdc, nXOffset, nYOffset);
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*
|
|
*/
|
|
INT
|
|
WINAPI
|
|
OffsetRgn( HRGN hrgn,
|
|
int nXOffset,
|
|
int nYOffset)
|
|
{
|
|
PRGN_ATTR pRgn_Attr;
|
|
int nLeftRect, nTopRect, nRightRect, nBottomRect;
|
|
|
|
// HACKFIX
|
|
// if (!GdiGetHandleUserData((HGDIOBJ) hrgn, GDI_OBJECT_TYPE_REGION, (PVOID) &pRgn_Attr))
|
|
return NtGdiOffsetRgn(hrgn,nXOffset,nYOffset);
|
|
|
|
if ( pRgn_Attr->Flags == NULLREGION)
|
|
return pRgn_Attr->Flags;
|
|
|
|
if ( pRgn_Attr->Flags != SIMPLEREGION)
|
|
return NtGdiOffsetRgn(hrgn,nXOffset,nYOffset);
|
|
|
|
nLeftRect = pRgn_Attr->Rect.left;
|
|
nTopRect = pRgn_Attr->Rect.top;
|
|
nRightRect = pRgn_Attr->Rect.right;
|
|
nBottomRect = pRgn_Attr->Rect.bottom;
|
|
|
|
if (nLeftRect < nRightRect)
|
|
{
|
|
if (nTopRect < nBottomRect)
|
|
{
|
|
nLeftRect = nXOffset + nLeftRect;
|
|
nTopRect = nYOffset + nTopRect;
|
|
nRightRect = nXOffset + nRightRect;
|
|
nBottomRect = nYOffset + nBottomRect;
|
|
|
|
/* 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;
|
|
}
|
|
|
|
pRgn_Attr->Rect.top = nTopRect;
|
|
pRgn_Attr->Rect.left = nLeftRect;
|
|
pRgn_Attr->Rect.right = nRightRect;
|
|
pRgn_Attr->Rect.bottom = nBottomRect;
|
|
pRgn_Attr->AttrFlags |= ATTR_RGN_DIRTY;
|
|
}
|
|
}
|
|
return pRgn_Attr->Flags;
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
BOOL
|
|
WINAPI
|
|
PtInRegion(IN HRGN hrgn,
|
|
int x,
|
|
int y)
|
|
{
|
|
PRGN_ATTR pRgn_Attr;
|
|
|
|
// HACKFIX
|
|
//if (!GdiGetHandleUserData((HGDIOBJ) hrgn, GDI_OBJECT_TYPE_REGION, (PVOID) &pRgn_Attr))
|
|
return NtGdiPtInRegion(hrgn,x,y);
|
|
|
|
if ( pRgn_Attr->Flags == NULLREGION)
|
|
return FALSE;
|
|
|
|
if ( pRgn_Attr->Flags != SIMPLEREGION)
|
|
return NtGdiPtInRegion(hrgn,x,y);
|
|
|
|
return INRECT( pRgn_Attr->Rect, x, y);
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
BOOL
|
|
WINAPI
|
|
RectInRegion(HRGN hrgn,
|
|
LPCRECT prcl)
|
|
{
|
|
PRGN_ATTR pRgn_Attr;
|
|
RECTL rc;
|
|
|
|
// HACKFIX
|
|
//if (!GdiGetHandleUserData((HGDIOBJ) hrgn, GDI_OBJECT_TYPE_REGION, (PVOID) &pRgn_Attr))
|
|
return NtGdiRectInRegion(hrgn, (LPRECT) prcl);
|
|
|
|
if ( pRgn_Attr->Flags == NULLREGION)
|
|
return FALSE;
|
|
|
|
if ( pRgn_Attr->Flags != SIMPLEREGION)
|
|
return NtGdiRectInRegion(hrgn, (LPRECT) prcl);
|
|
|
|
/* swap the coordinates to make right >= left and bottom >= top */
|
|
/* (region building rectangles are normalized the same way) */
|
|
if ( prcl->top > prcl->bottom)
|
|
{
|
|
rc.top = prcl->bottom;
|
|
rc.bottom = prcl->top;
|
|
}
|
|
else
|
|
{
|
|
rc.top = prcl->top;
|
|
rc.bottom = prcl->bottom;
|
|
}
|
|
if ( prcl->right < prcl->left)
|
|
{
|
|
rc.right = prcl->left;
|
|
rc.left = prcl->right;
|
|
}
|
|
else
|
|
{
|
|
rc.right = prcl->right;
|
|
rc.left = prcl->left;
|
|
}
|
|
|
|
if ( ComplexityFromRects( &pRgn_Attr->Rect, &rc) != DIFF_RGN )
|
|
return TRUE;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
int WINAPI
|
|
SelectClipRgn(
|
|
HDC hdc,
|
|
HRGN hrgn
|
|
)
|
|
{
|
|
return ExtSelectClipRgn(hdc, hrgn, RGN_COPY);
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
BOOL
|
|
WINAPI
|
|
SetRectRgn(HRGN hrgn,
|
|
int nLeftRect,
|
|
int nTopRect,
|
|
int nRightRect,
|
|
int nBottomRect)
|
|
{
|
|
PRGN_ATTR Rgn_Attr;
|
|
|
|
//if (!GdiGetHandleUserData((HGDIOBJ) hrgn, GDI_OBJECT_TYPE_REGION, (PVOID) &Rgn_Attr))
|
|
return NtGdiSetRectRgn(hrgn, nLeftRect, nTopRect, nRightRect, nBottomRect);
|
|
|
|
if ((nLeftRect == nRightRect) || (nTopRect == nBottomRect))
|
|
{
|
|
Rgn_Attr->AttrFlags |= ATTR_RGN_DIRTY;
|
|
Rgn_Attr->Flags = NULLREGION;
|
|
Rgn_Attr->Rect.left = Rgn_Attr->Rect.top =
|
|
Rgn_Attr->Rect.right = Rgn_Attr->Rect.bottom = 0;
|
|
return TRUE;
|
|
}
|
|
|
|
Rgn_Attr->Rect.left = nLeftRect;
|
|
Rgn_Attr->Rect.top = nTopRect;
|
|
Rgn_Attr->Rect.right = nRightRect;
|
|
Rgn_Attr->Rect.bottom = nBottomRect;
|
|
|
|
if(nLeftRect > nRightRect)
|
|
{
|
|
Rgn_Attr->Rect.left = nRightRect;
|
|
Rgn_Attr->Rect.right = nLeftRect;
|
|
}
|
|
if(nTopRect > nBottomRect)
|
|
{
|
|
Rgn_Attr->Rect.top = nBottomRect;
|
|
Rgn_Attr->Rect.bottom = nTopRect;
|
|
}
|
|
|
|
Rgn_Attr->AttrFlags |= ATTR_RGN_DIRTY ;
|
|
Rgn_Attr->Flags = SIMPLEREGION;
|
|
return TRUE;
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
int
|
|
WINAPI
|
|
SetMetaRgn( HDC hDC )
|
|
{
|
|
if (GDI_HANDLE_GET_TYPE(hDC) == GDI_OBJECT_TYPE_DC)
|
|
return NtGdiSetMetaRgn(hDC);
|
|
#if 0
|
|
PLDC pLDC = GdiGetLDC(hDC);
|
|
if ( pLDC && GDI_HANDLE_GET_TYPE(hDC) != GDI_OBJECT_TYPE_METADC )
|
|
{
|
|
if (pLDC->iType == LDC_EMFLDC || EMFDRV_SetMetaRgn(hDC))
|
|
{
|
|
return NtGdiSetMetaRgn(hDC);
|
|
}
|
|
else
|
|
SetLastError(ERROR_INVALID_HANDLE);
|
|
}
|
|
#endif
|
|
return ERROR;
|
|
}
|
|
|