/*
 * 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, Roderick Sheeter
 */

#include "hb-open-type.hh"
#include "hb-ot-glyf-table.hh"
#include "hb-set.h"
#include "hb-subset-glyf.hh"

struct loca_data_t
{
  bool          is_short;
  void         *data;
  unsigned int  size;

  inline bool
  _write_loca_entry (unsigned int  id,
                     unsigned int  offset)
  {
    unsigned int entry_size = is_short ? sizeof (OT::HBUINT16) : sizeof (OT::HBUINT32);
    if ((id + 1) * entry_size <= size)
    {
      if (is_short) {
        ((OT::HBUINT16*) data) [id] = offset / 2;
      } else {
        ((OT::HBUINT32*) data) [id] = offset;
      }
      return true;
    }

    // Offset was not written because the write is out of bounds.
    DEBUG_MSG(SUBSET,
              nullptr,
              "WARNING: Attempted to write an out of bounds loca entry at index %d. Loca size is %d.",
              id,
              size);
    return false;
  }
};

/*
 * If hints are being dropped find the range which in glyf at which
 * the hinting instructions are located. Add them to the instruction_ranges
 * vector.
 */
static bool
_add_instructions_range (const OT::glyf::accelerator_t &glyf,
                         hb_codepoint_t                 glyph_id,
                         unsigned int                   glyph_start_offset,
                         unsigned int                   glyph_end_offset,
                         bool                           drop_hints,
                         hb_vector_t<unsigned int>     *instruction_ranges /* OUT */)
{
  if (!instruction_ranges->resize (instruction_ranges->length + 2))
  {
    DEBUG_MSG(SUBSET, nullptr, "Failed to resize instruction_ranges.");
    return false;
  }
  unsigned int *instruction_start = &(*instruction_ranges)[instruction_ranges->length - 2];
  *instruction_start = 0;
  unsigned int *instruction_end = &(*instruction_ranges)[instruction_ranges->length - 1];
  *instruction_end = 0;

  if (drop_hints)
  {
    if (unlikely (!glyf.get_instruction_offsets (glyph_start_offset, glyph_end_offset,
                                                 instruction_start, instruction_end)))
    {
      DEBUG_MSG(SUBSET, nullptr, "Unable to get instruction offsets for %d", glyph_id);
      return false;
    }
  }

  return true;
}

static bool
_calculate_glyf_and_loca_prime_size (const OT::glyf::accelerator_t &glyf,
                                     const hb_subset_plan_t        *plan,
                                     loca_data_t                   *loca_data, /* OUT */
				     unsigned int                  *glyf_size /* OUT */,
				     hb_vector_t<unsigned int>     *instruction_ranges /* OUT */)
{
  unsigned int total = 0;

  hb_codepoint_t next_glyph = HB_SET_VALUE_INVALID;
  while (plan->glyphset ()->next (&next_glyph))
  {
    unsigned int start_offset = 0, end_offset = 0;
    if (unlikely (!(glyf.get_offsets (next_glyph, &start_offset, &end_offset) &&
		    glyf.remove_padding (start_offset, &end_offset))))
    {
      DEBUG_MSG(SUBSET, nullptr, "Invalid gid %d", next_glyph);
      start_offset = end_offset = 0;
    }

    bool is_zero_length = end_offset - start_offset < OT::glyf::GlyphHeader::static_size;
    if (!_add_instructions_range (glyf,
                                  next_glyph,
                                  start_offset,
                                  end_offset,
                                  plan->drop_hints && !is_zero_length,
                                  instruction_ranges))
      return false;

    if (is_zero_length)
      continue; /* 0-length glyph */

    total += end_offset - start_offset
             - ((*instruction_ranges)[instruction_ranges->length - 1]
                - (*instruction_ranges)[instruction_ranges->length - 2]);
    /* round2 so short loca will work */
    total += total % 2;
  }

  *glyf_size = total;
  loca_data->is_short = (total <= 131070);
  loca_data->size = (plan->num_output_glyphs () + 1)
      * (loca_data->is_short ? sizeof (OT::HBUINT16) : sizeof (OT::HBUINT32));

  DEBUG_MSG(SUBSET, nullptr, "preparing to subset glyf: final size %d, loca size %d, using %s loca",
	    total,
	    loca_data->size,
	    loca_data->is_short ? "short" : "long");
  return true;
}

