From b42125b79edc28af6508145a24308674403a8460 Mon Sep 17 00:00:00 2001 From: Robin Watts Date: Fri, 8 Jun 2012 20:46:58 +0100 Subject: Fix Bug 693097; memory overwrite when handling knockout groups. When handling knockout groups, we have to copy the background from the previous group in so we can 'knockout' properly. If the previous group is a different colorspace, this gives us problems! The fix, implemented here, is to update the copy_pixmap_rect function to know how to copy between pixmaps of different depth. Gray <-> RGB are the ones we really care about; the generic code will probably do a horrible job, but shouldn't ever be called at present. This suffices to stop the crashing - we will probably revisit this when we revise the blending support. --- fitz/res_pixmap.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 79 insertions(+), 7 deletions(-) (limited to 'fitz') diff --git a/fitz/res_pixmap.c b/fitz/res_pixmap.c index a160b6ca..29dd95a0 100644 --- a/fitz/res_pixmap.c +++ b/fitz/res_pixmap.c @@ -165,7 +165,7 @@ fz_copy_pixmap_rect(fz_context *ctx, fz_pixmap *dest, fz_pixmap *src, fz_bbox r) { const unsigned char *srcp; unsigned char *destp; - int y, w, destspan, srcspan; + int x, y, w, destspan, srcspan; r = fz_intersect_bbox(r, fz_pixmap_bbox(ctx, dest)); r = fz_intersect_bbox(r, fz_pixmap_bbox(ctx, src)); @@ -174,18 +174,90 @@ fz_copy_pixmap_rect(fz_context *ctx, fz_pixmap *dest, fz_pixmap *src, fz_bbox r) if (w <= 0 || y <= 0) return; - w *= src->n; srcspan = src->w * src->n; srcp = src->samples + srcspan * (r.y0 - src->y) + src->n * (r.x0 - src->x); destspan = dest->w * dest->n; destp = dest->samples + destspan * (r.y0 - dest->y) + dest->n * (r.x0 - dest->x); - do + + if (src->n == dest->n) + { + w *= src->n; + do + { + memcpy(destp, srcp, w); + srcp += srcspan; + destp += destspan; + } + while (--y); + } + else if (src->n == 2 && dest->n == 4) + { + /* Copy, and convert from grey+alpha to rgb+alpha */ + srcspan -= w*2; + destspan -= w*4; + do + { + for (x = w; x > 0; x--) + { + unsigned char v = *srcp++; + unsigned char a = *srcp++; + *destp++ = v; + *destp++ = v; + *destp++ = v; + *destp++ = a; + } + srcp += srcspan; + destp += destspan; + } + while (--y); + } + else if (src->n == 4 && dest->n == 2) { - memcpy(destp, srcp, w); - srcp += srcspan; - destp += destspan; + /* Copy, and convert from rgb+alpha to grey+alpha */ + srcspan -= w*4; + destspan -= w*2; + do + { + for (x = w; x > 0; x--) + { + int v; + v = *srcp++; + v += *srcp++; + v += *srcp++; + *destp++ = (unsigned char)((v+1)/3); + *destp++ = *srcp++; + } + srcp += srcspan; + destp += destspan; + } + while (--y); + } + else + { + /* FIXME: Crap conversion */ + int z; + int sn = src->n-1; + int dn = dest->n-1; + + srcspan -= w*src->n; + destspan -= w*dest->n; + do + { + for (x = w; x > 0; x--) + { + int v = 0; + for (z = sn; z > 0; z--) + v += *srcp++; + v = (v * dn + (sn>>1)) / sn; + for (z = dn; z > 0; z--) + *destp++ = (unsigned char)v; + *destp++ = *srcp++; + } + srcp += srcspan; + destp += destspan; + } + while (--y); } - while (--y); } void -- cgit v1.2.3