/*
 * Copyright © 2018 Adobe 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.
 *
 * Adobe Author(s): Michiharu Ariza
 */

#ifndef HB_OT_CFF1_TABLE_HH
#define HB_OT_CFF1_TABLE_HH

#include "hb-ot-head-table.hh"
#include "hb-ot-cff-common.hh"
#include "hb-subset-cff1.hh"

namespace CFF {

/*
 * CFF -- Compact Font Format (CFF)
 * http://www.adobe.com/content/dam/acom/en/devnet/font/pdfs/5176.CFF.pdf
 */
#define HB_OT_TAG_cff1 HB_TAG('C','F','F',' ')

#define CFF_UNDEF_SID   CFF_UNDEF_CODE

enum EncodingID { StandardEncoding = 0, ExpertEncoding = 1 };
enum CharsetID { ISOAdobeCharset = 0, ExpertCharset = 1, ExpertSubsetCharset = 2 };

typedef CFFIndex<HBUINT16>  CFF1Index;
template <typename Type> struct CFF1IndexOf : CFFIndexOf<HBUINT16, Type> {};

typedef CFFIndex<HBUINT16> CFF1Index;
typedef CFF1Index          CFF1CharStrings;
typedef FDArray<HBUINT16>  CFF1FDArray;
typedef Subrs<HBUINT16>    CFF1Subrs;

struct CFF1FDSelect : FDSelect {};

/* Encoding */
struct Encoding0 {
  bool sanitize (hb_sanitize_context_t *c) const
  {
    TRACE_SANITIZE (this);
    return_trace (codes.sanitize (c));
  }

  hb_codepoint_t get_code (hb_codepoint_t glyph) const
  {
    assert (glyph > 0);
    glyph--;
    if (glyph < nCodes ())
    {
      return (hb_codepoint_t)codes[glyph];
    }
    else
      return CFF_UNDEF_CODE;
  }

  HBUINT8 &nCodes () { return codes.len; }
  HBUINT8 nCodes () const { return codes.len; }

  ArrayOf<HBUINT8, HBUINT8> codes;

  DEFINE_SIZE_ARRAY_SIZED (1, codes);
};

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

  HBUINT8   first;
  HBUINT8   nLeft;

  DEFINE_SIZE_STATIC (2);
};

struct Encoding1 {
  bool sanitize (hb_sanitize_context_t *c) const
  {
    TRACE_SANITIZE (this);
    return_trace (ranges.sanitize (c));
  }

  hb_codepoint_t get_code (hb_codepoint_t glyph) const
  {
    assert (glyph > 0);
    glyph--;
    for (unsigned int i = 0; i < nRanges (); i++)
    {
      if (glyph <= ranges[i].nLeft)
      {
	hb_codepoint_t code = (hb_codepoint_t) ranges[i].first + glyph;
	return (likely (code < 0x100) ? code: CFF_UNDEF_CODE);
      }
      glyph -= (ranges[i].nLeft + 1);
    }
    return CFF_UNDEF_CODE;
  }

  HBUINT8 &nRanges () { return ranges.len; }
  HBUINT8 nRanges () const { return ranges.len; }

  ArrayOf<Encoding1_Range, HBUINT8> ranges;

  DEFINE_SIZE_ARRAY_SIZED (1, ranges);
};

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

  HBUINT8   code;
  HBUINT16  glyph;

  DEFINE_SIZE_STATIC (3);
};

struct CFF1SuppEncData {
  bool sanitize (hb_sanitize_context_t *c) const
  {
    TRACE_SANITIZE (this);
    return_trace (supps.sanitize (c));
  }

  void get_codes (hb_codepoint_t sid, hb_vector_t<hb_codepoint_t> &codes) const
  {
    for (unsigned int i = 0; i < nSups (); i++)
      if (sid == supps[i].glyph)
	codes.push (supps[i].code);
  }

  HBUINT8 &nSups () { return supps.len; }
  HBUINT8 nSups () const { return supps.len; }

  ArrayOf<SuppEncoding, HBUINT8> supps;

  DEFINE_SIZE_ARRAY_SIZED (1, supps);
};

struct Encoding
{
  /* serialize a fullset Encoding */
  bool serialize (hb_serialize_context_t *c, const Encoding &src)
  {
    TRACE_SERIALIZE (this);
    unsigned int size = src.get_size ();
    Encoding *dest = c->allocate_size<Encoding> (size);
    if (unlikely (dest == nullptr)) return_trace (false);
    memcpy (dest, &src, size);
    return_trace (true);
  }

