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
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.
34 * All fields are privates and should not be used directly.
35 * Use its public methods instead.
39 #include "adg-toy-text.h"
40 #include "adg-toy-text-private.h"
41 #include "adg-font-style.h"
42 #include "adg-type-builtins.h"
45 #define PARENT_OBJECT_CLASS ((GObjectClass *) adg_toy_text_parent_class)
46 #define PARENT_ENTITY_CLASS ((AdgEntityClass *) adg_toy_text_parent_class)
56 static void finalize (GObject
*object
);
57 static void get_property (GObject
*object
,
61 static void set_property (GObject
*object
,
65 static void get_local_matrix (AdgEntity
*entity
,
67 static gboolean
invalidate (AdgEntity
*entity
);
68 static gboolean
render (AdgEntity
*entity
,
70 static gboolean
set_label (AdgToyText
*toy_text
,
72 static gboolean
set_font_style (AdgToyText
*toy_text
,
73 AdgFontStyleId font_style
);
74 static void update_label_cache (AdgToyText
*toy_text
,
76 static void clear_label_cache (AdgToyText
*toy_text
);
79 G_DEFINE_TYPE(AdgToyText
, adg_toy_text
, ADG_TYPE_ENTITY
);
83 adg_toy_text_class_init(AdgToyTextClass
*klass
)
85 GObjectClass
*gobject_class
;
86 AdgEntityClass
*entity_class
;
89 gobject_class
= (GObjectClass
*) klass
;
90 entity_class
= (AdgEntityClass
*) klass
;
92 g_type_class_add_private(klass
, sizeof(AdgToyTextPrivate
));
94 gobject_class
->finalize
= finalize
;
95 gobject_class
->get_property
= get_property
;
96 gobject_class
->set_property
= set_property
;
98 entity_class
->get_local_matrix
= get_local_matrix
;
99 entity_class
->invalidate
= invalidate
;
100 entity_class
->render
= render
;
102 param
= g_param_spec_string("label",
104 P_("The label to display"),
105 NULL
, G_PARAM_READWRITE
);
106 g_object_class_install_property(gobject_class
, PROP_LABEL
, param
);
108 param
= g_param_spec_enum("font-style",
110 P_("The identifier of the font to use while rendering the label"),
111 ADG_TYPE_FONT_STYLE_ID
,
114 g_object_class_install_property(gobject_class
, PROP_FONT_STYLE
, param
);
118 adg_toy_text_init(AdgToyText
*toy_text
)
120 AdgToyTextPrivate
*data
= G_TYPE_INSTANCE_GET_PRIVATE(toy_text
,
125 data
->font_style
= ADG_FONT_STYLE_TEXT
;
128 toy_text
->data
= data
;
132 finalize(GObject
*object
)
134 AdgToyText
*toy_text
;
135 AdgToyTextPrivate
*data
;
137 toy_text
= (AdgToyText
*) object
;
138 data
= toy_text
->data
;
141 clear_label_cache(toy_text
);
143 if (PARENT_OBJECT_CLASS
->finalize
!= NULL
)
144 PARENT_OBJECT_CLASS
->finalize(object
);
148 get_property(GObject
*object
, guint prop_id
, GValue
*value
, GParamSpec
*pspec
)
150 AdgToyTextPrivate
*data
= ((AdgToyText
*) object
)->data
;
154 g_value_set_string(value
, data
->label
);
156 case PROP_FONT_STYLE
:
157 g_value_set_enum(value
, data
->font_style
);
160 G_OBJECT_WARN_INVALID_PROPERTY_ID(object
, prop_id
, pspec
);
166 set_property(GObject
*object
, guint prop_id
,
167 const GValue
*value
, GParamSpec
*pspec
)
169 AdgToyText
*toy_text
= (AdgToyText
*) object
;
173 set_label(toy_text
, g_value_get_string(value
));
175 case PROP_FONT_STYLE
:
176 set_font_style(toy_text
, g_value_get_enum(value
));
179 G_OBJECT_WARN_INVALID_PROPERTY_ID(object
, prop_id
, pspec
);
187 * @label: the label text
189 * Creates a new toy text entity using @label as its text
191 * Returns: the new entity
194 adg_toy_text_new(const gchar
*label
)
196 return (AdgEntity
*) g_object_new(ADG_TYPE_TOY_TEXT
, "label", label
, NULL
);
200 * adg_toy_text_get_label:
201 * @toy_text: an #AdgToyText
203 * Gets the label text. The string is internally owned and
204 * must not be freed or modified.
206 * Returns: the label text
209 adg_toy_text_get_label(AdgToyText
*toy_text
)
211 AdgToyTextPrivate
*data
;
213 g_return_val_if_fail(ADG_IS_TOY_TEXT(toy_text
), NULL
);
215 data
= toy_text
->data
;
221 * adg_toy_text_set_label:
222 * @toy_text: an #AdgToyText
223 * @label: the label text
225 * Sets a new label for @toy_text. @label can be also %NULL,
226 * in which case will be treated as an empty string.
229 adg_toy_text_set_label(AdgToyText
*toy_text
, const gchar
*label
)
231 g_return_if_fail(ADG_IS_TOY_TEXT(toy_text
));
233 if (set_label(toy_text
, label
))
234 g_object_notify((GObject
*) toy_text
, "label");
238 * adg_toy_text_get_font_style:
239 * @toy_text: an #AdgToyText
241 * Gets the font style id of this label.
243 * Returns: the font id
246 adg_toy_text_get_font_style(AdgToyText
*toy_text
)
248 AdgToyTextPrivate
*data
;
250 g_return_val_if_fail(ADG_IS_TOY_TEXT(toy_text
), ADG_FONT_STYLE_TEXT
);
252 data
= toy_text
->data
;
254 return data
->font_style
;
258 * adg_toy_text_set_font_style:
259 * @toy_text: an #AdgToyText
260 * @font_style: the new font style id to use
262 * Sets a new font style for @toy_text.
265 adg_toy_text_set_font_style(AdgToyText
*toy_text
, AdgFontStyleId font_style
)
267 g_return_if_fail(ADG_IS_TOY_TEXT(toy_text
));
269 if (set_font_style(toy_text
, font_style
))
270 g_object_notify((GObject
*) toy_text
, "font-style");
274 * adg_toy_text_get_extents:
275 * @toy_text: an #AdgToyText
276 * @cr: a cairo context
277 * @extents: where to store the extents
279 * Computes the extents of @toy_text and returns the result in @extents.
280 * The cairo context is required for font computation.
283 adg_toy_text_get_extents(AdgToyText
*toy_text
, cairo_t
*cr
,
284 cairo_text_extents_t
*extents
)
286 AdgToyTextPrivate
*data
;
288 g_return_if_fail(ADG_IS_TOY_TEXT(toy_text
));
289 g_return_if_fail(extents
!= NULL
);
291 update_label_cache(toy_text
, cr
);
293 data
= toy_text
->data
;
294 *extents
= data
->extents
;
299 get_local_matrix(AdgEntity
*entity
, AdgMatrix
*matrix
)
301 PARENT_ENTITY_CLASS
->get_local_matrix(entity
, matrix
);
302 cairo_matrix_init_translate(matrix
, matrix
->x0
, matrix
->y0
);
306 invalidate(AdgEntity
*entity
)
308 clear_label_cache((AdgToyText
*) entity
);
310 if (PARENT_ENTITY_CLASS
->invalidate
!= NULL
)
311 return PARENT_ENTITY_CLASS
->invalidate(entity
);
317 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
->label
!= NULL
&& data
->label
[0] != '\0') {
326 update_label_cache(toy_text
, cr
);
329 adg_entity_apply_local_matrix(entity
, cr
);
330 cairo_show_glyphs(cr
, data
->glyphs
, data
->num_glyphs
);
339 set_label(AdgToyText
*toy_text
, const gchar
*label
)
341 AdgToyTextPrivate
*data
= toy_text
->data
;
343 /* Check if the new label differs from the current label */
344 if (adg_strcmp(label
, data
->label
) == 0)
348 data
->label
= g_strdup(label
);
350 clear_label_cache(toy_text
);
355 set_font_style(AdgToyText
*toy_text
, AdgFontStyleId font_style
)
357 AdgToyTextPrivate
*data
= toy_text
->data
;
359 /* Check if the new style differs from the current one */
360 if (font_style
== data
->font_style
)
363 data
->font_style
= font_style
;
365 /* Changing the font invalidate the cache */
366 clear_label_cache(toy_text
);
371 update_label_cache(AdgToyText
*toy_text
, cairo_t
*cr
)
373 AdgToyTextPrivate
*data
;
374 cairo_status_t status
;
376 data
= toy_text
->data
;
378 adg_entity_apply_font((AdgEntity
*) toy_text
, data
->font_style
, cr
);
380 if (data
->glyphs
!= NULL
)
383 status
= cairo_scaled_font_text_to_glyphs(cairo_get_scaled_font(cr
),
384 0, 0, data
->label
, -1,
389 if (status
!= CAIRO_STATUS_SUCCESS
) {
390 clear_label_cache(toy_text
);
391 g_error("Unable to build glyphs (cairo message: %s)",
392 cairo_status_to_string(status
));
396 cairo_glyph_extents(cr
, data
->glyphs
, data
->num_glyphs
, &data
->extents
);
400 clear_label_cache(AdgToyText
*toy_text
)
402 AdgToyTextPrivate
*data
= toy_text
->data
;
404 if (data
->glyphs
!= NULL
) {
405 cairo_glyph_free(data
->glyphs
);
409 data
->num_glyphs
= 0;
410 memset(&data
->extents
, 0, sizeof(data
->extents
));