/*
 * Copyright © 2016  Elie Roux <elie.roux@telecom-bretagne.eu>
 * Copyright © 2018  Google, Inc.
 * Copyright © 2018-2019  Ebrahim Byagowi
 *
 *  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): Behdad Esfahbod
 */

#ifndef HB_OT_LAYOUT_BASE_TABLE_HH
#define HB_OT_LAYOUT_BASE_TABLE_HH

#include "hb-open-type.hh"
#include "hb-ot-layout-common.hh"

namespace OT {

/*
 * BASE -- Baseline
 * https://docs.microsoft.com/en-us/typography/opentype/spec/base
 */

struct BaseCoordFormat1
{
  hb_position_t get_coord (hb_font_t *font, hb_direction_t direction) const
  {
    return HB_DIRECTION_IS_HORIZONTAL (direction) ? font->em_scale_y (coordinate) : font->em_scale_x (coordinate);
  }

  bool sanitize (hb_sanitize_context_t *c) const
  {
    TRACE_SANITIZE (this);
    return_trace (c->check_struct (this));
  }

  protected:
  HBUINT16	format;		/* Format identifier--format = 1 */
  FWORD		coordinate;	/* X or Y value, in design units */
  public:
  DEFINE_SIZE_STATIC (4);
};

struct BaseCoordFormat2
{
  hb_position_t get_coord (hb_font_t *font, hb_direction_t direction) const
  {
    /* TODO */
    return HB_DIRECTION_IS_HORIZONTAL (direction) ? font->em_scale_y (coordinate) : font->em_scale_x (coordinate);
  }

  bool sanitize (hb_sanitize_context_t *c) const
  {
    TRACE_SANITIZE (this);
    return_trace (c->check_struct (this));
  }

  protected:
  HBUINT16	format;		/* Format identifier--format = 2 */
  FWORD		coordinate;	/* X or Y value, in design units */
  HBGlyphID16	referenceGlyph;	/* Glyph ID of control glyph */
  HBUINT16	coordPoint;	/* Index of contour point on the
				 * reference glyph */
  public:
  DEFINE_SIZE_STATIC (8);
};

struct BaseCoordFormat3
{
  hb_position_t get_coord (hb_font_t *font,
			   const VariationStore &var_store,
			   hb_direction_t direction) const
  {
    const Device &device = this+deviceTable;

    return HB_DIRECTION_IS_HORIZONTAL (direction)
	 ? font->em_scale_y (coordinate) + device.get_y_delta (font, var_store)
	 : font->em_scale_x (coordinate) + device.get_x_delta (font, var_store);
  }


  bool sanitize (hb_sanitize_context_t *c) const
  {
    TRACE_SANITIZE (this);
    return_trace (likely (c->check_struct (this) &&
			  deviceTable.sanitize (c, this)));
  }

  protected:
  HBUINT16	format;		/* Format identifier--format = 3 */
  FWORD		coordinate;	/* X or Y value, in design units */
  Offset16To<Device>
		deviceTable;	/* Offset to Device table for X or
				 * Y value, from beginning of
				 * BaseCoord table (may be NULL). */
  public:
  DEFINE_SIZE_STATIC (6);
};

struct BaseCoord
{
  bool has_data () const { return u.format; }

  hb_position_t get_coord (hb_font_t            *font,
			   const VariationStore &var_store,
			   hb_direction_t        direction) const
  {
    switch (u.format) {
    case 1: return u.format1.get_coord (font, direction);
    case 2: return u.format2.get_coord (font, direction);
    case 3: return u.format3.get_coord (font, var_store, direction);
    default:return 0;
    }
  }

  bool sanitize (hb_sanitize_context_t *c) const
  {
    TRACE_SANITIZE (this);
    if (unlikely (!u.format.sanitize (c))) return_trace (false);
    switch (u.format) {
    case 1: return_trace (u.format1.sanitize (c));
    case 2: return_trace (u.format2.sanitize (c));
    case 3: return_trace (u.format3.sanitize (c));
    default:return_trace (false);
    }
  }

  protected:
  union {
  HBUINT16		format;
  BaseCoordFormat1	format1;
  BaseCoordFormat2	format2;
  BaseCoordFormat3	format3;
  } u;
  public:
  DEFINE_SIZE_UNION (2, format);
};

struct FeatMinMaxRecord
{
  int cmp (hb_tag_t key) const { return tag.cmp (key); }

  bool has_data () const { return tag; }

  void get_min_max (const BaseCoord **min, const BaseCoord **max) const
  {
    if (likely (min)) *min = &(this+minCoord);
    if (likely (max)) *max = &(this+maxCoord);
  }

  bool sanitize (hb_sanitize_context_t *c, const void *base) const
  {
    TRACE_SANITIZE (this);
    return_trace (likely (c->check_struct (this) &&
			  minCoord.sanitize (c, base) &&
			  maxCoord.sanitize (c, base)));
  }

  protected:
  Tag		tag;		/* 4-byte feature identification tag--must
				 * match feature tag in FeatureList */
  Offset16To<BaseCoord>
		minCoord;	/* Offset to BaseCoord table that defines
				 * the minimum extent value, from beginning
				 * of MinMax table (may be NULL) */
  Offset16To<BaseCoord>
		maxCoord;	/* Offset to BaseCoord table that defines
				 * the maximum extent value, from beginning
				 * of MinMax table (may be NULL) */
  public:
  DEFINE_SIZE_STATIC (8);
};

struct MinMax
{
  void get_min_max (hb_tag_t          feature_tag,
		    const BaseCoord **min,
		    const BaseCoord **max) const
  {
    const FeatMinMaxRecord &minMaxCoord = featMinMaxRecords.bsearch (feature_tag);
    if (minMaxCoord.has_data ())
      minMaxCoord.get_min_max (min, max);
    else
    {
      if (likely (min)) *min = &(this+minCoord);
      if (likely (max)) *max = &(this+maxCoord);
    }
  }

  bool sanitize (hb_sanitize_context_t *c) const
  {
    TRACE_SANITIZE (this);
    return_trace (likely (c->check_struct (this) &&
			  minCoord.sanitize (c, this) &&
			  maxCoord.sanitize (c, this) &&
			  featMinMaxRecords.sanitize (c, this)));
  }

  protected:
  Offset16To<BaseCoord>
		minCoord;	/* Offset to BaseCoord table that defines
				 * minimum extent value, from the beginning
				 * of MinMax table (may be NULL) */
  Offset16To<BaseCoord>
		maxCoord;	/* Offset to BaseCoord table that defines
				 * maximum extent value, from the beginning
				 * of MinMax table (may be NULL) */
  SortedArray16Of<FeatMinMaxRecord>
		featMinMaxRecords;
				/* Array of FeatMinMaxRecords, in alphabetical
				 * order by featureTableTag */
  public:
  DEFINE_SIZE_ARRAY (6, featMinMaxRecords);
};

struct BaseValues
{
  const BaseCoord &get_base_coord (int baseline_tag_index) const
  {
    if (baseline_tag_index == -1) baseline_tag_index = defaultIndex;
    return this+baseCoords[baseline_tag_index];
  }

  bool sanitize (hb_sanitize_context_t *c) const
  {
    TRACE_SANITIZE (this);
    return_trace (likely (c->check_struct (this) &&
			  baseCoords.sanitize (c, this)));
  }

  protected:
  Index		defaultIndex;	/* Index number of default baseline for this
				 * script — equals index position of baseline tag
				 * in baselineTags array of the BaseTagList */
  Array16OfOffset16To<BaseCoord>
		baseCoords;	/* Number of BaseCoord tables defined — should equal
				 * baseTagCount in the BaseTagList
				 *
				 * Array of offsets to BaseCoord tables, from beginning of
				 * BaseValues table — order matches baselineTags array in
				 * the BaseTagList */
  public:
  DEFINE_SIZE_ARRAY (4, baseCoords);
};

struct BaseLangSysRecord
{
  int cmp (hb_tag_t key) const { return baseLangSysTag.cmp (key); }

  bool has_data () const { return baseLangSysTag; }

  const MinMax &get_min_max () const { return this+minMax; }

