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

Behdad Esfahbod behdad at kemper.freedesktop.org
Tue Apr 17 13:29:40 UTC 2018


 src/Makefile.am                                |    4 
 src/dump-fon.cc                                |  568 +++++++++++++++++++++++++
 src/hb-aat-layout-morx-table.hh                |    1 
 src/hb-aat-layout-trak-table.hh                |    1 
 src/hb-common.h                                |   10 
 src/hb-open-type-private.hh                    |   10 
 src/hb-ot-cmap-table.hh                        |   66 ++
 src/hb-ot-hdmx-table.hh                        |    1 
 src/hb-ot-hmtx-table.hh                        |    1 
 src/hb-ot-layout-common-private.hh             |    2 
 src/hb-ot-os2-table.hh                         |   19 
 src/hb-ot-post-table.hh                        |    1 
 src/hb-private.hh                              |    6 
 src/hb-subset.cc                               |   14 
 src/hb-subset.h                                |    5 
 src/hb-ucdn/ucdn.h                             |   10 
 test/api/Makefile.am                           |    2 
 test/api/fonts/Roboto-Regular.abc.format12.ttf |binary
 test/api/fonts/Roboto-Regular.abc.format4.ttf  |binary
 test/api/test-subset-codepoints.c              |  103 ++++
 20 files changed, 809 insertions(+), 15 deletions(-)

New commits:
commit 5dadbb0fa096574b6bccd75cced203baf615fedf
Author: Garret Rieger <grieger at google.com>
Date:   Tue Apr 17 07:00:23 2018 -0600

    [subset] Add implementation of cmap format 12 codepoint listing. (#988)

diff --git a/src/hb-ot-cmap-table.hh b/src/hb-ot-cmap-table.hh
index c7c5d0a9..5e71eaba 100644
--- a/src/hb-ot-cmap-table.hh
+++ b/src/hb-ot-cmap-table.hh
@@ -204,6 +204,8 @@ struct CmapSubtableLongGroup
 {
   friend struct CmapSubtableFormat12;
   friend struct CmapSubtableFormat13;
+  template<typename U>
+  friend struct CmapSubtableLongSegmented;
   friend struct cmap;
 
   int cmp (hb_codepoint_t codepoint) const
@@ -276,6 +278,15 @@ struct CmapSubtableLongSegmented
     return true;
   }
 
+  inline void get_all_codepoints (hb_set_t *out) const
+  {
+    for (unsigned int i = 0; i < this->groups.len; i++) {
+      hb_set_add_range (out,
+			this->groups[i].startCharCode,
+			this->groups[i].endCharCode);
+    }
+  }
+
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
@@ -690,7 +701,7 @@ struct cmap
 	  break;
 	case 12:
 	  this->get_glyph_func = get_glyph_from<OT::CmapSubtableFormat12>;
-	  this->get_all_codepoints_func = null_get_all_codepoints_func;
+	  this->get_all_codepoints_func = get_all_codepoints_from<OT::CmapSubtableFormat12>;
 	  break;
 	case  4:
 	  {
@@ -758,6 +769,14 @@ struct cmap
     }
 
     template <typename Type>
+    static inline void get_all_codepoints_from (const void *obj,
+						hb_set_t *out)
+    {
+      const Type *typed_obj = (const Type *) obj;
+      typed_obj->get_all_codepoints (out);
+    }
+
+    template <typename Type>
     static inline bool get_glyph_from_symbol (const void *obj,
 					      hb_codepoint_t codepoint,
 					      hb_codepoint_t *glyph)
diff --git a/test/api/fonts/Roboto-Regular.abc.format12.ttf b/test/api/fonts/Roboto-Regular.abc.format12.ttf
new file mode 100644
index 00000000..5aa63341
Binary files /dev/null and b/test/api/fonts/Roboto-Regular.abc.format12.ttf differ
diff --git a/test/api/test-subset-codepoints.c b/test/api/test-subset-codepoints.c
index c4f9c0ee..3bd1fe06 100644
--- a/test/api/test-subset-codepoints.c
+++ b/test/api/test-subset-codepoints.c
@@ -48,12 +48,56 @@ test_get_all_codepoints_format4 (void)
   hb_face_destroy (face);
 }
 
+static void
+test_get_all_codepoints_format12 (void)
+{
+  hb_face_t *face = hb_subset_test_open_font("fonts/Roboto-Regular.abc.format12.ttf");
+  hb_set_t *codepoints = hb_set_create();
+
+  hb_subset_get_all_codepoints (face, codepoints);
+
+  hb_codepoint_t cp = HB_SET_VALUE_INVALID;
+  g_assert (hb_set_next (codepoints, &cp));
+  g_assert_cmpuint (0x61, ==, cp);
+  g_assert (hb_set_next (codepoints, &cp));
+  g_assert_cmpuint (0x62, ==, cp);
+  g_assert (hb_set_next (codepoints, &cp));
+  g_assert_cmpuint (0x63, ==, cp);
+  g_assert (!hb_set_next (codepoints, &cp));
+
+  hb_set_destroy (codepoints);
+  hb_face_destroy (face);
+}
+
+static void
+test_get_all_codepoints (void)
+{
+  hb_face_t *face = hb_subset_test_open_font("fonts/Roboto-Regular.abc.ttf");
+  hb_set_t *codepoints = hb_set_create();
+
+  hb_subset_get_all_codepoints (face, codepoints);
+
+  hb_codepoint_t cp = HB_SET_VALUE_INVALID;
+  g_assert (hb_set_next (codepoints, &cp));
+  g_assert_cmpuint (0x61, ==, cp);
+  g_assert (hb_set_next (codepoints, &cp));
+  g_assert_cmpuint (0x62, ==, cp);
+  g_assert (hb_set_next (codepoints, &cp));
+  g_assert_cmpuint (0x63, ==, cp);
+  g_assert (!hb_set_next (codepoints, &cp));
+
+  hb_set_destroy (codepoints);
+  hb_face_destroy (face);
+}
+
 int
 main (int argc, char **argv)
 {
   hb_test_init (&argc, &argv);
 
+  hb_test_add (test_get_all_codepoints);
   hb_test_add (test_get_all_codepoints_format4);
+  hb_test_add (test_get_all_codepoints_format12);
 
   return hb_test_run();
 }
commit 6771e79bcc2166b5c03ca615d271c8508d692416
Author: Ebrahim Byagowi <ebrahim at gnu.org>
Date:   Tue Apr 17 09:36:52 2018 +0430

    Add pre-opentype font pages detection code (#986)
    
    As Khaled's finding on #981 this is the way Uniscribe detects those fonts. This is its detection part.

diff --git a/src/hb-ot-os2-table.hh b/src/hb-ot-os2-table.hh
index 84dce2fb..dfb87dc0 100644
--- a/src/hb-ot-os2-table.hh
+++ b/src/hb-ot-os2-table.hh
@@ -125,6 +125,24 @@ struct os2
     *max_cp = max;
   }
 
