[ADG] Moved text stuff from AdgToyText to AdgTextual
[adg.git] / src / adg / adg-toy-text.c
blobd4d9ec221af6e1aa3eedb3b9319ef7803786d1ba
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.
21 /**
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.
29 **/
31 /**
32 * AdgToyText:
34 * All fields are privates and should not be used directly.
35 * Use its public methods instead.
36 **/
39 #include "adg-internal.h"
40 #include "adg-dress.h"
41 #include "adg-dress-builtins.h"
42 #include "adg-style.h"
43 #include "adg-font-style.h"
44 #include "adg-textual.h"
46 #include "adg-toy-text.h"
47 #include "adg-toy-text-private.h"
50 #define _ADG_OLD_OBJECT_CLASS ((GObjectClass *) adg_toy_text_parent_class)
51 #define _ADG_OLD_ENTITY_CLASS ((AdgEntityClass *) adg_toy_text_parent_class)
54 static void _adg_iface_init (AdgTextualIface *iface);
57 G_DEFINE_TYPE_WITH_CODE(AdgToyText, adg_toy_text, ADG_TYPE_ENTITY,
58 G_IMPLEMENT_INTERFACE(ADG_TYPE_TEXTUAL, _adg_iface_init));
60 enum {
61 PROP_0,
62 PROP_FONT_DRESS,
63 PROP_TEXT
67 static void _adg_finalize (GObject *object);
68 static void _adg_get_property (GObject *object,
69 guint param_id,
70 GValue *value,
71 GParamSpec *pspec);
72 static void _adg_set_property (GObject *object,
73 guint param_id,
74 const GValue *value,
75 GParamSpec *pspec);
76 static void _adg_global_changed (AdgEntity *entity);
77 static void _adg_local_changed (AdgEntity *entity);
78 static void _adg_invalidate (AdgEntity *entity);
79 static void _adg_arrange (AdgEntity *entity);
80 static void _adg_render (AdgEntity *entity,
81 cairo_t *cr);
82 static void _adg_set_font_dress (AdgTextual *textual,
83 AdgDress dress);
84 static AdgDress _adg_get_font_dress (AdgTextual *textual);
85 static void _adg_set_text (AdgTextual *textual,
86 const gchar *text);
87 static gchar * _adg_dup_text (AdgTextual *textual);
88 static void _adg_clear_font (AdgToyText *toy_text);
89 static void _adg_clear_glyphs (AdgToyText *toy_text);
92 static void
93 adg_toy_text_class_init(AdgToyTextClass *klass)
95 GObjectClass *gobject_class;
96 AdgEntityClass *entity_class;
98 gobject_class = (GObjectClass *) klass;
99 entity_class = (AdgEntityClass *) klass;
101 g_type_class_add_private(klass, sizeof(AdgToyTextPrivate));
103 gobject_class->finalize = _adg_finalize;
104 gobject_class->get_property = _adg_get_property;
105 gobject_class->set_property = _adg_set_property;
107 entity_class->global_changed = _adg_global_changed;
108 entity_class->local_changed = _adg_local_changed;
109 entity_class->invalidate = _adg_invalidate;
110 entity_class->arrange = _adg_arrange;
111 entity_class->render = _adg_render;
113 g_object_class_override_property(gobject_class, PROP_FONT_DRESS, "font-dress");
114 g_object_class_override_property(gobject_class, PROP_TEXT, "text");
117 static void
118 _adg_iface_init(AdgTextualIface *iface)
120 iface->set_font_dress = _adg_set_font_dress;
121 iface->get_font_dress = _adg_get_font_dress;
122 iface->set_text = _adg_set_text;
123 iface->dup_text = _adg_dup_text;
124 iface->text_changed = NULL;
127 static void
128 adg_toy_text_init(AdgToyText *toy_text)
130 AdgToyTextPrivate *data = G_TYPE_INSTANCE_GET_PRIVATE(toy_text,
131 ADG_TYPE_TOY_TEXT,
132 AdgToyTextPrivate);
134 data->font_dress = ADG_DRESS_FONT_TEXT;
135 data->text = NULL;
136 data->glyphs = NULL;
138 toy_text->data = data;
141 static void
142 _adg_finalize(GObject *object)
144 AdgToyText *toy_text;
145 AdgToyTextPrivate *data;
147 toy_text = (AdgToyText *) object;
148 data = toy_text->data;
150 g_free(data->text);
151 _adg_clear_font(toy_text);
152 _adg_clear_glyphs(toy_text);
154 if (_ADG_OLD_OBJECT_CLASS->finalize)
155 _ADG_OLD_OBJECT_CLASS->finalize(object);
158 static void
159 _adg_get_property(GObject *object, guint prop_id,
160 GValue *value, GParamSpec *pspec)
162 AdgToyTextPrivate *data = ((AdgToyText *) object)->data;
164 switch (prop_id) {
165 case PROP_FONT_DRESS:
166 g_value_set_int(value, data->font_dress);
167 break;
168 case PROP_TEXT:
169 g_value_set_string(value, data->text);
170 break;
171 default:
172 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
173 break;
177 static void
178 _adg_set_property(GObject *object, guint prop_id,
179 const GValue *value, GParamSpec *pspec)
181 AdgToyText *toy_text;
182 AdgToyTextPrivate *data;
184 toy_text = (AdgToyText *) object;
185 data = toy_text->data;
187 switch (prop_id) {
188 case PROP_FONT_DRESS:
189 data->font_dress = g_value_get_int(value);
190 _adg_clear_font(toy_text);
191 break;
192 case PROP_TEXT:
193 g_free(data->text);
194 data->text = g_value_dup_string(value);
195 _adg_clear_glyphs(toy_text);
196 break;
197 default:
198 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
199 break;
205 * adg_toy_text_new:
206 * @text: the text
208 * Creates a new toy text entity using @text as its content.
209 * The #AdgEntity:local-method property is set by default to
210 * #ADG_LOCAL_NORMALIZED.
212 * Returns: the newly created toy text entity
214 AdgToyText *
215 adg_toy_text_new(const gchar *text)
217 return g_object_new(ADG_TYPE_TOY_TEXT,
218 "local-method", ADG_MIX_ANCESTORS_NORMALIZED,
219 "text", text, NULL);
223 static void
224 _adg_global_changed(AdgEntity *entity)
226 if (_ADG_OLD_ENTITY_CLASS->global_changed)
227 _ADG_OLD_ENTITY_CLASS->global_changed(entity);
229 adg_entity_invalidate(entity);
232 static void
233 _adg_local_changed(AdgEntity *entity)
235 if (_ADG_OLD_ENTITY_CLASS->local_changed)
236 _ADG_OLD_ENTITY_CLASS->local_changed(entity);
238 adg_entity_invalidate(entity);
241 static void
242 _adg_invalidate(AdgEntity *entity)
244 _adg_clear_font((AdgToyText *) entity);
245 _adg_clear_glyphs((AdgToyText *) entity);
247 if (_ADG_OLD_ENTITY_CLASS->invalidate)
248 _ADG_OLD_ENTITY_CLASS->invalidate(entity);
251 static void
252 _adg_arrange(AdgEntity *entity)
254 AdgToyText *toy_text;
255 AdgToyTextPrivate *data;
256 CpmlExtents extents;
258 toy_text = (AdgToyText *) entity;
259 data = toy_text->data;
261 if (data->font == NULL) {
262 AdgDress dress;
263 AdgFontStyle *font_style;
264 AdgMatrix ctm;
266 dress = data->font_dress;
267 font_style = (AdgFontStyle *) adg_entity_style(entity, dress);
269 adg_matrix_copy(&ctm, adg_entity_get_global_matrix(entity));
270 adg_matrix_transform(&ctm, adg_entity_get_local_matrix(entity),
271 ADG_TRANSFORM_BEFORE);
273 data->font = adg_font_style_get_scaled_font(font_style, &ctm);
276 if (adg_is_string_empty(data->text)) {
277 /* Undefined text */
278 extents.is_defined = FALSE;
279 } else if (data->glyphs != NULL) {
280 /* Cached result */
281 return;
282 } else {
283 cairo_status_t status;
284 cairo_text_extents_t cairo_extents;
286 status = cairo_scaled_font_text_to_glyphs(data->font, 0, 0,
287 data->text, -1,
288 &data->glyphs,
289 &data->num_glyphs,
290 NULL, NULL, NULL);
292 if (status != CAIRO_STATUS_SUCCESS) {
293 _adg_clear_glyphs(toy_text);
294 g_error(_("Unable to build glyphs (cairo message: %s)"),
295 cairo_status_to_string(status));
296 return;
299 cairo_scaled_font_glyph_extents(data->font, data->glyphs,
300 data->num_glyphs, &cairo_extents);
301 cpml_extents_from_cairo_text(&extents, &cairo_extents);
302 cpml_extents_transform(&extents, adg_entity_get_local_matrix(entity));
303 cpml_extents_transform(&extents, adg_entity_get_global_matrix(entity));
307 adg_entity_set_extents(entity, &extents);
310 static void
311 _adg_render(AdgEntity *entity, cairo_t *cr)
313 AdgToyText *toy_text;
314 AdgToyTextPrivate *data;
316 toy_text = (AdgToyText *) entity;
317 data = toy_text->data;
319 if (data->glyphs != NULL) {
320 adg_entity_apply_dress(entity, data->font_dress, cr);
321 cairo_transform(cr, adg_entity_get_global_matrix(entity));
322 cairo_transform(cr, adg_entity_get_local_matrix(entity));
323 cairo_show_glyphs(cr, data->glyphs, data->num_glyphs);
327 static void
328 _adg_set_font_dress(AdgTextual *textual, AdgDress dress)
330 g_object_set(textual, "font-dress", dress, NULL);
333 static AdgDress
334 _adg_get_font_dress(AdgTextual *textual)
336 AdgToyTextPrivate *data = ((AdgToyText *) textual)->data;
337 return data->font_dress;
340 static void
341 _adg_set_text(AdgTextual *textual, const gchar *text)
343 g_object_set(textual, "text", text, NULL);
346 static gchar *
347 _adg_dup_text(AdgTextual *textual)
349 AdgToyTextPrivate *data = ((AdgToyText *) textual)->data;
350 return g_strdup(data->text);
353 static void
354 _adg_clear_font(AdgToyText *toy_text)
356 AdgToyTextPrivate *data = toy_text->data;
358 data->font = NULL;
361 static void
362 _adg_clear_glyphs(AdgToyText *toy_text)
364 AdgToyTextPrivate *data = toy_text->data;
366 if (data->glyphs != NULL) {
367 cairo_glyph_free(data->glyphs);
368 data->glyphs = NULL;
371 data->num_glyphs = 0;