summaryrefslogtreecommitdiff
path: root/fitz/res_path.c
diff options
context:
space:
mode:
authorRobin Watts <robin.watts@artifex.com>2013-01-25 19:24:49 +0000
committerRobin Watts <robin.watts@artifex.com>2013-02-06 19:24:12 +0000
commitd3aa37962470253083714b5092a1ba759f674d47 (patch)
treeec60a0857cd3d44d3db5bc0c95aa69335b6b2d47 /fitz/res_path.c
parentc42dac496e0994c4253eb50ce67ceaec864ed379 (diff)
downloadmupdf-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 'fitz/res_path.c')
-rw-r--r--fitz/res_path.c68
1 files changed, 32 insertions, 36 deletions
diff --git a/fitz/res_path.c b/fitz/res_path.c
index 0f18b482..8bb5d778 100644
--- a/fitz/res_path.c
+++ b/fitz/res_path.c
@@ -243,36 +243,41 @@ fz_closepath(fz_context *ctx, fz_path *path)
path->items[path->len++].k = FZ_CLOSE_PATH;
}
-static inline fz_rect bound_expand(fz_rect r, fz_point p)
+static inline fz_rect *bound_expand(fz_rect *r, const fz_point *p)
{
- if (p.x < r.x0) r.x0 = p.x;
- if (p.y < r.y0) r.y0 = p.y;
- if (p.x > r.x1) r.x1 = p.x;
- if (p.y > r.y1) r.y1 = p.y;
+ if (p->x < r->x0) r->x0 = p->x;
+ if (p->y < r->y0) r->y0 = p->y;
+ if (p->x > r->x1) r->x1 = p->x;
+ if (p->y > r->y1) r->y1 = p->y;
return r;
}
-fz_rect
-fz_bound_path(fz_context *ctx, fz_path *path, fz_stroke_state *stroke, fz_matrix ctm)
+fz_rect *
+fz_bound_path(fz_context *ctx, fz_path *path, fz_stroke_state *stroke, const fz_matrix *ctm, fz_rect *r)
{
fz_point p;
- fz_rect r;
int i = 0;
/* If the path is empty, return the empty rectangle here - don't wait
* for it to be expanded in the stroked case below. */
if (path->len == 0)
- return fz_empty_rect;
+ {
+ *r = fz_empty_rect;
+ return r;
+ }
/* A path must start with a moveto - and if that's all there is
* then the path is empty. */
if (path->len == 3)
- return fz_empty_rect;
+ {
+ *r = fz_empty_rect;
+ return r;
+ }
p.x = path->items[1].v;
p.y = path->items[2].v;
- p = fz_transform_point(ctm, p);
- r.x0 = r.x1 = p.x;
- r.y0 = r.y1 = p.y;
+ fz_transform_point(&p, ctm);
+ r->x0 = r->x1 = p.x;
+ r->y0 = r->y1 = p.y;
while (i < path->len)
{
@@ -281,13 +286,13 @@ fz_bound_path(fz_context *ctx, fz_path *path, fz_stroke_state *stroke, fz_matrix
case FZ_CURVETO:
p.x = path->items[i++].v;
p.y = path->items[i++].v;
- r = bound_expand(r, fz_transform_point(ctm, p));
+ bound_expand(r, fz_transform_point(&p, ctm));
p.x = path->items[i++].v;
p.y = path->items[i++].v;
- r = bound_expand(r, fz_transform_point(ctm, p));
+ bound_expand(r, fz_transform_point(&p, ctm));
p.x = path->items[i++].v;
p.y = path->items[i++].v;
- r = bound_expand(r, fz_transform_point(ctm, p));
+ bound_expand(r, fz_transform_point(&p, ctm));
break;
case FZ_MOVETO:
if (i + 2 == path->len)
@@ -300,7 +305,7 @@ fz_bound_path(fz_context *ctx, fz_path *path, fz_stroke_state *stroke, fz_matrix
case FZ_LINETO:
p.x = path->items[i++].v;
p.y = path->items[i++].v;
- r = bound_expand(r, fz_transform_point(ctm, p));
+ bound_expand(r, fz_transform_point(&p, ctm));
break;
case FZ_CLOSE_PATH:
break;
@@ -309,14 +314,14 @@ fz_bound_path(fz_context *ctx, fz_path *path, fz_stroke_state *stroke, fz_matrix
if (stroke)
{
- r = fz_adjust_rect_for_stroke(r, stroke, ctm);
+ fz_adjust_rect_for_stroke(r, stroke, ctm);
}
return r;
}
-fz_rect
-fz_adjust_rect_for_stroke(fz_rect r, fz_stroke_state *stroke, fz_matrix ctm)
+fz_rect *
+fz_adjust_rect_for_stroke(fz_rect *r, fz_stroke_state *stroke, const fz_matrix *ctm)
{
float expand;
@@ -330,17 +335,16 @@ fz_adjust_rect_for_stroke(fz_rect r, fz_stroke_state *stroke, fz_matrix ctm)
if ((stroke->linejoin == FZ_LINEJOIN_MITER || stroke->linejoin == FZ_LINEJOIN_MITER_XPS) && stroke->miterlimit > 1)
expand *= stroke->miterlimit;
- r.x0 -= expand;
- r.y0 -= expand;
- r.x1 += expand;
- r.y1 += expand;
+ r->x0 -= expand;
+ r->y0 -= expand;
+ r->x1 += expand;
+ r->y1 += expand;
return r;
}
void
-fz_transform_path(fz_context *ctx, fz_path *path, fz_matrix ctm)
+fz_transform_path(fz_context *ctx, fz_path *path, const fz_matrix *ctm)
{
- fz_point p;
int k, i = 0;
while (i < path->len)
@@ -350,21 +354,13 @@ fz_transform_path(fz_context *ctx, fz_path *path, fz_matrix ctm)
case FZ_CURVETO:
for (k = 0; k < 3; k++)
{
- p.x = path->items[i].v;
- p.y = path->items[i+1].v;
- p = fz_transform_point(ctm, p);
- path->items[i].v = p.x;
- path->items[i+1].v = p.y;
+ fz_transform_point((fz_point *)(void *)&path->items[i].v, ctm);
i += 2;
}
break;
case FZ_MOVETO:
case FZ_LINETO:
- p.x = path->items[i].v;
- p.y = path->items[i+1].v;
- p = fz_transform_point(ctm, p);
- path->items[i].v = p.x;
- path->items[i+1].v = p.y;
+ fz_transform_point((fz_point *)(void *)&path->items[i].v, ctm);
i += 2;
break;
case FZ_CLOSE_PATH: