[Cogl] [PATCH 1/2] Remove the legacy CoglPath API

Neil Roberts neil at linux.intel.com
Mon Apr 16 05:21:14 PDT 2012


This removes the legacy path API which operates on an implicit global
CoglPath object and works in terms of integers. The newer API which
takes a CoglPath* pointer can be used instead.
---
 cogl/Makefile.am            |    7 +-
 cogl/cogl-clip-stack.h      |    2 +-
 cogl/cogl-clip-state.c      |   20 -
 cogl/cogl-clip-state.h      |   13 -
 cogl/cogl-context-private.h |    1 -
 cogl/cogl-context.c         |    6 +-
 cogl/cogl-framebuffer.h     |    5 -
 cogl/cogl-path-functions.h  |  430 -------------
 cogl/cogl-path.c            | 1393 +++++++++++++++++++++++++++++++++++++----
 cogl/cogl-path.h            |  386 ++++++++++++-
 cogl/cogl.h                 |    9 +-
 cogl/cogl.symbols           |   67 +--
 cogl/cogl1-context.h        |   13 -
 cogl/cogl2-path.c           | 1449 -------------------------------------------
 cogl/cogl2-path.h           |  506 ---------------
 15 files changed, 1675 insertions(+), 2632 deletions(-)
 delete mode 100644 cogl/cogl-path-functions.h
 delete mode 100644 cogl/cogl2-path.c
 delete mode 100644 cogl/cogl2-path.h

diff --git a/cogl/Makefile.am b/cogl/Makefile.am
index 16e7005..88b05bb 100644
--- a/cogl/Makefile.am
+++ b/cogl/Makefile.am
@@ -54,8 +54,6 @@ cogl_1_public_h = \
 	$(srcdir)/cogl-matrix.h 		\
 	$(srcdir)/cogl-offscreen.h 		\
 	$(srcdir)/cogl-primitives.h 		\
-	$(srcdir)/cogl-path.h 			\
-	$(srcdir)/cogl-path-functions.h         \
 	$(srcdir)/cogl-shader.h 		\
 	$(srcdir)/cogl-texture.h 		\
 	$(srcdir)/cogl-types.h 			\
@@ -76,7 +74,7 @@ cogl_experimental_h = \
 	$(srcdir)/cogl-pipeline-state.h 	\
 	$(srcdir)/cogl-pipeline-layer-state.h 	\
 	$(srcdir)/cogl-snippet.h		\
-	$(srcdir)/cogl2-path.h 			\
+	$(srcdir)/cogl-path.h 			\
 	$(srcdir)/cogl-index-buffer.h 		\
 	$(srcdir)/cogl-attribute-buffer.h 	\
 	$(srcdir)/cogl-indices.h 		\
@@ -199,10 +197,7 @@ cogl_sources_c = \
 	$(srcdir)/cogl-primitives.h 			\
 	$(srcdir)/cogl-primitives.c 			\
 	$(srcdir)/cogl-path-private.h 			\
-	$(srcdir)/cogl-path.h 				\
 	$(srcdir)/cogl-path.c 				\
-	$(srcdir)/cogl2-path.h 				\
-	$(srcdir)/cogl2-path.c 				\
 	$(srcdir)/cogl-bitmap-pixbuf.c 			\
 	$(srcdir)/cogl-clip-stack.h 			\
 	$(srcdir)/cogl-clip-stack.c			\
diff --git a/cogl/cogl-clip-stack.h b/cogl/cogl-clip-stack.h
index c263caa..ec7b52f 100644
--- a/cogl/cogl-clip-stack.h
+++ b/cogl/cogl-clip-stack.h
@@ -24,7 +24,7 @@
 #ifndef __COGL_CLIP_STACK_H
 #define __COGL_CLIP_STACK_H
 
-#include "cogl2-path.h"
+#include "cogl-path.h"
 #include "cogl-matrix.h"
 #include "cogl-primitive.h"
 #include "cogl-framebuffer.h"
diff --git a/cogl/cogl-clip-state.c b/cogl/cogl-clip-state.c
index ca34d78..97f8ce6 100644
--- a/cogl/cogl-clip-state.c
+++ b/cogl/cogl-clip-state.c
@@ -85,26 +85,6 @@ cogl_clip_push (float x_offset,
 }
 
 void
