[cairo-commit] 4 commits - src/cairo.c src/cairoint.h src/cairo-path-fixed.c src/cairo-path-fixed-private.h
Chris Wilson
ickle at kemper.freedesktop.org
Sun Jul 5 07:05:14 PDT 2009
src/cairo-path-fixed-private.h | 31 +-
src/cairo-path-fixed.c | 541 ++++++++++++++++++-----------------------
src/cairo.c | 4
src/cairoint.h | 3
4 files changed, 266 insertions(+), 313 deletions(-)
New commits:
commit fbd88db938bf3bb03934795da9b3d184c4f43608
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Sun Jul 5 14:43:50 2009 +0100
[path] Don't include current-point in hash
As we don't strictly use the current-point in comparing paths, exclude it
from the hash. Similarly use the path content flags as a cheap means to
differentiate contents.
diff --git a/src/cairo-path-fixed.c b/src/cairo-path-fixed.c
index 539e953..0a55039 100644
--- a/src/cairo-path-fixed.c
+++ b/src/cairo-path-fixed.c
@@ -163,17 +163,10 @@ _cairo_path_fixed_init_copy (cairo_path_fixed_t *path,
unsigned long
_cairo_path_fixed_hash (const cairo_path_fixed_t *path)
{
- unsigned long hash = 0;
+ unsigned long hash = _CAIRO_HASH_INIT_VALUE;
const cairo_path_buf_t *buf;
int num_points, num_ops;
- hash = _cairo_hash_bytes (hash,
- &path->current_point,
- sizeof (path->current_point));
- hash = _cairo_hash_bytes (hash,
- &path->last_move_point,
- sizeof (path->last_move_point));
-
num_ops = num_points = 0;
cairo_path_foreach_buf_start (buf, path) {
hash = _cairo_hash_bytes (hash, buf->op,
@@ -220,6 +213,14 @@ _cairo_path_fixed_equal (const cairo_path_fixed_t *a,
if (a == b)
return TRUE;
+ /* use the flags to quickly differentiate based on contents */
+ if (a->has_curve_to != b->has_curve_to ||
+ a->is_region != b->is_region ||
+ a->is_box != b->is_box)
+ {
+ return FALSE;
+ }
+
num_ops_a = num_points_a = 0;
if (a != NULL) {
cairo_path_foreach_buf_start (buf_a, a) {
commit 73f8019fd2afd0ad41c2515bef9877348355d246
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Sun Jul 5 14:37:02 2009 +0100
[path] Use cairo_list_t instead of open-coding its own
Use the cairo_list_t and its style of iterators to improve the readability
of the cairo_path_buf_t management. Note the complications that arise from
the embedding of the initial buf -- however the macros do help make the
unusual manipulations more identifiable.
diff --git a/src/cairo-path-fixed-private.h b/src/cairo-path-fixed-private.h
index c7101e9..6bd09f7 100644
--- a/src/cairo-path-fixed-private.h
+++ b/src/cairo-path-fixed-private.h
@@ -38,6 +38,7 @@
#include "cairo-types-private.h"
#include "cairo-compiler-private.h"
+#include "cairo-list-private.h"
#define WATCH_PATH 0
#if WATCH_PATH
@@ -50,15 +51,16 @@ enum cairo_path_op {
CAIRO_PATH_OP_CURVE_TO = 2,
CAIRO_PATH_OP_CLOSE_PATH = 3
};
-/* we want to make sure a single byte is used for thie enum */
+
+/* we want to make sure a single byte is used for the enum */
typedef char cairo_path_op_t;
-/* make _cairo_path_fixed fit a 512 bytes. about 50 items */
-#define CAIRO_PATH_BUF_SIZE ((512 - 4 * sizeof (void*) - sizeof (cairo_path_buf_t)) \
+/* make _cairo_path_fixed fit into ~512 bytes -- about 50 items */
+#define CAIRO_PATH_BUF_SIZE ((512 - sizeof (cairo_path_buf_t)) \
/ (2 * sizeof (cairo_point_t) + sizeof (cairo_path_op_t)))
typedef struct _cairo_path_buf {
- struct _cairo_path_buf *next, *prev;
+ cairo_list_t link;
unsigned int buf_size;
unsigned int num_ops;
unsigned int num_points;
@@ -66,6 +68,7 @@ typedef struct _cairo_path_buf {
cairo_path_op_t *op;
cairo_point_t *points;
} cairo_path_buf_t;
+
typedef struct _cairo_path_buf_fixed {
cairo_path_buf_t base;
@@ -81,8 +84,7 @@ struct _cairo_path_fixed {
unsigned int is_box : 1;
unsigned int is_region : 1;
- cairo_path_buf_t *buf_tail;
- cairo_path_buf_fixed_t buf_head;
+ cairo_path_buf_fixed_t buf;
};
cairo_private unsigned long
diff --git a/src/cairo-path-fixed.c b/src/cairo-path-fixed.c
index 1cc86c5..539e953 100644
--- a/src/cairo-path-fixed.c
+++ b/src/cairo-path-fixed.c
@@ -40,7 +40,6 @@
#include "cairo-path-fixed-private.h"
-/* private functions */
static cairo_status_t
_cairo_path_fixed_add (cairo_path_fixed_t *path,
cairo_path_op_t op,
@@ -66,28 +65,39 @@ _cairo_path_buf_add_points (cairo_path_buf_t *buf,
const cairo_point_t *points,
int num_points);
+#define cairo_path_head(path__) (&(path__)->buf.base)
+#define cairo_path_tail(path__) cairo_path_buf_prev (cairo_path_head (path__))
+
+#define cairo_path_buf_next(pos__) \
+ cairo_list_entry ((pos__)->link.next, cairo_path_buf_t, link)
+#define cairo_path_buf_prev(pos__) \
+ cairo_list_entry ((pos__)->link.prev, cairo_path_buf_t, link)
+
+#define cairo_path_foreach_buf_start(pos__, path__) \
+ pos__ = cairo_path_head (path__); do
+#define cairo_path_foreach_buf_end(pos__, path__) \
+ while ((pos__ = cairo_path_buf_next (pos__)) != cairo_path_head (path__))
+
void
_cairo_path_fixed_init (cairo_path_fixed_t *path)
{
VG (VALGRIND_MAKE_MEM_UNDEFINED (path, sizeof (cairo_path_fixed_t)));
- path->buf_head.base.next = NULL;
- path->buf_head.base.prev = NULL;
- path->buf_tail = &path->buf_head.base;
+ cairo_list_init (&path->buf.base.link);
- path->buf_head.base.num_ops = 0;
- path->buf_head.base.num_points = 0;
- path->buf_head.base.buf_size = CAIRO_PATH_BUF_SIZE;
- path->buf_head.base.op = path->buf_head.op;
- path->buf_head.base.points = path->buf_head.points;
+ path->buf.base.num_ops = 0;
+ path->buf.base.num_points = 0;
+ path->buf.base.buf_size = CAIRO_PATH_BUF_SIZE;
+ path->buf.base.op = path->buf.op;
+ path->buf.base.points = path->buf.points;
path->current_point.x = 0;
path->current_point.y = 0;
+ path->last_move_point = path->current_point;
path->has_current_point = FALSE;
path->has_curve_to = FALSE;
path->is_region = TRUE;
path->is_box = TRUE;
- path->last_move_point = path->current_point;
}
cairo_status_t
@@ -106,18 +116,18 @@ _cairo_path_fixed_init_copy (cairo_path_fixed_t *path,
path->is_box = other->is_box;
path->is_region = other->is_region;
- path->buf_head.base.num_ops = other->buf_head.base.num_ops;
- path->buf_head.base.num_points = other->buf_head.base.num_points;
- path->buf_head.base.buf_size = other->buf_head.base.buf_size;
- memcpy (path->buf_head.op, other->buf_head.base.op,
- other->buf_head.base.num_ops * sizeof (other->buf_head.op[0]));
- memcpy (path->buf_head.points, other->buf_head.points,
- other->buf_head.base.num_points * sizeof (other->buf_head.points[0]));
+ path->buf.base.num_ops = other->buf.base.num_ops;
+ path->buf.base.num_points = other->buf.base.num_points;
+ path->buf.base.buf_size = other->buf.base.buf_size;
+ memcpy (path->buf.op, other->buf.base.op,
+ other->buf.base.num_ops * sizeof (other->buf.op[0]));
+ memcpy (path->buf.points, other->buf.points,
+ other->buf.base.num_points * sizeof (other->buf.points[0]));
num_points = num_ops = 0;
- for (other_buf = other->buf_head.base.next;
- other_buf != NULL;
- other_buf = other_buf->next)
+ for (other_buf = cairo_path_buf_next (cairo_path_head (other));
+ other_buf != cairo_path_head (other);
+ other_buf = cairo_path_buf_next (other_buf))
{
num_ops += other_buf->num_ops;
num_points += other_buf->num_points;
@@ -131,9 +141,9 @@ _cairo_path_fixed_init_copy (cairo_path_fixed_t *path,
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
}
- for (other_buf = other->buf_head.base.next;
- other_buf != NULL;
- other_buf = other_buf->next)
+ for (other_buf = cairo_path_buf_next (cairo_path_head (other));
+ other_buf != cairo_path_head (other);
+ other_buf = cairo_path_buf_next (other_buf))
{
memcpy (buf->op + buf->num_ops, other_buf->op,
other_buf->num_ops * sizeof (buf->op[0]));
@@ -158,26 +168,22 @@ _cairo_path_fixed_hash (const cairo_path_fixed_t *path)
int num_points, num_ops;
hash = _cairo_hash_bytes (hash,
- &path->current_point,
- sizeof (path->current_point));
+ &path->current_point,
+ sizeof (path->current_point));
hash = _cairo_hash_bytes (hash,
- &path->last_move_point,
- sizeof (path->last_move_point));
-
- num_ops = path->buf_head.base.num_ops;
- num_points = path->buf_head.base.num_points;
- for (buf = path->buf_head.base.next;
- buf != NULL;
- buf = buf->next)
- {
+ &path->last_move_point,
+ sizeof (path->last_move_point));
+
+ num_ops = num_points = 0;
+ cairo_path_foreach_buf_start (buf, path) {
hash = _cairo_hash_bytes (hash, buf->op,
- buf->num_ops * sizeof (buf->op[0]));
+ buf->num_ops * sizeof (buf->op[0]));
hash = _cairo_hash_bytes (hash, buf->points,
- buf->num_points * sizeof (buf->points[0]));
+ buf->num_points * sizeof (buf->points[0]));
num_ops += buf->num_ops;
num_points += buf->num_points;
- }
+ } cairo_path_foreach_buf_end (buf, path);
hash = _cairo_hash_bytes (hash, &num_ops, sizeof (num_ops));
hash = _cairo_hash_bytes (hash, &num_points, sizeof (num_points));
@@ -191,15 +197,11 @@ _cairo_path_fixed_size (const cairo_path_fixed_t *path)
const cairo_path_buf_t *buf;
int num_points, num_ops;
- num_ops = path->buf_head.base.num_ops;
- num_points = path->buf_head.base.num_points;
- for (buf = path->buf_head.base.next;
- buf != NULL;
- buf = buf->next)
- {
+ num_ops = num_points = 0;
+ cairo_path_foreach_buf_start (buf, path) {
num_ops += buf->num_ops;
num_points += buf->num_points;
- }
+ } cairo_path_foreach_buf_end (buf, path);
return num_ops * sizeof (buf->op[0]) +
num_points * sizeof (buf->points[0]);
@@ -218,31 +220,21 @@ _cairo_path_fixed_equal (const cairo_path_fixed_t *a,
if (a == b)
return TRUE;
+ num_ops_a = num_points_a = 0;
if (a != NULL) {
- num_ops_a = a->buf_head.base.num_ops;
- num_points_a = a->buf_head.base.num_points;
- for (buf_a = a->buf_head.base.next;
- buf_a != NULL;
- buf_a = buf_a->next)
- {
+ cairo_path_foreach_buf_start (buf_a, a) {
num_ops_a += buf_a->num_ops;
num_points_a += buf_a->num_points;
- }
- } else
- num_ops_a = num_points_a = 0;
+ } cairo_path_foreach_buf_end (buf_a, a);
+ }
+ num_ops_b = num_points_b = 0;
if (b != NULL) {
- num_ops_b = b->buf_head.base.num_ops;
- num_points_b = b->buf_head.base.num_points;
- for (buf_b = b->buf_head.base.next;
- buf_b != NULL;
- buf_b = buf_b->next)
- {
+ cairo_path_foreach_buf_start (buf_b, b) {
num_ops_b += buf_b->num_ops;
num_points_b += buf_b->num_points;
- }
- } else
- num_ops_b = num_points_b = 0;
+ } cairo_path_foreach_buf_end (buf_b, b);
+ }
if (num_ops_a == 0 && num_ops_b == 0)
return TRUE;
@@ -252,13 +244,13 @@ _cairo_path_fixed_equal (const cairo_path_fixed_t *a,
assert (a != NULL && b != NULL);
- buf_a = &a->buf_head.base;
+ buf_a = cairo_path_head (a);
num_points_a = buf_a->num_points;
num_ops_a = buf_a->num_ops;
ops_a = buf_a->op;
points_a = buf_a->points;
- buf_b = &b->buf_head.base;
+ buf_b = cairo_path_head (b);
num_points_b = buf_b->num_points;
num_ops_b = buf_b->num_ops;
ops_b = buf_b->op;
@@ -281,8 +273,8 @@ _cairo_path_fixed_equal (const cairo_path_fixed_t *a,
if (num_ops_a || num_points_a)
return FALSE;
- buf_a = buf_a->next;
- if (buf_a == NULL)
+ buf_a = cairo_path_buf_next (buf_a);
+ if (buf_a == cairo_path_head (a))
break;
num_points_a = buf_a->num_points;
@@ -299,8 +291,8 @@ _cairo_path_fixed_equal (const cairo_path_fixed_t *a,
if (num_ops_b || num_points_b)
return FALSE;
- buf_b = buf_b->next;
- if (buf_b == NULL)
+ buf_b = cairo_path_buf_next (buf_b);
+ if (buf_b == cairo_path_head (b))
break;
num_points_b = buf_b->num_points;
@@ -313,7 +305,6 @@ _cairo_path_fixed_equal (const cairo_path_fixed_t *a,
return TRUE;
}
-
cairo_path_fixed_t *
_cairo_path_fixed_create (void)
{
@@ -334,10 +325,10 @@ _cairo_path_fixed_fini (cairo_path_fixed_t *path)
{
cairo_path_buf_t *buf;
- buf = path->buf_head.base.next;
- while (buf) {
+ buf = cairo_path_buf_next (cairo_path_head (path));
+ while (buf != cairo_path_head (path)) {
cairo_path_buf_t *this = buf;
- buf = buf->next;
+ buf = cairo_path_buf_next (buf);
_cairo_path_buf_destroy (this);
}
@@ -351,6 +342,18 @@ _cairo_path_fixed_destroy (cairo_path_fixed_t *path)
free (path);
}
+static cairo_path_op_t
+_cairo_path_last_op (cairo_path_fixed_t *path)
+{
+ cairo_path_buf_t *buf;
+
+ buf = cairo_path_tail (path);
+ if (buf->num_ops == 0)
+ return -1;
+
+ return buf->op[buf->num_ops - 1];
+}
+
cairo_status_t
_cairo_path_fixed_move_to (cairo_path_fixed_t *path,
cairo_fixed_t x,
@@ -364,12 +367,11 @@ _cairo_path_fixed_move_to (cairo_path_fixed_t *path,
/* If the previous op was also a MOVE_TO, then just change its
* point rather than adding a new op. */
- if (path->buf_tail && path->buf_tail->num_ops &&
- path->buf_tail->op[path->buf_tail->num_ops - 1] == CAIRO_PATH_OP_MOVE_TO)
- {
- cairo_point_t *last_move_to_point;
- last_move_to_point = &path->buf_tail->points[path->buf_tail->num_points - 1];
- *last_move_to_point = point;
+ if (_cairo_path_last_op (path) == CAIRO_PATH_OP_MOVE_TO) {
+ cairo_path_buf_t *buf;
+
+ buf = cairo_path_tail (path);
+ buf->points[buf->num_points - 1] = point;
} else {
status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_MOVE_TO, &point, 1);
if (unlikely (status))
@@ -388,8 +390,8 @@ _cairo_path_fixed_move_to (cairo_path_fixed_t *path,
}
path->current_point = point;
+ path->last_move_point = point;
path->has_current_point = TRUE;
- path->last_move_point = path->current_point;
return CAIRO_STATUS_SUCCESS;
}
@@ -562,7 +564,7 @@ _cairo_path_fixed_add (cairo_path_fixed_t *path,
const cairo_point_t *points,
int num_points)
{
- cairo_path_buf_t *buf = path->buf_tail;
+ cairo_path_buf_t *buf = cairo_path_tail (path);
if (buf->num_ops + 1 > buf->buf_size ||
buf->num_points + num_points > 2 * buf->buf_size)
@@ -610,11 +612,7 @@ static void
_cairo_path_fixed_add_buf (cairo_path_fixed_t *path,
cairo_path_buf_t *buf)
{
- buf->next = NULL;
- buf->prev = path->buf_tail;
-
- path->buf_tail->next = buf;
- path->buf_tail = buf;
+ cairo_list_add_tail (&buf->link, &cairo_path_head (path)->link);
}
static cairo_path_buf_t *
@@ -630,8 +628,6 @@ _cairo_path_buf_create (int buf_size)
2 * sizeof (cairo_point_t),
sizeof (cairo_path_buf_t));
if (buf) {
- buf->next = NULL;
- buf->prev = NULL;
buf->num_ops = 0;
buf->num_points = 0;
buf->buf_size = buf_size;
@@ -683,16 +679,15 @@ _cairo_path_fixed_interpret (const cairo_path_fixed_t *path,
0, /* cairo_path_op_close_path */
};
cairo_status_t status;
- const cairo_path_buf_t *buf;
+ const cairo_path_buf_t *buf, *first;
cairo_bool_t forward = (dir == CAIRO_DIRECTION_FORWARD);
int step = forward ? 1 : -1;
- for (buf = forward ? &path->buf_head.base : path->buf_tail;
- buf;
- buf = forward ? buf->next : buf->prev)
- {
+ buf = first = forward ? cairo_path_head (path) : cairo_path_tail (path);
+ do {
cairo_point_t *points;
int start, stop, i;
+
if (forward) {
start = 0;
stop = buf->num_ops;
@@ -731,7 +726,7 @@ _cairo_path_fixed_interpret (const cairo_path_fixed_t *path,
if (forward)
points += num_args[(int) op];
}
- }
+ } while ((buf = forward ? cairo_path_buf_next (buf) : cairo_path_buf_prev (buf)) != first);
return CAIRO_STATUS_SUCCESS;
}
@@ -788,10 +783,10 @@ _cairo_path_fixed_offset_and_scale (cairo_path_fixed_t *path,
cairo_fixed_t scalex,
cairo_fixed_t scaley)
{
- cairo_path_buf_t *buf = &path->buf_head.base;
+ cairo_path_buf_t *buf;
unsigned int i;
- while (buf) {
+ cairo_path_foreach_buf_start (buf, path) {
for (i = 0; i < buf->num_points; i++) {
if (scalex != CAIRO_FIXED_ONE)
buf->points[i].x = _cairo_fixed_mul (buf->points[i].x, scalex);
@@ -801,9 +796,7 @@ _cairo_path_fixed_offset_and_scale (cairo_path_fixed_t *path,
buf->points[i].y = _cairo_fixed_mul (buf->points[i].y, scaley);
buf->points[i].y += offy;
}
-
- buf = buf->next;
- }
+ } cairo_path_foreach_buf_end (buf, path);
}
/**
@@ -833,8 +826,7 @@ _cairo_path_fixed_transform (cairo_path_fixed_t *path,
return;
}
- buf = &path->buf_head.base;
- while (buf) {
+ cairo_path_foreach_buf_start (buf, path) {
for (i = 0; i < buf->num_points; i++) {
dx = _cairo_fixed_to_double (buf->points[i].x);
dy = _cairo_fixed_to_double (buf->points[i].y);
@@ -844,9 +836,7 @@ _cairo_path_fixed_transform (cairo_path_fixed_t *path,
buf->points[i].x = _cairo_fixed_from_double (dx);
buf->points[i].y = _cairo_fixed_from_double (dy);
}
-
- buf = buf->next;
- }
+ } cairo_path_foreach_buf_end (buf, path);
}
cairo_bool_t
@@ -865,13 +855,9 @@ _cairo_path_fixed_is_equal (cairo_path_fixed_t *path,
path->last_move_point.y != other->last_move_point.y)
return FALSE;
- other_buf = &other->buf_head.base;
- for (path_buf = &path->buf_head.base;
- path_buf != NULL;
- path_buf = path_buf->next)
- {
- if (other_buf == NULL ||
- path_buf->num_ops != other_buf->num_ops ||
+ other_buf = cairo_path_head (other);
+ cairo_path_foreach_buf_start (path_buf, path) {
+ if (path_buf->num_ops != other_buf->num_ops ||
path_buf->num_points != other_buf->num_points ||
memcmp (path_buf->op, other_buf->op,
sizeof (cairo_path_op_t) * path_buf->num_ops) != 0 ||
@@ -880,8 +866,9 @@ _cairo_path_fixed_is_equal (cairo_path_fixed_t *path,
{
return FALSE;
}
- other_buf = other_buf->next;
- }
+ other_buf = cairo_path_buf_next (other_buf);
+ } cairo_path_foreach_buf_end (path_buf, path);
+
return TRUE;
}
@@ -985,7 +972,7 @@ _cairo_path_fixed_interpret_flat (const cairo_path_fixed_t *path,
cairo_bool_t
_cairo_path_fixed_is_empty (cairo_path_fixed_t *path)
{
- if (path->buf_head.base.num_ops == 0)
+ if (cairo_path_head (path)->num_ops == 0)
return TRUE;
return FALSE;
@@ -998,15 +985,11 @@ cairo_bool_t
_cairo_path_fixed_is_box (cairo_path_fixed_t *path,
cairo_box_t *box)
{
- cairo_path_buf_t *buf = &path->buf_head.base;
+ cairo_path_buf_t *buf = cairo_path_head (path);
if (! path->is_box)
return FALSE;
- /* We can't have more than one buf for this check */
- if (buf->next != NULL)
- return FALSE;
-
/* Do we have the right number of ops? */
if (buf->num_ops != 5 && buf->num_ops != 6)
return FALSE;
@@ -1077,11 +1060,12 @@ cairo_bool_t
_cairo_path_fixed_is_rectangle (cairo_path_fixed_t *path,
cairo_box_t *box)
{
- cairo_path_buf_t *buf = &path->buf_head.base;
+ cairo_path_buf_t *buf;
if (!_cairo_path_fixed_is_box (path, box))
return FALSE;
+ buf = cairo_path_head (path);
if (buf->points[0].y == buf->points[1].y)
return TRUE;
@@ -1092,7 +1076,7 @@ void
_cairo_path_fixed_iter_init (cairo_path_fixed_iter_t *iter,
cairo_path_fixed_t *path)
{
- iter->buf = &path->buf_head.base;
+ iter->buf = cairo_path_head (path);
iter->n_op = 0;
iter->n_point = 0;
}
@@ -1101,7 +1085,7 @@ static cairo_bool_t
_cairo_path_fixed_iter_next_op (cairo_path_fixed_iter_t *iter)
{
if (++iter->n_op >= iter->buf->num_ops) {
- iter->buf = iter->buf->next;
+ iter->buf = cairo_path_buf_next (iter->buf);
iter->n_op = 0;
iter->n_point = 0;
}
diff --git a/src/cairo.c b/src/cairo.c
index eb78b7b..3e59049 100644
--- a/src/cairo.c
+++ b/src/cairo.c
@@ -58,7 +58,7 @@ static const cairo_t _cairo_nil = {
FALSE, /* has_curve_to */
FALSE, /* is_box */
FALSE, /* is_region */
- NULL, {{NULL}} /* buf_tail, buf_head */
+ {{{NULL,NULL}}} /* link */
}}
};
commit a04e3726648c62a1385b67cfc16a785a468e1d13
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Sun Jul 5 09:21:47 2009 +0100
[path] Add path watch debugging
Simple debug macro to print the path to stderr during construction.
diff --git a/src/cairo-path-fixed-private.h b/src/cairo-path-fixed-private.h
index 5df1849..c7101e9 100644
--- a/src/cairo-path-fixed-private.h
+++ b/src/cairo-path-fixed-private.h
@@ -39,6 +39,11 @@
#include "cairo-types-private.h"
#include "cairo-compiler-private.h"
+#define WATCH_PATH 0
+#if WATCH_PATH
+#include <stdio.h>
+#endif
+
enum cairo_path_op {
CAIRO_PATH_OP_MOVE_TO = 0,
CAIRO_PATH_OP_LINE_TO = 1,
@@ -110,6 +115,10 @@ _cairo_path_fixed_iter_at_end (const cairo_path_fixed_iter_t *iter);
static inline cairo_bool_t
_cairo_path_fixed_is_region (cairo_path_fixed_t *path)
{
+#if WATCH_PATH
+ fprintf (stderr, "_cairo_path_fixed_is_region () = %s\n",
+ path->is_region ? "true" : "false");
+#endif
return path->is_region;
}
diff --git a/src/cairo-path-fixed.c b/src/cairo-path-fixed.c
index 5574e2d..1cc86c5 100644
--- a/src/cairo-path-fixed.c
+++ b/src/cairo-path-fixed.c
@@ -574,6 +574,32 @@ _cairo_path_fixed_add (cairo_path_fixed_t *path,
_cairo_path_fixed_add_buf (path, buf);
}
+ if (WATCH_PATH) {
+ const char *op_str[] = {
+ "move-to",
+ "line-to",
+ "curve-to",
+ "close-path",
+ };
+ char buf[1024];
+ int len = 0;
+ int i;
+
+ len += snprintf (buf + len, sizeof (buf), "[");
+ for (i = 0; i < num_points; i++) {
+ if (i != 0)
+ len += snprintf (buf + len, sizeof (buf), " ");
+ len += snprintf (buf + len, sizeof (buf), "(%f, %f)",
+ _cairo_fixed_to_double (points[i].x),
+ _cairo_fixed_to_double (points[i].y));
+ }
+ len += snprintf (buf + len, sizeof (buf), "]");
+
+ fprintf (stderr,
+ "_cairo_path_fixed_add (%s, %s)\n",
+ op_str[(int) op], buf);
+ }
+
_cairo_path_buf_add_op (buf, op);
_cairo_path_buf_add_points (buf, points, num_points);
commit 1645352bfb69cc6d43fcbf3c77b4da5693af322a
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Sun Jul 5 09:09:42 2009 +0100
[path] Evaluate is_box && is_region during construction
Whilst constructing the path, if the operations continue to be
axis-aligned lines, allow the is_box and is_region flags to persist. These
are set to false as soon as a curve-to is added, a diagonal or in the case
of is_region a non-integer point.
diff --git a/src/cairo-path-fixed-private.h b/src/cairo-path-fixed-private.h
index 0ade988..5df1849 100644
--- a/src/cairo-path-fixed-private.h
+++ b/src/cairo-path-fixed-private.h
@@ -73,6 +73,8 @@ struct _cairo_path_fixed {
cairo_point_t current_point;
unsigned int has_current_point : 1;
unsigned int has_curve_to : 1;
+ unsigned int is_box : 1;
+ unsigned int is_region : 1;
cairo_path_buf_t *buf_tail;
cairo_path_buf_fixed_t buf_head;
@@ -105,4 +107,10 @@ _cairo_path_fixed_iter_is_fill_box (cairo_path_fixed_iter_t *_iter,
cairo_private cairo_bool_t
_cairo_path_fixed_iter_at_end (const cairo_path_fixed_iter_t *iter);
+static inline cairo_bool_t
+_cairo_path_fixed_is_region (cairo_path_fixed_t *path)
+{
+ return path->is_region;
+}
+
#endif /* CAIRO_PATH_FIXED_PRIVATE_H */
diff --git a/src/cairo-path-fixed.c b/src/cairo-path-fixed.c
index f95c64a..5574e2d 100644
--- a/src/cairo-path-fixed.c
+++ b/src/cairo-path-fixed.c
@@ -42,10 +42,10 @@
/* private functions */
static cairo_status_t
-_cairo_path_fixed_add (cairo_path_fixed_t *path,
- cairo_path_op_t op,
- cairo_point_t *points,
- int num_points);
+_cairo_path_fixed_add (cairo_path_fixed_t *path,
+ cairo_path_op_t op,
+ const cairo_point_t *points,
+ int num_points);
static void
_cairo_path_fixed_add_buf (cairo_path_fixed_t *path,
@@ -62,9 +62,9 @@ _cairo_path_buf_add_op (cairo_path_buf_t *buf,
cairo_path_op_t op);
static void
-_cairo_path_buf_add_points (cairo_path_buf_t *buf,
- cairo_point_t *points,
- int num_points);
+_cairo_path_buf_add_points (cairo_path_buf_t *buf,
+ const cairo_point_t *points,
+ int num_points);
void
_cairo_path_fixed_init (cairo_path_fixed_t *path)
@@ -85,6 +85,8 @@ _cairo_path_fixed_init (cairo_path_fixed_t *path)
path->current_point.y = 0;
path->has_current_point = FALSE;
path->has_curve_to = FALSE;
+ path->is_region = TRUE;
+ path->is_box = TRUE;
path->last_move_point = path->current_point;
}
@@ -99,8 +101,10 @@ _cairo_path_fixed_init_copy (cairo_path_fixed_t *path,
path->current_point = other->current_point;
path->has_current_point = other->has_current_point;
- path->has_curve_to = other->has_curve_to;
path->last_move_point = other->last_move_point;
+ path->has_curve_to = other->has_curve_to;
+ path->is_box = other->is_box;
+ path->is_region = other->is_region;
path->buf_head.base.num_ops = other->buf_head.base.num_ops;
path->buf_head.base.num_points = other->buf_head.base.num_points;
@@ -370,6 +374,17 @@ _cairo_path_fixed_move_to (cairo_path_fixed_t *path,
status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_MOVE_TO, &point, 1);
if (unlikely (status))
return status;
+
+ if (path->has_current_point && path->is_box) {
+ /* a move-to is first an implicit close */
+ path->is_box = path->current_point.x == path->last_move_point.x ||
+ path->current_point.y == path->last_move_point.y;
+ path->is_region &= path->is_box;
+ }
+ if (path->is_region) {
+ path->is_region = _cairo_fixed_is_integer (x) &&
+ _cairo_fixed_is_integer (y);
+ }
}
path->current_point = point;
@@ -390,15 +405,13 @@ _cairo_path_fixed_rel_move_to (cairo_path_fixed_t *path,
cairo_fixed_t dx,
cairo_fixed_t dy)
{
- cairo_fixed_t x, y;
-
- if (! path->has_current_point)
+ if (unlikely (! path->has_current_point))
return _cairo_error (CAIRO_STATUS_NO_CURRENT_POINT);
- x = path->current_point.x + dx;
- y = path->current_point.y + dy;
+ return _cairo_path_fixed_move_to (path,
+ path->current_point.x + dx,
+ path->current_point.y + dy);
- return _cairo_path_fixed_move_to (path, x, y);
}
cairo_status_t
@@ -417,18 +430,25 @@ _cairo_path_fixed_line_to (cairo_path_fixed_t *path,
* explicitly calling into _cairo_path_fixed_move_to to ensure
* that the last_move_point state is updated properly.
*/
- if (! path->has_current_point)
+ if (! path->has_current_point) {
status = _cairo_path_fixed_move_to (path, point.x, point.y);
- else
+ } else {
status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_LINE_TO, &point, 1);
-
- if (unlikely (status))
- return status;
+ if (path->is_box) {
+ path->is_box = path->current_point.x == x ||
+ path->current_point.y == y;
+ path->is_region &= path->is_box;
+ }
+ if (path->is_region) {
+ path->is_region = _cairo_fixed_is_integer (x) &&
+ _cairo_fixed_is_integer (y);
+ }
+ }
path->current_point = point;
path->has_current_point = TRUE;
- return CAIRO_STATUS_SUCCESS;
+ return status;
}
cairo_status_t
@@ -436,15 +456,12 @@ _cairo_path_fixed_rel_line_to (cairo_path_fixed_t *path,
cairo_fixed_t dx,
cairo_fixed_t dy)
{
- cairo_fixed_t x, y;
-
- if (! path->has_current_point)
+ if (unlikely (! path->has_current_point))
return _cairo_error (CAIRO_STATUS_NO_CURRENT_POINT);
- x = path->current_point.x + dx;
- y = path->current_point.y + dy;
-
- return _cairo_path_fixed_line_to (path, x, y);
+ return _cairo_path_fixed_line_to (path,
+ path->current_point.x + dx,
+ path->current_point.y + dy);
}
cairo_status_t
@@ -456,17 +473,19 @@ _cairo_path_fixed_curve_to (cairo_path_fixed_t *path,
cairo_status_t status;
cairo_point_t point[3];
- point[0].x = x0; point[0].y = y0;
- point[1].x = x1; point[1].y = y1;
- point[2].x = x2; point[2].y = y2;
-
/* make sure subpaths are started properly */
if (! path->has_current_point) {
- status = _cairo_path_fixed_move_to (path, point[0].x, point[0].y);
+ status = _cairo_path_fixed_move_to (path, x0, y0);
if (unlikely (status))
return status;
}
+ if (x2 == path->current_point.x && y2 == path->current_point.y)
+ return _cairo_path_fixed_line_to (path, x2, y2);
+
+ point[0].x = x0; point[0].y = y0;
+ point[1].x = x1; point[1].y = y1;
+ point[2].x = x2; point[2].y = y2;
status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_CURVE_TO, point, 3);
if (unlikely (status))
return status;
@@ -474,6 +493,8 @@ _cairo_path_fixed_curve_to (cairo_path_fixed_t *path,
path->current_point = point[2];
path->has_current_point = TRUE;
path->has_curve_to = TRUE;
+ path->is_box = FALSE;
+ path->is_region = FALSE;
return CAIRO_STATUS_SUCCESS;
}
@@ -484,26 +505,24 @@ _cairo_path_fixed_rel_curve_to (cairo_path_fixed_t *path,
cairo_fixed_t dx1, cairo_fixed_t dy1,
cairo_fixed_t dx2, cairo_fixed_t dy2)
{
- cairo_fixed_t x0, y0;
- cairo_fixed_t x1, y1;
- cairo_fixed_t x2, y2;
-
- if (! path->has_current_point)
+ if (unlikely (! path->has_current_point))
return _cairo_error (CAIRO_STATUS_NO_CURRENT_POINT);
- x0 = path->current_point.x + dx0;
- y0 = path->current_point.y + dy0;
+ if (dx2 == 0 && dy2 == 0) {
+ return _cairo_path_fixed_line_to (path,
+ path->current_point.x,
+ path->current_point.y);
+ }
- x1 = path->current_point.x + dx1;
- y1 = path->current_point.y + dy1;
+ return _cairo_path_fixed_curve_to (path,
+ path->current_point.x + dx0,
+ path->current_point.y + dy0,
- x2 = path->current_point.x + dx2;
- y2 = path->current_point.y + dy2;
+ path->current_point.x + dx1,
+ path->current_point.y + dy1,
- return _cairo_path_fixed_curve_to (path,
- x0, y0,
- x1, y1,
- x2, y2);
+ path->current_point.x + dx2,
+ path->current_point.y + dy2);
}
cairo_status_t
@@ -518,13 +537,9 @@ _cairo_path_fixed_close_path (cairo_path_fixed_t *path)
if (unlikely (status))
return status;
- status = _cairo_path_fixed_move_to (path,
- path->last_move_point.x,
- path->last_move_point.y);
- if (unlikely (status))
- return status;
-
- return CAIRO_STATUS_SUCCESS;
+ return _cairo_path_fixed_move_to (path,
+ path->last_move_point.x,
+ path->last_move_point.y);
}
cairo_bool_t
@@ -542,10 +557,10 @@ _cairo_path_fixed_get_current_point (cairo_path_fixed_t *path,
}
static cairo_status_t
-_cairo_path_fixed_add (cairo_path_fixed_t *path,
- cairo_path_op_t op,
- cairo_point_t *points,
- int num_points)
+_cairo_path_fixed_add (cairo_path_fixed_t *path,
+ cairo_path_op_t op,
+ const cairo_point_t *points,
+ int num_points)
{
cairo_path_buf_t *buf = path->buf_tail;
@@ -616,25 +631,16 @@ _cairo_path_buf_add_op (cairo_path_buf_t *buf,
}
static void
-_cairo_path_buf_add_points (cairo_path_buf_t *buf,
- cairo_point_t *points,
- int num_points)
+_cairo_path_buf_add_points (cairo_path_buf_t *buf,
+ const cairo_point_t *points,
+ int num_points)
{
- int i;
-
- for (i=0; i < num_points; i++) {
- buf->points[buf->num_points++] = points[i];
- }
+ memcpy (buf->points + buf->num_points,
+ points,
+ sizeof (points[0]) * num_points);
+ buf->num_points += num_points;
}
-static int const num_args[] =
-{
- 1, /* cairo_path_move_to */
- 1, /* cairo_path_op_line_to */
- 3, /* cairo_path_op_curve_to */
- 0, /* cairo_path_op_close_path */
-};
-
cairo_status_t
_cairo_path_fixed_interpret (const cairo_path_fixed_t *path,
cairo_direction_t dir,
@@ -644,9 +650,14 @@ _cairo_path_fixed_interpret (const cairo_path_fixed_t *path,
cairo_path_fixed_close_path_func_t *close_path,
void *closure)
{
+ const uint8_t num_args[] = {
+ 1, /* cairo_path_move_to */
+ 1, /* cairo_path_op_line_to */
+ 3, /* cairo_path_op_curve_to */
+ 0, /* cairo_path_op_close_path */
+ };
cairo_status_t status;
const cairo_path_buf_t *buf;
- cairo_path_op_t op;
cairo_bool_t forward = (dir == CAIRO_DIRECTION_FORWARD);
int step = forward ? 1 : -1;
@@ -666,12 +677,11 @@ _cairo_path_fixed_interpret (const cairo_path_fixed_t *path,
points = buf->points + buf->num_points;
}
- for (i=start; i != stop; i += step) {
- op = buf->op[i];
+ for (i = start; i != stop; i += step) {
+ cairo_path_op_t op = buf->op[i];
- if (! forward) {
+ if (! forward)
points -= num_args[(int) op];
- }
switch (op) {
case CAIRO_PATH_OP_MOVE_TO:
@@ -683,18 +693,17 @@ _cairo_path_fixed_interpret (const cairo_path_fixed_t *path,
case CAIRO_PATH_OP_CURVE_TO:
status = (*curve_to) (closure, &points[0], &points[1], &points[2]);
break;
- case CAIRO_PATH_OP_CLOSE_PATH:
default:
+ ASSERT_NOT_REACHED;
+ case CAIRO_PATH_OP_CLOSE_PATH:
status = (*close_path) (closure);
break;
}
if (unlikely (status))
return status;
- if (forward) {
+ if (forward)
points += num_args[(int) op];
- }
-
}
}
@@ -705,16 +714,14 @@ static cairo_status_t
_append_move_to (void *closure,
const cairo_point_t *point)
{
- cairo_path_fixed_t *path = (cairo_path_fixed_t *) closure;
- return _cairo_path_fixed_move_to (path, point->x, point->y);
+ return _cairo_path_fixed_move_to (closure, point->x, point->y);
}
static cairo_status_t
_append_line_to (void *closure,
const cairo_point_t *point)
{
- cairo_path_fixed_t *path = (cairo_path_fixed_t *) closure;
- return _cairo_path_fixed_line_to (path, point->x, point->y);
+ return _cairo_path_fixed_line_to (closure, point->x, point->y);
}
static cairo_status_t
@@ -723,15 +730,16 @@ _append_curve_to (void *closure,
const cairo_point_t *p1,
const cairo_point_t *p2)
{
- cairo_path_fixed_t *path = (cairo_path_fixed_t *) closure;
- return _cairo_path_fixed_curve_to (path, p0->x, p0->y, p1->x, p1->y, p2->x, p2->y);
+ return _cairo_path_fixed_curve_to (closure,
+ p0->x, p0->y,
+ p1->x, p1->y,
+ p2->x, p2->y);
}
static cairo_status_t
_append_close_path (void *closure)
{
- cairo_path_fixed_t *path = (cairo_path_fixed_t *) closure;
- return _cairo_path_fixed_close_path (path);
+ return _cairo_path_fixed_close_path (closure);
}
cairo_status_t
@@ -825,6 +833,8 @@ _cairo_path_fixed_is_equal (cairo_path_fixed_t *path,
path->current_point.y != other->current_point.y ||
path->has_current_point != other->has_current_point ||
path->has_curve_to != other->has_curve_to ||
+ path->is_box != other->is_box ||
+ path->is_region != other->is_region ||
path->last_move_point.x != other->last_move_point.x ||
path->last_move_point.y != other->last_move_point.y)
return FALSE;
@@ -913,7 +923,6 @@ _cpf_close_path (void *closure)
return cpf->close_path (cpf->closure);
}
-
cairo_status_t
_cairo_path_fixed_interpret_flat (const cairo_path_fixed_t *path,
cairo_direction_t dir,
@@ -925,7 +934,7 @@ _cairo_path_fixed_interpret_flat (const cairo_path_fixed_t *path,
{
cpf_t flattener;
- if (!path->has_curve_to) {
+ if (! path->has_curve_to) {
return _cairo_path_fixed_interpret (path, dir,
move_to,
line_to,
@@ -965,6 +974,9 @@ _cairo_path_fixed_is_box (cairo_path_fixed_t *path,
{
cairo_path_buf_t *buf = &path->buf_head.base;
+ if (! path->is_box)
+ return FALSE;
+
/* We can't have more than one buf for this check */
if (buf->next != NULL)
return FALSE;
@@ -1174,91 +1186,3 @@ _cairo_path_fixed_iter_at_end (const cairo_path_fixed_iter_t *iter)
return FALSE;
}
-
-/* Closure for path region testing. Every move_to must be to integer
- * coordinates, there must be no curves, and every line_to or
- * close_path must represent an axis aligned line to an integer point.
- * We're relying on the path interpreter always sending a single
- * move_to at the start of any subpath, not receiving having any
- * superfluous move_tos, and the path intepreter bailing with our
- * first non-successful error. */
-typedef struct cairo_path_region_tester {
- cairo_point_t last_move_point;
- cairo_point_t current_point;
-} cprt_t;
-
-static cairo_status_t
-_cprt_line_to (void *closure,
- const cairo_point_t *p2)
-{
- cprt_t *self = closure;
- cairo_point_t *p1 = &self->current_point;
-
- if (p2->x == p1->x) {
- if (_cairo_fixed_is_integer (p2->y)) {
- p1->y = p2->y;
- return CAIRO_STATUS_SUCCESS;
- }
- } else if (p2->y == p1->y) {
- if (_cairo_fixed_is_integer (p2->x)) {
- p1->x = p2->x;
- return CAIRO_STATUS_SUCCESS;
- }
- }
-
- return CAIRO_INT_STATUS_UNSUPPORTED;
-}
-
-static cairo_status_t
-_cprt_close_path (void *closure)
-{
- cprt_t *self = closure;
- return _cprt_line_to (closure, &self->last_move_point);
-}
-
-static cairo_status_t
-_cprt_move_to (void *closure,
- const cairo_point_t *p)
-{
- cprt_t *self = closure;
- cairo_status_t status;
-
- status = _cprt_close_path (closure);
- if (status)
- return status;
-
- if (_cairo_fixed_is_integer (p->x) && _cairo_fixed_is_integer (p->y)) {
- self->current_point = *p;
- self->last_move_point = *p;
- return CAIRO_STATUS_SUCCESS;
- }
-
- return CAIRO_INT_STATUS_UNSUPPORTED;
-}
-
-/*
- * Check whether the given path is representable as a region.
- * That is, if the path contains only axis aligned lines between
- * integer coordinates in device space.
- */
-cairo_bool_t
-_cairo_path_fixed_is_region (cairo_path_fixed_t *path)
-{
- cprt_t cprt;
-
- if (path->has_curve_to)
- return FALSE;
-
- cprt.current_point.x = 0;
- cprt.current_point.y = 0;
- cprt.last_move_point.x = 0;
- cprt.last_move_point.y = 0;
-
- return _cairo_path_fixed_interpret (path,
- CAIRO_DIRECTION_FORWARD,
- _cprt_move_to,
- _cprt_line_to,
- NULL,
- _cprt_close_path,
- &cprt) == CAIRO_STATUS_SUCCESS;
-}
diff --git a/src/cairo.c b/src/cairo.c
index 4324af7..eb78b7b 100644
--- a/src/cairo.c
+++ b/src/cairo.c
@@ -56,6 +56,8 @@ static const cairo_t _cairo_nil = {
{ 0, 0 }, /* current point */
FALSE, /* has_current_point */
FALSE, /* has_curve_to */
+ FALSE, /* is_box */
+ FALSE, /* is_region */
NULL, {{NULL}} /* buf_tail, buf_head */
}}
};
diff --git a/src/cairoint.h b/src/cairoint.h
index fed81a5..cb30f6d 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -1617,9 +1617,6 @@ cairo_private cairo_bool_t
_cairo_path_fixed_is_rectangle (cairo_path_fixed_t *path,
cairo_box_t *box);
-cairo_private cairo_bool_t
-_cairo_path_fixed_is_region (cairo_path_fixed_t *path);
-
/* cairo-path-in-fill.c */
cairo_private void
_cairo_path_fixed_in_fill (cairo_path_fixed_t *path,
More information about the cairo-commit
mailing list