root/src/ftfont.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. matching_prefix
  2. get_adstyle_property
  3. ftfont_pattern_entity
  4. ftfont_resolve_generic_family
  5. ftfont_lookup_cache
  6. ftfont_get_fc_charset
  7. ftfont_get_otf
  8. ftfont_get_cache
  9. ftfont_get_charset
  10. ftfont_get_open_type_spec
  11. xft_color_font_whitelisted_p
  12. ftfont_spec_pattern
  13. ftfont_list
  14. ftfont_list2
  15. ftfont_match
  16. ftfont_match2
  17. ftfont_list_family
  18. ftfont_fix_match
  19. ftfont_add_rendering_parameters
  20. ftfont_entity_pattern
  21. ftfont_open
  22. ftfont_close
  23. ftfont_has_char
  24. ftfont_encode_char
  25. ftfont_glyph_metrics
  26. ftfont_text_extents
  27. ftfont_get_bitmap
  28. ftfont_anchor_point
  29. ftfont_otf_features
  30. ftfont_otf_capability
  31. ftfont_get_glyph_id
  32. ftfont_get_metrics
  33. ftfont_check_otf
  34. adjust_anchor
  35. setup_otf_gstring
  36. ftfont_drive_otf
  37. ftfont_try_otf
  38. ftfont_drive_otf
  39. ftfont_shape_by_flt
  40. ftfont_shape
  41. ftfont_variation_glyphs
  42. fthbfont_begin_hb_font
  43. hbotf_open
  44. hbotf_check_features
  45. ftfont_filter_properties
  46. ftfont_combining_capability
  47. syms_of_ftfont
  48. syms_of_ftfont_for_pdumper

     1 /* ftfont.c -- FreeType font driver.
     2    Copyright (C) 2006-2023 Free Software Foundation, Inc.
     3    Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011
     4      National Institute of Advanced Industrial Science and Technology (AIST)
     5      Registration Number H13PRO009
     6 
     7 This file is part of GNU Emacs.
     8 
     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 of the License, or (at
    12 your option) any later version.
    13 
    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.
    18 
    19 You should have received a copy of the GNU General Public License
    20 along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
    21 
    22 #include <config.h>
    23 #include <fontconfig/fontconfig.h>
    24 #include <fontconfig/fcfreetype.h>
    25 
    26 /* These two blocks are here because this file is built when using XFT
    27    and when using Cairo, so struct font_info in ftfont.h needs access
    28    to the appropriate types.  */
    29 #ifdef HAVE_XFT
    30 # include <X11/Xlib.h>
    31 # include <X11/Xft/Xft.h>
    32 #endif
    33 #ifdef USE_CAIRO
    34 # include <cairo-ft.h>
    35 #endif
    36 
    37 #include <c-strcase.h>
    38 
    39 #include "lisp.h"
    40 #include "dispextern.h"
    41 #include "character.h"
    42 #include "charset.h"
    43 #include "category.h"
    44 #include "composite.h"
    45 #include "font.h"
    46 #include "ftfont.h"
    47 #include "pdumper.h"
    48 
    49 static struct font_driver const ftfont_driver;
    50 #ifdef HAVE_HARFBUZZ
    51 static struct font_driver fthbfont_driver;
    52 #endif  /* HAVE_HARFBUZZ */
    53 
    54 /* Flag to tell if FcInit is already called or not.  */
    55 static bool fc_initialized;
    56 
    57 /* Handle to a FreeType library instance.  */
    58 static FT_Library ft_library;
    59 
    60 /* Cache for FreeType fonts.  */
    61 static Lisp_Object freetype_font_cache;
    62 
    63 /* Cache for FT_Face and FcCharSet. */
    64 static Lisp_Object ft_face_cache;
    65 
    66 enum ftfont_cache_for
    67   {
    68     FTFONT_CACHE_FOR_FACE,
    69     FTFONT_CACHE_FOR_CHARSET,
    70     FTFONT_CACHE_FOR_ENTITY
    71   };
    72 
    73 static Lisp_Object ftfont_lookup_cache (Lisp_Object,
    74                                         enum ftfont_cache_for);
    75 
    76 #define SYMBOL_FcChar8(SYM) (FcChar8 *) SDATA (SYMBOL_NAME (SYM))
    77 
    78 static struct
    79 {
    80   /* registry name */
    81   const char *name;
    82   /* characters to distinguish the charset from the others */
    83   int uniquifier[6];
    84   /* additional constraint by language */
    85   const char *lang;
    86   /* set on demand */
    87   FcCharSet *fc_charset;
    88 } fc_charset_table[] =
    89   { { "iso8859-1", { 0x00A0, 0x00A1, 0x00B4, 0x00BC, 0x00D0 } },
    90     { "iso8859-2", { 0x00A0, 0x010E }},
    91     { "iso8859-3", { 0x00A0, 0x0108 }},
    92     { "iso8859-4", { 0x00A0, 0x00AF, 0x0128, 0x0156, 0x02C7 }},
    93     { "iso8859-5", { 0x00A0, 0x0401 }},
    94     { "iso8859-6", { 0x00A0, 0x060C }},
    95     { "iso8859-7", { 0x00A0, 0x0384 }},
    96     { "iso8859-8", { 0x00A0, 0x05D0 }},
    97     { "iso8859-9", { 0x00A0, 0x00A1, 0x00BC, 0x011E }},
    98     { "iso8859-10", { 0x00A0, 0x00D0, 0x0128, 0x2015 }},
    99     { "iso8859-11", { 0x00A0, 0x0E01 }},
   100     { "iso8859-13", { 0x00A0, 0x201C }},
   101     { "iso8859-14", { 0x00A0, 0x0174 }},
   102     { "iso8859-15", { 0x00A0, 0x00A1, 0x00D0, 0x0152 }},
   103     { "iso8859-16", { 0x00A0, 0x0218}},
   104     { "gb2312.1980-0", { 0x4E13 }, "zh-cn"},
   105     { "big5-0", { 0x9C21 }, "zh-tw" },
   106     { "jisx0208.1983-0", { 0x4E55 }, "ja"},
   107     { "ksc5601.1985-0", { 0xAC00 }, "ko"},
   108     { "cns11643.1992-1", { 0xFE32 }, "zh-tw"},
   109     { "cns11643.1992-2", { 0x4E33, 0x7934 }},
   110     { "cns11643.1992-3", { 0x201A9 }},
   111     { "cns11643.1992-4", { 0x20057 }},
   112     { "cns11643.1992-5", { 0x20000 }},
   113     { "cns11643.1992-6", { 0x20003 }},
   114     { "cns11643.1992-7", { 0x20055 }},
   115     { "gbk-0", { 0x4E06 }, "zh-cn"},
   116     { "jisx0212.1990-0", { 0x4E44 }},
   117     { "jisx0213.2000-1", { 0xFA10 }, "ja"},
   118     { "jisx0213.2000-2", { 0xFA49 }},
   119     { "jisx0213.2004-1", { 0x20B9F }},
   120     { "viscii1.1-1", { 0x1EA0, 0x1EAE, 0x1ED2 }, "vi"},
   121     { "tis620.2529-1", { 0x0E01 }, "th"},
   122     { "microsoft-cp1251", { 0x0401, 0x0490 }, "ru"},
   123     { "koi8-r", { 0x0401, 0x2219 }, "ru"},
   124     { "mulelao-1", { 0x0E81 }, "lo"},
   125     { "unicode-sip", { 0x20000 }},
   126     { NULL }
   127   };
   128 
   129 static bool
   130 matching_prefix (char const *str, ptrdiff_t len, char const *pat)
   131 {
   132   return len == strlen (pat) && c_strncasecmp (str, pat, len) == 0;
   133 }
   134 
   135 /* Dirty hack for handing ADSTYLE property.
   136 
   137    Fontconfig (actually the underlying FreeType) gives such ADSTYLE
   138    font property of PCF/BDF fonts in FC_STYLE.  And, "Bold",
   139    "Oblique", "Italic", or any non-normal SWIDTH property names
   140    (e.g. SemiCondensed) are appended.  In addition, if there's no
   141    ADSTYLE property nor non-normal WEIGHT/SLANT/SWIDTH properties,
   142    "Regular" is used for FC_STYLE (see the function
   143    pcf_interpret_style in src/pcf/pcfread.c of FreeType).
   144 
   145    Unfortunately this behavior is not documented, so the following
   146    code may fail if FreeType changes the behavior in the future.  */
   147 
   148 static Lisp_Object
   149 get_adstyle_property (FcPattern *p)
   150 {
   151   FcChar8 *fcstr;
   152   char *str, *end;
   153   Lisp_Object adstyle;
   154 
   155 #ifdef FC_FONTFORMAT
   156   if ((FcPatternGetString (p, FC_FONTFORMAT, 0, &fcstr) == FcResultMatch)
   157       && xstrcasecmp ((char *) fcstr, "bdf") != 0
   158       && xstrcasecmp ((char *) fcstr, "pcf") != 0)
   159     /* Not a BDF nor PCF font.  */
   160     return Qnil;
   161 #endif
   162   if (FcPatternGetString (p, FC_STYLE, 0, &fcstr) != FcResultMatch)
   163     return Qnil;
   164   str = (char *) fcstr;
   165   for (end = str; *end && *end != ' '; end++);
   166   if (matching_prefix (str, end - str, "Regular")
   167       || matching_prefix (str, end - str, "Bold")
   168       || matching_prefix (str, end - str, "Oblique")
   169       || matching_prefix (str, end - str, "Italic"))
   170     return Qnil;
   171   adstyle = font_intern_prop (str, end - str, 1);
   172   if (font_style_to_value (FONT_WIDTH_INDEX, adstyle, 0) >= 0)
   173     return Qnil;
   174   return adstyle;
   175 }
   176 
   177 static Lisp_Object
   178 ftfont_pattern_entity (FcPattern *p, Lisp_Object extra)
   179 {
   180   Lisp_Object key, cache, entity;
   181   FcChar8 *str;
   182   char *file;
   183   int idx;
   184   int numeric;
   185   double dbl;
   186   FcBool b;
   187 
   188   if (FcPatternGetString (p, FC_FILE, 0, &str) != FcResultMatch)
   189     return Qnil;
   190   if (FcPatternGetInteger (p, FC_INDEX, 0, &idx) != FcResultMatch)
   191     return Qnil;
   192 #ifdef FC_VARIABLE
   193   /* This is a virtual/meta FcPattern for a variable weight font, from
   194      which it is possible to extract an FcRange value specifying the
   195      minimum and maximum weights available in this file.  We don't
   196      need to know that information explicitly, so skip it.  We will be
   197      called with an FcPattern for each actually available, non-virtual
   198      weight.
   199 
   200      Fontconfig started generating virtual/meta patterns for variable
   201      weight fonts in the same release that FC_VARIABLE was added, so
   202      we conditionalize on that constant.  This also ensures that
   203      FcPatternGetRange is available.  */
   204   FcRange *range;
   205   if (FcPatternGetRange (p, FC_WEIGHT, 0, &range) == FcResultMatch
   206       && FcPatternGetBool (p, FC_VARIABLE, 0, &b) == FcResultMatch
   207       && b == FcTrue)
   208     return Qnil;
   209 #endif  /* FC_VARIABLE */
   210 
   211   file = (char *) str;
   212   key = Fcons (build_unibyte_string (file), make_fixnum (idx));
   213   cache = ftfont_lookup_cache (key, FTFONT_CACHE_FOR_ENTITY);
   214   entity = XCAR (cache);
   215   if (! NILP (entity))
   216     {
   217       Lisp_Object val = font_make_entity ();
   218       int i;
   219 
   220       for (i = 0; i < FONT_OBJLIST_INDEX; i++)
   221         ASET (val, i, AREF (entity, i));
   222 
   223       ASET (val, FONT_EXTRA_INDEX, Fcopy_sequence (extra));
   224       font_put_extra (val, QCfont_entity, key);
   225 
   226       return val;
   227     }
   228   entity = font_make_entity ();
   229   XSETCAR (cache, entity);
   230 
   231   ASET (entity, FONT_TYPE_INDEX, Qfreetype);
   232   ASET (entity, FONT_REGISTRY_INDEX, Qiso10646_1);
   233 
   234   if (FcPatternGetString (p, FC_FOUNDRY, 0, &str) == FcResultMatch)
   235     {
   236       char *s = (char *) str;
   237       ASET (entity, FONT_FOUNDRY_INDEX, font_intern_prop (s, strlen (s), 1));
   238     }
   239   if (FcPatternGetString (p, FC_FAMILY, 0, &str) == FcResultMatch)
   240     {
   241       char *s = (char *) str;
   242       ASET (entity, FONT_FAMILY_INDEX, font_intern_prop (s, strlen (s), 1));
   243     }
   244   if (FcPatternGetInteger (p, FC_WEIGHT, 0, &numeric) == FcResultMatch)
   245     {
   246       FONT_SET_STYLE (entity, FONT_WEIGHT_INDEX, make_fixnum (numeric));
   247     }
   248   if (FcPatternGetInteger (p, FC_SLANT, 0, &numeric) == FcResultMatch)
   249     {
   250       numeric += 100;
   251       FONT_SET_STYLE (entity, FONT_SLANT_INDEX, make_fixnum (numeric));
   252     }
   253   if (FcPatternGetInteger (p, FC_WIDTH, 0, &numeric) == FcResultMatch)
   254     {
   255       FONT_SET_STYLE (entity, FONT_WIDTH_INDEX, make_fixnum (numeric));
   256     }
   257   if (FcPatternGetDouble (p, FC_PIXEL_SIZE, 0, &dbl) == FcResultMatch)
   258     {
   259       ASET (entity, FONT_SIZE_INDEX, make_fixnum (dbl));
   260     }
   261   else
   262     ASET (entity, FONT_SIZE_INDEX, make_fixnum (0));
   263   if (FcPatternGetInteger (p, FC_SPACING, 0, &numeric) == FcResultMatch)
   264     ASET (entity, FONT_SPACING_INDEX, make_fixnum (numeric));
   265   if (FcPatternGetDouble (p, FC_DPI, 0, &dbl) == FcResultMatch)
   266     {
   267       int dpi = dbl;
   268       ASET (entity, FONT_DPI_INDEX, make_fixnum (dpi));
   269     }
   270   if (FcPatternGetBool (p, FC_SCALABLE, 0, &b) == FcResultMatch
   271       && b == FcTrue)
   272     {
   273       ASET (entity, FONT_SIZE_INDEX, make_fixnum (0));
   274       ASET (entity, FONT_AVGWIDTH_INDEX, make_fixnum (0));
   275     }
   276   else
   277     {
   278       /* As this font is not scalable, perhaps this is a BDF or PCF
   279          font. */
   280       FT_Face ft_face;
   281 
   282       ASET (entity, FONT_ADSTYLE_INDEX, get_adstyle_property (p));
   283       if ((ft_library || FT_Init_FreeType (&ft_library) == 0)
   284           && FT_New_Face (ft_library, file, idx, &ft_face) == 0)
   285         {
   286           BDF_PropertyRec rec;
   287 
   288           if (FT_Get_BDF_Property (ft_face, "AVERAGE_WIDTH", &rec) == 0
   289               && rec.type == BDF_PROPERTY_TYPE_INTEGER)
   290             ASET (entity, FONT_AVGWIDTH_INDEX, make_fixnum (rec.u.integer));
   291           FT_Done_Face (ft_face);
   292         }
   293     }
   294 
   295   ASET (entity, FONT_EXTRA_INDEX, Fcopy_sequence (extra));
   296   font_put_extra (entity, QCfont_entity, key);
   297   return entity;
   298 }
   299 
   300 
   301 static Lisp_Object ftfont_generic_family_list;
   302 
   303 static Lisp_Object
   304 ftfont_resolve_generic_family (Lisp_Object family, FcPattern *pattern)
   305 {
   306   Lisp_Object slot;
   307   FcPattern *match;
   308   FcResult result;
   309   FcLangSet *langset;
   310 
   311   family = Fintern (Fdowncase (SYMBOL_NAME (family)), Qnil);
   312   if (EQ (family, Qmono))
   313     family = Qmonospace;
   314   else if (EQ (family, Qsans) || EQ (family, Qsans__serif))
   315     family = Qsans_serif;
   316   slot = assq_no_quit (family, ftfont_generic_family_list);
   317   if (! CONSP (slot))
   318     return Qnil;
   319   if (! EQ (XCDR (slot), Qt))
   320     return XCDR (slot);
   321   pattern = FcPatternDuplicate (pattern);
   322   if (! pattern)
   323     goto err;
   324   FcPatternDel (pattern, FC_FOUNDRY);
   325   FcPatternDel (pattern, FC_FAMILY);
   326   FcPatternAddString (pattern, FC_FAMILY, SYMBOL_FcChar8 (family));
   327   if (FcPatternGetLangSet (pattern, FC_LANG, 0, &langset) != FcResultMatch)
   328     {
   329       /* This is to avoid the effect of locale.  */
   330       static const FcChar8 lang[] = "en";
   331       langset = FcLangSetCreate ();
   332       FcLangSetAdd (langset, lang);
   333       FcPatternAddLangSet (pattern, FC_LANG, langset);
   334       FcLangSetDestroy (langset);
   335     }
   336   FcConfigSubstitute (NULL, pattern, FcMatchPattern);
   337   FcDefaultSubstitute (pattern);
   338   match = FcFontMatch (NULL, pattern, &result);
   339   if (match)
   340     {
   341       FcChar8 *fam;
   342 
   343       if (FcPatternGetString (match, FC_FAMILY, 0, &fam) == FcResultMatch)
   344         family = intern ((char *) fam);
   345     }
   346   else
   347     family = Qnil;
   348   XSETCDR (slot, family);
   349   if (match) FcPatternDestroy (match);
   350  err:
   351   if (pattern) FcPatternDestroy (pattern);
   352   return family;
   353 }
   354 
   355 struct ftfont_cache_data
   356 {
   357   FT_Face ft_face;
   358   FcCharSet *fc_charset;
   359   intptr_t face_refcount;
   360 };
   361 
   362 static Lisp_Object
   363 ftfont_lookup_cache (Lisp_Object key, enum ftfont_cache_for cache_for)
   364 {
   365   Lisp_Object cache, val;
   366   struct ftfont_cache_data *cache_data;
   367 
   368   if (FONT_ENTITY_P (key))
   369     {
   370       val = assq_no_quit (QCfont_entity, AREF (key, FONT_EXTRA_INDEX));
   371       eassert (CONSP (val));
   372       key = XCDR (val);
   373     }
   374 
   375   if (NILP (ft_face_cache))
   376     cache = Qnil;
   377   else
   378     cache = Fgethash (key, ft_face_cache, Qnil);
   379   if (NILP (cache))
   380     {
   381       if (NILP (ft_face_cache))
   382         ft_face_cache = CALLN (Fmake_hash_table, QCtest, Qequal);
   383       cache_data = xzalloc (sizeof *cache_data);
   384       val = make_mint_ptr (cache_data);
   385       cache = Fcons (Qnil, val);
   386       Fputhash (key, cache, ft_face_cache);
   387     }
   388   else
   389     {
   390       val = XCDR (cache);
   391       cache_data = xmint_pointer (val);
   392     }
   393 
   394   if (cache_for == FTFONT_CACHE_FOR_ENTITY)
   395     return cache;
   396 
   397   if (cache_for == FTFONT_CACHE_FOR_FACE
   398       ? ! cache_data->ft_face : ! cache_data->fc_charset)
   399     {
   400       char *filename = SSDATA (XCAR (key));
   401       int idx = XFIXNUM (XCDR (key));
   402 
   403       if (cache_for == FTFONT_CACHE_FOR_FACE)
   404         {
   405           if (! ft_library
   406               && FT_Init_FreeType (&ft_library) != 0)
   407             return Qnil;
   408           if (FT_New_Face (ft_library, filename, idx, &cache_data->ft_face)
   409               != 0)
   410             return Qnil;
   411         }
   412       else
   413         {
   414           FcPattern *pat = NULL;
   415           FcFontSet *fontset = NULL;
   416           FcObjectSet *objset = NULL;
   417           FcCharSet *charset = NULL;
   418 
   419           pat = FcPatternBuild (0, FC_FILE, FcTypeString, (FcChar8 *) filename,
   420                                 FC_INDEX, FcTypeInteger, idx, NULL);
   421           if (! pat)
   422             goto finish;
   423           objset = FcObjectSetBuild (FC_CHARSET, FC_STYLE, NULL);
   424           if (! objset)
   425             goto finish;
   426           fontset = FcFontList (NULL, pat, objset);
   427           if (! fontset)
   428             goto finish;
   429           if (fontset && fontset->nfont > 0
   430               && (FcPatternGetCharSet (fontset->fonts[0], FC_CHARSET, 0,
   431                                        &charset)
   432                   == FcResultMatch))
   433             cache_data->fc_charset = FcCharSetCopy (charset);
   434           else
   435             cache_data->fc_charset = FcCharSetCreate ();
   436 
   437         finish:
   438           if (fontset)
   439             FcFontSetDestroy (fontset);
   440           if (objset)
   441             FcObjectSetDestroy (objset);
   442           if (pat)
   443             FcPatternDestroy (pat);
   444         }
   445     }
   446   return cache;
   447 }
   448 
   449 static FcCharSet *
   450 ftfont_get_fc_charset (Lisp_Object entity)
   451 {
   452   Lisp_Object val, cache;
   453   struct ftfont_cache_data *cache_data;
   454 
   455   cache = ftfont_lookup_cache (entity, FTFONT_CACHE_FOR_CHARSET);
   456   val = XCDR (cache);
   457   cache_data = xmint_pointer (val);
   458   return cache_data->fc_charset;
   459 }
   460 
   461 #ifdef HAVE_LIBOTF
   462 static OTF *
   463 ftfont_get_otf (struct font_info *ftfont_info)
   464 {
   465   OTF *otf;
   466 
   467   if (ftfont_info->otf)
   468     return ftfont_info->otf;
   469   if (! ftfont_info->maybe_otf)
   470     return NULL;
   471   otf = OTF_open_ft_face (ftfont_info->ft_size->face);
   472   if (! otf || OTF_get_table (otf, "head") < 0)
   473     {
   474       if (otf)
   475         OTF_close (otf);
   476       ftfont_info->maybe_otf = 0;
   477       return NULL;
   478     }
   479   ftfont_info->otf = otf;
   480   return otf;
   481 }
   482 #endif  /* HAVE_LIBOTF */
   483 
   484 Lisp_Object
   485 ftfont_get_cache (struct frame *f)
   486 {
   487   return freetype_font_cache;
   488 }
   489 
   490 static int
   491 ftfont_get_charset (Lisp_Object registry)
   492 {
   493   char *str = SSDATA (SYMBOL_NAME (registry));
   494   USE_SAFE_ALLOCA;
   495   char *re = SAFE_ALLOCA (SBYTES (SYMBOL_NAME (registry)) * 2 + 1);
   496   int i, j;
   497 
   498   for (i = j = 0; i < SBYTES (SYMBOL_NAME (registry)); i++, j++)
   499     {
   500       if (str[i] == '.')
   501         re[j++] = '\\';
   502       else if (str[i] == '*')
   503         re[j++] = '.';
   504       re[j] = str[i];
   505       if (re[j] == '?')
   506         re[j] = '.';
   507     }
   508   re[j] = '\0';
   509   AUTO_STRING_WITH_LEN (regexp, re, j);
   510   for (i = 0; fc_charset_table[i].name; i++)
   511     if (fast_c_string_match_ignore_case
   512         (regexp, fc_charset_table[i].name,
   513          strlen (fc_charset_table[i].name)) >= 0)
   514       break;
   515   SAFE_FREE ();
   516   if (! fc_charset_table[i].name)
   517     return -1;
   518   if (! fc_charset_table[i].fc_charset)
   519     {
   520       FcCharSet *charset = FcCharSetCreate ();
   521       int *uniquifier = fc_charset_table[i].uniquifier;
   522 
   523       if (! charset)
   524         return -1;
   525       for (j = 0; uniquifier[j]; j++)
   526         if (! FcCharSetAddChar (charset, uniquifier[j]))
   527           {
   528             FcCharSetDestroy (charset);
   529             return -1;
   530           }
   531       fc_charset_table[i].fc_charset = charset;
   532     }
   533   return i;
   534 }
   535 
   536 struct OpenTypeSpec
   537 {
   538   Lisp_Object script;
   539   unsigned int script_tag, langsys_tag;
   540   int nfeatures[2];
   541   unsigned int *features[2];
   542 };
   543 
   544 #define OTF_SYM_TAG(SYM, TAG)                                   \
   545   do {                                                          \
   546     unsigned char *p = SDATA (SYMBOL_NAME (SYM));               \
   547     TAG = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];     \
   548   } while (0)
   549 
   550 #define OTF_TAG_STR(TAG, P)                     \
   551   do {                                          \
   552     (P)[0] = (char) (TAG >> 24);                \
   553     (P)[1] = (char) ((TAG >> 16) & 0xFF);       \
   554     (P)[2] = (char) ((TAG >> 8) & 0xFF);        \
   555     (P)[3] = (char) (TAG & 0xFF);               \
   556     (P)[4] = '\0';                              \
   557   } while (0)
   558 
   559 #ifdef HAVE_LIBOTF
   560 #define OTF_TAG_SYM(SYM, TAG)                   \
   561   do {                                          \
   562     char str[5];                                \
   563                                                 \
   564     OTF_TAG_STR (TAG, str);                     \
   565     (SYM) = font_intern_prop (str, 4, 1);       \
   566   } while (0)
   567 #elif defined HAVE_HARFBUZZ
   568 /* Libotf emulations on HarfBuzz for the functions called from
   569    ftfont_list.  They are a bit slower than the original ones, so used
   570    as fallbacks when libotf is not available.  */
   571 typedef hb_face_t OTF;
   572 typedef unsigned int OTF_tag;
   573 static OTF *hbotf_open (const char *);
   574 static int hbotf_check_features (OTF *, int, OTF_tag, OTF_tag,
   575                                  const OTF_tag *, int);
   576 #define OTF_open hbotf_open
   577 #define OTF_close hb_face_destroy
   578 #define OTF_check_features hbotf_check_features
   579 #endif  /* !HAVE_LIBOTF && HAVE_HARFBUZZ */
   580 
   581 
   582 static struct OpenTypeSpec *
   583 ftfont_get_open_type_spec (Lisp_Object otf_spec)
   584 {
   585   struct OpenTypeSpec *spec = malloc (sizeof *spec);
   586   Lisp_Object val;
   587   int i, j;
   588   bool negative;
   589 
   590   if (! spec)
   591     return NULL;
   592   spec->script = XCAR (otf_spec);
   593   if (! NILP (spec->script))
   594     {
   595       OTF_SYM_TAG (spec->script, spec->script_tag);
   596       val = assq_no_quit (spec->script, Votf_script_alist);
   597       if (CONSP (val) && SYMBOLP (XCDR (val)))
   598         spec->script = XCDR (val);
   599       else
   600         spec->script = Qnil;
   601     }
   602   else
   603     spec->script_tag = 0x44464C54;      /* "DFLT" */
   604   otf_spec = XCDR (otf_spec);
   605   spec->langsys_tag = 0;
   606   if (! NILP (otf_spec))
   607     {
   608       val = XCAR (otf_spec);
   609       if (! NILP (val))
   610         OTF_SYM_TAG (val, spec->langsys_tag);
   611       otf_spec = XCDR (otf_spec);
   612     }
   613   spec->nfeatures[0] = spec->nfeatures[1] = 0;
   614   for (i = 0; i < 2 && ! NILP (otf_spec); i++, otf_spec = XCDR (otf_spec))
   615     {
   616       val = XCAR (otf_spec);
   617       if (NILP (val))
   618         continue;
   619       ptrdiff_t len = list_length (val);
   620       spec->features[i] =
   621         (min (PTRDIFF_MAX, SIZE_MAX) / sizeof (int) < len
   622          ? 0
   623          : malloc (len * sizeof *spec->features[i]));
   624       if (! spec->features[i])
   625         {
   626           if (i > 0 && spec->features[0])
   627             free (spec->features[0]);
   628           free (spec);
   629           return NULL;
   630         }
   631       for (j = 0, negative = 0; CONSP (val); val = XCDR (val))
   632         {
   633           if (NILP (XCAR (val)))
   634             negative = 1;
   635           else
   636             {
   637               unsigned int tag;
   638 
   639               OTF_SYM_TAG (XCAR (val), tag);
   640               spec->features[i][j++] = negative ? tag | 0x80000000 : tag;
   641             }
   642         }
   643       spec->nfeatures[i] = j;
   644     }
   645   return spec;
   646 }
   647 
   648 #if defined HAVE_XFT && defined FC_COLOR
   649 static bool
   650 xft_color_font_whitelisted_p (const char *family)
   651 {
   652   Lisp_Object tem, name;
   653 
   654   tem = Vxft_color_font_whitelist;
   655 
   656   FOR_EACH_TAIL_SAFE (tem)
   657     {
   658       name = XCAR (tem);
   659 
   660       if (STRINGP (name) && !strcmp (family, SSDATA (name)))
   661         return true;
   662     }
   663 
   664   return false;
   665 }
   666 #endif
   667 
   668 static FcPattern *
   669 ftfont_spec_pattern (Lisp_Object spec, char *otlayout,
   670                      struct OpenTypeSpec **otspec, const char **langname)
   671 {
   672   Lisp_Object tmp, extra;
   673   FcPattern *pattern = NULL;
   674   FcCharSet *charset = NULL;
   675   FcLangSet *langset = NULL;
   676   int n;
   677   int dpi = -1;
   678   int scalable = -1;
   679   Lisp_Object script = Qnil;
   680   Lisp_Object registry;
   681   int fc_charset_idx;
   682 
   683   if ((n = FONT_SLANT_NUMERIC (spec)) >= 0
   684       && n < 100)
   685     /* Fontconfig doesn't support reverse-italic/oblique.  */
   686     return NULL;
   687 
   688   if (FIXNUMP (AREF (spec, FONT_DPI_INDEX)))
   689     dpi = XFIXNUM (AREF (spec, FONT_DPI_INDEX));
   690   if (FIXNUMP (AREF (spec, FONT_AVGWIDTH_INDEX))
   691       && XFIXNUM (AREF (spec, FONT_AVGWIDTH_INDEX)) == 0)
   692     scalable = 1;
   693 
   694   registry = AREF (spec, FONT_REGISTRY_INDEX);
   695   if (NILP (registry)
   696       || EQ (registry, Qascii_0)
   697       || EQ (registry, Qiso10646_1)
   698       || EQ (registry, Qunicode_bmp))
   699     fc_charset_idx = -1;
   700   else
   701     {
   702       FcChar8 *lang;
   703 
   704       fc_charset_idx = ftfont_get_charset (registry);
   705       if (fc_charset_idx < 0)
   706         return NULL;
   707       charset = fc_charset_table[fc_charset_idx].fc_charset;
   708       *langname = fc_charset_table[fc_charset_idx].lang;
   709       lang = (FcChar8 *) *langname;
   710       if (lang)
   711         {
   712           langset = FcLangSetCreate ();
   713           if (! langset)
   714             goto err;
   715           FcLangSetAdd (langset, lang);
   716         }
   717     }
   718 
   719   otlayout[0] = '\0';
   720   for (extra = AREF (spec, FONT_EXTRA_INDEX);
   721        CONSP (extra); extra = XCDR (extra))
   722     {
   723       Lisp_Object key, val;
   724 
   725       key = XCAR (XCAR (extra)), val = XCDR (XCAR (extra));
   726       if (EQ (key, QCdpi))
   727         {
   728           if (FIXNUMP (val))
   729             dpi = XFIXNUM (val);
   730         }
   731       else if (EQ (key, QClang))
   732         {
   733           if (! langset)
   734             langset = FcLangSetCreate ();
   735           if (! langset)
   736             goto err;
   737           if (SYMBOLP (val))
   738             {
   739               if (! FcLangSetAdd (langset, SYMBOL_FcChar8 (val)))
   740                 goto err;
   741             }
   742           else
   743             for (; CONSP (val); val = XCDR (val))
   744               if (SYMBOLP (XCAR (val))
   745                   && ! FcLangSetAdd (langset, SYMBOL_FcChar8 (XCAR (val))))
   746                 goto err;
   747         }
   748       else if (EQ (key, QCotf))
   749         {
   750           if (CONSP (val))
   751             {
   752               *otspec = ftfont_get_open_type_spec (val);
   753               if (! *otspec)
   754                 return NULL;
   755               strcpy (otlayout, "otlayout:");
   756               OTF_TAG_STR ((*otspec)->script_tag, otlayout + 9);
   757               script = (*otspec)->script;
   758             }
   759         }
   760       else if (EQ (key, QCscript))
   761         script = val;
   762       else if (EQ (key, QCscalable))
   763         scalable = ! NILP (val);
   764     }
   765 
   766   if (! NILP (script) && ! charset)
   767     {
   768       Lisp_Object chars = assq_no_quit (script, Vscript_representative_chars);
   769 
   770       if (CONSP (chars) && CONSP (CDR (chars)))
   771         {
   772           charset = FcCharSetCreate ();
   773           if (! charset)
   774             goto err;
   775           for (chars = XCDR (chars); CONSP (chars); chars = XCDR (chars))
   776             if (CHARACTERP (XCAR (chars))
   777                 && ! FcCharSetAddChar (charset, XFIXNAT (XCAR (chars))))
   778               goto err;
   779         }
   780     }
   781 
   782   pattern = FcPatternCreate ();
   783   if (! pattern)
   784     goto err;
   785   tmp = AREF (spec, FONT_FOUNDRY_INDEX);
   786   if (! NILP (tmp)
   787       && ! FcPatternAddString (pattern, FC_FOUNDRY, SYMBOL_FcChar8 (tmp)))
   788     goto err;
   789   tmp = AREF (spec, FONT_FAMILY_INDEX);
   790   if (! NILP (tmp)
   791       && ! FcPatternAddString (pattern, FC_FAMILY, SYMBOL_FcChar8 (tmp)))
   792     goto err;
   793   if (charset
   794       && ! FcPatternAddCharSet (pattern, FC_CHARSET, charset))
   795     goto err;
   796   if (langset
   797       && ! FcPatternAddLangSet (pattern, FC_LANG, langset))
   798     goto err;
   799   if (dpi >= 0
   800       && ! FcPatternAddDouble (pattern, FC_DPI, dpi))
   801     goto err;
   802   if (scalable >= 0
   803       && ! FcPatternAddBool (pattern, FC_SCALABLE, scalable ? FcTrue : FcFalse))
   804     goto err;
   805 #if defined HAVE_XFT && defined FC_COLOR
   806   /* We really don't like color fonts, they cause Xft crashes.  See
   807      Bug#30874.  */
   808   if (xft_ignore_color_fonts
   809       && (NILP (AREF (spec, FONT_FAMILY_INDEX))
   810           || NILP (Vxft_color_font_whitelist))
   811       && ! FcPatternAddBool (pattern, FC_COLOR, FcFalse))
   812     goto err;
   813 #endif
   814 
   815   goto finish;
   816 
   817  err:
   818   /* We come here because of unexpected error in fontconfig API call
   819      (usually insufficient memory).  */
   820   if (pattern)
   821     {
   822       FcPatternDestroy (pattern);
   823       pattern = NULL;
   824     }
   825   if (*otspec)
   826     {
   827       if ((*otspec)->nfeatures[0] > 0)
   828         free ((*otspec)->features[0]);
   829       if ((*otspec)->nfeatures[1] > 0)
   830         free ((*otspec)->features[1]);
   831       free (*otspec);
   832       *otspec = NULL;
   833     }
   834 
   835  finish:
   836   if (langset) FcLangSetDestroy (langset);
   837   if (charset && fc_charset_idx < 0) FcCharSetDestroy (charset);
   838   return pattern;
   839 }
   840 
   841 static Lisp_Object
   842 ftfont_list (struct frame *f, Lisp_Object spec)
   843 {
   844   Lisp_Object val = Qnil, family, adstyle;
   845   int i;
   846   FcPattern *pattern;
   847   FcFontSet *fontset = NULL;
   848   FcObjectSet *objset = NULL;
   849   FcCharSet *charset;
   850   Lisp_Object chars = Qnil;
   851   char otlayout[15];            /* For "otlayout:XXXX" */
   852   struct OpenTypeSpec *otspec = NULL;
   853   int spacing = -1;
   854   const char *langname = NULL;
   855 
   856   if (! fc_initialized)
   857     {
   858       FcInit ();
   859       fc_initialized = 1;
   860     }
   861 
   862   pattern = ftfont_spec_pattern (spec, otlayout, &otspec, &langname);
   863   if (! pattern)
   864     return Qnil;
   865   if (FcPatternGetCharSet (pattern, FC_CHARSET, 0, &charset) != FcResultMatch)
   866     {
   867       val = assq_no_quit (QCscript, AREF (spec, FONT_EXTRA_INDEX));
   868       if (! NILP (val))
   869         {
   870           val = assq_no_quit (XCDR (val), Vscript_representative_chars);
   871           if (CONSP (val) && VECTORP (XCDR (val)))
   872             chars = XCDR (val);
   873         }
   874       val = Qnil;
   875     }
   876   if (FIXNUMP (AREF (spec, FONT_SPACING_INDEX)))
   877     spacing = XFIXNUM (AREF (spec, FONT_SPACING_INDEX));
   878   family = AREF (spec, FONT_FAMILY_INDEX);
   879   if (! NILP (family))
   880     {
   881       Lisp_Object resolved;
   882 
   883       resolved = ftfont_resolve_generic_family (family, pattern);
   884       if (! NILP (resolved))
   885         {
   886           FcPatternDel (pattern, FC_FAMILY);
   887           if (! FcPatternAddString (pattern, FC_FAMILY,
   888                                     SYMBOL_FcChar8 (resolved)))
   889             goto err;
   890         }
   891     }
   892   adstyle = AREF (spec, FONT_ADSTYLE_INDEX);
   893   if (! NILP (adstyle) && SBYTES (SYMBOL_NAME (adstyle)) == 0)
   894     adstyle = Qnil;
   895   objset = FcObjectSetBuild (FC_FOUNDRY, FC_FAMILY, FC_WEIGHT, FC_SLANT,
   896                              FC_WIDTH, FC_PIXEL_SIZE, FC_SPACING, FC_SCALABLE,
   897                              FC_STYLE, FC_FILE, FC_INDEX,
   898 #ifdef FC_CAPABILITY
   899                              FC_CAPABILITY,
   900 #endif  /* FC_CAPABILITY */
   901 #ifdef FC_FONTFORMAT
   902                              FC_FONTFORMAT,
   903 #endif
   904 #if defined HAVE_XFT && defined FC_COLOR
   905                              FC_COLOR,
   906 #endif
   907 #ifdef FC_VARIABLE
   908                              FC_VARIABLE,
   909 #endif  /* FC_VARIABLE */
   910                              NULL);
   911   if (! objset)
   912     goto err;
   913   if (! NILP (chars))
   914     FcObjectSetAdd (objset, FC_CHARSET);
   915 
   916   fontset = FcFontList (NULL, pattern, objset);
   917   if (! fontset || fontset->nfont == 0)
   918     goto finish;
   919 #if 0
   920   /* Need fix because this finds any fonts.  */
   921   if (fontset->nfont == 0 && ! NILP (family))
   922     {
   923       /* Try matching with configuration.  For instance, the
   924          configuration may specify "Nimbus Mono L" as an alias of
   925          "Courier".  */
   926       FcPattern *pat = FcPatternBuild (0, FC_FAMILY, FcTypeString,
   927                                        SYMBOL_FcChar8 (family), NULL);
   928       FcChar8 *fam;
   929 
   930       if (FcConfigSubstitute (NULL, pat, FcMatchPattern) == FcTrue)
   931         {
   932           for (i = 0;
   933                FcPatternGetString (pat, FC_FAMILY, i, &fam) == FcResultMatch;
   934                i++)
   935             {
   936               FcPatternDel (pattern, FC_FAMILY);
   937               FcPatternAddString (pattern, FC_FAMILY, fam);
   938               FcFontSetDestroy (fontset);
   939               fontset = FcFontList (NULL, pattern, objset);
   940               if (fontset && fontset->nfont > 0)
   941                 break;
   942             }
   943         }
   944     }
   945 #endif
   946   for (i = 0; i < fontset->nfont; i++)
   947     {
   948       Lisp_Object entity;
   949 #if defined HAVE_XFT && defined FC_COLOR
   950       {
   951         /* Some fonts, notably NotoColorEmoji, have an FC_COLOR value
   952            that's neither FcTrue nor FcFalse, which means FcFontList
   953            returns them even when it shouldn't really do so, so we
   954            need to manually skip them here (Bug#37786).  */
   955         FcBool b;
   956         FcChar8 *str;
   957 
   958         if (xft_ignore_color_fonts
   959             && (FcPatternGetString (fontset->fonts[i], FC_FAMILY,
   960                                     0, &str) != FcResultMatch
   961                 || !xft_color_font_whitelisted_p ((char *) str))
   962             && FcPatternGetBool (fontset->fonts[i], FC_COLOR, 0, &b)
   963             == FcResultMatch && b != FcFalse)
   964             continue;
   965       }
   966 #endif
   967       if (spacing >= 0)
   968         {
   969           int this;
   970 
   971           if ((FcPatternGetInteger (fontset->fonts[i], FC_SPACING, 0, &this)
   972                == FcResultMatch)
   973               && spacing != this)
   974             continue;
   975         }
   976 
   977 #ifdef FC_CAPABILITY
   978       if (otlayout[0])
   979         {
   980           FcChar8 *this;
   981 
   982           if (FcPatternGetString (fontset->fonts[i], FC_CAPABILITY, 0, &this)
   983               != FcResultMatch
   984               || ! strstr ((char *) this, otlayout))
   985             continue;
   986         }
   987 #endif  /* FC_CAPABILITY */
   988 #if defined HAVE_LIBOTF || defined HAVE_HARFBUZZ
   989       if (otspec)
   990         {
   991           FcChar8 *file;
   992           bool passed;
   993           OTF *otf;
   994 
   995           if (FcPatternGetString (fontset->fonts[i], FC_FILE, 0, &file)
   996               != FcResultMatch)
   997             continue;
   998           otf = OTF_open ((char *) file);
   999           if (! otf)
  1000             continue;
  1001           passed = (OTF_check_features (otf, 1, otspec->script_tag,
  1002                                         otspec->langsys_tag,
  1003                                         otspec->features[0],
  1004                                         otspec->nfeatures[0]) == 1
  1005                     && OTF_check_features (otf, 0, otspec->script_tag,
  1006                                            otspec->langsys_tag,
  1007                                            otspec->features[1],
  1008                                            otspec->nfeatures[1]) == 1);
  1009           OTF_close (otf);
  1010           if (!passed)
  1011             continue;
  1012         }
  1013 #endif  /* HAVE_LIBOTF || HAVE_HARFBUZZ */
  1014       if (VECTORP (chars))
  1015         {
  1016           ptrdiff_t j;
  1017 
  1018           if (FcPatternGetCharSet (fontset->fonts[i], FC_CHARSET, 0, &charset)
  1019               != FcResultMatch)
  1020             continue;
  1021           for (j = 0; j < ASIZE (chars); j++)
  1022             if (TYPE_RANGED_FIXNUMP (FcChar32, AREF (chars, j))
  1023                 && FcCharSetHasChar (charset, XFIXNAT (AREF (chars, j))))
  1024               break;
  1025           if (j == ASIZE (chars))
  1026             continue;
  1027         }
  1028       if (! NILP (adstyle) || langname)
  1029         {
  1030           Lisp_Object this_adstyle = get_adstyle_property (fontset->fonts[i]);
  1031 
  1032           if (! NILP (adstyle)
  1033               && (NILP (this_adstyle)
  1034                   || xstrcasecmp (SSDATA (SYMBOL_NAME (adstyle)),
  1035                                   SSDATA (SYMBOL_NAME (this_adstyle))) != 0))
  1036             continue;
  1037           if (langname
  1038               && ! NILP (this_adstyle)
  1039               && xstrcasecmp (langname, SSDATA (SYMBOL_NAME (this_adstyle))))
  1040             continue;
  1041         }
  1042       entity = ftfont_pattern_entity (fontset->fonts[i],
  1043                                       AREF (spec, FONT_EXTRA_INDEX));
  1044       if (! NILP (entity))
  1045         val = Fcons (entity, val);
  1046     }
  1047   val = Fnreverse (val);
  1048   goto finish;
  1049 
  1050  err:
  1051   /* We come here because of unexpected error in fontconfig API call
  1052      (usually insufficient memory).  */
  1053   val = Qnil;
  1054 
  1055  finish:
  1056   FONT_ADD_LOG ("ftfont-list", spec, val);
  1057   if (objset) FcObjectSetDestroy (objset);
  1058   if (fontset) FcFontSetDestroy (fontset);
  1059   if (pattern) FcPatternDestroy (pattern);
  1060   return val;
  1061 }
  1062 
  1063 Lisp_Object
  1064 ftfont_list2 (struct frame *f, Lisp_Object spec, Lisp_Object type)
  1065 {
  1066   Lisp_Object list = ftfont_list (f, spec);
  1067 
  1068   for (Lisp_Object tail = list; CONSP (tail); tail = XCDR (tail))
  1069     ASET (XCAR (tail), FONT_TYPE_INDEX, type);
  1070   return list;
  1071 }
  1072 
  1073 static Lisp_Object
  1074 ftfont_match (struct frame *f, Lisp_Object spec)
  1075 {
  1076   Lisp_Object entity = Qnil;
  1077   FcPattern *pattern, *match = NULL;
  1078   FcResult result;
  1079   char otlayout[15];            /* For "otlayout:XXXX" */
  1080   struct OpenTypeSpec *otspec = NULL;
  1081   const char *langname = NULL;
  1082 
  1083   if (! fc_initialized)
  1084     {
  1085       FcInit ();
  1086       fc_initialized = 1;
  1087     }
  1088 
  1089   pattern = ftfont_spec_pattern (spec, otlayout, &otspec, &langname);
  1090   if (! pattern)
  1091     return Qnil;
  1092 
  1093   if (FIXNUMP (AREF (spec, FONT_SIZE_INDEX)))
  1094     {
  1095       FcValue value;
  1096 
  1097       value.type = FcTypeDouble;
  1098       value.u.d = XFIXNUM (AREF (spec, FONT_SIZE_INDEX));
  1099       FcPatternAdd (pattern, FC_PIXEL_SIZE, value, FcFalse);
  1100     }
  1101   if (FcConfigSubstitute (NULL, pattern, FcMatchPattern) == FcTrue)
  1102     {
  1103       FcDefaultSubstitute (pattern);
  1104       match = FcFontMatch (NULL, pattern, &result);
  1105       if (match)
  1106         {
  1107           entity = ftfont_pattern_entity (match, AREF (spec, FONT_EXTRA_INDEX));
  1108           FcPatternDestroy (match);
  1109           if (! NILP (AREF (spec, FONT_FAMILY_INDEX))
  1110               && NILP (assq_no_quit (AREF (spec, FONT_FAMILY_INDEX),
  1111                                      ftfont_generic_family_list))
  1112               && NILP (Fstring_equal (AREF (spec, FONT_FAMILY_INDEX),
  1113                                       AREF (entity, FONT_FAMILY_INDEX))))
  1114             entity = Qnil;
  1115         }
  1116     }
  1117   FcPatternDestroy (pattern);
  1118 
  1119   FONT_ADD_LOG ("ftfont-match", spec, entity);
  1120   return entity;
  1121 }
  1122 
  1123 Lisp_Object
  1124 ftfont_match2 (struct frame *f, Lisp_Object spec, Lisp_Object type)
  1125 {
  1126   Lisp_Object entity = ftfont_match (f, spec);
  1127 
  1128   if (! NILP (entity))
  1129     ASET (entity, FONT_TYPE_INDEX, type);
  1130   return entity;
  1131 }
  1132 
  1133 Lisp_Object
  1134 ftfont_list_family (struct frame *f)
  1135 {
  1136   Lisp_Object list = Qnil;
  1137   FcPattern *pattern = NULL;
  1138   FcFontSet *fontset = NULL;
  1139   FcObjectSet *objset = NULL;
  1140   int i;
  1141 
  1142   if (! fc_initialized)
  1143     {
  1144       FcInit ();
  1145       fc_initialized = 1;
  1146     }
  1147 
  1148   pattern = FcPatternCreate ();
  1149   if (! pattern)
  1150     goto finish;
  1151   objset = FcObjectSetBuild (FC_FAMILY, NULL);
  1152   if (! objset)
  1153     goto finish;
  1154   fontset = FcFontList (NULL, pattern, objset);
  1155   if (! fontset)
  1156     goto finish;
  1157 
  1158   for (i = 0; i < fontset->nfont; i++)
  1159     {
  1160       FcPattern *pat = fontset->fonts[i];
  1161       FcChar8 *str;
  1162 
  1163       if (FcPatternGetString (pat, FC_FAMILY, 0, &str) == FcResultMatch)
  1164         list = Fcons (intern ((char *) str), list);
  1165     }
  1166 
  1167  finish:
  1168   if (objset) FcObjectSetDestroy (objset);
  1169   if (fontset) FcFontSetDestroy (fontset);
  1170   if (pattern) FcPatternDestroy (pattern);
  1171 
  1172   return list;
  1173 }
  1174 
  1175 void
  1176 ftfont_fix_match (FcPattern *pat, FcPattern *match)
  1177 {
  1178   /*  These values are not used for matching (except antialias), but for
  1179       rendering, so make sure they are carried over to the match.
  1180       We also put antialias here because most fonts are antialiased, so
  1181       the match will have antialias true.  */
  1182 
  1183   FcBool b = FcTrue;
  1184   int i;
  1185   double dpi;
  1186 
  1187   FcPatternGetBool (pat, FC_ANTIALIAS, 0, &b);
  1188   if (! b)
  1189     {
  1190       FcPatternDel (match, FC_ANTIALIAS);
  1191       FcPatternAddBool (match, FC_ANTIALIAS, FcFalse);
  1192     }
  1193   FcPatternGetBool (pat, FC_HINTING, 0, &b);
  1194   if (! b)
  1195     {
  1196       FcPatternDel (match, FC_HINTING);
  1197       FcPatternAddBool (match, FC_HINTING, FcFalse);
  1198     }
  1199 #ifndef FC_HINT_STYLE
  1200 # define FC_HINT_STYLE "hintstyle"
  1201 #endif
  1202   if (FcResultMatch == FcPatternGetInteger (pat, FC_HINT_STYLE, 0, &i))
  1203     {
  1204       FcPatternDel (match, FC_HINT_STYLE);
  1205       FcPatternAddInteger (match, FC_HINT_STYLE, i);
  1206     }
  1207 #ifndef FC_LCD_FILTER
  1208   /* Older fontconfig versions don't have FC_LCD_FILTER. */
  1209 #define FC_LCD_FILTER "lcdfilter"
  1210 #endif
  1211   if (FcResultMatch == FcPatternGetInteger (pat, FC_LCD_FILTER, 0, &i))
  1212     {
  1213       FcPatternDel (match, FC_LCD_FILTER);
  1214       FcPatternAddInteger (match, FC_LCD_FILTER, i);
  1215     }
  1216   if (FcResultMatch == FcPatternGetInteger (pat, FC_RGBA, 0, &i))
  1217     {
  1218       FcPatternDel (match, FC_RGBA);
  1219       FcPatternAddInteger (match, FC_RGBA, i);
  1220     }
  1221   if (FcResultMatch == FcPatternGetDouble (pat, FC_DPI, 0, &dpi))
  1222     {
  1223       FcPatternDel (match, FC_DPI);
  1224       FcPatternAddDouble (match, FC_DPI, dpi);
  1225     }
  1226 }
  1227 
  1228 void
  1229 ftfont_add_rendering_parameters (FcPattern *pat, Lisp_Object entity)
  1230 {
  1231   Lisp_Object tail;
  1232   int ival;
  1233 
  1234   for (tail = AREF (entity, FONT_EXTRA_INDEX); CONSP (tail); tail = XCDR (tail))
  1235     {
  1236       Lisp_Object key = XCAR (XCAR (tail));
  1237       Lisp_Object val = XCDR (XCAR (tail));
  1238 
  1239       if (EQ (key, QCantialias))
  1240           FcPatternAddBool (pat, FC_ANTIALIAS, NILP (val) ? FcFalse : FcTrue);
  1241       else if (EQ (key, QChinting))
  1242         FcPatternAddBool (pat, FC_HINTING, NILP (val) ? FcFalse : FcTrue);
  1243       else if (EQ (key, QCautohint))
  1244         FcPatternAddBool (pat, FC_AUTOHINT, NILP (val) ? FcFalse : FcTrue);
  1245       else if (EQ (key, QChintstyle))
  1246         {
  1247           if (FIXNUMP (val))
  1248             FcPatternAddInteger (pat, FC_HINT_STYLE, XFIXNUM (val));
  1249           else if (SYMBOLP (val)
  1250                    && FcNameConstant (SDATA (SYMBOL_NAME (val)), &ival))
  1251             FcPatternAddInteger (pat, FC_HINT_STYLE, ival);
  1252         }
  1253       else if (EQ (key, QCrgba))
  1254         {
  1255           if (FIXNUMP (val))
  1256             FcPatternAddInteger (pat, FC_RGBA, XFIXNUM (val));
  1257           else if (SYMBOLP (val)
  1258                    && FcNameConstant (SDATA (SYMBOL_NAME (val)), &ival))
  1259             FcPatternAddInteger (pat, FC_RGBA, ival);
  1260         }
  1261       else if (EQ (key, QClcdfilter))
  1262         {
  1263           if (FIXNUMP (val))
  1264             FcPatternAddInteger (pat, FC_LCD_FILTER, ival = XFIXNUM (val));
  1265           else if (SYMBOLP (val)
  1266                    && FcNameConstant (SDATA (SYMBOL_NAME (val)), &ival))
  1267             FcPatternAddInteger (pat, FC_LCD_FILTER, ival);
  1268         }
  1269 #ifdef FC_EMBOLDEN
  1270       else if (EQ (key, QCembolden))
  1271         FcPatternAddBool (pat, FC_EMBOLDEN, NILP (val) ? FcFalse : FcTrue);
  1272 #endif
  1273     }
  1274 }
  1275 
  1276 FcPattern *
  1277 ftfont_entity_pattern (Lisp_Object entity, int pixel_size)
  1278 {
  1279   Lisp_Object val, filename, idx;
  1280   FcPattern *pat;
  1281   int i;
  1282 
  1283   val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
  1284   eassert (CONSP (val));
  1285   val = XCDR (val);
  1286   filename = XCAR (val);
  1287   idx = XCDR (val);
  1288   pat = FcPatternCreate ();
  1289   FcPatternAddInteger (pat, FC_WEIGHT, FONT_WEIGHT_NUMERIC (entity));
  1290   i = FONT_SLANT_NUMERIC (entity) - 100;
  1291   if (i < 0) i = 0;
  1292   FcPatternAddInteger (pat, FC_SLANT, i);
  1293   FcPatternAddInteger (pat, FC_WIDTH, FONT_WIDTH_NUMERIC (entity));
  1294   FcPatternAddDouble (pat, FC_PIXEL_SIZE, pixel_size);
  1295   val = AREF (entity, FONT_FAMILY_INDEX);
  1296   if (! NILP (val))
  1297     FcPatternAddString (pat, FC_FAMILY, (FcChar8 *) SDATA (SYMBOL_NAME (val)));
  1298   val = AREF (entity, FONT_FOUNDRY_INDEX);
  1299   if (! NILP (val))
  1300     FcPatternAddString (pat, FC_FOUNDRY, (FcChar8 *) SDATA (SYMBOL_NAME (val)));
  1301   val = AREF (entity, FONT_SPACING_INDEX);
  1302   if (! NILP (val))
  1303     FcPatternAddInteger (pat, FC_SPACING, XFIXNUM (val));
  1304   val = AREF (entity, FONT_DPI_INDEX);
  1305   if (! NILP (val))
  1306     {
  1307       double dbl = XFIXNUM (val);
  1308 
  1309       FcPatternAddDouble (pat, FC_DPI, dbl);
  1310     }
  1311   val = AREF (entity, FONT_AVGWIDTH_INDEX);
  1312   if (FIXNUMP (val) && XFIXNUM (val) == 0)
  1313     FcPatternAddBool (pat, FC_SCALABLE, FcTrue);
  1314   /* This is necessary to identify the exact font (e.g. 10x20.pcf.gz
  1315      over 10x20-ISO8859-1.pcf.gz).  */
  1316   FcPatternAddCharSet (pat, FC_CHARSET, ftfont_get_fc_charset (entity));
  1317 
  1318   ftfont_add_rendering_parameters (pat, entity);
  1319 
  1320   FcPatternAddString (pat, FC_FILE, (FcChar8 *) SDATA (filename));
  1321   FcPatternAddInteger (pat, FC_INDEX, XFIXNUM (idx));
  1322 
  1323   return pat;
  1324 }
  1325 
  1326 #ifndef USE_CAIRO
  1327 
  1328 Lisp_Object
  1329 ftfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
  1330 {
  1331   struct font_info *ftfont_info;
  1332   struct font *font;
  1333   struct ftfont_cache_data *cache_data;
  1334   FT_Face ft_face;
  1335   FT_Size ft_size;
  1336   FT_UInt size;
  1337   Lisp_Object val, filename, idx, cache, font_object;
  1338   bool scalable;
  1339   int spacing;
  1340   int i;
  1341   double upEM;
  1342 
  1343   val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
  1344   if (! CONSP (val))
  1345     return Qnil;
  1346   val = XCDR (val);
  1347   cache = ftfont_lookup_cache (entity, FTFONT_CACHE_FOR_FACE);
  1348   if (NILP (cache))
  1349     return Qnil;
  1350   filename = XCAR (val);
  1351   idx = XCDR (val);
  1352   cache_data = xmint_pointer (XCDR (cache));
  1353   ft_face = cache_data->ft_face;
  1354   if (cache_data->face_refcount > 0)
  1355     {
  1356       /* FT_Face in this cache is already used by the different size.  */
  1357       if (FT_New_Size (ft_face, &ft_size) != 0)
  1358         return Qnil;
  1359       if (FT_Activate_Size (ft_size) != 0)
  1360         {
  1361           FT_Done_Size (ft_size);
  1362           return Qnil;
  1363         }
  1364     }
  1365   size = XFIXNUM (AREF (entity, FONT_SIZE_INDEX));
  1366   if (size == 0)
  1367     size = pixel_size;
  1368   if (FT_Set_Pixel_Sizes (ft_face, size, size) != 0)
  1369     {
  1370       if (cache_data->face_refcount == 0)
  1371         {
  1372           FT_Done_Face (ft_face);
  1373           cache_data->ft_face = NULL;
  1374         }
  1375       return Qnil;
  1376     }
  1377   cache_data->face_refcount++;
  1378 
  1379   font_object = font_build_object (VECSIZE (struct font_info),
  1380                                    Qfreetype, entity, size);
  1381   ASET (font_object, FONT_FILE_INDEX, filename);
  1382   font = XFONT_OBJECT (font_object);
  1383   ftfont_info = (struct font_info *) font;
  1384   ftfont_info->ft_size = ft_face->size;
  1385   ftfont_info->index = XFIXNUM (idx);
  1386 #ifdef HAVE_LIBOTF
  1387   ftfont_info->maybe_otf = (ft_face->face_flags & FT_FACE_FLAG_SFNT) != 0;
  1388   ftfont_info->otf = NULL;
  1389 #endif  /* HAVE_LIBOTF */
  1390 #ifdef HAVE_HARFBUZZ
  1391   ftfont_info->hb_font = NULL;
  1392 #endif  /* HAVE_HARFBUZZ */
  1393   /* This means that there's no need of transformation.  */
  1394   ftfont_info->matrix.xx = 0;
  1395   font->pixel_size = size;
  1396 #ifdef HAVE_HARFBUZZ
  1397   if (EQ (AREF (font_object, FONT_TYPE_INDEX), Qfreetypehb))
  1398     font->driver = &fthbfont_driver;
  1399   else
  1400 #endif  /* HAVE_HARFBUZZ */
  1401   font->driver = &ftfont_driver;
  1402   font->encoding_charset = font->repertory_charset = -1;
  1403 
  1404   val = assq_no_quit (QCminspace, AREF (entity, FONT_EXTRA_INDEX));
  1405   bool no_leading_p = !(CONSP (val) && NILP (XCDR (val)));
  1406   upEM = ft_face->units_per_EM;
  1407   scalable = (FIXNUMP (AREF (entity, FONT_AVGWIDTH_INDEX))
  1408               && XFIXNUM (AREF (entity, FONT_AVGWIDTH_INDEX)) == 0);
  1409   if (scalable)
  1410     {
  1411       font->ascent = ft_face->ascender * size / upEM + 0.5;
  1412       if (no_leading_p)
  1413         {
  1414           font->descent = - ft_face->descender * size / upEM + 0.5;
  1415           font->height = font->ascent + font->descent;
  1416         }
  1417       else
  1418         {
  1419           font->height = ft_face->height * size / upEM + 0.5;
  1420           font->descent = font->height - font->ascent;
  1421         }
  1422     }
  1423   else
  1424     {
  1425       font->ascent = ft_face->size->metrics.ascender >> 6;
  1426       if (no_leading_p)
  1427         {
  1428           font->descent = - ft_face->size->metrics.descender >> 6;
  1429           font->height = font->ascent + font->descent;
  1430         }
  1431       else
  1432         {
  1433           font->height = ft_face->size->metrics.height >> 6;
  1434           font->descent = font->height - font->ascent;
  1435         }
  1436     }
  1437   if (FIXNUMP (AREF (entity, FONT_SPACING_INDEX)))
  1438     spacing = XFIXNUM (AREF (entity, FONT_SPACING_INDEX));
  1439   else
  1440     spacing = FC_PROPORTIONAL;
  1441   if (spacing != FC_PROPORTIONAL
  1442 #ifdef FC_DUAL
  1443       && spacing != FC_DUAL
  1444 #endif  /* FC_DUAL */
  1445       )
  1446     font->min_width = font->average_width = font->space_width
  1447       = (scalable ? ft_face->max_advance_width * size / upEM + 0.5
  1448          : ft_face->size->metrics.max_advance >> 6);
  1449   else
  1450     {
  1451       int n;
  1452 
  1453       font->min_width = font->average_width = font->space_width = 0;
  1454       for (i = 32, n = 0; i < 127; i++)
  1455         if (FT_Load_Char (ft_face, i, FT_LOAD_DEFAULT) == 0)
  1456           {
  1457             int this_width = ft_face->glyph->metrics.horiAdvance >> 6;
  1458 
  1459             if (this_width > 0
  1460                 && (! font->min_width || font->min_width > this_width))
  1461               font->min_width = this_width;
  1462             if (i == 32)
  1463               font->space_width = this_width;
  1464             font->average_width += this_width;
  1465             n++;
  1466           }
  1467       if (n > 0)
  1468         font->average_width /= n;
  1469     }
  1470 
  1471   font->baseline_offset = 0;
  1472   font->relative_compose = 0;
  1473   font->default_ascent = 0;
  1474   font->vertical_centering = 0;
  1475   if (scalable)
  1476     {
  1477       font->underline_position = (-ft_face->underline_position * size / upEM
  1478                                   + 0.5);
  1479       font->underline_thickness = (ft_face->underline_thickness * size / upEM
  1480                                    + 0.5);
  1481     }
  1482   else
  1483     {
  1484       font->underline_position = -1;
  1485       font->underline_thickness = 0;
  1486     }
  1487 
  1488   return font_object;
  1489 }
  1490 
  1491 void
  1492 ftfont_close (struct font *font)
  1493 {
  1494   if (font_data_structures_may_be_ill_formed ())
  1495     return;
  1496 
  1497   struct font_info *ftfont_info = (struct font_info *) font;
  1498   Lisp_Object val, cache;
  1499 
  1500   val = Fcons (font->props[FONT_FILE_INDEX], make_fixnum (ftfont_info->index));
  1501   cache = ftfont_lookup_cache (val, FTFONT_CACHE_FOR_FACE);
  1502   eassert (CONSP (cache));
  1503   val = XCDR (cache);
  1504   struct ftfont_cache_data *cache_data = xmint_pointer (val);
  1505   cache_data->face_refcount--;
  1506   if (cache_data->face_refcount == 0)
  1507     {
  1508       FT_Done_Face (cache_data->ft_face);
  1509 #ifdef HAVE_LIBOTF
  1510       if (ftfont_info->otf)
  1511         OTF_close (ftfont_info->otf);
  1512 #endif
  1513 #ifdef HAVE_HARFBUZZ
  1514       if (ftfont_info->hb_font)
  1515         hb_font_destroy (ftfont_info->hb_font);
  1516 #endif
  1517       cache_data->ft_face = NULL;
  1518     }
  1519   else
  1520     FT_Done_Size (ftfont_info->ft_size);
  1521 }
  1522 
  1523 #endif /* !USE_CAIRO */
  1524 
  1525 int
  1526 ftfont_has_char (Lisp_Object font, int c)
  1527 {
  1528   struct charset *cs = NULL;
  1529 
  1530   if (EQ (AREF (font, FONT_ADSTYLE_INDEX), Qja)
  1531       && charset_jisx0208 >= 0)
  1532     cs = CHARSET_FROM_ID (charset_jisx0208);
  1533   else if (EQ (AREF (font, FONT_ADSTYLE_INDEX), Qko)
  1534       && charset_ksc5601 >= 0)
  1535     cs = CHARSET_FROM_ID (charset_ksc5601);
  1536   if (cs)
  1537     return (ENCODE_CHAR (cs, c) != CHARSET_INVALID_CODE (cs));
  1538 
  1539   if (FONT_ENTITY_P (font))
  1540     {
  1541       FcCharSet *charset = ftfont_get_fc_charset (font);
  1542 
  1543       return (FcCharSetHasChar (charset, c) == FcTrue);
  1544     }
  1545   else
  1546     {
  1547       struct font_info *ftfont_info;
  1548 
  1549       ftfont_info = (struct font_info *) XFONT_OBJECT (font);
  1550       return (FT_Get_Char_Index (ftfont_info->ft_size->face, (FT_ULong) c)
  1551               != 0);
  1552     }
  1553 }
  1554 
  1555 #ifndef USE_CAIRO
  1556 
  1557 unsigned
  1558 ftfont_encode_char (struct font *font, int c)
  1559 {
  1560   struct font_info *ftfont_info = (struct font_info *) font;
  1561   FT_Face ft_face = ftfont_info->ft_size->face;
  1562   FT_ULong charcode = c;
  1563   FT_UInt code = FT_Get_Char_Index (ft_face, charcode);
  1564 
  1565   return (code > 0 ? code : FONT_INVALID_CODE);
  1566 }
  1567 
  1568 static bool
  1569 ftfont_glyph_metrics (FT_Face ft_face, int c, int *advance, int *lbearing,
  1570                       int *rbearing, int *ascent, int *descent)
  1571 {
  1572   if (FT_Load_Glyph (ft_face, c, FT_LOAD_DEFAULT) == 0)
  1573     {
  1574       FT_Glyph_Metrics *m = &ft_face->glyph->metrics;
  1575       *advance = m->horiAdvance >> 6;
  1576       *lbearing = m->horiBearingX >> 6;
  1577       *rbearing = (m->horiBearingX + m->width) >> 6;
  1578       *ascent = m->horiBearingY >> 6;
  1579       *descent = (m->height - m->horiBearingY) >> 6;
  1580       return true;
  1581     }
  1582 
  1583   return false;
  1584 }
  1585 
  1586 void
  1587 ftfont_text_extents (struct font *font, const unsigned int *code,
  1588                      int nglyphs, struct font_metrics *metrics)
  1589 {
  1590   struct font_info *ftfont_info = (struct font_info *) font;
  1591   FT_Face ft_face = ftfont_info->ft_size->face;
  1592   int i, width = 0;
  1593   bool first;
  1594 
  1595   if (ftfont_info->ft_size != ft_face->size)
  1596     FT_Activate_Size (ftfont_info->ft_size);
  1597 
  1598   for (i = 0, first = 1; i < nglyphs; i++)
  1599     {
  1600       int advance, lbearing, rbearing, ascent, descent;
  1601       if (ftfont_glyph_metrics (ft_face, code[i], &advance, &lbearing,
  1602                                 &rbearing, &ascent, &descent))
  1603         {
  1604           if (first)
  1605             {
  1606               metrics->lbearing = lbearing;
  1607               metrics->rbearing = rbearing;
  1608               metrics->ascent = ascent;
  1609               metrics->descent = descent;
  1610               first = 0;
  1611             }
  1612           if (metrics->lbearing > width + lbearing)
  1613             metrics->lbearing = width + lbearing;
  1614           if (metrics->rbearing < width + rbearing)
  1615             metrics->rbearing = width + rbearing;
  1616           if (metrics->ascent < ascent)
  1617             metrics->ascent = ascent;
  1618           if (metrics->descent > descent)
  1619             metrics->descent = descent;
  1620           width += advance;
  1621         }
  1622       else
  1623         width += font->space_width;
  1624     }
  1625   metrics->width = width;
  1626 }
  1627 
  1628 #endif /* !USE_CAIRO */
  1629 
  1630 int
  1631 ftfont_get_bitmap (struct font *font, unsigned int code, struct font_bitmap *bitmap, int bits_per_pixel)
  1632 {
  1633   struct font_info *ftfont_info = (struct font_info *) font;
  1634   FT_Face ft_face = ftfont_info->ft_size->face;
  1635   FT_Int32 load_flags = FT_LOAD_RENDER;
  1636 
  1637   if (ftfont_info->ft_size != ft_face->size)
  1638     FT_Activate_Size (ftfont_info->ft_size);
  1639   if (bits_per_pixel == 1)
  1640     {
  1641 #ifdef FT_LOAD_TARGET_MONO
  1642       load_flags |= FT_LOAD_TARGET_MONO;
  1643 #else
  1644       load_flags |= FT_LOAD_MONOCHROME;
  1645 #endif
  1646     }
  1647   else if (bits_per_pixel != 8)
  1648     /* We don't support such a rendering.  */
  1649     return -1;
  1650 
  1651   if (FT_Load_Glyph (ft_face, code, load_flags) != 0)
  1652     return -1;
  1653   bitmap->bits_per_pixel
  1654     = (ft_face->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_MONO ? 1
  1655        : ft_face->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_GRAY ? 8
  1656        : ft_face->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_LCD ? 8
  1657        : ft_face->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_LCD_V ? 8
  1658        : -1);
  1659   if (bitmap->bits_per_pixel < 0)
  1660     /* We don't support that kind of pixel mode.  */
  1661     return -1;
  1662   bitmap->rows = ft_face->glyph->bitmap.rows;
  1663   bitmap->width = ft_face->glyph->bitmap.width;
  1664   bitmap->pitch = ft_face->glyph->bitmap.pitch;
  1665   bitmap->buffer = ft_face->glyph->bitmap.buffer;
  1666   bitmap->left = ft_face->glyph->bitmap_left;
  1667   bitmap->top = ft_face->glyph->bitmap_top;
  1668   bitmap->advance = ft_face->glyph->metrics.horiAdvance >> 6;
  1669 
  1670   return 0;
  1671 }
  1672 
  1673 int
  1674 ftfont_anchor_point (struct font *font, unsigned int code, int idx,
  1675                      int *x, int *y)
  1676 {
  1677   struct font_info *ftfont_info = (struct font_info *) font;
  1678   FT_Face ft_face = ftfont_info->ft_size->face;
  1679 
  1680   if (ftfont_info->ft_size != ft_face->size)
  1681     FT_Activate_Size (ftfont_info->ft_size);
  1682   if (FT_Load_Glyph (ft_face, code, FT_LOAD_DEFAULT) != 0)
  1683     return -1;
  1684   if (ft_face->glyph->format != FT_GLYPH_FORMAT_OUTLINE)
  1685     return -1;
  1686   if (idx >= ft_face->glyph->outline.n_points)
  1687     return -1;
  1688   *x = ft_face->glyph->outline.points[idx].x;
  1689   *y = ft_face->glyph->outline.points[idx].y;
  1690   return 0;
  1691 }
  1692 
  1693 #ifdef HAVE_LIBOTF
  1694 
  1695 static Lisp_Object
  1696 ftfont_otf_features (OTF_GSUB_GPOS *gsub_gpos)
  1697 {
  1698   Lisp_Object scripts, langsyses, features, sym;
  1699   int i, j, k, l;
  1700 
  1701   for (scripts = Qnil, i = gsub_gpos->ScriptList.ScriptCount - 1; i >= 0; i--)
  1702     {
  1703       OTF_Script *otf_script = gsub_gpos->ScriptList.Script + i;
  1704 
  1705       for (langsyses = Qnil, j = otf_script->LangSysCount - 1; j >= -1; j--)
  1706         {
  1707           OTF_LangSys *otf_langsys;
  1708 
  1709           if (j >= 0)
  1710             otf_langsys = otf_script->LangSys + j;
  1711           else if (otf_script->DefaultLangSysOffset)
  1712             otf_langsys = &otf_script->DefaultLangSys;
  1713           else
  1714             break;
  1715 
  1716           for (features = Qnil, k = otf_langsys->FeatureCount - 1; k >= 0; k--)
  1717             {
  1718               l = otf_langsys->FeatureIndex[k];
  1719               if (l >= gsub_gpos->FeatureList.FeatureCount)
  1720                 continue;
  1721               OTF_TAG_SYM (sym, gsub_gpos->FeatureList.Feature[l].FeatureTag);
  1722               features = Fcons (sym, features);
  1723             }
  1724           if (j >= 0)
  1725             OTF_TAG_SYM (sym, otf_script->LangSysRecord[j].LangSysTag);
  1726           else
  1727             sym = Qnil;
  1728           langsyses = Fcons (Fcons (sym, features), langsyses);
  1729         }
  1730 
  1731       OTF_TAG_SYM (sym, gsub_gpos->ScriptList.Script[i].ScriptTag);
  1732       scripts = Fcons (Fcons (sym, langsyses), scripts);
  1733     }
  1734   return scripts;
  1735 
  1736 }
  1737 
  1738 
  1739 Lisp_Object
  1740 ftfont_otf_capability (struct font *font)
  1741 {
  1742   struct font_info *ftfont_info = (struct font_info *) font;
  1743   OTF *otf = ftfont_get_otf (ftfont_info);
  1744   Lisp_Object gsub_gpos;
  1745 
  1746   if (! otf)
  1747     return Qnil;
  1748   gsub_gpos = Fcons (Qnil, Qnil);
  1749   if (OTF_get_table (otf, "GSUB") == 0
  1750       && otf->gsub->FeatureList.FeatureCount > 0)
  1751     XSETCAR (gsub_gpos, ftfont_otf_features (otf->gsub));
  1752   if (OTF_get_table (otf, "GPOS") == 0
  1753       && otf->gpos->FeatureList.FeatureCount > 0)
  1754     XSETCDR (gsub_gpos, ftfont_otf_features (otf->gpos));
  1755   return gsub_gpos;
  1756 }
  1757 
  1758 #ifdef HAVE_M17N_FLT
  1759 
  1760 #if (((LIBOTF_MAJOR_VERSION > 1) || (LIBOTF_RELEASE_NUMBER >= 10))      \
  1761      && ((M17NLIB_MAJOR_VERSION > 1) || (M17NLIB_MINOR_VERSION >= 6)))
  1762 /* We can use the new feature of libotf and m17n-flt to handle the
  1763    character encoding scheme introduced in Unicode 5.1 and 5.2 for
  1764    some Agian scripts.  */
  1765 #define M17N_FLT_USE_NEW_FEATURE
  1766 #endif
  1767 
  1768 struct MFLTFontFT
  1769 {
  1770   MFLTFont flt_font;
  1771   struct font *font;
  1772   FT_Face ft_face;
  1773   OTF *otf;
  1774   FT_Matrix *matrix;
  1775 };
  1776 
  1777 /* The actual type of elements in the array MFLTGlyphString.glyphs.
  1778    We use this structure instead of MFLTGlyph to utilize the new
  1779    feature of libotf ver.0.9.15 which requires saving and restoring
  1780    the value of OTF_GlyphString.positioning_type in the succeeding
  1781    calls of the callback function MFLTFont.drive_otf (which is set to
  1782    ftfont_drive_otf).  */
  1783 
  1784 typedef struct {
  1785   MFLTGlyph g;
  1786   unsigned int libotf_positioning_type;
  1787 } MFLTGlyphFT;
  1788 
  1789 static int
  1790 ftfont_get_glyph_id (MFLTFont *font, MFLTGlyphString *gstring,
  1791                      int from, int to)
  1792 {
  1793   struct MFLTFontFT *flt_font_ft = (struct MFLTFontFT *) font;
  1794   FT_Face ft_face = flt_font_ft->ft_face;
  1795   MFLTGlyphFT *g;
  1796 
  1797   for (g = (MFLTGlyphFT *) (gstring->glyphs) + from; from < to; g++, from++)
  1798     if (! g->g.encoded)
  1799       {
  1800         FT_UInt code = FT_Get_Char_Index (ft_face, g->g.code);
  1801 
  1802         g->g.code = code > 0 ? code : FONT_INVALID_CODE;
  1803         g->g.encoded = 1;
  1804       }
  1805   return 0;
  1806 }
  1807 
  1808 /* Operators for 26.6 fixed fractional pixel format */
  1809 
  1810 #define FLOOR(x)    ((x) & -64)
  1811 #define CEIL(x)     (((x)+63) & -64)
  1812 #define ROUND(x)    (((x)+32) & -64)
  1813 
  1814 static int
  1815 ftfont_get_metrics (MFLTFont *font, MFLTGlyphString *gstring,
  1816                     int from, int to)
  1817 {
  1818   struct MFLTFontFT *flt_font_ft = (struct MFLTFontFT *) font;
  1819   FT_Face ft_face = flt_font_ft->ft_face;
  1820   MFLTGlyphFT *g;
  1821 
  1822   for (g = (MFLTGlyphFT *) (gstring->glyphs) + from; from < to; g++, from++)
  1823     if (! g->g.measured)
  1824       {
  1825         if (g->g.code != FONT_INVALID_CODE)
  1826           {
  1827             FT_Glyph_Metrics *m;
  1828 
  1829             if (FT_Load_Glyph (ft_face, g->g.code, FT_LOAD_DEFAULT) != 0
  1830                 && FT_Load_Glyph (ft_face, g->g.code, FT_LOAD_NO_HINTING) != 0)
  1831               emacs_abort ();
  1832             m = &ft_face->glyph->metrics;
  1833             if (flt_font_ft->matrix)
  1834               {
  1835                 FT_Vector v[4];
  1836                 int i;
  1837 
  1838                 v[0].x = v[1].x = m->horiBearingX;
  1839                 v[2].x = v[3].x = m->horiBearingX + m->width;
  1840                 v[0].y = v[2].y = m->horiBearingY;
  1841                 v[1].y = v[3].y = m->horiBearingY - m->height;
  1842                 for (i = 0; i < 4; i++)
  1843                   FT_Vector_Transform (v + i, flt_font_ft->matrix);
  1844                 g->g.lbearing = v[0].x < v[1].x ? FLOOR (v[0].x) : FLOOR (v[1].x);
  1845                 g->g.rbearing = v[2].x > v[3].x ? CEIL (v[2].x) : CEIL (v[3].x);
  1846                 g->g.ascent = v[0].y > v[2].y ? CEIL (v[0].y) : CEIL (v[2].y);
  1847                 g->g.descent = v[1].y < v[3].y ? - FLOOR (v[1].y) : - FLOOR (v[3].y);
  1848               }
  1849             else
  1850               {
  1851                 g->g.lbearing = FLOOR (m->horiBearingX);
  1852                 g->g.rbearing = CEIL (m->horiBearingX + m->width);
  1853                 g->g.ascent = CEIL (m->horiBearingY);
  1854                 g->g.descent = - FLOOR (m->horiBearingY - m->height);
  1855               }
  1856             g->g.xadv = ROUND (ft_face->glyph->advance.x);
  1857           }
  1858         else
  1859           {
  1860             g->g.lbearing = 0;
  1861             g->g.rbearing = g->g.xadv = flt_font_ft->font->space_width << 6;
  1862             g->g.ascent = flt_font_ft->font->ascent << 6;
  1863             g->g.descent = flt_font_ft->font->descent << 6;
  1864           }
  1865         g->g.yadv = 0;
  1866         g->g.measured = 1;
  1867       }
  1868   return 0;
  1869 }
  1870 
  1871 static int
  1872 ftfont_check_otf (MFLTFont *font, MFLTOtfSpec *spec)
  1873 {
  1874 #define FEATURE_NONE(IDX) (! spec->features[IDX])
  1875 
  1876 #define FEATURE_ANY(IDX)        \
  1877   (spec->features[IDX]          \
  1878    && spec->features[IDX][0] == 0xFFFFFFFF && spec->features[IDX][1] == 0)
  1879 
  1880   struct MFLTFontFT *flt_font_ft = (struct MFLTFontFT *) font;
  1881   OTF *otf = flt_font_ft->otf;
  1882   OTF_Tag *tags;
  1883   int i, n;
  1884   bool negative;
  1885 
  1886   if (FEATURE_ANY (0) && FEATURE_ANY (1))
  1887     /* Return true iff any of GSUB or GPOS support the script (and
  1888        language).  */
  1889     return (otf
  1890             && (OTF_check_features (otf, 0, spec->script, spec->langsys,
  1891                                     NULL, 0) > 0
  1892                 || OTF_check_features (otf, 1, spec->script, spec->langsys,
  1893                                        NULL, 0) > 0));
  1894 
  1895   for (i = 0; i < 2; i++)
  1896     if (! FEATURE_ANY (i))
  1897       {
  1898         if (FEATURE_NONE (i))
  1899           {
  1900             if (otf
  1901                 && OTF_check_features (otf, i == 0, spec->script, spec->langsys,
  1902                                        NULL, 0) > 0)
  1903               return 0;
  1904             continue;
  1905           }
  1906         if (spec->features[i][0] == 0xFFFFFFFF)
  1907           {
  1908             if (! otf
  1909                 || OTF_check_features (otf, i == 0, spec->script, spec->langsys,
  1910                                        NULL, 0) <= 0)
  1911               continue;
  1912           }
  1913         else if (! otf)
  1914           return 0;
  1915         for (n = 1; spec->features[i][n]; n++);
  1916         USE_SAFE_ALLOCA;
  1917         SAFE_NALLOCA (tags, 1, n);
  1918         for (n = 0, negative = 0; spec->features[i][n]; n++)
  1919           {
  1920             if (spec->features[i][n] == 0xFFFFFFFF)
  1921               negative = 1;
  1922             else if (negative)
  1923               tags[n - 1] = spec->features[i][n] | 0x80000000;
  1924             else
  1925               tags[n] = spec->features[i][n];
  1926           }
  1927         bool passed = true;
  1928 #ifndef M17N_FLT_USE_NEW_FEATURE
  1929         passed = n - negative > 0;
  1930 #endif
  1931         if (passed)
  1932           passed = (OTF_check_features (otf, i == 0, spec->script,
  1933                                         spec->langsys, tags, n - negative)
  1934                     != 1);
  1935         SAFE_FREE ();
  1936         if (passed)
  1937           return 0;
  1938       }
  1939   return 1;
  1940 #undef FEATURE_NONE
  1941 #undef FEATURE_ANY
  1942 }
  1943 
  1944 #define DEVICE_DELTA(table, size)                               \
  1945   (((size) >= (table).StartSize && (size) <= (table).EndSize)   \
  1946    ? (table).DeltaValue[(size) - (table).StartSize] << 6        \
  1947    : 0)
  1948 
  1949 static void
  1950 adjust_anchor (FT_Face ft_face, OTF_Anchor *anchor,
  1951                unsigned code, int x_ppem, int y_ppem, int *x, int *y)
  1952 {
  1953   if (anchor->AnchorFormat == 2)
  1954     {
  1955       FT_Outline *outline;
  1956       int ap = anchor->f.f1.AnchorPoint;
  1957 
  1958       FT_Load_Glyph (ft_face, (FT_UInt) code, FT_LOAD_MONOCHROME);
  1959       outline = &ft_face->glyph->outline;
  1960       if (ap < outline->n_points)
  1961         {
  1962           *x = outline->points[ap].x << 6;
  1963           *y = outline->points[ap].y << 6;
  1964         }
  1965     }
  1966   else if (anchor->AnchorFormat == 3)
  1967     {
  1968       if (anchor->f.f2.XDeviceTable.offset
  1969           && anchor->f.f2.XDeviceTable.DeltaValue)
  1970         *x += DEVICE_DELTA (anchor->f.f2.XDeviceTable, x_ppem);
  1971       if (anchor->f.f2.YDeviceTable.offset
  1972           && anchor->f.f2.YDeviceTable.DeltaValue)
  1973         *y += DEVICE_DELTA (anchor->f.f2.YDeviceTable, y_ppem);
  1974     }
  1975 }
  1976 
  1977 static OTF_GlyphString otf_gstring;
  1978 
  1979 static void
  1980 setup_otf_gstring (int size)
  1981 {
  1982   if (otf_gstring.size < size)
  1983     {
  1984       ptrdiff_t new_size = otf_gstring.size;
  1985       xfree (otf_gstring.glyphs);
  1986       otf_gstring.glyphs = xpalloc (NULL, &new_size, size - otf_gstring.size,
  1987                                     INT_MAX, sizeof *otf_gstring.glyphs);
  1988       otf_gstring.size = new_size;
  1989     }
  1990   otf_gstring.used = size;
  1991   memset (otf_gstring.glyphs, 0, sizeof (OTF_Glyph) * size);
  1992 }
  1993 
  1994 #ifdef M17N_FLT_USE_NEW_FEATURE
  1995 
  1996 /* Pack 32-bit OTF tag (0x7F7F7F7F) into 28-bit (0x0FFFFFFF).  */
  1997 #define PACK_OTF_TAG(TAG)       \
  1998   ((((TAG) & 0x7F000000) >> 3)  \
  1999     | (((TAG) & 0x7F0000) >> 2) \
  2000     | (((TAG) & 0x7F00) >> 1)   \
  2001     | ((TAG) & 0x7F))
  2002 
  2003 /* Assuming that FONT is an OpenType font, apply OpenType features
  2004    specified in SPEC on glyphs between FROM and TO of IN, and record
  2005    the lastly applied feature in each glyph of IN.  If OUT is not
  2006    NULL, append the resulting glyphs to OUT while storing glyph
  2007    position adjustment information in ADJUSTMENT.  */
  2008 
  2009 static int
  2010 ftfont_drive_otf (MFLTFont *font,
  2011                   MFLTOtfSpec *spec,
  2012                   MFLTGlyphString *in,
  2013                   int from,
  2014                   int to,
  2015                   MFLTGlyphString *out,
  2016                   MFLTGlyphAdjustment *adjustment)
  2017 {
  2018   struct MFLTFontFT *flt_font_ft = (struct MFLTFontFT *) font;
  2019   MFLTGlyphFT *in_glyphs = (MFLTGlyphFT *) (in->glyphs) + from;
  2020   MFLTGlyphFT *out_glyphs = out ? (MFLTGlyphFT *) (out->glyphs) : NULL;
  2021   FT_Face ft_face = flt_font_ft->ft_face;
  2022   OTF *otf = flt_font_ft->otf;
  2023   int len = to - from;
  2024   int i, j, gidx;
  2025   OTF_Glyph *otfg;
  2026   char script[5], *langsys = NULL;
  2027   char *gsub_features = NULL, *gpos_features = NULL;
  2028   OTF_Feature *features;
  2029 
  2030   if (len == 0)
  2031     return from;
  2032   OTF_tag_name (spec->script, script);
  2033 
  2034   char langsysbuf[5];
  2035   if (spec->langsys)
  2036     {
  2037       langsys = langsysbuf;
  2038       OTF_tag_name (spec->langsys, langsys);
  2039     }
  2040 
  2041   USE_SAFE_ALLOCA;
  2042   for (i = 0; i < 2; i++)
  2043     {
  2044       char *p;
  2045 
  2046       if (spec->features[i] && spec->features[i][1] != 0xFFFFFFFF)
  2047         {
  2048           for (j = 0; spec->features[i][j]; j++);
  2049           SAFE_NALLOCA (p, 6, j);
  2050           if (i == 0)
  2051             gsub_features = p;
  2052           else
  2053             gpos_features = p;
  2054           for (j = 0; spec->features[i][j]; j++)
  2055             {
  2056               if (spec->features[i][j] == 0xFFFFFFFF)
  2057                 *p++ = '*', *p++ = ',';
  2058               else
  2059                 {
  2060                   OTF_tag_name (spec->features[i][j], p);
  2061                   p[4] = ',';
  2062                   p += 5;
  2063                 }
  2064             }
  2065           *--p = '\0';
  2066         }
  2067     }
  2068 
  2069   setup_otf_gstring (len);
  2070   for (i = 0; i < len; i++)
  2071     {
  2072       otf_gstring.glyphs[i].c = in_glyphs[i].g.c & 0x11FFFF;
  2073       otf_gstring.glyphs[i].glyph_id = in_glyphs[i].g.code;
  2074 #ifdef OTF_POSITIONING_TYPE_GET_FORMAT
  2075       otf_gstring.glyphs[i].positioning_type = in_glyphs[i].libotf_positioning_type;
  2076 #endif
  2077     }
  2078 
  2079   OTF_drive_gdef (otf, &otf_gstring);
  2080   gidx = out ? out->used : from;
  2081 
  2082   if (gsub_features && out)
  2083     {
  2084 #ifdef OTF_POSITIONING_TYPE_GET_FORMAT
  2085       if (OTF_drive_gsub_features (otf, &otf_gstring, script, langsys,
  2086                                    gsub_features) < 0)
  2087         goto simple_copy;
  2088 #else
  2089       if (OTF_drive_gsub_with_log (otf, &otf_gstring, script, langsys,
  2090                                    gsub_features) < 0)
  2091         goto simple_copy;
  2092 #endif
  2093       if (out->allocated < out->used + otf_gstring.used)
  2094         {
  2095           SAFE_FREE ();
  2096           return -2;
  2097         }
  2098       features = otf->gsub->FeatureList.Feature;
  2099       for (i = 0, otfg = otf_gstring.glyphs; i < otf_gstring.used; )
  2100         {
  2101           MFLTGlyphFT *g;
  2102           int min_from, max_to;
  2103           int feature_idx;
  2104 
  2105 #ifdef OTF_POSITIONING_TYPE_GET_FORMAT
  2106           feature_idx = OTF_POSITIONING_TYPE_GET_FEATURE (otfg);
  2107 #else
  2108           feature_idx = otfg->positioning_type >> 4;
  2109 #endif
  2110           g = out_glyphs + out->used;
  2111           *g = in_glyphs[otfg->f.index.from];
  2112           if (g->g.code != otfg->glyph_id)
  2113             {
  2114               g->g.c = 0;
  2115               g->g.code = otfg->glyph_id;
  2116               g->g.measured = 0;
  2117             }
  2118           out->used++;
  2119           min_from = g->g.from;
  2120           max_to = g->g.to;
  2121           if (otfg->f.index.from < otfg->f.index.to)
  2122             {
  2123               /* OTFG substitutes multiple glyphs in IN.  */
  2124               for (j = otfg->f.index.from + 1; j <= otfg->f.index.to; j++)
  2125                 {
  2126                   if (min_from > in_glyphs[j].g.from)
  2127                     min_from = in_glyphs[j].g.from;
  2128                   if (max_to < in_glyphs[j].g.to)
  2129                     max_to = in_glyphs[j].g.to;
  2130                 }
  2131               g->g.from = min_from;
  2132               g->g.to = max_to;
  2133             }
  2134           if (feature_idx)
  2135             {
  2136               unsigned int tag = features[feature_idx - 1].FeatureTag;
  2137               tag = PACK_OTF_TAG (tag);
  2138               g->g.internal = (g->g.internal & ~0x1FFFFFFF) | tag;
  2139             }
  2140 #ifdef OTF_POSITIONING_TYPE_GET_FORMAT
  2141           g->libotf_positioning_type
  2142             = otfg->positioning_type & OTF_positioning_type_components_mask;
  2143 #endif
  2144           for (i++, otfg++; (i < otf_gstring.used
  2145                              && otfg->f.index.from == otfg[-1].f.index.from);
  2146                i++, otfg++)
  2147             {
  2148               g = out_glyphs + out->used;
  2149               *g = in_glyphs[otfg->f.index.to];
  2150               if (g->g.code != otfg->glyph_id)
  2151                 {
  2152                   g->g.c = 0;
  2153                   g->g.code = otfg->glyph_id;
  2154                   g->g.measured = 0;
  2155                 }
  2156 #ifdef OTF_POSITIONING_TYPE_GET_FORMAT
  2157               feature_idx = OTF_POSITIONING_TYPE_GET_FEATURE (otfg);
  2158 #else
  2159               feature_idx = otfg->positioning_type >> 4;
  2160 #endif
  2161               if (feature_idx)
  2162                 {
  2163                   unsigned int tag = features[feature_idx - 1].FeatureTag;
  2164                   tag = PACK_OTF_TAG (tag);
  2165                   g->g.internal = (g->g.internal & ~0x1FFFFFFF) | tag;
  2166                 }
  2167 #ifdef OTF_POSITIONING_TYPE_GET_FORMAT
  2168               g->libotf_positioning_type
  2169                 = otfg->positioning_type & OTF_positioning_type_components_mask;
  2170 #endif
  2171               out->used++;
  2172             }
  2173         }
  2174     }
  2175   else if (gsub_features)
  2176     {
  2177       /* Just for checking which features will be applied.  */
  2178 #ifdef OTF_POSITIONING_TYPE_GET_FORMAT
  2179       if (OTF_drive_gsub_features (otf, &otf_gstring, script, langsys,
  2180                                    gsub_features) < 0)
  2181         goto simple_copy;
  2182 #else
  2183       if (OTF_drive_gsub_with_log (otf, &otf_gstring, script, langsys,
  2184                                    gsub_features) < 0)
  2185         goto simple_copy;
  2186 #endif
  2187       features = otf->gsub->FeatureList.Feature;
  2188       for (i = 0, otfg = otf_gstring.glyphs; i < otf_gstring.used; i++,
  2189              otfg++)
  2190         {
  2191           int feature_idx;
  2192 #ifdef OTF_POSITIONING_TYPE_GET_FORMAT
  2193           feature_idx = OTF_POSITIONING_TYPE_GET_FEATURE (otfg);
  2194 #else
  2195           feature_idx = otfg->positioning_type >> 4;
  2196 #endif
  2197           if (feature_idx)
  2198             {
  2199               unsigned int tag = features[feature_idx - 1].FeatureTag;
  2200               tag = PACK_OTF_TAG (tag);
  2201               for (j = otfg->f.index.from; j <= otfg->f.index.to; j++)
  2202                 {
  2203                   MFLTGlyphFT *g = in_glyphs + j;
  2204                   g->g.internal = (g->g.internal & ~0x1FFFFFFF) | tag;
  2205                 }
  2206             }
  2207         }
  2208     }
  2209   else if (out)
  2210     {
  2211       if (out->allocated < out->used + len)
  2212         {
  2213           SAFE_FREE ();
  2214           return -2;
  2215         }
  2216       for (i = 0; i < len; i++)
  2217         out_glyphs[out->used++] = in_glyphs[i];
  2218     }
  2219 
  2220   if (gpos_features && out)
  2221     {
  2222       MFLTGlyphFT *base = NULL, *mark = NULL, *g;
  2223       int x_ppem, y_ppem, x_scale, y_scale;
  2224 
  2225 #ifdef OTF_POSITIONING_TYPE_GET_FORMAT
  2226       if (OTF_drive_gpos_features (otf, &otf_gstring, script, langsys,
  2227                                    gpos_features) < 0)
  2228         {
  2229           SAFE_FREE ();
  2230           return to;
  2231         }
  2232 #else
  2233       if (OTF_drive_gpos_with_log (otf, &otf_gstring, script, langsys,
  2234                                    gpos_features) < 0)
  2235         {
  2236           SAFE_FREE ();
  2237           return to;
  2238         }
  2239 #endif
  2240       features = otf->gpos->FeatureList.Feature;
  2241       x_ppem = ft_face->size->metrics.x_ppem;
  2242       y_ppem = ft_face->size->metrics.y_ppem;
  2243       x_scale = ft_face->size->metrics.x_scale;
  2244       y_scale = ft_face->size->metrics.y_scale;
  2245 
  2246       for (i = 0, otfg = otf_gstring.glyphs, g = out_glyphs + gidx;
  2247            i < otf_gstring.used; i++, otfg++)
  2248         {
  2249           MFLTGlyphAdjustment *adjust = adjustment;
  2250           MFLTGlyphFT *prev;
  2251           int positioning_type, feature_idx;
  2252 
  2253 #ifdef OTF_POSITIONING_TYPE_GET_FORMAT
  2254           positioning_type = OTF_POSITIONING_TYPE_GET_FORMAT (otfg);
  2255           feature_idx = OTF_POSITIONING_TYPE_GET_FEATURE (otfg);
  2256 #else
  2257           positioning_type = otfg->positioning_type & 0xF;
  2258           feature_idx = otfg->positioning_type >> 4;
  2259 #endif
  2260           if (feature_idx)
  2261             {
  2262               unsigned int tag = features[feature_idx - 1].FeatureTag;
  2263               tag = PACK_OTF_TAG (tag);
  2264               g->g.internal = (g->g.internal & ~0x1FFFFFFF) | tag;
  2265             }
  2266 
  2267           if (! otfg->glyph_id)
  2268             /* This is a pseudo glyph that contains positioning
  2269                information to be accumulated to a real glyph.  */
  2270             adjust--;
  2271           switch (positioning_type)
  2272             {
  2273             case 0:
  2274               break;
  2275             case 1:             /* Single */
  2276             case 2:             /* Pair */
  2277               {
  2278                 int format = otfg->f.f1.format;
  2279 
  2280                 if (format & OTF_XPlacement)
  2281                   adjust->xoff
  2282                     = otfg->f.f1.value->XPlacement * x_scale / 0x10000;
  2283                 if (format & OTF_XPlaDevice)
  2284                   adjust->xoff
  2285                     += DEVICE_DELTA (otfg->f.f1.value->XPlaDevice, x_ppem);
  2286                 if (format & OTF_YPlacement)
  2287                   adjust->yoff
  2288                     = - (otfg->f.f1.value->YPlacement * y_scale / 0x10000);
  2289                 if (format & OTF_YPlaDevice)
  2290                   adjust->yoff
  2291                     -= DEVICE_DELTA (otfg->f.f1.value->YPlaDevice, y_ppem);
  2292                 if (format & OTF_XAdvance)
  2293                   adjust->xadv
  2294                     += otfg->f.f1.value->XAdvance * x_scale / 0x10000;
  2295                 if (format & OTF_XAdvDevice)
  2296                   adjust->xadv
  2297                     += DEVICE_DELTA (otfg->f.f1.value->XAdvDevice, x_ppem);
  2298                 if (format & OTF_YAdvance)
  2299                   adjust->yadv
  2300                     += otfg->f.f1.value->YAdvance * y_scale / 0x10000;
  2301                 if (format & OTF_YAdvDevice)
  2302                   adjust->yadv
  2303                     += DEVICE_DELTA (otfg->f.f1.value->YAdvDevice, y_ppem);
  2304                 adjust->set = 1;
  2305               }
  2306               break;
  2307             case 3:             /* Cursive */
  2308               /* Not yet supported.  */
  2309               break;
  2310             case 4:             /* Mark-to-Base */
  2311             case 5:             /* Mark-to-Ligature */
  2312               if (! base)
  2313                 break;
  2314               prev = base;
  2315               goto label_adjust_anchor;
  2316             default:            /* i.e. case 6 Mark-to-Mark */
  2317               if (! mark)
  2318                 break;
  2319               prev = mark;
  2320 #ifdef OTF_POSITIONING_TYPE_GET_FORMAT
  2321                   {
  2322                     int distance = OTF_POSITIONING_TYPE_GET_MARKDISTANCE (otfg);
  2323 
  2324                     if (distance > 0)
  2325                       {
  2326                         prev = g - distance;
  2327                         if (prev < out_glyphs)
  2328                           prev = mark;
  2329                       }
  2330                   }
  2331 #endif
  2332 
  2333             label_adjust_anchor:
  2334               {
  2335                 int base_x, base_y, mark_x, mark_y;
  2336                 int this_from, this_to;
  2337 
  2338                 base_x = otfg->f.f4.base_anchor->XCoordinate * x_scale / 0x10000;
  2339                 base_y = otfg->f.f4.base_anchor->YCoordinate * y_scale / 0x10000;
  2340                 mark_x = otfg->f.f4.mark_anchor->XCoordinate * x_scale / 0x10000;
  2341                 mark_y = otfg->f.f4.mark_anchor->YCoordinate * y_scale / 0x10000;
  2342 
  2343                 if (otfg->f.f4.base_anchor->AnchorFormat != 1)
  2344                   adjust_anchor (ft_face, otfg->f.f4.base_anchor, prev->g.code,
  2345                                  x_ppem, y_ppem, &base_x, &base_y);
  2346                 if (otfg->f.f4.mark_anchor->AnchorFormat != 1)
  2347                   adjust_anchor (ft_face, otfg->f.f4.mark_anchor, g->g.code,
  2348                                  x_ppem, y_ppem, &mark_x, &mark_y);
  2349                 adjust->xoff = (base_x - mark_x);
  2350                 adjust->yoff = - (base_y - mark_y);
  2351                 adjust->back = (g - prev);
  2352                 adjust->xadv = 0;
  2353                 adjust->advance_is_absolute = 1;
  2354                 adjust->set = 1;
  2355                 this_from = g->g.from;
  2356                 this_to = g->g.to;
  2357                 for (j = 0; prev + j < g; j++)
  2358                   {
  2359                     if (this_from > prev[j].g.from)
  2360                       this_from = prev[j].g.from;
  2361                     if (this_to < prev[j].g.to)
  2362                       this_to = prev[j].g.to;
  2363                   }
  2364                 for (; prev <= g; prev++)
  2365                   {
  2366                     prev->g.from = this_from;
  2367                     prev->g.to = this_to;
  2368                   }
  2369               }
  2370             }
  2371           if (otfg->glyph_id)
  2372             {
  2373               if (otfg->GlyphClass == OTF_GlyphClass0)
  2374                 base = mark = g;
  2375               else if (otfg->GlyphClass == OTF_GlyphClassMark)
  2376                 mark = g;
  2377               else
  2378                 base = g;
  2379               g++, adjustment++;
  2380             }
  2381         }
  2382     }
  2383   else if (gpos_features)
  2384     {
  2385       if (OTF_drive_gpos_with_log (otf, &otf_gstring, script, langsys,
  2386                                    gpos_features) < 0)
  2387         {
  2388           SAFE_FREE ();
  2389           return to;
  2390         }
  2391       features = otf->gpos->FeatureList.Feature;
  2392       for (i = 0, otfg = otf_gstring.glyphs; i < otf_gstring.used;
  2393            i++, otfg++)
  2394         if (otfg->positioning_type & 0xF)
  2395           {
  2396             int feature_idx = otfg->positioning_type >> 4;
  2397 
  2398             if (feature_idx)
  2399               {
  2400                 unsigned int tag = features[feature_idx - 1].FeatureTag;
  2401                 tag = PACK_OTF_TAG (tag);
  2402                 for (j = otfg->f.index.from; j <= otfg->f.index.to; j++)
  2403                   {
  2404                     MFLTGlyphFT *g = in_glyphs + j;
  2405                     g->g.internal = (g->g.internal & ~0x1FFFFFFF) | tag;
  2406                   }
  2407               }
  2408           }
  2409     }
  2410   SAFE_FREE ();
  2411   return to;
  2412 
  2413  simple_copy:
  2414   SAFE_FREE ();
  2415   if (! out)
  2416     return to;
  2417   if (out->allocated < out->used + len)
  2418     return -2;
  2419   font->get_metrics (font, in, from, to);
  2420   memcpy (out->glyphs + out->used, in_glyphs, sizeof (MFLTGlyphFT) * len);
  2421   out->used += len;
  2422   return to;
  2423 }
  2424 
  2425 static int
  2426 ftfont_try_otf (MFLTFont *font, MFLTOtfSpec *spec,
  2427                 MFLTGlyphString *in, int from, int to)
  2428 {
  2429   return ftfont_drive_otf (font, spec, in, from, to, NULL, NULL);
  2430 }
  2431 
  2432 #else  /* not M17N_FLT_USE_NEW_FEATURE */
  2433 
  2434 static int
  2435 ftfont_drive_otf (MFLTFont *font, MFLTOtfSpec *spec, MFLTGlyphString *in,
  2436                   int from, int to,
  2437                   MFLTGlyphString *out, MFLTGlyphAdjustment *adjustment)
  2438 {
  2439   struct MFLTFontFT *flt_font_ft = (struct MFLTFontFT *) font;
  2440   MFLTGlyphFT *in_glyphs = (MFLTGlyphFT *) (in->glyphs) + from;
  2441   MFLTGlyphFT *out_glyphs = out ? (MFLTGlyphFT *) (out->glyphs) : NULL;
  2442   FT_Face ft_face = flt_font_ft->ft_face;
  2443   OTF *otf = flt_font_ft->otf;
  2444   int len = to - from;
  2445   int i, j, gidx;
  2446   OTF_Glyph *otfg;
  2447   char script[5], *langsys = NULL;
  2448   char *gsub_features = NULL, *gpos_features = NULL;
  2449 
  2450   if (len == 0)
  2451     return from;
  2452   OTF_tag_name (spec->script, script);
  2453 
  2454   char langsysbuf[5];
  2455   if (spec->langsys)
  2456     {
  2457       langsys = langsysbuf;
  2458       OTF_tag_name (spec->langsys, langsys);
  2459     }
  2460 
  2461   USE_SAFE_ALLOCA;
  2462   for (i = 0; i < 2; i++)
  2463     {
  2464       char *p;
  2465 
  2466       if (spec->features[i] && spec->features[i][1] != 0xFFFFFFFF)
  2467         {
  2468           for (j = 0; spec->features[i][j]; j++);
  2469           SAFE_NALLOCA (p, 6, j);
  2470           if (i == 0)
  2471             gsub_features = p;
  2472           else
  2473             gpos_features = p;
  2474           for (j = 0; spec->features[i][j]; j++)
  2475             {
  2476               if (spec->features[i][j] == 0xFFFFFFFF)
  2477                 *p++ = '*', *p++ = ',';
  2478               else
  2479                 {
  2480                   OTF_tag_name (spec->features[i][j], p);
  2481                   p[4] = ',';
  2482                   p += 5;
  2483                 }
  2484             }
  2485           *--p = '\0';
  2486         }
  2487     }
  2488 
  2489   setup_otf_gstring (len);
  2490   for (i = 0; i < len; i++)
  2491     {
  2492       otf_gstring.glyphs[i].c = in_glyphs[i].g.c;
  2493       otf_gstring.glyphs[i].glyph_id = in_glyphs[i].g.code;
  2494     }
  2495 
  2496   OTF_drive_gdef (otf, &otf_gstring);
  2497   gidx = out->used;
  2498 
  2499   if (gsub_features)
  2500     {
  2501       if (OTF_drive_gsub (otf, &otf_gstring, script, langsys, gsub_features)
  2502           < 0)
  2503         goto simple_copy;
  2504       if (out->allocated < out->used + otf_gstring.used)
  2505         {
  2506           SAFE_FREE ();
  2507           return -2;
  2508         }
  2509       for (i = 0, otfg = otf_gstring.glyphs; i < otf_gstring.used; )
  2510         {
  2511           MFLTGlyphFT *g;
  2512           int min_from, max_to;
  2513           int j;
  2514 
  2515           g = out_glyphs + out->used;
  2516           *g = in_glyphs[otfg->f.index.from];
  2517           if (g->g.code != otfg->glyph_id)
  2518             {
  2519               g->g.c = 0;
  2520               g->g.code = otfg->glyph_id;
  2521               g->g.measured = 0;
  2522             }
  2523           out->used++;
  2524           min_from = g->g.from;
  2525           max_to = g->g.to;
  2526           if (otfg->f.index.from < otfg->f.index.to)
  2527             {
  2528               /* OTFG substitutes multiple glyphs in IN.  */
  2529               for (j = from + otfg->f.index.from + 1;
  2530                    j <= from + otfg->f.index.to; j++)
  2531                 {
  2532                   if (min_from > in->glyphs[j].from)
  2533                     min_from = in->glyphs[j].from;
  2534                   if (max_to < in->glyphs[j].to)
  2535                     max_to = in->glyphs[j].to;
  2536                 }
  2537               g->g.from = min_from;
  2538               g->g.to = max_to;
  2539             }
  2540           for (i++, otfg++; (i < otf_gstring.used
  2541                              && otfg->f.index.from == otfg[-1].f.index.from);
  2542                i++, otfg++)
  2543             {
  2544               g = out_glyphs + out->used;
  2545               *g = in_glyphs[otfg->f.index.to];
  2546               if (g->g.code != otfg->glyph_id)
  2547                 {
  2548                   g->g.c = 0;
  2549                   g->g.code = otfg->glyph_id;
  2550                   g->g.measured = 0;
  2551                 }
  2552               out->used++;
  2553             }
  2554         }
  2555     }
  2556   else
  2557     {
  2558       if (out->allocated < out->used + len)
  2559         {
  2560           SAFE_FREE ();
  2561           return -2;
  2562         }
  2563       for (i = 0; i < len; i++)
  2564         out_glyphs[out->used++] = in_glyphs[i];
  2565     }
  2566 
  2567   if (gpos_features)
  2568     {
  2569       MFLTGlyphFT *base = NULL, *mark = NULL, *g;
  2570       int x_ppem, y_ppem, x_scale, y_scale;
  2571 
  2572       if (OTF_drive_gpos (otf, &otf_gstring, script, langsys, gpos_features)
  2573           < 0)
  2574         {
  2575           SAFE_FREE ();
  2576           return to;
  2577         }
  2578 
  2579       x_ppem = ft_face->size->metrics.x_ppem;
  2580       y_ppem = ft_face->size->metrics.y_ppem;
  2581       x_scale = ft_face->size->metrics.x_scale;
  2582       y_scale = ft_face->size->metrics.y_scale;
  2583 
  2584       for (i = 0, otfg = otf_gstring.glyphs, g = out_glyphs + gidx;
  2585            i < otf_gstring.used; i++, otfg++, g++)
  2586         {
  2587           MFLTGlyphFT *prev;
  2588 
  2589           if (! otfg->glyph_id)
  2590             continue;
  2591           switch (otfg->positioning_type)
  2592             {
  2593             case 0:
  2594               break;
  2595             case 1:             /* Single */
  2596             case 2:             /* Pair */
  2597               {
  2598                 int format = otfg->f.f1.format;
  2599 
  2600                 if (format & OTF_XPlacement)
  2601                   adjustment[i].xoff
  2602                     = otfg->f.f1.value->XPlacement * x_scale / 0x10000;
  2603                 if (format & OTF_XPlaDevice)
  2604                   adjustment[i].xoff
  2605                     += DEVICE_DELTA (otfg->f.f1.value->XPlaDevice, x_ppem);
  2606                 if (format & OTF_YPlacement)
  2607                   adjustment[i].yoff
  2608                     = - (otfg->f.f1.value->YPlacement * y_scale / 0x10000);
  2609                 if (format & OTF_YPlaDevice)
  2610                   adjustment[i].yoff
  2611                     -= DEVICE_DELTA (otfg->f.f1.value->YPlaDevice, y_ppem);
  2612                 if (format & OTF_XAdvance)
  2613                   adjustment[i].xadv
  2614                     += otfg->f.f1.value->XAdvance * x_scale / 0x10000;
  2615                 if (format & OTF_XAdvDevice)
  2616                   adjustment[i].xadv
  2617                     += DEVICE_DELTA (otfg->f.f1.value->XAdvDevice, x_ppem);
  2618                 if (format & OTF_YAdvance)
  2619                   adjustment[i].yadv
  2620                     += otfg->f.f1.value->YAdvance * y_scale / 0x10000;
  2621                 if (format & OTF_YAdvDevice)
  2622                   adjustment[i].yadv
  2623                     += DEVICE_DELTA (otfg->f.f1.value->YAdvDevice, y_ppem);
  2624                 adjustment[i].set = 1;
  2625               }
  2626               break;
  2627             case 3:             /* Cursive */
  2628               /* Not yet supported.  */
  2629               break;
  2630             case 4:             /* Mark-to-Base */
  2631             case 5:             /* Mark-to-Ligature */
  2632               if (! base)
  2633                 break;
  2634               prev = base;
  2635               goto label_adjust_anchor;
  2636             default:            /* i.e. case 6 Mark-to-Mark */
  2637               if (! mark)
  2638                 break;
  2639               prev = mark;
  2640 
  2641             label_adjust_anchor:
  2642               {
  2643                 int base_x, base_y, mark_x, mark_y;
  2644                 int this_from, this_to;
  2645 
  2646                 base_x = otfg->f.f4.base_anchor->XCoordinate * x_scale / 0x10000;
  2647                 base_y = otfg->f.f4.base_anchor->YCoordinate * y_scale / 0x10000;
  2648                 mark_x = otfg->f.f4.mark_anchor->XCoordinate * x_scale / 0x10000;
  2649                 mark_y = otfg->f.f4.mark_anchor->YCoordinate * y_scale / 0x10000;
  2650 
  2651                 if (otfg->f.f4.base_anchor->AnchorFormat != 1)
  2652                   adjust_anchor (ft_face, otfg->f.f4.base_anchor, prev->g.code,
  2653                                  x_ppem, y_ppem, &base_x, &base_y);
  2654                 if (otfg->f.f4.mark_anchor->AnchorFormat != 1)
  2655                   adjust_anchor (ft_face, otfg->f.f4.mark_anchor, g->g.code,
  2656                                  x_ppem, y_ppem, &mark_x, &mark_y);
  2657                 adjustment[i].xoff = (base_x - mark_x);
  2658                 adjustment[i].yoff = - (base_y - mark_y);
  2659                 adjustment[i].back = (g - prev);
  2660                 adjustment[i].xadv = 0;
  2661                 adjustment[i].advance_is_absolute = 1;
  2662                 adjustment[i].set = 1;
  2663                 this_from = g->g.from;
  2664                 this_to = g->g.to;
  2665                 for (j = 0; prev + j < g; j++)
  2666                   {
  2667                     if (this_from > prev[j].g.from)
  2668                       this_from = prev[j].g.from;
  2669                     if (this_to < prev[j].g.to)
  2670                       this_to = prev[j].g.to;
  2671                   }
  2672                 for (; prev <= g; prev++)
  2673                   {
  2674                     prev->g.from = this_from;
  2675                     prev->g.to = this_to;
  2676                   }
  2677               }
  2678             }
  2679           if (otfg->GlyphClass == OTF_GlyphClass0)
  2680             base = mark = g;
  2681           else if (otfg->GlyphClass == OTF_GlyphClassMark)
  2682             mark = g;
  2683           else
  2684             base = g;
  2685         }
  2686     }
  2687   SAFE_FREE ();
  2688   return to;
  2689 
  2690  simple_copy:
  2691   SAFE_FREE ();
  2692   if (out->allocated < out->used + len)
  2693     return -2;
  2694   font->get_metrics (font, in, from, to);
  2695   memcpy (out_glyphs + out->used, in_glyphs,
  2696           sizeof (MFLTGlyphFT) * len);
  2697   out->used += len;
  2698   return to;
  2699 }
  2700 
  2701 #endif  /* not M17N_FLT_USE_NEW_FEATURE */
  2702 
  2703 static MFLTGlyphString gstring;
  2704 
  2705 static bool m17n_flt_initialized;
  2706 
  2707 static Lisp_Object
  2708 ftfont_shape_by_flt (Lisp_Object lgstring, struct font *font,
  2709                      FT_Face ft_face, OTF *otf, FT_Matrix *matrix)
  2710 {
  2711   ptrdiff_t len = LGSTRING_GLYPH_LEN (lgstring);
  2712   ptrdiff_t i;
  2713   struct MFLTFontFT flt_font_ft;
  2714   MFLT *flt = NULL;
  2715   bool with_variation_selector = false;
  2716 
  2717   if (! m17n_flt_initialized)
  2718     {
  2719       M17N_INIT ();
  2720 #ifdef M17N_FLT_USE_NEW_FEATURE
  2721       mflt_enable_new_feature = 1;
  2722       mflt_try_otf = ftfont_try_otf;
  2723 #endif  /* M17N_FLT_USE_NEW_FEATURE */
  2724       m17n_flt_initialized = 1;
  2725     }
  2726 
  2727   for (i = 0; i < len; i++)
  2728     {
  2729       Lisp_Object g = LGSTRING_GLYPH (lgstring, i);
  2730       int c;
  2731 
  2732       if (NILP (g))
  2733         break;
  2734       c = LGLYPH_CHAR (g);
  2735       if (CHAR_VARIATION_SELECTOR_P (c))
  2736         with_variation_selector = true;
  2737     }
  2738 
  2739   len = i;
  2740 
  2741   if (otf && with_variation_selector)
  2742     {
  2743       setup_otf_gstring (len);
  2744       for (i = 0; i < len; i++)
  2745         {
  2746           Lisp_Object g = LGSTRING_GLYPH (lgstring, i);
  2747 
  2748           otf_gstring.glyphs[i].c = LGLYPH_CHAR (g);
  2749           otf_gstring.glyphs[i].f.index.from = LGLYPH_FROM (g);
  2750           otf_gstring.glyphs[i].f.index.to = LGLYPH_TO (g);
  2751         }
  2752       OTF_drive_cmap (otf, &otf_gstring);
  2753       for (i = 0; i < otf_gstring.used; i++)
  2754         {
  2755           OTF_Glyph *otfg = otf_gstring.glyphs + i;
  2756           Lisp_Object g0 = LGSTRING_GLYPH (lgstring, otfg->f.index.from);
  2757           Lisp_Object g1 = LGSTRING_GLYPH (lgstring, otfg->f.index.to);
  2758 
  2759           LGLYPH_SET_CODE (g0, otfg->glyph_id);
  2760           LGLYPH_SET_TO (g0, LGLYPH_TO (g1));
  2761           LGSTRING_SET_GLYPH (lgstring, i, g0);
  2762         }
  2763       if (len > otf_gstring.used)
  2764         {
  2765           len = otf_gstring.used;
  2766           LGSTRING_SET_GLYPH (lgstring, len, Qnil);
  2767         }
  2768     }
  2769 
  2770   {
  2771     Lisp_Object family = Ffont_get (LGSTRING_FONT (lgstring), QCfamily);
  2772 
  2773     if (NILP (family))
  2774       flt_font_ft.flt_font.family = Mnil;
  2775     else
  2776       flt_font_ft.flt_font.family
  2777         = msymbol (SSDATA (Fdowncase (SYMBOL_NAME (family))));
  2778   }
  2779   flt_font_ft.flt_font.x_ppem = ft_face->size->metrics.x_ppem;
  2780   flt_font_ft.flt_font.y_ppem = ft_face->size->metrics.y_ppem;
  2781   flt_font_ft.flt_font.get_glyph_id = ftfont_get_glyph_id;
  2782   flt_font_ft.flt_font.get_metrics = ftfont_get_metrics;
  2783   flt_font_ft.flt_font.check_otf = ftfont_check_otf;
  2784   flt_font_ft.flt_font.drive_otf = ftfont_drive_otf;
  2785   flt_font_ft.flt_font.internal = NULL;
  2786   flt_font_ft.font = font;
  2787   flt_font_ft.ft_face = ft_face;
  2788   flt_font_ft.otf = otf;
  2789   flt_font_ft.matrix = matrix->xx != 0 ? matrix : 0;
  2790 
  2791   if (1 < len)
  2792     {
  2793       /* A little bit ad hoc.  Perhaps, shaper must get script and
  2794          language information, and select a proper flt for them
  2795          here.  */
  2796       int c1 = LGLYPH_CHAR (LGSTRING_GLYPH (lgstring, 1));
  2797       /* For the combining characters in the range U+300..U+36F,
  2798          "combining" is the sole FLT provided by the m17n-lib.  In
  2799          addition, it is the sole FLT that can handle the other
  2800          combining characters with non-OTF fonts.  */
  2801       if ((0x300 <= c1 && c1 <= 0x36F)
  2802           || (! otf && CHAR_HAS_CATEGORY (c1, '^')))
  2803         flt = mflt_get (msymbol ("combining"));
  2804     }
  2805   if (! flt && ! otf)
  2806     {
  2807       flt = mflt_find (LGLYPH_CHAR (LGSTRING_GLYPH (lgstring, 0)),
  2808                        &flt_font_ft.flt_font);
  2809       if (! flt)
  2810         return make_fixnum (0);
  2811     }
  2812 
  2813   MFLTGlyphFT *glyphs = (MFLTGlyphFT *) gstring.glyphs;
  2814   ptrdiff_t allocated = gstring.allocated;
  2815   ptrdiff_t incr_min = len - allocated;
  2816 
  2817   do
  2818     {
  2819       if (0 < incr_min)
  2820         {
  2821           xfree (glyphs);
  2822           glyphs = xpalloc (NULL, &allocated, incr_min, INT_MAX, sizeof *glyphs);
  2823         }
  2824       incr_min = 1;
  2825 
  2826       for (i = 0; i < len; i++)
  2827         {
  2828           Lisp_Object g = LGSTRING_GLYPH (lgstring, i);
  2829           memset (&glyphs[i], 0, sizeof glyphs[i]);
  2830           glyphs[i].g.c = LGLYPH_CHAR (g);
  2831           if (with_variation_selector)
  2832             {
  2833               glyphs[i].g.code = LGLYPH_CODE (g);
  2834               glyphs[i].g.encoded = 1;
  2835             }
  2836         }
  2837 
  2838       gstring.glyph_size = sizeof *glyphs;
  2839       gstring.glyphs = (MFLTGlyph *) glyphs;
  2840       gstring.allocated = allocated;
  2841       gstring.used = len;
  2842       gstring.r2l = 0;
  2843     }
  2844   while (mflt_run (&gstring, 0, len, &flt_font_ft.flt_font, flt) == -2);
  2845 
  2846   if (gstring.used > LGSTRING_GLYPH_LEN (lgstring))
  2847     return Qnil;
  2848 
  2849   /* mflt_run may fail to set g->g.to (which must be a valid index
  2850      into lgstring) correctly if the font has an OTF table that is
  2851      different from what the m17n library expects. */
  2852   for (i = 0; i < gstring.used; i++)
  2853     {
  2854       MFLTGlyphFT *g = (MFLTGlyphFT *) (gstring.glyphs) + i;
  2855       if (g->g.to >= len)
  2856         {
  2857           /* Invalid g->g.to. */
  2858           g->g.to = len - 1;
  2859           int from = g->g.from;
  2860           /* Fix remaining glyphs. */
  2861           for (++i; i < gstring.used; i++)
  2862             {
  2863               g = (MFLTGlyphFT *) (gstring.glyphs) + i;
  2864               g->g.from = from;
  2865               g->g.to = len - 1;
  2866             }
  2867         }
  2868     }
  2869 
  2870   for (i = 0; i < gstring.used; i++)
  2871     {
  2872       MFLTGlyphFT *g = (MFLTGlyphFT *) (gstring.glyphs) + i;
  2873       g->g.from = LGLYPH_FROM (LGSTRING_GLYPH (lgstring, g->g.from));
  2874       g->g.to = LGLYPH_TO (LGSTRING_GLYPH (lgstring, g->g.to));
  2875     }
  2876 
  2877   for (i = 0; i < gstring.used; i++)
  2878     {
  2879       Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i);
  2880       MFLTGlyphFT *g = (MFLTGlyphFT *) (gstring.glyphs) + i;
  2881 
  2882       if (NILP (lglyph))
  2883         {
  2884           lglyph = LGLYPH_NEW ();
  2885           LGSTRING_SET_GLYPH (lgstring, i, lglyph);
  2886         }
  2887       LGLYPH_SET_FROM (lglyph, g->g.from);
  2888       LGLYPH_SET_TO (lglyph, g->g.to);
  2889       LGLYPH_SET_CHAR (lglyph, g->g.c);
  2890       LGLYPH_SET_CODE (lglyph, g->g.code);
  2891       LGLYPH_SET_WIDTH (lglyph, g->g.xadv >> 6);
  2892       LGLYPH_SET_LBEARING (lglyph, g->g.lbearing >> 6);
  2893       LGLYPH_SET_RBEARING (lglyph, g->g.rbearing >> 6);
  2894       LGLYPH_SET_ASCENT (lglyph, g->g.ascent >> 6);
  2895       LGLYPH_SET_DESCENT (lglyph, g->g.descent >> 6);
  2896       if (g->g.adjusted)
  2897         LGLYPH_SET_ADJUSTMENT (lglyph, CALLN (Fvector,
  2898                                               make_fixnum (g->g.xoff >> 6),
  2899                                               make_fixnum (g->g.yoff >> 6),
  2900                                               make_fixnum (g->g.xadv >> 6)));
  2901     }
  2902   return make_fixnum (i);
  2903 }
  2904 
  2905 Lisp_Object
  2906 ftfont_shape (Lisp_Object lgstring, Lisp_Object direction)
  2907 {
  2908   struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring));
  2909   struct font_info *ftfont_info = (struct font_info *) font;
  2910   OTF *otf = ftfont_get_otf (ftfont_info);
  2911 
  2912   return ftfont_shape_by_flt (lgstring, font, ftfont_info->ft_size->face, otf,
  2913                               &ftfont_info->matrix);
  2914 }
  2915 
  2916 #endif  /* HAVE_M17N_FLT */
  2917 
  2918 #endif  /* HAVE_LIBOTF */
  2919 
  2920 #if defined HAVE_OTF_GET_VARIATION_GLYPHS || defined HAVE_FT_FACE_GETCHARVARIANTINDEX
  2921 int
  2922 ftfont_variation_glyphs (struct font *font, int c, unsigned variations[256])
  2923 {
  2924   struct font_info *ftfont_info = (struct font_info *) font;
  2925 #ifdef HAVE_OTF_GET_VARIATION_GLYPHS
  2926   OTF *otf = ftfont_get_otf (ftfont_info);
  2927 
  2928   if (! otf)
  2929     return 0;
  2930   return OTF_get_variation_glyphs (otf, c, variations);
  2931 #else  /* !HAVE_OTF_GET_VARIATION_GLYPHS */
  2932   FT_Face ft_face = ftfont_info->ft_size->face;
  2933   int i, n = 0;
  2934 
  2935   for (i = 0; i < 16; i++)
  2936     {
  2937       variations[i] = FT_Face_GetCharVariantIndex (ft_face, c, 0xFE00 + i);
  2938       if (variations[i])
  2939         n++;
  2940     }
  2941   for (; i < 256; i++)
  2942     {
  2943       variations[i] = FT_Face_GetCharVariantIndex (ft_face, c,
  2944                                                    0xE0100 + (i - 16));
  2945       if (variations[i])
  2946         n++;
  2947     }
  2948 
  2949   return n;
  2950 #endif  /* !HAVE_OTF_GET_VARIATION_GLYPHS */
  2951 }
  2952 #endif /* HAVE_OTF_GET_VARIATION_GLYPHS || HAVE_FT_FACE_GETCHARVARIANTINDEX */
  2953 
  2954 #ifdef HAVE_HARFBUZZ
  2955 
  2956 hb_font_t *
  2957 fthbfont_begin_hb_font (struct font *font, double *position_unit)
  2958 {
  2959   struct font_info *ftfont_info = (struct font_info *) font;
  2960 
  2961   *position_unit = 1.0 / (1 << 6);
  2962   if (! ftfont_info->hb_font)
  2963     ftfont_info->hb_font
  2964       = hb_ft_font_create_referenced (ftfont_info->ft_size->face);
  2965   return ftfont_info->hb_font;
  2966 }
  2967 
  2968 #ifndef HAVE_LIBOTF
  2969 #include <hb-ot.h>
  2970 
  2971 static OTF *
  2972 hbotf_open (const char *name)
  2973 {
  2974   FT_Face ft_face;
  2975 
  2976   if (! ft_library
  2977       && FT_Init_FreeType (&ft_library) != 0)
  2978     return NULL;
  2979   if (FT_New_Face (ft_library, name, 0, &ft_face)
  2980       != 0)
  2981     return NULL;
  2982 
  2983   hb_face_t *face = hb_ft_face_create_referenced (ft_face);
  2984   FT_Done_Face (ft_face);
  2985 
  2986   return face;
  2987 }
  2988 
  2989 static int
  2990 hbotf_check_features (OTF *otf, int gsubp,
  2991                       OTF_tag script, OTF_tag language,
  2992                       const OTF_tag *features, int n_features)
  2993 {
  2994   hb_face_t *face = otf;
  2995   hb_tag_t table_tag = gsubp ? HB_OT_TAG_GSUB : HB_OT_TAG_GPOS;
  2996   hb_tag_t script_tag = script, language_tag = language;
  2997 
  2998   unsigned int script_count
  2999     = hb_ot_layout_table_get_script_tags (face, table_tag, 0, NULL, NULL);
  3000   hb_tag_t *script_tags = xnmalloc (script_count, sizeof *script_tags);
  3001   hb_ot_layout_table_get_script_tags (face, table_tag, 0, &script_count,
  3002                                       script_tags);
  3003   unsigned int script_index;
  3004   for (script_index = 0; script_index < script_count; script_index++)
  3005     if (script_tags[script_index] == script_tag)
  3006       break;
  3007   xfree (script_tags);
  3008   if (script_index == script_count)
  3009     return 0;
  3010 
  3011   unsigned int language_index;
  3012   if (language_tag == 0)
  3013     language_index = HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX;
  3014   else
  3015     {
  3016       unsigned int language_count
  3017         = hb_ot_layout_script_get_language_tags (face, table_tag, script_index,
  3018                                                  0, NULL, NULL);
  3019       hb_tag_t *language_tags = xnmalloc (language_count,
  3020                                           sizeof *language_tags);
  3021       hb_ot_layout_script_get_language_tags (face, table_tag, script_index, 0,
  3022                                              &language_count, language_tags);
  3023       for (language_index = 0; language_index < script_count; language_index++)
  3024         if (language_tags[language_index] == language_tag)
  3025           break;
  3026       xfree (language_tags);
  3027       if (language_index == language_count)
  3028         return 0;
  3029     }
  3030 
  3031   for (int j = 0; j < n_features; j++)
  3032     {
  3033       hb_tag_t feature_tag = features[j];
  3034       hb_bool_t negate = 0;
  3035 
  3036       if (feature_tag == 0)
  3037         continue;
  3038       if (feature_tag & 0x80000000)
  3039         {
  3040           feature_tag &= 0x7FFFFFFF;
  3041           negate = 1;
  3042         }
  3043 
  3044       unsigned int feature_index;
  3045       if (hb_ot_layout_language_find_feature (face, table_tag, script_index,
  3046                                               language_index, feature_tag,
  3047                                               &feature_index) == negate)
  3048         return 0;
  3049     }
  3050   return 1;
  3051 }
  3052 #endif  /* !HAVE_LIBOTF */
  3053 #endif /* HAVE_HARFBUZZ */
  3054 
  3055 static const char *const ftfont_booleans [] = {
  3056   ":antialias",
  3057   ":hinting",
  3058   ":verticallayout",
  3059   ":autohint",
  3060   ":globaladvance",
  3061   ":outline",
  3062   ":scalable",
  3063   ":minspace",
  3064   ":embolden",
  3065   NULL,
  3066 };
  3067 
  3068 static const char *const ftfont_non_booleans [] = {
  3069   ":family",
  3070   ":familylang",
  3071   ":style",
  3072   ":stylelang",
  3073   ":fullname",
  3074   ":fullnamelang",
  3075   ":slant",
  3076   ":weight",
  3077   ":size",
  3078   ":width",
  3079   ":aspect",
  3080   ":pixelsize",
  3081   ":spacing",
  3082   ":foundry",
  3083   ":hintstyle",
  3084   ":file",
  3085   ":index",
  3086   ":ftface",
  3087   ":rasterizer",
  3088   ":scale",
  3089   ":dpi",
  3090   ":rgba",
  3091   ":lcdfilter",
  3092   ":charset",
  3093   ":lang",
  3094   ":fontversion",
  3095   ":capability",
  3096   NULL,
  3097 };
  3098 
  3099 void
  3100 ftfont_filter_properties (Lisp_Object font, Lisp_Object alist)
  3101 {
  3102   font_filter_properties (font, alist, ftfont_booleans, ftfont_non_booleans);
  3103 }
  3104 
  3105 
  3106 Lisp_Object
  3107 ftfont_combining_capability (struct font *font)
  3108 {
  3109 #ifdef HAVE_M17N_FLT
  3110   return Qt;
  3111 #else
  3112   return Qnil;
  3113 #endif
  3114 }
  3115 
  3116 static void syms_of_ftfont_for_pdumper (void);
  3117 
  3118 #ifndef USE_CAIRO
  3119 
  3120 static struct font_driver const ftfont_driver =
  3121   {
  3122   /* We can't draw a text without device dependent functions.  */
  3123   .type = LISPSYM_INITIALLY (Qfreetype),
  3124   .get_cache = ftfont_get_cache,
  3125   .list = ftfont_list,
  3126   .match = ftfont_match,
  3127   .list_family = ftfont_list_family,
  3128   .open_font = ftfont_open,
  3129   .close_font = ftfont_close,
  3130   .has_char = ftfont_has_char,
  3131   .encode_char = ftfont_encode_char,
  3132   .text_extents = ftfont_text_extents,
  3133   .get_bitmap = ftfont_get_bitmap,
  3134   .anchor_point = ftfont_anchor_point,
  3135 #ifdef HAVE_LIBOTF
  3136   .otf_capability = ftfont_otf_capability,
  3137 #endif
  3138 #if defined HAVE_M17N_FLT && defined HAVE_LIBOTF
  3139   .shape = ftfont_shape,
  3140 #endif
  3141 #if defined HAVE_OTF_GET_VARIATION_GLYPHS || defined HAVE_FT_FACE_GETCHARVARIANTINDEX
  3142   .get_variation_glyphs = ftfont_variation_glyphs,
  3143 #endif
  3144   .filter_properties = ftfont_filter_properties,
  3145   .combining_capability = ftfont_combining_capability,
  3146   };
  3147 
  3148 #endif /* !USE_CAIRO */
  3149 
  3150 void
  3151 syms_of_ftfont (void)
  3152 {
  3153   /* Symbolic type of this font-driver.  */
  3154   DEFSYM (Qfreetype, "freetype");
  3155 #ifdef HAVE_HARFBUZZ
  3156   DEFSYM (Qfreetypehb, "freetypehb");
  3157   Fput (Qfreetype, Qfont_driver_superseded_by, Qfreetypehb);
  3158 #endif  /* HAVE_HARFBUZZ */
  3159 
  3160 #ifdef HAVE_HAIKU
  3161   DEFSYM (Qmono, "mono");
  3162 #endif
  3163 
  3164   /* Fontconfig's generic families and their aliases.  */
  3165   DEFSYM (Qmonospace, "monospace");
  3166   DEFSYM (Qsans_serif, "sans-serif");
  3167   DEFSYM (Qsans, "sans");
  3168   DEFSYM (Qsans__serif, "sans serif");
  3169 
  3170   /* The boolean-valued font property key specifying the use of leading.  */
  3171   DEFSYM (QCminspace, ":minspace");
  3172 
  3173   /* Fontconfig's rendering parameters.  */
  3174   DEFSYM (QChinting, ":hinting");
  3175   DEFSYM (QCautohint, ":autohint");
  3176   DEFSYM (QChintstyle, ":hintstyle");
  3177   DEFSYM (QCrgba, ":rgba");
  3178   DEFSYM (QCembolden, ":embolden");
  3179   DEFSYM (QClcdfilter, ":lcdfilter");
  3180 
  3181   staticpro (&freetype_font_cache);
  3182   freetype_font_cache = list1 (Qt);
  3183 
  3184   staticpro (&ftfont_generic_family_list);
  3185   ftfont_generic_family_list = list3 (Fcons (Qmonospace, Qt),
  3186                                       Fcons (Qsans_serif, Qt),
  3187                                       Fcons (Qsans, Qt));
  3188 
  3189   staticpro (&ft_face_cache);
  3190   ft_face_cache = Qnil;
  3191 
  3192   pdumper_do_now_and_after_load (syms_of_ftfont_for_pdumper);
  3193 }
  3194 
  3195 static void
  3196 syms_of_ftfont_for_pdumper (void)
  3197 {
  3198   PDUMPER_RESET_LV (ft_face_cache, Qnil);
  3199   register_font_driver (&ftfont_driver, NULL);
  3200 #ifdef HAVE_HARFBUZZ
  3201   fthbfont_driver = ftfont_driver;
  3202   fthbfont_driver.type = Qfreetypehb;
  3203   fthbfont_driver.otf_capability = hbfont_otf_capability;
  3204   fthbfont_driver.shape = hbfont_shape;
  3205   fthbfont_driver.combining_capability = hbfont_combining_capability;
  3206   fthbfont_driver.begin_hb_font = fthbfont_begin_hb_font;
  3207   register_font_driver (&fthbfont_driver, NULL);
  3208 #endif  /* HAVE_HARFBUZZ */
  3209 }

/* [<][>][^][v][top][bottom][index][help] */