[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 @@
 
   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_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 @@
   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_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 @@
 
 /*
  * 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 @@
 
   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 @@
 
 /*
  * 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 @@
   }
 
   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 @@
 					 * 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 */