/*
 * Copyright © 2007,2008,2009  Red Hat, Inc.
 * Copyright © 2012  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.
 *
 * Red Hat Author(s): Behdad Esfahbod
 * Google Author(s): Behdad Esfahbod
 */

#ifndef HB_OPEN_FILE_PRIVATE_HH
#define HB_OPEN_FILE_PRIVATE_HH

#include "hb-open-type-private.hh"
#include "hb-ot-head-table.hh"


namespace OT {


/*
 *
 * The OpenType Font File
 *
 */


/*
 * Organization of an OpenType Font
 */

struct OpenTypeFontFile;
struct OffsetTable;
struct TTCHeader;


typedef struct TableRecord
{
  int cmp (Tag t) const
  { return -t.cmp (tag); }

  static int cmp (const void *pa, const void *pb)
  {
    const TableRecord *a = (const TableRecord *) pa;
    const TableRecord *b = (const TableRecord *) pb;
    return b->cmp (a->tag);
  }

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

  Tag		tag;		/* 4-byte identifier. */
  CheckSum	checkSum;	/* CheckSum for this table. */
  Offset32	offset;		/* Offset from beginning of TrueType font
				 * file. */
  HBUINT32	length;		/* Length of this table. */
  public:
  DEFINE_SIZE_STATIC (16);
} OpenTypeTable;

typedef struct OffsetTable
{
  friend struct OpenTypeFontFile;

  inline unsigned int get_table_count (void) const
  { return tables.len; }
  inline const TableRecord& get_table (unsigned int i) const
  {
    return tables[i];
  }
  inline unsigned int get_table_tags (unsigned int  start_offset,
				      unsigned int *table_count, /* IN/OUT */
				      hb_tag_t     *table_tags /* OUT */) const
  {
    if (table_count)
    {
      if (start_offset >= tables.len)
        *table_count = 0;
      else
        *table_count = MIN<unsigned int> (*table_count, tables.len - start_offset);

      const TableRecord *sub_tables = tables.arrayZ + start_offset;
      unsigned int count = *table_count;
      for (unsigned int i = 0; i < count; i++)
	table_tags[i] = sub_tables[i].tag;
    }
    return tables.len;
  }
  inline bool find_table_index (hb_tag_t tag, unsigned int *table_index) const
  {
    Tag t;
    t.set (tag);
    /* Linear-search for small tables to work around fonts with unsorted
     * table list. */
    int i = tables.len < 64 ? tables.lsearch (t) : tables.bsearch (t);
    if (table_index)
      *table_index = i == -1 ? Index::NOT_FOUND_INDEX : (unsigned int) i;
    return i != -1;
  }
  inline const TableRecord& get_table_by_tag (hb_tag_t tag) const
  {
    unsigned int table_index;
    find_table_index (tag, &table_index);
    return get_table (table_index);
  }

  public:

  inline bool serialize (hb_serialize_context_t *c,
			 hb_tag_t sfnt_tag,
			 Supplier<hb_tag_t> &tags,
			 Supplier<hb_blob_t *> &blobs,
			 unsigned int table_count)
  {
    TRACE_SERIALIZE (this);
    /* Alloc 12 for the OTHeader. */
    if (unlikely (!c->extend_min (*this))) return_trace (false);
    /* Write sfntVersion (bytes 0..3). */
    sfnt_version.set (sfnt_tag);
    /* Take space for numTables, searchRange, entrySelector, RangeShift
     * and the TableRecords themselves.  */
    if (unlikely (!tables.serialize (c, table_count))) return_trace (false);

    const char *dir_end = (const char *) c->head;
    HBUINT32 *checksum_adjustment = nullptr;

    /* Write OffsetTables, alloc for and write actual table blobs. */
    for (unsigned int i = 0; i < table_count; i++)
    {
      TableRecord &rec = tables.arrayZ[i];
      hb_blob_t *blob = blobs[i];
      rec.tag.set (tags[i]);
      rec.length.set (hb_blob_get_length (blob));
      rec.offset.serialize (c, this);

      /* Allocate room for the table and copy it. */
      char *start = (char *) c->allocate_size<void> (rec.length);
      if (unlikely (!start)) {return false;}

      memcpy (start, hb_blob_get_data (blob, nullptr), rec.length);

      /* 4-byte allignment. */
      if (rec.length % 4)
	c->allocate_size<void> (4 - rec.length % 4);
      const char *end = (const char *) c->head;

      if (tags[i] == HB_OT_TAG_head && end - start >= head::static_size)
      {
	head *h = (head *) start;
	checksum_adjustment = &h->checkSumAdjustment;
	checksum_adjustment->set (0);
      }

      rec.checkSum.set_for_data (start, end - start);
    }
    tags += table_count;
    blobs += table_count;

    tables.qsort ();

    if (checksum_adjustment)
    {
      CheckSum checksum;

      /* The following line is a slower version of the following block. */
      //checksum.set_for_data (this, (const char *) c->head - (const char *) this);
      checksum.set_for_data (this, dir_end - (const char *) this);
      for (unsigned int i = 0; i < table_count; i++)
      {
	TableRecord &rec = tables.arrayZ[i];
	checksum.set (checksum + rec.checkSum);
      }

      checksum_adjustment->set (0xB1B0AFBAu - checksum);
    }

    return_trace (true);
  }

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

  protected:
  Tag		sfnt_version;	/* '\0\001\0\00' if TrueType / 'OTTO' if CFF */
  BinSearchArrayOf<TableRecord>
		tables;
  public:
  DEFINE_SIZE_ARRAY (12, tables);
} OpenTypeFontFace;


/*
 * TrueType Collections
 */

struct TTCHeaderVersion1
{
  friend struct TTCHeader;

  inline unsigned int get_face_count (void) const { return table.len; }
  inline const OpenTypeFontFace& get_face (unsigned int i) const { return this+table[i]; }

  inline bool sanitize (hb_sanitize_context_t *c) const
  {
    TRACE_SANITIZE (this);
    return_trace (table.sanitize (c, this));
  }

  protected:
  Tag		ttcTag;		/* TrueType Collection ID string: 'ttcf' */
  FixedVersion<>version;	/* Version of the TTC Header (1.0),
				 * 0x00010000u */
  LArrayOf<LOffsetTo<OffsetTable> >
		table;		/* Array of offsets to the OffsetTable for each font
				 * from the beginning of the file */
  public:
  DEFINE_SIZE_ARRAY (12, table);
};

struct TTCHeader
{
  friend struct OpenTypeFontFile;

  private:

  inline unsigned int get_face_count (void) const
  {
    switch (u.header.version.major) {
    case 2: /* version 2 is compatible with version 1 */
    case 1: return u.version1.get_face_count ();
    default:return 0;
    }
  }
  inline const OpenTypeFontFace& get_face (unsigned int i) const
  {
    switch (u.header.version.major) {
    case 2: /* version 2 is compatible with version 1 */
    case 1: return u.version1.get_face (i);
    default:return Null(OpenTypeFontFace);
    }
  }

  inline bool sanitize (hb_sanitize_context_t *c) const
  {
    TRACE_SANITIZE (this);
    if (unlikely (!u.header.version.sanitize (c))) return_trace (false);
    switch (u.header.version.major) {
    case 2: /* version 2 is compatible with version 1 */
    case 1: return_trace (u.version1.sanitize (c));
    default:return_trace (true);
    }
  }

  protected:
  union {
  struct {
  Tag		ttcTag;		/* TrueType Collection ID string: 'ttcf' */
  FixedVersion<>version;	/* Version of the TTC Header (1.0 or 2.0),
				 * 0x00010000u or 0x00020000u */
  }			header;
  TTCHeaderVersion1	version1;
  } u;
};

/*
 * Mac Resource Fork
 */

struct ResourceRefItem
{
  inline bool sanitize (hb_sanitize_context_t *c) const
  {
    TRACE_SANITIZE (this);
    // actual data sanitization is done on ResourceForkHeader sanitizer
    return_trace (likely (c->check_struct (this)));
  }

  HBINT16	id;		/* Resource ID, is really should be signed? */
  HBINT16	nameOffset;	/* Offset from beginning of resource name list
				 * to resource name, minus means there is no */
  HBUINT8	attr;		/* Resource attributes */
  HBUINT24	dataOffset;	/* Offset from beginning of resource data to
				 * data for this resource */
  HBUINT32	reserved;	/* Reserved for handle to resource */
  public:
  DEFINE_SIZE_STATIC (12);
};

struct ResourceTypeItem
{
  inline bool sanitize (hb_sanitize_context_t *c) const
  {
    TRACE_SANITIZE (this);
    // RefList sanitization is done on ResourceMap sanitizer
    return_trace (likely (c->check_struct (this)));
  }