+  enum font_page_t {
+    HEBREW_FONT_PAGE		= 0xB100, // Hebrew Windows 3.1 font page
+    SIMP_ARABIC_FONT_PAGE	= 0xB200, // Simplified Arabic Windows 3.1 font page
+    TRAD_ARABIC_FONT_PAGE	= 0xB300, // Traditional Arabic Windows 3.1 font page
+    OEM_ARABIC_FONT_PAGE	= 0xB400, // OEM Arabic Windows 3.1 font page
+    SIMP_FARSI_FONT_PAGE	= 0xBA00, // Simplified Farsi Windows 3.1 font page
+    TRAD_FARSI_FONT_PAGE	= 0xBB00, // Traditional Farsi Windows 3.1 font page
+    THAI_FONT_PAGE		= 0xDE00  // Thai Windows 3.1 font page
+  };
+
+  // https://github.com/Microsoft/Font-Validator/blob/520aaae/OTFontFileVal/val_OS2.cs#L644-L681
+  inline font_page_t get_font_page () const
+  {
+    if (version != 0)
+      return (font_page_t) 0;
+    return (font_page_t) (fsSelection & 0xFF00);
+  }
+
   public:
   HBUINT16	version;
 
commit 277e328986d5887fa93c72dc8b12d842d41db87f
Author: Ebrahim Byagowi <ebrahim at gnu.org>
Date:   Tue Apr 17 09:13:35 2018 +0430

    Make some of implicit header uses explicit (#989)
    
    Splitted from #950 and #986 IIRC Chromium had a policy about this encouraging it,
    not sure about automated way to detect and add them but for now lets have the needed
    ones of them.

diff --git a/src/hb-aat-layout-morx-table.hh b/src/hb-aat-layout-morx-table.hh
index f785e726..8b27d670 100644
--- a/src/hb-aat-layout-morx-table.hh
+++ b/src/hb-aat-layout-morx-table.hh
@@ -29,6 +29,7 @@
 
 #include "hb-open-type-private.hh"
 #include "hb-aat-layout-common-private.hh"
+#include "hb-ot-layout-common-private.hh"
 
 /*
  * morx -- Extended Glyph Metamorphosis
diff --git a/src/hb-aat-layout-trak-table.hh b/src/hb-aat-layout-trak-table.hh
index a4714883..70f551a8 100644
--- a/src/hb-aat-layout-trak-table.hh
+++ b/src/hb-aat-layout-trak-table.hh
@@ -29,6 +29,7 @@
 #define HB_AAT_LAYOUT_TRAK_TABLE_HH
 
 #include "hb-aat-layout-common-private.hh"
+#include "hb-ot-layout-private.hh"
 #include "hb-open-type-private.hh"
 
 /*
diff --git a/src/hb-ot-hdmx-table.hh b/src/hb-ot-hdmx-table.hh
index 4ad78d2e..1c4f817c 100644
--- a/src/hb-ot-hdmx-table.hh
+++ b/src/hb-ot-hdmx-table.hh
@@ -28,6 +28,7 @@
 #define HB_OT_HDMX_TABLE_HH
 
 #include "hb-open-type-private.hh"
+#include "hb-subset-plan.hh"
 
 /*
  * hdmx -- Horizontal Device Metrics
diff --git a/src/hb-ot-hmtx-table.hh b/src/hb-ot-hmtx-table.hh
index bfc3e6a2..b209a4ec 100644
--- a/src/hb-ot-hmtx-table.hh
+++ b/src/hb-ot-hmtx-table.hh
@@ -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-subset-plan.hh"
 
 /*
  * hmtx -- Horizontal Metrics
diff --git a/src/hb-ot-os2-table.hh b/src/hb-ot-os2-table.hh
index 93c0fff2..84dce2fb 100644
--- a/src/hb-ot-os2-table.hh
+++ b/src/hb-ot-os2-table.hh
@@ -29,6 +29,7 @@
 
 #include "hb-open-type-private.hh"
 #include "hb-ot-os2-unicode-ranges.hh"
+#include "hb-subset-plan.hh"
 
 namespace OT {
 
diff --git a/src/hb-ot-post-table.hh b/src/hb-ot-post-table.hh
index 12e4cc92..1441e2cb 100644
--- a/src/hb-ot-post-table.hh
+++ b/src/hb-ot-post-table.hh
@@ -29,6 +29,7 @@
 
 #include "hb-open-type-private.hh"
 #include "hb-dsalgs.hh"
+#include "hb-subset-plan.hh"
 
 #define HB_STRING_ARRAY_NAME format1_names
 #define HB_STRING_ARRAY_LIST "hb-ot-post-macroman.hh"
commit f5811bad04be9dac8a4fca8e16904d6270e47777
Author: Ebrahim Byagowi <ebrahim at gnu.org>
Date:   Tue Apr 17 09:13:03 2018 +0430

    Add round to F2DOT14 inner store setter (#990)
    
    It uses floor implicitly without it but explicit use of round will be more correct.

diff --git a/src/hb-open-type-private.hh b/src/hb-open-type-private.hh
index 623d0b2e..1f2421b0 100644
--- a/src/hb-open-type-private.hh
+++ b/src/hb-open-type-private.hh
@@ -685,7 +685,7 @@ struct F2DOT14 : HBINT16
 {
   // 16384 means 1<<14
   inline float to_float (void) const { return ((int32_t) v) / 16384.0; }
-  inline void set_float (float f) { v.set (f * 16384.0); }
+  inline void set_float (float f) { v.set (round (f * 16384.0)); }
   public:
   DEFINE_SIZE_STATIC (2);
 };
commit 39754fb65981fa8d11615e1dced852285ad09e4e
Author: Garret Rieger <grieger at google.com>
Date:   Mon Apr 16 15:09:27 2018 -0700

    [subset] Don't assume the last segment in cmap 4 can be skipped, actually check it.

diff --git a/src/hb-ot-cmap-table.hh b/src/hb-ot-cmap-table.hh
index f94dc068..c7c5d0a9 100644
--- a/src/hb-ot-cmap-table.hh
+++ b/src/hb-ot-cmap-table.hh
@@ -130,8 +130,12 @@ struct CmapSubtableFormat4
     static inline void get_all_codepoints_func (const void *obj, hb_set_t *out)
     {
       const accelerator_t *thiz = (const accelerator_t *) obj;
-      for (unsigned int i = 0; i < thiz->segCount - 1; i++) // Skip the last segment (0xFFFF)
-	hb_set_add_range (out, thiz->startCount[i], thiz->endCount[i]);
+      for (unsigned int i = 0; i < thiz->segCount; i++)
+      {
+	if (thiz->startCount[i] != 0xFFFFu
+	    || thiz->endCount[i] != 0xFFFFu) // Skip the last segment (0xFFFF)
+	  hb_set_add_range (out, thiz->startCount[i], thiz->endCount[i]);
+      }
     }
 
     const HBUINT16 *endCount;
commit 21a181af2bf1582991c55de5f9281494733c5d12
Author: Garret Rieger <grieger at google.com>
Date:   Tue Apr 10 15:40:24 2018 -0700

    [subset] sketch out support for a call that lists all codepoints present in a font. Implement support for it in format 4 cmap sub table.

diff --git a/src/hb-ot-cmap-table.hh b/src/hb-ot-cmap-table.hh
index c2bfe4b5..f94dc068 100644
--- a/src/hb-ot-cmap-table.hh
+++ b/src/hb-ot-cmap-table.hh
@@ -127,6 +127,13 @@ struct CmapSubtableFormat4
       return true;
     }
 
+    static inline void get_all_codepoints_func (const void *obj, hb_set_t *out)
+    {
+      const accelerator_t *thiz = (const accelerator_t *) obj;
+      for (unsigned int i = 0; i < thiz->segCount - 1; i++) // Skip the last segment (0xFFFF)
+	hb_set_add_range (out, thiz->startCount[i], thiz->endCount[i]);
+    }
+
     const HBUINT16 *endCount;
     const HBUINT16 *startCount;
     const HBUINT16 *idDelta;
@@ -667,20 +674,30 @@ struct cmap
 
       this->get_glyph_data = subtable;
       if (unlikely (symbol))
+      {
 	this->get_glyph_func = get_glyph_from_symbol<OT::CmapSubtable>;
-      else
+	this->get_all_codepoints_func = null_get_all_codepoints_func;
+      } else {
 	switch (subtable->u.format) {
 	/* Accelerate format 4 and format 12. */
-	default: this->get_glyph_func = get_glyph_from<OT::CmapSubtable>;		break;
-	case 12: this->get_glyph_func = get_glyph_from<OT::CmapSubtableFormat12>;	break;
+	default:
+	  this->get_glyph_func = get_glyph_from<OT::CmapSubtable>;
+	  this->get_all_codepoints_func = null_get_all_codepoints_func;
+	  break;
+	case 12:
+	  this->get_glyph_func = get_glyph_from<OT::CmapSubtableFormat12>;
+	  this->get_all_codepoints_func = null_get_all_codepoints_func;
+	  break;
 	case  4:
 	  {
 	    this->format4_accel.init (&subtable->u.format4);
 	    this->get_glyph_data = &this->format4_accel;
 	    this->get_glyph_func = this->format4_accel.get_glyph_func;
+	    this->get_all_codepoints_func = this->format4_accel.get_all_codepoints_func;
 	  }
 	  break;
 	}