  /* serialize a subset Encoding */
  bool serialize (hb_serialize_context_t *c,
		  uint8_t format,
		  unsigned int enc_count,
		  const hb_vector_t<code_pair_t>& code_ranges,
		  const hb_vector_t<code_pair_t>& supp_codes)
  {
    TRACE_SERIALIZE (this);
    Encoding *dest = c->extend_min (*this);
    if (unlikely (dest == nullptr)) return_trace (false);
    dest->format = format | ((supp_codes.length > 0) ? 0x80 : 0);
    switch (format) {
    case 0:
    {
      Encoding0 *fmt0 = c->allocate_size<Encoding0> (Encoding0::min_size + HBUINT8::static_size * enc_count);
      if (unlikely (fmt0 == nullptr)) return_trace (false);
      fmt0->nCodes () = enc_count;
      unsigned int glyph = 0;
      for (unsigned int i = 0; i < code_ranges.length; i++)
      {
	hb_codepoint_t code = code_ranges[i].code;
	for (int left = (int)code_ranges[i].glyph; left >= 0; left--)
	  fmt0->codes[glyph++] = code++;
	if (unlikely (!((glyph <= 0x100) && (code <= 0x100))))
	  return_trace (false);
      }
    }
    break;

    case 1:
    {
      Encoding1 *fmt1 = c->allocate_size<Encoding1> (Encoding1::min_size + Encoding1_Range::static_size * code_ranges.length);
      if (unlikely (fmt1 == nullptr)) return_trace (false);
      fmt1->nRanges () = code_ranges.length;
      for (unsigned int i = 0; i < code_ranges.length; i++)
      {
	if (unlikely (!((code_ranges[i].code <= 0xFF) && (code_ranges[i].glyph <= 0xFF))))
	  return_trace (false);
	fmt1->ranges[i].first = code_ranges[i].code;
	fmt1->ranges[i].nLeft = code_ranges[i].glyph;
      }
    }
    break;

    }

    if (supp_codes.length)
    {
      CFF1SuppEncData *suppData = c->allocate_size<CFF1SuppEncData> (CFF1SuppEncData::min_size + SuppEncoding::static_size * supp_codes.length);
      if (unlikely (suppData == nullptr)) return_trace (false);
      suppData->nSups () = supp_codes.length;
      for (unsigned int i = 0; i < supp_codes.length; i++)
      {
	suppData->supps[i].code = supp_codes[i].code;
	suppData->supps[i].glyph = supp_codes[i].glyph; /* actually SID */
      }
    }

    return_trace (true);
  }

  /* parallel to above: calculate the size of a subset Encoding */
  static unsigned int calculate_serialized_size (uint8_t format,
						 unsigned int enc_count,
						 unsigned int supp_count)
  {
    unsigned int size = min_size;
    switch (format)
    {
    case 0: size += Encoding0::min_size + HBUINT8::static_size * enc_count; break;
    case 1: size += Encoding1::min_size + Encoding1_Range::static_size * enc_count; break;
    default:return 0;
    }
    if (supp_count > 0)
      size += CFF1SuppEncData::min_size + SuppEncoding::static_size * supp_count;
    return size;
  }

  unsigned int get_size () const
  {
    unsigned int size = min_size;
    switch (table_format ())
    {
    case 0: size += u.format0.get_size (); break;
    case 1: size += u.format1.get_size (); break;
    }
    if (has_supplement ())
      size += suppEncData ().get_size ();
    return size;
  }

  hb_codepoint_t get_code (hb_codepoint_t glyph) const
  {
    switch (table_format ())
    {
    case 0: return u.format0.get_code (glyph);
    case 1: return u.format1.get_code (glyph);
    default:return 0;
    }
  }

  uint8_t table_format () const { return format & 0x7F; }
  bool  has_supplement () const { return format & 0x80; }

  void get_supplement_codes (hb_codepoint_t sid, hb_vector_t<hb_codepoint_t> &codes) const
  {
    codes.resize (0);
    if (has_supplement ())
      suppEncData().get_codes (sid, codes);
  }

  bool sanitize (hb_sanitize_context_t *c) const
  {
    TRACE_SANITIZE (this);
    if (unlikely (!c->check_struct (this)))
      return_trace (false);

    switch (table_format ())
    {
    case 0: if (unlikely (!u.format0.sanitize (c))) { return_trace (false); } break;
    case 1: if (unlikely (!u.format1.sanitize (c))) { return_trace (false); } break;
    default:return_trace (false);
    }
    return_trace (likely (!has_supplement () || suppEncData ().sanitize (c)));
  }

  protected:
  const CFF1SuppEncData &suppEncData () const
  {
    switch (table_format ())
    {
    case 0: return StructAfter<CFF1SuppEncData> (u.format0.codes[u.format0.nCodes ()-1]);
    case 1: return StructAfter<CFF1SuppEncData> (u.format1.ranges[u.format1.nRanges ()-1]);
    default:return Null (CFF1SuppEncData);
    }
  }

  public:
  HBUINT8	format;
  union {
  Encoding0	format0;
  Encoding1	format1;
  } u;
  /* CFF1SuppEncData  suppEncData; */

  DEFINE_SIZE_MIN (1);
};

/* Charset */
struct Charset0 {
  bool sanitize (hb_sanitize_context_t *c, unsigned int num_glyphs) const
  {
    TRACE_SANITIZE (this);
    return_trace (c->check_struct (this) && sids[num_glyphs - 1].sanitize (c));
  }

  hb_codepoint_t get_sid (hb_codepoint_t glyph) const
  {
    if (glyph == 0)
      return 0;
    else
      return sids[glyph - 1];
  }

  hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const
  {
    if (sid == 0)
      return 0;

    for (unsigned int glyph = 1; glyph < num_glyphs; glyph++)
    {
      if (sids[glyph-1] == sid)
	return glyph;
    }
    return 0;
  }

  unsigned int get_size (unsigned int num_glyphs) const
  {
    assert (num_glyphs > 0);
    return HBUINT16::static_size * (num_glyphs - 1);
  }

  HBUINT16  sids[HB_VAR_ARRAY];

  DEFINE_SIZE_ARRAY(0, sids);
};

template <typename TYPE>
struct Charset_Range {
  bool sanitize (hb_sanitize_context_t *c) const
  {
    TRACE_SANITIZE (this);
    return_trace (c->check_struct (this));
  }

