Imported Upstream version 2.3.1
[platform/upstream/harfbuzz.git] / src / hb-ot-hdmx-table.hh
index d406e3e..95229c5 100644 (file)
@@ -27,8 +27,7 @@
 #ifndef HB_OT_HDMX_TABLE_HH
 #define HB_OT_HDMX_TABLE_HH
 
-#include "hb-open-type-private.hh"
-#include "hb-subset-plan.hh"
+#include "hb-open-type.hh"
 
 /*
  * hdmx -- Horizontal Device Metrics
@@ -45,57 +44,51 @@ struct DeviceRecord
   struct SubsetView
   {
     const DeviceRecord *source_device_record;
-    unsigned int size_device_record;
+    unsigned int sizeDeviceRecord;
     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)
+    void init (const DeviceRecord *source_device_record,
+              unsigned int sizeDeviceRecord,
+              hb_subset_plan_t   *subset_plan)
     {
       this->source_device_record = source_device_record;
-      this->size_device_record = size_device_record;
+      this->sizeDeviceRecord = sizeDeviceRecord;
       this->subset_plan = subset_plan;
     }
 
-    inline unsigned int len () const
-    {
-      return this->subset_plan->glyphs.len;
-    }
+    unsigned int len () const
+    { return this->subset_plan->glyphs.length; }
 
-    inline const HBUINT8* operator [] (unsigned int i) const
+    const HBUINT8* operator [] (unsigned int i) const
     {
-      if (unlikely (i >= len())) return nullptr;
+      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;
+      if (gid >= sizeDeviceRecord - DeviceRecord::min_size)
+        return nullptr;
+      return &(this->source_device_record->widthsZ[gid]);
     }
   };
 
-  static inline unsigned int get_size (unsigned int count)
-  {
-    unsigned int raw_size = min_size + count * HBUINT8::static_size;
-    if (raw_size % 4)
-      /* Align to 32 bits */
-      return raw_size + (4 - (raw_size % 4));
-    return raw_size;
-  }
+  static unsigned int get_size (unsigned int count)
+  { return hb_ceil_to_4 (min_size + count * HBUINT8::static_size); }
 
-  inline bool serialize (hb_serialize_context_t *c, const SubsetView &subset_view)
+  bool serialize (hb_serialize_context_t *c, const SubsetView &subset_view)
   {
     TRACE_SERIALIZE (this);
 
-    if (unlikely (!c->allocate_size<DeviceRecord> (get_size (subset_view.len()))))
+    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->pixel_size.set (subset_view.source_device_record->pixel_size);
-    this->max_width.set (subset_view.source_device_record->max_width);
+    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++)
+    for (unsigned int i = 0; i < subset_view.len (); i++)
     {
       const HBUINT8 *width = subset_view[i];
       if (!width)
@@ -103,56 +96,56 @@ struct DeviceRecord
        DEBUG_MSG(SUBSET, nullptr, "HDMX width for new gid %d is missing.", i);
        return_trace (false);
       }
-      widths[i].set (*width);
+      widthsZ[i].set (*width);
     }
 
     return_trace (true);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c, unsigned int size_device_record) const
+  bool sanitize (hb_sanitize_context_t *c, unsigned int sizeDeviceRecord) const
   {
     TRACE_SANITIZE (this);
     return_trace (likely (c->check_struct (this) &&
-                         c->check_range (this, size_device_record)));
+                         c->check_range (this, sizeDeviceRecord)));
   }
 
-  HBUINT8 pixel_size;   /* Pixel size for following widths (as ppem). */
-  HBUINT8 max_width;    /* Maximum width. */
-  HBUINT8 widths[VAR];  /* Array of widths (numGlyphs is from the 'maxp' table). */
+  HBUINT8                      pixelSize;      /* Pixel size for following widths (as ppem). */
+  HBUINT8                      maxWidth;       /* Maximum width. */
+  UnsizedArrayOf<HBUINT8>      widthsZ;        /* Array of widths (numGlyphs is from the 'maxp' table). */
   public:
-  DEFINE_SIZE_ARRAY (2, widths);
+  DEFINE_SIZE_ARRAY (2, widthsZ);
 };
 
 
 struct hdmx
 {
-  static const hb_tag_t tableTag = HB_OT_TAG_hdmx;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_hdmx;
 
-  inline unsigned int get_size (void) const
-  {
-    return min_size + num_records * size_device_record;
-  }
+  unsigned int get_size () const
+  { return min_size + numRecords * sizeDeviceRecord; }
 
-  inline const DeviceRecord& operator [] (unsigned int i) const
+  const DeviceRecord& operator [] (unsigned int i) const
   {
-    if (unlikely (i >= num_records)) return Null(DeviceRecord);
-    return StructAtOffset<DeviceRecord> (this->data, i * size_device_record);
+    /* XXX Null(DeviceRecord) is NOT safe as it's num-glyphs lengthed.
+     * https://github.com/harfbuzz/harfbuzz/issues/1300 */
+    if (unlikely (i >= numRecords)) return Null (DeviceRecord);
+    return StructAtOffset<DeviceRecord> (&this->firstDeviceRecord, i * sizeDeviceRecord);
   }
 
-  inline bool serialize (hb_serialize_context_t *c, const hdmx *source_hdmx, hb_subset_plan_t *plan)
+  bool serialize (hb_serialize_context_t *c, const hdmx *source_hdmx, hb_subset_plan_t *plan)
   {
     TRACE_SERIALIZE (this);
 
     if (unlikely (!c->extend_min ((*this))))  return_trace (false);
 
     this->version.set (source_hdmx->version);
-    this->num_records.set (source_hdmx->num_records);
-    this->size_device_record.set (DeviceRecord::get_size (plan->glyphs.len));
+    this->numRecords.set (source_hdmx->numRecords);
+    this->sizeDeviceRecord.set (DeviceRecord::get_size (plan->glyphs.length));
 
-    for (unsigned int i = 0; i < source_hdmx->num_records; i++)
+    for (unsigned int i = 0; i < source_hdmx->numRecords; i++)
     {
       DeviceRecord::SubsetView subset_view;
-      subset_view.init (&(*source_hdmx)[i], source_hdmx->size_device_record, plan);
+      subset_view.init (&(*source_hdmx)[i], source_hdmx->sizeDeviceRecord, plan);
 
       if (!c->start_embed<DeviceRecord> ()->serialize (c, subset_view))
        return_trace (false);
@@ -161,14 +154,14 @@ struct hdmx
     return_trace (true);
   }
 
-  static inline size_t get_subsetted_size (hb_subset_plan_t *plan)
+  static size_t get_subsetted_size (const hdmx *source_hdmx, hb_subset_plan_t *plan)
   {
-    return min_size + DeviceRecord::get_size (plan->glyphs.len);
+    return min_size + source_hdmx->numRecords * DeviceRecord::get_size (plan->glyphs.length);
   }
 
-  inline bool subset (hb_subset_plan_t *plan) const
+  bool subset (hb_subset_plan_t *plan) const
   {
-    size_t dest_size = get_subsetted_size (plan);
+    size_t dest_size = get_subsetted_size (this, plan);
     hdmx *dest = (hdmx *) malloc (dest_size);
     if (unlikely (!dest))
     {
@@ -178,8 +171,10 @@ struct hdmx
 
     hb_serialize_context_t c (dest, dest_size);
     hdmx *hdmx_prime = c.start_serialize<hdmx> ();
-    if (!hdmx_prime || !hdmx_prime->serialize (&c, this, plan)) {
+    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 ();
@@ -195,22 +190,22 @@ struct hdmx
     return result;
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     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()));
+    return_trace (c->check_struct (this) &&
+                 !hb_unsigned_mul_overflows (numRecords, sizeDeviceRecord) &&
+                 sizeDeviceRecord >= DeviceRecord::min_size &&
+                 c->check_range (this, get_size ()));
   }
 
   protected:
-  HBUINT16     version;                /* Table version number (0) */
-  HBUINT16     num_records;            /* Number of device records. */
-  HBUINT32     size_device_record;     /* Size of a device record, 32-bit aligned. */
-  HBUINT8      data[VAR];              /* 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_ARRAY (8, data);
+  DEFINE_SIZE_MIN (8);
 };
 
 } /* namespace OT */