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

    inline const HBUINT8* operator [] (unsigned int i) const
    {
      if (unlikely (i >= len())) return nullptr;
      hb_codepoint_t gid = this->subset_plan->gids_to_retain_sorted [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;
    }
  };

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

  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], source_hdmx->size_device_record, plan);

      if (!c->start_embed<DeviceRecord> ()->serialize (c, subset_view))
	return_trace (false);
    }

    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 */