  HBUINT16  first;
  TYPE      nLeft;

  DEFINE_SIZE_STATIC (HBUINT16::static_size + TYPE::static_size);
};

template <typename TYPE>
struct Charset1_2 {
  bool sanitize (hb_sanitize_context_t *c, unsigned int num_glyphs) const
  {
    TRACE_SANITIZE (this);
    if (unlikely (!c->check_struct (this)))
      return_trace (false);
    num_glyphs--;
    for (unsigned int i = 0; num_glyphs > 0; i++)
    {
      if (unlikely (!ranges[i].sanitize (c) || (num_glyphs < ranges[i].nLeft + 1)))
	return_trace (false);
      num_glyphs -= (ranges[i].nLeft + 1);
    }
    return_trace (true);
  }

  hb_codepoint_t get_sid (hb_codepoint_t glyph) const
  {
    if (glyph == 0) return 0;
    glyph--;
    for (unsigned int i = 0;; i++)
    {
      if (glyph <= ranges[i].nLeft)
	return (hb_codepoint_t)ranges[i].first + glyph;
      glyph -= (ranges[i].nLeft + 1);
    }

    return 0;
  }

  hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const
  {
    if (sid == 0) return 0;
    hb_codepoint_t  glyph = 1;
    for (unsigned int i = 0;; i++)
    {
      if (glyph >= num_glyphs)
      	return 0;
      if ((ranges[i].first <= sid) && (sid <= ranges[i].first + ranges[i].nLeft))
	return glyph + (sid - ranges[i].first);
      glyph += (ranges[i].nLeft + 1);
    }

    return 0;
  }

  unsigned int get_size (unsigned int num_glyphs) const
  {
    unsigned int size = HBUINT8::static_size;
    int glyph = (int)num_glyphs;

    assert (glyph > 0);
    glyph--;
    for (unsigned int i = 0; glyph > 0; i++)
    {
      glyph -= (ranges[i].nLeft + 1);
      size += Charset_Range<TYPE>::static_size;
    }

    return size;
  }

  Charset_Range<TYPE>   ranges[HB_VAR_ARRAY];

  DEFINE_SIZE_ARRAY (0, ranges);
};

typedef Charset1_2<HBUINT8>     Charset1;
typedef Charset1_2<HBUINT16>    Charset2;
typedef Charset_Range<HBUINT8>  Charset1_Range;
typedef Charset_Range<HBUINT16> Charset2_Range;

struct Charset
{
  /* serialize a fullset Charset */
  bool serialize (hb_serialize_context_t *c, const Charset &src, unsigned int num_glyphs)
  {
    TRACE_SERIALIZE (this);
    unsigned int size = src.get_size (num_glyphs);
    Charset *dest = c->allocate_size<Charset> (size);
    if (unlikely (dest == nullptr)) return_trace (false);
    memcpy (dest, &src, size);
    return_trace (true);
  }

  /* serialize a subset Charset */
  bool serialize (hb_serialize_context_t *c,
		  uint8_t format,
		  unsigned int num_glyphs,
		  const hb_vector_t<code_pair_t>& sid_ranges)
  {
    TRACE_SERIALIZE (this);
    Charset *dest = c->extend_min (*this);
    if (unlikely (dest == nullptr)) return_trace (false);
    dest->format = format;
    switch (format)
    {
    case 0:
    {
      Charset0 *fmt0 = c->allocate_size<Charset0> (Charset0::min_size + HBUINT16::static_size * (num_glyphs - 1));
      if (unlikely (fmt0 == nullptr)) return_trace (false);
      unsigned int glyph = 0;
      for (unsigned int i = 0; i < sid_ranges.length; i++)
      {
	hb_codepoint_t sid = sid_ranges[i].code;
	for (int left = (int)sid_ranges[i].glyph; left >= 0; left--)
	  fmt0->sids[glyph++] = sid++;
      }
    }
    break;

    case 1:
    {
      Charset1 *fmt1 = c->allocate_size<Charset1> (Charset1::min_size + Charset1_Range::static_size * sid_ranges.length);
      if (unlikely (fmt1 == nullptr)) return_trace (false);
      for (unsigned int i = 0; i < sid_ranges.length; i++)
      {
      	if (unlikely (!(sid_ranges[i].glyph <= 0xFF)))
	  return_trace (false);
	fmt1->ranges[i].first = sid_ranges[i].code;
	fmt1->ranges[i].nLeft = sid_ranges[i].glyph;
      }
    }
    break;

    case 2:
    {
      Charset2 *fmt2 = c->allocate_size<Charset2> (Charset2::min_size + Charset2_Range::static_size * sid_ranges.length);
      if (unlikely (fmt2 == nullptr)) return_trace (false);
      for (unsigned int i = 0; i < sid_ranges.length; i++)
      {
      	if (unlikely (!(sid_ranges[i].glyph <= 0xFFFF)))
	  return_trace (false);
	fmt2->ranges[i].first = sid_ranges[i].code;
	fmt2->ranges[i].nLeft = sid_ranges[i].glyph;
      }
    }
    break;

    }
    return_trace (true);
  }

  /* parallel to above: calculate the size of a subset Charset */
  static unsigned int calculate_serialized_size (uint8_t format,
						 unsigned int count)
  {
    switch (format)
    {
    case 0: return min_size + Charset0::min_size + HBUINT16::static_size * (count - 1);
    case 1: return min_size + Charset1::min_size + Charset1_Range::static_size * count;
    case 2: return min_size + Charset2::min_size + Charset2_Range::static_size * count;
    default:return 0;
    }
  }

