/*
 * Copyright © 2018 Adobe Systems Incorporated.
 *
 *  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
 */
#ifndef HB_CFF2_INTERP_CS_HH
#define HB_CFF2_INTERP_CS_HH

#include "hb.hh"
#include "hb-cff-interp-cs-common.hh"

namespace CFF {

using namespace OT;

struct BlendArg : Number
{
  inline void init (void)
  {
    Number::init ();
    deltas.init ();
  }

  inline void fini (void)
  {
    Number::fini ();
    deltas.fini_deep ();
  }

  inline void set_int (int v) { reset_blends (); Number::set_int (v); }
  inline void set_fixed (int32_t v) { reset_blends (); Number::set_fixed (v); }
  inline void set_real (float v) { reset_blends (); Number::set_real (v); }

  inline void set_blends (unsigned int numValues_, unsigned int valueIndex_,
                          unsigned int numBlends, const BlendArg *blends_)
  {
    numValues = numValues_;
    valueIndex = valueIndex_;
    deltas.resize (numBlends);
    for (unsigned int i = 0; i < numBlends; i++)
      deltas[i] = blends_[i];
  }

  inline bool blending (void) const { return deltas.len > 0; }
  inline void reset_blends (void)
  {
    numValues = valueIndex = 0;
    deltas.resize (0);
  }

  unsigned int numValues;
  unsigned int valueIndex;
  hb_vector_t<Number> deltas;
};

typedef InterpEnv<BlendArg> BlendInterpEnv;

struct CFF2CSInterpEnv : CSInterpEnv<BlendArg, CFF2Subrs>
{
  template <typename ACC>
  inline void init (const ByteStr &str, ACC &acc, unsigned int fd,
                    const int *coords_=nullptr, unsigned int num_coords_=0)
  {
    SUPER::init (str, *acc.globalSubrs, *acc.privateDicts[fd].localSubrs);
    
    coords = coords_;
    num_coords = num_coords_;
    varStore = acc.varStore;
    seen_blend = false;
    seen_vsindex = false;
    scalars.init ();
    do_blend = (coords != nullptr) && num_coords && (varStore != &Null(CFF2VariationStore));
    set_ivs (acc.privateDicts[fd].ivs);
  }

  inline void fini (void)
  {
    scalars.fini ();
    SUPER::fini ();
  }

  inline bool fetch_op (OpCode &op)
  {
    if (this->substr.avail ())
      return SUPER::fetch_op (op);

    /* make up return or endchar op */
    if (this->callStack.check_underflow ())
      op = OpCode_return;
    else
      op = OpCode_endchar;
    return true;
  }

  inline const BlendArg& eval_arg (unsigned int i)
  {
    return blend_arg (argStack[i]);
  }

  inline const BlendArg& pop_arg (void)
  {
    return blend_arg (argStack.pop ());
  }

  inline void process_blend (void)
  {
    if (!seen_blend)
    {
      region_count = varStore->varStore.get_region_index_count (get_ivs ());
      if (do_blend)
      {
        scalars.resize (region_count);
        varStore->varStore.get_scalars (get_ivs (),
                                        (int *)coords, num_coords,
                                        &scalars[0], region_count);
      }
      seen_blend = true;
    }
  }

  inline void process_vsindex (void)
  {
    if (do_blend)
    {
      unsigned int  index;
      if (likely (!seen_vsindex && !seen_blend && argStack.check_pop_uint (index)))
        set_ivs (argStack.check_pop_uint (index));
    }
    seen_vsindex = true;
  }

  inline unsigned int get_region_count (void) const { return region_count; }
  inline void         set_region_count (unsigned int region_count_) { region_count = region_count_; }
  inline unsigned int get_ivs (void) const { return ivs; }
  inline void         set_ivs (unsigned int ivs_) { ivs = ivs_; }

  protected:
  inline BlendArg& blend_arg (BlendArg &arg)
  {
    if (do_blend && arg.blending ())
    {
      if (likely (scalars.len == arg.deltas.len))
      {
        float v = arg.to_real ();
        for (unsigned int i = 0; i < scalars.len; i++)
        {
          v += scalars[i] * arg.deltas[i].to_real ();
        }
        arg.set_real (v);
        arg.deltas.resize (0);
      }
    }
    return arg;
  }

  protected:
  const int     *coords;
  unsigned int  num_coords;
  const         CFF2VariationStore *varStore;
  unsigned int  region_count;
  unsigned int  ivs;
  hb_vector_t<float>  scalars;
  bool          do_blend;
  bool          seen_vsindex;
  bool          seen_blend;

  typedef CSInterpEnv<BlendArg, CFF2Subrs> SUPER;
};
template <typename OPSET, typename PARAM, typename PATH=PathProcsNull<CFF2CSInterpEnv, PARAM> >
struct CFF2CSOpSet : CSOpSet<BlendArg, OPSET, CFF2CSInterpEnv, PARAM, PATH>
{
  static inline bool process_op (OpCode op, CFF2CSInterpEnv &env, PARAM& param)
  {
    switch (op) {
      case OpCode_callsubr:
      case OpCode_callgsubr:
        /* a subroutine number shoudln't be a blended value */
        if (unlikely (env.argStack.peek ().blending ()))
          return false;
        return SUPER::process_op (op, env, param);

      case OpCode_blendcs:
        return OPSET::process_blend (env, param);

      case OpCode_vsindexcs:
        if (unlikely (env.argStack.peek ().blending ()))
          return false;
        OPSET::process_vsindex (env, param);
        break;

      default:
        return SUPER::process_op (op, env, param);
    }
    return true;
  }

  static inline bool process_blend (CFF2CSInterpEnv &env, PARAM& param)
  {
    unsigned int n, k;

    env.process_blend ();
    k = env.get_region_count ();
    if (unlikely (!env.argStack.check_pop_uint (n) ||
                  (k+1) * n > env.argStack.get_count ()))
      return false;
    /* copy the blend values into blend array of the default values */
    unsigned int start = env.argStack.get_count () - ((k+1) * n);
    for (unsigned int i = 0; i < n; i++)
      env.argStack[start + i].set_blends (n, i, k, &env.argStack[start + n + (i * k)]);

    /* pop off blend values leaving default values now adorned with blend values */
    env.argStack.pop (k * n);
    return true;
  }

  static inline void process_vsindex (CFF2CSInterpEnv &env, PARAM& param)
  {
    env.process_vsindex ();
    OPSET::flush_args_and_op (OpCode_vsindexcs, env, param, env.argStack.get_count ()-1);
  }

  private:
  typedef CSOpSet<BlendArg, OPSET, CFF2CSInterpEnv, PARAM, PATH>  SUPER;
};

template <typename OPSET, typename PARAM>
struct CFF2CSInterpreter : CSInterpreter<CFF2CSInterpEnv, OPSET, PARAM> {};

} /* namespace CFF */

#endif /* HB_CFF2_INTERP_CS_HH */
