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-ot-cff1-table.hh"
32 #include "hb-cff1-interp-cs.hh"
33
34 using namespace CFF;
35
36 /* SID to code */
37 static const uint8_t standard_encoding_to_code [] =
38 {
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
49 };
50
51 /* SID to code */
52 static const uint8_t expert_encoding_to_code [] =
53 {
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
78 };
79
80 /* glyph ID to SID */
81 static const uint16_t expert_charset_to_sid [] =
82 {
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
94 };
95
96 /* glyph ID to SID */
97 static const uint16_t expert_subset_charset_to_sid [] =
98 {
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
105 };
106
107 /* code to SID */
108 static const uint8_t standard_encoding_to_sid [] =
109 {
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
126 };
127
lookup_standard_encoding_for_code(hb_codepoint_t sid)128 hb_codepoint_t OT::cff1::lookup_standard_encoding_for_code (hb_codepoint_t sid)
129 {
130 if (sid < ARRAY_LENGTH (standard_encoding_to_code))
131 return (hb_codepoint_t)standard_encoding_to_code[sid];
132 else
133 return 0;
134 }
135
lookup_expert_encoding_for_code(hb_codepoint_t sid)136 hb_codepoint_t OT::cff1::lookup_expert_encoding_for_code (hb_codepoint_t sid)
137 {
138 if (sid < ARRAY_LENGTH (expert_encoding_to_code))
139 return (hb_codepoint_t)expert_encoding_to_code[sid];
140 else
141 return 0;
142 }
143
lookup_expert_charset_for_sid(hb_codepoint_t glyph)144 hb_codepoint_t OT::cff1::lookup_expert_charset_for_sid (hb_codepoint_t glyph)
145 {
146 if (glyph < ARRAY_LENGTH (expert_charset_to_sid))
147 return (hb_codepoint_t)expert_charset_to_sid[glyph];
148 else
149 return 0;
150 }
151
lookup_expert_subset_charset_for_sid(hb_codepoint_t glyph)152 hb_codepoint_t OT::cff1::lookup_expert_subset_charset_for_sid (hb_codepoint_t glyph)
153 {
154 if (glyph < ARRAY_LENGTH (expert_subset_charset_to_sid))
155 return (hb_codepoint_t)expert_subset_charset_to_sid[glyph];
156 else
157 return 0;
158 }
159
lookup_standard_encoding_for_sid(hb_codepoint_t code)160 hb_codepoint_t OT::cff1::lookup_standard_encoding_for_sid (hb_codepoint_t code)
161 {
162 if (code < ARRAY_LENGTH (standard_encoding_to_sid))
163 return (hb_codepoint_t)standard_encoding_to_sid[code];
164 else
165 return CFF_UNDEF_SID;
166 }
167
168 struct bounds_t
169 {
initbounds_t170 void init ()
171 {
172 min.set_int (INT_MAX, INT_MAX);
173 max.set_int (INT_MIN, INT_MIN);
174 }
175
updatebounds_t176 void update (const point_t &pt)
177 {
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;
182 }
183
mergebounds_t184 void merge (const bounds_t &b)
185 {
186 if (empty ())
187 *this = b;
188 else if (!b.empty ())
189 {
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;
194 }
195 }
196
offsetbounds_t197 void offset (const point_t &delta)
198 {
199 if (!empty ())
200 {
201 min.move (delta);
202 max.move (delta);
203 }
204 }
205
emptybounds_t206 bool empty () const { return (min.x >= max.x) || (min.y >= max.y); }
207
208 point_t min;
209 point_t max;
210 };
211
212 struct cff1_extents_param_t
213 {
initcff1_extents_param_t214 void init (const OT::cff1::accelerator_t *_cff)
215 {
216 path_open = false;
217 cff = _cff;
218 bounds.init ();
219 }
220
start_pathcff1_extents_param_t221 void start_path () { path_open = true; }
end_pathcff1_extents_param_t222 void end_path () { path_open = false; }
is_path_opencff1_extents_param_t223 bool is_path_open () const { return path_open; }
224
225 bool path_open;
226 bounds_t bounds;
227
228 const OT::cff1::accelerator_t *cff;
229 };
230
231 struct cff1_path_procs_extents_t : path_procs_t<cff1_path_procs_extents_t, cff1_cs_interp_env_t, cff1_extents_param_t>
232 {
movetocff1_path_procs_extents_t233 static void moveto (cff1_cs_interp_env_t &env, cff1_extents_param_t& param, const point_t &pt)
234 {
235 param.end_path ();
236 env.moveto (pt);
237 }
238
linecff1_path_procs_extents_t239 static void line (cff1_cs_interp_env_t &env, cff1_extents_param_t& param, const point_t &pt1)
240 {
241 if (!param.is_path_open ())
242 {
243 param.start_path ();
244 param.bounds.update (env.get_pt ());
245 }
246 env.moveto (pt1);
247 param.bounds.update (env.get_pt ());
248 }
249
curvecff1_path_procs_extents_t250 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)
251 {
252 if (!param.is_path_open ())
253 {
254 param.start_path ();
255 param.bounds.update (env.get_pt ());
256 }
257 /* include control points */
258 param.bounds.update (pt1);
259 param.bounds.update (pt2);
260 env.moveto (pt3);
261 param.bounds.update (env.get_pt ());
262 }
263 };
264
265 static bool _get_bounds (const OT::cff1::accelerator_t *cff, hb_codepoint_t glyph, bounds_t &bounds, bool in_seac=false);
266
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>
268 {
process_seaccff1_cs_opset_extents_t269 static void process_seac (cff1_cs_interp_env_t &env, cff1_extents_param_t& param)
270 {
271 unsigned int n = env.argStack.get_count ();
272 point_t delta;
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 ());
277
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)))
282 {
283 param.bounds.merge (base_bounds);
284 accent_bounds.offset (delta);
285 param.bounds.merge (accent_bounds);
286 }
287 else
288 env.set_error ();
289 }
290 };
291
_get_bounds(const OT::cff1::accelerator_t * cff,hb_codepoint_t glyph,bounds_t & bounds,bool in_seac)292 bool _get_bounds (const OT::cff1::accelerator_t *cff, hb_codepoint_t glyph, bounds_t &bounds, bool in_seac)
293 {
294 bounds.init ();
295 if (unlikely (!cff->is_valid () || (glyph >= cff->num_glyphs))) return false;
296
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;
303 param.init (cff);
304 if (unlikely (!interp.interpret (param))) return false;
305 bounds = param.bounds;
306 return true;
307 }
308
get_extents(hb_font_t * font,hb_codepoint_t glyph,hb_glyph_extents_t * extents) const309 bool OT::cff1::accelerator_t::get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const
310 {
311 #ifdef HB_NO_OT_FONT_CFF
312 /* XXX Remove check when this code moves to .hh file. */
313 return true;
314 #endif
315
316 bounds_t bounds;
317
318 if (!_get_bounds (this, glyph, bounds))
319 return false;
320
321 if (bounds.min.x >= bounds.max.x)
322 {
323 extents->width = 0;
324 extents->x_bearing = 0;
325 }
326 else
327 {
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 ());
330 }
331 if (bounds.min.y >= bounds.max.y)
332 {
333 extents->height = 0;
334 extents->y_bearing = 0;
335 }
336 else
337 {
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 ());
340 }
341
342 return true;
343 }
344
345 struct get_seac_param_t
346 {
initget_seac_param_t347 void init (const OT::cff1::accelerator_t *_cff)
348 {
349 cff = _cff;
350 base = 0;
351 accent = 0;
352 }
353
has_seacget_seac_param_t354 bool has_seac () const { return base && accent; }
355
356 const OT::cff1::accelerator_t *cff;
357 hb_codepoint_t base;
358 hb_codepoint_t accent;
359 };
360
361 struct cff1_cs_opset_seac_t : cff1_cs_opset_t<cff1_cs_opset_seac_t, get_seac_param_t>
362 {
process_seaccff1_cs_opset_seac_t363 static void process_seac (cff1_cs_interp_env_t &env, get_seac_param_t& param)
364 {
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 ();
368
369 param.base = param.cff->std_code_to_glyph (base_char);
370 param.accent = param.cff->std_code_to_glyph (accent_char);
371 }
372 };
373
get_seac_components(hb_codepoint_t glyph,hb_codepoint_t * base,hb_codepoint_t * accent) const374 bool OT::cff1::accelerator_t::get_seac_components (hb_codepoint_t glyph, hb_codepoint_t *base, hb_codepoint_t *accent) const
375 {
376 if (unlikely (!is_valid () || (glyph >= num_glyphs))) return false;
377
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;
383 param.init (this);
384 if (unlikely (!interp.interpret (param))) return false;
385
386 if (param.has_seac ())
387 {
388 *base = param.base;
389 *accent = param.accent;
390 return true;
391 }
392 return false;
393 }
394
395
396 #endif
397