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 
cmpsid_to_gid_t43   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 
lookup_standard_encoding_for_code(hb_codepoint_t sid)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 
lookup_expert_encoding_for_code(hb_codepoint_t sid)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 
lookup_expert_charset_for_sid(hb_codepoint_t glyph)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 
lookup_expert_subset_charset_for_sid(hb_codepoint_t glyph)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 
lookup_expert_charset_for_glyph(hb_codepoint_t sid)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 
lookup_expert_subset_charset_for_glyph(hb_codepoint_t sid)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 
lookup_standard_encoding_for_sid(hb_codepoint_t code)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 {
initbounds_t270   void init ()
271   {
272     min.set_int (INT_MAX, INT_MAX);
273     max.set_int (INT_MIN, INT_MIN);
274   }
275 
updatebounds_t276   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 
mergebounds_t284   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 
offsetbounds_t297   void offset (const point_t &delta)
298   {
299     if (!empty ())
300     {
301       min.move (delta);
302       max.move (delta);
303     }
304   }
305 
emptybounds_t306   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 {
initcff1_extents_param_t314   void init (const OT::cff1::accelerator_t *_cff)
315   {
316     path_open = false;
317     cff = _cff;
318     bounds.init ();
319   }
320 
start_pathcff1_extents_param_t321   void start_path   ()       { path_open = true; }
end_pathcff1_extents_param_t322   void end_path     ()       { path_open = false; }
is_path_opencff1_extents_param_t323   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 {
movetocff1_path_procs_extents_t333   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 
linecff1_path_procs_extents_t339   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 
curvecff1_path_procs_extents_t350   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 {
process_seaccff1_cs_opset_extents_t369   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 
_get_bounds(const OT::cff1::accelerator_t * cff,hb_codepoint_t glyph,bounds_t & bounds,bool in_seac)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 
get_extents(hb_font_t * font,hb_codepoint_t glyph,hb_glyph_extents_t * extents) const409 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 ()) - extents->x_bearing;
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 ()) - extents->y_bearing;
440   }
441 
442   return true;
443 }
444 
445 #ifdef HB_EXPERIMENTAL_API
446 struct cff1_path_param_t
447 {
cff1_path_param_tcff1_path_param_t448   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 
move_tocff1_path_param_t457   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 
line_tocff1_path_param_t464   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 
cubic_tocff1_path_param_t471   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 
end_pathcff1_path_param_t485   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 {
movetocff1_path_procs_path_t496   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 
linecff1_path_procs_path_t502   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 
curvecff1_path_procs_path_t508   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 {
process_seaccff1_cs_opset_path_t520   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 
_get_path(const OT::cff1::accelerator_t * cff,hb_font_t * font,hb_codepoint_t glyph,draw_helper_t & draw_helper,bool in_seac,point_t * delta)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 
get_path(hb_font_t * font,hb_codepoint_t glyph,draw_helper_t & draw_helper) const558 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 {
initget_seac_param_t571   void init (const OT::cff1::accelerator_t *_cff)
572   {
573     cff = _cff;
574     base = 0;
575     accent = 0;
576   }
577 
has_seacget_seac_param_t578   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 {
process_seaccff1_cs_opset_seac_t587   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 
get_seac_components(hb_codepoint_t glyph,hb_codepoint_t * base,hb_codepoint_t * accent) const598 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
621