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