xref: /plan9-contrib/sys/src/cmd/gs/src/gxfill.h (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
1*593dc095SDavid du Colombier /* Copyright (C) 2003 Aladdin Enterprises.  All rights reserved.
2*593dc095SDavid du Colombier 
3*593dc095SDavid du Colombier   This software is provided AS-IS with no warranty, either express or
4*593dc095SDavid du Colombier   implied.
5*593dc095SDavid du Colombier 
6*593dc095SDavid du Colombier   This software is distributed under license and may not be copied,
7*593dc095SDavid du Colombier   modified or distributed except as expressly authorized under the terms
8*593dc095SDavid du Colombier   of the license contained in the file LICENSE in this distribution.
9*593dc095SDavid du Colombier 
10*593dc095SDavid du Colombier   For more information about licensing, please refer to
11*593dc095SDavid du Colombier   http://www.ghostscript.com/licensing/. For information on
12*593dc095SDavid du Colombier   commercial licensing, go to http://www.artifex.com/licensing/ or
13*593dc095SDavid du Colombier   contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14*593dc095SDavid du Colombier   San Rafael, CA  94903, U.S.A., +1(415)492-9861.
15*593dc095SDavid du Colombier */
16*593dc095SDavid du Colombier 
17*593dc095SDavid du Colombier /* $Id: gxfill.h,v 1.23 2004/10/26 03:51:16 giles Exp $ */
18*593dc095SDavid du Colombier /* Common structures for the filling algorithm and dropout prevention. */
19*593dc095SDavid du Colombier 
20*593dc095SDavid du Colombier #ifndef gxfill_INCLUDED
21*593dc095SDavid du Colombier #  define gxfill_INCLUDED
22*593dc095SDavid du Colombier 
23*593dc095SDavid du Colombier /* Define the structure for keeping track of active lines. */
24*593dc095SDavid du Colombier #ifndef active_line_DEFINED
25*593dc095SDavid du Colombier #  define active_line_DEFINED
26*593dc095SDavid du Colombier typedef struct active_line_s active_line;
27*593dc095SDavid du Colombier #endif
28*593dc095SDavid du Colombier struct active_line_s {
29*593dc095SDavid du Colombier     gs_fixed_point start;	/* x,y where line starts */
30*593dc095SDavid du Colombier     gs_fixed_point end; 	/* x,y where line ends */
31*593dc095SDavid du Colombier     gs_fixed_point diff;	/* end - start */
32*593dc095SDavid du Colombier     fixed y_fast_max;		/* can do x_at_y in fixed point */
33*593dc095SDavid du Colombier 				/* if y <= y_fast_max */
34*593dc095SDavid du Colombier     fixed num_adjust;		/* 0 if diff.x >= 0, -diff.y + epsilon if */
35*593dc095SDavid du Colombier 				/* diff.x < 0 and division truncates */
36*593dc095SDavid du Colombier #if ARCH_DIV_NEG_POS_TRUNCATES
37*593dc095SDavid du Colombier     /* neg/pos truncates, we must bias the numberator. */
38*593dc095SDavid du Colombier #  define SET_NUM_ADJUST(alp) \
39*593dc095SDavid du Colombier     (alp)->num_adjust =\
40*593dc095SDavid du Colombier       ((alp)->diff.x >= 0 ? 0 : -(alp)->diff.y + fixed_epsilon)
41*593dc095SDavid du Colombier #  define ADD_NUM_ADJUST(num, alp) ((num) + (alp)->num_adjust)
42*593dc095SDavid du Colombier #  define MAX_MINUS_NUM_ADJUST(alp) ADD_NUM_ADJUST(max_fixed, alp)
43*593dc095SDavid du Colombier #else
44*593dc095SDavid du Colombier     /* neg/pos takes the floor, no special action is needed. */
45*593dc095SDavid du Colombier #  define SET_NUM_ADJUST(alp) DO_NOTHING
46*593dc095SDavid du Colombier #  define ADD_NUM_ADJUST(num, alp) (num)
47*593dc095SDavid du Colombier #  define MAX_MINUS_NUM_ADJUST(alp) max_fixed
48*593dc095SDavid du Colombier #endif
49*593dc095SDavid du Colombier #define SET_AL_POINTS(alp, startp, endp)\
50*593dc095SDavid du Colombier   BEGIN\
51*593dc095SDavid du Colombier     (alp)->diff.y = (endp).y - (startp).y;\
52*593dc095SDavid du Colombier     (alp)->diff.x = (endp).x - (startp).x;\
53*593dc095SDavid du Colombier     SET_NUM_ADJUST(alp);\
54*593dc095SDavid du Colombier     (alp)->y_fast_max = MAX_MINUS_NUM_ADJUST(alp) /\
55*593dc095SDavid du Colombier       (((alp)->diff.x >= 0 ? (alp)->diff.x : -(alp)->diff.x) | 1) +\
56*593dc095SDavid du Colombier       (startp).y;\
57*593dc095SDavid du Colombier     (alp)->start = startp, (alp)->end = endp;\
58*593dc095SDavid du Colombier   END
59*593dc095SDavid du Colombier     /*
60*593dc095SDavid du Colombier      * We know that alp->start.y <= yv <= alp->end.y, because the fill loop
61*593dc095SDavid du Colombier      * guarantees that the only lines being considered are those with this
62*593dc095SDavid du Colombier      * property.
63*593dc095SDavid du Colombier      */
64*593dc095SDavid du Colombier #define AL_X_AT_Y(alp, yv)\
65*593dc095SDavid du Colombier   ((yv) == (alp)->end.y ? (alp)->end.x :\
66*593dc095SDavid du Colombier    ((yv) <= (alp)->y_fast_max ?\
67*593dc095SDavid du Colombier     ADD_NUM_ADJUST(((yv) - (alp)->start.y) * (alp)->diff.x, alp) / (alp)->diff.y :\
68*593dc095SDavid du Colombier     (INCR_EXPR(slow_x),\
69*593dc095SDavid du Colombier      fixed_mult_quo((alp)->diff.x, (yv) - (alp)->start.y, (alp)->diff.y))) +\
70*593dc095SDavid du Colombier    (alp)->start.x)
71*593dc095SDavid du Colombier     fixed x_current;		/* current x position */
72*593dc095SDavid du Colombier     fixed x_next;		/* x position at end of band */
73*593dc095SDavid du Colombier     const segment *pseg;	/* endpoint of this line */
74*593dc095SDavid du Colombier     int direction;		/* direction of line segment */
75*593dc095SDavid du Colombier #define DIR_UP 1
76*593dc095SDavid du Colombier #define DIR_HORIZONTAL 0	/* (these are handled specially) */
77*593dc095SDavid du Colombier #define DIR_DOWN (-1)
78*593dc095SDavid du Colombier     bool monotonic_x;		/* "false" means "don't know"; only for scanline. */
79*593dc095SDavid du Colombier     bool monotonic_y;		/* "false" means "don't know"; only for scanline. */
80*593dc095SDavid du Colombier     gx_flattened_iterator fi;
81*593dc095SDavid du Colombier     bool more_flattened;
82*593dc095SDavid du Colombier /*
83*593dc095SDavid du Colombier  * "Pending" lines (not reached in the Y ordering yet) use next and prev
84*593dc095SDavid du Colombier  * to order lines by increasing starting Y.  "Active" lines (being scanned)
85*593dc095SDavid du Colombier  * use next and prev to order lines by increasing current X, or if the
86*593dc095SDavid du Colombier  * current Xs are equal, by increasing final X.
87*593dc095SDavid du Colombier  */
88*593dc095SDavid du Colombier     active_line *prev, *next;
89*593dc095SDavid du Colombier /* Link together active_lines allocated individually */
90*593dc095SDavid du Colombier     active_line *alloc_next;
91*593dc095SDavid du Colombier };
92*593dc095SDavid du Colombier 
93*593dc095SDavid du Colombier typedef struct fill_options_s {
94*593dc095SDavid du Colombier     bool pseudo_rasterization;  /* See comment about "pseudo-rasterization". */
95*593dc095SDavid du Colombier     fixed ymin, ymax;
96*593dc095SDavid du Colombier     const gx_device_color * pdevc;
97*593dc095SDavid du Colombier     gs_logical_operation_t lop;
98*593dc095SDavid du Colombier     bool fill_direct;
99*593dc095SDavid du Colombier     fixed fixed_flat;
100*593dc095SDavid du Colombier     bool fill_by_trapezoids;
101*593dc095SDavid du Colombier     fixed adjust_left, adjust_right;
102*593dc095SDavid du Colombier     fixed adjust_below, adjust_above;
103*593dc095SDavid du Colombier     gx_device *dev;
104*593dc095SDavid du Colombier     const gs_fixed_rect * pbox;
105*593dc095SDavid du Colombier     bool is_spotan;
106*593dc095SDavid du Colombier     int rule;
107*593dc095SDavid du Colombier     dev_proc_fill_rectangle((*fill_rect));
108*593dc095SDavid du Colombier     dev_proc_fill_trapezoid((*fill_trap));
109*593dc095SDavid du Colombier } fill_options;
110*593dc095SDavid du Colombier 
111*593dc095SDavid du Colombier /* Line list structure */
112*593dc095SDavid du Colombier #ifndef line_list_DEFINED
113*593dc095SDavid du Colombier #  define line_list_DEFINED
114*593dc095SDavid du Colombier typedef struct line_list_s line_list;
115*593dc095SDavid du Colombier #endif
116*593dc095SDavid du Colombier struct line_list_s {
117*593dc095SDavid du Colombier     gs_memory_t *memory;
118*593dc095SDavid du Colombier     active_line *active_area;	/* allocated active_line list */
119*593dc095SDavid du Colombier     active_line *next_active;	/* next allocation slot */
120*593dc095SDavid du Colombier     active_line *limit; 	/* limit of local allocation */
121*593dc095SDavid du Colombier     int close_count;		/* # of added closing lines */
122*593dc095SDavid du Colombier     active_line *y_list;	/* Y-sorted list of pending lines */
123*593dc095SDavid du Colombier     active_line *y_line;	/* most recently inserted line */
124*593dc095SDavid du Colombier     active_line x_head; 	/* X-sorted list of active lines */
125*593dc095SDavid du Colombier #define x_list x_head.next
126*593dc095SDavid du Colombier     active_line *h_list0, *h_list1; /* lists of horizontal lines for y, y1 */
127*593dc095SDavid du Colombier     margin_set margin_set0, margin_set1;
128*593dc095SDavid du Colombier     margin *free_margin_list;
129*593dc095SDavid du Colombier     int local_margin_alloc_count;
130*593dc095SDavid du Colombier     int bbox_left, bbox_width;
131*593dc095SDavid du Colombier     int main_dir;
132*593dc095SDavid du Colombier     fixed y_break;
133*593dc095SDavid du Colombier     const fill_options * const fo;
134*593dc095SDavid du Colombier     /* Put the arrays last so the scalars will have */
135*593dc095SDavid du Colombier     /* small displacements. */
136*593dc095SDavid du Colombier     /* Allocate a few active_lines locally */
137*593dc095SDavid du Colombier     /* to avoid round trips through the allocator. */
138*593dc095SDavid du Colombier #if arch_small_memory
139*593dc095SDavid du Colombier #  define MAX_LOCAL_ACTIVE 6	/* don't overburden the stack */
140*593dc095SDavid du Colombier #  define MAX_LOCAL_SECTION 50
141*593dc095SDavid du Colombier #else
142*593dc095SDavid du Colombier #  define MAX_LOCAL_ACTIVE 20
143*593dc095SDavid du Colombier #  define MAX_LOCAL_SECTION 100
144*593dc095SDavid du Colombier #endif
145*593dc095SDavid du Colombier     active_line local_active[MAX_LOCAL_ACTIVE];
146*593dc095SDavid du Colombier     margin local_margins[MAX_LOCAL_ACTIVE];
147*593dc095SDavid du Colombier     section local_section0[MAX_LOCAL_SECTION];
148*593dc095SDavid du Colombier     section local_section1[MAX_LOCAL_SECTION];
149*593dc095SDavid du Colombier };
150*593dc095SDavid du Colombier 
151*593dc095SDavid du Colombier #define LOOP_FILL_RECTANGLE_DIRECT(fo, x, y, w, h)\
152*593dc095SDavid du Colombier   (/*fo->fill_direct*/FILL_DIRECT ?\
153*593dc095SDavid du Colombier    (fo)->fill_rect((fo)->dev, x, y, w, h, (fo)->pdevc->colors.pure) :\
154*593dc095SDavid du Colombier    gx_fill_rectangle_device_rop(x, y, w, h, (fo)->pdevc, (fo)->dev, (fo)->lop))
155*593dc095SDavid du Colombier 
156*593dc095SDavid du Colombier /* ---------------- Statistics ---------------- */
157*593dc095SDavid du Colombier 
158*593dc095SDavid du Colombier #ifdef DEBUG
159*593dc095SDavid du Colombier struct stats_fill_s {
160*593dc095SDavid du Colombier     long
161*593dc095SDavid du Colombier 	fill, fill_alloc, y_up, y_down, horiz, x_step, slow_x, iter, find_y,
162*593dc095SDavid du Colombier 	band, band_step, band_fill, afill, slant, slant_shallow, sfill,
163*593dc095SDavid du Colombier 	mq_cross, cross_slow, cross_low, order, slow_order;
164*593dc095SDavid du Colombier };
165*593dc095SDavid du Colombier typedef struct stats_fill_s stats_fill_t;
166*593dc095SDavid du Colombier extern stats_fill_t stats_fill;
167*593dc095SDavid du Colombier 
168*593dc095SDavid du Colombier #  define INCR(x) (++(stats_fill.x))
169*593dc095SDavid du Colombier #  define INCR_EXPR(x) INCR(x)
170*593dc095SDavid du Colombier #  define INCR_BY(x,n) (stats_fill.x += (n))
171*593dc095SDavid du Colombier #else
172*593dc095SDavid du Colombier #  define INCR(x) DO_NOTHING
173*593dc095SDavid du Colombier #  define INCR_EXPR(x) discard(0)
174*593dc095SDavid du Colombier #  define INCR_BY(x,n) DO_NOTHING
175*593dc095SDavid du Colombier #endif
176*593dc095SDavid du Colombier 
177*593dc095SDavid du Colombier #endif /* gxfill_INCLUDED */
178*593dc095SDavid du Colombier 
179*593dc095SDavid du Colombier 
180