/* Check for interrupts before a return. */ int gs_return_check_interrupt(const gs_memory_t *mem, int code) { if (code < 0) return code; { int icode = gp_check_interrupts(mem); return (icode == 0 ? code : gs_note_error((icode > 0 ? gs_error_interrupt : icode))); } }
/* Draw a one-pixel-wide line. */ int gz_draw_line_fixed(fixed ixf, fixed iyf, fixed itoxf, fixed itoyf, const gx_device_color *pdevc, gs_state *pgs) { int ix = fixed2int_var(ixf); int iy = fixed2int_var(iyf); int itox = fixed2int_var(itoxf); int itoy = fixed2int_var(itoyf); gx_device *dev; gp_check_interrupts(); if ( itoy == iy ) /* horizontal line */ { return (ix <= itox ? gz_fill_rectangle(ix, iy, itox - ix + 1, 1, pdevc, pgs) : gz_fill_rectangle(itox, iy, ix - itox + 1, 1, pdevc, pgs) ); } if ( itox == ix ) /* vertical line */ { return (iy <= itoy ? gz_fill_rectangle(ix, iy, 1, itoy - iy + 1, pdevc, pgs) : gz_fill_rectangle(ix, itoy, 1, iy - itoy + 1, pdevc, pgs) ); } if ( color_is_pure(pdevc) && (dev = pgs->device->info, (*dev->procs->draw_line)(dev, ix, iy, itox, itoy, pdevc->color1)) >= 0 ) return 0; { fixed h = itoyf - iyf; fixed w = itoxf - ixf; fixed tf; #define fswap(a, b) tf = a, a = b, b = tf if ( (w < 0 ? -w : w) <= (h < 0 ? -h : h) ) { if ( h < 0 ) fswap(ixf, itoxf), fswap(iyf, itoyf), h = -h; return gz_fill_trapezoid_fixed(ixf - fixed_half, fixed_1, iyf, itoxf - fixed_half, fixed_1, h, 0, pdevc, pgs); } else { if ( w < 0 ) fswap(ixf, itoxf), fswap(iyf, itoyf), w = -w; return gz_fill_trapezoid_fixed(iyf - fixed_half, fixed_1, ixf, itoyf - fixed_half, fixed_1, w, 1, pdevc, pgs); } #undef fswap } }
int gz_fill_trapezoid_fixed(fixed fx0, fixed fw0, fixed fy0, fixed fx1, fixed fw1, fixed fh, int swap_axes, const gx_device_color *pdevc, gs_state *pgs) { const fixed ymin = fixed_rounded(fy0) + fixed_half; const fixed ymax = fixed_rounded(fy0 + fh); int iy = fixed2int_var(ymin); const int iy1 = fixed2int_var(ymax); if ( iy >= iy1 ) return 0; /* no scan lines to sample */ { trap_line l, r; int rxl, rxr, ry; const fixed dxl = fx1 - fx0; const fixed dxr = dxl + fw1 - fw0; const fixed yline = ymin - fy0; /* partial pixel offset to */ /* first line to sample */ int fill_direct = color_is_pure(pdevc); gx_color_index cindex; gx_device *dev; dev_proc_fill_rectangle((*fill_rect)); int code; if_debug2('z', "[z]y=[%d,%d]\n", iy, iy1); if ( fill_direct ) cindex = pdevc->color1, dev = pgs->device->info, fill_rect = dev->procs->fill_rectangle; gp_check_interrupts(); r.x = (l.x = fx0 + fixed_half) + fw0; ry = iy; /* If the rounded X values are the same on both sides, */ /* we can save ourselves a *lot* of work. */ if ( fixed_truncated(l.x) == fixed_rounded(fx1) && fixed_truncated(r.x) == fixed_rounded(fx1 + fw1) ) { rxl = fixed2int_var(l.x); rxr = fixed2int_var(r.x); iy = iy1; if_debug2('z', "[z]rectangle, x=[%d,%d]\n", rxl, rxr); goto last; } #define fill_trap_rect(x,y,w,h)\ (fill_direct ?\ (swap_axes ? (*fill_rect)(dev, y, x, h, w, cindex) :\ (*fill_rect)(dev, x, y, w, h, cindex)) :\ swap_axes ? gz_fill_rectangle(y, x, h, w, pdevc, pgs) :\ gz_fill_rectangle(x, y, w, h, pdevc, pgs)) /* Compute the dx/dy ratios. */ /* dx# = dx#i + (dx#f / fh). */ #define compute_dx(tl, d)\ if ( d >= 0 )\ { if ( d < fh ) tl.di = 0, tl.df = d;\ else tl.di = (int)(d / fh), tl.df = d - tl.di * fh, tl.x += yline * tl.di;\ }\ else\ { if ( (tl.df = d + fh) >= 0 /* d >= -fh */ ) tl.di = -1, tl.x -= yline;\ else tl.di = (int)-((fh - 1 - d) / fh), tl.df = d - tl.di * fh, tl.x += yline * tl.di;\ } /* Compute the x offsets at the first scan line to sample. */ /* We need to be careful in computing yline * dx#f {/,%} fh */ /* because the multiplication may overflow. We know that */ /* all the quantities involved are non-negative, and that */ /* yline is less than 1 (as a fixed, of course); this gives us */ /* a cheap conservative check for overflow in the multiplication. */ #define ymult_limit (max_fixed / fixed_1) #define ymult_quo(yl, dxxf)\ (dxxf < ymult_limit ? yl * dxxf / fh : fixed_mult_quo(yl, dxxf, fh)) #define ymult_rem(yl, dxxf)\ (dxxf < ymult_limit ? yl * dxxf % fh : fixed_mult_rem(yl, dxxf, fh)) /* It's worth checking for dxl == dxr, since this is the case */ /* for parallelograms (including stroked lines). */ compute_dx(l, dxl); if ( dxr == dxl ) { fixed fx = ymult_quo(yline, l.df); l.x += fx; if ( l.di == 0 ) r.di = 0, r.df = l.df; else /* too hard to do adjustments right */ compute_dx(r, dxr); r.x += fx; } else { l.x += ymult_quo(yline, l.df); compute_dx(r, dxr); r.x += ymult_quo(yline, r.df); } rxl = fixed2int_var(l.x); rxr = fixed2int_var(r.x); /* Compute one line's worth of dx/dy. */ /* dx# * fixed_1 = ld#i + (ld#f / fh). */ /* We don't have to bother with this if */ /* we're only sampling a single scan line. */ if ( iy1 - iy == 1 ) { iy++; goto last; } #define compute_ldx(tl)\ if ( tl.df < ymult_limit )\ tl.ldi = int2fixed(tl.di) + int2fixed(tl.df) / fh,\ tl.ldf = int2fixed(tl.df) % fh,\ tl.xf = yline * tl.df % fh - fh;\ else\ tl.ldi = int2fixed(tl.di) + fixed_mult_quo(fixed_1, tl.df, fh),\ tl.ldf = fixed_mult_rem(fixed_1, tl.df, fh),\ tl.xf = fixed_mult_rem(yline, tl.df, fh) - fh compute_ldx(l); if ( dxr == dxl ) r.ldi = l.ldi, r.ldf = l.ldf, r.xf = l.xf; else { compute_ldx(r); } #undef compute_ldx while ( ++iy != iy1 ) { int ixl, ixr; #define step_line(tl)\ tl.x += tl.ldi;\ if ( (tl.xf += tl.ldf) >= 0 ) tl.xf -= fh, tl.x++; step_line(l); step_line(r); #undef step_line ixl = fixed2int_var(l.x); ixr = fixed2int_var(r.x); if ( ixl != rxl || ixr != rxr ) { code = fill_trap_rect(rxl, ry, rxr - rxl, iy - ry); if ( code < 0 ) goto xit; rxl = ixl, rxr = ixr, ry = iy; } } last: code = fill_trap_rect(rxl, ry, rxr - rxl, iy - ry); xit: gp_check_interrupts(); if ( code < 0 && fill_direct ) return_error(code); return code; } }