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 
  27 #include "hb-ot-cff1-table.hh"
  28 #include "hb-cff1-interp-cs.hh"
  29 
  30 using namespace CFF;
  31 
  32 /* SID to code */
  33 static const uint8_t standard_encoding_to_code [] =
  34 {
  35     0,   32,   33,   34,   35,   36,   37,   38,  39,   40,   41,   42,   43,   44,   45,   46,
  36    47,   48,   49,   50,   51,   52,   53,   54,  55,   56,   57,   58,   59,   60,   61,   62,
  37    63,   64,   65,   66,   67,   68,   69,   70,  71,   72,   73,   74,   75,   76,   77,   78,
  38    79,   80,   81,   82,   83,   84,   85,   86,  87,   88,   89,   90,   91,   92,   93,   94,
  39    95,   96,   97,   98,   99,  100,  101,  102, 103,  104,  105,  106,  107,  108,  109,  110,
  40   111,  112,  113,  114,  115,  116,  117,  118, 119,  120,  121,  122,  123,  124,  125,  126,
  41   161,  162,  163,  164,  165,  166,  167,  168, 169,  170,  171,  172,  173,  174,  175,  177,
  42   178,  179,  180,  182,  183,  184,  185,  186, 187,  188,  189,  191,  193,  194,  195,  196,
  43   197,  198,  199,  200,  202,  203,  205,  206, 207,  208,  225,  227,  232,  233,  234,  235,
  44   241,  245,  248,  249,  250,  251
  45 };
  46 
  47 /* SID to code */
  48 static const uint8_t expert_encoding_to_code [] =
  49 {
  50     0,   32,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,   44,   45,   46,
  51     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,   58,   59,    0,    0,    0,
  52     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  53     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  54     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  55     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  56     0,    0,    0,   47,    0,    0,    0,    0,    0,    0,    0,    0,    0,   87,   88,    0,
  57     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  58     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  59     0,    0,    0,    0,    0,    0,  201,    0,    0,    0,    0,  189,    0,    0,  188,    0,
  60     0,    0,    0,  190,  202,    0,    0,    0,    0,  203,    0,    0,    0,    0,    0,    0,
  61     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  62     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  63     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  64     0,    0,    0,    0,    0,   33,   34,   36,   37,   38,   39,   40,   41,   42,   43,   48,
  65    49,   50,   51,   52,   53,   54,   55,   56,   57,   60,   61,   62,   63,   65,   66,   67,
  66    68,   69,   73,   76,   77,   78,   79,   82,   83,   84,   86,   89,   90,   91,   93,   94,
  67    95,   96,   97,   98,   99,  100,  101,  102,  103,  104,  105,  106,  107,  108,  109,  110,
  68   111,  112,  113,  114,  115,  116,  117,  118,  119,  120,  121,  122,  123,  124,  125,  126,
  69   161,  162,  163,  166,  167,  168,  169,  170,  172,  175,  178,  179,  182,  183,  184,  191,
  70   192,  193,  194,  195,  196,  197,  200,  204,  205,  206,  207,  208,  209,  210,  211,  212,
  71   213,  214,  215,  216,  217,  218,  219,  220,  221,  222,  223,  224,  225,  226,  227,  228,
  72   229,  230,  231,  232,  233,  234,  235,  236,  237,  238,  239,  240,  241,  242,  243,  244,
  73   245,  246,  247,  248,  249,  250,  251,  252,  253,  254,  255
  74 };
  75 
  76 /* glyph ID to SID */
  77 static const uint16_t expert_charset_to_sid [] =
  78 {
  79     0,    1,  229,  230,  231,  232,  233,  234,  235,  236,  237,  238,   13,   14,   15,   99,
  80   239,  240,  241,  242,  243,  244,  245,  246,  247,  248,   27,   28,  249,  250,  251,  252,
  81   253,  254,  255,  256,  257,  258,  259,  260,  261,  262,  263,  264,  265,  266,  109,  110,
  82   267,  268,  269,  270,  271,  272,  273,  274,  275,  276,  277,  278,  279,  280,  281,  282,
  83   283,  284,  285,  286,  287,  288,  289,  290,  291,  292,  293,  294,  295,  296,  297,  298,
  84   299,  300,  301,  302,  303,  304,  305,  306,  307,  308,  309,  310,  311,  312,  313,  314,
  85   315,  316,  317,  318,  158,  155,  163,  319,  320,  321,  322,  323,  324,  325,  326,  150,
  86   164,  169,  327,  328,  329,  330,  331,  332,  333,  334,  335,  336,  337,  338,  339,  340,
  87   341,  342,  343,  344,  345,  346,  347,  348,  349,  350,  351,  352,  353,  354,  355,  356,
  88   357,  358,  359,  360,  361,  362,  363,  364,  365,  366,  367,  368,  369,  370,  371,  372,
  89   373,  374,  375,  376,  377,  378
  90 };
  91 
  92 /* glyph ID to SID */
  93 static const uint16_t expert_subset_charset_to_sid [] =
  94 {
  95     0,    1,  231,  232,  235,  236,  237,  238,   13,   14,   15,   99,  239,  240,  241,  242,
  96   243,  244,  245,  246,  247,  248,   27,   28,  249,  250,  251,  253,  254,  255,  256,  257,
  97   258,  259,  260,  261,  262,  263,  264,  265,  266,  109,  110,  267,  268,  269,  270,  272,
  98   300,  301,  302,  305,  314,  315,  158,  155,  163,  320,  321,  322,  323,  324,  325,  326,
  99   150,  164,  169,  327,  328,  329,  330,  331,  332,  333,  334,  335,  336,  337,  338,  339,
 100   340,  341,  342,  343,  344,  345,  346
 101 };
 102 
 103 /* code to SID */
 104 static const uint8_t standard_encoding_to_sid [] =
 105 {
 106     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
 107     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
 108     1,    2,    3,    4,    5,    6,    7,    8,    9,   10,   11,   12,   13,   14,   15,   16,
 109     17,  18,   19,   20,   21,   22,   23,   24,   25,   26,   27,   28,   29,   30,   31,   32,
 110     33,  34,   35,   36,   37,   38,   39,   40,   41,   42,   43,   44,   45,   46,   47,   48,
 111     49,  50,   51,   52,   53,   54,   55,   56,   57,   58,   59,   60,   61,   62,   63,   64,
 112     65,  66,   67,   68,   69,   70,   71,   72,   73,   74,   75,   76,   77,   78,   79,   80,
 113     81,  82,   83,   84,   85,   86,   87,   88,   89,   90,   91,   92,   93,   94,   95,    0,
 114     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
 115     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
 116     0,   96,   97,   98,   99,  100,  101,  102,  103,  104,  105,  106,  107,  108,  109,  110,
 117     0,  111,  112,  113,  114,    0,  115,  116,  117,  118,  119,  120,  121,  122,    0,  123,
 118     0,  124,  125,  126,  127,  128,  129,  130,  131,    0,  132,  133,    0,  134,  135,  136,
 119   137,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
 120     0,   138,   0,  139,    0,    0,    0,    0,  140,  141,  142,  143,    0,    0,    0,    0,
 121     0,   144,   0,    0,    0,  145,    0,    0,  146,  147,  148,  149,    0,    0,    0,    0
 122 };
 123 
 124 hb_codepoint_t OT::cff1::lookup_standard_encoding_for_code (hb_codepoint_t sid)
 125 {
 126   if (sid < ARRAY_LENGTH (standard_encoding_to_code))
 127     return (hb_codepoint_t)standard_encoding_to_code[sid];
 128   else
 129     return 0;
 130 }
 131 
 132 hb_codepoint_t OT::cff1::lookup_expert_encoding_for_code (hb_codepoint_t sid)
 133 {
 134   if (sid < ARRAY_LENGTH (expert_encoding_to_code))
 135     return (hb_codepoint_t)expert_encoding_to_code[sid];
 136   else
 137     return 0;
 138 }
 139 
 140 hb_codepoint_t OT::cff1::lookup_expert_charset_for_sid (hb_codepoint_t glyph)
 141 {
 142   if (glyph < ARRAY_LENGTH (expert_charset_to_sid))
 143     return (hb_codepoint_t)expert_charset_to_sid[glyph];
 144   else
 145     return 0;
 146 }
 147 
 148 hb_codepoint_t OT::cff1::lookup_expert_subset_charset_for_sid (hb_codepoint_t glyph)
 149 {
 150   if (glyph < ARRAY_LENGTH (expert_subset_charset_to_sid))
 151     return (hb_codepoint_t)expert_subset_charset_to_sid[glyph];
 152   else
 153     return 0;
 154 }
 155 
 156 hb_codepoint_t OT::cff1::lookup_standard_encoding_for_sid (hb_codepoint_t code)
 157 {
 158   if (code < ARRAY_LENGTH (standard_encoding_to_sid))
 159     return (hb_codepoint_t)standard_encoding_to_sid[code];
 160   else
 161     return CFF_UNDEF_SID;
 162 }
 163 
 164 struct bounds_t
 165 {
 166   void init ()
 167   {
 168     min.set_int (0x7FFFFFFF, 0x7FFFFFFF);
 169     max.set_int (-0x80000000, -0x80000000);
 170   }
 171 
 172   void update (const point_t &pt)
 173   {
 174     if (pt.x < min.x) min.x = pt.x;
 175     if (pt.x > max.x) max.x = pt.x;
 176     if (pt.y < min.y) min.y = pt.y;
 177     if (pt.y > max.y) max.y = pt.y;
 178   }
 179 
 180   void merge (const bounds_t &b)
 181   {
 182     if (empty ())
 183       *this = b;
 184     else if (!b.empty ())
 185     {
 186       if (b.min.x < min.x) min.x = b.min.x;
 187       if (b.max.x > max.x) max.x = b.max.x;
 188       if (b.min.y < min.y) min.y = b.min.y;
 189       if (b.max.y > max.y) max.y = b.max.y;
 190     }
 191   }
 192 
 193   void offset (const point_t &delta)
 194   {
 195     if (!empty ())
 196     {
 197       min.move (delta);
 198       max.move (delta);
 199     }
 200   }
 201 
 202   bool empty () const
 203   { return (min.x >= max.x) || (min.y >= max.y); }
 204 
 205   point_t min;
 206   point_t max;
 207 };
 208 
 209 struct extents_param_t
 210 {
 211   void init (const OT::cff1::accelerator_t *_cff)
 212   {
 213     path_open = false;
 214     cff = _cff;
 215     bounds.init ();
 216   }
 217 
 218   void start_path ()         { path_open = true; }
 219   void end_path ()           { path_open = false; }
 220   bool is_path_open () const { return path_open; }
 221 
 222   bool    path_open;
 223   bounds_t  bounds;
 224 
 225   const OT::cff1::accelerator_t *cff;
 226 };
 227 
 228 struct cff1_path_procs_extents_t : path_procs_t<cff1_path_procs_extents_t, cff1_cs_interp_env_t, extents_param_t>
 229 {
 230   static void moveto (cff1_cs_interp_env_t &env, extents_param_t& param, const point_t &pt)
 231   {
 232     param.end_path ();
 233     env.moveto (pt);
 234   }
 235 
 236   static void line (cff1_cs_interp_env_t &env, extents_param_t& param, const point_t &pt1)
 237   {
 238     if (!param.is_path_open ())
 239     {
 240       param.start_path ();
 241       param.bounds.update (env.get_pt ());
 242     }
 243     env.moveto (pt1);
 244     param.bounds.update (env.get_pt ());
 245   }
 246 
 247   static void curve (cff1_cs_interp_env_t &env, extents_param_t& param, const point_t &pt1, const point_t &pt2, const point_t &pt3)
 248   {
 249     if (!param.is_path_open ())
 250     {
 251       param.start_path ();
 252       param.bounds.update (env.get_pt ());
 253     }
 254     /* include control points */
 255     param.bounds.update (pt1);
 256     param.bounds.update (pt2);
 257     env.moveto (pt3);
 258     param.bounds.update (env.get_pt ());
 259   }
 260 };
 261 
 262 static bool _get_bounds (const OT::cff1::accelerator_t *cff, hb_codepoint_t glyph, bounds_t &bounds, bool in_seac=false);
 263 
 264 struct cff1_cs_opset_extents_t : cff1_cs_opset_t<cff1_cs_opset_extents_t, extents_param_t, cff1_path_procs_extents_t>
 265 {
 266   static void process_seac (cff1_cs_interp_env_t &env, extents_param_t& param)
 267   {
 268     unsigned int  n = env.argStack.get_count ();
 269     point_t delta;
 270     delta.x = env.argStack[n-4];
 271     delta.y = env.argStack[n-3];
 272     hb_codepoint_t base = param.cff->std_code_to_glyph (env.argStack[n-2].to_int ());
 273     hb_codepoint_t accent = param.cff->std_code_to_glyph (env.argStack[n-1].to_int ());
 274 
 275     bounds_t  base_bounds, accent_bounds;
 276     if (likely (!env.in_seac && base && accent
 277                && _get_bounds (param.cff, base, base_bounds, true)
 278                && _get_bounds (param.cff, accent, accent_bounds, true)))
 279     {
 280       param.bounds.merge (base_bounds);
 281       accent_bounds.offset (delta);
 282       param.bounds.merge (accent_bounds);
 283     }
 284     else
 285       env.set_error ();
 286   }
 287 };
 288 
 289 bool _get_bounds (const OT::cff1::accelerator_t *cff, hb_codepoint_t glyph, bounds_t &bounds, bool in_seac)
 290 {
 291   bounds.init ();
 292   if (unlikely (!cff->is_valid () || (glyph >= cff->num_glyphs))) return false;
 293 
 294   unsigned int fd = cff->fdSelect->get_fd (glyph);
 295   cff1_cs_interpreter_t<cff1_cs_opset_extents_t, extents_param_t> interp;
 296   const byte_str_t str = (*cff->charStrings)[glyph];
 297   interp.env.init (str, *cff, fd);
 298   interp.env.set_in_seac (in_seac);
 299   extents_param_t  param;
 300   param.init (cff);
 301   if (unlikely (!interp.interpret (param))) return false;
 302   bounds = param.bounds;
 303   return true;
 304 }
 305 
 306 bool OT::cff1::accelerator_t::get_extents (hb_codepoint_t glyph, hb_glyph_extents_t *extents) const
 307 {
 308   bounds_t  bounds;
 309 
 310   if (!_get_bounds (this, glyph, bounds))
 311     return false;
 312 
 313   if (bounds.min.x >= bounds.max.x)
 314   {
 315     extents->width = 0;
 316     extents->x_bearing = 0;
 317   }
 318   else
 319   {
 320     extents->x_bearing = (int32_t)bounds.min.x.floor ();
 321     extents->width = (int32_t)bounds.max.x.ceil () - extents->x_bearing;
 322   }
 323   if (bounds.min.y >= bounds.max.y)
 324   {
 325     extents->height = 0;
 326     extents->y_bearing = 0;
 327   }
 328   else
 329   {
 330     extents->y_bearing = (int32_t)bounds.max.y.ceil ();
 331     extents->height = (int32_t)bounds.min.y.floor () - extents->y_bearing;
 332   }
 333 
 334   return true;
 335 }
 336 
 337 struct get_seac_param_t
 338 {
 339   void init (const OT::cff1::accelerator_t *_cff)
 340   {
 341     cff = _cff;
 342     base = 0;
 343     accent = 0;
 344   }
 345 
 346   bool has_seac () const { return base && accent; }
 347 
 348   const OT::cff1::accelerator_t *cff;
 349   hb_codepoint_t  base;
 350   hb_codepoint_t  accent;
 351 };
 352 
 353 struct cff1_cs_opset_seac_t : cff1_cs_opset_t<cff1_cs_opset_seac_t, get_seac_param_t>
 354 {
 355   static void process_seac (cff1_cs_interp_env_t &env, get_seac_param_t& param)
 356   {
 357     unsigned int  n = env.argStack.get_count ();
 358     hb_codepoint_t  base_char = (hb_codepoint_t)env.argStack[n-2].to_int ();
 359     hb_codepoint_t  accent_char = (hb_codepoint_t)env.argStack[n-1].to_int ();
 360 
 361     param.base = param.cff->std_code_to_glyph (base_char);
 362     param.accent = param.cff->std_code_to_glyph (accent_char);
 363   }
 364 };
 365 
 366 bool OT::cff1::accelerator_t::get_seac_components (hb_codepoint_t glyph, hb_codepoint_t *base, hb_codepoint_t *accent) const
 367 {
 368   if (unlikely (!is_valid () || (glyph >= num_glyphs))) return false;
 369 
 370   unsigned int fd = fdSelect->get_fd (glyph);
 371   cff1_cs_interpreter_t<cff1_cs_opset_seac_t, get_seac_param_t> interp;
 372   const byte_str_t str = (*charStrings)[glyph];
 373   interp.env.init (str, *this, fd);
 374   get_seac_param_t  param;
 375   param.init (this);
 376   if (unlikely (!interp.interpret (param))) return false;
 377 
 378   if (param.has_seac ())
 379   {
 380     *base = param.base;
 381     *accent = param.accent;
 382     return true;
 383   }
 384   return false;
 385 }