📄 region.c
字号:
* None.
*
* \note Side Effects:
* Rectangles are overwritten in pReg->rects and pReg->numRects will
* be changed.
*
*/
static void FASTCALL
REGION_UnionO (
PROSRGNDATA pReg,
PRECT r1,
PRECT r1End,
PRECT r2,
PRECT r2End,
INT top,
INT bottom
)
{
RECT *pNextRect;
pNextRect = (PRECT)pReg->Buffer + pReg->rdh.nCount;
#define MERGERECT(r) \
if ((pReg->rdh.nCount != 0) && \
((pNextRect-1)->top == top) && \
((pNextRect-1)->bottom == bottom) && \
((pNextRect-1)->right >= r->left)) \
{ \
if ((pNextRect-1)->right < r->right) \
{ \
(pNextRect-1)->right = r->right; \
} \
} \
else \
{ \
MEMCHECK(pReg, pNextRect, pReg->Buffer); \
pNextRect->top = top; \
pNextRect->bottom = bottom; \
pNextRect->left = r->left; \
pNextRect->right = r->right; \
pReg->rdh.nCount += 1; \
pNextRect += 1; \
} \
r++;
while ((r1 != r1End) && (r2 != r2End))
{
if (r1->left < r2->left)
{
MERGERECT(r1);
}
else
{
MERGERECT(r2);
}
}
if (r1 != r1End)
{
do
{
MERGERECT(r1);
} while (r1 != r1End);
}
else while (r2 != r2End)
{
MERGERECT(r2);
}
return;
}
/***********************************************************************
* REGION_UnionRegion
*/
static void FASTCALL REGION_UnionRegion(ROSRGNDATA *newReg, ROSRGNDATA *reg1,
ROSRGNDATA *reg2)
{
/* checks all the simple cases */
/*
* Region 1 and 2 are the same or region 1 is empty
*/
if (reg1 == reg2 || 0 == reg1->rdh.nCount ||
reg1->rdh.rcBound.right <= reg1->rdh.rcBound.left ||
reg1->rdh.rcBound.bottom <= reg1->rdh.rcBound.top)
{
if (newReg != reg2)
{
REGION_CopyRegion(newReg, reg2);
}
return;
}
/*
* if nothing to union (region 2 empty)
*/
if (0 == reg2->rdh.nCount ||
reg2->rdh.rcBound.right <= reg2->rdh.rcBound.left ||
reg2->rdh.rcBound.bottom <= reg2->rdh.rcBound.top)
{
if (newReg != reg1)
{
REGION_CopyRegion(newReg, reg1);
}
return;
}
/*
* Region 1 completely subsumes region 2
*/
if (1 == reg1->rdh.nCount &&
reg1->rdh.rcBound.left <= reg2->rdh.rcBound.left &&
reg1->rdh.rcBound.top <= reg2->rdh.rcBound.top &&
reg2->rdh.rcBound.right <= reg1->rdh.rcBound.right &&
reg2->rdh.rcBound.bottom <= reg1->rdh.rcBound.bottom)
{
if (newReg != reg1)
{
REGION_CopyRegion(newReg, reg1);
}
return;
}
/*
* Region 2 completely subsumes region 1
*/
if (1 == reg2->rdh.nCount &&
reg2->rdh.rcBound.left <= reg1->rdh.rcBound.left &&
reg2->rdh.rcBound.top <= reg1->rdh.rcBound.top &&
reg1->rdh.rcBound.right <= reg2->rdh.rcBound.right &&
reg1->rdh.rcBound.bottom <= reg2->rdh.rcBound.bottom)
{
if (newReg != reg2)
{
REGION_CopyRegion(newReg, reg2);
}
return;
}
REGION_RegionOp ( newReg, reg1, reg2, REGION_UnionO,
REGION_UnionNonO, REGION_UnionNonO );
newReg->rdh.rcBound.left = min(reg1->rdh.rcBound.left, reg2->rdh.rcBound.left);
newReg->rdh.rcBound.top = min(reg1->rdh.rcBound.top, reg2->rdh.rcBound.top);
newReg->rdh.rcBound.right = max(reg1->rdh.rcBound.right, reg2->rdh.rcBound.right);
newReg->rdh.rcBound.bottom = max(reg1->rdh.rcBound.bottom, reg2->rdh.rcBound.bottom);
}
/***********************************************************************
* Region Subtraction
***********************************************************************/
/*!
* Deal with non-overlapping band for subtraction. Any parts from
* region 2 we discard. Anything from region 1 we add to the region.
*
* Results:
* None.
*
* \note Side Effects:
* pReg may be affected.
*
*/
static void FASTCALL
REGION_SubtractNonO1 (
PROSRGNDATA pReg,
PRECT r,
PRECT rEnd,
INT top,
INT bottom
)
{
RECT *pNextRect;
pNextRect = (PRECT)pReg->Buffer + pReg->rdh.nCount;
while (r != rEnd)
{
MEMCHECK(pReg, pNextRect, pReg->Buffer);
pNextRect->left = r->left;
pNextRect->top = top;
pNextRect->right = r->right;
pNextRect->bottom = bottom;
pReg->rdh.nCount += 1;
pNextRect++;
r++;
}
return;
}
/*!
* Overlapping band subtraction. x1 is the left-most point not yet
* checked.
*
* Results:
* None.
*
* \note Side Effects:
* pReg may have rectangles added to it.
*
*/
static void FASTCALL
REGION_SubtractO (
PROSRGNDATA pReg,
PRECT r1,
PRECT r1End,
PRECT r2,
PRECT r2End,
INT top,
INT bottom
)
{
RECT *pNextRect;
INT left;
left = r1->left;
pNextRect = (PRECT)pReg->Buffer + pReg->rdh.nCount;
while ((r1 != r1End) && (r2 != r2End))
{
if (r2->right <= left)
{
/*
* Subtrahend missed the boat: go to next subtrahend.
*/
r2++;
}
else if (r2->left <= left)
{
/*
* Subtrahend preceeds minuend: nuke left edge of minuend.
*/
left = r2->right;
if (left >= r1->right)
{
/*
* Minuend completely covered: advance to next minuend and
* reset left fence to edge of new minuend.
*/
r1++;
if (r1 != r1End)
left = r1->left;
}
else
{
/*
* Subtrahend now used up since it doesn't extend beyond
* minuend
*/
r2++;
}
}
else if (r2->left < r1->right)
{
/*
* Left part of subtrahend covers part of minuend: add uncovered
* part of minuend to region and skip to next subtrahend.
*/
MEMCHECK(pReg, pNextRect, pReg->Buffer);
pNextRect->left = left;
pNextRect->top = top;
pNextRect->right = r2->left;
pNextRect->bottom = bottom;
pReg->rdh.nCount += 1;
pNextRect++;
left = r2->right;
if (left >= r1->right)
{
/*
* Minuend used up: advance to new...
*/
r1++;
if (r1 != r1End)
left = r1->left;
}
else
{
/*
* Subtrahend used up
*/
r2++;
}
}
else
{
/*
* Minuend used up: add any remaining piece before advancing.
*/
if (r1->right > left)
{
MEMCHECK(pReg, pNextRect, pReg->Buffer);
pNextRect->left = left;
pNextRect->top = top;
pNextRect->right = r1->right;
pNextRect->bottom = bottom;
pReg->rdh.nCount += 1;
pNextRect++;
}
r1++;
left = r1->left;
}
}
/*
* Add remaining minuend rectangles to region.
*/
while (r1 != r1End)
{
MEMCHECK(pReg, pNextRect, pReg->Buffer);
pNextRect->left = left;
pNextRect->top = top;
pNextRect->right = r1->right;
pNextRect->bottom = bottom;
pReg->rdh.nCount += 1;
pNextRect++;
r1++;
if (r1 != r1End)
{
left = r1->left;
}
}
return;
}
/*!
* Subtract regS from regM and leave the result in regD.
* S stands for subtrahend, M for minuend and D for difference.
*
* Results:
* TRUE.
*
* \note Side Effects:
* regD is overwritten.
*
*/
static void FASTCALL REGION_SubtractRegion(ROSRGNDATA *regD, ROSRGNDATA *regM,
ROSRGNDATA *regS )
{
/* check for trivial reject */
if ( (!(regM->rdh.nCount)) || (!(regS->rdh.nCount)) ||
(!EXTENTCHECK(®M->rdh.rcBound, ®S->rdh.rcBound)) )
{
REGION_CopyRegion(regD, regM);
return;
}
REGION_RegionOp (regD, regM, regS, REGION_SubtractO,
REGION_SubtractNonO1, NULL);
/*
* Can't alter newReg's extents before we call miRegionOp because
* it might be one of the source regions and miRegionOp depends
* on the extents of those regions being the unaltered. Besides, this
* way there's no checking against rectangles that will be nuked
* due to coalescing, so we have to examine fewer rectangles.
*/
REGION_SetExtents (regD);
}
/***********************************************************************
* REGION_XorRegion
*/
static void FASTCALL REGION_XorRegion(ROSRGNDATA *dr, ROSRGNDATA *sra,
ROSRGNDATA *srb)
{
HRGN htra, htrb;
ROSRGNDATA *tra, *trb;
if(!(htra = RGNDATA_AllocRgn(sra->rdh.nCount + 1)))
return;
if(!(htrb = RGNDATA_AllocRgn(srb->rdh.nCount + 1)))
{
NtGdiDeleteObject( htra );
return;
}
tra = RGNDATA_LockRgn( htra );
if(!tra ){
NtGdiDeleteObject( htra );
NtGdiDeleteObject( htrb );
return;
}
trb = RGNDATA_LockRgn( htrb );
if( !trb ){
RGNDATA_UnlockRgn( tra );
NtGdiDeleteObject( htra );
NtGdiDeleteObject( htrb );
return;
}
REGION_SubtractRegion(tra,sra,srb);
REGION_SubtractRegion(trb,srb,sra);
REGION_UnionRegion(dr,tra,trb);
RGNDATA_UnlockRgn( tra );
RGNDATA_UnlockRgn( trb );
NtGdiDeleteObject( htra );
NtGdiDeleteObject( htrb );
return;
}
/*!
* Adds a rectangle to a REGION
*/
void FASTCALL REGION_UnionRectWithRegion(const RECT *rect, ROSRGNDATA *rgn)
{
ROSRGNDATA region;
region.Buffer = ®ion.rdh.rcBound;
region.rdh.nCount = 1;
region.rdh.nRgnSize = sizeof( RECT );
region.rdh.rcBound = *rect;
REGION_UnionRegion(rgn, rgn, ®ion);
}
BOOL FASTCALL REGION_CreateFrameRgn(HRGN hDest, HRGN hSrc, INT x, INT y)
{
PROSRGNDATA srcObj, destObj;
PRECT rc;
ULONG i;
if (!(srcObj = (PROSRGNDATA)RGNDATA_LockRgn(hSrc)))
{
return FALSE;
}
if (!REGION_NOT_EMPTY(srcObj))
{
RGNDATA_UnlockRgn(srcObj);
return FALSE;
}
if (!(destObj = (PROSRGNDATA)RGNDATA_LockRgn(hDest)))
{
RGNDATA_UnlockRgn(srcObj);
return FALSE;
}
EMPTY_REGION(destObj);
if (!REGION_CopyRegion(destObj, srcObj))
{
RGNDATA_UnlockRgn(destObj);
RGNDATA_UnlockRgn(srcObj);
return FALSE;
}
/* Original region moved to right */
rc = (PRECT)srcObj->Buffer;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -