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