diff options
Diffstat (limited to 'src/cairo-path-data.c')
-rw-r--r-- | src/cairo-path-data.c | 239 |
1 files changed, 196 insertions, 43 deletions
diff --git a/src/cairo-path-data.c b/src/cairo-path-data.c index 84d26554..3bb5fff7 100644 --- a/src/cairo-path-data.c +++ b/src/cairo-path-data.c @@ -34,6 +34,8 @@ */ #include "cairo-path-data-private.h" +#include "cairo-path-fixed-private.h" +#include "cairo-gstate-private.h" cairo_path_t _cairo_path_nil = { NULL, 0 }; @@ -41,56 +43,113 @@ _cairo_path_nil = { NULL, 0 }; /* Closure for path interpretation. */ typedef struct cairo_path_data_count { int count; + double tolerance; + cairo_point_t current_point; } cpdc_t; -static void -_cpdc_move_to (void *closure, double x, double y) +static cairo_status_t +_cpdc_move_to (void *closure, cairo_point_t *point) { cpdc_t *cpdc = closure; cpdc->count += 2; + + cpdc->current_point = *point; + + return CAIRO_STATUS_SUCCESS; } -static void -_cpdc_line_to (void *closure, double x, double y) +static cairo_status_t +_cpdc_line_to (void *closure, cairo_point_t *point) { cpdc_t *cpdc = closure; cpdc->count += 2; + + cpdc->current_point = *point; + + return CAIRO_STATUS_SUCCESS; } -static void -_cpdc_curve_to (void *closure, - double x1, double y1, - double x2, double y2, - double x3, double y3) +static cairo_status_t +_cpdc_curve_to (void *closure, + cairo_point_t *p1, + cairo_point_t *p2, + cairo_point_t *p3) { cpdc_t *cpdc = closure; cpdc->count += 4; + + cpdc->current_point = *p3; + + return CAIRO_STATUS_SUCCESS; } -static void +static cairo_status_t +_cpdc_curve_to_flatten (void *closure, + cairo_point_t *p1, + cairo_point_t *p2, + cairo_point_t *p3) +{ + cpdc_t *cpdc = closure; + cairo_status_t status; + cairo_spline_t spline; + int i; + + cairo_point_t *p0 = &cpdc->current_point; + + status = _cairo_spline_init (&spline, p0, p1, p2, p3); + if (status == CAIRO_INT_STATUS_DEGENERATE) + return CAIRO_STATUS_SUCCESS; + + status = _cairo_spline_decompose (&spline, cpdc->tolerance); + if (status) + return status; + + for (i=1; i < spline.num_points; i++) + _cpdc_line_to (cpdc, &spline.points[i]); + + cpdc->current_point = *p3; + + return CAIRO_STATUS_SUCCESS; +} + +static cairo_status_t _cpdc_close_path (void *closure) { cpdc_t *cpdc = closure; cpdc->count += 1; + + cpdc->current_point.x = 0; + cpdc->current_point.y = 0; + + return CAIRO_STATUS_SUCCESS; } static int -_cairo_path_data_count (cairo_gstate_t *gstate, cairo_bool_t flatten) +_cairo_path_data_count (cairo_path_t *path, + cairo_path_fixed_t *path_fixed, + double tolerance, + cairo_bool_t flatten) { cpdc_t cpdc; cpdc.count = 0; - - _cairo_gstate_interpret_path (gstate, - _cpdc_move_to, - _cpdc_line_to, - flatten ? NULL : _cpdc_curve_to, - _cpdc_close_path, - &cpdc); + cpdc.tolerance = tolerance; + cpdc.current_point.x = 0; + cpdc.current_point.y = 0; + + _cairo_path_fixed_interpret (path_fixed, + CAIRO_DIRECTION_FORWARD, + _cpdc_move_to, + _cpdc_line_to, + flatten ? + _cpdc_curve_to_flatten : + _cpdc_curve_to, + _cpdc_close_path, + &cpdc); return cpdc.count; } @@ -98,13 +157,22 @@ _cairo_path_data_count (cairo_gstate_t *gstate, cairo_bool_t flatten) /* Closure for path interpretation. */ typedef struct cairo_path_data_populate { cairo_path_data_t *data; + cairo_matrix_t *ctm_inverse; + double tolerance; + cairo_point_t current_point; } cpdp_t; -static void -_cpdp_move_to (void *closure, double x, double y) +static cairo_status_t +_cpdp_move_to (void *closure, cairo_point_t *point) { cpdp_t *cpdp = closure; cairo_path_data_t *data = cpdp->data; + double x, y; + + x = _cairo_fixed_to_double (point->x); + y = _cairo_fixed_to_double (point->y); + + cairo_matrix_transform_point (cpdp->ctm_inverse, &x, &y); data->header.type = CAIRO_PATH_MOVE_TO; data->header.length = 2; @@ -114,13 +182,23 @@ _cpdp_move_to (void *closure, double x, double y) data[1].point.y = y; cpdp->data += data->header.length; + + cpdp->current_point = *point; + + return CAIRO_STATUS_SUCCESS; } -static void -_cpdp_line_to (void *closure, double x, double y) +static cairo_status_t +_cpdp_line_to (void *closure, cairo_point_t *point) { cpdp_t *cpdp = closure; cairo_path_data_t *data = cpdp->data; + double x, y; + + x = _cairo_fixed_to_double (point->x); + y = _cairo_fixed_to_double (point->y); + + cairo_matrix_transform_point (cpdp->ctm_inverse, &x, &y); data->header.type = CAIRO_PATH_LINE_TO; data->header.length = 2; @@ -130,16 +208,35 @@ _cpdp_line_to (void *closure, double x, double y) data[1].point.y = y; cpdp->data += data->header.length; + + cpdp->current_point = *point; + + return CAIRO_STATUS_SUCCESS; } -static void -_cpdp_curve_to (void *closure, - double x1, double y1, - double x2, double y2, - double x3, double y3) +static cairo_status_t +_cpdp_curve_to (void *closure, + cairo_point_t *p1, + cairo_point_t *p2, + cairo_point_t *p3) { cpdp_t *cpdp = closure; cairo_path_data_t *data = cpdp->data; + double x1, y1; + double x2, y2; + double x3, y3; + + x1 = _cairo_fixed_to_double (p1->x); + y1 = _cairo_fixed_to_double (p1->y); + cairo_matrix_transform_point (cpdp->ctm_inverse, &x1, &y1); + + x2 = _cairo_fixed_to_double (p2->x); + y2 = _cairo_fixed_to_double (p2->y); + cairo_matrix_transform_point (cpdp->ctm_inverse, &x2, &y2); + + x3 = _cairo_fixed_to_double (p3->x); + y3 = _cairo_fixed_to_double (p3->y); + cairo_matrix_transform_point (cpdp->ctm_inverse, &x3, &y3); data->header.type = CAIRO_PATH_CURVE_TO; data->header.length = 4; @@ -155,9 +252,42 @@ _cpdp_curve_to (void *closure, data[3].point.y = y3; cpdp->data += data->header.length; + + cpdp->current_point = *p3; + + return CAIRO_STATUS_SUCCESS; } -static void +static cairo_status_t +_cpdp_curve_to_flatten (void *closure, + cairo_point_t *p1, + cairo_point_t *p2, + cairo_point_t *p3) +{ + cpdp_t *cpdp = closure; + cairo_status_t status; + cairo_spline_t spline; + int i; + + cairo_point_t *p0 = &cpdp->current_point; + + status = _cairo_spline_init (&spline, p0, p1, p2, p3); + if (status == CAIRO_INT_STATUS_DEGENERATE) + return CAIRO_STATUS_SUCCESS; + + status = _cairo_spline_decompose (&spline, cpdp->tolerance); + if (status) + return status; + + for (i=1; i < spline.num_points; i++) + _cpdp_line_to (cpdp, &spline.points[i]); + + cpdp->current_point = *p3; + + return CAIRO_STATUS_SUCCESS; +} + +static cairo_status_t _cpdp_close_path (void *closure) { cpdp_t *cpdp = closure; @@ -167,30 +297,47 @@ _cpdp_close_path (void *closure) data->header.length = 1; cpdp->data += data->header.length; + + cpdp->current_point.x = 0; + cpdp->current_point.y = 0; + + return CAIRO_STATUS_SUCCESS; } static void _cairo_path_data_populate (cairo_path_t *path, - cairo_gstate_t *gstate, + cairo_path_fixed_t *path_fixed, + cairo_matrix_t *ctm_inverse, + double tolerance, cairo_bool_t flatten) { cpdp_t cpdp; cpdp.data = path->data; - - _cairo_gstate_interpret_path (gstate, - _cpdp_move_to, - _cpdp_line_to, - flatten ? NULL : _cpdp_curve_to, - _cpdp_close_path, - &cpdp); + cpdp.ctm_inverse = ctm_inverse; + cpdp.tolerance = tolerance; + cpdp.current_point.x = 0; + cpdp.current_point.y = 0; + + _cairo_path_fixed_interpret (path_fixed, + CAIRO_DIRECTION_FORWARD, + _cpdp_move_to, + _cpdp_line_to, + flatten ? + _cpdp_curve_to_flatten : + _cpdp_curve_to, + _cpdp_close_path, + &cpdp); /* Sanity check the count */ assert (cpdp.data - path->data == path->num_data); } static cairo_path_t * -_cairo_path_data_create_real (cairo_gstate_t *gstate, cairo_bool_t flatten) +_cairo_path_data_create_real (cairo_path_fixed_t *path_fixed, + cairo_matrix_t *ctm_inverse, + double tolerance, + cairo_bool_t flatten) { cairo_path_t *path; @@ -198,7 +345,8 @@ _cairo_path_data_create_real (cairo_gstate_t *gstate, cairo_bool_t flatten) if (path == NULL) return &_cairo_path_nil; - path->num_data = _cairo_path_data_count (gstate, flatten); + path->num_data = _cairo_path_data_count (path, path_fixed, + tolerance, flatten); path->data = malloc (path->num_data * sizeof (cairo_path_data_t)); if (path->data == NULL) { @@ -206,7 +354,8 @@ _cairo_path_data_create_real (cairo_gstate_t *gstate, cairo_bool_t flatten) return &_cairo_path_nil; } - _cairo_path_data_populate (path, gstate, flatten); + _cairo_path_data_populate (path, path_fixed, + ctm_inverse, tolerance, flatten); return path; } @@ -220,15 +369,19 @@ cairo_path_destroy (cairo_path_t *path) } cairo_path_t * -_cairo_path_data_create (cairo_gstate_t *gstate) +_cairo_path_data_create (cairo_path_fixed_t *path, + cairo_matrix_t *ctm_inverse, + double tolerance) { - return _cairo_path_data_create_real (gstate, FALSE); + return _cairo_path_data_create_real (path, ctm_inverse, tolerance, FALSE); } cairo_path_t * -_cairo_path_data_create_flat (cairo_gstate_t *gstate) +_cairo_path_data_create_flat (cairo_path_fixed_t *path, + cairo_matrix_t *ctm_inverse, + double tolerance) { - return _cairo_path_data_create_real (gstate, TRUE); + return _cairo_path_data_create_real (path, ctm_inverse, tolerance, TRUE); } cairo_status_t |