Tested build process under ss-dev of OpenIndiana
[adg.git] / src / adg / adg-stroke.c
blob8fafb533aff4b95cd5898a88361b663eb9629c09
1 /* ADG - Automatic Drawing Generation
2 * Copyright (C) 2007,2008,2009,2010,2011 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 #AdgTrail 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-internal.h"
37 #include "adg-dress.h"
38 #include "adg-dress-builtins.h"
39 #include "adg-style.h"
40 #include "adg-line-style.h"
41 #include "adg-model.h"
42 #include "adg-trail.h"
44 #include "adg-stroke.h"
45 #include "adg-stroke-private.h"
47 #define _ADG_OLD_OBJECT_CLASS ((GObjectClass *) adg_stroke_parent_class)
48 #define _ADG_OLD_ENTITY_CLASS ((AdgEntityClass *) adg_stroke_parent_class)
51 G_DEFINE_TYPE(AdgStroke, adg_stroke, ADG_TYPE_ENTITY)
53 enum {
54 PROP_0,
55 PROP_LINE_DRESS,
56 PROP_TRAIL
60 static void _adg_dispose (GObject *object);
61 static void _adg_get_property (GObject *object,
62 guint param_id,
63 GValue *value,
64 GParamSpec *pspec);
65 static void _adg_set_property (GObject *object,
66 guint param_id,
67 const GValue *value,
68 GParamSpec *pspec);
69 static void _adg_global_changed (AdgEntity *entity);
70 static void _adg_local_changed (AdgEntity *entity);
71 static void _adg_arrange (AdgEntity *entity);
72 static void _adg_render (AdgEntity *entity,
73 cairo_t *cr);
74 static void _adg_unset_trail (AdgStroke *stroke);
77 static void
78 adg_stroke_class_init(AdgStrokeClass *klass)
80 GObjectClass *gobject_class;
81 AdgEntityClass *entity_class;
82 GParamSpec *param;
84 gobject_class = (GObjectClass *) klass;
85 entity_class = (AdgEntityClass *) klass;
87 g_type_class_add_private(klass, sizeof(AdgStrokePrivate));
89 gobject_class->dispose = _adg_dispose;
90 gobject_class->get_property = _adg_get_property;
91 gobject_class->set_property = _adg_set_property;
93 entity_class->global_changed = _adg_global_changed;
94 entity_class->local_changed = _adg_local_changed;
95 entity_class->arrange = _adg_arrange;
96 entity_class->render = _adg_render;
98 param = adg_param_spec_dress("line-dress",
99 P_("Line Dress"),
100 P_("The dress to use for stroking this entity"),
101 ADG_DRESS_LINE_STROKE,
102 G_PARAM_READWRITE);
103 g_object_class_install_property(gobject_class, PROP_LINE_DRESS, param);
105 param = g_param_spec_object("trail",
106 P_("Trail"),
107 P_("The trail to be stroked"),
108 ADG_TYPE_TRAIL,
109 G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
110 g_object_class_install_property(gobject_class, PROP_TRAIL, param);
113 static void
114 adg_stroke_init(AdgStroke *stroke)
116 AdgStrokePrivate *data = G_TYPE_INSTANCE_GET_PRIVATE(stroke,
117 ADG_TYPE_STROKE,
118 AdgStrokePrivate);
120 data->line_dress = ADG_DRESS_LINE_STROKE;
121 data->trail = NULL;
123 stroke->data = data;
126 static void
127 _adg_dispose(GObject *object)
129 AdgStroke *stroke = (AdgStroke *) object;
131 adg_stroke_set_trail(stroke, NULL);
133 if (_ADG_OLD_OBJECT_CLASS->dispose)
134 _ADG_OLD_OBJECT_CLASS->dispose(object);
137 static void
138 _adg_get_property(GObject *object, guint prop_id,
139 GValue *value, GParamSpec *pspec)
141 AdgStrokePrivate *data = ((AdgStroke *) object)->data;
143 switch (prop_id) {
144 case PROP_LINE_DRESS:
145 g_value_set_int(value, data->line_dress);
146 break;
147 case PROP_TRAIL:
148 g_value_set_object(value, data->trail);
149 break;
150 default:
151 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
152 break;
156 static void
157 _adg_set_property(GObject *object, guint prop_id,
158 const GValue *value, GParamSpec *pspec)
160 AdgStrokePrivate *data = ((AdgStroke *) object)->data;
161 AdgTrail *old_trail;
163 switch (prop_id) {
164 case PROP_LINE_DRESS:
165 data->line_dress = g_value_get_int(value);
166 break;
167 case PROP_TRAIL:
168 old_trail = data->trail;
169 data->trail = g_value_get_object(value);
171 if (data->trail != old_trail) {
172 if (data->trail) {
173 g_object_weak_ref((GObject *) data->trail,
174 (GWeakNotify) _adg_unset_trail, object);
175 adg_model_add_dependency((AdgModel *) data->trail,
176 (AdgEntity *) object);
178 if (old_trail) {
179 g_object_weak_unref((GObject *) old_trail,
180 (GWeakNotify) _adg_unset_trail, object);
181 adg_model_remove_dependency((AdgModel *) old_trail,
182 (AdgEntity *) object);
185 break;
186 default:
187 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
188 break;
194 * adg_stroke_new:
195 * @trail: the #AdgTrail to stroke
197 * Creates a new stroke entity based on the @trail model.
198 * @trail can be %NULL, in which case an empty stroke is created.
200 * Returns: the newly created stroke entity
202 AdgStroke *
203 adg_stroke_new(AdgTrail *trail)
205 return g_object_new(ADG_TYPE_STROKE, "trail", trail, NULL);
209 * adg_stroke_set_line_dress:
210 * @stroke: an #AdgStroke
211 * @dress: the new #AdgDress to use
213 * Sets a new line dress for rendering @stroke. The new dress
214 * must be related to the original dress for this property:
215 * you cannot set a dress used for line styles to a dress
216 * managing fonts.
218 * The check is done by calling adg_dress_are_related() with
219 * @dress and the previous dress as arguments. Check out its
220 * documentation for details on what is a related dress.
222 void
223 adg_stroke_set_line_dress(AdgStroke *stroke, AdgDress dress)
225 g_return_if_fail(ADG_IS_STROKE(stroke));
226 g_object_set(stroke, "line-dress", dress, NULL);
230 * adg_stroke_get_line_dress:
231 * @stroke: an #AdgStroke
233 * Gets the line dress to be used in rendering @stroke.
235 * Returns: the current line dress
237 AdgDress
238 adg_stroke_get_line_dress(AdgStroke *stroke)
240 AdgStrokePrivate *data;
242 g_return_val_if_fail(ADG_IS_STROKE(stroke), ADG_DRESS_UNDEFINED);
244 data = stroke->data;
246 return data->line_dress;
250 * adg_stroke_set_trail:
251 * @stroke: an #AdgStroke
252 * @trail: the new #AdgTrail to bind
254 * Sets @trail as the new trail to be stroked by @stroke.
256 void
257 adg_stroke_set_trail(AdgStroke *stroke, AdgTrail *trail)
259 g_return_if_fail(ADG_IS_STROKE(stroke));
260 g_object_set(stroke, "trail", trail, NULL);
264 * adg_stroke_get_trail:
265 * @stroke: an #AdgStroke
267 * Gets the #AdgTrail bound to this @stroke entity.
269 * Returns: the requested #AdgTrail or %NULL on errors
271 AdgTrail *
272 adg_stroke_get_trail(AdgStroke *stroke)
274 AdgStrokePrivate *data;
276 g_return_val_if_fail(ADG_IS_STROKE(stroke), NULL);
278 data = stroke->data;
280 return data->trail;
284 static void
285 _adg_global_changed(AdgEntity *entity)
287 if (_ADG_OLD_ENTITY_CLASS->global_changed)
288 _ADG_OLD_ENTITY_CLASS->global_changed(entity);
290 adg_entity_invalidate(entity);
293 static void
294 _adg_local_changed(AdgEntity *entity)
296 if (_ADG_OLD_ENTITY_CLASS->local_changed)
297 _ADG_OLD_ENTITY_CLASS->local_changed(entity);
299 adg_entity_invalidate(entity);
302 static void
303 _adg_arrange(AdgEntity *entity)
305 AdgStroke *stroke;
306 AdgStrokePrivate *data;
307 CpmlExtents extents;
309 /* Check for cached result */
310 if (adg_entity_get_extents(entity)->is_defined)
311 return;
313 stroke = (AdgStroke *) entity;
314 data = stroke->data;
316 cpml_extents_copy(&extents, adg_trail_get_extents(data->trail));
317 cpml_extents_transform(&extents, adg_entity_get_local_matrix(entity));
318 cpml_extents_transform(&extents, adg_entity_get_global_matrix(entity));
320 adg_entity_set_extents(entity, &extents);
323 static void
324 _adg_render(AdgEntity *entity, cairo_t *cr)
326 AdgStroke *stroke;
327 AdgStrokePrivate *data;
328 const cairo_path_t *cairo_path;
330 stroke = (AdgStroke *) entity;
331 data = stroke->data;
332 cairo_path = adg_trail_get_cairo_path(data->trail);
334 if (cairo_path != NULL) {
335 cairo_transform(cr, adg_entity_get_global_matrix(entity));
337 cairo_save(cr);
338 cairo_transform(cr, adg_entity_get_local_matrix(entity));
339 cairo_append_path(cr, cairo_path);
340 cairo_restore(cr);
342 adg_entity_apply_dress(entity, data->line_dress, cr);
343 cairo_stroke(cr);
347 static void
348 _adg_unset_trail(AdgStroke *stroke)
350 g_object_set(stroke, "trail", NULL, NULL);