  inline unsigned int get_resource_count () const
  {
    return numRes + 1;
  }

  inline bool is_sfnt () const
  {
    return type == HB_TAG ('s','f','n','t');
  }

  inline const ResourceRefItem& get_ref_item (const void *base,
					      unsigned int i) const
  {
    return (base+refList)[i];
  }

  protected:
  Tag		type;		/* Resource type */
  HBUINT16	numRes;		/* Number of resource this type in map minus 1 */
  OffsetTo<UnsizedArrayOf<ResourceRefItem> >
		refList;	/* Offset from beginning of resource type list
				 * to reference list for this type */
  public:
  DEFINE_SIZE_STATIC (8);
};

struct ResourceMap
{
  inline bool sanitize (hb_sanitize_context_t *c) const
  {
    TRACE_SANITIZE (this);
    if (unlikely (!c->check_struct (this)))
      return_trace (false);
    for (unsigned int i = 0; i < get_types_count (); ++i)
    {
      const ResourceTypeItem& type = get_type (i);
      if (unlikely (!type.sanitize (c)))
        return_trace (false);
      for (unsigned int j = 0; j < type.get_resource_count (); ++j)
	if (unlikely (!get_ref_item (type, j).sanitize (c)))
	  return_trace (false);
    }
    return_trace (true);
  }

  inline const ResourceTypeItem& get_type (unsigned int i) const
  {
    // Why offset from the second byte of the object? I'm not sure
    return ((&reserved[2])+typeList)[i];
  }

  inline unsigned int get_types_count () const
  {
    return nTypes + 1;
  }

  inline const ResourceRefItem &get_ref_item (const ResourceTypeItem &type,
					      unsigned int i) const
  {
    return type.get_ref_item (&(this+typeList), i);
  }

  inline const PString& get_name (const ResourceRefItem &item,
				  unsigned int i) const
  {
    if (item.nameOffset == -1)
      return Null (PString);

    return StructAtOffset<PString> (this, nameList + item.nameOffset);
  }

  protected:
  HBUINT8	reserved[16];	/* Reserved for copy of resource header */
  LOffsetTo<ResourceMap>
		reserved1;	/* Reserved for handle to next resource map */
  HBUINT16	reserved2;	/* Reserved for file reference number */
  HBUINT16	attr;		/* Resource fork attribute */
  OffsetTo<UnsizedArrayOf<ResourceTypeItem> >
		typeList;	/* Offset from beginning of map to
				 * resource type list */
  HBUINT16	nameList;	/* Offset from beginning of map to
				 * resource name list */
  HBUINT16	nTypes;		/* Number of types in the map minus 1 */
  public:
  DEFINE_SIZE_STATIC (30);
};

struct ResourceForkHeader
{
  inline unsigned int get_face_count () const
  {
    const ResourceMap &resource_map = this+map;
    for (unsigned int i = 0; i < resource_map.get_types_count (); ++i)
    {
      const ResourceTypeItem& type = resource_map.get_type (i);
      if (type.is_sfnt ())
	return type.get_resource_count ();
    }
    return 0;
  }

  inline const LArrayOf<HBUINT8>& get_data (const ResourceTypeItem& type,
					    unsigned int idx) const
  {
    const ResourceMap &resource_map = this+map;
    unsigned int offset = dataOffset;
    offset += resource_map.get_ref_item (type, idx).dataOffset;
    return StructAtOffset<LArrayOf<HBUINT8> > (this, offset);
  }

  inline const OpenTypeFontFace& get_face (unsigned int idx) const
  {
    const ResourceMap &resource_map = this+map;
    for (unsigned int i = 0; i < resource_map.get_types_count (); ++i)
    {
      const ResourceTypeItem& type = resource_map.get_type (i);
      if (type.is_sfnt () && idx < type.get_resource_count ())
	return (OpenTypeFontFace&) get_data (type, idx).arrayZ;
    }
    return Null (OpenTypeFontFace);
  }

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

    const ResourceMap &resource_map = this+map;
    if (unlikely (!resource_map.sanitize (c)))
      return_trace (false);

