/* This file is part of GEGL * * GEGL 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 3 of the License, or (at your option) any later version. * * GEGL 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 GEGL; if not, see . * * Copyright 2011 Michael Muré * Copyright 2007 Øyvind Kolås */ /*** * GeglPath: * * GeglPath is GEGLs means of storing the nodes and other knots and the * instructions for rendering 2d paths like poly lines, bezier curves and other * curve representations. */ #ifndef __GEGL_PATH_H__ #define __GEGL_PATH_H__ #include #include G_BEGIN_DECLS #define GEGL_TYPE_PATH (gegl_path_get_type ()) #define GEGL_PATH(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEGL_TYPE_PATH, GeglPath)) #define GEGL_PATH_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GEGL_TYPE_PATH, GeglPathClass)) #define GEGL_IS_PATH(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GEGL_TYPE_PATH)) #define GEGL_IS_PATH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GEGL_TYPE_PATH)) #define GEGL_PATH_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GEGL_TYPE_PATH, GeglPathClass)) typedef struct _GeglPathClass GeglPathClass; struct _GeglPath { GObject parent_instance; }; GType gegl_path_get_type (void) G_GNUC_CONST; /* Internally the following structures are used, parts * of the internal implementation are exposed through * the path access API. The linked list api is currently * only used for adding new path interpolators/flatteners * with new knot interpretations. */ /*** * GeglPathItem: * * A #GeglPathItem contains the type of instruction to perform as * well as it's arguments. In the public API the PathItem always has * 4 points internally only the needed amount of memory is stored * for a GeglPathItem. * *

typedef struct GeglPathPoint
 * {
 *   gfloat x;
 *   gfloat y;
 * } GeglPathPoint;

*

typedef struct GeglPathItem
 * {
 *   gchar  type;
 *   GeglPathPoint  point[4];
 * } GeglPathItem;

