build: depends on cairo-gobject if introspection is enabled
[adg.git] / src / adg / adg-toy-text.c
blob30930331e8404faf625cc52162720ec6c20a6865
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.
21 /**
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.
30 * <note><para>
31 * By default, the #AdgToyText:local-mix property is set to
32 * #ADG_MIX_ANCESTORS_NORMALIZED on #AdgToyText entities.
33 * </para></note>
35 * Since: 1.0
36 **/
38 /**
39 * AdgToyText:
41 * All fields are privates and should not be used directly.
42 * Use its public methods instead.
44 * Since: 1.0
45 **/
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))
69 enum {
70 PROP_0,
71 PROP_FONT_DRESS,
72 PROP_TEXT
76 static void _adg_finalize (GObject *object);
77 static void _adg_get_property (GObject *object,
78 guint param_id,
79 GValue *value,
80 GParamSpec *pspec);
81 static void _adg_set_property (GObject *object,
82 guint param_id,
83 const GValue *value,
84 GParamSpec *pspec);
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,
90 cairo_t *cr);
91 static void _adg_set_font_dress (AdgTextual *textual,
92 AdgDress dress);
93 static AdgDress _adg_get_font_dress (AdgTextual *textual);
94 static void _adg_set_text (AdgTextual *textual,
95 const gchar *text);
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);
101 static void
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");
126 static void
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;
136 static void
137 adg_toy_text_init(AdgToyText *toy_text)
139 AdgToyTextPrivate *data = G_TYPE_INSTANCE_GET_PRIVATE(toy_text,
140 ADG_TYPE_TOY_TEXT,
141 AdgToyTextPrivate);
142 AdgEntityPrivate *entity_data = ((AdgEntity *) toy_text)->data;
144 data->font_dress = ADG_DRESS_FONT_TEXT;
145 data->text = NULL;
146 data->glyphs = NULL;
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;
156 static void
157 _adg_finalize(GObject *object)
159 AdgToyText *toy_text;
160 AdgToyTextPrivate *data;
162 toy_text = (AdgToyText *) object;
163 data = toy_text->data;
165 g_free(data->text);
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);
173 static void
174 _adg_get_property(GObject *object, guint prop_id,
175 GValue *value, GParamSpec *pspec)
177 AdgToyTextPrivate *data = ((AdgToyText *) object)->data;
179 switch (prop_id) {
180 case PROP_FONT_DRESS:
181 g_value_set_enum(value, data->font_dress);
182 break;
183 case PROP_TEXT:
184 g_value_set_string(value, data->text);
185 break;
186 default:
187 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
188 break;
192 static void
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;
202 switch (prop_id) {
203 case PROP_FONT_DRESS:
204 data->font_dress = g_value_get_enum(value);
205 _adg_clear_font(toy_text);
206 break;
207 case PROP_TEXT:
208 g_free(data->text);
209 data->text = g_value_dup_string(value);
210 _adg_clear_glyphs(toy_text);
211 break;
212 default:
213 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
214 break;
220 * adg_toy_text_new:
221 * @text: the text
223 * Creates a new toy text entity using @text as its content.
225 * Returns: the newly created toy text entity
227 * Since: 1.0
229 AdgToyText *
230 adg_toy_text_new(const gchar *text)
232 return g_object_new(ADG_TYPE_TOY_TEXT,
233 "text", text, NULL);
237 static void
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);
246 static void
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);
255 static void
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);
265 static void
266 _adg_arrange(AdgEntity *entity)
268 AdgToyText *toy_text;
269 AdgToyTextPrivate *data;
270 CpmlExtents extents;
272 toy_text = (AdgToyText *) entity;
273 data = toy_text->data;
275 if (data->font == NULL) {
276 AdgDress dress;
277 AdgFontStyle *font_style;
278 cairo_matrix_t ctm;
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)) {
291 /* Undefined text */
292 extents.is_defined = FALSE;
293 } else if (data->glyphs != NULL) {
294 /* Cached result */
295 return;
296 } else {
297 cairo_status_t status;
298 cairo_text_extents_t cairo_extents;
300 status = cairo_scaled_font_text_to_glyphs(data->font, 0, 0,
301 data->text, -1,
302 &data->glyphs,
303 &data->num_glyphs,
304 NULL, NULL, NULL);
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));
310 return;
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);
324 static void
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);
341 static void
342 _adg_set_font_dress(AdgTextual *textual, AdgDress dress)
344 g_object_set(textual, "font-dress", dress, NULL);
347 static AdgDress
348 _adg_get_font_dress(AdgTextual *textual)
350 AdgToyTextPrivate *data = ((AdgToyText *) textual)->data;
351 return data->font_dress;
354 static void
355 _adg_set_text(AdgTextual *textual, const gchar *text)
357 g_object_set(textual, "text", text, NULL);
360 static gchar *
361 _adg_dup_text(AdgTextual *textual)
363 AdgToyTextPrivate *data = ((AdgToyText *) textual)->data;
364 return g_strdup(data->text);
367 static void
368 _adg_clear_font(AdgToyText *toy_text)
370 AdgToyTextPrivate *data = toy_text->data;
372 data->font = NULL;
375 static void
376 _adg_clear_glyphs(AdgToyText *toy_text)
378 AdgToyTextPrivate *data = toy_text->data;
380 if (data->glyphs != NULL) {
381 cairo_glyph_free(data->glyphs);
382 data->glyphs = NULL;
385 data->num_glyphs = 0;