static void
_update_components (const hb_subset_plan_t *plan,
		    char                   *glyph_start,
		    unsigned int            length)
{
  OT::glyf::CompositeGlyphHeader::Iterator iterator;
  if (OT::glyf::CompositeGlyphHeader::get_iterator (glyph_start,
						    length,
						    &iterator))
  {
    do
    {
      hb_codepoint_t new_gid;
      if (!plan->new_gid_for_old_gid (iterator.current->glyphIndex,
				      &new_gid))
	continue;

      ((OT::glyf::CompositeGlyphHeader *) iterator.current)->glyphIndex = new_gid;
    } while (iterator.move_to_next ());
  }
}

static bool _remove_composite_instruction_flag (char *glyf_prime, unsigned int length)
{
  /* remove WE_HAVE_INSTRUCTIONS from flags in dest */
  OT::glyf::CompositeGlyphHeader::Iterator composite_it;
  if (unlikely (!OT::glyf::CompositeGlyphHeader::get_iterator (glyf_prime, length, &composite_it))) return false;
  const OT::glyf::CompositeGlyphHeader *glyph;
  do {
    glyph = composite_it.current;
    OT::HBUINT16 *flags = const_cast<OT::HBUINT16 *> (&glyph->flags);
    *flags = (uint16_t) *flags & ~OT::glyf::CompositeGlyphHeader::WE_HAVE_INSTRUCTIONS;
  } while (composite_it.move_to_next ());
  return true;
}

static bool
_write_glyf_and_loca_prime (const hb_subset_plan_t        *plan,
			    const OT::glyf::accelerator_t &glyf,
			    const char                    *glyf_data,
			    hb_vector_t<unsigned int>     &instruction_ranges,
			    unsigned int                   glyf_prime_size,
			    char                          *glyf_prime_data /* OUT */,
			    loca_data_t                   *loca_prime /* OUT */)
{
  char *glyf_prime_data_next = glyf_prime_data;

  bool success = true;


  unsigned int i = 0;
  hb_codepoint_t new_gid;
  for (new_gid = 0; new_gid < plan->num_output_glyphs (); new_gid++)
  {
    hb_codepoint_t old_gid;
    if (!plan->old_gid_for_new_gid (new_gid, &old_gid))
    {
      // Empty glyph, add a loca entry and carry on.
      loca_prime->_write_loca_entry (new_gid,
                                     glyf_prime_data_next - glyf_prime_data);
      continue;
    }


    unsigned int start_offset = 0, end_offset = 0;
    if (unlikely (!(glyf.get_offsets (old_gid, &start_offset, &end_offset) &&
		    glyf.remove_padding (start_offset, &end_offset))))
      end_offset = start_offset = 0;

    unsigned int instruction_start = instruction_ranges[i * 2];
    unsigned int instruction_end = instruction_ranges[i * 2 + 1];

    int length = end_offset - start_offset - (instruction_end - instruction_start);

    if (glyf_prime_data_next + length > glyf_prime_data + glyf_prime_size)
    {
      DEBUG_MSG(SUBSET,
                nullptr,
                "WARNING: Attempted to write an out of bounds glyph entry for gid %d (length %d)",
                i, length);
      return false;
    }

    if (instruction_start == instruction_end)
      memcpy (glyf_prime_data_next, glyf_data + start_offset, length);
    else
    {
      memcpy (glyf_prime_data_next, glyf_data + start_offset, instruction_start - start_offset);
      memcpy (glyf_prime_data_next + instruction_start - start_offset, glyf_data + instruction_end, end_offset - instruction_end);
      /* if the instructions end at the end this was a composite glyph, else simple */
      if (instruction_end == end_offset)
      {
	if (unlikely (!_remove_composite_instruction_flag (glyf_prime_data_next, length))) return false;
      }
      else
	/* zero instruction length, which is just before instruction_start */
	memset (glyf_prime_data_next + instruction_start - start_offset - 2, 0, 2);
    }

    success = success && loca_prime->_write_loca_entry (new_gid,
                                                        glyf_prime_data_next - glyf_prime_data);
    _update_components (plan, glyf_prime_data_next, length);

    // TODO: don't align to two bytes if using long loca.
    glyf_prime_data_next += length + (length % 2); // Align to 2 bytes for short loca.

    i++;
  }

  // loca table has n+1 entries where the last entry signifies the end location of the last
  // glyph.
  success = success && loca_prime->_write_loca_entry (new_gid,
                                                      glyf_prime_data_next - glyf_prime_data);
  return success;
}

static bool
_hb_subset_glyf_and_loca (const OT::glyf::accelerator_t  &glyf,
			  const char                     *glyf_data,
			  hb_subset_plan_t               *plan,
			  bool                           *use_short_loca,
			  hb_blob_t                     **glyf_prime_blob /* OUT */,
			  hb_blob_t                     **loca_prime_blob /* OUT */)
{
  // TODO(grieger): Sanity check allocation size for the new table.
  loca_data_t loca_prime;
  unsigned int glyf_prime_size;
  hb_vector_t<unsigned int> instruction_ranges;
  instruction_ranges.init ();

  if (unlikely (!_calculate_glyf_and_loca_prime_size (glyf,
                                                      plan,
                                                      &loca_prime,
						      &glyf_prime_size,
						      &instruction_ranges))) {
    instruction_ranges.fini ();
    return false;
  }
  *use_short_loca = loca_prime.is_short;

  char *glyf_prime_data = (char *) calloc (1, glyf_prime_size);
  loca_prime.data = (void *) calloc (1, loca_prime.size);
  if (unlikely (!_write_glyf_and_loca_prime (plan, glyf, glyf_data,
					     instruction_ranges,
					     glyf_prime_size, glyf_prime_data,
					     &loca_prime))) {
    free (glyf_prime_data);
    free (loca_prime.data);
    instruction_ranges.fini ();
    return false;
  }
  instruction_ranges.fini ();

  *glyf_prime_blob = hb_blob_create (glyf_prime_data,
                                     glyf_prime_size,
                                     HB_MEMORY_MODE_READONLY,
                                     glyf_prime_data,
                                     free);
  *loca_prime_blob = hb_blob_create ((char *) loca_prime.data,
                                     loca_prime.size,
                                     HB_MEMORY_MODE_READONLY,
                                     loca_prime.data,
                                     free);
  return true;
}

/**
 * hb_subset_glyf:
 * Subsets the glyph table according to a provided plan.
 *
 * Return value: subsetted glyf table.
 *
 * Since: 1.7.5
 **/
bool
hb_subset_glyf_and_loca (hb_subset_plan_t *plan,
			 bool             *use_short_loca, /* OUT */
			 hb_blob_t       **glyf_prime, /* OUT */
			 hb_blob_t       **loca_prime /* OUT */)
{
  hb_blob_t *glyf_blob = hb_sanitize_context_t ().reference_table<OT::glyf> (plan->source);
  const char *glyf_data = hb_blob_get_data (glyf_blob, nullptr);

  OT::glyf::accelerator_t glyf;
  glyf.init (plan->source);
  bool result = _hb_subset_glyf_and_loca (glyf,
					  glyf_data,
					  plan,
					  use_short_loca,
					  glyf_prime,
					  loca_prime);

  hb_blob_destroy (glyf_blob);
  glyf.fini ();

  return result;
}
