1 /* ADG - Automatic Drawing Generation
2 * Copyright (C) 2007,2008,2009 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-font-style.h"
38 #include "adg-font-style-private.h"
42 #define PARENT_OBJECT_CLASS ((GObjectClass *) adg_font_style_parent_class)
58 static void dispose (GObject
*object
);
59 static void get_property (GObject
*object
,
63 static void set_property (GObject
*object
,
67 static void apply (AdgStyle
*style
,
69 static gboolean
set_family (AdgFontStyle
*font_style
,
71 static gboolean
set_slant (AdgFontStyle
*font_style
,
72 cairo_font_slant_t slant
);
73 static gboolean
set_weight (AdgFontStyle
*font_style
,
74 cairo_font_weight_t weight
);
75 static gboolean
set_size (AdgFontStyle
*font_style
,
77 static gboolean
set_antialias (AdgFontStyle
*font_style
,
78 cairo_antialias_t antialias
);
79 static gboolean
set_subpixel_order (AdgFontStyle
*font_style
,
80 cairo_subpixel_order_t subpixel_order
);
81 static gboolean
set_hint_style (AdgFontStyle
*font_style
,
82 cairo_hint_style_t hint_style
);
83 static gboolean
set_hint_metrics (AdgFontStyle
*font_style
,
84 cairo_hint_metrics_t hint_metrics
);
85 static void unset_face (AdgFontStyle
*font_style
);
86 static void unset_font (AdgFontStyle
*font_style
);
89 G_DEFINE_TYPE(AdgFontStyle
, adg_font_style
, ADG_TYPE_STYLE
);
93 adg_font_style_class_init(AdgFontStyleClass
*klass
)
95 GObjectClass
*gobject_class
;
96 AdgStyleClass
*style_class
;
99 gobject_class
= (GObjectClass
*) klass
;
100 style_class
= (AdgStyleClass
*) klass
;
102 g_type_class_add_private(klass
, sizeof(AdgFontStylePrivate
));
104 gobject_class
->dispose
= dispose
;
105 gobject_class
->get_property
= get_property
;
106 gobject_class
->set_property
= set_property
;
108 style_class
->apply
= apply
;
110 param
= g_param_spec_string("family",
112 P_("The font family name, encoded in UTF-8"),
115 g_object_class_install_property(gobject_class
, PROP_FAMILY
, param
);
117 param
= g_param_spec_int("slant",
119 P_("Variant of a font face based on its slant"),
120 G_MININT
, G_MAXINT
, CAIRO_FONT_SLANT_NORMAL
,
122 g_object_class_install_property(gobject_class
, PROP_SLANT
, param
);
124 param
= g_param_spec_int("weight",
126 P_("Variant of a font face based on its weight"),
127 G_MININT
, G_MAXINT
, CAIRO_FONT_WEIGHT_NORMAL
,
129 g_object_class_install_property(gobject_class
, PROP_WEIGHT
, param
);
131 param
= g_param_spec_double("size",
133 P_("Font size in user space units"),
136 g_object_class_install_property(gobject_class
, PROP_SIZE
, param
);
138 param
= g_param_spec_int("antialias",
139 P_("Font Antialiasing Mode"),
140 P_("Type of antialiasing to do when rendering text"),
141 G_MININT
, G_MAXINT
, CAIRO_ANTIALIAS_DEFAULT
,
143 g_object_class_install_property(gobject_class
, PROP_ANTIALIAS
, param
);
145 param
= g_param_spec_int("subpixel-order",
146 P_("Font Subpixel Order"),
147 P_("The order of color elements within each pixel on the display device when rendering with subpixel antialiasing mode"),
149 CAIRO_SUBPIXEL_ORDER_DEFAULT
,
151 g_object_class_install_property(gobject_class
, PROP_SUBPIXEL_ORDER
, param
);
153 param
= g_param_spec_int("hint-style",
154 P_("Type of Hinting"),
155 P_("How outlines must fit to the pixel grid in order to improve the glyph appearance"),
156 G_MININT
, G_MAXINT
, CAIRO_HINT_STYLE_DEFAULT
,
158 g_object_class_install_property(gobject_class
, PROP_HINT_STYLE
, param
);
160 param
= g_param_spec_int("hint-metrics",
161 P_("Font Metric Hinting"),
162 P_("Whether to hint font metrics, that is align them to integer values in device space"),
164 CAIRO_HINT_METRICS_DEFAULT
,
166 g_object_class_install_property(gobject_class
, PROP_HINT_METRICS
, param
);
170 adg_font_style_init(AdgFontStyle
*font_style
)
172 AdgFontStylePrivate
*data
= G_TYPE_INSTANCE_GET_PRIVATE(font_style
,
174 AdgFontStylePrivate
);
177 data
->slant
= CAIRO_FONT_SLANT_NORMAL
;
178 data
->weight
= CAIRO_FONT_WEIGHT_NORMAL
;
180 data
->antialias
= CAIRO_ANTIALIAS_DEFAULT
;
181 data
->subpixel_order
= CAIRO_SUBPIXEL_ORDER_DEFAULT
;
182 data
->hint_style
= CAIRO_HINT_STYLE_DEFAULT
;
183 data
->hint_metrics
= CAIRO_HINT_METRICS_DEFAULT
;
186 font_style
->data
= data
;
190 dispose(GObject
*object
)
192 AdgFontStyle
*font_style
= (AdgFontStyle
*) object
;
194 unset_font(font_style
);
195 unset_face(font_style
);
197 if (PARENT_OBJECT_CLASS
->dispose
!= NULL
)
198 PARENT_OBJECT_CLASS
->dispose(object
);
203 get_property(GObject
*object
, guint prop_id
, GValue
*value
, GParamSpec
*pspec
)
205 AdgFontStylePrivate
*data
= ((AdgFontStyle
*) object
)->data
;
209 g_value_set_string(value
, data
->family
);
212 g_value_set_int(value
, data
->slant
);
215 g_value_set_int(value
, data
->weight
);
218 g_value_set_double(value
, data
->size
);
221 g_value_set_int(value
, data
->antialias
);
223 case PROP_SUBPIXEL_ORDER
:
224 g_value_set_int(value
, data
->subpixel_order
);
226 case PROP_HINT_STYLE
:
227 g_value_set_int(value
, data
->hint_style
);
229 case PROP_HINT_METRICS
:
230 g_value_set_int(value
, data
->hint_metrics
);
233 G_OBJECT_WARN_INVALID_PROPERTY_ID(object
, prop_id
, pspec
);
239 set_property(GObject
*object
,
240 guint prop_id
, const GValue
*value
, GParamSpec
*pspec
)
242 AdgFontStyle
*font_style
;
243 AdgFontStylePrivate
*data
;
245 font_style
= (AdgFontStyle
*) object
;
246 data
= font_style
->data
;
250 set_family(font_style
, g_value_get_string(value
));
253 set_slant(font_style
, g_value_get_int(value
));
256 set_weight(font_style
, g_value_get_int(value
));
259 set_size(font_style
, g_value_get_double(value
));
262 set_antialias(font_style
, g_value_get_int(value
));
264 case PROP_SUBPIXEL_ORDER
:
265 set_subpixel_order(font_style
, g_value_get_int(value
));
267 case PROP_HINT_STYLE
:
268 set_hint_style(font_style
, g_value_get_int(value
));
270 case PROP_HINT_METRICS
:
271 set_hint_metrics(font_style
, g_value_get_int(value
));
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 new font style
288 adg_font_style_new(void)
290 return g_object_new(ADG_TYPE_FONT_STYLE
, NULL
);
294 * adg_font_style_font:
295 * @font_style: an #AdgFontStyle object
297 * Gets the scaled font of @font_style. The returned font is
298 * owned by @font_style and must not be destroyed by the caller.
300 * Returns: the scaled font
302 cairo_scaled_font_t
*
303 adg_font_style_font(AdgFontStyle
*font_style
, const AdgMatrix
*ctm
)
305 AdgFontStylePrivate
*data
;
306 cairo_font_options_t
*options
;
309 data
= font_style
->data
;
311 /* Check for cached font */
312 if (data
->font
!= NULL
) {
315 cairo_scaled_font_get_ctm(data
->font
, &font_ctm
);
317 /* The scaled font is valid only if the two ctm match */
318 if (ctm
->xx
== font_ctm
.xx
&& ctm
->yy
== font_ctm
.yy
&&
319 ctm
->xy
== font_ctm
.xy
&& ctm
->yx
== font_ctm
.yx
)
322 /* No valid cache found: rebuild the scaled font */
323 unset_font(font_style
);
326 if (data
->face
== NULL
) {
327 const gchar
*family
= data
->family
!= NULL
? data
->family
: "";
329 data
->face
= cairo_toy_font_face_create(family
, data
->slant
,
333 cairo_matrix_init_scale(&matrix
, data
->size
, data
->size
);
334 options
= cairo_font_options_create();
336 cairo_font_options_set_antialias(options
, data
->antialias
);
337 cairo_font_options_set_subpixel_order(options
, data
->subpixel_order
);
338 cairo_font_options_set_hint_style(options
, data
->hint_style
);
339 cairo_font_options_set_hint_metrics(options
, data
->hint_metrics
);
341 data
->font
= cairo_scaled_font_create(data
->face
, &matrix
, ctm
, options
);
343 cairo_font_options_destroy(options
);
349 * adg_font_style_get_family:
350 * @font_style: an #AdgFontStyle object
352 * Gets the family of @font_style. The returned pointer refers to
353 * internally managed text that must not be modified or freed.
355 * Returns: the requested family
358 adg_font_style_get_family(AdgFontStyle
*font_style
)
360 AdgFontStylePrivate
*data
;
362 g_return_val_if_fail(ADG_IS_FONT_STYLE(font_style
), NULL
);
364 data
= font_style
->data
;
370 * adg_font_style_set_family:
371 * @font_style: an #AdgFontStyle object
372 * @family: the new family
377 adg_font_style_set_family(AdgFontStyle
*font_style
, const gchar
*family
)
379 g_return_if_fail(ADG_IS_FONT_STYLE(font_style
));
381 if (set_family(font_style
, family
))
382 g_object_notify((GObject
*) font_style
, "family");
386 * adg_font_style_get_slant:
387 * @font_style: an #AdgFontStyle object
389 * Gets the slant variant of @font_style.
391 * Returns: the slant variant
394 adg_font_style_get_slant(AdgFontStyle
*font_style
)
396 AdgFontStylePrivate
*data
;
398 g_return_val_if_fail(ADG_IS_FONT_STYLE(font_style
),
399 CAIRO_FONT_SLANT_NORMAL
);
401 data
= font_style
->data
;
407 * adg_font_style_set_slant:
408 * @font_style: an #AdgFontStyle object
409 * @slant: the new slant
411 * Sets a new slant variant on @font_style.
414 adg_font_style_set_slant(AdgFontStyle
*font_style
,
415 cairo_font_slant_t slant
)
417 g_return_if_fail(ADG_IS_FONT_STYLE(font_style
));
419 if (set_slant(font_style
, slant
))
420 g_object_notify((GObject
*) font_style
, "slant");
424 * adg_font_style_get_weight:
425 * @font_style: an #AdgFontStyle object
427 * Gets the weight variant of @font_style.
429 * Returns: the weight variant
432 adg_font_style_get_weight(AdgFontStyle
*font_style
)
434 AdgFontStylePrivate
*data
;
436 g_return_val_if_fail(ADG_IS_FONT_STYLE(font_style
),
437 CAIRO_FONT_WEIGHT_NORMAL
);
439 data
= font_style
->data
;
445 * adg_font_style_set_weight:
446 * @font_style: an #AdgFontStyle object
447 * @weight: the new weight
449 * Sets a new weight variant on @font_style.
452 adg_font_style_set_weight(AdgFontStyle
*font_style
,
453 cairo_font_weight_t weight
)
455 g_return_if_fail(ADG_IS_FONT_STYLE(font_style
));
457 if (set_weight(font_style
, weight
))
458 g_object_notify((GObject
*) font_style
, "weight");
462 * adg_font_style_get_size:
463 * @font_style: an #AdgFontStyle object
465 * Gets the size (in global space) of @font_style.
467 * Returns: the size variant
470 adg_font_style_get_size(AdgFontStyle
*font_style
)
472 AdgFontStylePrivate
*data
;
474 g_return_val_if_fail(ADG_IS_FONT_STYLE(font_style
), 0.);
476 data
= font_style
->data
;
482 * adg_font_style_set_size:
483 * @font_style: an #AdgFontStyle object
484 * @size: the new size
486 * Sets a new size (in global space) on @font_style.
489 adg_font_style_set_size(AdgFontStyle
*font_style
, gdouble size
)
491 g_return_if_fail(ADG_IS_FONT_STYLE(font_style
));
493 if (set_size(font_style
, size
))
494 g_object_notify((GObject
*) font_style
, "size");
498 * adg_font_style_get_antialias:
499 * @font_style: an #AdgFontStyle object
501 * Gets the antialias mode used.
503 * Returns: the requested antialias mode
506 adg_font_style_get_antialias(AdgFontStyle
*font_style
)
508 AdgFontStylePrivate
*data
;
510 g_return_val_if_fail(ADG_IS_FONT_STYLE(font_style
),
511 CAIRO_ANTIALIAS_DEFAULT
);
513 data
= font_style
->data
;
515 return data
->antialias
;
519 * adg_font_style_set_antialias:
520 * @font_style: an #AdgFontStyle object
521 * @antialias: the new antialias mode
523 * Sets a new antialias mode.
526 adg_font_style_set_antialias(AdgFontStyle
*font_style
,
527 cairo_antialias_t antialias
)
529 g_return_if_fail(ADG_IS_FONT_STYLE(font_style
));
531 if (set_antialias(font_style
, antialias
))
532 g_object_notify((GObject
*) font_style
, "antialias");
536 * adg_font_style_get_subpixel_order:
537 * @font_style: an #AdgFontStyle object
539 * Gets the subpixel order mode used, that is the order of color elements
540 * within each pixel on the display device when rendering with an
541 * antialiasing mode of %CAIRO_ANTIALIAS_SUBPIXEL.
543 * Returns: the requested subpixel order mode
545 cairo_subpixel_order_t
546 adg_font_style_get_subpixel_order(AdgFontStyle
*font_style
)
548 AdgFontStylePrivate
*data
;
550 g_return_val_if_fail(ADG_IS_FONT_STYLE(font_style
),
551 CAIRO_SUBPIXEL_ORDER_DEFAULT
);
553 data
= font_style
->data
;
555 return data
->subpixel_order
;
559 * adg_font_style_set_subpixel_order:
560 * @font_style: an #AdgFontStyle object
561 * @subpixel_order: the new subpixel order mode
563 * Sets a new subpixel order mode.
566 adg_font_style_set_subpixel_order(AdgFontStyle
*font_style
,
567 cairo_subpixel_order_t subpixel_order
)
569 g_return_if_fail(ADG_IS_FONT_STYLE(font_style
));
571 if (set_subpixel_order(font_style
, subpixel_order
))
572 g_object_notify((GObject
*) font_style
, "subpixel-order");
576 * adg_font_style_get_hint_style:
577 * @font_style: an #AdgFontStyle object
579 * Gets the hint style mode used, that is how to fit outlines
580 * to the pixel grid in order to improve the appearance of the result.
582 * Returns: the requested hint style mode
585 adg_font_style_get_hint_style(AdgFontStyle
*font_style
)
587 AdgFontStylePrivate
*data
;
589 g_return_val_if_fail(ADG_IS_FONT_STYLE(font_style
),
590 CAIRO_HINT_STYLE_DEFAULT
);
592 data
= font_style
->data
;
594 return data
->hint_style
;
598 * adg_font_style_set_hint_style:
599 * @font_style: an #AdgFontStyle object
600 * @hint_style: the new hint style mode
602 * Sets a new hint style mode.
605 adg_font_style_set_hint_style(AdgFontStyle
*font_style
,
606 cairo_hint_style_t hint_style
)
608 g_return_if_fail(ADG_IS_FONT_STYLE(font_style
));
610 if (set_hint_style(font_style
, hint_style
))
611 g_object_notify((GObject
*) font_style
, "hint-style");
615 * adg_font_style_get_hint_metrics:
616 * @font_style: an #AdgFontStyle object
618 * Gets the state on whether to hint font metrics.
620 * Returns: the requested hint metrics state
623 adg_font_style_get_hint_metrics(AdgFontStyle
*font_style
)
625 AdgFontStylePrivate
*data
;
627 g_return_val_if_fail(ADG_IS_FONT_STYLE(font_style
),
628 CAIRO_HINT_METRICS_DEFAULT
);
630 data
= font_style
->data
;
632 return data
->hint_metrics
;
636 * adg_font_style_set_hint_metrics:
637 * @font_style: an #AdgFontStyle object
638 * @hint_metrics: the new hint metrics state
640 * Sets a new hint metrics state.
643 adg_font_style_set_hint_metrics(AdgFontStyle
*font_style
,
644 cairo_hint_metrics_t hint_metrics
)
646 g_return_if_fail(ADG_IS_FONT_STYLE(font_style
));
648 if (set_hint_metrics(font_style
, hint_metrics
))
649 g_object_notify((GObject
*) font_style
, "hint-metrics");
654 apply(AdgStyle
*style
, cairo_t
*cr
)
657 cairo_scaled_font_t
*font
;
659 cairo_get_matrix(cr
, &ctm
);
660 font
= adg_font_style_font((AdgFontStyle
*) style
, &ctm
);
662 cairo_set_scaled_font(cr
, font
);
666 set_family(AdgFontStyle
*font_style
, const gchar
*family
)
668 AdgFontStylePrivate
*data
= font_style
->data
;
670 if (adg_strcmp(family
, data
->family
) == 0)
673 g_free(data
->family
);
674 data
->family
= g_strdup(family
);
675 unset_face(font_style
);
681 set_slant(AdgFontStyle
*font_style
, cairo_font_slant_t slant
)
683 AdgFontStylePrivate
*data
= font_style
->data
;
685 if (slant
== data
->slant
)
689 unset_face(font_style
);
695 set_weight(AdgFontStyle
*font_style
, cairo_font_weight_t weight
)
697 AdgFontStylePrivate
*data
= font_style
->data
;
699 if (weight
== data
->weight
)
702 data
->weight
= weight
;
703 unset_face(font_style
);
709 set_size(AdgFontStyle
*font_style
, gdouble size
)
711 AdgFontStylePrivate
*data
= font_style
->data
;
713 if (size
== data
->size
)
717 unset_font(font_style
);
723 set_antialias(AdgFontStyle
*font_style
, cairo_antialias_t antialias
)
725 AdgFontStylePrivate
*data
= font_style
->data
;
727 if (antialias
== data
->antialias
)
730 data
->antialias
= antialias
;
731 unset_font(font_style
);
737 set_subpixel_order(AdgFontStyle
*font_style
,
738 cairo_subpixel_order_t subpixel_order
)
740 AdgFontStylePrivate
*data
= font_style
->data
;
742 if (subpixel_order
== data
->subpixel_order
)
745 data
->subpixel_order
= subpixel_order
;
746 unset_font(font_style
);
752 set_hint_style(AdgFontStyle
*font_style
, cairo_hint_style_t hint_style
)
754 AdgFontStylePrivate
*data
= font_style
->data
;
756 if (hint_style
== data
->hint_style
)
759 data
->hint_style
= hint_style
;
760 unset_font(font_style
);
766 set_hint_metrics(AdgFontStyle
*font_style
, cairo_hint_metrics_t hint_metrics
)
768 AdgFontStylePrivate
*data
= font_style
->data
;
770 if (hint_metrics
== data
->hint_metrics
)
773 data
->hint_metrics
= hint_metrics
;
774 unset_font(font_style
);
780 unset_face(AdgFontStyle
*font_style
)
782 AdgFontStylePrivate
*data
= font_style
->data
;
784 if (data
->face
== NULL
)
787 /* Changing the face invalidates the scaled font too */
788 unset_font(font_style
);
790 cairo_font_face_destroy(data
->face
);
795 unset_font(AdgFontStyle
*font_style
)
797 AdgFontStylePrivate
*data
= font_style
->data
;
799 if (data
->font
== NULL
)
802 cairo_scaled_font_destroy(data
->font
);