1 /* ftfont.c -- FreeType font driver.
2 Copyright (C) 2006, 2007, 2008 Free Software Foundation, Inc.
3 Copyright (C) 2006, 2007, 2008
4 National Institute of Advanced Industrial Science and Technology (AIST)
5 Registration Number H13PRO009
7 This file is part of GNU Emacs.
9 GNU Emacs is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3, or (at your option)
14 GNU Emacs is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with GNU Emacs; see the file COPYING. If not, write to
21 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22 Boston, MA 02110-1301, USA. */
27 #include <fontconfig/fontconfig.h>
28 #include <fontconfig/fcfreetype.h>
31 #include "dispextern.h"
33 #include "blockinput.h"
34 #include "character.h"
41 /* Symbolic type of this font-driver. */
42 Lisp_Object Qfreetype
;
44 /* Fontconfig's generic families and their aliases. */
45 static Lisp_Object Qmonospace
, Qsans_serif
, Qserif
, Qmono
, Qsans
, Qsans__serif
;
47 /* Flag to tell if FcInit is areadly called or not. */
48 static int fc_initialized
;
50 /* Handle to a FreeType library instance. */
51 static FT_Library ft_library
;
53 /* Cache for FreeType fonts. */
54 static Lisp_Object freetype_font_cache
;
56 /* Fontconfig's charset used for finding fonts of registry
58 static FcCharSet
*cs_iso8859_1
;
60 /* The actual structure for FreeType font that can be casted to struct
68 int maybe_otf
; /* Flag to tell if this may be OTF or not. */
70 #endif /* HAVE_LIBOTF */
73 static int ftfont_build_basic_charsets
P_ ((void));
74 static Lisp_Object ftfont_pattern_entity
P_ ((FcPattern
*, Lisp_Object
));
75 static Lisp_Object ftfont_list_generic_family
P_ ((Lisp_Object
));
76 Lisp_Object ftfont_font_format
P_ ((FcPattern
*));
78 #define SYMBOL_FcChar8(SYM) (FcChar8 *) SDATA (SYMBOL_NAME (SYM))
81 ftfont_build_basic_charsets ()
85 cs_iso8859_1
= FcCharSetCreate ();
88 for (c
= ' '; c
< 127; c
++)
89 if (! FcCharSetAddChar (cs_iso8859_1
, c
))
92 /* This part is currently disabled. Should be fixed later. */
93 for (c
= 192; c
< 256; c
++)
94 if (! FcCharSetAddChar (cs_iso8859_1
, c
))
100 extern Lisp_Object Qc
, Qm
, Qp
, Qd
;
103 ftfont_pattern_entity (p
, registry
)
105 Lisp_Object registry
;
108 FcChar8
*file
, *fontformat
;
115 if (FcPatternGetString (p
, FC_FILE
, 0, &file
) != FcResultMatch
)
117 if (FcPatternGetCharSet (p
, FC_CHARSET
, 0, &charset
) != FcResultMatch
)
120 if (FcPatternGetString (p
, FC_FONTFORMAT
, 0, &fontformat
) != FcResultMatch
)
121 #endif /* FC_FONTFORMAT */
124 entity
= font_make_entity ();
126 ASET (entity
, FONT_TYPE_INDEX
, Qfreetype
);
127 ASET (entity
, FONT_REGISTRY_INDEX
, registry
);
129 if (FcPatternGetString (p
, FC_FOUNDRY
, 0, &str
) == FcResultMatch
)
130 ASET (entity
, FONT_FOUNDRY_INDEX
, font_intern_prop (str
, strlen (str
)));
131 if (FcPatternGetString (p
, FC_FAMILY
, 0, &str
) == FcResultMatch
)
132 ASET (entity
, FONT_FAMILY_INDEX
, font_intern_prop (str
, strlen (str
)));
133 if (FcPatternGetInteger (p
, FC_WEIGHT
, 0, &numeric
) == FcResultMatch
)
135 if (numeric
>= FC_WEIGHT_REGULAR
&& numeric
< FC_WEIGHT_MEDIUM
)
136 numeric
= FC_WEIGHT_MEDIUM
;
137 FONT_SET_STYLE (entity
, FONT_WEIGHT_INDEX
, make_number (numeric
));
139 if (FcPatternGetInteger (p
, FC_SLANT
, 0, &numeric
) == FcResultMatch
)
142 FONT_SET_STYLE (entity
, FONT_SLANT_INDEX
, make_number (numeric
));
144 if (FcPatternGetInteger (p
, FC_WIDTH
, 0, &numeric
) == FcResultMatch
)
146 FONT_SET_STYLE (entity
, FONT_WIDTH_INDEX
, make_number (numeric
));
148 if (FcPatternGetDouble (p
, FC_PIXEL_SIZE
, 0, &dbl
) == FcResultMatch
)
149 ASET (entity
, FONT_SIZE_INDEX
, make_number (dbl
));
151 ASET (entity
, FONT_SIZE_INDEX
, make_number (0));
152 if (FcPatternGetInteger (p
, FC_SPACING
, 0, &numeric
) == FcResultMatch
)
153 ASET (entity
, FONT_SPACING_INDEX
, make_number (numeric
));
154 if (FcPatternGetDouble (p
, FC_DPI
, 0, &dbl
) == FcResultMatch
)
157 ASET (entity
, FONT_DPI_INDEX
, make_number (dpi
));
159 if (FcPatternGetBool (p
, FC_SCALABLE
, 0, &b
) == FcResultMatch
161 ASET (entity
, FONT_AVGWIDTH_INDEX
, make_number (0));
163 file
= FcStrCopy (file
);
166 p
= FcPatternCreate ();
170 if (FcPatternAddString (p
, FC_FILE
, file
) == FcFalse
172 && FcPatternAddCharSet (p
, FC_CHARSET
, charset
) == FcFalse
)
175 && FcPatternAddString (p
, FC_FONTFORMAT
, fontformat
) == FcFalse
)
176 #endif /* FC_FONTFORMAT */
179 FcPatternDestroy (p
);
182 font_put_extra (entity
, QCfont_entity
, make_save_value (p
, 0));
187 static Lisp_Object ftfont_generic_family_list
;
190 ftfont_list_generic_family (family
)
193 Lisp_Object slot
, list
, val
;
194 FcObjectSet
*objset
= NULL
;
195 FcPattern
*pattern
= NULL
, *pat
= NULL
;
196 FcFontSet
*fontset
= NULL
;
200 if (EQ (family
, Qmono
))
202 else if (EQ (family
, Qsans
) || EQ (family
, Qsans__serif
))
203 family
= Qsans_serif
;
204 slot
= assq_no_quit (family
, ftfont_generic_family_list
);
211 objset
= FcObjectSetBuild (FC_FAMILY
, NULL
);
214 pattern
= FcPatternBuild (NULL
, FC_FAMILY
, FcTypeString
,
215 SYMBOL_FcChar8 (family
), (char *) 0);
218 pat
= FcPatternCreate ();
221 FcConfigSubstitute (NULL
, pattern
, FcMatchPattern
);
222 for (i
= 0, list
= Qnil
;
223 FcPatternGetString (pattern
, FC_FAMILY
, i
, &fam
) == FcResultMatch
;
226 if (strcmp ((char *) fam
, (char *) SYMBOL_FcChar8 (family
)) == 0)
228 if (! FcPatternAddString (pat
, FC_FAMILY
, fam
))
230 fontset
= FcFontList (NULL
, pat
, objset
);
233 if (fontset
->nfont
> 0)
234 list
= Fcons (intern ((char *) fam
), list
);
235 FcFontSetDestroy (fontset
);
237 FcPatternDel (pat
, FC_FAMILY
);
239 XSETCDR (slot
, list
);
241 if (pat
) FcPatternDestroy (pat
);
242 if (pattern
) FcPatternDestroy (pattern
);
243 if (fontset
) FcFontSetDestroy (fontset
);
244 if (objset
) FcObjectSetDestroy (objset
);
248 static Lisp_Object ftfont_get_cache
P_ ((FRAME_PTR
));
249 static Lisp_Object ftfont_list
P_ ((Lisp_Object
, Lisp_Object
));
250 static Lisp_Object ftfont_match
P_ ((Lisp_Object
, Lisp_Object
));
251 static Lisp_Object ftfont_list_family
P_ ((Lisp_Object
));
252 static Lisp_Object ftfont_open
P_ ((FRAME_PTR
, Lisp_Object
, int));
253 static void ftfont_close
P_ ((FRAME_PTR
, struct font
*));
254 static int ftfont_has_char
P_ ((Lisp_Object
, int));
255 static unsigned ftfont_encode_char
P_ ((struct font
*, int));
256 static int ftfont_text_extents
P_ ((struct font
*, unsigned *, int,
257 struct font_metrics
*));
258 static int ftfont_get_bitmap
P_ ((struct font
*, unsigned,
259 struct font_bitmap
*, int));
260 static int ftfont_anchor_point
P_ ((struct font
*, unsigned, int,
262 static Lisp_Object ftfont_shape
P_ ((Lisp_Object
));
264 struct font_driver ftfont_driver
=
267 0, /* case insensitive */
275 /* We can't draw a text without device dependent functions. */
281 /* We can't draw a text without device dependent functions. */
292 #if defined (HAVE_M17N_FLT) && defined (HAVE_LIBOTF)
294 #else /* not (HAVE_M17N_FLT && HAVE_LIBOTF) */
296 #endif /* not (HAVE_M17N_FLT && HAVE_LIBOTF) */
299 extern Lisp_Object QCname
;
305 return freetype_font_cache
;
311 unsigned int script_tag
, langsys_tag
;
313 unsigned int *features
[2];
316 #define OTF_SYM_TAG(SYM, TAG) \
318 unsigned char *p = SDATA (SYMBOL_NAME (SYM)); \
319 TAG = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; \
322 #define OTF_TAG_STR(TAG, P) \
324 (P)[0] = (char) (TAG >> 24); \
325 (P)[1] = (char) ((TAG >> 16) & 0xFF); \
326 (P)[2] = (char) ((TAG >> 8) & 0xFF); \
327 (P)[3] = (char) (TAG & 0xFF); \
331 static struct OpenTypeSpec
*
332 ftfont_get_open_type_spec (Lisp_Object otf_spec
)
334 struct OpenTypeSpec
*spec
= malloc (sizeof (struct OpenTypeSpec
));
340 spec
->script
= XCAR (otf_spec
);
341 if (! NILP (spec
->script
))
343 OTF_SYM_TAG (spec
->script
, spec
->script_tag
);
344 val
= assq_no_quit (spec
->script
, Votf_script_alist
);
345 if (CONSP (val
) && SYMBOLP (XCDR (val
)))
346 spec
->script
= XCDR (val
);
351 spec
->script_tag
= 0x44464C54; /* "DFLT" */
352 otf_spec
= XCDR (otf_spec
);
353 val
= XCAR (otf_spec
);
355 OTF_SYM_TAG (val
, spec
->langsys_tag
);
357 spec
->langsys_tag
= 0;
358 spec
->nfeatures
[0] = spec
->nfeatures
[1] = 0;
359 for (i
= 0; i
< 2; i
++)
363 otf_spec
= XCDR (otf_spec
);
366 val
= XCAR (otf_spec
);
370 spec
->features
[i
] = malloc (sizeof (int) * XINT (len
));
371 if (! spec
->features
[i
])
373 if (i
> 0 && spec
->features
[0])
374 free (spec
->features
[0]);
378 for (j
= 0, negative
= 0; CONSP (val
); val
= XCDR (val
))
380 if (NILP (XCAR (val
)))
386 OTF_SYM_TAG (XCAR (val
), tag
);
387 spec
->features
[i
][j
++] = negative
? tag
& 0x80000000 : tag
;
390 spec
->nfeatures
[i
] = j
;
396 ftfont_spec_pattern (spec
, otlayout
, otspec
)
399 struct OpenTypeSpec
**otspec
;
401 Lisp_Object val
, tmp
, extra
;
403 FcPattern
*pattern
= NULL
;
404 FcCharSet
*charset
= NULL
;
405 FcLangSet
*langset
= NULL
;
410 Lisp_Object name
= Qnil
;
411 Lisp_Object script
= Qnil
;
412 Lisp_Object registry
= Qunicode_bmp
;
414 if (! NILP (AREF (spec
, FONT_ADSTYLE_INDEX
))
415 && SBYTES (SYMBOL_NAME (AREF (spec
, FONT_ADSTYLE_INDEX
))) > 0)
416 /* Fontconfig doesn't support adstyle property. */
418 if ((n
= FONT_SLANT_NUMERIC (spec
)) >= 0
420 /* Fontconfig doesn't support reverse-italic/obligue. */
423 if (INTEGERP (AREF (spec
, FONT_DPI_INDEX
)))
424 dpi
= XINT (AREF (spec
, FONT_DPI_INDEX
));
425 if (INTEGERP (AREF (spec
, FONT_SPACING_INDEX
)))
426 spacing
= XINT (AREF (spec
, FONT_SPACING_INDEX
));
427 if (INTEGERP (AREF (spec
, FONT_AVGWIDTH_INDEX
))
428 && XINT (AREF (spec
, FONT_AVGWIDTH_INDEX
)) == 0)
431 if (! NILP (AREF (spec
, FONT_REGISTRY_INDEX
)))
433 registry
= AREF (spec
, FONT_REGISTRY_INDEX
);
434 if (EQ (registry
, Qiso8859_1
))
437 && ftfont_build_basic_charsets () < 0)
439 charset
= cs_iso8859_1
;
441 else if (! EQ (registry
, Qiso10646_1
)
442 && ! EQ (registry
, Qunicode_bmp
)
443 && ! EQ (registry
, Qunicode_sip
))
448 for (extra
= AREF (spec
, FONT_EXTRA_INDEX
);
449 CONSP (extra
); extra
= XCDR (extra
))
451 Lisp_Object key
, val
;
453 key
= XCAR (XCAR (extra
)), val
= XCDR (XCAR (extra
));
456 else if (EQ (key
, QCfc_unknown_spec
))
458 else if (EQ (key
, QClang
))
460 langset
= FcLangSetCreate ();
465 if (! FcLangSetAdd (langset
, SYMBOL_FcChar8 (val
)))
469 for (; CONSP (val
); val
= XCDR (val
))
470 if (SYMBOLP (XCAR (val
))
471 && ! FcLangSetAdd (langset
, SYMBOL_FcChar8 (XCAR (val
))))
474 else if (EQ (key
, QCname
))
476 else if (EQ (key
, QCotf
))
478 *otspec
= ftfont_get_open_type_spec (val
);
481 strcat (otlayout
, "otlayout:");
482 OTF_TAG_STR ((*otspec
)->script_tag
, otlayout
+ 9);
483 script
= (*otspec
)->script
;
485 else if (EQ (key
, QCscript
))
487 else if (EQ (key
, QCscalable
))
488 scalable
= ! NILP (val
);
491 if (! NILP (script
) && ! charset
)
493 Lisp_Object chars
= assq_no_quit (script
, Vscript_representative_chars
);
497 charset
= FcCharSetCreate ();
500 for (chars
= XCDR (chars
); CONSP (chars
); chars
= XCDR (chars
))
501 if (CHARACTERP (XCAR (chars
))
502 && ! FcCharSetAddChar (charset
, XUINT (XCAR (chars
))))
507 pattern
= NILP (name
) ? FcPatternCreate () : FcNameParse (SDATA (name
));
510 FcPatternDel (pattern
, FC_SIZE
);
511 FcPatternDel (pattern
, FC_PIXEL_SIZE
);
512 tmp
= AREF (spec
, FONT_FOUNDRY_INDEX
);
514 && ! FcPatternAddString (pattern
, FC_FOUNDRY
, SYMBOL_FcChar8 (tmp
)))
517 && ! FcPatternAddCharSet (pattern
, FC_CHARSET
, charset
))
520 && ! FcPatternAddLangSet (pattern
, FC_LANG
, langset
))
523 && ! FcPatternAddDouble (pattern
, FC_DPI
, dpi
))
526 && ! FcPatternAddInteger (pattern
, FC_SPACING
, spacing
))
529 && ! FcPatternAddBool (pattern
, FC_SCALABLE
, scalable
? FcTrue
: FcFalse
))
534 /* We come here because of unexpected error in fontconfig API call
535 (usually insufficient memory). */
538 FcPatternDestroy (pattern
);
543 if ((*otspec
)->nfeatures
[0] > 0)
544 free ((*otspec
)->features
[0]);
545 if ((*otspec
)->nfeatures
[1] > 0)
546 free ((*otspec
)->features
[1]);
552 if (charset
&& charset
!= cs_iso8859_1
) FcCharSetDestroy (charset
);
553 if (langset
) FcLangSetDestroy (langset
);
558 ftfont_list (frame
, spec
)
559 Lisp_Object frame
, spec
;
561 Lisp_Object val
, tmp
, registry
, family
, family_list
;
564 FcFontSet
*fontset
= NULL
;
565 FcObjectSet
*objset
= NULL
;
566 double pixel_size
= 0;
567 int weight
= -1, slant
= -1, width
= -1;
571 char otlayout
[15]; /* For "otlayout:XXXX" */
572 struct OpenTypeSpec
*otspec
= NULL
;
574 if (! fc_initialized
)
580 pattern
= ftfont_spec_pattern (spec
, otlayout
, &otspec
);
583 objset
= FcObjectSetBuild (FC_FOUNDRY
, FC_FAMILY
, FC_WEIGHT
, FC_SLANT
,
584 FC_WIDTH
, FC_PIXEL_SIZE
, FC_SPACING
, FC_SCALABLE
,
588 #endif /* FC_CAPABILITY */
591 #endif /* FC_FONTFORMAT */
596 registry
= AREF (spec
, FONT_REGISTRY_INDEX
);
597 family
= AREF (spec
, FONT_FAMILY_INDEX
);
599 family_list
= Fcons (Qnil
, Qnil
);
602 family_list
= ftfont_list_generic_family (family
);
603 if (NILP (family_list
))
604 family_list
= Fcons (family
, Qnil
);
607 for (val
= Qnil
; CONSP (family_list
); family_list
= XCDR (family_list
))
609 family
= XCAR (family_list
);
612 FcPatternDel (pattern
, FC_FAMILY
);
613 if (! FcPatternAddString (pattern
, FC_FAMILY
, SYMBOL_FcChar8 (family
)))
616 fontset
= FcFontList (NULL
, pattern
, objset
);
619 for (i
= 0; i
< fontset
->nfont
; i
++)
630 if (FcPatternGetString (fontset
->fonts
[i
], FC_CAPABILITY
, 0,
631 &this) != FcResultMatch
632 || ! strstr ((char *) this, otlayout
))
635 #endif /* FC_CAPABILITY */
642 if (FcPatternGetString (fontset
->fonts
[i
], FC_FILE
, 0, &file
)
645 otf
= OTF_open ((char *) file
);
648 if (OTF_check_features (otf
, 1,
649 otspec
->script_tag
, otspec
->langsys_tag
,
651 otspec
->nfeatures
[0]) != 1
652 || OTF_check_features (otf
, 0,
653 otspec
->script_tag
, otspec
->langsys_tag
,
655 otspec
->nfeatures
[1]) != 1)
658 #endif /* HAVE_LIBOTF */
659 entity
= ftfont_pattern_entity (fontset
->fonts
[i
], registry
);
661 val
= Fcons (entity
, val
);
663 FcFontSetDestroy (fontset
);
669 /* We come here because of unexpected error in fontconfig API call
670 (usually insufficient memory). */
674 if (objset
) FcObjectSetDestroy (objset
);
675 if (fontset
) FcFontSetDestroy (fontset
);
676 if (pattern
) FcPatternDestroy (pattern
);
681 ftfont_match (frame
, spec
)
682 Lisp_Object frame
, spec
;
684 Lisp_Object extra
, val
, entity
;
685 FcPattern
*pattern
, *match
= NULL
;
687 char otlayout
[15]; /* For "otlayout:XXXX" */
688 struct OpenTypeSpec
*otspec
= NULL
;
690 if (! fc_initialized
)
696 pattern
= ftfont_spec_pattern (spec
, otlayout
, &otspec
);
700 if (INTEGERP (AREF (spec
, FONT_SIZE_INDEX
)))
704 value
.type
= FcTypeDouble
;
705 value
.u
.d
= XINT (AREF (spec
, FONT_SIZE_INDEX
));
706 FcPatternAdd (pattern
, FC_PIXEL_SIZE
, value
, FcFalse
);
708 if (FcConfigSubstitute (NULL
, pattern
, FcMatchPattern
) == FcTrue
)
710 FcDefaultSubstitute (pattern
);
711 match
= FcFontMatch (NULL
, pattern
, &result
);
714 entity
= ftfont_pattern_entity (match
, Qunicode_bmp
);
715 FcPatternDestroy (match
);
716 if (! NILP (AREF (spec
, FONT_FAMILY_INDEX
))
717 && NILP (assq_no_quit (AREF (spec
, FONT_FAMILY_INDEX
),
718 ftfont_generic_family_list
))
719 && NILP (Fstring_equal (AREF (spec
, FONT_FAMILY_INDEX
),
720 AREF (entity
, FONT_FAMILY_INDEX
))))
724 FcPatternDestroy (pattern
);
730 ftfont_list_family (frame
)
734 FcPattern
*pattern
= NULL
;
735 FcFontSet
*fontset
= NULL
;
736 FcObjectSet
*objset
= NULL
;
739 if (! fc_initialized
)
745 pattern
= FcPatternCreate ();
748 objset
= FcObjectSetBuild (FC_FAMILY
, NULL
);
751 fontset
= FcFontList (NULL
, pattern
, objset
);
756 for (i
= 0; i
< fontset
->nfont
; i
++)
758 FcPattern
*pat
= fontset
->fonts
[i
];
761 if (FcPatternGetString (pat
, FC_FAMILY
, 0, &str
) == FcResultMatch
)
762 list
= Fcons (intern ((char *) str
), list
);
766 if (objset
) FcObjectSetDestroy (objset
);
767 if (fontset
) FcFontSetDestroy (fontset
);
768 if (pattern
) FcPatternDestroy (pattern
);
775 ftfont_open (f
, entity
, pixel_size
)
780 struct ftfont_info
*ftfont_info
;
785 Lisp_Object val
, font_object
;
787 FcChar8
*file
= NULL
, *fmt
= NULL
;
794 val
= assq_no_quit (QCfont_entity
, AREF (entity
, FONT_EXTRA_INDEX
));
798 pattern
= XSAVE_VALUE (val
)->pointer
;
799 if (XSAVE_VALUE (val
)->integer
== 0)
801 /* We have not yet created FT_Face for this font. */
803 && FT_Init_FreeType (&ft_library
) != 0)
805 if (FcPatternGetString (pattern
, FC_FILE
, 0, &file
) != FcResultMatch
)
807 if (FT_New_Face (ft_library
, (char *) file
, 0, &ft_face
) != 0)
809 FcPatternAddFTFace (pattern
, FC_FT_FACE
, ft_face
);
810 ft_size
= ft_face
->size
;
811 XSAVE_VALUE (val
)->integer
++;
815 if (FcPatternGetFTFace (pattern
, FC_FT_FACE
, 0, &ft_face
)
818 if (FT_New_Size (ft_face
, &ft_size
) != 0)
820 if (FT_Activate_Size (ft_size
) != 0)
822 FT_Done_Size (ft_size
);
827 size
= XINT (AREF (entity
, FONT_SIZE_INDEX
));
830 if (FT_Set_Pixel_Sizes (ft_face
, size
, size
) != 0)
832 if (XSAVE_VALUE (val
)->integer
== 0)
833 FT_Done_Face (ft_face
);
837 font_object
= font_make_object (VECSIZE (struct ftfont_info
));
838 ASET (font_object
, FONT_TYPE_INDEX
, Qfreetype
);
839 for (i
= 1;i
< FONT_ENTITY_MAX
; i
++)
840 ASET (font_object
, i
, AREF (entity
, i
));
841 ASET (font_object
, FONT_SIZE_INDEX
, make_number (size
));
842 len
= font_unparse_xlfd (entity
, size
, name
, 256);
844 ASET (font_object
, FONT_NAME_INDEX
, make_unibyte_string (name
, len
));
845 len
= font_unparse_fcname (entity
, size
, name
, 256);
847 ASET (font_object
, FONT_FULLNAME_INDEX
, make_unibyte_string (name
, len
));
849 ASET (font_object
, FONT_FULLNAME_INDEX
,
850 AREF (font_object
, FONT_NAME_INDEX
));
852 && ! FcPatternGetString (pattern
, FC_FILE
, 0, &file
) != FcResultMatch
)
854 ASET (font_object
, FONT_FILE_INDEX
,
855 make_unibyte_string ((char *) file
, strlen ((char *) file
)));
856 ASET (font_object
, FONT_FORMAT_INDEX
, ftfont_font_format (pattern
));
857 font
= XFONT_OBJECT (font_object
);
858 ftfont_info
= (struct ftfont_info
*) font
;
859 ftfont_info
->ft_size
= ft_size
;
861 ftfont_info
->maybe_otf
= ft_face
->face_flags
& FT_FACE_FLAG_SFNT
;
862 ftfont_info
->otf
= NULL
;
863 #endif /* HAVE_LIBOTF */
864 font
->pixel_size
= size
;
865 font
->driver
= &ftfont_driver
;
866 font
->encoding_charset
= font
->repertory_charset
= -1;
868 upEM
= ft_face
->units_per_EM
;
869 if (! FcPatternGetBool (pattern
, FC_SCALABLE
, 0, &scalable
) == FcResultMatch
)
873 font
->ascent
= ft_face
->ascender
* size
/ upEM
;
874 font
->descent
= - ft_face
->descender
* size
/ upEM
;
875 font
->height
= ft_face
->height
* size
/ upEM
;
879 font
->ascent
= ft_face
->size
->metrics
.ascender
>> 6;
880 font
->descent
= - ft_face
->size
->metrics
.descender
>> 6;
881 font
->height
= ft_face
->size
->metrics
.height
>> 6;
883 if (FcPatternGetInteger (pattern
, FC_SPACING
, 0, &spacing
) != FcResultMatch
)
884 spacing
= FC_PROPORTIONAL
;
885 if (spacing
!= FC_PROPORTIONAL
)
886 font
->min_width
= font
->average_width
= font
->space_width
887 = (scalable
? ft_face
->max_advance_width
* size
/ upEM
888 : ft_face
->size
->metrics
.max_advance
>> 6);
893 font
->min_width
= font
->average_width
= font
->space_width
= 0;
894 for (i
= 32, n
= 0; i
< 127; i
++)
895 if (FT_Load_Char (ft_face
, i
, FT_LOAD_DEFAULT
) != 0)
897 int this_width
= ft_face
->glyph
->metrics
.horiAdvance
>> 6;
900 && (! font
->min_width
|| font
->min_width
> this_width
))
901 font
->min_width
= this_width
;
903 font
->space_width
= this_width
;
904 font
->average_width
+= this_width
;
908 font
->average_width
/= n
;
911 font
->baseline_offset
= 0;
912 font
->relative_compose
= 0;
913 font
->default_ascent
= 0;
914 font
->vertical_centering
= 0;
917 font
->underline_position
= -ft_face
->underline_position
* size
/ upEM
;
918 font
->underline_thickness
= -ft_face
->underline_thickness
* size
/ upEM
;
922 font
->underline_position
= -1;
923 font
->underline_thickness
= 0;
930 ftfont_close (f
, font
)
934 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
937 val
= assq_no_quit (QCfont_entity
, font
->props
[FONT_EXTRA_INDEX
]);
939 (XSAVE_VALUE (val
)->integer
)--;
940 if (XSAVE_VALUE (val
)->integer
== 0)
942 FT_Done_Face (ftfont_info
->ft_size
->face
);
944 if (ftfont_info
->otf
)
945 OTF_close (ftfont_info
->otf
);
949 FT_Done_Size (ftfont_info
->ft_size
);
953 ftfont_has_char (entity
, c
)
961 val
= assq_no_quit (QCfont_entity
, AREF (entity
, FONT_EXTRA_INDEX
));
963 pattern
= XSAVE_VALUE (val
)->pointer
;
964 if (FcPatternGetCharSet (pattern
, FC_CHARSET
, 0, &charset
) != FcResultMatch
)
966 return (FcCharSetHasChar (charset
, (FcChar32
) c
) == FcTrue
);
970 ftfont_encode_char (font
, c
)
974 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
975 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
976 FT_ULong charcode
= c
;
977 FT_UInt code
= FT_Get_Char_Index (ft_face
, charcode
);
979 return (code
> 0 ? code
: FONT_INVALID_CODE
);
983 ftfont_text_extents (font
, code
, nglyphs
, metrics
)
987 struct font_metrics
*metrics
;
989 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
990 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
994 if (ftfont_info
->ft_size
!= ft_face
->size
)
995 FT_Activate_Size (ftfont_info
->ft_size
);
997 bzero (metrics
, sizeof (struct font_metrics
));
998 for (i
= 0; i
< nglyphs
; i
++)
1000 if (FT_Load_Glyph (ft_face
, code
[i
], FT_LOAD_DEFAULT
) == 0)
1002 FT_Glyph_Metrics
*m
= &ft_face
->glyph
->metrics
;
1006 if (metrics
->lbearing
> width
+ (m
->horiBearingX
>> 6))
1007 metrics
->lbearing
= width
+ (m
->horiBearingX
>> 6);
1008 if (metrics
->rbearing
1009 < width
+ ((m
->horiBearingX
+ m
->width
) >> 6))
1011 = width
+ ((m
->horiBearingX
+ m
->width
) >> 6);
1012 if (metrics
->ascent
< (m
->horiBearingY
>> 6))
1013 metrics
->ascent
= m
->horiBearingY
>> 6;
1014 if (metrics
->descent
> ((m
->horiBearingY
+ m
->height
) >> 6))
1015 metrics
->descent
= (m
->horiBearingY
+ m
->height
) >> 6;
1017 width
+= m
->horiAdvance
>> 6;
1021 width
+= font
->space_width
;
1025 metrics
->width
= width
;
1031 ftfont_get_bitmap (font
, code
, bitmap
, bits_per_pixel
)
1034 struct font_bitmap
*bitmap
;
1037 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1038 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1039 FT_Int32 load_flags
= FT_LOAD_RENDER
;
1041 if (ftfont_info
->ft_size
!= ft_face
->size
)
1042 FT_Activate_Size (ftfont_info
->ft_size
);
1043 if (bits_per_pixel
== 1)
1045 #ifdef FT_LOAD_TARGET_MONO
1046 load_flags
|= FT_LOAD_TARGET_MONO
;
1048 load_flags
|= FT_LOAD_MONOCHROME
;
1051 else if (bits_per_pixel
!= 8)
1052 /* We don't support such a rendering. */
1055 if (FT_Load_Glyph (ft_face
, code
, load_flags
) != 0)
1057 bitmap
->bits_per_pixel
1058 = (ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_MONO
? 1
1059 : ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_GRAY
? 8
1060 : ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_LCD
? 8
1061 : ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_LCD_V
? 8
1063 if (bitmap
->bits_per_pixel
< 0)
1064 /* We don't suport that kind of pixel mode. */
1066 bitmap
->rows
= ft_face
->glyph
->bitmap
.rows
;
1067 bitmap
->width
= ft_face
->glyph
->bitmap
.width
;
1068 bitmap
->pitch
= ft_face
->glyph
->bitmap
.pitch
;
1069 bitmap
->buffer
= ft_face
->glyph
->bitmap
.buffer
;
1070 bitmap
->left
= ft_face
->glyph
->bitmap_left
;
1071 bitmap
->top
= ft_face
->glyph
->bitmap_top
;
1072 bitmap
->advance
= ft_face
->glyph
->metrics
.horiAdvance
>> 6;
1073 bitmap
->extra
= NULL
;
1079 ftfont_anchor_point (font
, code
, index
, x
, y
)
1085 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1086 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1088 if (ftfont_info
->ft_size
!= ft_face
->size
)
1089 FT_Activate_Size (ftfont_info
->ft_size
);
1090 if (FT_Load_Glyph (ft_face
, code
, FT_LOAD_DEFAULT
) != 0)
1092 if (ft_face
->glyph
->format
!= FT_GLYPH_FORMAT_OUTLINE
)
1094 if (index
>= ft_face
->glyph
->outline
.n_points
)
1096 *x
= ft_face
->glyph
->outline
.points
[index
].x
;
1097 *y
= ft_face
->glyph
->outline
.points
[index
].y
;
1102 #ifdef HAVE_M17N_FLT
1113 ftfont_get_glyph_id (font
, gstring
, from
, to
)
1115 MFLTGlyphString
*gstring
;
1118 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1119 FT_Face ft_face
= flt_font_ft
->ft_face
;
1122 for (g
= gstring
->glyphs
+ from
; from
< to
; g
++, from
++)
1125 FT_UInt code
= FT_Get_Char_Index (ft_face
, g
->code
);
1127 g
->code
= code
> 0 ? code
: FONT_INVALID_CODE
;
1134 ftfont_get_metrics (font
, gstring
, from
, to
)
1136 MFLTGlyphString
*gstring
;
1139 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1140 FT_Face ft_face
= flt_font_ft
->ft_face
;
1143 for (g
= gstring
->glyphs
+ from
; from
< to
; g
++, from
++)
1146 if (g
->code
!= FONT_INVALID_CODE
)
1148 FT_Glyph_Metrics
*m
;
1150 if (FT_Load_Glyph (ft_face
, g
->code
, FT_LOAD_DEFAULT
) != 0)
1152 m
= &ft_face
->glyph
->metrics
;
1154 g
->lbearing
= m
->horiBearingX
;
1155 g
->rbearing
= m
->horiBearingX
+ m
->width
;
1156 g
->ascent
= m
->horiBearingY
;
1157 g
->descent
= m
->height
- m
->horiBearingY
;
1158 g
->xadv
= m
->horiAdvance
;
1163 g
->rbearing
= g
->xadv
= flt_font_ft
->font
->space_width
<< 6;
1164 g
->ascent
= flt_font_ft
->font
->ascent
<< 6;
1165 g
->descent
= flt_font_ft
->font
->descent
<< 6;
1174 ftfont_check_otf (MFLTFont
*font
, MFLTOtfSpec
*spec
)
1176 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1177 OTF
*otf
= flt_font_ft
->otf
;
1181 for (i
= 0; i
< 2; i
++)
1183 if (! spec
->features
[i
])
1185 for (n
= 0; spec
->features
[i
][n
]; n
++);
1186 tags
= alloca (sizeof (OTF_Tag
) * n
);
1187 for (n
= 0, negative
= 0; spec
->features
[i
][n
]; n
++)
1189 if (spec
->features
[i
][n
] == 0xFFFFFFFF)
1192 tags
[n
- 1] = spec
->features
[i
][n
] | 0x80000000;
1194 tags
[n
] = spec
->features
[i
][n
];
1196 if (n
- negative
> 0
1197 && OTF_check_features (otf
, i
== 0, spec
->script
, spec
->langsys
,
1198 tags
, n
- negative
) != 1)
1204 #define DEVICE_DELTA(table, size) \
1205 (((size) >= (table).StartSize && (size) <= (table).EndSize) \
1206 ? (table).DeltaValue[(size) - (table).StartSize] << 6 \
1210 adjust_anchor (FT_Face ft_face
, OTF_Anchor
*anchor
,
1211 unsigned code
, int x_ppem
, int y_ppem
, int *x
, int *y
)
1213 if (anchor
->AnchorFormat
== 2)
1215 FT_Outline
*outline
;
1216 int ap
= anchor
->f
.f1
.AnchorPoint
;
1218 FT_Load_Glyph (ft_face
, (FT_UInt
) code
, FT_LOAD_MONOCHROME
);
1219 outline
= &ft_face
->glyph
->outline
;
1220 if (ap
< outline
->n_points
)
1222 *x
= outline
->points
[ap
].x
<< 6;
1223 *y
= outline
->points
[ap
].y
<< 6;
1226 else if (anchor
->AnchorFormat
== 3)
1228 if (anchor
->f
.f2
.XDeviceTable
.offset
)
1229 *x
+= DEVICE_DELTA (anchor
->f
.f2
.XDeviceTable
, x_ppem
);
1230 if (anchor
->f
.f2
.YDeviceTable
.offset
)
1231 *y
+= DEVICE_DELTA (anchor
->f
.f2
.YDeviceTable
, y_ppem
);
1235 static OTF_GlyphString otf_gstring
;
1238 ftfont_drive_otf (font
, spec
, in
, from
, to
, out
, adjustment
)
1241 MFLTGlyphString
*in
;
1243 MFLTGlyphString
*out
;
1244 MFLTGlyphAdjustment
*adjustment
;
1246 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1247 FT_Face ft_face
= flt_font_ft
->ft_face
;
1248 OTF
*otf
= flt_font_ft
->otf
;
1249 int len
= to
- from
;
1252 char script
[5], *langsys
= NULL
;
1253 char *gsub_features
= NULL
, *gpos_features
= NULL
;
1257 OTF_tag_name (spec
->script
, script
);
1260 langsys
= alloca (5);
1261 OTF_tag_name (spec
->langsys
, langsys
);
1263 for (i
= 0; i
< 2; i
++)
1267 if (spec
->features
[i
] && spec
->features
[i
][1] != 0xFFFFFFFF)
1269 for (j
= 0; spec
->features
[i
][j
]; j
++);
1271 p
= gsub_features
= alloca (6 * j
);
1273 p
= gpos_features
= alloca (6 * j
);
1274 for (j
= 0; spec
->features
[i
][j
]; j
++)
1276 if (spec
->features
[i
][j
] == 0xFFFFFFFF)
1277 *p
++ = '*', *p
++ = ',';
1280 OTF_tag_name (spec
->features
[i
][j
], p
);
1289 if (otf_gstring
.size
== 0)
1291 otf_gstring
.glyphs
= (OTF_Glyph
*) malloc (sizeof (OTF_Glyph
) * len
);
1292 otf_gstring
.size
= len
;
1294 else if (otf_gstring
.size
< len
)
1296 otf_gstring
.glyphs
= (OTF_Glyph
*) realloc (otf_gstring
.glyphs
,
1297 sizeof (OTF_Glyph
) * len
);
1298 otf_gstring
.size
= len
;
1300 otf_gstring
.used
= len
;
1301 memset (otf_gstring
.glyphs
, 0, sizeof (OTF_Glyph
) * len
);
1302 for (i
= 0; i
< len
; i
++)
1304 otf_gstring
.glyphs
[i
].c
= in
->glyphs
[from
+ i
].c
;
1305 otf_gstring
.glyphs
[i
].glyph_id
= in
->glyphs
[from
+ i
].code
;
1308 OTF_drive_gdef (otf
, &otf_gstring
);
1313 if (OTF_drive_gsub (otf
, &otf_gstring
, script
, langsys
, gsub_features
)
1316 if (out
->allocated
< out
->used
+ otf_gstring
.used
)
1318 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
; )
1322 int min_from
, max_to
;
1325 g
= out
->glyphs
+ out
->used
;
1326 *g
= in
->glyphs
[from
+ otfg
->f
.index
.from
];
1327 if (g
->code
!= otfg
->glyph_id
)
1330 g
->code
= otfg
->glyph_id
;
1336 if (otfg
->f
.index
.from
< otfg
->f
.index
.to
)
1338 /* OTFG substitutes multiple glyphs in IN. */
1339 for (j
= from
+ otfg
->f
.index
.from
+ 1;
1340 j
<= from
+ otfg
->f
.index
.to
; j
++)
1342 if (min_from
> in
->glyphs
[j
].from
)
1343 min_from
= in
->glyphs
[j
].from
;
1344 if (max_to
< in
->glyphs
[j
].to
)
1345 max_to
= in
->glyphs
[j
].to
;
1350 for (i
++, otfg
++; (i
< otf_gstring
.used
1351 && otfg
->f
.index
.from
== otfg
[-1].f
.index
.from
);
1354 g
= out
->glyphs
+ out
->used
;
1355 *g
= in
->glyphs
[from
+ otfg
->f
.index
.to
];
1356 if (g
->code
!= otfg
->glyph_id
)
1359 g
->code
= otfg
->glyph_id
;
1368 if (out
->allocated
< out
->used
+ len
)
1370 for (i
= 0; i
< len
; i
++)
1371 out
->glyphs
[out
->used
++] = in
->glyphs
[from
+ i
];
1376 MFLTGlyph
*base
= NULL
, *mark
= NULL
, *g
;
1377 int x_ppem
, y_ppem
, x_scale
, y_scale
;
1379 if (OTF_drive_gpos (otf
, &otf_gstring
, script
, langsys
, gpos_features
)
1383 x_ppem
= ft_face
->size
->metrics
.x_ppem
;
1384 y_ppem
= ft_face
->size
->metrics
.y_ppem
;
1385 x_scale
= ft_face
->size
->metrics
.x_scale
;
1386 y_scale
= ft_face
->size
->metrics
.y_scale
;
1388 for (i
= 0, otfg
= otf_gstring
.glyphs
, g
= out
->glyphs
+ gidx
;
1389 i
< otf_gstring
.used
; i
++, otfg
++, g
++)
1393 if (! otfg
->glyph_id
)
1395 switch (otfg
->positioning_type
)
1399 case 1: /* Single */
1402 int format
= otfg
->f
.f1
.format
;
1404 if (format
& OTF_XPlacement
)
1406 = otfg
->f
.f1
.value
->XPlacement
* x_scale
/ 0x10000;
1407 if (format
& OTF_XPlaDevice
)
1409 += DEVICE_DELTA (otfg
->f
.f1
.value
->XPlaDevice
, x_ppem
);
1410 if (format
& OTF_YPlacement
)
1412 = - (otfg
->f
.f1
.value
->YPlacement
* y_scale
/ 0x10000);
1413 if (format
& OTF_YPlaDevice
)
1415 -= DEVICE_DELTA (otfg
->f
.f1
.value
->YPlaDevice
, y_ppem
);
1416 if (format
& OTF_XAdvance
)
1418 += otfg
->f
.f1
.value
->XAdvance
* x_scale
/ 0x10000;
1419 if (format
& OTF_XAdvDevice
)
1421 += DEVICE_DELTA (otfg
->f
.f1
.value
->XAdvDevice
, x_ppem
);
1422 if (format
& OTF_YAdvance
)
1424 += otfg
->f
.f1
.value
->YAdvance
* y_scale
/ 0x10000;
1425 if (format
& OTF_YAdvDevice
)
1427 += DEVICE_DELTA (otfg
->f
.f1
.value
->YAdvDevice
, y_ppem
);
1428 adjustment
[i
].set
= 1;
1431 case 3: /* Cursive */
1432 /* Not yet supported. */
1434 case 4: /* Mark-to-Base */
1435 case 5: /* Mark-to-Ligature */
1439 goto label_adjust_anchor
;
1440 default: /* i.e. case 6 Mark-to-Mark */
1445 label_adjust_anchor
:
1447 int base_x
, base_y
, mark_x
, mark_y
;
1448 int this_from
, this_to
;
1450 base_x
= otfg
->f
.f4
.base_anchor
->XCoordinate
* x_scale
/ 0x10000;
1451 base_y
= otfg
->f
.f4
.base_anchor
->YCoordinate
* y_scale
/ 0x10000;
1452 mark_x
= otfg
->f
.f4
.mark_anchor
->XCoordinate
* x_scale
/ 0x10000;
1453 mark_y
= otfg
->f
.f4
.mark_anchor
->YCoordinate
* y_scale
/ 0x10000;;
1455 if (otfg
->f
.f4
.base_anchor
->AnchorFormat
!= 1)
1456 adjust_anchor (ft_face
, otfg
->f
.f4
.base_anchor
,
1457 prev
->code
, x_ppem
, y_ppem
, &base_x
, &base_y
);
1458 if (otfg
->f
.f4
.mark_anchor
->AnchorFormat
!= 1)
1459 adjust_anchor (ft_face
, otfg
->f
.f4
.mark_anchor
, g
->code
,
1460 x_ppem
, y_ppem
, &mark_x
, &mark_y
);
1461 adjustment
[i
].xoff
= (base_x
- mark_x
);
1462 adjustment
[i
].yoff
= - (base_y
- mark_y
);
1463 adjustment
[i
].back
= (g
- prev
);
1464 adjustment
[i
].xadv
= 0;
1465 adjustment
[i
].advance_is_absolute
= 1;
1466 adjustment
[i
].set
= 1;
1467 this_from
= g
->from
;
1469 for (j
= 0; prev
+ j
< g
; j
++)
1471 if (this_from
> prev
[j
].from
)
1472 this_from
= prev
[j
].from
;
1473 if (this_to
< prev
[j
].to
)
1474 this_to
= prev
[j
].to
;
1476 for (; prev
<= g
; prev
++)
1478 prev
->from
= this_from
;
1483 if (otfg
->GlyphClass
== OTF_GlyphClass0
)
1485 else if (otfg
->GlyphClass
== OTF_GlyphClassMark
)
1494 if (out
->allocated
< out
->used
+ len
)
1496 font
->get_metrics (font
, in
, from
, to
);
1497 memcpy (out
->glyphs
+ out
->used
, in
->glyphs
+ from
,
1498 sizeof (MFLTGlyph
) * len
);
1503 static MFLTGlyphString gstring
;
1505 static int m17n_flt_initialized
;
1507 extern Lisp_Object QCfamily
;
1510 ftfont_shape_by_flt (lgstring
, font
, ft_face
, otf
)
1511 Lisp_Object lgstring
;
1516 EMACS_UINT len
= LGSTRING_LENGTH (lgstring
);
1518 struct MFLTFontFT flt_font_ft
;
1520 if (! m17n_flt_initialized
)
1523 m17n_flt_initialized
= 1;
1526 for (i
= 0; i
< len
; i
++)
1527 if (NILP (LGSTRING_GLYPH (lgstring
, i
)))
1531 if (gstring
.allocated
== 0)
1533 gstring
.allocated
= len
* 2;
1534 gstring
.glyph_size
= sizeof (MFLTGlyph
);
1535 gstring
.glyphs
= malloc (sizeof (MFLTGlyph
) * gstring
.allocated
);
1537 else if (gstring
.allocated
< len
* 2)
1539 gstring
.allocated
= len
* 2;
1540 gstring
.glyphs
= realloc (gstring
.glyphs
,
1541 sizeof (MFLTGlyph
) * gstring
.allocated
);
1543 for (i
= 0; i
< len
; i
++)
1544 gstring
.glyphs
[i
].c
= LGLYPH_CHAR (LGSTRING_GLYPH (lgstring
, i
));
1549 Lisp_Object family
= Ffont_get (LGSTRING_FONT (lgstring
), QCfamily
);
1552 flt_font_ft
.flt_font
.family
= Mnil
;
1554 flt_font_ft
.flt_font
.family
= msymbol (SDATA (SYMBOL_NAME (family
)));
1556 flt_font_ft
.flt_font
.x_ppem
= ft_face
->size
->metrics
.x_ppem
;
1557 flt_font_ft
.flt_font
.y_ppem
= ft_face
->size
->metrics
.y_ppem
;
1558 flt_font_ft
.flt_font
.get_glyph_id
= ftfont_get_glyph_id
;
1559 flt_font_ft
.flt_font
.get_metrics
= ftfont_get_metrics
;
1560 flt_font_ft
.flt_font
.check_otf
= ftfont_check_otf
;
1561 flt_font_ft
.flt_font
.drive_otf
= ftfont_drive_otf
;
1562 flt_font_ft
.flt_font
.internal
= NULL
;
1563 flt_font_ft
.font
= font
;
1564 flt_font_ft
.ft_face
= ft_face
;
1565 flt_font_ft
.otf
= otf
;
1566 for (i
= 0; i
< 3; i
++)
1568 int result
= mflt_run (&gstring
, 0, len
, &flt_font_ft
.flt_font
, NULL
);
1571 gstring
.allocated
+= gstring
.allocated
;
1572 gstring
.glyphs
= realloc (gstring
.glyphs
,
1573 sizeof (MFLTGlyph
) * gstring
.allocated
);
1575 if (gstring
.used
> LGSTRING_LENGTH (lgstring
))
1577 for (i
= 0; i
< gstring
.used
; i
++)
1579 MFLTGlyph
*g
= gstring
.glyphs
+ i
;
1581 g
->from
= LGLYPH_FROM (LGSTRING_GLYPH (lgstring
, g
->from
));
1582 g
->to
= LGLYPH_TO (LGSTRING_GLYPH (lgstring
, g
->to
));
1585 for (i
= 0; i
< gstring
.used
; i
++)
1587 Lisp_Object lglyph
= LGSTRING_GLYPH (lgstring
, i
);
1588 MFLTGlyph
*g
= gstring
.glyphs
+ i
;
1592 lglyph
= Fmake_vector (make_number (LGLYPH_SIZE
), Qnil
);
1593 LGSTRING_SET_GLYPH (lgstring
, i
, lglyph
);
1595 LGLYPH_SET_FROM (lglyph
, g
->from
);
1596 LGLYPH_SET_TO (lglyph
, g
->to
);
1597 LGLYPH_SET_CHAR (lglyph
, g
->c
);
1598 LGLYPH_SET_CODE (lglyph
, g
->code
);
1599 LGLYPH_SET_WIDTH (lglyph
, g
->xadv
>> 6);
1600 LGLYPH_SET_LBEARING (lglyph
, g
->lbearing
>> 6);
1601 LGLYPH_SET_RBEARING (lglyph
, g
->rbearing
>> 6);
1602 LGLYPH_SET_ASCENT (lglyph
, g
->ascent
>> 6);
1603 LGLYPH_SET_DESCENT (lglyph
, g
->descent
>> 6);
1608 vec
= Fmake_vector (make_number (3), Qnil
);
1609 ASET (vec
, 0, make_number (g
->xoff
>> 6));
1610 ASET (vec
, 1, make_number (g
->yoff
>> 6));
1611 ASET (vec
, 2, make_number (g
->xadv
>> 6));
1612 LGLYPH_SET_ADJUSTMENT (lglyph
, vec
);
1615 return make_number (i
);
1619 ftfont_shape (lgstring
)
1620 Lisp_Object lgstring
;
1623 struct ftfont_info
*ftfont_info
;
1625 CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring
), font
);
1626 ftfont_info
= (struct ftfont_info
*) font
;
1627 if (! ftfont_info
->maybe_otf
)
1628 return make_number (0);
1629 if (! ftfont_info
->otf
)
1631 OTF
*otf
= OTF_open_ft_face (ftfont_info
->ft_size
->face
);
1633 if (! otf
|| OTF_get_table (otf
, "head") < 0)
1637 ftfont_info
->maybe_otf
= 0;
1638 return make_number (0);
1641 ftfont_info
->otf
= otf
;
1644 return ftfont_shape_by_flt (lgstring
, font
, ftfont_info
->ft_size
->face
,
1648 #endif /* HAVE_M17N_FLT */
1649 #endif /* HAVE_LIBOTF */
1652 ftfont_font_format (FcPattern
*pattern
)
1656 #ifdef FC_FONTFORMAT
1657 if (FcPatternGetString (pattern
, FC_FONTFORMAT
, 0, &str
) != FcResultMatch
)
1659 if (strcmp ((char *) str
, "TrueType") == 0)
1660 return intern ("truetype");
1661 if (strcmp ((char *) str
, "Type 1") == 0)
1662 return intern ("type1");
1663 if (strcmp ((char *) str
, "PCF") == 0)
1664 return intern ("pcf");
1665 if (strcmp ((char *) str
, "BDF") == 0)
1666 return intern ("bdf");
1667 #else /* not FC_FONTFORMAT */
1668 if (FcPatternGetString (pattern
, FC_FILE
, 0, &str
) != FcResultMatch
)
1670 if (strcasestr ((char *) str
, ".ttf") == 0)
1671 return intern ("truetype");
1672 if (strcasestr ((char *) str
, "pfb") == 0)
1673 return intern ("type1");
1674 if (strcasestr ((char *) str
, "pcf") == 0)
1675 return intern ("pcf");
1676 if (strcasestr ((char *) str
, "bdf") == 0)
1677 return intern ("bdf");
1678 #endif /* not FC_FONTFORMAT */
1679 return intern ("unknown");
1686 DEFSYM (Qfreetype
, "freetype");
1687 DEFSYM (Qmonospace
, "monospace");
1688 DEFSYM (Qsans_serif
, "sans-serif");
1689 DEFSYM (Qserif
, "serif");
1690 DEFSYM (Qmono
, "mono");
1691 DEFSYM (Qsans
, "sans");
1692 DEFSYM (Qsans__serif
, "sans serif");
1694 staticpro (&freetype_font_cache
);
1695 freetype_font_cache
= Fcons (Qt
, Qnil
);
1697 staticpro (&ftfont_generic_family_list
);
1698 ftfont_generic_family_list
1699 = Fcons (Fcons (Qmonospace
, Qt
),
1700 Fcons (Fcons (Qsans_serif
, Qt
),
1701 Fcons (Fcons (Qsans
, Qt
), Qnil
)));
1703 ftfont_driver
.type
= Qfreetype
;
1704 register_font_driver (&ftfont_driver
, NULL
);
1707 /* arch-tag: 7cfa432c-33a6-4988-83d2-a82ed8604aca
1708 (do not change this comment) */