2 * pangoft2.c: Routines for handling FreeType2 fonts
4 * Copyright (C) 1999 Red Hat Software
5 * Copyright (C) 2000 Tor Lillqvist
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
29 #include <glib/gprintf.h>
32 #include "pangoft2-private.h"
33 #include "pangofc-fontmap.h"
34 #include "pangofc-private.h"
36 /* for compatibility with older freetype versions */
37 #ifndef FT_LOAD_TARGET_MONO
38 #define FT_LOAD_TARGET_MONO FT_LOAD_MONOCHROME
41 #define PANGO_FT2_FONT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PANGO_TYPE_FT2_FONT, PangoFT2FontClass))
42 #define PANGO_FT2_IS_FONT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANGO_TYPE_FT2_FONT))
43 #define PANGO_FT2_FONT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PANGO_TYPE_FT2_FONT, PangoFT2FontClass))
45 typedef struct _PangoFT2FontClass PangoFT2FontClass;
47 struct _PangoFT2FontClass
49 PangoFcFontClass parent_class;
52 static void pango_ft2_font_finalize (GObject *object);
54 static void pango_ft2_font_get_glyph_extents (PangoFont *font,
56 PangoRectangle *ink_rect,
57 PangoRectangle *logical_rect);
59 static FT_Face pango_ft2_font_real_lock_face (PangoFcFont *font);
60 static void pango_ft2_font_real_unlock_face (PangoFcFont *font);
64 _pango_ft2_font_new (PangoFT2FontMap *ft2fontmap,
67 PangoFontMap *fontmap = PANGO_FONT_MAP (ft2fontmap);
68 PangoFT2Font *ft2font;
71 g_return_val_if_fail (fontmap != NULL, NULL);
72 g_return_val_if_fail (pattern != NULL, NULL);
74 ft2font = (PangoFT2Font *)g_object_new (PANGO_TYPE_FT2_FONT,
79 if (FcPatternGetDouble (pattern, FC_PIXEL_SIZE, 0, &d) == FcResultMatch)
80 ft2font->size = d*PANGO_SCALE;
86 load_fallback_face (PangoFT2Font *ft2font,
87 const char *original_file)
89 PangoFcFont *fcfont = PANGO_FC_FONT (ft2font);
94 FcChar8 *filename2 = NULL;
98 sans = FcPatternBuild (NULL,
99 FC_FAMILY, FcTypeString, "sans",
100 FC_PIXEL_SIZE, FcTypeDouble, (double)ft2font->size / PANGO_SCALE,
103 _pango_ft2_font_map_default_substitute ((PangoFcFontMap *)fcfont->fontmap, sans);
105 matched = FcFontMatch (NULL, sans, &result);
107 if (FcPatternGetString (matched, FC_FILE, 0, &filename2) != FcResultMatch)
110 if (FcPatternGetInteger (matched, FC_INDEX, 0, &id) != FcResultMatch)
113 error = FT_New_Face (_pango_ft2_font_map_get_library (fcfont->fontmap),
114 (char *) filename2, id, &ft2font->face);
120 name = pango_font_description_to_string (fcfont->description);
121 g_error ("Unable to open font file %s for font %s, exiting\n", filename2, name);
125 name = pango_font_description_to_string (fcfont->description);
126 g_warning ("Unable to open font file %s for font %s, falling back to %s\n", original_file, name, filename2);
130 FcPatternDestroy (sans);
131 FcPatternDestroy (matched);
135 set_transform (PangoFT2Font *ft2font)
137 PangoFcFont *fcfont = (PangoFcFont *)ft2font;
140 if (FcPatternGetMatrix (fcfont->font_pattern, FC_MATRIX, 0, &fc_matrix) == FcResultMatch)
144 ft_matrix.xx = 0x10000L * fc_matrix->xx;
145 ft_matrix.yy = 0x10000L * fc_matrix->yy;
146 ft_matrix.xy = 0x10000L * fc_matrix->xy;
147 ft_matrix.yx = 0x10000L * fc_matrix->yx;
149 FT_Set_Transform (ft2font->face, &ft_matrix, NULL);
154 * pango_ft2_font_get_face:
155 * @font: a #PangoFont
157 * Returns the native FreeType2 <type>FT_Face</type> structure used for this #PangoFont.
158 * This may be useful if you want to use FreeType2 functions directly.
160 * Use pango_fc_font_lock_face() instead; when you are done with a
161 * face from pango_fc_font_lock_face() you must call
162 * pango_fc_font_unlock_face().
164 * Return value: a pointer to a <type>FT_Face</type> structure, with the size set correctly,
165 * or %NULL if @font is %NULL.
168 pango_ft2_font_get_face (PangoFont *font)
170 PangoFT2Font *ft2font = (PangoFT2Font *)font;
171 PangoFcFont *fcfont = (PangoFcFont *)font;
175 FcBool antialias, hinting, autohint;
179 if (G_UNLIKELY (!font))
182 pattern = fcfont->font_pattern;
186 ft2font->load_flags = 0;
188 /* disable antialiasing if requested */
189 if (FcPatternGetBool (pattern,
190 FC_ANTIALIAS, 0, &antialias) != FcResultMatch)
194 ft2font->load_flags |= FT_LOAD_NO_BITMAP;
196 ft2font->load_flags |= FT_LOAD_TARGET_MONO;
198 /* disable hinting if requested */
199 if (FcPatternGetBool (pattern,
200 FC_HINTING, 0, &hinting) != FcResultMatch)
204 if (FcPatternGetInteger (pattern, FC_HINT_STYLE, 0, &hintstyle) != FcResultMatch)
205 hintstyle = FC_HINT_FULL;
207 if (!hinting || hintstyle == FC_HINT_NONE)
208 ft2font->load_flags |= FT_LOAD_NO_HINTING;
213 ft2font->load_flags |= FT_LOAD_TARGET_LIGHT;
216 ft2font->load_flags |= FT_LOAD_TARGET_NORMAL;
221 ft2font->load_flags |= FT_LOAD_NO_HINTING;
224 /* force autohinting if requested */
225 if (FcPatternGetBool (pattern,
226 FC_AUTOHINT, 0, &autohint) != FcResultMatch)
230 ft2font->load_flags |= FT_LOAD_FORCE_AUTOHINT;
232 if (FcPatternGetString (pattern, FC_FILE, 0, &filename) != FcResultMatch)
235 if (FcPatternGetInteger (pattern, FC_INDEX, 0, &id) != FcResultMatch)
238 error = FT_New_Face (_pango_ft2_font_map_get_library (fcfont->fontmap),
239 (char *) filename, id, &ft2font->face);
240 if (error != FT_Err_Ok)
243 load_fallback_face (ft2font, (char *) filename);
246 g_assert (ft2font->face);
248 set_transform (ft2font);
250 error = FT_Set_Char_Size (ft2font->face,
251 PANGO_PIXELS_26_6 (ft2font->size),
252 PANGO_PIXELS_26_6 (ft2font->size),
255 g_warning ("Error in FT_Set_Char_Size: %d", error);
258 return ft2font->face;
261 G_DEFINE_TYPE (PangoFT2Font, pango_ft2_font, PANGO_TYPE_FC_FONT)
264 pango_ft2_font_init (PangoFT2Font *ft2font)
266 ft2font->face = NULL;
270 ft2font->glyph_info = g_hash_table_new (NULL, NULL);
274 pango_ft2_font_class_init (PangoFT2FontClass *class)
276 GObjectClass *object_class = G_OBJECT_CLASS (class);
277 PangoFontClass *font_class = PANGO_FONT_CLASS (class);
278 PangoFcFontClass *fc_font_class = PANGO_FC_FONT_CLASS (class);
280 object_class->finalize = pango_ft2_font_finalize;
282 font_class->get_glyph_extents = pango_ft2_font_get_glyph_extents;
284 fc_font_class->lock_face = pango_ft2_font_real_lock_face;
285 fc_font_class->unlock_face = pango_ft2_font_real_unlock_face;
288 static PangoFT2GlyphInfo *
289 pango_ft2_font_get_glyph_info (PangoFont *font,
293 PangoFT2Font *ft2font = (PangoFT2Font *)font;
294 PangoFcFont *fcfont = (PangoFcFont *)font;
295 PangoFT2GlyphInfo *info;
297 info = g_hash_table_lookup (ft2font->glyph_info, GUINT_TO_POINTER (glyph));
299 if ((info == NULL) && create)
301 info = g_slice_new0 (PangoFT2GlyphInfo);
303 pango_fc_font_get_raw_extents (fcfont, ft2font->load_flags,
306 &info->logical_rect);
308 g_hash_table_insert (ft2font->glyph_info, GUINT_TO_POINTER(glyph), info);
315 pango_ft2_font_get_glyph_extents (PangoFont *font,
317 PangoRectangle *ink_rect,
318 PangoRectangle *logical_rect)
320 PangoFT2GlyphInfo *info;
321 gboolean empty = FALSE;
323 if (glyph == PANGO_GLYPH_EMPTY)
325 glyph = pango_fc_font_get_glyph ((PangoFcFont *) font, ' ');
329 if (glyph & PANGO_GLYPH_UNKNOWN_FLAG)
331 PangoFontMetrics *metrics = pango_font_get_metrics (font, NULL);
337 ink_rect->x = PANGO_SCALE;
338 ink_rect->width = metrics->approximate_char_width - 2 * PANGO_SCALE;
339 ink_rect->y = - (metrics->ascent - PANGO_SCALE);
340 ink_rect->height = metrics->ascent + metrics->descent - 2 * PANGO_SCALE;
345 logical_rect->width = metrics->approximate_char_width;
346 logical_rect->y = -metrics->ascent;
347 logical_rect->height = metrics->ascent + metrics->descent;
350 pango_font_metrics_unref (metrics);
355 ink_rect->x = ink_rect->y = ink_rect->height = ink_rect->width = 0;
357 logical_rect->x = logical_rect->y = logical_rect->height = logical_rect->width = 0;
362 info = pango_ft2_font_get_glyph_info (font, glyph, TRUE);
365 *ink_rect = info->ink_rect;
367 *logical_rect = info->logical_rect;
372 ink_rect->x = ink_rect->y = ink_rect->height = ink_rect->width = 0;
374 logical_rect->x = logical_rect->width = 0;
380 * pango_ft2_font_get_kerning:
381 * @font: a #PangoFont
382 * @left: the left #PangoGlyph
383 * @right: the right #PangoGlyph
385 * Retrieves kerning information for a combination of two glyphs.
387 * Use pango_fc_font_kern_glyphs() instead.
389 * Return value: The amount of kerning (in Pango units) to apply for
390 * the given combination of glyphs.
393 pango_ft2_font_get_kerning (PangoFont *font,
397 PangoFcFont *fc_font = PANGO_FC_FONT (font);
403 face = pango_fc_font_lock_face (fc_font);
407 if (!FT_HAS_KERNING (face))
409 pango_fc_font_unlock_face (fc_font);
413 error = FT_Get_Kerning (face, left, right, ft_kerning_default, &kerning);
414 if (error != FT_Err_Ok)
416 pango_fc_font_unlock_face (fc_font);
420 pango_fc_font_unlock_face (fc_font);
421 return PANGO_UNITS_26_6 (kerning.x);
425 pango_ft2_font_real_lock_face (PangoFcFont *font)
427 return pango_ft2_font_get_face ((PangoFont *)font);
431 pango_ft2_font_real_unlock_face (PangoFcFont *font G_GNUC_UNUSED)
436 pango_ft2_free_glyph_info_callback (gpointer key G_GNUC_UNUSED,
440 PangoFT2Font *font = PANGO_FT2_FONT (data);
441 PangoFT2GlyphInfo *info = value;
443 if (font->glyph_cache_destroy && info->cached_glyph)
444 (*font->glyph_cache_destroy) (info->cached_glyph);
446 g_slice_free (PangoFT2GlyphInfo, info);
451 pango_ft2_font_finalize (GObject *object)
453 PangoFT2Font *ft2font = (PangoFT2Font *)object;
457 FT_Done_Face (ft2font->face);
458 ft2font->face = NULL;
461 g_hash_table_foreach_remove (ft2font->glyph_info,
462 pango_ft2_free_glyph_info_callback, object);
463 g_hash_table_destroy (ft2font->glyph_info);
465 G_OBJECT_CLASS (pango_ft2_font_parent_class)->finalize (object);
469 * pango_ft2_font_get_coverage:
470 * @font: a #PangoFT2Font.
471 * @language: a language tag.
472 * @returns: a #PangoCoverage.
474 * Gets the #PangoCoverage for a #PangoFT2Font. Use
475 * pango_font_get_coverage() instead.
478 pango_ft2_font_get_coverage (PangoFont *font,
479 PangoLanguage *language)
481 return pango_font_get_coverage (font, language);
484 /* Utility functions */
487 * pango_ft2_get_unknown_glyph:
488 * @font: a #PangoFont
490 * Return the index of a glyph suitable for drawing unknown characters with
491 * @font, or %PANGO_GLYPH_EMPTY if no suitable glyph found.
493 * If you want to draw an unknown-box for a character that is not covered
495 * use PANGO_GET_UNKNOWN_GLYPH() instead.
497 * Return value: a glyph index into @font, or %PANGO_GLYPH_EMPTY
500 pango_ft2_get_unknown_glyph (PangoFont *font)
502 FT_Face face = pango_ft2_font_get_face (font);
503 if (face && FT_IS_SFNT (face))
504 /* TrueType fonts have an 'unknown glyph' box on glyph index 0 */
507 return PANGO_GLYPH_EMPTY;
514 } ft_error_description;
517 ft_error_compare (const void *pkey,
520 return ((ft_error_description *) pkey)->code - ((ft_error_description *) pbase)->code;
523 G_CONST_RETURN char *
524 _pango_ft2_ft_strerror (FT_Error error)
526 #undef __FTERRORS_H__
527 #define FT_ERRORDEF( e, v, s ) { e, s },
528 #define FT_ERROR_START_LIST {
529 #define FT_ERROR_END_LIST };
531 static const ft_error_description ft_errors[] =
535 #undef FT_ERROR_START_LIST
536 #undef FT_ERROR_END_LIST
538 ft_error_description *found =
539 bsearch (&error, ft_errors, G_N_ELEMENTS (ft_errors),
540 sizeof (ft_errors[0]), ft_error_compare);
545 static char *default_msg = NULL;
548 default_msg = g_malloc (60);
550 g_sprintf (default_msg, "Unknown FreeType2 error %#x", error);
556 _pango_ft2_font_get_cache_glyph_data (PangoFont *font,
559 PangoFT2GlyphInfo *info;
561 if (!PANGO_FT2_IS_FONT (font))
564 info = pango_ft2_font_get_glyph_info (font, glyph_index, FALSE);
569 return info->cached_glyph;
573 _pango_ft2_font_set_cache_glyph_data (PangoFont *font,
577 PangoFT2GlyphInfo *info;
579 if (!PANGO_FT2_IS_FONT (font))
582 info = pango_ft2_font_get_glyph_info (font, glyph_index, TRUE);
584 info->cached_glyph = cached_glyph;
586 /* TODO: Implement limiting of the number of cached glyphs */
590 _pango_ft2_font_set_glyph_cache_destroy (PangoFont *font,
591 GDestroyNotify destroy_notify)
593 if (!PANGO_FT2_IS_FONT (font))
596 PANGO_FT2_FONT (font)->glyph_cache_destroy = destroy_notify;