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-ot-cff1-table.hh" 28 #include "hb-cff1-interp-cs.hh" 29 30 using namespace CFF; 31 32 /* SID to code */ 33 static const uint8_t standard_encoding_to_code [] = 34 { 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 45 }; 46 47 /* SID to code */ 48 static const uint8_t expert_encoding_to_code [] = 49 { 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 74 }; 75 76 /* glyph ID to SID */ 77 static const uint16_t expert_charset_to_sid [] = 78 { 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 90 }; 91 92 /* glyph ID to SID */ 93 static const uint16_t expert_subset_charset_to_sid [] = 94 { 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 101 }; 102 103 /* code to SID */ 104 static const uint8_t standard_encoding_to_sid [] = 105 { 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 122 }; 123 124 hb_codepoint_t OT::cff1::lookup_standard_encoding_for_code (hb_codepoint_t sid) 125 { 126 if (sid < ARRAY_LENGTH (standard_encoding_to_code)) 127 return (hb_codepoint_t)standard_encoding_to_code[sid]; 128 else 129 return 0; 130 } 131 132 hb_codepoint_t OT::cff1::lookup_expert_encoding_for_code (hb_codepoint_t sid) 133 { 134 if (sid < ARRAY_LENGTH (expert_encoding_to_code)) 135 return (hb_codepoint_t)expert_encoding_to_code[sid]; 136 else 137 return 0; 138 } 139 140 hb_codepoint_t OT::cff1::lookup_expert_charset_for_sid (hb_codepoint_t glyph) 141 { 142 if (glyph < ARRAY_LENGTH (expert_charset_to_sid)) 143 return (hb_codepoint_t)expert_charset_to_sid[glyph]; 144 else 145 return 0; 146 } 147 148 hb_codepoint_t OT::cff1::lookup_expert_subset_charset_for_sid (hb_codepoint_t glyph) 149 { 150 if (glyph < ARRAY_LENGTH (expert_subset_charset_to_sid)) 151 return (hb_codepoint_t)expert_subset_charset_to_sid[glyph]; 152 else 153 return 0; 154 } 155 156 hb_codepoint_t OT::cff1::lookup_standard_encoding_for_sid (hb_codepoint_t code) 157 { 158 if (code < ARRAY_LENGTH (standard_encoding_to_sid)) 159 return (hb_codepoint_t)standard_encoding_to_sid[code]; 160 else 161 return CFF_UNDEF_SID; 162 } 163 164 struct Bounds 165 { 166 void init () 167 { 168 min.set_int (0x7FFFFFFF, 0x7FFFFFFF); 169 max.set_int (-0x80000000, -0x80000000); 170 } 171 172 void update (const Point &pt) 173 { 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; 178 } 179 180 void merge (const Bounds &b) 181 { 182 if (empty ()) 183 *this = b; 184 else if (!b.empty ()) 185 { 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; 190 } 191 } 192 193 void offset (const Point &delta) 194 { 195 if (!empty ()) 196 { 197 min.move (delta); 198 max.move (delta); 199 } 200 } 201 202 bool empty () const 203 { return (min.x >= max.x) || (min.y >= max.y); } 204 205 Point min; 206 Point max; 207 }; 208 209 struct ExtentsParam 210 { 211 void init (const OT::cff1::accelerator_t *_cff) 212 { 213 path_open = false; 214 cff = _cff; 215 bounds.init (); 216 } 217 218 void start_path () { path_open = true; } 219 void end_path () { path_open = false; } 220 bool is_path_open () const { return path_open; } 221 222 bool path_open; 223 Bounds bounds; 224 225 const OT::cff1::accelerator_t *cff; 226 }; 227 228 struct CFF1PathProcs_Extents : PathProcs<CFF1PathProcs_Extents, CFF1CSInterpEnv, ExtentsParam> 229 { 230 static void moveto (CFF1CSInterpEnv &env, ExtentsParam& param, const Point &pt) 231 { 232 param.end_path (); 233 env.moveto (pt); 234 } 235 236 static void line (CFF1CSInterpEnv &env, ExtentsParam& param, const Point &pt1) 237 { 238 if (!param.is_path_open ()) 239 { 240 param.start_path (); 241 param.bounds.update (env.get_pt ()); 242 } 243 env.moveto (pt1); 244 param.bounds.update (env.get_pt ()); 245 } 246 247 static void curve (CFF1CSInterpEnv &env, ExtentsParam& param, const Point &pt1, const Point &pt2, const Point &pt3) 248 { 249 if (!param.is_path_open ()) 250 { 251 param.start_path (); 252 param.bounds.update (env.get_pt ()); 253 } 254 /* include control points */ 255 param.bounds.update (pt1); 256 param.bounds.update (pt2); 257 env.moveto (pt3); 258 param.bounds.update (env.get_pt ()); 259 } 260 }; 261 262 static bool _get_bounds (const OT::cff1::accelerator_t *cff, hb_codepoint_t glyph, Bounds &bounds, bool in_seac=false); 263 264 struct CFF1CSOpSet_Extents : CFF1CSOpSet<CFF1CSOpSet_Extents, ExtentsParam, CFF1PathProcs_Extents> 265 { 266 static void process_seac (CFF1CSInterpEnv &env, ExtentsParam& param) 267 { 268 unsigned int n = env.argStack.get_count (); 269 Point delta; 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 ()); 274 275 Bounds 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))) 279 { 280 param.bounds.merge (base_bounds); 281 accent_bounds.offset (delta); 282 param.bounds.merge (accent_bounds); 283 } 284 else 285 env.set_error (); 286 } 287 }; 288 289 bool _get_bounds (const OT::cff1::accelerator_t *cff, hb_codepoint_t glyph, Bounds &bounds, bool in_seac) 290 { 291 bounds.init (); 292 if (unlikely (!cff->is_valid () || (glyph >= cff->num_glyphs))) return false; 293 294 unsigned int fd = cff->fdSelect->get_fd (glyph); 295 CFF1CSInterpreter<CFF1CSOpSet_Extents, ExtentsParam> interp; 296 const ByteStr str = (*cff->charStrings)[glyph]; 297 interp.env.init (str, *cff, fd); 298 interp.env.set_in_seac (in_seac); 299 ExtentsParam param; 300 param.init (cff); 301 if (unlikely (!interp.interpret (param))) return false; 302 bounds = param.bounds; 303 return true; 304 } 305 306 bool OT::cff1::accelerator_t::get_extents (hb_codepoint_t glyph, hb_glyph_extents_t *extents) const 307 { 308 Bounds bounds; 309 310 if (!_get_bounds (this, glyph, bounds)) 311 return false; 312 313 if (bounds.min.x >= bounds.max.x) 314 { 315 extents->width = 0; 316 extents->x_bearing = 0; 317 } 318 else 319 { 320 extents->x_bearing = (int32_t)bounds.min.x.floor (); 321 extents->width = (int32_t)bounds.max.x.ceil () - extents->x_bearing; 322 } 323 if (bounds.min.y >= bounds.max.y) 324 { 325 extents->height = 0; 326 extents->y_bearing = 0; 327 } 328 else 329 { 330 extents->y_bearing = (int32_t)bounds.max.y.ceil (); 331 extents->height = (int32_t)bounds.min.y.floor () - extents->y_bearing; 332 } 333 334 return true; 335 } 336 337 struct GetSeacParam 338 { 339 void init (const OT::cff1::accelerator_t *_cff) 340 { 341 cff = _cff; 342 base = 0; 343 accent = 0; 344 } 345 346 bool has_seac () const { return base && accent; } 347 348 const OT::cff1::accelerator_t *cff; 349 hb_codepoint_t base; 350 hb_codepoint_t accent; 351 }; 352 353 struct CFF1CSOpSet_Seac : CFF1CSOpSet<CFF1CSOpSet_Seac, GetSeacParam> 354 { 355 static void process_seac (CFF1CSInterpEnv &env, GetSeacParam& param) 356 { 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 (); 360 361 param.base = param.cff->std_code_to_glyph (base_char); 362 param.accent = param.cff->std_code_to_glyph (accent_char); 363 } 364 }; 365 366 bool OT::cff1::accelerator_t::get_seac_components (hb_codepoint_t glyph, hb_codepoint_t *base, hb_codepoint_t *accent) const 367 { 368 if (unlikely (!is_valid () || (glyph >= num_glyphs))) return false; 369 370 unsigned int fd = fdSelect->get_fd (glyph); 371 CFF1CSInterpreter<CFF1CSOpSet_Seac, GetSeacParam> interp; 372 const ByteStr str = (*charStrings)[glyph]; 373 interp.env.init (str, *this, fd); 374 GetSeacParam param; 375 param.init (this); 376 if (unlikely (!interp.interpret (param))) return false; 377 378 if (param.has_seac ()) 379 { 380 *base = param.base; 381 *accent = param.accent; 382 return true; 383 } 384 return false; 385 } 386