Blame gdk/gdkpolyreg-generic.c

Packit Service fb6fa5
/* $TOG: PolyReg.c /main/15 1998/02/06 17:47:08 kaleb $ */
Packit Service fb6fa5
/************************************************************************
Packit Service fb6fa5
Packit Service fb6fa5
Copyright 1987, 1998  The Open Group
Packit Service fb6fa5
Packit Service fb6fa5
All Rights Reserved.
Packit Service fb6fa5
Packit Service fb6fa5
The above copyright notice and this permission notice shall be included in
Packit Service fb6fa5
all copies or substantial portions of the Software.
Packit Service fb6fa5
Packit Service fb6fa5
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
Packit Service fb6fa5
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
Packit Service fb6fa5
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
Packit Service fb6fa5
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
Packit Service fb6fa5
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
Packit Service fb6fa5
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Packit Service fb6fa5
Packit Service fb6fa5
Except as contained in this notice, the name of The Open Group shall not be
Packit Service fb6fa5
used in advertising or otherwise to promote the sale, use or other dealings
Packit Service fb6fa5
in this Software without prior written authorization from The Open Group.
Packit Service fb6fa5
Packit Service fb6fa5
Packit Service fb6fa5
Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
Packit Service fb6fa5
Packit Service fb6fa5
                        All Rights Reserved
Packit Service fb6fa5
Packit Service fb6fa5
Permission to use, copy, modify, and distribute this software and its 
Packit Service fb6fa5
documentation for any purpose and without fee is hereby granted, 
Packit Service fb6fa5
provided that the above copyright notice appear in all copies and that
Packit Service fb6fa5
both that copyright notice and this permission notice appear in 
Packit Service fb6fa5
supporting documentation, and that the name of Digital not be
Packit Service fb6fa5
used in advertising or publicity pertaining to distribution of the
Packit Service fb6fa5
software without specific, written prior permission.  
Packit Service fb6fa5
Packit Service fb6fa5
DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
Packit Service fb6fa5
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
Packit Service fb6fa5
DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
Packit Service fb6fa5
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
Packit Service fb6fa5
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
Packit Service fb6fa5
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
Packit Service fb6fa5
SOFTWARE.
Packit Service fb6fa5
Packit Service fb6fa5
************************************************************************/
Packit Service fb6fa5
/* $XFree86: xc/lib/X11/PolyReg.c,v 1.4 1998/10/03 08:41:21 dawes Exp $ */
Packit Service fb6fa5
Packit Service fb6fa5
#define LARGE_COORDINATE 1000000
Packit Service fb6fa5
#define SMALL_COORDINATE -LARGE_COORDINATE
Packit Service fb6fa5
Packit Service fb6fa5
#include "config.h"
Packit Service fb6fa5
#include <gdkregion.h>
Packit Service fb6fa5
#include "gdkregion-generic.h"
Packit Service fb6fa5
#include "gdkpoly-generic.h"
Packit Service fb6fa5
#include "gdkalias.h"
Packit Service fb6fa5
Packit Service fb6fa5
/*
Packit Service fb6fa5
 *     InsertEdgeInET
Packit Service fb6fa5
 *
Packit Service fb6fa5
 *     Insert the given edge into the edge table.
Packit Service fb6fa5
 *     First we must find the correct bucket in the
Packit Service fb6fa5
 *     Edge table, then find the right slot in the
Packit Service fb6fa5
 *     bucket.  Finally, we can insert it.
Packit Service fb6fa5
 *
Packit Service fb6fa5
 */
Packit Service fb6fa5
static void
Packit Service fb6fa5
InsertEdgeInET (EdgeTable          *ET,
Packit Service fb6fa5
                EdgeTableEntry     *ETE,
Packit Service fb6fa5
                int                 scanline,
Packit Service fb6fa5
                ScanLineListBlock **SLLBlock,
Packit Service fb6fa5
                int                *iSLLBlock)
