void fz_convert_rasterizer(fz_context *ctx, fz_rasterizer *r, int eofill, fz_pixmap *pix, unsigned char *colorbv, fz_overprint *eop) { fz_irect clip = fz_bound_rasterizer(ctx, r); clip = fz_intersect_irect(clip, fz_pixmap_bbox_no_ctx(pix)); clip = fz_intersect_irect(clip, fz_clip_rasterizer(ctx, r)); if (!fz_is_empty_irect(clip)) r->fns.convert(ctx, r, eofill, &clip, pix, colorbv, eop); }
static void fz_paint_image_imp(fz_pixmap *dst, const fz_irect *scissor, fz_pixmap *shape, fz_pixmap *img, const fz_matrix *ctm, byte *color, int alpha) { byte *dp, *sp, *hp; int u, v, fa, fb, fc, fd; int x, y, w, h; int sw, sh, n, hw; fz_irect bbox; int dolerp; void (*paintfn)(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w, int n, int alpha, byte *color, byte *hp); fz_matrix local_ctm = *ctm; fz_rect rect; /* grid fit the image */ fz_gridfit_matrix(&local_ctm); /* turn on interpolation for upscaled and non-rectilinear transforms */ dolerp = 0; if (!fz_is_rectilinear(&local_ctm)) dolerp = 1; if (sqrtf(local_ctm.a * local_ctm.a + local_ctm.b * local_ctm.b) > img->w) dolerp = 1; if (sqrtf(local_ctm.c * local_ctm.c + local_ctm.d * local_ctm.d) > img->h) dolerp = 1; /* except when we shouldn't, at large magnifications */ if (!img->interpolate) { if (sqrtf(local_ctm.a * local_ctm.a + local_ctm.b * local_ctm.b) > img->w * 2) dolerp = 0; if (sqrtf(local_ctm.c * local_ctm.c + local_ctm.d * local_ctm.d) > img->h * 2) dolerp = 0; } rect = fz_unit_rect; fz_irect_from_rect(&bbox, fz_transform_rect(&rect, &local_ctm)); fz_intersect_irect(&bbox, scissor); x = bbox.x0; if (shape && shape->x > x) x = shape->x; y = bbox.y0; if (shape && shape->y > y) y = shape->y; w = bbox.x1; if (shape && shape->x + shape->w < w) w = shape->x + shape->w; w -= x; h = bbox.y1; if (shape && shape->y + shape->h < h) h = shape->y + shape->h; h -= y; if (w < 0 || h < 0) return; /* map from screen space (x,y) to image space (u,v) */ fz_pre_scale(&local_ctm, 1.0f / img->w, 1.0f / img->h); fz_invert_matrix(&local_ctm, &local_ctm); fa = (int)(local_ctm.a *= 65536.0f); fb = (int)(local_ctm.b *= 65536.0f); fc = (int)(local_ctm.c *= 65536.0f); fd = (int)(local_ctm.d *= 65536.0f); local_ctm.e *= 65536.0f; local_ctm.f *= 65536.0f; /* Calculate initial texture positions. Do a half step to start. */ /* Bug 693021: Keep calculation in float for as long as possible to * avoid overflow. */ u = (int)((local_ctm.a * x) + (local_ctm.c * y) + local_ctm.e + ((local_ctm.a + local_ctm.c) * .5f)); v = (int)((local_ctm.b * x) + (local_ctm.d * y) + local_ctm.f + ((local_ctm.b + local_ctm.d) * .5f)); /* RJW: The following is voodoo. No idea why it works, but it gives * the best match between scaled/unscaled/interpolated/non-interpolated * that we have found. */ if (dolerp) { u -= 32768; v -= 32768; } dp = dst->samples + (unsigned int)(((y - dst->y) * dst->w + (x - dst->x)) * dst->n); n = dst->n; sp = img->samples; sw = img->w; sh = img->h; if (shape) { hw = shape->w; hp = shape->samples + (unsigned int)(((y - shape->y) * hw) + x - shape->x); } else { hw = 0; hp = NULL; } /* TODO: if (fb == 0 && fa == 1) call fz_paint_span */ if (dst->n == 4 && img->n == 2) { assert(!color); if (dolerp) paintfn = fz_paint_affine_g2rgb_lerp; else paintfn = fz_paint_affine_g2rgb_near; } else { if (dolerp) { if (color) paintfn = fz_paint_affine_color_lerp; else paintfn = fz_paint_affine_lerp; } else { if (color) paintfn = fz_paint_affine_color_near; else paintfn = fz_paint_affine_near; } } while (h--) { paintfn(dp, sp, sw, sh, u, v, fa, fb, w, n, alpha, color, hp); dp += dst->w * n; hp += hw; u += fc; v += fd; } }