  unsigned int get_size (unsigned int num_glyphs) const
  {
    switch (format)
    {
    case 0: return min_size + u.format0.get_size (num_glyphs);
    case 1: return min_size + u.format1.get_size (num_glyphs);
    case 2: return min_size + u.format2.get_size (num_glyphs);
    default:return 0;
    }
  }

  hb_codepoint_t get_sid (hb_codepoint_t glyph) const
  {
    switch (format)
    {
    case 0: return u.format0.get_sid (glyph);
    case 1: return u.format1.get_sid (glyph);
    case 2: return u.format2.get_sid (glyph);
    default:return 0;
    }
  }

  hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const
  {
    switch (format)
    {
    case 0: return u.format0.get_glyph (sid, num_glyphs);
    case 1: return u.format1.get_glyph (sid, num_glyphs);
    case 2: return u.format2.get_glyph (sid, num_glyphs);
    default:return 0;
    }
  }

  bool sanitize (hb_sanitize_context_t *c) const
  {
    TRACE_SANITIZE (this);
    if (unlikely (!c->check_struct (this)))
      return_trace (false);

    switch (format)
    {
    case 0: return_trace (u.format0.sanitize (c, c->get_num_glyphs ()));
    case 1: return_trace (u.format1.sanitize (c, c->get_num_glyphs ()));
    case 2: return_trace (u.format2.sanitize (c, c->get_num_glyphs ()));
    default:return_trace (false);
    }
  }

  HBUINT8       format;
  union {
    Charset0    format0;
    Charset1    format1;
    Charset2    format2;
  } u;

  DEFINE_SIZE_MIN (1);
};

struct CFF1StringIndex : CFF1Index
{
  bool serialize (hb_serialize_context_t *c, const CFF1StringIndex &strings,
		  unsigned int offSize_, const hb_inc_bimap_t &sidmap)
  {
    TRACE_SERIALIZE (this);
    if (unlikely ((strings.count == 0) || (sidmap.get_population () == 0)))
    {
      if (unlikely (!c->extend_min (this->count)))
	return_trace (false);
      count = 0;
      return_trace (true);
    }

    byte_str_array_t bytesArray;
    bytesArray.init ();
    if (!bytesArray.resize (sidmap.get_population ()))
      return_trace (false);
    for (unsigned int i = 0; i < strings.count; i++)
    {
      hb_codepoint_t  j = sidmap[i];
      if (j != CFF_UNDEF_CODE)
	bytesArray[j] = strings[i];
    }

    bool result = CFF1Index::serialize (c, offSize_, bytesArray);
    bytesArray.fini ();
    return_trace (result);
  }

  /* in parallel to above */
  unsigned int calculate_serialized_size (unsigned int &offSize_ /*OUT*/, const hb_inc_bimap_t &sidmap) const
  {
    offSize_ = 0;
    if ((count == 0) || (sidmap.get_population () == 0))
      return count.static_size;

    unsigned int dataSize = 0;
    for (unsigned int i = 0; i < count; i++)
      if (sidmap[i] != CFF_UNDEF_CODE)
	dataSize += length_at (i);

    offSize_ = calcOffSize(dataSize);
    return CFF1Index::calculate_serialized_size (offSize_, sidmap.get_population (), dataSize);
  }
};

struct cff1_top_dict_interp_env_t : num_interp_env_t
{
  cff1_top_dict_interp_env_t ()
    : num_interp_env_t(), prev_offset(0), last_offset(0) {}

  unsigned int prev_offset;
  unsigned int last_offset;
};

struct name_dict_values_t
{
  enum name_dict_val_index_t
  {
      version,
      notice,
      copyright,
      fullName,
      familyName,
      weight,
      postscript,
      fontName,
      baseFontName,
      registry,
      ordering,

      ValCount
  };

  void init ()
  {
    for (unsigned int i = 0; i < ValCount; i++)
      values[i] = CFF_UNDEF_SID;
  }

  unsigned int& operator[] (unsigned int i)
  { assert (i < ValCount); return values[i]; }

  unsigned int operator[] (unsigned int i) const
  { assert (i < ValCount); return values[i]; }

  static enum name_dict_val_index_t name_op_to_index (op_code_t op)
  {
    switch (op) {
      default: // can't happen - just make some compiler happy
      case OpCode_version:
	return version;
      case OpCode_Notice:
	return notice;
      case OpCode_Copyright:
	return copyright;
      case OpCode_FullName:
	return fullName;
      case OpCode_FamilyName:
	return familyName;
      case OpCode_Weight:
	return weight;
      case OpCode_PostScript:
	return postscript;
      case OpCode_FontName:
	return fontName;
      case OpCode_BaseFontName:
	return baseFontName;
    }
  }

  unsigned int  values[ValCount];
};

struct cff1_top_dict_val_t : op_str_t
{
  unsigned int  last_arg_offset;
};

struct cff1_top_dict_values_t : top_dict_values_t<cff1_top_dict_val_t>
{
  void init ()
  {
    top_dict_values_t<cff1_top_dict_val_t>::init ();

    nameSIDs.init ();
    ros_supplement = 0;
    cidCount = 8720;
    EncodingOffset = 0;
    CharsetOffset = 0;
    FDSelectOffset = 0;
    privateDictInfo.init ();
  }
  void fini () { top_dict_values_t<cff1_top_dict_val_t>::fini (); }

