xref: /aosp_15_r20/external/harfbuzz_ng/src/hb-ot-cff1-table.cc (revision 2d1272b857b1f7575e6e246373e1cb218663db8a)
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 {
cff1_extents_param_tcff1_extents_param_t314   cff1_extents_param_t (const OT::cff1::accelerator_t *_cff) : cff (_cff)
315   {
316     bounds.init ();
317   }
318 
start_pathcff1_extents_param_t319   void start_path   ()       { path_open = true; }
end_pathcff1_extents_param_t320   void end_path     ()       { path_open = false; }
is_path_opencff1_extents_param_t321   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 {
movetocff1_path_procs_extents_t331   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 
linecff1_path_procs_extents_t337   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 
curvecff1_path_procs_extents_t348   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 {
process_seaccff1_cs_opset_extents_t367   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 
_get_bounds(const OT::cff1::accelerator_t * cff,hb_codepoint_t glyph,bounds_t & bounds,bool in_seac)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 
get_extents(hb_font_t * font,hb_codepoint_t glyph,hb_glyph_extents_t * extents) const406 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 {
cff1_path_param_tcff1_path_param_t446   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 
move_tocff1_path_param_t455   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 
line_tocff1_path_param_t462   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 
cubic_tocff1_path_param_t469   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 
end_pathcff1_path_param_t483   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 {
movetocff1_path_procs_path_t494   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 
linecff1_path_procs_path_t500   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 
curvecff1_path_procs_path_t506   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 {
process_seaccff1_cs_opset_path_t518   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 
_get_path(const OT::cff1::accelerator_t * cff,hb_font_t * font,hb_codepoint_t glyph,hb_draw_session_t & draw_session,bool in_seac,point_t * delta)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 
paint_glyph(hb_font_t * font,hb_codepoint_t glyph,hb_paint_funcs_t * funcs,void * data,hb_color_t foreground) const556 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 
get_path(hb_font_t * font,hb_codepoint_t glyph,hb_draw_session_t & draw_session) const565 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 {
get_seac_param_tget_seac_param_t577   get_seac_param_t (const OT::cff1::accelerator_subset_t *_cff) : cff (_cff) {}
578 
has_seacget_seac_param_t579   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 {
process_seaccff1_cs_opset_seac_t588   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 
get_seac_components(hb_codepoint_t glyph,hb_codepoint_t * base,hb_codepoint_t * accent) const599 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
621