[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 c7c5d0a..5e71eab 100644
--- a/src/hb-ot-cmap-table.hh
+++ b/src/hb-ot-cmap-table.hh
@@ -204,6 +204,8 @@
 {
   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 @@
     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 @@
 	  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 @@
     }
 
     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 0000000..5aa6334
--- /dev/null
+++ b/test/api/fonts/Roboto-Regular.abc.format12.ttf
Binary files differ
diff --git a/test/api/test-subset-codepoints.c b/test/api/test-subset-codepoints.c
index c4f9c0e..3bd1fe0 100644
--- a/test/api/test-subset-codepoints.c
+++ b/test/api/test-subset-codepoints.c
@@ -48,12 +48,56 @@
   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();
 }