src/hb-ot-font.cc         |  208 +++++++++++++++++++++++++++++-----------------
 src/hb-ot-hhea-table.hh   |   63 +++++++------
 src/hb-ot-hmtx-table.hh   |   35 ++++---
 util/helper-cairo-ansi.cc |    4 
 4 files changed, 189 insertions(+), 121 deletions(-)

New commits:
commit 80f77282264afb1356351024b1f062b2824bba3b
Author: Behdad Esfahbod <beh...@behdad.org>
Date:   Thu Sep 25 17:59:46 2014 +0300

    [util] Fix ansi output when surface is empty

diff --git a/util/helper-cairo-ansi.cc b/util/helper-cairo-ansi.cc
index 376bf2b..50f9eb4 100644
--- a/util/helper-cairo-ansi.cc
+++ b/util/helper-cairo-ansi.cc
@@ -63,10 +63,10 @@ helper_cairo_surface_write_to_ansi_stream (cairo_surface_t  
*surface,
    * Find the tight image top/bottom and only print in between. */
 
   /* Use corner color as background color. */
-  uint32_t bg_color = * (uint32_t *) data;
+  uint32_t bg_color = data ? * (uint32_t *) data : 0;
 
   /* Drop first row while empty */
-  while (height) 
+  while (height)
   {
     unsigned int i;
     for (i = 0; i < width; i++)
commit 156852991e18e5ac256ee4d6b2916931cc274977
Author: Behdad Esfahbod <beh...@behdad.org>
Date:   Thu Sep 25 17:45:49 2014 +0300

    [ot-font] Add hb_ot_face_cmap_accelerator_t

diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc
index 91df5ca..2af2f54 100644
--- a/src/hb-ot-font.cc
+++ b/src/hb-ot-font.cc
@@ -91,14 +91,72 @@ struct hb_ot_face_metrics_accelerator_t
   }
 };
 
+struct hb_ot_face_cmap_accelerator_t
+{
+  const OT::CmapSubtable *table;
+  const OT::CmapSubtable *uvs_table;
+  hb_blob_t *blob;
+
+  inline void init (hb_face_t *face)
+  {
+    this->blob = OT::Sanitizer<OT::cmap>::sanitize (face->reference_table 
(HB_OT_TAG_cmap));
+    const OT::cmap *cmap = OT::Sanitizer<OT::cmap>::lock_instance (this->blob);
+    const OT::CmapSubtable *subtable = NULL;
+    const OT::CmapSubtable *subtable_uvs = NULL;
+
+    /* 32-bit subtables. */
+    if (!subtable) subtable = cmap->find_subtable (3, 10);
+    if (!subtable) subtable = cmap->find_subtable (0, 6);
+    if (!subtable) subtable = cmap->find_subtable (0, 4);
+    /* 16-bit subtables. */
+    if (!subtable) subtable = cmap->find_subtable (3, 1);
+    if (!subtable) subtable = cmap->find_subtable (0, 3);
+    if (!subtable) subtable = cmap->find_subtable (0, 2);
+    if (!subtable) subtable = cmap->find_subtable (0, 1);
+    if (!subtable) subtable = cmap->find_subtable (0, 0);
+    /* Meh. */
+    if (!subtable) subtable = &OT::Null(OT::CmapSubtable);
+
+    /* UVS subtable. */
+    if (!subtable_uvs) subtable_uvs = cmap->find_subtable (0, 5);
+    /* Meh. */
+    if (!subtable_uvs) subtable_uvs = &OT::Null(OT::CmapSubtable);
+
+    this->table = subtable;
+    this->uvs_table = subtable_uvs;
+  }
+
+  inline void fini (void)
+  {
+    hb_blob_destroy (this->blob);
+  }
+
+  inline bool get_glyph (hb_codepoint_t  unicode,
+                        hb_codepoint_t  variation_selector,
+                        hb_codepoint_t *glyph) const
+  {
+    if (unlikely (variation_selector))
+    {
+      switch (this->uvs_table->get_glyph_variant (unicode,
+                                                 variation_selector,
+                                                 glyph))
+      {
+       case OT::GLYPH_VARIANT_NOT_FOUND:       return false;
+       case OT::GLYPH_VARIANT_FOUND:           return true;
+       case OT::GLYPH_VARIANT_USE_DEFAULT:     break;
+      }
+    }
+
+    return this->table->get_glyph (unicode, glyph);
+  }
+};
+
+
 struct hb_ot_font_t
 {
+  hb_ot_face_cmap_accelerator_t cmap;
   hb_ot_face_metrics_accelerator_t h_metrics;
   hb_ot_face_metrics_accelerator_t v_metrics;
-
-  const OT::CmapSubtable *cmap;
-  const OT::CmapSubtable *cmap_uvs;
-  hb_blob_t *cmap_blob;
 };
 
 
@@ -113,35 +171,9 @@ _hb_ot_font_create (hb_font_t *font)
 
   unsigned int upem = face->get_upem ();
 
