[cairo] [PATCH 12/39] [OpenVG] Made paint use the same source setup as stroke and fill, also enhanced pattern source.

tardyp at gmail.com tardyp at gmail.com
Fri Jul 10 10:02:14 PDT 2009


From: Øyvind Kolås <pippin at gimp.org>

---
 src/cairo-openvg-surface.c |  174 +++++++++++++++++++++++++++++--------------
 1 files changed, 117 insertions(+), 57 deletions(-)

diff --git a/src/cairo-openvg-surface.c b/src/cairo-openvg-surface.c
index 379d30c..946c476 100644
--- a/src/cairo-openvg-surface.c
+++ b/src/cairo-openvg-surface.c
@@ -93,33 +93,6 @@ _cairo_openvg_surface_get_extents (void *asurface,
 }
 
 static cairo_int_status_t
-_cairo_openvg_surface_paint (void *asurface,
-                             cairo_operator_t op,
-                             cairo_pattern_t *source)
-{
-    cairo_openvg_surface_t *s = asurface;
-
-    if (source->type == CAIRO_PATTERN_TYPE_SOLID)
-      {
-        cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *) source;
-        VGfloat color[] = {solid->color.red,
-                           solid->color.green,
-                           solid->color.blue,
-                           solid->color.alpha};
-        vgSetfv (VG_CLEAR_COLOR, 4, color);
-        vgClear (0, 0, s->width * 3, s->height * 2);
-      }
-    else
-      {
-        printf ("not supporting source of type %i for paint yet\n", source->type);
-        return CAIRO_INT_STATUS_UNSUPPORTED;
-      }
-
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_int_status_t
 _cairo_openvg_surface_mask (void *asurface,
                          cairo_operator_t op,
                          cairo_pattern_t *source,
@@ -438,33 +411,86 @@ static cairo_status_t
 _cairo_openvg_setup_surface_source (cairo_openvg_surface_t  *vgsurface,
                                     cairo_surface_pattern_t *spat)
 {
-  VGfloat color[] = {1.0, 1.0, 1.0, 1.0};
-  vgSetParameterfv (vgsurface->source_paint, VG_PAINT_COLOR, 4, color);
-  printf ("not handling source of type surface\n");
+  cairo_status_t status = CAIRO_STATUS_SUCCESS;
+  cairo_image_surface_t *image= (cairo_image_surface_t*)spat->surface;
+  cairo_rectangle_int_t  extents;
+  unsigned char *data;
+
+  status = _cairo_surface_get_extents (spat->surface, &extents);
+  if (status)
+    return CAIRO_INT_STATUS_UNSUPPORTED;
 
-  vgsurface->source_image = vgCreateImage (VG_sRGBA_8888, 128, 128, VG_IMAGE_QUALITY_BETTER);
+  if (!_cairo_surface_is_image (spat->surface))
+    return CAIRO_INT_STATUS_UNSUPPORTED;
 
+  assert (image->format == CAIRO_FORMAT_RGB24 ||
+          image->format == CAIRO_FORMAT_ARGB32 ||
+          image->format == CAIRO_FORMAT_A8 ||
+          image->format == CAIRO_FORMAT_A1);
+
+  vgsurface->source_image = vgCreateImage (VG_sRGBA_8888, 
+    image->width, image->height, VG_IMAGE_QUALITY_FASTER);
+  /* NONALIASED, FASTER, BETTER */
+
+  data = malloc (image->width * image->height * 4);
+
+  /* This extra allocation and copy/conversion should not be neccesary if the OpenVG implementation
+   * supports the pixelformats in the specification, at the moment it doesn't seem like neither
+   * ShivaVG nor AmantihVG does so however.
+   */
   {
-    unsigned char *data = malloc (128*128*4);
     int i;
-    for (i=0;i<128*128*4;i++)
+    for (i=0; i<image->width * image->height; i++)
       {
-        data[i] = 0;/*rand() % 255;*/
-        if (i%4 == 3)
-          data[i] = 255;
-        if (i%4 == 2)
-          data[i] = rand ()%255;
+        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];
       }
+  }
 
-    vgImageSubData (vgsurface->source_image, data, 128*4, VG_sRGBA_8888, 0,
-     0, 128, 128);
+  vgImageSubData (vgsurface->source_image, data, image->width*4,
+     VG_sRGBA_8888 | (0 << 6), 0, 0, image->width, image->height);
 
-    free (data);
-  }
-  
+  free (data);
 
