adg: renamed AdgMixMethod to AdgMix
[adg.git] / src / adg / adg-toy-text.c
blob2b330b549d7457127eebbf081e7d770de69efcc1
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 * Since: 1.0
31 **/
33 /**
34 * AdgToyText:
36 * All fields are privates and should not be used directly.
37 * Use its public methods instead.
39 * Since: 1.0
40 **/
43 #include "adg-internal.h"
44 #include "adg-dress.h"
45 #include "adg-dress-builtins.h"
46 #include "adg-style.h"
47 #include "adg-font-style.h"
48 #include "adg-textual.h"
50 #include "adg-toy-text.h"
51 #include "adg-toy-text-private.h"
54 #define _ADG_OLD_OBJECT_CLASS ((GObjectClass *) adg_toy_text_parent_class)
55 #define _ADG_OLD_ENTITY_CLASS ((AdgEntityClass *) adg_toy_text_parent_class)
58 static void _adg_iface_init (AdgTextualIface *iface);
61 G_DEFINE_TYPE_WITH_CODE(AdgToyText, adg_toy_text, ADG_TYPE_ENTITY,
62 G_IMPLEMENT_INTERFACE(ADG_TYPE_TEXTUAL, _adg_iface_init))
64 enum {
65 PROP_0,
66 PROP_FONT_DRESS,
67 PROP_TEXT
71 static void _adg_finalize (GObject *object);
72 static void _adg_get_property (GObject *object,
73 guint param_id,
74 GValue *value,
75 GParamSpec *pspec);
76 static void _adg_set_property (GObject *object,
77 guint param_id,
78 const GValue *value,
79 GParamSpec *pspec);
80 static void _adg_global_changed (AdgEntity *entity);
81 static void _adg_local_changed (AdgEntity *entity);
82 static void _adg_invalidate (AdgEntity *entity);
83 static void _adg_arrange (AdgEntity *entity);
84 static void _adg_render (AdgEntity *entity,
85 cairo_t *cr);
86 static void _adg_set_font_dress (AdgTextual *textual,
87 AdgDress dress);
88 static AdgDress _adg_get_font_dress (AdgTextual *textual);
89 static void _adg_set_text (AdgTextual *textual,
90 const gchar *text);
91 static gchar * _adg_dup_text (AdgTextual *textual);
92 static void _adg_clear_font (AdgToyText *toy_text);
93 static void _adg_clear_glyphs (AdgToyText *toy_text);
96 static void
97 adg_toy_text_class_init(AdgToyTextClass *klass)
99 GObjectClass *gobject_class;
100 AdgEntityClass *entity_class;
102 gobject_class = (GObjectClass *) klass;
103 entity_class = (AdgEntityClass *) klass;
105 g_type_class_add_private(klass, sizeof(AdgToyTextPrivate));
107 gobject_class->finalize = _adg_finalize;
108 gobject_class->get_property = _adg_get_property;
109 gobject_class->set_property = _adg_set_property;
111 entity_class->global_changed = _adg_global_changed;
112 entity_class->local_changed = _adg_local_changed;
113 entity_class->invalidate = _adg_invalidate;
114 entity_class->arrange = _adg_arrange;
115 entity_class->render = _adg_render;
117 g_object_class_override_property(gobject_class, PROP_FONT_DRESS, "font-dress");
118 g_object_class_override_property(gobject_class, PROP_TEXT, "text");
121 static void
122 _adg_iface_init(AdgTextualIface *iface)
124 iface->set_font_dress = _adg_set_font_dress;
125 iface->get_font_dress = _adg_get_font_dress;
126 iface->set_text = _adg_set_text;
127 iface->dup_text = _adg_dup_text;
128 iface->text_changed = NULL;
131 static void
132 adg_toy_text_init(AdgToyText *toy_text)
134 AdgToyTextPrivate *data = G_TYPE_INSTANCE_GET_PRIVATE(toy_text,
135 ADG_TYPE_TOY_TEXT,
136 AdgToyTextPrivate);
138 data->font_dress = ADG_DRESS_FONT_TEXT;
139 data->text = NULL;
140 data->glyphs = NULL;
142 toy_text->data = data;
145 static void
146 _adg_finalize(GObject *object)
148 AdgToyText *toy_text;
149 AdgToyTextPrivate *data;
151 toy_text = (AdgToyText *) object;
152 data = toy_text->data;
154 g_free(data->text);
155 _adg_clear_font(toy_text);
156 _adg_clear_glyphs(toy_text);
158 if (_ADG_OLD_OBJECT_CLASS->finalize)
159 _ADG_OLD_OBJECT_CLASS->finalize(object);
162 static void
163 _adg_get_property(GObject *object, guint prop_id,
164 GValue *value, GParamSpec *pspec)
166 AdgToyTextPrivate *data = ((AdgToyText *) object)->data;
168 switch (prop_id) {
169 case PROP_FONT_DRESS:
170 g_value_set_int(value, data->font_dress);
171 break;
172 case PROP_TEXT:
173 g_value_set_string(value, data->text);
174 break;
175 default:
176 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
177 break;
181 static void
182 _adg_set_property(GObject *object, guint prop_id,
183 const GValue *value, GParamSpec *pspec)
185 AdgToyText *toy_text;
186 AdgToyTextPrivate *data;
188 toy_text = (AdgToyText *) object;
189 data = toy_text->data;
191 switch (prop_id) {
192 case PROP_FONT_DRESS:
193 data->font_dress = g_value_get_int(value);
194 _adg_clear_font(toy_text);
195 break;
196 case PROP_TEXT:
197 g_free(data->text);
198 data->text = g_value_dup_string(value);
199 _adg_clear_glyphs(toy_text);
200 break;
201 default:
202 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
203 break;
209 * adg_toy_text_new:
210 * @text: the text
212 * Creates a new toy text entity using @text as its content.
213 * The #AdgEntity:local-mix property is set by default to
214 * #ADG_LOCAL_NORMALIZED.
216 * Returns: the newly created toy text entity
218 * Since: 1.0
220 AdgToyText *
221 adg_toy_text_new(const gchar *text)
223 return g_object_new(ADG_TYPE_TOY_TEXT,
224 "local-mix", ADG_MIX_ANCESTORS_NORMALIZED,
225 "text", text, NULL);
229 static void
230 _adg_global_changed(AdgEntity *entity)
232 if (_ADG_OLD_ENTITY_CLASS->global_changed)
233 _ADG_OLD_ENTITY_CLASS->global_changed(entity);
235 adg_entity_invalidate(entity);
238 static void
239 _adg_local_changed(AdgEntity *entity)
241 if (_ADG_OLD_ENTITY_CLASS->local_changed)
242 _ADG_OLD_ENTITY_CLASS->local_changed(entity);
244 adg_entity_invalidate(entity);
247 static void
248 _adg_invalidate(AdgEntity *entity)
250 _adg_clear_font((AdgToyText *) entity);
251 _adg_clear_glyphs((AdgToyText *) entity);
253 if (_ADG_OLD_ENTITY_CLASS->invalidate)
254 _ADG_OLD_ENTITY_CLASS->invalidate(entity);
257 static void
258 _adg_arrange(AdgEntity *entity)
260 AdgToyText *toy_text;
261 AdgToyTextPrivate *data;
262 CpmlExtents extents;
264 toy_text = (AdgToyText *) entity;
265 data = toy_text->data;
267 if (data->font == NULL) {
268 AdgDress dress;
269 AdgFontStyle *font_style;
270 cairo_matrix_t ctm;
272 dress = data->font_dress;
273 font_style = (AdgFontStyle *) adg_entity_style(entity, dress);
275 adg_matrix_copy(&ctm, adg_entity_get_global_matrix(entity));
276 adg_matrix_transform(&ctm, adg_entity_get_local_matrix(entity),
277 ADG_TRANSFORM_BEFORE);
279 data->font = adg_font_style_get_scaled_font(font_style, &ctm);
282 if (adg_is_string_empty(data->text)) {
283 /* Undefined text */
284 extents.is_defined = FALSE;
285 } else if (data->glyphs != NULL) {
286 /* Cached result */
287 return;
288 } else {
289 cairo_status_t status;
290 cairo_text_extents_t cairo_extents;
292 status = cairo_scaled_font_text_to_glyphs(data->font, 0, 0,
293 data->text, -1,
294 &data->glyphs,
295 &data->num_glyphs,
296 NULL, NULL, NULL);
298 if (status != CAIRO_STATUS_SUCCESS) {
299 _adg_clear_glyphs(toy_text);
300 g_error(_("Unable to build glyphs (cairo message: %s)"),
301 cairo_status_to_string(status));
302 return;
305 cairo_scaled_font_glyph_extents(data->font, data->glyphs,
306 data->num_glyphs, &cairo_extents);
307 cpml_extents_from_cairo_text(&extents, &cairo_extents);
308 cpml_extents_transform(&extents, adg_entity_get_local_matrix(entity));
309 cpml_extents_transform(&extents, adg_entity_get_global_matrix(entity));
313 adg_entity_set_extents(entity, &extents);
316 static void
317 _adg_render(AdgEntity *entity, cairo_t *cr)
319 AdgToyText *toy_text;
320 AdgToyTextPrivate *data;
322 toy_text = (AdgToyText *) entity;
323 data = toy_text->data;
325 if (data->glyphs != NULL) {
326 adg_entity_apply_dress(entity, data->font_dress, cr);
327 cairo_transform(cr, adg_entity_get_global_matrix(entity));
328 cairo_transform(cr, adg_entity_get_local_matrix(entity));
329 cairo_show_glyphs(cr, data->glyphs, data->num_glyphs);
333 static void
334 _adg_set_font_dress(AdgTextual *textual, AdgDress dress)
336 g_object_set(textual, "font-dress", dress, NULL);
339 static AdgDress
340 _adg_get_font_dress(AdgTextual *textual)
342 AdgToyTextPrivate *data = ((AdgToyText *) textual)->data;
343 return data->font_dress;
346 static void
347 _adg_set_text(AdgTextual *textual, const gchar *text)
349 g_object_set(textual, "text", text, NULL);
352 static gchar *
353 _adg_dup_text(AdgTextual *textual)
355 AdgToyTextPrivate *data = ((AdgToyText *) textual)->data;
356 return g_strdup(data->text);
359 static void
360 _adg_clear_font(AdgToyText *toy_text)
362 AdgToyTextPrivate *data = toy_text->data;
364 data->font = NULL;
367 static void
368 _adg_clear_glyphs(AdgToyText *toy_text)
370 AdgToyTextPrivate *data = toy_text->data;
372 if (data->glyphs != NULL) {
373 cairo_glyph_free(data->glyphs);
374 data->glyphs = NULL;
377 data->num_glyphs = 0;