+  ot_font->cmap.init (face);
   ot_font->h_metrics.init (face, HB_OT_TAG_hhea, HB_OT_TAG_hmtx, upem>>1);
-  /* TODO Can we do this lazily? */
-  ot_font->v_metrics.init (face, HB_OT_TAG_vhea, HB_OT_TAG_vmtx, upem);
-
-  ot_font->cmap_blob = OT::Sanitizer<OT::cmap>::sanitize 
(face->reference_table (HB_OT_TAG_cmap));
-  const OT::cmap *cmap = OT::Sanitizer<OT::cmap>::lock_instance 
(ot_font->cmap_blob);
-  const OT::CmapSubtable *subtable = NULL;
-  const OT::CmapSubtable *subtable_uvs = NULL;
-
-  /* 32-bit subtables. */
-  if (!subtable) subtable = cmap->find_subtable (3, 10);
-  if (!subtable) subtable = cmap->find_subtable (0, 6);
-  if (!subtable) subtable = cmap->find_subtable (0, 4);
-  /* 16-bit subtables. */
-  if (!subtable) subtable = cmap->find_subtable (3, 1);
-  if (!subtable) subtable = cmap->find_subtable (0, 3);
-  if (!subtable) subtable = cmap->find_subtable (0, 2);
-  if (!subtable) subtable = cmap->find_subtable (0, 1);
-  if (!subtable) subtable = cmap->find_subtable (0, 0);
-  /* Meh. */
-  if (!subtable) subtable = &OT::Null(OT::CmapSubtable);
-
-  /* UVS subtable. */
-  if (!subtable_uvs) subtable_uvs = cmap->find_subtable (0, 5);
-  /* Meh. */
-  if (!subtable_uvs) subtable_uvs = &OT::Null(OT::CmapSubtable);
-
-  ot_font->cmap = subtable;
-  ot_font->cmap_uvs = subtable_uvs;
+  ot_font->v_metrics.init (face, HB_OT_TAG_vhea, HB_OT_TAG_vmtx, upem); /* 
TODO Can we do this lazily? */
 
   return ot_font;
 }
