/*
 * Copyright © 2021  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.
 *
 */

#ifndef HB_OT_POST_TABLE_V2SUBSET_HH
#define HB_OT_POST_TABLE_V2SUBSET_HH

#include "hb-open-type.hh"
#include "hb-ot-post-table.hh"

/*
 * post -- PostScript
 * https://docs.microsoft.com/en-us/typography/opentype/spec/post
 */

namespace OT {
template<typename Iterator>
HB_INTERNAL bool postV2Tail::serialize (hb_serialize_context_t *c,
                                        Iterator it,
                                        const void* _post) const
{
  TRACE_SERIALIZE (this);
  auto *out = c->start_embed (this);
  if (unlikely (!c->check_success (out))) return_trace (false);
  if (!out->glyphNameIndex.serialize (c, + it
                                         | hb_map (hb_second)))
      return_trace (false);

  hb_set_t copied_indices;
  for (const auto& _ : + it )
  {
    unsigned glyph_id = _.first;
    unsigned new_index = _.second;

    if (new_index < 258) continue;
    if (copied_indices.has (new_index)) continue;
    copied_indices.add (new_index);

    hb_bytes_t s = reinterpret_cast<const post::accelerator_t*> (_post)->find_glyph_name (glyph_id);
    HBUINT8 *o = c->allocate_size<HBUINT8> (HBUINT8::static_size * (s.length + 1));
    if (unlikely (!o)) return_trace (false);
    if (!c->check_assign (o[0], s.length, HB_SERIALIZE_ERROR_INT_OVERFLOW)) return_trace (false);
    hb_memcpy (o+1, s.arrayZ, HBUINT8::static_size * s.length);
  }

  return_trace (true);
}

HB_INTERNAL bool postV2Tail::subset (hb_subset_context_t *c) const
{
  TRACE_SUBSET (this);

  const hb_map_t &reverse_glyph_map = *c->plan->reverse_glyph_map;
  unsigned num_glyphs = c->plan->num_output_glyphs ();
  hb_map_t old_new_index_map, old_gid_new_index_map;
  unsigned i = 0;

  post::accelerator_t _post (c->plan->source);

  hb_hashmap_t<hb_bytes_t, uint32_t, true> glyph_name_to_new_index;
  for (hb_codepoint_t new_gid = 0; new_gid < num_glyphs; new_gid++)
  {
    hb_codepoint_t old_gid = reverse_glyph_map.get (new_gid);
    unsigned old_index = glyphNameIndex[old_gid];

    unsigned new_index;
    const uint32_t *new_index2;
    if (old_index <= 257) new_index = old_index;
    else if (old_new_index_map.has (old_index, &new_index2))
    {
      new_index = *new_index2;
    } else {
      hb_bytes_t s = _post.find_glyph_name (old_gid);
      new_index = glyph_name_to_new_index.get (s);
      if (new_index == (unsigned)-1)
      {
        int standard_glyph_index = -1;
        for (unsigned i = 0; i < format1_names_length; i++)
        {
          if (s == format1_names (i))
          {
            standard_glyph_index = i;
            break;
          }
        }

        if (standard_glyph_index == -1)
        {
          new_index = 258 + i;
          i++;
        }
        else
        { new_index = standard_glyph_index; }
        glyph_name_to_new_index.set (s, new_index);
      }
      old_new_index_map.set (old_index, new_index);
    }
    old_gid_new_index_map.set (old_gid, new_index);
  }

  auto index_iter =
  + hb_range (num_glyphs)
  | hb_map (reverse_glyph_map)
  | hb_map_retains_sorting ([&](hb_codepoint_t old_gid)
                            {
                              unsigned new_index = old_gid_new_index_map.get (old_gid);
                              return hb_pair_t<unsigned, unsigned> (old_gid, new_index);
                            })
  ;

  return_trace (serialize (c->serializer, index_iter, &_post));
}

} /* namespace OT */
#endif /* HB_OT_POST_TABLE_V2SUBSET_HH */
