pangoxft-fontmap.c 10.5 KB
Newer Older
Owen Taylor's avatar
Owen Taylor committed
1
/* Pango
2
 * pangoxft-fontmap.c: Xft font handling
Owen Taylor's avatar
Owen Taylor committed
3
 *
4
 * Copyright (C) 2000-2003 Red Hat Software
Owen Taylor's avatar
Owen Taylor committed
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

22
#include "config.h"
23
#include <stdlib.h>
24 25
#include <string.h>

26
#include "pangofc-fontmap.h"
Owen Taylor's avatar
Owen Taylor committed
27 28 29
#include "pangoxft.h"
#include "pangoxft-private.h"

30 31 32
/* For XExtSetCloseDisplay */
#include <X11/Xlibint.h>

Owen Taylor's avatar
Owen Taylor committed
33
typedef struct _PangoXftFamily       PangoXftFamily;
34
typedef struct _PangoXftFontMapClass PangoXftFontMapClass;
Owen Taylor's avatar
Owen Taylor committed
35 36 37 38

#define PANGO_TYPE_XFT_FONT_MAP              (pango_xft_font_map_get_type ())
#define PANGO_XFT_FONT_MAP(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_XFT_FONT_MAP, PangoXftFontMap))
#define PANGO_XFT_IS_FONT_MAP(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_XFT_FONT_MAP))
Owen Taylor's avatar
Owen Taylor committed
39 40 41

struct _PangoXftFontMap
{
42
  PangoFcFontMap parent_instance;
Owen Taylor's avatar
Owen Taylor committed
43

Owen Taylor's avatar
Owen Taylor committed
44
  Display *display;
45
  int screen;
46

47 48 49 50 51 52
  /* Function to call on prepared patterns to do final
   * config tweaking.
   */
  PangoXftSubstituteFunc substitute_func;
  gpointer substitute_data;
  GDestroyNotify substitute_destroy;
Owen Taylor's avatar
Owen Taylor committed
53 54

  PangoRenderer *renderer;
Owen Taylor's avatar
Owen Taylor committed
55 56
};

57 58 59 60 61 62 63 64 65 66 67
struct _PangoXftFontMapClass
{
  PangoFcFontMapClass parent_class;
};

static void          pango_xft_font_map_default_substitute (PangoFcFontMap       *fcfontmap,
							    FcPattern            *pattern);
static PangoFcFont * pango_xft_font_map_new_font           (PangoFcFontMap       *fcfontmap,
							    FcPattern            *pattern);
static void          pango_xft_font_map_finalize           (GObject              *object);

68 69
G_LOCK_DEFINE_STATIC (fontmaps);
static GSList *fontmaps = NULL; /* MT-safe */
70

71
G_DEFINE_TYPE (PangoXftFontMap, pango_xft_font_map, PANGO_TYPE_FC_FONT_MAP)
72 73 74 75 76 77

static void
pango_xft_font_map_class_init (PangoXftFontMapClass *class)
{
  GObjectClass *gobject_class = G_OBJECT_CLASS (class);
  PangoFcFontMapClass *fcfontmap_class = PANGO_FC_FONT_MAP_CLASS (class);
Owen Taylor's avatar
Owen Taylor committed
78

79 80 81 82
  gobject_class->finalize  = pango_xft_font_map_finalize;
  fcfontmap_class->default_substitute = pango_xft_font_map_default_substitute;
  fcfontmap_class->new_font = pango_xft_font_map_new_font;
}
83

84
static void
Behdad Esfahbod's avatar
Behdad Esfahbod committed
85
pango_xft_font_map_init (PangoXftFontMap *xftfontmap G_GNUC_UNUSED)
86 87 88
{
}

89 90 91 92
static void
pango_xft_font_map_finalize (GObject *object)
{
  PangoXftFontMap *xftfontmap = PANGO_XFT_FONT_MAP (object);
93

Owen Taylor's avatar
Owen Taylor committed
94 95 96
  if (xftfontmap->renderer)
    g_object_unref (xftfontmap->renderer);

97
  G_LOCK (fontmaps);
98
  fontmaps = g_slist_remove (fontmaps, object);
99
  G_UNLOCK (fontmaps);
100

101 102
  if (xftfontmap->substitute_destroy)
    xftfontmap->substitute_destroy (xftfontmap->substitute_data);
Owen Taylor's avatar
Owen Taylor committed
103

104
  G_OBJECT_CLASS (pango_xft_font_map_parent_class)->finalize (object);
105
}
Owen Taylor's avatar
Owen Taylor committed
106

107

108 109 110 111 112
static PangoFontMap *
pango_xft_find_font_map (Display *display,
			 int      screen)
{
  GSList *tmp_list;
113

114
  G_LOCK (fontmaps);
115 116 117
  tmp_list = fontmaps;
  while (tmp_list)
    {
118
      PangoXftFontMap *xftfontmap = tmp_list->data;
119

120
      if (xftfontmap->display == display &&
121
	  xftfontmap->screen == screen)
122 123 124 125
        {
          G_UNLOCK (fontmaps);
	  return PANGO_FONT_MAP (xftfontmap);
        }
126 127 128

      tmp_list = tmp_list->next;
    }
129
  G_UNLOCK (fontmaps);
130 131 132 133

  return NULL;
}

134 135 136
/*
 * Hackery to set up notification when a Display is closed
 */
137
static GSList *registered_displays; /* MT-safe, protected by fontmaps lock */
138 139 140

static int
close_display_cb (Display   *display,
Behdad Esfahbod's avatar
Behdad Esfahbod committed
141
		  XExtCodes *extcodes G_GNUC_UNUSED)
142 143
{
  GSList *tmp_list;
144

145 146
  G_LOCK (fontmaps);

147 148 149
  tmp_list = fontmaps;
  while (tmp_list)
    {
150
      PangoXftFontMap *xftfontmap = tmp_list->data;
151 152
      tmp_list = tmp_list->next;

153 154
      if (xftfontmap->display == display)
	pango_xft_shutdown_display (display, xftfontmap->screen);
155 156 157 158
    }

  registered_displays = g_slist_remove (registered_displays, display);

159 160
  G_UNLOCK (fontmaps);

161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
  return 0;
}

static void
register_display (Display *display)
{
  XExtCodes *extcodes;
  GSList *tmp_list;

  for (tmp_list = registered_displays; tmp_list; tmp_list = tmp_list->next)
    {
      if (tmp_list->data == display)
	return;
    }

  registered_displays = g_slist_prepend (registered_displays, display);
177

178 179 180 181
  extcodes = XAddExtension (display);
  XESetCloseDisplay (display, extcodes->extension, close_display_cb);
}

Owen Taylor's avatar
Owen Taylor committed
182 183 184 185
/**
 * pango_xft_get_font_map:
 * @display: an X display
 * @screen: the screen number of a screen within @display
186
 *
187
 * Returns the #PangoXftFontmap for the given display and screen.
Owen Taylor's avatar
Owen Taylor committed
188 189
 * The fontmap is owned by Pango and will be valid until
 * the display is closed.
190
 *
191
 * Return value: (transfer none): a #PangoFontMap object, owned by Pango.
192 193
 *
 * Since: 1.2
Owen Taylor's avatar
Owen Taylor committed
194 195
 **/
