1 /* ADG - Automatic Drawing Generation
2 * Copyright (C) 2007-2019 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_WITH_PRIVATE(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 gobject_class
->get_property
= _adg_get_property
;
94 gobject_class
->set_property
= _adg_set_property
;
96 style_class
->invalidate
= _adg_invalidate
;
97 style_class
->apply
= _adg_apply
;
99 param
= adg_param_spec_dress("color-dress",
101 P_("The fallback color dress to bind to this style"),
104 g_object_class_install_property(gobject_class
, PROP_COLOR_DRESS
, param
);
106 param
= g_param_spec_string("family",
108 P_("The font family name, encoded in UTF-8"),
111 g_object_class_install_property(gobject_class
, PROP_FAMILY
, param
);
113 param
= g_param_spec_int("slant",
115 P_("Variant of a font face based on its slant"),
116 G_MININT
, G_MAXINT
, CAIRO_FONT_SLANT_NORMAL
,
118 g_object_class_install_property(gobject_class
, PROP_SLANT
, param
);
120 param
= g_param_spec_int("weight",
122 P_("Variant of a font face based on its weight"),
123 G_MININT
, G_MAXINT
, CAIRO_FONT_WEIGHT_NORMAL
,
125 g_object_class_install_property(gobject_class
, PROP_WEIGHT
, param
);
127 param
= g_param_spec_double("size",
129 P_("Font size in user space units"),
132 g_object_class_install_property(gobject_class
, PROP_SIZE
, param
);
134 param
= g_param_spec_int("antialias",
135 P_("Font Antialiasing Mode"),
136 P_("Type of antialiasing to do when rendering text"),
137 G_MININT
, G_MAXINT
, CAIRO_ANTIALIAS_DEFAULT
,
139 g_object_class_install_property(gobject_class
, PROP_ANTIALIAS
, param
);
141 param
= g_param_spec_int("subpixel-order",
142 P_("Font Subpixel Order"),
143 P_("The order of color elements within each pixel on the display device when rendering with subpixel antialiasing mode"),
145 CAIRO_SUBPIXEL_ORDER_DEFAULT
,
147 g_object_class_install_property(gobject_class
, PROP_SUBPIXEL_ORDER
, param
);
149 param
= g_param_spec_int("hint-style",
150 P_("Type of Hinting"),
151 P_("How outlines must fit to the pixel grid in order to improve the glyph appearance"),
152 G_MININT
, G_MAXINT
, CAIRO_HINT_STYLE_DEFAULT
,
154 g_object_class_install_property(gobject_class
, PROP_HINT_STYLE
, param
);
156 param
= g_param_spec_int("hint-metrics",
157 P_("Font Metric Hinting"),
158 P_("Whether to hint font metrics, that is align them to integer values in device space"),
160 CAIRO_HINT_METRICS_DEFAULT
,
162 g_object_class_install_property(gobject_class
, PROP_HINT_METRICS
, param
);
166 adg_font_style_init(AdgFontStyle
*font_style
)
168 AdgFontStylePrivate
*data
= adg_font_style_get_instance_private(font_style
);
169 data
->color_dress
= ADG_DRESS_COLOR
;
171 data
->slant
= CAIRO_FONT_SLANT_NORMAL
;
172 data
->weight
= CAIRO_FONT_WEIGHT_NORMAL
;
174 data
->antialias
= CAIRO_ANTIALIAS_DEFAULT
;
175 data
->subpixel_order
= CAIRO_SUBPIXEL_ORDER_DEFAULT
;
176 data
->hint_style
= CAIRO_HINT_STYLE_DEFAULT
;
177 data
->hint_metrics
= CAIRO_HINT_METRICS_DEFAULT
;
182 _adg_get_property(GObject
*object
, guint prop_id
,
183 GValue
*value
, GParamSpec
*pspec
)
185 AdgFontStylePrivate
*data
= adg_font_style_get_instance_private((AdgFontStyle
*) object
);
188 case PROP_COLOR_DRESS
:
189 g_value_set_enum(value
, data
->color_dress
);
192 g_value_set_string(value
, data
->family
);
195 g_value_set_int(value
, data
->slant
);
198 g_value_set_int(value
, data
->weight
);
201 g_value_set_double(value
, data
->size
);
204 g_value_set_int(value
, data
->antialias
);
206 case PROP_SUBPIXEL_ORDER
:
207 g_value_set_int(value
, data
->subpixel_order
);
209 case PROP_HINT_STYLE
:
210 g_value_set_int(value
, data
->hint_style
);
212 case PROP_HINT_METRICS
:
213 g_value_set_int(value
, data
->hint_metrics
);
216 G_OBJECT_WARN_INVALID_PROPERTY_ID(object
, prop_id
, pspec
);
222 _adg_set_property(GObject
*object
, guint prop_id
,
223 const GValue
*value
, GParamSpec
*pspec
)
225 AdgStyle
*style
= (AdgStyle
*) object
;
226 AdgFontStyle
*font_style
= (AdgFontStyle
*) object
;
227 AdgFontStylePrivate
*data
= adg_font_style_get_instance_private(font_style
);
230 case PROP_COLOR_DRESS
:
231 data
->color_dress
= g_value_get_enum(value
);
234 g_free(data
->family
);
235 data
->family
= g_value_dup_string(value
);
236 adg_style_invalidate(style
);
239 data
->slant
= g_value_get_int(value
);
240 adg_style_invalidate(style
);
243 data
->weight
= g_value_get_int(value
);
244 adg_style_invalidate(style
);
247 data
->size
= g_value_get_double(value
);
248 adg_style_invalidate(style
);
251 data
->antialias
= g_value_get_int(value
);
252 adg_style_invalidate(style
);
254 case PROP_SUBPIXEL_ORDER
:
255 data
->subpixel_order
= g_value_get_int(value
);
256 adg_style_invalidate(style
);
258 case PROP_HINT_STYLE
:
259 data
->hint_style
= g_value_get_int(value
);
260 adg_style_invalidate(style
);
262 case PROP_HINT_METRICS
:
263 data
->hint_metrics
= g_value_get_int(value
);
264 adg_style_invalidate(style
);
267 G_OBJECT_WARN_INVALID_PROPERTY_ID(object
, prop_id
, pspec
);
274 * adg_font_style_new:
276 * Constructs a new font style initialized with default params.
278 * Returns: (transfer full): a newly created font style
283 adg_font_style_new(void)
285 return g_object_new(ADG_TYPE_FONT_STYLE
, NULL
);
289 * adg_font_style_new_options:
290 * @font_style: an #AdgFontStyle object
292 * Creates a new set of #cairo_font_options_t filled with the values
293 * picked from @font_style. The returned value must be freed with
294 * cairo_font_options_destroy().
296 * Returns: (transfer full): a newly allocated list of cairo font options.
300 cairo_font_options_t
*
301 adg_font_style_new_options(AdgFontStyle
*font_style
)
303 AdgFontStylePrivate
*data
;
304 cairo_font_options_t
*options
;
306 g_return_val_if_fail(ADG_IS_FONT_STYLE(font_style
), NULL
);
308 data
= adg_font_style_get_instance_private(font_style
);
309 options
= cairo_font_options_create();
311 /* Check for cached font */
312 if (data
->font
!= NULL
) {
313 cairo_scaled_font_get_font_options(data
->font
, options
);
315 cairo_font_options_set_antialias(options
, data
->antialias
);
316 cairo_font_options_set_subpixel_order(options
, data
->subpixel_order
);
317 cairo_font_options_set_hint_style(options
, data
->hint_style
);
318 cairo_font_options_set_hint_metrics(options
, data
->hint_metrics
);
325 * adg_font_style_get_scaled_font:
326 * @font_style: an #AdgFontStyle object
327 * @ctm: the current transformation matrix
329 * Gets the scaled font of @font_style. The returned font is
330 * owned by @font_style and must not be destroyed by the caller.
332 * Returns: (transfer none): the scaled font.
336 cairo_scaled_font_t
*
337 adg_font_style_get_scaled_font(AdgFontStyle
*font_style
,
338 const cairo_matrix_t
*ctm
)
340 AdgFontStylePrivate
*data
;
341 cairo_font_options_t
*options
;
342 cairo_matrix_t 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
= adg_font_style_get_instance_private(font_style
);
349 /* Check for cached font */
350 if (data
->font
!= NULL
) {
351 cairo_matrix_t 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
)
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: (transfer none): 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.
397 adg_font_style_set_color_dress(AdgFontStyle
*font_style
, AdgDress dress
)
399 g_return_if_fail(ADG_IS_FONT_STYLE(font_style
));
400 g_object_set(font_style
, "color-dress", dress
, NULL
);
404 * adg_font_style_get_color_dress:
405 * @font_style: an #AdgFontStyle
407 * Gets the color dress used by @font_style.
409 * Returns: (transfer none): the current color dress.
414 adg_font_style_get_color_dress(AdgFontStyle
*font_style
)
416 AdgFontStylePrivate
*data
;
418 g_return_val_if_fail(ADG_IS_FONT_STYLE(font_style
), ADG_DRESS_UNDEFINED
);
420 data
= adg_font_style_get_instance_private(font_style
);
421 return data
->color_dress
;
425 * adg_font_style_set_family:
426 * @font_style: an #AdgFontStyle object
427 * @family: (transfer none): the new family
434 adg_font_style_set_family(AdgFontStyle
*font_style
, const gchar
*family
)
436 g_return_if_fail(ADG_IS_FONT_STYLE(font_style
));
437 g_object_set(font_style
, "family", family
, NULL
);
441 * adg_font_style_get_family:
442 * @font_style: an #AdgFontStyle object
444 * Gets the family of @font_style. The returned pointer refers to
445 * internally managed text that must not be modified or freed.
447 * Returns: (transfer none): the requested family.
452 adg_font_style_get_family(AdgFontStyle
*font_style
)
454 AdgFontStylePrivate
*data
;
456 g_return_val_if_fail(ADG_IS_FONT_STYLE(font_style
), NULL
);
458 data
= adg_font_style_get_instance_private(font_style
);
463 * adg_font_style_set_slant:
464 * @font_style: an #AdgFontStyle object
465 * @slant: (type gint): the new slant
467 * Sets a new slant variant on @font_style.
472 adg_font_style_set_slant(AdgFontStyle
*font_style
,
473 cairo_font_slant_t slant
)
475 g_return_if_fail(ADG_IS_FONT_STYLE(font_style
));
476 g_object_set(font_style
, "slant", slant
, NULL
);
480 * adg_font_style_get_slant:
481 * @font_style: an #AdgFontStyle object
483 * Gets the slant variant of @font_style.
485 * Returns: (type gint): the slant variant.
490 adg_font_style_get_slant(AdgFontStyle
*font_style
)
492 AdgFontStylePrivate
*data
;
494 g_return_val_if_fail(ADG_IS_FONT_STYLE(font_style
),
495 CAIRO_FONT_SLANT_NORMAL
);
497 data
= adg_font_style_get_instance_private(font_style
);
502 * adg_font_style_set_weight:
503 * @font_style: an #AdgFontStyle object
504 * @weight: (type gint): the new weight
506 * Sets a new weight variant on @font_style.
511 adg_font_style_set_weight(AdgFontStyle
*font_style
,
512 cairo_font_weight_t weight
)
514 g_return_if_fail(ADG_IS_FONT_STYLE(font_style
));
515 g_object_set(font_style
, "weight", weight
, NULL
);
519 * adg_font_style_get_weight:
520 * @font_style: an #AdgFontStyle object
522 * Gets the weight variant of @font_style.
524 * Returns: (type gint): the weight variant.
529 adg_font_style_get_weight(AdgFontStyle
*font_style
)
531 AdgFontStylePrivate
*data
;
533 g_return_val_if_fail(ADG_IS_FONT_STYLE(font_style
),
534 CAIRO_FONT_WEIGHT_NORMAL
);
536 data
= adg_font_style_get_instance_private(font_style
);
541 * adg_font_style_set_size:
542 * @font_style: an #AdgFontStyle object
543 * @size: the new size
545 * Sets a new size (in global space) on @font_style.
550 adg_font_style_set_size(AdgFontStyle
*font_style
, gdouble size
)
552 g_return_if_fail(ADG_IS_FONT_STYLE(font_style
));
553 g_object_set(font_style
, "size", size
, NULL
);
557 * adg_font_style_get_size:
558 * @font_style: an #AdgFontStyle object
560 * Gets the size (in global space) of @font_style.
562 * Returns: the size variant.
567 adg_font_style_get_size(AdgFontStyle
*font_style
)
569 AdgFontStylePrivate
*data
;
571 g_return_val_if_fail(ADG_IS_FONT_STYLE(font_style
), 0.);
573 data
= adg_font_style_get_instance_private(font_style
);
578 * adg_font_style_set_antialias:
579 * @font_style: an #AdgFontStyle object
580 * @antialias: (type gint): the new antialias mode
582 * Sets a new antialias mode.
587 adg_font_style_set_antialias(AdgFontStyle
*font_style
,
588 cairo_antialias_t antialias
)
590 g_return_if_fail(ADG_IS_FONT_STYLE(font_style
));
591 g_object_set(font_style
, "antialias", antialias
, NULL
);
595 * adg_font_style_get_antialias:
596 * @font_style: an #AdgFontStyle object
598 * Gets the antialias mode used.
600 * Returns: (type gint): the requested antialias mode.
605 adg_font_style_get_antialias(AdgFontStyle
*font_style
)
607 AdgFontStylePrivate
*data
;
609 g_return_val_if_fail(ADG_IS_FONT_STYLE(font_style
),
610 CAIRO_ANTIALIAS_DEFAULT
);
612 data
= adg_font_style_get_instance_private(font_style
);
613 return data
->antialias
;
617 * adg_font_style_set_subpixel_order:
618 * @font_style: an #AdgFontStyle object
619 * @subpixel_order: (type gint): the new subpixel order mode
621 * Sets a new subpixel order mode.
626 adg_font_style_set_subpixel_order(AdgFontStyle
*font_style
,
627 cairo_subpixel_order_t subpixel_order
)
629 g_return_if_fail(ADG_IS_FONT_STYLE(font_style
));
630 g_object_set(font_style
, "subpixel-order", subpixel_order
, NULL
);
634 * adg_font_style_get_subpixel_order:
635 * @font_style: an #AdgFontStyle object
637 * Gets the subpixel order mode used, that is the order of color elements
638 * within each pixel on the display device when rendering with an
639 * antialiasing mode of %CAIRO_ANTIALIAS_SUBPIXEL.
641 * Returns: (type gint): the requested subpixel order mode.
645 cairo_subpixel_order_t
646 adg_font_style_get_subpixel_order(AdgFontStyle
*font_style
)
648 AdgFontStylePrivate
*data
;
650 g_return_val_if_fail(ADG_IS_FONT_STYLE(font_style
),
651 CAIRO_SUBPIXEL_ORDER_DEFAULT
);
653 data
= adg_font_style_get_instance_private(font_style
);
654 return data
->subpixel_order
;
658 * adg_font_style_set_hint_style:
659 * @font_style: an #AdgFontStyle object
660 * @hint_style: (type gint): the new hint style mode
662 * Sets a new hint style mode.
667 adg_font_style_set_hint_style(AdgFontStyle
*font_style
,
668 cairo_hint_style_t hint_style
)
670 g_return_if_fail(ADG_IS_FONT_STYLE(font_style
));
671 g_object_set(font_style
, "hint-style", hint_style
, NULL
);
675 * adg_font_style_get_hint_style:
676 * @font_style: an #AdgFontStyle object
678 * Gets the hint style mode used, that is how to fit outlines
679 * to the pixel grid in order to improve the appearance of the result.
681 * Returns: (type gint): the requested hint style mode.
686 adg_font_style_get_hint_style(AdgFontStyle
*font_style
)
688 AdgFontStylePrivate
*data
;
690 g_return_val_if_fail(ADG_IS_FONT_STYLE(font_style
),
691 CAIRO_HINT_STYLE_DEFAULT
);
693 data
= adg_font_style_get_instance_private(font_style
);
694 return data
->hint_style
;
698 * adg_font_style_set_hint_metrics:
699 * @font_style: an #AdgFontStyle object
700 * @hint_metrics: (type gint): the new hint metrics state
702 * Sets a new hint metrics state.
707 adg_font_style_set_hint_metrics(AdgFontStyle
*font_style
,
708 cairo_hint_metrics_t hint_metrics
)
710 g_return_if_fail(ADG_IS_FONT_STYLE(font_style
));
711 g_object_set(font_style
, "hint-metrics", hint_metrics
, NULL
);
715 * adg_font_style_get_hint_metrics:
716 * @font_style: an #AdgFontStyle object
718 * Gets the state on whether to hint font metrics.
720 * Returns: (type gint): the requested hint metrics state.
725 adg_font_style_get_hint_metrics(AdgFontStyle
*font_style
)
727 AdgFontStylePrivate
*data
;
729 g_return_val_if_fail(ADG_IS_FONT_STYLE(font_style
),
730 CAIRO_HINT_METRICS_DEFAULT
);
732 data
= adg_font_style_get_instance_private(font_style
);
733 return data
->hint_metrics
;
738 _adg_invalidate(AdgStyle
*style
)
740 AdgFontStyle
*font_style
= (AdgFontStyle
*) style
;
741 AdgFontStylePrivate
*data
= adg_font_style_get_instance_private(font_style
);
743 if (data
->font
!= NULL
) {
744 cairo_scaled_font_destroy(data
->font
);
748 if (data
->face
== NULL
) {
749 cairo_font_face_destroy(data
->face
);
755 _adg_apply(AdgStyle
*style
, AdgEntity
*entity
, cairo_t
*cr
)
757 AdgFontStyle
*font_style
;
758 AdgFontStylePrivate
*data
;
760 cairo_scaled_font_t
*font
;
762 font_style
= (AdgFontStyle
*) style
;
763 data
= adg_font_style_get_instance_private(font_style
);
765 adg_entity_apply_dress(entity
, data
->color_dress
, cr
);
767 cairo_get_matrix(cr
, &ctm
);
768 font
= adg_font_style_get_scaled_font((AdgFontStyle
*) style
, &ctm
);
770 cairo_set_scaled_font(cr
, font
);