diff options
author | Tor Andersson <tor.andersson@artifex.com> | 2017-08-01 17:10:02 +0200 |
---|---|---|
committer | Tor Andersson <tor.andersson@artifex.com> | 2017-08-09 14:02:19 +0200 |
commit | 09d3d93b4e3d8951bf958f2404ee27b5a0769cb9 (patch) | |
tree | 668941dbbcb6b9e5a1525aa9f4a08b08a16cea39 | |
parent | 72e05eaace2fdb3b118b57f6d331054127c46fc5 (diff) | |
download | mupdf-09d3d93b4e3d8951bf958f2404ee27b5a0769cb9.tar.xz |
Render shadings to images in stext-device.
-rw-r--r-- | include/mupdf/fitz/device.h | 5 | ||||
-rw-r--r-- | include/mupdf/fitz/pixmap.h | 5 | ||||
-rw-r--r-- | source/fitz/device.c | 8 | ||||
-rw-r--r-- | source/fitz/pixmap.c | 31 | ||||
-rw-r--r-- | source/fitz/stext-device.c | 53 |
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; } |