/* fontset.c -- fontset module.
- Copyright (C) 2003, 2004
+ Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
National Institute of Advanced Industrial Science and Technology (AIST)
Registration Number H15PRO112
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
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
02111-1307, USA. */
/***en
#include "font.h"
#include "fontset.h"
+static int mdebug_flag = MDEBUG_FONTSET;
+
+static M17NObjectArray fontset_table;
+
struct MFontset
{
M17NObject control;
if (! plist)
mdebug_hook ();
mplist_pop (plist);
+ if (MPLIST_TAIL_P (fontset_list))
+ {
+ M17N_OBJECT_UNREF (fontset_list);
+ fontset_list = NULL;
+ }
+ M17N_OBJECT_UNREGISTER (fontset_table, fontset);
free (object);
}
{
MFontset *fontset = realized->fontset;
MPlist *per_script, *per_charset, *font_group;
- MPlist *plist, *pl, *p;
+ MPlist *plist, *p;
realized->per_script = per_script = mplist ();
/* The actual elements of per_script are realized on demand. */
#if 0
MPLIST_DO (plist, fontset->per_script)
{
+ MPlist *pl;
+
per_lang = mplist ();
per_script = mplist_add (per_script, MPLIST_KEY (plist), per_lang);
MPLIST_DO (pl, MPLIST_PLIST (plist))
#endif
realized->per_charset = per_charset = mplist ();
- MPLIST_DO (pl, fontset->per_charset)
+ MPLIST_DO (plist, fontset->per_charset)
{
font_group = mplist ();
per_charset = mplist_add (per_charset, MPLIST_KEY (plist), font_group);
- MPLIST_DO (p, MPLIST_PLIST (pl))
+ MPLIST_DO (p, MPLIST_PLIST (plist))
font_group = mplist_add (font_group, MPLIST_KEY (p), MPLIST_VAL (p));
}
realized->fallback = font_group = mplist ();
font_group = mplist_add (font_group, MPLIST_KEY (p), MPLIST_VAL (p));
}
+
+/* Return a plist of fonts for SCRIPT in FONTSET. The returned list
+ is acutally a plist of languages vs font groups (which is a plist).
+ If SCRIPT is nil, return a plist of fallback fonts. If FONTSET
+ doesn't record any fonts for SCRIPT, generate a proper font spec
+ lists for X backend and FreeType backend. */
+
MPlist *
get_per_script (MFontset *fontset, MSymbol script)
{
int
mfont__fontset_init ()
{
+ M17N_OBJECT_ADD_ARRAY (fontset_table, "Fontset");
+
Mfontset = msymbol ("fontset");
Mfontset->managing_key = 1;
fontset_list = mplist ();
void
mfont__fontset_fini ()
{
- while (! MPLIST_TAIL_P (fontset_list))
- free_fontset ((MFontset *) MPLIST_VAL (fontset_list));
- M17N_OBJECT_UNREF (fontset_list);
- fontset_list = NULL;
+ M17N_OBJECT_UNREF (default_fontset);
+ default_fontset = NULL;
}
if (fontset->mdb)
load_fontset_contents (fontset);
+ MFONT_INIT (&request);
mfont__set_spec_from_face (&request, face);
if (request.size <= 0)
{
MSTRUCT_CALLOC (realized, MERROR_FONTSET);
realized->fontset = fontset;
+ M17N_OBJECT_REF (fontset);
realized->tick = fontset->tick;
if (spec)
{
mfont__free_realized_fontset (MRealizedFontset *realized)
{
free_realized_fontset_elements (realized);
+ M17N_OBJECT_UNREF (realized->fontset);
if (realized->spec)
free (realized->spec);
free (realized);
/* Check if this font can display all glyphs. */
for (j = 0; j < *num; j++)
{
- int c = g[j].type == GLYPH_CHAR ? g[j].c : ' ';
+ int c = g[j].type == GLYPH_CHAR ? g[j].g.c : ' ';
+ MFLT *flt;
+ MCharTable *coverage;
+
if (layouter != Mt
- ? mfont__flt_encode_char (layouter, c) == MCHAR_INVALID_CODE
+ ? ((flt = mflt_get (layouter))
+ ? (coverage = mflt_coverage (flt),
+ ! mchartable_lookup (coverage, c))
+ : 0)
: ! mfont__has_char (frame, font, &font_list->object, c))
break;
}
continue;
if (j == *num || !all)
{
+ MCharTable *coverage = NULL;
+
/* We found a font that can display the requested range of
glyphs. */
if (font->type == MFONT_TYPE_REALIZED)
font_list->fonts[i].font = (MFont *) rfont;
}
rfont->layouter = layouter == Mt ? Mnil : layouter;
+ if (rfont->layouter)
+ {
+ MFLT *flt = mflt_get (rfont->layouter);
+
+ if (flt)
+ coverage = mflt_coverage (flt);
+ }
*num = j;
for (j = 0; j < *num; j++)
{
- int c = g[j].type == GLYPH_CHAR ? g[j].c : ' ';
+ int c = g[j].type == GLYPH_CHAR ? g[j].g.c : ' ';
- g[j].code = (rfont->layouter
- ? mfont__flt_encode_char (rfont->layouter, c)
- : mfont__encode_char (frame, (MFont *) rfont,
- &font_list->object, c));
+ g[j].g.code = (coverage
+ ? (unsigned ) mchartable_lookup (coverage, c)
+ : mfont__encode_char (frame, (MFont *) rfont,
+ &font_list->object, c));
}
return rfont;
}
font = MPLIST_VAL (plist);
if (font->type == MFONT_TYPE_SPEC)
{
+ /* We have not yet made this entry a MFontList. */
if (realized->spec)
{
MFont this = *font;
font_list = mfont__list (frame, font, request, size);
if (! font_list)
{
+ /* As there's no font matching this spec, remove this
+ element from the font group. */
mplist_pop (plist);
continue;
}
MPlist *plist;
MRealizedFont *rfont = NULL;
+ if (MDEBUG_FLAG ())
+ {
+ int i;
+
+ MDEBUG_PRINT1 (" [FONTSET] fontset looking up for %s:",
+ script ? script->name : "none");
+ for (i = 0; i < *num; i++)
+ MDEBUG_PRINT1 (" U+%04X", g[i].g.c);
+ MDEBUG_PRINT ("\n");
+ }
+
if (realized->tick != realized->fontset->tick)
update_fontset_elements (realized);
&& (per_charset = mplist_get (realized->per_charset, charset)) != NULL
&& (rfont = try_font_group (realized, &realized->request, per_charset,
g, num, size)))
- return rfont;
+ goto done;
if (script != Mnil)
{
MFont request = realized->request;
if (script != Mlatin)
- /* These are not appropriate for non-Latin scripts. */
- request.property[MFONT_FOUNDRY]
- = request.property[MFONT_FAMILY]
- = request.property[MFONT_REGISTRY] = 0;
+ /* This is not appropriate for non-Latin scripts. */
+ request.property[MFONT_REGISTRY] = 0;
per_script = mplist_get (realized->per_script, script);
if (! per_script)
{
per_script = mplist_copy (get_per_script (realized->fontset, script));
+ /* PER_SCRIPT ::= (LANGUAGE:(LAYOUTER:FONT-SPEC ...) ...) */
MPLIST_DO (plist, per_script)
MPLIST_VAL (plist) = mplist_copy (MPLIST_VAL (plist));
mplist_add (realized->per_script, script, per_script);
if ((per_lang = mplist_get (per_script, language))
&& (rfont = try_font_group (realized, &request, per_lang,
g, num, size)))
- return rfont;
+ goto done;
+ if (per_lang && *num > 1)
+ *num = 1;
if (language == Mt)
{
/* Try the above (3) */
&& (rfont = try_font_group (realized, &request,
MPLIST_PLIST (plist),
g, num, size)))
- return rfont;
+ goto done;
}
else
{
if ((per_lang = mplist_get (per_script, Mt))
&& (rfont = try_font_group (realized, &request, per_lang,
g, num, size)))
- return rfont;
+ goto done;
+ if (per_lang && *num > 1)
+ *num = 1;
/* Then try the above (3) */
MPLIST_DO (plist, per_script)
if (MPLIST_KEY (plist) != language
&& (rfont = try_font_group (realized, &request,
MPLIST_PLIST (plist),
g, num, size)))
- return rfont;
+ goto done;
}
if (ignore_fallback)
- return NULL;
+ goto done;
}
if (language != Mnil)
if ((per_lang = mplist_get (MPLIST_PLIST (plist), language))
&& (rfont = try_font_group (realized, &request, per_lang,
g, num, size)))
- return rfont;
+ goto done;
}
/* Try fallback fonts. */
- if ((rfont = try_font_group (realized, &realized->request,
- realized->fallback, g, num, size)))
- return rfont;
+ rfont = try_font_group (realized, &realized->request,
+ realized->fallback, g, num, size);
+ done:
+ if (MDEBUG_FLAG ())
+ {
+ if (rfont)
+ {
+ MSymbol family = mfont_get_prop (rfont->font, Mfamily);
+ MDEBUG_PRINT1 (" [FONTSET] found %s\n", family->name);
+ }
+ else
+ MDEBUG_PRINT (" [FONTSET] not found\n");
+ }
+
+ return rfont;
+}
+
+MRealizedFont *
+get_font_from_group (MFrame *frame, MPlist *plist, MFont *font)
+{
+ MRealizedFont *rfont;
+ MPLIST_DO (plist, plist)
+ {
+ MFont spec = *(MFont *) MPLIST_VAL (plist);
+ if (mfont__merge (&spec, font, 1) < 0)
+ continue;
+ if (font->type == MFONT_TYPE_SPEC)
+ rfont = (MRealizedFont *) mfont_find (frame, &spec, NULL, 0);
+ else if (font->type == MFONT_TYPE_OBJECT)
+ rfont = mfont__open (frame, font, &spec);
+ else
+ rfont = (MRealizedFont *) font;
+ if (rfont
+ && (spec.capability == Mnil
+ || mfont__check_capability (rfont, spec.capability) == 0))
+ {
+ rfont->layouter
+ = MPLIST_KEY (plist) == Mt ? Mnil : MPLIST_KEY (plist);
+ return rfont;
+ }
+ }
return NULL;
+}
+
+MRealizedFont *
+mfontset__get_font (MFrame *frame, MFontset *fontset,
+ MSymbol script, MSymbol language, MFont *font,
+ int *best)
+{
+ MPlist *per_script, *per_lang;
+ MRealizedFont *rfont;
+
+ if (best)
+ *best = 0;
+
+ if (language == Mnil)
+ language = Mt;
- /* At last try all fonts. */
- MPLIST_DO (per_script, realized->per_script)
+ if (script != Mnil)
{
- MPLIST_DO (per_lang, MPLIST_PLIST (per_script))
- if ((rfont = try_font_group (realized, &realized->request,
- MPLIST_PLIST (per_lang), g, num, size)))
+ per_script = get_per_script (fontset, script);
+ if ((per_lang = mplist_get (per_script, language))
+ && (rfont = get_font_from_group (frame, per_lang, font)))
+ {
+ if (best)
+ *best = 1;
return rfont;
+ }
+ if (best)
+ *best = per_lang ? 0 : 1;
+ if (language == Mt)
+ {
+ MPLIST_DO (per_script, per_script)
+ if (MPLIST_KEY (per_script) != language
+ && (rfont = get_font_from_group (frame,
+ MPLIST_PLIST (per_script),
+ font)))
+ return rfont;
+ }
+ else
+ {
+ if ((per_lang = mplist_get (per_script, Mt))
+ && (rfont = get_font_from_group (frame, per_lang, font)))
+ return rfont;
+ if (best)
+ *best = 0;
+ MPLIST_DO (per_script, per_script)
+ if (MPLIST_KEY (per_script) != language
+ && MPLIST_KEY (per_script) != Mt
+ && (rfont = get_font_from_group (frame,
+ MPLIST_PLIST (per_script),
+ font)))
+ return rfont;
+ }
}
- MPLIST_DO (per_charset, realized->per_charset)
- if ((rfont = try_font_group (realized, &realized->request,
- MPLIST_PLIST (per_charset), g, num, size)))
- return rfont;
+ if (language != Mt)
+ MPLIST_DO (per_script, fontset->per_script)
+ {
+ if ((per_lang = mplist_get (MPLIST_PLIST (per_script), language))
+ && (rfont = get_font_from_group (frame, per_lang, font)))
+ {
+ if (best)
+ *best = 1;
+ return rfont;
+ }
+ }
+
+ if (best)
+ *best = 0;
+ if ((rfont = get_font_from_group (frame, fontset->fallback, font)))
+ return rfont;
return NULL;
}
+
/*** @} */
#endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
MFontset *fontset;
if (! name)
- fontset = default_fontset;
+ {
+ fontset = default_fontset;
+ M17N_OBJECT_REF (fontset);
+ }
else
{
sym = msymbol (name);
fontset = mplist_get (fontset_list, sym);
- if (! fontset)
+ if (fontset)
+ M17N_OBJECT_REF (fontset);
+ else
{
M17N_OBJECT (fontset, free_fontset, MERROR_FONTSET);
+ M17N_OBJECT_REGISTER (fontset_table, fontset);
fontset->name = sym;
fontset->mdb = mdatabase_find (Mfontset, sym, Mnil, Mnil);
if (! fontset->mdb)
mplist_put (fontset_list, sym, fontset);
}
}
- M17N_OBJECT_REF (fontset);
return fontset;
}
if (copy)
return NULL;
M17N_OBJECT (copy, free_fontset, MERROR_FONTSET);
+ M17N_OBJECT_REGISTER (fontset_table, copy);
copy->name = sym;
if (fontset->mdb)
}
mplist_put (fontset_list, sym, copy);
- M17N_OBJECT_REF (copy);
return copy;
}
are removed from the group.
If $LAYOUTER_NAME is not @c Mnil, it must be a symbol representing
- a @ref flt (font layout table). In that case, if $FONT is
+ a @ref mdbFLT (font layout table). In that case, if $FONT is
selected for drawing an M-text, that font layout table is used to
generate a glyph code sequence from a character sequence.
¤¬Éé¤Ê¤é¤Ð¡¢ºÇÄã¤ÎÍ¥ÀèÅÙ¤ò»ý¤Ä¡£$HOW ¤¬ 0 ¤Ê¤é¤Ð¡¢$FONT
¤Ï´ØÏ¢ÉÕ¤±¤é¤ì¤¿¤â¤Î¤ËÂФ¹¤ëÍ£°ì¤ÎÍøÍѲÄǽ¤Ê¥Õ¥©¥ó¥È¤È¤Ê¤ê¡¢Â¾¤Î¥Õ¥©¥ó¥È¤Ï¥°¥ë¡¼¥×¤«¤é¼è¤ê½ü¤«¤ì¤ë¡£
- $LAYOUTER_NAME ¤Ï @c Mnil ¤Ç¤¢¤ë¤«¡¢@ref flt
+ $LAYOUTER_NAME ¤Ï @c Mnil ¤Ç¤¢¤ë¤«¡¢@ref mdbFLT
¡Ê¥Õ¥©¥ó¥È¥ì¥¤¥¢¥¦¥È¥Æ¡¼¥Ö¥ë¡Ë¤ò¼¨¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£¥·¥ó¥Ü¥ë¤Ç¤¢¤ì¤Ð¡¢$FONT ¤òÍѤ¤¤Æ
M-text ¤òɽ¼¨¤¹¤ëºÝ¤Ë¤Ï¡¢¤½¤Î¥Õ¥©¥ó¥È¥ì¥¤¥¢¥¦¥È¥Æ¡¼¥Ö¥ë¤ò»È¤Ã¤Æʸ»úÎ󤫤饰¥ê¥Õ¥³¡¼¥ÉÎó¤òÀ¸À®¤¹¤ë¡£