gxfillsl.h 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. /* Copyright (C) 2002 artofcode LLC. All rights reserved.
  2. This software is provided AS-IS with no warranty, either express or
  3. implied.
  4. This software is distributed under license and may not be copied,
  5. modified or distributed except as expressly authorized under the terms
  6. of the license contained in the file LICENSE in this distribution.
  7. For more information about licensing, please refer to
  8. http://www.ghostscript.com/licensing/. For information on
  9. commercial licensing, go to http://www.artifex.com/licensing/ or
  10. contact Artifex Software, Inc., 101 Lucas Valley Road #110,
  11. San Rafael, CA 94903, U.S.A., +1(415)492-9861.
  12. */
  13. /* $Id: gxfillsl.h,v 1.8 2005/02/15 14:47:37 igor Exp $ */
  14. /* Configurable algorithm for filling a path by scanlines. */
  15. /*
  16. * Since we need several statically defined variants of this agorithm,
  17. * we store it in .h file and include it several times into gxfill.c .
  18. * Configuration macros (template arguments) are :
  19. *
  20. * FILL_DIRECT - See LOOP_FILL_RECTANGLE_DIRECT.
  21. * TEMPLATE_spot_into_scanlines - the name of the procedure to generate.
  22. */
  23. private int
  24. TEMPLATE_spot_into_scanlines (line_list *ll, fixed band_mask)
  25. {
  26. const fill_options fo = *ll->fo;
  27. active_line *yll = ll->y_list;
  28. fixed y_limit = fo.ymax;
  29. /*
  30. * The meaning of adjust_below (B) and adjust_above (A) is that the
  31. * pixels that would normally be painted at coordinate Y get "smeared"
  32. * to coordinates Y-B through Y+A-epsilon, inclusive. This is
  33. * equivalent to saying that the pixels actually painted at coordinate Y
  34. * are those contributed by scan lines Y-A+epsilon through Y+B,
  35. * inclusive. (A = B = 0 is a special case, equivalent to B = 0, A =
  36. * epsilon.)
  37. */
  38. fixed y_frac_min =
  39. (fo.adjust_above == fixed_0 ? fixed_half :
  40. fixed_half + fixed_epsilon - fo.adjust_above);
  41. fixed y_frac_max =
  42. fixed_half + fo.adjust_below;
  43. int y0 = fixed2int(min_fixed);
  44. fixed y_bot = min_fixed; /* normally int2fixed(y0) + y_frac_min */
  45. fixed y_top = min_fixed; /* normally int2fixed(y0) + y_frac_max */
  46. fixed y = min_fixed;
  47. coord_range_list_t rlist;
  48. coord_range_t rlocal[MAX_LOCAL_ACTIVE];
  49. int code = 0;
  50. if (yll == 0) /* empty list */
  51. return 0;
  52. range_list_init(&rlist, rlocal, countof(rlocal), ll->memory);
  53. ll->x_list = 0;
  54. ll->x_head.x_current = min_fixed; /* stop backward scan */
  55. while (code >= 0) {
  56. active_line *alp, *nlp;
  57. fixed x;
  58. bool new_band;
  59. INCR(iter);
  60. move_al_by_y(ll, y); /* Skip horizontal pieces. */
  61. /*
  62. * Find the next sampling point, either the bottom of a sampling
  63. * band or a line start.
  64. */
  65. if (ll->x_list == 0)
  66. y = (yll == 0 ? ll->y_break : yll->start.y);
  67. else {
  68. y = y_bot + fixed_1;
  69. if (yll != 0)
  70. y = min(y, yll->start.y);
  71. for (alp = ll->x_list; alp != 0; alp = alp->next) {
  72. fixed yy = max(alp->fi.y3, alp->fi.y0);
  73. yy = max(yy, alp->end.y); /* Non-monotonic curves may have an inner extreme. */
  74. y = min(y, yy);
  75. }
  76. }
  77. /* Move newly active lines from y to x list. */
  78. while (yll != 0 && yll->start.y == y) {
  79. active_line *ynext = yll->next; /* insert smashes next/prev links */
  80. if (yll->direction == DIR_HORIZONTAL) {
  81. /* Ignore for now. */
  82. } else
  83. insert_x_new(yll, ll);
  84. yll = ynext;
  85. }
  86. /* Update active lines to y. */
  87. x = min_fixed;
  88. for (alp = ll->x_list; alp != 0; alp = nlp) {
  89. fixed nx;
  90. nlp = alp->next;
  91. e:if (alp->end.y <= y || alp->start.y == alp->end.y) {
  92. if (end_x_line(alp, ll, true))
  93. continue;
  94. if (alp->more_flattened)
  95. if (alp->end.y <= y || alp->start.y == alp->end.y)
  96. step_al(alp, true);
  97. goto e;
  98. }
  99. nx = alp->x_current = (alp->start.y >= y ? alp->start.x : AL_X_AT_Y(alp, y));
  100. if (nx < x) {
  101. /* Move this line backward in the list. */
  102. active_line *ilp = alp;
  103. while (nx < (ilp = ilp->prev)->x_current)
  104. DO_NOTHING;
  105. /* Now ilp->x_current <= nx < ilp->next->x_cur. */
  106. alp->prev->next = alp->next;
  107. if (alp->next)
  108. alp->next->prev = alp->prev;
  109. if (ilp->next)
  110. ilp->next->prev = alp;
  111. alp->next = ilp->next;
  112. ilp->next = alp;
  113. alp->prev = ilp;
  114. continue;
  115. }
  116. x = nx;
  117. }
  118. if (y > y_top || y >= y_limit) {
  119. /* We're beyond the end of the previous sampling band. */
  120. const coord_range_t *pcr;
  121. /* Fill the ranges for y0. */
  122. for (pcr = rlist.first.next; pcr != &rlist.last;
  123. pcr = pcr->next
  124. ) {
  125. int x0 = pcr->rmin, x1 = pcr->rmax;
  126. if_debug4('Q', "[Qr]draw 0x%lx: [%d,%d),%d\n", (ulong)pcr,
  127. x0, x1, y0);
  128. VD_RECT(x0, y0, x1 - x0, 1, VD_TRAP_COLOR);
  129. code = LOOP_FILL_RECTANGLE_DIRECT(&fo, x0, y0, x1 - x0, 1);
  130. if_debug3('F', "[F]drawing [%d:%d),%d\n", x0, x1, y0);
  131. if (code < 0)
  132. goto done;
  133. }
  134. range_list_reset(&rlist);
  135. /* Check whether we've reached the maximum y. */
  136. if (y >= y_limit)
  137. break;
  138. /* Reset the sampling band. */
  139. y0 = fixed2int(y);
  140. if (fixed_fraction(y) < y_frac_min)
  141. --y0;
  142. y_bot = int2fixed(y0) + y_frac_min;
  143. y_top = int2fixed(y0) + y_frac_max;
  144. new_band = true;
  145. } else
  146. new_band = false;
  147. if (y <= y_top) {
  148. /*
  149. * We're within the same Y pixel. Merge regions for segments
  150. * starting here (at y), up to y_top or the end of the segment.
  151. * If this is the first sampling within the band, run the
  152. * fill/eofill algorithm.
  153. */
  154. fixed y_min;
  155. if (new_band) {
  156. int inside = 0;
  157. INCR(band);
  158. for (alp = ll->x_list; alp != 0; alp = alp->next) {
  159. int x0 = fixed2int_pixround(alp->x_current - fo.adjust_left);
  160. for (;;) {
  161. /* We're inside a filled region. */
  162. print_al("step", alp);
  163. INCR(band_step);
  164. inside += alp->direction;
  165. if (!INSIDE_PATH_P(inside, fo.rule))
  166. break;
  167. /*
  168. * Since we're dealing with closed paths, the test
  169. * for alp == 0 shouldn't be needed, but we may have
  170. * omitted lines that are to the right of the
  171. * clipping region.
  172. */
  173. if ((alp = alp->next) == 0)
  174. goto out;
  175. }
  176. /* We just went from inside to outside, so fill the region. */
  177. code = range_list_add(&rlist, x0,
  178. fixed2int_rounded(alp->x_current +
  179. fo.adjust_right));
  180. if (code < 0)
  181. goto done;
  182. }
  183. out:
  184. y_min = min_fixed;
  185. } else
  186. y_min = y;
  187. code = merge_ranges(&rlist, ll, y_min, y_top);
  188. } /* else y < y_bot + 1, do nothing */
  189. }
  190. done:
  191. range_list_free(&rlist);
  192. return code;
  193. }