📄 xpol7.c
字号:
newAETPtrPtr = AETPtrPtr;
while ((AETPtr = *newAETPtrPtr) != 0) /* skip if nothing in AET */
{
AETPtr->Count--; /* decrement the y counter */
if (AETPtr->Count == 0) /* check if done with edge */
{ /* Yes, remove it from the AET. If it's not the edge
nearest the high water mark, copy the edge nearest the
high water mark into the hole and relink it; then move
the high water mark up one edge */
sameAsLast = 0;
*newAETPtrPtr = AETPtr->NextEdge;
tmpAETPtrPtr = newAETPtrPtr;
/* now, if there's an edge at the high water mark, move
it into the hole we just made */
/* point to the lowest address at which an edge could start */
tmpHighWater = (lineEdgeV *) ((long) (highWater + 2));
if (AETPtr != tmpHighWater) /* was the edge we just removed */
{ /* the one at the high water mark? */
tmpAETPtr = *AETPtrPtr; /* no need to check for NULL
pointer; if there was only one edge in the AET and
we just removed it, it would have been at the high
water mark and we'd never get here */
newAETPtrPtr = AETPtrPtr;
while (tmpAETPtr != tmpHighWater)
{
newAETPtrPtr = &tmpAETPtr->NextEdge;
tmpAETPtr = *newAETPtrPtr;
}
if (tmpAETPtr == (lineEdgeV *) tmpAETPtrPtr) /* was the */
{ /* last edge the one we're moving? */
tmpAETPtrPtr = (lineEdgeV **) AETPtr; /* remember
the edge's new location */
}
*newAETPtrPtr = AETPtr; /* relink the edge at its new
location */
newAETPtrPtr = (lineEdgeV **) AETPtr;
*AETPtr = *tmpAETPtr; /* move the data */
}
/* adjust the high water mark for the extra room we just
made available */
highWater = (rect *) (((long) highWater) + sizeof(lineEdgeV));
newAETPtrPtr = tmpAETPtrPtr;
}
else
{ /* count off one scan line for this edge */
if (AETPtr->WholePixelXMoveV != 0)
{ /* advance the edge's X coordinate by the minimum
# of pixels */
sameAsLast = 0;
AETPtr->CurrentX += (short) AETPtr->WholePixelXMoveV;
}
AETPtr->ErrorTermV += AETPtr->ErrorTermAdjUpV;
if (AETPtr->ErrorTermV > 0)
{ /* the error term turned over, so move X one more */
sameAsLast = 0;
AETPtr->CurrentX += (short) AETPtr->XDirection;
AETPtr->ErrorTermV -= AETPtr->ErrorTermAdjDownV;
}
newAETPtrPtr = &AETPtr->NextEdge;
}
}
XSortAET(AETPtrPtr); /* X sort the AET */
numLinesUntilNext--;
if (numLinesUntilNext == 0) /* time to add another edge to the AET? */
{
AddEdges: /* jump inside this loop the first time */
numLinesUntilNext = 0x7fff; /* max value so will always be replaced
by correct value if there is a next edge to start; otherwise,
counts down for the remainder of this fill (no more edges
to start) */
/* restore the previously saved data for the next GET build */
lclNpointsparm = saveLclNpointsparm;
vertexListPtr = saveVertexListPtr;
buf1Ptr = saveBuf1Ptr;
addEdgeVector = &AddEdgeToAET; /* routine called to add each
edge to the AET */
if (updateAETVector() == 0) /* add to the AET all edges that start */
{ /* at the current scan line, and set new numLinesUntilNext */
grafErrValue = c_PolyLine + c_EdgeOflo; /* there isn't even */
nuGrafErr(grafErrValue); /* enough memory to hold the AET */
return;
}
}
if ((AETPtr = *AETPtrPtr) != 0)
{
ScanOutAET(AETPtr); /* do winding rule scan out for this scan line */
}
currentY++; /* continue if we haven't done the bottom line yet */
} while (currentY <= maxY);
if (rectCount != 0) /* do any rects remain? */
{ /* yes, do the remaining rects */
lclFillRcd->blitCnt = rectCount; /* set the count field */
lclFillRcd->blitDmap->prFill(lclFillRcd); /* draw the rectangles */
}
return;
}
/* Function BuildSquareWidePenPolyLineGET builds a global edge table from
the point list for a square, wide pen. The GET is a linked list, sorted
first by Y coordinate, then by X coordinate.
Returns 1 for success, 0 for failure (insufficient memory). */
short BuildSquareWidePenPolyLineGET(void)
{
#define PEN_LEFT 0
#define PEN_RIGHT 1
#define PEN_UP 2
#define PEN_DOWN 3
/* For various directions, offset directions to corners of square pen at
which the edges parallel to the ideal line start and end. */
byte StartEndSetTable[8][8] = {
PEN_LEFT, PEN_DOWN, PEN_LEFT, PEN_UP, /* Dir0StartEnd */
PEN_RIGHT, PEN_UP, PEN_RIGHT, PEN_DOWN,
PEN_LEFT, PEN_UP, PEN_LEFT, PEN_UP, /* Dir1StartEnd */
PEN_RIGHT, PEN_DOWN, PEN_RIGHT, PEN_DOWN,
PEN_LEFT, PEN_UP, PEN_RIGHT, PEN_UP, /* Dir2StartEnd */
PEN_RIGHT, PEN_DOWN, PEN_LEFT, PEN_DOWN,
PEN_RIGHT, PEN_UP, PEN_RIGHT, PEN_UP, /* Dir3StartEnd */
PEN_LEFT, PEN_DOWN, PEN_LEFT, PEN_DOWN,
PEN_RIGHT, PEN_UP, PEN_RIGHT, PEN_DOWN, /* Dir4StartEnd */
PEN_LEFT, PEN_DOWN, PEN_LEFT, PEN_UP,
PEN_RIGHT, PEN_DOWN, PEN_RIGHT, PEN_DOWN, /* Dir5StartEnd */
PEN_LEFT, PEN_UP, PEN_LEFT, PEN_UP,
PEN_RIGHT, PEN_DOWN, PEN_LEFT, PEN_DOWN, /* Dir6StartEnd */
PEN_LEFT, PEN_UP, PEN_RIGHT, PEN_UP,
PEN_LEFT, PEN_DOWN, PEN_LEFT, PEN_DOWN, /* Dir7StartEnd */
PEN_RIGHT, PEN_UP, PEN_RIGHT, PEN_UP};
int xDirection;
int yDirection;
int directionDifference;
point *vrtxListPtr; /* local copy of vertexListPtr for wrap back */
rawLastX = vertexListPtr->X; /* remember this X,Y for next time */
rawLastY = vertexListPtr->Y;
vrtxListPtr = vertexListPtr;
if (globalLevel > 0) /* already in global? */
{ /* no, convert to global */
U2GP(rawLastX, rawLastY, &startX, &startY, 1);
}
else
{
startX = rawLastX;
startY = rawLastY;
}
firstSegment = 1; /* mark that this is the first line segment */
do {
if(lclNpointsparm == 1) /* is this the last vertex? */
{ /* yes, so potentially wrap back to the first point. Also
remember where the last point of the polyline is, in both
user and global coords, for advancing the pen location at
the end. This point is always reached at least once, even
when polyline drawing fails, and isn't reached until the
last point */
if (finalWrap != 1) /* do we wrap back from the end to the start? */
{ /* no, so we're done */
finalRawX = rawLastX; /* remember where the pen */
finalRawY = rawLastY; /* location advances to when */
finalGblX = startX; /* we're done */
finalGblY = startY;
break;
}
/* wrap back to the start of the vertex list */
/* load the endpoint of this segment and convert it
to global coords */
finalRawX = vertexListPtr->X;
finalRawY = vertexListPtr->Y;
if (globalLevel > 0) /* already in global? */
{ /* no, convert to global */
U2GP(finalRawX, finalRawY, &finalGblX, &finalGblY, 1);
}
else
{
finalGblX = finalRawX;
finalGblY = finalRawY;
}
}
else
{
vrtxListPtr++; /* point to next vertex */
if (lclModeparm == coordModePrevious) /* previous mode? */
{ /* yes, calculate new position as a delta from the
last X,Y in user coordinates */
rawLastX += vrtxListPtr->X;
rawLastY += vrtxListPtr->Y;
}
else
{
rawLastX = vrtxListPtr->X;
rawLastY = vrtxListPtr->Y;
}
if (globalLevel > 0) /* already in global? */
{ /* no, convert to global */
U2GP(rawLastX, rawLastY, &endX, &endY, 1);
}
else
{
endX = rawLastX;
endY = rawLastY;
}
}
xDirection = endX - startX;
yDirection = endY - startY;
if (xDirection == 0)
{ /* vertical direction */
/* BobB 5/19/99 - corrected the following line to continue to next point
if (yDirection == 0) break; */ /* no movement */
if (yDirection == 0)
continue; /* no movement */
if (yDirection < 0)
direction = 0; /* straight up */
else
direction = 4; /* straight down */
}
else
{
if (xDirection < 0)
{ /* moving left */
if (yDirection == 0)
direction = 6; /* straight left */
if (yDirection < 0)
direction = 7; /* up and to the left */
else
direction = 5; /* down and to the left */
}
else
{
if (yDirection == 0)
direction = 2; /* straight right */
if (yDirection < 0)
direction = 1; /* up and to the right */
else
direction = 3; /* down and to the right */
}
}
/* build the two edges that are parallel to the ideal line */
/*start->end edge start X */
startOutX = startX + halfWidth[StartEndSetTable[direction][0]];
/*start->end edge start Y */
startOutY = startY + halfWidth[StartEndSetTable[direction][1]];
/*start->end edge end X */
endInX = endX + halfWidth[StartEndSetTable[direction][2]];
/*start->end edge end Y */
endInY = endY + halfWidth[StartEndSetTable[direction][3]];
/* add start->end edge and check if enough memory */
addStartX = startOutX;
addStartY = startOutY;
addEndX = endInX;
addEndY = endInY;
if (addEdgeVector() != 1)
return(0); /* fail if return */
/* BobB 6/4/99 - corrected the following lines for table values */
/*end->start edge start X */
/* startInX = startX + halfWidth[StartEndSetTable[direction][4]]; */
/*end->start edge start Y */
/* startInY = startY + halfWidth[StartEndSetTable[direction][5]]; */
/*end->start edge end X */
/* endOutX = endX + halfWidth[StartEndSetTable[direction][6]]; */
/*end->start edge end Y */
/* endOutY = endY + halfWidth[StartEndSetTable[direction][7]]; */
/*end->start edge start X */
startInX = startX + halfWidth[StartEndSetTable[direction][6]];
/*end->start edge start Y */
startInY = startY + halfWidth[StartEndSetTable[direction][7]];
/*end->start edge end X */
endOutX = endX + halfWidth[StartEndSetTable[direction][4]];
/*end->start edge end Y */
endOutY = endY + halfWidth[StartEndSetTable[direction][5]];
/* add end->start edge and check if enough memory */
addStartX = endOutX;
addStartY = endOutY;
addEndX = startInX;
addEndY = startInY;
if (addEdgeVector() != 1)
return(0); /* fail if return */
if (firstSegment == 1) /* is this the first line segment? */
{ /* yes, just add an edge if necessary to close up the first segment */
firstSegment = 0; /* after this, it's not the first line segment */
/* close up according to direction */
if ((direction == 0) || (direction == 4))
goto PrepareForNext;
if (direction > 4)
{ /* direction 5-7 -- add a right edge */
addStartX = startX + halfWidthRight;
addStartY = startY + halfHeightUp;
addEndX = addStartX;
addEndY = startY + halfHeightDown;
if (addEdgeVector() != 1)
return(0); /* fail if return */
}
else
{ /* direction 1-3 -- add a left edge */
addStartX = startX + halfWidthLeft;
addStartY = startY + halfHeightDown;
addEndX = addStartX;
addEndY = startY + halfHeightUp;
if (addEdgeVector() != 1)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -