root/src/hbfont.c

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

DEFINITIONS

This source file includes following definitions.
  1. hbfont_init_w32_funcs
  2. hbfont_otf_features
  3. hbfont_otf_capability
  4. uni_combining
  5. uni_general
  6. uni_mirroring
  7. get_hb_unicode_funcs
  8. hbfont_shape
  9. hbfont_combining_capability

     1 /* hbfont.c -- Platform-independent support for HarfBuzz font driver.
     2    Copyright (C) 2019-2023 Free Software Foundation, Inc.
     3 
     4 This file is part of GNU Emacs.
     5 
     6 GNU Emacs is free software: you can redistribute it and/or modify
     7 it under the terms of the GNU General Public License as published by
     8 the Free Software Foundation, either version 3 of the License, or (at
     9 your option) any later version.
    10 
    11 GNU Emacs is distributed in the hope that it will be useful,
    12 but WITHOUT ANY WARRANTY; without even the implied warranty of
    13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    14 GNU General Public License for more details.
    15 
    16 You should have received a copy of the GNU General Public License
    17 along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
    18 
    19 #include <config.h>
    20 #include <math.h>
    21 #include <hb.h>
    22 #include <hb-ot.h>
    23 
    24 #include "lisp.h"
    25 #include "frame.h"
    26 #include "composite.h"
    27 #include "font.h"
    28 #include "dispextern.h"
    29 #include "buffer.h"
    30 
    31 #ifdef HAVE_NTGUI
    32 
    33 #include "w32common.h"
    34 
    35 /* The w32 implementation calls HarfBuzz functions via function
    36    pointers.  We use the below to declare the function pointers and
    37    redirect function names to those pointers.  */
    38 DEF_DLL_FN (hb_unicode_funcs_t *, hb_unicode_funcs_create,
    39             (hb_unicode_funcs_t *));
    40 DEF_DLL_FN (hb_unicode_funcs_t *, hb_unicode_funcs_get_default, (void));
    41 DEF_DLL_FN (void, hb_unicode_funcs_set_combining_class_func,
    42             (hb_unicode_funcs_t *, hb_unicode_combining_class_func_t,
    43              void *, hb_destroy_func_t));
    44 DEF_DLL_FN (void, hb_unicode_funcs_set_general_category_func,
    45             (hb_unicode_funcs_t *, hb_unicode_general_category_func_t,
    46              void *, hb_destroy_func_t));
    47 DEF_DLL_FN (void, hb_unicode_funcs_set_mirroring_func,
    48             (hb_unicode_funcs_t *, hb_unicode_mirroring_func_t,
    49              void *, hb_destroy_func_t));
    50 DEF_DLL_FN (hb_buffer_t *, hb_buffer_create, (void));
    51 DEF_DLL_FN (void, hb_buffer_set_unicode_funcs,
    52             (hb_buffer_t *, hb_unicode_funcs_t *));
    53 DEF_DLL_FN (void, hb_buffer_clear_contents, (hb_buffer_t *));
    54 DEF_DLL_FN (hb_bool_t, hb_buffer_pre_allocate, (hb_buffer_t *, unsigned int));
    55 DEF_DLL_FN (void, hb_buffer_add, (hb_buffer_t *, hb_codepoint_t, unsigned int));
    56 DEF_DLL_FN (void, hb_buffer_set_content_type,
    57             (hb_buffer_t *, hb_buffer_content_type_t));
    58 DEF_DLL_FN (void, hb_buffer_set_cluster_level,
    59             (hb_buffer_t *, hb_buffer_cluster_level_t));
    60 DEF_DLL_FN (void, hb_buffer_set_direction, (hb_buffer_t *, hb_direction_t));
    61 DEF_DLL_FN (void, hb_buffer_set_language, (hb_buffer_t *, hb_language_t));
    62 DEF_DLL_FN (hb_language_t, hb_language_from_string, (const char *, int));
    63 DEF_DLL_FN (void, hb_buffer_guess_segment_properties, (hb_buffer_t *));
    64 DEF_DLL_FN (hb_bool_t, hb_shape_full,
    65             (hb_font_t *, hb_buffer_t *, const hb_feature_t *,
    66              unsigned int, const char * const *));
    67 DEF_DLL_FN (unsigned int, hb_buffer_get_length, (hb_buffer_t *));
    68 DEF_DLL_FN (hb_direction_t, hb_buffer_get_direction, (hb_buffer_t *));
    69 DEF_DLL_FN (void, hb_buffer_reverse_clusters, (hb_buffer_t *));
    70 DEF_DLL_FN (hb_glyph_info_t *, hb_buffer_get_glyph_infos,
    71             (hb_buffer_t *, unsigned int *));
    72 DEF_DLL_FN (hb_glyph_position_t *, hb_buffer_get_glyph_positions,
    73             (hb_buffer_t *, unsigned int *));
    74 DEF_DLL_FN (void, hb_tag_to_string, (hb_tag_t, char *));
    75 DEF_DLL_FN (hb_face_t *, hb_font_get_face, (hb_font_t *font));
    76 DEF_DLL_FN (unsigned int, hb_ot_layout_table_get_script_tags,
    77             (hb_face_t *, hb_tag_t, unsigned int, unsigned int *, hb_tag_t *));
    78 DEF_DLL_FN (unsigned int, hb_ot_layout_table_get_feature_tags,
    79             (hb_face_t *, hb_tag_t, unsigned int, unsigned int *, hb_tag_t *));
    80 DEF_DLL_FN (unsigned int, hb_ot_layout_script_get_language_tags,
    81             (hb_face_t *, hb_tag_t, unsigned int, unsigned int, unsigned int *,
    82              hb_tag_t *));
    83 DEF_DLL_FN (unsigned int, hb_ot_layout_language_get_feature_tags,
    84             (hb_face_t *, hb_tag_t, unsigned int, unsigned int, unsigned int,
    85              unsigned int *, hb_tag_t *));
    86 
    87 #define hb_unicode_funcs_create fn_hb_unicode_funcs_create
    88 #define hb_unicode_funcs_get_default fn_hb_unicode_funcs_get_default
    89 #define hb_unicode_funcs_set_combining_class_func fn_hb_unicode_funcs_set_combining_class_func
    90 #define hb_unicode_funcs_set_general_category_func fn_hb_unicode_funcs_set_general_category_func
    91 #define hb_unicode_funcs_set_mirroring_func fn_hb_unicode_funcs_set_mirroring_func
    92 #define hb_buffer_create fn_hb_buffer_create
    93 #define hb_buffer_set_unicode_funcs fn_hb_buffer_set_unicode_funcs
    94 #define hb_buffer_clear_contents fn_hb_buffer_clear_contents
    95 #define hb_buffer_pre_allocate fn_hb_buffer_pre_allocate
    96 #define hb_buffer_add fn_hb_buffer_add
    97 #define hb_buffer_set_content_type fn_hb_buffer_set_content_type
    98 #define hb_buffer_set_cluster_level fn_hb_buffer_set_cluster_level
    99 #define hb_buffer_set_direction fn_hb_buffer_set_direction
   100 #define hb_buffer_set_language fn_hb_buffer_set_language
   101 #define hb_language_from_string fn_hb_language_from_string
   102 #define hb_buffer_guess_segment_properties fn_hb_buffer_guess_segment_properties
   103 #define hb_shape_full fn_hb_shape_full
   104 #define hb_buffer_get_length fn_hb_buffer_get_length
   105 #define hb_buffer_get_direction fn_hb_buffer_get_direction
   106 #define hb_buffer_reverse_clusters fn_hb_buffer_reverse_clusters
   107 #define hb_buffer_get_glyph_infos fn_hb_buffer_get_glyph_infos
   108 #define hb_buffer_get_glyph_positions fn_hb_buffer_get_glyph_positions
   109 #define hb_tag_to_string fn_hb_tag_to_string
   110 #define hb_font_get_face fn_hb_font_get_face
   111 #define hb_ot_layout_table_get_script_tags fn_hb_ot_layout_table_get_script_tags
   112 #define hb_ot_layout_table_get_feature_tags fn_hb_ot_layout_table_get_feature_tags
   113 #define hb_ot_layout_script_get_language_tags fn_hb_ot_layout_script_get_language_tags
   114 #define hb_ot_layout_language_get_feature_tags fn_hb_ot_layout_language_get_feature_tags
   115 
   116 /* This function is called from syms_of_w32uniscribe_for_pdumper to
   117    initialize the above function pointers.  */
   118 bool
   119 hbfont_init_w32_funcs (HMODULE library)
   120 {
   121   LOAD_DLL_FN (library, hb_unicode_funcs_create);
   122   LOAD_DLL_FN (library, hb_unicode_funcs_get_default);
   123   LOAD_DLL_FN (library, hb_unicode_funcs_set_combining_class_func);
   124   LOAD_DLL_FN (library, hb_unicode_funcs_set_general_category_func);
   125   LOAD_DLL_FN (library, hb_unicode_funcs_set_mirroring_func);
   126   LOAD_DLL_FN (library, hb_buffer_create);
   127   LOAD_DLL_FN (library, hb_buffer_set_unicode_funcs);
   128   LOAD_DLL_FN (library, hb_buffer_clear_contents);
   129   LOAD_DLL_FN (library, hb_buffer_pre_allocate);
   130   LOAD_DLL_FN (library, hb_buffer_add);
   131   LOAD_DLL_FN (library, hb_buffer_set_content_type);
   132   LOAD_DLL_FN (library, hb_buffer_set_cluster_level);
   133   LOAD_DLL_FN (library, hb_buffer_set_direction);
   134   LOAD_DLL_FN (library, hb_buffer_set_language);
   135   LOAD_DLL_FN (library, hb_language_from_string);
   136   LOAD_DLL_FN (library, hb_buffer_guess_segment_properties);
   137   LOAD_DLL_FN (library, hb_shape_full);
   138   LOAD_DLL_FN (library, hb_buffer_get_length);
   139   LOAD_DLL_FN (library, hb_buffer_get_direction);
   140   LOAD_DLL_FN (library, hb_buffer_reverse_clusters);
   141   LOAD_DLL_FN (library, hb_buffer_get_glyph_infos);
   142   LOAD_DLL_FN (library, hb_buffer_get_glyph_positions);
   143   LOAD_DLL_FN (library, hb_tag_to_string);
   144   LOAD_DLL_FN (library, hb_font_get_face);
   145   LOAD_DLL_FN (library, hb_ot_layout_table_get_script_tags);
   146   LOAD_DLL_FN (library, hb_ot_layout_table_get_feature_tags);
   147   LOAD_DLL_FN (library, hb_ot_layout_script_get_language_tags);
   148   LOAD_DLL_FN (library, hb_ot_layout_language_get_feature_tags);
   149   return true;
   150 }
   151 #endif  /* HAVE_NTGUI */
   152 
   153 static Lisp_Object
   154 hbfont_otf_features (hb_face_t *face, hb_tag_t table_tag)
   155 {
   156   hb_tag_t *language_tags = NULL, *feature_tags = NULL;
   157   char buf[4];
   158   unsigned int script_count
   159     = hb_ot_layout_table_get_script_tags (face, table_tag, 0, NULL, NULL);
   160   hb_tag_t *script_tags = xnmalloc (script_count, sizeof *script_tags);
   161   hb_ot_layout_table_get_script_tags (face, table_tag, 0, &script_count,
   162                                       script_tags);
   163   Lisp_Object scripts = Qnil;
   164   for (int i = script_count - 1; i >= 0; i--)
   165     {
   166       unsigned int language_count
   167         = hb_ot_layout_script_get_language_tags (face, table_tag, i, 0,
   168                                                  NULL, NULL);
   169       language_tags = xnrealloc (language_tags, language_count,
   170                                  sizeof *language_tags);
   171       hb_ot_layout_script_get_language_tags (face, table_tag, i, 0,
   172                                              &language_count, language_tags);
   173       Lisp_Object langsyses = Qnil;
   174       for (int j = language_count - 1; j >= -1; j--)
   175         {
   176           unsigned int language_index
   177             = j >= 0 ? j : HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX;
   178           unsigned int feature_count
   179             = hb_ot_layout_language_get_feature_tags (face, table_tag,
   180                                                       i, language_index, 0,
   181                                                       NULL, NULL);
   182           if (feature_count == 0)
   183             continue;
   184           feature_tags = xnrealloc (feature_tags, feature_count,
   185                                     sizeof *feature_tags);
   186           hb_ot_layout_language_get_feature_tags (face, table_tag,
   187                                                   i, language_index, 0,
   188                                                   &feature_count, feature_tags);
   189           Lisp_Object features = Qnil;
   190           for (int k = feature_count - 1; k >= 0; k--)
   191             {
   192               hb_tag_to_string (feature_tags[k], buf);
   193               features = Fcons (font_intern_prop (buf, 4, 1), features);
   194             }
   195 
   196           Lisp_Object sym = Qnil;
   197           if (j >= 0)
   198             {
   199               hb_tag_to_string (language_tags[j], buf);
   200               sym = font_intern_prop (buf, 4, 1);
   201             }
   202           langsyses = Fcons (Fcons (sym, features), langsyses);
   203         }
   204 
   205       hb_tag_to_string (script_tags[i], buf);
   206       scripts = Fcons (Fcons (font_intern_prop (buf, 4, 1), langsyses),
   207                        scripts);
   208     }
   209   xfree (feature_tags);
   210   xfree (language_tags);
   211   xfree (script_tags);
   212 
   213   return scripts;
   214 }
   215 
   216 Lisp_Object
   217 hbfont_otf_capability (struct font *font)
   218 {
   219   double position_unit;
   220   hb_font_t *hb_font
   221     = font->driver->begin_hb_font
   222     ? font->driver->begin_hb_font (font, &position_unit)
   223     : NULL;
   224   if (!hb_font)
   225     return Qnil;
   226 
   227   Lisp_Object gsub_gpos = Fcons (Qnil, Qnil);
   228   hb_face_t *face = hb_font_get_face (hb_font);
   229   if (hb_ot_layout_table_get_feature_tags (face, HB_OT_TAG_GSUB, 0, NULL, NULL))
   230     XSETCAR (gsub_gpos, hbfont_otf_features (face, HB_OT_TAG_GSUB));
   231   if (hb_ot_layout_table_get_feature_tags (face, HB_OT_TAG_GPOS, 0, NULL, NULL))
   232     XSETCDR (gsub_gpos, hbfont_otf_features (face, HB_OT_TAG_GPOS));
   233 
   234   if (font->driver->end_hb_font)
   235     font->driver->end_hb_font (font, hb_font);
   236 
   237   return gsub_gpos;
   238 }
   239 
   240 /* Support functions for HarfBuzz shaper.  */
   241 
   242 static bool combining_class_loaded = false;
   243 static Lisp_Object canonical_combining_class_table;
   244 
   245 static hb_unicode_combining_class_t
   246 uni_combining (hb_unicode_funcs_t *funcs, hb_codepoint_t ch, void *user_data)
   247 {
   248   /* Load the Unicode table first time it is needed.  */
   249   if (!combining_class_loaded)
   250     {
   251       canonical_combining_class_table =
   252         uniprop_table (Qcanonical_combining_class);
   253       if (NILP (canonical_combining_class_table))
   254         emacs_abort ();
   255       staticpro (&canonical_combining_class_table);
   256       combining_class_loaded = true;
   257     }
   258 
   259   Lisp_Object combining =
   260     get_unicode_property (canonical_combining_class_table, ch);
   261   if (FIXNUMP (combining))
   262     return (hb_unicode_combining_class_t) XFIXNUM (combining);
   263 
   264   return HB_UNICODE_COMBINING_CLASS_NOT_REORDERED;
   265 }
   266 
   267 static hb_unicode_general_category_t
   268 uni_general (hb_unicode_funcs_t *funcs, hb_codepoint_t ch, void *user_data)
   269 {
   270   Lisp_Object category = CHAR_TABLE_REF (Vunicode_category_table, ch);
   271 
   272   if (INTEGERP (category))
   273     {
   274     switch (XFIXNUM (category))
   275       {
   276       case UNICODE_CATEGORY_Cc:
   277         return HB_UNICODE_GENERAL_CATEGORY_CONTROL;
   278       case UNICODE_CATEGORY_Cf:
   279         return HB_UNICODE_GENERAL_CATEGORY_FORMAT;
   280       case UNICODE_CATEGORY_Cn:
   281         return HB_UNICODE_GENERAL_CATEGORY_UNASSIGNED;
   282       case UNICODE_CATEGORY_Co:
   283         return HB_UNICODE_GENERAL_CATEGORY_PRIVATE_USE;
   284       case UNICODE_CATEGORY_Cs:
   285         return HB_UNICODE_GENERAL_CATEGORY_SURROGATE;
   286       case UNICODE_CATEGORY_Ll:
   287         return HB_UNICODE_GENERAL_CATEGORY_LOWERCASE_LETTER;
   288       case UNICODE_CATEGORY_Lm:
   289         return HB_UNICODE_GENERAL_CATEGORY_MODIFIER_LETTER;
   290       case UNICODE_CATEGORY_Lo:
   291         return HB_UNICODE_GENERAL_CATEGORY_OTHER_LETTER;
   292       case UNICODE_CATEGORY_Lt:
   293         return HB_UNICODE_GENERAL_CATEGORY_TITLECASE_LETTER;
   294       case UNICODE_CATEGORY_Lu:
   295         return HB_UNICODE_GENERAL_CATEGORY_UPPERCASE_LETTER;
   296       case UNICODE_CATEGORY_Mc:
   297         return HB_UNICODE_GENERAL_CATEGORY_SPACING_MARK;
   298       case UNICODE_CATEGORY_Me:
   299         return HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK;
   300       case UNICODE_CATEGORY_Mn:
   301         return HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK;
   302       case UNICODE_CATEGORY_Nd:
   303         return HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER;
   304       case UNICODE_CATEGORY_Nl:
   305         return HB_UNICODE_GENERAL_CATEGORY_LETTER_NUMBER;
   306       case UNICODE_CATEGORY_No:
   307         return HB_UNICODE_GENERAL_CATEGORY_OTHER_NUMBER;
   308       case UNICODE_CATEGORY_Pc:
   309         return HB_UNICODE_GENERAL_CATEGORY_CONNECT_PUNCTUATION;
   310       case UNICODE_CATEGORY_Pd:
   311         return HB_UNICODE_GENERAL_CATEGORY_DASH_PUNCTUATION;
   312       case UNICODE_CATEGORY_Pe:
   313         return HB_UNICODE_GENERAL_CATEGORY_CLOSE_PUNCTUATION;
   314       case UNICODE_CATEGORY_Pf:
   315         return HB_UNICODE_GENERAL_CATEGORY_FINAL_PUNCTUATION;
   316       case UNICODE_CATEGORY_Pi:
   317         return HB_UNICODE_GENERAL_CATEGORY_INITIAL_PUNCTUATION;
   318       case UNICODE_CATEGORY_Po:
   319         return HB_UNICODE_GENERAL_CATEGORY_OTHER_PUNCTUATION;
   320       case UNICODE_CATEGORY_Ps:
   321         return HB_UNICODE_GENERAL_CATEGORY_OPEN_PUNCTUATION;
   322       case UNICODE_CATEGORY_Sc:
   323         return HB_UNICODE_GENERAL_CATEGORY_CURRENCY_SYMBOL;
   324       case UNICODE_CATEGORY_Sk:
   325         return HB_UNICODE_GENERAL_CATEGORY_MODIFIER_SYMBOL;
   326       case UNICODE_CATEGORY_Sm:
   327         return HB_UNICODE_GENERAL_CATEGORY_MATH_SYMBOL;
   328       case UNICODE_CATEGORY_So:
   329         return HB_UNICODE_GENERAL_CATEGORY_OTHER_SYMBOL;
   330       case UNICODE_CATEGORY_Zl:
   331         return HB_UNICODE_GENERAL_CATEGORY_LINE_SEPARATOR;
   332       case UNICODE_CATEGORY_Zp:
   333         return HB_UNICODE_GENERAL_CATEGORY_PARAGRAPH_SEPARATOR;
   334       case UNICODE_CATEGORY_Zs:
   335         return HB_UNICODE_GENERAL_CATEGORY_SPACE_SEPARATOR;
   336       case UNICODE_CATEGORY_UNKNOWN:
   337         return HB_UNICODE_GENERAL_CATEGORY_UNASSIGNED;
   338       }
   339     }
   340 
   341   return HB_UNICODE_GENERAL_CATEGORY_UNASSIGNED;
   342 }
   343 
   344 static hb_codepoint_t
   345 uni_mirroring (hb_unicode_funcs_t *funcs, hb_codepoint_t ch, void *user_data)
   346 {
   347   return bidi_mirror_char (ch);
   348 }
   349 
   350 static hb_unicode_funcs_t *
   351 get_hb_unicode_funcs (void)
   352 {
   353   /* Subclass HarfBuzz's default Unicode functions and override functions that
   354    * use data Emacs can provide. This way changing Emacs data is reflected in
   355    * the shaped output. */
   356   hb_unicode_funcs_t *funcs = hb_unicode_funcs_create (hb_unicode_funcs_get_default ());
   357 
   358   hb_unicode_funcs_set_combining_class_func (funcs, uni_combining, NULL, NULL);
   359   hb_unicode_funcs_set_general_category_func (funcs, uni_general, NULL, NULL);
   360   hb_unicode_funcs_set_mirroring_func (funcs, uni_mirroring, NULL, NULL);
   361 
   362   /* Use default implementation for Unicode composition/decomposition.
   363      We might want to revisit this later.
   364   hb_unicode_funcs_set_compose_func (funcs, uni_compose, NULL, NULL);
   365   hb_unicode_funcs_set_decompose_func (funcs, uni_decompose, NULL, NULL);
   366   */
   367 
   368   /* Emacs own script mapping for characters differs from Unicode, so we want
   369    * to keep the default HarfBuzz's implementation here.
   370   hb_unicode_funcs_set_script_func (funcs, uni_script, NULL, NULL);
   371   */
   372 
   373   return funcs;
   374 }
   375 
   376 /* HarfBuzz implementation of shape for font backend.
   377 
   378    Shape text in LGSTRING.  See the docstring of
   379    'composition-get-gstring' for the format of LGSTRING.  If the
   380    (N+1)th element of LGSTRING is nil, input of shaping is from the
   381    1st to (N)th elements.  In each input glyph, FROM, TO, CHAR, and
   382    CODE are already set, but FROM and TO need adjustments according
   383    to the glyphs produced by the shaping function.
   384    DIRECTION is either L2R or R2L, or nil if unknown.  During
   385    redisplay, this comes from applying the UBA, is passed from
   386    composition_reseat_it, and is used by the HarfBuzz shaper.
   387 
   388    This function updates all fields of the input glyphs.  If the
   389    output glyphs (M) are more than the input glyphs (N), (N+1)th
   390    through (M)th elements of LGSTRING are updated possibly by making
   391    a new glyph object and storing it in LGSTRING.  If (M) is greater
   392    than the length of LGSTRING, nil should be returned.  In that case,
   393    this function is called again with a larger LGSTRING.  */
   394 Lisp_Object
   395 hbfont_shape (Lisp_Object lgstring, Lisp_Object direction)
   396 {
   397   struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring));
   398   ptrdiff_t glyph_len = 0, text_len = LGSTRING_GLYPH_LEN (lgstring);
   399   ptrdiff_t i;
   400 
   401   hb_glyph_info_t *info;
   402   hb_glyph_position_t *pos;
   403 
   404   /* Cache the HarfBuzz buffer for better performance and less allocations.
   405    * We intentionally never destroy the buffer. */
   406   static hb_buffer_t *hb_buffer = NULL;
   407   if (! hb_buffer)
   408     {
   409       hb_buffer = hb_buffer_create ();
   410       hb_unicode_funcs_t* ufuncs = get_hb_unicode_funcs();
   411       hb_buffer_set_unicode_funcs(hb_buffer, ufuncs);
   412     }
   413 
   414   hb_buffer_clear_contents (hb_buffer);
   415   hb_buffer_pre_allocate (hb_buffer, text_len);
   416 
   417   /* Copy the characters in their original logical order, so we can
   418      assign them to glyphs correctly after shaping.  */
   419   int *chars = alloca (text_len * sizeof (int));
   420   for (i = 0; i < text_len; i++)
   421     {
   422       Lisp_Object g = LGSTRING_GLYPH (lgstring, i);
   423       int c;
   424 
   425       if (NILP (g))
   426         break;
   427       c = LGLYPH_CHAR (g);
   428       hb_buffer_add (hb_buffer, c, i);
   429       chars[i] = c;
   430     }
   431 
   432   text_len = i;
   433   if (!text_len)
   434     return Qnil;
   435 
   436   hb_buffer_set_content_type (hb_buffer, HB_BUFFER_CONTENT_TYPE_UNICODE);
   437   hb_buffer_set_cluster_level (hb_buffer,
   438                                HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES);
   439 
   440   /* If the caller didn't provide a meaningful DIRECTION, let HarfBuzz
   441      guess it. */
   442   if (!NILP (direction)
   443       /* If they bind bidi-display-reordering to nil, the DIRECTION
   444          they provide is meaningless, and we should let HarfBuzz guess
   445          the real direction.  */
   446       && !NILP (BVAR (current_buffer, bidi_display_reordering)))
   447     {
   448       hb_direction_t dir = HB_DIRECTION_LTR;
   449       if (EQ (direction, QL2R))
   450         dir = HB_DIRECTION_LTR;
   451       else if (EQ (direction, QR2L))
   452         dir = HB_DIRECTION_RTL;
   453       hb_buffer_set_direction (hb_buffer, dir);
   454     }
   455 
   456   /* Leave the script determination to HarfBuzz, until Emacs has a
   457      better idea of the script of LGSTRING.  FIXME. */
   458 #if 0
   459   hb_buffer_set_script (hb_buffer, XXX);
   460 #endif
   461 
   462   /* FIXME: This can only handle the single global language, which
   463      normally comes from the locale.  In addition, if
   464      current-iso639-language is a list, we arbitrarily use the first
   465      one.  We should instead have a notion of the language of the text
   466      being shaped.  */
   467   Lisp_Object lang = Vcurrent_iso639_language;
   468   if (CONSP (Vcurrent_iso639_language))
   469     lang = XCAR (Vcurrent_iso639_language);
   470   if (SYMBOLP (lang))
   471     {
   472       Lisp_Object lang_str = SYMBOL_NAME (lang);
   473       hb_buffer_set_language (hb_buffer,
   474                               hb_language_from_string (SSDATA (lang_str),
   475                                                        SBYTES (lang_str)));
   476     }
   477 
   478   /* Guess the default properties for when they cannot be determined above.
   479 
   480      FIXME: maybe drop this guessing once script and language handling
   481      is fixed above; but then will need to guess the direction by
   482      ourselves, perhaps by looking at the characters using
   483      bidi_get_type or somesuch.  */
   484   hb_buffer_guess_segment_properties (hb_buffer);
   485 
   486   double position_unit;
   487   hb_font_t *hb_font
   488     = font->driver->begin_hb_font
   489     ? font->driver->begin_hb_font (font, &position_unit)
   490     : NULL;
   491   if (!hb_font)
   492     return make_fixnum (0);
   493 
   494   hb_bool_t success = hb_shape_full (hb_font, hb_buffer, NULL, 0, NULL);
   495   if (font->driver->end_hb_font)
   496     font->driver->end_hb_font (font, hb_font);
   497   if (!success)
   498     return Qnil;
   499 
   500   glyph_len = hb_buffer_get_length (hb_buffer);
   501   if (glyph_len > LGSTRING_GLYPH_LEN (lgstring))
   502     return Qnil;
   503 
   504   /* We need the clusters in logical order.  */
   505   bool buf_reversed = false;
   506   if (HB_DIRECTION_IS_BACKWARD (hb_buffer_get_direction (hb_buffer)))
   507     {
   508       buf_reversed = true;
   509       hb_buffer_reverse_clusters (hb_buffer);
   510     }
   511   info = hb_buffer_get_glyph_infos (hb_buffer, NULL);
   512   pos = hb_buffer_get_glyph_positions (hb_buffer, NULL);
   513   ptrdiff_t from = -1, to UNINIT, cluster_offset UNINIT;
   514   int incr = buf_reversed ? -1 : 1;
   515   for (i = 0; i < glyph_len; i++)
   516     {
   517       Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i);
   518       struct font_metrics metrics = {.width = 0};
   519       int xoff, yoff, wadjust;
   520       bool new_lglyph = false;
   521 
   522       if (NILP (lglyph))
   523         {
   524           new_lglyph = true;
   525           lglyph = LGLYPH_NEW ();
   526           LGSTRING_SET_GLYPH (lgstring, i, lglyph);
   527         }
   528 
   529       if (info[i].cluster != from)
   530         {
   531           int j;
   532           /* Found a new cluster.  Determine its FROM and TO, and the
   533              offset to the first character of the cluster.  */
   534           /* FROM is the index of the first character that contributed
   535              to this cluster.  */
   536           from = info[i].cluster;
   537           /* TO is the index of the last character that contributed to
   538              this cluster.  */
   539           for (j = i; j < glyph_len && info[j].cluster == from; j++)
   540             ;
   541           to = (j == glyph_len) ? text_len - 1 : info[j].cluster - 1;
   542           cluster_offset = 0;
   543           /* For RTL buffers, HarfBuzz produces glyphs in a cluster in
   544              reverse order, so we need to account for that to record
   545              the correct character in each glyph.
   546 
   547              Implementation note: the character codepoint recorded in
   548              each glyph is not really used, except when we display the
   549              glyphs in descr-text.el.  So this is just an aesthetic
   550              issue.  */
   551           if (buf_reversed)
   552             cluster_offset = to - from;
   553         }
   554 
   555       /* All the glyphs in a cluster have the same values of FROM and TO.  */
   556       LGLYPH_SET_FROM (lglyph, from);
   557       /* This heuristic is for when the Lisp shape-gstring function
   558          substitutes known precomposed characters for decomposed
   559          sequences.  E.g., hebrew.el does that.  This makes TEXT_LEN
   560          be smaller than the original length of the composed character
   561          sequence.  In that case, we must not alter the largest TO,
   562          because the display engine must know that all the characters
   563          in the original sequence were processed by the composition.
   564          If we don't do this, some of the composed characters will be
   565          displayed again as separate glyphs.  */
   566       if (!(!new_lglyph
   567             && to == text_len - 1
   568             && LGLYPH_TO (lglyph) > to))
   569         LGLYPH_SET_TO (lglyph, to);
   570 
   571       /* Not every glyph in a cluster maps directly to a single
   572          character; in general, N characters can yield M glyphs, where
   573          M could be smaller or greater than N.  However, in many cases
   574          there is a one-to-one correspondence, and it would be a pity
   575          to lose that information, even if it's sometimes inaccurate.  */
   576       ptrdiff_t char_idx = from + cluster_offset;
   577       cluster_offset += incr;
   578       if (char_idx > to)
   579         char_idx = to;
   580       if (char_idx < from)
   581         char_idx = from;
   582       LGLYPH_SET_CHAR (lglyph, chars[char_idx]);
   583       LGLYPH_SET_CODE (lglyph, info[i].codepoint);
   584 
   585       unsigned code = info[i].codepoint;
   586       font->driver->text_extents (font, &code, 1, &metrics);
   587       LGLYPH_SET_WIDTH (lglyph, metrics.width);
   588       LGLYPH_SET_LBEARING (lglyph, metrics.lbearing);
   589       LGLYPH_SET_RBEARING (lglyph, metrics.rbearing);
   590       LGLYPH_SET_ASCENT (lglyph, metrics.ascent);
   591       LGLYPH_SET_DESCENT (lglyph, metrics.descent);
   592 
   593       xoff = lround (pos[i].x_offset * position_unit);
   594       yoff = - lround (pos[i].y_offset * position_unit);
   595       wadjust = lround (pos[i].x_advance * position_unit);
   596       if (xoff || yoff || wadjust != metrics.width)
   597         LGLYPH_SET_ADJUSTMENT (lglyph, CALLN (Fvector,
   598                                               make_fixnum (xoff),
   599                                               make_fixnum (yoff),
   600                                               make_fixnum (wadjust)));
   601     }
   602 
   603   return make_fixnum (glyph_len);
   604 }
   605 
   606 Lisp_Object
   607 hbfont_combining_capability (struct font *font)
   608 {
   609   return Qt;
   610 }

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