polyreg.c
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:21k
源码类别:

Symbian

开发平台:

C/C++

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