summaryrefslogtreecommitdiff
path: root/src/cairo-path-fixed.c
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2009-08-04 13:59:03 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2009-08-06 10:16:02 +0100
commitcb30c1f367967e3395296a5d01a3eb9050635e3b (patch)
treedadaf4654a347ff7cfdb84ed4ff2044b6f3cbcc7 /src/cairo-path-fixed.c
parent85b688a3f6271427befca699de3a7a15162fc59e (diff)
[path] Extend identical lines.
If a subsequent PATH_OP is just a continuation of the previous line, i.e. it has the same gradient, then just replace the end-point of the previous line with the new point rather than adding a new operation. Surprisingly this occurs in the wild, but the main motivation is a future optimisation to reduce the number of intersections during stroke-to-path.
Diffstat (limited to 'src/cairo-path-fixed.c')
-rw-r--r--src/cairo-path-fixed.c31
1 files changed, 28 insertions, 3 deletions
diff --git a/src/cairo-path-fixed.c b/src/cairo-path-fixed.c
index 921c79e99..b71603087 100644
--- a/src/cairo-path-fixed.c
+++ b/src/cairo-path-fixed.c
@@ -445,22 +445,47 @@ _cairo_path_fixed_line_to (cairo_path_fixed_t *path,
if (! path->has_current_point) {
status = _cairo_path_fixed_move_to (path, point.x, point.y);
} else {
+ /* If the previous op was also a LINE_TO with the same gradient,
+ * then just change its end-point rather than adding a new op.
+ */
+ if (_cairo_path_last_op (path) == CAIRO_PATH_OP_LINE_TO) {
+ cairo_path_buf_t *buf;
+ cairo_point_t *p;
+ cairo_slope_t prev, self;
+
+ buf = cairo_path_tail (path);
+ if (likely (buf->num_points >= 2)) {
+ p = &buf->points[buf->num_points-2];
+ } else {
+ cairo_path_buf_t *prev_buf = cairo_path_buf_prev (buf);
+ p = &prev_buf->points[prev_buf->num_points - (2 - buf->num_points)];
+ }
+ _cairo_slope_init (&prev, p, &path->current_point);
+ _cairo_slope_init (&self, &path->current_point, &point);
+ if (_cairo_slope_equal (&prev, &self)) {
+ buf->points[buf->num_points - 1] = point;
+ status = CAIRO_STATUS_SUCCESS;
+ goto DONE;
+ }
+ }
+
status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_LINE_TO, &point, 1);
if (path->is_rectilinear) {
path->is_rectilinear = path->current_point.x == x ||
- path->current_point.y == y;
+ path->current_point.y == y;
path->maybe_fill_region &= path->is_rectilinear;
}
if (path->maybe_fill_region) {
path->maybe_fill_region = _cairo_fixed_is_integer (x) &&
- _cairo_fixed_is_integer (y);
+ _cairo_fixed_is_integer (y);
}
if (path->is_empty_fill) {
path->is_empty_fill = path->current_point.x == x &&
- path->current_point.y == y;
+ path->current_point.y == y;
}
}
+DONE:
path->current_point = point;
path->has_current_point = TRUE;