mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-01-04 20:20:19 +01:00
[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:
parent
92a18464ba
commit
901b0c9752
3 changed files with 68 additions and 43 deletions
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue