diff options
-rw-r--r-- | include/mupdf/fitz/device.h | 29 | ||||
-rw-r--r-- | source/fitz/device.c | 85 | ||||
-rw-r--r-- | source/fitz/svg-device.c | 27 |
3 files changed, 96 insertions, 45 deletions
diff --git a/include/mupdf/fitz/device.h b/include/mupdf/fitz/device.h index 51a83c60..fe4a1dbd 100644 --- a/include/mupdf/fitz/device.h +++ b/include/mupdf/fitz/device.h @@ -73,6 +73,27 @@ enum int fz_lookup_blendmode(char *name); char *fz_blendmode_name(int blendmode); +typedef struct fz_device_container_stack_s fz_device_container_stack; + +struct fz_device_container_stack_s +{ + fz_rect scissor; + int flags; + int user; +}; + +enum +{ + fz_device_container_stack_is_clip_path = 1, + fz_device_container_stack_is_clip_stroke_path = 2, + fz_device_container_stack_is_clip_text = 4, + fz_device_container_stack_is_clip_stroke_text = 8, + fz_device_container_stack_is_clip_image_mask = 16, + fz_device_container_stack_in_mask = 32, + fz_device_container_stack_is_mask = 64, + fz_device_container_stack_is_group = 128, +}; + struct fz_device_s { int hints; @@ -114,9 +135,9 @@ struct fz_device_s int error_depth; char errmess[256]; - int scissor_len; - int scissor_cap; - fz_rect *scissor; + int container_len; + int container_cap; + fz_device_container_stack *container; fz_rect scissor_accumulator; }; @@ -181,7 +202,7 @@ enum FZ_IGNORE_IMAGE = 1, FZ_IGNORE_SHADE = 2, FZ_DONT_INTERPOLATE_IMAGES = 4, - FZ_MAINTAIN_SCISSOR_STACK = 8, + FZ_MAINTAIN_CONTAINER_STACK = 8, }; /* diff --git a/source/fitz/device.c b/source/fitz/device.c index 2d042ade..79f2f42a 100644 --- a/source/fitz/device.c +++ b/source/fitz/device.c @@ -19,7 +19,7 @@ fz_free_device(fz_device *dev) return; if (dev->free_user) dev->free_user(dev); - fz_free(dev->ctx, dev->scissor); + fz_free(dev->ctx, dev->container); fz_free(dev->ctx, dev); } @@ -50,24 +50,26 @@ fz_end_page(fz_device *dev) } static void -push_clip_stack(fz_device *dev, const fz_rect *rect) +push_clip_stack(fz_device *dev, const fz_rect *rect, int flags) { - if (dev->scissor_len == dev->scissor_cap) + if (dev->container_len == dev->container_cap) { - int newmax = dev->scissor_cap * 2; + int newmax = dev->container_cap * 2; if (newmax == 0) newmax = 4; - dev->scissor = fz_resize_array(dev->ctx, dev->scissor, newmax, sizeof(*dev->scissor)); - dev->scissor_cap = newmax; + dev->container = fz_resize_array(dev->ctx, dev->container, newmax, sizeof(*dev->container)); + dev->container_cap = newmax; } - if (dev->scissor_len == 0) - dev->scissor[0] = *rect; + if (dev->container_len == 0) + dev->container[0].scissor = *rect; else { - dev->scissor[dev->scissor_len] = dev->scissor[dev->scissor_len-1]; - fz_intersect_rect(&dev->scissor[dev->scissor_len], rect); + dev->container[dev->container_len].scissor = dev->container[dev->container_len-1].scissor; + fz_intersect_rect(&dev->container[dev->container_len].scissor, rect); } - dev->scissor_len++; + dev->container[dev->container_len].flags = flags; + dev->container[dev->container_len].user = 0; + dev->container_len++; } static void @@ -76,31 +78,33 @@ push_clip_stack_accumulate(fz_device *dev, const fz_rect *rect, int accumulate) if (accumulate <= 1) { dev->scissor_accumulator = *rect; - if (dev->scissor_len == dev->scissor_cap) + if (dev->container_len == dev->container_cap) { - int newmax = dev->scissor_cap * 2; + int newmax = dev->container_cap * 2; if (newmax == 0) newmax = 4; - dev->scissor = fz_resize_array(dev->ctx, dev->scissor, newmax, sizeof(*dev->scissor)); - dev->scissor_cap = newmax; + dev->container = fz_resize_array(dev->ctx, dev->container, newmax, sizeof(*dev->container)); + dev->container_cap = newmax; } - fz_intersect_rect(&dev->scissor[dev->scissor_len], rect); - dev->scissor_len++; + fz_intersect_rect(&dev->container[dev->container_len].scissor, rect); + dev->container[dev->container_len].flags = fz_device_container_stack_is_clip_text; + dev->container[dev->container_len].user = 0; + dev->container_len++; } else { - if (dev->scissor_len <= 0) + if (dev->container_len <= 0) return; fz_union_rect(&dev->scissor_accumulator, rect); - fz_intersect_rect(&dev->scissor[dev->scissor_len-1], &dev->scissor_accumulator); + fz_intersect_rect(&dev->container[dev->container_len-1].scissor, &dev->scissor_accumulator); } } static void pop_clip_stack(fz_device *dev) { - if (dev->scissor_len > 0) - dev->scissor_len--; + if (dev->container_len > 0) + dev->container_len--; } void @@ -136,16 +140,16 @@ fz_clip_path(fz_device *dev, fz_path *path, const fz_rect *rect, int even_odd, c fz_try(ctx) { - if (dev->hints & FZ_MAINTAIN_SCISSOR_STACK) + if (dev->hints & FZ_MAINTAIN_CONTAINER_STACK) { if (rect == NULL) { fz_rect bbox; fz_bound_path(ctx, path, NULL, ctm, &bbox); - push_clip_stack(dev, &bbox); + push_clip_stack(dev, &bbox, fz_device_container_stack_is_clip_path); } else - push_clip_stack(dev, rect); + push_clip_stack(dev, rect, fz_device_container_stack_is_clip_path); } if (dev->clip_path) dev->clip_path(dev, path, rect, even_odd, ctm); @@ -171,16 +175,16 @@ fz_clip_stroke_path(fz_device *dev, fz_path *path, const fz_rect *rect, fz_strok fz_try(ctx) { - if (dev->hints & FZ_MAINTAIN_SCISSOR_STACK) + if (dev->hints & FZ_MAINTAIN_CONTAINER_STACK) { if (rect == NULL) { fz_rect bbox; fz_bound_path(ctx, path, stroke, ctm, &bbox); - push_clip_stack(dev, &bbox); + push_clip_stack(dev, &bbox, fz_device_container_stack_is_clip_stroke_path); } else - push_clip_stack(dev, rect); + push_clip_stack(dev, rect, fz_device_container_stack_is_clip_stroke_path); } if (dev->clip_stroke_path) dev->clip_stroke_path(dev, path, rect, stroke, ctm); @@ -227,7 +231,7 @@ fz_clip_text(fz_device *dev, fz_text *text, const fz_matrix *ctm, int accumulate fz_try(ctx) { - if (dev->hints & FZ_MAINTAIN_SCISSOR_STACK) + if (dev->hints & FZ_MAINTAIN_CONTAINER_STACK) { fz_rect bbox; fz_bound_text(ctx, text, NULL, ctm, &bbox); @@ -259,11 +263,11 @@ fz_clip_stroke_text(fz_device *dev, fz_text *text, fz_stroke_state *stroke, cons fz_try(ctx) { - if (dev->hints & FZ_MAINTAIN_SCISSOR_STACK) + if (dev->hints & FZ_MAINTAIN_CONTAINER_STACK) { fz_rect bbox; fz_bound_text(ctx, text, stroke, ctm, &bbox); - push_clip_stack_accumulate(dev, &bbox, 0); + push_clip_stack(dev, &bbox, fz_device_container_stack_is_clip_stroke_text); } if (dev->clip_stroke_text) dev->clip_stroke_text(dev, text, stroke, ctm); @@ -295,7 +299,7 @@ fz_pop_clip(fz_device *dev) fz_throw(dev->ctx, FZ_ERROR_GENERIC, "%s", dev->errmess); return; } - if (dev->hints & FZ_MAINTAIN_SCISSOR_STACK) + if (dev->hints & FZ_MAINTAIN_CONTAINER_STACK) pop_clip_stack(dev); if (dev->pop_clip) dev->pop_clip(dev); @@ -342,8 +346,8 @@ fz_clip_image_mask(fz_device *dev, fz_image *image, const fz_rect *rect, const f fz_try(ctx) { - if (dev->hints & FZ_MAINTAIN_SCISSOR_STACK) - push_clip_stack(dev, rect); + if (dev->hints & FZ_MAINTAIN_CONTAINER_STACK) + push_clip_stack(dev, rect, fz_device_container_stack_is_clip_image_mask); if (dev->clip_image_mask) dev->clip_image_mask(dev, image, rect, ctm); } @@ -368,8 +372,8 @@ fz_begin_mask(fz_device *dev, const fz_rect *area, int luminosity, fz_colorspace fz_try(ctx) { - if (dev->hints & FZ_MAINTAIN_SCISSOR_STACK) - push_clip_stack(dev, area); + if (dev->hints & FZ_MAINTAIN_CONTAINER_STACK) + push_clip_stack(dev, area, fz_device_container_stack_in_mask); if (dev->begin_mask) dev->begin_mask(dev, area, luminosity, colorspace, bc); } @@ -389,6 +393,11 @@ fz_end_mask(fz_device *dev) /* Converts from mask to clip, so no change in stack depth */ return; } + if (dev->hints & FZ_MAINTAIN_CONTAINER_STACK) + { + dev->container[dev->container_len-1].flags &= ~fz_device_container_stack_in_mask; + dev->container[dev->container_len-1].flags |= fz_device_container_stack_is_mask; + } if (dev->end_mask) dev->end_mask(dev); } @@ -406,8 +415,8 @@ fz_begin_group(fz_device *dev, const fz_rect *area, int isolated, int knockout, fz_try(ctx) { - if (dev->hints & FZ_MAINTAIN_SCISSOR_STACK) - push_clip_stack(dev, area); + if (dev->hints & FZ_MAINTAIN_CONTAINER_STACK) + push_clip_stack(dev, area, fz_device_container_stack_is_group); if (dev->begin_group) dev->begin_group(dev, area, isolated, knockout, blendmode, alpha); } @@ -431,7 +440,7 @@ fz_end_group(fz_device *dev) } if (dev->end_group) dev->end_group(dev); - if (dev->hints & FZ_MAINTAIN_SCISSOR_STACK) + if (dev->hints & FZ_MAINTAIN_CONTAINER_STACK) pop_clip_stack(dev); } diff --git a/source/fitz/svg-device.c b/source/fitz/svg-device.c index 77eeb072..ddf4031c 100644 --- a/source/fitz/svg-device.c +++ b/source/fitz/svg-device.c @@ -723,10 +723,10 @@ svg_dev_fill_shade(fz_device *dev, fz_shade *shade, const fz_matrix *ctm, float fz_var(buf); - if (dev->scissor_len == 0) + if (dev->container_len == 0) return; - fz_round_rect(&bbox, fz_intersect_rect(fz_bound_shade(ctx, shade, ctm, &rect), &dev->scissor[dev->scissor_len-1])); + fz_round_rect(&bbox, fz_intersect_rect(fz_bound_shade(ctx, shade, ctm, &rect), &dev->container[dev->container_len-1].scissor)); if (fz_is_empty_irect(&bbox)) return; pix = fz_new_pixmap_with_bbox(ctx, fz_device_rgb(ctx), &bbox); @@ -847,11 +847,32 @@ svg_dev_pop_clip(fz_device *dev) static void svg_dev_begin_mask(fz_device *dev, const fz_rect *bbox, int luminosity, fz_colorspace *colorspace, float *color) { + svg_device *sdev = (svg_device *)dev->user; + fz_context *ctx = dev->ctx; + fz_output *out; + int mask = sdev->id++; + + out = start_def(sdev); + fz_printf(out, "<mask id=\"ma%d\">", mask); + + if (dev->container_len > 0) + dev->container[dev->container_len-1].user = mask; } static void svg_dev_end_mask(fz_device *dev) { + svg_device *sdev = (svg_device *)dev->user; + fz_context *ctx = dev->ctx; + fz_output *out = sdev->out; + int mask = 0; + + if (dev->container_len > 0) + mask = (int)dev->container[dev->container_len-1].user; + + fz_printf(out, "\"/></mask>\n"); + out = end_def(sdev); + fz_printf(out, "<g mask=\"url(#ma%d)\">\n", mask); } @@ -1050,7 +1071,7 @@ fz_device *fz_new_svg_device(fz_context *ctx, fz_output *out, float page_width, dev->begin_tile = svg_dev_begin_tile; dev->end_tile = svg_dev_end_tile; - dev->hints |= FZ_MAINTAIN_SCISSOR_STACK; + dev->hints |= FZ_MAINTAIN_CONTAINER_STACK; fz_printf(out, "<?xml version=\"1.0\" standalone=\"no\"?>\n"); fz_printf(out, "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n"); |