Packit Service fb6fa5
{
Packit Service fb6fa5
    EdgeTableEntry *start, *prev;
Packit Service fb6fa5
    ScanLineList *pSLL, *pPrevSLL;
Packit Service fb6fa5
    ScanLineListBlock *tmpSLLBlock;
Packit Service fb6fa5
Packit Service fb6fa5
    /*
Packit Service fb6fa5
     * find the right bucket to put the edge into
Packit Service fb6fa5
     */
Packit Service fb6fa5
    pPrevSLL = &ET->scanlines;
Packit Service fb6fa5
    pSLL = pPrevSLL->next;
Packit Service fb6fa5
    while (pSLL && (pSLL->scanline < scanline)) 
Packit Service fb6fa5
    {
Packit Service fb6fa5
        pPrevSLL = pSLL;
Packit Service fb6fa5
        pSLL = pSLL->next;
Packit Service fb6fa5
    }
Packit Service fb6fa5
Packit Service fb6fa5
    /*
Packit Service fb6fa5
     * reassign pSLL (pointer to ScanLineList) if necessary
Packit Service fb6fa5
     */
Packit Service fb6fa5
    if ((!pSLL) || (pSLL->scanline > scanline)) 
Packit Service fb6fa5
    {
Packit Service fb6fa5
        if (*iSLLBlock > SLLSPERBLOCK-1) 
Packit Service fb6fa5
        {
Packit Service fb6fa5
            tmpSLLBlock = 
Packit Service fb6fa5
		  (ScanLineListBlock *)g_malloc(sizeof(ScanLineListBlock));
Packit Service fb6fa5
            (*SLLBlock)->next = tmpSLLBlock;
Packit Service fb6fa5
            tmpSLLBlock->next = (ScanLineListBlock *)NULL;
Packit Service fb6fa5
            *SLLBlock = tmpSLLBlock;
Packit Service fb6fa5
            *iSLLBlock = 0;
Packit Service fb6fa5
        }
Packit Service fb6fa5
        pSLL = &((*SLLBlock)->SLLs[(*iSLLBlock)++]);
Packit Service fb6fa5
Packit Service fb6fa5
        pSLL->next = pPrevSLL->next;
Packit Service fb6fa5
        pSLL->edgelist = (EdgeTableEntry *)NULL;
Packit Service fb6fa5
        pPrevSLL->next = pSLL;
Packit Service fb6fa5
    }
Packit Service fb6fa5
    pSLL->scanline = scanline;
Packit Service fb6fa5
Packit Service fb6fa5
    /*
Packit Service fb6fa5
     * now insert the edge in the right bucket
Packit Service fb6fa5
     */
Packit Service fb6fa5
    prev = (EdgeTableEntry *)NULL;
Packit Service fb6fa5
    start = pSLL->edgelist;
Packit Service fb6fa5
    while (start && (start->bres.minor_axis < ETE->bres.minor_axis)) 
Packit Service fb6fa5
    {
Packit Service fb6fa5
        prev = start;
Packit Service fb6fa5
        start = start->next;
Packit Service fb6fa5
    }
Packit Service fb6fa5
    ETE->next = start;
Packit Service fb6fa5
Packit Service fb6fa5
    if (prev)
Packit Service fb6fa5
        prev->next = ETE;
Packit Service fb6fa5
    else
Packit Service fb6fa5
        pSLL->edgelist = ETE;
Packit Service fb6fa5
}
Packit Service fb6fa5

Packit Service fb6fa5
/*
Packit Service fb6fa5
 *     CreateEdgeTable
Packit Service fb6fa5
 *
Packit Service fb6fa5
 *     This routine creates the edge table for
Packit Service fb6fa5
 *     scan converting polygons. 
Packit Service fb6fa5
 *     The Edge Table (ET) looks like:
Packit Service fb6fa5
 *
Packit Service fb6fa5
 *    EdgeTable
Packit Service fb6fa5
 *     --------
Packit Service fb6fa5
 *    |  ymax  |        ScanLineLists
Packit Service fb6fa5
 *    |scanline|-->------------>-------------->...
Packit Service fb6fa5
 *     --------   |scanline|   |scanline|
Packit Service fb6fa5
 *                |edgelist|   |edgelist|
Packit Service fb6fa5
 *                ---------    ---------
Packit Service fb6fa5
 *                    |             |
Packit Service fb6fa5
 *                    |             |
Packit Service fb6fa5
 *                    V             V
Packit Service fb6fa5
 *              list of ETEs   list of ETEs
Packit Service fb6fa5
 *
Packit Service fb6fa5
 *     where ETE is an EdgeTableEntry data structure,
Packit Service fb6fa5
 *     and there is one ScanLineList per scanline at
Packit Service fb6fa5
 *     which an edge is initially entered.
Packit Service fb6fa5
 *
Packit Service fb6fa5
 */
Packit Service fb6fa5
Packit Service fb6fa5
static void
Packit Service fb6fa5
CreateETandAET (int                count,
Packit Service fb6fa5
                const GdkPoint    *pts,
Packit Service fb6fa5
                EdgeTable         *ET,
Packit Service fb6fa5
                EdgeTableEntry    *AET,
Packit Service fb6fa5
                EdgeTableEntry    *pETEs,
Packit Service fb6fa5
                ScanLineListBlock *pSLLBlock)
