Update copyright.
[m17n/m17n-lib.git] / src / font.c
1 /* font.c -- font module.
2    Copyright (C) 2003, 2004, 2005, 2006
3      National Institute of Advanced Industrial Science and Technology (AIST)
4      Registration Number H15PRO112
5
6    This file is part of the m17n library.
7
8    The m17n library is free software; you can redistribute it and/or
9    modify it under the terms of the GNU Lesser General Public License
10    as published by the Free Software Foundation; either version 2.1 of
11    the License, or (at your option) any later version.
12
13    The m17n library is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    Lesser General Public License for more details.
17
18    You should have received a copy of the GNU Lesser General Public
19    License along with the m17n library; if not, write to the Free
20    Software Foundation, Inc., 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 Mspacing.
34
35     When the key of a font property is @c Msize or @c Mresolution, its
36     value is an integer.  Otherwise the value is a symbol.  
37
38     "The font property that belongs to font F and whose key is @c
39     Mxxx" may be shortened to "the xxx property of F".
40
41     The value of a foundry property is a symbol representing font
42     foundry information, e.g. adobe, misc, etc.
43
44     The value of a family property is a symbol representing font family
45     information, e.g. times, helvetica, etc.
46
47     The value of a weight property is a symbol representing weight
48     information, e.g. normal, bold, etc.
49
50     The value of a style property is a symbol representing slant
51     information, e.g. normal, italic, etc.
52
53     The value of a stretch property is a symbol representing width
54     information, e.g. normal, semicondensed, etc.
55
56     The value of an adstyle property is a symbol representing abstract
57     font family information, e.g. serif, sans-serif, etc.
58
59     The value of a registry property is a symbol representing registry
60     information, e.g. iso10646-1, iso8895-1, etc.
61
62     The value of a size property is an integer representing design
63     size in the unit of 1/10 point.
64
65     The value of a resolution property is an integer representing
66     assumed device resolution in the unit of dots per inch (dpi).
67
68     The value of a type property is a symbol indicating a font driver;
69     currently Mx or Mfreetype.
70
71     The m17n library uses font objects for two purposes: to receive
72     font specification from an application program, and to present
73     available fonts to an application program.  When the m17n library
74     presents an available font to an application program, all font
75     properties have a concrete value.
76
77     The m17n library supports three kinds of fonts: Window system fonts,
78     FreeType fonts, and OpenType fonts.
79
80     <ul>
81
82     <li> Window system fonts
83
84     The m17n-X library supports all fonts handled by an X server and
85     an X font server.  The correspondence between XLFD fields and font
86     properties are shown below.
87
88 @verbatim
89     XLFD field                                  property
90     ---------------                             --------
91     FOUNDRY                                     foundry
92     FAMILY_NAME                                 family
93     WEIGHT_NAME                                 weight
94     SLANT                                       style
95     SETWIDTH_NAME                               stretch
96     ADD_STYLE_NAME                              adstyle
97     PIXEL_SIZE                                  size
98     RESOLUTION_Y                                resolution
99     CHARSET_REGISTRY-CHARSET_ENCODING           registry
100 @endverbatim
101
102     XLFD fields not listed in the above table are ignored.
103
104     <li> FreeType fonts
105
106     The m17n library, if configured to use the FreeType library,
107     supports all fonts that can be handled by the FreeType library.
108     The variable #mfont_freetype_path is initialized properly according
109     to the configuration of the m17n library and the environment
110     variable @c M17NDIR.  See the documentation of the variable for
111     details.
112
113     If the m17n library is configured to use the fontconfig library,
114     in addition to #mfont_freetype_path, all fonts available via
115     fontconfig are supported.
116
117     The family name of a FreeType font corresponds to the family
118     property.  Style names of FreeType fonts correspond to the weight,
119     style, and stretch properties as below.
120
121 @verbatim
122     style name          weight  style   stretch
123     ----------          ------  -----   -------
124     Regular             medium  r       normal
125     Italic              medium  i       normal
126     Bold                bold    r       normal
127     Bold Italic         bold    i       normal
128     Narrow              medium  r       condensed
129     Narrow Italic       medium  i       condensed
130     Narrow Bold         bold    r       condensed
131     Narrow Bold Italic  bold    i       condensed
132     Black               black   r       normal
133     Black Italic        black   i       normal
134     Oblique             medium  o       normal
135     BoldOblique         bold    o       normal
136 @endverbatim
137
138     Style names not listed in the above table are treated as
139     "Regular".
140
141     Combination of a platform ID and an encoding ID corresponds to the
142     registry property.  For example, if a font has the combination (1
143     1), the registry property is 1-1.  Some frequent combinations have
144     a predefined registry property as below.
145
146 @verbatim
147     platform ID         encoding ID     registry property
148     -----------         -----------     -----------------
149     0                   3               unicode-bmp
150     0                   4               unicode-full
151     1                   0               apple-roman
152     3                   1               unicode-bmp
153     3                   1               unicode-full
154 @endverbatim
155
156     Thus, a font that has two combinations (1 0) and (3 1) corresponds
157     to four font objects whose registries are 1-0, apple-roman, 3-1,
158     and unicode-bmp.
159
160     <li> OpenType fonts 
161
162     The m17n library, if configured to use both the FreeType library
163     and the OTF library, supports any OpenType fonts.  The list of
164     actually available fonts is created in the same way as in the case
165     of FreeType fonts.  If a fontset instructs to use an OpenType font
166     via an FLT (Font Layout Table), and the FLT has an OTF-related
167     command (e.g. otf:deva), the OTF library converts a character
168     sequence to a glyph code sequence according to the OpenType layout
169     tables of the font, and the FreeType library gives a bitmap image
170     for each glyph.
171
172     </ul>
173
174   */
175
176 /***ja
177     @addtogroup m17nFont
178     @brief ¥Õ¥©¥ó¥È¥ª¥Ö¥¸¥§¥¯¥È.
179
180     m17n GUI API ¤Ï¥Õ¥©¥ó¥È¤ò @c MFont ·¿¤Î¥ª¥Ö¥¸¥§¥¯¥È¤È¤·¤Æɽ¸½¤¹¤ë¡£
181     ¥Õ¥©¥ó¥È¤Ï @e ¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£ ¤ò»ý¤Ä¤³¤È¤¬¤Ç¤­¤ë¡£Â¾¤Î¥¿¥¤¥×¤Î¥×
182     ¥í¥Ñ¥Æ¥£Æ±ÍÍ¡¢¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤Ï¥­¡¼¤ÈÃͤ«¤é¤Ê¤ê¡¢¥­¡¼¤Ï°Ê²¼¤Î¥·
183     ¥ó¥Ü¥ë¤Î¤¤¤º¤ì¤«¤Ç¤¢¤ë¡£
184
185     @c Mfoundry, @c Mfamily, @c Mweight, @c Mstyle, @c Mstretch,
186     @c Madstyle, @c Mregistry, @c Msize, @c Mresolution, @c Mspacing
187
188     ¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼¤¬ @c Msize ¤¢¤ë¤¤¤Ï @c Mresolution 
189     ¤Î¾ì¹ç¡¢ÃͤÏÀ°¿ôÃͤǤ¢¤ê¡¢¥­¡¼¤¬¤½¤ì°Ê³°¤Î¾ì¹ç¡¢Ãͤϥ·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£
190
191     ¡Ö¥Õ¥©¥ó¥È F ¤Î¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¥­¡¼¤¬ @c Mxxx 
192     ¤Ç¤¢¤ë¤â¤Î¡×¤Î¤³¤È¤ò´Êñ¤Ë¡ÖF ¤Î xxx ¥×¥í¥Ñ¥Æ¥£¡×¤È¸Æ¤Ö¤³¤È¤¬¤¢¤ë¡£
193
194     foundry ¥×¥í¥Ñ¥Æ¥£¤ÎÃͤϡ¢adobe, misc 
195     Åù¤Î¥Õ¥©¥ó¥È¤Î³«È¯¸µ¾ðÊó¤ò¼¨¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£
196
197     family ¥×¥í¥Ñ¥Æ¥£¤ÎÃͤϡ¢times, helvetica 
198     Åù¤Î¥Õ¥©¥ó¥È¥Õ¥¡¥ß¥ê¡¼¤ò¼¨¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£
199
200     weight ¥×¥í¥Ñ¥Æ¥£¤ÎÃͤϡ¢normal, bold Åù¤ÎÂÀ¤µ¤Ë´Ø¤¹¤ë¾ðÊó¤ò¼¨¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£
201
202     style ¥×¥í¥Ñ¥Æ¥£¤ÎÃͤϡ¢normal, italic 
203     Åù¤Î¥¹¥¿¥¤¥ë¤Ë´Ø¤¹¤ë¾ðÊó¤ò¼¨¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£
204
205     stretch ¥×¥í¥Ñ¥Æ¥£¤ÎÃͤϡ¢normal, semicondensed 
206     Åù¤Îʸ»úÉý¤Ë´Ø¤¹¤ë¾ðÊó¤ò¼¨¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£
207
208     adstyle ¥×¥í¥Ñ¥Æ¥£¤ÎÃͤϡ¢serif, sans-serif
209     Åù¤ÎÃê¾ÝŪ¤Ê¥Õ¥©¥ó¥È¥Õ¥¡¥ß¥ê¡¼¤Ë´Ø¤¹¤ë¾ðÊó¤ò¼¨¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£
210
211     registry ¥×¥í¥Ñ¥Æ¥£¤ÎÃͤϡ¢iso10646, iso8895-1
212     Åù¤Î¥ì¥¸¥¹¥È¥ê¾ðÊó¤ò¼¨¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£
213
214     size ¥×¥í¥Ñ¥Æ¥£¤ÎÃͤϡ¢¥Õ¥©¥ó¥È¤Î¥Ç¥¶¥¤¥ó¥µ¥¤¥º¤òɽ¤ï¤¹À°¿ôÃͤǤ¢¤ê¡¢
215     Ã±°Ì¤Ï1/10 ¥Ý¥¤¥ó¥È¤Ç¤¢¤ë¡£
216
217     resolution ¥×¥í¥Ñ¥Æ¥£¤ÎÃͤϡ¢ÁÛÄꤵ¤ì¤Æ¤¤¤ë¥Ç¥Ð¥¤¥¹¤Î²òÁüÅÙ¤òɽ¤ï¤¹
218     À°¿ôÃͤǤ¢¤ê¡¢Ã±°Ì¤Ïdots per inch (dpi) ¤Ç¤¢¤ë¡£
219
220     type ¥×¥í¥Ñ¥Æ¥£¤ÎÃͤϡ¢¥Õ¥©¥ó¥È¥É¥é¥¤¥Ð¤ò»Ø¼¨¤·¡¢¸½ºß Mx ¤â¤·¤¯¤Ï
221     Mfreetype ¤Ç¤¢¤ë¡£
222
223     m17n ¥é¥¤¥Ö¥é¥ê¤Ï¥Õ¥©¥ó¥È¥ª¥Ö¥¸¥§¥¯¥È¤ò£²¤Ä¤ÎÌÜŪ¤ÇÍѤ¤¤Æ¤¤¤ë¡£¥¢¥×
224     ¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥à¤«¤é¥Õ¥©¥ó¥È¤Î»ØÄê¤ò¼õ¤±¼è¤ëÌÜŪ¤È¡¢¥¢¥×¥ê¥±¡¼
225     ¥·¥ç¥ó¥×¥í¥°¥é¥à¤ËÍøÍѲÄǽ¤Ê¥Õ¥©¥ó¥È¤òÄ󼨤¹¤ëÌÜŪ¤Ç¤¢¤ë¡£¥¢¥×¥ê¥±¡¼
226     ¥·¥ç¥ó¥×¥í¥°¥é¥à¤ËÂФ·¤ÆÄ󼨤ò¹Ô¤¦ºÝ¤Ë¤Ï¡¢¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤Ï¤¹¤Ù
227     ¤Æ¶ñÂÎŪ¤ÊÃͤò»ý¤Ä¡£
228
229     m17n ¥é¥¤¥Ö¥é¥ê¤Ï Window ¥·¥¹¥Æ¥à¥Õ¥©¥ó¥È¡¢FreeType¥Õ¥©¥ó¥È¡¢
230     OpenType¥Õ¥©¥ó¥È¤Î£³¼ïÎà¤ò¥µ¥Ý¡¼¥È¤·¤Æ¤¤¤ë¡£
231
232     <ul>
233
234     <li> Window ¥·¥¹¥Æ¥à¥Õ¥©¥ó¥È
235
236     m17n X ¥é¥¤¥Ö¥é¥ê¤Ï¡¢X ¥µ¡¼¥Ð¤È X ¥Õ¥©¥ó¥È¥µ¡¼¥Ð¤¬¼è¤ê°·¤¦Á´¤Æ¤Î¥Õ¥©¥ó¥È¤ò¥µ¥Ý¡¼¥È¤¹¤ë¡£
237     XLFD ¤Î³Æ¥Õ¥£¡¼¥ë¥É¤È¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤ÎÂбþ¤Ï°Ê²¼¤ÎÄ̤ꡣ¤³¤Îɽ¤Ë¤Ê¤¤¥Õ¥£¡¼¥ë¥É¤Ï̵»ë¤µ¤ì¤ë¡£
238
239 @verbatim
240     XLFD ¥Õ¥£¡¼¥ë¥É                             ¥×¥í¥Ñ¥Æ¥£
241     ---------------                             --------
242     FOUNDRY                                     foundry
243     FAMILY_NAME                                 family
244     WEIGHT_NAME                                 weight
245     SLANT                                       style
246     SETWIDTH_NAME                               stretch
247     ADD_STYLE_NAME                              adstyle
248     PIXEL_SIZE                                  size
249     RESOLUTION_Y                                resolution
250     CHARSET_REGISTRY-CHARSET_ENCODING           registry
251 @endverbatim
252
253     <li> FreeType fonts
254
255     m17n ¥é¥¤¥Ö¥é¥ê¤Ï¡¢FreeType ¥é¥¤¥Ö¥é¥ê¤ò»È¤¦¤è¤¦¤ËÀßÄꤵ¤ì¤¿¾ì¹ç¤Ë¤Ï¡¢
256     FreeType ¤¬°·¤¦¤¹¤Ù¤Æ¤Î¥Õ¥©¥ó¥È¤ò¥µ¥Ý¡¼¥È¤¹¤ë¡£ÊÑ¿ô 
257     #mfont_freetype_path ¤Ï m17n ¥é¥¤¥Ö¥é¥ê¤ÎÀßÄê¤È´Ä¶­ÊÑ¿ô @c M17NDIR 
258     ¤Ë±þ¤¸¤Æ½é´ü²½¤µ¤ì¤ë¡£¾ÜºÙ¤ÏÊÑ¿ô¤ÎÀâÌÀ¤ò»²¾È¤Î¤³¤È¡£
259
260     ¤â¤· m17n ¥é¥¤¥Ö¥é¥ê¤¬ fontconfig ¥é¥¤¥Ö¥é¥ê¤ò»È¤¦¤è¤¦¤ËÀßÄꤵ¤ì¤¿¾ì¹ç¤Ë¤Ï¡¢
261     #mfont_freetype_path ¤Ë²Ã¤¨¤Æ¡¢ fontconfig ¤Ç»ÈÍѲÄǽ¤Ê¥Õ¥©¥ó¥È¤â¤¹¤Ù¤Æ¥µ¥Ý¡¼¥È¤µ¤ì¤ë¡£
262
263     FreeType ¥Õ¥©¥ó¥È¤Î¥Õ¥¡¥ß¥ê̾¤Ï family ¥×¥í¥Ñ¥Æ¥£¤ËÂбþ¤¹¤ë¡£
264     FreeType ¥Õ¥©¥ó¥È¤Î¥¹¥¿¥¤¥ë̾¤Ï¡¢²¼¤Îɽ¤Î¤è¤¦¤Ë weight, style,
265     stretch ¥×¥í¥Ñ¥Æ¥£¤ËÂбþ¤¹¤ë¡£
266
267 @verbatim
268     ¥¹¥¿¥¤¥ë̾          weight  style   stretch
269     ----------          ------  -----   -------
270     Regular             medium  r       normal
271     Italic              medium  i       normal
272     Bold                bold    r       normal
273     Bold Italic         bold    i       normal
274     Narrow              medium  r       condensed
275     Narrow Italic       medium  i       condensed
276     Narrow Bold         bold    r       condensed
277     Narrow Bold Italic  bold    i       condensed
278     Black               black   r       normal
279     Black Italic        black   i       normal
280     Oblique             medium  o       normal
281     BoldOblique         bold    o       normal
282 @endverbatim
283
284     ¾å¤Îɽ¤Ë¸½¤ï¤ì¤Ê¤¤¥¹¥¿¥¤¥ë̾¤Ï "Regular" ¤È¤·¤Æ°·¤ï¤ì¤ë¡£
285
286     platform ID ¤È encoding ID ¤ÎÁȤ߹ç¤ï¤»¤¬ registry 
287     ¥×¥í¥Ñ¥Æ¥£¤ËÂбþ¤¹¤ë¡£¤¿¤È¤¨¤Ð¤¢¤ë¥Õ¥©¥ó¥È¤¬ (1 1) ¤È¤¤¤¦ ID ¤ÎÁȹ礻¤ò»ý¤Æ¤Ð¡¢
288     registry ¥×¥í¥Ñ¥Æ¥£¤Ï 1-1 ¤È¤Ê¤ë¡£ÉÑÈˤˤ¢¤é¤ï¤ì¤ëÁȹ礻¤Ë¤Ï°Ê²¼¤Î¤è¤¦¤ÊÄêµÁºÑ¤ß
289     registry ¥×¥í¥Ñ¥Æ¥£ ¤¬Í¿¤¨¤é¤ì¤Æ¤¤¤ë¡£
290
291 @verbatim
292     platform ID         encoding ID     registry ¥×¥í¥Ñ¥Æ¥£
293     -----------         -----------     -----------------
294     0                   3               unicode-bmp
295     0                   4               unicode-full
296     1                   0               apple-roman
297     3                   1               unicode-bmp
298     3                   1               unicode-full
299 @endverbatim
300
301     ¤·¤¿¤¬¤Ã¤Æ¡¢Æó¤Ä¤ÎÁȹ礻 (1 0) ¡¢(3 1) ¤ò»ý¤Ä¥Õ¥©¥ó¥È¤Ï¡¢¤½¤ì¤¾¤ì
302     registry ¥×¥í¥Ñ¥Æ¥£¤¬ 1-0, apple-roman, 3-1, unicode-bmp
303     ¤Ç¤¢¤ë£´¤Ä¤Î¥Õ¥©¥ó¥È¥ª¥Ö¥¸¥§¥¯¥È¤ËÂбþ¤¹¤ë¡£
304
305     <li> OpenType ¥Õ¥©¥ó¥È
306
307     m17n ¥é¥¤¥Ö¥é¥ê¤Ï¡¢FreeType ¥é¥¤¥Ö¥é¥ê¤È OTF 
308     ¥é¥¤¥Ö¥é¥ê¤ò»ÈÍѤ¹¤ë¤è¤¦¤ËÀßÄꤹ¤ì¤Ð¡¢¤¹¤Ù¤Æ¤Î OpenType 
309     ¥Õ¥©¥ó¥È¤ò¥µ¥Ý¡¼¥È¤¹¤ë¡£¼ÂºÝ¤ËÍøÍѤǤ­¤ë¥Õ¥©¥ó¥È¤Î¥ê¥¹¥È¤Ï FreeType
310     ¥Õ¥©¥ó¥È¤Î¾ì¹ç¤ÈƱÍͤ˺î¤é¤ì¤ë¡£OpenType ¥Õ¥©¥ó¥È¤ò FLT (Font Layout Table)
311     ·Ðͳ¤Ç»ÈÍѤ¹¤ë¤è¤¦¥Õ¥©¥ó¥È¥»¥Ã¥È¤Ë»ØÄꤵ¤ì¤Æ¤ª¤ê¡¢FLT ¤Ë OTF 
312     ´ØÏ¢¤Î¥³¥Þ¥ó¥É (¤¿¤È¤¨¤Ð otf:deva) ¤¬¤¢¤ì¤Ð¡¢OTF ¥é¥¤¥Ö¥é¥ê¤¬¥Õ¥©¥ó¥È¤Î OpenType
313     ¥ì¥¤¥¢¥¦¥È¥Æ¡¼¥Ö¥ë¤Ë½¾¤Ã¤Æʸ»úÎó¤ò¥°¥ê¥Õ¥³¡¼¥ÉÎó¤ËÊÑ´¹¤·¡¢FreeType
314     ¥é¥¤¥Ö¥é¥ê¤¬³Æ¥°¥ê¥Õ¤Î¥Ó¥Ã¥È¥Þ¥Ã¥×¥¤¥á¡¼¥¸¤òÄ󶡤¹¤ë¡£
315
316     </ul>
317
318 */
319
320 /*=*/
321
322 #if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE)
323 /*** @addtogroup m17nInternal
324      @{ */
325
326 #include "config.h"
327
328 #include <stdio.h>
329 #include <stdlib.h>
330 #include <string.h>
331
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 /* XLFD parser/generator */
716
717 /** Indices to each field of split font name.  */
718
719 enum xlfd_field_idx
720   {
721     XLFD_FOUNDRY,
722     XLFD_FAMILY,
723     XLFD_WEIGHT,
724     XLFD_SLANT,
725     XLFD_SWIDTH,
726     XLFD_ADSTYLE,
727     XLFD_PIXEL,
728     XLFD_POINT,
729     XLFD_RESX,
730     XLFD_RESY,
731     XLFD_SPACING,
732     XLFD_AVGWIDTH,
733     XLFD_REGISTRY,              /* This contains ENCODING.  */
734     /* anchor */
735     XLFD_FIELD_MAX
736   };
737
738 static int
739 xlfd_parse_name (const char *name, MFont *font)
740 {
741   char *field[XLFD_FIELD_MAX];
742   unsigned short resy, avgwidth;
743   unsigned size;
744   char copy[513];
745   int i;
746   char *p;
747   MSymbol sym;
748
749   if (name[0] != '-')
750     return -1;
751
752   field[0] = copy;
753   for (i = 1, p = copy, name++; *name; p++, name++)
754     {
755       if (p - copy > 512)
756         return -1;
757       if (*name == '-'
758           && i < XLFD_FIELD_MAX)
759         {
760           *p = '\0';
761           if (field[i - 1][0] == '*')
762             field[i - 1] = NULL;
763           field[i++] = p + 1;
764         }
765       else
766         *p = tolower (*name);
767     }
768   *p = '\0';
769   if (field[i - 1][0] == '*')
770     field[i - 1] = NULL;
771   while (i < XLFD_FIELD_MAX)
772     field[i++] = NULL;
773
774   resy = field[XLFD_RESY] ? atoi (field[XLFD_RESY]) : 0;
775   avgwidth = ((field[XLFD_AVGWIDTH] && isdigit (field[XLFD_AVGWIDTH][0]))
776               ? atoi (field[XLFD_AVGWIDTH]) : 1);
777   if (! avgwidth)
778     size = 0;
779   else if (! field[XLFD_PIXEL])
780     size = field[XLFD_POINT] ? atoi (field[XLFD_POINT]) * resy / 72 : 0;
781   else if (field[XLFD_PIXEL][0] == '[')
782     {
783       /* The pixel size field specifies a transformation matrix of the
784          form "[A B C D]".  The XLFD spec says that the scalar value N
785          for the pixel size is equivalent to D.  */
786       char *p0 = field[XLFD_PIXEL] + 1, *p1;
787       double d;
788
789       for (i = 0; i < 4; i++, p0 = p1)
790         d = strtod (p0, &p1);
791       size = d * 10;
792     }
793   else
794     size = atoi (field[XLFD_PIXEL]) * 10;
795
796   if (field[XLFD_FOUNDRY])
797     {
798       sym = msymbol (field[XLFD_FOUNDRY]);
799       if (! sym)
800         sym = msymbol ("Nil");
801       mfont__set_property (font, MFONT_FOUNDRY, sym);
802     }
803   if (field[XLFD_FAMILY])
804     {
805       sym = msymbol (field[XLFD_FAMILY]);
806       if (! sym)
807         sym = msymbol ("Nil");
808       mfont__set_property (font, MFONT_FAMILY, sym);
809     }
810   if (field[XLFD_WEIGHT])
811     mfont__set_property (font, MFONT_WEIGHT, msymbol (field[XLFD_WEIGHT]));
812   if (field[XLFD_SLANT])
813     mfont__set_property (font, MFONT_STYLE, msymbol (field[XLFD_SLANT]));
814   if (field[XLFD_SWIDTH])
815     mfont__set_property (font, MFONT_STRETCH, msymbol (field[XLFD_SWIDTH]));
816   if (field[XLFD_ADSTYLE])
817     mfont__set_property (font, MFONT_ADSTYLE, msymbol (field[XLFD_ADSTYLE]));
818   font->property[MFONT_RESY] = resy;
819   font->size = size;
820   if (field[XLFD_SPACING])
821     font->spacing
822       = ((field[XLFD_SPACING][0] == 'p' || field[XLFD_SPACING][0] == 'P')
823          ? MFONT_SPACING_PROPORTIONAL
824          : (field[XLFD_SPACING][0] == 'm' || field[XLFD_SPACING][0] == 'M')
825          ? MFONT_SPACING_MONO : MFONT_SPACING_CHARCELL);
826   if (field[XLFD_REGISTRY])
827     mfont__set_property (font, MFONT_REGISTRY, msymbol (field[XLFD_REGISTRY]));
828   font->type = MFONT_TYPE_SPEC;
829   font->source = MFONT_SOURCE_X;
830   return 0;
831 }
832
833 static char *
834 xlfd_unparse_name (MFont *font, int full_xlfd)
835 {
836   MSymbol prop[7];
837   char name[513];
838   char *str[7];
839   int len, i;
840   char spacing;
841   int size, resy;
842
843   prop[0] = (MSymbol) mfont_get_prop (font, Mfoundry);
844   prop[1] = (MSymbol) mfont_get_prop (font, Mfamily);
845   prop[2] = (MSymbol) mfont_get_prop (font, Mweight);
846   prop[3] = (MSymbol) mfont_get_prop (font, Mstyle);
847   prop[4] = (MSymbol) mfont_get_prop (font, Mstretch);
848   prop[5] = (MSymbol) mfont_get_prop (font, Madstyle);
849   prop[6] = (MSymbol) mfont_get_prop (font, Mregistry);
850   for (len = 0, i = 0; i < 7; i++)
851     {
852       if (prop[i] != Mnil)
853         {
854           str[i] = msymbol_name (prop[i]);
855           len += strlen (str[i]);
856         }
857       else
858         {
859           str[i] = "*";
860           len++;
861         }
862     }
863   spacing = (font->spacing == MFONT_SPACING_UNDECIDED ? '*'
864              : font->spacing == MFONT_SPACING_PROPORTIONAL ? 'p'
865              : font->spacing == MFONT_SPACING_MONO ? 'm'
866              : 'c');
867
868   if ((len
869        + 13                     /* 13 dashes */
870        + 2                      /* 2 asterisks */
871        + 30                     /* 3 integers (each 10 digits) */
872        + 1                      /* 1 spacing char */
873        + 1)                     /* '\0' terminal */
874       > 513)
875     return NULL;
876
877   resy = (int) mfont_get_prop (font, Mresolution);
878   size = font->size;
879   if (size >= 0)
880     {
881       if ((size % 10) < 5)
882         size /= 10;
883       else
884         size = size / 10 + 1;
885     }
886   else
887     size = - size;
888
889   if (full_xlfd)
890     {
891       if (font->size >= 0)
892         sprintf (name, "-%s-%s-%s-%s-%s-%s-%d-*-%d-%d-%c-*-%s",
893                  str[0], str[1], str[2], str[3], str[4], str[5],
894                  size, resy, resy, spacing, str[6]);
895       else
896         sprintf (name, "-%s-%s-%s-%s-%s-%s-*-%d-%d-%d-%c-*-%s",
897                  str[0], str[1], str[2], str[3], str[4], str[5],
898                  size, resy, resy, spacing, str[6]);
899     }
900   else
901     {
902       char *p = name;
903
904       p += sprintf (p, "-%s", str[0]);
905       for (i = 1; i < 6; i++)
906         if (p[-1] != '*' || str[i][0] != '*')
907           p += sprintf (p, "-%s", str[i]);
908       if (p[-1] != '*' || font->size > 0)
909         {
910           if (font->size > 0)
911             p += sprintf (p, "-%d-*", size);
912           else
913             p += sprintf (p, "-*");
914         }
915       if (str[6][0] != '*')
916         sprintf (p, "-%s", str[6]);
917     }
918
919   return strdup (name);
920 }
921
922 /* Compare FONT with REQUEST and return how much they differs.  */
923
924 static int
925 font_score (MFont *font, MFont *request)
926 {
927   int score = 0;
928   int i = FONT_SCORE_PRIORITY_SIZE;
929
930   while (--i >= 0)
931     {
932       enum MFontProperty prop = font_score_priority[i];
933       int val;
934
935       if (prop == MFONT_SIZE)
936         {
937           if (font->size && request->size)
938             {
939               val = font->size - request->size;
940               if (val)
941                 {
942                   if (val < 0)
943                     val = - val;
944                   if (val >= 0x10000)
945                     val = 0xFFFF;
946                   score |= (val << font_score_shift_bits[MFONT_SIZE]);
947                 }
948             }
949         }
950       else if (font->property[prop] && request->property[prop]
951                && font->property[prop] != request->property[prop])
952         {
953           if (prop <= MFONT_FAMILY)
954             val = 1;
955           else if (prop == MFONT_WEIGHT)
956             {
957               unsigned short v1 = font->property[prop];
958               unsigned short v2 = request->property[prop];
959
960               if (v1 == font_weight_regular || v1 == font_weight_normal)
961                 v1 = font_weight_medium;
962               if (v2 == font_weight_regular || v2 == font_weight_normal)
963                 v2 = font_weight_medium;
964               val = v1 > v2 ? v1 - v2 : v2 - v1;
965             }
966           else
967             {
968               val = font->property[prop] - request->property[prop];
969               if (val < 0)
970                 val = - val;
971               if (val > 3)
972                 val = 3;
973             }
974           score |= val << font_score_shift_bits[prop];
975         }
976     }
977   if (request->file != Mnil && request->file != font->file)
978     score |= 40000000;
979   return score;
980 }
981
982 \f
983 /* Internal API */
984
985 MSymbol Miso8859_1, Miso10646_1, Municode_bmp, Municode_full, Mapple_roman;
986
987 int
988 mfont__init ()
989 {
990   int i, shift;
991   MSymbol regular = msymbol ("regular");
992   MSymbol normal = msymbol ("normal");
993   MSymbol medium = msymbol ("medium");
994
995   M_font_capability = msymbol_as_managing_key ("  font-capability");
996   M_font_list = msymbol_as_managing_key ("  font-list");
997   M_font_list_len = msymbol ("  font-list-len");
998
999   Mfoundry = msymbol ("foundry");
1000   mfont__property_table[MFONT_FOUNDRY].property = Mfoundry;
1001   Mfamily = msymbol ("family");
1002   mfont__property_table[MFONT_FAMILY].property = Mfamily;
1003   Mweight = msymbol ("weight");
1004   mfont__property_table[MFONT_WEIGHT].property = Mweight;
1005   Mstyle = msymbol ("style");
1006   mfont__property_table[MFONT_STYLE].property = Mstyle;
1007   Mstretch = msymbol ("stretch");
1008   mfont__property_table[MFONT_STRETCH].property = Mstretch;
1009   Madstyle = msymbol ("adstyle");
1010   mfont__property_table[MFONT_ADSTYLE].property = Madstyle;
1011   Mregistry = msymbol ("registry");
1012   mfont__property_table[MFONT_REGISTRY].property = Mregistry;
1013
1014   Mspacing = msymbol ("spacing");
1015   Msize = msymbol ("size");
1016   Mresolution = msymbol ("resolution");
1017   Mmax_advance = msymbol ("max-advance");
1018   Mfontfile = msymbol ("fontfile");
1019
1020   Mfontconfig = msymbol ("fontconfig");
1021
1022   Mx = msymbol ("x");
1023   Mfreetype = msymbol ("freetype");
1024   Mxft = msymbol ("xft");
1025
1026   Miso8859_1 = msymbol ("iso8859-1");
1027   Miso10646_1 = msymbol ("iso10646-1");
1028   Municode_bmp = msymbol ("unicode-bmp");
1029   Municode_full = msymbol ("unicode-full");
1030   Mapple_roman = msymbol ("apple-roman");
1031
1032   /* The first entry of each mfont__property_table must be Mnil so
1033      that actual properties get positive numeric numbers.  */
1034   for (i = 0; i <= MFONT_REGISTRY; i++)
1035     {
1036       MLIST_INIT1 (&mfont__property_table[i], names, 8);
1037       MLIST_APPEND1 (&mfont__property_table[i], names, Mnil, MERROR_FONT);
1038     }
1039
1040   /* Register predefined font property names.  */
1041   for (i = 0; i <= MFONT_REGISTRY; i++)
1042     {
1043       int j;
1044
1045       for (j = 0; j < font_common_names[i].num; j++)
1046         {
1047           MSymbol sym = msymbol (font_common_names[i].names[j]);
1048
1049           if (sym == Mnil)
1050             return -1;
1051           if (msymbol_put (sym, mfont__property_table[i].property,
1052                            (void *) (j + 1)) < 0)
1053             return -1;
1054           MLIST_APPEND1 (&mfont__property_table[i], names, sym,
1055                          MERROR_FONT);
1056           if (i == MFONT_WEIGHT)
1057             {
1058               if (sym == regular)
1059                 font_weight_regular = j + 1;
1060               else if (sym == normal)
1061                 font_weight_normal = j + 1;
1062               else if (sym == medium)
1063                 font_weight_medium = j + 1;
1064             }
1065         }
1066     }
1067
1068   /* Here, SHIFT starts from 1, not 0.  This is because the lowest bit
1069      of a score is a flag for a scalable font (see the documentation
1070      of font_score).  */
1071   i = FONT_SCORE_PRIORITY_SIZE - 1;
1072   for (shift = 1; i >= 0; i--)
1073     {
1074       font_score_shift_bits[font_score_priority[i]] = shift;
1075       if (font_score_priority[i] == MFONT_SIZE)
1076         shift += 16;
1077       else if (font_score_priority[i] <= MFONT_FAMILY)
1078         shift++;
1079       else
1080         shift += 2;
1081     }
1082
1083   MFONT_INIT (&default_encoding.spec);
1084   default_encoding.encoding_name = Municode_full;
1085   default_encoding.encoding_charset = mcharset__unicode;
1086   default_encoding.repertory_name = Mnil;
1087   default_encoding.repertory_charset = NULL;
1088   {
1089     char *path, *buf;
1090     int bufsize;
1091     USE_SAFE_ALLOCA;
1092
1093     mfont_freetype_path = mplist ();
1094     bufsize = strlen (M17NDIR) + 7;
1095     SAFE_ALLOCA (buf, bufsize);
1096     sprintf (buf, "%s/fonts", M17NDIR);
1097     mplist_add (mfont_freetype_path, Mstring, strdup (buf));
1098     path = getenv ("M17NDIR");
1099     if (path)
1100       {
1101         bufsize = strlen (path) + 7;
1102         SAFE_ALLOCA (buf, bufsize);
1103         sprintf (buf, "%s/fonts", path);
1104         mplist_push (mfont_freetype_path, Mstring, strdup (buf));
1105       }
1106     SAFE_FREE (buf);
1107   }
1108
1109 #ifdef HAVE_FREETYPE
1110   if (mfont__ft_init () < 0)
1111     return -1;
1112 #endif /* HAVE_FREETYPE */
1113   if (mfont__flt_init () < 0)
1114     return -1;
1115
1116   return 0;
1117 }
1118
1119 void
1120 mfont__fini ()
1121 {
1122   MPlist *plist;
1123   int i;
1124
1125   mfont__flt_fini ();
1126 #ifdef HAVE_FREETYPE
1127   mfont__ft_fini ();
1128 #endif /* HAVE_FREETYPE */
1129
1130   MPLIST_DO (plist, mfont_freetype_path)
1131     free (MPLIST_VAL (plist));
1132   M17N_OBJECT_UNREF (mfont_freetype_path);
1133
1134   if (font_resize_list)
1135     {
1136       MPLIST_DO (plist, font_resize_list)
1137         free (MPLIST_VAL (plist));
1138       M17N_OBJECT_UNREF (font_resize_list);
1139       font_resize_list = NULL;
1140     }
1141   if (font_encoding_list)
1142     {
1143       MPLIST_DO (plist, font_encoding_list)
1144         free (MPLIST_VAL (plist));
1145       M17N_OBJECT_UNREF (font_encoding_list);
1146       font_encoding_list = NULL;
1147     }
1148   if (otf_script_list)
1149     {
1150       M17N_OBJECT_UNREF (otf_script_list);
1151       otf_script_list = NULL;
1152     }
1153
1154   for (i = 0; i <= MFONT_REGISTRY; i++)
1155     MLIST_FREE1 (&mfont__property_table[i], names);
1156 }
1157
1158
1159 MSymbol
1160 mfont__id (MFont *font)
1161 {
1162   char *buf, *p;
1163   int i;
1164   int file_len = (font->file == Mnil ? 0 : MSYMBOL_NAMELEN (font->file));
1165   int capability_len  = (font->capability == Mnil ? 0
1166                          : MSYMBOL_NAMELEN (font->capability));
1167   int total_len = MFONT_PROPERTY_MAX * 5 + 9 + file_len + capability_len;
1168   MSymbol id;
1169   USE_SAFE_ALLOCA;
1170
1171   SAFE_ALLOCA (buf, total_len);
1172   p = buf;
1173   if (font->property[0])
1174     p += sprintf (p, "%X", font->property[0]);
1175   for (i = 1; i < MFONT_PROPERTY_MAX; i++)
1176     {
1177       if (font->property[i])
1178         p += sprintf (p, "-%X", font->property[i]);
1179       else
1180         *p++ = '-';
1181     }
1182   if (font->size)
1183     p += sprintf (p, "-%X", font->size);
1184   if (font->spacing)
1185     p += sprintf (p, "-%X", font->spacing);
1186   if (capability_len > 0)
1187     {
1188       *p++ = '-';
1189       memcpy (p, MSYMBOL_NAME (font->capability), capability_len);
1190       p += capability_len;
1191     }
1192   if (file_len > 0)
1193     {
1194       *p++ = '-';
1195       memcpy (p, MSYMBOL_NAME (font->file), file_len);
1196       p += file_len;
1197     }      
1198   id = msymbol__with_len (buf, p - buf);
1199   SAFE_FREE (buf);
1200   return id;
1201 }
1202
1203 /** Return 1 iff FONT matches SPEC.  */
1204
1205 int
1206 mfont__match_p (MFont *font, MFont *spec, int prop)
1207 {
1208   if (spec->capability != font->capability
1209       && spec->capability != Mnil && font->capability != Mnil)
1210     return 0;
1211   if (spec->file != font->file
1212       && spec->file != Mnil && font->file != Mnil)
1213     return 0;
1214   for (; prop >= 0; prop--)
1215     if (spec->property[prop] && font->property[prop]
1216         && font->property[prop] != spec->property[prop])
1217       return 0;
1218   return 1;
1219 }
1220
1221 /* Merge SRC into DST.  If error_on_conflict is nonzero and a font
1222    property differs in SRC and DST, return -1.  */
1223
1224 int
1225 mfont__merge (MFont *dst, MFont *src, int error_on_conflict)
1226 {
1227   int i;
1228
1229   for (i = 0; i < MFONT_PROPERTY_MAX; i++)
1230     {
1231       if (! dst->property[i])
1232         dst->property[i] = src->property[i];
1233       else if (error_on_conflict
1234                && src->property[i]
1235                && dst->property[i] != src->property[i])
1236         return -1;
1237     }
1238   if (! dst->spacing)
1239     dst->spacing = src->spacing;
1240   else if (error_on_conflict
1241            && src->spacing
1242            && dst->spacing != src->spacing)
1243     return -1;
1244   if (! dst->size)
1245     dst->size = src->size;
1246   else if (error_on_conflict
1247            && src->size
1248            && dst->size != src->size)
1249     return -1;
1250   if (dst->capability == Mnil)
1251     dst->capability = src->capability;
1252   else if (error_on_conflict
1253            && src->capability
1254            && dst->capability != src->capability)
1255     return -1;
1256   if (dst->file == Mnil)
1257     dst->file = src->file;
1258   else if (error_on_conflict
1259            && src->file
1260            && dst->file != src->file)
1261     return -1;
1262   return 0;
1263 }
1264
1265 void
1266 mfont__set_spec_from_face (MFont *spec, MFace *face)
1267 {
1268   int i;
1269
1270   for (i = 0; i <= MFONT_ADSTYLE; i++)
1271     mfont__set_property (spec, i, face->property[i]);
1272   spec->property[MFONT_REGISTRY] = 0;
1273   spec->property[MFONT_RESY] = 0;
1274   spec->size = (int) (face->property[MFACE_SIZE]);
1275   spec->type = MFONT_TYPE_SPEC;
1276   spec->source = MFONT_SOURCE_UNDECIDED;
1277   spec->file = spec->capability = Mnil;
1278   spec->encoding = NULL;
1279 }
1280
1281
1282 extern MSymbol
1283 mfont__set_spec_from_plist (MFont *spec, MPlist *plist)
1284 {
1285   int i;
1286   MSymbol spec_list[MFONT_REGISTRY + 1];
1287   MSymbol registry;
1288   char *reg;
1289
1290   MFONT_INIT (spec);
1291   memset (spec_list, 0, sizeof spec_list);
1292   for (i = 0; ! MPLIST_TAIL_P (plist); i++, plist = MPLIST_NEXT (plist))
1293     {
1294       if (! MPLIST_SYMBOL_P (plist))
1295         MERROR (MERROR_FONT, Mnil);     
1296       spec_list[i] = MPLIST_SYMBOL (plist);
1297     }
1298   registry = spec_list[i - 1];
1299   if (i > 1 && registry != Mnil)
1300     {
1301       reg = MSYMBOL_NAME (registry);
1302       if (reg[0] == ':')
1303         {
1304           mfont__get_capability (registry);
1305           spec->capability = registry;
1306           registry = spec_list[i - 2];
1307           i--;
1308         }
1309     }
1310   mfont__set_property (spec, MFONT_REGISTRY, registry);
1311   for (i -= 2; i >= 0; i--)
1312     mfont__set_property (spec, i, spec_list[i]);
1313   spec->type = MFONT_TYPE_SPEC;
1314
1315   return registry;
1316 }
1317
1318
1319 MFont *
1320 mfont__select (MFrame *frame, MFont *font, int max_size)
1321 {
1322   MFontDriver *driver;
1323
1324   if (font->type == MFONT_TYPE_FAILURE)
1325     return NULL;
1326   if (font->type != MFONT_TYPE_SPEC)
1327     return font;
1328   if (font->source == MFONT_SOURCE_UNDECIDED)
1329     {
1330       if (font->file != Mnil || font->capability != Mnil)
1331         font->source = MFONT_SOURCE_FT;
1332       else if (font->property[MFONT_REGISTRY])
1333         {
1334           MSymbol registry = FONT_PROPERTY (font, MFONT_REGISTRY);
1335           char *reg = MSYMBOL_NAME (registry);
1336
1337           if (strncmp (reg, "unicode-", 8) == 0
1338               || strncmp (reg, "apple-roman", 11) == 0
1339               || (reg[0] >= '0' && reg[0] <= '9' && reg[1] == '-'))
1340             font->source = MFONT_SOURCE_FT;
1341         }
1342     }
1343   if (font->source != MFONT_SOURCE_FT)
1344     {
1345       driver = mplist_get (frame->font_driver_list, Mx);
1346       if (driver)
1347         return (driver->select) (frame, font, max_size);
1348     }
1349   driver = mplist_get (frame->font_driver_list, Mfreetype);
1350   if (! driver)
1351     return NULL;
1352   return (driver->select) (frame, font, max_size);
1353 }
1354
1355
1356 int
1357 mfont__available (MFrame *frame, MFont *font)
1358 {
1359   return -1;
1360 }
1361
1362 static int
1363 compare_font_score (const void *e1, const void *e2)
1364 {
1365   MFontScore *s1 = (MFontScore *) e1, *s2 = (MFontScore *) e2;
1366
1367   return (s1->font->for_full_width == s2->font->for_full_width
1368           ? s1->score > s2->score
1369           : s1->font->for_full_width);
1370 }
1371
1372 void
1373 mdebug_dump_font_list (MFontList *font_list)
1374 {
1375   int i;
1376
1377   for (i = 0; i < font_list->nfonts; i++)
1378     {
1379       fprintf (stderr, "%04X - ", font_list->fonts[i].score);
1380       mdebug_dump_font (font_list->fonts[i].font);
1381       fprintf (stderr, "\n");
1382     }
1383 }
1384
1385 void
1386 mfont__free_realized (MRealizedFont *rfont)
1387 {
1388   MRealizedFont *next;
1389
1390   for (; rfont; rfont = next)
1391     {
1392       next = rfont->next;
1393       M17N_OBJECT_UNREF (rfont->info);
1394       free (rfont);
1395       rfont = next;
1396     }
1397 }
1398
1399 MFontList *
1400 mfont__list (MFrame *frame, MFont *spec, MFont *request, int max_size)
1401 {
1402   MFontList *list;
1403   MSymbol id = mfont__id (spec);
1404   MPlist *pl, *p;
1405   int num, i;
1406
1407   pl = msymbol_get (id, M_font_list);
1408   if (pl)
1409     num = (int) msymbol_get (id, M_font_list_len);
1410   else
1411     {
1412       pl = mplist ();
1413       num = 0;
1414       MPLIST_DO (p, frame->font_driver_list)
1415         {
1416           if (spec->source == MFONT_SOURCE_X ? MPLIST_KEY (p) == Mx
1417               : spec->source == MFONT_SOURCE_FT ? MPLIST_KEY (p) == Mfreetype
1418               : 1)
1419             {
1420               MFontDriver *driver = MPLIST_VAL (p);
1421               num += (driver->list) (frame, pl, spec, 0);
1422             }
1423         }
1424       msymbol_put (id, M_font_list, pl);
1425       M17N_OBJECT_UNREF (pl);
1426       msymbol_put (id, M_font_list_len, (void *) num);
1427     }
1428   
1429   if (num == 0)
1430     return NULL;
1431
1432   MSTRUCT_MALLOC (list, MERROR_FONT);
1433   MTABLE_MALLOC (list->fonts, num, MERROR_FONT);
1434   for (i = 0; num > 0; num--, pl = MPLIST_NEXT (pl))
1435     {
1436       MFont *font = MPLIST_VAL (pl), *adjusted = font;
1437
1438       if (max_size == 0
1439           || font->size == 0
1440           || font->size < max_size)
1441         {
1442           list->fonts[i].font = font;
1443           if (spec == request)
1444             list->fonts[i].score = 0;
1445           else
1446             {
1447               int resize_ratio;
1448               MFont resized;
1449
1450               if (font->size > 0
1451                   && (resize_ratio = mfont_resize_ratio (font)) != 100)
1452                 {
1453                   resized = *font;
1454                   resized.size = font->size * 100 / resize_ratio;
1455                   adjusted = &resized;
1456                 }
1457               list->fonts[i].score = font_score (adjusted, request);
1458             }
1459           i++;
1460         }
1461     }
1462   if (i == 0)
1463     {
1464       free (list->fonts);
1465       free (list);
1466       return NULL;
1467     }
1468   list->nfonts = i;
1469   if (spec != request)
1470     qsort (list->fonts, i, sizeof (MFontScore), compare_font_score);
1471   list->object = *spec;
1472   mfont__merge (&list->object, request, 0);
1473   list->object.type = MFONT_TYPE_OBJECT;
1474   return list;
1475 }
1476
1477 /** Open a font specified in FONT.  */
1478
1479 MRealizedFont *
1480 mfont__open (MFrame *frame, MFont *font, MFont *spec)
1481 {
1482   MFontDriver *driver;
1483   MRealizedFont *rfont;
1484
1485   if (font->source == MFONT_SOURCE_UNDECIDED)
1486     MFATAL (MERROR_FONT);
1487   if (font->type != MFONT_TYPE_OBJECT)
1488     MFATAL (MERROR_FONT);
1489   for (rfont = MPLIST_VAL (frame->realized_font_list); rfont;
1490        rfont = rfont->next)
1491     {
1492       driver = rfont->driver;
1493       if (rfont->font == font
1494           && mplist_find_by_value (frame->font_driver_list, driver))
1495         break;
1496     }
1497
1498   if (! rfont)
1499     {
1500       driver = mplist_get (frame->font_driver_list,
1501                            font->source == MFONT_SOURCE_X ? Mx : Mfreetype);
1502       if (! driver)
1503         MFATAL (MERROR_FONT);
1504     }
1505   return (driver->open) (frame, font, spec, rfont);
1506 }
1507
1508 int
1509 mfont__has_char (MFrame *frame, MFont *font, MFont *spec, int c)
1510 {
1511   MFontEncoding *encoding;
1512   unsigned code;
1513   MFontDriver *driver;
1514
1515   if (font->source == MFONT_SOURCE_UNDECIDED)
1516     MFATAL (MERROR_FONT);
1517   encoding = (font->encoding ? font->encoding : find_encoding (font));
1518   if (! encoding->encoding_charset)
1519     return 0;
1520   if (encoding->repertory_charset)
1521     {
1522       code = ENCODE_CHAR (encoding->repertory_charset, c);
1523       return (code != MCHAR_INVALID_CODE);
1524     }
1525   code = ENCODE_CHAR (encoding->encoding_charset, c);
1526   if (code == MCHAR_INVALID_CODE)
1527     return 0;
1528   if (font->type == MFONT_TYPE_REALIZED)
1529     driver = ((MRealizedFont *) font)->driver;
1530   else
1531     {
1532       driver = mplist_get (frame->font_driver_list,
1533                            font->source == MFONT_SOURCE_X ? Mx : Mfreetype);
1534       if (! driver)
1535         MFATAL (MERROR_FONT);
1536     }
1537   return (driver->has_char) (frame, font, spec, c, code);
1538 }
1539
1540 unsigned
1541 mfont__encode_char (MFrame *frame, MFont *font, MFont *spec, int c)
1542 {
1543   MFontEncoding *encoding;
1544   unsigned code;
1545   MFontDriver *driver;
1546
1547   if (font->source == MFONT_SOURCE_UNDECIDED)
1548     MFATAL (MERROR_FONT);
1549   encoding = (font->encoding ? font->encoding : find_encoding (font));
1550   if (! encoding->encoding_charset)
1551     return MCHAR_INVALID_CODE;
1552   if (font->source == MFONT_SOURCE_X && encoding->repertory_charset)
1553     return (ENCODE_CHAR (encoding->repertory_charset, c));
1554   code = ENCODE_CHAR (encoding->encoding_charset, c);
1555   if (code == MCHAR_INVALID_CODE)
1556     return MCHAR_INVALID_CODE;
1557   if (font->type == MFONT_TYPE_REALIZED)
1558     driver = ((MRealizedFont *) font)->driver;
1559   else
1560     {
1561       driver = mplist_get (frame->font_driver_list,
1562                            font->source == MFONT_SOURCE_X ? Mx : Mfreetype);
1563       if (! driver)
1564         MFATAL (MERROR_FONT);
1565     }
1566   return (driver->encode_char) (frame, font, spec, code);
1567 }
1568
1569 void
1570 mfont__get_metric (MGlyphString *gstring, int from, int to)
1571 {
1572   MGlyph *from_g = MGLYPH (from), *to_g = MGLYPH (to), *g;
1573   MRealizedFont *rfont = from_g->rface->rfont;
1574
1575   for (g = from_g; g != to_g; g++)
1576     if (g->rface->rfont != rfont)
1577       {
1578         int idx = GLYPH_INDEX (g);
1579
1580         (rfont->driver->find_metric) (rfont, gstring, from, idx);
1581         from_g = g;
1582         rfont = g->rface->rfont;
1583         from = idx;
1584       }
1585   (rfont->driver->find_metric) (rfont, gstring, from, GLYPH_INDEX (g));
1586 }
1587
1588
1589 /* KEY <= MFONT_REGISTRY */
1590
1591 void
1592 mfont__set_property (MFont *font, enum MFontProperty key, MSymbol val)
1593 {
1594   int numeric;
1595
1596   if (val == Mnil)
1597     numeric = 0;
1598   else
1599     {
1600       numeric = FONT_PROPERTY_NUMERIC (val, key);
1601       if (! numeric)
1602         {
1603           numeric = mfont__property_table[key].used;
1604           MLIST_APPEND1 (mfont__property_table + key, names, val, MERROR_FONT);
1605           SET_FONT_PROPERTY_NUMERIC (val, key, numeric);
1606         }
1607     }
1608   font->property[key] = numeric;
1609 }
1610
1611 int
1612 mfont__parse_name_into_font (const char *name, MSymbol format, MFont *font)
1613 {
1614   int result = -1;
1615
1616   if (format == Mx || format == Mnil)
1617     result = xlfd_parse_name (name, font);
1618 #ifdef HAVE_FONTCONFIG
1619   if (format == Mfontconfig || (result < 0 && format == Mnil))
1620     result = mfont__ft_parse_name (name, font);
1621 #endif /* HAVE_FONTCONFIG */
1622   return result;
1623 }
1624
1625 MPlist *
1626 mfont__encoding_list (void)
1627 {
1628   if (! font_encoding_list)
1629     load_font_encoding_table ();
1630   return font_encoding_list;
1631 }
1632
1633 static void
1634 free_font_capability (void *object)
1635 {
1636   MFontCapability *cap = object;
1637   
1638   if (cap->lang)
1639     free (cap->lang);
1640   if (cap->script)
1641     {
1642       int i;
1643       for (i = 0; i < MFONT_OTT_MAX; i++)
1644         {
1645           if (cap->features[i].str)
1646             free (cap->features[i].str);
1647           if (cap->features[i].tags)
1648             free (cap->features[i].tags);
1649         }
1650     }
1651   free (cap);
1652 }
1653
1654 MFontCapability *
1655 mfont__get_capability (MSymbol sym)
1656 {
1657   MFontCapability *cap = msymbol_get (sym, M_font_capability);
1658   char *str, *p, *endp;
1659
1660   if (cap)
1661     return cap;
1662   str = MSYMBOL_NAME (sym);
1663   if (str[0] != ':')
1664     return NULL;
1665   M17N_OBJECT (cap, free_font_capability, MERROR_FONT);
1666   msymbol_put (sym, M_font_capability, cap);
1667   M17N_OBJECT_UNREF (cap);
1668   endp = str + MSYMBOL_NAMELEN (sym);
1669   while (str < endp)
1670     {
1671       if (*str++ != ':')
1672         continue;
1673       if (str[0] == 'o' && str[1] == 't' && str[2] == 'f' && str[3] == '=')
1674         {
1675           int i;
1676
1677           str += 4;
1678           for (i = 0, p = str; i < 4 && p < endp; i++, p++);
1679           if (i < 4)
1680             break;
1681           cap->script_tag = OTF_tag (str);
1682           cap->script = find_script_from_otf_tag (cap->script_tag);
1683           if (*p == '/')
1684             {
1685               for (i = 0, str = ++p; i < 4 && p < endp; i++, p++);
1686               if (i < 4)
1687                 {
1688                   cap->script = Mnil;
1689                   break;
1690                 }
1691               cap->langsys_tag = OTF_tag (str);
1692             }
1693           else
1694             cap->langsys_tag = 0;
1695
1696           for (i = 0; i < MFONT_OTT_MAX; i++)
1697             cap->features[i].nfeatures = -1;
1698
1699           while (*p == '=' || *p == '+')
1700             {
1701               int idx = *p == '=' ? MFONT_OTT_GSUB : MFONT_OTT_GPOS;
1702
1703               str = ++p;
1704               while (p < endp && *p != '+') p++;
1705               if (str < p)
1706                 {
1707                   int n;
1708                   /* We never have more than (p - str) tags.  */
1709                   OTF_Tag *tags = alloca (sizeof (OTF_Tag) * (p - str));
1710                   char *p0;
1711
1712                   cap->features[idx].str = malloc (p - str + 1);
1713                   for (i = n = 0, p0 = str; str + i < p; i++)
1714                     {
1715                       cap->features[idx].str[i] = str[i];
1716                       if (str[i] == ',' || str + i + 1 == p)
1717                         {
1718                           if (*p0 == '*')
1719                             tags[n] = 0;
1720                           else if (*p0 == '~')
1721                             tags[n] = OTF_tag (p0 + 1) | 0x80000000;
1722                           else
1723                             tags[n] = OTF_tag (p0);
1724                           n++;
1725                           p0 = str + i + 1;
1726                         }
1727                     }
1728                   cap->features[idx].str[i] = '\0';
1729                   cap->features[idx].nfeatures = n;
1730                   if (n > 0)
1731                     {
1732                       int size = sizeof (OTF_Tag) * n;
1733
1734                       cap->features[idx].tags = malloc (size);
1735                       memcpy (cap->features[idx].tags, tags, size);
1736                     }
1737                 }
1738               else
1739                 {
1740                   cap->features[idx].str = NULL;
1741                   cap->features[idx].nfeatures = 0;
1742                 }
1743             }
1744
1745           for (i = 0; i < MFONT_OTT_MAX; i++)
1746             if (cap->features[i].nfeatures < 0)
1747               {
1748                 cap->features[i].str = strdup ("*");
1749                 cap->features[i].nfeatures = 1;
1750                 cap->features[i].tags = malloc (sizeof (OTF_Tag));
1751                 cap->features[i].tags[0] = 0;
1752               }
1753           str = p;
1754         }
1755       else if (str[0] == 'l' && str[1] == 'a' && str[2] == 'n' && str[3] == 'g'
1756           && str[4] == '=')
1757         {
1758           int count;
1759
1760           str += 5;
1761           for (p = str, count = 2; p < endp && *p != ':'; p++)
1762             if (*p == ',')
1763               count++;
1764           MTABLE_MALLOC (cap->lang, count, MERROR_FONT);
1765           for (p = str, count = 0; p < endp && *p != ':'; p++)
1766             if (*p == ',')
1767               {
1768                 MSymbol lang = msymbol__with_len (str, p - str), sym;
1769
1770                 if (msymbol_get (lang, Miso639_2))
1771                   cap->lang[count++] = lang;
1772                 else if ((sym = msymbol_get (lang, Miso639_1)) != Mnil)
1773                   cap->lang[count++] = sym;
1774                 else if (msymbol_get (lang, Mlanguage))
1775                   cap->lang[count++] = lang;
1776                 str = p + 1;
1777               }
1778           if (str < p)
1779             cap->lang[count++] = msymbol__with_len (str, p - str);
1780           cap->lang[count] = Mnil;
1781           str = p;
1782         }
1783       else if (str[0] == 's' && str[1] == 'c' && str[2] == 'r' && str[3] == 'i'
1784                && str[4] == 'p' && str[5] == 't' && str[6] == '=')
1785         {
1786           str += 7;
1787           for (p = str; p < endp && *p != ':'; p++);
1788           if (str < p)
1789             cap->script = msymbol__with_len (str, p - str);
1790           str = p;
1791         }
1792     }
1793   return cap;
1794 }
1795
1796 int
1797 mfont__check_capability (MRealizedFont *rfont, MSymbol capability)
1798 {
1799   return (rfont->driver->check_capability (rfont, capability));
1800 }
1801
1802
1803 /*** @} */
1804 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
1805
1806 \f
1807
1808 /* External API */
1809
1810 /*** @addtogroup m17nFont */
1811 /*** @{ */
1812 /*=*/
1813
1814 /***en @name Variables: Keys of font property.  */
1815 /***ja @name ÊÑ¿ô: ¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤ò»ØÄꤹ¤ëÄêµÁºÑ¤ß¥·¥ó¥Ü¥ë */
1816 /*** @{ */
1817 /*=*/
1818
1819 /***en
1820     @brief Key of font property specifying foundry.
1821
1822     The variable #Mfoundry is a symbol of name <tt>"foundry"</tt> and
1823     is used as a key of font property and face property.  The property
1824     value must be a symbol whose name is a foundry name of a font.  */
1825 /***ja
1826     @brief ³«È¯¸µ¤ò»ØÄꤹ¤ë¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼.
1827     
1828     ÊÑ¿ô #Mfoundry ¤Ï <tt>"fonudry"</tt> 
1829     ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤È¥Õ¥§¡¼¥¹¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼¤È¤·¤ÆÍѤ¤¤é¤ì¤ë¡£
1830     Ãͤϡ¢¥Õ¥©¥ó¥È¤Î³«È¯¸µÌ¾¤ò̾Á°¤È¤·¤Æ»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£    */
1831
1832 MSymbol Mfoundry;
1833
1834 /***en
1835     @brief Key of font property specifying family.
1836
1837     The variable #Mfamily is a symbol of name <tt>"family"</tt> and is
1838     used as a key of font property and face property.  The property
1839     value must be a symbol whose name is a family name of a font.  */ 
1840 /***ja
1841     @brief ¥Õ¥¡¥ß¥ê¤ò»ØÄꤹ¤ë¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼.
1842     
1843     ÊÑ¿ô #Mfamily ¤Ï <tt>"family"</tt> 
1844     ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤È¥Õ¥§¡¼¥¹¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼¤È¤·¤ÆÍѤ¤¤é¤ì¤ë¡£
1845     Ãͤϡ¢¥Õ¥©¥ó¥È¤Î¥Õ¥¡¥ß¥ê̾¤ò̾Á°¤È¤·¤Æ»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£    */
1846
1847 MSymbol Mfamily;
1848
1849 /***en
1850     @brief Key of font property specifying weight.
1851
1852     The variable #Mweight is a symbol of name <tt>"weight"</tt> and is
1853     used as a key of font property and face property.  The property
1854     value must be a symbol whose name is a weight name of a font (e.g
1855     "medium", "bold").  */ 
1856 /***ja
1857     @brief ÂÀ¤µ¤ò»ØÄꤹ¤ë¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼.
1858     
1859     ÊÑ¿ô #Mweight ¤Ï <tt>"weight"</tt> 
1860     ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤È¥Õ¥§¡¼¥¹¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼¤È¤·¤ÆÍѤ¤¤é¤ì¤ë¡£
1861     Ãͤϡ¢¥Õ¥©¥ó¥È¤ÎÂÀ¤µÌ¾ ( "medium", "bold" Åù) ¤ò̾Á°¤È¤·¤Æ»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£    */
1862
1863 MSymbol Mweight;
1864
1865 /***en
1866     @brief Key of font property specifying style.
1867
1868     The variable #Mstyle is a symbol of name <tt>"style"</tt> and is
1869     used as a key of font property and face property.  The property
1870     value must be a symbol whose name is a style name of a font (e.g
1871     "r", "i", "o").  */ 
1872 /***ja
1873     @brief ¥¹¥¿¥¤¥ë¤ò»ØÄꤹ¤ë¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼.
1874     
1875     ÊÑ¿ô #Mstyle ¤Ï <tt>"style"</tt> 
1876     ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤È¥Õ¥§¡¼¥¹¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼¤È¤·¤ÆÍѤ¤¤é¤ì¤ë¡£
1877     Ãͤϡ¢¥Õ¥©¥ó¥È¤Î¥¹¥¿¥¤¥ë̾ ("r", "i", "o" Åù)¤ò̾Á°¤È¤·¤Æ»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£    */
1878
1879 MSymbol Mstyle;
1880
1881 /***en
1882     @brief Key of font property specifying stretch.
1883
1884     The variable #Mstretch is a symbol of name <tt>"stretch"</tt> and
1885     is used as a key of font property and face property.  The property
1886     value must be a symbol whose name is a stretch name of a font (e.g
1887     "normal", "condensed").  */ 
1888 /***ja
1889     @brief Éý¤ò»ØÄꤹ¤ë¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼.
1890     
1891     ÊÑ¿ô #Mstretch ¤Ï <tt>"stretch"</tt> 
1892     ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤È¥Õ¥§¡¼¥¹¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼¤È¤·¤ÆÍѤ¤¤é¤ì¤ë¡£
1893     Ãͤϡ¢¥Õ¥©¥ó¥È¤Îʸ»úÉý̾ ( "normal", "condensed" Åù)¤ò̾Á°¤È¤·¤Æ»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£    */
1894
1895 MSymbol Mstretch;
1896
1897 /***en
1898     @brief Key of font property specifying additional style.
1899
1900     The variable #Madstyle is a symbol of name <tt>"adstyle"</tt> and
1901     is used as a key of font property and face property.  The property
1902     value must be a symbol whose name is an additional style name of a
1903     font (e.g "serif", "", "sans").  */ 
1904 /***ja
1905     @brief adstyle ¤ò»ØÄꤹ¤ë¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼.
1906     
1907     ÊÑ¿ô #Madstyle ¤Ï <tt>"adstyle"</tt> 
1908     ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤È¥Õ¥§¡¼¥¹¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼¤È¤·¤ÆÍѤ¤¤é¤ì¤ë¡£
1909     Ãͤϡ¢¥Õ¥©¥ó¥È¤Î adstyle Ì¾("serif", "", "sans" Åù)¤ò̾Á°¤È¤·¤Æ»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£    */
1910
1911 MSymbol Madstyle;
1912
1913 /***en
1914     @brief Key of font property specifying spacing.
1915
1916     The variable #Madstyle is a symbol of name <tt>"spacing"</tt> and
1917     is used as a key of font property.  The property value must be a
1918     symbol whose name specifies the spacing of a font (e.g "p" for
1919     proportional, "m" for monospaced).  */ 
1920 /***ja
1921     @brief spacing ¤ò»ØÄꤹ¤ë¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼.
1922     
1923     ÊÑ¿ô #Mspacing ¤Ï <tt>"spacing"</tt> ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢
1924     ¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼¤È¤·¤ÆÍѤ¤¤é¤ì¤ë¡£Ãͤϡ¢¥Õ¥©¥ó¥È¤Î spacing
1925     ÆÃÀ­¤ò¼¨¤¹Ì¾Á° ("p", "m" Åù)¤ò»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£  */
1926
1927 MSymbol Mspacing;
1928
1929 /***en
1930     @brief Key of font property specifying registry.
1931
1932     The variable #Mregistry is a symbol of name <tt>"registry"</tt>
1933     and is used as a key of font property.  The property value must be
1934     a symbol whose name is a registry name a font registry
1935     (e.g. "iso8859-1", "jisx0208.1983-0").  */ 
1936 /***ja
1937     @brief ¥ì¥¸¥¹¥È¥ê¤ò»ØÄꤹ¤ë¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼.
1938     
1939     ÊÑ¿ô #Mregistry ¤Ï <tt>"registry"</tt> 
1940     ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤È¥Õ¥§¡¼¥¹¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼¤È¤·¤ÆÍѤ¤¤é¤ì¤ë¡£
1941     Ãͤϡ¢¥Õ¥©¥ó¥È¤Î¥ì¥¸¥¹¥È¥ê̾ ( "iso8859-1", "jisx0208.1983-0" 
1942     Åù) ¤ò̾Á°¤È¤·¤Æ»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£    */
1943
1944 MSymbol Mregistry;
1945
1946 /***en
1947     @brief Key of font property specifying size.
1948
1949     The variable #Msize is a symbol of name <tt>"size"</tt> and is
1950     used as a key of font property and face property.  The property
1951     value must be an integer specifying a font design size in the unit
1952     of 1/10 point (on 100 dpi display).  */ 
1953 /***ja
1954     @brief ¥µ¥¤¥º¤ò»ØÄꤹ¤ë¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼.
1955     
1956     ÊÑ¿ô #Msize ¤Ï <tt>"size"</tt> 
1957     ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤È¥Õ¥§¡¼¥¹¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼¤È¤·¤ÆÍѤ¤¤é¤ì¤ë¡£Ãͤϡ¢
1958     100 dpi ¤Î¥Ç¥£¥¹¥×¥ì¥¤¾å¤Ç¤Î¥Õ¥©¥ó¥È¤Î¥Ç¥¶¥¤¥ó¥µ¥¤¥º¤ò 1/10 
1959     ¥Ý¥¤¥ó¥Èñ°Ì¤Ç¼¨¤¹À°¿ôÃͤǤ¢¤ë¡£
1960     */
1961
1962 MSymbol Msize;
1963
1964 /***en
1965     @brief Key of font property specifying file name.
1966
1967     The variable #Mfontfile is a symbol of name <tt>"fontfile"</tt>
1968     and is used as a key of font property.  The property value must be
1969     a symbol whose name is a font file name.  */ 
1970 /***ja
1971     @brief ¥Õ¥©¥ó¥È¥Õ¥¡¥¤¥ë¤ò»ØÄꤹ¤ë¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼.
1972     
1973     ÊÑ¿ô #Mfontfile ¤Ï <tt>"fontfile"</tt> ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢
1974     ¤ê¡¢¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼¤È¤·¤ÆÍѤ¤¤é¤ì¤ë¡£Ãͤϡ¢¥Õ¥©¥ó¥È¥Õ¥¡¥¤
1975     ¥ë̾¤ò̾Á°¤È¤·¤Æ»ý¤Ä¤È¤¹¤ë¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£ */
1976
1977 MSymbol Mfontfile;
1978
1979 /***en
1980     @brief Key of font property specifying resolution.
1981
1982     The variable #Mresolution is a symbol of name <tt>"resolution"</tt> and
1983     is used as a key of font property and face property.  The property
1984     value must be an integer to specifying a font resolution in the
1985     unit of dots per inch (dpi).  */ 
1986 /***ja
1987     @brief ²òÁüÅÙ¤ò»ØÄꤹ¤ë¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼.
1988     
1989     ÊÑ¿ô #Mresolution ¤Ï <tt>"resolution"</tt> 
1990     ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤È¥Õ¥§¡¼¥¹¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼¤È¤·¤ÆÍѤ¤¤é¤ì¤ë¡£
1991     Ãͤϡ¢¥Õ¥©¥ó¥È¤Î²òÁüÅÙ¤ò dots per inch (dpi) Ã±°Ì¤Ç¼¨¤¹À°¿ôÃͤǤ¢¤ë¡£    */
1992
1993 MSymbol Mresolution;
1994
1995 /***en
1996     @brief Key of font property specifying max advance width.
1997
1998     The variable #Mmax_advance is a symbol of name
1999     <tt>"max-advance"</tt> and is used as a key of font property.  The
2000     property value must be an integer specifying a font's max advance
2001     value by pixels.  */ 
2002
2003 MSymbol Mmax_advance;
2004
2005
2006 /***en
2007     @brief Symbol of name "fontconfig".
2008
2009     The variable #Mfontconfig is to be used as an argument of the
2010     functions mfont_parse_name () and mfont_unparse_name ().  */
2011 /***ja
2012     @brief "fontconfig" ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë.
2013
2014     ÊÑ¿ô #Mfontconfig ¤Ï´Ø¿ô mfont_parse_name () ¤È mfont_unparse_name ()
2015     ¤Î°ú¿ô¤È¤·¤ÆÍѤ¤¤é¤ì¤ë¡£  */
2016
2017 MSymbol Mfontconfig;
2018
2019 /***en
2020     @brief Symbol of name "x".
2021
2022     The variable #Mx is to be used for a value of <type> member of the
2023     structure #MDrawGlyph to specify the type of <fontp> member is
2024     actually (XFontStruct *).  */
2025 /***ja
2026     @brief "x" ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë.
2027
2028     ÊÑ¿ô #Mx ¤Ï¹½Â¤ #MDrawGlyph ¤Î¥á¥ó¥Ð <type> 
2029     ¤ÎÃͤȤ·¤ÆÍѤ¤¤é¤ì¡¢¥á¥ó¥Ð <fontp> ¤Î·¿¤¬¼ÂºÝ¤Ë¤Ï (XFontStruct *) ¤Ç¤¢¤ë¤³¤È¤òɽ¤¹.  */
2030
2031 MSymbol Mx;
2032
2033 /***en
2034     @brief Symbol of name "freetype".
2035
2036     The variable #Mfreetype is to be used for a value of <type> member
2037     of the structure #MDrawGlyph to specify the type of <fontp> member
2038     is actually FT_Face.  */
2039 /***ja
2040     @brief "freetype" ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë.
2041
2042     ÊÑ¿ô #Mfreetype ¤Ï¹½Â¤ #MDrawGlyph ¤Î¥á¥ó¥Ð <type> 
2043     ¤ÎÃͤȤ·¤ÆÍѤ¤¤é¤ì¡¢¥á¥ó¥Ð <fontp> ¤Î·¿¤¬¼ÂºÝ¤Ë¤Ï FT_Face ¤Ç¤¢¤ë¤³¤È¤òɽ¤¹¡£  */
2044
2045 MSymbol Mfreetype;
2046
2047 /***en
2048     @brief Symbol of name "xft".
2049
2050     The variable #Mxft is to be used for a value of <type> member of the
2051     structure #MDrawGlyph to specify the type of <fontp> member
2052     is actually (XftFont *).  */
2053 /***ja
2054     @brief  "xft" ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë.
2055
2056     ÊÑ¿ô #Mxft ¤Ï¹½Â¤ #MDrawGlyph ¤Î¥á¥ó¥Ð <type> 
2057     ¤ÎÃͤȤ·¤ÆÍѤ¤¤é¤ì¡¢¥á¥ó¥Ð <fontp> ¤Î·¿¤¬¼ÂºÝ¤Ë¤Ï (XftFont *) ¤Ç¤¢¤ë¤³¤È¤òɽ¤¹¡£  */
2058
2059 MSymbol Mxft;
2060
2061 /*=*/
2062 /*** @} */
2063 /*=*/
2064
2065 /***en
2066     @brief List of font files and directories that contain font files.
2067
2068     The variable @c mfont_freetype_path is a plist of FreeType font
2069     files and directories that contain FreeType font files.  Key of
2070     the element is @c Mstring, and the value is a string that
2071     represents a font file or a directory.
2072
2073     The macro M17N_INIT () sets up this variable to contain the
2074     sub-directory "fonts" of the m17n database and the environment
2075     variable "M17NDIR".  The first call of mframe () creates the
2076     internal list of the actually available fonts from this variable.
2077     Thus, an application program, if necessary, must modify the
2078     variable before calling mframe ().  If it is going to add a new
2079     element, value must be a string that can be safely freed.
2080
2081     If the m17n library is not configured to use the FreeType library,
2082     this variable is not used.  */
2083 /***ja
2084     @brief ¥Õ¥©¥ó¥È¥Õ¥¡¥¤¥ë¤È¥Õ¥©¥ó¥È¥Õ¥¡¥¤¥ë¤ò´Þ¤à¥Ç¥£¥ì¥¯¥È¥ê¤Î¥ê¥¹¥È.
2085
2086     ÊÑ¿ô @c mfont_freetype_path ¤Ï¡¢¥Õ¥©¥ó¥È¥Õ¥¡¥¤¥ë¤È¥Õ¥©¥ó¥È¥Õ¥¡¥¤¥ë¤ò´Þ¤à¥Ç¥£¥ì¥¯¥È¥ê¤Î 
2087     plist ¤Ç¤¢¤ë¡£³ÆÍ×ÁǤΥ­¡¼¤Ï @c Mstring 
2088     ¤Ç¤¢¤ê¡¢Ãͤϥե©¥ó¥È¥Õ¥¡¥¤¥ë¤«¥Ç¥£¥ì¥¯¥È¥ê¤ò¼¨¤¹Ê¸»úÎó¤Ç¤¢¤ë¡£
2089
2090     ¥Þ¥¯¥í M17N_INIT () ¤Ë¤è¤Ã¤Æ¡¢¤³¤ÎÊÑ¿ô¤Ï m17n ¥Ç¡¼¥¿¥Ù¡¼¥¹¤È´Ä¶­ÊÑ¿ô 
2091     "M17NDIR" ÁÐÊý¤Î¥µ¥Ö¥Ç¥£¥ì¥¯¥È¥ê "fonts" ¤ò´Þ¤à¤è¤¦¤ËÀßÄꤵ¤ì¤ë¡£
2092     mframe () ¤ÎºÇ½é¤Î¸Æ¤Ó½Ð¤·¤ÎºÝ¤Ë¡¢¤³¤ÎÊÑ¿ô¤«¤é¼ÂºÝ¤Ë»ÈÍѤǤ­¤ë¥Õ¥©¥ó¥È¤ÎÆâÉô¥ê¥¹¥È¤¬ºî¤é¤ì¤ë¡£
2093     ¤½¤³¤Ç¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥à¤Ï¡¢mframe () 
2094     ¤ò¸Æ¤ÖÁ°¤Ë¡ÊɬÍפʤé¤Ð¡Ë¤³¤ÎÊÑ¿ô¤òÊѹ¹¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
2095     ¿·¤·¤¤Í×ÁǤòÄɲ乤ë¾ì¹ç¤Ë¤Ï¡¢¤½¤ÎÃͤϰÂÁ´¤Ë³«Êü¤Ç¤­¤ëʸ»úÎó¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
2096
2097     m17n ¥é¥¤¥Ö¥é¥ê¤¬ FreeType ¥é¥¤¥Ö¥é¥ê¤ò»È¤¦¤è¤¦¤ËÀßÄꤵ¤ì¤Æ¤Ê¤¤¾ì¹ç¤Ë¤Ï¡¢¤³¤ÎÊÑ¿ô¤ÏÍѤ¤¤é¤ì¤Ê¤¤¡£ */
2098
2099 MPlist *mfont_freetype_path;
2100
2101 /*=*/
2102
2103 /***en
2104     @brief Create a new font.
2105
2106     The mfont () function creates a new font object that has no
2107     property.
2108
2109     @return
2110     This function returns a pointer to the created font object.  */
2111 /***ja
2112     @brief ¿·¤·¤¤¥Õ¥©¥ó¥È¤òºî¤ë.
2113
2114     ´Ø¿ô mfont () ¤Ï¥×¥í¥Ñ¥Æ¥£¤ò°ìÀÚ»ý¤¿¤Ê¤¤¿·¤·¤¤¥Õ¥©¥ó¥È¤ò¥ª¥Ö¥¸¥§¥¯¥È¤òºî¤ë¡£
2115
2116     @return
2117     ¤³¤Î´Ø¿ô¤Ïºî¤Ã¤¿¥Õ¥©¥ó¥È¥ª¥Ö¥¸¥§¥¯¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£  */
2118
2119 MFont *
2120 mfont ()
2121 {
2122   MFont *font;
2123
2124   MSTRUCT_CALLOC (font, MERROR_FONT);
2125   return font;
2126 }
2127
2128 /*=*/
2129
2130 /***en
2131     @brief Create a font by parsing a fontname.
2132
2133     The mfont_parse_name () function creates a new font object.  The
2134     properties are extracted fontname $NAME.
2135
2136     $FORMAT specifies the format of $NAME.  If $FORMAT is #Mx, $NAME
2137     is parsed as XLFD (X Logical Font Description).  If $FORMAT is
2138     #Mfontconfig, $NAME is parsed as Fontconfig's textual
2139     representation of font.  If $FORMAT is #Mnil, $NAME is at first
2140     parsed as XLFD, and it it fails, parsed as Fontconfig's
2141     representation.
2142
2143     @return
2144     If the operation was successful, this function returns a pointer
2145     to the created font.  Otherwise it returns @c NULL.  */
2146
2147 /***ja
2148     @brief ¥Õ¥©¥ó¥È̾¤«¤é¥Õ¥©¥ó¥È¤òºî¤ë.
2149
2150     ´Ø¿ô mfont_parse_name () ¤Ï¡¢¥Õ¥©¥ó¥È̾ 
2151     $NAME ¤«¤é¼è¤ê½Ð¤µ¤ì¤¿¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ä¡¢¿·¤·¤¤¥Õ¥©¥ó¥È¥ª¥Ö¥¸¥§¥¯¥È¤òºî¤ë¡£
2152
2153     $FORMAT ¤Ï $NAME ¤Î¥Õ¥©¡¼¥Þ¥Ã¥È¤ò»ØÄꤹ¤ë¡£$FORMAT ¤¬ #Mx ¤Ç¤¢¤ì¤Ð¡¢
2154     $NAME ¤Ï XLFD (X Logical Font Description) ¤Ë½¾¤Ã¤Æ²òÀϤµ¤ì¤ë¡£
2155     $FORMAT ¤¬ #Mfontconfig ¤Ç¤¢¤ì¤Ð $NAME ¤Ï Fontfonfig 
2156     ¤Î¥Õ¥©¥ó¥È¥Æ¥­¥¹¥Èɽ¸½¤Ë½¾¤Ã¤Æ²òÀϤµ¤ì¤ë¡£$FORMAT ¤¬ #Mnil ¤Ç¤¢¤ì¤Ð¡¢¤Þ¤º XLFD 
2157     ¤Ë½¾¤Ã¤Æ²òÀϤµ¤ì¡¢¤½¤ì¤Ë¼ºÇÔ¤·¤¿¤é Fontconfig ¤Ë½¾¤Ã¤Æ²òÀϤµ¤ì¤ë¡£
2158
2159     @return
2160     ½èÍý¤¬À®¸ù¤¹¤ì¤Ð mfont_parse_name () 
2161     ¤Ï¿·¤·¤¯ºî¤é¤ì¤¿¥Õ¥©¥ó¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð @c NULL ¤òÊÖ¤¹¡£  */
2162
2163 MFont *
2164 mfont_parse_name (const char *name, MSymbol format)
2165 {
2166   MFont template, *font;
2167   
2168   MFONT_INIT (&template);
2169   if (mfont__parse_name_into_font (name, format, &template) < 0)
2170     MERROR (MERROR_FONT, NULL);
2171   MSTRUCT_CALLOC (font, MERROR_FONT);
2172   *font = template;
2173   return font;
2174 }
2175
2176 /*=*/
2177
2178 /***en
2179     @brief Create a fontname from a font.
2180
2181     The mfont_unparse_name () function creates a fontname string
2182     from font $FONT according to $FORMAT.
2183
2184     $FORMAT must be #Mx or #Mfontconfig.  If it is #Mx, the fontname
2185     is in XLFD (X Logical Font Description) format.  If it is
2186     #Mfontconfig, the fontname is in the style of Fontconfig's text
2187     representation.
2188
2189     @return
2190     This function returns a newly allocated fontname string, which is
2191     not freed unless the user explicitly does so by free ().  */
2192
2193 /***ja
2194     @brief ¥Õ¥©¥ó¥È¤«¤é¥Õ¥©¥ó¥È̾¤òºî¤ë.
2195
2196     ´Ø¿ô mfont_unparse_name () ¤Ï ¥Õ¥©¥ó¥È̾¤Îʸ»úÎó¤ò¥Õ¥©¥ó¥È $FONT 
2197     ¤ò¸µ¤Ë$FORMAT ¤Ë½¾¤Ã¤Æºî¤ë¡£
2198
2199     $FORMAT ¤Ï #Mx ¤Þ¤¿¤Ï #Mfontconfig ¤Ç¤¢¤ë¡£
2200     #Mx ¤Ê¤é¤Ð¥Õ¥©¥ó¥È̾¤Ï XLFD (X Logical Font Description) ¤Ë½¾¤¦¡£
2201     #Mfontconfig ¤Ê¤é¤Ð¥Õ¥©¥ó¥È̾¤Ï Fontconfig ¤Î¥Õ¥©¥ó¥È¥Æ¥­¥¹¥Èɽ¸½¤Ë½¾¤¦¡£
2202
2203     @return 
2204     ¤³¤Î´Ø¿ô¤Ï¿·¤¿¤Ë¥¢¥í¥±¡¼¥È¤·¤¿¥Õ¥©¥ó¥È̾¤Îʸ»úÎó¤òÊÖ¤¹¡£Ê¸»úÎó¤Ï¡¢¥æ¡¼¥¶¤¬
2205     free () ¤Ë¤è¤Ã¤ÆÌÀ¼¨Åª¤Ë²òÊü¤·¤Ê¤¤¸Â¤ê²òÊü¤µ¤ì¤Ê¤¤¡£  */
2206
2207 char *
2208 mfont_unparse_name (MFont *font, MSymbol format)
2209 {
2210   char *name;
2211
2212   if (format == Mx)
2213     name = xlfd_unparse_name (font, 1);
2214 #ifdef HAVE_FONTCONFIG
2215   else if (format == Mfontconfig)
2216     name = mfont__ft_unparse_name (font);
2217
2218 #endif /* HAVE_FONTCONFIG */
2219   else
2220     MERROR (MERROR_FONT, NULL);
2221   return name;
2222 }
2223
2224 /*=*/
2225
2226 /***en
2227     @brief Make a copy of a font.
2228
2229     The mfont_copy () function returns a new copy of font $FONT.  */
2230 /***ja
2231     @brief ¥Õ¥©¥ó¥È¤Î¥³¥Ô¡¼¤òºî¤ë.
2232
2233     ´Ø¿ô Mfont_copy () ¤Ï¥Õ¥©¥ó¥È $FONT ¤Î¥³¥Ô¡¼¤òºî¤ê¡¢¤½¤ì¤òÊÖ¤¹¡£ */
2234
2235 MFont *
2236 mfont_copy (MFont *font)
2237 {
2238   MFont *copy;
2239
2240   MSTRUCT_MALLOC (copy, MERROR_FONT);
2241   *copy = *font;
2242   return copy;
2243 }
2244
2245 /*=*/
2246
2247 /***en
2248     @brief Get a property value of a font.
2249
2250     The mfont_get_prop () function gets the value of $KEY property of
2251     font $FONT.  $KEY must be one of the following symbols:
2252
2253         @c Mfoundry, @c Mfamily, @c Mweight, @c Mstyle, @c Mstretch,
2254         @c Madstyle, @c Mregistry, @c Msize, @c Mresolution, @c Mspacing.
2255
2256     If $FONT is a return value of mfont_find (), $KEY can also be one
2257     of the following symbols:
2258
2259         #Mfont_ascent, #Mfont_descent, #Mmax_advance.
2260
2261     @return If $KEY is @c Mfoundry, @c Mfamily, @c Mweight, @c Mstyle,
2262     @c Mstretch, @c Madstyle, @c Mregistry, or @c Mspacing, this
2263     function returns the corresponding value as a symbol.  If the font
2264     does not have $KEY property, it returns @c Mnil.  If $KEY is @c
2265     Msize, @c Mresolution, #Mfont_ascent, Mfont_descent, or
2266     #Mmax_advance, this function returns the corresponding value as an
2267     integer.  If the font does not have $KEY property, it returns 0.
2268     If $KEY is something else, it returns @c NULL and assigns an error
2269     code to the external variable #merror_code.  */
2270  
2271 /***ja
2272     @brief ¥Õ¥©¥ó¥È¤Î¥×¥í¥Ñ¥Æ¥£¤ÎÃͤòÆÀ¤ë.
2273
2274     ´Ø¿ô mfont_get_prop () ¤Ï¥Õ¥©¥ó¥È $FONT ¤Î¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥­¡¼¤¬
2275     $KEY ¤Ç¤¢¤ë¤â¤Î¤ÎÃͤòÊÖ¤¹¡£$KEY ¤Ï°Ê²¼¤Î¥·¥ó¥Ü¥ë¤Î¤¤¤º¤ì¤«¤Ç¤Ê¤±¤ì
2276     ¤Ð¤Ê¤é¤Ê¤¤¡£
2277
2278         @c Mfoundry, @c Mfamily, @c Mweight, @c Mstyle, @c Mstretch,
2279         @c Madstyle, @c Mregistry, @c Msize, @c Mresolution, @c Mspacing.
2280
2281     @return $KEY ¤¬ @c Mfoundry, @c Mfamily, @c Mweight, @c Mstyle, @c
2282     Mstretch, @c Madstyle, @c Mregistry, @c Mspacing ¤Î¤¤¤º¤ì¤«¤Ç¤¢¤ì¤Ð¡¢
2283     ÁêÅö¤¹¤ëÃͤò¥·¥ó¥Ü¥ë¤È¤·¤ÆÊÖ¤¹¡£¥Õ¥©¥ó¥È¤¬¤½¤Î¥×¥í¥Ñ¥Æ¥£¤ò»ý¤¿¤Ê¤¤
2284     ¾ì¹ç¤Ë¤Ï@c Mnil ¤òÊÖ¤¹¡£$KEY ¤¬ @c Msize ¤¢¤ë¤¤¤Ï @c Mresolution ¤Î
2285     ¾ì¹ç¤Ë¤Ï¡¢ÁêÅö¤¹¤ëÃͤò¤ÏÀ°¿ôÃͤȤ·¤ÆÊÖ¤¹¡£¥Õ¥©¥ó¥È¤¬¤½¤Î¥×¥í¥Ñ¥Æ¥£
2286     ¤ò»ý¤¿¤Ê¤¤¾ì¹ç¤Ë¤Ï 0 ¤òÊÖ¤¹¡£$KEY ¤¬¤½¤ì°Ê³°¤Î¤â¤Î¤Ç¤¢¤ì¤Ð¡¢@c
2287     NULL ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£  */
2288
2289 void *
2290 mfont_get_prop (MFont *font, MSymbol key)
2291 {
2292   MRealizedFont *rfont = NULL;
2293
2294   if (font->type == MFONT_TYPE_REALIZED)
2295     rfont = (MRealizedFont *) font;
2296
2297   if (key == Mfoundry)
2298     return (void *) FONT_PROPERTY (font, MFONT_FOUNDRY);
2299   if (key == Mfamily)
2300     return (void *) FONT_PROPERTY (font, MFONT_FAMILY);
2301   if (key == Mweight)
2302     return (void *) FONT_PROPERTY (font, MFONT_WEIGHT);
2303   if (key == Mstyle)
2304     return (void *) FONT_PROPERTY (font, MFONT_STYLE);
2305   if (key == Mstretch)
2306     return (void *) FONT_PROPERTY (font, MFONT_STRETCH);
2307   if (key == Madstyle)
2308     return (void *) FONT_PROPERTY (font, MFONT_ADSTYLE);
2309   if (key == Mregistry)
2310     return (void *) FONT_PROPERTY (font, MFONT_REGISTRY);
2311   if (key == Msize)
2312     {
2313       int size = font->size;
2314       return (void *) size;
2315     }
2316   if (key == Mresolution)
2317     {
2318       int resy = font->property[MFONT_RESY];
2319       return (void *) resy;
2320     }
2321   if (key == Mfontfile)
2322     return (void *) font->file;
2323   if (key == Mspacing)
2324     return (font->spacing == MFONT_SPACING_UNDECIDED ? Mnil
2325             : msymbol (font->spacing == MFONT_SPACING_PROPORTIONAL ? "p"
2326                        : font->spacing == MFONT_SPACING_MONO ? "m" : "c"));
2327   if (rfont)
2328     {
2329       if (key == Mfont_ascent)
2330         return (void *) rfont->ascent;
2331       if (key == Mfont_descent)
2332         return (void *) rfont->descent;
2333       if (key == Mmax_advance)
2334         return (void *) rfont->max_advance;
2335     }
2336   MERROR (MERROR_FONT, NULL);
2337 }
2338
2339
2340 /*=*/
2341 /***en
2342     @brief Put a property value to a font.
2343
2344     The mfont_put_prop () function puts a font property whose key is
2345     $KEY and value is $VAL to font $FONT.  $KEY must be one of the
2346     following symbols:
2347
2348         @c Mfoundry, @c Mfamily, @c Mweight, @c Mstyle, @c Mstretch,
2349         @c Madstyle, @c Mregistry, @c Msize, @c Mresolution.
2350
2351     If $KEY is @c Msize or @c Mresolution, $VAL must be an integer.
2352     Otherwise, $VAL must be a symbol of a property value name.  But,
2353     if the name is "nil", a symbol of name "Nil" must be
2354     specified.  */
2355  /***ja
2356     @brief ¥Õ¥©¥ó¥È¤Î¥×¥í¥Ñ¥Æ¥£¤ËÃͤòÀßÄꤹ¤ë.
2357
2358     ´Ø¿ô mfont_put_prop () ¤Ï¡¢¥Õ¥©¥ó¥È $FONT ¤Î¥­¡¼¤¬$KEY ¤Ç¤¢¤ë¥×¥í¥Ñ
2359     ¥Æ¥£¤ÎÃͤò $VAL ¤ËÀßÄꤹ¤ë¡£$KEY ¤Ï°Ê²¼¤Î¥·¥ó¥Ü¥ë¤Î¤¤¤º¤ì¤«¤Ç¤¢¤ë¡£
2360
2361         @c Mfoundry, @c Mfamily, @c Mweight, @c Mstyle, @c Mstretch,
2362         @c Madstyle, @c Mregistry, @c Msize, @c Mresolution.
2363
2364     $KEY ¤¬ @c Msize ¤« @c Mresolution ¤Ç¤¢¤ì¤Ð $VAL ¤ÏÀ°¿ôÃͤǤʤ¯¤Æ¤Ï
2365     ¤é¤Ê¤¤¡£¤½¤ì°Ê³°¤Î¾ì¹ç¡¢$VAL ¤Ï¥×¥í¥Ñ¥Æ¥£ÃͤÎ̾Á°¤Î¥·¥ó¥Ü¥ë¤Ç¤Ê¤¯¤Æ
2366     ¤Ï¤Ê¤é¤Ê¤¤¡£¤¿¤À¤·¤â¤·¤½¤Î̾Á°¤¬ "nil" ¤Î¾ì¹ç¤Ï¡¢Ì¾Á°¤¬ "Nil" ¤Î¥·
2367     ¥ó¥Ü¥ë¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£*/
2368
2369 int
2370 mfont_put_prop (MFont *font, MSymbol key, void *val)
2371 {
2372   if (key == Mfoundry)
2373     mfont__set_property (font, MFONT_FOUNDRY, (MSymbol) val);
2374   else if (key == Mfamily)
2375     mfont__set_property (font, MFONT_FAMILY, (MSymbol) val);
2376   else if (key == Mweight)
2377     mfont__set_property (font, MFONT_WEIGHT, (MSymbol) val);
2378   else if (key == Mstyle)
2379     mfont__set_property (font, MFONT_STYLE, (MSymbol) val);
2380   else if (key == Mstretch)
2381     mfont__set_property (font, MFONT_STRETCH, (MSymbol) val);
2382   else if (key == Madstyle)
2383     mfont__set_property (font, MFONT_ADSTYLE, (MSymbol) val);
2384   else if (key == Mregistry)
2385     mfont__set_property (font, MFONT_REGISTRY, (MSymbol) val);
2386   else if (key == Msize)
2387     {
2388       int size = (int) val;
2389       font->size = size;
2390     }
2391   else if (key == Mresolution)
2392     {
2393       unsigned resy = (unsigned) val;
2394       font->property[MFONT_RESY] = resy;
2395     }
2396   else if (key == Mlanguage)
2397     {
2398       char *langname = MSYMBOL_NAME ((MSymbol) val);
2399       int len = MSYMBOL_NAMELEN ((MSymbol) val);
2400       
2401       if (len <= 3)
2402         {
2403           char buf[10];
2404
2405           sprintf (buf, ":lang=%s", langname);
2406           font->capability = msymbol (buf);
2407         }
2408     }
2409   else if (key == Mfontfile)
2410     {
2411       font->file = (MSymbol) val;
2412     }
2413   else
2414     MERROR (MERROR_FONT, -1);
2415   return 0;
2416 }
2417
2418 /*=*/
2419
2420 /***en
2421     @brief Return the font selection priority.
2422
2423     The mfont_selection_priority () function returns a newly created
2424     array of six symbols.  The elements are the following
2425     keys of font properties ordered by priority.
2426
2427         @c Mfamily, @c Mweight, @c Mstyle, @c Mstretch,
2428         @c Madstyle, @c Msize.
2429
2430    The m17n library selects the best matching font according to the
2431    order of this array.  A font that has a different value for a
2432    property of lower priority is preferred to a font that has a
2433    different value for a property of higher priority.  */
2434 /***ja
2435     @brief ¥Õ¥©¥ó¥ÈÁªÂò¤ÎÍ¥ÀèÅÙ¤òÊÖ¤¹.
2436
2437     ´Ø¿ô mfont_selection_priority () ¤Ï 6 ¤Ä¤Î¥·¥ó¥Ü¥ë¤«¤é¤Ê¤ëÇÛÎó¤òºî¤Ã¤ÆÊÖ¤¹¡£
2438     ÇÛÎó¤ÎÍ×ÁǤϡ¢°Ê²¼¤Î¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼¤òÍ¥ÀèÅÙ½ç¤Ëʤ٤¿¤â¤Î¤Ç¤¢¤ë¡£
2439
2440         @c Mfamily, @c Mweight, @c Mstyle, @c Mstretch,
2441         @c Madstyle, @c Msize.
2442
2443    m17n ¥é¥¤¥Ö¥é¥ê¤Ï¤³¤ÎÇÛÎó¤Ë½¾¤Ã¤Æ¡¢ºÇ¤â¹çÃפ¹¤ë¥Õ¥©¥ó¥È¤òÁªÂò¤¹¤ë¡£
2444    ÌÜŪ¤Î¥Õ¥©¥ó¥È¤È¡¢¤½¤ì¤¾¤ì°ã¤¦¥×¥í¥Ñ¥Æ¥£¤ÎÃͤ¬¹çÃפ·¤Ê¤¤¥Õ¥©¥ó¥È¤¬¤¢¤Ã¤¿¾ì¹ç¡¢Í¥ÀèÅÙ¤ÎÄ㤤¥×¥í¥Ñ¥Æ¥£¤ÎÃͤ¬¹çÃפ·¤Ê¤¤¥Õ¥©¥ó¥È¡ÊÍ¥ÀèÅ٤ι⤤¥×¥í¥Ñ¥Æ¥£¤ÎÃͤ¬¹çÃפ·¤Æ¤¤¤ë¥Õ¥©¥ó¥È¡Ë¤¬ÁªÂò¤µ¤ì¤ë¡£
2445
2446    */
2447
2448 MSymbol *
2449 mfont_selection_priority ()
2450 {
2451   MSymbol *keys;
2452   int i;
2453
2454   MTABLE_MALLOC (keys, FONT_SCORE_PRIORITY_SIZE, MERROR_FONT);
2455   for (i = 0; i < FONT_SCORE_PRIORITY_SIZE; i++)
2456     {
2457       enum MFontProperty prop = font_score_priority[i];
2458
2459       if (prop == MFONT_SIZE)
2460         keys[i] = Msize;
2461       else if (prop == MFONT_ADSTYLE)
2462         keys[i] = Madstyle;
2463       else if (prop == MFONT_FAMILY)
2464         keys[i] = Mfamily;
2465       else if (prop == MFONT_WEIGHT)
2466         keys[i] = Mweight;
2467       else if (prop == MFONT_STYLE)
2468         keys[i] = Mstyle;
2469       else if (prop == MFONT_STRETCH)
2470         keys[i] = Mstretch;
2471       else
2472         keys[i] = Mfoundry;
2473     }
2474   return keys;
2475 }
2476
2477 /*=*/
2478
2479 /***en
2480     @brief Set the font selection priority.
2481
2482     The mfont_set_selection_priority () function sets font selection
2483     priority according to $KEYS, which is an array of six symbols.
2484     Each element must be one of the below.  No two elements must be
2485     the same.
2486
2487         @c Mfamily, @c Mweight, @c Mstyle, @c Mstretch,
2488         @c Madstyle, @c Msize.
2489
2490     See the documentation of the function mfont_selection_priority ()
2491     for details.  */
2492 /***ja
2493     @brief ¥Õ¥©¥ó¥ÈÁªÂòÍ¥ÀèÅÙ¤òÀßÄꤹ¤ë.
2494
2495     ´Ø¿ô mfont_set_selection_priority () ¤Ï¡¢6¤Ä¤Î¥·¥ó¥Ü¥ë¤ÎÇÛÎó $KEYS 
2496     ¤Ë¤·¤¿¤¬¤Ã¤Æ¥Õ¥©¥ó¥ÈÁªÂòÍ¥ÀèÅÙ¤òÀßÄꤹ¤ë¡£ÇÛÎó¤Ï°Ê²¼¤Î³ÆÍ×ÁǤòŬÀÚ
2497     ¤Ê½çÈÖ¤Çʤ٤¿¤â¤Î¤Ç¤¢¤ë¡£
2498
2499         @c Mfamily, @c Mweight, @c Mstyle, @c Mstretch,
2500         @c Madstyle, @c Msize.
2501
2502     ¾ÜºÙ¤Ï´Ø¿ô mfont_selection_priority () ¤ÎÀâÌÀ¤ò»²¾È¤Î¤³¤È¡£
2503      */
2504
2505 int
2506 mfont_set_selection_priority (MSymbol *keys)
2507 {
2508   int priority[FONT_SCORE_PRIORITY_SIZE];
2509   int i, j, shift;
2510
2511   for (i = 0; i < FONT_SCORE_PRIORITY_SIZE; i++, keys++)
2512     {
2513       enum MFontProperty prop;
2514
2515       if (*keys == Msize)
2516         prop = MFONT_SIZE;
2517       else if (*keys == Madstyle)
2518         prop = MFONT_ADSTYLE;
2519       else if (*keys == Mfamily)
2520         prop = MFONT_FAMILY;
2521       else if (*keys == Mweight)
2522         prop = MFONT_WEIGHT;
2523       else if (*keys == Mstyle)
2524         prop = MFONT_STYLE;
2525       else if (*keys == Mstretch)
2526         prop = MFONT_STRETCH;
2527       else if (*keys == Mfoundry)
2528         prop = MFONT_FOUNDRY;
2529       else
2530         /* Invalid element.  */
2531         return -1;
2532       for (j = 0; j < i; j++)
2533         if (priority[j] == prop)
2534           /* Duplicated element.  */
2535           return -1;
2536       priority[i] = prop;
2537     }
2538   for (i = 0; i < FONT_SCORE_PRIORITY_SIZE; i++)
2539     font_score_priority[i] = priority[i];
2540   /* Here, SHIFT starts from 1, not 0.  This is because the lowest bit
2541      of a score is a flag for a scalable font (see the documentation
2542      of font_score).  */
2543   i = FONT_SCORE_PRIORITY_SIZE - 1;
2544   for (shift = 1; i >= 0; i--)
2545     {
2546       font_score_shift_bits[font_score_priority[i]] = shift;
2547       if (font_score_priority[i] == MFONT_SIZE)
2548         shift += 16;
2549       else if (font_score_priority[i] <= MFONT_FAMILY)
2550         shift++;
2551       else
2552         shift += 2;
2553     }
2554   return 0;
2555 }
2556
2557 /*=*/
2558
2559 /***en
2560     @brief Find a font.
2561
2562     The mfont_find () function returns a pointer to the available font
2563     that matches best the specification $SPEC on frame $FRAME.
2564
2565     $SCORE, if not NULL, must point to a place to store the score
2566     value that indicates how well the found font matches to $SPEC.  The
2567     smaller score means a better match.  */
2568 /***ja
2569     @brief ¥Õ¥©¥ó¥È¤òõ¤¹.
2570
2571     ´Ø¿ô mfont_find () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¾å¤Ç¥Õ¥©¥ó¥ÈÄêµÁ $SPEC 
2572     ¤Ë¤â¤Ã¤È¤â¹çÃפ¹¤ëÍøÍѲÄǽ¤Ê¥Õ¥©¥ó¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£  
2573
2574     $SCORE ¤Ï NULL ¤Ç¤¢¤ë¤«¡¢¸«¤Ä¤«¤Ã¤¿¥Õ¥©¥ó¥È¤¬ $SPEC 
2575     ¤Ë¤É¤ì¤Û¤É¹ç¤Ã¤Æ¤¤¤ë¤«¤ò¼¨¤¹¥¹¥³¥¢¤òÊݸ¤¹¤ë¾ì½ê¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ë¡£
2576     ¥¹¥³¥¢¤¬¾®¤µ¤¤¤Û¤ÉÎɤ¯¹ç¤Ã¤Æ¤¤¤ë¤³¤È¤ò°ÕÌ£¤¹¤ë¡£
2577     */
2578
2579 MFont *
2580 mfont_find (MFrame *frame, MFont *spec, int *score, int max_size)
2581 {
2582   MFont spec_copy;
2583   MFont *best;
2584   MFontList *list;
2585   MRealizedFont *rfont;
2586   MFont adjusted;
2587
2588   if (spec->size < 0)
2589     {
2590       double pt = - spec->size;
2591
2592       adjusted = *spec;
2593       adjusted.size = pt * frame->dpi / 72.27 + 0.5;
2594       spec = &adjusted;
2595     }
2596   MFONT_INIT (&spec_copy);
2597   spec_copy.property[MFONT_FAMILY] = spec->property[MFONT_FAMILY];
2598   spec_copy.property[MFONT_REGISTRY] = spec->property[MFONT_REGISTRY];
2599   spec_copy.capability = spec->capability;
2600   spec_copy.file = spec->file;
2601
2602   list = mfont__list (frame, &spec_copy, spec, max_size);
2603   if (! list)
2604     return NULL;
2605
2606   best = list->fonts[0].font;
2607   if (score)
2608     *score = list->fonts[0].score;
2609   free (list->fonts);
2610   free (list);
2611   spec_copy = *best;
2612   mfont__merge (&spec_copy, spec, 0);
2613   rfont = mfont__open (frame, best, spec);
2614   if (! rfont)
2615     return NULL;
2616   return (MFont *) rfont;
2617 }
2618
2619 /*=*/
2620 /***en
2621     @brief Set encoding of a font.
2622
2623     The mfont_set_encoding () function sets the encoding information
2624     of font $FONT.
2625
2626     $ENCODING_NAME is a symbol representing a charset that has the
2627     same encoding as the font.
2628
2629     $REPERTORY_NAME is @c Mnil or a symbol representing a charset that
2630     has the same repertory as the font.  If it is @c Mnil, whether a
2631     specific character is supported by the font is asked to each font
2632     driver.
2633
2634     @return
2635     If the operation was successful, this function returns 0.
2636     Otherwise it returns -1 and assigns an error code to the external
2637     variable #merror_code.  */
2638 /***ja
2639     @brief ¥Õ¥©¥ó¥È¤Î¥¨¥ó¥³¡¼¥Ç¥£¥ó¥°¤òÀßÄꤹ¤ë.
2640
2641     ´Ø¿ô mfont_set_encoding () ¤Ï¥Õ¥©¥ó¥È $FONT ¤Î¥¨¥ó¥³¡¼¥Ç¥£¥ó¥°¾ðÊó¤òÀßÄꤹ¤ë¡£
2642
2643     $ENCODING_NAME ¤Ï¥Õ¥©¥ó¥È¤ÈƱ¤¸¥¨¥ó¥³¡¼¥Ç¥£¥ó¥°¤ò»ý¤Äʸ»ú¥»¥Ã¥È¤ò¼¨¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£
2644
2645     $REPERTORY_NAME ¤Ï @c Mnil ¤Ç¤¢¤ë¤«¡¢¥Õ¥©¥ó¥È¤ÈƱ¤¸¥¨¥ó¥³¡¼¥Ç¥£¥ó¥°¤ò»ý¤Äʸ»ú¥»¥Ã¥È¤ò¼¨¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£
2646     @c Mnil ¤Ç¤¢¤ì¤Ð¡¢¸Ä¡¹¤Îʸ»ú¤¬¤½¤Î¥Õ¥©¥ó¥È¤Ç¥µ¥Ý¡¼¥È¤µ¤ì¤Æ¤¤¤ë¤«¤É¤¦¤«¤Ï¡¢³Æ¡¹¤Î¥Õ¥©¥ó¥È¥É¥é¥¤¥Ð¤ËÌ䤤¹ç¤ï¤»¤ë¡£
2647
2648     @return
2649     ½èÍý¤¬À®¸ù¤¹¤ì¤Ð¤³¤Î´Ø¿ô¤Ï 0 ¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô
2650     #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£  */
2651
2652
2653 int
2654 mfont_set_encoding (MFont *font, MSymbol encoding_name, MSymbol repertory_name)
2655 {
2656   MCharset *encoding_charset = MCHARSET (encoding_name);
2657   MCharset *repertory_charset;
2658   MSymbol registry;
2659   MFontEncoding *encoding;
2660   MPlist *plist;
2661
2662   if (! encoding_charset)
2663     MERROR (MERROR_FONT, -1);
2664   if (repertory_name != Mnil)
2665     {
2666       repertory_charset = MCHARSET (repertory_name);
2667       if (! repertory_charset)
2668         MERROR (MERROR_FONT, -1);
2669     }
2670   else
2671     repertory_charset = NULL;
2672
2673   MSTRUCT_CALLOC (encoding, MERROR_FONT);
2674   encoding->spec = *font;
2675   encoding->encoding_name = encoding_name;
2676   encoding->encoding_charset = encoding_charset;
2677   encoding->repertory_name = repertory_name;
2678   encoding->repertory_charset = repertory_charset;
2679   registry = FONT_PROPERTY (font, MFONT_REGISTRY);
2680   if (registry == Mnil)
2681     registry = Mt;
2682   if (! font_encoding_list)
2683     load_font_encoding_table ();
2684   mplist_push (font_encoding_list, registry, encoding);
2685   MPLIST_DO (plist, MPLIST_NEXT (font_encoding_list))
2686     if (! memcmp (font, &((MFontEncoding *) MPLIST_VAL (plist))->spec,
2687                   sizeof (MFont)))
2688       {
2689         mplist_pop (plist);
2690         break;
2691       }
2692   return 0;
2693 }
2694
2695 /*=*/
2696
2697 /***en
2698     @brief Create a fontname from a font.
2699
2700     This function is obsolete.   Use mfont_unparse_name instead. */
2701 /***ja
2702     @brief ¥Õ¥©¥ó¥È̾¤«¤é¥Õ¥©¥ó¥È¤òºî¤ë.
2703
2704     ¤³¤Î´Ø¿ô¤ÏÇÑ»ßͽÄê¤Ç¤¢¤ë¡£ mfont_unparse_name () ¤ò»ÈÍѤΤ³¤È¡£ */
2705
2706 char *
2707 mfont_name (MFont *font)
2708 {
2709   return mfont_unparse_name (font, Mx);
2710 }
2711
2712 /*=*/
2713
2714 /***en
2715     @brief Create a new font from fontname.
2716
2717     This function is obsolete.  Use mfont_parse_name () instead.  */
2718
2719 /***ja
2720     @brief ¥Õ¥©¥ó¥È¤«¤é¥Õ¥©¥ó¥È̾¤òºî¤ë.
2721
2722     ¤³¤ì¤Ï´Ø¿ô¤ÏÇÑ»ßͽÄê¤Ç¤¢¤ë¡£ mfont_parse_name () ¤ò»ÈÍѤΤ³¤È¡£  */
2723
2724 MFont *
2725 mfont_from_name (const char *name)
2726 {
2727   return mfont_parse_name (name, Mx);
2728 }
2729
2730 /*=*/
2731
2732 /***en
2733     @brief Get resize information of a font.
2734
2735     The mfont_resize_ratio () function lookups the m17n database
2736     \<font, reisize\> and returns a resizing ratio (in percentage) of
2737     FONT.  For instance, if the return value is 150, that means that
2738     the m17n library uses an 1.5 time bigger font than a specified
2739     size.  */
2740
2741 /***ja
2742     @brief ¥Õ¥©¥ó¥È¤Î¥ê¥µ¥¤¥º¾ðÊó¤òÆÀ¤ë
2743
2744     ´Ø¿ô mfont_resize_ratio ¤Ï m17n ¥Ç¡¼¥¿¥Ù¡¼¥¹ \<font, reisize\> 
2745     ¤ò¸¡º÷¤·¡¢¥Õ¥©¥ó¥È FONT ¤Î¥ê¥µ¥¤¥º¤ÎÈæΨ¡Ê¥Ñ¡¼¥»¥ó¥Æ¡¼¥¸¡Ë
2746     ¤òÊÖ¤¹¡£¤¿¤È¤¨¤ÐÊÖ¤¹Ãͤ¬ 150 ¤Ç¤¢¤ì¤Ð¡¢m17n ¥é¥¤¥Ö¥é¥ê¤Ï»ØÄꤵ¤ì¤¿¥µ¥¤¥º¤Î 1.5 
2747     ÇܤΥե©¥ó¥È¤ò»ÈÍѤ¹¤ë¤³¤È¤ò°ÕÌ£¤¹¤ë¡£ */
2748
2749 int
2750 mfont_resize_ratio (MFont *font)
2751 {
2752   MSymbol registry = FONT_PROPERTY (font, MFONT_REGISTRY);
2753   MFontResize *resize;
2754   MPlist *plist;
2755
2756   if (! font_resize_list)
2757     load_font_resize_table ();
2758   if (! MPLIST_TAIL_P (font_resize_list))
2759     while (1)
2760       {
2761         plist = font_resize_list;
2762         while (registry ? (plist = mplist_find_by_key (plist, registry))
2763                : plist)
2764           {
2765             resize = (MFontResize *) MPLIST_VAL (plist);
2766             if (mfont__match_p (font, &resize->spec, MFONT_ADSTYLE))
2767               return resize->resize;
2768             plist = MPLIST_NEXT (plist);
2769           }
2770         if (registry == Mt)
2771           break;
2772         registry = Mt;
2773       }
2774   return 100;
2775 }
2776
2777 /*=*/
2778
2779 /***en
2780     @brief Get a list of fonts.
2781
2782     The mfont_list () functions returns a list of fonts available on
2783     frame $FRAME.  $FONT, if not NULL, limits fonts to ones
2784     that match with $FONT.  $LANGUAGE, if not @c Mnil, limits fonts to
2785     ones that support $LANGUAGE.  $MAXNUM, if greater than 0, limits
2786     the number of fonts.
2787
2788     @return
2789     This function returns a plist whose keys are family names and
2790     values are pointers to the object MFont.  The plist must be freed
2791     by m17n_object_unref ().  If no font is found, it returns
2792     NULL.  */
2793
2794 /***ja
2795     @brief ¥Õ¥©¥ó¥È¤Î¥ê¥¹¥È¤òÆÀ¤ë
2796
2797     ´Ø¿ô mfont_list () ¤Ï¥Õ¥ì¡¼¥à $FRAME ¤ÇÍøÍѲÄǽ¤Ê¥Õ¥©¥ó¥È¤Î¥ê¥¹¥È¤òÊÖ¤¹¡£
2798     $FONT ¤¬ NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢$FONT ¤È¹çÃפ¹¤ëÍøÍѲÄǽ¤Ê¥Õ¥©¥ó¥È¤Î¥ê¥¹¥È¤òÊÖ¤¹¡£
2799     $LANGUAGE ¤¬ @c Mnil ¤Ç¤Ê¤±¤ì¤Ð¡¢$LANGUAGE ¤ò¥µ¥Ý¡¼¥È¤¹¤ëÍøÍѲÄǽ¤Ê¥Õ¥©¥ó¥È¤Î¥ê¥¹¥È¤òÊÖ¤¹¡£
2800     $MAXNUM ¤Ï¡¢0 ¤è¤êÂ礭¤¤¾ì¹ç¤Ë¤Ï¡¢ÊÖ¤¹¥Õ¥©¥ó¥È¤Î¿ô¤Î¾å¸Â¤Ç¤¢¤ë¡£
2801
2802     @return 
2803     ¤³¤Î´Ø¿ô¤Ï¥­¡¼¤¬¥Õ¥©¥ó¥È¥Õ¥¡¥ß¥ê̾¤Ç¤¢¤êÃͤ¬ MFont ¥ª¥Ö¥¸¥§¥¯¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ë¤è¤¦¤Ê
2804     plist ¤òÊÖ¤¹¡£plist ¤Ï m17n_object_unref () 
2805     ¤Ç²òÊü¤¹¤ëɬÍפ¬¤¢¤ë¡£¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤é¤Ê¤±¤ì¤ÐNULL ¤òÊÖ¤¹¡£  */
2806
2807 MPlist *
2808 mfont_list (MFrame *frame, MFont *font, MSymbol language, int maxnum)
2809 {
2810   MPlist *plist, *pl;
2811   MFontList *font_list;
2812   int i;
2813   MFont spec;
2814   
2815   if (font)
2816     spec = *font;
2817   else
2818     MFONT_INIT (&spec);
2819
2820   if (spec.size < 0)
2821     {
2822       double pt = - spec.size;
2823
2824       spec.size = pt * frame->dpi / 72.27 + 0.5;
2825     }
2826
2827   if (language != Mnil)
2828     {
2829       /* ":lang=XXX" */
2830       char *buf = alloca (MSYMBOL_NAMELEN (language) + 7);
2831
2832       sprintf (buf, ":lang=%s", MSYMBOL_NAME (language));
2833       spec.capability = msymbol (buf);
2834     }
2835
2836   font_list = mfont__list (frame, &spec, &spec, 0);
2837   if (! font_list)
2838     return NULL;
2839   if (font_list->nfonts == 0)
2840     {
2841       free (font_list);
2842       return NULL;
2843     }
2844
2845   plist = pl = mplist ();
2846   for (i = 0; i < font_list->nfonts; i++)
2847     {
2848       MSymbol family = FONT_PROPERTY (font_list->fonts[i].font, MFONT_FAMILY);
2849
2850       if (family != Mnil)
2851         pl = mplist_add (pl, family, font_list->fonts[i].font);
2852     }
2853   free (font_list);
2854   return plist;
2855 }
2856
2857
2858 /*=*/
2859
2860 /***en
2861     @brief Check the usability of a font.
2862
2863     The function mfont_check () checkes if $FONT can be used for
2864     $SCRIPT and $LANGUAGE in $FONTSET on $FRAME.
2865
2866     @return If the font is usable, return 1.  Otherwise return 0.
2867  */
2868
2869 int
2870 mfont_check (MFrame *frame, MFontset *fontset,
2871              MSymbol script, MSymbol language, MFont *font)
2872 {
2873   MRealizedFont *rfont;
2874   int best, score;
2875
2876   if (! fontset)
2877     fontset = frame->face->property[MFACE_FONTSET];
2878   rfont = mfontset__get_font (frame, fontset, script, language, font, &best);
2879   if (! rfont || ! best)
2880     return 0;
2881   score = font_score (&rfont->spec, font);
2882   return (score == 0 ? 2 : 1);
2883 }
2884
2885 /*** @} */
2886
2887 /*** @addtogroup m17nDebug */
2888 /*=*/
2889 /*** @{ */
2890
2891 /***en
2892     @brief Dump a font.
2893
2894     The mdebug_dump_font () function prints font $FONT in a human readable
2895     way to the stderr.
2896
2897     @return
2898     This function returns $FONT.  */
2899 /***ja
2900     @brief ¥Õ¥©¥ó¥È¤ò¥À¥ó¥×¤¹¤ë.
2901
2902     ´Ø¿ô mdebug_dump_font () ¤Ï¥Õ¥©¥ó¥È $FONT ¤ò stderr 
2903     ¤Ë¿Í´Ö¤Ë²ÄÆɤʷÁ¤Ç°õºþ¤¹¤ë¡£
2904
2905     @return
2906     ¤³¤Î´Ø¿ô¤Ï $FONT ¤òÊÖ¤¹¡£  */
2907
2908 MFont *
2909 mdebug_dump_font (MFont *font)
2910 {
2911   char *name;
2912   
2913   name = xlfd_unparse_name (font, 0);
2914   if (name)
2915     {
2916       fprintf (stderr, "%s", name);
2917       free (name);
2918     }
2919   if (font->file != Mnil)
2920     {
2921       char *file = MSYMBOL_NAME (font->file);
2922       char *lastslash = file, *p;
2923
2924       for (p = file; *p; p++)
2925         if (*p == '/')
2926           lastslash = p;
2927       if (name)
2928         fprintf (stderr, ",");
2929       fprintf (stderr, "%s", lastslash + 1);
2930     }
2931   if (font->capability != Mnil)
2932     fprintf (stderr, "%s", MSYMBOL_NAME (font->capability));
2933   return font;
2934 }
2935
2936 /*** @} */
2937
2938 /*
2939   Local Variables:
2940   coding: euc-japan
2941   End:
2942 */