  bool is_CID () const
  { return nameSIDs[name_dict_values_t::registry] != CFF_UNDEF_SID; }

  name_dict_values_t  nameSIDs;
  unsigned int    ros_supplement_offset;
  unsigned int    ros_supplement;
  unsigned int    cidCount;

  unsigned int    EncodingOffset;
  unsigned int    CharsetOffset;
  unsigned int    FDSelectOffset;
  table_info_t       privateDictInfo;
};

struct cff1_top_dict_opset_t : top_dict_opset_t<cff1_top_dict_val_t>
{
  static void process_op (op_code_t op, cff1_top_dict_interp_env_t& env, cff1_top_dict_values_t& dictval)
  {
    cff1_top_dict_val_t  val;
    val.last_arg_offset = (env.last_offset-1) - dictval.opStart;  /* offset to the last argument */

    switch (op) {
      case OpCode_version:
      case OpCode_Notice:
      case OpCode_Copyright:
      case OpCode_FullName:
      case OpCode_FamilyName:
      case OpCode_Weight:
      case OpCode_PostScript:
      case OpCode_BaseFontName:
	dictval.nameSIDs[name_dict_values_t::name_op_to_index (op)] = env.argStack.pop_uint ();
	env.clear_args ();
	break;
      case OpCode_isFixedPitch:
      case OpCode_ItalicAngle:
      case OpCode_UnderlinePosition:
      case OpCode_UnderlineThickness:
      case OpCode_PaintType:
      case OpCode_CharstringType:
      case OpCode_UniqueID:
      case OpCode_StrokeWidth:
      case OpCode_SyntheticBase:
      case OpCode_CIDFontVersion:
      case OpCode_CIDFontRevision:
      case OpCode_CIDFontType:
      case OpCode_UIDBase:
      case OpCode_FontBBox:
      case OpCode_XUID:
      case OpCode_BaseFontBlend:
	env.clear_args ();
	break;

      case OpCode_CIDCount:
	dictval.cidCount = env.argStack.pop_uint ();
	env.clear_args ();
	break;

      case OpCode_ROS:
	dictval.ros_supplement = env.argStack.pop_uint ();
	dictval.nameSIDs[name_dict_values_t::ordering] = env.argStack.pop_uint ();
	dictval.nameSIDs[name_dict_values_t::registry] = env.argStack.pop_uint ();
	env.clear_args ();
	break;

      case OpCode_Encoding:
	dictval.EncodingOffset = env.argStack.pop_uint ();
	env.clear_args ();
	if (unlikely (dictval.EncodingOffset == 0)) return;
	break;

      case OpCode_charset:
	dictval.CharsetOffset = env.argStack.pop_uint ();
	env.clear_args ();
	if (unlikely (dictval.CharsetOffset == 0)) return;
	break;

      case OpCode_FDSelect:
	dictval.FDSelectOffset = env.argStack.pop_uint ();
	env.clear_args ();
	break;

      case OpCode_Private:
	dictval.privateDictInfo.offset = env.argStack.pop_uint ();
	dictval.privateDictInfo.size = env.argStack.pop_uint ();
	env.clear_args ();
	break;

      default:
	env.last_offset = env.str_ref.offset;
	top_dict_opset_t<cff1_top_dict_val_t>::process_op (op, env, dictval);
	/* Record this operand below if stack is empty, otherwise done */
	if (!env.argStack.is_empty ()) return;
	break;
    }

    if (unlikely (env.in_error ())) return;

    dictval.add_op (op, env.str_ref, val);
  }
};

struct cff1_font_dict_values_t : dict_values_t<op_str_t>
{
  void init ()
  {
    dict_values_t<op_str_t>::init ();
    privateDictInfo.init ();
    fontName = CFF_UNDEF_SID;
  }
  void fini () { dict_values_t<op_str_t>::fini (); }

  table_info_t       privateDictInfo;
  unsigned int    fontName;
};

struct cff1_font_dict_opset_t : dict_opset_t
{
  static void process_op (op_code_t op, num_interp_env_t& env, cff1_font_dict_values_t& dictval)
  {
    switch (op) {
      case OpCode_FontName:
	dictval.fontName = env.argStack.pop_uint ();
	env.clear_args ();
	break;
      case OpCode_FontMatrix:
      case OpCode_PaintType:
	env.clear_args ();
	break;
      case OpCode_Private:
	dictval.privateDictInfo.offset = env.argStack.pop_uint ();
	dictval.privateDictInfo.size = env.argStack.pop_uint ();
	env.clear_args ();
	break;

      default:
	dict_opset_t::process_op (op, env);
	if (!env.argStack.is_empty ()) return;
	break;
    }

    if (unlikely (env.in_error ())) return;

    dictval.add_op (op, env.str_ref);
  }
};

template <typename VAL>
struct cff1_private_dict_values_base_t : dict_values_t<VAL>
{
  void init ()
  {
    dict_values_t<VAL>::init ();
    subrsOffset = 0;
    localSubrs = &Null(CFF1Subrs);
  }
  void fini () { dict_values_t<VAL>::fini (); }

