X-Git-Url: http://git.chise.org/gitweb/?a=blobdiff_plain;f=src%2Ffontset.c;h=a0eecbded8bf5fc76bdc15abe27a0c591c03eeb7;hb=ebb9aa922a01d5052acee38d06d4b175086ba725;hp=af938ae53cbd0215a2d728d0e00da36a1cbad523;hpb=1359a5c46aaaa266d1d6a0f30f2478a18e439b5c;p=m17n%2Fm17n-lib.git diff --git a/src/fontset.c b/src/fontset.c index af938ae..a0eecbd 100644 --- a/src/fontset.c +++ b/src/fontset.c @@ -28,21 +28,28 @@ M-text, a fontset provides rules to select a font for each character in the M-text according to the following information. - - The script character property of a character. - - The language text property of a character. - - The charset text property of a character. + @li The script character property of a character. + @li The language text property of a character. + @li The charset text property of a character. The documentation of mdraw_text () describes how that information is used. */ -/***ja - @addtogroup m17nFontset - @brief ¥Õ¥©¥ó¥È¥»¥Ã¥È¤Ï°ìÄê¤Î¥¹¥¿¥¤¥ë¤ò¶¦Í­¤¹¤ë¥Õ¥©¥ó¥È¤Î½¸¹ç¤Ç¤¢¤ë +/***ja @addtogroup m17nFontset + + @brief ¥Õ¥©¥ó¥È¥»¥Ã¥È¤Ïʸ»ú¤«¤é¥Õ¥©¥ó¥È¤Ø¤ÎÂбþÉÕ¤±¤ò¹Ô¤¦¥ª¥Ö¥¸¥§¥¯¥È¤Ç¤¢¤ë. + + @e ¥Õ¥©¥ó¥È¥»¥Ã¥È ¤Ï @c MFontset ·¿¤Î¥ª¥Ö¥¸¥§¥¯¥È¤Ç¤¢¤ë¡£M-text + ¤Îɽ¼¨¤ÎºÝ¡¢¥Õ¥©¥ó¥È¥»¥Ã¥È¤Ï°Ê²¼¤Î¾ðÊó¤òÍѤ¤¤Æ M-text + Ãæ¤Î¸Ä¡¹¤Îʸ»ú¤Ë¤É¤Î¥Õ¥©¥ó¥È¤òÍѤ¤¤ë¤«·è¤á¤ëµ¬Â§¤òÍ¿¤¨¤ë¡£ + + @li ʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "¥¹¥¯¥ê¥×¥È" + @li ʸ»ú¤Î¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£ "¸À¸ì" + @li ʸ»ú¤Î¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£ "ʸ»ú¥»¥Ã¥È" + + ¤³¤ì¤é¤Î¾ðÊ󤬤ɤΤ褦¤ËÍѤ¤¤é¤ì¤ë¤«¤Ï mdraw_text () ¤ÎÀâÌÀ¤ò»²¾È¤Î¤³¤È¡£ - @e ¥Õ¥©¥ó¥È¥»¥Ã¥È ¤Ï @c MFontset ·¿¤Î¥ª¥Ö¥¸¥§¥¯¥È¤Ç¤¢¤ê¡¢Â¿¸À¸ìʸ - ½ñ¤Îɽ¼¨¤ÎºÝ¡¢¸«¤«¤±¤Î»÷¤¿¥Õ¥©¥ó¥È¤ò½¸¤á¤Æ°ì´Ó¤·¤Æ¼è¤ê°·¤¦¤¿¤á¤Ë»È - ¤ï¤ì¤ë¡£¥Õ¥©¥ó¥È¥»¥Ã¥È¤Ï¤Þ¤¿¡¢¸À¸ì¡¢Ê¸»ú¥»¥Ã¥È¡¢Ê¸»ú¤¬Í¿¤¨¤é¤ì¤¿¤È - ¤­¤ËŬÀڤʥե©¥ó¥È¤òÁªÂò¤¹¤ë¤¿¤á¤Î¾ðÊó¤âÊÝ»ý¤·¤Æ¤¤¤ë¡£ */ + */ /*=*/ @@ -55,6 +62,7 @@ #include #include +#include "config.h" #include "m17n-gui.h" #include "m17n-misc.h" #include "internal.h" @@ -89,9 +97,6 @@ struct MFontset /* FONT-GROUP */ MPlist *fallback; - - /* Plist of Mt vs font specs. */ - MPlist *font_spec_list; }; static MFontset *default_fontset; @@ -106,8 +111,11 @@ struct MRealizedFontset /* Initialized to ->tick. */ unsigned tick; - /* Font spec extracted from a face. */ - MFont spec; + /* Font spec that must be satisfied, or NULL. */ + MFont *spec; + + /* Font spec requested by a face. */ + MFont request; /* The frame on which the realized fontset is realized. */ MFrame *frame; @@ -121,13 +129,13 @@ struct MRealizedFontset static MPlist * -load_font_group (MPlist *plist, MPlist *elt, MPlist *spec_list) +load_font_group (MPlist *plist, MPlist *elt) { MPLIST_DO (elt, elt) { - /* ELT ::= ( FONT-SPEC-LIST [ LAYOUTER ] ) ... */ - MPlist *elt2, *p; - MFont font, *spec = NULL; + /* ELT ::= ( FONT-SPEC [ LAYOUTER ] ) ... */ + MPlist *elt2; + MFont *font; MSymbol layouter_name; if (! MPLIST_PLIST_P (elt)) @@ -135,28 +143,15 @@ load_font_group (MPlist *plist, MPlist *elt, MPlist *spec_list) elt2 = MPLIST_PLIST (elt); if (! MPLIST_PLIST_P (elt2)) MWARNING (MERROR_FONTSET); - mfont__set_spec_from_plist (&font, MPLIST_PLIST (elt2)); - MPLIST_DO (p, spec_list) - { - if (! memcmp (MPLIST_VAL (p), &font, sizeof (MFont))) - { - spec = MPLIST_VAL (p); - break; - } - } - if (! spec) - { - MSTRUCT_MALLOC (spec, MERROR_FONTSET); - *spec = font; - mplist_add (spec_list, Mt, spec); - } + MSTRUCT_CALLOC (font, MERROR_FONTSET); + mfont__set_spec_from_plist (font, MPLIST_PLIST (elt2)); elt2 = MPLIST_NEXT (elt2); layouter_name = Mt; if (MPLIST_SYMBOL_P (elt2)) layouter_name = MPLIST_SYMBOL (elt2); if (layouter_name == Mnil) layouter_name = Mt; - plist = mplist_add (plist, layouter_name, spec); + plist = mplist_add (plist, layouter_name, font); continue; warning: /* ANSI-C requires some statement after a label. */ @@ -170,59 +165,53 @@ load_font_group (MPlist *plist, MPlist *elt, MPlist *spec_list) static void load_fontset_contents (MFontset *fontset) { - MPlist *per_script, *per_charset, *fallback, *spec_list, *font_group; - MSymbol script, lang; + MPlist *per_script, *per_charset, *font_group; MPlist *fontset_def, *plist; fontset->per_script = per_script = mplist (); fontset->per_charset = per_charset = mplist (); - fontset->fallback = fallback = mplist (); - fontset->font_spec_list = spec_list = mplist (); + fontset->fallback = mplist (); if (! (fontset_def = (MPlist *) mdatabase_load (fontset->mdb))) return; MPLIST_DO (plist, fontset_def) { - /* PLIST ::= ( SCRIPT ( LANGUAGE FONT-SPEC-ELT ... ) ... ) - | (CHARSET FONT-SPEC-ELT ...) - | FONT-SPEC-ELT */ + /* PLIST ::= ( SCRIPT ( LANGUAGE ( FONT-SPEC [LAYOUTER]) ... ) ... ) + | ( CHARSET ( FONT-SPEC [LAYOUTER] ) ...) + | ( nil ( FONT-SPEC [LAYOUTER] ) ...) + FONT-SPEC :: = ( ... ) */ MPlist *elt; + MSymbol sym; if (! MPLIST_PLIST_P (plist)) MWARNING (MERROR_FONTSET); elt = MPLIST_PLIST (plist); if (! MPLIST_SYMBOL_P (elt)) MWARNING (MERROR_FONTSET); - script = MPLIST_SYMBOL (elt); + sym = MPLIST_SYMBOL (elt); elt = MPLIST_NEXT (elt); if (! MPLIST_PLIST_P (elt)) MWARNING (MERROR_FONTSET); - if (script == Mnil) - fallback = load_font_group (fallback, elt, spec_list); + if (sym == Mnil) + load_font_group (fontset->fallback, elt); else if (MPLIST_PLIST_P (MPLIST_PLIST (elt))) { - font_group = mplist_find_by_key (fontset->per_charset, script); - if (! font_group) - { - font_group = mplist (); - per_charset = mplist_add (per_charset, script, font_group); - } - load_font_group (font_group, elt, spec_list); + /* SYM is a charset. */ + font_group = mplist (); + per_charset = mplist_add (per_charset, sym, font_group); + load_font_group (font_group, elt); } else { - MPlist *per_lang = mplist_find_by_key (fontset->per_script, script); - - if (! per_lang) - { - per_lang = mplist (); - per_script = mplist_add (per_script, script, per_lang); - } + /* SYM is a script */ + MPlist *per_lang = mplist (); + per_script = mplist_add (per_script, sym, per_lang); MPLIST_DO (elt, elt) { /* ELT ::= ( LANGUAGE FONT-DEF ...) ... */ MPlist *elt2; + MSymbol lang; if (! MPLIST_PLIST_P (elt)) MWARNING (MERROR_FONTSET); @@ -232,14 +221,10 @@ load_fontset_contents (MFontset *fontset) lang = MPLIST_SYMBOL (elt2); if (lang == Mnil) lang = Mt; - font_group = mplist_find_by_key (per_lang, lang); - if (! font_group) - { - font_group = mplist (); - mplist_add (per_lang, lang, font_group); - } + font_group = mplist (); + mplist_add (per_lang, lang, font_group); elt2 = MPLIST_NEXT (elt2); - load_font_group (font_group, elt2, spec_list); + load_font_group (font_group, elt2); } } continue; @@ -265,6 +250,8 @@ free_fontset (void *object) { MPLIST_DO (pl, MPLIST_PLIST (plist)) { + MPLIST_DO (p, MPLIST_PLIST (pl)) + free (MPLIST_VAL (p)); p = MPLIST_PLIST (pl); M17N_OBJECT_UNREF (p); } @@ -275,76 +262,187 @@ free_fontset (void *object) } if (fontset->per_charset) { - MPLIST_DO (plist, fontset->per_charset) + MPLIST_DO (pl, fontset->per_charset) { - pl = MPLIST_PLIST (plist); - M17N_OBJECT_UNREF (pl); + MPLIST_DO (p, MPLIST_PLIST (pl)) + free (MPLIST_VAL (p)); + p = MPLIST_PLIST (p); + M17N_OBJECT_UNREF (p); } M17N_OBJECT_UNREF (fontset->per_charset); } if (fontset->fallback) - M17N_OBJECT_UNREF (fontset->fallback); + { + MPLIST_DO (p, fontset->fallback) + free (MPLIST_VAL (p)); + M17N_OBJECT_UNREF (fontset->fallback); + } + plist = mplist_find_by_key (fontset_list, fontset->name); if (! plist) mdebug_hook (); mplist_pop (plist); - if (fontset->font_spec_list) - { - if (((M17NObject *) (fontset->font_spec_list))->ref_count == 1) - MPLIST_DO (plist, fontset->font_spec_list) - free (MPLIST_VAL (plist)); - M17N_OBJECT_UNREF (fontset->font_spec_list); - } free (object); } static void -realize_font_group (MFrame *frame, MFont *request, MPlist *font_group, - int size) +realize_fontset_elements (MFrame *frame, MRealizedFontset *realized) { - MPlist *plist = MPLIST_VAL (font_group), *pl, *p; + MFontset *fontset = realized->fontset; + MPlist *per_script, *per_charset, *font_group; + MPlist *plist, *pl, *p; - mplist_set (font_group, Mnil, NULL); - MPLIST_DO (pl, plist) + realized->per_script = per_script = mplist (); + /* The actual elements of per_script are realized on demand. */ +#if 0 + MPLIST_DO (plist, fontset->per_script) { - MRealizedFont *rfont = mfont__select (frame, MPLIST_VAL (pl), request, - size); + per_lang = mplist (); + per_script = mplist_add (per_script, MPLIST_KEY (plist), per_lang); + MPLIST_DO (pl, MPLIST_PLIST (plist)) + { + font_group = mplist (); + per_lang = mplist_add (per_lang, MPLIST_KEY (pl), font_group); + MPLIST_DO (p, MPLIST_PLIST (pl)) + font_group = mplist_add (font_group, + MPLIST_KEY (p), MPLIST_VAL (p)); + } + } +#endif - if (rfont) + realized->per_charset = per_charset = mplist (); + MPLIST_DO (pl, fontset->per_charset) + { + font_group = mplist (); + per_charset = mplist_add (per_charset, MPLIST_KEY (plist), font_group); + MPLIST_DO (p, MPLIST_PLIST (pl)) + font_group = mplist_add (font_group, MPLIST_KEY (p), MPLIST_VAL (p)); + } + realized->fallback = font_group = mplist (); + MPLIST_DO (p, fontset->fallback) + font_group = mplist_add (font_group, MPLIST_KEY (p), MPLIST_VAL (p)); +} + +MPlist * +get_per_script (MFontset *fontset, MSymbol script) +{ + MPlist *plist; + + if (script == Mnil) + return fontset->fallback; + plist = mplist_get (fontset->per_script, script); + if (! plist) + { + int len = MSYMBOL_NAMELEN (script); + char *cap = alloca (8 + len + 1); + MSymbol capability; + MFont *font; + MPlist *pl, *p; + + sprintf (cap, ":script=%s", MSYMBOL_NAME (script)); + capability = msymbol (cap); + + pl = mplist (); + MPLIST_DO (p, fontset->fallback) { - rfont->layouter = MPLIST_KEY (pl); - if (rfont->layouter == Mt) - rfont->layouter = Mnil; - MPLIST_DO (p, font_group) - if (((MRealizedFont *) (MPLIST_VAL (p)))->score > rfont->score) - break; - mplist_push (p, Mt, rfont); + font = mfont_copy (MPLIST_VAL (p)); + mfont_put_prop (font, Mregistry, Municode_bmp); + font->source = MFONT_SOURCE_FT; + font->capability = capability; + mplist_add (pl, Mt, font); + + font = mfont_copy (MPLIST_VAL (p)); + mfont_put_prop (font, Mregistry, Miso10646_1); + font->source = MFONT_SOURCE_X; + font->capability = capability; + mplist_add (pl, Mt, font); } + plist = mplist (); + mplist_add (plist, Mt, pl); + mplist_add (fontset->per_script, script, plist); } + return plist; } -int -check_fontset_element (MFrame *frame, MPlist *element, MGlyph *g, int size) +static void +free_realized_fontset_elements (MRealizedFontset *realized) { - MRealizedFont *rfont = (MRealizedFont *) MPLIST_VAL (element); + MPlist *plist, *pl, *p; + MFont *font; + MFontList *font_list; - if (! rfont) - /* We have already failed to select this font. */ - return 0; - if (! rfont->frame) + if (realized->per_script) { - rfont = mfont__select (frame, &rfont->spec, &rfont->request, size); - free (MPLIST_VAL (element)); - MPLIST_VAL (element) = rfont; - if (! rfont) - /* No font matches this spec. */ - return 0; + MPLIST_DO (plist, realized->per_script) + { + MPLIST_DO (pl, MPLIST_PLIST (plist)) + { + MPLIST_DO (p, MPLIST_PLIST (pl)) + { + font = MPLIST_VAL (p); + if (font->type == MFONT_TYPE_OBJECT) + { + font_list = (MFontList *) font; + free (font_list->fonts); + free (font_list); + } + /* This is to avoid freeing rfont again by the later + M17N_OBJECT_UNREF (p) */ + MPLIST_KEY (p) = Mt; + } + p = MPLIST_PLIST (pl); + M17N_OBJECT_UNREF (p); + } + pl = MPLIST_PLIST (plist); + M17N_OBJECT_UNREF (pl); + } + M17N_OBJECT_UNREF (realized->per_script); } + if (realized->per_charset) + { + MPLIST_DO (plist, realized->per_charset) + { + MPLIST_DO (pl, MPLIST_PLIST (plist)) + { + font = MPLIST_VAL (pl); + if (font->type == MFONT_TYPE_OBJECT) + { + font_list = (MFontList *) font; + free (font_list->fonts); + free (font_list); + } + MPLIST_KEY (pl) = Mt; + } + pl = MPLIST_PLIST (plist); + M17N_OBJECT_UNREF (pl); + } + M17N_OBJECT_UNREF (realized->per_charset); + } + if (realized->fallback) + { + MPLIST_DO (plist, realized->fallback) + { + font = MPLIST_VAL (plist); + if (font->type == MFONT_TYPE_OBJECT) + { + font_list = (MFontList *) font; + free (font_list->fonts); + free (font_list); + } + MPLIST_KEY (plist) = Mt; + } + M17N_OBJECT_UNREF (realized->fallback); + } +} - g->code = mfont__encode_char (rfont, g->c); - return (g->code != MCHAR_INVALID_CODE); +static void +update_fontset_elements (MRealizedFontset *realized) +{ + free_realized_fontset_elements (realized); + realize_fontset_elements (realized->frame, realized); } + /* Internal API */ @@ -383,59 +481,44 @@ mfont__fontset_fini () MRealizedFontset * -mfont__realize_fontset (MFrame *frame, MFontset *fontset, MFace *face) +mfont__realize_fontset (MFrame *frame, MFontset *fontset, + MFace *face, MFont *spec) { MRealizedFontset *realized; MFont request; - MPlist *per_script, *per_lang, *per_charset, *font_group; - MPlist *plist, *pl, *p; + MPlist *plist; if (fontset->mdb) load_fontset_contents (fontset); mfont__set_spec_from_face (&request, face); - if (request.property[MFONT_SIZE] <= 0) + if (request.size <= 0) { mdebug_hook (); - request.property[MFONT_SIZE] = 120; + request.size = 120; } - MPLIST_DO (p, frame->realized_fontset_list) + MPLIST_DO (plist, frame->realized_fontset_list) { - realized = (MRealizedFontset *) MPLIST_VAL (p); - if (fontset->name == MPLIST_KEY (p) - && ! memcmp (&request, &realized->spec, sizeof (request))) + realized = (MRealizedFontset *) MPLIST_VAL (plist); + if (fontset->name == MPLIST_KEY (plist) + && ! memcmp (&request, &realized->request, sizeof (MFont)) + && (realized->spec + ? (spec && ! memcmp (spec, &realized->spec, sizeof (MFont))) + : ! spec)) return realized; } - MSTRUCT_MALLOC (realized, MERROR_FONTSET); + MSTRUCT_CALLOC (realized, MERROR_FONTSET); realized->fontset = fontset; realized->tick = fontset->tick; - realized->spec = request; - realized->frame = frame; - realized->per_script = per_script = mplist (); - MPLIST_DO (plist, fontset->per_script) - { - per_lang = mplist (); - per_script = mplist_add (per_script, MPLIST_KEY (plist), per_lang); - MPLIST_DO (pl, MPLIST_PLIST (plist)) - { - font_group = mplist (); - mplist_add (font_group, Mplist, MPLIST_VAL (pl)); - per_lang = mplist_add (per_lang, MPLIST_KEY (pl), font_group); - } - } - - realized->per_charset = per_charset = mplist (); - MPLIST_DO (plist, fontset->per_charset) + if (spec) { - font_group = mplist (); - mplist_add (font_group, Mplist, MPLIST_VAL (plist)); - per_charset = mplist_add (per_charset, MPLIST_KEY (plist), font_group); + MSTRUCT_CALLOC (realized->spec, MERROR_FONTSET); + *realized->spec = *spec; } - - realized->fallback = mplist (); - mplist_add (realized->fallback, Mplist, fontset->fallback); - + realized->request = request; + realized->frame = frame; + realize_fontset_elements (frame, realized); mplist_add (frame->realized_fontset_list, fontset->name, realized); return realized; } @@ -444,155 +527,300 @@ mfont__realize_fontset (MFrame *frame, MFontset *fontset, MFace *face) void mfont__free_realized_fontset (MRealizedFontset *realized) { - MPlist *plist, *pl, *p; + free_realized_fontset_elements (realized); + if (realized->spec) + free (realized->spec); + free (realized); +} + + +static MRealizedFont * +try_font_list (MFrame *frame, MFontList *font_list, MFont *request, + MSymbol layouter, MGlyph *g, int *num, int all, int exact) +{ + int i, j; + MFont *font; MRealizedFont *rfont; - if (realized->per_script) + for (i = 0; i < font_list->nfonts; i++) { - MPLIST_DO (plist, realized->per_script) + if (font_list->fonts[i].font->type == MFONT_TYPE_SPEC) + MFATAL (MERROR_FONT); + if (exact) { - MPLIST_DO (pl, MPLIST_PLIST (plist)) + if (font_list->fonts[i].score > 0) + break; + } + else + { + if (font_list->fonts[i].score == 0) + continue; + } + font = font_list->fonts[i].font; + if (font->type == MFONT_TYPE_FAILURE) + continue; + /* Check if this font can display all glyphs. */ + for (j = 0; j < *num; j++) + { + int c = g[j].type == GLYPH_CHAR ? g[j].c : ' '; + if (layouter != Mt + ? mfont__flt_encode_char (layouter, c) == MCHAR_INVALID_CODE + : ! mfont__has_char (frame, font, &font_list->object, c)) + break; + } + if (j == 0 && *num > 0) + continue; + if (j == *num || !all) + { + /* We found a font that can display the requested range of + glyphs. */ + if (font->type == MFONT_TYPE_REALIZED) + rfont = (MRealizedFont *) font; + else { - MPLIST_DO (p, MPLIST_PLIST (pl)) - if ((rfont = MPLIST_VAL (p)) && ! rfont->frame) - free (rfont); - p = MPLIST_PLIST (pl); - M17N_OBJECT_UNREF (p); + rfont = mfont__open (frame, font, &font_list->object); + if (! rfont) + continue; + font_list->fonts[i].font = (MFont *) rfont; } - pl = MPLIST_PLIST (plist); - M17N_OBJECT_UNREF (pl); + rfont->layouter = layouter == Mt ? Mnil : layouter; + *num = j; + for (j = 0; j < *num; j++) + { + int c = g[j].type == GLYPH_CHAR ? g[j].c : ' '; + + g[j].code = (rfont->layouter + ? mfont__flt_encode_char (rfont->layouter, c) + : mfont__encode_char (frame, (MFont *) rfont, + &font_list->object, c)); + } + return rfont; } - M17N_OBJECT_UNREF (realized->per_script); } - if (realized->per_charset) + return NULL; +} + + +static MRealizedFont * +try_font_group (MRealizedFontset *realized, MFont *request, + MPlist *font_group, MGlyph *g, int *num, int size) +{ + MFrame *frame = realized->frame; + MFont *font; + MFontList *font_list; + MRealizedFont *rfont; + MPlist *plist; + MSymbol layouter; + int best_score = -1, worst_score; + + for (plist = font_group; ! MPLIST_TAIL_P (plist); ) { - MPLIST_DO (plist, realized->per_charset) + int this_score; + + layouter = MPLIST_KEY (plist); + font = MPLIST_VAL (plist); + if (font->type == MFONT_TYPE_SPEC) { - MPLIST_DO (pl, MPLIST_PLIST (plist)) - if ((rfont = MPLIST_VAL (pl)) && ! rfont->frame) - free (rfont); - pl = MPLIST_PLIST (plist); - M17N_OBJECT_UNREF (pl); + if (realized->spec) + { + MFont this = *font; + + if (mfont__merge (&this, realized->spec, 1) < 0) + { + mplist_pop (plist); + continue; + } + font_list = mfont__list (frame, &this, &this, size); + } + else + font_list = mfont__list (frame, font, request, size); + if (! font_list) + { + mplist_pop (plist); + continue; + } + MPLIST_VAL (plist) = font_list; + } + else + font_list = (MFontList *) font; + + this_score = font_list->fonts[0].score; + if ((this_score == 0) + && (rfont = try_font_list (frame, font_list, request, + layouter, g, num, 1, 1))) + return rfont; + if (best_score < 0) + { + best_score = worst_score = this_score; + plist = MPLIST_NEXT (plist); + } + else if (this_score >= worst_score) + { + worst_score = this_score; + plist = MPLIST_NEXT (plist); + } + else + { + MPlist *pl; + + MPLIST_DO (pl, font_group) + if (this_score < ((MFontList *) MPLIST_VAL (pl))->fonts[0].score) + break; + mplist_pop (plist); + mplist_push (pl, layouter, font_list); } - M17N_OBJECT_UNREF (realized->per_charset); } - if (realized->fallback) + + /* We couldn't find an exact matching font that can display all + glyphs. Find one that can at least display all glyphs. */ + MPLIST_DO (plist, font_group) { - MPLIST_DO (plist, realized->fallback) - if ((rfont = MPLIST_VAL (plist)) && ! rfont->frame) - free (rfont); - M17N_OBJECT_UNREF (realized->fallback); + rfont = try_font_list (frame, MPLIST_VAL (plist), request, + MPLIST_KEY (plist), g, num, 1, 0); + if (rfont) + return rfont; } - free (realized); -} + /* We couldn't find a font that can display all glyphs. Find an + exact matching font that can at least display the first + glyph. */ + MPLIST_DO (plist, font_group) + { + rfont = try_font_list (frame, MPLIST_VAL (plist), request, + MPLIST_KEY (plist), g, num, 0, 1); + if (rfont) + return rfont; + } + + /* Find any font that can at least display the first glyph. */ + MPLIST_DO (plist, font_group) + { + rfont = try_font_list (frame, MPLIST_VAL (plist), request, + MPLIST_KEY (plist), g, num, 0, 0); + if (rfont) + return rfont; + } + return NULL; +} MRealizedFont * mfont__lookup_fontset (MRealizedFontset *realized, MGlyph *g, int *num, MSymbol script, MSymbol language, MSymbol charset, - int size) + int size, int ignore_fallback) { - MFrame *frame = realized->frame; MCharset *preferred_charset = (charset == Mnil ? NULL : MCHARSET (charset)); - MPlist *per_charset, *per_script, *per_lang, *font_group; - MPlist *font_groups[256], *plist; - int n_font_group = 0; - MRealizedFont *first = NULL, *rfont; - int first_len; - int i; + MPlist *per_charset, *per_script, *per_lang; + MPlist *plist; + MRealizedFont *rfont = NULL; + + 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; - if (script != Mnil - && ((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. */ - if (language == Mnil) - language = Mt; - for (i = 0; i < 2; i++) - { - MPLIST_DO (per_lang, MPLIST_PLIST (per_script)) - if ((MPLIST_KEY (per_lang) == language) != i) - font_groups[n_font_group++] = MPLIST_PLIST (per_lang); - } - } - font_groups[n_font_group++] = realized->fallback; + && (per_charset = mplist_get (realized->per_charset, charset)) != NULL + && (rfont = try_font_group (realized, &realized->request, per_charset, + g, num, size))) + return rfont; - if (n_font_group == 1) + if (script != Mnil) { - /* As we only have a fallback font group, try all the other - fonts too. */ - MPLIST_DO (per_script, realized->per_script) - MPLIST_DO (per_lang, MPLIST_PLIST (per_script)) - font_groups[n_font_group++] = MPLIST_PLIST (per_lang); - MPLIST_DO (per_charset, realized->per_charset) - font_groups[n_font_group++] = MPLIST_PLIST (per_charset); - } + MFont request = realized->request; - for (i = 0; i < n_font_group; i++) - { - int j; - - if (MPLIST_PLIST_P (font_groups[i])) - realize_font_group (frame, &realized->spec, font_groups[i], size); + if (script != Mlatin) + /* These are not appropriate for non-Latin scripts. */ + request.property[MFONT_FOUNDRY] + = request.property[MFONT_FAMILY] + = request.property[MFONT_REGISTRY] = 0; - MPLIST_DO (plist, font_groups[i]) - { - rfont = (MRealizedFont *) MPLIST_VAL (plist); - g->code = mfont__encode_char (rfont, g->c); - if (g->code != MCHAR_INVALID_CODE) - break; + per_script = mplist_get (realized->per_script, script); + if (! per_script) + { + per_script = mplist_copy (get_per_script (realized->fontset, script)); + MPLIST_DO (plist, per_script) + MPLIST_VAL (plist) = mplist_copy (MPLIST_VAL (plist)); + mplist_add (realized->per_script, script, per_script); } - if (MPLIST_TAIL_P (plist)) - continue; - for (j = 1; j < *num; j++) + + /* We prefer font groups in this order: + (1) group matching with LANGUAGE if LANGUAGE is not Mnil + (2) group for generic language + (3) group not matching with LANGUAGE */ + if (language == Mnil) + language = Mt; + if ((per_lang = mplist_get (per_script, language)) + && (rfont = try_font_group (realized, &request, per_lang, + g, num, size))) + return rfont; + + if (language == Mt) { - g[j].code = mfont__encode_char (rfont, g[j].c); - if (g[j].code == MCHAR_INVALID_CODE) - break; + /* 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; } - if (! first) - first = rfont, first_len = j; - if (j == *num) - /* We found a font that can display all requested - characters. */ - break; - - MPLIST_DO (plist, MPLIST_NEXT (plist)) + else { - rfont = (MRealizedFont *) MPLIST_VAL (plist); - for (j = 0; j < *num; j++) - { - g[j].code = mfont__encode_char (rfont, g[j].c); - if (g[j].code == MCHAR_INVALID_CODE) - break; - } - if (j == *num) - break; + /* At first try the above (2) */ + if ((per_lang = mplist_get (per_script, Mt)) + && (rfont = try_font_group (realized, &request, per_lang, + g, num, size))) + return rfont; + + /* Then try the above (3) */ + MPLIST_DO (plist, per_script) + if (MPLIST_KEY (plist) != language + && MPLIST_KEY (plist) != Mt + && (rfont = try_font_group (realized, &request, + MPLIST_PLIST (plist), + g, num, size))) + return rfont; } - if (! MPLIST_TAIL_P (plist)) - break; - } - - if (i == n_font_group) - { - if (! first) + if (ignore_fallback) 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) + + if (language != Mnil) + /* Find a font group for this language from all scripts. */ + MPLIST_DO (plist, realized->per_script) + { + MFont request = realized->request; + + if (MPLIST_KEY (plist) != Mlatin) + request.property[MFONT_FOUNDRY] + = request.property[MFONT_FAMILY] + = request.property[MFONT_FAMILY] = 0; + if ((per_lang = mplist_get (MPLIST_PLIST (plist), language)) + && (rfont = try_font_group (realized, &request, per_lang, + g, num, size))) + return rfont; + } + + /* Try fallback fonts. */ + if ((rfont = try_font_group (realized, &realized->request, + realized->fallback, g, num, size))) + return rfont; + + return NULL; + + /* At last try all fonts. */ + MPLIST_DO (per_script, realized->per_script) { - MPLIST_VAL (font_group) = NULL; - return NULL; + MPLIST_DO (per_lang, MPLIST_PLIST (per_script)) + if ((rfont = try_font_group (realized, &realized->request, + MPLIST_PLIST (per_lang), g, num, size))) + return rfont; } - 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; + + return NULL; } /*** @} */ @@ -619,12 +847,29 @@ mfont__lookup_fontset (MRealizedFontset *realized, MGlyph *g, int *num, vacant. The macro M17N_INIT () creates the default fontset. An - application program can modify it before the first call of mframe - (). + application program can modify it before the first call of + mframe (). @return This function returns a pointer to the found or newly created fontset. */ +/***ja + @brief ¥Õ¥©¥ó¥È¥»¥Ã¥È¤òÊÖ¤¹. + + ´Ø¿ô mfontset () ¤Ï̾Á° $NAME ¤ò»ý¤Ä¥Õ¥©¥ó¥È¥»¥Ã¥È¥ª¥Ö¥¸¥§¥¯¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£ + $NAME ¤¬ @c NULL ¤Ê¤é¤Ð¡¢¥Ç¥Õ¥©¥ë¥È¥Õ¥©¥ó¥È¥»¥Ã¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£ + + $NAME ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥Õ¥©¥ó¥È¥»¥Ã¥È¤¬¤Ê¤±¤ì¤Ð¡¢¿·¤·¤¤¤â¤Î¤¬ºî¤é¤ì¤ë¡£¤½¤ÎºÝ¡¢ + m17n ¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ë \<@c fontset, $NAME\> + ¤È¤¤¤¦¥Ç¡¼¥¿¤¬¤¢¤ì¤Ð¡¢¥Õ¥©¥ó¥È¥»¥Ã¥È¤Ï¤½¤Î¥Ç¡¼¥¿¤Ë±è¤Ã¤Æ½é´ü²½¤µ¤ì¤ë¡£ + ¤Ê¤±¤ì¤Ð¡¢¶õ¤Î¤Þ¤Þ¤Ë¤µ¤ì¤ë¡£ + + ¥Þ¥¯¥í M17N_INIT () ¤Ï¥Ç¥Õ¥©¥ë¥È¤Î¥Õ¥©¥ó¥È¥»¥Ã¥È¤òºî¤ë¡£¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥à¤Ï + mframe () ¤ò½é¤á¤Æ¸Æ¤Ö¤Þ¤Ç¤Î´Ö¤Ï¥Ç¥Õ¥©¥ë¥È¥Õ¥©¥ó¥È¥»¥Ã¥È¤òÊѹ¹¤¹¤ë¤³¤È¤¬¤Ç¤­¤ë¡£ + + @return + ¤³¤Î´Ø¿ô¤Ï¸«¤Ä¤«¤Ã¤¿¡¢¤¢¤ë¤¤¤Ïºî¤Ã¤¿¥Õ¥©¥ó¥È¥»¥Ã¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£ + */ MFontset * mfontset (char *name) @@ -633,21 +878,25 @@ mfontset (char *name) 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->per_script = mplist (); - fontset->per_charset = mplist (); - fontset->fallback = mplist (); - } - mplist_put (fontset_list, sym, fontset); + fontset = default_fontset; + else + { + 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); + } + } M17N_OBJECT_REF (fontset); return fontset; } @@ -655,9 +904,13 @@ mfontset (char *name) /*=*/ /***en - @brief Return the name of a fontset + @brief Return the name of a fontset. + + The mfontset_name () function returns the name of fontset $FONTSET. */ +/***ja + @brief ¥Õ¥©¥ó¥È¥»¥Ã¥È¤Î̾Á°¤òÊÖ¤¹. - The mfontset_name () function returns the name of $FONTSET. */ + ´Ø¿ô mfontset_name () ¤Ï¥Õ¥©¥ó¥È¥»¥Ã¥È $FONTSET ¤Î̾Á°¤òÊÖ¤¹¡£ */ MSymbol mfontset_name (MFontset *fontset) { @@ -667,49 +920,78 @@ mfontset_name (MFontset *fontset) /*=*/ /***en - @brief Make a copy a fontset + @brief Make a copy of a fontset. - The mfontset_copy () function makes a copy of $FONTSET, gives it a + The mfontset_copy () function makes a copy of fontset $FONTSET, gives it a name $NAME, and returns a pointer to the created copy. $NAME must - not be a name of existing fontset. Otherwise, this function + not be a name of existing fontset. In such case, this function returns NULL without making a copy. */ +/***ja + @brief ¥Õ¥©¥ó¥È¥»¥Ã¥È¤Î¥³¥Ô¡¼¤òºî¤ë. + + ´Ø¿ô mfontset_copy () ¤Ï¥Õ¥©¥ó¥È¥»¥Ã¥È $FONTSET ¤Î¥³¥Ô¡¼¤òºî¤Ã¤Æ¡¢Ì¾Á° + $NAME ¤òÍ¿¤¨¡¢¤½¤Î¥³¥Ô¡¼¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£$NAME + ¤Ï´û¸¤Î¥Õ¥©¥ó¥È¥»¥Ã¥È¤Î̾Á°¤Ç¤¢¤Ã¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¤½¤Î¤è¤¦¤Ê¾ì¹ç¤Ë¤Ï¥³¥Ô¡¼¤òºî¤é¤º¤Ë + NULL ¤òÊÖ¤¹¡£ */ MFontset * mfontset_copy (MFontset *fontset, char *name) { MSymbol sym = msymbol (name); MFontset *copy = mplist_get (fontset_list, sym); - MPlist *plist, *pl; + MPlist *plist, *pl, *p; if (copy) return NULL; M17N_OBJECT (copy, free_fontset, MERROR_FONTSET); copy->name = sym; + if (fontset->mdb) + load_fontset_contents (fontset); + if (fontset->per_script) { copy->per_script = mplist (); MPLIST_DO (plist, fontset->per_script) { - MPlist *new = mplist (); + MPlist *per_lang = mplist (); + mplist_add (copy->per_script, MPLIST_KEY (plist), per_lang); MPLIST_DO (pl, MPLIST_PLIST (plist)) - mplist_add (new, MPLIST_KEY (pl), mplist_copy (MPLIST_PLIST (pl))); - mplist_add (copy->per_script, MPLIST_KEY (plist), new); + { + MPlist *font_group = mplist (); + + per_lang = mplist_add (per_lang, MPLIST_KEY (pl), font_group); + MPLIST_DO (p, MPLIST_PLIST (pl)) + font_group = mplist_add (font_group, MPLIST_KEY (p), + mfont_copy (MPLIST_VAL (p))); + } } } if (fontset->per_charset) { - copy->per_charset = mplist (); - MPLIST_DO (plist, fontset->per_charset) - mplist_add (copy->per_charset, MPLIST_KEY (plist), - mplist_copy (MPLIST_PLIST (plist))); + MPlist *per_charset = mplist (); + + copy->per_charset = per_charset; + MPLIST_DO (pl, fontset->per_charset) + { + MPlist *font_group = mplist (); + + per_charset = mplist_add (per_charset, MPLIST_KEY (pl), font_group); + MPLIST_DO (p, MPLIST_PLIST (pl)) + font_group = mplist_add (font_group, MPLIST_KEY (p), + mfont_copy (MPLIST_VAL (p))); + } } if (fontset->fallback) - copy->fallback = mplist_copy (fontset->fallback); + { + MPlist *font_group = mplist (); - copy->font_spec_list = fontset->font_spec_list; - M17N_OBJECT_REF (copy->font_spec_list); + copy->fallback = font_group; + MPLIST_DO (p, fontset->fallback) + font_group = mplist_add (font_group, MPLIST_KEY (p), + mfont_copy (MPLIST_VAL (p))); + } mplist_put (fontset_list, sym, copy); M17N_OBJECT_REF (copy); @@ -721,8 +1003,9 @@ mfontset_copy (MFontset *fontset, char *name) /***en @brief Modify the contents of a fontset. - The mfontset_modify_entry () function associates, in $FONTSET, a - copy of $FONT with the $SCRIPT / $LANGUAGE pair or with $CHARSET. + The mfontset_modify_entry () function associates, in fontset + $FONTSET, a copy of $FONT with the $SCRIPT / $LANGUAGE pair or + with $CHARSET. Each font in a fontset is associated with a particular script/language pair, with a particular charset, or with the @@ -739,12 +1022,11 @@ mfontset_copy (MFontset *fontset, char *name) charset. If both $SCRIPT and $CHARSET are not @c Mnil, two copies of $FONT - are created. Then one is associated with the script/language pair - and the other with the charset. + are created. Then one is associated with the $SCRIPT / $LANGUAGE + pair and the other with that charset. - If both $SCRIPT and $CHARSET are @c Mnil, $FONT is associated - with @c Mnil. This kind of fonts are called fallback - fonts. + If both $SCRIPT and $CHARSET are @c Mnil, $FONT is associated with + @c Mnil. This kind of fonts are called @e fallback @e fonts. The argument $HOW specifies the priority of $FONT. If $HOW is positive, $FONT has the highest priority in the group of fonts @@ -753,33 +1035,51 @@ mfontset_copy (MFontset *fontset, char *name) only available font for the associated item; all the other fonts are removed from the group. - If $LAYOUTER_NAME is not @c Mnil, it must be a symbol - representing a @ref flt. 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. + 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 + selected for drawing an M-text, that font layout table is used to + generate a glyph code sequence from a character sequence. @return If the operation was successful, mfontset_modify_entry () returns 0. Otherwise it returns -1 and assigns an error code to the external - variable @c merror_code. */ + variable #merror_code. */ /***ja - @brief ¸À¸ì¤È¥¹¥¯¥ê¥×¥È¤ÎÁȤ߹ç¤ï¤»¤Ë¥Õ¥©¥ó¥È¤ò´ØÏ¢ÉÕ¤±¤ë + @brief ¥Õ¥©¥ó¥È¥»¥Ã¥È¤ÎÆâÍƤòÊѹ¹¤¹¤ë. - ´Ø¿ô mfontset_set_language_script () ¤Ï¡¢$LANGUAGE ¤È $SCRIPT ¤ÎÁÈ - ¤ß¹ç¤ï¤»¤ËÂФ·¤Æ¥Õ¥©¥ó¥È $FONT ¤ò»È¤¦¤è¤¦¡¢¥Õ¥©¥ó¥È¥»¥Ã¥È $FONTSET - ¤òÀßÄꤹ¤ë¡£$LANGUAGE ¤È $SCRIPT ¤Ï¡¢¤½¤ì¤¾¤ì¸À¸ì¤È¥¹¥¯¥ê¥×¥È¤ò»Ø - Äꤹ¤ë¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£ + ´Ø¿ô mfontset_modify_entry () ¤Ï¡¢$LANGUAGE ¤È $SCRIPT ¤ÎÁȤ߹ç¤ï¤»¡¢¤Þ¤¿¤Ï + $CHARSET ¤ËÂФ·¤Æ $FONT ¤Î¥³¥Ô¡¼¤ò»È¤¦¤è¤¦¤Ë¡¢¥Õ¥©¥ó¥È¥»¥Ã¥È $FONTSET ¤òÀßÄꤹ¤ë¡£ - ¸À¸ì¤È¥¹¥¯¥ê¥×¥È¤ÎÁȤ߹ç¤ï¤»°ì¤Ä¤ËÂФ·¤ÆÊ£¿ô¤Î¥Õ¥©¥ó¥È¤òÀßÄꤹ¤ë¤³ - ¤È¤â¤Ç¤­¤ë¡£$PREPEND_P ¤¬ 0 °Ê³°¤Ê¤é¤Ð¡¢$FONT ¤Ï¤½¤ÎÁȤ߹ç¤ï¤»¤ËÂÐ - ¤·¤ÆºÇÍ¥Àè¤ÇÍѤ¤¤é¤ì¤ë¤â¤Î¤È¤Ê¤ë¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢Í¥ÀèÅÙºÇÄã¤Î¥Õ¥© - ¥ó¥È¤È¤·¤ÆÅÐÏ¿¤µ¤ì¤ë¡£ + ¥Õ¥©¥ó¥È¥»¥Ã¥ÈÃæ¤Î³Æ¥Õ¥©¥ó¥È¤Ï¡¢ÆÃÄê¤Î¥¹¥¯¥ê¥×¥È¤È¸À¸ì¤Î¥Ú¥¢¡¢ÆÃÄê¤Îʸ»ú¥»¥Ã¥È¡¢¥·¥ó¥Ü¥ë + @c Mnil ¤Î¤¤¤º¤ì¤«¤È´ØÏ¢ÉÕ¤±¤é¤ì¤Æ¤¤¤ë¡£Æ±¤¸¤â¤Î¤È´ØÏ¢ÉÕ¤±¤é¤ì¤¿¥Õ¥©¥ó¥È¤Ï¥°¥ë¡¼¥×¤ò¹½À®¤¹¤ë¡£ - @return - ½èÍý¤¬À®¸ù¤·¤¿¤È¤­¡¢mfontset_set_language_script () ¤Ï 0 ¤òÊÖ¤¹¡£ - ¼ºÇÔ¤·¤¿¤È¤­¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô @c merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤ò - ÀßÄꤹ¤ë¡£ */ + $SCRIPT ¤Ï @c Mnil ¤Ç¤¢¤ë¤«¡¢¥¹¥¯¥ê¥×¥È¤òÆÃÄꤹ¤ë¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£ + ¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¾ì¹ç¤Ë¤Ï¡¢$LANGUAGE ¤Ï¸À¸ì¤òÆÃÄꤹ¤ë¥·¥ó¥Ü¥ë¤« @c + Mnil ¤Ç¤¢¤ê¡¢$FONT ¤Ïthe $SCRIPT / $LANGUAGE ¥Ú¥¢¤Ë´ØÏ¢ÉÕ¤±¤é¤ì¤ë¡£ + + $CHARSET ¤Ï @c Mnil ¤Ç¤¢¤ë¤«¡¢Ê¸»ú¥»¥Ã¥È¥ª¥Ö¥¸¥§¥¯¥È¤òɽ¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£ + ¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¾ì¹ç¤Ë¤Ï $FONT ¤Ï¤½¤Îʸ»ú¥»¥Ã¥È¤È´ØÏ¢ÉÕ¤±¤é¤ì¤ë¡£ + + $SCRIPT ¤È $CHARSET ¤ÎÁÐÊý¤¬ @c Mnil ¤Ç¤Ê¤¤¾ì¹ç¤Ë¤Ï $FONT + ¤Î¥³¥Ô¡¼¤¬£²¤Äºî¤é¤ì¡¢¤½¤ì¤¾¤ì $SCRIPT / $LANGUAGE + ¥Ú¥¢¤Èʸ»ú¥»¥Ã¥È¤Ë´ØÏ¢ÉÕ¤±¤é¤ì¤ë¡£ + + $SCRIPT ¤È $CHARSET ¤ÎÁÐÊý¤¬ @c Mnil ¤Ê¤é¤Ð¡¢ $FONT ¤Ï @c Mnil + ¤È´ØÏ¢ÉÕ¤±¤é¤ì¤ë¡£¤³¤Î¼ï¤Î¥Õ¥©¥ó¥È¤Ï @e fallback @e font ¤È¸Æ¤Ð¤ì¤ë¡£ + + °ú¿ô $HOW ¤Ï $FONT ¤ÎÍ¥ÀèÅÙ¤ò»ØÄꤹ¤ë¡£$HOW ¤¬Àµ¤Ê¤é¤Ð¡¢$FONT + ¤ÏƱ¤¸¤â¤Î¤È´ØÏ¢ÉÕ¤±¤é¤ì¤¿¥°¥ë¡¼¥×Ãæ¤ÇºÇ¹â¤ÎÍ¥ÀèÅÙ¤ò»ý¤Ä¡£$HOW + ¤¬Éé¤Ê¤é¤Ð¡¢ºÇÄã¤ÎÍ¥ÀèÅÙ¤ò»ý¤Ä¡£$HOW ¤¬ 0 ¤Ê¤é¤Ð¡¢$FONT + ¤Ï´ØÏ¢ÉÕ¤±¤é¤ì¤¿¤â¤Î¤ËÂФ¹¤ëÍ£°ì¤ÎÍøÍѲÄǽ¤Ê¥Õ¥©¥ó¥È¤È¤Ê¤ê¡¢Â¾¤Î¥Õ¥©¥ó¥È¤Ï¥°¥ë¡¼¥×¤«¤é¼è¤ê½ü¤«¤ì¤ë¡£ + + $LAYOUTER_NAME ¤Ï @c Mnil ¤Ç¤¢¤ë¤«¡¢@ref flt + ¡Ê¥Õ¥©¥ó¥È¥ì¥¤¥¢¥¦¥È¥Æ¡¼¥Ö¥ë¡Ë¤ò¼¨¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£¥·¥ó¥Ü¥ë¤Ç¤¢¤ì¤Ð¡¢$FONT ¤òÍѤ¤¤Æ + M-text ¤òɽ¼¨¤¹¤ëºÝ¤Ë¤Ï¡¢¤½¤Î¥Õ¥©¥ó¥È¥ì¥¤¥¢¥¦¥È¥Æ¡¼¥Ö¥ë¤ò»È¤Ã¤Æʸ»úÎ󤫤饰¥ê¥Õ¥³¡¼¥ÉÎó¤òÀ¸À®¤¹¤ë¡£ + + @return + ½èÍý¤¬À®¸ù¤·¤¿¤È¤­¡¢mfontset_modify_entry () ¤Ï 0 ¤òÊÖ¤¹¡£ + ¼ºÇÔ¤·¤¿¤È¤­¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£ */ /*** @errors @@ -791,28 +1091,13 @@ mfontset_modify_entry (MFontset *fontset, MFont *spec, MSymbol layouter_name, int how) { - MPlist *per_lang, *plist[3], *pl; + MPlist *per_lang, *plist[3]; MFont *font = NULL; int i; 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 (! font) - { - font = mfont (); - *font = *spec; - mplist_add (fontset->font_spec_list, Mt, font); - } - i = 0; if (script != Mnil) { @@ -842,20 +1127,166 @@ mfontset_modify_entry (MFontset *fontset, layouter_name = Mt; for (i--; i >= 0; i--) { - if (how == -1) + font = mfont_copy (spec); + font->type = MFONT_TYPE_SPEC; + if (how == 1) mplist_push (plist[i], layouter_name, font); - else if (how == 1) + else if (how == -1) mplist_add (plist[i], layouter_name, font); else { + MPlist *pl; + + MPLIST_DO (pl, plist[i]) + free (MPLIST_VAL (pl)); mplist_set (plist[i], Mnil, NULL); mplist_add (plist[i], layouter_name, font); } } + 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 $SCRIPT is a script name symbol, the returned plist is decided + by $LANGUAGE. + + @li 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. + + @li If $LANGUAGE is a language name symbol, the plist is a @c + FONT-GROUP for the specified script and language. @c FONT-GROUP + is a plist whose keys are FLT (FontLayoutTable) name symbols (@c + Mt if no FLT is associated with the font) and values are pointers + to #MFont. + + @li If $LANGUAGE is @c Mnil, the plist is fallback @c FONT-GROUP + for the script. + + If $SCRIPT is @c Mnil, the returned plist is decided as below. + + @li If $CHARSET is @c Mt, keys of the returned plist are charset name + symbols for which some fonts are specified and values are NULL. + + @li If $CHARSET is a charset name symbol, the plist is a @c FONT-GROUP for + the charset. + + @li If $CHARSET is @c Mnil, the plist is a fallback @c FONT-GROUP. + + @return + It returns a plist describing the contents of a fontset. The + plist should be freed by m17n_object_unref (). */ +/***ja + @brief ¥Õ¥©¥ó¥È¥»¥Ã¥È¤ò¸¡º÷¤¹¤ë. + + ´Ø¿ô mfontset_lookup () ¤Ï $FONTSET ¤ò¸¡º÷¤·¡¢$FONTSET + ¤ÎÆâÍƤΤ¦¤Á»ØÄꤷ¤¿¥¹¥¯¥ê¥×¥È¡¢¸À¸ì¡¢Ê¸»ú¥»¥Ã¥È¤ËÂбþ¤¹¤ëÉôʬ¤òɽ¤¹ + plist ¤òÊÖ¤¹¡£ + + $SCRIPT ¤¬ @c Mt ¤Ê¤é¤Ð¡¢ÊÖ¤¹ plist + ¤Î¥­¡¼¤Ï¥Õ¥©¥ó¥È¤¬»ØÄꤵ¤ì¤Æ¤¤¤ë¥¹¥¯¥ê¥×¥È̾¤Î¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢ÃÍ¤Ï + NULL ¤Ç¤¢¤ë¡£ + + $SCRIPT ¤¬¥¹¥¯¥ê¥×¥È̾¤Î¥·¥ó¥Ü¥ë¤Ç¤¢¤ì¤Ð¡¢ÊÖ¤¹ + plist ¤Ï $LANGUAGE¤Ë¤è¤Ã¤ÆÄê¤Þ¤ë¡£ + + @li $LANGUAGE ¤¬ @c Mt ¤Ê¤é¤Ð¡¢plist + ¤Î¥­¡¼¤Ï¥Õ¥©¥ó¥È¤¬»ØÄꤵ¤ì¤Æ¤¤¤ë¸À¸ì̾¤Î¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢ÃÍ¤Ï + NULL ¤Ç¤¢¤ë¡£¥­¡¼¤Ï @c Mt + ¤Ç¤¢¤ë¤³¤È¤â¤¢¤ê¡¢¤½¤Î¾ì¹ç¤½¤Î¥¹¥¯¥ê¥×¥È¤Ë¥Õ¥©¡¼¥ë¥Ð¥Ã¥¯¥Õ¥©¥ó¥È¤¬¤¢¤ë¤³¤È¤ò°ÕÌ£¤¹¤ë¡£ + + @li $LANGUAGE ¤¬¸À¸ì̾¤Î¥·¥ó¥Ü¥ë¤Ê¤é¤Ð¡¢plist ¤Ï»ØÄê¤Î¥¹¥¯¥ê¥×¥È¤È¸À¸ì¤ËÂФ¹¤ë + @c FONT-GROUP ¤Ç¤¢¤ë¡£@c FONT-GROUP ¤È¤Ï¡¢¥­¡¼¤¬ FLT + (FontLayoutTable) ̾¤Î¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢Ãͤ¬ #MFont + ¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ë¤è¤¦¤Ê plist ¤Ç¤¢¤ë¡£¤¿¤À¤·¥Õ¥©¥ó¥È¤Ë FLT + ¤¬ÂбþÉÕ¤±¤é¤ì¤Æ¤¤¤Ê¤¤»þ¤Ë¤Ï¡¢¥­¡¼¤Ï @c Mt ¤Ë¤Ê¤ë¡£ + + @li $LANGUAGE ¤¬ @c Mnil ¤Ê¤é¤Ð¡¢plist ¤Ï¤½¤Î¥¹¥¯¥ê¥×¥ÈÍѤΥե©¡¼¥ë¥Ð¥Ã¥¯ + @c FONT-GROUP ¤Ç¤¢¤ë¡£ + + $SCRIPT ¤¬ @c Mnil ¤Ê¤é¤Ð¡¢ÊÖ¤¹ plist ¤Ï°Ê²¼¤Î¤è¤¦¤ËÄê¤Þ¤ë¡£ + + @li $CHARSET ¤¬ @c Mt ¤Ê¤é¤Ð¡¢plist + ¤Î¥­¡¼¤Ï¥Õ¥©¥ó¥È¤¬»ØÄꤵ¤ì¤Æ¤¤¤ëʸ»ú¥»¥Ã¥È̾¤Î¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢ÃÍ¤Ï + NULL ¤Ç¤¢¤ë¡£ + + @li $CHARSET ¤¬Ê¸»ú¥»¥Ã¥È̾¤Î¥·¥ó¥Ü¥ë¤Ê¤é¤Ð¡¢plist ¤Ï¤½¤Îʸ»ú¥»¥Ã¥ÈÍѤΠ+ @c FONT-GROUP ¤Ç¤¢¤ë¡£ + + @li $CHARSET ¤¬ @c Mnil ¤Ê¤é¤Ð¡¢plist ¤Ï¥Õ¥©¡¼¥ë¥Ð¥Ã¥¯ @c FONT-GROUP ¤Ç¤¢¤ë¡£ + + @return + ¤³¤Î´Ø¿ô¤Ï¥Õ¥©¥ó¥È¥»¥Ã¥È¤ÎÆâÍƤòɽ¤¹ plist ¤òÊÖ¤¹¡£ + plist ¤Ï 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) + { + pl = get_per_script (fontset, script); + if (MPLIST_TAIL_P (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 */ @@ -863,14 +1294,22 @@ mfontset_modify_entry (MFontset *fontset, /*** @{ */ /***en - @brief Dump a fontset + @brief Dump a fontset. - The mdebug_dump_fontset () function prints $FONTSET in a human readable + The mdebug_dump_fontset () function prints fontset $FONTSET in a human readable way to the stderr. $INDENT specifies how many columns to indent the lines but the first one. @return This function returns $FONTSET. */ +/***ja + @brief ¥Õ¥©¥ó¥È¥»¥Ã¥È¤ò¥À¥ó¥×¤¹¤ë. + + ´Ø¿ô mdebug_dump_face () ¤Ï¥Õ¥©¥ó¥È¥»¥Ã¥È $FONTSET ¤ò stderr + ¤Ë¿Í´Ö¤Ë²ÄÆɤʷÁ¤Ç°õºþ¤¹¤ë¡£ $INDENT ¤Ï£²¹ÔÌܰʹߤΥ¤¥ó¥Ç¥ó¥È¤ò»ØÄꤹ¤ë¡£ + + @return + ¤³¤Î´Ø¿ô¤Ï $FONTSET ¤òÊÖ¤¹¡£ */ MFontset * mdebug_dump_fontset (MFontset *fontset, int indent) @@ -891,7 +1330,8 @@ mdebug_dump_fontset (MFontset *fontset, int indent) fprintf (stderr, "\n %s(%s", prefix, MPLIST_KEY (pl)->name); MPLIST_DO (p, MPLIST_PLIST (pl)) { - fprintf (stderr, "\n %s(%s ", prefix, + fprintf (stderr, "\n %s(0x%X %s ", prefix, + (unsigned) MPLIST_VAL (p), MPLIST_KEY (p)->name); mdebug_dump_font (MPLIST_VAL (p)); fprintf (stderr, ")");