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-head-table.hh" 31 #include "hb-ot-cff-common.hh" 32 #include "hb-subset-cff1.hh" 33 34 namespace CFF { 35 36 /* 37 * CFF -- Compact Font Format (CFF) 38 * http://www.adobe.com/content/dam/acom/en/devnet/font/pdfs/5176.CFF.pdf 39 */ 40 #define HB_OT_TAG_cff1 HB_TAG('C','F','F',' ') 41 42 #define CFF_UNDEF_SID CFF_UNDEF_CODE 43 44 enum EncodingID { StandardEncoding = 0, ExpertEncoding = 1 }; 45 enum CharsetID { ISOAdobeCharset = 0, ExpertCharset = 1, ExpertSubsetCharset = 2 }; 46 47 typedef CFFIndex<HBUINT16> CFF1Index; 48 template <typename Type> struct CFF1IndexOf : CFFIndexOf<HBUINT16, Type> {}; 49 50 typedef CFFIndex<HBUINT16> CFF1Index; 51 typedef CFF1Index CFF1CharStrings; 52 typedef FDArray<HBUINT16> CFF1FDArray; 53 typedef Subrs<HBUINT16> CFF1Subrs; 54 55 struct CFF1FDSelect : FDSelect {}; 56 57 /* Encoding */ 58 struct Encoding0 { sanitizeCFF::Encoding059 bool sanitize (hb_sanitize_context_t *c) const 60 { 61 TRACE_SANITIZE (this); 62 return_trace (codes.sanitize (c)); 63 } 64 get_codeCFF::Encoding065 hb_codepoint_t get_code (hb_codepoint_t glyph) const 66 { 67 assert (glyph > 0); 68 glyph--; 69 if (glyph < nCodes ()) 70 { 71 return (hb_codepoint_t)codes[glyph]; 72 } 73 else 74 return CFF_UNDEF_CODE; 75 } 76 nCodesCFF::Encoding077 HBUINT8 &nCodes () { return codes.len; } nCodesCFF::Encoding078 HBUINT8 nCodes () const { return codes.len; } 79 80 ArrayOf<HBUINT8, HBUINT8> codes; 81 82 DEFINE_SIZE_ARRAY_SIZED (1, codes); 83 }; 84 85 struct Encoding1_Range { sanitizeCFF::Encoding1_Range86 bool sanitize (hb_sanitize_context_t *c) const 87 { 88 TRACE_SANITIZE (this); 89 return_trace (c->check_struct (this)); 90 } 91 92 HBUINT8 first; 93 HBUINT8 nLeft; 94 95 DEFINE_SIZE_STATIC (2); 96 }; 97 98 struct Encoding1 { sanitizeCFF::Encoding199 bool sanitize (hb_sanitize_context_t *c) const 100 { 101 TRACE_SANITIZE (this); 102 return_trace (ranges.sanitize (c)); 103 } 104 get_codeCFF::Encoding1105 hb_codepoint_t get_code (hb_codepoint_t glyph) const 106 { 107 assert (glyph > 0); 108 glyph--; 109 for (unsigned int i = 0; i < nRanges (); i++) 110 { 111 if (glyph <= ranges[i].nLeft) 112 { 113 hb_codepoint_t code = (hb_codepoint_t) ranges[i].first + glyph; 114 return (likely (code < 0x100) ? code: CFF_UNDEF_CODE); 115 } 116 glyph -= (ranges[i].nLeft + 1); 117 } 118 return CFF_UNDEF_CODE; 119 } 120 nRangesCFF::Encoding1121 HBUINT8 &nRanges () { return ranges.len; } nRangesCFF::Encoding1122 HBUINT8 nRanges () const { return ranges.len; } 123 124 ArrayOf<Encoding1_Range, HBUINT8> ranges; 125 126 DEFINE_SIZE_ARRAY_SIZED (1, ranges); 127 }; 128 129 struct SuppEncoding { sanitizeCFF::SuppEncoding130 bool sanitize (hb_sanitize_context_t *c) const 131 { 132 TRACE_SANITIZE (this); 133 return_trace (c->check_struct (this)); 134 } 135 136 HBUINT8 code; 137 HBUINT16 glyph; 138 139 DEFINE_SIZE_STATIC (3); 140 }; 141 142 struct CFF1SuppEncData { sanitizeCFF::CFF1SuppEncData143 bool sanitize (hb_sanitize_context_t *c) const 144 { 145 TRACE_SANITIZE (this); 146 return_trace (supps.sanitize (c)); 147 } 148 get_codesCFF::CFF1SuppEncData149 void get_codes (hb_codepoint_t sid, hb_vector_t<hb_codepoint_t> &codes) const 150 { 151 for (unsigned int i = 0; i < nSups (); i++) 152 if (sid == supps[i].glyph) 153 codes.push (supps[i].code); 154 } 155 nSupsCFF::CFF1SuppEncData156 HBUINT8 &nSups () { return supps.len; } nSupsCFF::CFF1SuppEncData157 HBUINT8 nSups () const { return supps.len; } 158 159 ArrayOf<SuppEncoding, HBUINT8> supps; 160 161 DEFINE_SIZE_ARRAY_SIZED (1, supps); 162 }; 163 164 struct Encoding 165 { 166 /* serialize a fullset Encoding */ serializeCFF::Encoding167 bool serialize (hb_serialize_context_t *c, const Encoding &src) 168 { 169 TRACE_SERIALIZE (this); 170 unsigned int size = src.get_size (); 171 Encoding *dest = c->allocate_size<Encoding> (size); 172 if (unlikely (dest == nullptr)) return_trace (false); 173 memcpy (dest, &src, size); 174 return_trace (true); 175 } 176 177 /* serialize a subset Encoding */ serializeCFF::Encoding178 bool serialize (hb_serialize_context_t *c, 179 uint8_t format, 180 unsigned int enc_count, 181 const hb_vector_t<code_pair_t>& code_ranges, 182 const hb_vector_t<code_pair_t>& supp_codes) 183 { 184 TRACE_SERIALIZE (this); 185 Encoding *dest = c->extend_min (*this); 186 if (unlikely (dest == nullptr)) return_trace (false); 187 dest->format = format | ((supp_codes.length > 0) ? 0x80 : 0); 188 switch (format) { 189 case 0: 190 { 191 Encoding0 *fmt0 = c->allocate_size<Encoding0> (Encoding0::min_size + HBUINT8::static_size * enc_count); 192 if (unlikely (fmt0 == nullptr)) return_trace (false); 193 fmt0->nCodes () = enc_count; 194 unsigned int glyph = 0; 195 for (unsigned int i = 0; i < code_ranges.length; i++) 196 { 197 hb_codepoint_t code = code_ranges[i].code; 198 for (int left = (int)code_ranges[i].glyph; left >= 0; left--) 199 fmt0->codes[glyph++] = code++; 200 if (unlikely (!((glyph <= 0x100) && (code <= 0x100)))) 201 return_trace (false); 202 } 203 } 204 break; 205 206 case 1: 207 { 208 Encoding1 *fmt1 = c->allocate_size<Encoding1> (Encoding1::min_size + Encoding1_Range::static_size * code_ranges.length); 209 if (unlikely (fmt1 == nullptr)) return_trace (false); 210 fmt1->nRanges () = code_ranges.length; 211 for (unsigned int i = 0; i < code_ranges.length; i++) 212 { 213 if (unlikely (!((code_ranges[i].code <= 0xFF) && (code_ranges[i].glyph <= 0xFF)))) 214 return_trace (false); 215 fmt1->ranges[i].first = code_ranges[i].code; 216 fmt1->ranges[i].nLeft = code_ranges[i].glyph; 217 } 218 } 219 break; 220 221 } 222 223 if (supp_codes.length) 224 { 225 CFF1SuppEncData *suppData = c->allocate_size<CFF1SuppEncData> (CFF1SuppEncData::min_size + SuppEncoding::static_size * supp_codes.length); 226 if (unlikely (suppData == nullptr)) return_trace (false); 227 suppData->nSups () = supp_codes.length; 228 for (unsigned int i = 0; i < supp_codes.length; i++) 229 { 230 suppData->supps[i].code = supp_codes[i].code; 231 suppData->supps[i].glyph = supp_codes[i].glyph; /* actually SID */ 232 } 233 } 234 235 return_trace (true); 236 } 237 238 /* parallel to above: calculate the size of a subset Encoding */ calculate_serialized_sizeCFF::Encoding239 static unsigned int calculate_serialized_size (uint8_t format, 240 unsigned int enc_count, 241 unsigned int supp_count) 242 { 243 unsigned int size = min_size; 244 switch (format) 245 { 246 case 0: size += Encoding0::min_size + HBUINT8::static_size * enc_count; break; 247 case 1: size += Encoding1::min_size + Encoding1_Range::static_size * enc_count; break; 248 default:return 0; 249 } 250 if (supp_count > 0) 251 size += CFF1SuppEncData::min_size + SuppEncoding::static_size * supp_count; 252 return size; 253 } 254 get_sizeCFF::Encoding255 unsigned int get_size () const 256 { 257 unsigned int size = min_size; 258 switch (table_format ()) 259 { 260 case 0: size += u.format0.get_size (); break; 261 case 1: size += u.format1.get_size (); break; 262 } 263 if (has_supplement ()) 264 size += suppEncData ().get_size (); 265 return size; 266 } 267 get_codeCFF::Encoding268 hb_codepoint_t get_code (hb_codepoint_t glyph) const 269 { 270 switch (table_format ()) 271 { 272 case 0: return u.format0.get_code (glyph); 273 case 1: return u.format1.get_code (glyph); 274 default:return 0; 275 } 276 } 277 table_formatCFF::Encoding278 uint8_t table_format () const { return format & 0x7F; } has_supplementCFF::Encoding279 bool has_supplement () const { return format & 0x80; } 280 get_supplement_codesCFF::Encoding281 void get_supplement_codes (hb_codepoint_t sid, hb_vector_t<hb_codepoint_t> &codes) const 282 { 283 codes.resize (0); 284 if (has_supplement ()) 285 suppEncData().get_codes (sid, codes); 286 } 287 sanitizeCFF::Encoding288 bool sanitize (hb_sanitize_context_t *c) const 289 { 290 TRACE_SANITIZE (this); 291 if (unlikely (!c->check_struct (this))) 292 return_trace (false); 293 294 switch (table_format ()) 295 { 296 case 0: if (unlikely (!u.format0.sanitize (c))) { return_trace (false); } break; 297 case 1: if (unlikely (!u.format1.sanitize (c))) { return_trace (false); } break; 298 default:return_trace (false); 299 } 300 return_trace (likely (!has_supplement () || suppEncData ().sanitize (c))); 301 } 302 303 protected: suppEncDataCFF::Encoding304 const CFF1SuppEncData &suppEncData () const 305 { 306 switch (table_format ()) 307 { 308 case 0: return StructAfter<CFF1SuppEncData> (u.format0.codes[u.format0.nCodes ()-1]); 309 case 1: return StructAfter<CFF1SuppEncData> (u.format1.ranges[u.format1.nRanges ()-1]); 310 default:return Null (CFF1SuppEncData); 311 } 312 } 313 314 public: 315 HBUINT8 format; 316 union { 317 Encoding0 format0; 318 Encoding1 format1; 319 } u; 320 /* CFF1SuppEncData suppEncData; */ 321 322 DEFINE_SIZE_MIN (1); 323 }; 324 325 /* Charset */ 326 struct Charset0 { sanitizeCFF::Charset0327 bool sanitize (hb_sanitize_context_t *c, unsigned int num_glyphs) const 328 { 329 TRACE_SANITIZE (this); 330 return_trace (c->check_struct (this) && sids[num_glyphs - 1].sanitize (c)); 331 } 332 get_sidCFF::Charset0333 hb_codepoint_t get_sid (hb_codepoint_t glyph) const 334 { 335 if (glyph == 0) 336 return 0; 337 else 338 return sids[glyph - 1]; 339 } 340 get_glyphCFF::Charset0341 hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const 342 { 343 if (sid == 0) 344 return 0; 345 346 for (unsigned int glyph = 1; glyph < num_glyphs; glyph++) 347 { 348 if (sids[glyph-1] == sid) 349 return glyph; 350 } 351 return 0; 352 } 353 get_sizeCFF::Charset0354 unsigned int get_size (unsigned int num_glyphs) const 355 { 356 assert (num_glyphs > 0); 357 return HBUINT16::static_size * (num_glyphs - 1); 358 } 359 360 HBUINT16 sids[HB_VAR_ARRAY]; 361 362 DEFINE_SIZE_ARRAY(0, sids); 363 }; 364 365 template <typename TYPE> 366 struct Charset_Range { sanitizeCFF::Charset_Range367 bool sanitize (hb_sanitize_context_t *c) const 368 { 369 TRACE_SANITIZE (this); 370 return_trace (c->check_struct (this)); 371 } 372 373 HBUINT16 first; 374 TYPE nLeft; 375 376 DEFINE_SIZE_STATIC (HBUINT16::static_size + TYPE::static_size); 377 }; 378 379 template <typename TYPE> 380 struct Charset1_2 { sanitizeCFF::Charset1_2381 bool sanitize (hb_sanitize_context_t *c, unsigned int num_glyphs) const 382 { 383 TRACE_SANITIZE (this); 384 if (unlikely (!c->check_struct (this))) 385 return_trace (false); 386 num_glyphs--; 387 for (unsigned int i = 0; num_glyphs > 0; i++) 388 { 389 if (unlikely (!ranges[i].sanitize (c) || (num_glyphs < ranges[i].nLeft + 1))) 390 return_trace (false); 391 num_glyphs -= (ranges[i].nLeft + 1); 392 } 393 return_trace (true); 394 } 395 get_sidCFF::Charset1_2396 hb_codepoint_t get_sid (hb_codepoint_t glyph) const 397 { 398 if (glyph == 0) return 0; 399 glyph--; 400 for (unsigned int i = 0;; i++) 401 { 402 if (glyph <= ranges[i].nLeft) 403 return (hb_codepoint_t)ranges[i].first + glyph; 404 glyph -= (ranges[i].nLeft + 1); 405 } 406 407 return 0; 408 } 409 get_glyphCFF::Charset1_2410 hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const 411 { 412 if (sid == 0) return 0; 413 hb_codepoint_t glyph = 1; 414 for (unsigned int i = 0;; i++) 415 { 416 if (glyph >= num_glyphs) 417 return 0; 418 if ((ranges[i].first <= sid) && (sid <= ranges[i].first + ranges[i].nLeft)) 419 return glyph + (sid - ranges[i].first); 420 glyph += (ranges[i].nLeft + 1); 421 } 422 423 return 0; 424 } 425 get_sizeCFF::Charset1_2426 unsigned int get_size (unsigned int num_glyphs) const 427 { 428 unsigned int size = HBUINT8::static_size; 429 int glyph = (int)num_glyphs; 430 431 assert (glyph > 0); 432 glyph--; 433 for (unsigned int i = 0; glyph > 0; i++) 434 { 435 glyph -= (ranges[i].nLeft + 1); 436 size += Charset_Range<TYPE>::static_size; 437 } 438 439 return size; 440 } 441 442 Charset_Range<TYPE> ranges[HB_VAR_ARRAY]; 443 444 DEFINE_SIZE_ARRAY (0, ranges); 445 }; 446 447 typedef Charset1_2<HBUINT8> Charset1; 448 typedef Charset1_2<HBUINT16> Charset2; 449 typedef Charset_Range<HBUINT8> Charset1_Range; 450 typedef Charset_Range<HBUINT16> Charset2_Range; 451 452 struct Charset 453 { 454 /* serialize a fullset Charset */ serializeCFF::Charset455 bool serialize (hb_serialize_context_t *c, const Charset &src, unsigned int num_glyphs) 456 { 457 TRACE_SERIALIZE (this); 458 unsigned int size = src.get_size (num_glyphs); 459 Charset *dest = c->allocate_size<Charset> (size); 460 if (unlikely (dest == nullptr)) return_trace (false); 461 memcpy (dest, &src, size); 462 return_trace (true); 463 } 464 465 /* serialize a subset Charset */ serializeCFF::Charset466 bool serialize (hb_serialize_context_t *c, 467 uint8_t format, 468 unsigned int num_glyphs, 469 const hb_vector_t<code_pair_t>& sid_ranges) 470 { 471 TRACE_SERIALIZE (this); 472 Charset *dest = c->extend_min (*this); 473 if (unlikely (dest == nullptr)) return_trace (false); 474 dest->format = format; 475 switch (format) 476 { 477 case 0: 478 { 479 Charset0 *fmt0 = c->allocate_size<Charset0> (Charset0::min_size + HBUINT16::static_size * (num_glyphs - 1)); 480 if (unlikely (fmt0 == nullptr)) return_trace (false); 481 unsigned int glyph = 0; 482 for (unsigned int i = 0; i < sid_ranges.length; i++) 483 { 484 hb_codepoint_t sid = sid_ranges[i].code; 485 for (int left = (int)sid_ranges[i].glyph; left >= 0; left--) 486 fmt0->sids[glyph++] = sid++; 487 } 488 } 489 break; 490 491 case 1: 492 { 493 Charset1 *fmt1 = c->allocate_size<Charset1> (Charset1::min_size + Charset1_Range::static_size * sid_ranges.length); 494 if (unlikely (fmt1 == nullptr)) return_trace (false); 495 for (unsigned int i = 0; i < sid_ranges.length; i++) 496 { 497 if (unlikely (!(sid_ranges[i].glyph <= 0xFF))) 498 return_trace (false); 499 fmt1->ranges[i].first = sid_ranges[i].code; 500 fmt1->ranges[i].nLeft = sid_ranges[i].glyph; 501 } 502 } 503 break; 504 505 case 2: 506 { 507 Charset2 *fmt2 = c->allocate_size<Charset2> (Charset2::min_size + Charset2_Range::static_size * sid_ranges.length); 508 if (unlikely (fmt2 == nullptr)) return_trace (false); 509 for (unsigned int i = 0; i < sid_ranges.length; i++) 510 { 511 if (unlikely (!(sid_ranges[i].glyph <= 0xFFFF))) 512 return_trace (false); 513 fmt2->ranges[i].first = sid_ranges[i].code; 514 fmt2->ranges[i].nLeft = sid_ranges[i].glyph; 515 } 516 } 517 break; 518 519 } 520 return_trace (true); 521 } 522 523 /* parallel to above: calculate the size of a subset Charset */ calculate_serialized_sizeCFF::Charset524 static unsigned int calculate_serialized_size (uint8_t format, 525 unsigned int count) 526 { 527 switch (format) 528 { 529 case 0: return min_size + Charset0::min_size + HBUINT16::static_size * (count - 1); 530 case 1: return min_size + Charset1::min_size + Charset1_Range::static_size * count; 531 case 2: return min_size + Charset2::min_size + Charset2_Range::static_size * count; 532 default:return 0; 533 } 534 } 535 get_sizeCFF::Charset536 unsigned int get_size (unsigned int num_glyphs) const 537 { 538 switch (format) 539 { 540 case 0: return min_size + u.format0.get_size (num_glyphs); 541 case 1: return min_size + u.format1.get_size (num_glyphs); 542 case 2: return min_size + u.format2.get_size (num_glyphs); 543 default:return 0; 544 } 545 } 546 get_sidCFF::Charset547 hb_codepoint_t get_sid (hb_codepoint_t glyph) const 548 { 549 switch (format) 550 { 551 case 0: return u.format0.get_sid (glyph); 552 case 1: return u.format1.get_sid (glyph); 553 case 2: return u.format2.get_sid (glyph); 554 default:return 0; 555 } 556 } 557 get_glyphCFF::Charset558 hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const 559 { 560 switch (format) 561 { 562 case 0: return u.format0.get_glyph (sid, num_glyphs); 563 case 1: return u.format1.get_glyph (sid, num_glyphs); 564 case 2: return u.format2.get_glyph (sid, num_glyphs); 565 default:return 0; 566 } 567 } 568 sanitizeCFF::Charset569 bool sanitize (hb_sanitize_context_t *c) const 570 { 571 TRACE_SANITIZE (this); 572 if (unlikely (!c->check_struct (this))) 573 return_trace (false); 574 575 switch (format) 576 { 577 case 0: return_trace (u.format0.sanitize (c, c->get_num_glyphs ())); 578 case 1: return_trace (u.format1.sanitize (c, c->get_num_glyphs ())); 579 case 2: return_trace (u.format2.sanitize (c, c->get_num_glyphs ())); 580 default:return_trace (false); 581 } 582 } 583 584 HBUINT8 format; 585 union { 586 Charset0 format0; 587 Charset1 format1; 588 Charset2 format2; 589 } u; 590 591 DEFINE_SIZE_MIN (1); 592 }; 593 594 struct CFF1StringIndex : CFF1Index 595 { serializeCFF::CFF1StringIndex596 bool serialize (hb_serialize_context_t *c, const CFF1StringIndex &strings, 597 unsigned int offSize_, const hb_inc_bimap_t &sidmap) 598 { 599 TRACE_SERIALIZE (this); 600 if (unlikely ((strings.count == 0) || (sidmap.get_population () == 0))) 601 { 602 if (unlikely (!c->extend_min (this->count))) 603 return_trace (false); 604 count = 0; 605 return_trace (true); 606 } 607 608 byte_str_array_t bytesArray; 609 bytesArray.init (); 610 if (!bytesArray.resize (sidmap.get_population ())) 611 return_trace (false); 612 for (unsigned int i = 0; i < strings.count; i++) 613 { 614 hb_codepoint_t j = sidmap[i]; 615 if (j != CFF_UNDEF_CODE) 616 bytesArray[j] = strings[i]; 617 } 618 619 bool result = CFF1Index::serialize (c, offSize_, bytesArray); 620 bytesArray.fini (); 621 return_trace (result); 622 } 623 624 /* in parallel to above */ calculate_serialized_sizeCFF::CFF1StringIndex625 unsigned int calculate_serialized_size (unsigned int &offSize_ /*OUT*/, const hb_inc_bimap_t &sidmap) const 626 { 627 offSize_ = 0; 628 if ((count == 0) || (sidmap.get_population () == 0)) 629 return count.static_size; 630 631 unsigned int dataSize = 0; 632 for (unsigned int i = 0; i < count; i++) 633 if (sidmap[i] != CFF_UNDEF_CODE) 634 dataSize += length_at (i); 635 636 offSize_ = calcOffSize(dataSize); 637 return CFF1Index::calculate_serialized_size (offSize_, sidmap.get_population (), dataSize); 638 } 639 }; 640 641 struct cff1_top_dict_interp_env_t : num_interp_env_t 642 { cff1_top_dict_interp_env_tCFF::cff1_top_dict_interp_env_t643 cff1_top_dict_interp_env_t () 644 : num_interp_env_t(), prev_offset(0), last_offset(0) {} 645 646 unsigned int prev_offset; 647 unsigned int last_offset; 648 }; 649 650 struct name_dict_values_t 651 { 652 enum name_dict_val_index_t 653 { 654 version, 655 notice, 656 copyright, 657 fullName, 658 familyName, 659 weight, 660 postscript, 661 fontName, 662 baseFontName, 663 registry, 664 ordering, 665 666 ValCount 667 }; 668 initCFF::name_dict_values_t669 void init () 670 { 671 for (unsigned int i = 0; i < ValCount; i++) 672 values[i] = CFF_UNDEF_SID; 673 } 674 operator []CFF::name_dict_values_t675 unsigned int& operator[] (unsigned int i) 676 { assert (i < ValCount); return values[i]; } 677 operator []CFF::name_dict_values_t678 unsigned int operator[] (unsigned int i) const 679 { assert (i < ValCount); return values[i]; } 680 name_op_to_indexCFF::name_dict_values_t681 static enum name_dict_val_index_t name_op_to_index (op_code_t op) 682 { 683 switch (op) { 684 default: // can't happen - just make some compiler happy 685 case OpCode_version: 686 return version; 687 case OpCode_Notice: 688 return notice; 689 case OpCode_Copyright: 690 return copyright; 691 case OpCode_FullName: 692 return fullName; 693 case OpCode_FamilyName: 694 return familyName; 695 case OpCode_Weight: 696 return weight; 697 case OpCode_PostScript: 698 return postscript; 699 case OpCode_FontName: 700 return fontName; 701 case OpCode_BaseFontName: 702 return baseFontName; 703 } 704 } 705 706 unsigned int values[ValCount]; 707 }; 708 709 struct cff1_top_dict_val_t : op_str_t 710 { 711 unsigned int last_arg_offset; 712 }; 713 714 struct cff1_top_dict_values_t : top_dict_values_t<cff1_top_dict_val_t> 715 { initCFF::cff1_top_dict_values_t716 void init () 717 { 718 top_dict_values_t<cff1_top_dict_val_t>::init (); 719 720 nameSIDs.init (); 721 ros_supplement = 0; 722 cidCount = 8720; 723 EncodingOffset = 0; 724 CharsetOffset = 0; 725 FDSelectOffset = 0; 726 privateDictInfo.init (); 727 } finiCFF::cff1_top_dict_values_t728 void fini () { top_dict_values_t<cff1_top_dict_val_t>::fini (); } 729 is_CIDCFF::cff1_top_dict_values_t730 bool is_CID () const 731 { return nameSIDs[name_dict_values_t::registry] != CFF_UNDEF_SID; } 732 733 name_dict_values_t nameSIDs; 734 unsigned int ros_supplement_offset; 735 unsigned int ros_supplement; 736 unsigned int cidCount; 737 738 unsigned int EncodingOffset; 739 unsigned int CharsetOffset; 740 unsigned int FDSelectOffset; 741 table_info_t privateDictInfo; 742 }; 743 744 struct cff1_top_dict_opset_t : top_dict_opset_t<cff1_top_dict_val_t> 745 { process_opCFF::cff1_top_dict_opset_t746 static void process_op (op_code_t op, cff1_top_dict_interp_env_t& env, cff1_top_dict_values_t& dictval) 747 { 748 cff1_top_dict_val_t val; 749 val.last_arg_offset = (env.last_offset-1) - dictval.opStart; /* offset to the last argument */ 750 751 switch (op) { 752 case OpCode_version: 753 case OpCode_Notice: 754 case OpCode_Copyright: 755 case OpCode_FullName: 756 case OpCode_FamilyName: 757 case OpCode_Weight: 758 case OpCode_PostScript: 759 case OpCode_BaseFontName: 760 dictval.nameSIDs[name_dict_values_t::name_op_to_index (op)] = env.argStack.pop_uint (); 761 env.clear_args (); 762 break; 763 case OpCode_isFixedPitch: 764 case OpCode_ItalicAngle: 765 case OpCode_UnderlinePosition: 766 case OpCode_UnderlineThickness: 767 case OpCode_PaintType: 768 case OpCode_CharstringType: 769 case OpCode_UniqueID: 770 case OpCode_StrokeWidth: 771 case OpCode_SyntheticBase: 772 case OpCode_CIDFontVersion: 773 case OpCode_CIDFontRevision: 774 case OpCode_CIDFontType: 775 case OpCode_UIDBase: 776 case OpCode_FontBBox: 777 case OpCode_XUID: 778 case OpCode_BaseFontBlend: 779 env.clear_args (); 780 break; 781 782 case OpCode_CIDCount: 783 dictval.cidCount = env.argStack.pop_uint (); 784 env.clear_args (); 785 break; 786 787 case OpCode_ROS: 788 dictval.ros_supplement = env.argStack.pop_uint (); 789 dictval.nameSIDs[name_dict_values_t::ordering] = env.argStack.pop_uint (); 790 dictval.nameSIDs[name_dict_values_t::registry] = env.argStack.pop_uint (); 791 env.clear_args (); 792 break; 793 794 case OpCode_Encoding: 795 dictval.EncodingOffset = env.argStack.pop_uint (); 796 env.clear_args (); 797 if (unlikely (dictval.EncodingOffset == 0)) return; 798 break; 799 800 case OpCode_charset: 801 dictval.CharsetOffset = env.argStack.pop_uint (); 802 env.clear_args (); 803 if (unlikely (dictval.CharsetOffset == 0)) return; 804 break; 805 806 case OpCode_FDSelect: 807 dictval.FDSelectOffset = env.argStack.pop_uint (); 808 env.clear_args (); 809 break; 810 811 case OpCode_Private: 812 dictval.privateDictInfo.offset = env.argStack.pop_uint (); 813 dictval.privateDictInfo.size = env.argStack.pop_uint (); 814 env.clear_args (); 815 break; 816 817 default: 818 env.last_offset = env.str_ref.offset; 819 top_dict_opset_t<cff1_top_dict_val_t>::process_op (op, env, dictval); 820 /* Record this operand below if stack is empty, otherwise done */ 821 if (!env.argStack.is_empty ()) return; 822 break; 823 } 824 825 if (unlikely (env.in_error ())) return; 826 827 dictval.add_op (op, env.str_ref, val); 828 } 829 }; 830 831 struct cff1_font_dict_values_t : dict_values_t<op_str_t> 832 { initCFF::cff1_font_dict_values_t833 void init () 834 { 835 dict_values_t<op_str_t>::init (); 836 privateDictInfo.init (); 837 fontName = CFF_UNDEF_SID; 838 } finiCFF::cff1_font_dict_values_t839 void fini () { dict_values_t<op_str_t>::fini (); } 840 841 table_info_t privateDictInfo; 842 unsigned int fontName; 843 }; 844 845 struct cff1_font_dict_opset_t : dict_opset_t 846 { process_opCFF::cff1_font_dict_opset_t847 static void process_op (op_code_t op, num_interp_env_t& env, cff1_font_dict_values_t& dictval) 848 { 849 switch (op) { 850 case OpCode_FontName: 851 dictval.fontName = env.argStack.pop_uint (); 852 env.clear_args (); 853 break; 854 case OpCode_FontMatrix: 855 case OpCode_PaintType: 856 env.clear_args (); 857 break; 858 case OpCode_Private: 859 dictval.privateDictInfo.offset = env.argStack.pop_uint (); 860 dictval.privateDictInfo.size = env.argStack.pop_uint (); 861 env.clear_args (); 862 break; 863 864 default: 865 dict_opset_t::process_op (op, env); 866 if (!env.argStack.is_empty ()) return; 867 break; 868 } 869 870 if (unlikely (env.in_error ())) return; 871 872 dictval.add_op (op, env.str_ref); 873 } 874 }; 875 876 template <typename VAL> 877 struct cff1_private_dict_values_base_t : dict_values_t<VAL> 878 { initCFF::cff1_private_dict_values_base_t879 void init () 880 { 881 dict_values_t<VAL>::init (); 882 subrsOffset = 0; 883 localSubrs = &Null(CFF1Subrs); 884 } finiCFF::cff1_private_dict_values_base_t885 void fini () { dict_values_t<VAL>::fini (); } 886 calculate_serialized_sizeCFF::cff1_private_dict_values_base_t887 unsigned int calculate_serialized_size () const 888 { 889 unsigned int size = 0; 890 for (unsigned int i = 0; i < dict_values_t<VAL>::get_count; i++) 891 if (dict_values_t<VAL>::get_value (i).op == OpCode_Subrs) 892 size += OpCode_Size (OpCode_shortint) + 2 + OpCode_Size (OpCode_Subrs); 893 else 894 size += dict_values_t<VAL>::get_value (i).str.length; 895 return size; 896 } 897 898 unsigned int subrsOffset; 899 const CFF1Subrs *localSubrs; 900 }; 901 902 typedef cff1_private_dict_values_base_t<op_str_t> cff1_private_dict_values_subset_t; 903 typedef cff1_private_dict_values_base_t<num_dict_val_t> cff1_private_dict_values_t; 904 905 struct cff1_private_dict_opset_t : dict_opset_t 906 { process_opCFF::cff1_private_dict_opset_t907 static void process_op (op_code_t op, num_interp_env_t& env, cff1_private_dict_values_t& dictval) 908 { 909 num_dict_val_t val; 910 val.init (); 911 912 switch (op) { 913 case OpCode_BlueValues: 914 case OpCode_OtherBlues: 915 case OpCode_FamilyBlues: 916 case OpCode_FamilyOtherBlues: 917 case OpCode_StemSnapH: 918 case OpCode_StemSnapV: 919 env.clear_args (); 920 break; 921 case OpCode_StdHW: 922 case OpCode_StdVW: 923 case OpCode_BlueScale: 924 case OpCode_BlueShift: 925 case OpCode_BlueFuzz: 926 case OpCode_ForceBold: 927 case OpCode_LanguageGroup: 928 case OpCode_ExpansionFactor: 929 case OpCode_initialRandomSeed: 930 case OpCode_defaultWidthX: 931 case OpCode_nominalWidthX: 932 val.single_val = env.argStack.pop_num (); 933 env.clear_args (); 934 break; 935 case OpCode_Subrs: 936 dictval.subrsOffset = env.argStack.pop_uint (); 937 env.clear_args (); 938 break; 939 940 default: 941 dict_opset_t::process_op (op, env); 942 if (!env.argStack.is_empty ()) return; 943 break; 944 } 945 946 if (unlikely (env.in_error ())) return; 947 948 dictval.add_op (op, env.str_ref, val); 949 } 950 }; 951 952 struct cff1_private_dict_opset_subset : dict_opset_t 953 { process_opCFF::cff1_private_dict_opset_subset954 static void process_op (op_code_t op, num_interp_env_t& env, cff1_private_dict_values_subset_t& dictval) 955 { 956 switch (op) { 957 case OpCode_BlueValues: 958 case OpCode_OtherBlues: 959 case OpCode_FamilyBlues: 960 case OpCode_FamilyOtherBlues: 961 case OpCode_StemSnapH: 962 case OpCode_StemSnapV: 963 case OpCode_StdHW: 964 case OpCode_StdVW: 965 case OpCode_BlueScale: 966 case OpCode_BlueShift: 967 case OpCode_BlueFuzz: 968 case OpCode_ForceBold: 969 case OpCode_LanguageGroup: 970 case OpCode_ExpansionFactor: 971 case OpCode_initialRandomSeed: 972 case OpCode_defaultWidthX: 973 case OpCode_nominalWidthX: 974 env.clear_args (); 975 break; 976 977 case OpCode_Subrs: 978 dictval.subrsOffset = env.argStack.pop_uint (); 979 env.clear_args (); 980 break; 981 982 default: 983 dict_opset_t::process_op (op, env); 984 if (!env.argStack.is_empty ()) return; 985 break; 986 } 987 988 if (unlikely (env.in_error ())) return; 989 990 dictval.add_op (op, env.str_ref); 991 } 992 }; 993 994 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; 995 typedef dict_interpreter_t<cff1_font_dict_opset_t, cff1_font_dict_values_t> cff1_font_dict_interpreter_t; 996 997 typedef CFF1Index CFF1NameIndex; 998 typedef CFF1IndexOf<TopDict> CFF1TopDictIndex; 999 1000 } /* namespace CFF */ 1001 1002 namespace OT { 1003 1004 using namespace CFF; 1005 1006 struct cff1 1007 { 1008 static constexpr hb_tag_t tableTag = HB_OT_TAG_cff1; 1009 sanitizeOT::cff11010 bool sanitize (hb_sanitize_context_t *c) const 1011 { 1012 TRACE_SANITIZE (this); 1013 return_trace (c->check_struct (this) && 1014 likely (version.major == 1)); 1015 } 1016 1017 template <typename PRIVOPSET, typename PRIVDICTVAL> 1018 struct accelerator_templ_t 1019 { initOT::cff1::accelerator_templ_t1020 void init (hb_face_t *face) 1021 { 1022 topDict.init (); 1023 fontDicts.init (); 1024 privateDicts.init (); 1025 1026 this->blob = sc.reference_table<cff1> (face); 1027 1028 /* setup for run-time santization */ 1029 sc.init (this->blob); 1030 sc.start_processing (); 1031 1032 const OT::cff1 *cff = this->blob->template as<OT::cff1> (); 1033 1034 if (cff == &Null(OT::cff1)) 1035 { fini (); return; } 1036 1037 nameIndex = &cff->nameIndex (cff); 1038 if ((nameIndex == &Null (CFF1NameIndex)) || !nameIndex->sanitize (&sc)) 1039 { fini (); return; } 1040 1041 topDictIndex = &StructAtOffset<CFF1TopDictIndex> (nameIndex, nameIndex->get_size ()); 1042 if ((topDictIndex == &Null (CFF1TopDictIndex)) || !topDictIndex->sanitize (&sc) || (topDictIndex->count == 0)) 1043 { fini (); return; } 1044 1045 { /* parse top dict */ 1046 const byte_str_t topDictStr = (*topDictIndex)[0]; 1047 if (unlikely (!topDictStr.sanitize (&sc))) { fini (); return; } 1048 cff1_top_dict_interpreter_t top_interp; 1049 top_interp.env.init (topDictStr); 1050 topDict.init (); 1051 if (unlikely (!top_interp.interpret (topDict))) { fini (); return; } 1052 } 1053 1054 if (is_predef_charset ()) 1055 charset = &Null(Charset); 1056 else 1057 { 1058 charset = &StructAtOffsetOrNull<Charset> (cff, topDict.CharsetOffset); 1059 if (unlikely ((charset == &Null (Charset)) || !charset->sanitize (&sc))) { fini (); return; } 1060 } 1061 1062 fdCount = 1; 1063 if (is_CID ()) 1064 { 1065 fdArray = &StructAtOffsetOrNull<CFF1FDArray> (cff, topDict.FDArrayOffset); 1066 fdSelect = &StructAtOffsetOrNull<CFF1FDSelect> (cff, topDict.FDSelectOffset); 1067 if (unlikely ((fdArray == &Null(CFF1FDArray)) || !fdArray->sanitize (&sc) || 1068 (fdSelect == &Null(CFF1FDSelect)) || !fdSelect->sanitize (&sc, fdArray->count))) 1069 { fini (); return; } 1070 1071 fdCount = fdArray->count; 1072 } 1073 else 1074 { 1075 fdArray = &Null(CFF1FDArray); 1076 fdSelect = &Null(CFF1FDSelect); 1077 } 1078 1079 stringIndex = &StructAtOffset<CFF1StringIndex> (topDictIndex, topDictIndex->get_size ()); 1080 if ((stringIndex == &Null (CFF1StringIndex)) || !stringIndex->sanitize (&sc)) 1081 { fini (); return; } 1082 1083 globalSubrs = &StructAtOffset<CFF1Subrs> (stringIndex, stringIndex->get_size ()); 1084 if ((globalSubrs != &Null (CFF1Subrs)) && !globalSubrs->sanitize (&sc)) 1085 { fini (); return; } 1086 1087 charStrings = &StructAtOffsetOrNull<CFF1CharStrings> (cff, topDict.charStringsOffset); 1088 1089 if ((charStrings == &Null(CFF1CharStrings)) || unlikely (!charStrings->sanitize (&sc))) 1090 { fini (); return; } 1091 1092 num_glyphs = charStrings->count; 1093 if (num_glyphs != sc.get_num_glyphs ()) 1094 { fini (); return; } 1095 1096 privateDicts.resize (fdCount); 1097 for (unsigned int i = 0; i < fdCount; i++) 1098 privateDicts[i].init (); 1099 1100 // parse CID font dicts and gather private dicts 1101 if (is_CID ()) 1102 { 1103 for (unsigned int i = 0; i < fdCount; i++) 1104 { 1105 byte_str_t fontDictStr = (*fdArray)[i]; 1106 if (unlikely (!fontDictStr.sanitize (&sc))) { fini (); return; } 1107 cff1_font_dict_values_t *font; 1108 cff1_font_dict_interpreter_t font_interp; 1109 font_interp.env.init (fontDictStr); 1110 font = fontDicts.push (); 1111 if (unlikely (font == &Crap(cff1_font_dict_values_t))) { fini (); return; } 1112 font->init (); 1113 if (unlikely (!font_interp.interpret (*font))) { fini (); return; } 1114 PRIVDICTVAL *priv = &privateDicts[i]; 1115 const byte_str_t privDictStr (StructAtOffset<UnsizedByteStr> (cff, font->privateDictInfo.offset), font->privateDictInfo.size); 1116 if (unlikely (!privDictStr.sanitize (&sc))) { fini (); return; } 1117 dict_interpreter_t<PRIVOPSET, PRIVDICTVAL> priv_interp; 1118 priv_interp.env.init (privDictStr); 1119 priv->init (); 1120 if (unlikely (!priv_interp.interpret (*priv))) { fini (); return; } 1121 1122 priv->localSubrs = &StructAtOffsetOrNull<CFF1Subrs> (&privDictStr, priv->subrsOffset); 1123 if (priv->localSubrs != &Null(CFF1Subrs) && 1124 unlikely (!priv->localSubrs->sanitize (&sc))) 1125 { fini (); return; } 1126 } 1127 } 1128 else /* non-CID */ 1129 { 1130 cff1_top_dict_values_t *font = &topDict; 1131 PRIVDICTVAL *priv = &privateDicts[0]; 1132 1133 const byte_str_t privDictStr (StructAtOffset<UnsizedByteStr> (cff, font->privateDictInfo.offset), font->privateDictInfo.size); 1134 if (unlikely (!privDictStr.sanitize (&sc))) { fini (); return; } 1135 dict_interpreter_t<PRIVOPSET, PRIVDICTVAL> priv_interp; 1136 priv_interp.env.init (privDictStr); 1137 priv->init (); 1138 if (unlikely (!priv_interp.interpret (*priv))) { fini (); return; } 1139 1140 priv->localSubrs = &StructAtOffsetOrNull<CFF1Subrs> (&privDictStr, priv->subrsOffset); 1141 if (priv->localSubrs != &Null(CFF1Subrs) && 1142 unlikely (!priv->localSubrs->sanitize (&sc))) 1143 { fini (); return; } 1144 } 1145 } 1146 finiOT::cff1::accelerator_templ_t1147 void fini () 1148 { 1149 sc.end_processing (); 1150 topDict.fini (); 1151 fontDicts.fini_deep (); 1152 privateDicts.fini_deep (); 1153 hb_blob_destroy (blob); 1154 blob = nullptr; 1155 } 1156 is_validOT::cff1::accelerator_templ_t1157 bool is_valid () const { return blob != nullptr; } is_CIDOT::cff1::accelerator_templ_t1158 bool is_CID () const { return topDict.is_CID (); } 1159 is_predef_charsetOT::cff1::accelerator_templ_t1160 bool is_predef_charset () const { return topDict.CharsetOffset <= ExpertSubsetCharset; } 1161 std_code_to_glyphOT::cff1::accelerator_templ_t1162 unsigned int std_code_to_glyph (hb_codepoint_t code) const 1163 { 1164 hb_codepoint_t sid = lookup_standard_encoding_for_sid (code); 1165 if (unlikely (sid == CFF_UNDEF_SID)) 1166 return 0; 1167 1168 if (charset != &Null(Charset)) 1169 return charset->get_glyph (sid, num_glyphs); 1170 else if ((topDict.CharsetOffset == ISOAdobeCharset) 1171 && (code <= 228 /*zcaron*/)) return sid; 1172 return 0; 1173 } 1174 1175 protected: 1176 hb_blob_t *blob; 1177 hb_sanitize_context_t sc; 1178 1179 public: 1180 const Charset *charset; 1181 const CFF1NameIndex *nameIndex; 1182 const CFF1TopDictIndex *topDictIndex; 1183 const CFF1StringIndex *stringIndex; 1184 const CFF1Subrs *globalSubrs; 1185 const CFF1CharStrings *charStrings; 1186 const CFF1FDArray *fdArray; 1187 const CFF1FDSelect *fdSelect; 1188 unsigned int fdCount; 1189 1190 cff1_top_dict_values_t topDict; 1191 hb_vector_t<cff1_font_dict_values_t> fontDicts; 1192 hb_vector_t<PRIVDICTVAL> privateDicts; 1193 1194 unsigned int num_glyphs; 1195 }; 1196 1197 struct accelerator_t : accelerator_templ_t<cff1_private_dict_opset_t, cff1_private_dict_values_t> 1198 { 1199 HB_INTERNAL bool get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const; 1200 HB_INTERNAL bool get_seac_components (hb_codepoint_t glyph, hb_codepoint_t *base, hb_codepoint_t *accent) const; 1201 }; 1202 1203 struct accelerator_subset_t : accelerator_templ_t<cff1_private_dict_opset_subset, cff1_private_dict_values_subset_t> 1204 { initOT::cff1::accelerator_subset_t1205 void init (hb_face_t *face) 1206 { 1207 SUPER::init (face); 1208 if (blob == nullptr) return; 1209 1210 const OT::cff1 *cff = this->blob->as<OT::cff1> (); 1211 encoding = &Null(Encoding); 1212 if (is_CID ()) 1213 { 1214 if (unlikely (charset == &Null(Charset))) { fini (); return; } 1215 } 1216 else 1217 { 1218 if (!is_predef_encoding ()) 1219 { 1220 encoding = &StructAtOffsetOrNull<Encoding> (cff, topDict.EncodingOffset); 1221 if (unlikely ((encoding == &Null (Encoding)) || !encoding->sanitize (&sc))) { fini (); return; } 1222 } 1223 } 1224 } 1225 is_predef_encodingOT::cff1::accelerator_subset_t1226 bool is_predef_encoding () const { return topDict.EncodingOffset <= ExpertEncoding; } 1227 glyph_to_codeOT::cff1::accelerator_subset_t1228 hb_codepoint_t glyph_to_code (hb_codepoint_t glyph) const 1229 { 1230 if (encoding != &Null(Encoding)) 1231 return encoding->get_code (glyph); 1232 else 1233 { 1234 hb_codepoint_t sid = glyph_to_sid (glyph); 1235 if (sid == 0) return 0; 1236 hb_codepoint_t code = 0; 1237 switch (topDict.EncodingOffset) 1238 { 1239 case StandardEncoding: 1240 code = lookup_standard_encoding_for_code (sid); 1241 break; 1242 case ExpertEncoding: 1243 code = lookup_expert_encoding_for_code (sid); 1244 break; 1245 default: 1246 break; 1247 } 1248 return code; 1249 } 1250 } 1251 glyph_to_sidOT::cff1::accelerator_subset_t1252 hb_codepoint_t glyph_to_sid (hb_codepoint_t glyph) const 1253 { 1254 if (charset != &Null(Charset)) 1255 return charset->get_sid (glyph); 1256 else 1257 { 1258 hb_codepoint_t sid = 0; 1259 switch (topDict.CharsetOffset) 1260 { 1261 case ISOAdobeCharset: 1262 if (glyph <= 228 /*zcaron*/) sid = glyph; 1263 break; 1264 case ExpertCharset: 1265 sid = lookup_expert_charset_for_sid (glyph); 1266 break; 1267 case ExpertSubsetCharset: 1268 sid = lookup_expert_subset_charset_for_sid (glyph); 1269 break; 1270 default: 1271 break; 1272 } 1273 return sid; 1274 } 1275 } 1276 1277 const Encoding *encoding; 1278 1279 private: 1280 typedef accelerator_templ_t<cff1_private_dict_opset_subset, cff1_private_dict_values_subset_t> SUPER; 1281 }; 1282 subsetOT::cff11283 bool subset (hb_subset_plan_t *plan) const 1284 { 1285 hb_blob_t *cff_prime = nullptr; 1286 1287 bool success = true; 1288 if (hb_subset_cff1 (plan, &cff_prime)) { 1289 success = success && plan->add_table (HB_OT_TAG_cff1, cff_prime); 1290 hb_blob_t *head_blob = hb_sanitize_context_t().reference_table<head> (plan->source); 1291 success = success && head_blob && plan->add_table (HB_OT_TAG_head, head_blob); 1292 hb_blob_destroy (head_blob); 1293 } else { 1294 success = false; 1295 } 1296 hb_blob_destroy (cff_prime); 1297 1298 return success; 1299 } 1300 1301 protected: 1302 HB_INTERNAL static hb_codepoint_t lookup_standard_encoding_for_code (hb_codepoint_t sid); 1303 HB_INTERNAL static hb_codepoint_t lookup_expert_encoding_for_code (hb_codepoint_t sid); 1304 HB_INTERNAL static hb_codepoint_t lookup_expert_charset_for_sid (hb_codepoint_t glyph); 1305 HB_INTERNAL static hb_codepoint_t lookup_expert_subset_charset_for_sid (hb_codepoint_t glyph); 1306 HB_INTERNAL static hb_codepoint_t lookup_standard_encoding_for_sid (hb_codepoint_t code); 1307 1308 public: 1309 FixedVersion<HBUINT8> version; /* Version of CFF table. set to 0x0100u */ 1310 OffsetTo<CFF1NameIndex, HBUINT8> nameIndex; /* headerSize = Offset to Name INDEX. */ 1311 HBUINT8 offSize; /* offset size (unused?) */ 1312 1313 public: 1314 DEFINE_SIZE_STATIC (4); 1315 }; 1316 1317 struct cff1_accelerator_t : cff1::accelerator_t {}; 1318 } /* namespace OT */ 1319 1320 #endif /* HB_OT_CFF1_TABLE_HH */ 1321