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.
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.
32 * All fields are private and should not be used directly.
33 * Use its public methods instead.
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
)
65 static void _adg_get_property (GObject
*object
,
69 static void _adg_set_property (GObject
*object
,
73 static void _adg_invalidate (AdgStyle
*style
);
74 static void _adg_apply (AdgStyle
*style
,
80 adg_font_style_class_init(AdgFontStyleClass
*klass
)
82 GObjectClass
*gobject_class
;
83 AdgStyleClass
*style_class
;
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",
99 P_("The fallback color dress to bind to this style"),
102 g_object_class_install_property(gobject_class
, PROP_COLOR_DRESS
, param
);
104 param
= g_param_spec_string("family",
106 P_("The font family name, encoded in UTF-8"),
109 g_object_class_install_property(gobject_class
, PROP_FAMILY
, param
);
111 param
= g_param_spec_int("slant",
113 P_("Variant of a font face based on its slant"),
114 G_MININT
, G_MAXINT
, CAIRO_FONT_SLANT_NORMAL
,
116 g_object_class_install_property(gobject_class
, PROP_SLANT
, param
);
118 param
= g_param_spec_int("weight",
120 P_("Variant of a font face based on its weight"),
121 G_MININT
, G_MAXINT
, CAIRO_FONT_WEIGHT_NORMAL
,
123 g_object_class_install_property(gobject_class
, PROP_WEIGHT
, param
);
125 param
= g_param_spec_double("size",
127 P_("Font size in user space units"),
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
,
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"),
143 CAIRO_SUBPIXEL_ORDER_DEFAULT
,
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
,
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"),
158 CAIRO_HINT_METRICS_DEFAULT
,
160 g_object_class_install_property(gobject_class
, PROP_HINT_METRICS
, param
);
164 adg_font_style_init(AdgFontStyle
*font_style
)
166 AdgFontStylePrivate
*data
= G_TYPE_INSTANCE_GET_PRIVATE(font_style
,
168 AdgFontStylePrivate
);
170 data
->color_dress
= ADG_DRESS_COLOR
;
172 data
->slant
= CAIRO_FONT_SLANT_NORMAL
;
173 data
->weight
= CAIRO_FONT_WEIGHT_NORMAL
;
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
;
181 font_style
->data
= data
;
185 _adg_get_property(GObject
*object
, guint prop_id
,
186 GValue
*value
, GParamSpec
*pspec
)
188 AdgFontStylePrivate
*data
= ((AdgFontStyle
*) object
)->data
;
191 case PROP_COLOR_DRESS
:
192 g_value_set_int(value
, data
->color_dress
);
195 g_value_set_string(value
, data
->family
);
198 g_value_set_int(value
, data
->slant
);
201 g_value_set_int(value
, data
->weight
);
204 g_value_set_double(value
, data
->size
);
207 g_value_set_int(value
, data
->antialias
);
209 case PROP_SUBPIXEL_ORDER
:
210 g_value_set_int(value
, data
->subpixel_order
);
212 case PROP_HINT_STYLE
:
213 g_value_set_int(value
, data
->hint_style
);
215 case PROP_HINT_METRICS
:
216 g_value_set_int(value
, data
->hint_metrics
);
219 G_OBJECT_WARN_INVALID_PROPERTY_ID(object
, prop_id
, pspec
);
225 _adg_set_property(GObject
*object
, guint prop_id
,
226 const GValue
*value
, GParamSpec
*pspec
)
229 AdgFontStyle
*font_style
;
230 AdgFontStylePrivate
*data
;
232 style
= (AdgStyle
*) object
;
233 font_style
= (AdgFontStyle
*) object
;
234 data
= font_style
->data
;
237 case PROP_COLOR_DRESS
:
238 data
->color_dress
= g_value_get_int(value
);
241 g_free(data
->family
);
242 data
->family
= g_value_dup_string(value
);
243 adg_style_invalidate(style
);
246 data
->slant
= g_value_get_int(value
);
247 adg_style_invalidate(style
);
250 data
->weight
= g_value_get_int(value
);
251 adg_style_invalidate(style
);
254 data
->size
= g_value_get_double(value
);
255 adg_style_invalidate(style
);
258 data
->antialias
= g_value_get_int(value
);
259 adg_style_invalidate(style
);
261 case PROP_SUBPIXEL_ORDER
:
262 data
->subpixel_order
= g_value_get_int(value
);
263 adg_style_invalidate(style
);
265 case PROP_HINT_STYLE
:
266 data
->hint_style
= g_value_get_int(value
);
267 adg_style_invalidate(style
);
269 case PROP_HINT_METRICS
:
270 data
->hint_metrics
= g_value_get_int(value
);
271 adg_style_invalidate(style
);
274 G_OBJECT_WARN_INVALID_PROPERTY_ID(object
, prop_id
, pspec
);
281 * adg_font_style_new:
283 * Constructs a new font style initialized with default params.
285 * Returns: a newly created font style
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
);
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
);
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
;
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
) {
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
)
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
,
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
);
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
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.
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
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
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
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
;
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.
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
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
;
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.
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
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
;
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.
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
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
;
563 * adg_font_style_set_antialias:
564 * @font_style: an #AdgFontStyle object
565 * @antialias: the new antialias mode
567 * Sets a new antialias mode.
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
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.
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.
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
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.
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
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
;
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
);
724 if (data
->face
== NULL
) {
725 cairo_font_face_destroy(data
->face
);
731 _adg_apply(AdgStyle
*style
, AdgEntity
*entity
, cairo_t
*cr
)
733 AdgFontStyle
*font_style
;
734 AdgFontStylePrivate
*data
;
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
);