(mfont__get_glyph_id): Return -1 if some code is invalid.
[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   int result = 0;
1680
1681   encoding = mfont->encoding ? mfont->encoding : find_encoding (mfont);
1682   for (; from < to; from++)
1683     {
1684       MGlyph *g = glyphs + from;
1685
1686       if (g->g.encoded)
1687         continue;
1688       if (! encoding->encoding_charset)
1689         g->g.code = MCHAR_INVALID_CODE;
1690       else if (mfont->source == MFONT_SOURCE_X && encoding->repertory_charset)
1691         g->g.code = ENCODE_CHAR (encoding->repertory_charset, g->g.code);
1692       else
1693         {
1694           unsigned code = ENCODE_CHAR (encoding->encoding_charset, g->g.code);
1695
1696           if (code != MCHAR_INVALID_CODE)
1697             {
1698               if (! driver)
1699                 {
1700                   if (mfont->type == MFONT_TYPE_REALIZED)
1701                     driver = rfont->driver;
1702                   else
1703                     {
1704                       driver = mplist_get (rfont->frame->font_driver_list,
1705                                            mfont->source == MFONT_SOURCE_X
1706                                            ? Mx : Mfreetype);
1707                       if (! driver)
1708                         MFATAL (MERROR_FONT);
1709                     }
1710                 }
1711               g->g.code
1712                 = (driver->encode_char) (rfont->frame, rfont->font, mfont,
1713                                          g->g.code);
1714             }
1715         }
1716       g->g.encoded = 1;
1717       if (g->g.code == MCHAR_INVALID_CODE)
1718         result = -1;
1719     }
1720   return result;
1721 }
1722
1723 int
1724 mfont__get_metrics (MFLTFont *font, MFLTGlyphString *gstring,
1725                     int from, int to)
1726 {
1727   MRealizedFont *rfont = ((MFLTFontForRealized *) font)->rfont;
1728   MGlyphString gstr;
1729
1730   gstr.glyphs = (MGlyph *) gstring->glyphs;
1731   (rfont->driver->find_metric) (rfont, &gstr, from, to);
1732   return 0;
1733 }
1734
1735 /* KEY <= MFONT_REGISTRY */
1736
1737 void
1738 mfont__set_property (MFont *font, enum MFontProperty key, MSymbol val)
1739 {
1740   int numeric;
1741
1742   if (val == Mnil)
1743     numeric = 0;
1744   else
1745     {
1746       numeric = FONT_PROPERTY_NUMERIC (val, key);
1747       if (! numeric)
1748         {
1749           numeric = mfont__property_table[key].used;
1750           MLIST_APPEND1 (mfont__property_table + key, names, val, MERROR_FONT);
1751           SET_FONT_PROPERTY_NUMERIC (val, key, numeric);
1752         }
1753     }
1754   font->property[key] = numeric;
1755 }
1756
1757 int
1758 mfont__parse_name_into_font (const char *name, MSymbol format, MFont *font)
1759 {
1760   int result = -1;
1761
1762   if (format == Mx || format == Mnil)
1763     result = xlfd_parse_name (name, font);
1764 #ifdef HAVE_FONTCONFIG
1765   if (format == Mfontconfig || (result < 0 && format == Mnil))
1766     result = mfont__ft_parse_name (name, font);
1767 #endif /* HAVE_FONTCONFIG */
1768   return result;
1769 }
1770
1771 MPlist *
1772 mfont__encoding_list (void)
1773 {
1774   if (! font_encoding_list)
1775     load_font_encoding_table ();
1776   return font_encoding_list;
1777 }
1778
1779 static void
1780 free_font_capability (void *object)
1781 {
1782   MFontCapability *cap = object;
1783   
1784   if (cap->script_tag)
1785     {
1786       int i;
1787       for (i = 0; i < MFONT_OTT_MAX; i++)
1788         {
1789           if (cap->features[i].str)
1790             free (cap->features[i].str);
1791           if (cap->features[i].tags)
1792             free (cap->features[i].tags);
1793         }
1794     }
1795   free (cap);
1796 }
1797
1798 MFontCapability *
1799 mfont__get_capability (MSymbol sym)
1800 {
1801   MFontCapability *cap = msymbol_get (sym, M_font_capability);
1802   char *str, *p, *endp;
1803
1804   if (cap)
1805     return cap;
1806   str = MSYMBOL_NAME (sym);
1807   if (str[0] != ':')
1808     return NULL;
1809   M17N_OBJECT (cap, free_font_capability, MERROR_FONT);
1810   msymbol_put (sym, M_font_capability, cap);
1811   M17N_OBJECT_UNREF (cap);
1812   endp = str + MSYMBOL_NAMELEN (sym);
1813   while (str < endp)
1814     {
1815       if (*str++ != ':')
1816         continue;
1817       if (str[0] == 'o' && strncmp (str + 1, "tf=", 3) == 0)
1818         {
1819           char *beg;
1820           MSymbol sym;
1821           int i;
1822
1823           str += 4;
1824           beg = str;
1825           for (i = 0, p = str; i < 4 && p < endp; i++, p++);
1826           if (i < 4)
1827             break;
1828           sym = msymbol__with_len (str, 4);
1829           cap->script = mscript__from_otf_tag (sym);
1830           if (cap->script == Mnil)
1831             break;
1832           cap->script_tag = OTF_tag (str);
1833           if (*p == '/')
1834             {
1835               for (i = 0, str = ++p; i < 4 && p < endp; i++, p++);
1836               if (i < 4)
1837                 {
1838                   cap->script = Mnil;
1839                   cap->script_tag = 0;
1840                   break;
1841                 }
1842               cap->langsys_tag = OTF_tag (str);
1843             }
1844           else
1845             cap->langsys_tag = 0;
1846
1847           for (i = 0; i < MFONT_OTT_MAX; i++)
1848             cap->features[i].nfeatures = -1;
1849
1850           while (*p == '=' || *p == '+')
1851             {
1852               int idx = *p == '=' ? MFONT_OTT_GSUB : MFONT_OTT_GPOS;
1853
1854               str = ++p;
1855               while (p < endp && *p != '+') p++;
1856               if (str < p)
1857                 {
1858                   int n;
1859                   /* We never have more than (p - str) tags.  */
1860                   OTF_Tag *tags = alloca (sizeof (OTF_Tag) * (p - str));
1861                   char *p0;
1862
1863                   cap->features[idx].str = malloc (p - str + 1);
1864                   for (i = n = 0, p0 = str; str + i < p; i++)
1865                     {
1866                       cap->features[idx].str[i] = str[i];
1867                       if (str[i] == ',' || str + i + 1 == p)
1868                         {
1869                           if (*p0 == '*')
1870                             tags[n] = 0;
1871                           else if (*p0 == '~')
1872                             tags[n] = OTF_tag (p0 + 1) | 0x80000000;
1873                           else
1874                             tags[n] = OTF_tag (p0);
1875                           n++;
1876                           p0 = str + i + 1;
1877                         }
1878                     }
1879                   cap->features[idx].str[i] = '\0';
1880                   cap->features[idx].nfeatures = n;
1881                   if (n > 0)
1882                     {
1883                       int size = sizeof (OTF_Tag) * n;
1884
1885                       cap->features[idx].tags = malloc (size);
1886                       memcpy (cap->features[idx].tags, tags, size);
1887                     }
1888                 }
1889               else
1890                 {
1891                   cap->features[idx].str = NULL;
1892                   cap->features[idx].nfeatures = 0;
1893                 }
1894             }
1895
1896           for (i = 0; i < MFONT_OTT_MAX; i++)
1897             if (cap->features[i].nfeatures < 0)
1898               {
1899                 cap->features[i].str = strdup ("*");
1900                 cap->features[i].nfeatures = 1;
1901                 cap->features[i].tags = malloc (sizeof (OTF_Tag));
1902                 cap->features[i].tags[0] = 0;
1903               }
1904           cap->otf = msymbol__with_len (beg, p - beg);
1905           str = p;
1906         }
1907       else if (str[0] == 'l' && strncmp (str + 1, "ang=", 4) == 0)
1908         {
1909           str += 5;
1910           for (p = str; p < endp && *p != ':'; p++);
1911           if (str < p)
1912             cap->language = msymbol__with_len (str, p - str);
1913           str = p;
1914         }
1915       else if (str[0] == 's' && strncmp (str + 1, "cript=", 6) == 0)
1916         {
1917           str += 7;
1918           for (p = str; p < endp && *p != ':'; p++);
1919           if (str < p)
1920             cap->script = msymbol__with_len (str, p - str);
1921           str = p;
1922         }
1923     }
1924   return cap;
1925 }
1926
1927 int
1928 mfont__check_capability (MRealizedFont *rfont, MSymbol capability)
1929 {
1930   return (rfont->driver->check_capability (rfont, capability));
1931 }
1932
1933
1934 /*** @} */
1935 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
1936
1937 \f
1938
1939 /* External API */
1940
1941 /*** @addtogroup m17nFont */
1942 /*** @{ */
1943 /*=*/
1944
1945 /***en @name Variables: Keys of font property.  */
1946 /***ja @name ÊÑ¿ô: ¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤ò»ØÄꤹ¤ëÄêµÁºÑ¤ß¥·¥ó¥Ü¥ë */
1947 /*** @{ */
1948 /*=*/
1949
1950 /***en
1951     @brief Key of font property specifying foundry.
1952
1953     The variable #Mfoundry is a symbol of name <tt>"foundry"</tt> and
1954     is used as a key of font property and face property.  The property
1955     value must be a symbol whose name is a foundry name of a font.  */
1956 /***ja
1957     @brief ³«È¯¸µ¤ò»ØÄꤹ¤ë¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼.
1958     
1959     ÊÑ¿ô #Mfoundry ¤Ï <tt>"fonudry"</tt> 
1960     ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤È¥Õ¥§¡¼¥¹¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼¤È¤·¤ÆÍѤ¤¤é¤ì¤ë¡£
1961     Ãͤϡ¢¥Õ¥©¥ó¥È¤Î³«È¯¸µÌ¾¤ò̾Á°¤È¤·¤Æ»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£    */
1962
1963 MSymbol Mfoundry;
1964
1965 /***en
1966     @brief Key of font property specifying family.
1967
1968     The variable #Mfamily is a symbol of name <tt>"family"</tt> and is
1969     used as a key of font property and face property.  The property
1970     value must be a symbol whose name is a family name of a font.  */ 
1971 /***ja
1972     @brief ¥Õ¥¡¥ß¥ê¤ò»ØÄꤹ¤ë¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼.
1973     
1974     ÊÑ¿ô #Mfamily ¤Ï <tt>"family"</tt> 
1975     ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤È¥Õ¥§¡¼¥¹¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼¤È¤·¤ÆÍѤ¤¤é¤ì¤ë¡£
1976     Ãͤϡ¢¥Õ¥©¥ó¥È¤Î¥Õ¥¡¥ß¥ê̾¤ò̾Á°¤È¤·¤Æ»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£    */
1977
1978 MSymbol Mfamily;
1979
1980 /***en
1981     @brief Key of font property specifying weight.
1982
1983     The variable #Mweight is a symbol of name <tt>"weight"</tt> and is
1984     used as a key of font property and face property.  The property
1985     value must be a symbol whose name is a weight name of a font (e.g
1986     "medium", "bold").  */ 
1987 /***ja
1988     @brief ÂÀ¤µ¤ò»ØÄꤹ¤ë¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼.
1989     
1990     ÊÑ¿ô #Mweight ¤Ï <tt>"weight"</tt> 
1991     ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤È¥Õ¥§¡¼¥¹¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼¤È¤·¤ÆÍѤ¤¤é¤ì¤ë¡£
1992     Ãͤϡ¢¥Õ¥©¥ó¥È¤ÎÂÀ¤µÌ¾ ( "medium", "bold" Åù) ¤ò̾Á°¤È¤·¤Æ»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£    */
1993
1994 MSymbol Mweight;
1995
1996 /***en
1997     @brief Key of font property specifying style.
1998
1999     The variable #Mstyle is a symbol of name <tt>"style"</tt> and is
2000     used as a key of font property and face property.  The property
2001     value must be a symbol whose name is a style name of a font (e.g
2002     "r", "i", "o").  */ 
2003 /***ja
2004     @brief ¥¹¥¿¥¤¥ë¤ò»ØÄꤹ¤ë¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼.
2005     
2006     ÊÑ¿ô #Mstyle ¤Ï <tt>"style"</tt> 
2007     ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤È¥Õ¥§¡¼¥¹¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼¤È¤·¤ÆÍѤ¤¤é¤ì¤ë¡£
2008     Ãͤϡ¢¥Õ¥©¥ó¥È¤Î¥¹¥¿¥¤¥ë̾ ("r", "i", "o" Åù)¤ò̾Á°¤È¤·¤Æ»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£    */
2009
2010 MSymbol Mstyle;
2011
2012 /***en
2013     @brief Key of font property specifying stretch.
2014
2015     The variable #Mstretch is a symbol of name <tt>"stretch"</tt> and
2016     is used as a key of font property and face property.  The property
2017     value must be a symbol whose name is a stretch name of a font (e.g
2018     "normal", "condensed").  */ 
2019 /***ja
2020     @brief Éý¤ò»ØÄꤹ¤ë¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼.
2021     
2022     ÊÑ¿ô #Mstretch ¤Ï <tt>"stretch"</tt> 
2023     ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤È¥Õ¥§¡¼¥¹¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼¤È¤·¤ÆÍѤ¤¤é¤ì¤ë¡£
2024     Ãͤϡ¢¥Õ¥©¥ó¥È¤Îʸ»úÉý̾ ( "normal", "condensed" Åù)¤ò̾Á°¤È¤·¤Æ»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£    */
2025
2026 MSymbol Mstretch;
2027
2028 /***en
2029     @brief Key of font property specifying additional style.
2030
2031     The variable #Madstyle is a symbol of name <tt>"adstyle"</tt> and
2032     is used as a key of font property and face property.  The property
2033     value must be a symbol whose name is an additional style name of a
2034     font (e.g "serif", "", "sans").  */ 
2035 /***ja
2036     @brief adstyle ¤ò»ØÄꤹ¤ë¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼.
2037     
2038     ÊÑ¿ô #Madstyle ¤Ï <tt>"adstyle"</tt> 
2039     ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤È¥Õ¥§¡¼¥¹¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼¤È¤·¤ÆÍѤ¤¤é¤ì¤ë¡£
2040     Ãͤϡ¢¥Õ¥©¥ó¥È¤Î adstyle Ì¾("serif", "", "sans" Åù)¤ò̾Á°¤È¤·¤Æ»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£    */
2041
2042 MSymbol Madstyle;
2043
2044 /***en
2045     @brief Key of font property specifying spacing.
2046
2047     The variable #Madstyle is a symbol of name <tt>"spacing"</tt> and
2048     is used as a key of font property.  The property value must be a
2049     symbol whose name specifies the spacing of a font (e.g "p" for
2050     proportional, "m" for monospaced).  */ 
2051 /***ja
2052     @brief spacing ¤ò»ØÄꤹ¤ë¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼.
2053     
2054     ÊÑ¿ô #Mspacing ¤Ï <tt>"spacing"</tt> ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢
2055     ¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼¤È¤·¤ÆÍѤ¤¤é¤ì¤ë¡£Ãͤϡ¢¥Õ¥©¥ó¥È¤Î spacing
2056     ÆÃÀ­¤ò¼¨¤¹Ì¾Á° ("p", "m" Åù)¤ò»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£  */
2057
2058 MSymbol Mspacing;
2059
2060 /***en
2061     @brief Key of font property specifying registry.
2062
2063     The variable #Mregistry is a symbol of name <tt>"registry"</tt>
2064     and is used as a key of font property.  The property value must be
2065     a symbol whose name is a registry name a font registry
2066     (e.g. "iso8859-1", "jisx0208.1983-0").  */ 
2067 /***ja
2068     @brief ¥ì¥¸¥¹¥È¥ê¤ò»ØÄꤹ¤ë¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼.
2069     
2070     ÊÑ¿ô #Mregistry ¤Ï <tt>"registry"</tt> 
2071     ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤È¥Õ¥§¡¼¥¹¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼¤È¤·¤ÆÍѤ¤¤é¤ì¤ë¡£
2072     Ãͤϡ¢¥Õ¥©¥ó¥È¤Î¥ì¥¸¥¹¥È¥ê̾ ( "iso8859-1", "jisx0208.1983-0" 
2073     Åù) ¤ò̾Á°¤È¤·¤Æ»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£    */
2074
2075 MSymbol Mregistry;
2076
2077 /***en
2078     @brief Key of font property specifying size.
2079
2080     The variable #Msize is a symbol of name <tt>"size"</tt> and is
2081     used as a key of font property and face property.  The property
2082     value must be an integer specifying a font design size in the unit
2083     of 1/10 point (on 100 dpi display).  */ 
2084 /***ja
2085     @brief ¥µ¥¤¥º¤ò»ØÄꤹ¤ë¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼.
2086     
2087     ÊÑ¿ô #Msize ¤Ï <tt>"size"</tt> 
2088     ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤È¥Õ¥§¡¼¥¹¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼¤È¤·¤ÆÍѤ¤¤é¤ì¤ë¡£Ãͤϡ¢
2089     100 dpi ¤Î¥Ç¥£¥¹¥×¥ì¥¤¾å¤Ç¤Î¥Õ¥©¥ó¥È¤Î¥Ç¥¶¥¤¥ó¥µ¥¤¥º¤ò 1/10 
2090     ¥Ý¥¤¥ó¥Èñ°Ì¤Ç¼¨¤¹À°¿ôÃͤǤ¢¤ë¡£
2091     */
2092
2093 MSymbol Msize;
2094
2095 /***en
2096     @brief Key of font property specifying file name.
2097
2098     The variable #Mfontfile is a symbol of name <tt>"fontfile"</tt>
2099     and is used as a key of font property.  The property value must be
2100     a symbol whose name is a font file name.  */ 
2101 MSymbol Motf;
2102
2103 /***en
2104     @brief Key of font property specifying file name.
2105
2106     The variable #Mfontfile is a symbol of name <tt>"fontfile"</tt>
2107     and is used as a key of font property.  The property value must be
2108     a symbol whose name is a font file name.  */ 
2109 /***ja
2110     @brief ¥Õ¥©¥ó¥È¥Õ¥¡¥¤¥ë¤ò»ØÄꤹ¤ë¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼.
2111     
2112     ÊÑ¿ô #Mfontfile ¤Ï <tt>"fontfile"</tt> ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢
2113     ¤ê¡¢¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼¤È¤·¤ÆÍѤ¤¤é¤ì¤ë¡£Ãͤϡ¢¥Õ¥©¥ó¥È¥Õ¥¡¥¤
2114     ¥ë̾¤ò̾Á°¤È¤·¤Æ»ý¤Ä¤È¤¹¤ë¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£ */
2115
2116 MSymbol Mfontfile;
2117
2118 /***en
2119     @brief Key of font property specifying resolution.
2120
2121     The variable #Mresolution is a symbol of name <tt>"resolution"</tt> and
2122     is used as a key of font property and face property.  The property
2123     value must be an integer to specifying a font resolution in the
2124     unit of dots per inch (dpi).  */ 
2125 /***ja
2126     @brief ²òÁüÅÙ¤ò»ØÄꤹ¤ë¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼.
2127     
2128     ÊÑ¿ô #Mresolution ¤Ï <tt>"resolution"</tt> 
2129     ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤È¥Õ¥§¡¼¥¹¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼¤È¤·¤ÆÍѤ¤¤é¤ì¤ë¡£
2130     Ãͤϡ¢¥Õ¥©¥ó¥È¤Î²òÁüÅÙ¤ò dots per inch (dpi) Ã±°Ì¤Ç¼¨¤¹À°¿ôÃͤǤ¢¤ë¡£    */
2131
2132 MSymbol Mresolution;
2133
2134 /***en
2135     @brief Key of font property specifying max advance width.
2136
2137     The variable #Mmax_advance is a symbol of name
2138     <tt>"max-advance"</tt> and is used as a key of font property.  The
2139     property value must be an integer specifying a font's max advance
2140     value by pixels.  */ 
2141
2142 MSymbol Mmax_advance;
2143
2144
2145 /***en
2146     @brief Symbol of name "fontconfig".
2147
2148     The variable #Mfontconfig is to be used as an argument of the
2149     functions mfont_parse_name () and mfont_unparse_name ().  */
2150 /***ja
2151     @brief "fontconfig" ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë.
2152
2153     ÊÑ¿ô #Mfontconfig ¤Ï´Ø¿ô mfont_parse_name () ¤È mfont_unparse_name ()
2154     ¤Î°ú¿ô¤È¤·¤ÆÍѤ¤¤é¤ì¤ë¡£  */
2155
2156 MSymbol Mfontconfig;
2157
2158 /***en
2159     @brief Symbol of name "x".
2160
2161     The variable #Mx is to be used for a value of <type> member of the
2162     structure #MDrawGlyph to specify the type of <fontp> member is
2163     actually (XFontStruct *).  */
2164 /***ja
2165     @brief "x" ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë.
2166
2167     ÊÑ¿ô #Mx ¤Ï¹½Â¤ #MDrawGlyph ¤Î¥á¥ó¥Ð <type> 
2168     ¤ÎÃͤȤ·¤ÆÍѤ¤¤é¤ì¡¢¥á¥ó¥Ð <fontp> ¤Î·¿¤¬¼ÂºÝ¤Ë¤Ï (XFontStruct *) ¤Ç¤¢¤ë¤³¤È¤òɽ¤¹.  */
2169
2170 MSymbol Mx;
2171
2172 /***en
2173     @brief Symbol of name "freetype".
2174
2175     The variable #Mfreetype is to be used for a value of <type> member
2176     of the structure #MDrawGlyph to specify the type of <fontp> member
2177     is actually FT_Face.  */
2178 /***ja
2179     @brief "freetype" ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë.
2180
2181     ÊÑ¿ô #Mfreetype ¤Ï¹½Â¤ #MDrawGlyph ¤Î¥á¥ó¥Ð <type> 
2182     ¤ÎÃͤȤ·¤ÆÍѤ¤¤é¤ì¡¢¥á¥ó¥Ð <fontp> ¤Î·¿¤¬¼ÂºÝ¤Ë¤Ï FT_Face ¤Ç¤¢¤ë¤³¤È¤òɽ¤¹¡£  */
2183
2184 MSymbol Mfreetype;
2185
2186 /***en
2187     @brief Symbol of name "xft".
2188
2189     The variable #Mxft is to be used for a value of <type> member of the
2190     structure #MDrawGlyph to specify the type of <fontp> member
2191     is actually (XftFont *).  */
2192 /***ja
2193     @brief  "xft" ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë.
2194
2195     ÊÑ¿ô #Mxft ¤Ï¹½Â¤ #MDrawGlyph ¤Î¥á¥ó¥Ð <type> 
2196     ¤ÎÃͤȤ·¤ÆÍѤ¤¤é¤ì¡¢¥á¥ó¥Ð <fontp> ¤Î·¿¤¬¼ÂºÝ¤Ë¤Ï (XftFont *) ¤Ç¤¢¤ë¤³¤È¤òɽ¤¹¡£  */
2197
2198 MSymbol Mxft;
2199
2200 /*=*/
2201 /*** @} */
2202 /*=*/
2203
2204 /***en
2205     @brief List of font files and directories that contain font files.
2206
2207     The variable @c mfont_freetype_path is a plist of FreeType font
2208     files and directories that contain FreeType font files.  Key of
2209     the element is @c Mstring, and the value is a string that
2210     represents a font file or a directory.
2211
2212     The macro M17N_INIT () sets up this variable to contain the
2213     sub-directory "fonts" of the m17n database and the environment
2214     variable "M17NDIR".  The first call of mframe () creates the
2215     internal list of the actually available fonts from this variable.
2216     Thus, an application program, if necessary, must modify the
2217     variable before calling mframe ().  If it is going to add a new
2218     element, value must be a string that can be safely freed.
2219
2220     If the m17n library is not configured to use the FreeType library,
2221     this variable is not used.  */
2222 /***ja
2223     @brief ¥Õ¥©¥ó¥È¥Õ¥¡¥¤¥ë¤È¥Õ¥©¥ó¥È¥Õ¥¡¥¤¥ë¤ò´Þ¤à¥Ç¥£¥ì¥¯¥È¥ê¤Î¥ê¥¹¥È.
2224
2225     ÊÑ¿ô @c mfont_freetype_path ¤Ï¡¢¥Õ¥©¥ó¥È¥Õ¥¡¥¤¥ë¤È¥Õ¥©¥ó¥È¥Õ¥¡¥¤¥ë¤ò´Þ¤à¥Ç¥£¥ì¥¯¥È¥ê¤Î 
2226     plist ¤Ç¤¢¤ë¡£³ÆÍ×ÁǤΥ­¡¼¤Ï @c Mstring 
2227     ¤Ç¤¢¤ê¡¢Ãͤϥե©¥ó¥È¥Õ¥¡¥¤¥ë¤«¥Ç¥£¥ì¥¯¥È¥ê¤ò¼¨¤¹Ê¸»úÎó¤Ç¤¢¤ë¡£
2228
2229     ¥Þ¥¯¥í M17N_INIT () ¤Ë¤è¤Ã¤Æ¡¢¤³¤ÎÊÑ¿ô¤Ï m17n ¥Ç¡¼¥¿¥Ù¡¼¥¹¤È´Ä¶­ÊÑ¿ô 
2230     "M17NDIR" ÁÐÊý¤Î¥µ¥Ö¥Ç¥£¥ì¥¯¥È¥ê "fonts" ¤ò´Þ¤à¤è¤¦¤ËÀßÄꤵ¤ì¤ë¡£
2231     mframe () ¤ÎºÇ½é¤Î¸Æ¤Ó½Ð¤·¤ÎºÝ¤Ë¡¢¤³¤ÎÊÑ¿ô¤«¤é¼ÂºÝ¤Ë»ÈÍѤǤ­¤ë¥Õ¥©¥ó¥È¤ÎÆâÉô¥ê¥¹¥È¤¬ºî¤é¤ì¤ë¡£
2232     ¤½¤³¤Ç¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥à¤Ï¡¢mframe () 
2233     ¤ò¸Æ¤ÖÁ°¤Ë¡ÊɬÍפʤé¤Ð¡Ë¤³¤ÎÊÑ¿ô¤òÊѹ¹¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
2234     ¿·¤·¤¤Í×ÁǤòÄɲ乤ë¾ì¹ç¤Ë¤Ï¡¢¤½¤ÎÃͤϰÂÁ´¤Ë³«Êü¤Ç¤­¤ëʸ»úÎó¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
2235
2236     m17n ¥é¥¤¥Ö¥é¥ê¤¬ FreeType ¥é¥¤¥Ö¥é¥ê¤ò»È¤¦¤è¤¦¤ËÀßÄꤵ¤ì¤Æ¤Ê¤¤¾ì¹ç¤Ë¤Ï¡¢¤³¤ÎÊÑ¿ô¤ÏÍѤ¤¤é¤ì¤Ê¤¤¡£ */
2237
2238 MPlist *mfont_freetype_path;
2239
2240 /*=*/
2241
2242 /***en
2243     @brief Create a new font.
2244
2245     The mfont () function creates a new font object that has no
2246     property.
2247
2248     @return
2249     This function returns a pointer to the created font object.  */
2250 /***ja
2251     @brief ¿·¤·¤¤¥Õ¥©¥ó¥È¤òºî¤ë.
2252
2253     ´Ø¿ô mfont () ¤Ï¥×¥í¥Ñ¥Æ¥£¤ò°ìÀÚ»ý¤¿¤Ê¤¤¿·¤·¤¤¥Õ¥©¥ó¥È¤ò¥ª¥Ö¥¸¥§¥¯¥È¤òºî¤ë¡£
2254
2255     @return
2256     ¤³¤Î´Ø¿ô¤Ïºî¤Ã¤¿¥Õ¥©¥ó¥È¥ª¥Ö¥¸¥§¥¯¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£  */
2257
2258 MFont *
2259 mfont ()
2260 {
2261   MFont *font;
2262
2263   MSTRUCT_CALLOC (font, MERROR_FONT);
2264   return font;
2265 }
2266
2267 /*=*/
2268
2269 /***en
2270     @brief Create a font by parsing a fontname.
2271
2272     The mfont_parse_name () function creates a new font object.  The
2273     properties are extracted fontname $NAME.
2274
2275     $FORMAT specifies the format of $NAME.  If $FORMAT is #Mx, $NAME
2276     is parsed as XLFD (X Logical Font Description).  If $FORMAT is
2277     #Mfontconfig, $NAME is parsed as Fontconfig's textual
2278     representation of font.  If $FORMAT is #Mnil, $NAME is at first
2279     parsed as XLFD, and it it fails, parsed as Fontconfig's
2280     representation.
2281
2282     @return
2283     If the operation was successful, this function returns a pointer
2284     to the created font.  Otherwise it returns @c NULL.  */
2285
2286 /***ja
2287     @brief ¥Õ¥©¥ó¥È̾¤«¤é¥Õ¥©¥ó¥È¤òºî¤ë.
2288
2289     ´Ø¿ô mfont_parse_name () ¤Ï¡¢¥Õ¥©¥ó¥È̾ 
2290     $NAME ¤«¤é¼è¤ê½Ð¤µ¤ì¤¿¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ä¡¢¿·¤·¤¤¥Õ¥©¥ó¥È¥ª¥Ö¥¸¥§¥¯¥È¤òºî¤ë¡£
2291
2292     $FORMAT ¤Ï $NAME ¤Î¥Õ¥©¡¼¥Þ¥Ã¥È¤ò»ØÄꤹ¤ë¡£$FORMAT ¤¬ #Mx ¤Ç¤¢¤ì¤Ð¡¢
2293     $NAME ¤Ï XLFD (X Logical Font Description) ¤Ë½¾¤Ã¤Æ²òÀϤµ¤ì¤ë¡£
2294     $FORMAT ¤¬ #Mfontconfig ¤Ç¤¢¤ì¤Ð $NAME ¤Ï Fontfonfig 
2295     ¤Î¥Õ¥©¥ó¥È¥Æ¥­¥¹¥Èɽ¸½¤Ë½¾¤Ã¤Æ²òÀϤµ¤ì¤ë¡£$FORMAT ¤¬ #Mnil ¤Ç¤¢¤ì¤Ð¡¢¤Þ¤º XLFD 
2296     ¤Ë½¾¤Ã¤Æ²òÀϤµ¤ì¡¢¤½¤ì¤Ë¼ºÇÔ¤·¤¿¤é Fontconfig ¤Ë½¾¤Ã¤Æ²òÀϤµ¤ì¤ë¡£
2297
2298     @return
2299     ½èÍý¤¬À®¸ù¤¹¤ì¤Ð mfont_parse_name () 
2300     ¤Ï¿·¤·¤¯ºî¤é¤ì¤¿¥Õ¥©¥ó¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð @c NULL ¤òÊÖ¤¹¡£  */
2301
2302 MFont *
2303 mfont_parse_name (const char *name, MSymbol format)
2304 {
2305   MFont template, *font;
2306   
2307   MFONT_INIT (&template);
2308   if (mfont__parse_name_into_font (name, format, &template) < 0)
2309     MERROR (MERROR_FONT, NULL);
2310   MSTRUCT_CALLOC (font, MERROR_FONT);
2311   *font = template;
2312   return font;
2313 }
2314
2315 /*=*/
2316
2317 /***en
2318     @brief Create a fontname from a font.
2319
2320     The mfont_unparse_name () function creates a fontname string
2321     from font $FONT according to $FORMAT.
2322
2323     $FORMAT must be #Mx or #Mfontconfig.  If it is #Mx, the fontname
2324     is in XLFD (X Logical Font Description) format.  If it is
2325     #Mfontconfig, the fontname is in the style of Fontconfig's text
2326     representation.
2327
2328     @return
2329     This function returns a newly allocated fontname string, which is
2330     not freed unless the user explicitly does so by free ().  */
2331
2332 /***ja
2333     @brief ¥Õ¥©¥ó¥È¤«¤é¥Õ¥©¥ó¥È̾¤òºî¤ë.
2334
2335     ´Ø¿ô mfont_unparse_name () ¤Ï ¥Õ¥©¥ó¥È̾¤Îʸ»úÎó¤ò¥Õ¥©¥ó¥È $FONT 
2336     ¤ò¸µ¤Ë$FORMAT ¤Ë½¾¤Ã¤Æºî¤ë¡£
2337
2338     $FORMAT ¤Ï #Mx ¤Þ¤¿¤Ï #Mfontconfig ¤Ç¤¢¤ë¡£
2339     #Mx ¤Ê¤é¤Ð¥Õ¥©¥ó¥È̾¤Ï XLFD (X Logical Font Description) ¤Ë½¾¤¦¡£
2340     #Mfontconfig ¤Ê¤é¤Ð¥Õ¥©¥ó¥È̾¤Ï Fontconfig ¤Î¥Õ¥©¥ó¥È¥Æ¥­¥¹¥Èɽ¸½¤Ë½¾¤¦¡£
2341
2342     @return 
2343     ¤³¤Î´Ø¿ô¤Ï¿·¤¿¤Ë¥¢¥í¥±¡¼¥È¤·¤¿¥Õ¥©¥ó¥È̾¤Îʸ»úÎó¤òÊÖ¤¹¡£Ê¸»úÎó¤Ï¡¢¥æ¡¼¥¶¤¬
2344     free () ¤Ë¤è¤Ã¤ÆÌÀ¼¨Åª¤Ë²òÊü¤·¤Ê¤¤¸Â¤ê²òÊü¤µ¤ì¤Ê¤¤¡£  */
2345
2346 char *
2347 mfont_unparse_name (MFont *font, MSymbol format)
2348 {
2349   char *name;
2350
2351   if (format == Mx)
2352     name = xlfd_unparse_name (font, 1);
2353 #ifdef HAVE_FONTCONFIG
2354   else if (format == Mfontconfig)
2355     name = mfont__ft_unparse_name (font);
2356
2357 #endif /* HAVE_FONTCONFIG */
2358   else
2359     MERROR (MERROR_FONT, NULL);
2360   return name;
2361 }
2362
2363 /*=*/
2364
2365 /***en
2366     @brief Make a copy of a font.
2367
2368     The mfont_copy () function returns a new copy of font $FONT.  */
2369 /***ja
2370     @brief ¥Õ¥©¥ó¥È¤Î¥³¥Ô¡¼¤òºî¤ë.
2371
2372     ´Ø¿ô Mfont_copy () ¤Ï¥Õ¥©¥ó¥È $FONT ¤Î¥³¥Ô¡¼¤òºî¤ê¡¢¤½¤ì¤òÊÖ¤¹¡£ */
2373
2374 MFont *
2375 mfont_copy (MFont *font)
2376 {
2377   MFont *copy;
2378
2379   MSTRUCT_MALLOC (copy, MERROR_FONT);
2380   *copy = *font;
2381   return copy;
2382 }
2383
2384 /*=*/
2385
2386 /***en
2387     @brief Get a property value of a font.
2388
2389     The mfont_get_prop () function gets the value of $KEY property of
2390     font $FONT.  $KEY must be one of the following symbols:
2391
2392         @c Mfoundry, @c Mfamily, @c Mweight, @c Mstyle, @c Mstretch,
2393         @c Madstyle, @c Mregistry, @c Msize, @c Mresolution, @c Mspacing.
2394
2395     If $FONT is a return value of mfont_find (), $KEY can also be one
2396     of the following symbols:
2397
2398         #Mfont_ascent, #Mfont_descent, #Mmax_advance.
2399
2400     @return If $KEY is @c Mfoundry, @c Mfamily, @c Mweight, @c Mstyle,
2401     @c Mstretch, @c Madstyle, @c Mregistry, or @c Mspacing, this
2402     function returns the corresponding value as a symbol.  If the font
2403     does not have $KEY property, it returns @c Mnil.  If $KEY is @c
2404     Msize, @c Mresolution, #Mfont_ascent, Mfont_descent, or
2405     #Mmax_advance, this function returns the corresponding value as an
2406     integer.  If the font does not have $KEY property, it returns 0.
2407     If $KEY is something else, it returns @c NULL and assigns an error
2408     code to the external variable #merror_code.  */
2409  
2410 /***ja
2411     @brief ¥Õ¥©¥ó¥È¤Î¥×¥í¥Ñ¥Æ¥£¤ÎÃͤòÆÀ¤ë.
2412
2413     ´Ø¿ô mfont_get_prop () ¤Ï¥Õ¥©¥ó¥È $FONT ¤Î¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥­¡¼¤¬
2414     $KEY ¤Ç¤¢¤ë¤â¤Î¤ÎÃͤòÊÖ¤¹¡£$KEY ¤Ï°Ê²¼¤Î¥·¥ó¥Ü¥ë¤Î¤¤¤º¤ì¤«¤Ç¤Ê¤±¤ì
2415     ¤Ð¤Ê¤é¤Ê¤¤¡£
2416
2417         @c Mfoundry, @c Mfamily, @c Mweight, @c Mstyle, @c Mstretch,
2418         @c Madstyle, @c Mregistry, @c Msize, @c Mresolution, @c Mspacing.
2419
2420     @return $KEY ¤¬ @c Mfoundry, @c Mfamily, @c Mweight, @c Mstyle, @c
2421     Mstretch, @c Madstyle, @c Mregistry, @c Mspacing ¤Î¤¤¤º¤ì¤«¤Ç¤¢¤ì¤Ð¡¢
2422     ÁêÅö¤¹¤ëÃͤò¥·¥ó¥Ü¥ë¤È¤·¤ÆÊÖ¤¹¡£¥Õ¥©¥ó¥È¤¬¤½¤Î¥×¥í¥Ñ¥Æ¥£¤ò»ý¤¿¤Ê¤¤
2423     ¾ì¹ç¤Ë¤Ï@c Mnil ¤òÊÖ¤¹¡£$KEY ¤¬ @c Msize ¤¢¤ë¤¤¤Ï @c Mresolution ¤Î
2424     ¾ì¹ç¤Ë¤Ï¡¢ÁêÅö¤¹¤ëÃͤò¤ÏÀ°¿ôÃͤȤ·¤ÆÊÖ¤¹¡£¥Õ¥©¥ó¥È¤¬¤½¤Î¥×¥í¥Ñ¥Æ¥£
2425     ¤ò»ý¤¿¤Ê¤¤¾ì¹ç¤Ë¤Ï 0 ¤òÊÖ¤¹¡£$KEY ¤¬¤½¤ì°Ê³°¤Î¤â¤Î¤Ç¤¢¤ì¤Ð¡¢@c
2426     NULL ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£  */
2427
2428 void *
2429 mfont_get_prop (MFont *font, MSymbol key)
2430 {
2431   MRealizedFont *rfont = NULL;
2432
2433   if (font->type == MFONT_TYPE_REALIZED)
2434     rfont = (MRealizedFont *) font;
2435
2436   if (key == Mfoundry)
2437     return (void *) FONT_PROPERTY (font, MFONT_FOUNDRY);
2438   if (key == Mfamily)
2439     return (void *) FONT_PROPERTY (font, MFONT_FAMILY);
2440   if (key == Mweight)
2441     return (void *) FONT_PROPERTY (font, MFONT_WEIGHT);
2442   if (key == Mstyle)
2443     return (void *) FONT_PROPERTY (font, MFONT_STYLE);
2444   if (key == Mstretch)
2445     return (void *) FONT_PROPERTY (font, MFONT_STRETCH);
2446   if (key == Madstyle)
2447     return (void *) FONT_PROPERTY (font, MFONT_ADSTYLE);
2448   if (key == Mregistry)
2449     return (void *) FONT_PROPERTY (font, MFONT_REGISTRY);
2450   if (key == Msize)
2451     {
2452       int size = font->size;
2453       return (void *) size;
2454     }
2455   if (key == Mresolution)
2456     {
2457       int resy = font->property[MFONT_RESY];
2458       return (void *) resy;
2459     }
2460   if (key == Mlanguage || key == Mscript || key == Motf)
2461     {
2462       MFontCapability *cap;
2463
2464       if (! font->capability)
2465         return NULL;
2466       cap = mfont__get_capability (font->capability);
2467       if (key == Mlanguage)
2468         return cap->language;
2469       if (key == Mscript)
2470         return cap->script;
2471       return cap->otf;
2472     }
2473
2474   if (key == Mfontfile)
2475     return (void *) font->file;
2476   if (key == Mspacing)
2477     return (font->spacing == MFONT_SPACING_UNDECIDED ? Mnil
2478             : msymbol (font->spacing == MFONT_SPACING_PROPORTIONAL ? "p"
2479                        : font->spacing == MFONT_SPACING_MONO ? "m" : "c"));
2480   if (rfont)
2481     {
2482       if (key == Mfont_ascent)
2483         return (void *) rfont->ascent;
2484       if (key == Mfont_descent)
2485         return (void *) rfont->descent;
2486       if (key == Mmax_advance)
2487         return (void *) rfont->max_advance;
2488     }
2489   MERROR (MERROR_FONT, NULL);
2490 }
2491
2492
2493 /*=*/
2494 /***en
2495     @brief Put a property value to a font.
2496
2497     The mfont_put_prop () function puts a font property whose key is
2498     $KEY and value is $VAL to font $FONT.  $KEY must be one of the
2499     following symbols:
2500
2501         @c Mfoundry, @c Mfamily, @c Mweight, @c Mstyle, @c Mstretch,
2502         @c Madstyle, @c Mregistry, @c Msize, @c Mresolution.
2503
2504     If $KEY is @c Msize or @c Mresolution, $VAL must be an integer.
2505     Otherwise, $VAL must be a symbol of a property value name.  But,
2506     if the name is "nil", a symbol of name "Nil" must be
2507     specified.  */
2508  /***ja
2509     @brief ¥Õ¥©¥ó¥È¤Î¥×¥í¥Ñ¥Æ¥£¤ËÃͤòÀßÄꤹ¤ë.
2510
2511     ´Ø¿ô mfont_put_prop () ¤Ï¡¢¥Õ¥©¥ó¥È $FONT ¤Î¥­¡¼¤¬$KEY ¤Ç¤¢¤ë¥×¥í¥Ñ
2512     ¥Æ¥£¤ÎÃͤò $VAL ¤ËÀßÄꤹ¤ë¡£$KEY ¤Ï°Ê²¼¤Î¥·¥ó¥Ü¥ë¤Î¤¤¤º¤ì¤«¤Ç¤¢¤ë¡£
2513
2514         @c Mfoundry, @c Mfamily, @c Mweight, @c Mstyle, @c Mstretch,
2515         @c Madstyle, @c Mregistry, @c Msize, @c Mresolution.
2516
2517     $KEY ¤¬ @c Msize ¤« @c Mresolution ¤Ç¤¢¤ì¤Ð $VAL ¤ÏÀ°¿ôÃͤǤʤ¯¤Æ¤Ï
2518     ¤é¤Ê¤¤¡£¤½¤ì°Ê³°¤Î¾ì¹ç¡¢$VAL ¤Ï¥×¥í¥Ñ¥Æ¥£ÃͤÎ̾Á°¤Î¥·¥ó¥Ü¥ë¤Ç¤Ê¤¯¤Æ
2519     ¤Ï¤Ê¤é¤Ê¤¤¡£¤¿¤À¤·¤â¤·¤½¤Î̾Á°¤¬ "nil" ¤Î¾ì¹ç¤Ï¡¢Ì¾Á°¤¬ "Nil" ¤Î¥·
2520     ¥ó¥Ü¥ë¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£*/
2521
2522 int
2523 mfont_put_prop (MFont *font, MSymbol key, void *val)
2524 {
2525   if (key == Mfoundry)
2526     mfont__set_property (font, MFONT_FOUNDRY, (MSymbol) val);
2527   else if (key == Mfamily)
2528     mfont__set_property (font, MFONT_FAMILY, (MSymbol) val);
2529   else if (key == Mweight)
2530     mfont__set_property (font, MFONT_WEIGHT, (MSymbol) val);
2531   else if (key == Mstyle)
2532     mfont__set_property (font, MFONT_STYLE, (MSymbol) val);
2533   else if (key == Mstretch)
2534     mfont__set_property (font, MFONT_STRETCH, (MSymbol) val);
2535   else if (key == Madstyle)
2536     mfont__set_property (font, MFONT_ADSTYLE, (MSymbol) val);
2537   else if (key == Mregistry)
2538     mfont__set_property (font, MFONT_REGISTRY, (MSymbol) val);
2539   else if (key == Msize)
2540     {
2541       int size = (int) val;
2542       font->size = size;
2543     }
2544   else if (key == Mresolution)
2545     {
2546       unsigned resy = (unsigned) val;
2547       font->property[MFONT_RESY] = resy;
2548     }
2549   else if (key == Mlanguage || key == Mscript || key == Motf)
2550     {
2551       font->capability = merge_capability (font->capability,
2552                                            key, (MSymbol) val, 1);
2553     }
2554   else if (key == Mfontfile)
2555     {
2556       font->file = (MSymbol) val;
2557     }
2558   else
2559     MERROR (MERROR_FONT, -1);
2560   return 0;
2561 }
2562
2563 /*=*/
2564
2565 /***en
2566     @brief Return the font selection priority.
2567
2568     The mfont_selection_priority () function returns a newly created
2569     array of six symbols.  The elements are the following
2570     keys of font properties ordered by priority.
2571
2572         @c Mfamily, @c Mweight, @c Mstyle, @c Mstretch,
2573         @c Madstyle, @c Msize.
2574
2575    The m17n library selects the best matching font according to the
2576    order of this array.  A font that has a different value for a
2577    property of lower priority is preferred to a font that has a
2578    different value for a property of higher priority.  */
2579 /***ja
2580     @brief ¥Õ¥©¥ó¥ÈÁªÂò¤ÎÍ¥ÀèÅÙ¤òÊÖ¤¹.
2581
2582     ´Ø¿ô mfont_selection_priority () ¤Ï 6 ¤Ä¤Î¥·¥ó¥Ü¥ë¤«¤é¤Ê¤ëÇÛÎó¤òºî¤Ã¤ÆÊÖ¤¹¡£
2583     ÇÛÎó¤ÎÍ×ÁǤϡ¢°Ê²¼¤Î¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼¤òÍ¥ÀèÅÙ½ç¤Ëʤ٤¿¤â¤Î¤Ç¤¢¤ë¡£
2584
2585         @c Mfamily, @c Mweight, @c Mstyle, @c Mstretch,
2586         @c Madstyle, @c Msize.
2587
2588    m17n ¥é¥¤¥Ö¥é¥ê¤Ï¤³¤ÎÇÛÎó¤Ë½¾¤Ã¤Æ¡¢ºÇ¤â¹çÃפ¹¤ë¥Õ¥©¥ó¥È¤òÁªÂò¤¹¤ë¡£
2589    ÌÜŪ¤Î¥Õ¥©¥ó¥È¤È¡¢¤½¤ì¤¾¤ì°ã¤¦¥×¥í¥Ñ¥Æ¥£¤ÎÃͤ¬¹çÃפ·¤Ê¤¤¥Õ¥©¥ó¥È¤¬¤¢¤Ã¤¿¾ì¹ç¡¢Í¥ÀèÅÙ¤ÎÄ㤤¥×¥í¥Ñ¥Æ¥£¤ÎÃͤ¬¹çÃפ·¤Ê¤¤¥Õ¥©¥ó¥È¡ÊÍ¥ÀèÅ٤ι⤤¥×¥í¥Ñ¥Æ¥£¤ÎÃͤ¬¹çÃפ·¤Æ¤¤¤ë¥Õ¥©¥ó¥È¡Ë¤¬ÁªÂò¤µ¤ì¤ë¡£
2590
2591    */
2592
2593 MSymbol *
2594 mfont_selection_priority ()
2595 {
2596   MSymbol *keys;
2597   int i;
2598
2599   MTABLE_MALLOC (keys, FONT_SCORE_PRIORITY_SIZE, MERROR_FONT);
2600   for (i = 0; i < FONT_SCORE_PRIORITY_SIZE; i++)
2601     {
2602       enum MFontProperty prop = font_score_priority[i];
2603
2604       if (prop == MFONT_SIZE)
2605         keys[i] = Msize;
2606       else if (prop == MFONT_ADSTYLE)
2607         keys[i] = Madstyle;
2608       else if (prop == MFONT_FAMILY)
2609         keys[i] = Mfamily;
2610       else if (prop == MFONT_WEIGHT)
2611         keys[i] = Mweight;
2612       else if (prop == MFONT_STYLE)
2613         keys[i] = Mstyle;
2614       else if (prop == MFONT_STRETCH)
2615         keys[i] = Mstretch;
2616       else
2617         keys[i] = Mfoundry;
2618     }
2619   return keys;
2620 }
2621
2622 /*=*/
2623
2624 /***en
2625     @brief Set the font selection priority.
2626
2627     The mfont_set_selection_priority () function sets font selection
2628     priority according to $KEYS, which is an array of six symbols.
2629     Each element must be one of the below.  No two elements must be
2630     the same.
2631
2632         @c Mfamily, @c Mweight, @c Mstyle, @c Mstretch,
2633         @c Madstyle, @c Msize.
2634
2635     See the documentation of the function mfont_selection_priority ()
2636     for details.  */
2637 /***ja
2638     @brief ¥Õ¥©¥ó¥ÈÁªÂòÍ¥ÀèÅÙ¤òÀßÄꤹ¤ë.
2639
2640     ´Ø¿ô mfont_set_selection_priority () ¤Ï¡¢6¤Ä¤Î¥·¥ó¥Ü¥ë¤ÎÇÛÎó $KEYS 
2641     ¤Ë¤·¤¿¤¬¤Ã¤Æ¥Õ¥©¥ó¥ÈÁªÂòÍ¥ÀèÅÙ¤òÀßÄꤹ¤ë¡£ÇÛÎó¤Ï°Ê²¼¤Î³ÆÍ×ÁǤòŬÀÚ
2642     ¤Ê½çÈÖ¤Çʤ٤¿¤â¤Î¤Ç¤¢¤ë¡£
2643
2644         @c Mfamily, @c Mweight, @c Mstyle, @c Mstretch,
2645         @c Madstyle, @c Msize.
2646
2647     ¾ÜºÙ¤Ï´Ø¿ô mfont_selection_priority () ¤ÎÀâÌÀ¤ò»²¾È¤Î¤³¤È¡£
2648      */
2649
2650 int
2651 mfont_set_selection_priority (MSymbol *keys)
2652 {
2653   int priority[FONT_SCORE_PRIORITY_SIZE];
2654   int i, j, shift;
2655
2656   for (i = 0; i < FONT_SCORE_PRIORITY_SIZE; i++, keys++)
2657     {
2658       enum MFontProperty prop;
2659
2660       if (*keys == Msize)
2661         prop = MFONT_SIZE;
2662       else if (*keys == Madstyle)
2663         prop = MFONT_ADSTYLE;
2664       else if (*keys == Mfamily)
2665         prop = MFONT_FAMILY;
2666       else if (*keys == Mweight)
2667         prop = MFONT_WEIGHT;
2668       else if (*keys == Mstyle)
2669         prop = MFONT_STYLE;
2670       else if (*keys == Mstretch)
2671         prop = MFONT_STRETCH;
2672       else if (*keys == Mfoundry)
2673         prop = MFONT_FOUNDRY;
2674       else
2675         /* Invalid element.  */
2676         return -1;
2677       for (j = 0; j < i; j++)
2678         if (priority[j] == prop)
2679           /* Duplicated element.  */
2680           return -1;
2681       priority[i] = prop;
2682     }
2683   for (i = 0; i < FONT_SCORE_PRIORITY_SIZE; i++)
2684     font_score_priority[i] = priority[i];
2685   /* Here, SHIFT starts from 1, not 0.  This is because the lowest bit
2686      of a score is a flag for a scalable font (see the documentation
2687      of font_score).  */
2688   i = FONT_SCORE_PRIORITY_SIZE - 1;
2689   for (shift = 1; i >= 0; i--)
2690     {
2691       font_score_shift_bits[font_score_priority[i]] = shift;
2692       if (font_score_priority[i] == MFONT_SIZE)
2693         shift += 16;
2694       else if (font_score_priority[i] <= MFONT_FAMILY)
2695         shift++;
2696       else
2697         shift += 2;
2698     }
2699   return 0;
2700 }
2701
2702 /*=*/
2703
2704 /***en
2705     @brief Find a font.
2706
2707     The mfont_find () function returns a pointer to the available font
2708     that matches best the specification $SPEC on frame $FRAME.
2709
2710     $SCORE, if not NULL, must point to a place to store the score
2711     value that indicates how well the found font matches to $SPEC.  The
2712     smaller score means a better match.  */
2713 /***ja
2714     @brief ¥Õ¥©¥ó¥È¤òõ¤¹.
2715
2716     ´Ø¿ô mfont_find () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¾å¤Ç¥Õ¥©¥ó¥ÈÄêµÁ $SPEC 
2717     ¤Ë¤â¤Ã¤È¤â¹çÃפ¹¤ëÍøÍѲÄǽ¤Ê¥Õ¥©¥ó¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£  
2718
2719     $SCORE ¤Ï NULL ¤Ç¤¢¤ë¤«¡¢¸«¤Ä¤«¤Ã¤¿¥Õ¥©¥ó¥È¤¬ $SPEC 
2720     ¤Ë¤É¤ì¤Û¤É¹ç¤Ã¤Æ¤¤¤ë¤«¤ò¼¨¤¹¥¹¥³¥¢¤òÊݸ¤¹¤ë¾ì½ê¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ë¡£
2721     ¥¹¥³¥¢¤¬¾®¤µ¤¤¤Û¤ÉÎɤ¯¹ç¤Ã¤Æ¤¤¤ë¤³¤È¤ò°ÕÌ£¤¹¤ë¡£
2722     */
2723
2724 MFont *
2725 mfont_find (MFrame *frame, MFont *spec, int *score, int max_size)
2726 {
2727   MFont spec_copy;
2728   MFont *best;
2729   MFontList *list;
2730   MRealizedFont *rfont;
2731   MFont adjusted;
2732
2733   if (spec->size < 0)
2734     {
2735       double pt = - spec->size;
2736
2737       adjusted = *spec;
2738       adjusted.size = pt * frame->dpi / 72.27 + 0.5;
2739       spec = &adjusted;
2740     }
2741   MFONT_INIT (&spec_copy);
2742   spec_copy.property[MFONT_FAMILY] = spec->property[MFONT_FAMILY];
2743   spec_copy.property[MFONT_REGISTRY] = spec->property[MFONT_REGISTRY];
2744   spec_copy.capability = spec->capability;
2745   spec_copy.file = spec->file;
2746
2747   list = mfont__list (frame, &spec_copy, spec, max_size);
2748   if (! list)
2749     return NULL;
2750
2751   best = list->fonts[0].font;
2752   if (score)
2753     *score = list->fonts[0].score;
2754   free (list->fonts);
2755   free (list);
2756   spec_copy = *best;
2757   mfont__merge (&spec_copy, spec, 0);
2758   rfont = mfont__open (frame, best, spec);
2759   if (! rfont)
2760     return NULL;
2761   return (MFont *) rfont;
2762 }
2763
2764 /*=*/
2765 /***en
2766     @brief Set encoding of a font.
2767
2768     The mfont_set_encoding () function sets the encoding information
2769     of font $FONT.
2770
2771     $ENCODING_NAME is a symbol representing a charset that has the
2772     same encoding as the font.
2773
2774     $REPERTORY_NAME is @c Mnil or a symbol representing a charset that
2775     has the same repertory as the font.  If it is @c Mnil, whether a
2776     specific character is supported by the font is asked to each font
2777     driver.
2778
2779     @return
2780     If the operation was successful, this function returns 0.
2781     Otherwise it returns -1 and assigns an error code to the external
2782     variable #merror_code.  */
2783 /***ja
2784     @brief ¥Õ¥©¥ó¥È¤Î¥¨¥ó¥³¡¼¥Ç¥£¥ó¥°¤òÀßÄꤹ¤ë.
2785
2786     ´Ø¿ô mfont_set_encoding () ¤Ï¥Õ¥©¥ó¥È $FONT ¤Î¥¨¥ó¥³¡¼¥Ç¥£¥ó¥°¾ðÊó¤òÀßÄꤹ¤ë¡£
2787
2788     $ENCODING_NAME ¤Ï¥Õ¥©¥ó¥È¤ÈƱ¤¸¥¨¥ó¥³¡¼¥Ç¥£¥ó¥°¤ò»ý¤Äʸ»ú¥»¥Ã¥È¤ò¼¨¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£
2789
2790     $REPERTORY_NAME ¤Ï @c Mnil ¤Ç¤¢¤ë¤«¡¢¥Õ¥©¥ó¥È¤ÈƱ¤¸¥¨¥ó¥³¡¼¥Ç¥£¥ó¥°¤ò»ý¤Äʸ»ú¥»¥Ã¥È¤ò¼¨¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£
2791     @c Mnil ¤Ç¤¢¤ì¤Ð¡¢¸Ä¡¹¤Îʸ»ú¤¬¤½¤Î¥Õ¥©¥ó¥È¤Ç¥µ¥Ý¡¼¥È¤µ¤ì¤Æ¤¤¤ë¤«¤É¤¦¤«¤Ï¡¢³Æ¡¹¤Î¥Õ¥©¥ó¥È¥É¥é¥¤¥Ð¤ËÌ䤤¹ç¤ï¤»¤ë¡£
2792
2793     @return
2794     ½èÍý¤¬À®¸ù¤¹¤ì¤Ð¤³¤Î´Ø¿ô¤Ï 0 ¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô
2795     #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£  */
2796
2797
2798 int
2799 mfont_set_encoding (MFont *font, MSymbol encoding_name, MSymbol repertory_name)
2800 {
2801   MCharset *encoding_charset = MCHARSET (encoding_name);
2802   MCharset *repertory_charset;
2803   MSymbol registry;
2804   MFontEncoding *encoding;
2805   MPlist *plist;
2806
2807   if (! encoding_charset)
2808     MERROR (MERROR_FONT, -1);
2809   if (repertory_name != Mnil)
2810     {
2811       repertory_charset = MCHARSET (repertory_name);
2812       if (! repertory_charset)
2813         MERROR (MERROR_FONT, -1);
2814     }
2815   else
2816     repertory_charset = NULL;
2817
2818   MSTRUCT_CALLOC (encoding, MERROR_FONT);
2819   encoding->spec = *font;
2820   encoding->encoding_name = encoding_name;
2821   encoding->encoding_charset = encoding_charset;
2822   encoding->repertory_name = repertory_name;
2823   encoding->repertory_charset = repertory_charset;
2824   registry = FONT_PROPERTY (font, MFONT_REGISTRY);
2825   if (registry == Mnil)
2826     registry = Mt;
2827   if (! font_encoding_list)
2828     load_font_encoding_table ();
2829   mplist_push (font_encoding_list, registry, encoding);
2830   MPLIST_DO (plist, MPLIST_NEXT (font_encoding_list))
2831     if (! memcmp (font, &((MFontEncoding *) MPLIST_VAL (plist))->spec,
2832                   sizeof (MFont)))
2833       {
2834         mplist_pop (plist);
2835         break;
2836       }
2837   return 0;
2838 }
2839
2840 /*=*/
2841
2842 /***en
2843     @brief Create a fontname from a font.
2844
2845     This function is obsolete.   Use mfont_unparse_name instead. */
2846 /***ja
2847     @brief ¥Õ¥©¥ó¥È̾¤«¤é¥Õ¥©¥ó¥È¤òºî¤ë.
2848
2849     ¤³¤Î´Ø¿ô¤ÏÇÑ»ßͽÄê¤Ç¤¢¤ë¡£ mfont_unparse_name () ¤ò»ÈÍѤΤ³¤È¡£ */
2850
2851 char *
2852 mfont_name (MFont *font)
2853 {
2854   return mfont_unparse_name (font, Mx);
2855 }
2856
2857 /*=*/
2858
2859 /***en
2860     @brief Create a new font from fontname.
2861
2862     This function is obsolete.  Use mfont_parse_name () instead.  */
2863
2864 /***ja
2865     @brief ¥Õ¥©¥ó¥È¤«¤é¥Õ¥©¥ó¥È̾¤òºî¤ë.
2866
2867     ¤³¤ì¤Ï´Ø¿ô¤ÏÇÑ»ßͽÄê¤Ç¤¢¤ë¡£ mfont_parse_name () ¤ò»ÈÍѤΤ³¤È¡£  */
2868
2869 MFont *
2870 mfont_from_name (const char *name)
2871 {
2872   return mfont_parse_name (name, Mx);
2873 }
2874
2875 /*=*/
2876
2877 /***en
2878     @brief Get resize information of a font.
2879
2880     The mfont_resize_ratio () function lookups the m17n database
2881     \<font, reisize\> and returns a resizing ratio (in percentage) of
2882     FONT.  For instance, if the return value is 150, that means that
2883     the m17n library uses an 1.5 time bigger font than a specified
2884     size.  */
2885
2886 /***ja
2887     @brief ¥Õ¥©¥ó¥È¤Î¥ê¥µ¥¤¥º¾ðÊó¤òÆÀ¤ë
2888
2889     ´Ø¿ô mfont_resize_ratio ¤Ï m17n ¥Ç¡¼¥¿¥Ù¡¼¥¹ \<font, reisize\> 
2890     ¤ò¸¡º÷¤·¡¢¥Õ¥©¥ó¥È FONT ¤Î¥ê¥µ¥¤¥º¤ÎÈæΨ¡Ê¥Ñ¡¼¥»¥ó¥Æ¡¼¥¸¡Ë
2891     ¤òÊÖ¤¹¡£¤¿¤È¤¨¤ÐÊÖ¤¹Ãͤ¬ 150 ¤Ç¤¢¤ì¤Ð¡¢m17n ¥é¥¤¥Ö¥é¥ê¤Ï»ØÄꤵ¤ì¤¿¥µ¥¤¥º¤Î 1.5 
2892     ÇܤΥե©¥ó¥È¤ò»ÈÍѤ¹¤ë¤³¤È¤ò°ÕÌ£¤¹¤ë¡£ */
2893
2894 int
2895 mfont_resize_ratio (MFont *font)
2896 {
2897   MSymbol registry = FONT_PROPERTY (font, MFONT_REGISTRY);
2898   MFontResize *resize;
2899   MPlist *plist;
2900
2901   if (! font_resize_list)
2902     load_font_resize_table ();
2903   if (! MPLIST_TAIL_P (font_resize_list))
2904     while (1)
2905       {
2906         plist = font_resize_list;
2907         while (registry ? (plist = mplist_find_by_key (plist, registry))
2908                : plist)
2909           {
2910             resize = (MFontResize *) MPLIST_VAL (plist);
2911             if (mfont__match_p (font, &resize->spec, MFONT_ADSTYLE))
2912               return resize->resize;
2913             plist = MPLIST_NEXT (plist);
2914           }
2915         if (registry == Mt)
2916           break;
2917         registry = Mt;
2918       }
2919   return 100;
2920 }
2921
2922 /*=*/
2923
2924 /***en
2925     @brief Get a list of fonts.
2926
2927     The mfont_list () functions returns a list of fonts available on
2928     frame $FRAME.  $FONT, if not NULL, limits fonts to ones
2929     that match with $FONT.  $LANGUAGE, if not @c Mnil, limits fonts to
2930     ones that support $LANGUAGE.  $MAXNUM, if greater than 0, limits
2931     the number of fonts.
2932
2933     $LANGUAGE argument exists just for backward compatibility, and the
2934     use is deprecated.  Use #Mlanguage font property instead.  If
2935     $FONT already has #Mlanguage property, $LANGUAGE is ignored.
2936
2937     @return
2938     This function returns a plist whose keys are family names and
2939     values are pointers to the object MFont.  The plist must be freed
2940     by m17n_object_unref ().  If no font is found, it returns
2941     NULL.  */
2942
2943 /***ja
2944     @brief ¥Õ¥©¥ó¥È¤Î¥ê¥¹¥È¤òÆÀ¤ë
2945
2946     ´Ø¿ô mfont_list () ¤Ï¥Õ¥ì¡¼¥à $FRAME ¤ÇÍøÍѲÄǽ¤Ê¥Õ¥©¥ó¥È¤Î¥ê¥¹¥È¤ò
2947     ÊÖ¤¹¡£$FONT ¤¬ NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢$FONT ¤È¹çÃפ¹¤ëÍøÍѲÄǽ¤Ê¥Õ¥©¥ó¥È
2948     ¤Î¥ê¥¹¥È¤òÊÖ¤¹¡£$LANGUAGE ¤¬ @c Mnil ¤Ç¤Ê¤±¤ì¤Ð¡¢$LANGUAGE ¤ò¥µ¥Ý¡¼
2949     ¥È¤¹¤ëÍøÍѲÄǽ¤Ê¥Õ¥©¥ó¥È¤Î¥ê¥¹¥È¤òÊÖ¤¹¡£$MAXNUM ¤Ï¡¢0 ¤è¤êÂ礭¤¤¾ì
2950     ¹ç¤Ë¤Ï¡¢ÊÖ¤¹¥Õ¥©¥ó¥È¤Î¿ô¤Î¾å¸Â¤Ç¤¢¤ë¡£
2951
2952     ¤¿¤À¤·¡¢°ú¿ô $LANGUAGE ¤ÏµìÈǤȤÎÀ°¹çÀ­¤Î¤¿¤á¤À¤±¤Ë¤¢¤ê¡¢¤½¤Î»ÈÍѤÏ
2953     ´«¤á¤é¤ì¤Ê¤¤¡£¥Õ¥©¥ó¥È¤Î #Mlanguage ¥×¥í¥Ñ¥Æ¥£¤ò»È¤¦¤Ù¤­¤Ç¤¢¤ë¡£¤â
2954     ¤· $FONT ¤¬¤¹¤Ç¤Ë¤³¤Î¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ã¤Æ¤¤¤¿¤é¡¢°ú¿ô $LANGUAGE ¤Ï̵
2955
2956
2957     @return 
2958     ¤³¤Î´Ø¿ô¤Ï¥­¡¼¤¬¥Õ¥©¥ó¥È¥Õ¥¡¥ß¥ê̾¤Ç¤¢¤êÃͤ¬ MFont ¥ª¥Ö¥¸¥§¥¯¥È¤Ø¤Î
2959     ¥Ý¥¤¥ó¥¿¤Ç¤¢¤ë¤è¤¦¤Êplist ¤òÊÖ¤¹¡£plist ¤Ï m17n_object_unref () ¤Ç
2960     ²òÊü¤¹¤ëɬÍפ¬¤¢¤ë¡£¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤é¤Ê¤±¤ì¤ÐNULL ¤òÊÖ¤¹¡£  */
2961
2962 MPlist *
2963 mfont_list (MFrame *frame, MFont *font, MSymbol language, int maxnum)
2964 {
2965   MPlist *plist, *pl;
2966   MFontList *font_list;
2967   int i;
2968   MFont spec;
2969   
2970   if (font)
2971     spec = *font;
2972   else
2973     MFONT_INIT (&spec);
2974
2975   if (spec.size < 0)
2976     {
2977       double pt = - spec.size;
2978
2979       spec.size = pt * frame->dpi / 72.27 + 0.5;
2980     }
2981
2982   if (language != Mnil)
2983     spec.capability = merge_capability (spec.capability, Mlanguage, language,
2984                                         0);
2985
2986   font_list = mfont__list (frame, &spec, &spec, 0);
2987   if (! font_list)
2988     return NULL;
2989   if (font_list->nfonts == 0)
2990     {
2991       free (font_list);
2992       return NULL;
2993     }
2994
2995   plist = pl = mplist ();
2996   for (i = 0; i < font_list->nfonts; i++)
2997     {
2998       MSymbol family = FONT_PROPERTY (font_list->fonts[i].font, MFONT_FAMILY);
2999
3000       if (family != Mnil)
3001         pl = mplist_add (pl, family, font_list->fonts[i].font);
3002     }
3003   free (font_list);
3004   return plist;
3005 }
3006
3007 /***en
3008     @brief Get a list of font famiy names.
3009
3010     The mfont_list_family_names () functions returns a list of font
3011     family names available on frame $FRAME.
3012
3013     @return
3014
3015     This function returns a plist whose keys are #Msymbol and values
3016     are symbols representing font family names.  The elements are
3017     sorted by alphabetical order.  The plist must be freed by
3018     m17n_object_unref ().  If not font is found, it returns NULL.  */
3019
3020 MPlist *
3021 mfont_list_family_names (MFrame *frame)
3022 {
3023   MPlist *plist = mplist (), *p;
3024
3025   MPLIST_DO (p, frame->font_driver_list)
3026     {
3027       MFontDriver *driver = MPLIST_VAL (p);
3028
3029       (driver->list_family_names) (frame, plist);
3030     }
3031   return plist;
3032 }
3033
3034
3035 /*=*/
3036
3037 /***en
3038     @brief Check the usability of a font.
3039
3040     The mfont_check () function checkes if $FONT can be used for
3041     $SCRIPT and $LANGUAGE in $FONTSET on $FRAME.
3042
3043     @return If the font is usable, return 1.  Otherwise return 0.
3044  */
3045
3046 int
3047 mfont_check (MFrame *frame, MFontset *fontset,
3048              MSymbol script, MSymbol language, MFont *font)
3049 {
3050   MRealizedFont *rfont;
3051   int best, score;
3052
3053   if (! fontset)
3054     fontset = frame->face->property[MFACE_FONTSET];
3055   rfont = mfontset__get_font (frame, fontset, script, language, font, &best);
3056   if (! rfont || ! best)
3057     return 0;
3058   score = font_score (&rfont->spec, font);
3059   return (score == 0 ? 2 : 1);
3060 }
3061
3062 /*=*/
3063
3064 /***en
3065     @brief Check is a font matches with a font spec.
3066
3067     The mfont_match_p () function checks if $FONT matches with the
3068     font-spec $SPEC.
3069
3070     @return 
3071     If the font matches, 1 is returned.  Otherwise 0 is returned.  */
3072
3073 int
3074 mfont_match_p (MFont *font, MFont *spec)
3075 {
3076   return mfont__match_p (font, spec, MFONT_REGISTRY);
3077 }
3078
3079 /*=*/
3080 /***en
3081     @brief Open a font.
3082
3083     The mfont_open () function opens $FONT on $FRAME, and returns a
3084     realized font.
3085
3086     @return
3087     If the font was successfully opened, a realized font is returned.
3088     Otherwize NULL is returned.
3089
3090     @seealso
3091     mfont_close ().  */
3092
3093
3094 MFont *
3095 mfont_open (MFrame *frame, MFont *font)
3096 {
3097   enum MFontType font_type = font->type;
3098
3099   if (font_type == MFONT_TYPE_SPEC)
3100     return mfont_find (frame, font, NULL, 0);
3101   if (font_type == MFONT_TYPE_OBJECT)
3102     return (MFont *) mfont__open (frame, font, font);
3103   if (font_type == MFONT_TYPE_REALIZED)
3104     return font;
3105   MERROR (MERROR_FONT, NULL);
3106 }
3107
3108 /*=*/
3109 /***en
3110     @brief Encapusulate a font.
3111
3112     The mfont_encapsulate () functions realizes a font by
3113     encapusulating data $DATA or type $DATA_TYPE on #FRAME.  Currently
3114     $DATA_TAPE is #Mfontconfig or #Mfreetype, and $DATA points to an
3115     object of FcPattern or FT_Face respectively.
3116
3117     @return
3118     If the operation was successful, a realized font is returned.
3119     Otherwise NULL is return.
3120
3121     @seealso
3122     mfont_close ().  */
3123
3124
3125 MFont *
3126 mfont_encapsulate (MFrame *frame, MSymbol data_type, void *data)
3127 {
3128   MPlist *p;
3129
3130   MPLIST_DO (p, frame->font_driver_list)
3131     {
3132       MFontDriver *driver = MPLIST_VAL (p);
3133       MRealizedFont *rfont;
3134
3135       if (driver->encapsulate
3136           && (rfont = driver->encapsulate (frame, data_type, data)))
3137         return (MFont *) rfont;
3138     }
3139
3140   return NULL;
3141 }
3142
3143 /*=*/
3144 /***en
3145     @brief Close a font.
3146
3147     The mfont_close () function close a realized font $FONT.  $FONT
3148     must be opened previously by mfont_open () or mfont_encapsulate
3149     ().
3150
3151     @return
3152     If the operation was successful, 0 is returned.  Otherwise, -1 is
3153     returned.
3154
3155     @seealso
3156     mfont_open (), mfont_encapsulate ().  */
3157
3158 int
3159 mfont_close (MFont *font)
3160 {
3161   enum MFontType font_type = font->type;
3162   MRealizedFont *rfont;
3163
3164   if (font_type != MFONT_TYPE_REALIZED)
3165     MERROR (MERROR_FONT, -1);
3166   rfont = (MRealizedFont *) font;
3167   if (rfont->encapsulating
3168       && rfont->driver->close)
3169     rfont->driver->close (rfont);
3170   return 0;
3171 }
3172
3173 /*** @} */
3174
3175 /*** @addtogroup m17nDebug */
3176 /*=*/
3177 /*** @{ */
3178
3179 /***en
3180     @brief Dump a font.
3181
3182     The mdebug_dump_font () function prints font $FONT in a human readable
3183     way to the stderr.
3184
3185     @return
3186     This function returns $FONT.  */
3187 /***ja
3188     @brief ¥Õ¥©¥ó¥È¤ò¥À¥ó¥×¤¹¤ë.
3189
3190     ´Ø¿ô mdebug_dump_font () ¤Ï¥Õ¥©¥ó¥È $FONT ¤ò stderr 
3191     ¤Ë¿Í´Ö¤Ë²ÄÆɤʷÁ¤Ç°õºþ¤¹¤ë¡£
3192
3193     @return
3194     ¤³¤Î´Ø¿ô¤Ï $FONT ¤òÊÖ¤¹¡£  */
3195
3196 MFont *
3197 mdebug_dump_font (MFont *font)
3198 {
3199   char *name;
3200   
3201   name = xlfd_unparse_name (font, 0);
3202   if (name)
3203     {
3204       fprintf (stderr, "%s", name);
3205       free (name);
3206     }
3207   if (font->file != Mnil)
3208     {
3209       char *file = MSYMBOL_NAME (font->file);
3210       char *lastslash = file, *p;
3211
3212       for (p = file; *p; p++)
3213         if (*p == '/')
3214           lastslash = p;
3215       if (name)
3216         fprintf (stderr, ",");
3217       fprintf (stderr, "%s", lastslash + 1);
3218     }
3219   if (font->capability != Mnil)
3220     fprintf (stderr, "%s", MSYMBOL_NAME (font->capability));
3221   return font;
3222 }
3223
3224 /*** @} */
3225
3226 /*
3227   Local Variables:
3228   coding: euc-japan
3229   End:
3230 */