Imported Upstream version 1.8.1
[platform/upstream/harfbuzz.git] / src / hb-ot-hdmx-table.hh
index f08fe39..d406e3e 100644 (file)
 #define HB_OT_HDMX_TABLE_HH
 
 #include "hb-open-type-private.hh"
-
-namespace OT {
-
+#include "hb-subset-plan.hh"
 
 /*
- * hdmx - Horizontal Device Metric
+ * hdmx -- Horizontal Device Metrics
+ * https://docs.microsoft.com/en-us/typography/opentype/spec/hdmx
  */
-
 #define HB_OT_TAG_hdmx HB_TAG('h','d','m','x')
 
+
+namespace OT {
+
+
 struct DeviceRecord
 {
   struct SubsetView
   {
     const DeviceRecord *source_device_record;
+    unsigned int size_device_record;
     hb_subset_plan_t *subset_plan;
 
     inline void init(const DeviceRecord *source_device_record,
+                    unsigned int size_device_record,
                     hb_subset_plan_t   *subset_plan)
     {
       this->source_device_record = source_device_record;
+      this->size_device_record = size_device_record;
       this->subset_plan = subset_plan;
     }
 
     inline unsigned int len () const
     {
-      return this->subset_plan->gids_to_retain_sorted.len;
+      return this->subset_plan->glyphs.len;
     }
 
-    inline const HBUINT8& operator [] (unsigned int i) const
+    inline const HBUINT8* operator [] (unsigned int i) const
     {
-      if (unlikely (i >= len())) return Null(HBUINT8);
-      hb_codepoint_t gid = this->subset_plan->gids_to_retain_sorted [i];
-      return this->source_device_record->widths[gid];
+      if (unlikely (i >= len())) return nullptr;
+      hb_codepoint_t gid = this->subset_plan->glyphs [i];
+
+      const HBUINT8* width = &(this->source_device_record->widths[gid]);
+
+      if (width < ((const HBUINT8 *) this->source_device_record) + size_device_record)
+       return width;
+      else
+       return nullptr;
     }
   };
 
@@ -85,7 +96,15 @@ struct DeviceRecord
     this->max_width.set (subset_view.source_device_record->max_width);
 
     for (unsigned int i = 0; i < subset_view.len(); i++)
-      widths[i].set (subset_view[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);
+      }
+      widths[i].set (*width);
+    }
 
     return_trace (true);
   }
@@ -117,7 +136,7 @@ struct hdmx
   inline const DeviceRecord& operator [] (unsigned int i) const
   {
     if (unlikely (i >= num_records)) return Null(DeviceRecord);
-    return StructAtOffset<DeviceRecord> (this, min_size + i * size_device_record);
+    return StructAtOffset<DeviceRecord> (this->data, i * size_device_record);
   }
 
   inline bool serialize (hb_serialize_context_t *c, const hdmx *source_hdmx, hb_subset_plan_t *plan)
@@ -128,14 +147,15 @@ struct hdmx
 
     this->version.set (source_hdmx->version);
     this->num_records.set (source_hdmx->num_records);
-    this->size_device_record.set (DeviceRecord::get_size (plan->gids_to_retain_sorted.len));
+    this->size_device_record.set (DeviceRecord::get_size (plan->glyphs.len));
 
     for (unsigned int i = 0; i < source_hdmx->num_records; i++)
     {
       DeviceRecord::SubsetView subset_view;
-      subset_view.init (&(*source_hdmx)[i], plan);
+      subset_view.init (&(*source_hdmx)[i], source_hdmx->size_device_record, plan);
 
-      c->start_embed<DeviceRecord> ()->serialize (c, subset_view);
+      if (!c->start_embed<DeviceRecord> ()->serialize (c, subset_view))
+       return_trace (false);
     }
 
     return_trace (true);
@@ -143,7 +163,7 @@ struct hdmx
 
   static inline size_t get_subsetted_size (hb_subset_plan_t *plan)
   {
-    return min_size + DeviceRecord::get_size (plan->gids_to_retain_sorted.len);
+    return min_size + DeviceRecord::get_size (plan->glyphs.len);
   }
 
   inline bool subset (hb_subset_plan_t *plan) const
@@ -169,7 +189,7 @@ struct hdmx
                                                 HB_MEMORY_MODE_READONLY,
                                                 dest,
                                                 free);
-    bool result = hb_subset_plan_add_table (plan, HB_OT_TAG_hdmx, hdmx_prime_blob);
+    bool result = plan->add_table (HB_OT_TAG_hdmx, hdmx_prime_blob);
     hb_blob_destroy (hdmx_prime_blob);
 
     return result;
@@ -180,6 +200,7 @@ struct hdmx
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) && version == 0 &&
                  !_hb_unsigned_int_mul_overflows (num_records, size_device_record) &&
+                 size_device_record >= DeviceRecord::min_size &&
                  c->check_range (this, get_size()));
   }