src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-font.cc
changeset 48274 51772bf1fb0c
parent 47216 71c04702a3d5
child 50352 25db2c8f3cf8
equal deleted inserted replaced
48273:e2065f7505eb 48274:51772bf1fb0c
    34 #include "hb-ot-cbdt-table.hh"
    34 #include "hb-ot-cbdt-table.hh"
    35 #include "hb-ot-glyf-table.hh"
    35 #include "hb-ot-glyf-table.hh"
    36 #include "hb-ot-head-table.hh"
    36 #include "hb-ot-head-table.hh"
    37 #include "hb-ot-hhea-table.hh"
    37 #include "hb-ot-hhea-table.hh"
    38 #include "hb-ot-hmtx-table.hh"
    38 #include "hb-ot-hmtx-table.hh"
       
    39 #include "hb-ot-kern-table.hh"
    39 #include "hb-ot-os2-table.hh"
    40 #include "hb-ot-os2-table.hh"
    40 //#include "hb-ot-post-table.hh"
    41 #include "hb-ot-post-table.hh"
       
    42 #include "hb-ot-var-hvar-table.hh"
    41 
    43 
    42 
    44 
    43 struct hb_ot_face_metrics_accelerator_t
    45 struct hb_ot_face_metrics_accelerator_t
    44 {
    46 {
    45   unsigned int num_metrics;
    47   unsigned int num_metrics;
    48   unsigned short ascender;
    50   unsigned short ascender;
    49   unsigned short descender;
    51   unsigned short descender;
    50   unsigned short line_gap;
    52   unsigned short line_gap;
    51   bool has_font_extents;
    53   bool has_font_extents;
    52 
    54 
    53   const OT::_mtx *table;
    55   const OT::hmtxvmtx *table;
    54   hb_blob_t *blob;
    56   hb_blob_t *blob;
       
    57 
       
    58   const OT::HVARVVAR *var;
       
    59   hb_blob_t *var_blob;
    55 
    60 
    56   inline void init (hb_face_t *face,
    61   inline void init (hb_face_t *face,
    57                     hb_tag_t _hea_tag,
    62                     hb_tag_t _hea_tag,
    58                     hb_tag_t _mtx_tag,
    63                     hb_tag_t _mtx_tag,
       
    64                     hb_tag_t _var_tag,
    59                     hb_tag_t os2_tag,
    65                     hb_tag_t os2_tag,
    60                     unsigned int default_advance = 0)
    66                     unsigned int default_advance = 0)
    61   {
    67   {
    62     this->default_advance = default_advance ? default_advance : face->get_upem ();
    68     this->default_advance = default_advance ? default_advance : face->get_upem ();
    63 
    69 
    89     }
    95     }
    90     hb_blob_destroy (_hea_blob);
    96     hb_blob_destroy (_hea_blob);
    91 
    97 
    92     this->has_font_extents = got_font_extents;
    98     this->has_font_extents = got_font_extents;
    93 
    99 
    94     this->blob = OT::Sanitizer<OT::_mtx>::sanitize (face->reference_table (_mtx_tag));
   100     this->blob = OT::Sanitizer<OT::hmtxvmtx>::sanitize (face->reference_table (_mtx_tag));
    95 
   101 
    96     /* Cap num_metrics() and num_advances() based on table length. */
   102     /* Cap num_metrics() and num_advances() based on table length. */
    97     unsigned int len = hb_blob_get_length (this->blob);
   103     unsigned int len = hb_blob_get_length (this->blob);
    98     if (unlikely (this->num_advances * 4 > len))
   104     if (unlikely (this->num_advances * 4 > len))
    99       this->num_advances = len / 4;
   105       this->num_advances = len / 4;
   105     {
   111     {
   106       this->num_metrics = this->num_advances = 0;
   112       this->num_metrics = this->num_advances = 0;
   107       hb_blob_destroy (this->blob);
   113       hb_blob_destroy (this->blob);
   108       this->blob = hb_blob_get_empty ();
   114       this->blob = hb_blob_get_empty ();
   109     }
   115     }
   110     this->table = OT::Sanitizer<OT::_mtx>::lock_instance (this->blob);
   116     this->table = OT::Sanitizer<OT::hmtxvmtx>::lock_instance (this->blob);
       
   117 
       
   118     this->var_blob = OT::Sanitizer<OT::HVARVVAR>::sanitize (face->reference_table (_var_tag));
       
   119     this->var = OT::Sanitizer<OT::HVARVVAR>::lock_instance (this->var_blob);
   111   }
   120   }
   112 
   121 
   113   inline void fini (void)
   122   inline void fini (void)
   114   {
   123   {
   115     hb_blob_destroy (this->blob);
   124     hb_blob_destroy (this->blob);
   116   }
   125     hb_blob_destroy (this->var_blob);
   117 
   126   }
   118   inline unsigned int get_advance (hb_codepoint_t glyph) const
   127 
       
   128   inline unsigned int get_advance (hb_codepoint_t  glyph,
       
   129                                    hb_font_t      *font) const
   119   {
   130   {
   120     if (unlikely (glyph >= this->num_metrics))
   131     if (unlikely (glyph >= this->num_metrics))
   121     {
   132     {
   122       /* If this->num_metrics is zero, it means we don't have the metrics table
   133       /* If this->num_metrics is zero, it means we don't have the metrics table
   123        * for this direction: return default advance.  Otherwise, it means that the
   134        * for this direction: return default advance.  Otherwise, it means that the
   126         return 0;
   137         return 0;
   127       else
   138       else
   128         return this->default_advance;
   139         return this->default_advance;
   129     }
   140     }
   130 
   141 
   131     if (glyph >= this->num_advances)
   142     return this->table->longMetric[MIN (glyph, (uint32_t) this->num_advances - 1)].advance
   132       glyph = this->num_advances - 1;
   143          + this->var->get_advance_var (glyph, font->coords, font->num_coords); // TODO Optimize?!
   133 
       
   134     return this->table->longMetric[glyph].advance;
       
   135   }
   144   }
   136 };
   145 };
   137 
   146 
   138 struct hb_ot_face_glyf_accelerator_t
   147 struct hb_ot_face_glyf_accelerator_t
   139 {
   148 {
   214   hb_blob_t *cbdt_blob;
   223   hb_blob_t *cbdt_blob;
   215   const OT::CBLC *cblc;
   224   const OT::CBLC *cblc;
   216   const OT::CBDT *cbdt;
   225   const OT::CBDT *cbdt;
   217 
   226 
   218   unsigned int cbdt_len;
   227   unsigned int cbdt_len;
   219   float upem;
   228   unsigned int upem;
   220 
   229 
   221   inline void init (hb_face_t *face)
   230   inline void init (hb_face_t *face)
   222   {
   231   {
   223     upem = face->get_upem();
   232     upem = face->get_upem();
   224 
   233 
   225     cblc_blob = OT::Sanitizer<OT::CBLC>::sanitize (face->reference_table (HB_OT_TAG_CBLC));
   234     cblc_blob = OT::Sanitizer<OT::CBLC>::sanitize (face->reference_table (HB_OT_TAG_CBLC));
   226     cbdt_blob = OT::Sanitizer<OT::CBDT>::sanitize (face->reference_table (HB_OT_TAG_CBDT));
   235     cbdt_blob = OT::Sanitizer<OT::CBDT>::sanitize (face->reference_table (HB_OT_TAG_CBDT));
   227     cbdt_len = hb_blob_get_length (cbdt_blob);
   236     cbdt_len = hb_blob_get_length (cbdt_blob);
   228 
   237 
   229     if (hb_blob_get_length (cblc_blob) == 0) {
   238     if (hb_blob_get_length (cblc_blob) == 0) {
   230       cblc = NULL;
   239       cblc = nullptr;
   231       cbdt = NULL;
   240       cbdt = nullptr;
   232       return;  /* Not a bitmap font. */
   241       return;  /* Not a bitmap font. */
   233     }
   242     }
   234     cblc = OT::Sanitizer<OT::CBLC>::lock_instance (cblc_blob);
   243     cblc = OT::Sanitizer<OT::CBLC>::lock_instance (cblc_blob);
   235     cbdt = OT::Sanitizer<OT::CBDT>::lock_instance (cbdt_blob);
   244     cbdt = OT::Sanitizer<OT::CBDT>::lock_instance (cbdt_blob);
   236 
   245 
   244 
   253 
   245   inline bool get_extents (hb_codepoint_t glyph, hb_glyph_extents_t *extents) const
   254   inline bool get_extents (hb_codepoint_t glyph, hb_glyph_extents_t *extents) const
   246   {
   255   {
   247     unsigned int x_ppem = upem, y_ppem = upem; /* TODO Use font ppem if available. */
   256     unsigned int x_ppem = upem, y_ppem = upem; /* TODO Use font ppem if available. */
   248 
   257 
   249     if (cblc == NULL)
   258     if (!cblc)
   250       return false;  // Not a color bitmap font.
   259       return false;  // Not a color bitmap font.
   251 
   260 
   252     const OT::IndexSubtableRecord *subtable_record = this->cblc->find_table(glyph, &x_ppem, &y_ppem);
   261     const OT::IndexSubtableRecord *subtable_record = this->cblc->find_table(glyph, &x_ppem, &y_ppem);
   253     if (subtable_record == NULL)
   262     if (!subtable_record || !x_ppem || !y_ppem)
   254       return false;
   263       return false;
   255 
   264 
   256     if (subtable_record->get_extents (extents))
   265     if (subtable_record->get_extents (extents))
   257       return true;
   266       return true;
   258 
   267 
   291 
   300 
   292     return true;
   301     return true;
   293   }
   302   }
   294 };
   303 };
   295 
   304 
       
   305 struct hb_ot_face_post_accelerator_t
       
   306 {
       
   307   hb_blob_t *post_blob;
       
   308   OT::post::accelerator_t accel;
       
   309 
       
   310   inline void init (hb_face_t *face)
       
   311   {
       
   312     hb_blob_t *blob = this->post_blob = OT::Sanitizer<OT::post>::sanitize (face->reference_table (HB_OT_TAG_post));
       
   313     accel.init (OT::Sanitizer<OT::post>::lock_instance (blob), hb_blob_get_length (blob));
       
   314   }
       
   315 
       
   316   inline void fini (void)
       
   317   {
       
   318     accel.fini ();
       
   319     hb_blob_destroy (this->post_blob);
       
   320   }
       
   321 
       
   322   inline bool get_glyph_name (hb_codepoint_t glyph,
       
   323                               char *name, unsigned int size) const
       
   324   {
       
   325     return this->accel.get_glyph_name (glyph, name, size);
       
   326   }
       
   327 
       
   328   inline bool get_glyph_from_name (const char *name, int len,
       
   329                                    hb_codepoint_t *glyph) const
       
   330   {
       
   331     if (unlikely (!len))
       
   332       return false;
       
   333 
       
   334     return this->accel.get_glyph_from_name (name, len, glyph);
       
   335   }
       
   336 };
       
   337 
       
   338 struct hb_ot_face_kern_accelerator_t
       
   339 {
       
   340   hb_blob_t *kern_blob;
       
   341   OT::kern::accelerator_t accel;
       
   342 
       
   343   inline void init (hb_face_t *face)
       
   344   {
       
   345     hb_blob_t *blob = this->kern_blob = OT::Sanitizer<OT::kern>::sanitize (face->reference_table (HB_OT_TAG_kern));
       
   346     accel.init (OT::Sanitizer<OT::kern>::lock_instance (blob), hb_blob_get_length (blob));
       
   347   }
       
   348 
       
   349   inline void fini (void)
       
   350   {
       
   351     accel.fini ();
       
   352     hb_blob_destroy (this->kern_blob);
       
   353   }
       
   354 
       
   355   inline int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right) const
       
   356   { return accel.get_h_kerning (left, right); }
       
   357 };
       
   358 
   296 typedef bool (*hb_cmap_get_glyph_func_t) (const void *obj,
   359 typedef bool (*hb_cmap_get_glyph_func_t) (const void *obj,
   297                                           hb_codepoint_t codepoint,
   360                                           hb_codepoint_t codepoint,
   298                                           hb_codepoint_t *glyph);
   361                                           hb_codepoint_t *glyph);
   299 
   362 
   300 template <typename Type>
   363 template <typename Type>
   339 
   402 
   340   inline void init (hb_face_t *face)
   403   inline void init (hb_face_t *face)
   341   {
   404   {
   342     this->blob = OT::Sanitizer<OT::cmap>::sanitize (face->reference_table (HB_OT_TAG_cmap));
   405     this->blob = OT::Sanitizer<OT::cmap>::sanitize (face->reference_table (HB_OT_TAG_cmap));
   343     const OT::cmap *cmap = OT::Sanitizer<OT::cmap>::lock_instance (this->blob);
   406     const OT::cmap *cmap = OT::Sanitizer<OT::cmap>::lock_instance (this->blob);
   344     const OT::CmapSubtable *subtable = NULL;
   407     const OT::CmapSubtable *subtable = nullptr;
   345     const OT::CmapSubtableFormat14 *subtable_uvs = NULL;
   408     const OT::CmapSubtableFormat14 *subtable_uvs = nullptr;
   346 
   409 
   347     bool symbol = false;
   410     bool symbol = false;
   348     /* 32-bit subtables. */
   411     /* 32-bit subtables. */
   349     if (!subtable) subtable = cmap->find_subtable (3, 10);
   412     if (!subtable) subtable = cmap->find_subtable (3, 10);
   350     if (!subtable) subtable = cmap->find_subtable (0, 6);
   413     if (!subtable) subtable = cmap->find_subtable (0, 6);
   419 
   482 
   420     return get_nominal_glyph (unicode, glyph);
   483     return get_nominal_glyph (unicode, glyph);
   421   }
   484   }
   422 };
   485 };
   423 
   486 
   424 template <typename T>
       
   425 struct hb_lazy_loader_t
       
   426 {
       
   427   inline void init (hb_face_t *face_)
       
   428   {
       
   429     face = face_;
       
   430     instance = NULL;
       
   431   }
       
   432 
       
   433   inline void fini (void)
       
   434   {
       
   435     if (instance && instance != &OT::Null(T))
       
   436     {
       
   437       instance->fini();
       
   438       free (instance);
       
   439     }
       
   440   }
       
   441 
       
   442   inline const T* operator-> (void) const
       
   443   {
       
   444   retry:
       
   445     T *p = (T *) hb_atomic_ptr_get (&instance);
       
   446     if (unlikely (!p))
       
   447     {
       
   448       p = (T *) calloc (1, sizeof (T));
       
   449       if (unlikely (!p))
       
   450         return &OT::Null(T);
       
   451       p->init (face);
       
   452       if (unlikely (!hb_atomic_ptr_cmpexch (const_cast<T **>(&instance), NULL, p)))
       
   453       {
       
   454         p->fini ();
       
   455         goto retry;
       
   456       }
       
   457     }
       
   458     return p;
       
   459   }
       
   460 
       
   461   private:
       
   462   hb_face_t *face;
       
   463   T *instance;
       
   464 };
       
   465 
       
   466 struct hb_ot_font_t
   487 struct hb_ot_font_t
   467 {
   488 {
   468   hb_ot_face_cmap_accelerator_t cmap;
   489   hb_ot_face_cmap_accelerator_t cmap;
   469   hb_ot_face_metrics_accelerator_t h_metrics;
   490   hb_ot_face_metrics_accelerator_t h_metrics;
   470   hb_ot_face_metrics_accelerator_t v_metrics;
   491   hb_ot_face_metrics_accelerator_t v_metrics;
   471   hb_lazy_loader_t<hb_ot_face_glyf_accelerator_t> glyf;
   492   OT::hb_lazy_loader_t<hb_ot_face_glyf_accelerator_t> glyf;
   472   hb_lazy_loader_t<hb_ot_face_cbdt_accelerator_t> cbdt;
   493   OT::hb_lazy_loader_t<hb_ot_face_cbdt_accelerator_t> cbdt;
       
   494   OT::hb_lazy_loader_t<hb_ot_face_post_accelerator_t> post;
       
   495   OT::hb_lazy_loader_t<hb_ot_face_kern_accelerator_t> kern;
   473 };
   496 };
   474 
   497 
   475 
   498 
   476 static hb_ot_font_t *
   499 static hb_ot_font_t *
   477 _hb_ot_font_create (hb_face_t *face)
   500 _hb_ot_font_create (hb_face_t *face)
   478 {
   501 {
   479   hb_ot_font_t *ot_font = (hb_ot_font_t *) calloc (1, sizeof (hb_ot_font_t));
   502   hb_ot_font_t *ot_font = (hb_ot_font_t *) calloc (1, sizeof (hb_ot_font_t));
   480 
   503 
   481   if (unlikely (!ot_font))
   504   if (unlikely (!ot_font))
   482     return NULL;
   505     return nullptr;
   483 
   506 
   484   ot_font->cmap.init (face);
   507   ot_font->cmap.init (face);
   485   ot_font->h_metrics.init (face, HB_OT_TAG_hhea, HB_OT_TAG_hmtx, HB_OT_TAG_os2);
   508   ot_font->h_metrics.init (face, HB_OT_TAG_hhea, HB_OT_TAG_hmtx, HB_OT_TAG_HVAR, HB_OT_TAG_os2);
   486   ot_font->v_metrics.init (face, HB_OT_TAG_vhea, HB_OT_TAG_vmtx, HB_TAG_NONE,
   509   ot_font->v_metrics.init (face, HB_OT_TAG_vhea, HB_OT_TAG_vmtx, HB_OT_TAG_VVAR, HB_TAG_NONE,
   487                            ot_font->h_metrics.ascender - ot_font->h_metrics.descender); /* TODO Can we do this lazily? */
   510                            ot_font->h_metrics.ascender - ot_font->h_metrics.descender); /* TODO Can we do this lazily? */
   488   ot_font->glyf.init (face);
   511   ot_font->glyf.init (face);
   489   ot_font->cbdt.init (face);
   512   ot_font->cbdt.init (face);
       
   513   ot_font->post.init (face);
       
   514   ot_font->kern.init (face);
   490 
   515 
   491   return ot_font;
   516   return ot_font;
   492 }
   517 }
   493 
   518 
   494 static void
   519 static void
   495 _hb_ot_font_destroy (hb_ot_font_t *ot_font)
   520 _hb_ot_font_destroy (void *data)
   496 {
   521 {
       
   522   hb_ot_font_t *ot_font = (hb_ot_font_t *) data;
       
   523 
   497   ot_font->cmap.fini ();
   524   ot_font->cmap.fini ();
   498   ot_font->h_metrics.fini ();
   525   ot_font->h_metrics.fini ();
   499   ot_font->v_metrics.fini ();
   526   ot_font->v_metrics.fini ();
   500   ot_font->glyf.fini ();
   527   ot_font->glyf.fini ();
   501   ot_font->cbdt.fini ();
   528   ot_font->cbdt.fini ();
       
   529   ot_font->post.fini ();
       
   530   ot_font->kern.fini ();
   502 
   531 
   503   free (ot_font);
   532   free (ot_font);
   504 }
   533 }
   505 
   534 
   506 
   535 
   527   const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
   556   const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
   528   return ot_font->cmap.get_variation_glyph (unicode, variation_selector, glyph);
   557   return ot_font->cmap.get_variation_glyph (unicode, variation_selector, glyph);
   529 }
   558 }
   530 
   559 
   531 static hb_position_t
   560 static hb_position_t
   532 hb_ot_get_glyph_h_advance (hb_font_t *font HB_UNUSED,
   561 hb_ot_get_glyph_h_advance (hb_font_t *font,
   533                            void *font_data,
   562                            void *font_data,
   534                            hb_codepoint_t glyph,
   563                            hb_codepoint_t glyph,
   535                            void *user_data HB_UNUSED)
   564                            void *user_data HB_UNUSED)
   536 {
   565 {
   537   const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
   566   const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
   538   return font->em_scale_x (ot_font->h_metrics.get_advance (glyph));
   567   return font->em_scale_x (ot_font->h_metrics.get_advance (glyph, font));
   539 }
   568 }
   540 
   569 
   541 static hb_position_t
   570 static hb_position_t
   542 hb_ot_get_glyph_v_advance (hb_font_t *font HB_UNUSED,
   571 hb_ot_get_glyph_v_advance (hb_font_t *font,
   543                            void *font_data,
   572                            void *font_data,
   544                            hb_codepoint_t glyph,
   573                            hb_codepoint_t glyph,
   545                            void *user_data HB_UNUSED)
   574                            void *user_data HB_UNUSED)
   546 {
   575 {
   547   const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
   576   const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
   548   return font->em_scale_y (-(int) ot_font->v_metrics.get_advance (glyph));
   577   return font->em_scale_y (-(int) ot_font->v_metrics.get_advance (glyph, font));
       
   578 }
       
   579 
       
   580 static hb_position_t
       
   581 hb_ot_get_glyph_h_kerning (hb_font_t *font,
       
   582                            void *font_data,
       
   583                            hb_codepoint_t left_glyph,
       
   584                            hb_codepoint_t right_glyph,
       
   585                            void *user_data HB_UNUSED)
       
   586 {
       
   587   const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
       
   588   return font->em_scale_x (ot_font->kern->get_h_kerning (left_glyph, right_glyph));
   549 }
   589 }
   550 
   590 
   551 static hb_bool_t
   591 static hb_bool_t
   552 hb_ot_get_glyph_extents (hb_font_t *font HB_UNUSED,
   592 hb_ot_get_glyph_extents (hb_font_t *font HB_UNUSED,
   553                          void *font_data,
   593                          void *font_data,
   557 {
   597 {
   558   const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
   598   const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
   559   bool ret = ot_font->glyf->get_extents (glyph, extents);
   599   bool ret = ot_font->glyf->get_extents (glyph, extents);
   560   if (!ret)
   600   if (!ret)
   561     ret = ot_font->cbdt->get_extents (glyph, extents);
   601     ret = ot_font->cbdt->get_extents (glyph, extents);
       
   602   // TODO Hook up side-bearings variations.
   562   extents->x_bearing = font->em_scale_x (extents->x_bearing);
   603   extents->x_bearing = font->em_scale_x (extents->x_bearing);
   563   extents->y_bearing = font->em_scale_y (extents->y_bearing);
   604   extents->y_bearing = font->em_scale_y (extents->y_bearing);
   564   extents->width     = font->em_scale_x (extents->width);
   605   extents->width     = font->em_scale_x (extents->width);
   565   extents->height    = font->em_scale_y (extents->height);
   606   extents->height    = font->em_scale_y (extents->height);
   566   return ret;
   607   return ret;
   567 }
   608 }
   568 
   609 
   569 static hb_bool_t
   610 static hb_bool_t
       
   611 hb_ot_get_glyph_name (hb_font_t *font HB_UNUSED,
       
   612                       void *font_data,
       
   613                       hb_codepoint_t glyph,
       
   614                       char *name, unsigned int size,
       
   615                       void *user_data HB_UNUSED)
       
   616 {
       
   617   const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
       
   618   return ot_font->post->get_glyph_name (glyph, name, size);
       
   619 }
       
   620 
       
   621 static hb_bool_t
       
   622 hb_ot_get_glyph_from_name (hb_font_t *font HB_UNUSED,
       
   623                            void *font_data,
       
   624                            const char *name, int len,
       
   625                            hb_codepoint_t *glyph,
       
   626                            void *user_data HB_UNUSED)
       
   627 {
       
   628   const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
       
   629   return ot_font->post->get_glyph_from_name (name, len, glyph);
       
   630 }
       
   631 
       
   632 static hb_bool_t
   570 hb_ot_get_font_h_extents (hb_font_t *font HB_UNUSED,
   633 hb_ot_get_font_h_extents (hb_font_t *font HB_UNUSED,
   571                           void *font_data,
   634                           void *font_data,
   572                           hb_font_extents_t *metrics,
   635                           hb_font_extents_t *metrics,
   573                           void *user_data HB_UNUSED)
   636                           void *user_data HB_UNUSED)
   574 {
   637 {
   575   const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
   638   const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
   576   metrics->ascender = font->em_scale_y (ot_font->h_metrics.ascender);
   639   metrics->ascender = font->em_scale_y (ot_font->h_metrics.ascender);
   577   metrics->descender = font->em_scale_y (ot_font->h_metrics.descender);
   640   metrics->descender = font->em_scale_y (ot_font->h_metrics.descender);
   578   metrics->line_gap = font->em_scale_y (ot_font->h_metrics.line_gap);
   641   metrics->line_gap = font->em_scale_y (ot_font->h_metrics.line_gap);
       
   642   // TODO Hook up variations.
   579   return ot_font->h_metrics.has_font_extents;
   643   return ot_font->h_metrics.has_font_extents;
   580 }
   644 }
   581 
   645 
   582 static hb_bool_t
   646 static hb_bool_t
   583 hb_ot_get_font_v_extents (hb_font_t *font HB_UNUSED,
   647 hb_ot_get_font_v_extents (hb_font_t *font HB_UNUSED,
   587 {
   651 {
   588   const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
   652   const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
   589   metrics->ascender = font->em_scale_x (ot_font->v_metrics.ascender);
   653   metrics->ascender = font->em_scale_x (ot_font->v_metrics.ascender);
   590   metrics->descender = font->em_scale_x (ot_font->v_metrics.descender);
   654   metrics->descender = font->em_scale_x (ot_font->v_metrics.descender);
   591   metrics->line_gap = font->em_scale_x (ot_font->v_metrics.line_gap);
   655   metrics->line_gap = font->em_scale_x (ot_font->v_metrics.line_gap);
       
   656   // TODO Hook up variations.
   592   return ot_font->v_metrics.has_font_extents;
   657   return ot_font->v_metrics.has_font_extents;
   593 }
   658 }
   594 
   659 
   595 static hb_font_funcs_t *static_ot_funcs = NULL;
   660 static hb_font_funcs_t *static_ot_funcs = nullptr;
   596 
   661 
   597 #ifdef HB_USE_ATEXIT
   662 #ifdef HB_USE_ATEXIT
   598 static
   663 static
   599 void free_static_ot_funcs (void)
   664 void free_static_ot_funcs (void)
   600 {
   665 {
   610 
   675 
   611   if (unlikely (!funcs))
   676   if (unlikely (!funcs))
   612   {
   677   {
   613     funcs = hb_font_funcs_create ();
   678     funcs = hb_font_funcs_create ();
   614 
   679 
   615     hb_font_funcs_set_font_h_extents_func (funcs, hb_ot_get_font_h_extents, NULL, NULL);
   680     hb_font_funcs_set_font_h_extents_func (funcs, hb_ot_get_font_h_extents, nullptr, nullptr);
   616     hb_font_funcs_set_font_v_extents_func (funcs, hb_ot_get_font_v_extents, NULL, NULL);
   681     hb_font_funcs_set_font_v_extents_func (funcs, hb_ot_get_font_v_extents, nullptr, nullptr);
   617     hb_font_funcs_set_nominal_glyph_func (funcs, hb_ot_get_nominal_glyph, NULL, NULL);
   682     hb_font_funcs_set_nominal_glyph_func (funcs, hb_ot_get_nominal_glyph, nullptr, nullptr);
   618     hb_font_funcs_set_variation_glyph_func (funcs, hb_ot_get_variation_glyph, NULL, NULL);
   683     hb_font_funcs_set_variation_glyph_func (funcs, hb_ot_get_variation_glyph, nullptr, nullptr);
   619     hb_font_funcs_set_glyph_h_advance_func (funcs, hb_ot_get_glyph_h_advance, NULL, NULL);
   684     hb_font_funcs_set_glyph_h_advance_func (funcs, hb_ot_get_glyph_h_advance, nullptr, nullptr);
   620     hb_font_funcs_set_glyph_v_advance_func (funcs, hb_ot_get_glyph_v_advance, NULL, NULL);
   685     hb_font_funcs_set_glyph_v_advance_func (funcs, hb_ot_get_glyph_v_advance, nullptr, nullptr);
   621     //hb_font_funcs_set_glyph_h_origin_func (funcs, hb_ot_get_glyph_h_origin, NULL, NULL);
   686     //hb_font_funcs_set_glyph_h_origin_func (funcs, hb_ot_get_glyph_h_origin, nullptr, nullptr);
   622     //hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ot_get_glyph_v_origin, NULL, NULL);
   687     //hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ot_get_glyph_v_origin, nullptr, nullptr);
   623     //hb_font_funcs_set_glyph_h_kerning_func (funcs, hb_ot_get_glyph_h_kerning, NULL, NULL); TODO
   688     hb_font_funcs_set_glyph_h_kerning_func (funcs, hb_ot_get_glyph_h_kerning, nullptr, nullptr);
   624     //hb_font_funcs_set_glyph_v_kerning_func (funcs, hb_ot_get_glyph_v_kerning, NULL, NULL);
   689     //hb_font_funcs_set_glyph_v_kerning_func (funcs, hb_ot_get_glyph_v_kerning, nullptr, nullptr);
   625     hb_font_funcs_set_glyph_extents_func (funcs, hb_ot_get_glyph_extents, NULL, NULL);
   690     hb_font_funcs_set_glyph_extents_func (funcs, hb_ot_get_glyph_extents, nullptr, nullptr);
   626     //hb_font_funcs_set_glyph_contour_point_func (funcs, hb_ot_get_glyph_contour_point, NULL, NULL); TODO
   691     //hb_font_funcs_set_glyph_contour_point_func (funcs, hb_ot_get_glyph_contour_point, nullptr, nullptr); TODO
   627     //hb_font_funcs_set_glyph_name_func (funcs, hb_ot_get_glyph_name, NULL, NULL); TODO
   692     hb_font_funcs_set_glyph_name_func (funcs, hb_ot_get_glyph_name, nullptr, nullptr);
   628     //hb_font_funcs_set_glyph_from_name_func (funcs, hb_ot_get_glyph_from_name, NULL, NULL); TODO
   693     hb_font_funcs_set_glyph_from_name_func (funcs, hb_ot_get_glyph_from_name, nullptr, nullptr);
   629 
   694 
   630     hb_font_funcs_make_immutable (funcs);
   695     hb_font_funcs_make_immutable (funcs);
   631 
   696 
   632     if (!hb_atomic_ptr_cmpexch (&static_ot_funcs, NULL, funcs)) {
   697     if (!hb_atomic_ptr_cmpexch (&static_ot_funcs, nullptr, funcs)) {
   633       hb_font_funcs_destroy (funcs);
   698       hb_font_funcs_destroy (funcs);
   634       goto retry;
   699       goto retry;
   635     }
   700     }
   636 
   701 
   637 #ifdef HB_USE_ATEXIT
   702 #ifdef HB_USE_ATEXIT
   656     return;
   721     return;
   657 
   722 
   658   hb_font_set_funcs (font,
   723   hb_font_set_funcs (font,
   659                      _hb_ot_get_font_funcs (),
   724                      _hb_ot_get_font_funcs (),
   660                      ot_font,
   725                      ot_font,
   661                      (hb_destroy_func_t) _hb_ot_font_destroy);
   726                      _hb_ot_font_destroy);
   662 }
   727 }