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