mi_plygen.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. /* This file is part of the GNU libxmi package.
  2. Copyright (C) 1985, 1986, 1987, 1988, 1989, X Consortium. For an
  3. associated permission notice, see the accompanying file README-X.
  4. GNU enhancements Copyright (C) 1998, 1999, 2000, 2005, Free Software
  5. Foundation, Inc.
  6. The GNU libxmi package is free software. You may redistribute it
  7. and/or modify it under the terms of the GNU General Public License as
  8. published by the Free Software foundation; either version 2, or (at your
  9. option) any later version.
  10. The GNU libxmi package is distributed in the hope that it will be
  11. useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. General Public License for more details.
  14. You should have received a copy of the GNU General Public License along
  15. with the GNU plotutils package; see the file COPYING. If not, write to
  16. the Free Software Foundation, Inc., 51 Franklin St., Fifth Floor,
  17. Boston, MA 02110-1301, USA. */
  18. #include "sys-defines.h"
  19. #include "extern.h"
  20. #include "xmi.h"
  21. #include "mi_spans.h"
  22. #include "mi_gc.h"
  23. #include "mi_api.h"
  24. #include "mi_scanfill.h"
  25. #include "mi_ply.h"
  26. /*
  27. *
  28. * Original author: Brian Kelleher, Oct. 1985.
  29. * Hacked by Robert S. Maier, 1998-9.
  30. *
  31. * Routine to fill a general (i.e., possibly non-convex or
  32. * self-intersecting) polygon. Two fill rules are supported: WINDING and
  33. * EVENODD. All painting goes through the low-level MI_PAINT_SPANS()
  34. * macro.
  35. *
  36. * This calls utility routines in mi_plyutil.c. See mi_scanfill.h for a
  37. * complete description of the algorithm. */
  38. /* ARGS: count = number of points, ptsIn = the points */
  39. void
  40. miFillGeneralPoly (miPaintedSet *paintedSet, const miGC *pGC, int count, const miPoint *ptsIn)
  41. {
  42. EdgeTableEntry *pAET; /* the Active Edge Table */
  43. int y; /* the current scanline */
  44. int nPts = 0; /* number of pts in buffer */
  45. EdgeTableEntry *pWETE; /* Winding Edge Table */
  46. ScanLineList *pSLL; /* Current ScanLineList */
  47. miPoint *ptsOut; /* ptr to output buffers */
  48. unsigned int *width;
  49. miPoint FirstPoint[NUMPTSTOBUFFER]; /* the output buffers */
  50. unsigned int FirstWidth[NUMPTSTOBUFFER];
  51. EdgeTableEntry *pPrevAET; /* previous AET entry */
  52. EdgeTable ET; /* Edge Table header node */
  53. EdgeTableEntry AET; /* Active ET header node */
  54. EdgeTableEntry *pETEs; /* Edge Table Entries buff */
  55. ScanLineListBlock SLLBlock; /* header for ScanLineList */
  56. bool fixWAET = false;
  57. if (count <= 2)
  58. return;
  59. pETEs = (EdgeTableEntry *) mi_xmalloc(sizeof(EdgeTableEntry) * count);
  60. ptsOut = FirstPoint;
  61. width = FirstWidth;
  62. miCreateETandAET (count, ptsIn, &ET, &AET, pETEs, &SLLBlock);
  63. pSLL = ET.scanlines.next;
  64. if (pGC->fillRule == (int)MI_EVEN_ODD_RULE)
  65. {
  66. /*
  67. * for each scanline
  68. */
  69. for (y = ET.ymin; y < ET.ymax; y++)
  70. {
  71. /*
  72. * Add a new edge to the active edge table when we
  73. * get to the next edge.
  74. */
  75. if (pSLL && y == pSLL->scanline)
  76. {
  77. miloadAET(&AET, pSLL->edgelist);
  78. pSLL = pSLL->next;
  79. }
  80. pPrevAET = &AET;
  81. pAET = AET.next;
  82. /*
  83. * for each active edge
  84. */
  85. while (pAET)
  86. {
  87. ptsOut->x = pAET->bres.minor_axis;
  88. ptsOut++->y = y;
  89. *width++ = (unsigned int)(pAET->next->bres.minor_axis - pAET->bres.minor_axis);
  90. nPts++;
  91. /*
  92. * send out the buffer when its full
  93. */
  94. if (nPts == NUMPTSTOBUFFER)
  95. {
  96. MI_COPY_AND_PAINT_SPANS(paintedSet, pGC->pixels[1], nPts, FirstPoint, FirstWidth)
  97. ptsOut = FirstPoint;
  98. width = FirstWidth;
  99. nPts = 0;
  100. }
  101. EVALUATEEDGEEVENODD(pAET, pPrevAET, y)
  102. EVALUATEEDGEEVENODD(pAET, pPrevAET, y);
  103. }
  104. miInsertionSort(&AET);
  105. }
  106. }
  107. else /* default to WindingNumber */
  108. {
  109. /*
  110. * for each scanline
  111. */
  112. for (y = ET.ymin; y < ET.ymax; y++)
  113. {
  114. /*
  115. * Add a new edge to the active edge table when we
  116. * get to the next edge.
  117. */
  118. if (pSLL && y == pSLL->scanline)
  119. {
  120. miloadAET(&AET, pSLL->edgelist);
  121. micomputeWAET(&AET);
  122. pSLL = pSLL->next;
  123. }
  124. pPrevAET = &AET;
  125. pAET = AET.next;
  126. pWETE = pAET;
  127. /*
  128. * for each active edge
  129. */
  130. while (pAET)
  131. {
  132. /*
  133. * if the next edge in the active edge table is
  134. * also the next edge in the winding active edge
  135. * table.
  136. */
  137. if (pWETE == pAET)
  138. {
  139. ptsOut->x = pAET->bres.minor_axis;
  140. ptsOut++->y = y;
  141. *width++ = (unsigned int)(pAET->nextWETE->bres.minor_axis - pAET->bres.minor_axis);
  142. nPts++;
  143. /*
  144. * send out the buffer
  145. */
  146. if (nPts == NUMPTSTOBUFFER)
  147. {
  148. MI_COPY_AND_PAINT_SPANS(paintedSet, pGC->pixels[1], nPts, FirstPoint, FirstWidth)
  149. ptsOut = FirstPoint;
  150. width = FirstWidth;
  151. nPts = 0;
  152. }
  153. pWETE = pWETE->nextWETE;
  154. while (pWETE != pAET)
  155. EVALUATEEDGEWINDING(pAET, pPrevAET, y, fixWAET);
  156. pWETE = pWETE->nextWETE;
  157. }
  158. EVALUATEEDGEWINDING(pAET, pPrevAET, y, fixWAET);
  159. }
  160. /*
  161. * reevaluate the Winding active edge table if we
  162. * just had to resort it or if we just exited an edge.
  163. */
  164. if (miInsertionSort(&AET) || fixWAET)
  165. {
  166. micomputeWAET(&AET);
  167. fixWAET = false;
  168. }
  169. }
  170. }
  171. /*
  172. * Get any spans that we missed by buffering
  173. */
  174. MI_COPY_AND_PAINT_SPANS(paintedSet, pGC->pixels[1], nPts, FirstPoint, FirstWidth)
  175. free (pETEs);
  176. miFreeStorage(SLLBlock.next);
  177. }