Packit Service fb6fa5
{
Packit Service fb6fa5
    const GdkPoint *top, *bottom;
Packit Service fb6fa5
    const GdkPoint *PrevPt, *CurrPt;
Packit Service fb6fa5
    int iSLLBlock = 0;
Packit Service fb6fa5
    int dy;
Packit Service fb6fa5
Packit Service fb6fa5
    if (count < 2)  return;
Packit Service fb6fa5
Packit Service fb6fa5
    /*
Packit Service fb6fa5
     *  initialize the Active Edge Table
Packit Service fb6fa5
     */
Packit Service fb6fa5
    AET->next = (EdgeTableEntry *)NULL;
Packit Service fb6fa5
    AET->back = (EdgeTableEntry *)NULL;
Packit Service fb6fa5
    AET->nextWETE = (EdgeTableEntry *)NULL;
Packit Service fb6fa5
    AET->bres.minor_axis = SMALL_COORDINATE;
Packit Service fb6fa5
Packit Service fb6fa5
    /*
Packit Service fb6fa5
     *  initialize the Edge Table.
Packit Service fb6fa5
     */
Packit Service fb6fa5
    ET->scanlines.next = (ScanLineList *)NULL;
Packit Service fb6fa5
    ET->ymax = SMALL_COORDINATE;
Packit Service fb6fa5
    ET->ymin = LARGE_COORDINATE;
Packit Service fb6fa5
    pSLLBlock->next = (ScanLineListBlock *)NULL;
Packit Service fb6fa5
Packit Service fb6fa5
    PrevPt = &pts[count-1];
Packit Service fb6fa5
Packit Service fb6fa5
    /*
Packit Service fb6fa5
     *  for each vertex in the array of points.
Packit Service fb6fa5
     *  In this loop we are dealing with two vertices at
Packit Service fb6fa5
     *  a time -- these make up one edge of the polygon.
Packit Service fb6fa5
     */
Packit Service fb6fa5
    while (count--) 
Packit Service fb6fa5
    {
Packit Service fb6fa5
        CurrPt = pts++;
Packit Service fb6fa5
Packit Service fb6fa5
        /*
Packit Service fb6fa5
         *  find out which point is above and which is below.
Packit Service fb6fa5
         */
Packit Service fb6fa5
        if (PrevPt->y > CurrPt->y) 
Packit Service fb6fa5
        {
Packit Service fb6fa5
            bottom = PrevPt, top = CurrPt;
Packit Service fb6fa5
            pETEs->ClockWise = 0;
Packit Service fb6fa5
        }
Packit Service fb6fa5
        else 
Packit Service fb6fa5
        {
Packit Service fb6fa5
            bottom = CurrPt, top = PrevPt;
Packit Service fb6fa5
            pETEs->ClockWise = 1;
Packit Service fb6fa5
        }
Packit Service fb6fa5
Packit Service fb6fa5
        /*
Packit Service fb6fa5
         * don't add horizontal edges to the Edge table.
Packit Service fb6fa5
         */
Packit Service fb6fa5
        if (bottom->y != top->y) 
Packit Service fb6fa5
        {
Packit Service fb6fa5
            pETEs->ymax = bottom->y-1;  /* -1 so we don't get last scanline */
Packit Service fb6fa5
Packit Service fb6fa5
            /*
Packit Service fb6fa5
             *  initialize integer edge algorithm
Packit Service fb6fa5
             */
Packit Service fb6fa5
            dy = bottom->y - top->y;
Packit Service fb6fa5
            BRESINITPGONSTRUCT(dy, top->x, bottom->x, pETEs->bres);
Packit Service fb6fa5
Packit Service fb6fa5
            InsertEdgeInET(ET, pETEs, top->y, &pSLLBlock, &iSLLBlock);
Packit Service fb6fa5
Packit Service fb6fa5
	    if (PrevPt->y > ET->ymax)
Packit Service fb6fa5
		ET->ymax = PrevPt->y;
Packit Service fb6fa5
	    if (PrevPt->y < ET->ymin)
Packit Service fb6fa5
		ET->ymin = PrevPt->y;
Packit Service fb6fa5
            pETEs++;
Packit Service fb6fa5
        }
Packit Service fb6fa5
Packit Service fb6fa5
        PrevPt = CurrPt;
Packit Service fb6fa5
    }
Packit Service fb6fa5
}
Packit Service fb6fa5

Packit Service fb6fa5
/*
Packit Service fb6fa5
 *     loadAET
Packit Service fb6fa5
 *
Packit Service fb6fa5
 *     This routine moves EdgeTableEntries from the
Packit Service fb6fa5
 *     EdgeTable into the Active Edge Table,
Packit Service fb6fa5
 *     leaving them sorted by smaller x coordinate.
Packit Service fb6fa5
 *
Packit Service fb6fa5
 */
Packit Service fb6fa5
Packit Service fb6fa5
static void
Packit Service fb6fa5
loadAET(EdgeTableEntry *AET,
Packit Service fb6fa5
        EdgeTableEntry *ETEs)
