[tests] Implemented basic CpmlPrimitive test
[adg.git] / src / adg / adg-font-style.c
blob7807d839daa45b4e6bed88cbb789d024e93c20e8
1 /* ADG - Automatic Drawing Generation
2 * Copyright (C) 2007,2008,2009,2010,2011 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.
29 /**
30 * AdgFontStyle:
32 * All fields are private and should not be used directly.
33 * Use its public methods instead.
34 **/
37 #include "adg-internal.h"
38 #include "adg-style.h"
39 #include "adg-dress.h"
40 #include "adg-dress-builtins.h"
42 #include "adg-font-style.h"
43 #include "adg-font-style-private.h"
46 #define _ADG_OLD_OBJECT_CLASS ((GObjectClass *) adg_font_style_parent_class)
49 G_DEFINE_TYPE(AdgFontStyle, adg_font_style, ADG_TYPE_STYLE)
51 enum {
52 PROP_0,
53 PROP_COLOR_DRESS,
54 PROP_FAMILY,
55 PROP_SLANT,
56 PROP_WEIGHT,
57 PROP_SIZE,
58 PROP_ANTIALIAS,
59 PROP_SUBPIXEL_ORDER,
60 PROP_HINT_STYLE,
61 PROP_HINT_METRICS
65 static void _adg_get_property (GObject *object,
66 guint prop_id,
67 GValue *value,
68 GParamSpec *pspec);
69 static void _adg_set_property (GObject *object,
70 guint prop_id,
71 const GValue *value,
72 GParamSpec *pspec);
73 static void _adg_invalidate (AdgStyle *style);
74 static void _adg_apply (AdgStyle *style,
75 AdgEntity *entity,
76 cairo_t *cr);
79 static void
80 adg_font_style_class_init(AdgFontStyleClass *klass)
82 GObjectClass *gobject_class;
83 AdgStyleClass *style_class;
84 GParamSpec *param;
86 gobject_class = (GObjectClass *) klass;
87 style_class = (AdgStyleClass *) klass;
89 g_type_class_add_private(klass, sizeof(AdgFontStylePrivate));
91 gobject_class->get_property = _adg_get_property;
92 gobject_class->set_property = _adg_set_property;
94 style_class->invalidate = _adg_invalidate;
95 style_class->apply = _adg_apply;
97 param = adg_param_spec_dress("color-dress",
98 P_("Color Dress"),
99 P_("The fallback color dress to bind to this style"),
100 ADG_DRESS_COLOR,
101 G_PARAM_READWRITE);
102 g_object_class_install_property(gobject_class, PROP_COLOR_DRESS, param);
104 param = g_param_spec_string("family",
105 P_("Font Family"),
106 P_("The font family name, encoded in UTF-8"),
107 NULL,
108 G_PARAM_READWRITE);
109 g_object_class_install_property(gobject_class, PROP_FAMILY, param);
111 param = g_param_spec_int("slant",
112 P_("Font Slant"),
113 P_("Variant of a font face based on its slant"),
114 G_MININT, G_MAXINT, CAIRO_FONT_SLANT_NORMAL,
115 G_PARAM_READWRITE);
116 g_object_class_install_property(gobject_class, PROP_SLANT, param);
118 param = g_param_spec_int("weight",
119 P_("Font Weight"),
120 P_("Variant of a font face based on its weight"),
121 G_MININT, G_MAXINT, CAIRO_FONT_WEIGHT_NORMAL,
122 G_PARAM_READWRITE);
123 g_object_class_install_property(gobject_class, PROP_WEIGHT, param);
125 param = g_param_spec_double("size",
126 P_("Font Size"),
127 P_("Font size in user space units"),
128 0, G_MAXDOUBLE, 10,
129 G_PARAM_READWRITE);
130 g_object_class_install_property(gobject_class, PROP_SIZE, param);
132 param = g_param_spec_int("antialias",
133 P_("Font Antialiasing Mode"),
134 P_("Type of antialiasing to do when rendering text"),
135 G_MININT, G_MAXINT, CAIRO_ANTIALIAS_DEFAULT,
136 G_PARAM_READWRITE);
137 g_object_class_install_property(gobject_class, PROP_ANTIALIAS, param);
139 param = g_param_spec_int("subpixel-order",
140 P_("Font Subpixel Order"),
141 P_("The order of color elements within each pixel on the display device when rendering with subpixel antialiasing mode"),
142 G_MININT, G_MAXINT,
143 CAIRO_SUBPIXEL_ORDER_DEFAULT,
144 G_PARAM_READWRITE);
145 g_object_class_install_property(gobject_class, PROP_SUBPIXEL_ORDER, param);
147 param = g_param_spec_int("hint-style",
148 P_("Type of Hinting"),
149 P_("How outlines must fit to the pixel grid in order to improve the glyph appearance"),
150 G_MININT, G_MAXINT, CAIRO_HINT_STYLE_DEFAULT,
151 G_PARAM_READWRITE);
152 g_object_class_install_property(gobject_class, PROP_HINT_STYLE, param);
154 param = g_param_spec_int("hint-metrics",
155 P_("Font Metric Hinting"),
156 P_("Whether to hint font metrics, that is align them to integer values in device space"),
157 G_MININT, G_MAXINT,
158 CAIRO_HINT_METRICS_DEFAULT,
159 G_PARAM_READWRITE);
160 g_object_class_install_property(gobject_class, PROP_HINT_METRICS, param);
163 static void
164 adg_font_style_init(AdgFontStyle *font_style)
166 AdgFontStylePrivate *data = G_TYPE_INSTANCE_GET_PRIVATE(font_style,
167 ADG_TYPE_FONT_STYLE,
168 AdgFontStylePrivate);
170 data->color_dress = ADG_DRESS_COLOR;
171 data->family = NULL;
172 data->slant = CAIRO_FONT_SLANT_NORMAL;
173 data->weight = CAIRO_FONT_WEIGHT_NORMAL;
174 data->size = 10;
175 data->antialias = CAIRO_ANTIALIAS_DEFAULT;
176 data->subpixel_order = CAIRO_SUBPIXEL_ORDER_DEFAULT;
177 data->hint_style = CAIRO_HINT_STYLE_DEFAULT;
178 data->hint_metrics = CAIRO_HINT_METRICS_DEFAULT;
179 data->font = NULL;
181 font_style->data = data;
184 static void
185 _adg_get_property(GObject *object, guint prop_id,
186 GValue *value, GParamSpec *pspec)
188 AdgFontStylePrivate *data = ((AdgFontStyle *) object)->data;
190 switch (prop_id) {
191 case PROP_COLOR_DRESS:
192 g_value_set_int(value, data->color_dress);
193 break;
194 case PROP_FAMILY:
195 g_value_set_string(value, data->family);
196 break;
197 case PROP_SLANT:
198 g_value_set_int(value, data->slant);
199 break;
200 case PROP_WEIGHT:
201 g_value_set_int(value, data->weight);
202 break;
203 case PROP_SIZE:
204 g_value_set_double(value, data->size);
205 break;
206 case PROP_ANTIALIAS:
207 g_value_set_int(value, data->antialias);
208 break;
209 case PROP_SUBPIXEL_ORDER:
210 g_value_set_int(value, data->subpixel_order);
211 break;
212 case PROP_HINT_STYLE:
213 g_value_set_int(value, data->hint_style);
214 break;
215 case PROP_HINT_METRICS:
216 g_value_set_int(value, data->hint_metrics);
217 break;
218 default:
219 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
220 break;
224 static void
225 _adg_set_property(GObject *object, guint prop_id,
226 const GValue *value, GParamSpec *pspec)
228 AdgStyle *style;
229 AdgFontStyle *font_style;
230 AdgFontStylePrivate *data;
232 style = (AdgStyle *) object;
233 font_style = (AdgFontStyle *) object;
234 data = font_style->data;
236 switch (prop_id) {
237 case PROP_COLOR_DRESS:
238 data->color_dress = g_value_get_int(value);
239 break;
240 case PROP_FAMILY:
241 g_free(data->family);
242 data->family = g_value_dup_string(value);
243 adg_style_invalidate(style);
244 break;
245 case PROP_SLANT:
246 data->slant = g_value_get_int(value);
247 adg_style_invalidate(style);
248 break;
249 case PROP_WEIGHT:
250 data->weight = g_value_get_int(value);
251 adg_style_invalidate(style);
252 break;
253 case PROP_SIZE:
254 data->size = g_value_get_double(value);
255 adg_style_invalidate(style);
256 break;
257 case PROP_ANTIALIAS:
258 data->antialias = g_value_get_int(value);
259 adg_style_invalidate(style);
260 break;
261 case PROP_SUBPIXEL_ORDER:
262 data->subpixel_order = g_value_get_int(value);
263 adg_style_invalidate(style);
264 break;
265 case PROP_HINT_STYLE:
266 data->hint_style = g_value_get_int(value);
267 adg_style_invalidate(style);
268 break;
269 case PROP_HINT_METRICS:
270 data->hint_metrics = g_value_get_int(value);
271 adg_style_invalidate(style);
272 break;
273 default:
274 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
275 break;
281 * adg_font_style_new:
283 * Constructs a new font style initialized with default params.
285 * Returns: a newly created font style
287 AdgFontStyle *
288 adg_font_style_new(void)
290 return g_object_new(ADG_TYPE_FONT_STYLE, NULL);
294 * adg_font_style_new_options:
295 * @font_style: an #AdgFontStyle object
297 * Creates a new set of #cairo_font_options_t filled with the values
298 * picked from @font_style. The returned value must be freed with
299 * cairo_font_options_destroy().
301 * Returns: a newly allocated list of cairo font options
303 cairo_font_options_t *
304 adg_font_style_new_options(AdgFontStyle *font_style)
306 AdgFontStylePrivate *data;
307 cairo_font_options_t *options;
309 g_return_val_if_fail(ADG_IS_FONT_STYLE(font_style), NULL);
311 data = font_style->data;
312 options = cairo_font_options_create();
314 /* Check for cached font */
315 if (data->font != NULL) {
316 cairo_scaled_font_get_font_options(data->font, options);
317 } else {
318 cairo_font_options_set_antialias(options, data->antialias);
319 cairo_font_options_set_subpixel_order(options, data->subpixel_order);
320 cairo_font_options_set_hint_style(options, data->hint_style);
321 cairo_font_options_set_hint_metrics(options, data->hint_metrics);
324 return options;
328 * adg_font_style_get_scaled_font:
329 * @font_style: an #AdgFontStyle object
330 * @ctm: the current transformation matrix
332 * Gets the scaled font of @font_style. The returned font is
333 * owned by @font_style and must not be destroyed by the caller.
335 * Returns: the scaled font
337 cairo_scaled_font_t *
338 adg_font_style_get_scaled_font(AdgFontStyle *font_style, const AdgMatrix *ctm)
340 AdgFontStylePrivate *data;
341 cairo_font_options_t *options;
342 AdgMatrix matrix;
344 g_return_val_if_fail(ADG_IS_FONT_STYLE(font_style), NULL);
345 g_return_val_if_fail(ctm != NULL, NULL);
347 data = font_style->data;
349 /* Check for cached font */
350 if (data->font != NULL) {
351 AdgMatrix font_ctm;
353 cairo_scaled_font_get_ctm(data->font, &font_ctm);
355 /* The scaled font is valid only if the two ctm match */
356 if (ctm->xx == font_ctm.xx && ctm->yy == font_ctm.yy &&
357 ctm->xy == font_ctm.xy && ctm->yx == font_ctm.yx)
358 return data->font;
360 /* No valid cache found: rebuild the scaled font */
361 adg_style_invalidate((AdgStyle *) font_style);
364 if (data->face == NULL) {
365 const gchar *family = data->family != NULL ? data->family : "";
367 data->face = cairo_toy_font_face_create(family, data->slant,
368 data->weight);
371 cairo_matrix_init_scale(&matrix, data->size, data->size);
372 options = adg_font_style_new_options(font_style);
373 data->font = cairo_scaled_font_create(data->face, &matrix, ctm, options);
374 cairo_font_options_destroy(options);
376 return data->font;
380 * adg_font_style_set_color_dress:
381 * @font_style: an #AdgFontStyle
382 * @dress: the new color dress to use
384 * Sets a new color dress on @font_style. The new dress
385 * should be related to the original dress: you cannot
386 * set a dress used for font styles to a dress managing
387 * fonts.
389 * The validation of the new dress is done by calling
390 * adg_dress_are_related() with @dress and the previous
391 * dress as arguments: check out its documentation for
392 * details on what is a related dress.
394 void
395 adg_font_style_set_color_dress(AdgFontStyle *font_style, AdgDress dress)
397 g_return_if_fail(ADG_IS_FONT_STYLE(font_style));
398 g_object_set(font_style, "color-dress", dress, NULL);
402 * adg_font_style_get_color_dress:
403 * @font_style: an #AdgFontStyle
405 * Gets the color dress used by @font_style.
407 * Returns: the current color dress
409 AdgDress
410 adg_font_style_get_color_dress(AdgFontStyle *font_style)
412 AdgFontStylePrivate *data;
414 g_return_val_if_fail(ADG_IS_FONT_STYLE(font_style), ADG_DRESS_UNDEFINED);
416 data = font_style->data;
418 return data->color_dress;
422 * adg_font_style_set_family:
423 * @font_style: an #AdgFontStyle object
424 * @family: the new family
426 * Sets a new family.
428 void
429 adg_font_style_set_family(AdgFontStyle *font_style, const gchar *family)
431 g_return_if_fail(ADG_IS_FONT_STYLE(font_style));
432 g_object_set(font_style, "family", family, NULL);
436 * adg_font_style_get_family:
437 * @font_style: an #AdgFontStyle object
439 * Gets the family of @font_style. The returned pointer refers to
440 * internally managed text that must not be modified or freed.
442 * Returns: the requested family
444 const gchar *
445 adg_font_style_get_family(AdgFontStyle *font_style)
447 AdgFontStylePrivate *data;
449 g_return_val_if_fail(ADG_IS_FONT_STYLE(font_style), NULL);
451 data = font_style->data;
453 return data->family;
457 * adg_font_style_set_slant:
458 * @font_style: an #AdgFontStyle object
459 * @slant: the new slant
461 * Sets a new slant variant on @font_style.
463 void
464 adg_font_style_set_slant(AdgFontStyle *font_style,
465 cairo_font_slant_t slant)
467 g_return_if_fail(ADG_IS_FONT_STYLE(font_style));
468 g_object_set(font_style, "slant", slant, NULL);
472 * adg_font_style_get_slant:
473 * @font_style: an #AdgFontStyle object
475 * Gets the slant variant of @font_style.
477 * Returns: the slant variant
479 cairo_font_slant_t
480 adg_font_style_get_slant(AdgFontStyle *font_style)
482 AdgFontStylePrivate *data;
484 g_return_val_if_fail(ADG_IS_FONT_STYLE(font_style),
485 CAIRO_FONT_SLANT_NORMAL);
487 data = font_style->data;
489 return data->slant;
493 * adg_font_style_set_weight:
494 * @font_style: an #AdgFontStyle object
495 * @weight: the new weight
497 * Sets a new weight variant on @font_style.
499 void
500 adg_font_style_set_weight(AdgFontStyle *font_style,
501 cairo_font_weight_t weight)
503 g_return_if_fail(ADG_IS_FONT_STYLE(font_style));
504 g_object_set(font_style, "weight", weight, NULL);
508 * adg_font_style_get_weight:
509 * @font_style: an #AdgFontStyle object
511 * Gets the weight variant of @font_style.
513 * Returns: the weight variant
515 cairo_font_weight_t
516 adg_font_style_get_weight(AdgFontStyle *font_style)
518 AdgFontStylePrivate *data;
520 g_return_val_if_fail(ADG_IS_FONT_STYLE(font_style),
521 CAIRO_FONT_WEIGHT_NORMAL);
523 data = font_style->data;
525 return data->weight;
529 * adg_font_style_set_size:
530 * @font_style: an #AdgFontStyle object
531 * @size: the new size
533 * Sets a new size (in global space) on @font_style.
535 void
536 adg_font_style_set_size(AdgFontStyle *font_style, gdouble size)
538 g_return_if_fail(ADG_IS_FONT_STYLE(font_style));
539 g_object_set(font_style, "size", size, NULL);
543 * adg_font_style_get_size:
544 * @font_style: an #AdgFontStyle object
546 * Gets the size (in global space) of @font_style.
548 * Returns: the size variant
550 gdouble
551 adg_font_style_get_size(AdgFontStyle *font_style)
553 AdgFontStylePrivate *data;
555 g_return_val_if_fail(ADG_IS_FONT_STYLE(font_style), 0.);
557 data = font_style->data;
559 return data->size;
563 * adg_font_style_set_antialias:
564 * @font_style: an #AdgFontStyle object
565 * @antialias: the new antialias mode
567 * Sets a new antialias mode.
569 void
570 adg_font_style_set_antialias(AdgFontStyle *font_style,
571 cairo_antialias_t antialias)
573 g_return_if_fail(ADG_IS_FONT_STYLE(font_style));
574 g_object_set(font_style, "antialias", antialias, NULL);
578 * adg_font_style_get_antialias:
579 * @font_style: an #AdgFontStyle object
581 * Gets the antialias mode used.
583 * Returns: the requested antialias mode
585 cairo_antialias_t
586 adg_font_style_get_antialias(AdgFontStyle *font_style)
588 AdgFontStylePrivate *data;
590 g_return_val_if_fail(ADG_IS_FONT_STYLE(font_style),
591 CAIRO_ANTIALIAS_DEFAULT);
593 data = font_style->data;
595 return data->antialias;
599 * adg_font_style_set_subpixel_order:
600 * @font_style: an #AdgFontStyle object
601 * @subpixel_order: the new subpixel order mode
603 * Sets a new subpixel order mode.
605 void
606 adg_font_style_set_subpixel_order(AdgFontStyle *font_style,
607 cairo_subpixel_order_t subpixel_order)
609 g_return_if_fail(ADG_IS_FONT_STYLE(font_style));
610 g_object_set(font_style, "subpixel-order", subpixel_order, NULL);
614 * adg_font_style_get_subpixel_order:
615 * @font_style: an #AdgFontStyle object
617 * Gets the subpixel order mode used, that is the order of color elements
618 * within each pixel on the display device when rendering with an
619 * antialiasing mode of %CAIRO_ANTIALIAS_SUBPIXEL.
621 * Returns: the requested subpixel order mode
623 cairo_subpixel_order_t
624 adg_font_style_get_subpixel_order(AdgFontStyle *font_style)
626 AdgFontStylePrivate *data;
628 g_return_val_if_fail(ADG_IS_FONT_STYLE(font_style),
629 CAIRO_SUBPIXEL_ORDER_DEFAULT);
631 data = font_style->data;
633 return data->subpixel_order;
637 * adg_font_style_set_hint_style:
638 * @font_style: an #AdgFontStyle object
639 * @hint_style: the new hint style mode
641 * Sets a new hint style mode.
643 void
644 adg_font_style_set_hint_style(AdgFontStyle *font_style,
645 cairo_hint_style_t hint_style)
647 g_return_if_fail(ADG_IS_FONT_STYLE(font_style));
648 g_object_set(font_style, "hint-style", hint_style, NULL);
652 * adg_font_style_get_hint_style:
653 * @font_style: an #AdgFontStyle object
655 * Gets the hint style mode used, that is how to fit outlines
656 * to the pixel grid in order to improve the appearance of the result.
658 * Returns: the requested hint style mode
660 cairo_hint_style_t
661 adg_font_style_get_hint_style(AdgFontStyle *font_style)
663 AdgFontStylePrivate *data;
665 g_return_val_if_fail(ADG_IS_FONT_STYLE(font_style),
666 CAIRO_HINT_STYLE_DEFAULT);
668 data = font_style->data;
670 return data->hint_style;
674 * adg_font_style_set_hint_metrics:
675 * @font_style: an #AdgFontStyle object
676 * @hint_metrics: the new hint metrics state
678 * Sets a new hint metrics state.
680 void
681 adg_font_style_set_hint_metrics(AdgFontStyle *font_style,
682 cairo_hint_metrics_t hint_metrics)
684 g_return_if_fail(ADG_IS_FONT_STYLE(font_style));
685 g_object_set(font_style, "hint-metrics", hint_metrics, NULL);
689 * adg_font_style_get_hint_metrics:
690 * @font_style: an #AdgFontStyle object
692 * Gets the state on whether to hint font metrics.
694 * Returns: the requested hint metrics state
696 cairo_hint_metrics_t
697 adg_font_style_get_hint_metrics(AdgFontStyle *font_style)
699 AdgFontStylePrivate *data;
701 g_return_val_if_fail(ADG_IS_FONT_STYLE(font_style),
702 CAIRO_HINT_METRICS_DEFAULT);
704 data = font_style->data;
706 return data->hint_metrics;
710 static void
711 _adg_invalidate(AdgStyle *style)
713 AdgFontStyle *font_style;
714 AdgFontStylePrivate *data;
716 font_style = (AdgFontStyle *) style;
717 data = font_style->data;
719 if (data->font != NULL) {
720 cairo_scaled_font_destroy(data->font);
721 data->font = NULL;
724 if (data->face == NULL) {
725 cairo_font_face_destroy(data->face);
726 data->face = NULL;
730 static void
731 _adg_apply(AdgStyle *style, AdgEntity *entity, cairo_t *cr)
733 AdgFontStyle *font_style;
734 AdgFontStylePrivate *data;
735 AdgMatrix ctm;
736 cairo_scaled_font_t *font;
738 font_style = (AdgFontStyle *) style;
739 data = font_style->data;
741 adg_entity_apply_dress(entity, data->color_dress, cr);
743 cairo_get_matrix(cr, &ctm);
744 font = adg_font_style_get_scaled_font((AdgFontStyle *) style, &ctm);
746 cairo_set_scaled_font(cr, font);