+      }
     }
 
     inline void fini (void)
@@ -710,10 +727,22 @@ struct cmap
       return get_nominal_glyph (unicode, glyph);
     }
 
+    inline void get_all_codepoints (hb_set_t *out) const
+    {
+      this->get_all_codepoints_func (get_glyph_data, out);
+    }
+
     protected:
     typedef bool (*hb_cmap_get_glyph_func_t) (const void *obj,
 					      hb_codepoint_t codepoint,
 					      hb_codepoint_t *glyph);
+    typedef void (*hb_cmap_get_all_codepoints_func_t) (const void *obj,
+						       hb_set_t *out);
+
+    static inline void null_get_all_codepoints_func (const void *obj, hb_set_t *out)
+    {
+      // NOOP
+    }
 
     template <typename Type>
     static inline bool get_glyph_from (const void *obj,
@@ -749,6 +778,8 @@ struct cmap
     private:
     hb_cmap_get_glyph_func_t get_glyph_func;
     const void *get_glyph_data;
+    hb_cmap_get_all_codepoints_func_t get_all_codepoints_func;
+
     OT::CmapSubtableFormat4::accelerator_t format4_accel;
 
     const OT::CmapSubtableFormat14 *uvs_table;
diff --git a/src/hb-subset.cc b/src/hb-subset.cc
index b253817e..5da46c79 100644
--- a/src/hb-subset.cc
+++ b/src/hb-subset.cc
@@ -371,3 +371,17 @@ hb_subset (hb_face_t *source,
   hb_subset_plan_destroy (plan);
   return result;
 }
+
+/**
+ * hb_subset_get_all_codepoints:
+ * @source: font face data to load.
+ * @out: set to add the all codepoints covered by font face, source.
+ */
+void
+hb_subset_get_all_codepoints (hb_face_t *source, hb_set_t *out)
+{
+  OT::cmap::accelerator_t cmap;
+  cmap.init (source);
+  cmap.get_all_codepoints (out);
+  cmap.fini();
+}
diff --git a/src/hb-subset.h b/src/hb-subset.h
index 55ce25b0..409581c7 100644
--- a/src/hb-subset.h
+++ b/src/hb-subset.h
@@ -72,12 +72,15 @@ HB_EXTERN hb_bool_t *
 hb_subset_input_drop_hints (hb_subset_input_t *subset_input);
 
 /* hb_subset() */
-
 HB_EXTERN hb_face_t *
 hb_subset (hb_face_t *source,
 	   hb_subset_profile_t *profile,
            hb_subset_input_t *input);
 
+/* hb_subset_get_all_codepoints */
+HB_EXTERN void
+hb_subset_get_all_codepoints (hb_face_t *source, hb_set_t *out);
+
 HB_END_DECLS
 
 #endif /* HB_SUBSET_H */
diff --git a/test/api/Makefile.am b/test/api/Makefile.am
index 0f7c82f7..65ceeda3 100644
--- a/test/api/Makefile.am
+++ b/test/api/Makefile.am
@@ -32,6 +32,7 @@ TEST_PROGS = \
 	test-set \
 	test-shape \
 	test-subset \
+	test-subset-codepoints \
 	test-subset-cmap \
 	test-subset-glyf \
 	test-subset-hdmx \
@@ -44,6 +45,7 @@ TEST_PROGS = \
 	$(NULL)
 
 test_subset_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la
+test_subset_codepoints_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la
 test_subset_cmap_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la
 test_subset_glyf_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la
 test_subset_hdmx_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la
diff --git a/test/api/fonts/Roboto-Regular.abc.format4.ttf b/test/api/fonts/Roboto-Regular.abc.format4.ttf
new file mode 100644
index 00000000..ccb074a8
Binary files /dev/null and b/test/api/fonts/Roboto-Regular.abc.format4.ttf differ
diff --git a/test/api/test-subset-codepoints.c b/test/api/test-subset-codepoints.c
new file mode 100644
index 00000000..c4f9c0ee
--- /dev/null
+++ b/test/api/test-subset-codepoints.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright © 2018  Google, Inc.
+ *
+ *  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.
+ *
+ * Google Author(s): Garret Rieger
+ */
+
+#include "hb-test.h"
+#include "hb-subset-test.h"
+
+static void
+test_get_all_codepoints_format4 (void)
+{
+  hb_face_t *face = hb_subset_test_open_font("fonts/Roboto-Regular.abc.format4.ttf");
+  hb_set_t *codepoints = hb_set_create();
+
+  hb_subset_get_all_codepoints (face, codepoints);
+
+  hb_codepoint_t cp = HB_SET_VALUE_INVALID;
+  g_assert (hb_set_next (codepoints, &cp));
+  g_assert_cmpuint (0x61, ==, cp);
+  g_assert (hb_set_next (codepoints, &cp));
+  g_assert_cmpuint (0x62, ==, cp);
+  g_assert (hb_set_next (codepoints, &cp));
+  g_assert_cmpuint (0x63, ==, cp);
+  g_assert (!hb_set_next (codepoints, &cp));
+
+  hb_set_destroy (codepoints);
+  hb_face_destroy (face);
+}
+
+int
+main (int argc, char **argv)
+{
+  hb_test_init (&argc, &argv);
+
+  hb_test_add (test_get_all_codepoints_format4);
+
+  return hb_test_run();
+}
commit aef96e246cb695c4c83b8b6daed06a0d14fe1d32
Author: Ebrahim Byagowi <ebrahim at gnu.org>
Date:   Mon Apr 16 18:30:25 2018 +0430

    Further improvements on dump-fon (#985)

diff --git a/src/dump-fon.cc b/src/dump-fon.cc
index 76a39c84..4d923563 100644
--- a/src/dump-fon.cc
+++ b/src/dump-fon.cc
@@ -128,15 +128,10 @@ typedef LEIntType<uint32_t, 3> LEUINT24;	/* 24-bit unsigned integer. */
 
 struct LE_FONTINFO16
 {
-  inline bool sanitize (OT::hb_sanitize_context_t *c) const
+  inline bool sanitize (OT::hb_sanitize_context_t *c, unsigned int length) const
   {
     TRACE_SANITIZE (this);
-    return_trace (likely (c->check_struct (this)));
-  }
-
-  inline unsigned int get_charset () const
-  {
-    return dfCharSet;
+    return_trace (likely (c->check_struct (this) && c->check_range (this, length)));
   }
 
   // https://msdn.microsoft.com/en-us/library/cc194829.aspx
@@ -161,6 +156,102 @@ struct LE_FONTINFO16
     OEM		= 0xFF	//
   };
 
+  inline const char* get_charset() const
+  {
+    switch (dfCharSet) {
+    case ANSI: return "ISO8859";
+    case DEFAULT: return "WinDefault";
+    case SYMBOL: return "Symbol";
+    case SHIFTJIS: return "JISX0208.1983";
+    case HANGUL: return "MSHangul";
+    case GB2312: return "GB2312.1980";
+    case CHINESEBIG5: return "Big5";
+    case GREEK: return "CP1253";
+    case TURKISH: return "CP1254";
+    case HEBREW: return "CP1255";
+    case ARABIC: return "CP1256";
+    case BALTIC: return "CP1257";
+    case RUSSIAN: return "CP1251";
+    case THAI: return "CP874";
+    case EE: return "CP1250";
+    case OEM: return "OEM";
+    default: return "Unknown";
+    }
+  }
+
+  inline unsigned int get_version () const
+  {
+    return dfVersion;
+  }
+
+  inline unsigned int get_weight () const
+  {
+    return dfWeight;
+  }
+
+  enum weight_t {
+    DONTCARE	= 0,
+    THIN	= 100,
+    EXTRALIGHT	= 200,
+    ULTRALIGHT	= 200,
+    LIGHT	= 300,
+    NORMAL	= 400,
+    REGULAR	= 400,
+    MEDIUM	= 500,
+    SEMIBOLD	= 600,
+    DEMIBOLD	= 600,
+    BOLD	= 700,
+    EXTRABOLD	= 800,
+    ULTRABOLD	= 800,
+    HEAVY	= 900,
+    BLACK	= 900
+  };
+
+  inline void dump () const
+  {
+    // With https://github.com/juanitogan/mkwinfont/blob/master/python/dewinfont.py help
+    // Should be implemented differently eventually, but for now
+    unsigned int ctstart;
+    unsigned int ctsize;
+    if (dfVersion == 0x200)
+    {
+      ctstart = 0x76;
+      ctsize = 4;
+    }
+    else
+    {
+      return; // must of ".fon"s are version 2 and even dewinfont V1 implmentation doesn't seem correct
+      ctstart = 0x94;
+      ctsize = 6;
+    }
+    // unsigned int maxwidth = 0;
+    for (unsigned int i = dfFirstChar; i < dfLastChar; ++i)
+    {
+      unsigned int entry = ctstart + ctsize * (i-dfFirstChar);
+      unsigned int w = (uint16_t) OT::StructAtOffset<LEUINT16> (this, entry);
+
+      unsigned int off;
+      if (ctsize == 4)
+        off = (uint16_t) OT::StructAtOffset<LEUINT16> (this, entry+2);
+      else
+        off = (uint32_t) OT::StructAtOffset<LEUINT32> (this, entry+2);
+
+      unsigned int widthbytes = (w + 7) / 8;
+      for (unsigned int j = 0; j < dfPixHeight; ++j)
+      {
+        for (unsigned int k = 0; k < widthbytes; ++k)
+	{
+	  unsigned int bytepos = off + k * dfPixHeight + j;
+	  const uint8_t b = (uint8_t) OT::StructAtOffset<LEINT8> (this, bytepos);
+	  for (unsigned int a = 128; a > 0; a >>= 1)
+	    printf (b & a ? "x" : ".");
+	}
+	printf ("\n");
+      }
+      printf ("\n\n");
+    }
+  }
+
   protected:
   LEUINT16	dfVersion;
   LEUINT32	dfSize;
@@ -175,7 +266,7 @@ struct LE_FONTINFO16
   LEUINT8	dfItalic;
   LEUINT8	dfUnderline;
   LEUINT8	dfStrikeOut;
-  LEUINT16	dfWeight;
+  LEUINT16	dfWeight; // see weight_t
   LEUINT8	dfCharSet;  // see charset_t
   LEUINT16	dfPixWidth;
   LEUINT16	dfPixHeight;
@@ -192,14 +283,16 @@ struct LE_FONTINFO16
   LEUINT32	dfBitsPointer;
   LEUINT32	dfBitsOffset;
   LEUINT8	dfReserved;
-  LEUINT32	dfFlags;
-  LEUINT16	dfAspace;
-  LEUINT16	dfBspace;
-  LEUINT16	dfCspace;
-  LEUINT32	dfColorPointer;
-  LEUINT32	dfReserved1[4];
+//   LEUINT32	dfFlags;
+//   LEUINT16	dfAspace;
+//   LEUINT16	dfBspace;
+//   LEUINT16	dfCspace;
+//   LEUINT32	dfColorPointer;
+//   LEUINT32	dfReserved1[4];
+  OT::UnsizedArrayOf<LEUINT8>
+		dataZ;
   public:
-  DEFINE_SIZE_STATIC (148);
+  DEFINE_SIZE_ARRAY (118, dataZ);
 };
 
 struct NE_NAMEINFO
@@ -210,14 +303,12 @@ struct NE_NAMEINFO
   {
     TRACE_SANITIZE (this);
     return_trace (likely (c->check_struct (this) &&
-			  c->check_range ((const char*)base + (offset << shift),
-					  length << shift) &&
-			  get_font (base, shift)->sanitize (c)));
+			  get_font (base, shift).sanitize (c, length << shift)));
   }
 
