*** empty log message ***
[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., 51 Franklin Street, Fifth Floor,
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
668 void
669 OTF_tag_name (OTF_Tag tag, char *name)
670 {
671   name[0] = (char) (tag >> 24);
672   name[1] = (char) ((tag >> 16) & 0xFF);
673   name[2] = (char) ((tag >> 8) & 0xFF);
674   name[3] = (char) (tag & 0xFF);
675   name[4] = '\0';
676 }
677 #endif  /* not HAVE_OTF */
678
679 /* XLFD parser/generator */
680
681 /** Indices to each field of split font name.  */
682
683 enum xlfd_field_idx
684   {
685     XLFD_FOUNDRY,
686     XLFD_FAMILY,
687     XLFD_WEIGHT,
688     XLFD_SLANT,
689     XLFD_SWIDTH,
690     XLFD_ADSTYLE,
691     XLFD_PIXEL,
692     XLFD_POINT,
693     XLFD_RESX,
694     XLFD_RESY,
695     XLFD_SPACING,
696     XLFD_AVGWIDTH,
697     XLFD_REGISTRY,              /* This contains ENCODING.  */
698     /* anchor */
699     XLFD_FIELD_MAX
700   };
701
702 static int
703 xlfd_parse_name (const char *name, MFont *font)
704 {
705   char *field[XLFD_FIELD_MAX];
706   unsigned short resy, avgwidth;
707   unsigned size;
708   char copy[513];
709   int i;
710   char *p;
711   MSymbol sym;
712
713   if (name[0] != '-')
714     return -1;
715
716   field[0] = copy;
717   for (i = 1, p = copy, name++; *name; p++, name++)
718     {
719       if (p - copy > 512)
720         return -1;
721       if (*name == '-'
722           && i < XLFD_FIELD_MAX)
723         {
724           *p = '\0';
725           if (field[i - 1][0] == '*')
726             field[i - 1] = NULL;
727           field[i++] = p + 1;
728         }
729       else
730         *p = tolower (*name);
731     }
732   *p = '\0';
733   if (field[i - 1][0] == '*')
734     field[i - 1] = NULL;
735   while (i < XLFD_FIELD_MAX)
736     field[i++] = NULL;
737
738   resy = field[XLFD_RESY] ? atoi (field[XLFD_RESY]) : 0;
739   avgwidth = ((field[XLFD_AVGWIDTH] && isdigit (field[XLFD_AVGWIDTH][0]))
740               ? atoi (field[XLFD_AVGWIDTH]) : 1);
741   if (! avgwidth)
742     size = 0;
743   else if (! field[XLFD_PIXEL])
744     size = field[XLFD_POINT] ? atoi (field[XLFD_POINT]) * resy / 72 : 0;
745   else if (field[XLFD_PIXEL][0] == '[')
746     {
747       /* The pixel size field specifies a transformation matrix of the
748          form "[A B C D]".  The XLFD spec says that the scalar value N
749          for the pixel size is equivalent to D.  */
750       char *p0 = field[XLFD_PIXEL] + 1, *p1;
751       double d;
752
753       for (i = 0; i < 4; i++, p0 = p1)
754         d = strtod (p0, &p1);
755       size = d * 10;
756     }
757   else
758     size = atoi (field[XLFD_PIXEL]) * 10;
759
760   if (field[XLFD_FOUNDRY])
761     {
762       sym = msymbol (field[XLFD_FOUNDRY]);
763       if (! sym)
764         sym = msymbol ("Nil");
765       mfont__set_property (font, MFONT_FOUNDRY, sym);
766     }
767   if (field[XLFD_FAMILY])
768     {
769       sym = msymbol (field[XLFD_FAMILY]);
770       if (! sym)
771         sym = msymbol ("Nil");
772       mfont__set_property (font, MFONT_FAMILY, sym);
773     }
774   if (field[XLFD_WEIGHT])
775     mfont__set_property (font, MFONT_WEIGHT, msymbol (field[XLFD_WEIGHT]));
776   if (field[XLFD_SLANT])
777     mfont__set_property (font, MFONT_STYLE, msymbol (field[XLFD_SLANT]));
778   if (field[XLFD_SWIDTH])
779     mfont__set_property (font, MFONT_STRETCH, msymbol (field[XLFD_SWIDTH]));
780   if (field[XLFD_ADSTYLE])
781     mfont__set_property (font, MFONT_ADSTYLE, msymbol (field[XLFD_ADSTYLE]));
782   font->property[MFONT_RESY] = resy;
783   font->size = size;
784   if (field[XLFD_SPACING])
785     font->spacing
786       = ((field[XLFD_SPACING][0] == 'p' || field[XLFD_SPACING][0] == 'P')
787          ? MFONT_SPACING_PROPORTIONAL
788          : (field[XLFD_SPACING][0] == 'm' || field[XLFD_SPACING][0] == 'M')
789          ? MFONT_SPACING_MONO : MFONT_SPACING_CHARCELL);
790   if (field[XLFD_REGISTRY])
791     mfont__set_property (font, MFONT_REGISTRY, msymbol (field[XLFD_REGISTRY]));
792   font->type = MFONT_TYPE_SPEC;
793   font->source = MFONT_SOURCE_X;
794   return 0;
795 }
796
797 static char *
798 xlfd_unparse_name (MFont *font, int full_xlfd)
799 {
800   MSymbol prop[7];
801   char name[513];
802   char *str[7];
803   int len, i;
804   char spacing;
805   int size, resy;
806   int all_nil = 1;
807
808   prop[0] = (MSymbol) mfont_get_prop (font, Mfoundry);
809   prop[1] = (MSymbol) mfont_get_prop (font, Mfamily);
810   prop[2] = (MSymbol) mfont_get_prop (font, Mweight);
811   prop[3] = (MSymbol) mfont_get_prop (font, Mstyle);
812   prop[4] = (MSymbol) mfont_get_prop (font, Mstretch);
813   prop[5] = (MSymbol) mfont_get_prop (font, Madstyle);
814   prop[6] = (MSymbol) mfont_get_prop (font, Mregistry);
815   for (len = 0, i = 0; i < 7; i++)
816     {
817       if (prop[i] != Mnil)
818         {
819           str[i] = msymbol_name (prop[i]);
820           len += strlen (str[i]);
821           all_nil = 0;
822         }
823       else
824         {
825           str[i] = "*";
826           len++;
827         }
828     }
829   spacing = (font->spacing == MFONT_SPACING_UNDECIDED ? '*'
830              : font->spacing == MFONT_SPACING_PROPORTIONAL ? 'p'
831              : font->spacing == MFONT_SPACING_MONO ? 'm'
832              : 'c');
833
834   if ((len
835        + 13                     /* 13 dashes */
836        + 2                      /* 2 asterisks */
837        + 30                     /* 3 integers (each 10 digits) */
838        + 1                      /* 1 spacing char */
839        + 1)                     /* '\0' terminal */
840       > 513)
841     return NULL;
842
843   resy = (int) mfont_get_prop (font, Mresolution);
844   size = font->size;
845   if (size >= 0)
846     {
847       if (font->multiple_sizes)
848         {
849           for (size = 0; size < 24; size++)
850             if (font->size & (1 << size))
851               break;
852           size += 6;
853         }
854       else if ((size % 10) < 5)
855         size /= 10;
856       else
857         size = size / 10 + 1;
858     }
859   else
860     size = - size;
861
862   if (full_xlfd)
863     {
864       if (font->size >= 0)
865         sprintf (name, "-%s-%s-%s-%s-%s-%s-%d-*-%d-%d-%c-*-%s",
866                  str[0], str[1], str[2], str[3], str[4], str[5],
867                  size, resy, resy, spacing, str[6]);
868       else
869         sprintf (name, "-%s-%s-%s-%s-%s-%s-*-%d-%d-%d-%c-*-%s",
870                  str[0], str[1], str[2], str[3], str[4], str[5],
871                  size, resy, resy, spacing, str[6]);
872     }
873   else if (all_nil && size == 0)
874     sprintf (name, "*");
875   else
876     {
877       char *p = name;
878
879       p += sprintf (p, "-%s", str[0]);
880       for (i = 1; i < 6; i++)
881         if (p[-1] != '*' || str[i][0] != '*')
882           p += sprintf (p, "-%s", str[i]);
883       if (p[-1] != '*' || font->size > 0)
884         {
885           if (font->size > 0)
886             p += sprintf (p, "-%d-*", size);
887           else
888             p += sprintf (p, "-*");
889         }
890       if (str[6][0] != '*')
891         sprintf (p, "-%s", str[6]);
892     }
893
894   return strdup (name);
895 }
896
897 /* Compare FONT with REQUEST and return how much they differs.  */
898
899 static int
900 font_score (MFont *font, MFont *request)
901 {
902   int score = 0;
903   int i = FONT_SCORE_PRIORITY_SIZE;
904
905   while (--i >= 0)
906     {
907       enum MFontProperty prop = font_score_priority[i];
908       int val;
909
910       if (prop == MFONT_SIZE)
911         {
912           if (font->size && request->size)
913             {
914               if (font->multiple_sizes)
915                 {
916                   int j, closest = 23;
917
918                   for (j = 23; j >= 0; j--)
919                     if (font->size & (1 << j))
920                       {
921                         closest = j;
922                         if (request->size >= (j + 6) * 10)
923                           break;
924                       }
925                   val = request->size - (closest + 6) * 10;
926                 }
927               else
928                 val = font->size - request->size;
929               if (val)
930                 {
931                   if (val < 0)
932                     val = - val;
933                   if (val >= 0x10000)
934                     val = 0xFFFF;
935                   score |= (val << font_score_shift_bits[MFONT_SIZE]);
936                 }
937             }
938         }
939       else if (font->property[prop] && request->property[prop]
940                && font->property[prop] != request->property[prop])
941         {
942           if (prop <= MFONT_FAMILY)
943             val = 1;
944           else if (prop == MFONT_WEIGHT)
945             {
946               unsigned short v1 = font->property[prop];
947               unsigned short v2 = request->property[prop];
948
949               if (v1 == font_weight_regular || v1 == font_weight_normal)
950                 v1 = font_weight_medium;
951               if (v2 == font_weight_regular || v2 == font_weight_normal)
952                 v2 = font_weight_medium;
953               val = v1 > v2 ? v1 - v2 : v2 - v1;
954             }
955           else
956             {
957               val = font->property[prop] - request->property[prop];
958               if (val < 0)
959                 val = - val;
960               if (val > 3)
961                 val = 3;
962             }
963           score |= val << font_score_shift_bits[prop];
964         }
965     }
966   if (request->file != Mnil && request->file != font->file)
967     score |= 40000000;
968   return score;
969 }
970
971 static MSymbol
972 merge_capability (MSymbol capability, MSymbol key, MSymbol val, int overwrite)
973 {
974   MFontCapability *cap = NULL;
975   char *lang = NULL, *script = NULL, *otf = NULL, *buf, *p;
976   int lang_len = 0, script_len = 0, otf_len = 0;
977
978   if (key == Mlanguage)
979     lang = MSYMBOL_NAME (val), lang_len = MSYMBOL_NAMELEN (val) + 6;
980   else if (key == Mscript)
981     script = MSYMBOL_NAME (val), script_len = MSYMBOL_NAMELEN (val) + 7;
982   else if (key == Motf)
983     otf = MSYMBOL_NAME (val), otf_len = MSYMBOL_NAMELEN (val) + 5;
984   else
985     return capability;
986
987   if (capability != Mnil)
988     {
989       cap = mfont__get_capability (capability);
990       if (! overwrite)
991         {
992           if (cap->language)
993             lang = NULL;
994           if (cap->script)
995             script = NULL;
996           if (cap->script_tag)
997             otf = NULL;
998           if (! lang && !script && !otf)
999             return capability;
1000         }
1001     }
1002
1003   if (! lang && cap && cap->language)
1004     {
1005       lang_len = MSYMBOL_NAMELEN (cap->language);
1006       lang = MSYMBOL_NAME (cap->language);
1007     }
1008   if (! script && cap && cap->script != Mnil)
1009     {
1010       script_len = MSYMBOL_NAMELEN (cap->script);
1011       script = MSYMBOL_NAME (cap->script);
1012     }
1013   if (! otf && cap && cap->script_tag)
1014     {
1015       int i;
1016
1017       otf_len = 4;                      /* for script_tag */
1018       if (cap->langsys_tag)
1019         otf_len += 5;           /* for "/XXXX */
1020       for (i = 0; i < MFONT_OTT_MAX; i++)
1021         if (cap->features[i].str)
1022           otf_len += strlen (cap->features[i].str) + 1; /* for "[=+]..." */
1023       otf = p = alloca (otf_len + 1);
1024       OTF_tag_name (cap->script_tag, otf);
1025       p += 4;
1026       if (cap->langsys_tag)
1027         {
1028           *p++ = '/';
1029           OTF_tag_name (cap->langsys_tag, p);
1030           p += 4;
1031         }
1032       if (cap->features[MFONT_OTT_GSUB].str)
1033         p += sprintf (p, "=%s", cap->features[MFONT_OTT_GSUB].str);
1034       if (cap->features[MFONT_OTT_GPOS].str)
1035         p += sprintf (p, "=%s", cap->features[MFONT_OTT_GSUB].str);
1036     }
1037   buf = p = alloca (lang_len + script_len + otf_len + 1);
1038   if (lang_len)
1039     p += sprintf (p, ":lang=%s", lang);
1040   if (script_len)
1041     p += sprintf (p, ":script=%s", script);
1042   if (otf_len)
1043     p += sprintf (p, ":otf=%s", otf);
1044   return msymbol (buf);
1045 }
1046
1047 \f
1048 /* Internal API */
1049
1050 MSymbol Miso8859_1, Miso10646_1, Municode_bmp, Municode_full, Mapple_roman;
1051
1052 int
1053 mfont__init ()
1054 {
1055   int i, shift;
1056   MSymbol regular = msymbol ("regular");
1057   MSymbol normal = msymbol ("normal");
1058   MSymbol medium = msymbol ("medium");
1059
1060   M_font_capability = msymbol_as_managing_key ("  font-capability");
1061   M_font_list = msymbol_as_managing_key ("  font-list");
1062   M_font_list_len = msymbol ("  font-list-len");
1063
1064   Mfoundry = msymbol ("foundry");
1065   mfont__property_table[MFONT_FOUNDRY].property = Mfoundry;
1066   Mfamily = msymbol ("family");
1067   mfont__property_table[MFONT_FAMILY].property = Mfamily;
1068   Mweight = msymbol ("weight");
1069   mfont__property_table[MFONT_WEIGHT].property = Mweight;
1070   Mstyle = msymbol ("style");
1071   mfont__property_table[MFONT_STYLE].property = Mstyle;
1072   Mstretch = msymbol ("stretch");
1073   mfont__property_table[MFONT_STRETCH].property = Mstretch;
1074   Madstyle = msymbol ("adstyle");
1075   mfont__property_table[MFONT_ADSTYLE].property = Madstyle;
1076   Mregistry = msymbol ("registry");
1077   mfont__property_table[MFONT_REGISTRY].property = Mregistry;
1078
1079   Mspacing = msymbol ("spacing");
1080   Msize = msymbol ("size");
1081   Mresolution = msymbol ("resolution");
1082   Mmax_advance = msymbol ("max-advance");
1083   Mfontfile = msymbol ("fontfile");
1084
1085   Mfontconfig = msymbol ("fontconfig");
1086
1087   Mx = msymbol ("x");
1088   Mfreetype = msymbol ("freetype");
1089   Mxft = msymbol ("xft");
1090
1091   Miso8859_1 = msymbol ("iso8859-1");
1092   Miso10646_1 = msymbol ("iso10646-1");
1093   Municode_bmp = msymbol ("unicode-bmp");
1094   Municode_full = msymbol ("unicode-full");
1095   Mapple_roman = msymbol ("apple-roman");
1096
1097   Motf = msymbol ("otf");
1098
1099   /* The first entry of each mfont__property_table must be Mnil so
1100      that actual properties get positive numeric numbers.  */
1101   for (i = 0; i <= MFONT_REGISTRY; i++)
1102     {
1103       MLIST_INIT1 (&mfont__property_table[i], names, 8);
1104       MLIST_APPEND1 (&mfont__property_table[i], names, Mnil, MERROR_FONT);
1105     }
1106
1107   /* Register predefined font property names.  */
1108   for (i = 0; i <= MFONT_REGISTRY; i++)
1109     {
1110       int j;
1111
1112       for (j = 0; j < font_common_names[i].num; j++)
1113         {
1114           MSymbol sym = msymbol (font_common_names[i].names[j]);
1115
1116           if (sym == Mnil)
1117             return -1;
1118           if (msymbol_put (sym, mfont__property_table[i].property,
1119                            (void *) (j + 1)) < 0)
1120             return -1;
1121           MLIST_APPEND1 (&mfont__property_table[i], names, sym,
1122                          MERROR_FONT);
1123           if (i == MFONT_WEIGHT)
1124             {
1125               if (sym == regular)
1126                 font_weight_regular = j + 1;
1127               else if (sym == normal)
1128                 font_weight_normal = j + 1;
1129               else if (sym == medium)
1130                 font_weight_medium = j + 1;
1131             }
1132         }
1133     }
1134
1135   /* Here, SHIFT starts from 1, not 0.  This is because the lowest bit
1136      of a score is a flag for a scalable font (see the documentation
1137      of font_score).  */
1138   i = FONT_SCORE_PRIORITY_SIZE - 1;
1139   for (shift = 1; i >= 0; i--)
1140     {
1141       font_score_shift_bits[font_score_priority[i]] = shift;
1142       if (font_score_priority[i] == MFONT_SIZE)
1143         shift += 16;
1144       else if (font_score_priority[i] <= MFONT_FAMILY)
1145         shift++;
1146       else
1147         shift += 2;
1148     }
1149
1150   MFONT_INIT (&default_encoding.spec);
1151   default_encoding.encoding_name = Municode_full;
1152   default_encoding.encoding_charset = mcharset__unicode;
1153   default_encoding.repertory_name = Mnil;
1154   default_encoding.repertory_charset = NULL;
1155   {
1156     char *path, *buf;
1157     int bufsize;
1158     USE_SAFE_ALLOCA;
1159
1160     mfont_freetype_path = mplist ();
1161     bufsize = strlen (M17NDIR) + 7;
1162     SAFE_ALLOCA (buf, bufsize);
1163     sprintf (buf, "%s/fonts", M17NDIR);
1164     mplist_add (mfont_freetype_path, Mstring, strdup (buf));
1165     path = getenv ("M17NDIR");
1166     if (path)
1167       {
1168         bufsize = strlen (path) + 7;
1169         SAFE_ALLOCA (buf, bufsize);
1170         sprintf (buf, "%s/fonts", path);
1171         mplist_push (mfont_freetype_path, Mstring, strdup (buf));
1172       }
1173     SAFE_FREE (buf);
1174   }
1175
1176 #ifdef HAVE_FREETYPE
1177   if (mfont__ft_init () < 0)
1178     return -1;
1179 #endif /* HAVE_FREETYPE */
1180   if (mfont__flt_init () < 0)
1181     return -1;
1182
1183   return 0;
1184 }
1185
1186 void
1187 mfont__fini ()
1188 {
1189   MPlist *plist;
1190   int i;
1191
1192   mfont__flt_fini ();
1193 #ifdef HAVE_FREETYPE
1194   mfont__ft_fini ();
1195 #endif /* HAVE_FREETYPE */
1196
1197   MPLIST_DO (plist, mfont_freetype_path)
1198     free (MPLIST_VAL (plist));
1199   M17N_OBJECT_UNREF (mfont_freetype_path);
1200
1201   if (font_resize_list)
1202     {
1203       MPLIST_DO (plist, font_resize_list)
1204         free (MPLIST_VAL (plist));
1205       M17N_OBJECT_UNREF (font_resize_list);
1206       font_resize_list = NULL;
1207     }
1208   if (font_encoding_list)
1209     {
1210       MPLIST_DO (plist, font_encoding_list)
1211         free (MPLIST_VAL (plist));
1212       M17N_OBJECT_UNREF (font_encoding_list);
1213       font_encoding_list = NULL;
1214     }
1215
1216   for (i = 0; i <= MFONT_REGISTRY; i++)
1217     MLIST_FREE1 (&mfont__property_table[i], names);
1218 }
1219
1220
1221 MSymbol
1222 mfont__id (MFont *font)
1223 {
1224   char *buf, *p;
1225   int i;
1226   int file_len = (font->file == Mnil ? 0 : MSYMBOL_NAMELEN (font->file));
1227   int capability_len  = (font->capability == Mnil ? 0
1228                          : MSYMBOL_NAMELEN (font->capability));
1229   int total_len = MFONT_PROPERTY_MAX * 5 + 9 + file_len + capability_len;
1230   MSymbol id;
1231   USE_SAFE_ALLOCA;
1232
1233   SAFE_ALLOCA (buf, total_len);
1234   p = buf;
1235   if (font->property[0])
1236     p += sprintf (p, "%X", font->property[0]);
1237   for (i = 1; i < MFONT_PROPERTY_MAX; i++)
1238     {
1239       if (font->property[i])
1240         p += sprintf (p, "-%X", font->property[i]);
1241       else
1242         *p++ = '-';
1243     }
1244   if (font->size)
1245     p += sprintf (p, "-%X", font->size);
1246   if (font->spacing)
1247     p += sprintf (p, "-%X", font->spacing);
1248   if (capability_len > 0)
1249     {
1250       *p++ = '-';
1251       memcpy (p, MSYMBOL_NAME (font->capability), capability_len);
1252       p += capability_len;
1253     }
1254   if (file_len > 0)
1255     {
1256       *p++ = '-';
1257       memcpy (p, MSYMBOL_NAME (font->file), file_len);
1258       p += file_len;
1259     }      
1260   id = msymbol__with_len (buf, p - buf);
1261   SAFE_FREE (buf);
1262   return id;
1263 }
1264
1265 /** Return 1 iff FONT matches SPEC.  */
1266
1267 int
1268 mfont__match_p (MFont *font, MFont *spec, int prop)
1269 {
1270   if (spec->capability != font->capability
1271       && spec->capability != Mnil)
1272     {
1273       MRealizedFont *rfont;
1274
1275       if (font->type != MFONT_TYPE_REALIZED)
1276         return (font->capability == Mnil);
1277       rfont = (MRealizedFont *) font;
1278       return (rfont->driver->check_capability
1279               && (rfont->driver->check_capability (rfont, spec->capability)
1280                   >= 0));
1281     }
1282   if (spec->file != font->file
1283       && spec->file != Mnil && font->file != Mnil)
1284     return 0;
1285   for (; prop >= 0; prop--)
1286     if (spec->property[prop] && font->property[prop]
1287         && font->property[prop] != spec->property[prop])
1288       return 0;
1289   return 1;
1290 }
1291
1292 /* Merge SRC into DST.  If error_on_conflict is nonzero and a font
1293    property differs in SRC and DST, return -1.  */
1294
1295 int
1296 mfont__merge (MFont *dst, MFont *src, int error_on_conflict)
1297 {
1298   int i;
1299
1300   for (i = 0; i < MFONT_PROPERTY_MAX; i++)
1301     {
1302       if (! dst->property[i])
1303         dst->property[i] = src->property[i];
1304       else if (error_on_conflict
1305                && src->property[i]
1306                && dst->property[i] != src->property[i])
1307         return -1;
1308     }
1309   if (! dst->spacing)
1310     dst->spacing = src->spacing;
1311   else if (error_on_conflict
1312            && src->spacing
1313            && dst->spacing != src->spacing)
1314     return -1;
1315   if (! dst->size)
1316     dst->size = src->size;
1317   else if (error_on_conflict
1318            && src->size
1319            && dst->size != src->size)
1320     return -1;
1321   if (dst->capability == Mnil)
1322     dst->capability = src->capability;
1323   else if (error_on_conflict
1324            && src->capability
1325            && dst->capability != src->capability)
1326     return -1;
1327   if (dst->file == Mnil)
1328     dst->file = src->file;
1329   else if (error_on_conflict
1330            && src->file
1331            && dst->file != src->file)
1332     return -1;
1333   return 0;
1334 }
1335
1336 void
1337 mfont__set_spec_from_face (MFont *spec, MFace *face)
1338 {
1339   int i;
1340
1341   for (i = 0; i <= MFONT_ADSTYLE; i++)
1342     mfont__set_property (spec, i, face->property[i]);
1343   spec->property[MFONT_REGISTRY] = 0;
1344   spec->property[MFONT_RESY] = 0;
1345   spec->multiple_sizes = 0;
1346   spec->size = (int) (face->property[MFACE_SIZE]);
1347   spec->type = MFONT_TYPE_SPEC;
1348   spec->source = MFONT_SOURCE_UNDECIDED;
1349   spec->file = spec->capability = Mnil;
1350   spec->encoding = NULL;
1351 }
1352
1353
1354 extern MSymbol
1355 mfont__set_spec_from_plist (MFont *spec, MPlist *plist)
1356 {
1357   int i;
1358   MSymbol spec_list[MFONT_REGISTRY + 1];
1359   MSymbol registry;
1360   char *reg;
1361
1362   MFONT_INIT (spec);
1363   memset (spec_list, 0, sizeof spec_list);
1364   for (i = 0; ! MPLIST_TAIL_P (plist); i++, plist = MPLIST_NEXT (plist))
1365     {
1366       if (! MPLIST_SYMBOL_P (plist))
1367         MERROR (MERROR_FONT, Mnil);     
1368       spec_list[i] = MPLIST_SYMBOL (plist);
1369     }
1370   registry = spec_list[i - 1];
1371   if (i > 1 && registry != Mnil)
1372     {
1373       reg = MSYMBOL_NAME (registry);
1374       if (reg[0] == ':')
1375         {
1376           mfont__get_capability (registry);
1377           spec->capability = registry;
1378           registry = spec_list[i - 2];
1379           i--;
1380         }
1381     }
1382   mfont__set_property (spec, MFONT_REGISTRY, registry);
1383   for (i -= 2; i >= 0; i--)
1384     mfont__set_property (spec, i, spec_list[i]);
1385   spec->type = MFONT_TYPE_SPEC;
1386
1387   return registry;
1388 }
1389
1390
1391 MFont *
1392 mfont__select (MFrame *frame, MFont *font, int max_size)
1393 {
1394   MFontDriver *driver;
1395
1396   if (font->type == MFONT_TYPE_FAILURE)
1397     return NULL;
1398   if (font->type != MFONT_TYPE_SPEC)
1399     return font;
1400   if (font->source == MFONT_SOURCE_UNDECIDED)
1401     {
1402       if (font->file != Mnil || font->capability != Mnil)
1403         font->source = MFONT_SOURCE_FT;
1404       else if (font->property[MFONT_REGISTRY])
1405         {
1406           MSymbol registry = FONT_PROPERTY (font, MFONT_REGISTRY);
1407           char *reg = MSYMBOL_NAME (registry);
1408
1409           if (strncmp (reg, "unicode-", 8) == 0
1410               || strncmp (reg, "apple-roman", 11) == 0
1411               || (reg[0] >= '0' && reg[0] <= '9' && reg[1] == '-'))
1412             font->source = MFONT_SOURCE_FT;
1413         }
1414     }
1415   if (font->source != MFONT_SOURCE_FT)
1416     {
1417       driver = mplist_get (frame->font_driver_list, Mx);
1418       if (driver)
1419         return (driver->select) (frame, font, max_size);
1420     }
1421   driver = mplist_get (frame->font_driver_list, Mfreetype);
1422   if (! driver)
1423     return NULL;
1424   return (driver->select) (frame, font, max_size);
1425 }
1426
1427
1428 int
1429 mfont__available (MFrame *frame, MFont *font)
1430 {
1431   return -1;
1432 }
1433
1434 static int
1435 compare_font_score (const void *e1, const void *e2)
1436 {
1437   MFontScore *s1 = (MFontScore *) e1, *s2 = (MFontScore *) e2;
1438
1439   return (s1->font->for_full_width == s2->font->for_full_width
1440           ? s1->score > s2->score
1441           : s1->font->for_full_width);
1442 }
1443
1444 void
1445 mdebug_dump_font_list (MFontList *font_list)
1446 {
1447   int i;
1448
1449   for (i = 0; i < font_list->nfonts; i++)
1450     {
1451       fprintf (stderr, "%04X - ", font_list->fonts[i].score);
1452       mdebug_dump_font (font_list->fonts[i].font);
1453       fprintf (stderr, "\n");
1454     }
1455 }
1456
1457 void
1458 mfont__free_realized (MRealizedFont *rfont)
1459 {
1460   MRealizedFont *next;
1461
1462   for (; rfont; rfont = next)
1463     {
1464       next = rfont->next;
1465       M17N_OBJECT_UNREF (rfont->info);
1466       free (rfont);
1467       rfont = next;
1468     }
1469 }
1470
1471 MFontList *
1472 mfont__list (MFrame *frame, MFont *spec, MFont *request, int max_size)
1473 {
1474   MFontList *list;
1475   MSymbol id = mfont__id (spec);
1476   MPlist *pl, *p;
1477   int num, i;
1478
1479   pl = msymbol_get (id, M_font_list);
1480   if (pl)
1481     num = (int) msymbol_get (id, M_font_list_len);
1482   else
1483     {
1484       pl = mplist ();
1485       num = 0;
1486       MPLIST_DO (p, frame->font_driver_list)
1487         {
1488           if (spec->source == MFONT_SOURCE_X ? MPLIST_KEY (p) == Mx
1489               : spec->source == MFONT_SOURCE_FT ? MPLIST_KEY (p) == Mfreetype
1490               : 1)
1491             {
1492               MFontDriver *driver = MPLIST_VAL (p);
1493               num += (driver->list) (frame, pl, spec, 0);
1494             }
1495         }
1496       msymbol_put (id, M_font_list, pl);
1497       M17N_OBJECT_UNREF (pl);
1498       msymbol_put (id, M_font_list_len, (void *) num);
1499     }
1500   
1501   if (num == 0)
1502     return NULL;
1503
1504   MSTRUCT_MALLOC (list, MERROR_FONT);
1505   MTABLE_MALLOC (list->fonts, num, MERROR_FONT);
1506   for (i = 0; num > 0; num--, pl = MPLIST_NEXT (pl))
1507     {
1508       MFont *font = MPLIST_VAL (pl), *adjusted = font;
1509
1510       if (max_size == 0
1511           || font->size == 0
1512           || font->size < max_size)
1513         {
1514           list->fonts[i].font = font;
1515           if (spec == request)
1516             list->fonts[i].score = 0;
1517           else
1518             {
1519               int resize_ratio;
1520               MFont resized;
1521
1522               if (font->size > 0
1523                   && (resize_ratio = mfont_resize_ratio (font)) != 100)
1524                 {
1525                   resized = *font;
1526                   resized.size = font->size * 100 / resize_ratio;
1527                   adjusted = &resized;
1528                 }
1529               list->fonts[i].score = font_score (adjusted, request);
1530             }
1531           i++;
1532         }
1533     }
1534   if (i == 0)
1535     {
1536       free (list->fonts);
1537       free (list);
1538       return NULL;
1539     }
1540   list->nfonts = i;
1541   if (spec != request)
1542     qsort (list->fonts, i, sizeof (MFontScore), compare_font_score);
1543   list->object = *spec;
1544   mfont__merge (&list->object, request, 0);
1545   list->object.type = MFONT_TYPE_OBJECT;
1546   return list;
1547 }
1548
1549 /** Open a font specified in FONT.  */
1550
1551 MRealizedFont *
1552 mfont__open (MFrame *frame, MFont *font, MFont *spec)
1553 {
1554   MFontDriver *driver;
1555   MRealizedFont *rfont;
1556
1557   if (font->source == MFONT_SOURCE_UNDECIDED)
1558     MFATAL (MERROR_FONT);
1559   if (font->type != MFONT_TYPE_OBJECT)
1560     MFATAL (MERROR_FONT);
1561   for (rfont = MPLIST_VAL (frame->realized_font_list); rfont;
1562        rfont = rfont->next)
1563     {
1564       driver = rfont->driver;
1565       if (rfont->font == font
1566           && mplist_find_by_value (frame->font_driver_list, driver))
1567         break;
1568     }
1569
1570   if (! rfont)
1571     {
1572       driver = mplist_get (frame->font_driver_list,
1573                            font->source == MFONT_SOURCE_X ? Mx : Mfreetype);
1574       if (! driver)
1575         MFATAL (MERROR_FONT);
1576     }
1577   return (driver->open) (frame, font, spec, rfont);
1578 }
1579
1580 int
1581 mfont__has_char (MFrame *frame, MFont *font, MFont *spec, int c)
1582 {
1583   MFontEncoding *encoding;
1584   unsigned code;
1585   MFontDriver *driver;
1586
1587   if (font->source == MFONT_SOURCE_UNDECIDED)
1588     MFATAL (MERROR_FONT);
1589   encoding = (font->encoding ? font->encoding : find_encoding (font));
1590   if (! encoding->encoding_charset)
1591     return 0;
1592   if (encoding->repertory_charset)
1593     {
1594       code = ENCODE_CHAR (encoding->repertory_charset, c);
1595       return (code != MCHAR_INVALID_CODE);
1596     }
1597   code = ENCODE_CHAR (encoding->encoding_charset, c);
1598   if (code == MCHAR_INVALID_CODE)
1599     return 0;
1600   if (font->type == MFONT_TYPE_REALIZED)
1601     driver = ((MRealizedFont *) font)->driver;
1602   else
1603     {
1604       driver = mplist_get (frame->font_driver_list,
1605                            font->source == MFONT_SOURCE_X ? Mx : Mfreetype);
1606       if (! driver)
1607         MFATAL (MERROR_FONT);
1608     }
1609   return (driver->has_char) (frame, font, spec, c, code);
1610 }
1611
1612 unsigned
1613 mfont__encode_char (MFrame *frame, MFont *font, MFont *spec, int c)
1614 {
1615   MFontEncoding *encoding;
1616   unsigned code;
1617   MFontDriver *driver;
1618
1619   if (font->source == MFONT_SOURCE_UNDECIDED)
1620     MFATAL (MERROR_FONT);
1621   encoding = (font->encoding ? font->encoding : find_encoding (font));
1622   if (! encoding->encoding_charset)
1623     return MCHAR_INVALID_CODE;
1624   if (font->source == MFONT_SOURCE_X && encoding->repertory_charset)
1625     return (ENCODE_CHAR (encoding->repertory_charset, c));
1626   code = ENCODE_CHAR (encoding->encoding_charset, c);
1627   if (code == MCHAR_INVALID_CODE)
1628     return MCHAR_INVALID_CODE;
1629   if (font->type == MFONT_TYPE_REALIZED)
1630     driver = ((MRealizedFont *) font)->driver;
1631   else
1632     {
1633       driver = mplist_get (frame->font_driver_list,
1634                            font->source == MFONT_SOURCE_X ? Mx : Mfreetype);
1635       if (! driver)
1636         MFATAL (MERROR_FONT);
1637     }
1638   return (driver->encode_char) (frame, font, spec, code);
1639 }
1640
1641 void
1642 mfont__get_metric (MGlyphString *gstring, int from, int to)
1643 {
1644   MGlyph *from_g = MGLYPH (from), *to_g = MGLYPH (to), *g;
1645   MRealizedFont *rfont = from_g->rface->rfont;
1646
1647   for (g = from_g; g != to_g; g++)
1648     if (g->rface->rfont != rfont)
1649       {
1650         int idx = GLYPH_INDEX (g);
1651
1652         (rfont->driver->find_metric) (rfont, gstring, from, idx);
1653         from_g = g;
1654         rfont = g->rface->rfont;
1655         from = idx;
1656       }
1657   (rfont->driver->find_metric) (rfont, gstring, from, GLYPH_INDEX (g));
1658 }
1659
1660
1661 /* KEY <= MFONT_REGISTRY */
1662
1663 void
1664 mfont__set_property (MFont *font, enum MFontProperty key, MSymbol val)
1665 {
1666   int numeric;
1667
1668   if (val == Mnil)
1669     numeric = 0;
1670   else
1671     {
1672       numeric = FONT_PROPERTY_NUMERIC (val, key);
1673       if (! numeric)
1674         {
1675           numeric = mfont__property_table[key].used;
1676           MLIST_APPEND1 (mfont__property_table + key, names, val, MERROR_FONT);
1677           SET_FONT_PROPERTY_NUMERIC (val, key, numeric);
1678         }
1679     }
1680   font->property[key] = numeric;
1681 }
1682
1683 int
1684 mfont__parse_name_into_font (const char *name, MSymbol format, MFont *font)
1685 {
1686   int result = -1;
1687
1688   if (format == Mx || format == Mnil)
1689     result = xlfd_parse_name (name, font);
1690 #ifdef HAVE_FONTCONFIG
1691   if (format == Mfontconfig || (result < 0 && format == Mnil))
1692     result = mfont__ft_parse_name (name, font);
1693 #endif /* HAVE_FONTCONFIG */
1694   return result;
1695 }
1696
1697 MPlist *
1698 mfont__encoding_list (void)
1699 {
1700   if (! font_encoding_list)
1701     load_font_encoding_table ();
1702   return font_encoding_list;
1703 }
1704
1705 static void
1706 free_font_capability (void *object)
1707 {
1708   MFontCapability *cap = object;
1709   
1710   if (cap->script_tag)
1711     {
1712       int i;
1713       for (i = 0; i < MFONT_OTT_MAX; i++)
1714         {
1715           if (cap->features[i].str)
1716             free (cap->features[i].str);
1717           if (cap->features[i].tags)
1718             free (cap->features[i].tags);
1719         }
1720     }
1721   free (cap);
1722 }
1723
1724 MFontCapability *
1725 mfont__get_capability (MSymbol sym)
1726 {
1727   MFontCapability *cap = msymbol_get (sym, M_font_capability);
1728   char *str, *p, *endp;
1729
1730   if (cap)
1731     return cap;
1732   str = MSYMBOL_NAME (sym);
1733   if (str[0] != ':')
1734     return NULL;
1735   M17N_OBJECT (cap, free_font_capability, MERROR_FONT);
1736   msymbol_put (sym, M_font_capability, cap);
1737   M17N_OBJECT_UNREF (cap);
1738   endp = str + MSYMBOL_NAMELEN (sym);
1739   while (str < endp)
1740     {
1741       if (*str++ != ':')
1742         continue;
1743       if (str[0] == 'o' && strncmp (str + 1, "tf=", 3) == 0)
1744         {
1745           char *beg;
1746           MSymbol sym;
1747           int i;
1748
1749           str += 4;
1750           beg = str;
1751           for (i = 0, p = str; i < 4 && p < endp; i++, p++);
1752           if (i < 4)
1753             break;
1754           sym = msymbol__with_len (str, 4);
1755           cap->script = mscript__from_otf_tag (sym);
1756           if (cap->script == Mnil)
1757             break;
1758           cap->script_tag = OTF_tag (str);
1759           if (*p == '/')
1760             {
1761               for (i = 0, str = ++p; i < 4 && p < endp; i++, p++);
1762               if (i < 4)
1763                 {
1764                   cap->script = Mnil;
1765                   cap->script_tag = 0;
1766                   break;
1767                 }
1768               cap->langsys_tag = OTF_tag (str);
1769             }
1770           else
1771             cap->langsys_tag = 0;
1772
1773           for (i = 0; i < MFONT_OTT_MAX; i++)
1774             cap->features[i].nfeatures = -1;
1775
1776           while (*p == '=' || *p == '+')
1777             {
1778               int idx = *p == '=' ? MFONT_OTT_GSUB : MFONT_OTT_GPOS;
1779
1780               str = ++p;
1781               while (p < endp && *p != '+') p++;
1782               if (str < p)
1783                 {
1784                   int n;
1785                   /* We never have more than (p - str) tags.  */
1786                   OTF_Tag *tags = alloca (sizeof (OTF_Tag) * (p - str));
1787                   char *p0;
1788
1789                   cap->features[idx].str = malloc (p - str + 1);
1790                   for (i = n = 0, p0 = str; str + i < p; i++)
1791                     {
1792                       cap->features[idx].str[i] = str[i];
1793                       if (str[i] == ',' || str + i + 1 == p)
1794                         {
1795                           if (*p0 == '*')
1796                             tags[n] = 0;
1797                           else if (*p0 == '~')
1798                             tags[n] = OTF_tag (p0 + 1) | 0x80000000;
1799                           else
1800                             tags[n] = OTF_tag (p0);
1801                           n++;
1802                           p0 = str + i + 1;
1803                         }
1804                     }
1805                   cap->features[idx].str[i] = '\0';
1806                   cap->features[idx].nfeatures = n;
1807                   if (n > 0)
1808                     {
1809                       int size = sizeof (OTF_Tag) * n;
1810
1811                       cap->features[idx].tags = malloc (size);
1812                       memcpy (cap->features[idx].tags, tags, size);
1813                     }
1814                 }
1815               else
1816                 {
1817                   cap->features[idx].str = NULL;
1818                   cap->features[idx].nfeatures = 0;
1819                 }
1820             }
1821
1822           for (i = 0; i < MFONT_OTT_MAX; i++)
1823             if (cap->features[i].nfeatures < 0)
1824               {
1825                 cap->features[i].str = strdup ("*");
1826                 cap->features[i].nfeatures = 1;
1827                 cap->features[i].tags = malloc (sizeof (OTF_Tag));
1828                 cap->features[i].tags[0] = 0;
1829               }
1830           cap->otf = msymbol__with_len (beg, p - beg);
1831           str = p;
1832         }
1833       else if (str[0] == 'l' && strncmp (str + 1, "ang=", 4) == 0)
1834         {
1835           str += 5;
1836           for (p = str; p < endp && *p != ':'; p++);
1837           if (str < p)
1838             cap->language = msymbol__with_len (str, p - str);
1839           str = p;
1840         }
1841       else if (str[0] == 's' && strncmp (str + 1, "cript=", 6) == 0)
1842         {
1843           str += 7;
1844           for (p = str; p < endp && *p != ':'; p++);
1845           if (str < p)
1846             cap->script = msymbol__with_len (str, p - str);
1847           str = p;
1848         }
1849     }
1850   return cap;
1851 }
1852
1853 int
1854 mfont__check_capability (MRealizedFont *rfont, MSymbol capability)
1855 {
1856   return (rfont->driver->check_capability (rfont, capability));
1857 }
1858
1859
1860 /*** @} */
1861 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
1862
1863 \f
1864
1865 /* External API */
1866
1867 /*** @addtogroup m17nFont */
1868 /*** @{ */
1869 /*=*/
1870
1871 /***en @name Variables: Keys of font property.  */
1872 /***ja @name ÊÑ¿ô: ¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤ò»ØÄꤹ¤ëÄêµÁºÑ¤ß¥·¥ó¥Ü¥ë */
1873 /*** @{ */
1874 /*=*/
1875
1876 /***en
1877     @brief Key of font property specifying foundry.
1878
1879     The variable #Mfoundry is a symbol of name <tt>"foundry"</tt> and
1880     is used as a key of font property and face property.  The property
1881     value must be a symbol whose name is a foundry name of a font.  */
1882 /***ja
1883     @brief ³«È¯¸µ¤ò»ØÄꤹ¤ë¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼.
1884     
1885     ÊÑ¿ô #Mfoundry ¤Ï <tt>"fonudry"</tt> 
1886     ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤È¥Õ¥§¡¼¥¹¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼¤È¤·¤ÆÍѤ¤¤é¤ì¤ë¡£
1887     Ãͤϡ¢¥Õ¥©¥ó¥È¤Î³«È¯¸µÌ¾¤ò̾Á°¤È¤·¤Æ»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£    */
1888
1889 MSymbol Mfoundry;
1890
1891 /***en
1892     @brief Key of font property specifying family.
1893
1894     The variable #Mfamily is a symbol of name <tt>"family"</tt> and is
1895     used as a key of font property and face property.  The property
1896     value must be a symbol whose name is a family name of a font.  */ 
1897 /***ja
1898     @brief ¥Õ¥¡¥ß¥ê¤ò»ØÄꤹ¤ë¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼.
1899     
1900     ÊÑ¿ô #Mfamily ¤Ï <tt>"family"</tt> 
1901     ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤È¥Õ¥§¡¼¥¹¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼¤È¤·¤ÆÍѤ¤¤é¤ì¤ë¡£
1902     Ãͤϡ¢¥Õ¥©¥ó¥È¤Î¥Õ¥¡¥ß¥ê̾¤ò̾Á°¤È¤·¤Æ»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£    */
1903
1904 MSymbol Mfamily;
1905
1906 /***en
1907     @brief Key of font property specifying weight.
1908
1909     The variable #Mweight is a symbol of name <tt>"weight"</tt> and is
1910     used as a key of font property and face property.  The property
1911     value must be a symbol whose name is a weight name of a font (e.g
1912     "medium", "bold").  */ 
1913 /***ja
1914     @brief ÂÀ¤µ¤ò»ØÄꤹ¤ë¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼.
1915     
1916     ÊÑ¿ô #Mweight ¤Ï <tt>"weight"</tt> 
1917     ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤È¥Õ¥§¡¼¥¹¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼¤È¤·¤ÆÍѤ¤¤é¤ì¤ë¡£
1918     Ãͤϡ¢¥Õ¥©¥ó¥È¤ÎÂÀ¤µÌ¾ ( "medium", "bold" Åù) ¤ò̾Á°¤È¤·¤Æ»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£    */
1919
1920 MSymbol Mweight;
1921
1922 /***en
1923     @brief Key of font property specifying style.
1924
1925     The variable #Mstyle is a symbol of name <tt>"style"</tt> and is
1926     used as a key of font property and face property.  The property
1927     value must be a symbol whose name is a style name of a font (e.g
1928     "r", "i", "o").  */ 
1929 /***ja
1930     @brief ¥¹¥¿¥¤¥ë¤ò»ØÄꤹ¤ë¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼.
1931     
1932     ÊÑ¿ô #Mstyle ¤Ï <tt>"style"</tt> 
1933     ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤È¥Õ¥§¡¼¥¹¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼¤È¤·¤ÆÍѤ¤¤é¤ì¤ë¡£
1934     Ãͤϡ¢¥Õ¥©¥ó¥È¤Î¥¹¥¿¥¤¥ë̾ ("r", "i", "o" Åù)¤ò̾Á°¤È¤·¤Æ»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£    */
1935
1936 MSymbol Mstyle;
1937
1938 /***en
1939     @brief Key of font property specifying stretch.
1940
1941     The variable #Mstretch is a symbol of name <tt>"stretch"</tt> and
1942     is used as a key of font property and face property.  The property
1943     value must be a symbol whose name is a stretch name of a font (e.g
1944     "normal", "condensed").  */ 
1945 /***ja
1946     @brief Éý¤ò»ØÄꤹ¤ë¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼.
1947     
1948     ÊÑ¿ô #Mstretch ¤Ï <tt>"stretch"</tt> 
1949     ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤È¥Õ¥§¡¼¥¹¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼¤È¤·¤ÆÍѤ¤¤é¤ì¤ë¡£
1950     Ãͤϡ¢¥Õ¥©¥ó¥È¤Îʸ»úÉý̾ ( "normal", "condensed" Åù)¤ò̾Á°¤È¤·¤Æ»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£    */
1951
1952 MSymbol Mstretch;
1953
1954 /***en
1955     @brief Key of font property specifying additional style.
1956
1957     The variable #Madstyle is a symbol of name <tt>"adstyle"</tt> and
1958     is used as a key of font property and face property.  The property
1959     value must be a symbol whose name is an additional style name of a
1960     font (e.g "serif", "", "sans").  */ 
1961 /***ja
1962     @brief adstyle ¤ò»ØÄꤹ¤ë¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼.
1963     
1964     ÊÑ¿ô #Madstyle ¤Ï <tt>"adstyle"</tt> 
1965     ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤È¥Õ¥§¡¼¥¹¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼¤È¤·¤ÆÍѤ¤¤é¤ì¤ë¡£
1966     Ãͤϡ¢¥Õ¥©¥ó¥È¤Î adstyle Ì¾("serif", "", "sans" Åù)¤ò̾Á°¤È¤·¤Æ»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£    */
1967
1968 MSymbol Madstyle;
1969
1970 /***en
1971     @brief Key of font property specifying spacing.
1972
1973     The variable #Madstyle is a symbol of name <tt>"spacing"</tt> and
1974     is used as a key of font property.  The property value must be a
1975     symbol whose name specifies the spacing of a font (e.g "p" for
1976     proportional, "m" for monospaced).  */ 
1977 /***ja
1978     @brief spacing ¤ò»ØÄꤹ¤ë¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼.
1979     
1980     ÊÑ¿ô #Mspacing ¤Ï <tt>"spacing"</tt> ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢
1981     ¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼¤È¤·¤ÆÍѤ¤¤é¤ì¤ë¡£Ãͤϡ¢¥Õ¥©¥ó¥È¤Î spacing
1982     ÆÃÀ­¤ò¼¨¤¹Ì¾Á° ("p", "m" Åù)¤ò»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£  */
1983
1984 MSymbol Mspacing;
1985
1986 /***en
1987     @brief Key of font property specifying registry.
1988
1989     The variable #Mregistry is a symbol of name <tt>"registry"</tt>
1990     and is used as a key of font property.  The property value must be
1991     a symbol whose name is a registry name a font registry
1992     (e.g. "iso8859-1", "jisx0208.1983-0").  */ 
1993 /***ja
1994     @brief ¥ì¥¸¥¹¥È¥ê¤ò»ØÄꤹ¤ë¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼.
1995     
1996     ÊÑ¿ô #Mregistry ¤Ï <tt>"registry"</tt> 
1997     ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤È¥Õ¥§¡¼¥¹¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼¤È¤·¤ÆÍѤ¤¤é¤ì¤ë¡£
1998     Ãͤϡ¢¥Õ¥©¥ó¥È¤Î¥ì¥¸¥¹¥È¥ê̾ ( "iso8859-1", "jisx0208.1983-0" 
1999     Åù) ¤ò̾Á°¤È¤·¤Æ»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£    */
2000
2001 MSymbol Mregistry;
2002
2003 /***en
2004     @brief Key of font property specifying size.
2005
2006     The variable #Msize is a symbol of name <tt>"size"</tt> and is
2007     used as a key of font property and face property.  The property
2008     value must be an integer specifying a font design size in the unit
2009     of 1/10 point (on 100 dpi display).  */ 
2010 /***ja
2011     @brief ¥µ¥¤¥º¤ò»ØÄꤹ¤ë¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼.
2012     
2013     ÊÑ¿ô #Msize ¤Ï <tt>"size"</tt> 
2014     ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤È¥Õ¥§¡¼¥¹¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼¤È¤·¤ÆÍѤ¤¤é¤ì¤ë¡£Ãͤϡ¢
2015     100 dpi ¤Î¥Ç¥£¥¹¥×¥ì¥¤¾å¤Ç¤Î¥Õ¥©¥ó¥È¤Î¥Ç¥¶¥¤¥ó¥µ¥¤¥º¤ò 1/10 
2016     ¥Ý¥¤¥ó¥Èñ°Ì¤Ç¼¨¤¹À°¿ôÃͤǤ¢¤ë¡£
2017     */
2018
2019 MSymbol Msize;
2020
2021 /***en
2022     @brief Key of font property specifying file name.
2023
2024     The variable #Mfontfile is a symbol of name <tt>"fontfile"</tt>
2025     and is used as a key of font property.  The property value must be
2026     a symbol whose name is a font file name.  */ 
2027 MSymbol Motf;
2028
2029 /***en
2030     @brief Key of font property specifying file name.
2031
2032     The variable #Mfontfile is a symbol of name <tt>"fontfile"</tt>
2033     and is used as a key of font property.  The property value must be
2034     a symbol whose name is a font file name.  */ 
2035 /***ja
2036     @brief ¥Õ¥©¥ó¥È¥Õ¥¡¥¤¥ë¤ò»ØÄꤹ¤ë¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼.
2037     
2038     ÊÑ¿ô #Mfontfile ¤Ï <tt>"fontfile"</tt> ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢
2039     ¤ê¡¢¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼¤È¤·¤ÆÍѤ¤¤é¤ì¤ë¡£Ãͤϡ¢¥Õ¥©¥ó¥È¥Õ¥¡¥¤
2040     ¥ë̾¤ò̾Á°¤È¤·¤Æ»ý¤Ä¤È¤¹¤ë¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£ */
2041
2042 MSymbol Mfontfile;
2043
2044 /***en
2045     @brief Key of font property specifying resolution.
2046
2047     The variable #Mresolution is a symbol of name <tt>"resolution"</tt> and
2048     is used as a key of font property and face property.  The property
2049     value must be an integer to specifying a font resolution in the
2050     unit of dots per inch (dpi).  */ 
2051 /***ja
2052     @brief ²òÁüÅÙ¤ò»ØÄꤹ¤ë¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼.
2053     
2054     ÊÑ¿ô #Mresolution ¤Ï <tt>"resolution"</tt> 
2055     ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤È¥Õ¥§¡¼¥¹¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼¤È¤·¤ÆÍѤ¤¤é¤ì¤ë¡£
2056     Ãͤϡ¢¥Õ¥©¥ó¥È¤Î²òÁüÅÙ¤ò dots per inch (dpi) Ã±°Ì¤Ç¼¨¤¹À°¿ôÃͤǤ¢¤ë¡£    */
2057
2058 MSymbol Mresolution;
2059
2060 /***en
2061     @brief Key of font property specifying max advance width.
2062
2063     The variable #Mmax_advance is a symbol of name
2064     <tt>"max-advance"</tt> and is used as a key of font property.  The
2065     property value must be an integer specifying a font's max advance
2066     value by pixels.  */ 
2067
2068 MSymbol Mmax_advance;
2069
2070
2071 /***en
2072     @brief Symbol of name "fontconfig".
2073
2074     The variable #Mfontconfig is to be used as an argument of the
2075     functions mfont_parse_name () and mfont_unparse_name ().  */
2076 /***ja
2077     @brief "fontconfig" ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë.
2078
2079     ÊÑ¿ô #Mfontconfig ¤Ï´Ø¿ô mfont_parse_name () ¤È mfont_unparse_name ()
2080     ¤Î°ú¿ô¤È¤·¤ÆÍѤ¤¤é¤ì¤ë¡£  */
2081
2082 MSymbol Mfontconfig;
2083
2084 /***en
2085     @brief Symbol of name "x".
2086
2087     The variable #Mx is to be used for a value of <type> member of the
2088     structure #MDrawGlyph to specify the type of <fontp> member is
2089     actually (XFontStruct *).  */
2090 /***ja
2091     @brief "x" ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë.
2092
2093     ÊÑ¿ô #Mx ¤Ï¹½Â¤ #MDrawGlyph ¤Î¥á¥ó¥Ð <type> 
2094     ¤ÎÃͤȤ·¤ÆÍѤ¤¤é¤ì¡¢¥á¥ó¥Ð <fontp> ¤Î·¿¤¬¼ÂºÝ¤Ë¤Ï (XFontStruct *) ¤Ç¤¢¤ë¤³¤È¤òɽ¤¹.  */
2095
2096 MSymbol Mx;
2097
2098 /***en
2099     @brief Symbol of name "freetype".
2100
2101     The variable #Mfreetype is to be used for a value of <type> member
2102     of the structure #MDrawGlyph to specify the type of <fontp> member
2103     is actually FT_Face.  */
2104 /***ja
2105     @brief "freetype" ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë.
2106
2107     ÊÑ¿ô #Mfreetype ¤Ï¹½Â¤ #MDrawGlyph ¤Î¥á¥ó¥Ð <type> 
2108     ¤ÎÃͤȤ·¤ÆÍѤ¤¤é¤ì¡¢¥á¥ó¥Ð <fontp> ¤Î·¿¤¬¼ÂºÝ¤Ë¤Ï FT_Face ¤Ç¤¢¤ë¤³¤È¤òɽ¤¹¡£  */
2109
2110 MSymbol Mfreetype;
2111
2112 /***en
2113     @brief Symbol of name "xft".
2114
2115     The variable #Mxft is to be used for a value of <type> member of the
2116     structure #MDrawGlyph to specify the type of <fontp> member
2117     is actually (XftFont *).  */
2118 /***ja
2119     @brief  "xft" ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë.
2120
2121     ÊÑ¿ô #Mxft ¤Ï¹½Â¤ #MDrawGlyph ¤Î¥á¥ó¥Ð <type> 
2122     ¤ÎÃͤȤ·¤ÆÍѤ¤¤é¤ì¡¢¥á¥ó¥Ð <fontp> ¤Î·¿¤¬¼ÂºÝ¤Ë¤Ï (XftFont *) ¤Ç¤¢¤ë¤³¤È¤òɽ¤¹¡£  */
2123
2124 MSymbol Mxft;
2125
2126 /*=*/
2127 /*** @} */
2128 /*=*/
2129
2130 /***en
2131     @brief List of font files and directories that contain font files.
2132
2133     The variable @c mfont_freetype_path is a plist of FreeType font
2134     files and directories that contain FreeType font files.  Key of
2135     the element is @c Mstring, and the value is a string that
2136     represents a font file or a directory.
2137
2138     The macro M17N_INIT () sets up this variable to contain the
2139     sub-directory "fonts" of the m17n database and the environment
2140     variable "M17NDIR".  The first call of mframe () creates the
2141     internal list of the actually available fonts from this variable.
2142     Thus, an application program, if necessary, must modify the
2143     variable before calling mframe ().  If it is going to add a new
2144     element, value must be a string that can be safely freed.
2145
2146     If the m17n library is not configured to use the FreeType library,
2147     this variable is not used.  */
2148 /***ja
2149     @brief ¥Õ¥©¥ó¥È¥Õ¥¡¥¤¥ë¤È¥Õ¥©¥ó¥È¥Õ¥¡¥¤¥ë¤ò´Þ¤à¥Ç¥£¥ì¥¯¥È¥ê¤Î¥ê¥¹¥È.
2150
2151     ÊÑ¿ô @c mfont_freetype_path ¤Ï¡¢¥Õ¥©¥ó¥È¥Õ¥¡¥¤¥ë¤È¥Õ¥©¥ó¥È¥Õ¥¡¥¤¥ë¤ò´Þ¤à¥Ç¥£¥ì¥¯¥È¥ê¤Î 
2152     plist ¤Ç¤¢¤ë¡£³ÆÍ×ÁǤΥ­¡¼¤Ï @c Mstring 
2153     ¤Ç¤¢¤ê¡¢Ãͤϥե©¥ó¥È¥Õ¥¡¥¤¥ë¤«¥Ç¥£¥ì¥¯¥È¥ê¤ò¼¨¤¹Ê¸»úÎó¤Ç¤¢¤ë¡£
2154
2155     ¥Þ¥¯¥í M17N_INIT () ¤Ë¤è¤Ã¤Æ¡¢¤³¤ÎÊÑ¿ô¤Ï m17n ¥Ç¡¼¥¿¥Ù¡¼¥¹¤È´Ä¶­ÊÑ¿ô 
2156     "M17NDIR" ÁÐÊý¤Î¥µ¥Ö¥Ç¥£¥ì¥¯¥È¥ê "fonts" ¤ò´Þ¤à¤è¤¦¤ËÀßÄꤵ¤ì¤ë¡£
2157     mframe () ¤ÎºÇ½é¤Î¸Æ¤Ó½Ð¤·¤ÎºÝ¤Ë¡¢¤³¤ÎÊÑ¿ô¤«¤é¼ÂºÝ¤Ë»ÈÍѤǤ­¤ë¥Õ¥©¥ó¥È¤ÎÆâÉô¥ê¥¹¥È¤¬ºî¤é¤ì¤ë¡£
2158     ¤½¤³¤Ç¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥à¤Ï¡¢mframe () 
2159     ¤ò¸Æ¤ÖÁ°¤Ë¡ÊɬÍפʤé¤Ð¡Ë¤³¤ÎÊÑ¿ô¤òÊѹ¹¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
2160     ¿·¤·¤¤Í×ÁǤòÄɲ乤ë¾ì¹ç¤Ë¤Ï¡¢¤½¤ÎÃͤϰÂÁ´¤Ë³«Êü¤Ç¤­¤ëʸ»úÎó¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
2161
2162     m17n ¥é¥¤¥Ö¥é¥ê¤¬ FreeType ¥é¥¤¥Ö¥é¥ê¤ò»È¤¦¤è¤¦¤ËÀßÄꤵ¤ì¤Æ¤Ê¤¤¾ì¹ç¤Ë¤Ï¡¢¤³¤ÎÊÑ¿ô¤ÏÍѤ¤¤é¤ì¤Ê¤¤¡£ */
2163
2164 MPlist *mfont_freetype_path;
2165
2166 /*=*/
2167
2168 /***en
2169     @brief Create a new font.
2170
2171     The mfont () function creates a new font object that has no
2172     property.
2173
2174     @return
2175     This function returns a pointer to the created font object.  */
2176 /***ja
2177     @brief ¿·¤·¤¤¥Õ¥©¥ó¥È¤òºî¤ë.
2178
2179     ´Ø¿ô mfont () ¤Ï¥×¥í¥Ñ¥Æ¥£¤ò°ìÀÚ»ý¤¿¤Ê¤¤¿·¤·¤¤¥Õ¥©¥ó¥È¤ò¥ª¥Ö¥¸¥§¥¯¥È¤òºî¤ë¡£
2180
2181     @return
2182     ¤³¤Î´Ø¿ô¤Ïºî¤Ã¤¿¥Õ¥©¥ó¥È¥ª¥Ö¥¸¥§¥¯¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£  */
2183
2184 MFont *
2185 mfont ()
2186 {
2187   MFont *font;
2188
2189   MSTRUCT_CALLOC (font, MERROR_FONT);
2190   return font;
2191 }
2192
2193 /*=*/
2194
2195 /***en
2196     @brief Create a font by parsing a fontname.
2197
2198     The mfont_parse_name () function creates a new font object.  The
2199     properties are extracted fontname $NAME.
2200
2201     $FORMAT specifies the format of $NAME.  If $FORMAT is #Mx, $NAME
2202     is parsed as XLFD (X Logical Font Description).  If $FORMAT is
2203     #Mfontconfig, $NAME is parsed as Fontconfig's textual
2204     representation of font.  If $FORMAT is #Mnil, $NAME is at first
2205     parsed as XLFD, and it it fails, parsed as Fontconfig's
2206     representation.
2207
2208     @return
2209     If the operation was successful, this function returns a pointer
2210     to the created font.  Otherwise it returns @c NULL.  */
2211
2212 /***ja
2213     @brief ¥Õ¥©¥ó¥È̾¤«¤é¥Õ¥©¥ó¥È¤òºî¤ë.
2214
2215     ´Ø¿ô mfont_parse_name () ¤Ï¡¢¥Õ¥©¥ó¥È̾ 
2216     $NAME ¤«¤é¼è¤ê½Ð¤µ¤ì¤¿¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ä¡¢¿·¤·¤¤¥Õ¥©¥ó¥È¥ª¥Ö¥¸¥§¥¯¥È¤òºî¤ë¡£
2217
2218     $FORMAT ¤Ï $NAME ¤Î¥Õ¥©¡¼¥Þ¥Ã¥È¤ò»ØÄꤹ¤ë¡£$FORMAT ¤¬ #Mx ¤Ç¤¢¤ì¤Ð¡¢
2219     $NAME ¤Ï XLFD (X Logical Font Description) ¤Ë½¾¤Ã¤Æ²òÀϤµ¤ì¤ë¡£
2220     $FORMAT ¤¬ #Mfontconfig ¤Ç¤¢¤ì¤Ð $NAME ¤Ï Fontfonfig 
2221     ¤Î¥Õ¥©¥ó¥È¥Æ¥­¥¹¥Èɽ¸½¤Ë½¾¤Ã¤Æ²òÀϤµ¤ì¤ë¡£$FORMAT ¤¬ #Mnil ¤Ç¤¢¤ì¤Ð¡¢¤Þ¤º XLFD 
2222     ¤Ë½¾¤Ã¤Æ²òÀϤµ¤ì¡¢¤½¤ì¤Ë¼ºÇÔ¤·¤¿¤é Fontconfig ¤Ë½¾¤Ã¤Æ²òÀϤµ¤ì¤ë¡£
2223
2224     @return
2225     ½èÍý¤¬À®¸ù¤¹¤ì¤Ð mfont_parse_name () 
2226     ¤Ï¿·¤·¤¯ºî¤é¤ì¤¿¥Õ¥©¥ó¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð @c NULL ¤òÊÖ¤¹¡£  */
2227
2228 MFont *
2229 mfont_parse_name (const char *name, MSymbol format)
2230 {
2231   MFont template, *font;
2232   
2233   MFONT_INIT (&template);
2234   if (mfont__parse_name_into_font (name, format, &template) < 0)
2235     MERROR (MERROR_FONT, NULL);
2236   MSTRUCT_CALLOC (font, MERROR_FONT);
2237   *font = template;
2238   return font;
2239 }
2240
2241 /*=*/
2242
2243 /***en
2244     @brief Create a fontname from a font.
2245
2246     The mfont_unparse_name () function creates a fontname string
2247     from font $FONT according to $FORMAT.
2248
2249     $FORMAT must be #Mx or #Mfontconfig.  If it is #Mx, the fontname
2250     is in XLFD (X Logical Font Description) format.  If it is
2251     #Mfontconfig, the fontname is in the style of Fontconfig's text
2252     representation.
2253
2254     @return
2255     This function returns a newly allocated fontname string, which is
2256     not freed unless the user explicitly does so by free ().  */
2257
2258 /***ja
2259     @brief ¥Õ¥©¥ó¥È¤«¤é¥Õ¥©¥ó¥È̾¤òºî¤ë.
2260
2261     ´Ø¿ô mfont_unparse_name () ¤Ï ¥Õ¥©¥ó¥È̾¤Îʸ»úÎó¤ò¥Õ¥©¥ó¥È $FONT 
2262     ¤ò¸µ¤Ë$FORMAT ¤Ë½¾¤Ã¤Æºî¤ë¡£
2263
2264     $FORMAT ¤Ï #Mx ¤Þ¤¿¤Ï #Mfontconfig ¤Ç¤¢¤ë¡£
2265     #Mx ¤Ê¤é¤Ð¥Õ¥©¥ó¥È̾¤Ï XLFD (X Logical Font Description) ¤Ë½¾¤¦¡£
2266     #Mfontconfig ¤Ê¤é¤Ð¥Õ¥©¥ó¥È̾¤Ï Fontconfig ¤Î¥Õ¥©¥ó¥È¥Æ¥­¥¹¥Èɽ¸½¤Ë½¾¤¦¡£
2267
2268     @return 
2269     ¤³¤Î´Ø¿ô¤Ï¿·¤¿¤Ë¥¢¥í¥±¡¼¥È¤·¤¿¥Õ¥©¥ó¥È̾¤Îʸ»úÎó¤òÊÖ¤¹¡£Ê¸»úÎó¤Ï¡¢¥æ¡¼¥¶¤¬
2270     free () ¤Ë¤è¤Ã¤ÆÌÀ¼¨Åª¤Ë²òÊü¤·¤Ê¤¤¸Â¤ê²òÊü¤µ¤ì¤Ê¤¤¡£  */
2271
2272 char *
2273 mfont_unparse_name (MFont *font, MSymbol format)
2274 {
2275   char *name;
2276
2277   if (format == Mx)
2278     name = xlfd_unparse_name (font, 1);
2279 #ifdef HAVE_FONTCONFIG
2280   else if (format == Mfontconfig)
2281     name = mfont__ft_unparse_name (font);
2282
2283 #endif /* HAVE_FONTCONFIG */
2284   else
2285     MERROR (MERROR_FONT, NULL);
2286   return name;
2287 }
2288
2289 /*=*/
2290
2291 /***en
2292     @brief Make a copy of a font.
2293
2294     The mfont_copy () function returns a new copy of font $FONT.  */
2295 /***ja
2296     @brief ¥Õ¥©¥ó¥È¤Î¥³¥Ô¡¼¤òºî¤ë.
2297
2298     ´Ø¿ô Mfont_copy () ¤Ï¥Õ¥©¥ó¥È $FONT ¤Î¥³¥Ô¡¼¤òºî¤ê¡¢¤½¤ì¤òÊÖ¤¹¡£ */
2299
2300 MFont *
2301 mfont_copy (MFont *font)
2302 {
2303   MFont *copy;
2304
2305   MSTRUCT_MALLOC (copy, MERROR_FONT);
2306   *copy = *font;
2307   return copy;
2308 }
2309
2310 /*=*/
2311
2312 /***en
2313     @brief Get a property value of a font.
2314
2315     The mfont_get_prop () function gets the value of $KEY property of
2316     font $FONT.  $KEY must be one of the following symbols:
2317
2318         @c Mfoundry, @c Mfamily, @c Mweight, @c Mstyle, @c Mstretch,
2319         @c Madstyle, @c Mregistry, @c Msize, @c Mresolution, @c Mspacing.
2320
2321     If $FONT is a return value of mfont_find (), $KEY can also be one
2322     of the following symbols:
2323
2324         #Mfont_ascent, #Mfont_descent, #Mmax_advance.
2325
2326     @return If $KEY is @c Mfoundry, @c Mfamily, @c Mweight, @c Mstyle,
2327     @c Mstretch, @c Madstyle, @c Mregistry, or @c Mspacing, this
2328     function returns the corresponding value as a symbol.  If the font
2329     does not have $KEY property, it returns @c Mnil.  If $KEY is @c
2330     Msize, @c Mresolution, #Mfont_ascent, Mfont_descent, or
2331     #Mmax_advance, this function returns the corresponding value as an
2332     integer.  If the font does not have $KEY property, it returns 0.
2333     If $KEY is something else, it returns @c NULL and assigns an error
2334     code to the external variable #merror_code.  */
2335  
2336 /***ja
2337     @brief ¥Õ¥©¥ó¥È¤Î¥×¥í¥Ñ¥Æ¥£¤ÎÃͤòÆÀ¤ë.
2338
2339     ´Ø¿ô mfont_get_prop () ¤Ï¥Õ¥©¥ó¥È $FONT ¤Î¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥­¡¼¤¬
2340     $KEY ¤Ç¤¢¤ë¤â¤Î¤ÎÃͤòÊÖ¤¹¡£$KEY ¤Ï°Ê²¼¤Î¥·¥ó¥Ü¥ë¤Î¤¤¤º¤ì¤«¤Ç¤Ê¤±¤ì
2341     ¤Ð¤Ê¤é¤Ê¤¤¡£
2342
2343         @c Mfoundry, @c Mfamily, @c Mweight, @c Mstyle, @c Mstretch,
2344         @c Madstyle, @c Mregistry, @c Msize, @c Mresolution, @c Mspacing.
2345
2346     @return $KEY ¤¬ @c Mfoundry, @c Mfamily, @c Mweight, @c Mstyle, @c
2347     Mstretch, @c Madstyle, @c Mregistry, @c Mspacing ¤Î¤¤¤º¤ì¤«¤Ç¤¢¤ì¤Ð¡¢
2348     ÁêÅö¤¹¤ëÃͤò¥·¥ó¥Ü¥ë¤È¤·¤ÆÊÖ¤¹¡£¥Õ¥©¥ó¥È¤¬¤½¤Î¥×¥í¥Ñ¥Æ¥£¤ò»ý¤¿¤Ê¤¤
2349     ¾ì¹ç¤Ë¤Ï@c Mnil ¤òÊÖ¤¹¡£$KEY ¤¬ @c Msize ¤¢¤ë¤¤¤Ï @c Mresolution ¤Î
2350     ¾ì¹ç¤Ë¤Ï¡¢ÁêÅö¤¹¤ëÃͤò¤ÏÀ°¿ôÃͤȤ·¤ÆÊÖ¤¹¡£¥Õ¥©¥ó¥È¤¬¤½¤Î¥×¥í¥Ñ¥Æ¥£
2351     ¤ò»ý¤¿¤Ê¤¤¾ì¹ç¤Ë¤Ï 0 ¤òÊÖ¤¹¡£$KEY ¤¬¤½¤ì°Ê³°¤Î¤â¤Î¤Ç¤¢¤ì¤Ð¡¢@c
2352     NULL ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£  */
2353
2354 void *
2355 mfont_get_prop (MFont *font, MSymbol key)
2356 {
2357   MRealizedFont *rfont = NULL;
2358
2359   if (font->type == MFONT_TYPE_REALIZED)
2360     rfont = (MRealizedFont *) font;
2361
2362   if (key == Mfoundry)
2363     return (void *) FONT_PROPERTY (font, MFONT_FOUNDRY);
2364   if (key == Mfamily)
2365     return (void *) FONT_PROPERTY (font, MFONT_FAMILY);
2366   if (key == Mweight)
2367     return (void *) FONT_PROPERTY (font, MFONT_WEIGHT);
2368   if (key == Mstyle)
2369     return (void *) FONT_PROPERTY (font, MFONT_STYLE);
2370   if (key == Mstretch)
2371     return (void *) FONT_PROPERTY (font, MFONT_STRETCH);
2372   if (key == Madstyle)
2373     return (void *) FONT_PROPERTY (font, MFONT_ADSTYLE);
2374   if (key == Mregistry)
2375     return (void *) FONT_PROPERTY (font, MFONT_REGISTRY);
2376   if (key == Msize)
2377     {
2378       int size = font->size;
2379       return (void *) size;
2380     }
2381   if (key == Mresolution)
2382     {
2383       int resy = font->property[MFONT_RESY];
2384       return (void *) resy;
2385     }
2386   if (key == Mlanguage || key == Mscript || key == Motf)
2387     {
2388       MFontCapability *cap;
2389
2390       if (! font->capability)
2391         return NULL;
2392       cap = mfont__get_capability (font->capability);
2393       if (key == Mlanguage)
2394         return cap->language;
2395       if (key == Mscript)
2396         return cap->script;
2397       return cap->otf;
2398     }
2399
2400   if (key == Mfontfile)
2401     return (void *) font->file;
2402   if (key == Mspacing)
2403     return (font->spacing == MFONT_SPACING_UNDECIDED ? Mnil
2404             : msymbol (font->spacing == MFONT_SPACING_PROPORTIONAL ? "p"
2405                        : font->spacing == MFONT_SPACING_MONO ? "m" : "c"));
2406   if (rfont)
2407     {
2408       if (key == Mfont_ascent)
2409         return (void *) rfont->ascent;
2410       if (key == Mfont_descent)
2411         return (void *) rfont->descent;
2412       if (key == Mmax_advance)
2413         return (void *) rfont->max_advance;
2414     }
2415   MERROR (MERROR_FONT, NULL);
2416 }
2417
2418
2419 /*=*/
2420 /***en
2421     @brief Put a property value to a font.
2422
2423     The mfont_put_prop () function puts a font property whose key is
2424     $KEY and value is $VAL to font $FONT.  $KEY must be one of the
2425     following symbols:
2426
2427         @c Mfoundry, @c Mfamily, @c Mweight, @c Mstyle, @c Mstretch,
2428         @c Madstyle, @c Mregistry, @c Msize, @c Mresolution.
2429
2430     If $KEY is @c Msize or @c Mresolution, $VAL must be an integer.
2431     Otherwise, $VAL must be a symbol of a property value name.  But,
2432     if the name is "nil", a symbol of name "Nil" must be
2433     specified.  */
2434  /***ja
2435     @brief ¥Õ¥©¥ó¥È¤Î¥×¥í¥Ñ¥Æ¥£¤ËÃͤòÀßÄꤹ¤ë.
2436
2437     ´Ø¿ô mfont_put_prop () ¤Ï¡¢¥Õ¥©¥ó¥È $FONT ¤Î¥­¡¼¤¬$KEY ¤Ç¤¢¤ë¥×¥í¥Ñ
2438     ¥Æ¥£¤ÎÃͤò $VAL ¤ËÀßÄꤹ¤ë¡£$KEY ¤Ï°Ê²¼¤Î¥·¥ó¥Ü¥ë¤Î¤¤¤º¤ì¤«¤Ç¤¢¤ë¡£
2439
2440         @c Mfoundry, @c Mfamily, @c Mweight, @c Mstyle, @c Mstretch,
2441         @c Madstyle, @c Mregistry, @c Msize, @c Mresolution.
2442
2443     $KEY ¤¬ @c Msize ¤« @c Mresolution ¤Ç¤¢¤ì¤Ð $VAL ¤ÏÀ°¿ôÃͤǤʤ¯¤Æ¤Ï
2444     ¤é¤Ê¤¤¡£¤½¤ì°Ê³°¤Î¾ì¹ç¡¢$VAL ¤Ï¥×¥í¥Ñ¥Æ¥£ÃͤÎ̾Á°¤Î¥·¥ó¥Ü¥ë¤Ç¤Ê¤¯¤Æ
2445     ¤Ï¤Ê¤é¤Ê¤¤¡£¤¿¤À¤·¤â¤·¤½¤Î̾Á°¤¬ "nil" ¤Î¾ì¹ç¤Ï¡¢Ì¾Á°¤¬ "Nil" ¤Î¥·
2446     ¥ó¥Ü¥ë¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£*/
2447
2448 int
2449 mfont_put_prop (MFont *font, MSymbol key, void *val)
2450 {
2451   if (key == Mfoundry)
2452     mfont__set_property (font, MFONT_FOUNDRY, (MSymbol) val);
2453   else if (key == Mfamily)
2454     mfont__set_property (font, MFONT_FAMILY, (MSymbol) val);
2455   else if (key == Mweight)
2456     mfont__set_property (font, MFONT_WEIGHT, (MSymbol) val);
2457   else if (key == Mstyle)
2458     mfont__set_property (font, MFONT_STYLE, (MSymbol) val);
2459   else if (key == Mstretch)
2460     mfont__set_property (font, MFONT_STRETCH, (MSymbol) val);
2461   else if (key == Madstyle)
2462     mfont__set_property (font, MFONT_ADSTYLE, (MSymbol) val);
2463   else if (key == Mregistry)
2464     mfont__set_property (font, MFONT_REGISTRY, (MSymbol) val);
2465   else if (key == Msize)
2466     {
2467       int size = (int) val;
2468       font->size = size;
2469     }
2470   else if (key == Mresolution)
2471     {
2472       unsigned resy = (unsigned) val;
2473       font->property[MFONT_RESY] = resy;
2474     }
2475   else if (key == Mlanguage || key == Mscript || key == Motf)
2476     {
2477       font->capability = merge_capability (font->capability,
2478                                            key, (MSymbol) val, 1);
2479     }
2480   else if (key == Mfontfile)
2481     {
2482       font->file = (MSymbol) val;
2483     }
2484   else
2485     MERROR (MERROR_FONT, -1);
2486   return 0;
2487 }
2488
2489 /*=*/
2490
2491 /***en
2492     @brief Return the font selection priority.
2493
2494     The mfont_selection_priority () function returns a newly created
2495     array of six symbols.  The elements are the following
2496     keys of font properties ordered by priority.
2497
2498         @c Mfamily, @c Mweight, @c Mstyle, @c Mstretch,
2499         @c Madstyle, @c Msize.
2500
2501    The m17n library selects the best matching font according to the
2502    order of this array.  A font that has a different value for a
2503    property of lower priority is preferred to a font that has a
2504    different value for a property of higher priority.  */
2505 /***ja
2506     @brief ¥Õ¥©¥ó¥ÈÁªÂò¤ÎÍ¥ÀèÅÙ¤òÊÖ¤¹.
2507
2508     ´Ø¿ô mfont_selection_priority () ¤Ï 6 ¤Ä¤Î¥·¥ó¥Ü¥ë¤«¤é¤Ê¤ëÇÛÎó¤òºî¤Ã¤ÆÊÖ¤¹¡£
2509     ÇÛÎó¤ÎÍ×ÁǤϡ¢°Ê²¼¤Î¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼¤òÍ¥ÀèÅÙ½ç¤Ëʤ٤¿¤â¤Î¤Ç¤¢¤ë¡£
2510
2511         @c Mfamily, @c Mweight, @c Mstyle, @c Mstretch,
2512         @c Madstyle, @c Msize.
2513
2514    m17n ¥é¥¤¥Ö¥é¥ê¤Ï¤³¤ÎÇÛÎó¤Ë½¾¤Ã¤Æ¡¢ºÇ¤â¹çÃפ¹¤ë¥Õ¥©¥ó¥È¤òÁªÂò¤¹¤ë¡£
2515    ÌÜŪ¤Î¥Õ¥©¥ó¥È¤È¡¢¤½¤ì¤¾¤ì°ã¤¦¥×¥í¥Ñ¥Æ¥£¤ÎÃͤ¬¹çÃפ·¤Ê¤¤¥Õ¥©¥ó¥È¤¬¤¢¤Ã¤¿¾ì¹ç¡¢Í¥ÀèÅÙ¤ÎÄ㤤¥×¥í¥Ñ¥Æ¥£¤ÎÃͤ¬¹çÃפ·¤Ê¤¤¥Õ¥©¥ó¥È¡ÊÍ¥ÀèÅ٤ι⤤¥×¥í¥Ñ¥Æ¥£¤ÎÃͤ¬¹çÃפ·¤Æ¤¤¤ë¥Õ¥©¥ó¥È¡Ë¤¬ÁªÂò¤µ¤ì¤ë¡£
2516
2517    */
2518
2519 MSymbol *
2520 mfont_selection_priority ()
2521 {
2522   MSymbol *keys;
2523   int i;
2524
2525   MTABLE_MALLOC (keys, FONT_SCORE_PRIORITY_SIZE, MERROR_FONT);
2526   for (i = 0; i < FONT_SCORE_PRIORITY_SIZE; i++)
2527     {
2528       enum MFontProperty prop = font_score_priority[i];
2529
2530       if (prop == MFONT_SIZE)
2531         keys[i] = Msize;
2532       else if (prop == MFONT_ADSTYLE)
2533         keys[i] = Madstyle;
2534       else if (prop == MFONT_FAMILY)
2535         keys[i] = Mfamily;
2536       else if (prop == MFONT_WEIGHT)
2537         keys[i] = Mweight;
2538       else if (prop == MFONT_STYLE)
2539         keys[i] = Mstyle;
2540       else if (prop == MFONT_STRETCH)
2541         keys[i] = Mstretch;
2542       else
2543         keys[i] = Mfoundry;
2544     }
2545   return keys;
2546 }
2547
2548 /*=*/
2549
2550 /***en
2551     @brief Set the font selection priority.
2552
2553     The mfont_set_selection_priority () function sets font selection
2554     priority according to $KEYS, which is an array of six symbols.
2555     Each element must be one of the below.  No two elements must be
2556     the same.
2557
2558         @c Mfamily, @c Mweight, @c Mstyle, @c Mstretch,
2559         @c Madstyle, @c Msize.
2560
2561     See the documentation of the function mfont_selection_priority ()
2562     for details.  */
2563 /***ja
2564     @brief ¥Õ¥©¥ó¥ÈÁªÂòÍ¥ÀèÅÙ¤òÀßÄꤹ¤ë.
2565
2566     ´Ø¿ô mfont_set_selection_priority () ¤Ï¡¢6¤Ä¤Î¥·¥ó¥Ü¥ë¤ÎÇÛÎó $KEYS 
2567     ¤Ë¤·¤¿¤¬¤Ã¤Æ¥Õ¥©¥ó¥ÈÁªÂòÍ¥ÀèÅÙ¤òÀßÄꤹ¤ë¡£ÇÛÎó¤Ï°Ê²¼¤Î³ÆÍ×ÁǤòŬÀÚ
2568     ¤Ê½çÈÖ¤Çʤ٤¿¤â¤Î¤Ç¤¢¤ë¡£
2569
2570         @c Mfamily, @c Mweight, @c Mstyle, @c Mstretch,
2571         @c Madstyle, @c Msize.
2572
2573     ¾ÜºÙ¤Ï´Ø¿ô mfont_selection_priority () ¤ÎÀâÌÀ¤ò»²¾È¤Î¤³¤È¡£
2574      */
2575
2576 int
2577 mfont_set_selection_priority (MSymbol *keys)
2578 {
2579   int priority[FONT_SCORE_PRIORITY_SIZE];
2580   int i, j, shift;
2581
2582   for (i = 0; i < FONT_SCORE_PRIORITY_SIZE; i++, keys++)
2583     {
2584       enum MFontProperty prop;
2585
2586       if (*keys == Msize)
2587         prop = MFONT_SIZE;
2588       else if (*keys == Madstyle)
2589         prop = MFONT_ADSTYLE;
2590       else if (*keys == Mfamily)
2591         prop = MFONT_FAMILY;
2592       else if (*keys == Mweight)
2593         prop = MFONT_WEIGHT;
2594       else if (*keys == Mstyle)
2595         prop = MFONT_STYLE;
2596       else if (*keys == Mstretch)
2597         prop = MFONT_STRETCH;
2598       else if (*keys == Mfoundry)
2599         prop = MFONT_FOUNDRY;
2600       else
2601         /* Invalid element.  */
2602         return -1;
2603       for (j = 0; j < i; j++)
2604         if (priority[j] == prop)
2605           /* Duplicated element.  */
2606           return -1;
2607       priority[i] = prop;
2608     }
2609   for (i = 0; i < FONT_SCORE_PRIORITY_SIZE; i++)
2610     font_score_priority[i] = priority[i];
2611   /* Here, SHIFT starts from 1, not 0.  This is because the lowest bit
2612      of a score is a flag for a scalable font (see the documentation
2613      of font_score).  */
2614   i = FONT_SCORE_PRIORITY_SIZE - 1;
2615   for (shift = 1; i >= 0; i--)
2616     {
2617       font_score_shift_bits[font_score_priority[i]] = shift;
2618       if (font_score_priority[i] == MFONT_SIZE)
2619         shift += 16;
2620       else if (font_score_priority[i] <= MFONT_FAMILY)
2621         shift++;
2622       else
2623         shift += 2;
2624     }
2625   return 0;
2626 }
2627
2628 /*=*/
2629
2630 /***en
2631     @brief Find a font.
2632
2633     The mfont_find () function returns a pointer to the available font
2634     that matches best the specification $SPEC on frame $FRAME.
2635
2636     $SCORE, if not NULL, must point to a place to store the score
2637     value that indicates how well the found font matches to $SPEC.  The
2638     smaller score means a better match.  */
2639 /***ja
2640     @brief ¥Õ¥©¥ó¥È¤òõ¤¹.
2641
2642     ´Ø¿ô mfont_find () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¾å¤Ç¥Õ¥©¥ó¥ÈÄêµÁ $SPEC 
2643     ¤Ë¤â¤Ã¤È¤â¹çÃפ¹¤ëÍøÍѲÄǽ¤Ê¥Õ¥©¥ó¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£  
2644
2645     $SCORE ¤Ï NULL ¤Ç¤¢¤ë¤«¡¢¸«¤Ä¤«¤Ã¤¿¥Õ¥©¥ó¥È¤¬ $SPEC 
2646     ¤Ë¤É¤ì¤Û¤É¹ç¤Ã¤Æ¤¤¤ë¤«¤ò¼¨¤¹¥¹¥³¥¢¤òÊݸ¤¹¤ë¾ì½ê¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ë¡£
2647     ¥¹¥³¥¢¤¬¾®¤µ¤¤¤Û¤ÉÎɤ¯¹ç¤Ã¤Æ¤¤¤ë¤³¤È¤ò°ÕÌ£¤¹¤ë¡£
2648     */
2649
2650 MFont *
2651 mfont_find (MFrame *frame, MFont *spec, int *score, int max_size)
2652 {
2653   MFont spec_copy;
2654   MFont *best;
2655   MFontList *list;
2656   MRealizedFont *rfont;
2657   MFont adjusted;
2658
2659   if (spec->size < 0)
2660     {
2661       double pt = - spec->size;
2662
2663       adjusted = *spec;
2664       adjusted.size = pt * frame->dpi / 72.27 + 0.5;
2665       spec = &adjusted;
2666     }
2667   MFONT_INIT (&spec_copy);
2668   spec_copy.property[MFONT_FAMILY] = spec->property[MFONT_FAMILY];
2669   spec_copy.property[MFONT_REGISTRY] = spec->property[MFONT_REGISTRY];
2670   spec_copy.capability = spec->capability;
2671   spec_copy.file = spec->file;
2672
2673   list = mfont__list (frame, &spec_copy, spec, max_size);
2674   if (! list)
2675     return NULL;
2676
2677   best = list->fonts[0].font;
2678   if (score)
2679     *score = list->fonts[0].score;
2680   free (list->fonts);
2681   free (list);
2682   spec_copy = *best;
2683   mfont__merge (&spec_copy, spec, 0);
2684   rfont = mfont__open (frame, best, spec);
2685   if (! rfont)
2686     return NULL;
2687   return (MFont *) rfont;
2688 }
2689
2690 /*=*/
2691 /***en
2692     @brief Set encoding of a font.
2693
2694     The mfont_set_encoding () function sets the encoding information
2695     of font $FONT.
2696
2697     $ENCODING_NAME is a symbol representing a charset that has the
2698     same encoding as the font.
2699
2700     $REPERTORY_NAME is @c Mnil or a symbol representing a charset that
2701     has the same repertory as the font.  If it is @c Mnil, whether a
2702     specific character is supported by the font is asked to each font
2703     driver.
2704
2705     @return
2706     If the operation was successful, this function returns 0.
2707     Otherwise it returns -1 and assigns an error code to the external
2708     variable #merror_code.  */
2709 /***ja
2710     @brief ¥Õ¥©¥ó¥È¤Î¥¨¥ó¥³¡¼¥Ç¥£¥ó¥°¤òÀßÄꤹ¤ë.
2711
2712     ´Ø¿ô mfont_set_encoding () ¤Ï¥Õ¥©¥ó¥È $FONT ¤Î¥¨¥ó¥³¡¼¥Ç¥£¥ó¥°¾ðÊó¤òÀßÄꤹ¤ë¡£
2713
2714     $ENCODING_NAME ¤Ï¥Õ¥©¥ó¥È¤ÈƱ¤¸¥¨¥ó¥³¡¼¥Ç¥£¥ó¥°¤ò»ý¤Äʸ»ú¥»¥Ã¥È¤ò¼¨¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£
2715
2716     $REPERTORY_NAME ¤Ï @c Mnil ¤Ç¤¢¤ë¤«¡¢¥Õ¥©¥ó¥È¤ÈƱ¤¸¥¨¥ó¥³¡¼¥Ç¥£¥ó¥°¤ò»ý¤Äʸ»ú¥»¥Ã¥È¤ò¼¨¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£
2717     @c Mnil ¤Ç¤¢¤ì¤Ð¡¢¸Ä¡¹¤Îʸ»ú¤¬¤½¤Î¥Õ¥©¥ó¥È¤Ç¥µ¥Ý¡¼¥È¤µ¤ì¤Æ¤¤¤ë¤«¤É¤¦¤«¤Ï¡¢³Æ¡¹¤Î¥Õ¥©¥ó¥È¥É¥é¥¤¥Ð¤ËÌ䤤¹ç¤ï¤»¤ë¡£
2718
2719     @return
2720     ½èÍý¤¬À®¸ù¤¹¤ì¤Ð¤³¤Î´Ø¿ô¤Ï 0 ¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô
2721     #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£  */
2722
2723
2724 int
2725 mfont_set_encoding (MFont *font, MSymbol encoding_name, MSymbol repertory_name)
2726 {
2727   MCharset *encoding_charset = MCHARSET (encoding_name);
2728   MCharset *repertory_charset;
2729   MSymbol registry;
2730   MFontEncoding *encoding;
2731   MPlist *plist;
2732
2733   if (! encoding_charset)
2734     MERROR (MERROR_FONT, -1);
2735   if (repertory_name != Mnil)
2736     {
2737       repertory_charset = MCHARSET (repertory_name);
2738       if (! repertory_charset)
2739         MERROR (MERROR_FONT, -1);
2740     }
2741   else
2742     repertory_charset = NULL;
2743
2744   MSTRUCT_CALLOC (encoding, MERROR_FONT);
2745   encoding->spec = *font;
2746   encoding->encoding_name = encoding_name;
2747   encoding->encoding_charset = encoding_charset;
2748   encoding->repertory_name = repertory_name;
2749   encoding->repertory_charset = repertory_charset;
2750   registry = FONT_PROPERTY (font, MFONT_REGISTRY);
2751   if (registry == Mnil)
2752     registry = Mt;
2753   if (! font_encoding_list)
2754     load_font_encoding_table ();
2755   mplist_push (font_encoding_list, registry, encoding);
2756   MPLIST_DO (plist, MPLIST_NEXT (font_encoding_list))
2757     if (! memcmp (font, &((MFontEncoding *) MPLIST_VAL (plist))->spec,
2758                   sizeof (MFont)))
2759       {
2760         mplist_pop (plist);
2761         break;
2762       }
2763   return 0;
2764 }
2765
2766 /*=*/
2767
2768 /***en
2769     @brief Create a fontname from a font.
2770
2771     This function is obsolete.   Use mfont_unparse_name instead. */
2772 /***ja
2773     @brief ¥Õ¥©¥ó¥È̾¤«¤é¥Õ¥©¥ó¥È¤òºî¤ë.
2774
2775     ¤³¤Î´Ø¿ô¤ÏÇÑ»ßͽÄê¤Ç¤¢¤ë¡£ mfont_unparse_name () ¤ò»ÈÍѤΤ³¤È¡£ */
2776
2777 char *
2778 mfont_name (MFont *font)
2779 {
2780   return mfont_unparse_name (font, Mx);
2781 }
2782
2783 /*=*/
2784
2785 /***en
2786     @brief Create a new font from fontname.
2787
2788     This function is obsolete.  Use mfont_parse_name () instead.  */
2789
2790 /***ja
2791     @brief ¥Õ¥©¥ó¥È¤«¤é¥Õ¥©¥ó¥È̾¤òºî¤ë.
2792
2793     ¤³¤ì¤Ï´Ø¿ô¤ÏÇÑ»ßͽÄê¤Ç¤¢¤ë¡£ mfont_parse_name () ¤ò»ÈÍѤΤ³¤È¡£  */
2794
2795 MFont *
2796 mfont_from_name (const char *name)
2797 {
2798   return mfont_parse_name (name, Mx);
2799 }
2800
2801 /*=*/
2802
2803 /***en
2804     @brief Get resize information of a font.
2805
2806     The mfont_resize_ratio () function lookups the m17n database
2807     \<font, reisize\> and returns a resizing ratio (in percentage) of
2808     FONT.  For instance, if the return value is 150, that means that
2809     the m17n library uses an 1.5 time bigger font than a specified
2810     size.  */
2811
2812 /***ja
2813     @brief ¥Õ¥©¥ó¥È¤Î¥ê¥µ¥¤¥º¾ðÊó¤òÆÀ¤ë
2814
2815     ´Ø¿ô mfont_resize_ratio ¤Ï m17n ¥Ç¡¼¥¿¥Ù¡¼¥¹ \<font, reisize\> 
2816     ¤ò¸¡º÷¤·¡¢¥Õ¥©¥ó¥È FONT ¤Î¥ê¥µ¥¤¥º¤ÎÈæΨ¡Ê¥Ñ¡¼¥»¥ó¥Æ¡¼¥¸¡Ë
2817     ¤òÊÖ¤¹¡£¤¿¤È¤¨¤ÐÊÖ¤¹Ãͤ¬ 150 ¤Ç¤¢¤ì¤Ð¡¢m17n ¥é¥¤¥Ö¥é¥ê¤Ï»ØÄꤵ¤ì¤¿¥µ¥¤¥º¤Î 1.5 
2818     ÇܤΥե©¥ó¥È¤ò»ÈÍѤ¹¤ë¤³¤È¤ò°ÕÌ£¤¹¤ë¡£ */
2819
2820 int
2821 mfont_resize_ratio (MFont *font)
2822 {
2823   MSymbol registry = FONT_PROPERTY (font, MFONT_REGISTRY);
2824   MFontResize *resize;
2825   MPlist *plist;
2826
2827   if (! font_resize_list)
2828     load_font_resize_table ();
2829   if (! MPLIST_TAIL_P (font_resize_list))
2830     while (1)
2831       {
2832         plist = font_resize_list;
2833         while (registry ? (plist = mplist_find_by_key (plist, registry))
2834                : plist)
2835           {
2836             resize = (MFontResize *) MPLIST_VAL (plist);
2837             if (mfont__match_p (font, &resize->spec, MFONT_ADSTYLE))
2838               return resize->resize;
2839             plist = MPLIST_NEXT (plist);
2840           }
2841         if (registry == Mt)
2842           break;
2843         registry = Mt;
2844       }
2845   return 100;
2846 }
2847
2848 /*=*/
2849
2850 /***en
2851     @brief Get a list of fonts.
2852
2853     The mfont_list () functions returns a list of fonts available on
2854     frame $FRAME.  $FONT, if not NULL, limits fonts to ones
2855     that match with $FONT.  $LANGUAGE, if not @c Mnil, limits fonts to
2856     ones that support $LANGUAGE.  $MAXNUM, if greater than 0, limits
2857     the number of fonts.
2858
2859     $LANGUAGE argument exists just for backward compatibility, and the
2860     use is deprecated.  Use #Mlanguage font property instead.  If
2861     $FONT already has #Mlanguage property, $LANGUAGE is ignored.
2862
2863     @return
2864     This function returns a plist whose keys are family names and
2865     values are pointers to the object MFont.  The plist must be freed
2866     by m17n_object_unref ().  If no font is found, it returns
2867     NULL.  */
2868
2869 /***ja
2870     @brief ¥Õ¥©¥ó¥È¤Î¥ê¥¹¥È¤òÆÀ¤ë
2871
2872     ´Ø¿ô mfont_list () ¤Ï¥Õ¥ì¡¼¥à $FRAME ¤ÇÍøÍѲÄǽ¤Ê¥Õ¥©¥ó¥È¤Î¥ê¥¹¥È¤ò
2873     ÊÖ¤¹¡£$FONT ¤¬ NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢$FONT ¤È¹çÃפ¹¤ëÍøÍѲÄǽ¤Ê¥Õ¥©¥ó¥È
2874     ¤Î¥ê¥¹¥È¤òÊÖ¤¹¡£$LANGUAGE ¤¬ @c Mnil ¤Ç¤Ê¤±¤ì¤Ð¡¢$LANGUAGE ¤ò¥µ¥Ý¡¼
2875     ¥È¤¹¤ëÍøÍѲÄǽ¤Ê¥Õ¥©¥ó¥È¤Î¥ê¥¹¥È¤òÊÖ¤¹¡£$MAXNUM ¤Ï¡¢0 ¤è¤êÂ礭¤¤¾ì
2876     ¹ç¤Ë¤Ï¡¢ÊÖ¤¹¥Õ¥©¥ó¥È¤Î¿ô¤Î¾å¸Â¤Ç¤¢¤ë¡£
2877
2878     ¤¿¤À¤·¡¢°ú¿ô $LANGUAGE ¤ÏµìÈǤȤÎÀ°¹çÀ­¤Î¤¿¤á¤À¤±¤Ë¤¢¤ê¡¢¤½¤Î»ÈÍѤÏ
2879     ´«¤á¤é¤ì¤Ê¤¤¡£¥Õ¥©¥ó¥È¤Î #Mlanguage ¥×¥í¥Ñ¥Æ¥£¤ò»È¤¦¤Ù¤­¤Ç¤¢¤ë¡£¤â
2880     ¤· $FONT ¤¬¤¹¤Ç¤Ë¤³¤Î¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ã¤Æ¤¤¤¿¤é¡¢°ú¿ô $LANGUAGE ¤Ï̵
2881
2882
2883     @return 
2884     ¤³¤Î´Ø¿ô¤Ï¥­¡¼¤¬¥Õ¥©¥ó¥È¥Õ¥¡¥ß¥ê̾¤Ç¤¢¤êÃͤ¬ MFont ¥ª¥Ö¥¸¥§¥¯¥È¤Ø¤Î
2885     ¥Ý¥¤¥ó¥¿¤Ç¤¢¤ë¤è¤¦¤Êplist ¤òÊÖ¤¹¡£plist ¤Ï m17n_object_unref () ¤Ç
2886     ²òÊü¤¹¤ëɬÍפ¬¤¢¤ë¡£¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤é¤Ê¤±¤ì¤ÐNULL ¤òÊÖ¤¹¡£  */
2887
2888 MPlist *
2889 mfont_list (MFrame *frame, MFont *font, MSymbol language, int maxnum)
2890 {
2891   MPlist *plist, *pl;
2892   MFontList *font_list;
2893   int i;
2894   MFont spec;
2895   
2896   if (font)
2897     spec = *font;
2898   else
2899     MFONT_INIT (&spec);
2900
2901   if (spec.size < 0)
2902     {
2903       double pt = - spec.size;
2904
2905       spec.size = pt * frame->dpi / 72.27 + 0.5;
2906     }
2907
2908   if (language != Mnil)
2909     spec.capability = merge_capability (spec.capability, Mlanguage, language,
2910                                         0);
2911
2912   font_list = mfont__list (frame, &spec, &spec, 0);
2913   if (! font_list)
2914     return NULL;
2915   if (font_list->nfonts == 0)
2916     {
2917       free (font_list);
2918       return NULL;
2919     }
2920
2921   plist = pl = mplist ();
2922   for (i = 0; i < font_list->nfonts; i++)
2923     {
2924       MSymbol family = FONT_PROPERTY (font_list->fonts[i].font, MFONT_FAMILY);
2925
2926       if (family != Mnil)
2927         pl = mplist_add (pl, family, font_list->fonts[i].font);
2928     }
2929   free (font_list);
2930   return plist;
2931 }
2932
2933 /***en
2934     @brief Get a list of font famiy names.
2935
2936     The mfont_list_family_names () functions returns a list of font
2937     family names available on frame $FRAME.
2938
2939     @return
2940
2941     This function returns a plist whose keys are #Msymbol and values
2942     are symbols representing font family names.  The elements are
2943     sorted by alphabetical order.  The plist must be freed by
2944     m17n_object_unref ().  If not font is found, it returns NULL.  */
2945
2946 MPlist *
2947 mfont_list_family_names (MFrame *frame)
2948 {
2949   MPlist *plist = mplist (), *p;
2950
2951   MPLIST_DO (p, frame->font_driver_list)
2952     {
2953       MFontDriver *driver = MPLIST_VAL (p);
2954
2955       (driver->list_family_names) (frame, plist);
2956     }
2957   return plist;
2958 }
2959
2960
2961 /*=*/
2962
2963 /***en
2964     @brief Check the usability of a font.
2965
2966     The mfont_check () function checkes if $FONT can be used for
2967     $SCRIPT and $LANGUAGE in $FONTSET on $FRAME.
2968
2969     @return If the font is usable, return 1.  Otherwise return 0.
2970  */
2971
2972 int
2973 mfont_check (MFrame *frame, MFontset *fontset,
2974              MSymbol script, MSymbol language, MFont *font)
2975 {
2976   MRealizedFont *rfont;
2977   int best, score;
2978
2979   if (! fontset)
2980     fontset = frame->face->property[MFACE_FONTSET];
2981   rfont = mfontset__get_font (frame, fontset, script, language, font, &best);
2982   if (! rfont || ! best)
2983     return 0;
2984   score = font_score (&rfont->spec, font);
2985   return (score == 0 ? 2 : 1);
2986 }
2987
2988 /*=*/
2989
2990 /***en
2991     @brief Check is a font matches with a font spec.
2992
2993     The mfont_match_p () function checks if $FONT matches with the
2994     font-spec $SPEC.
2995
2996     @return 
2997     If the font matches, 1 is returned.  Otherwise 0 is returned.  */
2998
2999 int
3000 mfont_match_p (MFont *font, MFont *spec)
3001 {
3002   return mfont__match_p (font, spec, MFONT_REGISTRY);
3003 }
3004
3005 /*=*/
3006 /***en
3007     @brief Open a font.
3008
3009     The mfont_open () function opens $FONT on $FRAME, and returns a
3010     realized font.
3011
3012     @return
3013     If the font was successfully opened, a realized font is returned.
3014     Otherwize NULL is returned.
3015
3016     @seealso
3017     mfont_close ().  */
3018
3019
3020 MFont *
3021 mfont_open (MFrame *frame, MFont *font)
3022 {
3023   enum MFontType font_type = font->type;
3024
3025   if (font_type == MFONT_TYPE_SPEC)
3026     return mfont_find (frame, font, NULL, 0);
3027   if (font_type == MFONT_TYPE_OBJECT)
3028     return (MFont *) mfont__open (frame, font, font);
3029   if (font_type == MFONT_TYPE_REALIZED)
3030     return font;
3031   MERROR (MERROR_FONT, NULL);
3032 }
3033
3034 /*=*/
3035 /***en
3036     @brief Encapusulate a font.
3037
3038     The mfont_encapsulate () functions realizes a font by
3039     encapusulating data $DATA or type $DATA_TYPE on #FRAME.  Currently
3040     $DATA_TAPE is #Mfontconfig or #Mfreetype, and $DATA points to an
3041     object of FcPattern or FT_Face respectively.
3042
3043     @return
3044     If the operation was successful, a realized font is returned.
3045     Otherwise NULL is return.
3046
3047     @seealso
3048     mfont_close ().  */
3049
3050
3051 MFont *
3052 mfont_encapsulate (MFrame *frame, MSymbol data_type, void *data)
3053 {
3054   MPlist *p;
3055
3056   MPLIST_DO (p, frame->font_driver_list)
3057     {
3058       MFontDriver *driver = MPLIST_VAL (p);
3059       MRealizedFont *rfont;
3060
3061       if (driver->encapsulate
3062           && (rfont = driver->encapsulate (frame, data_type, data)))
3063         return (MFont *) rfont;
3064     }
3065
3066   return NULL;
3067 }
3068
3069 /*=*/
3070 /***en
3071     @brief Close a font.
3072
3073     The mfont_close () function close a realized font $FONT.  $FONT
3074     must be opened previously by mfont_open () or mfont_encapsulate
3075     ().
3076
3077     @return
3078     If the operation was successful, 0 is returned.  Otherwise, -1 is
3079     returned.
3080
3081     @seealso
3082     mfont_open (), mfont_encapsulate ().  */
3083
3084 int
3085 mfont_close (MFont *font)
3086 {
3087   enum MFontType font_type = font->type;
3088   MRealizedFont *rfont;
3089
3090   if (font_type != MFONT_TYPE_REALIZED)
3091     MERROR (MERROR_FONT, -1);
3092   rfont = (MRealizedFont *) font;
3093   if (rfont->encapsulating
3094       && rfont->driver->close)
3095     rfont->driver->close (rfont);
3096   return 0;
3097 }
3098
3099 /*** @} */
3100
3101 /*** @addtogroup m17nDebug */
3102 /*=*/
3103 /*** @{ */
3104
3105 /***en
3106     @brief Dump a font.
3107
3108     The mdebug_dump_font () function prints font $FONT in a human readable
3109     way to the stderr.
3110
3111     @return
3112     This function returns $FONT.  */
3113 /***ja
3114     @brief ¥Õ¥©¥ó¥È¤ò¥À¥ó¥×¤¹¤ë.
3115
3116     ´Ø¿ô mdebug_dump_font () ¤Ï¥Õ¥©¥ó¥È $FONT ¤ò stderr 
3117     ¤Ë¿Í´Ö¤Ë²ÄÆɤʷÁ¤Ç°õºþ¤¹¤ë¡£
3118
3119     @return
3120     ¤³¤Î´Ø¿ô¤Ï $FONT ¤òÊÖ¤¹¡£  */
3121
3122 MFont *
3123 mdebug_dump_font (MFont *font)
3124 {
3125   char *name;
3126   
3127   name = xlfd_unparse_name (font, 0);
3128   if (name)
3129     {
3130       fprintf (stderr, "%s", name);
3131       free (name);
3132     }
3133   if (font->file != Mnil)
3134     {
3135       char *file = MSYMBOL_NAME (font->file);
3136       char *lastslash = file, *p;
3137
3138       for (p = file; *p; p++)
3139         if (*p == '/')
3140           lastslash = p;
3141       if (name)
3142         fprintf (stderr, ",");
3143       fprintf (stderr, "%s", lastslash + 1);
3144     }
3145   if (font->capability != Mnil)
3146     fprintf (stderr, "%s", MSYMBOL_NAME (font->capability));
3147   return font;
3148 }
3149
3150 /*** @} */
3151
3152 /*
3153   Local Variables:
3154   coding: euc-japan
3155   End:
3156 */