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