-  inline const LE_FONTINFO16* get_font (const void *base, int shift) const
+  inline const LE_FONTINFO16& get_font (const void *base, int shift) const
   {
-    return (const LE_FONTINFO16 *) ((const char *) base + (offset << shift));
+    return OT::StructAtOffset<LE_FONTINFO16> (base, offset << shift);
   }
 
   enum resource_type_flag_t {
@@ -257,11 +348,11 @@ struct NE_TYPEINFO
     return next;
   }
 
-  inline const LE_FONTINFO16* get_font (unsigned int idx, const void *base, int shift) const
+  inline const LE_FONTINFO16& get_font (unsigned int idx, const void *base, int shift) const
   {
     if (idx < count)
       return resources[idx].get_font (base, shift);
-    return &OT::Null (LE_FONTINFO16);
+    return OT::Null (LE_FONTINFO16);
   }
 
   inline unsigned int get_count () const
@@ -324,22 +415,22 @@ struct NE_RESOURCE_TABLE
     return alignmentShiftCount;
   }
 
-  inline const NE_TYPEINFO* get_fonts_entry () const
+  inline const NE_TYPEINFO& get_fonts_entry () const
   {
     const NE_TYPEINFO* n = &chain;
     while (n != &OT::Null (NE_TYPEINFO) && n->get_type_id () != 0)
     {
       if (n->get_type_id () == NE_TYPEINFO::FONT)
-	return n;
+	return *n;
       n = &n->next();
     }
-    return &OT::Null (NE_TYPEINFO);
+    return OT::Null (NE_TYPEINFO);
   }
 
   protected:
   LEUINT16	alignmentShiftCount;
   NE_TYPEINFO	chain;
