Git init
[external/pango1.0.git] / pango / pangoxft-fontmap.c
1 /* Pango
2  * pangoxft-fontmap.c: Xft font handling
3  *
4  * Copyright (C) 2000-2003 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 <string.h>
25
26 #include "pangofc-fontmap.h"
27 #include "pangoxft.h"
28 #include "pangoxft-private.h"
29
30 /* For XExtSetCloseDisplay */
31 #include <X11/Xlibint.h>
32
33 typedef struct _PangoXftFamily       PangoXftFamily;
34 typedef struct _PangoXftFontMapClass PangoXftFontMapClass;
35
36 #define PANGO_TYPE_XFT_FONT_MAP              (pango_xft_font_map_get_type ())
37 #define PANGO_XFT_FONT_MAP(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_XFT_FONT_MAP, PangoXftFontMap))
38 #define PANGO_XFT_IS_FONT_MAP(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_XFT_FONT_MAP))
39
40 struct _PangoXftFontMap
41 {
42   PangoFcFontMap parent_instance;
43
44   Display *display;
45   int screen;
46
47   /* Function to call on prepared patterns to do final
48    * config tweaking.
49    */
50   PangoXftSubstituteFunc substitute_func;
51   gpointer substitute_data;
52   GDestroyNotify substitute_destroy;
53
54   PangoRenderer *renderer;
55 };
56
57 struct _PangoXftFontMapClass
58 {
59   PangoFcFontMapClass parent_class;
60 };
61
62 static void          pango_xft_font_map_default_substitute (PangoFcFontMap       *fcfontmap,
63                                                             FcPattern            *pattern);
64 static PangoFcFont * pango_xft_font_map_new_font           (PangoFcFontMap       *fcfontmap,
65                                                             FcPattern            *pattern);
66 static void          pango_xft_font_map_finalize           (GObject              *object);
67
68 static GSList *fontmaps = NULL;
69
70 G_DEFINE_TYPE (PangoXftFontMap, pango_xft_font_map, PANGO_TYPE_FC_FONT_MAP)
71
72 static void
73 pango_xft_font_map_class_init (PangoXftFontMapClass *class)
74 {
75   GObjectClass *gobject_class = G_OBJECT_CLASS (class);
76   PangoFcFontMapClass *fcfontmap_class = PANGO_FC_FONT_MAP_CLASS (class);
77
78   gobject_class->finalize  = pango_xft_font_map_finalize;
79   fcfontmap_class->default_substitute = pango_xft_font_map_default_substitute;
80   fcfontmap_class->new_font = pango_xft_font_map_new_font;
81 }
82
83 static void
84 pango_xft_font_map_init (PangoXftFontMap *xftfontmap G_GNUC_UNUSED)
85 {
86 }
87
88 static void
89 pango_xft_font_map_finalize (GObject *object)
90 {
91   PangoXftFontMap *xftfontmap = PANGO_XFT_FONT_MAP (object);
92
93   if (xftfontmap->renderer)
94     g_object_unref (xftfontmap->renderer);
95
96   fontmaps = g_slist_remove (fontmaps, object);
97
98   if (xftfontmap->substitute_destroy)
99     xftfontmap->substitute_destroy (xftfontmap->substitute_data);
100
101   G_OBJECT_CLASS (pango_xft_font_map_parent_class)->finalize (object);
102 }
103
104
105 static PangoFontMap *
106 pango_xft_find_font_map (Display *display,
107                          int      screen)
108 {
109   GSList *tmp_list;
110
111   tmp_list = fontmaps;
112   while (tmp_list)
113     {
114       PangoXftFontMap *xftfontmap = tmp_list->data;
115
116       if (xftfontmap->display == display &&
117           xftfontmap->screen == screen)
118         return PANGO_FONT_MAP (xftfontmap);
119
120       tmp_list = tmp_list->next;
121     }
122
123   return NULL;
124 }
125
126 /*
127  * Hackery to set up notification when a Display is closed
128  */
129 static GSList *registered_displays;
130
131 static int
132 close_display_cb (Display   *display,
133                   XExtCodes *extcodes G_GNUC_UNUSED)
134 {
135   GSList *tmp_list;
136
137   tmp_list = fontmaps;
138   while (tmp_list)
139     {
140       PangoXftFontMap *xftfontmap = tmp_list->data;
141       tmp_list = tmp_list->next;
142
143       if (xftfontmap->display == display)
144         pango_xft_shutdown_display (display, xftfontmap->screen);
145     }
146
147   registered_displays = g_slist_remove (registered_displays, display);
148
149   return 0;
150 }
151
152 static void
153 register_display (Display *display)
154 {
155   XExtCodes *extcodes;
156   GSList *tmp_list;
157
158   for (tmp_list = registered_displays; tmp_list; tmp_list = tmp_list->next)
159     {
160       if (tmp_list->data == display)
161         return;
162     }
163
164   registered_displays = g_slist_prepend (registered_displays, display);
165
166   extcodes = XAddExtension (display);
167   XESetCloseDisplay (display, extcodes->extension, close_display_cb);
168 }
169
170 /**
171  * pango_xft_get_font_map:
172  * @display: an X display
173  * @screen: the screen number of a screen within @display
174  *
175  * Returns the #PangoXftFontmap for the given display and screen.
176  * The fontmap is owned by Pango and will be valid until
177  * the display is closed.
178  *
179  * Return value: a #PangoFontMap object, owned by Pango.
180  *
181  * Since: 1.2
182  **/
183 PangoFontMap *
184 pango_xft_get_font_map (Display *display,
185                         int      screen)
186 {
187   PangoFontMap *fontmap;
188   PangoXftFontMap *xftfontmap;
189
190   g_return_val_if_fail (display != NULL, NULL);
191
192   fontmap = pango_xft_find_font_map (display, screen);
193   if (fontmap)
194     return fontmap;
195
196   /* Make sure that the type system is initialized */
197   g_type_init ();
198
199   xftfontmap = (PangoXftFontMap *)g_object_new (PANGO_TYPE_XFT_FONT_MAP, NULL);
200
201   xftfontmap->display = display;
202   xftfontmap->screen = screen;
203
204   register_display (display);
205
206   fontmaps = g_slist_prepend (fontmaps, xftfontmap);
207
208   return PANGO_FONT_MAP (xftfontmap);
209 }
210
211 /**
212  * pango_xft_shutdown_display:
213  * @display: an X display
214  * @screen: the screen number of a screen within @display
215  *
216  * Release any resources that have been cached for the
217  * combination of @display and @screen. Note that when the
218  * X display is closed, resources are released automatically,
219  * without needing to call this function.
220  *
221  * Since: 1.2
222  **/
223 void
224 pango_xft_shutdown_display (Display *display,
225                             int      screen)
226 {
227   PangoFontMap *fontmap;
228
229   fontmap = pango_xft_find_font_map (display, screen);
230   if (fontmap)
231     {
232       PangoXftFontMap *xftfontmap = PANGO_XFT_FONT_MAP (fontmap);
233
234       fontmaps = g_slist_remove (fontmaps, fontmap);
235       pango_fc_font_map_shutdown (PANGO_FC_FONT_MAP (fontmap));
236
237       xftfontmap->display = NULL;
238       g_object_unref (fontmap);
239     }
240 }
241
242 /**
243  * pango_xft_set_default_substitute:
244  * @display: an X Display
245  * @screen: the screen number of a screen within @display
246  * @func: function to call to to do final config tweaking
247  *        on #FcPattern objects.
248  * @data: data to pass to @func
249  * @notify: function to call when @data is no longer used.
250  *
251  * Sets a function that will be called to do final configuration
252  * substitution on a #FcPattern before it is used to load
253  * the font. This function can be used to do things like set
254  * hinting and antialiasing options.
255  *
256  * Since: 1.2
257  **/
258 void
259 pango_xft_set_default_substitute (Display                *display,
260                                   int                     screen,
261                                   PangoXftSubstituteFunc  func,
262                                   gpointer                data,
263                                   GDestroyNotify          notify)
264 {
265   PangoXftFontMap *xftfontmap = (PangoXftFontMap *)pango_xft_get_font_map (display, screen);
266
267   if (xftfontmap->substitute_destroy)
268     xftfontmap->substitute_destroy (xftfontmap->substitute_data);
269
270   xftfontmap->substitute_func = func;
271   xftfontmap->substitute_data = data;
272   xftfontmap->substitute_destroy = notify;
273
274   pango_fc_font_map_cache_clear (PANGO_FC_FONT_MAP (xftfontmap));
275 }
276
277 /**
278  * pango_xft_substitute_changed:
279  * @display: an X Display
280  * @screen: the screen number of a screen within @display
281  *
282  * Call this function any time the results of the
283  * default substitution function set with
284  * pango_xft_set_default_substitute() change.
285  * That is, if your substitution function will return different
286  * results for the same input pattern, you must call this function.
287  *
288  * Since: 1.2
289  **/
290 void
291 pango_xft_substitute_changed (Display *display,
292                               int      screen)
293 {
294   PangoXftFontMap *xftfontmap = (PangoXftFontMap *)pango_xft_get_font_map (display, screen);
295
296   pango_fc_font_map_cache_clear (PANGO_FC_FONT_MAP (xftfontmap));
297 }
298
299 void
300 _pango_xft_font_map_get_info (PangoFontMap *fontmap,
301                               Display     **display,
302                               int          *screen)
303 {
304   PangoXftFontMap *xftfontmap = (PangoXftFontMap *)fontmap;
305
306   if (display)
307     *display = xftfontmap->display;
308   if (screen)
309     *screen = xftfontmap->screen;
310 }
311
312 /**
313  * pango_xft_get_context:
314  * @display: an X display.
315  * @screen: an X screen.
316  *
317  * Retrieves a #PangoContext appropriate for rendering with
318  * Xft fonts on the given screen of the given display.
319  *
320  * Return value: the new #PangoContext.
321  *
322  * Deprecated: 1.22: Use pango_xft_get_font_map() followed by
323  * pango_font_map_create_context() instead.
324  **/
325 PangoContext *
326 pango_xft_get_context (Display *display,
327                        int      screen)
328 {
329   g_return_val_if_fail (display != NULL, NULL);
330
331   return pango_font_map_create_context (pango_xft_get_font_map (display, screen));
332 }
333
334 /**
335  * _pango_xft_font_map_get_renderer:
336  * @fontmap: a #PangoXftFontmap
337  *
338  * Gets the singleton #PangoXFTRenderer for this fontmap.
339  *
340  * Return value: the renderer.
341  **/
342 PangoRenderer *
343 _pango_xft_font_map_get_renderer (PangoXftFontMap *xftfontmap)
344 {
345   if (!xftfontmap->renderer)
346     xftfontmap->renderer = pango_xft_renderer_new (xftfontmap->display,
347                                                    xftfontmap->screen);
348
349   return xftfontmap->renderer;
350 }
351
352 static void
353 pango_xft_font_map_default_substitute (PangoFcFontMap *fcfontmap,
354                                        FcPattern      *pattern)
355 {
356   PangoXftFontMap *xftfontmap = PANGO_XFT_FONT_MAP (fcfontmap);
357   double d;
358
359   FcConfigSubstitute (NULL, pattern, FcMatchPattern);
360   if (xftfontmap->substitute_func)
361     xftfontmap->substitute_func (pattern, xftfontmap->substitute_data);
362   XftDefaultSubstitute (xftfontmap->display, xftfontmap->screen, pattern);
363   if (FcPatternGetDouble (pattern, FC_PIXEL_SIZE, 0, &d) == FcResultMatch && d == 0.0)
364     {
365       FcValue v;
366       v.type = FcTypeDouble;
367       v.u.d = 1.0;
368       FcPatternAdd (pattern, FC_PIXEL_SIZE, v, FcFalse);
369     }
370 }
371
372 static PangoFcFont *
373 pango_xft_font_map_new_font (PangoFcFontMap  *fcfontmap,
374                              FcPattern       *pattern)
375 {
376   return (PangoFcFont *)_pango_xft_font_new (PANGO_XFT_FONT_MAP (fcfontmap), pattern);
377 }