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.
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.
34 * All fields are private and should not be used directly.
35 * Use its public methods instead.
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
)
69 static void _adg_get_property (GObject
*object
,
73 static void _adg_set_property (GObject
*object
,
77 static void _adg_invalidate (AdgStyle
*style
);
78 static void _adg_apply (AdgStyle
*style
,
84 adg_font_style_class_init(AdgFontStyleClass
*klass
)
86 GObjectClass
*gobject_class
;
87 AdgStyleClass
*style_class
;
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",
103 P_("The fallback color dress to bind to this style"),
106 g_object_class_install_property(gobject_class
, PROP_COLOR_DRESS
, param
);
108 param
= g_param_spec_string("family",
110 P_("The font family name, encoded in UTF-8"),
113 g_object_class_install_property(gobject_class
, PROP_FAMILY
, param
);
115 param
= g_param_spec_int("slant",
117 P_("Variant of a font face based on its slant"),
118 G_MININT
, G_MAXINT
, CAIRO_FONT_SLANT_NORMAL
,
120 g_object_class_install_property(gobject_class
, PROP_SLANT
, param
);
122 param
= g_param_spec_int("weight",
124 P_("Variant of a font face based on its weight"),
125 G_MININT
, G_MAXINT
, CAIRO_FONT_WEIGHT_NORMAL
,
127 g_object_class_install_property(gobject_class
, PROP_WEIGHT
, param
);
129 param
= g_param_spec_double("size",
131 P_("Font size in user space units"),
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
,
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"),
147 CAIRO_SUBPIXEL_ORDER_DEFAULT
,
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
,
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"),
162 CAIRO_HINT_METRICS_DEFAULT
,
164 g_object_class_install_property(gobject_class
, PROP_HINT_METRICS
, param
);
168 adg_font_style_init(AdgFontStyle
*font_style
)
170 AdgFontStylePrivate
*data
= G_TYPE_INSTANCE_GET_PRIVATE(font_style
,
172 AdgFontStylePrivate
);
174 data
->color_dress
= ADG_DRESS_COLOR
;
176 data
->slant
= CAIRO_FONT_SLANT_NORMAL
;
177 data
->weight
= CAIRO_FONT_WEIGHT_NORMAL
;
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
;
185 font_style
->data
= data
;
189 _adg_get_property(GObject
*object
, guint prop_id
,
190 GValue
*value
, GParamSpec
*pspec
)
192 AdgFontStylePrivate
*data
= ((AdgFontStyle
*) object
)->data
;
195 case PROP_COLOR_DRESS
:
196 g_value_set_enum(value
, data
->color_dress
);
199 g_value_set_string(value
, data
->family
);
202 g_value_set_int(value
, data
->slant
);
205 g_value_set_int(value
, data
->weight
);
208 g_value_set_double(value
, data
->size
);
211 g_value_set_int(value
, data
->antialias
);
213 case PROP_SUBPIXEL_ORDER
:
214 g_value_set_int(value
, data
->subpixel_order
);
216 case PROP_HINT_STYLE
:
217 g_value_set_int(value
, data
->hint_style
);
219 case PROP_HINT_METRICS
:
220 g_value_set_int(value
, data
->hint_metrics
);
223 G_OBJECT_WARN_INVALID_PROPERTY_ID(object
, prop_id
, pspec
);
229 _adg_set_property(GObject
*object
, guint prop_id
,
230 const GValue
*value
, GParamSpec
*pspec
)
233 AdgFontStyle
*font_style
;
234 AdgFontStylePrivate
*data
;
236 style
= (AdgStyle
*) object
;
237 font_style
= (AdgFontStyle
*) object
;
238 data
= font_style
->data
;
241 case PROP_COLOR_DRESS
:
242 data
->color_dress
= g_value_get_enum(value
);
245 g_free(data
->family
);
246 data
->family
= g_value_dup_string(value
);
247 adg_style_invalidate(style
);
250 data
->slant
= g_value_get_int(value
);
251 adg_style_invalidate(style
);
254 data
->weight
= g_value_get_int(value
);
255 adg_style_invalidate(style
);
258 data
->size
= g_value_get_double(value
);
259 adg_style_invalidate(style
);
262 data
->antialias
= g_value_get_int(value
);
263 adg_style_invalidate(style
);
265 case PROP_SUBPIXEL_ORDER
:
266 data
->subpixel_order
= g_value_get_int(value
);
267 adg_style_invalidate(style
);
269 case PROP_HINT_STYLE
:
270 data
->hint_style
= g_value_get_int(value
);
271 adg_style_invalidate(style
);
273 case PROP_HINT_METRICS
:
274 data
->hint_metrics
= g_value_get_int(value
);
275 adg_style_invalidate(style
);
278 G_OBJECT_WARN_INVALID_PROPERTY_ID(object
, prop_id
, pspec
);
285 * adg_font_style_new:
287 * Constructs a new font style initialized with default params.
289 * Returns: (transfer full): a newly created font style
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.
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
);
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
);
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.
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
)
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
,
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
);
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
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.
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.
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
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.
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
;
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.
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.
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
;
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.
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.
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
;
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.
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.
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
;
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.
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.
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.
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.
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.
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.
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.
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.
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
;
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
);
771 if (data
->face
== NULL
) {
772 cairo_font_face_destroy(data
->face
);
778 _adg_apply(AdgStyle
*style
, AdgEntity
*entity
, cairo_t
*cr
)
780 AdgFontStyle
*font_style
;
781 AdgFontStylePrivate
*data
;
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
);