From 0a0b581425019277569d823ea5bed6af760e5d2c Mon Sep 17 00:00:00 2001 From: handa Date: Wed, 20 Dec 2006 08:02:32 +0000 Subject: [PATCH] Copyright notice fixed. (G_LOG_DOMAIN): Changed to "Pango-M17N-FC". (fontset): New variable. (init_module): Delete local variable fontset. (fini_module): Unref fontset. (m17n_scripts): Add many scripts. (m17n_fc_get_family): New function. (m17n_fc_lookup_fontset): New function. (m17n_fc_free_font_info): New function. (m17n_fc_get_font): New function. (m17n_fc_engine_shape): Fix prototype. (m17n_fc_engine_shape): use m17n_fc_get_font. Fix geometry calculation. (m17n_fc_engine_covers): Use m17n_fc_get_font and m17n_fc_lookup_fontset. --- m17n-fc.c | 276 +++++++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 194 insertions(+), 82 deletions(-) diff --git a/m17n-fc.c b/m17n-fc.c index 0ff05ba..b042bfb 100644 --- a/m17n-fc.c +++ b/m17n-fc.c @@ -1,28 +1,26 @@ /* Pango * m17n-fc.c: Generic shaper using the m17n library for FreeType-based backends - Copyright (C) 2004, 2005 + Copyright (C) 2004, 2005, 2006 National Institute of Advanced Industrial Science and Technology (AIST) - Registration Number H15PRO112 + Registration Number H16PRO276 - This file is part of the m17n library. + This file is part of the pango-m17n library. - The m17n library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public License - as published by the Free Software Foundation; either version 2.1 of - the License, or (at your option) any later version. + The pango-m17n library is free software; you can redistribute it + and/or modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. - The m17n 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 - Lesser General Public License for more details. + The pango-m17n 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with the m17n library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307, USA. */ - -#include + License along with the pango-m17n library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, + MA 02111-1307, USA. */ #include #include @@ -37,7 +35,7 @@ #ifdef G_LOG_DOMAIN #undef G_LOG_DOMAIN #endif -#define G_LOG_DOMAIN "M17N-Pango-FC" +#define G_LOG_DOMAIN "Pango-M17N-FC" /* Control printing of debug information. It is initialized from the environment variable PANGO_M17N_FC_DEBUG. Currently, any positive @@ -47,6 +45,9 @@ static int debug_level; /* Commonly used frame on nulldevice. */ static MFrame *frame; +/* Commonly used "generic" fontset. */ +static MFontset *fontset; + /* Initialize this module. The main task is to open a frame on nulldevice. */ @@ -56,7 +57,6 @@ init_module () const char *envvar = g_getenv ("PANGO_M17N_FC_DEBUG"); MPlist *param; MFace *face; - MFontset *fontset; debug_level = envvar ? atoi (envvar) : 0; @@ -68,7 +68,6 @@ init_module () mplist_put (param, Mface, face); mplist_put (param, Mdevice, Mnil); frame = mframe (param); - m17n_object_unref (fontset); m17n_object_unref (face); m17n_object_unref (param); } @@ -79,6 +78,7 @@ static void fini_module () { m17n_object_unref (frame); + m17n_object_unref (fontset); } /* No extra fields needed for these structures. */ @@ -90,19 +90,34 @@ typedef PangoEngineShapeClass M17NEngineFcClass; static PangoEngineScriptInfo m17n_scripts[] = { { PANGO_SCRIPT_ARABIC, "*" }, + { PANGO_SCRIPT_ARMENIAN, "*" }, { PANGO_SCRIPT_BENGALI, "*" }, + { PANGO_SCRIPT_BOPOMOFO, "*" }, + { PANGO_SCRIPT_CHEROKEE, "*" }, + { PANGO_SCRIPT_COPTIC, "*" }, + { PANGO_SCRIPT_CYRILLIC, "*" }, + { PANGO_SCRIPT_DESERET, "*" }, { PANGO_SCRIPT_DEVANAGARI, "*" }, { PANGO_SCRIPT_ETHIOPIC, "*" }, { PANGO_SCRIPT_GEORGIAN, "*" }, + { PANGO_SCRIPT_GOTHIC, "*" }, + { PANGO_SCRIPT_GREEK, "*" }, { PANGO_SCRIPT_GUJARATI, "*" }, { PANGO_SCRIPT_GURMUKHI, "*" }, + { PANGO_SCRIPT_HAN, "*" }, + { PANGO_SCRIPT_HANGUL, "*" }, { PANGO_SCRIPT_HEBREW, "*" }, + { PANGO_SCRIPT_HIRAGANA, "*" }, { PANGO_SCRIPT_KANNADA, "*" }, + { PANGO_SCRIPT_KATAKANA, "*" }, { PANGO_SCRIPT_KHMER, "*" }, { PANGO_SCRIPT_LAO, "*" }, { PANGO_SCRIPT_MALAYALAM, "*" }, { PANGO_SCRIPT_MYANMAR, "*" }, + { PANGO_SCRIPT_OGHAM, "*" }, + { PANGO_SCRIPT_OLD_ITALIC, "*" }, { PANGO_SCRIPT_ORIYA, "*" }, + { PANGO_SCRIPT_RUNIC, "*" }, { PANGO_SCRIPT_SINHALA, "*" }, { PANGO_SCRIPT_SYRIAC, "*" }, { PANGO_SCRIPT_TAMIL, "*" }, @@ -110,6 +125,31 @@ static PangoEngineScriptInfo m17n_scripts[] = { { PANGO_SCRIPT_THAANA, "*" }, { PANGO_SCRIPT_THAI, "*" }, { PANGO_SCRIPT_TIBETAN, "*" }, + { PANGO_SCRIPT_CANADIAN_ABORIGINAL, "*" }, + { PANGO_SCRIPT_YI, "*" }, + +#ifdef PANGO_SCRIPT_BRAILLE + { PANGO_SCRIPT_BRAILLE, "*" }, + { PANGO_SCRIPT_CYPRIOT, "*" }, + { PANGO_SCRIPT_LIMBU, "*" }, + { PANGO_SCRIPT_OSMANYA, "*" }, + { PANGO_SCRIPT_SHAVIAN, "*" }, + { PANGO_SCRIPT_LINEAR_B, "*" }, + { PANGO_SCRIPT_TAI_LE, "*" }, + { PANGO_SCRIPT_UGARITIC, "*" }, +#endif /* PANGO_SCRIPT_BRAILLE */ + +#ifdef PANGO_SCRIPT_NEW_TAI_LUE + { PANGO_SCRIPT_NEW_TAI_LUE, "*" }, + { PANGO_SCRIPT_BUGINESE, "*" }, + { PANGO_SCRIPT_GLAGOLITIC, "*" }, + { PANGO_SCRIPT_TIFINAGH, "*" }, + { PANGO_SCRIPT_SYLOTI_NAGRI, "*" }, + { PANGO_SCRIPT_OLD_PERSIAN, "*" }, + { PANGO_SCRIPT_KHAROSHTHI, "*" }, +#endif /* PANGO_SCRIPT_NEW_TAI_LUE */ + + { PANGO_SCRIPT_COMMON, "" } }; static PangoEngineInfo script_engines[] = { @@ -121,6 +161,17 @@ static PangoEngineInfo script_engines[] = { } }; +static char * +m17n_fc_get_family (PangoFont *pango_font) +{ + PangoFcFont *pango_fc_font = PANGO_FC_FONT (pango_font); + FcChar8 *family; + + if (FcPatternGetString (pango_fc_font->font_pattern, FC_FAMILY, 0, &family) + == FcResultMatch) + return (char *) family; + return ""; +} /* Convert PANGO_LANGUAGE to m17n-lib's language symbol. If m17n-lib doesn't know about PANGO_LANGUAGE, return Mnil. */ @@ -156,14 +207,106 @@ m17n_fc_get_language (PangoLanguage *pango_language) return language; } + +/* Return a list of FONT-SPECs specified in the current fontset for + displaying SCRIPT in LANGUAGE. Callers must unref the returned + plist. */ + +MPlist * +m17n_fc_lookup_fontset (MSymbol script, MSymbol language) +{ + MPlist *plist = mfontset_lookup (fontset, script, language, Mnil); + + if (mplist_key (plist) == Mnil) + { + /* List up languages that have entries for SCRIPT. */ + MPlist *ll = mfontset_lookup (fontset, script, Mt, Mnil); + + if (! ll) + { + /* No entry for SCRIPT. Return fallback FONT-SPECs. */ + m17n_object_unref (plist); + plist = mfontset_lookup (fontset, Mnil, Mnil, Mnil); + } + else + { + if (mplist_length (ll) == 1) + { + /* If there's just one language, return FONT-SPECs for it. */ + m17n_object_unref (plist); + language = mplist_key (ll); + if (language == Mt) + language = Mnil; + plist = mfontset_lookup (fontset, script, mplist_key (ll), Mnil); + } + else + /* Sumup FONT-SPECs for all languages. */ + for (; mplist_key (ll) != Mnil; ll = mplist_next (ll)) + { + MPlist *pl; + + language = mplist_key (ll); + if (language == Mt) + language = Mnil; + for (pl = mfontset_lookup (fontset, script, language, Mnil); + mplist_key (pl) != Mnil; pl = mplist_next (pl)) + mplist_add (plist, mplist_key (pl), mplist_value (pl)); + } + } + } + return plist; +} + + +typedef struct +{ + PangoFcFont *pango_fc_font; + MFont *font; +} M17NFontInfo; + +static void +m17n_fc_free_font_info (gpointer data) +{ + M17NFontInfo *font_info = data; + + if (font_info->font) + { + mfont_close (font_info->font); + pango_fc_font_unlock_face (font_info->pango_fc_font); + } + g_free (data); +} + +static MFont * +m17n_fc_get_font (PangoFont *pango_font) +{ + GQuark info_id = g_quark_from_string ("m17n-font-info"); + M17NFontInfo *font_info; + + font_info = g_object_get_qdata (G_OBJECT (pango_font), info_id); + if (! font_info) + { + PangoFcFont *pango_fc_font = PANGO_FC_FONT (pango_font); + FT_Face ft_face = pango_fc_font_lock_face (pango_fc_font); + + font_info = g_new (M17NFontInfo, 1); + font_info->pango_fc_font = pango_fc_font; + font_info->font = mfont_encapsulate (frame, Mfreetype, ft_face); + g_object_set_qdata_full (G_OBJECT (pango_font), info_id, font_info, + (GDestroyNotify) m17n_fc_free_font_info); + } + return font_info->font; +} + + /* Shaper function. */ static void m17n_fc_engine_shape (PangoEngineShape *engine, PangoFont *pango_font, const char *text, - gint length, - PangoAnalysis *analysis, + int length, + const PangoAnalysis *analysis, PangoGlyphString *glyphs) { /* Symbols for character property `category'. */ @@ -174,8 +317,6 @@ m17n_fc_engine_shape (PangoEngineShape *engine, MText *mt; MDrawGlyph *m_glyphs; int nchars, nglyphs; - PangoFcFont *fc_font; - char *fontname; MFont *font; int i; const char *p; @@ -215,23 +356,8 @@ m17n_fc_engine_shape (PangoEngineShape *engine, for (i = 0, p = text; i < nchars; i++, p = g_utf8_next_char (p)) offsets[i] = p - text; - fc_font = PANGO_FC_FONT (pango_font); - fontname = (char *) FcNameUnparse (fc_font->font_pattern); - font = mfont_parse_name (fontname, Mfontconfig); - free (fontname); - { - FcChar8 *filename; - int size; - - if (FcPatternGetString (fc_font->font_pattern, FC_FILE, 0, &filename) - == FcResultMatch) - mfont_put_prop (font, Mfontfile, msymbol ((char *) filename)); - size = (int) mfont_get_prop (font, Msize); - if (size) - mfont_put_prop (font, Msize, (void *) (size * 256)); - if (debug_level > 0) - g_debug (" by %s", (char *) filename); - } + font = m17n_fc_get_font (pango_font); + g_return_if_fail (font != NULL); mtext_put_prop (mt, 0, nchars, Mfont, font); if (language != Mnil) @@ -256,9 +382,9 @@ m17n_fc_engine_shape (PangoEngineShape *engine, if (m_glyphs[i].glyph_code >= 0) { g->glyph = m_glyphs[i].glyph_code; - g->geometry.x_offset = m_glyphs[i].x_off * PANGO_SCALE / 256; - g->geometry.y_offset = m_glyphs[i].y_off * PANGO_SCALE / 256; - g->geometry.width = m_glyphs[i].x_advance * PANGO_SCALE / 256; + g->geometry.x_offset = m_glyphs[i].x_off * PANGO_SCALE; + g->geometry.y_offset = m_glyphs[i].y_off * PANGO_SCALE; + g->geometry.width = m_glyphs[i].x_advance * PANGO_SCALE; } else { @@ -269,7 +395,7 @@ m17n_fc_engine_shape (PangoEngineShape *engine, if (category == MZs) { g->glyph = 0; - g->geometry.width = m_glyphs[i].x_advance * PANGO_SCALE / 256; + g->geometry.width = m_glyphs[i].x_advance * PANGO_SCALE; } else if (category == MCf) { @@ -278,7 +404,8 @@ m17n_fc_engine_shape (PangoEngineShape *engine, } else { - g->glyph = pango_fc_font_get_unknown_glyph (fc_font, c); + g->glyph = (pango_fc_font_get_unknown_glyph + (PANGO_FC_FONT (pango_font), c)); pango_font_get_glyph_extents (pango_font, g->glyph, NULL, &logical_rect); g->geometry.width = logical_rect.width; @@ -293,7 +420,6 @@ m17n_fc_engine_shape (PangoEngineShape *engine, } m17n_object_unref (mt); - free (font); } /* Check if PANGO_FONT is suitable for the character WC. */ @@ -309,11 +435,9 @@ m17n_fc_engine_covers (PangoEngineShape *engine, static MSymbol Mlatin, Mcommon, Minherited; PangoCoverage *coverage; PangoCoverageLevel result; - PangoFcFont *fc_font; - char *fontname; - MFont *font; MSymbol script, language; - int check_result; + MPlist *spec_list, *p; + MFont *font; if (! Mlatin) { @@ -335,22 +459,11 @@ m17n_fc_engine_covers (PangoEngineShape *engine, if (result == PANGO_COVERAGE_NONE) { if (debug_level > 0) - { - fc_font = PANGO_FC_FONT (pango_font); - fontname = (char *) FcNameUnparse (fc_font->font_pattern); - font = mfont_parse_name (fontname, Mfontconfig); - g_debug (" %s none", - msymbol_name (mfont_get_prop (font, Mfamily))); - free (fontname); - free (font); - } + g_debug (" %s none", m17n_fc_get_family (pango_font)); return result; } - fc_font = PANGO_FC_FONT (pango_font); - fontname = (char *) FcNameUnparse (fc_font->font_pattern); - font = mfont_parse_name (fontname, Mfontconfig); - + language = m17n_fc_get_language (pango_language); if (wc < 0x100) script = Mlatin; else @@ -359,27 +472,26 @@ m17n_fc_engine_covers (PangoEngineShape *engine, if (script == Mcommon || script == Minherited) script = mchar_get_prop ((int) wc, msymbol ("block")); } - language = m17n_fc_get_language (pango_language); - check_result = mfont_check (frame, NULL, script, language, font); + font = m17n_fc_get_font (pango_font); + spec_list = m17n_fc_lookup_fontset (script, language); + + result = PANGO_COVERAGE_NONE; + for (p = spec_list; mplist_key (p) != Mnil; p = mplist_next (p)) + if (mfont_match_p (font, mplist_value (p))) + { + result = PANGO_COVERAGE_EXACT; + break; + } + m17n_object_unref (spec_list); if (debug_level > 0) - { - char *result_text = (check_result == 2 ? "exact" - : check_result == 1 ? "approximate" - : "fallback"); - - g_debug (" (%s,%s): %s %s", - (script ? msymbol_name (script) : ""), - (language ? msymbol_name (language) : ""), - msymbol_name (mfont_get_prop (font, Mfamily)), - result_text); - } - - free (fontname); - free (font); - return (check_result == 2 ? PANGO_COVERAGE_EXACT - : check_result == 1 ? PANGO_COVERAGE_APPROXIMATE - : PANGO_COVERAGE_FALLBACK); + g_debug (" (%s,%s): %s %s", + (script ? msymbol_name (script) : ""), + (language ? msymbol_name (language) : ""), + m17n_fc_get_family (pango_font), + result == PANGO_COVERAGE_EXACT ? "exact" : "none"); + + return result; } static void -- 1.7.10.4