4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncCopyright 1987, 1998 The Open Group
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncPermission to use, copy, modify, distribute, and sell this software and its
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncdocumentation for any purpose is hereby granted without fee, provided that
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncthe above copyright notice appear in all copies and that both that
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsynccopyright notice and this permission notice appear in supporting
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncdocumentation.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncThe above copyright notice and this permission notice shall be included
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncin all copies or substantial portions of the Software.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncOTHER DEALINGS IN THE SOFTWARE.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncExcept as contained in this notice, the name of The Open Group shall
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncnot be used in advertising or otherwise to promote the sale, use or
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncother dealings in this Software without prior written authorization
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncfrom The Open Group.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync*/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * fill.h
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Created by Brian Kelleher; Oct 1985
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Include file for filled polygon routines.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * These are the data structures needed to scan
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * convert regions. Two different scan conversion
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * methods are available -- the even-odd method, and
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * the winding number method.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * The even-odd rule states that a point is inside
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * the polygon if a ray drawn from that point in any
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * direction will pass through an odd number of
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * path segments.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * By the winding number rule, a point is decided
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * to be inside the polygon if a ray drawn from that
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * point in any direction passes through a different
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * number of clockwise and counter-clockwise path
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * segments.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * These data structures are adapted somewhat from
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * the algorithm in (Foley/Van Dam) for scan converting
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * polygons.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * The basic algorithm is to start at the top (smallest y)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * of the polygon, stepping down to the bottom of
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * the polygon by incrementing the y coordinate. We
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * keep a list of edges which the current scanline crosses,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * sorted by x. This list is called the Active Edge Table (AET)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * As we change the y-coordinate, we update each entry in
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * in the active edge table to reflect the edges new xcoord.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * This list must be sorted at each scanline in case
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * two edges intersect.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * We also keep a data structure known as the Edge Table (ET),
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * which keeps track of all the edges which the current
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * scanline has not yet reached. The ET is basically a
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * list of ScanLineList structures containing a list of
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * edges which are entered at a given scanline. There is one
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * ScanLineList per scanline at which an edge is entered.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * When we enter a new edge, we move it from the ET to the AET.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * From the AET, we can implement the even-odd rule as in
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * (Foley/Van Dam).
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * The winding number rule is a little trickier. We also
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * keep the EdgeTableEntries in the AET linked by the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * nextWETE (winding EdgeTableEntry) link. This allows
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * the edges to be linked just as before for updating
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * purposes, but only uses the edges linked by the nextWETE
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * link as edges representing spans of the polygon to
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * drawn (as with the even-odd rule).
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * for the winding number rule
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#define CLOCKWISE 1
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#define COUNTERCLOCKWISE -1
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsynctypedef struct _EdgeTableEntry {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int ymax; /* ycoord at which we exit this edge. */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BRESINFO bres; /* Bresenham info to run the edge */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync struct _EdgeTableEntry *next; /* next in the list */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync struct _EdgeTableEntry *back; /* for insertion sort */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync struct _EdgeTableEntry *nextWETE; /* for winding num rule */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int ClockWise; /* flag for winding number rule */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync} EdgeTableEntry;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsynctypedef struct _ScanLineList{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int scanline; /* the scanline represented */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EdgeTableEntry *edgelist; /* header node */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync struct _ScanLineList *next; /* next in the list */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync} ScanLineList;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsynctypedef struct {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int ymax; /* ymax for the polygon */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int ymin; /* ymin for the polygon */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ScanLineList scanlines; /* header node */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync} EdgeTable;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Here is a struct to help with storage allocation
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * so we can allocate a big chunk at a time, and then take
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * pieces from this heap when we need to.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#define SLLSPERBLOCK 25
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsynctypedef struct _ScanLineListBlock {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ScanLineList SLLs[SLLSPERBLOCK];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync struct _ScanLineListBlock *next;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync} ScanLineListBlock;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * number of points to buffer before sending them off
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * to scanlines() : Must be an even number
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#define NUMPTSTOBUFFER 200
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * a few macros for the inner loops of the fill code where
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * performance considerations don't allow a procedure call.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Evaluate the given edge at the given scanline.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * If the edge has expired, then we leave it and fix up
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * the active edge table; otherwise, we increment the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * x value to be ready for the next scanline.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * The winding number rule is in effect, so we must notify
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * the caller when the edge has been removed so he
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * can reorder the Winding Active Edge Table.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#define EVALUATEEDGEWINDING(pAET, pPrevAET, y, fixWAET) { \
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (pAET->ymax == y) { /* leaving this edge */ \
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pPrevAET->next = pAET->next; \
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pAET = pPrevAET->next; \
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fixWAET = 1; \
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (pAET) \
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pAET->back = pPrevAET; \
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } \
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync else { \
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BRESINCRPGONSTRUCT(pAET->bres); \
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pPrevAET = pAET; \
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pAET = pAET->next; \
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } \
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Evaluate the given edge at the given scanline.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * If the edge has expired, then we leave it and fix up
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * the active edge table; otherwise, we increment the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * x value to be ready for the next scanline.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * The even-odd rule is in effect.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#define EVALUATEEDGEEVENODD(pAET, pPrevAET, y) { \
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (pAET->ymax == y) { /* leaving this edge */ \
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pPrevAET->next = pAET->next; \
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pAET = pPrevAET->next; \
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (pAET) \
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pAET->back = pPrevAET; \
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } \
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync else { \
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BRESINCRPGONSTRUCT(pAET->bres); \
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pPrevAET = pAET; \
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pAET = pAET->next; \
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } \
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/* mipolyutil.c */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncextern Bool miInsertEdgeInET(
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EdgeTable * /*ET*/,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EdgeTableEntry * /*ETE*/,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int /*scanline*/,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ScanLineListBlock ** /*SLLBlock*/,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int * /*iSLLBlock*/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncextern Bool miCreateETandAET(
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int /*count*/,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DDXPointPtr /*pts*/,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EdgeTable * /*ET*/,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EdgeTableEntry * /*AET*/,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EdgeTableEntry * /*pETEs*/,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ScanLineListBlock * /*pSLLBlock*/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncextern void miloadAET(
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EdgeTableEntry * /*AET*/,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EdgeTableEntry * /*ETEs*/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncextern void micomputeWAET(
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EdgeTableEntry * /*AET*/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncextern int miInsertionSort(
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EdgeTableEntry * /*AET*/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncextern void miFreeStorage(
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ScanLineListBlock * /*pSLLBlock*/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync