(mfont__get_capability): Setup cap->otf.
[m17n/m17n-lib.git] / src / font.c
1 /* font.c -- font module.
2    Copyright (C) 2003, 2004, 2005, 2006
3      National Institute of Advanced Industrial Science and Technology (AIST)
4      Registration Number H15PRO112
5
6    This file is part of the m17n library.
7
8    The m17n library is free software; you can redistribute it and/or
9    modify it under the terms of the GNU Lesser General Public License
10    as published by the Free Software Foundation; either version 2.1 of
11    the License, or (at your option) any later version.
12
13    The m17n library is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    Lesser General Public License for more details.
17
18    You should have received a copy of the GNU Lesser General Public
19    License along with the m17n library; if not, write to the Free
20    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
21    02111-1307, USA.  */
22
23 /***en
24     @addtogroup m17nFont
25     @brief Font object.
26
27     The m17n GUI API represents a font by an object of the type @c
28     MFont.  A font can have @e font @e properties.  Like other types
29     of properties, a font property consists of a key and a value.  The
30     key of a font property must be one of the following symbols:
31
32     @c Mfoundry, @c Mfamily, @c Mweight, @c Mstyle, @c Mstretch,
33     @c Madstyle, @c Mregistry, @c Msize, @c Mresolution, @c Mspacing.
34
35     When the key of a font property is @c Msize or @c Mresolution, its
36     value is an integer.  Otherwise the value is a symbol.  
37
38     "The font property that belongs to font F and whose key is @c
39     Mxxx" may be shortened to "the xxx property of F".
40
41     The value of a foundry property is a symbol representing font
42     foundry information, e.g. adobe, misc, etc.
43
44     The value of a family property is a symbol representing font family
45     information, e.g. times, helvetica, etc.
46
47     The value of a weight property is a symbol representing weight
48     information, e.g. normal, bold, etc.
49
50     The value of a style property is a symbol representing slant
51     information, e.g. normal, italic, etc.
52
53     The value of a stretch property is a symbol representing width
54     information, e.g. normal, semicondensed, etc.
55
56     The value of an adstyle property is a symbol representing abstract
57     font family information, e.g. serif, sans-serif, etc.
58
59     The value of a registry property is a symbol representing registry
60     information, e.g. iso10646-1, iso8895-1, etc.
61
62     The value of a size property is an integer representing design
63     size in the unit of 1/10 point.
64
65     The value of a resolution property is an integer representing
66     assumed device resolution in the unit of dots per inch (dpi).
67
68     The value of a type property is a symbol indicating a font driver;
69     currently Mx or Mfreetype.
70
71     The m17n library uses font objects for two purposes: to receive
72     font specification from an application program, and to present
73     available fonts to an application program.  When the m17n library
74     presents an available font to an application program, all font
75     properties have a concrete value.
76
77     The m17n library supports three kinds of fonts: Window system fonts,
78     FreeType fonts, and OpenType fonts.
79
80     <ul>
81
82     <li> Window system fonts
83
84     The m17n-X library supports all fonts handled by an X server and
85     an X font server.  The correspondence between XLFD fields and font
86     properties are shown below.
87
88 @verbatim
89     XLFD field                                  property
90     ---------------                             --------
91     FOUNDRY                                     foundry
92     FAMILY_NAME                                 family
93     WEIGHT_NAME                                 weight
94     SLANT                                       style
95     SETWIDTH_NAME                               stretch
96     ADD_STYLE_NAME                              adstyle
97     PIXEL_SIZE                                  size
98     RESOLUTION_Y                                resolution
99     CHARSET_REGISTRY-CHARSET_ENCODING           registry
100 @endverbatim
101
102     XLFD fields not listed in the above table are ignored.
103
104     <li> FreeType fonts
105
106     The m17n library, if configured to use the FreeType library,
107     supports all fonts that can be handled by the FreeType library.
108     The variable #mfont_freetype_path is initialized properly according
109     to the configuration of the m17n library and the environment
110     variable @c M17NDIR.  See the documentation of the variable for
111     details.
112
113     If the m17n library is configured to use the fontconfig library,
114     in addition to #mfont_freetype_path, all fonts available via
115     fontconfig are supported.
116
117     The family name of a FreeType font corresponds to the family
118     property.  Style names of FreeType fonts correspond to the weight,
119     style, and stretch properties as below.
120
121 @verbatim
122     style name          weight  style   stretch
123     ----------          ------  -----   -------
124     Regular             medium  r       normal
125     Italic              medium  i       normal
126     Bold                bold    r       normal
127     Bold Italic         bold    i       normal
128     Narrow              medium  r       condensed
129     Narrow Italic       medium  i       condensed
130     Narrow Bold         bold    r       condensed
131     Narrow Bold Italic  bold    i       condensed
132     Black               black   r       normal
133     Black Italic        black   i       normal
134     Oblique             medium  o       normal
135     BoldOblique         bold    o       normal
136 @endverbatim
137
138     Style names not listed in the above table are treated as
139     "Regular".
140
141     Combination of a platform ID and an encoding ID corresponds to the
142     registry property.  For example, if a font has the combination (1
143     1), the registry property is 1-1.  Some frequent combinations have
144     a predefined registry property as below.
145
146 @verbatim
147     platform ID         encoding ID     registry property
148     -----------         -----------     -----------------
149     0                   3               unicode-bmp
150     0                   4               unicode-full
151     1                   0               apple-roman
152     3                   1               unicode-bmp
153     3                   1               unicode-full
154 @endverbatim
155
156     Thus, a font that has two combinations (1 0) and (3 1) corresponds
157     to four font objects whose registries are 1-0, apple-roman, 3-1,
158     and unicode-bmp.
159
160     <li> OpenType fonts 
161
162     The m17n library, if configured to use both the FreeType library
163     and the OTF library, supports any OpenType fonts.  The list of
164     actually available fonts is created in the same way as in the case
165     of FreeType fonts.  If a fontset instructs to use an OpenType font
166     via an FLT (Font Layout Table), and the FLT has an OTF-related
167     command (e.g. otf:deva), the OTF library converts a character
168     sequence to a glyph code sequence according to the OpenType layout
169     tables of the font, and the FreeType library gives a bitmap image
170     for each glyph.
171
172     </ul>
173
174   */
175
176 /***ja
177     @addtogroup m17nFont
178     @brief ¥Õ¥©¥ó¥È¥ª¥Ö¥¸¥§¥¯¥È.
179
180     m17n GUI API ¤Ï¥Õ¥©¥ó¥È¤ò @c MFont ·¿¤Î¥ª¥Ö¥¸¥§¥¯¥È¤È¤·¤Æɽ¸½¤¹¤ë¡£
181     ¥Õ¥©¥ó¥È¤Ï @e ¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£ ¤ò»ý¤Ä¤³¤È¤¬¤Ç¤­¤ë¡£Â¾¤Î¥¿¥¤¥×¤Î¥×
182     ¥í¥Ñ¥Æ¥£Æ±ÍÍ¡¢¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤Ï¥­¡¼¤ÈÃͤ«¤é¤Ê¤ê¡¢¥­¡¼¤Ï°Ê²¼¤Î¥·
183     ¥ó¥Ü¥ë¤Î¤¤¤º¤ì¤«¤Ç¤¢¤ë¡£
184
185     @c Mfoundry, @c Mfamily, @c Mweight, @c Mstyle, @c Mstretch,
186     @c Madstyle, @c Mregistry, @c Msize, @c Mresolution, @c Mspacing
187
188     ¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼¤¬ @c Msize ¤¢¤ë¤¤¤Ï @c Mresolution 
189     ¤Î¾ì¹ç¡¢ÃͤÏÀ°¿ôÃͤǤ¢¤ê¡¢¥­¡¼¤¬¤½¤ì°Ê³°¤Î¾ì¹ç¡¢Ãͤϥ·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£
190
191     ¡Ö¥Õ¥©¥ó¥È F ¤Î¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¥­¡¼¤¬ @c Mxxx 
192     ¤Ç¤¢¤ë¤â¤Î¡×¤Î¤³¤È¤ò´Êñ¤Ë¡ÖF ¤Î xxx ¥×¥í¥Ñ¥Æ¥£¡×¤È¸Æ¤Ö¤³¤È¤¬¤¢¤ë¡£
193
194     foundry ¥×¥í¥Ñ¥Æ¥£¤ÎÃͤϡ¢adobe, misc 
195     Åù¤Î¥Õ¥©¥ó¥È¤Î³«È¯¸µ¾ðÊó¤ò¼¨¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£
196
197     family ¥×¥í¥Ñ¥Æ¥£¤ÎÃͤϡ¢times, helvetica 
198     Åù¤Î¥Õ¥©¥ó¥È¥Õ¥¡¥ß¥ê¡¼¤ò¼¨¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£
199
200     weight ¥×¥í¥Ñ¥Æ¥£¤ÎÃͤϡ¢normal, bold Åù¤ÎÂÀ¤µ¤Ë´Ø¤¹¤ë¾ðÊó¤ò¼¨¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£
201
202     style ¥×¥í¥Ñ¥Æ¥£¤ÎÃͤϡ¢normal, italic 
203     Åù¤Î¥¹¥¿¥¤¥ë¤Ë´Ø¤¹¤ë¾ðÊó¤ò¼¨¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£
204
205     stretch ¥×¥í¥Ñ¥Æ¥£¤ÎÃͤϡ¢normal, semicondensed 
206     Åù¤Îʸ»úÉý¤Ë´Ø¤¹¤ë¾ðÊó¤ò¼¨¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£
207
208     adstyle ¥×¥í¥Ñ¥Æ¥£¤ÎÃͤϡ¢serif, sans-serif
209     Åù¤ÎÃê¾ÝŪ¤Ê¥Õ¥©¥ó¥È¥Õ¥¡¥ß¥ê¡¼¤Ë´Ø¤¹¤ë¾ðÊó¤ò¼¨¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£
210
211     registry ¥×¥í¥Ñ¥Æ¥£¤ÎÃͤϡ¢iso10646, iso8895-1
212     Åù¤Î¥ì¥¸¥¹¥È¥ê¾ðÊó¤ò¼¨¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£
213
214     size ¥×¥í¥Ñ¥Æ¥£¤ÎÃͤϡ¢¥Õ¥©¥ó¥È¤Î¥Ç¥¶¥¤¥ó¥µ¥¤¥º¤òɽ¤ï¤¹À°¿ôÃͤǤ¢¤ê¡¢
215     Ã±°Ì¤Ï1/10 ¥Ý¥¤¥ó¥È¤Ç¤¢¤ë¡£
216
217     resolution ¥×¥í¥Ñ¥Æ¥£¤ÎÃͤϡ¢ÁÛÄꤵ¤ì¤Æ¤¤¤ë¥Ç¥Ð¥¤¥¹¤Î²òÁüÅÙ¤òɽ¤ï¤¹
218     À°¿ôÃͤǤ¢¤ê¡¢Ã±°Ì¤Ïdots per inch (dpi) ¤Ç¤¢¤ë¡£
219
220     type ¥×¥í¥Ñ¥Æ¥£¤ÎÃͤϡ¢¥Õ¥©¥ó¥È¥É¥é¥¤¥Ð¤ò»Ø¼¨¤·¡¢¸½ºß Mx ¤â¤·¤¯¤Ï
221     Mfreetype ¤Ç¤¢¤ë¡£
222
223     m17n ¥é¥¤¥Ö¥é¥ê¤Ï¥Õ¥©¥ó¥È¥ª¥Ö¥¸¥§¥¯¥È¤ò£²¤Ä¤ÎÌÜŪ¤ÇÍѤ¤¤Æ¤¤¤ë¡£¥¢¥×
224     ¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥à¤«¤é¥Õ¥©¥ó¥È¤Î»ØÄê¤ò¼õ¤±¼è¤ëÌÜŪ¤È¡¢¥¢¥×¥ê¥±¡¼
225     ¥·¥ç¥ó¥×¥í¥°¥é¥à¤ËÍøÍѲÄǽ¤Ê¥Õ¥©¥ó¥È¤òÄ󼨤¹¤ëÌÜŪ¤Ç¤¢¤ë¡£¥¢¥×¥ê¥±¡¼
226     ¥·¥ç¥ó¥×¥í¥°¥é¥à¤ËÂФ·¤ÆÄ󼨤ò¹Ô¤¦ºÝ¤Ë¤Ï¡¢¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤Ï¤¹¤Ù
227     ¤Æ¶ñÂÎŪ¤ÊÃͤò»ý¤Ä¡£
228
229     m17n ¥é¥¤¥Ö¥é¥ê¤Ï Window ¥·¥¹¥Æ¥à¥Õ¥©¥ó¥È¡¢FreeType¥Õ¥©¥ó¥È¡¢
230     OpenType¥Õ¥©¥ó¥È¤Î£³¼ïÎà¤ò¥µ¥Ý¡¼¥È¤·¤Æ¤¤¤ë¡£
231
232     <ul>
233
234     <li> Window ¥·¥¹¥Æ¥à¥Õ¥©¥ó¥È
235
236     m17n X ¥é¥¤¥Ö¥é¥ê¤Ï¡¢X ¥µ¡¼¥Ð¤È X ¥Õ¥©¥ó¥È¥µ¡¼¥Ð¤¬¼è¤ê°·¤¦Á´¤Æ¤Î¥Õ¥©¥ó¥È¤ò¥µ¥Ý¡¼¥È¤¹¤ë¡£
237     XLFD ¤Î³Æ¥Õ¥£¡¼¥ë¥É¤È¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤ÎÂбþ¤Ï°Ê²¼¤ÎÄ̤ꡣ¤³¤Îɽ¤Ë¤Ê¤¤¥Õ¥£¡¼¥ë¥É¤Ï̵»ë¤µ¤ì¤ë¡£
238
239 @verbatim
240     XLFD ¥Õ¥£¡¼¥ë¥É                             ¥×¥í¥Ñ¥Æ¥£
241     ---------------                             --------
242     FOUNDRY                                     foundry
243     FAMILY_NAME                                 family
244     WEIGHT_NAME                                 weight
245     SLANT                                       style
246     SETWIDTH_NAME                               stretch
247     ADD_STYLE_NAME                              adstyle
248     PIXEL_SIZE                                  size
249     RESOLUTION_Y                                resolution
250     CHARSET_REGISTRY-CHARSET_ENCODING           registry
251 @endverbatim
252
253     <li> FreeType fonts
254
255     m17n ¥é¥¤¥Ö¥é¥ê¤Ï¡¢FreeType ¥é¥¤¥Ö¥é¥ê¤ò»È¤¦¤è¤¦¤ËÀßÄꤵ¤ì¤¿¾ì¹ç¤Ë¤Ï¡¢
256     FreeType ¤¬°·¤¦¤¹¤Ù¤Æ¤Î¥Õ¥©¥ó¥È¤ò¥µ¥Ý¡¼¥È¤¹¤ë¡£ÊÑ¿ô 
257     #mfont_freetype_path ¤Ï m17n ¥é¥¤¥Ö¥é¥ê¤ÎÀßÄê¤È´Ä¶­ÊÑ¿ô @c M17NDIR 
258     ¤Ë±þ¤¸¤Æ½é´ü²½¤µ¤ì¤ë¡£¾ÜºÙ¤ÏÊÑ¿ô¤ÎÀâÌÀ¤ò»²¾È¤Î¤³¤È¡£
259
260     ¤â¤· m17n ¥é¥¤¥Ö¥é¥ê¤¬ fontconfig ¥é¥¤¥Ö¥é¥ê¤ò»È¤¦¤è¤¦¤ËÀßÄꤵ¤ì¤¿¾ì¹ç¤Ë¤Ï¡¢
261     #mfont_freetype_path ¤Ë²Ã¤¨¤Æ¡¢ fontconfig ¤Ç»ÈÍѲÄǽ¤Ê¥Õ¥©¥ó¥È¤â¤¹¤Ù¤Æ¥µ¥Ý¡¼¥È¤µ¤ì¤ë¡£
262
263     FreeType ¥Õ¥©¥ó¥È¤Î¥Õ¥¡¥ß¥ê̾¤Ï family ¥×¥í¥Ñ¥Æ¥£¤ËÂбþ¤¹¤ë¡£
264     FreeType ¥Õ¥©¥ó¥È¤Î¥¹¥¿¥¤¥ë̾¤Ï¡¢²¼¤Îɽ¤Î¤è¤¦¤Ë weight, style,
265     stretch ¥×¥í¥Ñ¥Æ¥£¤ËÂбþ¤¹¤ë¡£
266
267 @verbatim
268     ¥¹¥¿¥¤¥ë̾          weight  style   stretch
269     ----------          ------  -----   -------
270     Regular             medium  r       normal
271     Italic              medium  i       normal
272     Bold                bold    r       normal
273     Bold Italic         bold    i       normal
274     Narrow              medium  r       condensed
275     Narrow Italic       medium  i       condensed
276     Narrow Bold         bold    r       condensed
277     Narrow Bold Italic  bold    i       condensed
278     Black               black   r       normal
279     Black Italic        black   i       normal
280     Oblique             medium  o       normal
281     BoldOblique         bold    o       normal
282 @endverbatim
283
284     ¾å¤Îɽ¤Ë¸½¤ï¤ì¤Ê¤¤¥¹¥¿¥¤¥ë̾¤Ï "Regular" ¤È¤·¤Æ°·¤ï¤ì¤ë¡£
285
286     platform ID ¤È encoding ID ¤ÎÁȤ߹ç¤ï¤»¤¬ registry 
287     ¥×¥í¥Ñ¥Æ¥£¤ËÂбþ¤¹¤ë¡£¤¿¤È¤¨¤Ð¤¢¤ë¥Õ¥©¥ó¥È¤¬ (1 1) ¤È¤¤¤¦ ID ¤ÎÁȹ礻¤ò»ý¤Æ¤Ð¡¢
288     registry ¥×¥í¥Ñ¥Æ¥£¤Ï 1-1 ¤È¤Ê¤ë¡£ÉÑÈˤˤ¢¤é¤ï¤ì¤ëÁȹ礻¤Ë¤Ï°Ê²¼¤Î¤è¤¦¤ÊÄêµÁºÑ¤ß
289     registry ¥×¥í¥Ñ¥Æ¥£ ¤¬Í¿¤¨¤é¤ì¤Æ¤¤¤ë¡£
290
291 @verbatim
292     platform ID         encoding ID     registry ¥×¥í¥Ñ¥Æ¥£
293     -----------         -----------     -----------------
294     0                   3               unicode-bmp
295     0                   4               unicode-full
296     1                   0               apple-roman
297     3                   1               unicode-bmp
298     3                   1               unicode-full
299 @endverbatim
300
301     ¤·¤¿¤¬¤Ã¤Æ¡¢Æó¤Ä¤ÎÁȹ礻 (1 0) ¡¢(3 1) ¤ò»ý¤Ä¥Õ¥©¥ó¥È¤Ï¡¢¤½¤ì¤¾¤ì
302     registry ¥×¥í¥Ñ¥Æ¥£¤¬ 1-0, apple-roman, 3-1, unicode-bmp
303     ¤Ç¤¢¤ë£´¤Ä¤Î¥Õ¥©¥ó¥È¥ª¥Ö¥¸¥§¥¯¥È¤ËÂбþ¤¹¤ë¡£
304
305     <li> OpenType ¥Õ¥©¥ó¥È
306
307     m17n ¥é¥¤¥Ö¥é¥ê¤Ï¡¢FreeType ¥é¥¤¥Ö¥é¥ê¤È OTF 
308     ¥é¥¤¥Ö¥é¥ê¤ò»ÈÍѤ¹¤ë¤è¤¦¤ËÀßÄꤹ¤ì¤Ð¡¢¤¹¤Ù¤Æ¤Î OpenType 
309     ¥Õ¥©¥ó¥È¤ò¥µ¥Ý¡¼¥È¤¹¤ë¡£¼ÂºÝ¤ËÍøÍѤǤ­¤ë¥Õ¥©¥ó¥È¤Î¥ê¥¹¥È¤Ï FreeType
310     ¥Õ¥©¥ó¥È¤Î¾ì¹ç¤ÈƱÍͤ˺î¤é¤ì¤ë¡£OpenType ¥Õ¥©¥ó¥È¤ò FLT (Font Layout Table)
311     ·Ðͳ¤Ç»ÈÍѤ¹¤ë¤è¤¦¥Õ¥©¥ó¥È¥»¥Ã¥È¤Ë»ØÄꤵ¤ì¤Æ¤ª¤ê¡¢FLT ¤Ë OTF 
312     ´ØÏ¢¤Î¥³¥Þ¥ó¥É (¤¿¤È¤¨¤Ð otf:deva) ¤¬¤¢¤ì¤Ð¡¢OTF ¥é¥¤¥Ö¥é¥ê¤¬¥Õ¥©¥ó¥È¤Î OpenType
313     ¥ì¥¤¥¢¥¦¥È¥Æ¡¼¥Ö¥ë¤Ë½¾¤Ã¤Æʸ»úÎó¤ò¥°¥ê¥Õ¥³¡¼¥ÉÎó¤ËÊÑ´¹¤·¡¢FreeType
314     ¥é¥¤¥Ö¥é¥ê¤¬³Æ¥°¥ê¥Õ¤Î¥Ó¥Ã¥È¥Þ¥Ã¥×¥¤¥á¡¼¥¸¤òÄ󶡤¹¤ë¡£
315
316     </ul>
317
318 */
319
320 /*=*/
321
322 #if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE)
323 /*** @addtogroup m17nInternal
324      @{ */
325
326 #include "config.h"
327
328 #include <stdio.h>
329 #include <stdlib.h>
330 #include <string.h>
331
332 #include "m17n-gui.h"
333 #include "m17n-misc.h"
334 #include "internal.h"
335 #include "mtext.h"
336 #include "symbol.h"
337 #include "plist.h"
338 #include "charset.h"
339 #include "language.h"
340 #include "internal-gui.h"
341 #include "font.h"
342 #include "face.h"
343 #include "fontset.h"
344
345 MPlist *mfont__driver_list;
346
347 static MSymbol M_font_capability, M_font_list, M_font_list_len;
348
349 /** Indices to font properties sorted by their priority.  */
350 static int font_score_priority[] =
351   { MFONT_SIZE,
352     MFONT_WEIGHT,
353     MFONT_STYLE,
354     MFONT_STRETCH,
355     MFONT_FAMILY,
356     MFONT_ADSTYLE,
357     MFONT_FOUNDRY
358   };
359
360 #define FONT_SCORE_PRIORITY_SIZE        \
361   (sizeof font_score_priority / sizeof font_score_priority[0])
362
363 /* Indexed by a font property MFONT_XXX, and the value is how many
364    bits to shift the difference of property values.  */
365 static int font_score_shift_bits[MFONT_SIZE + 1];
366
367 /** Predefined symbols for each font property.  The order is important
368     because the function font_score () decides how well a font matches
369     with a spec by checking how close the index is.  */
370
371 static char *common_foundry[] =
372   { "misc",
373     "adobe" };
374 static char *common_family[] =
375   { "fixed",
376     "courier",
377     "helvetica",
378     "times" };
379 static char *common_weight[] =
380   { "thin"
381     "ultralight",
382     "extralight",
383     "light",
384     "demilight",
385     "book",
386     "regular",
387     "normal",
388     "medium",
389     "demibold",
390     "semibold",
391     "bold",
392     "extrabold",
393     "ultrabold",
394     "black",
395     "heavy" };
396 static char *common_style[] =
397   { "o",
398     "i",
399     "slanted",
400     "r",
401     "rslanted",
402     "ri",
403     "ro" };
404 static char *common_stretch[] =
405   { "ultracondensed",
406     "extracondensed",
407     "condensed",
408     "narrow",
409     "semicondensed",
410     "normal",
411     "semiexpanded",
412     "expanded",
413     "extraexpanded",
414     "ultraexpanded" };
415 static char *common_adstyle[] =
416   { "serif",
417     "",
418     "sans" };
419 static char *common_registry[] =
420   { "iso8859-1" };
421
422 static unsigned short font_weight_regular;
423 static unsigned short font_weight_normal;
424 static unsigned short font_weight_medium;
425
426 /* Table containing all the data above.  */
427
428 struct MFontCommonNames
429 {
430   int num;
431   char **names;
432 };
433
434 static struct MFontCommonNames font_common_names[] =
435   {
436     { sizeof (common_foundry) / sizeof (char *), common_foundry},
437     { sizeof (common_family) / sizeof (char *), common_family},
438     { sizeof (common_weight) / sizeof (char *), common_weight},
439     { sizeof (common_style) / sizeof (char *), common_style},
440     { sizeof (common_stretch) / sizeof (char *), common_stretch},
441     { sizeof (common_adstyle) / sizeof (char *), common_adstyle},
442     { sizeof (common_registry) / sizeof (char *), common_registry}
443   };
444
445
446 /** Table of available font property names.  */
447
448 MFontPropertyTable mfont__property_table[MFONT_REGISTRY + 1];
449
450
451 /** Return the numeric value of SYMBOL as the Nth font property.  */
452
453 #define FONT_PROPERTY_NUMERIC(symbol, n)        \
454   ((symbol) == Mnil                             \
455    ? 0                                          \
456    : ((int) msymbol_get ((symbol), mfont__property_table[(n)].property)))
457
458
459 /** Set the numeric value of SYMBOL as the Nth font property to NUMERIC.  */
460
461 #define SET_FONT_PROPERTY_NUMERIC(symbol, n, numeric)           \
462   msymbol_put((symbol), mfont__property_table[(n)].property,    \
463               (void *) (numeric))
464
465 \f
466 /* Font selector.  */
467
468 struct MFontEncoding {
469   MFont spec;
470   MSymbol encoding_name;
471   MCharset *encoding_charset;
472   MSymbol repertory_name;
473   MCharset *repertory_charset;
474 };
475
476 static MPlist *font_encoding_list;
477 static MFontEncoding default_encoding;
478
479 /** Load font encoding table from the data <font encoding>.
480     The data has this form:
481         (FONT-SPEC ENCODING) ...
482     where FONT-SPEC has this form:
483         ([FOUNDRY FAMILY [WEIGHT [STYLE [STRETCH [ADSTYLE]]]]] REGISTRY)
484     All elements are symbols.  */
485
486 static int
487 load_font_encoding_table ()
488 {
489   MDatabase *mdb;
490   MPlist *encoding_list, *plist, *pl, *elt;
491
492   font_encoding_list = pl = mplist ();
493
494   mdb = mdatabase_find (Mfont, msymbol ("encoding"), Mnil, Mnil);
495   if (! mdb
496       || ! (encoding_list = (MPlist *) mdatabase_load (mdb)))
497     MERROR (MERROR_FONT, -1);
498
499   MPLIST_DO (plist, encoding_list)
500     {
501       MFontEncoding *encoding;
502       MSymbol registry;
503
504       MSTRUCT_CALLOC (encoding, MERROR_FONT);
505
506       if (! MPLIST_PLIST_P (plist)
507           || (elt = MPLIST_PLIST (plist), mplist_length (elt) < 2)
508           || ! MPLIST_PLIST_P (elt))
509         MWARNING (MERROR_FONT);
510       registry = mfont__set_spec_from_plist (&encoding->spec,
511                                              MPLIST_PLIST (elt));
512       elt = MPLIST_NEXT (elt);
513       if (! MPLIST_SYMBOL_P (elt))
514         MWARNING (MERROR_FONT);
515       encoding->encoding_name = MPLIST_SYMBOL (elt);
516       elt = MPLIST_NEXT (elt);
517       if (MPLIST_TAIL_P (elt))
518         encoding->repertory_name = encoding->encoding_name;
519       else if (! MPLIST_SYMBOL_P (elt))
520         MWARNING (MERROR_FONT);
521       else
522         encoding->repertory_name = MPLIST_SYMBOL (elt);
523
524       if (registry == Mnil)
525         mplist_push (font_encoding_list, Mt, encoding);
526       else
527         pl = mplist_add (pl, registry, encoding);
528       continue;
529
530     warning:
531       free (encoding);
532     }
533
534   M17N_OBJECT_UNREF (encoding_list);
535   return 0;
536 }
537
538 typedef struct {
539   MFont spec;
540   int resize;
541 } MFontResize;
542
543 static MPlist *font_resize_list;
544
545 /** Load font size table from the data <font size>.
546     The data has this form:
547         (FONT-SPEC RESIZE-FACTOR) ...
548     where FONT-SPEC has this form:
549         ([FOUNDRY FAMILY [WEIGHT [STYLE [STRETCH [ADSTYLE]]]]] REGISTRY)
550     All elements of FONT-SPEC are symbols.  */
551
552 static int
553 load_font_resize_table ()
554 {
555   MDatabase *mdb;
556   MPlist *size_adjust_list, *plist, *pl, *elt;
557
558   font_resize_list = pl = mplist ();
559
560   mdb = mdatabase_find (Mfont, msymbol ("resize"), Mnil, Mnil);
561   if (! mdb)
562     return -1;
563   if (! (size_adjust_list = (MPlist *) mdatabase_load (mdb)))
564     MERROR (MERROR_FONT, -1);
565
566   MPLIST_DO (plist, size_adjust_list)
567     {
568       MFontResize *resize;
569       MSymbol registry;
570
571       MSTRUCT_CALLOC (resize, MERROR_FONT);
572
573       if (! MPLIST_PLIST_P (plist)
574           || (elt = MPLIST_PLIST (plist), mplist_length (elt) != 2)
575           || ! MPLIST_PLIST_P (elt))
576         MWARNING (MERROR_FONT);
577       registry = mfont__set_spec_from_plist (&resize->spec,
578                                              MPLIST_PLIST (elt));
579       elt = MPLIST_NEXT (elt);
580       if (! MPLIST_INTEGER_P (elt))
581         MWARNING (MERROR_FONT);
582       resize->resize = MPLIST_INTEGER (elt);
583
584       if (registry == Mnil)
585         registry = Mt;
586       pl = mplist_add (pl, registry, resize);
587       continue;
588
589     warning:
590       free (resize);
591     }
592
593   M17N_OBJECT_UNREF (size_adjust_list);
594   return 0;
595 }
596
597 /** Return a font encoding (and repertory) of FONT.  */
598
599 static MFontEncoding *
600 find_encoding (MFont *font)
601 {
602   MSymbol registry = FONT_PROPERTY (font, MFONT_REGISTRY);
603   MFontEncoding *encoding = NULL;
604   MPlist *plist;
605
606   if (! font_encoding_list)
607     load_font_encoding_table ();
608   plist = font_encoding_list;
609   while (! MPLIST_TAIL_P (plist))
610     {
611       encoding = (MFontEncoding *) MPLIST_VAL (plist);
612       if (mfont__match_p (font, &encoding->spec, MFONT_REGISTRY))
613         {
614           if (encoding->encoding_name != Mnil
615               && ! encoding->encoding_charset)
616             {
617               encoding->encoding_charset = MCHARSET (encoding->encoding_name);
618               if (! encoding->encoding_charset)
619                 {
620                   mplist_pop (plist);
621                   continue;
622                 }
623             }
624           if (encoding->repertory_name == encoding->encoding_name)
625             encoding->repertory_charset = encoding->encoding_charset;
626           else if (encoding->repertory_name != Mnil)
627             {
628               encoding->repertory_charset
629                 = MCHARSET (encoding->repertory_name);
630               if (! encoding->repertory_charset)
631                 {
632                   mplist_pop (plist);
633                   continue;
634                 }
635             }
636           font->encoding = encoding;
637           return encoding;
638         }
639
640       if (registry && MPLIST_KEY (plist) != Mt)
641         {
642           plist = mplist_find_by_key (plist, registry);
643           if (! plist)
644             break;
645         }
646       else
647         plist = MPLIST_NEXT (plist);
648     }
649   font->encoding = &default_encoding;
650   return &default_encoding;
651 }
652
653 #ifndef HAVE_OTF
654 static OTF_Tag
655 OTF_tag (char *name)
656 {
657   unsigned char *p = (unsigned char *) name;
658
659   if (! name)
660     return (OTF_Tag) 0;
661   return (OTF_Tag) ((p[0] << 24)
662                     | (! p[1] ? 0
663                        : ((p[1] << 16)
664                           | (! p[2] ? 0
665                              : (p[2] << 8) | p[3]))));
666 }
667 #endif  /* not HAVE_OTF */
668
669 /* XLFD parser/generator */
670
671 /** Indices to each field of split font name.  */
672
673 enum xlfd_field_idx
674   {
675     XLFD_FOUNDRY,
676     XLFD_FAMILY,
677     XLFD_WEIGHT,
678     XLFD_SLANT,
679     XLFD_SWIDTH,
680     XLFD_ADSTYLE,
681     XLFD_PIXEL,
682     XLFD_POINT,
683     XLFD_RESX,
684     XLFD_RESY,
685     XLFD_SPACING,
686     XLFD_AVGWIDTH,
687     XLFD_REGISTRY,              /* This contains ENCODING.  */
688     /* anchor */
689     XLFD_FIELD_MAX
690   };
691
692 static int
693 xlfd_parse_name (const char *name, MFont *font)
694 {
695   char *field[XLFD_FIELD_MAX];
696   unsigned short resy, avgwidth;
697   unsigned size;
698   char copy[513];
699   int i;
700   char *p;
701   MSymbol sym;
702
703   if (name[0] != '-')
704     return -1;
705
706   field[0] = copy;
707   for (i = 1, p = copy, name++; *name; p++, name++)
708     {
709       if (p - copy > 512)
710         return -1;
711       if (*name == '-'
712           && i < XLFD_FIELD_MAX)
713         {
714           *p = '\0';
715           if (field[i - 1][0] == '*')
716             field[i - 1] = NULL;
717           field[i++] = p + 1;
718         }
719       else
720         *p = tolower (*name);
721     }
722   *p = '\0';
723   if (field[i - 1][0] == '*')
724     field[i - 1] = NULL;
725   while (i < XLFD_FIELD_MAX)
726     field[i++] = NULL;
727
728   resy = field[XLFD_RESY] ? atoi (field[XLFD_RESY]) : 0;
729   avgwidth = ((field[XLFD_AVGWIDTH] && isdigit (field[XLFD_AVGWIDTH][0]))
730               ? atoi (field[XLFD_AVGWIDTH]) : 1);
731   if (! avgwidth)
732     size = 0;
733   else if (! field[XLFD_PIXEL])
734     size = field[XLFD_POINT] ? atoi (field[XLFD_POINT]) * resy / 72 : 0;
735   else if (field[XLFD_PIXEL][0] == '[')
736     {
737       /* The pixel size field specifies a transformation matrix of the
738          form "[A B C D]".  The XLFD spec says that the scalar value N
739          for the pixel size is equivalent to D.  */
740       char *p0 = field[XLFD_PIXEL] + 1, *p1;
741       double d;
742
743       for (i = 0; i < 4; i++, p0 = p1)
744         d = strtod (p0, &p1);
745       size = d * 10;
746     }
747   else
748     size = atoi (field[XLFD_PIXEL]) * 10;
749
750   if (field[XLFD_FOUNDRY])
751     {
752       sym = msymbol (field[XLFD_FOUNDRY]);
753       if (! sym)
754         sym = msymbol ("Nil");
755       mfont__set_property (font, MFONT_FOUNDRY, sym);
756     }
757   if (field[XLFD_FAMILY])
758     {
759       sym = msymbol (field[XLFD_FAMILY]);
760       if (! sym)
761         sym = msymbol ("Nil");
762       mfont__set_property (font, MFONT_FAMILY, sym);
763     }
764   if (field[XLFD_WEIGHT])
765     mfont__set_property (font, MFONT_WEIGHT, msymbol (field[XLFD_WEIGHT]));
766   if (field[XLFD_SLANT])
767     mfont__set_property (font, MFONT_STYLE, msymbol (field[XLFD_SLANT]));
768   if (field[XLFD_SWIDTH])
769     mfont__set_property (font, MFONT_STRETCH, msymbol (field[XLFD_SWIDTH]));
770   if (field[XLFD_ADSTYLE])
771     mfont__set_property (font, MFONT_ADSTYLE, msymbol (field[XLFD_ADSTYLE]));
772   font->property[MFONT_RESY] = resy;
773   font->size = size;
774   if (field[XLFD_SPACING])
775     font->spacing
776       = ((field[XLFD_SPACING][0] == 'p' || field[XLFD_SPACING][0] == 'P')
777          ? MFONT_SPACING_PROPORTIONAL
778          : (field[XLFD_SPACING][0] == 'm' || field[XLFD_SPACING][0] == 'M')
779          ? MFONT_SPACING_MONO : MFONT_SPACING_CHARCELL);
780   if (field[XLFD_REGISTRY])
781     mfont__set_property (font, MFONT_REGISTRY, msymbol (field[XLFD_REGISTRY]));
782   font->type = MFONT_TYPE_SPEC;
783   font->source = MFONT_SOURCE_X;
784   return 0;
785 }
786
787 static char *
788 xlfd_unparse_name (MFont *font, int full_xlfd)
789 {
790   MSymbol prop[7];
791   char name[513];
792   char *str[7];
793   int len, i;
794   char spacing;
795   int size, resy;
796   int all_nil = 1;
797
798   prop[0] = (MSymbol) mfont_get_prop (font, Mfoundry);
799   prop[1] = (MSymbol) mfont_get_prop (font, Mfamily);
800   prop[2] = (MSymbol) mfont_get_prop (font, Mweight);
801   prop[3] = (MSymbol) mfont_get_prop (font, Mstyle);
802   prop[4] = (MSymbol) mfont_get_prop (font, Mstretch);
803   prop[5] = (MSymbol) mfont_get_prop (font, Madstyle);
804   prop[6] = (MSymbol) mfont_get_prop (font, Mregistry);
805   for (len = 0, i = 0; i < 7; i++)
806     {
807       if (prop[i] != Mnil)
808         {
809           str[i] = msymbol_name (prop[i]);
810           len += strlen (str[i]);
811           all_nil = 0;
812         }
813       else
814         {
815           str[i] = "*";
816           len++;
817         }
818     }
819   spacing = (font->spacing == MFONT_SPACING_UNDECIDED ? '*'
820              : font->spacing == MFONT_SPACING_PROPORTIONAL ? 'p'
821              : font->spacing == MFONT_SPACING_MONO ? 'm'
822              : 'c');
823
824   if ((len
825        + 13                     /* 13 dashes */
826        + 2                      /* 2 asterisks */
827        + 30                     /* 3 integers (each 10 digits) */
828        + 1                      /* 1 spacing char */
829        + 1)                     /* '\0' terminal */
830       > 513)
831     return NULL;
832
833   resy = (int) mfont_get_prop (font, Mresolution);
834   size = font->size;
835   if (size >= 0)
836     {
837       if ((size % 10) < 5)
838         size /= 10;
839       else
840         size = size / 10 + 1;
841     }
842   else
843     size = - size;
844
845   if (full_xlfd)
846     {
847       if (font->size >= 0)
848         sprintf (name, "-%s-%s-%s-%s-%s-%s-%d-*-%d-%d-%c-*-%s",
849                  str[0], str[1], str[2], str[3], str[4], str[5],
850                  size, resy, resy, spacing, str[6]);
851       else
852         sprintf (name, "-%s-%s-%s-%s-%s-%s-*-%d-%d-%d-%c-*-%s",
853                  str[0], str[1], str[2], str[3], str[4], str[5],
854                  size, resy, resy, spacing, str[6]);
855     }
856   else if (all_nil && size == 0)
857     sprintf (name, "*");
858   else
859     {
860       char *p = name;
861
862       p += sprintf (p, "-%s", str[0]);
863       for (i = 1; i < 6; i++)
864         if (p[-1] != '*' || str[i][0] != '*')
865           p += sprintf (p, "-%s", str[i]);
866       if (p[-1] != '*' || font->size > 0)
867         {
868           if (font->size > 0)
869             p += sprintf (p, "-%d-*", size);
870           else
871             p += sprintf (p, "-*");
872         }
873       if (str[6][0] != '*')
874         sprintf (p, "-%s", str[6]);
875     }
876
877   return strdup (name);
878 }
879
880 /* Compare FONT with REQUEST and return how much they differs.  */
881
882 static int
883 font_score (MFont *font, MFont *request)
884 {
885   int score = 0;
886   int i = FONT_SCORE_PRIORITY_SIZE;
887
888   while (--i >= 0)
889     {
890       enum MFontProperty prop = font_score_priority[i];
891       int val;
892
893       if (prop == MFONT_SIZE)
894         {
895           if (font->size && request->size)
896             {
897               val = font->size - request->size;
898               if (val)
899                 {
900                   if (val < 0)
901                     val = - val;
902                   if (val >= 0x10000)
903                     val = 0xFFFF;
904                   score |= (val << font_score_shift_bits[MFONT_SIZE]);
905                 }
906             }
907         }
908       else if (font->property[prop] && request->property[prop]
909                && font->property[prop] != request->property[prop])
910         {
911           if (prop <= MFONT_FAMILY)
912             val = 1;
913           else if (prop == MFONT_WEIGHT)
914             {
915               unsigned short v1 = font->property[prop];
916               unsigned short v2 = request->property[prop];
917
918               if (v1 == font_weight_regular || v1 == font_weight_normal)
919                 v1 = font_weight_medium;
920               if (v2 == font_weight_regular || v2 == font_weight_normal)
921                 v2 = font_weight_medium;
922               val = v1 > v2 ? v1 - v2 : v2 - v1;
923             }
924           else
925             {
926               val = font->property[prop] - request->property[prop];
927               if (val < 0)
928                 val = - val;
929               if (val > 3)
930                 val = 3;
931             }
932           score |= val << font_score_shift_bits[prop];
933         }
934     }
935   if (request->file != Mnil && request->file != font->file)
936     score |= 40000000;
937   return score;
938 }
939
940 static MSymbol
941 merge_capability (MSymbol capability, MSymbol key, MSymbol val, int overwrite)
942 {
943   MFontCapability *cap = NULL;
944   char *lang = NULL, *script = NULL, *otf = NULL, *buf, *p;
945   int lang_len = 0, script_len = 0, otf_len = 0;
946
947   if (key == Mlanguage)
948     lang = MSYMBOL_NAME (val), lang_len = MSYMBOL_NAMELEN (val) + 6;
949   else if (key == Mscript)
950     script = MSYMBOL_NAME (val), script_len = MSYMBOL_NAMELEN (val) + 7;
951   else if (key == Motf)
952     otf = MSYMBOL_NAME (val), otf_len = MSYMBOL_NAMELEN (val) + 5;
953   else
954     return capability;
955
956   if (capability != Mnil)
957     {
958       cap = mfont__get_capability (capability);
959       if (! overwrite)
960         {
961           if (cap->language)
962             lang = NULL;
963           if (cap->script)
964             script = NULL;
965           if (cap->script_tag)
966             otf = NULL;
967           if (! lang && !script && !otf)
968             return capability;
969         }
970     }
971
972   if (! lang && cap && cap->language)
973     {
974       lang_len = MSYMBOL_NAMELEN (cap->language);
975       lang = MSYMBOL_NAME (cap->language);
976     }
977   if (! script && cap && cap->script != Mnil)
978     {
979       script_len = MSYMBOL_NAMELEN (cap->script);
980       script = MSYMBOL_NAME (cap->script);
981     }
982   if (! otf && cap && cap->script_tag)
983     {
984       int i;
985
986       otf_len = 4;                      /* for script_tag */
987       if (cap->langsys_tag)
988         otf_len += 5;           /* for "/XXXX */
989       for (i = 0; i < MFONT_OTT_MAX; i++)
990         if (cap->features[i].str)
991           otf_len += strlen (cap->features[i].str) + 1; /* for "[=+]..." */
992       otf = p = alloca (otf_len + 1);
993       OTF_tag_name (cap->script_tag, otf);
994       p += 4;
995       if (cap->langsys_tag)
996         {
997           *p++ = '/';
998           OTF_tag_name (cap->langsys_tag, p);
999           p += 4;
1000         }
1001       if (cap->features[MFONT_OTT_GSUB].str)
1002         p += sprintf (p, "=%s", cap->features[MFONT_OTT_GSUB].str);
1003       if (cap->features[MFONT_OTT_GPOS].str)
1004         p += sprintf (p, "=%s", cap->features[MFONT_OTT_GSUB].str);
1005     }
1006   buf = p = alloca (lang_len + script_len + otf_len + 1);
1007   if (lang_len)
1008     p += sprintf (p, ":lang=%s", lang);
1009   if (script_len)
1010     p += sprintf (p, ":script=%s", script);
1011   if (otf_len)
1012     p += sprintf (p, ":otf=%s", otf);
1013   return msymbol (buf);
1014 }
1015
1016 \f
1017 /* Internal API */
1018
1019 MSymbol Miso8859_1, Miso10646_1, Municode_bmp, Municode_full, Mapple_roman;
1020
1021 int
1022 mfont__init ()
1023 {
1024   int i, shift;
1025   MSymbol regular = msymbol ("regular");
1026   MSymbol normal = msymbol ("normal");
1027   MSymbol medium = msymbol ("medium");
1028
1029   M_font_capability = msymbol_as_managing_key ("  font-capability");
1030   M_font_list = msymbol_as_managing_key ("  font-list");
1031   M_font_list_len = msymbol ("  font-list-len");
1032
1033   Mfoundry = msymbol ("foundry");
1034   mfont__property_table[MFONT_FOUNDRY].property = Mfoundry;
1035   Mfamily = msymbol ("family");
1036   mfont__property_table[MFONT_FAMILY].property = Mfamily;
1037   Mweight = msymbol ("weight");
1038   mfont__property_table[MFONT_WEIGHT].property = Mweight;
1039   Mstyle = msymbol ("style");
1040   mfont__property_table[MFONT_STYLE].property = Mstyle;
1041   Mstretch = msymbol ("stretch");
1042   mfont__property_table[MFONT_STRETCH].property = Mstretch;
1043   Madstyle = msymbol ("adstyle");
1044   mfont__property_table[MFONT_ADSTYLE].property = Madstyle;
1045   Mregistry = msymbol ("registry");
1046   mfont__property_table[MFONT_REGISTRY].property = Mregistry;
1047
1048   Mspacing = msymbol ("spacing");
1049   Msize = msymbol ("size");
1050   Mresolution = msymbol ("resolution");
1051   Mmax_advance = msymbol ("max-advance");
1052   Mfontfile = msymbol ("fontfile");
1053
1054   Mfontconfig = msymbol ("fontconfig");
1055
1056   Mx = msymbol ("x");
1057   Mfreetype = msymbol ("freetype");
1058   Mxft = msymbol ("xft");
1059
1060   Miso8859_1 = msymbol ("iso8859-1");
1061   Miso10646_1 = msymbol ("iso10646-1");
1062   Municode_bmp = msymbol ("unicode-bmp");
1063   Municode_full = msymbol ("unicode-full");
1064   Mapple_roman = msymbol ("apple-roman");
1065
1066   Motf = msymbol ("otf");
1067
1068   /* The first entry of each mfont__property_table must be Mnil so
1069      that actual properties get positive numeric numbers.  */
1070   for (i = 0; i <= MFONT_REGISTRY; i++)
1071     {
1072       MLIST_INIT1 (&mfont__property_table[i], names, 8);
1073       MLIST_APPEND1 (&mfont__property_table[i], names, Mnil, MERROR_FONT);
1074     }
1075
1076   /* Register predefined font property names.  */
1077   for (i = 0; i <= MFONT_REGISTRY; i++)
1078     {
1079       int j;
1080
1081       for (j = 0; j < font_common_names[i].num; j++)
1082         {
1083           MSymbol sym = msymbol (font_common_names[i].names[j]);
1084
1085           if (sym == Mnil)
1086             return -1;
1087           if (msymbol_put (sym, mfont__property_table[i].property,
1088                            (void *) (j + 1)) < 0)
1089             return -1;
1090           MLIST_APPEND1 (&mfont__property_table[i], names, sym,
1091                          MERROR_FONT);
1092           if (i == MFONT_WEIGHT)
1093             {
1094               if (sym == regular)
1095                 font_weight_regular = j + 1;
1096               else if (sym == normal)
1097                 font_weight_normal = j + 1;
1098               else if (sym == medium)
1099                 font_weight_medium = j + 1;
1100             }
1101         }
1102     }
1103
1104   /* Here, SHIFT starts from 1, not 0.  This is because the lowest bit
1105      of a score is a flag for a scalable font (see the documentation
1106      of font_score).  */
1107   i = FONT_SCORE_PRIORITY_SIZE - 1;
1108   for (shift = 1; i >= 0; i--)
1109     {
1110       font_score_shift_bits[font_score_priority[i]] = shift;
1111       if (font_score_priority[i] == MFONT_SIZE)
1112         shift += 16;
1113       else if (font_score_priority[i] <= MFONT_FAMILY)
1114         shift++;
1115       else
1116         shift += 2;
1117     }
1118
1119   MFONT_INIT (&default_encoding.spec);
1120   default_encoding.encoding_name = Municode_full;
1121   default_encoding.encoding_charset = mcharset__unicode;
1122   default_encoding.repertory_name = Mnil;
1123   default_encoding.repertory_charset = NULL;
1124   {
1125     char *path, *buf;
1126     int bufsize;
1127     USE_SAFE_ALLOCA;
1128
1129     mfont_freetype_path = mplist ();
1130     bufsize = strlen (M17NDIR) + 7;
1131     SAFE_ALLOCA (buf, bufsize);
1132     sprintf (buf, "%s/fonts", M17NDIR);
1133     mplist_add (mfont_freetype_path, Mstring, strdup (buf));
1134     path = getenv ("M17NDIR");
1135     if (path)
1136       {
1137         bufsize = strlen (path) + 7;
1138         SAFE_ALLOCA (buf, bufsize);
1139         sprintf (buf, "%s/fonts", path);
1140         mplist_push (mfont_freetype_path, Mstring, strdup (buf));
1141       }
1142     SAFE_FREE (buf);
1143   }
1144
1145 #ifdef HAVE_FREETYPE
1146   if (mfont__ft_init () < 0)
1147     return -1;
1148 #endif /* HAVE_FREETYPE */
1149   if (mfont__flt_init () < 0)
1150     return -1;
1151
1152   return 0;
1153 }
1154
1155 void
1156 mfont__fini ()
1157 {
1158   MPlist *plist;
1159   int i;
1160
1161   mfont__flt_fini ();
1162 #ifdef HAVE_FREETYPE
1163   mfont__ft_fini ();
1164 #endif /* HAVE_FREETYPE */
1165
1166   MPLIST_DO (plist, mfont_freetype_path)
1167     free (MPLIST_VAL (plist));
1168   M17N_OBJECT_UNREF (mfont_freetype_path);
1169
1170   if (font_resize_list)
1171     {
1172       MPLIST_DO (plist, font_resize_list)
1173         free (MPLIST_VAL (plist));
1174       M17N_OBJECT_UNREF (font_resize_list);
1175       font_resize_list = NULL;
1176     }
1177   if (font_encoding_list)
1178     {
1179       MPLIST_DO (plist, font_encoding_list)
1180         free (MPLIST_VAL (plist));
1181       M17N_OBJECT_UNREF (font_encoding_list);
1182       font_encoding_list = NULL;
1183     }
1184
1185   for (i = 0; i <= MFONT_REGISTRY; i++)
1186     MLIST_FREE1 (&mfont__property_table[i], names);
1187 }
1188
1189
1190 MSymbol
1191 mfont__id (MFont *font)
1192 {
1193   char *buf, *p;
1194   int i;
1195   int file_len = (font->file == Mnil ? 0 : MSYMBOL_NAMELEN (font->file));
1196   int capability_len  = (font->capability == Mnil ? 0
1197                          : MSYMBOL_NAMELEN (font->capability));
1198   int total_len = MFONT_PROPERTY_MAX * 5 + 9 + file_len + capability_len;
1199   MSymbol id;
1200   USE_SAFE_ALLOCA;
1201
1202   SAFE_ALLOCA (buf, total_len);
1203   p = buf;
1204   if (font->property[0])
1205     p += sprintf (p, "%X", font->property[0]);
1206   for (i = 1; i < MFONT_PROPERTY_MAX; i++)
1207     {
1208       if (font->property[i])
1209         p += sprintf (p, "-%X", font->property[i]);
1210       else
1211         *p++ = '-';
1212     }
1213   if (font->size)
1214     p += sprintf (p, "-%X", font->size);
1215   if (font->spacing)
1216     p += sprintf (p, "-%X", font->spacing);
1217   if (capability_len > 0)
1218     {
1219       *p++ = '-';
1220       memcpy (p, MSYMBOL_NAME (font->capability), capability_len);
1221       p += capability_len;
1222     }
1223   if (file_len > 0)
1224     {
1225       *p++ = '-';
1226       memcpy (p, MSYMBOL_NAME (font->file), file_len);
1227       p += file_len;
1228     }      
1229   id = msymbol__with_len (buf, p - buf);
1230   SAFE_FREE (buf);
1231   return id;
1232 }
1233
1234 /** Return 1 iff FONT matches SPEC.  */
1235
1236 int
1237 mfont__match_p (MFont *font, MFont *spec, int prop)
1238 {
1239   if (spec->capability != font->capability
1240       && spec->capability != Mnil && font->capability != Mnil)
1241     return 0;
1242   if (spec->file != font->file
1243       && spec->file != Mnil && font->file != Mnil)
1244     return 0;
1245   for (; prop >= 0; prop--)
1246     if (spec->property[prop] && font->property[prop]
1247         && font->property[prop] != spec->property[prop])
1248       return 0;
1249   return 1;
1250 }
1251
1252 /* Merge SRC into DST.  If error_on_conflict is nonzero and a font
1253    property differs in SRC and DST, return -1.  */
1254
1255 int
1256 mfont__merge (MFont *dst, MFont *src, int error_on_conflict)
1257 {
1258   int i;
1259
1260   for (i = 0; i < MFONT_PROPERTY_MAX; i++)
1261     {
1262       if (! dst->property[i])
1263         dst->property[i] = src->property[i];
1264       else if (error_on_conflict
1265                && src->property[i]
1266                && dst->property[i] != src->property[i])
1267         return -1;
1268     }
1269   if (! dst->spacing)
1270     dst->spacing = src->spacing;
1271   else if (error_on_conflict
1272            && src->spacing
1273            && dst->spacing != src->spacing)
1274     return -1;
1275   if (! dst->size)
1276     dst->size = src->size;
1277   else if (error_on_conflict
1278            && src->size
1279            && dst->size != src->size)
1280     return -1;
1281   if (dst->capability == Mnil)
1282     dst->capability = src->capability;
1283   else if (error_on_conflict
1284            && src->capability
1285            && dst->capability != src->capability)
1286     return -1;
1287   if (dst->file == Mnil)
1288     dst->file = src->file;
1289   else if (error_on_conflict
1290            && src->file
1291            && dst->file != src->file)
1292     return -1;
1293   return 0;
1294 }
1295
1296 void
1297 mfont__set_spec_from_face (MFont *spec, MFace *face)
1298 {
1299   int i;
1300
1301   for (i = 0; i <= MFONT_ADSTYLE; i++)
1302     mfont__set_property (spec, i, face->property[i]);
1303   spec->property[MFONT_REGISTRY] = 0;
1304   spec->property[MFONT_RESY] = 0;
1305   spec->size = (int) (face->property[MFACE_SIZE]);
1306   spec->type = MFONT_TYPE_SPEC;
1307   spec->source = MFONT_SOURCE_UNDECIDED;
1308   spec->file = spec->capability = Mnil;
1309   spec->encoding = NULL;
1310 }
1311
1312
1313 extern MSymbol
1314 mfont__set_spec_from_plist (MFont *spec, MPlist *plist)
1315 {
1316   int i;
1317   MSymbol spec_list[MFONT_REGISTRY + 1];
1318   MSymbol registry;
1319   char *reg;
1320
1321   MFONT_INIT (spec);
1322   memset (spec_list, 0, sizeof spec_list);
1323   for (i = 0; ! MPLIST_TAIL_P (plist); i++, plist = MPLIST_NEXT (plist))
1324     {
1325       if (! MPLIST_SYMBOL_P (plist))
1326         MERROR (MERROR_FONT, Mnil);     
1327       spec_list[i] = MPLIST_SYMBOL (plist);
1328     }
1329   registry = spec_list[i - 1];
1330   if (i > 1 && registry != Mnil)
1331     {
1332       reg = MSYMBOL_NAME (registry);
1333       if (reg[0] == ':')
1334         {
1335           mfont__get_capability (registry);
1336           spec->capability = registry;
1337           registry = spec_list[i - 2];
1338           i--;
1339         }
1340     }
1341   mfont__set_property (spec, MFONT_REGISTRY, registry);
1342   for (i -= 2; i >= 0; i--)
1343     mfont__set_property (spec, i, spec_list[i]);
1344   spec->type = MFONT_TYPE_SPEC;
1345
1346   return registry;
1347 }
1348
1349
1350 MFont *
1351 mfont__select (MFrame *frame, MFont *font, int max_size)
1352 {
1353   MFontDriver *driver;
1354
1355   if (font->type == MFONT_TYPE_FAILURE)
1356     return NULL;
1357   if (font->type != MFONT_TYPE_SPEC)
1358     return font;
1359   if (font->source == MFONT_SOURCE_UNDECIDED)
1360     {
1361       if (font->file != Mnil || font->capability != Mnil)
1362         font->source = MFONT_SOURCE_FT;
1363       else if (font->property[MFONT_REGISTRY])
1364         {
1365           MSymbol registry = FONT_PROPERTY (font, MFONT_REGISTRY);
1366           char *reg = MSYMBOL_NAME (registry);
1367
1368           if (strncmp (reg, "unicode-", 8) == 0
1369               || strncmp (reg, "apple-roman", 11) == 0
1370               || (reg[0] >= '0' && reg[0] <= '9' && reg[1] == '-'))
1371             font->source = MFONT_SOURCE_FT;
1372         }
1373     }
1374   if (font->source != MFONT_SOURCE_FT)
1375     {
1376       driver = mplist_get (frame->font_driver_list, Mx);
1377       if (driver)
1378         return (driver->select) (frame, font, max_size);
1379     }
1380   driver = mplist_get (frame->font_driver_list, Mfreetype);
1381   if (! driver)
1382     return NULL;
1383   return (driver->select) (frame, font, max_size);
1384 }
1385
1386
1387 int
1388 mfont__available (MFrame *frame, MFont *font)
1389 {
1390   return -1;
1391 }
1392
1393 static int
1394 compare_font_score (const void *e1, const void *e2)
1395 {
1396   MFontScore *s1 = (MFontScore *) e1, *s2 = (MFontScore *) e2;
1397
1398   return (s1->font->for_full_width == s2->font->for_full_width
1399           ? s1->score > s2->score
1400           : s1->font->for_full_width);
1401 }
1402
1403 void
1404 mdebug_dump_font_list (MFontList *font_list)
1405 {
1406   int i;
1407
1408   for (i = 0; i < font_list->nfonts; i++)
1409     {
1410       fprintf (stderr, "%04X - ", font_list->fonts[i].score);
1411       mdebug_dump_font (font_list->fonts[i].font);
1412       fprintf (stderr, "\n");
1413     }
1414 }
1415
1416 void
1417 mfont__free_realized (MRealizedFont *rfont)
1418 {
1419   MRealizedFont *next;
1420
1421   for (; rfont; rfont = next)
1422     {
1423       next = rfont->next;
1424       M17N_OBJECT_UNREF (rfont->info);
1425       free (rfont);
1426       rfont = next;
1427     }
1428 }
1429
1430 MFontList *
1431 mfont__list (MFrame *frame, MFont *spec, MFont *request, int max_size)
1432 {
1433   MFontList *list;
1434   MSymbol id = mfont__id (spec);
1435   MPlist *pl, *p;
1436   int num, i;
1437
1438   pl = msymbol_get (id, M_font_list);
1439   if (pl)
1440     num = (int) msymbol_get (id, M_font_list_len);
1441   else
1442     {
1443       pl = mplist ();
1444       num = 0;
1445       MPLIST_DO (p, frame->font_driver_list)
1446         {
1447           if (spec->source == MFONT_SOURCE_X ? MPLIST_KEY (p) == Mx
1448               : spec->source == MFONT_SOURCE_FT ? MPLIST_KEY (p) == Mfreetype
1449               : 1)
1450             {
1451               MFontDriver *driver = MPLIST_VAL (p);
1452               num += (driver->list) (frame, pl, spec, 0);
1453             }
1454         }
1455       msymbol_put (id, M_font_list, pl);
1456       M17N_OBJECT_UNREF (pl);
1457       msymbol_put (id, M_font_list_len, (void *) num);
1458     }
1459   
1460   if (num == 0)
1461     return NULL;
1462
1463   MSTRUCT_MALLOC (list, MERROR_FONT);
1464   MTABLE_MALLOC (list->fonts, num, MERROR_FONT);
1465   for (i = 0; num > 0; num--, pl = MPLIST_NEXT (pl))
1466     {
1467       MFont *font = MPLIST_VAL (pl), *adjusted = font;
1468
1469       if (max_size == 0
1470           || font->size == 0
1471           || font->size < max_size)
1472         {
1473           list->fonts[i].font = font;
1474           if (spec == request)
1475             list->fonts[i].score = 0;
1476           else
1477             {
1478               int resize_ratio;
1479               MFont resized;
1480
1481               if (font->size > 0
1482                   && (resize_ratio = mfont_resize_ratio (font)) != 100)
1483                 {
1484                   resized = *font;
1485                   resized.size = font->size * 100 / resize_ratio;
1486                   adjusted = &resized;
1487                 }
1488               list->fonts[i].score = font_score (adjusted, request);
1489             }
1490           i++;
1491         }
1492     }
1493   if (i == 0)
1494     {
1495       free (list->fonts);
1496       free (list);
1497       return NULL;
1498     }
1499   list->nfonts = i;
1500   if (spec != request)
1501     qsort (list->fonts, i, sizeof (MFontScore), compare_font_score);
1502   list->object = *spec;
1503   mfont__merge (&list->object, request, 0);
1504   list->object.type = MFONT_TYPE_OBJECT;
1505   return list;
1506 }
1507
1508 /** Open a font specified in FONT.  */
1509
1510 MRealizedFont *
1511 mfont__open (MFrame *frame, MFont *font, MFont *spec)
1512 {
1513   MFontDriver *driver;
1514   MRealizedFont *rfont;
1515
1516   if (font->source == MFONT_SOURCE_UNDECIDED)
1517     MFATAL (MERROR_FONT);
1518   if (font->type != MFONT_TYPE_OBJECT)
1519     MFATAL (MERROR_FONT);
1520   for (rfont = MPLIST_VAL (frame->realized_font_list); rfont;
1521        rfont = rfont->next)
1522     {
1523       driver = rfont->driver;
1524       if (rfont->font == font
1525           && mplist_find_by_value (frame->font_driver_list, driver))
1526         break;
1527     }
1528
1529   if (! rfont)
1530     {
1531       driver = mplist_get (frame->font_driver_list,
1532                            font->source == MFONT_SOURCE_X ? Mx : Mfreetype);
1533       if (! driver)
1534         MFATAL (MERROR_FONT);
1535     }
1536   return (driver->open) (frame, font, spec, rfont);
1537 }
1538
1539 int
1540 mfont__has_char (MFrame *frame, MFont *font, MFont *spec, int c)
1541 {
1542   MFontEncoding *encoding;
1543   unsigned code;
1544   MFontDriver *driver;
1545
1546   if (font->source == MFONT_SOURCE_UNDECIDED)
1547     MFATAL (MERROR_FONT);
1548   encoding = (font->encoding ? font->encoding : find_encoding (font));
1549   if (! encoding->encoding_charset)
1550     return 0;
1551   if (encoding->repertory_charset)
1552     {
1553       code = ENCODE_CHAR (encoding->repertory_charset, c);
1554       return (code != MCHAR_INVALID_CODE);
1555     }
1556   code = ENCODE_CHAR (encoding->encoding_charset, c);
1557   if (code == MCHAR_INVALID_CODE)
1558     return 0;
1559   if (font->type == MFONT_TYPE_REALIZED)
1560     driver = ((MRealizedFont *) font)->driver;
1561   else
1562     {
1563       driver = mplist_get (frame->font_driver_list,
1564                            font->source == MFONT_SOURCE_X ? Mx : Mfreetype);
1565       if (! driver)
1566         MFATAL (MERROR_FONT);
1567     }
1568   return (driver->has_char) (frame, font, spec, c, code);
1569 }
1570
1571 unsigned
1572 mfont__encode_char (MFrame *frame, MFont *font, MFont *spec, int c)
1573 {
1574   MFontEncoding *encoding;
1575   unsigned code;
1576   MFontDriver *driver;
1577
1578   if (font->source == MFONT_SOURCE_UNDECIDED)
1579     MFATAL (MERROR_FONT);
1580   encoding = (font->encoding ? font->encoding : find_encoding (font));
1581   if (! encoding->encoding_charset)
1582     return MCHAR_INVALID_CODE;
1583   if (font->source == MFONT_SOURCE_X && encoding->repertory_charset)
1584     return (ENCODE_CHAR (encoding->repertory_charset, c));
1585   code = ENCODE_CHAR (encoding->encoding_charset, c);
1586   if (code == MCHAR_INVALID_CODE)
1587     return MCHAR_INVALID_CODE;
1588   if (font->type == MFONT_TYPE_REALIZED)
1589     driver = ((MRealizedFont *) font)->driver;
1590   else
1591     {
1592       driver = mplist_get (frame->font_driver_list,
1593                            font->source == MFONT_SOURCE_X ? Mx : Mfreetype);
1594       if (! driver)
1595         MFATAL (MERROR_FONT);
1596     }
1597   return (driver->encode_char) (frame, font, spec, code);
1598 }
1599
1600 void
1601 mfont__get_metric (MGlyphString *gstring, int from, int to)
1602 {
1603   MGlyph *from_g = MGLYPH (from), *to_g = MGLYPH (to), *g;
1604   MRealizedFont *rfont = from_g->rface->rfont;
1605
1606   for (g = from_g; g != to_g; g++)
1607     if (g->rface->rfont != rfont)
1608       {
1609         int idx = GLYPH_INDEX (g);
1610
1611         (rfont->driver->find_metric) (rfont, gstring, from, idx);
1612         from_g = g;
1613         rfont = g->rface->rfont;
1614         from = idx;
1615       }
1616   (rfont->driver->find_metric) (rfont, gstring, from, GLYPH_INDEX (g));
1617 }
1618
1619
1620 /* KEY <= MFONT_REGISTRY */
1621
1622 void
1623 mfont__set_property (MFont *font, enum MFontProperty key, MSymbol val)
1624 {
1625   int numeric;
1626
1627   if (val == Mnil)
1628     numeric = 0;
1629   else
1630     {
1631       numeric = FONT_PROPERTY_NUMERIC (val, key);
1632       if (! numeric)
1633         {
1634           numeric = mfont__property_table[key].used;
1635           MLIST_APPEND1 (mfont__property_table + key, names, val, MERROR_FONT);
1636           SET_FONT_PROPERTY_NUMERIC (val, key, numeric);
1637         }
1638     }
1639   font->property[key] = numeric;
1640 }
1641
1642 int
1643 mfont__parse_name_into_font (const char *name, MSymbol format, MFont *font)
1644 {
1645   int result = -1;
1646
1647   if (format == Mx || format == Mnil)
1648     result = xlfd_parse_name (name, font);
1649 #ifdef HAVE_FONTCONFIG
1650   if (format == Mfontconfig || (result < 0 && format == Mnil))
1651     result = mfont__ft_parse_name (name, font);
1652 #endif /* HAVE_FONTCONFIG */
1653   return result;
1654 }
1655
1656 MPlist *
1657 mfont__encoding_list (void)
1658 {
1659   if (! font_encoding_list)
1660     load_font_encoding_table ();
1661   return font_encoding_list;
1662 }
1663
1664 static void
1665 free_font_capability (void *object)
1666 {
1667   MFontCapability *cap = object;
1668   
1669   if (cap->script_tag)
1670     {
1671       int i;
1672       for (i = 0; i < MFONT_OTT_MAX; i++)
1673         {
1674           if (cap->features[i].str)
1675             free (cap->features[i].str);
1676           if (cap->features[i].tags)
1677             free (cap->features[i].tags);
1678         }
1679     }
1680   free (cap);
1681 }
1682
1683 MFontCapability *
1684 mfont__get_capability (MSymbol sym)
1685 {
1686   MFontCapability *cap = msymbol_get (sym, M_font_capability);
1687   char *str, *p, *endp;
1688
1689   if (cap)
1690     return cap;
1691   str = MSYMBOL_NAME (sym);
1692   if (str[0] != ':')
1693     return NULL;
1694   M17N_OBJECT (cap, free_font_capability, MERROR_FONT);
1695   msymbol_put (sym, M_font_capability, cap);
1696   M17N_OBJECT_UNREF (cap);
1697   endp = str + MSYMBOL_NAMELEN (sym);
1698   while (str < endp)
1699     {
1700       if (*str++ != ':')
1701         continue;
1702       if (str[0] == 'o' && strncmp (str + 1, "tf=", 3) == 0)
1703         {
1704           char *beg;
1705           MSymbol sym;
1706           int i;
1707
1708           str += 4;
1709           beg = str;
1710           for (i = 0, p = str; i < 4 && p < endp; i++, p++);
1711           if (i < 4)
1712             break;
1713           sym = msymbol__with_len (str, 4);
1714           cap->script = mscript__from_otf_tag (sym);
1715           if (cap->script == Mnil)
1716             break;
1717           cap->script_tag = OTF_tag (str);
1718           if (*p == '/')
1719             {
1720               for (i = 0, str = ++p; i < 4 && p < endp; i++, p++);
1721               if (i < 4)
1722                 {
1723                   cap->script = Mnil;
1724                   cap->script_tag = 0;
1725                   break;
1726                 }
1727               cap->langsys_tag = OTF_tag (str);
1728             }
1729           else
1730             cap->langsys_tag = 0;
1731
1732           for (i = 0; i < MFONT_OTT_MAX; i++)
1733             cap->features[i].nfeatures = -1;
1734
1735           while (*p == '=' || *p == '+')
1736             {
1737               int idx = *p == '=' ? MFONT_OTT_GSUB : MFONT_OTT_GPOS;
1738
1739               str = ++p;
1740               while (p < endp && *p != '+') p++;
1741               if (str < p)
1742                 {
1743                   int n;
1744                   /* We never have more than (p - str) tags.  */
1745                   OTF_Tag *tags = alloca (sizeof (OTF_Tag) * (p - str));
1746                   char *p0;
1747
1748                   cap->features[idx].str = malloc (p - str + 1);
1749                   for (i = n = 0, p0 = str; str + i < p; i++)
1750                     {
1751                       cap->features[idx].str[i] = str[i];
1752                       if (str[i] == ',' || str + i + 1 == p)
1753                         {
1754                           if (*p0 == '*')
1755                             tags[n] = 0;
1756                           else if (*p0 == '~')
1757                             tags[n] = OTF_tag (p0 + 1) | 0x80000000;
1758                           else
1759                             tags[n] = OTF_tag (p0);
1760                           n++;
1761                           p0 = str + i + 1;
1762                         }
1763                     }
1764                   cap->features[idx].str[i] = '\0';
1765                   cap->features[idx].nfeatures = n;
1766                   if (n > 0)
1767                     {
1768                       int size = sizeof (OTF_Tag) * n;
1769
1770                       cap->features[idx].tags = malloc (size);
1771                       memcpy (cap->features[idx].tags, tags, size);
1772                     }
1773                 }
1774               else
1775                 {
1776                   cap->features[idx].str = NULL;
1777                   cap->features[idx].nfeatures = 0;
1778                 }
1779             }
1780
1781           for (i = 0; i < MFONT_OTT_MAX; i++)
1782             if (cap->features[i].nfeatures < 0)
1783               {
1784                 cap->features[i].str = strdup ("*");
1785                 cap->features[i].nfeatures = 1;
1786                 cap->features[i].tags = malloc (sizeof (OTF_Tag));
1787                 cap->features[i].tags[0] = 0;
1788               }
1789           cap->otf = msymbol__with_len (beg, p - beg);
1790           str = p;
1791         }
1792       else if (str[0] == 'l' && strncmp (str + 1, "ang=", 4) == 0)
1793         {
1794           str += 5;
1795           for (p = str; p < endp && *p != ':'; p++);
1796           if (str < p)
1797             cap->language = msymbol__with_len (str, p - str);
1798           str = p;
1799         }
1800       else if (str[0] == 's' && strncmp (str + 1, "cript=", 6) == 0)
1801         {
1802           str += 7;
1803           for (p = str; p < endp && *p != ':'; p++);
1804           if (str < p)
1805             cap->script = msymbol__with_len (str, p - str);
1806           str = p;
1807         }
1808     }
1809   return cap;
1810 }
1811
1812 int
1813 mfont__check_capability (MRealizedFont *rfont, MSymbol capability)
1814 {
1815   return (rfont->driver->check_capability (rfont, capability));
1816 }
1817
1818
1819 /*** @} */
1820 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
1821
1822 \f
1823
1824 /* External API */
1825
1826 /*** @addtogroup m17nFont */
1827 /*** @{ */
1828 /*=*/
1829
1830 /***en @name Variables: Keys of font property.  */
1831 /***ja @name ÊÑ¿ô: ¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤ò»ØÄꤹ¤ëÄêµÁºÑ¤ß¥·¥ó¥Ü¥ë */
1832 /*** @{ */
1833 /*=*/
1834
1835 /***en
1836     @brief Key of font property specifying foundry.
1837
1838     The variable #Mfoundry is a symbol of name <tt>"foundry"</tt> and
1839     is used as a key of font property and face property.  The property
1840     value must be a symbol whose name is a foundry name of a font.  */
1841 /***ja
1842     @brief ³«È¯¸µ¤ò»ØÄꤹ¤ë¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼.
1843     
1844     ÊÑ¿ô #Mfoundry ¤Ï <tt>"fonudry"</tt> 
1845     ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤È¥Õ¥§¡¼¥¹¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼¤È¤·¤ÆÍѤ¤¤é¤ì¤ë¡£
1846     Ãͤϡ¢¥Õ¥©¥ó¥È¤Î³«È¯¸µÌ¾¤ò̾Á°¤È¤·¤Æ»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£    */
1847
1848 MSymbol Mfoundry;
1849
1850 /***en
1851     @brief Key of font property specifying family.
1852
1853     The variable #Mfamily is a symbol of name <tt>"family"</tt> and is
1854     used as a key of font property and face property.  The property
1855     value must be a symbol whose name is a family name of a font.  */ 
1856 /***ja
1857     @brief ¥Õ¥¡¥ß¥ê¤ò»ØÄꤹ¤ë¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼.
1858     
1859     ÊÑ¿ô #Mfamily ¤Ï <tt>"family"</tt> 
1860     ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤È¥Õ¥§¡¼¥¹¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼¤È¤·¤ÆÍѤ¤¤é¤ì¤ë¡£
1861     Ãͤϡ¢¥Õ¥©¥ó¥È¤Î¥Õ¥¡¥ß¥ê̾¤ò̾Á°¤È¤·¤Æ»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£    */
1862
1863 MSymbol Mfamily;
1864
1865 /***en
1866     @brief Key of font property specifying weight.
1867
1868     The variable #Mweight is a symbol of name <tt>"weight"</tt> and is
1869     used as a key of font property and face property.  The property
1870     value must be a symbol whose name is a weight name of a font (e.g
1871     "medium", "bold").  */ 
1872 /***ja
1873     @brief ÂÀ¤µ¤ò»ØÄꤹ¤ë¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼.
1874     
1875     ÊÑ¿ô #Mweight ¤Ï <tt>"weight"</tt> 
1876     ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤È¥Õ¥§¡¼¥¹¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼¤È¤·¤ÆÍѤ¤¤é¤ì¤ë¡£
1877     Ãͤϡ¢¥Õ¥©¥ó¥È¤ÎÂÀ¤µÌ¾ ( "medium", "bold" Åù) ¤ò̾Á°¤È¤·¤Æ»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£    */
1878
1879 MSymbol Mweight;
1880
1881 /***en
1882     @brief Key of font property specifying style.
1883
1884     The variable #Mstyle is a symbol of name <tt>"style"</tt> and is
1885     used as a key of font property and face property.  The property
1886     value must be a symbol whose name is a style name of a font (e.g
1887     "r", "i", "o").  */ 
1888 /***ja
1889     @brief ¥¹¥¿¥¤¥ë¤ò»ØÄꤹ¤ë¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼.
1890     
1891     ÊÑ¿ô #Mstyle ¤Ï <tt>"style"</tt> 
1892     ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤È¥Õ¥§¡¼¥¹¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼¤È¤·¤ÆÍѤ¤¤é¤ì¤ë¡£
1893     Ãͤϡ¢¥Õ¥©¥ó¥È¤Î¥¹¥¿¥¤¥ë̾ ("r", "i", "o" Åù)¤ò̾Á°¤È¤·¤Æ»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£    */
1894
1895 MSymbol Mstyle;
1896
1897 /***en
1898     @brief Key of font property specifying stretch.
1899
1900     The variable #Mstretch is a symbol of name <tt>"stretch"</tt> and
1901     is used as a key of font property and face property.  The property
1902     value must be a symbol whose name is a stretch name of a font (e.g
1903     "normal", "condensed").  */ 
1904 /***ja
1905     @brief Éý¤ò»ØÄꤹ¤ë¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼.
1906     
1907     ÊÑ¿ô #Mstretch ¤Ï <tt>"stretch"</tt> 
1908     ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤È¥Õ¥§¡¼¥¹¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼¤È¤·¤ÆÍѤ¤¤é¤ì¤ë¡£
1909     Ãͤϡ¢¥Õ¥©¥ó¥È¤Îʸ»úÉý̾ ( "normal", "condensed" Åù)¤ò̾Á°¤È¤·¤Æ»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£    */
1910
1911 MSymbol Mstretch;
1912
1913 /***en
1914     @brief Key of font property specifying additional style.
1915
1916     The variable #Madstyle is a symbol of name <tt>"adstyle"</tt> and
1917     is used as a key of font property and face property.  The property
1918     value must be a symbol whose name is an additional style name of a
1919     font (e.g "serif", "", "sans").  */ 
1920 /***ja
1921     @brief adstyle ¤ò»ØÄꤹ¤ë¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼.
1922     
1923     ÊÑ¿ô #Madstyle ¤Ï <tt>"adstyle"</tt> 
1924     ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤È¥Õ¥§¡¼¥¹¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼¤È¤·¤ÆÍѤ¤¤é¤ì¤ë¡£
1925     Ãͤϡ¢¥Õ¥©¥ó¥È¤Î adstyle Ì¾("serif", "", "sans" Åù)¤ò̾Á°¤È¤·¤Æ»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£    */
1926
1927 MSymbol Madstyle;
1928
1929 /***en
1930     @brief Key of font property specifying spacing.
1931
1932     The variable #Madstyle is a symbol of name <tt>"spacing"</tt> and
1933     is used as a key of font property.  The property value must be a
1934     symbol whose name specifies the spacing of a font (e.g "p" for
1935     proportional, "m" for monospaced).  */ 
1936 /***ja
1937     @brief spacing ¤ò»ØÄꤹ¤ë¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼.
1938     
1939     ÊÑ¿ô #Mspacing ¤Ï <tt>"spacing"</tt> ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢
1940     ¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼¤È¤·¤ÆÍѤ¤¤é¤ì¤ë¡£Ãͤϡ¢¥Õ¥©¥ó¥È¤Î spacing
1941     ÆÃÀ­¤ò¼¨¤¹Ì¾Á° ("p", "m" Åù)¤ò»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£  */
1942
1943 MSymbol Mspacing;
1944
1945 /***en
1946     @brief Key of font property specifying registry.
1947
1948     The variable #Mregistry is a symbol of name <tt>"registry"</tt>
1949     and is used as a key of font property.  The property value must be
1950     a symbol whose name is a registry name a font registry
1951     (e.g. "iso8859-1", "jisx0208.1983-0").  */ 
1952 /***ja
1953     @brief ¥ì¥¸¥¹¥È¥ê¤ò»ØÄꤹ¤ë¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼.
1954     
1955     ÊÑ¿ô #Mregistry ¤Ï <tt>"registry"</tt> 
1956     ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤È¥Õ¥§¡¼¥¹¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼¤È¤·¤ÆÍѤ¤¤é¤ì¤ë¡£
1957     Ãͤϡ¢¥Õ¥©¥ó¥È¤Î¥ì¥¸¥¹¥È¥ê̾ ( "iso8859-1", "jisx0208.1983-0" 
1958     Åù) ¤ò̾Á°¤È¤·¤Æ»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£    */
1959
1960 MSymbol Mregistry;
1961
1962 /***en
1963     @brief Key of font property specifying size.
1964
1965     The variable #Msize is a symbol of name <tt>"size"</tt> and is
1966     used as a key of font property and face property.  The property
1967     value must be an integer specifying a font design size in the unit
1968     of 1/10 point (on 100 dpi display).  */ 
1969 /***ja
1970     @brief ¥µ¥¤¥º¤ò»ØÄꤹ¤ë¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼.
1971     
1972     ÊÑ¿ô #Msize ¤Ï <tt>"size"</tt> 
1973     ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤È¥Õ¥§¡¼¥¹¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼¤È¤·¤ÆÍѤ¤¤é¤ì¤ë¡£Ãͤϡ¢
1974     100 dpi ¤Î¥Ç¥£¥¹¥×¥ì¥¤¾å¤Ç¤Î¥Õ¥©¥ó¥È¤Î¥Ç¥¶¥¤¥ó¥µ¥¤¥º¤ò 1/10 
1975     ¥Ý¥¤¥ó¥Èñ°Ì¤Ç¼¨¤¹À°¿ôÃͤǤ¢¤ë¡£
1976     */
1977
1978 MSymbol Msize;
1979
1980 /***en
1981     @brief Key of font property specifying file name.
1982
1983     The variable #Mfontfile is a symbol of name <tt>"fontfile"</tt>
1984     and is used as a key of font property.  The property value must be
1985     a symbol whose name is a font file name.  */ 
1986 MSymbol Motf;
1987
1988 /***en
1989     @brief Key of font property specifying file name.
1990
1991     The variable #Mfontfile is a symbol of name <tt>"fontfile"</tt>
1992     and is used as a key of font property.  The property value must be
1993     a symbol whose name is a font file name.  */ 
1994 /***ja
1995     @brief ¥Õ¥©¥ó¥È¥Õ¥¡¥¤¥ë¤ò»ØÄꤹ¤ë¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼.
1996     
1997     ÊÑ¿ô #Mfontfile ¤Ï <tt>"fontfile"</tt> ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢
1998     ¤ê¡¢¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼¤È¤·¤ÆÍѤ¤¤é¤ì¤ë¡£Ãͤϡ¢¥Õ¥©¥ó¥È¥Õ¥¡¥¤
1999     ¥ë̾¤ò̾Á°¤È¤·¤Æ»ý¤Ä¤È¤¹¤ë¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£ */
2000
2001 MSymbol Mfontfile;
2002
2003 /***en
2004     @brief Key of font property specifying resolution.
2005
2006     The variable #Mresolution is a symbol of name <tt>"resolution"</tt> and
2007     is used as a key of font property and face property.  The property
2008     value must be an integer to specifying a font resolution in the
2009     unit of dots per inch (dpi).  */ 
2010 /***ja
2011     @brief ²òÁüÅÙ¤ò»ØÄꤹ¤ë¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼.
2012     
2013     ÊÑ¿ô #Mresolution ¤Ï <tt>"resolution"</tt> 
2014     ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤È¥Õ¥§¡¼¥¹¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼¤È¤·¤ÆÍѤ¤¤é¤ì¤ë¡£
2015     Ãͤϡ¢¥Õ¥©¥ó¥È¤Î²òÁüÅÙ¤ò dots per inch (dpi) Ã±°Ì¤Ç¼¨¤¹À°¿ôÃͤǤ¢¤ë¡£    */
2016
2017 MSymbol Mresolution;
2018
2019 /***en
2020     @brief Key of font property specifying max advance width.
2021
2022     The variable #Mmax_advance is a symbol of name
2023     <tt>"max-advance"</tt> and is used as a key of font property.  The
2024     property value must be an integer specifying a font's max advance
2025     value by pixels.  */ 
2026
2027 MSymbol Mmax_advance;
2028
2029
2030 /***en
2031     @brief Symbol of name "fontconfig".
2032
2033     The variable #Mfontconfig is to be used as an argument of the
2034     functions mfont_parse_name () and mfont_unparse_name ().  */
2035 /***ja
2036     @brief "fontconfig" ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë.
2037
2038     ÊÑ¿ô #Mfontconfig ¤Ï´Ø¿ô mfont_parse_name () ¤È mfont_unparse_name ()
2039     ¤Î°ú¿ô¤È¤·¤ÆÍѤ¤¤é¤ì¤ë¡£  */
2040
2041 MSymbol Mfontconfig;
2042
2043 /***en
2044     @brief Symbol of name "x".
2045
2046     The variable #Mx is to be used for a value of <type> member of the
2047     structure #MDrawGlyph to specify the type of <fontp> member is
2048     actually (XFontStruct *).  */
2049 /***ja
2050     @brief "x" ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë.
2051
2052     ÊÑ¿ô #Mx ¤Ï¹½Â¤ #MDrawGlyph ¤Î¥á¥ó¥Ð <type> 
2053     ¤ÎÃͤȤ·¤ÆÍѤ¤¤é¤ì¡¢¥á¥ó¥Ð <fontp> ¤Î·¿¤¬¼ÂºÝ¤Ë¤Ï (XFontStruct *) ¤Ç¤¢¤ë¤³¤È¤òɽ¤¹.  */
2054
2055 MSymbol Mx;
2056
2057 /***en
2058     @brief Symbol of name "freetype".
2059
2060     The variable #Mfreetype is to be used for a value of <type> member
2061     of the structure #MDrawGlyph to specify the type of <fontp> member
2062     is actually FT_Face.  */
2063 /***ja
2064     @brief "freetype" ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë.
2065
2066     ÊÑ¿ô #Mfreetype ¤Ï¹½Â¤ #MDrawGlyph ¤Î¥á¥ó¥Ð <type> 
2067     ¤ÎÃͤȤ·¤ÆÍѤ¤¤é¤ì¡¢¥á¥ó¥Ð <fontp> ¤Î·¿¤¬¼ÂºÝ¤Ë¤Ï FT_Face ¤Ç¤¢¤ë¤³¤È¤òɽ¤¹¡£  */
2068
2069 MSymbol Mfreetype;
2070
2071 /***en
2072     @brief Symbol of name "xft".
2073
2074     The variable #Mxft is to be used for a value of <type> member of the
2075     structure #MDrawGlyph to specify the type of <fontp> member
2076     is actually (XftFont *).  */
2077 /***ja
2078     @brief  "xft" ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë.
2079
2080     ÊÑ¿ô #Mxft ¤Ï¹½Â¤ #MDrawGlyph ¤Î¥á¥ó¥Ð <type> 
2081     ¤ÎÃͤȤ·¤ÆÍѤ¤¤é¤ì¡¢¥á¥ó¥Ð <fontp> ¤Î·¿¤¬¼ÂºÝ¤Ë¤Ï (XftFont *) ¤Ç¤¢¤ë¤³¤È¤òɽ¤¹¡£  */
2082
2083 MSymbol Mxft;
2084
2085 /*=*/
2086 /*** @} */
2087 /*=*/
2088
2089 /***en
2090     @brief List of font files and directories that contain font files.
2091
2092     The variable @c mfont_freetype_path is a plist of FreeType font
2093     files and directories that contain FreeType font files.  Key of
2094     the element is @c Mstring, and the value is a string that
2095     represents a font file or a directory.
2096
2097     The macro M17N_INIT () sets up this variable to contain the
2098     sub-directory "fonts" of the m17n database and the environment
2099     variable "M17NDIR".  The first call of mframe () creates the
2100     internal list of the actually available fonts from this variable.
2101     Thus, an application program, if necessary, must modify the
2102     variable before calling mframe ().  If it is going to add a new
2103     element, value must be a string that can be safely freed.
2104
2105     If the m17n library is not configured to use the FreeType library,
2106     this variable is not used.  */
2107 /***ja
2108     @brief ¥Õ¥©¥ó¥È¥Õ¥¡¥¤¥ë¤È¥Õ¥©¥ó¥È¥Õ¥¡¥¤¥ë¤ò´Þ¤à¥Ç¥£¥ì¥¯¥È¥ê¤Î¥ê¥¹¥È.
2109
2110     ÊÑ¿ô @c mfont_freetype_path ¤Ï¡¢¥Õ¥©¥ó¥È¥Õ¥¡¥¤¥ë¤È¥Õ¥©¥ó¥È¥Õ¥¡¥¤¥ë¤ò´Þ¤à¥Ç¥£¥ì¥¯¥È¥ê¤Î 
2111     plist ¤Ç¤¢¤ë¡£³ÆÍ×ÁǤΥ­¡¼¤Ï @c Mstring 
2112     ¤Ç¤¢¤ê¡¢Ãͤϥե©¥ó¥È¥Õ¥¡¥¤¥ë¤«¥Ç¥£¥ì¥¯¥È¥ê¤ò¼¨¤¹Ê¸»úÎó¤Ç¤¢¤ë¡£
2113
2114     ¥Þ¥¯¥í M17N_INIT () ¤Ë¤è¤Ã¤Æ¡¢¤³¤ÎÊÑ¿ô¤Ï m17n ¥Ç¡¼¥¿¥Ù¡¼¥¹¤È´Ä¶­ÊÑ¿ô 
2115     "M17NDIR" ÁÐÊý¤Î¥µ¥Ö¥Ç¥£¥ì¥¯¥È¥ê "fonts" ¤ò´Þ¤à¤è¤¦¤ËÀßÄꤵ¤ì¤ë¡£
2116     mframe () ¤ÎºÇ½é¤Î¸Æ¤Ó½Ð¤·¤ÎºÝ¤Ë¡¢¤³¤ÎÊÑ¿ô¤«¤é¼ÂºÝ¤Ë»ÈÍѤǤ­¤ë¥Õ¥©¥ó¥È¤ÎÆâÉô¥ê¥¹¥È¤¬ºî¤é¤ì¤ë¡£
2117     ¤½¤³¤Ç¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥à¤Ï¡¢mframe () 
2118     ¤ò¸Æ¤ÖÁ°¤Ë¡ÊɬÍפʤé¤Ð¡Ë¤³¤ÎÊÑ¿ô¤òÊѹ¹¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
2119     ¿·¤·¤¤Í×ÁǤòÄɲ乤ë¾ì¹ç¤Ë¤Ï¡¢¤½¤ÎÃͤϰÂÁ´¤Ë³«Êü¤Ç¤­¤ëʸ»úÎó¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
2120
2121     m17n ¥é¥¤¥Ö¥é¥ê¤¬ FreeType ¥é¥¤¥Ö¥é¥ê¤ò»È¤¦¤è¤¦¤ËÀßÄꤵ¤ì¤Æ¤Ê¤¤¾ì¹ç¤Ë¤Ï¡¢¤³¤ÎÊÑ¿ô¤ÏÍѤ¤¤é¤ì¤Ê¤¤¡£ */
2122
2123 MPlist *mfont_freetype_path;
2124
2125 /*=*/
2126
2127 /***en
2128     @brief Create a new font.
2129
2130     The mfont () function creates a new font object that has no
2131     property.
2132
2133     @return
2134     This function returns a pointer to the created font object.  */
2135 /***ja
2136     @brief ¿·¤·¤¤¥Õ¥©¥ó¥È¤òºî¤ë.
2137
2138     ´Ø¿ô mfont () ¤Ï¥×¥í¥Ñ¥Æ¥£¤ò°ìÀÚ»ý¤¿¤Ê¤¤¿·¤·¤¤¥Õ¥©¥ó¥È¤ò¥ª¥Ö¥¸¥§¥¯¥È¤òºî¤ë¡£
2139
2140     @return
2141     ¤³¤Î´Ø¿ô¤Ïºî¤Ã¤¿¥Õ¥©¥ó¥È¥ª¥Ö¥¸¥§¥¯¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£  */
2142
2143 MFont *
2144 mfont ()
2145 {
2146   MFont *font;
2147
2148   MSTRUCT_CALLOC (font, MERROR_FONT);
2149   return font;
2150 }
2151
2152 /*=*/
2153
2154 /***en
2155     @brief Create a font by parsing a fontname.
2156
2157     The mfont_parse_name () function creates a new font object.  The
2158     properties are extracted fontname $NAME.
2159
2160     $FORMAT specifies the format of $NAME.  If $FORMAT is #Mx, $NAME
2161     is parsed as XLFD (X Logical Font Description).  If $FORMAT is
2162     #Mfontconfig, $NAME is parsed as Fontconfig's textual
2163     representation of font.  If $FORMAT is #Mnil, $NAME is at first
2164     parsed as XLFD, and it it fails, parsed as Fontconfig's
2165     representation.
2166
2167     @return
2168     If the operation was successful, this function returns a pointer
2169     to the created font.  Otherwise it returns @c NULL.  */
2170
2171 /***ja
2172     @brief ¥Õ¥©¥ó¥È̾¤«¤é¥Õ¥©¥ó¥È¤òºî¤ë.
2173
2174     ´Ø¿ô mfont_parse_name () ¤Ï¡¢¥Õ¥©¥ó¥È̾ 
2175     $NAME ¤«¤é¼è¤ê½Ð¤µ¤ì¤¿¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ä¡¢¿·¤·¤¤¥Õ¥©¥ó¥È¥ª¥Ö¥¸¥§¥¯¥È¤òºî¤ë¡£
2176
2177     $FORMAT ¤Ï $NAME ¤Î¥Õ¥©¡¼¥Þ¥Ã¥È¤ò»ØÄꤹ¤ë¡£$FORMAT ¤¬ #Mx ¤Ç¤¢¤ì¤Ð¡¢
2178     $NAME ¤Ï XLFD (X Logical Font Description) ¤Ë½¾¤Ã¤Æ²òÀϤµ¤ì¤ë¡£
2179     $FORMAT ¤¬ #Mfontconfig ¤Ç¤¢¤ì¤Ð $NAME ¤Ï Fontfonfig 
2180     ¤Î¥Õ¥©¥ó¥È¥Æ¥­¥¹¥Èɽ¸½¤Ë½¾¤Ã¤Æ²òÀϤµ¤ì¤ë¡£$FORMAT ¤¬ #Mnil ¤Ç¤¢¤ì¤Ð¡¢¤Þ¤º XLFD 
2181     ¤Ë½¾¤Ã¤Æ²òÀϤµ¤ì¡¢¤½¤ì¤Ë¼ºÇÔ¤·¤¿¤é Fontconfig ¤Ë½¾¤Ã¤Æ²òÀϤµ¤ì¤ë¡£
2182
2183     @return
2184     ½èÍý¤¬À®¸ù¤¹¤ì¤Ð mfont_parse_name () 
2185     ¤Ï¿·¤·¤¯ºî¤é¤ì¤¿¥Õ¥©¥ó¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð @c NULL ¤òÊÖ¤¹¡£  */
2186
2187 MFont *
2188 mfont_parse_name (const char *name, MSymbol format)
2189 {
2190   MFont template, *font;
2191   
2192   MFONT_INIT (&template);
2193   if (mfont__parse_name_into_font (name, format, &template) < 0)
2194     MERROR (MERROR_FONT, NULL);
2195   MSTRUCT_CALLOC (font, MERROR_FONT);
2196   *font = template;
2197   return font;
2198 }
2199
2200 /*=*/
2201
2202 /***en
2203     @brief Create a fontname from a font.
2204
2205     The mfont_unparse_name () function creates a fontname string
2206     from font $FONT according to $FORMAT.
2207
2208     $FORMAT must be #Mx or #Mfontconfig.  If it is #Mx, the fontname
2209     is in XLFD (X Logical Font Description) format.  If it is
2210     #Mfontconfig, the fontname is in the style of Fontconfig's text
2211     representation.
2212
2213     @return
2214     This function returns a newly allocated fontname string, which is
2215     not freed unless the user explicitly does so by free ().  */
2216
2217 /***ja
2218     @brief ¥Õ¥©¥ó¥È¤«¤é¥Õ¥©¥ó¥È̾¤òºî¤ë.
2219
2220     ´Ø¿ô mfont_unparse_name () ¤Ï ¥Õ¥©¥ó¥È̾¤Îʸ»úÎó¤ò¥Õ¥©¥ó¥È $FONT 
2221     ¤ò¸µ¤Ë$FORMAT ¤Ë½¾¤Ã¤Æºî¤ë¡£
2222
2223     $FORMAT ¤Ï #Mx ¤Þ¤¿¤Ï #Mfontconfig ¤Ç¤¢¤ë¡£
2224     #Mx ¤Ê¤é¤Ð¥Õ¥©¥ó¥È̾¤Ï XLFD (X Logical Font Description) ¤Ë½¾¤¦¡£
2225     #Mfontconfig ¤Ê¤é¤Ð¥Õ¥©¥ó¥È̾¤Ï Fontconfig ¤Î¥Õ¥©¥ó¥È¥Æ¥­¥¹¥Èɽ¸½¤Ë½¾¤¦¡£
2226
2227     @return 
2228     ¤³¤Î´Ø¿ô¤Ï¿·¤¿¤Ë¥¢¥í¥±¡¼¥È¤·¤¿¥Õ¥©¥ó¥È̾¤Îʸ»úÎó¤òÊÖ¤¹¡£Ê¸»úÎó¤Ï¡¢¥æ¡¼¥¶¤¬
2229     free () ¤Ë¤è¤Ã¤ÆÌÀ¼¨Åª¤Ë²òÊü¤·¤Ê¤¤¸Â¤ê²òÊü¤µ¤ì¤Ê¤¤¡£  */
2230
2231 char *
2232 mfont_unparse_name (MFont *font, MSymbol format)
2233 {
2234   char *name;
2235
2236   if (format == Mx)
2237     name = xlfd_unparse_name (font, 1);
2238 #ifdef HAVE_FONTCONFIG
2239   else if (format == Mfontconfig)
2240     name = mfont__ft_unparse_name (font);
2241
2242 #endif /* HAVE_FONTCONFIG */
2243   else
2244     MERROR (MERROR_FONT, NULL);
2245   return name;
2246 }
2247
2248 /*=*/
2249
2250 /***en
2251     @brief Make a copy of a font.
2252
2253     The mfont_copy () function returns a new copy of font $FONT.  */
2254 /***ja
2255     @brief ¥Õ¥©¥ó¥È¤Î¥³¥Ô¡¼¤òºî¤ë.
2256
2257     ´Ø¿ô Mfont_copy () ¤Ï¥Õ¥©¥ó¥È $FONT ¤Î¥³¥Ô¡¼¤òºî¤ê¡¢¤½¤ì¤òÊÖ¤¹¡£ */
2258
2259 MFont *
2260 mfont_copy (MFont *font)
2261 {
2262   MFont *copy;
2263
2264   MSTRUCT_MALLOC (copy, MERROR_FONT);
2265   *copy = *font;
2266   return copy;
2267 }
2268
2269 /*=*/
2270
2271 /***en
2272     @brief Get a property value of a font.
2273
2274     The mfont_get_prop () function gets the value of $KEY property of
2275     font $FONT.  $KEY must be one of the following symbols:
2276
2277         @c Mfoundry, @c Mfamily, @c Mweight, @c Mstyle, @c Mstretch,
2278         @c Madstyle, @c Mregistry, @c Msize, @c Mresolution, @c Mspacing.
2279
2280     If $FONT is a return value of mfont_find (), $KEY can also be one
2281     of the following symbols:
2282
2283         #Mfont_ascent, #Mfont_descent, #Mmax_advance.
2284
2285     @return If $KEY is @c Mfoundry, @c Mfamily, @c Mweight, @c Mstyle,
2286     @c Mstretch, @c Madstyle, @c Mregistry, or @c Mspacing, this
2287     function returns the corresponding value as a symbol.  If the font
2288     does not have $KEY property, it returns @c Mnil.  If $KEY is @c
2289     Msize, @c Mresolution, #Mfont_ascent, Mfont_descent, or
2290     #Mmax_advance, this function returns the corresponding value as an
2291     integer.  If the font does not have $KEY property, it returns 0.
2292     If $KEY is something else, it returns @c NULL and assigns an error
2293     code to the external variable #merror_code.  */
2294  
2295 /***ja
2296     @brief ¥Õ¥©¥ó¥È¤Î¥×¥í¥Ñ¥Æ¥£¤ÎÃͤòÆÀ¤ë.
2297
2298     ´Ø¿ô mfont_get_prop () ¤Ï¥Õ¥©¥ó¥È $FONT ¤Î¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥­¡¼¤¬
2299     $KEY ¤Ç¤¢¤ë¤â¤Î¤ÎÃͤòÊÖ¤¹¡£$KEY ¤Ï°Ê²¼¤Î¥·¥ó¥Ü¥ë¤Î¤¤¤º¤ì¤«¤Ç¤Ê¤±¤ì
2300     ¤Ð¤Ê¤é¤Ê¤¤¡£
2301
2302         @c Mfoundry, @c Mfamily, @c Mweight, @c Mstyle, @c Mstretch,
2303         @c Madstyle, @c Mregistry, @c Msize, @c Mresolution, @c Mspacing.
2304
2305     @return $KEY ¤¬ @c Mfoundry, @c Mfamily, @c Mweight, @c Mstyle, @c
2306     Mstretch, @c Madstyle, @c Mregistry, @c Mspacing ¤Î¤¤¤º¤ì¤«¤Ç¤¢¤ì¤Ð¡¢
2307     ÁêÅö¤¹¤ëÃͤò¥·¥ó¥Ü¥ë¤È¤·¤ÆÊÖ¤¹¡£¥Õ¥©¥ó¥È¤¬¤½¤Î¥×¥í¥Ñ¥Æ¥£¤ò»ý¤¿¤Ê¤¤
2308     ¾ì¹ç¤Ë¤Ï@c Mnil ¤òÊÖ¤¹¡£$KEY ¤¬ @c Msize ¤¢¤ë¤¤¤Ï @c Mresolution ¤Î
2309     ¾ì¹ç¤Ë¤Ï¡¢ÁêÅö¤¹¤ëÃͤò¤ÏÀ°¿ôÃͤȤ·¤ÆÊÖ¤¹¡£¥Õ¥©¥ó¥È¤¬¤½¤Î¥×¥í¥Ñ¥Æ¥£
2310     ¤ò»ý¤¿¤Ê¤¤¾ì¹ç¤Ë¤Ï 0 ¤òÊÖ¤¹¡£$KEY ¤¬¤½¤ì°Ê³°¤Î¤â¤Î¤Ç¤¢¤ì¤Ð¡¢@c
2311     NULL ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£  */
2312
2313 void *
2314 mfont_get_prop (MFont *font, MSymbol key)
2315 {
2316   MRealizedFont *rfont = NULL;
2317
2318   if (font->type == MFONT_TYPE_REALIZED)
2319     rfont = (MRealizedFont *) font;
2320
2321   if (key == Mfoundry)
2322     return (void *) FONT_PROPERTY (font, MFONT_FOUNDRY);
2323   if (key == Mfamily)
2324     return (void *) FONT_PROPERTY (font, MFONT_FAMILY);
2325   if (key == Mweight)
2326     return (void *) FONT_PROPERTY (font, MFONT_WEIGHT);
2327   if (key == Mstyle)
2328     return (void *) FONT_PROPERTY (font, MFONT_STYLE);
2329   if (key == Mstretch)
2330     return (void *) FONT_PROPERTY (font, MFONT_STRETCH);
2331   if (key == Madstyle)
2332     return (void *) FONT_PROPERTY (font, MFONT_ADSTYLE);
2333   if (key == Mregistry)
2334     return (void *) FONT_PROPERTY (font, MFONT_REGISTRY);
2335   if (key == Msize)
2336     {
2337       int size = font->size;
2338       return (void *) size;
2339     }
2340   if (key == Mresolution)
2341     {
2342       int resy = font->property[MFONT_RESY];
2343       return (void *) resy;
2344     }
2345   if (key == Mlanguage || key == Mscript || key == Motf)
2346     {
2347       MFontCapability *cap;
2348
2349       if (! font->capability)
2350         return NULL;
2351       cap = mfont__get_capability (font->capability);
2352       if (key == Mlanguage)
2353         return cap->language;
2354       if (key == Mscript)
2355         return cap->script;
2356       return cap->otf;
2357     }
2358
2359   if (key == Mfontfile)
2360     return (void *) font->file;
2361   if (key == Mspacing)
2362     return (font->spacing == MFONT_SPACING_UNDECIDED ? Mnil
2363             : msymbol (font->spacing == MFONT_SPACING_PROPORTIONAL ? "p"
2364                        : font->spacing == MFONT_SPACING_MONO ? "m" : "c"));
2365   if (rfont)
2366     {
2367       if (key == Mfont_ascent)
2368         return (void *) rfont->ascent;
2369       if (key == Mfont_descent)
2370         return (void *) rfont->descent;
2371       if (key == Mmax_advance)
2372         return (void *) rfont->max_advance;
2373     }
2374   MERROR (MERROR_FONT, NULL);
2375 }
2376
2377
2378 /*=*/
2379 /***en
2380     @brief Put a property value to a font.
2381
2382     The mfont_put_prop () function puts a font property whose key is
2383     $KEY and value is $VAL to font $FONT.  $KEY must be one of the
2384     following symbols:
2385
2386         @c Mfoundry, @c Mfamily, @c Mweight, @c Mstyle, @c Mstretch,
2387         @c Madstyle, @c Mregistry, @c Msize, @c Mresolution.
2388
2389     If $KEY is @c Msize or @c Mresolution, $VAL must be an integer.
2390     Otherwise, $VAL must be a symbol of a property value name.  But,
2391     if the name is "nil", a symbol of name "Nil" must be
2392     specified.  */
2393  /***ja
2394     @brief ¥Õ¥©¥ó¥È¤Î¥×¥í¥Ñ¥Æ¥£¤ËÃͤòÀßÄꤹ¤ë.
2395
2396     ´Ø¿ô mfont_put_prop () ¤Ï¡¢¥Õ¥©¥ó¥È $FONT ¤Î¥­¡¼¤¬$KEY ¤Ç¤¢¤ë¥×¥í¥Ñ
2397     ¥Æ¥£¤ÎÃͤò $VAL ¤ËÀßÄꤹ¤ë¡£$KEY ¤Ï°Ê²¼¤Î¥·¥ó¥Ü¥ë¤Î¤¤¤º¤ì¤«¤Ç¤¢¤ë¡£
2398
2399         @c Mfoundry, @c Mfamily, @c Mweight, @c Mstyle, @c Mstretch,
2400         @c Madstyle, @c Mregistry, @c Msize, @c Mresolution.
2401
2402     $KEY ¤¬ @c Msize ¤« @c Mresolution ¤Ç¤¢¤ì¤Ð $VAL ¤ÏÀ°¿ôÃͤǤʤ¯¤Æ¤Ï
2403     ¤é¤Ê¤¤¡£¤½¤ì°Ê³°¤Î¾ì¹ç¡¢$VAL ¤Ï¥×¥í¥Ñ¥Æ¥£ÃͤÎ̾Á°¤Î¥·¥ó¥Ü¥ë¤Ç¤Ê¤¯¤Æ
2404     ¤Ï¤Ê¤é¤Ê¤¤¡£¤¿¤À¤·¤â¤·¤½¤Î̾Á°¤¬ "nil" ¤Î¾ì¹ç¤Ï¡¢Ì¾Á°¤¬ "Nil" ¤Î¥·
2405     ¥ó¥Ü¥ë¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£*/
2406
2407 int
2408 mfont_put_prop (MFont *font, MSymbol key, void *val)
2409 {
2410   if (key == Mfoundry)
2411     mfont__set_property (font, MFONT_FOUNDRY, (MSymbol) val);
2412   else if (key == Mfamily)
2413     mfont__set_property (font, MFONT_FAMILY, (MSymbol) val);
2414   else if (key == Mweight)
2415     mfont__set_property (font, MFONT_WEIGHT, (MSymbol) val);
2416   else if (key == Mstyle)
2417     mfont__set_property (font, MFONT_STYLE, (MSymbol) val);
2418   else if (key == Mstretch)
2419     mfont__set_property (font, MFONT_STRETCH, (MSymbol) val);
2420   else if (key == Madstyle)
2421     mfont__set_property (font, MFONT_ADSTYLE, (MSymbol) val);
2422   else if (key == Mregistry)
2423     mfont__set_property (font, MFONT_REGISTRY, (MSymbol) val);
2424   else if (key == Msize)
2425     {
2426       int size = (int) val;
2427       font->size = size;
2428     }
2429   else if (key == Mresolution)
2430     {
2431       unsigned resy = (unsigned) val;
2432       font->property[MFONT_RESY] = resy;
2433     }
2434   else if (key == Mlanguage || key == Mscript || key == Motf)
2435     {
2436       font->capability = merge_capability (font->capability,
2437                                            key, (MSymbol) val, 1);
2438     }
2439   else if (key == Mfontfile)
2440     {
2441       font->file = (MSymbol) val;
2442     }
2443   else
2444     MERROR (MERROR_FONT, -1);
2445   return 0;
2446 }
2447
2448 /*=*/
2449
2450 /***en
2451     @brief Return the font selection priority.
2452
2453     The mfont_selection_priority () function returns a newly created
2454     array of six symbols.  The elements are the following
2455     keys of font properties ordered by priority.
2456
2457         @c Mfamily, @c Mweight, @c Mstyle, @c Mstretch,
2458         @c Madstyle, @c Msize.
2459
2460    The m17n library selects the best matching font according to the
2461    order of this array.  A font that has a different value for a
2462    property of lower priority is preferred to a font that has a
2463    different value for a property of higher priority.  */
2464 /***ja
2465     @brief ¥Õ¥©¥ó¥ÈÁªÂò¤ÎÍ¥ÀèÅÙ¤òÊÖ¤¹.
2466
2467     ´Ø¿ô mfont_selection_priority () ¤Ï 6 ¤Ä¤Î¥·¥ó¥Ü¥ë¤«¤é¤Ê¤ëÇÛÎó¤òºî¤Ã¤ÆÊÖ¤¹¡£
2468     ÇÛÎó¤ÎÍ×ÁǤϡ¢°Ê²¼¤Î¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼¤òÍ¥ÀèÅÙ½ç¤Ëʤ٤¿¤â¤Î¤Ç¤¢¤ë¡£
2469
2470         @c Mfamily, @c Mweight, @c Mstyle, @c Mstretch,
2471         @c Madstyle, @c Msize.
2472
2473    m17n ¥é¥¤¥Ö¥é¥ê¤Ï¤³¤ÎÇÛÎó¤Ë½¾¤Ã¤Æ¡¢ºÇ¤â¹çÃפ¹¤ë¥Õ¥©¥ó¥È¤òÁªÂò¤¹¤ë¡£
2474    ÌÜŪ¤Î¥Õ¥©¥ó¥È¤È¡¢¤½¤ì¤¾¤ì°ã¤¦¥×¥í¥Ñ¥Æ¥£¤ÎÃͤ¬¹çÃפ·¤Ê¤¤¥Õ¥©¥ó¥È¤¬¤¢¤Ã¤¿¾ì¹ç¡¢Í¥ÀèÅÙ¤ÎÄ㤤¥×¥í¥Ñ¥Æ¥£¤ÎÃͤ¬¹çÃפ·¤Ê¤¤¥Õ¥©¥ó¥È¡ÊÍ¥ÀèÅ٤ι⤤¥×¥í¥Ñ¥Æ¥£¤ÎÃͤ¬¹çÃפ·¤Æ¤¤¤ë¥Õ¥©¥ó¥È¡Ë¤¬ÁªÂò¤µ¤ì¤ë¡£
2475
2476    */
2477
2478 MSymbol *
2479 mfont_selection_priority ()
2480 {
2481   MSymbol *keys;
2482   int i;
2483
2484   MTABLE_MALLOC (keys, FONT_SCORE_PRIORITY_SIZE, MERROR_FONT);
2485   for (i = 0; i < FONT_SCORE_PRIORITY_SIZE; i++)
2486     {
2487       enum MFontProperty prop = font_score_priority[i];
2488
2489       if (prop == MFONT_SIZE)
2490         keys[i] = Msize;
2491       else if (prop == MFONT_ADSTYLE)
2492         keys[i] = Madstyle;
2493       else if (prop == MFONT_FAMILY)
2494         keys[i] = Mfamily;
2495       else if (prop == MFONT_WEIGHT)
2496         keys[i] = Mweight;
2497       else if (prop == MFONT_STYLE)
2498         keys[i] = Mstyle;
2499       else if (prop == MFONT_STRETCH)
2500         keys[i] = Mstretch;
2501       else
2502         keys[i] = Mfoundry;
2503     }
2504   return keys;
2505 }
2506
2507 /*=*/
2508
2509 /***en
2510     @brief Set the font selection priority.
2511
2512     The mfont_set_selection_priority () function sets font selection
2513     priority according to $KEYS, which is an array of six symbols.
2514     Each element must be one of the below.  No two elements must be
2515     the same.
2516
2517         @c Mfamily, @c Mweight, @c Mstyle, @c Mstretch,
2518         @c Madstyle, @c Msize.
2519
2520     See the documentation of the function mfont_selection_priority ()
2521     for details.  */
2522 /***ja
2523     @brief ¥Õ¥©¥ó¥ÈÁªÂòÍ¥ÀèÅÙ¤òÀßÄꤹ¤ë.
2524
2525     ´Ø¿ô mfont_set_selection_priority () ¤Ï¡¢6¤Ä¤Î¥·¥ó¥Ü¥ë¤ÎÇÛÎó $KEYS 
2526     ¤Ë¤·¤¿¤¬¤Ã¤Æ¥Õ¥©¥ó¥ÈÁªÂòÍ¥ÀèÅÙ¤òÀßÄꤹ¤ë¡£ÇÛÎó¤Ï°Ê²¼¤Î³ÆÍ×ÁǤòŬÀÚ
2527     ¤Ê½çÈÖ¤Çʤ٤¿¤â¤Î¤Ç¤¢¤ë¡£
2528
2529         @c Mfamily, @c Mweight, @c Mstyle, @c Mstretch,
2530         @c Madstyle, @c Msize.
2531
2532     ¾ÜºÙ¤Ï´Ø¿ô mfont_selection_priority () ¤ÎÀâÌÀ¤ò»²¾È¤Î¤³¤È¡£
2533      */
2534
2535 int
2536 mfont_set_selection_priority (MSymbol *keys)
2537 {
2538   int priority[FONT_SCORE_PRIORITY_SIZE];
2539   int i, j, shift;
2540
2541   for (i = 0; i < FONT_SCORE_PRIORITY_SIZE; i++, keys++)
2542     {
2543       enum MFontProperty prop;
2544
2545       if (*keys == Msize)
2546         prop = MFONT_SIZE;
2547       else if (*keys == Madstyle)
2548         prop = MFONT_ADSTYLE;
2549       else if (*keys == Mfamily)
2550         prop = MFONT_FAMILY;
2551       else if (*keys == Mweight)
2552         prop = MFONT_WEIGHT;
2553       else if (*keys == Mstyle)
2554         prop = MFONT_STYLE;
2555       else if (*keys == Mstretch)
2556         prop = MFONT_STRETCH;
2557       else if (*keys == Mfoundry)
2558         prop = MFONT_FOUNDRY;
2559       else
2560         /* Invalid element.  */
2561         return -1;
2562       for (j = 0; j < i; j++)
2563         if (priority[j] == prop)
2564           /* Duplicated element.  */
2565           return -1;
2566       priority[i] = prop;
2567     }
2568   for (i = 0; i < FONT_SCORE_PRIORITY_SIZE; i++)
2569     font_score_priority[i] = priority[i];
2570   /* Here, SHIFT starts from 1, not 0.  This is because the lowest bit
2571      of a score is a flag for a scalable font (see the documentation
2572      of font_score).  */
2573   i = FONT_SCORE_PRIORITY_SIZE - 1;
2574   for (shift = 1; i >= 0; i--)
2575     {
2576       font_score_shift_bits[font_score_priority[i]] = shift;
2577       if (font_score_priority[i] == MFONT_SIZE)
2578         shift += 16;
2579       else if (font_score_priority[i] <= MFONT_FAMILY)
2580         shift++;
2581       else
2582         shift += 2;
2583     }
2584   return 0;
2585 }
2586
2587 /*=*/
2588
2589 /***en
2590     @brief Find a font.
2591
2592     The mfont_find () function returns a pointer to the available font
2593     that matches best the specification $SPEC on frame $FRAME.
2594
2595     $SCORE, if not NULL, must point to a place to store the score
2596     value that indicates how well the found font matches to $SPEC.  The
2597     smaller score means a better match.  */
2598 /***ja
2599     @brief ¥Õ¥©¥ó¥È¤òõ¤¹.
2600
2601     ´Ø¿ô mfont_find () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¾å¤Ç¥Õ¥©¥ó¥ÈÄêµÁ $SPEC 
2602     ¤Ë¤â¤Ã¤È¤â¹çÃפ¹¤ëÍøÍѲÄǽ¤Ê¥Õ¥©¥ó¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£  
2603
2604     $SCORE ¤Ï NULL ¤Ç¤¢¤ë¤«¡¢¸«¤Ä¤«¤Ã¤¿¥Õ¥©¥ó¥È¤¬ $SPEC 
2605     ¤Ë¤É¤ì¤Û¤É¹ç¤Ã¤Æ¤¤¤ë¤«¤ò¼¨¤¹¥¹¥³¥¢¤òÊݸ¤¹¤ë¾ì½ê¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ë¡£
2606     ¥¹¥³¥¢¤¬¾®¤µ¤¤¤Û¤ÉÎɤ¯¹ç¤Ã¤Æ¤¤¤ë¤³¤È¤ò°ÕÌ£¤¹¤ë¡£
2607     */
2608
2609 MFont *
2610 mfont_find (MFrame *frame, MFont *spec, int *score, int max_size)
2611 {
2612   MFont spec_copy;
2613   MFont *best;
2614   MFontList *list;
2615   MRealizedFont *rfont;
2616   MFont adjusted;
2617
2618   if (spec->size < 0)
2619     {
2620       double pt = - spec->size;
2621
2622       adjusted = *spec;
2623       adjusted.size = pt * frame->dpi / 72.27 + 0.5;
2624       spec = &adjusted;
2625     }
2626   MFONT_INIT (&spec_copy);
2627   spec_copy.property[MFONT_FAMILY] = spec->property[MFONT_FAMILY];
2628   spec_copy.property[MFONT_REGISTRY] = spec->property[MFONT_REGISTRY];
2629   spec_copy.capability = spec->capability;
2630   spec_copy.file = spec->file;
2631
2632   list = mfont__list (frame, &spec_copy, spec, max_size);
2633   if (! list)
2634     return NULL;
2635
2636   best = list->fonts[0].font;
2637   if (score)
2638     *score = list->fonts[0].score;
2639   free (list->fonts);
2640   free (list);
2641   spec_copy = *best;
2642   mfont__merge (&spec_copy, spec, 0);
2643   rfont = mfont__open (frame, best, spec);
2644   if (! rfont)
2645     return NULL;
2646   return (MFont *) rfont;
2647 }
2648
2649 /*=*/
2650 /***en
2651     @brief Set encoding of a font.
2652
2653     The mfont_set_encoding () function sets the encoding information
2654     of font $FONT.
2655
2656     $ENCODING_NAME is a symbol representing a charset that has the
2657     same encoding as the font.
2658
2659     $REPERTORY_NAME is @c Mnil or a symbol representing a charset that
2660     has the same repertory as the font.  If it is @c Mnil, whether a
2661     specific character is supported by the font is asked to each font
2662     driver.
2663
2664     @return
2665     If the operation was successful, this function returns 0.
2666     Otherwise it returns -1 and assigns an error code to the external
2667     variable #merror_code.  */
2668 /***ja
2669     @brief ¥Õ¥©¥ó¥È¤Î¥¨¥ó¥³¡¼¥Ç¥£¥ó¥°¤òÀßÄꤹ¤ë.
2670
2671     ´Ø¿ô mfont_set_encoding () ¤Ï¥Õ¥©¥ó¥È $FONT ¤Î¥¨¥ó¥³¡¼¥Ç¥£¥ó¥°¾ðÊó¤òÀßÄꤹ¤ë¡£
2672
2673     $ENCODING_NAME ¤Ï¥Õ¥©¥ó¥È¤ÈƱ¤¸¥¨¥ó¥³¡¼¥Ç¥£¥ó¥°¤ò»ý¤Äʸ»ú¥»¥Ã¥È¤ò¼¨¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£
2674
2675     $REPERTORY_NAME ¤Ï @c Mnil ¤Ç¤¢¤ë¤«¡¢¥Õ¥©¥ó¥È¤ÈƱ¤¸¥¨¥ó¥³¡¼¥Ç¥£¥ó¥°¤ò»ý¤Äʸ»ú¥»¥Ã¥È¤ò¼¨¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£
2676     @c Mnil ¤Ç¤¢¤ì¤Ð¡¢¸Ä¡¹¤Îʸ»ú¤¬¤½¤Î¥Õ¥©¥ó¥È¤Ç¥µ¥Ý¡¼¥È¤µ¤ì¤Æ¤¤¤ë¤«¤É¤¦¤«¤Ï¡¢³Æ¡¹¤Î¥Õ¥©¥ó¥È¥É¥é¥¤¥Ð¤ËÌ䤤¹ç¤ï¤»¤ë¡£
2677
2678     @return
2679     ½èÍý¤¬À®¸ù¤¹¤ì¤Ð¤³¤Î´Ø¿ô¤Ï 0 ¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô
2680     #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£  */
2681
2682
2683 int
2684 mfont_set_encoding (MFont *font, MSymbol encoding_name, MSymbol repertory_name)
2685 {
2686   MCharset *encoding_charset = MCHARSET (encoding_name);
2687   MCharset *repertory_charset;
2688   MSymbol registry;
2689   MFontEncoding *encoding;
2690   MPlist *plist;
2691
2692   if (! encoding_charset)
2693     MERROR (MERROR_FONT, -1);
2694   if (repertory_name != Mnil)
2695     {
2696       repertory_charset = MCHARSET (repertory_name);
2697       if (! repertory_charset)
2698         MERROR (MERROR_FONT, -1);
2699     }
2700   else
2701     repertory_charset = NULL;
2702
2703   MSTRUCT_CALLOC (encoding, MERROR_FONT);
2704   encoding->spec = *font;
2705   encoding->encoding_name = encoding_name;
2706   encoding->encoding_charset = encoding_charset;
2707   encoding->repertory_name = repertory_name;
2708   encoding->repertory_charset = repertory_charset;
2709   registry = FONT_PROPERTY (font, MFONT_REGISTRY);
2710   if (registry == Mnil)
2711     registry = Mt;
2712   if (! font_encoding_list)
2713     load_font_encoding_table ();
2714   mplist_push (font_encoding_list, registry, encoding);
2715   MPLIST_DO (plist, MPLIST_NEXT (font_encoding_list))
2716     if (! memcmp (font, &((MFontEncoding *) MPLIST_VAL (plist))->spec,
2717                   sizeof (MFont)))
2718       {
2719         mplist_pop (plist);
2720         break;
2721       }
2722   return 0;
2723 }
2724
2725 /*=*/
2726
2727 /***en
2728     @brief Create a fontname from a font.
2729
2730     This function is obsolete.   Use mfont_unparse_name instead. */
2731 /***ja
2732     @brief ¥Õ¥©¥ó¥È̾¤«¤é¥Õ¥©¥ó¥È¤òºî¤ë.
2733
2734     ¤³¤Î´Ø¿ô¤ÏÇÑ»ßͽÄê¤Ç¤¢¤ë¡£ mfont_unparse_name () ¤ò»ÈÍѤΤ³¤È¡£ */
2735
2736 char *
2737 mfont_name (MFont *font)
2738 {
2739   return mfont_unparse_name (font, Mx);
2740 }
2741
2742 /*=*/
2743
2744 /***en
2745     @brief Create a new font from fontname.
2746
2747     This function is obsolete.  Use mfont_parse_name () instead.  */
2748
2749 /***ja
2750     @brief ¥Õ¥©¥ó¥È¤«¤é¥Õ¥©¥ó¥È̾¤òºî¤ë.
2751
2752     ¤³¤ì¤Ï´Ø¿ô¤ÏÇÑ»ßͽÄê¤Ç¤¢¤ë¡£ mfont_parse_name () ¤ò»ÈÍѤΤ³¤È¡£  */
2753
2754 MFont *
2755 mfont_from_name (const char *name)
2756 {
2757   return mfont_parse_name (name, Mx);
2758 }
2759
2760 /*=*/
2761
2762 /***en
2763     @brief Get resize information of a font.
2764
2765     The mfont_resize_ratio () function lookups the m17n database
2766     \<font, reisize\> and returns a resizing ratio (in percentage) of
2767     FONT.  For instance, if the return value is 150, that means that
2768     the m17n library uses an 1.5 time bigger font than a specified
2769     size.  */
2770
2771 /***ja
2772     @brief ¥Õ¥©¥ó¥È¤Î¥ê¥µ¥¤¥º¾ðÊó¤òÆÀ¤ë
2773
2774     ´Ø¿ô mfont_resize_ratio ¤Ï m17n ¥Ç¡¼¥¿¥Ù¡¼¥¹ \<font, reisize\> 
2775     ¤ò¸¡º÷¤·¡¢¥Õ¥©¥ó¥È FONT ¤Î¥ê¥µ¥¤¥º¤ÎÈæΨ¡Ê¥Ñ¡¼¥»¥ó¥Æ¡¼¥¸¡Ë
2776     ¤òÊÖ¤¹¡£¤¿¤È¤¨¤ÐÊÖ¤¹Ãͤ¬ 150 ¤Ç¤¢¤ì¤Ð¡¢m17n ¥é¥¤¥Ö¥é¥ê¤Ï»ØÄꤵ¤ì¤¿¥µ¥¤¥º¤Î 1.5 
2777     ÇܤΥե©¥ó¥È¤ò»ÈÍѤ¹¤ë¤³¤È¤ò°ÕÌ£¤¹¤ë¡£ */
2778
2779 int
2780 mfont_resize_ratio (MFont *font)
2781 {
2782   MSymbol registry = FONT_PROPERTY (font, MFONT_REGISTRY);
2783   MFontResize *resize;
2784   MPlist *plist;
2785
2786   if (! font_resize_list)
2787     load_font_resize_table ();
2788   if (! MPLIST_TAIL_P (font_resize_list))
2789     while (1)
2790       {
2791         plist = font_resize_list;
2792         while (registry ? (plist = mplist_find_by_key (plist, registry))
2793                : plist)
2794           {
2795             resize = (MFontResize *) MPLIST_VAL (plist);
2796             if (mfont__match_p (font, &resize->spec, MFONT_ADSTYLE))
2797               return resize->resize;
2798             plist = MPLIST_NEXT (plist);
2799           }
2800         if (registry == Mt)
2801           break;
2802         registry = Mt;
2803       }
2804   return 100;
2805 }
2806
2807 /*=*/
2808
2809 /***en
2810     @brief Get a list of fonts.
2811
2812     The mfont_list () functions returns a list of fonts available on
2813     frame $FRAME.  $FONT, if not NULL, limits fonts to ones
2814     that match with $FONT.  $LANGUAGE, if not @c Mnil, limits fonts to
2815     ones that support $LANGUAGE.  $MAXNUM, if greater than 0, limits
2816     the number of fonts.
2817
2818     $LANGUAGE argument exists just for backward compatibility, and the
2819     use is deprecated.  Use #Mlanguage font property instead.  If
2820     $FONT already has #Mlanguage property, $LANGUAGE is ignored.
2821
2822     @return
2823     This function returns a plist whose keys are family names and
2824     values are pointers to the object MFont.  The plist must be freed
2825     by m17n_object_unref ().  If no font is found, it returns
2826     NULL.  */
2827
2828 /***ja
2829     @brief ¥Õ¥©¥ó¥È¤Î¥ê¥¹¥È¤òÆÀ¤ë
2830
2831     ´Ø¿ô mfont_list () ¤Ï¥Õ¥ì¡¼¥à $FRAME ¤ÇÍøÍѲÄǽ¤Ê¥Õ¥©¥ó¥È¤Î¥ê¥¹¥È¤ò
2832     ÊÖ¤¹¡£$FONT ¤¬ NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢$FONT ¤È¹çÃפ¹¤ëÍøÍѲÄǽ¤Ê¥Õ¥©¥ó¥È
2833     ¤Î¥ê¥¹¥È¤òÊÖ¤¹¡£$LANGUAGE ¤¬ @c Mnil ¤Ç¤Ê¤±¤ì¤Ð¡¢$LANGUAGE ¤ò¥µ¥Ý¡¼
2834     ¥È¤¹¤ëÍøÍѲÄǽ¤Ê¥Õ¥©¥ó¥È¤Î¥ê¥¹¥È¤òÊÖ¤¹¡£$MAXNUM ¤Ï¡¢0 ¤è¤êÂ礭¤¤¾ì
2835     ¹ç¤Ë¤Ï¡¢ÊÖ¤¹¥Õ¥©¥ó¥È¤Î¿ô¤Î¾å¸Â¤Ç¤¢¤ë¡£
2836
2837     ¤¿¤À¤·¡¢°ú¿ô $LANGUAGE ¤ÏµìÈǤȤÎÀ°¹çÀ­¤Î¤¿¤á¤À¤±¤Ë¤¢¤ê¡¢¤½¤Î»ÈÍѤÏ
2838     ´«¤á¤é¤ì¤Ê¤¤¡£¥Õ¥©¥ó¥È¤Î #Mlanguage ¥×¥í¥Ñ¥Æ¥£¤ò»È¤¦¤Ù¤­¤Ç¤¢¤ë¡£¤â
2839     ¤· $FONT ¤¬¤¹¤Ç¤Ë¤³¤Î¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ã¤Æ¤¤¤¿¤é¡¢°ú¿ô $LANGUAGE ¤Ï̵
2840
2841
2842     @return 
2843     ¤³¤Î´Ø¿ô¤Ï¥­¡¼¤¬¥Õ¥©¥ó¥È¥Õ¥¡¥ß¥ê̾¤Ç¤¢¤êÃͤ¬ MFont ¥ª¥Ö¥¸¥§¥¯¥È¤Ø¤Î
2844     ¥Ý¥¤¥ó¥¿¤Ç¤¢¤ë¤è¤¦¤Êplist ¤òÊÖ¤¹¡£plist ¤Ï m17n_object_unref () ¤Ç
2845     ²òÊü¤¹¤ëɬÍפ¬¤¢¤ë¡£¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤é¤Ê¤±¤ì¤ÐNULL ¤òÊÖ¤¹¡£  */
2846
2847 MPlist *
2848 mfont_list (MFrame *frame, MFont *font, MSymbol language, int maxnum)
2849 {
2850   MPlist *plist, *pl;
2851   MFontList *font_list;
2852   int i;
2853   MFont spec;
2854   
2855   if (font)
2856     spec = *font;
2857   else
2858     MFONT_INIT (&spec);
2859
2860   if (spec.size < 0)
2861     {
2862       double pt = - spec.size;
2863
2864       spec.size = pt * frame->dpi / 72.27 + 0.5;
2865     }
2866
2867   if (language != Mnil)
2868     spec.capability = merge_capability (spec.capability, Mlanguage, language,
2869                                         0);
2870
2871   font_list = mfont__list (frame, &spec, &spec, 0);
2872   if (! font_list)
2873     return NULL;
2874   if (font_list->nfonts == 0)
2875     {
2876       free (font_list);
2877       return NULL;
2878     }
2879
2880   plist = pl = mplist ();
2881   for (i = 0; i < font_list->nfonts; i++)
2882     {
2883       MSymbol family = FONT_PROPERTY (font_list->fonts[i].font, MFONT_FAMILY);
2884
2885       if (family != Mnil)
2886         pl = mplist_add (pl, family, font_list->fonts[i].font);
2887     }
2888   free (font_list);
2889   return plist;
2890 }
2891
2892 /***en
2893     @brief Get a list of font famiy names.
2894
2895     The mfont_list_family_names () functions returns a list of font
2896     family names available on frame $FRAME.
2897
2898     @return
2899
2900     This function returns a plist whose keys are #Msymbol and values
2901     are symbols representing font family names.  The elements are
2902     sorted by alphabetical order.  The plist must be freed by
2903     m17n_object_unref ().  If not font is found, it returns NULL.  */
2904
2905 MPlist *
2906 mfont_list_family_names (MFrame *frame)
2907 {
2908   MPlist *plist = mplist (), *p;
2909
2910   MPLIST_DO (p, frame->font_driver_list)
2911     {
2912       MFontDriver *driver = MPLIST_VAL (p);
2913
2914       (driver->list_family_names) (frame, plist);
2915     }
2916   return plist;
2917 }
2918
2919
2920 /*=*/
2921
2922 /***en
2923     @brief Check the usability of a font.
2924
2925     The function mfont_check () checkes if $FONT can be used for
2926     $SCRIPT and $LANGUAGE in $FONTSET on $FRAME.
2927
2928     @return If the font is usable, return 1.  Otherwise return 0.
2929  */
2930
2931 int
2932 mfont_check (MFrame *frame, MFontset *fontset,
2933              MSymbol script, MSymbol language, MFont *font)
2934 {
2935   MRealizedFont *rfont;
2936   int best, score;
2937
2938   if (! fontset)
2939     fontset = frame->face->property[MFACE_FONTSET];
2940   rfont = mfontset__get_font (frame, fontset, script, language, font, &best);
2941   if (! rfont || ! best)
2942     return 0;
2943   score = font_score (&rfont->spec, font);
2944   return (score == 0 ? 2 : 1);
2945 }
2946
2947 /*** @} */
2948
2949 /*** @addtogroup m17nDebug */
2950 /*=*/
2951 /*** @{ */
2952
2953 /***en
2954     @brief Dump a font.
2955
2956     The mdebug_dump_font () function prints font $FONT in a human readable
2957     way to the stderr.
2958
2959     @return
2960     This function returns $FONT.  */
2961 /***ja
2962     @brief ¥Õ¥©¥ó¥È¤ò¥À¥ó¥×¤¹¤ë.
2963
2964     ´Ø¿ô mdebug_dump_font () ¤Ï¥Õ¥©¥ó¥È $FONT ¤ò stderr 
2965     ¤Ë¿Í´Ö¤Ë²ÄÆɤʷÁ¤Ç°õºþ¤¹¤ë¡£
2966
2967     @return
2968     ¤³¤Î´Ø¿ô¤Ï $FONT ¤òÊÖ¤¹¡£  */
2969
2970 MFont *
2971 mdebug_dump_font (MFont *font)
2972 {
2973   char *name;
2974   
2975   name = xlfd_unparse_name (font, 0);
2976   if (name)
2977     {
2978       fprintf (stderr, "%s", name);
2979       free (name);
2980     }
2981   if (font->file != Mnil)
2982     {
2983       char *file = MSYMBOL_NAME (font->file);
2984       char *lastslash = file, *p;
2985
2986       for (p = file; *p; p++)
2987         if (*p == '/')
2988           lastslash = p;
2989       if (name)
2990         fprintf (stderr, ",");
2991       fprintf (stderr, "%s", lastslash + 1);
2992     }
2993   if (font->capability != Mnil)
2994     fprintf (stderr, "%s", MSYMBOL_NAME (font->capability));
2995   return font;
2996 }
2997
2998 /*** @} */
2999
3000 /*
3001   Local Variables:
3002   coding: euc-japan
3003   End:
3004 */