/* * Handle the case of a large value or a value with a fraction part. * See gxmatrix.h for more details. */ fixed fixed_coeff_mult(fixed value, long coeff, const fixed_coeff *pfc, int maxb) { int shift = pfc->shift; /* * Test if the value is too large for simple long math. */ if ((value + (fixed_1 << (maxb - 1))) & (-fixed_1 << maxb)) { /* The second argument of fixed_mult_quo must be non-negative. */ return (coeff < 0 ? -fixed_mult_quo(value, -coeff, fixed_1 << shift) : fixed_mult_quo(value, coeff, fixed_1 << shift)); } else { /* * The construction above guarantees that the multiplications * won't overflow the capacity of an int. */ return (fixed) arith_rshift(fixed2int_var(value) * coeff + fixed2int(fixed_fraction(value) * coeff) + pfc->round, shift); } }
static fixed edge_x_at_y(const gs_fixed_edge * edge, fixed y) { return fixed_mult_quo(edge->end.x - edge->start.x, y - edge->start.y, edge->end.y - edge->start.y) + edge->start.x; }
/* Compute ldi, ldf, and xf similarly. */ static inline void compute_ldx(trap_line *tl, fixed ys) { int di = tl->di; fixed df = tl->df; fixed h = tl->h; if ( df < YMULT_LIMIT ) { if ( df == 0 ) /* vertical edge, worth checking for */ tl->ldi = int2fixed(di), tl->ldf = 0, tl->xf = -h; else { tl->ldi = int2fixed(di) + int2fixed(df) / h; tl->ldf = int2fixed(df) % h; tl->xf = (ys < fixed_1 ? ys * df % h : fixed_mult_rem(ys, df, h)) - h; } } else { tl->ldi = int2fixed(di) + fixed_mult_quo(fixed_1, df, h); tl->ldf = fixed_mult_rem(fixed_1, df, h); tl->xf = fixed_mult_rem(ys, df, h) - h; } }
static inline fixed Y_AT_X(active_line *alp, fixed xp) { return alp->start.y + fixed_mult_quo(xp - alp->start.x, alp->diff.y, alp->diff.x); }
/* We should swap axes to get best accuracy, but we don't. */ int gx_default_fill_triangle(gx_device * dev, fixed px, fixed py, fixed ax, fixed ay, fixed bx, fixed by, const gx_device_color * pdevc, gs_logical_operation_t lop) { fixed t; fixed ym; dev_proc_fill_trapezoid((*fill_trapezoid)) = dev_proc(dev, fill_trapezoid); gs_fixed_edge left, right; int code; /* Ensure ay >= 0, by >= 0. */ if (ay < 0) px += ax, py += ay, bx -= ax, by -= ay, ax = -ax, ay = -ay; if (by < 0) px += bx, py += by, ax -= bx, ay -= by, bx = -bx, by = -by; /* Ensure ay <= by. */ if (ay > by) SWAP(ax, bx, t), SWAP(ay, by, t); /* * Make a special check for a flat bottom or top, * which we can handle with a single call on fill_trapezoid. */ left.start.x = right.start.x = px; left.start.y = right.start.y = py; if (ay == 0) { /* Flat top */ if (ax < 0) left.start.x = px + ax; else right.start.x = px + ax; left.end.x = right.end.x = px + bx; left.end.y = right.end.y = py + by; ym = py; } else if (ay == by) { /* Flat bottom */ if (ax < bx) left.end.x = px + ax, right.end.x = px + bx; else left.end.x = px + bx, right.end.x = px + ax; left.end.y = right.end.y = py + by; ym = py; } else { ym = py + ay; if (fixed_mult_quo(bx, ay, by) < ax) { /* The 'b' line is to the left of the 'a' line. */ left.end.x = px + bx, left.end.y = py + by; right.end.x = px + ax, right.end.y = py + ay; code = (*fill_trapezoid) (dev, &left, &right, py, ym, false, pdevc, lop); right.start = right.end; right.end = left.end; } else { /* The 'a' line is to the left of the 'b' line. */ left.end.x = px + ax, left.end.y = py + ay; right.end.x = px + bx, right.end.y = py + by; code = (*fill_trapezoid) (dev, &left, &right, py, ym, false, pdevc, lop); left.start = left.end; left.end = right.end; } if (code < 0) return code; } return (*fill_trapezoid) (dev, &left, &right, ym, right.end.y, false, pdevc, lop); }
/* Define the 'remainder' analogue of fixed_mult_quo. */ static fixed fixed_mult_rem(fixed a, fixed b, fixed c) { /* All kinds of truncation may happen here, but it's OK. */ return a * b - fixed_mult_quo(a, b, c) * c; }