1 /* ADG - Automatic Drawing Generation
2 * Copyright (C) 2007,2008,2009,2010,2011,2012,2013 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 uses 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.
31 * By default, the #AdgToyText:local-mix property is set to
32 * #ADG_MIX_ANCESTORS_NORMALIZED on #AdgToyText entities.
41 * All fields are privates and should not be used directly.
42 * Use its public methods instead.
48 #include "adg-internal.h"
49 #include "adg-dress.h"
50 #include "adg-style.h"
51 #include "adg-font-style.h"
52 #include "adg-textual.h"
53 #include "adg-entity-private.h"
55 #include "adg-toy-text.h"
56 #include "adg-toy-text-private.h"
59 #define _ADG_OLD_OBJECT_CLASS ((GObjectClass *) adg_toy_text_parent_class)
60 #define _ADG_OLD_ENTITY_CLASS ((AdgEntityClass *) adg_toy_text_parent_class)
63 static void _adg_iface_init (AdgTextualIface
*iface
);
66 G_DEFINE_TYPE_WITH_CODE(AdgToyText
, adg_toy_text
, ADG_TYPE_ENTITY
,
67 G_IMPLEMENT_INTERFACE(ADG_TYPE_TEXTUAL
, _adg_iface_init
))
76 static void _adg_finalize (GObject
*object
);
77 static void _adg_get_property (GObject
*object
,
81 static void _adg_set_property (GObject
*object
,
85 static void _adg_global_changed (AdgEntity
*entity
);
86 static void _adg_local_changed (AdgEntity
*entity
);
87 static void _adg_invalidate (AdgEntity
*entity
);
88 static void _adg_arrange (AdgEntity
*entity
);
89 static void _adg_render (AdgEntity
*entity
,
91 static void _adg_set_font_dress (AdgTextual
*textual
,
93 static AdgDress
_adg_get_font_dress (AdgTextual
*textual
);
94 static void _adg_set_text (AdgTextual
*textual
,
96 static gchar
* _adg_dup_text (AdgTextual
*textual
);
97 static void _adg_clear_font (AdgToyText
*toy_text
);
98 static void _adg_clear_glyphs (AdgToyText
*toy_text
);
102 adg_toy_text_class_init(AdgToyTextClass
*klass
)
104 GObjectClass
*gobject_class
;
105 AdgEntityClass
*entity_class
;
107 gobject_class
= (GObjectClass
*) klass
;
108 entity_class
= (AdgEntityClass
*) klass
;
110 g_type_class_add_private(klass
, sizeof(AdgToyTextPrivate
));
112 gobject_class
->finalize
= _adg_finalize
;
113 gobject_class
->get_property
= _adg_get_property
;
114 gobject_class
->set_property
= _adg_set_property
;
116 entity_class
->global_changed
= _adg_global_changed
;
117 entity_class
->local_changed
= _adg_local_changed
;
118 entity_class
->invalidate
= _adg_invalidate
;
119 entity_class
->arrange
= _adg_arrange
;
120 entity_class
->render
= _adg_render
;
122 g_object_class_override_property(gobject_class
, PROP_FONT_DRESS
, "font-dress");
123 g_object_class_override_property(gobject_class
, PROP_TEXT
, "text");
127 _adg_iface_init(AdgTextualIface
*iface
)
129 iface
->set_font_dress
= _adg_set_font_dress
;
130 iface
->get_font_dress
= _adg_get_font_dress
;
131 iface
->set_text
= _adg_set_text
;
132 iface
->dup_text
= _adg_dup_text
;
133 iface
->text_changed
= NULL
;
137 adg_toy_text_init(AdgToyText
*toy_text
)
139 AdgToyTextPrivate
*data
= G_TYPE_INSTANCE_GET_PRIVATE(toy_text
,
142 AdgEntityPrivate
*entity_data
= ((AdgEntity
*) toy_text
)->data
;
144 data
->font_dress
= ADG_DRESS_FONT_TEXT
;
148 toy_text
->data
= data
;
150 /* Initialize to custom default some AdgEntity field by directly
151 * accessing the private struct to avoid notify signal emissions
153 entity_data
->local_mix
= ADG_MIX_ANCESTORS_NORMALIZED
;
157 _adg_finalize(GObject
*object
)
159 AdgToyText
*toy_text
;
160 AdgToyTextPrivate
*data
;
162 toy_text
= (AdgToyText
*) object
;
163 data
= toy_text
->data
;
166 _adg_clear_font(toy_text
);
167 _adg_clear_glyphs(toy_text
);
169 if (_ADG_OLD_OBJECT_CLASS
->finalize
)
170 _ADG_OLD_OBJECT_CLASS
->finalize(object
);
174 _adg_get_property(GObject
*object
, guint prop_id
,
175 GValue
*value
, GParamSpec
*pspec
)
177 AdgToyTextPrivate
*data
= ((AdgToyText
*) object
)->data
;
180 case PROP_FONT_DRESS
:
181 g_value_set_enum(value
, data
->font_dress
);
184 g_value_set_string(value
, data
->text
);
187 G_OBJECT_WARN_INVALID_PROPERTY_ID(object
, prop_id
, pspec
);
193 _adg_set_property(GObject
*object
, guint prop_id
,
194 const GValue
*value
, GParamSpec
*pspec
)
196 AdgToyText
*toy_text
;
197 AdgToyTextPrivate
*data
;
199 toy_text
= (AdgToyText
*) object
;
200 data
= toy_text
->data
;
203 case PROP_FONT_DRESS
:
204 data
->font_dress
= g_value_get_enum(value
);
205 _adg_clear_font(toy_text
);
209 data
->text
= g_value_dup_string(value
);
210 _adg_clear_glyphs(toy_text
);
213 G_OBJECT_WARN_INVALID_PROPERTY_ID(object
, prop_id
, pspec
);
223 * Creates a new toy text entity using @text as its content.
225 * Returns: the newly created toy text entity
230 adg_toy_text_new(const gchar
*text
)
232 return g_object_new(ADG_TYPE_TOY_TEXT
,
238 _adg_global_changed(AdgEntity
*entity
)
240 if (_ADG_OLD_ENTITY_CLASS
->global_changed
)
241 _ADG_OLD_ENTITY_CLASS
->global_changed(entity
);
243 adg_entity_invalidate(entity
);
247 _adg_local_changed(AdgEntity
*entity
)
249 if (_ADG_OLD_ENTITY_CLASS
->local_changed
)
250 _ADG_OLD_ENTITY_CLASS
->local_changed(entity
);
252 adg_entity_invalidate(entity
);
256 _adg_invalidate(AdgEntity
*entity
)
258 _adg_clear_font((AdgToyText
*) entity
);
259 _adg_clear_glyphs((AdgToyText
*) entity
);
261 if (_ADG_OLD_ENTITY_CLASS
->invalidate
)
262 _ADG_OLD_ENTITY_CLASS
->invalidate(entity
);
266 _adg_arrange(AdgEntity
*entity
)
268 AdgToyText
*toy_text
;
269 AdgToyTextPrivate
*data
;
272 toy_text
= (AdgToyText
*) entity
;
273 data
= toy_text
->data
;
275 if (data
->font
== NULL
) {
277 AdgFontStyle
*font_style
;
280 dress
= data
->font_dress
;
281 font_style
= (AdgFontStyle
*) adg_entity_style(entity
, dress
);
283 adg_matrix_copy(&ctm
, adg_entity_get_global_matrix(entity
));
284 adg_matrix_transform(&ctm
, adg_entity_get_local_matrix(entity
),
285 ADG_TRANSFORM_BEFORE
);
287 data
->font
= adg_font_style_get_scaled_font(font_style
, &ctm
);
290 if (adg_is_string_empty(data
->text
)) {
292 extents
.is_defined
= FALSE
;
293 } else if (data
->glyphs
!= NULL
) {
297 cairo_status_t status
;
298 cairo_text_extents_t cairo_extents
;
300 status
= cairo_scaled_font_text_to_glyphs(data
->font
, 0, 0,
306 if (status
!= CAIRO_STATUS_SUCCESS
) {
307 _adg_clear_glyphs(toy_text
);
308 g_error(_("Unable to build glyphs (cairo message: %s)"),
309 cairo_status_to_string(status
));
313 cairo_scaled_font_glyph_extents(data
->font
, data
->glyphs
,
314 data
->num_glyphs
, &cairo_extents
);
315 cpml_extents_from_cairo_text(&extents
, &cairo_extents
);
316 cpml_extents_transform(&extents
, adg_entity_get_local_matrix(entity
));
317 cpml_extents_transform(&extents
, adg_entity_get_global_matrix(entity
));
321 adg_entity_set_extents(entity
, &extents
);
325 _adg_render(AdgEntity
*entity
, cairo_t
*cr
)
327 AdgToyText
*toy_text
;
328 AdgToyTextPrivate
*data
;
330 toy_text
= (AdgToyText
*) entity
;
331 data
= toy_text
->data
;
333 if (data
->glyphs
!= NULL
) {
334 adg_entity_apply_dress(entity
, data
->font_dress
, cr
);
335 cairo_transform(cr
, adg_entity_get_global_matrix(entity
));
336 cairo_transform(cr
, adg_entity_get_local_matrix(entity
));
337 cairo_show_glyphs(cr
, data
->glyphs
, data
->num_glyphs
);
342 _adg_set_font_dress(AdgTextual
*textual
, AdgDress dress
)
344 g_object_set(textual
, "font-dress", dress
, NULL
);
348 _adg_get_font_dress(AdgTextual
*textual
)
350 AdgToyTextPrivate
*data
= ((AdgToyText
*) textual
)->data
;
351 return data
->font_dress
;
355 _adg_set_text(AdgTextual
*textual
, const gchar
*text
)
357 g_object_set(textual
, "text", text
, NULL
);
361 _adg_dup_text(AdgTextual
*textual
)
363 AdgToyTextPrivate
*data
= ((AdgToyText
*) textual
)->data
;
364 return g_strdup(data
->text
);
368 _adg_clear_font(AdgToyText
*toy_text
)
370 AdgToyTextPrivate
*data
= toy_text
->data
;
376 _adg_clear_glyphs(AdgToyText
*toy_text
)
378 AdgToyTextPrivate
*data
= toy_text
->data
;
380 if (data
->glyphs
!= NULL
) {
381 cairo_glyph_free(data
->glyphs
);
385 data
->num_glyphs
= 0;