• 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-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 
lookup_standard_encoding_for_code(hb_codepoint_t sid)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 
lookup_expert_encoding_for_code(hb_codepoint_t sid)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 
lookup_expert_charset_for_sid(hb_codepoint_t glyph)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 
lookup_expert_subset_charset_for_sid(hb_codepoint_t glyph)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 
lookup_standard_encoding_for_sid(hb_codepoint_t code)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 {
initBounds166   void init ()
167   {
168     min.set_int (0x7FFFFFFF, 0x7FFFFFFF);
169     max.set_int (-0x80000000, -0x80000000);
170   }
171 
updateBounds172   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 
mergeBounds180   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 
offsetBounds193   void offset (const Point &delta)
194   {
195     if (!empty ())
196     {
197       min.move (delta);
198       max.move (delta);
199     }
200   }
201 
emptyBounds202   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 {
initExtentsParam211   void init (const OT::cff1::accelerator_t *_cff)
212   {
213     path_open = false;
214     cff = _cff;
215     bounds.init ();
216   }
217 
start_pathExtentsParam218   void start_path ()         { path_open = true; }
end_pathExtentsParam219   void end_path ()           { path_open = false; }
is_path_openExtentsParam220   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 {
movetoCFF1PathProcs_Extents230   static void moveto (CFF1CSInterpEnv &env, ExtentsParam& param, const Point &pt)
231   {
232     param.end_path ();
233     env.moveto (pt);
234   }
235 
lineCFF1PathProcs_Extents236   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 
curveCFF1PathProcs_Extents247   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 {
process_seacCFF1CSOpSet_Extents266   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 
_get_bounds(const OT::cff1::accelerator_t * cff,hb_codepoint_t glyph,Bounds & bounds,bool in_seac)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 
get_extents(hb_codepoint_t glyph,hb_glyph_extents_t * extents) const306 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 {
initGetSeacParam339   void init (const OT::cff1::accelerator_t *_cff)
340   {
341     cff = _cff;
342     base = 0;
343     accent = 0;
344   }
345 
has_seacGetSeacParam346   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 {
process_seacCFF1CSOpSet_Seac355   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 
get_seac_components(hb_codepoint_t glyph,hb_codepoint_t * base,hb_codepoint_t * accent) const366 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