  bool sanitize (hb_sanitize_context_t *c, const void *base) const
  {
    TRACE_SANITIZE (this);
    return_trace (likely (c->check_struct (this) &&
			  minMax.sanitize (c, base)));
  }

  protected:
  Tag		baseLangSysTag;	/* 4-byte language system identification tag */
  Offset16To<MinMax>
		minMax;		/* Offset to MinMax table, from beginning
				 * of BaseScript table */
  public:
  DEFINE_SIZE_STATIC (6);
};

struct BaseScript
{
  const MinMax &get_min_max (hb_tag_t language_tag) const
  {
    const BaseLangSysRecord& record = baseLangSysRecords.bsearch (language_tag);
    return record.has_data () ? record.get_min_max () : this+defaultMinMax;
  }

  const BaseCoord &get_base_coord (int baseline_tag_index) const
  { return (this+baseValues).get_base_coord (baseline_tag_index); }

  bool has_values () const { return baseValues; }
  bool has_min_max () const { return defaultMinMax; /* TODO What if only per-language is present? */ }

  bool sanitize (hb_sanitize_context_t *c) const
  {
    TRACE_SANITIZE (this);
    return_trace (likely (c->check_struct (this) &&
			  baseValues.sanitize (c, this) &&
			  defaultMinMax.sanitize (c, this) &&
			  baseLangSysRecords.sanitize (c, this)));
  }

  protected:
  Offset16To<BaseValues>
		baseValues;	/* Offset to BaseValues table, from beginning
				 * of BaseScript table (may be NULL) */
  Offset16To<MinMax>
		defaultMinMax;	/* Offset to MinMax table, from beginning of
				 * BaseScript table (may be NULL) */
  SortedArray16Of<BaseLangSysRecord>
		baseLangSysRecords;
				/* Number of BaseLangSysRecords
				 * defined — may be zero (0) */

  public:
  DEFINE_SIZE_ARRAY (6, baseLangSysRecords);
};

struct BaseScriptList;
struct BaseScriptRecord
{
  int cmp (hb_tag_t key) const { return baseScriptTag.cmp (key); }

  bool has_data () const { return baseScriptTag; }

  const BaseScript &get_base_script (const BaseScriptList *list) const
  { return list+baseScript; }

  bool sanitize (hb_sanitize_context_t *c, const void *base) const
  {
    TRACE_SANITIZE (this);
    return_trace (likely (c->check_struct (this) &&
			  baseScript.sanitize (c, base)));
  }

  protected:
  Tag		baseScriptTag;	/* 4-byte script identification tag */
  Offset16To<BaseScript>
		baseScript;	/* Offset to BaseScript table, from beginning
				 * of BaseScriptList */

  public:
  DEFINE_SIZE_STATIC (6);
};

struct BaseScriptList
{
  const BaseScript &get_base_script (hb_tag_t script) const
  {
    const BaseScriptRecord *record = &baseScriptRecords.bsearch (script);
    if (!record->has_data ()) record = &baseScriptRecords.bsearch (HB_TAG ('D','F','L','T'));
    return record->has_data () ? record->get_base_script (this) : Null (BaseScript);
  }

  bool sanitize (hb_sanitize_context_t *c) const
  {
    TRACE_SANITIZE (this);
    return_trace (c->check_struct (this) &&
		  baseScriptRecords.sanitize (c, this));
  }

  protected:
  SortedArray16Of<BaseScriptRecord>
			baseScriptRecords;

  public:
  DEFINE_SIZE_ARRAY (2, baseScriptRecords);
};

struct Axis
{
  bool get_baseline (hb_tag_t          baseline_tag,
		     hb_tag_t          script_tag,
		     hb_tag_t          language_tag,
		     const BaseCoord **coord) const
  {
    const BaseScript &base_script = (this+baseScriptList).get_base_script (script_tag);
    if (!base_script.has_values ())
    {
      *coord = nullptr;
      return false;
    }

    if (likely (coord))
    {
      unsigned int tag_index = 0;
      if (!(this+baseTagList).bfind (baseline_tag, &tag_index))
      {
        *coord = nullptr;
        return false;
      }
      *coord = &base_script.get_base_coord (tag_index);
    }

    return true;
  }

