/* 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 <config.h>
+ 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 <string.h>
#include <stdlib.h>
#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
/* 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. */
const char *envvar = g_getenv ("PANGO_M17N_FC_DEBUG");
MPlist *param;
MFace *face;
- MFontset *fontset;
debug_level = envvar ? atoi (envvar) : 0;
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);
}
fini_module ()
{
m17n_object_unref (frame);
+ m17n_object_unref (fontset);
}
/* No extra fields needed for these structures. */
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, "*" },
{ 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[] = {
}
};
+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. */
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'. */
MText *mt;
MDrawGlyph *m_glyphs;
int nchars, nglyphs;
- PangoFcFont *fc_font;
- char *fontname;
MFont *font;
int i;
const char *p;
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)
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
{
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)
{
}
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;
}
m17n_object_unref (mt);
- free (font);
}
/* Check if PANGO_FONT is suitable for the character WC. */
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)
{
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
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