-  // It follows by an array of OT::ArrayOf<LEUINT8, LEUINT8> chars;
+  // It is followed by an array of OT::ArrayOf<LEUINT8, LEUINT8> chars;
   public:
   DEFINE_SIZE_MIN (2);
 };
@@ -465,11 +556,13 @@ int main (int argc, char** argv) {
 
   const NE_RESOURCE_TABLE &rtable = dos_header->get_os2_header ().get_resource_table ();
   int shift = rtable.get_shift_value ();
-  const NE_TYPEINFO* entry = rtable.get_fonts_entry ();
-  for (int i = 0; i < entry->get_count (); ++i)
+  const NE_TYPEINFO& entry = rtable.get_fonts_entry ();
+  for (unsigned int i = 0; i < entry.get_count (); ++i)
   {
-    const LE_FONTINFO16* font = entry->get_font (i, dos_header, shift);
-    printf ("charset: %d\n", font->get_charset ());
+    const LE_FONTINFO16& font = entry.get_font (i, dos_header, shift);
+    printf ("version: %x, weight: %d, charset: %s\n", font.get_version (),
+	    font.get_weight (), font.get_charset ());
+    // font.dump ();
   }
   return 0;
 }
commit 67dfb1937b703b3f1dc45251f4f884abf35c8576
Author: Ebrahim Byagowi <ebrahim at gnu.org>
Date:   Mon Apr 16 14:25:45 2018 +0430

    Add dump-fon, a prototype on how to work with .fon/.fnt files (#981)

diff --git a/src/Makefile.am b/src/Makefile.am
index 46fc141a..b4aad51f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -362,11 +362,15 @@ dist_check_SCRIPTS += \
 endif
 
 check_PROGRAMS += \
+	dump-fon \
 	dump-indic-data \
 	dump-khmer-data \
 	dump-myanmar-data \
 	dump-use-data \
 	$(NULL)
+dump_fon_SOURCES = dump-fon.cc
+dump_fon_CPPFLAGS = $(HBCFLAGS)
+dump_fon_LDADD = libharfbuzz.la $(HBLIBS)
 dump_indic_data_SOURCES = dump-indic-data.cc hb-ot-shape-complex-indic-table.cc
 dump_indic_data_CPPFLAGS = $(HBCFLAGS)
 dump_indic_data_LDADD = libharfbuzz.la $(HBLIBS)
diff --git a/src/dump-fon.cc b/src/dump-fon.cc
new file mode 100644
index 00000000..76a39c84
--- /dev/null
+++ b/src/dump-fon.cc
@@ -0,0 +1,475 @@
+/*
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include "hb-open-type-private.hh"
+
+#ifndef HB_NO_VISIBILITY
+const void * const OT::_hb_NullPool[HB_NULL_POOL_SIZE / sizeof (void *)] = {};
+#endif
+
+template <typename Type, int Bytes> struct LEInt;
+
+template <typename Type>
+struct LEInt<Type, 1>
+{
+  public:
+  inline void set (Type V)
+  {
+    v = V;
+  }
+  inline operator Type (void) const
+  {
+    return v;
+  }
+  private: uint8_t v;
+};
+template <typename Type>
+struct LEInt<Type, 2>
+{
+  public:
+  inline void set (Type V)
+  {
+    v[1] = (V >>  8) & 0xFF;
+    v[0] = (V      ) & 0xFF;
+  }
+  inline operator Type (void) const
+  {
+    return (v[1] <<  8)
+         + (v[0]      );
+  }
+  private: uint8_t v[2];
+};
+template <typename Type>
+struct LEInt<Type, 3>
+{
+  public:
+  inline void set (Type V)
+  {
+    v[2] = (V >> 16) & 0xFF;
+    v[1] = (V >>  8) & 0xFF;
+    v[0] = (V      ) & 0xFF;
+  }
+  inline operator Type (void) const
+  {
+    return (v[2] << 16)
+         + (v[1] <<  8)
+         + (v[0]      );
+  }
+  private: uint8_t v[3];
+};
+template <typename Type>
+struct LEInt<Type, 4>
+{
+  public:
+  inline void set (Type V)
+  {
+    v[3] = (V >> 24) & 0xFF;
+    v[2] = (V >> 16) & 0xFF;
+    v[1] = (V >>  8) & 0xFF;
+    v[0] = (V      ) & 0xFF;
+  }
+  inline operator Type (void) const
+  {
+    return (v[3] << 24)
+         + (v[2] << 16)
+         + (v[1] <<  8)
+         + (v[0]      );
+  }
+  private: uint8_t v[4];
+};
+
+template <typename Type, unsigned int Size>
+struct LEIntType
+{
+  inline void set (Type i) { v.set (i); }
+  inline operator Type(void) const { return v; }
+  inline bool sanitize (OT::hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this)));
+  }
+  protected:
+  LEInt<Type, Size> v;
+  public:
+  DEFINE_SIZE_STATIC (Size);
+};
+
+typedef LEIntType<uint8_t,  1> LEUINT8;		/* 8-bit unsigned integer. */
+typedef LEIntType<int8_t,   1> LEINT8;		/* 8-bit signed integer. */
+typedef LEIntType<uint16_t, 2> LEUINT16;	/* 16-bit unsigned integer. */
+typedef LEIntType<int16_t,  2> LEINT16;		/* 16-bit signed integer. */
+typedef LEIntType<uint32_t, 4> LEUINT32;	/* 32-bit unsigned integer. */
+typedef LEIntType<int32_t,  4> LEINT32;		/* 32-bit signed integer. */
+typedef LEIntType<uint32_t, 3> LEUINT24;	/* 24-bit unsigned integer. */
+
+
+struct LE_FONTINFO16
+{
+  inline bool sanitize (OT::hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this)));
+  }
+
+  inline unsigned int get_charset () const
+  {
+    return dfCharSet;
+  }
+
+  // https://msdn.microsoft.com/en-us/library/cc194829.aspx
+  enum charset_t
+  {
+    // dfCharSet possible values and the codepage they are indicating to
+    ANSI	= 0x00,	// 1252
+    DEFAULT	= 0x01,	//
+    SYMBOL	= 0x02,	//
+    SHIFTJIS	= 0x80,	// 932
+    HANGUL	= 0x81,	// 949
+    GB2312	= 0x86,	// 936
+    CHINESEBIG5	= 0x88,	// 950
+    GREEK	= 0xA1,	// 1253
+    TURKISH	= 0xA2,	// 1254
+    HEBREW	= 0xB1,	// 1255
+    ARABIC	= 0xB2,	// 1256
+    BALTIC	= 0xBA,	// 1257
+    RUSSIAN	= 0xCC,	// 1251
+    THAI	= 0xDE,	// 874
+    EE		= 0xEE,	// 1250
+    OEM		= 0xFF	//
+  };
+
+  protected:
+  LEUINT16	dfVersion;
+  LEUINT32	dfSize;
+  LEUINT8	dfCopyright[60];
+  LEUINT16	dfType;
+  LEUINT16	dfPoints;
+  LEUINT16	dfVertRes;
+  LEUINT16	dfHorizRes;
+  LEUINT16	dfAscent;
+  LEUINT16	dfInternalLeading;
+  LEUINT16	dfExternalLeading;
+  LEUINT8	dfItalic;
+  LEUINT8	dfUnderline;
+  LEUINT8	dfStrikeOut;
+  LEUINT16	dfWeight;
+  LEUINT8	dfCharSet;  // see charset_t
+  LEUINT16	dfPixWidth;
+  LEUINT16	dfPixHeight;
+  LEUINT8	dfPitchAndFamily;
+  LEUINT16	dfAvgWidth;
+  LEUINT16	dfMaxWidth;
+  LEUINT8	dfFirstChar;
+  LEUINT8	dfLastChar;
+  LEUINT8	dfDefaultChar;
+  LEUINT8	dfBreakChar;
+  LEUINT16	dfWidthBytes;
+  LEUINT32	dfDevice;
+  LEUINT32	dfFace;
+  LEUINT32	dfBitsPointer;
+  LEUINT32	dfBitsOffset;
+  LEUINT8	dfReserved;
+  LEUINT32	dfFlags;
+  LEUINT16	dfAspace;
+  LEUINT16	dfBspace;
+  LEUINT16	dfCspace;
+  LEUINT32	dfColorPointer;
+  LEUINT32	dfReserved1[4];
+  public:
+  DEFINE_SIZE_STATIC (148);
+};
+
+struct NE_NAMEINFO
+{
+  friend struct NE_TYPEINFO;
+
+  inline bool sanitize (OT::hb_sanitize_context_t *c, const void *base, unsigned int shift) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this) &&
+			  c->check_range ((const char*)base + (offset << shift),
+					  length << shift) &&
+			  get_font (base, shift)->sanitize (c)));
+  }
+
+  inline const LE_FONTINFO16* get_font (const void *base, int shift) const
+  {
+    return (const LE_FONTINFO16 *) ((const char *) base + (offset << shift));
+  }
+
+  enum resource_type_flag_t {
+    NONE     = 0x0000,
+    MOVEABLE = 0x0010,
+    PURE     = 0x0020,
+    PRELOAD  = 0x0040
+  };
+
+  protected:
+  LEUINT16	offset;	// Should be shifted with alignmentShiftCount before use
+  LEUINT16	length;	// Should be shifted with alignmentShiftCount before use
+  LEUINT16	flags;	// resource_type_flag_t
+  LEUINT16	id;
+  LEUINT16	handle;
+  LEUINT16	usage;
+  public:
+  DEFINE_SIZE_STATIC (12);
+};
+
+struct NE_TYPEINFO
+{
+  inline bool sanitize (OT::hb_sanitize_context_t *c, const void *base, unsigned int shift) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && resources.sanitize (c, count, base, shift));
+  }
+
+  inline unsigned int get_size (void) const
+  { return 8 + count * NE_NAMEINFO::static_size; }
+
+  inline const NE_TYPEINFO& next () const
+  {
+    const NE_TYPEINFO& next = OT::StructAfter<NE_TYPEINFO> (*this);
+    if (type_id == 0)
+      return OT::Null (NE_TYPEINFO);
+    return next;
+  }
+
+  inline const LE_FONTINFO16* get_font (unsigned int idx, const void *base, int shift) const
+  {
+    if (idx < count)
+      return resources[idx].get_font (base, shift);
+    return &OT::Null (LE_FONTINFO16);
+  }
+
+  inline unsigned int get_count () const
+  {
+    return count;
+  }
+
+  inline unsigned int get_type_id () const
+  {
+    return type_id;
+  }
+
+  enum type_id_t {
+    CURSOR		= 0x8001,
+    BITMAP		= 0x8002,
+    ICON		= 0x8003,
+    MENU		= 0x8004,
+    DIALOG		= 0x8005,
+    STRING		= 0x8006,
+    FONT_DIRECTORY	= 0x8007,
+    FONT		= 0x8008,
+    ACCELERATOR_TABLE	= 0x8009,
+    RESOURCE_DATA	= 0x800a,
+    GROUP_CURSOR	= 0x800c,
+    GROUP_ICON		= 0x800e,
+    VERSION		= 0x8010
+  };
+
+  protected:
+  LEUINT16	type_id; // see type_id_t
+  LEUINT16	count;
+  LEUINT32	resloader;
+  OT::UnsizedArrayOf<NE_NAMEINFO>
+		resources;
+  public:
+  DEFINE_SIZE_ARRAY (8, resources);
+};
+
+struct NE_RESOURCE_TABLE
+{
+  inline bool sanitize (OT::hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+
+    if (!c->check_struct (this))
+      return_trace (false);
+
+    const NE_TYPEINFO* n = &chain;
+    while (n != &OT::Null (NE_TYPEINFO) && c->check_struct (n) && n->get_type_id () != 0)
+    {
+      if (n->get_type_id () == NE_TYPEINFO::FONT)
+	return_trace (n->sanitize (c, base, alignmentShiftCount));
+      n = &n->next();
+    }
+    return_trace (false);
+  }
+
+  inline unsigned int get_shift_value () const
+  {
+    return alignmentShiftCount;
+  }
+
+  inline const NE_TYPEINFO* get_fonts_entry () const
+  {
+    const NE_TYPEINFO* n = &chain;
+    while (n != &OT::Null (NE_TYPEINFO) && n->get_type_id () != 0)
+    {
+      if (n->get_type_id () == NE_TYPEINFO::FONT)
+	return n;
+      n = &n->next();
+    }
+    return &OT::Null (NE_TYPEINFO);
+  }
+
+  protected:
+  LEUINT16	alignmentShiftCount;
+  NE_TYPEINFO	chain;
+  // It follows by an array of OT::ArrayOf<LEUINT8, LEUINT8> chars;
+  public:
+  DEFINE_SIZE_MIN (2);
+};
+
+// https://github.com/wine-mirror/wine/blob/master/include/winnt.h#L2467
+struct LE_IMAGE_OS2_HEADER
+{
+  inline bool sanitize (OT::hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this) && (this+rsrctab).sanitize (c, base)));
+  }
+
+  inline const NE_RESOURCE_TABLE& get_resource_table () const
+  {
+    if (magic != 0x454E) // Only NE containers are support for now, NE == 0x454E
+      return OT::Null (NE_RESOURCE_TABLE);
+    return this+rsrctab;
+  }
+
+  protected:
+  LEUINT16	magic;		/* 00 NE signature 'NE' */
+  LEUINT8	ver;		/* 02 Linker version number */
+  LEUINT8	rev;		/* 03 Linker revision number */
+  LEUINT16	enttab;		/* 04 Offset to entry table relative to NE */
+  LEUINT16	cbenttab;	/* 06 Length of entry table in bytes */
+  LEUINT32	crc;		/* 08 Checksum */
+  LEUINT16	flags;		/* 0c Flags about segments in this file */
+  LEUINT16	autodata;	/* 0e Automatic data segment number */
+  LEUINT16	heap;		/* 10 Initial size of local heap */
+  LEUINT16	stack;		/* 12 Initial size of stack */
+  LEUINT32	csip;		/* 14 Initial CS:IP */
+  LEUINT32	sssp;		/* 18 Initial SS:SP */
+  LEUINT16	cseg;		/* 1c # of entries in segment table */
+  LEUINT16	cmod;		/* 1e # of entries in module reference tab. */
+  LEUINT16	cbnrestab;	/* 20 Length of nonresident-name table     */
+  LEUINT16	segtab;		/* 22 Offset to segment table */
+  OT::OffsetTo<NE_RESOURCE_TABLE, LEUINT16>
+		rsrctab;	/* 24 Offset to resource table */
+  LEUINT16	restab;		/* 26 Offset to resident-name table */
+  LEUINT16	modtab;		/* 28 Offset to module reference table */
+  LEUINT16	imptab;		/* 2a Offset to imported name table */
+  LEUINT32	nrestab;	/* 2c Offset to nonresident-name table */
+  LEUINT16	cmovent;	/* 30 # of movable entry points */
+  LEUINT16	align;		/* 32 Logical sector alignment shift count */
+  LEUINT16	cres;		/* 34 # of resource segments */
+  LEUINT8	exetyp;		/* 36 Flags indicating target OS */
+  LEUINT8	flagsothers;	/* 37 Additional information flags */
+  LEUINT16	pretthunks;	/* 38 Offset to return thunks */
+  LEUINT16	psegrefbytes;	/* 3a Offset to segment ref. bytes */
+  LEUINT16	swaparea;	/* 3c Reserved by Microsoft */
+  LEUINT16	expver;		/* 3e Expected Windows version number */
+  public:
+  DEFINE_SIZE_STATIC (64);
+};
+
+struct LE_IMAGE_DOS_HEADER {
+  inline bool sanitize (OT::hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this) &&
+			  get_os2_header ().sanitize (c, this)));
+  }
+
+  inline const LE_IMAGE_OS2_HEADER& get_os2_header () const
+  {
+    return this+e_lfanew;
+  }
+
+  protected:
+  LEUINT16	e_magic;	// Magic number
+  LEUINT16	e_cblp;		// Bytes on last page of file
+  LEUINT16	e_cp;		// Pages in file
+  LEUINT16	e_crlc;		// Relocations
+  LEUINT16	e_cparhdr;	// Size of header in paragraphs
+  LEUINT16	e_minalloc;	// Minimum extra paragraphs needed
+  LEUINT16	e_maxalloc;	// Maximum extra paragraphs needed
+  LEUINT16	e_ss;		// Initial (relative) SS value
+  LEUINT16	e_sp;		// Initial SP value
+  LEUINT16	e_csum;		// Checksum
+  LEUINT16	e_ip;		// Initial IP value
+  LEUINT16	e_cs;		// Initial (relative) CS value
+  LEUINT16	e_lfarlc;	// File address of relocation table
+  LEUINT16	e_ovno;		// Overlay number
+  LEUINT16	e_res_0;	// Reserved words
+  LEUINT16	e_res_1;	// Reserved words
+  LEUINT16	e_res_2;	// Reserved words
+  LEUINT16	e_res_3;	// Reserved words
+  LEUINT16	e_oemid;	// OEM identifier (for e_oeminfo)
+  LEUINT16	e_oeminfo;	// OEM information; e_oemid specific
+  LEUINT16	e_res2_0;	// Reserved words
+  LEUINT16	e_res2_1;	// Reserved words
+  LEUINT16	e_res2_2;	// Reserved words
+  LEUINT16	e_res2_3;	// Reserved words
+  LEUINT16	e_res2_4;	// Reserved words
+  LEUINT16	e_res2_5;	// Reserved words
+  LEUINT16	e_res2_6;	// Reserved words
+  LEUINT16	e_res2_7;	// Reserved words
+  LEUINT16	e_res2_8;	// Reserved words
+  LEUINT16	e_res2_9;	// Reserved words
+  OT::OffsetTo<LE_IMAGE_OS2_HEADER, LEUINT32>
+		e_lfanew;	// File address of new exe header
+  public:
+  DEFINE_SIZE_STATIC (64);
+};
+
+int main (int argc, char** argv) {
+  FILE *f = fopen (argv[1], "rb");
+  fseek (f, 0, SEEK_END);
+  unsigned int len = ftell (f);
+  rewind (f);
+  const char *font_data = (const char *) malloc (len);
+  len = fread ((char *) font_data, 1, len, f);
+
+
+  OT::Sanitizer<LE_IMAGE_DOS_HEADER> sanitizer;
+  hb_blob_t *blob = hb_blob_create (font_data, len, HB_MEMORY_MODE_WRITABLE,
+				    (void *) font_data, free);
+  hb_blob_t *font_blob = sanitizer.sanitize (blob);
+  const LE_IMAGE_DOS_HEADER* dos_header =
+    OT::Sanitizer<LE_IMAGE_DOS_HEADER>::lock_instance (font_blob);
+
+
+  const NE_RESOURCE_TABLE &rtable = dos_header->get_os2_header ().get_resource_table ();
+  int shift = rtable.get_shift_value ();
+  const NE_TYPEINFO* entry = rtable.get_fonts_entry ();
+  for (int i = 0; i < entry->get_count (); ++i)
+  {
+    const LE_FONTINFO16* font = entry->get_font (i, dos_header, shift);
+    printf ("charset: %d\n", font->get_charset ());
+  }
+  return 0;
+}
commit ce99dd04de830c8426af14c11dbee45f8bcc9e60
Author: Ebrahim Byagowi <ebrahim at gnu.org>
Date:   Sun Apr 15 22:08:50 2018 +0430

    Implement to_float and set_float of F2DOT14 (#984)

diff --git a/src/hb-open-type-private.hh b/src/hb-open-type-private.hh
index 38c5613a..623d0b2e 100644
--- a/src/hb-open-type-private.hh
+++ b/src/hb-open-type-private.hh
@@ -683,15 +683,17 @@ typedef HBUINT16 UFWORD;
 /* 16-bit signed fixed number with the low 14 bits of fraction (2.14). */
 struct F2DOT14 : HBINT16
 {
-  //inline float to_float (void) const { return ???; }
-  //inline void set_float (float f) { v.set (f * ???); }
+  // 16384 means 1<<14
+  inline float to_float (void) const { return ((int32_t) v) / 16384.0; }
+  inline void set_float (float f) { v.set (f * 16384.0); }
   public:
   DEFINE_SIZE_STATIC (2);
 };
 
 /* 32-bit signed fixed-point number (16.16). */
-struct Fixed: HBINT32
+struct Fixed : HBINT32
 {
+  // 65536 means 1<<16
   inline float to_float (void) const { return ((int32_t) v) / 65536.0; }
   inline void set_float (float f) { v.set (round (f * 65536.0)); }
   public:
commit 435b1878e710b67e21872572ad9fd5ed1369e97f
Author: Ebrahim Byagowi <ebrahim at gnu.org>
Date:   Sun Apr 15 21:18:48 2018 +0430

    Rename UINT24 to HBUINT24 for consistency (#983)

diff --git a/src/hb-open-type-private.hh b/src/hb-open-type-private.hh
index beefff14..38c5613a 100644
--- a/src/hb-open-type-private.hh
+++ b/src/hb-open-type-private.hh
@@ -672,7 +672,7 @@ typedef IntType<uint16_t, 2> HBUINT16;	/* 16-bit unsigned integer. */
 typedef IntType<int16_t,  2> HBINT16;	/* 16-bit signed integer. */
 typedef IntType<uint32_t, 4> HBUINT32;	/* 32-bit unsigned integer. */
 typedef IntType<int32_t,  4> HBINT32;	/* 32-bit signed integer. */
-typedef IntType<uint32_t, 3> UINT24;	/* 24-bit unsigned integer. */
+typedef IntType<uint32_t, 3> HBUINT24;	/* 24-bit unsigned integer. */
 
 /* 16-bit signed integer (HBINT16) that describes a quantity in FUnits. */
 typedef HBINT16 FWORD;
diff --git a/src/hb-ot-cmap-table.hh b/src/hb-ot-cmap-table.hh
index 959ca97f..c2bfe4b5 100644
--- a/src/hb-ot-cmap-table.hh
+++ b/src/hb-ot-cmap-table.hh
@@ -328,7 +328,7 @@ struct UnicodeValueRange
     return_trace (c->check_struct (this));
   }
 
-  UINT24	startUnicodeValue;	/* First value in this range. */
+  HBUINT24	startUnicodeValue;	/* First value in this range. */
   HBUINT8		additionalCount;	/* Number of additional values in this
 					 * range. */
   public:
@@ -350,7 +350,7 @@ struct UVSMapping
     return_trace (c->check_struct (this));
   }
 
-  UINT24	unicodeValue;	/* Base Unicode value of the UVS */
+  HBUINT24	unicodeValue;	/* Base Unicode value of the UVS */
   GlyphID	glyphID;	/* Glyph ID of the UVS */
   public:
   DEFINE_SIZE_STATIC (5);
@@ -392,7 +392,7 @@ struct VariationSelectorRecord
 		  nonDefaultUVS.sanitize (c, base));
   }
 
