2 * pangofc-font.c: Shared interfaces for fontconfig-based backends
4 * Copyright (C) 2003 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.
24 #include "pangofc-font.h"
25 #include "pangofc-fontmap.h"
26 #include "pangofc-private.h"
27 #include "pango-layout.h"
28 #include "pango-modules.h"
29 #include "pango-impl-utils.h"
31 #include <fontconfig/fcfreetype.h>
33 #include FT_TRUETYPE_TABLES_H
41 typedef struct _PangoFcFontPrivate PangoFcFontPrivate;
43 struct _PangoFcFontPrivate
45 PangoFcDecoder *decoder;
47 PangoFcCmapCache *cmap_cache;
48 gboolean has_weak_pointer; /* have set a weak_pointer from fontmap to us */
51 static gboolean pango_fc_font_real_has_char (PangoFcFont *font,
53 static guint pango_fc_font_real_get_glyph (PangoFcFont *font,
56 static void pango_fc_font_finalize (GObject *object);
57 static void pango_fc_font_set_property (GObject *object,
61 static void pango_fc_font_get_property (GObject *object,
65 static PangoEngineShape * pango_fc_font_find_shaper (PangoFont *font,
66 PangoLanguage *language,
68 static PangoCoverage * pango_fc_font_get_coverage (PangoFont *font,
69 PangoLanguage *language);
70 static PangoFontMetrics * pango_fc_font_get_metrics (PangoFont *font,
71 PangoLanguage *language);
72 static PangoFontMap * pango_fc_font_get_font_map (PangoFont *font);
73 static PangoFontDescription *pango_fc_font_describe (PangoFont *font);
74 static PangoFontDescription *pango_fc_font_describe_absolute (PangoFont *font);
77 #define PANGO_FC_FONT_LOCK_FACE(font) (PANGO_FC_FONT_GET_CLASS (font)->lock_face (font))
78 #define PANGO_FC_FONT_UNLOCK_FACE(font) (PANGO_FC_FONT_GET_CLASS (font)->unlock_face (font))
80 G_DEFINE_ABSTRACT_TYPE (PangoFcFont, pango_fc_font, PANGO_TYPE_FONT)
83 pango_fc_font_class_init (PangoFcFontClass *class)
85 GObjectClass *object_class = G_OBJECT_CLASS (class);
86 PangoFontClass *font_class = PANGO_FONT_CLASS (class);
88 class->has_char = pango_fc_font_real_has_char;
89 class->get_glyph = pango_fc_font_real_get_glyph;
90 class->get_unknown_glyph = NULL;
92 object_class->finalize = pango_fc_font_finalize;
93 object_class->set_property = pango_fc_font_set_property;
94 object_class->get_property = pango_fc_font_get_property;
95 font_class->describe = pango_fc_font_describe;
96 font_class->describe_absolute = pango_fc_font_describe_absolute;
97 font_class->find_shaper = pango_fc_font_find_shaper;
98 font_class->get_coverage = pango_fc_font_get_coverage;
99 font_class->get_metrics = pango_fc_font_get_metrics;
100 font_class->get_font_map = pango_fc_font_get_font_map;
102 g_object_class_install_property (object_class, PROP_PATTERN,
103 g_param_spec_pointer ("pattern",
105 "The fontconfig pattern for this font",
106 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
107 G_PARAM_STATIC_STRINGS));
108 g_object_class_install_property (object_class, PROP_FONTMAP,
109 g_param_spec_object ("fontmap",
111 "The PangoFc font map this font is associated with (Since: 1.26)",
112 PANGO_TYPE_FC_FONT_MAP,
114 G_PARAM_STATIC_STRINGS));
116 g_type_class_add_private (object_class, sizeof (PangoFcFontPrivate));
120 pango_fc_font_init (PangoFcFont *fcfont)
122 fcfont->priv = G_TYPE_INSTANCE_GET_PRIVATE (fcfont,
128 free_metrics_info (PangoFcMetricsInfo *info)
130 pango_font_metrics_unref (info->metrics);
131 g_slice_free (PangoFcMetricsInfo, info);
135 pango_fc_font_finalize (GObject *object)
137 PangoFcFont *fcfont = PANGO_FC_FONT (object);
138 PangoFcFontPrivate *priv = fcfont->priv;
140 g_slist_foreach (fcfont->metrics_by_lang, (GFunc)free_metrics_info, NULL);
141 g_slist_free (fcfont->metrics_by_lang);
145 _pango_fc_font_map_remove (PANGO_FC_FONT_MAP (fcfont->fontmap), fcfont);
146 if (priv->has_weak_pointer)
148 priv->has_weak_pointer = FALSE;
149 g_object_remove_weak_pointer (G_OBJECT (fcfont->fontmap), (gpointer *) (gpointer) &fcfont->fontmap);
151 fcfont->fontmap = NULL;
154 FcPatternDestroy (fcfont->font_pattern);
155 pango_font_description_free (fcfont->description);
158 _pango_fc_font_set_decoder (fcfont, NULL);
160 if (priv->cmap_cache)
161 _pango_fc_cmap_cache_unref (priv->cmap_cache);
163 G_OBJECT_CLASS (pango_fc_font_parent_class)->finalize (object);
167 pattern_is_hinted (FcPattern *pattern)
171 if (FcPatternGetBool (pattern,
172 FC_HINTING, 0, &hinting) != FcResultMatch)
179 pattern_is_transformed (FcPattern *pattern)
183 if (FcPatternGetMatrix (pattern, FC_MATRIX, 0, &fc_matrix) == FcResultMatch)
187 ft_matrix.xx = 0x10000L * fc_matrix->xx;
188 ft_matrix.yy = 0x10000L * fc_matrix->yy;
189 ft_matrix.xy = 0x10000L * fc_matrix->xy;
190 ft_matrix.yx = 0x10000L * fc_matrix->yx;
192 return ((ft_matrix.xy | ft_matrix.yx) != 0 ||
193 ft_matrix.xx != 0x10000L ||
194 ft_matrix.yy != 0x10000L);
201 pango_fc_font_set_property (GObject *object,
206 PangoFcFont *fcfont = PANGO_FC_FONT (object);
212 FcPattern *pattern = g_value_get_pointer (value);
214 g_return_if_fail (pattern != NULL);
215 g_return_if_fail (fcfont->font_pattern == NULL);
217 FcPatternReference (pattern);
218 fcfont->font_pattern = pattern;
219 fcfont->description = pango_fc_font_description_from_pattern (pattern, TRUE);
220 fcfont->is_hinted = pattern_is_hinted (pattern);
221 fcfont->is_transformed = pattern_is_transformed (pattern);
227 PangoFcFontMap *fcfontmap = PANGO_FC_FONT_MAP (g_value_get_object (value));
229 g_return_if_fail (fcfont->fontmap == NULL);
230 fcfont->fontmap = (PangoFontMap *) fcfontmap;
233 PangoFcFontPrivate *priv = fcfont->priv;
234 priv->has_weak_pointer = TRUE;
235 g_object_add_weak_pointer (G_OBJECT (fcfont->fontmap), (gpointer *) (gpointer) &fcfont->fontmap);
241 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
246 /* set decoder if both pattern and fontmap are set now */
247 if (fcfont->font_pattern && fcfont->fontmap)
248 _pango_fc_font_set_decoder (fcfont,
249 pango_fc_font_map_find_decoder ((PangoFcFontMap *) fcfont->fontmap,
250 fcfont->font_pattern));
254 pango_fc_font_get_property (GObject *object,
263 PangoFcFont *fcfont = PANGO_FC_FONT (object);
264 g_value_set_pointer (value, fcfont->font_pattern);
269 PangoFcFont *fcfont = PANGO_FC_FONT (object);
270 g_value_set_object (value, fcfont->fontmap);
274 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
279 static PangoFontDescription *
280 pango_fc_font_describe (PangoFont *font)
282 PangoFcFont *fcfont = (PangoFcFont *)font;
284 return pango_font_description_copy (fcfont->description);
287 static PangoFontDescription *
288 pango_fc_font_describe_absolute (PangoFont *font)
290 PangoFcFont *fcfont = (PangoFcFont *)font;
291 PangoFontDescription *desc = pango_font_description_copy (fcfont->description);
294 if (FcPatternGetDouble (fcfont->font_pattern, FC_PIXEL_SIZE, 0, &size) == FcResultMatch)
295 pango_font_description_set_absolute_size (desc, size * PANGO_SCALE);
301 pango_fc_get_shaper_map (PangoLanguage *language)
303 static guint engine_type_id = 0;
304 static guint render_type_id = 0;
306 if (engine_type_id == 0)
308 engine_type_id = g_quark_from_static_string (PANGO_ENGINE_TYPE_SHAPE);
309 render_type_id = g_quark_from_static_string (PANGO_RENDER_TYPE_FC);
312 return pango_find_map (language, engine_type_id, render_type_id);
315 static PangoEngineShape *
316 pango_fc_font_find_shaper (PangoFont *font G_GNUC_UNUSED,
317 PangoLanguage *language,
320 PangoMap *shaper_map = NULL;
323 shaper_map = pango_fc_get_shaper_map (language);
324 script = pango_script_for_unichar (ch);
325 return (PangoEngineShape *)pango_map_get_engine (shaper_map, script);
328 static PangoCoverage *
329 pango_fc_font_get_coverage (PangoFont *font,
330 PangoLanguage *language G_GNUC_UNUSED)
332 PangoFcFont *fcfont = (PangoFcFont *)font;
333 PangoFcFontPrivate *priv = fcfont->priv;
338 charset = pango_fc_decoder_get_charset (priv->decoder, fcfont);
339 return _pango_fc_font_map_fc_to_coverage (charset);
342 if (!fcfont->fontmap)
343 return pango_coverage_new ();
345 return _pango_fc_font_map_get_coverage (PANGO_FC_FONT_MAP (fcfont->fontmap),
349 /* For Xft, it would be slightly more efficient to simply to
350 * call Xft, and also more robust against changes in Xft.
351 * But for now, we simply use the same code for all backends.
353 * The code in this function is partly based on code from Xft,
354 * Copyright 2000 Keith Packard
357 get_face_metrics (PangoFcFont *fcfont,
358 PangoFontMetrics *metrics)
360 FT_Face face = PANGO_FC_FONT_LOCK_FACE (fcfont);
364 gboolean have_transform = FALSE;
366 if (G_UNLIKELY (!face))
368 metrics->descent = 0;
369 metrics->ascent = PANGO_SCALE * PANGO_UNKNOWN_GLYPH_HEIGHT;
370 metrics->underline_thickness = PANGO_SCALE;
371 metrics->underline_position = - PANGO_SCALE;
372 metrics->strikethrough_thickness = PANGO_SCALE;
373 metrics->strikethrough_position = PANGO_SCALE * (PANGO_UNKNOWN_GLYPH_HEIGHT/2);
377 if (FcPatternGetMatrix (fcfont->font_pattern,
378 FC_MATRIX, 0, &fc_matrix) == FcResultMatch)
380 ft_matrix.xx = 0x10000L * fc_matrix->xx;
381 ft_matrix.yy = 0x10000L * fc_matrix->yy;
382 ft_matrix.xy = 0x10000L * fc_matrix->xy;
383 ft_matrix.yx = 0x10000L * fc_matrix->yx;
385 have_transform = (ft_matrix.xx != 0x10000 || ft_matrix.xy != 0 ||
386 ft_matrix.yx != 0 || ft_matrix.yy != 0x10000);
394 vector.y = face->size->metrics.descender;
395 FT_Vector_Transform (&vector, &ft_matrix);
396 metrics->descent = - PANGO_UNITS_26_6 (vector.y);
399 vector.y = face->size->metrics.ascender;
400 FT_Vector_Transform (&vector, &ft_matrix);
401 metrics->ascent = PANGO_UNITS_26_6 (vector.y);
403 else if (fcfont->is_hinted ||
404 (face->face_flags & FT_FACE_FLAG_SCALABLE) == 0)
406 metrics->descent = - PANGO_UNITS_26_6 (face->size->metrics.descender);
407 metrics->ascent = PANGO_UNITS_26_6 (face->size->metrics.ascender);
411 FT_Fixed ascender, descender;
413 descender = FT_MulFix (face->descender, face->size->metrics.y_scale);
414 metrics->descent = - PANGO_UNITS_26_6 (descender);
416 ascender = FT_MulFix (face->ascender, face->size->metrics.y_scale);
417 metrics->ascent = PANGO_UNITS_26_6 (ascender);
421 metrics->underline_thickness = 0;
422 metrics->underline_position = 0;
425 FT_Fixed ft_thickness, ft_position;
427 ft_thickness = FT_MulFix (face->underline_thickness, face->size->metrics.y_scale);
428 metrics->underline_thickness = PANGO_UNITS_26_6 (ft_thickness);
430 ft_position = FT_MulFix (face->underline_position, face->size->metrics.y_scale);
431 metrics->underline_position = PANGO_UNITS_26_6 (ft_position);
434 if (metrics->underline_thickness == 0 || metrics->underline_position == 0)
436 metrics->underline_thickness = (PANGO_SCALE * face->size->metrics.y_ppem) / 14;
437 metrics->underline_position = - metrics->underline_thickness;
441 metrics->strikethrough_thickness = 0;
442 metrics->strikethrough_position = 0;
444 os2 = FT_Get_Sfnt_Table (face, ft_sfnt_os2);
445 if (os2 && os2->version != 0xFFFF)
447 FT_Fixed ft_thickness, ft_position;
449 ft_thickness = FT_MulFix (os2->yStrikeoutSize, face->size->metrics.y_scale);
450 metrics->strikethrough_thickness = PANGO_UNITS_26_6 (ft_thickness);
452 ft_position = FT_MulFix (os2->yStrikeoutPosition, face->size->metrics.y_scale);
453 metrics->strikethrough_position = PANGO_UNITS_26_6 (ft_position);
456 if (metrics->strikethrough_thickness == 0 || metrics->strikethrough_position == 0)
458 metrics->strikethrough_thickness = metrics->underline_thickness;
459 metrics->strikethrough_position = (PANGO_SCALE * face->size->metrics.y_ppem) / 4;
463 /* If hinting is on for this font, quantize the underline and strikethrough position
466 if (fcfont->is_hinted)
468 pango_quantize_line_geometry (&metrics->underline_thickness,
469 &metrics->underline_position);
470 pango_quantize_line_geometry (&metrics->strikethrough_thickness,
471 &metrics->strikethrough_position);
473 /* Quantizing may have pushed underline_position to 0. Not good */
474 if (metrics->underline_position == 0)
475 metrics->underline_position = - metrics->underline_thickness;
479 PANGO_FC_FONT_UNLOCK_FACE (fcfont);
483 pango_fc_font_create_base_metrics_for_context (PangoFcFont *fcfont,
484 PangoContext *context)
486 PangoFontMetrics *metrics;
487 metrics = pango_font_metrics_new ();
489 get_face_metrics (fcfont, metrics);
495 max_glyph_width (PangoLayout *layout)
500 for (l = pango_layout_get_lines_readonly (layout); l; l = l->next)
502 PangoLayoutLine *line = l->data;
504 for (r = line->runs; r; r = r->next)
506 PangoGlyphString *glyphs = ((PangoGlyphItem *)r->data)->glyphs;
509 for (i = 0; i < glyphs->num_glyphs; i++)
510 if (glyphs->glyphs[i].geometry.width > max_width)
511 max_width = glyphs->glyphs[i].geometry.width;
518 static PangoFontMetrics *
519 pango_fc_font_get_metrics (PangoFont *font,
520 PangoLanguage *language)
522 PangoFcFont *fcfont = PANGO_FC_FONT (font);
523 PangoFcMetricsInfo *info = NULL; /* Quiet gcc */
526 const char *sample_str = pango_language_get_sample_string (language);
528 tmp_list = fcfont->metrics_by_lang;
531 info = tmp_list->data;
533 if (info->sample_str == sample_str) /* We _don't_ need strcmp */
536 tmp_list = tmp_list->next;
541 PangoFontMap *fontmap;
542 PangoContext *context;
544 /* XXX this is racy. because weakref's are racy... */
545 fontmap = fcfont->fontmap;
547 return pango_font_metrics_new ();
548 fontmap = g_object_ref (fontmap);
550 info = g_slice_new0 (PangoFcMetricsInfo);
552 fcfont->metrics_by_lang = g_slist_prepend (fcfont->metrics_by_lang,
555 info->sample_str = sample_str;
557 context = pango_font_map_create_context (fontmap);
558 pango_context_set_language (context, language);
560 info->metrics = pango_fc_font_create_base_metrics_for_context (fcfont, context);
562 { /* Compute derived metrics */
564 PangoRectangle extents;
565 const char *sample_str = pango_language_get_sample_string (language);
566 PangoFontDescription *desc = pango_font_describe_with_absolute_size (font);
568 layout = pango_layout_new (context);
569 pango_layout_set_font_description (layout, desc);
570 pango_font_description_free (desc);
572 pango_layout_set_text (layout, sample_str, -1);
573 pango_layout_get_extents (layout, NULL, &extents);
575 info->metrics->approximate_char_width = extents.width / pango_utf8_strwidth (sample_str);
577 pango_layout_set_text (layout, "0123456789", -1);
578 info->metrics->approximate_digit_width = max_glyph_width (layout);
580 g_object_unref (layout);
583 g_object_unref (context);
584 g_object_unref (fontmap);
587 return pango_font_metrics_ref (info->metrics);
590 static PangoFontMap *
591 pango_fc_font_get_font_map (PangoFont *font)
593 PangoFcFont *fcfont = PANGO_FC_FONT (font);
595 return fcfont->fontmap;
599 pango_fc_font_real_has_char (PangoFcFont *font,
604 if (FcPatternGetCharSet (font->font_pattern,
605 FC_CHARSET, 0, &charset) != FcResultMatch)
608 return FcCharSetHasChar (charset, wc);
612 pango_fc_font_real_get_glyph (PangoFcFont *font,
615 PangoFcFontPrivate *priv = font->priv;
620 PangoFcCmapCacheEntry *entry;
623 if (G_UNLIKELY (priv->cmap_cache == NULL))
625 priv->cmap_cache = _pango_fc_font_map_get_cmap_cache ((PangoFcFontMap *) font->fontmap,
628 if (G_UNLIKELY (!priv->cmap_cache))
632 idx = wc & CMAP_CACHE_MASK;
633 entry = priv->cmap_cache->entries + idx;
637 face = PANGO_FC_FONT_LOCK_FACE (font);
640 index = FcFreeTypeCharIndex (face, wc);
641 if (index > (FT_UInt)face->num_glyphs)
644 PANGO_FC_FONT_UNLOCK_FACE (font);
650 entry->glyph = index;
657 * pango_fc_font_lock_face:
658 * @font: a #PangoFcFont.
660 * Gets the FreeType <type>FT_Face</type> associated with a font,
661 * This face will be kept around until you call
662 * pango_fc_font_unlock_face().
664 * Return value: the FreeType <type>FT_Face</type> associated with @font.
669 pango_fc_font_lock_face (PangoFcFont *font)
671 g_return_val_if_fail (PANGO_IS_FC_FONT (font), NULL);
673 return PANGO_FC_FONT_LOCK_FACE (font);
677 * pango_fc_font_unlock_face:
678 * @font: a #PangoFcFont.
680 * Releases a font previously obtained with
681 * pango_fc_font_lock_face().
686 pango_fc_font_unlock_face (PangoFcFont *font)
688 g_return_if_fail (PANGO_IS_FC_FONT (font));
690 PANGO_FC_FONT_UNLOCK_FACE (font);
694 * pango_fc_font_has_char:
695 * @font: a #PangoFcFont
696 * @wc: Unicode codepoint to look up
698 * Determines whether @font has a glyph for the codepoint @wc.
700 * Return value: %TRUE if @font has the requested codepoint.
705 pango_fc_font_has_char (PangoFcFont *font,
708 PangoFcFontPrivate *priv = font->priv;
711 g_return_val_if_fail (PANGO_IS_FC_FONT (font), FALSE);
715 charset = pango_fc_decoder_get_charset (priv->decoder, font);
716 return FcCharSetHasChar (charset, wc);
719 return PANGO_FC_FONT_GET_CLASS (font)->has_char (font, wc);
723 * pango_fc_font_get_glyph:
724 * @font: a #PangoFcFont
725 * @wc: Unicode character to look up
727 * Gets the glyph index for a given Unicode character
728 * for @font. If you only want to determine
729 * whether the font has the glyph, use pango_fc_font_has_char().
731 * Return value: the glyph index, or 0, if the Unicode
732 * character doesn't exist in the font.
737 pango_fc_font_get_glyph (PangoFcFont *font,
740 PangoFcFontPrivate *priv = font->priv;
742 /* Replace NBSP with a normal space; it should be invariant that
743 * they shape the same other than breaking properties.
749 return pango_fc_decoder_get_glyph (priv->decoder, font, wc);
751 return PANGO_FC_FONT_GET_CLASS (font)->get_glyph (font, wc);
756 * pango_fc_font_get_unknown_glyph:
757 * @font: a #PangoFcFont
758 * @wc: the Unicode character for which a glyph is needed.
760 * Returns the index of a glyph suitable for drawing @wc as an
763 * Use PANGO_GET_UNKNOWN_GLYPH() instead.
765 * Return value: a glyph index into @font.
770 pango_fc_font_get_unknown_glyph (PangoFcFont *font,
773 if (font && PANGO_FC_FONT_GET_CLASS (font)->get_unknown_glyph)
774 return PANGO_FC_FONT_GET_CLASS (font)->get_unknown_glyph (font, wc);
776 return PANGO_GET_UNKNOWN_GLYPH (wc);
780 _pango_fc_font_shutdown (PangoFcFont *font)
782 g_return_if_fail (PANGO_IS_FC_FONT (font));
784 if (PANGO_FC_FONT_GET_CLASS (font)->shutdown)
785 PANGO_FC_FONT_GET_CLASS (font)->shutdown (font);
789 * pango_fc_font_kern_glyphs:
790 * @font: a #PangoFcFont
791 * @glyphs: a #PangoGlyphString
793 * Adjust each adjacent pair of glyphs in @glyphs according to
794 * kerning information in @font.
799 pango_fc_font_kern_glyphs (PangoFcFont *font,
800 PangoGlyphString *glyphs)
806 gboolean hinting = font->is_hinted;
807 gboolean scale = FALSE;
811 g_return_if_fail (PANGO_IS_FC_FONT (font));
812 g_return_if_fail (glyphs != NULL);
814 face = PANGO_FC_FONT_LOCK_FACE (font);
815 if (G_UNLIKELY (!face))
818 if (!FT_HAS_KERNING (face))
820 PANGO_FC_FONT_UNLOCK_FACE (font);
824 /* This is a kludge, and dupped in pango_ot_buffer_output().
825 * Should move the scale factor to PangoFcFont layer. */
826 key = _pango_fc_font_get_font_key (font);
828 const PangoMatrix *matrix = pango_fc_font_key_get_matrix (key);
829 PangoMatrix identity = PANGO_MATRIX_INIT;
830 if (G_UNLIKELY (matrix && 0 != memcmp (&identity, matrix, 2 * sizeof (double))))
833 pango_matrix_get_font_scale_factors (matrix, &xscale, NULL);
834 if (xscale) xscale = 1 / xscale;
838 for (i = 1; i < glyphs->num_glyphs; ++i)
840 error = FT_Get_Kerning (face,
841 glyphs->glyphs[i-1].glyph,
842 glyphs->glyphs[i].glyph,
846 if (error == FT_Err_Ok) {
847 int adjustment = PANGO_UNITS_26_6 (kerning.x);
850 adjustment = PANGO_UNITS_ROUND (adjustment);
851 if (G_UNLIKELY (scale))
852 adjustment *= xscale;
854 glyphs->glyphs[i-1].geometry.width += adjustment;
858 PANGO_FC_FONT_UNLOCK_FACE (font);
862 * _pango_fc_font_get_decoder:
863 * @font: a #PangoFcFont
865 * This will return any custom decoder set on this font.
867 * Return value: The custom decoder
873 _pango_fc_font_get_decoder (PangoFcFont *font)
875 PangoFcFontPrivate *priv = font->priv;
877 return priv->decoder;
881 * _pango_fc_font_set_decoder:
882 * @font: a #PangoFcFont
883 * @decoder: a #PangoFcDecoder to set for this font
885 * This sets a custom decoder for this font. Any previous decoder
886 * will be released before this one is set.
892 _pango_fc_font_set_decoder (PangoFcFont *font,
893 PangoFcDecoder *decoder)
895 PangoFcFontPrivate *priv = font->priv;
898 g_object_unref (priv->decoder);
900 priv->decoder = decoder;
903 g_object_ref (priv->decoder);
907 _pango_fc_font_get_font_key (PangoFcFont *fcfont)
909 PangoFcFontPrivate *priv = fcfont->priv;
915 _pango_fc_font_set_font_key (PangoFcFont *fcfont,
918 PangoFcFontPrivate *priv = fcfont->priv;
923 static FT_Glyph_Metrics *
924 get_per_char (FT_Face face,
929 FT_Glyph_Metrics *result;
931 error = FT_Load_Glyph (face, glyph, load_flags);
932 if (error == FT_Err_Ok)
933 result = &face->glyph->metrics;
941 * pango_fc_font_get_raw_extents:
942 * @fcfont: a #PangoFcFont
943 * @load_flags: flags to pass to FT_Load_Glyph()
944 * @glyph: the glyph index to load
945 * @ink_rect: location to store ink extents of the glyph, or %NULL
946 * @logical_rect: location to store logical extents of the glyph or %NULL
948 * Gets the extents of a single glyph from a font. The extents are in
949 * user space; that is, they are not transformed by any matrix in effect
952 * Long term, this functionality probably belongs in the default
953 * implementation of the get_glyph_extents() virtual function.
954 * The other possibility would be to to make it public in something
955 * like it's current form, and also expose glyph information
956 * caching functionality similar to pango_ft2_font_set_glyph_info().
961 pango_fc_font_get_raw_extents (PangoFcFont *fcfont,
964 PangoRectangle *ink_rect,
965 PangoRectangle *logical_rect)
967 FT_Glyph_Metrics *gm;
970 g_return_if_fail (PANGO_IS_FC_FONT (fcfont));
972 face = PANGO_FC_FONT_LOCK_FACE (fcfont);
973 if (G_UNLIKELY (!face))
975 /* Get generic unknown-glyph extents. */
976 pango_font_get_glyph_extents (NULL, glyph, ink_rect, logical_rect);
980 if (glyph == PANGO_GLYPH_EMPTY)
983 gm = get_per_char (face, load_flags, glyph);
989 ink_rect->x = PANGO_UNITS_26_6 (gm->horiBearingX);
990 ink_rect->width = PANGO_UNITS_26_6 (gm->width);
991 ink_rect->y = -PANGO_UNITS_26_6 (gm->horiBearingY);
992 ink_rect->height = PANGO_UNITS_26_6 (gm->height);
998 logical_rect->width = PANGO_UNITS_26_6 (gm->horiAdvance);
999 if (fcfont->is_hinted ||
1000 (face->face_flags & FT_FACE_FLAG_SCALABLE) == 0)
1002 logical_rect->y = - PANGO_UNITS_26_6 (face->size->metrics.ascender);
1003 logical_rect->height = PANGO_UNITS_26_6 (face->size->metrics.ascender - face->size->metrics.descender);
1007 FT_Fixed ascender, descender;
1009 ascender = FT_MulFix (face->ascender, face->size->metrics.y_scale);
1010 descender = FT_MulFix (face->descender, face->size->metrics.y_scale);
1012 logical_rect->y = - PANGO_UNITS_26_6 (ascender);
1013 logical_rect->height = PANGO_UNITS_26_6 (ascender - descender);
1022 ink_rect->width = 0;
1024 ink_rect->height = 0;
1029 logical_rect->x = 0;
1030 logical_rect->width = 0;
1031 logical_rect->y = 0;
1032 logical_rect->height = 0;
1036 PANGO_FC_FONT_UNLOCK_FACE (fcfont);