2 * pangoxft-font.c: Routines for handling X fonts
4 * Copyright (C) 2000 Red Hat Software
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.
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.
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.
26 #include "pangofc-fontmap.h"
27 #include "pangoxft-private.h"
28 #include "pangofc-private.h"
30 #define PANGO_XFT_FONT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PANGO_TYPE_XFT_FONT, PangoXftFontClass))
31 #define PANGO_XFT_IS_FONT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANGO_TYPE_XFT_FONT))
32 #define PANGO_XFT_FONT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PANGO_TYPE_XFT_FONT, PangoXftFontClass))
34 typedef struct _PangoXftFontClass PangoXftFontClass;
36 struct _PangoXftFontClass
38 PangoFcFontClass parent_class;
41 static void pango_xft_font_finalize (GObject *object);
43 static void pango_xft_font_get_glyph_extents (PangoFont *font,
45 PangoRectangle *ink_rect,
46 PangoRectangle *logical_rect);
48 static FT_Face pango_xft_font_real_lock_face (PangoFcFont *font);
49 static void pango_xft_font_real_unlock_face (PangoFcFont *font);
50 static gboolean pango_xft_font_real_has_char (PangoFcFont *font,
52 static guint pango_xft_font_real_get_glyph (PangoFcFont *font,
54 static void pango_xft_font_real_shutdown (PangoFcFont *font);
56 static XftFont *xft_font_get_font (PangoFont *font);
58 G_DEFINE_TYPE (PangoXftFont, pango_xft_font, PANGO_TYPE_FC_FONT)
61 pango_xft_font_class_init (PangoXftFontClass *class)
63 GObjectClass *object_class = G_OBJECT_CLASS (class);
64 PangoFontClass *font_class = PANGO_FONT_CLASS (class);
65 PangoFcFontClass *fc_font_class = PANGO_FC_FONT_CLASS (class);
67 object_class->finalize = pango_xft_font_finalize;
69 font_class->get_glyph_extents = pango_xft_font_get_glyph_extents;
71 fc_font_class->lock_face = pango_xft_font_real_lock_face;
72 fc_font_class->unlock_face = pango_xft_font_real_unlock_face;
73 fc_font_class->has_char = pango_xft_font_real_has_char;
74 fc_font_class->get_glyph = pango_xft_font_real_get_glyph;
75 fc_font_class->shutdown = pango_xft_font_real_shutdown;
79 pango_xft_font_init (PangoXftFont *xftfont G_GNUC_UNUSED)
84 _pango_xft_font_new (PangoXftFontMap *xftfontmap,
87 PangoFontMap *fontmap = PANGO_FONT_MAP (xftfontmap);
90 g_return_val_if_fail (fontmap != NULL, NULL);
91 g_return_val_if_fail (pattern != NULL, NULL);
93 xfont = (PangoXftFont *)g_object_new (PANGO_TYPE_XFT_FONT,
98 /* Hack to force hinting of vertical metrics; hinting off for
99 * a Xft font just means to not hint outlines, but we still
100 * want integer line spacing, underline positions, etc
102 PANGO_FC_FONT (xfont)->is_hinted = TRUE;
104 xfont->xft_font = NULL;
110 * _pango_xft_font_get_mini_font:
111 * @xfont: a #PangoXftFont
113 * Gets the font used for drawing the digits in the
114 * missing-character hex squares
116 * Return value: the #PangoFont used for the digits; this
117 * value is associated with the main font and will be freed
118 * along with the main font.
121 _pango_xft_font_get_mini_font (PangoXftFont *xfont)
123 PangoFcFont *fcfont = (PangoFcFont *)xfont;
125 if (!fcfont || !fcfont->fontmap)
128 if (!xfont->mini_font)
132 PangoFontDescription *desc = pango_font_description_new ();
133 PangoContext *context;
135 int width = 0, height = 0;
140 _pango_xft_font_map_get_info (fcfont->fontmap, &display, &screen);
142 context = pango_font_map_create_context (pango_xft_get_font_map (display, screen));
143 pango_context_set_language (context, pango_language_from_string ("en"));
145 pango_font_description_set_family_static (desc, "monospace");
147 new_size = pango_font_description_get_size (fcfont->description) / 2;
149 if (pango_font_description_get_size_is_absolute (fcfont->description))
150 pango_font_description_set_absolute_size (desc, new_size);
152 pango_font_description_set_size (desc, new_size);
154 xfont->mini_font = pango_font_map_load_font (fcfont->fontmap, context, desc);
155 pango_font_description_free (desc);
156 g_object_unref (context);
158 if (!xfont->mini_font)
161 mini_xft = xft_font_get_font (xfont->mini_font);
163 for (i = 0 ; i < 16 ; i++)
165 char c = i < 10 ? '0' + i : 'A' + i - 10;
166 XftTextExtents8 (display, mini_xft, (FcChar8 *) &c, 1, &extents);
167 width = MAX (width, extents.width);
168 height = MAX (height, extents.height);
171 xfont->mini_width = PANGO_SCALE * width;
172 xfont->mini_height = PANGO_SCALE * height;
173 xfont->mini_pad = PANGO_SCALE * MIN (height / 2, MAX ((int)(2.2 * height + 27) / 28, 1));
176 return xfont->mini_font;
180 pango_xft_font_finalize (GObject *object)
182 PangoXftFont *xfont = (PangoXftFont *)object;
183 PangoFcFont *fcfont = (PangoFcFont *)object;
185 if (xfont->mini_font)
186 g_object_unref (xfont->mini_font);
192 _pango_xft_font_map_get_info (fcfont->fontmap, &display, NULL);
193 XftFontClose (display, xfont->xft_font);
196 if (xfont->glyph_info)
197 g_hash_table_destroy (xfont->glyph_info);
199 G_OBJECT_CLASS (pango_xft_font_parent_class)->finalize (object);
203 get_glyph_extents_missing (PangoXftFont *xfont,
205 PangoRectangle *ink_rect,
206 PangoRectangle *logical_rect)
209 PangoFont *font = PANGO_FONT (xfont);
210 XftFont *xft_font = xft_font_get_font (font);
214 ch = glyph & ~PANGO_GLYPH_UNKNOWN_FLAG;
216 if (G_UNLIKELY (glyph == PANGO_GLYPH_INVALID_INPUT || ch > 0x10FFFF))
219 cols = ch > 0xffff ? 3 : 2;
221 _pango_xft_font_get_mini_font (xfont);
226 ink_rect->y = - PANGO_SCALE * xft_font->ascent + PANGO_SCALE * (((xft_font->ascent + xft_font->descent) - (xfont->mini_height * 2 + xfont->mini_pad * 5 + PANGO_SCALE / 2) / PANGO_SCALE) / 2);
227 ink_rect->width = xfont->mini_width * cols + xfont->mini_pad * (2 * cols + 1);
228 ink_rect->height = xfont->mini_height * 2 + xfont->mini_pad * 5;
234 logical_rect->y = - PANGO_SCALE * xft_font->ascent;
235 logical_rect->width = xfont->mini_width * cols + xfont->mini_pad * (2 * cols + 2);
236 logical_rect->height = (xft_font->ascent + xft_font->descent) * PANGO_SCALE;
241 get_glyph_extents_xft (PangoFcFont *fcfont,
243 PangoRectangle *ink_rect,
244 PangoRectangle *logical_rect)
246 XftFont *xft_font = xft_font_get_font ((PangoFont *)fcfont);
249 FT_UInt ft_glyph = glyph;
251 _pango_xft_font_map_get_info (fcfont->fontmap, &display, NULL);
253 XftGlyphExtents (display, xft_font, &ft_glyph, 1, &extents);
257 ink_rect->x = - extents.x * PANGO_SCALE; /* Xft crack-rock sign choice */
258 ink_rect->y = - extents.y * PANGO_SCALE; /* " */
259 ink_rect->width = extents.width * PANGO_SCALE;
260 ink_rect->height = extents.height * PANGO_SCALE;
266 logical_rect->y = - xft_font->ascent * PANGO_SCALE;
267 logical_rect->width = extents.xOff * PANGO_SCALE;
268 logical_rect->height = (xft_font->ascent + xft_font->descent) * PANGO_SCALE;
274 PangoRectangle ink_rect;
275 PangoRectangle logical_rect;
279 extents_free (Extents *ext)
281 g_slice_free (Extents, ext);
285 get_glyph_extents_raw (PangoXftFont *xfont,
287 PangoRectangle *ink_rect,
288 PangoRectangle *logical_rect)
292 if (!xfont->glyph_info)
293 xfont->glyph_info = g_hash_table_new_full (NULL, NULL,
294 NULL, (GDestroyNotify)extents_free);
296 extents = g_hash_table_lookup (xfont->glyph_info,
297 GUINT_TO_POINTER (glyph));
301 extents = g_slice_new (Extents);
303 pango_fc_font_get_raw_extents (PANGO_FC_FONT (xfont),
304 FT_LOAD_NO_BITMAP | FT_LOAD_NO_HINTING,
307 &extents->logical_rect);
309 g_hash_table_insert (xfont->glyph_info,
310 GUINT_TO_POINTER (glyph),
315 *ink_rect = extents->ink_rect;
318 *logical_rect = extents->logical_rect;
322 pango_xft_font_get_glyph_extents (PangoFont *font,
324 PangoRectangle *ink_rect,
325 PangoRectangle *logical_rect)
327 PangoXftFont *xfont = (PangoXftFont *)font;
328 PangoFcFont *fcfont = PANGO_FC_FONT (font);
329 gboolean empty = FALSE;
331 if (G_UNLIKELY (!fcfont->fontmap)) /* Display closed */
334 ink_rect->x = ink_rect->width = ink_rect->y = ink_rect->height = 0;
336 logical_rect->x = logical_rect->width = logical_rect->y = logical_rect->height = 0;
340 if (glyph == PANGO_GLYPH_EMPTY)
342 glyph = pango_fc_font_get_glyph (fcfont, ' ');
346 if (glyph & PANGO_GLYPH_UNKNOWN_FLAG)
348 get_glyph_extents_missing (xfont, glyph, ink_rect, logical_rect);
352 if (!fcfont->is_transformed)
353 get_glyph_extents_xft (fcfont, glyph, ink_rect, logical_rect);
355 get_glyph_extents_raw (xfont, glyph, ink_rect, logical_rect);
361 ink_rect->x = ink_rect->y = ink_rect->height = ink_rect->width = 0;
363 logical_rect->x = logical_rect->width = 0;
369 load_fallback_font (PangoXftFont *xfont)
371 PangoFcFont *fcfont = PANGO_FC_FONT (xfont);
375 gboolean size_is_absolute;
378 _pango_xft_font_map_get_info (fcfont->fontmap, &display, &screen);
380 size_is_absolute = pango_font_description_get_size_is_absolute (fcfont->description);
381 size = pango_font_description_get_size (fcfont->description) / PANGO_SCALE;
383 xft_font = XftFontOpen (display, screen,
384 FC_FAMILY, FcTypeString, "sans",
385 size_is_absolute ? FC_PIXEL_SIZE : FC_SIZE, FcTypeDouble, size,
388 xfont->xft_font = xft_font;
392 xft_font_get_font (PangoFont *font)
399 xfont = (PangoXftFont *)font;
400 fcfont = (PangoFcFont *)font;
402 if (G_UNLIKELY (xfont->xft_font == NULL))
404 FcPattern *pattern = FcPatternDuplicate (fcfont->font_pattern);
405 FcPatternDel (pattern, FC_SPACING);
407 _pango_xft_font_map_get_info (fcfont->fontmap, &display, &screen);
409 xfont->xft_font = XftFontOpenPattern (display, pattern);
410 if (!xfont->xft_font)
412 gchar *name = pango_font_description_to_string (fcfont->description);
413 g_warning ("Cannot open font file for font %s", name);
416 load_fallback_font (xfont);
420 return xfont->xft_font;
424 pango_xft_font_real_lock_face (PangoFcFont *font)
426 XftFont *xft_font = xft_font_get_font ((PangoFont *)font);
428 return XftLockFace (xft_font);
432 pango_xft_font_real_unlock_face (PangoFcFont *font)
434 XftFont *xft_font = xft_font_get_font ((PangoFont *)font);
436 XftUnlockFace (xft_font);
440 pango_xft_font_real_has_char (PangoFcFont *font,
443 XftFont *xft_font = xft_font_get_font ((PangoFont *)font);
445 return XftCharExists (NULL, xft_font, wc);
449 pango_xft_font_real_get_glyph (PangoFcFont *font,
452 XftFont *xft_font = xft_font_get_font ((PangoFont *)font);
454 return XftCharIndex (NULL, xft_font, wc);
458 pango_xft_font_real_shutdown (PangoFcFont *fcfont)
460 PangoXftFont *xfont = PANGO_XFT_FONT (fcfont);
466 _pango_xft_font_map_get_info (fcfont->fontmap, &display, NULL);
467 XftFontClose (display, xfont->xft_font);
468 xfont->xft_font = NULL;
473 * pango_xft_font_get_font:
474 * @font: a #PangoFont.
476 * Returns the XftFont of a font.
478 * Return value: the XftFont associated to @font, or %NULL if @font is %NULL.
481 pango_xft_font_get_font (PangoFont *font)
483 if (G_UNLIKELY (!font))
486 return xft_font_get_font (font);
490 * pango_xft_font_get_display:
491 * @font: a #PangoFont.
493 * Returns the X display of the XftFont of a font.
495 * Return value: the X display of the XftFont associated to @font.
498 pango_xft_font_get_display (PangoFont *font)
503 g_return_val_if_fail (PANGO_XFT_IS_FONT (font), NULL);
505 fcfont = PANGO_FC_FONT (font);
506 _pango_xft_font_map_get_info (fcfont->fontmap, &display, NULL);
512 * pango_xft_font_get_unknown_glyph:
513 * @font: a #PangoFont.
514 * @wc: the Unicode character for which a glyph is needed.
516 * Returns the index of a glyph suitable for drawing @wc as an
519 * Use PANGO_GET_UNKNOWN_GLYPH() instead.
521 * Return value: a glyph index into @font.
524 pango_xft_font_get_unknown_glyph (PangoFont *font,
527 g_return_val_if_fail (PANGO_XFT_IS_FONT (font), PANGO_GLYPH_EMPTY);
529 return pango_fc_font_get_unknown_glyph (PANGO_FC_FONT (font), wc);
533 * pango_xft_font_lock_face:
534 * @font: a #PangoFont.
536 * Gets the FreeType <type>FT_Face</type> associated with a font,
537 * This face will be kept around until you call
538 * pango_xft_font_unlock_face().
540 * Use pango_fc_font_lock_face() instead.
542 * Return value: the FreeType <type>FT_Face</type> associated with @font.
547 pango_xft_font_lock_face (PangoFont *font)
549 g_return_val_if_fail (PANGO_XFT_IS_FONT (font), NULL);
551 return pango_fc_font_lock_face (PANGO_FC_FONT (font));
555 * pango_xft_font_unlock_face:
556 * @font: a #PangoFont.
558 * Releases a font previously obtained with
559 * pango_xft_font_lock_face().
561 * Use pango_fc_font_unlock_face() instead.
566 pango_xft_font_unlock_face (PangoFont *font)
568 g_return_if_fail (PANGO_XFT_IS_FONT (font));
570 pango_fc_font_unlock_face (PANGO_FC_FONT (font));
574 * pango_xft_font_get_glyph:
575 * @font: a #PangoFont for the Xft backend
576 * @wc: Unicode codepoint to look up
578 * Gets the glyph index for a given Unicode character
579 * for @font. If you only want to determine
580 * whether the font has the glyph, use pango_xft_font_has_char().
582 * Use pango_fc_font_get_glyph() instead.
584 * Return value: the glyph index, or 0, if the Unicode
585 * character does not exist in the font.
590 pango_xft_font_get_glyph (PangoFont *font,
593 g_return_val_if_fail (PANGO_XFT_IS_FONT (font), 0);
595 return pango_fc_font_get_glyph (PANGO_FC_FONT (font), wc);
599 * pango_xft_font_has_char:
600 * @font: a #PangoFont for the Xft backend
601 * @wc: Unicode codepoint to look up
603 * Determines whether @font has a glyph for the codepoint @wc.
605 * Use pango_fc_font_has_char() instead.
607 * Return value: %TRUE if @font has the requested codepoint.
612 pango_xft_font_has_char (PangoFont *font,
615 g_return_val_if_fail (PANGO_XFT_IS_FONT (font), 0);
617 return pango_fc_font_has_char (PANGO_FC_FONT (font), wc);