diff options
author | Robin Watts <robin.watts@artifex.com> | 2012-06-08 20:46:58 +0100 |
---|---|---|
committer | Robin Watts <robin.watts@artifex.com> | 2012-06-08 20:46:58 +0100 |
commit | b42125b79edc28af6508145a24308674403a8460 (patch) | |
tree | c705cb39f6ecf7493f69a2a6dab0a8fcaa8d350b | |
parent | 65b8ae915465849babc1fa712971c701136f4ed5 (diff) | |
download | mupdf-b42125b79edc28af6508145a24308674403a8460.tar.xz |
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.
-rw-r--r-- | fitz/res_pixmap.c | 86 |
1 files changed, 79 insertions, 7 deletions
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 |