@@ -149,7 +181,7 @@ _hb_ot_font_create (hb_font_t *font)
 static void
 _hb_ot_font_destroy (hb_ot_font_t *ot_font)
 {
-  hb_blob_destroy (ot_font->cmap_blob);
+  ot_font->cmap.fini ();
   ot_font->h_metrics.fini ();
   ot_font->v_metrics.fini ();
 
@@ -167,20 +199,7 @@ hb_ot_get_glyph (hb_font_t *font HB_UNUSED,
 
 {
   const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
-
-  if (unlikely (variation_selector))
-  {
-    switch (ot_font->cmap_uvs->get_glyph_variant (unicode,
-                                                 variation_selector,
-                                                 glyph))
-    {
-      case OT::GLYPH_VARIANT_NOT_FOUND:                return false;
-      case OT::GLYPH_VARIANT_FOUND:            return true;
-      case OT::GLYPH_VARIANT_USE_DEFAULT:      break;
-    }
-  }
-
-  return ot_font->cmap->get_glyph (unicode, glyph);
+  return ot_font->cmap.get_glyph (unicode, variation_selector, glyph);
 }
 
 static hb_position_t
commit d088ccaf11d9475fe0d269ce130b1793b8a1ffbf
Author: Behdad Esfahbod <beh...@behdad.org>
Date:   Thu Sep 25 17:26:56 2014 +0300

    [ot-font] Minor

diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc
index 24de830..91df5ca 100644
--- a/src/hb-ot-font.cc
+++ b/src/hb-ot-font.cc
@@ -35,7 +35,7 @@
 #include "hb-ot-hmtx-table.hh"
 
 
-struct metrics_accel_t
+struct hb_ot_face_metrics_accelerator_t
 {
   unsigned int num_metrics;
   unsigned int num_advances;
@@ -43,19 +43,19 @@ struct metrics_accel_t
   const OT::_mtx *table;
   hb_blob_t *blob;
 
-  inline void init (hb_font_t *font,
+  inline void init (hb_face_t *face,
                    hb_tag_t _hea_tag, hb_tag_t _mtx_tag,
                    unsigned int default_advance)
   {
     this->default_advance = default_advance;
-    this->num_metrics = font->face->get_num_glyphs ();
+    this->num_metrics = face->get_num_glyphs ();
 
-    hb_blob_t *_hea_blob = OT::Sanitizer<OT::_hea>::sanitize 
(font->face->reference_table (_hea_tag));
+    hb_blob_t *_hea_blob = OT::Sanitizer<OT::_hea>::sanitize 
(face->reference_table (_hea_tag));
     const OT::_hea *_hea = OT::Sanitizer<OT::_hea>::lock_instance (_hea_blob);
     this->num_advances = _hea->numberOfLongMetrics;
     hb_blob_destroy (_hea_blob);
 
-    this->blob = OT::Sanitizer<OT::_mtx>::sanitize 
(font->face->reference_table (_mtx_tag));
+    this->blob = OT::Sanitizer<OT::_mtx>::sanitize (face->reference_table 
(_mtx_tag));
     if (unlikely (!this->num_advances ||
                  2 * (this->num_advances + this->num_metrics) < 
hb_blob_get_length (this->blob)))
     {
@@ -93,8 +93,8 @@ struct metrics_accel_t
 
 struct hb_ot_font_t
 {
-  metrics_accel_t h_metrics;
-  metrics_accel_t v_metrics;
+  hb_ot_face_metrics_accelerator_t h_metrics;
+  hb_ot_face_metrics_accelerator_t v_metrics;
 
   const OT::CmapSubtable *cmap;
   const OT::CmapSubtable *cmap_uvs;
@@ -106,17 +106,18 @@ static hb_ot_font_t *
 _hb_ot_font_create (hb_font_t *font)
 {
   hb_ot_font_t *ot_font = (hb_ot_font_t *) calloc (1, sizeof (hb_ot_font_t));
+  hb_face_t *face = font->face;
 
   if (unlikely (!ot_font))
     return NULL;
 
-  unsigned int upem = font->face->get_upem ();
+  unsigned int upem = face->get_upem ();
 
-  ot_font->h_metrics.init (font, HB_OT_TAG_hhea, HB_OT_TAG_hmtx, upem>>1);
+  ot_font->h_metrics.init (face, HB_OT_TAG_hhea, HB_OT_TAG_hmtx, upem>>1);
   /* TODO Can we do this lazily? */
-  ot_font->v_metrics.init (font, HB_OT_TAG_vhea, HB_OT_TAG_vmtx, upem);
+  ot_font->v_metrics.init (face, HB_OT_TAG_vhea, HB_OT_TAG_vmtx, upem);
 
-  ot_font->cmap_blob = OT::Sanitizer<OT::cmap>::sanitize 
(font->face->reference_table (HB_OT_TAG_cmap));
+  ot_font->cmap_blob = OT::Sanitizer<OT::cmap>::sanitize 
(face->reference_table (HB_OT_TAG_cmap));
   const OT::cmap *cmap = OT::Sanitizer<OT::cmap>::lock_instance 
(ot_font->cmap_blob);
   const OT::CmapSubtable *subtable = NULL;
   const OT::CmapSubtable *subtable_uvs = NULL;
commit d7c160a1530adabbcf33725b105072293115a34c
Author: Behdad Esfahbod <beh...@behdad.org>
Date:   Thu Sep 25 17:15:35 2014 +0300

    [ot-font] Handle missing vertical metrics tables

diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc
index d629c41..24de830 100644
--- a/src/hb-ot-font.cc
+++ b/src/hb-ot-font.cc
@@ -39,11 +39,15 @@ struct metrics_accel_t
 {
   unsigned int num_metrics;
   unsigned int num_advances;
+  unsigned int default_advance;
   const OT::_mtx *table;
   hb_blob_t *blob;
 
-  inline void init (hb_font_t *font, hb_tag_t _hea_tag, hb_tag_t _mtx_tag)
+  inline void init (hb_font_t *font,
+                   hb_tag_t _hea_tag, hb_tag_t _mtx_tag,
+                   unsigned int default_advance)
   {
+    this->default_advance = default_advance;
     this->num_metrics = font->face->get_num_glyphs ();
 
     hb_blob_t *_hea_blob = OT::Sanitizer<OT::_hea>::sanitize 
(font->face->reference_table (_hea_tag));
@@ -55,6 +59,7 @@ struct metrics_accel_t
     if (unlikely (!this->num_advances ||
                  2 * (this->num_advances + this->num_metrics) < 
hb_blob_get_length (this->blob)))
     {
+      this->num_metrics = this->num_advances = 0;
       hb_blob_destroy (this->blob);
       this->blob = hb_blob_get_empty ();
     }
@@ -69,7 +74,15 @@ struct metrics_accel_t
   inline unsigned int get_advance (hb_codepoint_t glyph) const
   {
     if (unlikely (glyph >= this->num_metrics))
-      return 0;
+    {
+      /* If this->num_metrics is zero, it means we don't have the metrics table
+       * for this direction: return one EM.  Otherwise, it means that the glyph
+       * index is out of bound: return zero. */
+      if (this->num_metrics)
+       return 0;
+      else
+       return this->default_advance;
+    }
 
     if (glyph >= this->num_advances)
       glyph = this->num_advances - 1;
@@ -80,8 +93,6 @@ struct metrics_accel_t
 
 struct hb_ot_font_t
 {
-  unsigned int num_glyphs;
-
   metrics_accel_t h_metrics;
   metrics_accel_t v_metrics;
 
@@ -99,11 +110,11 @@ _hb_ot_font_create (hb_font_t *font)
   if (unlikely (!ot_font))
     return NULL;
 
-  ot_font->num_glyphs = font->face->get_num_glyphs ();
+  unsigned int upem = font->face->get_upem ();
 
-  ot_font->h_metrics.init (font, HB_OT_TAG_hhea, HB_OT_TAG_hmtx);
+  ot_font->h_metrics.init (font, HB_OT_TAG_hhea, HB_OT_TAG_hmtx, upem>>1);
   /* TODO Can we do this lazily? */
-  ot_font->v_metrics.init (font, HB_OT_TAG_vhea, HB_OT_TAG_vmtx);
+  ot_font->v_metrics.init (font, HB_OT_TAG_vhea, HB_OT_TAG_vmtx, upem);
 
   ot_font->cmap_blob = OT::Sanitizer<OT::cmap>::sanitize 
(font->face->reference_table (HB_OT_TAG_cmap));
   const OT::cmap *cmap = OT::Sanitizer<OT::cmap>::lock_instance 
(ot_font->cmap_blob);
@@ -233,6 +244,7 @@ hb_ot_get_glyph_v_kerning (hb_font_t *font HB_UNUSED,
                           hb_codepoint_t bottom_glyph HB_UNUSED,
                           void *user_data HB_UNUSED)
 {
+  /* OpenType doesn't have vertical-kerning other than GPOS. */
   return 0;
 }
 
commit be1cca270257bfdfee3fbe821175269713acf408
Author: Behdad Esfahbod <beh...@behdad.org>
Date:   Thu Sep 25 16:53:24 2014 +0300

    [ot-font] Add metrics_accel_t

diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc
index 25fe511..d629c41 100644
--- a/src/hb-ot-font.cc
+++ b/src/hb-ot-font.cc
@@ -35,18 +35,55 @@
 #include "hb-ot-hmtx-table.hh"
 
 
+struct metrics_accel_t
+{
+  unsigned int num_metrics;
+  unsigned int num_advances;
+  const OT::_mtx *table;
+  hb_blob_t *blob;
+
+  inline void init (hb_font_t *font, hb_tag_t _hea_tag, hb_tag_t _mtx_tag)
+  {
+    this->num_metrics = font->face->get_num_glyphs ();
+
+    hb_blob_t *_hea_blob = OT::Sanitizer<OT::_hea>::sanitize 
(font->face->reference_table (_hea_tag));
+    const OT::_hea *_hea = OT::Sanitizer<OT::_hea>::lock_instance (_hea_blob);
+    this->num_advances = _hea->numberOfLongMetrics;
+    hb_blob_destroy (_hea_blob);
+
+    this->blob = OT::Sanitizer<OT::_mtx>::sanitize 
(font->face->reference_table (_mtx_tag));
+    if (unlikely (!this->num_advances ||
+                 2 * (this->num_advances + this->num_metrics) < 
hb_blob_get_length (this->blob)))
+    {
+      hb_blob_destroy (this->blob);
+      this->blob = hb_blob_get_empty ();
+    }
+    this->table = OT::Sanitizer<OT::_mtx>::lock_instance (this->blob);
+  }
+
+  inline void fini (void)
+  {
+    hb_blob_destroy (this->blob);
+  }
+
+  inline unsigned int get_advance (hb_codepoint_t glyph) const
+  {
+    if (unlikely (glyph >= this->num_metrics))
+      return 0;
+
+    if (glyph >= this->num_advances)
+      glyph = this->num_advances - 1;
+
+    return this->table->longMetric[glyph].advance;
+  }
+};
 
 struct hb_ot_font_t
 {
   unsigned int num_glyphs;
 
-  unsigned int num_hmetrics;
-  const OT::hmtx *hmtx;
-  hb_blob_t *hmtx_blob;
-
-  unsigned int num_vmetrics;
-  const OT::vmtx *vmtx;
-  hb_blob_t *vmtx_blob;
+  metrics_accel_t h_metrics;
+  metrics_accel_t v_metrics;
 
   const OT::CmapSubtable *cmap;
   const OT::CmapSubtable *cmap_uvs;
@@ -64,41 +101,9 @@ _hb_ot_font_create (hb_font_t *font)
 
   ot_font->num_glyphs = font->face->get_num_glyphs ();
 
-  /* Setup horizontal metrics. */
-  {
-    hb_blob_t *hhea_blob = OT::Sanitizer<OT::hhea>::sanitize 
(font->face->reference_table (HB_OT_TAG_hhea));
-    const OT::hhea *hhea = OT::Sanitizer<OT::hhea>::lock_instance (hhea_blob);
-    ot_font->num_hmetrics = hhea->numberOfMetrics;
-    hb_blob_destroy (hhea_blob);
-
-    ot_font->hmtx_blob = OT::Sanitizer<OT::hmtx>::sanitize 
(font->face->reference_table (HB_OT_TAG_hmtx));
-    if (unlikely (!ot_font->num_hmetrics ||
-                 2 * (ot_font->num_hmetrics + ot_font->num_glyphs) < 
hb_blob_get_length (ot_font->hmtx_blob)))
-    {
-      hb_blob_destroy (ot_font->hmtx_blob);
-      free (ot_font);
-      return NULL;
-    }
-    ot_font->hmtx = OT::Sanitizer<OT::hmtx>::lock_instance 
(ot_font->hmtx_blob);
-  }
-
-  /* Setup vertical metrics. */
-  {
-    hb_blob_t *vhea_blob = OT::Sanitizer<OT::vhea>::sanitize 
(font->face->reference_table (HB_OT_TAG_vhea));
-    const OT::vhea *vhea = OT::Sanitizer<OT::vhea>::lock_instance (vhea_blob);
-    ot_font->num_vmetrics = vhea->numberOfMetrics;
-    hb_blob_destroy (vhea_blob);
-
-    ot_font->vmtx_blob = OT::Sanitizer<OT::vmtx>::sanitize 
(font->face->reference_table (HB_TAG('v','m','t','x')));
-    if (unlikely (!ot_font->num_vmetrics ||
-                 2 * (ot_font->num_vmetrics + ot_font->num_glyphs) < 
hb_blob_get_length (ot_font->vmtx_blob)))
-    {
-      hb_blob_destroy (ot_font->vmtx_blob);
-      free (ot_font);
-      return NULL;
-    }
-    ot_font->vmtx = OT::Sanitizer<OT::vmtx>::lock_instance 
(ot_font->vmtx_blob);
-  }
+  ot_font->h_metrics.init (font, HB_OT_TAG_hhea, HB_OT_TAG_hmtx);
+  /* TODO Can we do this lazily? */
+  ot_font->v_metrics.init (font, HB_OT_TAG_vhea, HB_OT_TAG_vmtx);
 
   ot_font->cmap_blob = OT::Sanitizer<OT::cmap>::sanitize 
(font->face->reference_table (HB_OT_TAG_cmap));
   const OT::cmap *cmap = OT::Sanitizer<OT::cmap>::lock_instance 
(ot_font->cmap_blob);
@@ -133,8 +138,8 @@ static void
 _hb_ot_font_destroy (hb_ot_font_t *ot_font)
 {
   hb_blob_destroy (ot_font->cmap_blob);
-  hb_blob_destroy (ot_font->hmtx_blob);
-  hb_blob_destroy (ot_font->vmtx_blob);
+  ot_font->h_metrics.fini ();
+  ot_font->v_metrics.fini ();
 
   free (ot_font);
 }
@@ -173,14 +178,7 @@ hb_ot_get_glyph_h_advance (hb_font_t *font HB_UNUSED,
                           void *user_data HB_UNUSED)
 {
   const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
-
-  if (unlikely (glyph >= ot_font->num_glyphs))
-    return 0;
-
-  if (glyph >= ot_font->num_hmetrics)
-    glyph = ot_font->num_hmetrics - 1;
-
-  return font->em_scale_x (ot_font->hmtx->longHorMetric[glyph].advance);
+  return font->em_scale_x (ot_font->h_metrics.get_advance (glyph));
 }
 
 static hb_position_t
@@ -190,14 +188,7 @@ hb_ot_get_glyph_v_advance (hb_font_t *font HB_UNUSED,
                           void *user_data HB_UNUSED)
 {
   const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
-
-  if (unlikely (glyph >= ot_font->num_glyphs))
-    return 0;
-
-  if (glyph >= ot_font->num_vmetrics)
-    glyph = ot_font->num_vmetrics - 1;
-
-  return font->em_scale_y (-ot_font->vmtx->longHorMetric[glyph].advance);
+  return font->em_scale_y (-ot_font->v_metrics.get_advance (glyph));
 }
 
 static hb_bool_t
diff --git a/src/hb-ot-hhea-table.hh b/src/hb-ot-hhea-table.hh
index 9999bca..6bf6d5f 100644
--- a/src/hb-ot-hhea-table.hh
+++ b/src/hb-ot-hhea-table.hh
@@ -80,7 +80,7 @@ struct _hea
   SHORT                reserved3;              /* Set to 0. */
   SHORT                reserved4;              /* Set to 0. */
   SHORT                metricDataFormat;       /* 0 for current format. */
-  USHORT       numberOfMetrics;        /* Number of LongMetric entries in 
metric
+  USHORT       numberOfLongMetrics;    /* Number of LongMetric entries in 
metric
                                         * table. */
   public:
   DEFINE_SIZE_STATIC (36);
diff --git a/src/hb-ot-hmtx-table.hh b/src/hb-ot-hmtx-table.hh
index 642c636..932f973 100644
--- a/src/hb-ot-hmtx-table.hh
+++ b/src/hb-ot-hmtx-table.hh
@@ -63,7 +63,7 @@ struct _mtx
   }
 
   public:
-  LongMetric   longHorMetric[VAR];     /* Paired advance width and leading
+  LongMetric   longMetric[VAR];        /* Paired advance width and leading
                                         * bearing values for each glyph. The
                                         * value numOfHMetrics comes from
                                         * the 'hhea' table. If the font is
@@ -85,7 +85,7 @@ struct _mtx
                                         * font to vary the side bearing
                                         * values for each glyph. */
   public:
-  DEFINE_SIZE_ARRAY2 (0, longHorMetric, leadingBearingX);
+  DEFINE_SIZE_ARRAY2 (0, longMetric, leadingBearingX);
 };
 
 struct hmtx : _mtx {
commit d41b809e9d21e655129a97c600d28f278fd7e62c
Author: Behdad Esfahbod <beh...@behdad.org>
Date:   Thu Sep 25 13:04:08 2014 +0300

    [ot-font] Start adding vertical support

diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc
index 3514fcc..25fe511 100644
--- a/src/hb-ot-font.cc
+++ b/src/hb-ot-font.cc
@@ -39,10 +39,15 @@
 struct hb_ot_font_t
 {
   unsigned int num_glyphs;
+
   unsigned int num_hmetrics;
   const OT::hmtx *hmtx;
   hb_blob_t *hmtx_blob;
 
+  unsigned int num_vmetrics;
+  const OT::vmtx *vmtx;
+  hb_blob_t *vmtx_blob;
+
   const OT::CmapSubtable *cmap;
   const OT::CmapSubtable *cmap_uvs;
   hb_blob_t *cmap_blob;
@@ -59,21 +64,41 @@ _hb_ot_font_create (hb_font_t *font)
 
   ot_font->num_glyphs = font->face->get_num_glyphs ();
 
+  /* Setup horizontal metrics. */
   {
     hb_blob_t *hhea_blob = OT::Sanitizer<OT::hhea>::sanitize 
(font->face->reference_table (HB_OT_TAG_hhea));
     const OT::hhea *hhea = OT::Sanitizer<OT::hhea>::lock_instance (hhea_blob);
-    ot_font->num_hmetrics = hhea->numberOfHMetrics;
+    ot_font->num_hmetrics = hhea->numberOfMetrics;
     hb_blob_destroy (hhea_blob);
+
+    ot_font->hmtx_blob = OT::Sanitizer<OT::hmtx>::sanitize 
(font->face->reference_table (HB_OT_TAG_hmtx));
+    if (unlikely (!ot_font->num_hmetrics ||
+                 2 * (ot_font->num_hmetrics + ot_font->num_glyphs) < 
hb_blob_get_length (ot_font->hmtx_blob)))
+    {
+      hb_blob_destroy (ot_font->hmtx_blob);
+      free (ot_font);
+      return NULL;
+    }
+    ot_font->hmtx = OT::Sanitizer<OT::hmtx>::lock_instance 
(ot_font->hmtx_blob);
   }
-  ot_font->hmtx_blob = OT::Sanitizer<OT::hmtx>::sanitize 
(font->face->reference_table (HB_OT_TAG_hmtx));
-  if (unlikely (!ot_font->num_hmetrics ||
-               2 * (ot_font->num_hmetrics + ot_font->num_glyphs) < 
hb_blob_get_length (ot_font->hmtx_blob)))
+
+  /* Setup vertical metrics. */
   {
-    hb_blob_destroy (ot_font->hmtx_blob);
-    free (ot_font);
-    return NULL;
+    hb_blob_t *vhea_blob = OT::Sanitizer<OT::vhea>::sanitize 
(font->face->reference_table (HB_OT_TAG_vhea));
+    const OT::vhea *vhea = OT::Sanitizer<OT::vhea>::lock_instance (vhea_blob);
+    ot_font->num_vmetrics = vhea->numberOfMetrics;
+    hb_blob_destroy (vhea_blob);
+
+    ot_font->vmtx_blob = OT::Sanitizer<OT::vmtx>::sanitize 
(font->face->reference_table (HB_TAG('v','m','t','x')));
+    if (unlikely (!ot_font->num_vmetrics ||
+                 2 * (ot_font->num_vmetrics + ot_font->num_glyphs) < 
hb_blob_get_length (ot_font->vmtx_blob)))
+    {
+      hb_blob_destroy (ot_font->vmtx_blob);
+      free (ot_font);
+      return NULL;
+    }
+    ot_font->vmtx = OT::Sanitizer<OT::vmtx>::lock_instance 
(ot_font->vmtx_blob);
   }
-  ot_font->hmtx = OT::Sanitizer<OT::hmtx>::lock_instance (ot_font->hmtx_blob);
 
   ot_font->cmap_blob = OT::Sanitizer<OT::cmap>::sanitize 
(font->face->reference_table (HB_OT_TAG_cmap));
   const OT::cmap *cmap = OT::Sanitizer<OT::cmap>::lock_instance 
(ot_font->cmap_blob);
@@ -109,6 +134,7 @@ _hb_ot_font_destroy (hb_ot_font_t *ot_font)
 {
   hb_blob_destroy (ot_font->cmap_blob);
   hb_blob_destroy (ot_font->hmtx_blob);
+  hb_blob_destroy (ot_font->vmtx_blob);
 
   free (ot_font);
 }
@@ -149,12 +175,12 @@ hb_ot_get_glyph_h_advance (hb_font_t *font HB_UNUSED,
   const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
 
   if (unlikely (glyph >= ot_font->num_glyphs))
-    return 0; /* Maybe better to return notdef's advance instead? */
+    return 0;
 
   if (glyph >= ot_font->num_hmetrics)
     glyph = ot_font->num_hmetrics - 1;
 
-  return font->em_scale_x (ot_font->hmtx->longHorMetric[glyph].advanceWidth);
+  return font->em_scale_x (ot_font->hmtx->longHorMetric[glyph].advance);
 }
 
 static hb_position_t
@@ -163,8 +189,15 @@ hb_ot_get_glyph_v_advance (hb_font_t *font HB_UNUSED,
                           hb_codepoint_t glyph,
                           void *user_data HB_UNUSED)
 {
-  /* TODO */
-  return 0;
+  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
+
+  if (unlikely (glyph >= ot_font->num_glyphs))
+    return 0;
+
+  if (glyph >= ot_font->num_vmetrics)
+    glyph = ot_font->num_vmetrics - 1;
+
+  return font->em_scale_y (-ot_font->vmtx->longHorMetric[glyph].advance);
 }
 
 static hb_bool_t
diff --git a/src/hb-ot-hhea-table.hh b/src/hb-ot-hhea-table.hh
index d433200..9999bca 100644
--- a/src/hb-ot-hhea-table.hh
+++ b/src/hb-ot-hhea-table.hh
@@ -35,14 +35,17 @@ namespace OT {
 
 /*
  * hhea -- The Horizontal Header Table
+ * vhea -- The Vertical Header Table
  */
 
 #define HB_OT_TAG_hhea HB_TAG('h','h','e','a')
+#define HB_OT_TAG_vhea HB_TAG('v','h','e','a')
 
 
-struct hhea
+struct _hea
 {
-  static const hb_tag_t tableTag       = HB_OT_TAG_hhea;
+  static const hb_tag_t hheaTag        = HB_OT_TAG_hhea;
+  static const hb_tag_t vheaTag        = HB_OT_TAG_vhea;
 
   inline bool sanitize (hb_sanitize_context_t *c) {
     TRACE_SANITIZE (this);
@@ -51,45 +54,45 @@ struct hhea
 
   public:
   FixedVersion version;                /* 0x00010000u for version 1.0. */
-  FWORD                ascender;               /* Typographic ascent. <a
-                                        * 
href="http://developer.apple.com/fonts/TTRefMan/RM06/Chap6hhea.html";>
-                                        * (Distance from baseline of highest
-                                        * ascender)</a> */
-  FWORD                descender;              /* Typographic descent. <a
-                                        * 
href="http://developer.apple.com/fonts/TTRefMan/RM06/Chap6hhea.html";>
-                                        * (Distance from baseline of lowest
-                                        * descender)</a> */
-  FWORD                lineGap;                /* Typographic line gap. 
Negative
-                                        * LineGap values are treated as zero
-                                        * in Windows 3.1, System 6, and
-                                        * System 7. */
-  UFWORD       advanceWidthMax;        /* Maximum advance width value in
-                                        * 'hmtx' table. */
-  FWORD                minLeftSideBearing;     /* Minimum left sidebearing 
value in
-                                        * 'hmtx' table. */
-  FWORD                minRightSideBearing;    /* Minimum right sidebearing 
value;
+  FWORD                ascender;               /* Typographic ascent. */
+  FWORD                descender;              /* Typographic descent. */
+  FWORD                lineGap;                /* Typographic line gap. */
+  UFWORD       advanceMax;             /* Maximum advance width/height value in
+                                        * metrics table. */
+  FWORD                minLeadingBearing;      /* Minimum left/top sidebearing 
value in
+                                        * metrics table. */
+  FWORD                minTrailingBearing;     /* Minimum right/bottom 
sidebearing value;
                                         * calculated as Min(aw - lsb -
-                                        * (xMax - xMin)). */
-  FWORD                xMaxExtent;             /* Max(lsb + (xMax - xMin)). */
+                                        * (xMax - xMin)) for horizontal. */
+  FWORD                maxExtent;              /* horizontal: Max(lsb + (xMax 
- xMin)),
+                                        * vertical: 
minLeadingBearing+(yMax-yMin). */
   SHORT                caretSlopeRise;         /* Used to calculate the slope 
of the
-                                        * cursor (rise/run); 1 for vertical. */
-  SHORT                caretSlopeRun;          /* 0 for vertical. */
+                                        * cursor (rise/run); 1 for vertical 
caret,
+                                        * 0 for horizontal.*/
+  SHORT                caretSlopeRun;          /* 0 for vertical caret, 1 for 
horizontal. */
   SHORT                caretOffset;            /* The amount by which a slanted
                                         * highlight on a glyph needs
                                         * to be shifted to produce the
                                         * best appearance. Set to 0 for
-                                        * non--slanted fonts */
-  SHORT                reserved1;              /* set to 0 */
-  SHORT                reserved2;              /* set to 0 */
-  SHORT                reserved3;              /* set to 0 */
-  SHORT                reserved4;              /* set to 0 */
+                                        * non-slanted fonts. */
+  SHORT                reserved1;              /* Set to 0. */
+  SHORT                reserved2;              /* Set to 0. */
+  SHORT                reserved3;              /* Set to 0. */
+  SHORT                reserved4;              /* Set to 0. */
   SHORT                metricDataFormat;       /* 0 for current format. */
-  USHORT       numberOfHMetrics;       /* Number of hMetric entries in 'hmtx'
-                                        * table */
+  USHORT       numberOfMetrics;        /* Number of LongMetric entries in 
metric
+                                        * table. */
   public:
   DEFINE_SIZE_STATIC (36);
 };
 
+struct hhea : _hea {
+  static const hb_tag_t tableTag       = HB_OT_TAG_hhea;
+};
+struct vhea : _hea {
+  static const hb_tag_t tableTag       = HB_OT_TAG_vhea;
+};
+
 
 } /* namespace OT */
 
diff --git a/src/hb-ot-hmtx-table.hh b/src/hb-ot-hmtx-table.hh
index e918e3b..642c636 100644
--- a/src/hb-ot-hmtx-table.hh
+++ b/src/hb-ot-hmtx-table.hh
@@ -35,22 +35,25 @@ namespace OT {
 
 /*
  * hmtx -- The Horizontal Metrics Table
+ * vmtx -- The Vertical Metrics Table
  */
 
 #define HB_OT_TAG_hmtx HB_TAG('h','m','t','x')
+#define HB_OT_TAG_vmtx HB_TAG('v','m','t','x')
 
 
-struct LongHorMetric
+struct LongMetric
 {
-  USHORT       advanceWidth;
-  SHORT                lsb;
+  USHORT       advance; /* Advance width/height. */
+  SHORT                lsb; /* Leading (left/top) side bearing. */
   public:
   DEFINE_SIZE_STATIC (4);
 };
 
-struct hmtx
+struct _mtx
 {
-  static const hb_tag_t tableTag       = HB_OT_TAG_hmtx;
+  static const hb_tag_t hmtxTag        = HB_OT_TAG_hmtx;
+  static const hb_tag_t vmtxTag        = HB_OT_TAG_vmtx;
 
   inline bool sanitize (hb_sanitize_context_t *c) {
     TRACE_SANITIZE (this);
@@ -60,7 +63,7 @@ struct hmtx
   }
 
   public:
-  LongHorMetric        longHorMetric[VAR];     /* Paired advance width and 
left side
+  LongMetric   longHorMetric[VAR];     /* Paired advance width and leading
                                         * bearing values for each glyph. The
                                         * value numOfHMetrics comes from
                                         * the 'hhea' table. If the font is
@@ -68,23 +71,29 @@ struct hmtx
                                         * be in the array, but that entry is
                                         * required. The last entry applies to
                                         * all subsequent glyphs. */
-  SHORT                leftSideBearingX[VAR];  /* Here the advanceWidth is 
assumed
-                                        * to be the same as the advanceWidth
+  SHORT                leadingBearingX[VAR];   /* Here the advance is assumed
+                                        * to be the same as the advance
                                         * for the last entry above. The
                                         * number of entries in this array is
                                         * derived from numGlyphs (from 'maxp'
-                                        * table) minus numberOfHMetrics. This
-                                        * generally is used with a run of
-                                        * monospaced glyphs (e.g., Kanji
+                                        * table) minus numberOfLongMetrics.
+                                        * This generally is used with a run
+                                        * of monospaced glyphs (e.g., Kanji
                                         * fonts or Courier fonts). Only one
                                         * run is allowed and it must be at
                                         * the end. This allows a monospaced
-                                        * font to vary the left side bearing
+                                        * font to vary the side bearing
                                         * values for each glyph. */
   public:
-  DEFINE_SIZE_ARRAY2 (0, longHorMetric, leftSideBearingX);
+  DEFINE_SIZE_ARRAY2 (0, longHorMetric, leadingBearingX);
 };
 
+struct hmtx : _mtx {
+  static const hb_tag_t tableTag       = HB_OT_TAG_hmtx;
+};
+struct vmtx : _mtx {
+  static const hb_tag_t tableTag       = HB_OT_TAG_vmtx;
+};
 
 } /* namespace OT */
 
_______________________________________________
HarfBuzz mailing list
HarfBuzz@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/harfbuzz

Reply via email to