From 3a1456f34e17161b54ecd8ec55692e8a40c46456 Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Wed, 23 Jun 2010 13:40:43 +0100 Subject: [PATCH] cogl-path: Allow changing the fill rule 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 | 3 + clutter/cogl/cogl/cogl-path.c | 38 ++++++++ clutter/cogl/cogl/cogl-path.h | 88 ++++++++++++++---- doc/reference/cogl/Makefile.am | 6 +- doc/reference/cogl/cogl-sections.txt | 3 + .../{fill-rule.png => fill-rule-even-odd.png} | Bin doc/reference/cogl/fill-rule-non-zero.png | Bin 0 -> 3143 bytes 7 files changed, 120 insertions(+), 18 deletions(-) rename doc/reference/cogl/{fill-rule.png => fill-rule-even-odd.png} (100%) create mode 100644 doc/reference/cogl/fill-rule-non-zero.png diff --git a/clutter/cogl/cogl/cogl-path-private.h b/clutter/cogl/cogl/cogl-path-private.h index ecfb52024..8addddaa8 100644 --- a/clutter/cogl/cogl/cogl-path-private.h +++ b/clutter/cogl/cogl/cogl-path-private.h @@ -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; diff --git a/clutter/cogl/cogl/cogl-path.c b/clutter/cogl/cogl/cogl-path.c index f27218f0b..687fdaa15 100644 --- a/clutter/cogl/cogl/cogl-path.c +++ b/clutter/cogl/cogl/cogl-path.c @@ -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); diff --git a/clutter/cogl/cogl/cogl-path.h b/clutter/cogl/cogl/cogl-path.h index a4c74c083..edeefe0dc 100644 --- a/clutter/cogl/cogl/cogl-path.h +++ b/clutter/cogl/cogl/cogl-path.h @@ -53,6 +53,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 . + * @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 . + * + * #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. + * + *
+ * Example of filling various paths using the non-zero rule + * + *
+ * + *
+ * Example of filling various paths using the even-odd rule + * + *
+ * + * Since: 1.4 + */ +typedef enum { + COGL_PATH_FILL_RULE_NON_ZERO, + COGL_PATH_FILL_RULE_EVEN_ODD +} CoglPathFillRule; + /** * cogl_is_path: * @handle: A CoglHandle @@ -65,6 +107,31 @@ typedef struct _CoglPath CoglPath; 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: * @@ -72,21 +139,8 @@ cogl_is_path (CoglHandle handle); * 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 for a demonstration of the fill - * rule. - * - *
- * Example of filling various paths - * - *
+ * 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 */ diff --git a/doc/reference/cogl/Makefile.am b/doc/reference/cogl/Makefile.am index 5b1d1fb5f..3ea046337 100644 --- a/doc/reference/cogl/Makefile.am +++ b/doc/reference/cogl/Makefile.am @@ -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 diff --git a/doc/reference/cogl/cogl-sections.txt b/doc/reference/cogl/cogl-sections.txt index 6a4b7e40a..3ab3ad69f 100644 --- a/doc/reference/cogl/cogl-sections.txt +++ b/doc/reference/cogl/cogl-sections.txt @@ -181,6 +181,9 @@ cogl_path_round_rectangle cogl_path_ellipse +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.png b/doc/reference/cogl/fill-rule-even-odd.png similarity index 100% rename from doc/reference/cogl/fill-rule.png rename to doc/reference/cogl/fill-rule-even-odd.png diff --git a/doc/reference/cogl/fill-rule-non-zero.png b/doc/reference/cogl/fill-rule-non-zero.png new file mode 100644 index 0000000000000000000000000000000000000000..2d8ad314c4baacc70c84b83b0b83b35e6a93a01c GIT binary patch literal 3143 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 y<{bqu5{34YKxrUl;;`YAegRT~^Z(xwR