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-cff-common.hh" 32 #include "hb-draw.hh" 33 #include "hb-paint.hh" 34 35 #define HB_STRING_ARRAY_NAME cff1_std_strings 36 #define HB_STRING_ARRAY_LIST "hb-ot-cff1-std-str.hh" 37 #include "hb-string-array.hh" 38 #undef HB_STRING_ARRAY_LIST 39 #undef HB_STRING_ARRAY_NAME 40 41 namespace CFF { 42 43 /* 44 * CFF -- Compact Font Format (CFF) 45 * https://www.adobe.com/content/dam/acom/en/devnet/font/pdfs/5176.CFF.pdf 46 */ 47 #define HB_OT_TAG_CFF1 HB_TAG('C','F','F',' ') 48 49 #define CFF_UNDEF_SID CFF_UNDEF_CODE 50 51 enum EncodingID { StandardEncoding = 0, ExpertEncoding = 1 }; 52 enum CharsetID { ISOAdobeCharset = 0, ExpertCharset = 1, ExpertSubsetCharset = 2 }; 53 54 typedef CFFIndex<HBUINT16> CFF1Index; 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 /* TODO: Add cache like get_sid. */ 113 assert (glyph > 0); 114 glyph--; 115 for (unsigned int i = 0; i < nRanges (); i++) 116 { 117 if (glyph <= ranges[i].nLeft) 118 { 119 hb_codepoint_t code = (hb_codepoint_t) ranges[i].first + glyph; 120 return (likely (code < 0x100) ? code: CFF_UNDEF_CODE); 121 } 122 glyph -= (ranges[i].nLeft + 1); 123 } 124 return CFF_UNDEF_CODE; 125 } 126 nRangesCFF::Encoding1127 HBUINT8 &nRanges () { return ranges.len; } nRangesCFF::Encoding1128 HBUINT8 nRanges () const { return ranges.len; } 129 130 ArrayOf<Encoding1_Range, HBUINT8> ranges; 131 132 DEFINE_SIZE_ARRAY_SIZED (1, ranges); 133 }; 134 135 struct SuppEncoding { sanitizeCFF::SuppEncoding136 bool sanitize (hb_sanitize_context_t *c) const 137 { 138 TRACE_SANITIZE (this); 139 return_trace (c->check_struct (this)); 140 } 141 142 HBUINT8 code; 143 HBUINT16 glyph; 144 145 DEFINE_SIZE_STATIC (3); 146 }; 147 148 struct CFF1SuppEncData { sanitizeCFF::CFF1SuppEncData149 bool sanitize (hb_sanitize_context_t *c) const 150 { 151 TRACE_SANITIZE (this); 152 return_trace (supps.sanitize (c)); 153 } 154 get_codesCFF::CFF1SuppEncData155 void get_codes (hb_codepoint_t sid, hb_vector_t<hb_codepoint_t> &codes) const 156 { 157 for (unsigned int i = 0; i < nSups (); i++) 158 if (sid == supps[i].glyph) 159 codes.push (supps[i].code); 160 } 161 nSupsCFF::CFF1SuppEncData162 HBUINT8 &nSups () { return supps.len; } nSupsCFF::CFF1SuppEncData163 HBUINT8 nSups () const { return supps.len; } 164 165 ArrayOf<SuppEncoding, HBUINT8> supps; 166 167 DEFINE_SIZE_ARRAY_SIZED (1, supps); 168 }; 169 170 struct Encoding 171 { 172 /* serialize a fullset Encoding */ serializeCFF::Encoding173 bool serialize (hb_serialize_context_t *c, const Encoding &src) 174 { 175 TRACE_SERIALIZE (this); 176 return_trace (c->embed (src)); 177 } 178 179 /* serialize a subset Encoding */ serializeCFF::Encoding180 bool serialize (hb_serialize_context_t *c, 181 uint8_t format, 182 unsigned int enc_count, 183 const hb_vector_t<code_pair_t>& code_ranges, 184 const hb_vector_t<code_pair_t>& supp_codes) 185 { 186 TRACE_SERIALIZE (this); 187 Encoding *dest = c->extend_min (this); 188 if (unlikely (!dest)) return_trace (false); 189 dest->format = format | ((supp_codes.length > 0) ? 0x80 : 0); 190 switch (format) { 191 case 0: 192 { 193 Encoding0 *fmt0 = c->allocate_size<Encoding0> (Encoding0::min_size + HBUINT8::static_size * enc_count); 194 if (unlikely (!fmt0)) return_trace (false); 195 fmt0->nCodes () = enc_count; 196 unsigned int glyph = 0; 197 for (unsigned int i = 0; i < code_ranges.length; i++) 198 { 199 hb_codepoint_t code = code_ranges[i].code; 200 for (int left = (int)code_ranges[i].glyph; left >= 0; left--) 201 fmt0->codes[glyph++] = code++; 202 if (unlikely (!((glyph <= 0x100) && (code <= 0x100)))) 203 return_trace (false); 204 } 205 } 206 break; 207 208 case 1: 209 { 210 Encoding1 *fmt1 = c->allocate_size<Encoding1> (Encoding1::min_size + Encoding1_Range::static_size * code_ranges.length); 211 if (unlikely (!fmt1)) return_trace (false); 212 fmt1->nRanges () = code_ranges.length; 213 for (unsigned int i = 0; i < code_ranges.length; i++) 214 { 215 if (unlikely (!((code_ranges[i].code <= 0xFF) && (code_ranges[i].glyph <= 0xFF)))) 216 return_trace (false); 217 fmt1->ranges[i].first = code_ranges[i].code; 218 fmt1->ranges[i].nLeft = code_ranges[i].glyph; 219 } 220 } 221 break; 222 223 } 224 225 if (supp_codes.length) 226 { 227 CFF1SuppEncData *suppData = c->allocate_size<CFF1SuppEncData> (CFF1SuppEncData::min_size + SuppEncoding::static_size * supp_codes.length); 228 if (unlikely (!suppData)) return_trace (false); 229 suppData->nSups () = supp_codes.length; 230 for (unsigned int i = 0; i < supp_codes.length; i++) 231 { 232 suppData->supps[i].code = supp_codes[i].code; 233 suppData->supps[i].glyph = supp_codes[i].glyph; /* actually SID */ 234 } 235 } 236 237 return_trace (true); 238 } 239 get_sizeCFF::Encoding240 unsigned int get_size () const 241 { 242 unsigned int size = min_size; 243 switch (table_format ()) 244 { 245 case 0: size += u.format0.get_size (); break; 246 case 1: size += u.format1.get_size (); break; 247 } 248 if (has_supplement ()) 249 size += suppEncData ().get_size (); 250 return size; 251 } 252 get_codeCFF::Encoding253 hb_codepoint_t get_code (hb_codepoint_t glyph) const 254 { 255 switch (table_format ()) 256 { 257 case 0: return u.format0.get_code (glyph); 258 case 1: return u.format1.get_code (glyph); 259 default:return 0; 260 } 261 } 262 table_formatCFF::Encoding263 uint8_t table_format () const { return format & 0x7F; } has_supplementCFF::Encoding264 bool has_supplement () const { return format & 0x80; } 265 get_supplement_codesCFF::Encoding266 void get_supplement_codes (hb_codepoint_t sid, hb_vector_t<hb_codepoint_t> &codes) const 267 { 268 codes.resize (0); 269 if (has_supplement ()) 270 suppEncData().get_codes (sid, codes); 271 } 272 sanitizeCFF::Encoding273 bool sanitize (hb_sanitize_context_t *c) const 274 { 275 TRACE_SANITIZE (this); 276 if (unlikely (!c->check_struct (this))) 277 return_trace (false); 278 279 switch (table_format ()) 280 { 281 case 0: if (unlikely (!u.format0.sanitize (c))) { return_trace (false); } break; 282 case 1: if (unlikely (!u.format1.sanitize (c))) { return_trace (false); } break; 283 default:return_trace (false); 284 } 285 return_trace (likely (!has_supplement () || suppEncData ().sanitize (c))); 286 } 287 288 protected: suppEncDataCFF::Encoding289 const CFF1SuppEncData &suppEncData () const 290 { 291 switch (table_format ()) 292 { 293 case 0: return StructAfter<CFF1SuppEncData> (u.format0.codes[u.format0.nCodes ()-1]); 294 case 1: return StructAfter<CFF1SuppEncData> (u.format1.ranges[u.format1.nRanges ()-1]); 295 default:return Null (CFF1SuppEncData); 296 } 297 } 298 299 public: 300 HBUINT8 format; 301 union { 302 Encoding0 format0; 303 Encoding1 format1; 304 } u; 305 /* CFF1SuppEncData suppEncData; */ 306 307 DEFINE_SIZE_MIN (1); 308 }; 309 310 /* Charset */ 311 struct Charset0 312 { sanitizeCFF::Charset0313 bool sanitize (hb_sanitize_context_t *c, unsigned int num_glyphs, unsigned *num_charset_entries) const 314 { 315 TRACE_SANITIZE (this); 316 if (num_charset_entries) *num_charset_entries = num_glyphs; 317 return_trace (sids.sanitize (c, num_glyphs - 1)); 318 } 319 get_sidCFF::Charset0320 hb_codepoint_t get_sid (hb_codepoint_t glyph, unsigned num_glyphs) const 321 { 322 if (unlikely (glyph >= num_glyphs)) return 0; 323 if (unlikely (glyph == 0)) 324 return 0; 325 else 326 return sids[glyph - 1]; 327 } 328 collect_glyph_to_sid_mapCFF::Charset0329 void collect_glyph_to_sid_map (glyph_to_sid_map_t *mapping, unsigned int num_glyphs) const 330 { 331 mapping->resize (num_glyphs, false); 332 for (hb_codepoint_t gid = 1; gid < num_glyphs; gid++) 333 mapping->arrayZ[gid] = {sids[gid - 1], gid}; 334 } 335 get_glyphCFF::Charset0336 hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const 337 { 338 if (sid == 0) 339 return 0; 340 341 for (unsigned int glyph = 1; glyph < num_glyphs; glyph++) 342 { 343 if (sids[glyph-1] == sid) 344 return glyph; 345 } 346 return 0; 347 } 348 get_sizeCFF::Charset0349 static unsigned int get_size (unsigned int num_glyphs) 350 { 351 assert (num_glyphs > 0); 352 return UnsizedArrayOf<HBUINT16>::get_size (num_glyphs - 1); 353 } 354 355 UnsizedArrayOf<HBUINT16> sids; 356 357 DEFINE_SIZE_ARRAY(0, sids); 358 }; 359 360 template <typename TYPE> 361 struct Charset_Range { sanitizeCFF::Charset_Range362 bool sanitize (hb_sanitize_context_t *c) const 363 { 364 TRACE_SANITIZE (this); 365 return_trace (c->check_struct (this)); 366 } 367 368 HBUINT16 first; 369 TYPE nLeft; 370 371 DEFINE_SIZE_STATIC (HBUINT16::static_size + TYPE::static_size); 372 }; 373 374 template <typename TYPE> 375 struct Charset1_2 { sanitizeCFF::Charset1_2376 bool sanitize (hb_sanitize_context_t *c, unsigned int num_glyphs, unsigned *num_charset_entries) const 377 { 378 TRACE_SANITIZE (this); 379 if (unlikely (!c->check_struct (this))) 380 return_trace (false); 381 num_glyphs--; 382 unsigned i; 383 for (i = 0; num_glyphs > 0; i++) 384 { 385 if (unlikely (!ranges[i].sanitize (c) || (num_glyphs < ranges[i].nLeft + 1))) 386 return_trace (false); 387 num_glyphs -= (ranges[i].nLeft + 1); 388 } 389 if (num_charset_entries) 390 *num_charset_entries = i; 391 return_trace (true); 392 } 393 get_sidCFF::Charset1_2394 hb_codepoint_t get_sid (hb_codepoint_t glyph, unsigned num_glyphs, 395 code_pair_t *cache = nullptr) const 396 { 397 if (unlikely (glyph >= num_glyphs)) return 0; 398 unsigned i; 399 hb_codepoint_t start_glyph; 400 if (cache && likely (cache->glyph <= glyph)) 401 { 402 i = cache->code; 403 start_glyph = cache->glyph; 404 } 405 else 406 { 407 if (unlikely (glyph == 0)) return 0; 408 i = 0; 409 start_glyph = 1; 410 } 411 glyph -= start_glyph; 412 for (;; i++) 413 { 414 unsigned count = ranges[i].nLeft; 415 if (glyph <= count) 416 { 417 if (cache) 418 *cache = {i, start_glyph}; 419 return ranges[i].first + glyph; 420 } 421 count++; 422 start_glyph += count; 423 glyph -= count; 424 } 425 426 return 0; 427 } 428 collect_glyph_to_sid_mapCFF::Charset1_2429 void collect_glyph_to_sid_map (glyph_to_sid_map_t *mapping, unsigned int num_glyphs) const 430 { 431 mapping->resize (num_glyphs, false); 432 hb_codepoint_t gid = 1; 433 if (gid >= num_glyphs) 434 return; 435 for (unsigned i = 0;; i++) 436 { 437 hb_codepoint_t sid = ranges[i].first; 438 unsigned count = ranges[i].nLeft + 1; 439 unsigned last = gid + count; 440 for (unsigned j = 0; j < count; j++) 441 mapping->arrayZ[gid++] = {sid++, last - 1}; 442 443 if (gid >= num_glyphs) 444 break; 445 } 446 } 447 get_glyphCFF::Charset1_2448 hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const 449 { 450 if (sid == 0) return 0; 451 hb_codepoint_t glyph = 1; 452 for (unsigned int i = 0;; i++) 453 { 454 if (glyph >= num_glyphs) 455 return 0; 456 if ((ranges[i].first <= sid) && (sid <= ranges[i].first + ranges[i].nLeft)) 457 return glyph + (sid - ranges[i].first); 458 glyph += (ranges[i].nLeft + 1); 459 } 460 461 return 0; 462 } 463 get_sizeCFF::Charset1_2464 unsigned int get_size (unsigned int num_glyphs) const 465 { 466 int glyph = (int) num_glyphs; 467 unsigned num_ranges = 0; 468 469 assert (glyph > 0); 470 glyph--; 471 for (unsigned int i = 0; glyph > 0; i++) 472 { 473 glyph -= (ranges[i].nLeft + 1); 474 num_ranges++; 475 } 476 477 return get_size_for_ranges (num_ranges); 478 } 479 get_size_for_rangesCFF::Charset1_2480 static unsigned int get_size_for_ranges (unsigned int num_ranges) 481 { 482 return UnsizedArrayOf<Charset_Range<TYPE> >::get_size (num_ranges); 483 } 484 485 UnsizedArrayOf<Charset_Range<TYPE>> ranges; 486 487 DEFINE_SIZE_ARRAY (0, ranges); 488 }; 489 490 typedef Charset1_2<HBUINT8> Charset1; 491 typedef Charset1_2<HBUINT16> Charset2; 492 typedef Charset_Range<HBUINT8> Charset1_Range; 493 typedef Charset_Range<HBUINT16> Charset2_Range; 494 495 struct Charset 496 { 497 /* serialize a fullset Charset */ serializeCFF::Charset498 bool serialize (hb_serialize_context_t *c, const Charset &src, unsigned int num_glyphs) 499 { 500 TRACE_SERIALIZE (this); 501 return_trace (c->embed ((const char *) &src, src.get_size (num_glyphs))); 502 } 503 504 /* serialize a subset Charset */ serializeCFF::Charset505 bool serialize (hb_serialize_context_t *c, 506 uint8_t format, 507 unsigned int num_glyphs, 508 const hb_vector_t<code_pair_t>& sid_ranges) 509 { 510 TRACE_SERIALIZE (this); 511 Charset *dest = c->extend_min (this); 512 if (unlikely (!dest)) return_trace (false); 513 dest->format = format; 514 switch (format) 515 { 516 case 0: 517 { 518 Charset0 *fmt0 = c->allocate_size<Charset0> (Charset0::get_size (num_glyphs), false); 519 if (unlikely (!fmt0)) return_trace (false); 520 unsigned int glyph = 0; 521 for (unsigned int i = 0; i < sid_ranges.length; i++) 522 { 523 hb_codepoint_t sid = sid_ranges.arrayZ[i].code; 524 for (int left = (int)sid_ranges.arrayZ[i].glyph; left >= 0; left--) 525 fmt0->sids[glyph++] = sid++; 526 } 527 } 528 break; 529 530 case 1: 531 { 532 Charset1 *fmt1 = c->allocate_size<Charset1> (Charset1::get_size_for_ranges (sid_ranges.length), false); 533 if (unlikely (!fmt1)) return_trace (false); 534 hb_codepoint_t all_glyphs = 0; 535 for (unsigned int i = 0; i < sid_ranges.length; i++) 536 { 537 auto &_ = sid_ranges.arrayZ[i]; 538 all_glyphs |= _.glyph; 539 fmt1->ranges[i].first = _.code; 540 fmt1->ranges[i].nLeft = _.glyph; 541 } 542 if (unlikely (!(all_glyphs <= 0xFF))) 543 return_trace (false); 544 } 545 break; 546 547 case 2: 548 { 549 Charset2 *fmt2 = c->allocate_size<Charset2> (Charset2::get_size_for_ranges (sid_ranges.length), false); 550 if (unlikely (!fmt2)) return_trace (false); 551 hb_codepoint_t all_glyphs = 0; 552 for (unsigned int i = 0; i < sid_ranges.length; i++) 553 { 554 auto &_ = sid_ranges.arrayZ[i]; 555 all_glyphs |= _.glyph; 556 fmt2->ranges[i].first = _.code; 557 fmt2->ranges[i].nLeft = _.glyph; 558 } 559 if (unlikely (!(all_glyphs <= 0xFFFF))) 560 return_trace (false); 561 } 562 break; 563 564 } 565 return_trace (true); 566 } 567 get_sizeCFF::Charset568 unsigned int get_size (unsigned int num_glyphs) const 569 { 570 switch (format) 571 { 572 case 0: return min_size + u.format0.get_size (num_glyphs); 573 case 1: return min_size + u.format1.get_size (num_glyphs); 574 case 2: return min_size + u.format2.get_size (num_glyphs); 575 default:return 0; 576 } 577 } 578 get_sidCFF::Charset579 hb_codepoint_t get_sid (hb_codepoint_t glyph, unsigned int num_glyphs, 580 code_pair_t *cache = nullptr) const 581 { 582 switch (format) 583 { 584 case 0: return u.format0.get_sid (glyph, num_glyphs); 585 case 1: return u.format1.get_sid (glyph, num_glyphs, cache); 586 case 2: return u.format2.get_sid (glyph, num_glyphs, cache); 587 default:return 0; 588 } 589 } 590 collect_glyph_to_sid_mapCFF::Charset591 void collect_glyph_to_sid_map (glyph_to_sid_map_t *mapping, unsigned int num_glyphs) const 592 { 593 switch (format) 594 { 595 case 0: u.format0.collect_glyph_to_sid_map (mapping, num_glyphs); return; 596 case 1: u.format1.collect_glyph_to_sid_map (mapping, num_glyphs); return; 597 case 2: u.format2.collect_glyph_to_sid_map (mapping, num_glyphs); return; 598 default:return; 599 } 600 } 601 get_glyphCFF::Charset602 hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const 603 { 604 switch (format) 605 { 606 case 0: return u.format0.get_glyph (sid, num_glyphs); 607 case 1: return u.format1.get_glyph (sid, num_glyphs); 608 case 2: return u.format2.get_glyph (sid, num_glyphs); 609 default:return 0; 610 } 611 } 612 sanitizeCFF::Charset613 bool sanitize (hb_sanitize_context_t *c, unsigned *num_charset_entries) const 614 { 615 TRACE_SANITIZE (this); 616 if (unlikely (!c->check_struct (this))) 617 return_trace (false); 618 619 switch (format) 620 { 621 case 0: return_trace (u.format0.sanitize (c, c->get_num_glyphs (), num_charset_entries)); 622 case 1: return_trace (u.format1.sanitize (c, c->get_num_glyphs (), num_charset_entries)); 623 case 2: return_trace (u.format2.sanitize (c, c->get_num_glyphs (), num_charset_entries)); 624 default:return_trace (false); 625 } 626 } 627 628 HBUINT8 format; 629 union { 630 Charset0 format0; 631 Charset1 format1; 632 Charset2 format2; 633 } u; 634 635 DEFINE_SIZE_MIN (1); 636 }; 637 638 struct CFF1StringIndex : CFF1Index 639 { serializeCFF::CFF1StringIndex640 bool serialize (hb_serialize_context_t *c, const CFF1StringIndex &strings, 641 const hb_vector_t<unsigned> &sidmap) 642 { 643 TRACE_SERIALIZE (this); 644 if (unlikely ((strings.count == 0) || (sidmap.length == 0))) 645 { 646 if (unlikely (!c->extend_min (this->count))) 647 return_trace (false); 648 count = 0; 649 return_trace (true); 650 } 651 652 if (unlikely (sidmap.in_error ())) return_trace (false); 653 654 // Save this in a vector since serialize() iterates it twice. 655 hb_vector_t<hb_ubytes_t> bytesArray (+ hb_iter (sidmap) 656 | hb_map (strings)); 657 658 if (unlikely (bytesArray.in_error ())) return_trace (false); 659 660 bool result = CFF1Index::serialize (c, bytesArray); 661 return_trace (result); 662 } 663 }; 664 665 struct cff1_top_dict_interp_env_t : num_interp_env_t 666 { cff1_top_dict_interp_env_tCFF::cff1_top_dict_interp_env_t667 cff1_top_dict_interp_env_t () 668 : num_interp_env_t(), prev_offset(0), last_offset(0) {} cff1_top_dict_interp_env_tCFF::cff1_top_dict_interp_env_t669 cff1_top_dict_interp_env_t (const hb_ubytes_t &bytes) 670 : num_interp_env_t(bytes), prev_offset(0), last_offset(0) {} 671 672 unsigned int prev_offset; 673 unsigned int last_offset; 674 }; 675 676 struct name_dict_values_t 677 { 678 enum name_dict_val_index_t 679 { 680 version, 681 notice, 682 copyright, 683 fullName, 684 familyName, 685 weight, 686 postscript, 687 fontName, 688 baseFontName, 689 registry, 690 ordering, 691 692 ValCount 693 }; 694 initCFF::name_dict_values_t695 void init () 696 { 697 for (unsigned int i = 0; i < ValCount; i++) 698 values[i] = CFF_UNDEF_SID; 699 } 700 operator []CFF::name_dict_values_t701 unsigned int& operator[] (unsigned int i) 702 { assert (i < ValCount); return values[i]; } 703 operator []CFF::name_dict_values_t704 unsigned int operator[] (unsigned int i) const 705 { assert (i < ValCount); return values[i]; } 706 name_op_to_indexCFF::name_dict_values_t707 static enum name_dict_val_index_t name_op_to_index (op_code_t op) 708 { 709 switch (op) { 710 default: // can't happen - just make some compiler happy 711 case OpCode_version: 712 return version; 713 case OpCode_Notice: 714 return notice; 715 case OpCode_Copyright: 716 return copyright; 717 case OpCode_FullName: 718 return fullName; 719 case OpCode_FamilyName: 720 return familyName; 721 case OpCode_Weight: 722 return weight; 723 case OpCode_PostScript: 724 return postscript; 725 case OpCode_FontName: 726 return fontName; 727 case OpCode_BaseFontName: 728 return baseFontName; 729 } 730 } 731 732 unsigned int values[ValCount]; 733 }; 734 735 struct cff1_top_dict_val_t : op_str_t 736 { 737 unsigned int last_arg_offset; 738 }; 739 740 struct cff1_top_dict_values_t : top_dict_values_t<cff1_top_dict_val_t> 741 { initCFF::cff1_top_dict_values_t742 void init () 743 { 744 top_dict_values_t<cff1_top_dict_val_t>::init (); 745 746 nameSIDs.init (); 747 ros_supplement = 0; 748 cidCount = 8720; 749 EncodingOffset = 0; 750 CharsetOffset = 0; 751 FDSelectOffset = 0; 752 privateDictInfo.init (); 753 } finiCFF::cff1_top_dict_values_t754 void fini () { top_dict_values_t<cff1_top_dict_val_t>::fini (); } 755 is_CIDCFF::cff1_top_dict_values_t756 bool is_CID () const 757 { return nameSIDs[name_dict_values_t::registry] != CFF_UNDEF_SID; } 758 759 name_dict_values_t nameSIDs; 760 unsigned int ros_supplement_offset; 761 unsigned int ros_supplement; 762 unsigned int cidCount; 763 764 unsigned int EncodingOffset; 765 unsigned int CharsetOffset; 766 unsigned int FDSelectOffset; 767 table_info_t privateDictInfo; 768 }; 769 770 struct cff1_top_dict_opset_t : top_dict_opset_t<cff1_top_dict_val_t> 771 { process_opCFF::cff1_top_dict_opset_t772 static void process_op (op_code_t op, cff1_top_dict_interp_env_t& env, cff1_top_dict_values_t& dictval) 773 { 774 cff1_top_dict_val_t val; 775 val.last_arg_offset = (env.last_offset-1) - dictval.opStart; /* offset to the last argument */ 776 777 switch (op) { 778 case OpCode_version: 779 case OpCode_Notice: 780 case OpCode_Copyright: 781 case OpCode_FullName: 782 case OpCode_FontName: 783 case OpCode_FamilyName: 784 case OpCode_Weight: 785 case OpCode_PostScript: 786 case OpCode_BaseFontName: 787 dictval.nameSIDs[name_dict_values_t::name_op_to_index (op)] = env.argStack.pop_uint (); 788 env.clear_args (); 789 break; 790 case OpCode_isFixedPitch: 791 case OpCode_ItalicAngle: 792 case OpCode_UnderlinePosition: 793 case OpCode_UnderlineThickness: 794 case OpCode_PaintType: 795 case OpCode_CharstringType: 796 case OpCode_UniqueID: 797 case OpCode_StrokeWidth: 798 case OpCode_SyntheticBase: 799 case OpCode_CIDFontVersion: 800 case OpCode_CIDFontRevision: 801 case OpCode_CIDFontType: 802 case OpCode_UIDBase: 803 case OpCode_FontBBox: 804 case OpCode_XUID: 805 case OpCode_BaseFontBlend: 806 env.clear_args (); 807 break; 808 809 case OpCode_CIDCount: 810 dictval.cidCount = env.argStack.pop_uint (); 811 env.clear_args (); 812 break; 813 814 case OpCode_ROS: 815 dictval.ros_supplement = env.argStack.pop_uint (); 816 dictval.nameSIDs[name_dict_values_t::ordering] = env.argStack.pop_uint (); 817 dictval.nameSIDs[name_dict_values_t::registry] = env.argStack.pop_uint (); 818 env.clear_args (); 819 break; 820 821 case OpCode_Encoding: 822 dictval.EncodingOffset = env.argStack.pop_uint (); 823 env.clear_args (); 824 if (unlikely (dictval.EncodingOffset == 0)) return; 825 break; 826 827 case OpCode_charset: 828 dictval.CharsetOffset = env.argStack.pop_uint (); 829 env.clear_args (); 830 if (unlikely (dictval.CharsetOffset == 0)) return; 831 break; 832 833 case OpCode_FDSelect: 834 dictval.FDSelectOffset = env.argStack.pop_uint (); 835 env.clear_args (); 836 break; 837 838 case OpCode_Private: 839 dictval.privateDictInfo.offset = env.argStack.pop_uint (); 840 dictval.privateDictInfo.size = env.argStack.pop_uint (); 841 env.clear_args (); 842 break; 843 844 default: 845 env.last_offset = env.str_ref.get_offset (); 846 top_dict_opset_t<cff1_top_dict_val_t>::process_op (op, env, dictval); 847 /* Record this operand below if stack is empty, otherwise done */ 848 if (!env.argStack.is_empty ()) return; 849 break; 850 } 851 852 if (unlikely (env.in_error ())) return; 853 854 dictval.add_op (op, env.str_ref, val); 855 } 856 }; 857 858 struct cff1_font_dict_values_t : dict_values_t<op_str_t> 859 { initCFF::cff1_font_dict_values_t860 void init () 861 { 862 dict_values_t<op_str_t>::init (); 863 privateDictInfo.init (); 864 fontName = CFF_UNDEF_SID; 865 } finiCFF::cff1_font_dict_values_t866 void fini () { dict_values_t<op_str_t>::fini (); } 867 868 table_info_t privateDictInfo; 869 unsigned int fontName; 870 }; 871 872 struct cff1_font_dict_opset_t : dict_opset_t 873 { process_opCFF::cff1_font_dict_opset_t874 static void process_op (op_code_t op, num_interp_env_t& env, cff1_font_dict_values_t& dictval) 875 { 876 switch (op) { 877 case OpCode_FontName: 878 dictval.fontName = env.argStack.pop_uint (); 879 env.clear_args (); 880 break; 881 case OpCode_FontMatrix: 882 case OpCode_PaintType: 883 env.clear_args (); 884 break; 885 case OpCode_Private: 886 dictval.privateDictInfo.offset = env.argStack.pop_uint (); 887 dictval.privateDictInfo.size = env.argStack.pop_uint (); 888 env.clear_args (); 889 break; 890 891 default: 892 dict_opset_t::process_op (op, env); 893 if (!env.argStack.is_empty ()) return; 894 break; 895 } 896 897 if (unlikely (env.in_error ())) return; 898 899 dictval.add_op (op, env.str_ref); 900 } 901 }; 902 903 template <typename VAL> 904 struct cff1_private_dict_values_base_t : dict_values_t<VAL> 905 { initCFF::cff1_private_dict_values_base_t906 void init () 907 { 908 dict_values_t<VAL>::init (); 909 subrsOffset = 0; 910 localSubrs = &Null (CFF1Subrs); 911 } finiCFF::cff1_private_dict_values_base_t912 void fini () { dict_values_t<VAL>::fini (); } 913 914 unsigned int subrsOffset; 915 const CFF1Subrs *localSubrs; 916 }; 917 918 typedef cff1_private_dict_values_base_t<op_str_t> cff1_private_dict_values_subset_t; 919 typedef cff1_private_dict_values_base_t<num_dict_val_t> cff1_private_dict_values_t; 920 921 struct cff1_private_dict_opset_t : dict_opset_t 922 { process_opCFF::cff1_private_dict_opset_t923 static void process_op (op_code_t op, num_interp_env_t& env, cff1_private_dict_values_t& dictval) 924 { 925 num_dict_val_t val; 926 val.init (); 927 928 switch (op) { 929 case OpCode_BlueValues: 930 case OpCode_OtherBlues: 931 case OpCode_FamilyBlues: 932 case OpCode_FamilyOtherBlues: 933 case OpCode_StemSnapH: 934 case OpCode_StemSnapV: 935 case OpCode_StdHW: 936 case OpCode_StdVW: 937 case OpCode_BlueScale: 938 case OpCode_BlueShift: 939 case OpCode_BlueFuzz: 940 case OpCode_ForceBold: 941 case OpCode_LanguageGroup: 942 case OpCode_ExpansionFactor: 943 case OpCode_initialRandomSeed: 944 case OpCode_defaultWidthX: 945 case OpCode_nominalWidthX: 946 env.clear_args (); 947 break; 948 case OpCode_Subrs: 949 dictval.subrsOffset = env.argStack.pop_uint (); 950 env.clear_args (); 951 break; 952 953 default: 954 dict_opset_t::process_op (op, env); 955 if (!env.argStack.is_empty ()) return; 956 break; 957 } 958 959 if (unlikely (env.in_error ())) return; 960 961 dictval.add_op (op, env.str_ref, val); 962 } 963 }; 964 965 struct cff1_private_dict_opset_subset_t : dict_opset_t 966 { process_opCFF::cff1_private_dict_opset_subset_t967 static void process_op (op_code_t op, num_interp_env_t& env, cff1_private_dict_values_subset_t& dictval) 968 { 969 switch (op) { 970 case OpCode_BlueValues: 971 case OpCode_OtherBlues: 972 case OpCode_FamilyBlues: 973 case OpCode_FamilyOtherBlues: 974 case OpCode_StemSnapH: 975 case OpCode_StemSnapV: 976 case OpCode_StdHW: 977 case OpCode_StdVW: 978 case OpCode_BlueScale: 979 case OpCode_BlueShift: 980 case OpCode_BlueFuzz: 981 case OpCode_ForceBold: 982 case OpCode_LanguageGroup: 983 case OpCode_ExpansionFactor: 984 case OpCode_initialRandomSeed: 985 case OpCode_defaultWidthX: 986 case OpCode_nominalWidthX: 987 env.clear_args (); 988 break; 989 990 case OpCode_Subrs: 991 dictval.subrsOffset = env.argStack.pop_uint (); 992 env.clear_args (); 993 break; 994 995 default: 996 dict_opset_t::process_op (op, env); 997 if (!env.argStack.is_empty ()) return; 998 break; 999 } 1000 1001 if (unlikely (env.in_error ())) return; 1002 1003 dictval.add_op (op, env.str_ref); 1004 } 1005 }; 1006 1007 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; 1008 typedef dict_interpreter_t<cff1_font_dict_opset_t, cff1_font_dict_values_t> cff1_font_dict_interpreter_t; 1009 1010 typedef CFF1Index CFF1NameIndex; 1011 typedef CFF1Index CFF1TopDictIndex; 1012 1013 struct cff1_font_dict_values_mod_t 1014 { cff1_font_dict_values_mod_tCFF::cff1_font_dict_values_mod_t1015 cff1_font_dict_values_mod_t() { init (); } 1016 initCFF::cff1_font_dict_values_mod_t1017 void init () { init ( &Null (cff1_font_dict_values_t), CFF_UNDEF_SID ); } 1018 initCFF::cff1_font_dict_values_mod_t1019 void init (const cff1_font_dict_values_t *base_, 1020 unsigned int fontName_) 1021 { 1022 base = base_; 1023 fontName = fontName_; 1024 privateDictInfo.init (); 1025 } 1026 get_countCFF::cff1_font_dict_values_mod_t1027 unsigned get_count () const { return base->get_count (); } 1028 operator []CFF::cff1_font_dict_values_mod_t1029 const op_str_t &operator [] (unsigned int i) const { return (*base)[i]; } 1030 1031 const cff1_font_dict_values_t *base; 1032 table_info_t privateDictInfo; 1033 unsigned int fontName; 1034 }; 1035 1036 struct CFF1FDArray : FDArray<HBUINT16> 1037 { 1038 /* FDArray::serialize() requires this partial specialization to compile */ 1039 template <typename ITER, typename OP_SERIALIZER> serializeCFF::CFF1FDArray1040 bool serialize (hb_serialize_context_t *c, ITER it, OP_SERIALIZER& opszr) 1041 { return FDArray<HBUINT16>::serialize<cff1_font_dict_values_mod_t, cff1_font_dict_values_mod_t> (c, it, opszr); } 1042 }; 1043 1044 } /* namespace CFF */ 1045 1046 namespace OT { 1047 1048 using namespace CFF; 1049 1050 struct cff1 1051 { 1052 static constexpr hb_tag_t tableTag = HB_OT_TAG_CFF1; 1053 sanitizeOT::cff11054 bool sanitize (hb_sanitize_context_t *c) const 1055 { 1056 TRACE_SANITIZE (this); 1057 return_trace (c->check_struct (this) && 1058 likely (version.major == 1)); 1059 } 1060 1061 template <typename PRIVOPSET, typename PRIVDICTVAL> 1062 struct accelerator_templ_t 1063 { 1064 static constexpr hb_tag_t tableTag = cff1::tableTag; 1065 accelerator_templ_tOT::cff1::accelerator_templ_t1066 accelerator_templ_t (hb_face_t *face) 1067 { 1068 if (!face) return; 1069 1070 topDict.init (); 1071 fontDicts.init (); 1072 privateDicts.init (); 1073 1074 this->blob = sc.reference_table<cff1> (face); 1075 1076 /* setup for run-time santization */ 1077 sc.init (this->blob); 1078 sc.start_processing (); 1079 1080 const OT::cff1 *cff = this->blob->template as<OT::cff1> (); 1081 1082 if (cff == &Null (OT::cff1)) 1083 goto fail; 1084 1085 nameIndex = &cff->nameIndex (cff); 1086 if ((nameIndex == &Null (CFF1NameIndex)) || !nameIndex->sanitize (&sc)) 1087 goto fail; 1088 1089 topDictIndex = &StructAtOffset<CFF1TopDictIndex> (nameIndex, nameIndex->get_size ()); 1090 if ((topDictIndex == &Null (CFF1TopDictIndex)) || !topDictIndex->sanitize (&sc) || (topDictIndex->count == 0)) 1091 goto fail; 1092 1093 { /* parse top dict */ 1094 const hb_ubytes_t topDictStr = (*topDictIndex)[0]; 1095 if (unlikely (!topDictStr.sanitize (&sc))) goto fail; 1096 cff1_top_dict_interp_env_t env (topDictStr); 1097 cff1_top_dict_interpreter_t top_interp (env); 1098 if (unlikely (!top_interp.interpret (topDict))) goto fail; 1099 } 1100 1101 if (is_predef_charset ()) 1102 charset = &Null (Charset); 1103 else 1104 { 1105 charset = &StructAtOffsetOrNull<Charset> (cff, topDict.CharsetOffset); 1106 if (unlikely ((charset == &Null (Charset)) || !charset->sanitize (&sc, &num_charset_entries))) goto fail; 1107 } 1108 1109 fdCount = 1; 1110 if (is_CID ()) 1111 { 1112 fdArray = &StructAtOffsetOrNull<CFF1FDArray> (cff, topDict.FDArrayOffset); 1113 fdSelect = &StructAtOffsetOrNull<CFF1FDSelect> (cff, topDict.FDSelectOffset); 1114 if (unlikely ((fdArray == &Null (CFF1FDArray)) || !fdArray->sanitize (&sc) || 1115 (fdSelect == &Null (CFF1FDSelect)) || !fdSelect->sanitize (&sc, fdArray->count))) 1116 goto fail; 1117 1118 fdCount = fdArray->count; 1119 } 1120 else 1121 { 1122 fdArray = &Null (CFF1FDArray); 1123 fdSelect = &Null (CFF1FDSelect); 1124 } 1125 1126 encoding = &Null (Encoding); 1127 if (is_CID ()) 1128 { 1129 if (unlikely (charset == &Null (Charset))) goto fail; 1130 } 1131 else 1132 { 1133 if (!is_predef_encoding ()) 1134 { 1135 encoding = &StructAtOffsetOrNull<Encoding> (cff, topDict.EncodingOffset); 1136 if (unlikely ((encoding == &Null (Encoding)) || !encoding->sanitize (&sc))) goto fail; 1137 } 1138 } 1139 1140 stringIndex = &StructAtOffset<CFF1StringIndex> (topDictIndex, topDictIndex->get_size ()); 1141 if ((stringIndex == &Null (CFF1StringIndex)) || !stringIndex->sanitize (&sc)) 1142 goto fail; 1143 1144 globalSubrs = &StructAtOffset<CFF1Subrs> (stringIndex, stringIndex->get_size ()); 1145 if ((globalSubrs != &Null (CFF1Subrs)) && !globalSubrs->sanitize (&sc)) 1146 goto fail; 1147 1148 charStrings = &StructAtOffsetOrNull<CFF1CharStrings> (cff, topDict.charStringsOffset); 1149 1150 if ((charStrings == &Null (CFF1CharStrings)) || unlikely (!charStrings->sanitize (&sc))) 1151 goto fail; 1152 1153 num_glyphs = charStrings->count; 1154 if (num_glyphs != sc.get_num_glyphs ()) 1155 goto fail; 1156 1157 if (unlikely (!privateDicts.resize (fdCount))) 1158 goto fail; 1159 for (unsigned int i = 0; i < fdCount; i++) 1160 privateDicts[i].init (); 1161 1162 // parse CID font dicts and gather private dicts 1163 if (is_CID ()) 1164 { 1165 for (unsigned int i = 0; i < fdCount; i++) 1166 { 1167 hb_ubytes_t fontDictStr = (*fdArray)[i]; 1168 if (unlikely (!fontDictStr.sanitize (&sc))) goto fail; 1169 cff1_font_dict_values_t *font; 1170 cff1_top_dict_interp_env_t env (fontDictStr); 1171 cff1_font_dict_interpreter_t font_interp (env); 1172 font = fontDicts.push (); 1173 if (unlikely (fontDicts.in_error ())) goto fail; 1174 1175 font->init (); 1176 if (unlikely (!font_interp.interpret (*font))) goto fail; 1177 PRIVDICTVAL *priv = &privateDicts[i]; 1178 const hb_ubytes_t privDictStr = StructAtOffset<UnsizedByteStr> (cff, font->privateDictInfo.offset).as_ubytes (font->privateDictInfo.size); 1179 if (unlikely (!privDictStr.sanitize (&sc))) goto fail; 1180 num_interp_env_t env2 (privDictStr); 1181 dict_interpreter_t<PRIVOPSET, PRIVDICTVAL> priv_interp (env2); 1182 priv->init (); 1183 if (unlikely (!priv_interp.interpret (*priv))) goto fail; 1184 1185 priv->localSubrs = &StructAtOffsetOrNull<CFF1Subrs> (&privDictStr, priv->subrsOffset); 1186 if (priv->localSubrs != &Null (CFF1Subrs) && 1187 unlikely (!priv->localSubrs->sanitize (&sc))) 1188 goto fail; 1189 } 1190 } 1191 else /* non-CID */ 1192 { 1193 cff1_top_dict_values_t *font = &topDict; 1194 PRIVDICTVAL *priv = &privateDicts[0]; 1195 1196 const hb_ubytes_t privDictStr = StructAtOffset<UnsizedByteStr> (cff, font->privateDictInfo.offset).as_ubytes (font->privateDictInfo.size); 1197 if (unlikely (!privDictStr.sanitize (&sc))) goto fail; 1198 num_interp_env_t env (privDictStr); 1199 dict_interpreter_t<PRIVOPSET, PRIVDICTVAL> priv_interp (env); 1200 priv->init (); 1201 if (unlikely (!priv_interp.interpret (*priv))) goto fail; 1202 1203 priv->localSubrs = &StructAtOffsetOrNull<CFF1Subrs> (&privDictStr, priv->subrsOffset); 1204 if (priv->localSubrs != &Null (CFF1Subrs) && 1205 unlikely (!priv->localSubrs->sanitize (&sc))) 1206 goto fail; 1207 } 1208 1209 return; 1210 1211 fail: 1212 _fini (); 1213 } ~accelerator_templ_tOT::cff1::accelerator_templ_t1214 ~accelerator_templ_t () { _fini (); } _finiOT::cff1::accelerator_templ_t1215 void _fini () 1216 { 1217 sc.end_processing (); 1218 topDict.fini (); 1219 fontDicts.fini (); 1220 privateDicts.fini (); 1221 hb_blob_destroy (blob); 1222 blob = nullptr; 1223 } 1224 get_blobOT::cff1::accelerator_templ_t1225 hb_blob_t *get_blob () const { return blob; } 1226 is_validOT::cff1::accelerator_templ_t1227 bool is_valid () const { return blob; } is_CIDOT::cff1::accelerator_templ_t1228 bool is_CID () const { return topDict.is_CID (); } 1229 is_predef_charsetOT::cff1::accelerator_templ_t1230 bool is_predef_charset () const { return topDict.CharsetOffset <= ExpertSubsetCharset; } 1231 std_code_to_glyphOT::cff1::accelerator_templ_t1232 unsigned int std_code_to_glyph (hb_codepoint_t code) const 1233 { 1234 hb_codepoint_t sid = lookup_standard_encoding_for_sid (code); 1235 if (unlikely (sid == CFF_UNDEF_SID)) 1236 return 0; 1237 1238 if (charset != &Null (Charset)) 1239 return charset->get_glyph (sid, num_glyphs); 1240 else if ((topDict.CharsetOffset == ISOAdobeCharset) 1241 && (code <= 228 /*zcaron*/)) return sid; 1242 return 0; 1243 } 1244 is_predef_encodingOT::cff1::accelerator_templ_t1245 bool is_predef_encoding () const { return topDict.EncodingOffset <= ExpertEncoding; } 1246 glyph_to_codeOT::cff1::accelerator_templ_t1247 hb_codepoint_t glyph_to_code (hb_codepoint_t glyph, 1248 code_pair_t *glyph_to_sid_cache = nullptr) const 1249 { 1250 if (encoding != &Null (Encoding)) 1251 return encoding->get_code (glyph); 1252 else 1253 { 1254 hb_codepoint_t sid = glyph_to_sid (glyph, glyph_to_sid_cache); 1255 if (sid == 0) return 0; 1256 hb_codepoint_t code = 0; 1257 switch (topDict.EncodingOffset) 1258 { 1259 case StandardEncoding: 1260 code = lookup_standard_encoding_for_code (sid); 1261 break; 1262 case ExpertEncoding: 1263 code = lookup_expert_encoding_for_code (sid); 1264 break; 1265 default: 1266 break; 1267 } 1268 return code; 1269 } 1270 } 1271 create_glyph_to_sid_mapOT::cff1::accelerator_templ_t1272 glyph_to_sid_map_t *create_glyph_to_sid_map () const 1273 { 1274 if (charset != &Null (Charset)) 1275 { 1276 auto *mapping = (glyph_to_sid_map_t *) hb_malloc (sizeof (glyph_to_sid_map_t)); 1277 if (unlikely (!mapping)) return nullptr; 1278 mapping = new (mapping) glyph_to_sid_map_t (); 1279 mapping->push (code_pair_t {0, 1}); 1280 charset->collect_glyph_to_sid_map (mapping, num_glyphs); 1281 return mapping; 1282 } 1283 else 1284 return nullptr; 1285 } 1286 glyph_to_sidOT::cff1::accelerator_templ_t1287 hb_codepoint_t glyph_to_sid (hb_codepoint_t glyph, 1288 code_pair_t *cache = nullptr) const 1289 { 1290 if (charset != &Null (Charset)) 1291 return charset->get_sid (glyph, num_glyphs, cache); 1292 else 1293 { 1294 hb_codepoint_t sid = 0; 1295 switch (topDict.CharsetOffset) 1296 { 1297 case ISOAdobeCharset: 1298 if (glyph <= 228 /*zcaron*/) sid = glyph; 1299 break; 1300 case ExpertCharset: 1301 sid = lookup_expert_charset_for_sid (glyph); 1302 break; 1303 case ExpertSubsetCharset: 1304 sid = lookup_expert_subset_charset_for_sid (glyph); 1305 break; 1306 default: 1307 break; 1308 } 1309 return sid; 1310 } 1311 } 1312 sid_to_glyphOT::cff1::accelerator_templ_t1313 hb_codepoint_t sid_to_glyph (hb_codepoint_t sid) const 1314 { 1315 if (charset != &Null (Charset)) 1316 return charset->get_glyph (sid, num_glyphs); 1317 else 1318 { 1319 hb_codepoint_t glyph = 0; 1320 switch (topDict.CharsetOffset) 1321 { 1322 case ISOAdobeCharset: 1323 if (sid <= 228 /*zcaron*/) glyph = sid; 1324 break; 1325 case ExpertCharset: 1326 glyph = lookup_expert_charset_for_glyph (sid); 1327 break; 1328 case ExpertSubsetCharset: 1329 glyph = lookup_expert_subset_charset_for_glyph (sid); 1330 break; 1331 default: 1332 break; 1333 } 1334 return glyph; 1335 } 1336 } 1337 1338 protected: 1339 hb_sanitize_context_t sc; 1340 1341 public: 1342 hb_blob_t *blob = nullptr; 1343 const Encoding *encoding = nullptr; 1344 const Charset *charset = nullptr; 1345 const CFF1NameIndex *nameIndex = nullptr; 1346 const CFF1TopDictIndex *topDictIndex = nullptr; 1347 const CFF1StringIndex *stringIndex = nullptr; 1348 const CFF1Subrs *globalSubrs = nullptr; 1349 const CFF1CharStrings *charStrings = nullptr; 1350 const CFF1FDArray *fdArray = nullptr; 1351 const CFF1FDSelect *fdSelect = nullptr; 1352 unsigned int fdCount = 0; 1353 1354 cff1_top_dict_values_t topDict; 1355 hb_vector_t<cff1_font_dict_values_t> 1356 fontDicts; 1357 hb_vector_t<PRIVDICTVAL> privateDicts; 1358 1359 unsigned int num_glyphs = 0; 1360 unsigned int num_charset_entries = 0; 1361 }; 1362 1363 struct accelerator_t : accelerator_templ_t<cff1_private_dict_opset_t, cff1_private_dict_values_t> 1364 { accelerator_tOT::cff1::accelerator_t1365 accelerator_t (hb_face_t *face) : SUPER (face) 1366 { 1367 glyph_names.set_relaxed (nullptr); 1368 1369 if (!is_valid ()) return; 1370 if (is_CID ()) return; 1371 } ~accelerator_tOT::cff1::accelerator_t1372 ~accelerator_t () 1373 { 1374 hb_sorted_vector_t<gname_t> *names = glyph_names.get_relaxed (); 1375 if (names) 1376 { 1377 names->fini (); 1378 hb_free (names); 1379 } 1380 } 1381 get_glyph_nameOT::cff1::accelerator_t1382 bool get_glyph_name (hb_codepoint_t glyph, 1383 char *buf, unsigned int buf_len) const 1384 { 1385 if (unlikely (glyph >= num_glyphs)) return false; 1386 if (unlikely (!is_valid ())) return false; 1387 if (is_CID()) return false; 1388 if (unlikely (!buf_len)) return true; 1389 hb_codepoint_t sid = glyph_to_sid (glyph); 1390 const char *str; 1391 size_t str_len; 1392 if (sid < cff1_std_strings_length) 1393 { 1394 hb_bytes_t byte_str = cff1_std_strings (sid); 1395 str = byte_str.arrayZ; 1396 str_len = byte_str.length; 1397 } 1398 else 1399 { 1400 hb_ubytes_t ubyte_str = (*stringIndex)[sid - cff1_std_strings_length]; 1401 str = (const char *)ubyte_str.arrayZ; 1402 str_len = ubyte_str.length; 1403 } 1404 if (!str_len) return false; 1405 unsigned int len = hb_min (buf_len - 1, str_len); 1406 strncpy (buf, (const char*)str, len); 1407 buf[len] = '\0'; 1408 return true; 1409 } 1410 get_glyph_from_nameOT::cff1::accelerator_t1411 bool get_glyph_from_name (const char *name, int len, 1412 hb_codepoint_t *glyph) const 1413 { 1414 if (unlikely (!is_valid ())) return false; 1415 if (is_CID()) return false; 1416 if (len < 0) len = strlen (name); 1417 if (unlikely (!len)) return false; 1418 1419 retry: 1420 hb_sorted_vector_t<gname_t> *names = glyph_names.get_acquire (); 1421 if (unlikely (!names)) 1422 { 1423 names = (hb_sorted_vector_t<gname_t> *) hb_calloc (sizeof (hb_sorted_vector_t<gname_t>), 1); 1424 if (likely (names)) 1425 { 1426 names->init (); 1427 /* TODO */ 1428 1429 /* fill glyph names */ 1430 code_pair_t glyph_to_sid_cache {0, HB_CODEPOINT_INVALID}; 1431 for (hb_codepoint_t gid = 0; gid < num_glyphs; gid++) 1432 { 1433 hb_codepoint_t sid = glyph_to_sid (gid, &glyph_to_sid_cache); 1434 gname_t gname; 1435 gname.sid = sid; 1436 if (sid < cff1_std_strings_length) 1437 gname.name = cff1_std_strings (sid); 1438 else 1439 { 1440 hb_ubytes_t ustr = (*stringIndex)[sid - cff1_std_strings_length]; 1441 gname.name = hb_bytes_t ((const char*) ustr.arrayZ, ustr.length); 1442 } 1443 if (unlikely (!gname.name.arrayZ)) 1444 gname.name = hb_bytes_t ("", 0); /* To avoid nullptr. */ 1445 names->push (gname); 1446 } 1447 names->qsort (); 1448 } 1449 if (unlikely (!glyph_names.cmpexch (nullptr, names))) 1450 { 1451 if (names) 1452 { 1453 names->fini (); 1454 hb_free (names); 1455 } 1456 goto retry; 1457 } 1458 } 1459 1460 gname_t key = { hb_bytes_t (name, len), 0 }; 1461 const gname_t *gname = names ? names->bsearch (key) : nullptr; 1462 if (!gname) return false; 1463 hb_codepoint_t gid = sid_to_glyph (gname->sid); 1464 if (!gid && gname->sid) return false; 1465 *glyph = gid; 1466 return true; 1467 } 1468 1469 HB_INTERNAL bool get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const; 1470 HB_INTERNAL bool paint_glyph (hb_font_t *font, hb_codepoint_t glyph, hb_paint_funcs_t *funcs, void *data, hb_color_t foreground) const; 1471 HB_INTERNAL bool get_path (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session) const; 1472 1473 private: 1474 struct gname_t 1475 { 1476 hb_bytes_t name; 1477 uint16_t sid; 1478 cmpOT::cff1::accelerator_t::gname_t1479 static int cmp (const void *a_, const void *b_) 1480 { 1481 const gname_t *a = (const gname_t *)a_; 1482 const gname_t *b = (const gname_t *)b_; 1483 unsigned minlen = hb_min (a->name.length, b->name.length); 1484 int ret = strncmp (a->name.arrayZ, b->name.arrayZ, minlen); 1485 if (ret) return ret; 1486 return a->name.length - b->name.length; 1487 } 1488 cmpOT::cff1::accelerator_t::gname_t1489 int cmp (const gname_t &a) const { return cmp (&a, this); } 1490 }; 1491 1492 mutable hb_atomic_ptr_t<hb_sorted_vector_t<gname_t>> glyph_names; 1493 1494 typedef accelerator_templ_t<cff1_private_dict_opset_t, cff1_private_dict_values_t> SUPER; 1495 }; 1496 1497 struct accelerator_subset_t : accelerator_templ_t<cff1_private_dict_opset_subset_t, cff1_private_dict_values_subset_t> 1498 { accelerator_subset_tOT::cff1::accelerator_subset_t1499 accelerator_subset_t (hb_face_t *face) : SUPER (face) {} ~accelerator_subset_tOT::cff1::accelerator_subset_t1500 ~accelerator_subset_t () 1501 { 1502 if (cff_accelerator) 1503 cff_subset_accelerator_t::destroy (cff_accelerator); 1504 } 1505 1506 HB_INTERNAL bool subset (hb_subset_context_t *c) const; 1507 HB_INTERNAL bool serialize (hb_serialize_context_t *c, 1508 struct cff1_subset_plan &plan) const; 1509 HB_INTERNAL bool get_seac_components (hb_codepoint_t glyph, hb_codepoint_t *base, hb_codepoint_t *accent) const; 1510 1511 mutable CFF::cff_subset_accelerator_t* cff_accelerator = nullptr; 1512 1513 typedef accelerator_templ_t<cff1_private_dict_opset_subset_t, cff1_private_dict_values_subset_t> SUPER; 1514 }; 1515 1516 protected: 1517 HB_INTERNAL static hb_codepoint_t lookup_standard_encoding_for_code (hb_codepoint_t sid); 1518 HB_INTERNAL static hb_codepoint_t lookup_expert_encoding_for_code (hb_codepoint_t sid); 1519 HB_INTERNAL static hb_codepoint_t lookup_expert_charset_for_sid (hb_codepoint_t glyph); 1520 HB_INTERNAL static hb_codepoint_t lookup_expert_subset_charset_for_sid (hb_codepoint_t glyph); 1521 HB_INTERNAL static hb_codepoint_t lookup_expert_charset_for_glyph (hb_codepoint_t sid); 1522 HB_INTERNAL static hb_codepoint_t lookup_expert_subset_charset_for_glyph (hb_codepoint_t sid); 1523 HB_INTERNAL static hb_codepoint_t lookup_standard_encoding_for_sid (hb_codepoint_t code); 1524 1525 public: 1526 FixedVersion<HBUINT8> version; /* Version of CFF table. set to 0x0100u */ 1527 NNOffsetTo<CFF1NameIndex, HBUINT8> nameIndex; /* headerSize = Offset to Name INDEX. */ 1528 HBUINT8 offSize; /* offset size (unused?) */ 1529 1530 public: 1531 DEFINE_SIZE_STATIC (4); 1532 }; 1533 1534 struct cff1_accelerator_t : cff1::accelerator_t { cff1_accelerator_tOT::cff1_accelerator_t1535 cff1_accelerator_t (hb_face_t *face) : cff1::accelerator_t (face) {} 1536 }; 1537 1538 struct cff1_subset_accelerator_t : cff1::accelerator_subset_t { cff1_subset_accelerator_tOT::cff1_subset_accelerator_t1539 cff1_subset_accelerator_t (hb_face_t *face) : cff1::accelerator_subset_t (face) {} 1540 }; 1541 1542 } /* namespace OT */ 1543 1544 #endif /* HB_OT_CFF1_TABLE_HH */ 1545