1 /* Copyright (C) 2002 artofcode LLC. All rights reserved.
2
3 This software is provided AS-IS with no warranty, either express or
4 implied.
5
6 This software is distributed under license and may not be copied,
7 modified or distributed except as expressly authorized under the terms
8 of the license contained in the file LICENSE in this distribution.
9
10 For more information about licensing, please refer to
11 http://www.ghostscript.com/licensing/. For information on
12 commercial licensing, go to http://www.artifex.com/licensing/ or
13 contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14 San Rafael, CA 94903, U.S.A., +1(415)492-9861.
15 */
16
17 /* $Id: gxfillts.h,v 1.5 2004/10/26 04:08:59 giles Exp $ */
18 /* Configurable algorithm for filling a slanted trapezoid. */
19
20 /*
21 * Since we need several statically defined variants of this agorithm,
22 * we store it in .h file and include it several times into gxfill.c .
23 * Configuration macros (template arguments) are :
24 *
25 * FILL_DIRECT - See LOOP_FILL_RECTANGLE_DIRECT.
26 * TEMPLATE_slant_into_trapezoids - the name of the procedure to generate.
27 */
28
29
30 private inline int
TEMPLATE_slant_into_trapezoids(const line_list * ll,const active_line * flp,const active_line * alp,fixed y,fixed y1)31 TEMPLATE_slant_into_trapezoids (const line_list *ll,
32 const active_line *flp, const active_line *alp, fixed y, fixed y1)
33 {
34 /*
35 * We want to get the effect of filling an area whose
36 * outline is formed by dragging a square of side adj2
37 * along the border of the trapezoid. This is *not*
38 * equivalent to simply expanding the corners by
39 * adjust: There are 3 cases needing different
40 * algorithms, plus rectangles as a fast special case.
41 */
42 const fill_options * const fo = ll->fo;
43 int xli = fixed2int_var_pixround(flp->x_next - fo->adjust_left);
44 gs_fixed_edge le, re;
45 int code = 0;
46 /*
47 * Define a faster test for
48 * fixed2int_pixround(y - below) != fixed2int_pixround(y + above)
49 * where we know
50 * 0 <= below <= _fixed_pixround_v,
51 * 0 <= above <= min(fixed_half, fixed_1 - below).
52 * Subtracting out the integer parts, this is equivalent to
53 * fixed2int_pixround(fixed_fraction(y) - below) !=
54 * fixed2int_pixround(fixed_fraction(y) + above)
55 * or to
56 * fixed2int(fixed_fraction(y) + _fixed_pixround_v - below) !=
57 * fixed2int(fixed_fraction(y) + _fixed_pixround_v + above)
58 * Letting A = _fixed_pixround_v - below and B = _fixed_pixround_v + above,
59 * we can rewrite this as
60 * fixed2int(fixed_fraction(y) + A) != fixed2int(fixed_fraction(y) + B)
61 * Because of the range constraints given above, this is true precisely when
62 * fixed_fraction(y) + A < fixed_1 && fixed_fraction(y) + B >= fixed_1
63 * or equivalently
64 * fixed_fraction(y + B) < B - A.
65 * i.e.
66 * fixed_fraction(y + _fixed_pixround_v + above) < below + above
67 */
68 fixed y_span_delta = _fixed_pixround_v + fo->adjust_above;
69 fixed y_span_limit = fo->adjust_below + fo->adjust_above;
70 le.start.x = flp->start.x - fo->adjust_left;
71 le.end.x = flp->end.x - fo->adjust_left;
72 re.start.x = alp->start.x + fo->adjust_right;
73 re.end.x = alp->end.x + fo->adjust_right;
74
75 #define ADJUSTED_Y_SPANS_PIXEL(y)\
76 (fixed_fraction((y) + y_span_delta) < y_span_limit)
77
78 if (le.end.x <= le.start.x) {
79 if (re.end.x >= re.start.x) { /* Top wider than bottom. */
80 le.start.y = flp->start.y - fo->adjust_below;
81 le.end.y = flp->end.y - fo->adjust_below;
82 re.start.y = alp->start.y - fo->adjust_below;
83 re.end.y = alp->end.y - fo->adjust_below;
84 code = loop_fill_trap_np(ll, &le, &re, y - fo->adjust_below, y1 - fo->adjust_below);
85 if (ADJUSTED_Y_SPANS_PIXEL(y1)) {
86 if (code < 0)
87 return code;
88 INCR(afill);
89 code = LOOP_FILL_RECTANGLE_DIRECT(fo,
90 xli, fixed2int_pixround(y1 - fo->adjust_below),
91 fixed2int_var_pixround(alp->x_next + fo->adjust_right) - xli, 1);
92 vd_rect(flp->x_next - fo->adjust_left, y1 - fo->adjust_below,
93 alp->x_next + fo->adjust_right, y1, 1, VD_TRAP_COLOR);
94 }
95 } else { /* Slanted trapezoid. */
96 code = fill_slant_adjust(ll, flp, alp, y, y1);
97 }
98 } else {
99 if (re.end.x <= re.start.x) { /* Bottom wider than top. */
100 if (ADJUSTED_Y_SPANS_PIXEL(y)) {
101 INCR(afill);
102 xli = fixed2int_var_pixround(flp->x_current - fo->adjust_left);
103 code = LOOP_FILL_RECTANGLE_DIRECT(fo,
104 xli, fixed2int_pixround(y - fo->adjust_below),
105 fixed2int_var_pixround(alp->x_current + fo->adjust_right) - xli, 1);
106 vd_rect(flp->x_current - fo->adjust_left, y - fo->adjust_below,
107 alp->x_current + fo->adjust_right, y, 1, VD_TRAP_COLOR);
108 if (code < 0)
109 return code;
110 }
111 le.start.y = flp->start.y + fo->adjust_above;
112 le.end.y = flp->end.y + fo->adjust_above;
113 re.start.y = alp->start.y + fo->adjust_above;
114 re.end.y = alp->end.y + fo->adjust_above;
115 code = loop_fill_trap_np(ll, &le, &re, y + fo->adjust_above, y1 + fo->adjust_above);
116 } else { /* Slanted trapezoid. */
117 code = fill_slant_adjust(ll, flp, alp, y, y1);
118 }
119 }
120 return code;
121 }
122
123