Imported Upstream version 2.6.7
[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-draw.hh"
32 #include "hb-algs.hh"
33 #include "hb-ot-cff1-table.hh"
34 #include "hb-cff1-interp-cs.hh"
35
36 using namespace CFF;
37
38 struct sid_to_gid_t
39 {
40   uint16_t  sid;
41   uint8_t   gid;
42
43   int cmp (uint16_t a) const
44   {
45     if (a == sid) return 0;
46     return (a < sid) ? -1 : 1;
47   }
48 };
49
50 /* SID to code */
51 static const uint8_t standard_encoding_to_code [] =
52 {
53     0,   32,   33,   34,   35,   36,   37,   38,  39,   40,   41,   42,   43,   44,   45,   46,
54    47,   48,   49,   50,   51,   52,   53,   54,  55,   56,   57,   58,   59,   60,   61,   62,
55    63,   64,   65,   66,   67,   68,   69,   70,  71,   72,   73,   74,   75,   76,   77,   78,
56    79,   80,   81,   82,   83,   84,   85,   86,  87,   88,   89,   90,   91,   92,   93,   94,
57    95,   96,   97,   98,   99,  100,  101,  102, 103,  104,  105,  106,  107,  108,  109,  110,
58   111,  112,  113,  114,  115,  116,  117,  118, 119,  120,  121,  122,  123,  124,  125,  126,
59   161,  162,  163,  164,  165,  166,  167,  168, 169,  170,  171,  172,  173,  174,  175,  177,
60   178,  179,  180,  182,  183,  184,  185,  186, 187,  188,  189,  191,  193,  194,  195,  196,
61   197,  198,  199,  200,  202,  203,  205,  206, 207,  208,  225,  227,  232,  233,  234,  235,
62   241,  245,  248,  249,  250,  251
63 };
64
65 /* SID to code */
66 static const uint8_t expert_encoding_to_code [] =
67 {
68     0,   32,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,   44,   45,   46,
69     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,   58,   59,    0,    0,    0,
70     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
71     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
72     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
73     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
74     0,    0,    0,   47,    0,    0,    0,    0,    0,    0,    0,    0,    0,   87,   88,    0,
75     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
76     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
77     0,    0,    0,    0,    0,    0,  201,    0,    0,    0,    0,  189,    0,    0,  188,    0,
78     0,    0,    0,  190,  202,    0,    0,    0,    0,  203,    0,    0,    0,    0,    0,    0,
79     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
80     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
81     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
82     0,    0,    0,    0,    0,   33,   34,   36,   37,   38,   39,   40,   41,   42,   43,   48,
83    49,   50,   51,   52,   53,   54,   55,   56,   57,   60,   61,   62,   63,   65,   66,   67,
84    68,   69,   73,   76,   77,   78,   79,   82,   83,   84,   86,   89,   90,   91,   93,   94,
85    95,   96,   97,   98,   99,  100,  101,  102,  103,  104,  105,  106,  107,  108,  109,  110,
86   111,  112,  113,  114,  115,  116,  117,  118,  119,  120,  121,  122,  123,  124,  125,  126,
87   161,  162,  163,  166,  167,  168,  169,  170,  172,  175,  178,  179,  182,  183,  184,  191,
88   192,  193,  194,  195,  196,  197,  200,  204,  205,  206,  207,  208,  209,  210,  211,  212,
89   213,  214,  215,  216,  217,  218,  219,  220,  221,  222,  223,  224,  225,  226,  227,  228,
90   229,  230,  231,  232,  233,  234,  235,  236,  237,  238,  239,  240,  241,  242,  243,  244,
91   245,  246,  247,  248,  249,  250,  251,  252,  253,  254,  255
92 };
93
94 /* glyph ID to SID */
95 static const uint16_t expert_charset_to_sid [] =
96 {
97     0,    1,  229,  230,  231,  232,  233,  234,  235,  236,  237,  238,   13,   14,   15,   99,
98   239,  240,  241,  242,  243,  244,  245,  246,  247,  248,   27,   28,  249,  250,  251,  252,
99   253,  254,  255,  256,  257,  258,  259,  260,  261,  262,  263,  264,  265,  266,  109,  110,
100   267,  268,  269,  270,  271,  272,  273,  274,  275,  276,  277,  278,  279,  280,  281,  282,
101   283,  284,  285,  286,  287,  288,  289,  290,  291,  292,  293,  294,  295,  296,  297,  298,
102   299,  300,  301,  302,  303,  304,  305,  306,  307,  308,  309,  310,  311,  312,  313,  314,
103   315,  316,  317,  318,  158,  155,  163,  319,  320,  321,  322,  323,  324,  325,  326,  150,
104   164,  169,  327,  328,  329,  330,  331,  332,  333,  334,  335,  336,  337,  338,  339,  340,
105   341,  342,  343,  344,  345,  346,  347,  348,  349,  350,  351,  352,  353,  354,  355,  356,
106   357,  358,  359,  360,  361,  362,  363,  364,  365,  366,  367,  368,  369,  370,  371,  372,
107   373,  374,  375,  376,  377,  378
108 };
109
110 /* glyph ID to SID */
111 static const uint16_t expert_subset_charset_to_sid [] =
112 {
113     0,    1,  231,  232,  235,  236,  237,  238,   13,   14,   15,   99,  239,  240,  241,  242,
114   243,  244,  245,  246,  247,  248,   27,   28,  249,  250,  251,  253,  254,  255,  256,  257,
115   258,  259,  260,  261,  262,  263,  264,  265,  266,  109,  110,  267,  268,  269,  270,  272,
116   300,  301,  302,  305,  314,  315,  158,  155,  163,  320,  321,  322,  323,  324,  325,  326,
117   150,  164,  169,  327,  328,  329,  330,  331,  332,  333,  334,  335,  336,  337,  338,  339,
118   340,  341,  342,  343,  344,  345,  346
119 };
120
121 /* SID to glyph ID */
122 static const sid_to_gid_t expert_charset_sid_to_gid [] =
123 {
124     { 1, 1 },     { 13, 12 },   { 14, 13 },   { 15, 14 },
125     { 27, 26 },   { 28, 27 },   { 99, 15 },   { 109, 46 },
126     { 110, 47 },  { 150, 111 }, { 155, 101 }, { 158, 100 },
127     { 163, 102 }, { 164, 112 }, { 169, 113 }, { 229, 2 },
128     { 230, 3 },   { 231, 4 },   { 232, 5 },   { 233, 6 },
129     { 234, 7 },   { 235, 8 },   { 236, 9 },   { 237, 10 },
130     { 238, 11 },  { 239, 16 },  { 240, 17 },  { 241, 18 },
131     { 242, 19 },  { 243, 20 },  { 244, 21 },  { 245, 22 },
132     { 246, 23 },  { 247, 24 },  { 248, 25 },  { 249, 28 },
133     { 250, 29 },  { 251, 30 },  { 252, 31 },  { 253, 32 },
134     { 254, 33 },  { 255, 34 },  { 256, 35 },  { 257, 36 },
135     { 258, 37 },  { 259, 38 },  { 260, 39 },  { 261, 40 },
136     { 262, 41 },  { 263, 42 },  { 264, 43 },  { 265, 44 },
137     { 266, 45 },  { 267, 48 },  { 268, 49 },  { 269, 50 },
138     { 270, 51 },  { 271, 52 },  { 272, 53 },  { 273, 54 },
139     { 274, 55 },  { 275, 56 },  { 276, 57 },  { 277, 58 },
140     { 278, 59 },  { 279, 60 },  { 280, 61 },  { 281, 62 },
141     { 282, 63 },  { 283, 64 },  { 284, 65 },  { 285, 66 },
142     { 286, 67 },  { 287, 68 },  { 288, 69 },  { 289, 70 },
143     { 290, 71 },  { 291, 72 },  { 292, 73 },  { 293, 74 },
144     { 294, 75 },  { 295, 76 },  { 296, 77 },  { 297, 78 },
145     { 298, 79 },  { 299, 80 },  { 300, 81 },  { 301, 82 },
146     { 302, 83 },  { 303, 84 },  { 304, 85 },  { 305, 86 },
147     { 306, 87 },  { 307, 88 },  { 308, 89 },  { 309, 90 },
148     { 310, 91 },  { 311, 92 },  { 312, 93 },  { 313, 94 },
149     { 314, 95 },  { 315, 96 },  { 316, 97 },  { 317, 98 },
150     { 318, 99 },  { 319, 103 }, { 320, 104 }, { 321, 105 },
151     { 322, 106 }, { 323, 107 }, { 324, 108 }, { 325, 109 },
152     { 326, 110 }, { 327, 114 }, { 328, 115 }, { 329, 116 },
153     { 330, 117 }, { 331, 118 }, { 332, 119 }, { 333, 120 },
154     { 334, 121 }, { 335, 122 }, { 336, 123 }, { 337, 124 },
155     { 338, 125 }, { 339, 126 }, { 340, 127 }, { 341, 128 },
156     { 342, 129 }, { 343, 130 }, { 344, 131 }, { 345, 132 },
157     { 346, 133 }, { 347, 134 }, { 348, 135 }, { 349, 136 },
158     { 350, 137 }, { 351, 138 }, { 352, 139 }, { 353, 140 },
159     { 354, 141 }, { 355, 142 }, { 356, 143 }, { 357, 144 },
160     { 358, 145 }, { 359, 146 }, { 360, 147 }, { 361, 148 },
161     { 362, 149 }, { 363, 150 }, { 364, 151 }, { 365, 152 },
162     { 366, 153 }, { 367, 154 }, { 368, 155 }, { 369, 156 },
163     { 370, 157 }, { 371, 158 }, { 372, 159 }, { 373, 160 },
164     { 374, 161 }, { 375, 162 }, { 376, 163 }, { 377, 164 },
165     { 378, 165 }
166 };
167
168 /* SID to glyph ID */
169 static const sid_to_gid_t expert_subset_charset_sid_to_gid [] =
170 {
171   { 1, 1 },       { 13, 8 },      { 14, 9 },      { 15, 10 },
172   { 27, 22 },     { 28, 23 },     { 99, 11 },     { 109, 41 },
173   { 110, 42 },    { 150, 64 },    { 155, 55 },    { 158, 54 },
174   { 163, 56 },    { 164, 65 },    { 169, 66 },    { 231, 2 },
175   { 232, 3 },     { 235, 4 },     { 236, 5 },     { 237, 6 },
176   { 238, 7 },     { 239, 12 },    { 240, 13 },    { 241, 14 },
177   { 242, 15 },    { 243, 16 },    { 244, 17 },    { 245, 18 },
178   { 246, 19 },    { 247, 20 },    { 248, 21 },    { 249, 24 },
179   { 250, 25 },    { 251, 26 },    { 253, 27 },    { 254, 28 },
180   { 255, 29 },    { 256, 30 },    { 257, 31 },    { 258, 32 },
181   { 259, 33 },    { 260, 34 },    { 261, 35 },    { 262, 36 },
182   { 263, 37 },    { 264, 38 },    { 265, 39 },    { 266, 40 },
183   { 267, 43 },    { 268, 44 },    { 269, 45 },    { 270, 46 },
184   { 272, 47 },    { 300, 48 },    { 301, 49 },    { 302, 50 },
185   { 305, 51 },    { 314, 52 },    { 315, 53 },    { 320, 57 },
186   { 321, 58 },    { 322, 59 },    { 323, 60 },    { 324, 61 },
187   { 325, 62 },    { 326, 63 },    { 327, 67 },    { 328, 68 },
188   { 329, 69 },    { 330, 70 },    { 331, 71 },    { 332, 72 },
189   { 333, 73 },    { 334, 74 },    { 335, 75 },    { 336, 76 },
190   { 337, 77 },    { 338, 78 },    { 339, 79 },    { 340, 80 },
191   { 341, 81 },    { 342, 82 },    { 343, 83 },    { 344, 84 },
192   { 345, 85 },    { 346, 86 }
193 };
194
195 /* code to SID */
196 static const uint8_t standard_encoding_to_sid [] =
197 {
198     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
199     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
200     1,    2,    3,    4,    5,    6,    7,    8,    9,   10,   11,   12,   13,   14,   15,   16,
201     17,  18,   19,   20,   21,   22,   23,   24,   25,   26,   27,   28,   29,   30,   31,   32,
202     33,  34,   35,   36,   37,   38,   39,   40,   41,   42,   43,   44,   45,   46,   47,   48,
203     49,  50,   51,   52,   53,   54,   55,   56,   57,   58,   59,   60,   61,   62,   63,   64,
204     65,  66,   67,   68,   69,   70,   71,   72,   73,   74,   75,   76,   77,   78,   79,   80,
205     81,  82,   83,   84,   85,   86,   87,   88,   89,   90,   91,   92,   93,   94,   95,    0,
206     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
207     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
208     0,   96,   97,   98,   99,  100,  101,  102,  103,  104,  105,  106,  107,  108,  109,  110,
209     0,  111,  112,  113,  114,    0,  115,  116,  117,  118,  119,  120,  121,  122,    0,  123,
210     0,  124,  125,  126,  127,  128,  129,  130,  131,    0,  132,  133,    0,  134,  135,  136,
211   137,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
212     0,   138,   0,  139,    0,    0,    0,    0,  140,  141,  142,  143,    0,    0,    0,    0,
213     0,   144,   0,    0,    0,  145,    0,    0,  146,  147,  148,  149,    0,    0,    0,    0
214 };
215
216 hb_codepoint_t OT::cff1::lookup_standard_encoding_for_code (hb_codepoint_t sid)
217 {
218   if (sid < ARRAY_LENGTH (standard_encoding_to_code))
219     return (hb_codepoint_t)standard_encoding_to_code[sid];
220   else
221     return 0;
222 }
223
224 hb_codepoint_t OT::cff1::lookup_expert_encoding_for_code (hb_codepoint_t sid)
225 {
226   if (sid < ARRAY_LENGTH (expert_encoding_to_code))
227     return (hb_codepoint_t)expert_encoding_to_code[sid];
228   else
229     return 0;
230 }
231
232 hb_codepoint_t OT::cff1::lookup_expert_charset_for_sid (hb_codepoint_t glyph)
233 {
234   if (glyph < ARRAY_LENGTH (expert_charset_to_sid))
235     return (hb_codepoint_t)expert_charset_to_sid[glyph];
236   else
237     return 0;
238 }
239
240 hb_codepoint_t OT::cff1::lookup_expert_subset_charset_for_sid (hb_codepoint_t glyph)
241 {
242   if (glyph < ARRAY_LENGTH (expert_subset_charset_to_sid))
243     return (hb_codepoint_t)expert_subset_charset_to_sid[glyph];
244   else
245     return 0;
246 }
247
248 hb_codepoint_t OT::cff1::lookup_expert_charset_for_glyph (hb_codepoint_t sid)
249 {
250   const auto *pair = hb_sorted_array (expert_charset_sid_to_gid).bsearch (sid);
251   return pair ? pair->gid : 0;
252 }
253
254 hb_codepoint_t OT::cff1::lookup_expert_subset_charset_for_glyph (hb_codepoint_t sid)
255 {
256   const auto *pair = hb_sorted_array (expert_subset_charset_sid_to_gid).bsearch (sid);
257   return pair ? pair->gid : 0;
258 }
259
260 hb_codepoint_t OT::cff1::lookup_standard_encoding_for_sid (hb_codepoint_t code)
261 {
262   if (code < ARRAY_LENGTH (standard_encoding_to_sid))
263     return (hb_codepoint_t)standard_encoding_to_sid[code];
264   else
265     return CFF_UNDEF_SID;
266 }
267
268 struct bounds_t
269 {
270   void init ()
271   {
272     min.set_int (INT_MAX, INT_MAX);
273     max.set_int (INT_MIN, INT_MIN);
274   }
275
276   void update (const point_t &pt)
277   {
278     if (pt.x < min.x) min.x = pt.x;
279     if (pt.x > max.x) max.x = pt.x;
280     if (pt.y < min.y) min.y = pt.y;
281     if (pt.y > max.y) max.y = pt.y;
282   }
283
284   void merge (const bounds_t &b)
285   {
286     if (empty ())
287       *this = b;
288     else if (!b.empty ())
289     {
290       if (b.min.x < min.x) min.x = b.min.x;
291       if (b.max.x > max.x) max.x = b.max.x;
292       if (b.min.y < min.y) min.y = b.min.y;
293       if (b.max.y > max.y) max.y = b.max.y;
294     }
295   }
296
297   void offset (const point_t &delta)
298   {
299     if (!empty ())
300     {
301       min.move (delta);
302       max.move (delta);
303     }
304   }
305
306   bool empty () const { return (min.x >= max.x) || (min.y >= max.y); }
307
308   point_t min;
309   point_t max;
310 };
311
312 struct cff1_extents_param_t
313 {
314   void init (const OT::cff1::accelerator_t *_cff)
315   {
316     path_open = false;
317     cff = _cff;
318     bounds.init ();
319   }
320
321   void start_path   ()       { path_open = true; }
322   void end_path     ()       { path_open = false; }
323   bool is_path_open () const { return path_open; }
324
325   bool path_open;
326   bounds_t bounds;
327
328   const OT::cff1::accelerator_t *cff;
329 };
330
331 struct cff1_path_procs_extents_t : path_procs_t<cff1_path_procs_extents_t, cff1_cs_interp_env_t, cff1_extents_param_t>
332 {
333   static void moveto (cff1_cs_interp_env_t &env, cff1_extents_param_t& param, const point_t &pt)
334   {
335     param.end_path ();
336     env.moveto (pt);
337   }
338
339   static void line (cff1_cs_interp_env_t &env, cff1_extents_param_t& param, const point_t &pt1)
340   {
341     if (!param.is_path_open ())
342     {
343       param.start_path ();
344       param.bounds.update (env.get_pt ());
345     }
346     env.moveto (pt1);
347     param.bounds.update (env.get_pt ());
348   }
349
350   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)
351   {
352     if (!param.is_path_open ())
353     {
354       param.start_path ();
355       param.bounds.update (env.get_pt ());
356     }
357     /* include control points */
358     param.bounds.update (pt1);
359     param.bounds.update (pt2);
360     env.moveto (pt3);
361     param.bounds.update (env.get_pt ());
362   }
363 };
364
365 static bool _get_bounds (const OT::cff1::accelerator_t *cff, hb_codepoint_t glyph, bounds_t &bounds, bool in_seac=false);
366
367 struct cff1_cs_opset_extents_t : cff1_cs_opset_t<cff1_cs_opset_extents_t, cff1_extents_param_t, cff1_path_procs_extents_t>
368 {
369   static void process_seac (cff1_cs_interp_env_t &env, cff1_extents_param_t& param)
370   {
371     unsigned int  n = env.argStack.get_count ();
372     point_t delta;
373     delta.x = env.argStack[n-4];
374     delta.y = env.argStack[n-3];
375     hb_codepoint_t base = param.cff->std_code_to_glyph (env.argStack[n-2].to_int ());
376     hb_codepoint_t accent = param.cff->std_code_to_glyph (env.argStack[n-1].to_int ());
377
378     bounds_t  base_bounds, accent_bounds;
379     if (likely (!env.in_seac && base && accent
380                && _get_bounds (param.cff, base, base_bounds, true)
381                && _get_bounds (param.cff, accent, accent_bounds, true)))
382     {
383       param.bounds.merge (base_bounds);
384       accent_bounds.offset (delta);
385       param.bounds.merge (accent_bounds);
386     }
387     else
388       env.set_error ();
389   }
390 };
391
392 bool _get_bounds (const OT::cff1::accelerator_t *cff, hb_codepoint_t glyph, bounds_t &bounds, bool in_seac)
393 {
394   bounds.init ();
395   if (unlikely (!cff->is_valid () || (glyph >= cff->num_glyphs))) return false;
396
397   unsigned int fd = cff->fdSelect->get_fd (glyph);
398   cff1_cs_interpreter_t<cff1_cs_opset_extents_t, cff1_extents_param_t> interp;
399   const byte_str_t str = (*cff->charStrings)[glyph];
400   interp.env.init (str, *cff, fd);
401   interp.env.set_in_seac (in_seac);
402   cff1_extents_param_t  param;
403   param.init (cff);
404   if (unlikely (!interp.interpret (param))) return false;
405   bounds = param.bounds;
406   return true;
407 }
408
409 bool OT::cff1::accelerator_t::get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const
410 {
411 #ifdef HB_NO_OT_FONT_CFF
412   /* XXX Remove check when this code moves to .hh file. */
413   return true;
414 #endif
415
416   bounds_t bounds;
417
418   if (!_get_bounds (this, glyph, bounds))
419     return false;
420
421   if (bounds.min.x >= bounds.max.x)
422   {
423     extents->width = 0;
424     extents->x_bearing = 0;
425   }
426   else
427   {
428     extents->x_bearing = font->em_scalef_x (bounds.min.x.to_real ());
429     extents->width = font->em_scalef_x (bounds.max.x.to_real () - bounds.min.x.to_real ());
430   }
431   if (bounds.min.y >= bounds.max.y)
432   {
433     extents->height = 0;
434     extents->y_bearing = 0;
435   }
436   else
437   {
438     extents->y_bearing = font->em_scalef_y (bounds.max.y.to_real ());
439     extents->height = font->em_scalef_y (bounds.min.y.to_real () - bounds.max.y.to_real ());
440   }
441
442   return true;
443 }
444
445 #ifdef HB_EXPERIMENTAL_API
446 struct cff1_path_param_t
447 {
448   cff1_path_param_t (const OT::cff1::accelerator_t *cff_, hb_font_t *font_,
449                      draw_helper_t &draw_helper_, point_t *delta_)
450   {
451     draw_helper = &draw_helper_;
452     cff = cff_;
453     font = font_;
454     delta = delta_;
455   }
456
457   void move_to (const point_t &p)
458   {
459     point_t point = p;
460     if (delta) point.move (*delta);
461     draw_helper->move_to (font->em_scalef_x (point.x.to_real ()), font->em_scalef_y (point.y.to_real ()));
462   }
463
464   void line_to (const point_t &p)
465   {
466     point_t point = p;
467     if (delta) point.move (*delta);
468     draw_helper->line_to (font->em_scalef_x (point.x.to_real ()), font->em_scalef_y (point.y.to_real ()));
469   }
470
471   void cubic_to (const point_t &p1, const point_t &p2, const point_t &p3)
472   {
473     point_t point1 = p1, point2 = p2, point3 = p3;
474     if (delta)
475     {
476       point1.move (*delta);
477       point2.move (*delta);
478       point3.move (*delta);
479     }
480     draw_helper->cubic_to (font->em_scalef_x (point1.x.to_real ()), font->em_scalef_y (point1.y.to_real ()),
481                            font->em_scalef_x (point2.x.to_real ()), font->em_scalef_y (point2.y.to_real ()),
482                            font->em_scalef_x (point3.x.to_real ()), font->em_scalef_y (point3.y.to_real ()));
483   }
484
485   void end_path () { draw_helper->end_path (); }
486
487   hb_font_t *font;
488   draw_helper_t *draw_helper;
489   point_t *delta;
490
491   const OT::cff1::accelerator_t *cff;
492 };
493
494 struct cff1_path_procs_path_t : path_procs_t<cff1_path_procs_path_t, cff1_cs_interp_env_t, cff1_path_param_t>
495 {
496   static void moveto (cff1_cs_interp_env_t &env, cff1_path_param_t& param, const point_t &pt)
497   {
498     param.move_to (pt);
499     env.moveto (pt);
500   }
501
502   static void line (cff1_cs_interp_env_t &env, cff1_path_param_t &param, const point_t &pt1)
503   {
504     param.line_to (pt1);
505     env.moveto (pt1);
506   }
507
508   static void curve (cff1_cs_interp_env_t &env, cff1_path_param_t &param, const point_t &pt1, const point_t &pt2, const point_t &pt3)
509   {
510     param.cubic_to (pt1, pt2, pt3);
511     env.moveto (pt3);
512   }
513 };
514
515 static bool _get_path (const OT::cff1::accelerator_t *cff, hb_font_t *font, hb_codepoint_t glyph,
516                        draw_helper_t &draw_helper, bool in_seac = false, point_t *delta = nullptr);
517
518 struct cff1_cs_opset_path_t : cff1_cs_opset_t<cff1_cs_opset_path_t, cff1_path_param_t, cff1_path_procs_path_t>
519 {
520   static void process_seac (cff1_cs_interp_env_t &env, cff1_path_param_t& param)
521   {
522     /* End previous path */
523     param.end_path ();
524
525     unsigned int n = env.argStack.get_count ();
526     point_t delta;
527     delta.x = env.argStack[n-4];
528     delta.y = env.argStack[n-3];
529     hb_codepoint_t base = param.cff->std_code_to_glyph (env.argStack[n-2].to_int ());
530     hb_codepoint_t accent = param.cff->std_code_to_glyph (env.argStack[n-1].to_int ());
531
532     if (unlikely (!(!env.in_seac && base && accent
533                     && _get_path (param.cff, param.font, base, *param.draw_helper, true)
534                     && _get_path (param.cff, param.font, accent, *param.draw_helper, true, &delta))))
535       env.set_error ();
536   }
537 };
538
539 bool _get_path (const OT::cff1::accelerator_t *cff, hb_font_t *font, hb_codepoint_t glyph,
540                 draw_helper_t &draw_helper, bool in_seac, point_t *delta)
541 {
542   if (unlikely (!cff->is_valid () || (glyph >= cff->num_glyphs))) return false;
543
544   unsigned int fd = cff->fdSelect->get_fd (glyph);
545   cff1_cs_interpreter_t<cff1_cs_opset_path_t, cff1_path_param_t> interp;
546   const byte_str_t str = (*cff->charStrings)[glyph];
547   interp.env.init (str, *cff, fd);
548   interp.env.set_in_seac (in_seac);
549   cff1_path_param_t param (cff, font, draw_helper, delta);
550   if (unlikely (!interp.interpret (param))) return false;
551
552   /* Let's end the path specially since it is called inside seac also */
553   param.end_path ();
554
555   return true;
556 }
557
558 bool OT::cff1::accelerator_t::get_path (hb_font_t *font, hb_codepoint_t glyph, draw_helper_t &draw_helper) const
559 {
560 #ifdef HB_NO_OT_FONT_CFF
561   /* XXX Remove check when this code moves to .hh file. */
562   return true;
563 #endif
564
565   return _get_path (this, font, glyph, draw_helper);
566 }
567 #endif
568
569 struct get_seac_param_t
570 {
571   void init (const OT::cff1::accelerator_t *_cff)
572   {
573     cff = _cff;
574     base = 0;
575     accent = 0;
576   }
577
578   bool has_seac () const { return base && accent; }
579
580   const OT::cff1::accelerator_t *cff;
581   hb_codepoint_t  base;
582   hb_codepoint_t  accent;
583 };
584
585 struct cff1_cs_opset_seac_t : cff1_cs_opset_t<cff1_cs_opset_seac_t, get_seac_param_t>
586 {
587   static void process_seac (cff1_cs_interp_env_t &env, get_seac_param_t& param)
588   {
589     unsigned int  n = env.argStack.get_count ();
590     hb_codepoint_t  base_char = (hb_codepoint_t)env.argStack[n-2].to_int ();
591     hb_codepoint_t  accent_char = (hb_codepoint_t)env.argStack[n-1].to_int ();
592
593     param.base = param.cff->std_code_to_glyph (base_char);
594     param.accent = param.cff->std_code_to_glyph (accent_char);
595   }
596 };
597
598 bool OT::cff1::accelerator_t::get_seac_components (hb_codepoint_t glyph, hb_codepoint_t *base, hb_codepoint_t *accent) const
599 {
600   if (unlikely (!is_valid () || (glyph >= num_glyphs))) return false;
601
602   unsigned int fd = fdSelect->get_fd (glyph);
603   cff1_cs_interpreter_t<cff1_cs_opset_seac_t, get_seac_param_t> interp;
604   const byte_str_t str = (*charStrings)[glyph];
605   interp.env.init (str, *this, fd);
606   get_seac_param_t  param;
607   param.init (this);
608   if (unlikely (!interp.interpret (param))) return false;
609
610   if (param.has_seac ())
611   {
612     *base = param.base;
613     *accent = param.accent;
614     return true;
615   }
616   return false;
617 }
618
619
620 #endif