[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