[AdgPath] Added adg_path_get_segment()
[adg.git] / adg / adg-stroke.c
blob6fae5936dbc6690f7cc379d885e692dde5052748
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 Lesser 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 * Lesser 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., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
21 /**
22 * SECTION:adg-stroke
23 * @short_description: A stroked entity
25 * The #AdgStroke object is a stroked representation of an #AdgPath model.
26 **/
28 /**
29 * AdgStroke:
31 * All fields are private and should not be used directly.
32 * Use its public methods instead.
33 **/
36 #include "adg-stroke.h"
37 #include "adg-stroke-private.h"
38 #include "adg-line-style.h"
39 #include "adg-intl.h"
42 enum {
43 PROP_0,
44 PROP_PATH
47 static void get_property (GObject *object,
48 guint param_id,
49 GValue *value,
50 GParamSpec *pspec);
51 static void set_property (GObject *object,
52 guint param_id,
53 const GValue *value,
54 GParamSpec *pspec);
55 static gboolean set_path (AdgStroke *stroke,
56 AdgPath *path);
57 static void unset_path (AdgStroke *stroke);
58 static gboolean render (AdgEntity *entity,
59 cairo_t *cr);
62 G_DEFINE_TYPE(AdgStroke, adg_stroke, ADG_TYPE_ENTITY);
65 static void
66 adg_stroke_class_init(AdgStrokeClass *klass)
68 GObjectClass *gobject_class;
69 AdgEntityClass *entity_class;
70 GParamSpec *param;
72 gobject_class = (GObjectClass *) klass;
73 entity_class = (AdgEntityClass *) klass;
75 g_type_class_add_private(klass, sizeof(AdgStrokePrivate));
77 gobject_class->get_property = get_property;
78 gobject_class->set_property = set_property;
80 entity_class->render = render;
82 param = g_param_spec_object("path",
83 P_("Path"),
84 P_("The path to be stroked"),
85 ADG_TYPE_PATH,
86 G_PARAM_CONSTRUCT|G_PARAM_READWRITE);
87 g_object_class_install_property(gobject_class, PROP_PATH, param);
90 static void
91 adg_stroke_init(AdgStroke *stroke)
93 AdgStrokePrivate *data = G_TYPE_INSTANCE_GET_PRIVATE(stroke,
94 ADG_TYPE_STROKE,
95 AdgStrokePrivate);
97 data->path = NULL;
99 stroke->data = data;
102 static void
103 get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
105 AdgStrokePrivate *data = ((AdgStroke *) object)->data;
107 switch (prop_id) {
108 case PROP_PATH:
109 g_value_set_object(value, &data->path);
110 break;
111 default:
112 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
113 break;
117 static void
118 set_property(GObject *object, guint prop_id,
119 const GValue *value, GParamSpec *pspec)
121 AdgStroke *stroke = (AdgStroke *) object;
123 switch (prop_id) {
124 case PROP_PATH:
125 set_path(stroke, (AdgPath *) g_value_get_object(value));
126 break;
127 default:
128 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
129 break;
135 * adg_stroke_new:
136 * @path: the #AdgPath to stroke
138 * Creates a new stroke entity.
140 * Returns: the newly created entity
142 AdgEntity *
143 adg_stroke_new(AdgPath *path)
145 g_return_val_if_fail(ADG_IS_PATH(path), NULL);
147 return (AdgEntity *) g_object_new(ADG_TYPE_STROKE, "path", path, NULL);
152 * adg_stroke_get_path:
153 * @stroke: an #AdgStroke
155 * Gets the #AdgPath binded to this @stroke entity.
157 * Returns: the requested #AdgPath or %NULL on errors
159 AdgPath *
160 adg_stroke_get_path(AdgStroke *stroke)
162 AdgStrokePrivate *data;
164 g_return_val_if_fail(ADG_IS_STROKE(stroke), NULL);
166 data = stroke->data;
168 return data->path;
172 * adg_stroke_set_path:
173 * @stroke: an #AdgStroke
174 * @path: the new #AdgPath to bind
176 * Sets @path as the new path to be stroked by @stroke.
178 void
179 adg_stroke_set_path(AdgStroke *stroke, AdgPath *path)
181 g_return_if_fail(ADG_IS_STROKE(stroke));
183 if (set_path(stroke, path))
184 g_object_notify((GObject *) stroke, "path");
188 static gboolean
189 set_path(AdgStroke *stroke, AdgPath *path)
191 AdgEntity *entity;
192 AdgStrokePrivate *data;
194 entity = (AdgEntity *) stroke;
195 data = stroke->data;
197 if (path == data->path)
198 return FALSE;
200 if (data->path != NULL) {
201 g_object_weak_unref((GObject *) data->path,
202 (GWeakNotify) unset_path, stroke);
203 adg_model_remove_dependency((AdgModel *) data->path, entity);
206 data->path = path;
208 if (data->path != NULL) {
209 g_object_weak_ref((GObject *) data->path,
210 (GWeakNotify) unset_path, stroke);
211 adg_model_add_dependency((AdgModel *) data->path, entity);
214 return TRUE;
217 static void
218 unset_path(AdgStroke *stroke)
220 AdgStrokePrivate *data = stroke->data;
222 if (data->path != NULL) {
223 data->path = NULL;
224 adg_entity_invalidate((AdgEntity *) stroke);
228 static gboolean
229 render(AdgEntity *entity, cairo_t *cr)
231 AdgStroke *stroke;
232 AdgStrokePrivate *data;
233 const cairo_path_t *cairo_path;
235 stroke = (AdgStroke *) entity;
236 data = stroke->data;
237 cairo_path = adg_path_get_cairo_path(data->path);
239 if (cairo_path != NULL) {
240 AdgMatrix local, ctm;
242 adg_entity_get_local_matrix(entity, &local);
244 cairo_save(cr);
246 /* Apply the local matrix BEFORE the global one */
247 cairo_get_matrix(cr, &ctm);
248 cairo_matrix_multiply(&ctm, &ctm, &local);
249 cairo_set_matrix(cr, &ctm);
251 cairo_append_path(cr, cairo_path);
253 cairo_restore(cr);
255 adg_entity_apply(entity, ADG_SLOT_LINE_STYLE, cr);
256 cairo_stroke(cr);
259 return TRUE;