Packit Service fb6fa5
{
Packit Service fb6fa5
    EdgeTableEntry *pPrevAET;
Packit Service fb6fa5
    EdgeTableEntry *tmp;
Packit Service fb6fa5
Packit Service fb6fa5
    pPrevAET = AET;
Packit Service fb6fa5
    AET = AET->next;
Packit Service fb6fa5
    while (ETEs) 
Packit Service fb6fa5
    {
Packit Service fb6fa5
        while (AET && (AET->bres.minor_axis < ETEs->bres.minor_axis)) 
Packit Service fb6fa5
        {
Packit Service fb6fa5
            pPrevAET = AET;
Packit Service fb6fa5
            AET = AET->next;
Packit Service fb6fa5
        }
Packit Service fb6fa5
        tmp = ETEs->next;
Packit Service fb6fa5
        ETEs->next = AET;
Packit Service fb6fa5
        if (AET)
Packit Service fb6fa5
            AET->back = ETEs;
Packit Service fb6fa5
        ETEs->back = pPrevAET;
Packit Service fb6fa5
        pPrevAET->next = ETEs;
Packit Service fb6fa5
        pPrevAET = ETEs;
Packit Service fb6fa5
Packit Service fb6fa5
        ETEs = tmp;
Packit Service fb6fa5
    }
Packit Service fb6fa5
}
Packit Service fb6fa5

Packit Service fb6fa5
/*
Packit Service fb6fa5
 *     computeWAET
Packit Service fb6fa5
 *
Packit Service fb6fa5
 *     This routine links the AET by the
Packit Service fb6fa5
 *     nextWETE (winding EdgeTableEntry) link for
Packit Service fb6fa5
 *     use by the winding number rule.  The final 
Packit Service fb6fa5
 *     Active Edge Table (AET) might look something
Packit Service fb6fa5
 *     like:
Packit Service fb6fa5
 *
Packit Service fb6fa5
 *     AET
Packit Service fb6fa5
 *     ----------  ---------   ---------
Packit Service fb6fa5
 *     |ymax    |  |ymax    |  |ymax    | 
Packit Service fb6fa5
 *     | ...    |  |...     |  |...     |
Packit Service fb6fa5
 *     |next    |->|next    |->|next    |->...
Packit Service fb6fa5
 *     |nextWETE|  |nextWETE|  |nextWETE|
Packit Service fb6fa5
 *     ---------   ---------   ^--------
Packit Service fb6fa5
 *         |                   |       |
Packit Service fb6fa5
 *         V------------------->       V---> ...
Packit Service fb6fa5
 *
Packit Service fb6fa5
 */
Packit Service fb6fa5
static void
Packit Service fb6fa5
computeWAET (EdgeTableEntry *AET)
Packit Service fb6fa5
{
Packit Service fb6fa5
    EdgeTableEntry *pWETE;
Packit Service fb6fa5
    int inside = 1;
Packit Service fb6fa5
    int isInside = 0;
Packit Service fb6fa5
Packit Service fb6fa5
    AET->nextWETE = (EdgeTableEntry *)NULL;
Packit Service fb6fa5
    pWETE = AET;
Packit Service fb6fa5
    AET = AET->next;
Packit Service fb6fa5
    while (AET) 
Packit Service fb6fa5
    {
Packit Service fb6fa5
        if (AET->ClockWise)
Packit Service fb6fa5
            isInside++;
Packit Service fb6fa5
        else
Packit Service fb6fa5
            isInside--;
Packit Service fb6fa5
Packit Service fb6fa5
        if ((!inside && !isInside) ||
Packit Service fb6fa5
            ( inside &&  isInside)) 
Packit Service fb6fa5
        {
Packit Service fb6fa5
            pWETE->nextWETE = AET;
Packit Service fb6fa5
            pWETE = AET;
Packit Service fb6fa5
            inside = !inside;
Packit Service fb6fa5
        }
Packit Service fb6fa5
        AET = AET->next;
Packit Service fb6fa5
    }
Packit Service fb6fa5
    pWETE->nextWETE = (EdgeTableEntry *)NULL;
Packit Service fb6fa5
}
Packit Service fb6fa5

Packit Service fb6fa5
/*
Packit Service fb6fa5
 *     InsertionSort
Packit Service fb6fa5
 *
Packit Service fb6fa5
 *     Just a simple insertion sort using
Packit Service fb6fa5
 *     pointers and back pointers to sort the Active
Packit Service fb6fa5
 *     Edge Table.
Packit Service fb6fa5
 *
Packit Service fb6fa5
 */
Packit Service fb6fa5
Packit Service fb6fa5
static int
Packit Service fb6fa5
InsertionSort (EdgeTableEntry *AET)
Packit Service fb6fa5
{
Packit Service fb6fa5
    EdgeTableEntry *pETEchase;
Packit Service fb6fa5
    EdgeTableEntry *pETEinsert;
Packit Service fb6fa5
    EdgeTableEntry *pETEchaseBackTMP;
Packit Service fb6fa5
    int changed = 0;
Packit Service fb6fa5
Packit Service fb6fa5
    AET = AET->next;
Packit Service fb6fa5
    while (AET) 
Packit Service fb6fa5
    {
Packit Service fb6fa5
        pETEinsert = AET;
Packit Service fb6fa5
        pETEchase = AET;
Packit Service fb6fa5
        while (pETEchase->back->bres.minor_axis > AET->bres.minor_axis)
Packit Service fb6fa5
            pETEchase = pETEchase->back;
Packit Service fb6fa5
Packit Service fb6fa5
        AET = AET->next;
Packit Service fb6fa5
        if (pETEchase != pETEinsert) 
Packit Service fb6fa5
        {
Packit Service fb6fa5
            pETEchaseBackTMP = pETEchase->back;
Packit Service fb6fa5
            pETEinsert->back->next = AET;
Packit Service fb6fa5
            if (AET)
Packit Service fb6fa5
                AET->back = pETEinsert->back;
Packit Service fb6fa5
            pETEinsert->next = pETEchase;
Packit Service fb6fa5
            pETEchase->back->next = pETEinsert;
Packit Service fb6fa5
            pETEchase->back = pETEinsert;
Packit Service fb6fa5
            pETEinsert->back = pETEchaseBackTMP;
Packit Service fb6fa5
            changed = 1;
Packit Service fb6fa5
        }
Packit Service fb6fa5
    }
Packit Service fb6fa5
    return(changed);
Packit Service fb6fa5
}
Packit Service fb6fa5

Packit Service fb6fa5
/*
Packit Service fb6fa5
 *     Clean up our act.
Packit Service fb6fa5
 */
Packit Service fb6fa5
static void
Packit Service fb6fa5
FreeStorage (ScanLineListBlock *pSLLBlock)
Packit Service fb6fa5
{
Packit Service fb6fa5
    ScanLineListBlock   *tmpSLLBlock;
Packit Service fb6fa5
Packit Service fb6fa5
    while (pSLLBlock) 
Packit Service fb6fa5
    {
Packit Service fb6fa5
        tmpSLLBlock = pSLLBlock->next;
Packit Service fb6fa5
        g_free (pSLLBlock);
Packit Service fb6fa5
        pSLLBlock = tmpSLLBlock;
Packit Service fb6fa5
    }
Packit Service fb6fa5
}
Packit Service fb6fa5
Packit Service fb6fa5
/*
Packit Service fb6fa5
 *     Create an array of rectangles from a list of points.
Packit Service fb6fa5
 *     If indeed these things (POINTS, RECTS) are the same,
Packit Service fb6fa5
 *     then this proc is still needed, because it allocates
Packit Service fb6fa5
 *     storage for the array, which was allocated on the
Packit Service fb6fa5
 *     stack by the calling procedure.
Packit Service fb6fa5
 *
Packit Service fb6fa5
 */
Packit Service fb6fa5
static int
Packit Service fb6fa5
PtsToRegion (int         numFullPtBlocks,
Packit Service fb6fa5
             int         iCurPtBlock,
Packit Service fb6fa5
             POINTBLOCK *FirstPtBlock,
Packit Service fb6fa5
             GdkRegion  *reg)
