/*
 * 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);
}
