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