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 max_glyph_width (PangoLayout *layout)
488 for (l = pango_layout_get_lines_readonly (layout); l; l = l->next)
490 PangoLayoutLine *line = l->data;
492 for (r = line->runs; r; r = r->next)
494 PangoGlyphString *glyphs = ((PangoGlyphItem *)r->data)->glyphs;
497 for (i = 0; i < glyphs->num_glyphs; i++)
498 if (glyphs->glyphs[i].geometry.width > max_width)
499 max_width = glyphs->glyphs[i].geometry.width;
507 pango_fc_font_create_metrics_for_context (PangoFcFont *fcfont,
508 PangoContext *context)
510 PangoFontMetrics *metrics;
512 PangoRectangle extents;
513 PangoLanguage *language = pango_context_get_language (context);
514 const char *sample_str = pango_language_get_sample_string (language);
515 PangoFontDescription *desc = pango_font_describe_with_absolute_size (PANGO_FONT (fcfont));
517 metrics = pango_font_metrics_new ();
519 get_face_metrics (fcfont, metrics);
521 layout = pango_layout_new (context);
522 pango_layout_set_font_description (layout, desc);
523 pango_font_description_free (desc);
525 pango_layout_set_text (layout, sample_str, -1);
526 pango_layout_get_extents (layout, NULL, &extents);
528 metrics->approximate_char_width =
529 extents.width / pango_utf8_strwidth (sample_str);
531 pango_layout_set_text (layout, "0123456789", -1);
532 metrics->approximate_digit_width = max_glyph_width (layout);
534 g_object_unref (layout);
539 /* This function is cut-and-pasted into pangocairo-fcfont.c - it might be
540 * better to add a virtual fcfont->create_context (font).
542 static PangoFontMetrics *
543 pango_fc_font_get_metrics (PangoFont *font,
544 PangoLanguage *language)
546 PangoFcFont *fcfont = PANGO_FC_FONT (font);
547 PangoFcMetricsInfo *info = NULL; /* Quiet gcc */
550 const char *sample_str = pango_language_get_sample_string (language);
552 tmp_list = fcfont->metrics_by_lang;
555 info = tmp_list->data;
557 if (info->sample_str == sample_str) /* We _don't_ need strcmp */
560 tmp_list = tmp_list->next;
565 PangoFontMap *fontmap;
566 PangoContext *context;
568 /* XXX this is racy. because weakref's are racy... */
569 fontmap = fcfont->fontmap;
571 return pango_font_metrics_new ();
572 fontmap = g_object_ref (fontmap);
574 info = g_slice_new0 (PangoFcMetricsInfo);
576 fcfont->metrics_by_lang = g_slist_prepend (fcfont->metrics_by_lang,
579 info->sample_str = sample_str;
581 context = pango_font_map_create_context (fontmap);
582 pango_context_set_language (context, language);
584 info->metrics = pango_fc_font_create_metrics_for_context (fcfont, context);
586 g_object_unref (context);
587 g_object_unref (fontmap);
590 return pango_font_metrics_ref (info->metrics);
593 static PangoFontMap *
594 pango_fc_font_get_font_map (PangoFont *font)
596 PangoFcFont *fcfont = PANGO_FC_FONT (font);
598 return fcfont->fontmap;
602 pango_fc_font_real_has_char (PangoFcFont *font,
607 if (FcPatternGetCharSet (font->font_pattern,
608 FC_CHARSET, 0, &charset) != FcResultMatch)
611 return FcCharSetHasChar (charset, wc);
615 pango_fc_font_real_get_glyph (PangoFcFont *font,
618 PangoFcFontPrivate *priv = font->priv;
623 PangoFcCmapCacheEntry *entry;
626 if (G_UNLIKELY (priv->cmap_cache == NULL))
628 priv->cmap_cache = _pango_fc_font_map_get_cmap_cache ((PangoFcFontMap *) font->fontmap,
631 if (G_UNLIKELY (!priv->cmap_cache))
635 idx = wc & CMAP_CACHE_MASK;
636 entry = priv->cmap_cache->entries + idx;
640 face = PANGO_FC_FONT_LOCK_FACE (font);
643 index = FcFreeTypeCharIndex (face, wc);
644 if (index > (FT_UInt)face->num_glyphs)
647 PANGO_FC_FONT_UNLOCK_FACE (font);
653 entry->glyph = index;
660 * pango_fc_font_lock_face:
661 * @font: a #PangoFcFont.
663 * Gets the FreeType <type>FT_Face</type> associated with a font,
664 * This face will be kept around until you call
665 * pango_fc_font_unlock_face().
667 * Return value: the FreeType <type>FT_Face</type> associated with @font.
672 pango_fc_font_lock_face (PangoFcFont *font)
674 g_return_val_if_fail (PANGO_IS_FC_FONT (font), NULL);
676 return PANGO_FC_FONT_LOCK_FACE (font);
680 * pango_fc_font_unlock_face:
681 * @font: a #PangoFcFont.
683 * Releases a font previously obtained with
684 * pango_fc_font_lock_face().
689 pango_fc_font_unlock_face (PangoFcFont *font)
691 g_return_if_fail (PANGO_IS_FC_FONT (font));
693 PANGO_FC_FONT_UNLOCK_FACE (font);
697 * pango_fc_font_has_char:
698 * @font: a #PangoFcFont
699 * @wc: Unicode codepoint to look up
701 * Determines whether @font has a glyph for the codepoint @wc.
703 * Return value: %TRUE if @font has the requested codepoint.
708 pango_fc_font_has_char (PangoFcFont *font,
711 PangoFcFontPrivate *priv = font->priv;
714 g_return_val_if_fail (PANGO_IS_FC_FONT (font), FALSE);
718 charset = pango_fc_decoder_get_charset (priv->decoder, font);
719 return FcCharSetHasChar (charset, wc);
722 return PANGO_FC_FONT_GET_CLASS (font)->has_char (font, wc);
726 * pango_fc_font_get_glyph:
727 * @font: a #PangoFcFont
728 * @wc: Unicode character to look up
730 * Gets the glyph index for a given Unicode character
731 * for @font. If you only want to determine
732 * whether the font has the glyph, use pango_fc_font_has_char().
734 * Return value: the glyph index, or 0, if the Unicode
735 * character doesn't exist in the font.
740 pango_fc_font_get_glyph (PangoFcFont *font,
743 PangoFcFontPrivate *priv = font->priv;
745 /* Replace NBSP with a normal space; it should be invariant that
746 * they shape the same other than breaking properties.
752 return pango_fc_decoder_get_glyph (priv->decoder, font, wc);
754 return PANGO_FC_FONT_GET_CLASS (font)->get_glyph (font, wc);
759 * pango_fc_font_get_unknown_glyph:
760 * @font: a #PangoFcFont
761 * @wc: the Unicode character for which a glyph is needed.
763 * Returns the index of a glyph suitable for drawing @wc as an
766 * Use PANGO_GET_UNKNOWN_GLYPH() instead.
768 * Return value: a glyph index into @font.
773 pango_fc_font_get_unknown_glyph (PangoFcFont *font,
776 if (font && PANGO_FC_FONT_GET_CLASS (font)->get_unknown_glyph)
777 return PANGO_FC_FONT_GET_CLASS (font)->get_unknown_glyph (font, wc);
779 return PANGO_GET_UNKNOWN_GLYPH (wc);
783 _pango_fc_font_shutdown (PangoFcFont *font)
785 g_return_if_fail (PANGO_IS_FC_FONT (font));
787 if (PANGO_FC_FONT_GET_CLASS (font)->shutdown)
788 PANGO_FC_FONT_GET_CLASS (font)->shutdown (font);
792 * pango_fc_font_kern_glyphs
793 * @font: a #PangoFcFont
794 * @glyphs: a #PangoGlyphString
796 * Adjust each adjacent pair of glyphs in @glyphs according to
797 * kerning information in @font.
802 pango_fc_font_kern_glyphs (PangoFcFont *font,
803 PangoGlyphString *glyphs)
809 gboolean hinting = font->is_hinted;
810 gboolean scale = FALSE;
814 g_return_if_fail (PANGO_IS_FC_FONT (font));
815 g_return_if_fail (glyphs != NULL);
817 face = PANGO_FC_FONT_LOCK_FACE (font);
818 if (G_UNLIKELY (!face))
821 if (!FT_HAS_KERNING (face))
823 PANGO_FC_FONT_UNLOCK_FACE (font);
827 /* This is a kludge, and dupped in pango_ot_buffer_output().
828 * Should move the scale factor to PangoFcFont layer. */
829 key = _pango_fc_font_get_font_key (font);
831 const PangoMatrix *matrix = pango_fc_font_key_get_matrix (key);
832 PangoMatrix identity = PANGO_MATRIX_INIT;
833 if (G_UNLIKELY (matrix && 0 != memcmp (&identity, matrix, 2 * sizeof (double))))
836 pango_matrix_get_font_scale_factors (matrix, &xscale, NULL);
837 if (xscale) xscale = 1 / xscale;
841 for (i = 1; i < glyphs->num_glyphs; ++i)
843 error = FT_Get_Kerning (face,
844 glyphs->glyphs[i-1].glyph,
845 glyphs->glyphs[i].glyph,
849 if (error == FT_Err_Ok) {
850 int adjustment = PANGO_UNITS_26_6 (kerning.x);
853 adjustment = PANGO_UNITS_ROUND (adjustment);
854 if (G_UNLIKELY (scale))
855 adjustment *= xscale;
857 glyphs->glyphs[i-1].geometry.width += adjustment;
861 PANGO_FC_FONT_UNLOCK_FACE (font);
865 * _pango_fc_font_get_decoder
866 * @font: a #PangoFcFont
868 * This will return any custom decoder set on this font.
870 * Return value: The custom decoder
876 _pango_fc_font_get_decoder (PangoFcFont *font)
878 PangoFcFontPrivate *priv = font->priv;
880 return priv->decoder;
884 * _pango_fc_font_set_decoder
885 * @font: a #PangoFcFont
886 * @decoder: a #PangoFcDecoder to set for this font
888 * This sets a custom decoder for this font. Any previous decoder
889 * will be released before this one is set.
895 _pango_fc_font_set_decoder (PangoFcFont *font,
896 PangoFcDecoder *decoder)
898 PangoFcFontPrivate *priv = font->priv;
901 g_object_unref (priv->decoder);
903 priv->decoder = decoder;
906 g_object_ref (priv->decoder);
910 _pango_fc_font_get_font_key (PangoFcFont *fcfont)
912 PangoFcFontPrivate *priv = fcfont->priv;
918 _pango_fc_font_set_font_key (PangoFcFont *fcfont,
921 PangoFcFontPrivate *priv = fcfont->priv;
926 static FT_Glyph_Metrics *
927 get_per_char (FT_Face face,
932 FT_Glyph_Metrics *result;
934 error = FT_Load_Glyph (face, glyph, load_flags);
935 if (error == FT_Err_Ok)
936 result = &face->glyph->metrics;
944 * pango_fc_font_get_raw_extents:
945 * @fcfont: a #PangoFcFont
946 * @load_flags: flags to pass to FT_Load_Glyph()
947 * @glyph: the glyph index to load
948 * @ink_rect: location to store ink extents of the glyph, or %NULL
949 * @logical_rect: location to store logical extents of the glyph or %NULL
951 * Gets the extents of a single glyph from a font. The extents are in
952 * user space; that is, they are not transformed by any matrix in effect
955 * Long term, this functionality probably belongs in the default
956 * implementation of the get_glyph_extents() virtual function.
957 * The other possibility would be to to make it public in something
958 * like it's current form, and also expose glyph information
959 * caching functionality similar to pango_ft2_font_set_glyph_info().
964 pango_fc_font_get_raw_extents (PangoFcFont *fcfont,
967 PangoRectangle *ink_rect,
968 PangoRectangle *logical_rect)
970 FT_Glyph_Metrics *gm;
973 g_return_if_fail (PANGO_IS_FC_FONT (fcfont));
975 face = PANGO_FC_FONT_LOCK_FACE (fcfont);
976 if (G_UNLIKELY (!face))
978 /* Get generic unknown-glyph extents. */
979 pango_font_get_glyph_extents (NULL, glyph, ink_rect, logical_rect);
983 if (glyph == PANGO_GLYPH_EMPTY)
986 gm = get_per_char (face, load_flags, glyph);
992 ink_rect->x = PANGO_UNITS_26_6 (gm->horiBearingX);
993 ink_rect->width = PANGO_UNITS_26_6 (gm->width);
994 ink_rect->y = -PANGO_UNITS_26_6 (gm->horiBearingY);
995 ink_rect->height = PANGO_UNITS_26_6 (gm->height);
1000 logical_rect->x = 0;
1001 logical_rect->width = PANGO_UNITS_26_6 (gm->horiAdvance);
1002 if (fcfont->is_hinted ||
1003 (face->face_flags & FT_FACE_FLAG_SCALABLE) == 0)
1005 logical_rect->y = - PANGO_UNITS_26_6 (face->size->metrics.ascender);
1006 logical_rect->height = PANGO_UNITS_26_6 (face->size->metrics.ascender - face->size->metrics.descender);
1010 FT_Fixed ascender, descender;
1012 ascender = FT_MulFix (face->ascender, face->size->metrics.y_scale);
1013 descender = FT_MulFix (face->descender, face->size->metrics.y_scale);
1015 logical_rect->y = - PANGO_UNITS_26_6 (ascender);
1016 logical_rect->height = PANGO_UNITS_26_6 (ascender - descender);
1025 ink_rect->width = 0;
1027 ink_rect->height = 0;
1032 logical_rect->x = 0;
1033 logical_rect->width = 0;
1034 logical_rect->y = 0;
1035 logical_rect->height = 0;
1039 PANGO_FC_FONT_UNLOCK_FACE (fcfont);