summaryrefslogtreecommitdiff
path: root/source/fitz/device.c
diff options
context:
space:
mode:
authorRobin Watts <robin.watts@artifex.com>2013-10-10 10:28:13 +0100
committerRobin Watts <robin.watts@artifex.com>2013-10-10 11:16:58 +0100
commit6bf8f97d9be871c026eccf25c71f79aaffee2a53 (patch)
treee866535bbca63ed78a8bbca7156ad6fd8c693321 /source/fitz/device.c
parentf7098ecf6d5fccf6b3283d497e3c9b1f14470e1e (diff)
downloadmupdf-6bf8f97d9be871c026eccf25c71f79aaffee2a53.tar.xz
Add scissor stack functionality to null device.
If the appropriate device hint is set, the null device will keep a scissor stack. This saves duplicating code in every device.
Diffstat (limited to 'source/fitz/device.c')
-rw-r--r--source/fitz/device.c99
1 files changed, 99 insertions, 0 deletions
diff --git a/source/fitz/device.c b/source/fitz/device.c
index 175b00db..ed30e114 100644
--- a/source/fitz/device.c
+++ b/source/fitz/device.c
@@ -19,6 +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);
}
@@ -48,6 +49,60 @@ fz_end_page(fz_device *dev)
dev->end_page(dev);
}
+static void
+push_clip_stack(fz_device *dev, const fz_rect *rect)
+{
+ if (dev->scissor_len == dev->scissor_cap)
+ {
+ int newmax = dev->scissor_cap * 2;
+ if (newmax == 0)
+ newmax = 4;
+ dev->scissor = fz_resize_array(dev->ctx, dev->scissor, newmax, sizeof(*dev->scissor));
+ dev->scissor_cap = newmax;
+ }
+ if (dev->scissor_len == 0)
+ dev->scissor[0] = *rect;
+ else
+ {
+ dev->scissor[dev->scissor_len+1] = dev->scissor[dev->scissor_len];
+ fz_intersect_rect(&dev->scissor[dev->scissor_len], rect);
+ }
+ dev->scissor_len++;
+}
+
+static void
+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)
+ {
+ int newmax = dev->scissor_cap * 2;
+ if (newmax == 0)
+ newmax = 4;
+ dev->scissor = fz_resize_array(dev->ctx, dev->scissor, newmax, sizeof(*dev->scissor));
+ dev->scissor_cap = newmax;
+ }
+ fz_intersect_rect(&dev->scissor[dev->scissor_len], rect);
+ dev->scissor_len++;
+ }
+ else
+ {
+ if (dev->scissor_len <= 0)
+ return;
+ fz_union_rect(&dev->scissor_accumulator, rect);
+ fz_intersect_rect(&dev->scissor[dev->scissor_len-1], &dev->scissor_accumulator);
+ }
+}
+
+static void
+pop_clip_stack(fz_device *dev)
+{
+ if (dev->scissor_len > 0)
+ dev->scissor_len--;
+}
+
void
fz_fill_path(fz_device *dev, fz_path *path, int even_odd, const fz_matrix *ctm,
fz_colorspace *colorspace, float *color, float alpha)
@@ -81,6 +136,17 @@ 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 (rect == NULL)
+ {
+ fz_rect bbox;
+ fz_bound_path(ctx, path, NULL, ctm, &bbox);
+ push_clip_stack(dev, &bbox);
+ }
+ else
+ push_clip_stack(dev, rect);
+ }
if (dev->clip_path)
dev->clip_path(dev, path, rect, even_odd, ctm);
}
@@ -105,6 +171,17 @@ 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 (rect == NULL)
+ {
+ fz_rect bbox;
+ fz_bound_path(ctx, path, stroke, ctm, &bbox);
+ push_clip_stack(dev, &bbox);
+ }
+ else
+ push_clip_stack(dev, rect);
+ }
if (dev->clip_stroke_path)
dev->clip_stroke_path(dev, path, rect, stroke, ctm);
}
@@ -150,6 +227,12 @@ 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)
+ {
+ fz_rect bbox;
+ fz_bound_text(ctx, text, NULL, ctm, &bbox);
+ push_clip_stack_accumulate(dev, &bbox, accumulate);
+ }
if (dev->clip_text)
dev->clip_text(dev, text, ctm, accumulate);
}
@@ -176,6 +259,12 @@ 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)
+ {
+ fz_rect bbox;
+ fz_bound_text(ctx, text, stroke, ctm, &bbox);
+ push_clip_stack_accumulate(dev, &bbox, 0);
+ }
if (dev->clip_stroke_text)
dev->clip_stroke_text(dev, text, stroke, ctm);
}
@@ -206,6 +295,8 @@ fz_pop_clip(fz_device *dev)
fz_throw(dev->ctx, FZ_ERROR_GENERIC, "%s", dev->errmess);
return;
}
+ if (dev->hints & FZ_MAINTAIN_SCISSOR_STACK)
+ pop_clip_stack(dev);
if (dev->pop_clip)
dev->pop_clip(dev);
}
@@ -251,6 +342,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->clip_image_mask)
dev->clip_image_mask(dev, image, rect, ctm);
}
@@ -275,6 +368,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->begin_mask)
dev->begin_mask(dev, area, luminosity, colorspace, bc);
}
@@ -311,6 +406,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->begin_group)
dev->begin_group(dev, area, isolated, knockout, blendmode, alpha);
}
@@ -334,6 +431,8 @@ fz_end_group(fz_device *dev)
}
if (dev->end_group)
dev->end_group(dev);
+ if (dev->hints & FZ_MAINTAIN_SCISSOR_STACK)
+ pop_clip_stack(dev);
}
void