From 6b793c25b62b5eed449c19302aa87d39c66a9dd1 Mon Sep 17 00:00:00 2001 From: Søren Sandmann Pedersen Date: Sat, 29 Sep 2012 18:04:30 -0400 Subject: stroke and fill --- src/cairo-pixman-surface.c | 198 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 150 insertions(+), 48 deletions(-) diff --git a/src/cairo-pixman-surface.c b/src/cairo-pixman-surface.c index 4c549a65..1222ffe4 100644 --- a/src/cairo-pixman-surface.c +++ b/src/cairo-pixman-surface.c @@ -608,45 +608,64 @@ project_line_x_onto_16_16 (const cairo_line_t *line, static void ptrap_from_cairo_trap (pixman_trapezoid_t *ptrap, cairo_trapezoid_t *trap) { - /* top/bottom will be clamped to surface bounds */ - ptrap->top = _cairo_fixed_to_16_16 (trap->top); - ptrap->bottom = _cairo_fixed_to_16_16 (trap->bottom); - - /* However, all the other coordinates will have been left - * untouched so as not to introduce numerical error. Recompute - * them if they - * exceed the 16.16 limits. - */ - if (unlikely (line_exceeds_16_16 (&trap->left))) - { - project_line_x_onto_16_16 ( - &trap->left, trap->top, trap->bottom, &ptrap->left); - - ptrap->left.p1.y = ptrap->top; - ptrap->left.p2.y = ptrap->bottom; - } - else +} + +static pixman_trapezoid_t * +traps_to_pixman_trapezoids (const cairo_traps_t *traps) +{ + pixman_trapezoid_t *ptraps; + int i; + + if (!(ptraps = malloc (traps->num_traps * sizeof (pixman_trapezoid_t)))) + return NULL; + + for (i = 0; i < traps->num_traps; ++i) { - ptrap->left.p1.x = _cairo_fixed_to_16_16 (trap->left.p1.x); - ptrap->left.p1.y = _cairo_fixed_to_16_16 (trap->left.p1.y); - ptrap->left.p2.x = _cairo_fixed_to_16_16 (trap->left.p2.x); - ptrap->left.p2.y = _cairo_fixed_to_16_16 (trap->left.p2.y); - } + cairo_trapezoid_t *trap = &(traps->traps[i]); + pixman_trapezoid_t *ptrap = &ptraps[i]; + + /* top/bottom will be clamped to surface bounds */ + ptrap->top = _cairo_fixed_to_16_16 (trap->top); + ptrap->bottom = _cairo_fixed_to_16_16 (trap->bottom); - if (unlikely (line_exceeds_16_16 (&trap->right))) - { - project_line_x_onto_16_16 ( - &trap->right, trap->top, trap->bottom, &ptrap->right); - ptrap->right.p1.y = ptrap->top; - ptrap->right.p2.y = ptrap->bottom; - } - else - { - ptrap->right.p1.x = _cairo_fixed_to_16_16 (trap->right.p1.x); - ptrap->right.p1.y = _cairo_fixed_to_16_16 (trap->right.p1.y); - ptrap->right.p2.x = _cairo_fixed_to_16_16 (trap->right.p2.x); - ptrap->right.p2.y = _cairo_fixed_to_16_16 (trap->right.p2.y); + /* However, all the other coordinates will have been left + * untouched so as not to introduce numerical error. Recompute + * them if they + * exceed the 16.16 limits. + */ + if (unlikely (line_exceeds_16_16 (&trap->left))) + { + project_line_x_onto_16_16 ( + &trap->left, trap->top, trap->bottom, &ptrap->left); + + ptrap->left.p1.y = ptrap->top; + ptrap->left.p2.y = ptrap->bottom; + } + else + { + ptrap->left.p1.x = _cairo_fixed_to_16_16 (trap->left.p1.x); + ptrap->left.p1.y = _cairo_fixed_to_16_16 (trap->left.p1.y); + ptrap->left.p2.x = _cairo_fixed_to_16_16 (trap->left.p2.x); + ptrap->left.p2.y = _cairo_fixed_to_16_16 (trap->left.p2.y); + } + + if (unlikely (line_exceeds_16_16 (&trap->right))) + { + project_line_x_onto_16_16 ( + &trap->right, trap->top, trap->bottom, &ptrap->right); + ptrap->right.p1.y = ptrap->top; + ptrap->right.p2.y = ptrap->bottom; + } + else + { + ptrap->right.p1.x = _cairo_fixed_to_16_16 (trap->right.p1.x); + ptrap->right.p1.y = _cairo_fixed_to_16_16 (trap->right.p1.y); + ptrap->right.p2.x = _cairo_fixed_to_16_16 (trap->right.p2.x); + ptrap->right.p2.y = _cairo_fixed_to_16_16 (trap->right.p2.y); + } } + + return ptraps; } static cairo_int_status_t @@ -713,7 +732,6 @@ create_clip_image (const cairo_clip_t *clip, pixman_image_t **clip_image) cairo_polygon_t polygon; cairo_traps_t traps; pixman_trapezoid_t *ptraps; - int i; _cairo_polygon_init (&polygon, NULL, 0); _cairo_traps_init (&traps); @@ -723,20 +741,12 @@ create_clip_image (const cairo_clip_t *clip, pixman_image_t **clip_image) status = _cairo_bentley_ottmann_tessellate_polygon ( &traps, &polygon, clip_path->fill_rule); - - if (!(ptraps = malloc (traps.num_traps * sizeof (pixman_trapezoid_t)))) + + if (!(ptraps = traps_to_pixman_trapezoids (&traps))) status = CAIRO_INT_STATUS_NO_MEMORY; if (status == CAIRO_INT_STATUS_SUCCESS) { - for (i = 0; i < traps.num_traps; ++i) - { - cairo_trapezoid_t *trap = &(traps.traps[i]); - pixman_trapezoid_t *ptrap = &ptraps[i]; - - ptrap_from_cairo_trap (ptrap, trap); - } - pixman_composite_trapezoids ( PIXMAN_OP_IN, white_img, *clip_image, PIXMAN_a8, 0, 0, 0, 0, traps.num_traps, ptraps); @@ -1034,6 +1044,65 @@ cairo_pixman_surface_mask (void *abstract_surface, return status; } +static cairo_int_status_t +clip_and_composite_traps (cairo_pixman_surface_t *psurface, + cairo_operator_t operator, + const cairo_pattern_t *source, + const cairo_traps_t *traps, + cairo_antialias_t antialias, + const cairo_clip_t *clip) +{ + cairo_int_status_t status; + pixman_trapezoid_t *ptraps = NULL; + pixman_image_t *mask_image = NULL; + pixman_format_code_t format; + int w, h; + + w = pixman_image_get_width (psurface->pimage); + h = pixman_image_get_height (psurface->pimage); + + switch (antialias) + { + case CAIRO_ANTIALIAS_NONE: + format = PIXMAN_a1; + break; + + case CAIRO_ANTIALIAS_FAST: + format = PIXMAN_a4; + break; + + case CAIRO_ANTIALIAS_GRAY: + case CAIRO_ANTIALIAS_DEFAULT: + case CAIRO_ANTIALIAS_SUBPIXEL: + case CAIRO_ANTIALIAS_GOOD: + case CAIRO_ANTIALIAS_BEST: + format = PIXMAN_a8; + break; + } + + status = CAIRO_INT_STATUS_NO_MEMORY; + + if (!(mask_image = pixman_image_create_bits (format, w, h, NULL, -1))) + goto out; + + if (!(ptraps = traps_to_pixman_trapezoids (traps))) + goto out; + + status = CAIRO_INT_STATUS_SUCCESS; + + pixman_add_trapezoids (mask_image, 0, 0, traps->num_traps, ptraps); + + status = clip_and_composite (psurface, operator, source, mask_image, clip); + +out: + free (ptraps); + + if (mask_image) + pixman_image_unref (mask_image); + + return status; +} + static cairo_int_status_t cairo_pixman_surface_stroke (void *abstract_surface, cairo_operator_t op, @@ -1046,7 +1115,23 @@ cairo_pixman_surface_stroke (void *abstract_surface, cairo_antialias_t antialias, const cairo_clip_t *clip) { - + cairo_pixman_surface_t *psurface = abstract_surface; + cairo_int_status_t status; + cairo_traps_t traps; + + _cairo_traps_init (&traps); + + status = _cairo_path_fixed_stroke_to_traps ( + path, style, ctm, ctm_inverse, tolerance, &traps); + + if (status == CAIRO_INT_STATUS_SUCCESS) + { + status = clip_and_composite_traps ( + psurface, op, source, &traps, antialias, clip); + } + + _cairo_traps_fini (&traps); + return status; } static cairo_int_status_t @@ -1059,6 +1144,23 @@ cairo_pixman_surface_fill (void *abstract_surface, cairo_antialias_t antialias, const cairo_clip_t *clip) { + cairo_pixman_surface_t *psurface = abstract_surface; + cairo_int_status_t status; + cairo_traps_t traps; + + _cairo_traps_init (&traps); + + status = _cairo_path_fixed_fill_to_traps ( + path, fill_rule, tolerance, &traps); + + if (status == CAIRO_INT_STATUS_SUCCESS) + { + status = clip_and_composite_traps ( + psurface, op, source, &traps, antialias, clip); + } + + _cairo_traps_fini (&traps); + return status; } static cairo_int_status_t -- cgit v1.2.3