[AdgToyText] s/TEXT_NORMAL/TEXT_REGULAR/
[adg.git] / adg / adg-toy-text.c
blob778b2ff940c3ddc594ced8b9f984722f65264a29
1 /* ADG - Automatic Drawing Generation
2 * Copyright (C) 2007,2008,2009 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-toy-text.h"
40 #include "adg-toy-text-private.h"
41 #include "adg-type-builtins.h"
42 #include "adg-intl.h"
44 #define PARENT_OBJECT_CLASS ((GObjectClass *) adg_toy_text_parent_class)
45 #define PARENT_ENTITY_CLASS ((AdgEntityClass *) adg_toy_text_parent_class)
48 enum {
49 PROP_0,
50 PROP_DRESS,
51 PROP_LABEL
55 static void finalize (GObject *object);
56 static void get_property (GObject *object,
57 guint param_id,
58 GValue *value,
59 GParamSpec *pspec);
60 static void set_property (GObject *object,
61 guint param_id,
62 const GValue *value,
63 GParamSpec *pspec);
64 static void get_local_matrix (AdgEntity *entity,
65 AdgMatrix *matrix);
66 static gboolean invalidate (AdgEntity *entity);
67 static gboolean render (AdgEntity *entity,
68 cairo_t *cr);
69 static gboolean set_label (AdgToyText *toy_text,
70 const gchar *label);
71 static void update_label_cache (AdgToyText *toy_text,
72 cairo_t *cr);
73 static void clear_label_cache (AdgToyText *toy_text);
76 G_DEFINE_TYPE(AdgToyText, adg_toy_text, ADG_TYPE_ENTITY);
79 static void
80 adg_toy_text_class_init(AdgToyTextClass *klass)
82 GObjectClass *gobject_class;
83 AdgEntityClass *entity_class;
84 GParamSpec *param;
86 gobject_class = (GObjectClass *) klass;
87 entity_class = (AdgEntityClass *) klass;
89 g_type_class_add_private(klass, sizeof(AdgToyTextPrivate));
91 gobject_class->finalize = finalize;
92 gobject_class->get_property = get_property;
93 gobject_class->set_property = set_property;
95 entity_class->get_local_matrix = get_local_matrix;
96 entity_class->invalidate = invalidate;
97 entity_class->render = render;
99 param = adg_param_spec_dress("dress",
100 P_("Dress Style"),
101 P_("The dress style to use for rendering this text"),
102 ADG_DRESS_TEXT_REGULAR,
103 G_PARAM_READWRITE);
104 g_object_class_install_property(gobject_class, PROP_DRESS, param);
106 param = g_param_spec_string("label",
107 P_("Label"),
108 P_("The label to display"),
109 NULL,
110 G_PARAM_READWRITE);
111 g_object_class_install_property(gobject_class, PROP_LABEL, param);
114 static void
115 adg_toy_text_init(AdgToyText *toy_text)
117 AdgToyTextPrivate *data = G_TYPE_INSTANCE_GET_PRIVATE(toy_text,
118 ADG_TYPE_TOY_TEXT,
119 AdgToyTextPrivate);
121 data->dress = ADG_DRESS_TEXT_REGULAR;
122 data->label = NULL;
123 data->glyphs = NULL;
125 toy_text->data = data;
128 static void
129 finalize(GObject *object)
131 AdgToyText *toy_text;
132 AdgToyTextPrivate *data;
134 toy_text = (AdgToyText *) object;
135 data = toy_text->data;
137 g_free(data->label);
138 clear_label_cache(toy_text);
140 if (PARENT_OBJECT_CLASS->finalize != NULL)
141 PARENT_OBJECT_CLASS->finalize(object);
144 static void
145 get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
147 AdgToyTextPrivate *data = ((AdgToyText *) object)->data;
149 switch (prop_id) {
150 case PROP_DRESS:
151 g_value_set_int(value, data->dress);
152 break;
153 case PROP_LABEL:
154 g_value_set_string(value, data->label);
155 break;
156 default:
157 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
158 break;
162 static void
163 set_property(GObject *object, guint prop_id,
164 const GValue *value, GParamSpec *pspec)
166 AdgToyText *toy_text;
167 AdgToyTextPrivate *data;
169 toy_text = (AdgToyText *) object;
170 data = toy_text->data;
172 switch (prop_id) {
173 case PROP_DRESS:
174 adg_dress_set(&data->dress, g_value_get_int(value));
175 break;
176 case PROP_LABEL:
177 set_label(toy_text, g_value_get_string(value));
178 break;
179 default:
180 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
181 break;
187 * adg_toy_text_new:
188 * @label: the label text
190 * Creates a new toy text entity using @label as its text
192 * Returns: the newly created toy text entity
194 AdgToyText *
195 adg_toy_text_new(const gchar *label)
197 return g_object_new(ADG_TYPE_TOY_TEXT, "label", label, NULL);
201 * adg_toy_text_get_label:
202 * @toy_text: an #AdgToyText
204 * Gets the label text. The string is internally owned and
205 * must not be freed or modified.
207 * Returns: the label text
209 const gchar *
210 adg_toy_text_get_label(AdgToyText *toy_text)
212 AdgToyTextPrivate *data;
214 g_return_val_if_fail(ADG_IS_TOY_TEXT(toy_text), NULL);
216 data = toy_text->data;
218 return data->label;
222 * adg_toy_text_set_label:
223 * @toy_text: an #AdgToyText
224 * @label: the label text
226 * Sets a new label for @toy_text. @label can be also %NULL,
227 * in which case will be treated as an empty string.
229 void
230 adg_toy_text_set_label(AdgToyText *toy_text, const gchar *label)
232 g_return_if_fail(ADG_IS_TOY_TEXT(toy_text));
234 if (set_label(toy_text, label))
235 g_object_notify((GObject *) toy_text, "label");
239 * adg_toy_text_get_extents:
240 * @toy_text: an #AdgToyText
241 * @cr: a cairo context
242 * @extents: where to store the extents
244 * Computes the extents of @toy_text and returns the result in @extents.
245 * The cairo context is required for font computation.
247 void
248 adg_toy_text_get_extents(AdgToyText *toy_text, cairo_t *cr,
249 cairo_text_extents_t *extents)
251 AdgToyTextPrivate *data;
253 g_return_if_fail(ADG_IS_TOY_TEXT(toy_text));
254 g_return_if_fail(extents != NULL);
256 update_label_cache(toy_text, cr);
258 data = toy_text->data;
259 *extents = data->extents;
263 static void
264 get_local_matrix(AdgEntity *entity, AdgMatrix *matrix)
266 PARENT_ENTITY_CLASS->get_local_matrix(entity, matrix);
267 cairo_matrix_init_translate(matrix, matrix->x0, matrix->y0);
270 static gboolean
271 invalidate(AdgEntity *entity)
273 clear_label_cache((AdgToyText *) entity);
275 if (PARENT_ENTITY_CLASS->invalidate != NULL)
276 return PARENT_ENTITY_CLASS->invalidate(entity);
278 return TRUE;
281 static gboolean
282 render(AdgEntity *entity, cairo_t *cr)
284 AdgToyText *toy_text;
285 AdgToyTextPrivate *data;
287 toy_text = (AdgToyText *) entity;
288 data = toy_text->data;
290 if (data->label != NULL && data->label[0] != '\0') {
291 update_label_cache(toy_text, cr);
293 cairo_save(cr);
294 adg_entity_apply_local_matrix(entity, cr);
295 cairo_show_glyphs(cr, data->glyphs, data->num_glyphs);
296 cairo_restore(cr);
299 return TRUE;
303 static gboolean
304 set_label(AdgToyText *toy_text, const gchar *label)
306 AdgToyTextPrivate *data = toy_text->data;
308 /* Check if the new label differs from the current label */
309 if (adg_strcmp(label, data->label) == 0)
310 return FALSE;
312 g_free(data->label);
313 data->label = g_strdup(label);
315 clear_label_cache(toy_text);
316 return TRUE;
319 static void
320 update_label_cache(AdgToyText *toy_text, cairo_t *cr)
322 AdgToyTextPrivate *data;
323 cairo_status_t status;
325 data = toy_text->data;
327 adg_entity_apply_dress((AdgEntity *) toy_text, data->dress, cr);
329 if (data->glyphs != NULL)
330 return;
332 status = cairo_scaled_font_text_to_glyphs(cairo_get_scaled_font(cr),
333 0, 0, data->label, -1,
334 &data->glyphs,
335 &data->num_glyphs,
336 NULL, NULL, NULL);
338 if (status != CAIRO_STATUS_SUCCESS) {
339 clear_label_cache(toy_text);
340 g_error("Unable to build glyphs (cairo message: %s)",
341 cairo_status_to_string(status));
342 return;
345 cairo_glyph_extents(cr, data->glyphs, data->num_glyphs, &data->extents);
348 static void
349 clear_label_cache(AdgToyText *toy_text)
351 AdgToyTextPrivate *data = toy_text->data;
353 if (data->glyphs != NULL) {
354 cairo_glyph_free(data->glyphs);
355 data->glyphs = NULL;
358 data->num_glyphs = 0;
359 memset(&data->extents, 0, sizeof(data->extents));