summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSøren Sandmann Pedersen <ssp@redhat.com>2012-09-29 18:04:30 -0400
committerSøren Sandmann Pedersen <ssp@redhat.com>2012-09-29 18:04:30 -0400
commit6b793c25b62b5eed449c19302aa87d39c66a9dd1 (patch)
tree5c6398460b548d3d7f149de0991646f87bacc990
parent1f65b69c145d641c0ebd188d944ab1be6f3a67b6 (diff)
stroke and fill
-rw-r--r--src/cairo-pixman-surface.c198
1 files 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);
@@ -1035,6 +1045,65 @@ cairo_pixman_surface_mask (void *abstract_surface,
}
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,
const cairo_pattern_t *source,
@@ -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