summaryrefslogtreecommitdiff
path: root/source/fitz/draw-device.c
diff options
context:
space:
mode:
authorRobin Watts <robin.watts@artifex.com>2015-07-13 16:23:14 +0100
committerRobin Watts <robin.watts@artifex.com>2015-07-20 17:19:03 +0100
commit269fdfce2527cbba02e68d658af3f4b92ef40be0 (patch)
treec75e9e4abdae745c64f98eaafa86d572e747f536 /source/fitz/draw-device.c
parentd8353609755104010afaf3e1967a36959f28c5dc (diff)
downloadmupdf-269fdfce2527cbba02e68d658af3f4b92ef40be0.tar.xz
Improve Grid fitting of images for .gproof files.
By default in MuPDF, when we render an axis aligned image, we 'gridfit' it. This is a heuristic used to improve the rendering of tiled images, and avoid the background showing through on the antialiased edges. The general algorithm we use is to expand any image outwards so that it completely covers any pixels that it touches any part of. This is 'safe' in that we never cause any pixels to not be covered that should otherwise be so, and is important when we have images that are aligned with (say) line art rectangles. For gproof files though, this gives nasty results - because we have multiple images tiled across the page all exactly abutting, in most cases the edges will not be on exact integer coordinates. This means we expand both images and 1 (destination) pixel is lost. This severely hurts the rendering (in particular on text based pages). We therefore introduce a new type of grid fitting, where we simply align the edges of images to the closest integer pixel. This is safe because we know that neighbouring images will be adjusted identically and edges will stay coincident. We enable/disable this behaviour through a new device flag, and make the gproof interpreter set/clear this flag when generating the page - thus normal rendering is unaffected. We *could* have just poked the dev->flags fields directly, but that would require magic in the display list device to check for them being set/unset and to poke the dev->flags fields on playback, so instead we introduce a new fz_render_flags function (that calls a device function) to set/unset flags. The other attraction of this is that if we ever have devices that 'filter', we can neatly handle passing flag changes on with those. Currently the display list implementation only copes with set/clear of the FZ_DEVFLAG_GRIDFIT_AS_TILED option. We only readily have 6 bits available to us, so we'll just extend this as required if we add new render flags.
Diffstat (limited to 'source/fitz/draw-device.c')
-rw-r--r--source/fitz/draw-device.c24
1 files changed, 18 insertions, 6 deletions
diff --git a/source/fitz/draw-device.c b/source/fitz/draw-device.c
index a2499016..fdb631f4 100644
--- a/source/fitz/draw-device.c
+++ b/source/fitz/draw-device.c
@@ -610,7 +610,7 @@ fz_draw_fill_text(fz_context *ctx, fz_device *devp, fz_text *text, const fz_matr
fz_matrix mat;
mat.a = pixmap->w; mat.b = mat.c = 0; mat.d = pixmap->h;
mat.e = x + pixmap->x; mat.f = y + pixmap->y;
- fz_paint_image(state->dest, &state->scissor, state->shape, pixmap, &mat, alpha * 255, !(devp->hints & FZ_DONT_INTERPOLATE_IMAGES));
+ fz_paint_image(state->dest, &state->scissor, state->shape, pixmap, &mat, alpha * 255, !(devp->hints & FZ_DONT_INTERPOLATE_IMAGES), devp->flags & FZ_DEVFLAG_GRIDFIT_AS_TILED);
}
fz_drop_glyph(ctx, glyph);
}
@@ -1040,7 +1040,9 @@ fz_transform_pixmap(fz_context *ctx, fz_draw_device *dev, fz_pixmap *image, fz_m
/* Unrotated or X-flip or Y-flip or XY-flip */
fz_matrix m = *ctm;
if (gridfit)
- fz_gridfit_matrix(&m);
+ {
+ fz_gridfit_matrix(dev->flags & FZ_DEVFLAG_GRIDFIT_AS_TILED, &m);
+ }
scaled = fz_scale_pixmap_cached(ctx, image, m.e, m.f, m.a, m.d, clip, dev->cache_x, dev->cache_y);
if (!scaled)
return NULL;
@@ -1057,7 +1059,7 @@ fz_transform_pixmap(fz_context *ctx, fz_draw_device *dev, fz_pixmap *image, fz_m
fz_matrix m = *ctm;
fz_irect rclip;
if (gridfit)
- fz_gridfit_matrix(&m);
+ fz_gridfit_matrix(dev->flags & FZ_DEVFLAG_GRIDFIT_AS_TILED, &m);
if (clip)
{
rclip.x0 = clip->y0;
@@ -1174,7 +1176,7 @@ fz_draw_fill_image(fz_context *ctx, fz_device *devp, fz_image *image, const fz_m
}
}
- fz_paint_image(state->dest, &state->scissor, state->shape, pixmap, &local_ctm, alpha * 255, !(devp->hints & FZ_DONT_INTERPOLATE_IMAGES));
+ fz_paint_image(state->dest, &state->scissor, state->shape, pixmap, &local_ctm, alpha * 255, !(devp->hints & FZ_DONT_INTERPOLATE_IMAGES), devp->flags & FZ_DEVFLAG_GRIDFIT_AS_TILED);
if (state->blendmode & FZ_BLEND_KNOCKOUT)
fz_knockout_end(ctx, dev);
@@ -1245,7 +1247,7 @@ fz_draw_fill_image_mask(fz_context *ctx, fz_device *devp, fz_image *image, const
colorbv[i] = colorfv[i] * 255;
colorbv[i] = alpha * 255;
- fz_paint_image_with_color(state->dest, &state->scissor, state->shape, pixmap, &local_ctm, colorbv, !(devp->hints & FZ_DONT_INTERPOLATE_IMAGES));
+ fz_paint_image_with_color(state->dest, &state->scissor, state->shape, pixmap, &local_ctm, colorbv, !(devp->hints & FZ_DONT_INTERPOLATE_IMAGES), devp->flags & FZ_DEVFLAG_GRIDFIT_AS_TILED);
if (scaled)
fz_drop_pixmap(ctx, scaled);
@@ -1351,7 +1353,7 @@ fz_draw_clip_image_mask(fz_context *ctx, fz_device *devp, fz_image *image, const
if (scaled)
pixmap = scaled;
}
- fz_paint_image(mask, &bbox, state->shape, pixmap, &local_ctm, 255, !(devp->hints & FZ_DONT_INTERPOLATE_IMAGES));
+ fz_paint_image(mask, &bbox, state->shape, pixmap, &local_ctm, 255, !(devp->hints & FZ_DONT_INTERPOLATE_IMAGES), devp->flags & FZ_DEVFLAG_GRIDFIT_AS_TILED);
}
fz_always(ctx)
{
@@ -2040,6 +2042,14 @@ fz_draw_drop_imp(fz_context *ctx, fz_device *devp)
fz_drop_gel(ctx, gel);
}
+static void
+fz_draw_render_flags(fz_context *ctx, fz_device *devp, int set, int clear)
+{
+ fz_draw_device *dev = (fz_draw_device*)devp;
+
+ dev->flags = (dev->flags | set ) & ~clear;
+}
+
fz_device *
fz_new_draw_device(fz_context *ctx, fz_pixmap *dest)
{
@@ -2073,6 +2083,8 @@ fz_new_draw_device(fz_context *ctx, fz_pixmap *dest)
dev->super.begin_tile = fz_draw_begin_tile;
dev->super.end_tile = fz_draw_end_tile;
+ dev->super.render_flags = fz_draw_render_flags;
+
dev->flags = 0;
dev->top = 0;
dev->stack = &dev->init_stack[0];