-  UINT24	varSelector;	/* Variation selector. */
+  HBUINT24	varSelector;	/* Variation selector. */
   LOffsetTo<DefaultUVS>
 		defaultUVS;	/* Offset to Default UVS Table. May be 0. */
   LOffsetTo<NonDefaultUVS>
diff --git a/src/hb-ot-layout-common-private.hh b/src/hb-ot-layout-common-private.hh
index 9251a6a9..66df2a71 100644
--- a/src/hb-ot-layout-common-private.hh
+++ b/src/hb-ot-layout-common-private.hh
@@ -449,7 +449,7 @@ struct FeatureParamsCharacterVariants
 					 * user-interface labels for the
 					 * feature parameters. (Must be zero
 					 * if numParameters is zero.) */
-  ArrayOf<UINT24>
+  ArrayOf<HBUINT24>
 		characters;		/* Array of the Unicode Scalar Value
 					 * of the characters for which this
 					 * feature provides glyph variants.
commit 3737c652a5e0b6d73b6090dc6c3863008c9dc8fd
Merge: 632713ba 8f4c1230
Author: Ebrahim Byagowi <ebrahim at gnu.org>
Date:   Fri Apr 13 23:19:19 2018 +0430

    Merge pull request #979 from ebraminio/msvc05
    
    Reinstate support for Visual Studio 2005

commit 8f4c12308a8d9e61922fb352e913acae46b28a88
Author: Tor Andersson <tor.andersson at artifex.com>
Date:   Fri Apr 13 23:01:54 2018 +0430

    Reinstate support for Visual Studio 2005

diff --git a/src/hb-common.h b/src/hb-common.h
index 9040f504..e34df025 100644
--- a/src/hb-common.h
+++ b/src/hb-common.h
@@ -49,6 +49,16 @@
 #  include <inttypes.h>
 #elif defined (_AIX)
 #  include <sys/inttypes.h>
+#elif defined (_MSC_VER) && _MSC_VER < 1600
+/* VS 2010 (_MSC_VER 1600) has stdint.h */
+typedef __int8 int8_t;
+typedef unsigned __int8 uint8_t;
+typedef __int16 int16_t;
+typedef unsigned __int16 uint16_t;
+typedef __int32 int32_t;
+typedef unsigned __int32 uint32_t;
+typedef __int64 int64_t;
+typedef unsigned __int64 uint64_t;
 #else
 #  include <stdint.h>
 #endif
