[cairo] [PATCH 19/39] [OpenVG] Implemented intersect_clip_path, using software rendered path and masks.
tardyp at gmail.com
tardyp at gmail.com
Fri Jul 10 10:02:21 PDT 2009
From: Øyvind Kolås <pippin at gimp.org>
---
src/cairo-openvg-surface.c | 100 +++++++++++++++++++++++++++++++++++++-------
1 files changed, 84 insertions(+), 16 deletions(-)
diff --git a/src/cairo-openvg-surface.c b/src/cairo-openvg-surface.c
index 2419d55..9f9d200 100644
--- a/src/cairo-openvg-surface.c
+++ b/src/cairo-openvg-surface.c
@@ -76,18 +76,69 @@ _cairo_openvg_surface_clone_similar (void *asurface,
return CAIRO_STATUS_SUCCESS;
}
-#if 0
+#include "cairo-private.h"
+
static cairo_int_status_t
_cairo_openvg_surface_intersect_clip_path (void *asurface,
cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
- double toleance,
+ double tolerance,
cairo_antialias_t antialias)
{
- printf ("intersect clip path\n");
- return CAIRO_STATUS_SUCCESS;
+ cairo_status_t status = CAIRO_STATUS_SUCCESS;
+ cairo_openvg_surface_t *vgsurface = asurface;
+ cairo_surface_t *image;
+ cairo_t *cr;
+ cairo_pattern_t *white;
+
+ if (path == NULL)
+ {
+ vgMask (VG_INVALID_HANDLE, VG_FILL_MASK, 0, 0, vgsurface->width, vgsurface->height);
+ vgSeti (VG_MASKING, VG_FALSE);
+ return CAIRO_STATUS_SUCCESS;
+ }
+
+ /* FIXME: cache paths used for clipping in, and store their resulting masks on
+ the gpu, hoping that they can be reused, probably keeping only a small
+ number, and disabling the caching if continous thrashing is detected.
+
+ should also shrink the size the uploaded buffer to the bounding box
+ of the path
+ */
+ image = cairo_image_surface_create (CAIRO_FORMAT_A8, vgsurface->width,
+ vgsurface->height);
+ cr = cairo_create (image);
+ filled = cairo_pattern_create_rgba (0.0, 0.0, 0.0, 1.0);
+
+ cairo_save (cr);
+ cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
+ cairo_paint (cr);
+ cairo_restore (cr);
+
+ status = _cairo_surface_fill (image,
+ CAIRO_OPERATOR_SOURCE,
+ filled,
+ path,
+ fill_rule,
+ tolerance,
+ antialias);
+ if (status == CAIRO_STATUS_SUCCESS)
+ {
+ VGImage vgimage;
+ unsigned char *data = cairo_image_surface_get_data (image);
+ vgSeti (VG_MASKING, VG_TRUE);
+ vgimage = vgCreateImage (VG_A_8, vgsurface->width, vgsurface->height, VG_IMAGE_QUALITY_FASTER);
+ vgImageSubData (vgimage, data, vgsurface->width, VG_A_8, 0, 0, vgsurface->width, vgsurface->height);
+ vgMask (vgimage, VG_INTERSECT_MASK, 0, 0, vgsurface->width, vgsurface->height);
+ vgDestroyImage (vgimage);
+ }
+
+ cairo_pattern_destroy (filled);
+ cairo_destroy (cr);
+
+ cairo_surface_destroy (image);
+ return status;
}
-#endif
static cairo_int_status_t
_cairo_openvg_surface_get_extents (void *asurface,
@@ -101,16 +152,6 @@ _cairo_openvg_surface_get_extents (void *asurface,
return CAIRO_STATUS_SUCCESS;
}
-static cairo_int_status_t
-_cairo_openvg_surface_mask (void *asurface,
- cairo_operator_t op,
- cairo_pattern_t *source,
- cairo_pattern_t *mask)
-{
- printf ("mask\n");
- return CAIRO_STATUS_SUCCESS;
-}
-
typedef struct _openvg_stroke {
VGPath path;
cairo_matrix_t *ctm_inverse; /* useful for somthing? */
@@ -439,10 +480,17 @@ _cairo_openvg_setup_surface_source (cairo_openvg_surface_t *vgsurface,
int i;
for (i=0; i<image->width * image->height; i++)
{
+#if 1
data[4*i+0] = image->data[4*i+2];
data[4*i+1] = image->data[4*i+1];
data[4*i+2] = image->data[4*i+0];
data[4*i+3] = image->data[4*i+3];
+#else
+ data[4*i+0] = image->data[4*i+3];
+ data[4*i+1] = image->data[4*i+0];
+ data[4*i+2] = image->data[4*i+1];
+ data[4*i+3] = image->data[4*i+2];
+#endif
}
}
@@ -546,6 +594,7 @@ teardown_source (cairo_openvg_surface_t *vgsurface,
return CAIRO_STATUS_SUCCESS;
}
+
static cairo_int_status_t
_cairo_openvg_surface_stroke (void *asurface,
cairo_operator_t op,
@@ -687,6 +736,22 @@ BAIL:
return rv;
}
+static cairo_int_status_t
+_cairo_openvg_surface_mask (void *asurface,
+ cairo_operator_t op,
+ cairo_pattern_t *source,
+ cairo_pattern_t *mask)
+{
+ cairo_status_t status = CAIRO_STATUS_SUCCESS;
+ printf ("mask\n");
+
+ /* upload source as image */
+ status = _cairo_openvg_surface_paint (asurface, op, source);
+
+ return status;
+}
+
+
static cairo_int_status_t
_cairo_openvg_surface_show_glyphs (void *asurface,
@@ -733,7 +798,7 @@ cairo_openvg_surface_backend = {
NULL, /* copy_page */
NULL, /* show_page */
NULL, /* set_clip_egion */
- NULL, /*_cairo_openvg_surface_intersect_clip_path,*/
+ _cairo_openvg_surface_intersect_clip_path,
_cairo_openvg_surface_get_extents,
NULL, /* old_show_glyphs */
NULL, /* get_font_options */
@@ -770,5 +835,8 @@ cairo_openvg_surface_create (int width, int height)
vgTranslate (0.0, height);
vgScale (1.0, -1.0);
+ /* Force an initial "clip", that resets the mask */
+ _cairo_openvg_surface_intersect_clip_path (s, NULL, 0, 0.0, 0);
+
return (cairo_surface_t *) s;
}
--
1.6.0.4
More information about the cairo
mailing list