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.
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
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.
@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
¤Î¾ì¹ç¡¢ÃͤÏÀ°¿ôÃͤǤ¢¤ê¡¢¥¡¼¤¬¤½¤ì°Ê³°¤Î¾ì¹ç¡¢Ãͤϥ·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£
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¥Õ¥©¥ó¥È¤Î£³¼ïÎà¤ò¥µ¥Ý¡¼¥È¤·¤Æ¤¤¤ë¡£
#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
};
/* 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[] =
"helvetica",
"times" };
static char *common_weight[] =
- { "ultralight",
+ { "thin"
+ "ultralight",
"extralight",
"light",
"demilight",
"normal",
"medium",
"demibold",
+ "semibold",
"bold",
"extrabold",
"ultrabold",
- "black" };
+ "black",
+ "heavy" };
static char *common_style[] =
{ "o",
"i",
"ri",
"ro" };
static char *common_stretch[] =
- { "condensed",
+ { "ultracondensed",
+ "extracondensed",
+ "condensed",
"narrow",
"semicondensed",
"normal",
"semiexpanded",
- "expanded" };
+ "expanded",
+ "extraexpanded",
+ "ultraexpanded" };
static char *common_adstyle[] =
{ "serif",
"",
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
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;
-}
-
-
\f
/* Font selector. */
continue;
}
}
+ font->encoding = encoding;
return encoding;
}
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. */
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;
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;
}
> 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],
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;
+}
+
\f
/* 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;
Msize = msymbol ("size");
Mresolution = msymbol ("resolution");
+ Mfontfile = msymbol ("fontfile");
Mfontconfig = msymbol ("fontconfig");
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++)
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
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])
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)
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;
}
int i;
MSymbol spec_list[MFONT_REGISTRY + 1];
MSymbol registry;
+ char *reg;
MFONT_INIT (spec);
memset (spec_list, 0, sizeof spec_list);
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
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);
}
+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
}
+/* KEY <= MFONT_REGISTRY */
+
void
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
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 */
MSymbol Msize;
/***en
+ @brief Key of font property specifying file name.
+
+ The variable #Mfontfile is a symbol of name <tt>"fontfile"</tt>
+ 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 ¤Ï <tt>"fontfile"</tt> ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢
+ ¤ê¡¢¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤Î¥¡¼¤È¤·¤ÆÍѤ¤¤é¤ì¤ë¡£Ãͤϡ¢¥Õ¥©¥ó¥È¥Õ¥¡¥¤
+ ¥ë̾¤ò̾Á°¤È¤·¤Æ»ý¤Ä¤È¤¹¤ë¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£ */
+
+MSymbol Mfontfile;
+
+/***en
@brief Key of font property specifying resolution.
The variable #Mresolution is a symbol of name <tt>"resolution"</tt> and
#ifdef HAVE_FONTCONFIG
else if (format == Mfontconfig)
name = mfont__ft_unparse_name (font);
-#endif
+
+#endif /* HAVE_FONTCONFIG */
else
MERROR (MERROR_FONT, NULL);
return name;
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
/***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)
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)
int resy = font->property[MFONT_RESY];
return (void *) resy;
}
-
+ if (key == Mfontfile)
+ return (void *) font->file;
MERROR (MERROR_FONT, NULL);
}
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);
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++)
{
}
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;
}
*/
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;
}
/*=*/
MFont request = *font;
mfont__resize (font, &request);
- return (font->property[MFONT_SIZE] * 100 / request.property[MFONT_SIZE]);
+ return (font->size * 100 / request.size);
}
/*=*/
@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.
@brief ¥Õ¥©¥ó¥È¤Î¥ê¥¹¥È¤òÆÀ¤ë
´Ø¿ô mfont_list () ¤Ï¥Õ¥ì¡¼¥à $FRAME ¤ÇÍøÍѲÄǽ¤Ê¥Õ¥©¥ó¥È¤Î¥ê¥¹¥È¤òÊÖ¤¹¡£
- $FONT ¤¬ @c Mnil ¤Ç¤Ê¤±¤ì¤Ð¡¢$FONT ¤È¹çÃפ¹¤ëÍøÍѲÄǽ¤Ê¥Õ¥©¥ó¥È¤Î¥ê¥¹¥È¤òÊÖ¤¹¡£
+ $FONT ¤¬ NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢$FONT ¤È¹çÃפ¹¤ëÍøÍѲÄǽ¤Ê¥Õ¥©¥ó¥È¤Î¥ê¥¹¥È¤òÊÖ¤¹¡£
$LANGUAGE ¤¬ @c Mnil ¤Ç¤Ê¤±¤ì¤Ð¡¢$LANGUAGE ¤ò¥µ¥Ý¡¼¥È¤¹¤ëÍøÍѲÄǽ¤Ê¥Õ¥©¥ó¥È¤Î¥ê¥¹¥È¤òÊÖ¤¹¡£
$MAXNUM ¤Ï¡¢0 ¤è¤êÂ礤¤¾ì¹ç¤Ë¤Ï¡¢ÊÖ¤¹¥Õ¥©¥ó¥È¤Î¿ô¤Î¾å¸Â¤Ç¤¢¤ë¡£
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 */
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);
-}
-
/*** @} */
/*