[AdgLogo] Redesigned logo to better fit a cell
[adg.git] / adg / adg-logo.c
blobfa7e35a498634cfd4bc28e24110e34e914498618
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.
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-logo.h"
37 #include "adg-logo-private.h"
38 #include "adg-line-style.h"
39 #include "adg-dress-builtins.h"
40 #include "adg-intl.h"
42 #define PARENT_OBJECT_CLASS ((GObjectClass *) adg_logo_parent_class)
45 enum {
46 PROP_0,
47 PROP_SYMBOL_DRESS,
48 PROP_SCREEN_DRESS,
49 PROP_FRAME_DRESS
53 static void get_property (GObject *object,
54 guint param_id,
55 GValue *value,
56 GParamSpec *pspec);
57 static void set_property (GObject *object,
58 guint param_id,
59 const GValue *value,
60 GParamSpec *pspec);
61 static void arrange (AdgEntity *entity);
62 static void render (AdgEntity *entity,
63 cairo_t *cr);
64 static void arrange_class (AdgLogoClass *logo_class);
67 G_DEFINE_TYPE(AdgLogo, adg_logo, ADG_TYPE_ENTITY);
70 static void
71 adg_logo_class_init(AdgLogoClass *klass)
73 GObjectClass *gobject_class;
74 AdgEntityClass *entity_class;
75 GParamSpec *param;
76 AdgLogoClassPrivate *data_class;
78 gobject_class = (GObjectClass *) klass;
79 entity_class = (AdgEntityClass *) klass;
81 g_type_class_add_private(klass, sizeof(AdgLogoPrivate));
83 gobject_class->get_property = get_property;
84 gobject_class->set_property = set_property;
86 entity_class->arrange = arrange;
87 entity_class->render = render;
89 param = adg_param_spec_dress("symbol-dress",
90 P_("Symbol Dress"),
91 P_("The line dress to use for rendering the symbol of the logo"),
92 ADG_DRESS_LINE,
93 G_PARAM_READWRITE);
94 g_object_class_install_property(gobject_class, PROP_SYMBOL_DRESS, param);
96 param = adg_param_spec_dress("screen-dress",
97 P_("Screen Dress"),
98 P_("The line dress to use for rendering the screen shape around the logo"),
99 ADG_DRESS_LINE,
100 G_PARAM_READWRITE);
101 g_object_class_install_property(gobject_class, PROP_SCREEN_DRESS, param);
103 param = adg_param_spec_dress("frame-dress",
104 P_("Frame Dress"),
105 P_("The line dress to use for rendering the frame"),
106 ADG_DRESS_LINE,
107 G_PARAM_READWRITE);
108 g_object_class_install_property(gobject_class, PROP_FRAME_DRESS, param);
110 /* Initialize the private class data: the allocated struct is
111 * never freed as this type is registered statically, hence
112 * never destroyed. A better approach would be to use the old
113 * type initialization (no G_TYPE_DEFINE and friends) that
114 * allows to specify a custom class finalization method */
115 data_class = g_new(AdgLogoClassPrivate, 1);
117 data_class->symbol = NULL;
118 data_class->screen = NULL;
119 data_class->frame = NULL;
120 data_class->extents.is_defined = FALSE;
122 klass->data_class = data_class;
125 static void
126 adg_logo_init(AdgLogo *logo)
128 AdgLogoPrivate *data = G_TYPE_INSTANCE_GET_PRIVATE(logo, ADG_TYPE_LOGO,
129 AdgLogoPrivate);
131 data->symbol_dress = ADG_DRESS_LINE;
132 data->screen_dress = ADG_DRESS_LINE;
133 data->frame_dress = ADG_DRESS_LINE;
135 logo->data = data;
138 static void
139 get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
141 AdgLogoPrivate *data = ((AdgLogo *) object)->data;
143 switch (prop_id) {
144 case PROP_SYMBOL_DRESS:
145 g_value_set_int(value, data->symbol_dress);
146 break;
147 case PROP_SCREEN_DRESS:
148 g_value_set_int(value, data->screen_dress);
149 break;
150 case PROP_FRAME_DRESS:
151 g_value_set_int(value, data->frame_dress);
152 break;
153 default:
154 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
155 break;
159 static void
160 set_property(GObject *object, guint prop_id,
161 const GValue *value, GParamSpec *pspec)
163 AdgLogo *logo;
164 AdgLogoPrivate *data;
166 logo = (AdgLogo *) object;
167 data = logo->data;
169 switch (prop_id) {
170 case PROP_SYMBOL_DRESS:
171 adg_dress_set(&data->symbol_dress, g_value_get_int(value));
172 break;
173 case PROP_SCREEN_DRESS:
174 adg_dress_set(&data->screen_dress, g_value_get_int(value));
175 break;
176 case PROP_FRAME_DRESS:
177 adg_dress_set(&data->frame_dress, g_value_get_int(value));
178 break;
179 default:
180 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
181 break;
187 * adg_logo_new:
189 * Creates a new logo entity. The #AdgEntity:local-method
190 * property is set by default to #ADG_MIX_DISABLED, that is the
191 * logo is not subject to any local transformations.
193 * Returns: the newly created logo entity
195 AdgLogo *
196 adg_logo_new(void)
198 return g_object_new(ADG_TYPE_LOGO,
199 "local-method", ADG_MIX_DISABLED, NULL);
203 * adg_logo_get_symbol_dress:
204 * @logo: an #AdgLogo
206 * Gets the line dress to be used in stroking the symbol of @logo.
208 * Returns: the requested line dress
210 AdgDress
211 adg_logo_get_symbol_dress(AdgLogo *logo)
213 AdgLogoPrivate *data;
215 g_return_val_if_fail(ADG_IS_LOGO(logo), ADG_DRESS_UNDEFINED);
217 data = logo->data;
219 return data->symbol_dress;
223 * adg_logo_set_symbol_dress:
224 * @logo: an #AdgLogo
225 * @dress: the new #AdgDress to use
227 * Sets a new line dress for rendering the symbol of @logo. The
228 * new dress must be a line dress: the check is done by calling
229 * adg_dress_are_related() with @dress and the old dress as
230 * arguments. Check out its documentation for further details.
232 * The default dress is a transparent line dress: the rendering
233 * callback will stroke the symbol using the default color with
234 * a predefined thickness.
236 void
237 adg_logo_set_symbol_dress(AdgLogo *logo, AdgDress dress)
239 AdgLogoPrivate *data;
241 g_return_if_fail(ADG_IS_LOGO(logo));
243 data = logo->data;
245 if (adg_dress_set(&data->symbol_dress, dress))
246 g_object_notify((GObject *) logo, "symbol-dress");
250 * adg_logo_get_screen_dress:
251 * @logo: an #AdgLogo
253 * Gets the line dress to be used in stroking the screen shape of @logo.
255 * Returns: the requested line dress
257 AdgDress
258 adg_logo_get_screen_dress(AdgLogo *logo)
260 AdgLogoPrivate *data;
262 g_return_val_if_fail(ADG_IS_LOGO(logo), ADG_DRESS_UNDEFINED);
264 data = logo->data;
266 return data->screen_dress;
270 * adg_logo_set_screen_dress:
271 * @logo: an #AdgLogo
272 * @dress: the new #AdgDress to use
274 * Sets a new line dress for rendering the screen of @logo.
275 * The new dress must be a line dress: the check is done by
276 * calling adg_dress_are_related() with @dress and the old
277 * dress as arguments. Check out its documentation for
278 * further details.
280 * The default dress is a transparent line dress: the rendering
281 * callback will stroke the screen using the default color with
282 * a predefined thickness.
284 void
285 adg_logo_set_screen_dress(AdgLogo *logo, AdgDress dress)
287 AdgLogoPrivate *data;
289 g_return_if_fail(ADG_IS_LOGO(logo));
291 data = logo->data;
293 if (adg_dress_set(&data->screen_dress, dress))
294 g_object_notify((GObject *) logo, "screen-dress");
298 * adg_logo_get_frame_dress:
299 * @logo: an #AdgLogo
301 * Gets the line dress to be used in stroking the frame of @logo.
303 * Returns: the requested line dress
305 AdgDress
306 adg_logo_get_frame_dress(AdgLogo *logo)
308 AdgLogoPrivate *data;
310 g_return_val_if_fail(ADG_IS_LOGO(logo), ADG_DRESS_UNDEFINED);
312 data = logo->data;
314 return data->frame_dress;
318 * adg_logo_set_frame_dress:
319 * @logo: an #AdgLogo
320 * @dress: the new #AdgDress to use
322 * Sets a new line dress for rendering the frame of @logo.
323 * The new dress must be a line dress: the check is done by
324 * calling adg_dress_are_related() with @dress and the old
325 * dress as arguments. Check out its documentation for
326 * further details.
328 * The default dress is a transparent line dress: the rendering
329 * callback will stroke the frame using the default color with
330 * a predefined thickness.
332 void
333 adg_logo_set_frame_dress(AdgLogo *logo, AdgDress dress)
335 AdgLogoPrivate *data;
337 g_return_if_fail(ADG_IS_LOGO(logo));
339 data = logo->data;
341 if (adg_dress_set(&data->frame_dress, dress))
342 g_object_notify((GObject *) logo, "frame-dress");
346 static void
347 arrange(AdgEntity *entity)
349 AdgLogoClass *logo_class;
350 AdgLogoClassPrivate *data_class;
351 CpmlExtents *extents;
352 const AdgMatrix *local;
354 logo_class = ADG_LOGO_GET_CLASS(entity);
355 data_class = logo_class->data_class;
356 extents = (CpmlExtents *) adg_entity_extents(entity);
357 local = adg_entity_local_matrix(entity);
359 arrange_class(logo_class);
360 cpml_extents_copy(extents, &data_class->extents);
362 /* Apply the local matrix to the extents of this logo instance */
363 cpml_pair_transform(&extents->org, local);
364 cpml_vector_transform(&extents->size, local);
367 static void
368 arrange_class(AdgLogoClass *logo_class)
370 AdgLogoClassPrivate *data_class;
371 CpmlExtents *extents;
373 data_class = logo_class->data_class;
374 extents = &data_class->extents;
376 if (data_class->symbol == NULL) {
377 AdgPath *path = adg_path_new();
379 adg_path_move_to_explicit(path, 3, -5);
380 adg_path_line_to_explicit(path, 11, -13);
381 adg_path_arc_to_explicit(path, 15, -9, 11, -5);
382 adg_path_line_to_explicit(path, 11, -12.5);
384 adg_path_move_to_explicit(path, 19, -13);
385 adg_path_arc_to_explicit(path, 15, -9, 19, -5);
386 adg_path_line_to_explicit(path, 19, -7);
387 adg_path_line_to_explicit(path, 18, -7);
389 adg_path_move_to_explicit(path, 10.5, -7);
390 adg_path_line_to_explicit(path, 7, -7);
392 data_class->symbol = path;
393 extents->is_defined = FALSE;
396 if (data_class->screen == NULL) {
397 AdgPath *path = adg_path_new();
399 adg_path_move_to_explicit(path, 2, -2);
400 adg_path_line_to_explicit(path, 23, -2);
401 adg_path_fillet(path, 5);
402 adg_path_line_to_explicit(path, 23, -16);
403 adg_path_fillet(path, 5);
404 adg_path_line_to_explicit(path, 2, -16);
405 adg_path_fillet(path, 5);
406 adg_path_close(path);
407 adg_path_fillet(path, 5);
409 data_class->screen = path;
410 extents->is_defined = FALSE;
413 if (data_class->frame == NULL) {
414 AdgPath *path = adg_path_new();
416 adg_path_move_to_explicit(path, 0, 0);
417 adg_path_line_to_explicit(path, 25, 0);
418 adg_path_line_to_explicit(path, 25, -18);
419 adg_path_line_to_explicit(path, 0, -18);
420 adg_path_close(path);
422 data_class->frame = path;
423 extents->is_defined = FALSE;
426 if (!data_class->extents.is_defined) {
427 cpml_extents_add(extents,
428 adg_trail_extents((AdgTrail *) data_class->symbol));
429 cpml_extents_add(extents,
430 adg_trail_extents((AdgTrail *) data_class->screen));
431 cpml_extents_add(extents,
432 adg_trail_extents((AdgTrail *) data_class->frame));
436 static void
437 render(AdgEntity *entity, cairo_t *cr)
439 AdgLogoClassPrivate *data_class;
440 AdgLogoPrivate *data;
441 const cairo_path_t *cairo_path;
443 data_class = ADG_LOGO_GET_CLASS(entity)->data_class;
444 data = ((AdgLogo *) entity)->data;
446 cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND);
448 cairo_path = adg_trail_get_cairo_path((AdgTrail *) data_class->symbol);
449 if (cairo_path != NULL) {
450 cairo_save(cr);
451 cairo_set_matrix(cr, adg_entity_ctm(entity));
452 cairo_append_path(cr, cairo_path);
453 cairo_restore(cr);
455 cairo_set_line_width(cr, 2.25);
456 adg_entity_apply_dress(entity, data->symbol_dress, cr);
458 cairo_stroke(cr);
461 cairo_path = adg_trail_get_cairo_path((AdgTrail *) data_class->screen);
462 if (cairo_path != NULL) {
463 cairo_save(cr);
464 cairo_set_matrix(cr, adg_entity_ctm(entity));
465 cairo_append_path(cr, cairo_path);
466 cairo_restore(cr);
468 cairo_set_line_width(cr, 1.5);
469 adg_entity_apply_dress(entity, data->screen_dress, cr);
471 cairo_stroke(cr);
474 cairo_path = adg_trail_get_cairo_path((AdgTrail *) data_class->frame);
475 if (cairo_path != NULL) {
476 cairo_save(cr);
477 cairo_set_matrix(cr, adg_entity_ctm(entity));
478 cairo_append_path(cr, cairo_path);
479 cairo_restore(cr);
481 cairo_set_line_width(cr, 1.5);
482 adg_entity_apply_dress(entity, data->frame_dress, cr);
484 cairo_stroke(cr);