/*
 * Copyright © 2018  Google, Inc.
 *
 *  This is part of HarfBuzz, a text shaping library.
 *
 * Permission is hereby granted, without written agreement and without
 * license or royalty fees, to use, copy, modify, and distribute this
 * software and its documentation for any purpose, provided that the
 * above copyright notice and the following two paragraphs appear in
 * all copies of this software.
 *
 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
 * DAMAGE.
 *
 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 *
 * Google Author(s): Garret Rieger
 */

#ifndef HB_OT_HDMX_TABLE_HH
#define HB_OT_HDMX_TABLE_HH

#include "hb-open-type-private.hh"

namespace OT {


/*
 * hdmx - Horizontal Device Metric
 */

#define HB_OT_TAG_hdmx HB_TAG('h','d','m','x')

struct DeviceRecord
{
  struct SubsetView
  {
    const DeviceRecord *source_device_record;
    hb_subset_plan_t *subset_plan;

    inline void init(const DeviceRecord *source_device_record,
		     hb_subset_plan_t   *subset_plan)
    {
      this->source_device_record = source_device_record;
      this->subset_plan = subset_plan;
    }

    inline unsigned int len () const
    {
      return this->subset_plan->gids_to_retain_sorted.len;
    }

    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];
    }
  };

  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;
  }

  inline 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()))))
      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);

    for (unsigned int i = 0; i < subset_view.len(); i++)
      widths[i].set (subset_view[i]);

    return_trace (true);
  }

  inline bool sanitize (hb_sanitize_context_t *c, unsigned int size_device_record) const
  {
    TRACE_SANITIZE (this);
    return_trace (likely (c->check_struct (this) &&
			  c->check_range (this, size_device_record)));
  }

  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). */
  public:
  DEFINE_SIZE_ARRAY (2, widths);
};


struct hdmx
{
  static const hb_tag_t tableTag = HB_OT_TAG_hdmx;

  inline unsigned int get_size (void) const
  {
    return min_size + num_records * size_device_record;
  }

  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);
  }

  inline 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->gids_to_retain_sorted.len));

    for (unsigned int i = 0; i < source_hdmx->num_records; i++)
    {
      DeviceRecord::SubsetView subset_view;
      subset_view.init (&(*source_hdmx)[i], plan);

      c->start_embed<DeviceRecord> ()->serialize (c, subset_view);
    }

    return_trace (true);
  }

  static inline size_t get_subsetted_size (hb_subset_plan_t *plan)
  {
    return min_size + DeviceRecord::get_size (plan->gids_to_retain_sorted.len);
  }

  inline bool subset (hb_subset_plan_t *plan) const
  {
    size_t dest_size = get_subsetted_size (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);
      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 = hb_subset_plan_add_table (plan, HB_OT_TAG_hdmx, hdmx_prime_blob);
    hb_blob_destroy (hdmx_prime_blob);

    return result;
  }

  inline 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) &&
		  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. */
  public:
  DEFINE_SIZE_ARRAY (8, data);
};

} /* namespace OT */


#endif /* HB_OT_HDMX_TABLE_HH */
