📄 regclip.c
字号:
/*************************************************************************/
/* */
/* Copyright (c) 1997 - 1999 Accelerated Technology, Inc. */
/* */
/* PROPRIETARY RIGHTS of Accelerated Technology are involved in the */
/* subject matter of this material. All manufacturing, reproduction, */
/* use, and sales rights pertaining to this subject matter are governed */
/* by the license agreement. The recipient of this software implicitly */
/* accepts the terms of the license. */
/* */
/*************************************************************************/
/*************************************************************************/
/* */
/* FILE NAME VERSION */
/* */
/* regclip.c 1.9 */
/* */
/* COMPONENT */
/* */
/* All */
/* */
/* DESCRIPTION */
/* */
/* This file contains the region clipping functions. */
/* */
/* AUTHOR */
/* */
/* Robert G. Burrill, Accelerated Technology, Inc. */
/* */
/* DATA STRUCTURES */
/* */
/* None */
/* */
/* FUNCTIONS */
/* */
/* None */
/* */
/* DEPENDENCIES */
/* */
/* None */
/* */
/* HISTORY */
/* */
/* NAME DATE REMARKS */
/* */
/* BobB 5/11/98 Corrected for drawing first line */
/* BobB 11/17/98 Corrected line clipping loop */
/* BobB 7/1/99 Corrected clipping error */
/* BobB 11/18/99 Corrected first/last status */
/* */
/*************************************************************************/
#include "meta_wnd.h"
#include "metconst.h" /* MetaWINDOW Constant & Stucture Definitions */
#include "metports.h" /* MetaWINDOW Port & Bitmap Definitions */
#include "metaproc.h"
#include "grafdata.h"
#include "regclipv.h"
/* Region-clipping functions. Variables required are in regclipv.h. Set
isLine = 1 to disable support for YX banded blitRecs. Set blitMayOverlap = 1
to enable set-up support for blits within the same bitmap that could
potentially overlap. If NO_REGION_CLIP is defined, Set_Up_Clip only sets
up rect clipping, flagging region clipping as off, and all region-clipping
routines are effectively no-oped, so region clipping is turned off (and the
code is shrunk, too). Note that this no-oping relies on clipToRegionFlag
never being turned on by Set_Up_Clip (*all* region code is not compiled if
NOT_REGION_CLIP is defined, with only a return), so if NOT_REGION_CLIP is
defined, clipToRegionFlag should always be left at 0. Check_YX_Band,
which doesn't require regions, stays the same. */
/* Function Blit_Clip_Region fills/blits a rectangle, clipped to a region,
processing the region from top->bottom, and left->right within each band for
the blit routines. Returns a 1 if YX banded and there are more rectangles
to draw, else 0.
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
nextRegionPtr must be set to the point at which to start scanning
through the region rect list (on exit, updated to start point for
scanning next time)
lclbfYXBanded must be set to !0 if the blitList of rects to draw is YX
banded, 0 otherwise (used to advance nextRegionPtr, and to exit
early when possible)
bXmin, bYmin, bXmax, bYmax, bandYmin, dYminTemp, dYmaxTemp, bsXmin, bsYmin,
bsXmax and bsYmax, sYminTemp and sYmaxTemp */
int Blit_Clip_Region(blitRcd *fcRec, rect *fillRect, rect *sRect)
{
#ifndef NO_REGION_CLIP
rect *regionRectPtr;
regionRectPtr = nextRegionPtr; /* point to the first region rect at
which to start clipping */
/* Find a region band not entirely above dest rect. */
while (fillRect->Ymin >= regionRectPtr->Ymax)
{
regionRectPtr++;
}
/* Start at this point next time if the blitRcd is YX banded. */
if (lclbfYXBanded != 0) nextRegionPtr = regionRectPtr;
/* Skip if the band is entirely below dest rect. */
if (fillRect->Ymax <= regionRectPtr->Ymin) goto BandFullyBelow;
/* So long as we're in a band that overlaps vertically with 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. */
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 */
do { /* clipping and drawing loop */
/* remember top edge of this YX band */
bandYmin = regionRectPtr->Ymin;
/* set Y extent of dest rect, clipped to the Y extent of this YX band */
if (bRect.Ymin < regionRectPtr->Ymin)
{
dYminTemp = regionRectPtr->Ymin;
sYminTemp = bsRect.Ymin - (bRect.Ymin - dYminTemp);
}
else
{
dYminTemp = bRect.Ymin;
sYminTemp = bsRect.Ymin;
}
if (bRect.Ymax > regionRectPtr->Ymax)
{
dYmaxTemp = regionRectPtr->Ymax;
sYmaxTemp = bsRect.Ymax - (bRect.Ymax - dYmaxTemp);
}
else
{
dYmaxTemp = bRect.Ymax;
sYmaxTemp = bsRect.Ymax;
}
/* skip region rects in this band that are fully to the left of
dest rect */
while (bRect.Xmin >= regionRectPtr->Xmax)
{
regionRectPtr++;
/* switch to next band if we just changed bands */
if (regionRectPtr->Ymin != bandYmin) goto BandBottom;
}
/* start clipping and drawing */
while (bRect.Xmax >= regionRectPtr->Xmin)
{
/* set the Y extent of the rectangle to draw (base rect clipped
to YX band) */
dRect.Ymin = dYminTemp;
dRect.Ymax = dYmaxTemp;
/* set the Y extent of the rectangle from which to draw (base
source rect clipped to YX band) */
sRect->Ymin = sYminTemp;
sRect->Ymax = sYmaxTemp;
if (bRect.Xmax > regionRectPtr->Xmax)
{
dRect.Xmax = regionRectPtr->Xmax;
sRect->Xmax = bsRect.Xmax - (bRect.Xmax - dRect.Xmax);
}
else
{
dRect.Xmax = bRect.Xmax;
sRect->Xmax = bsRect.Xmax;
}
if (bRect.Xmin < regionRectPtr->Xmin)
{
dRect.Xmin = regionRectPtr->Xmin;
sRect->Xmin = bsRect.Xmin - (bRect.Xmin - dRect.Xmin);
}
else
{
dRect.Xmin = bRect.Xmin;
sRect->Xmin = bsRect.Xmin;
}
/* fill the dest rect clipped to the region rect */
FillDrawer(fcRec);
regionRectPtr++;
/* switch to next band if we just changed bands */
if (regionRectPtr->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 {
regionRectPtr++;
} while (regionRectPtr->Ymin == bandYmin);
/* continue as long as the dest rect's bottom is below the region
rect's top (they overlap vertically) */
BandBottom:
/* remember top edge of this YX band */
bandYmin = regionRectPtr->Ymin;
} while (bRect.Ymax > bandYmin);
return(1); /* get next rectangle */
BandFullyBelow:
if (regionRectPtr->Ymin != 0x7fff) return(0);
if (lclbfYXBanded != 0) return(1);
#endif
return(0);
}
/* Function Fill_Clip_Region fills a rectangle, clipped to a region,
processing the region from top->bottom, and left->right within each band for
non-blit routines. Returns a 1 if YX banded and there are more rectangles
to draw, else 0.
Parameters:
fcRec = pointer to blitRcd
fillRect = pointer rect to draw, 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
nextRegionPtr must be set to the point at which to start scanning
through the region rect list (on exit, updated to start point for
scanning next time)
lclbfYXBanded must be set to !0 if the blitList of rects to draw is YX
banded, 0 otherwise (used to advance nextRegionPtr, and to exit
early when possible)
bXmin, bYmin, bXmax, bYmax, bandYmin, dYminTemp, dYmaxTemp, sYminTemp and
sYmaxTemp */
int Fill_Clip_Region(blitRcd *fcRec, rect *fillRect)
{
#ifndef NO_REGION_CLIP
rect *regionRectPtr;
regionRectPtr = nextRegionPtr; /* point to the first region rect at
which to start clipping */
/* Find a region band not entirely above dest rect. */
while (1)
{
if (fillRect->Ymin < regionRectPtr->Ymax) break;
regionRectPtr++;
}
/* Start at this point next time if the blitRcd is YX banded. */
if (lclbfYXBanded != 0) nextRegionPtr = regionRectPtr;
/* Skip if the band is entirely below dest rect. */
if (fillRect->Ymax <= regionRectPtr->Ymin) goto BandFullyBelow;
/* So long as we're in a band that overlaps vertically with 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. */
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 */
/* remember top edge of this YX band */
bandYmin = regionRectPtr->Ymin;
do { /* clipping and drawing loop */
/* set Y extent of dest rect, clipped to the Y extent of this YX band */
if (bRect.Ymin < regionRectPtr->Ymin)
{
dYminTemp = regionRectPtr->Ymin;
}
else
{
dYminTemp = bRect.Ymin;
}
if (bRect.Ymax > regionRectPtr->Ymax)
{
dYmaxTemp = regionRectPtr->Ymax;
}
else
{
dYmaxTemp = bRect.Ymax;
}
/* skip region rects in this band that are fully to the left of
dest rect */
while (bRect.Xmin >= regionRectPtr->Xmax)
{
regionRectPtr++;
/* switch to next band if we just changed bands */
if (regionRectPtr->Ymin != bandYmin) goto BandBottom;
}
/* start clipping and drawing */
while (bRect.Xmax >= regionRectPtr->Xmin)
{
/* set the Y extent of the rectangle to draw (base rect clipped
to YX band) */
dRect.Ymin = dYminTemp;
dRect.Ymax = dYmaxTemp;
if (bRect.Xmax > regionRectPtr->Xmax)
{
dRect.Xmax = regionRectPtr->Xmax;
}
else
{
dRect.Xmax = bRect.Xmax;
}
if (bRect.Xmin < regionRectPtr->Xmin)
{
dRect.Xmin = regionRectPtr->Xmin;
}
else
{
dRect.Xmin = bRect.Xmin;
}
/* fill the dest rect clipped to the region rect */
FillDrawer(fcRec);
regionRectPtr++;
/* switch to next band if we just changed bands */
if (regionRectPtr->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 {
regionRectPtr++;
} while (regionRectPtr->Ymin == bandYmin);
/* continue as long as the dest rect's bottom is below the region
rect's top (they overlap vertically) */
BandBottom:
/* remember top edge of this YX band */
bandYmin = regionRectPtr->Ymin;
} while (bRect.Ymax > bandYmin);
return(1); /* get next rectangle */
BandFullyBelow:
if (regionRectPtr->Ymin != 0x7fff) return(0);
if (lclbfYXBanded != 0) return(1);
#endif
return(0);
}
/* Function Set_Up_Clip sets up rectangular and/or region clipping as
specified by the blitRcd clipBlit.
Returns 1 if no drawing to do (region clip specified but region empty, or
both region and rectangular clip specified but rectangle and region extent
have no overlap) else 0.
The following regclipv.h common variables are required:
clipToRectFlag is set to 0 if no rect clipping, !0 if is rect clipping
clipToRegionFlag is set to 0 if no region clipping, !0 if is region
clipping
nextRegionPtr is set to point to the start of the region rect list
lclbfYXBanded is set to !0 if the blitList of rects to draw is
YX banded, 0 otherwise (used to advance nextRegionPtr, and to
exit early when possible)
clipR is set to the clip rect (intersection of clip rect and region
extent if both active)
if BLIT_MAY_OVERLAP is TRUE, nextRegionPtrB is set by this macro to
point to the end of the region rect list */
int Set_Up_Clip(blitRcd *clipBlit, rect *clipR, int blitMayOverlap,
int isLine)
{
if(isLine)
{
lclbfYXBanded = 0; /* lines are never YX banded */
}
else
{ /* 0 if not YX banded, !0 if is */
lclbfYXBanded = clipBlit->blitFlags & bfYXBanded;
}
clipToRectFlag = clipBlit->blitFlags & bfClipRect;
if (clipToRectFlag != 0)
{ /* rect clipping; copy over the clip rect */
*clipR = *clipBlit->blitClip;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -