Merge branch 'upstream' into tizen
[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   cff1_extents_param_t (const OT::cff1::accelerator_t *_cff) : cff (_cff)
315   {
316     bounds.init ();
317   }
318
319   void start_path   ()       { path_open = true; }
320   void end_path     ()       { path_open = false; }
321   bool is_path_open () const { return path_open; }
322
323   bool path_open = false;
324   bounds_t bounds;
325
326   const OT::cff1::accelerator_t *cff;
327 };
328
329 struct cff1_path_procs_extents_t : path_procs_t<cff1_path_procs_extents_t, cff1_cs_interp_env_t, cff1_extents_param_t>
330 {
331   static void moveto (cff1_cs_interp_env_t &env, cff1_extents_param_t& param, const point_t &pt)
332   {
333     param.end_path ();
334     env.moveto (pt);
335   }
336
337   static void line (cff1_cs_interp_env_t &env, cff1_extents_param_t& param, const point_t &pt1)
338   {
339     if (!param.is_path_open ())
340     {
341       param.start_path ();
342       param.bounds.update (env.get_pt ());
343     }
344     env.moveto (pt1);
345     param.bounds.update (env.get_pt ());
346   }
347
348   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)
349   {
350     if (!param.is_path_open ())
351     {
352       param.start_path ();
353       param.bounds.update (env.get_pt ());
354     }
355     /* include control points */
356     param.bounds.update (pt1);
357     param.bounds.update (pt2);
358     env.moveto (pt3);
359     param.bounds.update (env.get_pt ());
360   }
361 };
362
363 static bool _get_bounds (const OT::cff1::accelerator_t *cff, hb_codepoint_t glyph, bounds_t &bounds, bool in_seac=false);
364
365 struct cff1_cs_opset_extents_t : cff1_cs_opset_t<cff1_cs_opset_extents_t, cff1_extents_param_t, cff1_path_procs_extents_t>
366 {
367   static void process_seac (cff1_cs_interp_env_t &env, cff1_extents_param_t& param)
368   {
369     unsigned int  n = env.argStack.get_count ();
370     point_t delta;
371     delta.x = env.argStack[n-4];
372     delta.y = env.argStack[n-3];
373     hb_codepoint_t base = param.cff->std_code_to_glyph (env.argStack[n-2].to_int ());
374     hb_codepoint_t accent = param.cff->std_code_to_glyph (env.argStack[n-1].to_int ());
375
376     bounds_t  base_bounds, accent_bounds;
377     if (likely (!env.in_seac && base && accent
378                && _get_bounds (param.cff, base, base_bounds, true)
379                && _get_bounds (param.cff, accent, accent_bounds, true)))
380     {
381       param.bounds.merge (base_bounds);
382       accent_bounds.offset (delta);
383       param.bounds.merge (accent_bounds);
384     }
385     else
386       env.set_error ();
387   }
388 };
389
390 bool _get_bounds (const OT::cff1::accelerator_t *cff, hb_codepoint_t glyph, bounds_t &bounds, bool in_seac)
391 {
392   bounds.init ();
393   if (unlikely (!cff->is_valid () || (glyph >= cff->num_glyphs))) return false;
394
395   unsigned int fd = cff->fdSelect->get_fd (glyph);
396   const hb_ubytes_t str = (*cff->charStrings)[glyph];
397   cff1_cs_interp_env_t env (str, *cff, fd);
398   env.set_in_seac (in_seac);
399   cff1_cs_interpreter_t<cff1_cs_opset_extents_t, cff1_extents_param_t> interp (env);
400   cff1_extents_param_t param (cff);
401   if (unlikely (!interp.interpret (param))) return false;
402   bounds = param.bounds;
403   return true;
404 }
405
406 bool OT::cff1::accelerator_t::get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const
407 {
408 #ifdef HB_NO_OT_FONT_CFF
409   /* XXX Remove check when this code moves to .hh file. */
410   return true;
411 #endif
412
413   bounds_t bounds;
414
415   if (!_get_bounds (this, glyph, bounds))
416     return false;
417
418   if (bounds.min.x >= bounds.max.x)
419   {
420     extents->width = 0;
421     extents->x_bearing = 0;
422   }
423   else
424   {
425     extents->x_bearing = roundf (bounds.min.x.to_real ());
426     extents->width = roundf (bounds.max.x.to_real () - extents->x_bearing);
427   }
428   if (bounds.min.y >= bounds.max.y)
429   {
430     extents->height = 0;
431     extents->y_bearing = 0;
432   }
433   else
434   {
435     extents->y_bearing = roundf (bounds.max.y.to_real ());
436     extents->height = roundf (bounds.min.y.to_real () - extents->y_bearing);
437   }
438
439   font->scale_glyph_extents (extents);
440
441   return true;
442 }
443
444 struct cff1_path_param_t
445 {
446   cff1_path_param_t (const OT::cff1::accelerator_t *cff_, hb_font_t *font_,
447                      hb_draw_session_t &draw_session_, point_t *delta_)
448   {
449     draw_session = &draw_session_;
450     cff = cff_;
451     font = font_;
452     delta = delta_;
453   }
454
455   void move_to (const point_t &p)
456   {
457     point_t point = p;
458     if (delta) point.move (*delta);
459     draw_session->move_to (font->em_fscalef_x (point.x.to_real ()), font->em_fscalef_y (point.y.to_real ()));
460   }
461
462   void line_to (const point_t &p)
463   {
464     point_t point = p;
465     if (delta) point.move (*delta);
466     draw_session->line_to (font->em_fscalef_x (point.x.to_real ()), font->em_fscalef_y (point.y.to_real ()));
467   }
468
469   void cubic_to (const point_t &p1, const point_t &p2, const point_t &p3)
470   {
471     point_t point1 = p1, point2 = p2, point3 = p3;
472     if (delta)
473     {
474       point1.move (*delta);
475       point2.move (*delta);
476       point3.move (*delta);
477     }
478     draw_session->cubic_to (font->em_fscalef_x (point1.x.to_real ()), font->em_fscalef_y (point1.y.to_real ()),
479                            font->em_fscalef_x (point2.x.to_real ()), font->em_fscalef_y (point2.y.to_real ()),
480                            font->em_fscalef_x (point3.x.to_real ()), font->em_fscalef_y (point3.y.to_real ()));
481   }
482
483   void end_path () { draw_session->close_path (); }
484
485   hb_font_t *font;
486   hb_draw_session_t *draw_session;
487   point_t *delta;
488
489   const OT::cff1::accelerator_t *cff;
490 };
491
492 struct cff1_path_procs_path_t : path_procs_t<cff1_path_procs_path_t, cff1_cs_interp_env_t, cff1_path_param_t>
493 {
494   static void moveto (cff1_cs_interp_env_t &env, cff1_path_param_t& param, const point_t &pt)
495   {
496     param.move_to (pt);
497     env.moveto (pt);
498   }
499
500   static void line (cff1_cs_interp_env_t &env, cff1_path_param_t &param, const point_t &pt1)
501   {
502     param.line_to (pt1);
503     env.moveto (pt1);
504   }
505
506   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)
507   {
508     param.cubic_to (pt1, pt2, pt3);
509     env.moveto (pt3);
510   }
511 };
512
513 static bool _get_path (const OT::cff1::accelerator_t *cff, hb_font_t *font, hb_codepoint_t glyph,
514                        hb_draw_session_t &draw_session, bool in_seac = false, point_t *delta = nullptr);
515
516 struct cff1_cs_opset_path_t : cff1_cs_opset_t<cff1_cs_opset_path_t, cff1_path_param_t, cff1_path_procs_path_t>
517 {
518   static void process_seac (cff1_cs_interp_env_t &env, cff1_path_param_t& param)
519   {
520     /* End previous path */
521     param.end_path ();
522
523     unsigned int n = env.argStack.get_count ();
524     point_t delta;
525     delta.x = env.argStack[n-4];
526     delta.y = env.argStack[n-3];
527     hb_codepoint_t base = param.cff->std_code_to_glyph (env.argStack[n-2].to_int ());
528     hb_codepoint_t accent = param.cff->std_code_to_glyph (env.argStack[n-1].to_int ());
529
530     if (unlikely (!(!env.in_seac && base && accent
531                     && _get_path (param.cff, param.font, base, *param.draw_session, true)
532                     && _get_path (param.cff, param.font, accent, *param.draw_session, true, &delta))))
533       env.set_error ();
534   }
535 };
536
537 bool _get_path (const OT::cff1::accelerator_t *cff, hb_font_t *font, hb_codepoint_t glyph,
538                 hb_draw_session_t &draw_session, bool in_seac, point_t *delta)
539 {
540   if (unlikely (!cff->is_valid () || (glyph >= cff->num_glyphs))) return false;
541
542   unsigned int fd = cff->fdSelect->get_fd (glyph);
543   const hb_ubytes_t str = (*cff->charStrings)[glyph];
544   cff1_cs_interp_env_t env (str, *cff, fd);
545   env.set_in_seac (in_seac);
546   cff1_cs_interpreter_t<cff1_cs_opset_path_t, cff1_path_param_t> interp (env);
547   cff1_path_param_t param (cff, font, draw_session, delta);
548   if (unlikely (!interp.interpret (param))) return false;
549
550   /* Let's end the path specially since it is called inside seac also */
551   param.end_path ();
552
553   return true;
554 }
555
556 bool OT::cff1::accelerator_t::paint_glyph (hb_font_t *font, hb_codepoint_t glyph, hb_paint_funcs_t *funcs, void *data, hb_color_t foreground) const
557 {
558   funcs->push_clip_glyph (data, glyph, font);
559   funcs->color (data, true, foreground);
560   funcs->pop_clip (data);
561
562   return true;
563 }
564
565 bool OT::cff1::accelerator_t::get_path (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session) const
566 {
567 #ifdef HB_NO_OT_FONT_CFF
568   /* XXX Remove check when this code moves to .hh file. */
569   return true;
570 #endif
571
572   return _get_path (this, font, glyph, draw_session);
573 }
574
575 struct get_seac_param_t
576 {
577   get_seac_param_t (const OT::cff1::accelerator_subset_t *_cff) : cff (_cff) {}
578
579   bool has_seac () const { return base && accent; }
580
581   const OT::cff1::accelerator_subset_t *cff;
582   hb_codepoint_t  base = 0;
583   hb_codepoint_t  accent = 0;
584 };
585
586 struct cff1_cs_opset_seac_t : cff1_cs_opset_t<cff1_cs_opset_seac_t, get_seac_param_t>
587 {
588   static void process_seac (cff1_cs_interp_env_t &env, get_seac_param_t& param)
589   {
590     unsigned int  n = env.argStack.get_count ();
591     hb_codepoint_t  base_char = (hb_codepoint_t)env.argStack[n-2].to_int ();
592     hb_codepoint_t  accent_char = (hb_codepoint_t)env.argStack[n-1].to_int ();
593
594     param.base = param.cff->std_code_to_glyph (base_char);
595     param.accent = param.cff->std_code_to_glyph (accent_char);
596   }
597 };
598
599 bool OT::cff1::accelerator_subset_t::get_seac_components (hb_codepoint_t glyph, hb_codepoint_t *base, hb_codepoint_t *accent) const
600 {
601   if (unlikely (!is_valid () || (glyph >= num_glyphs))) return false;
602
603   unsigned int fd = fdSelect->get_fd (glyph);
604   const hb_ubytes_t str = (*charStrings)[glyph];
605   cff1_cs_interp_env_t env (str, *this, fd);
606   cff1_cs_interpreter_t<cff1_cs_opset_seac_t, get_seac_param_t> interp (env);
607   get_seac_param_t  param (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