Upload tizen 2.0 beta source
[external/pango1.0.git] / pango / pango-fontmap.c
1 /* Pango
2  * pango-fontmap.c: Font handling
3  *
4  * Copyright (C) 2000 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 "pango-fontmap.h"
24 #include "pango-impl-utils.h"
25 #include <stdlib.h>
26
27 static PangoFontset *pango_font_map_real_load_fontset (PangoFontMap               *fontmap,
28                                                        PangoContext               *context,
29                                                        const PangoFontDescription *desc,
30                                                        PangoLanguage              *language);
31
32
33 G_DEFINE_ABSTRACT_TYPE (PangoFontMap, pango_font_map, G_TYPE_OBJECT)
34
35 static void
36 pango_font_map_class_init (PangoFontMapClass *class)
37 {
38   class->load_fontset = pango_font_map_real_load_fontset;
39 }
40
41 static void
42 pango_font_map_init (PangoFontMap *fontmap G_GNUC_UNUSED)
43 {
44 }
45
46 /**
47  * pango_font_map_create_context:
48  * @fontmap: a #PangoFontMap
49  *
50  * Creates a #PangoContext connected to @fontmap.  This is equivalent
51  * to pango_context_new() followed by pango_context_set_font_map().
52  *
53  * If you are using Pango as part of a higher-level system,
54  * that system may have it's own way of create a #PangoContext.
55  * For instance, the GTK+ toolkit has, among others,
56  * gdk_pango_context_get_for_screen(), and
57  * gtk_widget_get_pango_context().  Use those instead.
58  *
59  * Return value: the newly allocated #PangoContext, which should
60  *               be freed with g_object_unref().
61  *
62  * Since: 1.22
63  **/
64 PangoContext *
65 pango_font_map_create_context (PangoFontMap *fontmap)
66 {
67   PangoContext *context;
68
69   g_return_val_if_fail (fontmap != NULL, NULL);
70
71   context = pango_context_new ();
72   pango_context_set_font_map (context, fontmap);
73
74   return context;
75 }
76
77 /**
78  * pango_font_map_load_font:
79  * @fontmap: a #PangoFontMap
80  * @context: the #PangoContext the font will be used with
81  * @desc: a #PangoFontDescription describing the font to load
82  *
83  * Load the font in the fontmap that is the closest match for @desc.
84  *
85  * Returns: the font loaded, or %NULL if no font matched.
86  **/
87 PangoFont *
88 pango_font_map_load_font  (PangoFontMap               *fontmap,
89                            PangoContext               *context,
90                            const PangoFontDescription *desc)
91 {
92   g_return_val_if_fail (fontmap != NULL, NULL);
93
94   return PANGO_FONT_MAP_GET_CLASS (fontmap)->load_font (fontmap, context, desc);
95 }
96
97 /**
98  * pango_font_map_list_families:
99  * @fontmap: a #PangoFontMap
100  * @families: location to store a pointer to an array of #PangoFontFamily *.
101  *            This array should be freed with g_free().
102  * @n_families: location to store the number of elements in @families
103  *
104  * List all families for a fontmap.
105  **/
106 void
107 pango_font_map_list_families (PangoFontMap      *fontmap,
108                               PangoFontFamily ***families,
109                               int               *n_families)
110 {
111   g_return_if_fail (fontmap != NULL);
112
113   PANGO_FONT_MAP_GET_CLASS (fontmap)->list_families (fontmap, families, n_families);
114 }
115
116 /**
117  * pango_font_map_load_fontset:
118  * @fontmap: a #PangoFontMap
119  * @context: the #PangoContext the font will be used with
120  * @desc: a #PangoFontDescription describing the font to load
121  * @language: a #PangoLanguage the fonts will be used for
122  *
123  * Load a set of fonts in the fontmap that can be used to render
124  * a font matching @desc.
125  *
126  * Returns: the fontset, or %NULL if no font matched.
127  **/
128 PangoFontset *
129 pango_font_map_load_fontset (PangoFontMap                 *fontmap,
130                              PangoContext                 *context,
131                              const PangoFontDescription   *desc,
132                              PangoLanguage                *language)
133 {
134   g_return_val_if_fail (fontmap != NULL, NULL);
135
136   return PANGO_FONT_MAP_GET_CLASS (fontmap)->load_fontset (fontmap, context, desc, language);
137 }
138
139 static void
140 pango_font_map_fontset_add_fonts (PangoFontMap          *fontmap,
141                                   PangoContext          *context,
142                                   PangoFontsetSimple    *fonts,
143                                   PangoFontDescription  *desc,
144                                   const char            *family)
145 {
146   char **aliases;
147   int n_aliases;
148   int j;
149   PangoFont *font;
150
151   pango_lookup_aliases (family,
152                         &aliases,
153                         &n_aliases);
154
155   if (n_aliases)
156     {
157       for (j = 0; j < n_aliases; j++)
158         {
159           pango_font_description_set_family_static (desc, aliases[j]);
160           font = pango_font_map_load_font (fontmap, context, desc);
161           if (font)
162             pango_fontset_simple_append (fonts, font);
163         }
164     }
165   else
166     {
167       pango_font_description_set_family_static (desc, family);
168       font = pango_font_map_load_font (fontmap, context, desc);
169       if (font)
170         pango_fontset_simple_append (fonts, font);
171     }
172 }
173
174 static PangoFontset *
175 pango_font_map_real_load_fontset (PangoFontMap               *fontmap,
176                                   PangoContext               *context,
177                                   const PangoFontDescription *desc,
178                                   PangoLanguage              *language)
179 {
180   PangoFontDescription *tmp_desc = pango_font_description_copy_static (desc);
181   const char *family;
182   char **families;
183   int i;
184   PangoFontsetSimple *fonts;
185   static GHashTable *warned_fonts = NULL;
186
187   family = pango_font_description_get_family (desc);
188   families = g_strsplit (family ? family : "", ",", -1);
189
190   fonts = pango_fontset_simple_new (language);
191
192   for (i = 0; families[i]; i++)
193     pango_font_map_fontset_add_fonts (fontmap,
194                                       context,
195                                       fonts,
196                                       tmp_desc,
197                                       families[i]);
198
199   g_strfreev (families);
200
201   /* The font description was completely unloadable, try with
202    * family == "Sans"
203    */
204   if (pango_fontset_simple_size (fonts) == 0)
205     {
206       char *ctmp1, *ctmp2;
207
208       pango_font_description_set_family_static (tmp_desc,
209                                                 pango_font_description_get_family (desc));
210
211       ctmp1 = pango_font_description_to_string (desc);
212       pango_font_description_set_family_static (tmp_desc, "Sans");
213
214       if (!warned_fonts || !g_hash_table_lookup (warned_fonts, ctmp1))
215         {
216           if (!warned_fonts)
217             warned_fonts = g_hash_table_new (g_str_hash, g_str_equal);
218
219           g_hash_table_insert (warned_fonts, g_strdup (ctmp1), GINT_TO_POINTER (1));
220
221           ctmp2 = pango_font_description_to_string (tmp_desc);
222           g_warning ("couldn't load font \"%s\", falling back to \"%s\", "
223                      "expect ugly output.", ctmp1, ctmp2);
224           g_free (ctmp2);
225         }
226       g_free (ctmp1);
227
228       pango_font_map_fontset_add_fonts (fontmap,
229                                         context,
230                                         fonts,
231                                         tmp_desc,
232                                         "Sans");
233     }
234
235   /* We couldn't try with Sans and the specified style. Try Sans Normal
236    */
237   if (pango_fontset_simple_size (fonts) == 0)
238     {
239       char *ctmp1, *ctmp2;
240
241       pango_font_description_set_family_static (tmp_desc, "Sans");
242       ctmp1 = pango_font_description_to_string (tmp_desc);
243       pango_font_description_set_style (tmp_desc, PANGO_STYLE_NORMAL);
244       pango_font_description_set_weight (tmp_desc, PANGO_WEIGHT_NORMAL);
245       pango_font_description_set_variant (tmp_desc, PANGO_VARIANT_NORMAL);
246       pango_font_description_set_stretch (tmp_desc, PANGO_STRETCH_NORMAL);
247
248       if (!warned_fonts || !g_hash_table_lookup (warned_fonts, ctmp1))
249         {
250           g_hash_table_insert (warned_fonts, g_strdup (ctmp1), GINT_TO_POINTER (1));
251
252           ctmp2 = pango_font_description_to_string (tmp_desc);
253
254           g_warning ("couldn't load font \"%s\", falling back to \"%s\", "
255                      "expect ugly output.", ctmp1, ctmp2);
256           g_free (ctmp2);
257         }
258
259       g_free (ctmp1);
260
261       pango_font_map_fontset_add_fonts (fontmap,
262                                         context,
263                                         fonts,
264                                         tmp_desc,
265                                         "Sans");
266     }
267
268   pango_font_description_free (tmp_desc);
269
270   /* Everything failed, we are screwed, there is no way to continue,
271    * but lets just not crash here.
272    */
273   if (pango_fontset_simple_size (fonts) == 0)
274       g_warning ("All font fallbacks failed!!!!");
275
276   return PANGO_FONTSET (fonts);
277 }
278
279 /**
280  * pango_font_map_get_shape_engine_type:
281  * @fontmap: a #PangoFontMap
282  *
283  * Returns the render ID for shape engines for this fontmap.
284  * See the <structfield>render_type</structfield> field of
285  * #PangoEngineInfo.
286   *
287  * Return value: the ID string for shape engines for
288  *  this fontmap. Owned by Pango, should not be modified
289  *  or freed.
290  *
291  * Since: 1.4
292  **/
293 G_CONST_RETURN char *
294 pango_font_map_get_shape_engine_type (PangoFontMap *fontmap)
295 {
296   g_return_val_if_fail (PANGO_IS_FONT_MAP (fontmap), NULL);
297
298   return PANGO_FONT_MAP_GET_CLASS (fontmap)->shape_engine_type;
299 }
300