From 5050e529cf5f8ab0402f16c0a48265bd1e6f3fc7 Mon Sep 17 00:00:00 2001 From: handa Date: Wed, 17 Aug 2005 13:00:30 +0000 Subject: [PATCH] Include "fontset.h". (M_font_capability, M_font_list, M_font_list_len): New variables. (font_score_priority): Change order of initial elements. (font_score_shift_bits): Fix array size. (common_weight): Add "thin", "semibold", and "heavy". (common_stretch): Add "ultracondensed", "extracondensed", "extraexpanded", and "utltraexpand". (font_weight_regular, font_weight_normal, font_weight_medium): New variables. (gen_font_name): This function deleted. (find_encoding): Set font->encoding. (OTF_tag): New function. (otf_script_list): New variable. (load_otf_script_list): New function. (find_script_from_otf_tag): New function. (xlfd_parse_name): Set font->type and font->source. (mfont__free_realized): Free chains rfonts. (font_score): Renamed from mfont__score. (Miso8859_1, Miso10646_1, Municode_bmp, Municode_full) (Mapple_roman): New variables. (mfont__init): Initilize new variables. Initalize default_encoding.encoding_name and default_encoding.encoding_charset to Municode_full and mcharset__unicode. Use SAFE* macros for allocating filepath buffer. (mfont__fini): Free otf_script_list. (mfont__id): New function. (mfont__match_p): Check also capability member of MFont. (mfont__merge): New funciton. (mfont__set_spec_from_face): Set type and source members. (mfont__set_spec_from_plist): Set capability and type members. (mfont__select): Argument changed. (mfont__available): New function. (compare_font_score): New function. (mfont__list): New function. (mfont__open): Return a realized font. (mfont__resize): Adjusted for the change of MFont. (mfont__has_char): New function. (mfont__encode_char): Argument changed. (mfont__set_spec): Argument changed. (free_font_capability): New function. (mfont__get_capability): New function. (MFontfile): New variable. (mfont_get_prop): Adjusted for the change of MFont. (mfont_put_prop): Likewise. (mfont_set_selection_priority): Fix the way of setting font_score_priority[]. (mfont_find): Use mfont__list instead of mfont__select. (mfont_resize_ratio): Adjusted for the change of MFont. (mfont_list): Use mfont__list. (mfont_check): New function. --- src/font.c | 1090 ++++++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 837 insertions(+), 253 deletions(-) diff --git a/src/font.c b/src/font.c index 0a59172..ae30530 100644 --- a/src/font.c +++ b/src/font.c @@ -30,7 +30,7 @@ key of a font property must be one of the following symbols: @c Mfoundry, @c Mfamily, @c Mweight, @c Mstyle, @c Mstretch, - @c Madstyle, @c Mregistry, @c Msize, @c Mresolution. + @c Madstyle, @c Mregistry, @c Msize, @c Mresolution, @c Mtype. When the key of a font property is @c Msize or @c Mresolution, its value is an integer. Otherwise the value is a symbol. @@ -63,7 +63,10 @@ size in the unit of 1/10 point. The value of a resolution property is an integer representing - assumed device resolution in the unit of dots per inch (dpi) + assumed device resolution in the unit of dots per inch (dpi). + + The value of a type property is a symbol indicating a font driver; + currently Mx or Mfreetype. The m17n library uses font objects for two purposes: to receive font specification from an application program, and to present @@ -107,7 +110,7 @@ variable @c M17NDIR. See the documentation of the variable for details. - If the m17n library is configured to use the fontconfig librray, + If the m17n library is configured to use the fontconfig library, in addition to #mfont_freetype_path, all fonts available via fontconfig are supported. @@ -174,11 +177,13 @@ @addtogroup m17nFont @brief ¥Õ¥©¥ó¥È¥ª¥Ö¥¸¥§¥¯¥È. - m17n GUI API ¤Ï¥Õ¥©¥ó¥È¤ò @c MFont ·¿¤Î¥ª¥Ö¥¸¥§¥¯¥È¤È¤·¤Æɽ¸½¤¹¤ë¡£¥Õ¥©¥ó¥È¤Ï @e - ¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£ ¤ò»ý¤Ä¤³¤È¤¬¤Ç¤­¤ë¡£Â¾¤Î¥¿¥¤¥×¤Î¥×¥í¥Ñ¥Æ¥£Æ±ÍÍ¡¢¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤Ï¥­¡¼¤ÈÃͤ«¤é¤Ê¤ê¡¢¥­¡¼¤Ï°Ê²¼¤Î¥·¥ó¥Ü¥ë¤Î¤¤¤º¤ì¤«¤Ç¤¢¤ë¡£ + m17n GUI API ¤Ï¥Õ¥©¥ó¥È¤ò @c MFont ·¿¤Î¥ª¥Ö¥¸¥§¥¯¥È¤È¤·¤Æɽ¸½¤¹¤ë¡£ + ¥Õ¥©¥ó¥È¤Ï @e ¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£ ¤ò»ý¤Ä¤³¤È¤¬¤Ç¤­¤ë¡£Â¾¤Î¥¿¥¤¥×¤Î¥× + ¥í¥Ñ¥Æ¥£Æ±ÍÍ¡¢¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤Ï¥­¡¼¤ÈÃͤ«¤é¤Ê¤ê¡¢¥­¡¼¤Ï°Ê²¼¤Î¥· + ¥ó¥Ü¥ë¤Î¤¤¤º¤ì¤«¤Ç¤¢¤ë¡£ @c Mfoundry, @c Mfamily, @c Mweight, @c Mstyle, @c Mstretch, - @c Madstyle, @c Mregistry, @c Msize, @c Mresolution + @c Madstyle, @c Mregistry, @c Msize, @c Mresolution, @c Mtype ¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼¤¬ @c Msize ¤¢¤ë¤¤¤Ï @c Mresolution ¤Î¾ì¹ç¡¢ÃͤÏÀ°¿ôÃͤǤ¢¤ê¡¢¥­¡¼¤¬¤½¤ì°Ê³°¤Î¾ì¹ç¡¢Ãͤϥ·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£ @@ -206,15 +211,20 @@ registry ¥×¥í¥Ñ¥Æ¥£¤ÎÃͤϡ¢iso10646, iso8895-1 Åù¤Î¥ì¥¸¥¹¥È¥ê¾ðÊó¤ò¼¨¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£ - size ¥×¥í¥Ñ¥Æ¥£¤ÎÃͤϡ¢¥Õ¥©¥ó¥È¤Î¥Ç¥¶¥¤¥ó¥µ¥¤¥º¤òɽ¤ï¤¹À°¿ôÃͤǤ¢¤ê¡¢Ã±°Ì¤Ï - 1/10 ¥Ý¥¤¥ó¥È¤Ç¤¢¤ë¡£ + size ¥×¥í¥Ñ¥Æ¥£¤ÎÃͤϡ¢¥Õ¥©¥ó¥È¤Î¥Ç¥¶¥¤¥ó¥µ¥¤¥º¤òɽ¤ï¤¹À°¿ôÃͤǤ¢¤ê¡¢ + ñ°Ì¤Ï1/10 ¥Ý¥¤¥ó¥È¤Ç¤¢¤ë¡£ + + resolution ¥×¥í¥Ñ¥Æ¥£¤ÎÃͤϡ¢ÁÛÄꤵ¤ì¤Æ¤¤¤ë¥Ç¥Ð¥¤¥¹¤Î²òÁüÅÙ¤òɽ¤ï¤¹ + À°¿ôÃͤǤ¢¤ê¡¢Ã±°Ì¤Ïdots per inch (dpi) ¤Ç¤¢¤ë¡£ - resolution ¥×¥í¥Ñ¥Æ¥£¤ÎÃͤϡ¢ÁÛÄꤵ¤ì¤Æ¤¤¤ë¥Ç¥Ð¥¤¥¹¤Î²òÁüÅÙ¤òɽ¤ï¤¹À°¿ôÃͤǤ¢¤ê¡¢Ã±°Ì¤Ï - dots per inch (dpi) ¤Ç¤¢¤ë¡£ + type ¥×¥í¥Ñ¥Æ¥£¤ÎÃͤϡ¢¥Õ¥©¥ó¥È¥É¥é¥¤¥Ð¤ò»Ø¼¨¤·¡¢¸½ºß Mx ¤â¤·¤¯¤Ï + Mfreetype ¤Ç¤¢¤ë¡£ - m17n ¥é¥¤¥Ö¥é¥ê¤Ï¥Õ¥©¥ó¥È¥ª¥Ö¥¸¥§¥¯¥È¤ò£²¤Ä¤ÎÌÜŪ¤ÇÍѤ¤¤Æ¤¤¤ë¡£ - ¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥à¤«¤é¥Õ¥©¥ó¥È¤Î»ØÄê¤ò¼õ¤±¼è¤ëÌÜŪ¤È¡¢¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥à¤ËÍøÍѲÄǽ¤Ê¥Õ¥©¥ó¥È¤òÄ󼨤¹¤ëÌÜŪ¤Ç¤¢¤ë¡£ - ¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥à¤ËÂФ·¤ÆÄ󼨤ò¹Ô¤¦ºÝ¤Ë¤Ï¡¢¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤Ï¤¹¤Ù¤Æ¶ñÂÎŪ¤ÊÃͤò»ý¤Ä¡£ + m17n ¥é¥¤¥Ö¥é¥ê¤Ï¥Õ¥©¥ó¥È¥ª¥Ö¥¸¥§¥¯¥È¤ò£²¤Ä¤ÎÌÜŪ¤ÇÍѤ¤¤Æ¤¤¤ë¡£¥¢¥× + ¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥à¤«¤é¥Õ¥©¥ó¥È¤Î»ØÄê¤ò¼õ¤±¼è¤ëÌÜŪ¤È¡¢¥¢¥×¥ê¥±¡¼ + ¥·¥ç¥ó¥×¥í¥°¥é¥à¤ËÍøÍѲÄǽ¤Ê¥Õ¥©¥ó¥È¤òÄ󼨤¹¤ëÌÜŪ¤Ç¤¢¤ë¡£¥¢¥×¥ê¥±¡¼ + ¥·¥ç¥ó¥×¥í¥°¥é¥à¤ËÂФ·¤ÆÄ󼨤ò¹Ô¤¦ºÝ¤Ë¤Ï¡¢¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤Ï¤¹¤Ù + ¤Æ¶ñÂÎŪ¤ÊÃͤò»ý¤Ä¡£ m17n ¥é¥¤¥Ö¥é¥ê¤Ï Window ¥·¥¹¥Æ¥à¥Õ¥©¥ó¥È¡¢FreeType¥Õ¥©¥ó¥È¡¢ OpenType¥Õ¥©¥ó¥È¤Î£³¼ïÎà¤ò¥µ¥Ý¡¼¥È¤·¤Æ¤¤¤ë¡£ @@ -329,17 +339,20 @@ #include "internal-gui.h" #include "font.h" #include "face.h" +#include "fontset.h" MPlist *mfont__driver_list; +static MSymbol M_font_capability, M_font_list, M_font_list_len; + /** Indices to font properties sorted by their priority. */ static int font_score_priority[] = { MFONT_SIZE, - MFONT_ADSTYLE, - MFONT_FAMILY, MFONT_WEIGHT, MFONT_STYLE, MFONT_STRETCH, + MFONT_FAMILY, + MFONT_ADSTYLE, MFONT_FOUNDRY }; @@ -348,10 +361,10 @@ static int font_score_priority[] = /* Indexed by a font property MFONT_XXX, and the value is how many bits to shift the difference of property values. */ -static int font_score_shift_bits[MFONT_PROPERTY_MAX]; +static int font_score_shift_bits[MFONT_SIZE + 1]; /** Predefined symbols for each font property. The order is important - because the function score_font () decides how well a font matches + because the function font_score () decides how well a font matches with a spec by checking how close the index is. */ static char *common_foundry[] = @@ -363,7 +376,8 @@ static char *common_family[] = "helvetica", "times" }; static char *common_weight[] = - { "ultralight", + { "thin" + "ultralight", "extralight", "light", "demilight", @@ -372,10 +386,12 @@ static char *common_weight[] = "normal", "medium", "demibold", + "semibold", "bold", "extrabold", "ultrabold", - "black" }; + "black", + "heavy" }; static char *common_style[] = { "o", "i", @@ -385,12 +401,16 @@ static char *common_style[] = "ri", "ro" }; static char *common_stretch[] = - { "condensed", + { "ultracondensed", + "extracondensed", + "condensed", "narrow", "semicondensed", "normal", "semiexpanded", - "expanded" }; + "expanded", + "extraexpanded", + "ultraexpanded" }; static char *common_adstyle[] = { "serif", "", @@ -398,6 +418,10 @@ static char *common_adstyle[] = static char *common_registry[] = { "iso8859-1" }; +static unsigned short font_weight_regular; +static unsigned short font_weight_normal; +static unsigned short font_weight_medium; + /* Table containing all the data above. */ struct MFontCommonNames @@ -437,31 +461,6 @@ MFontPropertyTable mfont__property_table[MFONT_REGISTRY + 1]; msymbol_put((symbol), mfont__property_table[(n)].property, \ (void *) (numeric)) -static char * -gen_font_name (char *buf, MFont *font) -{ - char size[16]; - int i; - - buf[0] = '\0'; - for (i = 0; i <= MFONT_REGISTRY; i++) - if (FONT_PROPERTY (font, i) != Mnil) - { - char *name = msymbol_name (FONT_PROPERTY (font, i)); - - if (name[0]) - { - if (i > 0) - strcat (buf, ","); - strcat (buf, name); - } - } - sprintf (size, ",%d", font->property[MFONT_SIZE] / 10); - strcat (buf, size); - return buf; -} - - /* Font selector. */ @@ -633,6 +632,7 @@ find_encoding (MFont *font) continue; } } + font->encoding = encoding; return encoding; } @@ -645,9 +645,74 @@ find_encoding (MFont *font) else plist = MPLIST_NEXT (plist); } + font->encoding = &default_encoding; return &default_encoding; } +#ifndef HAVE_OTF +static OTF_Tag +OTF_tag (char *name) +{ + unsigned char *p = (unsigned char *) name; + + if (! name) + return (OTF_Tag) 0; + return (OTF_Tag) ((p[0] << 24) + | (! p[1] ? 0 + : ((p[1] << 16) + | (! p[2] ? 0 + : (p[2] << 8) | p[3])))); +} +#endif /* not HAVE_OTF */ + +static MPlist *otf_script_list; + +static int +load_otf_script_list () +{ + MDatabase *mdb; + MPlist *plist, *pl; + + otf_script_list = mplist (); + mdb = mdatabase_find (msymbol ("standard"), Mscript, msymbol ("otf"), Mnil); + if (! mdb + || ! (plist = mdatabase_load (mdb))) + MERROR (MERROR_FONT, -1); + MPLIST_DO (pl, plist) + { + MPlist *p; + MSymbol script, otf_script; + OTF_Tag tag; + + if (! MPLIST_PLIST_P (pl)) + continue; + p = MPLIST_PLIST (pl); + if (! MPLIST_SYMBOL_P (p)) + continue; + script = MPLIST_SYMBOL (p); + p = MPLIST_NEXT (p); + if (! MPLIST_SYMBOL_P (p)) + continue; + otf_script = MPLIST_SYMBOL (p); + tag = OTF_tag (MSYMBOL_NAME (otf_script)); + mplist_push (otf_script_list, script, (void *) tag); + } + M17N_OBJECT_UNREF (plist); + return 0; +} + +static MSymbol +find_script_from_otf_tag (OTF_Tag tag) +{ + MPlist *plist; + + if (! otf_script_list) + load_otf_script_list (); + plist = mplist_find_by_value (otf_script_list, (void *) tag); + return (plist ? MPLIST_KEY (plist) : Mnil); +} + + /* XLFD parser/generator */ /** Indices to each field of split font name. */ @@ -675,7 +740,8 @@ static int xlfd_parse_name (char *name, MFont *font) { char *field[XLFD_FIELD_MAX]; - unsigned short size, resy, avgwidth; + unsigned short resy, avgwidth; + unsigned size; MSymbol attrs[MFONT_PROPERTY_MAX]; char copy[513]; int i; @@ -743,6 +809,8 @@ xlfd_parse_name (char *name, MFont *font) attrs[MFONT_REGISTRY] = field[XLFD_REGISTRY] ? msymbol (field[XLFD_REGISTRY]) : Mnil; mfont__set_spec (font, attrs, size, resy); + font->type = MFONT_TYPE_SPEC; + font->source = MFONT_SOURCE_X; return 0; } @@ -783,12 +851,12 @@ xlfd_unparse_name (MFont *font) > 513) return NULL; - size = (int) mfont_get_prop (font, Msize); + resy = (int) mfont_get_prop (font, Mresolution); + size = font->size; if ((size % 10) < 5) size /= 10; else size = size / 10 + 1; - resy = (int) mfont_get_prop (font, Mresolution); sprintf (name, "-%s-%s-%s-%s-%s-%s-%d-*-%d-%d-*-*-%s", str[0], str[1], str[2], str[3], str[4], str[5], @@ -796,13 +864,97 @@ xlfd_unparse_name (MFont *font) return strdup (name); } +void +mfont__free_realized (MRealizedFont *rfont) +{ + MRealizedFont *next; + + for (; rfont; rfont = next) + { + next = rfont->next; + M17N_OBJECT_UNREF (rfont->info); + free (rfont); + rfont = next; + } +} + + +/* Compare FONT with REQUEST and return how much they differs. */ + +int +font_score (MFont *font, MFont *request) +{ + int score = 0; + int i = FONT_SCORE_PRIORITY_SIZE; + + while (--i >= 0) + { + enum MFontProperty prop = font_score_priority[i]; + int val; + + if (prop == MFONT_SIZE) + { + if (font->size && request->size) + { + val = font->size - request->size; + if (val) + { + if (val < 0) + val = - val; + if (val >= 0x10000) + val = 0xFFFF; + score |= (val << font_score_shift_bits[MFONT_SIZE]); + } + } + } + else if (font->property[prop] && request->property[prop] + && font->property[prop] != request->property[prop]) + { + if (prop <= MFONT_FAMILY) + val = 1; + else if (prop == MFONT_WEIGHT) + { + unsigned short v1 = font->property[prop]; + unsigned short v2 = request->property[prop]; + + if (v1 == font_weight_regular || v1 == font_weight_normal) + v1 = font_weight_medium; + if (v2 == font_weight_regular || v2 == font_weight_normal) + v2 = font_weight_medium; + val = v1 > v2 ? v1 - v2 : v2 - v1; + } + else + { + val = font->property[prop] - request->property[prop]; + if (val < 0) + val = - val; + if (val > 3) + val = 3; + } + score |= val << font_score_shift_bits[prop]; + } + } + if (request->file != Mnil && request->file != font->file) + score |= 40000000; + return score; +} + /* Internal API */ +MSymbol Miso8859_1, Miso10646_1, Municode_bmp, Municode_full, Mapple_roman; + int mfont__init () { int i, shift; + MSymbol regular = msymbol ("regular"); + MSymbol normal = msymbol ("normal"); + MSymbol medium = msymbol ("medium"); + + M_font_capability = msymbol_as_managing_key (" font-capability"); + M_font_list = msymbol_as_managing_key (" font-list"); + M_font_list_len = msymbol (" font-list-len"); Mfoundry = msymbol ("foundry"); mfont__property_table[MFONT_FOUNDRY].property = Mfoundry; @@ -821,6 +973,7 @@ mfont__init () Msize = msymbol ("size"); Mresolution = msymbol ("resolution"); + Mfontfile = msymbol ("fontfile"); Mfontconfig = msymbol ("fontconfig"); @@ -828,6 +981,12 @@ mfont__init () Mfreetype = msymbol ("freetype"); Mxft = msymbol ("xft"); + Miso8859_1 = msymbol ("iso8859-1"); + Miso10646_1 = msymbol ("iso10646-1"); + Municode_bmp = msymbol ("unicode-bmp"); + Municode_full = msymbol ("unicode-full"); + Mapple_roman = msymbol ("apple-roman"); + /* The first entry of each mfont__property_table must be Mnil so that actual properties get positive numeric numbers. */ for (i = 0; i <= MFONT_REGISTRY; i++) @@ -850,46 +1009,59 @@ mfont__init () if (msymbol_put (sym, mfont__property_table[i].property, (void *) (j + 1)) < 0) return -1; - MLIST_APPEND1 (&mfont__property_table[i], names, sym, MERROR_FONT); + MLIST_APPEND1 (&mfont__property_table[i], names, sym, + MERROR_FONT); + if (i == MFONT_WEIGHT) + { + if (sym == regular) + font_weight_regular = j + 1; + else if (sym == normal) + font_weight_normal = j + 1; + else if (sym == medium) + font_weight_medium = j + 1; + } } } /* Here, SHIFT starts from 1, not 0. This is because the lowest bit of a score is a flag for a scalable font (see the documentation - of mfont_score). */ + of font_score). */ i = FONT_SCORE_PRIORITY_SIZE - 1; for (shift = 1; i >= 0; i--) { font_score_shift_bits[font_score_priority[i]] = shift; if (font_score_priority[i] == MFONT_SIZE) shift += 16; + else if (font_score_priority[i] <= MFONT_FAMILY) + shift++; else shift += 2; } MFONT_INIT (&default_encoding.spec); - default_encoding.encoding_name = Mnil; - default_encoding.encoding_charset = NULL; + default_encoding.encoding_name = Municode_full; + default_encoding.encoding_charset = mcharset__unicode; default_encoding.repertory_name = Mnil; default_encoding.repertory_charset = NULL; { char *path, *buf; int bufsize; + USE_SAFE_ALLOCA; mfont_freetype_path = mplist (); bufsize = strlen (M17NDIR) + 7; - buf = alloca (bufsize); + SAFE_ALLOCA (buf, bufsize); sprintf (buf, "%s/fonts", M17NDIR); mplist_add (mfont_freetype_path, Mstring, strdup (buf)); path = getenv ("M17NDIR"); if (path) { - i = strlen (path) + 7; - if (i > bufsize) - buf = alloca (i); + bufsize = strlen (path) + 7; + SAFE_ALLOCA (buf, bufsize); sprintf (buf, "%s/fonts", path); mplist_push (mfont_freetype_path, Mstring, strdup (buf)); } + SAFE_FREE (buf); } #ifdef HAVE_FREETYPE @@ -931,65 +1103,70 @@ mfont__fini () M17N_OBJECT_UNREF (font_encoding_list); font_encoding_list = NULL; } + if (otf_script_list) + { + M17N_OBJECT_UNREF (otf_script_list); + otf_script_list = NULL; + } + for (i = 0; i <= MFONT_REGISTRY; i++) MLIST_FREE1 (&mfont__property_table[i], names); } -void -mfont__free_realized (MRealizedFont *rfont) -{ - M17N_OBJECT_UNREF (rfont->info); - free (rfont); -} - -/* Compare FONT with REQUEST and return how much they differs. If - FONT does not match with SPEC, return -1. */ - -int -mfont__score (MFont *font, MFont *spec, MFont *request, int limited_size) +MSymbol +mfont__id (MFont *font) { - int score = 0; - int i = FONT_SCORE_PRIORITY_SIZE; - - while (--i >= 0) + char *buf, *p; + int i; + int file_len = (font->file == Mnil ? 0 : MSYMBOL_NAMELEN (font->file)); + int capability_len = (font->capability == Mnil ? 0 + : MSYMBOL_NAMELEN (font->capability)); + int total_len = MFONT_PROPERTY_MAX * 5 + 7 + file_len + capability_len; + MSymbol id; + USE_SAFE_ALLOCA; + + SAFE_ALLOCA (buf, total_len); + p = buf; + if (font->property[0]) + p += sprintf (p, "%X", font->property[0]); + for (i = 1; i < MFONT_PROPERTY_MAX; i++) { - enum MFontProperty prop = font_score_priority[i]; - - if (request->property[prop] != 0) - { - int val = 0; - - if (spec->property[prop] && font->property[prop] - && font->property[prop] != spec->property[prop]) - return -1; - if (font->property[prop]) - val = abs (font->property[prop] - request->property[prop]); - if (val && prop <= MFONT_FAMILY) - val = 1; - if (prop == MFONT_SIZE) - { - if (font->property[MFONT_RESY] == 0) - /* This is a scalable font. We prefer a bitmap font - if the size matches exactly. */ - score |= 1; - else - score |= (val << font_score_shift_bits[MFONT_SIZE] - | ((limited_size && val > 0) ? 0x400000 : 0)); - } - else - score |= (val > 3 ? 3 : val) << font_score_shift_bits[prop]; - } + if (font->property[i]) + p += sprintf (p, "-%X", font->property[i]); + else + *p++ = '-'; } - return score; + if (font->size) + p += sprintf (p, "-%X", font->size); + if (capability_len > 0) + { + *p++ = '-'; + memcpy (p, MSYMBOL_NAME (font->capability), capability_len); + p += capability_len; + } + if (file_len > 0) + { + *p++ = '-'; + memcpy (p, MSYMBOL_NAME (font->file), file_len); + p += file_len; + } + id = msymbol__with_len (buf, p - buf); + SAFE_FREE (buf); + return id; } - /** Return 1 iff FONT matches SPEC. */ int mfont__match_p (MFont *font, MFont *spec, int prop) { + if (spec->capability != font->capability + && spec->capability != Mnil && font->capability != Mnil) + return 0; + if (spec->file != font->file + && spec->file != Mnil && font->file != Mnil) + return 0; for (; prop >= 0; prop--) if (spec->property[prop] && font->property[prop] && font->property[prop] != spec->property[prop]) @@ -997,6 +1174,43 @@ mfont__match_p (MFont *font, MFont *spec, int prop) return 1; } +/* Merge SRC into DST. If error_on_conflict is nonzero and a font + property differs in SRC and DST, return -1. */ + +int +mfont__merge (MFont *dst, MFont *src, int error_on_conflict) +{ + int i; + + for (i = 0; i < MFONT_PROPERTY_MAX; i++) + { + if (! dst->property[i]) + dst->property[i] = src->property[i]; + else if (error_on_conflict + && src->property[i] + && dst->property[i] != src->property[i]) + return -1; + } + if (! dst->size) + dst->size = src->size; + else if (error_on_conflict + && src->size + && dst->size != src->size) + return -1; + if (dst->capability == Mnil) + dst->capability = src->capability; + else if (error_on_conflict + && src->capability + && dst->capability != src->capability) + return -1; + if (dst->file == Mnil) + dst->file = src->file; + else if (error_on_conflict + && src->file + && dst->file != src->file) + return -1; + return 0; +} void mfont__set_spec_from_face (MFont *spec, MFace *face) @@ -1005,10 +1219,13 @@ mfont__set_spec_from_face (MFont *spec, MFace *face) for (i = 0; i <= MFONT_ADSTYLE; i++) mfont__set_property (spec, i, face->property[i]); - /* The value 1 is "iso8859-1". */ - spec->property[MFONT_REGISTRY] = 1; - spec->property[MFONT_SIZE] = (int) (face->property[MFACE_SIZE]); + spec->property[MFONT_REGISTRY] = 0; spec->property[MFONT_RESY] = 0; + spec->size = (int) (face->property[MFACE_SIZE]); + spec->type = MFONT_TYPE_SPEC; + spec->source = MFONT_SOURCE_UNDECIDED; + spec->file = spec->capability = Mnil; + spec->encoding = NULL; } @@ -1018,6 +1235,7 @@ mfont__set_spec_from_plist (MFont *spec, MPlist *plist) int i; MSymbol spec_list[MFONT_REGISTRY + 1]; MSymbol registry; + char *reg; MFONT_INIT (spec); memset (spec_list, 0, sizeof spec_list); @@ -1028,109 +1246,181 @@ mfont__set_spec_from_plist (MFont *spec, MPlist *plist) spec_list[i] = MPLIST_SYMBOL (plist); } registry = spec_list[i - 1]; + if (i > 1 && registry != Mnil) + { + reg = MSYMBOL_NAME (registry); + if (reg[0] == ':') + { + mfont__get_capability (registry); + spec->capability = registry; + registry = spec_list[i - 2]; + i--; + } + } mfont__set_property (spec, MFONT_REGISTRY, registry); for (i -= 2; i >= 0; i--) mfont__set_property (spec, i, spec_list[i]); + spec->type = MFONT_TYPE_SPEC; + return registry; } -MRealizedFont * -mfont__select (MFrame *frame, MFont *spec, MFont *request, int limited_size, - MSymbol layouter) + +MFont * +mfont__select (MFrame *frame, MFont *font, int max_size) +{ + MFontDriver *driver; + + if (font->type == MFONT_TYPE_FAILURE) + return NULL; + if (font->type != MFONT_TYPE_SPEC) + return font; + if (font->source == MFONT_SOURCE_UNDECIDED) + { + if (font->file != Mnil || font->capability != Mnil) + font->source = MFONT_SOURCE_FT; + else if (font->property[MFONT_REGISTRY]) + { + MSymbol registry = FONT_PROPERTY (font, MFONT_REGISTRY); + char *reg = MSYMBOL_NAME (registry); + + if (strncmp (reg, "unicode-", 8) == 0 + || strncmp (reg, "apple-roman", 11) == 0 + || (reg[0] >= '0' && reg[0] <= '9' && reg[1] == '-')) + font->source = MFONT_SOURCE_FT; + } + } + if (font->source != MFONT_SOURCE_FT) + { + driver = mplist_get (frame->font_driver_list, Mx); + if (driver) + return (driver->select) (frame, font, max_size); + } + driver = mplist_get (frame->font_driver_list, Mfreetype); + if (! driver) + return NULL; + return (driver->select) (frame, font, max_size); +} + + +int +mfont__available (MFrame *frame, MFont *font) +{ + return -1; +} + +static int +compare_font_score (const void *e1, const void *e2) +{ + return (((MFontScore *) e1)->score > ((MFontScore *) e2)->score); +} + +void +mdebug_dump_font_list (MFontList *font_list) { - MSymbol registry = FONT_PROPERTY (spec, MFONT_REGISTRY); - MPlist *plist; - MRealizedFont *best; int i; - int mdebug_mask = MDEBUG_FONT; - if (registry == Mnil) - registry = Mt; + for (i = 0; i < font_list->nfonts; i++) + { + fprintf (stderr, "%04X - ", font_list->fonts[i].score); + mdebug_dump_font (font_list->fonts[i].font); + fprintf (stderr, "\n"); + } +} - MPLIST_DO (plist, frame->realized_font_list) +MFontList * +mfont__list (MFrame *frame, MFont *spec, MFont *request, int max_size) +{ + MFontList *list; + MSymbol id = mfont__id (spec); + MPlist *pl, *p; + int num, i; + + pl = msymbol_get (id, M_font_list); + if (pl) + num = (int) msymbol_get (id, M_font_list_len); + else { - best = MPLIST_VAL (plist); - if (MPLIST_KEY (plist) == registry - && ! memcmp (&best->spec, spec, sizeof (MFont)) - && ! memcmp (&best->request, request, sizeof (MFont))) + pl = mplist (); + num = 0; + MPLIST_DO (p, frame->font_driver_list) { - if (best->layouter != layouter) + if (spec->source == MFONT_SOURCE_X ? MPLIST_KEY (p) == Mx + : spec->source == MFONT_SOURCE_FT ? MPLIST_KEY (p) == Mfreetype + : 1) { - MRealizedFont *copy; - - MSTRUCT_MALLOC (copy, MERROR_FONT); - *copy = *best; - copy->layouter = layouter; - mplist_add (frame->realized_font_list, registry, copy); - if (copy->info) - M17N_OBJECT_REF (copy->info); - best = copy; + MFontDriver *driver = MPLIST_VAL (p); + num += (driver->list) (frame, pl, spec, 0); } - return best; } + msymbol_put (id, M_font_list, pl); + M17N_OBJECT_UNREF (pl); + msymbol_put (id, M_font_list_len, (void *) num); } + + if (num == 0) + return NULL; - MDEBUG_PUSH_TIME (); - best = NULL; - MPLIST_DO (plist, frame->font_driver_list) + MSTRUCT_MALLOC (list, MERROR_FONT); + MTABLE_MALLOC (list->fonts, num, MERROR_FONT); + for (i = 0; num > 0; num--, pl = MPLIST_NEXT (pl)) { - MFontDriver *driver = MPLIST_VAL (plist); - MRealizedFont *this - = (driver->select) (frame, spec, request, limited_size); + MFont *font = MPLIST_VAL (pl); - if (this) + if (max_size == 0 + || font->size == 0 + || font->size < max_size) { - this->driver = driver; - if (! best - || this->score < best->score) - { - if (best) - mfont__free_realized (best); - best = this; - if (this->score == 0) - break; - } - else - mfont__free_realized (this); + list->fonts[i].font = font; + list->fonts[i].score + = spec == request ? 0 : font_score (font, request); + i++; } } - - if (mdebug__flag & mdebug_mask) + if (i == 0) { - char buf1[256], buf2[256]; - MFont font = *spec; - - for (i = 0; i < MFONT_PROPERTY_MAX; i++) - if (! font.property[i]) - font.property[i] = request->property[i]; - gen_font_name (buf2, &font); - - if (best) - MDEBUG_PRINT_TIME ("FONT", - (stderr, " to select <%s> (%x)from <%s>.", - gen_font_name (buf1, &best->font), - best->score, - buf2)); - else - MDEBUG_PRINT_TIME ("FONT", (stderr, " to fail to find <%s>.", buf2)); - MDEBUG_POP_TIME (); + free (list->fonts); + free (list); + return NULL; } - - if (! best) - return NULL; - best->layouter = layouter; - mplist_add (frame->realized_font_list, registry, best); - return best; + list->nfonts = i; + if (spec != request) + qsort (list->fonts, i, sizeof (MFontScore), compare_font_score); + list->object = *spec; + mfont__merge (&list->object, request, 0); + list->object.type = MFONT_TYPE_OBJECT; + return list; } +/** Open a font specified in FONT. */ -/** Open a font specified in RFONT. Return 0 if successfully - opened, otherwise return -1. */ - -int -mfont__open (MRealizedFont *rfont) +MRealizedFont * +mfont__open (MFrame *frame, MFont *font, MFont *spec) { - return (rfont->driver->open) (rfont); + MFontDriver *driver; + MRealizedFont *rfont; + + if (font->source == MFONT_SOURCE_UNDECIDED) + MFATAL (MERROR_FONT); + if (font->type != MFONT_TYPE_OBJECT) + MFATAL (MERROR_FONT); + for (rfont = MPLIST_VAL (frame->realized_font_list); rfont; + rfont = rfont->next) + { + driver = rfont->driver; + if (rfont->font == font + && mplist_find_by_value (frame->font_driver_list, driver)) + break; + } + + if (! rfont) + { + driver = mplist_get (frame->font_driver_list, + font->source == MFONT_SOURCE_X ? Mx : Mfreetype); + if (! driver) + MFATAL (MERROR_FONT); + } + return (driver->open) (frame, font, spec, rfont); } void @@ -1152,8 +1442,7 @@ mfont__resize (MFont *spec, MFont *request) resize = (MFontResize *) MPLIST_VAL (plist); if (mfont__match_p (spec, &resize->spec, MFONT_ADSTYLE)) { - request->property[MFONT_SIZE] - = request->property[MFONT_SIZE] * resize->resize / 100; + request->size = request->size * resize->resize / 100; return; } plist = MPLIST_NEXT (plist); @@ -1165,26 +1454,65 @@ mfont__resize (MFont *spec, MFont *request) } +int +mfont__has_char (MFrame *frame, MFont *font, MFont *spec, int c) +{ + MFontEncoding *encoding; + unsigned code; + MFontDriver *driver; + + if (font->source == MFONT_SOURCE_UNDECIDED) + MFATAL (MERROR_FONT); + encoding = (font->encoding ? font->encoding : find_encoding (font)); + if (! encoding->encoding_charset) + return 0; + if (encoding->repertory_charset) + { + code = ENCODE_CHAR (encoding->repertory_charset, c); + return (code != MCHAR_INVALID_CODE); + } + code = ENCODE_CHAR (encoding->encoding_charset, c); + if (code == MCHAR_INVALID_CODE) + return 0; + if (font->type == MFONT_TYPE_REALIZED) + driver = ((MRealizedFont *) font)->driver; + else + { + driver = mplist_get (frame->font_driver_list, + font->source == MFONT_SOURCE_X ? Mx : Mfreetype); + if (! driver) + MFATAL (MERROR_FONT); + } + return (driver->has_char) (frame, font, spec, c, code); +} + unsigned -mfont__encode_char (MRealizedFont *rfont, int c) +mfont__encode_char (MFrame *frame, MFont *font, MFont *spec, int c) { MFontEncoding *encoding; unsigned code; + MFontDriver *driver; - if (rfont->layouter != Mnil) - return mfont__flt_encode_char (rfont->layouter, c); - if (! rfont->encoding) - rfont->encoding = find_encoding (&rfont->font); - encoding = rfont->encoding; + if (font->source == MFONT_SOURCE_UNDECIDED) + MFATAL (MERROR_FONT); + encoding = (font->encoding ? font->encoding : find_encoding (font)); if (! encoding->encoding_charset) return MCHAR_INVALID_CODE; - if (encoding->repertory_charset - && ENCODE_CHAR (encoding->repertory_charset, c) == MCHAR_INVALID_CODE) - return MCHAR_INVALID_CODE; + if (encoding->repertory_charset) + return (ENCODE_CHAR (encoding->repertory_charset, c)); code = ENCODE_CHAR (encoding->encoding_charset, c); if (code == MCHAR_INVALID_CODE) return MCHAR_INVALID_CODE; - return (rfont->driver->encode_char) (rfont, code); + if (font->type == MFONT_TYPE_REALIZED) + driver = ((MRealizedFont *) font)->driver; + else + { + driver = mplist_get (frame->font_driver_list, + font->source == MFONT_SOURCE_X ? Mx : Mfreetype); + if (! driver) + MFATAL (MERROR_FONT); + } + return (driver->encode_char) (frame, font, spec, code); } void @@ -1207,6 +1535,8 @@ mfont__get_metric (MGlyphString *gstring, int from, int to) } +/* KEY <= MFONT_REGISTRY */ + void mfont__set_property (MFont *font, enum MFontProperty key, MSymbol val) { @@ -1229,14 +1559,14 @@ mfont__set_property (MFont *font, enum MFontProperty key, MSymbol val) void mfont__set_spec (MFont *font, MSymbol *attrs, - unsigned short size, unsigned short resy) + unsigned size, unsigned short resy) { int i; for (i = 0; i <= MFONT_REGISTRY; i++) mfont__set_property (font, i, attrs[i]); - font->property[MFONT_SIZE] = size; font->property[MFONT_RESY] = resy; + font->size = size; } int @@ -1261,6 +1591,171 @@ mfont__encoding_list (void) return font_encoding_list; } +static void +free_font_capability (void *object) +{ + MFontCapability *cap = object; + int i; + + if (cap->lang) + free (cap->lang); +#ifdef HAVE_OTF + if (cap->script) + for (i = 0; i < MFONT_OTT_MAX; i++) + { + if (cap->features[i].str) + free (cap->features[i].str); + if (cap->features[i].tags) + free (cap->features[i].tags); + } +#endif /* HAVE_OTF */ + free (cap); +} + +MFontCapability * +mfont__get_capability (MSymbol sym) +{ + MFontCapability *cap = msymbol_get (sym, M_font_capability); + char *str, *p, *endp; + int i; + + if (cap) + return cap; + str = MSYMBOL_NAME (sym); + if (str[0] != ':') + return NULL; + M17N_OBJECT (cap, free_font_capability, MERROR_FONT); + msymbol_put (sym, M_font_capability, cap); + M17N_OBJECT_UNREF (cap); + endp = str + MSYMBOL_NAMELEN (sym); + while (str < endp) + { + if (*str++ != ':') + continue; +#ifdef HAVE_OTF + if (str[0] == 'o' && str[1] == 't' && str[2] == 'f' && str[3] == '=') + { + str += 4; + for (i = 0, p = str; i < 4 && p < endp; i++, p++); + if (i < 4) + break; + cap->script_tag = OTF_tag (str); + cap->script = find_script_from_otf_tag (cap->script_tag); + if (*p == '/') + { + for (i = 0, str = ++p; i < 4 && p < endp; i++, p++); + if (i < 4) + { + cap->script = Mnil; + break; + } + cap->langsys_tag = OTF_tag (str); + } + else + cap->langsys_tag = 0; + + for (i = 0; i < MFONT_OTT_MAX; i++) + cap->features[i].nfeatures = -1; + + while (*p == '=' || *p == '+') + { + int idx = *p == '=' ? MFONT_OTT_GSUB : MFONT_OTT_GPOS; + + str = ++p; + while (p < endp && *p != '+') p++; + if (str < p) + { + int n; + /* We never have more than (p - str) tags. */ + OTF_Tag *tags = alloca (sizeof (OTF_Tag) * (p - str)); + char *p0; + + cap->features[idx].str = malloc (p - str + 1); + for (i = n = 0, p0 = str; str + i < p; i++) + { + cap->features[idx].str[i] = str[i]; + if (str[i] == ',' || str + i + 1 == p) + { + if (*p0 == '*') + tags[n] = 0; + else if (*p0 == '~') + tags[n] = OTF_tag (p0 + 1) | 0x80000000; + else + tags[n] = OTF_tag (p0); + n++; + p0 = str + i + 1; + } + } + cap->features[idx].str[i] = '\0'; + cap->features[idx].nfeatures = n; + if (n > 0) + { + int size = sizeof (OTF_Tag) * n; + + cap->features[idx].tags = malloc (size); + memcpy (cap->features[idx].tags, tags, size); + } + } + else + { + cap->features[idx].str = NULL; + cap->features[idx].nfeatures = 0; + } + } + + for (i = 0; i < MFONT_OTT_MAX; i++) + if (cap->features[i].nfeatures < 0) + { + cap->features[i].str = strdup ("*"); + cap->features[i].nfeatures = 1; + cap->features[i].tags = malloc (sizeof (OTF_Tag)); + cap->features[i].tags[0] = 0; + } + str = p; + continue; + } +#endif /* HAVE_OTF */ + if (str[0] == 'l' && str[1] == 'a' && str[2] == 'n' && str[3] == 'g' + && str[4] == '=') + { + int count; + + str += 5; + for (p = str, count = 2; p < endp && *p != ':'; p++) + if (*p == ',') + count++; + MTABLE_MALLOC (cap->lang, count, MERROR_FONT); + for (p = str, count = 0; p < endp && *p != ':'; p++) + if (*p == ',') + { + MSymbol lang = msymbol__with_len (str, p - str), sym; + + if (msymbol_get (lang, Miso639_2)) + cap->lang[count++] = lang; + else if ((sym = msymbol_get (lang, Miso639_1)) != Mnil) + cap->lang[count++] = sym; + else if (msymbol_get (lang, Mlanguage)) + cap->lang[count++] = lang; + str = p + 1; + } + if (str < p) + cap->lang[count++] = msymbol__with_len (str, p - str); + cap->lang[count] = Mnil; + str = p; + } + else if (str[0] == 's' && str[1] == 'c' && str[2] == 'r' && str[3] == 'i' + && str[4] == 'p' && str[5] == 't' && str[6] == '=') + { + str += 7; + for (p = str; p < endp && *p != ':'; p++); + if (str < p) + cap->script = msymbol__with_len (str, p - str); + str = p; + } + } + return cap; +} + /*** @} */ #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */ @@ -1407,6 +1902,21 @@ MSymbol Mregistry; MSymbol Msize; /***en + @brief Key of font property specifying file name. + + The variable #Mfontfile is a symbol of name "fontfile" + and is used as a key of font property. The property value must be + a symbol whose name is a font file name. */ +/***ja + @brief ¥Õ¥©¥ó¥È¥Õ¥¡¥¤¥ë¤ò»ØÄꤹ¤ë¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼. + + ÊÑ¿ô #Mfontfile ¤Ï "fontfile" ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢ + ¤ê¡¢¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼¤È¤·¤ÆÍѤ¤¤é¤ì¤ë¡£Ãͤϡ¢¥Õ¥©¥ó¥È¥Õ¥¡¥¤ + ¥ë̾¤ò̾Á°¤È¤·¤Æ»ý¤Ä¤È¤¹¤ë¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£ */ + +MSymbol Mfontfile; + +/***en @brief Key of font property specifying resolution. The variable #Mresolution is a symbol of name "resolution" and @@ -1633,7 +2143,8 @@ mfont_unparse_name (MFont *font, MSymbol format) #ifdef HAVE_FONTCONFIG else if (format == Mfontconfig) name = mfont__ft_unparse_name (font); -#endif + +#endif /* HAVE_FONTCONFIG */ else MERROR (MERROR_FONT, NULL); return name; @@ -1669,11 +2180,11 @@ mfont_copy (MFont *font) font $FONT. $KEY must be one of the following symbols: @c Mfamily, @c Mweight, @c Mstyle, @c Mstretch, - @c Madstyle, @c Mregistry, @c Msize, @c Mresolution. + @c Madstyle, @c Mregistry, @c Msize, @c Mresolution, @c Mtype. @return If $KEY is @c Mfamily, @c Mweight, @c Mstyle, @c Mstretch, @c - Madstyle, or @c Mregistry, this function returns the + Madstyle, @c Mregistry, or @c Mtype, this function returns the corresponding value as a symbol. If the font does not have $KEY property, it returns @c Mnil. If $KEY is @c Msize or @c Mresolution, this function returns the @@ -1685,20 +2196,21 @@ mfont_copy (MFont *font) /***ja @brief ¥Õ¥©¥ó¥È¤Î¥×¥í¥Ñ¥Æ¥£¤ÎÃͤòÆÀ¤ë. - ´Ø¿ô mfont_get_prop () ¤Ï¥Õ¥©¥ó¥È $FONT ¤Î¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥­¡¼¤¬ - $KEY ¤Ç¤¢¤ë¤â¤Î¤ÎÃͤòÊÖ¤¹¡£$KEY ¤Ï°Ê²¼¤Î¥·¥ó¥Ü¥ë¤Î¤¤¤º¤ì¤«¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£ + ´Ø¿ô mfont_get_prop () ¤Ï¥Õ¥©¥ó¥È $FONT ¤Î¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥­¡¼¤¬ + $KEY ¤Ç¤¢¤ë¤â¤Î¤ÎÃͤòÊÖ¤¹¡£$KEY ¤Ï°Ê²¼¤Î¥·¥ó¥Ü¥ë¤Î¤¤¤º¤ì¤«¤Ç¤Ê¤±¤ì + ¤Ð¤Ê¤é¤Ê¤¤¡£ @c Mfamily, @c Mweight, @c Mstyle, @c Mstretch, - @c Madstyle, @c Mregistry, @c Msize, @c Mresolution. + @c Madstyle, @c Mregistry, @c Msize, @c Mresolution, @c Mtype. @return $KEY ¤¬ @c Mfamily, @c Mweight, @c Mstyle, @c Mstretch, @c - Madstyle, @c Mregistry ¤Î¤¤¤º¤ì¤«¤Ç¤¢¤ì¤Ð¡¢ÁêÅö¤¹¤ëÃͤò¥·¥ó¥Ü¥ë¤È¤·¤ÆÊÖ¤¹¡£ - ¥Õ¥©¥ó¥È¤¬¤½¤Î¥×¥í¥Ñ¥Æ¥£¤ò»ý¤¿¤Ê¤¤¾ì¹ç¤Ë¤Ï @c Mnil ¤òÊÖ¤¹¡£ - $KEY ¤¬ @c Msize ¤¢¤ë¤¤¤Ï @c Mresolution - ¤Î¾ì¹ç¤Ë¤Ï¡¢ÁêÅö¤¹¤ëÃͤò¤ÏÀ°¿ôÃͤȤ·¤ÆÊÖ¤¹¡£¥Õ¥©¥ó¥È¤¬¤½¤Î¥×¥í¥Ñ¥Æ¥£¤ò»ý¤¿¤Ê¤¤¾ì¹ç¤Ë¤Ï 0 - ¤òÊÖ¤¹¡£$KEY ¤¬¤½¤ì°Ê³°¤Î¤â¤Î¤Ç¤¢¤ì¤Ð¡¢@c NULL ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô - #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£ */ + Madstyle, @c Mregistry, @c Mtype ¤Î¤¤¤º¤ì¤«¤Ç¤¢¤ì¤Ð¡¢ÁêÅö¤¹¤ëÃͤò¥· + ¥ó¥Ü¥ë¤È¤·¤ÆÊÖ¤¹¡£¥Õ¥©¥ó¥È¤¬¤½¤Î¥×¥í¥Ñ¥Æ¥£¤ò»ý¤¿¤Ê¤¤¾ì¹ç¤Ë¤Ï @c + Mnil ¤òÊÖ¤¹¡£$KEY ¤¬ @c Msize ¤¢¤ë¤¤¤Ï @c Mresolution ¤Î¾ì¹ç¤Ë¤Ï¡¢ + ÁêÅö¤¹¤ëÃͤò¤ÏÀ°¿ôÃͤȤ·¤ÆÊÖ¤¹¡£¥Õ¥©¥ó¥È¤¬¤½¤Î¥×¥í¥Ñ¥Æ¥£¤ò»ý¤¿¤Ê¤¤ + ¾ì¹ç¤Ë¤Ï 0 ¤òÊÖ¤¹¡£$KEY ¤¬¤½¤ì°Ê³°¤Î¤â¤Î¤Ç¤¢¤ì¤Ð¡¢@c NULL ¤òÊÖ¤·¡¢ + ³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£ */ void * mfont_get_prop (MFont *font, MSymbol key) @@ -1719,7 +2231,7 @@ mfont_get_prop (MFont *font, MSymbol key) return (void *) FONT_PROPERTY (font, MFONT_REGISTRY); if (key == Msize) { - int size = font->property[MFONT_SIZE]; + int size = font->size; return (void *) size; } if (key == Mresolution) @@ -1727,7 +2239,8 @@ mfont_get_prop (MFont *font, MSymbol key) int resy = font->property[MFONT_RESY]; return (void *) resy; } - + if (key == Mfontfile) + return (void *) font->file; MERROR (MERROR_FONT, NULL); } @@ -1777,12 +2290,16 @@ mfont_put_prop (MFont *font, MSymbol key, void *val) else if (key == Msize) { unsigned size = (unsigned) val; - font->property[MFONT_SIZE] = size; + font->size = size; } else if (key == Mresolution) { unsigned resy = (unsigned) val; - font->property[MFONT_RESY] = resy; + font->property[MFONT_RESY] = resy; + } + else if (key == Mfontfile) + { + font->file = (MSymbol) val; } else MERROR (MERROR_FONT, -1); @@ -1880,7 +2397,7 @@ int mfont_set_selection_priority (MSymbol *keys) { int priority[FONT_SCORE_PRIORITY_SIZE]; - int i, j; + int i, j, shift; for (i = 0; i < FONT_SCORE_PRIORITY_SIZE; i++, keys++) { @@ -1911,6 +2428,20 @@ mfont_set_selection_priority (MSymbol *keys) } for (i = 0; i < FONT_SCORE_PRIORITY_SIZE; i++) font_score_priority[i] = priority[i]; + /* Here, SHIFT starts from 1, not 0. This is because the lowest bit + of a score is a flag for a scalable font (see the documentation + of font_score). */ + i = FONT_SCORE_PRIORITY_SIZE - 1; + for (shift = 1; i >= 0; i--) + { + font_score_shift_bits[font_score_priority[i]] = shift; + if (font_score_priority[i] == MFONT_SIZE) + shift += 16; + else if (font_score_priority[i] <= MFONT_FAMILY) + shift++; + else + shift += 2; + } return 0; } @@ -1937,20 +2468,28 @@ mfont_set_selection_priority (MSymbol *keys) */ MFont * -mfont_find (MFrame *frame, MFont *spec, int *score, int limited_size) +mfont_find (MFrame *frame, MFont *spec, int *score, int max_size) { MFont spec_copy; - MRealizedFont *rfont; + MFont *best; + MFontList *list; MFONT_INIT (&spec_copy); + spec_copy.property[MFONT_FAMILY] = spec->property[MFONT_FAMILY]; spec_copy.property[MFONT_REGISTRY] = spec->property[MFONT_REGISTRY]; + spec_copy.capability = spec->capability; + spec_copy.file = spec->file; - rfont = mfont__select (frame, &spec_copy, spec, limited_size, Mnil); - if (!rfont) + list = mfont__list (frame, &spec_copy, spec, max_size); + if (! list) return NULL; + + best = list->fonts[0].font; if (score) - *score = rfont->score; - return &rfont->font; + *score = list->fonts[0].score; + free (list->fonts); + free (list); + return best; } /*=*/ @@ -2089,7 +2628,7 @@ mfont_resize_ratio (MFont *font) MFont request = *font; mfont__resize (font, &request); - return (font->property[MFONT_SIZE] * 100 / request.property[MFONT_SIZE]); + return (font->size * 100 / request.size); } /*=*/ @@ -2098,7 +2637,7 @@ mfont_resize_ratio (MFont *font) @brief Get a list of fonts. The mfont_list () functions returns a list of fonts available on - frame $FRAME. $FONT, if not @c Mnil, limits fonts to ones + frame $FRAME. $FONT, if not NULL, limits fonts to ones that match with $FONT. $LANGUAGE, if not @c Mnil, limits fonts to ones that support $LANGUAGE. $MAXNUM, if greater than 0, limits the number of fonts. @@ -2113,7 +2652,7 @@ mfont_resize_ratio (MFont *font) @brief ¥Õ¥©¥ó¥È¤Î¥ê¥¹¥È¤òÆÀ¤ë ´Ø¿ô mfont_list () ¤Ï¥Õ¥ì¡¼¥à $FRAME ¤ÇÍøÍѲÄǽ¤Ê¥Õ¥©¥ó¥È¤Î¥ê¥¹¥È¤òÊÖ¤¹¡£ - $FONT ¤¬ @c Mnil ¤Ç¤Ê¤±¤ì¤Ð¡¢$FONT ¤È¹çÃפ¹¤ëÍøÍѲÄǽ¤Ê¥Õ¥©¥ó¥È¤Î¥ê¥¹¥È¤òÊÖ¤¹¡£ + $FONT ¤¬ NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢$FONT ¤È¹çÃפ¹¤ëÍøÍѲÄǽ¤Ê¥Õ¥©¥ó¥È¤Î¥ê¥¹¥È¤òÊÖ¤¹¡£ $LANGUAGE ¤¬ @c Mnil ¤Ç¤Ê¤±¤ì¤Ð¡¢$LANGUAGE ¤ò¥µ¥Ý¡¼¥È¤¹¤ëÍøÍѲÄǽ¤Ê¥Õ¥©¥ó¥È¤Î¥ê¥¹¥È¤òÊÖ¤¹¡£ $MAXNUM ¤Ï¡¢0 ¤è¤êÂ礭¤¤¾ì¹ç¤Ë¤Ï¡¢ÊÖ¤¹¥Õ¥©¥ó¥È¤Î¿ô¤Î¾å¸Â¤Ç¤¢¤ë¡£ @@ -2125,26 +2664,94 @@ mfont_resize_ratio (MFont *font) MPlist * mfont_list (MFrame *frame, MFont *font, MSymbol language, int maxnum) { - MPlist *plist = mplist (), *p; - int num = 0; + MPlist *plist, *pl; + MFontList *font_list; + int i; - MPLIST_DO (p, frame->font_driver_list) + if (language != Mnil) { - MFontDriver *driver = MPLIST_VAL (p); + /* ":lang=XXX" */ + char *buf = alloca (MSYMBOL_NAMELEN (language) + 7); - num += (driver->list) (frame, plist, font, language, - maxnum > 0 ? maxnum - num : 0); - if (maxnum > 0 && num >= maxnum) - break; + sprintf (buf, ":lang=%s", MSYMBOL_NAME (language)); + font->capability = msymbol (buf); + } + + font_list = mfont__list (frame, font, font, 0); + if (! font_list) + return NULL; + if (font_list->nfonts == 0) + { + free (font_list); + return NULL; } - if (MPLIST_TAIL_P (plist)) + + plist = pl = mplist (); + for (i = 0; i < font_list->nfonts; i++) { - M17N_OBJECT_UNREF (plist); - plist = NULL; + MSymbol family = FONT_PROPERTY (font_list->fonts[i].font, MFONT_FAMILY); + + if (family != Mnil) + pl = mplist_add (pl, family, font_list->fonts[i].font); } + free (font_list); return plist; } + +/*=*/ + +/***en + @brief Check if FONT can be used for SCRIPT and LANGUAGE in FONTSET. + */ + +int +mfont_check (MFrame *frame, MFontset *fontset, MFont *font, + MSymbol script, MSymbol language) +{ + MFont spec; + MPlist *plist, *pl; + int result = 0; + + if (! fontset) + fontset = frame->face->property[MFACE_FONTSET]; + + plist = mfontset_lookup (fontset, script, Mt, Mnil); + if (script != Mnil) + { + if (language == Mnil) + { + if (! mplist_find_by_key (plist, Mt)) + /* No fallback fonts. */ + language = MPLIST_KEY (plist); + } + else if (! mplist_find_by_key (plist, language)) + { + /* Try fallback fonts. */ + if (mplist_find_by_key (plist, Mt)) + language = Mnil; + else + /* No fallback fonts. */ + language = MPLIST_KEY (plist); + } + + M17N_OBJECT_UNREF (plist); + plist = mfontset_lookup (fontset, script, language, Mnil); + } + MPLIST_DO (pl, plist) + { + spec = *(MFont *) MPLIST_VAL (pl); + if (mfont__merge (&spec, font, 1) >= 0 + && mfont__select (frame, &spec, 0)) + { + result = 1; + break; + } + } + M17N_OBJECT_UNREF (plist); + return result; +} + /*** @} */ /*** @addtogroup m17nDebug */ @@ -2182,29 +2789,6 @@ mdebug_dump_font (MFont *font) return font; } -void -mdebug_dump_font_list (MFrame *frame, MSymbol family, MSymbol lang) -{ - MPlist *plist, *p; - - if (family == Mnil) - plist = mfont_list (frame, NULL, lang, 0); - else - { - MFont font; - - MFONT_INIT (&font); - mfont__set_property (&font, MFONT_FAMILY, family); - plist = mfont_list (frame, &font, lang, 0); - } - MPLIST_DO (p, plist) - { - mdebug_dump_font (MPLIST_VAL (p)); - fprintf (stderr, "\n"); - } - M17N_OBJECT_UNREF (plist); -} - /*** @} */ /* -- 1.7.10.4