doc: update copyright line for 2021
[adg.git] / src / adg / adg-fill-style.c
blob308e26eeb9752ec4bade8748ae2413633f997af0
1 /* ADG - Automatic Drawing Generation
2 * Copyright (C) 2007-2021 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 <function>set_extents</function> implementation simply sets
46 * the extents owned by the fill style instance to the one provided, so the
47 * last call has precedence. Any derived class can override it to customize
48 * this behavior, for example to keep the greatest boundary box instead of
49 * the last one.
51 * Since: 1.0
52 **/
55 #include "adg-internal.h"
56 #include "adg-style.h"
57 #include "adg-cairo-fallback.h"
59 #include "adg-fill-style.h"
60 #include "adg-fill-style-private.h"
63 G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE(AdgFillStyle, adg_fill_style, ADG_TYPE_STYLE)
65 enum {
66 PROP_0,
67 PROP_PATTERN
71 static void _adg_finalize (GObject *object);
72 static void _adg_get_property (GObject *object,
73 guint prop_id,
74 GValue *value,
75 GParamSpec *pspec);
76 static void _adg_set_property (GObject *object,
77 guint prop_id,
78 const GValue *value,
79 GParamSpec *pspec);
80 static void _adg_apply (AdgStyle *style,
81 AdgEntity *entity,
82 cairo_t *cr);
83 static void _adg_set_extents (AdgFillStyle *fill_style,
84 const CpmlExtents *extents);
87 static void
88 adg_fill_style_class_init(AdgFillStyleClass *klass)
90 GObjectClass *gobject_class;
91 AdgStyleClass *style_class;
92 GParamSpec *param;
94 gobject_class = (GObjectClass *) klass;
95 style_class = (AdgStyleClass *) klass;
97 gobject_class->finalize = _adg_finalize;
98 gobject_class->get_property = _adg_get_property;
99 gobject_class->set_property = _adg_set_property;
101 style_class->apply = _adg_apply;
103 klass->set_extents = _adg_set_extents;
105 param = g_param_spec_boxed("pattern",
106 P_("Pattern"),
107 P_("The cairo pattern set for this entity"),
108 CAIRO_GOBJECT_TYPE_PATTERN,
109 G_PARAM_READWRITE);
110 g_object_class_install_property(gobject_class, PROP_PATTERN, param);
113 static void
114 adg_fill_style_init(AdgFillStyle *fill_style)
116 AdgFillStylePrivate *data = adg_fill_style_get_instance_private(fill_style);
117 data->pattern = NULL;
120 static void
121 _adg_finalize(GObject *object)
123 AdgFillStylePrivate *data = adg_fill_style_get_instance_private((AdgFillStyle *) object);
125 if (data->pattern != NULL) {
126 cairo_pattern_destroy(data->pattern);
127 data->pattern = NULL;
131 static void
132 _adg_get_property(GObject *object, guint prop_id,
133 GValue *value, GParamSpec *pspec)
135 AdgFillStylePrivate *data = adg_fill_style_get_instance_private((AdgFillStyle *) object);
137 switch (prop_id) {
138 case PROP_PATTERN:
139 g_value_set_boxed(value, data->pattern);
140 break;
141 default:
142 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
143 break;
147 static void
148 _adg_set_property(GObject *object, guint prop_id,
149 const GValue *value, GParamSpec *pspec)
151 AdgFillStylePrivate *data = adg_fill_style_get_instance_private((AdgFillStyle *) object);
152 cairo_pattern_t *old_pattern;
154 switch (prop_id) {
155 case PROP_PATTERN:
156 old_pattern = data->pattern;
157 data->pattern = g_value_get_boxed(value);
159 if (data->pattern)
160 cairo_pattern_reference(data->pattern);
161 if (old_pattern)
162 cairo_pattern_destroy(old_pattern);
163 break;
164 default:
165 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
166 break;
172 * adg_fill_style_set_pattern:
173 * @fill_style: an #AdgFillStyle
174 * @pattern: the new pattern
176 * <note><para>
177 * This function is only useful in new fill implementations.
178 * </para></note>
180 * Sets a new pattern on @fill_style. A new reference is added to
181 * @pattern with cairo_pattern_reference() and the old pattern
182 * (if any) is unreferenced with cairo_pattern_destroy().
184 * Since: 1.0
186 void
187 adg_fill_style_set_pattern(AdgFillStyle *fill_style,
188 cairo_pattern_t *pattern)
190 g_return_if_fail(ADG_IS_FILL_STYLE(fill_style));
191 g_object_set(fill_style, "pattern", pattern, NULL);
195 * adg_fill_style_get_pattern:
196 * @fill_style: an #AdgFillStyle
198 * Gets the current pattern binded to @fill_style.
200 * Returns: (transfer none): the current pattern
202 * Since: 1.0
204 cairo_pattern_t *
205 adg_fill_style_get_pattern(AdgFillStyle *fill_style)
207 AdgFillStylePrivate *data;
209 g_return_val_if_fail(ADG_IS_FILL_STYLE(fill_style), NULL);
211 data = adg_fill_style_get_instance_private(fill_style);
212 return data->pattern;
216 * adg_fill_style_set_extents:
217 * @fill_style: an #AdgFillStyle
218 * @extents: the new extents
220 * <note><para>
221 * This function is only useful in new fill style implementations.
222 * </para></note>
224 * Forcibly sets new extents on @fill_style. Any fill style class
225 * that want to make some kind of customization can override the
226 * <function>set_extents</function> virtual method to intercept
227 * any extents change.
229 * Sets new extents on @fill_style. These extents are usually set
230 * by the arrange() method of the entity using this filling style.
232 * Since: 1.0
234 void
235 adg_fill_style_set_extents(AdgFillStyle *fill_style,
236 const CpmlExtents *extents)
238 AdgFillStyleClass *klass;
240 g_return_if_fail(ADG_IS_FILL_STYLE(fill_style));
241 g_return_if_fail(extents != NULL);
243 klass = ADG_FILL_STYLE_GET_CLASS(fill_style);
245 if (klass->set_extents)
246 klass->set_extents(fill_style, extents);
250 * adg_fill_style_get_extents:
251 * @fill_style: an #AdgFillStyle
253 * Stores a copy of the extents of @fill_style in @extents.
254 * This struct specifies the maximum portion (in global space)
255 * this fill style should be applied: it will clamped by the
256 * entities as needed.
258 * Returns: (transfer none): the extents of @fill_style or <constant>NULL</constant> on errors.
260 * Since: 1.0
262 const CpmlExtents *
263 adg_fill_style_get_extents(AdgFillStyle *fill_style)
265 AdgFillStylePrivate *data;
267 g_return_val_if_fail(ADG_IS_FILL_STYLE(fill_style), NULL);
269 data = adg_fill_style_get_instance_private(fill_style);
270 return &data->extents;
274 static void
275 _adg_apply(AdgStyle *style, AdgEntity *entity, cairo_t *cr)
277 AdgFillStylePrivate *data = adg_fill_style_get_instance_private((AdgFillStyle *) style);
278 if (data->pattern == NULL)
279 g_warning(_("%s: pattern undefined for type '%s'"),
280 G_STRLOC, g_type_name(G_OBJECT_TYPE(style)));
281 else
282 cairo_set_source(cr, data->pattern);
285 static void
286 _adg_set_extents(AdgFillStyle *fill_style, const CpmlExtents *extents)
288 AdgFillStylePrivate *data = adg_fill_style_get_instance_private(fill_style);
289 cpml_extents_copy(&data->extents, extents);