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

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

/* Disable FDSelect format 0 for compatibility with fonttools which doesn't seem choose it.
 * Rarely any/much smaller than format 3 anyway. */
#define CFF_SERIALIZE_FDSELECT_0  0

using namespace CFF;

/**
 * hb_plan_subset_cff_fdselect
 * Determine an optimal FDSelect format according to a provided plan.
 *
 * Return value: FDSelect format, size, and ranges for the most compact subset FDSelect
 * along with a font index remapping table
 **/

bool
hb_plan_subset_cff_fdselect (const hb_vector_t<hb_codepoint_t> &glyphs,
			    unsigned int fdCount,
			    const FDSelect &src, /* IN */
			    unsigned int &subset_fd_count /* OUT */,
			    unsigned int &subset_fdselect_size /* OUT */,
			    unsigned int &subset_fdselect_format /* OUT */,
			    hb_vector_t<code_pair> &fdselect_ranges /* OUT */,
			    Remap &fdmap /* OUT */)
{
  subset_fd_count = 0;
  subset_fdselect_size = 0;
  subset_fdselect_format = 0;
  unsigned int  num_ranges = 0;

  unsigned int subset_num_glyphs = glyphs.len;
  if (subset_num_glyphs == 0)
    return true;

  {
    /* use hb_set to determine the subset of font dicts */
    hb_set_t  *set = hb_set_create ();
    if (set == &Null (hb_set_t))
      return false;
    hb_codepoint_t  prev_fd = CFF_UNDEF_CODE;
    for (hb_codepoint_t i = 0; i < subset_num_glyphs; i++)
    {
      hb_codepoint_t  fd = src.get_fd (glyphs[i]);
      set->add (fd);

      if (fd != prev_fd)
      {
	num_ranges++;
	prev_fd = fd;
	code_pair pair = { fd, i };
	fdselect_ranges.push (pair);
      }
    }

    subset_fd_count = set->get_population ();
    if (subset_fd_count == fdCount)
    {
      /* all font dicts belong to the subset. no need to subset FDSelect & FDArray */
      fdmap.identity (fdCount);
      hb_set_destroy (set);
    }
    else
    {
      /* create a fdmap */
      if (!fdmap.reset (fdCount))
      {
	hb_set_destroy (set);
	return false;
      }

      hb_codepoint_t  fd = CFF_UNDEF_CODE;
      while (set->next (&fd))
	fdmap.add (fd);
      assert (fdmap.get_count () == subset_fd_count);
      hb_set_destroy (set);
    }

    /* update each font dict index stored as "code" in fdselect_ranges */
    for (unsigned int i = 0; i < fdselect_ranges.len; i++)
      fdselect_ranges[i].code = fdmap[fdselect_ranges[i].code];
  }

  /* determine which FDSelect format is most compact */
  if (subset_fd_count > 0xFF)
  {
    assert (src.format == 4);
    subset_fdselect_format = 4;
    subset_fdselect_size = FDSelect::min_size + FDSelect4::min_size + FDSelect4_Range::static_size * num_ranges + HBUINT32::static_size;
  }
  else
  {
#if CFF_SERIALIZE_FDSELECT_0
    unsigned int format0_size = FDSelect::min_size + FDSelect0::min_size + HBUINT8::static_size * subset_num_glyphs;
#endif
    unsigned int format3_size = FDSelect::min_size + FDSelect3::min_size + FDSelect3_Range::static_size * num_ranges + HBUINT16::static_size;

#if CFF_SERIALIZE_FDSELECT_0
    if (format0_size <= format3_size)
    {
      // subset_fdselect_format = 0;
      subset_fdselect_size = format0_size;
    }
    else
#endif
    {
      subset_fdselect_format = 3;
      subset_fdselect_size = format3_size;
    }
  }

  return true;
}

template <typename FDSELECT3_4>
static inline bool
serialize_fdselect_3_4 (hb_serialize_context_t *c,
			  const unsigned int num_glyphs,
			  const FDSelect &src,
			  unsigned int size,
			  const hb_vector_t<code_pair> &fdselect_ranges)
{
  TRACE_SERIALIZE (this);
  FDSELECT3_4 *p = c->allocate_size<FDSELECT3_4> (size);
  if (unlikely (p == nullptr)) return_trace (false);
  p->nRanges.set (fdselect_ranges.len);
  for (unsigned int i = 0; i < fdselect_ranges.len; i++)
  {
    p->ranges[i].first.set (fdselect_ranges[i].glyph);
    p->ranges[i].fd.set (fdselect_ranges[i].code);
  }
  p->sentinel().set (num_glyphs);
  return_trace (true);
}

/**
 * hb_serialize_cff_fdselect
 * Serialize a subset FDSelect format planned above.
 **/
bool
hb_serialize_cff_fdselect (hb_serialize_context_t *c,
			  const unsigned int num_glyphs,
			  const FDSelect &src,
			  unsigned int fd_count,
			  unsigned int fdselect_format,
			  unsigned int size,
			  const hb_vector_t<code_pair> &fdselect_ranges)
{
  TRACE_SERIALIZE (this);
  FDSelect  *p = c->allocate_min<FDSelect> ();
  if (unlikely (p == nullptr)) return_trace (false);
  p->format.set (fdselect_format);
  size -= FDSelect::min_size;

  switch (fdselect_format)
  {
#if CFF_SERIALIZE_FDSELECT_0
    case 0:
    {
      FDSelect0 *p = c->allocate_size<FDSelect0> (size);
      if (unlikely (p == nullptr)) return_trace (false);
      unsigned int range_index = 0;
      unsigned int  fd = fdselect_ranges[range_index++].code;
      for (unsigned int i = 0; i < num_glyphs; i++)
      {
	if ((range_index < fdselect_ranges.len) &&
	    (i >= fdselect_ranges[range_index].glyph))
	{
	  fd = fdselect_ranges[range_index++].code;
	}
	p->fds[i].set (fd);
      }
      break;
    }
#endif /* CFF_SERIALIZE_FDSELECT_0 */

    case 3:
      return serialize_fdselect_3_4<FDSelect3> (c,
						num_glyphs,
						src,
						size,
						fdselect_ranges);

    case 4:
      return serialize_fdselect_3_4<FDSelect4> (c,
						num_glyphs,
						src,
						size,
						fdselect_ranges);

    default:
      assert(false);
  }

  return_trace (true);
}
