cogl-path: Allow changing the fill rule
authorNeil Roberts <neil@linux.intel.com>
Wed, 23 Jun 2010 12:40:43 +0000 (13:40 +0100)
committerNeil Roberts <neil@linux.intel.com>
Tue, 29 Jun 2010 19:37:14 +0000 (20:37 +0100)
This adds two new API calls- cogl_path_set_fill_rule and
cogl_path_get_fill_rule. This allows modifying the fill rule of the
current path. In addition to the previous default fill rule of
'even-odd' it now supports the 'non-zero' rule. The fill rule is a
property of the path (not the Cogl context) so creating a new path or
preserving a path with cogl_path_get_handle affects the fill rule.

clutter/cogl/cogl/cogl-path-private.h
clutter/cogl/cogl/cogl-path.c
clutter/cogl/cogl/cogl-path.h
doc/reference/cogl/Makefile.am
doc/reference/cogl/cogl-sections.txt
doc/reference/cogl/fill-rule-even-odd.png [moved from doc/reference/cogl/fill-rule.png with 100% similarity]
doc/reference/cogl/fill-rule-non-zero.png [new file with mode: 0644]

index ecfb520..8adddda 100644 (file)
@@ -25,6 +25,7 @@
 #define __COGL_PATH_PRIVATE_H
 
 #include "cogl-handle.h"
+#include "cogl-path.h"
 
 #define COGL_PATH(tex) ((CoglPath *)(tex))
 
@@ -69,6 +70,8 @@ struct _CoglPathData
 {
   unsigned int      ref_count;
 
+  CoglPathFillRule  fill_rule;
+
   GArray           *path_nodes;
 
   floatVec2         path_start;
index f27218f..687fdaa 100644 (file)
@@ -103,6 +103,35 @@ _cogl_path_modify (CoglPath *path)
     }
 }
 
