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

static bool
_calculate_glyf_and_loca_prime_size (const OT::glyf::accelerator_t &glyf,
				     hb_vector_t<hb_codepoint_t> &glyph_ids,
				     hb_bool_t drop_hints,
				     bool *use_short_loca /* OUT */,
				     unsigned int *glyf_size /* OUT */,
				     unsigned int *loca_size /* OUT */,
				     hb_vector_t<unsigned int> *instruction_ranges /* OUT */)
{
  unsigned int total = 0;
  for (unsigned int i = 0; i < glyph_ids.len; i++)
  {
    hb_codepoint_t next_glyph = glyph_ids[i];
    if (!instruction_ranges->resize (instruction_ranges->len + 2))
    {
      DEBUG_MSG(SUBSET, nullptr, "Failed to resize instruction_ranges.");
      return false;
    }
    unsigned int *instruction_start = &(*instruction_ranges)[instruction_ranges->len - 2];
    *instruction_start = 0;
    unsigned int *instruction_end = &(*instruction_ranges)[instruction_ranges->len - 1];
    *instruction_end = 0;

    unsigned int start_offset, end_offset;
    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);
      continue;
    }
    if (end_offset - start_offset < OT::glyf::GlyphHeader::static_size)
      continue; /* 0-length glyph */

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

    total += end_offset - start_offset - (*instruction_end - *instruction_start);
    /* round2 so short loca will work */
    total += total % 2;
  }

  *glyf_size = total;
  *use_short_loca = (total <= 131070);
  *loca_size = (glyph_ids.len + 1)
      * (*use_short_loca ? 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_size,
	    *use_short_loca ? "short" : "long");
  return true;
}

static bool
_write_loca_entry (unsigned int  id,
		   unsigned int  offset,
		   bool          is_short,
		   void         *loca_prime,
		   unsigned int  loca_size)
{
  unsigned int entry_size = is_short ? sizeof (OT::HBUINT16) : sizeof (OT::HBUINT32);
  if ((id + 1) * entry_size <= loca_size)
  {
    if (is_short) {
      ((OT::HBUINT16*) loca_prime) [id].set (offset / 2);
    } else {
      ((OT::HBUINT32*) loca_prime) [id].set (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,
	    loca_size);
  return false;
}

static void
_update_components (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.set (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->set ( (uint16_t) *flags & ~OT::glyf::CompositeGlyphHeader::WE_HAVE_INSTRUCTIONS);
  } while (composite_it.move_to_next ());
  return true;
}

static bool
_write_glyf_and_loca_prime (hb_subset_plan_t              *plan,
			    const OT::glyf::accelerator_t &glyf,
			    const char                    *glyf_data,
			    bool                           use_short_loca,
			    hb_vector_t<unsigned int> &instruction_ranges,
			    unsigned int                   glyf_prime_size,
			    char                          *glyf_prime_data /* OUT */,
			    unsigned int                   loca_prime_size,
			    char                          *loca_prime_data /* OUT */)
{
  hb_vector_t<hb_codepoint_t> &glyph_ids = plan->glyphs;
  char *glyf_prime_data_next = glyf_prime_data;

  bool success = true;
  for (unsigned int i = 0; i < glyph_ids.len; i++)
  {
    unsigned int start_offset, end_offset;
    if (unlikely (!(glyf.get_offsets (glyph_ids[i], &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 && _write_loca_entry (i,
					    glyf_prime_data_next - glyf_prime_data,
					    use_short_loca,
					    loca_prime_data,
					    loca_prime_size);
    _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.
  }

  success = success && _write_loca_entry (glyph_ids.len,
					  glyf_prime_data_next - glyf_prime_data,
					  use_short_loca,
					  loca_prime_data,
					  loca_prime_size);
  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 /* OUT */,
			  hb_blob_t                     **loca_prime /* OUT */)
{
  // TODO(grieger): Sanity check allocation size for the new table.
  hb_vector_t<hb_codepoint_t> &glyphs_to_retain = plan->glyphs;

  unsigned int glyf_prime_size;
  unsigned int loca_prime_size;
  hb_vector_t<unsigned int> instruction_ranges;
  instruction_ranges.init ();

  if (unlikely (!_calculate_glyf_and_loca_prime_size (glyf,
						      glyphs_to_retain,
						      plan->drop_hints,
						      use_short_loca,
						      &glyf_prime_size,
						      &loca_prime_size,
						      &instruction_ranges))) {
    instruction_ranges.fini ();
    return false;
  }

  char *glyf_prime_data = (char *) calloc (1, glyf_prime_size);
  char *loca_prime_data = (char *) calloc (1, loca_prime_size);
  if (unlikely (!_write_glyf_and_loca_prime (plan, glyf, glyf_data,
					     *use_short_loca,
					     instruction_ranges,
					     glyf_prime_size, glyf_prime_data,
					     loca_prime_size, loca_prime_data))) {
    free (glyf_prime_data);
    free (loca_prime_data);
    instruction_ranges.fini ();
    return false;
  }
  instruction_ranges.fini ();

  *glyf_prime = hb_blob_create (glyf_prime_data,
				glyf_prime_size,
				HB_MEMORY_MODE_READONLY,
				glyf_prime_data,
				free);
  *loca_prime = hb_blob_create (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;
}