  unsigned int calculate_serialized_size () const
  {
    unsigned int size = 0;
    for (unsigned int i = 0; i < dict_values_t<VAL>::get_count; i++)
      if (dict_values_t<VAL>::get_value (i).op == OpCode_Subrs)
	size += OpCode_Size (OpCode_shortint) + 2 + OpCode_Size (OpCode_Subrs);
      else
	size += dict_values_t<VAL>::get_value (i).str.length;
    return size;
  }

  unsigned int      subrsOffset;
  const CFF1Subrs    *localSubrs;
};

typedef cff1_private_dict_values_base_t<op_str_t> cff1_private_dict_values_subset_t;
typedef cff1_private_dict_values_base_t<num_dict_val_t> cff1_private_dict_values_t;

struct cff1_private_dict_opset_t : dict_opset_t
{
  static void process_op (op_code_t op, num_interp_env_t& env, cff1_private_dict_values_t& dictval)
  {
    num_dict_val_t val;
    val.init ();

    switch (op) {
      case OpCode_BlueValues:
      case OpCode_OtherBlues:
      case OpCode_FamilyBlues:
      case OpCode_FamilyOtherBlues:
      case OpCode_StemSnapH:
      case OpCode_StemSnapV:
	env.clear_args ();
	break;
      case OpCode_StdHW:
      case OpCode_StdVW:
      case OpCode_BlueScale:
      case OpCode_BlueShift:
      case OpCode_BlueFuzz:
      case OpCode_ForceBold:
      case OpCode_LanguageGroup:
      case OpCode_ExpansionFactor:
      case OpCode_initialRandomSeed:
      case OpCode_defaultWidthX:
      case OpCode_nominalWidthX:
	val.single_val = env.argStack.pop_num ();
	env.clear_args ();
	break;
      case OpCode_Subrs:
	dictval.subrsOffset = env.argStack.pop_uint ();
	env.clear_args ();
	break;

      default:
	dict_opset_t::process_op (op, env);
	if (!env.argStack.is_empty ()) return;
	break;
    }

    if (unlikely (env.in_error ())) return;

    dictval.add_op (op, env.str_ref, val);
  }
};

struct cff1_private_dict_opset_subset : dict_opset_t
{
  static void process_op (op_code_t op, num_interp_env_t& env, cff1_private_dict_values_subset_t& dictval)
  {
    switch (op) {
      case OpCode_BlueValues:
      case OpCode_OtherBlues:
      case OpCode_FamilyBlues:
      case OpCode_FamilyOtherBlues:
      case OpCode_StemSnapH:
      case OpCode_StemSnapV:
      case OpCode_StdHW:
      case OpCode_StdVW:
      case OpCode_BlueScale:
      case OpCode_BlueShift:
      case OpCode_BlueFuzz:
      case OpCode_ForceBold:
      case OpCode_LanguageGroup:
      case OpCode_ExpansionFactor:
      case OpCode_initialRandomSeed:
      case OpCode_defaultWidthX:
      case OpCode_nominalWidthX:
	env.clear_args ();
	break;

      case OpCode_Subrs:
	dictval.subrsOffset = env.argStack.pop_uint ();
	env.clear_args ();
	break;

      default:
	dict_opset_t::process_op (op, env);
	if (!env.argStack.is_empty ()) return;
	break;
    }

    if (unlikely (env.in_error ())) return;

    dictval.add_op (op, env.str_ref);
  }
};

typedef dict_interpreter_t<cff1_top_dict_opset_t, cff1_top_dict_values_t, cff1_top_dict_interp_env_t> cff1_top_dict_interpreter_t;
typedef dict_interpreter_t<cff1_font_dict_opset_t, cff1_font_dict_values_t> cff1_font_dict_interpreter_t;

typedef CFF1Index CFF1NameIndex;
typedef CFF1IndexOf<TopDict> CFF1TopDictIndex;

} /* namespace CFF */

namespace OT {

using namespace CFF;

struct cff1
{
  static constexpr hb_tag_t tableTag = HB_OT_TAG_cff1;

  bool sanitize (hb_sanitize_context_t *c) const
  {
    TRACE_SANITIZE (this);
    return_trace (c->check_struct (this) &&
		  likely (version.major == 1));
  }