diff --git a/src/hb-private.hh b/src/hb-private.hh
index 3181eb57..7e6d8e51 100644
--- a/src/hb-private.hh
+++ b/src/hb-private.hh
@@ -51,7 +51,7 @@
 #include <stdio.h>
 #include <stdarg.h>
 
-#if defined(_MSC_VER) || defined(__MINGW32__)
+#if (defined(_MSC_VER) && _MSC_VER >= 1500) || defined(__MINGW32__)
 #include <intrin.h>
 #endif
 
@@ -381,7 +381,7 @@ _hb_bit_storage (T v)
     return sizeof (unsigned long long) * 8 - __builtin_clzll (v);
 #endif
 
-#if defined(_MSC_VER) || defined(__MINGW32__)
+#if (defined(_MSC_VER) && _MSC_VER >= 1500) || defined(__MINGW32__)
   if (sizeof (T) <= sizeof (unsigned int))
   {
     unsigned long where;
@@ -454,7 +454,7 @@ _hb_ctz (T v)
     return __builtin_ctzll (v);
 #endif
 
-#if defined(_MSC_VER) || defined(__MINGW32__)
+#if (defined(_MSC_VER) && _MSC_VER >= 1500) || defined(__MINGW32__)
   if (sizeof (T) <= sizeof (unsigned int))
   {
     unsigned long where;
diff --git a/src/hb-ucdn/ucdn.h b/src/hb-ucdn/ucdn.h
index 2d5fc359..9b0f9d4c 100644
--- a/src/hb-ucdn/ucdn.h
+++ b/src/hb-ucdn/ucdn.h
@@ -42,6 +42,16 @@ HB_BEGIN_HEADER
 #  include <inttypes.h>
 #elif defined (_AIX)
 #  include <sys/inttypes.h>
+#elif defined (_MSC_VER) && _MSC_VER < 1600
+/* VS 2010 (_MSC_VER 1600) has stdint.h */
+typedef __int8 int8_t;
+typedef unsigned __int8 uint8_t;
+typedef __int16 int16_t;
+typedef unsigned __int16 uint16_t;
+typedef __int32 int32_t;
+typedef unsigned __int32 uint32_t;
+typedef __int64 int64_t;
+typedef unsigned __int64 uint64_t;
 #else
 #  include <stdint.h>
 #endif


More information about the HarfBuzz mailing list