summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTor Andersson <tor.andersson@artifex.com>2017-08-01 17:10:02 +0200
committerTor Andersson <tor.andersson@artifex.com>2017-08-09 14:02:19 +0200
commit09d3d93b4e3d8951bf958f2404ee27b5a0769cb9 (patch)
tree668941dbbcb6b9e5a1525aa9f4a08b08a16cea39
parent72e05eaace2fdb3b118b57f6d331054127c46fc5 (diff)
downloadmupdf-09d3d93b4e3d8951bf958f2404ee27b5a0769cb9.tar.xz
Render shadings to images in stext-device.
-rw-r--r--include/mupdf/fitz/device.h5
-rw-r--r--include/mupdf/fitz/pixmap.h5
-rw-r--r--source/fitz/device.c8
-rw-r--r--source/fitz/pixmap.c31
-rw-r--r--source/fitz/stext-device.c53
5 files changed, 102 insertions, 0 deletions
diff --git a/include/mupdf/fitz/device.h b/include/mupdf/fitz/device.h
index afbd8563..0198a3e6 100644
--- a/include/mupdf/fitz/device.h
+++ b/include/mupdf/fitz/device.h
@@ -181,6 +181,11 @@ void fz_enable_device_hints(fz_context *ctx, fz_device *dev, int hints);
*/
void fz_disable_device_hints(fz_context *ctx, fz_device *dev, int hints);
+/*
+ Find current scissor region as tracked by the device.
+*/
+const fz_rect *fz_device_current_scissor(fz_context *ctx, fz_device *dev);
+
enum
{
/* Hints */
diff --git a/include/mupdf/fitz/pixmap.h b/include/mupdf/fitz/pixmap.h
index 16217578..533ff735 100644
--- a/include/mupdf/fitz/pixmap.h
+++ b/include/mupdf/fitz/pixmap.h
@@ -219,6 +219,11 @@ void fz_set_pixmap_resolution(fz_context *ctx, fz_pixmap *pix, int xres, int yre
void fz_clear_pixmap_with_value(fz_context *ctx, fz_pixmap *pix, int value);
/*
+ Fill pixmap with solid color.
+*/
+void fz_fill_pixmap_with_color(fz_context *ctx, fz_pixmap *pix, fz_colorspace *colorspace, float *color, const fz_color_params *color_params);
+
+/*
fz_clear_pixmap_with_value: Clears a subrect of a pixmap with the given value.
pix: The pixmap to clear.
diff --git a/source/fitz/device.c b/source/fitz/device.c
index 0f658d31..5d2b7d7e 100644
--- a/source/fitz/device.c
+++ b/source/fitz/device.c
@@ -520,3 +520,11 @@ fz_set_default_colorspaces(fz_context *ctx, fz_device *dev, fz_default_colorspac
if (dev->set_default_colorspaces)
dev->set_default_colorspaces(ctx, dev, default_cs);
}
+
+const fz_rect *
+fz_device_current_scissor(fz_context *ctx, fz_device *dev)
+{
+ if (dev->container_len > 0)
+ return &dev->container[dev->container_len-1].scissor;
+ return &fz_infinite_rect;
+}
diff --git a/source/fitz/pixmap.c b/source/fitz/pixmap.c
index 1c4ea52b..bef5b6a5 100644
--- a/source/fitz/pixmap.c
+++ b/source/fitz/pixmap.c
@@ -526,6 +526,37 @@ fz_clear_pixmap_with_value(fz_context *ctx, fz_pixmap *pix, int value)
}
void
+fz_fill_pixmap_with_color(fz_context *ctx, fz_pixmap *pix, fz_colorspace *colorspace, float *color, const fz_color_params *color_params)
+{
+ float colorfv[FZ_MAX_COLORS];
+ unsigned char colorbv[FZ_MAX_COLORS];
+ int i, n, a, s, x, y, w, h;
+
+ n = fz_colorspace_n(ctx, pix->colorspace);
+ a = pix->alpha;
+ s = pix->s;
+ fz_convert_color(ctx, color_params, NULL, pix->colorspace, colorfv, colorspace, color);
+ for (i = 0; i < n; ++i)
+ colorbv[i] = colorfv[i] * 255;
+
+ w = pix->w;
+ h = pix->h;
+ for (y = 0; y < h; ++y)
+ {
+ unsigned char *p = pix->samples + y * pix->stride;
+ for (x = 0; x < w; ++x)
+ {
+ for (i = 0; i < n; ++i)
+ *p++ = colorbv[i];
+ for (i = 0; i < s; ++i)
+ *p++ = 0;
+ if (a)
+ *p++ = 255;
+ }
+ }
+}
+
+void
fz_copy_pixmap_rect(fz_context *ctx, fz_pixmap *dest, fz_pixmap *src, const fz_irect *b, const fz_default_colorspaces *default_cs)
{
unsigned char *srcp;
diff --git a/source/fitz/stext-device.c b/source/fitz/stext-device.c
index f942babe..73fa309e 100644
--- a/source/fitz/stext-device.c
+++ b/source/fitz/stext-device.c
@@ -974,6 +974,57 @@ fz_stext_fill_image(fz_context *ctx, fz_device *dev, fz_image *img, const fz_mat
fz_stext_fill_image_mask(ctx, dev, img, ctm, NULL, NULL, alpha, color_params);
}
+static fz_image *
+fz_new_image_from_shade(fz_context *ctx, fz_shade *shade, fz_matrix *in_out_ctm, const fz_color_params *color_params, const fz_rect *scissor)
+{
+ fz_matrix ctm = *in_out_ctm;
+ fz_pixmap *pix;
+ fz_image *img;
+ fz_rect bounds;
+ fz_irect bbox;
+
+ fz_bound_shade(ctx, shade, &ctm, &bounds);
+ fz_intersect_rect(&bounds, scissor);
+ fz_irect_from_rect(&bbox, &bounds);
+
+ pix = fz_new_pixmap_with_bbox(ctx, fz_device_rgb(ctx), &bbox, NULL, !shade->use_background);
+ fz_try(ctx)
+ {
+ if (shade->use_background)
+ fz_fill_pixmap_with_color(ctx, pix, shade->colorspace, shade->background, color_params);
+ else
+ fz_clear_pixmap(ctx, pix);
+ fz_paint_shade(ctx, shade, &ctm, pix, NULL, color_params, &bbox);
+ img = fz_new_image_from_pixmap(ctx, pix, NULL);
+ }
+ fz_always(ctx)
+ fz_drop_pixmap(ctx, pix);
+ fz_catch(ctx)
+ fz_rethrow(ctx);
+
+ in_out_ctm->a = pix->w;
+ in_out_ctm->b = 0;
+ in_out_ctm->c = 0;
+ in_out_ctm->d = pix->h;
+ in_out_ctm->e = pix->x;
+ in_out_ctm->f = pix->y;
+ return img;
+}
+
+static void
+fz_stext_fill_shade(fz_context *ctx, fz_device *dev, fz_shade *shade, const fz_matrix *ctm, float alpha, const fz_color_params *color_params)
+{
+ fz_matrix local_ctm = *ctm;
+ const fz_rect *scissor = fz_device_current_scissor(ctx, dev);
+ fz_image *image = fz_new_image_from_shade(ctx, shade, &local_ctm, color_params, scissor);
+ fz_try(ctx)
+ fz_stext_fill_image(ctx, dev, image, &local_ctm, alpha, color_params);
+ fz_always(ctx)
+ fz_drop_image(ctx, image);
+ fz_catch(ctx)
+ fz_rethrow(ctx);
+}
+
static int
direction_from_bidi_class(int bidiclass, int curdir)
{
@@ -1117,6 +1168,8 @@ fz_new_stext_device(fz_context *ctx, fz_stext_sheet *sheet, fz_stext_page *page,
if (opts && (opts->flags & FZ_STEXT_PRESERVE_IMAGES))
{
+ dev->super.hints |= FZ_MAINTAIN_CONTAINER_STACK;
+ dev->super.fill_shade = fz_stext_fill_shade;
dev->super.fill_image = fz_stext_fill_image;
dev->super.fill_image_mask = fz_stext_fill_image_mask;
}