summaryrefslogtreecommitdiff
path: root/source/fitz
diff options
context:
space:
mode:
authorRobin Watts <robin.watts@artifex.com>2013-10-11 18:36:26 +0100
committerRobin Watts <robin.watts@artifex.com>2013-10-11 18:39:08 +0100
commita0712d442fa13c6fd775239b2a661c93fc99ed54 (patch)
treef9742349a3c7f150bf27122b5dce67539c5d66a0 /source/fitz
parent79faa2b83d2295a53645e1f5330edfc33be61305 (diff)
downloadmupdf-a0712d442fa13c6fd775239b2a661c93fc99ed54.tar.xz
SVG: Add simple smask support.
The luminosity flag and background color are currently ignored. The clip stack optionally held in the null device is updated here to be a container stack, together with a flags word (currently just used to indicate the type of the container at the current place in the stack), and a user value (used by the SVG device to stash the id for the mask it's generating).
Diffstat (limited to 'source/fitz')
-rw-r--r--source/fitz/device.c85
-rw-r--r--source/fitz/svg-device.c27
2 files changed, 71 insertions, 41 deletions
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");