summaryrefslogtreecommitdiff
path: root/src/cairo-path-fixed.c
diff options
context:
space:
mode:
authorAndrea Canciani <ranma42@gmail.com>2010-10-21 15:14:31 +0200
committerAndrea Canciani <ranma42@gmail.com>2010-10-29 17:31:22 +0200
commit166453c1abf2279b884a4d878729fa4fcfa550cb (patch)
tree8d4c9a4d2849e11432413f4d3b324f78bc803f28 /src/cairo-path-fixed.c
parenta2ac91eb5f66f4c633abbcd6945f6015837ff211 (diff)
path: New path construction logic
Now move_to's are actually added to the path when followed by a drawing operation (line_to, curve_to or close_path). This is implemented by updating the current_point and setting the needs_move_to when a move_to operation is requested. Whenever a drawing operation is requested and the needs_move_to flag is set, a move_to is added before the drawing operation.
Diffstat (limited to 'src/cairo-path-fixed.c')
-rw-r--r--src/cairo-path-fixed.c111
1 files changed, 60 insertions, 51 deletions
diff --git a/src/cairo-path-fixed.c b/src/cairo-path-fixed.c
index 627d2cca5..d3c2c994c 100644
--- a/src/cairo-path-fixed.c
+++ b/src/cairo-path-fixed.c
@@ -98,15 +98,17 @@ _cairo_path_fixed_init (cairo_path_fixed_t *path)
path->current_point.x = 0;
path->current_point.y = 0;
path->last_move_point = path->current_point;
- path->has_last_move_point = FALSE;
+
path->has_current_point = FALSE;
+ path->needs_move_to = TRUE;
+ path->has_extents = FALSE;
path->has_curve_to = FALSE;
path->is_rectilinear = TRUE;
path->maybe_fill_region = TRUE;
path->is_empty_fill = TRUE;
- path->extents.p1.x = path->extents.p1.y = INT_MAX;
- path->extents.p2.x = path->extents.p2.y = INT_MIN;
+ path->extents.p1.x = path->extents.p1.y = 0;
+ path->extents.p2.x = path->extents.p2.y = 0;
}
cairo_status_t
@@ -127,8 +129,10 @@ _cairo_path_fixed_init_copy (cairo_path_fixed_t *path,
path->current_point = other->current_point;
path->last_move_point = other->last_move_point;
- path->has_last_move_point = other->has_last_move_point;
+
path->has_current_point = other->has_current_point;
+ path->needs_move_to = other->needs_move_to;
+ path->has_extents = other->has_extents;
path->has_curve_to = other->has_curve_to;
path->is_rectilinear = other->is_rectilinear;
path->maybe_fill_region = other->maybe_fill_region;
@@ -423,48 +427,54 @@ _cairo_path_fixed_move_to (cairo_path_fixed_t *path,
cairo_fixed_t x,
cairo_fixed_t y)
{
- cairo_status_t status;
- cairo_point_t point;
+ _cairo_path_fixed_new_sub_path (path);
- point.x = x;
- point.y = y;
+ path->has_current_point = TRUE;
+ path->current_point.x = x;
+ path->current_point.y = y;
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cairo_path_fixed_move_to_apply (cairo_path_fixed_t *path)
+{
+ if (likely (! path->needs_move_to))
+ return CAIRO_STATUS_SUCCESS;
- /* If the previous op was also a MOVE_TO, then just change its
- * point rather than adding a new op. */
- if (_cairo_path_fixed_last_op (path) == CAIRO_PATH_OP_MOVE_TO) {
- cairo_path_buf_t *buf;
+ path->needs_move_to = FALSE;
- buf = cairo_path_tail (path);
- buf->points[buf->num_points - 1] = point;
+ if (path->has_extents) {
+ _cairo_box_add_point (&path->extents, &path->current_point);
} else {
- status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_MOVE_TO, &point, 1);
- if (unlikely (status))
- return status;
+ _cairo_box_set (&path->extents, &path->current_point, &path->current_point);
+ path->has_extents = TRUE;
+ }
- if (path->has_current_point && path->is_rectilinear) {
- /* a move-to is first an implicit close */
- path->is_rectilinear = path->current_point.x == path->last_move_point.x ||
- path->current_point.y == path->last_move_point.y;
- path->maybe_fill_region &= path->is_rectilinear;
- }
- if (path->maybe_fill_region) {
- path->maybe_fill_region =
- _cairo_fixed_is_integer (path->last_move_point.x) &&
- _cairo_fixed_is_integer (path->last_move_point.y);
- }
+ if (path->maybe_fill_region) {
+ path->maybe_fill_region = _cairo_fixed_is_integer (path->current_point.x) &&
+ _cairo_fixed_is_integer (path->current_point.y);
}
- path->current_point = point;
- path->last_move_point = point;
- path->has_last_move_point = TRUE;
- path->has_current_point = TRUE;
+ path->last_move_point = path->current_point;
- return CAIRO_STATUS_SUCCESS;
+ return _cairo_path_fixed_add (path, CAIRO_PATH_OP_MOVE_TO, &path->current_point, 1);
}
void
_cairo_path_fixed_new_sub_path (cairo_path_fixed_t *path)
{
+ if (! path->needs_move_to) {
+ /* If the current subpath doesn't need_move_to, it contains at least one command */
+ if (path->is_rectilinear) {
+ /* Implicitly close for fill */
+ path->is_rectilinear = path->current_point.x == path->last_move_point.x ||
+ path->current_point.y == path->last_move_point.y;
+ path->maybe_fill_region &= path->is_rectilinear;
+ }
+ path->needs_move_to = TRUE;
+ }
+
path->has_current_point = FALSE;
}
@@ -501,6 +511,10 @@ _cairo_path_fixed_line_to (cairo_path_fixed_t *path,
if (! path->has_current_point)
return _cairo_path_fixed_move_to (path, point.x, point.y);
+ status = _cairo_path_fixed_move_to_apply (path);
+ if (unlikely (status))
+ return status;
+
/* If the previous op was but the initial MOVE_TO and this segment
* is degenerate, then we can simply skip this point. Note that
* a move-to followed by a degenerate line-to is a valid path for
@@ -556,11 +570,8 @@ _cairo_path_fixed_line_to (cairo_path_fixed_t *path,
}
path->current_point = point;
- if (path->has_last_move_point) {
- _cairo_path_fixed_extents_add (path, &path->last_move_point);
- path->has_last_move_point = FALSE;
- }
- _cairo_path_fixed_extents_add (path, &point);
+
+ _cairo_box_add_point (&path->extents, &point);
return _cairo_path_fixed_add (path, CAIRO_PATH_OP_LINE_TO, &point, 1);
}
@@ -590,10 +601,13 @@ _cairo_path_fixed_curve_to (cairo_path_fixed_t *path,
/* make sure subpaths are started properly */
if (! path->has_current_point) {
status = _cairo_path_fixed_move_to (path, x0, y0);
- if (unlikely (status))
- return status;
+ assert (status == CAIRO_STATUS_SUCCESS);
}
+ status = _cairo_path_fixed_move_to_apply (path);
+ if (unlikely (status))
+ return status;
+
/* If the previous op was a degenerate LINE_TO, drop it. */
if (_cairo_path_fixed_last_op (path) == CAIRO_PATH_OP_LINE_TO) {
const cairo_point_t *p;
@@ -609,22 +623,17 @@ _cairo_path_fixed_curve_to (cairo_path_fixed_t *path,
point[1].x = x1; point[1].y = y1;
point[2].x = x2; point[2].y = y2;
- path->current_point = point[2];
- path->has_current_point = TRUE;
- path->is_empty_fill = FALSE;
- path->has_curve_to = TRUE;
- path->is_rectilinear = FALSE;
- path->maybe_fill_region = FALSE;
-
/* coarse bounds */
- if (path->has_last_move_point) {
- _cairo_path_fixed_extents_add (path, &path->last_move_point);
- path->has_last_move_point = FALSE;
- }
_cairo_path_fixed_extents_add (path, &point[0]);
_cairo_path_fixed_extents_add (path, &point[1]);
_cairo_path_fixed_extents_add (path, &point[2]);
+ path->current_point = point[2];
+ path->has_curve_to = TRUE;
+ path->is_rectilinear = FALSE;
+ path->maybe_fill_region = FALSE;
+ path->is_empty_fill = FALSE;
+
return _cairo_path_fixed_add (path, CAIRO_PATH_OP_CURVE_TO, point, 3);
}