From 20191dcca2bde592da73db125193bb773c62f502 Mon Sep 17 00:00:00 2001 From: Tor Andersson Date: Thu, 20 May 2010 23:49:12 +0200 Subject: Draw images with anti-aliased edges. --- fitz/dev_draw.c | 197 +++++++++++++++++--------------------------------------- 1 file changed, 60 insertions(+), 137 deletions(-) (limited to 'fitz/dev_draw.c') diff --git a/fitz/dev_draw.c b/fitz/dev_draw.c index cc7bdc0c..1b2b4ded 100644 --- a/fitz/dev_draw.c +++ b/fitz/dev_draw.c @@ -133,11 +133,11 @@ fz_drawfillpath(void *user, fz_path *path, int evenodd, fz_matrix ctm, argb[1] = rgb[0] * 255; argb[2] = rgb[1] * 255; argb[3] = rgb[2] * 255; - fz_scanconvert(dev->gel, dev->ael, evenodd, bbox, dev->dest, argb, 1); + fz_scanconvert(dev->gel, dev->ael, evenodd, bbox, dev->dest, argb, nil, nil); } else { - fz_scanconvert(dev->gel, dev->ael, evenodd, bbox, dev->dest, nil, 1); + fz_scanconvert(dev->gel, dev->ael, evenodd, bbox, dev->dest, nil, nil, nil); } } @@ -176,11 +176,11 @@ fz_drawstrokepath(void *user, fz_path *path, fz_strokestate *stroke, fz_matrix c argb[1] = rgb[0] * 255; argb[2] = rgb[1] * 255; argb[3] = rgb[2] * 255; - fz_scanconvert(dev->gel, dev->ael, 0, bbox, dev->dest, argb, 1); + fz_scanconvert(dev->gel, dev->ael, 0, bbox, dev->dest, argb, nil, nil); } else { - fz_scanconvert(dev->gel, dev->ael, 0, bbox, dev->dest, nil, 1); + fz_scanconvert(dev->gel, dev->ael, 0, bbox, dev->dest, nil, nil, nil); } } @@ -222,7 +222,7 @@ fz_drawclippath(void *user, fz_path *path, int evenodd, fz_matrix ctm) memset(mask->samples, 0, mask->w * mask->h * mask->n); memset(dest->samples, 0, dest->w * dest->h * dest->n); - fz_scanconvert(dev->gel, dev->ael, evenodd, bbox, mask, nil, 1); + fz_scanconvert(dev->gel, dev->ael, evenodd, bbox, mask, nil, nil, nil); dev->clipstack[dev->cliptop].scissor = dev->scissor; dev->clipstack[dev->cliptop].mask = mask; @@ -268,7 +268,7 @@ fz_drawclipstrokepath(void *user, fz_path *path, fz_strokestate *stroke, fz_matr memset(dest->samples, 0, dest->w * dest->h * dest->n); if (!fz_isemptyrect(bbox)) - fz_scanconvert(dev->gel, dev->ael, 0, bbox, mask, nil, 1); + fz_scanconvert(dev->gel, dev->ael, 0, bbox, mask, nil, nil, nil); dev->clipstack[dev->cliptop].scissor = dev->scissor; dev->clipstack[dev->cliptop].mask = mask; @@ -515,49 +515,66 @@ fz_drawfillshade(void *user, fz_shade *shade, fz_matrix ctm) } static inline void -calcimagescale(fz_matrix ctm, int w, int h, int *odx, int *ody) +calcimagestate(fz_drawdevice *dev, fz_pixmap *image, fz_matrix ctm, + fz_bbox *bbox, fz_matrix *invmat, int *dx, int *dy) { - float sx = w / sqrt(ctm.a * ctm.a + ctm.b * ctm.b); - float sy = h / sqrt(ctm.c * ctm.c + ctm.d * ctm.d); + float sx, sy; + fz_path *path; + fz_matrix mat; + int w, h; + + sx = image->w / sqrt(ctm.a * ctm.a + ctm.b * ctm.b); + sy = image->h / sqrt(ctm.c * ctm.c + ctm.d * ctm.d); if (sx < 1.0) - *odx = 1; + *dx = 1; else - *odx = sx; + *dx = sx; if (sy < 1.0) - *ody = 1; + *dy = 1; else - *ody = sy; -} + *dy = sy; + + w = image->w / *dx; + h = image->h / *dy; + + path = fz_newpath(); + fz_moveto(path, 0.0, 0.0); + fz_lineto(path, 1.0, 0.0); + fz_lineto(path, 1.0, 1.0); + fz_lineto(path, 0.0, 1.0); + fz_closepath(path); -#define PDST(p) p->samples + ((y0-p->y) * p->w + (x0-p->x)) * p->n, p->w * p->n + fz_resetgel(dev->gel, dev->scissor); + fz_fillpath(dev->gel, path, ctm, 1.0); + fz_sortgel(dev->gel); + + fz_freepath(path); + + *bbox = fz_boundgel(dev->gel); + *bbox = fz_intersectbbox(*bbox, dev->scissor); + + mat.a = 1.0 / w; + mat.b = 0.0; + mat.c = 0.0; + mat.d = -1.0 / h; + mat.e = 0.0; + mat.f = 1.0; + *invmat = fz_invertmatrix(fz_concat(mat, ctm)); + invmat->e -= 0.5; + invmat->f -= 0.5; +} static void fz_drawfillimage(void *user, fz_pixmap *image, fz_matrix ctm) { fz_drawdevice *dev = user; - fz_rect bounds; fz_bbox bbox; int dx, dy; fz_pixmap *scaled = nil; fz_pixmap *converted = nil; - fz_matrix imgmat; fz_matrix invmat; - int fa, fb, fc, fd; - int u0, v0; - int x0, y0; - int w, h; - - bounds = fz_transformrect(ctm, fz_unitrect); - bbox = fz_roundrect(bounds); - bbox = fz_intersectbbox(bbox, dev->scissor); - - if (fz_isemptyrect(bbox)) - return; - - if (image->w == 0 || image->h == 0) - return; if (!dev->model) { @@ -565,7 +582,10 @@ fz_drawfillimage(void *user, fz_pixmap *image, fz_matrix ctm) return; } - calcimagescale(ctm, image->w, image->h, &dx, &dy); + calcimagestate(dev, image, ctm, &bbox, &invmat, &dx, &dy); + + if (fz_isemptyrect(bbox) || image->w == 0 || image->h == 0) + return; if (dx != 1 || dy != 1) { @@ -580,34 +600,7 @@ fz_drawfillimage(void *user, fz_pixmap *image, fz_matrix ctm) image = converted; } - imgmat.a = 1.0 / image->w; - imgmat.b = 0.0; - imgmat.c = 0.0; - imgmat.d = -1.0 / image->h; - imgmat.e = 0.0; - imgmat.f = 1.0; - invmat = fz_invertmatrix(fz_concat(imgmat, ctm)); - - invmat.e -= 0.5; - invmat.f -= 0.5; - - w = bbox.x1 - bbox.x0; - h = bbox.y1 - bbox.y0; - x0 = bbox.x0; - y0 = bbox.y0; - u0 = (invmat.a * (x0+0.5) + invmat.c * (y0+0.5) + invmat.e) * 65536; - v0 = (invmat.b * (x0+0.5) + invmat.d * (y0+0.5) + invmat.f) * 65536; - fa = invmat.a * 65536; - fb = invmat.b * 65536; - fc = invmat.c * 65536; - fd = invmat.d * 65536; - - if (dev->dest->colorspace) - fz_img_4o4(image->samples, image->w, image->h, PDST(dev->dest), - u0, v0, fa, fb, fc, fd, w, h); - else - fz_img_1o1(image->samples, image->w, image->h, PDST(dev->dest), - u0, v0, fa, fb, fc, fd, w, h); + fz_scanconvert(dev->gel, dev->ael, 0, bbox, dev->dest, nil, image, &invmat); if (scaled) fz_droppixmap(scaled); @@ -620,57 +613,22 @@ fz_drawfillimagemask(void *user, fz_pixmap *image, fz_matrix ctm, fz_colorspace *colorspace, float *color, float alpha) { fz_drawdevice *dev = user; - fz_rect bounds; fz_bbox bbox; int dx, dy; fz_pixmap *scaled = nil; - fz_matrix imgmat; fz_matrix invmat; - int fa, fb, fc, fd; - int u0, v0; - int x0, y0; - int w, h; - bounds = fz_transformrect(ctm, fz_unitrect); - bbox = fz_roundrect(bounds); - bbox = fz_intersectbbox(bbox, dev->scissor); + calcimagestate(dev, image, ctm, &bbox, &invmat, &dx, &dy); - if (fz_isemptyrect(bbox)) + if (fz_isemptyrect(bbox) || image->w == 0 || image->h == 0) return; - if (image->w == 0 || image->h == 0) - return; - - calcimagescale(ctm, image->w, image->h, &dx, &dy); - if (dx != 1 || dy != 1) { scaled = fz_scalepixmap(image, dx, dy); image = scaled; } - imgmat.a = 1.0 / image->w; - imgmat.b = 0.0; - imgmat.c = 0.0; - imgmat.d = -1.0 / image->h; - imgmat.e = 0.0; - imgmat.f = 1.0; - invmat = fz_invertmatrix(fz_concat(imgmat, ctm)); - - invmat.e -= 0.5; - invmat.f -= 0.5; - - w = bbox.x1 - bbox.x0; - h = bbox.y1 - bbox.y0; - x0 = bbox.x0; - y0 = bbox.y0; - u0 = (invmat.a * (x0+0.5) + invmat.c * (y0+0.5) + invmat.e) * 65536; - v0 = (invmat.b * (x0+0.5) + invmat.d * (y0+0.5) + invmat.f) * 65536; - fa = invmat.a * 65536; - fb = invmat.b * 65536; - fc = invmat.c * 65536; - fd = invmat.d * 65536; - if (dev->dest->colorspace) { unsigned char argb[4]; @@ -680,13 +638,11 @@ fz_drawfillimagemask(void *user, fz_pixmap *image, fz_matrix ctm, argb[1] = rgb[0] * 255; argb[2] = rgb[1] * 255; argb[3] = rgb[2] * 255; - fz_img_w4i1o4(argb, image->samples, image->w, image->h, PDST(dev->dest), - u0, v0, fa, fb, fc, fd, w, h); + fz_scanconvert(dev->gel, dev->ael, 0, bbox, dev->dest, argb, image, &invmat); } else { - fz_img_1o1(image->samples, image->w, image->h, PDST(dev->dest), - u0, v0, fa, fb, fc, fd, w, h); + fz_scanconvert(dev->gel, dev->ael, 0, bbox, dev->dest, nil, image, &invmat); } if (scaled) @@ -697,17 +653,11 @@ static void fz_drawclipimagemask(void *user, fz_pixmap *image, fz_matrix ctm) { fz_drawdevice *dev = user; - fz_rect bounds; fz_bbox bbox; fz_pixmap *mask, *dest; int dx, dy; fz_pixmap *scaled = nil; - fz_matrix imgmat; fz_matrix invmat; - int fa, fb, fc, fd; - int u0, v0; - int x0, y0; - int w, h; if (dev->cliptop == MAXCLIP) { @@ -715,11 +665,9 @@ fz_drawclipimagemask(void *user, fz_pixmap *image, fz_matrix ctm) return; } - bounds = fz_transformrect(ctm, fz_unitrect); - bbox = fz_roundrect(bounds); - bbox = fz_intersectbbox(bbox, dev->scissor); + calcimagestate(dev, image, ctm, &bbox, &invmat, &dx, &dy); - if (fz_isemptyrect(bbox) || (image->w == 0 || image->h == 0)) + if (fz_isemptyrect(bbox) || image->w == 0 || image->h == 0) { dev->clipstack[dev->cliptop].scissor = dev->scissor; dev->clipstack[dev->cliptop].mask = nil; @@ -729,44 +677,19 @@ fz_drawclipimagemask(void *user, fz_pixmap *image, fz_matrix ctm) return; } - calcimagescale(ctm, image->w, image->h, &dx, &dy); - if (dx != 1 || dy != 1) { scaled = fz_scalepixmap(image, dx, dy); image = scaled; } - imgmat.a = 1.0 / image->w; - imgmat.b = 0.0; - imgmat.c = 0.0; - imgmat.d = -1.0 / image->h; - imgmat.e = 0.0; - imgmat.f = 1.0; - invmat = fz_invertmatrix(fz_concat(imgmat, ctm)); - - invmat.e -= 0.5; - invmat.f -= 0.5; - - w = bbox.x1 - bbox.x0; - h = bbox.y1 - bbox.y0; - x0 = bbox.x0; - y0 = bbox.y0; - u0 = (invmat.a * (x0+0.5) + invmat.c * (y0+0.5) + invmat.e) * 65536; - v0 = (invmat.b * (x0+0.5) + invmat.d * (y0+0.5) + invmat.f) * 65536; - fa = invmat.a * 65536; - fb = invmat.b * 65536; - fc = invmat.c * 65536; - fd = invmat.d * 65536; - mask = fz_newpixmapwithrect(nil, bbox); dest = fz_newpixmapwithrect(dev->model, bbox); memset(mask->samples, 0, mask->w * mask->h * mask->n); memset(dest->samples, 0, dest->w * dest->h * dest->n); - fz_img_1o1(image->samples, image->w, image->h, PDST(mask), - u0, v0, fa, fb, fc, fd, w, h); + fz_scanconvert(dev->gel, dev->ael, 0, bbox, mask, nil, image, &invmat); dev->clipstack[dev->cliptop].scissor = dev->scissor; dev->clipstack[dev->cliptop].mask = mask; -- cgit v1.2.3