Emmanuele Bassi

              ebassi@linux.intel.com

# Migrating to ClutterPath

Between Clutter 0.8 and Clutter 1.0 the #ClutterBehaviourPath behaviour lost all the path manipulation functions and the ClutterBehaviourBspline class was entirely deprecated.

The class that replaced the path description and manipulation functionality is called #ClutterPath. A #ClutterPath allows describing a path using a sequence of #ClutterPathNodes or using a subset of the SVG path description syntax. A Path instance also allows describing complex paths, with linear and Bezier segments and with gaps.

Finally, #ClutterPath also provides integration with Cairo, by being able to add paths described by the Cairo cairo_path_t data structure and being able to "replay" a #ClutterPath onto a cairo_t Cairo context.

## Creating a #ClutterPath

Before Clutter 1.0, all the path-related functions inside #ClutterBehaviourPath and ClutterBehaviourBspline were replicated, but were also subtly different given the different nature of the types of path handled by the two #ClutterBehaviours.

ClutterBehaviourPath example

The following code shows how a #ClutterBehaviourPath was created prior to the introduction of #ClutterPath. The path described is a square box between 100, 100 and 200, 200.

      ClutterBehaviour *behaviour;
      ClutterKnot knots[] = {
        { 100, 100 },
        { 200, 100 },
        { 200, 200 },
        { 100, 200 },
        { 100, 100 }
      };

      behaviour = clutter_behaviour_path_new (alpha, knots, G_N_ELEMENTS (knots));

The construction for a B-Spline path behaviour was similar, though the #ClutterKnots could only describe a curvilinear path.

Constructing ClutterPath

The following code shows how to construct a #ClutterPath and assign it to a #ClutterBehaviourPath. The created path is the same as the example above.

      ClutterBehaviour *behaviour;
      ClutterPath *path;

      path = clutter_path_new ();
      clutter_path_add_move_to (path, 100, 100);
      clutter_path_add_line_to (path, 200, 100);
      clutter_path_add_line_to (path, 200, 200);
      clutter_path_add_line_to (path, 100, 200);
      clutter_path_add_close (path);

      behaviour = clutter_behaviour_path_new (alpha, path);

A #ClutterPath object can be shared across behaviours, just like the #ClutterAlpha objects can.

Path can be described by using a subset of the SVG notation for paths as well as using #ClutterPathNode structures.

Describing ClutterPath

The SVG path notation subset used by #ClutterPath is in string format and can be both set as the whole path description using clutter_path_set_description() or can be added to an existing #ClutterPath using clutter_path_add_string(). The following example shows the same path as the two examples above.

      ClutterPath *path = clutter_path_new ();

      clutter_path_set_description (path,
                                    "M 100,100 " /* move to */
                                    "L 200,100 " /* line to */
                                    "L 200,200 "
                                    "L 100,200 "
                                    "z"          /* close   */);

A #ClutterPath can describe not only linear, closed paths; it can also describe paths with Beziér curvers and can add gaps.

Describing a mixed ClutterPath

A mixed #ClutterPath, with a Beziér curve between the point at 200, 200 and 100, 100 and both control points in 100, 200.

      ClutterPath *path = clutter_path_new ();

      clutter_path_set_description (path,
                                    "M 100,100 "
                                    "L 200,100 "
                                    "L 200,200 "
                                    "C 100,200 100,200 100,100");

## Iterating over a #ClutterPath

It is possible to iterate over all the #ClutterPathNodes inside a #ClutterPath by using clutter_path_get_nodes(), which will return a #GSList of #ClutterPathNodes; or by using clutter_path_foreach() with a function.

The function pointer passed to clutter_path_foreach() should have the following definition:

      static void
      foreach_node (ClutterPathNode *path_node,
                    gpointer         user_data)
      {
      }

## Integration with Cairo

A #ClutterPath can use a previously defined cairo_path_t to add new nodes, by using the clutter_path_add_cairo_path() function.

It is also possible to paint a #ClutterPath on a Cairo context, by moving the Cairo pen across the nodes of the path using the clutter_path_to_cairo_path() function.