1 /* ADG - Automatic Drawing Generation
2 * Copyright (C) 2007,2008,2009,2010,2011 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-toy-text
23 * @short_description: Simple text entity that use the cairo "toy" text API
25 * The #AdgToyText class is a basic class to show simple text. It internally
26 * uses the so called cairo "toy" API and it shares the same limitations.
28 * The toy text entity is not subject to the local matrix, only its origin is.
34 * All fields are privates and should not be used directly.
35 * Use its public methods instead.
39 #include "adg-internal.h"
40 #include "adg-toy-text.h"
41 #include "adg-toy-text-private.h"
42 #include "adg-dress-builtins.h"
43 #include "adg-font-style.h"
45 #define _ADG_OLD_OBJECT_CLASS ((GObjectClass *) adg_toy_text_parent_class)
46 #define _ADG_OLD_ENTITY_CLASS ((AdgEntityClass *) adg_toy_text_parent_class)
49 G_DEFINE_TYPE(AdgToyText
, adg_toy_text
, ADG_TYPE_ENTITY
);
58 static void _adg_finalize (GObject
*object
);
59 static void _adg_get_property (GObject
*object
,
63 static void _adg_set_property (GObject
*object
,
67 static void _adg_global_changed (AdgEntity
*entity
);
68 static void _adg_local_changed (AdgEntity
*entity
);
69 static void _adg_invalidate (AdgEntity
*entity
);
70 static void _adg_arrange (AdgEntity
*entity
);
71 static void _adg_render (AdgEntity
*entity
,
73 static void _adg_clear_font (AdgToyText
*toy_text
);
74 static void _adg_clear_glyphs (AdgToyText
*toy_text
);
78 adg_toy_text_class_init(AdgToyTextClass
*klass
)
80 GObjectClass
*gobject_class
;
81 AdgEntityClass
*entity_class
;
84 gobject_class
= (GObjectClass
*) klass
;
85 entity_class
= (AdgEntityClass
*) klass
;
87 g_type_class_add_private(klass
, sizeof(AdgToyTextPrivate
));
89 gobject_class
->finalize
= _adg_finalize
;
90 gobject_class
->get_property
= _adg_get_property
;
91 gobject_class
->set_property
= _adg_set_property
;
93 entity_class
->global_changed
= _adg_global_changed
;
94 entity_class
->local_changed
= _adg_local_changed
;
95 entity_class
->invalidate
= _adg_invalidate
;
96 entity_class
->arrange
= _adg_arrange
;
97 entity_class
->render
= _adg_render
;
99 param
= adg_param_spec_dress("font-dress",
101 P_("The font dress to use for rendering this text"),
104 g_object_class_install_property(gobject_class
, PROP_FONT_DRESS
, param
);
106 param
= g_param_spec_string("label",
108 P_("The label to display"),
111 g_object_class_install_property(gobject_class
, PROP_LABEL
, param
);
115 adg_toy_text_init(AdgToyText
*toy_text
)
117 AdgToyTextPrivate
*data
= G_TYPE_INSTANCE_GET_PRIVATE(toy_text
,
121 data
->font_dress
= ADG_DRESS_FONT_TEXT
;
125 toy_text
->data
= data
;
129 _adg_finalize(GObject
*object
)
131 AdgToyText
*toy_text
;
132 AdgToyTextPrivate
*data
;
134 toy_text
= (AdgToyText
*) object
;
135 data
= toy_text
->data
;
138 _adg_clear_font(toy_text
);
139 _adg_clear_glyphs(toy_text
);
141 if (_ADG_OLD_OBJECT_CLASS
->finalize
)
142 _ADG_OLD_OBJECT_CLASS
->finalize(object
);
146 _adg_get_property(GObject
*object
, guint prop_id
,
147 GValue
*value
, GParamSpec
*pspec
)
149 AdgToyTextPrivate
*data
= ((AdgToyText
*) object
)->data
;
152 case PROP_FONT_DRESS
:
153 g_value_set_int(value
, data
->font_dress
);
156 g_value_set_string(value
, data
->label
);
159 G_OBJECT_WARN_INVALID_PROPERTY_ID(object
, prop_id
, pspec
);
165 _adg_set_property(GObject
*object
, guint prop_id
,
166 const GValue
*value
, GParamSpec
*pspec
)
168 AdgToyText
*toy_text
;
169 AdgToyTextPrivate
*data
;
171 toy_text
= (AdgToyText
*) object
;
172 data
= toy_text
->data
;
175 case PROP_FONT_DRESS
:
176 data
->font_dress
= g_value_get_int(value
);
177 _adg_clear_font(toy_text
);
181 data
->label
= g_value_dup_string(value
);
182 _adg_clear_glyphs(toy_text
);
185 G_OBJECT_WARN_INVALID_PROPERTY_ID(object
, prop_id
, pspec
);
193 * @label: the label text
195 * Creates a new toy text entity using @label as its text. The
196 * #AdgEntity:local-method property is set by default to
197 * #ADG_LOCAL_NORMALIZED.
199 * Returns: the newly created toy text entity
202 adg_toy_text_new(const gchar
*label
)
204 return g_object_new(ADG_TYPE_TOY_TEXT
,
205 "local-method", ADG_MIX_ANCESTORS_NORMALIZED
,
206 "label", label
, NULL
);
210 * adg_toy_text_set_font_dress:
211 * @toy_text: an #AdgToyText
212 * @dress: the new #AdgDress to use
214 * Sets a new font dress for rendering @toy_text. The new dress
215 * must be related to the original dress for this property:
216 * you cannot set a dress used for line styles to a dress
219 * The check is done by calling adg_dress_are_related() with
220 * @dress and the previous dress as arguments. Check out its
221 * documentation for details on what is a related dress.
224 adg_toy_text_set_font_dress(AdgToyText
*toy_text
, AdgDress dress
)
226 g_return_if_fail(ADG_IS_TOY_TEXT(toy_text
));
227 g_object_set(toy_text
, "font-dress", dress
, NULL
);
231 * adg_toy_text_get_font_dress:
232 * @toy_text: an #AdgToyText
234 * Gets the font dress to be used in rendering @toy_text.
236 * Returns: the current font dress
239 adg_toy_text_get_font_dress(AdgToyText
*toy_text
)
241 AdgToyTextPrivate
*data
;
243 g_return_val_if_fail(ADG_IS_TOY_TEXT(toy_text
), ADG_DRESS_UNDEFINED
);
245 data
= toy_text
->data
;
247 return data
->font_dress
;
251 * adg_toy_text_set_label:
252 * @toy_text: an #AdgToyText
253 * @label: the label text
255 * Sets a new label for @toy_text. @label can be also %NULL,
256 * in which case will be treated as an empty string.
259 adg_toy_text_set_label(AdgToyText
*toy_text
, const gchar
*label
)
261 g_return_if_fail(ADG_IS_TOY_TEXT(toy_text
));
262 g_object_set(toy_text
, "label", label
, NULL
);
266 * adg_toy_text_get_label:
267 * @toy_text: an #AdgToyText
269 * Gets the label text. The string is internally owned and
270 * must not be freed or modified.
272 * Returns: the label text
275 adg_toy_text_get_label(AdgToyText
*toy_text
)
277 AdgToyTextPrivate
*data
;
279 g_return_val_if_fail(ADG_IS_TOY_TEXT(toy_text
), NULL
);
281 data
= toy_text
->data
;
288 _adg_global_changed(AdgEntity
*entity
)
290 if (_ADG_OLD_ENTITY_CLASS
->global_changed
)
291 _ADG_OLD_ENTITY_CLASS
->global_changed(entity
);
293 adg_entity_invalidate(entity
);
297 _adg_local_changed(AdgEntity
*entity
)
299 if (_ADG_OLD_ENTITY_CLASS
->local_changed
)
300 _ADG_OLD_ENTITY_CLASS
->local_changed(entity
);
302 adg_entity_invalidate(entity
);
306 _adg_invalidate(AdgEntity
*entity
)
308 _adg_clear_font((AdgToyText
*) entity
);
309 _adg_clear_glyphs((AdgToyText
*) entity
);
311 if (_ADG_OLD_ENTITY_CLASS
->invalidate
)
312 _ADG_OLD_ENTITY_CLASS
->invalidate(entity
);
316 _adg_arrange(AdgEntity
*entity
)
318 AdgToyText
*toy_text
;
319 AdgToyTextPrivate
*data
;
322 toy_text
= (AdgToyText
*) entity
;
323 data
= toy_text
->data
;
325 if (data
->font
== NULL
) {
327 AdgFontStyle
*font_style
;
330 dress
= data
->font_dress
;
331 font_style
= (AdgFontStyle
*) adg_entity_style(entity
, dress
);
333 adg_matrix_copy(&ctm
, adg_entity_get_global_matrix(entity
));
334 adg_matrix_transform(&ctm
, adg_entity_get_local_matrix(entity
),
335 ADG_TRANSFORM_BEFORE
);
337 data
->font
= adg_font_style_get_scaled_font(font_style
, &ctm
);
340 if (adg_is_string_empty(data
->label
)) {
341 /* Undefined label */
342 extents
.is_defined
= FALSE
;
343 } else if (data
->glyphs
!= NULL
) {
347 cairo_status_t status
;
348 cairo_text_extents_t cairo_extents
;
350 status
= cairo_scaled_font_text_to_glyphs(data
->font
, 0, 0,
356 if (status
!= CAIRO_STATUS_SUCCESS
) {
357 _adg_clear_glyphs(toy_text
);
358 g_error(_("Unable to build glyphs (cairo message: %s)"),
359 cairo_status_to_string(status
));
363 cairo_scaled_font_glyph_extents(data
->font
, data
->glyphs
,
364 data
->num_glyphs
, &cairo_extents
);
365 cpml_extents_from_cairo_text(&extents
, &cairo_extents
);
366 cpml_extents_transform(&extents
, adg_entity_get_local_matrix(entity
));
367 cpml_extents_transform(&extents
, adg_entity_get_global_matrix(entity
));
371 adg_entity_set_extents(entity
, &extents
);
375 _adg_render(AdgEntity
*entity
, cairo_t
*cr
)
377 AdgToyText
*toy_text
;
378 AdgToyTextPrivate
*data
;
380 toy_text
= (AdgToyText
*) entity
;
381 data
= toy_text
->data
;
383 if (data
->glyphs
!= NULL
) {
384 adg_entity_apply_dress(entity
, data
->font_dress
, cr
);
385 cairo_transform(cr
, adg_entity_get_global_matrix(entity
));
386 cairo_transform(cr
, adg_entity_get_local_matrix(entity
));
387 cairo_show_glyphs(cr
, data
->glyphs
, data
->num_glyphs
);
392 _adg_clear_font(AdgToyText
*toy_text
)
394 AdgToyTextPrivate
*data
= toy_text
->data
;
400 _adg_clear_glyphs(AdgToyText
*toy_text
)
402 AdgToyTextPrivate
*data
= toy_text
->data
;
404 if (data
->glyphs
!= NULL
) {
405 cairo_glyph_free(data
->glyphs
);
409 data
->num_glyphs
= 0;