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
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
33 #include "hb-ot-cff1-table.hh"
34 #include "hb-cff1-interp-cs.hh"
43 int cmp (uint16_t a) const
45 if (a == sid) return 0;
46 return (a < sid) ? -1 : 1;
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
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
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 },
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 }
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];
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];
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];
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];
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];
265 return CFF_UNDEF_SID;
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)
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)
306 bool empty () const { return (min.x >= max.x) || (min.y >= max.y); }
312 struct cff1_extents_param_t
314 cff1_extents_param_t (const OT::cff1::accelerator_t *_cff) : cff (_cff)
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;
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)
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 ())
342 param.bounds.update (env.get_pt ());
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 ())
353 param.bounds.update (env.get_pt ());
355 /* include control points */
356 param.bounds.update (pt1);
357 param.bounds.update (pt2);
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 ();
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);
390 bool _get_bounds (const OT::cff1::accelerator_t *cff, hb_codepoint_t glyph, bounds_t &bounds, bool in_seac)
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;
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. */
415 if (!_get_bounds (this, glyph, bounds))
418 if (bounds.min.x >= bounds.max.x)
421 extents->x_bearing = 0;
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)
431 extents->y_bearing = 0;
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);
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_;
455 void move_to (const point_t &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)
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;
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 (); }
486 hb_draw_session_t *draw_session;
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)
500 static void line (cff1_cs_interp_env_t &env, cff1_path_param_t ¶m, const point_t &pt1)
506 static void curve (cff1_cs_interp_env_t &env, cff1_path_param_t ¶m, const point_t &pt1, const point_t &pt2, const point_t &pt3)
508 param.cubic_to (pt1, pt2, 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 */
523 unsigned int n = env.argStack.get_count ();
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))))
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 */
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);
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. */
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 ())
613 *accent = param.accent;