Upload tizen 2.0 beta source
[external/pango1.0.git] / pango / fonts.c
1 /* Pango
2  * fonts.c:
3  *
4  * Copyright (C) 1999 Red Hat Software
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21
22 #include "config.h"
23 #include <stdlib.h>
24 #include <math.h>
25 #include <string.h>
26
27 #include "pango-types.h"
28 #include "pango-font.h"
29 #include "pango-fontmap.h"
30 #include "pango-impl-utils.h"
31
32 struct _PangoFontDescription
33 {
34   char *family_name;
35
36   PangoStyle style;
37   PangoVariant variant;
38   PangoWeight weight;
39   PangoStretch stretch;
40   PangoGravity gravity;
41
42   guint16 mask;
43   guint static_family : 1;
44   guint size_is_absolute : 1;
45
46   int size;
47 };
48
49 GType
50 pango_font_description_get_type (void)
51 {
52   static GType our_type = 0;
53
54   if (G_UNLIKELY (our_type == 0))
55     our_type = g_boxed_type_register_static (I_("PangoFontDescription"),
56                                              (GBoxedCopyFunc)pango_font_description_copy,
57                                              (GBoxedFreeFunc)pango_font_description_free);
58
59   return our_type;
60 }
61
62
63 static const PangoFontDescription pfd_defaults = {
64   NULL,                 /* family_name */
65
66   PANGO_STYLE_NORMAL,   /* style */
67   PANGO_VARIANT_NORMAL, /* variant */
68   PANGO_WEIGHT_NORMAL,  /* weight */
69   PANGO_STRETCH_NORMAL, /* stretch */
70   PANGO_GRAVITY_SOUTH,  /* gravity */
71
72   0,                    /* mask */
73   0,                    /* static_family */
74   FALSE,                /* size_is_absolute */
75
76   0,                    /* size */
77 };
78
79 /**
80  * pango_font_description_new:
81  *
82  * Creates a new font description structure with all fields unset.
83  *
84  * Return value: the newly allocated #PangoFontDescription, which
85  *               should be freed using pango_font_description_free().
86  **/
87 PangoFontDescription *
88 pango_font_description_new (void)
89 {
90   PangoFontDescription *desc = g_slice_new (PangoFontDescription);
91
92   *desc = pfd_defaults;
93
94   return desc;
95 }
96
97 /**
98  * pango_font_description_set_family:
99  * @desc: a #PangoFontDescription.
100  * @family: a string representing the family name.
101  *
102  * Sets the family name field of a font description. The family
103  * name represents a family of related font styles, and will
104  * resolve to a particular #PangoFontFamily. In some uses of
105  * #PangoFontDescription, it is also possible to use a comma
106  * separated list of family names for this field.
107  **/
108 void
109 pango_font_description_set_family (PangoFontDescription *desc,
110                                    const char           *family)
111 {
112   g_return_if_fail (desc != NULL);
113
114   pango_font_description_set_family_static (desc, family ? g_strdup (family) : NULL);
115   if (family)
116     desc->static_family = FALSE;
117 }
118
119 /**
120  * pango_font_description_set_family_static:
121  * @desc: a #PangoFontDescription
122  * @family: a string representing the family name.
123  *
124  * Like pango_font_description_set_family(), except that no
125  * copy of @family is made. The caller must make sure that the
126  * string passed in stays around until @desc has been freed
127  * or the name is set again. This function can be used if
128  * @family is a static string such as a C string literal, or
129  * if @desc is only needed temporarily.
130  **/
131 void
132 pango_font_description_set_family_static (PangoFontDescription *desc,
133                                           const char           *family)
134 {
135   g_return_if_fail (desc != NULL);
136
137   if (desc->family_name == family)
138     return;
139
140   if (desc->family_name && !desc->static_family)
141     g_free (desc->family_name);
142
143   if (family)
144     {
145       desc->family_name = (char *)family;
146       desc->static_family = TRUE;
147       desc->mask |= PANGO_FONT_MASK_FAMILY;
148     }
149   else
150     {
151       desc->family_name = pfd_defaults.family_name;
152       desc->static_family = pfd_defaults.static_family;
153       desc->mask &= ~PANGO_FONT_MASK_FAMILY;
154     }
155 }
156
157 /**
158  * pango_font_description_get_family:
159  * @desc: a #PangoFontDescription.
160  *
161  * Gets the family name field of a font description. See
162  * pango_font_description_set_family().
163  *
164  * Return value: the family name field for the font description, or
165  *               %NULL if not previously set.  This has the same life-time
166  *               as the font description itself and should not be freed.
167  **/
168 G_CONST_RETURN char *
169 pango_font_description_get_family (const PangoFontDescription *desc)
170 {
171   g_return_val_if_fail (desc != NULL, NULL);
172
173   return desc->family_name;
174 }
175
176 /**
177  * pango_font_description_set_style:
178  * @desc: a #PangoFontDescription
179  * @style: the style for the font description
180  *
181  * Sets the style field of a #PangoFontDescription. The
182  * #PangoStyle enumeration describes whether the font is slanted and
183  * the manner in which it is slanted; it can be either
184  * #PANGO_STYLE_NORMAL, #PANGO_STYLE_ITALIC, or #PANGO_STYLE_OBLIQUE.
185  * Most fonts will either have a italic style or an oblique
186  * style, but not both, and font matching in Pango will
187  * match italic specifications with oblique fonts and vice-versa
188  * if an exact match is not found.
189  **/
190 void
191 pango_font_description_set_style (PangoFontDescription *desc,
192                                   PangoStyle            style)
193 {
194   g_return_if_fail (desc != NULL);
195
196   desc->style = style;
197   desc->mask |= PANGO_FONT_MASK_STYLE;
198 }
199
200 /**
201  * pango_font_description_get_style:
202  * @desc: a #PangoFontDescription
203  *
204  * Gets the style field of a #PangoFontDescription. See
205  * pango_font_description_set_style().
206  *
207  * Return value: the style field for the font description.
208  *   Use pango_font_description_get_set_fields() to find out if
209  *   the field was explicitly set or not.
210  **/
211 PangoStyle
212 pango_font_description_get_style (const PangoFontDescription *desc)
213 {
214   g_return_val_if_fail (desc != NULL, pfd_defaults.style);
215
216   return desc->style;
217 }
218
219 /**
220  * pango_font_description_set_variant:
221  * @desc: a #PangoFontDescription
222  * @variant: the variant type for the font description.
223  *
224  * Sets the variant field of a font description. The #PangoVariant
225  * can either be %PANGO_VARIANT_NORMAL or %PANGO_VARIANT_SMALL_CAPS.
226  **/
227 void
228 pango_font_description_set_variant (PangoFontDescription *desc,
229                                     PangoVariant          variant)
230 {
231   g_return_if_fail (desc != NULL);
232
233   desc->variant = variant;
234   desc->mask |= PANGO_FONT_MASK_VARIANT;
235 }
236
237 /**
238  * pango_font_description_get_variant:
239  * @desc: a #PangoFontDescription.
240  *
241  * Gets the variant field of a #PangoFontDescription. See
242  * pango_font_description_set_variant().
243  *
244  * Return value: the variant field for the font description. Use
245  *   pango_font_description_get_set_fields() to find out if
246  *   the field was explicitly set or not.
247  **/
248 PangoVariant
249 pango_font_description_get_variant (const PangoFontDescription *desc)
250 {
251   g_return_val_if_fail (desc != NULL, pfd_defaults.variant);
252
253   return desc->variant;
254 }
255
256 /**
257  * pango_font_description_set_weight:
258  * @desc: a #PangoFontDescription
259  * @weight: the weight for the font description.
260  *
261  * Sets the weight field of a font description. The weight field
262  * specifies how bold or light the font should be. In addition
263  * to the values of the #PangoWeight enumeration, other intermediate
264  * numeric values are possible.
265  **/
266 void
267 pango_font_description_set_weight (PangoFontDescription *desc,
268                                    PangoWeight          weight)
269 {
270   g_return_if_fail (desc != NULL);
271
272   desc->weight = weight;
273   desc->mask |= PANGO_FONT_MASK_WEIGHT;
274 }
275
276 /**
277  * pango_font_description_get_weight:
278  * @desc: a #PangoFontDescription
279  *
280  * Gets the weight field of a font description. See
281  * pango_font_description_set_weight().
282  *
283  * Return value: the weight field for the font description. Use
284  *   pango_font_description_get_set_fields() to find out if
285  *   the field was explicitly set or not.
286  **/
287 PangoWeight
288 pango_font_description_get_weight (const PangoFontDescription *desc)
289 {
290   g_return_val_if_fail (desc != NULL, pfd_defaults.weight);
291
292   return desc->weight;
293 }
294
295 /**
296  * pango_font_description_set_stretch:
297  * @desc: a #PangoFontDescription
298  * @stretch: the stretch for the font description
299  *
300  * Sets the stretch field of a font description. The stretch field
301  * specifies how narrow or wide the font should be.
302  **/
303 void
304 pango_font_description_set_stretch (PangoFontDescription *desc,
305                                     PangoStretch          stretch)
306 {
307   g_return_if_fail (desc != NULL);
308
309   desc->stretch = stretch;
310   desc->mask |= PANGO_FONT_MASK_STRETCH;
311 }
312
313 /**
314  * pango_font_description_get_stretch:
315  * @desc: a #PangoFontDescription.
316  *
317  * Gets the stretch field of a font description.
318  * See pango_font_description_set_stretch().
319  *
320  * Return value: the stretch field for the font description. Use
321  *   pango_font_description_get_set_fields() to find out if
322  *   the field was explicitly set or not.
323  **/
324 PangoStretch
325 pango_font_description_get_stretch (const PangoFontDescription *desc)
326 {
327   g_return_val_if_fail (desc != NULL, pfd_defaults.stretch);
328
329   return desc->stretch;
330 }
331
332 /**
333  * pango_font_description_set_size:
334  * @desc: a #PangoFontDescription
335  * @size: the size of the font in points, scaled by PANGO_SCALE. (That is,
336  *        a @size value of 10 * PANGO_SCALE is a 10 point font. The conversion
337  *        factor between points and device units depends on system configuration
338  *        and the output device. For screen display, a logical DPI of 96 is
339  *        common, in which case a 10 point font corresponds to a 10 * (96 / 72) = 13.3
340  *        pixel font. Use pango_font_description_set_absolute_size() if you need
341  *        a particular size in device units.
342  *
343  * Sets the size field of a font description in fractional points. This is mutually
344  * exclusive with pango_font_description_set_absolute_size().
345  **/
346 void
347 pango_font_description_set_size (PangoFontDescription *desc,
348                                  gint                  size)
349 {
350   g_return_if_fail (desc != NULL);
351   g_return_if_fail (size >= 0);
352
353   desc->size = size;
354   desc->size_is_absolute = FALSE;
355   desc->mask |= PANGO_FONT_MASK_SIZE;
356 }
357
358 /**
359  * pango_font_description_get_size:
360  * @desc: a #PangoFontDescription
361  *
362  * Gets the size field of a font description.
363  * See pango_font_description_set_size().
364  *
365  * Return value: the size field for the font description in points or device units.
366  *   You must call pango_font_description_get_size_is_absolute()
367  *   to find out which is the case. Returns 0 if the size field has not
368  *   previously been set or it has been set to 0 explicitly.
369  *   Use pango_font_description_get_set_fields() to
370  *   find out if the field was explicitly set or not.
371  **/
372 gint
373 pango_font_description_get_size (const PangoFontDescription *desc)
374 {
375   g_return_val_if_fail (desc != NULL, pfd_defaults.size);
376
377   return desc->size;
378 }
379
380 /**
381  * pango_font_description_set_absolute_size:
382  * @desc: a #PangoFontDescription
383  * @size: the new size, in Pango units. There are %PANGO_SCALE Pango units in one
384  *   device unit. For an output backend where a device unit is a pixel, a @size
385  *   value of 10 * PANGO_SCALE gives a 10 pixel font.
386  *
387  * Sets the size field of a font description, in device units. This is mutually
388  * exclusive with pango_font_description_set_size() which sets the font size
389  * in points.
390  *
391  * Since: 1.8
392  **/
393 void
394 pango_font_description_set_absolute_size (PangoFontDescription *desc,
395                                           double                size)
396 {
397   g_return_if_fail (desc != NULL);
398   g_return_if_fail (size >= 0);
399
400   desc->size = size;
401   desc->size_is_absolute = TRUE;
402   desc->mask |= PANGO_FONT_MASK_SIZE;
403 }
404
405 /**
406  * pango_font_description_get_size_is_absolute:
407  * @desc: a #PangoFontDescription
408  *
409  * Determines whether the size of the font is in points (not absolute) or device units (absolute).
410  * See pango_font_description_set_size() and pango_font_description_set_absolute_size().
411  *
412  * Return value: whether the size for the font description is in
413  *   points or device units.  Use pango_font_description_get_set_fields() to
414  *   find out if the size field of the font description was explicitly set or not.
415  *
416  * Since: 1.8
417  **/
418 gboolean
419 pango_font_description_get_size_is_absolute (const PangoFontDescription *desc)
420 {
421   g_return_val_if_fail (desc != NULL, pfd_defaults.size_is_absolute);
422
423   return desc->size_is_absolute;
424 }
425
426 /**
427  * pango_font_description_set_gravity:
428  * @desc: a #PangoFontDescription
429  * @gravity: the gravity for the font description.
430  *
431  * Sets the gravity field of a font description. The gravity field
432  * specifies how the glyphs should be rotated.  If @gravity is
433  * %PANGO_GRAVITY_AUTO, this actually unsets the gravity mask on
434  * the font description.
435  *
436  * This function is seldom useful to the user.  Gravity should normally
437  * be set on a #PangoContext.
438  *
439  * Since: 1.16
440  **/
441 void
442 pango_font_description_set_gravity (PangoFontDescription *desc,
443                                     PangoGravity          gravity)
444 {
445   g_return_if_fail (desc != NULL);
446
447   if (gravity == PANGO_GRAVITY_AUTO)
448     {
449       pango_font_description_unset_fields (desc, PANGO_FONT_MASK_GRAVITY);
450       return;
451     }
452
453   desc->gravity = gravity;
454   desc->mask |= PANGO_FONT_MASK_GRAVITY;
455 }
456
457 /**
458  * pango_font_description_get_gravity:
459  * @desc: a #PangoFontDescription
460  *
461  * Gets the gravity field of a font description. See
462  * pango_font_description_set_gravity().
463  *
464  * Return value: the gravity field for the font description. Use
465  *   pango_font_description_get_set_fields() to find out if
466  *   the field was explicitly set or not.
467  *
468  * Since: 1.16
469  **/
470 PangoGravity
471 pango_font_description_get_gravity (const PangoFontDescription *desc)
472 {
473   g_return_val_if_fail (desc != NULL, pfd_defaults.gravity);
474
475   return desc->gravity;
476 }
477
478 /**
479  * pango_font_description_get_set_fields:
480  * @desc: a #PangoFontDescription
481  *
482  * Determines which fields in a font description have been set.
483  *
484  * Return value: a bitmask with bits set corresponding to the
485  *   fields in @desc that have been set.
486  **/
487 PangoFontMask
488 pango_font_description_get_set_fields (const PangoFontDescription *desc)
489 {
490   g_return_val_if_fail (desc != NULL, pfd_defaults.mask);
491
492   return desc->mask;
493 }
494
495 /**
496  * pango_font_description_unset_fields:
497  * @desc: a #PangoFontDescription
498  * @to_unset: bitmask of fields in the @desc to unset.
499  *
500  * Unsets some of the fields in a #PangoFontDescription.  The unset
501  * fields will get back to their default values.
502  **/
503 void
504 pango_font_description_unset_fields (PangoFontDescription *desc,
505                                      PangoFontMask         to_unset)
506 {
507   PangoFontDescription unset_desc;
508
509   g_return_if_fail (desc != NULL);
510
511   unset_desc = pfd_defaults;
512   unset_desc.mask = to_unset;
513
514   pango_font_description_merge_static (desc, &unset_desc, TRUE);
515
516   desc->mask &= ~to_unset;
517 }
518
519 /**
520  * pango_font_description_merge:
521  * @desc: a #PangoFontDescription
522  * @desc_to_merge: the #PangoFontDescription to merge from, or %NULL
523  * @replace_existing: if %TRUE, replace fields in @desc with the
524  *   corresponding values from @desc_to_merge, even if they
525  *   are already exist.
526  *
527  * Merges the fields that are set in @desc_to_merge into the fields in
528  * @desc.  If @replace_existing is %FALSE, only fields in @desc that
529  * are not already set are affected. If %TRUE, then fields that are
530  * already set will be replaced as well.
531  *
532  * If @desc_to_merge is %NULL, this function performs nothing.
533  **/
534 void
535 pango_font_description_merge (PangoFontDescription       *desc,
536                               const PangoFontDescription *desc_to_merge,
537                               gboolean                    replace_existing)
538 {
539   gboolean family_merged;
540
541   g_return_if_fail (desc != NULL);
542
543   if (desc_to_merge == NULL)
544     return;
545
546   family_merged = desc_to_merge->family_name && (replace_existing || !desc->family_name);
547
548   pango_font_description_merge_static (desc, desc_to_merge, replace_existing);
549
550   if (family_merged)
551     {
552       desc->family_name = g_strdup (desc->family_name);
553       desc->static_family = FALSE;
554     }
555 }
556
557 /**
558  * pango_font_description_merge_static:
559  * @desc: a #PangoFontDescription
560  * @desc_to_merge: the #PangoFontDescription to merge from
561  * @replace_existing: if %TRUE, replace fields in @desc with the
562  *   corresponding values from @desc_to_merge, even if they
563  *   are already exist.
564  *
565  * Like pango_font_description_merge(), but only a shallow copy is made
566  * of the family name and other allocated fields. @desc can only be
567  * used until @desc_to_merge is modified or freed. This is meant
568  * to be used when the merged font description is only needed temporarily.
569  **/
570 void
571 pango_font_description_merge_static (PangoFontDescription       *desc,
572                                      const PangoFontDescription *desc_to_merge,
573                                      gboolean                    replace_existing)
574 {
575   PangoFontMask new_mask;
576
577   g_return_if_fail (desc != NULL);
578   g_return_if_fail (desc_to_merge != NULL);
579
580   if (replace_existing)
581     new_mask = desc_to_merge->mask;
582   else
583     new_mask = desc_to_merge->mask & ~desc->mask;
584
585   if (new_mask & PANGO_FONT_MASK_FAMILY)
586     pango_font_description_set_family_static (desc, desc_to_merge->family_name);
587   if (new_mask & PANGO_FONT_MASK_STYLE)
588     desc->style = desc_to_merge->style;
589   if (new_mask & PANGO_FONT_MASK_VARIANT)
590     desc->variant = desc_to_merge->variant;
591   if (new_mask & PANGO_FONT_MASK_WEIGHT)
592     desc->weight = desc_to_merge->weight;
593   if (new_mask & PANGO_FONT_MASK_STRETCH)
594     desc->stretch = desc_to_merge->stretch;
595   if (new_mask & PANGO_FONT_MASK_SIZE)
596     {
597       desc->size = desc_to_merge->size;
598       desc->size_is_absolute = desc_to_merge->size_is_absolute;
599     }
600   if (new_mask & PANGO_FONT_MASK_GRAVITY)
601     desc->gravity = desc_to_merge->gravity;
602
603   desc->mask |= new_mask;
604 }
605
606 static gint
607 compute_distance (const PangoFontDescription *a,
608                   const PangoFontDescription *b)
609 {
610   if (a->style == b->style)
611     {
612       return abs(a->weight - b->weight);
613     }
614   else if (a->style != PANGO_STYLE_NORMAL &&
615            b->style != PANGO_STYLE_NORMAL)
616     {
617       /* Equate oblique and italic, but with a big penalty
618        */
619       return 1000000 + abs (a->weight - b->weight);
620     }
621   else
622     return G_MAXINT;
623 }
624
625 /**
626  * pango_font_description_better_match:
627  * @desc: a #PangoFontDescription
628  * @old_match: a #PangoFontDescription, or %NULL
629  * @new_match: a #PangoFontDescription
630  *
631  * Determines if the style attributes of @new_match are a closer match
632  * for @desc than those of @old_match are, or if @old_match is %NULL,
633  * determines if @new_match is a match at all.
634  * Approximate matching is done for
635  * weight and style; other style attributes must match exactly.
636  * Style attributes are all attributes other than family and size-related
637  * attributes.  Approximate matching for style considers PANGO_STYLE_OBLIQUE
638  * and PANGO_STYLE_ITALIC as matches, but not as good a match as when the
639  * styles are equal.
640  *
641  * Note that @old_match must match @desc.
642  *
643  * Return value: %TRUE if @new_match is a better match
644  **/
645 gboolean
646 pango_font_description_better_match (const PangoFontDescription *desc,
647                                      const PangoFontDescription *old_match,
648                                      const PangoFontDescription *new_match)
649 {
650   g_return_val_if_fail (desc != NULL, G_MAXINT);
651   g_return_val_if_fail (new_match != NULL, G_MAXINT);
652
653   if (new_match->variant == desc->variant &&
654       new_match->stretch == desc->stretch &&
655       new_match->gravity == desc->gravity)
656     {
657       int old_distance = old_match ? compute_distance (desc, old_match) : G_MAXINT;
658       int new_distance = compute_distance (desc, new_match);
659
660       if (new_distance < old_distance)
661         return TRUE;
662     }
663
664   return FALSE;
665 }
666
667 /**
668  * pango_font_description_copy:
669  * @desc: a #PangoFontDescription, may be %NULL
670  *
671  * Make a copy of a #PangoFontDescription.
672  *
673  * Return value: the newly allocated #PangoFontDescription, which should
674  *               be freed with pango_font_description_free(), or %NULL
675  *               if @desc was %NULL.
676  **/
677 PangoFontDescription *
678 pango_font_description_copy  (const PangoFontDescription  *desc)
679 {
680   PangoFontDescription *result;
681
682   if (desc == NULL)
683     return NULL;
684
685   result = g_slice_new (PangoFontDescription);
686
687   *result = *desc;
688
689   if (result->family_name)
690     {
691       result->family_name = g_strdup (result->family_name);
692       result->static_family = FALSE;
693     }
694
695   return result;
696 }
697
698 /**
699  * pango_font_description_copy_static:
700  * @desc: a #PangoFontDescription, may be %NULL
701  *
702  * Like pango_font_description_copy(), but only a shallow copy is made
703  * of the family name and other allocated fields. The result can only
704  * be used until @desc is modified or freed. This is meant to be used
705  * when the copy is only needed temporarily.
706  *
707  * Return value: the newly allocated #PangoFontDescription, which should
708  *               be freed with pango_font_description_free(), or %NULL
709  *               if @desc was %NULL.
710  **/
711 PangoFontDescription *
712 pango_font_description_copy_static (const PangoFontDescription *desc)
713 {
714   PangoFontDescription *result;
715
716   if (desc == NULL)
717     return NULL;
718
719   result = g_slice_new (PangoFontDescription);
720
721   *result = *desc;
722   if (result->family_name)
723     result->static_family = TRUE;
724
725   return result;
726 }
727
728 /**
729  * pango_font_description_equal:
730  * @desc1: a #PangoFontDescription
731  * @desc2: another #PangoFontDescription
732  *
733  * Compares two font descriptions for equality. Two font descriptions
734  * are considered equal if the fonts they describe are provably identical.
735  * This means that their masks do not have to match, as long as other fields
736  * are all the same. (Two font descriptions may result in identical fonts
737  * being loaded, but still compare %FALSE.)
738  *
739  * Return value: %TRUE if the two font descriptions are identical,
740  *               %FALSE otherwise.
741  **/
742 gboolean
743 pango_font_description_equal (const PangoFontDescription  *desc1,
744                               const PangoFontDescription  *desc2)
745 {
746   g_return_val_if_fail (desc1 != NULL, FALSE);
747   g_return_val_if_fail (desc2 != NULL, FALSE);
748
749   return desc1->style == desc2->style &&
750          desc1->variant == desc2->variant &&
751          desc1->weight == desc2->weight &&
752          desc1->stretch == desc2->stretch &&
753          desc1->size == desc2->size &&
754          desc1->size_is_absolute == desc2->size_is_absolute &&
755          desc1->gravity == desc2->gravity &&
756          (desc1->family_name == desc2->family_name ||
757           (desc1->family_name && desc2->family_name && g_ascii_strcasecmp (desc1->family_name, desc2->family_name) == 0));
758 }
759
760 #define TOLOWER(c) \
761   (((c) >= 'A' && (c) <= 'Z') ? (c) - 'A' + 'a' : (c))
762
763 static guint
764 case_insensitive_hash (const char *key)
765 {
766   const char *p = key;
767   guint h = TOLOWER (*p);
768
769   if (h)
770     {
771       for (p += 1; *p != '\0'; p++)
772         h = (h << 5) - h + TOLOWER (*p);
773     }
774
775   return h;
776 }
777
778 /**
779  * pango_font_description_hash:
780  * @desc: a #PangoFontDescription
781  *
782  * Computes a hash of a #PangoFontDescription structure suitable
783  * to be used, for example, as an argument to g_hash_table_new().
784  * The hash value is independent of @desc->mask.
785  *
786  * Return value: the hash value.
787  **/
788 guint
789 pango_font_description_hash (const PangoFontDescription *desc)
790 {
791   guint hash = 0;
792
793   g_return_val_if_fail (desc != NULL, 0);
794
795   if (desc->family_name)
796     hash = case_insensitive_hash (desc->family_name);
797   hash ^= desc->size;
798   hash ^= desc->size_is_absolute ? 0xc33ca55a : 0;
799   hash ^= desc->style << 16;
800   hash ^= desc->variant << 18;
801   hash ^= desc->weight << 16;
802   hash ^= desc->stretch << 26;
803   hash ^= desc->gravity << 28;
804
805   return hash;
806 }
807
808 /**
809  * pango_font_description_free:
810  * @desc: a #PangoFontDescription, may be %NULL
811  *
812  * Frees a font description.
813  **/
814 void
815 pango_font_description_free  (PangoFontDescription  *desc)
816 {
817   if (desc == NULL)
818     return;
819
820   if (desc->family_name && !desc->static_family)
821     g_free (desc->family_name);
822
823   g_slice_free (PangoFontDescription, desc);
824 }
825
826 /**
827  * pango_font_descriptions_free:
828  * @descs: a pointer to an array of #PangoFontDescription, may be %NULL
829  * @n_descs: number of font descriptions in @descs
830  *
831  * Frees an array of font descriptions.
832  **/
833 void
834 pango_font_descriptions_free (PangoFontDescription **descs,
835                               int                    n_descs)
836 {
837   int i;
838
839   if (descs == NULL)
840     return;
841
842   for (i = 0; i<n_descs; i++)
843     pango_font_description_free (descs[i]);
844   g_free (descs);
845 }
846
847 typedef struct
848 {
849   int value;
850   const char str[16];
851 } FieldMap;
852
853 static const FieldMap style_map[] = {
854   { PANGO_STYLE_NORMAL, "" },
855   { PANGO_STYLE_NORMAL, "Roman" },
856   { PANGO_STYLE_OBLIQUE, "Oblique" },
857   { PANGO_STYLE_ITALIC, "Italic" }
858 };
859
860 static const FieldMap variant_map[] = {
861   { PANGO_VARIANT_NORMAL, "" },
862   { PANGO_VARIANT_SMALL_CAPS, "Small-Caps" }
863 };
864
865 static const FieldMap weight_map[] = {
866   { PANGO_WEIGHT_THIN, "Thin" },
867   { PANGO_WEIGHT_ULTRALIGHT, "Ultra-Light" },
868   { PANGO_WEIGHT_ULTRALIGHT, "Extra-Light" },
869   { PANGO_WEIGHT_LIGHT, "Light" },
870   { PANGO_WEIGHT_BOOK, "Book" },
871   { PANGO_WEIGHT_NORMAL, "" },
872   { PANGO_WEIGHT_NORMAL, "Regular" },
873   { PANGO_WEIGHT_MEDIUM, "Medium" },
874   { PANGO_WEIGHT_SEMIBOLD, "Semi-Bold" },
875   { PANGO_WEIGHT_SEMIBOLD, "Demi-Bold" },
876   { PANGO_WEIGHT_BOLD, "Bold" },
877   { PANGO_WEIGHT_ULTRABOLD, "Ultra-Bold" },
878   { PANGO_WEIGHT_ULTRABOLD, "Extra-Bold" },
879   { PANGO_WEIGHT_HEAVY, "Heavy" },
880   { PANGO_WEIGHT_HEAVY, "Black" },
881   { PANGO_WEIGHT_ULTRAHEAVY, "Ultra-Heavy" },
882   { PANGO_WEIGHT_ULTRAHEAVY, "Extra-Heavy" },
883   { PANGO_WEIGHT_ULTRAHEAVY, "Ultra-Black" },
884   { PANGO_WEIGHT_ULTRAHEAVY, "Extra-Black" }
885 };
886
887 static const FieldMap stretch_map[] = {
888   { PANGO_STRETCH_ULTRA_CONDENSED, "Ultra-Condensed" },
889   { PANGO_STRETCH_EXTRA_CONDENSED, "Extra-Condensed" },
890   { PANGO_STRETCH_CONDENSED,       "Condensed" },
891   { PANGO_STRETCH_SEMI_CONDENSED,  "Semi-Condensed" },
892   { PANGO_STRETCH_NORMAL,          "" },
893   { PANGO_STRETCH_SEMI_EXPANDED,   "Semi-Expanded" },
894   { PANGO_STRETCH_EXPANDED,        "Expanded" },
895   { PANGO_STRETCH_EXTRA_EXPANDED,  "Extra-Expanded" },
896   { PANGO_STRETCH_ULTRA_EXPANDED,  "Ultra-Expanded" }
897 };
898
899 static const FieldMap gravity_map[] = {
900   { PANGO_GRAVITY_SOUTH, "Not-Rotated" },
901   { PANGO_GRAVITY_SOUTH, "South" },
902   { PANGO_GRAVITY_SOUTH, "Upside-Down" },
903   { PANGO_GRAVITY_NORTH, "North" },
904   { PANGO_GRAVITY_EAST,  "Rotated-Left" },
905   { PANGO_GRAVITY_EAST,  "East" },
906   { PANGO_GRAVITY_WEST,  "Rotated-Right" },
907   { PANGO_GRAVITY_WEST,  "West" }
908 };
909
910 static gboolean
911 field_matches (const gchar *s1,
912                const gchar *s2,
913                gsize n)
914 {
915   gint c1, c2;
916
917   g_return_val_if_fail (s1 != NULL, 0);
918   g_return_val_if_fail (s2 != NULL, 0);
919
920   while (n && *s1 && *s2)
921     {
922       c1 = (gint)(guchar) TOLOWER (*s1);
923       c2 = (gint)(guchar) TOLOWER (*s2);
924       if (c1 != c2) {
925         if (c1 == '-') {
926           s1++;
927           continue;
928         }
929         return FALSE;
930       }
931       s1++; s2++;
932       n--;
933     }
934
935   return n == 0 && *s1 == '\0';
936 }
937
938 static gboolean
939 parse_int (const char *word,
940            size_t      wordlen,
941            int        *out)
942 {
943   char *end;
944   long val = strtol (word, &end, 10);
945   int i = val;
946
947   if (end != word && (end == word + wordlen) && val >= 0 && val == i)
948     {
949       if (out)
950         *out = i;
951
952       return TRUE;
953     }
954
955   return FALSE;
956 }
957
958 static gboolean
959 find_field (const char *what,
960             const FieldMap *map,
961             int n_elements,
962             const char *str,
963             int len,
964             int *val)
965 {
966   int i;
967   gboolean had_prefix = FALSE;
968
969   if (what)
970     {
971       i = strlen (what);
972       if (len > i && 0 == strncmp (what, str, i) && str[i] == '=')
973         {
974           str += i + 1;
975           len -= i + 1;
976           had_prefix = TRUE;
977         }
978     }
979
980   for (i=0; i<n_elements; i++)
981     {
982       if (map[i].str[0] && field_matches (map[i].str, str, len))
983         {
984           if (val)
985             *val = map[i].value;
986           return TRUE;
987         }
988     }
989
990   if (!what || had_prefix)
991     return parse_int (str, len, val);
992
993   return FALSE;
994 }
995
996 static gboolean
997 find_field_any (const char *str, int len, PangoFontDescription *desc)
998 {
999   if (field_matches ("Normal", str, len))
1000     return TRUE;
1001
1002 #define FIELD(NAME, MASK) \
1003   G_STMT_START { \
1004   if (find_field (G_STRINGIFY (NAME), NAME##_map, G_N_ELEMENTS (NAME##_map), str, len, \
1005                   desc ? (int *)(void *)&desc->NAME : NULL)) \
1006     { \
1007       if (desc) \
1008         desc->mask |= MASK; \
1009       return TRUE; \
1010     } \
1011   } G_STMT_END
1012
1013   FIELD (weight,  PANGO_FONT_MASK_WEIGHT);
1014   FIELD (style,   PANGO_FONT_MASK_STYLE);
1015   FIELD (stretch, PANGO_FONT_MASK_STRETCH);
1016   FIELD (variant, PANGO_FONT_MASK_VARIANT);
1017   FIELD (gravity, PANGO_FONT_MASK_GRAVITY);
1018
1019 #undef FIELD
1020
1021   return FALSE;
1022 }
1023
1024 static const char *
1025 getword (const char *str, const char *last, size_t *wordlen)
1026 {
1027   const char *result;
1028
1029   while (last > str && g_ascii_isspace (*(last - 1)))
1030     last--;
1031
1032   result = last;
1033   while (result > str && !g_ascii_isspace (*(result - 1)) && *(result - 1) != ',')
1034     result--;
1035
1036   *wordlen = last - result;
1037
1038   return result;
1039 }
1040
1041 static gboolean
1042 parse_size (const char *word,
1043             size_t      wordlen,
1044             int        *pango_size,
1045             gboolean   *size_is_absolute)
1046 {
1047   char *end;
1048   double size = g_ascii_strtod (word, &end);
1049
1050   if (end != word &&
1051       (end == word + wordlen ||
1052        (end + 2 == word + wordlen && !strncmp (end, "px", 2))
1053       ) && size >= 0 && size <= 1000000) /* word is a valid float */
1054     {
1055       if (pango_size)
1056         *pango_size = (int)(size * PANGO_SCALE + 0.5);
1057
1058       if (size_is_absolute)
1059         *size_is_absolute = end < word + wordlen;
1060
1061       return TRUE;
1062     }
1063
1064   return FALSE;
1065 }
1066
1067 /**
1068  * pango_font_description_from_string:
1069  * @str: string representation of a font description.
1070  *
1071  * Creates a new font description from a string representation in the
1072  * form "[FAMILY-LIST] [STYLE-OPTIONS] [SIZE]", where FAMILY-LIST is a
1073  * comma separated list of families optionally terminated by a comma,
1074  * STYLE_OPTIONS is a whitespace separated list of words where each WORD
1075  * describes one of style, variant, weight, stretch, or gravity, and SIZE
1076  * is a decimal number (size in points) or optionally followed by the
1077  * unit modifier "px" for absolute size. Any one of the options may
1078  * be absent.  If FAMILY-LIST is absent, then the family_name field of
1079  * the resulting font description will be initialized to %NULL.  If
1080  * STYLE-OPTIONS is missing, then all style options will be set to the
1081  * default values. If SIZE is missing, the size in the resulting font
1082  * description will be set to 0.
1083  *
1084  * Return value: a new #PangoFontDescription.
1085  **/
1086 PangoFontDescription *
1087 pango_font_description_from_string (const char *str)
1088 {
1089   PangoFontDescription *desc;
1090   const char *p, *last;
1091   size_t len, wordlen;
1092
1093   g_return_val_if_fail (str != NULL, NULL);
1094
1095   desc = pango_font_description_new ();
1096
1097   desc->mask = PANGO_FONT_MASK_STYLE |
1098                PANGO_FONT_MASK_WEIGHT |
1099                PANGO_FONT_MASK_VARIANT |
1100                PANGO_FONT_MASK_STRETCH;
1101
1102   len = strlen (str);
1103   last = str + len;
1104   p = getword (str, last, &wordlen);
1105
1106   /* Look for a size at the end of the string
1107    */
1108   if (wordlen != 0)
1109     {
1110       gboolean size_is_absolute;
1111       if (parse_size (p, wordlen, &desc->size, &size_is_absolute))
1112         {
1113           desc->size_is_absolute = size_is_absolute;
1114           desc->mask |= PANGO_FONT_MASK_SIZE;
1115           last = p;
1116         }
1117     }
1118
1119   /* Now parse style words
1120    */
1121   p = getword (str, last, &wordlen);
1122   while (wordlen != 0)
1123     {
1124       if (!find_field_any (p, wordlen, desc))
1125         break;
1126       else
1127         {
1128           last = p;
1129           p = getword (str, last, &wordlen);
1130         }
1131     }
1132
1133   /* Remainder (str => p) is family list. Trim off trailing commas and leading and trailing white space
1134    */
1135
1136   while (last > str && g_ascii_isspace (*(last - 1)))
1137     last--;
1138
1139   if (last > str && *(last - 1) == ',')
1140     last--;
1141
1142   while (last > str && g_ascii_isspace (*(last - 1)))
1143     last--;
1144
1145   while (last > str && g_ascii_isspace (*str))
1146     str++;
1147
1148   if (str != last)
1149     {
1150       int i;
1151       char **families;
1152
1153       desc->family_name = g_strndup (str, last - str);
1154
1155       /* Now sanitize it to trim space from around individual family names.
1156        * bug #499624 */
1157
1158       families = g_strsplit (desc->family_name, ",", -1);
1159
1160       for (i = 0; families[i]; i++)
1161         g_strstrip (families[i]);
1162
1163       g_free (desc->family_name);
1164       desc->family_name = g_strjoinv (",", families);
1165       g_strfreev (families);
1166
1167       desc->mask |= PANGO_FONT_MASK_FAMILY;
1168     }
1169
1170   return desc;
1171 }
1172
1173 static void
1174 append_field (GString *str, const char *what, const FieldMap *map, int n_elements, int val)
1175 {
1176   int i;
1177   for (i=0; i<n_elements; i++)
1178     {
1179       if (map[i].value != val)
1180         continue;
1181
1182       if (G_LIKELY (map[i].str && map[i].str[0]))
1183         {
1184           if (G_LIKELY (str->len > 0 && str->str[str->len -1] != ' '))
1185             g_string_append_c (str, ' ');
1186           g_string_append (str, map[i].str);
1187         }
1188       return;
1189     }
1190
1191   if (G_LIKELY (str->len > 0 || str->str[str->len -1] != ' '))
1192     g_string_append_c (str, ' ');
1193   g_string_append_printf (str, "%s=%d", what, val);
1194 }
1195
1196 /**
1197  * pango_font_description_to_string:
1198  * @desc: a #PangoFontDescription
1199  *
1200  * Creates a string representation of a font description. See
1201  * pango_font_description_from_string() for a description of the
1202  * format of the string representation. The family list in the
1203  * string description will only have a terminating comma if the
1204  * last word of the list is a valid style option.
1205  *
1206  * Return value: a new string that must be freed with g_free().
1207  **/
1208 char *
1209 pango_font_description_to_string (const PangoFontDescription  *desc)
1210 {
1211   GString *result;
1212
1213   g_return_val_if_fail (desc != NULL, NULL);
1214
1215   result = g_string_new (NULL);
1216
1217   if (G_LIKELY (desc->family_name && desc->mask & PANGO_FONT_MASK_FAMILY))
1218     {
1219       const char *p;
1220       size_t wordlen;
1221
1222       g_string_append (result, desc->family_name);
1223
1224       /* We need to add a trailing comma if the family name ends
1225        * in a keyword like "Bold", or if the family name ends in
1226        * a number and no keywords will be added.
1227        */
1228       p = getword (desc->family_name, desc->family_name + strlen(desc->family_name), &wordlen);
1229       if (wordlen != 0 &&
1230           (find_field_any (p, wordlen, NULL) ||
1231            (parse_size (p, wordlen, NULL, NULL) &&
1232             desc->weight == PANGO_WEIGHT_NORMAL &&
1233             desc->style == PANGO_STYLE_NORMAL &&
1234             desc->stretch == PANGO_STRETCH_NORMAL &&
1235             desc->variant == PANGO_VARIANT_NORMAL &&
1236             (desc->mask & (PANGO_FONT_MASK_GRAVITY | PANGO_FONT_MASK_SIZE)) == 0)))
1237         g_string_append_c (result, ',');
1238     }
1239
1240 #define FIELD(NAME, MASK) \
1241   append_field (result, G_STRINGIFY (NAME), NAME##_map, G_N_ELEMENTS (NAME##_map), desc->NAME)
1242
1243   FIELD (weight,  PANGO_FONT_MASK_WEIGHT);
1244   FIELD (style,   PANGO_FONT_MASK_STYLE);
1245   FIELD (stretch, PANGO_FONT_MASK_STRETCH);
1246   FIELD (variant, PANGO_FONT_MASK_VARIANT);
1247   if (desc->mask & PANGO_FONT_MASK_GRAVITY)
1248     FIELD (gravity, PANGO_FONT_MASK_GRAVITY);
1249
1250 #undef FIELD
1251
1252   if (result->len == 0)
1253     g_string_append (result, "Normal");
1254
1255   if (desc->mask & PANGO_FONT_MASK_SIZE)
1256     {
1257       char buf[G_ASCII_DTOSTR_BUF_SIZE];
1258
1259       if (result->len > 0 || result->str[result->len -1] != ' ')
1260         g_string_append_c (result, ' ');
1261
1262       g_ascii_dtostr (buf, sizeof (buf), (double)desc->size / PANGO_SCALE);
1263       g_string_append (result, buf);
1264
1265       if (desc->size_is_absolute)
1266         g_string_append (result, "px");
1267     }
1268
1269   return g_string_free (result, FALSE);
1270 }
1271
1272 /**
1273  * pango_font_description_to_filename:
1274  * @desc: a #PangoFontDescription
1275  *
1276  * Creates a filename representation of a font description. The
1277  * filename is identical to the result from calling
1278  * pango_font_description_to_string(), but with underscores instead of
1279  * characters that are untypical in filenames, and in lower case only.
1280  *
1281  * Return value: a new string that must be freed with g_free().
1282  **/
1283 char *
1284 pango_font_description_to_filename (const PangoFontDescription  *desc)
1285 {
1286   char *result;
1287   char *p;
1288
1289   g_return_val_if_fail (desc != NULL, NULL);
1290
1291   result = pango_font_description_to_string (desc);
1292
1293   p = result;
1294   while (*p)
1295     {
1296       if (G_UNLIKELY ((guchar) *p >= 128))
1297         /* skip over non-ASCII chars */;
1298       else if (strchr ("-+_.", *p) == NULL && !g_ascii_isalnum (*p))
1299         *p = '_';
1300       else
1301         *p = g_ascii_tolower (*p);
1302       p++;
1303     }
1304
1305   return result;
1306 }
1307
1308
1309 static gboolean
1310 parse_field (const char *what,
1311              const FieldMap *map,
1312              int n_elements,
1313              const char *str,
1314              int *val,
1315              gboolean warn)
1316 {
1317   gboolean found;
1318   int len = strlen (str);
1319
1320   if (G_UNLIKELY (*str == '\0'))
1321     return FALSE;
1322
1323   if (field_matches ("Normal", str, len))
1324     {
1325       /* find the map entry with empty string */
1326       int i;
1327
1328       for (i = 0; i < n_elements; i++)
1329         if (map[i].str[0] == '\0')
1330           {
1331             *val = map[i].value;
1332             return TRUE;
1333           }
1334
1335       *val = 0;
1336       return TRUE;
1337     }
1338
1339   found = find_field (NULL, map, n_elements, str, len, val);
1340
1341   if (!found && warn)
1342     {
1343         int i;
1344         GString *s = g_string_new (NULL);
1345
1346         for (i = 0; i < n_elements; i++)
1347           {
1348             if (i)
1349               g_string_append_c (s, '/');
1350             g_string_append (s, map[i].str[0] == '\0' ? "Normal" : map[i].str);
1351           }
1352
1353         g_warning ("%s must be one of %s or a number",
1354                    what,
1355                    s->str);
1356
1357         g_string_free (s, TRUE);
1358     }
1359
1360   return found;
1361 }
1362
1363 #define FIELD(NAME, MASK) \
1364   parse_field (G_STRINGIFY (NAME), NAME##_map, G_N_ELEMENTS (NAME##_map), str, (int *)(void *)NAME, warn)
1365
1366 /**
1367  * pango_parse_style:
1368  * @str: a string to parse.
1369  * @style: a #PangoStyle to store the result in.
1370  * @warn: if %TRUE, issue a g_warning() on bad input.
1371  *
1372  * Parses a font style. The allowed values are "normal",
1373  * "italic" and "oblique", case variations being
1374  * ignored.
1375  *
1376  * Return value: %TRUE if @str was successfully parsed.
1377  **/
1378 gboolean
1379 pango_parse_style (const char *str,
1380                    PangoStyle *style,
1381                    gboolean    warn)
1382 {
1383   return FIELD (style,   PANGO_FONT_MASK_STYLE);
1384 }
1385
1386 /**
1387  * pango_parse_variant:
1388  * @str: a string to parse.
1389  * @variant: a #PangoVariant to store the result in.
1390  * @warn: if %TRUE, issue a g_warning() on bad input.
1391  *
1392  * Parses a font variant. The allowed values are "normal"
1393  * and "smallcaps" or "small_caps", case variations being
1394  * ignored.
1395  *
1396  * Return value: %TRUE if @str was successfully parsed.
1397  **/
1398 gboolean
1399 pango_parse_variant (const char   *str,
1400                      PangoVariant *variant,
1401                      gboolean      warn)
1402 {
1403   return FIELD (variant, PANGO_FONT_MASK_VARIANT);
1404 }
1405
1406 /**
1407  * pango_parse_weight:
1408  * @str: a string to parse.
1409  * @weight: a #PangoWeight to store the result in.
1410  * @warn: if %TRUE, issue a g_warning() on bad input.
1411  *
1412  * Parses a font weight. The allowed values are "heavy",
1413  * "ultrabold", "bold", "normal", "light", "ultraleight"
1414  * and integers. Case variations are ignored.
1415  *
1416  * Return value: %TRUE if @str was successfully parsed.
1417  **/
1418 gboolean
1419 pango_parse_weight (const char  *str,
1420                     PangoWeight *weight,
1421                     gboolean     warn)
1422 {
1423   return FIELD (weight,  PANGO_FONT_MASK_WEIGHT);
1424 }
1425
1426 /**
1427  * pango_parse_stretch:
1428  * @str: a string to parse.
1429  * @stretch: a #PangoStretch to store the result in.
1430  * @warn: if %TRUE, issue a g_warning() on bad input.
1431  *
1432  * Parses a font stretch. The allowed values are
1433  * "ultra_condensed", "extra_condensed", "condensed",
1434  * "semi_condensed", "normal", "semi_expanded", "expanded",
1435  * "extra_expanded" and "ultra_expanded". Case variations are
1436  * ignored and the '_' characters may be omitted.
1437  *
1438  * Return value: %TRUE if @str was successfully parsed.
1439  **/
1440 gboolean
1441 pango_parse_stretch (const char   *str,
1442                      PangoStretch *stretch,
1443                      gboolean      warn)
1444 {
1445   return FIELD (stretch, PANGO_FONT_MASK_STRETCH);
1446 }
1447
1448
1449
1450
1451 /*
1452  * PangoFont
1453  */
1454
1455 G_DEFINE_ABSTRACT_TYPE (PangoFont, pango_font, G_TYPE_OBJECT)
1456
1457 static void
1458 pango_font_class_init (PangoFontClass *class G_GNUC_UNUSED)
1459 {
1460 }
1461
1462 static void
1463 pango_font_init (PangoFont *font G_GNUC_UNUSED)
1464 {
1465 }
1466
1467 /**
1468  * pango_font_describe:
1469  * @font: a #PangoFont
1470  *
1471  * Returns a description of the font, with font size set in points.
1472  * Use pango_font_describe_with_absolute_size() if you want the font
1473  * size in device units.
1474  *
1475  * Return value: a newly-allocated #PangoFontDescription object.
1476  **/
1477 PangoFontDescription *
1478 pango_font_describe (PangoFont      *font)
1479 {
1480   g_return_val_if_fail (font != NULL, NULL);
1481
1482   return PANGO_FONT_GET_CLASS (font)->describe (font);
1483 }
1484
1485 /**
1486  * pango_font_describe_with_absolute_size:
1487  * @font: a #PangoFont
1488  *
1489  * Returns a description of the font, with absolute font size set
1490  * (in device units). Use pango_font_describe() if you want the font
1491  * size in points.
1492  *
1493  * Return value: a newly-allocated #PangoFontDescription object.
1494  *
1495  * Since: 1.14
1496  **/
1497 PangoFontDescription *
1498 pango_font_describe_with_absolute_size (PangoFont      *font)
1499 {
1500   g_return_val_if_fail (font != NULL, NULL);
1501
1502   if (G_UNLIKELY (!PANGO_FONT_GET_CLASS (font)->describe_absolute))
1503     {
1504       g_warning ("describe_absolute not implemented for this font class, report this as a bug");
1505       return pango_font_describe (font);
1506     }
1507
1508   return PANGO_FONT_GET_CLASS (font)->describe_absolute (font);
1509 }
1510
1511 /**
1512  * pango_font_get_coverage:
1513  * @font: a #PangoFont
1514  * @language: the language tag
1515  *
1516  * Computes the coverage map for a given font and language tag.
1517  *
1518  * Return value: a newly-allocated #PangoCoverage object.
1519  **/
1520 PangoCoverage *
1521 pango_font_get_coverage (PangoFont     *font,
1522                          PangoLanguage *language)
1523 {
1524   g_return_val_if_fail (font != NULL, NULL);
1525
1526   return PANGO_FONT_GET_CLASS (font)->get_coverage (font, language);
1527 }
1528
1529 /**
1530  * pango_font_find_shaper:
1531  * @font: a #PangoFont
1532  * @language: the language tag
1533  * @ch: a Unicode character.
1534  *
1535  * Finds the best matching shaper for a font for a particular
1536  * language tag and character point.
1537  *
1538  * Return value: the best matching shaper.
1539  **/
1540 PangoEngineShape *
1541 pango_font_find_shaper (PangoFont     *font,
1542                         PangoLanguage *language,
1543                         guint32        ch)
1544 {
1545   PangoEngineShape* shaper;
1546
1547   g_return_val_if_fail (font != NULL, NULL);
1548
1549   shaper = PANGO_FONT_GET_CLASS (font)->find_shaper (font, language, ch);
1550
1551   return shaper;
1552 }
1553
1554 /**
1555  * pango_font_get_glyph_extents:
1556  * @font: a #PangoFont
1557  * @glyph: the glyph index
1558  * @ink_rect: rectangle used to store the extents of the glyph as drawn
1559  *            or %NULL to indicate that the result is not needed.
1560  * @logical_rect: rectangle used to store the logical extents of the glyph
1561  *            or %NULL to indicate that the result is not needed.
1562  *
1563  * Gets the logical and ink extents of a glyph within a font. The
1564  * coordinate system for each rectangle has its origin at the
1565  * base line and horizontal origin of the character with increasing
1566  * coordinates extending to the right and down. The macros PANGO_ASCENT(),
1567  * PANGO_DESCENT(), PANGO_LBEARING(), and PANGO_RBEARING() can be used to convert
1568  * from the extents rectangle to more traditional font metrics. The units
1569  * of the rectangles are in 1/PANGO_SCALE of a device unit.
1570  *
1571  * If @font is %NULL, this function gracefully sets some sane values in the
1572  * output variables and returns.
1573  **/
1574 void
1575 pango_font_get_glyph_extents  (PangoFont      *font,
1576                                PangoGlyph      glyph,
1577                                PangoRectangle *ink_rect,
1578                                PangoRectangle *logical_rect)
1579 {
1580   if (G_UNLIKELY (!font))
1581     {
1582       if (ink_rect)
1583         {
1584           ink_rect->x = PANGO_SCALE;
1585           ink_rect->y = - (PANGO_UNKNOWN_GLYPH_HEIGHT - 1) * PANGO_SCALE;
1586           ink_rect->height = (PANGO_UNKNOWN_GLYPH_HEIGHT - 2) * PANGO_SCALE;
1587           ink_rect->width = (PANGO_UNKNOWN_GLYPH_WIDTH - 2) * PANGO_SCALE;
1588         }
1589       if (logical_rect)
1590         {
1591           logical_rect->x = logical_rect->y = 0;
1592           logical_rect->y = - PANGO_UNKNOWN_GLYPH_HEIGHT * PANGO_SCALE;
1593           logical_rect->height = PANGO_UNKNOWN_GLYPH_HEIGHT * PANGO_SCALE;
1594           logical_rect->width = PANGO_UNKNOWN_GLYPH_WIDTH * PANGO_SCALE;
1595         }
1596       return;
1597     }
1598
1599   PANGO_FONT_GET_CLASS (font)->get_glyph_extents (font, glyph, ink_rect, logical_rect);
1600 }
1601
1602 /**
1603  * pango_font_get_metrics:
1604  * @font: a #PangoFont
1605  * @language: language tag used to determine which script to get the metrics
1606  *            for, or %NULL to indicate to get the metrics for the entire
1607  *            font.
1608  *
1609  * Gets overall metric information for a font. Since the metrics may be
1610  * substantially different for different scripts, a language tag can
1611  * be provided to indicate that the metrics should be retrieved that
1612  * correspond to the script(s) used by that language.
1613  *
1614  * If @font is %NULL, this function gracefully sets some sane values in the
1615  * output variables and returns.
1616  *
1617  * Return value: a #PangoFontMetrics object. The caller must call pango_font_metrics_unref()
1618  *   when finished using the object.
1619  **/
1620 PangoFontMetrics *
1621 pango_font_get_metrics (PangoFont        *font,
1622                         PangoLanguage    *language)
1623 {
1624   if (G_UNLIKELY (!font))
1625     {
1626       PangoFontMetrics *metrics = pango_font_metrics_new ();
1627
1628       metrics->ascent = PANGO_SCALE * PANGO_UNKNOWN_GLYPH_HEIGHT;
1629       metrics->descent = 0;
1630       metrics->approximate_char_width = PANGO_SCALE * PANGO_UNKNOWN_GLYPH_WIDTH;
1631       metrics->approximate_digit_width = PANGO_SCALE * PANGO_UNKNOWN_GLYPH_WIDTH;
1632       metrics->underline_position = -PANGO_SCALE;
1633       metrics->underline_thickness = PANGO_SCALE;
1634       metrics->strikethrough_position = PANGO_SCALE * PANGO_UNKNOWN_GLYPH_HEIGHT / 2;
1635       metrics->strikethrough_thickness = PANGO_SCALE;
1636
1637       return metrics;
1638     }
1639
1640   return PANGO_FONT_GET_CLASS (font)->get_metrics (font, language);
1641 }
1642
1643 /**
1644  * pango_font_get_font_map:
1645  * @font: a #PangoFont, or %NULL
1646  *
1647  * Gets the font map for which the font was created.
1648  *
1649  * Note that the font maintains a <firstterm>weak</firstterm> reference
1650  * to the font map, so if all references to font map are dropped, the font
1651  * map will be finalized even if there are fonts created with the font
1652  * map that are still alive.  In that case this function will return %NULL.
1653  * It is the responsibility of the user to ensure that the font map is kept
1654  * alive.  In most uses this is not an issue as a #PangoContext holds
1655  * a reference to the font map.
1656  *
1657  * Return value: the #PangoFontMap for the font, or %NULL if @font is %NULL.
1658  *
1659  * Since: 1.10
1660  **/
1661 PangoFontMap *
1662 pango_font_get_font_map (PangoFont *font)
1663 {
1664   if (G_UNLIKELY (!font))
1665     return NULL;
1666
1667   if (PANGO_FONT_GET_CLASS (font)->get_font_map)
1668     return PANGO_FONT_GET_CLASS (font)->get_font_map (font);
1669   else
1670     return NULL;
1671 }
1672
1673 GType
1674 pango_font_metrics_get_type (void)
1675 {
1676   static GType our_type = 0;
1677
1678   if (G_UNLIKELY (our_type == 0))
1679     our_type = g_boxed_type_register_static (I_("PangoFontMetrics"),
1680                                              (GBoxedCopyFunc)pango_font_metrics_ref,
1681                                              (GBoxedFreeFunc)pango_font_metrics_unref);
1682
1683   return our_type;
1684 }
1685
1686
1687 /**
1688  * pango_font_metrics_new:
1689  *
1690  * Creates a new #PangoFontMetrics structure. This is only for
1691  * internal use by Pango backends and there is no public way
1692  * to set the fields of the structure.
1693  *
1694  * Return value: a newly-created #PangoFontMetrics structure
1695  *   with a reference count of 1.
1696  **/
1697 PangoFontMetrics *
1698 pango_font_metrics_new (void)
1699 {
1700   PangoFontMetrics *metrics = g_slice_new0 (PangoFontMetrics);
1701   metrics->ref_count = 1;
1702
1703   return metrics;
1704 }
1705
1706 /**
1707  * pango_font_metrics_ref:
1708  * @metrics: a #PangoFontMetrics structure, may be %NULL
1709  *
1710  * Increase the reference count of a font metrics structure by one.
1711  *
1712  * Return value: @metrics
1713  **/
1714 PangoFontMetrics *
1715 pango_font_metrics_ref (PangoFontMetrics *metrics)
1716 {
1717   if (metrics == NULL)
1718     return NULL;
1719
1720   g_atomic_int_inc ((int *) &metrics->ref_count);
1721
1722   return metrics;
1723 }
1724
1725 /**
1726  * pango_font_metrics_unref:
1727  * @metrics: a #PangoFontMetrics structure, may be %NULL
1728  *
1729  * Decrease the reference count of a font metrics structure by one. If
1730  * the result is zero, frees the structure and any associated
1731  * memory.
1732  **/
1733 void
1734 pango_font_metrics_unref (PangoFontMetrics *metrics)
1735 {
1736   if (metrics == NULL)
1737     return;
1738
1739   g_return_if_fail (metrics->ref_count > 0 );
1740
1741   if (g_atomic_int_dec_and_test ((int *) &metrics->ref_count))
1742     g_slice_free (PangoFontMetrics, metrics);
1743 }
1744
1745 /**
1746  * pango_font_metrics_get_ascent:
1747  * @metrics: a #PangoFontMetrics structure
1748  *
1749  * Gets the ascent from a font metrics structure. The ascent is
1750  * the distance from the baseline to the logical top of a line
1751  * of text. (The logical top may be above or below the top of the
1752  * actual drawn ink. It is necessary to lay out the text to figure
1753  * where the ink will be.)
1754  *
1755  * Return value: the ascent, in Pango units.
1756  **/
1757 int
1758 pango_font_metrics_get_ascent (PangoFontMetrics *metrics)
1759 {
1760   g_return_val_if_fail (metrics != NULL, 0);
1761
1762   return metrics->ascent;
1763 }
1764
1765 /**
1766  * pango_font_metrics_get_descent:
1767  * @metrics: a #PangoFontMetrics structure
1768  *
1769  * Gets the descent from a font metrics structure. The descent is
1770  * the distance from the baseline to the logical bottom of a line
1771  * of text. (The logical bottom may be above or below the bottom of the
1772  * actual drawn ink. It is necessary to lay out the text to figure
1773  * where the ink will be.)
1774  *
1775  * Return value: the descent, in Pango units.
1776  **/
1777 int
1778 pango_font_metrics_get_descent (PangoFontMetrics *metrics)
1779 {
1780   g_return_val_if_fail (metrics != NULL, 0);
1781
1782   return metrics->descent;
1783 }
1784
1785 /**
1786  * pango_font_metrics_get_approximate_char_width:
1787  * @metrics: a #PangoFontMetrics structure
1788  *
1789  * Gets the approximate character width for a font metrics structure.
1790  * This is merely a representative value useful, for example, for
1791  * determining the initial size for a window. Actual characters in
1792  * text will be wider and narrower than this.
1793  *
1794  * Return value: the character width, in Pango units.
1795  **/
1796 int
1797 pango_font_metrics_get_approximate_char_width (PangoFontMetrics *metrics)
1798 {
1799   g_return_val_if_fail (metrics != NULL, 0);
1800
1801   return metrics->approximate_char_width;
1802 }
1803
1804 /**
1805  * pango_font_metrics_get_approximate_digit_width:
1806  * @metrics: a #PangoFontMetrics structure
1807  *
1808  * Gets the approximate digit width for a font metrics structure.
1809  * This is merely a representative value useful, for example, for
1810  * determining the initial size for a window. Actual digits in
1811  * text can be wider or narrower than this, though this value
1812  * is generally somewhat more accurate than the result of
1813  * pango_font_metrics_get_approximate_char_width() for digits.
1814  *
1815  * Return value: the digit width, in Pango units.
1816  **/
1817 int
1818 pango_font_metrics_get_approximate_digit_width (PangoFontMetrics *metrics)
1819 {
1820   g_return_val_if_fail (metrics != NULL, 0);
1821
1822   return metrics->approximate_digit_width;
1823 }
1824
1825 /**
1826  * pango_font_metrics_get_underline_position:
1827  * @metrics: a #PangoFontMetrics structure
1828  *
1829  * Gets the suggested position to draw the underline.
1830  * The value returned is the distance <emphasis>above</emphasis> the
1831  * baseline of the top of the underline. Since most fonts have
1832  * underline positions beneath the baseline, this value is typically
1833  * negative.
1834  *
1835  * Return value: the suggested underline position, in Pango units.
1836  *
1837  * Since: 1.6
1838  **/
1839 int
1840 pango_font_metrics_get_underline_position (PangoFontMetrics *metrics)
1841 {
1842   g_return_val_if_fail (metrics != NULL, 0);
1843
1844   return metrics->underline_position;
1845 }
1846
1847 /**
1848  * pango_font_metrics_get_underline_thickness:
1849  * @metrics: a #PangoFontMetrics structure
1850  *
1851  * Gets the suggested thickness to draw for the underline.
1852  *
1853  * Return value: the suggested underline thickness, in Pango units.
1854  *
1855  * Since: 1.6
1856  **/
1857 int
1858 pango_font_metrics_get_underline_thickness (PangoFontMetrics *metrics)
1859 {
1860   g_return_val_if_fail (metrics != NULL, 0);
1861
1862   return metrics->underline_thickness;
1863 }
1864
1865 /**
1866  * pango_font_metrics_get_strikethrough_position:
1867  * @metrics: a #PangoFontMetrics structure
1868  *
1869  * Gets the suggested position to draw the strikethrough.
1870  * The value returned is the distance <emphasis>above</emphasis> the
1871  * baseline of the top of the strikethrough.
1872  *
1873  * Return value: the suggested strikethrough position, in Pango units.
1874  *
1875  * Since: 1.6
1876  **/
1877 int
1878 pango_font_metrics_get_strikethrough_position (PangoFontMetrics *metrics)
1879 {
1880   g_return_val_if_fail (metrics != NULL, 0);
1881
1882   return metrics->strikethrough_position;
1883 }
1884
1885 /**
1886  * pango_font_metrics_get_strikethrough_thickness:
1887  * @metrics: a #PangoFontMetrics structure
1888  *
1889  * Gets the suggested thickness to draw for the strikethrough.
1890  *
1891  * Return value: the suggested strikethrough thickness, in Pango units.
1892  *
1893  * Since: 1.6
1894  **/
1895 int
1896 pango_font_metrics_get_strikethrough_thickness (PangoFontMetrics *metrics)
1897 {
1898   g_return_val_if_fail (metrics != NULL, 0);
1899
1900   return metrics->strikethrough_thickness;
1901 }
1902
1903 /*
1904  * PangoFontFamily
1905  */
1906
1907 G_DEFINE_ABSTRACT_TYPE (PangoFontFamily, pango_font_family, G_TYPE_OBJECT)
1908
1909 static void
1910 pango_font_family_class_init (PangoFontFamilyClass *class G_GNUC_UNUSED)
1911 {
1912 }
1913
1914 static void
1915 pango_font_family_init (PangoFontFamily *family G_GNUC_UNUSED)
1916 {
1917 }
1918
1919 /**
1920  * pango_font_family_get_name:
1921  * @family: a #PangoFontFamily
1922  *
1923  * Gets the name of the family. The name is unique among all
1924  * fonts for the font backend and can be used in a #PangoFontDescription
1925  * to specify that a face from this family is desired.
1926  *
1927  * Return value: the name of the family. This string is owned
1928  *   by the family object and must not be modified or freed.
1929  **/
1930 G_CONST_RETURN char *
1931 pango_font_family_get_name (PangoFontFamily  *family)
1932 {
1933   g_return_val_if_fail (PANGO_IS_FONT_FAMILY (family), NULL);
1934
1935   return PANGO_FONT_FAMILY_GET_CLASS (family)->get_name (family);
1936 }
1937
1938 /**
1939  * pango_font_family_list_faces:
1940  * @family: a #PangoFontFamily
1941  * @faces: location to store an array of pointers to #PangoFontFace
1942  *   objects, or %NULL. This array should be freed with g_free()
1943  *   when it is no longer needed.
1944  * @n_faces: location to store number of elements in @faces.
1945  *
1946  * Lists the different font faces that make up @family. The faces
1947  * in a family share a common design, but differ in slant, weight,
1948  * width and other aspects.
1949  **/
1950 void
1951 pango_font_family_list_faces (PangoFontFamily  *family,
1952                               PangoFontFace  ***faces,
1953                               int              *n_faces)
1954 {
1955   g_return_if_fail (PANGO_IS_FONT_FAMILY (family));
1956
1957   PANGO_FONT_FAMILY_GET_CLASS (family)->list_faces (family, faces, n_faces);
1958 }
1959
1960 /**
1961  * pango_font_family_is_monospace:
1962  * @family: a #PangoFontFamily
1963  *
1964  * A monospace font is a font designed for text display where the the
1965  * characters form a regular grid. For Western languages this would
1966  * mean that the advance width of all characters are the same, but
1967  * this categorization also includes Asian fonts which include
1968  * double-width characters: characters that occupy two grid cells.
1969  * g_unichar_iswide() returns a result that indicates whether a
1970  * character is typically double-width in a monospace font.
1971  *
1972  * The best way to find out the grid-cell size is to call
1973  * pango_font_metrics_get_approximate_digit_width(), since the results
1974  * of pango_font_metrics_get_approximate_char_width() may be affected
1975  * by double-width characters.
1976  *
1977  * Return value: %TRUE if the family is monospace.
1978  *
1979  * Since: 1.4
1980  **/
1981 gboolean
1982 pango_font_family_is_monospace (PangoFontFamily  *family)
1983 {
1984   g_return_val_if_fail (PANGO_IS_FONT_FAMILY (family), FALSE);
1985
1986   if (PANGO_FONT_FAMILY_GET_CLASS (family)->is_monospace)
1987     return PANGO_FONT_FAMILY_GET_CLASS (family)->is_monospace (family);
1988   else
1989     return FALSE;
1990 }
1991
1992 /*
1993  * PangoFontFace
1994  */
1995
1996 G_DEFINE_ABSTRACT_TYPE (PangoFontFace, pango_font_face, G_TYPE_OBJECT)
1997
1998 static void
1999 pango_font_face_class_init (PangoFontFaceClass *class G_GNUC_UNUSED)
2000 {
2001 }
2002
2003 static void
2004 pango_font_face_init (PangoFontFace *face G_GNUC_UNUSED)
2005 {
2006 }
2007
2008 /**
2009  * pango_font_face_describe:
2010  * @face: a #PangoFontFace
2011  *
2012  * Returns the family, style, variant, weight and stretch of
2013  * a #PangoFontFace. The size field of the resulting font description
2014  * will be unset.
2015  *
2016  * Return value: a newly-created #PangoFontDescription structure
2017  *  holding the description of the face. Use pango_font_description_free()
2018  *  to free the result.
2019  **/
2020 PangoFontDescription *
2021 pango_font_face_describe (PangoFontFace *face)
2022 {
2023   g_return_val_if_fail (PANGO_IS_FONT_FACE (face), NULL);
2024
2025   return PANGO_FONT_FACE_GET_CLASS (face)->describe (face);
2026 }
2027
2028 /**
2029  * pango_font_face_is_synthesized:
2030  * @face: a #PangoFontFace
2031  *
2032  * Returns whether a #PangoFontFace is synthesized by the underlying
2033  * font rendering engine from another face, perhaps by shearing, emboldening,
2034  * or lightening it.
2035  *
2036  * Return value: whether @face is synthesized.
2037  *
2038  * Since: 1.18
2039  **/
2040 gboolean
2041 pango_font_face_is_synthesized (PangoFontFace  *face)
2042 {
2043   g_return_val_if_fail (PANGO_IS_FONT_FACE (face), FALSE);
2044
2045   if (PANGO_FONT_FACE_GET_CLASS (face)->is_synthesized != NULL)
2046     return PANGO_FONT_FACE_GET_CLASS (face)->is_synthesized (face);
2047   else
2048     return FALSE;
2049 }
2050
2051 /**
2052  * pango_font_face_get_face_name:
2053  * @face: a #PangoFontFace.
2054  *
2055  * Gets a name representing the style of this face among the
2056  * different faces in the #PangoFontFamily for the face. This
2057  * name is unique among all faces in the family and is suitable
2058  * for displaying to users.
2059  *
2060  * Return value: the face name for the face. This string is
2061  *   owned by the face object and must not be modified or freed.
2062  **/
2063 G_CONST_RETURN char *
2064 pango_font_face_get_face_name (PangoFontFace *face)
2065 {
2066   g_return_val_if_fail (PANGO_IS_FONT_FACE (face), NULL);
2067
2068   return PANGO_FONT_FACE_GET_CLASS (face)->get_face_name (face);
2069 }
2070
2071 /**
2072  * pango_font_face_list_sizes:
2073  * @face: a #PangoFontFace.
2074  * @sizes: location to store a pointer to an array of int. This array
2075  *         should be freed with g_free().
2076  * @n_sizes: location to store the number of elements in @sizes
2077  *
2078  * List the available sizes for a font. This is only applicable to bitmap
2079  * fonts. For scalable fonts, stores %NULL at the location pointed to by
2080  * @sizes and 0 at the location pointed to by @n_sizes. The sizes returned
2081  * are in Pango units and are sorted in ascending order.
2082  *
2083  * Since: 1.4
2084  **/
2085 void
2086 pango_font_face_list_sizes (PangoFontFace  *face,
2087                             int           **sizes,
2088                             int            *n_sizes)
2089 {
2090   g_return_if_fail (PANGO_IS_FONT_FACE (face));
2091   g_return_if_fail (sizes == NULL || n_sizes != NULL);
2092
2093   if (n_sizes == NULL)
2094     return;
2095
2096   if (PANGO_FONT_FACE_GET_CLASS (face)->list_sizes != NULL)
2097     PANGO_FONT_FACE_GET_CLASS (face)->list_sizes (face, sizes, n_sizes);
2098   else
2099     {
2100       if (sizes != NULL)
2101         *sizes = NULL;
2102       *n_sizes = 0;
2103     }
2104 }