(ft_open, ft_encapsulate): Set rfont->id.
[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 notation "xxx property of F" means the font property that
39     belongs to font F and whose key is @c Mxxx.
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>"foundry"</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         @b Mfont_ascent, @b Mfont_descent, #Mmax_advance.
2399
2400     @return 
2401     If $KEY is @c Mfoundry, @c Mfamily, @c Mweight, @c Mstyle,
2402     @c Mstretch, @c Madstyle, @c Mregistry, or @c Mspacing, this
2403     function returns the corresponding value as a symbol.  If the font
2404     does not have $KEY property, it returns @c Mnil.  If $KEY is @c
2405     Msize, @c Mresolution, @b Mfont_ascent, Mfont_descent, or
2406     #Mmax_advance, this function returns the corresponding value as an
2407     integer.  If the font does not have $KEY property, it returns 0.
2408     If $KEY is something else, it returns @c NULL and assigns an error
2409     code to the external variable #merror_code.  */
2410  
2411 /***ja
2412     @brief ¥Õ¥©¥ó¥È¤Î¥×¥í¥Ñ¥Æ¥£¤ÎÃͤòÆÀ¤ë.
2413
2414     ´Ø¿ô mfont_get_prop () ¤Ï¥Õ¥©¥ó¥È $FONT ¤Î¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥­¡¼¤¬
2415     $KEY ¤Ç¤¢¤ë¤â¤Î¤ÎÃͤòÊÖ¤¹¡£$KEY ¤Ï°Ê²¼¤Î¥·¥ó¥Ü¥ë¤Î¤¤¤º¤ì¤«¤Ç¤Ê¤±¤ì
2416     ¤Ð¤Ê¤é¤Ê¤¤¡£
2417
2418         @c Mfoundry, @c Mfamily, @c Mweight, @c Mstyle, @c Mstretch,
2419         @c Madstyle, @c Mregistry, @c Msize, @c Mresolution, @c Mspacing.
2420
2421     @return 
2422     $KEY ¤¬ @c Mfoundry, @c Mfamily, @c Mweight, @c Mstyle, @c
2423     Mstretch, @c Madstyle, @c Mregistry, @c Mspacing ¤Î¤¤¤º¤ì¤«¤Ç¤¢¤ì¤Ð¡¢
2424     ÁêÅö¤¹¤ëÃͤò¥·¥ó¥Ü¥ë¤È¤·¤ÆÊÖ¤¹¡£¥Õ¥©¥ó¥È¤¬¤½¤Î¥×¥í¥Ñ¥Æ¥£¤ò»ý¤¿¤Ê¤¤
2425     ¾ì¹ç¤Ë¤Ï@c Mnil ¤òÊÖ¤¹¡£$KEY ¤¬ @c Msize ¤¢¤ë¤¤¤Ï @c Mresolution ¤Î
2426     ¾ì¹ç¤Ë¤Ï¡¢ÁêÅö¤¹¤ëÃͤò¤ÏÀ°¿ôÃͤȤ·¤ÆÊÖ¤¹¡£¥Õ¥©¥ó¥È¤¬¤½¤Î¥×¥í¥Ñ¥Æ¥£
2427     ¤ò»ý¤¿¤Ê¤¤¾ì¹ç¤Ë¤Ï 0 ¤òÊÖ¤¹¡£$KEY ¤¬¤½¤ì°Ê³°¤Î¤â¤Î¤Ç¤¢¤ì¤Ð¡¢@c
2428     NULL ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£  */
2429
2430 void *
2431 mfont_get_prop (MFont *font, MSymbol key)
2432 {
2433   MRealizedFont *rfont = NULL;
2434
2435   if (font->type == MFONT_TYPE_REALIZED)
2436     rfont = (MRealizedFont *) font;
2437
2438   if (key == Mfoundry)
2439     return (void *) FONT_PROPERTY (font, MFONT_FOUNDRY);
2440   if (key == Mfamily)
2441     return (void *) FONT_PROPERTY (font, MFONT_FAMILY);
2442   if (key == Mweight)
2443     return (void *) FONT_PROPERTY (font, MFONT_WEIGHT);
2444   if (key == Mstyle)
2445     return (void *) FONT_PROPERTY (font, MFONT_STYLE);
2446   if (key == Mstretch)
2447     return (void *) FONT_PROPERTY (font, MFONT_STRETCH);
2448   if (key == Madstyle)
2449     return (void *) FONT_PROPERTY (font, MFONT_ADSTYLE);
2450   if (key == Mregistry)
2451     return (void *) FONT_PROPERTY (font, MFONT_REGISTRY);
2452   if (key == Msize)
2453     {
2454       int size = font->size;
2455       return (void *) size;
2456     }
2457   if (key == Mresolution)
2458     {
2459       int resy = font->property[MFONT_RESY];
2460       return (void *) resy;
2461     }
2462   if (key == Mlanguage || key == Mscript || key == Motf)
2463     {
2464       MFontCapability *cap;
2465
2466       if (! font->capability)
2467         return NULL;
2468       cap = mfont__get_capability (font->capability);
2469       if (key == Mlanguage)
2470         return cap->language;
2471       if (key == Mscript)
2472         return cap->script;
2473       return cap->otf;
2474     }
2475
2476   if (key == Mfontfile)
2477     return (void *) font->file;
2478   if (key == Mspacing)
2479     return (font->spacing == MFONT_SPACING_UNDECIDED ? Mnil
2480             : msymbol (font->spacing == MFONT_SPACING_PROPORTIONAL ? "p"
2481                        : font->spacing == MFONT_SPACING_MONO ? "m" : "c"));
2482   if (rfont)
2483     {
2484       if (key == Mfont_ascent)
2485         return (void *) rfont->ascent;
2486       if (key == Mfont_descent)
2487         return (void *) rfont->descent;
2488       if (key == Mmax_advance)
2489         return (void *) rfont->max_advance;
2490     }
2491   MERROR (MERROR_FONT, NULL);
2492 }
2493
2494
2495 /*=*/
2496 /***en
2497     @brief Put a property value to a font.
2498
2499     The mfont_put_prop () function puts a font property whose key is
2500     $KEY and value is $VAL to font $FONT.  $KEY must be one of the
2501     following symbols:
2502
2503         @c Mfoundry, @c Mfamily, @c Mweight, @c Mstyle, @c Mstretch,
2504         @c Madstyle, @c Mregistry, @c Msize, @c Mresolution.
2505
2506     If $KEY is @c Msize or @c Mresolution, $VAL must be an integer.
2507     Otherwise, $VAL must be a symbol of a property value name.  But,
2508     if the name is "nil", a symbol of name "Nil" must be
2509     specified.  */
2510  /***ja
2511     @brief ¥Õ¥©¥ó¥È¤Î¥×¥í¥Ñ¥Æ¥£¤ËÃͤòÀßÄꤹ¤ë.
2512
2513     ´Ø¿ô mfont_put_prop () ¤Ï¡¢¥Õ¥©¥ó¥È $FONT ¤Î¥­¡¼¤¬$KEY ¤Ç¤¢¤ë¥×¥í¥Ñ
2514     ¥Æ¥£¤ÎÃͤò $VAL ¤ËÀßÄꤹ¤ë¡£$KEY ¤Ï°Ê²¼¤Î¥·¥ó¥Ü¥ë¤Î¤¤¤º¤ì¤«¤Ç¤¢¤ë¡£
2515
2516         @c Mfoundry, @c Mfamily, @c Mweight, @c Mstyle, @c Mstretch,
2517         @c Madstyle, @c Mregistry, @c Msize, @c Mresolution.
2518
2519     $KEY ¤¬ @c Msize ¤« @c Mresolution ¤Ç¤¢¤ì¤Ð $VAL ¤ÏÀ°¿ôÃͤǤʤ¯¤Æ¤Ï
2520     ¤é¤Ê¤¤¡£¤½¤ì°Ê³°¤Î¾ì¹ç¡¢$VAL ¤Ï¥×¥í¥Ñ¥Æ¥£ÃͤÎ̾Á°¤Î¥·¥ó¥Ü¥ë¤Ç¤Ê¤¯¤Æ
2521     ¤Ï¤Ê¤é¤Ê¤¤¡£¤¿¤À¤·¤â¤·¤½¤Î̾Á°¤¬ "nil" ¤Î¾ì¹ç¤Ï¡¢Ì¾Á°¤¬ "Nil" ¤Î¥·
2522     ¥ó¥Ü¥ë¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£*/
2523
2524 int
2525 mfont_put_prop (MFont *font, MSymbol key, void *val)
2526 {
2527   if (key == Mfoundry)
2528     mfont__set_property (font, MFONT_FOUNDRY, (MSymbol) val);
2529   else if (key == Mfamily)
2530     mfont__set_property (font, MFONT_FAMILY, (MSymbol) val);
2531   else if (key == Mweight)
2532     mfont__set_property (font, MFONT_WEIGHT, (MSymbol) val);
2533   else if (key == Mstyle)
2534     mfont__set_property (font, MFONT_STYLE, (MSymbol) val);
2535   else if (key == Mstretch)
2536     mfont__set_property (font, MFONT_STRETCH, (MSymbol) val);
2537   else if (key == Madstyle)
2538     mfont__set_property (font, MFONT_ADSTYLE, (MSymbol) val);
2539   else if (key == Mregistry)
2540     mfont__set_property (font, MFONT_REGISTRY, (MSymbol) val);
2541   else if (key == Msize)
2542     {
2543       int size = (int) val;
2544       font->size = size;
2545     }
2546   else if (key == Mresolution)
2547     {
2548       unsigned resy = (unsigned) val;
2549       font->property[MFONT_RESY] = resy;
2550     }
2551   else if (key == Mlanguage || key == Mscript || key == Motf)
2552     {
2553       font->capability = merge_capability (font->capability,
2554                                            key, (MSymbol) val, 1);
2555     }
2556   else if (key == Mfontfile)
2557     {
2558       font->file = (MSymbol) val;
2559     }
2560   else
2561     MERROR (MERROR_FONT, -1);
2562   return 0;
2563 }
2564
2565 /*=*/
2566
2567 /***en
2568     @brief Return the font selection priority.
2569
2570     The mfont_selection_priority () function returns a newly created
2571     array of six symbols.  The elements are the following
2572     keys of font properties ordered by priority.
2573
2574         @c Mfamily, @c Mweight, @c Mstyle, @c Mstretch,
2575         @c Madstyle, @c Msize.
2576
2577    The m17n library selects the best matching font according to the
2578    order of this array.  A font that has a different value for a
2579    property of lower priority is preferred to a font that has a
2580    different value for a property of higher priority.  */
2581 /***ja
2582     @brief ¥Õ¥©¥ó¥ÈÁªÂò¤ÎÍ¥ÀèÅÙ¤òÊÖ¤¹.
2583
2584     ´Ø¿ô mfont_selection_priority () ¤Ï 6 ¤Ä¤Î¥·¥ó¥Ü¥ë¤«¤é¤Ê¤ëÇÛÎó¤òºî¤Ã¤ÆÊÖ¤¹¡£
2585     ÇÛÎó¤ÎÍ×ÁǤϡ¢°Ê²¼¤Î¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼¤òÍ¥ÀèÅÙ½ç¤Ëʤ٤¿¤â¤Î¤Ç¤¢¤ë¡£
2586
2587         @c Mfamily, @c Mweight, @c Mstyle, @c Mstretch,
2588         @c Madstyle, @c Msize.
2589
2590    m17n ¥é¥¤¥Ö¥é¥ê¤Ï¤³¤ÎÇÛÎó¤Ë½¾¤Ã¤Æ¡¢ºÇ¤â¹çÃפ¹¤ë¥Õ¥©¥ó¥È¤òÁªÂò¤¹¤ë¡£
2591    ÌÜŪ¤Î¥Õ¥©¥ó¥È¤È¡¢¤½¤ì¤¾¤ì°ã¤¦¥×¥í¥Ñ¥Æ¥£¤ÎÃͤ¬¹çÃפ·¤Ê¤¤¥Õ¥©¥ó¥È¤¬¤¢¤Ã¤¿¾ì¹ç¡¢Í¥ÀèÅÙ¤ÎÄ㤤¥×¥í¥Ñ¥Æ¥£¤ÎÃͤ¬¹çÃפ·¤Ê¤¤¥Õ¥©¥ó¥È¡ÊÍ¥ÀèÅ٤ι⤤¥×¥í¥Ñ¥Æ¥£¤ÎÃͤ¬¹çÃפ·¤Æ¤¤¤ë¥Õ¥©¥ó¥È¡Ë¤¬ÁªÂò¤µ¤ì¤ë¡£
2592
2593    */
2594
2595 MSymbol *
2596 mfont_selection_priority ()
2597 {
2598   MSymbol *keys;
2599   int i;
2600
2601   MTABLE_MALLOC (keys, FONT_SCORE_PRIORITY_SIZE, MERROR_FONT);
2602   for (i = 0; i < FONT_SCORE_PRIORITY_SIZE; i++)
2603     {
2604       enum MFontProperty prop = font_score_priority[i];
2605
2606       if (prop == MFONT_SIZE)
2607         keys[i] = Msize;
2608       else if (prop == MFONT_ADSTYLE)
2609         keys[i] = Madstyle;
2610       else if (prop == MFONT_FAMILY)
2611         keys[i] = Mfamily;
2612       else if (prop == MFONT_WEIGHT)
2613         keys[i] = Mweight;
2614       else if (prop == MFONT_STYLE)
2615         keys[i] = Mstyle;
2616       else if (prop == MFONT_STRETCH)
2617         keys[i] = Mstretch;
2618       else
2619         keys[i] = Mfoundry;
2620     }
2621   return keys;
2622 }
2623
2624 /*=*/
2625
2626 /***en
2627     @brief Set the font selection priority.
2628
2629     The mfont_set_selection_priority () function sets font selection
2630     priority according to $KEYS, which is an array of six symbols.
2631     Each element must be one of the below.  No two elements must be
2632     the same.
2633
2634         @c Mfamily, @c Mweight, @c Mstyle, @c Mstretch,
2635         @c Madstyle, @c Msize.
2636
2637     See the documentation of the function mfont_selection_priority ()
2638     for details.  */
2639 /***ja
2640     @brief ¥Õ¥©¥ó¥ÈÁªÂòÍ¥ÀèÅÙ¤òÀßÄꤹ¤ë.
2641
2642     ´Ø¿ô mfont_set_selection_priority () ¤Ï¡¢6¤Ä¤Î¥·¥ó¥Ü¥ë¤ÎÇÛÎó $KEYS 
2643     ¤Ë¤·¤¿¤¬¤Ã¤Æ¥Õ¥©¥ó¥ÈÁªÂòÍ¥ÀèÅÙ¤òÀßÄꤹ¤ë¡£ÇÛÎó¤Ï°Ê²¼¤Î³ÆÍ×ÁǤòŬÀÚ
2644     ¤Ê½çÈÖ¤Çʤ٤¿¤â¤Î¤Ç¤¢¤ë¡£
2645
2646         @c Mfamily, @c Mweight, @c Mstyle, @c Mstretch,
2647         @c Madstyle, @c Msize.
2648
2649     ¾ÜºÙ¤Ï´Ø¿ô mfont_selection_priority () ¤ÎÀâÌÀ¤ò»²¾È¤Î¤³¤È¡£
2650      */
2651
2652 int
2653 mfont_set_selection_priority (MSymbol *keys)
2654 {
2655   int priority[FONT_SCORE_PRIORITY_SIZE];
2656   int i, j, shift;
2657
2658   for (i = 0; i < FONT_SCORE_PRIORITY_SIZE; i++, keys++)
2659     {
2660       enum MFontProperty prop;
2661
2662       if (*keys == Msize)
2663         prop = MFONT_SIZE;
2664       else if (*keys == Madstyle)
2665         prop = MFONT_ADSTYLE;
2666       else if (*keys == Mfamily)
2667         prop = MFONT_FAMILY;
2668       else if (*keys == Mweight)
2669         prop = MFONT_WEIGHT;
2670       else if (*keys == Mstyle)
2671         prop = MFONT_STYLE;
2672       else if (*keys == Mstretch)
2673         prop = MFONT_STRETCH;
2674       else if (*keys == Mfoundry)
2675         prop = MFONT_FOUNDRY;
2676       else
2677         /* Invalid element.  */
2678         return -1;
2679       for (j = 0; j < i; j++)
2680         if (priority[j] == prop)
2681           /* Duplicated element.  */
2682           return -1;
2683       priority[i] = prop;
2684     }
2685   for (i = 0; i < FONT_SCORE_PRIORITY_SIZE; i++)
2686     font_score_priority[i] = priority[i];
2687   /* Here, SHIFT starts from 1, not 0.  This is because the lowest bit
2688      of a score is a flag for a scalable font (see the documentation
2689      of font_score).  */
2690   i = FONT_SCORE_PRIORITY_SIZE - 1;
2691   for (shift = 1; i >= 0; i--)
2692     {
2693       font_score_shift_bits[font_score_priority[i]] = shift;
2694       if (font_score_priority[i] == MFONT_SIZE)
2695         shift += 16;
2696       else if (font_score_priority[i] <= MFONT_FAMILY)
2697         shift++;
2698       else
2699         shift += 2;
2700     }
2701   return 0;
2702 }
2703
2704 /*=*/
2705
2706 /***en
2707     @brief Find a font.
2708
2709     The mfont_find () function returns a pointer to the available font
2710     that matches best the specification $SPEC on frame $FRAME.
2711
2712     $SCORE, if not NULL, must point to a place to store the score
2713     value that indicates how well the found font matches to $SPEC.  The
2714     smaller score means a better match.  */
2715 /***ja
2716     @brief ¥Õ¥©¥ó¥È¤òõ¤¹.
2717
2718     ´Ø¿ô mfont_find () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¾å¤Ç¥Õ¥©¥ó¥ÈÄêµÁ $SPEC 
2719     ¤Ë¤â¤Ã¤È¤â¹çÃפ¹¤ëÍøÍѲÄǽ¤Ê¥Õ¥©¥ó¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£  
2720
2721     $SCORE ¤Ï NULL ¤Ç¤¢¤ë¤«¡¢¸«¤Ä¤«¤Ã¤¿¥Õ¥©¥ó¥È¤¬ $SPEC 
2722     ¤Ë¤É¤ì¤Û¤É¹ç¤Ã¤Æ¤¤¤ë¤«¤ò¼¨¤¹¥¹¥³¥¢¤òÊݸ¤¹¤ë¾ì½ê¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ë¡£
2723     ¥¹¥³¥¢¤¬¾®¤µ¤¤¤Û¤ÉÎɤ¯¹ç¤Ã¤Æ¤¤¤ë¤³¤È¤ò°ÕÌ£¤¹¤ë¡£
2724     */
2725
2726 MFont *
2727 mfont_find (MFrame *frame, MFont *spec, int *score, int max_size)
2728 {
2729   MFont spec_copy;
2730   MFont *best;
2731   MFontList *list;
2732   MRealizedFont *rfont;
2733   MFont adjusted;
2734
2735   if (spec->size < 0)
2736     {
2737       double pt = - spec->size;
2738
2739       adjusted = *spec;
2740       adjusted.size = pt * frame->dpi / 72.27 + 0.5;
2741       spec = &adjusted;
2742     }
2743   MFONT_INIT (&spec_copy);
2744   spec_copy.property[MFONT_FAMILY] = spec->property[MFONT_FAMILY];
2745   spec_copy.property[MFONT_REGISTRY] = spec->property[MFONT_REGISTRY];
2746   spec_copy.capability = spec->capability;
2747   spec_copy.file = spec->file;
2748
2749   list = mfont__list (frame, &spec_copy, spec, max_size);
2750   if (! list)
2751     return NULL;
2752
2753   best = list->fonts[0].font;
2754   if (score)
2755     *score = list->fonts[0].score;
2756   free (list->fonts);
2757   free (list);
2758   spec_copy = *best;
2759   mfont__merge (&spec_copy, spec, 0);
2760   rfont = mfont__open (frame, best, spec);
2761   if (! rfont)
2762     return NULL;
2763   return (MFont *) rfont;
2764 }
2765
2766 /*=*/
2767 /***en
2768     @brief Set encoding of a font.
2769
2770     The mfont_set_encoding () function sets the encoding information
2771     of font $FONT.
2772
2773     $ENCODING_NAME is a symbol representing a charset that has the
2774     same encoding as the font.
2775
2776     $REPERTORY_NAME is @c Mnil or a symbol representing a charset that
2777     has the same repertory as the font.  If it is @c Mnil, whether a
2778     specific character is supported by the font is asked to each font
2779     driver.
2780
2781     @return
2782     If the operation was successful, this function returns 0.
2783     Otherwise it returns -1 and assigns an error code to the external
2784     variable #merror_code.  */
2785 /***ja
2786     @brief ¥Õ¥©¥ó¥È¤Î¥¨¥ó¥³¡¼¥Ç¥£¥ó¥°¤òÀßÄꤹ¤ë.
2787
2788     ´Ø¿ô mfont_set_encoding () ¤Ï¥Õ¥©¥ó¥È $FONT ¤Î¥¨¥ó¥³¡¼¥Ç¥£¥ó¥°¾ðÊó¤òÀßÄꤹ¤ë¡£
2789
2790     $ENCODING_NAME ¤Ï¥Õ¥©¥ó¥È¤ÈƱ¤¸¥¨¥ó¥³¡¼¥Ç¥£¥ó¥°¤ò»ý¤Äʸ»ú¥»¥Ã¥È¤ò¼¨¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£
2791
2792     $REPERTORY_NAME ¤Ï @c Mnil ¤Ç¤¢¤ë¤«¡¢¥Õ¥©¥ó¥È¤ÈƱ¤¸¥¨¥ó¥³¡¼¥Ç¥£¥ó¥°¤ò»ý¤Äʸ»ú¥»¥Ã¥È¤ò¼¨¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£
2793     @c Mnil ¤Ç¤¢¤ì¤Ð¡¢¸Ä¡¹¤Îʸ»ú¤¬¤½¤Î¥Õ¥©¥ó¥È¤Ç¥µ¥Ý¡¼¥È¤µ¤ì¤Æ¤¤¤ë¤«¤É¤¦¤«¤Ï¡¢³Æ¡¹¤Î¥Õ¥©¥ó¥È¥É¥é¥¤¥Ð¤ËÌ䤤¹ç¤ï¤»¤ë¡£
2794
2795     @return
2796     ½èÍý¤¬À®¸ù¤¹¤ì¤Ð¤³¤Î´Ø¿ô¤Ï 0 ¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô
2797     #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£  */
2798
2799
2800 int
2801 mfont_set_encoding (MFont *font, MSymbol encoding_name, MSymbol repertory_name)
2802 {
2803   MCharset *encoding_charset = MCHARSET (encoding_name);
2804   MCharset *repertory_charset;
2805   MSymbol registry;
2806   MFontEncoding *encoding;
2807   MPlist *plist;
2808
2809   if (! encoding_charset)
2810     MERROR (MERROR_FONT, -1);
2811   if (repertory_name != Mnil)
2812     {
2813       repertory_charset = MCHARSET (repertory_name);
2814       if (! repertory_charset)
2815         MERROR (MERROR_FONT, -1);
2816     }
2817   else
2818     repertory_charset = NULL;
2819
2820   MSTRUCT_CALLOC (encoding, MERROR_FONT);
2821   encoding->spec = *font;
2822   encoding->encoding_name = encoding_name;
2823   encoding->encoding_charset = encoding_charset;
2824   encoding->repertory_name = repertory_name;
2825   encoding->repertory_charset = repertory_charset;
2826   registry = FONT_PROPERTY (font, MFONT_REGISTRY);
2827   if (registry == Mnil)
2828     registry = Mt;
2829   if (! font_encoding_list)
2830     load_font_encoding_table ();
2831   mplist_push (font_encoding_list, registry, encoding);
2832   MPLIST_DO (plist, MPLIST_NEXT (font_encoding_list))
2833     if (! memcmp (font, &((MFontEncoding *) MPLIST_VAL (plist))->spec,
2834                   sizeof (MFont)))
2835       {
2836         mplist_pop (plist);
2837         break;
2838       }
2839   return 0;
2840 }
2841
2842 /*=*/
2843
2844 /***en
2845     @brief Create a fontname from a font.
2846
2847     This function is obsolete.   Use mfont_unparse_name instead. */
2848 /***ja
2849     @brief ¥Õ¥©¥ó¥È̾¤«¤é¥Õ¥©¥ó¥È¤òºî¤ë.
2850
2851     ¤³¤Î´Ø¿ô¤ÏÇÑ»ßͽÄê¤Ç¤¢¤ë¡£ mfont_unparse_name () ¤ò»ÈÍѤΤ³¤È¡£ */
2852
2853 char *
2854 mfont_name (MFont *font)
2855 {
2856   return mfont_unparse_name (font, Mx);
2857 }
2858
2859 /*=*/
2860
2861 /***en
2862     @brief Create a new font from fontname.
2863
2864     This function is obsolete.  Use mfont_parse_name () instead.  */
2865
2866 /***ja
2867     @brief ¥Õ¥©¥ó¥È¤«¤é¥Õ¥©¥ó¥È̾¤òºî¤ë.
2868
2869     ¤³¤ì¤Ï´Ø¿ô¤ÏÇÑ»ßͽÄê¤Ç¤¢¤ë¡£ mfont_parse_name () ¤ò»ÈÍѤΤ³¤È¡£  */
2870
2871 MFont *
2872 mfont_from_name (const char *name)
2873 {
2874   return mfont_parse_name (name, Mx);
2875 }
2876
2877 /*=*/
2878
2879 /***en
2880     @brief Get resize information of a font.
2881
2882     The mfont_resize_ratio () function lookups the m17n database
2883     \<font, reisize\> and returns a resizing ratio (in percentage) of
2884     FONT.  For instance, if the return value is 150, that means that
2885     the m17n library uses an 1.5 time bigger font than a specified
2886     size.  */
2887
2888 /***ja
2889     @brief ¥Õ¥©¥ó¥È¤Î¥ê¥µ¥¤¥º¾ðÊó¤òÆÀ¤ë
2890
2891     ´Ø¿ô mfont_resize_ratio ¤Ï m17n ¥Ç¡¼¥¿¥Ù¡¼¥¹ \<font, reisize\> 
2892     ¤ò¸¡º÷¤·¡¢¥Õ¥©¥ó¥È FONT ¤Î¥ê¥µ¥¤¥º¤ÎÈæΨ¡Ê¥Ñ¡¼¥»¥ó¥Æ¡¼¥¸¡Ë
2893     ¤òÊÖ¤¹¡£¤¿¤È¤¨¤ÐÊÖ¤¹Ãͤ¬ 150 ¤Ç¤¢¤ì¤Ð¡¢m17n ¥é¥¤¥Ö¥é¥ê¤Ï»ØÄꤵ¤ì¤¿¥µ¥¤¥º¤Î 1.5 
2894     ÇܤΥե©¥ó¥È¤ò»ÈÍѤ¹¤ë¤³¤È¤ò°ÕÌ£¤¹¤ë¡£ */
2895
2896 int
2897 mfont_resize_ratio (MFont *font)
2898 {
2899   MSymbol registry = FONT_PROPERTY (font, MFONT_REGISTRY);
2900   MFontResize *resize;
2901   MPlist *plist;
2902
2903   if (! font_resize_list)
2904     load_font_resize_table ();
2905   if (! MPLIST_TAIL_P (font_resize_list))
2906     while (1)
2907       {
2908         plist = font_resize_list;
2909         while (registry ? (plist = mplist_find_by_key (plist, registry))
2910                : plist)
2911           {
2912             resize = (MFontResize *) MPLIST_VAL (plist);
2913             if (mfont__match_p (font, &resize->spec, MFONT_ADSTYLE))
2914               return resize->resize;
2915             plist = MPLIST_NEXT (plist);
2916           }
2917         if (registry == Mt)
2918           break;
2919         registry = Mt;
2920       }
2921   return 100;
2922 }
2923
2924 /*=*/
2925
2926 /***en
2927     @brief Get a list of fonts.
2928
2929     The mfont_list () functions returns a list of fonts available on
2930     frame $FRAME.  $FONT, if not NULL, limits fonts to ones
2931     that match with $FONT.  $LANGUAGE, if not @c Mnil, limits fonts to
2932     ones that support $LANGUAGE.  $MAXNUM, if greater than 0, limits
2933     the number of fonts.
2934
2935     $LANGUAGE argument exists just for backward compatibility, and the
2936     use is deprecated.  Use #Mlanguage font property instead.  If
2937     $FONT already has #Mlanguage property, $LANGUAGE is ignored.
2938
2939     @return
2940     This function returns a plist whose keys are family names and
2941     values are pointers to the object MFont.  The plist must be freed
2942     by m17n_object_unref ().  If no font is found, it returns
2943     NULL.  */
2944
2945 /***ja
2946     @brief ¥Õ¥©¥ó¥È¤Î¥ê¥¹¥È¤òÆÀ¤ë
2947
2948     ´Ø¿ô mfont_list () ¤Ï¥Õ¥ì¡¼¥à $FRAME ¤ÇÍøÍѲÄǽ¤Ê¥Õ¥©¥ó¥È¤Î¥ê¥¹¥È¤ò
2949     ÊÖ¤¹¡£$FONT ¤¬ NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢$FONT ¤È¹çÃפ¹¤ëÍøÍѲÄǽ¤Ê¥Õ¥©¥ó¥È
2950     ¤Î¥ê¥¹¥È¤òÊÖ¤¹¡£$LANGUAGE ¤¬ @c Mnil ¤Ç¤Ê¤±¤ì¤Ð¡¢$LANGUAGE ¤ò¥µ¥Ý¡¼
2951     ¥È¤¹¤ëÍøÍѲÄǽ¤Ê¥Õ¥©¥ó¥È¤Î¥ê¥¹¥È¤òÊÖ¤¹¡£$MAXNUM ¤Ï¡¢0 ¤è¤êÂ礭¤¤¾ì
2952     ¹ç¤Ë¤Ï¡¢ÊÖ¤¹¥Õ¥©¥ó¥È¤Î¿ô¤Î¾å¸Â¤Ç¤¢¤ë¡£
2953
2954     ¤¿¤À¤·¡¢°ú¿ô $LANGUAGE ¤ÏµìÈǤȤÎÀ°¹çÀ­¤Î¤¿¤á¤À¤±¤Ë¤¢¤ê¡¢¤½¤Î»ÈÍѤÏ
2955     ´«¤á¤é¤ì¤Ê¤¤¡£¥Õ¥©¥ó¥È¤Î #Mlanguage ¥×¥í¥Ñ¥Æ¥£¤ò»È¤¦¤Ù¤­¤Ç¤¢¤ë¡£¤â
2956     ¤· $FONT ¤¬¤¹¤Ç¤Ë¤³¤Î¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ã¤Æ¤¤¤¿¤é¡¢°ú¿ô $LANGUAGE ¤Ï̵
2957
2958
2959     @return 
2960     ¤³¤Î´Ø¿ô¤Ï¥­¡¼¤¬¥Õ¥©¥ó¥È¥Õ¥¡¥ß¥ê̾¤Ç¤¢¤êÃͤ¬ MFont ¥ª¥Ö¥¸¥§¥¯¥È¤Ø¤Î
2961     ¥Ý¥¤¥ó¥¿¤Ç¤¢¤ë¤è¤¦¤Êplist ¤òÊÖ¤¹¡£plist ¤Ï m17n_object_unref () ¤Ç
2962     ²òÊü¤¹¤ëɬÍפ¬¤¢¤ë¡£¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤é¤Ê¤±¤ì¤ÐNULL ¤òÊÖ¤¹¡£  */
2963
2964 MPlist *
2965 mfont_list (MFrame *frame, MFont *font, MSymbol language, int maxnum)
2966 {
2967   MPlist *plist, *pl;
2968   MFontList *font_list;
2969   int i;
2970   MFont spec;
2971   
2972   if (font)
2973     spec = *font;
2974   else
2975     MFONT_INIT (&spec);
2976
2977   if (spec.size < 0)
2978     {
2979       double pt = - spec.size;
2980
2981       spec.size = pt * frame->dpi / 72.27 + 0.5;
2982     }
2983
2984   if (language != Mnil)
2985     spec.capability = merge_capability (spec.capability, Mlanguage, language,
2986                                         0);
2987
2988   font_list = mfont__list (frame, &spec, &spec, 0);
2989   if (! font_list)
2990     return NULL;
2991   if (font_list->nfonts == 0)
2992     {
2993       free (font_list);
2994       return NULL;
2995     }
2996
2997   plist = pl = mplist ();
2998   for (i = 0; i < font_list->nfonts; i++)
2999     {
3000       MSymbol family = FONT_PROPERTY (font_list->fonts[i].font, MFONT_FAMILY);
3001
3002       if (family != Mnil)
3003         pl = mplist_add (pl, family, font_list->fonts[i].font);
3004     }
3005   free (font_list);
3006   return plist;
3007 }
3008
3009 /***en
3010     @brief Get a list of font famiy names.
3011
3012     The mfont_list_family_names () functions returns a list of font
3013     family names available on frame $FRAME.
3014
3015     @return
3016
3017     This function returns a plist whose keys are #Msymbol and values
3018     are symbols representing font family names.  The elements are
3019     sorted by alphabetical order.  The plist must be freed by
3020     m17n_object_unref ().  If not font is found, it returns NULL.  */
3021
3022 MPlist *
3023 mfont_list_family_names (MFrame *frame)
3024 {
3025   MPlist *plist = mplist (), *p;
3026
3027   MPLIST_DO (p, frame->font_driver_list)
3028     {
3029       MFontDriver *driver = MPLIST_VAL (p);
3030
3031       (driver->list_family_names) (frame, plist);
3032     }
3033   return plist;
3034 }
3035
3036
3037 /*=*/
3038
3039 /***en
3040     @brief Check the usability of a font.
3041
3042     The mfont_check () function checkes if $FONT can be used for
3043     $SCRIPT and $LANGUAGE in $FONTSET on $FRAME.
3044
3045     @return 
3046     If the font is usable, return 1.  Otherwise return 0.
3047  */
3048
3049 int
3050 mfont_check (MFrame *frame, MFontset *fontset,
3051              MSymbol script, MSymbol language, MFont *font)
3052 {
3053   MRealizedFont *rfont;
3054   int best, score;
3055
3056   if (! fontset)
3057     fontset = frame->face->property[MFACE_FONTSET];
3058   rfont = mfontset__get_font (frame, fontset, script, language, font, &best);
3059   if (! rfont || ! best)
3060     return 0;
3061   score = font_score (&rfont->spec, font);
3062   return (score == 0 ? 2 : 1);
3063 }
3064
3065 /*=*/
3066
3067 /***en
3068     @brief Check is a font matches with a font spec.
3069
3070     The mfont_match_p () function checks if $FONT matches with the
3071     font-spec $SPEC.
3072
3073     @return 
3074     If the font matches, 1 is returned.  Otherwise 0 is returned.  */
3075
3076 int
3077 mfont_match_p (MFont *font, MFont *spec)
3078 {
3079   return mfont__match_p (font, spec, MFONT_REGISTRY);
3080 }
3081
3082 /*=*/
3083 /***en
3084     @brief Open a font.
3085
3086     The mfont_open () function opens $FONT on $FRAME, and returns a
3087     realized font.
3088
3089     @return
3090     If the font was successfully opened, a realized font is returned.
3091     Otherwize NULL is returned.
3092
3093     @seealso
3094     mfont_close ().  */
3095
3096
3097 MFont *
3098 mfont_open (MFrame *frame, MFont *font)
3099 {
3100   enum MFontType font_type = font->type;
3101
3102   if (font_type == MFONT_TYPE_SPEC)
3103     return mfont_find (frame, font, NULL, 0);
3104   if (font_type == MFONT_TYPE_OBJECT)
3105     return (MFont *) mfont__open (frame, font, font);
3106   if (font_type == MFONT_TYPE_REALIZED)
3107     return font;
3108   MERROR (MERROR_FONT, NULL);
3109 }
3110
3111 /*=*/
3112 /***en
3113     @brief Encapusulate a font.
3114
3115     The mfont_encapsulate () functions realizes a font by
3116     encapusulating data $DATA or type $DATA_TYPE on $FRAME.  Currently
3117     $DATA_TAPE is #Mfontconfig or #Mfreetype, and $DATA points to an
3118     object of FcPattern or FT_Face respectively.
3119
3120     @return
3121     If the operation was successful, a realized font is returned.
3122     Otherwise NULL is return.
3123
3124     @seealso
3125     mfont_close ().  */
3126
3127
3128 MFont *
3129 mfont_encapsulate (MFrame *frame, MSymbol data_type, void *data)
3130 {
3131   MPlist *p;
3132
3133   MPLIST_DO (p, frame->font_driver_list)
3134     {
3135       MFontDriver *driver = MPLIST_VAL (p);
3136       MRealizedFont *rfont;
3137
3138       if (driver->encapsulate
3139           && (rfont = driver->encapsulate (frame, data_type, data)))
3140         return (MFont *) rfont;
3141     }
3142
3143   return NULL;
3144 }
3145
3146 /*=*/
3147 /***en
3148     @brief Close a font.
3149
3150     The mfont_close () function close a realized font $FONT.  $FONT
3151     must be opened previously by mfont_open () or mfont_encapsulate
3152     ().
3153
3154     @return
3155     If the operation was successful, 0 is returned.  Otherwise, -1 is
3156     returned.
3157
3158     @seealso
3159     mfont_open (), mfont_encapsulate ().  */
3160
3161 int
3162 mfont_close (MFont *font)
3163 {
3164   enum MFontType font_type = font->type;
3165   MRealizedFont *rfont;
3166
3167   if (font_type != MFONT_TYPE_REALIZED)
3168     MERROR (MERROR_FONT, -1);
3169   rfont = (MRealizedFont *) font;
3170   if (rfont->encapsulating
3171       && rfont->driver->close)
3172     rfont->driver->close (rfont);
3173   return 0;
3174 }
3175
3176 /*** @} */
3177
3178 /*** @addtogroup m17nDebug */
3179 /*=*/
3180 /*** @{ */
3181
3182 /***en
3183     @brief Dump a font.
3184
3185     The mdebug_dump_font () function prints font $FONT in a human readable
3186     way to the stderr.
3187
3188     @return
3189     This function returns $FONT.  */
3190 /***ja
3191     @brief ¥Õ¥©¥ó¥È¤ò¥À¥ó¥×¤¹¤ë.
3192
3193     ´Ø¿ô mdebug_dump_font () ¤Ï¥Õ¥©¥ó¥È $FONT ¤ò stderr 
3194     ¤Ë¿Í´Ö¤Ë²ÄÆɤʷÁ¤Ç°õºþ¤¹¤ë¡£
3195
3196     @return
3197     ¤³¤Î´Ø¿ô¤Ï $FONT ¤òÊÖ¤¹¡£  */
3198
3199 MFont *
3200 mdebug_dump_font (MFont *font)
3201 {
3202   char *name;
3203   
3204   name = xlfd_unparse_name (font, 0);
3205   if (name)
3206     {
3207       fprintf (stderr, "%s", name);
3208       free (name);
3209     }
3210   if (font->file != Mnil)
3211     {
3212       char *file = MSYMBOL_NAME (font->file);
3213       char *lastslash = file, *p;
3214
3215       for (p = file; *p; p++)
3216         if (*p == '/')
3217           lastslash = p;
3218       if (name)
3219         fprintf (stderr, ",");
3220       fprintf (stderr, "%s", lastslash + 1);
3221     }
3222   if (font->capability != Mnil)
3223     fprintf (stderr, "%s", MSYMBOL_NAME (font->capability));
3224   return font;
3225 }
3226
3227 /*** @} */
3228
3229 /*
3230   Local Variables:
3231   coding: euc-japan
3232   End:
3233 */