[cairo-path-stroke] Avoid allocation for single rectangle.

The most common case for path stroking is a single rectangle, so embed
sufficient segments into the stroker to avoid an extra allocation.
This commit is contained in:
Chris Wilson 2008-05-07 09:20:17 +01:00
parent ba6b2d092a
commit d9b2e8f004

View file

@ -1191,9 +1191,10 @@ typedef struct _cairo_rectilinear_stroker
cairo_point_t current_point;
cairo_point_t first_point;
cairo_bool_t open_sub_path;
cairo_line_t *segments;
int segments_size;
int num_segments;
int segments_size;
cairo_line_t *segments;
cairo_line_t segments_embedded[8]; /* common case is a single rectangle */
} cairo_rectilinear_stroker_t;
static void
@ -1206,15 +1207,16 @@ _cairo_rectilinear_stroker_init (cairo_rectilinear_stroker_t *stroker,
_cairo_fixed_from_double (stroke_style->line_width / 2.0);
stroker->traps = traps;
stroker->open_sub_path = FALSE;
stroker->segments = NULL;
stroker->segments_size = 0;
stroker->segments = stroker->segments_embedded;
stroker->segments_size = ARRAY_LENGTH (stroker->segments_embedded);
stroker->num_segments = 0;
}
static void
_cairo_rectilinear_stroker_fini (cairo_rectilinear_stroker_t *stroker)
{
free (stroker->segments);
if (stroker->segments != stroker->segments_embedded)
free (stroker->segments);
}
static cairo_status_t
@ -1222,18 +1224,24 @@ _cairo_rectilinear_stroker_add_segment (cairo_rectilinear_stroker_t *stroker,
cairo_point_t *p1,
cairo_point_t *p2)
{
int new_size;
cairo_line_t *new_segments;
if (stroker->num_segments == stroker->segments_size) {
new_size = stroker->segments_size * 2;
/* Common case is one rectangle of exactly 4 segments. */
if (new_size == 0)
new_size = 4;
new_segments = _cairo_realloc_ab (stroker->segments,
new_size, sizeof (cairo_line_t));
if (new_segments == NULL)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
int new_size = stroker->segments_size * 2;
cairo_line_t *new_segments;
if (stroker->segments == stroker->segments_embedded) {
new_segments = _cairo_malloc_ab (new_size, sizeof (cairo_line_t));
if (new_segments == NULL)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
memcpy (new_segments, stroker->segments,
stroker->num_segments * sizeof (cairo_line_t));
} else {
new_segments = _cairo_realloc_ab (stroker->segments,
new_size, sizeof (cairo_line_t));
if (new_segments == NULL)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
}
stroker->segments_size = new_size;
stroker->segments = new_segments;
@ -1390,8 +1398,7 @@ _cairo_rectilinear_stroker_line_to (void *closure,
if (a->x == b->x && a->y == b->y)
return CAIRO_STATUS_SUCCESS;
status = _cairo_rectilinear_stroker_add_segment (stroker,
a, b);
status = _cairo_rectilinear_stroker_add_segment (stroker, a, b);
stroker->current_point = *point;
stroker->open_sub_path = TRUE;