Packit Service fb6fa5
{
Packit Service fb6fa5
    GdkRegionBox *rects;
Packit Service fb6fa5
    GdkPoint *pts;
Packit Service fb6fa5
    POINTBLOCK *CurPtBlock;
Packit Service fb6fa5
    int i;
Packit Service fb6fa5
    GdkRegionBox *extents;
Packit Service fb6fa5
    int numRects;
Packit Service fb6fa5
Packit Service fb6fa5
    extents = &reg->extents;
Packit Service fb6fa5
 
Packit Service fb6fa5
    numRects = ((numFullPtBlocks * NUMPTSTOBUFFER) + iCurPtBlock) >> 1;
Packit Service fb6fa5
 
Packit Service fb6fa5
    GROWREGION(reg, numRects);
Packit Service fb6fa5
Packit Service fb6fa5
    CurPtBlock = FirstPtBlock;
Packit Service fb6fa5
    rects = reg->rects - 1;
Packit Service fb6fa5
    numRects = 0;
Packit Service fb6fa5
    extents->x1 = G_MAXSHORT,  extents->x2 = G_MINSHORT;
Packit Service fb6fa5
 
Packit Service fb6fa5
    for ( ; numFullPtBlocks >= 0; numFullPtBlocks--) {
Packit Service fb6fa5
	/* the loop uses 2 points per iteration */
Packit Service fb6fa5
	i = NUMPTSTOBUFFER >> 1;
Packit Service fb6fa5
	if (!numFullPtBlocks)
Packit Service fb6fa5
	    i = iCurPtBlock >> 1;
Packit Service fb6fa5
	for (pts = CurPtBlock->pts; i--; pts += 2) {
Packit Service fb6fa5
	    if (pts->x == pts[1].x)
Packit Service fb6fa5
		continue;
Packit Service fb6fa5
	    if (numRects && pts->x == rects->x1 && pts->y == rects->y2 &&
Packit Service fb6fa5
		pts[1].x == rects->x2 &&
Packit Service fb6fa5
		(numRects == 1 || rects[-1].y1 != rects->y1) &&
Packit Service fb6fa5
		(i && pts[2].y > pts[1].y)) {
Packit Service fb6fa5
		rects->y2 = pts[1].y + 1;
Packit Service fb6fa5
		continue;
Packit Service fb6fa5
	    }
Packit Service fb6fa5
	    numRects++;
Packit Service fb6fa5
	    rects++;
Packit Service fb6fa5
	    rects->x1 = pts->x;  rects->y1 = pts->y;
Packit Service fb6fa5
	    rects->x2 = pts[1].x;  rects->y2 = pts[1].y + 1;
Packit Service fb6fa5
	    if (rects->x1 < extents->x1)
Packit Service fb6fa5
		extents->x1 = rects->x1;
Packit Service fb6fa5
	    if (rects->x2 > extents->x2)
Packit Service fb6fa5
		extents->x2 = rects->x2;
Packit Service fb6fa5
        }
Packit Service fb6fa5
	CurPtBlock = CurPtBlock->next;
Packit Service fb6fa5
    }
Packit Service fb6fa5
Packit Service fb6fa5
    if (numRects) {
Packit Service fb6fa5
	extents->y1 = reg->rects->y1;
Packit Service fb6fa5
	extents->y2 = rects->y2;
Packit Service fb6fa5
    } else {
Packit Service fb6fa5
	extents->x1 = 0;
Packit Service fb6fa5
	extents->y1 = 0;
Packit Service fb6fa5
	extents->x2 = 0;
Packit Service fb6fa5
	extents->y2 = 0;
Packit Service fb6fa5
    }
Packit Service fb6fa5
    reg->numRects = numRects;
Packit Service fb6fa5
 
Packit Service fb6fa5
    return(TRUE);
Packit Service fb6fa5
}
Packit Service fb6fa5
Packit Service fb6fa5
/**
Packit Service fb6fa5
 * gdk_region_polygon:
Packit Service fb6fa5
 * @points: an array of #GdkPoint structs
Packit Service fb6fa5
 * @n_points: the number of elements in the @points array
Packit Service fb6fa5
 * @fill_rule: specifies which pixels are included in the region when the 
Packit Service fb6fa5
 *     polygon overlaps itself.
Packit Service fb6fa5
 * 
Packit Service fb6fa5
 * Creates a new #GdkRegion using the polygon defined by a 
Packit Service fb6fa5
 * number of points.
Packit Service fb6fa5
 *
Packit Service fb6fa5
 * Returns: a new #GdkRegion based on the given polygon
Packit Service fb6fa5
 *
Packit Service fb6fa5
 * Deprecated: 2.22: There is no replacement. For working with paths, please
Packit Service fb6fa5
 *             use Cairo.
Packit Service fb6fa5
 */
Packit Service fb6fa5
GdkRegion *
Packit Service fb6fa5
gdk_region_polygon (const GdkPoint *points,
Packit Service fb6fa5
                    gint            n_points,
Packit Service fb6fa5
                    GdkFillRule     fill_rule)
