Fix severe security issues
[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: (transfer full): the newly allocated #PangoContext,
60  *               which should 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: (transfer full): the newly allocated #PangoFont loaded,
86  *          or %NULL if no font matched.
87  **/
88 PangoFont *
89 pango_font_map_load_font  (PangoFontMap               *fontmap,
90                            PangoContext               *context,
91                            const PangoFontDescription *desc)
92 {
93   g_return_val_if_fail (fontmap != NULL, NULL);
94
95   return PANGO_FONT_MAP_GET_CLASS (fontmap)->load_font (fontmap, context, desc);
96 }
97
98 /**
99  * pango_font_map_list_families:
100  * @fontmap: a #PangoFontMap
101  * @families: (out) (array length=n_families) (transfer container): location to store a pointer to an array of #PangoFontFamily *.
102  *            This array should be freed with g_free().
103  * @n_families: (out): location to store the number of elements in @families
104  *
105  * List all families for a fontmap.
106  **/
107 void
108 pango_font_map_list_families (PangoFontMap      *fontmap,
109                               PangoFontFamily ***families,
110                               int               *n_families)
111 {
112   g_return_if_fail (fontmap != NULL);
113
114   PANGO_FONT_MAP_GET_CLASS (fontmap)->list_families (fontmap, families, n_families);
115 }
116
117 /**
118  * pango_font_map_load_fontset:
119  * @fontmap: a #PangoFontMap
120  * @context: the #PangoContext the font will be used with
121  * @desc: a #PangoFontDescription describing the font to load
122  * @language: a #PangoLanguage the fonts will be used for
123  *
124  * Load a set of fonts in the fontmap that can be used to render
125  * a font matching @desc.
126  *
127  * Returns: (transfer full): the newly allocated #PangoFontset
128  *          loaded, or %NULL if no font matched.
129  **/
130 PangoFontset *
131 pango_font_map_load_fontset (PangoFontMap                 *fontmap,
132                              PangoContext                 *context,
133                              const PangoFontDescription   *desc,
134                              PangoLanguage                *language)
135 {
136   g_return_val_if_fail (fontmap != NULL, NULL);
137
138   return PANGO_FONT_MAP_GET_CLASS (fontmap)->load_fontset (fontmap, context, desc, language);
139 }
140
141 static void
142 pango_font_map_fontset_add_fonts (PangoFontMap          *fontmap,
143                                   PangoContext          *context,
144                                   PangoFontsetSimple    *fonts,
145                                   PangoFontDescription  *desc,
146                                   const char            *family)
147 {
148   char **aliases;
149   int n_aliases;
150   int j;
151   PangoFont *font;
152
153   pango_lookup_aliases (family,
154                         &aliases,
155                         &n_aliases);
156
157   if (n_aliases)
158     {
159       for (j = 0; j < n_aliases; j++)
160         {
161           pango_font_description_set_family_static (desc, aliases[j]);
162           font = pango_font_map_load_font (fontmap, context, desc);
163           if (font)
164             pango_fontset_simple_append (fonts, font);
165         }
166     }
167   else
168     {
169       pango_font_description_set_family_static (desc, family);
170       font = pango_font_map_load_font (fontmap, context, desc);
171       if (font)
172         pango_fontset_simple_append (fonts, font);
173     }
174 }
175
176 static PangoFontset *
177 pango_font_map_real_load_fontset (PangoFontMap               *fontmap,
178                                   PangoContext               *context,
179                                   const PangoFontDescription *desc,
180                                   PangoLanguage              *language)
181 {
182   PangoFontDescription *tmp_desc = pango_font_description_copy_static (desc);
183   const char *family;
184   char **families;
185   int i;
186   PangoFontsetSimple *fonts;
187   static GHashTable *warned_fonts = NULL;
188
189   family = pango_font_description_get_family (desc);
190   families = g_strsplit (family ? family : "", ",", -1);
191
192   fonts = pango_fontset_simple_new (language);
193
194   for (i = 0; families[i]; i++)
195     pango_font_map_fontset_add_fonts (fontmap,
196                                       context,
197                                       fonts,
198                                       tmp_desc,
199                                       families[i]);
200
201   g_strfreev (families);
202
203   /* The font description was completely unloadable, try with
204    * family == "Sans"
205    */
206   if (pango_fontset_simple_size (fonts) == 0)
207     {
208       char *ctmp1, *ctmp2;
209
210       pango_font_description_set_family_static (tmp_desc,
211                                                 pango_font_description_get_family (desc));
212
213       ctmp1 = pango_font_description_to_string (desc);
214       pango_font_description_set_family_static (tmp_desc, "Sans");
215
216       if (!warned_fonts || !g_hash_table_lookup (warned_fonts, ctmp1))
217         {
218           if (!warned_fonts)
219             warned_fonts = g_hash_table_new (g_str_hash, g_str_equal);
220
221           g_hash_table_insert (warned_fonts, g_strdup (ctmp1), GINT_TO_POINTER (1));
222
223           ctmp2 = pango_font_description_to_string (tmp_desc);
224           g_warning ("couldn't load font \"%s\", falling back to \"%s\", "
225                      "expect ugly output.", ctmp1, ctmp2);
226           g_free (ctmp2);
227         }
228       g_free (ctmp1);
229
230       pango_font_map_fontset_add_fonts (fontmap,
231                                         context,
232                                         fonts,
233                                         tmp_desc,
234                                         "Sans");
235     }
236
237   /* We couldn't try with Sans and the specified style. Try Sans Normal
238    */
239   if (pango_fontset_simple_size (fonts) == 0)
240     {
241       char *ctmp1, *ctmp2;
242
243       pango_font_description_set_family_static (tmp_desc, "Sans");
244       ctmp1 = pango_font_description_to_string (tmp_desc);
245       pango_font_description_set_style (tmp_desc, PANGO_STYLE_NORMAL);
246       pango_font_description_set_weight (tmp_desc, PANGO_WEIGHT_NORMAL);
247       pango_font_description_set_variant (tmp_desc, PANGO_VARIANT_NORMAL);
248       pango_font_description_set_stretch (tmp_desc, PANGO_STRETCH_NORMAL);
249
250       if (!warned_fonts || !g_hash_table_lookup (warned_fonts, ctmp1))
251         {
252           g_hash_table_insert (warned_fonts, g_strdup (ctmp1), GINT_TO_POINTER (1));
253
254           ctmp2 = pango_font_description_to_string (tmp_desc);
255
256           g_warning ("couldn't load font \"%s\", falling back to \"%s\", "
257                      "expect ugly output.", ctmp1, ctmp2);
258           g_free (ctmp2);
259         }
260
261       g_free (ctmp1);
262
263       pango_font_map_fontset_add_fonts (fontmap,
264                                         context,
265                                         fonts,
266                                         tmp_desc,
267                                         "Sans");
268     }
269
270   pango_font_description_free (tmp_desc);
271
272   /* Everything failed, we are screwed, there is no way to continue,
273    * but lets just not crash here.
274    */
275   if (pango_fontset_simple_size (fonts) == 0)
276       g_warning ("All font fallbacks failed!!!!");
277
278   return PANGO_FONTSET (fonts);
279 }
280
281 /**
282  * pango_font_map_get_shape_engine_type:
283  * @fontmap: a #PangoFontMap
284  *
285  * Returns the render ID for shape engines for this fontmap.
286  * See the <structfield>render_type</structfield> field of
287  * #PangoEngineInfo.
288   *
289  * Return value: the ID string for shape engines for
290  *  this fontmap. Owned by Pango, should not be modified
291  *  or freed.
292  *
293  * Since: 1.4
294  **/
295 const char *
296 pango_font_map_get_shape_engine_type (PangoFontMap *fontmap)
297 {
298   g_return_val_if_fail (PANGO_IS_FONT_MAP (fontmap), NULL);
299
300   return PANGO_FONT_MAP_GET_CLASS (fontmap)->shape_engine_type;
301 }
302