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
27 #include "hb-ot-cff1-table.hh"
28 #include "hb-cff1-interp-cs.hh"
33 static const uint8_t standard_encoding_to_code [] =
35 0, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46,
36 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62,
37 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78,
38 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94,
39 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110,
40 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126,
41 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 177,
42 178, 179, 180, 182, 183, 184, 185, 186, 187, 188, 189, 191, 193, 194, 195, 196,
43 197, 198, 199, 200, 202, 203, 205, 206, 207, 208, 225, 227, 232, 233, 234, 235,
44 241, 245, 248, 249, 250, 251
48 static const uint8_t expert_encoding_to_code [] =
50 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 45, 46,
51 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 58, 59, 0, 0, 0,
52 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
53 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
54 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
55 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
56 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87, 88, 0,
57 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
58 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
59 0, 0, 0, 0, 0, 0, 201, 0, 0, 0, 0, 189, 0, 0, 188, 0,
60 0, 0, 0, 190, 202, 0, 0, 0, 0, 203, 0, 0, 0, 0, 0, 0,
61 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
62 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
63 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
64 0, 0, 0, 0, 0, 33, 34, 36, 37, 38, 39, 40, 41, 42, 43, 48,
65 49, 50, 51, 52, 53, 54, 55, 56, 57, 60, 61, 62, 63, 65, 66, 67,
66 68, 69, 73, 76, 77, 78, 79, 82, 83, 84, 86, 89, 90, 91, 93, 94,
67 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110,
68 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126,
69 161, 162, 163, 166, 167, 168, 169, 170, 172, 175, 178, 179, 182, 183, 184, 191,
70 192, 193, 194, 195, 196, 197, 200, 204, 205, 206, 207, 208, 209, 210, 211, 212,
71 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228,
72 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244,
73 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255
77 static const uint16_t expert_charset_to_sid [] =
79 0, 1, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 13, 14, 15, 99,
80 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 27, 28, 249, 250, 251, 252,
81 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 109, 110,
82 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282,
83 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298,
84 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314,
85 315, 316, 317, 318, 158, 155, 163, 319, 320, 321, 322, 323, 324, 325, 326, 150,
86 164, 169, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340,
87 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356,
88 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372,
89 373, 374, 375, 376, 377, 378
93 static const uint16_t expert_subset_charset_to_sid [] =
95 0, 1, 231, 232, 235, 236, 237, 238, 13, 14, 15, 99, 239, 240, 241, 242,
96 243, 244, 245, 246, 247, 248, 27, 28, 249, 250, 251, 253, 254, 255, 256, 257,
97 258, 259, 260, 261, 262, 263, 264, 265, 266, 109, 110, 267, 268, 269, 270, 272,
98 300, 301, 302, 305, 314, 315, 158, 155, 163, 320, 321, 322, 323, 324, 325, 326,
99 150, 164, 169, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339,
100 340, 341, 342, 343, 344, 345, 346
104 static const uint8_t standard_encoding_to_sid [] =
106 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
107 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
108 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
109 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
110 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
111 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
112 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
113 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 0,
114 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
115 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
116 0, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110,
117 0, 111, 112, 113, 114, 0, 115, 116, 117, 118, 119, 120, 121, 122, 0, 123,
118 0, 124, 125, 126, 127, 128, 129, 130, 131, 0, 132, 133, 0, 134, 135, 136,
119 137, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
120 0, 138, 0, 139, 0, 0, 0, 0, 140, 141, 142, 143, 0, 0, 0, 0,
121 0, 144, 0, 0, 0, 145, 0, 0, 146, 147, 148, 149, 0, 0, 0, 0
124 hb_codepoint_t OT::cff1::lookup_standard_encoding_for_code (hb_codepoint_t sid)
126 if (sid < ARRAY_LENGTH (standard_encoding_to_code))
127 return (hb_codepoint_t)standard_encoding_to_code[sid];
132 hb_codepoint_t OT::cff1::lookup_expert_encoding_for_code (hb_codepoint_t sid)
134 if (sid < ARRAY_LENGTH (expert_encoding_to_code))
135 return (hb_codepoint_t)expert_encoding_to_code[sid];
140 hb_codepoint_t OT::cff1::lookup_expert_charset_for_sid (hb_codepoint_t glyph)
142 if (glyph < ARRAY_LENGTH (expert_charset_to_sid))
143 return (hb_codepoint_t)expert_charset_to_sid[glyph];
148 hb_codepoint_t OT::cff1::lookup_expert_subset_charset_for_sid (hb_codepoint_t glyph)
150 if (glyph < ARRAY_LENGTH (expert_subset_charset_to_sid))
151 return (hb_codepoint_t)expert_subset_charset_to_sid[glyph];
156 hb_codepoint_t OT::cff1::lookup_standard_encoding_for_sid (hb_codepoint_t code)
158 if (code < ARRAY_LENGTH (standard_encoding_to_sid))
159 return (hb_codepoint_t)standard_encoding_to_sid[code];
161 return CFF_UNDEF_SID;
168 min.set_int (0x7FFFFFFF, 0x7FFFFFFF);
169 max.set_int (-0x80000000, -0x80000000);
172 void update (const point_t &pt)
174 if (pt.x < min.x) min.x = pt.x;
175 if (pt.x > max.x) max.x = pt.x;
176 if (pt.y < min.y) min.y = pt.y;
177 if (pt.y > max.y) max.y = pt.y;
180 void merge (const bounds_t &b)
184 else if (!b.empty ())
186 if (b.min.x < min.x) min.x = b.min.x;
187 if (b.max.x > max.x) max.x = b.max.x;
188 if (b.min.y < min.y) min.y = b.min.y;
189 if (b.max.y > max.y) max.y = b.max.y;
193 void offset (const point_t &delta)
203 { return (min.x >= max.x) || (min.y >= max.y); }
209 struct extents_param_t
211 void init (const OT::cff1::accelerator_t *_cff)
218 void start_path () { path_open = true; }
219 void end_path () { path_open = false; }
220 bool is_path_open () const { return path_open; }
225 const OT::cff1::accelerator_t *cff;
228 struct cff1_path_procs_extents_t : path_procs_t<cff1_path_procs_extents_t, cff1_cs_interp_env_t, extents_param_t>
230 static void moveto (cff1_cs_interp_env_t &env, extents_param_t& param, const point_t &pt)
236 static void line (cff1_cs_interp_env_t &env, extents_param_t& param, const point_t &pt1)
238 if (!param.is_path_open ())
241 param.bounds.update (env.get_pt ());
244 param.bounds.update (env.get_pt ());
247 static void curve (cff1_cs_interp_env_t &env, extents_param_t& param, const point_t &pt1, const point_t &pt2, const point_t &pt3)
249 if (!param.is_path_open ())
252 param.bounds.update (env.get_pt ());
254 /* include control points */
255 param.bounds.update (pt1);
256 param.bounds.update (pt2);
258 param.bounds.update (env.get_pt ());
262 static bool _get_bounds (const OT::cff1::accelerator_t *cff, hb_codepoint_t glyph, bounds_t &bounds, bool in_seac=false);
264 struct cff1_cs_opset_extents_t : cff1_cs_opset_t<cff1_cs_opset_extents_t, extents_param_t, cff1_path_procs_extents_t>
266 static void process_seac (cff1_cs_interp_env_t &env, extents_param_t& param)
268 unsigned int n = env.argStack.get_count ();
270 delta.x = env.argStack[n-4];
271 delta.y = env.argStack[n-3];
272 hb_codepoint_t base = param.cff->std_code_to_glyph (env.argStack[n-2].to_int ());
273 hb_codepoint_t accent = param.cff->std_code_to_glyph (env.argStack[n-1].to_int ());
275 bounds_t base_bounds, accent_bounds;
276 if (likely (!env.in_seac && base && accent
277 && _get_bounds (param.cff, base, base_bounds, true)
278 && _get_bounds (param.cff, accent, accent_bounds, true)))
280 param.bounds.merge (base_bounds);
281 accent_bounds.offset (delta);
282 param.bounds.merge (accent_bounds);
289 bool _get_bounds (const OT::cff1::accelerator_t *cff, hb_codepoint_t glyph, bounds_t &bounds, bool in_seac)
292 if (unlikely (!cff->is_valid () || (glyph >= cff->num_glyphs))) return false;
294 unsigned int fd = cff->fdSelect->get_fd (glyph);
295 cff1_cs_interpreter_t<cff1_cs_opset_extents_t, extents_param_t> interp;
296 const byte_str_t str = (*cff->charStrings)[glyph];
297 interp.env.init (str, *cff, fd);
298 interp.env.set_in_seac (in_seac);
299 extents_param_t param;
301 if (unlikely (!interp.interpret (param))) return false;
302 bounds = param.bounds;
306 bool OT::cff1::accelerator_t::get_extents (hb_codepoint_t glyph, hb_glyph_extents_t *extents) const
310 if (!_get_bounds (this, glyph, bounds))
313 if (bounds.min.x >= bounds.max.x)
316 extents->x_bearing = 0;
320 extents->x_bearing = (int32_t)bounds.min.x.floor ();
321 extents->width = (int32_t)bounds.max.x.ceil () - extents->x_bearing;
323 if (bounds.min.y >= bounds.max.y)
326 extents->y_bearing = 0;
330 extents->y_bearing = (int32_t)bounds.max.y.ceil ();
331 extents->height = (int32_t)bounds.min.y.floor () - extents->y_bearing;
337 struct get_seac_param_t
339 void init (const OT::cff1::accelerator_t *_cff)
346 bool has_seac () const { return base && accent; }
348 const OT::cff1::accelerator_t *cff;
350 hb_codepoint_t accent;
353 struct cff1_cs_opset_seac_t : cff1_cs_opset_t<cff1_cs_opset_seac_t, get_seac_param_t>
355 static void process_seac (cff1_cs_interp_env_t &env, get_seac_param_t& param)
357 unsigned int n = env.argStack.get_count ();
358 hb_codepoint_t base_char = (hb_codepoint_t)env.argStack[n-2].to_int ();
359 hb_codepoint_t accent_char = (hb_codepoint_t)env.argStack[n-1].to_int ();
361 param.base = param.cff->std_code_to_glyph (base_char);
362 param.accent = param.cff->std_code_to_glyph (accent_char);
366 bool OT::cff1::accelerator_t::get_seac_components (hb_codepoint_t glyph, hb_codepoint_t *base, hb_codepoint_t *accent) const
368 if (unlikely (!is_valid () || (glyph >= num_glyphs))) return false;
370 unsigned int fd = fdSelect->get_fd (glyph);
371 cff1_cs_interpreter_t<cff1_cs_opset_seac_t, get_seac_param_t> interp;
372 const byte_str_t str = (*charStrings)[glyph];
373 interp.env.init (str, *this, fd);
374 get_seac_param_t param;
376 if (unlikely (!interp.interpret (param))) return false;
378 if (param.has_seac ())
381 *accent = param.accent;