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