[ADG] Avoid to forcibly set the CTM on the cr
[adg.git] / src / adg / adg-logo.c
blob9b6e77acb1cc8348fa403d68141780b50abb1dd4
1 /* ADG - Automatic Drawing Generation
2 * Copyright (C) 2007,2008,2009,2010 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-logo
23 * @short_description: The ADG default logo
25 * The #AdgLogo is an entity representing the default ADG logo.
26 **/
28 /**
29 * AdgLogo:
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-logo.h"
38 #include "adg-logo-private.h"
39 #include "adg-line-style.h"
40 #include "adg-dress-builtins.h"
43 G_DEFINE_TYPE(AdgLogo, adg_logo, ADG_TYPE_ENTITY);
45 enum {
46 PROP_0,
47 PROP_SYMBOL_DRESS,
48 PROP_SCREEN_DRESS,
49 PROP_FRAME_DRESS
53 static void _adg_get_property (GObject *object,
54 guint param_id,
55 GValue *value,
56 GParamSpec *pspec);
57 static void _adg_set_property (GObject *object,
58 guint param_id,
59 const GValue *value,
60 GParamSpec *pspec);
61 static void _adg_arrange (AdgEntity *entity);
62 static void _adg_render (AdgEntity *entity,
63 cairo_t *cr);
64 static void _adg_arrange_class (AdgLogoClass *logo_class);
67 static void
68 adg_logo_class_init(AdgLogoClass *klass)
70 GObjectClass *gobject_class;
71 AdgEntityClass *entity_class;
72 GParamSpec *param;
73 AdgLogoClassPrivate *data_class;
75 gobject_class = (GObjectClass *) klass;
76 entity_class = (AdgEntityClass *) klass;
78 g_type_class_add_private(klass, sizeof(AdgLogoPrivate));
80 gobject_class->get_property = _adg_get_property;
81 gobject_class->set_property = _adg_set_property;
83 entity_class->arrange = _adg_arrange;
84 entity_class->render = _adg_render;
86 param = adg_param_spec_dress("symbol-dress",
87 P_("Symbol Dress"),
88 P_("The line dress to use for rendering the symbol of the logo"),
89 ADG_DRESS_LINE,
90 G_PARAM_READWRITE);
91 g_object_class_install_property(gobject_class, PROP_SYMBOL_DRESS, param);
93 param = adg_param_spec_dress("screen-dress",
94 P_("Screen Dress"),
95 P_("The line dress to use for rendering the screen shape around the logo"),
96 ADG_DRESS_LINE,
97 G_PARAM_READWRITE);
98 g_object_class_install_property(gobject_class, PROP_SCREEN_DRESS, param);
100 param = adg_param_spec_dress("frame-dress",
101 P_("Frame Dress"),
102 P_("The line dress to use for rendering the frame"),
103 ADG_DRESS_LINE,
104 G_PARAM_READWRITE);
105 g_object_class_install_property(gobject_class, PROP_FRAME_DRESS, param);
107 /* Initialize the private class data: the allocated struct is
108 * never freed as this type is registered statically, hence
109 * never destroyed. A better approach would be to use the old
110 * type initialization (no G_TYPE_DEFINE and friends) that
111 * allows to specify a custom class finalization method */
112 data_class = g_new(AdgLogoClassPrivate, 1);
114 data_class->symbol = NULL;
115 data_class->screen = NULL;
116 data_class->frame = NULL;
117 data_class->extents.is_defined = FALSE;
119 klass->data_class = data_class;
122 static void
123 adg_logo_init(AdgLogo *logo)
125 AdgLogoPrivate *data = G_TYPE_INSTANCE_GET_PRIVATE(logo, ADG_TYPE_LOGO,
126 AdgLogoPrivate);
128 data->symbol_dress = ADG_DRESS_LINE;
129 data->screen_dress = ADG_DRESS_LINE;
130 data->frame_dress = ADG_DRESS_LINE;
132 logo->data = data;
135 static void
136 _adg_get_property(GObject *object, guint prop_id,
137 GValue *value, GParamSpec *pspec)
139 AdgLogoPrivate *data = ((AdgLogo *) object)->data;
141 switch (prop_id) {
142 case PROP_SYMBOL_DRESS:
143 g_value_set_int(value, data->symbol_dress);
144 break;
145 case PROP_SCREEN_DRESS:
146 g_value_set_int(value, data->screen_dress);
147 break;
148 case PROP_FRAME_DRESS:
149 g_value_set_int(value, data->frame_dress);
150 break;
151 default:
152 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
153 break;
157 static void
158 _adg_set_property(GObject *object, guint prop_id,
159 const GValue *value, GParamSpec *pspec)
161 AdgLogo *logo;
162 AdgLogoPrivate *data;
164 logo = (AdgLogo *) object;
165 data = logo->data;
167 switch (prop_id) {
168 case PROP_SYMBOL_DRESS:
169 data->symbol_dress = g_value_get_int(value);
170 break;
171 case PROP_SCREEN_DRESS:
172 data->screen_dress = g_value_get_int(value);
173 break;
174 case PROP_FRAME_DRESS:
175 data->frame_dress = g_value_get_int(value);
176 break;
177 default:
178 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
179 break;
185 * adg_logo_new:
187 * Creates a new logo entity.
189 * Returns: the newly created logo entity
191 AdgLogo *
192 adg_logo_new(void)
194 return g_object_new(ADG_TYPE_LOGO, NULL);
198 * adg_logo_set_symbol_dress:
199 * @logo: an #AdgLogo
200 * @dress: the new #AdgDress to use
202 * Sets a new line dress for rendering the symbol of @logo. The
203 * new dress must be a line dress: the check is done by calling
204 * adg_dress_are_related() with @dress and the old dress as
205 * arguments. Check out its documentation for further details.
207 * The default dress is a transparent line dress: the rendering
208 * callback will stroke the symbol using the default color with
209 * a predefined thickness.
211 void
212 adg_logo_set_symbol_dress(AdgLogo *logo, AdgDress dress)
214 g_return_if_fail(ADG_IS_LOGO(logo));
215 g_object_set((GObject *) logo, "symbol-dress", dress, NULL);
219 * adg_logo_get_symbol_dress:
220 * @logo: an #AdgLogo
222 * Gets the line dress to be used in stroking the symbol of @logo.
224 * Returns: the requested line dress
226 AdgDress
227 adg_logo_get_symbol_dress(AdgLogo *logo)
229 AdgLogoPrivate *data;
231 g_return_val_if_fail(ADG_IS_LOGO(logo), ADG_DRESS_UNDEFINED);
233 data = logo->data;
235 return data->symbol_dress;
239 * adg_logo_set_screen_dress:
240 * @logo: an #AdgLogo
241 * @dress: the new #AdgDress to use
243 * Sets a new line dress for rendering the screen of @logo.
244 * The new dress must be a line dress: the check is done by
245 * calling adg_dress_are_related() with @dress and the old
246 * dress as arguments. Check out its documentation for
247 * further details.
249 * The default dress is a transparent line dress: the rendering
250 * callback will stroke the screen using the default color with
251 * a predefined thickness.
253 void
254 adg_logo_set_screen_dress(AdgLogo *logo, AdgDress dress)
256 g_return_if_fail(ADG_IS_LOGO(logo));
257 g_object_set((GObject *) logo, "screen-dress", dress, NULL);
261 * adg_logo_get_screen_dress:
262 * @logo: an #AdgLogo
264 * Gets the line dress to be used in stroking the screen shape of @logo.
266 * Returns: the requested line dress
268 AdgDress
269 adg_logo_get_screen_dress(AdgLogo *logo)
271 AdgLogoPrivate *data;
273 g_return_val_if_fail(ADG_IS_LOGO(logo), ADG_DRESS_UNDEFINED);
275 data = logo->data;
277 return data->screen_dress;
281 * adg_logo_set_frame_dress:
282 * @logo: an #AdgLogo
283 * @dress: the new #AdgDress to use
285 * Sets a new line dress for rendering the frame of @logo.
286 * The new dress must be a line dress: the check is done by
287 * calling adg_dress_are_related() with @dress and the old
288 * dress as arguments. Check out its documentation for
289 * further details.
291 * The default dress is a transparent line dress: the rendering
292 * callback will stroke the frame using the default color with
293 * a predefined thickness.
295 void
296 adg_logo_set_frame_dress(AdgLogo *logo, AdgDress dress)
298 g_return_if_fail(ADG_IS_LOGO(logo));
299 g_object_set((GObject *) logo, "frame-dress", dress, NULL);
303 * adg_logo_get_frame_dress:
304 * @logo: an #AdgLogo
306 * Gets the line dress to be used in stroking the frame of @logo.
308 * Returns: the requested line dress
310 AdgDress
311 adg_logo_get_frame_dress(AdgLogo *logo)
313 AdgLogoPrivate *data;
315 g_return_val_if_fail(ADG_IS_LOGO(logo), ADG_DRESS_UNDEFINED);
317 data = logo->data;
319 return data->frame_dress;
323 static void
324 _adg_arrange(AdgEntity *entity)
326 AdgLogoClass *logo_class;
327 AdgLogoClassPrivate *data_class;
328 CpmlExtents extents;
330 logo_class = ADG_LOGO_GET_CLASS(entity);
331 data_class = logo_class->data_class;
333 _adg_arrange_class(logo_class);
334 cpml_extents_copy(&extents, &data_class->extents);
336 cpml_extents_transform(&extents, adg_entity_get_local_matrix(entity));
337 cpml_extents_transform(&extents, adg_entity_get_global_matrix(entity));
338 adg_entity_set_extents(entity, &extents);
341 static void
342 _adg_arrange_class(AdgLogoClass *logo_class)
344 AdgLogoClassPrivate *data_class;
345 CpmlExtents *extents;
347 data_class = logo_class->data_class;
348 extents = &data_class->extents;
350 if (data_class->symbol == NULL) {
351 AdgPath *path = adg_path_new();
353 adg_path_move_to_explicit(path, 8, 26);
354 adg_path_line_to_explicit(path, 24, 10);
355 adg_path_arc_to_explicit(path, 32, 18, 24, 26);
356 adg_path_line_to_explicit(path, 24, 11);
358 adg_path_move_to_explicit(path, 40, 10);
359 adg_path_arc_to_explicit(path, 32, 18, 40, 26);
360 adg_path_line_to_explicit(path, 40, 22);
361 adg_path_line_to_explicit(path, 38, 22);
363 adg_path_move_to_explicit(path, 23, 22);
364 adg_path_line_to_explicit(path, 16, 22);
366 data_class->symbol = path;
367 extents->is_defined = FALSE;
370 if (data_class->screen == NULL) {
371 AdgPath *path = adg_path_new();
373 adg_path_move_to_explicit(path, 3, 3);
374 adg_path_line_to_explicit(path, 47, 3);
375 adg_path_fillet(path, 10);
376 adg_path_line_to_explicit(path, 47, 33);
377 adg_path_fillet(path, 10);
378 adg_path_line_to_explicit(path, 3, 33);
379 adg_path_fillet(path, 10);
380 adg_path_close(path);
381 adg_path_fillet(path, 10);
383 data_class->screen = path;
384 extents->is_defined = FALSE;
387 if (data_class->frame == NULL) {
388 AdgPath *path = adg_path_new();
390 adg_path_move_to_explicit(path, 0, 0);
391 adg_path_line_to_explicit(path, 50, 0);
392 adg_path_line_to_explicit(path, 50, 36);
393 adg_path_line_to_explicit(path, 0, 36);
394 adg_path_close(path);
396 data_class->frame = path;
397 extents->is_defined = FALSE;
400 if (!data_class->extents.is_defined) {
401 cpml_extents_add(extents,
402 adg_trail_get_extents((AdgTrail *) data_class->symbol));
403 cpml_extents_add(extents,
404 adg_trail_get_extents((AdgTrail *) data_class->screen));
405 cpml_extents_add(extents,
406 adg_trail_get_extents((AdgTrail *) data_class->frame));
410 static void
411 _adg_render(AdgEntity *entity, cairo_t *cr)
413 AdgLogoClassPrivate *data_class;
414 AdgLogoPrivate *data;
415 const cairo_path_t *cairo_path;
417 data_class = ADG_LOGO_GET_CLASS(entity)->data_class;
418 data = ((AdgLogo *) entity)->data;
420 cairo_transform(cr, adg_entity_get_global_matrix(entity));
421 cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND);
423 cairo_path = adg_trail_get_cairo_path((AdgTrail *) data_class->symbol);
424 if (cairo_path != NULL) {
425 cairo_save(cr);
426 cairo_transform(cr, adg_entity_get_local_matrix(entity));
427 cairo_append_path(cr, cairo_path);
428 cairo_restore(cr);
430 cairo_set_line_width(cr, 3);
431 adg_entity_apply_dress(entity, data->symbol_dress, cr);
433 cairo_stroke(cr);
436 cairo_path = adg_trail_get_cairo_path((AdgTrail *) data_class->screen);
437 if (cairo_path != NULL) {
438 cairo_save(cr);
439 cairo_transform(cr, adg_entity_get_local_matrix(entity));
440 cairo_append_path(cr, cairo_path);
441 cairo_restore(cr);
443 cairo_set_line_width(cr, 2);
444 adg_entity_apply_dress(entity, data->screen_dress, cr);
446 cairo_stroke(cr);
449 cairo_path = adg_trail_get_cairo_path((AdgTrail *) data_class->frame);
450 if (cairo_path != NULL) {
451 cairo_save(cr);
452 cairo_transform(cr, adg_entity_get_local_matrix(entity));
453 cairo_append_path(cr, cairo_path);
454 cairo_restore(cr);
456 cairo_set_line_width(cr, 2);
457 cairo_set_antialias(cr, CAIRO_ANTIALIAS_NONE);
458 adg_entity_apply_dress(entity, data->frame_dress, cr);
460 cairo_stroke(cr);