#include <string.h>
#include <ctype.h>
+#include "config.h"
#include "m17n-gui.h"
#include "m17n-misc.h"
#include "internal.h"
}
}
-\f
-
-/* Internal API */
-
-int
-mfont__fontset_init ()
-{
- Mfontset = msymbol ("fontset");
- Mfontset->managing_key = 1;
- fontset_list = mplist ();
- default_fontset = mfontset ("default");
- if (! default_fontset->mdb)
- {
- MFont font;
-
- MFONT_INIT (&font);
- mfont_put_prop (&font, Mregistry, msymbol ("iso8859-1"));
- mfontset_modify_entry (default_fontset, Mnil, Mnil, Mnil,
- &font, Mnil, 1);
- mfont_put_prop (&font, Mregistry, msymbol ("iso10646-1"));
- mfontset_modify_entry (default_fontset, Mnil, Mnil, Mnil,
- &font, Mnil, 1);
- }
- return 0;
-}
-
-
-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;
-}
-
-
-MRealizedFontset *
-mfont__realize_fontset (MFrame *frame, MFontset *fontset, MFace *face)
+static void
+realize_fontset_elements (MFrame *frame, MRealizedFontset *realized,
+ MFontset *fontset, MFont *request)
{
- MRealizedFontset *realized;
- MFont request;
MPlist *per_script, *per_lang, *per_charset, *font_group;
- MPlist *plist, *pl, *p;
-
- if (fontset->mdb)
- load_fontset_contents (fontset);
-
- mfont__set_spec_from_face (&request, face);
- if (request.property[MFONT_SIZE] <= 0)
- {
- mdebug_hook ();
- request.property[MFONT_SIZE] = 120;
- }
- MPLIST_DO (p, frame->realized_fontset_list)
- {
- realized = (MRealizedFontset *) MPLIST_VAL (p);
- if (fontset->name == MPLIST_KEY (p)
- && ! memcmp (&request, &realized->spec, sizeof (request)))
- return realized;
- }
+ MPlist *plist, *pl;
- MSTRUCT_MALLOC (realized, MERROR_FONTSET);
realized->fontset = fontset;
realized->tick = fontset->tick;
- realized->spec = request;
+ realized->spec = *request;
realized->frame = frame;
realized->per_script = per_script = mplist ();
MPLIST_DO (plist, fontset->per_script)
realized->fallback = mplist ();
mplist_add (realized->fallback, Mplist, fontset->fallback);
- mplist_add (frame->realized_fontset_list, fontset->name, realized);
- return realized;
}
-
-void
-mfont__free_realized_fontset (MRealizedFontset *realized)
+static void
+free_realized_fontset_elements (MRealizedFontset *realized)
{
MPlist *plist, *pl, *p;
MRealizedFont *rfont;
free (rfont);
M17N_OBJECT_UNREF (realized->fallback);
}
+}
+
+static void
+update_fontset_elements (MRealizedFontset *realized)
+{
+ free_realized_fontset_elements (realized);
+ realize_fontset_elements (realized->frame, realized, realized->fontset,
+ &realized->spec);
+}
+
+
+\f
+
+/* Internal API */
+
+int
+mfont__fontset_init ()
+{
+ Mfontset = msymbol ("fontset");
+ Mfontset->managing_key = 1;
+ fontset_list = mplist ();
+ default_fontset = mfontset ("default");
+ if (! default_fontset->mdb)
+ {
+ MFont font;
+
+ MFONT_INIT (&font);
+ mfont_put_prop (&font, Mregistry, msymbol ("iso8859-1"));
+ mfontset_modify_entry (default_fontset, Mnil, Mnil, Mnil,
+ &font, Mnil, 1);
+ mfont_put_prop (&font, Mregistry, msymbol ("iso10646-1"));
+ mfontset_modify_entry (default_fontset, Mnil, Mnil, Mnil,
+ &font, Mnil, 1);
+ }
+ return 0;
+}
+
+
+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;
+}
+
+MRealizedFontset *
+mfont__realize_fontset (MFrame *frame, MFontset *fontset, MFace *face)
+{
+ MRealizedFontset *realized;
+ MFont request;
+ MPlist *plist;
+
+ if (fontset->mdb)
+ load_fontset_contents (fontset);
+
+ mfont__set_spec_from_face (&request, face);
+ if (request.property[MFONT_SIZE] <= 0)
+ {
+ mdebug_hook ();
+ request.property[MFONT_SIZE] = 120;
+ }
+ MPLIST_DO (plist, frame->realized_fontset_list)
+ {
+ realized = (MRealizedFontset *) MPLIST_VAL (plist);
+ if (fontset->name == MPLIST_KEY (plist)
+ && ! memcmp (&request, &realized->spec, sizeof (request)))
+ return realized;
+ }
+
+ MSTRUCT_MALLOC (realized, MERROR_FONTSET);
+ realize_fontset_elements (frame, realized, fontset, &request);
+ mplist_add (frame->realized_fontset_list, fontset->name, realized);
+ return realized;
+}
+
+
+void
+mfont__free_realized_fontset (MRealizedFontset *realized)
+{
+ free_realized_fontset_elements (realized);
free (realized);
}
{
MFrame *frame = realized->frame;
MCharset *preferred_charset = (charset == Mnil ? NULL : MCHARSET (charset));
- MPlist *per_charset, *per_script, *per_lang, *font_group;
+ MPlist *per_charset, *per_script, *per_lang;
MPlist *font_groups[256], *plist;
int n_font_group = 0;
- MRealizedFont *first = NULL, *rfont;
- int first_len;
+ MRealizedFont *rfont;
int i;
+ if (realized->tick != realized->fontset->tick)
+ update_fontset_elements (realized);
+
if (preferred_charset
&& (per_charset = mplist_get (realized->per_charset, charset)) != NULL)
font_groups[n_font_group++] = per_charset;
&& ((per_script = mplist_find_by_key (realized->per_script, script))
!= NULL))
{
- /* The first loop is for matching language (if any), and the second
- loop is for non-matching languages. */
+ /* We prefer font groups in this order:
+ (1) group matching LANGUAGE
+ (2) group for generic LANGUAGE
+ (3) group non-matching LANGUAGE */
if (language == Mnil)
language = Mt;
- for (i = 0; i < 2; i++)
+ per_lang = mplist_find_by_key (MPLIST_PLIST (per_script), language);
+ if (per_lang)
+ {
+ font_groups[n_font_group++] = MPLIST_PLIST (per_lang);
+ if (language == Mt)
+ {
+ MPLIST_DO (per_lang, MPLIST_PLIST (per_script))
+ if (MPLIST_KEY (per_lang) != language)
+ font_groups[n_font_group++] = MPLIST_PLIST (per_lang);
+ }
+ }
+ if (language != Mt)
{
- MPLIST_DO (per_lang, MPLIST_PLIST (per_script))
- if ((MPLIST_KEY (per_lang) == language) != i)
- font_groups[n_font_group++] = MPLIST_PLIST (per_lang);
+ plist = mplist_get (MPLIST_PLIST (per_script), Mt);
+ if (plist)
+ font_groups[n_font_group++] = plist;
}
+ MPLIST_DO (per_lang, MPLIST_PLIST (per_script))
+ if (MPLIST_KEY (per_lang) != language
+ && MPLIST_KEY (per_lang) != Mt)
+ font_groups[n_font_group++] = MPLIST_PLIST (per_lang);
}
font_groups[n_font_group++] = realized->fallback;
rfont = (MRealizedFont *) MPLIST_VAL (plist);
if (rfont->status < 0)
continue;
- g->code = mfont__encode_char (rfont, g->c);
- if (g->code != MCHAR_INVALID_CODE)
- break;
- }
- if (MPLIST_TAIL_P (plist))
- continue;
- for (j = 1; j < *num; j++)
- {
- g[j].code = mfont__encode_char (rfont, g[j].c);
- if (g[j].code == MCHAR_INVALID_CODE)
- break;
+ /* Check if this font can display all glyphs. */
+ for (j = 0; j < *num; j++)
+ {
+ g[j].code = mfont__encode_char (rfont,
+ g[j].type == GLYPH_CHAR ? g[j].c
+ : ' ');
+ if (g[j].code == MCHAR_INVALID_CODE)
+ break;
+ }
+ if (j == *num)
+ {
+ if (rfont->status > 0
+ || mfont__open (rfont) == 0)
+ /* We found a font that can display all glyphs. */
+ break;
+ }
}
- if (! first)
- first = rfont, first_len = j;
- if (j == *num)
- /* We found a font that can display all requested
- characters. */
+ if (! MPLIST_TAIL_P (plist))
break;
+ }
+
+ if (i < n_font_group)
+ return rfont;
- MPLIST_DO (plist, MPLIST_NEXT (plist))
+ /* We couldn't find a font that can display all glyphs. Find one
+ that can display at least the first glyph. */
+ for (i = 0; i < n_font_group; i++)
+ {
+ MPLIST_DO (plist, font_groups[i])
{
rfont = (MRealizedFont *) MPLIST_VAL (plist);
if (rfont->status < 0)
continue;
- for (j = 0; j < *num; j++)
+ g->code = mfont__encode_char (rfont,
+ g->type == GLYPH_CHAR ? g->c : ' ');
+ if (g->code != MCHAR_INVALID_CODE)
{
- g[j].code = mfont__encode_char (rfont, g[j].c);
- if (g[j].code == MCHAR_INVALID_CODE)
+ if (rfont->status > 0
+ || mfont__open (rfont) == 0)
break;
}
- if (j == *num)
- break;
}
if (! MPLIST_TAIL_P (plist))
break;
}
-
- if (i == n_font_group)
- {
- if (! first)
- return NULL;
- rfont = first, *num = first_len;
- for (i = 0; i < *num; i++)
- g[i].code = mfont__encode_char (rfont, g[i].c);
- }
- if (! rfont->status
- && mfont__open (rfont) < 0)
- {
- MPLIST_VAL (font_group) = NULL;
- return NULL;
- }
- return rfont;
+ return (i < n_font_group ? rfont : NULL);
}
/*** @} */
MFontset *fontset;
if (! name)
- return default_fontset;
- sym = msymbol (name);
- fontset = mplist_get (fontset_list, sym);
- if (fontset)
- return fontset;
- M17N_OBJECT (fontset, free_fontset, MERROR_FONTSET);
- fontset->name = sym;
- fontset->mdb = mdatabase_find (Mfontset, sym, Mnil, Mnil);
- if (! fontset->mdb)
+ fontset = default_fontset;
+ else
{
- fontset->per_script = mplist ();
- fontset->per_charset = mplist ();
- fontset->fallback = mplist ();
+ sym = msymbol (name);
+ fontset = mplist_get (fontset_list, sym);
+ if (! fontset)
+ {
+ M17N_OBJECT (fontset, free_fontset, MERROR_FONTSET);
+ fontset->name = sym;
+ fontset->mdb = mdatabase_find (Mfontset, sym, Mnil, Mnil);
+ if (! fontset->mdb)
+ {
+ fontset->per_script = mplist ();
+ fontset->per_charset = mplist ();
+ fontset->fallback = mplist ();
+ }
+ mplist_put (fontset_list, sym, fontset);
+ }
}
- mplist_put (fontset_list, sym, fontset);
M17N_OBJECT_REF (fontset);
return fontset;
}
if (fontset->mdb)
load_fontset_contents (fontset);
- MPLIST_DO (pl, fontset->font_spec_list)
- {
- if (! memcmp (MPLIST_VAL (pl), spec, sizeof (MFont)))
- {
- font = MPLIST_VAL (pl);
- break;
- }
- }
+ if (! fontset->font_spec_list)
+ fontset->font_spec_list = mplist ();
+ else
+ MPLIST_DO (pl, fontset->font_spec_list)
+ {
+ if (! memcmp (MPLIST_VAL (pl), spec, sizeof (MFont)))
+ {
+ font = MPLIST_VAL (pl);
+ break;
+ }
+ }
if (! font)
{
font = mfont ();
}
}
+ fontset->tick++;
return 0;
}
+/*=*/
+
+/***en
+ @brief Lookup a fontset.
+
+ The mfontset_lookup () function lookups $FONTSET and returns a
+ plist that describes the contents of $FONTSET corresponding to the
+ specified script, language, and charset.
+
+ If $SCRIPT is @c Mt, keys of the returned plist are script name
+ symbols for which some fonts are specified and values are NULL.
+
+ If $SCIRPT is a script symbol, the returned plist is decided by
+ $LANGUAGE.
+
+ If $LANGUAGE is @c Mt, keys of the plist are language name symbols
+ for which some fonts are specified and values are NULL. A key may
+ be @c Mt which means some fallback fonts are specified for the
+ script.
+
+ If $LANGUAGE is a language name symbol, the plist is a @c
+ FONT-GROUP for the specified script and langauge.
+
+ If $LANGAUGE is @c Mt, the plist is fallback @c FONT-GROUP for the
+ script.
+
+ If $SCRIPT is @c Mnil, the returned plist is decided as below.
+
+ If $CHARSET is @c Mt, keys of the returned plist are charset name
+ symbols for which some fonts are specified and values are NULL.
+
+ If $CHARSET is a charset symbol, the plist is a @c FONT-GROUP for
+ the charset.
+
+ If $CHARSET is @c Mnil, the plist is a fallback @c FONT-GROUP.
+
+ @c FONT-GROUP is a plist whose keys are FLT name symbols (@c Mt if
+ no FLT is associated with the font) and values are pointers to
+ #MFont.
+
+ @return
+ It returns a plist describing the contents of a fontset. The
+ plist should be freed by m17n_object_unref (). */
+
+MPlist *
+mfontset_lookup (MFontset *fontset,
+ MSymbol script, MSymbol language, MSymbol charset)
+{
+ MPlist *plist = mplist (), *pl, *p;
+
+ if (fontset->mdb)
+ load_fontset_contents (fontset);
+ if (script == Mt)
+ {
+ if (! fontset->per_script)
+ return plist;
+ p = plist;
+ MPLIST_DO (pl, fontset->per_script)
+ p = mplist_add (p, MPLIST_KEY (pl), NULL);
+ return plist;
+ }
+ if (script != Mnil)
+ {
+ if (! fontset->per_script)
+ return plist;
+ pl = mplist_get (fontset->per_script, script);
+ if (! pl)
+ return plist;
+ if (language == Mt)
+ {
+ p = plist;
+ MPLIST_DO (pl, pl)
+ p = mplist_add (p, MPLIST_KEY (pl), NULL);
+ return plist;
+ }
+ if (language == Mnil)
+ language = Mt;
+ pl = mplist_get (pl, language);
+ }
+ else if (charset != Mnil)
+ {
+ if (! fontset->per_charset)
+ return plist;
+ if (charset == Mt)
+ {
+ p = plist;
+ MPLIST_DO (pl, fontset->per_charset)
+ p = mplist_add (p, MPLIST_KEY (pl), NULL);
+ return plist;
+ }
+ pl = mplist_get (fontset->per_charset, charset);
+ }
+ else
+ pl = fontset->fallback;
+ if (! pl)
+ return plist;
+ return mplist_copy (pl);
+}
+
+
/*** @} */
/*** @addtogroup m17nDebug */