645f8e860b60d2d10881caeb90c0b06d7890f420
[m17n/m17n-lib.git] / src / font.c
1 /* font.c -- font module.
2    Copyright (C) 2003, 2004
3      National Institute of Advanced Industrial Science and Technology (AIST)
4      Registration Number H15PRO112
5
6    This file is part of the m17n library.
7
8    The m17n library is free software; you can redistribute it and/or
9    modify it under the terms of the GNU Lesser General Public License
10    as published by the Free Software Foundation; either version 2.1 of
11    the License, or (at your option) any later version.
12
13    The m17n library is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    Lesser General Public License for more details.
17
18    You should have received a copy of the GNU Lesser General Public
19    License along with the m17n library; if not, write to the Free
20    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
21    02111-1307, USA.  */
22
23 /***en
24     @addtogroup m17nFont
25     @brief Font object
26
27     The m17n GUI API represents a font by an object of the type @c
28     MFont.  A font can have @e font @e properties.  Like other types
29     of properties, a font property consists of a key and a value.  The
30     key of a font property must be one of the following symbols:
31
32     @c Mfoundry, @c Mfamily, @c Mweight, @c Mstyle, @c Mstretch,
33     @c Madstyle, @c Mregistry, @c Msize, @c Mresolution.
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.  "The font
37     property that belongs to font F and whose key is @c Mxxx" may be
38     shortened to "the xxx property of F".
39
40     The value of a foundry property is a symbol representing font
41     foundry information, e.g. adobe, misc, etc.
42
43     The value of a family property is a symbol representing font family
44     information, e.g. times, helvetica, etc.
45
46     The value of a weight property is a symbol representing weight
47     information, e.g. normal, bold, etc.
48
49     The value of a style property is a symbol representing slant
50     information, e.g. normal, italic, etc.
51
52     The value of a stretch property is a symbol representing width
53     information, e.g. normal, semicondensed, etc.
54
55     The value of an adstyle property is a symbol representing abstract
56     font family information, e.g. serif, sans-serif, etc.
57
58     The value of a registry property is a symbol representing registry
59     information, e.g. iso10646-1, iso8895-1, etc.
60
61     The value of a size property is an integer representing design
62     size in the unit of 1/10 point.
63
64     The value of a resolution property is an integer representing
65     assumed device resolution in the unit of dots per inch (dpi)
66
67     The m17n library uses font objects for two purposes: to receive
68     font specification from an application program, and to present
69     available fonts to an application program.  When the m17n library
70     presents an available font to an application program, all font
71     properties have a concrete value.
72
73     The m17n library supports three kinds of fonts: Window system fonts,
74     FreeType fonts, and OpenType fonts.
75
76     <ul>
77
78     <li> Window system fonts
79
80     The m17n-X library supports all fonts handled by an X server and
81     an X font server.  The correspondence between XLFD fields and font
82     properties are shown below.
83
84 @verbatim
85     XLFD field                                  property
86     ---------------                             --------
87     FOUNDRY                                     foundry
88     FAMILY_NAME                                 family
89     WEIGHT_NAME                                 weight
90     SLANT                                       style
91     SETWIDTH_NAME                               stretch
92     ADD_STYLE_NAME                              adstyle
93     POINT_SIZE                                  size
94     RESOLUTION_Y                                resolution
95     CHARSET_REGISTRY-CHARSET_ENCODING           registry
96 @endverbatim
97
98     XLFD fields not listed in the above table are ignored.
99
100     <li> FreeType fonts
101
102     The m17n library, if configured to use the FreeType library,
103     supports all fonts that can be handled by the FreeType library.
104     The variable #mfont_freetype_path is initialized properly accoding
105     to the configuration of the m17n librayr and the environment
106     variable @c M17NDIR.  See the documentation of the variable for
107     details.
108
109     The family name of a FreeType font corresponds to the family
110     property.  Style names of FreeType fonts correspond to the weight,
111     style, and stretch properties as below.
112
113 @verbatim
114     style name          weight  style   stretch
115     ----------          ------  -----   -------
116     Regular             medium  r       normal
117     Italic              medium  i       normal
118     Bold                bold    r       normal
119     Bold Italic         bold    i       normal
120     Narrow              medium  r       condensed
121     Narrow Italic       medium  i       condensed
122     Narrow Bold         bold    r       condensed
123     Narrow Bold Italic  bold    i       condensed
124     Black               black   r       normal
125     Black Italic        black   i       normal
126 @endverbatim
127
128     Style names not listed in the above table are treated as
129     "Regular".
130
131     Combination of a platform ID and an encoding ID corresponds to the
132     registry property.  For example, if a font has the combination (1
133     1), the registry property is 1-1.  Some frequent combinations have
134     a predefined registry property as below.
135
136 @verbatim
137     platform ID         encoding ID     registry property
138     -----------         -----------     -----------------
139     0                   3               unicode-bmp
140     0                   4               unicode-full
141     1                   0               apple-roman
142     3                   1               unicode-bmp
143     3                   1               unicode-full
144 @endverbatim
145
146     Thus, a font that has two combinations (1 0) and (3 1) corresponds
147     to four font objects whose registries are 1-0, apple-roman, 3-1,
148     and unicode-bmp.
149
150     <li> OpenType fonts 
151
152     The m17n library, if configured to use both the FreeType library
153     and the OTF library, supports any OpenType fonts.  The list of
154     actually available fonts is created in the same way as in the case
155     of FreeType fonts.  If a fontset instructs to use an OpenType font
156     via an FLT (Font Layout Table), and the FLT has an OTF-related
157     command (e.g. otf:deva), the OTF library converts a character
158     sequence to a glyph code sequence according to the OpenType layout
159     tables of the font, and the FreeType library gives a bitmap image
160     for each glyph.
161
162     </ul>
163
164   */
165
166 /***ja
167     @addtogroup m17nFont
168     @brief ¥Õ¥©¥ó¥È¤È¤Ï¡¢¸Ä¡¹¤Î¥·¥¹¥Æ¥à¥Õ¥©¥ó¥È¤ËÂбþ¤¹¤ë¥ª¥Ö¥¸¥§¥¯¥È¤Ç¤¢¤ë
169
170     m17n-win API ¤Ë¤ª¤±¤ë @e ¥Õ¥©¥ó¥È ¤È¤Ï¡¢@c MFont ·¿¤Î¥ª¥Ö¥¸¥§¥¯¥È
171     ¤Ç¤¢¤ê¡¢¥¦¥£¥ó¥É¥¦¥·¥¹¥Æ¥à°Í¸¤Î @e ¥·¥¹¥Æ¥à¥Õ¥©¥ó¥È ¤È°ìÂаì¤ËÂÐ
172     ±þÉÕ¤±¤é¤ì¤ë¡£¥Õ¥©¥ó¥È¤Ï¸ÇÄê¸Ä¿ô¤Î @e ¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£ ¤ò»ý¤Ä¡£
173     ¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤Ï¥­¡¼¤ÈÃͤ«¤é¤Ê¤ë¡£¥­¡¼¤Ï¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢
174
175     @c Mfoundry, @c Mfamily, @c Mweight, @c Mstyle, @c Mstretch,
176     @c Madstyle, @c Mregistry, @c Msize, @c Mresolution
177
178     ¤Î¤¤¤º¤ì¤«¤Ç¤¢¤ë¡£¥­¡¼¤¬ @c Msize ¤¢¤ë¤¤¤Ï @c Mresolution ¤Î¾ì¹ç¡¢
179     ÃͤÏÀ°¿ô¤Ç¤¢¤ë¡£¥­¡¼¤¬¤½¤ì°Ê³°¤Î¾ì¹ç¡¢Ãͤϥ·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£¡Ö¥Õ¥©¥ó
180     ¥È F ¤Î¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¥­¡¼¤¬ @c Mxxx ¤Ç¤¢¤ë¤â¤Î¡×¤Î¤³¤È¤ò
181     ´Êñ¤Ë¡ÖF ¤Î xxx ¥×¥í¥Ñ¥Æ¥£¡×¤È¸Æ¤Ö¤³¤È¤¬¤¢¤ë¡£
182
183     Family ¥×¥í¥Ñ¥Æ¥£¤ÎÃͤϡ¢times, helvetica Åù¤Î¥Õ¥©¥ó¥È¥Õ¥¡¥ß¥ê¡¼¤ò
184     É½¤ï¤¹¡£
185
186     Weight ¥×¥í¥Ñ¥Æ¥£¤ÎÃͤϡ¢normal, bold Åù¤ÎÂÀ¤µ¤Ë´Ø¤¹¤ë¾ðÊó¤òɽ¤ï¤¹¡£
187
188     Style ¥×¥í¥Ñ¥Æ¥£¤ÎÃͤϡ¢normal, italic Åù¤Î·¹¤­¤Ë´Ø¤¹¤ë¾ðÊó¤òɽ¤ï
189     ¤¹¡£
190
191     Stretch ¥×¥í¥Ñ¥Æ¥£¤ÎÃͤϡ¢normal, semicondensed Åù¤Îʸ»úÉý¤Ë´Ø¤¹¤ë
192     ¾ðÊó¤òɽ¤ï¤¹¡£
193
194     Adstyle ¥×¥í¥Ñ¥Æ¥£¤ÎÃͤϡ¢serif, sans-serif Åù¤ÎÃê¾ÝŪ¤Ê¥Õ¥©¥ó¥È
195     ¥Õ¥¡¥ß¥ê¡¼¤òɽ¤ï¤¹¡£
196
197     Registry ¥×¥í¥Ñ¥Æ¥£¤ÎÃͤϡ¢iso10646, iso8895-1 ¤Î¥ì¥¸¥¹¥È¥ê¤òɽ¤ï
198     ¤¹¡£
199
200     Size ¥×¥í¥Ñ¥Æ¥£¤ÎÃͤϡ¢¥Õ¥©¥ó¥È¤Î¥Ç¥¶¥¤¥ó¥µ¥¤¥º¤òɽ¤ï¤¹¡£Ã±°Ì
201     ¤Ï 1/10 ¥Ý¥¤¥ó¥È¤Ç¤¢¤ë¡£
202
203     Resolution ¥×¥í¥Ñ¥Æ¥£¤ÎÃͤϡ¢ÁÛÄꤵ¤ì¤Æ¤¤¤ë¥Ç¥Ð¥¤¥¹¤Î²òÁüÅÙ¤ò É½¤ï
204     ¤¹¡£Ã±°Ì¤Ï dots per inch (dpi) ¤Ç¤¢¤ë¡£  */
205
206 /*=*/
207
208 #if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE)
209 /*** @addtogroup m17nInternal
210      @{ */
211
212 #include "config.h"
213
214 #include <stdio.h>
215 #include <stdlib.h>
216 #include <string.h>
217
218 #include "m17n-gui.h"
219 #include "m17n-misc.h"
220 #include "internal.h"
221 #include "mtext.h"
222 #include "symbol.h"
223 #include "plist.h"
224 #include "charset.h"
225 #include "internal-gui.h"
226 #include "font.h"
227 #include "face.h"
228
229 MFontDriver *mfont__driver_list[MFONT_TYPE_MAX];
230
231 /** Indices to font properties sorted by their priority.  */
232 static int font_score_priority[] =
233   { MFONT_SIZE,
234     MFONT_ADSTYLE,
235     MFONT_FAMILY,
236     MFONT_WEIGHT,
237     MFONT_STYLE,
238     MFONT_STRETCH,
239     MFONT_FOUNDRY
240   };
241
242 #define FONT_SCORE_PRIORITY_SIZE        \
243   (sizeof font_score_priority / sizeof font_score_priority[0])
244
245 /* Indexed by a font property MFONT_XXX, and the value is how many
246    bits to shift the difference of property values.  */
247 static int font_score_shift_bits[MFONT_PROPERTY_MAX];
248
249 /** Predefined symbols for each font property.  The order is important
250     because the function score_font () decides how well a font matches
251     with a spec by checking how close the index is.  */
252
253 static char *common_foundry[] =
254   { "misc",
255     "adobe" };
256 static char *common_family[] =
257   { "fixed",
258     "courier",
259     "helvetica",
260     "times" };
261 static char *common_weight[] =
262   { "ultralight",
263     "extralight",
264     "light",
265     "demilight",
266     "book",
267     "normal",
268     "medium",
269     "regular",
270     "demibold",
271     "bold",
272     "extrabold",
273     "ultrabold",
274     "black" };
275 static char *common_style[] =
276   { "o",
277     "i",
278     "r",
279     "ri",
280     "ro" };
281 static char *common_stretch[] =
282   { "condensed",
283     "narrow",
284     "semicondensed",
285     "normal",
286     "semiexpanded",
287     "expanded" };
288 static char *common_adstyle[] =
289   { "serif",
290     "",
291     "sans" };
292 static char *common_registry[] =
293   { "iso8859-1" };
294
295 /* Table containing all the data above.  */
296
297 struct MFontCommonNames
298 {
299   int num;
300   char **names;
301 };
302
303 static struct MFontCommonNames font_common_names[] =
304   {
305     { sizeof (common_foundry) / sizeof (char *), common_foundry},
306     { sizeof (common_family) / sizeof (char *), common_family},
307     { sizeof (common_weight) / sizeof (char *), common_weight},
308     { sizeof (common_style) / sizeof (char *), common_style},
309     { sizeof (common_stretch) / sizeof (char *), common_stretch},
310     { sizeof (common_adstyle) / sizeof (char *), common_adstyle},
311     { sizeof (common_registry) / sizeof (char *), common_registry}
312   };
313
314
315 /** Table of available font property names.  */
316
317 MFontPropertyTable mfont__property_table[MFONT_REGISTRY + 1];
318
319
320 /** Return the numeric value of SYMBOL as the Nth font property.  */
321
322 #define FONT_PROPERTY_NUMERIC(symbol, n)        \
323   ((symbol) == Mnil                             \
324    ? 0                                          \
325    : ((int) msymbol_get ((symbol), mfont__property_table[(n)].property)))
326
327
328 /** Set the numeric value of SYMBOL as the Nth font property to NUMERIC.  */
329
330 #define SET_FONT_PROPERTY_NUMERIC(symbol, n, numeric)           \
331   msymbol_put((symbol), mfont__property_table[(n)].property,    \
332               (void *) (numeric))
333
334 static char *
335 gen_font_name (char *buf, MFont *font)
336 {
337   char size[16];
338   int i;
339
340   buf[0] = '\0';
341   for (i = 0; i <= MFONT_REGISTRY; i++)
342     if (FONT_PROPERTY (font, i) != Mnil)
343       {
344         char *name = msymbol_name (FONT_PROPERTY (font, i));
345
346         if (name[0])
347           {
348             if (i > 0)
349               strcat (buf, ",");
350             strcat (buf, name);
351           }
352       }
353   sprintf (size, ",%d", font->property[MFONT_SIZE] / 10);
354   strcat (buf, size);
355   return buf;
356 }
357
358
359 \f
360 /* Font selector.  */
361
362 struct MFontEncoding {
363   MFont spec;
364   MSymbol encoding_name;
365   MCharset *encoding_charset;
366   MSymbol repertory_name;
367   MCharset *repertory_charset;
368 };
369
370 static MPlist *font_encoding_list;
371 static MFontEncoding default_encoding;
372
373 /** Load font encoding table from the data <font encoding>.
374     The data has this form:
375         (FONT-SPEC ENCODING) ...
376     where FONT-SPEC has this form:
377         ([FOUNDRY FAMILY [WEIGHT [STYLE [STRETCH [ADSTYLE]]]]] REGISTRY)
378     All elements are symbols.  */
379
380 static int
381 load_font_encoding_table ()
382 {
383   MDatabase *mdb;
384   MPlist *encoding_list, *plist, *pl, *elt;
385
386   font_encoding_list = pl = mplist ();
387
388   mdb = mdatabase_find (Mfont, msymbol ("encoding"), Mnil, Mnil);
389   if (! mdb
390       || ! (encoding_list = (MPlist *) mdatabase_load (mdb)))
391     MERROR (MERROR_FONT, -1);
392
393   MPLIST_DO (plist, encoding_list)
394     {
395       MFontEncoding *encoding;
396       MSymbol registry;
397
398       MSTRUCT_CALLOC (encoding, MERROR_FONT);
399
400       if (! MPLIST_PLIST_P (plist)
401           || (elt = MPLIST_PLIST (plist), mplist_length (elt) < 2)
402           || ! MPLIST_PLIST_P (elt))
403         MWARNING (MERROR_FONT);
404       registry = mfont__set_spec_from_plist (&encoding->spec,
405                                              MPLIST_PLIST (elt));
406       elt = MPLIST_NEXT (elt);
407       if (! MPLIST_SYMBOL_P (elt))
408         MWARNING (MERROR_FONT);
409       encoding->encoding_name = MPLIST_SYMBOL (elt);
410       elt = MPLIST_NEXT (elt);
411       if (MPLIST_TAIL_P (elt))
412         encoding->repertory_name = encoding->encoding_name;
413       else if (! MPLIST_SYMBOL_P (elt))
414         MWARNING (MERROR_FONT);
415       else
416         encoding->repertory_name = MPLIST_SYMBOL (elt);
417
418       if (registry == Mnil)
419         registry = Mt;
420       pl = mplist_add (pl, registry, encoding);
421       continue;
422
423     warning:
424       free (encoding);
425     }
426
427   M17N_OBJECT_UNREF (encoding_list);
428   return 0;
429 }
430
431 typedef struct {
432   MFont spec;
433   int resize;
434 } MFontResize;
435
436 static MPlist *font_resize_list;
437
438 /** Load font size table from the data <font size>.
439     The data has this form:
440         (FONT-SPEC RESIZE-FACTOR) ...
441     where FONT-SPEC has this form:
442         ([FOUNDRY FAMILY [WEIGHT [STYLE [STRETCH [ADSTYLE]]]]] REGISTRY)
443     All elements of FONT-SPEC are symbols.  */
444
445 static int
446 load_font_resize_table ()
447 {
448   MDatabase *mdb;
449   MPlist *size_adjust_list, *plist, *pl, *elt;
450
451   font_resize_list = pl = mplist ();
452
453   mdb = mdatabase_find (Mfont, msymbol ("resize"), Mnil, Mnil);
454   if (! mdb)
455     return -1;
456   if (! (size_adjust_list = (MPlist *) mdatabase_load (mdb)))
457     MERROR (MERROR_FONT, -1);
458
459   MPLIST_DO (plist, size_adjust_list)
460     {
461       MFontResize *resize;
462       MSymbol registry;
463
464       MSTRUCT_CALLOC (resize, MERROR_FONT);
465
466       if (! MPLIST_PLIST_P (plist)
467           || (elt = MPLIST_PLIST (plist), mplist_length (elt) != 2)
468           || ! MPLIST_PLIST_P (elt))
469         MWARNING (MERROR_FONT);
470       registry = mfont__set_spec_from_plist (&resize->spec,
471                                              MPLIST_PLIST (elt));
472       elt = MPLIST_NEXT (elt);
473       if (! MPLIST_INTEGER_P (elt))
474         MWARNING (MERROR_FONT);
475       resize->resize = MPLIST_INTEGER (elt);
476
477       if (registry == Mnil)
478         registry = Mt;
479       pl = mplist_add (pl, registry, resize);
480       continue;
481
482     warning:
483       free (resize);
484     }
485
486   M17N_OBJECT_UNREF (size_adjust_list);
487   return 0;
488 }
489
490 /** Return a font encoding (and repertory) of FONT.  */
491
492 static MFontEncoding *
493 find_encoding (MFont *font)
494 {
495   MSymbol registry = FONT_PROPERTY (font, MFONT_REGISTRY);
496   MFontEncoding *encoding = NULL;
497   MPlist *plist;
498
499   if (! font_encoding_list)
500     load_font_encoding_table ();
501   if (! MPLIST_TAIL_P (font_encoding_list))
502     while (1)
503       {
504         plist = font_encoding_list;
505         while (registry ? (plist = mplist_find_by_key (plist, registry))
506                : plist)
507           {
508             encoding = (MFontEncoding *) MPLIST_VAL (plist);
509             if (mfont__match_p (font, &encoding->spec, MFONT_ADSTYLE))
510               {
511                 if (! encoding->encoding_charset)
512                   encoding->encoding_charset
513                     = MCHARSET (encoding->encoding_name);
514                 if (! encoding->encoding_charset)
515                   {
516                     mplist_pop (plist);
517                     continue;
518                   }
519                 if (encoding->repertory_name == encoding->encoding_name)
520                   encoding->repertory_charset = encoding->encoding_charset;
521                 else if (encoding->repertory_name != Mnil)
522                   {
523                     encoding->repertory_charset
524                       = MCHARSET (encoding->repertory_name);
525                     if (! encoding->repertory_charset)
526                       {
527                         mplist_pop (plist);
528                         continue;
529                       }
530                   }
531                 return encoding;
532               }
533             else
534               plist = MPLIST_NEXT (plist);
535           }
536         if (registry == Mnil || registry == Mt)
537           break;
538         registry = Mt;
539       }
540   return &default_encoding;
541 }
542
543
544 \f
545 /* Internal API */
546
547 int
548 mfont__init ()
549 {
550   int i, shift;
551
552   Mfoundry = msymbol ("foundry");
553   mfont__property_table[MFONT_FOUNDRY].property = Mfoundry;
554   Mfamily = msymbol ("family");
555   mfont__property_table[MFONT_FAMILY].property = Mfamily;
556   Mweight = msymbol ("weight");
557   mfont__property_table[MFONT_WEIGHT].property = Mweight;
558   Mstyle = msymbol ("style");
559   mfont__property_table[MFONT_STYLE].property = Mstyle;
560   Mstretch = msymbol ("stretch");
561   mfont__property_table[MFONT_STRETCH].property = Mstretch;
562   Madstyle = msymbol ("adstyle");
563   mfont__property_table[MFONT_ADSTYLE].property = Madstyle;
564   Mregistry = msymbol ("registry");
565   mfont__property_table[MFONT_REGISTRY].property = Mregistry;
566
567   Msize = msymbol ("size");
568   Mresolution = msymbol ("resolution");
569
570   /* The first entry of each mfont__property_table must be Mnil so
571      that actual properties get positive numeric numbers.  */
572   for (i = 0; i <= MFONT_REGISTRY; i++)
573     {
574       MLIST_INIT1 (&mfont__property_table[i], names, 8);
575       MLIST_APPEND1 (&mfont__property_table[i], names, Mnil, MERROR_FONT);
576     }
577
578   /* Register predefined font property names.  */
579   for (i = 0; i <= MFONT_REGISTRY; i++)
580     {
581       int j;
582
583       for (j = 0; j < font_common_names[i].num; j++)
584         {
585           MSymbol sym = msymbol (font_common_names[i].names[j]);
586
587           if (sym == Mnil)
588             return -1;
589           if (msymbol_put(sym, mfont__property_table[i].property,
590                           (void *) (j + 1)) < 0)
591             return -1;
592           MLIST_APPEND1 (&mfont__property_table[i], names, sym, MERROR_FONT);
593         }
594     }
595
596   memset (mfont__driver_list, 0, sizeof mfont__driver_list);
597
598   /* Here, SHIFT starts from 1, not 0.  This is because the lowest bit
599      of a score is a flag for a scalable font (see the documentation
600      of mfont_score).  */
601   i = FONT_SCORE_PRIORITY_SIZE - 1;
602   for (shift = 1; i >= 0; i--)
603     {
604       font_score_shift_bits[font_score_priority[i]] = shift;
605       if (font_score_priority[i] == MFONT_SIZE)
606         shift += 16;
607       else
608         shift += 2;
609     }
610
611   MFONT_INIT (&default_encoding.spec);
612   default_encoding.encoding_name = Mnil;
613   default_encoding.encoding_charset = NULL;
614   default_encoding.repertory_name = Mnil;
615   default_encoding.repertory_charset = NULL;
616   {
617     char *path, *buf;
618     int bufsize;
619
620     mfont_freetype_path = mplist ();
621     bufsize = strlen (M17NDIR) + 7;
622     buf = alloca (bufsize);
623     sprintf (buf, "%s/fonts", M17NDIR);
624     mplist_add (mfont_freetype_path, Mstring, strdup (buf));
625     path = getenv ("M17NDIR");
626     if (path)
627       {
628         i = strlen (path) + 7;
629         if (i > bufsize)
630           buf = alloca (i);
631         sprintf (buf, "%s/fonts", path);
632         mplist_push (mfont_freetype_path, Mstring, strdup (buf));
633       }
634   }
635
636 #ifdef HAVE_FREETYPE
637   if (mfont__ft_init () < 0)
638     return -1;
639 #endif /* HAVE_FREETYPE */
640   if (mfont__flt_init () < 0)
641     return -1;
642
643   return 0;
644 }
645
646 void
647 mfont__fini ()
648 {
649   MPlist *plist;
650   int i;
651
652   mfont__flt_fini ();
653 #ifdef HAVE_FREETYPE
654   mfont__ft_fini ();
655 #endif /* HAVE_FREETYPE */
656
657   MPLIST_DO (plist, mfont_freetype_path)
658     free (MPLIST_VAL (plist));
659   M17N_OBJECT_UNREF (mfont_freetype_path);
660
661   if (font_resize_list)
662     {
663       MPLIST_DO (plist, font_resize_list)
664         free (MPLIST_VAL (plist));
665       M17N_OBJECT_UNREF (font_resize_list);
666       font_resize_list = NULL;
667     }
668   if (font_encoding_list)
669     {
670       MPLIST_DO (plist, font_encoding_list)
671         free (MPLIST_VAL (plist));
672       M17N_OBJECT_UNREF (font_encoding_list);
673       font_encoding_list = NULL;
674     }
675   for (i = 0; i <= MFONT_REGISTRY; i++)
676     MLIST_FREE1 (&mfont__property_table[i], names);
677 }
678
679 void
680 mfont__free_realized (MRealizedFont *rfont)
681 {
682   if (rfont->info)
683     M17N_OBJECT_UNREF (rfont->info);
684   free (rfont);
685 }
686
687
688 /* Compare FONT with REQUEST and return how much they differs.  If
689    FONT does not match with SPEC, return -1.  */
690
691 int
692 mfont__score (MFont *font, MFont *spec, MFont *request, int limited_size)
693 {
694   int score = 0;
695   int i = FONT_SCORE_PRIORITY_SIZE;
696
697   while (--i >= 0)
698     {
699       enum MFontProperty prop = font_score_priority[i];
700
701       if (request->property[prop] != 0)
702         {
703           int val = 0;
704
705           if (spec->property[prop] && font->property[prop]
706               && font->property[prop] != spec->property[prop])
707             return -1;
708           if (font->property[prop])
709             val = abs (font->property[prop] - request->property[prop]);
710           if (prop == MFONT_SIZE)
711             {
712               if (font->property[MFONT_RESY] == 0)
713                 /* This is a scalable font.  We prefer a bitmap font
714                    if the size matches exactly.  */
715                 score |= 1;
716               else
717                 score |= (val << font_score_shift_bits[MFONT_SIZE]
718                           | ((limited_size && val > 0) ? 0x400000 : 0));
719             }
720           else
721             score |= (val > 3 ? 3 : val) << font_score_shift_bits[prop];
722         }
723     }
724   return score;
725 }
726
727
728 /** Return 1 iff FONT matches SPEC.  */
729
730 int
731 mfont__match_p (MFont *font, MFont *spec, int prop)
732 {
733   for (; prop >= 0; prop--)
734     if (spec->property[prop] && font->property[prop]
735         && font->property[prop] != spec->property[prop])
736       return 0;
737   return 1;
738 }
739
740
741 void
742 mfont__set_spec_from_face (MFont *spec, MFace *face)
743 {
744   int i;
745
746   for (i = 0; i <= MFONT_ADSTYLE; i++)
747     mfont__set_property (spec, i, face->property[i]);
748   /* The value 1 is "iso8859-1".  */
749   spec->property[MFONT_REGISTRY] = 1;
750   spec->property[MFONT_SIZE] = (int) (face->property[MFACE_SIZE]);
751   spec->property[MFONT_RESY] = 0;
752   spec->property[MFONT_TYPE] = 0;
753 }
754
755
756 extern MSymbol
757 mfont__set_spec_from_plist (MFont *spec, MPlist *plist)
758 {
759   int i;
760   MSymbol spec_list[MFONT_REGISTRY + 1];
761   MSymbol registry;
762
763   MFONT_INIT (spec);
764   memset (spec_list, 0, sizeof spec_list);
765   for (i = 0; ! MPLIST_TAIL_P (plist); i++, plist = MPLIST_NEXT (plist))
766     {
767       if (! MPLIST_SYMBOL_P (plist))
768         MERROR (MERROR_FONT, Mnil);     
769       spec_list[i] = MPLIST_SYMBOL (plist);
770     }
771   registry = spec_list[i - 1];
772   mfont__set_property (spec, MFONT_REGISTRY, registry);
773   for (i -= 2; i >= 0; i--)
774     mfont__set_property (spec, i, spec_list[i]);
775   return registry;
776 }
777
778 MRealizedFont *
779 mfont__select (MFrame *frame, MFont *spec, MFont *request, int limited_size)
780 {
781   MSymbol registry = FONT_PROPERTY (spec, MFONT_REGISTRY);
782   MPlist *realized_font_list;
783   MRealizedFont *best_font[MFONT_TYPE_MAX];
784   int best_index;
785   int i;
786   int mdebug_mask = MDEBUG_FONT;
787
788   if (registry == Mnil)
789     registry = Mt;
790
791   MPLIST_DO (realized_font_list, frame->realized_font_list)
792     {
793       MRealizedFont *best = MPLIST_VAL (realized_font_list);
794
795       if (MPLIST_KEY (realized_font_list) == registry
796           && ! memcmp (&best->spec, spec, sizeof (MFont))
797           && ! memcmp (&best->request, request, sizeof (MFont)))
798         return best;
799     }
800
801   MDEBUG_PUSH_TIME ();
802   best_index = -1;
803   for (i = 0; i < MFONT_TYPE_MAX; i++)
804     {
805       MFontDriver *driver = mfont__driver_list[i];
806
807       best_font[i] = (driver
808                       ? (driver->select) (frame, spec, request, limited_size)
809                       : NULL);
810       if (best_font[i]
811           && (best_index < 0
812               || best_font[best_index]->score > best_font[i]->score))
813         best_index = i;
814     }
815   for (i = 0; i < MFONT_TYPE_MAX; i++)
816     {
817       if (i == best_index)
818         mplist_add (frame->realized_font_list, registry, best_font[i]);
819       else if (best_font[i])
820         free (best_font[i]);
821     }
822
823   if (mdebug__flag & mdebug_mask)
824     {
825       char buf1[256], buf2[256];
826       MFont font = *spec;
827
828       for (i = 0; i < MFONT_PROPERTY_MAX; i++)
829         if (! font.property[i])
830           font.property[i] = request->property[i];
831       gen_font_name (buf2, &font);
832
833       if (best_index >= 0)
834         MDEBUG_PRINT_TIME ("FONT", 
835                            (stderr, " to select <%s> from <%s>.",
836                             gen_font_name (buf1,
837                                            &best_font[best_index]->font),
838                             buf2));
839       else
840         MDEBUG_PRINT_TIME ("FONT", (stderr, " to fail to find <%s>.", buf2));
841       MDEBUG_POP_TIME ();
842     }
843
844   return (best_index >= 0 ? best_font[best_index] : NULL);
845 }
846
847
848 /** Open a font specified in RFONT.  Return 0 if successfully
849     opened, otherwise return -1.  */
850
851 int
852 mfont__open (MRealizedFont *rfont)
853 {
854   MPlist *realized_font_list;
855   MSymbol registry = FONT_PROPERTY (&rfont->font, MFONT_REGISTRY);
856
857   if (rfont->status)
858     mdebug_hook ();
859
860   MPLIST_DO (realized_font_list, rfont->frame->realized_font_list)
861     {
862       MRealizedFont *this_rfont = MPLIST_VAL (realized_font_list);
863
864       if (this_rfont->status != 0
865           && MPLIST_KEY (realized_font_list) == registry
866           && ! memcmp (&this_rfont->font, &rfont->font, sizeof (MFont)))
867         {
868           if (rfont->info)
869             M17N_OBJECT_UNREF (rfont->info);
870           rfont->info = this_rfont->info;
871           M17N_OBJECT_REF (this_rfont->info);
872           rfont->status = this_rfont->status;
873           return (this_rfont->status > 0 ? 0 : -1);
874         }
875     }
876
877   return (rfont->driver->open) (rfont);
878 }
879
880 void
881 mfont__close (MRealizedFont *rfont)
882 {
883   (rfont->driver->close) (rfont);
884 }
885
886 void
887 mfont__resize (MFont *spec, MFont *request)
888 {
889   MSymbol registry = FONT_PROPERTY (spec, MFONT_REGISTRY);
890   MFontResize *resize;
891   MPlist *plist;
892
893   if (! font_resize_list)
894     load_font_resize_table ();
895   if (! MPLIST_TAIL_P (font_resize_list))
896     while (1)
897       {
898         plist = font_resize_list;
899         while (registry ? (plist = mplist_find_by_key (plist, registry))
900                : plist)
901           {
902             resize = (MFontResize *) MPLIST_VAL (plist);
903             if (mfont__match_p (spec, &resize->spec, MFONT_ADSTYLE))
904               {
905                 request->property[MFONT_SIZE]
906                   = request->property[MFONT_SIZE] * resize->resize / 100;
907                 return;
908               }
909             plist = MPLIST_NEXT (plist);
910           }
911         if (registry == Mt)
912           break;
913         registry = Mt;
914       }
915 }
916
917 /* Return 1 if C is encodable, 0, if C is not encodable, -1 if it
918    can't be decided now.  */
919
920 int
921 mfont__encodable_p (MRealizedFont *rfont, MSymbol layouter_name, int c)
922 {
923   MFontEncoding *encoding;
924
925   if (layouter_name != Mnil)
926     return (mfont__flt_encode_char (layouter_name, c)
927             != MCHAR_INVALID_CODE);
928   if (! rfont->encoding)
929     rfont->encoding = find_encoding (&rfont->spec);
930   encoding = rfont->encoding;
931   if (! encoding->repertory_charset)
932     return -1;
933   return (ENCODE_CHAR (encoding->repertory_charset, c) != MCHAR_INVALID_CODE);
934 }
935
936 unsigned
937 mfont__encode_char (MRealizedFont *rfont, int c)
938 {
939   MFontEncoding *encoding;
940   unsigned code;
941
942   if (rfont->layouter != Mnil)
943     return mfont__flt_encode_char (rfont->layouter, c);
944   if (! rfont->encoding)
945     rfont->encoding = find_encoding (&rfont->font);
946   encoding = rfont->encoding;
947   if (! encoding->encoding_charset)
948     return MCHAR_INVALID_CODE;
949   code = ENCODE_CHAR (encoding->encoding_charset, c);
950   if (code == MCHAR_INVALID_CODE)
951     return MCHAR_INVALID_CODE;
952   if (! encoding->repertory_charset)
953     return (rfont->driver->encode_char) (rfont, c, code);
954   if (ENCODE_CHAR (encoding->repertory_charset, c) == MCHAR_INVALID_CODE)
955     return MCHAR_INVALID_CODE;
956   return code;
957 }
958
959 void
960 mfont__get_metric (MRealizedFont *rfont, MGlyph *g)
961 {
962   (rfont->driver->find_metric) (rfont, g);
963 }
964
965
966 void
967 mfont__set_property (MFont *font, enum MFontProperty key, MSymbol val)
968 {
969   int numeric;
970
971   if (val == Mnil)
972     numeric = 0;
973   else
974     {
975       numeric = FONT_PROPERTY_NUMERIC (val, key);
976       if (! numeric)
977         {
978           numeric = mfont__property_table[key].used;
979           MLIST_APPEND1 (mfont__property_table + key, names, val, MERROR_FONT);
980           SET_FONT_PROPERTY_NUMERIC (val, key, numeric);
981         }
982     }
983   font->property[key] = numeric;
984 }
985
986 void
987 mfont__set_spec (MFont *font, MSymbol *attrs,
988                  unsigned short size, unsigned short resy)
989 {
990   int i;
991
992   for (i = 0; i <= MFONT_REGISTRY; i++)
993     mfont__set_property (font, i, attrs[i]);
994   font->property[MFONT_SIZE] = size;
995   font->property[MFONT_RESY] = resy;
996 }
997
998 /*** @} */
999 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
1000
1001 \f
1002
1003 /* External API */
1004
1005 /*** @addtogroup m17nFont */
1006 /*** @{ */
1007 /*=*/
1008
1009 /***en @name Variables: Keys of font property.  */
1010 /***ja @name ÊÑ¿ô: ¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£¤ò»ØÄꤹ¤ëÄêµÁºÑ¤ß¥·¥ó¥Ü¥ë */
1011 /*** @{ */
1012 /*=*/
1013
1014 /***en
1015     @brief Key of font property specifying foundry.
1016
1017     The variable #Mfoundry is a symbol of name <tt>"foundry"</tt> and
1018     is used as a key of font property and face property.  The property
1019     value must be a symbol whose name is a foundry name of a font.  */
1020
1021 MSymbol Mfoundry;
1022
1023 /***en
1024     @brief Key of font property specifying foundry.
1025
1026     The variable #Mfamily is a symbol of name <tt>"family"</tt> and is
1027     used as a key of font property and face property.  The property
1028     value must be a symbol whose name is a family name of a font.  */ 
1029
1030 /***ja
1031     @brief ¥Õ¥©¥ó¥È¤Î family ¥×¥í¥Ñ¥Æ¥£¤ò»ØÄꤹ¤ë¤¿¤á¤Î¥·¥ó¥Ü¥ë
1032
1033     ¥·¥ó¥Ü¥ë @c Mfamily ¤Ï <tt>"family"</tt> ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Á¡¢¥Õ¥©¥ó
1034     ¥È¤Î family ¥×¥í¥Ñ¥Æ¥£¤ÎÃͤòÆÀ¤ë¤È¤­¤Ë´Ø¿ô mfont_get_prop () ¤Î°ú
1035     ¿ô¤È¤·¤Æ»È¤ï¤ì¤ë¡£
1036
1037     ¤Þ¤¿¤³¤Î¥·¥ó¥Ü¥ë¤Ï¡¢¥Õ¥§¡¼¥¹Á´ÂΤˤª¤±¤ë¥Ç¥Õ¥©¥ë¥È¤Î family ¤ò»ØÄê
1038     ¤¹¤ëºÝ¤Ë¡¢¥Õ¥§¡¼¥¹¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼¤È¤·¤Æ¤â»È¤ï¤ì¤ë¡£  */
1039
1040 MSymbol Mfamily;
1041
1042 /***en
1043     @brief Key of font property specifying weight.
1044
1045     The variable #Mweight is a symbol of name <tt>"weight"</tt> and is
1046     used as a key of font property and face property.  The property
1047     value must be a symbol whose name is a weight name of a font (e.g
1048     "medium", "bold").  */ 
1049
1050 /***ja
1051     @brief ¥Õ¥©¥ó¥È¤Î weight ¥×¥í¥Ñ¥Æ¥£¤ò»ØÄꤹ¤ë¤¿¤á¤Î¥·¥ó¥Ü¥ë
1052
1053     ¥·¥ó¥Ü¥ë @c Mweight ¤Ï <tt>"weight"</tt> ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Á¡¢¥Õ¥©¥ó
1054     ¥È¤Î weight ¥×¥í¥Ñ¥Æ¥£¤ÎÃͤòÆÀ¤ë¤È¤­¤Ë´Ø¿ô mfont_get_prop () ¤Î°ú
1055     ¿ô¤È¤·¤Æ»È¤ï¤ì¤ë¡£
1056
1057     ¤Þ¤¿¤³¤Î¥·¥ó¥Ü¥ë¤Ï¡¢¥Õ¥§¡¼¥¹Á´ÂΤˤª¤±¤ë¥Ç¥Õ¥©¥ë¥È¤Î weight ¤ò»ØÄê
1058     ¤¹¤ëºÝ¤Ë¡¢¥Õ¥§¡¼¥¹¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼¤È¤·¤Æ¤â»È¤ï¤ì¤ë¡£  */
1059
1060 MSymbol Mweight;
1061
1062 /***en
1063     @brief Key of font property specifying style.
1064
1065     The variable #Mstyle is a symbol of name <tt>"style"</tt> and is
1066     used as a key of font property and face property.  The property
1067     value must be a symbol whose name is a style name of a font (e.g
1068     "r", "i", "o").  */ 
1069
1070 /***ja
1071     @brief ¥Õ¥©¥ó¥È¤Î style ¥×¥í¥Ñ¥Æ¥£¤ò»ØÄꤹ¤ë¤¿¤á¤Î¥·¥ó¥Ü¥ë
1072
1073     ¥·¥ó¥Ü¥ë @c Mstyle ¤Ï <tt>"style"</tt> ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Á¡¢¥Õ¥©¥ó¥È
1074     ¤Î style ¥×¥í¥Ñ¥Æ¥£¤ÎÃͤòÆÀ¤ë¤È¤­¤Ë´Ø¿ô mfont_get_prop () ¤Î°ú¿ô¤È
1075     ¤·¤Æ»È¤ï¤ì¤ë¡£
1076
1077     ¤Þ¤¿¤³¤Î¥·¥ó¥Ü¥ë¤Ï¡¢¥Õ¥§¡¼¥¹Á´ÂΤˤª¤±¤ë¥Ç¥Õ¥©¥ë¥È¤Î style ¤ò»ØÄê
1078     ¤¹¤ëºÝ¤Ë¡¢¥Õ¥§¡¼¥¹¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼¤È¤·¤Æ¤â»È¤ï¤ì¤ë¡£  */
1079
1080 MSymbol Mstyle;
1081
1082 /***en
1083     @brief Key of font property specifying stretch.
1084
1085     The variable #Mstretch is a symbol of name <tt>"stretch"</tt> and
1086     is used as a key of font property and face property.  The property
1087     value must be a symbol whose name is a stretch name of a font (e.g
1088     "normal", "condensed").  */ 
1089
1090 /***ja
1091     @brief ¥Õ¥©¥ó¥È¤Î stretch ¥×¥í¥Ñ¥Æ¥£¤ò»ØÄꤹ¤ë¤¿¤á¤Î¥·¥ó¥Ü¥ë
1092
1093     ¥·¥ó¥Ü¥ë @c Mstretch ¤Ï <tt>"stretch"</tt> ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Á¡¢¥Õ¥©
1094     ¥ó¥È¤Î stretch ¥×¥í¥Ñ¥Æ¥£¤ÎÃͤòÆÀ¤ë¤È¤­¤Ë´Ø¿ô mfont_get_prop () ¤Î
1095     °ú¿ô¤È¤·¤Æ»È¤ï¤ì¤ë¡£
1096
1097     ¤Þ¤¿¤³¤Î¥·¥ó¥Ü¥ë¤Ï¡¢¥Õ¥§¡¼¥¹Á´ÂΤˤª¤±¤ë¥Ç¥Õ¥©¥ë¥È¤Î stretch ¤ò»Ø
1098     Äꤹ¤ëºÝ¤Ë¡¢¥Õ¥§¡¼¥¹¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼¤È¤·¤Æ¤â»È¤ï¤ì¤ë¡£  */
1099
1100 MSymbol Mstretch;
1101
1102 /***en
1103     @brief Key of font property specifying additional style.
1104
1105     The variable #Madstyle is a symbol of name <tt>"adstyle"</tt> and
1106     is used as a key of font property and face property.  The property
1107     value must be a symbol whose name is an additional style name of a
1108     font (e.g "serif", "", "sans").  */ 
1109
1110 /***ja
1111     @brief ¥Õ¥©¥ó¥È¤Î adstyle ¥×¥í¥Ñ¥Æ¥£¤ò»ØÄꤹ¤ë¤¿¤á¤Î¥·¥ó¥Ü¥ë
1112
1113     ¥·¥ó¥Ü¥ë @c Madstyle ¤Ï <tt>"adstyle"</tt> ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Á¡¢¥Õ¥©
1114     ¥ó¥È¤Î adstyle ¥×¥í¥Ñ¥Æ¥£¤ÎÃͤòÆÀ¤ë¤È¤­¤Ë´Ø¿ô mfont_get_prop () ¤Î
1115     °ú¿ô¤È¤·¤Æ»È¤ï¤ì¤ë¡£
1116
1117     ¤Þ¤¿¤³¤Î¥·¥ó¥Ü¥ë¤Ï¡¢¥Õ¥§¡¼¥¹Á´ÂΤˤª¤±¤ë¥Ç¥Õ¥©¥ë¥È¤Î adstyle ¤ò»Ø
1118     Äꤹ¤ëºÝ¤Ë¡¢¥Õ¥§¡¼¥¹¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼¤È¤·¤Æ»È¤ï¤ì¤ë¡£  */
1119
1120 MSymbol Madstyle;
1121
1122 /***en
1123     @brief Key of font property specifying registry.
1124
1125     The variable #Mregistry is a symbol of name <tt>"registry"</tt>
1126     and is used as a key of font property.  The property value must be
1127     a symbol whose name is a registry name a font registry
1128     (e.g. "iso8859-1", "jisx0208.1983-0").  */ 
1129
1130 /***ja
1131     @brief ¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£ registry ¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë
1132
1133     ¥·¥ó¥Ü¥ë @c Mregistry ¤Ï <tt>"registry"</tt> ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Á¡¢¥Õ¥©
1134     ¥ó¥È¤Î registry ¥×¥í¥Ñ¥Æ¥£¤ÎÃͤòÆÀ¤ë¤È¤­¤Ë¡¢´Ø¿ô mfont_get_prop () 
1135     ¤Î°ú¿ô¤È¤·¤Æ»È¤ï¤ì¤ë¡£  */
1136
1137 MSymbol Mregistry;
1138
1139 /***en
1140     @brief Key of font property specifying size.
1141
1142     The variable #Msize is a symbol of name <tt>"size"</tt> and is
1143     used as a key of font property and face property.  The property
1144     value must be an integer specifying a font design size in the unit
1145     of 1/10 point (on 100 dpi display).  */ 
1146
1147 /***ja
1148     @brief ¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£ size ¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë
1149
1150     ¥·¥ó¥Ü¥ë @c Msize ¤Ï <tt>"size"</tt> ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Á¡¢¥Õ¥©¥ó¥È¤Î size ¥×¥í
1151     ¥Ñ¥Æ¥£¤ÎÃͤòÆÀ¤ë¤È¤­¤Ë´Ø¿ô mfont_get_prop () ¤Î°ú¿ô¤È¤·¤Æ»È¤ï¤ì¤ë¡£
1152
1153     ¤Þ¤¿¤³¤Î¥·¥ó¥Ü¥ë¤Ï¡¢¥Õ¥§¡¼¥¹Á´ÂΤˤª¤±¤ë¥Ç¥Õ¥©¥ë¥È¤Î size ¤ò»ØÄꤹ
1154     ¤ëºÝ¤Ë¡¢¥Õ¥§¡¼¥¹¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼¤È¤·¤Æ»È¤ï¤ì¤ë¡£  */
1155
1156 MSymbol Msize;
1157
1158 /***en
1159     @brief Key of font property specifying resolution.
1160
1161     The variable #Mresolution is a symbol of name <tt>"size"</tt> and
1162     is used as a key of font property and face property.  The property
1163     value must be an integer to specifying a font resolution in the
1164     unit of dots per inch (dpi).  */ 
1165
1166 /***ja
1167     @brief ¥Õ¥©¥ó¥È¥×¥í¥Ñ¥Æ¥£ resolution ¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë
1168
1169     ¥·¥ó¥Ü¥ë @c Mresolution ¤Ï <tt>"resolution"</tt> ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Á¡¢
1170     ¥Õ¥©¥ó¥È¤Î resolution ¥×¥í¥Ñ¥Æ¥£¤ÎÃͤòÆÀ¤ë¤È¤­¤Ë¡¢´Ø¿ô 
1171     mfont_get_prop () ¤Î°ú¿ô¤È¤·¤Æ»È¤ï¤ì¤ë¡£  */
1172
1173 MSymbol Mresolution;
1174
1175 /*=*/
1176 /*** @} */
1177 /*=*/
1178
1179 /***en
1180     @brief List of font files and directories that contain font files.
1181
1182     The variable @c mfont_freetype_path is a plist of FreeType font
1183     files and directories that contain FreeType font files.  Key of
1184     the element is @c Mstring, and the value is a string that
1185     represents a font file or a directory.
1186
1187     The macro M17N_INIT () sets up this variable to contain the
1188     sub-directory "fonts" of the m17n database and the environment
1189     variable "M17NDIR".  The first call of mframe () creates the
1190     internal list of the actually available fonts from this variable.
1191     Thus, an application program, if necessary, must modify the
1192     variable before calling mframe ().  If it is going to add a new
1193     element, value must be a string that can be safely freed.
1194
1195     If the m17n library is not configured to use the FreeType library,
1196     this variable is not used.  */
1197
1198 MPlist *mfont_freetype_path;
1199
1200 /*=*/
1201
1202 /***en
1203     @brief Create a new font.
1204
1205     The mfont () function creates a new font object that has no
1206     property.
1207
1208     @return
1209     This function returns a pointer to the created font object.  */
1210
1211
1212 MFont *
1213 mfont ()
1214 {
1215   MFont *font;
1216
1217   MSTRUCT_CALLOC (font, MERROR_FONT);
1218   return font;
1219 }
1220
1221 /*=*/
1222
1223 /***en
1224     @brief Create a new font from fontname.
1225
1226     The mfont_from_name () function creates a new font object.  The
1227     properties are extracted fontname $NAME.
1228
1229     How to extract properties is window system dependent.  The m17n-X
1230     library parses $NAME as XLFD (X Logical Font Description).
1231
1232     @return
1233     If the operation was successful, this function returns a pointer
1234     to the created font.  Otherwise it returns @c NULL.  */
1235
1236 /***ja
1237     @brief ¥Õ¥©¥ó¥È̾¤«¤é¥Õ¥©¥ó¥È¤òºî¤ë
1238
1239     ´Ø¿ô mfont_from_name () ¤Ï¥Õ¥©¥ó¥È̾ $NAME ¤ò²òÀϤ·¡¢¿·¤·¤¤¥Õ¥©¥ó
1240     ¥È¤òºî¤ë¡£
1241
1242     ¥Õ¥©¥ó¥È̾¤Îʸˡ¤Ï¥¦¥£¥ó¥É¥¦¥·¥¹¥Æ¥à¤Ë°Í¸¤¹¤ë¡£m17n-X ¥é¥¤¥Ö¥é¥ê
1243     ¤Î¾ì¹ç¤Ï XLFD (X Logical Font Description) ¤Ë½¾¤¦¡£
1244
1245     @return
1246     ½èÍý¤¬À®¸ù¤¹¤ì¤Ð mfont_from_name () ¤Ï¿·¤·¤¯ºî¤é¤ì¤¿¥Õ¥©¥ó¥È¤Ø¤Î
1247     ¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£$NAME ¤Î²òÀϤ˼ºÇÔ¤·¤¿¾ì¹ç¤Ï @c NULL ¤òÊÖ¤¹¡£  */
1248
1249 MFont *
1250 mfont_from_name (char *name)
1251 {
1252   MFont template, *font;
1253
1254   if (mwin__parse_font_name (name, &template) < 0)
1255     return NULL;
1256   MSTRUCT_CALLOC (font, MERROR_FONT);
1257   *font = template;
1258   return font;
1259 }
1260
1261 /*=*/
1262
1263 /***en
1264     @brief Return a copy of a font.
1265
1266     The mfont_copy () function returns a new copy of $FONT.  */
1267
1268 MFont *
1269 mfont_copy (MFont *font)
1270 {
1271   MFont *copy;
1272
1273   MSTRUCT_MALLOC (copy, MERROR_FONT);
1274   *copy = *font;
1275   return copy;
1276 }
1277
1278 /*=*/
1279
1280 /***en
1281     @brief Create a fontname from a font.
1282
1283     The mfont_name () function creates a fontname string created from
1284     $FONT.
1285
1286     The syntax of fontname is window system dependent.  The m17n-X
1287     library returns a fontname conforming to XLFD (X Logical Font
1288     Description).
1289
1290     @return
1291     This function returns the created fontname string, which is not freed
1292     unless the user explicitly does so by free ().  */
1293
1294 char *
1295 mfont_name (MFont *font)
1296 {
1297   return mwin__build_font_name (font);
1298 }
1299
1300 /*=*/
1301
1302 /***en
1303     @brief Get a property value of a font.
1304
1305     The mfont_get_prop () function gets the value of $KEY property of
1306     $FONT.  $KEY must be one of the following symbols:
1307
1308         @c Mfamily, @c Mweight, @c Mstyle, @c Mstretch,
1309         @c Madstyle, @c Mregistry, @c Msize, @c Mresolution.
1310
1311     @return
1312     If $KEY is @c Mfamily, @c Mweight, @c Mstyle, @c Mstretch, @c
1313     Madstyle, or @c Mregistry, this function returns the
1314     corresponding value as a symbol.  If the font does not have $KEY
1315     property, it returns @c Mnil.
1316
1317     If $KEY is @c Msize or @c Mresolution, this function returns the
1318     corresponding value as an integer.  If the font does not have $KEY
1319     property, it returns 0.
1320
1321     If $KEY is something else, it returns @c NULL and assigns an error
1322     code to the external variable @c merror_code.  */
1323
1324 /***ja
1325     @brief ¥Õ¥©¥ó¥È¤Î¥×¥í¥Ñ¥Æ¥£ÃͤòÆÀ¤ë
1326
1327     ´Ø¿ô mfont_get_prop () ¤Ï¥Õ¥©¥ó¥È $FONT ¤Î¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥­¡¼¤¬ 
1328     $KEY ¤Ç¤¢¤ë¤â¤Î¤ÎÃͤòÊÖ¤¹¡£$KEY ¤Ï°Ê²¼¤Î¥·¥ó¥Ü¥ë¤Î¤¤¤º¤ì¤«¤Ç¤Ê¤±¤ì
1329     ¤Ð¤Ê¤é¤Ê¤¤¡£
1330
1331         @c Mfamily, @c Mweight, @c Mstyle, @c Mstretch,
1332         @c Madstyle, @c Mregistry, @c Msize, @c Mresolution.
1333
1334     @return
1335     ¤â¤· $KEY ¤¬ @c Msize ¤¢¤ë¤¤¤Ï @c Mresolution ¤Î¾ì¹ç¡¢
1336     mfont_get_prop () ¤ÏÀ°¿ô¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¥·¥ó¥Ü¥ë¤òÊÖ¤¹¡£¥¨¥é¡¼
1337     ¤¬¸¡½Ð¤µ¤ì¤¿¾ì¹ç¤Ï @c NULL ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô @c merror_code ¤Ë¥¨¥é¡¼
1338     ¥³¡¼¥É¤òÀßÄꤹ¤ë¡£  */
1339
1340 void *
1341 mfont_get_prop (MFont *font, MSymbol key)
1342 {
1343   if (key == Mfoundry)
1344     return (void *) FONT_PROPERTY (font, MFONT_FOUNDRY);
1345   if (key == Mfamily)
1346     return (void *) FONT_PROPERTY (font, MFONT_FAMILY);
1347   if (key == Mweight)
1348     return (void *) FONT_PROPERTY (font, MFONT_WEIGHT);
1349   if (key == Mstyle)
1350     return (void *) FONT_PROPERTY (font, MFONT_STYLE);
1351   if (key == Mstretch)
1352     return (void *) FONT_PROPERTY (font, MFONT_STRETCH);
1353   if (key == Madstyle)
1354     return (void *) FONT_PROPERTY (font, MFONT_ADSTYLE);
1355   if (key == Mregistry)
1356     return (void *) FONT_PROPERTY (font, MFONT_REGISTRY);
1357   if (key == Msize)
1358     {
1359       int size = font->property[MFONT_SIZE];
1360       return (void *) size;
1361     }
1362   if (key == Mresolution)
1363     {
1364       int resy = font->property[MFONT_RESY];
1365       return (void *) resy;
1366     }
1367
1368   MERROR (MERROR_FONT, NULL);
1369 }
1370
1371
1372 /*=*/
1373 /***en
1374     @brief Put a property value to a font.
1375
1376     The mfont_put_prop () function puts a font property whose key is
1377     $KEY and value is $VAL to $FONT.  $KEY must be one of the following
1378     symbols:
1379
1380         @c Mfamily, @c Mweight, @c Mstyle, @c Mstretch,
1381         @c Madstyle, @c Mregistry, @c Msize, @c Mresolution.
1382
1383     If $KEY is @c Msize of @c Mresolution, $VAL must be an integer.
1384     Otherwise, $VAL must be a symbol.  */
1385
1386 int
1387 mfont_put_prop (MFont *font, MSymbol key, void *val)
1388 {
1389   if (key == Mfoundry)
1390     mfont__set_property (font, MFONT_FOUNDRY, (MSymbol) val);
1391   else if (key == Mfamily)
1392     mfont__set_property (font, MFONT_FAMILY, (MSymbol) val);
1393   else if (key == Mweight)
1394     mfont__set_property (font, MFONT_WEIGHT, (MSymbol) val);
1395   else if (key == Mstyle)
1396     mfont__set_property (font, MFONT_STYLE, (MSymbol) val);
1397   else if (key == Mstretch)
1398     mfont__set_property (font, MFONT_STRETCH, (MSymbol) val);
1399   else if (key == Madstyle)
1400     mfont__set_property (font, MFONT_ADSTYLE, (MSymbol) val);
1401   else if (key == Mregistry)
1402     mfont__set_property (font, MFONT_REGISTRY, (MSymbol) val);
1403   else if (key == Msize)
1404     {
1405       unsigned size = (unsigned) val;
1406       font->property[MFONT_SIZE] = size;
1407     }
1408   else if (key == Mresolution)
1409     {
1410       unsigned resy = (unsigned) val;
1411       font->property[MFONT_RESY] =  resy;
1412     }
1413   else
1414     MERROR (MERROR_FONT, -1);
1415   return 0;
1416 }
1417
1418 /*=*/
1419
1420 /***en
1421     @brief Return the font selection priority.
1422
1423     The mfont_selection_priority () function returns a newly created
1424     array of six symbols.  The elements are the following
1425     keys of font properties ordered by priority.
1426
1427         @c Mfamily, @c Mweight, @c Mstyle, @c Mstretch,
1428         @c Madstyle, @c Msize.
1429
1430    The m17n library selects the best matching font according to the
1431    order of this array.  A font that has a different value for a
1432    property of lower priority is preferred to a font that has a
1433    different value for a property of higher priority.  */
1434
1435 MSymbol *
1436 mfont_selection_priority ()
1437 {
1438   MSymbol *keys;
1439   int i;
1440
1441   MTABLE_MALLOC (keys, FONT_SCORE_PRIORITY_SIZE, MERROR_FONT);
1442   for (i = 0; i < FONT_SCORE_PRIORITY_SIZE; i++)
1443     {
1444       enum MFontProperty prop = font_score_priority[i];
1445
1446       if (prop == MFONT_SIZE)
1447         keys[i] = Msize;
1448       else if (prop == MFONT_ADSTYLE)
1449         keys[i] = Madstyle;
1450       else if (prop == MFONT_FAMILY)
1451         keys[i] = Mfamily;
1452       else if (prop == MFONT_WEIGHT)
1453         keys[i] = Mweight;
1454       else if (prop == MFONT_STYLE)
1455         keys[i] = Mstyle;
1456       else if (prop == MFONT_STRETCH)
1457         keys[i] = Mstretch;
1458       else
1459         keys[i] = Mfoundry;
1460     }
1461   return keys;
1462 }
1463
1464 /*=*/
1465
1466 /***en
1467     @brief Set the font selection priority.
1468
1469     The mfont_set_selection_priority () function sets font selection
1470     priority according to $KEYS, which is an array of six symbols.
1471     Each element must be one of the below.  No two elements must be
1472     the same.
1473
1474         @c Mfamily, @c Mweight, @c Mstyle, @c Mstretch,
1475         @c Madstyle, @c Msize.
1476
1477     See the documentation of the function mfont_selection_priority ()
1478     for details.  */
1479
1480 int
1481 mfont_set_selection_priority (MSymbol *keys)
1482 {
1483   int priority[FONT_SCORE_PRIORITY_SIZE];
1484   int i, j;
1485
1486   for (i = 0; i < FONT_SCORE_PRIORITY_SIZE; i++, keys++)
1487     {
1488       enum MFontProperty prop;
1489
1490       if (*keys == Msize)
1491         prop = MFONT_SIZE;
1492       else if (*keys == Madstyle)
1493         prop = MFONT_ADSTYLE;
1494       else if (*keys == Mfamily)
1495         prop = MFONT_FAMILY;
1496       else if (*keys == Mweight)
1497         prop = MFONT_WEIGHT;
1498       else if (*keys == Mstyle)
1499         prop = MFONT_STYLE;
1500       else if (*keys == Mstretch)
1501         prop = MFONT_STRETCH;
1502       else if (*keys == Mfoundry)
1503         prop = MFONT_FOUNDRY;
1504       else
1505         /* Invalid element.  */
1506         return -1;
1507       for (j = 0; j < i; j++)
1508         if (priority[j] == prop)
1509           /* Duplicated element.  */
1510           return -1;
1511       priority[i] = prop;
1512     }
1513   for (i = 0; i < FONT_SCORE_PRIORITY_SIZE; i++)
1514     font_score_priority[i] = priority[i];
1515   return 0;
1516 }
1517
1518 /*=*/
1519
1520 /***en
1521     @brief Find a font.
1522
1523     The mfont_find () function returns a pointer to the available font
1524     that matches best the specification $SPEC on frame $FRAME.
1525
1526     $SCORE, if not NULL, must point to a place to store the score
1527     value that indicates how well the found font matches to $SPEC.  A
1528     smaller score means a better match.  */
1529
1530 /***ja
1531     @brief ¥Õ¥©¥ó¥È¤òõ¤¹
1532
1533     ´Ø¿ô mfont_find () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¾å¤Ç¥Õ¥©¥ó¥ÈÄêµÁ $SPEC ¤Ë¤â¤Ã
1534     ¤È¤â¶á¤¤¥Õ¥©¥ó¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£  */
1535
1536 MFont *
1537 mfont_find (MFrame *frame, MFont *spec, int *score, int limited_size)
1538 {
1539   MFont spec_copy;
1540   MRealizedFont *rfont;
1541
1542   MFONT_INIT (&spec_copy);
1543   spec_copy.property[MFONT_REGISTRY] = spec->property[MFONT_REGISTRY];
1544
1545   rfont = mfont__select (frame, &spec_copy, spec, limited_size);
1546   if (!rfont)
1547     return NULL;
1548   if (score)
1549     *score = rfont->score;
1550   return &rfont->font;
1551 }
1552
1553 /*=*/
1554 /***en
1555     @brief Set encoding of a font.
1556
1557     The mfont_set_encoding () function sets the encoding information
1558     of $FONT.
1559
1560     If $ENCODING_NAME is be a symbol representing a charset that has
1561     the same encoding as the font.
1562
1563     If $REPERTORY_NAME @c Mnil or a symbol representing a charset that
1564     has the same repertory as the font.  If it is @c Mnil, whether a
1565     specific character is supported by the font is asked to each font
1566     driver.
1567
1568     @return
1569     If the operation was successful, this function returns 0.
1570     Otherwise it returns -1 and assigns an error code to the external
1571     variable @c merror_code.  */
1572
1573 int
1574 mfont_set_encoding (MFont *font, MSymbol encoding_name, MSymbol repertory_name)
1575 {
1576   MCharset *encoding_charset = MCHARSET (encoding_name);
1577   MCharset *repertory_charset;
1578   MSymbol registry;
1579   MFontEncoding *encoding;
1580   MPlist *plist;
1581
1582   if (! encoding_charset)
1583     MERROR (MERROR_FONT, -1);
1584   if (repertory_name != Mnil)
1585     {
1586       repertory_charset = MCHARSET (repertory_name);
1587       if (! repertory_charset)
1588         MERROR (MERROR_FONT, -1);
1589     }
1590   else
1591     repertory_charset = NULL;
1592
1593   MSTRUCT_CALLOC (encoding, MERROR_FONT);
1594   encoding->spec = *font;
1595   encoding->encoding_name = encoding_name;
1596   encoding->encoding_charset = encoding_charset;
1597   encoding->repertory_name = repertory_name;
1598   encoding->repertory_charset = repertory_charset;
1599   registry = FONT_PROPERTY (font, MFONT_REGISTRY);
1600   if (registry == Mnil)
1601     registry = Mt;
1602   if (! font_encoding_list)
1603     load_font_encoding_table ();
1604   mplist_push (font_encoding_list, registry, encoding);
1605   MPLIST_DO (plist, MPLIST_NEXT (font_encoding_list))
1606     if (! memcmp (font, &((MFontEncoding *) MPLIST_VAL (plist))->spec,
1607                   sizeof (MFont)))
1608       {
1609         mplist_pop (plist);
1610         break;
1611       }
1612   return 0;
1613 }
1614
1615 /*** @} */
1616
1617 /*** @addtogroup m17nDebug */
1618 /*=*/
1619 /*** @{ */
1620
1621 /***en
1622     @brief Dump a font
1623
1624     The mdebug_dump_font () function prints $FONT in a human readable
1625     way to the stderr.
1626
1627     @return
1628     This function returns $FONT.  */
1629
1630 MFont *
1631 mdebug_dump_font (MFont *font)
1632 {
1633   char *name = mwin__build_font_name (font);
1634
1635   fprintf (stderr, "%s", name);
1636   free (name);
1637   return font;
1638 }
1639
1640 /*** @} */
1641
1642 /*
1643   Local Variables:
1644   coding: euc-japan
1645   End:
1646 */