  bool get_min_max (hb_tag_t          script_tag,
		    hb_tag_t          language_tag,
		    hb_tag_t          feature_tag,
		    const BaseCoord **min_coord,
		    const BaseCoord **max_coord) const
  {
    const BaseScript &base_script = (this+baseScriptList).get_base_script (script_tag);
    if (!base_script.has_min_max ())
    {
      *min_coord = *max_coord = nullptr;
      return false;
    }

    base_script.get_min_max (language_tag).get_min_max (feature_tag, min_coord, max_coord);

    return true;
  }

  bool sanitize (hb_sanitize_context_t *c) const
  {
    TRACE_SANITIZE (this);
    return_trace (likely (c->check_struct (this) &&
			  baseTagList.sanitize (c, this) &&
			  baseScriptList.sanitize (c, this)));
  }

  protected:
  Offset16To<SortedArray16Of<Tag>>
		baseTagList;	/* Offset to BaseTagList table, from beginning
				 * of Axis table (may be NULL)
				 * Array of 4-byte baseline identification tags — must
				 * be in alphabetical order */
  Offset16To<BaseScriptList>
		baseScriptList;	/* Offset to BaseScriptList table, from beginning
				 * of Axis table
				 * Array of BaseScriptRecords, in alphabetical order
				 * by baseScriptTag */

  public:
  DEFINE_SIZE_STATIC (4);
};

struct BASE
{
  static constexpr hb_tag_t tableTag = HB_OT_TAG_BASE;

  const Axis &get_axis (hb_direction_t direction) const
  { return HB_DIRECTION_IS_VERTICAL (direction) ? this+vAxis : this+hAxis; }

  const VariationStore &get_var_store () const
  { return version.to_int () < 0x00010001u ? Null (VariationStore) : this+varStore; }

  bool get_baseline (hb_font_t      *font,
		     hb_tag_t        baseline_tag,
		     hb_direction_t  direction,
		     hb_tag_t        script_tag,
		     hb_tag_t        language_tag,
		     hb_position_t  *base) const
  {
    const BaseCoord *base_coord = nullptr;
    if (unlikely (!get_axis (direction).get_baseline (baseline_tag, script_tag, language_tag, &base_coord) ||
		  !base_coord || !base_coord->has_data ()))
      return false;

    if (likely (base))
      *base = base_coord->get_coord (font, get_var_store (), direction);

    return true;
  }

  bool get_min_max (hb_font_t      *font,
		    hb_direction_t  direction,
		    hb_tag_t        script_tag,
		    hb_tag_t        language_tag,
		    hb_tag_t        feature_tag,
		    hb_position_t  *min,
		    hb_position_t  *max) const
  {
    const BaseCoord *min_coord, *max_coord;
    if (!get_axis (direction).get_min_max (script_tag, language_tag, feature_tag,
					   &min_coord, &max_coord))
      return false;

    const VariationStore &var_store = get_var_store ();
    if (likely (min && min_coord)) *min = min_coord->get_coord (font, var_store, direction);
    if (likely (max && max_coord)) *max = max_coord->get_coord (font, var_store, direction);
    return true;
  }

  bool sanitize (hb_sanitize_context_t *c) const
  {
    TRACE_SANITIZE (this);
    return_trace (likely (c->check_struct (this) &&
			  likely (version.major == 1) &&
			  hAxis.sanitize (c, this) &&
			  vAxis.sanitize (c, this) &&
			  (version.to_int () < 0x00010001u || varStore.sanitize (c, this))));
  }

  protected:
  FixedVersion<>version;	/* Version of the BASE table */
  Offset16To<Axis>hAxis;		/* Offset to horizontal Axis table, from beginning
				 * of BASE table (may be NULL) */
  Offset16To<Axis>vAxis;		/* Offset to vertical Axis table, from beginning
				 * of BASE table (may be NULL) */
  Offset32To<VariationStore>
		varStore;	/* Offset to the table of Item Variation
				 * Store--from beginning of BASE
				 * header (may be NULL).  Introduced
				 * in version 0x00010001. */
  public:
  DEFINE_SIZE_MIN (8);
};


} /* namespace OT */


#endif /* HB_OT_LAYOUT_BASE_TABLE_HH */
