[HarfBuzz] harfbuzz: Branch 'master' - 35 commits

Behdad Esfahbod behdad at kemper.freedesktop.org
Tue Sep 27 15:07:48 UTC 2016


 NEWS                                    |    7 
 configure.ac                            |    2 
 docs/harfbuzz-docs.xml                  |    9 
 docs/harfbuzz-sections.txt              |   30 +
 src/Makefile.sources                    |    2 
 src/hb-font-private.hh                  |    9 
 src/hb-ot-layout-math-table.hh          |  722 ++++++++++++++++++++++++++++++++
 src/hb-ot-layout-private.hh             |    3 
 src/hb-ot-layout.cc                     |  257 +++++++++++
 src/hb-ot-math.h                        |  209 +++++++++
 src/hb-ot.h                             |    1 
 test/api/Makefile.am                    |   14 
 test/api/fonts/MathTestFontEmpty.otf    |binary
 test/api/fonts/MathTestFontFull.otf     |binary
 test/api/fonts/MathTestFontNone.otf     |binary
 test/api/fonts/MathTestFontPartial1.otf |binary
 test/api/fonts/MathTestFontPartial2.otf |binary
 test/api/fonts/MathTestFontPartial3.otf |binary
 test/api/fonts/MathTestFontPartial4.otf |binary
 test/api/test-ot-math.c                 |  694 ++++++++++++++++++++++++++++++
 20 files changed, 1952 insertions(+), 7 deletions(-)

New commits:
commit 05eaf951240608354c9482c7f4aa110dbdf0118e
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Tue Sep 27 13:50:54 2016 +0200

    1.3.2

diff --git a/NEWS b/NEWS
index 5268687..ae0926e 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,10 @@
+Overview of changes leading to 1.3.2
+Wednesday, September 27, 2016
+====================================
+
+- Fix build of hb-coretext on older OS X versions.
+
+
 Overview of changes leading to 1.3.1
 Wednesday, September 7, 2016
 ====================================
diff --git a/configure.ac b/configure.ac
index 318c1ef..57e9e6d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,6 +1,6 @@
 AC_PREREQ([2.64])
 AC_INIT([HarfBuzz],
-        [1.3.1],
+        [1.3.2],
         [https://github.com/behdad/harfbuzz/issues/new],
         [harfbuzz],
         [http://harfbuzz.org/])
commit f3f3205ac169c1e4038df65716921ed44fc48b96
Merge: f16bf6c 73e4884
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Tue Sep 27 17:06:51 2016 +0200

    Merge pull request #331 from behdad/math
    
    Merge MATH table branch

commit 73e48843e1ceaecb26b1ef9f5fb8d0f7425aa44d
Merge: c3e21a6 f16bf6c
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Tue Sep 27 17:06:14 2016 +0200

    Merge branch 'master' into math

commit c3e21a6620c35500afa350d11620f69802920df3
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Tue Sep 27 16:51:38 2016 +0200

    [MATH] Fix more docs

diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc
index 49c75b0..6c8a9c4 100644
--- a/src/hb-ot-layout.cc
+++ b/src/hb-ot-layout.cc
@@ -1238,7 +1238,7 @@ hb_ot_layout_substitute_lookup (OT::hb_apply_context_t *c,
  *
  * Return value: #TRUE if face has a MATH table and #FALSE otherwise
  *
- * Since: 1.4
+ * Since: 1.4.0
  **/
 hb_bool_t
 hb_ot_math_has_data (hb_face_t *face)
@@ -1260,7 +1260,7 @@ hb_ot_math_has_data (hb_face_t *face)
  *
  * Return value: the requested constant or 0
  *
- * Since: 1.4
+ * Since: 1.4.0
  **/
 hb_position_t
 hb_ot_math_get_constant (hb_font_t *font,
@@ -1278,7 +1278,7 @@ hb_ot_math_get_constant (hb_font_t *font,
  *
  * Return value: the italics correction of the glyph or 0
  *
- * Since: 1.4
+ * Since: 1.4.0
  **/
 hb_position_t
 hb_ot_math_get_glyph_italics_correction (hb_font_t *font,
@@ -1296,7 +1296,7 @@ hb_ot_math_get_glyph_italics_correction (hb_font_t *font,
  *
  * Return value: the top accent attachment of the glyph or 0
  *
- * Since: 1.4
+ * Since: 1.4.0
  **/
 hb_position_t
 hb_ot_math_get_glyph_top_accent_attachment (hb_font_t *font,
@@ -1314,7 +1314,7 @@ hb_ot_math_get_glyph_top_accent_attachment (hb_font_t *font,
  *
  * Return value: #TRUE if the glyph is an extended shape and #FALSE otherwise
  *
- * Since: 1.4
+ * Since: 1.4.0
  **/
 hb_bool_t
 hb_ot_math_is_glyph_extended_shape (hb_face_t *face,
@@ -1340,7 +1340,7 @@ hb_ot_math_is_glyph_extended_shape (hb_face_t *face,
  *
  * Return value: requested kerning or 0
  *
- * Since: 1.4
+ * Since: 1.4.0
  **/
 hb_position_t
 hb_ot_math_get_glyph_kerning (hb_font_t *font,
@@ -1370,7 +1370,7 @@ hb_ot_math_get_glyph_kerning (hb_font_t *font,
  *
  * Return value: the total number of size variants available or 0
  *
- * Since: 1.4
+ * Since: 1.4.0
  **/
 unsigned int
 hb_ot_math_get_glyph_variants (hb_font_t *font,
@@ -1400,7 +1400,7 @@ hb_ot_math_get_glyph_variants (hb_font_t *font,
  *
  * Return value: requested min connector overlap or 0
  *
- * Since: 1.4
+ * Since: 1.4.0
  **/
 hb_position_t
 hb_ot_math_get_min_connector_overlap (hb_font_t *font,
@@ -1429,7 +1429,7 @@ hb_ot_math_get_min_connector_overlap (hb_font_t *font,
  *
  * Return value: the total number of parts in the glyph assembly
  *
- * Since: 1.4
+ * Since: 1.4.0
  **/
 unsigned int
 hb_ot_math_get_glyph_assembly (hb_font_t *font,
diff --git a/src/hb-ot-math.h b/src/hb-ot-math.h
index e186fa9..0fc251b 100644
--- a/src/hb-ot-math.h
+++ b/src/hb-ot-math.h
@@ -47,6 +47,11 @@ HB_BEGIN_DECLS
 
 /* Types */
 
+/**
+ * hb_ot_math_constant_t:
+ *
+ * Since: 1.4.0
+ */
 typedef enum {
   HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN = 0,
   HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN = 1,
@@ -106,6 +111,11 @@ typedef enum {
   HB_OT_MATH_CONSTANT_RADICAL_DEGREE_BOTTOM_RAISE_PERCENT = 55
 } hb_ot_math_constant_t;
 
+/**
+ * hb_ot_math_kern_t:
+ *
+ * Since: 1.4.0
+ */
 typedef enum {
   HB_OT_MATH_KERN_TOP_RIGHT = 0,
   HB_OT_MATH_KERN_TOP_LEFT = 1,
@@ -113,15 +123,30 @@ typedef enum {
   HB_OT_MATH_KERN_BOTTOM_LEFT = 3
 } hb_ot_math_kern_t;
 
+/**
+ * hb_ot_math_glyph_variant_t:
+ *
+ * Since: 1.4.0
+ */
 typedef struct hb_ot_math_glyph_variant_t {
   hb_codepoint_t glyph;
   hb_position_t advance;
 } hb_ot_math_glyph_variant_t;
 
+/**
+ * hb_ot_math_glyph_part_flags_t:
+ *
+ * Since: 1.4.0
+ */
 typedef enum { /*< flags >*/
   HB_MATH_GLYPH_PART_FLAG_EXTENDER	= 0x00000001u  /* Extender glyph */
 } hb_ot_math_glyph_part_flags_t;
 
+/**
+ * hb_ot_math_glyph_part_t:
+ *
+ * Since: 1.4.0
+ */
 typedef struct hb_ot_math_glyph_part_t {
   hb_codepoint_t glyph;
   hb_position_t start_connector_length;
commit 46cc4a3a2a529c80677babe38ca1542f9c773ac0
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Tue Sep 27 16:44:22 2016 +0200

    [MATH] Rename hb_math_*_t types to hb_ot_math_*_t
    
    With this, I believe MATH table API is not ready to be merged.

diff --git a/docs/harfbuzz-sections.txt b/docs/harfbuzz-sections.txt
index d94cf70..75d7492 100644
--- a/docs/harfbuzz-sections.txt
+++ b/docs/harfbuzz-sections.txt
@@ -426,10 +426,10 @@ Xhb_ot_layout_lookup_substitute
 <FILE>hb-ot-math</FILE>
 HB_OT_TAG_MATH
 HB_OT_MATH_SCRIPT
-hb_math_glyph_part_flags_t
-hb_math_glyph_part_t
-hb_math_glyph_variant_t
 hb_ot_math_constant_t
+hb_ot_math_glyph_part_flags_t
+hb_ot_math_glyph_part_t
+hb_ot_math_glyph_variant_t
 hb_ot_math_get_constant
 hb_ot_math_get_glyph_assembly
 hb_ot_math_get_glyph_italics_correction
diff --git a/src/hb-ot-layout-math-table.hh b/src/hb-ot-layout-math-table.hh
index efffd2b..b52b121 100644
--- a/src/hb-ot-layout-math-table.hh
+++ b/src/hb-ot-layout-math-table.hh
@@ -453,7 +453,7 @@ struct MathGlyphPartRecord
     return_trace (c->check_struct (this));
   }
 
-  inline void extract (hb_math_glyph_part_t &out,
+  inline void extract (hb_ot_math_glyph_part_t &out,
 		       int scale,
 		       hb_font_t *font) const
   {
@@ -466,7 +466,7 @@ struct MathGlyphPartRecord
     ASSERT_STATIC ((unsigned int) HB_MATH_GLYPH_PART_FLAG_EXTENDER ==
 		   (unsigned int) PartFlags::Extender);
 
-    out.flags = (hb_math_glyph_part_flags_t)
+    out.flags = (hb_ot_math_glyph_part_flags_t)
 		(unsigned int)
 		(partFlags & PartFlags::Defined);
   }
@@ -504,7 +504,7 @@ struct MathGlyphAssembly
 				 hb_font_t *font,
 				 unsigned int start_offset,
 				 unsigned int *parts_count, /* IN/OUT */
-				 hb_math_glyph_part_t *parts /* OUT */,
+				 hb_ot_math_glyph_part_t *parts /* OUT */,
 				 hb_position_t *italics_correction /* OUT */) const
   {
     if (parts_count)
@@ -552,7 +552,7 @@ struct MathGlyphConstruction
 				    hb_font_t *font,
 				    unsigned int start_offset,
 				    unsigned int *variants_count, /* IN/OUT */
-				    hb_math_glyph_variant_t *variants /* OUT */) const
+				    hb_ot_math_glyph_variant_t *variants /* OUT */) const
   {
     if (variants_count)
     {
@@ -613,7 +613,7 @@ struct MathVariants
 					  hb_font_t *font,
 					  unsigned int start_offset,
 					  unsigned int *variants_count, /* IN/OUT */
-					  hb_math_glyph_variant_t *variants /* OUT */) const
+					  hb_ot_math_glyph_variant_t *variants /* OUT */) const
   { return get_glyph_construction (glyph, direction, font)
 	   .get_variants (direction, font, start_offset, variants_count, variants); }
 
@@ -622,7 +622,7 @@ struct MathVariants
 				       hb_font_t *font,
 				       unsigned int start_offset,
 				       unsigned int *parts_count, /* IN/OUT */
-				       hb_math_glyph_part_t *parts /* OUT */,
+				       hb_ot_math_glyph_part_t *parts /* OUT */,
 				       hb_position_t *italics_correction /* OUT */) const
   { return get_glyph_construction (glyph, direction, font)
 	   .get_assembly ()
diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc
index 210af50..49c75b0 100644
--- a/src/hb-ot-layout.cc
+++ b/src/hb-ot-layout.cc
@@ -1366,7 +1366,7 @@ hb_ot_math_get_glyph_kerning (hb_font_t *font,
  * This function tries to retrieve the MathGlyphConstruction for the specified
  * font, glyph and direction. Note that only the value of
  * #HB_DIRECTION_IS_HORIZONTAL is considered. It provides the corresponding list
- * of size variants as an array of hb_math_glyph_variant_t structs.
+ * of size variants as an array of hb_ot_math_glyph_variant_t structs.
  *
  * Return value: the total number of size variants available or 0
  *
@@ -1378,7 +1378,7 @@ hb_ot_math_get_glyph_variants (hb_font_t *font,
 			       hb_direction_t direction,
 			       unsigned int start_offset,
 			       unsigned int *variants_count, /* IN/OUT */
-			       hb_math_glyph_variant_t *variants /* OUT */)
+			       hb_ot_math_glyph_variant_t *variants /* OUT */)
 {
   const OT::MATH &math = _get_math (font->face);
   return math.get_math_variants().get_glyph_variants (glyph, direction, font,
@@ -1425,7 +1425,7 @@ hb_ot_math_get_min_connector_overlap (hb_font_t *font,
  * This function tries to retrieve the GlyphAssembly for the specified font,
  * glyph and direction. Note that only the value of #HB_DIRECTION_IS_HORIZONTAL
  * is considered. It provides the information necessary to draw the glyph
- * assembly as an array of #hb_math_glyph_part_t.
+ * assembly as an array of #hb_ot_math_glyph_part_t.
  *
  * Return value: the total number of parts in the glyph assembly
  *
@@ -1437,7 +1437,7 @@ hb_ot_math_get_glyph_assembly (hb_font_t *font,
 			       hb_direction_t direction,
 			       unsigned int start_offset,
 			       unsigned int *parts_count, /* IN/OUT */
-			       hb_math_glyph_part_t *parts, /* OUT */
+			       hb_ot_math_glyph_part_t *parts, /* OUT */
 			       hb_position_t *italics_correction /* OUT */)
 {
   const OT::MATH &math = _get_math (font->face);
diff --git a/src/hb-ot-math.h b/src/hb-ot-math.h
index 814e404..e186fa9 100644
--- a/src/hb-ot-math.h
+++ b/src/hb-ot-math.h
@@ -113,22 +113,22 @@ typedef enum {
   HB_OT_MATH_KERN_BOTTOM_LEFT = 3
 } hb_ot_math_kern_t;
 
-typedef struct hb_math_glyph_variant_t {
+typedef struct hb_ot_math_glyph_variant_t {
   hb_codepoint_t glyph;
   hb_position_t advance;
-} hb_math_glyph_variant_t;
+} hb_ot_math_glyph_variant_t;
 
 typedef enum { /*< flags >*/
   HB_MATH_GLYPH_PART_FLAG_EXTENDER	= 0x00000001u  /* Extender glyph */
-} hb_math_glyph_part_flags_t;
+} hb_ot_math_glyph_part_flags_t;
 
-typedef struct hb_math_glyph_part_t {
+typedef struct hb_ot_math_glyph_part_t {
   hb_codepoint_t glyph;
   hb_position_t start_connector_length;
   hb_position_t end_connector_length;
   hb_position_t full_advance;
-  hb_math_glyph_part_flags_t flags;
-} hb_math_glyph_part_t;
+  hb_ot_math_glyph_part_flags_t flags;
+} hb_ot_math_glyph_part_t;
 
 /* Methods */
 
@@ -163,7 +163,7 @@ hb_ot_math_get_glyph_variants (hb_font_t *font,
 			       hb_direction_t direction,
 			       unsigned int start_offset,
 			       unsigned int *variants_count, /* IN/OUT */
-			       hb_math_glyph_variant_t *variants /* OUT */);
+			       hb_ot_math_glyph_variant_t *variants /* OUT */);
 
 HB_EXTERN hb_position_t
 hb_ot_math_get_min_connector_overlap (hb_font_t *font,
@@ -175,7 +175,7 @@ hb_ot_math_get_glyph_assembly (hb_font_t *font,
 			       hb_direction_t direction,
 			       unsigned int start_offset,
 			       unsigned int *parts_count, /* IN/OUT */
-			       hb_math_glyph_part_t *parts, /* OUT */
+			       hb_ot_math_glyph_part_t *parts, /* OUT */
 			       hb_position_t *italics_correction /* OUT */);
 
 
diff --git a/test/api/test-ot-math.c b/test/api/test-ot-math.c
index 4d6f67b..5f4ccb7 100644
--- a/test/api/test-ot-math.c
+++ b/test/api/test-ot-math.c
@@ -459,7 +459,7 @@ test_get_glyph_variants (void)
                                                  NULL), ==, 0);
 
   g_assert(hb_font_get_glyph_from_name (hb_font, "arrowleft", -1, &glyph));
-  hb_math_glyph_variant_t variants[20];
+  hb_ot_math_glyph_variant_t variants[20];
   unsigned variantsSize = sizeof (variants) / sizeof (variants[0]);
   unsigned int count;
   unsigned int offset = 0;
@@ -586,7 +586,7 @@ test_get_glyph_assembly (void)
                                                  NULL), ==, 0);
 
   g_assert(hb_font_get_glyph_from_name (hb_font, "arrowright", -1, &glyph));
-  hb_math_glyph_part_t parts[20];
+  hb_ot_math_glyph_part_t parts[20];
   unsigned partsSize = sizeof (parts) / sizeof (parts[0]);
   unsigned int count;
   unsigned int offset = 0;
commit db5ebcf10f8595d1f4a9df27befd6cb5e76ca94d
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Tue Sep 27 16:42:25 2016 +0200

    Update docs

diff --git a/docs/harfbuzz-docs.xml b/docs/harfbuzz-docs.xml
index 2c43c46..ea99732 100644
--- a/docs/harfbuzz-docs.xml
+++ b/docs/harfbuzz-docs.xml
@@ -80,6 +80,7 @@
         <xi:include href="xml/hb-ot-tag.xml"/>
         <xi:include href="xml/hb-ot-font.xml"/>
         <xi:include href="xml/hb-ot-shape.xml"/>
+        <xi:include href="xml/hb-ot-math.xml"/>
 
         <xi:include href="xml/hb-shape-plan.xml"/>
 
@@ -175,6 +176,14 @@
         <title>Index of new symbols in 1.1.3</title>
         <xi:include href="xml/api-index-1.1.3.xml"><xi:fallback /></xi:include>
       </index>
+      <index id="api-index-1-2-3" role="1.2.3">
+        <title>Index of new symbols in 1.2.3</title>
+        <xi:include href="xml/api-index-1.2.3.xml"><xi:fallback /></xi:include>
+      </index>
+      <index id="api-index-1-4-0" role="1.4.0">
+        <title>Index of new symbols in 1.4.0</title>
+        <xi:include href="xml/api-index-1.4.0.xml"><xi:fallback /></xi:include>
+      </index>
       <index id="deprecated-api-index" role="deprecated">
         <title>Index of deprecated API</title>
         <xi:include href="xml/api-index-deprecated.xml"><xi:fallback /></xi:include>
diff --git a/docs/harfbuzz-sections.txt b/docs/harfbuzz-sections.txt
index e0dc23d..d94cf70 100644
--- a/docs/harfbuzz-sections.txt
+++ b/docs/harfbuzz-sections.txt
@@ -144,6 +144,8 @@ uint8_t
 HB_BUFFER_FLAGS_DEFAULT
 HB_BUFFER_SERIALIZE_FLAGS_DEFAULT
 HB_SCRIPT_CANADIAN_ABORIGINAL
+hb_font_funcs_set_glyph_func
+hb_font_get_glyph_func_t
 </SECTION>
 
 <SECTION>
@@ -193,7 +195,6 @@ hb_font_funcs_reference
 hb_font_funcs_set_glyph_contour_point_func
 hb_font_funcs_set_glyph_extents_func
 hb_font_funcs_set_glyph_from_name_func
-hb_font_funcs_set_glyph_func
 hb_font_funcs_set_glyph_h_advance_func
 hb_font_funcs_set_glyph_h_kerning_func
 hb_font_funcs_set_glyph_h_origin_func
@@ -201,7 +202,9 @@ hb_font_funcs_set_glyph_name_func
 hb_font_funcs_set_glyph_v_advance_func
 hb_font_funcs_set_glyph_v_kerning_func
 hb_font_funcs_set_glyph_v_origin_func
+hb_font_funcs_set_nominal_glyph_func
 hb_font_funcs_set_user_data
+hb_font_funcs_set_variation_glyph_func
 hb_font_funcs_t
 hb_font_get_empty
 hb_font_get_face
@@ -216,7 +219,6 @@ hb_font_get_glyph_extents_for_origin
 hb_font_get_glyph_extents_func_t
 hb_font_get_glyph_from_name
 hb_font_get_glyph_from_name_func_t
-hb_font_get_glyph_func_t
 hb_font_get_glyph_h_advance
 hb_font_get_glyph_h_advance_func_t
 hb_font_get_glyph_h_kerning
@@ -235,10 +237,14 @@ hb_font_get_glyph_v_kerning
 hb_font_get_glyph_v_kerning_func_t
 hb_font_get_glyph_v_origin
 hb_font_get_glyph_v_origin_func_t
+hb_font_get_nominal_glyph
+hb_font_get_nominal_glyph_func_t
 hb_font_get_parent
 hb_font_get_ppem
 hb_font_get_scale
 hb_font_get_user_data
+hb_font_get_variation_glyph
+hb_font_get_variation_glyph_func_t
 hb_font_glyph_from_string
 hb_font_glyph_to_string
 hb_font_is_immutable
@@ -417,6 +423,26 @@ Xhb_ot_layout_lookup_substitute
 </SECTION>
 
 <SECTION>
+<FILE>hb-ot-math</FILE>
+HB_OT_TAG_MATH
+HB_OT_MATH_SCRIPT
+hb_math_glyph_part_flags_t
+hb_math_glyph_part_t
+hb_math_glyph_variant_t
+hb_ot_math_constant_t
+hb_ot_math_get_constant
+hb_ot_math_get_glyph_assembly
+hb_ot_math_get_glyph_italics_correction
+hb_ot_math_get_glyph_kerning
+hb_ot_math_get_glyph_top_accent_attachment
+hb_ot_math_get_glyph_variants
+hb_ot_math_get_min_connector_overlap
+hb_ot_math_has_data
+hb_ot_math_is_glyph_extended_shape
+hb_ot_math_kern_t
+</SECTION>
+
+<SECTION>
 <FILE>hb-ot-tag</FILE>
 HB_OT_TAG_DEFAULT_LANGUAGE
 HB_OT_TAG_DEFAULT_SCRIPT
commit 0762b35474c47171e5661904e93851eb73a44e5c
Author: Frédéric Wang <fred.wang at free.fr>
Date:   Tue Sep 27 15:28:35 2016 +0200

    Document API for MathVariants (#330)

diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc
index 588f5ab..210af50 100644
--- a/src/hb-ot-layout.cc
+++ b/src/hb-ot-layout.cc
@@ -1352,6 +1352,26 @@ hb_ot_math_get_glyph_kerning (hb_font_t *font,
   return math.get_math_glyph_info().get_kerning (glyph, kern, correction_height, font);
 }
 
+/**
+ * hb_ot_math_get_glyph_variants:
+ *
+ * @font: #hb_font_t from which to retrieve the values
+ * @glyph: index of the glyph to stretch
+ * @direction: direction of the stretching
+ * @start_offset: offset of the first variant to retrieve
+ * @variants_count: maximum number of variants to retrieve after start_offset
+ * (IN) and actual number of variants retrieved (OUT)
+ * @variants: array of size at least @variants_count to store the result
+ *
+ * This function tries to retrieve the MathGlyphConstruction for the specified
+ * font, glyph and direction. Note that only the value of
+ * #HB_DIRECTION_IS_HORIZONTAL is considered. It provides the corresponding list
+ * of size variants as an array of hb_math_glyph_variant_t structs.
+ *
+ * Return value: the total number of size variants available or 0
+ *
+ * Since: 1.4
+ **/
 unsigned int
 hb_ot_math_get_glyph_variants (hb_font_t *font,
 			       hb_codepoint_t glyph,
@@ -1367,6 +1387,21 @@ hb_ot_math_get_glyph_variants (hb_font_t *font,
 						      variants);
 }
 
+/**
+ * hb_ot_math_get_min_connector_overlap:
+ *
+ * @font: #hb_font_t from which to retrieve the value
+ * @direction: direction of the stretching
+ *
+ * This function tries to retrieve the MathVariants table for the specified
+ * font and returns the minimum overlap of connecting glyphs to draw a glyph
+ * assembly in the specified direction. Note that only the value of
+ * #HB_DIRECTION_IS_HORIZONTAL is considered.
+ *
+ * Return value: requested min connector overlap or 0
+ *
+ * Since: 1.4
+ **/
 hb_position_t
 hb_ot_math_get_min_connector_overlap (hb_font_t *font,
 				      hb_direction_t direction)
@@ -1375,6 +1410,27 @@ hb_ot_math_get_min_connector_overlap (hb_font_t *font,
   return math.get_math_variants().get_min_connector_overlap (direction, font);
 }
 
+/**
+ * hb_ot_math_get_glyph_assembly:
+ *
+ * @font: #hb_font_t from which to retrieve the values
+ * @glyph: index of the glyph to stretch
+ * @direction: direction of the stretching
+ * @start_offset: offset of the first glyph part to retrieve
+ * @parts_count: maximum number of glyph parts to retrieve after start_offset
+ * (IN) and actual number of parts retrieved (OUT)
+ * @parts: array of size at least @parts_count to store the result
+ * @italics_correction: italic correction of the glyph assembly
+ *
+ * This function tries to retrieve the GlyphAssembly for the specified font,
+ * glyph and direction. Note that only the value of #HB_DIRECTION_IS_HORIZONTAL
+ * is considered. It provides the information necessary to draw the glyph
+ * assembly as an array of #hb_math_glyph_part_t.
+ *
+ * Return value: the total number of parts in the glyph assembly
+ *
+ * Since: 1.4
+ **/
 unsigned int
 hb_ot_math_get_glyph_assembly (hb_font_t *font,
 			       hb_codepoint_t glyph,
commit 8d622f1114d6a0eca1786b94c7fc1a0bcd87f74b
Author: Frédéric Wang <fred.wang at free.fr>
Date:   Tue Sep 27 13:53:34 2016 +0200

    Add tests for get_mathvariant (#329)

diff --git a/test/api/test-ot-math.c b/test/api/test-ot-math.c
index 99993e0..4d6f67b 100644
--- a/test/api/test-ot-math.c
+++ b/test/api/test-ot-math.c
@@ -515,6 +515,165 @@ test_get_glyph_variants (void)
   cleanupFreeType();
 }
 
+static void
+test_get_glyph_assembly (void)
+{
+  hb_codepoint_t glyph;
+  initFreeType();
+
+  openFont("fonts/MathTestFontEmpty.otf");
+  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
+  g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, glyph, HB_DIRECTION_RTL, 0, NULL, NULL, NULL), ==, 0);
+  g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, glyph, HB_DIRECTION_BTT, 0, NULL, NULL, NULL), ==, 0);
+  closeFont();
+
+  openFont("fonts/MathTestFontPartial1.otf");
+  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
+  g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, glyph, HB_DIRECTION_RTL, 0, NULL, NULL, NULL), ==, 0);
+  g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, glyph, HB_DIRECTION_BTT, 0, NULL, NULL, NULL), ==, 0);
+  closeFont();
+
+  openFont("fonts/MathTestFontPartial2.otf");
+  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
+  g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, glyph, HB_DIRECTION_RTL, 0, NULL, NULL, NULL), ==, 0);
+  g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, glyph, HB_DIRECTION_BTT, 0, NULL, NULL, NULL), ==, 0);
+  closeFont();
+
+  openFont("fonts/MathTestFontPartial3.otf");
+  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
+  g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, glyph, HB_DIRECTION_RTL, 0, NULL, NULL, NULL), ==, 0);
+  g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, glyph, HB_DIRECTION_BTT, 0, NULL, NULL, NULL), ==, 0);
+  closeFont();
+
+  openFont("fonts/MathTestFontPartial4.otf");
+  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
+  g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, glyph, HB_DIRECTION_RTL, 0, NULL, NULL, NULL), ==, 0);
+  g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, glyph, HB_DIRECTION_BTT, 0, NULL, NULL, NULL), ==, 0);
+  closeFont();
+
+  openFont("fonts/MathTestFontFull.otf");
+
+  g_assert(hb_font_get_glyph_from_name (hb_font, "arrowright", -1, &glyph));
+  g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font,
+                                                 glyph,
+                                                 HB_DIRECTION_BTT,
+                                                 0,
+                                                 NULL,
+                                                 NULL,
+                                                 NULL), ==, 0);
+  g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font,
+                                                 glyph,
+                                                 HB_DIRECTION_RTL,
+                                                 0,
+                                                 NULL,
+                                                 NULL,
+                                                 NULL), ==, 3);
+
+  g_assert(hb_font_get_glyph_from_name (hb_font, "arrowdown", -1, &glyph));
+  g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font,
+                                                 glyph,
+                                                 HB_DIRECTION_BTT,
+                                                 0,
+                                                 NULL,
+                                                 NULL,
+                                                 NULL), ==, 5);
+  g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font,
+                                                 glyph,
+                                                 HB_DIRECTION_RTL,
+                                                 0,
+                                                 NULL,
+                                                 NULL,
+                                                 NULL), ==, 0);
+
+  g_assert(hb_font_get_glyph_from_name (hb_font, "arrowright", -1, &glyph));
+  hb_math_glyph_part_t parts[20];
+  unsigned partsSize = sizeof (parts) / sizeof (parts[0]);
+  unsigned int count;
+  unsigned int offset = 0;
+  do {
+    count = partsSize;
+    hb_ot_math_get_glyph_assembly (hb_font,
+                                   glyph,
+                                   HB_DIRECTION_RTL,
+                                   offset,
+                                   &count,
+                                   parts,
+                                   NULL);
+    offset += count;
+  } while (count == partsSize);
+  g_assert_cmpint(offset, ==, 3);
+  g_assert(hb_font_get_glyph_from_name (hb_font, "left", -1, &glyph));
+  g_assert_cmpint(parts[0].glyph, ==, glyph);
+  g_assert_cmpint(parts[0].start_connector_length, ==, 800);
+  g_assert_cmpint(parts[0].end_connector_length, ==, 384);
+  g_assert_cmpint(parts[0].full_advance, ==, 2000);
+  g_assert(!(parts[0].flags & HB_MATH_GLYPH_PART_FLAG_EXTENDER));
+  g_assert(hb_font_get_glyph_from_name (hb_font, "horizontal", -1, &glyph));
+  g_assert_cmpint(parts[1].glyph, ==, glyph);
+  g_assert_cmpint(parts[1].start_connector_length, ==, 524);
+  g_assert_cmpint(parts[1].end_connector_length, ==, 800);
+  g_assert_cmpint(parts[1].full_advance, ==, 2000);
+  g_assert(parts[1].flags & HB_MATH_GLYPH_PART_FLAG_EXTENDER);
+  g_assert(hb_font_get_glyph_from_name (hb_font, "right", -1, &glyph));
+  g_assert_cmpint(parts[2].glyph, ==, glyph);
+  g_assert_cmpint(parts[2].start_connector_length, ==, 316);
+  g_assert_cmpint(parts[2].end_connector_length, ==, 454);
+  g_assert_cmpint(parts[2].full_advance, ==, 2000);
+  g_assert(!(parts[2].flags & HB_MATH_GLYPH_PART_FLAG_EXTENDER));
+
+  g_assert(hb_font_get_glyph_from_name (hb_font, "arrowdown", -1, &glyph));
+  offset = 0;
+  do {
+    count = partsSize;
+    hb_ot_math_get_glyph_assembly (hb_font,
+                                   glyph,
+                                   HB_DIRECTION_BTT,
+                                   offset,
+                                   &count,
+                                   parts,
+                                   NULL);
+    offset += count;
+  } while (count == partsSize);
+  g_assert_cmpint(offset, ==, 5);
+  g_assert(hb_font_get_glyph_from_name (hb_font, "bottom", -1, &glyph));
+  g_assert_cmpint(parts[0].glyph, ==, glyph);
+  g_assert_cmpint(parts[0].start_connector_length, ==, 365);
+  g_assert_cmpint(parts[0].end_connector_length, ==, 158);
+  g_assert_cmpint(parts[0].full_advance, ==, 1000);
+  g_assert(!(parts[0].flags & HB_MATH_GLYPH_PART_FLAG_EXTENDER));
+  g_assert(hb_font_get_glyph_from_name (hb_font, "vertical", -1, &glyph));
+  g_assert_cmpint(parts[1].glyph, ==, glyph);
+  g_assert_cmpint(parts[1].glyph, ==, glyph);
+  g_assert_cmpint(parts[1].start_connector_length, ==, 227);
+  g_assert_cmpint(parts[1].end_connector_length, ==, 365);
+  g_assert_cmpint(parts[1].full_advance, ==, 1000);
+  g_assert(parts[1].flags & HB_MATH_GLYPH_PART_FLAG_EXTENDER);
+  g_assert(hb_font_get_glyph_from_name (hb_font, "center", -1, &glyph));
+  g_assert_cmpint(parts[2].glyph, ==, glyph);
+  g_assert_cmpint(parts[2].start_connector_length, ==, 54);
+  g_assert_cmpint(parts[2].end_connector_length, ==, 158);
+  g_assert_cmpint(parts[2].full_advance, ==, 1000);
+  g_assert(!(parts[2].flags & HB_MATH_GLYPH_PART_FLAG_EXTENDER));
+  g_assert(hb_font_get_glyph_from_name (hb_font, "vertical", -1, &glyph));
+  g_assert_cmpint(parts[3].glyph, ==, glyph);
+  g_assert_cmpint(parts[3].glyph, ==, glyph);
+  g_assert_cmpint(parts[3].glyph, ==, glyph);
+  g_assert_cmpint(parts[3].start_connector_length, ==, 400);
+  g_assert_cmpint(parts[3].end_connector_length, ==, 296);
+  g_assert_cmpint(parts[3].full_advance, ==, 1000);
+  g_assert(parts[1].flags & HB_MATH_GLYPH_PART_FLAG_EXTENDER);
+  g_assert(hb_font_get_glyph_from_name (hb_font, "top", -1, &glyph));
+  g_assert_cmpint(parts[4].glyph, ==, glyph);
+  g_assert_cmpint(parts[4].start_connector_length, ==, 123);
+  g_assert_cmpint(parts[4].end_connector_length, ==, 192);
+  g_assert_cmpint(parts[4].full_advance, ==, 1000);
+  g_assert(!(parts[4].flags & HB_MATH_GLYPH_PART_FLAG_EXTENDER));
+
+  closeFont();
+
+  cleanupFreeType();
+}
+
 int
 main (int argc, char **argv)
 {
@@ -529,6 +688,7 @@ main (int argc, char **argv)
   hb_test_add (test_get_glyph_assembly_italics_correction);
   hb_test_add (test_get_min_connector_overlap);
   hb_test_add (test_get_glyph_variants);
+  hb_test_add (test_get_glyph_assembly);
 
   return hb_test_run();
 }
