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.
23 * @short_description: The ADG default logo
25 * The #AdgLogo is an entity representing the default ADG logo.
31 * All fields are private and should not be used directly.
32 * Use its public methods instead.
37 #include "adg-logo-private.h"
38 #include "adg-line-style.h"
39 #include "adg-dress-builtins.h"
42 #define PARENT_OBJECT_CLASS ((GObjectClass *) adg_logo_parent_class)
53 static void get_property (GObject
*object
,
57 static void set_property (GObject
*object
,
61 static void arrange (AdgEntity
*entity
);
62 static void render (AdgEntity
*entity
,
64 static void arrange_class (AdgLogoClass
*logo_class
);
67 G_DEFINE_TYPE(AdgLogo
, adg_logo
, ADG_TYPE_ENTITY
);
71 adg_logo_class_init(AdgLogoClass
*klass
)
73 GObjectClass
*gobject_class
;
74 AdgEntityClass
*entity_class
;
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",
91 P_("The line dress to use for rendering the symbol of the logo"),
94 g_object_class_install_property(gobject_class
, PROP_SYMBOL_DRESS
, param
);
96 param
= adg_param_spec_dress("screen-dress",
98 P_("The line dress to use for rendering the screen shape around the logo"),
101 g_object_class_install_property(gobject_class
, PROP_SCREEN_DRESS
, param
);
103 param
= adg_param_spec_dress("frame-dress",
105 P_("The line dress to use for rendering the frame"),
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
;
126 adg_logo_init(AdgLogo
*logo
)
128 AdgLogoPrivate
*data
= G_TYPE_INSTANCE_GET_PRIVATE(logo
, ADG_TYPE_LOGO
,
131 data
->symbol_dress
= ADG_DRESS_LINE
;
132 data
->screen_dress
= ADG_DRESS_LINE
;
133 data
->frame_dress
= ADG_DRESS_LINE
;
139 get_property(GObject
*object
, guint prop_id
, GValue
*value
, GParamSpec
*pspec
)
141 AdgLogoPrivate
*data
= ((AdgLogo
*) object
)->data
;
144 case PROP_SYMBOL_DRESS
:
145 g_value_set_int(value
, data
->symbol_dress
);
147 case PROP_SCREEN_DRESS
:
148 g_value_set_int(value
, data
->screen_dress
);
150 case PROP_FRAME_DRESS
:
151 g_value_set_int(value
, data
->frame_dress
);
154 G_OBJECT_WARN_INVALID_PROPERTY_ID(object
, prop_id
, pspec
);
160 set_property(GObject
*object
, guint prop_id
,
161 const GValue
*value
, GParamSpec
*pspec
)
164 AdgLogoPrivate
*data
;
166 logo
= (AdgLogo
*) object
;
170 case PROP_SYMBOL_DRESS
:
171 adg_dress_set(&data
->symbol_dress
, g_value_get_int(value
));
173 case PROP_SCREEN_DRESS
:
174 adg_dress_set(&data
->screen_dress
, g_value_get_int(value
));
176 case PROP_FRAME_DRESS
:
177 adg_dress_set(&data
->frame_dress
, g_value_get_int(value
));
180 G_OBJECT_WARN_INVALID_PROPERTY_ID(object
, prop_id
, pspec
);
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
198 return g_object_new(ADG_TYPE_LOGO
,
199 "local-method", ADG_MIX_DISABLED
, NULL
);
203 * adg_logo_get_symbol_dress:
206 * Gets the line dress to be used in stroking the symbol of @logo.
208 * Returns: the requested line dress
211 adg_logo_get_symbol_dress(AdgLogo
*logo
)
213 AdgLogoPrivate
*data
;
215 g_return_val_if_fail(ADG_IS_LOGO(logo
), ADG_DRESS_UNDEFINED
);
219 return data
->symbol_dress
;
223 * adg_logo_set_symbol_dress:
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.
237 adg_logo_set_symbol_dress(AdgLogo
*logo
, AdgDress dress
)
239 AdgLogoPrivate
*data
;
241 g_return_if_fail(ADG_IS_LOGO(logo
));
245 if (adg_dress_set(&data
->symbol_dress
, dress
))
246 g_object_notify((GObject
*) logo
, "symbol-dress");
250 * adg_logo_get_screen_dress:
253 * Gets the line dress to be used in stroking the screen shape of @logo.
255 * Returns: the requested line dress
258 adg_logo_get_screen_dress(AdgLogo
*logo
)
260 AdgLogoPrivate
*data
;
262 g_return_val_if_fail(ADG_IS_LOGO(logo
), ADG_DRESS_UNDEFINED
);
266 return data
->screen_dress
;
270 * adg_logo_set_screen_dress:
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
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.
285 adg_logo_set_screen_dress(AdgLogo
*logo
, AdgDress dress
)
287 AdgLogoPrivate
*data
;
289 g_return_if_fail(ADG_IS_LOGO(logo
));
293 if (adg_dress_set(&data
->screen_dress
, dress
))
294 g_object_notify((GObject
*) logo
, "screen-dress");
298 * adg_logo_get_frame_dress:
301 * Gets the line dress to be used in stroking the frame of @logo.
303 * Returns: the requested line dress
306 adg_logo_get_frame_dress(AdgLogo
*logo
)
308 AdgLogoPrivate
*data
;
310 g_return_val_if_fail(ADG_IS_LOGO(logo
), ADG_DRESS_UNDEFINED
);
314 return data
->frame_dress
;
318 * adg_logo_set_frame_dress:
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
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.
333 adg_logo_set_frame_dress(AdgLogo
*logo
, AdgDress dress
)
335 AdgLogoPrivate
*data
;
337 g_return_if_fail(ADG_IS_LOGO(logo
));
341 if (adg_dress_set(&data
->frame_dress
, dress
))
342 g_object_notify((GObject
*) logo
, "frame-dress");
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
);
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
));
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
) {
451 cairo_set_matrix(cr
, adg_entity_ctm(entity
));
452 cairo_append_path(cr
, cairo_path
);
455 cairo_set_line_width(cr
, 2.25);
456 adg_entity_apply_dress(entity
, data
->symbol_dress
, cr
);
461 cairo_path
= adg_trail_get_cairo_path((AdgTrail
*) data_class
->screen
);
462 if (cairo_path
!= NULL
) {
464 cairo_set_matrix(cr
, adg_entity_ctm(entity
));
465 cairo_append_path(cr
, cairo_path
);
468 cairo_set_line_width(cr
, 1.5);
469 adg_entity_apply_dress(entity
, data
->screen_dress
, cr
);
474 cairo_path
= adg_trail_get_cairo_path((AdgTrail
*) data_class
->frame
);
475 if (cairo_path
!= NULL
) {
477 cairo_set_matrix(cr
, adg_entity_ctm(entity
));
478 cairo_append_path(cr
, cairo_path
);
481 cairo_set_line_width(cr
, 1.5);
482 adg_entity_apply_dress(entity
, data
->frame_dress
, cr
);