[AdgADim] Added "angle1" and "angle2" properties
[adg.git] / adg / adg-font-style.c
blob89f8bd59e1d5807c5ead16bba8040221efba550d
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.
21 /**
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.
29 /**
30 * AdgFontStyle:
32 * All fields are private and should not be used directly.
33 * Use its public methods instead.
34 **/
37 /**
38 * ADG_SLOT_FONT_STYLE:
40 * Gets the slot id for this style class.
42 * Return value: the requested slot id
43 **/
46 #include "adg-font-style.h"
47 #include "adg-font-style-private.h"
48 #include "adg-context.h"
49 #include "adg-intl.h"
50 #include "adg-util.h"
53 enum {
54 PROP_0,
55 PROP_FAMILY,
56 PROP_SLANT,
57 PROP_WEIGHT,
58 PROP_SIZE,
59 PROP_ANTIALIAS,
60 PROP_SUBPIXEL_ORDER,
61 PROP_HINT_STYLE,
62 PROP_HINT_METRICS
66 static void get_property (GObject *object,
67 guint prop_id,
68 GValue *value,
69 GParamSpec *pspec);
70 static void set_property (GObject *object,
71 guint prop_id,
72 const GValue *value,
73 GParamSpec *pspec);
74 static GPtrArray * get_pool (void);
75 static void apply (AdgStyle *style,
76 cairo_t *cr);
77 static void set_family (AdgFontStyle *font_style,
78 const gchar *family);
81 G_DEFINE_TYPE(AdgFontStyle, adg_font_style, ADG_TYPE_STYLE)
84 static void
85 adg_font_style_class_init(AdgFontStyleClass *klass)
87 GObjectClass *gobject_class;
88 AdgStyleClass *style_class;
89 GParamSpec *param;
91 gobject_class = (GObjectClass *) klass;
92 style_class = (AdgStyleClass *) klass;
94 g_type_class_add_private(klass, sizeof(AdgFontStylePrivate));
96 gobject_class->get_property = get_property;
97 gobject_class->set_property = set_property;
99 style_class->get_pool = get_pool;
100 style_class->apply = apply;
102 param = g_param_spec_string("family",
103 P_("Font Family"),
105 ("The font family name, encoded in UTF-8"),
106 NULL, G_PARAM_READWRITE);
107 g_object_class_install_property(gobject_class, PROP_FAMILY, param);
109 param = g_param_spec_int("slant",
110 P_("Font Slant"),
112 ("Variant of a font face based on its slant"),
113 G_MININT, G_MAXINT, CAIRO_FONT_SLANT_NORMAL,
114 G_PARAM_READWRITE);
115 g_object_class_install_property(gobject_class, PROP_SLANT, param);
117 param = g_param_spec_int("weight",
118 P_("Font Weight"),
120 ("Variant of a font face based on its weight"),
121 G_MININT, G_MAXINT, CAIRO_FONT_WEIGHT_NORMAL,
122 G_PARAM_READWRITE);
123 g_object_class_install_property(gobject_class, PROP_WEIGHT, param);
125 param = g_param_spec_double("size",
126 P_("Font Size"),
127 P_("Font size in user space units"),
128 0., G_MAXDOUBLE, 10., G_PARAM_READWRITE);
129 g_object_class_install_property(gobject_class, PROP_SIZE, param);
131 param = g_param_spec_int("antialias",
132 P_("Font Antialiasing Mode"),
134 ("Type of antialiasing to do when rendering text"),
135 G_MININT, G_MAXINT, CAIRO_ANTIALIAS_DEFAULT,
136 G_PARAM_READWRITE);
137 g_object_class_install_property(gobject_class, PROP_ANTIALIAS, param);
139 param = g_param_spec_int("subpixel-order",
140 P_("Font Subpixel Order"),
142 ("The order of color elements within each pixel on the display device when rendering with subpixel antialiasing mode"),
143 G_MININT, G_MAXINT,
144 CAIRO_SUBPIXEL_ORDER_DEFAULT,
145 G_PARAM_READWRITE);
146 g_object_class_install_property(gobject_class, PROP_SUBPIXEL_ORDER,
147 param);
149 param = g_param_spec_int("hint-style",
150 P_("Type of Hinting"),
152 ("How outlines must fit to the pixel grid in order to improve the glyph appearance"),
153 G_MININT, G_MAXINT, CAIRO_HINT_STYLE_DEFAULT,
154 G_PARAM_READWRITE);
155 g_object_class_install_property(gobject_class, PROP_HINT_STYLE, param);
157 param = g_param_spec_int("hint-metrics",
158 P_("Font Metric Hinting"),
160 ("Whether to hint font metrics, that is align them to integer values in device space"),
161 G_MININT, G_MAXINT,
162 CAIRO_HINT_METRICS_DEFAULT,
163 G_PARAM_READWRITE);
164 g_object_class_install_property(gobject_class, PROP_HINT_METRICS,
165 param);
168 static void
169 adg_font_style_init(AdgFontStyle *font_style)
171 AdgFontStylePrivate *data = G_TYPE_INSTANCE_GET_PRIVATE(font_style,
172 ADG_TYPE_FONT_STYLE,
173 AdgFontStylePrivate);
175 data->family = NULL;
176 data->slant = CAIRO_FONT_SLANT_NORMAL;
177 data->weight = CAIRO_FONT_WEIGHT_NORMAL;
178 data->size = 10.;
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;
184 font_style->data = data;
187 static void
188 get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
190 AdgFontStylePrivate *data = ((AdgFontStyle *) object)->data;
192 switch (prop_id) {
193 case PROP_FAMILY:
194 g_value_set_string(value, data->family);
195 break;
196 case PROP_SLANT:
197 g_value_set_int(value, data->slant);
198 break;
199 case PROP_WEIGHT:
200 g_value_set_int(value, data->weight);
201 break;
202 case PROP_SIZE:
203 g_value_set_double(value, data->size);
204 break;
205 case PROP_ANTIALIAS:
206 g_value_set_int(value, data->antialias);
207 break;
208 case PROP_SUBPIXEL_ORDER:
209 g_value_set_int(value, data->subpixel_order);
210 break;
211 case PROP_HINT_STYLE:
212 g_value_set_int(value, data->hint_style);
213 break;
214 case PROP_HINT_METRICS:
215 g_value_set_int(value, data->hint_metrics);
216 break;
217 default:
218 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
219 break;
223 static void
224 set_property(GObject *object,
225 guint prop_id, const GValue *value, GParamSpec *pspec)
227 AdgFontStyle *font_style;
228 AdgFontStylePrivate *data;
230 font_style = (AdgFontStyle *) object;
231 data = font_style->data;
233 switch (prop_id) {
234 case PROP_FAMILY:
235 set_family(font_style, g_value_get_string(value));
236 break;
237 case PROP_SLANT:
238 data->slant = g_value_get_int(value);
239 break;
240 case PROP_WEIGHT:
241 data->weight = g_value_get_int(value);
242 break;
243 case PROP_SIZE:
244 data->size = g_value_get_double(value);
245 break;
246 case PROP_ANTIALIAS:
247 data->antialias = g_value_get_int(value);
248 break;
249 case PROP_SUBPIXEL_ORDER:
250 data->subpixel_order = g_value_get_int(value);
251 break;
252 case PROP_HINT_STYLE:
253 data->hint_style = g_value_get_int(value);
254 break;
255 case PROP_HINT_METRICS:
256 data->hint_metrics = g_value_get_int(value);
257 break;
258 default:
259 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
260 break;
265 AdgStyleSlot
266 _adg_font_style_get_slot(void)
268 static AdgStyleSlot slot = -1;
270 if (G_UNLIKELY(slot < 0))
271 slot = adg_context_get_slot(ADG_TYPE_FONT_STYLE);
273 return slot;
277 * adg_font_style_new:
279 * Constructs a new font style initialized with default params.
281 * Return value: a new font style
283 AdgStyle *
284 adg_font_style_new(void)
286 return g_object_new(ADG_TYPE_FONT_STYLE, NULL);
290 * adg_font_style_get_family:
291 * @font_style: an #AdgFontStyle object
293 * Gets the family of @font_style. The returned pointer refers to
294 * internally managed text that must not be modified or freed.
296 * Return value: the requested family
298 const gchar *
299 adg_font_style_get_family(AdgFontStyle *font_style)
301 AdgFontStylePrivate *data;
303 g_return_val_if_fail(ADG_IS_FONT_STYLE(font_style), NULL);
305 data = font_style->data;
307 return data->family;
311 * adg_font_style_set_family:
312 * @font_style: an #AdgFontStyle object
313 * @family: the new family
315 * Sets a new family.
317 void
318 adg_font_style_set_family(AdgFontStyle *font_style, const gchar *family)
320 g_return_if_fail(ADG_IS_FONT_STYLE(font_style));
322 set_family(font_style, family);
323 g_object_notify((GObject *) font_style, "family");
327 * adg_font_style_get_slant:
328 * @font_style: an #AdgFontStyle object
330 * Gets the slant variant of @font_style.
332 * Return value: the slant variant
334 cairo_font_slant_t
335 adg_font_style_get_slant(AdgFontStyle *font_style)
337 AdgFontStylePrivate *data;
339 g_return_val_if_fail(ADG_IS_FONT_STYLE(font_style),
340 CAIRO_FONT_SLANT_NORMAL);
342 data = font_style->data;
344 return data->slant;
348 * adg_font_style_set_slant:
349 * @font_style: an #AdgFontStyle object
350 * @slant: the new slant
352 * Sets a new slant variant on @font_style.
354 void
355 adg_font_style_set_slant(AdgFontStyle *font_style,
356 cairo_font_slant_t slant)
358 AdgFontStylePrivate *data;
360 g_return_if_fail(ADG_IS_FONT_STYLE(font_style));
362 data = font_style->data;
363 data->slant = slant;
365 g_object_notify((GObject *) font_style, "slant");
369 * adg_font_style_get_weight:
370 * @font_style: an #AdgFontStyle object
372 * Gets the weight variant of @font_style.
374 * Return value: the weight variant
376 cairo_font_weight_t
377 adg_font_style_get_weight(AdgFontStyle *font_style)
379 AdgFontStylePrivate *data;
381 g_return_val_if_fail(ADG_IS_FONT_STYLE(font_style),
382 CAIRO_FONT_WEIGHT_NORMAL);
384 data = font_style->data;
386 return data->weight;
390 * adg_font_style_set_weight:
391 * @font_style: an #AdgFontStyle object
392 * @weight: the new weight
394 * Sets a new weight variant on @font_style.
396 void
397 adg_font_style_set_weight(AdgFontStyle *font_style,
398 cairo_font_weight_t weight)
400 AdgFontStylePrivate *data;
402 g_return_if_fail(ADG_IS_FONT_STYLE(font_style));
404 data = font_style->data;
405 data->weight = weight;
407 g_object_notify((GObject *) font_style, "weight");
411 * adg_font_style_get_size:
412 * @font_style: an #AdgFontStyle object
414 * Gets the size (in paper units) of @font_style.
416 * Return value: the size variant
418 gdouble
419 adg_font_style_get_size(AdgFontStyle *font_style)
421 AdgFontStylePrivate *data;
423 g_return_val_if_fail(ADG_IS_FONT_STYLE(font_style), 0.);
425 data = font_style->data;
427 return data->size;
431 * adg_font_style_set_size:
432 * @font_style: an #AdgFontStyle object
433 * @size: the new size
435 * Sets a new size (in paper units) on @font_style.
437 void
438 adg_font_style_set_size(AdgFontStyle *font_style, gdouble size)
440 AdgFontStylePrivate *data;
442 g_return_if_fail(ADG_IS_FONT_STYLE(font_style));
444 data = font_style->data;
445 data->size = size;
447 g_object_notify((GObject *) font_style, "size");
451 * adg_font_style_get_antialias:
452 * @font_style: an #AdgFontStyle object
454 * Gets the antialias mode used.
456 * Return value: the requested antialias mode
458 cairo_antialias_t
459 adg_font_style_get_antialias(AdgFontStyle *font_style)
461 AdgFontStylePrivate *data;
463 g_return_val_if_fail(ADG_IS_FONT_STYLE(font_style),
464 CAIRO_ANTIALIAS_DEFAULT);
466 data = font_style->data;
468 return data->antialias;
472 * adg_font_style_set_antialias:
473 * @font_style: an #AdgFontStyle object
474 * @antialias: the new antialias mode
476 * Sets a new antialias mode.
478 void
479 adg_font_style_set_antialias(AdgFontStyle *font_style,
480 cairo_antialias_t antialias)
482 AdgFontStylePrivate *data;
484 g_return_if_fail(ADG_IS_FONT_STYLE(font_style));
486 data = font_style->data;
487 data->antialias = antialias;
489 g_object_notify((GObject *) font_style, "antialias");
493 * adg_font_style_get_subpixel_order:
494 * @font_style: an #AdgFontStyle object
496 * Gets the subpixel order mode used, that is the order of color elements
497 * within each pixel on the display device when rendering with an
498 * antialiasing mode of %CAIRO_ANTIALIAS_SUBPIXEL.
500 * Return value: the requested subpixel order mode
502 cairo_subpixel_order_t
503 adg_font_style_get_subpixel_order(AdgFontStyle *font_style)
505 AdgFontStylePrivate *data;
507 g_return_val_if_fail(ADG_IS_FONT_STYLE(font_style),
508 CAIRO_SUBPIXEL_ORDER_DEFAULT);
510 data = font_style->data;
512 return data->subpixel_order;
516 * adg_font_style_set_subpixel_order:
517 * @font_style: an #AdgFontStyle object
518 * @subpixel_order: the new subpixel order mode
520 * Sets a new subpixel order mode.
522 void
523 adg_font_style_set_subpixel_order(AdgFontStyle *font_style,
524 cairo_subpixel_order_t subpixel_order)
526 AdgFontStylePrivate *data;
528 g_return_if_fail(ADG_IS_FONT_STYLE(font_style));
530 data = font_style->data;
531 data->subpixel_order = subpixel_order;
533 g_object_notify((GObject *) font_style, "subpixel-order");
537 * adg_font_style_get_hint_style:
538 * @font_style: an #AdgFontStyle object
540 * Gets the hint style mode used, that is how to fit outlines
541 * to the pixel grid in order to improve the appearance of the result.
543 * Return value: the requested hint style mode
545 cairo_hint_style_t
546 adg_font_style_get_hint_style(AdgFontStyle *font_style)
548 AdgFontStylePrivate *data;
550 g_return_val_if_fail(ADG_IS_FONT_STYLE(font_style),
551 CAIRO_HINT_STYLE_DEFAULT);
553 data = font_style->data;
555 return data->hint_style;
559 * adg_font_style_set_hint_style:
560 * @font_style: an #AdgFontStyle object
561 * @hint_style: the new hint style mode
563 * Sets a new hint style mode.
565 void
566 adg_font_style_set_hint_style(AdgFontStyle *font_style,
567 cairo_hint_style_t hint_style)
569 AdgFontStylePrivate *data;
571 g_return_if_fail(ADG_IS_FONT_STYLE(font_style));
573 data = font_style->data;
574 data->hint_style = hint_style;
576 g_object_notify((GObject *) font_style, "hint-style");
580 * adg_font_style_get_hint_metrics:
581 * @font_style: an #AdgFontStyle object
583 * Gets the state on whether to hint font metrics.
585 * Return value: the requested hint metrics state
587 cairo_hint_metrics_t
588 adg_font_style_get_hint_metrics(AdgFontStyle *font_style)
590 AdgFontStylePrivate *data;
592 g_return_val_if_fail(ADG_IS_FONT_STYLE(font_style),
593 CAIRO_HINT_METRICS_DEFAULT);
595 data = font_style->data;
597 return data->hint_metrics;
601 * adg_font_style_set_hint_metrics:
602 * @font_style: an #AdgFontStyle object
603 * @hint_metrics: the new hint metrics state
605 * Sets a new hint metrics state.
607 void
608 adg_font_style_set_hint_metrics(AdgFontStyle *font_style,
609 cairo_hint_metrics_t hint_metrics)
611 AdgFontStylePrivate *data;
613 g_return_if_fail(ADG_IS_FONT_STYLE(font_style));
615 data = font_style->data;
616 data->hint_metrics = hint_metrics;
618 g_object_notify((GObject *) font_style, "hint-metrics");
622 static GPtrArray *
623 get_pool(void)
625 static GPtrArray *pool = NULL;
627 if (G_UNLIKELY(pool == NULL)) {
628 pool = g_ptr_array_sized_new(ADG_FONT_STYLE_LAST);
630 pool->pdata[ADG_FONT_STYLE_TEXT] =
631 g_object_new(ADG_TYPE_FONT_STYLE, "family", "Serif", "size",
632 14., NULL);
633 pool->pdata[ADG_FONT_STYLE_QUOTE] =
634 g_object_new(ADG_TYPE_FONT_STYLE, "family", "Sans", "size",
635 12., "weight", CAIRO_FONT_WEIGHT_BOLD, NULL);
636 pool->pdata[ADG_FONT_STYLE_TOLERANCE] =
637 g_object_new(ADG_TYPE_FONT_STYLE, "family", "Sans", "size", 8.,
638 NULL);
639 pool->pdata[ADG_FONT_STYLE_NOTE] =
640 g_object_new(ADG_TYPE_FONT_STYLE, "family", "Sans", "size",
641 12., NULL);
643 pool->len = ADG_FONT_STYLE_LAST;
646 return pool;
649 static void
650 apply(AdgStyle *style, cairo_t *cr)
652 AdgFontStyle *font_style;
653 AdgFontStylePrivate *data;
654 AdgStyleClass *style_class;
655 double size;
656 cairo_font_options_t *options;
657 cairo_matrix_t matrix;
658 cairo_matrix_t font_matrix;
660 font_style = (AdgFontStyle *) style;
661 data = font_style->data;
662 style_class = (AdgStyleClass *) adg_font_style_parent_class;
663 cairo_get_matrix(cr, &matrix);
664 size = data->size;
666 if (style_class->apply != NULL)
667 style_class->apply(style, cr);
669 if (data->family)
670 cairo_select_font_face(cr, data->family,
671 data->slant, data->weight);
673 cairo_matrix_init_scale(&font_matrix,
674 size / (matrix.xx - matrix.yx),
675 size / (matrix.yy + matrix.xy));
676 cairo_set_font_matrix(cr, &font_matrix);
678 options = cairo_font_options_create();
680 cairo_font_options_set_antialias(options, data->antialias);
681 cairo_font_options_set_subpixel_order(options, data->subpixel_order);
682 cairo_font_options_set_hint_style(options, data->hint_style);
683 cairo_font_options_set_hint_metrics(options, data->hint_metrics);
685 cairo_set_font_options(cr, options);
686 cairo_font_options_destroy(options);
689 static void
690 set_family(AdgFontStyle *font_style, const gchar *family)
692 AdgFontStylePrivate *data = font_style->data;
694 g_free(data->family);
695 data->family = g_strdup(family);