commit 485e4873fb7cacfa9d853272c2275bbc5826023e
Author: Frédéric Wang <fred.wang at free.fr>
Date:   Tue Sep 27 13:18:00 2016 +0200

    Add tests for hb_ot_math_get_glyph_variants (#328)

diff --git a/test/api/test-ot-math.c b/test/api/test-ot-math.c
index 668cc97..99993e0 100644
--- a/test/api/test-ot-math.c
+++ b/test/api/test-ot-math.c
@@ -326,6 +326,7 @@ get_glyph_assembly_italics_correction (hb_font_t *font,
   return corr;
 }
 
+static void
 test_get_glyph_assembly_italics_correction (void)
 {
   hb_codepoint_t glyph;
@@ -373,6 +374,7 @@ test_get_glyph_assembly_italics_correction (void)
   cleanupFreeType();
 }
 
+static void
 test_get_min_connector_overlap (void)
 {
   initFreeType();
@@ -390,6 +392,129 @@ test_get_min_connector_overlap (void)
   cleanupFreeType();
 }
 
+static void
+test_get_glyph_variants (void)
+{
+  hb_codepoint_t glyph;
+  initFreeType();
+
+  openFont("fonts/MathTestFontEmpty.otf");
+  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
+  g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, glyph, HB_DIRECTION_RTL, 0, NULL, NULL), ==, 0);
+  g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, glyph, HB_DIRECTION_BTT, 0, NULL, NULL), ==, 0);
+  closeFont();
+
+  openFont("fonts/MathTestFontPartial1.otf");
+  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
+  g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, glyph, HB_DIRECTION_RTL, 0, NULL, NULL), ==, 0);
+  g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, glyph, HB_DIRECTION_BTT, 0, NULL, NULL), ==, 0);
+  closeFont();
+
+  openFont("fonts/MathTestFontPartial2.otf");
+  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
+  g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, glyph, HB_DIRECTION_RTL, 0, NULL, NULL), ==, 0);
+  g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, glyph, HB_DIRECTION_BTT, 0, NULL, NULL), ==, 0);
+  closeFont();
+
+  openFont("fonts/MathTestFontPartial3.otf");
+  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
+  g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, glyph, HB_DIRECTION_RTL, 0, NULL, NULL), ==, 0);
+  g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, glyph, HB_DIRECTION_BTT, 0, NULL, NULL), ==, 0);
+  closeFont();
+
+  openFont("fonts/MathTestFontPartial4.otf");
+  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
+  g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, glyph, HB_DIRECTION_RTL, 0, NULL, NULL), ==, 0);
+  g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, glyph, HB_DIRECTION_BTT, 0, NULL, NULL), ==, 0);
+  closeFont();
+
+  openFont("fonts/MathTestFontFull.otf");
+
+  g_assert(hb_font_get_glyph_from_name (hb_font, "arrowleft", -1, &glyph));
+  g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font,
+                                                 glyph,
+                                                 HB_DIRECTION_BTT,
+                                                 0,
+                                                 NULL,
+                                                 NULL), ==, 0);
+  g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font,
+                                                 glyph,
+                                                 HB_DIRECTION_RTL,
+                                                 0,
+                                                 NULL,
+                                                 NULL), ==, 3);
+
+  g_assert(hb_font_get_glyph_from_name (hb_font, "arrowup", -1, &glyph));
+  g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font,
+                                                 glyph,
+                                                 HB_DIRECTION_BTT,
+                                                 0,
+                                                 NULL,
+                                                 NULL), ==, 4);
+  g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font,
+                                                 glyph,
+                                                 HB_DIRECTION_RTL,
+                                                 0,
+                                                 NULL,
+                                                 NULL), ==, 0);
+
+  g_assert(hb_font_get_glyph_from_name (hb_font, "arrowleft", -1, &glyph));
+  hb_math_glyph_variant_t variants[20];
+  unsigned variantsSize = sizeof (variants) / sizeof (variants[0]);
+  unsigned int count;
+  unsigned int offset = 0;
+  do {
+    count = variantsSize;
+    hb_ot_math_get_glyph_variants (hb_font,
+                                   glyph,
+                                   HB_DIRECTION_RTL,
+                                   offset,
+                                   &count,
+                                   variants);
+    offset += count;
+  } while (count == variantsSize);
+  g_assert_cmpint(offset, ==, 3);
+  g_assert(hb_font_get_glyph_from_name (hb_font, "uni2190_size2", -1, &glyph));
+  g_assert_cmpint(variants[0].glyph, ==, glyph);
+  g_assert_cmpint(variants[0].advance, ==, 4302);
+  g_assert(hb_font_get_glyph_from_name (hb_font, "uni2190_size3", -1, &glyph));
+  g_assert_cmpint(variants[1].glyph, ==, glyph);
+  g_assert_cmpint(variants[1].advance, ==, 4802);
+  g_assert(hb_font_get_glyph_from_name (hb_font, "uni2190_size4", -1, &glyph));
+  g_assert_cmpint(variants[2].glyph, ==, glyph);
+  g_assert_cmpint(variants[2].advance, ==, 5802);
+
+  g_assert(hb_font_get_glyph_from_name (hb_font, "arrowup", -1, &glyph));
+  offset = 0;
+  do {
+    count = variantsSize;
+    hb_ot_math_get_glyph_variants (hb_font,
+                                   glyph,
+                                   HB_DIRECTION_BTT,
+                                   offset,
+                                   &count,
+                                   variants);
+    offset += count;
+  } while (count == variantsSize);
+  g_assert_cmpint(offset, ==, 4);
+  g_assert(hb_font_get_glyph_from_name (hb_font, "uni2191_size2", -1, &glyph));
+  g_assert_cmpint(variants[0].glyph, ==, glyph);
+  g_assert_cmpint(variants[0].advance, ==, 2251);
+  g_assert(hb_font_get_glyph_from_name (hb_font, "uni2191_size3", -1, &glyph));
+  g_assert_cmpint(variants[1].glyph, ==, glyph);
+  g_assert_cmpint(variants[1].advance, ==, 2501);
+  g_assert(hb_font_get_glyph_from_name (hb_font, "uni2191_size4", -1, &glyph));
+  g_assert_cmpint(variants[2].glyph, ==, glyph);
+  g_assert_cmpint(variants[2].advance, ==, 3001);
+  g_assert(hb_font_get_glyph_from_name (hb_font, "uni2191_size5", -1, &glyph));
+  g_assert_cmpint(variants[3].glyph, ==, glyph);
+  g_assert_cmpint(variants[3].advance, ==, 3751);
+
+  closeFont();
+
+  cleanupFreeType();
+}
+
 int
 main (int argc, char **argv)
 {
@@ -403,6 +528,7 @@ main (int argc, char **argv)
   hb_test_add (test_get_glyph_kerning);
   hb_test_add (test_get_glyph_assembly_italics_correction);
   hb_test_add (test_get_min_connector_overlap);
+  hb_test_add (test_get_glyph_variants);
 
   return hb_test_run();
 }
commit a5629a2ed9c2e69f2b4ebb74d85fbe0b5ba2be67
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Tue Sep 27 11:30:44 2016 +0200

    [MATH] Simplify test

diff --git a/test/api/test-ot-math.c b/test/api/test-ot-math.c
index 4bffcc0..668cc97 100644
--- a/test/api/test-ot-math.c
+++ b/test/api/test-ot-math.c
@@ -319,10 +319,9 @@ get_glyph_assembly_italics_correction (hb_font_t *font,
 				       hb_bool_t horizontal)
 {
   hb_position_t corr;
-  unsigned int count = 0;
   hb_ot_math_get_glyph_assembly (font, glyph,
 				 horizontal ? HB_DIRECTION_LTR : HB_DIRECTION_TTB,
-				 0, &count, NULL,
+				 0, NULL, NULL,
 				 &corr);
   return corr;
 }
commit edcfa789bf92c18f5badad31c0ad04a6a77d7226
Author: Frédéric Wang <fred.wang at free.fr>
Date:   Tue Sep 27 11:02:08 2016 +0200

    test-ot-math: Use different scales for vertical and horizontal directions and add test for hb_ot_math_get_min_connector_overlap. (#327)

diff --git a/test/api/test-ot-math.c b/test/api/test-ot-math.c
index 4a79681..4bffcc0 100644
--- a/test/api/test-ot-math.c
+++ b/test/api/test-ot-math.c
@@ -63,8 +63,7 @@ openFont(const char* fontFile)
   }
   g_free(path);
 
-#define fontSize 1000
-  if ((ft_error = FT_Set_Char_Size (ft_face, fontSize, fontSize, 0, 0)))
+  if ((ft_error = FT_Set_Char_Size (ft_face, 2000, 1000, 0, 0)))
     abort();
   hb_font = hb_ft_font_create (ft_face, NULL);
   hb_face = hb_ft_face_create_cached(ft_face);
@@ -118,7 +117,7 @@ test_get_constant (void)
   g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SUPERSCRIPT_BASELINE_DROP_MAX)), ==, 1400);
   g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SUB_SUPERSCRIPT_GAP_MIN)), ==, 1500);
   g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SUPERSCRIPT_BOTTOM_MAX_WITH_SUBSCRIPT)), ==, 1600);
-  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SPACE_AFTER_SCRIPT)), ==, 1700);
+  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SPACE_AFTER_SCRIPT)), ==, 3400);
   g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_UPPER_LIMIT_GAP_MIN)), ==, 1800);
   g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_UPPER_LIMIT_BASELINE_RISE_MIN)), ==, 1900);
   g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_LOWER_LIMIT_GAP_MIN)), ==, 2200);
@@ -142,7 +141,7 @@ test_get_constant (void)
   g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_RULE_THICKNESS)), ==, 4000);
   g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_GAP_MIN)), ==, 4100);
   g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_DENOM_DISPLAY_STYLE_GAP_MIN)), ==, 4200);
-  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SKEWED_FRACTION_HORIZONTAL_GAP)), ==, 4300);
+  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SKEWED_FRACTION_HORIZONTAL_GAP)), ==, 8600);
   g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SKEWED_FRACTION_VERTICAL_GAP)), ==, 4400);
   g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_OVERBAR_VERTICAL_GAP)), ==, 4500);
   g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_OVERBAR_RULE_THICKNESS)), ==, 4600);
@@ -154,8 +153,8 @@ test_get_constant (void)
   g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_DISPLAY_STYLE_VERTICAL_GAP)), ==, 5200);
   g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_RULE_THICKNESS)), ==, 5300);
   g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_EXTRA_ASCENDER)), ==, 5400);
-  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_KERN_BEFORE_DEGREE)), ==, 5500);
-  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_KERN_AFTER_DEGREE)), ==, 5600);
+  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_KERN_BEFORE_DEGREE)), ==, 11000);
+  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_KERN_AFTER_DEGREE)), ==, 11200);
   g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN)), ==, 87);
   g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN)), ==, 76);
   g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_DEGREE_BOTTOM_RAISE_PERCENT)), ==, 65);
@@ -189,11 +188,11 @@ test_get_glyph_italics_correction (void)
   g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
   g_assert_cmpint(hb_ot_math_get_glyph_italics_correction (hb_font, glyph), ==, 0); // Glyph without italic correction.
   g_assert(hb_font_get_glyph_from_name (hb_font, "A", -1, &glyph));
-  g_assert_cmpint(hb_ot_math_get_glyph_italics_correction (hb_font, glyph), ==, 197);
+  g_assert_cmpint(hb_ot_math_get_glyph_italics_correction (hb_font, glyph), ==, 394);
   g_assert(hb_font_get_glyph_from_name (hb_font, "B", -1, &glyph));
-  g_assert_cmpint(hb_ot_math_get_glyph_italics_correction (hb_font, glyph), ==, 150);
+  g_assert_cmpint(hb_ot_math_get_glyph_italics_correction (hb_font, glyph), ==, 300);
   g_assert(hb_font_get_glyph_from_name (hb_font, "C", -1, &glyph));
-  g_assert_cmpint(hb_ot_math_get_glyph_italics_correction (hb_font, glyph), ==, 452);
+  g_assert_cmpint(hb_ot_math_get_glyph_italics_correction (hb_font, glyph), ==, 904);
   closeFont();
 
   cleanupFreeType();
@@ -207,28 +206,28 @@ test_get_glyph_top_accent_attachment (void)
 
   openFont("fonts/MathTestFontEmpty.otf");
   g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
-  g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 500); // MathGlyphInfo not available
+  g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 1000); // MathGlyphInfo not available
   closeFont();
 
   openFont("fonts/MathTestFontPartial1.otf");
   g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
-  g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 500); // MathGlyphInfo empty
+  g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 1000); // MathGlyphInfo empty
   closeFont();
 
   openFont("fonts/MathTestFontPartial2.otf");
   g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
-  g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 500); // MathTopAccentAttachment empty
+  g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 1000); // MathTopAccentAttachment empty
   closeFont();
 
   openFont("fonts/MathTestFontFull.otf");
   g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
-  g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 500); // Glyph without top accent attachment.
+  g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 1000); // Glyph without top accent attachment.
   g_assert(hb_font_get_glyph_from_name (hb_font, "D", -1, &glyph));
-  g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 374);
+  g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 748);
   g_assert(hb_font_get_glyph_from_name (hb_font, "E", -1, &glyph));
-  g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 346);
+  g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 692);
   g_assert(hb_font_get_glyph_from_name (hb_font, "F", -1, &glyph));
-  g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 318);
+  g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 636);
   closeFont();
 
   cleanupFreeType();
@@ -293,20 +292,20 @@ test_get_glyph_kerning (void)
   openFont("fonts/MathTestFontFull.otf");
   g_assert(hb_font_get_glyph_from_name (hb_font, "I", -1, &glyph));
 
-  g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 7), ==, 31); // lower than min heigth
-  g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 14), ==, 31); // equal to min height
-  g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 20), ==, 52);
-  g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 23), ==, 52);
-  g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 31), ==, 73);
-  g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 32), ==, 73);
-  g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 86), ==, 199); // equal to max height
-  g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 91), ==, 220); // larger than max height
-  g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 96), ==, 220); // larger than max height
-
-  g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 39), ==, 94); // top right
-  g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_LEFT, 39), ==, 55); // top left
-  g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_RIGHT, 39), ==, 22); // bottom right
-  g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_LEFT, 39), ==, 50); // bottom left
+  g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 7), ==, 62); // lower than min heigth
+  g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 14), ==, 62); // equal to min height
+  g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 20), ==, 104);
+  g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 23), ==, 104);
+  g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 31), ==, 146);
+  g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 32), ==, 146);
+  g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 86), ==, 398); // equal to max height
+  g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 91), ==, 440); // larger than max height
+  g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 96), ==, 440); // larger than max height
+
+  g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 39), ==, 188); // top right
+  g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_LEFT, 39), ==, 110); // top left
+  g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_RIGHT, 39), ==, 44); // bottom right
+  g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_LEFT, 39), ==, 100); // bottom left
 
   closeFont();
 
@@ -365,11 +364,28 @@ test_get_glyph_assembly_italics_correction (void)
 
   openFont("fonts/MathTestFontFull.otf");
   g_assert(hb_font_get_glyph_from_name (hb_font, "arrowleft", -1, &glyph));
-  g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, TRUE), ==, 124);
+  g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, TRUE), ==, 248);
   g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, FALSE), ==, 0);
   g_assert(hb_font_get_glyph_from_name (hb_font, "arrowup", -1, &glyph));
   g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, TRUE), ==, 0);
-  g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, FALSE), ==, 331);
+  g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, FALSE), ==, 662);
+  closeFont();
+
+  cleanupFreeType();
+}
+
+test_get_min_connector_overlap (void)
+{
+  initFreeType();
+
+  openFont("fonts/MathTestFontEmpty.otf");
+  g_assert_cmpint(hb_ot_math_get_min_connector_overlap(hb_font, FALSE), ==, 0); // MathVariants not available
+  g_assert_cmpint(hb_ot_math_get_min_connector_overlap(hb_font, TRUE), ==, 0); // MathVariants not available
+  closeFont();
+
+  openFont("fonts/MathTestFontPartial1.otf");
+  g_assert_cmpint(hb_ot_math_get_min_connector_overlap(hb_font, HB_DIRECTION_LTR), ==, 108);
+  g_assert_cmpint(hb_ot_math_get_min_connector_overlap(hb_font, HB_DIRECTION_TTB), ==, 54);
   closeFont();
 
   cleanupFreeType();
@@ -387,6 +403,7 @@ main (int argc, char **argv)
   hb_test_add (test_is_glyph_extended_shape);
   hb_test_add (test_get_glyph_kerning);
   hb_test_add (test_get_glyph_assembly_italics_correction);
+  hb_test_add (test_get_min_connector_overlap);
 
   return hb_test_run();
 }
commit bc19f7fe20e89823dba07a46c3d48c7406b781b6
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Tue Sep 27 10:58:08 2016 +0200

    [MATH] Add HB_OT_MATH_SCRIPT

diff --git a/src/hb-ot-math.h b/src/hb-ot-math.h
index ad8bf14..814e404 100644
--- a/src/hb-ot-math.h
+++ b/src/hb-ot-math.h
@@ -42,6 +42,9 @@ HB_BEGIN_DECLS
 
 #define HB_OT_TAG_MATH HB_TAG('M','A','T','H')
 
+/* Use with hb_buffer_set_script() for math shaping. */
+#define HB_OT_MATH_SCRIPT HB_TAG('m','a','t','h')
+
 /* Types */
 
 typedef enum {
commit cdc9eef7da934ae71578694f29665e439686c3bd
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Sep 26 22:18:41 2016 +0200

    [MATH] Enable tests for glyph-assembly italics-correction

diff --git a/test/api/test-ot-math.c b/test/api/test-ot-math.c
index 23c19ef..4a79681 100644
--- a/test/api/test-ot-math.c
+++ b/test/api/test-ot-math.c
@@ -314,55 +314,66 @@ test_get_glyph_kerning (void)
 }
 
 
-#if 0
-static void
-test_get_math_italic_correction_for_glyph_assembly (void)
+static hb_position_t
+get_glyph_assembly_italics_correction (hb_font_t *font,
+				       hb_codepoint_t glyph,
+				       hb_bool_t horizontal)
+{
+  hb_position_t corr;
+  unsigned int count = 0;
+  hb_ot_math_get_glyph_assembly (font, glyph,
+				 horizontal ? HB_DIRECTION_LTR : HB_DIRECTION_TTB,
+				 0, &count, NULL,
+				 &corr);
+  return corr;
+}
+
+test_get_glyph_assembly_italics_correction (void)
 {
   hb_codepoint_t glyph;
   initFreeType();
 
   openFont("fonts/MathTestFontEmpty.otf");
   g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
-  g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, TRUE), ==, 0); // MathVariants not available
-  g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, FALSE), ==, 0); // MathVariants not available
+  g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, TRUE), ==, 0); // MathVariants not available
+  g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, FALSE), ==, 0); // MathVariants not available
   closeFont();
 
   openFont("fonts/MathTestFontPartial1.otf");
   g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
-  g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, TRUE), ==, 0); // VertGlyphCoverage and HorizGlyphCoverage absent
-  g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, FALSE), ==, 0); // VertGlyphCoverage and HorizGlyphCoverage absent
+  g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, TRUE), ==, 0); // VertGlyphCoverage and HorizGlyphCoverage absent
+  g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, FALSE), ==, 0); // VertGlyphCoverage and HorizGlyphCoverage absent
   closeFont();
 
   openFont("fonts/MathTestFontPartial2.otf");
   g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
-  g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, TRUE), ==, 0); // VertGlyphCoverage and HorizGlyphCoverage empty
-  g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, FALSE), ==, 0); // VertGlyphCoverage and HorizGlyphCoverage empty
+  g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, TRUE), ==, 0); // VertGlyphCoverage and HorizGlyphCoverage empty
+  g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, FALSE), ==, 0); // VertGlyphCoverage and HorizGlyphCoverage empty
   closeFont();
 
   openFont("fonts/MathTestFontPartial3.otf");
   g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
-  g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, TRUE), ==, 0); // HorizGlyphConstruction and VertGlyphConstruction empty
-  g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, FALSE), ==, 0);  // HorizGlyphConstruction and VertGlyphConstruction empty
+  g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, TRUE), ==, 0); // HorizGlyphConstruction and VertGlyphConstruction empty
+  g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, FALSE), ==, 0);  // HorizGlyphConstruction and VertGlyphConstruction empty
   closeFont();
 
   openFont("fonts/MathTestFontPartial4.otf");
   g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
-  g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, TRUE), ==, 0);
-  g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, FALSE), ==, 0);
+  g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, TRUE), ==, 0);
+  g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, FALSE), ==, 0);
   closeFont();
 
   openFont("fonts/MathTestFontFull.otf");
   g_assert(hb_font_get_glyph_from_name (hb_font, "arrowleft", -1, &glyph));
-  g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, TRUE), ==, 124);
-  g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, FALSE), ==, 0);
+  g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, TRUE), ==, 124);
+  g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, FALSE), ==, 0);
   g_assert(hb_font_get_glyph_from_name (hb_font, "arrowup", -1, &glyph));
-  g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, TRUE), ==, 0);
-  g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, FALSE), ==, 331);
+  g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, TRUE), ==, 0);
+  g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, FALSE), ==, 331);
   closeFont();
 
   cleanupFreeType();
 }
-#endif
 
 int
 main (int argc, char **argv)
@@ -375,7 +386,7 @@ main (int argc, char **argv)
   hb_test_add (test_get_glyph_top_accent_attachment);
   hb_test_add (test_is_glyph_extended_shape);
   hb_test_add (test_get_glyph_kerning);
-  //hb_test_add (test_get_math_italic_correction_for_glyph_assembly);
+  hb_test_add (test_get_glyph_assembly_italics_correction);
 
   return hb_test_run();
 }
commit 86106c7528d9bff8de6bc3e1487be780c31ea4fd
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Sep 26 22:12:48 2016 +0200

    [MATH] Rename all API to hb_ot_math_*

diff --git a/src/hb-ot-layout-private.hh b/src/hb-ot-layout-private.hh
index 775261a..a4272de 100644
--- a/src/hb-ot-layout-private.hh
+++ b/src/hb-ot-layout-private.hh
@@ -617,15 +617,5 @@ _hb_buffer_assert_gsubgpos_vars (hb_buffer_t *buffer)
 #undef lig_props
 #undef glyph_props
 
-namespace OT {
-  struct MathGlyphConstruction;
-};
-
-HB_INTERNAL hb_bool_t
-hb_ot_layout_get_math_glyph_construction (hb_font_t *font,
-                                          hb_codepoint_t glyph,
-                                          hb_bool_t horizontal,
-                                          hb_position_t &minConnectorOverlap,
-                                          const OT::MathGlyphConstruction *&glyph_construction);
 
 #endif /* HB_OT_LAYOUT_PRIVATE_HH */
diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc
index 942158e..588f5ab 100644
--- a/src/hb-ot-layout.cc
+++ b/src/hb-ot-layout.cc
@@ -1225,9 +1225,10 @@ hb_ot_layout_substitute_lookup (OT::hb_apply_context_t *c,
 /*
  * MATH
  */
+/* TODO Move this to hb-ot-math.cc and separate it from hb_ot_layout_t. */
 
 /**
- * hb_ot_layout_has_math_data:
+ * hb_ot_math_has_data:
  *
  * @face: #hb_face_t to test
  *
@@ -1240,13 +1241,13 @@ hb_ot_layout_substitute_lookup (OT::hb_apply_context_t *c,
  * Since: 1.4
  **/
 hb_bool_t
-hb_ot_layout_has_math_data (hb_face_t *face)
+hb_ot_math_has_data (hb_face_t *face)
 {
   return &_get_math (face) != &OT::Null(OT::MATH);
 }
 
 /**
- * hb_ot_layout_get_math_constant:
+ * hb_ot_math_get_constant:
  *
  * @font: #hb_font_t from which to retrieve the value
  * @constant: #hb_ot_math_constant_t the constant to retrieve
@@ -1262,15 +1263,15 @@ hb_ot_layout_has_math_data (hb_face_t *face)
  * Since: 1.4
  **/
 hb_position_t
-hb_ot_layout_get_math_constant (hb_font_t *font,
-				hb_ot_math_constant_t constant)
+hb_ot_math_get_constant (hb_font_t *font,
+			 hb_ot_math_constant_t constant)
 {
   const OT::MATH &math = _get_math (font->face);
   return math.get_constant(constant, font);
 }
 
 /**
- * hb_ot_layout_get_math_italics_correction:
+ * hb_ot_math_get_glyph_italics_correction:
  *
  * @font: #hb_font_t from which to retrieve the value
  * @glyph: glyph index from which to retrieve the value
@@ -1280,15 +1281,15 @@ hb_ot_layout_get_math_constant (hb_font_t *font,
  * Since: 1.4
  **/
 hb_position_t
-hb_ot_layout_get_math_italics_correction (hb_font_t *font,
-					  hb_codepoint_t glyph)
+hb_ot_math_get_glyph_italics_correction (hb_font_t *font,
+					 hb_codepoint_t glyph)
 {
   const OT::MATH &math = _get_math (font->face);
   return math.get_math_glyph_info().get_italics_correction (glyph, font);
 }
 
 /**
- * hb_ot_layout_get_math_top_accent_attachment:
+ * hb_ot_math_get_glyph_top_accent_attachment:
  *
  * @font: #hb_font_t from which to retrieve the value
  * @glyph: glyph index from which to retrieve the value
@@ -1298,15 +1299,15 @@ hb_ot_layout_get_math_italics_correction (hb_font_t *font,
  * Since: 1.4
  **/
 hb_position_t
-hb_ot_layout_get_math_top_accent_attachment (hb_font_t *font,
-					     hb_codepoint_t glyph)
+hb_ot_math_get_glyph_top_accent_attachment (hb_font_t *font,
+					    hb_codepoint_t glyph)
 {
   const OT::MATH &math = _get_math (font->face);
   return math.get_math_glyph_info().get_top_accent_attachment (glyph, font);
 }
 
 /**
- * hb_ot_layout_is_math_extended_shape:
+ * hb_ot_math_is_glyph_extended_shape:
  *
  * @font: a #hb_font_t to test
  * @glyph: a glyph index to test
@@ -1316,15 +1317,15 @@ hb_ot_layout_get_math_top_accent_attachment (hb_font_t *font,
  * Since: 1.4
  **/
 hb_bool_t
-hb_ot_layout_is_math_extended_shape (hb_face_t *face,
-				     hb_codepoint_t glyph)
+hb_ot_math_is_glyph_extended_shape (hb_face_t *face,
+				    hb_codepoint_t glyph)
 {
   const OT::MATH &math = _get_math (face);
   return math.get_math_glyph_info().is_extended_shape (glyph);
 }
 
 /**
- * hb_ot_layout_get_math_kerning:
+ * hb_ot_math_get_glyph_kerning:
  *
  * @font: #hb_font_t from which to retrieve the value
  * @glyph: glyph index from which to retrieve the value
@@ -1342,22 +1343,22 @@ hb_ot_layout_is_math_extended_shape (hb_face_t *face,
  * Since: 1.4
  **/
 hb_position_t
-hb_ot_layout_get_math_kerning (hb_font_t *font,
-			       hb_codepoint_t glyph,
-			       hb_ot_math_kern_t kern,
-			       hb_position_t correction_height)
+hb_ot_math_get_glyph_kerning (hb_font_t *font,
+			      hb_codepoint_t glyph,
+			      hb_ot_math_kern_t kern,
+			      hb_position_t correction_height)
 {
   const OT::MATH &math = _get_math (font->face);
   return math.get_math_glyph_info().get_kerning (glyph, kern, correction_height, font);
 }
 
 unsigned int
-hb_ot_layout_get_math_glyph_variants (hb_font_t *font,
-				      hb_codepoint_t glyph,
-				      hb_direction_t direction,
-				      unsigned int start_offset,
-				      unsigned int *variants_count, /* IN/OUT */
-				      hb_math_glyph_variant_t *variants /* OUT */)
+hb_ot_math_get_glyph_variants (hb_font_t *font,
+			       hb_codepoint_t glyph,
+			       hb_direction_t direction,
+			       unsigned int start_offset,
+			       unsigned int *variants_count, /* IN/OUT */
+			       hb_math_glyph_variant_t *variants /* OUT */)
 {
   const OT::MATH &math = _get_math (font->face);
   return math.get_math_variants().get_glyph_variants (glyph, direction, font,
@@ -1367,21 +1368,21 @@ hb_ot_layout_get_math_glyph_variants (hb_font_t *font,
 }
 
 hb_position_t
-hb_ot_layout_get_math_min_connector_overlap (hb_font_t *font,
-					     hb_direction_t direction)
+hb_ot_math_get_min_connector_overlap (hb_font_t *font,
+				      hb_direction_t direction)
 {
   const OT::MATH &math = _get_math (font->face);
   return math.get_math_variants().get_min_connector_overlap (direction, font);
 }
 
 unsigned int
-hb_ot_layout_get_math_glyph_assembly (hb_font_t *font,
-				      hb_codepoint_t glyph,
-				      hb_direction_t direction,
-				      unsigned int start_offset,
-				      unsigned int *parts_count, /* IN/OUT */
-				      hb_math_glyph_part_t *parts, /* OUT */
-				      hb_position_t *italics_correction /* OUT */)
+hb_ot_math_get_glyph_assembly (hb_font_t *font,
+			       hb_codepoint_t glyph,
+			       hb_direction_t direction,
+			       unsigned int start_offset,
+			       unsigned int *parts_count, /* IN/OUT */
+			       hb_math_glyph_part_t *parts, /* OUT */
+			       hb_position_t *italics_correction /* OUT */)
 {
   const OT::MATH &math = _get_math (font->face);
   return math.get_math_variants().get_glyph_parts (glyph, direction, font,
diff --git a/src/hb-ot-math.h b/src/hb-ot-math.h
index 5ff19fd..ad8bf14 100644
--- a/src/hb-ot-math.h
+++ b/src/hb-ot-math.h
@@ -130,50 +130,50 @@ typedef struct hb_math_glyph_part_t {
 /* Methods */
 
 HB_EXTERN hb_bool_t
-hb_ot_layout_has_math_data (hb_face_t *face);
+hb_ot_math_has_data (hb_face_t *face);
 
 HB_EXTERN hb_position_t
-hb_ot_layout_get_math_constant (hb_font_t *font,
-				hb_ot_math_constant_t constant);
+hb_ot_math_get_constant (hb_font_t *font,
+			 hb_ot_math_constant_t constant);
 
 HB_EXTERN hb_position_t
-hb_ot_layout_get_math_italics_correction (hb_font_t *font,
-					  hb_codepoint_t glyph);
+hb_ot_math_get_glyph_italics_correction (hb_font_t *font,
+					 hb_codepoint_t glyph);
 
 HB_EXTERN hb_position_t
-hb_ot_layout_get_math_top_accent_attachment (hb_font_t *font,
-					     hb_codepoint_t glyph);
+hb_ot_math_get_glyph_top_accent_attachment (hb_font_t *font,
+					    hb_codepoint_t glyph);
 
 HB_EXTERN hb_bool_t
-hb_ot_layout_is_math_extended_shape (hb_face_t *face,
-				     hb_codepoint_t glyph);
+hb_ot_math_is_glyph_extended_shape (hb_face_t *face,
+				    hb_codepoint_t glyph);
 
 HB_EXTERN hb_position_t
-hb_ot_layout_get_math_kerning (hb_font_t *font,
-			       hb_codepoint_t glyph,
-			       hb_ot_math_kern_t kern,
-			       hb_position_t correction_height);
+hb_ot_math_get_glyph_kerning (hb_font_t *font,
+			      hb_codepoint_t glyph,
+			      hb_ot_math_kern_t kern,
+			      hb_position_t correction_height);
 
 HB_EXTERN unsigned int
-hb_ot_layout_get_math_glyph_variants (hb_font_t *font,
-				      hb_codepoint_t glyph,
-				      hb_direction_t direction,
-				      unsigned int start_offset,
-				      unsigned int *variants_count, /* IN/OUT */
-				      hb_math_glyph_variant_t *variants /* OUT */);
+hb_ot_math_get_glyph_variants (hb_font_t *font,
+			       hb_codepoint_t glyph,
+			       hb_direction_t direction,
+			       unsigned int start_offset,
+			       unsigned int *variants_count, /* IN/OUT */
+			       hb_math_glyph_variant_t *variants /* OUT */);
 
 HB_EXTERN hb_position_t
-hb_ot_layout_get_math_min_connector_overlap (hb_font_t *font,
-					     hb_direction_t direction);
+hb_ot_math_get_min_connector_overlap (hb_font_t *font,
+				      hb_direction_t direction);
 
 HB_EXTERN unsigned int
-hb_ot_layout_get_math_glyph_assembly (hb_font_t *font,
-				      hb_codepoint_t glyph,
-				      hb_direction_t direction,
-				      unsigned int start_offset,
-				      unsigned int *parts_count, /* IN/OUT */
-				      hb_math_glyph_part_t *parts, /* OUT */
-				      hb_position_t *italics_correction /* OUT */);
+hb_ot_math_get_glyph_assembly (hb_font_t *font,
+			       hb_codepoint_t glyph,
+			       hb_direction_t direction,
+			       unsigned int start_offset,
+			       unsigned int *parts_count, /* IN/OUT */
+			       hb_math_glyph_part_t *parts, /* OUT */
+			       hb_position_t *italics_correction /* OUT */);
 
 
 HB_END_DECLS
diff --git a/test/api/Makefile.am b/test/api/Makefile.am
index 27520ff..58f4914 100644
--- a/test/api/Makefile.am
+++ b/test/api/Makefile.am
@@ -50,10 +50,10 @@ TEST_PROGS += \
 
 if HAVE_FREETYPE
 TEST_PROGS += \
-	test-ot-layout-math \
+	test-ot-math \
 	$(NULL)
-test_ot_layout_math_LDADD = $(LDADD) $(FREETYPE_LIBS)
-test_ot_layout_math_CPPFLAGS = $(AM_CPPFLAGS) $(FREETYPE_CFLAGS)
+test_ot_math_LDADD = $(LDADD) $(FREETYPE_LIBS)
+test_ot_math_CPPFLAGS = $(AM_CPPFLAGS) $(FREETYPE_CFLAGS)
 endif # HAVE_FREETYPE
 
 endif # HAVE_OT
diff --git a/test/api/test-ot-layout-math.c b/test/api/test-ot-layout-math.c
deleted file mode 100644
index 34ed0fc..0000000
--- a/test/api/test-ot-layout-math.c
+++ /dev/null
@@ -1,382 +0,0 @@
-/*
- * Copyright © 2016  Igalia S.L.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Igalia Author(s): Frédéric Wang
- */
-
-
-#include "hb-test.h"
-
-#include "hb-ft.h"
-#include "hb-ot.h"
-
-/* Unit tests for hb-ot-layout.h - OpenType MATH table  */
-
-static FT_Library ft_library;
-static FT_Face ft_face;
-static hb_font_t *hb_font;
-static hb_face_t *hb_face;
-
-static inline void
-initFreeType (void)
-{
-  FT_Error ft_error;
-  if ((ft_error = FT_Init_FreeType (&ft_library)))
-    abort();
-}
-
-static inline void
-cleanupFreeType (void)
-{
-  FT_Done_FreeType (ft_library);
-}
-
-static void
-openFont(const char* fontFile)
-{
-  gchar* path = g_test_build_filename(G_TEST_DIST, fontFile, NULL);
-
-  FT_Error ft_error;
-  if ((ft_error = FT_New_Face (ft_library, path, 0, &ft_face))) {
-    g_free(path);
-    abort();
-  }
-  g_free(path);
-
-#define fontSize 1000
-  if ((ft_error = FT_Set_Char_Size (ft_face, fontSize, fontSize, 0, 0)))
-    abort();
-  hb_font = hb_ft_font_create (ft_face, NULL);
-  hb_face = hb_ft_face_create_cached(ft_face);
-}
-
-static inline void
-closeFont (void)
-{
-  hb_font_destroy (hb_font);
-  FT_Done_Face (ft_face);
-}
-
-static void
-test_has_math_data (void)
-{
-  initFreeType();
-
-  openFont("fonts/MathTestFontNone.otf");
-  g_assert(!hb_ot_layout_has_math_data (hb_face)); // MATH table not available
-  closeFont();
-
-  openFont("fonts/MathTestFontEmpty.otf");
-  g_assert(hb_ot_layout_has_math_data (hb_face)); // MATH table available
-  closeFont();
-
-  cleanupFreeType();
-}
-
-static void
-test_get_math_constant (void)
-{
-  initFreeType();
-
-  openFont("fonts/MathTestFontEmpty.otf");
-  g_assert_cmpint(hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT), ==, 0); // MathConstants not available
-  closeFont();
-
-  openFont("fonts/MathTestFontFull.otf");
-  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT)), ==, 100);
-  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_DISPLAY_OPERATOR_MIN_HEIGHT)), ==, 200);
-  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_MATH_LEADING)), ==, 300);
-  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_AXIS_HEIGHT)), ==, 400);
-  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_ACCENT_BASE_HEIGHT)), ==, 500);
-  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_FLATTENED_ACCENT_BASE_HEIGHT)), ==, 600);
-  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_SUBSCRIPT_SHIFT_DOWN)), ==, 700);
-  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_SUBSCRIPT_TOP_MAX)), ==, 800);
-  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_SUBSCRIPT_BASELINE_DROP_MIN)), ==, 900);
-  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_SUPERSCRIPT_SHIFT_UP)), ==, 1100);
-  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_SUPERSCRIPT_SHIFT_UP_CRAMPED)), ==, 1200);
-  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_SUPERSCRIPT_BOTTOM_MIN)), ==, 1300);
-  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_SUPERSCRIPT_BASELINE_DROP_MAX)), ==, 1400);
-  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_SUB_SUPERSCRIPT_GAP_MIN)), ==, 1500);
-  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_SUPERSCRIPT_BOTTOM_MAX_WITH_SUBSCRIPT)), ==, 1600);
-  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_SPACE_AFTER_SCRIPT)), ==, 1700);
-  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_UPPER_LIMIT_GAP_MIN)), ==, 1800);
-  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_UPPER_LIMIT_BASELINE_RISE_MIN)), ==, 1900);
-  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_LOWER_LIMIT_GAP_MIN)), ==, 2200);
-  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_LOWER_LIMIT_BASELINE_DROP_MIN)), ==, 2300);
-  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_STACK_TOP_SHIFT_UP)), ==, 2400);
-  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_STACK_TOP_DISPLAY_STYLE_SHIFT_UP)), ==, 2500);
-  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_STACK_BOTTOM_SHIFT_DOWN)), ==, 2600);
-  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_STACK_BOTTOM_DISPLAY_STYLE_SHIFT_DOWN)), ==, 2700);
-  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_STACK_GAP_MIN)), ==, 2800);
-  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_STACK_DISPLAY_STYLE_GAP_MIN)), ==, 2900);
-  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_STRETCH_STACK_TOP_SHIFT_UP)), ==, 3000);
-  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_STRETCH_STACK_BOTTOM_SHIFT_DOWN)), ==, 3100);
-  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_STRETCH_STACK_GAP_ABOVE_MIN)), ==, 3200);
-  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_STRETCH_STACK_GAP_BELOW_MIN)), ==, 3300);
-  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_SHIFT_UP)), ==, 3400);
-  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_DISPLAY_STYLE_SHIFT_UP)), ==, 3500);
-  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_SHIFT_DOWN)), ==, 3600);
-  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_DISPLAY_STYLE_SHIFT_DOWN)), ==, 3700);
-  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_GAP_MIN)), ==, 3800);
-  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_NUM_DISPLAY_STYLE_GAP_MIN)), ==, 3900);
-  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_RULE_THICKNESS)), ==, 4000);
-  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_GAP_MIN)), ==, 4100);
-  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_DENOM_DISPLAY_STYLE_GAP_MIN)), ==, 4200);
-  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_SKEWED_FRACTION_HORIZONTAL_GAP)), ==, 4300);
-  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_SKEWED_FRACTION_VERTICAL_GAP)), ==, 4400);
-  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_OVERBAR_VERTICAL_GAP)), ==, 4500);
-  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_OVERBAR_RULE_THICKNESS)), ==, 4600);
-  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_OVERBAR_EXTRA_ASCENDER)), ==, 4700);
-  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_UNDERBAR_VERTICAL_GAP)), ==, 4800);
-  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_UNDERBAR_RULE_THICKNESS)), ==, 4900);
-  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_UNDERBAR_EXTRA_DESCENDER)), ==, 5000);
-  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_VERTICAL_GAP)), ==, 5100);
-  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_DISPLAY_STYLE_VERTICAL_GAP)), ==, 5200);
-  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_RULE_THICKNESS)), ==, 5300);
-  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_EXTRA_ASCENDER)), ==, 5400);
-  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_KERN_BEFORE_DEGREE)), ==, 5500);
-  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_KERN_AFTER_DEGREE)), ==, 5600);
-  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN)), ==, 87);
-  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN)), ==, 76);
-  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_DEGREE_BOTTOM_RAISE_PERCENT)), ==, 65);
-  closeFont();
-
-  cleanupFreeType();
-}
-
-static void
-test_get_math_italics_correction (void)
-{
-  hb_codepoint_t glyph;
-  initFreeType();
-
-  openFont("fonts/MathTestFontEmpty.otf");
-  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
-  g_assert_cmpint(hb_ot_layout_get_math_italics_correction (hb_font, glyph), ==, 0); // MathGlyphInfo not available
-  closeFont();
-
-  openFont("fonts/MathTestFontPartial1.otf");
-  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
-  g_assert_cmpint(hb_ot_layout_get_math_italics_correction (hb_font, glyph), ==, 0); // MathGlyphInfo empty
-  closeFont();
-
-  openFont("fonts/MathTestFontPartial2.otf");
-  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
-  g_assert_cmpint(hb_ot_layout_get_math_italics_correction (hb_font, glyph), ==, 0); // MathItalicsCorrectionInfo empty
-  closeFont();
-
-  openFont("fonts/MathTestFontFull.otf");
-  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
-  g_assert_cmpint(hb_ot_layout_get_math_italics_correction (hb_font, glyph), ==, 0); // Glyph without italic correction.
-  g_assert(hb_font_get_glyph_from_name (hb_font, "A", -1, &glyph));
-  g_assert_cmpint(hb_ot_layout_get_math_italics_correction (hb_font, glyph), ==, 197);
-  g_assert(hb_font_get_glyph_from_name (hb_font, "B", -1, &glyph));
-  g_assert_cmpint(hb_ot_layout_get_math_italics_correction (hb_font, glyph), ==, 150);
-  g_assert(hb_font_get_glyph_from_name (hb_font, "C", -1, &glyph));
-  g_assert_cmpint(hb_ot_layout_get_math_italics_correction (hb_font, glyph), ==, 452);
-  closeFont();
-
-  cleanupFreeType();
-
-}
-
-static void
-test_get_math_top_accent_attachment (void)
-{
-  hb_codepoint_t glyph;
-  initFreeType();
-
-  openFont("fonts/MathTestFontEmpty.otf");
-  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
-  g_assert_cmpint(hb_ot_layout_get_math_top_accent_attachment (hb_font, glyph), ==, 500); // MathGlyphInfo not available
-  closeFont();
-
-  openFont("fonts/MathTestFontPartial1.otf");
-  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
-  g_assert_cmpint(hb_ot_layout_get_math_top_accent_attachment (hb_font, glyph), ==, 500); // MathGlyphInfo empty
-  closeFont();
-
-  openFont("fonts/MathTestFontPartial2.otf");
-  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
-  g_assert_cmpint(hb_ot_layout_get_math_top_accent_attachment (hb_font, glyph), ==, 500); // MathTopAccentAttachment empty
-  closeFont();
-
-  openFont("fonts/MathTestFontFull.otf");
-  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
-  g_assert_cmpint(hb_ot_layout_get_math_top_accent_attachment (hb_font, glyph), ==, 500); // Glyph without top accent attachment.
-  g_assert(hb_font_get_glyph_from_name (hb_font, "D", -1, &glyph));
-  g_assert_cmpint(hb_ot_layout_get_math_top_accent_attachment (hb_font, glyph), ==, 374);
-  g_assert(hb_font_get_glyph_from_name (hb_font, "E", -1, &glyph));
-  g_assert_cmpint(hb_ot_layout_get_math_top_accent_attachment (hb_font, glyph), ==, 346);
-  g_assert(hb_font_get_glyph_from_name (hb_font, "F", -1, &glyph));
-  g_assert_cmpint(hb_ot_layout_get_math_top_accent_attachment (hb_font, glyph), ==, 318);
-  closeFont();
-
-  cleanupFreeType();
-}
-
-static void
-test_is_math_extended_shape (void)
-{
-  hb_codepoint_t glyph;
-  initFreeType();
-
-  openFont("fonts/MathTestFontEmpty.otf");
-  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
-  g_assert(!hb_ot_layout_is_math_extended_shape (hb_face, glyph)); // MathGlyphInfo not available
-  closeFont();
-
-  openFont("fonts/MathTestFontPartial1.otf");
-  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
-  g_assert(!hb_ot_layout_is_math_extended_shape (hb_face, glyph)); // MathGlyphInfo empty
-  closeFont();
-
-  openFont("fonts/MathTestFontFull.otf");
-  g_assert(hb_font_get_glyph_from_name (hb_font, "G", -1, &glyph));
-  g_assert(!hb_ot_layout_is_math_extended_shape (hb_face, glyph));
-  g_assert(hb_font_get_glyph_from_name (hb_font, "H", -1, &glyph));
-  g_assert(hb_ot_layout_is_math_extended_shape (hb_face, glyph));
-  closeFont();
-
-  cleanupFreeType();
-}
-
-static void
-test_get_math_kerning (void)
-{
-  hb_codepoint_t glyph;
-  initFreeType();
-
-  openFont("fonts/MathTestFontEmpty.otf");
-  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
-  g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 0), ==, 0); // MathGlyphInfo not available
-  g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_LEFT, 0), ==, 0); // MathGlyphInfo not available
-  g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_RIGHT, 0), ==, 0); // MathGlyphInfo not available
-  g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_LEFT, 0), ==, 0); // MathGlyphInfo not available
-  closeFont();
-
-  openFont("fonts/MathTestFontPartial2.otf");
-  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
-  g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 0), ==, 0); // MathKernInfo empty
-  g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_LEFT, 0), ==, 0); // MathKernInfo empty
-  g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_RIGHT, 0), ==, 0); // MathKernInfo empty
-  g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_LEFT, 0), ==, 0); // MathKernInfo empty
-  closeFont();
-
-  openFont("fonts/MathTestFontPartial3.otf");
-  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
-  g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 0), ==, 0); // MathKernInfoRecords empty
-  g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_LEFT, 0), ==, 0); // MathKernInfoRecords empty
-  g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_RIGHT, 0), ==, 0); // MathKernInfoRecords empty
-  g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_LEFT, 0), ==, 0); // MathKernInfoRecords empty
-  closeFont();
-
-  openFont("fonts/MathTestFontFull.otf");
-  g_assert(hb_font_get_glyph_from_name (hb_font, "I", -1, &glyph));
-
-  g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 7), ==, 31); // lower than min heigth
-  g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 14), ==, 31); // equal to min height
-  g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 20), ==, 52);
-  g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 23), ==, 52);
-  g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 31), ==, 73);
-  g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 32), ==, 73);
-  g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 86), ==, 199); // equal to max height
-  g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 91), ==, 220); // larger than max height
-  g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 96), ==, 220); // larger than max height
-
-  g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 39), ==, 94); // top right
-  g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_LEFT, 39), ==, 55); // top left
-  g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_RIGHT, 39), ==, 22); // bottom right
-  g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_LEFT, 39), ==, 50); // bottom left
-
-  closeFont();
-
-  cleanupFreeType();
-}
-
-
-#if 0
-static void
-test_get_math_italic_correction_for_glyph_assembly (void)
-{
-  hb_codepoint_t glyph;
-  initFreeType();
-
-  openFont("fonts/MathTestFontEmpty.otf");
-  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
-  g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, TRUE), ==, 0); // MathVariants not available
-  g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, FALSE), ==, 0); // MathVariants not available
-  closeFont();
-
-  openFont("fonts/MathTestFontPartial1.otf");
-  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
-  g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, TRUE), ==, 0); // VertGlyphCoverage and HorizGlyphCoverage absent
-  g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, FALSE), ==, 0); // VertGlyphCoverage and HorizGlyphCoverage absent
-  closeFont();
-
-  openFont("fonts/MathTestFontPartial2.otf");
-  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
-  g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, TRUE), ==, 0); // VertGlyphCoverage and HorizGlyphCoverage empty
-  g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, FALSE), ==, 0); // VertGlyphCoverage and HorizGlyphCoverage empty
-  closeFont();
-
-  openFont("fonts/MathTestFontPartial3.otf");
-  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
-  g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, TRUE), ==, 0); // HorizGlyphConstruction and VertGlyphConstruction empty
-  g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, FALSE), ==, 0);  // HorizGlyphConstruction and VertGlyphConstruction empty
-  closeFont();
-
-  openFont("fonts/MathTestFontPartial4.otf");
-  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
-  g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, TRUE), ==, 0);
-  g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, FALSE), ==, 0);
-  closeFont();
-
-  openFont("fonts/MathTestFontFull.otf");
-  g_assert(hb_font_get_glyph_from_name (hb_font, "arrowleft", -1, &glyph));
-  g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, TRUE), ==, 124);
-  g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, FALSE), ==, 0);
-  g_assert(hb_font_get_glyph_from_name (hb_font, "arrowup", -1, &glyph));
-  g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, TRUE), ==, 0);
-  g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, FALSE), ==, 331);
-  closeFont();
-
-  cleanupFreeType();
-}
-#endif
-
-int
-main (int argc, char **argv)
-{
-  hb_test_init (&argc, &argv);
-
-  hb_test_add (test_has_math_data);
-  hb_test_add (test_get_math_constant);
-  hb_test_add (test_get_math_italics_correction);
-  hb_test_add (test_get_math_top_accent_attachment);
-  hb_test_add (test_is_math_extended_shape);
-  hb_test_add (test_get_math_kerning);
-  //hb_test_add (test_get_math_italic_correction_for_glyph_assembly);
-
-  return hb_test_run();
-}
diff --git a/test/api/test-ot-math.c b/test/api/test-ot-math.c
new file mode 100644
index 0000000..23c19ef
--- /dev/null
+++ b/test/api/test-ot-math.c
@@ -0,0 +1,381 @@
+/*
+ * Copyright © 2016  Igalia S.L.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Igalia Author(s): Frédéric Wang
+ */
+
+
+#include "hb-test.h"
+
+#include "hb-ft.h"
+#include "hb-ot.h"
+
+/* Unit tests for hb-ot-math.h - OpenType MATH table  */
+
+static FT_Library ft_library;
+static FT_Face ft_face;
+static hb_font_t *hb_font;
+static hb_face_t *hb_face;
+
+static inline void
+initFreeType (void)
+{
+  FT_Error ft_error;
+  if ((ft_error = FT_Init_FreeType (&ft_library)))
+    abort();
+}
+
+static inline void
+cleanupFreeType (void)
+{
+  FT_Done_FreeType (ft_library);
+}
+
+static void
+openFont(const char* fontFile)
+{
+  gchar* path = g_test_build_filename(G_TEST_DIST, fontFile, NULL);
+
+  FT_Error ft_error;
+  if ((ft_error = FT_New_Face (ft_library, path, 0, &ft_face))) {
+    g_free(path);
+    abort();
+  }
+  g_free(path);
+
+#define fontSize 1000
+  if ((ft_error = FT_Set_Char_Size (ft_face, fontSize, fontSize, 0, 0)))
+    abort();
+  hb_font = hb_ft_font_create (ft_face, NULL);
+  hb_face = hb_ft_face_create_cached(ft_face);
+}
+
+static inline void
+closeFont (void)
+{
+  hb_font_destroy (hb_font);
+  FT_Done_Face (ft_face);
+}
+
+static void
+test_has_data (void)
+{
+  initFreeType();
+
+  openFont("fonts/MathTestFontNone.otf");
+  g_assert(!hb_ot_math_has_data (hb_face)); // MATH table not available
+  closeFont();
+
+  openFont("fonts/MathTestFontEmpty.otf");
+  g_assert(hb_ot_math_has_data (hb_face)); // MATH table available
+  closeFont();
+
+  cleanupFreeType();
+}
+
+static void
+test_get_constant (void)
+{
+  initFreeType();
+
+  openFont("fonts/MathTestFontEmpty.otf");
+  g_assert_cmpint(hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT), ==, 0); // MathConstants not available
+  closeFont();
+
+  openFont("fonts/MathTestFontFull.otf");
+  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT)), ==, 100);
+  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_DISPLAY_OPERATOR_MIN_HEIGHT)), ==, 200);
+  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_MATH_LEADING)), ==, 300);
+  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_AXIS_HEIGHT)), ==, 400);
+  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_ACCENT_BASE_HEIGHT)), ==, 500);
+  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FLATTENED_ACCENT_BASE_HEIGHT)), ==, 600);
+  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SUBSCRIPT_SHIFT_DOWN)), ==, 700);
+  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SUBSCRIPT_TOP_MAX)), ==, 800);
+  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SUBSCRIPT_BASELINE_DROP_MIN)), ==, 900);
+  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SUPERSCRIPT_SHIFT_UP)), ==, 1100);
+  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SUPERSCRIPT_SHIFT_UP_CRAMPED)), ==, 1200);
+  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SUPERSCRIPT_BOTTOM_MIN)), ==, 1300);
+  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SUPERSCRIPT_BASELINE_DROP_MAX)), ==, 1400);
+  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SUB_SUPERSCRIPT_GAP_MIN)), ==, 1500);
+  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SUPERSCRIPT_BOTTOM_MAX_WITH_SUBSCRIPT)), ==, 1600);
+  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SPACE_AFTER_SCRIPT)), ==, 1700);
+  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_UPPER_LIMIT_GAP_MIN)), ==, 1800);
+  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_UPPER_LIMIT_BASELINE_RISE_MIN)), ==, 1900);
+  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_LOWER_LIMIT_GAP_MIN)), ==, 2200);
+  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_LOWER_LIMIT_BASELINE_DROP_MIN)), ==, 2300);
+  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_STACK_TOP_SHIFT_UP)), ==, 2400);
+  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_STACK_TOP_DISPLAY_STYLE_SHIFT_UP)), ==, 2500);
+  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_STACK_BOTTOM_SHIFT_DOWN)), ==, 2600);
+  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_STACK_BOTTOM_DISPLAY_STYLE_SHIFT_DOWN)), ==, 2700);
+  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_STACK_GAP_MIN)), ==, 2800);
+  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_STACK_DISPLAY_STYLE_GAP_MIN)), ==, 2900);
+  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_STRETCH_STACK_TOP_SHIFT_UP)), ==, 3000);
+  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_STRETCH_STACK_BOTTOM_SHIFT_DOWN)), ==, 3100);
+  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_STRETCH_STACK_GAP_ABOVE_MIN)), ==, 3200);
+  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_STRETCH_STACK_GAP_BELOW_MIN)), ==, 3300);
+  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_SHIFT_UP)), ==, 3400);
+  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_DISPLAY_STYLE_SHIFT_UP)), ==, 3500);
+  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_SHIFT_DOWN)), ==, 3600);
+  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_DISPLAY_STYLE_SHIFT_DOWN)), ==, 3700);
+  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_GAP_MIN)), ==, 3800);
+  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_NUM_DISPLAY_STYLE_GAP_MIN)), ==, 3900);
+  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_RULE_THICKNESS)), ==, 4000);
+  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_GAP_MIN)), ==, 4100);
+  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_DENOM_DISPLAY_STYLE_GAP_MIN)), ==, 4200);
+  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SKEWED_FRACTION_HORIZONTAL_GAP)), ==, 4300);
+  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SKEWED_FRACTION_VERTICAL_GAP)), ==, 4400);
+  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_OVERBAR_VERTICAL_GAP)), ==, 4500);
+  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_OVERBAR_RULE_THICKNESS)), ==, 4600);
+  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_OVERBAR_EXTRA_ASCENDER)), ==, 4700);
+  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_UNDERBAR_VERTICAL_GAP)), ==, 4800);
+  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_UNDERBAR_RULE_THICKNESS)), ==, 4900);
+  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_UNDERBAR_EXTRA_DESCENDER)), ==, 5000);
+  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_VERTICAL_GAP)), ==, 5100);
+  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_DISPLAY_STYLE_VERTICAL_GAP)), ==, 5200);
+  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_RULE_THICKNESS)), ==, 5300);
+  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_EXTRA_ASCENDER)), ==, 5400);
+  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_KERN_BEFORE_DEGREE)), ==, 5500);
+  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_KERN_AFTER_DEGREE)), ==, 5600);
+  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN)), ==, 87);
+  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN)), ==, 76);
+  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_DEGREE_BOTTOM_RAISE_PERCENT)), ==, 65);
+  closeFont();
+
+  cleanupFreeType();
+}
+
+static void
+test_get_glyph_italics_correction (void)
+{
+  hb_codepoint_t glyph;
+  initFreeType();
+
+  openFont("fonts/MathTestFontEmpty.otf");
+  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
+  g_assert_cmpint(hb_ot_math_get_glyph_italics_correction (hb_font, glyph), ==, 0); // MathGlyphInfo not available
+  closeFont();
+
+  openFont("fonts/MathTestFontPartial1.otf");
+  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
+  g_assert_cmpint(hb_ot_math_get_glyph_italics_correction (hb_font, glyph), ==, 0); // MathGlyphInfo empty
+  closeFont();
+
+  openFont("fonts/MathTestFontPartial2.otf");
+  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
+  g_assert_cmpint(hb_ot_math_get_glyph_italics_correction (hb_font, glyph), ==, 0); // MathItalicsCorrectionInfo empty
+  closeFont();
+
+  openFont("fonts/MathTestFontFull.otf");
+  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
+  g_assert_cmpint(hb_ot_math_get_glyph_italics_correction (hb_font, glyph), ==, 0); // Glyph without italic correction.
+  g_assert(hb_font_get_glyph_from_name (hb_font, "A", -1, &glyph));
+  g_assert_cmpint(hb_ot_math_get_glyph_italics_correction (hb_font, glyph), ==, 197);
+  g_assert(hb_font_get_glyph_from_name (hb_font, "B", -1, &glyph));
+  g_assert_cmpint(hb_ot_math_get_glyph_italics_correction (hb_font, glyph), ==, 150);
+  g_assert(hb_font_get_glyph_from_name (hb_font, "C", -1, &glyph));
+  g_assert_cmpint(hb_ot_math_get_glyph_italics_correction (hb_font, glyph), ==, 452);
+  closeFont();
+
+  cleanupFreeType();
+}
+
+static void
+test_get_glyph_top_accent_attachment (void)
+{
+  hb_codepoint_t glyph;
+  initFreeType();
+
+  openFont("fonts/MathTestFontEmpty.otf");
+  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
+  g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 500); // MathGlyphInfo not available
+  closeFont();
+
+  openFont("fonts/MathTestFontPartial1.otf");
+  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
+  g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 500); // MathGlyphInfo empty
+  closeFont();
+
+  openFont("fonts/MathTestFontPartial2.otf");
+  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
+  g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 500); // MathTopAccentAttachment empty
+  closeFont();
+
+  openFont("fonts/MathTestFontFull.otf");
+  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
+  g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 500); // Glyph without top accent attachment.
+  g_assert(hb_font_get_glyph_from_name (hb_font, "D", -1, &glyph));
+  g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 374);
+  g_assert(hb_font_get_glyph_from_name (hb_font, "E", -1, &glyph));
+  g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 346);
+  g_assert(hb_font_get_glyph_from_name (hb_font, "F", -1, &glyph));
+  g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 318);
+  closeFont();
+
+  cleanupFreeType();
+}
+
+static void
+test_is_glyph_extended_shape (void)
+{
+  hb_codepoint_t glyph;
+  initFreeType();
+
+  openFont("fonts/MathTestFontEmpty.otf");
+  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
+  g_assert(!hb_ot_math_is_glyph_extended_shape (hb_face, glyph)); // MathGlyphInfo not available
+  closeFont();
+
+  openFont("fonts/MathTestFontPartial1.otf");
+  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
+  g_assert(!hb_ot_math_is_glyph_extended_shape (hb_face, glyph)); // MathGlyphInfo empty
+  closeFont();
+
+  openFont("fonts/MathTestFontFull.otf");
+  g_assert(hb_font_get_glyph_from_name (hb_font, "G", -1, &glyph));
+  g_assert(!hb_ot_math_is_glyph_extended_shape (hb_face, glyph));
+  g_assert(hb_font_get_glyph_from_name (hb_font, "H", -1, &glyph));
+  g_assert(hb_ot_math_is_glyph_extended_shape (hb_face, glyph));
+  closeFont();
+
+  cleanupFreeType();
+}
+
+static void
+test_get_glyph_kerning (void)
+{
+  hb_codepoint_t glyph;
+  initFreeType();
+
+  openFont("fonts/MathTestFontEmpty.otf");
+  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
+  g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 0), ==, 0); // MathGlyphInfo not available
+  g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_LEFT, 0), ==, 0); // MathGlyphInfo not available
+  g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_RIGHT, 0), ==, 0); // MathGlyphInfo not available
+  g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_LEFT, 0), ==, 0); // MathGlyphInfo not available
+  closeFont();
+
+  openFont("fonts/MathTestFontPartial2.otf");
+  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
+  g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 0), ==, 0); // MathKernInfo empty
+  g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_LEFT, 0), ==, 0); // MathKernInfo empty
+  g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_RIGHT, 0), ==, 0); // MathKernInfo empty
+  g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_LEFT, 0), ==, 0); // MathKernInfo empty
+  closeFont();
+
+  openFont("fonts/MathTestFontPartial3.otf");
+  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
+  g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 0), ==, 0); // MathKernInfoRecords empty
+  g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_LEFT, 0), ==, 0); // MathKernInfoRecords empty
+  g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_RIGHT, 0), ==, 0); // MathKernInfoRecords empty
+  g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_LEFT, 0), ==, 0); // MathKernInfoRecords empty
+  closeFont();
+
+  openFont("fonts/MathTestFontFull.otf");
+  g_assert(hb_font_get_glyph_from_name (hb_font, "I", -1, &glyph));
+
+  g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 7), ==, 31); // lower than min heigth
+  g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 14), ==, 31); // equal to min height
+  g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 20), ==, 52);
+  g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 23), ==, 52);
+  g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 31), ==, 73);
+  g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 32), ==, 73);
+  g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 86), ==, 199); // equal to max height
+  g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 91), ==, 220); // larger than max height
+  g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 96), ==, 220); // larger than max height
+
+  g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 39), ==, 94); // top right
+  g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_LEFT, 39), ==, 55); // top left
+  g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_RIGHT, 39), ==, 22); // bottom right
+  g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_LEFT, 39), ==, 50); // bottom left
+
+  closeFont();
+
+  cleanupFreeType();
+}
+
+
+#if 0
+static void
+test_get_math_italic_correction_for_glyph_assembly (void)
+{
+  hb_codepoint_t glyph;
+  initFreeType();
+
+  openFont("fonts/MathTestFontEmpty.otf");
+  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
+  g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, TRUE), ==, 0); // MathVariants not available
+  g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, FALSE), ==, 0); // MathVariants not available
+  closeFont();
+
+  openFont("fonts/MathTestFontPartial1.otf");
+  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
+  g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, TRUE), ==, 0); // VertGlyphCoverage and HorizGlyphCoverage absent
+  g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, FALSE), ==, 0); // VertGlyphCoverage and HorizGlyphCoverage absent
+  closeFont();
+
+  openFont("fonts/MathTestFontPartial2.otf");
+  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
+  g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, TRUE), ==, 0); // VertGlyphCoverage and HorizGlyphCoverage empty
+  g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, FALSE), ==, 0); // VertGlyphCoverage and HorizGlyphCoverage empty
+  closeFont();
+
+  openFont("fonts/MathTestFontPartial3.otf");
+  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
+  g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, TRUE), ==, 0); // HorizGlyphConstruction and VertGlyphConstruction empty
+  g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, FALSE), ==, 0);  // HorizGlyphConstruction and VertGlyphConstruction empty
+  closeFont();
+
+  openFont("fonts/MathTestFontPartial4.otf");
+  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
+  g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, TRUE), ==, 0);
+  g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, FALSE), ==, 0);
+  closeFont();
+
+  openFont("fonts/MathTestFontFull.otf");
+  g_assert(hb_font_get_glyph_from_name (hb_font, "arrowleft", -1, &glyph));
+  g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, TRUE), ==, 124);
+  g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, FALSE), ==, 0);
+  g_assert(hb_font_get_glyph_from_name (hb_font, "arrowup", -1, &glyph));
+  g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, TRUE), ==, 0);
+  g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, FALSE), ==, 331);
+  closeFont();
+
+  cleanupFreeType();
+}
+#endif
+
+int
+main (int argc, char **argv)
+{
+  hb_test_init (&argc, &argv);
+
+  hb_test_add (test_has_data);
+  hb_test_add (test_get_constant);
+  hb_test_add (test_get_glyph_italics_correction);
+  hb_test_add (test_get_glyph_top_accent_attachment);
+  hb_test_add (test_is_glyph_extended_shape);
+  hb_test_add (test_get_glyph_kerning);
+  //hb_test_add (test_get_math_italic_correction_for_glyph_assembly);
+
+  return hb_test_run();
+}
commit 1ba767cd4e3606beb9dc59806b83b1e61f5958d4
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Sep 26 21:57:14 2016 +0200

    [MATH] Move API from hb-ot-layout.h to hb-ot-math.h

diff --git a/src/hb-ot-layout.h b/src/hb-ot-layout.h
index b6fbd00..eb23d45 100644
--- a/src/hb-ot-layout.h
+++ b/src/hb-ot-layout.h
@@ -33,7 +33,6 @@
 
 #include "hb.h"
 
-#include "hb-ot-math.h"
 #include "hb-ot-tag.h"
 
 HB_BEGIN_DECLS
@@ -43,7 +42,6 @@ HB_BEGIN_DECLS
 #define HB_OT_TAG_GSUB HB_TAG('G','S','U','B')
 #define HB_OT_TAG_GPOS HB_TAG('G','P','O','S')
 #define HB_OT_TAG_JSTF HB_TAG('J','S','T','F')
-#define HB_OT_TAG_MATH HB_TAG('M','A','T','H')
 
 
 /*
@@ -299,56 +297,6 @@ hb_ot_layout_get_size_params (hb_face_t    *face,
 			      unsigned int *range_end          /* OUT.  May be NULL */);
 
 
-/*
- * MATH
- */
-
-HB_EXTERN hb_bool_t
-hb_ot_layout_has_math_data (hb_face_t *face);
-
-HB_EXTERN hb_position_t
-hb_ot_layout_get_math_constant (hb_font_t *font,
-				hb_ot_math_constant_t constant);
-
-HB_EXTERN hb_position_t
-hb_ot_layout_get_math_italics_correction (hb_font_t *font,
-					  hb_codepoint_t glyph);
-
-HB_EXTERN hb_position_t
-hb_ot_layout_get_math_top_accent_attachment (hb_font_t *font,
-					     hb_codepoint_t glyph);
-
-HB_EXTERN hb_bool_t
-hb_ot_layout_is_math_extended_shape (hb_face_t *face,
-				     hb_codepoint_t glyph);
-
-HB_EXTERN hb_position_t
-hb_ot_layout_get_math_kerning (hb_font_t *font,
-			       hb_codepoint_t glyph,
-			       hb_ot_math_kern_t kern,
-			       hb_position_t correction_height);
-
-HB_EXTERN unsigned int
-hb_ot_layout_get_math_glyph_variants (hb_font_t *font,
-				      hb_codepoint_t glyph,
-				      hb_direction_t direction,
-				      unsigned int start_offset,
-				      unsigned int *variants_count, /* IN/OUT */
-				      hb_math_glyph_variant_t *variants /* OUT */);
-
-HB_EXTERN hb_position_t
-hb_ot_layout_get_math_min_connector_overlap (hb_font_t *font,
-					     hb_direction_t direction);
-
-HB_EXTERN unsigned int
-hb_ot_layout_get_math_glyph_assembly (hb_font_t *font,
-				      hb_codepoint_t glyph,
-				      hb_direction_t direction,
-				      unsigned int start_offset,
-				      unsigned int *parts_count, /* IN/OUT */
-				      hb_math_glyph_part_t *parts, /* OUT */
-				      hb_position_t *italics_correction /* OUT */);
-
 HB_END_DECLS
 
 #endif /* HB_OT_LAYOUT_H */
diff --git a/src/hb-ot-math.h b/src/hb-ot-math.h
index bf37975..5ff19fd 100644
--- a/src/hb-ot-math.h
+++ b/src/hb-ot-math.h
@@ -36,6 +36,14 @@
 HB_BEGIN_DECLS
 
 
+/*
+ * MATH
+ */
+
+#define HB_OT_TAG_MATH HB_TAG('M','A','T','H')
+
+/* Types */
+
 typedef enum {
   HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN = 0,
   HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN = 1,
@@ -119,6 +127,54 @@ typedef struct hb_math_glyph_part_t {
   hb_math_glyph_part_flags_t flags;
 } hb_math_glyph_part_t;
 
+/* Methods */
+
+HB_EXTERN hb_bool_t
+hb_ot_layout_has_math_data (hb_face_t *face);
+
+HB_EXTERN hb_position_t
+hb_ot_layout_get_math_constant (hb_font_t *font,
+				hb_ot_math_constant_t constant);
+
+HB_EXTERN hb_position_t
+hb_ot_layout_get_math_italics_correction (hb_font_t *font,
+					  hb_codepoint_t glyph);
+
+HB_EXTERN hb_position_t
+hb_ot_layout_get_math_top_accent_attachment (hb_font_t *font,
+					     hb_codepoint_t glyph);
+
+HB_EXTERN hb_bool_t
+hb_ot_layout_is_math_extended_shape (hb_face_t *face,
+				     hb_codepoint_t glyph);
+
+HB_EXTERN hb_position_t
+hb_ot_layout_get_math_kerning (hb_font_t *font,
+			       hb_codepoint_t glyph,
+			       hb_ot_math_kern_t kern,
+			       hb_position_t correction_height);
+
+HB_EXTERN unsigned int
+hb_ot_layout_get_math_glyph_variants (hb_font_t *font,
+				      hb_codepoint_t glyph,
+				      hb_direction_t direction,
+				      unsigned int start_offset,
+				      unsigned int *variants_count, /* IN/OUT */
+				      hb_math_glyph_variant_t *variants /* OUT */);
+
+HB_EXTERN hb_position_t
+hb_ot_layout_get_math_min_connector_overlap (hb_font_t *font,
+					     hb_direction_t direction);
+
+HB_EXTERN unsigned int
+hb_ot_layout_get_math_glyph_assembly (hb_font_t *font,
+				      hb_codepoint_t glyph,
+				      hb_direction_t direction,
+				      unsigned int start_offset,
+				      unsigned int *parts_count, /* IN/OUT */
+				      hb_math_glyph_part_t *parts, /* OUT */
+				      hb_position_t *italics_correction /* OUT */);
+
 
 HB_END_DECLS
 
diff --git a/src/hb-ot.h b/src/hb-ot.h
index 47c92a5..113e37b 100644
--- a/src/hb-ot.h
+++ b/src/hb-ot.h
@@ -32,6 +32,7 @@
 
 #include "hb-ot-font.h"
 #include "hb-ot-layout.h"
+#include "hb-ot-math.h"
 #include "hb-ot-tag.h"
 #include "hb-ot-shape.h"
 
commit 97b72da6006d8d6355ee90d514f627e6604a4936
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Sep 26 21:53:25 2016 +0200

    Whitespace

diff --git a/src/hb-ot-layout-math-table.hh b/src/hb-ot-layout-math-table.hh
index 886ed2d..efffd2b 100644
--- a/src/hb-ot-layout-math-table.hh
+++ b/src/hb-ot-layout-math-table.hh
@@ -514,7 +514,7 @@ struct MathGlyphAssembly
 	    partRecords.sub_array (start_offset, parts_count);
       unsigned int count = *parts_count;
       for (unsigned int i = 0; i < count; i++)
-        arr[i].extract (parts[i], scale, font);
+	arr[i].extract (parts[i], scale, font);
     }
 
     if (italics_correction)
commit 559eb564472575ae4d87a241314b8a3ca24418c4
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Sep 26 21:46:05 2016 +0200

    [MATH] Wire up get_glyph_assembly()

diff --git a/src/hb-ot-layout-math-table.hh b/src/hb-ot-layout-math-table.hh
index da65c38..886ed2d 100644
--- a/src/hb-ot-layout-math-table.hh
+++ b/src/hb-ot-layout-math-table.hh
@@ -436,7 +436,9 @@ struct MathGlyphVariantRecord
 struct PartFlags : USHORT
 {
   enum Flags {
-    Extender = 0x0001u, /* If set, the part can be skipped or repeated. */
+    Extender	= 0x0001u, /* If set, the part can be skipped or repeated. */
+
+    Defined	= 0x0001u, /* All defined flags. */
   };
 
   public:
@@ -445,14 +447,30 @@ struct PartFlags : USHORT
 
 struct MathGlyphPartRecord
 {
-  friend struct MathGlyphAssembly;
-
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
   }
 
+  inline void extract (hb_math_glyph_part_t &out,
+		       int scale,
+		       hb_font_t *font) const
+  {
+    out.glyph			= glyph;
+
+    out.start_connector_length	= font->em_scale (startConnectorLength, scale);
+    out.end_connector_length	= font->em_scale (endConnectorLength, scale);
+    out.full_advance		= font->em_scale (fullAdvance, scale);
+
+    ASSERT_STATIC ((unsigned int) HB_MATH_GLYPH_PART_FLAG_EXTENDER ==
+		   (unsigned int) PartFlags::Extender);
+
+    out.flags = (hb_math_glyph_part_flags_t)
+		(unsigned int)
+		(partFlags & PartFlags::Defined);
+  }
+
   protected:
   GlyphID   glyph;		  /* Glyph ID for the part. */
   USHORT    startConnectorLength; /* Advance width/ height of the straight bar
@@ -482,8 +500,28 @@ struct MathGlyphAssembly
 		  partRecords.sanitize(c));
   }
 
-  inline hb_position_t get_italic_correction (hb_font_t *font) const
-  { return italicsCorrection.get_x_value(font, this); }
+  inline unsigned int get_parts (hb_direction_t direction,
+				 hb_font_t *font,
+				 unsigned int start_offset,
+				 unsigned int *parts_count, /* IN/OUT */
+				 hb_math_glyph_part_t *parts /* OUT */,
+				 hb_position_t *italics_correction /* OUT */) const
+  {
+    if (parts_count)
+    {
+      int scale = font->dir_scale (direction);
+      const MathGlyphPartRecord *arr =
+	    partRecords.sub_array (start_offset, parts_count);
+      unsigned int count = *parts_count;
+      for (unsigned int i = 0; i < count; i++)
+        arr[i].extract (parts[i], scale, font);
+    }
+
+    if (italics_correction)
+      *italics_correction = italicsCorrection.get_x_value (font, this);
+
+    return partRecords.len;
+  }
 
   protected:
   MathValueRecord	   italicsCorrection; /* Italics correction of this
@@ -507,6 +545,9 @@ struct MathGlyphConstruction
 		  mathGlyphVariantRecord.sanitize(c));
   }
 
+  inline const MathGlyphAssembly &get_assembly (void) const
+  { return this+glyphAssembly; }
+
   inline unsigned int get_variants (hb_direction_t direction,
 				    hb_font_t *font,
 				    unsigned int start_offset,
@@ -576,6 +617,19 @@ struct MathVariants
   { return get_glyph_construction (glyph, direction, font)
 	   .get_variants (direction, font, start_offset, variants_count, variants); }
 
+  inline unsigned int get_glyph_parts (hb_codepoint_t glyph,
+				       hb_direction_t direction,
+				       hb_font_t *font,
+				       unsigned int start_offset,
+				       unsigned int *parts_count, /* IN/OUT */
+				       hb_math_glyph_part_t *parts /* OUT */,
+				       hb_position_t *italics_correction /* OUT */) const
+  { return get_glyph_construction (glyph, direction, font)
+	   .get_assembly ()
+	   .get_parts (direction, font,
+		       start_offset, parts_count, parts,
+		       italics_correction); }
+
   private:
   inline const MathGlyphConstruction &
 		get_glyph_construction (hb_codepoint_t glyph,
diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc
index 0d3f19b..942158e 100644
--- a/src/hb-ot-layout.cc
+++ b/src/hb-ot-layout.cc
@@ -1341,7 +1341,7 @@ hb_ot_layout_is_math_extended_shape (hb_face_t *face,
  *
  * Since: 1.4
  **/
-HB_EXTERN hb_position_t
+hb_position_t
 hb_ot_layout_get_math_kerning (hb_font_t *font,
 			       hb_codepoint_t glyph,
 			       hb_ot_math_kern_t kern,
@@ -1351,7 +1351,7 @@ hb_ot_layout_get_math_kerning (hb_font_t *font,
   return math.get_math_glyph_info().get_kerning (glyph, kern, correction_height, font);
 }
 
-HB_EXTERN unsigned int
+unsigned int
 hb_ot_layout_get_math_glyph_variants (hb_font_t *font,
 				      hb_codepoint_t glyph,
 				      hb_direction_t direction,
@@ -1374,15 +1374,19 @@ hb_ot_layout_get_math_min_connector_overlap (hb_font_t *font,
   return math.get_math_variants().get_min_connector_overlap (direction, font);
 }
 
-HB_EXTERN unsigned int
-hb_ot_layout_get_math_glyph_assembly_parts (hb_font_t *font,
-					    hb_codepoint_t glyph,
-					    hb_direction_t direction,
-					    unsigned int start_offset,
-					    unsigned int *parts_count, /* IN/OUT */
-					    hb_math_glyph_part_t *parts, /* OUT */
-					    hb_position_t *italic_correction /* OUT */)
+unsigned int
+hb_ot_layout_get_math_glyph_assembly (hb_font_t *font,
+				      hb_codepoint_t glyph,
+				      hb_direction_t direction,
+				      unsigned int start_offset,
+				      unsigned int *parts_count, /* IN/OUT */
+				      hb_math_glyph_part_t *parts, /* OUT */
+				      hb_position_t *italics_correction /* OUT */)
 {
   const OT::MATH &math = _get_math (font->face);
-  return 0;
+  return math.get_math_variants().get_glyph_parts (glyph, direction, font,
+						   start_offset,
+						   parts_count,
+						   parts,
+						   italics_correction);
 }
diff --git a/src/hb-ot-layout.h b/src/hb-ot-layout.h
index 4c01d63..b6fbd00 100644
--- a/src/hb-ot-layout.h
+++ b/src/hb-ot-layout.h
@@ -341,13 +341,13 @@ hb_ot_layout_get_math_min_connector_overlap (hb_font_t *font,
 					     hb_direction_t direction);
 
 HB_EXTERN unsigned int
-hb_ot_layout_get_math_glyph_assembly_parts (hb_font_t *font,
-					    hb_codepoint_t glyph,
-					    hb_direction_t direction,
-					    unsigned int start_offset,
-					    unsigned int *parts_count, /* IN/OUT */
-					    hb_math_glyph_part_t *parts, /* OUT */
-					    hb_position_t *italic_correction /* OUT */);
+hb_ot_layout_get_math_glyph_assembly (hb_font_t *font,
+				      hb_codepoint_t glyph,
+				      hb_direction_t direction,
+				      unsigned int start_offset,
+				      unsigned int *parts_count, /* IN/OUT */
+				      hb_math_glyph_part_t *parts, /* OUT */
+				      hb_position_t *italics_correction /* OUT */);
 
 HB_END_DECLS
 
commit 353f455af7ccbc1af8338dcb0c8ab87aef866c79
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Sep 26 21:22:48 2016 +0200

    [MATH] Wire up get_glyph_variants()

diff --git a/src/hb-font-private.hh b/src/hb-font-private.hh
index 07bc900..6d5012e 100644
--- a/src/hb-font-private.hh
+++ b/src/hb-font-private.hh
@@ -116,12 +116,12 @@ struct hb_font_t {
 
 
   /* Convert from font-space to user-space */
-  inline hb_position_t em_scale_x (int16_t v) { return em_scale (v, this->x_scale); }
-  inline hb_position_t em_scale_y (int16_t v) { return em_scale (v, this->y_scale); }
+  inline int dir_scale (hb_direction_t direction)
+  { return HB_DIRECTION_IS_VERTICAL(direction) ? y_scale : x_scale; }
+  inline hb_position_t em_scale_x (int16_t v) { return em_scale (v, x_scale); }
+  inline hb_position_t em_scale_y (int16_t v) { return em_scale (v, y_scale); }
   inline hb_position_t em_scale_dir (int16_t v, hb_direction_t direction)
-  { return em_scale (v,
-		     HB_DIRECTION_IS_VERTICAL(direction) ?
-		     this->y_scale : this->x_scale); }
+  { return em_scale (v, dir_scale (direction)); }
 
   /* Convert from parent-font user-space to our user-space */
   inline hb_position_t parent_scale_x_distance (hb_position_t v) {
@@ -508,7 +508,6 @@ struct hb_font_t {
     return false;
   }
 
-  private:
   inline hb_position_t em_scale (int16_t v, int scale)
   {
     int upem = face->get_upem ();
diff --git a/src/hb-ot-layout-math-table.hh b/src/hb-ot-layout-math-table.hh
index 81fc1b0..da65c38 100644
--- a/src/hb-ot-layout-math-table.hh
+++ b/src/hb-ot-layout-math-table.hh
@@ -47,13 +47,13 @@ struct MathValueRecord
     return_trace (c->check_struct (this) && deviceTable.sanitize (c, base));
   }
 
-protected:
+  protected:
   SHORT			value;		/* The X or Y value in design units */
   OffsetTo<Device>	deviceTable;	/* Offset to the device table - from the
 					 * beginning of parent table. May be NULL.
 					 * Suggested format for device table is 1. */
 
-public:
+  public:
   DEFINE_SIZE_STATIC (4);
 };
 
@@ -153,13 +153,13 @@ struct MathConstants
     }
   }
 
-protected:
+  protected:
   SHORT percentScaleDown[2];
   USHORT minHeight[2];
   MathValueRecord mathValueRecords[51];
   SHORT radicalDegreeBottomRaisePercent;
 
-public:
+  public:
   DEFINE_SIZE_STATIC (214);
 };
 
@@ -180,7 +180,7 @@ struct MathItalicsCorrectionInfo
     return italicsCorrection[index].get_x_value (font, this);
   }
 
-protected:
+  protected:
   OffsetTo<Coverage>       coverage;		/* Offset to Coverage table -
 						 * from the beginning of
 						 * MathItalicsCorrectionInfo
@@ -190,7 +190,7 @@ protected:
 						 * values for each
 						 * covered glyph. */
 
-public:
+  public:
   DEFINE_SIZE_ARRAY (4, italicsCorrection);
 };
 
@@ -213,7 +213,7 @@ struct MathTopAccentAttachment
     return topAccentAttachment[index].get_x_value(font, this);
   }
 
-protected:
+  protected:
   OffsetTo<Coverage>       topAccentCoverage;   /* Offset to Coverage table -
 						 * from the beginning of
 						 * MathTopAccentAttachment
@@ -223,7 +223,7 @@ protected:
 						 * attachment points for each
 						 * covered glyph. */
 
-public:
+  public:
   DEFINE_SIZE_ARRAY (2 + 2, topAccentAttachment);
 };
 
@@ -278,7 +278,7 @@ struct MathKern
     return kernValue[i].get_x_value(font, this);
   }
 
-protected:
+  protected:
   USHORT	  heightCount;
   MathValueRecord mathValueRecords[VAR]; /* Array of correction heights at
 					  * which the kern value changes.
@@ -289,7 +289,7 @@ protected:
 					  * to heights. (heightCount+1 entries).
 					  */
 
-public:
+  public:
   DEFINE_SIZE_ARRAY (2, mathValueRecords);
 };
 
@@ -317,12 +317,12 @@ struct MathKernInfoRecord
     return (base+mathKern[idx]).get_value (correction_height, font);
   }
 
-protected:
+  protected:
   /* Offset to MathKern table for each corner -
    * from the beginning of MathKernInfo table. May be NULL. */
   OffsetTo<MathKern> mathKern[4];
 
-public:
+  public:
   DEFINE_SIZE_STATIC (8);
 };
 
@@ -345,7 +345,7 @@ struct MathKernInfo
     return mathKernInfoRecords[index].get_kerning (kern, correction_height, font, this);
   }
 
-protected:
+  protected:
   OffsetTo<Coverage>		mathKernCoverage;    /* Offset to Coverage table -
 						      * from the beginning of the
 						      * MathKernInfo table. */
@@ -356,7 +356,7 @@ protected:
 						      * of subscripts and
 						      * superscripts. */
 
-public:
+  public:
   DEFINE_SIZE_ARRAY (4, mathKernInfoRecords);
 };
 
@@ -389,7 +389,7 @@ struct MathGlyphInfo
 				    hb_font_t *font) const
   { return (this+mathKernInfo).get_kerning (glyph, kern, correction_height, font); }
 
-protected:
+  protected:
   /* Offset to MathItalicsCorrectionInfo table -
    * from the beginning of MathGlyphInfo table. */
   OffsetTo<MathItalicsCorrectionInfo> mathItalicsCorrectionInfo;
@@ -409,34 +409,27 @@ protected:
     * from the beginning of MathGlyphInfo table. */
   OffsetTo<MathKernInfo> mathKernInfo;
 
-public:
+  public:
   DEFINE_SIZE_STATIC (8);
 };
 
 struct MathGlyphVariantRecord
 {
+  friend struct MathGlyphConstruction;
+
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
   }
 
-  hb_codepoint_t get_glyph() const { return variantGlyph; }
-  inline hb_position_t get_advance_measurement (hb_font_t *font,
-						bool horizontal) const
-  {
-    return horizontal ?
-      font->em_scale_x (advanceMeasurement) :
-      font->em_scale_y (advanceMeasurement);
-  }
-
-protected:
+  protected:
   GlyphID variantGlyph;       /* Glyph ID for the variant. */
   USHORT  advanceMeasurement; /* Advance width/height, in design units, of the
 			       * variant, in the direction of requested
 			       * glyph extension. */
 
-public:
+  public:
   DEFINE_SIZE_STATIC (4);
 };
 
@@ -446,49 +439,21 @@ struct PartFlags : USHORT
     Extender = 0x0001u, /* If set, the part can be skipped or repeated. */
   };
 
-public:
+  public:
   DEFINE_SIZE_STATIC (2);
 };
 
-struct GlyphPartRecord
+struct MathGlyphPartRecord
 {
+  friend struct MathGlyphAssembly;
+
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
   }
 
-  hb_codepoint_t get_glyph() const { return glyph; }
-
-  inline hb_position_t
-  get_start_connector_length (hb_font_t *font, bool horizontal) const
-  {
-    return horizontal ?
-      font->em_scale_x (startConnectorLength) :
-      font->em_scale_y (startConnectorLength);
-  }
-
-  inline hb_position_t
-  get_end_connector_length (hb_font_t *font, bool horizontal) const
-  {
-    return horizontal ?
-      font->em_scale_x (endConnectorLength) :
-      font->em_scale_y (endConnectorLength);
-  }
-
-  inline hb_position_t
-  get_full_advance (hb_font_t *font, bool horizontal) const
-  {
-    return horizontal ?
-      font->em_scale_x (fullAdvance) :
-      font->em_scale_y (fullAdvance);
-  }
-
-  inline bool is_extender() const {
-    return partFlags & PartFlags::Flags::Extender;
-  }
-
-protected:
+  protected:
   GlyphID   glyph;		  /* Glyph ID for the part. */
   USHORT    startConnectorLength; /* Advance width/ height of the straight bar
 				   * connector material, in design units, is at
@@ -503,11 +468,11 @@ protected:
 				   * In design units. */
   PartFlags partFlags;		  /* Part qualifiers. */
 
-public:
+  public:
   DEFINE_SIZE_STATIC (10);
 };
 
-struct GlyphAssembly
+struct MathGlyphAssembly
 {
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
@@ -520,20 +485,15 @@ struct GlyphAssembly
   inline hb_position_t get_italic_correction (hb_font_t *font) const
   { return italicsCorrection.get_x_value(font, this); }
 
-  inline unsigned int part_record_count() const { return partRecords.len; }
-  inline const GlyphPartRecord &get_part_record(unsigned int i) const {
-    return partRecords[i];
-  }
-
-protected:
+  protected:
   MathValueRecord	   italicsCorrection; /* Italics correction of this
-					       * GlyphAssembly. Should not
+					       * MathGlyphAssembly. Should not
 					       * depend on the assembly size. */
-  ArrayOf<GlyphPartRecord> partRecords;       /* Array of part records, from
+  ArrayOf<MathGlyphPartRecord> partRecords;   /* Array of part records, from
 					       * left to right and bottom to
 					       * top. */
 
-public:
+  public:
   DEFINE_SIZE_ARRAY (6, partRecords);
 };
 
@@ -547,15 +507,36 @@ struct MathGlyphConstruction
 		  mathGlyphVariantRecord.sanitize(c));
   }
 
-protected:
-  /* Offset to GlyphAssembly table for this shape - from the beginning of
+  inline unsigned int get_variants (hb_direction_t direction,
+				    hb_font_t *font,
+				    unsigned int start_offset,
+				    unsigned int *variants_count, /* IN/OUT */
+				    hb_math_glyph_variant_t *variants /* OUT */) const
+  {
+    if (variants_count)
+    {
+      int scale = font->dir_scale (direction);
+      const MathGlyphVariantRecord *arr =
+	    mathGlyphVariantRecord.sub_array (start_offset, variants_count);
+      unsigned int count = *variants_count;
+      for (unsigned int i = 0; i < count; i++)
+      {
+	variants[i].glyph = arr[i].variantGlyph;
+	variants[i].advance = font->em_scale (arr[i].advanceMeasurement, scale);
+      }
+    }
+    return mathGlyphVariantRecord.len;
+  }
+
+  protected:
+  /* Offset to MathGlyphAssembly table for this shape - from the beginning of
      MathGlyphConstruction table. May be NULL. */
-  OffsetTo<GlyphAssembly>	  glyphAssembly;
+  OffsetTo<MathGlyphAssembly>	  glyphAssembly;
 
   /* MathGlyphVariantRecords for alternative variants of the glyphs. */
   ArrayOf<MathGlyphVariantRecord> mathGlyphVariantRecord;
 
-public:
+  public:
   DEFINE_SIZE_ARRAY (4, mathGlyphVariantRecord);
 };
 
@@ -586,27 +567,36 @@ struct MathVariants
 						  hb_font_t *font) const
   { return font->em_scale_dir (minConnectorOverlap, direction); }
 
-  inline bool
-  get_glyph_construction (hb_codepoint_t glyph,
-			  hb_bool_t horizontal,
-			  const MathGlyphConstruction *&glyph_construction) const {
-    unsigned int index =
-      horizontal ?
-      (this+horizGlyphCoverage).get_coverage (glyph) :
-      (this+vertGlyphCoverage).get_coverage (glyph);
-    if (likely (index == NOT_COVERED)) return false;
+  inline unsigned int get_glyph_variants (hb_codepoint_t glyph,
+					  hb_direction_t direction,
+					  hb_font_t *font,
+					  unsigned int start_offset,
+					  unsigned int *variants_count, /* IN/OUT */
+					  hb_math_glyph_variant_t *variants /* OUT */) const
+  { return get_glyph_construction (glyph, direction, font)
+	   .get_variants (direction, font, start_offset, variants_count, variants); }
+
+  private:
+  inline const MathGlyphConstruction &
+		get_glyph_construction (hb_codepoint_t glyph,
+					hb_direction_t direction,
+					hb_font_t *font) const
+  {
+    bool vertical = HB_DIRECTION_IS_VERTICAL (direction);
+    unsigned int count = vertical ? vertGlyphCount : horizGlyphCount;
+    const OffsetTo<Coverage> &coverage = vertical ? vertGlyphCoverage
+						  : horizGlyphCoverage;
 
-    USHORT glyphCount = horizontal ? horizGlyphCount : vertGlyphCount;
-    if (unlikely (index >= glyphCount)) return false;
+    unsigned int index = (this+coverage).get_coverage (glyph);
+    if (unlikely (index >= count)) return Null(MathGlyphConstruction);
 
-    if (horizontal)
+    if (!vertical)
       index += vertGlyphCount;
 
-    glyph_construction = &(this + glyphConstruction[index]);
-    return true;
+    return this+glyphConstruction[index];
   }
 
-protected:
+  protected:
   USHORT	     minConnectorOverlap; /* Minimum overlap of connecting
 					   * glyphs during glyph construction,
 					   * in design units. */
@@ -626,9 +616,9 @@ protected:
   /* Array of offsets to MathGlyphConstruction tables - from the beginning of
      the MathVariants table, for shapes growing in vertical/horizontal
      direction. */
-  OffsetTo<MathGlyphConstruction>       glyphConstruction[VAR];
+  OffsetTo<MathGlyphConstruction> glyphConstruction[VAR];
 
-public:
+  public:
   DEFINE_SIZE_ARRAY (10, glyphConstruction);
 };
 
@@ -661,14 +651,14 @@ struct MATH
   inline const MathVariants &get_math_variants (void) const
   { return this+mathVariants; }
 
-protected:
+  protected:
   FixedVersion<>version;		/* Version of the MATH table
 					 * initially set to 0x00010000u */
   OffsetTo<MathConstants> mathConstants;/* MathConstants table */
   OffsetTo<MathGlyphInfo> mathGlyphInfo;/* MathGlyphInfo table */
   OffsetTo<MathVariants>  mathVariants;	/* MathVariants table */
 
-public:
+  public:
   DEFINE_SIZE_STATIC (10);
 };
 
diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc
index eeebb5d..0d3f19b 100644
--- a/src/hb-ot-layout.cc
+++ b/src/hb-ot-layout.cc
@@ -1356,11 +1356,14 @@ hb_ot_layout_get_math_glyph_variants (hb_font_t *font,
 				      hb_codepoint_t glyph,
 				      hb_direction_t direction,
 				      unsigned int start_offset,
-				      unsigned int *variant_count, /* IN/OUT */
+				      unsigned int *variants_count, /* IN/OUT */
 				      hb_math_glyph_variant_t *variants /* OUT */)
 {
   const OT::MATH &math = _get_math (font->face);
-  return 0;
+  return math.get_math_variants().get_glyph_variants (glyph, direction, font,
+						      start_offset,
+						      variants_count,
+						      variants);
 }
 
 hb_position_t
diff --git a/src/hb-ot-layout.h b/src/hb-ot-layout.h
index 8eb8d6c..4c01d63 100644
--- a/src/hb-ot-layout.h
+++ b/src/hb-ot-layout.h
@@ -333,7 +333,7 @@ hb_ot_layout_get_math_glyph_variants (hb_font_t *font,
 				      hb_codepoint_t glyph,
 				      hb_direction_t direction,
 				      unsigned int start_offset,
-				      unsigned int *variant_count, /* IN/OUT */
+				      unsigned int *variants_count, /* IN/OUT */
 				      hb_math_glyph_variant_t *variants /* OUT */);
 
 HB_EXTERN hb_position_t
commit 7fe0e28c22331a353d396f8bc1e3a60f1580a96d
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Sep 26 17:51:47 2016 +0100

    [MATH] Start fleshing out glyph variant API

diff --git a/src/hb-font-private.hh b/src/hb-font-private.hh
index 0b75577..07bc900 100644
--- a/src/hb-font-private.hh
+++ b/src/hb-font-private.hh
@@ -118,6 +118,10 @@ struct hb_font_t {
   /* Convert from font-space to user-space */
   inline hb_position_t em_scale_x (int16_t v) { return em_scale (v, this->x_scale); }
   inline hb_position_t em_scale_y (int16_t v) { return em_scale (v, this->y_scale); }
+  inline hb_position_t em_scale_dir (int16_t v, hb_direction_t direction)
+  { return em_scale (v,
+		     HB_DIRECTION_IS_VERTICAL(direction) ?
+		     this->y_scale : this->x_scale); }
 
   /* Convert from parent-font user-space to our user-space */
   inline hb_position_t parent_scale_x_distance (hb_position_t v) {
diff --git a/src/hb-ot-layout-math-table.hh b/src/hb-ot-layout-math-table.hh
index bec53f3..81fc1b0 100644
--- a/src/hb-ot-layout-math-table.hh
+++ b/src/hb-ot-layout-math-table.hh
@@ -582,13 +582,9 @@ struct MathVariants
 		  sanitize_offsets (c));
   }
 
-  inline hb_position_t get_min_connector_overlap (hb_font_t *font,
-						  bool horizontal) const
-  {
-    return horizontal ?
-      font->em_scale_x (minConnectorOverlap) :
-      font->em_scale_y (minConnectorOverlap);
-  }
+  inline hb_position_t get_min_connector_overlap (hb_direction_t direction,
+						  hb_font_t *font) const
+  { return font->em_scale_dir (minConnectorOverlap, direction); }
 
   inline bool
   get_glyph_construction (hb_codepoint_t glyph,
diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc
index e92d38b..eeebb5d 100644
--- a/src/hb-ot-layout.cc
+++ b/src/hb-ot-layout.cc
@@ -1279,7 +1279,7 @@ hb_ot_layout_get_math_constant (hb_font_t *font,
  *
  * Since: 1.4
  **/
-HB_EXTERN hb_position_t
+hb_position_t
 hb_ot_layout_get_math_italics_correction (hb_font_t *font,
 					  hb_codepoint_t glyph)
 {
@@ -1297,7 +1297,7 @@ hb_ot_layout_get_math_italics_correction (hb_font_t *font,
  *
  * Since: 1.4
  **/
-HB_EXTERN hb_position_t
+hb_position_t
 hb_ot_layout_get_math_top_accent_attachment (hb_font_t *font,
 					     hb_codepoint_t glyph)
 {
@@ -1315,7 +1315,7 @@ hb_ot_layout_get_math_top_accent_attachment (hb_font_t *font,
  *
  * Since: 1.4
  **/
-HB_EXTERN hb_bool_t
+hb_bool_t
 hb_ot_layout_is_math_extended_shape (hb_face_t *face,
 				     hb_codepoint_t glyph)
 {
@@ -1351,56 +1351,35 @@ hb_ot_layout_get_math_kerning (hb_font_t *font,
   return math.get_math_glyph_info().get_kerning (glyph, kern, correction_height, font);
 }
 
-#if 0
-/**
- * hb_ot_layout_get_math_italic_correction_for_glyph_assembly:
- * @font: an #hb_font_t with an OpenType MATH table
- * @base_glyph: index of the glyph to stretch
- * @horizontal: direction of the stretching
- *
- * This function tries and get the italic correction associated to the glyph
- * assembly used to stretch the base glyph in the specified direction.
- *
- * Return value: the italic correction of the glyph assembly or 0
- *
- * Since: ????
- **/
-HB_EXTERN hb_position_t
-hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font_t *font,
-                                                            hb_codepoint_t base_glyph,
-                                                            hb_bool_t horizontal)
+HB_EXTERN unsigned int
+hb_ot_layout_get_math_glyph_variants (hb_font_t *font,
+				      hb_codepoint_t glyph,
+				      hb_direction_t direction,
+				      unsigned int start_offset,
+				      unsigned int *variant_count, /* IN/OUT */
+				      hb_math_glyph_variant_t *variants /* OUT */)
 {
   const OT::MATH &math = _get_math (font->face);
-
-  if (math.has_math_variants()) {
-    const OT::MathGlyphConstruction* glyph_construction;
-    if (math.get_math_variants().
-        get_glyph_construction(base_glyph, horizontal, glyph_construction) &&
-        glyph_construction->has_glyph_assembly())
-      return glyph_construction->
-        get_glyph_assembly().get_italic_correction(font);
-  }
-
   return 0;
 }
 
-HB_INTERNAL hb_bool_t
-hb_ot_layout_get_math_glyph_construction (hb_font_t    *font,
-                                          hb_codepoint_t glyph,
-                                          hb_bool_t horizontal,
-                                          hb_position_t &minConnectorOverlap,
-                                          const OT::MathGlyphConstruction *&glyph_construction)
+hb_position_t
+hb_ot_layout_get_math_min_connector_overlap (hb_font_t *font,
+					     hb_direction_t direction)
 {
   const OT::MATH &math = _get_math (font->face);
+  return math.get_math_variants().get_min_connector_overlap (direction, font);
+}
 
-  if (!math.has_math_variants()) return false;
-
-  const OT::MathVariants &mathVariants = math.get_math_variants();
-  if (!mathVariants.get_glyph_construction(glyph, horizontal,
-                                           glyph_construction)) return false;
-
-  minConnectorOverlap = mathVariants.get_min_connector_overlap(font, horizontal);
-
-  return true;
+HB_EXTERN unsigned int
+hb_ot_layout_get_math_glyph_assembly_parts (hb_font_t *font,
+					    hb_codepoint_t glyph,
+					    hb_direction_t direction,
+					    unsigned int start_offset,
+					    unsigned int *parts_count, /* IN/OUT */
+					    hb_math_glyph_part_t *parts, /* OUT */
+					    hb_position_t *italic_correction /* OUT */)
+{
+  const OT::MATH &math = _get_math (font->face);
+  return 0;
 }
-#endif
diff --git a/src/hb-ot-layout.h b/src/hb-ot-layout.h
index 9c1c57b..8eb8d6c 100644
--- a/src/hb-ot-layout.h
+++ b/src/hb-ot-layout.h
@@ -328,6 +328,26 @@ hb_ot_layout_get_math_kerning (hb_font_t *font,
 			       hb_ot_math_kern_t kern,
 			       hb_position_t correction_height);
 
+HB_EXTERN unsigned int
+hb_ot_layout_get_math_glyph_variants (hb_font_t *font,
+				      hb_codepoint_t glyph,
+				      hb_direction_t direction,
+				      unsigned int start_offset,
+				      unsigned int *variant_count, /* IN/OUT */
+				      hb_math_glyph_variant_t *variants /* OUT */);
+
+HB_EXTERN hb_position_t
+hb_ot_layout_get_math_min_connector_overlap (hb_font_t *font,
+					     hb_direction_t direction);
+
+HB_EXTERN unsigned int
+hb_ot_layout_get_math_glyph_assembly_parts (hb_font_t *font,
+					    hb_codepoint_t glyph,
+					    hb_direction_t direction,
+					    unsigned int start_offset,
+					    unsigned int *parts_count, /* IN/OUT */
+					    hb_math_glyph_part_t *parts, /* OUT */
+					    hb_position_t *italic_correction /* OUT */);
 
 HB_END_DECLS
 
diff --git a/src/hb-ot-math.h b/src/hb-ot-math.h
index a62b4b6..bf37975 100644
--- a/src/hb-ot-math.h
+++ b/src/hb-ot-math.h
@@ -102,6 +102,24 @@ typedef enum {
   HB_OT_MATH_KERN_BOTTOM_LEFT = 3
 } hb_ot_math_kern_t;
 
+typedef struct hb_math_glyph_variant_t {
+  hb_codepoint_t glyph;
+  hb_position_t advance;
+} hb_math_glyph_variant_t;
+
+typedef enum { /*< flags >*/
+  HB_MATH_GLYPH_PART_FLAG_EXTENDER	= 0x00000001u  /* Extender glyph */
+} hb_math_glyph_part_flags_t;
+
+typedef struct hb_math_glyph_part_t {
+  hb_codepoint_t glyph;
+  hb_position_t start_connector_length;
+  hb_position_t end_connector_length;
+  hb_position_t full_advance;
+  hb_math_glyph_part_flags_t flags;
+} hb_math_glyph_part_t;
+
+
 HB_END_DECLS
 
 #endif /* HB_OT_MATH_H */
commit 1f3327f21045df8a050a21a949b44b9ce186ceaa
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Sep 26 16:10:08 2016 +0100

    [MATH] Clean up math variants

diff --git a/src/hb-ot-layout-math-table.hh b/src/hb-ot-layout-math-table.hh
index 784f5c1..bec53f3 100644
--- a/src/hb-ot-layout-math-table.hh
+++ b/src/hb-ot-layout-math-table.hh
@@ -437,7 +437,7 @@ protected:
 			       * glyph extension. */
 
 public:
-  DEFINE_SIZE_STATIC (2 + 2);
+  DEFINE_SIZE_STATIC (4);
 };
 
 struct PartFlags : USHORT
@@ -504,7 +504,7 @@ protected:
   PartFlags partFlags;		  /* Part qualifiers. */
 
 public:
-  DEFINE_SIZE_STATIC (5 * 2);
+  DEFINE_SIZE_STATIC (10);
 };
 
 struct GlyphAssembly
@@ -522,7 +522,6 @@ struct GlyphAssembly
 
   inline unsigned int part_record_count() const { return partRecords.len; }
   inline const GlyphPartRecord &get_part_record(unsigned int i) const {
-    assert(i < partRecords.len);
     return partRecords[i];
   }
 
@@ -535,7 +534,7 @@ protected:
 					       * top. */
 
 public:
-  DEFINE_SIZE_ARRAY (4 + 2, partRecords);
+  DEFINE_SIZE_ARRAY (6, partRecords);
 };
 
 struct MathGlyphConstruction
@@ -548,19 +547,6 @@ struct MathGlyphConstruction
 		  mathGlyphVariantRecord.sanitize(c));
   }
 
-  inline bool has_glyph_assembly (void) const { return glyphAssembly != 0; }
-  inline const GlyphAssembly &get_glyph_assembly (void) const {
-    return this+glyphAssembly;
-  }
-
-  inline unsigned int glyph_variant_count() const {
-    return mathGlyphVariantRecord.len;
-  }
-  inline const MathGlyphVariantRecord &get_glyph_variant(unsigned int i) const {
-    assert(i < mathGlyphVariantRecord.len);
-    return mathGlyphVariantRecord[i];
-  }
-
 protected:
   /* Offset to GlyphAssembly table for this shape - from the beginning of
      MathGlyphConstruction table. May be NULL. */
@@ -570,7 +556,7 @@ protected:
   ArrayOf<MathGlyphVariantRecord> mathGlyphVariantRecord;
 
 public:
-  DEFINE_SIZE_ARRAY (2 + 2, mathGlyphVariantRecord);
+  DEFINE_SIZE_ARRAY (4, mathGlyphVariantRecord);
 };
 
 struct MathVariants
@@ -647,7 +633,7 @@ protected:
   OffsetTo<MathGlyphConstruction>       glyphConstruction[VAR];
 
 public:
-  DEFINE_SIZE_ARRAY (5 * 2, glyphConstruction);
+  DEFINE_SIZE_ARRAY (10, glyphConstruction);
 };
 
 
@@ -673,14 +659,11 @@ struct MATH
 				     hb_font_t		   *font) const
   { return (this+mathConstants).get_value (constant, font); }
 
-  inline const MathGlyphInfo &get_math_glyph_info (void) const {
-    return this+mathGlyphInfo;
-  }
+  inline const MathGlyphInfo &get_math_glyph_info (void) const
+  { return this+mathGlyphInfo; }
 
-  inline bool has_math_variants (void) const { return mathVariants != 0; }
-  inline const MathVariants &get_math_variants (void) const {
-    return this+mathVariants;
-  }
+  inline const MathVariants &get_math_variants (void) const
+  { return this+mathVariants; }
 
 protected:
   FixedVersion<>version;		/* Version of the MATH table
commit 51da7a1cd672aada84bdbb3a2a8dd77ab1134249
Author: Frédéric Wang <fred.wang at free.fr>
Date:   Thu Aug 25 11:17:50 2016 +0200

    MATH table: Add API to access math variants.

diff --git a/src/hb-ot-layout-math-table.hh b/src/hb-ot-layout-math-table.hh
index 7686bf1..784f5c1 100644
--- a/src/hb-ot-layout-math-table.hh
+++ b/src/hb-ot-layout-math-table.hh
@@ -279,7 +279,7 @@ struct MathKern
   }
 
 protected:
-  USHORT          heightCount;
+  USHORT	  heightCount;
   MathValueRecord mathValueRecords[VAR]; /* Array of correction heights at
 					  * which the kern value changes.
 					  * Sorted by the height value in
@@ -413,6 +413,243 @@ public:
   DEFINE_SIZE_STATIC (8);
 };
 
+struct MathGlyphVariantRecord
+{
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  hb_codepoint_t get_glyph() const { return variantGlyph; }
+  inline hb_position_t get_advance_measurement (hb_font_t *font,
+						bool horizontal) const
+  {
+    return horizontal ?
+      font->em_scale_x (advanceMeasurement) :
+      font->em_scale_y (advanceMeasurement);
+  }
+
+protected:
+  GlyphID variantGlyph;       /* Glyph ID for the variant. */
+  USHORT  advanceMeasurement; /* Advance width/height, in design units, of the
+			       * variant, in the direction of requested
+			       * glyph extension. */
+
+public:
+  DEFINE_SIZE_STATIC (2 + 2);
+};
+
+struct PartFlags : USHORT
+{
+  enum Flags {
+    Extender = 0x0001u, /* If set, the part can be skipped or repeated. */
+  };
+
+public:
+  DEFINE_SIZE_STATIC (2);
+};
+
+struct GlyphPartRecord
+{
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  hb_codepoint_t get_glyph() const { return glyph; }
+
+  inline hb_position_t
+  get_start_connector_length (hb_font_t *font, bool horizontal) const
+  {
+    return horizontal ?
+      font->em_scale_x (startConnectorLength) :
+      font->em_scale_y (startConnectorLength);
+  }
+
+  inline hb_position_t
+  get_end_connector_length (hb_font_t *font, bool horizontal) const
+  {
+    return horizontal ?
+      font->em_scale_x (endConnectorLength) :
+      font->em_scale_y (endConnectorLength);
+  }
+
+  inline hb_position_t
+  get_full_advance (hb_font_t *font, bool horizontal) const
+  {
+    return horizontal ?
+      font->em_scale_x (fullAdvance) :
+      font->em_scale_y (fullAdvance);
+  }
+
+  inline bool is_extender() const {
+    return partFlags & PartFlags::Flags::Extender;
+  }
+
+protected:
+  GlyphID   glyph;		  /* Glyph ID for the part. */
+  USHORT    startConnectorLength; /* Advance width/ height of the straight bar
+				   * connector material, in design units, is at
+				   * the beginning of the glyph, in the
+				   * direction of the extension. */
+  USHORT    endConnectorLength;   /* Advance width/ height of the straight bar
+				   * connector material, in design units, is at
+				   * the end of the glyph, in the direction of
+				   * the extension. */
+  USHORT    fullAdvance;	  /* Full advance width/height for this part,
+				   * in the direction of the extension.
+				   * In design units. */
+  PartFlags partFlags;		  /* Part qualifiers. */
+
+public:
+  DEFINE_SIZE_STATIC (5 * 2);
+};
+
+struct GlyphAssembly
+{
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+		  italicsCorrection.sanitize(c, this) &&
+		  partRecords.sanitize(c));
+  }
+
+  inline hb_position_t get_italic_correction (hb_font_t *font) const
+  { return italicsCorrection.get_x_value(font, this); }
+
+  inline unsigned int part_record_count() const { return partRecords.len; }
+  inline const GlyphPartRecord &get_part_record(unsigned int i) const {
+    assert(i < partRecords.len);
+    return partRecords[i];
+  }
+
+protected:
+  MathValueRecord	   italicsCorrection; /* Italics correction of this
+					       * GlyphAssembly. Should not
+					       * depend on the assembly size. */
+  ArrayOf<GlyphPartRecord> partRecords;       /* Array of part records, from
+					       * left to right and bottom to
+					       * top. */
+
+public:
+  DEFINE_SIZE_ARRAY (4 + 2, partRecords);
+};
+
+struct MathGlyphConstruction
+{
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+		  glyphAssembly.sanitize(c, this) &&
+		  mathGlyphVariantRecord.sanitize(c));
+  }
+
+  inline bool has_glyph_assembly (void) const { return glyphAssembly != 0; }
+  inline const GlyphAssembly &get_glyph_assembly (void) const {
+    return this+glyphAssembly;
+  }
+
+  inline unsigned int glyph_variant_count() const {
+    return mathGlyphVariantRecord.len;
+  }
+  inline const MathGlyphVariantRecord &get_glyph_variant(unsigned int i) const {
+    assert(i < mathGlyphVariantRecord.len);
+    return mathGlyphVariantRecord[i];
+  }
+
+protected:
+  /* Offset to GlyphAssembly table for this shape - from the beginning of
+     MathGlyphConstruction table. May be NULL. */
+  OffsetTo<GlyphAssembly>	  glyphAssembly;
+
+  /* MathGlyphVariantRecords for alternative variants of the glyphs. */
+  ArrayOf<MathGlyphVariantRecord> mathGlyphVariantRecord;
+
+public:
+  DEFINE_SIZE_ARRAY (2 + 2, mathGlyphVariantRecord);
+};
+
+struct MathVariants
+{
+  inline bool sanitize_offsets (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    unsigned int count = vertGlyphCount + horizGlyphCount;
+    for (unsigned int i = 0; i < count; i++)
+      if (!glyphConstruction[i].sanitize (c, this)) return_trace (false);
+    return_trace (true);
+  }
+
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+		  vertGlyphCoverage.sanitize (c, this) &&
+		  horizGlyphCoverage.sanitize (c, this) &&
+		  c->check_array (glyphConstruction,
+				  glyphConstruction[0].static_size,
+				  vertGlyphCount + horizGlyphCount) &&
+		  sanitize_offsets (c));
+  }
+
+  inline hb_position_t get_min_connector_overlap (hb_font_t *font,
+						  bool horizontal) const
+  {
+    return horizontal ?
+      font->em_scale_x (minConnectorOverlap) :
+      font->em_scale_y (minConnectorOverlap);
+  }
+
+  inline bool
+  get_glyph_construction (hb_codepoint_t glyph,
+			  hb_bool_t horizontal,
+			  const MathGlyphConstruction *&glyph_construction) const {
+    unsigned int index =
+      horizontal ?
+      (this+horizGlyphCoverage).get_coverage (glyph) :
+      (this+vertGlyphCoverage).get_coverage (glyph);
+    if (likely (index == NOT_COVERED)) return false;
+
+    USHORT glyphCount = horizontal ? horizGlyphCount : vertGlyphCount;
+    if (unlikely (index >= glyphCount)) return false;
+
+    if (horizontal)
+      index += vertGlyphCount;
+
+    glyph_construction = &(this + glyphConstruction[index]);
+    return true;
+  }
+
+protected:
+  USHORT	     minConnectorOverlap; /* Minimum overlap of connecting
+					   * glyphs during glyph construction,
+					   * in design units. */
+  OffsetTo<Coverage> vertGlyphCoverage;   /* Offset to Coverage table -
+					   * from the beginning of MathVariants
+					   * table. */
+  OffsetTo<Coverage> horizGlyphCoverage;  /* Offset to Coverage table -
+					   * from the beginning of MathVariants
+					   * table. */
+  USHORT	     vertGlyphCount;      /* Number of glyphs for which
+					   * information is provided for
+					   * vertically growing variants. */
+  USHORT	     horizGlyphCount;     /* Number of glyphs for which
+					   * information is provided for
+					   * horizontally growing variants. */
+
+  /* Array of offsets to MathGlyphConstruction tables - from the beginning of
+     the MathVariants table, for shapes growing in vertical/horizontal
+     direction. */
+  OffsetTo<MathGlyphConstruction>       glyphConstruction[VAR];
+
+public:
+  DEFINE_SIZE_ARRAY (5 * 2, glyphConstruction);
+};
+
 
 /*
  * MATH -- The MATH Table
@@ -428,24 +665,32 @@ struct MATH
     return_trace (version.sanitize (c) &&
 		  likely (version.major == 1) &&
 		  mathConstants.sanitize (c, this) &&
-		  mathGlyphInfo.sanitize (c, this));
+		  mathGlyphInfo.sanitize (c, this) &&
+		  mathVariants.sanitize (c, this));
   }
 
   inline hb_position_t get_constant (hb_ot_math_constant_t  constant,
-				     hb_font_t             *font) const
+				     hb_font_t		   *font) const
   { return (this+mathConstants).get_value (constant, font); }
 
   inline const MathGlyphInfo &get_math_glyph_info (void) const {
     return this+mathGlyphInfo;
   }
+
+  inline bool has_math_variants (void) const { return mathVariants != 0; }
+  inline const MathVariants &get_math_variants (void) const {
+    return this+mathVariants;
+  }
+
 protected:
   FixedVersion<>version;		/* Version of the MATH table
 					 * initially set to 0x00010000u */
   OffsetTo<MathConstants> mathConstants;/* MathConstants table */
   OffsetTo<MathGlyphInfo> mathGlyphInfo;/* MathGlyphInfo table */
+  OffsetTo<MathVariants>  mathVariants;	/* MathVariants table */
 
 public:
-  DEFINE_SIZE_STATIC (8);
+  DEFINE_SIZE_STATIC (10);
 };
 
 } /* mathspace OT */
diff --git a/src/hb-ot-layout-private.hh b/src/hb-ot-layout-private.hh
index a4272de..775261a 100644
--- a/src/hb-ot-layout-private.hh
+++ b/src/hb-ot-layout-private.hh
@@ -617,5 +617,15 @@ _hb_buffer_assert_gsubgpos_vars (hb_buffer_t *buffer)
 #undef lig_props
 #undef glyph_props
 
+namespace OT {
+  struct MathGlyphConstruction;
+};
+
+HB_INTERNAL hb_bool_t
+hb_ot_layout_get_math_glyph_construction (hb_font_t *font,
+                                          hb_codepoint_t glyph,
+                                          hb_bool_t horizontal,
+                                          hb_position_t &minConnectorOverlap,
+                                          const OT::MathGlyphConstruction *&glyph_construction);
 
 #endif /* HB_OT_LAYOUT_PRIVATE_HH */
diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc
index 3d87b50..e92d38b 100644
--- a/src/hb-ot-layout.cc
+++ b/src/hb-ot-layout.cc
@@ -1350,3 +1350,57 @@ hb_ot_layout_get_math_kerning (hb_font_t *font,
   const OT::MATH &math = _get_math (font->face);
   return math.get_math_glyph_info().get_kerning (glyph, kern, correction_height, font);
 }
+
+#if 0
+/**
+ * hb_ot_layout_get_math_italic_correction_for_glyph_assembly:
+ * @font: an #hb_font_t with an OpenType MATH table
+ * @base_glyph: index of the glyph to stretch
+ * @horizontal: direction of the stretching
+ *
+ * This function tries and get the italic correction associated to the glyph
+ * assembly used to stretch the base glyph in the specified direction.
+ *
+ * Return value: the italic correction of the glyph assembly or 0
+ *
+ * Since: ????
+ **/
+HB_EXTERN hb_position_t
+hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font_t *font,
+                                                            hb_codepoint_t base_glyph,
+                                                            hb_bool_t horizontal)
+{
+  const OT::MATH &math = _get_math (font->face);
+
+  if (math.has_math_variants()) {
+    const OT::MathGlyphConstruction* glyph_construction;
+    if (math.get_math_variants().
+        get_glyph_construction(base_glyph, horizontal, glyph_construction) &&
+        glyph_construction->has_glyph_assembly())
+      return glyph_construction->
+        get_glyph_assembly().get_italic_correction(font);
+  }
+
+  return 0;
+}
+
+HB_INTERNAL hb_bool_t
+hb_ot_layout_get_math_glyph_construction (hb_font_t    *font,
+                                          hb_codepoint_t glyph,
+                                          hb_bool_t horizontal,
+                                          hb_position_t &minConnectorOverlap,
+                                          const OT::MathGlyphConstruction *&glyph_construction)
+{
+  const OT::MATH &math = _get_math (font->face);
+
+  if (!math.has_math_variants()) return false;
+
+  const OT::MathVariants &mathVariants = math.get_math_variants();
+  if (!mathVariants.get_glyph_construction(glyph, horizontal,
+                                           glyph_construction)) return false;
+
+  minConnectorOverlap = mathVariants.get_min_connector_overlap(font, horizontal);
+
+  return true;
+}
+#endif
diff --git a/test/api/fonts/MathTestFontPartial4.otf b/test/api/fonts/MathTestFontPartial4.otf
new file mode 100644
index 0000000..cda3057
Binary files /dev/null and b/test/api/fonts/MathTestFontPartial4.otf differ
diff --git a/test/api/test-ot-layout-math.c b/test/api/test-ot-layout-math.c
index 93dab74..34ed0fc 100644
--- a/test/api/test-ot-layout-math.c
+++ b/test/api/test-ot-layout-math.c
@@ -315,6 +315,56 @@ test_get_math_kerning (void)
 }
 
 
+#if 0
+static void
+test_get_math_italic_correction_for_glyph_assembly (void)
+{
+  hb_codepoint_t glyph;
+  initFreeType();
+
+  openFont("fonts/MathTestFontEmpty.otf");
+  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
+  g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, TRUE), ==, 0); // MathVariants not available
+  g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, FALSE), ==, 0); // MathVariants not available
+  closeFont();
+
+  openFont("fonts/MathTestFontPartial1.otf");
+  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
+  g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, TRUE), ==, 0); // VertGlyphCoverage and HorizGlyphCoverage absent
+  g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, FALSE), ==, 0); // VertGlyphCoverage and HorizGlyphCoverage absent
+  closeFont();
+
+  openFont("fonts/MathTestFontPartial2.otf");
+  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
+  g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, TRUE), ==, 0); // VertGlyphCoverage and HorizGlyphCoverage empty
+  g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, FALSE), ==, 0); // VertGlyphCoverage and HorizGlyphCoverage empty
+  closeFont();
+
+  openFont("fonts/MathTestFontPartial3.otf");
+  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
+  g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, TRUE), ==, 0); // HorizGlyphConstruction and VertGlyphConstruction empty
+  g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, FALSE), ==, 0);  // HorizGlyphConstruction and VertGlyphConstruction empty
+  closeFont();
+
+  openFont("fonts/MathTestFontPartial4.otf");
+  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
+  g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, TRUE), ==, 0);
+  g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, FALSE), ==, 0);
+  closeFont();
+
+  openFont("fonts/MathTestFontFull.otf");
+  g_assert(hb_font_get_glyph_from_name (hb_font, "arrowleft", -1, &glyph));
+  g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, TRUE), ==, 124);
+  g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, FALSE), ==, 0);
+  g_assert(hb_font_get_glyph_from_name (hb_font, "arrowup", -1, &glyph));
+  g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, TRUE), ==, 0);
+  g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, FALSE), ==, 331);
+  closeFont();
+
+  cleanupFreeType();
+}
+#endif
+
 int
 main (int argc, char **argv)
 {
@@ -326,6 +376,7 @@ main (int argc, char **argv)
   hb_test_add (test_get_math_top_accent_attachment);
   hb_test_add (test_is_math_extended_shape);
   hb_test_add (test_get_math_kerning);
+  //hb_test_add (test_get_math_italic_correction_for_glyph_assembly);
 
   return hb_test_run();
 }
commit 722e620f20fa2225cf874f4aeb115a064142fcf1
Author: Frédéric Wang <fred.wang at free.fr>
Date:   Mon Sep 26 11:51:36 2016 +0200

    Use G_TEST_DIST to build the path of math test fonts

diff --git a/test/api/Makefile.am b/test/api/Makefile.am
index 322cd7d..27520ff 100644
--- a/test/api/Makefile.am
+++ b/test/api/Makefile.am
@@ -83,6 +83,8 @@ TESTS_ENVIRONMENT = \
 	G_DEBUG=gc-friendly \
 	G_SLICE=always-malloc \
 	srcdir=$(srcdir) \
+	G_TEST_SRCDIR=$(abs_srcdir) \
+	G_TEST_BUILDDIR=$(abs_builddir) \
 	$(NULL)
 
 
diff --git a/test/api/test-ot-layout-math.c b/test/api/test-ot-layout-math.c
index d7121a2..93dab74 100644
--- a/test/api/test-ot-layout-math.c
+++ b/test/api/test-ot-layout-math.c
@@ -54,12 +54,16 @@ cleanupFreeType (void)
 static void
 openFont(const char* fontFile)
 {
+  gchar* path = g_test_build_filename(G_TEST_DIST, fontFile, NULL);
+
   FT_Error ft_error;
-  if ((ft_error = FT_New_Face (ft_library, fontFile, 0, &ft_face)))
+  if ((ft_error = FT_New_Face (ft_library, path, 0, &ft_face))) {
+    g_free(path);
     abort();
+  }
+  g_free(path);
 
 #define fontSize 1000
-
   if ((ft_error = FT_Set_Char_Size (ft_face, fontSize, fontSize, 0, 0)))
     abort();
   hb_font = hb_ft_font_create (ft_face, NULL);
commit 8d58e3433e242bd9dd18aa08f55ab0a406583fb0
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Sep 26 13:39:58 2016 +0100

    [MATH] Fix get_kerning() with negative y-scale

diff --git a/src/hb-ot-layout-math-table.hh b/src/hb-ot-layout-math-table.hh
index 4600eab..7686bf1 100644
--- a/src/hb-ot-layout-math-table.hh
+++ b/src/hb-ot-layout-math-table.hh
@@ -252,20 +252,24 @@ struct MathKern
   {
     const MathValueRecord* correctionHeight = mathValueRecords;
     const MathValueRecord* kernValue = mathValueRecords + heightCount;
-    // The description of the MathKern table is a ambiguous, but interpreting
-    // "between the two heights found at those indexes" for 0 < i < len as
-    //
-    //   correctionHeight[i-1] < correction_height <= correctionHeight[i]
-    //
-    // makes the result consistent with the limit cases and we can just use the
-    // binary search algorithm of std::upper_bound:
-    unsigned int count = heightCount;
+    int sign = font->y_scale < 0 ? -1 : +1;
+
+    /* The description of the MathKern table is a ambiguous, but interpreting
+     * "between the two heights found at those indexes" for 0 < i < len as
+     *
+     *   correctionHeight[i-1] < correction_height <= correctionHeight[i]
+     *
+     * makes the result consistent with the limit cases and we can just use the
+     * binary search algorithm of std::upper_bound:
+     */
     unsigned int i = 0;
-    while (count > 0) {
+    unsigned int count = heightCount;
+    while (count > 0)
+    {
       unsigned int half = count / 2;
-      hb_position_t height =
-	correctionHeight[i + half].get_y_value(font, this);
-      if (height < correction_height) {
+      hb_position_t height = correctionHeight[i + half].get_y_value(font, this);
+      if (sign * height < sign * correction_height)
+      {
 	i += half + 1;
 	count -= half + 1;
       } else
@@ -279,9 +283,11 @@ protected:
   MathValueRecord mathValueRecords[VAR]; /* Array of correction heights at
 					  * which the kern value changes.
 					  * Sorted by the height value in
-					  * design units. */
-					 /* Array of kern values corresponding
-					  * to heights. */
+					  * design units (heightCount entries),
+					  * Followed by:
+					  * Array of kern values corresponding
+					  * to heights. (heightCount+1 entries).
+					  */
 
 public:
   DEFINE_SIZE_ARRAY (2, mathValueRecords);
commit 94f5df5626b223ad92d0c167f560c1f2e2f19042
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Sep 26 13:31:47 2016 +0100

    [MATH] Clean up get_kerning()

diff --git a/src/hb-ot-layout-math-table.hh b/src/hb-ot-layout-math-table.hh
index 8f7ce3d..4600eab 100644
--- a/src/hb-ot-layout-math-table.hh
+++ b/src/hb-ot-layout-math-table.hh
@@ -248,8 +248,7 @@ struct MathKern
 		  sanitize_math_value_records (c));
   }
 
-  inline hb_position_t get_value (hb_font_t *font,
-				  hb_position_t &correction_height) const
+  inline hb_position_t get_value (hb_position_t correction_height, hb_font_t *font) const
   {
     const MathValueRecord* correctionHeight = mathValueRecords;
     const MathValueRecord* kernValue = mathValueRecords + heightCount;
@@ -302,12 +301,14 @@ struct MathKernInfoRecord
     return_trace (true);
   }
 
-  inline const MathKern &get_math_kern (hb_ot_math_kern_t kern,
-					const void *base) const
+  inline hb_position_t get_kerning (hb_ot_math_kern_t kern,
+				    hb_position_t correction_height,
+				    hb_font_t *font,
+				    const void *base) const
   {
     unsigned int idx = kern;
-    if (unlikely (idx > ARRAY_LENGTH (mathKern))) return Null(MathKern);
-    return base+mathKern[idx];
+    if (unlikely (idx >= ARRAY_LENGTH (mathKern))) return 0;
+    return (base+mathKern[idx]).get_value (correction_height, font);
   }
 
 protected:
@@ -329,11 +330,13 @@ struct MathKernInfo
 		  mathKernInfoRecords.sanitize (c, this));
   }
 
-  inline const MathKernInfoRecord&
-  get_math_kern_info_record (hb_codepoint_t glyph) const
+  inline hb_position_t get_kerning (hb_codepoint_t glyph,
+				    hb_ot_math_kern_t kern,
+				    hb_position_t correction_height,
+				    hb_font_t *font) const
   {
     unsigned int index = (this+mathKernCoverage).get_coverage (glyph);
-    return mathKernInfoRecords[index];
+    return mathKernInfoRecords[index].get_kerning (kern, correction_height, font, this);
   }
 
 protected:
@@ -374,9 +377,11 @@ struct MathGlyphInfo
   inline bool is_extended_shape (hb_codepoint_t glyph) const
   { return (this+extendedShapeCoverage).get_coverage (glyph) != NOT_COVERED; }
 
-  inline const MathKernInfo &get_math_kern_info (void) const {
-    return this+mathKernInfo;
-  }
+  inline hb_position_t get_kerning (hb_codepoint_t glyph,
+				    hb_ot_math_kern_t kern,
+				    hb_position_t correction_height,
+				    hb_font_t *font) const
+  { return (this+mathKernInfo).get_kerning (glyph, kern, correction_height, font); }
 
 protected:
   /* Offset to MathItalicsCorrectionInfo table -
diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc
index 6d6cf5b..3d87b50 100644
--- a/src/hb-ot-layout.cc
+++ b/src/hb-ot-layout.cc
@@ -1348,8 +1348,5 @@ hb_ot_layout_get_math_kerning (hb_font_t *font,
 			       hb_position_t correction_height)
 {
   const OT::MATH &math = _get_math (font->face);
-  const OT::MathGlyphInfo &glyphInfo = math.get_math_glyph_info();
-  const OT::MathKernInfo &kernInfo = glyphInfo.get_math_kern_info();
-  const OT::MathKernInfoRecord &kernInfoRecord = kernInfo.get_math_kern_info_record(glyph);
-  return kernInfoRecord.get_math_kern (kern, &kernInfo).get_value (font, correction_height);
+  return math.get_math_glyph_info().get_kerning (glyph, kern, correction_height, font);
 }
commit 17ff30e9afde79e41c17786223293e867b49ebba
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Sep 26 12:18:32 2016 +0100

    [MATH] Clean up get_top_accent_attachment()
    
    Note, the function now returns "half of horizontal advance width"
    if top accent attachment for glyph is not explicitly defined.
    This is what the spec requires.  Updated tests.

diff --git a/src/hb-ot-layout-math-table.hh b/src/hb-ot-layout-math-table.hh
index 3899b16..8f7ce3d 100644
--- a/src/hb-ot-layout-math-table.hh
+++ b/src/hb-ot-layout-math-table.hh
@@ -178,7 +178,6 @@ struct MathItalicsCorrectionInfo
   {
     unsigned int index = (this+coverage).get_coverage (glyph);
     return italicsCorrection[index].get_x_value (font, this);
-    return true;
   }
 
 protected:
@@ -205,14 +204,13 @@ struct MathTopAccentAttachment
 		  topAccentAttachment.sanitize (c, this));
   }
 
-  inline bool get_value (hb_font_t *font, hb_codepoint_t glyph,
-			 hb_position_t &value) const
+  inline hb_position_t get_value (hb_codepoint_t glyph,
+				  hb_font_t *font) const
   {
     unsigned int index = (this+topAccentCoverage).get_coverage (glyph);
-    if (likely (index == NOT_COVERED)) return false;
-    if (unlikely (index >= topAccentAttachment.len)) return false;
-    value = topAccentAttachment[index].get_x_value(font, this);
-    return true;
+    if (index == NOT_COVERED)
+      return font->get_glyph_h_advance (glyph) / 2;
+    return topAccentAttachment[index].get_x_value(font, this);
   }
 
 protected:
@@ -366,22 +364,15 @@ struct MathGlyphInfo
   }
 
   inline hb_position_t
-  get_italics_correction (hb_codepoint_t glyph,
-			  hb_font_t *font) const
-  {
-    return (this+mathItalicsCorrectionInfo).get_value (glyph, font);
-  }
+  get_italics_correction (hb_codepoint_t  glyph, hb_font_t *font) const
+  { return (this+mathItalicsCorrectionInfo).get_value (glyph, font); }
 
-  inline const MathTopAccentAttachment&
-  get_math_top_accent_attachment (void) const {
-    return this+mathTopAccentAttachment;
-  }
+  inline hb_position_t
+  get_top_accent_attachment (hb_codepoint_t  glyph, hb_font_t *font) const
+  { return (this+mathTopAccentAttachment).get_value (glyph, font); }
 
   inline bool is_extended_shape (hb_codepoint_t glyph) const
-  {
-    unsigned int index = (this+extendedShapeCoverage).get_coverage (glyph);
-    return index != NOT_COVERED;
-  }
+  { return (this+extendedShapeCoverage).get_coverage (glyph) != NOT_COVERED; }
 
   inline const MathKernInfo &get_math_kern_info (void) const {
     return this+mathKernInfo;
diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc
index 5f171ca..6d6cf5b 100644
--- a/src/hb-ot-layout.cc
+++ b/src/hb-ot-layout.cc
@@ -1302,12 +1302,7 @@ hb_ot_layout_get_math_top_accent_attachment (hb_font_t *font,
 					     hb_codepoint_t glyph)
 {
   const OT::MATH &math = _get_math (font->face);
-  const OT::MathGlyphInfo &glyphInfo = math.get_math_glyph_info();
-  hb_position_t value;
-  if (glyphInfo.get_math_top_accent_attachment().get_value(font, glyph, value))
-    return value;
-  else
-    return 0; // XXX font->get_glyph_h_advance (glyph) / 2;
+  return math.get_math_glyph_info().get_top_accent_attachment (glyph, font);
 }
 
 /**
diff --git a/test/api/test-ot-layout-math.c b/test/api/test-ot-layout-math.c
index a6f4453..d7121a2 100644
--- a/test/api/test-ot-layout-math.c
+++ b/test/api/test-ot-layout-math.c
@@ -204,22 +204,22 @@ test_get_math_top_accent_attachment (void)
 
   openFont("fonts/MathTestFontEmpty.otf");
   g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
-  g_assert_cmpint(hb_ot_layout_get_math_top_accent_attachment (hb_font, glyph), ==, 0); // MathGlyphInfo not available
+  g_assert_cmpint(hb_ot_layout_get_math_top_accent_attachment (hb_font, glyph), ==, 500); // MathGlyphInfo not available
   closeFont();
 
   openFont("fonts/MathTestFontPartial1.otf");
   g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
-  g_assert_cmpint(hb_ot_layout_get_math_top_accent_attachment (hb_font, glyph), ==, 0); // MathGlyphInfo empty
+  g_assert_cmpint(hb_ot_layout_get_math_top_accent_attachment (hb_font, glyph), ==, 500); // MathGlyphInfo empty
   closeFont();
 
   openFont("fonts/MathTestFontPartial2.otf");
   g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
-  g_assert_cmpint(hb_ot_layout_get_math_top_accent_attachment (hb_font, glyph), ==, 0); // MathTopAccentAttachment empty
+  g_assert_cmpint(hb_ot_layout_get_math_top_accent_attachment (hb_font, glyph), ==, 500); // MathTopAccentAttachment empty
   closeFont();
 
   openFont("fonts/MathTestFontFull.otf");
   g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
-  g_assert_cmpint(hb_ot_layout_get_math_top_accent_attachment (hb_font, glyph), ==, 0); // Glyph without top accent attachment.
+  g_assert_cmpint(hb_ot_layout_get_math_top_accent_attachment (hb_font, glyph), ==, 500); // Glyph without top accent attachment.
   g_assert(hb_font_get_glyph_from_name (hb_font, "D", -1, &glyph));
   g_assert_cmpint(hb_ot_layout_get_math_top_accent_attachment (hb_font, glyph), ==, 374);
   g_assert(hb_font_get_glyph_from_name (hb_font, "E", -1, &glyph));
commit 8bcf517fe59608d2247a8974445b3ff0f4b4b4ac
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Sep 26 12:12:41 2016 +0100

    [MATH] Clean up get_italics_correction()

diff --git a/src/hb-ot-layout-math-table.hh b/src/hb-ot-layout-math-table.hh
index 53038e3..3899b16 100644
--- a/src/hb-ot-layout-math-table.hh
+++ b/src/hb-ot-layout-math-table.hh
@@ -173,13 +173,11 @@ struct MathItalicsCorrectionInfo
 		  italicsCorrection.sanitize (c, this));
   }
 
-  inline bool get_value (hb_font_t *font, hb_codepoint_t glyph,
-			 hb_position_t &value) const
+  inline hb_position_t get_value (hb_codepoint_t glyph,
+				  hb_font_t *font) const
   {
     unsigned int index = (this+coverage).get_coverage (glyph);
-    if (likely (index == NOT_COVERED)) return false;
-    if (unlikely (index >= italicsCorrection.len)) return false;
-    value = italicsCorrection[index].get_x_value(font, this);
+    return italicsCorrection[index].get_x_value (font, this);
     return true;
   }
 
@@ -367,9 +365,11 @@ struct MathGlyphInfo
 		  mathKernInfo.sanitize(c, this));
   }
 
-  inline const MathItalicsCorrectionInfo&
-  get_math_italics_correction_info (void) const {
-    return this+mathItalicsCorrectionInfo;
+  inline hb_position_t
+  get_italics_correction (hb_codepoint_t glyph,
+			  hb_font_t *font) const
+  {
+    return (this+mathItalicsCorrectionInfo).get_value (glyph, font);
   }
 
   inline const MathTopAccentAttachment&
diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc
index 6fa61a4..5f171ca 100644
--- a/src/hb-ot-layout.cc
+++ b/src/hb-ot-layout.cc
@@ -1270,26 +1270,21 @@ hb_ot_layout_get_math_constant (hb_font_t *font,
 }
 
 /**
- * hb_ot_layout_get_math_italic_correction:
+ * hb_ot_layout_get_math_italics_correction:
  *
  * @font: #hb_font_t from which to retrieve the value
  * @glyph: glyph index from which to retrieve the value
  *
- * Return value: the italic correction of the glyph or 0
+ * Return value: the italics correction of the glyph or 0
  *
  * Since: 1.4
  **/
 HB_EXTERN hb_position_t
-hb_ot_layout_get_math_italic_correction (hb_font_t *font,
-					 hb_codepoint_t glyph)
+hb_ot_layout_get_math_italics_correction (hb_font_t *font,
+					  hb_codepoint_t glyph)
 {
   const OT::MATH &math = _get_math (font->face);
-  const OT::MathGlyphInfo &glyphInfo = math.get_math_glyph_info();
-  hb_position_t value;
-  if (glyphInfo.get_math_italics_correction_info().get_value(font, glyph, value))
-    return value;
-  else
-    return 0;
+  return math.get_math_glyph_info().get_italics_correction (glyph, font);
 }
 
 /**
@@ -1330,7 +1325,7 @@ hb_ot_layout_is_math_extended_shape (hb_face_t *face,
 				     hb_codepoint_t glyph)
 {
   const OT::MATH &math = _get_math (face);
-  return math.get_math_glyph_info().is_extended_shape(glyph);
+  return math.get_math_glyph_info().is_extended_shape (glyph);
 }
 
 /**
diff --git a/src/hb-ot-layout.h b/src/hb-ot-layout.h
index f9ed2d8..9c1c57b 100644
--- a/src/hb-ot-layout.h
+++ b/src/hb-ot-layout.h
@@ -311,8 +311,8 @@ hb_ot_layout_get_math_constant (hb_font_t *font,
 				hb_ot_math_constant_t constant);
 
 HB_EXTERN hb_position_t
-hb_ot_layout_get_math_italic_correction (hb_font_t *font,
-					 hb_codepoint_t glyph);
+hb_ot_layout_get_math_italics_correction (hb_font_t *font,
+					  hb_codepoint_t glyph);
 
 HB_EXTERN hb_position_t
 hb_ot_layout_get_math_top_accent_attachment (hb_font_t *font,
diff --git a/test/api/test-ot-layout-math.c b/test/api/test-ot-layout-math.c
index 5ba583f..a6f4453 100644
--- a/test/api/test-ot-layout-math.c
+++ b/test/api/test-ot-layout-math.c
@@ -161,35 +161,35 @@ test_get_math_constant (void)
 }
 
 static void
-test_get_math_italic_correction (void)
+test_get_math_italics_correction (void)
 {
   hb_codepoint_t glyph;
   initFreeType();
 
   openFont("fonts/MathTestFontEmpty.otf");
   g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
-  g_assert_cmpint(hb_ot_layout_get_math_italic_correction (hb_font, glyph), ==, 0); // MathGlyphInfo not available
+  g_assert_cmpint(hb_ot_layout_get_math_italics_correction (hb_font, glyph), ==, 0); // MathGlyphInfo not available
   closeFont();
 
   openFont("fonts/MathTestFontPartial1.otf");
   g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
-  g_assert_cmpint(hb_ot_layout_get_math_italic_correction (hb_font, glyph), ==, 0); // MathGlyphInfo empty
+  g_assert_cmpint(hb_ot_layout_get_math_italics_correction (hb_font, glyph), ==, 0); // MathGlyphInfo empty
   closeFont();
 
   openFont("fonts/MathTestFontPartial2.otf");
   g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
-  g_assert_cmpint(hb_ot_layout_get_math_italic_correction (hb_font, glyph), ==, 0); // MathItalicsCorrectionInfo empty
+  g_assert_cmpint(hb_ot_layout_get_math_italics_correction (hb_font, glyph), ==, 0); // MathItalicsCorrectionInfo empty
   closeFont();
 
   openFont("fonts/MathTestFontFull.otf");
   g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
-  g_assert_cmpint(hb_ot_layout_get_math_italic_correction (hb_font, glyph), ==, 0); // Glyph without italic correction.
+  g_assert_cmpint(hb_ot_layout_get_math_italics_correction (hb_font, glyph), ==, 0); // Glyph without italic correction.
   g_assert(hb_font_get_glyph_from_name (hb_font, "A", -1, &glyph));
-  g_assert_cmpint(hb_ot_layout_get_math_italic_correction (hb_font, glyph), ==, 197);
+  g_assert_cmpint(hb_ot_layout_get_math_italics_correction (hb_font, glyph), ==, 197);
   g_assert(hb_font_get_glyph_from_name (hb_font, "B", -1, &glyph));
-  g_assert_cmpint(hb_ot_layout_get_math_italic_correction (hb_font, glyph), ==, 150);
+  g_assert_cmpint(hb_ot_layout_get_math_italics_correction (hb_font, glyph), ==, 150);
   g_assert(hb_font_get_glyph_from_name (hb_font, "C", -1, &glyph));
-  g_assert_cmpint(hb_ot_layout_get_math_italic_correction (hb_font, glyph), ==, 452);
+  g_assert_cmpint(hb_ot_layout_get_math_italics_correction (hb_font, glyph), ==, 452);
   closeFont();
 
   cleanupFreeType();
@@ -318,7 +318,7 @@ main (int argc, char **argv)
 
   hb_test_add (test_has_math_data);
   hb_test_add (test_get_math_constant);
-  hb_test_add (test_get_math_italic_correction);
+  hb_test_add (test_get_math_italics_correction);
   hb_test_add (test_get_math_top_accent_attachment);
   hb_test_add (test_is_math_extended_shape);
   hb_test_add (test_get_math_kerning);
commit 06003f71ba0d0327fb1a17098a9d7faa8fb336f0
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Sep 26 12:07:29 2016 +0100

    [MATH] Clean up a bit more

diff --git a/src/hb-ot-layout-math-table.hh b/src/hb-ot-layout-math-table.hh
index cbdee48..53038e3 100644
--- a/src/hb-ot-layout-math-table.hh
+++ b/src/hb-ot-layout-math-table.hh
@@ -367,17 +367,11 @@ struct MathGlyphInfo
 		  mathKernInfo.sanitize(c, this));
   }
 
-  inline bool has_math_italics_correction_info (void) const {
-    return mathItalicsCorrectionInfo != 0;
-  }
   inline const MathItalicsCorrectionInfo&
   get_math_italics_correction_info (void) const {
     return this+mathItalicsCorrectionInfo;
   }
 
-  inline bool has_math_top_accent_attachment (void) const {
-    return mathTopAccentAttachment != 0;
-  }
   inline const MathTopAccentAttachment&
   get_math_top_accent_attachment (void) const {
     return this+mathTopAccentAttachment;
@@ -385,13 +379,10 @@ struct MathGlyphInfo
 
   inline bool is_extended_shape (hb_codepoint_t glyph) const
   {
-    if (likely (extendedShapeCoverage == 0)) return false;
     unsigned int index = (this+extendedShapeCoverage).get_coverage (glyph);
-    if (likely (index == NOT_COVERED)) return false;
-    return true;
+    return index != NOT_COVERED;
   }
 
-  inline bool has_math_kern_info (void) const { return mathKernInfo != 0; }
   inline const MathKernInfo &get_math_kern_info (void) const {
     return this+mathKernInfo;
   }
@@ -442,7 +433,6 @@ struct MATH
 				     hb_font_t             *font) const
   { return (this+mathConstants).get_value (constant, font); }
 
-  inline bool has_math_glyph_info (void) const { return mathGlyphInfo != 0; }
   inline const MathGlyphInfo &get_math_glyph_info (void) const {
     return this+mathGlyphInfo;
   }
diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc
index 359d941..6fa61a4 100644
--- a/src/hb-ot-layout.cc
+++ b/src/hb-ot-layout.cc
@@ -1277,23 +1277,19 @@ hb_ot_layout_get_math_constant (hb_font_t *font,
  *
  * Return value: the italic correction of the glyph or 0
  *
- * Since: ????
+ * Since: 1.4
  **/
 HB_EXTERN hb_position_t
 hb_ot_layout_get_math_italic_correction (hb_font_t *font,
 					 hb_codepoint_t glyph)
 {
   const OT::MATH &math = _get_math (font->face);
-  if (math.has_math_glyph_info()) {
-    const OT::MathGlyphInfo &glyphInfo = math.get_math_glyph_info();
-    if (glyphInfo.has_math_italics_correction_info()) {
-      hb_position_t value;
-      if (glyphInfo.get_math_italics_correction_info().get_value(font, glyph,
-								 value))
-	return value;
-    }
-  }
-  return 0;
+  const OT::MathGlyphInfo &glyphInfo = math.get_math_glyph_info();
+  hb_position_t value;
+  if (glyphInfo.get_math_italics_correction_info().get_value(font, glyph, value))
+    return value;
+  else
+    return 0;
 }
 
 /**
@@ -1304,23 +1300,19 @@ hb_ot_layout_get_math_italic_correction (hb_font_t *font,
  *
  * Return value: the top accent attachment of the glyph or 0
  *
- * Since: ????
+ * Since: 1.4
  **/
 HB_EXTERN hb_position_t
 hb_ot_layout_get_math_top_accent_attachment (hb_font_t *font,
 					     hb_codepoint_t glyph)
 {
   const OT::MATH &math = _get_math (font->face);
-  if (math.has_math_glyph_info()) {
-    const OT::MathGlyphInfo &glyphInfo = math.get_math_glyph_info();
-    if (glyphInfo.has_math_top_accent_attachment()) {
-      hb_position_t value;
-      if (glyphInfo.get_math_top_accent_attachment().get_value(font, glyph,
-							       value))
-	return value;
-    }
-  }
-  return 0;
+  const OT::MathGlyphInfo &glyphInfo = math.get_math_glyph_info();
+  hb_position_t value;
+  if (glyphInfo.get_math_top_accent_attachment().get_value(font, glyph, value))
+    return value;
+  else
+    return 0; // XXX font->get_glyph_h_advance (glyph) / 2;
 }
 
 /**
@@ -1331,15 +1323,14 @@ hb_ot_layout_get_math_top_accent_attachment (hb_font_t *font,
  *
  * Return value: #TRUE if the glyph is an extended shape and #FALSE otherwise
  *
- * Since: ????
+ * Since: 1.4
  **/
 HB_EXTERN hb_bool_t
 hb_ot_layout_is_math_extended_shape (hb_face_t *face,
 				     hb_codepoint_t glyph)
 {
   const OT::MATH &math = _get_math (face);
-  return math.has_math_glyph_info() &&
-    math.get_math_glyph_info().is_extended_shape(glyph);
+  return math.get_math_glyph_info().is_extended_shape(glyph);
 }
 
 /**
@@ -1358,7 +1349,7 @@ hb_ot_layout_is_math_extended_shape (hb_face_t *face,
  *
  * Return value: requested kerning or 0
  *
- * Since: ????
+ * Since: 1.4
  **/
 HB_EXTERN hb_position_t
 hb_ot_layout_get_math_kerning (hb_font_t *font,
@@ -1367,14 +1358,8 @@ hb_ot_layout_get_math_kerning (hb_font_t *font,
 			       hb_position_t correction_height)
 {
   const OT::MATH &math = _get_math (font->face);
-  if (math.has_math_glyph_info()) {
-    const OT::MathGlyphInfo &glyphInfo = math.get_math_glyph_info();
-    if (glyphInfo.has_math_kern_info()) {
-      const OT::MathKernInfo &kernInfo = glyphInfo.get_math_kern_info();
-      const OT::MathKernInfoRecord &kernInfoRecord = kernInfo.get_math_kern_info_record(glyph);
-      return kernInfoRecord.get_math_kern (kern, &kernInfo).get_value (font, correction_height);
-    }
-  }
-
-  return 0;
+  const OT::MathGlyphInfo &glyphInfo = math.get_math_glyph_info();
+  const OT::MathKernInfo &kernInfo = glyphInfo.get_math_kern_info();
+  const OT::MathKernInfoRecord &kernInfoRecord = kernInfo.get_math_kern_info_record(glyph);
+  return kernInfoRecord.get_math_kern (kern, &kernInfo).get_value (font, correction_height);
 }
commit 54c0cc38fba24fa4370231408ba121589b190a28
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Sep 26 11:56:40 2016 +0100

    [MATH] Clean up get_math_constant implementation

diff --git a/src/hb-ot-layout-math-table.hh b/src/hb-ot-layout-math-table.hh
index 7f6c6b0..cbdee48 100644
--- a/src/hb-ot-layout-math-table.hh
+++ b/src/hb-ot-layout-math-table.hh
@@ -77,7 +77,8 @@ struct MathConstants
     return_trace (c->check_struct (this) && sanitize_math_value_records(c));
   }
 
-  inline hb_position_t get_value (hb_font_t *font, hb_ot_math_constant_t constant) const
+  inline hb_position_t get_value (hb_ot_math_constant_t constant,
+				  hb_font_t *font) const
   {
     switch (constant) {
 
@@ -437,10 +438,9 @@ struct MATH
 		  mathGlyphInfo.sanitize (c, this));
   }
 
-  inline bool has_math_constants (void) const { return mathConstants != 0; }
-  inline const MathConstants &get_math_constants (void) const {
-    return this+mathConstants;
-  }
+  inline hb_position_t get_constant (hb_ot_math_constant_t  constant,
+				     hb_font_t             *font) const
+  { return (this+mathConstants).get_value (constant, font); }
 
   inline bool has_math_glyph_info (void) const { return mathGlyphInfo != 0; }
   inline const MathGlyphInfo &get_math_glyph_info (void) const {
diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc
index 3dcdfb6..359d941 100644
--- a/src/hb-ot-layout.cc
+++ b/src/hb-ot-layout.cc
@@ -1259,15 +1259,14 @@ hb_ot_layout_has_math_data (hb_face_t *face)
  *
  * Return value: the requested constant or 0
  *
- * Since: ????
+ * Since: 1.4
  **/
 hb_position_t
 hb_ot_layout_get_math_constant (hb_font_t *font,
 				hb_ot_math_constant_t constant)
 {
   const OT::MATH &math = _get_math (font->face);
-  return math.has_math_constants() ?
-    math.get_math_constants().get_value(font, constant) : 0;
+  return math.get_constant(constant, font);
 }
 
 /**
commit 8a8cfad9a0834fe278a747c1d755144bd78f564b
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Sep 26 11:47:05 2016 +0100

    [MATH] Cleanup previous commit a bit

diff --git a/src/hb-ot-layout-math-table.hh b/src/hb-ot-layout-math-table.hh
index 2eb0d92..7f6c6b0 100644
--- a/src/hb-ot-layout-math-table.hh
+++ b/src/hb-ot-layout-math-table.hh
@@ -48,10 +48,10 @@ struct MathValueRecord
   }
 
 protected:
-  SHORT            value;       /* The X or Y value in design units */
-  OffsetTo<Device> deviceTable; /* Offset to the device table - from the
-                                   beginning of parent table. May be NULL.
-                                   Suggested format for device table is 1. */
+  SHORT			value;		/* The X or Y value in design units */
+  OffsetTo<Device>	deviceTable;	/* Offset to the device table - from the
+					 * beginning of parent table. May be NULL.
+					 * Suggested format for device table is 1. */
 
 public:
   DEFINE_SIZE_STATIC (4);
@@ -62,9 +62,12 @@ struct MathConstants
   inline bool sanitize_math_value_records (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
+
     unsigned int count = ARRAY_LENGTH (mathValueRecords);
     for (unsigned int i = 0; i < count; i++)
-      if (!mathValueRecords[i].sanitize (c, this)) return_trace (false);
+      if (!mathValueRecords[i].sanitize (c, this))
+	return_trace (false);
+
     return_trace (true);
   }
 
@@ -165,12 +168,12 @@ struct MathItalicsCorrectionInfo
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
-                  coverage.sanitize (c, this) &&
-                  italicsCorrection.sanitize (c, this));
+		  coverage.sanitize (c, this) &&
+		  italicsCorrection.sanitize (c, this));
   }
 
   inline bool get_value (hb_font_t *font, hb_codepoint_t glyph,
-                         hb_position_t &value) const
+			 hb_position_t &value) const
   {
     unsigned int index = (this+coverage).get_coverage (glyph);
     if (likely (index == NOT_COVERED)) return false;
@@ -180,17 +183,17 @@ struct MathItalicsCorrectionInfo
   }
 
 protected:
-  OffsetTo<Coverage>       coverage;          /* Offset to Coverage table -
-                                                 from the beginning of
-                                                 MathItalicsCorrectionInfo
-                                                 table. */
-  ArrayOf<MathValueRecord> italicsCorrection; /* Array of MathValueRecords
-                                                 defining italics correction
-                                                 values for each
-                                                 covered glyph. */
+  OffsetTo<Coverage>       coverage;		/* Offset to Coverage table -
+						 * from the beginning of
+						 * MathItalicsCorrectionInfo
+						 * table. */
+  ArrayOf<MathValueRecord> italicsCorrection;	/* Array of MathValueRecords
+						 * defining italics correction
+						 * values for each
+						 * covered glyph. */
 
 public:
-  DEFINE_SIZE_ARRAY (2 + 2, italicsCorrection);
+  DEFINE_SIZE_ARRAY (4, italicsCorrection);
 };
 
 struct MathTopAccentAttachment
@@ -199,12 +202,12 @@ struct MathTopAccentAttachment
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
-                  topAccentCoverage.sanitize (c, this) &&
-                  topAccentAttachment.sanitize (c, this));
+		  topAccentCoverage.sanitize (c, this) &&
+		  topAccentAttachment.sanitize (c, this));
   }
 
   inline bool get_value (hb_font_t *font, hb_codepoint_t glyph,
-                         hb_position_t &value) const
+			 hb_position_t &value) const
   {
     unsigned int index = (this+topAccentCoverage).get_coverage (glyph);
     if (likely (index == NOT_COVERED)) return false;
@@ -215,13 +218,13 @@ struct MathTopAccentAttachment
 
 protected:
   OffsetTo<Coverage>       topAccentCoverage;   /* Offset to Coverage table -
-                                                   from the beginning of
-                                                   MathTopAccentAttachment
-                                                   table. */
+						 * from the beginning of
+						 * MathTopAccentAttachment
+						 * table. */
   ArrayOf<MathValueRecord> topAccentAttachment; /* Array of MathValueRecords
-                                                   defining top accent
-                                                   attachment points for each
-                                                   covered glyph. */
+						 * defining top accent
+						 * attachment points for each
+						 * covered glyph. */
 
 public:
   DEFINE_SIZE_ARRAY (2 + 2, topAccentAttachment);
@@ -242,14 +245,14 @@ struct MathKern
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
-                  c->check_array (mathValueRecords,
-                                  mathValueRecords[0].static_size,
-                                  2 * heightCount + 1) &&
-                  sanitize_math_value_records (c));
+		  c->check_array (mathValueRecords,
+				  mathValueRecords[0].static_size,
+				  2 * heightCount + 1) &&
+		  sanitize_math_value_records (c));
   }
 
   inline hb_position_t get_value (hb_font_t *font,
-                                  hb_position_t &correction_height) const
+				  hb_position_t &correction_height) const
   {
     const MathValueRecord* correctionHeight = mathValueRecords;
     const MathValueRecord* kernValue = mathValueRecords + heightCount;
@@ -265,12 +268,12 @@ struct MathKern
     while (count > 0) {
       unsigned int half = count / 2;
       hb_position_t height =
-        correctionHeight[i + half].get_y_value(font, this);
+	correctionHeight[i + half].get_y_value(font, this);
       if (height < correction_height) {
-        i += half + 1;
-        count -= half + 1;
+	i += half + 1;
+	count -= half + 1;
       } else
-        count = half;
+	count = half;
     }
     return kernValue[i].get_x_value(font, this);
   }
@@ -278,11 +281,11 @@ struct MathKern
 protected:
   USHORT          heightCount;
   MathValueRecord mathValueRecords[VAR]; /* Array of correction heights at
-                                            which the kern value changes.
-                                            Sorted by the height value in
-                                            design units. */
-                                         /* Array of kern values corresponding
-                                            to heights. */
+					  * which the kern value changes.
+					  * Sorted by the height value in
+					  * design units. */
+					 /* Array of kern values corresponding
+					  * to heights. */
 
 public:
   DEFINE_SIZE_ARRAY (2, mathValueRecords);
@@ -293,30 +296,30 @@ struct MathKernInfoRecord
   inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
   {
     TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-                  mathKern[HB_OT_MATH_KERN_TOP_RIGHT].sanitize (c, base) &&
-                  mathKern[HB_OT_MATH_KERN_TOP_LEFT].sanitize (c, base) &&
-                  mathKern[HB_OT_MATH_KERN_BOTTOM_RIGHT].sanitize (c, base) &&
-                  mathKern[HB_OT_MATH_KERN_BOTTOM_LEFT].sanitize (c, base));
-  }
 
-  inline bool has_math_kern (hb_ot_math_kern_t kern) const {
-    return mathKern[kern] != 0;
+    unsigned int count = ARRAY_LENGTH (mathKern);
+    for (unsigned int i = 0; i < count; i++)
+      if (unlikely (!mathKern[i].sanitize (c, base)))
+	return_trace (false);
+
+    return_trace (true);
   }
+
   inline const MathKern &get_math_kern (hb_ot_math_kern_t kern,
-                                        const void *base) const {
-    return base+mathKern[kern];
+					const void *base) const
+  {
+    unsigned int idx = kern;
+    if (unlikely (idx > ARRAY_LENGTH (mathKern))) return Null(MathKern);
+    return base+mathKern[idx];
   }
 
 protected:
   /* Offset to MathKern table for each corner -
-     from the beginning of MathKernInfo table. May be NULL. */
-  OffsetTo<MathKern> mathKern[HB_OT_MATH_KERN_BOTTOM_LEFT -
-                              HB_OT_MATH_KERN_TOP_RIGHT + 1];
+   * from the beginning of MathKernInfo table. May be NULL. */
+  OffsetTo<MathKern> mathKern[4];
 
 public:
-  DEFINE_SIZE_STATIC (2 * (HB_OT_MATH_KERN_BOTTOM_LEFT -
-                           HB_OT_MATH_KERN_TOP_RIGHT + 1));
+  DEFINE_SIZE_STATIC (8);
 };
 
 struct MathKernInfo
@@ -325,34 +328,30 @@ struct MathKernInfo
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
-                  mathKernCoverage.sanitize (c, this) &&
-                  mathKernInfoRecords.sanitize (c, this));
+		  mathKernCoverage.sanitize (c, this) &&
+		  mathKernInfoRecords.sanitize (c, this));
   }
 
-  inline bool
-  get_math_kern_info_record (hb_codepoint_t glyph,
-                             const MathKernInfoRecord *&record) const
+  inline const MathKernInfoRecord&
+  get_math_kern_info_record (hb_codepoint_t glyph) const
   {
     unsigned int index = (this+mathKernCoverage).get_coverage (glyph);
-    if (likely (index == NOT_COVERED)) return false;
-    if (unlikely (index >= mathKernInfoRecords.len)) return false;
-    record = &mathKernInfoRecords[index];
-    return true;
+    return mathKernInfoRecords[index];
   }
 
 protected:
-  OffsetTo<Coverage>          mathKernCoverage;    /* Offset to Coverage table -
-                                                      from the beginning of the
-                                                      MathKernInfo table. */
-  ArrayOf<MathKernInfoRecord> mathKernInfoRecords; /* Array of
-                                                      MathKernInfoRecords,
-                                                      per-glyph information for
-                                                      mathematical positioning
-                                                      of subscripts and
-                                                      superscripts. */
+  OffsetTo<Coverage>		mathKernCoverage;    /* Offset to Coverage table -
+						      * from the beginning of the
+						      * MathKernInfo table. */
+  ArrayOf<MathKernInfoRecord>	mathKernInfoRecords; /* Array of
+						      * MathKernInfoRecords,
+						      * per-glyph information for
+						      * mathematical positioning
+						      * of subscripts and
+						      * superscripts. */
 
 public:
-  DEFINE_SIZE_ARRAY (2 + 2, mathKernInfoRecords);
+  DEFINE_SIZE_ARRAY (4, mathKernInfoRecords);
 };
 
 struct MathGlyphInfo
@@ -361,10 +360,10 @@ struct MathGlyphInfo
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
-                  mathItalicsCorrectionInfo.sanitize (c, this) &&
-                  mathTopAccentAttachment.sanitize (c, this) &&
-                  extendedShapeCoverage.sanitize (c, this) &&
-                  mathKernInfo.sanitize(c, this));
+		  mathItalicsCorrectionInfo.sanitize (c, this) &&
+		  mathTopAccentAttachment.sanitize (c, this) &&
+		  extendedShapeCoverage.sanitize (c, this) &&
+		  mathKernInfo.sanitize(c, this));
   }
 
   inline bool has_math_italics_correction_info (void) const {
@@ -398,28 +397,29 @@ struct MathGlyphInfo
 
 protected:
   /* Offset to MathItalicsCorrectionInfo table -
-     from the beginning of MathGlyphInfo table. */
+   * from the beginning of MathGlyphInfo table. */
   OffsetTo<MathItalicsCorrectionInfo> mathItalicsCorrectionInfo;
 
   /* Offset to MathTopAccentAttachment table -
-     from the beginning of MathGlyphInfo table. */
+   * from the beginning of MathGlyphInfo table. */
   OffsetTo<MathTopAccentAttachment> mathTopAccentAttachment;
 
   /* Offset to coverage table for Extended Shape glyphs -
-     from the beginning of MathGlyphInfo table. When the left or right glyph of
-     a box is an extended shape variant, the (ink) box (and not the default
-     position defined by values in MathConstants table) should be used for
-     vertical positioning purposes. May be NULL.. */
+   * from the beginning of MathGlyphInfo table. When the left or right glyph of
+   * a box is an extended shape variant, the (ink) box (and not the default
+   * position defined by values in MathConstants table) should be used for
+   * vertical positioning purposes. May be NULL.. */
   OffsetTo<Coverage> extendedShapeCoverage;
 
    /* Offset to MathKernInfo table -
-      from the beginning of MathGlyphInfo table. */
+    * from the beginning of MathGlyphInfo table. */
   OffsetTo<MathKernInfo> mathKernInfo;
 
 public:
-  DEFINE_SIZE_STATIC (4 * 2);
+  DEFINE_SIZE_STATIC (8);
 };
 
+
 /*
  * MATH -- The MATH Table
  */
@@ -432,9 +432,9 @@ struct MATH
   {
     TRACE_SANITIZE (this);
     return_trace (version.sanitize (c) &&
-                  likely (version.major == 1) &&
-                  mathConstants.sanitize (c, this) &&
-                  mathGlyphInfo.sanitize (c, this));
+		  likely (version.major == 1) &&
+		  mathConstants.sanitize (c, this) &&
+		  mathGlyphInfo.sanitize (c, this));
   }
 
   inline bool has_math_constants (void) const { return mathConstants != 0; }
@@ -447,10 +447,10 @@ struct MATH
     return this+mathGlyphInfo;
   }
 protected:
-  FixedVersion<>version;                 /* Version of the MATH table
-                                          * initially set to 0x00010000u */
-  OffsetTo<MathConstants> mathConstants; /* MathConstants table */
-  OffsetTo<MathGlyphInfo> mathGlyphInfo; /* MathGlyphInfo table */
+  FixedVersion<>version;		/* Version of the MATH table
+					 * initially set to 0x00010000u */
+  OffsetTo<MathConstants> mathConstants;/* MathConstants table */
+  OffsetTo<MathGlyphInfo> mathGlyphInfo;/* MathGlyphInfo table */
 
 public:
   DEFINE_SIZE_STATIC (8);
diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc
index f14611b..3dcdfb6 100644
--- a/src/hb-ot-layout.cc
+++ b/src/hb-ot-layout.cc
@@ -1263,7 +1263,7 @@ hb_ot_layout_has_math_data (hb_face_t *face)
  **/
 hb_position_t
 hb_ot_layout_get_math_constant (hb_font_t *font,
-                                hb_ot_math_constant_t constant)
+				hb_ot_math_constant_t constant)
 {
   const OT::MATH &math = _get_math (font->face);
   return math.has_math_constants() ?
@@ -1282,7 +1282,7 @@ hb_ot_layout_get_math_constant (hb_font_t *font,
  **/
 HB_EXTERN hb_position_t
 hb_ot_layout_get_math_italic_correction (hb_font_t *font,
-                                         hb_codepoint_t glyph)
+					 hb_codepoint_t glyph)
 {
   const OT::MATH &math = _get_math (font->face);
   if (math.has_math_glyph_info()) {
@@ -1290,8 +1290,8 @@ hb_ot_layout_get_math_italic_correction (hb_font_t *font,
     if (glyphInfo.has_math_italics_correction_info()) {
       hb_position_t value;
       if (glyphInfo.get_math_italics_correction_info().get_value(font, glyph,
-                                                                 value))
-        return value;
+								 value))
+	return value;
     }
   }
   return 0;
@@ -1309,7 +1309,7 @@ hb_ot_layout_get_math_italic_correction (hb_font_t *font,
  **/
 HB_EXTERN hb_position_t
 hb_ot_layout_get_math_top_accent_attachment (hb_font_t *font,
-                                             hb_codepoint_t glyph)
+					     hb_codepoint_t glyph)
 {
   const OT::MATH &math = _get_math (font->face);
   if (math.has_math_glyph_info()) {
@@ -1317,8 +1317,8 @@ hb_ot_layout_get_math_top_accent_attachment (hb_font_t *font,
     if (glyphInfo.has_math_top_accent_attachment()) {
       hb_position_t value;
       if (glyphInfo.get_math_top_accent_attachment().get_value(font, glyph,
-                                                               value))
-        return value;
+							       value))
+	return value;
     }
   }
   return 0;
@@ -1336,7 +1336,7 @@ hb_ot_layout_get_math_top_accent_attachment (hb_font_t *font,
  **/
 HB_EXTERN hb_bool_t
 hb_ot_layout_is_math_extended_shape (hb_face_t *face,
-                                     hb_codepoint_t glyph)
+				     hb_codepoint_t glyph)
 {
   const OT::MATH &math = _get_math (face);
   return math.has_math_glyph_info() &&
@@ -1363,21 +1363,17 @@ hb_ot_layout_is_math_extended_shape (hb_face_t *face,
  **/
 HB_EXTERN hb_position_t
 hb_ot_layout_get_math_kerning (hb_font_t *font,
-                               hb_codepoint_t glyph,
-                               hb_ot_math_kern_t kern,
-                               hb_position_t correction_height)
+			       hb_codepoint_t glyph,
+			       hb_ot_math_kern_t kern,
+			       hb_position_t correction_height)
 {
   const OT::MATH &math = _get_math (font->face);
   if (math.has_math_glyph_info()) {
     const OT::MathGlyphInfo &glyphInfo = math.get_math_glyph_info();
     if (glyphInfo.has_math_kern_info()) {
       const OT::MathKernInfo &kernInfo = glyphInfo.get_math_kern_info();
-      const OT::MathKernInfoRecord *kernInfoRecord;
-      if (kernInfo.get_math_kern_info_record(glyph, kernInfoRecord) &&
-          kernInfoRecord->has_math_kern(kern)) {
-        return kernInfoRecord->
-          get_math_kern(kern, &kernInfo).get_value(font, correction_height);
-      }
+      const OT::MathKernInfoRecord &kernInfoRecord = kernInfo.get_math_kern_info_record(glyph);
+      return kernInfoRecord.get_math_kern (kern, &kernInfo).get_value (font, correction_height);
     }
   }
 
diff --git a/src/hb-ot-layout.h b/src/hb-ot-layout.h
index ffb6321..f9ed2d8 100644
--- a/src/hb-ot-layout.h
+++ b/src/hb-ot-layout.h
@@ -308,25 +308,25 @@ hb_ot_layout_has_math_data (hb_face_t *face);
 
 HB_EXTERN hb_position_t
 hb_ot_layout_get_math_constant (hb_font_t *font,
-                                hb_ot_math_constant_t constant);
+				hb_ot_math_constant_t constant);
 
 HB_EXTERN hb_position_t
 hb_ot_layout_get_math_italic_correction (hb_font_t *font,
-                                         hb_codepoint_t glyph);
+					 hb_codepoint_t glyph);
 
 HB_EXTERN hb_position_t
 hb_ot_layout_get_math_top_accent_attachment (hb_font_t *font,
-                                             hb_codepoint_t glyph);
+					     hb_codepoint_t glyph);
 
 HB_EXTERN hb_bool_t
 hb_ot_layout_is_math_extended_shape (hb_face_t *face,
-                                     hb_codepoint_t glyph);
+				     hb_codepoint_t glyph);
 
 HB_EXTERN hb_position_t
 hb_ot_layout_get_math_kerning (hb_font_t *font,
-                               hb_codepoint_t glyph,
-                               hb_ot_math_kern_t kern,
-                               hb_position_t correction_height);
+			       hb_codepoint_t glyph,
+			       hb_ot_math_kern_t kern,
+			       hb_position_t correction_height);
 
 
 HB_END_DECLS
commit d7182d129612c619b9026ee9b15f2dcfada132db
Author: Frédéric Wang <fred.wang at free.fr>
Date:   Thu Aug 25 11:15:31 2016 +0200

    MATH Table: Add API to access glyph info.

diff --git a/src/hb-ot-layout-math-table.hh b/src/hb-ot-layout-math-table.hh
index e65680b..2eb0d92 100644
--- a/src/hb-ot-layout-math-table.hh
+++ b/src/hb-ot-layout-math-table.hh
@@ -159,6 +159,267 @@ public:
   DEFINE_SIZE_STATIC (214);
 };
 
