1 /* Copyright (C) 1989, 2000 Aladdin Enterprises. All rights reserved. 2 3 This file is part of AFPL Ghostscript. 4 5 AFPL Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author or 6 distributor accepts any responsibility for the consequences of using it, or 7 for whether it serves any particular purpose or works at all, unless he or 8 she says so in writing. Refer to the Aladdin Free Public License (the 9 "License") for full details. 10 11 Every copy of AFPL Ghostscript must include a copy of the License, normally 12 in a plain ASCII text file named PUBLIC. The License grants you the right 13 to copy, modify and redistribute AFPL Ghostscript, but only under certain 14 conditions described in the License. Among other things, the License 15 requires that the copyright notice and this notice be preserved on all 16 copies. 17 */ 18 19 /*$Id: gxfill.c,v 1.8 2001/05/10 18:35:14 igorm Exp $ */ 20 /* Lower-level path filling procedures */ 21 #include "gx.h" 22 #include "gserrors.h" 23 #include "gsstruct.h" 24 #include "gxfixed.h" 25 #include "gxdevice.h" 26 #include "gzpath.h" 27 #include "gzcpath.h" 28 #include "gxdcolor.h" 29 #include "gxhttile.h" 30 #include "gxistate.h" 31 #include "gxpaint.h" /* for prototypes */ 32 #include "gsptype2.h" 33 34 /* 35 * Define which fill algorithm(s) to use. At least one of the following 36 * two #defines must be included (not commented out). 37 */ 38 #define FILL_SCAN_LINES 39 #define FILL_TRAPEZOIDS 40 /* 41 * Define whether to sample curves when using the scan line algorithm 42 * rather than flattening them. This produces more accurate output, at 43 * some cost in time. 44 */ 45 #define FILL_CURVES 46 47 /* ---------------- Statistics ---------------- */ 48 49 #ifdef DEBUG 50 struct stats_fill_s { 51 long 52 fill, fill_alloc, y_up, y_down, horiz, x_step, slow_x, iter, find_y, 53 band, band_step, band_fill, afill, slant, slant_shallow, sfill, 54 mq_cross, cross_slow, cross_low, order, slow_order; 55 } stats_fill; 56 57 # define INCR(x) (++(stats_fill.x)) 58 # define INCR_EXPR(x) INCR(x) 59 # define INCR_BY(x,n) (stats_fill.x += (n)) 60 #else 61 # define INCR(x) DO_NOTHING 62 # define INCR_EXPR(x) discard(0) 63 # define INCR_BY(x,n) DO_NOTHING 64 #endif 65 66 /* ---------------- Active line management ---------------- */ 67 68 /* Define the structure for keeping track of active lines. */ 69 typedef struct active_line_s active_line; 70 struct active_line_s { 71 gs_fixed_point start; /* x,y where line starts */ 72 gs_fixed_point end; /* x,y where line ends */ 73 gs_fixed_point diff; /* end - start */ 74 #define AL_DX(alp) ((alp)->diff.x) 75 #define AL_DY(alp) ((alp)->diff.y) 76 fixed y_fast_max; /* can do x_at_y in fixed point */ 77 /* if y <= y_fast_max */ 78 fixed num_adjust; /* 0 if diff.x >= 0, -diff.y + epsilon if */ 79 /* diff.x < 0 and division truncates */ 80 #if ARCH_DIV_NEG_POS_TRUNCATES 81 /* neg/pos truncates, we must bias the numberator. */ 82 # define SET_NUM_ADJUST(alp) \ 83 (alp)->num_adjust =\ 84 ((alp)->diff.x >= 0 ? 0 : -(alp)->diff.y + fixed_epsilon) 85 # define ADD_NUM_ADJUST(num, alp) ((num) + (alp)->num_adjust) 86 # define MAX_MINUS_NUM_ADJUST(alp) ADD_NUM_ADJUST(max_fixed, alp) 87 #else 88 /* neg/pos takes the floor, no special action is needed. */ 89 # define SET_NUM_ADJUST(alp) DO_NOTHING 90 # define ADD_NUM_ADJUST(num, alp) (num) 91 # define MAX_MINUS_NUM_ADJUST(alp) max_fixed 92 #endif 93 #define SET_AL_POINTS(alp, startp, endp)\ 94 BEGIN\ 95 (alp)->diff.y = (endp).y - (startp).y;\ 96 (alp)->diff.x = (endp).x - (startp).x;\ 97 SET_NUM_ADJUST(alp);\ 98 (alp)->y_fast_max = MAX_MINUS_NUM_ADJUST(alp) /\ 99 (((alp)->diff.x >= 0 ? (alp)->diff.x : -(alp)->diff.x) | 1) +\ 100 (startp).y;\ 101 (alp)->start = startp, (alp)->end = endp;\ 102 END 103 /* 104 * We know that alp->start.y <= yv <= alp->end.y, because the fill loop 105 * guarantees that the only lines being considered are those with this 106 * property. 107 */ 108 #define AL_X_AT_Y(alp, yv)\ 109 ((yv) == (alp)->end.y ? (alp)->end.x :\ 110 ((yv) <= (alp)->y_fast_max ?\ 111 ADD_NUM_ADJUST(((yv) - (alp)->start.y) * AL_DX(alp), alp) / AL_DY(alp) :\ 112 (INCR_EXPR(slow_x),\ 113 fixed_mult_quo(AL_DX(alp), (yv) - (alp)->start.y, AL_DY(alp)))) +\ 114 (alp)->start.x) 115 fixed x_current; /* current x position */ 116 fixed x_next; /* x position at end of band */ 117 const segment *pseg; /* endpoint of this line */ 118 int direction; /* direction of line segment */ 119 #define DIR_UP 1 120 #define DIR_HORIZONTAL 0 /* (these are handled specially) */ 121 #define DIR_DOWN (-1) 122 int curve_k; /* # of subdivisions for curves,-1 for lines */ 123 curve_cursor cursor; /* cursor for curves, unused for lines */ 124 /* 125 * "Pending" lines (not reached in the Y ordering yet) use next and prev 126 * to order lines by increasing starting Y. "Active" lines (being scanned) 127 * use next and prev to order lines by increasing current X, or if the 128 * current Xs are equal, by increasing final X. 129 */ 130 active_line *prev, *next; 131 /* Link together active_lines allocated individually */ 132 active_line *alloc_next; 133 }; 134 135 /* 136 * Define the ordering criterion for active lines that overlap in Y. 137 * Return -1, 0, or 1 if lp1 precedes, coincides with, or follows lp2. 138 * 139 * The lines' x_current values are correct for some Y value that crosses 140 * both of them and that is not both the start of one and the end of the 141 * other. (Neither line is horizontal.) We want the ordering at this 142 * Y value, or, of the x_current values are equal, greater Y values 143 * (if any: this Y value might be the end of both lines). 144 */ 145 private int 146 x_order(const active_line *lp1, const active_line *lp2) 147 { 148 bool s1; 149 150 INCR(order); 151 if (lp1->x_current < lp2->x_current) 152 return -1; 153 else if (lp1->x_current > lp2->x_current) 154 return 1; 155 /* 156 * We need to compare the slopes of the lines. Start by 157 * checking one fast case, where the slopes have opposite signs. 158 */ 159 if ((s1 = lp1->start.x < lp1->end.x) != (lp2->start.x < lp2->end.x)) 160 return (s1 ? 1 : -1); 161 /* 162 * We really do have to compare the slopes. Fortunately, this isn't 163 * needed very often. We want the sign of the comparison 164 * dx1/dy1 - dx2/dy2, or (since we know dy1 and dy2 are positive) 165 * dx1 * dy2 - dx2 * dy1. In principle, we can't simply do this using 166 * doubles, since we need complete accuracy and doubles don't have 167 * enough fraction bits. However, with the usual 20+12-bit fixeds and 168 * 64-bit doubles, both of the factors would have to exceed 2^15 169 * device space pixels for the result to be inaccurate, so we 170 * simply disregard this possibility. ****** FIX SOMEDAY ****** 171 */ 172 INCR(slow_order); 173 { 174 fixed dx1 = lp1->end.x - lp1->start.x, 175 dy1 = lp1->end.y - lp1->start.y; 176 fixed dx2 = lp2->end.x - lp2->start.x, 177 dy2 = lp2->end.y - lp2->start.y; 178 double diff = (double)dx1 * dy2 - (double)dx2 * dy1; 179 180 return (diff < 0 ? -1 : diff > 0 ? 1 : 0); 181 } 182 } 183 184 /* 185 * The active_line structure isn't really simple, but since its instances 186 * only exist temporarily during a fill operation, we don't have to 187 * worry about a garbage collection occurring. 188 */ 189 gs_private_st_simple(st_active_line, active_line, "active_line"); 190 191 #ifdef DEBUG 192 /* Internal procedures for printing and checking active lines. */ 193 private void 194 print_active_line(const char *label, const active_line * alp) 195 { 196 dlprintf5("[f]%s 0x%lx(%d): x_current=%f x_next=%f\n", 197 label, (ulong) alp, alp->direction, 198 fixed2float(alp->x_current), fixed2float(alp->x_next)); 199 dlprintf5(" start=(%f,%f) pt_end=0x%lx(%f,%f)\n", 200 fixed2float(alp->start.x), fixed2float(alp->start.y), 201 (ulong) alp->pseg, 202 fixed2float(alp->end.x), fixed2float(alp->end.y)); 203 dlprintf2(" prev=0x%lx next=0x%lx\n", 204 (ulong) alp->prev, (ulong) alp->next); 205 } 206 private void 207 print_line_list(const active_line * flp) 208 { 209 const active_line *lp; 210 211 for (lp = flp; lp != 0; lp = lp->next) { 212 fixed xc = lp->x_current, xn = lp->x_next; 213 214 dlprintf3("[f]0x%lx(%d): x_current/next=%g", 215 (ulong) lp, lp->direction, 216 fixed2float(xc)); 217 if (xn != xc) 218 dprintf1("/%g", fixed2float(xn)); 219 dputc('\n'); 220 } 221 } 222 inline private void 223 print_al(const char *label, const active_line * alp) 224 { 225 if (gs_debug_c('F')) 226 print_active_line(label, alp); 227 } 228 private int 229 check_line_list(const active_line * flp) 230 { 231 const active_line *alp; 232 233 if (flp != 0) 234 for (alp = flp->prev->next; alp != 0; alp = alp->next) 235 if (alp->next != 0 && alp->next->x_current < alp->x_current) { 236 lprintf("[f]Lines out of order!\n"); 237 print_active_line(" 1:", alp); 238 print_active_line(" 2:", alp->next); 239 return_error(gs_error_Fatal); 240 } 241 return 0; 242 } 243 #else 244 #define print_al(label,alp) DO_NOTHING 245 #endif 246 247 /* Line list structure */ 248 struct line_list_s { 249 gs_memory_t *memory; 250 active_line *active_area; /* allocated active_line list */ 251 active_line *next_active; /* next allocation slot */ 252 active_line *limit; /* limit of local allocation */ 253 int close_count; /* # of added closing lines */ 254 active_line *y_list; /* Y-sorted list of pending lines */ 255 active_line *y_line; /* most recently inserted line */ 256 active_line x_head; /* X-sorted list of active lines */ 257 #define x_list x_head.next 258 /* Put the arrays last so the scalars will have */ 259 /* small displacements. */ 260 /* Allocate a few active_lines locally */ 261 /* to avoid round trips through the allocator. */ 262 #if arch_small_memory 263 # define MAX_LOCAL_ACTIVE 6 /* don't overburden the stack */ 264 #else 265 # define MAX_LOCAL_ACTIVE 20 266 #endif 267 active_line local_active[MAX_LOCAL_ACTIVE]; 268 }; 269 typedef struct line_list_s line_list; 270 typedef line_list *ll_ptr; 271 272 /* Forward declarations */ 273 private void init_line_list(P2(ll_ptr, gs_memory_t *)); 274 private void unclose_path(P2(gx_path *, int)); 275 private void free_line_list(P1(ll_ptr)); 276 private int add_y_list(P5(gx_path *, ll_ptr, fixed, fixed, 277 const gs_fixed_rect *)); 278 private int add_y_line(P4(const segment *, const segment *, int, ll_ptr)); 279 private void insert_x_new(P2(active_line *, ll_ptr)); 280 private bool end_x_line(P2(active_line *, bool)); 281 282 #define FILL_LOOP_PROC(proc)\ 283 int proc(P11(ll_ptr, gx_device *,\ 284 const gx_fill_params *, const gx_device_color *, gs_logical_operation_t,\ 285 const gs_fixed_rect *, fixed, fixed, fixed, fixed, fixed)) 286 private FILL_LOOP_PROC(fill_loop_by_scan_lines); 287 private FILL_LOOP_PROC(fill_loop_by_trapezoids); 288 289 /* 290 * This is the general path filling algorithm. 291 * It uses the center-of-pixel rule for filling. 292 * We can implement Microsoft's upper-left-corner-of-pixel rule 293 * by subtracting (0.5, 0.5) from all the coordinates in the path. 294 * 295 * The adjust parameters are a hack for keeping regions 296 * from coming out too faint: they specify an amount by which to expand 297 * the sides of every filled region. 298 * Setting adjust = fixed_half is supposed to produce the effect of Adobe's 299 * any-part-of-pixel rule, but it doesn't quite, because of the 300 * closed/open interval rule for regions. We detect this as a special case 301 * and do the slightly ugly things necessary to make it work. 302 */ 303 304 /* 305 * Tweak the fill adjustment if necessary so that (nearly) empty 306 * rectangles are guaranteed to produce some output. This is a hack 307 * to work around a bug in the Microsoft Windows PostScript driver, 308 * which draws thin lines by filling zero-width rectangles, and in 309 * some other drivers that try to fill epsilon-width rectangles. 310 */ 311 void 312 gx_adjust_if_empty(const gs_fixed_rect * pbox, gs_fixed_point * adjust) 313 { 314 /* 315 * For extremely large coordinates, the obvious subtractions could 316 * overflow. We can work around this easily by noting that since 317 * we know q.{x,y} >= p.{x,y}, the subtraction overflows iff the 318 * result is negative. 319 */ 320 const fixed 321 dx = pbox->q.x - pbox->p.x, dy = pbox->q.y - pbox->p.y; 322 323 if (dx < fixed_half && dx > 0 && (dy >= int2fixed(2) || dy < 0)) { 324 adjust->x = arith_rshift_1(fixed_1 + fixed_epsilon - dx); 325 if_debug1('f', "[f]thin adjust_x=%g\n", 326 fixed2float(adjust->x)); 327 } else if (dy < fixed_half && dy > 0 && (dx >= int2fixed(2) || dx < 0)) { 328 adjust->y = arith_rshift_1(fixed_1 + fixed_epsilon - dy); 329 if_debug1('f', "[f]thin adjust_y=%g\n", 330 fixed2float(adjust->y)); 331 } 332 } 333 334 /* 335 * The general fill path algorithm. 336 */ 337 private int 338 gx_general_fill_path(gx_device * pdev, const gs_imager_state * pis, 339 gx_path * ppath, const gx_fill_params * params, 340 const gx_device_color * pdevc, const gx_clip_path * pcpath) 341 { 342 gs_fixed_point adjust; 343 gs_logical_operation_t lop = pis->log_op; 344 gs_fixed_rect ibox, bbox; 345 gx_device_clip cdev; 346 gx_device *dev = pdev; 347 gx_device *save_dev = dev; 348 gx_path ffpath; 349 gx_path *pfpath; 350 int code; 351 fixed adjust_left, adjust_right, adjust_below, adjust_above; 352 int max_fill_band = dev->max_fill_band; 353 #define NO_BAND_MASK ((fixed)(-1) << (sizeof(fixed) * 8 - 1)) 354 bool fill_by_trapezoids; 355 line_list lst; 356 357 adjust = params->adjust; 358 /* 359 * Compute the bounding box before we flatten the path. 360 * This can save a lot of time if the path has curves. 361 * If the path is neither fully within nor fully outside 362 * the quick-check boxes, we could recompute the bounding box 363 * and make the checks again after flattening the path, 364 * but right now we don't bother. 365 */ 366 gx_path_bbox(ppath, &ibox); 367 if (params->fill_zero_width) 368 gx_adjust_if_empty(&ibox, &adjust); 369 /* Check the bounding boxes. */ 370 if_debug6('f', "[f]adjust=%g,%g bbox=(%g,%g),(%g,%g)\n", 371 fixed2float(adjust.x), fixed2float(adjust.y), 372 fixed2float(ibox.p.x), fixed2float(ibox.p.y), 373 fixed2float(ibox.q.x), fixed2float(ibox.q.y)); 374 if (pcpath) 375 gx_cpath_inner_box(pcpath, &bbox); 376 else 377 (*dev_proc(dev, get_clipping_box)) (dev, &bbox); 378 if (!rect_within(ibox, bbox)) { 379 /* 380 * Intersect the path box and the clip bounding box. 381 * If the intersection is empty, this fill is a no-op. 382 */ 383 if (pcpath) 384 gx_cpath_outer_box(pcpath, &bbox); 385 if_debug4('f', " outer_box=(%g,%g),(%g,%g)\n", 386 fixed2float(bbox.p.x), fixed2float(bbox.p.y), 387 fixed2float(bbox.q.x), fixed2float(bbox.q.y)); 388 rect_intersect(ibox, bbox); 389 if (ibox.p.x - adjust.x >= ibox.q.x + adjust.x || 390 ibox.p.y - adjust.y >= ibox.q.y + adjust.y 391 ) { /* Intersection of boxes is empty! */ 392 return 0; 393 } 394 /* 395 * The path is neither entirely inside the inner clip box 396 * nor entirely outside the outer clip box. 397 * If we had to flatten the path, this is where we would 398 * recompute its bbox and make the tests again, 399 * but we don't bother right now. 400 * 401 * If there is a clipping path, set up a clipping device. 402 */ 403 if (pcpath) { 404 dev = (gx_device *) & cdev; 405 gx_make_clip_device(&cdev, gx_cpath_list(pcpath)); 406 cdev.target = save_dev; 407 cdev.max_fill_band = save_dev->max_fill_band; 408 (*dev_proc(dev, open_device)) (dev); 409 } 410 } 411 /* 412 * Compute the proper adjustment values. 413 * To get the effect of the any-part-of-pixel rule, 414 * we may have to tweak them slightly. 415 * NOTE: We changed the adjust_right/above value from 0.5+epsilon 416 * to 0.5 in release 5.01; even though this does the right thing 417 * in every case we could imagine, we aren't confident that it's 418 * correct. (The old values were definitely incorrect, since they 419 * caused 1-pixel-wide/high objects to color 2 pixels even if 420 * they fell exactly on pixel boundaries.) 421 */ 422 if (adjust.x == fixed_half) 423 adjust_left = fixed_half - fixed_epsilon, 424 adjust_right = fixed_half /* + fixed_epsilon */ ; /* see above */ 425 else 426 adjust_left = adjust_right = adjust.x; 427 if (adjust.y == fixed_half) 428 adjust_below = fixed_half - fixed_epsilon, 429 adjust_above = fixed_half /* + fixed_epsilon */ ; /* see above */ 430 else 431 adjust_below = adjust_above = adjust.y; 432 /* Initialize the active line list. */ 433 init_line_list(&lst, ppath->memory); 434 /* 435 * We have a choice of two different filling algorithms: 436 * scan-line-based and trapezoid-based. They compare as follows: 437 * 438 * Scan Trap 439 * ---- ---- 440 * skip +draw 0-height horizontal lines 441 * slow +fast rectangles 442 * +fast slow curves 443 * +yes no write pixels at most once when adjust != 0 444 * 445 * Normally we use the scan line algorithm for characters, where curve 446 * speed is important, and for non-idempotent RasterOps, where double 447 * pixel writing must be avoided, and the trapezoid algorithm otherwise. 448 * However, we always use the trapezoid algorithm for rectangles. 449 */ 450 #define DOUBLE_WRITE_OK() lop_is_idempotent(lop) 451 #ifdef FILL_SCAN_LINES 452 # ifdef FILL_TRAPEZOIDS 453 fill_by_trapezoids = 454 (!gx_path_has_curves(ppath) || params->flatness >= 1.0); 455 # else 456 fill_by_trapezoids = false; 457 # endif 458 #else 459 fill_by_trapezoids = true; 460 #endif 461 #ifdef FILL_TRAPEZOIDS 462 if (fill_by_trapezoids && !DOUBLE_WRITE_OK()) { 463 /* Avoid filling rectangles by scan line. */ 464 gs_fixed_rect rbox; 465 466 if (gx_path_is_rectangular(ppath, &rbox)) { 467 int x0 = fixed2int_pixround(rbox.p.x - adjust_left); 468 int y0 = fixed2int_pixround(rbox.p.y - adjust_below); 469 int x1 = fixed2int_pixround(rbox.q.x + adjust_right); 470 int y1 = fixed2int_pixround(rbox.q.y + adjust_above); 471 472 return gx_fill_rectangle_device_rop(x0, y0, x1 - x0, y1 - y0, 473 pdevc, dev, lop); 474 } 475 fill_by_trapezoids = false; /* avoid double write */ 476 } 477 #endif 478 #undef DOUBLE_WRITE_OK 479 /* 480 * Pre-process curves. When filling by trapezoids, we need to 481 * flatten the path completely; when filling by scan lines, we only 482 * need to monotonize it, unless FILL_CURVES is undefined. 483 */ 484 gx_path_init_local(&ffpath, ppath->memory); 485 if (!gx_path_has_curves(ppath)) /* don't need to flatten */ 486 pfpath = ppath; 487 else 488 #if defined(FILL_CURVES) && defined(FILL_SCAN_LINES) 489 /* Filling curves is possible. */ 490 # ifdef FILL_TRAPEZOIDS 491 /* Not filling curves is also possible. */ 492 if (fill_by_trapezoids) 493 # endif 494 #endif 495 #if !defined(FILL_CURVES) || defined(FILL_TRAPEZOIDS) 496 /* Not filling curves is possible. */ 497 { 498 gx_path_init_local(&ffpath, ppath->memory); 499 code = gx_path_add_flattened_accurate(ppath, &ffpath, 500 params->flatness, 501 pis->accurate_curves); 502 if (code < 0) 503 return code; 504 pfpath = &ffpath; 505 } 506 #endif 507 #if defined(FILL_CURVES) && defined(FILL_SCAN_LINES) 508 /* Filling curves is possible. */ 509 # ifdef FILL_TRAPEZOIDS 510 /* Not filling curves is also possible. */ 511 else 512 # endif 513 if (gx_path_is_monotonic(ppath)) 514 pfpath = ppath; 515 else { 516 gx_path_init_local(&ffpath, ppath->memory); 517 code = gx_path_add_monotonized(ppath, &ffpath); 518 if (code < 0) 519 return code; 520 pfpath = &ffpath; 521 } 522 #endif 523 if ((code = add_y_list(pfpath, &lst, adjust_below, adjust_above, &ibox)) < 0) 524 goto nope; 525 { 526 FILL_LOOP_PROC((*fill_loop)); 527 528 /* Some short-sighted compilers won't allow a conditional here.... */ 529 if (fill_by_trapezoids) 530 fill_loop = fill_loop_by_trapezoids; 531 else 532 fill_loop = fill_loop_by_scan_lines; 533 code = (*fill_loop) 534 (&lst, dev, params, pdevc, lop, &ibox, 535 adjust_left, adjust_right, adjust_below, adjust_above, 536 (max_fill_band == 0 ? NO_BAND_MASK : int2fixed(-max_fill_band))); 537 } 538 nope:if (lst.close_count != 0) 539 unclose_path(pfpath, lst.close_count); 540 free_line_list(&lst); 541 if (pfpath != ppath) /* had to flatten */ 542 gx_path_free(pfpath, "gx_default_fill_path(flattened path)"); 543 #ifdef DEBUG 544 if (gs_debug_c('f')) { 545 dlputs("[f] # alloc up down horiz step slowx iter find band bstep bfill\n"); 546 dlprintf5(" %5ld %5ld %5ld %5ld %5ld", 547 stats_fill.fill, stats_fill.fill_alloc, 548 stats_fill.y_up, stats_fill.y_down, 549 stats_fill.horiz); 550 dlprintf4(" %5ld %5ld %5ld %5ld", 551 stats_fill.x_step, stats_fill.slow_x, 552 stats_fill.iter, stats_fill.find_y); 553 dlprintf3(" %5ld %5ld %5ld\n", 554 stats_fill.band, stats_fill.band_step, 555 stats_fill.band_fill); 556 dlputs("[f] afill slant shall sfill mqcrs order slowo\n"); 557 dlprintf7(" %5ld %5ld %5ld %5ld %5ld %5ld %5ld\n", 558 stats_fill.afill, stats_fill.slant, 559 stats_fill.slant_shallow, stats_fill.sfill, 560 stats_fill.mq_cross, stats_fill.order, 561 stats_fill.slow_order); 562 } 563 #endif 564 return code; 565 } 566 567 /* 568 * Fill a path. This is the default implementation of the driver 569 * fill_path procedure. 570 */ 571 int 572 gx_default_fill_path(gx_device * pdev, const gs_imager_state * pis, 573 gx_path * ppath, const gx_fill_params * params, 574 const gx_device_color * pdevc, const gx_clip_path * pcpath) 575 { 576 if (gx_dc_is_pattern2_color(pdevc)) { 577 /* Optimization for shading fill : 578 The general path filling algorithm subdivides fill region with 579 trapezoid or rectangle subregions and then paints each subregion 580 with given color. If the color is shading, each subregion to be 581 subdivided into areas of constant color. But with radial 582 shading each area is a high order polygon, being 583 subdivided into smaller subregions, so as total number of 584 subregions grows huge. Faster processing is done here by changing 585 the order of subdivision cycles : we first subdivide the shading into 586 areas of constant color, then apply the general path filling algorithm 587 (i.e. subdivide each area into trapezoids or rectangles), using the 588 filling path as clip mask. 589 */ 590 591 gx_clip_path cpath_intersection; 592 gx_path path_intersection; 593 int code; 594 595 /* Shading fill algorithm uses "current path" parameter of the general 596 path filling algorithm as boundary of constant color area, 597 so we need to intersect the filling path with the clip path now, 598 reducing the number of pathes passed to it : 599 */ 600 gx_path_init_local(&path_intersection, pdev->memory); 601 gx_cpath_init_local_shared(&cpath_intersection, pcpath, pdev->memory); 602 if ((code = gx_cpath_intersect(&cpath_intersection, ppath, params->rule, (gs_imager_state *)pis)) >= 0) 603 code = gx_cpath_to_path(&cpath_intersection, &path_intersection); 604 605 /* Do fill : */ 606 if (code >= 0) 607 code = gx_dc_pattern2_fill_path_adjusted(pdevc, &path_intersection, NULL, pdev); 608 609 /* Destruct local data and return :*/ 610 gx_path_free(&path_intersection, "shading_fill_path_intersection"); 611 gx_cpath_free(&cpath_intersection, "shading_fill_cpath_intersection"); 612 return code; 613 } 614 return gx_general_fill_path(pdev, pis, ppath, params, pdevc, pcpath); 615 } 616 617 /* Initialize the line list for a path. */ 618 private void 619 init_line_list(ll_ptr ll, gs_memory_t * mem) 620 { 621 ll->memory = mem; 622 ll->active_area = 0; 623 ll->next_active = ll->local_active; 624 ll->limit = ll->next_active + MAX_LOCAL_ACTIVE; 625 ll->close_count = 0; 626 ll->y_list = 0; 627 ll->y_line = 0; 628 INCR(fill); 629 } 630 631 /* Unlink any line_close segments added temporarily. */ 632 private void 633 unclose_path(gx_path * ppath, int count) 634 { 635 subpath *psub; 636 637 for (psub = ppath->first_subpath; count != 0; 638 psub = (subpath *) psub->last->next 639 ) 640 if (psub->last == (segment *) & psub->closer) { 641 segment *prev = psub->closer.prev, *next = psub->closer.next; 642 643 prev->next = next; 644 if (next) 645 next->prev = prev; 646 psub->last = prev; 647 count--; 648 } 649 } 650 651 /* Free the line list. */ 652 private void 653 free_line_list(ll_ptr ll) 654 { 655 /* Free any individually allocated active_lines. */ 656 gs_memory_t *mem = ll->memory; 657 active_line *alp; 658 659 while ((alp = ll->active_area) != 0) { 660 active_line *next = alp->alloc_next; 661 662 gs_free_object(mem, alp, "active line"); 663 ll->active_area = next; 664 } 665 } 666 667 /* 668 * Construct a Y-sorted list of segments for rasterizing a path. We assume 669 * the path is non-empty. Only include non-horizontal lines or (monotonic) 670 * curve segments where one endpoint is locally Y-minimal, and horizontal 671 * lines that might color some additional pixels. 672 */ 673 private int 674 add_y_list(gx_path * ppath, ll_ptr ll, fixed adjust_below, fixed adjust_above, 675 const gs_fixed_rect * pbox) 676 { 677 segment *pseg = (segment *) ppath->first_subpath; 678 int close_count = 0; 679 /* fixed xmin = pbox->p.x; *//* not currently used */ 680 fixed ymin = pbox->p.y; 681 /* fixed xmax = pbox->q.x; *//* not currently used */ 682 fixed ymax = pbox->q.y; 683 int code; 684 685 while (pseg) { 686 /* We know that pseg points to a subpath head (s_start). */ 687 subpath *psub = (subpath *) pseg; 688 segment *plast = psub->last; 689 int dir = 2; /* hack to skip first segment */ 690 int first_dir, prev_dir; 691 segment *prev; 692 693 if (plast->type != s_line_close) { 694 /* Create a fake s_line_close */ 695 line_close_segment *lp = &psub->closer; 696 segment *next = plast->next; 697 698 lp->next = next; 699 lp->prev = plast; 700 plast->next = (segment *) lp; 701 if (next) 702 next->prev = (segment *) lp; 703 lp->type = s_line_close; 704 lp->pt = psub->pt; 705 lp->sub = psub; 706 psub->last = plast = (segment *) lp; 707 ll->close_count++; 708 } 709 while ((prev_dir = dir, prev = pseg, 710 (pseg = pseg->next) != 0 && pseg->type != s_start) 711 ) { 712 /* This element is either a line or a monotonic curve segment. */ 713 fixed iy = pseg->pt.y; 714 fixed py = prev->pt.y; 715 716 /* 717 * Segments falling entirely outside the ibox in Y 718 * are treated as though they were horizontal, * 719 * i.e., they are never put on the list. 720 */ 721 #define COMPUTE_DIR(xo, xe, yo, ye)\ 722 (ye > yo ? (ye <= ymin || yo >= ymax ? 0 : DIR_UP) :\ 723 ye < yo ? (yo <= ymin || ye >= ymax ? 0 : DIR_DOWN) :\ 724 2) 725 #define ADD_DIR_LINES(prev2, prev, this, pdir, dir)\ 726 BEGIN\ 727 if (pdir)\ 728 { if ((code = add_y_line(prev2, prev, pdir, ll)) < 0) return code; }\ 729 if (dir)\ 730 { if ((code = add_y_line(prev, this, dir, ll)) < 0) return code; }\ 731 END 732 dir = COMPUTE_DIR(prev->pt.x, pseg->pt.x, py, iy); 733 if (dir == 2) { /* Put horizontal lines on the list */ 734 /* if they would color any pixels. */ 735 if (fixed2int_pixround(iy - adjust_below) < 736 fixed2int_pixround(iy + adjust_above) 737 ) { 738 INCR(horiz); 739 if ((code = add_y_line(prev, pseg, 740 DIR_HORIZONTAL, ll)) < 0 741 ) 742 return code; 743 } 744 dir = 0; 745 } 746 if (dir > prev_dir) { 747 ADD_DIR_LINES(prev->prev, prev, pseg, prev_dir, dir); 748 } else if (prev_dir == 2) /* first segment */ 749 first_dir = dir; 750 if (pseg == plast) { 751 /* 752 * We skipped the first segment of the subpath, so the last 753 * segment must receive special consideration. Note that we 754 * have `closed' all subpaths. 755 */ 756 if (first_dir > dir) { 757 ADD_DIR_LINES(prev, pseg, psub->next, dir, first_dir); 758 } 759 } 760 } 761 #undef COMPUTE_DIR 762 #undef ADD_DIR_LINES 763 } 764 return close_count; 765 } 766 /* 767 * Internal routine to test a segment and add it to the pending list if 768 * appropriate. 769 */ 770 private int 771 add_y_line(const segment * prev_lp, const segment * lp, int dir, ll_ptr ll) 772 { 773 gs_fixed_point this, prev; 774 active_line *alp = ll->next_active; 775 fixed y_start; 776 777 if (alp == ll->limit) { /* Allocate separately */ 778 alp = gs_alloc_struct(ll->memory, active_line, 779 &st_active_line, "active line"); 780 if (alp == 0) 781 return_error(gs_error_VMerror); 782 alp->alloc_next = ll->active_area; 783 ll->active_area = alp; 784 INCR(fill_alloc); 785 } else 786 ll->next_active++; 787 this.x = lp->pt.x; 788 this.y = lp->pt.y; 789 prev.x = prev_lp->pt.x; 790 prev.y = prev_lp->pt.y; 791 switch ((alp->direction = dir)) { 792 case DIR_UP: 793 y_start = prev.y; 794 SET_AL_POINTS(alp, prev, this); 795 alp->pseg = lp; 796 break; 797 case DIR_DOWN: 798 y_start = this.y; 799 SET_AL_POINTS(alp, this, prev); 800 alp->pseg = prev_lp; 801 break; 802 case DIR_HORIZONTAL: 803 y_start = this.y; /* = prev.y */ 804 alp->start = prev; 805 alp->end = this; 806 /* Don't need to set dx or y_fast_max */ 807 alp->pseg = prev_lp; /* may not need this either */ 808 break; 809 default: /* can't happen */ 810 return_error(gs_error_unregistered); 811 } 812 /* Insert the new line in the Y ordering */ 813 { 814 active_line *yp = ll->y_line; 815 active_line *nyp; 816 817 if (yp == 0) { 818 alp->next = alp->prev = 0; 819 ll->y_list = alp; 820 } else if (y_start >= yp->start.y) { /* Insert the new line after y_line */ 821 while (INCR_EXPR(y_up), 822 ((nyp = yp->next) != NULL && 823 y_start > nyp->start.y) 824 ) 825 yp = nyp; 826 alp->next = nyp; 827 alp->prev = yp; 828 yp->next = alp; 829 if (nyp) 830 nyp->prev = alp; 831 } else { /* Insert the new line before y_line */ 832 while (INCR_EXPR(y_down), 833 ((nyp = yp->prev) != NULL && 834 y_start < nyp->start.y) 835 ) 836 yp = nyp; 837 alp->prev = nyp; 838 alp->next = yp; 839 yp->prev = alp; 840 if (nyp) 841 nyp->next = alp; 842 else 843 ll->y_list = alp; 844 } 845 } 846 ll->y_line = alp; 847 print_al("add ", alp); 848 return 0; 849 } 850 851 /* ---------------- Filling loop utilities ---------------- */ 852 853 /* Insert a newly active line in the X ordering. */ 854 private void 855 insert_x_new(active_line * alp, ll_ptr ll) 856 { 857 active_line *next; 858 active_line *prev = &ll->x_head; 859 860 alp->x_current = alp->start.x; 861 while (INCR_EXPR(x_step), 862 (next = prev->next) != 0 && x_order(next, alp) < 0 863 ) 864 prev = next; 865 alp->next = next; 866 alp->prev = prev; 867 if (next != 0) 868 next->prev = alp; 869 prev->next = alp; 870 } 871 872 /* 873 * Handle a line segment that just ended. Return true iff this was 874 * the end of a line sequence. 875 */ 876 private bool 877 end_x_line(active_line *alp, bool update) 878 { 879 const segment *pseg = alp->pseg; 880 /* 881 * The computation of next relies on the fact that 882 * all subpaths have been closed. When we cycle 883 * around to the other end of a subpath, we must be 884 * sure not to process the start/end point twice. 885 */ 886 const segment *next = 887 (alp->direction == DIR_UP ? 888 ( /* Upward line, go forward along path. */ 889 pseg->type == s_line_close ? /* end of subpath */ 890 ((const line_close_segment *)pseg)->sub->next : 891 pseg->next) : 892 ( /* Downward line, go backward along path. */ 893 pseg->type == s_start ? /* start of subpath */ 894 ((const subpath *)pseg)->last->prev : 895 pseg->prev) 896 ); 897 gs_fixed_point npt; 898 899 npt.y = next->pt.y; 900 if (!update) 901 return npt.y <= pseg->pt.y; 902 if_debug5('F', "[F]ended 0x%lx: pseg=0x%lx y=%f next=0x%lx npt.y=%f\n", 903 (ulong) alp, (ulong) pseg, fixed2float(pseg->pt.y), 904 (ulong) next, fixed2float(npt.y)); 905 if (npt.y <= pseg->pt.y) { /* End of a line sequence */ 906 active_line *nlp = alp->next; 907 908 alp->prev->next = nlp; 909 if (nlp) 910 nlp->prev = alp->prev; 911 if_debug1('F', "[F]drop 0x%lx\n", (ulong) alp); 912 return true; 913 } 914 alp->pseg = next; 915 npt.x = next->pt.x; 916 SET_AL_POINTS(alp, alp->end, npt); 917 print_al("repl", alp); 918 return false; 919 } 920 921 #define LOOP_FILL_RECTANGLE(x, y, w, h)\ 922 gx_fill_rectangle_device_rop(x, y, w, h, pdevc, dev, lop) 923 #define LOOP_FILL_RECTANGLE_DIRECT(x, y, w, h)\ 924 (fill_direct ?\ 925 (*fill_rect)(dev, x, y, w, h, cindex) :\ 926 gx_fill_rectangle_device_rop(x, y, w, h, pdevc, dev, lop)) 927 928 /* ---------------- Trapezoid filling loop ---------------- */ 929 930 /* Forward references */ 931 private int fill_slant_adjust(P12(fixed, fixed, fixed, fixed, fixed, 932 fixed, fixed, fixed, const gs_fixed_rect *, 933 const gx_device_color *, gx_device *, gs_logical_operation_t)); 934 private void resort_x_line(P1(active_line *)); 935 936 /****** PATCH ******/ 937 #define LOOP_FILL_TRAPEZOID_FIXED(fx0, fw0, fy0, fx1, fw1, fh)\ 938 loop_fill_trap(dev, fx0, fw0, fy0, fx1, fw1, fh, pbox, pdevc, lop) 939 private int 940 loop_fill_trap(gx_device * dev, fixed fx0, fixed fw0, fixed fy0, 941 fixed fx1, fixed fw1, fixed fh, const gs_fixed_rect * pbox, 942 const gx_device_color * pdevc, gs_logical_operation_t lop) 943 { 944 fixed fy1 = fy0 + fh; 945 fixed ybot = max(fy0, pbox->p.y); 946 fixed ytop = min(fy1, pbox->q.y); 947 gs_fixed_edge left, right; 948 949 if (ybot >= ytop) 950 return 0; 951 left.start.y = right.start.y = fy0; 952 left.end.y = right.end.y = fy1; 953 right.start.x = (left.start.x = fx0) + fw0; 954 right.end.x = (left.end.x = fx1) + fw1; 955 return (*dev_proc(dev, fill_trapezoid)) 956 (dev, &left, &right, ybot, ytop, false, pdevc, lop); 957 } 958 /****** END PATCH ******/ 959 960 /* Main filling loop. Takes lines off of y_list and adds them to */ 961 /* x_list as needed. band_mask limits the size of each band, */ 962 /* by requiring that ((y1 - 1) & band_mask) == (y0 & band_mask). */ 963 private int 964 fill_loop_by_trapezoids(ll_ptr ll, gx_device * dev, 965 const gx_fill_params * params, const gx_device_color * pdevc, 966 gs_logical_operation_t lop, const gs_fixed_rect * pbox, 967 fixed adjust_left, fixed adjust_right, 968 fixed adjust_below, fixed adjust_above, fixed band_mask) 969 { 970 int rule = params->rule; 971 const fixed y_limit = pbox->q.y; 972 active_line *yll = ll->y_list; 973 fixed y; 974 int code; 975 bool fill_direct = color_writes_pure(pdevc, lop); 976 gx_color_index cindex; 977 978 dev_proc_fill_rectangle((*fill_rect)); 979 /* 980 * Define a faster test for 981 * fixed2int_pixround(y - below) != fixed2int_pixround(y + above) 982 * where we know 983 * 0 <= below <= _fixed_pixround_v, 984 * 0 <= above <= min(fixed_half, fixed_1 - below). 985 * Subtracting out the integer parts, this is equivalent to 986 * fixed2int_pixround(fixed_fraction(y) - below) != 987 * fixed2int_pixround(fixed_fraction(y) + above) 988 * or to 989 * fixed2int(fixed_fraction(y) + _fixed_pixround_v - below) != 990 * fixed2int(fixed_fraction(y) + _fixed_pixround_v + above) 991 * Letting A = _fixed_pixround_v - below and B = _fixed_pixround_v + above, 992 * we can rewrite this as 993 * fixed2int(fixed_fraction(y) + A) != fixed2int(fixed_fraction(y) + B) 994 * Because of the range constraints given above, this is true precisely when 995 * fixed_fraction(y) + A < fixed_1 && fixed_fraction(y) + B >= fixed_1 996 * or equivalently 997 * fixed_fraction(y + B) < B - A. 998 * i.e. 999 * fixed_fraction(y + _fixed_pixround_v + above) < below + above 1000 */ 1001 fixed y_span_delta = _fixed_pixround_v + adjust_above; 1002 fixed y_span_limit = adjust_below + adjust_above; 1003 1004 #define ADJUSTED_Y_SPANS_PIXEL(y)\ 1005 (fixed_fraction((y) + y_span_delta) < y_span_limit) 1006 1007 if (yll == 0) 1008 return 0; /* empty list */ 1009 if (fill_direct) 1010 cindex = pdevc->colors.pure, 1011 fill_rect = dev_proc(dev, fill_rectangle); 1012 y = yll->start.y; /* first Y value */ 1013 ll->x_list = 0; 1014 ll->x_head.x_current = min_fixed; /* stop backward scan */ 1015 while (1) { 1016 fixed y1; 1017 active_line *endp, *alp, *stopx; 1018 fixed x; 1019 int draw; 1020 1021 INCR(iter); 1022 /* Move newly active lines from y to x list. */ 1023 while (yll != 0 && yll->start.y == y) { 1024 active_line *ynext = yll->next; /* insert smashes next/prev links */ 1025 1026 if (yll->direction == DIR_HORIZONTAL) { 1027 /* 1028 * This is a hack to make sure that isolated horizontal 1029 * lines get stroked. 1030 */ 1031 int yi = fixed2int_pixround(y - adjust_below); 1032 int xi, wi; 1033 1034 if (yll->start.x <= yll->end.x) 1035 xi = fixed2int_pixround(yll->start.x - 1036 adjust_left), 1037 wi = fixed2int_pixround(yll->end.x + 1038 adjust_right) - xi; 1039 else 1040 xi = fixed2int_pixround(yll->end.x - 1041 adjust_left), 1042 wi = fixed2int_pixround(yll->start.x + 1043 adjust_right) - xi; 1044 code = LOOP_FILL_RECTANGLE_DIRECT(xi, yi, wi, 1); 1045 if (code < 0) 1046 return code; 1047 } else 1048 insert_x_new(yll, ll); 1049 yll = ynext; 1050 } 1051 /* Check whether we've reached the maximum y. */ 1052 if (y >= y_limit) 1053 break; 1054 if (ll->x_list == 0) { /* No active lines, skip to next start */ 1055 if (yll == 0) 1056 break; /* no lines left */ 1057 y = yll->start.y; 1058 continue; 1059 } 1060 /* Find the next evaluation point. */ 1061 /* Start by finding the smallest y value */ 1062 /* at which any currently active line ends */ 1063 /* (or the next to-be-active line begins). */ 1064 y1 = (yll != 0 ? yll->start.y : y_limit); 1065 /* Make sure we don't exceed the maximum band height. */ 1066 { 1067 fixed y_band = y | ~band_mask; 1068 1069 if (y1 > y_band) 1070 y1 = y_band + 1; 1071 } 1072 for (alp = ll->x_list; alp != 0; alp = alp->next) 1073 if (alp->end.y < y1) 1074 y1 = alp->end.y; 1075 #ifdef DEBUG 1076 if (gs_debug_c('F')) { 1077 dlprintf2("[F]before loop: y=%f y1=%f:\n", 1078 fixed2float(y), fixed2float(y1)); 1079 print_line_list(ll->x_list); 1080 } 1081 #endif 1082 /* Now look for line intersections before y1. */ 1083 x = min_fixed; 1084 #define HAVE_PIXELS()\ 1085 (fixed_pixround(y - adjust_below) < fixed_pixround(y1 + adjust_above)) 1086 draw = (HAVE_PIXELS()? 1 : -1); 1087 /* 1088 * Loop invariants: 1089 * alp = endp->next; 1090 * for all lines lp from stopx up to alp, 1091 * lp->x_next = AL_X_AT_Y(lp, y1). 1092 */ 1093 for (alp = stopx = ll->x_list; 1094 INCR_EXPR(find_y), alp != 0; 1095 endp = alp, alp = alp->next 1096 ) { 1097 fixed nx = AL_X_AT_Y(alp, y1); 1098 fixed dx_old, dx_den; 1099 1100 /* Check for intersecting lines. */ 1101 if (nx >= x) 1102 x = nx; 1103 else if 1104 (draw >= 0 && /* don't bother if no pixels */ 1105 (dx_old = alp->x_current - endp->x_current) >= 0 && 1106 (dx_den = dx_old + endp->x_next - nx) > dx_old 1107 ) { /* Make a good guess at the intersection */ 1108 /* Y value using only local information. */ 1109 fixed dy = y1 - y, y_new; 1110 1111 if_debug3('F', "[F]cross: dy=%g, dx_old=%g, dx_new=%g\n", 1112 fixed2float(dy), fixed2float(dx_old), 1113 fixed2float(dx_den - dx_old)); 1114 /* Do the computation in single precision */ 1115 /* if the values are small enough. */ 1116 y_new = 1117 ((dy | dx_old) < 1L << (size_of(fixed) * 4 - 1) ? 1118 dy * dx_old / dx_den : 1119 (INCR_EXPR(mq_cross), fixed_mult_quo(dy, dx_old, dx_den))) 1120 + y; 1121 /* The crossing value doesn't have to be */ 1122 /* very accurate, but it does have to be */ 1123 /* greater than y and less than y1. */ 1124 if_debug3('F', "[F]cross y=%g, y_new=%g, y1=%g\n", 1125 fixed2float(y), fixed2float(y_new), 1126 fixed2float(y1)); 1127 stopx = alp; 1128 if (y_new <= y) { 1129 /* 1130 * This isn't possible. Recompute the intersection 1131 * accurately. 1132 */ 1133 fixed ys, xs0, xs1, ye, xe0, xe1, dy, dx0, dx1; 1134 1135 INCR(cross_slow); 1136 if (endp->start.y < alp->start.y) 1137 ys = alp->start.y, 1138 xs0 = AL_X_AT_Y(endp, ys), xs1 = alp->start.x; 1139 else 1140 ys = endp->start.y, 1141 xs0 = endp->start.x, xs1 = AL_X_AT_Y(alp, ys); 1142 if (endp->end.y > alp->end.y) 1143 ye = alp->end.y, 1144 xe0 = AL_X_AT_Y(endp, ye), xe1 = alp->end.x; 1145 else 1146 ye = endp->end.y, 1147 xe0 = endp->end.x, xe1 = AL_X_AT_Y(alp, ye); 1148 dy = ye - ys; 1149 dx0 = xe0 - xs0; 1150 dx1 = xe1 - xs1; 1151 /* We need xs0 + cross * dx0 == xs1 + cross * dx1. */ 1152 if (dx0 == dx1) { 1153 /* The two lines are coincident. Do nothing. */ 1154 y_new = y1; 1155 } else { 1156 double cross = (double)(xs0 - xs1) / (dx1 - dx0); 1157 1158 y_new = (fixed)(ys + cross * dy); 1159 if (y_new <= y) { 1160 /* 1161 * This can only happen through some kind of 1162 * numeric disaster, but we have to check. 1163 */ 1164 INCR(cross_low); 1165 y_new = y + fixed_epsilon; 1166 } 1167 } 1168 } 1169 if (y_new < y1) { 1170 y1 = y_new; 1171 nx = AL_X_AT_Y(alp, y1); 1172 draw = 0; 1173 } 1174 if (nx > x) 1175 x = nx; 1176 } 1177 alp->x_next = nx; 1178 } 1179 /* Recompute next_x for lines before the intersection. */ 1180 for (alp = ll->x_list; alp != stopx; alp = alp->next) 1181 alp->x_next = AL_X_AT_Y(alp, y1); 1182 #ifdef DEBUG 1183 if (gs_debug_c('F')) { 1184 dlprintf1("[F]after loop: y1=%f\n", fixed2float(y1)); 1185 print_line_list(ll->x_list); 1186 } 1187 #endif 1188 /* Fill a multi-trapezoid band for the active lines. */ 1189 /* Don't bother if no pixel centers lie within the band. */ 1190 if (draw > 0 || (draw == 0 && HAVE_PIXELS())) { 1191 fixed height = y1 - y; 1192 fixed xlbot, xltop; /* as of last "outside" line */ 1193 int inside = 0; 1194 active_line *nlp; 1195 1196 INCR(band); 1197 for (x = min_fixed, alp = ll->x_list; alp != 0; alp = nlp) { 1198 fixed xbot = alp->x_current; 1199 fixed xtop = alp->x_current = alp->x_next; 1200 fixed wtop; 1201 int xi, xli; 1202 int code; 1203 1204 print_al("step", alp); 1205 INCR(band_step); 1206 nlp = alp->next; 1207 /* Handle ended or out-of-order lines. After this, */ 1208 /* the only member of alp we use is alp->direction. */ 1209 if (alp->end.y != y1 || !end_x_line(alp, true)) { 1210 if (xtop <= x) 1211 resort_x_line(alp); 1212 else 1213 x = xtop; 1214 } 1215 /* rule = -1 for winding number rule, i.e. */ 1216 /* we are inside if the winding number is non-zero; */ 1217 /* rule = 1 for even-odd rule, i.e. */ 1218 /* we are inside if the winding number is odd. */ 1219 #define INSIDE_PATH_P() ((inside & rule) != 0) 1220 if (!INSIDE_PATH_P()) { /* i.e., outside */ 1221 inside += alp->direction; 1222 if (INSIDE_PATH_P()) /* about to go in */ 1223 xlbot = xbot, xltop = xtop; 1224 continue; 1225 } 1226 /* We're inside a region being filled. */ 1227 inside += alp->direction; 1228 if (INSIDE_PATH_P()) /* not about to go out */ 1229 continue; 1230 #undef INSIDE_PATH_P 1231 /* We just went from inside to outside, so fill the region. */ 1232 wtop = xtop - xltop; 1233 INCR(band_fill); 1234 /* 1235 * If lines are temporarily out of order, we might have 1236 * xtop < xltop. Patch this up now if necessary. Note that 1237 * we can't test wtop < 0, because the subtraction might 1238 * overflow. 1239 */ 1240 if (xtop < xltop) { 1241 if_debug2('f', "[f]patch %g,%g\n", 1242 fixed2float(xltop), fixed2float(xtop)); 1243 xtop = xltop += arith_rshift(wtop, 1); 1244 wtop = 0; 1245 } 1246 if ((adjust_left | adjust_right) != 0) { 1247 xlbot -= adjust_left; 1248 xbot += adjust_right; 1249 xltop -= adjust_left; 1250 xtop += adjust_right; 1251 wtop = xtop - xltop; 1252 } 1253 if ((xli = fixed2int_var_pixround(xltop)) == 1254 fixed2int_var_pixround(xlbot) && 1255 (xi = fixed2int_var_pixround(xtop)) == 1256 fixed2int_var_pixround(xbot) 1257 ) { /* Rectangle. */ 1258 int yi = fixed2int_pixround(y - adjust_below); 1259 int wi = fixed2int_pixround(y1 + adjust_above) - yi; 1260 1261 code = LOOP_FILL_RECTANGLE_DIRECT(xli, yi, 1262 xi - xli, wi); 1263 } else if ((adjust_below | adjust_above) != 0) { 1264 /* 1265 * We want to get the effect of filling an area whose 1266 * outline is formed by dragging a square of side adj2 1267 * along the border of the trapezoid. This is *not* 1268 * equivalent to simply expanding the corners by 1269 * adjust: There are 3 cases needing different 1270 * algorithms, plus rectangles as a fast special case. 1271 */ 1272 fixed wbot = xbot - xlbot; 1273 1274 if (xltop <= xlbot) { 1275 if (xtop >= xbot) { /* Top wider than bottom. */ 1276 code = LOOP_FILL_TRAPEZOID_FIXED( 1277 xlbot, wbot, y - adjust_below, 1278 xltop, wtop, height); 1279 if (ADJUSTED_Y_SPANS_PIXEL(y1)) { 1280 if (code < 0) 1281 return code; 1282 INCR(afill); 1283 code = LOOP_FILL_RECTANGLE_DIRECT( 1284 xli, fixed2int_pixround(y1 - adjust_below), 1285 fixed2int_var_pixround(xtop) - xli, 1); 1286 } 1287 } else { /* Slanted trapezoid. */ 1288 code = fill_slant_adjust(xlbot, xbot, y, 1289 xltop, xtop, height, adjust_below, 1290 adjust_above, pbox, 1291 pdevc, dev, lop); 1292 } 1293 } else { 1294 if (xtop <= xbot) { /* Bottom wider than top. */ 1295 if (ADJUSTED_Y_SPANS_PIXEL(y)) { 1296 INCR(afill); 1297 xli = fixed2int_var_pixround(xlbot); 1298 code = LOOP_FILL_RECTANGLE_DIRECT( 1299 xli, fixed2int_pixround(y - adjust_below), 1300 fixed2int_var_pixround(xbot) - xli, 1); 1301 if (code < 0) 1302 return code; 1303 } 1304 code = LOOP_FILL_TRAPEZOID_FIXED( 1305 xlbot, wbot, y + adjust_above, 1306 xltop, wtop, height); 1307 } else { /* Slanted trapezoid. */ 1308 code = fill_slant_adjust(xlbot, xbot, y, 1309 xltop, xtop, height, adjust_below, 1310 adjust_above, pbox, 1311 pdevc, dev, lop); 1312 } 1313 } 1314 } else /* No Y adjustment. */ 1315 code = LOOP_FILL_TRAPEZOID_FIXED(xlbot, xbot - xlbot, 1316 y, xltop, wtop, height); 1317 if (code < 0) 1318 return code; 1319 } 1320 } else { 1321 /* Just scan for ended or out-of-order lines. */ 1322 active_line *nlp; 1323 1324 for (x = min_fixed, alp = ll->x_list; alp != 0; 1325 alp = nlp 1326 ) { 1327 fixed nx = alp->x_current = alp->x_next; 1328 1329 nlp = alp->next; 1330 if_debug4('F', 1331 "[F]check 0x%lx,x=%g 0x%lx,x=%g\n", 1332 (ulong) alp->prev, fixed2float(x), 1333 (ulong) alp, fixed2float(nx)); 1334 if (alp->end.y == y1) { 1335 if (end_x_line(alp, true)) 1336 continue; 1337 } 1338 if (nx <= x) 1339 resort_x_line(alp); 1340 else 1341 x = nx; 1342 } 1343 } 1344 #ifdef DEBUG 1345 if (gs_debug_c('f')) { 1346 int code = check_line_list(ll->x_list); 1347 1348 if (code < 0) 1349 return code; 1350 } 1351 #endif 1352 y = y1; 1353 } 1354 return 0; 1355 } 1356 1357 /* 1358 * Handle the case of a slanted trapezoid with adjustment. 1359 * To do this exactly right requires filling a central trapezoid 1360 * (or rectangle) plus two horizontal almost-rectangles. 1361 */ 1362 private int 1363 fill_slant_adjust(fixed xlbot, fixed xbot, fixed y, 1364 fixed xltop, fixed xtop, fixed height, fixed adjust_below, 1365 fixed adjust_above, const gs_fixed_rect * pbox, 1366 const gx_device_color * pdevc, gx_device * dev, 1367 gs_logical_operation_t lop) 1368 { 1369 fixed y1 = y + height; 1370 1371 dev_proc_fill_trapezoid((*fill_trap)) = 1372 dev_proc(dev, fill_trapezoid); 1373 const fixed yb = y - adjust_below; 1374 const fixed ya = y + adjust_above; 1375 const fixed y1b = y1 - adjust_below; 1376 const fixed y1a = y1 + adjust_above; 1377 const gs_fixed_edge *plbot; 1378 const gs_fixed_edge *prbot; 1379 const gs_fixed_edge *pltop; 1380 const gs_fixed_edge *prtop; 1381 gs_fixed_edge vert_left, slant_left, vert_right, slant_right; 1382 int code; 1383 1384 INCR(slant); 1385 1386 /* Set up all the edges, even though we may not need them all. */ 1387 1388 if (xlbot < xltop) { /* && xbot < xtop */ 1389 vert_left.start.x = vert_left.end.x = xlbot; 1390 vert_left.start.y = yb, vert_left.end.y = ya; 1391 vert_right.start.x = vert_right.end.x = xtop; 1392 vert_right.start.y = y1b, vert_right.end.y = y1a; 1393 slant_left.start.y = ya, slant_left.end.y = y1a; 1394 slant_right.start.y = yb, slant_right.end.y = y1b; 1395 plbot = &vert_left, prbot = &slant_right, 1396 pltop = &slant_left, prtop = &vert_right; 1397 } else { 1398 vert_left.start.x = vert_left.end.x = xltop; 1399 vert_left.start.y = y1b, vert_left.end.y = y1a; 1400 vert_right.start.x = vert_right.end.x = xbot; 1401 vert_right.start.y = yb, vert_right.end.y = ya; 1402 slant_left.start.y = yb, slant_left.end.y = y1b; 1403 slant_right.start.y = ya, slant_right.end.y = y1a; 1404 plbot = &slant_left, prbot = &vert_right, 1405 pltop = &vert_left, prtop = &slant_right; 1406 } 1407 slant_left.start.x = xlbot, slant_left.end.x = xltop; 1408 slant_right.start.x = xbot, slant_right.end.x = xtop; 1409 1410 if (ya >= y1b) { 1411 /* 1412 * The upper and lower adjustment bands overlap. 1413 * Since the entire entity is less than 2 pixels high 1414 * in this case, we could handle it very efficiently 1415 * with no more than 2 rectangle fills, but for right now 1416 * we don't attempt to do this. 1417 */ 1418 int iyb = fixed2int_var_pixround(yb); 1419 int iya = fixed2int_var_pixround(ya); 1420 int iy1b = fixed2int_var_pixround(y1b); 1421 int iy1a = fixed2int_var_pixround(y1a); 1422 1423 INCR(slant_shallow); 1424 if (iy1b > iyb) { 1425 code = (*fill_trap) (dev, plbot, prbot, 1426 yb, y1b, false, pdevc, lop); 1427 if (code < 0) 1428 return code; 1429 } 1430 if (iya > iy1b) { 1431 int ix = fixed2int_var_pixround(vert_left.start.x); 1432 int iw = fixed2int_var_pixround(vert_right.start.x) - ix; 1433 1434 code = LOOP_FILL_RECTANGLE(ix, iy1b, iw, iya - iy1b); 1435 if (code < 0) 1436 return code; 1437 } 1438 if (iy1a > iya) 1439 code = (*fill_trap) (dev, pltop, prtop, 1440 ya, y1a, false, pdevc, lop); 1441 else 1442 code = 0; 1443 } else { 1444 /* 1445 * Clip the trapezoid if possible. This can save a lot 1446 * of work when filling paths that cross band boundaries. 1447 */ 1448 fixed yac; 1449 1450 if (pbox->p.y < ya) { 1451 code = (*fill_trap) (dev, plbot, prbot, 1452 yb, ya, false, pdevc, lop); 1453 if (code < 0) 1454 return code; 1455 yac = ya; 1456 } else 1457 yac = pbox->p.y; 1458 if (pbox->q.y > y1b) { 1459 code = (*fill_trap) (dev, &slant_left, &slant_right, 1460 yac, y1b, false, pdevc, lop); 1461 if (code < 0) 1462 return code; 1463 code = (*fill_trap) (dev, pltop, prtop, 1464 y1b, y1a, false, pdevc, lop); 1465 } else 1466 code = (*fill_trap) (dev, &slant_left, &slant_right, 1467 yac, pbox->q.y, false, pdevc, lop); 1468 } 1469 return code; 1470 } 1471 1472 /* Re-sort the x list by moving alp backward to its proper spot. */ 1473 private void 1474 resort_x_line(active_line * alp) 1475 { 1476 active_line *prev = alp->prev; 1477 active_line *next = alp->next; 1478 1479 prev->next = next; 1480 if (next) 1481 next->prev = prev; 1482 while (x_order(prev, alp) > 0) { 1483 if_debug2('F', "[F]swap 0x%lx,0x%lx\n", 1484 (ulong) alp, (ulong) prev); 1485 next = prev, prev = prev->prev; 1486 } 1487 alp->next = next; 1488 alp->prev = prev; 1489 /* next might be null, if alp was in the correct spot already. */ 1490 if (next) 1491 next->prev = alp; 1492 prev->next = alp; 1493 } 1494 1495 /* ---------------- Range list management ---------------- */ 1496 1497 /* 1498 * We originally thought we would store fixed values in coordinate ranges, 1499 * but it turned out we want to store integers. 1500 */ 1501 typedef int coord_value_t; 1502 #define MIN_COORD_VALUE min_int 1503 #define MAX_COORD_VALUE max_int 1504 /* 1505 * The invariant for coord_range_ts in a coord_range_list_t: 1506 * if prev == 0: 1507 * next != 0 1508 * rmin == rmax == MIN_COORD_VALUE 1509 * else if next == 0: 1510 * prev != 0 1511 * rmin == rmax == MAX_COORD_VALUE 1512 * else 1513 * rmin < rmax 1514 * if prev != 0: 1515 * prev->next == this 1516 * prev->rmax < rmin 1517 * if next != 0: 1518 * next->prev = this 1519 * next->rmin > rmax 1520 * A coord_range_list_t has a boundary element at each end to avoid having 1521 * to test for null pointers in the insertion loop. The boundary elements 1522 * are the only empty ranges. 1523 */ 1524 typedef struct coord_range_s coord_range_t; 1525 struct coord_range_s { 1526 coord_value_t rmin, rmax; 1527 coord_range_t *prev, *next; 1528 coord_range_t *alloc_next; 1529 }; 1530 /* We declare coord_range_ts as simple because they only exist transiently. */ 1531 gs_private_st_simple(st_coord_range, coord_range_t, "coord_range_t"); 1532 1533 typedef struct coord_range_list_s { 1534 gs_memory_t *memory; 1535 struct rl_ { 1536 coord_range_t *first, *next, *limit; 1537 } local; 1538 coord_range_t *allocated; 1539 coord_range_t *freed; 1540 coord_range_t *current; 1541 coord_range_t first, last; 1542 } coord_range_list_t; 1543 1544 private coord_range_t * 1545 range_alloc(coord_range_list_t *pcrl) 1546 { 1547 coord_range_t *pcr; 1548 1549 if (pcrl->freed) { 1550 pcr = pcrl->freed; 1551 pcrl->freed = pcr->next; 1552 } else if (pcrl->local.next < pcrl->local.limit) 1553 pcr = pcrl->local.next++; 1554 else { 1555 pcr = gs_alloc_struct(pcrl->memory, coord_range_t, &st_coord_range, 1556 "range_alloc"); 1557 if (pcr == 0) 1558 return 0; 1559 pcr->alloc_next = pcrl->allocated; 1560 pcrl->allocated = pcr; 1561 } 1562 return pcr; 1563 } 1564 1565 private void 1566 range_delete(coord_range_list_t *pcrl, coord_range_t *pcr) 1567 { 1568 if_debug3('Q', "[Qr]delete 0x%lx: [%d,%d)\n", (ulong)pcr, pcr->rmin, 1569 pcr->rmax); 1570 pcr->prev->next = pcr->next; 1571 pcr->next->prev = pcr->prev; 1572 pcr->next = pcrl->freed; 1573 pcrl->freed = pcr; 1574 } 1575 1576 private void 1577 range_list_clear(coord_range_list_t *pcrl) 1578 { 1579 if_debug0('Q', "[Qr]clearing\n"); 1580 pcrl->first.next = &pcrl->last; 1581 pcrl->last.prev = &pcrl->first; 1582 pcrl->current = &pcrl->last; 1583 } 1584 1585 /* ------ "Public" procedures ------ */ 1586 1587 /* Initialize a range list. We require num_local >= 2. */ 1588 private void range_list_clear(P1(coord_range_list_t *)); 1589 private void 1590 range_list_init(coord_range_list_t *pcrl, coord_range_t *pcr_local, 1591 int num_local, gs_memory_t *mem) 1592 { 1593 pcrl->memory = mem; 1594 pcrl->local.first = pcrl->local.next = pcr_local; 1595 pcrl->local.limit = pcr_local + num_local; 1596 pcrl->allocated = pcrl->freed = 0; 1597 pcrl->first.rmin = pcrl->first.rmax = MIN_COORD_VALUE; 1598 pcrl->first.prev = 0; 1599 pcrl->last.rmin = pcrl->last.rmax = MAX_COORD_VALUE; 1600 pcrl->last.next = 0; 1601 range_list_clear(pcrl); 1602 } 1603 1604 /* Reset an initialized range list to the empty state. */ 1605 private void 1606 range_list_reset(coord_range_list_t *pcrl) 1607 { 1608 if (pcrl->first.next != &pcrl->last) { 1609 pcrl->last.prev->next = pcrl->freed; 1610 pcrl->freed = pcrl->first.next; 1611 range_list_clear(pcrl); 1612 } 1613 } 1614 1615 /* 1616 * Move the cursor to the beginning of a range list, in the belief that 1617 * the next added ranges will roughly parallel the existing ones. 1618 * (Only affects performance, not function.) 1619 */ 1620 inline private void 1621 range_list_rescan(coord_range_list_t *pcrl) 1622 { 1623 pcrl->current = pcrl->first.next; 1624 } 1625 1626 /* Free a range list. */ 1627 private void 1628 range_list_free(coord_range_list_t *pcrl) 1629 { 1630 coord_range_t *pcr; 1631 1632 while ((pcr = pcrl->allocated) != 0) { 1633 coord_range_t *next = pcr->alloc_next; 1634 1635 gs_free_object(pcrl->memory, pcr, "range_list_free"); 1636 pcrl->allocated = next; 1637 } 1638 } 1639 1640 /* Add a range. */ 1641 private int 1642 range_list_add(coord_range_list_t *pcrl, coord_value_t rmin, coord_value_t rmax) 1643 { 1644 coord_range_t *pcr = pcrl->current; 1645 1646 if (rmin >= rmax) 1647 return 0; 1648 /* 1649 * Usually, ranges are added in increasing order within each scan line, 1650 * and overlapping ranges don't differ much. Optimize accordingly. 1651 */ 1652 top: 1653 if (rmax < pcr->rmin) { 1654 if (rmin > pcr->prev->rmax) 1655 goto ins; 1656 pcr = pcr->prev; 1657 goto top; 1658 } 1659 if (rmin > pcr->rmax) { 1660 pcr = pcr->next; 1661 if (rmax < pcr->rmin) 1662 goto ins; 1663 goto top; 1664 } 1665 /* 1666 * Now we know that (rmin,rmax) overlaps (pcr->rmin,pcr->rmax). 1667 * Don't delete or merge into the special min and max ranges. 1668 */ 1669 while (rmin <= pcr->prev->rmax) { 1670 /* Merge the range below pcr into this one. */ 1671 if (!pcr->prev->prev) 1672 break; /* don't merge into the min range */ 1673 pcr->rmin = pcr->prev->rmin; 1674 range_delete(pcrl, pcr->prev); 1675 } 1676 while (rmax >= pcr->next->rmin) { 1677 /* Merge the range above pcr into this one. */ 1678 if (!pcr->next->next) 1679 break; /* don't merge into the max range */ 1680 pcr->rmax = pcr->next->rmax; 1681 range_delete(pcrl, pcr->next); 1682 } 1683 /* 1684 * Now we know that the union of (rmin,rmax) and (pcr->rmin,pcr->rmax) 1685 * doesn't overlap or abut either adjacent range, except that it may 1686 * abut if the adjacent range is the special min or max range. 1687 */ 1688 if (rmin < pcr->rmin) { 1689 if_debug3('Q', "[Qr]update 0x%lx => [%d,%d)\n", (ulong)pcr, rmin, 1690 pcr->rmax); 1691 pcr->rmin = rmin; 1692 } 1693 if (rmax > pcr->rmax) { 1694 if_debug3('Q', "[Qr]update 0x%lx => [%d,%d)\n", (ulong)pcr, pcr->rmin, 1695 rmax); 1696 pcr->rmax = rmax; 1697 } 1698 pcrl->current = pcr->next; 1699 return 0; 1700 ins: 1701 /* Insert a new range below pcr. */ 1702 { 1703 coord_range_t *prev = range_alloc(pcrl); 1704 1705 if (prev == 0) 1706 return_error(gs_error_VMerror); 1707 if_debug3('Q', "[Qr]insert 0x%lx: [%d,%d)\n", (ulong)prev, rmin, rmax); 1708 prev->rmin = rmin, prev->rmax = rmax; 1709 (prev->prev = pcr->prev)->next = prev; 1710 prev->next = pcr; 1711 pcr->prev = prev; 1712 } 1713 pcrl->current = pcr; 1714 return 0; 1715 } 1716 1717 /* ---------------- Scan line filling loop ---------------- */ 1718 1719 /* Forward references */ 1720 private int merge_ranges(P6(coord_range_list_t *pcrl, ll_ptr ll, 1721 fixed y_min, fixed y_top, 1722 fixed adjust_left, fixed adjust_right)); 1723 private void set_scan_line_points(P2(active_line *, fixed)); 1724 1725 /* Main filling loop. */ 1726 private int 1727 fill_loop_by_scan_lines(ll_ptr ll, gx_device * dev, 1728 const gx_fill_params * params, 1729 const gx_device_color * pdevc, 1730 gs_logical_operation_t lop, const gs_fixed_rect * pbox, 1731 fixed adjust_left, fixed adjust_right, 1732 fixed adjust_below, fixed adjust_above, 1733 fixed band_mask) 1734 { 1735 int rule = params->rule; 1736 fixed fixed_flat = float2fixed(params->flatness); 1737 bool fill_direct = color_writes_pure(pdevc, lop); 1738 gx_color_index cindex; 1739 dev_proc_fill_rectangle((*fill_rect)); 1740 active_line *yll = ll->y_list; 1741 fixed y_limit = pbox->q.y; 1742 /* 1743 * The meaning of adjust_below (B) and adjust_above (A) is that the 1744 * pixels that would normally be painted at coordinate Y get "smeared" 1745 * to coordinates Y-B through Y+A-epsilon, inclusive. This is 1746 * equivalent to saying that the pixels actually painted at coordinate Y 1747 * are those contributed by scan lines Y-A+epsilon through Y+B, 1748 * inclusive. (A = B = 0 is a special case, equivalent to B = 0, A = 1749 * epsilon.) 1750 */ 1751 fixed y_frac_min = 1752 (adjust_above == fixed_0 ? fixed_half : 1753 fixed_half + fixed_epsilon - adjust_above); 1754 fixed y_frac_max = 1755 fixed_half + adjust_below; 1756 int y0 = fixed2int(min_fixed); 1757 fixed y_bot = min_fixed; /* normally int2fixed(y0) + y_frac_min */ 1758 fixed y_top = min_fixed; /* normally int2fixed(y0) + y_frac_max */ 1759 coord_range_list_t rlist; 1760 coord_range_t rlocal[MAX_LOCAL_ACTIVE]; 1761 int code = 0; 1762 1763 if (yll == 0) /* empty list */ 1764 return 0; 1765 range_list_init(&rlist, rlocal, countof(rlocal), ll->memory); 1766 if (fill_direct) 1767 cindex = pdevc->colors.pure, 1768 fill_rect = dev_proc(dev, fill_rectangle); 1769 ll->x_list = 0; 1770 ll->x_head.x_current = min_fixed; /* stop backward scan */ 1771 while (code >= 0) { 1772 active_line *alp, *nlp; 1773 fixed y, x; 1774 bool new_band; 1775 1776 INCR(iter); 1777 1778 /* 1779 * Find the next sampling point, either the bottom of a sampling 1780 * band or a line start. 1781 */ 1782 1783 if (ll->x_list == 0) 1784 y = (yll == 0 ? y_limit : yll->start.y); 1785 else { 1786 y = y_bot + fixed_1; 1787 if (yll != 0) 1788 y = min(y, yll->start.y); 1789 for (alp = ll->x_list; alp != 0; alp = alp->next) 1790 if (!end_x_line(alp, false)) 1791 y = min(y, alp->end.y); 1792 } 1793 1794 /* Move newly active lines from y to x list. */ 1795 1796 while (yll != 0 && yll->start.y == y) { 1797 active_line *ynext = yll->next; /* insert smashes next/prev links */ 1798 1799 if (yll->direction == DIR_HORIZONTAL) { 1800 /* Ignore for now. */ 1801 } else { 1802 insert_x_new(yll, ll); 1803 set_scan_line_points(yll, fixed_flat); 1804 } 1805 yll = ynext; 1806 } 1807 1808 /* Update active lines to y. */ 1809 1810 x = min_fixed; 1811 for (alp = ll->x_list; alp != 0; alp = nlp) { 1812 fixed nx; 1813 1814 nlp = alp->next; 1815 e:if (alp->end.y <= y) { 1816 if (end_x_line(alp, true)) 1817 continue; 1818 set_scan_line_points(alp, fixed_flat); 1819 goto e; 1820 } 1821 nx = alp->x_current = 1822 (alp->start.y >= y ? alp->start.x : 1823 alp->curve_k < 0 ? 1824 AL_X_AT_Y(alp, y) : 1825 gx_curve_x_at_y(&alp->cursor, y)); 1826 if (nx < x) { 1827 /* Move this line backward in the list. */ 1828 active_line *ilp = alp; 1829 1830 while (nx < (ilp = ilp->prev)->x_current) 1831 DO_NOTHING; 1832 /* Now ilp->x_current <= nx < ilp->next->x_cur. */ 1833 alp->prev->next = alp->next; 1834 if (alp->next) 1835 alp->next->prev = alp->prev; 1836 if (ilp->next) 1837 ilp->next->prev = alp; 1838 alp->next = ilp->next; 1839 ilp->next = alp; 1840 alp->prev = ilp; 1841 continue; 1842 } 1843 x = nx; 1844 } 1845 1846 if (y > y_top || y >= y_limit) { 1847 /* We're beyond the end of the previous sampling band. */ 1848 const coord_range_t *pcr; 1849 1850 /* Fill the ranges for y0. */ 1851 1852 for (pcr = rlist.first.next; pcr != &rlist.last; 1853 pcr = pcr->next 1854 ) { 1855 int x0 = pcr->rmin, x1 = pcr->rmax; 1856 1857 if_debug4('Q', "[Qr]draw 0x%lx: [%d,%d),%d\n", (ulong)pcr, 1858 x0, x1, y0); 1859 code = LOOP_FILL_RECTANGLE_DIRECT(x0, y0, x1 - x0, 1); 1860 if_debug3('F', "[F]drawing [%d:%d),%d\n", x0, x1, y0); 1861 if (code < 0) 1862 goto done; 1863 } 1864 range_list_reset(&rlist); 1865 1866 /* Check whether we've reached the maximum y. */ 1867 1868 if (y >= y_limit) 1869 break; 1870 1871 /* Reset the sampling band. */ 1872 1873 y0 = fixed2int(y); 1874 if (fixed_fraction(y) < y_frac_min) 1875 --y0; 1876 y_bot = int2fixed(y0) + y_frac_min; 1877 y_top = int2fixed(y0) + y_frac_max; 1878 new_band = true; 1879 } else 1880 new_band = false; 1881 1882 if (y <= y_top) { 1883 /* 1884 * We're within the same Y pixel. Merge regions for segments 1885 * starting here (at y), up to y_top or the end of the segment. 1886 * If this is the first sampling within the band, run the 1887 * fill/eofill algorithm. 1888 */ 1889 fixed y_min; 1890 1891 if (new_band) { 1892 /* 1893 * rule = -1 for winding number rule, i.e. 1894 * we are inside if the winding number is non-zero; 1895 * rule = 1 for even-odd rule, i.e. 1896 * we are inside if the winding number is odd. 1897 */ 1898 int inside = 0; 1899 1900 #define INSIDE_PATH_P() ((inside & rule) != 0) 1901 INCR(band); 1902 for (alp = ll->x_list; alp != 0; alp = alp->next) { 1903 int x0 = fixed2int_pixround(alp->x_current - adjust_left); 1904 1905 for (;;) { 1906 /* We're inside a filled region. */ 1907 print_al("step", alp); 1908 INCR(band_step); 1909 inside += alp->direction; 1910 if (!INSIDE_PATH_P()) 1911 break; 1912 /* 1913 * Since we're dealing with closed paths, the test 1914 * for alp == 0 shouldn't be needed, but we may have 1915 * omitted lines that are to the right of the 1916 * clipping region. 1917 */ 1918 if ((alp = alp->next) == 0) 1919 goto out; 1920 } 1921 #undef INSIDE_PATH_P 1922 /* We just went from inside to outside, so fill the region. */ 1923 code = range_list_add(&rlist, x0, 1924 fixed2int_rounded(alp->x_current + 1925 adjust_right)); 1926 if (code < 0) 1927 goto done; 1928 } 1929 out: 1930 y_min = min_fixed; 1931 } else 1932 y_min = y; 1933 code = merge_ranges(&rlist, ll, y_min, y_top, adjust_left, 1934 adjust_right); 1935 } /* else y < y_bot + 1, do nothing */ 1936 } 1937 done: 1938 range_list_free(&rlist); 1939 return code; 1940 } 1941 1942 /* 1943 * Merge regions for active segments starting at a given Y, or all active 1944 * segments, up to the end of the sampling band or the end of the segment, 1945 * into the range list. 1946 */ 1947 private int 1948 merge_ranges(coord_range_list_t *pcrl, ll_ptr ll, fixed y_min, fixed y_top, 1949 fixed adjust_left, fixed adjust_right) 1950 { 1951 active_line *alp, *nlp; 1952 int code = 0; 1953 1954 range_list_rescan(pcrl); 1955 for (alp = ll->x_list; alp != 0 && code >= 0; alp = nlp) { 1956 fixed x0 = alp->x_current, x1, xt; 1957 1958 nlp = alp->next; 1959 if (alp->start.y < y_min) 1960 continue; 1961 if (alp->end.y < y_top) 1962 x1 = alp->end.x; 1963 else if (alp->curve_k < 0) 1964 x1 = AL_X_AT_Y(alp, y_top); 1965 else 1966 x1 = gx_curve_x_at_y(&alp->cursor, y_top); 1967 if (x0 > x1) 1968 xt = x0, x0 = x1, x1 = xt; 1969 code = range_list_add(pcrl, 1970 fixed2int_pixround(x0 - adjust_left), 1971 fixed2int_rounded(x1 + adjust_right)); 1972 } 1973 return code; 1974 } 1975 1976 /* 1977 * Set curve_k and, if necessary, the curve rendering parameters for 1978 * the current segment of an active line. 1979 */ 1980 private void 1981 set_scan_line_points(active_line * alp, fixed fixed_flat) 1982 { 1983 const segment *pseg = alp->pseg; 1984 const gs_fixed_point *pp0; 1985 1986 if (alp->direction < 0) { 1987 pseg = 1988 (pseg->type == s_line_close ? 1989 ((const line_close_segment *)pseg)->sub->next : 1990 pseg->next); 1991 if (pseg->type != s_curve) { 1992 alp->curve_k = -1; 1993 return; 1994 } 1995 pp0 = &alp->end; 1996 } else { 1997 if (pseg->type != s_curve) { 1998 alp->curve_k = -1; 1999 return; 2000 } 2001 pp0 = &alp->start; 2002 } 2003 { 2004 const curve_segment *const pcseg = (const curve_segment *)pseg; 2005 2006 alp->curve_k = 2007 gx_curve_log2_samples(pp0->x, pp0->y, pcseg, fixed_flat); 2008 gx_curve_cursor_init(&alp->cursor, pp0->x, pp0->y, pcseg, 2009 alp->curve_k); 2010 } 2011 } 2012