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