[subset] Implement subsetting of SingleSubst
authorBehdad Esfahbod <behdad@behdad.org>
Tue, 4 Sep 2018 03:50:11 +0000 (20:50 -0700)
committerBehdad Esfahbod <behdad@behdad.org>
Tue, 4 Sep 2018 21:20:35 +0000 (14:20 -0700)
src/hb-machinery.hh
src/hb-null.hh
src/hb-ot-layout-gsub-table.hh
src/hb-vector.hh

index 280a5a6..6899416 100644 (file)
@@ -452,6 +452,8 @@ struct hb_serialize_context_t
     this->debug_depth = 0;
   }
 
+  inline bool err (bool e) { return this->ran_out_of_room = this->ran_out_of_room || e; }
+
   /* To be called around main operation. */
   template <typename Type>
   inline Type *start_serialize (void)
index 19886a5..7128f0a 100644 (file)
@@ -51,27 +51,40 @@ static inline Type const & Null (void) {
 
 /* Specializaitons for arbitrary-content Null objects expressed in bytes. */
 #define DECLARE_NULL_NAMESPACE_BYTES(Namespace, Type) \
-} /* Close namespace. */ \
-extern HB_INTERNAL const unsigned char _hb_Null_##Namespace##_##Type[Namespace::Type::min_size]; \
-template <> \
-/*static*/ inline const Namespace::Type& Null<Namespace::Type> (void) { \
-  return *reinterpret_cast<const Namespace::Type *> (_hb_Null_##Namespace##_##Type); \
-} \
-namespace Namespace { \
-static_assert (true, "Just so we take semicolon after.")
+       } /* Close namespace. */ \
+       extern HB_INTERNAL const unsigned char _hb_Null_##Namespace##_##Type[Namespace::Type::min_size]; \
+       template <> \
+       /*static*/ inline const Namespace::Type& Null<Namespace::Type> (void) { \
+         return *reinterpret_cast<const Namespace::Type *> (_hb_Null_##Namespace##_##Type); \
+       } \
+       namespace Namespace { \
+       static_assert (true, "Just so we take semicolon after.")
 #define DEFINE_NULL_NAMESPACE_BYTES(Namespace, Type) \
-const unsigned char _hb_Null_##Namespace##_##Type[Namespace::Type::min_size]
+       const unsigned char _hb_Null_##Namespace##_##Type[Namespace::Type::min_size]
 
 /* Specializaitons for arbitrary-content Null objects expressed as struct initializer. */
 #define DECLARE_NULL_INSTANCE(Type) \
-extern HB_INTERNAL const Type _hb_Null_##Type; \
-template <> \
-/*static*/ inline const Type& Null<Type> (void) { \
-  return _hb_Null_##Type; \
-} \
+       extern HB_INTERNAL const Type _hb_Null_##Type; \
+       template <> \
+       /*static*/ inline const Type& Null<Type> (void) { \
+         return _hb_Null_##Type; \
+       } \
 static_assert (true, "Just so we take semicolon after.")
 #define DEFINE_NULL_INSTANCE(Type) \
-const Type _hb_Null_##Type
+       const Type _hb_Null_##Type
+
+/* Specializaiton to disallow Null objects. */
+#define DECLARE_NULL_DISALLOW(Type) \
+       template <> inline const Type& Null<Type> (void)
+#define DECLARE_NULL_NAMSPACE_DISALLOW(Namespace, Type) \
+       } /* Close namespace. */ \
+       template <> \
+       /*static*/ inline const Namespace::Type& Null<Namespace::Type> (void) { \
+         extern void *_hb_undefined; \
+         return *reinterpret_cast<const Namespace::Type *> (_hb_undefined); \
+       } \
+       namespace Namespace { \
+       static_assert (true, "Just so we take semicolon after.")
 
 /* Global writable pool.  Enlarge as necessary. */
 
index c0f7081..5763361 100644 (file)
 namespace OT {
 
 
+static inline void SingleSubst_serialize (hb_serialize_context_t *c,
+                                         Supplier<GlyphID> &glyphs,
+                                         Supplier<GlyphID> &substitutes,
+                                         unsigned int num_glyphs);
+
 struct SingleSubstFormat1
 {
   inline bool intersects (const hb_set_t *glyphs) const
@@ -104,19 +109,26 @@ struct SingleSubstFormat1
 
   inline bool subset (hb_subset_context_t *c) const
   {
-    return false;
     TRACE_SUBSET (this);
-    hb_auto_t<hb_vector_t<hb_codepoint_t>> from;
-    hb_auto_t<hb_vector_t<hb_codepoint_t>> to;
+    hb_auto_t<hb_vector_t<GlyphID>> from;
+    hb_auto_t<hb_vector_t<GlyphID>> to;
     hb_codepoint_t delta = deltaGlyphID;
     for (hb_auto_t<Coverage::Iter> iter (this+coverage); iter.more (); iter.next ())
     {
-      //if (!c->plan->glyphs->has (iter.get_glyph ()))
-      //  continue;
-      from.push (iter.get_glyph ());
-      to.push ((iter.get_glyph () + delta) & 0xFFFF);
+      if (!c->plan->glyphset->has (iter.get_glyph ()))
+        continue;
+      from.push ()->set (iter.get_glyph ());
+      to.push ()->set ((iter.get_glyph () + delta) & 0xFFFF);
     }
-    return_trace (false);
+    c->serializer->err (from.in_error () || to.in_error ());
+
+    Supplier<GlyphID> from_supplier (&from);
+    Supplier<GlyphID> to_supplier (&to);
+    SingleSubst_serialize (c->serializer,
+                          from_supplier,
+                          to_supplier,
+                          from.len);
+    return_trace (from.len);
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
@@ -204,8 +216,24 @@ struct SingleSubstFormat2
   inline bool subset (hb_subset_context_t *c) const
   {
     TRACE_SUBSET (this);
-    // TODO(subset)
-    return_trace (false);
+    hb_auto_t<hb_vector_t<GlyphID>> from;
+    hb_auto_t<hb_vector_t<GlyphID>> to;
+    for (hb_auto_t<Coverage::Iter> iter (this+coverage); iter.more (); iter.next ())
+    {
+      if (!c->plan->glyphset->has (iter.get_glyph ()))
+        continue;
+      from.push ()->set (iter.get_glyph ());
+      to.push ()->set (substitute[iter.get_coverage ()]);
+    }
+    c->serializer->err (from.in_error () || to.in_error ());
+
+    Supplier<GlyphID> from_supplier (&from);
+    Supplier<GlyphID> to_supplier (&to);
+    SingleSubst_serialize (c->serializer,
+                          from_supplier,
+                          to_supplier,
+                          from.len);
+    return_trace (from.len);
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
@@ -275,6 +303,17 @@ struct SingleSubst
   } u;
 };
 
+static inline void
+SingleSubst_serialize (hb_serialize_context_t *c,
+                      Supplier<GlyphID> &glyphs,
+                      Supplier<GlyphID> &substitutes,
+                      unsigned int num_glyphs)
+{
+  c->start_embed<SingleSubst> ()->serialize (c,
+                                            glyphs,
+                                            substitutes,
+                                            num_glyphs);
+}
 
 struct Sequence
 {
index 3134174..da548cb 100644 (file)
@@ -72,6 +72,8 @@ struct hb_vector_t
     return p;
   }
 
+  inline bool in_error (void) const { return allocated == 0; }
+
   /* Allocate for size but don't adjust len. */
   inline bool alloc (unsigned int size)
   {