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 CFF1Index CFF1CharStrings; 55 typedef Subrs<HBUINT16> CFF1Subrs; 56 57 struct CFF1FDSelect : FDSelect {}; 58 59 /* Encoding */ 60 struct Encoding0 { sanitizeCFF::Encoding061 bool sanitize (hb_sanitize_context_t *c) const 62 { 63 TRACE_SANITIZE (this); 64 return_trace (codes.sanitize (c)); 65 } 66 get_codeCFF::Encoding067 hb_codepoint_t get_code (hb_codepoint_t glyph) const 68 { 69 assert (glyph > 0); 70 glyph--; 71 if (glyph < nCodes ()) 72 { 73 return (hb_codepoint_t)codes[glyph]; 74 } 75 else 76 return CFF_UNDEF_CODE; 77 } 78 nCodesCFF::Encoding079 HBUINT8 &nCodes () { return codes.len; } nCodesCFF::Encoding080 HBUINT8 nCodes () const { return codes.len; } 81 82 ArrayOf<HBUINT8, HBUINT8> codes; 83 84 DEFINE_SIZE_ARRAY_SIZED (1, codes); 85 }; 86 87 struct Encoding1_Range { sanitizeCFF::Encoding1_Range88 bool sanitize (hb_sanitize_context_t *c) const 89 { 90 TRACE_SANITIZE (this); 91 return_trace (c->check_struct (this)); 92 } 93 94 HBUINT8 first; 95 HBUINT8 nLeft; 96 97 DEFINE_SIZE_STATIC (2); 98 }; 99 100 struct Encoding1 { sanitizeCFF::Encoding1101 bool sanitize (hb_sanitize_context_t *c) const 102 { 103 TRACE_SANITIZE (this); 104 return_trace (ranges.sanitize (c)); 105 } 106 get_codeCFF::Encoding1107 hb_codepoint_t get_code (hb_codepoint_t glyph) const 108 { 109 /* TODO: Add cache like get_sid. */ 110 assert (glyph > 0); 111 glyph--; 112 for (unsigned int i = 0; i < nRanges (); i++) 113 { 114 if (glyph <= ranges[i].nLeft) 115 { 116 hb_codepoint_t code = (hb_codepoint_t) ranges[i].first + glyph; 117 return (likely (code < 0x100) ? code: CFF_UNDEF_CODE); 118 } 119 glyph -= (ranges[i].nLeft + 1); 120 } 121 return CFF_UNDEF_CODE; 122 } 123 nRangesCFF::Encoding1124 HBUINT8 &nRanges () { return ranges.len; } nRangesCFF::Encoding1125 HBUINT8 nRanges () const { return ranges.len; } 126 127 ArrayOf<Encoding1_Range, HBUINT8> ranges; 128 129 DEFINE_SIZE_ARRAY_SIZED (1, ranges); 130 }; 131 132 struct SuppEncoding { sanitizeCFF::SuppEncoding133 bool sanitize (hb_sanitize_context_t *c) const 134 { 135 TRACE_SANITIZE (this); 136 return_trace (c->check_struct (this)); 137 } 138 139 HBUINT8 code; 140 HBUINT16 glyph; 141 142 DEFINE_SIZE_STATIC (3); 143 }; 144 145 struct CFF1SuppEncData { sanitizeCFF::CFF1SuppEncData146 bool sanitize (hb_sanitize_context_t *c) const 147 { 148 TRACE_SANITIZE (this); 149 return_trace (supps.sanitize (c)); 150 } 151 get_codesCFF::CFF1SuppEncData152 void get_codes (hb_codepoint_t sid, hb_vector_t<hb_codepoint_t> &codes) const 153 { 154 for (unsigned int i = 0; i < nSups (); i++) 155 if (sid == supps[i].glyph) 156 codes.push (supps[i].code); 157 } 158 nSupsCFF::CFF1SuppEncData159 HBUINT8 &nSups () { return supps.len; } nSupsCFF::CFF1SuppEncData160 HBUINT8 nSups () const { return supps.len; } 161 162 ArrayOf<SuppEncoding, HBUINT8> supps; 163 164 DEFINE_SIZE_ARRAY_SIZED (1, supps); 165 }; 166 167 struct Encoding 168 { 169 /* serialize a fullset Encoding */ serializeCFF::Encoding170 bool serialize (hb_serialize_context_t *c, const Encoding &src) 171 { 172 TRACE_SERIALIZE (this); 173 return_trace (c->embed (src)); 174 } 175 176 /* serialize a subset Encoding */ serializeCFF::Encoding177 bool serialize (hb_serialize_context_t *c, 178 uint8_t format, 179 unsigned int enc_count, 180 const hb_vector_t<code_pair_t>& code_ranges, 181 const hb_vector_t<code_pair_t>& supp_codes) 182 { 183 TRACE_SERIALIZE (this); 184 Encoding *dest = c->extend_min (this); 185 if (unlikely (!dest)) return_trace (false); 186 dest->format = format | ((supp_codes.length > 0) ? 0x80 : 0); 187 switch (format) { 188 case 0: 189 { 190 Encoding0 *fmt0 = c->allocate_size<Encoding0> (Encoding0::min_size + HBUINT8::static_size * enc_count); 191 if (unlikely (!fmt0)) return_trace (false); 192 fmt0->nCodes () = enc_count; 193 unsigned int glyph = 0; 194 for (unsigned int i = 0; i < code_ranges.length; i++) 195 { 196 hb_codepoint_t code = code_ranges[i].code; 197 for (int left = (int)code_ranges[i].glyph; left >= 0; left--) 198 fmt0->codes[glyph++] = code++; 199 if (unlikely (!((glyph <= 0x100) && (code <= 0x100)))) 200 return_trace (false); 201 } 202 } 203 break; 204 205 case 1: 206 { 207 Encoding1 *fmt1 = c->allocate_size<Encoding1> (Encoding1::min_size + Encoding1_Range::static_size * code_ranges.length); 208 if (unlikely (!fmt1)) return_trace (false); 209 fmt1->nRanges () = code_ranges.length; 210 for (unsigned int i = 0; i < code_ranges.length; i++) 211 { 212 if (unlikely (!((code_ranges[i].code <= 0xFF) && (code_ranges[i].glyph <= 0xFF)))) 213 return_trace (false); 214 fmt1->ranges[i].first = code_ranges[i].code; 215 fmt1->ranges[i].nLeft = code_ranges[i].glyph; 216 } 217 } 218 break; 219 220 } 221 222 if (supp_codes.length) 223 { 224 CFF1SuppEncData *suppData = c->allocate_size<CFF1SuppEncData> (CFF1SuppEncData::min_size + SuppEncoding::static_size * supp_codes.length); 225 if (unlikely (!suppData)) return_trace (false); 226 suppData->nSups () = supp_codes.length; 227 for (unsigned int i = 0; i < supp_codes.length; i++) 228 { 229 suppData->supps[i].code = supp_codes[i].code; 230 suppData->supps[i].glyph = supp_codes[i].glyph; /* actually SID */ 231 } 232 } 233 234 return_trace (true); 235 } 236 get_sizeCFF::Encoding237 unsigned int get_size () const 238 { 239 unsigned int size = min_size; 240 switch (table_format ()) 241 { 242 case 0: hb_barrier (); size += u.format0.get_size (); break; 243 case 1: hb_barrier (); size += u.format1.get_size (); break; 244 } 245 if (has_supplement ()) 246 size += suppEncData ().get_size (); 247 return size; 248 } 249 get_codeCFF::Encoding250 hb_codepoint_t get_code (hb_codepoint_t glyph) const 251 { 252 switch (table_format ()) 253 { 254 case 0: hb_barrier (); return u.format0.get_code (glyph); 255 case 1: hb_barrier (); return u.format1.get_code (glyph); 256 default:return 0; 257 } 258 } 259 table_formatCFF::Encoding260 uint8_t table_format () const { return format & 0x7F; } has_supplementCFF::Encoding261 bool has_supplement () const { return format & 0x80; } 262 get_supplement_codesCFF::Encoding263 void get_supplement_codes (hb_codepoint_t sid, hb_vector_t<hb_codepoint_t> &codes) const 264 { 265 codes.resize (0); 266 if (has_supplement ()) 267 suppEncData().get_codes (sid, codes); 268 } 269 sanitizeCFF::Encoding270 bool sanitize (hb_sanitize_context_t *c) const 271 { 272 TRACE_SANITIZE (this); 273 if (unlikely (!c->check_struct (this))) 274 return_trace (false); 275 hb_barrier (); 276 277 switch (table_format ()) 278 { 279 case 0: hb_barrier (); if (unlikely (!u.format0.sanitize (c))) { return_trace (false); } break; 280 case 1: hb_barrier (); if (unlikely (!u.format1.sanitize (c))) { return_trace (false); } break; 281 default:return_trace (false); 282 } 283 return_trace (likely (!has_supplement () || suppEncData ().sanitize (c))); 284 } 285 286 protected: suppEncDataCFF::Encoding287 const CFF1SuppEncData &suppEncData () const 288 { 289 switch (table_format ()) 290 { 291 case 0: hb_barrier (); return StructAfter<CFF1SuppEncData> (u.format0.codes[u.format0.nCodes ()-1]); 292 case 1: hb_barrier (); return StructAfter<CFF1SuppEncData> (u.format1.ranges[u.format1.nRanges ()-1]); 293 default:return Null (CFF1SuppEncData); 294 } 295 } 296 297 public: 298 HBUINT8 format; 299 union { 300 Encoding0 format0; 301 Encoding1 format1; 302 } u; 303 /* CFF1SuppEncData suppEncData; */ 304 305 DEFINE_SIZE_MIN (1); 306 }; 307 308 /* Charset */ 309 struct Charset0 310 { sanitizeCFF::Charset0311 bool sanitize (hb_sanitize_context_t *c, unsigned int num_glyphs, unsigned *num_charset_entries) const 312 { 313 TRACE_SANITIZE (this); 314 if (num_charset_entries) *num_charset_entries = num_glyphs; 315 return_trace (sids.sanitize (c, num_glyphs - 1)); 316 } 317 get_sidCFF::Charset0318 hb_codepoint_t get_sid (hb_codepoint_t glyph, unsigned num_glyphs) const 319 { 320 if (unlikely (glyph >= num_glyphs)) return 0; 321 if (unlikely (glyph == 0)) 322 return 0; 323 else 324 return sids[glyph - 1]; 325 } 326 collect_glyph_to_sid_mapCFF::Charset0327 void collect_glyph_to_sid_map (glyph_to_sid_map_t *mapping, unsigned int num_glyphs) const 328 { 329 mapping->resize (num_glyphs, false); 330 for (hb_codepoint_t gid = 1; gid < num_glyphs; gid++) 331 mapping->arrayZ[gid] = {sids[gid - 1], gid}; 332 } 333 get_glyphCFF::Charset0334 hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const 335 { 336 if (sid == 0) 337 return 0; 338 339 for (unsigned int glyph = 1; glyph < num_glyphs; glyph++) 340 { 341 if (sids[glyph-1] == sid) 342 return glyph; 343 } 344 return 0; 345 } 346 get_sizeCFF::Charset0347 static unsigned int get_size (unsigned int num_glyphs) 348 { 349 assert (num_glyphs > 0); 350 return UnsizedArrayOf<HBUINT16>::get_size (num_glyphs - 1); 351 } 352 353 UnsizedArrayOf<HBUINT16> sids; 354 355 DEFINE_SIZE_ARRAY(0, sids); 356 }; 357 358 template <typename TYPE> 359 struct Charset_Range { sanitizeCFF::Charset_Range360 bool sanitize (hb_sanitize_context_t *c) const 361 { 362 TRACE_SANITIZE (this); 363 return_trace (c->check_struct (this)); 364 } 365 366 HBUINT16 first; 367 TYPE nLeft; 368 369 DEFINE_SIZE_STATIC (HBUINT16::static_size + TYPE::static_size); 370 }; 371 372 template <typename TYPE> 373 struct Charset1_2 { sanitizeCFF::Charset1_2374 bool sanitize (hb_sanitize_context_t *c, unsigned int num_glyphs, unsigned *num_charset_entries) const 375 { 376 TRACE_SANITIZE (this); 377 num_glyphs--; 378 unsigned i; 379 for (i = 0; num_glyphs > 0; i++) 380 { 381 if (unlikely (!(ranges[i].sanitize (c) && 382 hb_barrier () && 383 (num_glyphs >= ranges[i].nLeft + 1)))) 384 return_trace (false); 385 num_glyphs -= (ranges[i].nLeft + 1); 386 } 387 if (num_charset_entries) 388 *num_charset_entries = i; 389 return_trace (true); 390 } 391 get_sidCFF::Charset1_2392 hb_codepoint_t get_sid (hb_codepoint_t glyph, unsigned num_glyphs, 393 code_pair_t *cache = nullptr) const 394 { 395 if (unlikely (glyph >= num_glyphs)) return 0; 396 unsigned i; 397 hb_codepoint_t start_glyph; 398 if (cache && likely (cache->glyph <= glyph)) 399 { 400 i = cache->code; 401 start_glyph = cache->glyph; 402 } 403 else 404 { 405 if (unlikely (glyph == 0)) return 0; 406 i = 0; 407 start_glyph = 1; 408 } 409 glyph -= start_glyph; 410 for (;; i++) 411 { 412 unsigned count = ranges[i].nLeft; 413 if (glyph <= count) 414 { 415 if (cache) 416 *cache = {i, start_glyph}; 417 return ranges[i].first + glyph; 418 } 419 count++; 420 start_glyph += count; 421 glyph -= count; 422 } 423 424 return 0; 425 } 426 collect_glyph_to_sid_mapCFF::Charset1_2427 void collect_glyph_to_sid_map (glyph_to_sid_map_t *mapping, unsigned int num_glyphs) const 428 { 429 mapping->resize (num_glyphs, false); 430 hb_codepoint_t gid = 1; 431 if (gid >= num_glyphs) 432 return; 433 for (unsigned i = 0;; i++) 434 { 435 hb_codepoint_t sid = ranges[i].first; 436 unsigned count = ranges[i].nLeft + 1; 437 unsigned last = gid + count; 438 for (unsigned j = 0; j < count; j++) 439 mapping->arrayZ[gid++] = {sid++, last - 1}; 440 441 if (gid >= num_glyphs) 442 break; 443 } 444 } 445 get_glyphCFF::Charset1_2446 hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const 447 { 448 if (sid == 0) return 0; 449 hb_codepoint_t glyph = 1; 450 for (unsigned int i = 0;; i++) 451 { 452 if (glyph >= num_glyphs) 453 return 0; 454 if ((ranges[i].first <= sid) && (sid <= ranges[i].first + ranges[i].nLeft)) 455 return glyph + (sid - ranges[i].first); 456 glyph += (ranges[i].nLeft + 1); 457 } 458 459 return 0; 460 } 461 get_sizeCFF::Charset1_2462 unsigned int get_size (unsigned int num_glyphs) const 463 { 464 int glyph = (int) num_glyphs; 465 unsigned num_ranges = 0; 466 467 assert (glyph > 0); 468 glyph--; 469 for (unsigned int i = 0; glyph > 0; i++) 470 { 471 glyph -= (ranges[i].nLeft + 1); 472 num_ranges++; 473 } 474 475 return get_size_for_ranges (num_ranges); 476 } 477 get_size_for_rangesCFF::Charset1_2478 static unsigned int get_size_for_ranges (unsigned int num_ranges) 479 { 480 return UnsizedArrayOf<Charset_Range<TYPE> >::get_size (num_ranges); 481 } 482 483 UnsizedArrayOf<Charset_Range<TYPE>> ranges; 484 485 DEFINE_SIZE_ARRAY (0, ranges); 486 }; 487 488 typedef Charset1_2<HBUINT8> Charset1; 489 typedef Charset1_2<HBUINT16> Charset2; 490 typedef Charset_Range<HBUINT8> Charset1_Range; 491 typedef Charset_Range<HBUINT16> Charset2_Range; 492 493 struct Charset 494 { 495 /* serialize a fullset Charset */ serializeCFF::Charset496 bool serialize (hb_serialize_context_t *c, const Charset &src, unsigned int num_glyphs) 497 { 498 TRACE_SERIALIZE (this); 499 return_trace (c->embed ((const char *) &src, src.get_size (num_glyphs))); 500 } 501 502 /* serialize a subset Charset */ serializeCFF::Charset503 bool serialize (hb_serialize_context_t *c, 504 uint8_t format, 505 unsigned int num_glyphs, 506 const hb_vector_t<code_pair_t>& sid_ranges) 507 { 508 TRACE_SERIALIZE (this); 509 Charset *dest = c->extend_min (this); 510 if (unlikely (!dest)) return_trace (false); 511 dest->format = format; 512 switch (format) 513 { 514 case 0: 515 { 516 Charset0 *fmt0 = c->allocate_size<Charset0> (Charset0::get_size (num_glyphs), false); 517 if (unlikely (!fmt0)) return_trace (false); 518 unsigned int glyph = 0; 519 for (unsigned int i = 0; i < sid_ranges.length; i++) 520 { 521 hb_codepoint_t sid = sid_ranges.arrayZ[i].code; 522 for (int left = (int)sid_ranges.arrayZ[i].glyph; left >= 0; left--) 523 fmt0->sids[glyph++] = sid++; 524 } 525 } 526 break; 527 528 case 1: 529 { 530 Charset1 *fmt1 = c->allocate_size<Charset1> (Charset1::get_size_for_ranges (sid_ranges.length), false); 531 if (unlikely (!fmt1)) return_trace (false); 532 hb_codepoint_t all_glyphs = 0; 533 for (unsigned int i = 0; i < sid_ranges.length; i++) 534 { 535 auto &_ = sid_ranges.arrayZ[i]; 536 all_glyphs |= _.glyph; 537 fmt1->ranges[i].first = _.code; 538 fmt1->ranges[i].nLeft = _.glyph; 539 } 540 if (unlikely (!(all_glyphs <= 0xFF))) 541 return_trace (false); 542 } 543 break; 544 545 case 2: 546 { 547 Charset2 *fmt2 = c->allocate_size<Charset2> (Charset2::get_size_for_ranges (sid_ranges.length), false); 548 if (unlikely (!fmt2)) return_trace (false); 549 hb_codepoint_t all_glyphs = 0; 550 for (unsigned int i = 0; i < sid_ranges.length; i++) 551 { 552 auto &_ = sid_ranges.arrayZ[i]; 553 all_glyphs |= _.glyph; 554 fmt2->ranges[i].first = _.code; 555 fmt2->ranges[i].nLeft = _.glyph; 556 } 557 if (unlikely (!(all_glyphs <= 0xFFFF))) 558 return_trace (false); 559 } 560 break; 561 562 } 563 return_trace (true); 564 } 565 get_sizeCFF::Charset566 unsigned int get_size (unsigned int num_glyphs) const 567 { 568 switch (format) 569 { 570 case 0: hb_barrier (); return min_size + u.format0.get_size (num_glyphs); 571 case 1: hb_barrier (); return min_size + u.format1.get_size (num_glyphs); 572 case 2: hb_barrier (); return min_size + u.format2.get_size (num_glyphs); 573 default:return 0; 574 } 575 } 576 get_sidCFF::Charset577 hb_codepoint_t get_sid (hb_codepoint_t glyph, unsigned int num_glyphs, 578 code_pair_t *cache = nullptr) const 579 { 580 switch (format) 581 { 582 case 0: hb_barrier (); return u.format0.get_sid (glyph, num_glyphs); 583 case 1: hb_barrier (); return u.format1.get_sid (glyph, num_glyphs, cache); 584 case 2: hb_barrier (); return u.format2.get_sid (glyph, num_glyphs, cache); 585 default:return 0; 586 } 587 } 588 collect_glyph_to_sid_mapCFF::Charset589 void collect_glyph_to_sid_map (glyph_to_sid_map_t *mapping, unsigned int num_glyphs) const 590 { 591 switch (format) 592 { 593 case 0: hb_barrier (); u.format0.collect_glyph_to_sid_map (mapping, num_glyphs); return; 594 case 1: hb_barrier (); u.format1.collect_glyph_to_sid_map (mapping, num_glyphs); return; 595 case 2: hb_barrier (); u.format2.collect_glyph_to_sid_map (mapping, num_glyphs); return; 596 default:return; 597 } 598 } 599 get_glyphCFF::Charset600 hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const 601 { 602 switch (format) 603 { 604 case 0: hb_barrier (); return u.format0.get_glyph (sid, num_glyphs); 605 case 1: hb_barrier (); return u.format1.get_glyph (sid, num_glyphs); 606 case 2: hb_barrier (); return u.format2.get_glyph (sid, num_glyphs); 607 default:return 0; 608 } 609 } 610 sanitizeCFF::Charset611 bool sanitize (hb_sanitize_context_t *c, unsigned *num_charset_entries) const 612 { 613 TRACE_SANITIZE (this); 614 if (unlikely (!c->check_struct (this))) 615 return_trace (false); 616 hb_barrier (); 617 618 switch (format) 619 { 620 case 0: hb_barrier (); return_trace (u.format0.sanitize (c, c->get_num_glyphs (), num_charset_entries)); 621 case 1: hb_barrier (); return_trace (u.format1.sanitize (c, c->get_num_glyphs (), num_charset_entries)); 622 case 2: hb_barrier (); return_trace (u.format2.sanitize (c, c->get_num_glyphs (), num_charset_entries)); 623 default:return_trace (false); 624 } 625 } 626 627 HBUINT8 format; 628 union { 629 Charset0 format0; 630 Charset1 format1; 631 Charset2 format2; 632 } u; 633 634 DEFINE_SIZE_MIN (1); 635 }; 636 637 struct CFF1StringIndex : CFF1Index 638 { serializeCFF::CFF1StringIndex639 bool serialize (hb_serialize_context_t *c, const CFF1StringIndex &strings, 640 const hb_vector_t<unsigned> &sidmap) 641 { 642 TRACE_SERIALIZE (this); 643 if (unlikely ((strings.count == 0) || (sidmap.length == 0))) 644 { 645 if (unlikely (!c->extend_min (this->count))) 646 return_trace (false); 647 count = 0; 648 return_trace (true); 649 } 650 651 if (unlikely (sidmap.in_error ())) return_trace (false); 652 653 // Save this in a vector since serialize() iterates it twice. 654 hb_vector_t<hb_ubytes_t> bytesArray (+ hb_iter (sidmap) 655 | hb_map (strings)); 656 657 if (unlikely (bytesArray.in_error ())) return_trace (false); 658 659 bool result = CFF1Index::serialize (c, bytesArray); 660 return_trace (result); 661 } 662 }; 663 664 struct cff1_top_dict_interp_env_t : num_interp_env_t 665 { cff1_top_dict_interp_env_tCFF::cff1_top_dict_interp_env_t666 cff1_top_dict_interp_env_t () 667 : num_interp_env_t(), prev_offset(0), last_offset(0) {} cff1_top_dict_interp_env_tCFF::cff1_top_dict_interp_env_t668 cff1_top_dict_interp_env_t (const hb_ubytes_t &bytes) 669 : num_interp_env_t(bytes), prev_offset(0), last_offset(0) {} 670 671 unsigned int prev_offset; 672 unsigned int last_offset; 673 }; 674 675 struct name_dict_values_t 676 { 677 enum name_dict_val_index_t 678 { 679 version, 680 notice, 681 copyright, 682 fullName, 683 familyName, 684 weight, 685 postscript, 686 fontName, 687 baseFontName, 688 registry, 689 ordering, 690 691 ValCount 692 }; 693 initCFF::name_dict_values_t694 void init () 695 { 696 for (unsigned int i = 0; i < ValCount; i++) 697 values[i] = CFF_UNDEF_SID; 698 } 699 operator []CFF::name_dict_values_t700 unsigned int& operator[] (unsigned int i) 701 { assert (i < ValCount); return values[i]; } 702 operator []CFF::name_dict_values_t703 unsigned int operator[] (unsigned int i) const 704 { assert (i < ValCount); return values[i]; } 705 name_op_to_indexCFF::name_dict_values_t706 static enum name_dict_val_index_t name_op_to_index (op_code_t op) 707 { 708 switch (op) { 709 default: // can't happen - just make some compiler happy 710 case OpCode_version: 711 return version; 712 case OpCode_Notice: 713 return notice; 714 case OpCode_Copyright: 715 return copyright; 716 case OpCode_FullName: 717 return fullName; 718 case OpCode_FamilyName: 719 return familyName; 720 case OpCode_Weight: 721 return weight; 722 case OpCode_PostScript: 723 return postscript; 724 case OpCode_FontName: 725 return fontName; 726 case OpCode_BaseFontName: 727 return baseFontName; 728 } 729 } 730 731 unsigned int values[ValCount]; 732 }; 733 734 struct cff1_top_dict_val_t : op_str_t 735 { 736 unsigned int last_arg_offset; 737 }; 738 739 struct cff1_top_dict_values_t : top_dict_values_t<cff1_top_dict_val_t> 740 { initCFF::cff1_top_dict_values_t741 void init () 742 { 743 top_dict_values_t<cff1_top_dict_val_t>::init (); 744 745 nameSIDs.init (); 746 ros_supplement = 0; 747 cidCount = 8720; 748 EncodingOffset = 0; 749 CharsetOffset = 0; 750 FDSelectOffset = 0; 751 privateDictInfo.init (); 752 } finiCFF::cff1_top_dict_values_t753 void fini () { top_dict_values_t<cff1_top_dict_val_t>::fini (); } 754 is_CIDCFF::cff1_top_dict_values_t755 bool is_CID () const 756 { return nameSIDs[name_dict_values_t::registry] != CFF_UNDEF_SID; } 757 758 name_dict_values_t nameSIDs; 759 unsigned int ros_supplement_offset; 760 unsigned int ros_supplement; 761 unsigned int cidCount; 762 763 int EncodingOffset; 764 int CharsetOffset; 765 int FDSelectOffset; 766 table_info_t privateDictInfo; 767 }; 768 769 struct cff1_top_dict_opset_t : top_dict_opset_t<cff1_top_dict_val_t> 770 { process_opCFF::cff1_top_dict_opset_t771 static void process_op (op_code_t op, cff1_top_dict_interp_env_t& env, cff1_top_dict_values_t& dictval) 772 { 773 cff1_top_dict_val_t val; 774 val.last_arg_offset = (env.last_offset-1) - dictval.opStart; /* offset to the last argument */ 775 776 switch (op) { 777 case OpCode_version: 778 case OpCode_Notice: 779 case OpCode_Copyright: 780 case OpCode_FullName: 781 case OpCode_FontName: 782 case OpCode_FamilyName: 783 case OpCode_Weight: 784 case OpCode_PostScript: 785 case OpCode_BaseFontName: 786 dictval.nameSIDs[name_dict_values_t::name_op_to_index (op)] = env.argStack.pop_uint (); 787 env.clear_args (); 788 break; 789 case OpCode_isFixedPitch: 790 case OpCode_ItalicAngle: 791 case OpCode_UnderlinePosition: 792 case OpCode_UnderlineThickness: 793 case OpCode_PaintType: 794 case OpCode_CharstringType: 795 case OpCode_UniqueID: 796 case OpCode_StrokeWidth: 797 case OpCode_SyntheticBase: 798 case OpCode_CIDFontVersion: 799 case OpCode_CIDFontRevision: 800 case OpCode_CIDFontType: 801 case OpCode_UIDBase: 802 case OpCode_FontBBox: 803 case OpCode_XUID: 804 case OpCode_BaseFontBlend: 805 env.clear_args (); 806 break; 807 808 case OpCode_CIDCount: 809 dictval.cidCount = env.argStack.pop_uint (); 810 env.clear_args (); 811 break; 812 813 case OpCode_ROS: 814 dictval.ros_supplement = env.argStack.pop_uint (); 815 dictval.nameSIDs[name_dict_values_t::ordering] = env.argStack.pop_uint (); 816 dictval.nameSIDs[name_dict_values_t::registry] = env.argStack.pop_uint (); 817 env.clear_args (); 818 break; 819 820 case OpCode_Encoding: 821 dictval.EncodingOffset = env.argStack.pop_int (); 822 env.clear_args (); 823 if (unlikely (dictval.EncodingOffset == 0)) return; 824 break; 825 826 case OpCode_charset: 827 dictval.CharsetOffset = env.argStack.pop_int (); 828 env.clear_args (); 829 if (unlikely (dictval.CharsetOffset == 0)) return; 830 break; 831 832 case OpCode_FDSelect: 833 dictval.FDSelectOffset = env.argStack.pop_int (); 834 env.clear_args (); 835 break; 836 837 case OpCode_Private: 838 dictval.privateDictInfo.offset = env.argStack.pop_int (); 839 dictval.privateDictInfo.size = env.argStack.pop_uint (); 840 env.clear_args (); 841 break; 842 843 default: 844 env.last_offset = env.str_ref.get_offset (); 845 top_dict_opset_t<cff1_top_dict_val_t>::process_op (op, env, dictval); 846 /* Record this operand below if stack is empty, otherwise done */ 847 if (!env.argStack.is_empty ()) return; 848 break; 849 } 850 851 if (unlikely (env.in_error ())) return; 852 853 dictval.add_op (op, env.str_ref, val); 854 } 855 }; 856 857 struct cff1_font_dict_values_t : dict_values_t<op_str_t> 858 { initCFF::cff1_font_dict_values_t859 void init () 860 { 861 dict_values_t<op_str_t>::init (); 862 privateDictInfo.init (); 863 fontName = CFF_UNDEF_SID; 864 } finiCFF::cff1_font_dict_values_t865 void fini () { dict_values_t<op_str_t>::fini (); } 866 867 table_info_t privateDictInfo; 868 unsigned int fontName; 869 }; 870 871 struct cff1_font_dict_opset_t : dict_opset_t 872 { process_opCFF::cff1_font_dict_opset_t873 static void process_op (op_code_t op, num_interp_env_t& env, cff1_font_dict_values_t& dictval) 874 { 875 switch (op) { 876 case OpCode_FontName: 877 dictval.fontName = env.argStack.pop_uint (); 878 env.clear_args (); 879 break; 880 case OpCode_FontMatrix: 881 case OpCode_PaintType: 882 env.clear_args (); 883 break; 884 case OpCode_Private: 885 dictval.privateDictInfo.offset = env.argStack.pop_uint (); 886 dictval.privateDictInfo.size = 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); 899 } 900 }; 901 902 template <typename VAL> 903 struct cff1_private_dict_values_base_t : dict_values_t<VAL> 904 { initCFF::cff1_private_dict_values_base_t905 void init () 906 { 907 dict_values_t<VAL>::init (); 908 subrsOffset = 0; 909 localSubrs = &Null (CFF1Subrs); 910 } finiCFF::cff1_private_dict_values_base_t911 void fini () { dict_values_t<VAL>::fini (); } 912 913 int subrsOffset; 914 const CFF1Subrs *localSubrs; 915 }; 916 917 typedef cff1_private_dict_values_base_t<op_str_t> cff1_private_dict_values_subset_t; 918 typedef cff1_private_dict_values_base_t<num_dict_val_t> cff1_private_dict_values_t; 919 920 struct cff1_private_dict_opset_t : dict_opset_t 921 { process_opCFF::cff1_private_dict_opset_t922 static void process_op (op_code_t op, num_interp_env_t& env, cff1_private_dict_values_t& dictval) 923 { 924 num_dict_val_t val; 925 val.init (); 926 927 switch (op) { 928 case OpCode_BlueValues: 929 case OpCode_OtherBlues: 930 case OpCode_FamilyBlues: 931 case OpCode_FamilyOtherBlues: 932 case OpCode_StemSnapH: 933 case OpCode_StemSnapV: 934 case OpCode_StdHW: 935 case OpCode_StdVW: 936 case OpCode_BlueScale: 937 case OpCode_BlueShift: 938 case OpCode_BlueFuzz: 939 case OpCode_ForceBold: 940 case OpCode_LanguageGroup: 941 case OpCode_ExpansionFactor: 942 case OpCode_initialRandomSeed: 943 case OpCode_defaultWidthX: 944 case OpCode_nominalWidthX: 945 env.clear_args (); 946 break; 947 case OpCode_Subrs: 948 dictval.subrsOffset = env.argStack.pop_int (); 949 env.clear_args (); 950 break; 951 952 default: 953 dict_opset_t::process_op (op, env); 954 if (!env.argStack.is_empty ()) return; 955 break; 956 } 957 958 if (unlikely (env.in_error ())) return; 959 960 dictval.add_op (op, env.str_ref, val); 961 } 962 }; 963 964 struct cff1_private_dict_opset_subset_t : dict_opset_t 965 { process_opCFF::cff1_private_dict_opset_subset_t966 static void process_op (op_code_t op, num_interp_env_t& env, cff1_private_dict_values_subset_t& dictval) 967 { 968 switch (op) { 969 case OpCode_BlueValues: 970 case OpCode_OtherBlues: 971 case OpCode_FamilyBlues: 972 case OpCode_FamilyOtherBlues: 973 case OpCode_StemSnapH: 974 case OpCode_StemSnapV: 975 case OpCode_StdHW: 976 case OpCode_StdVW: 977 case OpCode_BlueScale: 978 case OpCode_BlueShift: 979 case OpCode_BlueFuzz: 980 case OpCode_ForceBold: 981 case OpCode_LanguageGroup: 982 case OpCode_ExpansionFactor: 983 case OpCode_initialRandomSeed: 984 case OpCode_defaultWidthX: 985 case OpCode_nominalWidthX: 986 env.clear_args (); 987 break; 988 989 case OpCode_Subrs: 990 dictval.subrsOffset = env.argStack.pop_int (); 991 env.clear_args (); 992 break; 993 994 default: 995 dict_opset_t::process_op (op, env); 996 if (!env.argStack.is_empty ()) return; 997 break; 998 } 999 1000 if (unlikely (env.in_error ())) return; 1001 1002 dictval.add_op (op, env.str_ref); 1003 } 1004 }; 1005 1006 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; 1007 typedef dict_interpreter_t<cff1_font_dict_opset_t, cff1_font_dict_values_t> cff1_font_dict_interpreter_t; 1008 1009 typedef CFF1Index CFF1NameIndex; 1010 typedef CFF1Index CFF1TopDictIndex; 1011 1012 struct cff1_font_dict_values_mod_t 1013 { cff1_font_dict_values_mod_tCFF::cff1_font_dict_values_mod_t1014 cff1_font_dict_values_mod_t() { init (); } 1015 initCFF::cff1_font_dict_values_mod_t1016 void init () { init ( &Null (cff1_font_dict_values_t), CFF_UNDEF_SID ); } 1017 initCFF::cff1_font_dict_values_mod_t1018 void init (const cff1_font_dict_values_t *base_, 1019 unsigned int fontName_) 1020 { 1021 base = base_; 1022 fontName = fontName_; 1023 privateDictInfo.init (); 1024 } 1025 get_countCFF::cff1_font_dict_values_mod_t1026 unsigned get_count () const { return base->get_count (); } 1027 operator []CFF::cff1_font_dict_values_mod_t1028 const op_str_t &operator [] (unsigned int i) const { return (*base)[i]; } 1029 1030 const cff1_font_dict_values_t *base; 1031 table_info_t privateDictInfo; 1032 unsigned int fontName; 1033 }; 1034 1035 struct CFF1FDArray : FDArray<HBUINT16> 1036 { 1037 /* FDArray::serialize() requires this partial specialization to compile */ 1038 template <typename ITER, typename OP_SERIALIZER> serializeCFF::CFF1FDArray1039 bool serialize (hb_serialize_context_t *c, ITER it, OP_SERIALIZER& opszr) 1040 { return FDArray<HBUINT16>::serialize<cff1_font_dict_values_mod_t, cff1_font_dict_values_mod_t> (c, it, opszr); } 1041 }; 1042 1043 } /* namespace CFF */ 1044 1045 namespace OT { 1046 1047 using namespace CFF; 1048 1049 struct cff1 1050 { 1051 static constexpr hb_tag_t tableTag = HB_OT_TAG_CFF1; 1052 sanitizeOT::cff11053 bool sanitize (hb_sanitize_context_t *c) const 1054 { 1055 TRACE_SANITIZE (this); 1056 return_trace (c->check_struct (this) && 1057 hb_barrier () && 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 hb_barrier (); 1089 1090 topDictIndex = &StructAtOffsetOrNull<CFF1TopDictIndex> (nameIndex, nameIndex->get_size (), sc); 1091 if (topDictIndex == &Null (CFF1TopDictIndex) || (topDictIndex->count == 0)) 1092 goto fail; 1093 hb_barrier (); 1094 1095 { /* parse top dict */ 1096 const hb_ubytes_t topDictStr = (*topDictIndex)[0]; 1097 if (unlikely (!topDictStr.sanitize (&sc))) goto fail; 1098 hb_barrier (); 1099 cff1_top_dict_interp_env_t env (topDictStr); 1100 cff1_top_dict_interpreter_t top_interp (env); 1101 if (unlikely (!top_interp.interpret (topDict))) goto fail; 1102 } 1103 1104 if (is_predef_charset ()) 1105 charset = &Null (Charset); 1106 else 1107 { 1108 charset = &StructAtOffsetOrNull<Charset> (cff, topDict.CharsetOffset, sc, &num_charset_entries); 1109 if (unlikely (charset == &Null (Charset))) goto fail; 1110 } 1111 1112 fdCount = 1; 1113 if (is_CID ()) 1114 { 1115 fdArray = &StructAtOffsetOrNull<CFF1FDArray> (cff, topDict.FDArrayOffset, sc); 1116 fdSelect = &StructAtOffsetOrNull<CFF1FDSelect> (cff, topDict.FDSelectOffset, sc, fdArray->count); 1117 if (unlikely (fdArray == &Null (CFF1FDArray) || 1118 fdSelect == &Null (CFF1FDSelect))) 1119 goto fail; 1120 1121 fdCount = fdArray->count; 1122 } 1123 else 1124 { 1125 fdArray = &Null (CFF1FDArray); 1126 fdSelect = &Null (CFF1FDSelect); 1127 } 1128 1129 encoding = &Null (Encoding); 1130 if (is_CID ()) 1131 { 1132 if (unlikely (charset == &Null (Charset))) goto fail; 1133 } 1134 else 1135 { 1136 if (!is_predef_encoding ()) 1137 { 1138 encoding = &StructAtOffsetOrNull<Encoding> (cff, topDict.EncodingOffset, sc); 1139 if (unlikely (encoding == &Null (Encoding))) goto fail; 1140 } 1141 } 1142 1143 stringIndex = &StructAtOffsetOrNull<CFF1StringIndex> (topDictIndex, topDictIndex->get_size (), sc); 1144 if (stringIndex == &Null (CFF1StringIndex)) 1145 goto fail; 1146 1147 globalSubrs = &StructAtOffsetOrNull<CFF1Subrs> (stringIndex, stringIndex->get_size (), sc); 1148 charStrings = &StructAtOffsetOrNull<CFF1CharStrings> (cff, topDict.charStringsOffset, sc); 1149 if (charStrings == &Null (CFF1CharStrings)) 1150 goto fail; 1151 1152 num_glyphs = charStrings->count; 1153 if (num_glyphs != sc.get_num_glyphs ()) 1154 goto fail; 1155 1156 if (unlikely (!privateDicts.resize (fdCount))) 1157 goto fail; 1158 for (unsigned int i = 0; i < fdCount; i++) 1159 privateDicts[i].init (); 1160 1161 // parse CID font dicts and gather private dicts 1162 if (is_CID ()) 1163 { 1164 for (unsigned int i = 0; i < fdCount; i++) 1165 { 1166 hb_ubytes_t fontDictStr = (*fdArray)[i]; 1167 if (unlikely (!fontDictStr.sanitize (&sc))) goto fail; 1168 hb_barrier (); 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 = StructAtOffsetOrNull<UnsizedByteStr> (cff, font->privateDictInfo.offset, sc, font->privateDictInfo.size).as_ubytes (font->privateDictInfo.size); 1179 if (unlikely (privDictStr == (const unsigned char *) &Null (UnsizedByteStr))) 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, sc); 1186 } 1187 } 1188 else /* non-CID */ 1189 { 1190 cff1_top_dict_values_t *font = &topDict; 1191 PRIVDICTVAL *priv = &privateDicts[0]; 1192 1193 const hb_ubytes_t privDictStr = StructAtOffsetOrNull<UnsizedByteStr> (cff, font->privateDictInfo.offset, sc, font->privateDictInfo.size).as_ubytes (font->privateDictInfo.size); 1194 if (unlikely (privDictStr == (const unsigned char *) &Null (UnsizedByteStr))) goto fail; 1195 num_interp_env_t env (privDictStr); 1196 dict_interpreter_t<PRIVOPSET, PRIVDICTVAL> priv_interp (env); 1197 priv->init (); 1198 if (unlikely (!priv_interp.interpret (*priv))) goto fail; 1199 1200 priv->localSubrs = &StructAtOffsetOrNull<CFF1Subrs> (&privDictStr, priv->subrsOffset, sc); 1201 hb_barrier (); 1202 } 1203 1204 return; 1205 1206 fail: 1207 _fini (); 1208 } ~accelerator_templ_tOT::cff1::accelerator_templ_t1209 ~accelerator_templ_t () { _fini (); } _finiOT::cff1::accelerator_templ_t1210 void _fini () 1211 { 1212 sc.end_processing (); 1213 topDict.fini (); 1214 fontDicts.fini (); 1215 privateDicts.fini (); 1216 hb_blob_destroy (blob); 1217 blob = nullptr; 1218 } 1219 get_blobOT::cff1::accelerator_templ_t1220 hb_blob_t *get_blob () const { return blob; } 1221 is_validOT::cff1::accelerator_templ_t1222 bool is_valid () const { return blob; } is_CIDOT::cff1::accelerator_templ_t1223 bool is_CID () const { return topDict.is_CID (); } 1224 is_predef_charsetOT::cff1::accelerator_templ_t1225 bool is_predef_charset () const { return topDict.CharsetOffset <= ExpertSubsetCharset; } 1226 std_code_to_glyphOT::cff1::accelerator_templ_t1227 unsigned int std_code_to_glyph (hb_codepoint_t code) const 1228 { 1229 hb_codepoint_t sid = lookup_standard_encoding_for_sid (code); 1230 if (unlikely (sid == CFF_UNDEF_SID)) 1231 return 0; 1232 1233 if (charset != &Null (Charset)) 1234 return charset->get_glyph (sid, num_glyphs); 1235 else if ((topDict.CharsetOffset == ISOAdobeCharset) 1236 && (code <= 228 /*zcaron*/)) return sid; 1237 return 0; 1238 } 1239 is_predef_encodingOT::cff1::accelerator_templ_t1240 bool is_predef_encoding () const { return topDict.EncodingOffset <= ExpertEncoding; } 1241 glyph_to_codeOT::cff1::accelerator_templ_t1242 hb_codepoint_t glyph_to_code (hb_codepoint_t glyph, 1243 code_pair_t *glyph_to_sid_cache = nullptr) const 1244 { 1245 if (encoding != &Null (Encoding)) 1246 return encoding->get_code (glyph); 1247 else 1248 { 1249 hb_codepoint_t sid = glyph_to_sid (glyph, glyph_to_sid_cache); 1250 if (sid == 0) return 0; 1251 hb_codepoint_t code = 0; 1252 switch (topDict.EncodingOffset) 1253 { 1254 case StandardEncoding: 1255 code = lookup_standard_encoding_for_code (sid); 1256 break; 1257 case ExpertEncoding: 1258 code = lookup_expert_encoding_for_code (sid); 1259 break; 1260 default: 1261 break; 1262 } 1263 return code; 1264 } 1265 } 1266 create_glyph_to_sid_mapOT::cff1::accelerator_templ_t1267 glyph_to_sid_map_t *create_glyph_to_sid_map () const 1268 { 1269 if (charset != &Null (Charset)) 1270 { 1271 auto *mapping = (glyph_to_sid_map_t *) hb_malloc (sizeof (glyph_to_sid_map_t)); 1272 if (unlikely (!mapping)) return nullptr; 1273 mapping = new (mapping) glyph_to_sid_map_t (); 1274 mapping->push (code_pair_t {0, 1}); 1275 charset->collect_glyph_to_sid_map (mapping, num_glyphs); 1276 return mapping; 1277 } 1278 else 1279 return nullptr; 1280 } 1281 glyph_to_sidOT::cff1::accelerator_templ_t1282 hb_codepoint_t glyph_to_sid (hb_codepoint_t glyph, 1283 code_pair_t *cache = nullptr) const 1284 { 1285 if (charset != &Null (Charset)) 1286 return charset->get_sid (glyph, num_glyphs, cache); 1287 else 1288 { 1289 hb_codepoint_t sid = 0; 1290 switch (topDict.CharsetOffset) 1291 { 1292 case ISOAdobeCharset: 1293 if (glyph <= 228 /*zcaron*/) sid = glyph; 1294 break; 1295 case ExpertCharset: 1296 sid = lookup_expert_charset_for_sid (glyph); 1297 break; 1298 case ExpertSubsetCharset: 1299 sid = lookup_expert_subset_charset_for_sid (glyph); 1300 break; 1301 default: 1302 break; 1303 } 1304 return sid; 1305 } 1306 } 1307 sid_to_glyphOT::cff1::accelerator_templ_t1308 hb_codepoint_t sid_to_glyph (hb_codepoint_t sid) const 1309 { 1310 if (charset != &Null (Charset)) 1311 return charset->get_glyph (sid, num_glyphs); 1312 else 1313 { 1314 hb_codepoint_t glyph = 0; 1315 switch (topDict.CharsetOffset) 1316 { 1317 case ISOAdobeCharset: 1318 if (sid <= 228 /*zcaron*/) glyph = sid; 1319 break; 1320 case ExpertCharset: 1321 glyph = lookup_expert_charset_for_glyph (sid); 1322 break; 1323 case ExpertSubsetCharset: 1324 glyph = lookup_expert_subset_charset_for_glyph (sid); 1325 break; 1326 default: 1327 break; 1328 } 1329 return glyph; 1330 } 1331 } 1332 1333 protected: 1334 hb_sanitize_context_t sc; 1335 1336 public: 1337 hb_blob_t *blob = nullptr; 1338 const Encoding *encoding = nullptr; 1339 const Charset *charset = nullptr; 1340 const CFF1NameIndex *nameIndex = nullptr; 1341 const CFF1TopDictIndex *topDictIndex = nullptr; 1342 const CFF1StringIndex *stringIndex = nullptr; 1343 const CFF1Subrs *globalSubrs = nullptr; 1344 const CFF1CharStrings *charStrings = nullptr; 1345 const CFF1FDArray *fdArray = nullptr; 1346 const CFF1FDSelect *fdSelect = nullptr; 1347 unsigned int fdCount = 0; 1348 1349 cff1_top_dict_values_t topDict; 1350 hb_vector_t<cff1_font_dict_values_t> 1351 fontDicts; 1352 hb_vector_t<PRIVDICTVAL> privateDicts; 1353 1354 unsigned int num_glyphs = 0; 1355 unsigned int num_charset_entries = 0; 1356 }; 1357 1358 struct accelerator_t : accelerator_templ_t<cff1_private_dict_opset_t, cff1_private_dict_values_t> 1359 { accelerator_tOT::cff1::accelerator_t1360 accelerator_t (hb_face_t *face) : SUPER (face) 1361 { 1362 glyph_names.set_relaxed (nullptr); 1363 1364 if (!is_valid ()) return; 1365 if (is_CID ()) return; 1366 } ~accelerator_tOT::cff1::accelerator_t1367 ~accelerator_t () 1368 { 1369 hb_sorted_vector_t<gname_t> *names = glyph_names.get_relaxed (); 1370 if (names) 1371 { 1372 names->fini (); 1373 hb_free (names); 1374 } 1375 } 1376 get_glyph_nameOT::cff1::accelerator_t1377 bool get_glyph_name (hb_codepoint_t glyph, 1378 char *buf, unsigned int buf_len) const 1379 { 1380 if (unlikely (glyph >= num_glyphs)) return false; 1381 if (unlikely (!is_valid ())) return false; 1382 if (is_CID()) return false; 1383 if (unlikely (!buf_len)) return true; 1384 hb_codepoint_t sid = glyph_to_sid (glyph); 1385 const char *str; 1386 size_t str_len; 1387 if (sid < cff1_std_strings_length) 1388 { 1389 hb_bytes_t byte_str = cff1_std_strings (sid); 1390 str = byte_str.arrayZ; 1391 str_len = byte_str.length; 1392 } 1393 else 1394 { 1395 hb_ubytes_t ubyte_str = (*stringIndex)[sid - cff1_std_strings_length]; 1396 str = (const char *)ubyte_str.arrayZ; 1397 str_len = ubyte_str.length; 1398 } 1399 if (!str_len) return false; 1400 unsigned int len = hb_min (buf_len - 1, str_len); 1401 strncpy (buf, (const char*)str, len); 1402 buf[len] = '\0'; 1403 return true; 1404 } 1405 get_glyph_from_nameOT::cff1::accelerator_t1406 bool get_glyph_from_name (const char *name, int len, 1407 hb_codepoint_t *glyph) const 1408 { 1409 if (unlikely (!is_valid ())) return false; 1410 if (is_CID()) return false; 1411 if (len < 0) len = strlen (name); 1412 if (unlikely (!len)) return false; 1413 1414 retry: 1415 hb_sorted_vector_t<gname_t> *names = glyph_names.get_acquire (); 1416 if (unlikely (!names)) 1417 { 1418 names = (hb_sorted_vector_t<gname_t> *) hb_calloc (1, sizeof (hb_sorted_vector_t<gname_t>)); 1419 if (likely (names)) 1420 { 1421 names->init (); 1422 /* TODO */ 1423 1424 /* fill glyph names */ 1425 code_pair_t glyph_to_sid_cache {0, HB_CODEPOINT_INVALID}; 1426 for (hb_codepoint_t gid = 0; gid < num_glyphs; gid++) 1427 { 1428 hb_codepoint_t sid = glyph_to_sid (gid, &glyph_to_sid_cache); 1429 gname_t gname; 1430 gname.sid = sid; 1431 if (sid < cff1_std_strings_length) 1432 gname.name = cff1_std_strings (sid); 1433 else 1434 { 1435 hb_ubytes_t ustr = (*stringIndex)[sid - cff1_std_strings_length]; 1436 gname.name = hb_bytes_t ((const char*) ustr.arrayZ, ustr.length); 1437 } 1438 if (unlikely (!gname.name.arrayZ)) 1439 gname.name = hb_bytes_t ("", 0); /* To avoid nullptr. */ 1440 names->push (gname); 1441 } 1442 names->qsort (); 1443 } 1444 if (unlikely (!glyph_names.cmpexch (nullptr, names))) 1445 { 1446 if (names) 1447 { 1448 names->fini (); 1449 hb_free (names); 1450 } 1451 goto retry; 1452 } 1453 } 1454 1455 gname_t key = { hb_bytes_t (name, len), 0 }; 1456 const gname_t *gname = names ? names->bsearch (key) : nullptr; 1457 if (!gname) return false; 1458 hb_codepoint_t gid = sid_to_glyph (gname->sid); 1459 if (!gid && gname->sid) return false; 1460 *glyph = gid; 1461 return true; 1462 } 1463 1464 HB_INTERNAL bool get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const; 1465 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; 1466 HB_INTERNAL bool get_path (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session) const; 1467 1468 private: 1469 struct gname_t 1470 { 1471 hb_bytes_t name; 1472 uint16_t sid; 1473 cmpOT::cff1::accelerator_t::gname_t1474 static int cmp (const void *a_, const void *b_) 1475 { 1476 const gname_t *a = (const gname_t *)a_; 1477 const gname_t *b = (const gname_t *)b_; 1478 unsigned minlen = hb_min (a->name.length, b->name.length); 1479 int ret = strncmp (a->name.arrayZ, b->name.arrayZ, minlen); 1480 if (ret) return ret; 1481 return a->name.length - b->name.length; 1482 } 1483 cmpOT::cff1::accelerator_t::gname_t1484 int cmp (const gname_t &a) const { return cmp (&a, this); } 1485 }; 1486 1487 mutable hb_atomic_ptr_t<hb_sorted_vector_t<gname_t>> glyph_names; 1488 1489 typedef accelerator_templ_t<cff1_private_dict_opset_t, cff1_private_dict_values_t> SUPER; 1490 }; 1491 1492 struct accelerator_subset_t : accelerator_templ_t<cff1_private_dict_opset_subset_t, cff1_private_dict_values_subset_t> 1493 { accelerator_subset_tOT::cff1::accelerator_subset_t1494 accelerator_subset_t (hb_face_t *face) : SUPER (face) {} ~accelerator_subset_tOT::cff1::accelerator_subset_t1495 ~accelerator_subset_t () 1496 { 1497 if (cff_accelerator) 1498 cff_subset_accelerator_t::destroy (cff_accelerator); 1499 } 1500 1501 HB_INTERNAL bool subset (hb_subset_context_t *c) const; 1502 HB_INTERNAL bool serialize (hb_serialize_context_t *c, 1503 struct cff1_subset_plan &plan) const; 1504 HB_INTERNAL bool get_seac_components (hb_codepoint_t glyph, hb_codepoint_t *base, hb_codepoint_t *accent) const; 1505 1506 mutable CFF::cff_subset_accelerator_t* cff_accelerator = nullptr; 1507 1508 typedef accelerator_templ_t<cff1_private_dict_opset_subset_t, cff1_private_dict_values_subset_t> SUPER; 1509 }; 1510 1511 protected: 1512 HB_INTERNAL static hb_codepoint_t lookup_standard_encoding_for_code (hb_codepoint_t sid); 1513 HB_INTERNAL static hb_codepoint_t lookup_expert_encoding_for_code (hb_codepoint_t sid); 1514 HB_INTERNAL static hb_codepoint_t lookup_expert_charset_for_sid (hb_codepoint_t glyph); 1515 HB_INTERNAL static hb_codepoint_t lookup_expert_subset_charset_for_sid (hb_codepoint_t glyph); 1516 HB_INTERNAL static hb_codepoint_t lookup_expert_charset_for_glyph (hb_codepoint_t sid); 1517 HB_INTERNAL static hb_codepoint_t lookup_expert_subset_charset_for_glyph (hb_codepoint_t sid); 1518 HB_INTERNAL static hb_codepoint_t lookup_standard_encoding_for_sid (hb_codepoint_t code); 1519 1520 public: 1521 FixedVersion<HBUINT8> version; /* Version of CFF table. set to 0x0100u */ 1522 NNOffsetTo<CFF1NameIndex, HBUINT8> nameIndex; /* headerSize = Offset to Name INDEX. */ 1523 HBUINT8 offSize; /* offset size (unused?) */ 1524 1525 public: 1526 DEFINE_SIZE_STATIC (4); 1527 }; 1528 1529 struct cff1_accelerator_t : cff1::accelerator_t { cff1_accelerator_tOT::cff1_accelerator_t1530 cff1_accelerator_t (hb_face_t *face) : cff1::accelerator_t (face) {} 1531 }; 1532 1533 struct cff1_subset_accelerator_t : cff1::accelerator_subset_t { cff1_subset_accelerator_tOT::cff1_subset_accelerator_t1534 cff1_subset_accelerator_t (hb_face_t *face) : cff1::accelerator_subset_t (face) {} 1535 }; 1536 1537 } /* namespace OT */ 1538 1539 #endif /* HB_OT_CFF1_TABLE_HH */ 1540