Imported Upstream version 2.6.7
[platform/upstream/harfbuzz.git] / src / hb-ot-hdmx-table.hh
index 953ccab..c9c391b 100644 (file)
@@ -41,71 +41,31 @@ namespace OT {
 
 struct DeviceRecord
 {
-  struct SubsetView
-  {
-    const DeviceRecord *source_device_record;
-    unsigned int sizeDeviceRecord;
-    hb_subset_plan_t *subset_plan;
-
-    void init (const DeviceRecord *source_device_record,
-              unsigned int sizeDeviceRecord,
-              hb_subset_plan_t   *subset_plan)
-    {
-      this->source_device_record = source_device_record;
-      this->sizeDeviceRecord = sizeDeviceRecord;
-      this->subset_plan = subset_plan;
-    }
-
-    unsigned int len () const
-    { return this->subset_plan->num_output_glyphs (); }
-
-    const HBUINT8* operator [] (unsigned int new_gid) const
-    {
-      if (unlikely (new_gid >= len ())) return nullptr;
-
-      hb_codepoint_t old_gid;
-      if (!this->subset_plan->old_gid_for_new_gid (new_gid, &old_gid))
-        return &Null(HBUINT8);
-
-      if (old_gid >= sizeDeviceRecord - DeviceRecord::min_size)
-        return nullptr;
-      return &(this->source_device_record->widthsZ[old_gid]);
-    }
-  };
-
-  static unsigned int get_size (unsigned int count)
+  static unsigned int get_size (unsigned count)
   { return hb_ceil_to_4 (min_size + count * HBUINT8::static_size); }
 
-  bool serialize (hb_serialize_context_t *c, const SubsetView &subset_view)
+  template<typename Iterator,
+          hb_requires (hb_is_iterator (Iterator))>
+  bool serialize (hb_serialize_context_t *c, unsigned pixelSize, Iterator it)
   {
     TRACE_SERIALIZE (this);
 
-    unsigned int size = get_size (subset_view.len ());
-    if (unlikely (!c->allocate_size<DeviceRecord> (size)))
-    {
-      DEBUG_MSG(SUBSET, nullptr, "Couldn't allocate enough space for DeviceRecord: %d.",
-                size);
-      return_trace (false);
-    }
-
-    this->pixelSize.set (subset_view.source_device_record->pixelSize);
-    this->maxWidth.set (subset_view.source_device_record->maxWidth);
-
-    for (unsigned int i = 0; i < subset_view.len (); i++)
-    {
-      const HBUINT8 *width = subset_view[i];
-      if (!width)
-      {
-       DEBUG_MSG(SUBSET, nullptr, "HDMX width for new gid %d is missing.", i);
-       return_trace (false);
-      }
-      widthsZ[i].set (*width);
-    }
+    unsigned length = it.len ();
+
+    if (unlikely (!c->extend (*this, length)))  return_trace (false);
+
+    this->pixelSize = pixelSize;
+    this->maxWidth =
+    + it
+    | hb_reduce (hb_max, 0u);
+
+    + it
+    | hb_sink (widthsZ.as_array (length));
 
     return_trace (true);
   }
 
-  bool sanitize (hb_sanitize_context_t *c, unsigned int sizeDeviceRecord) const
+  bool sanitize (hb_sanitize_context_t *c, unsigned sizeDeviceRecord) const
   {
     TRACE_SANITIZE (this);
     return_trace (likely (c->check_struct (this) &&
@@ -135,62 +95,60 @@ struct hdmx
     return StructAtOffset<DeviceRecord> (&this->firstDeviceRecord, i * sizeDeviceRecord);
   }
 
-  bool serialize (hb_serialize_context_t *c, const hdmx *source_hdmx, hb_subset_plan_t *plan)
+  template<typename Iterator,
+          hb_requires (hb_is_iterator (Iterator))>
+  bool serialize (hb_serialize_context_t *c, unsigned version, Iterator it)
   {
     TRACE_SERIALIZE (this);
 
     if (unlikely (!c->extend_min ((*this))))  return_trace (false);
 
-    this->version.set (source_hdmx->version);
-    this->numRecords.set (source_hdmx->numRecords);
-    this->sizeDeviceRecord.set (DeviceRecord::get_size (plan->num_output_glyphs ()));
+    this->version = version;
+    this->numRecords = it.len ();
+    this->sizeDeviceRecord = DeviceRecord::get_size (it ? (*it).second.len () : 0);
 
-    for (unsigned int i = 0; i < source_hdmx->numRecords; i++)
-    {
-      DeviceRecord::SubsetView subset_view;
-      subset_view.init (&(*source_hdmx)[i], source_hdmx->sizeDeviceRecord, plan);
+    for (const hb_item_type<Iterator>& _ : +it)
+      c->start_embed<DeviceRecord> ()->serialize (c, _.first, _.second);
 
-      if (!c->start_embed<DeviceRecord> ()->serialize (c, subset_view))
-       return_trace (false);
-    }
-
-    return_trace (true);
+    return_trace (c->successful);
   }
 
-  static size_t get_subsetted_size (const hdmx *source_hdmx, hb_subset_plan_t *plan)
+
+  bool subset (hb_subset_context_t *c) const
   {
-    return min_size + source_hdmx->numRecords * DeviceRecord::get_size (plan->num_output_glyphs ());
+    TRACE_SUBSET (this);
+
+    hdmx *hdmx_prime = c->serializer->start_embed <hdmx> ();
+    if (unlikely (!hdmx_prime)) return_trace (false);
+
+    auto it =
+    + hb_range ((unsigned) numRecords)
+    | hb_map ([c, this] (unsigned _)
+       {
+         const DeviceRecord *device_record =
+           &StructAtOffset<DeviceRecord> (&firstDeviceRecord,
+                                          _ * sizeDeviceRecord);
+         auto row =
+           + hb_range (c->plan->num_output_glyphs ())
+           | hb_map (c->plan->reverse_glyph_map)
+           | hb_map ([this, c, device_record] (hb_codepoint_t _)
+                     {
+                       if (c->plan->is_empty_glyph (_))
+                         return Null (HBUINT8);
+                       return device_record->widthsZ.as_array (get_num_glyphs ()) [_];
+                     })
+           ;
+         return hb_pair ((unsigned) device_record->pixelSize, +row);
+       })
+    ;
+
+    hdmx_prime->serialize (c->serializer, version, it);
+    return_trace (true);
   }
 
-  bool subset (hb_subset_plan_t *plan) const
+  unsigned get_num_glyphs () const
   {
-    size_t dest_size = get_subsetted_size (this, plan);
-    hdmx *dest = (hdmx *) malloc (dest_size);
-    if (unlikely (!dest))
-    {
-      DEBUG_MSG(SUBSET, nullptr, "Unable to alloc %lu for hdmx subset output.", (unsigned long) dest_size);
-      return false;
-    }
-
-    hb_serialize_context_t c (dest, dest_size);
-    hdmx *hdmx_prime = c.start_serialize<hdmx> ();
-    if (!hdmx_prime || !hdmx_prime->serialize (&c, this, plan))
-    {
-      free (dest);
-      DEBUG_MSG(SUBSET, nullptr, "Failed to serialize write new hdmx.");
-      return false;
-    }
-    c.end_serialize ();
-
-    hb_blob_t *hdmx_prime_blob = hb_blob_create ((const char *) dest,
-                                                dest_size,
-                                                HB_MEMORY_MODE_READONLY,
-                                                dest,
-                                                free);
-    bool result = plan->add_table (HB_OT_TAG_hdmx, hdmx_prime_blob);
-    hb_blob_destroy (hdmx_prime_blob);
-
-    return result;
+    return sizeDeviceRecord - DeviceRecord::min_size;
   }
 
   bool sanitize (hb_sanitize_context_t *c) const
@@ -203,10 +161,12 @@ struct hdmx
   }
 
   protected:
-  HBUINT16             version;                /* Table version number (0) */
-  HBUINT16             numRecords;             /* Number of device records. */
-  HBUINT32             sizeDeviceRecord;       /* Size of a device record, 32-bit aligned. */
-  DeviceRecord         firstDeviceRecord;      /* Array of device records. */
+  HBUINT16     version;        /* Table version number (0) */
+  HBUINT16     numRecords;     /* Number of device records. */
+  HBUINT32     sizeDeviceRecord;
+                               /* Size of a device record, 32-bit aligned. */
+  DeviceRecord firstDeviceRecord;
+                               /* Array of device records. */
   public:
   DEFINE_SIZE_MIN (8);
 };