+void
+cogl_path_set_fill_rule (CoglPathFillRule fill_rule)
+{
+  CoglPath *path;
+
+  _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+
+  path = COGL_PATH (ctx->current_path);
+
+  if (path->data->fill_rule != fill_rule)
+    {
+      _cogl_path_modify (path);
+
+      path->data->fill_rule = fill_rule;
+    }
+}
+
+CoglPathFillRule
+cogl_path_get_fill_rule (void)
+{
+  CoglPath *path;
+
+  _COGL_GET_CONTEXT (ctx, 0);
+
+  path = COGL_PATH (ctx->current_path);
+
+  return path->data->fill_rule;
+}
+
 static void
 _cogl_path_add_node (gboolean new_sub_path,
                     float x,
@@ -945,6 +974,7 @@ _cogl_path_new (void)
   data = path->data = g_slice_new (CoglPathData);
 
   data->ref_count = 1;
+  data->fill_rule = COGL_PATH_FILL_RULE_EVEN_ODD;
   data->path_nodes = g_array_new (FALSE, FALSE, sizeof (CoglPathNode));
   data->last_path = 0;
   data->vbo = COGL_INVALID_HANDLE;
@@ -1400,6 +1430,14 @@ _cogl_path_build_vbo (CoglPath *path)
   _cogl_path_tesselator_allocate_indices_array (&tess);
 
   tess.glu_tess = gluNewTess ();
+
+  if (data->fill_rule == COGL_PATH_FILL_RULE_EVEN_ODD)
+    gluTessProperty (tess.glu_tess, GLU_TESS_WINDING_RULE,
+                     GLU_TESS_WINDING_ODD);
+  else
+    gluTessProperty (tess.glu_tess, GLU_TESS_WINDING_RULE,
+                     GLU_TESS_WINDING_NONZERO);
+
   /* All vertices are on the xy-plane */
   gluTessNormal (tess.glu_tess, 0.0, 0.0, 1.0);
 
index a4c74c0..edeefe0 100644 (file)
@@ -54,6 +54,48 @@ G_BEGIN_DECLS
 typedef struct _CoglPath CoglPath;
 
 /**
+ * CoglPathFillRule:
+ * @COGL_PATH_FILL_RULE_NON_ZERO: Each time the line crosses an edge of
+ * the path from left to right one is added to a counter and each time
+ * it crosses from right to left the counter is decremented. If the
+ * counter is non-zero then the point will be filled. See <xref
+ * linkend="fill-rule-non-zero"/>.
+ * @COGL_PATH_FILL_RULE_EVEN_ODD: If the line crosses an edge of the
+ * path an odd number of times then the point will filled, otherwise
+ * it won't. See <xref linkend="fill-rule-even-odd"/>.
+ *
+ * #CoglPathFillRule is used to determine how a path is filled. There
+ * are two options - 'non-zero' and 'even-odd'. To work out whether any
+ * point will be filled imagine drawing an infinetely long line in any
+ * direction from that point. The number of times and the direction
+ * that the edges of the path crosses this line determines whether the
+ * line is filled as described below. Any open sub paths are treated
+ * as if there was an extra line joining the first point and the last
+ * point.
+ *
+ * The default fill rule is %COGL_PATH_FILL_RULE_EVEN_ODD. The fill
+ * rule is attached to the current path so preserving a path with
+ * cogl_get_path() also preserves the fill rule. Calling
+ * cogl_path_new() resets the current fill rule to the default.
+ *
+ * <figure id="fill-rule-non-zero">
+ *   <title>Example of filling various paths using the non-zero rule</title>
+ *   <graphic fileref="fill-rule-non-zero.png" format="PNG"/>
+ * </figure>
+ *
+ * <figure id="fill-rule-even-odd">
+ *   <title>Example of filling various paths using the even-odd rule</title>
+ *   <graphic fileref="fill-rule-even-odd.png" format="PNG"/>
+ * </figure>
+ *
+ * Since: 1.4
+ */
+typedef enum {
+  COGL_PATH_FILL_RULE_NON_ZERO,
+  COGL_PATH_FILL_RULE_EVEN_ODD
+} CoglPathFillRule;
+
+/**
  * cogl_is_path:
  * @handle: A CoglHandle
  *
@@ -66,27 +108,39 @@ gboolean
 cogl_is_path (CoglHandle handle);
 
 /**
+ * cogl_path_set_fill_rule:
+ * @fill_rule: The new fill rule.
+ *
+ * Sets the fill rule of the current path to @fill_rule. This will
+ * affect how the path is filled when cogl_path_fill() is later
+ * called. Note that the fill rule state is attached to the path so
+ * calling cogl_get_path() will preserve the fill rule and calling
+ * cogl_path_new() will reset the fill rule back to the default.
+ *
+ * Since: 1.4
+ */
+void
+cogl_path_set_fill_rule (CoglPathFillRule fill_rule);
+
+/**
+ * cogl_path_get_fill_rule:
+ *
+ * Return value: the fill rule that is used for the current path.
+ *
+ * Since: 1.4
+ */
+CoglPathFillRule
+cogl_path_get_fill_rule (void);
+
+/**
  * cogl_path_fill:
  *
  * Fills the interior of the constructed shape using the current
  * drawing color. The current path is then cleared. To use the path
  * again, call cogl_path_fill_preserve() instead.
  *
- * The interior of the shape is determined using the 'even-odd'
- * rule. Any open sub-paths are treated as if there is an extra line
- * joining the last point and first point. You can work out whether
- * any point in the stage will be filled if you imagine drawing an
- * infinitely long line in any direction from that point and then
- * counting the number times it crosses a line in the path. If the
- * number is odd it will be filled, otherwise it will not.
- *
- * See <xref linkend="fill-rule"/> for a demonstration of the fill
- * rule.
- *
- * <figure id="fill-rule">
- *   <title>Example of filling various paths</title>
- *   <graphic fileref="fill-rule.png" format="PNG"/>
- * </figure>
+ * The interior of the shape is determined using the fill rule of the
+ * path. See %CoglPathFillRule for details.
  **/
 void
 cogl_path_fill (void);
@@ -129,7 +183,9 @@ cogl_path_stroke_preserve (void);
 /**
  * cogl_path_new:
  *
- * Clears the current path and starts a new one.
+ * Clears the current path and starts a new one. Creating a new path
+ * also resets the fill rule to the default which is
+ * %COGL_PATH_FILL_RULE_EVEN_ODD.
  *
  * Since: 1.0
  */
index 5b1d1fb..3ea0463 100644 (file)
@@ -92,7 +92,8 @@ EXTRA_HFILES=
 # Images to copy into HTML directory.
 # e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png
 HTML_IMAGES = \
-       fill-rule.png \
+       fill-rule-non-zero.png \
+       fill-rule-even-odd.png \
        cogl_ortho.png
 
 # Extra SGML files that are included by $(DOC_MAIN_SGML_FILE).
@@ -122,5 +123,6 @@ include $(top_srcdir)/gtk-doc.make
 # e.g. EXTRA_DIST += version.xml.in
 
 EXTRA_DIST += \
-       fill-rule.png \
+       fill-rule-non-zero.png \
+       fill-rule-even-odd.png \
        cogl_ortho.png
index 6a4b7e4..3ab3ad6 100644 (file)
@@ -181,6 +181,9 @@ cogl_path_round_rectangle
 cogl_path_ellipse
 
 <SUBSECTION>
+CoglPathFillRule
+cogl_path_set_fill_rule
+cogl_path_get_fill_rule
 cogl_path_fill
 cogl_path_fill_preserve
 cogl_path_stroke
diff --git a/doc/reference/cogl/fill-rule-non-zero.png b/doc/reference/cogl/fill-rule-non-zero.png
new file mode 100644 (file)
index 0000000..2d8ad31
Binary files /dev/null and b/doc/reference/cogl/fill-rule-non-zero.png differ