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.
22 * SECTION:adg-fill-style
23 * @short_description: Generic pattern fill
25 * A style defining a generic fill based on cairo_pattern_t.
31 * All fields are private and should not be used directly.
32 * Use its public methods instead.
36 #include "adg-fill-style.h"
37 #include "adg-fill-style-private.h"
40 #define PARENT_STYLE_CLASS ((AdgStyleClass *) adg_fill_style_parent_class)
49 static void finalize (GObject
*object
);
50 static void get_property (GObject
*object
,
54 static void set_property (GObject
*object
,
58 static void apply (AdgStyle
*style
,
61 static gboolean
set_pattern (AdgFillStyle
*fill_style
,
63 static void set_extents (AdgFillStyle
*fill_style
,
64 const CpmlExtents
*extents
);
67 G_DEFINE_ABSTRACT_TYPE(AdgFillStyle
, adg_fill_style
, ADG_TYPE_STYLE
);
71 adg_fill_style_class_init(AdgFillStyleClass
*klass
)
73 GObjectClass
*gobject_class
;
74 AdgStyleClass
*style_class
;
77 gobject_class
= (GObjectClass
*) klass
;
78 style_class
= (AdgStyleClass
*) klass
;
80 g_type_class_add_private(klass
, sizeof(AdgFillStylePrivate
));
82 gobject_class
->finalize
= finalize
;
83 gobject_class
->get_property
= get_property
;
84 gobject_class
->set_property
= set_property
;
86 style_class
->apply
= apply
;
88 klass
->set_extents
= set_extents
;
90 param
= g_param_spec_boxed("pattern",
92 P_("The cairo pattern set for this entity"),
95 g_object_class_install_property(gobject_class
, PROP_PATTERN
, param
);
99 adg_fill_style_init(AdgFillStyle
*fill_style
)
101 AdgFillStylePrivate
*data
= G_TYPE_INSTANCE_GET_PRIVATE(fill_style
,
103 AdgFillStylePrivate
);
105 data
->pattern
= NULL
;
107 fill_style
->data
= data
;
111 finalize(GObject
*object
)
113 AdgFillStylePrivate
*data
= ((AdgFillStyle
*) object
)->data
;
115 if (data
->pattern
!= NULL
) {
116 cairo_pattern_destroy(data
->pattern
);
117 data
->pattern
= NULL
;
122 get_property(GObject
*object
,
123 guint prop_id
, GValue
*value
, GParamSpec
*pspec
)
125 AdgFillStylePrivate
*data
= ((AdgFillStyle
*) object
)->data
;
129 g_value_set_boxed(value
, data
->pattern
);
132 G_OBJECT_WARN_INVALID_PROPERTY_ID(object
, prop_id
, pspec
);
138 set_property(GObject
*object
,
139 guint prop_id
, const GValue
*value
, GParamSpec
*pspec
)
141 AdgFillStyle
*fill_style
= (AdgFillStyle
*) object
;
145 set_pattern(fill_style
, g_value_get_boxed(value
));
148 G_OBJECT_WARN_INVALID_PROPERTY_ID(object
, prop_id
, pspec
);
155 * adg_fill_style_get_pattern:
156 * @fill_style: an #AdgFillStyle
158 * Gets the current pattern binded to @fill_style.
160 * Returns: the current pattern
163 adg_fill_style_get_pattern(AdgFillStyle
*fill_style
)
165 AdgFillStylePrivate
*data
;
167 g_return_val_if_fail(ADG_IS_FILL_STYLE(fill_style
), NULL
);
169 data
= fill_style
->data
;
171 return data
->pattern
;
175 * adg_fill_style_set_pattern:
176 * @fill_style: an #AdgFillStyle
177 * @pattern: the new pattern
180 * This function is only useful in new fill implementations.
183 * Sets a new pattern on @fill_style. A new reference is added to
184 * @pattern with cairo_pattern_reference() and the old pattern
185 * (if any) is unreferenced with cairo_pattern_destroy().
188 adg_fill_style_set_pattern(AdgFillStyle
*fill_style
, AdgPattern
*pattern
)
190 g_return_if_fail(ADG_IS_FILL_STYLE(fill_style
));
192 if (set_pattern(fill_style
, pattern
))
193 g_object_notify((GObject
*) fill_style
, "pattern");
197 * adg_fill_style_get_extents:
198 * @fill_style: an #AdgFillStyle
199 * @extents: where to store the extents
201 * Stores a copy of the extents of @fill_style in @extents.
202 * This struct specifies the maximum portion (in global space)
203 * this fill style should be applied: it will clamped by the
204 * entities as needed.
206 * Returns: the extents of @fill_style or %NULL on errors
209 adg_fill_style_get_extents(AdgFillStyle
*fill_style
)
211 AdgFillStylePrivate
*data
;
213 g_return_val_if_fail(ADG_IS_FILL_STYLE(fill_style
), NULL
);
215 data
= fill_style
->data
;
217 return &data
->extents
;
221 * adg_fill_style_set_extents:
222 * @fill_style: an #AdgFillStyle
223 * @extents: the new extents
226 * This function is only useful in new fill style implementations.
229 * Forcibly sets new extents on @fill_style. Any fill style class
230 * that want to make some kind of customization can override the
231 * set_extents() virtual method to intercept any extents change.
233 * Sets new extents on @fill_style. These extents are usually set
234 * by the arrange() method of the entity using this filling style.
235 * The default implementation simply sets the extents, so the
236 * last one has precedence. Any fill style implementation can
237 * override the set_extents() implementation to customize this
238 * behavior, for example to keep the greatest boundary box instead
242 adg_fill_style_set_extents(AdgFillStyle
*fill_style
,
243 const CpmlExtents
*extents
)
245 AdgFillStyleClass
*klass
;
247 g_return_if_fail(ADG_IS_FILL_STYLE(fill_style
));
248 g_return_if_fail(extents
!= NULL
);
250 klass
= ADG_FILL_STYLE_GET_CLASS(fill_style
);
252 if (klass
->set_extents
)
253 klass
->set_extents(fill_style
, extents
);
258 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
)));
266 cairo_set_source(cr
, data
->pattern
);
270 set_pattern(AdgFillStyle
*fill_style
, AdgPattern
*pattern
)
272 AdgFillStylePrivate
*data
= fill_style
->data
;
274 if (pattern
== data
->pattern
)
277 if (data
->pattern
!= NULL
)
278 cairo_pattern_destroy(data
->pattern
);
280 data
->pattern
= pattern
;
282 if (data
->pattern
!= NULL
)
283 cairo_pattern_reference(data
->pattern
);
289 set_extents(AdgFillStyle
*fill_style
, const CpmlExtents
*extents
)
291 AdgFillStylePrivate
*data
= fill_style
->data
;
293 cpml_extents_copy(&data
->extents
, extents
);