[CpmlSegment] Renamed cpml_segment_init() to cpml_segment_from_cairo()
[adg.git] / adg / adg-path.c
blobb85930c317dcb18f8e94cf34268b705ad20d7d43
1 /* ADG - Automatic Drawing Generation
2 * Copyright (C) 2007,2008,2009 Nicola Fontana <ntd at entidi.it>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
20 /**
21 * SECTION:path
22 * @title: AdgPath
23 * @short_description: A stroked path entity
25 * The #AdgPath object is probably the simplest entity: it represents a path
26 * (as intended by the #cairo_path_t structure) in model space.
27 **/
29 #include "adg-path.h"
30 #include "adg-path-private.h"
31 #include "adg-line-style.h"
32 #include "adg-intl.h"
34 #define PARENT_CLASS ((AdgEntityClass *) adg_path_parent_class)
37 static void finalize (GObject *object);
38 static void invalidate (AdgEntity *entity);
39 static void render (AdgEntity *entity,
40 cairo_t *cr);
41 static void clear_path_cache (AdgPath *path);
44 G_DEFINE_TYPE(AdgPath, adg_path, ADG_TYPE_ENTITY)
47 static void
48 adg_path_class_init(AdgPathClass *klass)
50 GObjectClass *gobject_class;
51 AdgEntityClass *entity_class;
53 gobject_class = (GObjectClass *) klass;
54 entity_class = (AdgEntityClass *) klass;
56 g_type_class_add_private(klass, sizeof(AdgPathPrivate));
58 gobject_class->finalize = finalize;
60 entity_class->invalidate = invalidate;
61 entity_class->render = render;
64 static void
65 adg_path_init(AdgPath *path)
67 AdgPathPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE(path, ADG_TYPE_PATH,
68 AdgPathPrivate);
70 priv->cp.x = priv->cp.y = 0.;
71 priv->cairo_path = NULL;
72 priv->callback = NULL;
74 path->priv = priv;
77 static void
78 finalize(GObject *object)
80 clear_path_cache((AdgPath *) object);
82 ((GObjectClass *) PARENT_CLASS)->finalize(object);
85 /**
86 * adg_path_new:
87 * @callback: an #AdgCallback callback
88 * @user_data: user provided pointer to pass to the callback
90 * Creates a new path entity. The path must be constructed in the @callback
91 * function: AdgPath will cache and reuse the cairo_copy_path() returned by
92 * the cairo context after the @callback call.
94 * Return value: the new entity
95 **/
96 AdgEntity *
97 adg_path_new(AdgCallback callback, gpointer user_data)
99 AdgPath *path;
101 path = (AdgPath *) g_object_new(ADG_TYPE_PATH, NULL);
102 path->priv->callback = callback;
103 path->priv->user_data = user_data;
105 return (AdgEntity *) path;
109 * adg_path_get_cairo_path:
110 * @path: an #AdgPath
112 * Gets a pointer to the cairo path structure of @path. The return value
113 * is owned by @path and must be considered read-only.
115 * Return value: a pointer to the internal #cairo_path_t structure
117 const cairo_path_t *
118 adg_path_get_cairo_path(AdgPath *path)
120 g_return_val_if_fail(ADG_IS_PATH(path), NULL);
122 return path->priv->cairo_path;
126 * adg_path_dump:
127 * @path: an #AdgPath
129 * Dumps the data content of @path to stdout in a human readable format.
131 void
132 adg_path_dump(AdgPath *path)
134 CpmlSegment segment;
136 g_return_if_fail(ADG_IS_PATH(path));
138 if (!cpml_segment_from_cairo(&segment, path->priv->cairo_path)) {
139 g_print("Invalid path data to dump!\n");
140 } else {
141 do {
142 cpml_segment_dump(&segment);
143 } while (cpml_segment_next(&segment));
147 static void
148 invalidate(AdgEntity *entity)
150 clear_path_cache((AdgPath *) entity);
152 PARENT_CLASS->invalidate(entity);
155 static void
156 render(AdgEntity *entity, cairo_t *cr)
158 AdgPath *path = (AdgPath *) entity;
160 if (path->priv->cairo_path) {
161 /* Use cached data */
162 cairo_move_to(cr, path->priv->cp.x, path->priv->cp.y);
163 cairo_append_path(cr, path->priv->cairo_path);
164 } else {
165 /* Construct and store the cache */
166 cairo_get_current_point(cr, &path->priv->cp.x, &path->priv->cp.y);
168 if (path->priv->callback)
169 path->priv->callback(entity, cr, path->priv->user_data);
171 path->priv->cairo_path = cairo_copy_path(cr);
174 adg_entity_apply(entity, ADG_SLOT_LINE_STYLE, cr);
175 cairo_stroke(cr);
177 PARENT_CLASS->render(entity, cr);
180 static void
181 clear_path_cache(AdgPath *path)
183 AdgPathPrivate *priv = path->priv;
185 if (priv->cairo_path != NULL) {
186 cairo_path_destroy(priv->cairo_path);
187 priv->cairo_path = NULL;
190 priv->cp.x = priv->cp.y = 0.;