summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/mupdf/fitz/pixmap.h18
-rw-r--r--source/fitz/draw-device.c80
-rw-r--r--source/fitz/pixmap.c35
3 files changed, 94 insertions, 39 deletions
diff --git a/include/mupdf/fitz/pixmap.h b/include/mupdf/fitz/pixmap.h
index a7bb4354..fcf9d8b3 100644
--- a/include/mupdf/fitz/pixmap.h
+++ b/include/mupdf/fitz/pixmap.h
@@ -136,6 +136,19 @@ fz_pixmap *fz_new_pixmap_with_data(fz_context *ctx, fz_colorspace *colorspace, i
fz_pixmap *fz_new_pixmap_with_bbox_and_data(fz_context *ctx, fz_colorspace *colorspace, const fz_irect *rect, fz_separations *seps, int alpha, unsigned char *samples);
/*
+ fz_new_pixmap_from_pixmap: Create a new pixmap that represents
+ a subarea of the specified pixmap. A reference is taken to his
+ pixmap that will be dropped on destruction.
+
+ The supplied rectangle must be wholly contained within the original
+ pixmap.
+
+ Returns a pointer to the new pixmap. Throws exception on failure to
+ allocate.
+*/
+fz_pixmap *fz_new_pixmap_from_pixmap(fz_context *ctx, fz_pixmap *pixmap, const fz_irect *rect);
+
+/*
fz_keep_pixmap: Take a reference to a pixmap.
pix: The pixmap to increment the reference for.
@@ -319,8 +332,6 @@ fz_pixmap *fz_convert_pixmap(fz_context *ctx, fz_pixmap *pix, fz_colorspace *cs_
Bit 0: If set, draw the image with linear interpolation.
Bit 1: If set, free the samples buffer when the pixmap
is destroyed.
- Bit 2: If set, all separations are enabled (ignore the
- fields in the seps structure).
stride: The byte offset from the data for any given pixel
to the data for the same pixel on the row below.
@@ -351,12 +362,13 @@ struct fz_pixmap_s
int xres, yres;
fz_colorspace *colorspace;
unsigned char *samples;
+ fz_pixmap *underlying;
};
enum
{
FZ_PIXMAP_FLAG_INTERPOLATE = 1,
- FZ_PIXMAP_FLAG_FREE_SAMPLES = 2,
+ FZ_PIXMAP_FLAG_FREE_SAMPLES = 2
};
void fz_drop_pixmap_imp(fz_context *ctx, fz_storable *pix);
diff --git a/source/fitz/draw-device.c b/source/fitz/draw-device.c
index 03351940..8686c7dd 100644
--- a/source/fitz/draw-device.c
+++ b/source/fitz/draw-device.c
@@ -2692,6 +2692,9 @@ fz_draw_end_tile(fz_context *ctx, fz_device *devp)
fz_rect scissor_tmp, tile_tmp;
int x0, y0, x1, y1, x, y, extra_x, extra_y;
fz_draw_state *state;
+ fz_pixmap *dest = NULL;
+ fz_pixmap *shape = NULL;
+ fz_pixmap *group_alpha = NULL;
if (dev->top == 0)
{
@@ -2764,52 +2767,57 @@ fz_draw_end_tile(fz_context *ctx, fz_device *devp)
if (state[0].group_alpha)
fz_dump_blend(ctx, "/GA=", state[0].group_alpha);
#endif
+ dest = fz_new_pixmap_from_pixmap(ctx, state[1].dest, NULL);
+
+ fz_var(shape);
+ fz_var(group_alpha);
- for (y = y0; y < y1; y++)
+ fz_try(ctx)
{
- for (x = x0; x < x1; x++)
+ shape = fz_new_pixmap_from_pixmap(ctx, state[1].shape, NULL);
+ group_alpha = fz_new_pixmap_from_pixmap(ctx, state[1].group_alpha, NULL);
+
+ for (y = y0; y < y1; y++)
{
- ttm = ctm;
- fz_pre_translate(&ttm, x * xstep, y * ystep);
- state[1].dest->x = ttm.e;
- state[1].dest->y = ttm.f;
- /* Check for overflow due to float -> int conversions */
- if (state[1].dest->x > 0 && state[1].dest->x + state[1].dest->w < 0)
- continue;
- if (state[1].dest->y > 0 && state[1].dest->y + state[1].dest->h < 0)
- continue;
- fz_paint_pixmap_with_bbox(state[0].dest, state[1].dest, 255, state[0].scissor);
- if (state[1].shape)
+ for (x = x0; x < x1; x++)
{
- ttm = shapectm;
+ ttm = ctm;
fz_pre_translate(&ttm, x * xstep, y * ystep);
- state[1].shape->x = ttm.e;
- state[1].shape->y = ttm.f;
- fz_paint_pixmap_with_bbox(state[0].shape, state[1].shape, 255, state[0].scissor);
- }
- if (state[1].group_alpha)
- {
- ttm = gactm;
- fz_pre_translate(&ttm, x * xstep, y * ystep);
- state[1].group_alpha->x = ttm.e;
- state[1].group_alpha->y = ttm.f;
- fz_paint_pixmap_with_bbox(state[0].group_alpha, state[1].group_alpha, 255, state[0].scissor);
+ dest->x = ttm.e;
+ dest->y = ttm.f;
+ /* Check for overflow due to float -> int conversions */
+ if (dest->x > 0 && dest->x + dest->w < 0)
+ continue;
+ if (dest->y > 0 && dest->y + dest->h < 0)
+ continue;
+ fz_paint_pixmap_with_bbox(state[0].dest, dest, 255, state[0].scissor);
+ if (shape)
+ {
+ ttm = shapectm;
+ fz_pre_translate(&ttm, x * xstep, y * ystep);
+ shape->x = ttm.e;
+ shape->y = ttm.f;
+ fz_paint_pixmap_with_bbox(state[0].shape, shape, 255, state[0].scissor);
+ }
+ if (group_alpha)
+ {
+ ttm = gactm;
+ fz_pre_translate(&ttm, x * xstep, y * ystep);
+ group_alpha->x = ttm.e;
+ group_alpha->y = ttm.f;
+ fz_paint_pixmap_with_bbox(state[0].group_alpha, group_alpha, 255, state[0].scissor);
+ }
}
}
}
-
- state[1].dest->x = ctm.e;
- state[1].dest->y = ctm.f;
- if (state[1].shape)
- {
- state[1].shape->x = shapectm.e;
- state[1].shape->y = shapectm.f;
- }
- if (state[1].group_alpha)
+ fz_always(ctx)
{
- state[1].group_alpha->x = gactm.e;
- state[1].group_alpha->y = gactm.f;
+ fz_drop_pixmap(ctx, dest);
+ fz_drop_pixmap(ctx, shape);
+ fz_drop_pixmap(ctx, group_alpha);
}
+ fz_catch(ctx)
+ fz_rethrow(ctx);
/* Now we try to cache the tiles. Any failure here will just result in us not caching. */
if (state[1].encache && state[1].id != 0)
diff --git a/source/fitz/pixmap.c b/source/fitz/pixmap.c
index 4e3f62cb..93f8fed6 100644
--- a/source/fitz/pixmap.c
+++ b/source/fitz/pixmap.c
@@ -26,6 +26,7 @@ fz_drop_pixmap_imp(fz_context *ctx, fz_storable *pix_)
fz_drop_separations(ctx, pix->seps);
if (pix->flags & FZ_PIXMAP_FLAG_FREE_SAMPLES)
fz_free(ctx, pix->samples);
+ fz_drop_pixmap(ctx, pix->underlying);
fz_free(ctx, pix);
}
@@ -126,6 +127,40 @@ fz_new_pixmap_with_bbox_and_data(fz_context *ctx, fz_colorspace *colorspace, con
return pixmap;
}
+fz_pixmap *fz_new_pixmap_from_pixmap(fz_context *ctx, fz_pixmap *pixmap, const fz_irect *rect)
+{
+ fz_irect local_rect;
+ fz_pixmap *subpix;
+
+ if (!pixmap)
+ return NULL;
+
+ if (rect == NULL)
+ {
+ rect = &local_rect;
+ local_rect.x0 = pixmap->x;
+ local_rect.y0 = pixmap->y;
+ local_rect.x1 = pixmap->x + pixmap->w;
+ local_rect.y1 = pixmap->y + pixmap->h;
+ }
+ else if (rect->x0 < pixmap->x || rect->y0 < pixmap->y || rect->x1 > pixmap->x + pixmap->w || rect->y1 > pixmap->y + pixmap->h)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "Pixmap region is not a subarea");
+
+ subpix = fz_malloc_struct(ctx, fz_pixmap);
+ *subpix = *pixmap;
+ subpix->x = rect->x0;
+ subpix->y = rect->y0;
+ subpix->w = rect->x1 - rect->x0;
+ subpix->h = rect->y1 - rect->y0;
+ subpix->samples += (rect->x0 - pixmap->x) + (rect->y0 - pixmap->y) * pixmap->stride;
+ subpix->underlying = fz_keep_pixmap(ctx, pixmap);
+ subpix->colorspace = fz_keep_colorspace(ctx, pixmap->colorspace);
+ subpix->seps = fz_keep_separations(ctx, pixmap->seps);
+ subpix->flags &= ~FZ_PIXMAP_FLAG_FREE_SAMPLES;
+
+ return subpix;
+}
+
fz_irect *
fz_pixmap_bbox(fz_context *ctx, const fz_pixmap *pix, fz_irect *bbox)
{