diff --git a/src/cairo-path-fill.c b/src/cairo-path-fill.c index 25420297f..f8e4ab023 100644 --- a/src/cairo-path-fill.c +++ b/src/cairo-path-fill.c @@ -214,7 +214,7 @@ static cairo_int_status_t _cairo_path_fixed_fill_rectangle (cairo_path_fixed_t *path, cairo_traps_t *traps) { - cairo_path_buf_t *buf = path->buf_head; + cairo_path_buf_t *buf = &path->buf_head.base; int final; /* Ensure the path has the operators we expect for a rectangular path. diff --git a/src/cairo-path-fixed-private.h b/src/cairo-path-fixed-private.h index 6e1300abe..f506c3449 100644 --- a/src/cairo-path-fixed-private.h +++ b/src/cairo-path-fixed-private.h @@ -46,18 +46,24 @@ enum cairo_path_op { typedef char cairo_path_op_t; /* make cairo_path_fixed fit a 512 bytes. about 50 items */ -#define CAIRO_PATH_BUF_SIZE ((512 - 12 * sizeof (void*)) \ - / (sizeof (cairo_point_t) + sizeof (cairo_path_op_t))) +#define CAIRO_PATH_BUF_SIZE ((512 - 4 * sizeof (void*) - 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; + int buf_size; int num_ops; int num_points; - cairo_path_op_t op[CAIRO_PATH_BUF_SIZE]; - cairo_point_t points[CAIRO_PATH_BUF_SIZE]; - + cairo_path_op_t *op; + cairo_point_t *points; } cairo_path_buf_t; +typedef struct _cairo_path_buf_fixed { + cairo_path_buf_t base; + + cairo_path_op_t op[CAIRO_PATH_BUF_SIZE]; + cairo_point_t points[2 * CAIRO_PATH_BUF_SIZE]; +} cairo_path_buf_fixed_t; struct _cairo_path_fixed { cairo_point_t last_move_point; @@ -65,8 +71,8 @@ struct _cairo_path_fixed { unsigned int has_current_point : 1; unsigned int has_curve_to : 1; - cairo_path_buf_t *buf_tail; - cairo_path_buf_t buf_head[1]; + cairo_path_buf_t *buf_tail; + cairo_path_buf_fixed_t buf_head; }; #endif /* CAIRO_PATH_FIXED_PRIVATE_H */ diff --git a/src/cairo-path-fixed.c b/src/cairo-path-fixed.c index 6aaa2eef6..05f8144bf 100644 --- a/src/cairo-path-fixed.c +++ b/src/cairo-path-fixed.c @@ -52,7 +52,7 @@ _cairo_path_fixed_add_buf (cairo_path_fixed_t *path, cairo_path_buf_t *buf); static cairo_path_buf_t * -_cairo_path_buf_create (void); +_cairo_path_buf_create (int buf_size); static void _cairo_path_buf_destroy (cairo_path_buf_t *buf); @@ -69,12 +69,15 @@ _cairo_path_buf_add_points (cairo_path_buf_t *buf, void _cairo_path_fixed_init (cairo_path_fixed_t *path) { - path->buf_head->next = NULL; - path->buf_head->prev = NULL; - path->buf_tail = path->buf_head; + path->buf_head.base.next = NULL; + path->buf_head.base.prev = NULL; + path->buf_tail = &path->buf_head.base; - path->buf_head->num_ops = 0; - path->buf_head->num_points = 0; + 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->current_point.x = 0; path->current_point.y = 0; @@ -90,27 +93,32 @@ _cairo_path_fixed_init_copy (cairo_path_fixed_t *path, cairo_path_buf_t *buf, *other_buf; _cairo_path_fixed_init (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->buf_head->num_ops = other->buf_head->num_ops; - path->buf_head->num_points = other->buf_head->num_points; - memcpy (path->buf_head->op, other->buf_head->op, - other->buf_head->num_ops * sizeof (other->buf_head->op[0])); - memcpy (path->buf_head->points, other->buf_head->points, - other->buf_head->num_points * sizeof (other->buf_head->points[0])); - for (other_buf = other->buf_head->next; + 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])); + for (other_buf = other->buf_head.base.next; other_buf; other_buf = other_buf->next) { - buf = _cairo_path_buf_create (); + buf = _cairo_path_buf_create (other_buf->buf_size); if (buf == NULL) { _cairo_path_fixed_fini (path); return _cairo_error (CAIRO_STATUS_NO_MEMORY); } - memcpy (buf, other_buf, sizeof (cairo_path_buf_t)); + memcpy (buf->op, other_buf->op, + buf->num_ops * sizeof (buf->op[0])); + memcpy (buf->points, other_buf->points, + buf->num_points * sizeof (buf->points[0])); _cairo_path_fixed_add_buf (path, buf); } @@ -137,17 +145,17 @@ _cairo_path_fixed_fini (cairo_path_fixed_t *path) { cairo_path_buf_t *buf; - buf = path->buf_head->next; + buf = path->buf_head.base.next; while (buf) { cairo_path_buf_t *this = buf; buf = buf->next; _cairo_path_buf_destroy (this); } - path->buf_head->next = NULL; - path->buf_head->prev = NULL; - path->buf_tail = path->buf_head; - path->buf_head->num_ops = 0; - path->buf_head->num_points = 0; + path->buf_head.base.next = NULL; + path->buf_head.base.prev = NULL; + path->buf_tail = &path->buf_head.base; + path->buf_head.base.num_ops = 0; + path->buf_head.base.num_points = 0; path->has_current_point = FALSE; path->has_curve_to = FALSE; @@ -360,20 +368,20 @@ _cairo_path_fixed_add (cairo_path_fixed_t *path, cairo_point_t *points, int num_points) { - if ((unsigned int) path->buf_tail->num_ops + 1 > CAIRO_PATH_BUF_SIZE || - (unsigned int) path->buf_tail->num_points + num_points > CAIRO_PATH_BUF_SIZE) - { - cairo_path_buf_t *buf; + cairo_path_buf_t *buf = path->buf_tail; - buf = _cairo_path_buf_create (); + if (buf->num_ops + 1 > buf->buf_size || + buf->num_points + num_points > 2 * buf->buf_size) + { + buf = _cairo_path_buf_create (buf->buf_size * 2); if (buf == NULL) return _cairo_error (CAIRO_STATUS_NO_MEMORY); _cairo_path_fixed_add_buf (path, buf); } - _cairo_path_buf_add_op (path->buf_tail, op); - _cairo_path_buf_add_points (path->buf_tail, points, num_points); + _cairo_path_buf_add_op (buf, op); + _cairo_path_buf_add_points (buf, points, num_points); return CAIRO_STATUS_SUCCESS; } @@ -390,17 +398,23 @@ _cairo_path_fixed_add_buf (cairo_path_fixed_t *path, } static cairo_path_buf_t * -_cairo_path_buf_create (void) +_cairo_path_buf_create (int buf_size) { cairo_path_buf_t *buf; - buf = malloc (sizeof (cairo_path_buf_t)); - + buf = _cairo_malloc_ab_plus_c (buf_size, + sizeof (cairo_path_op_t) + + 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; + + buf->op = (cairo_path_op_t *) (buf + 1); + buf->points = (cairo_point_t *) (buf->op + buf_size); } return buf; @@ -454,7 +468,7 @@ _cairo_path_fixed_interpret (cairo_path_fixed_t *path, cairo_bool_t forward = (dir == CAIRO_DIRECTION_FORWARD); int step = forward ? 1 : -1; - for (buf = forward ? path->buf_head : path->buf_tail; + for (buf = forward ? &path->buf_head.base : path->buf_tail; buf; buf = forward ? buf->next : buf->prev) { @@ -512,7 +526,7 @@ _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; + cairo_path_buf_t *buf = &path->buf_head.base; int i; while (buf) { @@ -569,14 +583,19 @@ _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; - for (path_buf = path->buf_head; path_buf != NULL; path_buf = path_buf->next) { + 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 || path_buf->num_points != other_buf->num_points || memcmp (path_buf->op, other_buf->op, path_buf->num_ops) != 0 || memcmp (path_buf->points, other_buf->points, path_buf->num_points != 0)) + { return FALSE; + } other_buf = other_buf->next; } return TRUE;