1 /* font.c -- font module.
2    Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
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    Boston, MA 02110-1301 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 
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
load_font_encoding_table()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
load_font_resize_table()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 *
find_encoding(MFont * font)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
OTF_tag(char * name)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
OTF_tag_name(OTF_Tag tag,char * name)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
xlfd_parse_name(const char * name,MFont * font)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 *
xlfd_unparse_name(MFont * font,int full_xlfd)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
font_score(MFont * font,MFont * request)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
merge_capability(MSymbol capability,MSymbol key,MSymbol val,int overwrite)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 
1049 /* Internal API */
1050 
1051 MSymbol Miso8859_1, Miso10646_1, Municode_bmp, Municode_full, Mapple_roman;
1052 
1053 int
mfont__init()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 = NULL;
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
mfont__fini()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
mfont__id(MFont * font)1220 mfont__id (MFont *font)
1221 {
1222   char *buf = NULL, *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
mfont__match_p(MFont * font,MFont * spec,int prop)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
mfont__merge(MFont * dst,MFont * src,int error_on_conflict)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
mfont__set_spec_from_face(MFont * spec,MFace * face)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
mfont__set_spec_from_plist(MFont * spec,MPlist * plist)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   if (i == 0)
1369     MERROR (MERROR_FONT, Mnil);
1370   registry = spec_list[i - 1];
1371   if (i > 1 && registry != Mnil)
1372     {
1373       reg = MSYMBOL_NAME (registry);
1374       if (reg[0] == ':')
1375 	{
1376 	  mfont__get_capability (registry);
1377 	  spec->capability = registry;
1378 	  registry = spec_list[i - 2];
1379 	  i--;
1380 	}
1381     }
1382   mfont__set_property (spec, MFONT_REGISTRY, registry);
1383   for (i -= 2; i >= 0; i--)
1384     mfont__set_property (spec, i, spec_list[i]);
1385   spec->type = MFONT_TYPE_SPEC;
1386 
1387   return registry;
1388 }
1389 
1390 
1391 MFont *
mfont__select(MFrame * frame,MFont * font,int max_size)1392 mfont__select (MFrame *frame, MFont *font, int max_size)
1393 {
1394   MFontDriver *driver;
1395 
1396   if (font->type == MFONT_TYPE_FAILURE)
1397     return NULL;
1398   if (font->type != MFONT_TYPE_SPEC)
1399     return font;
1400   if (font->source == MFONT_SOURCE_UNDECIDED)
1401     {
1402       if (font->file != Mnil || font->capability != Mnil)
1403 	font->source = MFONT_SOURCE_FT;
1404       else if (font->property[MFONT_REGISTRY])
1405 	{
1406 	  MSymbol registry = FONT_PROPERTY (font, MFONT_REGISTRY);
1407 	  char *reg = MSYMBOL_NAME (registry);
1408 
1409 	  if (strncmp (reg, "unicode-", 8) == 0
1410 	      || strncmp (reg, "apple-roman", 11) == 0
1411 	      || (reg[0] >= '0' && reg[0] <= '9' && reg[1] == '-'))
1412 	    font->source = MFONT_SOURCE_FT;
1413 	}
1414     }
1415   if (font->source != MFONT_SOURCE_FT)
1416     {
1417       driver = mplist_get (frame->font_driver_list, Mx);
1418       if (driver)
1419 	return (driver->select) (frame, font, max_size);
1420     }
1421   driver = mplist_get (frame->font_driver_list, Mfreetype);
1422   if (! driver)
1423     return NULL;
1424   return (driver->select) (frame, font, max_size);
1425 }
1426 
1427 
1428 int
mfont__available(MFrame * frame,MFont * font)1429 mfont__available (MFrame *frame, MFont *font)
1430 {
1431   return -1;
1432 }
1433 
1434 static int
compare_font_score(const void * e1,const void * e2)1435 compare_font_score (const void *e1, const void *e2)
1436 {
1437   MFontScore *s1 = (MFontScore *) e1, *s2 = (MFontScore *) e2;
1438 
1439   return (s1->font->for_full_width == s2->font->for_full_width
1440 	  ? s1->score > s2->score
1441 	  : s1->font->for_full_width);
1442 }
1443 
1444 void
mdebug_dump_font_list(MFontList * font_list)1445 mdebug_dump_font_list (MFontList *font_list)
1446 {
1447   int i;
1448 
1449   for (i = 0; i < font_list->nfonts; i++)
1450     {
1451       fprintf (mdebug__output, "%04X - ", font_list->fonts[i].score);
1452       mdebug_dump_font (font_list->fonts[i].font);
1453       fprintf (mdebug__output, "\n");
1454     }
1455 }
1456 
1457 void
mfont__free_realized(MRealizedFont * rfont)1458 mfont__free_realized (MRealizedFont *rfont)
1459 {
1460   MRealizedFont *next;
1461 
1462   for (; rfont; rfont = next)
1463     {
1464       next = rfont->next;
1465       M17N_OBJECT_UNREF (rfont->info);
1466       free (rfont);
1467       rfont = next;
1468     }
1469 }
1470 
1471 MFontList *
mfont__list(MFrame * frame,MFont * spec,MFont * request,int max_size)1472 mfont__list (MFrame *frame, MFont *spec, MFont *request, int max_size)
1473 {
1474   MFontList *list;
1475   MSymbol id = mfont__id (spec);
1476   MPlist *pl, *p;
1477   int num, i;
1478 
1479   pl = msymbol_get (id, M_font_list);
1480   if (pl)
1481     num = (int) msymbol_get (id, M_font_list_len);
1482   else
1483     {
1484       pl = mplist ();
1485       num = 0;
1486       MPLIST_DO (p, frame->font_driver_list)
1487 	{
1488 	  if (spec->source == MFONT_SOURCE_X ? MPLIST_KEY (p) == Mx
1489 	      : spec->source == MFONT_SOURCE_FT ? MPLIST_KEY (p) == Mfreetype
1490 	      : 1)
1491 	    {
1492 	      MFontDriver *driver = MPLIST_VAL (p);
1493 	      num += (driver->list) (frame, pl, spec, 0);
1494 	    }
1495 	}
1496       msymbol_put (id, M_font_list, pl);
1497       M17N_OBJECT_UNREF (pl);
1498       msymbol_put (id, M_font_list_len, (void *) num);
1499     }
1500 
1501   if (num == 0)
1502     return NULL;
1503 
1504   MSTRUCT_MALLOC (list, MERROR_FONT);
1505   MTABLE_MALLOC (list->fonts, num, MERROR_FONT);
1506   for (i = 0; num > 0; num--, pl = MPLIST_NEXT (pl))
1507     {
1508       MFont *font = MPLIST_VAL (pl), *adjusted = font;
1509 
1510       if (max_size == 0
1511 	  || font->size == 0
1512 	  || font->size < max_size)
1513 	{
1514 	  list->fonts[i].font = font;
1515 	  if (spec == request)
1516 	    list->fonts[i].score = 0;
1517 	  else
1518 	    {
1519 	      int resize_ratio;
1520 	      MFont resized;
1521 
1522 	      if (font->size > 0
1523 		  && (resize_ratio = mfont_resize_ratio (font)) != 100)
1524 		{
1525 		  resized = *font;
1526 		  resized.size = font->size * 100 / resize_ratio;
1527 		  adjusted = &resized;
1528 		}
1529 	      list->fonts[i].score = font_score (adjusted, request);
1530 	    }
1531 	  i++;
1532 	}
1533     }
1534   if (i == 0)
1535     {
1536       free (list->fonts);
1537       free (list);
1538       return NULL;
1539     }
1540   list->nfonts = i;
1541   if (spec != request)
1542     qsort (list->fonts, i, sizeof (MFontScore), compare_font_score);
1543   list->object = *spec;
1544   mfont__merge (&list->object, request, 0);
1545   list->object.type = MFONT_TYPE_OBJECT;
1546   return list;
1547 }
1548 
1549 /** Open a font specified in FONT.  */
1550 
1551 MRealizedFont *
mfont__open(MFrame * frame,MFont * font,MFont * spec)1552 mfont__open (MFrame *frame, MFont *font, MFont *spec)
1553 {
1554   MFontDriver *driver;
1555   MRealizedFont *rfont;
1556 
1557   if (font->source == MFONT_SOURCE_UNDECIDED)
1558     MFATAL (MERROR_FONT);
1559   if (font->type != MFONT_TYPE_OBJECT)
1560     MFATAL (MERROR_FONT);
1561   for (rfont = MPLIST_VAL (frame->realized_font_list); rfont;
1562        rfont = rfont->next)
1563     {
1564       driver = rfont->driver;
1565       if (rfont->font == font
1566 	  && mplist_find_by_value (frame->font_driver_list, driver))
1567 	break;
1568     }
1569 
1570   if (! rfont)
1571     {
1572       driver = mplist_get (frame->font_driver_list,
1573 			   font->source == MFONT_SOURCE_X ? Mx : Mfreetype);
1574       if (! driver)
1575 	MFATAL (MERROR_FONT);
1576     }
1577   return (driver->open) (frame, font, spec, rfont);
1578 }
1579 
1580 int
mfont__has_char(MFrame * frame,MFont * font,MFont * spec,int c)1581 mfont__has_char (MFrame *frame, MFont *font, MFont *spec, int c)
1582 {
1583   MFontEncoding *encoding;
1584   unsigned code;
1585   MFontDriver *driver;
1586 
1587   if (font->source == MFONT_SOURCE_UNDECIDED)
1588     MFATAL (MERROR_FONT);
1589   encoding = (font->encoding ? font->encoding : find_encoding (font));
1590   if (! encoding->encoding_charset)
1591     return 0;
1592   if (encoding->repertory_charset)
1593     {
1594       code = ENCODE_CHAR (encoding->repertory_charset, c);
1595       return (code != MCHAR_INVALID_CODE);
1596     }
1597   code = ENCODE_CHAR (encoding->encoding_charset, c);
1598   if (code == MCHAR_INVALID_CODE)
1599     return 0;
1600   if (font->type == MFONT_TYPE_REALIZED)
1601     driver = ((MRealizedFont *) font)->driver;
1602   else
1603     {
1604       driver = mplist_get (frame->font_driver_list,
1605 			   font->source == MFONT_SOURCE_X ? Mx : Mfreetype);
1606       if (! driver)
1607 	MFATAL (MERROR_FONT);
1608     }
1609   return (driver->has_char) (frame, font, spec, c, code);
1610 }
1611 
1612 unsigned
mfont__encode_char(MFrame * frame,MFont * font,MFont * spec,int c)1613 mfont__encode_char (MFrame *frame, MFont *font, MFont *spec, int c)
1614 {
1615   MFontEncoding *encoding;
1616   unsigned code;
1617   MFontDriver *driver;
1618 
1619   if (font->source == MFONT_SOURCE_UNDECIDED)
1620     MFATAL (MERROR_FONT);
1621   encoding = (font->encoding ? font->encoding : find_encoding (font));
1622   if (! encoding->encoding_charset)
1623     return MCHAR_INVALID_CODE;
1624   if (font->source == MFONT_SOURCE_X && encoding->repertory_charset)
1625     return (ENCODE_CHAR (encoding->repertory_charset, c));
1626   code = ENCODE_CHAR (encoding->encoding_charset, c);
1627   if (code == MCHAR_INVALID_CODE)
1628     return MCHAR_INVALID_CODE;
1629   if (font->type == MFONT_TYPE_REALIZED)
1630     driver = ((MRealizedFont *) font)->driver;
1631   else
1632     {
1633       driver = mplist_get (frame->font_driver_list,
1634 			   font->source == MFONT_SOURCE_X ? Mx : Mfreetype);
1635       if (! driver)
1636 	MFATAL (MERROR_FONT);
1637     }
1638   return (driver->encode_char) (frame, font, spec, code);
1639 }
1640 
1641 void
mfont__get_metric(MGlyphString * gstring,int from,int to)1642 mfont__get_metric (MGlyphString *gstring, int from, int to)
1643 {
1644   MGlyph *from_g = MGLYPH (from), *to_g = MGLYPH (to), *g;
1645   MRealizedFont *rfont = from_g->rface->rfont;
1646 
1647   for (g = from_g; ; g++)
1648     if (g == to_g || g->rface->rfont != rfont)
1649       {
1650 	int idx = GLYPH_INDEX (g);
1651 
1652 	(rfont->driver->find_metric) (rfont, gstring, from, idx);
1653 	while (from_g < g)
1654 	  {
1655 	    from_g->g.xadv >>= 6;
1656 	    from_g->g.yadv >>= 6;
1657 	    from_g->g.xoff >>= 6;
1658 	    from_g->g.yoff >>= 6;
1659 	    from_g->g.ascent >>= 6;
1660 	    from_g->g.descent >>= 6;
1661 	    from_g->g.lbearing >>= 6;
1662 	    from_g->g.rbearing >>= 6;
1663 	    from_g++;
1664 	  }
1665 	if (g == to_g)
1666 	  break;
1667 	rfont = g->rface->rfont;
1668 	from = idx;
1669       }
1670 }
1671 
1672 int
mfont__get_glyph_id(MFLTFont * font,MFLTGlyphString * gstring,int from,int to)1673 mfont__get_glyph_id (MFLTFont *font, MFLTGlyphString *gstring,
1674 		     int from, int to)
1675 {
1676   MFont *mfont = (MFont *) ((MFLTFontForRealized *) font)->rfont;
1677   MRealizedFont *rfont = ((MFLTFontForRealized *) font)->rfont;
1678   MFontEncoding *encoding;
1679   MFontDriver *driver = NULL;
1680   MGlyph *glyphs = (MGlyph *) gstring->glyphs;
1681   int result = 0;
1682 
1683   encoding = mfont->encoding ? mfont->encoding : find_encoding (mfont);
1684   for (; from < to; from++)
1685     {
1686       MGlyph *g = glyphs + from;
1687 
1688       if (g->g.encoded)
1689 	continue;
1690       if (mfont->source == MFONT_SOURCE_X && encoding->repertory_charset)
1691 	g->g.code = ENCODE_CHAR (encoding->repertory_charset, g->g.c);
1692       else
1693 	{
1694 	  unsigned code;
1695 
1696 	  if (encoding->encoding_charset)
1697 	    code = ENCODE_CHAR (encoding->encoding_charset, g->g.c);
1698 	  else
1699 	    code = g->g.code;
1700 
1701 	  if (code != MCHAR_INVALID_CODE)
1702 	    {
1703 	      if (! driver)
1704 		{
1705 		  if (mfont->type == MFONT_TYPE_REALIZED)
1706 		    driver = rfont->driver;
1707 		  else
1708 		    {
1709 		      driver = mplist_get (rfont->frame->font_driver_list,
1710 					   mfont->source == MFONT_SOURCE_X
1711 					   ? Mx : Mfreetype);
1712 		      if (! driver)
1713 			MFATAL (MERROR_FONT);
1714 		    }
1715 		}
1716 	      g->g.code = (driver->encode_char) (rfont->frame, rfont->font,
1717 						 mfont, code);
1718 	    }
1719 	}
1720       g->g.encoded = 1;
1721       if (g->g.code == MCHAR_INVALID_CODE)
1722 	result = -1;
1723     }
1724   return result;
1725 }
1726 
1727 int
mfont__get_metrics(MFLTFont * font,MFLTGlyphString * gstring,int from,int to)1728 mfont__get_metrics (MFLTFont *font, MFLTGlyphString *gstring,
1729 		    int from, int to)
1730 {
1731   MRealizedFont *rfont = ((MFLTFontForRealized *) font)->rfont;
1732   MGlyphString gstr;
1733 
1734   gstr.glyphs = (MGlyph *) gstring->glyphs;
1735   (rfont->driver->find_metric) (rfont, &gstr, from, to);
1736   return 0;
1737 }
1738 
1739 /* KEY <= MFONT_REGISTRY */
1740 
1741 void
mfont__set_property(MFont * font,enum MFontProperty key,MSymbol val)1742 mfont__set_property (MFont *font, enum MFontProperty key, MSymbol val)
1743 {
1744   int numeric;
1745 
1746   if (val == Mnil)
1747     numeric = 0;
1748   else
1749     {
1750       numeric = FONT_PROPERTY_NUMERIC (val, key);
1751       if (! numeric)
1752 	{
1753 	  numeric = mfont__property_table[key].used;
1754 	  MLIST_APPEND1 (mfont__property_table + key, names, val, MERROR_FONT);
1755 	  SET_FONT_PROPERTY_NUMERIC (val, key, numeric);
1756 	}
1757     }
1758   font->property[key] = numeric;
1759 }
1760 
1761 int
mfont__parse_name_into_font(const char * name,MSymbol format,MFont * font)1762 mfont__parse_name_into_font (const char *name, MSymbol format, MFont *font)
1763 {
1764   int result = -1;
1765 
1766   if (format == Mx || format == Mnil)
1767     result = xlfd_parse_name (name, font);
1768 #ifdef HAVE_FONTCONFIG
1769   if (format == Mfontconfig || (result < 0 && format == Mnil))
1770     result = mfont__ft_parse_name (name, font);
1771 #endif /* HAVE_FONTCONFIG */
1772   return result;
1773 }
1774 
1775 MPlist *
mfont__encoding_list(void)1776 mfont__encoding_list (void)
1777 {
1778   if (! font_encoding_list)
1779     load_font_encoding_table ();
1780   return font_encoding_list;
1781 }
1782 
1783 static void
free_font_capability(void * object)1784 free_font_capability (void *object)
1785 {
1786   MFontCapability *cap = object;
1787 
1788   if (cap->script_tag)
1789     {
1790       int i;
1791       for (i = 0; i < MFONT_OTT_MAX; i++)
1792 	{
1793 	  if (cap->features[i].str)
1794 	    free (cap->features[i].str);
1795 	  if (cap->features[i].tags)
1796 	    free (cap->features[i].tags);
1797 	}
1798     }
1799   free (cap);
1800 }
1801 
1802 MFontCapability *
mfont__get_capability(MSymbol sym)1803 mfont__get_capability (MSymbol sym)
1804 {
1805   MFontCapability *cap = msymbol_get (sym, M_font_capability);
1806   char *str, *p, *endp;
1807 
1808   if (cap)
1809     return cap;
1810   str = MSYMBOL_NAME (sym);
1811   if (str[0] != ':')
1812     return NULL;
1813   M17N_OBJECT (cap, free_font_capability, MERROR_FONT);
1814   msymbol_put (sym, M_font_capability, cap);
1815   M17N_OBJECT_UNREF (cap);
1816   endp = str + MSYMBOL_NAMELEN (sym);
1817   while (str < endp)
1818     {
1819       if (*str++ != ':')
1820 	continue;
1821       if (str[0] == 'o' && strncmp (str + 1, "tf=", 3) == 0)
1822 	{
1823 	  char *beg;
1824 	  MSymbol sym;
1825 	  int i;
1826 
1827 	  str += 4;
1828 	  beg = str;
1829 	  for (i = 0, p = str; i < 4 && p < endp; i++, p++);
1830 	  if (i < 4)
1831 	    break;
1832 	  sym = msymbol__with_len (str, 4);
1833 	  cap->script = mscript__from_otf_tag (sym);
1834 	  if (cap->script == Mnil)
1835 	    break;
1836 	  cap->script_tag = OTF_tag (str);
1837 	  if (*p == '/')
1838 	    {
1839 	      for (i = 0, str = ++p; i < 4 && p < endp; i++, p++);
1840 	      if (i < 4)
1841 		{
1842 		  cap->script = Mnil;
1843 		  cap->script_tag = 0;
1844 		  break;
1845 		}
1846 	      cap->langsys_tag = OTF_tag (str);
1847 	    }
1848 	  else
1849 	    cap->langsys_tag = 0;
1850 
1851 	  for (i = 0; i < MFONT_OTT_MAX; i++)
1852 	    cap->features[i].nfeatures = -1;
1853 
1854 	  while (*p == '=' || *p == '+')
1855 	    {
1856 	      int idx = *p == '=' ? MFONT_OTT_GSUB : MFONT_OTT_GPOS;
1857 
1858 	      str = ++p;
1859 	      while (p < endp && *p != '+') p++;
1860 	      if (str < p)
1861 		{
1862 		  int n;
1863 		  /* We never have more than (p - str) tags.  */
1864 		  OTF_Tag *tags = alloca (sizeof (OTF_Tag) * (p - str));
1865 		  char *p0;
1866 
1867 		  cap->features[idx].str = malloc (p - str + 1);
1868 		  for (i = n = 0, p0 = str; str + i < p; i++)
1869 		    {
1870 		      cap->features[idx].str[i] = str[i];
1871 		      if (str[i] == ',' || str + i + 1 == p)
1872 			{
1873 			  if (*p0 == '*')
1874 			    tags[n] = 0;
1875 			  else if (*p0 == '~')
1876 			    tags[n] = OTF_tag (p0 + 1) | 0x80000000;
1877 			  else
1878 			    tags[n] = OTF_tag (p0);
1879 			  n++;
1880 			  p0 = str + i + 1;
1881 			}
1882 		    }
1883 		  cap->features[idx].str[i] = '\0';
1884 		  cap->features[idx].nfeatures = n;
1885 		  if (n > 0)
1886 		    {
1887 		      int size = sizeof (OTF_Tag) * n;
1888 
1889 		      cap->features[idx].tags = malloc (size);
1890 		      memcpy (cap->features[idx].tags, tags, size);
1891 		    }
1892 		}
1893 	      else
1894 		{
1895 		  cap->features[idx].str = NULL;
1896 		  cap->features[idx].nfeatures = 0;
1897 		}
1898 	    }
1899 
1900 	  for (i = 0; i < MFONT_OTT_MAX; i++)
1901 	    if (cap->features[i].nfeatures < 0)
1902 	      {
1903 		cap->features[i].str = strdup ("*");
1904 		cap->features[i].nfeatures = 1;
1905 		cap->features[i].tags = malloc (sizeof (OTF_Tag));
1906 		cap->features[i].tags[0] = 0;
1907 	      }
1908 	  cap->otf = msymbol__with_len (beg, p - beg);
1909 	  str = p;
1910 	}
1911       else if (str[0] == 'l' && strncmp (str + 1, "ang=", 4) == 0)
1912 	{
1913 	  str += 5;
1914 	  for (p = str; p < endp && *p != ':'; p++);
1915 	  if (str < p)
1916 	    cap->language = msymbol__with_len (str, p - str);
1917 	  str = p;
1918 	}
1919       else if (str[0] == 's' && strncmp (str + 1, "cript=", 6) == 0)
1920 	{
1921 	  str += 7;
1922 	  for (p = str; p < endp && *p != ':'; p++);
1923 	  if (str < p)
1924 	    cap->script = msymbol__with_len (str, p - str);
1925 	  str = p;
1926 	}
1927     }
1928   return cap;
1929 }
1930 
1931 int
mfont__check_capability(MRealizedFont * rfont,MSymbol capability)1932 mfont__check_capability (MRealizedFont *rfont, MSymbol capability)
1933 {
1934   return (rfont->driver->check_capability (rfont, capability));
1935 }
1936 
1937 
1938 /*** @} */
1939 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
1940 
1941 
1942 
1943 /* External API */
1944 
1945 /*** @addtogroup m17nFont */
1946 /*** @{ */
1947 /*=*/
1948 
1949 /***en @name Variables: Keys of font property.  */
1950 /***ja @name �ѿ�: �ե���ȥץ�ѥƥ�����ꤹ������Ѥߥ���ܥ� */
1951 /*** @{ */
1952 /*=*/
1953 
1954 /***en
1955     @brief Key of font property specifying foundry.
1956 
1957     The variable #Mfoundry is a symbol of name <tt>"foundry"</tt> and
1958     is used as a key of font property and face property.  The property
1959     value must be a symbol whose name is a foundry name of a font.  */
1960 /***ja
1961     @brief ��ȯ������ꤹ��ե���ȥץ�ѥƥ��Υ���.
1962 
1963     �ѿ� #Mfoundry �� <tt>"foundry"</tt>
1964     �Ȥ���̾������ĥ���ܥ�Ǥ��ꡢ�ե���ȥץ�ѥƥ��ȥե������ץ�ѥƥ��Υ����Ȥ����Ѥ����롣
1965     �ͤϡ��ե���Ȥγ�ȯ��̾��̾���Ȥ��ƻ��ĥ���ܥ�Ǥ��롣    */
1966 
1967 MSymbol Mfoundry;
1968 
1969 /***en
1970     @brief Key of font property specifying family.
1971 
1972     The variable #Mfamily is a symbol of name <tt>"family"</tt> and is
1973     used as a key of font property and face property.  The property
1974     value must be a symbol whose name is a family name of a font.  */
1975 /***ja
1976     @brief �ե��ߥ����ꤹ��ե���ȥץ�ѥƥ��Υ���.
1977 
1978     �ѿ� #Mfamily �� <tt>"family"</tt>
1979     �Ȥ���̾������ĥ���ܥ�Ǥ��ꡢ�ե���ȥץ�ѥƥ��ȥե������ץ�ѥƥ��Υ����Ȥ����Ѥ����롣
1980     �ͤϡ��ե���ȤΥե��ߥ�̾��̾���Ȥ��ƻ��ĥ���ܥ�Ǥ��롣    */
1981 
1982 MSymbol Mfamily;
1983 
1984 /***en
1985     @brief Key of font property specifying weight.
1986 
1987     The variable #Mweight is a symbol of name <tt>"weight"</tt> and is
1988     used as a key of font property and face property.  The property
1989     value must be a symbol whose name is a weight name of a font (e.g
1990     "medium", "bold").  */
1991 /***ja
1992     @brief ��������ꤹ��ե���ȥץ�ѥƥ��Υ���.
1993 
1994     �ѿ� #Mweight �� <tt>"weight"</tt>
1995     �Ȥ���̾������ĥ���ܥ�Ǥ��ꡢ�ե���ȥץ�ѥƥ��ȥե������ץ�ѥƥ��Υ����Ȥ����Ѥ����롣
1996     �ͤϡ��ե���Ȥ�����̾ ( "medium", "bold" ��) ��̾���Ȥ��ƻ��ĥ���ܥ�Ǥ��롣    */
1997 
1998 MSymbol Mweight;
1999 
2000 /***en
2001     @brief Key of font property specifying style.
2002 
2003     The variable #Mstyle is a symbol of name <tt>"style"</tt> and is
2004     used as a key of font property and face property.  The property
2005     value must be a symbol whose name is a style name of a font (e.g
2006     "r", "i", "o").  */
2007 /***ja
2008     @brief �����������ꤹ��ե���ȥץ�ѥƥ��Υ���.
2009 
2010     �ѿ� #Mstyle �� <tt>"style"</tt>
2011     �Ȥ���̾������ĥ���ܥ�Ǥ��ꡢ�ե���ȥץ�ѥƥ��ȥե������ץ�ѥƥ��Υ����Ȥ����Ѥ����롣
2012     �ͤϡ��ե���ȤΥ�������̾ ("r", "i", "o" ��)��̾���Ȥ��ƻ��ĥ���ܥ�Ǥ��롣    */
2013 
2014 MSymbol Mstyle;
2015 
2016 /***en
2017     @brief Key of font property specifying stretch.
2018 
2019     The variable #Mstretch is a symbol of name <tt>"stretch"</tt> and
2020     is used as a key of font property and face property.  The property
2021     value must be a symbol whose name is a stretch name of a font (e.g
2022     "normal", "condensed").  */
2023 /***ja
2024     @brief ������ꤹ��ե���ȥץ�ѥƥ��Υ���.
2025 
2026     �ѿ� #Mstretch �� <tt>"stretch"</tt>
2027     �Ȥ���̾������ĥ���ܥ�Ǥ��ꡢ�ե���ȥץ�ѥƥ��ȥե������ץ�ѥƥ��Υ����Ȥ����Ѥ����롣
2028     �ͤϡ��ե���Ȥ�ʸ����̾ ( "normal", "condensed" ��)��̾���Ȥ��ƻ��ĥ���ܥ�Ǥ��롣    */
2029 
2030 MSymbol Mstretch;
2031 
2032 /***en
2033     @brief Key of font property specifying additional style.
2034 
2035     The variable #Madstyle is a symbol of name <tt>"adstyle"</tt> and
2036     is used as a key of font property and face property.  The property
2037     value must be a symbol whose name is an additional style name of a
2038     font (e.g "serif", "", "sans").  */
2039 /***ja
2040     @brief adstyle ����ꤹ��ե���ȥץ�ѥƥ��Υ���.
2041 
2042     �ѿ� #Madstyle �� <tt>"adstyle"</tt>
2043     �Ȥ���̾������ĥ���ܥ�Ǥ��ꡢ�ե���ȥץ�ѥƥ��ȥե������ץ�ѥƥ��Υ����Ȥ����Ѥ����롣
2044     �ͤϡ��ե���Ȥ� adstyle ̾("serif", "", "sans" ��)��̾���Ȥ��ƻ��ĥ���ܥ�Ǥ��롣    */
2045 
2046 MSymbol Madstyle;
2047 
2048 /***en
2049     @brief Key of font property specifying spacing.
2050 
2051     The variable #Madstyle is a symbol of name <tt>"spacing"</tt> and
2052     is used as a key of font property.  The property value must be a
2053     symbol whose name specifies the spacing of a font (e.g "p" for
2054     proportional, "m" for monospaced).  */
2055 /***ja
2056     @brief spacing ����ꤹ��ե���ȥץ�ѥƥ��Υ���.
2057 
2058     �ѿ� #Mspacing �� <tt>"spacing"</tt> �Ȥ���̾������ĥ���ܥ�Ǥ��ꡢ
2059     �ե���ȥץ�ѥƥ��Υ����Ȥ����Ѥ����롣�ͤϡ��ե���Ȥ� spacing
2060     ��������̾�� ("p", "m" ��)����ĥ���ܥ�Ǥ��롣  */
2061 
2062 MSymbol Mspacing;
2063 
2064 /***en
2065     @brief Key of font property specifying registry.
2066 
2067     The variable #Mregistry is a symbol of name <tt>"registry"</tt>
2068     and is used as a key of font property.  The property value must be
2069     a symbol whose name is a registry name a font registry
2070     (e.g. "iso8859-1", "jisx0208.1983-0").  */
2071 /***ja
2072     @brief �쥸���ȥ����ꤹ��ե���ȥץ�ѥƥ��Υ���.
2073 
2074     �ѿ� #Mregistry �� <tt>"registry"</tt>
2075     �Ȥ���̾������ĥ���ܥ�Ǥ��ꡢ�ե���ȥץ�ѥƥ��ȥե������ץ�ѥƥ��Υ����Ȥ����Ѥ����롣
2076     �ͤϡ��ե���ȤΥ쥸���ȥ�̾ ( "iso8859-1", "jisx0208.1983-0"
2077     ��) ��̾���Ȥ��ƻ��ĥ���ܥ�Ǥ��롣    */
2078 
2079 MSymbol Mregistry;
2080 
2081 /***en
2082     @brief Key of font property specifying size.
2083 
2084     The variable #Msize is a symbol of name <tt>"size"</tt> and is
2085     used as a key of font property and face property.  The property
2086     value must be an integer specifying a font design size in the unit
2087     of 1/10 point (on 100 dpi display).  */
2088 /***ja
2089     @brief ����������ꤹ��ե���ȥץ�ѥƥ��Υ���.
2090 
2091     �ѿ� #Msize �� <tt>"size"</tt>
2092     �Ȥ���̾������ĥ���ܥ�Ǥ��ꡢ�ե���ȥץ�ѥƥ��ȥե������ץ�ѥƥ��Υ����Ȥ����Ѥ����롣�ͤϡ�
2093     100 dpi �Υǥ����ץ쥤��ǤΥե���ȤΥǥ����������� 1/10
2094     �ݥ����ñ�̤Ǽ��������ͤǤ��롣
2095     */
2096 
2097 MSymbol Msize;
2098 
2099 /***en
2100     @brief Key of font property specifying file name.
2101 
2102     The variable #Mfontfile is a symbol of name <tt>"fontfile"</tt>
2103     and is used as a key of font property.  The property value must be
2104     a symbol whose name is a font file name.  */
2105 MSymbol Motf;
2106 
2107 /***en
2108     @brief Key of font property specifying file name.
2109 
2110     The variable #Mfontfile is a symbol of name <tt>"fontfile"</tt>
2111     and is used as a key of font property.  The property value must be
2112     a symbol whose name is a font file name.  */
2113 /***ja
2114     @brief �ե���ȥե��������ꤹ��ե���ȥץ�ѥƥ��Υ���.
2115 
2116     �ѿ� #Mfontfile �� <tt>"fontfile"</tt> �Ȥ���̾������ĥ���ܥ�Ǥ�
2117     �ꡢ�ե���ȥץ�ѥƥ��Υ����Ȥ����Ѥ����롣�ͤϡ��ե���ȥե���
2118     ��̾��̾���Ȥ��ƻ��ĤȤ��륷��ܥ�Ǥ��롣 */
2119 
2120 MSymbol Mfontfile;
2121 
2122 /***en
2123     @brief Key of font property specifying resolution.
2124 
2125     The variable #Mresolution is a symbol of name <tt>"resolution"</tt> and
2126     is used as a key of font property and face property.  The property
2127     value must be an integer to specifying a font resolution in the
2128     unit of dots per inch (dpi).  */
2129 /***ja
2130     @brief �����٤���ꤹ��ե���ȥץ�ѥƥ��Υ���.
2131 
2132     �ѿ� #Mresolution �� <tt>"resolution"</tt>
2133     �Ȥ���̾������ĥ���ܥ�Ǥ��ꡢ�ե���ȥץ�ѥƥ��ȥե������ץ�ѥƥ��Υ����Ȥ����Ѥ����롣
2134     �ͤϡ��ե���Ȥβ����٤� dots per inch (dpi) ñ�̤Ǽ��������ͤǤ��롣    */
2135 
2136 MSymbol Mresolution;
2137 
2138 /***en
2139     @brief Key of font property specifying max advance width.
2140 
2141     The variable #Mmax_advance is a symbol of name
2142     <tt>"max-advance"</tt> and is used as a key of font property.  The
2143     property value must be an integer specifying a font's max advance
2144     value by pixels.  */
2145 
2146 MSymbol Mmax_advance;
2147 
2148 
2149 /***en
2150     @brief Symbol of name "fontconfig".
2151 
2152     The variable #Mfontconfig is to be used as an argument of the
2153     functions mfont_parse_name () and mfont_unparse_name ().  */
2154 /***ja
2155     @brief "fontconfig" �Ȥ���̾������ĥ���ܥ�.
2156 
2157     �ѿ� #Mfontconfig �ϴؿ� mfont_parse_name () �� mfont_unparse_name ()
2158     �ΰ����Ȥ����Ѥ����롣  */
2159 
2160 MSymbol Mfontconfig;
2161 
2162 /***en
2163     @brief Symbol of name "x".
2164 
2165     The variable #Mx is to be used for a value of \<type\> member of the
2166     structure #MDrawGlyph to specify the type of \<fontp\> member is
2167     actually (XFontStruct *).  */
2168 /***ja
2169     @brief "x" �Ȥ���̾������ĥ���ܥ�.
2170 
2171     �ѿ� #Mx �Ϲ�¤ #MDrawGlyph �Υ��� \<type\>
2172     ���ͤȤ����Ѥ���졢���� \<fontp\> �η����ºݤˤ� (XFontStruct *) �Ǥ��뤳�Ȥ�ɽ��.  */
2173 
2174 MSymbol Mx;
2175 
2176 /***en
2177     @brief Symbol of name "freetype".
2178 
2179     The variable #Mfreetype is to be used for a value of \<type\> member
2180     of the structure #MDrawGlyph to specify the type of \<fontp\> member
2181     is actually FT_Face.  */
2182 /***ja
2183     @brief "freetype" �Ȥ���̾������ĥ���ܥ�.
2184 
2185     �ѿ� #Mfreetype �Ϲ�¤ #MDrawGlyph �Υ��� \<type\>
2186     ���ͤȤ����Ѥ���졢���� \<fontp\> �η����ºݤˤ� FT_Face �Ǥ��뤳�Ȥ�ɽ����  */
2187 
2188 MSymbol Mfreetype;
2189 
2190 /***en
2191     @brief Symbol of name "xft".
2192 
2193     The variable #Mxft is to be used for a value of \<type\> member of the
2194     structure #MDrawGlyph to specify the type of \<fontp\> member
2195     is actually (XftFont *).  */
2196 /***ja
2197     @brief  "xft" �Ȥ���̾������ĥ���ܥ�.
2198 
2199     �ѿ� #Mxft �Ϲ�¤ #MDrawGlyph �Υ��� \<type\>
2200     ���ͤȤ����Ѥ���졢���� \<fontp\> �η����ºݤˤ� (XftFont *) �Ǥ��뤳�Ȥ�ɽ����  */
2201 
2202 MSymbol Mxft;
2203 
2204 /*=*/
2205 /*** @} */
2206 /*=*/
2207 
2208 /***en
2209     @brief List of font files and directories that contain font files.
2210 
2211     The variable @c mfont_freetype_path is a plist of FreeType font
2212     files and directories that contain FreeType font files.  Key of
2213     the element is @c Mstring, and the value is a string that
2214     represents a font file or a directory.
2215 
2216     The macro M17N_INIT () sets up this variable to contain the
2217     sub-directory "fonts" of the m17n database and the environment
2218     variable "M17NDIR".  The first call of mframe () creates the
2219     internal list of the actually available fonts from this variable.
2220     Thus, an application program, if necessary, must modify the
2221     variable before calling mframe ().  If it is going to add a new
2222     element, value must be a string that can be safely freed.
2223 
2224     If the m17n library is not configured to use the FreeType library,
2225     this variable is not used.  */
2226 /***ja
2227     @brief �ե���ȥե�����ȥե���ȥե������ޤ�ǥ��쥯�ȥ�Υꥹ��.
2228 
2229     �ѿ� @c mfont_freetype_path �ϡ��ե���ȥե�����ȥե���ȥե������ޤ�ǥ��쥯�ȥ��
2230     plist �Ǥ��롣�����ǤΥ����� @c Mstring
2231     �Ǥ��ꡢ�ͤϥե���ȥե����뤫�ǥ��쥯�ȥ����ʸ����Ǥ��롣
2232 
2233     �ޥ��� M17N_INIT () �ˤ�äơ������ѿ��� m17n �ǡ����١����ȴĶ��ѿ�
2234     "M17NDIR" �����Υ��֥ǥ��쥯�ȥ� "fonts" ��ޤ�褦�����ꤵ��롣
2235     mframe () �κǽ�θƤӽФ��κݤˡ������ѿ�����ºݤ˻��ѤǤ���ե���Ȥ������ꥹ�Ȥ�����롣
2236     �����ǥ��ץꥱ�������ץ����ϡ�mframe ()
2237     ��Ƥ����ˡ�ɬ�פʤ�Сˤ����ѿ����ѹ����ʤ��ƤϤʤ�ʤ���
2238     ���������Ǥ��ɲä�����ˤϡ������ͤϰ����˳����Ǥ���ʸ����Ǥʤ��ƤϤʤ�ʤ���
2239 
2240     m17n �饤�֥�꤬ FreeType �饤�֥���Ȥ��褦�����ꤵ��Ƥʤ����ˤϡ������ѿ����Ѥ����ʤ��� */
2241 
2242 MPlist *mfont_freetype_path;
2243 
2244 /*=*/
2245 
2246 /***en
2247     @brief Create a new font.
2248 
2249     The mfont () function creates a new font object that has no
2250     property.
2251 
2252     @return
2253     This function returns a pointer to the created font object.  */
2254 /***ja
2255     @brief �������ե���Ȥ���.
2256 
2257     �ؿ� mfont () �ϥץ�ѥƥ�����ڻ����ʤ��������ե���Ȥ��֥������Ȥ��롣
2258 
2259     @return
2260     ���δؿ��Ϻ�ä��ե���ȥ��֥������ȤؤΥݥ������֤���  */
2261 
2262 MFont *
mfont()2263 mfont ()
2264 {
2265   MFont *font;
2266 
2267   MSTRUCT_CALLOC (font, MERROR_FONT);
2268   return font;
2269 }
2270 
2271 /*=*/
2272 
2273 /***en
2274     @brief Create a font by parsing a fontname.
2275 
2276     The mfont_parse_name () function creates a new font object.  The
2277     properties are extracted fontname $NAME.
2278 
2279     $FORMAT specifies the format of $NAME.  If $FORMAT is #Mx, $NAME
2280     is parsed as XLFD (X Logical Font Description).  If $FORMAT is
2281     #Mfontconfig, $NAME is parsed as Fontconfig's textual
2282     representation of font.  If $FORMAT is #Mnil, $NAME is at first
2283     parsed as XLFD, and it it fails, parsed as Fontconfig's
2284     representation.
2285 
2286     @return
2287     If the operation was successful, this function returns a pointer
2288     to the created font.  Otherwise it returns @c NULL.  */
2289 
2290 /***ja
2291     @brief �ե����̾����ե���Ȥ���.
2292 
2293     �ؿ� mfont_parse_name () �ϡ��ե����̾
2294     $NAME ������Ф��줿�ץ�ѥƥ�����ġ��������ե���ȥ��֥������Ȥ��롣
2295 
2296     $FORMAT �� $NAME �Υե����ޥåȤ���ꤹ�롣$FORMAT �� #Mx �Ǥ���С�
2297     $NAME �� XLFD (X Logical Font Description) �˽��äƲ��Ϥ���롣
2298     $FORMAT �� #Mfontconfig �Ǥ���� $NAME �� Fontfonfig
2299     �Υե���ȥƥ�����ɽ���˽��äƲ��Ϥ���롣$FORMAT �� #Mnil �Ǥ���С��ޤ� XLFD
2300     �˽��äƲ��Ϥ��졢����˼��Ԥ����� Fontconfig �˽��äƲ��Ϥ���롣
2301 
2302     @return
2303     ��������������� mfont_parse_name ()
2304     �Ͽ��������줿�ե���ȤؤΥݥ������֤��������Ǥʤ���� @c NULL ���֤���  */
2305 
2306 MFont *
mfont_parse_name(const char * name,MSymbol format)2307 mfont_parse_name (const char *name, MSymbol format)
2308 {
2309   MFont template, *font;
2310 
2311   MFONT_INIT (&template);
2312   if (mfont__parse_name_into_font (name, format, &template) < 0)
2313     MERROR (MERROR_FONT, NULL);
2314   MSTRUCT_CALLOC (font, MERROR_FONT);
2315   *font = template;
2316   return font;
2317 }
2318 
2319 /*=*/
2320 
2321 /***en
2322     @brief Create a fontname from a font.
2323 
2324     The mfont_unparse_name () function creates a fontname string
2325     from font $FONT according to $FORMAT.
2326 
2327     $FORMAT must be #Mx or #Mfontconfig.  If it is #Mx, the fontname
2328     is in XLFD (X Logical Font Description) format.  If it is
2329     #Mfontconfig, the fontname is in the style of Fontconfig's text
2330     representation.
2331 
2332     @return
2333     This function returns a newly allocated fontname string, which is
2334     not freed unless the user explicitly does so by free ().  */
2335 
2336 /***ja
2337     @brief �ե���Ȥ���ե����̾����.
2338 
2339     �ؿ� mfont_unparse_name () �� �ե����̾��ʸ�����ե���� $FONT
2340     ����$FORMAT �˽��äƺ�롣
2341 
2342     $FORMAT �� #Mx �ޤ��� #Mfontconfig �Ǥ��롣
2343     #Mx �ʤ�Хե����̾�� XLFD (X Logical Font Description) �˽�����
2344     #Mfontconfig �ʤ�Хե����̾�� Fontconfig �Υե���ȥƥ�����ɽ���˽�����
2345 
2346     @return
2347     ���δؿ��Ͽ����˥������Ȥ����ե����̾��ʸ������֤���ʸ����ϡ��桼����
2348     free () �ˤ�ä�����Ū�˲������ʤ��¤��������ʤ���  */
2349 
2350 char *
mfont_unparse_name(MFont * font,MSymbol format)2351 mfont_unparse_name (MFont *font, MSymbol format)
2352 {
2353   char *name;
2354 
2355   if (format == Mx)
2356     name = xlfd_unparse_name (font, 1);
2357 #ifdef HAVE_FONTCONFIG
2358   else if (format == Mfontconfig)
2359     name = mfont__ft_unparse_name (font);
2360 
2361 #endif /* HAVE_FONTCONFIG */
2362   else
2363     MERROR (MERROR_FONT, NULL);
2364   return name;
2365 }
2366 
2367 /*=*/
2368 
2369 /***en
2370     @brief Make a copy of a font.
2371 
2372     The mfont_copy () function returns a new copy of font $FONT.  */
2373 /***ja
2374     @brief �ե���ȤΥ��ԡ�����.
2375 
2376     �ؿ� Mfont_copy () �ϥե���� $FONT �Υ��ԡ����ꡢ������֤��� */
2377 
2378 MFont *
mfont_copy(MFont * font)2379 mfont_copy (MFont *font)
2380 {
2381   MFont *copy;
2382 
2383   MSTRUCT_MALLOC (copy, MERROR_FONT);
2384   *copy = *font;
2385   return copy;
2386 }
2387 
2388 /*=*/
2389 
2390 /***en
2391     @brief Get a property value of a font.
2392 
2393     The mfont_get_prop () function gets the value of $KEY property of
2394     font $FONT.  $KEY must be one of the following symbols:
2395 
2396 	@c Mfoundry, @c Mfamily, @c Mweight, @c Mstyle, @c Mstretch,
2397 	@c Madstyle, @c Mregistry, @c Msize, @c Mresolution, @c Mspacing.
2398 
2399     If $FONT is a return value of mfont_find (), $KEY can also be one
2400     of the following symbols:
2401 
2402 	@b Mfont_ascent, @b Mfont_descent, #Mmax_advance.
2403 
2404     @return
2405     If $KEY is @c Mfoundry, @c Mfamily, @c Mweight, @c Mstyle,
2406     @c Mstretch, @c Madstyle, @c Mregistry, or @c Mspacing, this
2407     function returns the corresponding value as a symbol.  If the font
2408     does not have $KEY property, it returns @c Mnil.  If $KEY is @c
2409     Msize, @c Mresolution, @b Mfont_ascent, Mfont_descent, or
2410     #Mmax_advance, this function returns the corresponding value as an
2411     integer.  If the font does not have $KEY property, it returns 0.
2412     If $KEY is something else, it returns @c NULL and assigns an error
2413     code to the external variable #merror_code.  */
2414 
2415 /***ja
2416     @brief �ե���ȤΥץ�ѥƥ����ͤ�����.
2417 
2418     �ؿ� mfont_get_prop () �ϥե���� $FONT �Υץ�ѥƥ��Τ�����������
2419     $KEY �Ǥ����Τ��ͤ��֤���$KEY �ϰʲ��Υ���ܥ�Τ����줫�Ǥʤ���
2420     �Фʤ�ʤ���
2421 
2422 	@c Mfoundry, @c Mfamily, @c Mweight, @c Mstyle, @c Mstretch,
2423 	@c Madstyle, @c Mregistry, @c Msize, @c Mresolution, @c Mspacing.
2424 
2425     @return
2426     $KEY �� @c Mfoundry, @c Mfamily, @c Mweight, @c Mstyle, @c
2427     Mstretch, @c Madstyle, @c Mregistry, @c Mspacing �Τ����줫�Ǥ���С�
2428     ���������ͤ���ܥ�Ȥ����֤����ե���Ȥ����Υץ�ѥƥ�������ʤ�
2429     ���ˤ�@c Mnil ���֤���$KEY �� @c Msize ���뤤�� @c Mresolution ��
2430     ���ˤϡ����������ͤ�������ͤȤ����֤����ե���Ȥ����Υץ�ѥƥ�
2431     ������ʤ����ˤ� 0 ���֤���$KEY ������ʳ��Τ�ΤǤ���С�@c
2432     NULL ���֤��������ѿ� #merror_code �˥��顼�����ɤ����ꤹ�롣  */
2433 
2434 void *
mfont_get_prop(MFont * font,MSymbol key)2435 mfont_get_prop (MFont *font, MSymbol key)
2436 {
2437   MRealizedFont *rfont = NULL;
2438 
2439   if (font->type == MFONT_TYPE_REALIZED)
2440     rfont = (MRealizedFont *) font;
2441 
2442   if (key == Mfoundry)
2443     return (void *) FONT_PROPERTY (font, MFONT_FOUNDRY);
2444   if (key == Mfamily)
2445     return (void *) FONT_PROPERTY (font, MFONT_FAMILY);
2446   if (key == Mweight)
2447     return (void *) FONT_PROPERTY (font, MFONT_WEIGHT);
2448   if (key == Mstyle)
2449     return (void *) FONT_PROPERTY (font, MFONT_STYLE);
2450   if (key == Mstretch)
2451     return (void *) FONT_PROPERTY (font, MFONT_STRETCH);
2452   if (key == Madstyle)
2453     return (void *) FONT_PROPERTY (font, MFONT_ADSTYLE);
2454   if (key == Mregistry)
2455     return (void *) FONT_PROPERTY (font, MFONT_REGISTRY);
2456   if (key == Msize)
2457     {
2458       int size = font->size;
2459       return (void *) size;
2460     }
2461   if (key == Mresolution)
2462     {
2463       int resy = font->property[MFONT_RESY];
2464       return (void *) resy;
2465     }
2466   if (key == Mlanguage || key == Mscript || key == Motf)
2467     {
2468       MFontCapability *cap;
2469 
2470       if (! font->capability)
2471 	return NULL;
2472       cap = mfont__get_capability (font->capability);
2473       if (key == Mlanguage)
2474 	return cap->language;
2475       if (key == Mscript)
2476 	return cap->script;
2477       return cap->otf;
2478     }
2479 
2480   if (key == Mfontfile)
2481     return (void *) font->file;
2482   if (key == Mspacing)
2483     return (font->spacing == MFONT_SPACING_UNDECIDED ? Mnil
2484 	    : msymbol (font->spacing == MFONT_SPACING_PROPORTIONAL ? "p"
2485 		       : font->spacing == MFONT_SPACING_MONO ? "m" : "c"));
2486   if (rfont)
2487     {
2488       if (key == Mfont_ascent)
2489 	return (void *) rfont->ascent;
2490       if (key == Mfont_descent)
2491 	return (void *) rfont->descent;
2492       if (key == Mmax_advance)
2493 	return (void *) rfont->max_advance;
2494     }
2495   MERROR (MERROR_FONT, NULL);
2496 }
2497 
2498 
2499 /*=*/
2500 /***en
2501     @brief Put a property value to a font.
2502 
2503     The mfont_put_prop () function puts a font property whose key is
2504     $KEY and value is $VAL to font $FONT.  $KEY must be one of the
2505     following symbols:
2506 
2507 	@c Mfoundry, @c Mfamily, @c Mweight, @c Mstyle, @c Mstretch,
2508 	@c Madstyle, @c Mregistry, @c Msize, @c Mresolution.
2509 
2510     If $KEY is @c Msize or @c Mresolution, $VAL must be an integer.
2511     Otherwise, $VAL must be a symbol of a property value name.  But,
2512     if the name is "nil", a symbol of name "Nil" must be
2513     specified.  */
2514  /***ja
2515     @brief �ե���ȤΥץ�ѥƥ����ͤ����ꤹ��.
2516 
2517     �ؿ� mfont_put_prop () �ϡ��ե���� $FONT �Υ�����$KEY �Ǥ���ץ��
2518     �ƥ����ͤ� $VAL �����ꤹ�롣$KEY �ϰʲ��Υ���ܥ�Τ����줫�Ǥ��롣
2519 
2520 	@c Mfoundry, @c Mfamily, @c Mweight, @c Mstyle, @c Mstretch,
2521 	@c Madstyle, @c Mregistry, @c Msize, @c Mresolution.
2522 
2523     $KEY �� @c Msize �� @c Mresolution �Ǥ���� $VAL �������ͤǤʤ��Ƥ�
2524     ��ʤ�������ʳ��ξ�硢$VAL �ϥץ�ѥƥ��ͤ�̾���Υ���ܥ�Ǥʤ���
2525     �Ϥʤ�ʤ����������⤷����̾���� "nil" �ξ��ϡ�̾���� "Nil" �Υ�
2526     ��ܥ�Ǥʤ��ƤϤʤ�ʤ���*/
2527 
2528 int
mfont_put_prop(MFont * font,MSymbol key,void * val)2529 mfont_put_prop (MFont *font, MSymbol key, void *val)
2530 {
2531   if (key == Mfoundry)
2532     mfont__set_property (font, MFONT_FOUNDRY, (MSymbol) val);
2533   else if (key == Mfamily)
2534     mfont__set_property (font, MFONT_FAMILY, (MSymbol) val);
2535   else if (key == Mweight)
2536     mfont__set_property (font, MFONT_WEIGHT, (MSymbol) val);
2537   else if (key == Mstyle)
2538     mfont__set_property (font, MFONT_STYLE, (MSymbol) val);
2539   else if (key == Mstretch)
2540     mfont__set_property (font, MFONT_STRETCH, (MSymbol) val);
2541   else if (key == Madstyle)
2542     mfont__set_property (font, MFONT_ADSTYLE, (MSymbol) val);
2543   else if (key == Mregistry)
2544     mfont__set_property (font, MFONT_REGISTRY, (MSymbol) val);
2545   else if (key == Msize)
2546     {
2547       int size = (int) val;
2548       font->size = size;
2549     }
2550   else if (key == Mresolution)
2551     {
2552       unsigned resy = (unsigned) val;
2553       font->property[MFONT_RESY] = resy;
2554     }
2555   else if (key == Mlanguage || key == Mscript || key == Motf)
2556     {
2557       font->capability = merge_capability (font->capability,
2558 					   key, (MSymbol) val, 1);
2559     }
2560   else if (key == Mfontfile)
2561     {
2562       font->file = (MSymbol) val;
2563     }
2564   else
2565     MERROR (MERROR_FONT, -1);
2566   return 0;
2567 }
2568 
2569 /*=*/
2570 
2571 /***en
2572     @brief Return the font selection priority.
2573 
2574     The mfont_selection_priority () function returns a newly created
2575     array of six symbols.  The elements are the following
2576     keys of font properties ordered by priority.
2577 
2578 	@c Mfamily, @c Mweight, @c Mstyle, @c Mstretch,
2579 	@c Madstyle, @c Msize.
2580 
2581    The m17n library selects the best matching font according to the
2582    order of this array.  A font that has a different value for a
2583    property of lower priority is preferred to a font that has a
2584    different value for a property of higher priority.  */
2585 /***ja
2586     @brief �ե���������ͥ���٤��֤�.
2587 
2588     �ؿ� mfont_selection_priority () �� 6 �ĤΥ���ܥ뤫��ʤ�������ä��֤���
2589     ��������Ǥϡ��ʲ��Υե���ȥץ�ѥƥ��Υ�����ͥ���ٽ���¤٤���ΤǤ��롣
2590 
2591 	@c Mfamily, @c Mweight, @c Mstyle, @c Mstretch,
2592 	@c Madstyle, @c Msize.
2593 
2594    m17n �饤�֥��Ϥ�������˽��äơ��Ǥ���פ���ե���Ȥ������롣
2595    ��Ū�Υե���Ȥȡ����줾��㤦�ץ�ѥƥ����ͤ����פ��ʤ��ե���Ȥ����ä���硢ͥ���٤��㤤�ץ�ѥƥ����ͤ����פ��ʤ��ե���ȡ�ͥ���٤ι⤤�ץ�ѥƥ����ͤ����פ��Ƥ���ե���ȡˤ�������롣
2596 
2597    */
2598 
2599 MSymbol *
mfont_selection_priority()2600 mfont_selection_priority ()
2601 {
2602   MSymbol *keys;
2603   int i;
2604 
2605   MTABLE_MALLOC (keys, FONT_SCORE_PRIORITY_SIZE, MERROR_FONT);
2606   for (i = 0; i < FONT_SCORE_PRIORITY_SIZE; i++)
2607     {
2608       enum MFontProperty prop = font_score_priority[i];
2609 
2610       if (prop == MFONT_SIZE)
2611 	keys[i] = Msize;
2612       else if (prop == MFONT_ADSTYLE)
2613 	keys[i] = Madstyle;
2614       else if (prop == MFONT_FAMILY)
2615 	keys[i] = Mfamily;
2616       else if (prop == MFONT_WEIGHT)
2617 	keys[i] = Mweight;
2618       else if (prop == MFONT_STYLE)
2619 	keys[i] = Mstyle;
2620       else if (prop == MFONT_STRETCH)
2621 	keys[i] = Mstretch;
2622       else
2623 	keys[i] = Mfoundry;
2624     }
2625   return keys;
2626 }
2627 
2628 /*=*/
2629 
2630 /***en
2631     @brief Set the font selection priority.
2632 
2633     The mfont_set_selection_priority () function sets font selection
2634     priority according to $KEYS, which is an array of six symbols.
2635     Each element must be one of the below.  No two elements must be
2636     the same.
2637 
2638 	@c Mfamily, @c Mweight, @c Mstyle, @c Mstretch,
2639 	@c Madstyle, @c Msize.
2640 
2641     See the documentation of the function mfont_selection_priority ()
2642     for details.  */
2643 /***ja
2644     @brief �ե��������ͥ���٤����ꤹ��.
2645 
2646     �ؿ� mfont_set_selection_priority () �ϡ�6�ĤΥ���ܥ������ $KEYS
2647     �ˤ������äƥե��������ͥ���٤����ꤹ�롣����ϰʲ��γ����Ǥ�Ŭ��
2648     �ʽ��֤��¤٤���ΤǤ��롣
2649 
2650 	@c Mfamily, @c Mweight, @c Mstyle, @c Mstretch,
2651 	@c Madstyle, @c Msize.
2652 
2653     �ܺ٤ϴؿ� mfont_selection_priority () ���������ȤΤ��ȡ�
2654      */
2655 
2656 int
mfont_set_selection_priority(MSymbol * keys)2657 mfont_set_selection_priority (MSymbol *keys)
2658 {
2659   int priority[FONT_SCORE_PRIORITY_SIZE];
2660   int i, j, shift;
2661 
2662   for (i = 0; i < FONT_SCORE_PRIORITY_SIZE; i++, keys++)
2663     {
2664       enum MFontProperty prop;
2665 
2666       if (*keys == Msize)
2667 	prop = MFONT_SIZE;
2668       else if (*keys == Madstyle)
2669 	prop = MFONT_ADSTYLE;
2670       else if (*keys == Mfamily)
2671 	prop = MFONT_FAMILY;
2672       else if (*keys == Mweight)
2673 	prop = MFONT_WEIGHT;
2674       else if (*keys == Mstyle)
2675 	prop = MFONT_STYLE;
2676       else if (*keys == Mstretch)
2677 	prop = MFONT_STRETCH;
2678       else if (*keys == Mfoundry)
2679 	prop = MFONT_FOUNDRY;
2680       else
2681 	/* Invalid element.  */
2682 	return -1;
2683       for (j = 0; j < i; j++)
2684 	if (priority[j] == prop)
2685 	  /* Duplicated element.  */
2686 	  return -1;
2687       priority[i] = prop;
2688     }
2689   for (i = 0; i < FONT_SCORE_PRIORITY_SIZE; i++)
2690     font_score_priority[i] = priority[i];
2691   /* Here, SHIFT starts from 1, not 0.  This is because the lowest bit
2692      of a score is a flag for a scalable font (see the documentation
2693      of font_score).  */
2694   i = FONT_SCORE_PRIORITY_SIZE - 1;
2695   for (shift = 1; i >= 0; i--)
2696     {
2697       font_score_shift_bits[font_score_priority[i]] = shift;
2698       if (font_score_priority[i] == MFONT_SIZE)
2699 	shift += 16;
2700       else if (font_score_priority[i] <= MFONT_FAMILY)
2701 	shift++;
2702       else
2703 	shift += 2;
2704     }
2705   return 0;
2706 }
2707 
2708 /*=*/
2709 
2710 /***en
2711     @brief Find a font.
2712 
2713     The mfont_find () function returns a pointer to the available font
2714     that matches best the specification $SPEC on frame $FRAME.
2715 
2716     $SCORE, if not NULL, must point to a place to store the score
2717     value that indicates how well the found font matches to $SPEC.  The
2718     smaller score means a better match.  */
2719 /***ja
2720     @brief �ե���Ȥ�õ��.
2721 
2722     �ؿ� mfont_find () �ϡ��ե졼�� $FRAME ��ǥե������� $SPEC
2723     �ˤ�äȤ���פ������Ѳ�ǽ�ʥե���ȤؤΥݥ������֤���
2724 
2725     $SCORE �� NULL �Ǥ��뤫�����Ĥ��ä��ե���Ȥ� $SPEC
2726     �ˤɤ�ۤɹ�äƤ��뤫��������������¸������ؤΥݥ����Ǥ��롣
2727     ���������������ۤ��ɤ���äƤ��뤳�Ȥ��̣���롣
2728     */
2729 
2730 MFont *
mfont_find(MFrame * frame,MFont * spec,int * score,int max_size)2731 mfont_find (MFrame *frame, MFont *spec, int *score, int max_size)
2732 {
2733   MFont spec_copy;
2734   MFont *best;
2735   MFontList *list;
2736   MRealizedFont *rfont;
2737   MFont adjusted;
2738 
2739   if (spec->size < 0)
2740     {
2741       double pt = - spec->size;
2742 
2743       adjusted = *spec;
2744       adjusted.size = pt * frame->dpi / 72.27 + 0.5;
2745       spec = &adjusted;
2746     }
2747   MFONT_INIT (&spec_copy);
2748   spec_copy.property[MFONT_FAMILY] = spec->property[MFONT_FAMILY];
2749   spec_copy.property[MFONT_REGISTRY] = spec->property[MFONT_REGISTRY];
2750   spec_copy.capability = spec->capability;
2751   spec_copy.file = spec->file;
2752 
2753   list = mfont__list (frame, &spec_copy, spec, max_size);
2754   if (! list)
2755     return NULL;
2756 
2757   best = list->fonts[0].font;
2758   if (score)
2759     *score = list->fonts[0].score;
2760   free (list->fonts);
2761   free (list);
2762   spec_copy = *best;
2763   mfont__merge (&spec_copy, spec, 0);
2764   rfont = mfont__open (frame, best, spec);
2765   if (! rfont)
2766     return NULL;
2767   return (MFont *) rfont;
2768 }
2769 
2770 /*=*/
2771 /***en
2772     @brief Set encoding of a font.
2773 
2774     The mfont_set_encoding () function sets the encoding information
2775     of font $FONT.
2776 
2777     $ENCODING_NAME is a symbol representing a charset that has the
2778     same encoding as the font.
2779 
2780     $REPERTORY_NAME is @c Mnil or a symbol representing a charset that
2781     has the same repertory as the font.  If it is @c Mnil, whether a
2782     specific character is supported by the font is asked to each font
2783     driver.
2784 
2785     @return
2786     If the operation was successful, this function returns 0.
2787     Otherwise it returns -1 and assigns an error code to the external
2788     variable #merror_code.  */
2789 /***ja
2790     @brief �ե���ȤΥ������ǥ��������ꤹ��.
2791 
2792     �ؿ� mfont_set_encoding () �ϥե���� $FONT �Υ������ǥ�����������ꤹ�롣
2793 
2794     $ENCODING_NAME �ϥե���Ȥ�Ʊ���������ǥ��������ʸ�����åȤ�������ܥ�Ǥ��롣
2795 
2796     $REPERTORY_NAME �� @c Mnil �Ǥ��뤫���ե���Ȥ�Ʊ���������ǥ��������ʸ�����åȤ�������ܥ�Ǥ��롣
2797     @c Mnil �Ǥ���С��ġ���ʸ�������Υե���Ȥǥ��ݡ��Ȥ���Ƥ��뤫�ɤ����ϡ��ơ��Υե���ȥɥ饤�Ф��䤤��碌�롣
2798 
2799     @return
2800     ��������������Ф��δؿ��� 0 ���֤��������Ǥʤ���� -1 ���֤��������ѿ�
2801     #merror_code �˥��顼�����ɤ����ꤹ�롣  */
2802 
2803 
2804 int
mfont_set_encoding(MFont * font,MSymbol encoding_name,MSymbol repertory_name)2805 mfont_set_encoding (MFont *font, MSymbol encoding_name, MSymbol repertory_name)
2806 {
2807   MCharset *encoding_charset = MCHARSET (encoding_name);
2808   MCharset *repertory_charset;
2809   MSymbol registry;
2810   MFontEncoding *encoding;
2811   MPlist *plist;
2812 
2813   if (! encoding_charset)
2814     MERROR (MERROR_FONT, -1);
2815   if (repertory_name != Mnil)
2816     {
2817       repertory_charset = MCHARSET (repertory_name);
2818       if (! repertory_charset)
2819 	MERROR (MERROR_FONT, -1);
2820     }
2821   else
2822     repertory_charset = NULL;
2823 
2824   MSTRUCT_CALLOC (encoding, MERROR_FONT);
2825   encoding->spec = *font;
2826   encoding->encoding_name = encoding_name;
2827   encoding->encoding_charset = encoding_charset;
2828   encoding->repertory_name = repertory_name;
2829   encoding->repertory_charset = repertory_charset;
2830   registry = FONT_PROPERTY (font, MFONT_REGISTRY);
2831   if (registry == Mnil)
2832     registry = Mt;
2833   if (! font_encoding_list)
2834     load_font_encoding_table ();
2835   mplist_push (font_encoding_list, registry, encoding);
2836   MPLIST_DO (plist, MPLIST_NEXT (font_encoding_list))
2837     if (! memcmp (font, &((MFontEncoding *) MPLIST_VAL (plist))->spec,
2838 		  sizeof (MFont)))
2839       {
2840 	mplist_pop (plist);
2841 	break;
2842       }
2843   return 0;
2844 }
2845 
2846 /*=*/
2847 
2848 /***en
2849     @brief Create a fontname from a font.
2850 
2851     This function is obsolete.   Use mfont_unparse_name instead. */
2852 /***ja
2853     @brief �ե����̾����ե���Ȥ���.
2854 
2855     ���δؿ����ѻ�ͽ��Ǥ��롣 mfont_unparse_name () ����ѤΤ��ȡ� */
2856 
2857 char *
mfont_name(MFont * font)2858 mfont_name (MFont *font)
2859 {
2860   return mfont_unparse_name (font, Mx);
2861 }
2862 
2863 /*=*/
2864 
2865 /***en
2866     @brief Create a new font from fontname.
2867 
2868     This function is obsolete.  Use mfont_parse_name () instead.  */
2869 
2870 /***ja
2871     @brief �ե���Ȥ���ե����̾����.
2872 
2873     ����ϴؿ����ѻ�ͽ��Ǥ��롣 mfont_parse_name () ����ѤΤ��ȡ�  */
2874 
2875 MFont *
mfont_from_name(const char * name)2876 mfont_from_name (const char *name)
2877 {
2878   return mfont_parse_name (name, Mx);
2879 }
2880 
2881 /*=*/
2882 
2883 /***en
2884     @brief Get resize information of a font.
2885 
2886     The mfont_resize_ratio () function lookups the m17n database
2887     \<font, reisize\> and returns a resizing ratio (in percentage) of
2888     FONT.  For instance, if the return value is 150, that means that
2889     the m17n library uses an 1.5 time bigger font than a specified
2890     size.  */
2891 
2892 /***ja
2893     @brief �ե���ȤΥꥵ�������������
2894 
2895     �ؿ� mfont_resize_ratio �� m17n �ǡ����١��� \<font, reisize\>
2896     ���������ե���� FONT �Υꥵ��������Ψ�ʥѡ�����ơ�����
2897     ���֤������Ȥ����֤��ͤ� 150 �Ǥ���С�m17n �饤�֥��ϻ��ꤵ�줿�������� 1.5
2898     �ܤΥե���Ȥ���Ѥ��뤳�Ȥ��̣���롣 */
2899 
2900 int
mfont_resize_ratio(MFont * font)2901 mfont_resize_ratio (MFont *font)
2902 {
2903   MSymbol registry = FONT_PROPERTY (font, MFONT_REGISTRY);
2904   MFontResize *resize;
2905   MPlist *plist;
2906 
2907   if (! font_resize_list)
2908     load_font_resize_table ();
2909   if (! MPLIST_TAIL_P (font_resize_list))
2910     while (1)
2911       {
2912 	plist = font_resize_list;
2913 	while (registry ? (plist = mplist_find_by_key (plist, registry))
2914 	       : plist)
2915 	  {
2916 	    resize = (MFontResize *) MPLIST_VAL (plist);
2917 	    if (mfont__match_p (font, &resize->spec, MFONT_ADSTYLE))
2918 	      return resize->resize;
2919 	    plist = MPLIST_NEXT (plist);
2920 	  }
2921 	if (registry == Mt)
2922 	  break;
2923 	registry = Mt;
2924       }
2925   return 100;
2926 }
2927 
2928 /*=*/
2929 
2930 /***en
2931     @brief Get a list of fonts.
2932 
2933     The mfont_list () functions returns a list of fonts available on
2934     frame $FRAME.  $FONT, if not NULL, limits fonts to ones
2935     that match with $FONT.  $LANGUAGE, if not @c Mnil, limits fonts to
2936     ones that support $LANGUAGE.  $MAXNUM, if greater than 0, limits
2937     the number of fonts.
2938 
2939     $LANGUAGE argument exists just for backward compatibility, and the
2940     use is deprecated.  Use #Mlanguage font property instead.  If
2941     $FONT already has #Mlanguage property, $LANGUAGE is ignored.
2942 
2943     @return
2944     This function returns a plist whose keys are family names and
2945     values are pointers to the object MFont.  The plist must be freed
2946     by m17n_object_unref ().  If no font is found, it returns
2947     NULL.  */
2948 
2949 /***ja
2950     @brief �ե���ȤΥꥹ�Ȥ�����
2951 
2952     �ؿ� mfont_list () �ϥե졼�� $FRAME �����Ѳ�ǽ�ʥե���ȤΥꥹ�Ȥ�
2953     �֤���$FONT �� NULL �Ǥʤ���С�$FONT �ȹ��פ������Ѳ�ǽ�ʥե����
2954     �Υꥹ�Ȥ��֤���$LANGUAGE �� @c Mnil �Ǥʤ���С�$LANGUAGE ���ݡ�
2955     �Ȥ������Ѳ�ǽ�ʥե���ȤΥꥹ�Ȥ��֤���$MAXNUM �ϡ�0 ����礭����
2956     ��ˤϡ��֤��ե���Ȥο��ξ�¤Ǥ��롣
2957 
2958     ������������ $LANGUAGE �ϵ��ǤȤ��������Τ�������ˤ��ꡢ���λ��Ѥ�
2959     ������ʤ����ե���Ȥ� #Mlanguage �ץ�ѥƥ���Ȥ��٤��Ǥ��롣��
2960     �� $FONT �����Ǥˤ��Υץ�ѥƥ�����äƤ����顢���� $LANGUAGE ��̵
2961 
2962 
2963     @return
2964     ���δؿ��ϥ������ե���ȥե��ߥ�̾�Ǥ����ͤ� MFont ���֥������Ȥؤ�
2965     �ݥ����Ǥ���褦��plist ���֤���plist �� m17n_object_unref () ��
2966     ��������ɬ�פ����롣�ե���Ȥ����Ĥ���ʤ����NULL ���֤���  */
2967 
2968 MPlist *
mfont_list(MFrame * frame,MFont * font,MSymbol language,int maxnum)2969 mfont_list (MFrame *frame, MFont *font, MSymbol language, int maxnum)
2970 {
2971   MPlist *plist, *pl;
2972   MFontList *font_list;
2973   int i;
2974   MFont spec;
2975 
2976   if (font)
2977     spec = *font;
2978   else
2979     MFONT_INIT (&spec);
2980 
2981   if (spec.size < 0)
2982     {
2983       double pt = - spec.size;
2984 
2985       spec.size = pt * frame->dpi / 72.27 + 0.5;
2986     }
2987 
2988   if (language != Mnil)
2989     spec.capability = merge_capability (spec.capability, Mlanguage, language,
2990 					0);
2991 
2992   font_list = mfont__list (frame, &spec, &spec, 0);
2993   if (! font_list)
2994     return NULL;
2995   if (font_list->nfonts == 0)
2996     {
2997       free (font_list);
2998       return NULL;
2999     }
3000 
3001   plist = pl = mplist ();
3002   for (i = 0; i < font_list->nfonts; i++)
3003     {
3004       MSymbol family = FONT_PROPERTY (font_list->fonts[i].font, MFONT_FAMILY);
3005 
3006       if (family != Mnil)
3007 	pl = mplist_add (pl, family, font_list->fonts[i].font);
3008     }
3009   free (font_list);
3010   return plist;
3011 }
3012 
3013 /***en
3014     @brief Get a list of font famiy names.
3015 
3016     The mfont_list_family_names () functions returns a list of font
3017     family names available on frame $FRAME.
3018 
3019     @return
3020 
3021     This function returns a plist whose keys are #Msymbol and values
3022     are symbols representing font family names.  The elements are
3023     sorted by alphabetical order.  The plist must be freed by
3024     m17n_object_unref ().  If not font is found, it returns NULL.  */
3025 
3026 MPlist *
mfont_list_family_names(MFrame * frame)3027 mfont_list_family_names (MFrame *frame)
3028 {
3029   MPlist *plist = mplist (), *p;
3030 
3031   MPLIST_DO (p, frame->font_driver_list)
3032     {
3033       MFontDriver *driver = MPLIST_VAL (p);
3034 
3035       (driver->list_family_names) (frame, plist);
3036     }
3037   return plist;
3038 }
3039 
3040 
3041 /*=*/
3042 
3043 /***en
3044     @brief Check the usability of a font.
3045 
3046     The mfont_check () function checkes if $FONT can be used for
3047     $SCRIPT and $LANGUAGE in $FONTSET on $FRAME.
3048 
3049     @return
3050     If the font is usable, return 1.  Otherwise return 0.
3051  */
3052 
3053 int
mfont_check(MFrame * frame,MFontset * fontset,MSymbol script,MSymbol language,MFont * font)3054 mfont_check (MFrame *frame, MFontset *fontset,
3055 	     MSymbol script, MSymbol language, MFont *font)
3056 {
3057   MRealizedFont *rfont;
3058   int best, score;
3059 
3060   if (! fontset)
3061     fontset = frame->face->property[MFACE_FONTSET];
3062   rfont = mfontset__get_font (frame, fontset, script, language, font, &best);
3063   if (! rfont || ! best)
3064     return 0;
3065   score = font_score (&rfont->spec, font);
3066   return (score == 0 ? 2 : 1);
3067 }
3068 
3069 /*=*/
3070 
3071 /***en
3072     @brief Check is a font matches with a font spec.
3073 
3074     The mfont_match_p () function checks if $FONT matches with the
3075     font-spec $SPEC.
3076 
3077     @return
3078     If the font matches, 1 is returned.  Otherwise 0 is returned.  */
3079 
3080 int
mfont_match_p(MFont * font,MFont * spec)3081 mfont_match_p (MFont *font, MFont *spec)
3082 {
3083   return mfont__match_p (font, spec, MFONT_REGISTRY);
3084 }
3085 
3086 /*=*/
3087 /***en
3088     @brief Open a font.
3089 
3090     The mfont_open () function opens $FONT on $FRAME, and returns a
3091     realized font.
3092 
3093     @return
3094     If the font was successfully opened, a realized font is returned.
3095     Otherwize NULL is returned.
3096 
3097     @seealso
3098     mfont_close ().  */
3099 
3100 
3101 MFont *
mfont_open(MFrame * frame,MFont * font)3102 mfont_open (MFrame *frame, MFont *font)
3103 {
3104   enum MFontType font_type = font->type;
3105 
3106   if (font_type == MFONT_TYPE_SPEC)
3107     return mfont_find (frame, font, NULL, 0);
3108   if (font_type == MFONT_TYPE_OBJECT)
3109     return (MFont *) mfont__open (frame, font, font);
3110   if (font_type == MFONT_TYPE_REALIZED)
3111     return font;
3112   MERROR (MERROR_FONT, NULL);
3113 }
3114 
3115 /*=*/
3116 /***en
3117     @brief Encapusulate a font.
3118 
3119     The mfont_encapsulate () functions realizes a font by
3120     encapusulating data $DATA or type $DATA_TYPE on $FRAME.  Currently
3121     $DATA_TAPE is #Mfontconfig or #Mfreetype, and $DATA points to an
3122     object of FcPattern or FT_Face respectively.
3123 
3124     @return
3125     If the operation was successful, a realized font is returned.
3126     Otherwise NULL is return.
3127 
3128     @seealso
3129     mfont_close ().  */
3130 
3131 
3132 MFont *
mfont_encapsulate(MFrame * frame,MSymbol data_type,void * data)3133 mfont_encapsulate (MFrame *frame, MSymbol data_type, void *data)
3134 {
3135   MPlist *p;
3136 
3137   MPLIST_DO (p, frame->font_driver_list)
3138     {
3139       MFontDriver *driver = MPLIST_VAL (p);
3140       MRealizedFont *rfont;
3141 
3142       if (driver->encapsulate
3143 	  && (rfont = driver->encapsulate (frame, data_type, data)))
3144 	return (MFont *) rfont;
3145     }
3146 
3147   return NULL;
3148 }
3149 
3150 /*=*/
3151 /***en
3152     @brief Close a font.
3153 
3154     The mfont_close () function close a realized font $FONT.  $FONT
3155     must be opened previously by mfont_open () or mfont_encapsulate
3156     ().
3157 
3158     @return
3159     If the operation was successful, 0 is returned.  Otherwise, -1 is
3160     returned.
3161 
3162     @seealso
3163     mfont_open (), mfont_encapsulate ().  */
3164 
3165 int
mfont_close(MFont * font)3166 mfont_close (MFont *font)
3167 {
3168   enum MFontType font_type = font->type;
3169   MRealizedFont *rfont;
3170 
3171   if (font_type != MFONT_TYPE_REALIZED)
3172     MERROR (MERROR_FONT, -1);
3173   rfont = (MRealizedFont *) font;
3174   if (rfont->encapsulating
3175       && rfont->driver->close)
3176     rfont->driver->close (rfont);
3177   return 0;
3178 }
3179 
3180 /*** @} */
3181 
3182 /*** @addtogroup m17nDebug */
3183 /*=*/
3184 /*** @{ */
3185 
3186 /***en
3187     @brief Dump a font.
3188 
3189     The mdebug_dump_font () function prints font $FONT in a human
3190     readable way to the stderr or to what specified by the environment
3191     variable MDEBUG_OUTPUT_FILE.
3192 
3193     @return
3194     This function returns $FONT.  */
3195 /***ja
3196     @brief �ե���Ȥ����פ���.
3197 
3198     �ؿ� mdebug_dump_font () �ϥե���� $FONT ��ɸ�२�顼���Ϥ⤷����
3199     �Ķ��ѿ� MDEBUG_DUMP_FONT �ǻ��ꤵ�줿�ե�����˿ʹ֤˲��ɤʷ��ǽ�
3200     �Ϥ��롣
3201 
3202     @return
3203     ���δؿ��� $FONT ���֤���  */
3204 
3205 MFont *
mdebug_dump_font(MFont * font)3206 mdebug_dump_font (MFont *font)
3207 {
3208   char *name;
3209 
3210   name = xlfd_unparse_name (font, 0);
3211   if (name)
3212     {
3213       fprintf (mdebug__output, "%s", name);
3214       free (name);
3215     }
3216   if (font->file != Mnil)
3217     {
3218       char *file = MSYMBOL_NAME (font->file);
3219       char *lastslash = file, *p;
3220 
3221       for (p = file; *p; p++)
3222 	if (*p == '/')
3223 	  lastslash = p;
3224       if (name)
3225 	fprintf (mdebug__output, ",");
3226       fprintf (mdebug__output, "%s", lastslash + 1);
3227     }
3228   if (font->capability != Mnil)
3229     fprintf (mdebug__output, "%s", MSYMBOL_NAME (font->capability));
3230   return font;
3231 }
3232 
3233 /*** @} */
3234 
3235 /*
3236   Local Variables:
3237   coding: euc-japan
3238   End:
3239 */
3240