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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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
_______________________________________________
HarfBuzz mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/harfbuzz

Reply via email to