[cairo-path-fixed] Exponentially enlarge cairo_path_buf_t.

Allocate subsequent path bufs twice as large as the previous buf,
whilst still embedding a small initial buf into cairo_path_fixed_t
that handles the most frequent usage.
This commit is contained in:
Chris Wilson 2007-11-04 11:55:25 +00:00
parent 92a18464ba
commit 901b0c9752
3 changed files with 68 additions and 43 deletions

View file

@ -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.

View file

@ -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 */

View file

@ -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;