Home | History | Annotate | Download | only in src
      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
    165 {
    166   void init ()
    167   {
    168     min.set_int (0x7FFFFFFF, 0x7FFFFFFF);
    169     max.set_int (-0x80000000, -0x80000000);
    170   }
    171 
    172   void update (const Point &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 &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 &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 min;
    206   Point max;
    207 };
    208 
    209 struct ExtentsParam
    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  bounds;
    224 
    225   const OT::cff1::accelerator_t *cff;
    226 };
    227 
    228 struct CFF1PathProcs_Extents : PathProcs<CFF1PathProcs_Extents, CFF1CSInterpEnv, ExtentsParam>
    229 {
    230   static void moveto (CFF1CSInterpEnv &env, ExtentsParam& param, const Point &pt)
    231   {
    232     param.end_path ();
    233     env.moveto (pt);
    234   }
    235 
    236   static void line (CFF1CSInterpEnv &env, ExtentsParam& param, const Point &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 (CFF1CSInterpEnv &env, ExtentsParam& param, const Point &pt1, const Point &pt2, const Point &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 &bounds, bool in_seac=false);
    263 
    264 struct CFF1CSOpSet_Extents : CFF1CSOpSet<CFF1CSOpSet_Extents, ExtentsParam, CFF1PathProcs_Extents>
    265 {
    266   static void process_seac (CFF1CSInterpEnv &env, ExtentsParam& param)
    267   {
    268     unsigned int  n = env.argStack.get_count ();
    269     Point 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  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 &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   CFF1CSInterpreter<CFF1CSOpSet_Extents, ExtentsParam> interp;
    296   const ByteStr str = (*cff->charStrings)[glyph];
    297   interp.env.init (str, *cff, fd);
    298   interp.env.set_in_seac (in_seac);
    299   ExtentsParam  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  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 GetSeacParam
    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 CFF1CSOpSet_Seac : CFF1CSOpSet<CFF1CSOpSet_Seac, GetSeacParam>
    354 {
    355   static void process_seac (CFF1CSInterpEnv &env, GetSeacParam& 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   CFF1CSInterpreter<CFF1CSOpSet_Seac, GetSeacParam> interp;
    372   const ByteStr str = (*charStrings)[glyph];
    373   interp.env.init (str, *this, fd);
    374   GetSeacParam  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 }
    386