    for (unsigned int i = 0; i < resource_map.get_types_count (); ++i)
    {
      const ResourceTypeItem& type = resource_map.get_type (i);
      for (unsigned int j = 0; j < type.get_resource_count (); ++j)
      {
        const LArrayOf<HBUINT8>& data = get_data (type, j);
	if (unlikely (!(data.sanitize (c) &&
			((OpenTypeFontFace&) data.arrayZ).sanitize (c))))
	  return_trace (false);
      }
    }

    return_trace (true);
  }

  protected:
  HBUINT32	dataOffset;	/* Offset from beginning of resource fork
				 * to resource data */
  LOffsetTo<ResourceMap>
		map;		/* Offset from beginning of resource fork
				 * to resource map */
  HBUINT32	dataLen;	/* Length of resource data */
  HBUINT32	mapLen;		/* Length of resource map */
  public:
  DEFINE_SIZE_STATIC (16);
};

/*
 * OpenType Font File
 */

struct OpenTypeFontFile
{
  static const hb_tag_t tableTag	= HB_TAG ('_','_','_','_'); /* Sanitizer needs this. */

  enum {
    CFFTag		= HB_TAG ('O','T','T','O'), /* OpenType with Postscript outlines */
    TrueTypeTag	= HB_TAG ( 0 , 1 , 0 , 0 ), /* OpenType with TrueType outlines */
    TTCTag		= HB_TAG ('t','t','c','f'), /* TrueType Collection */
    DFontTag		= HB_TAG ( 0 , 0 , 1 , 0 ), /* DFont Mac Resource Fork */
    TrueTag		= HB_TAG ('t','r','u','e'), /* Obsolete Apple TrueType */
    Typ1Tag		= HB_TAG ('t','y','p','1')  /* Obsolete Apple Type1 font in SFNT container */
  };

  inline hb_tag_t get_tag (void) const { return u.tag; }

  inline unsigned int get_face_count (void) const
  {
    switch (u.tag) {
    case CFFTag:	/* All the non-collection tags */
    case TrueTag:
    case Typ1Tag:
    case TrueTypeTag:	return 1;
    case TTCTag:	return u.ttcHeader.get_face_count ();
//    case DFontTag:	return u.rfHeader.get_face_count ();
    default:		return 0;
    }
  }
  inline const OpenTypeFontFace& get_face (unsigned int i) const
  {
    switch (u.tag) {
    /* Note: for non-collection SFNT data we ignore index.  This is because
     * Apple dfont container is a container of SFNT's.  So each SFNT is a
     * non-TTC, but the index is more than zero. */
    case CFFTag:	/* All the non-collection tags */
    case TrueTag:
    case Typ1Tag:
    case TrueTypeTag:	return u.fontFace;
    case TTCTag:	return u.ttcHeader.get_face (i);
//    case DFontTag:	return u.rfHeader.get_face (i);
    default:		return Null(OpenTypeFontFace);
    }
  }

  inline bool serialize_single (hb_serialize_context_t *c,
				hb_tag_t sfnt_tag,
			        Supplier<hb_tag_t> &tags,
			        Supplier<hb_blob_t *> &blobs,
			        unsigned int table_count)
  {
    TRACE_SERIALIZE (this);
    assert (sfnt_tag != TTCTag);
    if (unlikely (!c->extend_min (*this))) return_trace (false);
    return_trace (u.fontFace.serialize (c, sfnt_tag, tags, blobs, table_count));
  }

  inline bool sanitize (hb_sanitize_context_t *c) const
  {
    TRACE_SANITIZE (this);
    if (unlikely (!u.tag.sanitize (c))) return_trace (false);
    switch (u.tag) {
    case CFFTag:	/* All the non-collection tags */
    case TrueTag:
    case Typ1Tag:
    case TrueTypeTag:	return_trace (u.fontFace.sanitize (c));
    case TTCTag:	return_trace (u.ttcHeader.sanitize (c));
//    case DFontTag:	return_trace (u.rfHeader.sanitize (c));
    default:		return_trace (true);
    }
  }

  protected:
  union {
  Tag			tag;		/* 4-byte identifier. */
  OpenTypeFontFace	fontFace;
  TTCHeader		ttcHeader;
  ResourceForkHeader	rfHeader;
  } u;
  public:
  DEFINE_SIZE_UNION (4, tag);
};


} /* namespace OT */


#endif /* HB_OPEN_FILE_PRIVATE_HH */
