Updated "GNU Library General License" to "GNU Lesser General License
[adg.git] / adg / adg-font-style.c
blob5fb58bcbf8c3498ae00a11553cff9e9117ade651
1 /* ADG - Automatic Drawing Generation
2 * Copyright (C) 2007-2008, 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.
20 /**
21 * SECTION:font-style
22 * @title: AdgFontStyle
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 #include "adg-font-style.h"
30 #include "adg-font-style-private.h"
31 #include "adg-intl.h"
32 #include "adg-util.h"
34 #define PARENT_CLASS ((AdgStyleClass *) adg_font_style_parent_class)
37 enum {
38 PROP_0,
39 PROP_FAMILY,
40 PROP_SLANT,
41 PROP_WEIGHT,
42 PROP_SIZE,
43 PROP_ANTIALIAS,
44 PROP_SUBPIXEL_ORDER,
45 PROP_HINT_STYLE,
46 PROP_HINT_METRICS
50 static void get_property (GObject *object,
51 guint prop_id,
52 GValue *value,
53 GParamSpec *pspec);
54 static void set_property (GObject *object,
55 guint prop_id,
56 const GValue *value,
57 GParamSpec *pspec);
58 static GPtrArray * get_pool (void);
59 static void apply (AdgStyle *style,
60 cairo_t *cr);
61 static void set_family (AdgFontStyle *font_style,
62 const gchar *family);
65 G_DEFINE_TYPE(AdgFontStyle, adg_font_style, ADG_TYPE_STYLE)
68 static void
69 adg_font_style_class_init(AdgFontStyleClass *klass)
71 GObjectClass *gobject_class;
72 AdgStyleClass *style_class;
73 GParamSpec *param;
75 gobject_class = (GObjectClass *) klass;
76 style_class = (AdgStyleClass *) klass;
78 g_type_class_add_private(klass, sizeof(AdgFontStylePrivate));
80 gobject_class->get_property = get_property;
81 gobject_class->set_property = set_property;
83 style_class->get_pool = get_pool;
84 style_class->apply = apply;
86 param = g_param_spec_string("family",
87 P_("Font Family"),
89 ("The font family name, encoded in UTF-8"),
90 NULL, G_PARAM_READWRITE);
91 g_object_class_install_property(gobject_class, PROP_FAMILY, param);
93 param = g_param_spec_int("slant",
94 P_("Font Slant"),
96 ("Variant of a font face based on its slant"),
97 G_MININT, G_MAXINT, CAIRO_FONT_SLANT_NORMAL,
98 G_PARAM_READWRITE);
99 g_object_class_install_property(gobject_class, PROP_SLANT, param);
101 param = g_param_spec_int("weight",
102 P_("Font Weight"),
104 ("Variant of a font face based on its weight"),
105 G_MININT, G_MAXINT, CAIRO_FONT_WEIGHT_NORMAL,
106 G_PARAM_READWRITE);
107 g_object_class_install_property(gobject_class, PROP_WEIGHT, param);
109 param = g_param_spec_double("size",
110 P_("Font Size"),
111 P_("Font size in user space units"),
112 0., G_MAXDOUBLE, 10., G_PARAM_READWRITE);
113 g_object_class_install_property(gobject_class, PROP_SIZE, param);
115 param = g_param_spec_int("antialias",
116 P_("Font Antialiasing Mode"),
118 ("Type of antialiasing to do when rendering text"),
119 G_MININT, G_MAXINT, CAIRO_ANTIALIAS_DEFAULT,
120 G_PARAM_READWRITE);
121 g_object_class_install_property(gobject_class, PROP_ANTIALIAS, param);
123 param = g_param_spec_int("subpixel-order",
124 P_("Font Subpixel Order"),
126 ("The order of color elements within each pixel on the display device when rendering with subpixel antialiasing mode"),
127 G_MININT, G_MAXINT,
128 CAIRO_SUBPIXEL_ORDER_DEFAULT,
129 G_PARAM_READWRITE);
130 g_object_class_install_property(gobject_class, PROP_SUBPIXEL_ORDER,
131 param);
133 param = g_param_spec_int("hint-style",
134 P_("Type of Hinting"),
136 ("How outlines must fit to the pixel grid in order to improve the glyph appearance"),
137 G_MININT, G_MAXINT, CAIRO_HINT_STYLE_DEFAULT,
138 G_PARAM_READWRITE);
139 g_object_class_install_property(gobject_class, PROP_HINT_STYLE, param);
141 param = g_param_spec_int("hint-metrics",
142 P_("Font Metric Hinting"),
144 ("Whether to hint font metrics, that is align them to integer values in device space"),
145 G_MININT, G_MAXINT,
146 CAIRO_HINT_METRICS_DEFAULT,
147 G_PARAM_READWRITE);
148 g_object_class_install_property(gobject_class, PROP_HINT_METRICS,
149 param);
152 static void
153 adg_font_style_init(AdgFontStyle *font_style)
155 AdgFontStylePrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE(font_style,
156 ADG_TYPE_FONT_STYLE,
157 AdgFontStylePrivate);
159 priv->family = NULL;
160 priv->slant = CAIRO_FONT_SLANT_NORMAL;
161 priv->weight = CAIRO_FONT_WEIGHT_NORMAL;
162 priv->size = 10.;
163 priv->antialias = CAIRO_ANTIALIAS_DEFAULT;
164 priv->subpixel_order = CAIRO_SUBPIXEL_ORDER_DEFAULT;
165 priv->hint_style = CAIRO_HINT_STYLE_DEFAULT;
166 priv->hint_metrics = CAIRO_HINT_METRICS_DEFAULT;
168 font_style->priv = priv;
171 static void
172 get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
174 AdgFontStyle *font_style = (AdgFontStyle *) object;
176 switch (prop_id) {
177 case PROP_FAMILY:
178 g_value_set_string(value, font_style->priv->family);
179 break;
180 case PROP_SLANT:
181 g_value_set_int(value, font_style->priv->slant);
182 break;
183 case PROP_WEIGHT:
184 g_value_set_int(value, font_style->priv->weight);
185 break;
186 case PROP_SIZE:
187 g_value_set_double(value, font_style->priv->size);
188 break;
189 case PROP_ANTIALIAS:
190 g_value_set_int(value, font_style->priv->antialias);
191 break;
192 case PROP_SUBPIXEL_ORDER:
193 g_value_set_int(value, font_style->priv->subpixel_order);
194 break;
195 case PROP_HINT_STYLE:
196 g_value_set_int(value, font_style->priv->hint_style);
197 break;
198 case PROP_HINT_METRICS:
199 g_value_set_int(value, font_style->priv->hint_metrics);
200 break;
201 default:
202 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
203 break;
207 static void
208 set_property(GObject *object,
209 guint prop_id, const GValue *value, GParamSpec *pspec)
211 AdgFontStyle *font_style = (AdgFontStyle *) object;
213 switch (prop_id) {
214 case PROP_FAMILY:
215 set_family(font_style, g_value_get_string(value));
216 break;
217 case PROP_SLANT:
218 font_style->priv->slant = g_value_get_int(value);
219 break;
220 case PROP_WEIGHT:
221 font_style->priv->weight = g_value_get_int(value);
222 break;
223 case PROP_SIZE:
224 font_style->priv->size = g_value_get_double(value);
225 break;
226 case PROP_ANTIALIAS:
227 font_style->priv->antialias = g_value_get_int(value);
228 break;
229 case PROP_SUBPIXEL_ORDER:
230 font_style->priv->subpixel_order = g_value_get_int(value);
231 break;
232 case PROP_HINT_STYLE:
233 font_style->priv->hint_style = g_value_get_int(value);
234 break;
235 case PROP_HINT_METRICS:
236 font_style->priv->hint_metrics = g_value_get_int(value);
237 break;
238 default:
239 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
240 break;
246 * adg_font_style_get_slot:
248 * Gets the slot id for this style class.
250 * Return value: the slot
252 AdgStyleSlot
253 adg_font_style_get_slot(void)
255 static AdgStyleSlot slot = -1;
257 if (G_UNLIKELY(slot < 0))
258 slot = adg_context_get_slot(ADG_TYPE_FONT_STYLE);
260 return slot;
264 * adg_font_style_new:
266 * Constructs a new font style initialized with default params.
268 * Return value: a new font style
270 AdgStyle *
271 adg_font_style_new(void)
273 return g_object_new(ADG_TYPE_FONT_STYLE, NULL);
277 * adg_font_style_get_family:
278 * @font_style: an #AdgFontStyle object
280 * Gets the family of @font_style. The returned pointer refers to
281 * internally managed text that must not be modified or freed.
283 * Return value: the requested family
285 const gchar *
286 adg_font_style_get_family(AdgFontStyle *font_style)
288 g_return_val_if_fail(ADG_IS_FONT_STYLE(font_style), NULL);
290 return font_style->priv->family;
294 * adg_font_style_set_family:
295 * @font_style: an #AdgFontStyle object
296 * @family: the new family
298 * Sets a new family.
300 void
301 adg_font_style_set_family(AdgFontStyle *font_style, const gchar *family)
303 g_return_if_fail(ADG_IS_FONT_STYLE(font_style));
305 set_family(font_style, family);
306 g_object_notify((GObject *) font_style, "family");
310 * adg_font_style_get_slant:
311 * @font_style: an #AdgFontStyle object
313 * Gets the slant variant of @font_style.
315 * Return value: the slant variant
317 cairo_font_slant_t
318 adg_font_style_get_slant(AdgFontStyle *font_style)
320 g_return_val_if_fail(ADG_IS_FONT_STYLE(font_style),
321 CAIRO_FONT_SLANT_NORMAL);
323 return font_style->priv->slant;
327 * adg_font_style_set_slant:
328 * @font_style: an #AdgFontStyle object
329 * @slant: the new slant
331 * Sets a new slant variant on @font_style.
333 void
334 adg_font_style_set_slant(AdgFontStyle *font_style,
335 cairo_font_slant_t slant)
337 g_return_if_fail(ADG_IS_FONT_STYLE(font_style));
339 font_style->priv->slant = slant;
340 g_object_notify((GObject *) font_style, "slant");
344 * adg_font_style_get_weight:
345 * @font_style: an #AdgFontStyle object
347 * Gets the weight variant of @font_style.
349 * Return value: the weight variant
351 cairo_font_weight_t
352 adg_font_style_get_weight(AdgFontStyle *font_style)
354 g_return_val_if_fail(ADG_IS_FONT_STYLE(font_style),
355 CAIRO_FONT_WEIGHT_NORMAL);
357 return font_style->priv->weight;
361 * adg_font_style_set_weight:
362 * @font_style: an #AdgFontStyle object
363 * @weight: the new weight
365 * Sets a new weight variant on @font_style.
367 void
368 adg_font_style_set_weight(AdgFontStyle *font_style,
369 cairo_font_weight_t weight)
371 g_return_if_fail(ADG_IS_FONT_STYLE(font_style));
373 font_style->priv->weight = weight;
374 g_object_notify((GObject *) font_style, "weight");
378 * adg_font_style_get_size:
379 * @font_style: an #AdgFontStyle object
381 * Gets the size (in paper units) of @font_style.
383 * Return value: the size variant
385 gdouble
386 adg_font_style_get_size(AdgFontStyle *font_style)
388 g_return_val_if_fail(ADG_IS_FONT_STYLE(font_style), 0.);
390 return font_style->priv->size;
394 * adg_font_style_set_size:
395 * @font_style: an #AdgFontStyle object
396 * @size: the new size
398 * Sets a new size (in paper units) on @font_style.
400 void
401 adg_font_style_set_size(AdgFontStyle *font_style, gdouble size)
403 g_return_if_fail(ADG_IS_FONT_STYLE(font_style));
405 font_style->priv->size = size;
406 g_object_notify((GObject *) font_style, "size");
410 * adg_font_style_get_antialias:
411 * @font_style: an #AdgFontStyle object
413 * Gets the antialias mode used.
415 * Return value: the requested antialias mode
417 cairo_antialias_t
418 adg_font_style_get_antialias(AdgFontStyle *font_style)
420 g_return_val_if_fail(ADG_IS_FONT_STYLE(font_style),
421 CAIRO_ANTIALIAS_DEFAULT);
423 return font_style->priv->antialias;
427 * adg_font_style_set_antialias:
428 * @font_style: an #AdgFontStyle object
429 * @antialias: the new antialias mode
431 * Sets a new antialias mode.
433 void
434 adg_font_style_set_antialias(AdgFontStyle *font_style,
435 cairo_antialias_t antialias)
437 g_return_if_fail(ADG_IS_FONT_STYLE(font_style));
439 font_style->priv->antialias = antialias;
440 g_object_notify((GObject *) font_style, "antialias");
444 * adg_font_style_get_subpixel_order:
445 * @font_style: an #AdgFontStyle object
447 * Gets the subpixel order mode used, that is the order of color elements
448 * within each pixel on the display device when rendering with an
449 * antialiasing mode of %CAIRO_ANTIALIAS_SUBPIXEL.
451 * Return value: the requested subpixel order mode
453 cairo_subpixel_order_t
454 adg_font_style_get_subpixel_order(AdgFontStyle *font_style)
456 g_return_val_if_fail(ADG_IS_FONT_STYLE(font_style),
457 CAIRO_SUBPIXEL_ORDER_DEFAULT);
459 return font_style->priv->subpixel_order;
463 * adg_font_style_set_subpixel_order:
464 * @font_style: an #AdgFontStyle object
465 * @subpixel_order: the new subpixel order mode
467 * Sets a new subpixel order mode.
469 void
470 adg_font_style_set_subpixel_order(AdgFontStyle *font_style,
471 cairo_subpixel_order_t subpixel_order)
473 g_return_if_fail(ADG_IS_FONT_STYLE(font_style));
475 font_style->priv->subpixel_order = subpixel_order;
476 g_object_notify((GObject *) font_style, "subpixel-order");
480 * adg_font_style_get_hint_style:
481 * @font_style: an #AdgFontStyle object
483 * Gets the hint style mode used, that is how to fit outlines
484 * to the pixel grid in order to improve the appearance of the result.
486 * Return value: the requested hint style mode
488 cairo_hint_style_t
489 adg_font_style_get_hint_style(AdgFontStyle *font_style)
491 g_return_val_if_fail(ADG_IS_FONT_STYLE(font_style),
492 CAIRO_HINT_STYLE_DEFAULT);
494 return font_style->priv->hint_style;
498 * adg_font_style_set_hint_style:
499 * @font_style: an #AdgFontStyle object
500 * @hint_style: the new hint style mode
502 * Sets a new hint style mode.
504 void
505 adg_font_style_set_hint_style(AdgFontStyle *font_style,
506 cairo_hint_style_t hint_style)
508 g_return_if_fail(ADG_IS_FONT_STYLE(font_style));
510 font_style->priv->hint_style = hint_style;
511 g_object_notify((GObject *) font_style, "hint-style");
515 * adg_font_style_get_hint_metrics:
516 * @font_style: an #AdgFontStyle object
518 * Gets the state on whether to hint font metrics.
520 * Return value: the requested hint metrics state
522 cairo_hint_metrics_t
523 adg_font_style_get_hint_metrics(AdgFontStyle *font_style)
525 g_return_val_if_fail(ADG_IS_FONT_STYLE(font_style),
526 CAIRO_HINT_METRICS_DEFAULT);
528 return font_style->priv->hint_metrics;
532 * adg_font_style_set_hint_metrics:
533 * @font_style: an #AdgFontStyle object
534 * @hint_metrics: the new hint metrics state
536 * Sets a new hint metrics state.
538 void
539 adg_font_style_set_hint_metrics(AdgFontStyle *font_style,
540 cairo_hint_metrics_t hint_metrics)
542 g_return_if_fail(ADG_IS_FONT_STYLE(font_style));
544 font_style->priv->hint_metrics = hint_metrics;
545 g_object_notify((GObject *) font_style, "hint-metrics");
549 static GPtrArray *
550 get_pool(void)
552 static GPtrArray *pool = NULL;
554 if (G_UNLIKELY(pool == NULL)) {
555 pool = g_ptr_array_sized_new(ADG_FONT_STYLE_LAST);
557 pool->pdata[ADG_FONT_STYLE_TEXT] =
558 g_object_new(ADG_TYPE_FONT_STYLE, "family", "Serif", "size",
559 14., NULL);
560 pool->pdata[ADG_FONT_STYLE_QUOTE] =
561 g_object_new(ADG_TYPE_FONT_STYLE, "family", "Sans", "size",
562 12., "weight", CAIRO_FONT_WEIGHT_BOLD, NULL);
563 pool->pdata[ADG_FONT_STYLE_TOLERANCE] =
564 g_object_new(ADG_TYPE_FONT_STYLE, "family", "Sans", "size", 8.,
565 NULL);
566 pool->pdata[ADG_FONT_STYLE_NOTE] =
567 g_object_new(ADG_TYPE_FONT_STYLE, "family", "Sans", "size",
568 12., NULL);
570 pool->len = ADG_FONT_STYLE_LAST;
573 return pool;
576 static void
577 apply(AdgStyle *style, cairo_t *cr)
579 AdgFontStyle *font_style;
580 cairo_font_options_t *options;
581 cairo_matrix_t matrix;
582 double size;
583 cairo_matrix_t font_matrix;
585 font_style = (AdgFontStyle *) style;
586 cairo_get_matrix(cr, &matrix);
587 size = font_style->priv->size;
589 PARENT_CLASS->apply(style, cr);
591 if (font_style->priv->family)
592 cairo_select_font_face(cr, font_style->priv->family,
593 font_style->priv->slant,
594 font_style->priv->weight);
596 cairo_matrix_init_scale(&font_matrix,
597 size / (matrix.xx - matrix.yx),
598 size / (matrix.yy + matrix.xy));
599 cairo_set_font_matrix(cr, &font_matrix);
601 options = cairo_font_options_create();
603 cairo_font_options_set_antialias(options, font_style->priv->antialias);
604 cairo_font_options_set_subpixel_order(options,
605 font_style->priv->
606 subpixel_order);
607 cairo_font_options_set_hint_style(options,
608 font_style->priv->hint_style);
609 cairo_font_options_set_hint_metrics(options,
610 font_style->priv->hint_metrics);
612 cairo_set_font_options(cr, options);
613 cairo_font_options_destroy(options);
616 static void
617 set_family(AdgFontStyle *font_style, const gchar *family)
619 g_free(font_style->priv->family);
620 font_style->priv->family = g_strdup(family);