summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to 'source')
-rw-r--r--source/fitz/device.c7
-rw-r--r--source/fitz/draw-affine.c71
-rw-r--r--source/fitz/draw-device.c24
-rw-r--r--source/fitz/draw-imp.h4
-rw-r--r--source/fitz/list-device.c45
-rw-r--r--source/gprf/gprf-doc.c2
6 files changed, 132 insertions, 21 deletions
diff --git a/source/fitz/device.c b/source/fitz/device.c
index 5e3bb61a..6df650f4 100644
--- a/source/fitz/device.c
+++ b/source/fitz/device.c
@@ -488,3 +488,10 @@ fz_end_tile(fz_context *ctx, fz_device *dev)
if (dev->end_tile)
dev->end_tile(ctx, dev);
}
+
+void
+fz_render_flags(fz_context *ctx, fz_device *dev, int set, int clear)
+{
+ if (dev->render_flags)
+ dev->render_flags(ctx, dev, set, clear);
+}
diff --git a/source/fitz/draw-affine.c b/source/fitz/draw-affine.c
index ec19d936..1c6c26d1 100644
--- a/source/fitz/draw-affine.c
+++ b/source/fitz/draw-affine.c
@@ -807,12 +807,31 @@ fz_paint_affine_color_near(byte *dp, byte *sp, int sw, int sh, int u, int v, int
*/
#define MY_EPSILON 0.001
+/* We have 2 possible ways of gridfitting images. The first way, considered
+ * 'safe' in all cases, is to expand an image out to fill a box that entirely
+ * covers all the pixels touched by the current image. This is our 'standard'
+ * mechanism.
+ * The alternative, used when we know images are tiled across a page, is to
+ * round the edge of each image to the closest integer pixel boundary. This
+ * would not be safe in the general case, but gives less distortion across
+ * neighbouring images when tiling is used. We use this for .gproof files.
+ */
void
-fz_gridfit_matrix(fz_matrix *m)
+fz_gridfit_matrix(int as_tiled, fz_matrix *m)
{
if (fabsf(m->b) < FLT_EPSILON && fabsf(m->c) < FLT_EPSILON)
{
- if (m->a > 0)
+ if (as_tiled)
+ {
+ float f;
+ /* Nearest boundary for left */
+ f = (float)(int)(m->e + 0.5);
+ m->a += m->e - f; /* Adjust width for change */
+ m->e = f;
+ /* Nearest boundary for right (width really) */
+ m->a = (float)(int)(m->a + 0.5);
+ }
+ else if (m->a > 0)
{
float f;
/* Adjust left hand side onto pixel boundary */
@@ -842,7 +861,17 @@ fz_gridfit_matrix(fz_matrix *m)
f -= 1.0; /* Ensure it moves left */
m->a = f;
}
- if (m->d > 0)
+ if (as_tiled)
+ {
+ float f;
+ /* Nearest boundary for top */
+ f = (float)(int)(m->f + 0.5);
+ m->d += m->f - f; /* Adjust width for change */
+ m->f = f;
+ /* Nearest boundary for bottom (height really) */
+ m->d = (float)(int)(m->d + 0.5);
+ }
+ else if (m->d > 0)
{
float f;
/* Adjust top onto pixel boundary */
@@ -875,7 +904,17 @@ fz_gridfit_matrix(fz_matrix *m)
}
else if (fabsf(m->a) < FLT_EPSILON && fabsf(m->d) < FLT_EPSILON)
{
- if (m->b > 0)
+ if (as_tiled)
+ {
+ float f;
+ /* Nearest boundary for left */
+ f = (float)(int)(m->e + 0.5);
+ m->b += m->e - f; /* Adjust width for change */
+ m->e = f;
+ /* Nearest boundary for right (width really) */
+ m->b = (float)(int)(m->b + 0.5);
+ }
+ else if (m->b > 0)
{
float f;
/* Adjust left hand side onto pixel boundary */
@@ -905,7 +944,17 @@ fz_gridfit_matrix(fz_matrix *m)
f -= 1.0; /* Ensure it moves left */
m->b = f;
}
- if (m->c > 0)
+ if (as_tiled)
+ {
+ float f;
+ /* Nearest boundary for left */
+ f = (float)(int)(m->f + 0.5);
+ m->c += m->f - f; /* Adjust width for change */
+ m->f = f;
+ /* Nearest boundary for right (width really) */
+ m->c = (float)(int)(m->c + 0.5);
+ }
+ else if (m->c > 0)
{
float f;
/* Adjust top onto pixel boundary */
@@ -941,7 +990,7 @@ fz_gridfit_matrix(fz_matrix *m)
/* Draw an image with an affine transform on destination */
static void
-fz_paint_image_imp(fz_pixmap *dst, const fz_irect *scissor, fz_pixmap *shape, fz_pixmap *img, const fz_matrix *ctm, byte *color, int alpha, int lerp_allowed)
+fz_paint_image_imp(fz_pixmap *dst, const fz_irect *scissor, fz_pixmap *shape, fz_pixmap *img, const fz_matrix *ctm, byte *color, int alpha, int lerp_allowed, int as_tiled)
{
byte *dp, *sp, *hp;
int u, v, fa, fb, fc, fd;
@@ -955,7 +1004,7 @@ fz_paint_image_imp(fz_pixmap *dst, const fz_irect *scissor, fz_pixmap *shape, fz
int is_rectilinear;
/* grid fit the image */
- fz_gridfit_matrix(&local_ctm);
+ fz_gridfit_matrix(as_tiled, &local_ctm);
/* turn on interpolation for upscaled and non-rectilinear transforms */
dolerp = 0;
@@ -1084,15 +1133,15 @@ fz_paint_image_imp(fz_pixmap *dst, const fz_irect *scissor, fz_pixmap *shape, fz
}
void
-fz_paint_image_with_color(fz_pixmap *dst, const fz_irect *scissor, fz_pixmap *shape, fz_pixmap *img, const fz_matrix *ctm, byte *color, int lerp_allowed)
+fz_paint_image_with_color(fz_pixmap *dst, const fz_irect *scissor, fz_pixmap *shape, fz_pixmap *img, const fz_matrix *ctm, byte *color, int lerp_allowed, int as_tiled)
{
assert(img->n == 1);
- fz_paint_image_imp(dst, scissor, shape, img, ctm, color, 255, lerp_allowed);
+ fz_paint_image_imp(dst, scissor, shape, img, ctm, color, 255, lerp_allowed, as_tiled);
}
void
-fz_paint_image(fz_pixmap *dst, const fz_irect *scissor, fz_pixmap *shape, fz_pixmap *img, const fz_matrix *ctm, int alpha, int lerp_allowed)
+fz_paint_image(fz_pixmap *dst, const fz_irect *scissor, fz_pixmap *shape, fz_pixmap *img, const fz_matrix *ctm, int alpha, int lerp_allowed, int as_tiled)
{
assert(dst->n == img->n || (dst->n == 4 && img->n == 2));
- fz_paint_image_imp(dst, scissor, shape, img, ctm, NULL, alpha, lerp_allowed);
+ fz_paint_image_imp(dst, scissor, shape, img, ctm, NULL, alpha, lerp_allowed, as_tiled);
}
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];
diff --git a/source/fitz/draw-imp.h b/source/fitz/draw-imp.h
index 3a1ddbd2..8a750860 100644
--- a/source/fitz/draw-imp.h
+++ b/source/fitz/draw-imp.h
@@ -35,8 +35,8 @@ void fz_paint_solid_color(unsigned char * restrict dp, int n, int w, unsigned ch
void fz_paint_span(unsigned char * restrict dp, unsigned char * restrict sp, int n, int w, int alpha);
void fz_paint_span_with_color(unsigned char * restrict dp, unsigned char * restrict mp, int n, int w, unsigned char *color);
-void fz_paint_image(fz_pixmap *dst, const fz_irect *scissor, fz_pixmap *shape, fz_pixmap *img, const fz_matrix *ctm, int alpha, int lerp_allowed);
-void fz_paint_image_with_color(fz_pixmap *dst, const fz_irect *scissor, fz_pixmap *shape, fz_pixmap *img, const fz_matrix *ctm, unsigned char *colorbv, int lerp_allowed);
+void fz_paint_image(fz_pixmap *dst, const fz_irect *scissor, fz_pixmap *shape, fz_pixmap *img, const fz_matrix *ctm, int alpha, int lerp_allowed, int gridfit_as_tiled);
+void fz_paint_image_with_color(fz_pixmap *dst, const fz_irect *scissor, fz_pixmap *shape, fz_pixmap *img, const fz_matrix *ctm, unsigned char *colorbv, int lerp_allowed, int gridfit_as_tiled);
void fz_paint_pixmap(fz_pixmap *dst, fz_pixmap *src, int alpha);
void fz_paint_pixmap_with_mask(fz_pixmap *dst, fz_pixmap *src, fz_pixmap *msk);
diff --git a/source/fitz/list-device.c b/source/fitz/list-device.c
index 038517b4..0a282018 100644
--- a/source/fitz/list-device.c
+++ b/source/fitz/list-device.c
@@ -28,7 +28,8 @@ typedef enum fz_display_command_e
FZ_CMD_BEGIN_GROUP,
FZ_CMD_END_GROUP,
FZ_CMD_BEGIN_TILE,
- FZ_CMD_END_TILE
+ FZ_CMD_END_TILE,
+ FZ_CMD_RENDER_FLAGS
} fz_display_command;
/* The display list is a list of nodes.
@@ -1212,6 +1213,37 @@ fz_list_end_tile(fz_context *ctx, fz_device *dev)
}
static void
+fz_list_render_flags(fz_context *ctx, fz_device *dev, int set, int clear)
+{
+ int flags;
+
+ /* Pack the options down */
+ if (set == FZ_DEVFLAG_GRIDFIT_AS_TILED && clear == 0)
+ flags = 1;
+ else if (set == 0 && clear == FZ_DEVFLAG_GRIDFIT_AS_TILED)
+ flags = 0;
+ else
+ {
+ assert("Unsupported flags combination" == NULL);
+ return;
+ }
+ fz_append_display_node(
+ ctx,
+ dev,
+ FZ_CMD_RENDER_FLAGS,
+ flags, /* flags */
+ NULL,
+ NULL, /* path */
+ NULL, /* color */
+ NULL, /* colorspace */
+ NULL, /* alpha */
+ NULL, /* ctm */
+ NULL, /* stroke */
+ NULL, /* private_data */
+ 0); /* private_data_len */
+}
+
+static void
drop_writer(fz_context *ctx, fz_device *dev)
{
fz_list_device *writer = (fz_list_device *)dev;
@@ -1257,6 +1289,8 @@ fz_new_list_device(fz_context *ctx, fz_display_list *list)
dev->super.begin_tile = fz_list_begin_tile;
dev->super.end_tile = fz_list_end_tile;
+ dev->super.render_flags = fz_list_render_flags;
+
dev->super.drop_imp = drop_writer;
dev->list = list;
@@ -1570,7 +1604,8 @@ fz_run_display_list(fz_context *ctx, fz_display_list *list, fz_device *dev, cons
if (tiled ||
n.cmd == FZ_CMD_BEGIN_TILE || n.cmd == FZ_CMD_END_TILE ||
- n.cmd == FZ_CMD_BEGIN_PAGE || n.cmd == FZ_CMD_END_PAGE)
+ n.cmd == FZ_CMD_BEGIN_PAGE || n.cmd == FZ_CMD_END_PAGE ||
+ n.cmd == FZ_CMD_RENDER_FLAGS)
{
empty = 0;
}
@@ -1700,6 +1735,12 @@ visible:
tiled--;
fz_end_tile(ctx, dev);
break;
+ case FZ_CMD_RENDER_FLAGS:
+ if (n.flags == 0)
+ fz_render_flags(ctx, dev, 0, FZ_DEVFLAG_GRIDFIT_AS_TILED);
+ else if (n.flags == 1)
+ fz_render_flags(ctx, dev, FZ_DEVFLAG_GRIDFIT_AS_TILED, 0);
+ break;
}
}
fz_catch(ctx)
diff --git a/source/gprf/gprf-doc.c b/source/gprf/gprf-doc.c
index bcd631ad..e9638340 100644
--- a/source/gprf/gprf-doc.c
+++ b/source/gprf/gprf-doc.c
@@ -596,6 +596,7 @@ gprf_run_page(fz_context *ctx, fz_page *page_, fz_device *dev, const fz_matrix *
page_rect.y0 = 0;
page_rect.x1 = 72.0 * page->width / doc->res;
page_rect.y1 = 72.0 * page->height / doc->res;
+ fz_render_flags(ctx, dev, FZ_DEVFLAG_GRIDFIT_AS_TILED, 0);
fz_begin_page(ctx, dev, &page_rect, ctm);
i = 0;
@@ -618,6 +619,7 @@ gprf_run_page(fz_context *ctx, fz_page *page_, fz_device *dev, const fz_matrix *
}
}
fz_end_page(ctx, dev);
+ fz_render_flags(ctx, dev, 0, FZ_DEVFLAG_GRIDFIT_AS_TILED);
}