  template <typename PRIVOPSET, typename PRIVDICTVAL>
  struct accelerator_templ_t
  {
    void init (hb_face_t *face)
    {
      topDict.init ();
      fontDicts.init ();
      privateDicts.init ();

      this->blob = sc.reference_table<cff1> (face);

      /* setup for run-time santization */
      sc.init (this->blob);
      sc.start_processing ();

      const OT::cff1 *cff = this->blob->template as<OT::cff1> ();

      if (cff == &Null(OT::cff1))
      { fini (); return; }

      nameIndex = &cff->nameIndex (cff);
      if ((nameIndex == &Null (CFF1NameIndex)) || !nameIndex->sanitize (&sc))
      { fini (); return; }

      topDictIndex = &StructAtOffset<CFF1TopDictIndex> (nameIndex, nameIndex->get_size ());
      if ((topDictIndex == &Null (CFF1TopDictIndex)) || !topDictIndex->sanitize (&sc) || (topDictIndex->count == 0))
      { fini (); return; }

      { /* parse top dict */
	const byte_str_t topDictStr = (*topDictIndex)[0];
	if (unlikely (!topDictStr.sanitize (&sc))) { fini (); return; }
	cff1_top_dict_interpreter_t top_interp;
	top_interp.env.init (topDictStr);
	topDict.init ();
	if (unlikely (!top_interp.interpret (topDict))) { fini (); return; }
      }

      if (is_predef_charset ())
	charset = &Null(Charset);
      else
      {
	charset = &StructAtOffsetOrNull<Charset> (cff, topDict.CharsetOffset);
	if (unlikely ((charset == &Null (Charset)) || !charset->sanitize (&sc))) { fini (); return; }
      }

      fdCount = 1;
      if (is_CID ())
      {
	fdArray = &StructAtOffsetOrNull<CFF1FDArray> (cff, topDict.FDArrayOffset);
	fdSelect = &StructAtOffsetOrNull<CFF1FDSelect> (cff, topDict.FDSelectOffset);
	if (unlikely ((fdArray == &Null(CFF1FDArray)) || !fdArray->sanitize (&sc) ||
	    (fdSelect == &Null(CFF1FDSelect)) || !fdSelect->sanitize (&sc, fdArray->count)))
	{ fini (); return; }

	fdCount = fdArray->count;
      }
      else
      {
	fdArray = &Null(CFF1FDArray);
	fdSelect = &Null(CFF1FDSelect);
      }

      stringIndex = &StructAtOffset<CFF1StringIndex> (topDictIndex, topDictIndex->get_size ());
      if ((stringIndex == &Null (CFF1StringIndex)) || !stringIndex->sanitize (&sc))
      { fini (); return; }

      globalSubrs = &StructAtOffset<CFF1Subrs> (stringIndex, stringIndex->get_size ());
      if ((globalSubrs != &Null (CFF1Subrs)) && !globalSubrs->sanitize (&sc))
      { fini (); return; }

      charStrings = &StructAtOffsetOrNull<CFF1CharStrings> (cff, topDict.charStringsOffset);

      if ((charStrings == &Null(CFF1CharStrings)) || unlikely (!charStrings->sanitize (&sc)))
      { fini (); return; }

      num_glyphs = charStrings->count;
      if (num_glyphs != sc.get_num_glyphs ())
      { fini (); return; }

      privateDicts.resize (fdCount);
      for (unsigned int i = 0; i < fdCount; i++)
	privateDicts[i].init ();

      // parse CID font dicts and gather private dicts
      if (is_CID ())
      {
	for (unsigned int i = 0; i < fdCount; i++)
	{
	  byte_str_t fontDictStr = (*fdArray)[i];
	  if (unlikely (!fontDictStr.sanitize (&sc))) { fini (); return; }
	  cff1_font_dict_values_t  *font;
	  cff1_font_dict_interpreter_t font_interp;
	  font_interp.env.init (fontDictStr);
	  font = fontDicts.push ();
	  if (unlikely (font == &Crap(cff1_font_dict_values_t))) { fini (); return; }
	  font->init ();
	  if (unlikely (!font_interp.interpret (*font))) { fini (); return; }
	  PRIVDICTVAL  *priv = &privateDicts[i];
	  const byte_str_t privDictStr (StructAtOffset<UnsizedByteStr> (cff, font->privateDictInfo.offset), font->privateDictInfo.size);
	  if (unlikely (!privDictStr.sanitize (&sc))) { fini (); return; }
	  dict_interpreter_t<PRIVOPSET, PRIVDICTVAL> priv_interp;
	  priv_interp.env.init (privDictStr);
	  priv->init ();
	  if (unlikely (!priv_interp.interpret (*priv))) { fini (); return; }

	  priv->localSubrs = &StructAtOffsetOrNull<CFF1Subrs> (&privDictStr, priv->subrsOffset);
	  if (priv->localSubrs != &Null(CFF1Subrs) &&
	      unlikely (!priv->localSubrs->sanitize (&sc)))
	  { fini (); return; }
	}
      }
      else  /* non-CID */
      {
	cff1_top_dict_values_t  *font = &topDict;
	PRIVDICTVAL  *priv = &privateDicts[0];

	const byte_str_t privDictStr (StructAtOffset<UnsizedByteStr> (cff, font->privateDictInfo.offset), font->privateDictInfo.size);
	if (unlikely (!privDictStr.sanitize (&sc))) { fini (); return; }
	dict_interpreter_t<PRIVOPSET, PRIVDICTVAL> priv_interp;
	priv_interp.env.init (privDictStr);
	priv->init ();
	if (unlikely (!priv_interp.interpret (*priv))) { fini (); return; }

	priv->localSubrs = &StructAtOffsetOrNull<CFF1Subrs> (&privDictStr, priv->subrsOffset);
	if (priv->localSubrs != &Null(CFF1Subrs) &&
	    unlikely (!priv->localSubrs->sanitize (&sc)))
	{ fini (); return; }
      }
    }

    void fini ()
    {
      sc.end_processing ();
      topDict.fini ();
      fontDicts.fini_deep ();
      privateDicts.fini_deep ();
      hb_blob_destroy (blob);
      blob = nullptr;
    }

    bool is_valid () const { return blob != nullptr; }
    bool   is_CID () const { return topDict.is_CID (); }

    bool is_predef_charset () const { return topDict.CharsetOffset <= ExpertSubsetCharset; }

    unsigned int std_code_to_glyph (hb_codepoint_t code) const
    {
      hb_codepoint_t sid = lookup_standard_encoding_for_sid (code);
      if (unlikely (sid == CFF_UNDEF_SID))
	return 0;

      if (charset != &Null(Charset))
	return charset->get_glyph (sid, num_glyphs);
      else if ((topDict.CharsetOffset == ISOAdobeCharset)
	      && (code <= 228 /*zcaron*/)) return sid;
      return 0;
    }

