src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ft.cc
changeset 54232 7c11a7cc7c1d
parent 51303 0eeff620cdf5
equal deleted inserted replaced
54231:e4813eded7cb 54232:7c11a7cc7c1d
    25  *
    25  *
    26  * Red Hat Author(s): Behdad Esfahbod
    26  * Red Hat Author(s): Behdad Esfahbod
    27  * Google Author(s): Behdad Esfahbod
    27  * Google Author(s): Behdad Esfahbod
    28  */
    28  */
    29 
    29 
    30 #include "hb-private.hh"
    30 #include "hb.hh"
    31 #include "hb-debug.hh"
       
    32 
    31 
    33 #include "hb-ft.h"
    32 #include "hb-ft.h"
    34 
    33 
    35 #include "hb-font-private.hh"
    34 #include "hb-font.hh"
       
    35 #include "hb-machinery.hh"
       
    36 #include "hb-cache.hh"
    36 
    37 
    37 #include FT_ADVANCES_H
    38 #include FT_ADVANCES_H
    38 #include FT_MULTIPLE_MASTERS_H
    39 #include FT_MULTIPLE_MASTERS_H
    39 #include FT_TRUETYPE_TABLES_H
    40 #include FT_TRUETYPE_TABLES_H
    40 
    41 
    41 
    42 
       
    43 /**
       
    44  * SECTION:hb-ft
       
    45  * @title: hb-ft
       
    46  * @short_description: FreeType integration
       
    47  * @include: hb-ft.h
       
    48  *
       
    49  * Functions for using HarfBuzz with the FreeType library to provide face and
       
    50  * font data.
       
    51  **/
       
    52 
       
    53 
    42 /* TODO:
    54 /* TODO:
    43  *
    55  *
    44  * In general, this file does a fine job of what it's supposed to do.
    56  * In general, this file does a fine job of what it's supposed to do.
    45  * There are, however, things that need more work:
    57  * There are, however, things that need more work:
    46  *
       
    47  *   - I remember seeing FT_Get_Advance() without the NO_HINTING flag to be buggy.
       
    48  *     Have not investigated.
       
    49  *
    58  *
    50  *   - FreeType works in 26.6 mode.  Clients can decide to use that mode, and everything
    59  *   - FreeType works in 26.6 mode.  Clients can decide to use that mode, and everything
    51  *     would work fine.  However, we also abuse this API for performing in font-space,
    60  *     would work fine.  However, we also abuse this API for performing in font-space,
    52  *     but don't pass the correct flags to FreeType.  We just abuse the no-hinting mode
    61  *     but don't pass the correct flags to FreeType.  We just abuse the no-hinting mode
    53  *     for that, such that no rounding etc happens.  As such, we don't set ppem, and
    62  *     for that, such that no rounding etc happens.  As such, we don't set ppem, and
    54  *     pass NO_HINTING as load_flags.  Would be much better to use NO_SCALE, and scale
    63  *     pass NO_HINTING as load_flags.  Would be much better to use NO_SCALE, and scale
    55  *     ourselves, like we do in uniscribe, etc.
    64  *     ourselves.
    56  *
    65  *
    57  *   - We don't handle / allow for emboldening / obliqueing.
    66  *   - We don't handle / allow for emboldening / obliqueing.
    58  *
    67  *
    59  *   - In the future, we should add constructors to create fonts in font space?
    68  *   - In the future, we should add constructors to create fonts in font space?
    60  *
       
    61  *   - FT_Load_Glyph() is extremely costly.  Do something about it?
       
    62  */
    69  */
    63 
    70 
    64 
    71 
    65 struct hb_ft_font_t
    72 struct hb_ft_font_t
    66 {
    73 {
       
    74   mutable hb_mutex_t lock;
    67   FT_Face ft_face;
    75   FT_Face ft_face;
    68   int load_flags;
    76   int load_flags;
    69   bool symbol; /* Whether selected cmap is symbol cmap. */
    77   bool symbol; /* Whether selected cmap is symbol cmap. */
    70   bool unref; /* Whether to destroy ft_face when done. */
    78   bool unref; /* Whether to destroy ft_face when done. */
       
    79 
       
    80   mutable hb_atomic_int_t cached_x_scale;
       
    81   mutable hb_advance_cache_t advance_cache;
    71 };
    82 };
    72 
    83 
    73 static hb_ft_font_t *
    84 static hb_ft_font_t *
    74 _hb_ft_font_create (FT_Face ft_face, bool symbol, bool unref)
    85 _hb_ft_font_create (FT_Face ft_face, bool symbol, bool unref)
    75 {
    86 {
    76   hb_ft_font_t *ft_font = (hb_ft_font_t *) calloc (1, sizeof (hb_ft_font_t));
    87   hb_ft_font_t *ft_font = (hb_ft_font_t *) calloc (1, sizeof (hb_ft_font_t));
    77 
    88 
    78   if (unlikely (!ft_font))
    89   if (unlikely (!ft_font))
    79     return nullptr;
    90     return nullptr;
    80 
    91 
       
    92   ft_font->lock.init ();
    81   ft_font->ft_face = ft_face;
    93   ft_font->ft_face = ft_face;
    82   ft_font->symbol = symbol;
    94   ft_font->symbol = symbol;
    83   ft_font->unref = unref;
    95   ft_font->unref = unref;
    84 
    96 
    85   ft_font->load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING;
    97   ft_font->load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING;
    86 
    98 
       
    99   ft_font->cached_x_scale.set (0);
       
   100   ft_font->advance_cache.init ();
       
   101 
    87   return ft_font;
   102   return ft_font;
    88 }
   103 }
    89 
   104 
    90 static void
   105 static void
    91 _hb_ft_face_destroy (void *data)
   106 _hb_ft_face_destroy (void *data)
    96 static void
   111 static void
    97 _hb_ft_font_destroy (void *data)
   112 _hb_ft_font_destroy (void *data)
    98 {
   113 {
    99   hb_ft_font_t *ft_font = (hb_ft_font_t *) data;
   114   hb_ft_font_t *ft_font = (hb_ft_font_t *) data;
   100 
   115 
       
   116   ft_font->advance_cache.fini ();
       
   117 
   101   if (ft_font->unref)
   118   if (ft_font->unref)
   102     _hb_ft_face_destroy (ft_font->ft_face);
   119     _hb_ft_face_destroy (ft_font->ft_face);
       
   120 
       
   121   ft_font->lock.fini ();
   103 
   122 
   104   free (ft_font);
   123   free (ft_font);
   105 }
   124 }
   106 
   125 
   107 /**
   126 /**
   114  * Since: 1.0.5
   133  * Since: 1.0.5
   115  **/
   134  **/
   116 void
   135 void
   117 hb_ft_font_set_load_flags (hb_font_t *font, int load_flags)
   136 hb_ft_font_set_load_flags (hb_font_t *font, int load_flags)
   118 {
   137 {
   119   if (font->immutable)
   138   if (hb_object_is_immutable (font))
   120     return;
   139     return;
   121 
   140 
   122   if (font->destroy != (hb_destroy_func_t) _hb_ft_font_destroy)
   141   if (font->destroy != (hb_destroy_func_t) _hb_ft_font_destroy)
   123     return;
   142     return;
   124 
   143 
   166                          hb_codepoint_t unicode,
   185                          hb_codepoint_t unicode,
   167                          hb_codepoint_t *glyph,
   186                          hb_codepoint_t *glyph,
   168                          void *user_data HB_UNUSED)
   187                          void *user_data HB_UNUSED)
   169 {
   188 {
   170   const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
   189   const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
       
   190   hb_lock_t lock (ft_font->lock);
   171   unsigned int g = FT_Get_Char_Index (ft_font->ft_face, unicode);
   191   unsigned int g = FT_Get_Char_Index (ft_font->ft_face, unicode);
   172 
   192 
   173   if (unlikely (!g))
   193   if (unlikely (!g))
   174   {
   194   {
   175     if (unlikely (ft_font->symbol) && unicode <= 0x00FFu)
   195     if (unlikely (ft_font->symbol) && unicode <= 0x00FFu)
   189 
   209 
   190   *glyph = g;
   210   *glyph = g;
   191   return true;
   211   return true;
   192 }
   212 }
   193 
   213 
       
   214 static unsigned int
       
   215 hb_ft_get_nominal_glyphs (hb_font_t *font HB_UNUSED,
       
   216                           void *font_data,
       
   217                           unsigned int count,
       
   218                           const hb_codepoint_t *first_unicode,
       
   219                           unsigned int unicode_stride,
       
   220                           hb_codepoint_t *first_glyph,
       
   221                           unsigned int glyph_stride,
       
   222                           void *user_data HB_UNUSED)
       
   223 {
       
   224   const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
       
   225   hb_lock_t lock (ft_font->lock);
       
   226   unsigned int done;
       
   227   for (done = 0;
       
   228        done < count && (*first_glyph = FT_Get_Char_Index (ft_font->ft_face, *first_unicode));
       
   229        done++)
       
   230   {
       
   231     first_unicode = &StructAtOffsetUnaligned<hb_codepoint_t> (first_unicode, unicode_stride);
       
   232     first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
       
   233   }
       
   234   /* We don't need to do ft_font->symbol dance here, since HB calls the singular
       
   235    * nominal_glyph() for what we don't handle here. */
       
   236   return done;
       
   237 }
       
   238 
       
   239 
   194 static hb_bool_t
   240 static hb_bool_t
   195 hb_ft_get_variation_glyph (hb_font_t *font HB_UNUSED,
   241 hb_ft_get_variation_glyph (hb_font_t *font HB_UNUSED,
   196                            void *font_data,
   242                            void *font_data,
   197                            hb_codepoint_t unicode,
   243                            hb_codepoint_t unicode,
   198                            hb_codepoint_t variation_selector,
   244                            hb_codepoint_t variation_selector,
   199                            hb_codepoint_t *glyph,
   245                            hb_codepoint_t *glyph,
   200                            void *user_data HB_UNUSED)
   246                            void *user_data HB_UNUSED)
   201 {
   247 {
   202   const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
   248   const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
       
   249   hb_lock_t lock (ft_font->lock);
   203   unsigned int g = FT_Face_GetCharVariantIndex (ft_font->ft_face, unicode, variation_selector);
   250   unsigned int g = FT_Face_GetCharVariantIndex (ft_font->ft_face, unicode, variation_selector);
   204 
   251 
   205   if (unlikely (!g))
   252   if (unlikely (!g))
   206     return false;
   253     return false;
   207 
   254 
   208   *glyph = g;
   255   *glyph = g;
   209   return true;
   256   return true;
   210 }
   257 }
   211 
   258 
   212 static hb_position_t
   259 static void
   213 hb_ft_get_glyph_h_advance (hb_font_t *font,
   260 hb_ft_get_glyph_h_advances (hb_font_t* font, void* font_data,
   214                            void *font_data,
   261                             unsigned count,
   215                            hb_codepoint_t glyph,
   262                             const hb_codepoint_t *first_glyph,
   216                            void *user_data HB_UNUSED)
   263                             unsigned glyph_stride,
   217 {
   264                             hb_position_t *first_advance,
   218   const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
   265                             unsigned advance_stride,
   219   FT_Fixed v;
   266                             void *user_data HB_UNUSED)
   220 
   267 {
   221   if (unlikely (FT_Get_Advance (ft_font->ft_face, glyph, ft_font->load_flags, &v)))
   268   const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
   222     return 0;
   269   hb_lock_t lock (ft_font->lock);
   223 
   270   FT_Face ft_face = ft_font->ft_face;
   224   if (font->x_scale < 0)
   271   int load_flags = ft_font->load_flags;
   225     v = -v;
   272   int mult = font->x_scale < 0 ? -1 : +1;
   226 
   273 
   227   return (v + (1<<9)) >> 10;
   274   if (font->x_scale != ft_font->cached_x_scale.get ())
       
   275   {
       
   276     ft_font->advance_cache.clear ();
       
   277     ft_font->cached_x_scale.set (font->x_scale);
       
   278   }
       
   279 
       
   280   for (unsigned int i = 0; i < count; i++)
       
   281   {
       
   282     FT_Fixed v = 0;
       
   283     hb_codepoint_t glyph = *first_glyph;
       
   284 
       
   285     unsigned int cv;
       
   286     if (ft_font->advance_cache.get (glyph, &cv))
       
   287       v = cv;
       
   288     else
       
   289     {
       
   290       FT_Get_Advance (ft_face, glyph, load_flags, &v);
       
   291       ft_font->advance_cache.set (glyph, v);
       
   292     }
       
   293 
       
   294     *first_advance = (v * mult + (1<<9)) >> 10;
       
   295     first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
       
   296     first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
       
   297   }
   228 }
   298 }
   229 
   299 
   230 static hb_position_t
   300 static hb_position_t
   231 hb_ft_get_glyph_v_advance (hb_font_t *font,
   301 hb_ft_get_glyph_v_advance (hb_font_t *font,
   232                            void *font_data,
   302                            void *font_data,
   233                            hb_codepoint_t glyph,
   303                            hb_codepoint_t glyph,
   234                            void *user_data HB_UNUSED)
   304                            void *user_data HB_UNUSED)
   235 {
   305 {
   236   const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
   306   const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
       
   307   hb_lock_t lock (ft_font->lock);
   237   FT_Fixed v;
   308   FT_Fixed v;
   238 
   309 
   239   if (unlikely (FT_Get_Advance (ft_font->ft_face, glyph, ft_font->load_flags | FT_LOAD_VERTICAL_LAYOUT, &v)))
   310   if (unlikely (FT_Get_Advance (ft_font->ft_face, glyph, ft_font->load_flags | FT_LOAD_VERTICAL_LAYOUT, &v)))
   240     return 0;
   311     return 0;
   241 
   312 
   254                           hb_position_t *x,
   325                           hb_position_t *x,
   255                           hb_position_t *y,
   326                           hb_position_t *y,
   256                           void *user_data HB_UNUSED)
   327                           void *user_data HB_UNUSED)
   257 {
   328 {
   258   const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
   329   const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
       
   330   hb_lock_t lock (ft_font->lock);
   259   FT_Face ft_face = ft_font->ft_face;
   331   FT_Face ft_face = ft_font->ft_face;
   260 
   332 
   261   if (unlikely (FT_Load_Glyph (ft_face, glyph, ft_font->load_flags)))
   333   if (unlikely (FT_Load_Glyph (ft_face, glyph, ft_font->load_flags)))
   262     return false;
   334     return false;
   263 
   335 
   270     *x = -*x;
   342     *x = -*x;
   271   if (font->y_scale < 0)
   343   if (font->y_scale < 0)
   272     *y = -*y;
   344     *y = -*y;
   273 
   345 
   274   return true;
   346   return true;
   275 }
       
   276 
       
   277 static hb_position_t
       
   278 hb_ft_get_glyph_h_kerning (hb_font_t *font,
       
   279                            void *font_data,
       
   280                            hb_codepoint_t left_glyph,
       
   281                            hb_codepoint_t right_glyph,
       
   282                            void *user_data HB_UNUSED)
       
   283 {
       
   284   const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
       
   285   FT_Vector kerningv;
       
   286 
       
   287   FT_Kerning_Mode mode = font->x_ppem ? FT_KERNING_DEFAULT : FT_KERNING_UNFITTED;
       
   288   if (FT_Get_Kerning (ft_font->ft_face, left_glyph, right_glyph, mode, &kerningv))
       
   289     return 0;
       
   290 
       
   291   return kerningv.x;
       
   292 }
   347 }
   293 
   348 
   294 static hb_bool_t
   349 static hb_bool_t
   295 hb_ft_get_glyph_extents (hb_font_t *font,
   350 hb_ft_get_glyph_extents (hb_font_t *font,
   296                          void *font_data,
   351                          void *font_data,
   297                          hb_codepoint_t glyph,
   352                          hb_codepoint_t glyph,
   298                          hb_glyph_extents_t *extents,
   353                          hb_glyph_extents_t *extents,
   299                          void *user_data HB_UNUSED)
   354                          void *user_data HB_UNUSED)
   300 {
   355 {
   301   const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
   356   const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
       
   357   hb_lock_t lock (ft_font->lock);
   302   FT_Face ft_face = ft_font->ft_face;
   358   FT_Face ft_face = ft_font->ft_face;
   303 
   359 
   304   if (unlikely (FT_Load_Glyph (ft_face, glyph, ft_font->load_flags)))
   360   if (unlikely (FT_Load_Glyph (ft_face, glyph, ft_font->load_flags)))
   305     return false;
   361     return false;
   306 
   362 
   329                                hb_position_t *x,
   385                                hb_position_t *x,
   330                                hb_position_t *y,
   386                                hb_position_t *y,
   331                                void *user_data HB_UNUSED)
   387                                void *user_data HB_UNUSED)
   332 {
   388 {
   333   const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
   389   const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
       
   390   hb_lock_t lock (ft_font->lock);
   334   FT_Face ft_face = ft_font->ft_face;
   391   FT_Face ft_face = ft_font->ft_face;
   335 
   392 
   336   if (unlikely (FT_Load_Glyph (ft_face, glyph, ft_font->load_flags)))
   393   if (unlikely (FT_Load_Glyph (ft_face, glyph, ft_font->load_flags)))
   337       return false;
   394       return false;
   338 
   395 
   354                       hb_codepoint_t glyph,
   411                       hb_codepoint_t glyph,
   355                       char *name, unsigned int size,
   412                       char *name, unsigned int size,
   356                       void *user_data HB_UNUSED)
   413                       void *user_data HB_UNUSED)
   357 {
   414 {
   358   const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
   415   const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
   359 
   416   hb_lock_t lock (ft_font->lock);
   360   hb_bool_t ret = !FT_Get_Glyph_Name (ft_font->ft_face, glyph, name, size);
   417   FT_Face ft_face = ft_font->ft_face;
       
   418 
       
   419   hb_bool_t ret = !FT_Get_Glyph_Name (ft_face, glyph, name, size);
   361   if (ret && (size && !*name))
   420   if (ret && (size && !*name))
   362     ret = false;
   421     ret = false;
   363 
   422 
   364   return ret;
   423   return ret;
   365 }
   424 }
   370                            const char *name, int len, /* -1 means nul-terminated */
   429                            const char *name, int len, /* -1 means nul-terminated */
   371                            hb_codepoint_t *glyph,
   430                            hb_codepoint_t *glyph,
   372                            void *user_data HB_UNUSED)
   431                            void *user_data HB_UNUSED)
   373 {
   432 {
   374   const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
   433   const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
       
   434   hb_lock_t lock (ft_font->lock);
   375   FT_Face ft_face = ft_font->ft_face;
   435   FT_Face ft_face = ft_font->ft_face;
   376 
   436 
   377   if (len < 0)
   437   if (len < 0)
   378     *glyph = FT_Get_Name_Index (ft_face, (FT_String *) name);
   438     *glyph = FT_Get_Name_Index (ft_face, (FT_String *) name);
   379   else {
   439   else {
   402                           void *font_data,
   462                           void *font_data,
   403                           hb_font_extents_t *metrics,
   463                           hb_font_extents_t *metrics,
   404                           void *user_data HB_UNUSED)
   464                           void *user_data HB_UNUSED)
   405 {
   465 {
   406   const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
   466   const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
       
   467   hb_lock_t lock (ft_font->lock);
   407   FT_Face ft_face = ft_font->ft_face;
   468   FT_Face ft_face = ft_font->ft_face;
   408   metrics->ascender = ft_face->size->metrics.ascender;
   469   metrics->ascender = FT_MulFix(ft_face->ascender, ft_face->size->metrics.y_scale);
   409   metrics->descender = ft_face->size->metrics.descender;
   470   metrics->descender = FT_MulFix(ft_face->descender, ft_face->size->metrics.y_scale);
   410   metrics->line_gap = ft_face->size->metrics.height - (ft_face->size->metrics.ascender - ft_face->size->metrics.descender);
   471   metrics->line_gap = FT_MulFix( ft_face->height, ft_face->size->metrics.y_scale ) - (metrics->ascender - metrics->descender);
   411   if (font->y_scale < 0)
   472   if (font->y_scale < 0)
   412   {
   473   {
   413     metrics->ascender = -metrics->ascender;
   474     metrics->ascender = -metrics->ascender;
   414     metrics->descender = -metrics->descender;
   475     metrics->descender = -metrics->descender;
   415     metrics->line_gap = -metrics->line_gap;
   476     metrics->line_gap = -metrics->line_gap;
   416   }
   477   }
   417   return true;
   478   return true;
   418 }
   479 }
   419 
   480 
   420 static hb_font_funcs_t *static_ft_funcs = nullptr;
   481 #if HB_USE_ATEXIT
   421 
   482 static void free_static_ft_funcs ();
   422 #ifdef HB_USE_ATEXIT
   483 #endif
   423 static
   484 
   424 void free_static_ft_funcs (void)
   485 static struct hb_ft_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ft_font_funcs_lazy_loader_t>
   425 {
   486 {
   426 retry:
   487   static hb_font_funcs_t *create ()
   427   hb_font_funcs_t *ft_funcs = (hb_font_funcs_t *) hb_atomic_ptr_get (&static_ft_funcs);
   488   {
   428   if (!hb_atomic_ptr_cmpexch (&static_ft_funcs, ft_funcs, nullptr))
   489     hb_font_funcs_t *funcs = hb_font_funcs_create ();
   429     goto retry;
       
   430 
       
   431   hb_font_funcs_destroy (ft_funcs);
       
   432 }
       
   433 #endif
       
   434 
       
   435 static void
       
   436 _hb_ft_font_set_funcs (hb_font_t *font, FT_Face ft_face, bool unref)
       
   437 {
       
   438 retry:
       
   439   hb_font_funcs_t *funcs = (hb_font_funcs_t *) hb_atomic_ptr_get (&static_ft_funcs);
       
   440 
       
   441   if (unlikely (!funcs))
       
   442   {
       
   443     funcs = hb_font_funcs_create ();
       
   444 
   490 
   445     hb_font_funcs_set_font_h_extents_func (funcs, hb_ft_get_font_h_extents, nullptr, nullptr);
   491     hb_font_funcs_set_font_h_extents_func (funcs, hb_ft_get_font_h_extents, nullptr, nullptr);
   446     //hb_font_funcs_set_font_v_extents_func (funcs, hb_ft_get_font_v_extents, nullptr, nullptr);
   492     //hb_font_funcs_set_font_v_extents_func (funcs, hb_ft_get_font_v_extents, nullptr, nullptr);
   447     hb_font_funcs_set_nominal_glyph_func (funcs, hb_ft_get_nominal_glyph, nullptr, nullptr);
   493     hb_font_funcs_set_nominal_glyph_func (funcs, hb_ft_get_nominal_glyph, nullptr, nullptr);
       
   494     hb_font_funcs_set_nominal_glyphs_func (funcs, hb_ft_get_nominal_glyphs, nullptr, nullptr);
   448     hb_font_funcs_set_variation_glyph_func (funcs, hb_ft_get_variation_glyph, nullptr, nullptr);
   495     hb_font_funcs_set_variation_glyph_func (funcs, hb_ft_get_variation_glyph, nullptr, nullptr);
   449     hb_font_funcs_set_glyph_h_advance_func (funcs, hb_ft_get_glyph_h_advance, nullptr, nullptr);
   496     hb_font_funcs_set_glyph_h_advances_func (funcs, hb_ft_get_glyph_h_advances, nullptr, nullptr);
   450     hb_font_funcs_set_glyph_v_advance_func (funcs, hb_ft_get_glyph_v_advance, nullptr, nullptr);
   497     hb_font_funcs_set_glyph_v_advance_func (funcs, hb_ft_get_glyph_v_advance, nullptr, nullptr);
   451     //hb_font_funcs_set_glyph_h_origin_func (funcs, hb_ft_get_glyph_h_origin, nullptr, nullptr);
   498     //hb_font_funcs_set_glyph_h_origin_func (funcs, hb_ft_get_glyph_h_origin, nullptr, nullptr);
   452     hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ft_get_glyph_v_origin, nullptr, nullptr);
   499     hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ft_get_glyph_v_origin, nullptr, nullptr);
   453     hb_font_funcs_set_glyph_h_kerning_func (funcs, hb_ft_get_glyph_h_kerning, nullptr, nullptr);
       
   454     //hb_font_funcs_set_glyph_v_kerning_func (funcs, hb_ft_get_glyph_v_kerning, nullptr, nullptr);
       
   455     hb_font_funcs_set_glyph_extents_func (funcs, hb_ft_get_glyph_extents, nullptr, nullptr);
   500     hb_font_funcs_set_glyph_extents_func (funcs, hb_ft_get_glyph_extents, nullptr, nullptr);
   456     hb_font_funcs_set_glyph_contour_point_func (funcs, hb_ft_get_glyph_contour_point, nullptr, nullptr);
   501     hb_font_funcs_set_glyph_contour_point_func (funcs, hb_ft_get_glyph_contour_point, nullptr, nullptr);
   457     hb_font_funcs_set_glyph_name_func (funcs, hb_ft_get_glyph_name, nullptr, nullptr);
   502     hb_font_funcs_set_glyph_name_func (funcs, hb_ft_get_glyph_name, nullptr, nullptr);
   458     hb_font_funcs_set_glyph_from_name_func (funcs, hb_ft_get_glyph_from_name, nullptr, nullptr);
   503     hb_font_funcs_set_glyph_from_name_func (funcs, hb_ft_get_glyph_from_name, nullptr, nullptr);
   459 
   504 
   460     hb_font_funcs_make_immutable (funcs);
   505     hb_font_funcs_make_immutable (funcs);
   461 
   506 
   462     if (!hb_atomic_ptr_cmpexch (&static_ft_funcs, nullptr, funcs)) {
   507 #if HB_USE_ATEXIT
   463       hb_font_funcs_destroy (funcs);
   508     atexit (free_static_ft_funcs);
   464       goto retry;
   509 #endif
   465     }
   510 
   466 
   511     return funcs;
   467 #ifdef HB_USE_ATEXIT
   512   }
   468     atexit (free_static_ft_funcs); /* First person registers atexit() callback. */
   513 } static_ft_funcs;
   469 #endif
   514 
   470   };
   515 #if HB_USE_ATEXIT
   471 
   516 static
       
   517 void free_static_ft_funcs ()
       
   518 {
       
   519   static_ft_funcs.free_instance ();
       
   520 }
       
   521 #endif
       
   522 
       
   523 static hb_font_funcs_t *
       
   524 _hb_ft_get_font_funcs ()
       
   525 {
       
   526   return static_ft_funcs.get_unconst ();
       
   527 }
       
   528 
       
   529 static void
       
   530 _hb_ft_font_set_funcs (hb_font_t *font, FT_Face ft_face, bool unref)
       
   531 {
   472   bool symbol = ft_face->charmap && ft_face->charmap->encoding == FT_ENCODING_MS_SYMBOL;
   532   bool symbol = ft_face->charmap && ft_face->charmap->encoding == FT_ENCODING_MS_SYMBOL;
   473 
   533 
   474   hb_font_set_funcs (font,
   534   hb_font_set_funcs (font,
   475                      funcs,
   535                      _hb_ft_get_font_funcs (),
   476                      _hb_ft_font_create (ft_face, symbol, unref),
   536                      _hb_ft_font_create (ft_face, symbol, unref),
   477                      _hb_ft_font_destroy);
   537                      _hb_ft_font_destroy);
   478 }
   538 }
   479 
   539 
   480 
   540 
   495   buffer = (FT_Byte *) malloc (length);
   555   buffer = (FT_Byte *) malloc (length);
   496   if (!buffer)
   556   if (!buffer)
   497     return nullptr;
   557     return nullptr;
   498 
   558 
   499   error = FT_Load_Sfnt_Table (ft_face, tag, 0, buffer, &length);
   559   error = FT_Load_Sfnt_Table (ft_face, tag, 0, buffer, &length);
   500   if (error) {
   560   if (error)
       
   561   {
   501     free (buffer);
   562     free (buffer);
   502     return nullptr;
   563     return nullptr;
   503   }
   564   }
   504 
   565 
   505   return hb_blob_create ((const char *) buffer, length,
   566   return hb_blob_create ((const char *) buffer, length,
   681 {
   742 {
   682   FT_Reference_Face (ft_face);
   743   FT_Reference_Face (ft_face);
   683   return hb_ft_font_create (ft_face, _hb_ft_face_destroy);
   744   return hb_ft_font_create (ft_face, _hb_ft_face_destroy);
   684 }
   745 }
   685 
   746 
   686 
   747 #if HB_USE_ATEXIT
   687 /* Thread-safe, lock-free, FT_Library */
   748 static void free_static_ft_library ();
   688 
   749 #endif
   689 static FT_Library ft_library;
   750 
   690 
   751 static struct hb_ft_library_lazy_loader_t : hb_lazy_loader_t<hb_remove_pointer (FT_Library),
   691 #ifdef HB_USE_ATEXIT
   752                                                              hb_ft_library_lazy_loader_t>
       
   753 {
       
   754   static FT_Library create ()
       
   755   {
       
   756     FT_Library l;
       
   757     if (FT_Init_FreeType (&l))
       
   758       return nullptr;
       
   759 
       
   760 #if HB_USE_ATEXIT
       
   761     atexit (free_static_ft_library);
       
   762 #endif
       
   763 
       
   764     return l;
       
   765   }
       
   766   static void destroy (FT_Library l)
       
   767   {
       
   768     FT_Done_FreeType (l);
       
   769   }
       
   770   static FT_Library get_null ()
       
   771   {
       
   772     return nullptr;
       
   773   }
       
   774 } static_ft_library;
       
   775 
       
   776 #if HB_USE_ATEXIT
   692 static
   777 static
   693 void free_ft_library (void)
   778 void free_static_ft_library ()
   694 {
   779 {
   695 retry:
   780   static_ft_library.free_instance ();
   696   FT_Library library = (FT_Library) hb_atomic_ptr_get (&ft_library);
       
   697   if (!hb_atomic_ptr_cmpexch (&ft_library, library, nullptr))
       
   698     goto retry;
       
   699 
       
   700   FT_Done_FreeType (library);
       
   701 }
   781 }
   702 #endif
   782 #endif
   703 
   783 
   704 static FT_Library
   784 static FT_Library
   705 get_ft_library (void)
   785 get_ft_library ()
   706 {
   786 {
   707 retry:
   787   return static_ft_library.get_unconst ();
   708   FT_Library library = (FT_Library) hb_atomic_ptr_get (&ft_library);
       
   709 
       
   710   if (unlikely (!library))
       
   711   {
       
   712     /* Not found; allocate one. */
       
   713     if (FT_Init_FreeType (&library))
       
   714       return nullptr;
       
   715 
       
   716     if (!hb_atomic_ptr_cmpexch (&ft_library, nullptr, library)) {
       
   717       FT_Done_FreeType (library);
       
   718       goto retry;
       
   719     }
       
   720 
       
   721 #ifdef HB_USE_ATEXIT
       
   722     atexit (free_ft_library); /* First person registers atexit() callback. */
       
   723 #endif
       
   724   }
       
   725 
       
   726   return library;
       
   727 }
   788 }
   728 
   789 
   729 static void
   790 static void
   730 _release_blob (FT_Face ft_face)
   791 _release_blob (FT_Face ft_face)
   731 {
   792 {