build: depends on cairo-gobject if introspection is enabled
[adg.git] / src / adg / adg-font-style.c
blob7b81d0f75d4862db071571fc905b350c126d8427
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-font-style
23 * @short_description: Font style related stuff
25 * Contains parameters on how to draw texts such as font family, slanting,
26 * weight, hinting and so on.
28 * Since: 1.0
31 /**
32 * AdgFontStyle:
34 * All fields are private and should not be used directly.
35 * Use its public methods instead.
37 * Since: 1.0
38 **/
41 #include "adg-internal.h"
42 #include "adg-style.h"
43 #include "adg-dress.h"
44 #include "adg-param-dress.h"
46 #include "adg-font-style.h"
47 #include "adg-font-style-private.h"
50 #define _ADG_OLD_OBJECT_CLASS ((GObjectClass *) adg_font_style_parent_class)
53 G_DEFINE_TYPE(AdgFontStyle, adg_font_style, ADG_TYPE_STYLE)
55 enum {
56 PROP_0,
57 PROP_COLOR_DRESS,
58 PROP_FAMILY,
59 PROP_SLANT,
60 PROP_WEIGHT,
61 PROP_SIZE,
62 PROP_ANTIALIAS,
63 PROP_SUBPIXEL_ORDER,
64 PROP_HINT_STYLE,
65 PROP_HINT_METRICS
69 static void _adg_get_property (GObject *object,
70 guint prop_id,
71 GValue *value,
72 GParamSpec *pspec);
73 static void _adg_set_property (GObject *object,
74 guint prop_id,
75 const GValue *value,
76 GParamSpec *pspec);
77 static void _adg_invalidate (AdgStyle *style);
78 static void _adg_apply (AdgStyle *style,
79 AdgEntity *entity,
80 cairo_t *cr);
83 static void
84 adg_font_style_class_init(AdgFontStyleClass *klass)
86 GObjectClass *gobject_class;
87 AdgStyleClass *style_class;
88 GParamSpec *param;
90 gobject_class = (GObjectClass *) klass;
91 style_class = (AdgStyleClass *) klass;
93 g_type_class_add_private(klass, sizeof(AdgFontStylePrivate));
95 gobject_class->get_property = _adg_get_property;
96 gobject_class->set_property = _adg_set_property;
98 style_class->invalidate = _adg_invalidate;
99 style_class->apply = _adg_apply;
101 param = adg_param_spec_dress("color-dress",
102 P_("Color Dress"),
103 P_("The fallback color dress to bind to this style"),
104 ADG_DRESS_COLOR,
105 G_PARAM_READWRITE);
106 g_object_class_install_property(gobject_class, PROP_COLOR_DRESS, param);
108 param = g_param_spec_string("family",
109 P_("Font Family"),
110 P_("The font family name, encoded in UTF-8"),
111 NULL,
112 G_PARAM_READWRITE);
113 g_object_class_install_property(gobject_class, PROP_FAMILY, param);
115 param = g_param_spec_int("slant",
116 P_("Font Slant"),
117 P_("Variant of a font face based on its slant"),
118 G_MININT, G_MAXINT, CAIRO_FONT_SLANT_NORMAL,
119 G_PARAM_READWRITE);
120 g_object_class_install_property(gobject_class, PROP_SLANT, param);
122 param = g_param_spec_int("weight",
123 P_("Font Weight"),
124 P_("Variant of a font face based on its weight"),
125 G_MININT, G_MAXINT, CAIRO_FONT_WEIGHT_NORMAL,
126 G_PARAM_READWRITE);
127 g_object_class_install_property(gobject_class, PROP_WEIGHT, param);
129 param = g_param_spec_double("size",
130 P_("Font Size"),
131 P_("Font size in user space units"),
132 0, G_MAXDOUBLE, 10,
133 G_PARAM_READWRITE);
134 g_object_class_install_property(gobject_class, PROP_SIZE, param);
136 param = g_param_spec_int("antialias",
137 P_("Font Antialiasing Mode"),
138 P_("Type of antialiasing to do when rendering text"),
139 G_MININT, G_MAXINT, CAIRO_ANTIALIAS_DEFAULT,
140 G_PARAM_READWRITE);
141 g_object_class_install_property(gobject_class, PROP_ANTIALIAS, param);
143 param = g_param_spec_int("subpixel-order",
144 P_("Font Subpixel Order"),
145 P_("The order of color elements within each pixel on the display device when rendering with subpixel antialiasing mode"),
146 G_MININT, G_MAXINT,
147 CAIRO_SUBPIXEL_ORDER_DEFAULT,
148 G_PARAM_READWRITE);
149 g_object_class_install_property(gobject_class, PROP_SUBPIXEL_ORDER, param);
151 param = g_param_spec_int("hint-style",
152 P_("Type of Hinting"),
153 P_("How outlines must fit to the pixel grid in order to improve the glyph appearance"),
154 G_MININT, G_MAXINT, CAIRO_HINT_STYLE_DEFAULT,
155 G_PARAM_READWRITE);
156 g_object_class_install_property(gobject_class, PROP_HINT_STYLE, param);
158 param = g_param_spec_int("hint-metrics",
159 P_("Font Metric Hinting"),
160 P_("Whether to hint font metrics, that is align them to integer values in device space"),
161 G_MININT, G_MAXINT,
162 CAIRO_HINT_METRICS_DEFAULT,
163 G_PARAM_READWRITE);
164 g_object_class_install_property(gobject_class, PROP_HINT_METRICS, param);
167 static void
168 adg_font_style_init(AdgFontStyle *font_style)
170 AdgFontStylePrivate *data = G_TYPE_INSTANCE_GET_PRIVATE(font_style,
171 ADG_TYPE_FONT_STYLE,
172 AdgFontStylePrivate);
174 data->color_dress = ADG_DRESS_COLOR;
175 data->family = NULL;
176 data->slant = CAIRO_FONT_SLANT_NORMAL;
177 data->weight = CAIRO_FONT_WEIGHT_NORMAL;
178 data->size = 10;
179 data->antialias = CAIRO_ANTIALIAS_DEFAULT;
180 data->subpixel_order = CAIRO_SUBPIXEL_ORDER_DEFAULT;
181 data->hint_style = CAIRO_HINT_STYLE_DEFAULT;
182 data->hint_metrics = CAIRO_HINT_METRICS_DEFAULT;
183 data->font = NULL;
185 font_style->data = data;
188 static void
189 _adg_get_property(GObject *object, guint prop_id,
190 GValue *value, GParamSpec *pspec)
192 AdgFontStylePrivate *data = ((AdgFontStyle *) object)->data;
194 switch (prop_id) {
195 case PROP_COLOR_DRESS:
196 g_value_set_enum(value, data->color_dress);
197 break;
198 case PROP_FAMILY:
199 g_value_set_string(value, data->family);
200 break;
201 case PROP_SLANT:
202 g_value_set_int(value, data->slant);
203 break;
204 case PROP_WEIGHT:
205 g_value_set_int(value, data->weight);
206 break;
207 case PROP_SIZE:
208 g_value_set_double(value, data->size);
209 break;
210 case PROP_ANTIALIAS:
211 g_value_set_int(value, data->antialias);
212 break;
213 case PROP_SUBPIXEL_ORDER:
214 g_value_set_int(value, data->subpixel_order);
215 break;
216 case PROP_HINT_STYLE:
217 g_value_set_int(value, data->hint_style);
218 break;
219 case PROP_HINT_METRICS:
220 g_value_set_int(value, data->hint_metrics);
221 break;
222 default:
223 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
224 break;
228 static void
229 _adg_set_property(GObject *object, guint prop_id,
230 const GValue *value, GParamSpec *pspec)
232 AdgStyle *style;
233 AdgFontStyle *font_style;
234 AdgFontStylePrivate *data;
236 style = (AdgStyle *) object;
237 font_style = (AdgFontStyle *) object;
238 data = font_style->data;
240 switch (prop_id) {
241 case PROP_COLOR_DRESS:
242 data->color_dress = g_value_get_enum(value);
243 break;
244 case PROP_FAMILY:
245 g_free(data->family);
246 data->family = g_value_dup_string(value);
247 adg_style_invalidate(style);
248 break;
249 case PROP_SLANT:
250 data->slant = g_value_get_int(value);
251 adg_style_invalidate(style);
252 break;
253 case PROP_WEIGHT:
254 data->weight = g_value_get_int(value);
255 adg_style_invalidate(style);
256 break;
257 case PROP_SIZE:
258 data->size = g_value_get_double(value);
259 adg_style_invalidate(style);
260 break;
261 case PROP_ANTIALIAS:
262 data->antialias = g_value_get_int(value);
263 adg_style_invalidate(style);
264 break;
265 case PROP_SUBPIXEL_ORDER:
266 data->subpixel_order = g_value_get_int(value);
267 adg_style_invalidate(style);
268 break;
269 case PROP_HINT_STYLE:
270 data->hint_style = g_value_get_int(value);
271 adg_style_invalidate(style);
272 break;
273 case PROP_HINT_METRICS:
274 data->hint_metrics = g_value_get_int(value);
275 adg_style_invalidate(style);
276 break;
277 default:
278 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
279 break;
285 * adg_font_style_new:
287 * Constructs a new font style initialized with default params.
289 * Returns: (transfer full): a newly created font style
291 * Since: 1.0
293 AdgFontStyle *
294 adg_font_style_new(void)
296 return g_object_new(ADG_TYPE_FONT_STYLE, NULL);
300 * adg_font_style_new_options:
301 * @font_style: an #AdgFontStyle object
303 * Creates a new set of #cairo_font_options_t filled with the values
304 * picked from @font_style. The returned value must be freed with
305 * cairo_font_options_destroy().
307 * Returns: (transfer full): a newly allocated list of cairo font options.
309 * Since: 1.0
311 cairo_font_options_t *
312 adg_font_style_new_options(AdgFontStyle *font_style)
314 AdgFontStylePrivate *data;
315 cairo_font_options_t *options;
317 g_return_val_if_fail(ADG_IS_FONT_STYLE(font_style), NULL);
319 data = font_style->data;
320 options = cairo_font_options_create();
322 /* Check for cached font */
323 if (data->font != NULL) {
324 cairo_scaled_font_get_font_options(data->font, options);
325 } else {
326 cairo_font_options_set_antialias(options, data->antialias);
327 cairo_font_options_set_subpixel_order(options, data->subpixel_order);
328 cairo_font_options_set_hint_style(options, data->hint_style);
329 cairo_font_options_set_hint_metrics(options, data->hint_metrics);
332 return options;
336 * adg_font_style_get_scaled_font:
337 * @font_style: an #AdgFontStyle object
338 * @ctm: the current transformation matrix
340 * Gets the scaled font of @font_style. The returned font is
341 * owned by @font_style and must not be destroyed by the caller.
343 * Returns: (transfer none): the scaled font.
345 * Since: 1.0
347 cairo_scaled_font_t *
348 adg_font_style_get_scaled_font(AdgFontStyle *font_style,
349 const cairo_matrix_t *ctm)
351 AdgFontStylePrivate *data;
352 cairo_font_options_t *options;
353 cairo_matrix_t matrix;
355 g_return_val_if_fail(ADG_IS_FONT_STYLE(font_style), NULL);
356 g_return_val_if_fail(ctm != NULL, NULL);
358 data = font_style->data;
360 /* Check for cached font */
361 if (data->font != NULL) {
362 cairo_matrix_t font_ctm;
364 cairo_scaled_font_get_ctm(data->font, &font_ctm);
366 /* The scaled font is valid only if the two ctm match */
367 if (ctm->xx == font_ctm.xx && ctm->yy == font_ctm.yy &&
368 ctm->xy == font_ctm.xy && ctm->yx == font_ctm.yx)
369 return data->font;
371 /* No valid cache found: rebuild the scaled font */
372 adg_style_invalidate((AdgStyle *) font_style);
375 if (data->face == NULL) {
376 const gchar *family = data->family != NULL ? data->family : "";
378 data->face = cairo_toy_font_face_create(family, data->slant,
379 data->weight);
382 cairo_matrix_init_scale(&matrix, data->size, data->size);
383 options = adg_font_style_new_options(font_style);
384 data->font = cairo_scaled_font_create(data->face, &matrix, ctm, options);
385 cairo_font_options_destroy(options);
387 return data->font;
391 * adg_font_style_set_color_dress:
392 * @font_style: an #AdgFontStyle
393 * @dress: (transfer none): the new color dress to use
395 * Sets a new color dress on @font_style. The new dress
396 * should be related to the original dress: you cannot
397 * set a dress used for font styles to a dress managing
398 * fonts.
400 * The validation of the new dress is done by calling
401 * adg_dress_are_related() with @dress and the previous
402 * dress as arguments: check out its documentation for
403 * details on what is a related dress.
405 * Since: 1.0
407 void
408 adg_font_style_set_color_dress(AdgFontStyle *font_style, AdgDress dress)
410 g_return_if_fail(ADG_IS_FONT_STYLE(font_style));
411 g_object_set(font_style, "color-dress", dress, NULL);
415 * adg_font_style_get_color_dress:
416 * @font_style: an #AdgFontStyle
418 * Gets the color dress used by @font_style.
420 * Returns: (transfer none): the current color dress.
422 * Since: 1.0
424 AdgDress
425 adg_font_style_get_color_dress(AdgFontStyle *font_style)
427 AdgFontStylePrivate *data;
429 g_return_val_if_fail(ADG_IS_FONT_STYLE(font_style), ADG_DRESS_UNDEFINED);
431 data = font_style->data;
433 return data->color_dress;
437 * adg_font_style_set_family:
438 * @font_style: an #AdgFontStyle object
439 * @family: (transfer none): the new family
441 * Sets a new family.
443 * Since: 1.0
445 void
446 adg_font_style_set_family(AdgFontStyle *font_style, const gchar *family)
448 g_return_if_fail(ADG_IS_FONT_STYLE(font_style));
449 g_object_set(font_style, "family", family, NULL);
453 * adg_font_style_get_family:
454 * @font_style: an #AdgFontStyle object
456 * Gets the family of @font_style. The returned pointer refers to
457 * internally managed text that must not be modified or freed.
459 * Returns: (transfer none): the requested family.
461 * Since: 1.0
463 const gchar *
464 adg_font_style_get_family(AdgFontStyle *font_style)
466 AdgFontStylePrivate *data;
468 g_return_val_if_fail(ADG_IS_FONT_STYLE(font_style), NULL);
470 data = font_style->data;
472 return data->family;
476 * adg_font_style_set_slant:
477 * @font_style: an #AdgFontStyle object
478 * @slant: (type gint): the new slant
480 * Sets a new slant variant on @font_style.
482 * Since: 1.0
484 void
485 adg_font_style_set_slant(AdgFontStyle *font_style,
486 cairo_font_slant_t slant)
488 g_return_if_fail(ADG_IS_FONT_STYLE(font_style));
489 g_object_set(font_style, "slant", slant, NULL);
493 * adg_font_style_get_slant:
494 * @font_style: an #AdgFontStyle object
496 * Gets the slant variant of @font_style.
498 * Returns: (type gint) (transfer none): the slant variant.
500 * Since: 1.0
502 cairo_font_slant_t
503 adg_font_style_get_slant(AdgFontStyle *font_style)
505 AdgFontStylePrivate *data;
507 g_return_val_if_fail(ADG_IS_FONT_STYLE(font_style),
508 CAIRO_FONT_SLANT_NORMAL);
510 data = font_style->data;
512 return data->slant;
516 * adg_font_style_set_weight:
517 * @font_style: an #AdgFontStyle object
518 * @weight: (type gint): the new weight
520 * Sets a new weight variant on @font_style.
522 * Since: 1.0
524 void
525 adg_font_style_set_weight(AdgFontStyle *font_style,
526 cairo_font_weight_t weight)
528 g_return_if_fail(ADG_IS_FONT_STYLE(font_style));
529 g_object_set(font_style, "weight", weight, NULL);
533 * adg_font_style_get_weight:
534 * @font_style: an #AdgFontStyle object
536 * Gets the weight variant of @font_style.
538 * Returns: (type gint) (transfer none): the weight variant.
540 * Since: 1.0
542 cairo_font_weight_t
543 adg_font_style_get_weight(AdgFontStyle *font_style)
545 AdgFontStylePrivate *data;
547 g_return_val_if_fail(ADG_IS_FONT_STYLE(font_style),
548 CAIRO_FONT_WEIGHT_NORMAL);
550 data = font_style->data;
552 return data->weight;
556 * adg_font_style_set_size:
557 * @font_style: an #AdgFontStyle object
558 * @size: the new size
560 * Sets a new size (in global space) on @font_style.
562 * Since: 1.0
564 void
565 adg_font_style_set_size(AdgFontStyle *font_style, gdouble size)
567 g_return_if_fail(ADG_IS_FONT_STYLE(font_style));
568 g_object_set(font_style, "size", size, NULL);
572 * adg_font_style_get_size:
573 * @font_style: an #AdgFontStyle object
575 * Gets the size (in global space) of @font_style.
577 * Returns: the size variant.
579 * Since: 1.0
581 gdouble
582 adg_font_style_get_size(AdgFontStyle *font_style)
584 AdgFontStylePrivate *data;
586 g_return_val_if_fail(ADG_IS_FONT_STYLE(font_style), 0.);
588 data = font_style->data;
590 return data->size;
594 * adg_font_style_set_antialias:
595 * @font_style: an #AdgFontStyle object
596 * @antialias: (type gint): the new antialias mode
598 * Sets a new antialias mode.
600 * Since: 1.0
602 void
603 adg_font_style_set_antialias(AdgFontStyle *font_style,
604 cairo_antialias_t antialias)
606 g_return_if_fail(ADG_IS_FONT_STYLE(font_style));
607 g_object_set(font_style, "antialias", antialias, NULL);
611 * adg_font_style_get_antialias:
612 * @font_style: an #AdgFontStyle object
614 * Gets the antialias mode used.
616 * Returns: (type gint) (transfer none): the requested antialias mode.
618 * Since: 1.0
620 cairo_antialias_t
621 adg_font_style_get_antialias(AdgFontStyle *font_style)
623 AdgFontStylePrivate *data;
625 g_return_val_if_fail(ADG_IS_FONT_STYLE(font_style),
626 CAIRO_ANTIALIAS_DEFAULT);
628 data = font_style->data;
630 return data->antialias;
634 * adg_font_style_set_subpixel_order:
635 * @font_style: an #AdgFontStyle object
636 * @subpixel_order: (type gint): the new subpixel order mode
638 * Sets a new subpixel order mode.
640 * Since: 1.0
642 void
643 adg_font_style_set_subpixel_order(AdgFontStyle *font_style,
644 cairo_subpixel_order_t subpixel_order)
646 g_return_if_fail(ADG_IS_FONT_STYLE(font_style));
647 g_object_set(font_style, "subpixel-order", subpixel_order, NULL);
651 * adg_font_style_get_subpixel_order:
652 * @font_style: an #AdgFontStyle object
654 * Gets the subpixel order mode used, that is the order of color elements
655 * within each pixel on the display device when rendering with an
656 * antialiasing mode of %CAIRO_ANTIALIAS_SUBPIXEL.
658 * Returns: (type gint) (transfer none): the requested subpixel order mode.
660 * Since: 1.0
662 cairo_subpixel_order_t
663 adg_font_style_get_subpixel_order(AdgFontStyle *font_style)
665 AdgFontStylePrivate *data;
667 g_return_val_if_fail(ADG_IS_FONT_STYLE(font_style),
668 CAIRO_SUBPIXEL_ORDER_DEFAULT);
670 data = font_style->data;
672 return data->subpixel_order;
676 * adg_font_style_set_hint_style:
677 * @font_style: an #AdgFontStyle object
678 * @hint_style: (type gint): the new hint style mode
680 * Sets a new hint style mode.
682 * Since: 1.0
684 void
685 adg_font_style_set_hint_style(AdgFontStyle *font_style,
686 cairo_hint_style_t hint_style)
688 g_return_if_fail(ADG_IS_FONT_STYLE(font_style));
689 g_object_set(font_style, "hint-style", hint_style, NULL);
693 * adg_font_style_get_hint_style:
694 * @font_style: an #AdgFontStyle object
696 * Gets the hint style mode used, that is how to fit outlines
697 * to the pixel grid in order to improve the appearance of the result.
699 * Returns: (type gint) (transfer none): the requested hint style mode.
701 * Since: 1.0
703 cairo_hint_style_t
704 adg_font_style_get_hint_style(AdgFontStyle *font_style)
706 AdgFontStylePrivate *data;
708 g_return_val_if_fail(ADG_IS_FONT_STYLE(font_style),
709 CAIRO_HINT_STYLE_DEFAULT);
711 data = font_style->data;
713 return data->hint_style;
717 * adg_font_style_set_hint_metrics:
718 * @font_style: an #AdgFontStyle object
719 * @hint_metrics: (type gint): the new hint metrics state
721 * Sets a new hint metrics state.
723 * Since: 1.0
725 void
726 adg_font_style_set_hint_metrics(AdgFontStyle *font_style,
727 cairo_hint_metrics_t hint_metrics)
729 g_return_if_fail(ADG_IS_FONT_STYLE(font_style));
730 g_object_set(font_style, "hint-metrics", hint_metrics, NULL);
734 * adg_font_style_get_hint_metrics:
735 * @font_style: an #AdgFontStyle object
737 * Gets the state on whether to hint font metrics.
739 * Returns: (type gint) (transfer none): the requested hint metrics state.
741 * Since: 1.0
743 cairo_hint_metrics_t
744 adg_font_style_get_hint_metrics(AdgFontStyle *font_style)
746 AdgFontStylePrivate *data;
748 g_return_val_if_fail(ADG_IS_FONT_STYLE(font_style),
749 CAIRO_HINT_METRICS_DEFAULT);
751 data = font_style->data;
753 return data->hint_metrics;
757 static void
758 _adg_invalidate(AdgStyle *style)
760 AdgFontStyle *font_style;
761 AdgFontStylePrivate *data;
763 font_style = (AdgFontStyle *) style;
764 data = font_style->data;
766 if (data->font != NULL) {
767 cairo_scaled_font_destroy(data->font);
768 data->font = NULL;
771 if (data->face == NULL) {
772 cairo_font_face_destroy(data->face);
773 data->face = NULL;
777 static void
778 _adg_apply(AdgStyle *style, AdgEntity *entity, cairo_t *cr)
780 AdgFontStyle *font_style;
781 AdgFontStylePrivate *data;
782 cairo_matrix_t ctm;
783 cairo_scaled_font_t *font;
785 font_style = (AdgFontStyle *) style;
786 data = font_style->data;
788 adg_entity_apply_dress(entity, data->color_dress, cr);
790 cairo_get_matrix(cr, &ctm);
791 font = adg_font_style_get_scaled_font((AdgFontStyle *) style, &ctm);
793 cairo_set_scaled_font(cr, font);