📄 xpol4.c
字号:
if (pGETPtr->XDirection == 1)
{
pGETPtr->WholePixelXMoveV = DeltaX / DeltaY;
}
else
{
pGETPtr->WholePixelXMoveV = - DeltaX / DeltaY;
}
}
/* if the edge starts above the top clip, jump it ahead to the
top clip scan line */
if (pGETPtr->StartY < clpR.Ymin) /* does this edge start above top clip? */
{ /* yes, jump it ahead */
DeltaY = clpR.Ymin - pGETPtr->StartY;
pGETPtr->Count -= DeltaY; /* clip count */
pGETPtr->StartY = clpR.Ymin; /* new start Y (at top clip) */
/* adjust error term for # of times we would have adjusted it in
advancing that many points */
pGETPtr->ErrorTermV += (DeltaY * pGETPtr->ErrorTermAdjUpV);
if (pGETPtr->ErrorTermV >= 0) /* check if it turned over */
{ /* yes it did so correct it */
if (pGETPtr->XDirection == 1) /* which direction? */
{ /* left->right */
pGETPtr->CurrentX += ((pGETPtr->ErrorTermV /
pGETPtr->ErrorTermAdjDownV) + 1);
}
else
{ /* right to left */
pGETPtr->CurrentX -= ((pGETPtr->ErrorTermV /
pGETPtr->ErrorTermAdjDownV) + 1);
}
pGETPtr->ErrorTermV = ((pGETPtr->ErrorTermV %
pGETPtr->ErrorTermAdjDownV) - pGETPtr->ErrorTermAdjDownV);
}
pGETPtr->CurrentX += (short) (DeltaY * pGETPtr->WholePixelXMoveV);
}
/* if the edge goes past the bottom clip, truncate it there */
DeltaY = clpR.Ymax - pGETPtr->StartY; /* # of scan lines to clip
bottom, not including the clip bottom */
if (pGETPtr->Count > DeltaY) pGETPtr->Count = DeltaY;
/* finally, link the new edge in so that the edge list is still
sorted by Y coordinate, and by X coordinate for all edges with the
same Y coordinate */
lGETPtr = ptrToGETPtr;
while ((NextEdgePtr = *lGETPtr) != 0)
{
if (NextEdgePtr->StartY > pGETPtr->StartY) break;
if ((NextEdgePtr->StartY == pGETPtr->StartY) &&
(NextEdgePtr->CurrentX >= pGETPtr->CurrentX)) break;
lGETPtr = &NextEdgePtr->NextEdge;
getCnt++;
}
/* link in the edge before the next edge we just reached */
pGETPtr->NextEdge = NextEdgePtr;
*lGETPtr = pGETPtr;
pGETPtr++;
buf1Ptr = (byte *) (long) pGETPtr; /* point to next free edge */
return(1);
}
/* Function FillPolygon is the X-Windows compatible polygon drawer.
Convex polygons are simply scanned into a line list and then passed
to the filler. Nonconvex and complex polygons are Y-sorted into a
global edge table, then scanned from top to bottom via an active edge
table. If the memory pool size is greater than or equal to
STACK_BUFFER_SIZE, the convex polygon edge list is maintained there;
otherwise, the convex polygon edge list is maintained in a buffer on
the stack. In either case, if the buffer fills, the contents are
drawn, and scanning continues, so convex polygons with any number of
edges can be handled without significant performance degradation. For
nonconvex polygons, if there's enough memory the edge lists (active,
and global, if possible) are maintained in either the passed buffer
or the stack buffer; however, if the buffer overflows, a much slower
line-by-line approach is employed. Therefore, it behooves the
application to provide as much memory in the memory pool as possible.
"Convex" means that every horizontal line drawn through the polygon
at any point would cross exactly two active edges (neither horizontal
lines nor zero-length edges count as active edges; both are
acceptable anywhere in the polygon), and that the right & left edges
never cross. (It's OK for them to touch, though, so long as the right
edge never crosses over to the left of the left edge.) Nonconvex and
complex polygons won't be drawn properly if convex is specified.
"Nonconvex" means that edges never cross. Complex polygons won't be
drawn properly if nonconvex is specified. Nonconvex polygons are
currently handled by the general-case complex polygon code.
"Complex" covers all polygons.
Polygon edges are scanned X-style: all interior points are filled; for
those points exactly on non-horizontal boundaries, only points that
have the body of the polygon immediately to the right are drawn; for
those points exactly on horizontal boundaries, only points that have
the body of the polygon immediately below are drawn. At vertices
joining horizontal and non-horizontal edges, the non-horizontal edge
rules apply. */
void FillPolygon(point *pointsparm, unsigned int npointsparm, int modeparm,
int shape)
{
long lclCoordAdjX; /* local coord adjust */
long lclCoordAdjY;
blitRcd *tmpBlit;
/* there must be enough vertices to make a visible polygon */
if ((npointsparm < 3 ) || (grafPort.pnLevel < 0)) return;
clpR = ViewClip; /* copy clip rectangle over */
/* decide which buffer to use, stack or memory pool */
buf1Ptr = mpWorkSpace; /* assume using general memory pool */
bufCntr = (long) (mpWorkEnd - buf1Ptr);
if (bufCntr <= STACK_BUFFER_SIZE) /* is the memory pool smaller than */
{ /* the stack buffer? */
bufCntr = STACK_BUFFER_SIZE; /* set up to use the stack buffer */
buf1Ptr = &buf1[0];
}
lclNpointsparm = npointsparm; /* for counting down */
vertexListPtr = pointsparm; /* remember where the first vertex is */
if (shape == convex) /* is the polygon guaranteed convex? */
{ /* yes, it's a convex polygon */
if (globalLevel > 0)
{ /* only local coords with port origin = upperLeft can be handled
by the special fast convex polygon filler */
if ((grafPort.portFlags & (pfVirtual | pfUpper)) ^ pfUpper)
goto NotConvex;
/* Set adjustments from local to global coordinates */
lclCoordAdjX = grafPort.portOrgn.X - grafPort.portRect.Xmin;
lclCoordAdjY = grafPort.portOrgn.Y - grafPort.portRect.Ymin;
}
else
{
lclCoordAdjX = 0; /* zero local coord adjust */
lclCoordAdjY = 0;
}
/* handle as special fast convex fill; now set up the fill record
according to the settings in the current port */
tmpBlit = (blitRcd *) buf1Ptr;
*tmpBlit = grafBlit;
mwFC(buf1Ptr, bufCntr, pointsparm, npointsparm, modeparm,
lclCoordAdjX, lclCoordAdjY); /* draw the convex polygon */
return;
}
NotConvex:
/* See if there's room in the scratch buffer for the entire GET plus a
blitRcd, two pointers, and at least one rect; if so, we can handle this
the easy way, with a GET and an AET. */
if (grafPort.portFlags & pfFillRule) /* 1 for winding rule, 0 for odd/even */
{
lclFillRule = 1;
}
else
{
lclFillRule = 0;
}
addEdgeVector = &AddEdgeToGET; /* routine called to add each edge to the GET */
/* must leave room for at least one rect and a blitRcd - point to last byte at
which an edge can start without overflowing the buffer */
endAvailForGET = ((long) buf1Ptr) + bufCntr - sizeof(blitRcd) - sizeof(rect) -
sizeof(lineEdgeV);
ptrToGETPtr = (lineEdgeV **) (long) buf1Ptr; /* remember where the GET pointer is */
*ptrToGETPtr = 0; /* set the GET to empty to start */
buf1Ptr += SIZEOFF * 2; /* point past the GET and AET pointers */
if (BuildGET() == 1) /* create the GET, Y-X sorted */
{ /* scan out the global edge table */
bufCntr -= ((long) buf1Ptr - (long) ptrToGETPtr); /* # of bytes
left for blitRcd */
mwScanGET((void **)ptrToGETPtr, (blitRcd *)buf1Ptr, bufCntr, shape, (long) lclFillRule, 1);
}
else
{ /* There's not enough memory for the GET, two pointers, a blitRcd,
and at least one rect, so we'll have to scan the whole vertex list
each time to maintain the AET. */
lclNpointsparm = npointsparm; /* reset saved values */
vertexListPtr = pointsparm;
updateAETVector = &BuildGET; /* vector used to update the AET by
scanning vertices */
__mwSL(); /* scan out the polygon */
}
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -