summaryrefslogtreecommitdiff
path: root/draw
diff options
context:
space:
mode:
authorRobin Watts <robin.watts@artifex.com>2012-11-21 15:59:56 +0000
committerRobin Watts <robin.watts@artifex.com>2012-11-21 17:31:02 +0000
commit678904ef2e6fb9c449b8bdaeba5802643592d4a4 (patch)
treec5c5b97fc6a9a62d25a1ce8331feb76683522990 /draw
parent06fd5ad8a48b0339bb00ef531d84733fb05f19c6 (diff)
downloadmupdf-678904ef2e6fb9c449b8bdaeba5802643592d4a4.tar.xz
Add weights caches for pixmap scaling.
This means that repeated scaling of the same pixmap (or scales of 'stacked' pixmaps) will do less needless recalculation.
Diffstat (limited to 'draw')
-rw-r--r--draw/draw_device.c29
-rw-r--r--draw/draw_scale.c88
-rw-r--r--draw/draw_simple_scale.c88
3 files changed, 177 insertions, 28 deletions
diff --git a/draw/draw_device.c b/draw/draw_device.c
index 8d2c4d8b..a52c77ca 100644
--- a/draw/draw_device.c
+++ b/draw/draw_device.c
@@ -40,6 +40,8 @@ struct fz_draw_device_s
fz_context *ctx;
int flags;
int top;
+ fz_scale_cache *cache_x;
+ fz_scale_cache *cache_y;
fz_draw_state *stack;
int stack_max;
fz_draw_state init_stack[STACK_SIZE];
@@ -937,9 +939,10 @@ fz_draw_fill_shade(fz_device *devp, fz_shade *shade, fz_matrix ctm, float alpha)
}
static fz_pixmap *
-fz_transform_pixmap(fz_context *ctx, fz_pixmap *image, fz_matrix *ctm, int x, int y, int dx, int dy, int gridfit, fz_bbox *clip)
+fz_transform_pixmap(fz_draw_device *dev, fz_pixmap *image, fz_matrix *ctm, int x, int y, int dx, int dy, int gridfit, fz_bbox *clip)
{
fz_pixmap *scaled;
+ fz_context *ctx = dev->ctx;
if (ctm->a != 0 && ctm->b == 0 && ctm->c == 0 && ctm->d != 0)
{
@@ -947,7 +950,7 @@ fz_transform_pixmap(fz_context *ctx, fz_pixmap *image, fz_matrix *ctm, int x, in
fz_matrix m = *ctm;
if (gridfit)
fz_gridfit_matrix(&m);
- scaled = fz_scale_pixmap(ctx, image, m.e, m.f, m.a, m.d, clip);
+ 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;
ctm->a = scaled->w;
@@ -971,7 +974,7 @@ fz_transform_pixmap(fz_context *ctx, fz_pixmap *image, fz_matrix *ctm, int x, in
rclip.x1 = clip->y1;
rclip.y1 = clip->x1;
}
- scaled = fz_scale_pixmap(ctx, image, m.f, m.e, m.b, m.c, (clip ? &rclip : 0));
+ scaled = fz_scale_pixmap_cached(ctx, image, m.f, m.e, m.b, m.c, (clip ? &rclip : 0), dev->cache_x, dev->cache_y);
if (!scaled)
return NULL;
ctm->b = scaled->w;
@@ -984,7 +987,7 @@ fz_transform_pixmap(fz_context *ctx, fz_pixmap *image, fz_matrix *ctm, int x, in
/* Downscale, non rectilinear case */
if (dx > 0 && dy > 0)
{
- scaled = fz_scale_pixmap(ctx, image, 0, 0, (float)dx, (float)dy, NULL);
+ scaled = fz_scale_pixmap_cached(ctx, image, 0, 0, (float)dx, (float)dy, NULL, dev->cache_x, dev->cache_y);
return scaled;
}
@@ -1048,14 +1051,14 @@ fz_draw_fill_image(fz_device *devp, fz_image *image, fz_matrix ctm, float alpha)
if (dx < pixmap->w && dy < pixmap->h)
{
int gridfit = alpha == 1.0f && !(dev->flags & FZ_DRAWDEV_FLAGS_TYPE3);
- scaled = fz_transform_pixmap(ctx, pixmap, &ctm, state->dest->x, state->dest->y, dx, dy, gridfit, &clip);
+ scaled = fz_transform_pixmap(dev, pixmap, &ctm, state->dest->x, state->dest->y, dx, dy, gridfit, &clip);
if (!scaled)
{
if (dx < 1)
dx = 1;
if (dy < 1)
dy = 1;
- scaled = fz_scale_pixmap(ctx, pixmap, pixmap->x, pixmap->y, dx, dy, NULL);
+ scaled = fz_scale_pixmap_cached(ctx, pixmap, pixmap->x, pixmap->y, dx, dy, NULL, dev->cache_x, dev->cache_y);
}
if (scaled)
pixmap = scaled;
@@ -1128,14 +1131,14 @@ fz_draw_fill_image_mask(fz_device *devp, fz_image *image, fz_matrix ctm,
if (dx < pixmap->w && dy < pixmap->h)
{
int gridfit = alpha == 1.0f && !(dev->flags & FZ_DRAWDEV_FLAGS_TYPE3);
- scaled = fz_transform_pixmap(dev->ctx, pixmap, &ctm, state->dest->x, state->dest->y, dx, dy, gridfit, &clip);
+ scaled = fz_transform_pixmap(dev, pixmap, &ctm, state->dest->x, state->dest->y, dx, dy, gridfit, &clip);
if (!scaled)
{
if (dx < 1)
dx = 1;
if (dy < 1)
dy = 1;
- scaled = fz_scale_pixmap(dev->ctx, pixmap, pixmap->x, pixmap->y, dx, dy, NULL);
+ scaled = fz_scale_pixmap_cached(dev->ctx, pixmap, pixmap->x, pixmap->y, dx, dy, NULL, dev->cache_x, dev->cache_y);
}
if (scaled)
pixmap = scaled;
@@ -1227,14 +1230,14 @@ fz_draw_clip_image_mask(fz_device *devp, fz_image *image, fz_rect *rect, fz_matr
if (dx < pixmap->w && dy < pixmap->h)
{
int gridfit = !(dev->flags & FZ_DRAWDEV_FLAGS_TYPE3);
- scaled = fz_transform_pixmap(dev->ctx, pixmap, &ctm, state->dest->x, state->dest->y, dx, dy, gridfit, &clip);
+ scaled = fz_transform_pixmap(dev, pixmap, &ctm, state->dest->x, state->dest->y, dx, dy, gridfit, &clip);
if (!scaled)
{
if (dx < 1)
dx = 1;
if (dy < 1)
dy = 1;
- scaled = fz_scale_pixmap(dev->ctx, pixmap, pixmap->x, pixmap->y, dx, dy, NULL);
+ scaled = fz_scale_pixmap_cached(dev->ctx, pixmap, pixmap->x, pixmap->y, dx, dy, NULL, dev->cache_x, dev->cache_y);
}
if (scaled)
pixmap = scaled;
@@ -1699,6 +1702,8 @@ fz_draw_free_user(fz_device *devp)
*/
if (dev->stack != &dev->init_stack[0])
fz_free(ctx, dev->stack);
+ fz_free_scale_cache(ctx, dev->cache_x);
+ fz_free_scale_cache(ctx, dev->cache_y);
fz_free_gel(dev->gel);
fz_free(ctx, dev);
}
@@ -1716,6 +1721,8 @@ fz_new_draw_device(fz_context *ctx, fz_pixmap *dest)
ddev->flags = 0;
ddev->ctx = ctx;
ddev->top = 0;
+ ddev->cache_x = fz_new_scale_cache(ctx);
+ ddev->cache_y = fz_new_scale_cache(ctx);
ddev->stack = &ddev->init_stack[0];
ddev->stack_max = STACK_SIZE;
ddev->stack[0].dest = dest;
@@ -1731,6 +1738,8 @@ fz_new_draw_device(fz_context *ctx, fz_pixmap *dest)
}
fz_catch(ctx)
{
+ fz_free_scale_cache(ctx, ddev->cache_x);
+ fz_free_scale_cache(ctx, ddev->cache_y);
fz_free_gel(ddev->gel);
fz_free(ctx, ddev);
fz_rethrow(ctx);
diff --git a/draw/draw_scale.c b/draw/draw_scale.c
index aceec939..34738fab 100644
--- a/draw/draw_scale.c
+++ b/draw/draw_scale.c
@@ -273,6 +273,21 @@ struct fz_weights_s
int index[1];
};
+struct fz_scale_cache_s
+{
+ int src_w;
+ float x;
+ float dst_w;
+ fz_scale_filter *filter;
+ int vertical;
+ int dst_w_int;
+ int patch_l;
+ int patch_r;
+ int n;
+ int flip;
+ fz_weights *weights;
+};
+
static fz_weights *
new_weights(fz_context *ctx, fz_scale_filter *filter, int src_w, float dst_w, int patch_w, int n, int flip, int patch_l)
{
@@ -493,13 +508,37 @@ check_weights(fz_weights *weights, int j, int w, float x, float wf)
}
static fz_weights *
-make_weights(fz_context *ctx, int src_w, float x, float dst_w, fz_scale_filter *filter, int vertical, int dst_w_int, int patch_l, int patch_r, int n, int flip)
+make_weights(fz_context *ctx, int src_w, float x, float dst_w, fz_scale_filter *filter, int vertical, int dst_w_int, int patch_l, int patch_r, int n, int flip, fz_scale_cache *cache)
{
fz_weights *weights;
float F, G;
float window;
int j;
+ if (cache)
+ {
+ if (cache->src_w == src_w && cache->x == x && cache->dst_w == dst_w &&
+ cache->filter == filter && cache->vertical == vertical &&
+ cache->dst_w_int == dst_w_int &&
+ cache->patch_l == patch_l && cache->patch_r == patch_r &&
+ cache->n == n && cache->flip == flip)
+ {
+ return cache->weights;
+ }
+ cache->src_w = src_w;
+ cache->x = x;
+ cache->dst_w = dst_w;
+ cache->filter = filter;
+ cache->vertical = vertical;
+ cache->dst_w_int = dst_w_int;
+ cache->patch_l = patch_l;
+ cache->patch_r = patch_r;
+ cache->n = n;
+ cache->flip = flip;
+ fz_free(ctx, cache->weights);
+ cache->weights = NULL;
+ }
+
if (dst_w < src_w)
{
/* Scaling down */
@@ -537,6 +576,10 @@ make_weights(fz_context *ctx, int src_w, float x, float dst_w, fz_scale_filter *
}
}
weights->count++; /* weights->count = dst_w_int now */
+ if (cache)
+ {
+ cache->weights = weights;
+ }
return weights;
}
@@ -1197,6 +1240,12 @@ scale_single_col(unsigned char *dst, unsigned char *src, fz_weights *weights, in
fz_pixmap *
fz_scale_pixmap(fz_context *ctx, fz_pixmap *src, float x, float y, float w, float h, fz_bbox *clip)
{
+ return fz_scale_pixmap_cached(ctx, src, x, y, w, h, clip, NULL, NULL);
+}
+
+fz_pixmap *
+fz_scale_pixmap_cached(fz_context *ctx, fz_pixmap *src, float x, float y, float w, float h, fz_bbox *clip, fz_scale_cache *cache_x, fz_scale_cache *cache_y)
+{
fz_scale_filter *filter = &fz_scale_filter_simple;
fz_weights *contrib_rows = NULL;
fz_weights *contrib_cols = NULL;
@@ -1332,20 +1381,22 @@ fz_scale_pixmap(fz_context *ctx, fz_pixmap *src, float x, float y, float w, floa
contrib_cols = NULL;
else
#endif /* SINGLE_PIXEL_SPECIALS */
- contrib_cols = make_weights(ctx, src->w, x, w, filter, 0, dst_w_int, patch.x0, patch.x1, src->n, flip_x);
+ contrib_cols = make_weights(ctx, src->w, x, w, filter, 0, dst_w_int, patch.x0, patch.x1, src->n, flip_x, cache_x);
#ifdef SINGLE_PIXEL_SPECIALS
if (src->h == 1)
contrib_rows = NULL;
else
#endif /* SINGLE_PIXEL_SPECIALS */
- contrib_rows = make_weights(ctx, src->h, y, h, filter, 1, dst_h_int, patch.y0, patch.y1, src->n, flip_y);
+ contrib_rows = make_weights(ctx, src->h, y, h, filter, 1, dst_h_int, patch.y0, patch.y1, src->n, flip_y, cache_y);
output = fz_new_pixmap(ctx, src->colorspace, patch.x1 - patch.x0, patch.y1 - patch.y0);
}
fz_catch(ctx)
{
- fz_free(ctx, contrib_cols);
- fz_free(ctx, contrib_rows);
+ if (!cache_x)
+ fz_free(ctx, contrib_cols);
+ if (!cache_y)
+ fz_free(ctx, contrib_rows);
fz_rethrow(ctx);
}
output->x = dst_x_int;
@@ -1388,8 +1439,10 @@ fz_scale_pixmap(fz_context *ctx, fz_pixmap *src, float x, float y, float w, floa
fz_catch(ctx)
{
fz_drop_pixmap(ctx, output);
- fz_free(ctx, contrib_cols);
- fz_free(ctx, contrib_rows);
+ if (!cache_x)
+ fz_free(ctx, contrib_cols);
+ if (!cache_y)
+ fz_free(ctx, contrib_rows);
fz_rethrow(ctx);
}
switch (src->n)
@@ -1434,7 +1487,24 @@ fz_scale_pixmap(fz_context *ctx, fz_pixmap *src, float x, float y, float w, floa
}
cleanup:
- fz_free(ctx, contrib_rows);
- fz_free(ctx, contrib_cols);
+ if (!cache_y)
+ fz_free(ctx, contrib_rows);
+ if (!cache_x)
+ fz_free(ctx, contrib_cols);
return output;
}
+
+void
+fz_free_scale_cache(fz_context *ctx, fz_scale_cache *sc)
+{
+ if (!sc)
+ return;
+ fz_free(ctx, sc->weights);
+ fz_free(ctx, sc);
+}
+
+fz_scale_cache *
+fz_new_scale_cache(fz_context *ctx)
+{
+ return fz_malloc_struct(ctx, fz_scale_cache);
+}
diff --git a/draw/draw_simple_scale.c b/draw/draw_simple_scale.c
index af995edc..606ee2bb 100644
--- a/draw/draw_simple_scale.c
+++ b/draw/draw_simple_scale.c
@@ -214,6 +214,21 @@ struct fz_weights_s
int index[1];
};
+struct fz_scale_cache_s
+{
+ int src_w;
+ float x;
+ float dst_w;
+ fz_scale_filter *filter;
+ int vertical;
+ int dst_w_int;
+ int patch_l;
+ int patch_r;
+ int n;
+ int flip;
+ fz_weights *weights;
+};
+
static fz_weights *
new_weights(fz_context *ctx, fz_scale_filter *filter, int src_w, float dst_w, int patch_w, int n, int flip, int patch_l)
{
@@ -442,13 +457,37 @@ check_weights(fz_weights *weights, int j, int w, float x, float wf)
}
static fz_weights *
-make_weights(fz_context *ctx, int src_w, float x, float dst_w, fz_scale_filter *filter, int vertical, int dst_w_int, int patch_l, int patch_r, int n, int flip)
+make_weights(fz_context *ctx, int src_w, float x, float dst_w, fz_scale_filter *filter, int vertical, int dst_w_int, int patch_l, int patch_r, int n, int flip, fz_scale_cache *cache)
{
fz_weights *weights;
float F, G;
float window;
int j;
+ if (cache)
+ {
+ if (cache->src_w == src_w && cache->x == x && cache->dst_w == dst_w &&
+ cache->filter == filter && cache->vertical == vertical &&
+ cache->dst_w_int == dst_w_int &&
+ cache->patch_l == patch_l && cache->patch_r == patch_r &&
+ cache->n == n && cache->flip == flip)
+ {
+ return cache->weights;
+ }
+ cache->src_w = src_w;
+ cache->x = x;
+ cache->dst_w = dst_w;
+ cache->filter = filter;
+ cache->vertical = vertical;
+ cache->dst_w_int = dst_w_int;
+ cache->patch_l = patch_l;
+ cache->patch_r = patch_r;
+ cache->n = n;
+ cache->flip = flip;
+ fz_free(ctx, cache->weights);
+ cache->weights = NULL;
+ }
+
if (dst_w < src_w)
{
/* Scaling down */
@@ -486,6 +525,10 @@ make_weights(fz_context *ctx, int src_w, float x, float dst_w, fz_scale_filter *
}
}
weights->count++; /* weights->count = dst_w_int now */
+ if (cache)
+ {
+ cache->weights = weights;
+ }
return weights;
}
@@ -1173,6 +1216,12 @@ scale_single_col(unsigned char *dst, unsigned char *src, fz_weights *weights, in
fz_pixmap *
fz_scale_pixmap(fz_context *ctx, fz_pixmap *src, float x, float y, float w, float h, fz_bbox *clip)
{
+ return fz_scale_pixmap_cached(ctx, src, x, y, w, h, clip, NULL, NULL);
+}
+
+fz_pixmap *
+fz_scale_pixmap_cached(fz_context *ctx, fz_pixmap *src, float x, float y, float w, float h, fz_bbox *clip, fz_scale_cache *cache_x, fz_scale_cache *cache_y)
+{
fz_scale_filter *filter = &fz_scale_filter_simple;
fz_weights *contrib_rows = NULL;
fz_weights *contrib_cols = NULL;
@@ -1310,20 +1359,22 @@ fz_scale_pixmap(fz_context *ctx, fz_pixmap *src, float x, float y, float w, floa
contrib_cols = NULL;
else
#endif /* SINGLE_PIXEL_SPECIALS */
- contrib_cols = make_weights(ctx, src->w, x, w, filter, 0, dst_w_int, patch.x0, patch.x1, src->n, flip_x);
+ contrib_cols = make_weights(ctx, src->w, x, w, filter, 0, dst_w_int, patch.x0, patch.x1, src->n, flip_x, cache_x);
#ifdef SINGLE_PIXEL_SPECIALS
if (src->h == 1)
contrib_rows = NULL;
else
#endif /* SINGLE_PIXEL_SPECIALS */
- contrib_rows = make_weights(ctx, src->h, y, h, filter, 1, dst_h_int, patch.y0, patch.y1, src->n, flip_y);
+ contrib_rows = make_weights(ctx, src->h, y, h, filter, 1, dst_h_int, patch.y0, patch.y1, src->n, flip_y, cache_y);
output = fz_new_pixmap(ctx, src->colorspace, patch.x1 - patch.x0, patch.y1 - patch.y0);
}
fz_catch(ctx)
{
- fz_free(ctx, contrib_cols);
- fz_free(ctx, contrib_rows);
+ if (!cache_x)
+ fz_free(ctx, contrib_cols);
+ if (!cache_y)
+ fz_free(ctx, contrib_rows);
fz_rethrow(ctx);
}
output->x = dst_x_int;
@@ -1366,8 +1417,10 @@ fz_scale_pixmap(fz_context *ctx, fz_pixmap *src, float x, float y, float w, floa
fz_catch(ctx)
{
fz_drop_pixmap(ctx, output);
- fz_free(ctx, contrib_cols);
- fz_free(ctx, contrib_rows);
+ if (!cache_x)
+ fz_free(ctx, contrib_cols);
+ if (!cache_y)
+ fz_free(ctx, contrib_rows);
fz_rethrow(ctx);
}
switch (src->n)
@@ -1412,7 +1465,24 @@ fz_scale_pixmap(fz_context *ctx, fz_pixmap *src, float x, float y, float w, floa
}
cleanup:
- fz_free(ctx, contrib_rows);
- fz_free(ctx, contrib_cols);
+ if (!cache_y)
+ fz_free(ctx, contrib_rows);
+ if (!cache_x)
+ fz_free(ctx, contrib_cols);
return output;
}
+
+void
+fz_free_scale_cache(fz_context *ctx, fz_scale_cache *sc)
+{
+ if (!sc)
+ return;
+ fz_free(ctx, sc->weights);
+ fz_free(ctx, sc);
+}
+
+fz_scale_cache *
+fz_new_scale_cache(fz_context *ctx)
+{
+ return fz_malloc_struct(ctx, fz_scale_cache);
+}