adg: "transfer none" on get_cairo_path()
[adg.git] / src / adg / adg-fill-style.c
blob8e8b0dd43950e60fa88a1dbe930643ceb2a4cc78
1 /* ADG - Automatic Drawing Generation
2 * Copyright (C) 2007,2008,2009,2010,2011,2012,2013 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-fill-style
23 * @short_description: Generic pattern fill
25 * A style defining a generic fill based on cairo_pattern_t.
27 * Since: 1.0
28 **/
30 /**
31 * AdgFillStyle:
33 * All fields are private and should not be used directly.
34 * Use its public methods instead.
36 * Since: 1.0
37 **/
39 /**
40 * AdgFillStyleClass:
41 * @set_extents: virtual method that specifies where a specific fill style
42 * must be applied. It is called by #AdgHatch in the rendering
43 * phase passing with its boundary box as argument.
45 * The default @set_extents@ implementation simply sets the extents owned by
46 * the fill style instance to the one provided, so the last call has
47 * precedence. Any derived class can override it to customize this behavior,
48 * for example to keep the greatest boundary box instead of the last one.
50 * Since: 1.0
51 **/
54 #include "adg-internal.h"
55 #include "adg-style.h"
56 #include "adg-cairo-fallback.h"
58 #include "adg-fill-style.h"
59 #include "adg-fill-style-private.h"
62 G_DEFINE_ABSTRACT_TYPE(AdgFillStyle, adg_fill_style, ADG_TYPE_STYLE)
64 enum {
65 PROP_0,
66 PROP_PATTERN
70 static void _adg_finalize (GObject *object);
71 static void _adg_get_property (GObject *object,
72 guint prop_id,
73 GValue *value,
74 GParamSpec *pspec);
75 static void _adg_set_property (GObject *object,
76 guint prop_id,
77 const GValue *value,
78 GParamSpec *pspec);
79 static void _adg_apply (AdgStyle *style,
80 AdgEntity *entity,
81 cairo_t *cr);
82 static void _adg_set_extents (AdgFillStyle *fill_style,
83 const CpmlExtents *extents);
86 static void
87 adg_fill_style_class_init(AdgFillStyleClass *klass)
89 GObjectClass *gobject_class;
90 AdgStyleClass *style_class;
91 GParamSpec *param;
93 gobject_class = (GObjectClass *) klass;
94 style_class = (AdgStyleClass *) klass;
96 g_type_class_add_private(klass, sizeof(AdgFillStylePrivate));
98 gobject_class->finalize = _adg_finalize;
99 gobject_class->get_property = _adg_get_property;
100 gobject_class->set_property = _adg_set_property;
102 style_class->apply = _adg_apply;
104 klass->set_extents = _adg_set_extents;
106 param = g_param_spec_boxed("pattern",
107 P_("Pattern"),
108 P_("The cairo pattern set for this entity"),
109 CAIRO_GOBJECT_TYPE_PATTERN,
110 G_PARAM_READWRITE);
111 g_object_class_install_property(gobject_class, PROP_PATTERN, param);
114 static void
115 adg_fill_style_init(AdgFillStyle *fill_style)
117 AdgFillStylePrivate *data = G_TYPE_INSTANCE_GET_PRIVATE(fill_style,
118 ADG_TYPE_FILL_STYLE,
119 AdgFillStylePrivate);
121 data->pattern = NULL;
123 fill_style->data = data;
126 static void
127 _adg_finalize(GObject *object)
129 AdgFillStylePrivate *data = ((AdgFillStyle *) object)->data;
131 if (data->pattern != NULL) {
132 cairo_pattern_destroy(data->pattern);
133 data->pattern = NULL;
137 static void
138 _adg_get_property(GObject *object, guint prop_id,
139 GValue *value, GParamSpec *pspec)
141 AdgFillStylePrivate *data = ((AdgFillStyle *) object)->data;
143 switch (prop_id) {
144 case PROP_PATTERN:
145 g_value_set_boxed(value, data->pattern);
146 break;
147 default:
148 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
149 break;
153 static void
154 _adg_set_property(GObject *object, guint prop_id,
155 const GValue *value, GParamSpec *pspec)
157 AdgFillStylePrivate *data = ((AdgFillStyle *) object)->data;
158 cairo_pattern_t *old_pattern;
160 switch (prop_id) {
161 case PROP_PATTERN:
162 old_pattern = data->pattern;
163 data->pattern = g_value_get_boxed(value);
165 if (data->pattern)
166 cairo_pattern_reference(data->pattern);
167 if (old_pattern)
168 cairo_pattern_destroy(old_pattern);
169 break;
170 default:
171 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
172 break;
178 * adg_fill_style_set_pattern:
179 * @fill_style: an #AdgFillStyle
180 * @pattern: the new pattern
182 * <note><para>
183 * This function is only useful in new fill implementations.
184 * </para></note>
186 * Sets a new pattern on @fill_style. A new reference is added to
187 * @pattern with cairo_pattern_reference() and the old pattern
188 * (if any) is unreferenced with cairo_pattern_destroy().
190 * Since: 1.0
192 void
193 adg_fill_style_set_pattern(AdgFillStyle *fill_style,
194 cairo_pattern_t *pattern)
196 g_return_if_fail(ADG_IS_FILL_STYLE(fill_style));
197 g_object_set(fill_style, "pattern", pattern, NULL);
201 * adg_fill_style_get_pattern:
202 * @fill_style: an #AdgFillStyle
204 * Gets the current pattern binded to @fill_style.
206 * Returns: (transfer none): the current pattern
208 * Since: 1.0
210 cairo_pattern_t *
211 adg_fill_style_get_pattern(AdgFillStyle *fill_style)
213 AdgFillStylePrivate *data;
215 g_return_val_if_fail(ADG_IS_FILL_STYLE(fill_style), NULL);
217 data = fill_style->data;
219 return data->pattern;
223 * adg_fill_style_set_extents:
224 * @fill_style: an #AdgFillStyle
225 * @extents: the new extents
227 * <note><para>
228 * This function is only useful in new fill style implementations.
229 * </para></note>
231 * Forcibly sets new extents on @fill_style. Any fill style class
232 * that want to make some kind of customization can override the
233 * set_extents() virtual method to intercept any extents change.
235 * Sets new extents on @fill_style. These extents are usually set
236 * by the arrange() method of the entity using this filling style.
238 * Since: 1.0
240 void
241 adg_fill_style_set_extents(AdgFillStyle *fill_style,
242 const CpmlExtents *extents)
244 AdgFillStyleClass *klass;
246 g_return_if_fail(ADG_IS_FILL_STYLE(fill_style));
247 g_return_if_fail(extents != NULL);
249 klass = ADG_FILL_STYLE_GET_CLASS(fill_style);
251 if (klass->set_extents)
252 klass->set_extents(fill_style, extents);
256 * adg_fill_style_get_extents:
257 * @fill_style: an #AdgFillStyle
259 * Stores a copy of the extents of @fill_style in @extents.
260 * This struct specifies the maximum portion (in global space)
261 * this fill style should be applied: it will clamped by the
262 * entities as needed.
264 * Returns: (transfer none): the extents of @fill_style or %NULL on errors.
266 * Since: 1.0
268 const CpmlExtents *
269 adg_fill_style_get_extents(AdgFillStyle *fill_style)
271 AdgFillStylePrivate *data;
273 g_return_val_if_fail(ADG_IS_FILL_STYLE(fill_style), NULL);
275 data = fill_style->data;
277 return &data->extents;
281 static void
282 _adg_apply(AdgStyle *style, AdgEntity *entity, cairo_t *cr)
284 AdgFillStylePrivate *data = ((AdgFillStyle *) style)->data;
286 if (data->pattern == NULL)
287 g_warning(_("%s: pattern undefined for type `%s'"),
288 G_STRLOC, g_type_name(G_OBJECT_TYPE(style)));
289 else
290 cairo_set_source(cr, data->pattern);
293 static void
294 _adg_set_extents(AdgFillStyle *fill_style, const CpmlExtents *extents)
296 AdgFillStylePrivate *data = fill_style->data;
298 cpml_extents_copy(&data->extents, extents);