[cairo-commit] [cairo-www] src/cookbook src/cookbook.mdwn

Bryce Harrington bryce at freedesktop.org
Fri Jan 15 19:00:34 PST 2016


 src/cookbook.mdwn                              |    1 
 src/cookbook/outside_clipping.mdwn             |   89 +++++++++++++++++++++++++
 src/cookbook/outside_clipping/outside_clip.png |binary
 3 files changed, 90 insertions(+)

New commits:
commit f4534a34ca5665ef991af253bc62089835708aad
Author: Lawrence D'Oliveiro <ldo at geek-central.gen.nz>
Date:   Sat Jan 16 14:36:06 2016 +1300

    PATCH cairo-www: add outside-clipping cookbook example
    
    Thought it might be useful to demonstrate this technique.
    
    >From 6ffa8c1dd0979bc75b93af20534822a370283d88 Mon Sep 17 00:00:00 2001
    From: Lawrence D'Oliveiro <ldo at geek-central.gen.nz>
    Date: Sat, 16 Jan 2016 01:33:13 +0000
    Subject: [PATCH] add outside-clipping cookbook example

diff --git a/src/cookbook.mdwn b/src/cookbook.mdwn
index 9e5471b..f9cb78e 100644
--- a/src/cookbook.mdwn
+++ b/src/cookbook.mdwn
@@ -6,6 +6,7 @@
     * [[Rounded_rectangles|roundedrectangles]]
     * [[Ellipses With Uniform Stroke Width|ellipses]]
     * [[A_description_of_compositing_operators_in_Cairo|operators]]
+    * [[Clipping Outside A Region|outside_clipping]]
 
 + Matrix Transformations
     * [[Basic_matrix_transformation_reminder|matrix_transform]]
diff --git a/src/cookbook/outside_clipping.mdwn b/src/cookbook/outside_clipping.mdwn
new file mode 100644
index 0000000..6220b18
--- /dev/null
+++ b/src/cookbook/outside_clipping.mdwn
@@ -0,0 +1,89 @@
+[[!meta title="Clipping Outside A Region"]]
+
+Cairo lets you clip drawing to arbitrary regions defined by paths. The basic technique
+is:
+
+  * construct your path
+  * use [`cairo_clip()`](http://cairographics.org/manual/cairo-cairo-t.html#cairo-clip)
+    to intersect the clip region with the interior of your path.
+
+Note that the intersection is with the *interior* of your path—that is, the area
+that would be filled if you did a `cairo_fill()` operation on your path. But supposing
+you have a path, and you want drawing to be clipped to the *exterior* of that path?
+
+The way to reverse the definitions of “interior” and “exterior” is simple: simply add
+another subpath to your path, surrounding the entire drawing area. If you use
+`CAIRO_FILL_RULE_WINDING` for your fill rule (the default), then make sure the enclosing
+subpath is defined in the opposite direction to the inner one. Now the interior of
+the path becomes the area between the subpaths, rather than inside the inner subpath.
+
+Alternatively, you can use `CAIRO_FILL_RULE_EVEN_ODD` for your fill rule, then the
+subpath directions don’t matter.
+
+    const int img_size = 300;
+    cairo_surface_t * const pix = cairo_image_surface_create
+      (
+        /*format =*/ CAIRO_FORMAT_RGB24,
+        /*width =*/ img_size,
+        /*height =*/ img_size
+      );
+    cairo_t * const cr = cairo_create(pix);
+    cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
+      /* use overwriting operator to make clear that overwriting is blocked by clipping */
+    cairo_set_source_rgb(cr, 1, 1, 1); /* background */
+    cairo_paint(cr);
+    for (bool outside = false;;)
+      {
+      /* Do two drawing passes, once clipped inside the region, then clipped outside. */
+      /* Because of the clipping, the second pass does not overwrite the first. */
+        cairo_reset_clip(cr);
+        cairo_new_path(cr);
+        cairo_arc /* example inner region--note subpath is defined clockwise */
+          (
+            /*cr =*/ cr,
+            /*xc =*/ img_size / 2.0,
+            /*yc =*/ img_size / 2.0,
+            /*radius =*/ img_size / 4.0,
+            /*angle1 =*/ 0,
+            /*angle2 =*/ 2 * M_PI
+          );
+        if (outside)
+          {
+          /* add outer subpath in anticlockwise direction */
+            cairo_new_sub_path(cr);
+            cairo_move_to(cr, img_size, 0);
+            cairo_line_to(cr, 0, 0);
+            cairo_line_to(cr, 0, img_size);
+            cairo_line_to(cr, img_size, img_size);
+            cairo_close_path(cr);
+          } /*if*/
+        cairo_clip(cr);
+        if (outside) /* use different colours to distinguish cases */
+          {
+            cairo_set_source_rgb(cr, 1.0, 0.91, 0.83);
+          }
+        else
+          {
+            cairo_set_source_rgb(cr, 0.1, 0.7, 0.67);
+          } /*if*/
+        cairo_rectangle
+          /* example shape that extends both inside and outside inner clipping region */
+          (
+            /*cr =*/ cr,
+            /*x =*/ 0,
+            /*y =*/ img_size / 4.0,
+            /*width =*/ img_size,
+            /*height =*/ img_size / 2.0
+          );
+        cairo_fill(cr);
+        if (outside)
+            break;
+        outside = true;
+      } /*for*/
+
+Sample output:
+
+[[!img "outside_clip.png" link="no"]]
+
+This technique also extends to more than one inner subpath, defining multiple discontiguous
+inner regions to be clipped out of the drawing area.
diff --git a/src/cookbook/outside_clipping/outside_clip.png b/src/cookbook/outside_clipping/outside_clip.png
new file mode 100644
index 0000000..e9d406c
Binary files /dev/null and b/src/cookbook/outside_clipping/outside_clip.png differ


More information about the cairo-commit mailing list