summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin Watts <robin.watts@artifex.com>2016-05-31 14:53:38 +0100
committerRobin Watts <robin.watts@artifex.com>2016-05-31 15:41:37 +0100
commit3f9d9ffbb30220b9592072a6dde5e4d440ab2e15 (patch)
tree0ea07cb0fddc027ecadbdc688d6eda00f7d86793
parent009937106775864f68a18c061959159a0893e35e (diff)
downloadmupdf-3f9d9ffbb30220b9592072a6dde5e4d440ab2e15.tar.xz
Update test device with passthrough option.
Update the test device so it can be used 'wrapping' another device. In particular, it can be used to wrap the display list device so that we can evaluate 'color or not' while building the display list rather than having to rerun the display list afterwards. Also, give improved control over whether we test every pixel of images/shadings.
-rw-r--r--include/mupdf/fitz/device.h30
-rw-r--r--source/fitz/test-device.c496
-rw-r--r--source/tools/mudraw.c2
3 files changed, 385 insertions, 143 deletions
diff --git a/include/mupdf/fitz/device.h b/include/mupdf/fitz/device.h
index caa01cb2..d0a8f0ed 100644
--- a/include/mupdf/fitz/device.h
+++ b/include/mupdf/fitz/device.h
@@ -296,11 +296,39 @@ fz_device *fz_new_bbox_device(fz_context *ctx, fz_rect *rectp);
Currently only tests for the presence of non-grayscale colors.
+ is_color: Possible values returned:
+ 0: Definitely greyscale
+ 1: Probably color (all colors were grey, but there
+ were images or shadings in a non grey colorspace).
+ 2: Definitely color
+
threshold: The difference from grayscale that will be tolerated.
Typical values to use are either 0 (be exact) and 0.02 (allow an
imperceptible amount of slop).
+
+ options: A set of bitfield options, from the FZ_TEST_OPT set.
+
+ passthrough: A device to pass all calls through to, or NULL.
+ If set, then the test device can both test and pass through to
+ an underlying device (like, say, the display list device). This
+ means that a display list can be created and at the end we'll
+ know if it's color or not.
+
+ In the absence of a passthrough device, the device will throw
+ an exception to stop page interpretation when color is found.
*/
-fz_device *fz_new_test_device(fz_context *ctx, int *is_color, float threshold);
+fz_device *fz_new_test_device(fz_context *ctx, int *is_color, float threshold, int options, fz_device *passthrough);
+
+enum
+{
+ /* If set, test every pixel of images exhaustively.
+ * If clear, just look at colorspaces for images. */
+ FZ_TEST_OPT_IMAGES = 1,
+
+ /* If set, test every pixel of shadings. */
+ /* If clear, just look at colorspaces for shadings. */
+ FZ_TEST_OPT_SHADINGS = 2
+};
/*
fz_new_draw_device: Create a device to draw on a pixmap.
diff --git a/source/fitz/test-device.c b/source/fitz/test-device.c
index 15e6a3ff..1c1aa628 100644
--- a/source/fitz/test-device.c
+++ b/source/fitz/test-device.c
@@ -5,6 +5,9 @@ typedef struct fz_test_device_s
fz_device super;
int *is_color;
float threshold;
+ int options;
+ fz_device *passthrough;
+ int resolved;
} fz_test_device;
static int
@@ -26,19 +29,18 @@ is_rgb_color_u8(int threshold_u8, int r, int g, int b)
}
static void
-fz_test_color(fz_context *ctx, fz_device *dev, fz_colorspace *colorspace, const float *color)
+fz_test_color(fz_context *ctx, fz_test_device *t, fz_colorspace *colorspace, const float *color)
{
- fz_test_device *t = (fz_test_device*)dev;
-
if (!*t->is_color && colorspace && colorspace != fz_device_gray(ctx))
{
if (colorspace == fz_device_rgb(ctx))
{
if (is_rgb_color(t->threshold, color[0], color[1], color[2]))
{
- *t->is_color = 1;
- dev->hints |= FZ_IGNORE_IMAGE;
- fz_throw(ctx, FZ_ERROR_ABORT, "Page found as color; stopping interpretation");
+ *t->is_color = 2;
+ t->resolved = 1;
+ if (t->passthrough == NULL)
+ fz_throw(ctx, FZ_ERROR_ABORT, "Page found as color; stopping interpretation");
}
}
else
@@ -47,49 +49,81 @@ fz_test_color(fz_context *ctx, fz_device *dev, fz_colorspace *colorspace, const
fz_convert_color(ctx, fz_device_rgb(ctx), rgb, colorspace, color);
if (is_rgb_color(t->threshold, rgb[0], rgb[1], rgb[2]))
{
- *t->is_color = 1;
- dev->hints |= FZ_IGNORE_IMAGE;
- fz_throw(ctx, FZ_ERROR_ABORT, "Page found as color; stopping interpretation");
+ *t->is_color = 2;
+ t->resolved = 1;
+ if (t->passthrough == NULL)
+ {
+ t->super.hints |= FZ_IGNORE_IMAGE;
+ fz_throw(ctx, FZ_ERROR_ABORT, "Page found as color; stopping interpretation");
+ }
}
}
}
}
static void
-fz_test_fill_path(fz_context *ctx, fz_device *dev, const fz_path *path, int even_odd, const fz_matrix *ctm,
+fz_test_fill_path(fz_context *ctx, fz_device *dev_, const fz_path *path, int even_odd, const fz_matrix *ctm,
fz_colorspace *colorspace, const float *color, float alpha)
{
- if (alpha != 0.0f)
- fz_test_color(ctx, dev, colorspace, color);
+ fz_test_device *dev = (fz_test_device*)dev_;
+
+ if (dev->resolved == 0)
+ {
+ if (alpha != 0.0f)
+ fz_test_color(ctx, dev, colorspace, color);
+ }
+ if (dev->passthrough)
+ fz_fill_path(ctx, dev->passthrough, path, even_odd, ctm, colorspace, color, alpha);
}
static void
-fz_test_stroke_path(fz_context *ctx, fz_device *dev, const fz_path *path, const fz_stroke_state *stroke,
+fz_test_stroke_path(fz_context *ctx, fz_device *dev_, const fz_path *path, const fz_stroke_state *stroke,
const fz_matrix *ctm, fz_colorspace *colorspace, const float *color, float alpha)
{
- if (alpha != 0.0f)
- fz_test_color(ctx, dev, colorspace, color);
+ fz_test_device *dev = (fz_test_device*)dev_;
+
+ if (dev->resolved == 0)
+ {
+ if (alpha != 0.0f)
+ fz_test_color(ctx, dev, colorspace, color);
+ }
+ if (dev->passthrough)
+ fz_stroke_path(ctx, dev->passthrough, path, stroke, ctm, colorspace, color, alpha);
}
static void
-fz_test_fill_text(fz_context *ctx, fz_device *dev, const fz_text *text, const fz_matrix *ctm,
+fz_test_fill_text(fz_context *ctx, fz_device *dev_, const fz_text *text, const fz_matrix *ctm,
fz_colorspace *colorspace, const float *color, float alpha)
{
- if (alpha != 0.0f)
- fz_test_color(ctx, dev, colorspace, color);
+ fz_test_device *dev = (fz_test_device*)dev_;
+
+ if (dev->resolved == 0)
+ {
+ if (alpha != 0.0f)
+ fz_test_color(ctx, dev, colorspace, color);
+ }
+ if (dev->passthrough)
+ fz_fill_text(ctx, dev->passthrough, text, ctm, colorspace, color, alpha);
}
static void
-fz_test_stroke_text(fz_context *ctx, fz_device *dev, const fz_text *text, const fz_stroke_state *stroke,
+fz_test_stroke_text(fz_context *ctx, fz_device *dev_, const fz_text *text, const fz_stroke_state *stroke,
const fz_matrix *ctm, fz_colorspace *colorspace, const float *color, float alpha)
{
- if (alpha != 0.0f)
- fz_test_color(ctx, dev, colorspace, color);
+ fz_test_device *dev = (fz_test_device*)dev_;
+
+ if (dev->resolved == 0)
+ {
+ if (alpha != 0.0f)
+ fz_test_color(ctx, dev, colorspace, color);
+ }
+ if (dev->passthrough)
+ fz_stroke_text(ctx, dev->passthrough, text, stroke, ctm, colorspace, color, alpha);
}
struct shadearg
{
- fz_device *dev;
+ fz_test_device *dev;
fz_shade *shade;
};
@@ -97,176 +131,336 @@ static void
prepare_vertex(fz_context *ctx, void *arg_, fz_vertex *v, const float *color)
{
struct shadearg *arg = arg_;
- fz_device *dev = arg->dev;
+ fz_test_device *dev = arg->dev;
fz_shade *shade = arg->shade;
if (!shade->use_function)
fz_test_color(ctx, dev, shade->colorspace, color);
}
static void
-fz_test_fill_shade(fz_context *ctx, fz_device *dev, fz_shade *shade, const fz_matrix *ctm, float alpha)
+fz_test_fill_shade(fz_context *ctx, fz_device *dev_, fz_shade *shade, const fz_matrix *ctm, float alpha)
{
- if (shade->use_function)
- {
- int i;
- for (i = 0; i < 256; i++)
- fz_test_color(ctx, dev, shade->colorspace, shade->function[i]);
- }
- else
+ fz_test_device *dev = (fz_test_device*)dev_;
+
+ if (dev->resolved == 0)
{
- struct shadearg arg;
- arg.dev = dev;
- arg.shade = shade;
- fz_process_mesh(ctx, shade, ctm, prepare_vertex, NULL, &arg);
+ if ((dev->options & FZ_TEST_OPT_SHADINGS) == 0)
+ {
+ if (shade->colorspace != fz_device_gray(ctx))
+ {
+ /* Don't test every pixel. Upgrade us from "black and white" to "probably color" */
+ if (*dev->is_color == 0)
+ *dev->is_color = 1;
+ dev->resolved = 1;
+ if (dev->passthrough == NULL)
+ fz_throw(ctx, FZ_ERROR_ABORT, "Page found as color; stopping interpretation");
+ }
+ }
+ else
+ {
+ if (shade->use_function)
+ {
+ int i;
+ for (i = 0; i < 256; i++)
+ fz_test_color(ctx, dev, shade->colorspace, shade->function[i]);
+ }
+ else
+ {
+ struct shadearg arg;
+ arg.dev = dev;
+ arg.shade = shade;
+ fz_process_mesh(ctx, shade, ctm, prepare_vertex, NULL, &arg);
+ }
+ }
}
+ if (dev->passthrough)
+ fz_fill_shade(ctx, dev->passthrough, shade, ctm, alpha);
}
static void
-fz_test_fill_image(fz_context *ctx, fz_device *dev, fz_image *image, const fz_matrix *ctm, float alpha)
+fz_test_fill_image(fz_context *ctx, fz_device *dev_, fz_image *image, const fz_matrix *ctm, float alpha)
{
- fz_test_device *t = (fz_test_device*)dev;
+ fz_test_device *dev = (fz_test_device*)dev_;
- fz_pixmap *pix;
- unsigned int count, i, k, h, sa, ss;
- unsigned char *s;
- fz_compressed_buffer *buffer;
+ while (dev->resolved == 0) /* So we can break out */
+ {
+ fz_pixmap *pix;
+ unsigned int count, i, k, h, sa, ss;
+ unsigned char *s;
+ fz_compressed_buffer *buffer;
- if (*t->is_color || !image->colorspace || image->colorspace == fz_device_gray(ctx))
- return;
+ if (*dev->is_color || !image->colorspace || image->colorspace == fz_device_gray(ctx))
+ break;
- buffer = fz_compressed_image_buffer(ctx, image);
- if (buffer && image->bpc == 8)
- {
- fz_stream *stream = fz_open_compressed_buffer(ctx, buffer);
- count = (unsigned int)image->w * (unsigned int)image->h;
- if (image->colorspace == fz_device_rgb(ctx))
+ if ((dev->options & FZ_TEST_OPT_IMAGES) == 0)
{
- int threshold_u8 = t->threshold * 255;
- for (i = 0; i < count; i++)
+ /* Don't test every pixel. Upgrade us from "black and white" to "probably color" */
+ if (*dev->is_color == 0)
+ *dev->is_color = 1;
+ dev->resolved = 1;
+ if (dev->passthrough == NULL)
+ fz_throw(ctx, FZ_ERROR_ABORT, "Page found as color; stopping interpretation");
+ break;
+ }
+
+ buffer = fz_compressed_image_buffer(ctx, image);
+ if (buffer && image->bpc == 8)
+ {
+ fz_stream *stream = fz_open_compressed_buffer(ctx, buffer);
+ count = (unsigned int)image->w * (unsigned int)image->h;
+ if (image->colorspace == fz_device_rgb(ctx))
{
- int r = fz_read_byte(ctx, stream);
- int g = fz_read_byte(ctx, stream);
- int b = fz_read_byte(ctx, stream);
- if (is_rgb_color_u8(threshold_u8, r, g, b))
+ int threshold_u8 = dev->threshold * 255;
+ for (i = 0; i < count; i++)
{
- *t->is_color = 1;
- dev->hints |= FZ_IGNORE_IMAGE;
- fz_drop_stream(ctx, stream);
- fz_throw(ctx, FZ_ERROR_ABORT, "Page found as color; stopping interpretation");
- break;
+ int r = fz_read_byte(ctx, stream);
+ int g = fz_read_byte(ctx, stream);
+ int b = fz_read_byte(ctx, stream);
+ if (is_rgb_color_u8(threshold_u8, r, g, b))
+ {
+ *dev->is_color = 1;
+ dev->resolved = 1;
+ fz_drop_stream(ctx, stream);
+ if (dev->passthrough == NULL)
+ fz_throw(ctx, FZ_ERROR_ABORT, "Page found as color; stopping interpretation");
+ break;
+ }
}
}
- }
- else
- {
- fz_color_converter cc;
- unsigned int n = (unsigned int)image->n;
-
- fz_init_cached_color_converter(ctx, &cc, fz_device_rgb(ctx), image->colorspace);
- for (i = 0; i < count; i++)
+ else
{
- float cs[FZ_MAX_COLORS];
- float ds[FZ_MAX_COLORS];
+ fz_color_converter cc;
+ unsigned int n = (unsigned int)image->n;
- for (k = 0; k < n; k++)
- cs[k] = fz_read_byte(ctx, stream) / 255.0f;
-
- cc.convert(ctx, &cc, ds, cs);
-
- if (is_rgb_color(t->threshold, ds[0], ds[1], ds[2]))
+ fz_init_cached_color_converter(ctx, &cc, fz_device_rgb(ctx), image->colorspace);
+ for (i = 0; i < count; i++)
{
- *t->is_color = 1;
- dev->hints |= FZ_IGNORE_IMAGE;
- fz_drop_stream(ctx, stream);
- fz_fin_cached_color_converter(ctx, &cc);
- fz_throw(ctx, FZ_ERROR_ABORT, "Page found as color; stopping interpretation");
- break;
+ float cs[FZ_MAX_COLORS];
+ float ds[FZ_MAX_COLORS];
+
+ for (k = 0; k < n; k++)
+ cs[k] = fz_read_byte(ctx, stream) / 255.0f;
+
+ cc.convert(ctx, &cc, ds, cs);
+
+ if (is_rgb_color(dev->threshold, ds[0], ds[1], ds[2]))
+ {
+ *dev->is_color = 1;
+ dev->resolved = 1;
+ if (dev->passthrough == NULL)
+ {
+ fz_drop_stream(ctx, stream);
+ fz_fin_cached_color_converter(ctx, &cc);
+ fz_throw(ctx, FZ_ERROR_ABORT, "Page found as color; stopping interpretation");
+ }
+ break;
+ }
}
+ fz_fin_cached_color_converter(ctx, &cc);
}
- fz_fin_cached_color_converter(ctx, &cc);
+ fz_drop_stream(ctx, stream);
+ break;
}
- fz_drop_stream(ctx, stream);
- return;
- }
- pix = fz_get_pixmap_from_image(ctx, image, NULL, NULL, 0, 0);
- if (pix == NULL) /* Should never happen really, but... */
- return;
+ pix = fz_get_pixmap_from_image(ctx, image, NULL, NULL, 0, 0);
+ if (pix == NULL) /* Should never happen really, but... */
+ break;
- count = pix->w;
- h = pix->h;
- s = pix->samples;
- sa = pix->alpha;
- ss = pix->stride - pix->w * pix->n;
+ count = pix->w;
+ h = pix->h;
+ s = pix->samples;
+ sa = pix->alpha;
+ ss = pix->stride - pix->w * pix->n;
- if (pix->colorspace == fz_device_rgb(ctx))
- {
- int threshold_u8 = t->threshold * 255;
- while (h--)
+ if (pix->colorspace == fz_device_rgb(ctx))
{
- for (i = 0; i < count; i++)
+ int threshold_u8 = dev->threshold * 255;
+ while (h--)
{
- if ((!sa || s[3] != 0) && is_rgb_color_u8(threshold_u8, s[0], s[1], s[2]))
+ for (i = 0; i < count; i++)
{
- *t->is_color = 1;
- dev->hints |= FZ_IGNORE_IMAGE;
- fz_drop_pixmap(ctx, pix);
- fz_throw(ctx, FZ_ERROR_ABORT, "Page found as color; stopping interpretation");
- break;
+ if ((!sa || s[3] != 0) && is_rgb_color_u8(threshold_u8, s[0], s[1], s[2]))
+ {
+ *dev->is_color = 1;
+ dev->resolved = 1;
+ if (dev->passthrough == NULL)
+ {
+ fz_drop_pixmap(ctx, pix);
+ fz_throw(ctx, FZ_ERROR_ABORT, "Page found as color; stopping interpretation");
+ }
+ break;
+ }
+ s += 3 + sa;
}
- s += 3 + sa;
+ s += ss;
}
- s += ss;
}
- }
- else
- {
- fz_color_converter cc;
- unsigned int n = (unsigned int)pix->n-1;
-
- fz_init_cached_color_converter(ctx, &cc, fz_device_rgb(ctx), pix->colorspace);
- while (h--)
+ else
{
- for (i = 0; i < count; i++)
- {
- float cs[FZ_MAX_COLORS];
- float ds[FZ_MAX_COLORS];
-
- for (k = 0; k < n; k++)
- cs[k] = (*s++) / 255.0f;
- if (sa && *s++ == 0)
- continue;
-
- cc.convert(ctx, &cc, ds, cs);
+ fz_color_converter cc;
+ unsigned int n = (unsigned int)pix->n-1;
- if (is_rgb_color(t->threshold, ds[0], ds[1], ds[2]))
+ fz_init_cached_color_converter(ctx, &cc, fz_device_rgb(ctx), pix->colorspace);
+ while (h--)
+ {
+ for (i = 0; i < count; i++)
{
- *t->is_color = 1;
- dev->hints |= FZ_IGNORE_IMAGE;
- fz_fin_cached_color_converter(ctx, &cc);
- fz_drop_pixmap(ctx, pix);
- fz_throw(ctx, FZ_ERROR_ABORT, "Page found as color; stopping interpretation");
- break;
+ float cs[FZ_MAX_COLORS];
+ float ds[FZ_MAX_COLORS];
+
+ for (k = 0; k < n; k++)
+ cs[k] = (*s++) / 255.0f;
+ if (sa && *s++ == 0)
+ continue;
+
+ cc.convert(ctx, &cc, ds, cs);
+
+ if (is_rgb_color(dev->threshold, ds[0], ds[1], ds[2]))
+ {
+ *dev->is_color = 1;
+ dev->resolved = 1;
+ if (dev->passthrough == NULL)
+ {
+ fz_fin_cached_color_converter(ctx, &cc);
+ fz_drop_pixmap(ctx, pix);
+ fz_throw(ctx, FZ_ERROR_ABORT, "Page found as color; stopping interpretation");
+ }
+ break;
+ }
}
+ s += ss;
}
- s += ss;
+ fz_fin_cached_color_converter(ctx, &cc);
}
- fz_fin_cached_color_converter(ctx, &cc);
- }
- fz_drop_pixmap(ctx, pix);
+ fz_drop_pixmap(ctx, pix);
+ break;
+ }
+ if (dev->passthrough)
+ fz_fill_image(ctx, dev->passthrough, image, ctm, alpha);
}
static void
-fz_test_fill_image_mask(fz_context *ctx, fz_device *dev, fz_image *image, const fz_matrix *ctm,
+fz_test_fill_image_mask(fz_context *ctx, fz_device *dev_, fz_image *image, const fz_matrix *ctm,
fz_colorspace *colorspace, const float *color, float alpha)
{
- /* We assume that at least some of the image pixels are non-zero */
- fz_test_color(ctx, dev, colorspace, color);
+ fz_test_device *dev = (fz_test_device*)dev_;
+
+ if (dev->resolved == 0)
+ {
+ /* We assume that at least some of the image pixels are non-zero */
+ fz_test_color(ctx, dev, colorspace, color);
+ }
+ if (dev->passthrough)
+ fz_fill_image_mask(ctx, dev->passthrough, image, ctm, colorspace, color, alpha);
+}
+
+static void
+fz_test_clip_path(fz_context *ctx, fz_device *dev_, const fz_path *path, int even_odd, const fz_matrix *ctm, const fz_rect *scissor)
+{
+ fz_test_device *dev = (fz_test_device*)dev_;
+
+ fz_clip_path(ctx, dev->passthrough, path, even_odd, ctm, scissor);
+}
+
+static void
+fz_test_clip_stroke_path(fz_context *ctx, fz_device *dev_, const fz_path *path, const fz_stroke_state *stroke, const fz_matrix *ctm, const fz_rect *scissor)
+{
+ fz_test_device *dev = (fz_test_device*)dev_;
+
+ fz_clip_stroke_path(ctx, dev->passthrough, path, stroke, ctm, scissor);
+}
+
+static void
+fz_test_clip_text(fz_context *ctx, fz_device *dev_, const fz_text *text, const fz_matrix *ctm, const fz_rect *scissor)
+{
+ fz_test_device *dev = (fz_test_device*)dev_;
+
+ fz_clip_text(ctx, dev->passthrough, text, ctm, scissor);
+}
+
+static void
+fz_test_clip_stroke_text(fz_context *ctx, fz_device *dev_, const fz_text *text, const fz_stroke_state *stroke, const fz_matrix *ctm, const fz_rect *scissor)
+{
+ fz_test_device *dev = (fz_test_device*)dev_;
+
+ fz_clip_stroke_text(ctx, dev->passthrough, text, stroke, ctm, scissor);
+}
+
+static void
+fz_test_ignore_text(fz_context *ctx, fz_device *dev_, const fz_text *text, const fz_matrix *ctm)
+{
+ fz_test_device *dev = (fz_test_device*)dev_;
+
+ fz_ignore_text(ctx, dev->passthrough, text, ctm);
+}
+
+static void
+fz_test_clip_image_mask(fz_context *ctx, fz_device *dev_, fz_image *img, const fz_matrix *ctm, const fz_rect *scissor)
+{
+ fz_test_device *dev = (fz_test_device*)dev_;
+
+ fz_clip_image_mask(ctx, dev->passthrough, img, ctm, scissor);
+}
+
+static void
+fz_test_pop_clip(fz_context *ctx, fz_device *dev_)
+{
+ fz_test_device *dev = (fz_test_device*)dev_;
+
+ fz_pop_clip(ctx, dev->passthrough);
+}
+
+static void
+fz_test_begin_mask(fz_context *ctx, fz_device *dev_, const fz_rect *rect, int luminosity, fz_colorspace *cs, const float *bc)
+{
+ fz_test_device *dev = (fz_test_device*)dev_;
+
+ fz_begin_mask(ctx, dev->passthrough, rect, luminosity, cs, bc);
+}
+
+static void
+fz_test_end_mask(fz_context *ctx, fz_device *dev_)
+{
+ fz_test_device *dev = (fz_test_device*)dev_;
+
+ fz_end_mask(ctx, dev->passthrough);
+}
+
+static void
+fz_test_begin_group(fz_context *ctx, fz_device *dev_, const fz_rect *rect, int isolated, int knockout, int blendmode, float alpha)
+{
+ fz_test_device *dev = (fz_test_device*)dev_;
+
+ fz_begin_group(ctx, dev->passthrough, rect, isolated, knockout, blendmode, alpha);
+}
+
+static void
+fz_test_end_group(fz_context *ctx, fz_device *dev_)
+{
+ fz_test_device *dev = (fz_test_device*)dev_;
+
+ fz_end_group(ctx, dev->passthrough);
+}
+
+static int
+fz_test_begin_tile(fz_context *ctx, fz_device *dev_, const fz_rect *area, const fz_rect *view, float xstep, float ystep, const fz_matrix *ctm, int id)
+{
+ fz_test_device *dev = (fz_test_device*)dev_;
+
+ return fz_begin_tile_id(ctx, dev->passthrough, area, view, xstep, ystep, ctm, id);
+}
+
+static void
+fz_test_end_tile(fz_context *ctx, fz_device *dev_)
+{
+ fz_test_device *dev = (fz_test_device*)dev_;
+
+ fz_end_tile(ctx, dev->passthrough);
}
fz_device *
-fz_new_test_device(fz_context *ctx, int *is_color, float threshold)
+fz_new_test_device(fz_context *ctx, int *is_color, float threshold, int options, fz_device *passthrough)
{
fz_test_device *dev = fz_new_device(ctx, sizeof *dev);
@@ -278,8 +472,28 @@ fz_new_test_device(fz_context *ctx, int *is_color, float threshold)
dev->super.fill_image = fz_test_fill_image;
dev->super.fill_image_mask = fz_test_fill_image_mask;
+ if (passthrough)
+ {
+ dev->super.clip_path = fz_test_clip_path;
+ dev->super.clip_stroke_path = fz_test_clip_stroke_path;
+ dev->super.clip_text = fz_test_clip_text;
+ dev->super.clip_stroke_text = fz_test_clip_stroke_text;
+ dev->super.ignore_text = fz_test_ignore_text;
+ dev->super.clip_image_mask = fz_test_clip_image_mask;
+ dev->super.pop_clip = fz_test_pop_clip;
+ dev->super.begin_mask = fz_test_begin_mask;
+ dev->super.end_mask = fz_test_end_mask;
+ dev->super.begin_group = fz_test_begin_group;
+ dev->super.end_group = fz_test_end_group;
+ dev->super.begin_tile = fz_test_begin_tile;
+ dev->super.end_tile = fz_test_end_tile;
+ }
+
dev->is_color = is_color;
+ dev->options = options;
dev->threshold = threshold;
+ dev->passthrough = passthrough;
+ dev->resolved = 0;
*dev->is_color = 0;
diff --git a/source/tools/mudraw.c b/source/tools/mudraw.c
index 85553ea8..12d5247a 100644
--- a/source/tools/mudraw.c
+++ b/source/tools/mudraw.c
@@ -1147,7 +1147,7 @@ static void drawpage(fz_context *ctx, fz_document *doc, int pagenum)
if (showfeatures)
{
int iscolor;
- dev = fz_new_test_device(ctx, &iscolor, 0.02f);
+ dev = fz_new_test_device(ctx, &iscolor, 0.02f, 0, NULL);
if (lowmemory)
fz_enable_device_hints(ctx, dev, FZ_NO_CACHE);
fz_try(ctx)