📄 xpol6.c
字号:
return;
}
/* it's a Y-major (more vertical) edge */
/* restart vector for next time */
restartStrucPtr->restartVector = YMajorRestart;
restartStrucPtr->restartAE = deltaX;
restartStrucPtr->restartDE = advanceAmt;
restartStrucPtr->restartBR = height;
if (skipFirst == 1)
{ /* skip the first point */
errorTerm += deltaX;
if (errorTerm >= 0)
{ /* time for X coord to advance */
startX += advanceAmt;
errorTerm -= height;
}
numScans--;
}
YMajorLoopR:
while (numScans > 0)
{
scanListPtr->X = startX;
scanListPtr += 2;
errorTerm += deltaX;
if (errorTerm >= 0)
{ /* time for X coord to advance */
startX += advanceAmt;
errorTerm -= height;
}
numScans--;
}
restartStrucPtr->restartCE = errorTerm;
restartStrucPtr->restartSN = startX;
*scanListPtrPtr = scanListPtr; /* update pointer for next time */
return;
}
/* Function ScanBurst scans out edges for mwFC - updates pointer to
next vertex */
void ScanBurst(int scanCnt, int skipFirst, short xAdjust, char scanDir,
restartStruc *restartStrucPtr, point **scanListPtr,
point *currentVertex, short *currentXPtr, point *points, int mode)
{
int tempXDelta; /* used by previous mode code */
int tempYDelta = 0;
short startX = 0;
short endX = 0;
point *nextVertex;
int numScans; /* # of scan lines to scan out for edge when doing
restartable scanning */
nextVertex = currentVertex; /* get passed vertex pointer */
/* are we restarting this edge? */
if (restartStrucPtr->scanEdgeFirstPass == 1)
{ /* no, draw from the start, scan convert each line in the edge from
top to bottom, for as long as we have room to store the rects */
restartStrucPtr->restartVector = 0;
if (mode == coordModePrevious) /* which coord mode? */
{ /* coord mode is previous (relative) */
do {
if (scanDir == 1) /* scan in ascending order? */
{ /* yes, point to the next vertex */
nextVertex = nextVertex + 1;
if ((long) nextVertex == vertexListEnd)
{ /* wrap back to the start */
nextVertex = points;
/* first point is absolute */
tempXDelta = nextVertex->X - lastPointX;
tempYDelta = nextVertex->Y - lastPointY;
}
else
{
tempXDelta = nextVertex->X;
tempYDelta = nextVertex->Y;
}
}
else
{ /* no, point to previous vertex */
if (nextVertex == points)
{ /* at the top of the list */
nextVertex = (point *) vertexListEnd;
/* first point is absolute */
tempXDelta = lastPointX - nextVertex->X;
tempYDelta = lastPointY - nextVertex->Y;
}
else
{
tempXDelta = - nextVertex->X;
tempYDelta = - nextVertex->Y;
}
nextVertex = nextVertex - 1;
}
startX = *currentXPtr; /* absolute X of this vertex */
endX = startX + tempXDelta; /* absolute X of next vertex */
*currentXPtr = endX;
tempYDelta -= skipFirst; /* # of scan lines drawn for
this edge */
if (tempYDelta != 0) /* any rects to draw? */
{ /* do we have that much room? */
if ((tempYDelta < 0) || (tempYDelta > scanCnt))
{ /* no, we'll have to start and then suspend it */
/* undo earlier skipFirst to get true height */
scanCnt += skipFirst;
tempYDelta += skipFirst;
numScans = scanCnt;
/* # of scan lines left to process in this edge */
restartStrucPtr->restartRemaining = tempYDelta - scanCnt;
startX += xAdjust;
endX += xAdjust;
__mwScanEdgeRestart(startX, endX, (short) tempYDelta, scanListPtr,
skipFirst, restartStrucPtr, numScans);
return; /* done with this burst */
}
else
{ /* yes, we can draw this whole edge in a single
burst */
scanCnt -= tempYDelta; /* # of scan lines
available after this */
tempYDelta += skipFirst; /* undo earlier
skipFirst to get true height */
startX += xAdjust;
endX += xAdjust;
__mwScanEdge(startX, endX, (short) tempYDelta, scanListPtr,
skipFirst);
scanCnt += skipFirst;
}
}
SBPNextEdgeReentry:
skipFirst = 0; /* don't skip from now on */
/* did this edge exactly finish out the buffer or complete
the polygon? */
} while (scanCnt > 0);
return;
}
else
{ /* coord mode is origin (absolute) */
do {
startX = nextVertex->X; /* get previous coords */
tempYDelta = nextVertex->Y;
if (scanDir == 1) /* scan in ascending order? */
{ /* yes, point to the next vertex */
nextVertex = nextVertex + 1;
if ((long) nextVertex == vertexListEnd)
nextVertex = points;
}
else
{ /* no, point to previous vertex */
if (nextVertex == points)
{
nextVertex = (point *) vertexListEnd;
}
nextVertex = nextVertex - 1;
}
/* # of scan lines drawn for this edge */
endX = nextVertex->X; /* X of next vertex */
tempYDelta = nextVertex->Y - tempYDelta - skipFirst;
if (tempYDelta != 0) /* any rects to draw? */
{ /* do we have that much room? */
if ((tempYDelta < 0) || (tempYDelta > scanCnt))
{ /* no, we'll have to start and then suspend it */
/* undo earlier skipFirst to get true height */
scanCnt += skipFirst;
tempYDelta += skipFirst;
numScans = scanCnt;
/* # of scan lines left to process in this edge */
restartStrucPtr->restartRemaining = tempYDelta - scanCnt;
startX += xAdjust;
endX += xAdjust;
__mwScanEdgeRestart(startX, endX, (short) tempYDelta, scanListPtr,
skipFirst, restartStrucPtr, numScans);
return; /* done with this burst */
}
else
{ /* yes, we can draw this whole edge in a single
burst */
scanCnt -= tempYDelta; /* # of scan lines
available after this */
tempYDelta += skipFirst; /* undo earlier
skipFirst to get true height */
startX += xAdjust;
endX += xAdjust;
__mwScanEdge(startX, endX, (short) tempYDelta, scanListPtr,
skipFirst);
scanCnt += skipFirst;
}
}
SBNextEdgeReentry:
skipFirst = 0; /* don't skip from now on */
/* did this edge exactly finish out the buffer or complete
the polygon? */
} while (scanCnt > 0);
return;
}
}
else
{ /* yes, do we have that much room? */
if (restartStrucPtr->restartRemaining <= scanCnt)
{ /* yes, so draw whatever remains and move on to the next edge */
numScans = (int) restartStrucPtr->restartRemaining;
scanCnt -= numScans; /* # of scan lines available after this */
/* next time we're starting a new edge, not restarting this one */
restartStrucPtr->scanEdgeFirstPass = 1;
if (scanDir == 1) /* scan in ascending order? */
{ /* yes, point to the next vertex */
nextVertex = nextVertex + 1;
if ((long) nextVertex == vertexListEnd)
nextVertex = points;
}
else
{ /* no, point to previous vertex */
if (nextVertex == points)
{
nextVertex = (point *) vertexListEnd;
}
nextVertex = nextVertex - 1;
}
/* do the last restart */
__mwScanEdgeRestart(startX, endX, (short) tempYDelta, scanListPtr,
skipFirst, restartStrucPtr, numScans);
/* which coord mode? */
if (mode == coordModePrevious) goto SBPNextEdgeReentry;
goto SBNextEdgeReentry;
}
else
{ /* no, we'll have to restart and then suspend it again */
numScans = scanCnt;
/* # of scan lines left to process in this edge */
restartStrucPtr->restartRemaining -= scanCnt;
__mwScanEdgeRestart(startX, endX, (short) tempYDelta, scanListPtr,
skipFirst, restartStrucPtr, numScans);
return; /* done with this burst */
}
}
}
/* Function mwFC scans and draws a convex polygon. Intended for internal
use; doesn't check pnLevel.
Parameters:
lclScratchBufferPtr = far pointer to buffer in which to build rect list;
the buffer must have a filled-in blitRcd at the top. blitList is
filled out in this module. We don't just use the default blitRcd
because: a) this way the blitList and the blitRcd are both in the
same segment, and, b) this way a caller can fill a convex polygon in
any arbitrary bitmap
lclScratchBufferSize = # of bytes in lclScratchBufferPtr (64K-1 max).
Size includes the blitRcd at the top of the buffer
points = far pointer to vertex list
npoints = # of points in points vertex list (must be > 3)
mode = coordModeOrigin (coordinates are absolute) or coordModePrevious
(coordinates after the first are relative to the preceding one)
lclXAdjust = amount to add to X coordinates, used to perform local to
global coordinate conversion when needed, by being set to
portOrgn.X - portRect.Xmin; should be set to 0 if coordinates are
already in global coordinates
lclYAdjust = amount to add to Y coordinates, used to perform local to
global coordinate conversion when needed, by being set to
portOrgn.Y - portRect.Ymin; should be set to 0 if coordinates are
already in global coordinates
***IMPORTANT NOTES***
blitCnt and blitList are modified in the passed-in blitRcd, so this
should be a throwaway copy, not a permanent or reusable blitRcd.
Coordinates must be either global (in which case the adjust values
should be 0), or local with port origin = TOPBOT (in which case the
adjust values convert from local to global). Coordinates that are
virtual or coordinates with port origin != TOPBOT will not produce
proper results! */
void mwFC(byte *lclScratchBufferPtr, long lclScratchBufferSize,
point * points, int npoints, int mode,
long lclXAdjust, long lclYAdjust)
{
restartStruc leftRestartStruc; /* stores left edge scanning state
for edges that are too long to scan in one pass */
restartStruc rightRestartStruc; /* ditto for the right edge */
blitRcd *lclBlitRcdPtr; /* local bilt record pointer */
rect *scanListPtrR; /* offset of next free entry in rect list for
scanned out polygon */
point *scanListPtrP; /* above offset as a point pointer for X values */
point *scanListPtrPR; /* above offset as a point pointer for X values */
long maxRectCnt; /* maximum # of rect strucs that will fit into the
working buffer */
short minPoint_Y; /* lowest Y coord in polygon */
short maxPoint_Y; /* highest Y coord in polygon */
short minX; /* lowest X coord in poly */
short maxX; /* highest X coord in poly */
point relPoint; /* running total of relative points */
point *minIndexLPtr; /* pointer to point struc for leftmost point
with Y coord of minPoint_Y */
point *minIndexRPtr; /* pointer to point struc for rightmost point
with Y coord of minPoint_Y */
/* BobB 11/9/99 - removed the following variable since it is never used
point *maxIndexPtr; */ /* pointer to point struc for a point with Y coord
of maxPoint_Y */
point *lPoints; /* copy of points pointer */
point *tmpMinIndexPtr;
int topIsFlat; /* 1 if the top of the polygon is flat,
0 if it's pointed */
int currentYScan; /* Y coord of scan line we're currently processing */
int polyScans; /* # of scan lines in polygon */
int skipFirstL; /* 1 to skip top scan line on left edge */
int skipFirstR; /* likewise for right edge */
char leftEdgeDir; /* 1 if left edge runs up through vertex list,
-1 if it runs down */
char skipFill; /* 1 to skip filling a given burst of scan lines,
0 to fill */
short leftEdgeStartX; /* in previous mode X coordinates of first point */
short rightEdgeStartX; /* on each edge */
short deltaXN;
short deltaYN;
short deltaXP;
short deltaYP;
long deltaXPYN;
long deltaXNYP;
rect clpR; /* Clip rect */
char rectClipFlag; /* local copy of rectclip flag in the blitRcd */
int i;
/* set the blitList pointer */
lclBlitRcdPtr = (blitRcd *) ((long) lclScratchBufferPtr);
/* BobB 10/2/98 - corrected the following line to keep from overwriting blitRcd
lclBlitRcdPtr->blitList = (long) (lclBlitRcdPtr + 1); */
lclBlitRcdPtr->blitList = (long) (lclBlitRcdPtr) + sizeof(blitRcd);
/* copy clipping flags and clip rect (if enabled) to local vars
***region clipping is ignored at this level***/
rectClipFlag = lclBlitRcdPtr->blitFlags & bfClipRect;
if (rectClipFlag)
{
clpR.Xmin = lclBlitRcdPtr->blitClip->Xmin;
clpR.Xmax = lclBlitRcdPtr->blitClip->Xmax;
clpR.Ymin = lclBlitRcdPtr->blitClip->Ymin;
clpR.Ymax = lclBlitRcdPtr->blitClip->Ymax;
}
/* scan the list to find the top and bottom of the polygon & figure out
how many rects we can handle at time */
maxRectCnt = (lclScratchBufferSize - sizeof(blitRcd)) / sizeof(rect);
if (maxRectCnt <= 0) return; /* return if buffer not big enough */
relPoint = *points; /* get first point */
minX = relPoint.X; /* initial min and max X coords */
maxX = minX;
minPoint_Y = relPoint.Y; /* initial min and max Y coords */
maxPoint_Y = minPoint_Y;
minIndexLPtr = points; /* initial minIndexLPtr */
/* BobB 11/9/99 - removed the following line since maxIndexPtr is never used
maxIndexPtr = points; */ /* initial maxIndexPtr */
leftEdgeStartX = points->X; /* X coord of the initial Ymin point */
lPoints = points; /* get original pointer */
lPoints++; /* point to the next vertex */
npoints--; /* count off first point, which we've already done */
if (mode == coordModePrevious) /* which coord mode? */
{ /* coord mode is previous (relative) */
for (; npoints >= 1; npoints--)
{
relPoint.X += lPoints->X; /* get the next vertex's X & Y coords */
relPoint.Y += lPoints->Y; /* as deltas from the last vertex and check min/max */
if (relPoint.X < minX)
{
minX = relPoint.X;
}
else
{
if (relPoint.X > maxX) maxX = relPoint.X;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -