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