Bug 1883518 - Remove a bunch of unused ServoBindings.toml entries. r=firefox-style...
[gecko.git] / gfx / harfbuzz / src / hb-ot-cff1-table.cc
blob66df28aae1df9667ba62d93e589c8fe902ba659d
1 /*
2 * Copyright © 2018 Adobe Inc.
4 * This is part of HarfBuzz, a text shaping library.
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.
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.
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.
24 * Adobe Author(s): Michiharu Ariza
27 #include "hb.hh"
29 #ifndef HB_NO_CFF
31 #include "hb-draw.hh"
32 #include "hb-algs.hh"
33 #include "hb-ot-cff1-table.hh"
34 #include "hb-cff1-interp-cs.hh"
36 using namespace CFF;
38 struct sid_to_gid_t
40 uint16_t sid;
41 uint8_t gid;
43 int cmp (uint16_t a) const
45 if (a == sid) return 0;
46 return (a < sid) ? -1 : 1;
50 /* SID to code */
51 static const uint8_t standard_encoding_to_code [] =
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
65 /* SID to code */
66 static const uint8_t expert_encoding_to_code [] =
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
94 /* glyph ID to SID */
95 static const uint16_t expert_charset_to_sid [] =
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
110 /* glyph ID to SID */
111 static const uint16_t expert_subset_charset_to_sid [] =
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
121 /* SID to glyph ID */
122 static const sid_to_gid_t expert_charset_sid_to_gid [] =
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 }
168 /* SID to glyph ID */
169 static const sid_to_gid_t expert_subset_charset_sid_to_gid [] =
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 }
195 /* code to SID */
196 static const uint8_t standard_encoding_to_sid [] =
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
216 hb_codepoint_t OT::cff1::lookup_standard_encoding_for_code (hb_codepoint_t sid)
218 if (sid < ARRAY_LENGTH (standard_encoding_to_code))
219 return (hb_codepoint_t)standard_encoding_to_code[sid];
220 else
221 return 0;
224 hb_codepoint_t OT::cff1::lookup_expert_encoding_for_code (hb_codepoint_t sid)
226 if (sid < ARRAY_LENGTH (expert_encoding_to_code))
227 return (hb_codepoint_t)expert_encoding_to_code[sid];
228 else
229 return 0;
232 hb_codepoint_t OT::cff1::lookup_expert_charset_for_sid (hb_codepoint_t glyph)
234 if (glyph < ARRAY_LENGTH (expert_charset_to_sid))
235 return (hb_codepoint_t)expert_charset_to_sid[glyph];
236 else
237 return 0;
240 hb_codepoint_t OT::cff1::lookup_expert_subset_charset_for_sid (hb_codepoint_t glyph)
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;
248 hb_codepoint_t OT::cff1::lookup_expert_charset_for_glyph (hb_codepoint_t sid)
250 const auto *pair = hb_sorted_array (expert_charset_sid_to_gid).bsearch (sid);
251 return pair ? pair->gid : 0;
254 hb_codepoint_t OT::cff1::lookup_expert_subset_charset_for_glyph (hb_codepoint_t sid)
256 const auto *pair = hb_sorted_array (expert_subset_charset_sid_to_gid).bsearch (sid);
257 return pair ? pair->gid : 0;
260 hb_codepoint_t OT::cff1::lookup_standard_encoding_for_sid (hb_codepoint_t code)
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;
268 struct bounds_t
270 void init ()
272 min.set_int (INT_MAX, INT_MAX);
273 max.set_int (INT_MIN, INT_MIN);
276 void update (const point_t &pt)
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;
284 void merge (const bounds_t &b)
286 if (empty ())
287 *this = b;
288 else if (!b.empty ())
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;
297 void offset (const point_t &delta)
299 if (!empty ())
301 min.move (delta);
302 max.move (delta);
306 bool empty () const { return (min.x >= max.x) || (min.y >= max.y); }
308 point_t min;
309 point_t max;
312 struct cff1_extents_param_t
314 cff1_extents_param_t (const OT::cff1::accelerator_t *_cff) : cff (_cff)
316 bounds.init ();
319 void start_path () { path_open = true; }
320 void end_path () { path_open = false; }
321 bool is_path_open () const { return path_open; }
323 bool path_open = false;
324 bounds_t bounds;
326 const OT::cff1::accelerator_t *cff;
329 struct cff1_path_procs_extents_t : path_procs_t<cff1_path_procs_extents_t, cff1_cs_interp_env_t, cff1_extents_param_t>
331 static void moveto (cff1_cs_interp_env_t &env, cff1_extents_param_t& param, const point_t &pt)
333 param.end_path ();
334 env.moveto (pt);
337 static void line (cff1_cs_interp_env_t &env, cff1_extents_param_t& param, const point_t &pt1)
339 if (!param.is_path_open ())
341 param.start_path ();
342 param.bounds.update (env.get_pt ());
344 env.moveto (pt1);
345 param.bounds.update (env.get_pt ());
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)
350 if (!param.is_path_open ())
352 param.start_path ();
353 param.bounds.update (env.get_pt ());
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 ());
363 static bool _get_bounds (const OT::cff1::accelerator_t *cff, hb_codepoint_t glyph, bounds_t &bounds, bool in_seac=false);
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>
367 static void process_seac (cff1_cs_interp_env_t &env, cff1_extents_param_t& param)
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 ());
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)))
381 param.bounds.merge (base_bounds);
382 accent_bounds.offset (delta);
383 param.bounds.merge (accent_bounds);
385 else
386 env.set_error ();
390 bool _get_bounds (const OT::cff1::accelerator_t *cff, hb_codepoint_t glyph, bounds_t &bounds, bool in_seac)
392 bounds.init ();
393 if (unlikely (!cff->is_valid () || (glyph >= cff->num_glyphs))) return false;
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;
406 bool OT::cff1::accelerator_t::get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const
408 #ifdef HB_NO_OT_FONT_CFF
409 /* XXX Remove check when this code moves to .hh file. */
410 return true;
411 #endif
413 bounds_t bounds;
415 if (!_get_bounds (this, glyph, bounds))
416 return false;
418 if (bounds.min.x >= bounds.max.x)
420 extents->width = 0;
421 extents->x_bearing = 0;
423 else
425 extents->x_bearing = roundf (bounds.min.x.to_real ());
426 extents->width = roundf (bounds.max.x.to_real () - extents->x_bearing);
428 if (bounds.min.y >= bounds.max.y)
430 extents->height = 0;
431 extents->y_bearing = 0;
433 else
435 extents->y_bearing = roundf (bounds.max.y.to_real ());
436 extents->height = roundf (bounds.min.y.to_real () - extents->y_bearing);
439 font->scale_glyph_extents (extents);
441 return true;
444 struct cff1_path_param_t
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_)
449 draw_session = &draw_session_;
450 cff = cff_;
451 font = font_;
452 delta = delta_;
455 void move_to (const point_t &p)
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 ()));
462 void line_to (const point_t &p)
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 ()));
469 void cubic_to (const point_t &p1, const point_t &p2, const point_t &p3)
471 point_t point1 = p1, point2 = p2, point3 = p3;
472 if (delta)
474 point1.move (*delta);
475 point2.move (*delta);
476 point3.move (*delta);
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 ()));
483 void end_path () { draw_session->close_path (); }
485 hb_font_t *font;
486 hb_draw_session_t *draw_session;
487 point_t *delta;
489 const OT::cff1::accelerator_t *cff;
492 struct cff1_path_procs_path_t : path_procs_t<cff1_path_procs_path_t, cff1_cs_interp_env_t, cff1_path_param_t>
494 static void moveto (cff1_cs_interp_env_t &env, cff1_path_param_t& param, const point_t &pt)
496 param.move_to (pt);
497 env.moveto (pt);
500 static void line (cff1_cs_interp_env_t &env, cff1_path_param_t &param, const point_t &pt1)
502 param.line_to (pt1);
503 env.moveto (pt1);
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)
508 param.cubic_to (pt1, pt2, pt3);
509 env.moveto (pt3);
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);
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>
518 static void process_seac (cff1_cs_interp_env_t &env, cff1_path_param_t& param)
520 /* End previous path */
521 param.end_path ();
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 ());
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 ();
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)
540 if (unlikely (!cff->is_valid () || (glyph >= cff->num_glyphs))) return false;
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;
550 /* Let's end the path specially since it is called inside seac also */
551 param.end_path ();
553 return true;
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
558 funcs->push_clip_glyph (data, glyph, font);
559 funcs->color (data, true, foreground);
560 funcs->pop_clip (data);
562 return true;
565 bool OT::cff1::accelerator_t::get_path (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session) const
567 #ifdef HB_NO_OT_FONT_CFF
568 /* XXX Remove check when this code moves to .hh file. */
569 return true;
570 #endif
572 return _get_path (this, font, glyph, draw_session);
575 struct get_seac_param_t
577 get_seac_param_t (const OT::cff1::accelerator_subset_t *_cff) : cff (_cff) {}
579 bool has_seac () const { return base && accent; }
581 const OT::cff1::accelerator_subset_t *cff;
582 hb_codepoint_t base = 0;
583 hb_codepoint_t accent = 0;
586 struct cff1_cs_opset_seac_t : cff1_cs_opset_t<cff1_cs_opset_seac_t, get_seac_param_t>
588 static void process_seac (cff1_cs_interp_env_t &env, get_seac_param_t& param)
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 ();
594 param.base = param.cff->std_code_to_glyph (base_char);
595 param.accent = param.cff->std_code_to_glyph (accent_char);
599 bool OT::cff1::accelerator_subset_t::get_seac_components (hb_codepoint_t glyph, hb_codepoint_t *base, hb_codepoint_t *accent) const
601 if (unlikely (!is_valid () || (glyph >= num_glyphs))) return false;
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;
610 if (param.has_seac ())
612 *base = param.base;
613 *accent = param.accent;
614 return true;
616 return false;
620 #endif