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