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.
22 * SECTION:adg-toy-text
24 * @short_description: Simple text entity that use the cairo "toy" text API
26 * The #AdgToyText class is a basic class to show simple text. It internally
27 * uses the so called cairo "toy" API and it shares the same limitations.
33 * All fields are privates and should not be used directly.
34 * Use its public methods instead.
38 #include "adg-toy-text.h"
39 #include "adg-toy-text-private.h"
40 #include "adg-rotable.h"
41 #include "adg-font-style.h"
51 static void rotable_init (AdgRotableIface
*iface
);
52 static gdouble
get_angle (AdgRotable
*rotable
);
53 static void set_angle (AdgRotable
*rotable
,
56 static void finalize (GObject
*object
);
57 static void get_property (GObject
*object
,
61 static void set_property (GObject
*object
,
65 static void model_matrix_changed (AdgEntity
*entity
,
66 AdgMatrix
*parent_matrix
);
67 static void invalidate (AdgEntity
*entity
);
68 static void render (AdgEntity
*entity
,
70 static gboolean
update_origin_cache (AdgToyText
*toy_text
,
72 static gboolean
update_label_cache (AdgToyText
*toy_text
,
74 static void clear_label_cache (AdgToyText
*toy_text
);
77 G_DEFINE_TYPE_WITH_CODE(AdgToyText
, adg_toy_text
, ADG_TYPE_ENTITY
,
78 G_IMPLEMENT_INTERFACE(ADG_TYPE_ROTABLE
, rotable_init
))
82 rotable_init(AdgRotableIface
*iface
)
84 iface
->get_angle
= get_angle
;
85 iface
->set_angle
= set_angle
;
89 get_angle(AdgRotable
*rotable
)
92 AdgToyTextPrivate
*data
;
94 toy_text
= (AdgToyText
*) rotable
;
95 data
= toy_text
->data
;
101 set_angle(AdgRotable
*rotable
, gdouble angle
)
103 AdgToyText
*toy_text
;
104 AdgToyTextPrivate
*data
;
106 toy_text
= (AdgToyText
*) rotable
;
107 data
= toy_text
->data
;
114 adg_toy_text_class_init(AdgToyTextClass
*klass
)
116 GObjectClass
*gobject_class
;
117 AdgEntityClass
*entity_class
;
120 gobject_class
= (GObjectClass
*) klass
;
121 entity_class
= (AdgEntityClass
*) klass
;
123 g_type_class_add_private(klass
, sizeof(AdgToyTextPrivate
));
125 gobject_class
->finalize
= finalize
;
126 gobject_class
->get_property
= get_property
;
127 gobject_class
->set_property
= set_property
;
129 entity_class
->model_matrix_changed
= model_matrix_changed
;
130 entity_class
->invalidate
= invalidate
;
131 entity_class
->render
= render
;
133 g_object_class_override_property(gobject_class
, PROP_ANGLE
, "angle");
135 param
= g_param_spec_string("label",
137 P_("The label to display"),
138 NULL
, G_PARAM_READWRITE
);
139 g_object_class_install_property(gobject_class
, PROP_LABEL
, param
);
143 adg_toy_text_init(AdgToyText
*toy_text
)
145 AdgToyTextPrivate
*data
= G_TYPE_INSTANCE_GET_PRIVATE(toy_text
,
152 toy_text
->data
= data
;
156 finalize(GObject
*object
)
158 AdgToyText
*toy_text
;
159 AdgToyTextPrivate
*data
;
160 GObjectClass
*object_class
;
162 toy_text
= (AdgToyText
*) object
;
163 data
= toy_text
->data
;
164 object_class
= (GObjectClass
*) adg_toy_text_parent_class
;
167 clear_label_cache(toy_text
);
169 if (object_class
->finalize
!= NULL
)
170 object_class
->finalize(object
);
174 get_property(GObject
*object
, guint prop_id
, GValue
*value
, GParamSpec
*pspec
)
176 AdgToyTextPrivate
*data
= ((AdgToyText
*) object
)->data
;
180 g_value_set_double(value
, data
->angle
);
183 g_value_set_string(value
, data
->label
);
186 G_OBJECT_WARN_INVALID_PROPERTY_ID(object
, prop_id
, pspec
);
192 set_property(GObject
*object
, guint prop_id
,
193 const GValue
*value
, GParamSpec
*pspec
)
195 AdgToyText
*toy_text
;
196 AdgToyTextPrivate
*data
;
198 toy_text
= (AdgToyText
*) object
;
199 data
= toy_text
->data
;
203 data
->angle
= g_value_get_double(value
);
207 data
->label
= g_value_dup_string(value
);
208 clear_label_cache(toy_text
);
211 G_OBJECT_WARN_INVALID_PROPERTY_ID(object
, prop_id
, pspec
);
219 * @label: the label text
221 * Creates a new toy text entity using @label as its text
223 * Return value: the new entity
226 adg_toy_text_new(const gchar
*label
)
228 return (AdgEntity
*) g_object_new(ADG_TYPE_TOY_TEXT
, "label", label
, NULL
);
232 * adg_toy_text_get_label:
233 * @toy_text: an #AdgToyText
235 * Gets the label text. The string is internally owned and
236 * must not be freed or modified.
238 * Return value: the label text
241 adg_toy_text_get_label(AdgToyText
*toy_text
)
243 AdgToyTextPrivate
*data
;
245 g_return_val_if_fail(ADG_IS_TOY_TEXT(toy_text
), NULL
);
247 data
= toy_text
->data
;
253 * adg_toy_text_set_label:
254 * @toy_text: an #AdgToyText
255 * @label: the label text
257 * Explicitely sets the text to use as label.
260 adg_toy_text_set_label(AdgToyText
*toy_text
, const gchar
*label
)
262 AdgToyTextPrivate
*data
;
264 g_return_if_fail(ADG_IS_TOY_TEXT(label
));
266 data
= toy_text
->data
;
268 data
->label
= g_strdup(label
);
270 g_object_notify((GObject
*) toy_text
, "label");
271 clear_label_cache(toy_text
);
276 render(AdgEntity
*entity
, cairo_t
*cr
)
278 AdgToyText
*toy_text
;
279 AdgToyTextPrivate
*data
;
280 AdgEntityClass
*entity_class
;
282 toy_text
= (AdgToyText
*) entity
;
283 data
= toy_text
->data
;
284 entity_class
= (AdgEntityClass
*) adg_toy_text_parent_class
;
287 AdgStyle
*font_style
;
289 font_style
= adg_entity_get_style(entity
, ADG_SLOT_FONT_STYLE
);
292 cairo_set_matrix(cr
, adg_entity_get_paper_matrix(entity
));
293 adg_style_apply(font_style
, cr
);
294 cairo_rotate(cr
, data
->angle
);
297 update_label_cache(toy_text
, cr
);
298 update_origin_cache(toy_text
, cr
);
300 cairo_show_glyphs(cr
, data
->glyphs
, data
->num_glyphs
);
304 if (entity_class
->render
!= NULL
)
305 entity_class
->render(entity
, cr
);
309 model_matrix_changed(AdgEntity
*entity
, AdgMatrix
*parent_matrix
)
311 AdgEntityClass
*entity_class
= (AdgEntityClass
*) adg_toy_text_parent_class
;
314 if (entity_class
->model_matrix_changed
!= NULL
)
315 entity_class
->model_matrix_changed(entity
, parent_matrix
);
319 invalidate(AdgEntity
*entity
)
321 AdgToyText
*toy_text
;
322 AdgEntityClass
*entity_class
;
324 toy_text
= (AdgToyText
*) entity
;
325 entity_class
= (AdgEntityClass
*) adg_toy_text_parent_class
;
327 clear_label_cache(toy_text
);
329 if (entity_class
->invalidate
!= NULL
)
330 entity_class
->invalidate(entity
);
334 update_origin_cache(AdgToyText
*toy_text
, cairo_t
*cr
)
336 AdgToyTextPrivate
*data
;
337 cairo_glyph_t
*glyph
;
342 data
= toy_text
->data
;
343 glyph
= data
->glyphs
;
344 cnt
= data
->num_glyphs
;
346 /* On undefined label return error */
347 if (glyph
== NULL
|| cnt
<= 0)
350 adg_entity_get_local_matrix((AdgEntity
*) toy_text
, &matrix
);
351 cairo_matrix_transform_point(&matrix
, &x
, &y
);
352 adg_entity_get_global_matrix((AdgEntity
*) toy_text
, &matrix
);
353 cairo_matrix_transform_point(&matrix
, &x
, &y
);
355 /* Check if the origin is still the same */
356 if (x
== glyph
->x
&& y
== glyph
->y
)
372 update_label_cache(AdgToyText
*toy_text
, cairo_t
*cr
)
374 AdgToyTextPrivate
*data
= toy_text
->data
;
375 cairo_status_t status
;
377 status
= cairo_scaled_font_text_to_glyphs(cairo_get_scaled_font(cr
),
378 0., 0., data
->label
, -1,
383 if (status
!= CAIRO_STATUS_SUCCESS
) {
384 g_error("Unable to build glyphs (cairo message: %s)",
385 cairo_status_to_string(status
));
389 cairo_glyph_extents(cr
, data
->glyphs
, data
->num_glyphs
, &data
->extents
);
395 clear_label_cache(AdgToyText
*toy_text
)
397 AdgToyTextPrivate
*data
= toy_text
->data
;
400 cairo_glyph_free(data
->glyphs
);
404 data
->num_glyphs
= 0;
405 memset(&data
->extents
, 0, sizeof(data
->extents
));