📄 xpol5.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 */
/* */
/* XPOL5.c 1.9 */
/* */
/* COMPONENT */
/* */
/* All */
/* */
/* DESCRIPTION */
/* */
/* This file contains the XSortAET, DrawBurst, ScanOutAET, mwSTQA, */
/* mwSBQA, mwSV, mwSLE, mwScanGET and four vectored stepping functions. */
/* */
/* AUTHOR */
/* */
/* Robert G. Burrill, Accelerated Technology, Inc. */
/* */
/* DATA STRUCTURES */
/* */
/* None */
/* */
/* FUNCTIONS */
/* */
/* None */
/* */
/* DEPENDENCIES */
/* */
/* None */
/* */
/* HISTORY */
/* */
/* NAME DATE REMARKS */
/* */
/* BobB 2/2/99 Corrected floating point divide */
/* GiacD 2/9/99 Added fixed-point math support */
/* */
/*************************************************************************/
#include "meta_wnd.h"
#include "metconst.h" /* MetaWINDOW Constant & Stucture Definitions */
#include "metports.h" /* MetaWINDOW Port & Bitmap Definitions */
#include "grafdata.h"
#include "metmacs3.h"
#include "xpol_4.h"
#include "xpol_5.h"
/* Function XSortAET sorts all edges currently in the active edge table into
ascending order of current X coordinates. */
void XSortAET(lineEdgeV **CurrentEdgePtr)
{
byte didSwap; /* flag that a swap occurred */
lineEdgeV *NextEdgePtr;
lineEdgeV *TempEdge;
lineEdgeV *newEdge;
lineEdgeV **tempCurrentEdgePtr;
/* scan through the AET and swap any adjacent edges for which the second
edge is at a lower current X coord than the first edge. Repeat until no
further swapping is needed. */
if (*CurrentEdgePtr == 0) return; /* skip if nothing in AET */
do {
didSwap = 0; /* mark that no swap has yet occurred */
newEdge = *CurrentEdgePtr;
tempCurrentEdgePtr = CurrentEdgePtr;
while ((NextEdgePtr = newEdge->NextEdge) != 0)
{ /*if there is no next edge after the current one, we've traversed
the entire list */
if (newEdge->CurrentX > NextEdgePtr->CurrentX)
{ /* the second edge has a lower X than the first; reconnect the
links so that the two edges switch order in the AET */
TempEdge = NextEdgePtr->NextEdge;
*tempCurrentEdgePtr = NextEdgePtr;
NextEdgePtr->NextEdge = newEdge;
newEdge->NextEdge = TempEdge;
didSwap = 1; /* mark that a swap occurred */
}
tempCurrentEdgePtr = &(*tempCurrentEdgePtr)->NextEdge;
newEdge = *tempCurrentEdgePtr;
}
} while (didSwap != 0);
return;
}
/* Function DrawBurst draws the current fill burst and clears the rect list. */
void DrawBurst(void)
{
lclFillRcd->blitCnt = rectCount; /* set the count field in the blitRcd */
lclFillRcd->blitDmap->prFill(lclFillRcd); /* draw filled rectangle */
rectCount = 0; /* reset the # of rects in the rect */
rectPtr = rectBase; /* the next rect goes at the start of the rect list */
sameAsLast = 0; /* the next line can't be treated as the same as this line,
because this line's rectangles aren't around any more */
return;
}
/* Function ScanOutAET draws the scan line described by the current AET at
the current Y coordinate, according to lclFillRule. */
void ScanOutAET(void *AETPtr)
{
sbyte sumTopToBottom; /* running total of TopToBottom/BottomToTop */
sbyte zeroCount; /* 0-count counter */
sbyte oneCount; /* 1-count counter */
byte zero_one; /* 0 or 1 count indicator */
short grafErrValue; /* error value */
int currentYP1; /* current Y + 1 */
Vedge *newEdge;
rect *tempLastScanPtr;
/* does this scan line have the same edges in the same locations as the
last scan line? */
if (sameAsLast == 1)
{ /* yes, so enlarge last time's rects */
tempLastScanPtr = lastScanPtr;
do { /* advance the end of the rects to the current scan line */
tempLastScanPtr->Ymax = currentY + 1; /* make it X-style */
tempLastScanPtr++; /* point to the next rect */
} while (tempLastScanPtr < rectPtr); /* continue if there are any
more rects */
return;
}
/* no, so assume that the next line has the same edges as this line */
sameAsLast = 1;
lastScanPtr = rectPtr; /* remember where this scan line's rect list starts */
newEdge = (Vedge *)AETPtr; /* set up pointer */
/* scan through the AET, building a rect list from the line segments as
each pair of edge crossings is encountered (or each matched pair, for the
winding rule). The nearest pixel on or to the right of left edges is drawn,
and the nearest pixel to the left of but not on right edges is drawn. */
currentYP1 = currentY + 1;
if (lclFillRule > 0) /* test kind of fill */
{ /* normal winding rule fill */
while (newEdge != 0)
{
rectPtr->Ymin = currentY; /* set start Y in rect */
rectPtr->Ymax = currentYP1; /* set end Y in rect */
rectPtr->Xmin = newEdge->CurrentX; /* set start X in rect */
sumTopToBottom = newEdge->TopToBottom; /* get the top->bottom
status for this edge */
/* scan across until equal numbers of up and down edges have been
crossed */
do {
newEdge = newEdge->NextEdge;
// if(newEdge == 0)
// break;
sumTopToBottom += newEdge->TopToBottom; /* get the top->bottom
status for this edge & update the running sum of top->bottom
and bottom->top edges*/
} while (sumTopToBottom != 0); /* keep going if the edge count hasn't
balanced yet */
//if(newEdge == 0)
// break;
rectPtr->Xmax = newEdge->CurrentX; /* set end X in rect */
rectCount++; /* count this rect */
if (rectPtr > highWater) /* is that all the rects that'll fit in */
{ /* the rect list? */
DrawBurst(); /* yes, so draw the burst and clear the rect list */
}
else
{
rectPtr++; /* point to the next rect */
}
newEdge = newEdge->NextEdge;
}
return;
}
if (lclFillRule == 0)
{ /* odd/even fill */
while (newEdge != 0)
{
rectPtr->Ymin = currentY; /* set start Y in rect */
rectPtr->Ymax = currentYP1; /* set end Y in rect */
rectPtr->Xmin = newEdge->CurrentX; /* set start X in rect */
newEdge = newEdge->NextEdge;
rectPtr->Xmax = newEdge->CurrentX; /* set end X in rect */
rectCount++; /* count this rect */
if (rectPtr > highWater) /* is that all the rects that'll fit in */
{ /* the rect list? */
DrawBurst(); /* yes, so draw the burst and clear the rect list */
}
else
{
rectPtr++; /* point to the next rect */
}
newEdge = newEdge->NextEdge;
}
return;
}
/* double winding rule fill (intersection of two sets of edges)
Scan out with double winding rule (counts 0 and 1 (called 0-count and
1-count) both have to be positive to draw; this gives the intersection of
two edge lists). Note that this can only handle a maximum of 256 stacked
(pending same-direction) edges of either type. */
zeroCount = 0; /* initialize 0-count and 1-count counters to 0 */
oneCount = 0;
do {
if (newEdge->countNumber == 0) /* is initial edge 0-count? */
{ /* We have an active 0-count; look for an active 1-count to start
drawing, or count the 0-count down to 0, to get back to the initial
condition. */
zeroCount = newEdge->TopToBottom;
ScanOutDoubleLoop0:
do {
newEdge = newEdge->NextEdge;
if (newEdge->countNumber == 1) /* 1-count? */
{ /* yes, we have a drawable area */
zero_one = 1; /* set indicator */
oneCount = newEdge->TopToBottom; /* set the 1-count */
goto ScanOutDoubleRecord;
}
/* no, 0-count; 1-count is still 0 */
zeroCount += newEdge->TopToBottom; /* update the 0-count
top->bottom status for this edge */
} while (zeroCount != 0); /* keep going if the edge count hasn't
balanced yet */
}
else
{ /* We have an active 1-count; look for an active 0-count to start
drawing, or count the 1-count down to 0, to get back to the initial
condition. */
oneCount = newEdge->TopToBottom;
ScanOutDoubleLoop1:
do {
newEdge = newEdge->NextEdge;
if (newEdge->countNumber == 0) /* 0-count? */
{ /* yes, we have a drawable area */
zero_one = 0; /* set indicator */
zeroCount = newEdge->TopToBottom; /* set the 0-count */
goto ScanOutDoubleRecord;
}
/* no, 1-count; 0-count is still 0 */
oneCount += newEdge->TopToBottom; /* update the 1-count
top->bottom status for this edge */
} while (oneCount != 0); /* keep going if the edge count hasn't
balanced yet */
}
/* both counts are down to 0; do we have any more edges to process? */
newEdge = newEdge->NextEdge;
} while (newEdge != 0);
return;
ScanOutDoubleRecord:
/* We were working with an active 0 or 1-count, and found the other count
edge; this is the start of a drawable area. Count the other count and start
looking for either count to go inactive. */
rectPtr->Ymin = currentY; /* set start Y in rect */
rectPtr->Ymax = currentYP1; /* set end Y in rect */
rectPtr->Xmin = newEdge->CurrentX; /* set start X in rect */
while (1)
{
if (newEdge == 0)
{
grafErrValue = c_FillPoly + 99;
nuGrafErr(grafErrValue); /* report error */
return;
}
newEdge = newEdge->NextEdge;
if (newEdge->countNumber == 1) /*1-count? */
{ /* update the 1-count top->bottom status for this edge */
oneCount += newEdge->TopToBottom;
zero_one = 1; /* set indicator */
}
else
{ /* update the 0-count top->bottom status for this edge */
zeroCount += newEdge->TopToBottom;
zero_one = 0; /* set indicator */
}
if ((zeroCount == 0) || (oneCount == 0)) break; /* stop if either count = 0 */
}
/* we've ended the 0/1-count span, so that's the end of the drawable span */
if (newEdge->CurrentX != rectPtr->Xmin) /* check if 0-width case? */
{ /* no */
rectPtr->Xmax = newEdge->CurrentX; /* set end X in rect */
rectCount++; /* count this rect */
if (rectPtr > highWater) /* is that all the rects that'll fit in */
{ /* the rect list? */
DrawBurst(); /* yes, so draw the burst and clear the rect list */
}
else
{
rectPtr++; /* point to the next rect */
}
}
/* we have only one active 0/1-count now; scan for other count or end of
this count */
if (zero_one == 0) goto ScanOutDoubleLoop1;
goto ScanOutDoubleLoop0;
}
/* Function mwScanGET scans and fills an edge list.
Parameters:
GETPtrPtr = far pointer to near pointer to first edge in global edge table
(the near pointer must be in the same segment as the GET, and the
pointer to the GET must be followed by space for a pointer to the
AET)
fillRcd = far pointer to start of fillRcd buffer (not filled out by caller;
filled out in this module)
scanRcdSize = # of bytes in fillRcd buffer, including space for the fillRcd
itself. Must be room for one blitRcd and at least one rect
shape = convex, nonconvex, or complex
fillRule = 0 if odd/even fill desired, 1 if winding fill desired, -1 if
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -