Implement a simple API for fetching opentype metrics
authorEbrahim Byagowi <ebrahim@gnu.org>
Tue, 20 Nov 2018 19:56:46 +0000 (23:26 +0330)
committerBehdad Esfahbod <behdad@behdad.org>
Thu, 18 Jul 2019 21:15:58 +0000 (14:15 -0700)
Fixes https://github.com/harfbuzz/harfbuzz/pull/1432

15 files changed:
docs/harfbuzz-sections.txt
src/Makefile.sources
src/hb-ot-face-table-list.hh
src/hb-ot-hhea-table.hh
src/hb-ot-hmtx-table.hh
src/hb-ot-layout.cc
src/hb-ot-metrics-internal.cc [new file with mode: 0644]
src/hb-ot-metrics.cc [new file with mode: 0644]
src/hb-ot-metrics.h [new file with mode: 0644]
src/hb-ot-metrics.hh [new file with mode: 0644]
src/hb-ot-os2-table.hh
src/hb-ot-post-table.hh
src/hb-ot.h
test/api/Makefile.am
test/api/test-ot-metrics.c [new file with mode: 0644]

index 4be248d..91d7cfa 100644 (file)
@@ -601,6 +601,15 @@ hb_ot_math_get_glyph_assembly
 </SECTION>
 
 <SECTION>
+<FILE>hb-ot-metrics</FILE>
+hb_ot_metrics_t
+hb_ot_metrics_get_position
+hb_ot_metrics_get_variation
+hb_ot_metrics_get_x_variation
+hb_ot_metrics_get_y_variation
+</SECTION>
+
+<SECTION>
 <FILE>hb-ot-shape</FILE>
 hb_ot_shape_glyphs_closure
 </SECTION>
index 6f42ba3..d30c489 100644 (file)
@@ -88,6 +88,9 @@ HB_BASE_sources = \
        hb-ot-math-table.hh \
        hb-ot-math.cc \
        hb-ot-maxp-table.hh \
+       hb-ot-metrics-internal.cc \
+       hb-ot-metrics.cc \
+       hb-ot-metrics.hh \
        hb-ot-name-language-static.hh \
        hb-ot-name-language.hh \
        hb-ot-name-table.hh \
@@ -191,6 +194,7 @@ HB_BASE_headers = \
        hb-ot-font.h \
        hb-ot-layout.h \
        hb-ot-math.h \
+       hb-ot-metrics.h \
        hb-ot-name.h \
        hb-ot-shape.h \
        hb-ot-var.h \
@@ -233,6 +237,8 @@ HB_ICU_headers = hb-icu.h
 HB_SUBSET_sources = \
        hb-ot-cff1-table.cc \
        hb-ot-cff2-table.cc \
+       hb-ot-metrics-internal.cc \
+       hb-ot-metrics.hh \
        hb-static.cc \
        hb-subset-cff-common.cc \
        hb-subset-cff-common.hh \
index ac70527..09e000d 100644 (file)
@@ -50,6 +50,7 @@ HB_OT_TABLE (OT, head)
 #if !defined(HB_NO_FACE_COLLECT_UNICODES) || !defined(HB_NO_OT_FONT)
 HB_OT_ACCELERATOR (OT, cmap)
 #endif
+HB_OT_TABLE (OT, hhea)
 HB_OT_ACCELERATOR (OT, hmtx)
 HB_OT_TABLE (OT, OS2)
 #ifndef HB_NO_OT_FONT_GLYPH_NAMES
@@ -63,6 +64,7 @@ HB_OT_TABLE (OT, STAT)
 #endif
 
 /* Vertical layout. */
+HB_OT_TABLE (OT, vhea)
 HB_OT_ACCELERATOR (OT, vmtx)
 
 /* TrueType outlines. */
index c3155b7..778b6c5 100644 (file)
@@ -45,6 +45,8 @@ namespace OT {
 template <typename T>
 struct _hea
 {
+  bool has_data () const { return version.major; }
+
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
index 754a376..09df44a 100644 (file)
@@ -31,6 +31,7 @@
 #include "hb-ot-hhea-table.hh"
 #include "hb-ot-os2-table.hh"
 #include "hb-ot-var-hvar-table.hh"
+#include "hb-ot-metrics.hh"
 
 /*
  * hmtx -- Horizontal Metrics
@@ -88,22 +89,22 @@ struct hmtxvmtx
 
   template<typename Iterator,
            hb_requires (hb_is_iterator (Iterator))>
-  void serialize (hb_serialize_context_t *c, 
-                  Iterator it, 
+  void serialize (hb_serialize_context_t *c,
+                  Iterator it,
                   unsigned num_advances)
   {
     unsigned idx = 0;
     + it
     | hb_apply ([c, &idx, num_advances] (const hb_item_type<Iterator>& _)
                 {
-                  if (idx < num_advances) 
+                  if (idx < num_advances)
                   {
                     LongMetric lm;
                     lm.advance = _.first;
                     lm.sb = _.second;
                     if (unlikely (!c->embed<LongMetric> (&lm))) return;
-                  } 
-                  else 
+                  }
+                  else
                   {
                     FWORD *sb = c->allocate_size<FWORD> (FWORD::static_size);
                     if (unlikely (!sb)) return;
@@ -120,12 +121,12 @@ struct hmtxvmtx
 
     T *table_prime = c->serializer->start_embed <T> ();
     if (unlikely (!table_prime)) return_trace (false);
-    
+
     accelerator_t _mtx;
     _mtx.init (c->plan->source);
     unsigned num_advances = _mtx.num_advances_for_subset (c->plan);
-    
-    auto it = 
+
+    auto it =
     + hb_range (c->plan->num_output_glyphs ())
     | hb_map ([c, &_mtx] (unsigned _)
        {
@@ -161,29 +162,16 @@ struct hmtxvmtx
                unsigned int default_advance_ = 0)
     {
       default_advance = default_advance_ ? default_advance_ : hb_face_get_upem (face);
+      ascender = 0; descender = 0; line_gap = 0;
 
-      bool got_font_extents = false;
-      if (T::os2Tag != HB_TAG_NONE && face->table.OS2->is_typo_metrics ())
-      {
-       ascender = abs (face->table.OS2->sTypoAscender);
-       descender = -abs (face->table.OS2->sTypoDescender);
-       line_gap = face->table.OS2->sTypoLineGap;
-       got_font_extents = (ascender | descender) != 0;
-      }
-
-      hb_blob_t *_hea_blob = hb_sanitize_context_t().reference_table<H> (face);
-      const H *_hea_table = _hea_blob->as<H> ();
-      num_advances = _hea_table->numberOfLongMetrics;
-      if (!got_font_extents)
-      {
-       ascender = abs (_hea_table->ascender);
-       descender = -abs (_hea_table->descender);
-       line_gap = _hea_table->lineGap;
-       got_font_extents = (ascender | descender) != 0;
-      }
-      hb_blob_destroy (_hea_blob);
+      hb_ot_metrics_get_position_internal (face, (hb_ot_metrics_t) T::ascenderTag, &ascender);
+      hb_ot_metrics_get_position_internal (face, (hb_ot_metrics_t) T::descenderTag, &descender);
+      hb_ot_metrics_get_position_internal (face, (hb_ot_metrics_t) T::lineGapTag, &line_gap);
+      ascender = fabs (ascender);
+      descender = -fabs (descender);
+      has_font_extents = ascender != 0 || descender != 0;
 
-      has_font_extents = got_font_extents;
+      num_advances = T::is_horizontal ? face->table.hhea->numberOfLongMetrics : face->table.vhea->numberOfLongMetrics;
 
       table = hb_sanitize_context_t().reference_table<hmtxvmtx> (face, T::tableTag);
 
@@ -279,9 +267,9 @@ struct hmtxvmtx
 
     public:
     bool has_font_extents;
-    int ascender;
-    int descender;
-    int line_gap;
+    float ascender;
+    float descender;
+    float line_gap;
 
     protected:
     unsigned int num_metrics;
@@ -322,12 +310,18 @@ struct hmtxvmtx
 struct hmtx : hmtxvmtx<hmtx, hhea> {
   static constexpr hb_tag_t tableTag = HB_OT_TAG_hmtx;
   static constexpr hb_tag_t variationsTag = HB_OT_TAG_HVAR;
-  static constexpr hb_tag_t os2Tag = HB_OT_TAG_OS2;
+  static constexpr hb_tag_t ascenderTag = HB_OT_METRICS_HORIZONTAL_ASCENDER;
+  static constexpr hb_tag_t descenderTag = HB_OT_METRICS_HORIZONTAL_DESCENDER;
+  static constexpr hb_tag_t lineGapTag = HB_OT_METRICS_HORIZONTAL_LINE_GAP;
+  static constexpr bool is_horizontal = true;
 };
 struct vmtx : hmtxvmtx<vmtx, vhea> {
   static constexpr hb_tag_t tableTag = HB_OT_TAG_vmtx;
   static constexpr hb_tag_t variationsTag = HB_OT_TAG_VVAR;
-  static constexpr hb_tag_t os2Tag = HB_TAG_NONE;
+  static constexpr hb_tag_t ascenderTag = HB_OT_METRICS_VERTICAL_ASCENDER;
+  static constexpr hb_tag_t descenderTag = HB_OT_METRICS_VERTICAL_DESCENDER;
+  static constexpr hb_tag_t lineGapTag = HB_OT_METRICS_VERTICAL_LINE_GAP;
+  static constexpr bool is_horizontal = false;
 };
 
 struct hmtx_accelerator_t : hmtx::accelerator_t {};
index 98cd109..c67cd0c 100644 (file)
@@ -43,7 +43,6 @@
 #include "hb-map.hh"
 
 #include "hb-ot-kern-table.hh"
-#include "hb-ot-gasp-table.hh" // Just so we compile it; unused otherwise.
 #include "hb-ot-layout-gdef-table.hh"
 #include "hb-ot-layout-gsub-table.hh"
 #include "hb-ot-layout-gpos-table.hh"
diff --git a/src/hb-ot-metrics-internal.cc b/src/hb-ot-metrics-internal.cc
new file mode 100644 (file)
index 0000000..9f0294f
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * Copyright © 2018  Ebrahim Byagowi
+ *
+ *  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.
+ */
+
+#include "hb.hh"
+
+#include "hb-ot-gasp-table.hh" // Just so we compile it; unused otherwise.
+#include "hb-ot-os2-table.hh"
+#include "hb-ot-post-table.hh"
+#include "hb-ot-hmtx-table.hh"
+#include "hb-ot-var-mvar-table.hh"
+#include "hb-ot-metrics.hh"
+
+#include "hb-ot-face.hh"
+
+#if 0
+static bool
+_get_gasp (hb_face_t *face, float *result, hb_ot_metrics_t metrics_tag)
+{
+  const OT::GaspRange& range = face->table.gasp->get_gasp_range (metrics_tag - HB_TAG ('g','s','p','0'));
+  if (&range == &Null (OT::GaspRange)) return false;
+  if (result) *result = range.rangeMaxPPEM + face->table.MVAR->get_var (metrics_tag, nullptr, 0);
+  return true;
+}
+#endif
+
+bool
+hb_ot_metrics_get_position_internal (hb_face_t       *face,
+                                    hb_ot_metrics_t  metrics_tag,
+                                    float           *position     /* OUT.  May be NULL. */)
+{
+  switch (metrics_tag)
+  {
+#define GET_METRIC(TABLE, ATTR) \
+  (face->table.TABLE->has_data () && \
+    (position && (*position = face->table.TABLE->ATTR + face->table.MVAR->get_var (metrics_tag, nullptr, 0)), true))
+  case HB_OT_METRICS_HORIZONTAL_ASCENDER:
+    return (face->table.OS2->is_typo_metrics () ^ GET_METRIC (hhea, ascender)) ||
+          GET_METRIC (OS2, sTypoAscender);
+  case HB_OT_METRICS_HORIZONTAL_DESCENDER:
+    return (face->table.OS2->is_typo_metrics () ^ GET_METRIC (hhea, descender)) ||
+          GET_METRIC (OS2, sTypoDescender);
+  case HB_OT_METRICS_HORIZONTAL_LINE_GAP:
+    return (face->table.OS2->is_typo_metrics () ^ GET_METRIC (hhea, lineGap)) ||
+          GET_METRIC (OS2, sTypoLineGap);
+  case HB_OT_METRICS_HORIZONTAL_CLIPPING_ASCENT:  return GET_METRIC (OS2, usWinAscent);
+  case HB_OT_METRICS_HORIZONTAL_CLIPPING_DESCENT: return GET_METRIC (OS2, usWinDescent);
+  case HB_OT_METRICS_VERTICAL_ASCENDER:           return GET_METRIC (vhea, ascender);
+  case HB_OT_METRICS_VERTICAL_DESCENDER:          return GET_METRIC (vhea, descender);
+  case HB_OT_METRICS_VERTICAL_LINE_GAP:           return GET_METRIC (vhea, lineGap);
+  case HB_OT_METRICS_HORIZONTAL_CARET_RISE:       return GET_METRIC (hhea, caretSlopeRise);
+  case HB_OT_METRICS_HORIZONTAL_CARET_RUN:        return GET_METRIC (hhea, caretSlopeRun);
+  case HB_OT_METRICS_HORIZONTAL_CARET_OFFSET:     return GET_METRIC (hhea, caretOffset);
+  case HB_OT_METRICS_VERTICAL_CARET_RISE:         return GET_METRIC (vhea, caretSlopeRise);
+  case HB_OT_METRICS_VERTICAL_CARET_RUN:          return GET_METRIC (vhea, caretSlopeRun);
+  case HB_OT_METRICS_VERTICAL_CARET_OFFSET:       return GET_METRIC (vhea, caretOffset);
+  case HB_OT_METRICS_X_HEIGHT:                    return GET_METRIC (OS2->v2 (), sxHeight);
+  case HB_OT_METRICS_CAP_HEIGHT:                  return GET_METRIC (OS2->v2 (), sCapHeight);
+  case HB_OT_METRICS_SUBSCRIPT_EM_X_SIZE:         return GET_METRIC (OS2, ySubscriptXSize);
+  case HB_OT_METRICS_SUBSCRIPT_EM_Y_SIZE:         return GET_METRIC (OS2, ySubscriptYSize);
+  case HB_OT_METRICS_SUBSCRIPT_EM_X_OFFSET:       return GET_METRIC (OS2, ySubscriptXOffset);
+  case HB_OT_METRICS_SUBSCRIPT_EM_Y_OFFSET:       return GET_METRIC (OS2, ySubscriptYOffset);
+  case HB_OT_METRICS_SUPERSCRIPT_EM_X_SIZE:       return GET_METRIC (OS2, ySuperscriptXSize);
+  case HB_OT_METRICS_SUPERSCRIPT_EM_Y_SIZE:       return GET_METRIC (OS2, ySuperscriptYSize);
+  case HB_OT_METRICS_SUPERSCRIPT_EM_X_OFFSET:     return GET_METRIC (OS2, ySuperscriptXOffset);
+  case HB_OT_METRICS_SUPERSCRIPT_EM_Y_OFFSET:     return GET_METRIC (OS2, ySuperscriptYOffset);
+  case HB_OT_METRICS_STRIKEOUT_SIZE:              return GET_METRIC (OS2, yStrikeoutSize);
+  case HB_OT_METRICS_STRIKEOUT_OFFSET:            return GET_METRIC (OS2, yStrikeoutPosition);
+  case HB_OT_METRICS_UNDERLINE_SIZE:              return GET_METRIC (post->table, underlineThickness);
+  case HB_OT_METRICS_UNDERLINE_OFFSET:            return GET_METRIC (post->table, underlinePosition);
+#undef GET_METRIC
+  default:                                        return false;
+  }
+}
diff --git a/src/hb-ot-metrics.cc b/src/hb-ot-metrics.cc
new file mode 100644 (file)
index 0000000..d6672c6
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ * Copyright © 2018  Ebrahim Byagowi
+ *
+ *  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.
+ */
+
+#include "hb.hh"
+
+#include "hb-ot-metrics.hh"
+#include "hb-ot-var-mvar-table.hh"
+#include "hb-ot-face.hh"
+
+
+/**
+ * hb_ot_metrics_get_position:
+ * @font:
+ * @metrics_tag:
+ * @position: (out) (optional):
+ *
+ * Returns: Whether found the requested metrics
+ *
+ * Since: REPLACEME
+ **/
+hb_bool_t
+hb_ot_metrics_get_position (hb_font_t       *font,
+                           hb_ot_metrics_t  metrics_tag,
+                           hb_position_t   *position     /* OUT.  May be NULL. */)
+{
+  switch (metrics_tag)
+  {
+  case HB_OT_METRICS_HORIZONTAL_ASCENDER:
+  case HB_OT_METRICS_HORIZONTAL_DESCENDER:
+  case HB_OT_METRICS_HORIZONTAL_LINE_GAP:
+  case HB_OT_METRICS_HORIZONTAL_CLIPPING_ASCENT:
+  case HB_OT_METRICS_HORIZONTAL_CLIPPING_DESCENT:
+  case HB_OT_METRICS_HORIZONTAL_CARET_RISE:
+  case HB_OT_METRICS_VERTICAL_CARET_RUN:
+  case HB_OT_METRICS_VERTICAL_CARET_OFFSET:
+  case HB_OT_METRICS_X_HEIGHT:
+  case HB_OT_METRICS_CAP_HEIGHT:
+  case HB_OT_METRICS_SUBSCRIPT_EM_Y_SIZE:
+  case HB_OT_METRICS_SUBSCRIPT_EM_Y_OFFSET:
+  case HB_OT_METRICS_SUPERSCRIPT_EM_Y_SIZE:
+  case HB_OT_METRICS_SUPERSCRIPT_EM_Y_OFFSET:
+  case HB_OT_METRICS_STRIKEOUT_SIZE:
+  case HB_OT_METRICS_STRIKEOUT_OFFSET:
+  case HB_OT_METRICS_UNDERLINE_SIZE:
+  case HB_OT_METRICS_UNDERLINE_OFFSET: {
+    float value;
+    bool result = hb_ot_metrics_get_position_internal (font->face, metrics_tag, &value);
+    if (result && position) *position = font->em_scalef_y (value);
+    return result;
+  }
+  case HB_OT_METRICS_VERTICAL_ASCENDER:
+  case HB_OT_METRICS_VERTICAL_DESCENDER:
+  case HB_OT_METRICS_VERTICAL_LINE_GAP:
+  case HB_OT_METRICS_HORIZONTAL_CARET_RUN:
+  case HB_OT_METRICS_HORIZONTAL_CARET_OFFSET:
+  case HB_OT_METRICS_VERTICAL_CARET_RISE:
+  case HB_OT_METRICS_SUBSCRIPT_EM_X_SIZE:
+  case HB_OT_METRICS_SUBSCRIPT_EM_X_OFFSET:
+  case HB_OT_METRICS_SUPERSCRIPT_EM_X_SIZE:
+  case HB_OT_METRICS_SUPERSCRIPT_EM_X_OFFSET: {
+    float value;
+    bool result = hb_ot_metrics_get_position_internal (font->face, metrics_tag, &value);
+    if (result && position) *position = font->em_scalef_x (value);
+    return result;
+  }
+  default:
+    return false;
+  }
+}
+
+/**
+ * hb_ot_metrics_get_variation:
+ * @face:
+ * @metrics_tag:
+ *
+ * Returns:
+ *
+ * Since: REPLACEME
+ **/
+float
+hb_ot_metrics_get_variation (hb_face_t *face, hb_ot_metrics_t metrics_tag)
+{
+  return face->table.MVAR->get_var (metrics_tag, nullptr, 0);
+}
+
+/**
+ * hb_ot_metrics_get_x_variation:
+ * @font:
+ * @metrics_tag:
+ *
+ * Returns:
+ *
+ * Since: REPLACEME
+ **/
+hb_position_t
+hb_ot_metrics_get_x_variation (hb_font_t *font, hb_ot_metrics_t metrics_tag)
+{
+  return font->em_scalef_x (hb_ot_metrics_get_variation (font->face, metrics_tag));
+}
+
+/**
+ * hb_ot_metrics_get_y_variation:
+ * @font:
+ * @metrics_tag:
+ *
+ * Returns:
+ *
+ * Since: REPLACEME
+ **/
+hb_position_t
+hb_ot_metrics_get_y_variation (hb_font_t *font, hb_ot_metrics_t metrics_tag)
+{
+  return font->em_scalef_y (hb_ot_metrics_get_variation (font->face, metrics_tag));
+}
diff --git a/src/hb-ot-metrics.h b/src/hb-ot-metrics.h
new file mode 100644 (file)
index 0000000..611222f
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * Copyright © 2018  Ebrahim Byagowi
+ *
+ *  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.
+ */
+
+#ifndef HB_OT_H_IN
+#error "Include <hb-ot.h> instead."
+#endif
+
+#ifndef HB_OT_METRICS_H
+#define HB_OT_METRICS_H
+
+#include "hb.h"
+#include "hb-ot-name.h"
+
+HB_BEGIN_DECLS
+
+
+/**
+ * hb_ot_metrics_t:
+ *
+ * From https://docs.microsoft.com/en-us/typography/opentype/spec/mvar#value-tags
+ *
+ * Since: REPLACEME
+ **/
+typedef enum {
+  HB_OT_METRICS_HORIZONTAL_ASCENDER            = HB_TAG ('h','a','s','c'),
+  HB_OT_METRICS_HORIZONTAL_DESCENDER           = HB_TAG ('h','d','s','c'),
+  HB_OT_METRICS_HORIZONTAL_LINE_GAP            = HB_TAG ('h','l','g','p'),
+  HB_OT_METRICS_HORIZONTAL_CLIPPING_ASCENT     = HB_TAG ('h','c','l','a'),
+  HB_OT_METRICS_HORIZONTAL_CLIPPING_DESCENT    = HB_TAG ('h','c','l','d'),
+  HB_OT_METRICS_VERTICAL_ASCENDER              = HB_TAG ('v','a','s','c'),
+  HB_OT_METRICS_VERTICAL_DESCENDER             = HB_TAG ('v','d','s','c'),
+  HB_OT_METRICS_VERTICAL_LINE_GAP              = HB_TAG ('v','l','g','p'),
+  HB_OT_METRICS_HORIZONTAL_CARET_RISE          = HB_TAG ('h','c','r','s'),
+  HB_OT_METRICS_HORIZONTAL_CARET_RUN           = HB_TAG ('h','c','r','n'),
+  HB_OT_METRICS_HORIZONTAL_CARET_OFFSET                = HB_TAG ('h','c','o','f'),
+  HB_OT_METRICS_VERTICAL_CARET_RISE            = HB_TAG ('v','c','r','s'),
+  HB_OT_METRICS_VERTICAL_CARET_RUN             = HB_TAG ('v','c','r','n'),
+  HB_OT_METRICS_VERTICAL_CARET_OFFSET          = HB_TAG ('v','c','o','f'),
+  HB_OT_METRICS_X_HEIGHT                       = HB_TAG ('x','h','g','t'),
+  HB_OT_METRICS_CAP_HEIGHT                     = HB_TAG ('c','p','h','t'),
+  HB_OT_METRICS_SUBSCRIPT_EM_X_SIZE            = HB_TAG ('s','b','x','s'),
+  HB_OT_METRICS_SUBSCRIPT_EM_Y_SIZE            = HB_TAG ('s','b','y','s'),
+  HB_OT_METRICS_SUBSCRIPT_EM_X_OFFSET          = HB_TAG ('s','b','x','o'),
+  HB_OT_METRICS_SUBSCRIPT_EM_Y_OFFSET          = HB_TAG ('s','b','y','o'),
+  HB_OT_METRICS_SUPERSCRIPT_EM_X_SIZE          = HB_TAG ('s','p','x','s'),
+  HB_OT_METRICS_SUPERSCRIPT_EM_Y_SIZE          = HB_TAG ('s','p','y','s'),
+  HB_OT_METRICS_SUPERSCRIPT_EM_X_OFFSET                = HB_TAG ('s','p','x','o'),
+  HB_OT_METRICS_SUPERSCRIPT_EM_Y_OFFSET                = HB_TAG ('s','p','y','o'),
+  HB_OT_METRICS_STRIKEOUT_SIZE                 = HB_TAG ('s','t','r','s'),
+  HB_OT_METRICS_STRIKEOUT_OFFSET               = HB_TAG ('s','t','r','o'),
+  HB_OT_METRICS_UNDERLINE_SIZE                 = HB_TAG ('u','n','d','s'),
+  HB_OT_METRICS_UNDERLINE_OFFSET               = HB_TAG ('u','n','d','o')
+} hb_ot_metrics_t;
+
+HB_EXTERN hb_bool_t
+hb_ot_metrics_get_position (hb_font_t       *font,
+                           hb_ot_metrics_t  metrics_tag,
+                           hb_position_t   *position     /* OUT.  May be NULL. */);
+
+HB_EXTERN float
+hb_ot_metrics_get_variation (hb_face_t *face, hb_ot_metrics_t metrics_tag);
+
+HB_EXTERN hb_position_t
+hb_ot_metrics_get_x_variation (hb_font_t *font, hb_ot_metrics_t metrics_tag);
+
+HB_EXTERN hb_position_t
+hb_ot_metrics_get_y_variation (hb_font_t *font, hb_ot_metrics_t metrics_tag);
+
+HB_END_DECLS
+
+#endif /* HB_OT_METRICS_H */
diff --git a/src/hb-ot-metrics.hh b/src/hb-ot-metrics.hh
new file mode 100644 (file)
index 0000000..e813f46
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright © 2018  Ebrahim Byagowi
+ *
+ *  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.
+ */
+
+#ifndef HB_OT_METRICS_HH
+#define HB_OT_METRICS_HH
+
+#include "hb.hh"
+
+HB_INTERNAL bool
+hb_ot_metrics_get_position_internal (hb_face_t       *face,
+                                    hb_ot_metrics_t  metrics_tag,
+                                    float           *position     /* OUT.  May be NULL. */);
+
+#endif /* HB_OT_METRICS_HH */
index 16e29ca..bfe8ef9 100644 (file)
@@ -59,6 +59,10 @@ struct OS2V1Tail
 
 struct OS2V2Tail
 {
+  bool has_data () const { return this != &Null (OS2V2Tail); }
+
+  const OS2V2Tail * operator -> () const { return this; }
+
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
index 720e03b..fb826cd 100644 (file)
@@ -178,6 +178,8 @@ struct post
       return false;
     }
 
+    hb_blob_ptr_t<post> table;
+
     protected:
 
     unsigned int get_glyph_count () const
@@ -237,7 +239,6 @@ struct post
     }
 
     private:
-    hb_blob_ptr_t<post> table;
     uint32_t version;
     const ArrayOf<HBUINT16> *glyphNameIndex;
     hb_vector_t<uint32_t> index_to_offset;
@@ -245,6 +246,8 @@ struct post
     hb_atomic_ptr_t<uint16_t *> gids_sorted_by_name;
   };
 
+  bool has_data () const { return version.to_int (); }
+
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
index db78469..d00ee80 100644 (file)
@@ -35,6 +35,7 @@
 #include "hb-ot-font.h"
 #include "hb-ot-layout.h"
 #include "hb-ot-math.h"
+#include "hb-ot-metrics.h"
 #include "hb-ot-name.h"
 #include "hb-ot-shape.h"
 #include "hb-ot-var.h"
index b9d4d79..63c7195 100644 (file)
@@ -84,6 +84,7 @@ TEST_PROGS += \
        test-ot-color \
        test-ot-ligature-carets \
        test-ot-name \
+       test-ot-metrics \
        test-ot-tag \
        test-ot-extents-cff \
        $(NULL)
diff --git a/test/api/test-ot-metrics.c b/test/api/test-ot-metrics.c
new file mode 100644 (file)
index 0000000..270de88
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright © 2018  Ebrahim Byagowi
+ *
+ *  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.
+ */
+
+#include "hb-test.h"
+
+#include <hb-ot.h>
+
+#include <math.h>
+
+/* Unit tests for hb-ot-metrics.h */
+
+static void
+test_ot_metrics_get (void)
+{
+  hb_face_t *face = hb_test_open_font_file ("fonts/cpal-v0.ttf");
+  hb_font_t *font = hb_font_create (face);
+  hb_position_t value;
+  g_assert (hb_ot_metrics_get_position (font, HB_OT_METRICS_HORIZONTAL_ASCENDER, &value));
+  g_assert_cmpint (value, ==, 1000);
+  g_assert_cmpint (hb_ot_metrics_get_x_variation (font, HB_OT_METRICS_HORIZONTAL_ASCENDER), ==, 0);
+  g_assert_cmpint (hb_ot_metrics_get_y_variation (font, HB_OT_METRICS_HORIZONTAL_ASCENDER), ==, 0);
+  // g_assert_cmpint ((int) hb_ot_metrics_get_variation (face, HB_OT_METRICS_HORIZONTAL_ASCENDER), ==, 0);
+  hb_font_destroy (font);
+  hb_face_destroy (face);
+}
+
+int
+main (int argc, char **argv)
+{
+  hb_test_init (&argc, &argv);
+  hb_test_add (test_ot_metrics_get);
+  return hb_test_run ();
+}