diff options
author | Robin Watts <robin.watts@artifex.com> | 2013-01-25 19:24:49 +0000 |
---|---|---|
committer | Robin Watts <robin.watts@artifex.com> | 2013-02-06 19:24:12 +0000 |
commit | d3aa37962470253083714b5092a1ba759f674d47 (patch) | |
tree | ec60a0857cd3d44d3db5bc0c95aa69335b6b2d47 /draw/draw_affine.c | |
parent | c42dac496e0994c4253eb50ce67ceaec864ed379 (diff) | |
download | mupdf-d3aa37962470253083714b5092a1ba759f674d47.tar.xz |
Change to pass structures by reference rather than value.
This is faster on ARM in particular. The primary changes involve
fz_matrix, fz_rect and fz_bbox.
Rather than passing 'fz_rect r' into a function, we now consistently
pass 'const fz_rect *r'. Where a rect is passed in and modified, we
miss the 'const' off. Where possible, we return the pointer to the
modified structure to allow 'chaining' of expressions.
The basic upshot of this work is that we do far fewer copies of
rectangle/matrix structures, and all the copies we do are explicit.
This has opened the way to other optimisations, also performed in
this commit.
Rather than using expressions like:
fz_concat(fz_scale(sx, sy), fz_translate(tx, ty))
we now have fz_pre_{scale,translate,rotate} functions. These
can be implemented much more efficiently than doing the fully
fledged matrix multiplication that fz_concat requires.
We add fz_rect_{min,max} functions to return pointers to the
min/max points of a rect. These can be used to in transformations
to directly manipulate values.
With a little casting in the path transformation code we can avoid
more needless copying.
We rename fz_widget_bbox to the more consistent fz_bound_widget.
Diffstat (limited to 'draw/draw_affine.c')
-rw-r--r-- | draw/draw_affine.c | 184 |
1 files changed, 92 insertions, 92 deletions
diff --git a/draw/draw_affine.c b/draw/draw_affine.c index 64234bf5..8943214f 100644 --- a/draw/draw_affine.c +++ b/draw/draw_affine.c @@ -463,175 +463,176 @@ fz_paint_affine_color_near(byte *dp, byte *sp, int sw, int sh, int u, int v, int */ #define MY_EPSILON 0.001 -fz_matrix -fz_gridfit_matrix(fz_matrix m) +void +fz_gridfit_matrix(fz_matrix *m) { - if (fabsf(m.b) < FLT_EPSILON && fabsf(m.c) < FLT_EPSILON) + if (fabsf(m->b) < FLT_EPSILON && fabsf(m->c) < FLT_EPSILON) { - if (m.a > 0) + if (m->a > 0) { float f; /* Adjust left hand side onto pixel boundary */ - f = (float)(int)(m.e); - if (f - m.e > MY_EPSILON) + f = (float)(int)(m->e); + if (f - m->e > MY_EPSILON) f -= 1.0; /* Ensure it moves left */ - m.a += m.e - f; /* width gets wider as f <= m.e */ - m.e = f; + m->a += m->e - f; /* width gets wider as f <= m.e */ + m->e = f; /* Adjust right hand side onto pixel boundary */ - f = (float)(int)(m.a); - if (m.a - f > MY_EPSILON) + f = (float)(int)(m->a); + if (m->a - f > MY_EPSILON) f += 1.0; /* Ensure it moves right */ - m.a = f; + m->a = f; } - else if (m.a < 0) + else if (m->a < 0) { float f; /* Adjust right hand side onto pixel boundary */ - f = (float)(int)(m.e); - if (m.e - f > MY_EPSILON) + f = (float)(int)(m->e); + if (m->e - f > MY_EPSILON) f += 1.0; /* Ensure it moves right */ - m.a += m.e - f; /* width gets wider (more -ve) */ - m.e = f; + m->a += m->e - f; /* width gets wider (more -ve) */ + m->e = f; /* Adjust left hand side onto pixel boundary */ - f = (float)(int)(m.a); - if (f - m.a > MY_EPSILON) + f = (float)(int)(m->a); + if (f - m->a > MY_EPSILON) f -= 1.0; /* Ensure it moves left */ - m.a = f; + m->a = f; } - if (m.d > 0) + if (m->d > 0) { float f; /* Adjust top onto pixel boundary */ - f = (float)(int)(m.f); - if (f - m.f > MY_EPSILON) + f = (float)(int)(m->f); + if (f - m->f > MY_EPSILON) f -= 1.0; /* Ensure it moves upwards */ - m.d += m.f - f; /* width gets wider as f <= m.f */ - m.f = f; + m->d += m->f - f; /* width gets wider as f <= m.f */ + m->f = f; /* Adjust bottom onto pixel boundary */ - f = (float)(int)(m.d); - if (m.d - f > MY_EPSILON) + f = (float)(int)(m->d); + if (m->d - f > MY_EPSILON) f += 1.0; /* Ensure it moves down */ - m.d = f; + m->d = f; } - else if (m.d < 0) + else if (m->d < 0) { float f; /* Adjust bottom onto pixel boundary */ - f = (float)(int)(m.f); - if (m.f - f > MY_EPSILON) + f = (float)(int)(m->f); + if (m->f - f > MY_EPSILON) f += 1.0; /* Ensure it moves down */ - m.d += m.f - f; /* width gets wider (more -ve) */ - m.f = f; + m->d += m->f - f; /* width gets wider (more -ve) */ + m->f = f; /* Adjust top onto pixel boundary */ - f = (float)(int)(m.d); - if (f - m.d > MY_EPSILON) + f = (float)(int)(m->d); + if (f - m->d > MY_EPSILON) f -= 1.0; /* Ensure it moves up */ - m.d = f; + m->d = f; } } - else if (fabsf(m.a) < FLT_EPSILON && fabsf(m.d) < FLT_EPSILON) + else if (fabsf(m->a) < FLT_EPSILON && fabsf(m->d) < FLT_EPSILON) { - if (m.b > 0) + if (m->b > 0) { float f; /* Adjust left hand side onto pixel boundary */ - f = (float)(int)(m.f); - if (f - m.f > MY_EPSILON) + f = (float)(int)(m->f); + if (f - m->f > MY_EPSILON) f -= 1.0; /* Ensure it moves left */ - m.b += m.f - f; /* width gets wider as f <= m.f */ - m.f = f; + m->b += m->f - f; /* width gets wider as f <= m.f */ + m->f = f; /* Adjust right hand side onto pixel boundary */ - f = (float)(int)(m.b); - if (m.b - f > MY_EPSILON) + f = (float)(int)(m->b); + if (m->b - f > MY_EPSILON) f += 1.0; /* Ensure it moves right */ - m.b = f; + m->b = f; } - else if (m.b < 0) + else if (m->b < 0) { float f; /* Adjust right hand side onto pixel boundary */ - f = (float)(int)(m.f); - if (m.f - f > MY_EPSILON) + f = (float)(int)(m->f); + if (m->f - f > MY_EPSILON) f += 1.0; /* Ensure it moves right */ - m.b += m.f - f; /* width gets wider (more -ve) */ - m.f = f; + m->b += m->f - f; /* width gets wider (more -ve) */ + m->f = f; /* Adjust left hand side onto pixel boundary */ - f = (float)(int)(m.b); - if (f - m.b > MY_EPSILON) + f = (float)(int)(m->b); + if (f - m->b > MY_EPSILON) f -= 1.0; /* Ensure it moves left */ - m.b = f; + m->b = f; } - if (m.c > 0) + if (m->c > 0) { float f; /* Adjust top onto pixel boundary */ - f = (float)(int)(m.e); - if (f - m.e > MY_EPSILON) + f = (float)(int)(m->e); + if (f - m->e > MY_EPSILON) f -= 1.0; /* Ensure it moves upwards */ - m.c += m.e - f; /* width gets wider as f <= m.e */ - m.e = f; + m->c += m->e - f; /* width gets wider as f <= m.e */ + m->e = f; /* Adjust bottom onto pixel boundary */ - f = (float)(int)(m.c); - if (m.c - f > MY_EPSILON) + f = (float)(int)(m->c); + if (m->c - f > MY_EPSILON) f += 1.0; /* Ensure it moves down */ - m.c = f; + m->c = f; } - else if (m.c < 0) + else if (m->c < 0) { float f; /* Adjust bottom onto pixel boundary */ - f = (float)(int)(m.e); - if (m.e - f > MY_EPSILON) + f = (float)(int)(m->e); + if (m->e - f > MY_EPSILON) f += 1.0; /* Ensure it moves down */ - m.c += m.e - f; /* width gets wider (more -ve) */ - m.e = f; + m->c += m->e - f; /* width gets wider (more -ve) */ + m->e = f; /* Adjust top onto pixel boundary */ - f = (float)(int)(m.c); - if (f - m.c > MY_EPSILON) + f = (float)(int)(m->c); + if (f - m->c > MY_EPSILON) f -= 1.0; /* Ensure it moves up */ - m.c = f; + m->c = f; } } - return m; } /* Draw an image with an affine transform on destination */ static void -fz_paint_image_imp(fz_pixmap *dst, fz_bbox scissor, fz_pixmap *shape, fz_pixmap *img, fz_matrix ctm, byte *color, int alpha) +fz_paint_image_imp(fz_pixmap *dst, const fz_bbox *scissor, fz_pixmap *shape, fz_pixmap *img, const fz_matrix *ctm, byte *color, int alpha) { byte *dp, *sp, *hp; int u, v, fa, fb, fc, fd; int x, y, w, h; int sw, sh, n, hw; - fz_matrix inv; fz_bbox bbox; int dolerp; void (*paintfn)(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w, int n, int alpha, byte *color, byte *hp); + fz_matrix local_ctm = *ctm; + fz_rect rect; /* grid fit the image */ - ctm = fz_gridfit_matrix(ctm); + fz_gridfit_matrix(&local_ctm); /* turn on interpolation for upscaled and non-rectilinear transforms */ dolerp = 0; - if (!fz_is_rectilinear(ctm)) + if (!fz_is_rectilinear(&local_ctm)) dolerp = 1; - if (sqrtf(ctm.a * ctm.a + ctm.b * ctm.b) > img->w) + if (sqrtf(local_ctm.a * local_ctm.a + local_ctm.b * local_ctm.b) > img->w) dolerp = 1; - if (sqrtf(ctm.c * ctm.c + ctm.d * ctm.d) > img->h) + if (sqrtf(local_ctm.c * local_ctm.c + local_ctm.d * local_ctm.d) > img->h) dolerp = 1; /* except when we shouldn't, at large magnifications */ if (!img->interpolate) { - if (sqrtf(ctm.a * ctm.a + ctm.b * ctm.b) > img->w * 2) + if (sqrtf(local_ctm.a * local_ctm.a + local_ctm.b * local_ctm.b) > img->w * 2) dolerp = 0; - if (sqrtf(ctm.c * ctm.c + ctm.d * ctm.d) > img->h * 2) + if (sqrtf(local_ctm.c * local_ctm.c + local_ctm.d * local_ctm.d) > img->h * 2) dolerp = 0; } - bbox = fz_bbox_from_rect(fz_transform_rect(ctm, fz_unit_rect)); - bbox = fz_intersect_bbox(bbox, scissor); + rect = fz_unit_rect; + fz_bbox_from_rect(&bbox, fz_transform_rect(&rect, &local_ctm)); + fz_intersect_bbox(&bbox, scissor); x = bbox.x0; if (shape && shape->x > x) @@ -651,22 +652,21 @@ fz_paint_image_imp(fz_pixmap *dst, fz_bbox scissor, fz_pixmap *shape, fz_pixmap return; /* map from screen space (x,y) to image space (u,v) */ - inv = fz_scale(1.0f / img->w, 1.0f / img->h); - inv = fz_concat(inv, ctm); - inv = fz_invert_matrix(inv); + fz_pre_scale(&local_ctm, 1.0f / img->w, 1.0f / img->h); + fz_invert_matrix(&local_ctm, &local_ctm); - fa = (int)(inv.a *= 65536.0f); - fb = (int)(inv.b *= 65536.0f); - fc = (int)(inv.c *= 65536.0f); - fd = (int)(inv.d *= 65536.0f); - inv.e *= 65536.0f; - inv.f *= 65536.0f; + fa = (int)(local_ctm.a *= 65536.0f); + fb = (int)(local_ctm.b *= 65536.0f); + fc = (int)(local_ctm.c *= 65536.0f); + fd = (int)(local_ctm.d *= 65536.0f); + local_ctm.e *= 65536.0f; + local_ctm.f *= 65536.0f; /* Calculate initial texture positions. Do a half step to start. */ /* Bug 693021: Keep calculation in float for as long as possible to * avoid overflow. */ - u = (int)((inv.a * x) + (inv.c * y) + inv.e + ((inv.a + inv.c) * .5f)); - v = (int)((inv.b * x) + (inv.d * y) + inv.f + ((inv.b + inv.d) * .5f)); + u = (int)((local_ctm.a * x) + (local_ctm.c * y) + local_ctm.e + ((local_ctm.a + local_ctm.c) * .5f)); + v = (int)((local_ctm.b * x) + (local_ctm.d * y) + local_ctm.f + ((local_ctm.b + local_ctm.d) * .5f)); /* RJW: The following is voodoo. No idea why it works, but it gives * the best match between scaled/unscaled/interpolated/non-interpolated @@ -731,14 +731,14 @@ fz_paint_image_imp(fz_pixmap *dst, fz_bbox scissor, fz_pixmap *shape, fz_pixmap } void -fz_paint_image_with_color(fz_pixmap *dst, fz_bbox scissor, fz_pixmap *shape, fz_pixmap *img, fz_matrix ctm, byte *color) +fz_paint_image_with_color(fz_pixmap *dst, const fz_bbox *scissor, fz_pixmap *shape, fz_pixmap *img, const fz_matrix *ctm, byte *color) { assert(img->n == 1); fz_paint_image_imp(dst, scissor, shape, img, ctm, color, 255); } void -fz_paint_image(fz_pixmap *dst, fz_bbox scissor, fz_pixmap *shape, fz_pixmap *img, fz_matrix ctm, int alpha) +fz_paint_image(fz_pixmap *dst, const fz_bbox *scissor, fz_pixmap *shape, fz_pixmap *img, const fz_matrix *ctm, int alpha) { assert(dst->n == img->n || (dst->n == 4 && img->n == 2)); fz_paint_image_imp(dst, scissor, shape, img, ctm, NULL, alpha); |