    protected:
    hb_blob_t	       *blob;
    hb_sanitize_context_t   sc;

    public:
    const Charset	   *charset;
    const CFF1NameIndex     *nameIndex;
    const CFF1TopDictIndex  *topDictIndex;
    const CFF1StringIndex   *stringIndex;
    const CFF1Subrs	 *globalSubrs;
    const CFF1CharStrings   *charStrings;
    const CFF1FDArray       *fdArray;
    const CFF1FDSelect      *fdSelect;
    unsigned int	    fdCount;

    cff1_top_dict_values_t       topDict;
    hb_vector_t<cff1_font_dict_values_t>   fontDicts;
    hb_vector_t<PRIVDICTVAL>	  privateDicts;

    unsigned int	    num_glyphs;
  };

  struct accelerator_t : accelerator_templ_t<cff1_private_dict_opset_t, cff1_private_dict_values_t>
  {
    HB_INTERNAL bool get_extents (hb_codepoint_t glyph, hb_glyph_extents_t *extents) const;
    HB_INTERNAL bool get_seac_components (hb_codepoint_t glyph, hb_codepoint_t *base, hb_codepoint_t *accent) const;
  };

  struct accelerator_subset_t : accelerator_templ_t<cff1_private_dict_opset_subset, cff1_private_dict_values_subset_t>
  {
    void init (hb_face_t *face)
    {
      SUPER::init (face);
      if (blob == nullptr) return;

      const OT::cff1 *cff = this->blob->as<OT::cff1> ();
      encoding = &Null(Encoding);
      if (is_CID ())
      {
	if (unlikely (charset == &Null(Charset))) { fini (); return; }
      }
      else
      {
	if (!is_predef_encoding ())
	{
	  encoding = &StructAtOffsetOrNull<Encoding> (cff, topDict.EncodingOffset);
	  if (unlikely ((encoding == &Null (Encoding)) || !encoding->sanitize (&sc))) { fini (); return; }
	}
      }
    }

    bool is_predef_encoding () const { return topDict.EncodingOffset <= ExpertEncoding; }

    hb_codepoint_t glyph_to_code (hb_codepoint_t glyph) const
    {
      if (encoding != &Null(Encoding))
	return encoding->get_code (glyph);
      else
      {
	hb_codepoint_t sid = glyph_to_sid (glyph);
	if (sid == 0) return 0;
	hb_codepoint_t code = 0;
	switch (topDict.EncodingOffset)
	{
	case StandardEncoding:
	  code = lookup_standard_encoding_for_code (sid);
	  break;
	case ExpertEncoding:
	  code = lookup_expert_encoding_for_code (sid);
	  break;
	default:
	  break;
	}
	return code;
      }
    }

    hb_codepoint_t glyph_to_sid (hb_codepoint_t glyph) const
    {
      if (charset != &Null(Charset))
	return charset->get_sid (glyph);
      else
      {
	hb_codepoint_t sid = 0;
	switch (topDict.CharsetOffset)
	{
	  case  ISOAdobeCharset:
	    if (glyph <= 228 /*zcaron*/) sid = glyph;
	    break;
	  case  ExpertCharset:
	    sid = lookup_expert_charset_for_sid (glyph);
	    break;
	  case  ExpertSubsetCharset:
	      sid = lookup_expert_subset_charset_for_sid (glyph);
	    break;
	  default:
	    break;
	}
	return sid;
      }
    }

    const Encoding	  *encoding;

    private:
    typedef accelerator_templ_t<cff1_private_dict_opset_subset, cff1_private_dict_values_subset_t> SUPER;
  };

  bool subset (hb_subset_plan_t *plan) const
  {
    hb_blob_t *cff_prime = nullptr;

    bool success = true;
    if (hb_subset_cff1 (plan, &cff_prime)) {
      success = success && plan->add_table (HB_OT_TAG_cff1, cff_prime);
      hb_blob_t *head_blob = hb_sanitize_context_t().reference_table<head> (plan->source);
      success = success && head_blob && plan->add_table (HB_OT_TAG_head, head_blob);
      hb_blob_destroy (head_blob);
    } else {
      success = false;
    }
    hb_blob_destroy (cff_prime);

    return success;
  }

  protected:
  HB_INTERNAL static hb_codepoint_t lookup_standard_encoding_for_code (hb_codepoint_t sid);
  HB_INTERNAL static hb_codepoint_t lookup_expert_encoding_for_code (hb_codepoint_t sid);
  HB_INTERNAL static hb_codepoint_t lookup_expert_charset_for_sid (hb_codepoint_t glyph);
  HB_INTERNAL static hb_codepoint_t lookup_expert_subset_charset_for_sid (hb_codepoint_t glyph);
  HB_INTERNAL static hb_codepoint_t lookup_standard_encoding_for_sid (hb_codepoint_t code);

  public:
  FixedVersion<HBUINT8> version;	  /* Version of CFF table. set to 0x0100u */
  OffsetTo<CFF1NameIndex, HBUINT8> nameIndex; /* headerSize = Offset to Name INDEX. */
  HBUINT8	       offSize;	  /* offset size (unused?) */

  public:
  DEFINE_SIZE_STATIC (4);
};

struct cff1_accelerator_t : cff1::accelerator_t {};
} /* namespace OT */

#endif /* HB_OT_CFF1_TABLE_HH */
