• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
lookup_standard_encoding_for_code(hb_codepoint_t sid)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 
lookup_expert_encoding_for_code(hb_codepoint_t sid)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 
lookup_expert_charset_for_sid(hb_codepoint_t glyph)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 
lookup_expert_subset_charset_for_sid(hb_codepoint_t glyph)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 
lookup_standard_encoding_for_sid(hb_codepoint_t code)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 {
initbounds_t170   void init ()
171   {
172     min.set_int (INT_MAX, INT_MAX);
173     max.set_int (INT_MIN, INT_MIN);
174   }
175 
updatebounds_t176   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 
mergebounds_t184   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 
offsetbounds_t197   void offset (const point_t &delta)
198   {
199     if (!empty ())
200     {
201       min.move (delta);
202       max.move (delta);
203     }
204   }
205 
emptybounds_t206   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 {
initcff1_extents_param_t214   void init (const OT::cff1::accelerator_t *_cff)
215   {
216     path_open = false;
217     cff = _cff;
218     bounds.init ();
219   }
220 
start_pathcff1_extents_param_t221   void start_path   ()       { path_open = true; }
end_pathcff1_extents_param_t222   void end_path     ()       { path_open = false; }
is_path_opencff1_extents_param_t223   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 {
movetocff1_path_procs_extents_t233   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 
linecff1_path_procs_extents_t239   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 
curvecff1_path_procs_extents_t250   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 {
process_seaccff1_cs_opset_extents_t269   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 
_get_bounds(const OT::cff1::accelerator_t * cff,hb_codepoint_t glyph,bounds_t & bounds,bool in_seac)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 
get_extents(hb_font_t * font,hb_codepoint_t glyph,hb_glyph_extents_t * extents) const309 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 {
initget_seac_param_t347   void init (const OT::cff1::accelerator_t *_cff)
348   {
349     cff = _cff;
350     base = 0;
351     accent = 0;
352   }
353 
has_seacget_seac_param_t354   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 {
process_seaccff1_cs_opset_seac_t363   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 
get_seac_components(hb_codepoint_t glyph,hb_codepoint_t * base,hb_codepoint_t * accent) const374 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
397