* */ typedef struct GeglPathPoint { gfloat x; gfloat y; } GeglPathPoint; typedef struct GeglPathItem { gchar type; /* should perhaps be padded out? */ GeglPathPoint point[4]; /* Note: internally GeglPath operates with paths that * have the exact number of pairs allocated. */ } GeglPathItem; /** * gegl_path_new: * * Creates a new #GeglPath with no nodes. * * Returns the newly created #GeglPath */ GeglPath * gegl_path_new (void); /** * gegl_path_new_from_string: * @instructions: a string describing the path. * * Creates a new #GeglPath with the nodes described in the string * @instructions. See gegl_path_parse_string() for details of the * format of the string. * * Returns the newly created #GeglPath */ GeglPath * gegl_path_new_from_string(const gchar *instructions); /** * gegl_path_is_empty: * @path: a #GeglPath * * Check if the path contains any nodes. * * Returns TRUE if the path has no nodes. */ gboolean gegl_path_is_empty (GeglPath *path); /** * gegl_path_get_n_nodes: * @path: a #GeglPath * * Retrieves the number of nodes in the path. * * Return value: the number of nodes in the path. */ gint gegl_path_get_n_nodes (GeglPath *path); /** * gegl_path_get_length: * @path: a #GeglPath * * Returns the total length of the path. * * Return value: the length of the path. */ gdouble gegl_path_get_length (GeglPath *path); /** * gegl_path_get_node: * @path: a #GeglPath * @index: the node number to retrieve * @node: (out): a pointer to a #GeglPathItem record to be written. * * Retrieve the node of the path at position @pos. * * Returns TRUE if the node was successfully retrieved. */ gboolean gegl_path_get_node (GeglPath *path, gint index, GeglPathItem *node); /** * gegl_path_to_string: * @path: a #GeglPath * * Serialize the paths nodes to a string. * * Return value: return a string with instructions describing the string you * need to free this with g_free(). */ gchar * gegl_path_to_string (GeglPath *path); /** * gegl_path_set_matrix: * @path: a #GeglPath * @matrix: (in) (transfer none): a #GeglMatrix3 to copy the matrix from * * Set the transformation matrix of the path. * * The path is transformed through this matrix when being evaluated, * causing the calculated positions and length to be changed by the transform. */ void gegl_path_set_matrix (GeglPath *path, GeglMatrix3 *matrix); /** * gegl_path_get_matrix: * @path: a #GeglPath * @matrix: (out caller-allocates): a #GeglMatrix3 to copy the matrix into * * Get the transformation matrix of the path. */ void gegl_path_get_matrix (GeglPath *path, GeglMatrix3 *matrix); /** * gegl_path_closest_point: * @path: a #GeglPath * @x: x coordinate. * @y: y coordinate * @on_path_x: (out): return location for x coordinate on the path that was closest * @on_path_y: (out): return location for y coordinate on the path that was closest * @node_pos_before: (out): the node position interpreted before this position * was deemed the closest coordinate. * * Figure out what and where on a path is closest to arbitrary coordinates. * * Returns the length along the path where the closest point was encountered. */ gdouble gegl_path_closest_point (GeglPath *path, gdouble x, gdouble y, gdouble *on_path_x, gdouble *on_path_y, gint *node_pos_before); /** * gegl_path_calc_y_for_x: * @path: a #GeglPath * @x: x coordinate to compute for * @y: (out): return location for y coordinate * * Compute a corresponding y coordinate for a given x input coordinate, * returns 0 if computed correctly and -1 if the path doesn't exist for the * specified x coordinate. */ gint gegl_path_calc_y_for_x (GeglPath *path, gdouble x, gdouble *y); /** * gegl_path_calc: * @path: a #GeglPath * @pos: how far along the path. * @x: (out): return location for x coordinate. * @y: (out): return location for y coordinate * * Compute the coordinates of the path at the @position (length measured from * start of path, not including discontinuities). */ gboolean gegl_path_calc (GeglPath *path, gdouble pos, gdouble *x, gdouble *y); /** * gegl_path_calc_values: (skip) * @path: a #GeglPath * @num_samples: number of samples to compute * @xs: (out caller-allocates) (array length=num_samples): return location for x coordinates * @ys: (out caller-allocates) (array length=num_samples): return location for y coordinates * * Compute @num_samples for a path into the provided arrays @xs and @ys * the returned values include the start and end positions of the path. */ void gegl_path_calc_values (GeglPath *path, guint num_samples, gdouble *xs, gdouble *ys); /** * gegl_path_get_bounds: * @self: a #GeglPath. * @min_x: (out): return location for minimum x coordinate * @max_x: (out): return location for maximum x coordinate * @min_y: (out): return location for minimum y coordinate * @max_y: (out): return location for maximum y coordinate * * Compute the bounding box of a path. */ void gegl_path_get_bounds (GeglPath *self, gdouble *min_x, gdouble *max_x, gdouble *min_y, gdouble *max_y); /* XXX: LP and RP are nasty hacks because the GEGL docs code scanner gets * confused, need to be fixed there */ #define LP ( #define RP ) typedef void LP *GeglNodeFunction RP LP const GeglPathItem *node, gpointer user_data RP; #undef LP #undef RP /** * gegl_path_foreach: * @path: a #GeglPath * @each_item: (closure user_data) (scope call): a function to call for each node in the path. * @user_data: user data to pass to the function (in addition to the GeglPathItem). * * Execute a provided function for every node in the path (useful for * drawing and otherwise traversing a path.) */ void gegl_path_foreach (GeglPath *path, GeglNodeFunction each_item, gpointer user_data); /** * gegl_path_foreach_flat: * @path: a #GeglPath * @each_item: (closure user_data) (scope call): a function to call for each node in the path. * @user_data: user data to pass to a node. * * Execute a provided function for the segments of a poly line approximating * the path. */ void gegl_path_foreach_flat (GeglPath *path, GeglNodeFunction each_item, gpointer user_data); /** * gegl_path_clear: * @path: a #GeglPath * * Remove all nods from a @path. */ void gegl_path_clear (GeglPath *path); /** * gegl_path_insert_node: * @path: a #GeglPath * @pos: the position we want the new node to have. * @node: pointer to a structure describing the GeglPathItem we want to store * * Insert the new node @node at position @pos in @path. * if @pos = -1, the node is added in the last position. */ void gegl_path_insert_node (GeglPath *path, gint pos, const GeglPathItem *node); /** * gegl_path_replace_node: * @path: a #GeglPath * @pos: the position we want the new node to have. * @node: pointer to a structure describing the GeglPathItem we want to store. * * Replaces the exiting node at position @pos in @path. */ void gegl_path_replace_node (GeglPath *path, gint pos, const GeglPathItem *node); /** * gegl_path_remove_node: * @path: a #GeglPath * @pos: a node in the path. * * Removes the node number @pos in @path. */ void gegl_path_remove_node (GeglPath *path, gint pos); /** * gegl_path_parse_string: * @path: a #GeglPath * @instructions: a string describing a path. * * Parses @instructions and appends corresponding nodes to path (call * gegl_path_clean() first if you want to replace the existing path. */ void gegl_path_parse_string (GeglPath *path, const gchar *instructions); /** * gegl_path_append: * @path: a #GeglPath * @...: first instruction. * * Use as follows: gegl_path_append (path, 'M', 0.0, 0.0); * and gegl_path_append (path, 'C', 10.0, 10.0, 50.0, 10.0, 60.0, 0.0) the * number of arguments are determined from the instruction provided. */ void gegl_path_append (GeglPath *path, ...); /** * gegl_path_freeze: * @path: a @GeglPath * * Make the @GeglPath stop firing signals as it changes must be paired with a * gegl_path_thaw() for the signals to start again. */ void gegl_path_freeze (GeglPath *path); /** * gegl_path_thaw: * @path: a @GeglPath * * Restart firing signals (unless the path has been frozen multiple times). */ void gegl_path_thaw (GeglPath *path); /** * gegl_param_spec_path: * @name: canonical name of the property specified * @nick: nick name for the property specified * @blurb: description of the property specified * @default_path: the default value for the property specified * @flags: flags for the property specified * * Creates a new #GParamSpec instance specifying a #GeglPath property. * * Returns: (transfer full): a newly created parameter specification */ GParamSpec * gegl_param_spec_path (const gchar *name, const gchar *nick, const gchar *blurb, GeglPath *default_path, GParamFlags flags); #define GEGL_TYPE_PARAM_PATH (gegl_param_path_get_type ()) #define GEGL_IS_PARAM_PATH(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GEGL_TYPE_PARAM_PATH)) GType gegl_param_path_get_type (void) G_GNUC_CONST; /** * gegl_path_add_type: * @type: a gchar to recognize in path descriptions. * @items: the number of floating point data items the instruction takes * @description: a human readable description of this entry * * Adds a new type to the path system, FIXME this should probably * return something on registration conflicts, for now it expects * all registered paths to be aware of each other. */ void gegl_path_add_type (gchar type, gint items, const gchar *description); /*** * GeglPathList: (skip) * * Linked list used internally, and for the plug-in API for new path * interpolators. */ typedef struct GeglPathList { struct GeglPathList *next; GeglPathItem d; } GeglPathList; /** * gegl_path_list_append: (skip) * @head: a #GeglPathList * @...: additional #GeglPathList items to append * * Appends to path list, if head is NULL a new list is created */ GeglPathList * gegl_path_list_append (GeglPathList *head, ...); /** * gegl_path_list_destroy: (skip) * @path: A #GeglPathList * * Frees up a path list */ GeglPathList * gegl_path_list_destroy (GeglPathList *path); /*** * GeglFlattenerFunc: (skip) * * prototype of function passed to gegl_path_add_flattener() */ typedef GeglPathList *(*GeglFlattenerFunc) (GeglPathList *original); /** * gegl_path_add_flattener: (skip) * @func: a #GeglFlattenerFunc * * Add a new flattener, the flattener should produce a type of path that * GeglPath already understands, if the flattener is unable to flatten * the incoming path (doesn't understand the instructions), the original * path should be returned. */ void gegl_path_add_flattener (GeglFlattenerFunc func); /** * gegl_path_get_path: (skip) * @path: a #GeglPath * * Return the internal untouched #GeglPathList */ GeglPathList * gegl_path_get_path (GeglPath *path); /** * gegl_path_get_flat_path: (skip) * @path: a #GeglPath * * Return a polyline version of @path */ GeglPathList * gegl_path_get_flat_path (GeglPath *path); /*** * GeglPathPoint: (skip) */ /** * gegl_path_point_lerp: (skip) * @dest: return location for the result * @a: origin GeglPathPoint * @b: destination GeglPathPoint * @t: ratio between @a and @b * * linear interpolation between two #GeglPathPoint */ void gegl_path_point_lerp (GeglPathPoint *dest, GeglPathPoint *a, GeglPathPoint *b, gfloat t); /** * gegl_path_point_dist: (skip) * @a: an arbitrary GeglPathPoint * @b: an arbitrary GeglPathPoint * * Compute the distance between #GeglPathPoint @a and @b */ gdouble gegl_path_point_dist (GeglPathPoint *a, GeglPathPoint *b); /** * gegl_path_dirty: * @path: a #GeglPath * * Marks the path as dirty and issues an invalidation for the path rendering, * use this if modifying the values of a GeglPathPoint inline. */ void gegl_path_dirty (GeglPath *path); G_END_DECLS #endif /* __GEGL_PATH_H__ */