s/2010 N/2010,2011 N/
[adg.git] / src / adg / adg-fill-style.c
blob1664318ad56984b49807857697776f63de6f7048
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-fill-style
23 * @short_description: Generic pattern fill
25 * A style defining a generic fill based on cairo_pattern_t.
26 **/
28 /**
29 * AdgFillStyle:
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-fill-style.h"
38 #include "adg-fill-style-private.h"
41 G_DEFINE_ABSTRACT_TYPE(AdgFillStyle, adg_fill_style, ADG_TYPE_STYLE);
43 enum {
44 PROP_0,
45 PROP_PATTERN
49 static void _adg_finalize (GObject *object);
50 static void _adg_get_property (GObject *object,
51 guint prop_id,
52 GValue *value,
53 GParamSpec *pspec);
54 static void _adg_set_property (GObject *object,
55 guint prop_id,
56 const GValue *value,
57 GParamSpec *pspec);
58 static void _adg_apply (AdgStyle *style,
59 AdgEntity *entity,
60 cairo_t *cr);
61 static void _adg_set_extents (AdgFillStyle *fill_style,
62 const CpmlExtents *extents);
65 static void
66 adg_fill_style_class_init(AdgFillStyleClass *klass)
68 GObjectClass *gobject_class;
69 AdgStyleClass *style_class;
70 GParamSpec *param;
72 gobject_class = (GObjectClass *) klass;
73 style_class = (AdgStyleClass *) klass;
75 g_type_class_add_private(klass, sizeof(AdgFillStylePrivate));
77 gobject_class->finalize = _adg_finalize;
78 gobject_class->get_property = _adg_get_property;
79 gobject_class->set_property = _adg_set_property;
81 style_class->apply = _adg_apply;
83 klass->set_extents = _adg_set_extents;
85 param = g_param_spec_boxed("pattern",
86 P_("Pattern"),
87 P_("The cairo pattern set for this entity"),
88 ADG_TYPE_PATTERN,
89 G_PARAM_READWRITE);
90 g_object_class_install_property(gobject_class, PROP_PATTERN, param);
93 static void
94 adg_fill_style_init(AdgFillStyle *fill_style)
96 AdgFillStylePrivate *data = G_TYPE_INSTANCE_GET_PRIVATE(fill_style,
97 ADG_TYPE_FILL_STYLE,
98 AdgFillStylePrivate);
100 data->pattern = NULL;
102 fill_style->data = data;
105 static void
106 _adg_finalize(GObject *object)
108 AdgFillStylePrivate *data = ((AdgFillStyle *) object)->data;
110 if (data->pattern != NULL) {
111 cairo_pattern_destroy(data->pattern);
112 data->pattern = NULL;
116 static void
117 _adg_get_property(GObject *object, guint prop_id,
118 GValue *value, GParamSpec *pspec)
120 AdgFillStylePrivate *data = ((AdgFillStyle *) object)->data;
122 switch (prop_id) {
123 case PROP_PATTERN:
124 g_value_set_boxed(value, data->pattern);
125 break;
126 default:
127 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
128 break;
132 static void
133 _adg_set_property(GObject *object, guint prop_id,
134 const GValue *value, GParamSpec *pspec)
136 AdgFillStylePrivate *data = ((AdgFillStyle *) object)->data;
137 cairo_pattern_t *old_pattern;
139 switch (prop_id) {
140 case PROP_PATTERN:
141 old_pattern = data->pattern;
142 data->pattern = g_value_get_boxed(value);
144 if (data->pattern)
145 cairo_pattern_reference(data->pattern);
146 if (old_pattern)
147 cairo_pattern_destroy(old_pattern);
148 break;
149 default:
150 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
151 break;
157 * adg_fill_style_set_pattern:
158 * @fill_style: an #AdgFillStyle
159 * @pattern: the new pattern
161 * <note><para>
162 * This function is only useful in new fill implementations.
163 * </para></note>
165 * Sets a new pattern on @fill_style. A new reference is added to
166 * @pattern with cairo_pattern_reference() and the old pattern
167 * (if any) is unreferenced with cairo_pattern_destroy().
169 void
170 adg_fill_style_set_pattern(AdgFillStyle *fill_style, AdgPattern *pattern)
172 g_return_if_fail(ADG_IS_FILL_STYLE(fill_style));
173 g_object_set(fill_style, "pattern", pattern, NULL);
177 * adg_fill_style_get_pattern:
178 * @fill_style: an #AdgFillStyle
180 * Gets the current pattern binded to @fill_style.
182 * Returns: the current pattern
184 AdgPattern *
185 adg_fill_style_get_pattern(AdgFillStyle *fill_style)
187 AdgFillStylePrivate *data;
189 g_return_val_if_fail(ADG_IS_FILL_STYLE(fill_style), NULL);
191 data = fill_style->data;
193 return data->pattern;
197 * adg_fill_style_set_extents:
198 * @fill_style: an #AdgFillStyle
199 * @extents: the new extents
201 * <note><para>
202 * This function is only useful in new fill style implementations.
203 * </para></note>
205 * Forcibly sets new extents on @fill_style. Any fill style class
206 * that want to make some kind of customization can override the
207 * set_extents() virtual method to intercept any extents change.
209 * Sets new extents on @fill_style. These extents are usually set
210 * by the arrange() method of the entity using this filling style.
211 * The default implementation simply sets the extents, so the
212 * last one has precedence. Any fill style implementation can
213 * override the set_extents() implementation to customize this
214 * behavior, for example to keep the greatest boundary box instead
215 * of the last one.
217 void
218 adg_fill_style_set_extents(AdgFillStyle *fill_style,
219 const CpmlExtents *extents)
221 AdgFillStyleClass *klass;
223 g_return_if_fail(ADG_IS_FILL_STYLE(fill_style));
224 g_return_if_fail(extents != NULL);
226 klass = ADG_FILL_STYLE_GET_CLASS(fill_style);
228 if (klass->set_extents)
229 klass->set_extents(fill_style, extents);
233 * adg_fill_style_get_extents:
234 * @fill_style: an #AdgFillStyle
235 * @extents: where to store the extents
237 * Stores a copy of the extents of @fill_style in @extents.
238 * This struct specifies the maximum portion (in global space)
239 * this fill style should be applied: it will clamped by the
240 * entities as needed.
242 * Returns: the extents of @fill_style or %NULL on errors
244 const CpmlExtents *
245 adg_fill_style_get_extents(AdgFillStyle *fill_style)
247 AdgFillStylePrivate *data;
249 g_return_val_if_fail(ADG_IS_FILL_STYLE(fill_style), NULL);
251 data = fill_style->data;
253 return &data->extents;
257 static void
258 _adg_apply(AdgStyle *style, AdgEntity *entity, cairo_t *cr)
260 AdgFillStylePrivate *data = ((AdgFillStyle *) style)->data;
262 if (data->pattern == NULL)
263 g_warning(_("%s: pattern undefined for type `%s'"),
264 G_STRLOC, g_type_name(G_OBJECT_TYPE(style)));
265 else
266 cairo_set_source(cr, data->pattern);
269 static void
270 _adg_set_extents(AdgFillStyle *fill_style, const CpmlExtents *extents)
272 AdgFillStylePrivate *data = fill_style->data;
274 cpml_extents_copy(&data->extents, extents);