src/java.desktop/share/native/libfontmanager/harfbuzz/hb-cff2-interp-cs.hh
changeset 54232 7c11a7cc7c1d
equal deleted inserted replaced
54231:e4813eded7cb 54232:7c11a7cc7c1d
       
     1 /*
       
     2  * Copyright © 2018 Adobe Inc.
       
     3  *
       
     4  *  This is part of HarfBuzz, a text shaping library.
       
     5  *
       
     6  * Permission is hereby granted, without written agreement and without
       
     7  * license or royalty fees, to use, copy, modify, and distribute this
       
     8  * software and its documentation for any purpose, provided that the
       
     9  * above copyright notice and the following two paragraphs appear in
       
    10  * all copies of this software.
       
    11  *
       
    12  * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
       
    13  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
       
    14  * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
       
    15  * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
       
    16  * DAMAGE.
       
    17  *
       
    18  * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
       
    19  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
       
    20  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
       
    21  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
       
    22  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
       
    23  *
       
    24  * Adobe Author(s): Michiharu Ariza
       
    25  */
       
    26 #ifndef HB_CFF2_INTERP_CS_HH
       
    27 #define HB_CFF2_INTERP_CS_HH
       
    28 
       
    29 #include "hb.hh"
       
    30 #include "hb-cff-interp-cs-common.hh"
       
    31 
       
    32 namespace CFF {
       
    33 
       
    34 using namespace OT;
       
    35 
       
    36 struct blend_arg_t : number_t
       
    37 {
       
    38   void init ()
       
    39   {
       
    40     number_t::init ();
       
    41     deltas.init ();
       
    42   }
       
    43 
       
    44   void fini ()
       
    45   {
       
    46     number_t::fini ();
       
    47     deltas.fini_deep ();
       
    48   }
       
    49 
       
    50   void set_int (int v) { reset_blends (); number_t::set_int (v); }
       
    51   void set_fixed (int32_t v) { reset_blends (); number_t::set_fixed (v); }
       
    52   void set_real (double v) { reset_blends (); number_t::set_real (v); }
       
    53 
       
    54   void set_blends (unsigned int numValues_, unsigned int valueIndex_,
       
    55                           unsigned int numBlends, hb_array_t<const blend_arg_t> blends_)
       
    56   {
       
    57     numValues = numValues_;
       
    58     valueIndex = valueIndex_;
       
    59     deltas.resize (numBlends);
       
    60     for (unsigned int i = 0; i < numBlends; i++)
       
    61       deltas[i] = blends_[i];
       
    62   }
       
    63 
       
    64   bool blending () const { return deltas.length > 0; }
       
    65   void reset_blends ()
       
    66   {
       
    67     numValues = valueIndex = 0;
       
    68     deltas.resize (0);
       
    69   }
       
    70 
       
    71   unsigned int numValues;
       
    72   unsigned int valueIndex;
       
    73   hb_vector_t<number_t> deltas;
       
    74 };
       
    75 
       
    76 typedef interp_env_t<blend_arg_t> BlendInterpEnv;
       
    77 typedef biased_subrs_t<CFF2Subrs>   cff2_biased_subrs_t;
       
    78 
       
    79 struct cff2_cs_interp_env_t : cs_interp_env_t<blend_arg_t, CFF2Subrs>
       
    80 {
       
    81   template <typename ACC>
       
    82   void init (const byte_str_t &str, ACC &acc, unsigned int fd,
       
    83                     const int *coords_=nullptr, unsigned int num_coords_=0)
       
    84   {
       
    85     SUPER::init (str, *acc.globalSubrs, *acc.privateDicts[fd].localSubrs);
       
    86 
       
    87     coords = coords_;
       
    88     num_coords = num_coords_;
       
    89     varStore = acc.varStore;
       
    90     seen_blend = false;
       
    91     seen_vsindex_ = false;
       
    92     scalars.init ();
       
    93     do_blend = (coords != nullptr) && num_coords && (varStore != &Null(CFF2VariationStore));
       
    94     set_ivs (acc.privateDicts[fd].ivs);
       
    95   }
       
    96 
       
    97   void fini ()
       
    98   {
       
    99     scalars.fini ();
       
   100     SUPER::fini ();
       
   101   }
       
   102 
       
   103   op_code_t fetch_op ()
       
   104   {
       
   105     if (this->str_ref.avail ())
       
   106       return SUPER::fetch_op ();
       
   107 
       
   108     /* make up return or endchar op */
       
   109     if (this->callStack.is_empty ())
       
   110       return OpCode_endchar;
       
   111     else
       
   112       return OpCode_return;
       
   113   }
       
   114 
       
   115   const blend_arg_t& eval_arg (unsigned int i)
       
   116   {
       
   117     blend_arg_t  &arg = argStack[i];
       
   118     blend_arg (arg);
       
   119     return arg;
       
   120   }
       
   121 
       
   122   const blend_arg_t& pop_arg ()
       
   123   {
       
   124     blend_arg_t  &arg = argStack.pop ();
       
   125     blend_arg (arg);
       
   126     return arg;
       
   127   }
       
   128 
       
   129   void process_blend ()
       
   130   {
       
   131     if (!seen_blend)
       
   132     {
       
   133       region_count = varStore->varStore.get_region_index_count (get_ivs ());
       
   134       if (do_blend)
       
   135       {
       
   136         scalars.resize (region_count);
       
   137         varStore->varStore.get_scalars (get_ivs (),
       
   138                                         (int *)coords, num_coords,
       
   139                                         &scalars[0], region_count);
       
   140       }
       
   141       seen_blend = true;
       
   142     }
       
   143   }
       
   144 
       
   145   void process_vsindex ()
       
   146   {
       
   147     unsigned int  index = argStack.pop_uint ();
       
   148     if (unlikely (seen_vsindex () || seen_blend))
       
   149     {
       
   150       set_error ();
       
   151     }
       
   152     else
       
   153     {
       
   154       set_ivs (index);
       
   155     }
       
   156     seen_vsindex_ = true;
       
   157   }
       
   158 
       
   159   unsigned int get_region_count () const { return region_count; }
       
   160   void   set_region_count (unsigned int region_count_) { region_count = region_count_; }
       
   161   unsigned int get_ivs () const { return ivs; }
       
   162   void   set_ivs (unsigned int ivs_) { ivs = ivs_; }
       
   163   bool   seen_vsindex () const { return seen_vsindex_; }
       
   164 
       
   165   protected:
       
   166   void blend_arg (blend_arg_t &arg)
       
   167   {
       
   168     if (do_blend && arg.blending ())
       
   169     {
       
   170       if (likely (scalars.length == arg.deltas.length))
       
   171       {
       
   172         double v = arg.to_real ();
       
   173         for (unsigned int i = 0; i < scalars.length; i++)
       
   174         {
       
   175           v += (double)scalars[i] * arg.deltas[i].to_real ();
       
   176         }
       
   177         arg.set_real (v);
       
   178         arg.deltas.resize (0);
       
   179       }
       
   180     }
       
   181   }
       
   182 
       
   183   protected:
       
   184   const int     *coords;
       
   185   unsigned int  num_coords;
       
   186   const  CFF2VariationStore *varStore;
       
   187   unsigned int  region_count;
       
   188   unsigned int  ivs;
       
   189   hb_vector_t<float>  scalars;
       
   190   bool    do_blend;
       
   191   bool    seen_vsindex_;
       
   192   bool    seen_blend;
       
   193 
       
   194   typedef cs_interp_env_t<blend_arg_t, CFF2Subrs> SUPER;
       
   195 };
       
   196 template <typename OPSET, typename PARAM, typename PATH=path_procs_null_t<cff2_cs_interp_env_t, PARAM> >
       
   197 struct cff2_cs_opset_t : cs_opset_t<blend_arg_t, OPSET, cff2_cs_interp_env_t, PARAM, PATH>
       
   198 {
       
   199   static void process_op (op_code_t op, cff2_cs_interp_env_t &env, PARAM& param)
       
   200   {
       
   201     switch (op) {
       
   202       case OpCode_callsubr:
       
   203       case OpCode_callgsubr:
       
   204         /* a subroutine number shoudln't be a blended value */
       
   205         if (unlikely (env.argStack.peek ().blending ()))
       
   206         {
       
   207           env.set_error ();
       
   208           break;
       
   209         }
       
   210         SUPER::process_op (op, env, param);
       
   211         break;
       
   212 
       
   213       case OpCode_blendcs:
       
   214         OPSET::process_blend (env, param);
       
   215         break;
       
   216 
       
   217       case OpCode_vsindexcs:
       
   218         if (unlikely (env.argStack.peek ().blending ()))
       
   219         {
       
   220           env.set_error ();
       
   221           break;
       
   222         }
       
   223         OPSET::process_vsindex (env, param);
       
   224         break;
       
   225 
       
   226       default:
       
   227         SUPER::process_op (op, env, param);
       
   228     }
       
   229   }
       
   230 
       
   231   static void process_blend (cff2_cs_interp_env_t &env, PARAM& param)
       
   232   {
       
   233     unsigned int n, k;
       
   234 
       
   235     env.process_blend ();
       
   236     k = env.get_region_count ();
       
   237     n = env.argStack.pop_uint ();
       
   238     /* copy the blend values into blend array of the default values */
       
   239     unsigned int start = env.argStack.get_count () - ((k+1) * n);
       
   240     /* let an obvious error case fail, but note CFF2 spec doesn't forbid n==0 */
       
   241     if (unlikely (start > env.argStack.get_count ()))
       
   242     {
       
   243       env.set_error ();
       
   244       return;
       
   245     }
       
   246     for (unsigned int i = 0; i < n; i++)
       
   247     {
       
   248       const hb_array_t<const blend_arg_t>       blends = env.argStack.get_subarray (start + n + (i * k));
       
   249       env.argStack[start + i].set_blends (n, i, k, blends);
       
   250     }
       
   251 
       
   252     /* pop off blend values leaving default values now adorned with blend values */
       
   253     env.argStack.pop (k * n);
       
   254   }
       
   255 
       
   256   static void process_vsindex (cff2_cs_interp_env_t &env, PARAM& param)
       
   257   {
       
   258     env.process_vsindex ();
       
   259     env.clear_args ();
       
   260   }
       
   261 
       
   262   private:
       
   263   typedef cs_opset_t<blend_arg_t, OPSET, cff2_cs_interp_env_t, PARAM, PATH>  SUPER;
       
   264 };
       
   265 
       
   266 template <typename OPSET, typename PARAM>
       
   267 struct cff2_cs_interpreter_t : cs_interpreter_t<cff2_cs_interp_env_t, OPSET, PARAM> {};
       
   268 
       
   269 } /* namespace CFF */
       
   270 
       
   271 #endif /* HB_CFF2_INTERP_CS_HH */