-  return CAIRO_STATUS_SUCCESS;
-  return CAIRO_INT_STATUS_UNSUPPORTED;
+  vgSetParameteri (vgsurface->source_paint,
+                   VG_PAINT_TYPE, VG_PAINT_TYPE_PATTERN);
+
+  switch (spat->base.extend)
+    {
+      case CAIRO_EXTEND_PAD:
+        vgSetParameteri(vgsurface->source_paint,
+                        VG_PAINT_PATTERN_TILING_MODE,
+                        VG_TILE_PAD);
+        break;
+      case CAIRO_EXTEND_NONE:
+        vgSetParameteri(vgsurface->source_paint,
+                        VG_PAINT_PATTERN_TILING_MODE,
+                        VG_TILE_FILL);
+        {
+          VGfloat color[] = {0,0,0,0};
+          vgSetfv (VG_TILE_FILL_COLOR, 4, color);
+        }
+
+        break;
+      case CAIRO_EXTEND_REPEAT:
+        vgSetParameteri(vgsurface->source_paint,
+                        VG_PAINT_PATTERN_TILING_MODE,
+                        VG_TILE_REPEAT);
+        break;
+      case CAIRO_EXTEND_REFLECT:
+        vgSetParameteri(vgsurface->source_paint,
+                        VG_PAINT_PATTERN_TILING_MODE,
+                        VG_TILE_REFLECT);
+      default:
+        break;
+    }
+
+
+  vgPaintPattern(vgsurface->source_paint, vgsurface->source_image);
+
+  return status;
 }
 
 static cairo_status_t
@@ -515,7 +541,7 @@ teardown_source (cairo_openvg_surface_t *vgsurface,
     }
   if (vgsurface->source_image)
     {
-      vgDestroyImage (vgsurface->source_paint);
+      vgDestroyImage (vgsurface->source_image);
       vgsurface->source_image = 0;
     }
   return CAIRO_STATUS_SUCCESS;
@@ -606,22 +632,55 @@ _cairo_openvg_surface_fill (void *asurface,
   if (rv)
     goto BAIL;
 
+  vgSetPaint(vgsurface->source_paint, VG_FILL_PATH);
+  vgDrawPath (vg_path.path, VG_FILL_PATH);
+  vgDestroyPath (vg_path.path);
 
+  teardown_source (vgsurface, source);
+BAIL:
 
+  return rv;
+}
 
-  if (vgsurface->source_image)
-    {
-      printf ("WARNING: attempting to paint with image pattern\n");
-      vgSeti(VG_IMAGE_MODE, VG_DRAW_IMAGE_NORMAL);
-      vgSetParameteri(vgsurface->source_image, VG_PAINT_PATTERN_TILING_MODE,
-                      VG_TILE_REPEAT);
-      vgPaintPattern(vgsurface->source_paint, vgsurface->source_image);
-    }
-  vgSetPaint(vgsurface->source_paint, VG_FILL_PATH);
+static cairo_int_status_t
+_cairo_openvg_surface_paint (void *asurface,
+                             cairo_operator_t op,
+                             cairo_pattern_t *source)
+{
+  cairo_openvg_surface_t *vgsurface = asurface;
+  cairo_status_t rv = CAIRO_STATUS_SUCCESS;
+  openvg_stroke_t vg_path;
 
-  vgDrawPath (vg_path.path, VG_FILL_PATH);
+  if (op == CAIRO_OPERATOR_DEST)
+    return CAIRO_STATUS_SUCCESS;
 
-  vgDestroyPath (vg_path.path);
+  vg_path.path = vgCreatePath (VG_PATH_FORMAT_STANDARD,
+                               VG_PATH_DATATYPE_F,
+                               1,0,0,0, VG_PATH_CAPABILITY_ALL);
+  vg_path.ctm_inverse = NULL;
+
+  vgSeti(VG_BLEND_MODE, _cairo_openvg_cairo_operator_to_openvg (op));
+
+  rv = setup_source (vgsurface, source);
+  if (rv)
+    goto BAIL;
+
+  vgSetPaint(vgsurface->source_paint, VG_FILL_PATH);
+
+  { /* creating a rectangular path that should cover the extent */
+    VGPath fullext; VGubyte segs[] = {VG_MOVE_TO_ABS, VG_LINE_TO_ABS,
+                                      VG_LINE_TO_ABS, VG_LINE_TO_ABS, 
+                                      VG_CLOSE_PATH};
+    VGfloat data[] = {0,0,
+                      vgsurface->width, 0,
+                      vgsurface->width, vgsurface->height,
+                      0, vgsurface->height};
+    fullext = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F,
+                      1,0,0,0, VG_PATH_CAPABILITY_ALL);
+    vgAppendPathData(fullext, sizeof(segs), segs, data);
+    vgDrawPath (fullext, VG_FILL_PATH);
+    vgDestroyPath (fullext);
+  }
 
   teardown_source (vgsurface, source);
 BAIL:
@@ -629,6 +688,7 @@ BAIL:
   return rv;
 }
 
+
 #if 0
 static cairo_int_status_t
 _cairo_openvg_surface_show_glyphs (void *asurface,
-- 
1.6.0.4



More information about the cairo mailing list