[path] Inline path ops during append_to_context()

By inlining the operations, and most significantly, precomputing the
combined user-to-backend matrix, we can achieve a speed up of over 50%,
which is a noticeable performance boost in swfdec - where append-to-path
accounts for over 35% [inclusive] of the time for a h/w accelerated
backend.
This commit is contained in:
Chris Wilson 2009-02-03 10:20:26 +00:00
parent d295942b9d
commit 005436758c

View file

@ -36,6 +36,7 @@
#include "cairoint.h"
#include "cairo-private.h"
#include "cairo-path-private.h"
#include "cairo-path-fixed-private.h"
@ -441,43 +442,82 @@ cairo_status_t
_cairo_path_append_to_context (const cairo_path_t *path,
cairo_t *cr)
{
int i;
cairo_path_data_t *p;
const cairo_path_data_t *p, *end;
cairo_fixed_t x1_fixed, y1_fixed;
cairo_fixed_t x2_fixed, y2_fixed;
cairo_fixed_t x3_fixed, y3_fixed;
cairo_matrix_t user_to_backend;
cairo_status_t status;
double x, y;
for (i=0; i < path->num_data; i += path->data[i].header.length) {
p = &path->data[i];
user_to_backend = cr->gstate->ctm;
cairo_matrix_multiply (&user_to_backend,
&cr->gstate->target->device_transform,
&user_to_backend);
end = &path->data[path->num_data];
for (p = &path->data[0]; p < end; p += p->header.length) {
switch (p->header.type) {
case CAIRO_PATH_MOVE_TO:
if (p->header.length < 2)
if (unlikely (p->header.length < 2))
return _cairo_error (CAIRO_STATUS_INVALID_PATH_DATA);
cairo_move_to (cr,
p[1].point.x, p[1].point.y);
x = p[1].point.x, y = p[1].point.y;
cairo_matrix_transform_point (&user_to_backend, &x, &y);
x1_fixed = _cairo_fixed_from_double (x);
y1_fixed = _cairo_fixed_from_double (y);
status = _cairo_path_fixed_move_to (cr->path, x1_fixed, y1_fixed);
break;
case CAIRO_PATH_LINE_TO:
if (p->header.length < 2)
if (unlikely (p->header.length < 2))
return _cairo_error (CAIRO_STATUS_INVALID_PATH_DATA);
cairo_line_to (cr,
p[1].point.x, p[1].point.y);
x = p[1].point.x, y = p[1].point.y;
cairo_matrix_transform_point (&user_to_backend, &x, &y);
x1_fixed = _cairo_fixed_from_double (x);
y1_fixed = _cairo_fixed_from_double (y);
status = _cairo_path_fixed_line_to (cr->path, x1_fixed, y1_fixed);
break;
case CAIRO_PATH_CURVE_TO:
if (p->header.length < 4)
if (unlikely (p->header.length < 4))
return _cairo_error (CAIRO_STATUS_INVALID_PATH_DATA);
cairo_curve_to (cr,
p[1].point.x, p[1].point.y,
p[2].point.x, p[2].point.y,
p[3].point.x, p[3].point.y);
x = p[1].point.x, y = p[1].point.y;
cairo_matrix_transform_point (&user_to_backend, &x, &y);
x1_fixed = _cairo_fixed_from_double (x);
y1_fixed = _cairo_fixed_from_double (y);
x = p[2].point.x, y = p[2].point.y;
cairo_matrix_transform_point (&user_to_backend, &x, &y);
x2_fixed = _cairo_fixed_from_double (x);
y2_fixed = _cairo_fixed_from_double (y);
x = p[3].point.x, y = p[3].point.y;
cairo_matrix_transform_point (&user_to_backend, &x, &y);
x3_fixed = _cairo_fixed_from_double (x);
y3_fixed = _cairo_fixed_from_double (y);
status = _cairo_path_fixed_curve_to (cr->path,
x1_fixed, y1_fixed,
x2_fixed, y2_fixed,
x3_fixed, y3_fixed);
break;
case CAIRO_PATH_CLOSE_PATH:
if (p->header.length < 1)
if (unlikely (p->header.length < 1))
return _cairo_error (CAIRO_STATUS_INVALID_PATH_DATA);
cairo_close_path (cr);
status = _cairo_path_fixed_close_path (cr->path);
break;
default:
return _cairo_error (CAIRO_STATUS_INVALID_PATH_DATA);
}
status = cairo_status (cr);
if (unlikely (status))
return status;
}