home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / evbl0627.zip / everblue_20010627.zip / x11 / Xlib_PolyReg.c < prev    next >
C/C++ Source or Header  |  1999-11-02  |  20KB  |  646 lines

  1. /* $XConsortium: PolyReg.c,v 11.23 94/11/17 21:59:37 converse Exp $ */
  2. /************************************************************************
  3.  
  4. Copyright (c) 1987  X Consortium
  5.  
  6. Permission is hereby granted, free of charge, to any person obtaining a copy
  7. of this software and associated documentation files (the "Software"), to deal
  8. in the Software without restriction, including without limitation the rights
  9. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10. copies of the Software, and to permit persons to whom the Software is
  11. furnished to do so, subject to the following conditions:
  12.  
  13. The above copyright notice and this permission notice shall be included in
  14. all copies or substantial portions of the Software.
  15.  
  16. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
  19. X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  20. AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  21. CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  22.  
  23. Except as contained in this notice, the name of the X Consortium shall not be
  24. used in advertising or otherwise to promote the sale, use or other dealings
  25. in this Software without prior written authorization from the X Consortium.
  26.  
  27.  
  28. Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
  29.  
  30.                         All Rights Reserved
  31.  
  32. Permission to use, copy, modify, and distribute this software and its 
  33. documentation for any purpose and without fee is hereby granted, 
  34. provided that the above copyright notice appear in all copies and that
  35. both that copyright notice and this permission notice appear in 
  36. supporting documentation, and that the name of Digital not be
  37. used in advertising or publicity pertaining to distribution of the
  38. software without specific, written prior permission.  
  39.  
  40. DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  41. ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  42. DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  43. ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  44. WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  45. ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  46. SOFTWARE.
  47.  
  48. ************************************************************************/
  49. /* $XFree86: xc/lib/X11/PolyReg.c,v 1.1.1.2.8.2 1998/10/04 15:22:49 hohndel Exp $ */
  50.  
  51. #define LARGE_COORDINATE 1000000
  52. #define SMALL_COORDINATE -LARGE_COORDINATE
  53.  
  54. #include "Xlib_private.h"
  55. #include "X11/Xutil.h"
  56. #include "region.h"
  57. #include "poly.h"
  58.  
  59. /*
  60.  *     InsertEdgeInET
  61.  *
  62.  *     Insert the given edge into the edge table.
  63.  *     First we must find the correct bucket in the
  64.  *     Edge table, then find the right slot in the
  65.  *     bucket.  Finally, we can insert it.
  66.  *
  67.  */
  68. static void
  69. InsertEdgeInET(ET, ETE, scanline, SLLBlock, iSLLBlock)
  70.     EdgeTable *ET;
  71.     EdgeTableEntry *ETE;
  72.     int scanline;
  73.     ScanLineListBlock **SLLBlock;
  74.     int *iSLLBlock;
  75. {
  76.     DBUG_ENTER("InsertEdgeInET")
  77.     register EdgeTableEntry *start, *prev;
  78.     register ScanLineList *pSLL, *pPrevSLL;
  79.     ScanLineListBlock *tmpSLLBlock;
  80.  
  81.     /*
  82.      * find the right bucket to put the edge into
  83.      */
  84.     pPrevSLL = &ET->scanlines;
  85.     pSLL = pPrevSLL->next;
  86.     while (pSLL && (pSLL->scanline < scanline)) 
  87.     {
  88.         pPrevSLL = pSLL;
  89.         pSLL = pSLL->next;
  90.     }
  91.  
  92.     /*
  93.      * reassign pSLL (pointer to ScanLineList) if necessary
  94.      */
  95.     if ((!pSLL) || (pSLL->scanline > scanline)) 
  96.     {
  97.         if (*iSLLBlock > SLLSPERBLOCK-1) 
  98.         {
  99.             tmpSLLBlock = 
  100.           (ScanLineListBlock *)Xmalloc(sizeof(ScanLineListBlock));
  101.             (*SLLBlock)->next = tmpSLLBlock;
  102.             tmpSLLBlock->next = (ScanLineListBlock *)NULL;
  103.             *SLLBlock = tmpSLLBlock;
  104.             *iSLLBlock = 0;
  105.         }
  106.         pSLL = &((*SLLBlock)->SLLs[(*iSLLBlock)++]);
  107.  
  108.         pSLL->next = pPrevSLL->next;
  109.         pSLL->edgelist = (EdgeTableEntry *)NULL;
  110.         pPrevSLL->next = pSLL;
  111.     }
  112.     pSLL->scanline = scanline;
  113.  
  114.     /*
  115.      * now insert the edge in the right bucket
  116.      */
  117.     prev = (EdgeTableEntry *)NULL;
  118.     start = pSLL->edgelist;
  119.     while (start && (start->bres.minor_axis < ETE->bres.minor_axis)) 
  120.     {
  121.         prev = start;
  122.         start = start->next;
  123.     }
  124.     ETE->next = start;
  125.  
  126.     if (prev)
  127.         prev->next = ETE;
  128.     else
  129.         pSLL->edgelist = ETE;
  130.     DBUG_VOID_RETURN;
  131. }
  132.  
  133. /*
  134.  *     CreateEdgeTable
  135.  *
  136.  *     This routine creates the edge table for
  137.  *     scan converting polygons. 
  138.  *     The Edge Table (ET) looks like:
  139.  *
  140.  *    EdgeTable
  141.  *     --------
  142.  *    |  ymax  |        ScanLineLists
  143.  *    |scanline|-->------------>-------------->...
  144.  *     --------   |scanline|   |scanline|
  145.  *                |edgelist|   |edgelist|
  146.  *                ---------    ---------
  147.  *                    |             |
  148.  *                    |             |
  149.  *                    V             V
  150.  *              list of ETEs   list of ETEs
  151.  *
  152.  *     where ETE is an EdgeTableEntry data structure,
  153.  *     and there is one ScanLineList per scanline at
  154.  *     which an edge is initially entered.
  155.  *
  156.  */
  157.  
  158. static void
  159. CreateETandAET(count, pts, ET, AET, pETEs, pSLLBlock)
  160.     register int count;
  161.     register XPoint *pts;
  162.     EdgeTable *ET;
  163.     EdgeTableEntry *AET;
  164.     register EdgeTableEntry *pETEs;
  165.     ScanLineListBlock   *pSLLBlock;
  166. {
  167.     DBUG_ENTER("CreateETandAET")
  168.     register XPoint *top, *bottom;
  169.     register XPoint *PrevPt, *CurrPt;
  170.     int iSLLBlock = 0;
  171.     int dy;
  172.  
  173.     if (count < 2)  DBUG_VOID_RETURN;
  174.  
  175.     /*
  176.      *  initialize the Active Edge Table
  177.      */
  178.     AET->next = (EdgeTableEntry *)NULL;
  179.     AET->back = (EdgeTableEntry *)NULL;
  180.     AET->nextWETE = (EdgeTableEntry *)NULL;
  181.     AET->bres.minor_axis = SMALL_COORDINATE;
  182.  
  183.     /*
  184.      *  initialize the Edge Table.
  185.      */
  186.     ET->scanlines.next = (ScanLineList *)NULL;
  187.     ET->ymax = SMALL_COORDINATE;
  188.     ET->ymin = LARGE_COORDINATE;
  189.     pSLLBlock->next = (ScanLineListBlock *)NULL;
  190.  
  191.     PrevPt = &pts[count-1];
  192.  
  193.     /*
  194.      *  for each vertex in the array of points.
  195.      *  In this loop we are dealing with two vertices at
  196.      *  a time -- these make up one edge of the polygon.
  197.      */
  198.     while (count--) 
  199.     {
  200.         CurrPt = pts++;
  201.  
  202.         /*
  203.          *  find out which point is above and which is below.
  204.          */
  205.         if (PrevPt->y > CurrPt->y) 
  206.         {
  207.             bottom = PrevPt, top = CurrPt;
  208.             pETEs->ClockWise = 0;
  209.         }
  210.         else 
  211.         {
  212.             bottom = CurrPt, top = PrevPt;
  213.             pETEs->ClockWise = 1;
  214.         }
  215.  
  216.         /*
  217.          * don't add horizontal edges to the Edge table.
  218.          */
  219.         if (bottom->y != top->y) 
  220.         {
  221.             pETEs->ymax = bottom->y-1;  /* -1 so we don't get last scanline */
  222.  
  223.             /*
  224.              *  initialize integer edge algorithm
  225.              */
  226.             dy = bottom->y - top->y;
  227.             BRESINITPGONSTRUCT(dy, top->x, bottom->x, pETEs->bres);
  228.  
  229.             InsertEdgeInET(ET, pETEs, top->y, &pSLLBlock, &iSLLBlock);
  230.  
  231.         if (PrevPt->y > ET->ymax)
  232.         ET->ymax = PrevPt->y;
  233.         if (PrevPt->y < ET->ymin)
  234.         ET->ymin = PrevPt->y;
  235.             pETEs++;
  236.         }
  237.  
  238.         PrevPt = CurrPt;
  239.     }
  240.     DBUG_VOID_RETURN;
  241. }
  242.  
  243. /*
  244.  *     loadAET
  245.  *
  246.  *     This routine moves EdgeTableEntries from the
  247.  *     EdgeTable into the Active Edge Table,
  248.  *     leaving them sorted by smaller x coordinate.
  249.  *
  250.  */
  251.  
  252. static void
  253. loadAET(AET, ETEs)
  254.     register EdgeTableEntry *AET, *ETEs;
  255. {
  256.     DBUG_ENTER("loadAET")
  257.     register EdgeTableEntry *pPrevAET;
  258.     register EdgeTableEntry *tmp;
  259.  
  260.     pPrevAET = AET;
  261.     AET = AET->next;
  262.     while (ETEs) 
  263.     {
  264.         while (AET && (AET->bres.minor_axis < ETEs->bres.minor_axis)) 
  265.         {
  266.             pPrevAET = AET;
  267.             AET = AET->next;
  268.         }
  269.         tmp = ETEs->next;
  270.         ETEs->next = AET;
  271.         if (AET)
  272.             AET->back = ETEs;
  273.         ETEs->back = pPrevAET;
  274.         pPrevAET->next = ETEs;
  275.         pPrevAET = ETEs;
  276.  
  277.         ETEs = tmp;
  278.     }
  279.     DBUG_VOID_RETURN;
  280. }
  281.  
  282. /*
  283.  *     computeWAET
  284.  *
  285.  *     This routine links the AET by the
  286.  *     nextWETE (winding EdgeTableEntry) link for
  287.  *     use by the winding number rule.  The final 
  288.  *     Active Edge Table (AET) might look something
  289.  *     like:
  290.  *
  291.  *     AET
  292.  *     ----------  ---------   ---------
  293.  *     |ymax    |  |ymax    |  |ymax    | 
  294.  *     | ...    |  |...     |  |...     |
  295.  *     |next    |->|next    |->|next    |->...
  296.  *     |nextWETE|  |nextWETE|  |nextWETE|
  297.  *     ---------   ---------   ^--------
  298.  *         |                   |       |
  299.  *         V------------------->       V---> ...
  300.  *
  301.  */
  302. static void
  303. computeWAET(AET)
  304.     register EdgeTableEntry *AET;
  305. {
  306.     DBUG_ENTER("computeWAET")
  307.     register EdgeTableEntry *pWETE;
  308.     register int inside = 1;
  309.     register int isInside = 0;
  310.  
  311.     AET->nextWETE = (EdgeTableEntry *)NULL;
  312.     pWETE = AET;
  313.     AET = AET->next;
  314.     while (AET) 
  315.     {
  316.         if (AET->ClockWise)
  317.             isInside++;
  318.         else
  319.             isInside--;
  320.  
  321.         if ((!inside && !isInside) ||
  322.             ( inside &&  isInside)) 
  323.         {
  324.             pWETE->nextWETE = AET;
  325.             pWETE = AET;
  326.             inside = !inside;
  327.         }
  328.         AET = AET->next;
  329.     }
  330.     pWETE->nextWETE = (EdgeTableEntry *)NULL;
  331.     DBUG_VOID_RETURN;
  332. }
  333.  
  334. /*
  335.  *     InsertionSort
  336.  *
  337.  *     Just a simple insertion sort using
  338.  *     pointers and back pointers to sort the Active
  339.  *     Edge Table.
  340.  *
  341.  */
  342.  
  343. static int
  344. InsertionSort(AET)
  345.     register EdgeTableEntry *AET;
  346. {
  347.     DBUG_ENTER("InsertionSort")
  348.     register EdgeTableEntry *pETEchase;
  349.     register EdgeTableEntry *pETEinsert;
  350.     register EdgeTableEntry *pETEchaseBackTMP;
  351.     register int changed = 0;
  352.  
  353.     AET = AET->next;
  354.     while (AET) 
  355.     {
  356.         pETEinsert = AET;
  357.         pETEchase = AET;
  358.         while (pETEchase->back->bres.minor_axis > AET->bres.minor_axis)
  359.             pETEchase = pETEchase->back;
  360.  
  361.         AET = AET->next;
  362.         if (pETEchase != pETEinsert) 
  363.         {
  364.             pETEchaseBackTMP = pETEchase->back;
  365.             pETEinsert->back->next = AET;
  366.             if (AET)
  367.                 AET->back = pETEinsert->back;
  368.             pETEinsert->next = pETEchase;
  369.             pETEchase->back->next = pETEinsert;
  370.             pETEchase->back = pETEinsert;
  371.             pETEinsert->back = pETEchaseBackTMP;
  372.             changed = 1;
  373.         }
  374.     }
  375.     DBUG_RETURN(changed);
  376. }
  377.  
  378. /*
  379.  *     Clean up our act.
  380.  */
  381. static void
  382. FreeStorage(pSLLBlock)
  383.     register ScanLineListBlock   *pSLLBlock;
  384. {
  385.     DBUG_ENTER("FreeStorage")
  386.     register ScanLineListBlock   *tmpSLLBlock;
  387.  
  388.     while (pSLLBlock) 
  389.     {
  390.         tmpSLLBlock = pSLLBlock->next;
  391.         Xfree((char *)pSLLBlock);
  392.         pSLLBlock = tmpSLLBlock;
  393.     }
  394.     DBUG_VOID_RETURN;
  395. }
  396.  
  397. /*
  398.  *     Create an array of rectangles from a list of points.
  399.  *     If indeed these things (POINTS, RECTS) are the same,
  400.  *     then this proc is still needed, because it allocates
  401.  *     storage for the array, which was allocated on the
  402.  *     stack by the calling procedure.
  403.  *
  404.  */
  405. static int PtsToRegion(numFullPtBlocks, iCurPtBlock, FirstPtBlock, reg)
  406.     register int  numFullPtBlocks, iCurPtBlock;
  407.     POINTBLOCK *FirstPtBlock;
  408.     REGION *reg;
  409. {
  410.     DBUG_ENTER("PtsToRegion")
  411.     register BOX  *rects;
  412.     register XPoint *pts;
  413.     register POINTBLOCK *CurPtBlock;
  414.     register int i;
  415.     register BOX *extents;
  416.     register int numRects;
  417.     BOX *prevRects = reg->rects;
  418.  
  419.     extents = ®->extents;
  420.  
  421.     numRects = ((numFullPtBlocks * NUMPTSTOBUFFER) + iCurPtBlock) >> 1;
  422.  
  423.     if (!(reg->rects = (BOX *)Xrealloc((char *)reg->rects, 
  424.         (unsigned) (sizeof(BOX) * numRects))))  {
  425.     Xfree(prevRects);
  426.     DBUG_RETURN(0);
  427.     }
  428.  
  429.     reg->size = numRects;
  430.     CurPtBlock = FirstPtBlock;
  431.     rects = reg->rects - 1;
  432.     numRects = 0;
  433.     extents->x1 = MAXSHORT,  extents->x2 = MINSHORT;
  434.  
  435.     for ( ; numFullPtBlocks >= 0; numFullPtBlocks--) {
  436.     /* the loop uses 2 points per iteration */
  437.     i = NUMPTSTOBUFFER >> 1;
  438.     if (!numFullPtBlocks)
  439.         i = iCurPtBlock >> 1;
  440.     for (pts = CurPtBlock->pts; i--; pts += 2) {
  441.         if (pts->x == pts[1].x)
  442.         continue;
  443.         if (numRects && pts->x == rects->x1 && pts->y == rects->y2 &&
  444.         pts[1].x == rects->x2 &&
  445.         (numRects == 1 || rects[-1].y1 != rects->y1) &&
  446.         (i && pts[2].y > pts[1].y)) {
  447.         rects->y2 = pts[1].y + 1;
  448.         continue;
  449.         }
  450.         numRects++;
  451.         rects++;
  452.         rects->x1 = pts->x;  rects->y1 = pts->y;
  453.         rects->x2 = pts[1].x;  rects->y2 = pts[1].y + 1;
  454.         if (rects->x1 < extents->x1)
  455.         extents->x1 = rects->x1;
  456.         if (rects->x2 > extents->x2)
  457.         extents->x2 = rects->x2;
  458.         }
  459.     CurPtBlock = CurPtBlock->next;
  460.     }
  461.  
  462.     if (numRects) {
  463.     extents->y1 = reg->rects->y1;
  464.     extents->y2 = rects->y2;
  465.     } else {
  466.     extents->x1 = 0;
  467.     extents->y1 = 0;
  468.     extents->x2 = 0;
  469.     extents->y2 = 0;
  470.     }
  471.     reg->numRects = numRects;
  472.  
  473.     DBUG_RETURN(TRUE);
  474. }
  475.  
  476. /*
  477.  *     polytoregion
  478.  *
  479.  *     Scan converts a polygon by returning a run-length
  480.  *     encoding of the resultant bitmap -- the run-length
  481.  *     encoding is in the form of an array of rectangles.
  482.  */
  483. Region 
  484. XPolygonRegion(Pts, Count, rule)
  485.     int       Count;                 /* number of pts           */
  486.     XPoint     *Pts;             /* the pts                 */
  487.     int    rule;                 /* winding rule */
  488. {
  489.     DBUG_ENTER("XPolygonRegion")
  490.     Region region;
  491.     register EdgeTableEntry *pAET;   /* Active Edge Table       */
  492.     register int y;                  /* current scanline        */
  493.     register int iPts = 0;           /* number of pts in buffer */
  494.     register EdgeTableEntry *pWETE;  /* Winding Edge Table Entry*/
  495.     register ScanLineList *pSLL;     /* current scanLineList    */
  496.     register XPoint *pts;             /* output buffer           */
  497.     EdgeTableEntry *pPrevAET;        /* ptr to previous AET     */
  498.     EdgeTable ET;                    /* header node for ET      */
  499.     EdgeTableEntry AET;              /* header node for AET     */
  500.     EdgeTableEntry *pETEs;           /* EdgeTableEntries pool   */
  501.     ScanLineListBlock SLLBlock;      /* header for scanlinelist */
  502.     int fixWAET = FALSE;
  503.     POINTBLOCK FirstPtBlock, *curPtBlock; /* PtBlock buffers    */
  504.     POINTBLOCK *tmpPtBlock;
  505.     int numFullPtBlocks = 0;
  506.  
  507.     if (! (region = XCreateRegion())) DBUG_RETURN((Region) NULL);
  508.  
  509.     /* special case a rectangle */
  510.     pts = Pts;
  511.     if (((Count == 4) ||
  512.      ((Count == 5) && (pts[4].x == pts[0].x) && (pts[4].y == pts[0].y))) &&
  513.     (((pts[0].y == pts[1].y) &&
  514.       (pts[1].x == pts[2].x) &&
  515.       (pts[2].y == pts[3].y) &&
  516.       (pts[3].x == pts[0].x)) ||
  517.      ((pts[0].x == pts[1].x) &&
  518.       (pts[1].y == pts[2].y) &&
  519.       (pts[2].x == pts[3].x) &&
  520.       (pts[3].y == pts[0].y)))) {
  521.     region->extents.x1 = min(pts[0].x, pts[2].x);
  522.     region->extents.y1 = min(pts[0].y, pts[2].y);
  523.     region->extents.x2 = max(pts[0].x, pts[2].x);
  524.     region->extents.y2 = max(pts[0].y, pts[2].y);
  525.     if ((region->extents.x1 != region->extents.x2) &&
  526.         (region->extents.y1 != region->extents.y2)) {
  527.         region->numRects = 1;
  528.         *(region->rects) = region->extents;
  529.     }
  530.     DBUG_RETURN(region);
  531.     }
  532.  
  533.     if (! (pETEs = (EdgeTableEntry *)
  534.        Xmalloc((unsigned) (sizeof(EdgeTableEntry) * Count))))
  535.     DBUG_RETURN((Region) NULL);
  536.  
  537.     pts = FirstPtBlock.pts;
  538.     CreateETandAET(Count, Pts, &ET, &AET, pETEs, &SLLBlock);
  539.     pSLL = ET.scanlines.next;
  540.     curPtBlock = &FirstPtBlock;
  541.  
  542.     if (rule == EvenOddRule) {
  543.         /*
  544.          *  for each scanline
  545.          */
  546.         for (y = ET.ymin; y < ET.ymax; y++) {
  547.             /*
  548.              *  Add a new edge to the active edge table when we
  549.              *  get to the next edge.
  550.              */
  551.             if (pSLL != NULL && y == pSLL->scanline) {
  552.                 loadAET(&AET, pSLL->edgelist);
  553.                 pSLL = pSLL->next;
  554.             }
  555.             pPrevAET = &AET;
  556.             pAET = AET.next;
  557.  
  558.             /*
  559.              *  for each active edge
  560.              */
  561.             while (pAET) {
  562.                 pts->x = pAET->bres.minor_axis,  pts->y = y;
  563.                 pts++, iPts++;
  564.  
  565.                 /*
  566.                  *  send out the buffer
  567.                  */
  568.                 if (iPts == NUMPTSTOBUFFER) {
  569.                     tmpPtBlock = (POINTBLOCK *)Xmalloc(sizeof(POINTBLOCK));
  570.                     curPtBlock->next = tmpPtBlock;
  571.                     curPtBlock = tmpPtBlock;
  572.                     pts = curPtBlock->pts;
  573.                     numFullPtBlocks++;
  574.                     iPts = 0;
  575.                 }
  576.                 EVALUATEEDGEEVENODD(pAET, pPrevAET, y);
  577.             }
  578.             (void) InsertionSort(&AET);
  579.         }
  580.     }
  581.     else {
  582.         /*
  583.          *  for each scanline
  584.          */
  585.         for (y = ET.ymin; y < ET.ymax; y++) {
  586.             /*
  587.              *  Add a new edge to the active edge table when we
  588.              *  get to the next edge.
  589.              */
  590.             if (pSLL != NULL && y == pSLL->scanline) {
  591.                 loadAET(&AET, pSLL->edgelist);
  592.                 computeWAET(&AET);
  593.                 pSLL = pSLL->next;
  594.             }
  595.             pPrevAET = &AET;
  596.             pAET = AET.next;
  597.             pWETE = pAET;
  598.  
  599.             /*
  600.              *  for each active edge
  601.              */
  602.             while (pAET) {
  603.                 /*
  604.                  *  add to the buffer only those edges that
  605.                  *  are in the Winding active edge table.
  606.                  */
  607.                 if (pWETE == pAET) {
  608.                     pts->x = pAET->bres.minor_axis,  pts->y = y;
  609.                     pts++, iPts++;
  610.  
  611.                     /*
  612.                      *  send out the buffer
  613.                      */
  614.                     if (iPts == NUMPTSTOBUFFER) {
  615.                         tmpPtBlock = (POINTBLOCK *)Xmalloc(sizeof(POINTBLOCK));
  616.                         curPtBlock->next = tmpPtBlock;
  617.                         curPtBlock = tmpPtBlock;
  618.                         pts = curPtBlock->pts;
  619.                         numFullPtBlocks++;    iPts = 0;
  620.                     }
  621.                     pWETE = pWETE->nextWETE;
  622.                 }
  623.                 EVALUATEEDGEWINDING(pAET, pPrevAET, y, fixWAET);
  624.             }
  625.  
  626.             /*
  627.              *  recompute the winding active edge table if
  628.              *  we just resorted or have exited an edge.
  629.              */
  630.             if (InsertionSort(&AET) || fixWAET) {
  631.                 computeWAET(&AET);
  632.                 fixWAET = FALSE;
  633.             }
  634.         }
  635.     }
  636.     FreeStorage(SLLBlock.next);    
  637.     (void) PtsToRegion(numFullPtBlocks, iPts, &FirstPtBlock, region);
  638.     for (curPtBlock = FirstPtBlock.next; --numFullPtBlocks >= 0;) {
  639.     tmpPtBlock = curPtBlock->next;
  640.     Xfree((char *)curPtBlock);
  641.     curPtBlock = tmpPtBlock;
  642.     }
  643.     Xfree((char *)pETEs);
  644.     DBUG_RETURN(region);
  645. }
  646.