-cogl_clip_push_from_path_preserve (void)
-{
-  _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-  cogl_framebuffer_push_path_clip (cogl_get_draw_framebuffer (),
-                                   ctx->current_path);
-}
-
-#undef cogl_clip_push_from_path
-void
-cogl_clip_push_from_path (void)
-{
-  _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
-  cogl_clip_push_from_path_preserve ();
-
-  cogl_object_unref (ctx->current_path);
-  ctx->current_path = cogl2_path_new ();
-}
-
-void
 cogl_clip_push_primitive (CoglPrimitive *primitive,
                           float bounds_x1,
                           float bounds_y1,
diff --git a/cogl/cogl-clip-state.h b/cogl/cogl-clip-state.h
index b51943f..4865ae5 100644
--- a/cogl/cogl-clip-state.h
+++ b/cogl/cogl-clip-state.h
@@ -32,19 +32,6 @@
 
 G_BEGIN_DECLS
 
-/**
- * cogl_clip_push_from_path:
- *
- * Sets a new clipping area using the current path. The current path
- * is then cleared. The clipping area is intersected with the previous
- * clipping area. To restore the previous clipping area, call
- * cogl_clip_pop().
- *
- * Since: 1.0
- */
-void
-cogl_clip_push_from_path (void);
-
 G_END_DECLS
 
 #endif /* __COGL_CLIP_STATE_H */
diff --git a/cogl/cogl-context-private.h b/cogl/cogl-context-private.h
index 333235b..3adadc5 100644
--- a/cogl/cogl-context-private.h
+++ b/cogl/cogl-context-private.h
@@ -177,7 +177,6 @@ struct _CoglContext
   CoglFramebuffer  *current_read_buffer;
 
   /* Primitives */
-  CoglPath         *current_path;
   CoglPipeline     *stencil_pipeline;
 
   /* Pre-generated VBOs containing indices to generate GL_TRIANGLES
diff --git a/cogl/cogl-context.c b/cogl/cogl-context.c
index 94ce2f1..6a01fcc 100644
--- a/cogl/cogl-context.c
+++ b/cogl/cogl-context.c
@@ -44,7 +44,7 @@
 #include "cogl-pipeline-opengl-private.h"
 #include "cogl-framebuffer-private.h"
 #include "cogl-onscreen-private.h"
-#include "cogl2-path.h"
+#include "cogl-path.h"
 #include "cogl-attribute-private.h"
 #include "cogl1-context.h"
 #include "cogl-gpu-info-private.h"
@@ -370,7 +370,6 @@ cogl_context_new (CoglDisplay *display,
       cogl_object_unref (COGL_FRAMEBUFFER (window));
     }
 
-  context->current_path = cogl2_path_new ();
   context->stencil_pipeline = cogl_pipeline_new (context);
 
   context->in_begin_gl_block = FALSE;
@@ -462,9 +461,6 @@ _cogl_context_free (CoglContext *context)
 
   _cogl_free_framebuffer_stack (context->framebuffer_stack);
 
-  if (context->current_path)
-    cogl_handle_unref (context->current_path);
-
   if (context->default_gl_texture_2d_tex)
     cogl_object_unref (context->default_gl_texture_2d_tex);
   if (context->default_gl_texture_3d_tex)
diff --git a/cogl/cogl-framebuffer.h b/cogl/cogl-framebuffer.h
index 07886db..1769975 100644
--- a/cogl/cogl-framebuffer.h
+++ b/cogl/cogl-framebuffer.h
@@ -34,12 +34,7 @@
 #include <windows.h>
 #endif /* COGL_HAS_WIN32_SUPPORT */
 
-#ifdef COGL_ENABLE_EXPERIMENTAL_2_0_API
-#include <cogl/cogl2-path.h>
-#else
 #include <cogl/cogl-path.h>
-#endif
-
 #include <cogl/cogl-pipeline.h>
 #include <cogl/cogl-indices.h>
 #include <cogl/cogl-bitmap.h>
diff --git a/cogl/cogl-path-functions.h b/cogl/cogl-path-functions.h
deleted file mode 100644
index 2566fe1..0000000
--- a/cogl/cogl-path-functions.h
+++ /dev/null
@@ -1,430 +0,0 @@
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2008,2009,2012 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#if !defined(__COGL_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
-#error "Only <cogl/cogl.h> can be included directly."
-#endif
-
-#ifndef __COGL_PATH_FUNCTIONS_H__
-#define __COGL_PATH_FUNCTIONS_H__
-
-/* The functions are declared separately because cogl-path.c needs to
-   get the function declarations from the old 1.0 API without
-   colliding with the enum declarations from the 2.0 API */
-
-#include <cogl/cogl-types.h>
-
-G_BEGIN_DECLS
-
-/**
- * cogl_is_path:
- * @handle: A CoglHandle
- *
- * Gets whether the given handle references an existing path object.
- *
- * Return value: %TRUE if the handle references a #CoglPath,
- *   %FALSE otherwise
- */
-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:
- *
- * Retrieves the fill rule set using cogl_path_set_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 fill rule of the
- * path. See %CoglPathFillRule for details.
- **/
-void
-cogl_path_fill (void);
-
-/**
- * cogl_path_fill_preserve:
- *
- * Fills the interior of the constructed shape using the current
- * drawing color and preserves the path to be used again. See
- * cogl_path_fill() for a description what is considered the interior
- * of the shape.
- *
- * Since: 1.0
- **/
-void
-cogl_path_fill_preserve (void);
-
-/**
- * cogl_path_stroke:
- *
- * Strokes the constructed shape using the current drawing color and a
- * width of 1 pixel (regardless of the current transformation
- * matrix). To current path is then cleared. To use the path again,
- * call cogl_path_stroke_preserve() instead.
- **/
-void
-cogl_path_stroke (void);
-
-/**
- * cogl_path_stroke_preserve:
- *
- * Strokes the constructed shape using the current drawing color and
- * preserves the path to be used again.
- *
- * Since: 1.0
- **/
-void
-cogl_path_stroke_preserve (void);
-
-/**
- * cogl_path_new:
- *
- * 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
- */
-void
-cogl_path_new (void);
-
-/**
- * cogl_path_move_to:
- * @x: X coordinate of the pen location to move to.
- * @y: Y coordinate of the pen location to move to.
- *
- * Moves the pen to the given location. If there is an existing path
- * this will start a new disjoint subpath.
-  **/
-void
-cogl_path_move_to (float x,
-                   float y);
-
-
-/**
- * cogl_path_rel_move_to:
- * @x: X offset from the current pen location to move the pen to.
- * @y: Y offset from the current pen location to move the pen to.
- *
- * Moves the pen to the given offset relative to the current pen
- * location. If there is an existing path this will start a new
- * disjoint subpath.
- **/
-void
-cogl_path_rel_move_to (float x,
-                       float y);
-
-/**
- * cogl_path_line_to:
- * @x: X coordinate of the end line vertex
- * @y: Y coordinate of the end line vertex
- *
- * Adds a straight line segment to the current path that ends at the
- * given coordinates.
- **/
-void
-cogl_path_line_to (float x,
-                   float y);
-
-/**
- * cogl_path_rel_line_to:
- * @x: X offset from the current pen location of the end line vertex
- * @y: Y offset from the current pen location of the end line vertex
- *
- * Adds a straight line segment to the current path that ends at the
- * given coordinates relative to the current pen location.
- **/
-void
-cogl_path_rel_line_to (float x,
-                       float y);
-
-
-/**
- * cogl_path_arc:
- * @center_x: X coordinate of the elliptical arc center
- * @center_y: Y coordinate of the elliptical arc center
- * @radius_x: X radius of the elliptical arc
- * @radius_y: Y radius of the elliptical arc
- * @angle_1: Angle in degrees at which the arc begin
- * @angle_2: Angle in degrees at which the arc ends
- *
- * Adds an elliptical arc segment to the current path. A straight line
- * segment will link the current pen location with the first vertex
- * of the arc. If you perform a move_to to the arcs start just before
- * drawing it you create a free standing arc.
- *
- * The angles are measured in degrees where 0° is in the direction of
- * the positive X axis and 90° is in the direction of the positive Y
- * axis. The angle of the arc begins at @angle_1 and heads towards
- * @angle_2 (so if @angle_2 is less than @angle_1 it will decrease,
- * otherwise it will increase).
- **/
-void
-cogl_path_arc (float center_x,
-               float center_y,
-               float radius_x,
-               float radius_y,
-               float angle_1,
-               float angle_2);
-
-/**
- * cogl_path_curve_to:
- * @x_1: X coordinate of the second bezier control point
- * @y_1: Y coordinate of the second bezier control point
- * @x_2: X coordinate of the third bezier control point
- * @y_2: Y coordinate of the third bezier control point
- * @x_3: X coordinate of the fourth bezier control point
- * @y_3: Y coordinate of the fourth bezier control point
- *
- * Adds a cubic bezier curve segment to the current path with the given
- * second, third and fourth control points and using current pen location
- * as the first control point.
- **/
-void
-cogl_path_curve_to (float x_1,
-                    float y_1,
-                    float x_2,
-                    float y_2,
-                    float x_3,
-                    float y_3);
-
-/**
- * cogl_path_rel_curve_to:
- * @x_1: X coordinate of the second bezier control point
- * @y_1: Y coordinate of the second bezier control point
- * @x_2: X coordinate of the third bezier control point
- * @y_2: Y coordinate of the third bezier control point
- * @x_3: X coordinate of the fourth bezier control point
- * @y_3: Y coordinate of the fourth bezier control point
- *
- * Adds a cubic bezier curve segment to the current path with the given
- * second, third and fourth control points and using current pen location
- * as the first control point. The given coordinates are relative to the
- * current pen location.
- */
-void
-cogl_path_rel_curve_to (float x_1,
-                        float y_1,
-                        float x_2,
-                        float y_2,
-                        float x_3,
-                        float y_3);
-
-/**
- * cogl_path_close:
- *
- * Closes the path being constructed by adding a straight line segment
- * to it that ends at the first vertex of the path.
- **/
-void
-cogl_path_close (void);
-
-/**
- * cogl_path_line:
- * @x_1: X coordinate of the start line vertex
- * @y_1: Y coordinate of the start line vertex
- * @x_2: X coordinate of the end line vertex
- * @y_2: Y coordinate of the end line vertex
- *
- * Constructs a straight line shape starting and ending at the given
- * coordinates. If there is an existing path this will start a new
- * disjoint sub-path.
- **/
-void
-cogl_path_line (float x_1,
-                float y_1,
-                float x_2,
-                float y_2);
-
-/**
- * cogl_path_polyline:
- * @coords: (in) (array) (transfer none): A pointer to the first element of an
- * array of fixed-point values that specify the vertex coordinates.
- * @num_points: The total number of vertices.
- *
- * Constructs a series of straight line segments, starting from the
- * first given vertex coordinate. If there is an existing path this
- * will start a new disjoint sub-path. Each subsequent segment starts
- * where the previous one ended and ends at the next given vertex
- * coordinate.
- *
- * The coords array must contain 2 * num_points values. The first value
- * represents the X coordinate of the first vertex, the second value
- * represents the Y coordinate of the first vertex, continuing in the same
- * fashion for the rest of the vertices. (num_points - 1) segments will
- * be constructed.
- **/
-void
-cogl_path_polyline (const float *coords,
-                    int          num_points);
-
-
-/**
- * cogl_path_polygon:
- * @coords: (in) (array) (transfer none): A pointer to the first element of
- * an array of fixed-point values that specify the vertex coordinates.
- * @num_points: The total number of vertices.
- *
- * Constructs a polygonal shape of the given number of vertices. If
- * there is an existing path this will start a new disjoint sub-path.
- *
- * The coords array must contain 2 * num_points values. The first value
- * represents the X coordinate of the first vertex, the second value
- * represents the Y coordinate of the first vertex, continuing in the same
- * fashion for the rest of the vertices.
- **/
-void
-cogl_path_polygon (const float *coords,
-                   int          num_points);
-
-
-/**
- * cogl_path_rectangle:
- * @x_1: X coordinate of the top-left corner.
- * @y_1: Y coordinate of the top-left corner.
- * @x_2: X coordinate of the bottom-right corner.
- * @y_2: Y coordinate of the bottom-right corner.
- *
- * Constructs a rectangular shape at the given coordinates. If there
- * is an existing path this will start a new disjoint sub-path.
- **/
-void
-cogl_path_rectangle (float x_1,
-                     float y_1,
-                     float x_2,
-                     float y_2);
-
-/**
- * cogl_path_ellipse:
- * @center_x: X coordinate of the ellipse center
- * @center_y: Y coordinate of the ellipse center
- * @radius_x: X radius of the ellipse
- * @radius_y: Y radius of the ellipse
- *
- * Constructs an ellipse shape. If there is an existing path this will
- * start a new disjoint sub-path.
- **/
-void
-cogl_path_ellipse (float center_x,
-                   float center_y,
-                   float radius_x,
-                   float radius_y);
-
-/**
- * cogl_path_round_rectangle:
- * @x_1: X coordinate of the top-left corner.
- * @y_1: Y coordinate of the top-left corner.
- * @x_2: X coordinate of the bottom-right corner.
- * @y_2: Y coordinate of the bottom-right corner.
- * @radius: Radius of the corner arcs.
- * @arc_step: Angle increment resolution for subdivision of
- * the corner arcs.
- *
- * Constructs a rectangular shape with rounded corners. If there is an
- * existing path this will start a new disjoint sub-path.
- **/
-void
-cogl_path_round_rectangle (float x_1,
-                           float y_1,
-                           float x_2,
-                           float y_2,
-                           float radius,
-                           float arc_step);
-
-/**
- * cogl_get_path: (skip)
- *
- * Gets a pointer to the current path. The path can later be used
- * again by calling cogl_path_set(). Note that the path isn't copied
- * so if you later call any functions to add to the path it will
- * affect the returned object too. No reference is taken on the path
- * so if you want to retain it you should take your own reference with
- * cogl_object_ref().
- *
- * Return value: a pointer to the current path.
- *
- * Since: 1.4
- */
-CoglPath *
-cogl_get_path (void);
-
-/**
- * cogl_set_path: (skip)
- * @path: A #CoglPath object
- *
- * Replaces the current path with @path. A reference is taken on the
- * object so if you no longer need the path you should unref with
- * cogl_object_unref().
- *
- * Since: 1.4
- */
-void
-cogl_set_path (CoglPath *path);
-
-/**
- * cogl_path_copy: (skip)
- * @path: A #CoglPath object
- *
- * Returns a new copy of the path in @path. The new path has a
- * reference count of 1 so you should unref it with
- * cogl_object_unref() if you no longer need it.
- *
- * Internally the path will share the data until one of the paths is
- * modified so copying paths should be relatively cheap.
- *
- * Return value: (transfer full): a copy of the path in @path.
- */
-CoglPath *
-cogl_path_copy (CoglPath *path);
-
-G_END_DECLS
-
-#endif /* __COGL_PATH_FUNCTIONS_H__ */
-
diff --git a/cogl/cogl-path.c b/cogl/cogl-path.c
index aab3dfb..571114b 100644
--- a/cogl/cogl-path.c
+++ b/cogl/cogl-path.c
@@ -3,7 +3,7 @@
  *
  * An object oriented GL/GLES Abstraction/Utility Layer
  *
- * Copyright (C) 2010 Intel Corporation.
+ * Copyright (C) 2007,2008,2009,2010 Intel Corporation.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -20,7 +20,10 @@
  * <http://www.gnu.org/licenses/>.
  *
  * Authors:
- *  Robert Bragg <robert at linux.intel.com>
+ *  Ivan Leben    <ivan at openedhand.com>
+ *  Øyvind Kolås  <pippin at linux.intel.com>
+ *  Neil Roberts  <neil at linux.intel.com>
+ *  Robert Bragg  <robert at linux.intel.com>
  */
 
 #ifdef HAVE_CONFIG_H
@@ -28,279 +31,1419 @@
 #endif
 
 #include "cogl-util.h"
+#include "cogl-object.h"
 #include "cogl-internal.h"
 #include "cogl-context-private.h"
-#include "cogl2-path.h"
+#include "cogl-journal-private.h"
+#include "cogl-pipeline-private.h"
+#include "cogl-pipeline-opengl-private.h"
+#include "cogl-framebuffer-private.h"
+#include "cogl-path-private.h"
+#include "cogl-texture-private.h"
+#include "cogl-primitives-private.h"
+#include "cogl-private.h"
+#include "cogl-attribute-private.h"
+#include "cogl1-context.h"
+#include "tesselator/tesselator.h"
 
 #include <string.h>
 #include <math.h>
 
-#undef cogl_path_set_fill_rule
-#undef cogl_path_get_fill_rule
-#undef cogl_path_fill
-#undef cogl_path_fill_preserve
-#undef cogl_path_stroke
-#undef cogl_path_stroke_preserve
-#undef cogl_path_move_to
-#undef cogl_path_rel_move_to
-#undef cogl_path_line_to
-#undef cogl_path_rel_line_to
-#undef cogl_path_close
-#undef cogl_path_new
-#undef cogl_path_line
-#undef cogl_path_polyline
-#undef cogl_path_polygon
-#undef cogl_path_rectangle
-#undef cogl_path_arc
-#undef cogl_path_ellipse
-#undef cogl_path_round_rectangle
-#undef cogl_path_curve_to
-#undef cogl_path_rel_curve_to
-
-#include "cogl-path-functions.h"
+#define _COGL_MAX_BEZ_RECURSE_DEPTH 16
+
+static void _cogl_path_free (CoglPath *path);
+
+static void _cogl_path_build_fill_attribute_buffer (CoglPath *path);
+static void _cogl_path_build_stroke_attribute_buffer (CoglPath *path);
+
+COGL_OBJECT_DEFINE (Path, path);
+
+static void
+_cogl_path_data_clear_vbos (CoglPathData *data)
+{
+  int i;
+
+  if (data->fill_attribute_buffer)
+    {
+      cogl_object_unref (data->fill_attribute_buffer);
+      cogl_object_unref (data->fill_vbo_indices);
+
+      for (i = 0; i < COGL_PATH_N_ATTRIBUTES; i++)
+        cogl_object_unref (data->fill_attributes[i]);
+
+      data->fill_attribute_buffer = NULL;
+    }
+
+  if (data->stroke_attribute_buffer)
+    {
+      cogl_object_unref (data->stroke_attribute_buffer);
+
+      for (i = 0; i < data->stroke_n_attributes; i++)
+        cogl_object_unref (data->stroke_attributes[i]);
+
+      g_free (data->stroke_attributes);
+
+      data->stroke_attribute_buffer = NULL;
+    }
+}
+
+static void
+_cogl_path_data_unref (CoglPathData *data)
+{
+  if (--data->ref_count <= 0)
+    {
+      _cogl_path_data_clear_vbos (data);
+
+      g_array_free (data->path_nodes, TRUE);
+
+      g_slice_free (CoglPathData, data);
+    }
+}
+
+static void
+_cogl_path_modify (CoglPath *path)
+{
+  /* This needs to be called whenever the path is about to be modified
+     to implement copy-on-write semantics */
+
+  /* If there is more than one path using the data then we need to
+     copy the data instead */
+  if (path->data->ref_count != 1)
+    {
+      CoglPathData *old_data = path->data;
+
+      path->data = g_slice_dup (CoglPathData, old_data);
+      path->data->path_nodes = g_array_new (FALSE, FALSE,
+                                            sizeof (CoglPathNode));
+      g_array_append_vals (path->data->path_nodes,
+                           old_data->path_nodes->data,
+                           old_data->path_nodes->len);
+
+      path->data->fill_attribute_buffer = NULL;
+      path->data->stroke_attribute_buffer = NULL;
+      path->data->ref_count = 1;
+
+      _cogl_path_data_unref (old_data);
+    }
+  else
+    /* The path is altered so the vbos will now be invalid */
+    _cogl_path_data_clear_vbos (path->data);
+}
 
 void
-cogl_path_set_fill_rule (CoglPathFillRule fill_rule)
+cogl_path_set_fill_rule (CoglPath *path,
+                         CoglPathFillRule fill_rule)
 {
-  _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+  _COGL_RETURN_IF_FAIL (cogl_is_path (path));
+
+  if (path->data->fill_rule != fill_rule)
+    {
+      _cogl_path_modify (path);
 
-  cogl2_path_set_fill_rule (ctx->current_path, fill_rule);
+      path->data->fill_rule = fill_rule;
+    }
 }
 
 CoglPathFillRule
-cogl_path_get_fill_rule (void)
+cogl_path_get_fill_rule (CoglPath *path)
 {
-  _COGL_GET_CONTEXT (ctx, COGL_PATH_FILL_RULE_EVEN_ODD);
+  _COGL_RETURN_VAL_IF_FAIL (cogl_is_path (path), COGL_PATH_FILL_RULE_NON_ZERO);
 
-  return cogl2_path_get_fill_rule (ctx->current_path);
+  return path->data->fill_rule;
 }
 
-void
-cogl_path_fill (void)
+static void
+_cogl_path_add_node (CoglPath *path,
+                     gboolean new_sub_path,
+		     float x,
+		     float y)
 {
-  _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+  CoglPathNode new_node;
+  CoglPathData *data;
 
-  cogl2_path_fill (ctx->current_path);
+  _cogl_path_modify (path);
 
-  cogl_object_unref (ctx->current_path);
-  ctx->current_path = cogl2_path_new ();
+  data = path->data;
+
+  new_node.x = x;
+  new_node.y = y;
+  new_node.path_size = 0;
+
+  if (new_sub_path || data->path_nodes->len == 0)
+    data->last_path = data->path_nodes->len;
+
+  g_array_append_val (data->path_nodes, new_node);
+
+  g_array_index (data->path_nodes, CoglPathNode, data->last_path).path_size++;
+
+  if (data->path_nodes->len == 1)
+    {
+      data->path_nodes_min.x = data->path_nodes_max.x = x;
+      data->path_nodes_min.y = data->path_nodes_max.y = y;
+    }
+  else
+    {
+      if (x < data->path_nodes_min.x)
+        data->path_nodes_min.x = x;
+      if (x > data->path_nodes_max.x)
+        data->path_nodes_max.x = x;
+      if (y < data->path_nodes_min.y)
+        data->path_nodes_min.y = y;
+      if (y > data->path_nodes_max.y)
+        data->path_nodes_max.y = y;
+    }
+
+  /* Once the path nodes have been modified then we'll assume it's no
+     longer a rectangle. cogl_path_rectangle will set this back to
+     TRUE if this has been called from there */
+  data->is_rectangle = FALSE;
 }
 
-void
-cogl_path_fill_preserve (void)
+static void
+_cogl_path_stroke_nodes (CoglPath *path)
 {
+  CoglPathData *data = path->data;
+  CoglPipeline *copy = NULL;
+  CoglPipeline *source;
+  unsigned int path_start;
+  int path_num = 0;
+  CoglPathNode *node;
+
   _COGL_GET_CONTEXT (ctx, NO_RETVAL);
 
-  cogl2_path_fill (ctx->current_path);
+  source = cogl_get_source ();
+
+  if (cogl_pipeline_get_n_layers (source) != 0)
+    {
+      copy = cogl_pipeline_copy (source);
+      _cogl_pipeline_prune_to_n_layers (copy, 0);
+      source = copy;
+    }
+
+  _cogl_path_build_stroke_attribute_buffer (path);
+
+  cogl_push_source (source);
+
+  for (path_start = 0;
+       path_start < data->path_nodes->len;
+       path_start += node->path_size)
+    {
+      node = &g_array_index (data->path_nodes, CoglPathNode, path_start);
+
+      cogl_framebuffer_vdraw_attributes (cogl_get_draw_framebuffer (),
+                                         source,
+                                         COGL_VERTICES_MODE_LINE_STRIP,
+                                         0, node->path_size,
+                                         data->stroke_attributes[path_num],
+                                         NULL);
+
+      path_num++;
+    }
+
+  cogl_pop_source ();
+
+  if (copy)
+    cogl_object_unref (copy);
 }
 
 void
-cogl_path_stroke (void)
+_cogl_path_get_bounds (CoglPath *path,
+                       float *min_x,
+                       float *min_y,
+                       float *max_x,
+                       float *max_y)
 {
+  CoglPathData *data = path->data;
+
+  if (data->path_nodes->len == 0)
+    {
+      *min_x = 0.0f;
+      *min_y = 0.0f;
+      *max_x = 0.0f;
+      *max_y = 0.0f;
+    }
+  else
+    {
+      *min_x = data->path_nodes_min.x;
+      *min_y = data->path_nodes_min.y;
+      *max_x = data->path_nodes_max.x;
+      *max_y = data->path_nodes_max.y;
+    }
+}
+
+static void
+_cogl_path_fill_nodes_with_clipped_rectangle (CoglPath *path)
+{
+  CoglFramebuffer *fb;
+
   _COGL_GET_CONTEXT (ctx, NO_RETVAL);
 
-  cogl2_path_stroke (ctx->current_path);
+  if (!(ctx->private_feature_flags & COGL_PRIVATE_FEATURE_STENCIL_BUFFER))
+    {
+      static gboolean seen_warning = FALSE;
+
+      if (!seen_warning)
+        {
+          g_warning ("Paths can not be filled using materials with "
+                     "sliced textures unless there is a stencil "
+                     "buffer");
+          seen_warning = TRUE;
+        }
+    }
+
+  fb = cogl_get_draw_framebuffer ();
+  cogl_framebuffer_push_path_clip (fb, path);
+  cogl_rectangle (path->data->path_nodes_min.x,
+                  path->data->path_nodes_min.y,
+                  path->data->path_nodes_max.x,
+                  path->data->path_nodes_max.y);
+  cogl_framebuffer_pop_clip (fb);
+}
+
+static gboolean
+validate_layer_cb (CoglPipelineLayer *layer, void *user_data)
+{
+  gboolean *needs_fallback = user_data;
+  CoglTexture *texture = _cogl_pipeline_layer_get_texture (layer);
+
+  /* If any of the layers of the current pipeline contain sliced
+   * textures or textures with waste then it won't work to draw the
+   * path directly. Instead we fallback to pushing the path as a clip
+   * on the clip-stack and drawing the path's bounding rectangle
+   * instead.
+   */
+
+  if (texture != NULL && (cogl_texture_is_sliced (texture) ||
+                          !_cogl_texture_can_hardware_repeat (texture)))
+    *needs_fallback = TRUE;
 
-  cogl_object_unref (ctx->current_path);
-  ctx->current_path = cogl2_path_new ();
+  return !*needs_fallback;
 }
 
 void
-cogl_path_stroke_preserve (void)
+_cogl_path_fill_nodes (CoglPath *path, CoglDrawFlags flags)
 {
-  _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+  gboolean needs_fallback = FALSE;
+  CoglPipeline *pipeline = cogl_get_source ();
+
+  _cogl_pipeline_foreach_layer_internal (pipeline,
+                                         validate_layer_cb, &needs_fallback);
+  if (needs_fallback)
+    {
+      _cogl_path_fill_nodes_with_clipped_rectangle (path);
+      return;
+    }
+
+  _cogl_path_build_fill_attribute_buffer (path);
 
-  cogl2_path_stroke (ctx->current_path);
+  _cogl_framebuffer_draw_indexed_attributes (cogl_get_draw_framebuffer (),
+                                             pipeline,
+                                             COGL_VERTICES_MODE_TRIANGLES,
+                                             0, /* first_vertex */
+                                             path->data->fill_vbo_n_indices,
+                                             path->data->fill_vbo_indices,
+                                             path->data->fill_attributes,
+                                             COGL_PATH_N_ATTRIBUTES,
+                                             flags);
 }
 
 void
-cogl_path_move_to (float x,
-                   float y)
+cogl_path_fill (CoglPath *path)
 {
-  _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+  _COGL_RETURN_IF_FAIL (cogl_is_path (path));
+
+  if (path->data->path_nodes->len == 0)
+    return;
+
+  /* If the path is a simple rectangle then we can divert to using
+     cogl_rectangle which should be faster because it can go through
+     the journal instead of uploading the geometry just for two
+     triangles */
+  if (path->data->is_rectangle)
+    {
+      float x_1, y_1, x_2, y_2;
 
-  cogl2_path_move_to (ctx->current_path, x, y);
+      _cogl_path_get_bounds (path, &x_1, &y_1, &x_2, &y_2);
+      cogl_rectangle (x_1, y_1, x_2, y_2);
+    }
+  else
+    _cogl_path_fill_nodes (path, 0);
 }
 
 void
-cogl_path_rel_move_to (float x,
-                       float y)
+cogl_path_stroke (CoglPath *path)
 {
-  _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+  _COGL_RETURN_IF_FAIL (cogl_is_path (path));
+
+  if (path->data->path_nodes->len == 0)
+    return;
 
-  cogl2_path_rel_move_to (ctx->current_path, x, y);
+  _cogl_path_stroke_nodes (path);
 }
 
 void
-cogl_path_line_to (float x,
+cogl_path_move_to (CoglPath *path,
+                   float x,
                    float y)
 {
-  _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+  CoglPathData *data;
+
+  _COGL_RETURN_IF_FAIL (cogl_is_path (path));
 
-  cogl2_path_line_to (ctx->current_path, x, y);
+  _cogl_path_add_node (path, TRUE, x, y);
+
+  data = path->data;
+
+  data->path_start.x = x;
+  data->path_start.y = y;
+
+  data->path_pen = data->path_start;
 }
 
 void
-cogl_path_rel_line_to (float x,
+cogl_path_rel_move_to (CoglPath *path,
+                       float x,
                        float y)
 {
-  _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+  CoglPathData *data;
 
-  cogl2_path_rel_line_to (ctx->current_path, x, y);
+  _COGL_RETURN_IF_FAIL (cogl_is_path (path));
+
+  data = path->data;
+
+  cogl_path_move_to (path,
+                     data->path_pen.x + x,
+                     data->path_pen.y + y);
 }
 
 void
-cogl_path_close (void)
+cogl_path_line_to (CoglPath *path,
+                   float x,
+                   float y)
 {
-  _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+  CoglPathData *data;
 
-  cogl2_path_close (ctx->current_path);
+  _COGL_RETURN_IF_FAIL (cogl_is_path (path));
+
+  _cogl_path_add_node (path, FALSE, x, y);
+
+  data = path->data;
+
+  data->path_pen.x = x;
+  data->path_pen.y = y;
 }
 
 void
-cogl_path_new (void)
+cogl_path_rel_line_to (CoglPath *path,
+                       float x,
+                       float y)
 {
-  _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+  CoglPathData *data;
+
+  _COGL_RETURN_IF_FAIL (cogl_is_path (path));
+
+  data = path->data;
 
-  cogl_object_unref (ctx->current_path);
-  ctx->current_path = cogl2_path_new ();
+  cogl_path_line_to (path,
+                     data->path_pen.x + x,
+                     data->path_pen.y + y);
 }
 
 void
-cogl_path_line (float x_1,
-	        float y_1,
-	        float x_2,
-	        float y_2)
+cogl_path_close (CoglPath *path)
 {
-  _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+  _COGL_RETURN_IF_FAIL (cogl_is_path (path));
 
-  cogl2_path_line (ctx->current_path, x_1, y_1, x_2, y_2);
+  _cogl_path_add_node (path, FALSE, path->data->path_start.x,
+                       path->data->path_start.y);
+
+  path->data->path_pen = path->data->path_start;
 }
 
 void
-cogl_path_polyline (const float *coords,
-	            int num_points)
+cogl_path_line (CoglPath *path,
+                float x_1,
+                float y_1,
+                float x_2,
+                float y_2)
 {
-  _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
-  cogl2_path_polyline (ctx->current_path, coords, num_points);
+  cogl_path_move_to (path, x_1, y_1);
+  cogl_path_line_to (path, x_2, y_2);
 }
 
 void
-cogl_path_polygon (const float *coords,
-	           int num_points)
+cogl_path_polyline (CoglPath *path,
+                    const float *coords,
+                    int num_points)
 {
-  _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+  int c = 0;
+
+  _COGL_RETURN_IF_FAIL (cogl_is_path (path));
+
+  cogl_path_move_to (path, coords[0], coords[1]);
 
-  cogl2_path_polygon (ctx->current_path, coords, num_points);
+  for (c = 1; c < num_points; ++c)
+    cogl_path_line_to (path, coords[2*c], coords[2*c+1]);
 }
 
 void
-cogl_path_rectangle (float x_1,
+cogl_path_polygon (CoglPath *path,
+                   const float *coords,
+                   int num_points)
+{
+  cogl_path_polyline (path, coords, num_points);
+  cogl_path_close (path);
+}
+
+void
+cogl_path_rectangle (CoglPath *path,
+                     float x_1,
                      float y_1,
                      float x_2,
                      float y_2)
 {
-  _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+  gboolean is_rectangle;
+
+  /* If the path was previously empty and the rectangle isn't mirrored
+     then we'll record that this is a simple rectangle path so that we
+     can optimise it */
+  is_rectangle = (path->data->path_nodes->len == 0 &&
+                  x_2 >= x_1 &&
+                  y_2 >= y_1);
+
+  cogl_path_move_to (path, x_1, y_1);
+  cogl_path_line_to (path, x_2, y_1);
+  cogl_path_line_to (path, x_2, y_2);
+  cogl_path_line_to (path, x_1, y_2);
+  cogl_path_close (path);
+
+  path->data->is_rectangle = is_rectangle;
+}
+
+gboolean
+_cogl_path_is_rectangle (CoglPath *path)
+{
+  return path->data->is_rectangle;
+}
+
+static void
+_cogl_path_arc (CoglPath *path,
+                float center_x,
+	        float center_y,
+                float radius_x,
+                float radius_y,
+                float angle_1,
+                float angle_2,
+                float angle_step,
+                unsigned int move_first)
+{
+  float a = 0x0;
+  float cosa = 0x0;
+  float sina = 0x0;
+  float px = 0x0;
+  float py = 0x0;
 
-  cogl2_path_rectangle (ctx->current_path, x_1, y_1, x_2, y_2);
+  /* Fix invalid angles */
+
+  if (angle_1 == angle_2 || angle_step == 0x0)
+    return;
+
+  if (angle_step < 0x0)
+    angle_step = -angle_step;
+
+  /* Walk the arc by given step */
+
+  a = angle_1;
+  while (a != angle_2)
+    {
+      cosa = cosf (a * (G_PI/180.0));
+      sina = sinf (a * (G_PI/180.0));
+
+      px = center_x + (cosa * radius_x);
+      py = center_y + (sina * radius_y);
+
+      if (a == angle_1 && move_first)
+	cogl_path_move_to (path, px, py);
+      else
+	cogl_path_line_to (path, px, py);
+
+      if (G_LIKELY (angle_2 > angle_1))
+        {
+          a += angle_step;
+          if (a > angle_2)
+            a = angle_2;
+        }
+      else
+        {
+          a -= angle_step;
+          if (a < angle_2)
+            a = angle_2;
+        }
+    }
+
+  /* Make sure the final point is drawn */
+
+  cosa = cosf (angle_2 * (G_PI/180.0));
+  sina = sinf (angle_2 * (G_PI/180.0));
+
+  px = center_x + (cosa * radius_x);
+  py = center_y + (sina * radius_y);
+
+  cogl_path_line_to (path, px, py);
 }
 
 void
-cogl_path_arc (float center_x,
+cogl_path_arc (CoglPath *path,
+               float center_x,
                float center_y,
                float radius_x,
                float radius_y,
                float angle_1,
                float angle_2)
 {
-  _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+  float angle_step = 10;
+
+  _COGL_RETURN_IF_FAIL (cogl_is_path (path));
+
+  /* it is documented that a move to is needed to create a freestanding
+   * arc
+   */
+  _cogl_path_arc (path,
+                  center_x, center_y,
+	          radius_x, radius_y,
+	          angle_1, angle_2,
+	          angle_step, 0 /* no move */);
+}
+
+
+static void
+_cogl_path_rel_arc (CoglPath *path,
+                    float center_x,
+                    float center_y,
+                    float radius_x,
+                    float radius_y,
+                    float angle_1,
+                    float angle_2,
+                    float angle_step)
+{
+  CoglPathData *data;
 
-  cogl2_path_arc (ctx->current_path,
-                  center_x,
-                  center_y,
-                  radius_x,
-                  radius_y,
-                  angle_1,
-                  angle_2);
+  data = path->data;
+
+  _cogl_path_arc (path,
+                  data->path_pen.x + center_x,
+	          data->path_pen.y + center_y,
+	          radius_x, radius_y,
+	          angle_1, angle_2,
+	          angle_step, 0 /* no move */);
 }
 
 void
-cogl_path_ellipse (float center_x,
+cogl_path_ellipse (CoglPath *path,
+                   float center_x,
                    float center_y,
                    float radius_x,
                    float radius_y)
 {
-  _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+  float angle_step = 10;
+
+  _COGL_RETURN_IF_FAIL (cogl_is_path (path));
+
+  /* FIXME: if shows to be slow might be optimized
+   * by mirroring just a quarter of it */
 
-  cogl2_path_ellipse (ctx->current_path,
-                      center_x,
-                      center_y,
-                      radius_x,
-                      radius_y);
+  _cogl_path_arc (path,
+                  center_x, center_y,
+	          radius_x, radius_y,
+	          0, 360,
+	          angle_step, 1 /* move first */);
+
+  cogl_path_close (path);
 }
 
 void
-cogl_path_round_rectangle (float x_1,
+cogl_path_round_rectangle (CoglPath *path,
+                           float x_1,
                            float y_1,
                            float x_2,
                            float y_2,
                            float radius,
                            float arc_step)
 {
-  _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+  float inner_width = x_2 - x_1 - radius * 2;
+  float inner_height = y_2 - y_1 - radius * 2;
+
+  _COGL_RETURN_IF_FAIL (cogl_is_path (path));
+
+  cogl_path_move_to (path, x_1, y_1 + radius);
+  _cogl_path_rel_arc (path,
+                      radius, 0,
+                      radius, radius,
+                      180,
+                      270,
+                      arc_step);
 
-  cogl2_path_round_rectangle (ctx->current_path,
-                              x_1, y_1, x_2, y_2, radius, arc_step);
+  cogl_path_line_to (path,
+                     path->data->path_pen.x + inner_width,
+                     path->data->path_pen.y);
+  _cogl_path_rel_arc (path,
+                      0, radius,
+                      radius, radius,
+                      -90,
+                      0,
+                      arc_step);
+
+  cogl_path_line_to (path,
+                     path->data->path_pen.x,
+                     path->data->path_pen.y + inner_height);
+
+  _cogl_path_rel_arc (path,
+                      -radius, 0,
+                      radius, radius,
+                      0,
+                      90,
+                      arc_step);
+
+  cogl_path_line_to (path,
+                     path->data->path_pen.x - inner_width,
+                     path->data->path_pen.y);
+  _cogl_path_rel_arc (path,
+                      0, -radius,
+                      radius, radius,
+                      90,
+                      180,
+                      arc_step);
+
+  cogl_path_close (path);
+}
+
+static void
+_cogl_path_bezier3_sub (CoglPath *path,
+                        CoglBezCubic *cubic)
+{
+  CoglBezCubic cubics[_COGL_MAX_BEZ_RECURSE_DEPTH];
+  CoglBezCubic *cleft;
+  CoglBezCubic *cright;
+  CoglBezCubic *c;
+  floatVec2 dif1;
+  floatVec2 dif2;
+  floatVec2 mm;
+  floatVec2 c1;
+  floatVec2 c2;
+  floatVec2 c3;
+  floatVec2 c4;
+  floatVec2 c5;
+  int cindex;
+
+  /* Put first curve on stack */
+  cubics[0] = *cubic;
+  cindex =  0;
+
+  while (cindex >= 0)
+    {
+      c = &cubics[cindex];
+
+
+      /* Calculate distance of control points from their
+       * counterparts on the line between end points */
+      dif1.x = (c->p2.x * 3) - (c->p1.x * 2) - c->p4.x;
+      dif1.y = (c->p2.y * 3) - (c->p1.y * 2) - c->p4.y;
+      dif2.x = (c->p3.x * 3) - (c->p4.x * 2) - c->p1.x;
+      dif2.y = (c->p3.y * 3) - (c->p4.y * 2) - c->p1.y;
+
+      if (dif1.x < 0)
+        dif1.x = -dif1.x;
+      if (dif1.y < 0)
+        dif1.y = -dif1.y;
+      if (dif2.x < 0)
+        dif2.x = -dif2.x;
+      if (dif2.y < 0)
+        dif2.y = -dif2.y;
+
+
+      /* Pick the greatest of two distances */
+      if (dif1.x < dif2.x) dif1.x = dif2.x;
+      if (dif1.y < dif2.y) dif1.y = dif2.y;
+
+      /* Cancel if the curve is flat enough */
+      if (dif1.x + dif1.y <= 1.0 ||
+	  cindex == _COGL_MAX_BEZ_RECURSE_DEPTH-1)
+	{
+	  /* Add subdivision point (skip last) */
+	  if (cindex == 0)
+            return;
+
+	  _cogl_path_add_node (path, FALSE, c->p4.x, c->p4.y);
+
+	  --cindex;
+
+          continue;
+	}
+
+      /* Left recursion goes on top of stack! */
+      cright = c; cleft = &cubics[++cindex];
+
+      /* Subdivide into 2 sub-curves */
+      c1.x = ((c->p1.x + c->p2.x) / 2);
+      c1.y = ((c->p1.y + c->p2.y) / 2);
+      mm.x = ((c->p2.x + c->p3.x) / 2);
+      mm.y = ((c->p2.y + c->p3.y) / 2);
+      c5.x = ((c->p3.x + c->p4.x) / 2);
+      c5.y = ((c->p3.y + c->p4.y) / 2);
+
+      c2.x = ((c1.x + mm.x) / 2);
+      c2.y = ((c1.y + mm.y) / 2);
+      c4.x = ((mm.x + c5.x) / 2);
+      c4.y = ((mm.y + c5.y) / 2);
+
+      c3.x = ((c2.x + c4.x) / 2);
+      c3.y = ((c2.y + c4.y) / 2);
+
+      /* Add left recursion to stack */
+      cleft->p1 = c->p1;
+      cleft->p2 = c1;
+      cleft->p3 = c2;
+      cleft->p4 = c3;
+
+      /* Add right recursion to stack */
+      cright->p1 = c3;
+      cright->p2 = c4;
+      cright->p3 = c5;
+      cright->p4 = c->p4;
+    }
 }
 
 void
-cogl_path_curve_to (float x_1,
+cogl_path_curve_to (CoglPath *path,
+                    float x_1,
                     float y_1,
                     float x_2,
                     float y_2,
                     float x_3,
                     float y_3)
 {
-  _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+  CoglBezCubic cubic;
+
+  _COGL_RETURN_IF_FAIL (cogl_is_path (path));
+
+  /* Prepare cubic curve */
+  cubic.p1 = path->data->path_pen;
+  cubic.p2.x = x_1;
+  cubic.p2.y = y_1;
+  cubic.p3.x = x_2;
+  cubic.p3.y = y_2;
+  cubic.p4.x = x_3;
+  cubic.p4.y = y_3;
 
-  cogl2_path_curve_to (ctx->current_path,
-                       x_1, y_1, x_2, y_2, x_3, y_3);
+  /* Run subdivision */
+  _cogl_path_bezier3_sub (path, &cubic);
+
+  /* Add last point */
+  _cogl_path_add_node (path, FALSE, cubic.p4.x, cubic.p4.y);
+  path->data->path_pen = cubic.p4;
 }
 
 void
-cogl_path_rel_curve_to (float x_1,
+cogl_path_rel_curve_to (CoglPath *path,
+                        float x_1,
                         float y_1,
                         float x_2,
                         float y_2,
                         float x_3,
                         float y_3)
 {
-  _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+  CoglPathData *data;
+
+  _COGL_RETURN_IF_FAIL (cogl_is_path (path));
+
+  data = path->data;
 
-  cogl2_path_rel_curve_to (ctx->current_path,
-                           x_1, y_1, x_2, y_2, x_3, y_3);
+  cogl_path_curve_to (path,
+                      data->path_pen.x + x_1,
+                      data->path_pen.y + y_1,
+                      data->path_pen.x + x_2,
+                      data->path_pen.y + y_2,
+                      data->path_pen.x + x_3,
+                      data->path_pen.y + y_3);
 }
 
 CoglPath *
-cogl_get_path (void)
+cogl_path_new (void)
+{
+  CoglPath *path;
+  CoglPathData *data;
+
+  path = g_slice_new (CoglPath);
+  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->fill_attribute_buffer = NULL;
+  data->stroke_attribute_buffer = NULL;
+  data->is_rectangle = FALSE;
+
+  return _cogl_path_object_new (path);
+}
+
+CoglPath *
+cogl_path_copy (CoglPath *old_path)
+{
+  CoglPath *new_path;
+
+  _COGL_RETURN_VAL_IF_FAIL (cogl_is_path (old_path), NULL);
+
+  new_path = g_slice_new (CoglPath);
+  new_path->data = old_path->data;
+  new_path->data->ref_count++;
+
+  return _cogl_path_object_new (new_path);
+}
+
+static void
+_cogl_path_free (CoglPath *path)
 {
-  _COGL_GET_CONTEXT (ctx, NULL);
+  _cogl_path_data_unref (path->data);
+  g_slice_free (CoglPath, path);
+}
+
+/* If second order beziers were needed the following code could
+ * be re-enabled:
+ */
+#if 0
+
+static void
+_cogl_path_bezier2_sub (CoglPath *path,
+                        CoglBezQuad *quad)
+{
+  CoglBezQuad quads[_COGL_MAX_BEZ_RECURSE_DEPTH];
+  CoglBezQuad *qleft;
+  CoglBezQuad *qright;
+  CoglBezQuad *q;
+  floatVec2 mid;
+  floatVec2 dif;
+  floatVec2 c1;
+  floatVec2 c2;
+  floatVec2 c3;
+  int qindex;
+
+  /* Put first curve on stack */
+  quads[0] = *quad;
+  qindex =  0;
+
+  /* While stack is not empty */
+  while (qindex >= 0)
+    {
+
+      q = &quads[qindex];
+
+      /* Calculate distance of control point from its
+       * counterpart on the line between end points */
+      mid.x = ((q->p1.x + q->p3.x) / 2);
+      mid.y = ((q->p1.y + q->p3.y) / 2);
+      dif.x = (q->p2.x - mid.x);
+      dif.y = (q->p2.y - mid.y);
+      if (dif.x < 0) dif.x = -dif.x;
+      if (dif.y < 0) dif.y = -dif.y;
+
+      /* Cancel if the curve is flat enough */
+      if (dif.x + dif.y <= 1.0 ||
+          qindex == _COGL_MAX_BEZ_RECURSE_DEPTH - 1)
+	{
+	  /* Add subdivision point (skip last) */
+	  if (qindex == 0) return;
+	  _cogl_path_add_node (path, FALSE, q->p3.x, q->p3.y);
+	  --qindex; continue;
+	}
 
-  return ctx->current_path;
+      /* Left recursion goes on top of stack! */
+      qright = q; qleft = &quads[++qindex];
+
+      /* Subdivide into 2 sub-curves */
+      c1.x = ((q->p1.x + q->p2.x) / 2);
+      c1.y = ((q->p1.y + q->p2.y) / 2);
+      c3.x = ((q->p2.x + q->p3.x) / 2);
+      c3.y = ((q->p2.y + q->p3.y) / 2);
+      c2.x = ((c1.x + c3.x) / 2);
+      c2.y = ((c1.y + c3.y) / 2);
+
+      /* Add left recursion onto stack */
+      qleft->p1 = q->p1;
+      qleft->p2 = c1;
+      qleft->p3 = c2;
+
+      /* Add right recursion onto stack */
+      qright->p1 = c2;
+      qright->p2 = c3;
+      qright->p3 = q->p3;
+    }
 }
 
 void
-cogl_set_path (CoglPath *path)
+cogl_path_curve2_to (CoglPath *path,
+                     float x_1,
+                     float y_1,
+                     float x_2,
+                     float y_2)
 {
-  _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+  CoglBezQuad quad;
+
+  /* Prepare quadratic curve */
+  quad.p1 = path->data->path_pen;
+  quad.p2.x = x_1;
+  quad.p2.y = y_1;
+  quad.p3.x = x_2;
+  quad.p3.y = y_2;
+
+  /* Run subdivision */
+  _cogl_path_bezier2_sub (&quad);
+
+  /* Add last point */
+  _cogl_path_add_node (FALSE, quad.p3.x, quad.p3.y);
+  path->data->path_pen = quad.p3;
+}
+
+void
+cogl_rel_curve2_to (CoglPath *path,
+                    float x_1,
+                    float y_1,
+                    float x_2,
+                    float y_2)
+{
+  CoglPathData *data;
 
   _COGL_RETURN_IF_FAIL (cogl_is_path (path));
 
-  /* Reference the new object first in case it is the same as the old
-     object */
-  cogl_object_ref (path);
-  cogl_object_unref (ctx->current_path);
-  ctx->current_path = path;
+  data = path->data;
+
+  cogl_path_curve2_to (data->path_pen.x + x_1,
+                       data->path_pen.y + y_1,
+                       data->path_pen.x + x_2,
+                       data->path_pen.y + y_2);
+}
+
+#endif
+
+typedef struct _CoglPathTesselator CoglPathTesselator;
+typedef struct _CoglPathTesselatorVertex CoglPathTesselatorVertex;
+
+struct _CoglPathTesselator
+{
+  GLUtesselator *glu_tess;
+  GLenum primitive_type;
+  int vertex_number;
+  /* Array of CoglPathTesselatorVertex. This needs to grow when the
+     combine callback is called */
+  GArray *vertices;
+  /* Array of integers for the indices into the vertices array. Each
+     element will either be guint8, guint16 or guint32 depending on
+     the number of vertices */
+  GArray *indices;
+  CoglIndicesType indices_type;
+  /* Indices used to split fans and strips */
+  int index_a, index_b;
+};
+
+struct _CoglPathTesselatorVertex
+{
+  float x, y, s, t;
+};
+
+static void
+_cogl_path_tesselator_begin (GLenum type,
+                             CoglPathTesselator *tess)
+{
+  g_assert (type == GL_TRIANGLES ||
+            type == GL_TRIANGLE_FAN ||
+            type == GL_TRIANGLE_STRIP);
+
+  tess->primitive_type = type;
+  tess->vertex_number = 0;
 }
 
+static CoglIndicesType
+_cogl_path_tesselator_get_indices_type_for_size (int n_vertices)
+{
+  if (n_vertices <= 256)
+    return COGL_INDICES_TYPE_UNSIGNED_BYTE;
+  else if (n_vertices <= 65536)
+    return COGL_INDICES_TYPE_UNSIGNED_SHORT;
+  else
+    return COGL_INDICES_TYPE_UNSIGNED_INT;
+}
+
+static void
+_cogl_path_tesselator_allocate_indices_array (CoglPathTesselator *tess)
+{
+  switch (tess->indices_type)
+    {
+    case COGL_INDICES_TYPE_UNSIGNED_BYTE:
+      tess->indices = g_array_new (FALSE, FALSE, sizeof (guint8));
+      break;
+
+    case COGL_INDICES_TYPE_UNSIGNED_SHORT:
+      tess->indices = g_array_new (FALSE, FALSE, sizeof (guint16));
+      break;
+
+    case COGL_INDICES_TYPE_UNSIGNED_INT:
+      tess->indices = g_array_new (FALSE, FALSE, sizeof (guint32));
+      break;
+    }
+}
+
+static void
+_cogl_path_tesselator_add_index (CoglPathTesselator *tess, int vertex_index)
+{
+  switch (tess->indices_type)
+    {
+    case COGL_INDICES_TYPE_UNSIGNED_BYTE:
+      {
+        guint8 val = vertex_index;
+        g_array_append_val (tess->indices, val);
+      }
+      break;
+
+    case COGL_INDICES_TYPE_UNSIGNED_SHORT:
+      {
+        guint16 val = vertex_index;
+        g_array_append_val (tess->indices, val);
+      }
+      break;
+
+    case COGL_INDICES_TYPE_UNSIGNED_INT:
+      {
+        guint32 val = vertex_index;
+        g_array_append_val (tess->indices, val);
+      }
+      break;
+    }
+}
+
+static void
+_cogl_path_tesselator_vertex (void *vertex_data,
+                              CoglPathTesselator *tess)
+{
+  int vertex_index;
+
+  vertex_index = GPOINTER_TO_INT (vertex_data);
+
+  /* This tries to convert all of the primitives into GL_TRIANGLES
+     with indices to share vertices */
+  switch (tess->primitive_type)
+    {
+    case GL_TRIANGLES:
+      /* Directly use the vertex */
+      _cogl_path_tesselator_add_index (tess, vertex_index);
+      break;
+
+    case GL_TRIANGLE_FAN:
+      if (tess->vertex_number == 0)
+        tess->index_a = vertex_index;
+      else if (tess->vertex_number == 1)
+        tess->index_b = vertex_index;
+      else
+        {
+          /* Create a triangle with the first vertex, the previous
+             vertex and this vertex */
+          _cogl_path_tesselator_add_index (tess, tess->index_a);
+          _cogl_path_tesselator_add_index (tess, tess->index_b);
+          _cogl_path_tesselator_add_index (tess, vertex_index);
+          /* Next time we will use this vertex as the previous
+             vertex */
+          tess->index_b = vertex_index;
+        }
+      break;
+
+    case GL_TRIANGLE_STRIP:
+      if (tess->vertex_number == 0)
+        tess->index_a = vertex_index;
+      else if (tess->vertex_number == 1)
+        tess->index_b = vertex_index;
+      else
+        {
+          _cogl_path_tesselator_add_index (tess, tess->index_a);
+          _cogl_path_tesselator_add_index (tess, tess->index_b);
+          _cogl_path_tesselator_add_index (tess, vertex_index);
+          if (tess->vertex_number & 1)
+            tess->index_b = vertex_index;
+          else
+            tess->index_a = vertex_index;
+        }
+      break;
+
+    default:
+      g_assert_not_reached ();
+    }
+
+  tess->vertex_number++;
+}
+
+static void
+_cogl_path_tesselator_end (CoglPathTesselator *tess)
+{
+  tess->primitive_type = GL_FALSE;
+}
+
+static void
+_cogl_path_tesselator_combine (double coords[3],
+                               void *vertex_data[4],
+                               float weight[4],
+                               void **out_data,
+                               CoglPathTesselator *tess)
+{
+  CoglPathTesselatorVertex *vertex;
+  CoglIndicesType new_indices_type;
+  int i;
+
+  /* Add a new vertex to the array */
+  g_array_set_size (tess->vertices, tess->vertices->len + 1);
+  vertex = &g_array_index (tess->vertices,
+                           CoglPathTesselatorVertex,
+                           tess->vertices->len - 1);
+  /* The data is just the index to the vertex */
+  *out_data = GINT_TO_POINTER (tess->vertices->len - 1);
+  /* Set the coordinates of the new vertex */
+  vertex->x = coords[0];
+  vertex->y = coords[1];
+  /* Generate the texture coordinates as the weighted average of the
+     four incoming coordinates */
+  vertex->s = 0.0f;
+  vertex->t = 0.0f;
+  for (i = 0; i < 4; i++)
+    {
+      CoglPathTesselatorVertex *old_vertex =
+        &g_array_index (tess->vertices, CoglPathTesselatorVertex,
+                        GPOINTER_TO_INT (vertex_data[i]));
+      vertex->s += old_vertex->s * weight[i];
+      vertex->t += old_vertex->t * weight[i];
+    }
+
+  /* Check if we've reached the limit for the data type of our indices */
+  new_indices_type =
+    _cogl_path_tesselator_get_indices_type_for_size (tess->vertices->len);
+  if (new_indices_type != tess->indices_type)
+    {
+      CoglIndicesType old_indices_type = new_indices_type;
+      GArray *old_vertices = tess->indices;
+
+      /* Copy the indices to an array of the new type */
+      tess->indices_type = new_indices_type;
+      _cogl_path_tesselator_allocate_indices_array (tess);
+
+      switch (old_indices_type)
+        {
+        case COGL_INDICES_TYPE_UNSIGNED_BYTE:
+          for (i = 0; i < old_vertices->len; i++)
+            _cogl_path_tesselator_add_index (tess,
+                                             g_array_index (old_vertices,
+                                                            guint8, i));
+          break;
+
+        case COGL_INDICES_TYPE_UNSIGNED_SHORT:
+          for (i = 0; i < old_vertices->len; i++)
+            _cogl_path_tesselator_add_index (tess,
+                                             g_array_index (old_vertices,
+                                                            guint16, i));
+          break;
+
+        case COGL_INDICES_TYPE_UNSIGNED_INT:
+          for (i = 0; i < old_vertices->len; i++)
+            _cogl_path_tesselator_add_index (tess,
+                                             g_array_index (old_vertices,
+                                                            guint32, i));
+          break;
+        }
+
+      g_array_free (old_vertices, TRUE);
+    }
+}
+
+static void
+_cogl_path_build_fill_attribute_buffer (CoglPath *path)
+{
+  CoglPathTesselator tess;
+  unsigned int path_start = 0;
+  CoglPathData *data = path->data;
+  int i;
+
+  _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+
+  /* If we've already got a vbo then we don't need to do anything */
+  if (data->fill_attribute_buffer)
+    return;
+
+  tess.primitive_type = FALSE;
+
+  /* Generate a vertex for each point on the path */
+  tess.vertices = g_array_new (FALSE, FALSE, sizeof (CoglPathTesselatorVertex));
+  g_array_set_size (tess.vertices, data->path_nodes->len);
+  for (i = 0; i < data->path_nodes->len; i++)
+    {
+      CoglPathNode *node =
+        &g_array_index (data->path_nodes, CoglPathNode, i);
+      CoglPathTesselatorVertex *vertex =
+        &g_array_index (tess.vertices, CoglPathTesselatorVertex, i);
+
+      vertex->x = node->x;
+      vertex->y = node->y;
+
+      /* Add texture coordinates so that a texture would be drawn to
+         fit the bounding box of the path and then cropped by the
+         path */
+      if (data->path_nodes_min.x == data->path_nodes_max.x)
+        vertex->s = 0.0f;
+      else
+        vertex->s = ((node->x - data->path_nodes_min.x)
+                     / (data->path_nodes_max.x - data->path_nodes_min.x));
+      if (data->path_nodes_min.y == data->path_nodes_max.y)
+        vertex->t = 0.0f;
+      else
+        vertex->t = ((node->y - data->path_nodes_min.y)
+                     / (data->path_nodes_max.y - data->path_nodes_min.y));
+    }
+
+  tess.indices_type =
+    _cogl_path_tesselator_get_indices_type_for_size (data->path_nodes->len);
+  _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);
+
+  gluTessCallback (tess.glu_tess, GLU_TESS_BEGIN_DATA,
+                   _cogl_path_tesselator_begin);
+  gluTessCallback (tess.glu_tess, GLU_TESS_VERTEX_DATA,
+                   _cogl_path_tesselator_vertex);
+  gluTessCallback (tess.glu_tess, GLU_TESS_END_DATA,
+                   _cogl_path_tesselator_end);
+  gluTessCallback (tess.glu_tess, GLU_TESS_COMBINE_DATA,
+                   _cogl_path_tesselator_combine);
+
+  gluTessBeginPolygon (tess.glu_tess, &tess);
+
+  while (path_start < data->path_nodes->len)
+    {
+      CoglPathNode *node =
+        &g_array_index (data->path_nodes, CoglPathNode, path_start);
+
+      gluTessBeginContour (tess.glu_tess);
+
+      for (i = 0; i < node->path_size; i++)
+        {
+          double vertex[3] = { node[i].x, node[i].y, 0.0 };
+          gluTessVertex (tess.glu_tess, vertex,
+                         GINT_TO_POINTER (i + path_start));
+        }
+
+      gluTessEndContour (tess.glu_tess);
+
+      path_start += node->path_size;
+    }
+
+  gluTessEndPolygon (tess.glu_tess);
+
+  gluDeleteTess (tess.glu_tess);
+
+  data->fill_attribute_buffer =
+    cogl_attribute_buffer_new (ctx,
+                               sizeof (CoglPathTesselatorVertex) *
+                               tess.vertices->len,
+                               tess.vertices->data);
+  g_array_free (tess.vertices, TRUE);
+
+  data->fill_attributes[0] =
+    cogl_attribute_new (data->fill_attribute_buffer,
+                        "cogl_position_in",
+                        sizeof (CoglPathTesselatorVertex),
+                        G_STRUCT_OFFSET (CoglPathTesselatorVertex, x),
+                        2, /* n_components */
+                        COGL_ATTRIBUTE_TYPE_FLOAT);
+  data->fill_attributes[1] =
+    cogl_attribute_new (data->fill_attribute_buffer,
+                        "cogl_tex_coord0_in",
+                        sizeof (CoglPathTesselatorVertex),
+                        G_STRUCT_OFFSET (CoglPathTesselatorVertex, s),
+                        2, /* n_components */
+                        COGL_ATTRIBUTE_TYPE_FLOAT);
+
+  data->fill_vbo_indices = cogl_indices_new (ctx,
+                                             tess.indices_type,
+                                             tess.indices->data,
+                                             tess.indices->len);
+  data->fill_vbo_n_indices = tess.indices->len;
+  g_array_free (tess.indices, TRUE);
+}
+
+static void
+_cogl_path_build_stroke_attribute_buffer (CoglPath *path)
+{
+  CoglPathData *data = path->data;
+  CoglBuffer *buffer;
+  unsigned int n_attributes = 0;
+  unsigned int path_start;
+  CoglPathNode *node;
+  floatVec2 *buffer_p;
+  unsigned int i;
+
+  _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+
+  /* If we've already got a cached vbo then we don't need to do anything */
+  if (data->stroke_attribute_buffer)
+    return;
+
+  data->stroke_attribute_buffer =
+    cogl_attribute_buffer_new (ctx, data->path_nodes->len * sizeof (floatVec2),
+                               NULL);
+
+  buffer = COGL_BUFFER (data->stroke_attribute_buffer);
+  buffer_p = _cogl_buffer_map_for_fill_or_fallback (buffer);
+
+  /* Copy the vertices in and count the number of sub paths. Each sub
+     path will form a separate attribute so we can paint the disjoint
+     line strips */
+  for (path_start = 0;
+       path_start < data->path_nodes->len;
+       path_start += node->path_size)
+    {
+      node = &g_array_index (data->path_nodes, CoglPathNode, path_start);
+
+      for (i = 0; i < node->path_size; i++)
+        {
+          buffer_p[path_start + i].x = node[i].x;
+          buffer_p[path_start + i].y = node[i].y;
+        }
+
+      n_attributes++;
+    }
+
+  _cogl_buffer_unmap_for_fill_or_fallback (buffer);
+
+  data->stroke_attributes = g_new (CoglAttribute *, n_attributes);
+
+  /* Now we can loop the sub paths again to create the attributes */
+  for (i = 0, path_start = 0;
+       path_start < data->path_nodes->len;
+       i++, path_start += node->path_size)
+    {
+      node = &g_array_index (data->path_nodes, CoglPathNode, path_start);
+
+      data->stroke_attributes[i] =
+        cogl_attribute_new (data->stroke_attribute_buffer,
+                            "cogl_position_in",
+                            sizeof (floatVec2),
+                            path_start * sizeof (floatVec2),
+                            2, /* n_components */
+                            COGL_ATTRIBUTE_TYPE_FLOAT);
+    }
+
+  data->stroke_n_attributes = n_attributes;
+}
diff --git a/cogl/cogl-path.h b/cogl/cogl-path.h
index c3d0d45..5ab976f 100644
--- a/cogl/cogl-path.h
+++ b/cogl/cogl-path.h
@@ -56,6 +56,332 @@ typedef struct _CoglPath CoglPath;
 #define COGL_PATH(obj) ((CoglPath *)(obj))
 
 /**
+ * cogl_path_new:
+ *
+ * Creates a new, empty path object. The default fill rule is
+ * %COGL_PATH_FILL_RULE_EVEN_ODD.
+ *
+ * Return value: A pointer to a newly allocated #CoglPath, which can
+ * be freed using cogl_object_unref().
+ *
+ * Since: 2.0
+ */
+CoglPath *
+cogl_path_new (void);
+
+/**
+ * cogl_path_copy:
+ * @path: A #CoglPath object
+ *
+ * Returns a new copy of the path in @path. The new path has a
+ * reference count of 1 so you should unref it with
+ * cogl_object_unref() if you no longer need it.
+ *
+ * Internally the path will share the data until one of the paths is
+ * modified so copying paths should be relatively cheap.
+ *
+ * Return value: a copy of the path in @path.
+ *
+ * Since: 2.0
+ */
+CoglPath *
+cogl_path_copy (CoglPath *path);
+
+/**
+ * cogl_is_path:
+ * @object: A #CoglObject
+ *
+ * Gets whether the given object references an existing path object.
+ *
+ * Return value: %TRUE if the object references a #CoglPath,
+ *   %FALSE otherwise.
+ *
+ * Since: 2.0
+ */
+gboolean
+cogl_is_path (void *object);
+
+/**
+ * cogl_path_move_to:
+ * @x: X coordinate of the pen location to move to.
+ * @y: Y coordinate of the pen location to move to.
+ *
+ * Moves the pen to the given location. If there is an existing path
+ * this will start a new disjoint subpath.
+ *
+ * Since: 2.0
+ */
+void
+cogl_path_move_to (CoglPath *path,
+                   float x,
+                   float y);
+
+/**
+ * cogl_path_rel_move_to:
+ * @x: X offset from the current pen location to move the pen to.
+ * @y: Y offset from the current pen location to move the pen to.
+ *
+ * Moves the pen to the given offset relative to the current pen
+ * location. If there is an existing path this will start a new
+ * disjoint subpath.
+ *
+ * Since: 2.0
+ */
+void
+cogl_path_rel_move_to (CoglPath *path,
+                       float x,
+                       float y);
+
+/**
+ * cogl_path_line_to:
+ * @x: X coordinate of the end line vertex
+ * @y: Y coordinate of the end line vertex
+ *
+ * Adds a straight line segment to the current path that ends at the
+ * given coordinates.
+ *
+ * Since: 2.0
+ */
+void
+cogl_path_line_to (CoglPath *path,
+                   float x,
+                   float y);
+
+/**
+ * cogl_path_rel_line_to:
+ * @x: X offset from the current pen location of the end line vertex
+ * @y: Y offset from the current pen location of the end line vertex
+ *
+ * Adds a straight line segment to the current path that ends at the
+ * given coordinates relative to the current pen location.
+ *
+ * Since: 2.0
+ */
+void
+cogl_path_rel_line_to (CoglPath *path,
+                       float x,
+                       float y);
+
+/**
+ * cogl_path_arc:
+ * @center_x: X coordinate of the elliptical arc center
+ * @center_y: Y coordinate of the elliptical arc center
+ * @radius_x: X radius of the elliptical arc
+ * @radius_y: Y radius of the elliptical arc
+ * @angle_1: Angle in degrees at which the arc begin
+ * @angle_2: Angle in degrees at which the arc ends
+ *
+ * Adds an elliptical arc segment to the current path. A straight line
+ * segment will link the current pen location with the first vertex
+ * of the arc. If you perform a move_to to the arcs start just before
+ * drawing it you create a free standing arc.
+ *
+ * The angles are measured in degrees where 0° is in the direction of
+ * the positive X axis and 90° is in the direction of the positive Y
+ * axis. The angle of the arc begins at @angle_1 and heads towards
+ * @angle_2 (so if @angle_2 is less than @angle_1 it will decrease,
+ * otherwise it will increase).
+ *
+ * Since: 2.0
+ */
+void
+cogl_path_arc (CoglPath *path,
+               float center_x,
+               float center_y,
+               float radius_x,
+               float radius_y,
+               float angle_1,
+               float angle_2);
+
+/**
+ * cogl_path_curve_to:
+ * @x_1: X coordinate of the second bezier control point
+ * @y_1: Y coordinate of the second bezier control point
+ * @x_2: X coordinate of the third bezier control point
+ * @y_2: Y coordinate of the third bezier control point
+ * @x_3: X coordinate of the fourth bezier control point
+ * @y_3: Y coordinate of the fourth bezier control point
+ *
+ * Adds a cubic bezier curve segment to the current path with the given
+ * second, third and fourth control points and using current pen location
+ * as the first control point.
+ *
+ * Since: 2.0
+ */
+void
+cogl_path_curve_to (CoglPath *path,
+                    float x_1,
+                    float y_1,
+                    float x_2,
+                    float y_2,
+                    float x_3,
+                    float y_3);
+
+/**
+ * cogl_path_rel_curve_to:
+ * @x_1: X coordinate of the second bezier control point
+ * @y_1: Y coordinate of the second bezier control point
+ * @x_2: X coordinate of the third bezier control point
+ * @y_2: Y coordinate of the third bezier control point
+ * @x_3: X coordinate of the fourth bezier control point
+ * @y_3: Y coordinate of the fourth bezier control point
+ *
+ * Adds a cubic bezier curve segment to the current path with the given
+ * second, third and fourth control points and using current pen location
+ * as the first control point. The given coordinates are relative to the
+ * current pen location.
+ *
+ * Since: 2.0
+ */
+void
+cogl_path_rel_curve_to (CoglPath *path,
+                        float x_1,
+                        float y_1,
+                        float x_2,
+                        float y_2,
+                        float x_3,
+                        float y_3);
+
+/**
+ * cogl_path_close:
+ *
+ * Closes the path being constructed by adding a straight line segment
+ * to it that ends at the first vertex of the path.
+ *
+ * Since: 2.0
+ */
+void
+cogl_path_close (CoglPath *path);
+
+/**
+ * cogl_path_line:
+ * @x_1: X coordinate of the start line vertex
+ * @y_1: Y coordinate of the start line vertex
+ * @x_2: X coordinate of the end line vertex
+ * @y_2: Y coordinate of the end line vertex
+ *
+ * Constructs a straight line shape starting and ending at the given
+ * coordinates. If there is an existing path this will start a new
+ * disjoint sub-path.
+ *
+ * Since: 2.0
+ */
+void
+cogl_path_line (CoglPath *path,
+                float x_1,
+                float y_1,
+                float x_2,
+                float y_2);
+
+/**
+ * cogl_path_polyline:
+ * @coords: (in) (array) (transfer none): A pointer to the first element of an
+ * array of fixed-point values that specify the vertex coordinates.
+ * @num_points: The total number of vertices.
+ *
+ * Constructs a series of straight line segments, starting from the
+ * first given vertex coordinate. If there is an existing path this
+ * will start a new disjoint sub-path. Each subsequent segment starts
+ * where the previous one ended and ends at the next given vertex
+ * coordinate.
+ *
+ * The coords array must contain 2 * num_points values. The first value
+ * represents the X coordinate of the first vertex, the second value
+ * represents the Y coordinate of the first vertex, continuing in the same
+ * fashion for the rest of the vertices. (num_points - 1) segments will
+ * be constructed.
+ *
+ * Since: 2.0
+ */
+void
+cogl_path_polyline (CoglPath *path,
+                    const float *coords,
+                    int num_points);
+
+/**
+ * cogl_path_polygon:
+ * @coords: (in) (array) (transfer none): A pointer to the first element of
+ * an array of fixed-point values that specify the vertex coordinates.
+ * @num_points: The total number of vertices.
+ *
+ * Constructs a polygonal shape of the given number of vertices. If
+ * there is an existing path this will start a new disjoint sub-path.
+ *
+ * The coords array must contain 2 * num_points values. The first value
+ * represents the X coordinate of the first vertex, the second value
+ * represents the Y coordinate of the first vertex, continuing in the same
+ * fashion for the rest of the vertices.
+ *
+ * Since: 2.0
+ */
+void
+cogl_path_polygon (CoglPath *path,
+                   const float *coords,
+                   int num_points);
+
+/**
+ * cogl_path_rectangle:
+ * @x_1: X coordinate of the top-left corner.
+ * @y_1: Y coordinate of the top-left corner.
+ * @x_2: X coordinate of the bottom-right corner.
+ * @y_2: Y coordinate of the bottom-right corner.
+ *
+ * Constructs a rectangular shape at the given coordinates. If there
+ * is an existing path this will start a new disjoint sub-path.
+ *
+ * Since: 2.0
+ */
+void
+cogl_path_rectangle (CoglPath *path,
+                     float x_1,
+                     float y_1,
+                     float x_2,
+                     float y_2);
+
+/**
+ * cogl_path_ellipse:
+ * @center_x: X coordinate of the ellipse center
+ * @center_y: Y coordinate of the ellipse center
+ * @radius_x: X radius of the ellipse
+ * @radius_y: Y radius of the ellipse
+ *
+ * Constructs an ellipse shape. If there is an existing path this will
+ * start a new disjoint sub-path.
+ *
+ * Since: 2.0
+ */
+void
+cogl_path_ellipse (CoglPath *path,
+                   float center_x,
+                   float center_y,
+                   float radius_x,
+                   float radius_y);
+
+/**
+ * cogl_path_round_rectangle:
+ * @x_1: X coordinate of the top-left corner.
+ * @y_1: Y coordinate of the top-left corner.
+ * @x_2: X coordinate of the bottom-right corner.
+ * @y_2: Y coordinate of the bottom-right corner.
+ * @radius: Radius of the corner arcs.
+ * @arc_step: Angle increment resolution for subdivision of
+ * the corner arcs.
+ *
+ * Constructs a rectangular shape with rounded corners. If there is an
+ * existing path this will start a new disjoint sub-path.
+ *
+ * Since: 2.0
+ */
+void
+cogl_path_round_rectangle (CoglPath *path,
+                           float x_1,
+                           float y_1,
+                           float x_2,
+                           float y_2,
+                           float radius,
+                           float arc_step);
+
+/**
  * 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
@@ -97,9 +423,65 @@ typedef enum {
   COGL_PATH_FILL_RULE_EVEN_ODD
 } CoglPathFillRule;
 
-G_END_DECLS
+/**
+ * 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: 2.0
+ */
+void
+cogl_path_set_fill_rule (CoglPath *path, CoglPathFillRule fill_rule);
 
-#include "cogl-path-functions.h"
+/**
+ * cogl_path_get_fill_rule:
+ *
+ * Retrieves the fill rule set using cogl_path_set_fill_rule().
+ *
+ * Return value: the fill rule that is used for the current path.
+ *
+ * Since: 2.0
+ */
+CoglPathFillRule
+cogl_path_get_fill_rule (CoglPath *path);
+
+/**
+ * cogl_path_fill:
+ *
+ * Fills the interior of the constructed shape using the current
+ * drawing color.
+ *
+ * The interior of the shape is determined using the fill rule of the
+ * path. See %CoglPathFillRule for details.
+ *
+ * <note>The result of referencing sliced textures in your current
+ * pipeline when filling a path are undefined. You should pass
+ * the %COGL_TEXTURE_NO_SLICING flag when loading any texture you will
+ * use while filling a path.</note>
+ *
+ * Since: 2.0
+ */
+void
+cogl_path_fill (CoglPath *path);
+
+/**
+ * cogl_path_stroke:
+ *
+ * Strokes the constructed shape using the current drawing color and a
+ * width of 1 pixel (regardless of the current transformation
+ * matrix).
+ *
+ * Since: 2.0
+ */
+void
+cogl_path_stroke (CoglPath *path);
+
+G_END_DECLS
 
 #endif /* __COGL_PATH_H__ */
 
diff --git a/cogl/cogl.h b/cogl/cogl.h
index baacd8a..6f2a5d1 100644
--- a/cogl/cogl.h
+++ b/cogl/cogl.h
@@ -60,12 +60,12 @@
 #include <cogl/cogl-primitives.h>
 #include <cogl/cogl-texture.h>
 #include <cogl/cogl-types.h>
+#include <cogl/cogl-path.h>
 
 /*
  * 1.x only api...
  */
 #ifndef COGL_ENABLE_EXPERIMENTAL_2_0_API
-#include <cogl/cogl-path.h>
 #include <cogl/cogl-clip-state.h>
 #include <cogl/cogl-enum-types.h>
 #include <cogl/cogl-shader.h>
@@ -123,13 +123,6 @@
 #endif
 
 /*
- * 2.0 only api...
- */
-#ifdef COGL_ENABLE_EXPERIMENTAL_2_0_API
-#include <cogl/cogl2-path.h>
-#endif
-
-/*
  * API deprecations
  */
 #include <cogl/cogl-deprecated.h>
diff --git a/cogl/cogl.symbols b/cogl/cogl.symbols
index d0627b7..47ee24c 100644
--- a/cogl/cogl.symbols
+++ b/cogl/cogl.symbols
@@ -4,28 +4,25 @@
 /* (this may be subject to change!) */
 #endif
 
-/* cogl2_clip_push_from_path is only for 1.10.x*/
-cogl2_clip_push_from_path
-
-cogl2_path_arc
-cogl2_path_close
-cogl2_path_curve_to
-cogl2_path_ellipse
-cogl2_path_fill
-cogl2_path_get_fill_rule
-cogl2_path_line
-cogl2_path_line_to
-cogl2_path_move_to
-cogl2_path_new
-cogl2_path_polygon
-cogl2_path_polyline
-cogl2_path_rectangle
-cogl2_path_rel_curve_to
-cogl2_path_rel_line_to
-cogl2_path_rel_move_to
-cogl2_path_round_rectangle
-cogl2_path_set_fill_rule
-cogl2_path_stroke
+cogl_path_arc
+cogl_path_close
+cogl_path_curve_to
+cogl_path_ellipse
+cogl_path_fill
+cogl_path_get_fill_rule
+cogl_path_line
+cogl_path_line_to
+cogl_path_move_to
+cogl_path_new
+cogl_path_polygon
+cogl_path_polyline
+cogl_path_rectangle
+cogl_path_rel_curve_to
+cogl_path_rel_line_to
+cogl_path_rel_move_to
+cogl_path_round_rectangle
+cogl_path_set_fill_rule
+cogl_path_stroke
 
 #ifdef COGL_HAS_EGL_PLATFORM_ANDROID_SUPPORT
 cogl_android_set_native_window_EXP
@@ -93,8 +90,6 @@ cogl_clip_pop
 cogl_clip_push
 #endif
 
-cogl_clip_push_from_path
-cogl_clip_push_from_path_preserve
 cogl_clip_push_rectangle
 
 cogl_clip_push_window_rect
@@ -404,30 +399,6 @@ cogl_onscreen_template_set_swap_throttled
 
 cogl_ortho
 
-cogl_path_arc
-cogl_path_close
-cogl_path_copy
-cogl_path_curve_to
-cogl_path_ellipse
-cogl_path_fill
-cogl_path_fill_preserve		/* this is COGL 1.0 API */
-cogl_path_fill_rule_get_type
-cogl_path_get_fill_rule
-cogl_path_line
-cogl_path_line_to
-cogl_path_move_to
-cogl_path_new
-cogl_path_polygon
-cogl_path_polyline
-cogl_path_rectangle
-cogl_path_rel_curve_to
-cogl_path_rel_line_to
-cogl_path_rel_move_to
-cogl_path_round_rectangle
-cogl_path_set_fill_rule
-cogl_path_stroke
-cogl_path_stroke_preserve	/* this is COGL 1.0 API */
-
 cogl_perspective
 
 cogl_pipeline_add_layer_snippet
diff --git a/cogl/cogl1-context.h b/cogl/cogl1-context.h
index c59bd69..519b8b0 100644
--- a/cogl/cogl1-context.h
+++ b/cogl/cogl1-context.h
@@ -750,19 +750,6 @@ cogl_clip_push_rectangle (float x0,
                           float x1,
                           float y1);
 
-/**
- * cogl_clip_push_from_path_preserve:
- *
- * Sets a new clipping area using the current path. The current path
- * is then cleared. The clipping area is intersected with the previous
- * clipping area. To restore the previous clipping area, call
- * cogl_clip_pop().
- *
- * Since: 1.0
- */
-void
-cogl_clip_push_from_path_preserve (void);
-
 #ifdef COGL_ENABLE_EXPERIMENTAL_2_0_API
 /**
  * cogl_clip_push_primitive:
diff --git a/cogl/cogl2-path.c b/cogl/cogl2-path.c
deleted file mode 100644
index d9426ae..0000000
--- a/cogl/cogl2-path.c
+++ /dev/null
@@ -1,1449 +0,0 @@
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2007,2008,2009,2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- * Authors:
- *  Ivan Leben    <ivan at openedhand.com>
- *  Øyvind Kolås  <pippin at linux.intel.com>
- *  Neil Roberts  <neil at linux.intel.com>
- *  Robert Bragg  <robert at linux.intel.com>
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "cogl-util.h"
-#include "cogl-object.h"
-#include "cogl-internal.h"
-#include "cogl-context-private.h"
-#include "cogl-journal-private.h"
-#include "cogl-pipeline-private.h"
-#include "cogl-pipeline-opengl-private.h"
-#include "cogl-framebuffer-private.h"
-#include "cogl-path-private.h"
-#include "cogl-texture-private.h"
-#include "cogl-primitives-private.h"
-#include "cogl-private.h"
-#include "cogl-attribute-private.h"
-#include "cogl1-context.h"
-#include "tesselator/tesselator.h"
-
-#include <string.h>
-#include <math.h>
-
-#define _COGL_MAX_BEZ_RECURSE_DEPTH 16
-
-static void _cogl_path_free (CoglPath *path);
-
-static void _cogl_path_build_fill_attribute_buffer (CoglPath *path);
-static void _cogl_path_build_stroke_attribute_buffer (CoglPath *path);
-
-COGL_OBJECT_DEFINE (Path, path);
-
-static void
-_cogl_path_data_clear_vbos (CoglPathData *data)
-{
-  int i;
-
-  if (data->fill_attribute_buffer)
-    {
-      cogl_object_unref (data->fill_attribute_buffer);
-      cogl_object_unref (data->fill_vbo_indices);
-
-      for (i = 0; i < COGL_PATH_N_ATTRIBUTES; i++)
-        cogl_object_unref (data->fill_attributes[i]);
-
-      data->fill_attribute_buffer = NULL;
-    }
-
-  if (data->stroke_attribute_buffer)
-    {
-      cogl_object_unref (data->stroke_attribute_buffer);
-
-      for (i = 0; i < data->stroke_n_attributes; i++)
-        cogl_object_unref (data->stroke_attributes[i]);
-
-      g_free (data->stroke_attributes);
-
-      data->stroke_attribute_buffer = NULL;
-    }
-}
-
-static void
-_cogl_path_data_unref (CoglPathData *data)
-{
-  if (--data->ref_count <= 0)
-    {
-      _cogl_path_data_clear_vbos (data);
-
-      g_array_free (data->path_nodes, TRUE);
-
-      g_slice_free (CoglPathData, data);
-    }
-}
-
-static void
-_cogl_path_modify (CoglPath *path)
-{
-  /* This needs to be called whenever the path is about to be modified
-     to implement copy-on-write semantics */
-
-  /* If there is more than one path using the data then we need to
-     copy the data instead */
-  if (path->data->ref_count != 1)
-    {
-      CoglPathData *old_data = path->data;
-
-      path->data = g_slice_dup (CoglPathData, old_data);
-      path->data->path_nodes = g_array_new (FALSE, FALSE,
-                                            sizeof (CoglPathNode));
-      g_array_append_vals (path->data->path_nodes,
-                           old_data->path_nodes->data,
-                           old_data->path_nodes->len);
-
-      path->data->fill_attribute_buffer = NULL;
-      path->data->stroke_attribute_buffer = NULL;
-      path->data->ref_count = 1;
-
-      _cogl_path_data_unref (old_data);
-    }
-  else
-    /* The path is altered so the vbos will now be invalid */
-    _cogl_path_data_clear_vbos (path->data);
-}
-
-void
-cogl2_path_set_fill_rule (CoglPath *path,
-                          CoglPathFillRule fill_rule)
-{
-  _COGL_RETURN_IF_FAIL (cogl_is_path (path));
-
-  if (path->data->fill_rule != fill_rule)
-    {
-      _cogl_path_modify (path);
-
-      path->data->fill_rule = fill_rule;
-    }
-}
-
-CoglPathFillRule
-cogl2_path_get_fill_rule (CoglPath *path)
-{
-  _COGL_RETURN_VAL_IF_FAIL (cogl_is_path (path), COGL_PATH_FILL_RULE_NON_ZERO);
-
-  return path->data->fill_rule;
-}
-
-static void
-_cogl_path_add_node (CoglPath *path,
-                     gboolean new_sub_path,
-		     float x,
-		     float y)
-{
-  CoglPathNode new_node;
-  CoglPathData *data;
-
-  _cogl_path_modify (path);
-
-  data = path->data;
-
-  new_node.x = x;
-  new_node.y = y;
-  new_node.path_size = 0;
-
-  if (new_sub_path || data->path_nodes->len == 0)
-    data->last_path = data->path_nodes->len;
-
-  g_array_append_val (data->path_nodes, new_node);
-
-  g_array_index (data->path_nodes, CoglPathNode, data->last_path).path_size++;
-
-  if (data->path_nodes->len == 1)
-    {
-      data->path_nodes_min.x = data->path_nodes_max.x = x;
-      data->path_nodes_min.y = data->path_nodes_max.y = y;
-    }
-  else
-    {
-      if (x < data->path_nodes_min.x)
-        data->path_nodes_min.x = x;
-      if (x > data->path_nodes_max.x)
-        data->path_nodes_max.x = x;
-      if (y < data->path_nodes_min.y)
-        data->path_nodes_min.y = y;
-      if (y > data->path_nodes_max.y)
-        data->path_nodes_max.y = y;
-    }
-
-  /* Once the path nodes have been modified then we'll assume it's no
-     longer a rectangle. cogl2_path_rectangle will set this back to
-     TRUE if this has been called from there */
-  data->is_rectangle = FALSE;
-}
-
-static void
-_cogl_path_stroke_nodes (CoglPath *path)
-{
-  CoglPathData *data = path->data;
-  CoglPipeline *copy = NULL;
-  CoglPipeline *source;
-  unsigned int path_start;
-  int path_num = 0;
-  CoglPathNode *node;
-
-  _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
-  source = cogl_get_source ();
-
-  if (cogl_pipeline_get_n_layers (source) != 0)
-    {
-      copy = cogl_pipeline_copy (source);
-      _cogl_pipeline_prune_to_n_layers (copy, 0);
-      source = copy;
-    }
-
-  _cogl_path_build_stroke_attribute_buffer (path);
-
-  cogl_push_source (source);
-
-  for (path_start = 0;
-       path_start < data->path_nodes->len;
-       path_start += node->path_size)
-    {
-      node = &g_array_index (data->path_nodes, CoglPathNode, path_start);
-
-      cogl_framebuffer_vdraw_attributes (cogl_get_draw_framebuffer (),
-                                         source,
-                                         COGL_VERTICES_MODE_LINE_STRIP,
-                                         0, node->path_size,
-                                         data->stroke_attributes[path_num],
-                                         NULL);
-
-      path_num++;
-    }
-
-  cogl_pop_source ();
-
-  if (copy)
-    cogl_object_unref (copy);
-}
-
-void
-_cogl_path_get_bounds (CoglPath *path,
-                       float *min_x,
-                       float *min_y,
-                       float *max_x,
-                       float *max_y)
-{
-  CoglPathData *data = path->data;
-
-  if (data->path_nodes->len == 0)
-    {
-      *min_x = 0.0f;
-      *min_y = 0.0f;
-      *max_x = 0.0f;
-      *max_y = 0.0f;
-    }
-  else
-    {
-      *min_x = data->path_nodes_min.x;
-      *min_y = data->path_nodes_min.y;
-      *max_x = data->path_nodes_max.x;
-      *max_y = data->path_nodes_max.y;
-    }
-}
-
-static void
-_cogl_path_fill_nodes_with_clipped_rectangle (CoglPath *path)
-{
-  CoglFramebuffer *fb;
-
-  _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
-  if (!(ctx->private_feature_flags & COGL_PRIVATE_FEATURE_STENCIL_BUFFER))
-    {
-      static gboolean seen_warning = FALSE;
-
-      if (!seen_warning)
-        {
-          g_warning ("Paths can not be filled using materials with "
-                     "sliced textures unless there is a stencil "
-                     "buffer");
-          seen_warning = TRUE;
-        }
-    }
-
-  fb = cogl_get_draw_framebuffer ();
-  cogl_framebuffer_push_path_clip (fb, path);
-  cogl_rectangle (path->data->path_nodes_min.x,
-                  path->data->path_nodes_min.y,
-                  path->data->path_nodes_max.x,
-                  path->data->path_nodes_max.y);
-  cogl_framebuffer_pop_clip (fb);
-}
-
-static gboolean
-validate_layer_cb (CoglPipelineLayer *layer, void *user_data)
-{
-  gboolean *needs_fallback = user_data;
-  CoglTexture *texture = _cogl_pipeline_layer_get_texture (layer);
-
-  /* If any of the layers of the current pipeline contain sliced
-   * textures or textures with waste then it won't work to draw the
-   * path directly. Instead we fallback to pushing the path as a clip
-   * on the clip-stack and drawing the path's bounding rectangle
-   * instead.
-   */
-
-  if (texture != NULL && (cogl_texture_is_sliced (texture) ||
-                          !_cogl_texture_can_hardware_repeat (texture)))
-    *needs_fallback = TRUE;
-
-  return !*needs_fallback;
-}
-
-void
-_cogl_path_fill_nodes (CoglPath *path, CoglDrawFlags flags)
-{
-  gboolean needs_fallback = FALSE;
-  CoglPipeline *pipeline = cogl_get_source ();
-
-  _cogl_pipeline_foreach_layer_internal (pipeline,
-                                         validate_layer_cb, &needs_fallback);
-  if (needs_fallback)
-    {
-      _cogl_path_fill_nodes_with_clipped_rectangle (path);
-      return;
-    }
-
-  _cogl_path_build_fill_attribute_buffer (path);
-
-  _cogl_framebuffer_draw_indexed_attributes (cogl_get_draw_framebuffer (),
-                                             pipeline,
-                                             COGL_VERTICES_MODE_TRIANGLES,
-                                             0, /* first_vertex */
-                                             path->data->fill_vbo_n_indices,
-                                             path->data->fill_vbo_indices,
-                                             path->data->fill_attributes,
-                                             COGL_PATH_N_ATTRIBUTES,
-                                             flags);
-}
-
-void
-cogl2_path_fill (CoglPath *path)
-{
-  _COGL_RETURN_IF_FAIL (cogl_is_path (path));
-
-  if (path->data->path_nodes->len == 0)
-    return;
-
-  /* If the path is a simple rectangle then we can divert to using
-     cogl_rectangle which should be faster because it can go through
-     the journal instead of uploading the geometry just for two
-     triangles */
-  if (path->data->is_rectangle)
-    {
-      float x_1, y_1, x_2, y_2;
-
-      _cogl_path_get_bounds (path, &x_1, &y_1, &x_2, &y_2);
-      cogl_rectangle (x_1, y_1, x_2, y_2);
-    }
-  else
-    _cogl_path_fill_nodes (path, 0);
-}
-
-void
-cogl2_path_stroke (CoglPath *path)
-{
-  _COGL_RETURN_IF_FAIL (cogl_is_path (path));
-
-  if (path->data->path_nodes->len == 0)
-    return;
-
-  _cogl_path_stroke_nodes (path);
-}
-
-void
-cogl2_path_move_to (CoglPath *path,
-                    float x,
-                    float y)
-{
-  CoglPathData *data;
-
-  _COGL_RETURN_IF_FAIL (cogl_is_path (path));
-
-  _cogl_path_add_node (path, TRUE, x, y);
-
-  data = path->data;
-
-  data->path_start.x = x;
-  data->path_start.y = y;
-
-  data->path_pen = data->path_start;
-}
-
-void
-cogl2_path_rel_move_to (CoglPath *path,
-                        float x,
-                        float y)
-{
-  CoglPathData *data;
-
-  _COGL_RETURN_IF_FAIL (cogl_is_path (path));
-
-  data = path->data;
-
-  cogl2_path_move_to (path,
-                      data->path_pen.x + x,
-                      data->path_pen.y + y);
-}
-
-void
-cogl2_path_line_to (CoglPath *path,
-                    float x,
-                    float y)
-{
-  CoglPathData *data;
-
-  _COGL_RETURN_IF_FAIL (cogl_is_path (path));
-
-  _cogl_path_add_node (path, FALSE, x, y);
-
-  data = path->data;
-
-  data->path_pen.x = x;
-  data->path_pen.y = y;
-}
-
-void
-cogl2_path_rel_line_to (CoglPath *path,
-                        float x,
-                        float y)
-{
-  CoglPathData *data;
-
-  _COGL_RETURN_IF_FAIL (cogl_is_path (path));
-
-  data = path->data;
-
-  cogl2_path_line_to (path,
-                      data->path_pen.x + x,
-                      data->path_pen.y + y);
-}
-
-void
-cogl2_path_close (CoglPath *path)
-{
-  _COGL_RETURN_IF_FAIL (cogl_is_path (path));
-
-  _cogl_path_add_node (path, FALSE, path->data->path_start.x,
-                       path->data->path_start.y);
-
-  path->data->path_pen = path->data->path_start;
-}
-
-void
-cogl2_path_line (CoglPath *path,
-                 float x_1,
-	         float y_1,
-	         float x_2,
-	         float y_2)
-{
-  cogl2_path_move_to (path, x_1, y_1);
-  cogl2_path_line_to (path, x_2, y_2);
-}
-
-void
-cogl2_path_polyline (CoglPath *path,
-                     const float *coords,
-                     int num_points)
-{
-  int c = 0;
-
-  _COGL_RETURN_IF_FAIL (cogl_is_path (path));
-
-  cogl2_path_move_to (path, coords[0], coords[1]);
-
-  for (c = 1; c < num_points; ++c)
-    cogl2_path_line_to (path, coords[2*c], coords[2*c+1]);
-}
-
-void
-cogl2_path_polygon (CoglPath *path,
-                    const float *coords,
-                    int num_points)
-{
-  cogl2_path_polyline (path, coords, num_points);
-  cogl2_path_close (path);
-}
-
-void
-cogl2_path_rectangle (CoglPath *path,
-                      float x_1,
-                      float y_1,
-                      float x_2,
-                      float y_2)
-{
-  gboolean is_rectangle;
-
-  /* If the path was previously empty and the rectangle isn't mirrored
-     then we'll record that this is a simple rectangle path so that we
-     can optimise it */
-  is_rectangle = (path->data->path_nodes->len == 0 &&
-                  x_2 >= x_1 &&
-                  y_2 >= y_1);
-
-  cogl2_path_move_to (path, x_1, y_1);
-  cogl2_path_line_to (path, x_2, y_1);
-  cogl2_path_line_to (path, x_2, y_2);
-  cogl2_path_line_to (path, x_1, y_2);
-  cogl2_path_close (path);
-
-  path->data->is_rectangle = is_rectangle;
-}
-
-gboolean
-_cogl_path_is_rectangle (CoglPath *path)
-{
-  return path->data->is_rectangle;
-}
-
-static void
-_cogl_path_arc (CoglPath *path,
-                float center_x,
-	        float center_y,
-                float radius_x,
-                float radius_y,
-                float angle_1,
-                float angle_2,
-                float angle_step,
-                unsigned int move_first)
-{
-  float a = 0x0;
-  float cosa = 0x0;
-  float sina = 0x0;
-  float px = 0x0;
-  float py = 0x0;
-
-  /* Fix invalid angles */
-
-  if (angle_1 == angle_2 || angle_step == 0x0)
-    return;
-
-  if (angle_step < 0x0)
-    angle_step = -angle_step;
-
-  /* Walk the arc by given step */
-
-  a = angle_1;
-  while (a != angle_2)
-    {
-      cosa = cosf (a * (G_PI/180.0));
-      sina = sinf (a * (G_PI/180.0));
-
-      px = center_x + (cosa * radius_x);
-      py = center_y + (sina * radius_y);
-
-      if (a == angle_1 && move_first)
-	cogl2_path_move_to (path, px, py);
-      else
-	cogl2_path_line_to (path, px, py);
-
-      if (G_LIKELY (angle_2 > angle_1))
-        {
-          a += angle_step;
-          if (a > angle_2)
-            a = angle_2;
-        }
-      else
-        {
-          a -= angle_step;
-          if (a < angle_2)
-            a = angle_2;
-        }
-    }
-
-  /* Make sure the final point is drawn */
-
-  cosa = cosf (angle_2 * (G_PI/180.0));
-  sina = sinf (angle_2 * (G_PI/180.0));
-
-  px = center_x + (cosa * radius_x);
-  py = center_y + (sina * radius_y);
-
-  cogl2_path_line_to (path, px, py);
-}
-
-void
-cogl2_path_arc (CoglPath *path,
-                float center_x,
-                float center_y,
-                float radius_x,
-                float radius_y,
-                float angle_1,
-                float angle_2)
-{
-  float angle_step = 10;
-
-  _COGL_RETURN_IF_FAIL (cogl_is_path (path));
-
-  /* it is documented that a move to is needed to create a freestanding
-   * arc
-   */
-  _cogl_path_arc (path,
-                  center_x, center_y,
-	          radius_x, radius_y,
-	          angle_1, angle_2,
-	          angle_step, 0 /* no move */);
-}
-
-
-static void
-_cogl_path_rel_arc (CoglPath *path,
-                    float center_x,
-                    float center_y,
-                    float radius_x,
-                    float radius_y,
-                    float angle_1,
-                    float angle_2,
-                    float angle_step)
-{
-  CoglPathData *data;
-
-  data = path->data;
-
-  _cogl_path_arc (path,
-                  data->path_pen.x + center_x,
-	          data->path_pen.y + center_y,
-	          radius_x, radius_y,
-	          angle_1, angle_2,
-	          angle_step, 0 /* no move */);
-}
-
-void
-cogl2_path_ellipse (CoglPath *path,
-                    float center_x,
-                    float center_y,
-                    float radius_x,
-                    float radius_y)
-{
-  float angle_step = 10;
-
-  _COGL_RETURN_IF_FAIL (cogl_is_path (path));
-
-  /* FIXME: if shows to be slow might be optimized
-   * by mirroring just a quarter of it */
-
-  _cogl_path_arc (path,
-                  center_x, center_y,
-	          radius_x, radius_y,
-	          0, 360,
-	          angle_step, 1 /* move first */);
-
-  cogl2_path_close (path);
-}
-
-void
-cogl2_path_round_rectangle (CoglPath *path,
-                            float x_1,
-                            float y_1,
-                            float x_2,
-                            float y_2,
-                            float radius,
-                            float arc_step)
-{
-  float inner_width = x_2 - x_1 - radius * 2;
-  float inner_height = y_2 - y_1 - radius * 2;
-
-  _COGL_RETURN_IF_FAIL (cogl_is_path (path));
-
-  cogl2_path_move_to (path, x_1, y_1 + radius);
-  _cogl_path_rel_arc (path,
-                      radius, 0,
-                      radius, radius,
-                      180,
-                      270,
-                      arc_step);
-
-  cogl2_path_line_to (path,
-                     path->data->path_pen.x + inner_width,
-                     path->data->path_pen.y);
-  _cogl_path_rel_arc (path,
-                      0, radius,
-                      radius, radius,
-                      -90,
-                      0,
-                      arc_step);
-
-  cogl2_path_line_to (path,
-                     path->data->path_pen.x,
-                     path->data->path_pen.y + inner_height);
-
-  _cogl_path_rel_arc (path,
-                      -radius, 0,
-                      radius, radius,
-                      0,
-                      90,
-                      arc_step);
-
-  cogl2_path_line_to (path,
-                     path->data->path_pen.x - inner_width,
-                     path->data->path_pen.y);
-  _cogl_path_rel_arc (path,
-                      0, -radius,
-                      radius, radius,
-                      90,
-                      180,
-                      arc_step);
-
-  cogl2_path_close (path);
-}
-
-static void
-_cogl_path_bezier3_sub (CoglPath *path,
-                        CoglBezCubic *cubic)
-{
-  CoglBezCubic cubics[_COGL_MAX_BEZ_RECURSE_DEPTH];
-  CoglBezCubic *cleft;
-  CoglBezCubic *cright;
-  CoglBezCubic *c;
-  floatVec2 dif1;
-  floatVec2 dif2;
-  floatVec2 mm;
-  floatVec2 c1;
-  floatVec2 c2;
-  floatVec2 c3;
-  floatVec2 c4;
-  floatVec2 c5;
-  int cindex;
-
-  /* Put first curve on stack */
-  cubics[0] = *cubic;
-  cindex =  0;
-
-  while (cindex >= 0)
-    {
-      c = &cubics[cindex];
-
-
-      /* Calculate distance of control points from their
-       * counterparts on the line between end points */
-      dif1.x = (c->p2.x * 3) - (c->p1.x * 2) - c->p4.x;
-      dif1.y = (c->p2.y * 3) - (c->p1.y * 2) - c->p4.y;
-      dif2.x = (c->p3.x * 3) - (c->p4.x * 2) - c->p1.x;
-      dif2.y = (c->p3.y * 3) - (c->p4.y * 2) - c->p1.y;
-
-      if (dif1.x < 0)
-        dif1.x = -dif1.x;
-      if (dif1.y < 0)
-        dif1.y = -dif1.y;
-      if (dif2.x < 0)
-        dif2.x = -dif2.x;
-      if (dif2.y < 0)
-        dif2.y = -dif2.y;
-
-
-      /* Pick the greatest of two distances */
-      if (dif1.x < dif2.x) dif1.x = dif2.x;
-      if (dif1.y < dif2.y) dif1.y = dif2.y;
-
-      /* Cancel if the curve is flat enough */
-      if (dif1.x + dif1.y <= 1.0 ||
-	  cindex == _COGL_MAX_BEZ_RECURSE_DEPTH-1)
-	{
-	  /* Add subdivision point (skip last) */
-	  if (cindex == 0)
-            return;
-
-	  _cogl_path_add_node (path, FALSE, c->p4.x, c->p4.y);
-
-	  --cindex;
-
-          continue;
-	}
-
-      /* Left recursion goes on top of stack! */
-      cright = c; cleft = &cubics[++cindex];
-
-      /* Subdivide into 2 sub-curves */
-      c1.x = ((c->p1.x + c->p2.x) / 2);
-      c1.y = ((c->p1.y + c->p2.y) / 2);
-      mm.x = ((c->p2.x + c->p3.x) / 2);
-      mm.y = ((c->p2.y + c->p3.y) / 2);
-      c5.x = ((c->p3.x + c->p4.x) / 2);
-      c5.y = ((c->p3.y + c->p4.y) / 2);
-
-      c2.x = ((c1.x + mm.x) / 2);
-      c2.y = ((c1.y + mm.y) / 2);
-      c4.x = ((mm.x + c5.x) / 2);
-      c4.y = ((mm.y + c5.y) / 2);
-
-      c3.x = ((c2.x + c4.x) / 2);
-      c3.y = ((c2.y + c4.y) / 2);
-
-      /* Add left recursion to stack */
-      cleft->p1 = c->p1;
-      cleft->p2 = c1;
-      cleft->p3 = c2;
-      cleft->p4 = c3;
-
-      /* Add right recursion to stack */
-      cright->p1 = c3;
-      cright->p2 = c4;
-      cright->p3 = c5;
-      cright->p4 = c->p4;
-    }
-}
-
-void
-cogl2_path_curve_to (CoglPath *path,
-                     float x_1,
-                     float y_1,
-                     float x_2,
-                     float y_2,
-                     float x_3,
-                     float y_3)
-{
-  CoglBezCubic cubic;
-
-  _COGL_RETURN_IF_FAIL (cogl_is_path (path));
-
-  /* Prepare cubic curve */
-  cubic.p1 = path->data->path_pen;
-  cubic.p2.x = x_1;
-  cubic.p2.y = y_1;
-  cubic.p3.x = x_2;
-  cubic.p3.y = y_2;
-  cubic.p4.x = x_3;
-  cubic.p4.y = y_3;
-
-  /* Run subdivision */
-  _cogl_path_bezier3_sub (path, &cubic);
-
-  /* Add last point */
-  _cogl_path_add_node (path, FALSE, cubic.p4.x, cubic.p4.y);
-  path->data->path_pen = cubic.p4;
-}
-
-void
-cogl2_path_rel_curve_to (CoglPath *path,
-                         float x_1,
-                         float y_1,
-                         float x_2,
-                         float y_2,
-                         float x_3,
-                         float y_3)
-{
-  CoglPathData *data;
-
-  _COGL_RETURN_IF_FAIL (cogl_is_path (path));
-
-  data = path->data;
-
-  cogl2_path_curve_to (path,
-                       data->path_pen.x + x_1,
-                       data->path_pen.y + y_1,
-                       data->path_pen.x + x_2,
-                       data->path_pen.y + y_2,
-                       data->path_pen.x + x_3,
-                       data->path_pen.y + y_3);
-}
-
-CoglPath *
-cogl2_path_new (void)
-{
-  CoglPath *path;
-  CoglPathData *data;
-
-  path = g_slice_new (CoglPath);
-  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->fill_attribute_buffer = NULL;
-  data->stroke_attribute_buffer = NULL;
-  data->is_rectangle = FALSE;
-
-  return _cogl_path_object_new (path);
-}
-
-CoglPath *
-cogl_path_copy (CoglPath *old_path)
-{
-  CoglPath *new_path;
-
-  _COGL_RETURN_VAL_IF_FAIL (cogl_is_path (old_path), NULL);
-
-  new_path = g_slice_new (CoglPath);
-  new_path->data = old_path->data;
-  new_path->data->ref_count++;
-
-  return _cogl_path_object_new (new_path);
-}
-
-static void
-_cogl_path_free (CoglPath *path)
-{
-  _cogl_path_data_unref (path->data);
-  g_slice_free (CoglPath, path);
-}
-
-/* If second order beziers were needed the following code could
- * be re-enabled:
- */
-#if 0
-
-static void
-_cogl_path_bezier2_sub (CoglPath *path,
-                        CoglBezQuad *quad)
-{
-  CoglBezQuad quads[_COGL_MAX_BEZ_RECURSE_DEPTH];
-  CoglBezQuad *qleft;
-  CoglBezQuad *qright;
-  CoglBezQuad *q;
-  floatVec2 mid;
-  floatVec2 dif;
-  floatVec2 c1;
-  floatVec2 c2;
-  floatVec2 c3;
-  int qindex;
-
-  /* Put first curve on stack */
-  quads[0] = *quad;
-  qindex =  0;
-
-  /* While stack is not empty */
-  while (qindex >= 0)
-    {
-
-      q = &quads[qindex];
-
-      /* Calculate distance of control point from its
-       * counterpart on the line between end points */
-      mid.x = ((q->p1.x + q->p3.x) / 2);
-      mid.y = ((q->p1.y + q->p3.y) / 2);
-      dif.x = (q->p2.x - mid.x);
-      dif.y = (q->p2.y - mid.y);
-      if (dif.x < 0) dif.x = -dif.x;
-      if (dif.y < 0) dif.y = -dif.y;
-
-      /* Cancel if the curve is flat enough */
-      if (dif.x + dif.y <= 1.0 ||
-          qindex == _COGL_MAX_BEZ_RECURSE_DEPTH - 1)
-	{
-	  /* Add subdivision point (skip last) */
-	  if (qindex == 0) return;
-	  _cogl_path_add_node (path, FALSE, q->p3.x, q->p3.y);
-	  --qindex; continue;
-	}
-
-      /* Left recursion goes on top of stack! */
-      qright = q; qleft = &quads[++qindex];
-
-      /* Subdivide into 2 sub-curves */
-      c1.x = ((q->p1.x + q->p2.x) / 2);
-      c1.y = ((q->p1.y + q->p2.y) / 2);
-      c3.x = ((q->p2.x + q->p3.x) / 2);
-      c3.y = ((q->p2.y + q->p3.y) / 2);
-      c2.x = ((c1.x + c3.x) / 2);
-      c2.y = ((c1.y + c3.y) / 2);
-
-      /* Add left recursion onto stack */
-      qleft->p1 = q->p1;
-      qleft->p2 = c1;
-      qleft->p3 = c2;
-
-      /* Add right recursion onto stack */
-      qright->p1 = c2;
-      qright->p2 = c3;
-      qright->p3 = q->p3;
-    }
-}
-
-void
-cogl_path_curve2_to (CoglPath *path,
-                     float x_1,
-                     float y_1,
-                     float x_2,
-                     float y_2)
-{
-  CoglBezQuad quad;
-
-  /* Prepare quadratic curve */
-  quad.p1 = path->data->path_pen;
-  quad.p2.x = x_1;
-  quad.p2.y = y_1;
-  quad.p3.x = x_2;
-  quad.p3.y = y_2;
-
-  /* Run subdivision */
-  _cogl_path_bezier2_sub (&quad);
-
-  /* Add last point */
-  _cogl_path_add_node (FALSE, quad.p3.x, quad.p3.y);
-  path->data->path_pen = quad.p3;
-}
-
-void
-cogl_rel_curve2_to (CoglPath *path,
-                    float x_1,
-                    float y_1,
-                    float x_2,
-                    float y_2)
-{
-  CoglPathData *data;
-
-  _COGL_RETURN_IF_FAIL (cogl_is_path (path));
-
-  data = path->data;
-
-  cogl_path_curve2_to (data->path_pen.x + x_1,
-                       data->path_pen.y + y_1,
-                       data->path_pen.x + x_2,
-                       data->path_pen.y + y_2);
-}
-
-#endif
-
-typedef struct _CoglPathTesselator CoglPathTesselator;
-typedef struct _CoglPathTesselatorVertex CoglPathTesselatorVertex;
-
-struct _CoglPathTesselator
-{
-  GLUtesselator *glu_tess;
-  GLenum primitive_type;
-  int vertex_number;
-  /* Array of CoglPathTesselatorVertex. This needs to grow when the
-     combine callback is called */
-  GArray *vertices;
-  /* Array of integers for the indices into the vertices array. Each
-     element will either be guint8, guint16 or guint32 depending on
-     the number of vertices */
-  GArray *indices;
-  CoglIndicesType indices_type;
-  /* Indices used to split fans and strips */
-  int index_a, index_b;
-};
-
-struct _CoglPathTesselatorVertex
-{
-  float x, y, s, t;
-};
-
-static void
-_cogl_path_tesselator_begin (GLenum type,
-                             CoglPathTesselator *tess)
-{
-  g_assert (type == GL_TRIANGLES ||
-            type == GL_TRIANGLE_FAN ||
-            type == GL_TRIANGLE_STRIP);
-
-  tess->primitive_type = type;
-  tess->vertex_number = 0;
-}
-
-static CoglIndicesType
-_cogl_path_tesselator_get_indices_type_for_size (int n_vertices)
-{
-  if (n_vertices <= 256)
-    return COGL_INDICES_TYPE_UNSIGNED_BYTE;
-  else if (n_vertices <= 65536)
-    return COGL_INDICES_TYPE_UNSIGNED_SHORT;
-  else
-    return COGL_INDICES_TYPE_UNSIGNED_INT;
-}
-
-static void
-_cogl_path_tesselator_allocate_indices_array (CoglPathTesselator *tess)
-{
-  switch (tess->indices_type)
-    {
-    case COGL_INDICES_TYPE_UNSIGNED_BYTE:
-      tess->indices = g_array_new (FALSE, FALSE, sizeof (guint8));
-      break;
-
-    case COGL_INDICES_TYPE_UNSIGNED_SHORT:
-      tess->indices = g_array_new (FALSE, FALSE, sizeof (guint16));
-      break;
-
-    case COGL_INDICES_TYPE_UNSIGNED_INT:
-      tess->indices = g_array_new (FALSE, FALSE, sizeof (guint32));
-      break;
-    }
-}
-
-static void
-_cogl_path_tesselator_add_index (CoglPathTesselator *tess, int vertex_index)
-{
-  switch (tess->indices_type)
-    {
-    case COGL_INDICES_TYPE_UNSIGNED_BYTE:
-      {
-        guint8 val = vertex_index;
-        g_array_append_val (tess->indices, val);
-      }
-      break;
-
-    case COGL_INDICES_TYPE_UNSIGNED_SHORT:
-      {
-        guint16 val = vertex_index;
-        g_array_append_val (tess->indices, val);
-      }
-      break;
-
-    case COGL_INDICES_TYPE_UNSIGNED_INT:
-      {
-        guint32 val = vertex_index;
-        g_array_append_val (tess->indices, val);
-      }
-      break;
-    }
-}
-
-static void
-_cogl_path_tesselator_vertex (void *vertex_data,
-                              CoglPathTesselator *tess)
-{
-  int vertex_index;
-
-  vertex_index = GPOINTER_TO_INT (vertex_data);
-
-  /* This tries to convert all of the primitives into GL_TRIANGLES
-     with indices to share vertices */
-  switch (tess->primitive_type)
-    {
-    case GL_TRIANGLES:
-      /* Directly use the vertex */
-      _cogl_path_tesselator_add_index (tess, vertex_index);
-      break;
-
-    case GL_TRIANGLE_FAN:
-      if (tess->vertex_number == 0)
-        tess->index_a = vertex_index;
-      else if (tess->vertex_number == 1)
-        tess->index_b = vertex_index;
-      else
-        {
-          /* Create a triangle with the first vertex, the previous
-             vertex and this vertex */
-          _cogl_path_tesselator_add_index (tess, tess->index_a);
-          _cogl_path_tesselator_add_index (tess, tess->index_b);
-          _cogl_path_tesselator_add_index (tess, vertex_index);
-          /* Next time we will use this vertex as the previous
-             vertex */
-          tess->index_b = vertex_index;
-        }
-      break;
-
-    case GL_TRIANGLE_STRIP:
-      if (tess->vertex_number == 0)
-        tess->index_a = vertex_index;
-      else if (tess->vertex_number == 1)
-        tess->index_b = vertex_index;
-      else
-        {
-          _cogl_path_tesselator_add_index (tess, tess->index_a);
-          _cogl_path_tesselator_add_index (tess, tess->index_b);
-          _cogl_path_tesselator_add_index (tess, vertex_index);
-          if (tess->vertex_number & 1)
-            tess->index_b = vertex_index;
-          else
-            tess->index_a = vertex_index;
-        }
-      break;
-
-    default:
-      g_assert_not_reached ();
-    }
-
-  tess->vertex_number++;
-}
-
-static void
-_cogl_path_tesselator_end (CoglPathTesselator *tess)
-{
-  tess->primitive_type = GL_FALSE;
-}
-
-static void
-_cogl_path_tesselator_combine (double coords[3],
-                               void *vertex_data[4],
-                               float weight[4],
-                               void **out_data,
-                               CoglPathTesselator *tess)
-{
-  CoglPathTesselatorVertex *vertex;
-  CoglIndicesType new_indices_type;
-  int i;
-
-  /* Add a new vertex to the array */
-  g_array_set_size (tess->vertices, tess->vertices->len + 1);
-  vertex = &g_array_index (tess->vertices,
-                           CoglPathTesselatorVertex,
-                           tess->vertices->len - 1);
-  /* The data is just the index to the vertex */
-  *out_data = GINT_TO_POINTER (tess->vertices->len - 1);
-  /* Set the coordinates of the new vertex */
-  vertex->x = coords[0];
-  vertex->y = coords[1];
-  /* Generate the texture coordinates as the weighted average of the
-     four incoming coordinates */
-  vertex->s = 0.0f;
-  vertex->t = 0.0f;
-  for (i = 0; i < 4; i++)
-    {
-      CoglPathTesselatorVertex *old_vertex =
-        &g_array_index (tess->vertices, CoglPathTesselatorVertex,
-                        GPOINTER_TO_INT (vertex_data[i]));
-      vertex->s += old_vertex->s * weight[i];
-      vertex->t += old_vertex->t * weight[i];
-    }
-
-  /* Check if we've reached the limit for the data type of our indices */
-  new_indices_type =
-    _cogl_path_tesselator_get_indices_type_for_size (tess->vertices->len);
-  if (new_indices_type != tess->indices_type)
-    {
-      CoglIndicesType old_indices_type = new_indices_type;
-      GArray *old_vertices = tess->indices;
-
-      /* Copy the indices to an array of the new type */
-      tess->indices_type = new_indices_type;
-      _cogl_path_tesselator_allocate_indices_array (tess);
-
-      switch (old_indices_type)
-        {
-        case COGL_INDICES_TYPE_UNSIGNED_BYTE:
-          for (i = 0; i < old_vertices->len; i++)
-            _cogl_path_tesselator_add_index (tess,
-                                             g_array_index (old_vertices,
-                                                            guint8, i));
-          break;
-
-        case COGL_INDICES_TYPE_UNSIGNED_SHORT:
-          for (i = 0; i < old_vertices->len; i++)
-            _cogl_path_tesselator_add_index (tess,
-                                             g_array_index (old_vertices,
-                                                            guint16, i));
-          break;
-
-        case COGL_INDICES_TYPE_UNSIGNED_INT:
-          for (i = 0; i < old_vertices->len; i++)
-            _cogl_path_tesselator_add_index (tess,
-                                             g_array_index (old_vertices,
-                                                            guint32, i));
-          break;
-        }
-
-      g_array_free (old_vertices, TRUE);
-    }
-}
-
-static void
-_cogl_path_build_fill_attribute_buffer (CoglPath *path)
-{
-  CoglPathTesselator tess;
-  unsigned int path_start = 0;
-  CoglPathData *data = path->data;
-  int i;
-
-  _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
-  /* If we've already got a vbo then we don't need to do anything */
-  if (data->fill_attribute_buffer)
-    return;
-
-  tess.primitive_type = FALSE;
-
-  /* Generate a vertex for each point on the path */
-  tess.vertices = g_array_new (FALSE, FALSE, sizeof (CoglPathTesselatorVertex));
-  g_array_set_size (tess.vertices, data->path_nodes->len);
-  for (i = 0; i < data->path_nodes->len; i++)
-    {
-      CoglPathNode *node =
-        &g_array_index (data->path_nodes, CoglPathNode, i);
-      CoglPathTesselatorVertex *vertex =
-        &g_array_index (tess.vertices, CoglPathTesselatorVertex, i);
-
-      vertex->x = node->x;
-      vertex->y = node->y;
-
-      /* Add texture coordinates so that a texture would be drawn to
-         fit the bounding box of the path and then cropped by the
-         path */
-      if (data->path_nodes_min.x == data->path_nodes_max.x)
-        vertex->s = 0.0f;
-      else
-        vertex->s = ((node->x - data->path_nodes_min.x)
-                     / (data->path_nodes_max.x - data->path_nodes_min.x));
-      if (data->path_nodes_min.y == data->path_nodes_max.y)
-        vertex->t = 0.0f;
-      else
-        vertex->t = ((node->y - data->path_nodes_min.y)
-                     / (data->path_nodes_max.y - data->path_nodes_min.y));
-    }
-
-  tess.indices_type =
-    _cogl_path_tesselator_get_indices_type_for_size (data->path_nodes->len);
-  _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);
-
-  gluTessCallback (tess.glu_tess, GLU_TESS_BEGIN_DATA,
-                   _cogl_path_tesselator_begin);
-  gluTessCallback (tess.glu_tess, GLU_TESS_VERTEX_DATA,
-                   _cogl_path_tesselator_vertex);
-  gluTessCallback (tess.glu_tess, GLU_TESS_END_DATA,
-                   _cogl_path_tesselator_end);
-  gluTessCallback (tess.glu_tess, GLU_TESS_COMBINE_DATA,
-                   _cogl_path_tesselator_combine);
-
-  gluTessBeginPolygon (tess.glu_tess, &tess);
-
-  while (path_start < data->path_nodes->len)
-    {
-      CoglPathNode *node =
-        &g_array_index (data->path_nodes, CoglPathNode, path_start);
-
-      gluTessBeginContour (tess.glu_tess);
-
-      for (i = 0; i < node->path_size; i++)
-        {
-          double vertex[3] = { node[i].x, node[i].y, 0.0 };
-          gluTessVertex (tess.glu_tess, vertex,
-                         GINT_TO_POINTER (i + path_start));
-        }
-
-      gluTessEndContour (tess.glu_tess);
-
-      path_start += node->path_size;
-    }
-
-  gluTessEndPolygon (tess.glu_tess);
-
-  gluDeleteTess (tess.glu_tess);
-
-  data->fill_attribute_buffer =
-    cogl_attribute_buffer_new (ctx,
-                               sizeof (CoglPathTesselatorVertex) *
-                               tess.vertices->len,
-                               tess.vertices->data);
-  g_array_free (tess.vertices, TRUE);
-
-  data->fill_attributes[0] =
-    cogl_attribute_new (data->fill_attribute_buffer,
-                        "cogl_position_in",
-                        sizeof (CoglPathTesselatorVertex),
-                        G_STRUCT_OFFSET (CoglPathTesselatorVertex, x),
-                        2, /* n_components */
-                        COGL_ATTRIBUTE_TYPE_FLOAT);
-  data->fill_attributes[1] =
-    cogl_attribute_new (data->fill_attribute_buffer,
-                        "cogl_tex_coord0_in",
-                        sizeof (CoglPathTesselatorVertex),
-                        G_STRUCT_OFFSET (CoglPathTesselatorVertex, s),
-                        2, /* n_components */
-                        COGL_ATTRIBUTE_TYPE_FLOAT);
-
-  data->fill_vbo_indices = cogl_indices_new (ctx,
-                                             tess.indices_type,
-                                             tess.indices->data,
-                                             tess.indices->len);
-  data->fill_vbo_n_indices = tess.indices->len;
-  g_array_free (tess.indices, TRUE);
-}
-
-static void
-_cogl_path_build_stroke_attribute_buffer (CoglPath *path)
-{
-  CoglPathData *data = path->data;
-  CoglBuffer *buffer;
-  unsigned int n_attributes = 0;
-  unsigned int path_start;
-  CoglPathNode *node;
-  floatVec2 *buffer_p;
-  unsigned int i;
-
-  _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
-  /* If we've already got a cached vbo then we don't need to do anything */
-  if (data->stroke_attribute_buffer)
-    return;
-
-  data->stroke_attribute_buffer =
-    cogl_attribute_buffer_new (ctx, data->path_nodes->len * sizeof (floatVec2),
-                               NULL);
-
-  buffer = COGL_BUFFER (data->stroke_attribute_buffer);
-  buffer_p = _cogl_buffer_map_for_fill_or_fallback (buffer);
-
-  /* Copy the vertices in and count the number of sub paths. Each sub
-     path will form a separate attribute so we can paint the disjoint
-     line strips */
-  for (path_start = 0;
-       path_start < data->path_nodes->len;
-       path_start += node->path_size)
-    {
-      node = &g_array_index (data->path_nodes, CoglPathNode, path_start);
-
-      for (i = 0; i < node->path_size; i++)
-        {
-          buffer_p[path_start + i].x = node[i].x;
-          buffer_p[path_start + i].y = node[i].y;
-        }
-
-      n_attributes++;
-    }
-
-  _cogl_buffer_unmap_for_fill_or_fallback (buffer);
-
-  data->stroke_attributes = g_new (CoglAttribute *, n_attributes);
-
-  /* Now we can loop the sub paths again to create the attributes */
-  for (i = 0, path_start = 0;
-       path_start < data->path_nodes->len;
-       i++, path_start += node->path_size)
-    {
-      node = &g_array_index (data->path_nodes, CoglPathNode, path_start);
-
-      data->stroke_attributes[i] =
-        cogl_attribute_new (data->stroke_attribute_buffer,
-                            "cogl_position_in",
-                            sizeof (floatVec2),
-                            path_start * sizeof (floatVec2),
-                            2, /* n_components */
-                            COGL_ATTRIBUTE_TYPE_FLOAT);
-    }
-
-  data->stroke_n_attributes = n_attributes;
-}
diff --git a/cogl/cogl2-path.h b/cogl/cogl2-path.h
deleted file mode 100644
index f702c4a..0000000
--- a/cogl/cogl2-path.h
+++ /dev/null
@@ -1,506 +0,0 @@
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2008,2009 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#if !defined(__COGL_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
-#error "Only <cogl/cogl.h> can be included directly."
-#endif
-
-#ifndef __COGL2_PATH_H__
-#define __COGL2_PATH_H__
-
-#include <cogl/cogl-types.h>
-
-G_BEGIN_DECLS
-
-/**
- * SECTION:cogl-paths
- * @short_description: Functions for constructing and drawing 2D paths.
- *
- * There are two levels on which drawing with cogl-paths can be used.
- * The highest level functions construct various simple primitive
- * shapes to be either filled or stroked. Using a lower-level set of
- * functions more complex and arbitrary paths can be constructed by
- * concatenating straight line, bezier curve and arc segments.
- *
- * When constructing arbitrary paths, the current pen location is
- * initialized using the move_to command. The subsequent path segments
- * implicitly use the last pen location as their first vertex and move
- * the pen location to the last vertex they produce at the end. Also
- * there are special versions of functions that allow specifying the
- * vertices of the path segments relative to the last pen location
- * rather then in the absolute coordinates.
- */
-
-typedef struct _CoglPath CoglPath;
-
-#define COGL_PATH(obj) ((CoglPath *)(obj))
-
-#define cogl_path_new cogl2_path_new
-/**
- * cogl_path_new:
- *
- * Creates a new, empty path object. The default fill rule is
- * %COGL_PATH_FILL_RULE_EVEN_ODD.
- *
- * Return value: A pointer to a newly allocated #CoglPath, which can
- * be freed using cogl_object_unref().
- *
- * Since: 2.0
- */
-CoglPath *
-cogl_path_new (void);
-
-/**
- * cogl_path_copy:
- * @path: A #CoglPath object
- *
- * Returns a new copy of the path in @path. The new path has a
- * reference count of 1 so you should unref it with
- * cogl_object_unref() if you no longer need it.
- *
- * Internally the path will share the data until one of the paths is
- * modified so copying paths should be relatively cheap.
- *
- * Return value: a copy of the path in @path.
- *
- * Since: 2.0
- */
-CoglPath *
-cogl_path_copy (CoglPath *path);
-
-/**
- * cogl_is_path:
- * @object: A #CoglObject
- *
- * Gets whether the given object references an existing path object.
- *
- * Return value: %TRUE if the object references a #CoglPath,
- *   %FALSE otherwise.
- *
- * Since: 2.0
- */
-gboolean
-cogl_is_path (void *object);
-
-#define cogl_path_move_to cogl2_path_move_to
-/**
- * cogl_path_move_to:
- * @x: X coordinate of the pen location to move to.
- * @y: Y coordinate of the pen location to move to.
- *
- * Moves the pen to the given location. If there is an existing path
- * this will start a new disjoint subpath.
- *
- * Since: 2.0
- */
-void
-cogl_path_move_to (CoglPath *path,
-                   float x,
-                   float y);
-
-#define cogl_path_rel_move_to cogl2_path_rel_move_to
-/**
- * cogl_path_rel_move_to:
- * @x: X offset from the current pen location to move the pen to.
- * @y: Y offset from the current pen location to move the pen to.
- *
- * Moves the pen to the given offset relative to the current pen
- * location. If there is an existing path this will start a new
- * disjoint subpath.
- *
- * Since: 2.0
- */
-void
-cogl_path_rel_move_to (CoglPath *path,
-                       float x,
-                       float y);
-
-#define cogl_path_line_to cogl2_path_line_to
-/**
- * cogl_path_line_to:
- * @x: X coordinate of the end line vertex
- * @y: Y coordinate of the end line vertex
- *
- * Adds a straight line segment to the current path that ends at the
- * given coordinates.
- *
- * Since: 2.0
- */
-void
-cogl_path_line_to (CoglPath *path,
-                   float x,
-                   float y);
-
-#define cogl_path_rel_line_to cogl2_path_rel_line_to
-/**
- * cogl_path_rel_line_to:
- * @x: X offset from the current pen location of the end line vertex
- * @y: Y offset from the current pen location of the end line vertex
- *
- * Adds a straight line segment to the current path that ends at the
- * given coordinates relative to the current pen location.
- *
- * Since: 2.0
- */
-void
-cogl_path_rel_line_to (CoglPath *path,
-                       float x,
-                       float y);
-
-#define cogl_path_arc cogl2_path_arc
-/**
- * cogl_path_arc:
- * @center_x: X coordinate of the elliptical arc center
- * @center_y: Y coordinate of the elliptical arc center
- * @radius_x: X radius of the elliptical arc
- * @radius_y: Y radius of the elliptical arc
- * @angle_1: Angle in degrees at which the arc begin
- * @angle_2: Angle in degrees at which the arc ends
- *
- * Adds an elliptical arc segment to the current path. A straight line
- * segment will link the current pen location with the first vertex
- * of the arc. If you perform a move_to to the arcs start just before
- * drawing it you create a free standing arc.
- *
- * The angles are measured in degrees where 0° is in the direction of
- * the positive X axis and 90° is in the direction of the positive Y
- * axis. The angle of the arc begins at @angle_1 and heads towards
- * @angle_2 (so if @angle_2 is less than @angle_1 it will decrease,
- * otherwise it will increase).
- *
- * Since: 2.0
- */
-void
-cogl_path_arc (CoglPath *path,
-               float center_x,
-               float center_y,
-               float radius_x,
-               float radius_y,
-               float angle_1,
-               float angle_2);
-
-#define cogl_path_curve_to cogl2_path_curve_to
-/**
- * cogl_path_curve_to:
- * @x_1: X coordinate of the second bezier control point
- * @y_1: Y coordinate of the second bezier control point
- * @x_2: X coordinate of the third bezier control point
- * @y_2: Y coordinate of the third bezier control point
- * @x_3: X coordinate of the fourth bezier control point
- * @y_3: Y coordinate of the fourth bezier control point
- *
- * Adds a cubic bezier curve segment to the current path with the given
- * second, third and fourth control points and using current pen location
- * as the first control point.
- *
- * Since: 2.0
- */
-void
-cogl_path_curve_to (CoglPath *path,
-                    float x_1,
-                    float y_1,
-                    float x_2,
-                    float y_2,
-                    float x_3,
-                    float y_3);
-
-#define cogl_path_rel_curve_to cogl2_path_rel_curve_to
-/**
- * cogl_path_rel_curve_to:
- * @x_1: X coordinate of the second bezier control point
- * @y_1: Y coordinate of the second bezier control point
- * @x_2: X coordinate of the third bezier control point
- * @y_2: Y coordinate of the third bezier control point
- * @x_3: X coordinate of the fourth bezier control point
- * @y_3: Y coordinate of the fourth bezier control point
- *
- * Adds a cubic bezier curve segment to the current path with the given
- * second, third and fourth control points and using current pen location
- * as the first control point. The given coordinates are relative to the
- * current pen location.
- *
- * Since: 2.0
- */
-void
-cogl_path_rel_curve_to (CoglPath *path,
-                        float x_1,
-                        float y_1,
-                        float x_2,
-                        float y_2,
-                        float x_3,
-                        float y_3);
-
-#define cogl_path_close cogl2_path_close
-/**
- * cogl_path_close:
- *
- * Closes the path being constructed by adding a straight line segment
- * to it that ends at the first vertex of the path.
- *
- * Since: 2.0
- */
-void
-cogl_path_close (CoglPath *path);
-
-#define cogl_path_line cogl2_path_line
-/**
- * cogl_path_line:
- * @x_1: X coordinate of the start line vertex
- * @y_1: Y coordinate of the start line vertex
- * @x_2: X coordinate of the end line vertex
- * @y_2: Y coordinate of the end line vertex
- *
- * Constructs a straight line shape starting and ending at the given
- * coordinates. If there is an existing path this will start a new
- * disjoint sub-path.
- *
- * Since: 2.0
- */
-void
-cogl_path_line (CoglPath *path,
-                float x_1,
-                float y_1,
-                float x_2,
-                float y_2);
-
-#define cogl_path_polyline cogl2_path_polyline
-/**
- * cogl_path_polyline:
- * @coords: (in) (array) (transfer none): A pointer to the first element of an
- * array of fixed-point values that specify the vertex coordinates.
- * @num_points: The total number of vertices.
- *
- * Constructs a series of straight line segments, starting from the
- * first given vertex coordinate. If there is an existing path this
- * will start a new disjoint sub-path. Each subsequent segment starts
- * where the previous one ended and ends at the next given vertex
- * coordinate.
- *
- * The coords array must contain 2 * num_points values. The first value
- * represents the X coordinate of the first vertex, the second value
- * represents the Y coordinate of the first vertex, continuing in the same
- * fashion for the rest of the vertices. (num_points - 1) segments will
- * be constructed.
- *
- * Since: 2.0
- */
-void
-cogl_path_polyline (CoglPath *path,
-                    const float *coords,
-                    int num_points);
-
-#define cogl_path_polygon cogl2_path_polygon
-/**
- * cogl_path_polygon:
- * @coords: (in) (array) (transfer none): A pointer to the first element of
- * an array of fixed-point values that specify the vertex coordinates.
- * @num_points: The total number of vertices.
- *
- * Constructs a polygonal shape of the given number of vertices. If
- * there is an existing path this will start a new disjoint sub-path.
- *
- * The coords array must contain 2 * num_points values. The first value
- * represents the X coordinate of the first vertex, the second value
- * represents the Y coordinate of the first vertex, continuing in the same
- * fashion for the rest of the vertices.
- *
- * Since: 2.0
- */
-void
-cogl_path_polygon (CoglPath *path,
-                   const float *coords,
-                   int num_points);
-
-#define cogl_path_rectangle cogl2_path_rectangle
-/**
- * cogl_path_rectangle:
- * @x_1: X coordinate of the top-left corner.
- * @y_1: Y coordinate of the top-left corner.
- * @x_2: X coordinate of the bottom-right corner.
- * @y_2: Y coordinate of the bottom-right corner.
- *
- * Constructs a rectangular shape at the given coordinates. If there
- * is an existing path this will start a new disjoint sub-path.
- *
- * Since: 2.0
- */
-void
-cogl_path_rectangle (CoglPath *path,
-                     float x_1,
-                     float y_1,
-                     float x_2,
-                     float y_2);
-
-#define cogl_path_ellipse cogl2_path_ellipse
-/**
- * cogl_path_ellipse:
- * @center_x: X coordinate of the ellipse center
- * @center_y: Y coordinate of the ellipse center
- * @radius_x: X radius of the ellipse
- * @radius_y: Y radius of the ellipse
- *
- * Constructs an ellipse shape. If there is an existing path this will
- * start a new disjoint sub-path.
- *
- * Since: 2.0
- */
-void
-cogl_path_ellipse (CoglPath *path,
-                   float center_x,
-                   float center_y,
-                   float radius_x,
-                   float radius_y);
-
-#define cogl_path_round_rectangle cogl2_path_round_rectangle
-/**
- * cogl_path_round_rectangle:
- * @x_1: X coordinate of the top-left corner.
- * @y_1: Y coordinate of the top-left corner.
- * @x_2: X coordinate of the bottom-right corner.
- * @y_2: Y coordinate of the bottom-right corner.
- * @radius: Radius of the corner arcs.
- * @arc_step: Angle increment resolution for subdivision of
- * the corner arcs.
- *
- * Constructs a rectangular shape with rounded corners. If there is an
- * existing path this will start a new disjoint sub-path.
- *
- * Since: 2.0
- */
-void
-cogl_path_round_rectangle (CoglPath *path,
-                           float x_1,
-                           float y_1,
-                           float x_2,
-                           float y_2,
-                           float radius,
-                           float arc_step);
-
-/**
- * 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;
-
-#define cogl_path_set_fill_rule cogl2_path_set_fill_rule
-/**
- * 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: 2.0
- */
-void
-cogl_path_set_fill_rule (CoglPath *path, CoglPathFillRule fill_rule);
-
-#define cogl_path_get_fill_rule cogl2_path_get_fill_rule
-/**
- * cogl_path_get_fill_rule:
- *
- * Retrieves the fill rule set using cogl_path_set_fill_rule().
- *
- * Return value: the fill rule that is used for the current path.
- *
- * Since: 2.0
- */
-CoglPathFillRule
-cogl_path_get_fill_rule (CoglPath *path);
-
-#define cogl_path_fill cogl2_path_fill
-/**
- * cogl_path_fill:
- *
- * Fills the interior of the constructed shape using the current
- * drawing color.
- *
- * The interior of the shape is determined using the fill rule of the
- * path. See %CoglPathFillRule for details.
- *
- * <note>The result of referencing sliced textures in your current
- * pipeline when filling a path are undefined. You should pass
- * the %COGL_TEXTURE_NO_SLICING flag when loading any texture you will
- * use while filling a path.</note>
- *
- * Since: 2.0
- */
-void
-cogl_path_fill (CoglPath *path);
-
-#define cogl_path_stroke cogl2_path_stroke
-/**
- * cogl_path_stroke:
- *
- * Strokes the constructed shape using the current drawing color and a
- * width of 1 pixel (regardless of the current transformation
- * matrix).
- *
- * Since: 2.0
- */
-void
-cogl_path_stroke (CoglPath *path);
-
-G_END_DECLS
-
-#endif /* __COGL2_PATH_H__ */
-
-- 
1.7.3.16.g9464b



More information about the Cogl mailing list