/*
 * 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
 */
#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;
typedef BiasedSubrs<CFF2Subrs>   CFF2BiasedSubrs;

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 OpCode fetch_op (void)
  {
    if (this->substr.avail ())
      return SUPER::fetch_op ();

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

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

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

  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)
  {
    unsigned int  index = argStack.pop_uint ();
    if (unlikely (seen_vsindex () || seen_blend))
    {
      set_error ();
    }
    else
    {
      set_ivs (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_; }
  inline bool	 seen_vsindex (void) const { return seen_vsindex_; }

  protected:
  inline void 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);
      }
    }
  }

  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 void 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 ()))
	{
	  env.set_error ();
	  break;
	}
	SUPER::process_op (op, env, param);
	break;

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

      case OpCode_vsindexcs:
	if (unlikely (env.argStack.peek ().blending ()))
	{
	  env.set_error ();
	  break;
	}
	OPSET::process_vsindex (env, param);
	break;

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

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

    env.process_blend ();
    k = env.get_region_count ();
    n = env.argStack.pop_uint ();
    /* 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);
  }

  static inline void process_vsindex (CFF2CSInterpEnv &env, PARAM& param)
  {
    env.process_vsindex ();
    env.clear_args ();
  }

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