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 #ifndef HB_OT_CFF1_TABLE_HH 28 #define HB_OT_CFF1_TABLE_HH 29 30 #include "hb-ot-cff-common.hh" 31 32 #define HB_STRING_ARRAY_NAME cff1_std_strings 33 #define HB_STRING_ARRAY_LIST "hb-ot-cff1-std-str.hh" 34 #include "hb-string-array.hh" 35 #undef HB_STRING_ARRAY_LIST 36 #undef HB_STRING_ARRAY_NAME 37 38 namespace CFF { 39 40 /* 41 * CFF -- Compact Font Format (CFF) 42 * https://www.adobe.com/content/dam/acom/en/devnet/font/pdfs/5176.CFF.pdf 43 */ 44 #define HB_OT_TAG_cff1 HB_TAG('C', 'F', 'F', ' ') 45 46 #define CFF_UNDEF_SID CFF_UNDEF_CODE 47 48 enum EncodingID { StandardEncoding = 0, ExpertEncoding = 1 }; 49 enum CharsetID { ISOAdobeCharset = 0, ExpertCharset = 1, ExpertSubsetCharset = 2 }; 50 51 typedef CFFIndex<HBUINT16> CFF1Index; 52 template <typename Type> struct CFF1IndexOf : CFFIndexOf<HBUINT16, Type> 53 { 54 }; 55 56 typedef CFFIndex<HBUINT16> CFF1Index; 57 typedef CFF1Index CFF1CharStrings; 58 typedef Subrs<HBUINT16> CFF1Subrs; 59 60 struct CFF1FDSelect : FDSelect 61 { 62 }; 63 64 /* Encoding */ 65 struct Encoding0 66 { sanitizeCFF::Encoding067 bool sanitize(hb_sanitize_context_t *c) const 68 { 69 TRACE_SANITIZE(this); 70 return_trace(codes.sanitize(c)); 71 } 72 get_codeCFF::Encoding073 hb_codepoint_t get_code(hb_codepoint_t glyph) const 74 { 75 assert(glyph > 0); 76 glyph--; 77 if (glyph < nCodes()) { 78 return (hb_codepoint_t)codes[glyph]; 79 } else 80 return CFF_UNDEF_CODE; 81 } 82 nCodesCFF::Encoding083 HBUINT8 &nCodes() 84 { 85 return codes.len; 86 } nCodesCFF::Encoding087 HBUINT8 nCodes() const 88 { 89 return codes.len; 90 } 91 92 ArrayOf<HBUINT8, HBUINT8> codes; 93 94 DEFINE_SIZE_ARRAY_SIZED(1, codes); 95 }; 96 97 struct Encoding1_Range 98 { sanitizeCFF::Encoding1_Range99 bool sanitize(hb_sanitize_context_t *c) const 100 { 101 TRACE_SANITIZE(this); 102 return_trace(c->check_struct(this)); 103 } 104 105 HBUINT8 first; 106 HBUINT8 nLeft; 107 108 DEFINE_SIZE_STATIC(2); 109 }; 110 111 struct Encoding1 112 { sanitizeCFF::Encoding1113 bool sanitize(hb_sanitize_context_t *c) const 114 { 115 TRACE_SANITIZE(this); 116 return_trace(ranges.sanitize(c)); 117 } 118 get_codeCFF::Encoding1119 hb_codepoint_t get_code(hb_codepoint_t glyph) const 120 { 121 assert(glyph > 0); 122 glyph--; 123 for (unsigned int i = 0; i < nRanges(); i++) { 124 if (glyph <= ranges[i].nLeft) { 125 hb_codepoint_t code = (hb_codepoint_t)ranges[i].first + glyph; 126 return (likely(code < 0x100) ? code : CFF_UNDEF_CODE); 127 } 128 glyph -= (ranges[i].nLeft + 1); 129 } 130 return CFF_UNDEF_CODE; 131 } 132 nRangesCFF::Encoding1133 HBUINT8 &nRanges() 134 { 135 return ranges.len; 136 } nRangesCFF::Encoding1137 HBUINT8 nRanges() const 138 { 139 return ranges.len; 140 } 141 142 ArrayOf<Encoding1_Range, HBUINT8> ranges; 143 144 DEFINE_SIZE_ARRAY_SIZED(1, ranges); 145 }; 146 147 struct SuppEncoding 148 { sanitizeCFF::SuppEncoding149 bool sanitize(hb_sanitize_context_t *c) const 150 { 151 TRACE_SANITIZE(this); 152 return_trace(c->check_struct(this)); 153 } 154 155 HBUINT8 code; 156 HBUINT16 glyph; 157 158 DEFINE_SIZE_STATIC(3); 159 }; 160 161 struct CFF1SuppEncData 162 { sanitizeCFF::CFF1SuppEncData163 bool sanitize(hb_sanitize_context_t *c) const 164 { 165 TRACE_SANITIZE(this); 166 return_trace(supps.sanitize(c)); 167 } 168 get_codesCFF::CFF1SuppEncData169 void get_codes(hb_codepoint_t sid, hb_vector_t<hb_codepoint_t> &codes) const 170 { 171 for (unsigned int i = 0; i < nSups(); i++) 172 if (sid == supps[i].glyph) 173 codes.push(supps[i].code); 174 } 175 nSupsCFF::CFF1SuppEncData176 HBUINT8 &nSups() 177 { 178 return supps.len; 179 } nSupsCFF::CFF1SuppEncData180 HBUINT8 nSups() const 181 { 182 return supps.len; 183 } 184 185 ArrayOf<SuppEncoding, HBUINT8> supps; 186 187 DEFINE_SIZE_ARRAY_SIZED(1, supps); 188 }; 189 190 struct Encoding 191 { get_sizeCFF::Encoding192 unsigned int get_size() const 193 { 194 unsigned int size = min_size; 195 switch (table_format()) { 196 case 0: 197 size += u.format0.get_size(); 198 break; 199 case 1: 200 size += u.format1.get_size(); 201 break; 202 } 203 if (has_supplement()) 204 size += suppEncData().get_size(); 205 return size; 206 } 207 get_codeCFF::Encoding208 hb_codepoint_t get_code(hb_codepoint_t glyph) const 209 { 210 switch (table_format()) { 211 case 0: 212 return u.format0.get_code(glyph); 213 case 1: 214 return u.format1.get_code(glyph); 215 default: 216 return 0; 217 } 218 } 219 table_formatCFF::Encoding220 uint8_t table_format() const 221 { 222 return format & 0x7F; 223 } has_supplementCFF::Encoding224 bool has_supplement() const 225 { 226 return format & 0x80; 227 } 228 get_supplement_codesCFF::Encoding229 void get_supplement_codes(hb_codepoint_t sid, hb_vector_t<hb_codepoint_t> &codes) const 230 { 231 codes.resize(0); 232 if (has_supplement()) 233 suppEncData().get_codes(sid, codes); 234 } 235 sanitizeCFF::Encoding236 bool sanitize(hb_sanitize_context_t *c) const 237 { 238 TRACE_SANITIZE(this); 239 if (unlikely(!c->check_struct(this))) 240 return_trace(false); 241 242 switch (table_format()) { 243 case 0: 244 if (unlikely(!u.format0.sanitize(c))) { 245 return_trace(false); 246 } 247 break; 248 case 1: 249 if (unlikely(!u.format1.sanitize(c))) { 250 return_trace(false); 251 } 252 break; 253 default: 254 return_trace(false); 255 } 256 return_trace(likely(!has_supplement() || suppEncData().sanitize(c))); 257 } 258 259 protected: suppEncDataCFF::Encoding260 const CFF1SuppEncData &suppEncData() const 261 { 262 switch (table_format()) { 263 case 0: 264 return StructAfter<CFF1SuppEncData>(u.format0.codes[u.format0.nCodes() - 1]); 265 case 1: 266 return StructAfter<CFF1SuppEncData>(u.format1.ranges[u.format1.nRanges() - 1]); 267 default: 268 return Null(CFF1SuppEncData); 269 } 270 } 271 272 public: 273 HBUINT8 format; 274 union { 275 Encoding0 format0; 276 Encoding1 format1; 277 } u; 278 /* CFF1SuppEncData suppEncData; */ 279 280 DEFINE_SIZE_MIN(1); 281 }; 282 283 /* Charset */ 284 struct Charset0 285 { sanitizeCFF::Charset0286 bool sanitize(hb_sanitize_context_t *c, unsigned int num_glyphs) const 287 { 288 TRACE_SANITIZE(this); 289 return_trace(c->check_struct(this) && sids[num_glyphs - 1].sanitize(c)); 290 } 291 get_sidCFF::Charset0292 hb_codepoint_t get_sid(hb_codepoint_t glyph) const 293 { 294 if (glyph == 0) 295 return 0; 296 else 297 return sids[glyph - 1]; 298 } 299 get_glyphCFF::Charset0300 hb_codepoint_t get_glyph(hb_codepoint_t sid, unsigned int num_glyphs) const 301 { 302 if (sid == 0) 303 return 0; 304 305 for (unsigned int glyph = 1; glyph < num_glyphs; glyph++) { 306 if (sids[glyph - 1] == sid) 307 return glyph; 308 } 309 return 0; 310 } 311 get_sizeCFF::Charset0312 unsigned int get_size(unsigned int num_glyphs) const 313 { 314 assert(num_glyphs > 0); 315 return HBUINT16::static_size * (num_glyphs - 1); 316 } 317 318 HBUINT16 sids[HB_VAR_ARRAY]; 319 320 DEFINE_SIZE_ARRAY(0, sids); 321 }; 322 323 template <typename TYPE> struct Charset_Range 324 { sanitizeCFF::Charset_Range325 bool sanitize(hb_sanitize_context_t *c) const 326 { 327 TRACE_SANITIZE(this); 328 return_trace(c->check_struct(this)); 329 } 330 331 HBUINT16 first; 332 TYPE nLeft; 333 334 DEFINE_SIZE_STATIC(HBUINT16::static_size + TYPE::static_size); 335 }; 336 337 template <typename TYPE> struct Charset1_2 338 { sanitizeCFF::Charset1_2339 bool sanitize(hb_sanitize_context_t *c, unsigned int num_glyphs) const 340 { 341 TRACE_SANITIZE(this); 342 if (unlikely(!c->check_struct(this))) 343 return_trace(false); 344 num_glyphs--; 345 for (unsigned int i = 0; num_glyphs > 0; i++) { 346 if (unlikely(!ranges[i].sanitize(c) || (num_glyphs < ranges[i].nLeft + 1))) 347 return_trace(false); 348 num_glyphs -= (ranges[i].nLeft + 1); 349 } 350 return_trace(true); 351 } 352 get_sidCFF::Charset1_2353 hb_codepoint_t get_sid(hb_codepoint_t glyph) const 354 { 355 if (glyph == 0) 356 return 0; 357 glyph--; 358 for (unsigned int i = 0;; i++) { 359 if (glyph <= ranges[i].nLeft) 360 return (hb_codepoint_t)ranges[i].first + glyph; 361 glyph -= (ranges[i].nLeft + 1); 362 } 363 364 return 0; 365 } 366 get_glyphCFF::Charset1_2367 hb_codepoint_t get_glyph(hb_codepoint_t sid, unsigned int num_glyphs) const 368 { 369 if (sid == 0) 370 return 0; 371 hb_codepoint_t glyph = 1; 372 for (unsigned int i = 0;; i++) { 373 if (glyph >= num_glyphs) 374 return 0; 375 if ((ranges[i].first <= sid) && (sid <= ranges[i].first + ranges[i].nLeft)) 376 return glyph + (sid - ranges[i].first); 377 glyph += (ranges[i].nLeft + 1); 378 } 379 380 return 0; 381 } 382 get_sizeCFF::Charset1_2383 unsigned int get_size(unsigned int num_glyphs) const 384 { 385 unsigned int size = HBUINT8::static_size; 386 int glyph = (int)num_glyphs; 387 388 assert(glyph > 0); 389 glyph--; 390 for (unsigned int i = 0; glyph > 0; i++) { 391 glyph -= (ranges[i].nLeft + 1); 392 size += Charset_Range<TYPE>::static_size; 393 } 394 395 return size; 396 } 397 398 Charset_Range<TYPE> ranges[HB_VAR_ARRAY]; 399 400 DEFINE_SIZE_ARRAY(0, ranges); 401 }; 402 403 typedef Charset1_2<HBUINT8> Charset1; 404 typedef Charset1_2<HBUINT16> Charset2; 405 typedef Charset_Range<HBUINT8> Charset1_Range; 406 typedef Charset_Range<HBUINT16> Charset2_Range; 407 408 struct Charset 409 { get_sizeCFF::Charset410 unsigned int get_size(unsigned int num_glyphs) const 411 { 412 switch (format) { 413 case 0: 414 return min_size + u.format0.get_size(num_glyphs); 415 case 1: 416 return min_size + u.format1.get_size(num_glyphs); 417 case 2: 418 return min_size + u.format2.get_size(num_glyphs); 419 default: 420 return 0; 421 } 422 } 423 get_sidCFF::Charset424 hb_codepoint_t get_sid(hb_codepoint_t glyph, unsigned int num_glyphs) const 425 { 426 if (unlikely(glyph >= num_glyphs)) 427 return 0; 428 switch (format) { 429 case 0: 430 return u.format0.get_sid(glyph); 431 case 1: 432 return u.format1.get_sid(glyph); 433 case 2: 434 return u.format2.get_sid(glyph); 435 default: 436 return 0; 437 } 438 } 439 get_glyphCFF::Charset440 hb_codepoint_t get_glyph(hb_codepoint_t sid, unsigned int num_glyphs) const 441 { 442 switch (format) { 443 case 0: 444 return u.format0.get_glyph(sid, num_glyphs); 445 case 1: 446 return u.format1.get_glyph(sid, num_glyphs); 447 case 2: 448 return u.format2.get_glyph(sid, num_glyphs); 449 default: 450 return 0; 451 } 452 } 453 sanitizeCFF::Charset454 bool sanitize(hb_sanitize_context_t *c) const 455 { 456 TRACE_SANITIZE(this); 457 if (unlikely(!c->check_struct(this))) 458 return_trace(false); 459 460 switch (format) { 461 case 0: 462 return_trace(u.format0.sanitize(c, c->get_num_glyphs())); 463 case 1: 464 return_trace(u.format1.sanitize(c, c->get_num_glyphs())); 465 case 2: 466 return_trace(u.format2.sanitize(c, c->get_num_glyphs())); 467 default: 468 return_trace(false); 469 } 470 } 471 472 HBUINT8 format; 473 union { 474 Charset0 format0; 475 Charset1 format1; 476 Charset2 format2; 477 } u; 478 479 DEFINE_SIZE_MIN(1); 480 }; 481 482 struct CFF1StringIndex : CFF1Index 483 { 484 }; 485 486 struct cff1_top_dict_interp_env_t : num_interp_env_t 487 { cff1_top_dict_interp_env_tCFF::cff1_top_dict_interp_env_t488 cff1_top_dict_interp_env_t() 489 : num_interp_env_t() 490 , prev_offset(0) 491 , last_offset(0) 492 { 493 } 494 495 unsigned int prev_offset; 496 unsigned int last_offset; 497 }; 498 499 struct name_dict_values_t 500 { 501 enum name_dict_val_index_t { 502 version, 503 notice, 504 copyright, 505 fullName, 506 familyName, 507 weight, 508 postscript, 509 fontName, 510 baseFontName, 511 registry, 512 ordering, 513 514 ValCount 515 }; 516 initCFF::name_dict_values_t517 void init() 518 { 519 for (unsigned int i = 0; i < ValCount; i++) 520 values[i] = CFF_UNDEF_SID; 521 } 522 operator []CFF::name_dict_values_t523 unsigned int &operator[](unsigned int i) 524 { 525 assert(i < ValCount); 526 return values[i]; 527 } 528 operator []CFF::name_dict_values_t529 unsigned int operator[](unsigned int i) const 530 { 531 assert(i < ValCount); 532 return values[i]; 533 } 534 name_op_to_indexCFF::name_dict_values_t535 static enum name_dict_val_index_t name_op_to_index(op_code_t op) 536 { 537 switch (op) { 538 default: // can't happen - just make some compiler happy 539 case OpCode_version: 540 return version; 541 case OpCode_Notice: 542 return notice; 543 case OpCode_Copyright: 544 return copyright; 545 case OpCode_FullName: 546 return fullName; 547 case OpCode_FamilyName: 548 return familyName; 549 case OpCode_Weight: 550 return weight; 551 case OpCode_PostScript: 552 return postscript; 553 case OpCode_FontName: 554 return fontName; 555 case OpCode_BaseFontName: 556 return baseFontName; 557 } 558 } 559 560 unsigned int values[ValCount]; 561 }; 562 563 struct cff1_top_dict_val_t : op_str_t 564 { 565 unsigned int last_arg_offset; 566 }; 567 568 struct cff1_top_dict_values_t : top_dict_values_t<cff1_top_dict_val_t> 569 { initCFF::cff1_top_dict_values_t570 void init() 571 { 572 top_dict_values_t<cff1_top_dict_val_t>::init(); 573 574 nameSIDs.init(); 575 ros_supplement = 0; 576 cidCount = 8720; 577 EncodingOffset = 0; 578 CharsetOffset = 0; 579 FDSelectOffset = 0; 580 privateDictInfo.init(); 581 } finiCFF::cff1_top_dict_values_t582 void fini() 583 { 584 top_dict_values_t<cff1_top_dict_val_t>::fini(); 585 } 586 is_CIDCFF::cff1_top_dict_values_t587 bool is_CID() const 588 { 589 return nameSIDs[name_dict_values_t::registry] != CFF_UNDEF_SID; 590 } 591 592 name_dict_values_t nameSIDs; 593 unsigned int ros_supplement_offset; 594 unsigned int ros_supplement; 595 unsigned int cidCount; 596 597 unsigned int EncodingOffset; 598 unsigned int CharsetOffset; 599 unsigned int FDSelectOffset; 600 table_info_t privateDictInfo; 601 }; 602 603 struct cff1_top_dict_opset_t : top_dict_opset_t<cff1_top_dict_val_t> 604 { process_opCFF::cff1_top_dict_opset_t605 static void process_op(op_code_t op, cff1_top_dict_interp_env_t &env, cff1_top_dict_values_t &dictval) 606 { 607 cff1_top_dict_val_t val; 608 val.last_arg_offset = (env.last_offset - 1) - dictval.opStart; /* offset to the last argument */ 609 610 switch (op) { 611 case OpCode_version: 612 case OpCode_Notice: 613 case OpCode_Copyright: 614 case OpCode_FullName: 615 case OpCode_FamilyName: 616 case OpCode_Weight: 617 case OpCode_PostScript: 618 case OpCode_BaseFontName: 619 dictval.nameSIDs[name_dict_values_t::name_op_to_index(op)] = env.argStack.pop_uint(); 620 env.clear_args(); 621 break; 622 case OpCode_isFixedPitch: 623 case OpCode_ItalicAngle: 624 case OpCode_UnderlinePosition: 625 case OpCode_UnderlineThickness: 626 case OpCode_PaintType: 627 case OpCode_CharstringType: 628 case OpCode_UniqueID: 629 case OpCode_StrokeWidth: 630 case OpCode_SyntheticBase: 631 case OpCode_CIDFontVersion: 632 case OpCode_CIDFontRevision: 633 case OpCode_CIDFontType: 634 case OpCode_UIDBase: 635 case OpCode_FontBBox: 636 case OpCode_XUID: 637 case OpCode_BaseFontBlend: 638 env.clear_args(); 639 break; 640 641 case OpCode_CIDCount: 642 dictval.cidCount = env.argStack.pop_uint(); 643 env.clear_args(); 644 break; 645 646 case OpCode_ROS: 647 dictval.ros_supplement = env.argStack.pop_uint(); 648 dictval.nameSIDs[name_dict_values_t::ordering] = env.argStack.pop_uint(); 649 dictval.nameSIDs[name_dict_values_t::registry] = env.argStack.pop_uint(); 650 env.clear_args(); 651 break; 652 653 case OpCode_Encoding: 654 dictval.EncodingOffset = env.argStack.pop_uint(); 655 env.clear_args(); 656 if (unlikely(dictval.EncodingOffset == 0)) 657 return; 658 break; 659 660 case OpCode_charset: 661 dictval.CharsetOffset = env.argStack.pop_uint(); 662 env.clear_args(); 663 if (unlikely(dictval.CharsetOffset == 0)) 664 return; 665 break; 666 667 case OpCode_FDSelect: 668 dictval.FDSelectOffset = env.argStack.pop_uint(); 669 env.clear_args(); 670 break; 671 672 case OpCode_Private: 673 dictval.privateDictInfo.offset = env.argStack.pop_uint(); 674 dictval.privateDictInfo.size = env.argStack.pop_uint(); 675 env.clear_args(); 676 break; 677 678 default: 679 env.last_offset = env.str_ref.offset; 680 top_dict_opset_t<cff1_top_dict_val_t>::process_op(op, env, dictval); 681 /* Record this operand below if stack is empty, otherwise done */ 682 if (!env.argStack.is_empty()) 683 return; 684 break; 685 } 686 687 if (unlikely(env.in_error())) 688 return; 689 690 dictval.add_op(op, env.str_ref, val); 691 } 692 }; 693 694 struct cff1_font_dict_values_t : dict_values_t<op_str_t> 695 { initCFF::cff1_font_dict_values_t696 void init() 697 { 698 dict_values_t<op_str_t>::init(); 699 privateDictInfo.init(); 700 fontName = CFF_UNDEF_SID; 701 } finiCFF::cff1_font_dict_values_t702 void fini() 703 { 704 dict_values_t<op_str_t>::fini(); 705 } 706 707 table_info_t privateDictInfo; 708 unsigned int fontName; 709 }; 710 711 struct cff1_font_dict_opset_t : dict_opset_t 712 { process_opCFF::cff1_font_dict_opset_t713 static void process_op(op_code_t op, num_interp_env_t &env, cff1_font_dict_values_t &dictval) 714 { 715 switch (op) { 716 case OpCode_FontName: 717 dictval.fontName = env.argStack.pop_uint(); 718 env.clear_args(); 719 break; 720 case OpCode_FontMatrix: 721 case OpCode_PaintType: 722 env.clear_args(); 723 break; 724 case OpCode_Private: 725 dictval.privateDictInfo.offset = env.argStack.pop_uint(); 726 dictval.privateDictInfo.size = env.argStack.pop_uint(); 727 env.clear_args(); 728 break; 729 730 default: 731 dict_opset_t::process_op(op, env); 732 if (!env.argStack.is_empty()) 733 return; 734 break; 735 } 736 737 if (unlikely(env.in_error())) 738 return; 739 740 dictval.add_op(op, env.str_ref); 741 } 742 }; 743 744 template <typename VAL> struct cff1_private_dict_values_base_t : dict_values_t<VAL> 745 { initCFF::cff1_private_dict_values_base_t746 void init() 747 { 748 dict_values_t<VAL>::init(); 749 subrsOffset = 0; 750 localSubrs = &Null(CFF1Subrs); 751 } finiCFF::cff1_private_dict_values_base_t752 void fini() 753 { 754 dict_values_t<VAL>::fini(); 755 } 756 757 unsigned int subrsOffset; 758 const CFF1Subrs *localSubrs; 759 }; 760 761 typedef cff1_private_dict_values_base_t<op_str_t> cff1_private_dict_values_subset_t; 762 typedef cff1_private_dict_values_base_t<num_dict_val_t> cff1_private_dict_values_t; 763 764 struct cff1_private_dict_opset_t : dict_opset_t 765 { process_opCFF::cff1_private_dict_opset_t766 static void process_op(op_code_t op, num_interp_env_t &env, cff1_private_dict_values_t &dictval) 767 { 768 num_dict_val_t val; 769 val.init(); 770 771 switch (op) { 772 case OpCode_BlueValues: 773 case OpCode_OtherBlues: 774 case OpCode_FamilyBlues: 775 case OpCode_FamilyOtherBlues: 776 case OpCode_StemSnapH: 777 case OpCode_StemSnapV: 778 env.clear_args(); 779 break; 780 case OpCode_StdHW: 781 case OpCode_StdVW: 782 case OpCode_BlueScale: 783 case OpCode_BlueShift: 784 case OpCode_BlueFuzz: 785 case OpCode_ForceBold: 786 case OpCode_LanguageGroup: 787 case OpCode_ExpansionFactor: 788 case OpCode_initialRandomSeed: 789 case OpCode_defaultWidthX: 790 case OpCode_nominalWidthX: 791 val.single_val = env.argStack.pop_num(); 792 env.clear_args(); 793 break; 794 case OpCode_Subrs: 795 dictval.subrsOffset = env.argStack.pop_uint(); 796 env.clear_args(); 797 break; 798 799 default: 800 dict_opset_t::process_op(op, env); 801 if (!env.argStack.is_empty()) 802 return; 803 break; 804 } 805 806 if (unlikely(env.in_error())) 807 return; 808 809 dictval.add_op(op, env.str_ref, val); 810 } 811 }; 812 813 struct cff1_private_dict_opset_subset : dict_opset_t 814 { process_opCFF::cff1_private_dict_opset_subset815 static void process_op(op_code_t op, num_interp_env_t &env, cff1_private_dict_values_subset_t &dictval) 816 { 817 switch (op) { 818 case OpCode_BlueValues: 819 case OpCode_OtherBlues: 820 case OpCode_FamilyBlues: 821 case OpCode_FamilyOtherBlues: 822 case OpCode_StemSnapH: 823 case OpCode_StemSnapV: 824 case OpCode_StdHW: 825 case OpCode_StdVW: 826 case OpCode_BlueScale: 827 case OpCode_BlueShift: 828 case OpCode_BlueFuzz: 829 case OpCode_ForceBold: 830 case OpCode_LanguageGroup: 831 case OpCode_ExpansionFactor: 832 case OpCode_initialRandomSeed: 833 case OpCode_defaultWidthX: 834 case OpCode_nominalWidthX: 835 env.clear_args(); 836 break; 837 838 case OpCode_Subrs: 839 dictval.subrsOffset = env.argStack.pop_uint(); 840 env.clear_args(); 841 break; 842 843 default: 844 dict_opset_t::process_op(op, env); 845 if (!env.argStack.is_empty()) 846 return; 847 break; 848 } 849 850 if (unlikely(env.in_error())) 851 return; 852 853 dictval.add_op(op, env.str_ref); 854 } 855 }; 856 857 typedef dict_interpreter_t<cff1_top_dict_opset_t, cff1_top_dict_values_t, cff1_top_dict_interp_env_t> 858 cff1_top_dict_interpreter_t; 859 typedef dict_interpreter_t<cff1_font_dict_opset_t, cff1_font_dict_values_t> cff1_font_dict_interpreter_t; 860 861 typedef CFF1Index CFF1NameIndex; 862 typedef CFF1IndexOf<TopDict> CFF1TopDictIndex; 863 864 struct cff1_font_dict_values_mod_t 865 { cff1_font_dict_values_mod_tCFF::cff1_font_dict_values_mod_t866 cff1_font_dict_values_mod_t() 867 { 868 init(); 869 } 870 initCFF::cff1_font_dict_values_mod_t871 void init() 872 { 873 init(&Null(cff1_font_dict_values_t), CFF_UNDEF_SID); 874 } 875 initCFF::cff1_font_dict_values_mod_t876 void init(const cff1_font_dict_values_t *base_, unsigned int fontName_) 877 { 878 base = base_; 879 fontName = fontName_; 880 privateDictInfo.init(); 881 } 882 get_countCFF::cff1_font_dict_values_mod_t883 unsigned get_count() const 884 { 885 return base->get_count(); 886 } 887 operator []CFF::cff1_font_dict_values_mod_t888 const op_str_t &operator[](unsigned int i) const 889 { 890 return (*base)[i]; 891 } 892 893 const cff1_font_dict_values_t *base; 894 table_info_t privateDictInfo; 895 unsigned int fontName; 896 }; 897 898 struct CFF1FDArray : FDArray<HBUINT16> 899 { 900 }; 901 902 } /* namespace CFF */ 903 904 namespace OT { 905 906 using namespace CFF; 907 908 struct cff1 909 { 910 static constexpr hb_tag_t tableTag = HB_OT_TAG_cff1; 911 sanitizeOT::cff1912 bool sanitize(hb_sanitize_context_t *c) const 913 { 914 TRACE_SANITIZE(this); 915 return_trace(c->check_struct(this) && likely(version.major == 1)); 916 } 917 918 template <typename PRIVOPSET, typename PRIVDICTVAL> struct accelerator_templ_t 919 { initOT::cff1::accelerator_templ_t920 void init(hb_face_t *face) 921 { 922 topDict.init(); 923 fontDicts.init(); 924 privateDicts.init(); 925 926 this->blob = sc.reference_table<cff1>(face); 927 928 /* setup for run-time santization */ 929 sc.init(this->blob); 930 sc.start_processing(); 931 932 const OT::cff1 *cff = this->blob->template as<OT::cff1>(); 933 934 if (cff == &Null(OT::cff1)) { 935 fini(); 936 return; 937 } 938 939 nameIndex = &cff->nameIndex(cff); 940 if ((nameIndex == &Null(CFF1NameIndex)) || !nameIndex->sanitize(&sc)) { 941 fini(); 942 return; 943 } 944 945 topDictIndex = &StructAtOffset<CFF1TopDictIndex>(nameIndex, nameIndex->get_size()); 946 if ((topDictIndex == &Null(CFF1TopDictIndex)) || !topDictIndex->sanitize(&sc) || 947 (topDictIndex->count == 0)) { 948 fini(); 949 return; 950 } 951 952 { /* parse top dict */ 953 const byte_str_t topDictStr = (*topDictIndex)[0]; 954 if (unlikely(!topDictStr.sanitize(&sc))) { 955 fini(); 956 return; 957 } 958 cff1_top_dict_interpreter_t top_interp; 959 top_interp.env.init(topDictStr); 960 topDict.init(); 961 if (unlikely(!top_interp.interpret(topDict))) { 962 fini(); 963 return; 964 } 965 } 966 967 if (is_predef_charset()) 968 charset = &Null(Charset); 969 else { 970 charset = &StructAtOffsetOrNull<Charset>(cff, topDict.CharsetOffset); 971 if (unlikely((charset == &Null(Charset)) || !charset->sanitize(&sc))) { 972 fini(); 973 return; 974 } 975 } 976 977 fdCount = 1; 978 if (is_CID()) { 979 fdArray = &StructAtOffsetOrNull<CFF1FDArray>(cff, topDict.FDArrayOffset); 980 fdSelect = &StructAtOffsetOrNull<CFF1FDSelect>(cff, topDict.FDSelectOffset); 981 if (unlikely((fdArray == &Null(CFF1FDArray)) || !fdArray->sanitize(&sc) || 982 (fdSelect == &Null(CFF1FDSelect)) || !fdSelect->sanitize(&sc, fdArray->count))) { 983 fini(); 984 return; 985 } 986 987 fdCount = fdArray->count; 988 } else { 989 fdArray = &Null(CFF1FDArray); 990 fdSelect = &Null(CFF1FDSelect); 991 } 992 993 encoding = &Null(Encoding); 994 if (is_CID()) { 995 if (unlikely(charset == &Null(Charset))) { 996 fini(); 997 return; 998 } 999 } else { 1000 if (!is_predef_encoding()) { 1001 encoding = &StructAtOffsetOrNull<Encoding>(cff, topDict.EncodingOffset); 1002 if (unlikely((encoding == &Null(Encoding)) || !encoding->sanitize(&sc))) { 1003 fini(); 1004 return; 1005 } 1006 } 1007 } 1008 1009 stringIndex = &StructAtOffset<CFF1StringIndex>(topDictIndex, topDictIndex->get_size()); 1010 if ((stringIndex == &Null(CFF1StringIndex)) || !stringIndex->sanitize(&sc)) { 1011 fini(); 1012 return; 1013 } 1014 1015 globalSubrs = &StructAtOffset<CFF1Subrs>(stringIndex, stringIndex->get_size()); 1016 if ((globalSubrs != &Null(CFF1Subrs)) && !globalSubrs->sanitize(&sc)) { 1017 fini(); 1018 return; 1019 } 1020 1021 charStrings = &StructAtOffsetOrNull<CFF1CharStrings>(cff, topDict.charStringsOffset); 1022 1023 if ((charStrings == &Null(CFF1CharStrings)) || unlikely(!charStrings->sanitize(&sc))) { 1024 fini(); 1025 return; 1026 } 1027 1028 num_glyphs = charStrings->count; 1029 if (num_glyphs != sc.get_num_glyphs()) { 1030 fini(); 1031 return; 1032 } 1033 1034 privateDicts.resize(fdCount); 1035 for (unsigned int i = 0; i < fdCount; i++) 1036 privateDicts[i].init(); 1037 1038 // parse CID font dicts and gather private dicts 1039 if (is_CID()) { 1040 for (unsigned int i = 0; i < fdCount; i++) { 1041 byte_str_t fontDictStr = (*fdArray)[i]; 1042 if (unlikely(!fontDictStr.sanitize(&sc))) { 1043 fini(); 1044 return; 1045 } 1046 cff1_font_dict_values_t *font; 1047 cff1_font_dict_interpreter_t font_interp; 1048 font_interp.env.init(fontDictStr); 1049 font = fontDicts.push(); 1050 if (unlikely(font == &Crap(cff1_font_dict_values_t))) { 1051 fini(); 1052 return; 1053 } 1054 font->init(); 1055 if (unlikely(!font_interp.interpret(*font))) { 1056 fini(); 1057 return; 1058 } 1059 PRIVDICTVAL *priv = &privateDicts[i]; 1060 const byte_str_t privDictStr(StructAtOffset<UnsizedByteStr>(cff, font->privateDictInfo.offset), 1061 font->privateDictInfo.size); 1062 if (unlikely(!privDictStr.sanitize(&sc))) { 1063 fini(); 1064 return; 1065 } 1066 dict_interpreter_t<PRIVOPSET, PRIVDICTVAL> priv_interp; 1067 priv_interp.env.init(privDictStr); 1068 priv->init(); 1069 if (unlikely(!priv_interp.interpret(*priv))) { 1070 fini(); 1071 return; 1072 } 1073 1074 priv->localSubrs = &StructAtOffsetOrNull<CFF1Subrs>(&privDictStr, priv->subrsOffset); 1075 if (priv->localSubrs != &Null(CFF1Subrs) && unlikely(!priv->localSubrs->sanitize(&sc))) { 1076 fini(); 1077 return; 1078 } 1079 } 1080 } else /* non-CID */ 1081 { 1082 cff1_top_dict_values_t *font = &topDict; 1083 PRIVDICTVAL *priv = &privateDicts[0]; 1084 1085 const byte_str_t privDictStr(StructAtOffset<UnsizedByteStr>(cff, font->privateDictInfo.offset), 1086 font->privateDictInfo.size); 1087 if (unlikely(!privDictStr.sanitize(&sc))) { 1088 fini(); 1089 return; 1090 } 1091 dict_interpreter_t<PRIVOPSET, PRIVDICTVAL> priv_interp; 1092 priv_interp.env.init(privDictStr); 1093 priv->init(); 1094 if (unlikely(!priv_interp.interpret(*priv))) { 1095 fini(); 1096 return; 1097 } 1098 1099 priv->localSubrs = &StructAtOffsetOrNull<CFF1Subrs>(&privDictStr, priv->subrsOffset); 1100 if (priv->localSubrs != &Null(CFF1Subrs) && unlikely(!priv->localSubrs->sanitize(&sc))) { 1101 fini(); 1102 return; 1103 } 1104 } 1105 } 1106 finiOT::cff1::accelerator_templ_t1107 void fini() 1108 { 1109 sc.end_processing(); 1110 topDict.fini(); 1111 fontDicts.fini_deep(); 1112 privateDicts.fini_deep(); 1113 hb_blob_destroy(blob); 1114 blob = nullptr; 1115 } 1116 is_validOT::cff1::accelerator_templ_t1117 bool is_valid() const 1118 { 1119 return blob; 1120 } is_CIDOT::cff1::accelerator_templ_t1121 bool is_CID() const 1122 { 1123 return topDict.is_CID(); 1124 } 1125 is_predef_charsetOT::cff1::accelerator_templ_t1126 bool is_predef_charset() const 1127 { 1128 return topDict.CharsetOffset <= ExpertSubsetCharset; 1129 } 1130 std_code_to_glyphOT::cff1::accelerator_templ_t1131 unsigned int std_code_to_glyph(hb_codepoint_t code) const 1132 { 1133 hb_codepoint_t sid = lookup_standard_encoding_for_sid(code); 1134 if (unlikely(sid == CFF_UNDEF_SID)) 1135 return 0; 1136 1137 if (charset != &Null(Charset)) 1138 return charset->get_glyph(sid, num_glyphs); 1139 else if ((topDict.CharsetOffset == ISOAdobeCharset) && (code <= 228 /*zcaron*/)) 1140 return sid; 1141 return 0; 1142 } 1143 is_predef_encodingOT::cff1::accelerator_templ_t1144 bool is_predef_encoding() const 1145 { 1146 return topDict.EncodingOffset <= ExpertEncoding; 1147 } 1148 glyph_to_codeOT::cff1::accelerator_templ_t1149 hb_codepoint_t glyph_to_code(hb_codepoint_t glyph) const 1150 { 1151 if (encoding != &Null(Encoding)) 1152 return encoding->get_code(glyph); 1153 else { 1154 hb_codepoint_t sid = glyph_to_sid(glyph); 1155 if (sid == 0) 1156 return 0; 1157 hb_codepoint_t code = 0; 1158 switch (topDict.EncodingOffset) { 1159 case StandardEncoding: 1160 code = lookup_standard_encoding_for_code(sid); 1161 break; 1162 case ExpertEncoding: 1163 code = lookup_expert_encoding_for_code(sid); 1164 break; 1165 default: 1166 break; 1167 } 1168 return code; 1169 } 1170 } 1171 glyph_to_sidOT::cff1::accelerator_templ_t1172 hb_codepoint_t glyph_to_sid(hb_codepoint_t glyph) const 1173 { 1174 if (charset != &Null(Charset)) 1175 return charset->get_sid(glyph, num_glyphs); 1176 else { 1177 hb_codepoint_t sid = 0; 1178 switch (topDict.CharsetOffset) { 1179 case ISOAdobeCharset: 1180 if (glyph <= 228 /*zcaron*/) 1181 sid = glyph; 1182 break; 1183 case ExpertCharset: 1184 sid = lookup_expert_charset_for_sid(glyph); 1185 break; 1186 case ExpertSubsetCharset: 1187 sid = lookup_expert_subset_charset_for_sid(glyph); 1188 break; 1189 default: 1190 break; 1191 } 1192 return sid; 1193 } 1194 } 1195 sid_to_glyphOT::cff1::accelerator_templ_t1196 hb_codepoint_t sid_to_glyph(hb_codepoint_t sid) const 1197 { 1198 if (charset != &Null(Charset)) 1199 return charset->get_glyph(sid, num_glyphs); 1200 else { 1201 hb_codepoint_t glyph = 0; 1202 switch (topDict.CharsetOffset) { 1203 case ISOAdobeCharset: 1204 if (sid <= 228 /*zcaron*/) 1205 glyph = sid; 1206 break; 1207 case ExpertCharset: 1208 glyph = lookup_expert_charset_for_glyph(sid); 1209 break; 1210 case ExpertSubsetCharset: 1211 glyph = lookup_expert_subset_charset_for_glyph(sid); 1212 break; 1213 default: 1214 break; 1215 } 1216 return glyph; 1217 } 1218 } 1219 1220 protected: 1221 hb_blob_t *blob; 1222 hb_sanitize_context_t sc; 1223 1224 public: 1225 const Encoding *encoding; 1226 const Charset *charset; 1227 const CFF1NameIndex *nameIndex; 1228 const CFF1TopDictIndex *topDictIndex; 1229 const CFF1StringIndex *stringIndex; 1230 const CFF1Subrs *globalSubrs; 1231 const CFF1CharStrings *charStrings; 1232 const CFF1FDArray *fdArray; 1233 const CFF1FDSelect *fdSelect; 1234 unsigned int fdCount; 1235 1236 cff1_top_dict_values_t topDict; 1237 hb_vector_t<cff1_font_dict_values_t> fontDicts; 1238 hb_vector_t<PRIVDICTVAL> privateDicts; 1239 1240 unsigned int num_glyphs; 1241 }; 1242 1243 struct accelerator_t : accelerator_templ_t<cff1_private_dict_opset_t, cff1_private_dict_values_t> 1244 { initOT::cff1::accelerator_t1245 void init(hb_face_t *face) 1246 { 1247 SUPER::init(face); 1248 1249 if (!is_valid()) 1250 return; 1251 if (is_CID()) 1252 return; 1253 1254 /* fill glyph_names */ 1255 for (hb_codepoint_t gid = 0; gid < num_glyphs; gid++) { 1256 hb_codepoint_t sid = glyph_to_sid(gid); 1257 gname_t gname; 1258 gname.sid = sid; 1259 if (sid < cff1_std_strings_length) 1260 gname.name = cff1_std_strings(sid); 1261 else { 1262 byte_str_t ustr = (*stringIndex)[sid - cff1_std_strings_length]; 1263 gname.name = hb_bytes_t((const char *)ustr.arrayZ, ustr.length); 1264 } 1265 if (unlikely(!gname.name.arrayZ)) { 1266 fini(); 1267 return; 1268 } 1269 glyph_names.push(gname); 1270 } 1271 glyph_names.qsort(); 1272 } 1273 finiOT::cff1::accelerator_t1274 void fini() 1275 { 1276 glyph_names.fini(); 1277 1278 SUPER::fini(); 1279 } 1280 get_glyph_nameOT::cff1::accelerator_t1281 bool get_glyph_name(hb_codepoint_t glyph, char *buf, unsigned int buf_len) const 1282 { 1283 if (!buf) 1284 return true; 1285 if (unlikely(!is_valid())) 1286 return false; 1287 if (is_CID()) 1288 return false; 1289 hb_codepoint_t sid = glyph_to_sid(glyph); 1290 const char *str; 1291 size_t str_len; 1292 if (sid < cff1_std_strings_length) { 1293 hb_bytes_t byte_str = cff1_std_strings(sid); 1294 str = byte_str.arrayZ; 1295 str_len = byte_str.length; 1296 } else { 1297 byte_str_t ubyte_str = (*stringIndex)[sid - cff1_std_strings_length]; 1298 str = (const char *)ubyte_str.arrayZ; 1299 str_len = ubyte_str.length; 1300 } 1301 if (!str_len) 1302 return false; 1303 unsigned int len = hb_min(buf_len - 1, str_len); 1304 strncpy(buf, (const char *)str, len); 1305 buf[len] = '\0'; 1306 return true; 1307 } 1308 get_glyph_from_nameOT::cff1::accelerator_t1309 bool get_glyph_from_name(const char *name, int len, hb_codepoint_t *glyph) const 1310 { 1311 if (len < 0) 1312 len = strlen(name); 1313 if (unlikely(!len)) 1314 return false; 1315 1316 gname_t key = {hb_bytes_t(name, len), 0}; 1317 const gname_t *gname = glyph_names.bsearch(key); 1318 if (!gname) 1319 return false; 1320 hb_codepoint_t gid = sid_to_glyph(gname->sid); 1321 if (!gid && gname->sid) 1322 return false; 1323 *glyph = gid; 1324 return true; 1325 } 1326 1327 HB_INTERNAL bool get_extents(hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const; 1328 HB_INTERNAL bool get_seac_components(hb_codepoint_t glyph, hb_codepoint_t *base, hb_codepoint_t *accent) const; 1329 1330 private: 1331 struct gname_t 1332 { 1333 hb_bytes_t name; 1334 uint16_t sid; 1335 cmpOT::cff1::accelerator_t::gname_t1336 static int cmp(const void *a_, const void *b_) 1337 { 1338 const gname_t *a = (const gname_t *)a_; 1339 const gname_t *b = (const gname_t *)b_; 1340 int minlen = hb_min(a->name.length, b->name.length); 1341 int ret = strncmp(a->name.arrayZ, b->name.arrayZ, minlen); 1342 if (ret) 1343 return ret; 1344 return a->name.length - b->name.length; 1345 } 1346 cmpOT::cff1::accelerator_t::gname_t1347 int cmp(const gname_t &a) const 1348 { 1349 return cmp(&a, this); 1350 } 1351 }; 1352 1353 hb_sorted_vector_t<gname_t> glyph_names; 1354 1355 typedef accelerator_templ_t<cff1_private_dict_opset_t, cff1_private_dict_values_t> SUPER; 1356 }; 1357 1358 struct accelerator_subset_t : accelerator_templ_t<cff1_private_dict_opset_subset, cff1_private_dict_values_subset_t> 1359 { 1360 }; 1361 1362 protected: 1363 HB_INTERNAL static hb_codepoint_t lookup_standard_encoding_for_code(hb_codepoint_t sid); 1364 HB_INTERNAL static hb_codepoint_t lookup_expert_encoding_for_code(hb_codepoint_t sid); 1365 HB_INTERNAL static hb_codepoint_t lookup_expert_charset_for_sid(hb_codepoint_t glyph); 1366 HB_INTERNAL static hb_codepoint_t lookup_expert_subset_charset_for_sid(hb_codepoint_t glyph); 1367 HB_INTERNAL static hb_codepoint_t lookup_expert_charset_for_glyph(hb_codepoint_t sid); 1368 HB_INTERNAL static hb_codepoint_t lookup_expert_subset_charset_for_glyph(hb_codepoint_t sid); 1369 HB_INTERNAL static hb_codepoint_t lookup_standard_encoding_for_sid(hb_codepoint_t code); 1370 1371 public: 1372 FixedVersion<HBUINT8> version; /* Version of CFF table. set to 0x0100u */ 1373 OffsetTo<CFF1NameIndex, HBUINT8> nameIndex; /* headerSize = Offset to Name INDEX. */ 1374 HBUINT8 offSize; /* offset size (unused?) */ 1375 1376 public: 1377 DEFINE_SIZE_STATIC(4); 1378 }; 1379 1380 struct cff1_accelerator_t : cff1::accelerator_t 1381 { 1382 }; 1383 } /* namespace OT */ 1384 1385 #endif /* HB_OT_CFF1_TABLE_HH */ 1386