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