📄 devrgn.c
字号:
*/
if (left < right)
{
MEMCHECK(pReg, pNextRect, pReg->rects);
pNextRect->left = left;
pNextRect->top = top;
pNextRect->right = right;
pNextRect->bottom = bottom;
pReg->numRects += 1;
pNextRect++;
}
/*
* Need to advance the pointers. Shift the one that extends
* to the right the least, since the other still has a chance to
* overlap with that region's next rectangle, if you see what I mean.
*/
if (r1->right < r2->right)
{
r1++;
}
else if (r2->right < r1->right)
{
r2++;
}
else
{
r1++;
r2++;
}
}
}
/***********************************************************************
* GdIntersectRegion
*/
void
GdIntersectRegion(MWCLIPREGION *newReg, MWCLIPREGION *reg1, MWCLIPREGION *reg2)
{
/* check for trivial reject */
if ( (!(reg1->numRects)) || (!(reg2->numRects)) ||
(!EXTENTCHECK(®1->extents, ®2->extents)))
newReg->numRects = 0;
else
REGION_RegionOp (newReg, reg1, reg2,
(voidProcp) REGION_IntersectO, (voidProcp) NULL, (voidProcp) 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 same. 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(newReg);
newReg->type = (newReg->numRects) ? MWREGION_COMPLEX : MWREGION_NULL ;
}
/***********************************************************************
* Region Union
***********************************************************************/
/***********************************************************************
* REGION_UnionNonO
*
* Handle a non-overlapping band for the union operation. Just
* Adds the rectangles into the region. Doesn't have to check for
* subsumption or anything.
*
* Results:
* None.
*
* Side Effects:
* pReg->numRects is incremented and the final rectangles overwritten
* with the rectangles we're passed.
*
*/
static void
REGION_UnionNonO(MWCLIPREGION *pReg,MWRECT *r,MWRECT *rEnd,MWCOORD top,
MWCOORD bottom)
{
MWRECT *pNextRect;
pNextRect = &pReg->rects[pReg->numRects];
while (r != rEnd)
{
MEMCHECK(pReg, pNextRect, pReg->rects);
pNextRect->left = r->left;
pNextRect->top = top;
pNextRect->right = r->right;
pNextRect->bottom = bottom;
pReg->numRects += 1;
pNextRect++;
r++;
}
}
/***********************************************************************
* REGION_UnionO
*
* Handle an overlapping band for the union operation. Picks the
* left-most rectangle each time and merges it into the region.
*
* Results:
* None.
*
* Side Effects:
* Rectangles are overwritten in pReg->rects and pReg->numRects will
* be changed.
*
*/
static void
REGION_UnionO(MWCLIPREGION *pReg, MWRECT *r1, MWRECT *r1End,
MWRECT *r2, MWRECT *r2End, MWCOORD top, MWCOORD bottom)
{
MWRECT *pNextRect;
pNextRect = &pReg->rects[pReg->numRects];
#define MERGERECT(r) \
if ((pReg->numRects != 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->rects); \
pNextRect->top = top; \
pNextRect->bottom = bottom; \
pNextRect->left = r->left; \
pNextRect->right = r->right; \
pReg->numRects += 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);
}
}
/***********************************************************************
* GdUnionRegion
*/
void
GdUnionRegion(MWCLIPREGION *newReg, MWCLIPREGION *reg1, MWCLIPREGION *reg2)
{
/* checks all the simple cases */
/*
* Region 1 and 2 are the same or region 1 is empty
*/
if ( (reg1 == reg2) || (!(reg1->numRects)) )
{
if (newReg != reg2)
GdCopyRegion(newReg, reg2);
return;
}
/*
* if nothing to union (region 2 empty)
*/
if (!(reg2->numRects))
{
if (newReg != reg1)
GdCopyRegion(newReg, reg1);
return;
}
/*
* Region 1 completely subsumes region 2
*/
if ((reg1->numRects == 1) &&
(reg1->extents.left <= reg2->extents.left) &&
(reg1->extents.top <= reg2->extents.top) &&
(reg1->extents.right >= reg2->extents.right) &&
(reg1->extents.bottom >= reg2->extents.bottom))
{
if (newReg != reg1)
GdCopyRegion(newReg, reg1);
return;
}
/*
* Region 2 completely subsumes region 1
*/
if ((reg2->numRects == 1) &&
(reg2->extents.left <= reg1->extents.left) &&
(reg2->extents.top <= reg1->extents.top) &&
(reg2->extents.right >= reg1->extents.right) &&
(reg2->extents.bottom >= reg1->extents.bottom))
{
if (newReg != reg2)
GdCopyRegion(newReg, reg2);
return;
}
REGION_RegionOp (newReg, reg1, reg2, (voidProcp) REGION_UnionO,
(voidProcp) REGION_UnionNonO, (voidProcp) REGION_UnionNonO);
newReg->extents.left = MWMIN(reg1->extents.left, reg2->extents.left);
newReg->extents.top = MWMIN(reg1->extents.top, reg2->extents.top);
newReg->extents.right = MWMAX(reg1->extents.right, reg2->extents.right);
newReg->extents.bottom = MWMAX(reg1->extents.bottom, reg2->extents.bottom);
newReg->type = (newReg->numRects) ? MWREGION_COMPLEX : MWREGION_NULL ;
}
/***********************************************************************
* 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:
* pReg may be affected.
*
*/
static void
REGION_SubtractNonO1(MWCLIPREGION *pReg, MWRECT *r, MWRECT *rEnd,
MWCOORD top, MWCOORD bottom)
{
MWRECT *pNextRect;
pNextRect = &pReg->rects[pReg->numRects];
while (r != rEnd)
{
MEMCHECK(pReg, pNextRect, pReg->rects);
pNextRect->left = r->left;
pNextRect->top = top;
pNextRect->right = r->right;
pNextRect->bottom = bottom;
pReg->numRects += 1;
pNextRect++;
r++;
}
}
/***********************************************************************
* REGION_SubtractO
*
* Overlapping band subtraction. x1 is the left-most point not yet
* checked.
*
* Results:
* None.
*
* Side Effects:
* pReg may have rectangles added to it.
*
*/
static void
REGION_SubtractO(MWCLIPREGION *pReg, MWRECT *r1, MWRECT *r1End,
MWRECT *r2, MWRECT *r2End, MWCOORD top, MWCOORD bottom)
{
MWRECT *pNextRect;
MWCOORD left;
left = r1->left;
pNextRect = &pReg->rects[pReg->numRects];
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->rects);
pNextRect->left = left;
pNextRect->top = top;
pNextRect->right = r2->left;
pNextRect->bottom = bottom;
pReg->numRects += 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->rects);
pNextRect->left = left;
pNextRect->top = top;
pNextRect->right = r1->right;
pNextRect->bottom = bottom;
pReg->numRects += 1;
pNextRect++;
}
r1++;
left = r1->left;
}
}
/*
* Add remaining minuend rectangles to region.
*/
while (r1 != r1End)
{
MEMCHECK(pReg, pNextRect, pReg->rects);
pNextRect->left = left;
pNextRect->top = top;
pNextRect->right = r1->right;
pNextRect->bottom = bottom;
pReg->numRects += 1;
pNextRect++;
r1++;
if (r1 != r1End)
{
left = r1->left;
}
}
}
/***********************************************************************
* GdSubtractRegion
*
* Subtract regS from regM and leave the result in regD.
* S stands for subtrahend, M for minuend and D for difference.
*
* Results:
* TRUE.
*
* Side Effects:
* regD is overwritten.
*
*/
void
GdSubtractRegion(MWCLIPREGION *regD, MWCLIPREGION *regM, MWCLIPREGION *regS )
{
/* check for trivial reject */
if ( (!(regM->numRects)) || (!(regS->numRects)) ||
(!EXTENTCHECK(®M->extents, ®S->extents)) )
{
GdCopyRegion(regD, regM);
return;
}
REGION_RegionOp (regD, regM, regS, (voidProcp) REGION_SubtractO,
(voidProcp) REGION_SubtractNonO1, (voidProcp) 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);
regD->type = (regD->numRects) ? MWREGION_COMPLEX : MWREGION_NULL ;
}
/***********************************************************************
* GdXorRegion
*/
void
GdXorRegion(MWCLIPREGION *dr, MWCLIPREGION *sra, MWCLIPREGION *srb)
{
MWCLIPREGION *tra, *trb;
if ((! (tra = GdAllocRegion())) || (! (trb = GdAllocRegion())))
return;
GdSubtractRegion(tra,sra,srb);
GdSubtractRegion(trb,srb,sra);
GdUnionRegion(dr,tra,trb);
GdDestroyRegion(tra);
GdDestroyRegion(trb);
}
#if 0
/***********************************************************************
* DumpRegion
* Outputs the contents of a MWCLIPREGION
*/
void
DumpRegion(MWCLIPREGION *pReg)
{
MWRECT *pRect, *pRectEnd = pReg->rects + pReg->numRects;
DPRINTF("Region %p: %d,%d - %d,%d %d rects\n", pReg,
pReg->extents.left, pReg->extents.top,
pReg->extents.right, pReg->extents.bottom, pReg->numRects);
for(pRect = pReg->rects; pRect < pRectEnd; pRect++)
DPRINTF("\t%d,%d - %d,%d\n", pRect->left, pRect->top,
pRect->right, pRect->bottom);
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -