📄 regclip.c
字号:
#ifdef NO_REGION_CLIP
clipToRegionFlag = 0; /* 0 if not clip to region */
return(0);
#else /* 0 if not clip to region, 1 if is */
clipToRegionFlag = clipBlit->blitFlags & bfClipRegn;
if (clipToRegionFlag == 0) return(0);
/* region clipping; set up parameters */
#ifdef FIXUP386
#define gmDllFixup (long)mapAltMgr
#endif
if (blitMayOverlap)
{ /* point to the last rect in the region list */
nextRegionPtrB = clipBlit->blitRegn->rgnListEnd;
#ifdef FIXUP386
nextRegionPtrB += (rect *)(gmDllFixup + (long)clipBlit->blitDmap);
#endif
}
nextRegionPtr = clipBlit->blitRegn->rgnList;
#ifdef FIXUP386
nextRegionPtr += (rect *)(gmDllFixup + (long)clipBlit->blitDmap);
#endif
/* if the first region rect is the end-of-region rect, then there are
no active region rects and we're done */
if (nextRegionPtr->Ymin == 0x07fff) return(1);
if (clipToRectFlag == 0)
{ /* there is no rect clipping, so make the region extent the clip rect */
*clipR = clipBlit->blitRegn->rgnRect;
clipToRectFlag = 1; /* we'll clip to the region extent rect as if
it were a normal clip rect */
return(0);
}
/* rect clipping so improve efficiency by trimming the clip rect to the
region extent, and/or trimming the region to the clip rect */
if (clipR->Xmin < clipBlit->blitRegn->rgnRect.Xmin)
clipR->Xmin = clipBlit->blitRegn->rgnRect.Xmin;
if (clipBlit->blitRegn->rgnRect.Ymin >= clipR->Ymin)
{
clipR->Ymin = clipBlit->blitRegn->rgnRect.Ymin;
}
else
{
if (clipR->Ymin == 0x7fff) return(1);
/* there's no way anything can be drawable with this clip rect;
at least part of the region is off the top of the clip rect,
so advance the region pointer to the first region rect that
isn't fully clipped off the top */
while (nextRegionPtr->Ymax <= clipR->Ymin)
{
nextRegionPtr++;
}
}
if (clipR->Xmax > clipBlit->blitRegn->rgnRect.Xmax)
clipR->Xmax = clipBlit->blitRegn->rgnRect.Xmax;
if (clipBlit->blitRegn->rgnRect.Ymax <= clipR->Ymax)
{
clipR->Ymax = clipBlit->blitRegn->rgnRect.Ymax;
}
else
{
if (blitMayOverlap)
/* advance (backwards) the region-end pointer to the first region
rect going backwards that isn't fully clipped off the bottom */
while (nextRegionPtrB->Ymin >= clipR->Ymax)
{
nextRegionPtrB--;
}
/* no need for overlap checking, since we already did that going
in the other direction */
}
/* done if there's no overlap between the clip rect and the region
extent */
if ((clipR->Xmin >= clipR->Xmax) || (clipR->Ymin >= clipR->Ymax))
return(1);
#endif
return(0);
}
/* Function Check_YX_Band_Blit checks to see whether the rectangle was
trivially clipped because it was fully below the clip rect, in which
case we can discard the rest of a YX banded blitList, or because it
was fully above the clip rect, in which case we can whiz ahead through
a YX banded blitList until we run out of rects or find a rect that
isn't fully above the clip rect.
Returns 1 if done with checking; else 0.
The following regclipv.h common variables must be set on entry:
lclbfYXBanded = !0 if the blitList of rects to draw is YX banded, 0
otherwise (used to advance nextRegionPtr, and to exit early when
possible) */
int Check_YX_Band_Blit(rect *bandRect, rect *blitRectPtr, rect *clipR,
int *rectCnt)
{
/* BobB 7/1/99 - removed the following three lines to correct clipping
error at top and bottom of screen */
/* first, just finish if there are no more rects */
/**rectCnt -= 1; */ /* count off rects */
/*if (*rectCnt < 0) return(1); */ /* done if no more rects */
if (lclbfYXBanded == 0) return(0); /* can't do anything clever;
blitList is YX banded */
if (bandRect->Ymin >= clipR->Ymax) return(1); /* the rest of the
blitList is also below and we're done */
if (bandRect->Ymax > clipR->Ymin) return(0);
/* dest rect is fully above the clip rect, so skip ahead until the
dest rect does overlap the clip rect or we run out of rects */
while ((blitRectPtr + 1)->Ymax <= clipR->Ymin)
{
*rectCnt -= 1; /* count off rects */
if (*rectCnt < 0) return(1); /* done if no more rects */
blitRectPtr += 2; /* point to next rect pair in blitList */
}
return(0);
}
/* Function Check_YX_Band checks to see whether the rectangle was
trivially clipped because it was fully below the clip rect, in which
case we can discard the rest of a YX banded blitList, or because it
was fully above the clip rect, in which case we can whiz ahead through
a YX banded blitList until we run out of rects or find a rect that
isn't fully above the clip rect.
** This function is for the non-blit case.
Returns 1 if done with checking; else 0.
The following regclipv.h common variables must be set on entry:
lclbfYXBanded = !0 if the blitList of rects to draw is YX banded, 0
otherwise (used to advance nextRegionPtr, and to exit early when
possible) */
int Check_YX_Band(rect *bandRect, rect *blitRectPtr, rect *clipR,
int *rectCnt)
{
/* BobB 7/1/99 - removed the following three lines to correct clipping
error at top and bottom of screen */
/* first, just finish if there are no more rects */
/**rectCnt -= 1; */ /* count off rects */
/*if (*rectCnt < 0) return(1); */ /* done if no more rects */
if (lclbfYXBanded == 0) return(0); /* can't do anything clever;
blitList is YX banded */
if (bandRect->Ymin >= clipR->Ymax) return(1); /* the rest of the
blitList is also below and we're done */
if (bandRect->Ymax > clipR->Ymin) return(0);
/* dest rect is fully above the clip rect, so skip ahead until the
dest rect does overlap the clip rect or we run out of rects */
while (blitRectPtr->Ymax <= clipR->Ymin)
{
*rectCnt -= 1; /* count off rects */
if (*rectCnt < 0) return(1); /* done if no more rects */
blitRectPtr++; /* point to next rect in blitList */
}
return(0);
}
/* Function Line_Clip_Region draws a line list, clipped to a region.
This is a self-contained loop.
The following regclipv.h common variables are required:
LineDrawer = the routine to draw the clipped line
nextRegionPtr must be set to the point at which to start scanning
through the region rect list
bXmin, bYmin, bXmax, bYmax, bcXmin, bcYmin, bcXmax, bcYmax, cdXmin,
cdYmin, cdXmax, cdYmax and bandYmin */
void Line_Clip_Region(int rectCnt, lineS *listPtr)
{
#ifndef NO_REGION_CLIP
rect *lclRectPtr;
/* BobB 5/11/98 - corrected the following line to draw the last line
while (--rectCnt > 0) */
while (--rectCnt >= 0)
{
/* BobB 11/18/99 - corrected the following line to draw the first/last status
bDrawStat = (char ) listPtr->flStat; */ /* get the draw first/last
status */
drawStat = (char ) listPtr->flStat; /* get the draw first/last
status */
dRect.Xmin = listPtr->lStart.X;
dRect.Ymin = listPtr->lStart.Y;
dRect.Xmax = listPtr->lEnd.X;
dRect.Ymax = listPtr->lEnd.Y;
listPtr++; /* point to the next line to draw */
/* make a copy of the dest rect, because the low level alters the
standard copy each time we clip it to a region rect */
bRect = dRect;
/* put the limits in standard rect format (upper left->lower right) */
if (dRect.Xmin > dRect.Xmax)
{
dRect.Xmin = dRect.Xmax;
dRect.Xmax = bRect.Xmin;
}
if (dRect.Ymin > dRect.Ymax)
{
dRect.Ymin = dRect.Ymax;
dRect.Ymax = bRect.Ymin;
}
/* clip the dest rect to the clip rect, for use in calculating
region overlap (both are in old-style MW) */
if (dRect.Xmin < bcXmin) dRect.Xmin = bcXmin;
if (dRect.Ymin < bcYmin) dRect.Ymin = bcYmin;
if (dRect.Xmax > bcXmax) dRect.Xmax = bcXmax;
if (dRect.Ymax > bcYmax) dRect.Ymax = bcYmax;
/* BobB 11/17/98 - corrected the following two lines to go to next rectangle */
/*if (dRect.Xmin > dRect.Xmax) break;*/ /* line is fully clipped by clip rect */
/*if (dRect.Ymin > dRect.Ymax) break;*/ /* line is fully clipped by clip rect */
if (dRect.Xmin > dRect.Xmax) continue; /* line is fully clipped by clip rect */
if (dRect.Ymin > dRect.Ymax) continue; /* line is fully clipped by clip rect */
dRect.Xmax++; /* convert to X-style rect */
dRect.Ymax++;
cdXmin = dRect.Xmin;
cdYmin = dRect.Ymin;
cdXmax = dRect.Xmax;
cdYmax = dRect.Ymax;
lclRectPtr = nextRegionPtr; /* point to the first region rect at
which to start clipping */
/* Find a region band not entirely above clipped dest rect */
while (dRect.Ymin >= lclRectPtr->Ymax)
{
lclRectPtr++;
}
/* BobB 11/17/98 - corrected the following line to go to next rectangle */
/*if (lclRectPtr->Ymin > dRect.Ymax) break;*/ /* the band is fully below
dest rect so there's no possible overlap */
if (lclRectPtr->Ymin > dRect.Ymax) continue; /* the band is fully below
dest rect so there's no possible overlap */
/* So long as we're in a band that overlaps vertically with the
clipped destRect, scan across from the left until we find a region
rect that overlaps horizontally or we move to another band, then
draw destRect clipped to each region rect until we either find a
region rect that doesn't overlap or we move to another band, then
scan until we move to another band. If the next band isn't past
the bottom of destRect, repeat. */
/* remember top edge of this YX band */
bandYmin = lclRectPtr->Ymin;
do{
/* set Y extent of dest rect, clipped to the Y extent of this
band */
if (lclRectPtr->Ymin >= cdYmin)
{
cRect.Ymin = lclRectPtr->Ymin;
}
else
{
cRect.Ymin = cdYmin;
}
if (lclRectPtr->Ymax <= cdYmax)
{
cRect.Ymax = lclRectPtr->Ymax;
}
else
{
cRect.Ymax = cdYmax;
}
cRect.Ymax--; /* convert from X-style to old MW style, which the
clip and draw code expects */
/* skip region rects in this band that are fully to the left
of dest rect */
while (cdXmin >= lclRectPtr->Xmax)
{
lclRectPtr++;
/* switch to next band if we just changed bands */
if (lclRectPtr->Ymin != bandYmin) goto BandBottom;
}
/* start clipping and drawing */
while (cdXmax > lclRectPtr->Xmin)
{
if (cdXmax <= lclRectPtr->Xmax)
{
cRect.Xmax = cdXmax;
}
else
{
cRect.Xmax = lclRectPtr->Xmax;
}
cRect.Xmax--; /* convert from X-style to old MW style,
which the clip and draw code expects */
if (cdXmin >= lclRectPtr->Xmin)
{
cRect.Xmin = cdXmin;
}
else
{
cRect.Xmin = lclRectPtr->Xmin;
}
/* the region rect intersect clip rect intersect line =
effective clipping rect is all set */
dRect = bRect; /* get back the line to draw */
LineDrawer(); /* draw the line clipped to clip rect
intersect region rect */
lclRectPtr++;
/* switch to next band if we just changed bands */
if (lclRectPtr->Ymin != bandYmin) goto BandBottom;
}
/* skip region rects in this band that are fully to the right
of dest rect;; basically, scan to the next YX band */
do {
lclRectPtr++;
}while (lclRectPtr->Ymin == bandYmin);
BandBottom: /* continue as long as the dest rect's bottom is below the
region rect's top (they overlap vertically) */
/* remember top edge of this YX band */
bandYmin = lclRectPtr->Ymin;
}while (cdYmax > bandYmin);
} /* back for the next line */
#endif
return;
}
/* Function Blit_Clip_Region_BT_RL fills/blits a rectangle, clipped to a
region, processing the region from bottom->top, and right->left within
each band for the blit routines.
Parameters:
fcRec = pointer to blitRcd
fillRect = pointer rect to draw, already clipped to the clip rect
sRect = pointer rect to draw from, already clipped to the clip rect; Ymin
must be less than 0x7fff
The following regclipv.h common variables are required:
FillDrawer = routine to call to draw each region-clipped rect
nextRegionPtrB must be set to the point at which to start scanning
backward through the region rect list (on exit, updated to start
point for scanning next time)
bXmin, bYmin, bXmax, bYmax, bandYmin, dYminTemp, dYmaxTemp, bsXmin, bsYmin,
bsXmax and bsYmax, sYminTemp and sYmaxTemp */
void Blit_Clip_Region_BT_RL(blitRcd *fcRec, rect *fillRect, rect *sRect)
{
#ifndef NO_REGION_CLIP
rect *regionRectPtr;
regionRectPtr = nextRegionPtrB; /* point to the first region rect at
which to start clipping */
/* Find a region band not entirely below dest rect. */
while (fillRect->Ymax <= regionRectPtr->Ymin)
{
regionRectPtr--;
}
/* Skip if the band is entirely above dest rect. */
if (fillRect->Ymin >= regionRectPtr->Ymax) return;
/* So long as we're in a band that overlaps vertically with destRect,
scan across from the right until we find a region rect that overlaps
horizontally or we move to another band, then draw destRect clipped
to each region rect until we either find a region rect that doesn't
overlap or we move to another band, then scan until we move to another
band. If the next band isn't past the top of destRect, repeat. */
bRect = *fillRect; /* make a copy of dest rect, because we're going
to alter the standard copy each time we clip it
to a region rect */
bsRect = *sRect; /* likewise, make a copy of the source rect */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -