📄 winrgn.c
字号:
*
* Side Effects:
* Rectangles are overwritten in region->rects and region->numRects will
* be changed.
*
*/
static void REGION_UnionO(TREGION *region, const TClipRect *r1, const TClipRect *r1End,
const TClipRect *r2, const TClipRect *r2End, int top, int bottom)
{
TClipRect *newcliprect;
#define MERGERECT(r) \
if ((region->head) && \
(region->tail->rc.top == top) && \
(region->tail->rc.bottom == bottom) && \
(region->tail->rc.right >= r->rc.left)) \
{ \
if (region->tail->rc.right < r->rc.right) \
{ \
region->tail->rc.right = r->rc.right; \
} \
} \
else \
{ \
NEWCLIPRECT(region, newcliprect); \
newcliprect->rc.top = top; \
newcliprect->rc.bottom = bottom; \
newcliprect->rc.left = r->rc.left; \
newcliprect->rc.right = r->rc.right; \
} \
r = r->next;
while ((r1 != r1End) && (r2 != r2End))
{
if (r1->rc.left < r2->rc.left)
{
MERGERECT(r1);
}
else
{
MERGERECT(r2);
}
}
if (r1 != r1End)
{
do {
MERGERECT(r1);
} while (r1 != r1End);
}
else while (r2 != r2End)
{
MERGERECT(r2);
}
}
/***********************************************************************
* Region Subtraction
***********************************************************************/
/***********************************************************************
* REGION_SubtractNonO1
*
* 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.
*
* Side Effects:
* region may be affected.
*
*/
static void REGION_SubtractNonO1 (TREGION *region, const TClipRect *r, const TClipRect *rEnd,
int top, int bottom)
{
TClipRect *newcliprect;
while (r != rEnd) {
NEWCLIPRECT(region, newcliprect);
newcliprect->rc.left = r->rc.left;
newcliprect->rc.top = top;
newcliprect->rc.right = r->rc.right;
newcliprect->rc.bottom = bottom;
r = r->next;
}
}
/***********************************************************************
* REGION_SubtractO
*
* Overlapping band subtraction. x1 is the left-most point not yet
* checked.
*
* Results:
* None.
*
* Side Effects:
* region may have rectangles added to it.
*
*/
static void REGION_SubtractO (TREGION *region, const TClipRect *r1, const TClipRect *r1End,
const TClipRect *r2, const TClipRect *r2End, int top, int bottom)
{
TClipRect *newcliprect;
int left;
left = r1->rc.left;
while ((r1 != r1End) && (r2 != r2End)) {
if (r2->rc.right <= left) {
/*
* Subtrahend missed the boat: go to next subtrahend.
*/
r2 = r2->next;
}
else if (r2->rc.left <= left)
{
/*
* Subtrahend preceeds minuend: nuke left edge of minuend.
*/
left = r2->rc.right;
if (left >= r1->rc.right)
{
/*
* Minuend completely covered: advance to next minuend and
* reset left fence to edge of new minuend.
*/
r1 = r1->next;
if (r1 != r1End)
left = r1->rc.left;
}
else
{
/*
* Subtrahend now used up since it doesn't extend beyond
* minuend
*/
r2 = r2->next;
}
}
else if (r2->rc.left < r1->rc.right)
{
/*
* Left part of subtrahend covers part of minuend: add uncovered
* part of minuend to region and skip to next subtrahend.
*/
NEWCLIPRECT(region, newcliprect);
newcliprect->rc.left = left;
newcliprect->rc.top = top;
newcliprect->rc.right = r2->rc.left;
newcliprect->rc.bottom = bottom;
left = r2->rc.right;
if (left >= r1->rc.right)
{
/*
* Minuend used up: advance to new...
*/
r1 = r1->next;
if (r1 != r1End)
left = r1->rc.left;
}
else
{
/*
* Subtrahend used up
*/
r2 = r2->next;
}
}
else
{
/*
* Minuend used up: add any remaining piece before advancing.
*/
if (r1->rc.right > left)
{
NEWCLIPRECT(region, newcliprect);
newcliprect->rc.left = left;
newcliprect->rc.top = top;
newcliprect->rc.right = r1->rc.right;
newcliprect->rc.bottom = bottom;
}
r1 = r1->next;
if (r1 != r1End)
left = r1->rc.left;
}
}
/*
* Add remaining minuend rectangles to region.
*/
while (r1 != r1End)
{
NEWCLIPRECT(region, newcliprect);
newcliprect->rc.left = left;
newcliprect->rc.top = top;
newcliprect->rc.right = r1->rc.right;
newcliprect->rc.bottom = bottom;
r1 = r1->next;
if (r1 != r1End)
left = r1->rc.left;
}
}
/***********************************************************************
* IntersectRegion
*/
void RegionIntersect(TREGION *dst, const TREGION *src1, const TREGION *src2)
{
/* check for trivial reject */
if ( (!(src1->head)) || (!(src2->head)) || (!IsRectOverlap(&src1->rcBound, &src2->rcBound)))
{ ClearRegion (dst);
}
else
{ REGION_RegionOp (dst, src1, src2, REGION_IntersectO, NULL, NULL);
REGION_SetExtents(dst);
dst->type = (dst->head) ? COMPLEXREGION : NULLREGION ;
}
}
/***********************************************************************
* SubtractRegion
*
* Subtract rgnS from rgnM and leave the result in rgnD.
* S stands for subtrahend, M for minuend and D for difference.
*
* Results:
* true.
*
* Side Effects:
* regD is overwritten.
*
*/
void RegionSubtract (TREGION *rgnD, const TREGION *rgnM, const TREGION *rgnS)
{
/* check for trivial reject */
if ( (!(rgnM->head)) || (!(rgnS->head)) || (!IsRectOverlap(&rgnM->rcBound, &rgnS->rcBound)) )
{ RegionCopy (rgnD, rgnM);
}
else
{ REGION_RegionOp (rgnD, rgnM, rgnS, REGION_SubtractO,REGION_SubtractNonO1, NULL);
REGION_SetExtents (rgnD);
rgnD->type = (rgnD->head) ? COMPLEXREGION : NULLREGION;
}
}
/***********************************************************************
* UnionRegion
*/
void RegionUnion (TREGION *dst, const TREGION *src1, const TREGION *src2)
{ int boundLeft,boundRight;
/* checks all the simple cases */
/*
* Region 1 and 2 are the same or region 1 is empty
*/
if ( (src1 == src2) || (!(src1->head)) )
{ if (dst != src2)
RegionCopy (dst, src2);
return;
}
/*
* if nothing to union (region 2 empty)
*/
if (!(src2->head))
{ if (dst != src1)
RegionCopy (dst, src1);
return;
}
/*
* Region 1 completely subsumes region 2
*/
if (src1->head == src1->tail && RectInRect(&src2->rcBound,&src1->rcBound) )
{ if (dst != src1)
RegionCopy (dst, src1);
return;
}
/*
* Region 2 completely subsumes region 1
*/
if (src2->head == src2->tail && RectInRect(&src1->rcBound,&src2->rcBound) )
{ if (dst != src2)
RegionCopy(dst, src2);
return;
}
boundLeft=min (src1->rcBound.left, src2->rcBound.left);
boundRight=max (src1->rcBound.right, src2->rcBound.right);
REGION_RegionOp (dst, src1, src2, REGION_UnionO, REGION_UnionNonO, REGION_UnionNonO);
dst->rcBound.left = boundLeft;
dst->rcBound.top = dst->head->rc.top;
dst->rcBound.right = boundRight;
dst->rcBound.bottom = dst->tail->rc.bottom;
dst->type = (dst->head) ? COMPLEXREGION : NULLREGION ;
}
/* XorRegion */
void RegionXor (TREGION *dst, const TREGION *src1, const TREGION *src2)
{
TREGION tmpa, tmpb;
InitRegion(&tmpa, src1->heap);
InitRegion(&tmpb, src2->heap);
RegionSubtract(&tmpa, src1, src2);
RegionSubtract(&tmpb, src2, src1);
RegionUnion(dst, &tmpa, &tmpb);
ClearRegion(&tmpa);
ClearRegion(&tmpb);
}
/* Adds a rectangle to a region */
void RegionUnionRect (TREGION *region, const TRECT *rect)
{ if (!IsRectEmpty(rect))
{ TREGION my_region;
TClipRect my_cliprect;
my_cliprect.rc = *rect;
my_cliprect.next = NULL;
my_cliprect.prev = NULL;
my_region.type = SIMPLEREGION;
my_region.rcBound = *rect;
my_region.head = &my_cliprect;
my_region.tail = &my_cliprect;
my_region.heap = NULL;
RegionUnion(region, region, &my_region);
}
}
/* Intersect a rect with a region */
void RegionIntersectRect (TREGION *region, const TRECT* rect)
{ if(IsRegionEmpty(region)) return;
if(!IsRectEmpty(rect) && IsRectOverlap(®ion->rcBound,rect) )
{ if(!RectInRect(®ion->rcBound,rect))
{ TREGION my_region;
TClipRect my_cliprect;
my_cliprect.rc = *rect;
my_cliprect.next = NULL;
my_cliprect.prev = NULL;
my_region.type = SIMPLEREGION;
my_region.rcBound = *rect;
my_region.head = &my_cliprect;
my_region.tail = &my_cliprect;
my_region.heap = NULL;
REGION_RegionOp(region, region, &my_region, REGION_IntersectO, NULL, NULL);
REGION_SetExtents(region);
region->type = (region->head) ? COMPLEXREGION : NULLREGION ;
}else return;
}
else
{ ClearRegion(region);
}
}
void RegionSubtractRect(TREGION *region, const TRECT* rect)
{ if(!IsRegionEmpty(region) && !IsRectEmpty(rect) && IsRectOverlap(®ion->rcBound,rect))
{ if(!RectInRect(®ion->rcBound,rect))
{ TREGION my_region;
TClipRect my_cliprect;
my_cliprect.rc = *rect;
my_cliprect.next = NULL;
my_cliprect.prev = NULL;
my_region.type = SIMPLEREGION;
my_region.rcBound = *rect;
my_region.head = &my_cliprect;
my_region.tail = &my_cliprect;
my_region.heap = NULL;
REGION_RegionOp(region, region, &my_region, REGION_SubtractO,REGION_SubtractNonO1, NULL);
REGION_SetExtents(region);
region->type = (region->head) ? COMPLEXREGION : NULLREGION;
}
else
{ ClearRegion(region);
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -