gxfillts.h 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  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: gxfillts.h,v 1.5 2004/10/26 04:08:59 giles Exp $ */
  14. /* Configurable algorithm for filling a slanted trapezoid. */
  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_slant_into_trapezoids - the name of the procedure to generate.
  22. */
  23. private inline int
  24. TEMPLATE_slant_into_trapezoids (const line_list *ll,
  25. const active_line *flp, const active_line *alp, fixed y, fixed y1)
  26. {
  27. /*
  28. * We want to get the effect of filling an area whose
  29. * outline is formed by dragging a square of side adj2
  30. * along the border of the trapezoid. This is *not*
  31. * equivalent to simply expanding the corners by
  32. * adjust: There are 3 cases needing different
  33. * algorithms, plus rectangles as a fast special case.
  34. */
  35. const fill_options * const fo = ll->fo;
  36. int xli = fixed2int_var_pixround(flp->x_next - fo->adjust_left);
  37. gs_fixed_edge le, re;
  38. int code = 0;
  39. /*
  40. * Define a faster test for
  41. * fixed2int_pixround(y - below) != fixed2int_pixround(y + above)
  42. * where we know
  43. * 0 <= below <= _fixed_pixround_v,
  44. * 0 <= above <= min(fixed_half, fixed_1 - below).
  45. * Subtracting out the integer parts, this is equivalent to
  46. * fixed2int_pixround(fixed_fraction(y) - below) !=
  47. * fixed2int_pixround(fixed_fraction(y) + above)
  48. * or to
  49. * fixed2int(fixed_fraction(y) + _fixed_pixround_v - below) !=
  50. * fixed2int(fixed_fraction(y) + _fixed_pixround_v + above)
  51. * Letting A = _fixed_pixround_v - below and B = _fixed_pixround_v + above,
  52. * we can rewrite this as
  53. * fixed2int(fixed_fraction(y) + A) != fixed2int(fixed_fraction(y) + B)
  54. * Because of the range constraints given above, this is true precisely when
  55. * fixed_fraction(y) + A < fixed_1 && fixed_fraction(y) + B >= fixed_1
  56. * or equivalently
  57. * fixed_fraction(y + B) < B - A.
  58. * i.e.
  59. * fixed_fraction(y + _fixed_pixround_v + above) < below + above
  60. */
  61. fixed y_span_delta = _fixed_pixround_v + fo->adjust_above;
  62. fixed y_span_limit = fo->adjust_below + fo->adjust_above;
  63. le.start.x = flp->start.x - fo->adjust_left;
  64. le.end.x = flp->end.x - fo->adjust_left;
  65. re.start.x = alp->start.x + fo->adjust_right;
  66. re.end.x = alp->end.x + fo->adjust_right;
  67. #define ADJUSTED_Y_SPANS_PIXEL(y)\
  68. (fixed_fraction((y) + y_span_delta) < y_span_limit)
  69. if (le.end.x <= le.start.x) {
  70. if (re.end.x >= re.start.x) { /* Top wider than bottom. */
  71. le.start.y = flp->start.y - fo->adjust_below;
  72. le.end.y = flp->end.y - fo->adjust_below;
  73. re.start.y = alp->start.y - fo->adjust_below;
  74. re.end.y = alp->end.y - fo->adjust_below;
  75. code = loop_fill_trap_np(ll, &le, &re, y - fo->adjust_below, y1 - fo->adjust_below);
  76. if (ADJUSTED_Y_SPANS_PIXEL(y1)) {
  77. if (code < 0)
  78. return code;
  79. INCR(afill);
  80. code = LOOP_FILL_RECTANGLE_DIRECT(fo,
  81. xli, fixed2int_pixround(y1 - fo->adjust_below),
  82. fixed2int_var_pixround(alp->x_next + fo->adjust_right) - xli, 1);
  83. vd_rect(flp->x_next - fo->adjust_left, y1 - fo->adjust_below,
  84. alp->x_next + fo->adjust_right, y1, 1, VD_TRAP_COLOR);
  85. }
  86. } else { /* Slanted trapezoid. */
  87. code = fill_slant_adjust(ll, flp, alp, y, y1);
  88. }
  89. } else {
  90. if (re.end.x <= re.start.x) { /* Bottom wider than top. */
  91. if (ADJUSTED_Y_SPANS_PIXEL(y)) {
  92. INCR(afill);
  93. xli = fixed2int_var_pixround(flp->x_current - fo->adjust_left);
  94. code = LOOP_FILL_RECTANGLE_DIRECT(fo,
  95. xli, fixed2int_pixround(y - fo->adjust_below),
  96. fixed2int_var_pixround(alp->x_current + fo->adjust_right) - xli, 1);
  97. vd_rect(flp->x_current - fo->adjust_left, y - fo->adjust_below,
  98. alp->x_current + fo->adjust_right, y, 1, VD_TRAP_COLOR);
  99. if (code < 0)
  100. return code;
  101. }
  102. le.start.y = flp->start.y + fo->adjust_above;
  103. le.end.y = flp->end.y + fo->adjust_above;
  104. re.start.y = alp->start.y + fo->adjust_above;
  105. re.end.y = alp->end.y + fo->adjust_above;
  106. code = loop_fill_trap_np(ll, &le, &re, y + fo->adjust_above, y1 + fo->adjust_above);
  107. } else { /* Slanted trapezoid. */
  108. code = fill_slant_adjust(ll, flp, alp, y, y1);
  109. }
  110. }
  111. return code;
  112. }