+struct MathItalicsCorrectionInfo
+{
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                  coverage.sanitize (c, this) &&
+                  italicsCorrection.sanitize (c, this));
+  }
+
+  inline bool get_value (hb_font_t *font, hb_codepoint_t glyph,
+                         hb_position_t &value) const
+  {
+    unsigned int index = (this+coverage).get_coverage (glyph);
+    if (likely (index == NOT_COVERED)) return false;
+    if (unlikely (index >= italicsCorrection.len)) return false;
+    value = italicsCorrection[index].get_x_value(font, this);
+    return true;
+  }
+
+protected:
+  OffsetTo<Coverage>       coverage;          /* Offset to Coverage table -
+                                                 from the beginning of
+                                                 MathItalicsCorrectionInfo
+                                                 table. */
+  ArrayOf<MathValueRecord> italicsCorrection; /* Array of MathValueRecords
+                                                 defining italics correction
+                                                 values for each
+                                                 covered glyph. */
+
+public:
+  DEFINE_SIZE_ARRAY (2 + 2, italicsCorrection);
+};
+
+struct MathTopAccentAttachment
+{
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                  topAccentCoverage.sanitize (c, this) &&
+                  topAccentAttachment.sanitize (c, this));
+  }
+
+  inline bool get_value (hb_font_t *font, hb_codepoint_t glyph,
+                         hb_position_t &value) const
+  {
+    unsigned int index = (this+topAccentCoverage).get_coverage (glyph);
+    if (likely (index == NOT_COVERED)) return false;
+    if (unlikely (index >= topAccentAttachment.len)) return false;
+    value = topAccentAttachment[index].get_x_value(font, this);
+    return true;
+  }
+
+protected:
+  OffsetTo<Coverage>       topAccentCoverage;   /* Offset to Coverage table -
+                                                   from the beginning of
+                                                   MathTopAccentAttachment
+                                                   table. */
+  ArrayOf<MathValueRecord> topAccentAttachment; /* Array of MathValueRecords
+                                                   defining top accent
+                                                   attachment points for each
+                                                   covered glyph. */
+
+public:
+  DEFINE_SIZE_ARRAY (2 + 2, topAccentAttachment);
+};
+
+struct MathKern
+{
+  inline bool sanitize_math_value_records (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    unsigned int count = 2 * heightCount + 1;
+    for (unsigned int i = 0; i < count; i++)
+      if (!mathValueRecords[i].sanitize (c, this)) return_trace (false);
+    return_trace (true);
+  }
+
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                  c->check_array (mathValueRecords,
+                                  mathValueRecords[0].static_size,
+                                  2 * heightCount + 1) &&
+                  sanitize_math_value_records (c));
+  }
+
+  inline hb_position_t get_value (hb_font_t *font,
+                                  hb_position_t &correction_height) const
+  {
+    const MathValueRecord* correctionHeight = mathValueRecords;
+    const MathValueRecord* kernValue = mathValueRecords + heightCount;
+    // The description of the MathKern table is a ambiguous, but interpreting
+    // "between the two heights found at those indexes" for 0 < i < len as
+    //
+    //   correctionHeight[i-1] < correction_height <= correctionHeight[i]
+    //
+    // makes the result consistent with the limit cases and we can just use the
+    // binary search algorithm of std::upper_bound:
+    unsigned int count = heightCount;
+    unsigned int i = 0;
+    while (count > 0) {
+      unsigned int half = count / 2;
+      hb_position_t height =
+        correctionHeight[i + half].get_y_value(font, this);
+      if (height < correction_height) {
+        i += half + 1;
+        count -= half + 1;
+      } else
+        count = half;
+    }
+    return kernValue[i].get_x_value(font, this);
+  }
+
+protected:
+  USHORT          heightCount;
+  MathValueRecord mathValueRecords[VAR]; /* Array of correction heights at
+                                            which the kern value changes.
+                                            Sorted by the height value in
+                                            design units. */
+                                         /* Array of kern values corresponding
+                                            to heights. */
+
+public:
+  DEFINE_SIZE_ARRAY (2, mathValueRecords);
+};
+
+struct MathKernInfoRecord
+{
+  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                  mathKern[HB_OT_MATH_KERN_TOP_RIGHT].sanitize (c, base) &&
+                  mathKern[HB_OT_MATH_KERN_TOP_LEFT].sanitize (c, base) &&
+                  mathKern[HB_OT_MATH_KERN_BOTTOM_RIGHT].sanitize (c, base) &&
+                  mathKern[HB_OT_MATH_KERN_BOTTOM_LEFT].sanitize (c, base));
+  }
+
+  inline bool has_math_kern (hb_ot_math_kern_t kern) const {
+    return mathKern[kern] != 0;
+  }
+  inline const MathKern &get_math_kern (hb_ot_math_kern_t kern,
+                                        const void *base) const {
+    return base+mathKern[kern];
+  }
+
+protected:
+  /* Offset to MathKern table for each corner -
+     from the beginning of MathKernInfo table. May be NULL. */
+  OffsetTo<MathKern> mathKern[HB_OT_MATH_KERN_BOTTOM_LEFT -
+                              HB_OT_MATH_KERN_TOP_RIGHT + 1];
+
+public:
+  DEFINE_SIZE_STATIC (2 * (HB_OT_MATH_KERN_BOTTOM_LEFT -
+                           HB_OT_MATH_KERN_TOP_RIGHT + 1));
+};
+
+struct MathKernInfo
+{
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                  mathKernCoverage.sanitize (c, this) &&
+                  mathKernInfoRecords.sanitize (c, this));
+  }
+
+  inline bool
+  get_math_kern_info_record (hb_codepoint_t glyph,
+                             const MathKernInfoRecord *&record) const
+  {
+    unsigned int index = (this+mathKernCoverage).get_coverage (glyph);
+    if (likely (index == NOT_COVERED)) return false;
+    if (unlikely (index >= mathKernInfoRecords.len)) return false;
+    record = &mathKernInfoRecords[index];
+    return true;
+  }
+
+protected:
+  OffsetTo<Coverage>          mathKernCoverage;    /* Offset to Coverage table -
+                                                      from the beginning of the
+                                                      MathKernInfo table. */
+  ArrayOf<MathKernInfoRecord> mathKernInfoRecords; /* Array of
+                                                      MathKernInfoRecords,
+                                                      per-glyph information for
+                                                      mathematical positioning
+                                                      of subscripts and
+                                                      superscripts. */
+
+public:
+  DEFINE_SIZE_ARRAY (2 + 2, mathKernInfoRecords);
+};
+
+struct MathGlyphInfo
+{
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                  mathItalicsCorrectionInfo.sanitize (c, this) &&
+                  mathTopAccentAttachment.sanitize (c, this) &&
+                  extendedShapeCoverage.sanitize (c, this) &&
+                  mathKernInfo.sanitize(c, this));
+  }
+
+  inline bool has_math_italics_correction_info (void) const {
+    return mathItalicsCorrectionInfo != 0;
+  }
+  inline const MathItalicsCorrectionInfo&
+  get_math_italics_correction_info (void) const {
+    return this+mathItalicsCorrectionInfo;
+  }
+
+  inline bool has_math_top_accent_attachment (void) const {
+    return mathTopAccentAttachment != 0;
+  }
+  inline const MathTopAccentAttachment&
+  get_math_top_accent_attachment (void) const {
+    return this+mathTopAccentAttachment;
+  }
+
+  inline bool is_extended_shape (hb_codepoint_t glyph) const
+  {
+    if (likely (extendedShapeCoverage == 0)) return false;
+    unsigned int index = (this+extendedShapeCoverage).get_coverage (glyph);
+    if (likely (index == NOT_COVERED)) return false;
+    return true;
+  }
+
+  inline bool has_math_kern_info (void) const { return mathKernInfo != 0; }
+  inline const MathKernInfo &get_math_kern_info (void) const {
+    return this+mathKernInfo;
+  }
+
+protected:
+  /* Offset to MathItalicsCorrectionInfo table -
+     from the beginning of MathGlyphInfo table. */
+  OffsetTo<MathItalicsCorrectionInfo> mathItalicsCorrectionInfo;
+
+  /* Offset to MathTopAccentAttachment table -
+     from the beginning of MathGlyphInfo table. */
+  OffsetTo<MathTopAccentAttachment> mathTopAccentAttachment;
+
+  /* Offset to coverage table for Extended Shape glyphs -
+     from the beginning of MathGlyphInfo table. When the left or right glyph of
+     a box is an extended shape variant, the (ink) box (and not the default
+     position defined by values in MathConstants table) should be used for
+     vertical positioning purposes. May be NULL.. */
+  OffsetTo<Coverage> extendedShapeCoverage;
+
+   /* Offset to MathKernInfo table -
+      from the beginning of MathGlyphInfo table. */
+  OffsetTo<MathKernInfo> mathKernInfo;
+
+public:
+  DEFINE_SIZE_STATIC (4 * 2);
+};
+
 /*
  * MATH -- The MATH Table
  */
@@ -172,7 +433,8 @@ struct MATH
     TRACE_SANITIZE (this);
     return_trace (version.sanitize (c) &&
                   likely (version.major == 1) &&
-                  mathConstants.sanitize (c, this));
+                  mathConstants.sanitize (c, this) &&
+                  mathGlyphInfo.sanitize (c, this));
   }
 
   inline bool has_math_constants (void) const { return mathConstants != 0; }
@@ -180,13 +442,18 @@ struct MATH
     return this+mathConstants;
   }
 
+  inline bool has_math_glyph_info (void) const { return mathGlyphInfo != 0; }
+  inline const MathGlyphInfo &get_math_glyph_info (void) const {
+    return this+mathGlyphInfo;
+  }
 protected:
   FixedVersion<>version;                 /* Version of the MATH table
                                           * initially set to 0x00010000u */
   OffsetTo<MathConstants> mathConstants; /* MathConstants table */
+  OffsetTo<MathGlyphInfo> mathGlyphInfo; /* MathGlyphInfo table */
 
 public:
-  DEFINE_SIZE_STATIC (6);
+  DEFINE_SIZE_STATIC (8);
 };
 
 } /* mathspace OT */
diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc
index 2ae1388..f14611b 100644
--- a/src/hb-ot-layout.cc
+++ b/src/hb-ot-layout.cc
@@ -1269,3 +1269,117 @@ hb_ot_layout_get_math_constant (hb_font_t *font,
   return math.has_math_constants() ?
     math.get_math_constants().get_value(font, constant) : 0;
 }
+
+/**
+ * hb_ot_layout_get_math_italic_correction:
+ *
+ * @font: #hb_font_t from which to retrieve the value
+ * @glyph: glyph index from which to retrieve the value
+ *
+ * Return value: the italic correction of the glyph or 0
+ *
+ * Since: ????
+ **/
+HB_EXTERN hb_position_t
+hb_ot_layout_get_math_italic_correction (hb_font_t *font,
+                                         hb_codepoint_t glyph)
+{
+  const OT::MATH &math = _get_math (font->face);
+  if (math.has_math_glyph_info()) {
+    const OT::MathGlyphInfo &glyphInfo = math.get_math_glyph_info();
+    if (glyphInfo.has_math_italics_correction_info()) {
+      hb_position_t value;
+      if (glyphInfo.get_math_italics_correction_info().get_value(font, glyph,
+                                                                 value))
+        return value;
+    }
+  }
+  return 0;
+}
+
+/**
+ * hb_ot_layout_get_math_top_accent_attachment:
+ *
+ * @font: #hb_font_t from which to retrieve the value
+ * @glyph: glyph index from which to retrieve the value
+ *
+ * Return value: the top accent attachment of the glyph or 0
+ *
+ * Since: ????
+ **/
+HB_EXTERN hb_position_t
+hb_ot_layout_get_math_top_accent_attachment (hb_font_t *font,
+                                             hb_codepoint_t glyph)
+{
+  const OT::MATH &math = _get_math (font->face);
+  if (math.has_math_glyph_info()) {
+    const OT::MathGlyphInfo &glyphInfo = math.get_math_glyph_info();
+    if (glyphInfo.has_math_top_accent_attachment()) {
+      hb_position_t value;
+      if (glyphInfo.get_math_top_accent_attachment().get_value(font, glyph,
+                                                               value))
+        return value;
+    }
+  }
+  return 0;
+}
+
+/**
+ * hb_ot_layout_is_math_extended_shape:
+ *
+ * @font: a #hb_font_t to test
+ * @glyph: a glyph index to test
+ *
+ * Return value: #TRUE if the glyph is an extended shape and #FALSE otherwise
+ *
+ * Since: ????
+ **/
+HB_EXTERN hb_bool_t
+hb_ot_layout_is_math_extended_shape (hb_face_t *face,
+                                     hb_codepoint_t glyph)
+{
+  const OT::MATH &math = _get_math (face);
+  return math.has_math_glyph_info() &&
+    math.get_math_glyph_info().is_extended_shape(glyph);
+}
+
+/**
+ * hb_ot_layout_get_math_kerning:
+ *
+ * @font: #hb_font_t from which to retrieve the value
+ * @glyph: glyph index from which to retrieve the value
+ * @kern: the #hb_ot_math_kern_t from which to retrieve the value
+ * @correction_height: the correction height to use to determine the kerning.
+ *
+ * This function tries to retrieve the MathKern table for the specified font,
+ * glyph and #hb_ot_math_kern_t. Then it browses the list of heights from the
+ * MathKern table to find one value that is greater or equal to specified
+ * correction_height. If one is found the corresponding value from the list of
+ * kerns is returned and otherwise the last kern value is returned.
+ *
+ * Return value: requested kerning or 0
+ *
+ * Since: ????
+ **/
+HB_EXTERN hb_position_t
+hb_ot_layout_get_math_kerning (hb_font_t *font,
+                               hb_codepoint_t glyph,
+                               hb_ot_math_kern_t kern,
+                               hb_position_t correction_height)
+{
+  const OT::MATH &math = _get_math (font->face);
+  if (math.has_math_glyph_info()) {
+    const OT::MathGlyphInfo &glyphInfo = math.get_math_glyph_info();
+    if (glyphInfo.has_math_kern_info()) {
+      const OT::MathKernInfo &kernInfo = glyphInfo.get_math_kern_info();
+      const OT::MathKernInfoRecord *kernInfoRecord;
+      if (kernInfo.get_math_kern_info_record(glyph, kernInfoRecord) &&
+          kernInfoRecord->has_math_kern(kern)) {
+        return kernInfoRecord->
+          get_math_kern(kern, &kernInfo).get_value(font, correction_height);
+      }
+    }
+  }
+
+  return 0;
+}
diff --git a/src/hb-ot-layout.h b/src/hb-ot-layout.h
index 501082e..ffb6321 100644
--- a/src/hb-ot-layout.h
+++ b/src/hb-ot-layout.h
@@ -310,6 +310,24 @@ HB_EXTERN hb_position_t
 hb_ot_layout_get_math_constant (hb_font_t *font,
                                 hb_ot_math_constant_t constant);
 
+HB_EXTERN hb_position_t
+hb_ot_layout_get_math_italic_correction (hb_font_t *font,
+                                         hb_codepoint_t glyph);
+
+HB_EXTERN hb_position_t
+hb_ot_layout_get_math_top_accent_attachment (hb_font_t *font,
+                                             hb_codepoint_t glyph);
+
+HB_EXTERN hb_bool_t
+hb_ot_layout_is_math_extended_shape (hb_face_t *face,
+                                     hb_codepoint_t glyph);
+
+HB_EXTERN hb_position_t
+hb_ot_layout_get_math_kerning (hb_font_t *font,
+                               hb_codepoint_t glyph,
+                               hb_ot_math_kern_t kern,
+                               hb_position_t correction_height);
+
 
 HB_END_DECLS
 
diff --git a/src/hb-ot-math.h b/src/hb-ot-math.h
index 7f0ec27..a62b4b6 100644
--- a/src/hb-ot-math.h
+++ b/src/hb-ot-math.h
@@ -95,6 +95,13 @@ typedef enum {
   HB_OT_MATH_CONSTANT_RADICAL_DEGREE_BOTTOM_RAISE_PERCENT = 55
 } hb_ot_math_constant_t;
 
+typedef enum {
+  HB_OT_MATH_KERN_TOP_RIGHT = 0,
+  HB_OT_MATH_KERN_TOP_LEFT = 1,
+  HB_OT_MATH_KERN_BOTTOM_RIGHT = 2,
+  HB_OT_MATH_KERN_BOTTOM_LEFT = 3
+} hb_ot_math_kern_t;
+
 HB_END_DECLS
 
 #endif /* HB_OT_MATH_H */
diff --git a/test/api/fonts/MathTestFontPartial1.otf b/test/api/fonts/MathTestFontPartial1.otf
new file mode 100644
index 0000000..b3bf36e
Binary files /dev/null and b/test/api/fonts/MathTestFontPartial1.otf differ
diff --git a/test/api/fonts/MathTestFontPartial2.otf b/test/api/fonts/MathTestFontPartial2.otf
new file mode 100644
index 0000000..4607c11
Binary files /dev/null and b/test/api/fonts/MathTestFontPartial2.otf differ
diff --git a/test/api/fonts/MathTestFontPartial3.otf b/test/api/fonts/MathTestFontPartial3.otf
new file mode 100644
index 0000000..ca18a9a
Binary files /dev/null and b/test/api/fonts/MathTestFontPartial3.otf differ
diff --git a/test/api/test-ot-layout-math.c b/test/api/test-ot-layout-math.c
index 219959b..5ba583f 100644
--- a/test/api/test-ot-layout-math.c
+++ b/test/api/test-ot-layout-math.c
@@ -160,6 +160,157 @@ test_get_math_constant (void)
   cleanupFreeType();
 }
 
+static void
+test_get_math_italic_correction (void)
+{
+  hb_codepoint_t glyph;
+  initFreeType();
+
+  openFont("fonts/MathTestFontEmpty.otf");
+  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
+  g_assert_cmpint(hb_ot_layout_get_math_italic_correction (hb_font, glyph), ==, 0); // MathGlyphInfo not available
+  closeFont();
+
+  openFont("fonts/MathTestFontPartial1.otf");
+  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
+  g_assert_cmpint(hb_ot_layout_get_math_italic_correction (hb_font, glyph), ==, 0); // MathGlyphInfo empty
+  closeFont();
+
+  openFont("fonts/MathTestFontPartial2.otf");
+  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
+  g_assert_cmpint(hb_ot_layout_get_math_italic_correction (hb_font, glyph), ==, 0); // MathItalicsCorrectionInfo empty
+  closeFont();
+
+  openFont("fonts/MathTestFontFull.otf");
+  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
+  g_assert_cmpint(hb_ot_layout_get_math_italic_correction (hb_font, glyph), ==, 0); // Glyph without italic correction.
+  g_assert(hb_font_get_glyph_from_name (hb_font, "A", -1, &glyph));
+  g_assert_cmpint(hb_ot_layout_get_math_italic_correction (hb_font, glyph), ==, 197);
+  g_assert(hb_font_get_glyph_from_name (hb_font, "B", -1, &glyph));
+  g_assert_cmpint(hb_ot_layout_get_math_italic_correction (hb_font, glyph), ==, 150);
+  g_assert(hb_font_get_glyph_from_name (hb_font, "C", -1, &glyph));
+  g_assert_cmpint(hb_ot_layout_get_math_italic_correction (hb_font, glyph), ==, 452);
+  closeFont();
+
+  cleanupFreeType();
+
+}
+
+static void
+test_get_math_top_accent_attachment (void)
+{
+  hb_codepoint_t glyph;
+  initFreeType();
+
+  openFont("fonts/MathTestFontEmpty.otf");
+  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
+  g_assert_cmpint(hb_ot_layout_get_math_top_accent_attachment (hb_font, glyph), ==, 0); // MathGlyphInfo not available
+  closeFont();
+
+  openFont("fonts/MathTestFontPartial1.otf");
+  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
+  g_assert_cmpint(hb_ot_layout_get_math_top_accent_attachment (hb_font, glyph), ==, 0); // MathGlyphInfo empty
+  closeFont();
+
+  openFont("fonts/MathTestFontPartial2.otf");
+  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
+  g_assert_cmpint(hb_ot_layout_get_math_top_accent_attachment (hb_font, glyph), ==, 0); // MathTopAccentAttachment empty
+  closeFont();
+
+  openFont("fonts/MathTestFontFull.otf");
+  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
+  g_assert_cmpint(hb_ot_layout_get_math_top_accent_attachment (hb_font, glyph), ==, 0); // Glyph without top accent attachment.
+  g_assert(hb_font_get_glyph_from_name (hb_font, "D", -1, &glyph));
+  g_assert_cmpint(hb_ot_layout_get_math_top_accent_attachment (hb_font, glyph), ==, 374);
+  g_assert(hb_font_get_glyph_from_name (hb_font, "E", -1, &glyph));
+  g_assert_cmpint(hb_ot_layout_get_math_top_accent_attachment (hb_font, glyph), ==, 346);
+  g_assert(hb_font_get_glyph_from_name (hb_font, "F", -1, &glyph));
+  g_assert_cmpint(hb_ot_layout_get_math_top_accent_attachment (hb_font, glyph), ==, 318);
+  closeFont();
+
+  cleanupFreeType();
+}
+
+static void
+test_is_math_extended_shape (void)
+{
+  hb_codepoint_t glyph;
+  initFreeType();
+
+  openFont("fonts/MathTestFontEmpty.otf");
+  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
+  g_assert(!hb_ot_layout_is_math_extended_shape (hb_face, glyph)); // MathGlyphInfo not available
+  closeFont();
+
+  openFont("fonts/MathTestFontPartial1.otf");
+  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
+  g_assert(!hb_ot_layout_is_math_extended_shape (hb_face, glyph)); // MathGlyphInfo empty
+  closeFont();
+
+  openFont("fonts/MathTestFontFull.otf");
+  g_assert(hb_font_get_glyph_from_name (hb_font, "G", -1, &glyph));
+  g_assert(!hb_ot_layout_is_math_extended_shape (hb_face, glyph));
+  g_assert(hb_font_get_glyph_from_name (hb_font, "H", -1, &glyph));
+  g_assert(hb_ot_layout_is_math_extended_shape (hb_face, glyph));
+  closeFont();
+
+  cleanupFreeType();
+}
+
+static void
+test_get_math_kerning (void)
+{
+  hb_codepoint_t glyph;
+  initFreeType();
+
+  openFont("fonts/MathTestFontEmpty.otf");
+  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
+  g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 0), ==, 0); // MathGlyphInfo not available
+  g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_LEFT, 0), ==, 0); // MathGlyphInfo not available
+  g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_RIGHT, 0), ==, 0); // MathGlyphInfo not available
+  g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_LEFT, 0), ==, 0); // MathGlyphInfo not available
+  closeFont();
+
+  openFont("fonts/MathTestFontPartial2.otf");
+  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
+  g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 0), ==, 0); // MathKernInfo empty
+  g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_LEFT, 0), ==, 0); // MathKernInfo empty
+  g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_RIGHT, 0), ==, 0); // MathKernInfo empty
+  g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_LEFT, 0), ==, 0); // MathKernInfo empty
+  closeFont();
+
+  openFont("fonts/MathTestFontPartial3.otf");
+  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
+  g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 0), ==, 0); // MathKernInfoRecords empty
+  g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_LEFT, 0), ==, 0); // MathKernInfoRecords empty
+  g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_RIGHT, 0), ==, 0); // MathKernInfoRecords empty
+  g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_LEFT, 0), ==, 0); // MathKernInfoRecords empty
+  closeFont();
+
+  openFont("fonts/MathTestFontFull.otf");
+  g_assert(hb_font_get_glyph_from_name (hb_font, "I", -1, &glyph));
+
+  g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 7), ==, 31); // lower than min heigth
+  g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 14), ==, 31); // equal to min height
+  g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 20), ==, 52);
+  g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 23), ==, 52);
+  g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 31), ==, 73);
+  g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 32), ==, 73);
+  g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 86), ==, 199); // equal to max height
+  g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 91), ==, 220); // larger than max height
+  g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 96), ==, 220); // larger than max height
+
+  g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 39), ==, 94); // top right
+  g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_LEFT, 39), ==, 55); // top left
+  g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_RIGHT, 39), ==, 22); // bottom right
+  g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_LEFT, 39), ==, 50); // bottom left
+
+  closeFont();
+
+  cleanupFreeType();
+}
+
+
 int
 main (int argc, char **argv)
 {
@@ -167,6 +318,10 @@ main (int argc, char **argv)
 
   hb_test_add (test_has_math_data);
   hb_test_add (test_get_math_constant);
+  hb_test_add (test_get_math_italic_correction);
+  hb_test_add (test_get_math_top_accent_attachment);
+  hb_test_add (test_is_math_extended_shape);
+  hb_test_add (test_get_math_kerning);
 
   return hb_test_run();
 }
commit 6fd2fe418dc838743f0d4a8a2222cdcaf587500c
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Sep 26 11:24:39 2016 +0100

    [MATH] Fixup math constants commit a bit more

diff --git a/src/hb-ot-layout-math-table.hh b/src/hb-ot-layout-math-table.hh
index c215d32..e65680b 100644
--- a/src/hb-ot-layout-math-table.hh
+++ b/src/hb-ot-layout-math-table.hh
@@ -62,9 +62,7 @@ struct MathConstants
   inline bool sanitize_math_value_records (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    unsigned int count =
-      HB_OT_MATH_CONSTANT_RADICAL_KERN_AFTER_DEGREE -
-      HB_OT_MATH_CONSTANT_MATH_LEADING + 1;
+    unsigned int count = ARRAY_LENGTH (mathValueRecords);
     for (unsigned int i = 0; i < count; i++)
       if (!mathValueRecords[i].sanitize (c, this)) return_trace (false);
     return_trace (true);
@@ -79,6 +77,11 @@ struct MathConstants
   inline hb_position_t get_value (hb_font_t *font, hb_ot_math_constant_t constant) const
   {
     switch (constant) {
+
+    case HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN:
+    case HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN:
+      return percentScaleDown[constant - HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN];
+
     case HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT:
     case HB_OT_MATH_CONSTANT_DISPLAY_OPERATOR_MIN_HEIGHT:
       return font->em_scale_y (minHeight[constant - HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT]);
@@ -138,27 +141,22 @@ struct MathConstants
     case HB_OT_MATH_CONSTANT_UPPER_LIMIT_GAP_MIN:
       return mathValueRecords[constant - HB_OT_MATH_CONSTANT_MATH_LEADING].get_y_value(font, this);
 
-    case HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN:
-    case HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN:
-      return percentScaleDown[constant - HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN];
-
     case HB_OT_MATH_CONSTANT_RADICAL_DEGREE_BOTTOM_RAISE_PERCENT:
       return radicalDegreeBottomRaisePercent;
+
     default:
       return 0;
     }
   }
 
 protected:
-  SHORT percentScaleDown[HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN - HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN + 1];
-  USHORT minHeight[HB_OT_MATH_CONSTANT_DISPLAY_OPERATOR_MIN_HEIGHT - HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT + 1];
-  MathValueRecord mathValueRecords[HB_OT_MATH_CONSTANT_RADICAL_KERN_AFTER_DEGREE - HB_OT_MATH_CONSTANT_MATH_LEADING + 1];
+  SHORT percentScaleDown[2];
+  USHORT minHeight[2];
+  MathValueRecord mathValueRecords[51];
   SHORT radicalDegreeBottomRaisePercent;
 
 public:
-  DEFINE_SIZE_STATIC (2 * (HB_OT_MATH_CONSTANT_DISPLAY_OPERATOR_MIN_HEIGHT - HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN + 1) +
-                      4 * (HB_OT_MATH_CONSTANT_RADICAL_KERN_AFTER_DEGREE - HB_OT_MATH_CONSTANT_MATH_LEADING + 1) +
-                      2);
+  DEFINE_SIZE_STATIC (214);
 };
 
 /*
commit 1a381153a2e6a15bded1f8e31f6b0e0cadb078af
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Sep 26 11:15:59 2016 +0100

    [MATH] Fixups for math constants commit

diff --git a/src/hb-ot-layout-math-table.hh b/src/hb-ot-layout-math-table.hh
index 02a1d45..c215d32 100644
--- a/src/hb-ot-layout-math-table.hh
+++ b/src/hb-ot-layout-math-table.hh
@@ -36,13 +36,10 @@ namespace OT {
 
 struct MathValueRecord
 {
-  inline hb_position_t get_value (hb_font_t *font, bool horizontal,
-                                  const void *base) const
-  {
-    return horizontal ?
-      font->em_scale_x (value) + (base+deviceTable).get_x_delta (font) :
-      font->em_scale_y (value) + (base+deviceTable).get_y_delta (font);
-  }
+  inline hb_position_t get_x_value (hb_font_t *font, const void *base) const
+  { return font->em_scale_x (value) + (base+deviceTable).get_x_delta (font); }
+  inline hb_position_t get_y_value (hb_font_t *font, const void *base) const
+  { return font->em_scale_y (value) + (base+deviceTable).get_y_delta (font); }
 
   inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
   {
@@ -57,7 +54,7 @@ protected:
                                    Suggested format for device table is 1. */
 
 public:
-  DEFINE_SIZE_STATIC (2 * 2);
+  DEFINE_SIZE_STATIC (4);
 };
 
 struct MathConstants
@@ -90,7 +87,7 @@ struct MathConstants
     case HB_OT_MATH_CONSTANT_RADICAL_KERN_BEFORE_DEGREE:
     case HB_OT_MATH_CONSTANT_SKEWED_FRACTION_HORIZONTAL_GAP:
     case HB_OT_MATH_CONSTANT_SPACE_AFTER_SCRIPT:
-      return mathValueRecords[constant - HB_OT_MATH_CONSTANT_MATH_LEADING].get_value(font, true, this);
+      return mathValueRecords[constant - HB_OT_MATH_CONSTANT_MATH_LEADING].get_x_value(font, this);
 
     case HB_OT_MATH_CONSTANT_ACCENT_BASE_HEIGHT:
     case HB_OT_MATH_CONSTANT_AXIS_HEIGHT:
@@ -139,7 +136,7 @@ struct MathConstants
     case HB_OT_MATH_CONSTANT_UNDERBAR_VERTICAL_GAP:
     case HB_OT_MATH_CONSTANT_UPPER_LIMIT_BASELINE_RISE_MIN:
     case HB_OT_MATH_CONSTANT_UPPER_LIMIT_GAP_MIN:
-      return mathValueRecords[constant - HB_OT_MATH_CONSTANT_MATH_LEADING].get_value(font, false, this);
+      return mathValueRecords[constant - HB_OT_MATH_CONSTANT_MATH_LEADING].get_y_value(font, this);
 
     case HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN:
     case HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN:
@@ -147,6 +144,8 @@ struct MathConstants
 
     case HB_OT_MATH_CONSTANT_RADICAL_DEGREE_BOTTOM_RAISE_PERCENT:
       return radicalDegreeBottomRaisePercent;
+    default:
+      return 0;
     }
   }
 
commit 319ff59161e6b027391f8b9fdce0db6dd44cc20d
Author: Frédéric Wang <fred.wang at free.fr>
Date:   Thu Aug 25 11:06:41 2016 +0200

    MATH Table: Add API to access math contants.

diff --git a/src/Makefile.sources b/src/Makefile.sources
index cd30b12..5c695c5 100644
--- a/src/Makefile.sources
+++ b/src/Makefile.sources
@@ -112,6 +112,7 @@ HB_OT_headers = \
 	hb-ot.h \
 	hb-ot-font.h \
 	hb-ot-layout.h \
+	hb-ot-math.h \
 	hb-ot-shape.h \
 	hb-ot-tag.h \
 	$(NULL)
diff --git a/src/hb-ot-layout-math-table.hh b/src/hb-ot-layout-math-table.hh
index 7b3c0c7..02a1d45 100644
--- a/src/hb-ot-layout-math-table.hh
+++ b/src/hb-ot-layout-math-table.hh
@@ -29,9 +29,139 @@
 
 #include "hb-open-type-private.hh"
 #include "hb-ot-layout-common-private.hh"
+#include "hb-ot-math.h"
 
 namespace OT {
 
+
+struct MathValueRecord
+{
+  inline hb_position_t get_value (hb_font_t *font, bool horizontal,
+                                  const void *base) const
+  {
+    return horizontal ?
+      font->em_scale_x (value) + (base+deviceTable).get_x_delta (font) :
+      font->em_scale_y (value) + (base+deviceTable).get_y_delta (font);
+  }
+
+  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && deviceTable.sanitize (c, base));
+  }
+
+protected:
+  SHORT            value;       /* The X or Y value in design units */
+  OffsetTo<Device> deviceTable; /* Offset to the device table - from the
+                                   beginning of parent table. May be NULL.
+                                   Suggested format for device table is 1. */
+
+public:
+  DEFINE_SIZE_STATIC (2 * 2);
+};
+
+struct MathConstants
+{
+  inline bool sanitize_math_value_records (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    unsigned int count =
+      HB_OT_MATH_CONSTANT_RADICAL_KERN_AFTER_DEGREE -
+      HB_OT_MATH_CONSTANT_MATH_LEADING + 1;
+    for (unsigned int i = 0; i < count; i++)
+      if (!mathValueRecords[i].sanitize (c, this)) return_trace (false);
+    return_trace (true);
+  }
+
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && sanitize_math_value_records(c));
+  }
+
+  inline hb_position_t get_value (hb_font_t *font, hb_ot_math_constant_t constant) const
+  {
+    switch (constant) {
+    case HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT:
+    case HB_OT_MATH_CONSTANT_DISPLAY_OPERATOR_MIN_HEIGHT:
+      return font->em_scale_y (minHeight[constant - HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT]);
+
+    case HB_OT_MATH_CONSTANT_RADICAL_KERN_AFTER_DEGREE:
+    case HB_OT_MATH_CONSTANT_RADICAL_KERN_BEFORE_DEGREE:
+    case HB_OT_MATH_CONSTANT_SKEWED_FRACTION_HORIZONTAL_GAP:
+    case HB_OT_MATH_CONSTANT_SPACE_AFTER_SCRIPT:
+      return mathValueRecords[constant - HB_OT_MATH_CONSTANT_MATH_LEADING].get_value(font, true, this);
+
+    case HB_OT_MATH_CONSTANT_ACCENT_BASE_HEIGHT:
+    case HB_OT_MATH_CONSTANT_AXIS_HEIGHT:
+    case HB_OT_MATH_CONSTANT_FLATTENED_ACCENT_BASE_HEIGHT:
+    case HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_DISPLAY_STYLE_SHIFT_DOWN:
+    case HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_GAP_MIN:
+    case HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_SHIFT_DOWN:
+    case HB_OT_MATH_CONSTANT_FRACTION_DENOM_DISPLAY_STYLE_GAP_MIN:
+    case HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_DISPLAY_STYLE_SHIFT_UP:
+    case HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_GAP_MIN:
+    case HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_SHIFT_UP:
+    case HB_OT_MATH_CONSTANT_FRACTION_NUM_DISPLAY_STYLE_GAP_MIN:
+    case HB_OT_MATH_CONSTANT_FRACTION_RULE_THICKNESS:
+    case HB_OT_MATH_CONSTANT_LOWER_LIMIT_BASELINE_DROP_MIN:
+    case HB_OT_MATH_CONSTANT_LOWER_LIMIT_GAP_MIN:
+    case HB_OT_MATH_CONSTANT_MATH_LEADING:
+    case HB_OT_MATH_CONSTANT_OVERBAR_EXTRA_ASCENDER:
+    case HB_OT_MATH_CONSTANT_OVERBAR_RULE_THICKNESS:
+    case HB_OT_MATH_CONSTANT_OVERBAR_VERTICAL_GAP:
+    case HB_OT_MATH_CONSTANT_RADICAL_DISPLAY_STYLE_VERTICAL_GAP:
+    case HB_OT_MATH_CONSTANT_RADICAL_EXTRA_ASCENDER:
+    case HB_OT_MATH_CONSTANT_RADICAL_RULE_THICKNESS:
+    case HB_OT_MATH_CONSTANT_RADICAL_VERTICAL_GAP:
+    case HB_OT_MATH_CONSTANT_SKEWED_FRACTION_VERTICAL_GAP:
+    case HB_OT_MATH_CONSTANT_STACK_BOTTOM_DISPLAY_STYLE_SHIFT_DOWN:
+    case HB_OT_MATH_CONSTANT_STACK_BOTTOM_SHIFT_DOWN:
+    case HB_OT_MATH_CONSTANT_STACK_DISPLAY_STYLE_GAP_MIN:
+    case HB_OT_MATH_CONSTANT_STACK_GAP_MIN:
+    case HB_OT_MATH_CONSTANT_STACK_TOP_DISPLAY_STYLE_SHIFT_UP:
+    case HB_OT_MATH_CONSTANT_STACK_TOP_SHIFT_UP:
+    case HB_OT_MATH_CONSTANT_STRETCH_STACK_BOTTOM_SHIFT_DOWN:
+    case HB_OT_MATH_CONSTANT_STRETCH_STACK_GAP_ABOVE_MIN:
+    case HB_OT_MATH_CONSTANT_STRETCH_STACK_GAP_BELOW_MIN:
+    case HB_OT_MATH_CONSTANT_STRETCH_STACK_TOP_SHIFT_UP:
+    case HB_OT_MATH_CONSTANT_SUBSCRIPT_BASELINE_DROP_MIN:
+    case HB_OT_MATH_CONSTANT_SUBSCRIPT_SHIFT_DOWN:
+    case HB_OT_MATH_CONSTANT_SUBSCRIPT_TOP_MAX:
+    case HB_OT_MATH_CONSTANT_SUB_SUPERSCRIPT_GAP_MIN:
+    case HB_OT_MATH_CONSTANT_SUPERSCRIPT_BASELINE_DROP_MAX:
+    case HB_OT_MATH_CONSTANT_SUPERSCRIPT_BOTTOM_MAX_WITH_SUBSCRIPT:
+    case HB_OT_MATH_CONSTANT_SUPERSCRIPT_BOTTOM_MIN:
+    case HB_OT_MATH_CONSTANT_SUPERSCRIPT_SHIFT_UP:
+    case HB_OT_MATH_CONSTANT_SUPERSCRIPT_SHIFT_UP_CRAMPED:
+    case HB_OT_MATH_CONSTANT_UNDERBAR_EXTRA_DESCENDER:
+    case HB_OT_MATH_CONSTANT_UNDERBAR_RULE_THICKNESS:
+    case HB_OT_MATH_CONSTANT_UNDERBAR_VERTICAL_GAP:
+    case HB_OT_MATH_CONSTANT_UPPER_LIMIT_BASELINE_RISE_MIN:
+    case HB_OT_MATH_CONSTANT_UPPER_LIMIT_GAP_MIN:
+      return mathValueRecords[constant - HB_OT_MATH_CONSTANT_MATH_LEADING].get_value(font, false, this);
+
+    case HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN:
+    case HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN:
+      return percentScaleDown[constant - HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN];
+
+    case HB_OT_MATH_CONSTANT_RADICAL_DEGREE_BOTTOM_RAISE_PERCENT:
+      return radicalDegreeBottomRaisePercent;
+    }
+  }
+
+protected:
+  SHORT percentScaleDown[HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN - HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN + 1];
+  USHORT minHeight[HB_OT_MATH_CONSTANT_DISPLAY_OPERATOR_MIN_HEIGHT - HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT + 1];
+  MathValueRecord mathValueRecords[HB_OT_MATH_CONSTANT_RADICAL_KERN_AFTER_DEGREE - HB_OT_MATH_CONSTANT_MATH_LEADING + 1];
+  SHORT radicalDegreeBottomRaisePercent;
+
+public:
+  DEFINE_SIZE_STATIC (2 * (HB_OT_MATH_CONSTANT_DISPLAY_OPERATOR_MIN_HEIGHT - HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN + 1) +
+                      4 * (HB_OT_MATH_CONSTANT_RADICAL_KERN_AFTER_DEGREE - HB_OT_MATH_CONSTANT_MATH_LEADING + 1) +
+                      2);
+};
+
 /*
  * MATH -- The MATH Table
  */
@@ -44,14 +174,22 @@ struct MATH
   {
     TRACE_SANITIZE (this);
     return_trace (version.sanitize (c) &&
-		  likely (version.major == 1));
+                  likely (version.major == 1) &&
+                  mathConstants.sanitize (c, this));
+  }
+
+  inline bool has_math_constants (void) const { return mathConstants != 0; }
+  inline const MathConstants &get_math_constants (void) const {
+    return this+mathConstants;
   }
 
 protected:
-  FixedVersion<>version;		 /* Version of the MATH table
-					  * initially set to 0x00010000u */
+  FixedVersion<>version;                 /* Version of the MATH table
+                                          * initially set to 0x00010000u */
+  OffsetTo<MathConstants> mathConstants; /* MathConstants table */
+
 public:
-  DEFINE_SIZE_STATIC (4);
+  DEFINE_SIZE_STATIC (6);
 };
 
 } /* mathspace OT */
diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc
index e6316e1..2ae1388 100644
--- a/src/hb-ot-layout.cc
+++ b/src/hb-ot-layout.cc
@@ -1244,3 +1244,28 @@ hb_ot_layout_has_math_data (hb_face_t *face)
 {
   return &_get_math (face) != &OT::Null(OT::MATH);
 }
+
+/**
+ * hb_ot_layout_get_math_constant:
+ *
+ * @font: #hb_font_t from which to retrieve the value
+ * @constant: #hb_ot_math_constant_t the constant to retrieve
+ *
+ * This function returns the requested math constants as a #hb_position_t.
+ * If the request constant is HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN,
+ * HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN or
+ * HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN then the return value is
+ * actually an integer between 0 and 100 representing that percentage.
+ *
+ * Return value: the requested constant or 0
+ *
+ * Since: ????
+ **/
+hb_position_t
+hb_ot_layout_get_math_constant (hb_font_t *font,
+                                hb_ot_math_constant_t constant)
+{
+  const OT::MATH &math = _get_math (font->face);
+  return math.has_math_constants() ?
+    math.get_math_constants().get_value(font, constant) : 0;
+}
diff --git a/src/hb-ot-layout.h b/src/hb-ot-layout.h
index e786790..501082e 100644
--- a/src/hb-ot-layout.h
+++ b/src/hb-ot-layout.h
@@ -33,6 +33,7 @@
 
 #include "hb.h"
 
+#include "hb-ot-math.h"
 #include "hb-ot-tag.h"
 
 HB_BEGIN_DECLS
@@ -305,6 +306,10 @@ hb_ot_layout_get_size_params (hb_face_t    *face,
 HB_EXTERN hb_bool_t
 hb_ot_layout_has_math_data (hb_face_t *face);
 
+HB_EXTERN hb_position_t
+hb_ot_layout_get_math_constant (hb_font_t *font,
+                                hb_ot_math_constant_t constant);
+
 
 HB_END_DECLS
 
diff --git a/src/hb-ot-math.h b/src/hb-ot-math.h
new file mode 100644
index 0000000..7f0ec27
--- /dev/null
+++ b/src/hb-ot-math.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright © 2016  Igalia S.L.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Igalia Author(s): Frédéric Wang
+ */
+
+#ifndef HB_OT_H_IN
+#error "Include <hb-ot.h> instead."
+#endif
+
+#ifndef HB_OT_MATH_H
+#define HB_OT_MATH_H
+
+#include "hb.h"
+
+HB_BEGIN_DECLS
+
+
+typedef enum {
+  HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN = 0,
+  HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN = 1,
+  HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT = 2,
+  HB_OT_MATH_CONSTANT_DISPLAY_OPERATOR_MIN_HEIGHT = 3,
+  HB_OT_MATH_CONSTANT_MATH_LEADING = 4,
+  HB_OT_MATH_CONSTANT_AXIS_HEIGHT = 5,
+  HB_OT_MATH_CONSTANT_ACCENT_BASE_HEIGHT = 6,
+  HB_OT_MATH_CONSTANT_FLATTENED_ACCENT_BASE_HEIGHT = 7,
+  HB_OT_MATH_CONSTANT_SUBSCRIPT_SHIFT_DOWN = 8,
+  HB_OT_MATH_CONSTANT_SUBSCRIPT_TOP_MAX = 9,
+  HB_OT_MATH_CONSTANT_SUBSCRIPT_BASELINE_DROP_MIN = 10,
+  HB_OT_MATH_CONSTANT_SUPERSCRIPT_SHIFT_UP = 11,
+  HB_OT_MATH_CONSTANT_SUPERSCRIPT_SHIFT_UP_CRAMPED = 12,
+  HB_OT_MATH_CONSTANT_SUPERSCRIPT_BOTTOM_MIN = 13,
+  HB_OT_MATH_CONSTANT_SUPERSCRIPT_BASELINE_DROP_MAX = 14,
+  HB_OT_MATH_CONSTANT_SUB_SUPERSCRIPT_GAP_MIN = 15,
+  HB_OT_MATH_CONSTANT_SUPERSCRIPT_BOTTOM_MAX_WITH_SUBSCRIPT = 16,
+  HB_OT_MATH_CONSTANT_SPACE_AFTER_SCRIPT = 17,
+  HB_OT_MATH_CONSTANT_UPPER_LIMIT_GAP_MIN = 18,
+  HB_OT_MATH_CONSTANT_UPPER_LIMIT_BASELINE_RISE_MIN = 19,
+  HB_OT_MATH_CONSTANT_LOWER_LIMIT_GAP_MIN = 20,
+  HB_OT_MATH_CONSTANT_LOWER_LIMIT_BASELINE_DROP_MIN = 21,
+  HB_OT_MATH_CONSTANT_STACK_TOP_SHIFT_UP = 22,
+  HB_OT_MATH_CONSTANT_STACK_TOP_DISPLAY_STYLE_SHIFT_UP = 23,
+  HB_OT_MATH_CONSTANT_STACK_BOTTOM_SHIFT_DOWN = 24,
+  HB_OT_MATH_CONSTANT_STACK_BOTTOM_DISPLAY_STYLE_SHIFT_DOWN = 25,
+  HB_OT_MATH_CONSTANT_STACK_GAP_MIN = 26,
+  HB_OT_MATH_CONSTANT_STACK_DISPLAY_STYLE_GAP_MIN = 27,
+  HB_OT_MATH_CONSTANT_STRETCH_STACK_TOP_SHIFT_UP = 28,
+  HB_OT_MATH_CONSTANT_STRETCH_STACK_BOTTOM_SHIFT_DOWN = 29,
+  HB_OT_MATH_CONSTANT_STRETCH_STACK_GAP_ABOVE_MIN = 30,
+  HB_OT_MATH_CONSTANT_STRETCH_STACK_GAP_BELOW_MIN = 31,
+  HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_SHIFT_UP = 32,
+  HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_DISPLAY_STYLE_SHIFT_UP = 33,
+  HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_SHIFT_DOWN = 34,
+  HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_DISPLAY_STYLE_SHIFT_DOWN = 35,
+  HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_GAP_MIN = 36,
+  HB_OT_MATH_CONSTANT_FRACTION_NUM_DISPLAY_STYLE_GAP_MIN = 37,
+  HB_OT_MATH_CONSTANT_FRACTION_RULE_THICKNESS = 38,
+  HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_GAP_MIN = 39,
+  HB_OT_MATH_CONSTANT_FRACTION_DENOM_DISPLAY_STYLE_GAP_MIN = 40,
+  HB_OT_MATH_CONSTANT_SKEWED_FRACTION_HORIZONTAL_GAP = 41,
+  HB_OT_MATH_CONSTANT_SKEWED_FRACTION_VERTICAL_GAP = 42,
+  HB_OT_MATH_CONSTANT_OVERBAR_VERTICAL_GAP = 43,
+  HB_OT_MATH_CONSTANT_OVERBAR_RULE_THICKNESS = 44,
+  HB_OT_MATH_CONSTANT_OVERBAR_EXTRA_ASCENDER = 45,
+  HB_OT_MATH_CONSTANT_UNDERBAR_VERTICAL_GAP = 46,
+  HB_OT_MATH_CONSTANT_UNDERBAR_RULE_THICKNESS = 47,
+  HB_OT_MATH_CONSTANT_UNDERBAR_EXTRA_DESCENDER = 48,
+  HB_OT_MATH_CONSTANT_RADICAL_VERTICAL_GAP = 49,
+  HB_OT_MATH_CONSTANT_RADICAL_DISPLAY_STYLE_VERTICAL_GAP = 50,
+  HB_OT_MATH_CONSTANT_RADICAL_RULE_THICKNESS = 51,
+  HB_OT_MATH_CONSTANT_RADICAL_EXTRA_ASCENDER = 52,
+  HB_OT_MATH_CONSTANT_RADICAL_KERN_BEFORE_DEGREE = 53,
+  HB_OT_MATH_CONSTANT_RADICAL_KERN_AFTER_DEGREE = 54,
+  HB_OT_MATH_CONSTANT_RADICAL_DEGREE_BOTTOM_RAISE_PERCENT = 55
+} hb_ot_math_constant_t;
+
+HB_END_DECLS
+
+#endif /* HB_OT_MATH_H */
diff --git a/test/api/fonts/MathTestFontFull.otf b/test/api/fonts/MathTestFontFull.otf
new file mode 100644
index 0000000..6c7c9a9
Binary files /dev/null and b/test/api/fonts/MathTestFontFull.otf differ
diff --git a/test/api/test-ot-layout-math.c b/test/api/test-ot-layout-math.c
index 3e8fec6..219959b 100644
--- a/test/api/test-ot-layout-math.c
+++ b/test/api/test-ot-layout-math.c
@@ -89,12 +89,84 @@ test_has_math_data (void)
   cleanupFreeType();
 }
 
+static void
+test_get_math_constant (void)
+{
+  initFreeType();
+
+  openFont("fonts/MathTestFontEmpty.otf");
+  g_assert_cmpint(hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT), ==, 0); // MathConstants not available
+  closeFont();
+
+  openFont("fonts/MathTestFontFull.otf");
+  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT)), ==, 100);
+  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_DISPLAY_OPERATOR_MIN_HEIGHT)), ==, 200);
+  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_MATH_LEADING)), ==, 300);
+  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_AXIS_HEIGHT)), ==, 400);
+  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_ACCENT_BASE_HEIGHT)), ==, 500);
+  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_FLATTENED_ACCENT_BASE_HEIGHT)), ==, 600);
+  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_SUBSCRIPT_SHIFT_DOWN)), ==, 700);
+  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_SUBSCRIPT_TOP_MAX)), ==, 800);
+  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_SUBSCRIPT_BASELINE_DROP_MIN)), ==, 900);
+  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_SUPERSCRIPT_SHIFT_UP)), ==, 1100);
+  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_SUPERSCRIPT_SHIFT_UP_CRAMPED)), ==, 1200);
+  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_SUPERSCRIPT_BOTTOM_MIN)), ==, 1300);
+  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_SUPERSCRIPT_BASELINE_DROP_MAX)), ==, 1400);
+  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_SUB_SUPERSCRIPT_GAP_MIN)), ==, 1500);
+  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_SUPERSCRIPT_BOTTOM_MAX_WITH_SUBSCRIPT)), ==, 1600);
+  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_SPACE_AFTER_SCRIPT)), ==, 1700);
+  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_UPPER_LIMIT_GAP_MIN)), ==, 1800);
+  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_UPPER_LIMIT_BASELINE_RISE_MIN)), ==, 1900);
+  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_LOWER_LIMIT_GAP_MIN)), ==, 2200);
+  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_LOWER_LIMIT_BASELINE_DROP_MIN)), ==, 2300);
+  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_STACK_TOP_SHIFT_UP)), ==, 2400);
+  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_STACK_TOP_DISPLAY_STYLE_SHIFT_UP)), ==, 2500);
+  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_STACK_BOTTOM_SHIFT_DOWN)), ==, 2600);
+  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_STACK_BOTTOM_DISPLAY_STYLE_SHIFT_DOWN)), ==, 2700);
+  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_STACK_GAP_MIN)), ==, 2800);
+  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_STACK_DISPLAY_STYLE_GAP_MIN)), ==, 2900);
+  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_STRETCH_STACK_TOP_SHIFT_UP)), ==, 3000);
+  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_STRETCH_STACK_BOTTOM_SHIFT_DOWN)), ==, 3100);
+  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_STRETCH_STACK_GAP_ABOVE_MIN)), ==, 3200);
+  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_STRETCH_STACK_GAP_BELOW_MIN)), ==, 3300);
+  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_SHIFT_UP)), ==, 3400);
+  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_DISPLAY_STYLE_SHIFT_UP)), ==, 3500);
+  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_SHIFT_DOWN)), ==, 3600);
+  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_DISPLAY_STYLE_SHIFT_DOWN)), ==, 3700);
+  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_GAP_MIN)), ==, 3800);
+  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_NUM_DISPLAY_STYLE_GAP_MIN)), ==, 3900);
+  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_RULE_THICKNESS)), ==, 4000);
+  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_GAP_MIN)), ==, 4100);
+  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_DENOM_DISPLAY_STYLE_GAP_MIN)), ==, 4200);
+  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_SKEWED_FRACTION_HORIZONTAL_GAP)), ==, 4300);
+  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_SKEWED_FRACTION_VERTICAL_GAP)), ==, 4400);
+  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_OVERBAR_VERTICAL_GAP)), ==, 4500);
+  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_OVERBAR_RULE_THICKNESS)), ==, 4600);
+  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_OVERBAR_EXTRA_ASCENDER)), ==, 4700);
+  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_UNDERBAR_VERTICAL_GAP)), ==, 4800);
+  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_UNDERBAR_RULE_THICKNESS)), ==, 4900);
+  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_UNDERBAR_EXTRA_DESCENDER)), ==, 5000);
+  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_VERTICAL_GAP)), ==, 5100);
+  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_DISPLAY_STYLE_VERTICAL_GAP)), ==, 5200);
+  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_RULE_THICKNESS)), ==, 5300);
+  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_EXTRA_ASCENDER)), ==, 5400);
+  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_KERN_BEFORE_DEGREE)), ==, 5500);
+  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_KERN_AFTER_DEGREE)), ==, 5600);
+  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN)), ==, 87);
+  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN)), ==, 76);
+  g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_DEGREE_BOTTOM_RAISE_PERCENT)), ==, 65);
+  closeFont();
+
+  cleanupFreeType();
+}
+
 int
 main (int argc, char **argv)
 {
   hb_test_init (&argc, &argv);
 
   hb_test_add (test_has_math_data);
+  hb_test_add (test_get_math_constant);
 
   return hb_test_run();
 }
commit 4d3892e9b05a4df67b2f5cfd6dd3a1e0f5b38fc7
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Sep 26 10:45:58 2016 +0100

    [MATH] Fixups for previous commit

diff --git a/src/hb-ot-layout-math-table.hh b/src/hb-ot-layout-math-table.hh
index f4ecf3f..7b3c0c7 100644
--- a/src/hb-ot-layout-math-table.hh
+++ b/src/hb-ot-layout-math-table.hh
@@ -38,18 +38,18 @@ namespace OT {
 
 struct MATH
 {
-  static const hb_tag_t tableTag        = HB_OT_TAG_MATH;
+  static const hb_tag_t tableTag	= HB_OT_TAG_MATH;
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (version.sanitize (c) &&
-                  likely (version.major == 1));
+		  likely (version.major == 1));
   }
 
 protected:
-  FixedVersion<>version;                 /* Version of the MATH table
-                                            initially set to 0x00010000u */
+  FixedVersion<>version;		 /* Version of the MATH table
+					  * initially set to 0x00010000u */
 public:
   DEFINE_SIZE_STATIC (4);
 };
diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc
index 24d290c..e6316e1 100644
--- a/src/hb-ot-layout.cc
+++ b/src/hb-ot-layout.cc
@@ -61,7 +61,7 @@ _hb_ot_layout_create (hb_face_t *face)
   layout->gpos_blob = OT::Sanitizer<OT::GPOS>::sanitize (face->reference_table (HB_OT_TAG_GPOS));
   layout->gpos = OT::Sanitizer<OT::GPOS>::lock_instance (layout->gpos_blob);
 
-  // The MATH table is rarer so we only try and load it in _get_math
+  /* The MATH table is rarely used, so only try and load it in _get_math. */
   layout->math_blob = NULL;
   layout->math = NULL;
 
@@ -182,8 +182,7 @@ _hb_ot_layout_destroy (hb_ot_layout_t *layout)
   hb_blob_destroy (layout->gdef_blob);
   hb_blob_destroy (layout->gsub_blob);
   hb_blob_destroy (layout->gpos_blob);
-
-  if (layout->math_blob) hb_blob_destroy (layout->math_blob);
+  hb_blob_destroy (layout->math_blob);
 
   free (layout);
 }
@@ -213,13 +212,22 @@ _get_math (hb_face_t *face)
 
   hb_ot_layout_t * layout = hb_ot_layout_from_face (face);
 
-  // If the MATH table is not loaded yet, do it now.
-  if (!layout->math_blob) {
-    layout->math_blob = OT::Sanitizer<OT::MATH>::sanitize (face->reference_table (HB_OT_TAG_MATH));
-    layout->math = OT::Sanitizer<OT::MATH>::lock_instance (layout->math_blob);
+retry:
+  const OT::MATH *math = (const OT::MATH *) hb_atomic_ptr_get (&layout->math);
+
+  if (unlikely (!math))
+  {
+    hb_blob_t *blob = OT::Sanitizer<OT::MATH>::sanitize (face->reference_table (HB_OT_TAG_MATH));
+    math = OT::Sanitizer<OT::MATH>::lock_instance (blob);
+    if (!hb_atomic_ptr_cmpexch (&layout->math, NULL, math))
+    {
+      hb_blob_destroy (blob);
+      goto retry;
+    }
+    layout->math_blob = blob;
   }
 
-  return *layout->math;
+  return *math;
 }
 
 
@@ -1213,8 +1221,9 @@ hb_ot_layout_substitute_lookup (OT::hb_apply_context_t *c,
   apply_string<GSUBProxy> (c, lookup, accel);
 }
 
+
 /*
- * OT::MATH
+ * MATH
  */
 
 /**
@@ -1228,7 +1237,7 @@ hb_ot_layout_substitute_lookup (OT::hb_apply_context_t *c,
  *
  * Return value: #TRUE if face has a MATH table and #FALSE otherwise
  *
- * Since: ????
+ * Since: 1.4
  **/
 hb_bool_t
 hb_ot_layout_has_math_data (hb_face_t *face)
diff --git a/src/hb-ot-layout.h b/src/hb-ot-layout.h
index 7cbd794..e786790 100644
--- a/src/hb-ot-layout.h
+++ b/src/hb-ot-layout.h
@@ -304,6 +304,8 @@ hb_ot_layout_get_size_params (hb_face_t    *face,
 
 HB_EXTERN hb_bool_t
 hb_ot_layout_has_math_data (hb_face_t *face);
+
+
 HB_END_DECLS
 
 #endif /* HB_OT_LAYOUT_H */
diff --git a/test/api/Makefile.am b/test/api/Makefile.am
index dae8700..322cd7d 100644
--- a/test/api/Makefile.am
+++ b/test/api/Makefile.am
@@ -52,10 +52,8 @@ if HAVE_FREETYPE
 TEST_PROGS += \
 	test-ot-layout-math \
 	$(NULL)
-test_ot_layout_math_LDADD = $(LDADD)
-test_ot_layout_math_CPPFLAGS = $(AM_CPPFLAGS)
-test_ot_layout_math_CPPFLAGS += $(FREETYPE_CFLAGS)
-test_ot_layout_math_LDADD += $(FREETYPE_LIBS)
+test_ot_layout_math_LDADD = $(LDADD) $(FREETYPE_LIBS)
+test_ot_layout_math_CPPFLAGS = $(AM_CPPFLAGS) $(FREETYPE_CFLAGS)
 endif # HAVE_FREETYPE
 
 endif # HAVE_OT
diff --git a/test/api/test-ot-layout-math.c b/test/api/test-ot-layout-math.c
index cf7d76c..3e8fec6 100644
--- a/test/api/test-ot-layout-math.c
+++ b/test/api/test-ot-layout-math.c
@@ -37,16 +37,16 @@ static FT_Face ft_face;
 static hb_font_t *hb_font;
 static hb_face_t *hb_face;
 
-static void
-initFreeType()
+static inline void
+initFreeType (void)
 {
   FT_Error ft_error;
   if ((ft_error = FT_Init_FreeType (&ft_library)))
     abort();
 }
 
-static void
-cleanupFreeType()
+static inline void
+cleanupFreeType (void)
 {
   FT_Done_FreeType (ft_library);
 }
@@ -57,15 +57,17 @@ openFont(const char* fontFile)
   FT_Error ft_error;
   if ((ft_error = FT_New_Face (ft_library, fontFile, 0, &ft_face)))
     abort();
-  unsigned int fontSize = 1000;
+
+#define fontSize 1000
+
   if ((ft_error = FT_Set_Char_Size (ft_face, fontSize, fontSize, 0, 0)))
     abort();
   hb_font = hb_ft_font_create (ft_face, NULL);
   hb_face = hb_ft_face_create_cached(ft_face);
 }
 
-static void
-closeFont()
+static inline void
+closeFont (void)
 {
   hb_font_destroy (hb_font);
   FT_Done_Face (ft_face);
commit 5fbcb992bd7887f95b1cf2ca045c9226de8148fc
Author: Frédéric Wang <fred.wang at free.fr>
Date:   Thu Aug 25 10:47:15 2016 +0200

    MATH Table: Add API to check availability of math data.

diff --git a/src/Makefile.sources b/src/Makefile.sources
index ac80683..cd30b12 100644
--- a/src/Makefile.sources
+++ b/src/Makefile.sources
@@ -75,6 +75,7 @@ HB_OT_sources = \
 	hb-ot-layout-gsubgpos-private.hh \
 	hb-ot-layout-gsub-table.hh \
 	hb-ot-layout-jstf-table.hh \
+	hb-ot-layout-math-table.hh \
 	hb-ot-layout-private.hh \
 	hb-ot-map.cc \
 	hb-ot-map-private.hh \
diff --git a/src/hb-ot-layout-math-table.hh b/src/hb-ot-layout-math-table.hh
new file mode 100644
index 0000000..f4ecf3f
--- /dev/null
+++ b/src/hb-ot-layout-math-table.hh
@@ -0,0 +1,60 @@
+/*
+ * Copyright © 2016  Igalia S.L.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Igalia Author(s): Frédéric Wang
+ */
+
+#ifndef HB_OT_LAYOUT_MATH_TABLE_HH
+#define HB_OT_LAYOUT_MATH_TABLE_HH
+
+#include "hb-open-type-private.hh"
+#include "hb-ot-layout-common-private.hh"
+
+namespace OT {
+
+/*
+ * MATH -- The MATH Table
+ */
+
+struct MATH
+{
+  static const hb_tag_t tableTag        = HB_OT_TAG_MATH;
+
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (version.sanitize (c) &&
+                  likely (version.major == 1));
+  }
+
+protected:
+  FixedVersion<>version;                 /* Version of the MATH table
+                                            initially set to 0x00010000u */
+public:
+  DEFINE_SIZE_STATIC (4);
+};
+
+} /* mathspace OT */
+
+
+#endif /* HB_OT_LAYOUT_MATH_TABLE_HH */
diff --git a/src/hb-ot-layout-private.hh b/src/hb-ot-layout-private.hh
index 778b2c4..a4272de 100644
--- a/src/hb-ot-layout-private.hh
+++ b/src/hb-ot-layout-private.hh
@@ -124,6 +124,7 @@ namespace OT {
   struct GDEF;
   struct GSUB;
   struct GPOS;
+  struct MATH;
 }
 
 struct hb_ot_layout_lookup_accelerator_t
@@ -152,10 +153,12 @@ struct hb_ot_layout_t
   hb_blob_t *gdef_blob;
   hb_blob_t *gsub_blob;
   hb_blob_t *gpos_blob;
+  hb_blob_t *math_blob;
 
   const struct OT::GDEF *gdef;
   const struct OT::GSUB *gsub;
   const struct OT::GPOS *gpos;
+  const struct OT::MATH *math;
 
   unsigned int gsub_lookup_count;
   unsigned int gpos_lookup_count;
diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc
index 5cb1491..24d290c 100644
--- a/src/hb-ot-layout.cc
+++ b/src/hb-ot-layout.cc
@@ -35,6 +35,7 @@
 #include "hb-ot-layout-gsub-table.hh"
 #include "hb-ot-layout-gpos-table.hh"
 #include "hb-ot-layout-jstf-table.hh"
+#include "hb-ot-layout-math-table.hh"
 
 #include "hb-ot-map-private.hh"
 
@@ -60,6 +61,10 @@ _hb_ot_layout_create (hb_face_t *face)
   layout->gpos_blob = OT::Sanitizer<OT::GPOS>::sanitize (face->reference_table (HB_OT_TAG_GPOS));
   layout->gpos = OT::Sanitizer<OT::GPOS>::lock_instance (layout->gpos_blob);
 
+  // The MATH table is rarer so we only try and load it in _get_math
+  layout->math_blob = NULL;
+  layout->math = NULL;
+
   {
     /*
      * The ugly business of blacklisting individual fonts' tables happen here!
@@ -178,6 +183,8 @@ _hb_ot_layout_destroy (hb_ot_layout_t *layout)
   hb_blob_destroy (layout->gsub_blob);
   hb_blob_destroy (layout->gpos_blob);
 
+  if (layout->math_blob) hb_blob_destroy (layout->math_blob);
+
   free (layout);
 }
 
@@ -199,6 +206,21 @@ _get_gpos (hb_face_t *face)
   if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::GPOS);
   return *hb_ot_layout_from_face (face)->gpos;
 }
+static inline const OT::MATH&
+_get_math (hb_face_t *face)
+{
+  if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::MATH);
+
+  hb_ot_layout_t * layout = hb_ot_layout_from_face (face);
+
+  // If the MATH table is not loaded yet, do it now.
+  if (!layout->math_blob) {
+    layout->math_blob = OT::Sanitizer<OT::MATH>::sanitize (face->reference_table (HB_OT_TAG_MATH));
+    layout->math = OT::Sanitizer<OT::MATH>::lock_instance (layout->math_blob);
+  }
+
+  return *layout->math;
+}
 
 
 /*
@@ -1190,3 +1212,26 @@ hb_ot_layout_substitute_lookup (OT::hb_apply_context_t *c,
 {
   apply_string<GSUBProxy> (c, lookup, accel);
 }
+
+/*
+ * OT::MATH
+ */
+
+/**
+ * hb_ot_layout_has_math_data:
+ *
+ * @face: #hb_face_t to test
+ *
+ * This function allows to verify the presence of an OpenType MATH table on the
+ * face. If so, such a table will be loaded into memory and sanitized. You can
+ * then safely call other functions for math layout and shaping.
+ *
+ * Return value: #TRUE if face has a MATH table and #FALSE otherwise
+ *
+ * Since: ????
+ **/
+hb_bool_t
+hb_ot_layout_has_math_data (hb_face_t *face)
+{
+  return &_get_math (face) != &OT::Null(OT::MATH);
+}
diff --git a/src/hb-ot-layout.h b/src/hb-ot-layout.h
index eb23d45..7cbd794 100644
--- a/src/hb-ot-layout.h
+++ b/src/hb-ot-layout.h
@@ -42,6 +42,7 @@ HB_BEGIN_DECLS
 #define HB_OT_TAG_GSUB HB_TAG('G','S','U','B')
 #define HB_OT_TAG_GPOS HB_TAG('G','P','O','S')
 #define HB_OT_TAG_JSTF HB_TAG('J','S','T','F')
+#define HB_OT_TAG_MATH HB_TAG('M','A','T','H')
 
 
 /*
@@ -297,6 +298,12 @@ hb_ot_layout_get_size_params (hb_face_t    *face,
 			      unsigned int *range_end          /* OUT.  May be NULL */);
 
 
+/*
+ * MATH
+ */
+
+HB_EXTERN hb_bool_t
+hb_ot_layout_has_math_data (hb_face_t *face);
 HB_END_DECLS
 
 #endif /* HB_OT_LAYOUT_H */
diff --git a/test/api/Makefile.am b/test/api/Makefile.am
index d7d40af..dae8700 100644
--- a/test/api/Makefile.am
+++ b/test/api/Makefile.am
@@ -43,10 +43,22 @@ endif
 
 
 if HAVE_OT
+
 TEST_PROGS += \
 	test-ot-tag \
 	$(NULL)
-endif
+
+if HAVE_FREETYPE
+TEST_PROGS += \
+	test-ot-layout-math \
+	$(NULL)
+test_ot_layout_math_LDADD = $(LDADD)
+test_ot_layout_math_CPPFLAGS = $(AM_CPPFLAGS)
+test_ot_layout_math_CPPFLAGS += $(FREETYPE_CFLAGS)
+test_ot_layout_math_LDADD += $(FREETYPE_LIBS)
+endif # HAVE_FREETYPE
+
+endif # HAVE_OT
 
 # Tests for header compilation
 TEST_PROGS += \
diff --git a/test/api/fonts/MathTestFontEmpty.otf b/test/api/fonts/MathTestFontEmpty.otf
new file mode 100644
index 0000000..6b50d66
Binary files /dev/null and b/test/api/fonts/MathTestFontEmpty.otf differ
diff --git a/test/api/fonts/MathTestFontNone.otf b/test/api/fonts/MathTestFontNone.otf
new file mode 100644
index 0000000..52984ee
Binary files /dev/null and b/test/api/fonts/MathTestFontNone.otf differ
diff --git a/test/api/test-ot-layout-math.c b/test/api/test-ot-layout-math.c
new file mode 100644
index 0000000..cf7d76c
--- /dev/null
+++ b/test/api/test-ot-layout-math.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright © 2016  Igalia S.L.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Igalia Author(s): Frédéric Wang
+ */
+
+
+#include "hb-test.h"
+
+#include "hb-ft.h"
+#include "hb-ot.h"
+
+/* Unit tests for hb-ot-layout.h - OpenType MATH table  */
+
+static FT_Library ft_library;
+static FT_Face ft_face;
+static hb_font_t *hb_font;
+static hb_face_t *hb_face;
+
+static void
+initFreeType()
+{
+  FT_Error ft_error;
+  if ((ft_error = FT_Init_FreeType (&ft_library)))
+    abort();
+}
+
+static void
+cleanupFreeType()
+{
+  FT_Done_FreeType (ft_library);
+}
+
+static void
+openFont(const char* fontFile)
+{
+  FT_Error ft_error;
+  if ((ft_error = FT_New_Face (ft_library, fontFile, 0, &ft_face)))
+    abort();
+  unsigned int fontSize = 1000;
+  if ((ft_error = FT_Set_Char_Size (ft_face, fontSize, fontSize, 0, 0)))
+    abort();
+  hb_font = hb_ft_font_create (ft_face, NULL);
+  hb_face = hb_ft_face_create_cached(ft_face);
+}
+
+static void
+closeFont()
+{
+  hb_font_destroy (hb_font);
+  FT_Done_Face (ft_face);
+}
+
+static void
+test_has_math_data (void)
+{
+  initFreeType();
+
+  openFont("fonts/MathTestFontNone.otf");
+  g_assert(!hb_ot_layout_has_math_data (hb_face)); // MATH table not available
+  closeFont();
+
+  openFont("fonts/MathTestFontEmpty.otf");
+  g_assert(hb_ot_layout_has_math_data (hb_face)); // MATH table available
+  closeFont();
+
+  cleanupFreeType();
+}
+
+int
+main (int argc, char **argv)
+{
+  hb_test_init (&argc, &argv);
+
+  hb_test_add (test_has_math_data);
+
+  return hb_test_run();
+}


More information about the HarfBuzz mailing list