Packit Service fb6fa5
{
Packit Service fb6fa5
    GdkRegion *region;
Packit Service fb6fa5
    EdgeTableEntry *pAET;   /* Active Edge Table       */
Packit Service fb6fa5
    int y;                  /* current scanline        */
Packit Service fb6fa5
    int iPts = 0;           /* number of pts in buffer */
Packit Service fb6fa5
    EdgeTableEntry *pWETE;  /* Winding Edge Table Entry*/
Packit Service fb6fa5
    ScanLineList *pSLL;     /* current scanLineList    */
Packit Service fb6fa5
    GdkPoint *pts;          /* output buffer           */
Packit Service fb6fa5
    EdgeTableEntry *pPrevAET;        /* ptr to previous AET     */
Packit Service fb6fa5
    EdgeTable ET;                    /* header node for ET      */
Packit Service fb6fa5
    EdgeTableEntry AET;              /* header node for AET     */
Packit Service fb6fa5
    EdgeTableEntry *pETEs;           /* EdgeTableEntries pool   */
Packit Service fb6fa5
    ScanLineListBlock SLLBlock;      /* header for scanlinelist */
Packit Service fb6fa5
    int fixWAET = FALSE;
Packit Service fb6fa5
    POINTBLOCK FirstPtBlock, *curPtBlock; /* PtBlock buffers    */
Packit Service fb6fa5
    POINTBLOCK *tmpPtBlock;
Packit Service fb6fa5
    int numFullPtBlocks = 0;
Packit Service fb6fa5
 
Packit Service fb6fa5
    region = gdk_region_new ();
Packit Service fb6fa5
Packit Service fb6fa5
    /* special case a rectangle */
Packit Service fb6fa5
    if (((n_points == 4) ||
Packit Service fb6fa5
	 ((n_points == 5) && (points[4].x == points[0].x) && (points[4].y == points[0].y))) &&
Packit Service fb6fa5
	(((points[0].y == points[1].y) &&
Packit Service fb6fa5
	  (points[1].x == points[2].x) &&
Packit Service fb6fa5
	  (points[2].y == points[3].y) &&
Packit Service fb6fa5
	  (points[3].x == points[0].x)) ||
Packit Service fb6fa5
	 ((points[0].x == points[1].x) &&
Packit Service fb6fa5
	  (points[1].y == points[2].y) &&
Packit Service fb6fa5
	  (points[2].x == points[3].x) &&
Packit Service fb6fa5
	  (points[3].y == points[0].y)))) {
Packit Service fb6fa5
	region->extents.x1 = MIN(points[0].x, points[2].x);
Packit Service fb6fa5
	region->extents.y1 = MIN(points[0].y, points[2].y);
Packit Service fb6fa5
	region->extents.x2 = MAX(points[0].x, points[2].x);
Packit Service fb6fa5
	region->extents.y2 = MAX(points[0].y, points[2].y);
Packit Service fb6fa5
	if ((region->extents.x1 != region->extents.x2) &&
Packit Service fb6fa5
	    (region->extents.y1 != region->extents.y2)) {
Packit Service fb6fa5
	    region->numRects = 1;
Packit Service fb6fa5
	    *(region->rects) = region->extents;
Packit Service fb6fa5
	}
Packit Service fb6fa5
	return(region);
Packit Service fb6fa5
    }
Packit Service fb6fa5
Packit Service fb6fa5
    pETEs = g_new (EdgeTableEntry, n_points);
Packit Service fb6fa5
Packit Service fb6fa5
    pts = FirstPtBlock.pts;
Packit Service fb6fa5
    CreateETandAET(n_points, points, &ET, &AET, pETEs, &SLLBlock);
Packit Service fb6fa5
    pSLL = ET.scanlines.next;
Packit Service fb6fa5
    curPtBlock = &FirstPtBlock;
Packit Service fb6fa5
 
Packit Service fb6fa5
    if (fill_rule == GDK_EVEN_ODD_RULE) {
Packit Service fb6fa5
        /*
Packit Service fb6fa5
         *  for each scanline
Packit Service fb6fa5
         */
Packit Service fb6fa5
        for (y = ET.ymin; y < ET.ymax; y++) {
Packit Service fb6fa5
            /*
Packit Service fb6fa5
             *  Add a new edge to the active edge table when we
Packit Service fb6fa5
             *  get to the next edge.
Packit Service fb6fa5
             */
Packit Service fb6fa5
            if (pSLL != NULL && y == pSLL->scanline) {
Packit Service fb6fa5
                loadAET(&AET, pSLL->edgelist);
Packit Service fb6fa5
                pSLL = pSLL->next;
Packit Service fb6fa5
            }
Packit Service fb6fa5
            pPrevAET = &AET;
Packit Service fb6fa5
            pAET = AET.next;
Packit Service fb6fa5
 
Packit Service fb6fa5
            /*
Packit Service fb6fa5
             *  for each active edge
Packit Service fb6fa5
             */
Packit Service fb6fa5
            while (pAET) {
Packit Service fb6fa5
                pts->x = pAET->bres.minor_axis,  pts->y = y;
Packit Service fb6fa5
                pts++, iPts++;
Packit Service fb6fa5
 
Packit Service fb6fa5
                /*
Packit Service fb6fa5
                 *  send out the buffer
Packit Service fb6fa5
                 */
Packit Service fb6fa5
                if (iPts == NUMPTSTOBUFFER) {
Packit Service fb6fa5
                    tmpPtBlock = (POINTBLOCK *)g_malloc(sizeof(POINTBLOCK));
Packit Service fb6fa5
		    tmpPtBlock->next = NULL;
Packit Service fb6fa5
                    curPtBlock->next = tmpPtBlock;
Packit Service fb6fa5
                    curPtBlock = tmpPtBlock;
Packit Service fb6fa5
                    pts = curPtBlock->pts;
Packit Service fb6fa5
                    numFullPtBlocks++;
Packit Service fb6fa5
                    iPts = 0;
Packit Service fb6fa5
                }
Packit Service fb6fa5
                EVALUATEEDGEEVENODD(pAET, pPrevAET, y);
Packit Service fb6fa5
            }
Packit Service fb6fa5
            (void) InsertionSort(&AET;;
Packit Service fb6fa5
        }
Packit Service fb6fa5
    }
Packit Service fb6fa5
    else {
Packit Service fb6fa5
        /*
Packit Service fb6fa5
         *  for each scanline
Packit Service fb6fa5
         */
Packit Service fb6fa5
        for (y = ET.ymin; y < ET.ymax; y++) {
Packit Service fb6fa5
            /*
Packit Service fb6fa5
             *  Add a new edge to the active edge table when we
Packit Service fb6fa5
             *  get to the next edge.
Packit Service fb6fa5
             */
Packit Service fb6fa5
            if (pSLL != NULL && y == pSLL->scanline) {
Packit Service fb6fa5
                loadAET(&AET, pSLL->edgelist);
Packit Service fb6fa5
                computeWAET(&AET;;
Packit Service fb6fa5
                pSLL = pSLL->next;
Packit Service fb6fa5
            }
Packit Service fb6fa5
            pPrevAET = &AET;
Packit Service fb6fa5
            pAET = AET.next;
Packit Service fb6fa5
            pWETE = pAET;
Packit Service fb6fa5
 
Packit Service fb6fa5
            /*
Packit Service fb6fa5
             *  for each active edge
Packit Service fb6fa5
             */
Packit Service fb6fa5
            while (pAET) {
Packit Service fb6fa5
                /*
Packit Service fb6fa5
                 *  add to the buffer only those edges that
Packit Service fb6fa5
                 *  are in the Winding active edge table.
Packit Service fb6fa5
                 */
Packit Service fb6fa5
                if (pWETE == pAET) {
Packit Service fb6fa5
                    pts->x = pAET->bres.minor_axis,  pts->y = y;
Packit Service fb6fa5
                    pts++, iPts++;
Packit Service fb6fa5
 
Packit Service fb6fa5
                    /*
Packit Service fb6fa5
                     *  send out the buffer
Packit Service fb6fa5
                     */
Packit Service fb6fa5
                    if (iPts == NUMPTSTOBUFFER) {
Packit Service fb6fa5
                        tmpPtBlock = (POINTBLOCK *)g_malloc(sizeof(POINTBLOCK));
Packit Service fb6fa5
			tmpPtBlock->next = NULL;
Packit Service fb6fa5
                        curPtBlock->next = tmpPtBlock;
Packit Service fb6fa5
                        curPtBlock = tmpPtBlock;
Packit Service fb6fa5
                        pts = curPtBlock->pts;
Packit Service fb6fa5
                        numFullPtBlocks++;    iPts = 0;
Packit Service fb6fa5
                    }
Packit Service fb6fa5
                    pWETE = pWETE->nextWETE;
Packit Service fb6fa5
                }
Packit Service fb6fa5
                EVALUATEEDGEWINDING(pAET, pPrevAET, y, fixWAET);
Packit Service fb6fa5
            }
Packit Service fb6fa5
 
Packit Service fb6fa5
            /*
Packit Service fb6fa5
             *  recompute the winding active edge table if
Packit Service fb6fa5
             *  we just resorted or have exited an edge.
Packit Service fb6fa5
             */
Packit Service fb6fa5
            if (InsertionSort(&AET) || fixWAET) {
Packit Service fb6fa5
                computeWAET(&AET;;
Packit Service fb6fa5
                fixWAET = FALSE;
Packit Service fb6fa5
            }
Packit Service fb6fa5
        }
Packit Service fb6fa5
    }
Packit Service fb6fa5
    FreeStorage(SLLBlock.next);	
Packit Service fb6fa5
    (void) PtsToRegion(numFullPtBlocks, iPts, &FirstPtBlock, region);
Packit Service fb6fa5
    for (curPtBlock = FirstPtBlock.next; --numFullPtBlocks >= 0;) {
Packit Service fb6fa5
	tmpPtBlock = curPtBlock->next;
Packit Service fb6fa5
	g_free (curPtBlock);
Packit Service fb6fa5
	curPtBlock = tmpPtBlock;
Packit Service fb6fa5
    }
Packit Service fb6fa5
    g_free (pETEs);
Packit Service fb6fa5
    return(region);
Packit Service fb6fa5
}
Packit Service fb6fa5
Packit Service fb6fa5
#define __GDK_POLYREG_GENERIC_C__
Packit Service fb6fa5
#include "gdkaliasdef.c"