PangoFontMap *
Owen Taylor's avatar
Owen Taylor committed
196 197 198
pango_xft_get_font_map (Display *display,
			int      screen)
{
199
  PangoFontMap *fontmap;
200
  PangoXftFontMap *xftfontmap;
Owen Taylor's avatar
Owen Taylor committed
201 202

  g_return_val_if_fail (display != NULL, NULL);
203

204 205 206
  fontmap = pango_xft_find_font_map (display, screen);
  if (fontmap)
    return fontmap;
207

208 209 210
  /* Make sure that the type system is initialized */
  g_type_init ();

211
  xftfontmap = (PangoXftFontMap *)g_object_new (PANGO_TYPE_XFT_FONT_MAP, NULL);
212

213 214
  xftfontmap->display = display;
  xftfontmap->screen = screen;
Owen Taylor's avatar
Owen Taylor committed
215

216 217
  G_LOCK (fontmaps);

218 219
  register_display (display);

220
  fontmaps = g_slist_prepend (fontmaps, xftfontmap);
Owen Taylor's avatar
Owen Taylor committed
221

222 223
  G_UNLOCK (fontmaps);

224
  return PANGO_FONT_MAP (xftfontmap);
Owen Taylor's avatar
Owen Taylor committed
225 226
}

227 228 229 230
/**
 * pango_xft_shutdown_display:
 * @display: an X display
 * @screen: the screen number of a screen within @display
231
 *
232
 * Release any resources that have been cached for the
233 234 235
 * combination of @display and @screen. Note that when the
 * X display is closed, resources are released automatically,
 * without needing to call this function.
236 237
 *
 * Since: 1.2
238 239 240 241 242 243
 **/
void
pango_xft_shutdown_display (Display *display,
			    int      screen)
{
  PangoFontMap *fontmap;
244

245 246 247
  fontmap = pango_xft_find_font_map (display, screen);
  if (fontmap)
    {
248
      PangoXftFontMap *xftfontmap = PANGO_XFT_FONT_MAP (fontmap);
249

250
      G_LOCK (fontmaps);
251
      fontmaps = g_slist_remove (fontmaps, fontmap);
252
      G_UNLOCK (fontmaps);
253
      pango_fc_font_map_shutdown (PANGO_FC_FONT_MAP (fontmap));
254

255
      xftfontmap->display = NULL;
256
      g_object_unref (fontmap);
257
    }
258
}
259

260
/**
261
 * pango_xft_set_default_substitute:
262 263
 * @display: an X Display
 * @screen: the screen number of a screen within @display
264 265 266 267
 * @func: function to call to to do final config tweaking
 *        on #FcPattern objects.
 * @data: data to pass to @func
 * @notify: function to call when @data is no longer used.
268
 *
269 270 271
 * Sets a function that will be called to do final configuration
 * substitution on a #FcPattern before it is used to load
 * the font. This function can be used to do things like set
272
 * hinting and antialiasing options.
273 274
 *
 * Since: 1.2
275 276 277 278 279 280 281 282
 **/
void
pango_xft_set_default_substitute (Display                *display,
				  int                     screen,
				  PangoXftSubstituteFunc  func,
				  gpointer                data,
				  GDestroyNotify          notify)
{
283
  PangoXftFontMap *xftfontmap = (PangoXftFontMap *)pango_xft_get_font_map (display, screen);
284

285 286
  if (xftfontmap->substitute_destroy)
    xftfontmap->substitute_destroy (xftfontmap->substitute_data);
287

288 289 290
  xftfontmap->substitute_func = func;
  xftfontmap->substitute_data = data;
  xftfontmap->substitute_destroy = notify;
291

292
  pango_fc_font_map_cache_clear (PANGO_FC_FONT_MAP (xftfontmap));
293 294 295
}

/**
296
 * pango_xft_substitute_changed:
Matthias Clasen's avatar
Matthias Clasen committed
297 298
 * @display: an X Display
 * @screen: the screen number of a screen within @display
299
 *
300 301
 * Call this function any time the results of the
 * default substitution function set with
302
 * pango_xft_set_default_substitute() change.
Behdad Esfahbod's avatar
Behdad Esfahbod committed
303
 * That is, if your substitution function will return different
304
 * results for the same input pattern, you must call this function.
305 306
 *
 * Since: 1.2
307 308 309 310 311
 **/
void
pango_xft_substitute_changed (Display *display,
			      int      screen)
{
312
  PangoXftFontMap *xftfontmap = (PangoXftFontMap *)pango_xft_get_font_map (display, screen);
313

314
  pango_fc_font_map_cache_clear (PANGO_FC_FONT_MAP (xftfontmap));
315 316 317 318 319 320 321
}

void
_pango_xft_font_map_get_info (PangoFontMap *fontmap,
			      Display     **display,
			      int          *screen)
{
322
  PangoXftFontMap *xftfontmap = (PangoXftFontMap *)fontmap;
323 324 325 326 327

  if (display)
    *display = xftfontmap->display;
  if (screen)
    *screen = xftfontmap->screen;
328 329
}

Matthias Clasen's avatar
Matthias Clasen committed
330
/**
331
 * pango_xft_get_context: (skip)
Matthias Clasen's avatar
Matthias Clasen committed
332 333 334 335
 * @display: an X display.
 * @screen: an X screen.
 *
 * Retrieves a #PangoContext appropriate for rendering with
336
 * Xft fonts on the given screen of the given display.
Matthias Clasen's avatar
Matthias Clasen committed
337
 *
338
 * Return value: the new #PangoContext.
339 340 341
 *
 * Deprecated: 1.22: Use pango_xft_get_font_map() followed by
 * pango_font_map_create_context() instead.
Matthias Clasen's avatar
Matthias Clasen committed
342
 **/
Owen Taylor's avatar
Owen Taylor committed
343 344 345 346 347 348
PangoContext *
pango_xft_get_context (Display *display,
		       int      screen)
{
  g_return_val_if_fail (display != NULL, NULL);

349
  return pango_font_map_create_context (pango_xft_get_font_map (display, screen));
Owen Taylor's avatar
Owen Taylor committed
350 351
}

Owen Taylor's avatar
Owen Taylor committed
352 353 354
/**
 * _pango_xft_font_map_get_renderer:
 * @fontmap: a #PangoXftFontmap
355
 *
Behdad Esfahbod's avatar
Behdad Esfahbod committed
356
 * Gets the singleton #PangoXFTRenderer for this fontmap.
357
 *
358
 * Return value: the renderer.
Owen Taylor's avatar
Owen Taylor committed
359 360 361 362 363 364 365 366 367 368 369
 **/
PangoRenderer *
_pango_xft_font_map_get_renderer (PangoXftFontMap *xftfontmap)
{
  if (!xftfontmap->renderer)
    xftfontmap->renderer = pango_xft_renderer_new (xftfontmap->display,
						   xftfontmap->screen);

  return xftfontmap->renderer;
}

Owen Taylor's avatar
Owen Taylor committed
370
static void
371 372
pango_xft_font_map_default_substitute (PangoFcFontMap *fcfontmap,
				       FcPattern      *pattern)
Owen Taylor's avatar
Owen Taylor committed
373
{
374
  PangoXftFontMap *xftfontmap = PANGO_XFT_FONT_MAP (fcfontmap);
375
  double d;
376

377 378 379 380
  FcConfigSubstitute (NULL, pattern, FcMatchPattern);
  if (xftfontmap->substitute_func)
    xftfontmap->substitute_func (pattern, xftfontmap->substitute_data);
  XftDefaultSubstitute (xftfontmap->display, xftfontmap->screen, pattern);
381 382 383 384 385 386 387
  if (FcPatternGetDouble (pattern, FC_PIXEL_SIZE, 0, &d) == FcResultMatch && d == 0.0)
    {
      FcValue v;
      v.type = FcTypeDouble;
      v.u.d = 1.0;
      FcPatternAdd (pattern, FC_PIXEL_SIZE, v, FcFalse);
    }
Owen Taylor's avatar
Owen Taylor committed
388 389
}

390 391
static PangoFcFont *
pango_xft_font_map_new_font (PangoFcFontMap  *fcfontmap,
392
			     FcPattern       *pattern)
Owen Taylor's avatar
Owen Taylor committed
393
{
394
  return (PangoFcFont *)_pango_xft_font_new (PANGO_XFT_FONT_MAP (fcfontmap), pattern);
Owen Taylor's avatar
Owen Taylor committed
395
}