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.
22 * SECTION:adg-fill-style
23 * @short_description: Generic pattern fill
25 * A style defining a generic fill based on cairo_pattern_t.
33 * All fields are private and should not be used directly.
34 * Use its public methods instead.
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
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
)
71 static void _adg_finalize (GObject
*object
);
72 static void _adg_get_property (GObject
*object
,
76 static void _adg_set_property (GObject
*object
,
80 static void _adg_apply (AdgStyle
*style
,
83 static void _adg_set_extents (AdgFillStyle
*fill_style
,
84 const CpmlExtents
*extents
);
88 adg_fill_style_class_init(AdgFillStyleClass
*klass
)
90 GObjectClass
*gobject_class
;
91 AdgStyleClass
*style_class
;
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",
107 P_("The cairo pattern set for this entity"),
108 CAIRO_GOBJECT_TYPE_PATTERN
,
110 g_object_class_install_property(gobject_class
, PROP_PATTERN
, param
);
114 adg_fill_style_init(AdgFillStyle
*fill_style
)
116 AdgFillStylePrivate
*data
= adg_fill_style_get_instance_private(fill_style
);
117 data
->pattern
= NULL
;
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
;
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
);
139 g_value_set_boxed(value
, data
->pattern
);
142 G_OBJECT_WARN_INVALID_PROPERTY_ID(object
, prop_id
, pspec
);
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
;
156 old_pattern
= data
->pattern
;
157 data
->pattern
= g_value_get_boxed(value
);
160 cairo_pattern_reference(data
->pattern
);
162 cairo_pattern_destroy(old_pattern
);
165 G_OBJECT_WARN_INVALID_PROPERTY_ID(object
, prop_id
, pspec
);
172 * adg_fill_style_set_pattern:
173 * @fill_style: an #AdgFillStyle
174 * @pattern: the new pattern
177 * This function is only useful in new fill implementations.
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().
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
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
221 * This function is only useful in new fill style implementations.
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.
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.
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
;
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
)));
282 cairo_set_source(cr
, data
->pattern
);
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
);