1 /* 2 * Copyright © 2018 Adobe Inc. 3 * 4 * This is part of HarfBuzz, a text shaping library. 5 * 6 * Permission is hereby granted, without written agreement and without 7 * license or royalty fees, to use, copy, modify, and distribute this 8 * software and its documentation for any purpose, provided that the 9 * above copyright notice and the following two paragraphs appear in 10 * all copies of this software. 11 * 12 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR 13 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 14 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN 15 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 16 * DAMAGE. 17 * 18 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, 19 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 20 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS 21 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO 22 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 23 * 24 * Adobe Author(s): Michiharu Ariza 25 */ 26 27 #ifndef HB_OT_CFF1_TABLE_HH 28 #define HB_OT_CFF1_TABLE_HH 29 30 #include "hb-ot-cff-common.hh" 31 #include "hb-subset-cff1.hh" 32 #include "hb-draw.hh" 33 34 #define HB_STRING_ARRAY_NAME cff1_std_strings 35 #define HB_STRING_ARRAY_LIST "hb-ot-cff1-std-str.hh" 36 #include "hb-string-array.hh" 37 #undef HB_STRING_ARRAY_LIST 38 #undef HB_STRING_ARRAY_NAME 39 40 namespace CFF { 41 42 /* 43 * CFF -- Compact Font Format (CFF) 44 * https://www.adobe.com/content/dam/acom/en/devnet/font/pdfs/5176.CFF.pdf 45 */ 46 #define HB_OT_TAG_cff1 HB_TAG('C','F','F',' ') 47 48 #define CFF_UNDEF_SID CFF_UNDEF_CODE 49 50 enum EncodingID { StandardEncoding = 0, ExpertEncoding = 1 }; 51 enum CharsetID { ISOAdobeCharset = 0, ExpertCharset = 1, ExpertSubsetCharset = 2 }; 52 53 typedef CFFIndex<HBUINT16> CFF1Index; 54 template <typename Type> struct CFF1IndexOf : CFFIndexOf<HBUINT16, Type> {}; 55 56 typedef CFFIndex<HBUINT16> CFF1Index; 57 typedef CFF1Index CFF1CharStrings; 58 typedef Subrs<HBUINT16> CFF1Subrs; 59 60 struct CFF1FDSelect : FDSelect {}; 61 62 /* Encoding */ 63 struct Encoding0 { sanitizeCFF::Encoding064 bool sanitize (hb_sanitize_context_t *c) const 65 { 66 TRACE_SANITIZE (this); 67 return_trace (codes.sanitize (c)); 68 } 69 get_codeCFF::Encoding070 hb_codepoint_t get_code (hb_codepoint_t glyph) const 71 { 72 assert (glyph > 0); 73 glyph--; 74 if (glyph < nCodes ()) 75 { 76 return (hb_codepoint_t)codes[glyph]; 77 } 78 else 79 return CFF_UNDEF_CODE; 80 } 81 nCodesCFF::Encoding082 HBUINT8 &nCodes () { return codes.len; } nCodesCFF::Encoding083 HBUINT8 nCodes () const { return codes.len; } 84 85 ArrayOf<HBUINT8, HBUINT8> codes; 86 87 DEFINE_SIZE_ARRAY_SIZED (1, codes); 88 }; 89 90 struct Encoding1_Range { sanitizeCFF::Encoding1_Range91 bool sanitize (hb_sanitize_context_t *c) const 92 { 93 TRACE_SANITIZE (this); 94 return_trace (c->check_struct (this)); 95 } 96 97 HBUINT8 first; 98 HBUINT8 nLeft; 99 100 DEFINE_SIZE_STATIC (2); 101 }; 102 103 struct Encoding1 { sanitizeCFF::Encoding1104 bool sanitize (hb_sanitize_context_t *c) const 105 { 106 TRACE_SANITIZE (this); 107 return_trace (ranges.sanitize (c)); 108 } 109 get_codeCFF::Encoding1110 hb_codepoint_t get_code (hb_codepoint_t glyph) const 111 { 112 assert (glyph > 0); 113 glyph--; 114 for (unsigned int i = 0; i < nRanges (); i++) 115 { 116 if (glyph <= ranges[i].nLeft) 117 { 118 hb_codepoint_t code = (hb_codepoint_t) ranges[i].first + glyph; 119 return (likely (code < 0x100) ? code: CFF_UNDEF_CODE); 120 } 121 glyph -= (ranges[i].nLeft + 1); 122 } 123 return CFF_UNDEF_CODE; 124 } 125 nRangesCFF::Encoding1126 HBUINT8 &nRanges () { return ranges.len; } nRangesCFF::Encoding1127 HBUINT8 nRanges () const { return ranges.len; } 128 129 ArrayOf<Encoding1_Range, HBUINT8> ranges; 130 131 DEFINE_SIZE_ARRAY_SIZED (1, ranges); 132 }; 133 134 struct SuppEncoding { sanitizeCFF::SuppEncoding135 bool sanitize (hb_sanitize_context_t *c) const 136 { 137 TRACE_SANITIZE (this); 138 return_trace (c->check_struct (this)); 139 } 140 141 HBUINT8 code; 142 HBUINT16 glyph; 143 144 DEFINE_SIZE_STATIC (3); 145 }; 146 147 struct CFF1SuppEncData { sanitizeCFF::CFF1SuppEncData148 bool sanitize (hb_sanitize_context_t *c) const 149 { 150 TRACE_SANITIZE (this); 151 return_trace (supps.sanitize (c)); 152 } 153 get_codesCFF::CFF1SuppEncData154 void get_codes (hb_codepoint_t sid, hb_vector_t<hb_codepoint_t> &codes) const 155 { 156 for (unsigned int i = 0; i < nSups (); i++) 157 if (sid == supps[i].glyph) 158 codes.push (supps[i].code); 159 } 160 nSupsCFF::CFF1SuppEncData161 HBUINT8 &nSups () { return supps.len; } nSupsCFF::CFF1SuppEncData162 HBUINT8 nSups () const { return supps.len; } 163 164 ArrayOf<SuppEncoding, HBUINT8> supps; 165 166 DEFINE_SIZE_ARRAY_SIZED (1, supps); 167 }; 168 169 struct Encoding 170 { 171 /* serialize a fullset Encoding */ serializeCFF::Encoding172 bool serialize (hb_serialize_context_t *c, const Encoding &src) 173 { 174 TRACE_SERIALIZE (this); 175 unsigned int size = src.get_size (); 176 Encoding *dest = c->allocate_size<Encoding> (size); 177 if (unlikely (!dest)) return_trace (false); 178 hb_memcpy (dest, &src, size); 179 return_trace (true); 180 } 181 182 /* serialize a subset Encoding */ serializeCFF::Encoding183 bool serialize (hb_serialize_context_t *c, 184 uint8_t format, 185 unsigned int enc_count, 186 const hb_vector_t<code_pair_t>& code_ranges, 187 const hb_vector_t<code_pair_t>& supp_codes) 188 { 189 TRACE_SERIALIZE (this); 190 Encoding *dest = c->extend_min (this); 191 if (unlikely (!dest)) return_trace (false); 192 dest->format = format | ((supp_codes.length > 0) ? 0x80 : 0); 193 switch (format) { 194 case 0: 195 { 196 Encoding0 *fmt0 = c->allocate_size<Encoding0> (Encoding0::min_size + HBUINT8::static_size * enc_count); 197 if (unlikely (!fmt0)) return_trace (false); 198 fmt0->nCodes () = enc_count; 199 unsigned int glyph = 0; 200 for (unsigned int i = 0; i < code_ranges.length; i++) 201 { 202 hb_codepoint_t code = code_ranges[i].code; 203 for (int left = (int)code_ranges[i].glyph; left >= 0; left--) 204 fmt0->codes[glyph++] = code++; 205 if (unlikely (!((glyph <= 0x100) && (code <= 0x100)))) 206 return_trace (false); 207 } 208 } 209 break; 210 211 case 1: 212 { 213 Encoding1 *fmt1 = c->allocate_size<Encoding1> (Encoding1::min_size + Encoding1_Range::static_size * code_ranges.length); 214 if (unlikely (!fmt1)) return_trace (false); 215 fmt1->nRanges () = code_ranges.length; 216 for (unsigned int i = 0; i < code_ranges.length; i++) 217 { 218 if (unlikely (!((code_ranges[i].code <= 0xFF) && (code_ranges[i].glyph <= 0xFF)))) 219 return_trace (false); 220 fmt1->ranges[i].first = code_ranges[i].code; 221 fmt1->ranges[i].nLeft = code_ranges[i].glyph; 222 } 223 } 224 break; 225 226 } 227 228 if (supp_codes.length) 229 { 230 CFF1SuppEncData *suppData = c->allocate_size<CFF1SuppEncData> (CFF1SuppEncData::min_size + SuppEncoding::static_size * supp_codes.length); 231 if (unlikely (!suppData)) return_trace (false); 232 suppData->nSups () = supp_codes.length; 233 for (unsigned int i = 0; i < supp_codes.length; i++) 234 { 235 suppData->supps[i].code = supp_codes[i].code; 236 suppData->supps[i].glyph = supp_codes[i].glyph; /* actually SID */ 237 } 238 } 239 240 return_trace (true); 241 } 242 get_sizeCFF::Encoding243 unsigned int get_size () const 244 { 245 unsigned int size = min_size; 246 switch (table_format ()) 247 { 248 case 0: size += u.format0.get_size (); break; 249 case 1: size += u.format1.get_size (); break; 250 } 251 if (has_supplement ()) 252 size += suppEncData ().get_size (); 253 return size; 254 } 255 get_codeCFF::Encoding256 hb_codepoint_t get_code (hb_codepoint_t glyph) const 257 { 258 switch (table_format ()) 259 { 260 case 0: return u.format0.get_code (glyph); 261 case 1: return u.format1.get_code (glyph); 262 default:return 0; 263 } 264 } 265 table_formatCFF::Encoding266 uint8_t table_format () const { return format & 0x7F; } has_supplementCFF::Encoding267 bool has_supplement () const { return format & 0x80; } 268 get_supplement_codesCFF::Encoding269 void get_supplement_codes (hb_codepoint_t sid, hb_vector_t<hb_codepoint_t> &codes) const 270 { 271 codes.resize (0); 272 if (has_supplement ()) 273 suppEncData().get_codes (sid, codes); 274 } 275 sanitizeCFF::Encoding276 bool sanitize (hb_sanitize_context_t *c) const 277 { 278 TRACE_SANITIZE (this); 279 if (unlikely (!c->check_struct (this))) 280 return_trace (false); 281 282 switch (table_format ()) 283 { 284 case 0: if (unlikely (!u.format0.sanitize (c))) { return_trace (false); } break; 285 case 1: if (unlikely (!u.format1.sanitize (c))) { return_trace (false); } break; 286 default:return_trace (false); 287 } 288 return_trace (likely (!has_supplement () || suppEncData ().sanitize (c))); 289 } 290 291 protected: suppEncDataCFF::Encoding292 const CFF1SuppEncData &suppEncData () const 293 { 294 switch (table_format ()) 295 { 296 case 0: return StructAfter<CFF1SuppEncData> (u.format0.codes[u.format0.nCodes ()-1]); 297 case 1: return StructAfter<CFF1SuppEncData> (u.format1.ranges[u.format1.nRanges ()-1]); 298 default:return Null (CFF1SuppEncData); 299 } 300 } 301 302 public: 303 HBUINT8 format; 304 union { 305 Encoding0 format0; 306 Encoding1 format1; 307 } u; 308 /* CFF1SuppEncData suppEncData; */ 309 310 DEFINE_SIZE_MIN (1); 311 }; 312 313 /* Charset */ 314 struct Charset0 { sanitizeCFF::Charset0315 bool sanitize (hb_sanitize_context_t *c, unsigned int num_glyphs) const 316 { 317 TRACE_SANITIZE (this); 318 return_trace (c->check_struct (this) && sids[num_glyphs - 1].sanitize (c)); 319 } 320 get_sidCFF::Charset0321 hb_codepoint_t get_sid (hb_codepoint_t glyph, unsigned num_glyphs) const 322 { 323 if (unlikely (glyph >= num_glyphs)) return 0; 324 if (glyph == 0) 325 return 0; 326 else 327 return sids[glyph - 1]; 328 } 329 collect_glyph_to_sid_mapCFF::Charset0330 void collect_glyph_to_sid_map (hb_map_t *mapping, unsigned int num_glyphs) const 331 { 332 for (hb_codepoint_t gid = 1; gid < num_glyphs; gid++) 333 mapping->set (gid, sids[gid - 1]); 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 unsigned int get_size (unsigned int num_glyphs) const 350 { 351 assert (num_glyphs > 0); 352 return HBUINT16::static_size * (num_glyphs - 1); 353 } 354 355 HBUINT16 sids[HB_VAR_ARRAY]; 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) const 377 { 378 TRACE_SANITIZE (this); 379 if (unlikely (!c->check_struct (this))) 380 return_trace (false); 381 num_glyphs--; 382 for (unsigned int i = 0; num_glyphs > 0; i++) 383 { 384 if (unlikely (!ranges[i].sanitize (c) || (num_glyphs < ranges[i].nLeft + 1))) 385 return_trace (false); 386 num_glyphs -= (ranges[i].nLeft + 1); 387 } 388 return_trace (true); 389 } 390 get_sidCFF::Charset1_2391 hb_codepoint_t get_sid (hb_codepoint_t glyph, unsigned num_glyphs) const 392 { 393 if (unlikely (glyph >= num_glyphs)) return 0; 394 if (glyph == 0) return 0; 395 glyph--; 396 for (unsigned int i = 0;; i++) 397 { 398 if (glyph <= ranges[i].nLeft) 399 return (hb_codepoint_t) ranges[i].first + glyph; 400 glyph -= (ranges[i].nLeft + 1); 401 } 402 403 return 0; 404 } 405 collect_glyph_to_sid_mapCFF::Charset1_2406 void collect_glyph_to_sid_map (hb_map_t *mapping, unsigned int num_glyphs) const 407 { 408 hb_codepoint_t gid = 1; 409 if (gid >= num_glyphs) 410 return; 411 for (unsigned i = 0;; i++) 412 { 413 hb_codepoint_t sid = ranges[i].first; 414 unsigned count = ranges[i].nLeft + 1; 415 for (unsigned j = 0; j < count; j++) 416 mapping->set (gid++, sid++); 417 418 if (gid >= num_glyphs) 419 break; 420 } 421 } 422 get_glyphCFF::Charset1_2423 hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const 424 { 425 if (sid == 0) return 0; 426 hb_codepoint_t glyph = 1; 427 for (unsigned int i = 0;; i++) 428 { 429 if (glyph >= num_glyphs) 430 return 0; 431 if ((ranges[i].first <= sid) && (sid <= ranges[i].first + ranges[i].nLeft)) 432 return glyph + (sid - ranges[i].first); 433 glyph += (ranges[i].nLeft + 1); 434 } 435 436 return 0; 437 } 438 get_sizeCFF::Charset1_2439 unsigned int get_size (unsigned int num_glyphs) const 440 { 441 unsigned int size = HBUINT8::static_size; 442 int glyph = (int)num_glyphs; 443 444 assert (glyph > 0); 445 glyph--; 446 for (unsigned int i = 0; glyph > 0; i++) 447 { 448 glyph -= (ranges[i].nLeft + 1); 449 size += Charset_Range<TYPE>::static_size; 450 } 451 452 return size; 453 } 454 455 Charset_Range<TYPE> ranges[HB_VAR_ARRAY]; 456 457 DEFINE_SIZE_ARRAY (0, ranges); 458 }; 459 460 typedef Charset1_2<HBUINT8> Charset1; 461 typedef Charset1_2<HBUINT16> Charset2; 462 typedef Charset_Range<HBUINT8> Charset1_Range; 463 typedef Charset_Range<HBUINT16> Charset2_Range; 464 465 struct Charset 466 { 467 /* serialize a fullset Charset */ serializeCFF::Charset468 bool serialize (hb_serialize_context_t *c, const Charset &src, unsigned int num_glyphs) 469 { 470 TRACE_SERIALIZE (this); 471 unsigned int size = src.get_size (num_glyphs); 472 Charset *dest = c->allocate_size<Charset> (size); 473 if (unlikely (!dest)) return_trace (false); 474 hb_memcpy (dest, &src, size); 475 return_trace (true); 476 } 477 478 /* serialize a subset Charset */ serializeCFF::Charset479 bool serialize (hb_serialize_context_t *c, 480 uint8_t format, 481 unsigned int num_glyphs, 482 const hb_vector_t<code_pair_t>& sid_ranges) 483 { 484 TRACE_SERIALIZE (this); 485 Charset *dest = c->extend_min (this); 486 if (unlikely (!dest)) return_trace (false); 487 dest->format = format; 488 switch (format) 489 { 490 case 0: 491 { 492 Charset0 *fmt0 = c->allocate_size<Charset0> (Charset0::min_size + HBUINT16::static_size * (num_glyphs - 1)); 493 if (unlikely (!fmt0)) return_trace (false); 494 unsigned int glyph = 0; 495 for (unsigned int i = 0; i < sid_ranges.length; i++) 496 { 497 hb_codepoint_t sid = sid_ranges[i].code; 498 for (int left = (int)sid_ranges[i].glyph; left >= 0; left--) 499 fmt0->sids[glyph++] = sid++; 500 } 501 } 502 break; 503 504 case 1: 505 { 506 Charset1 *fmt1 = c->allocate_size<Charset1> (Charset1::min_size + Charset1_Range::static_size * sid_ranges.length); 507 if (unlikely (!fmt1)) return_trace (false); 508 for (unsigned int i = 0; i < sid_ranges.length; i++) 509 { 510 if (unlikely (!(sid_ranges[i].glyph <= 0xFF))) 511 return_trace (false); 512 fmt1->ranges[i].first = sid_ranges[i].code; 513 fmt1->ranges[i].nLeft = sid_ranges[i].glyph; 514 } 515 } 516 break; 517 518 case 2: 519 { 520 Charset2 *fmt2 = c->allocate_size<Charset2> (Charset2::min_size + Charset2_Range::static_size * sid_ranges.length); 521 if (unlikely (!fmt2)) return_trace (false); 522 for (unsigned int i = 0; i < sid_ranges.length; i++) 523 { 524 if (unlikely (!(sid_ranges[i].glyph <= 0xFFFF))) 525 return_trace (false); 526 fmt2->ranges[i].first = sid_ranges[i].code; 527 fmt2->ranges[i].nLeft = sid_ranges[i].glyph; 528 } 529 } 530 break; 531 532 } 533 return_trace (true); 534 } 535 get_sizeCFF::Charset536 unsigned int get_size (unsigned int num_glyphs) const 537 { 538 switch (format) 539 { 540 case 0: return min_size + u.format0.get_size (num_glyphs); 541 case 1: return min_size + u.format1.get_size (num_glyphs); 542 case 2: return min_size + u.format2.get_size (num_glyphs); 543 default:return 0; 544 } 545 } 546 get_sidCFF::Charset547 hb_codepoint_t get_sid (hb_codepoint_t glyph, unsigned int num_glyphs) const 548 { 549 switch (format) 550 { 551 case 0: return u.format0.get_sid (glyph, num_glyphs); 552 case 1: return u.format1.get_sid (glyph, num_glyphs); 553 case 2: return u.format2.get_sid (glyph, num_glyphs); 554 default:return 0; 555 } 556 } 557 collect_glyph_to_sid_mapCFF::Charset558 void collect_glyph_to_sid_map (hb_map_t *mapping, unsigned int num_glyphs) const 559 { 560 switch (format) 561 { 562 case 0: u.format0.collect_glyph_to_sid_map (mapping, num_glyphs); return; 563 case 1: u.format1.collect_glyph_to_sid_map (mapping, num_glyphs); return; 564 case 2: u.format2.collect_glyph_to_sid_map (mapping, num_glyphs); return; 565 default:return; 566 } 567 } 568 get_glyphCFF::Charset569 hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const 570 { 571 switch (format) 572 { 573 case 0: return u.format0.get_glyph (sid, num_glyphs); 574 case 1: return u.format1.get_glyph (sid, num_glyphs); 575 case 2: return u.format2.get_glyph (sid, num_glyphs); 576 default:return 0; 577 } 578 } 579 sanitizeCFF::Charset580 bool sanitize (hb_sanitize_context_t *c) const 581 { 582 TRACE_SANITIZE (this); 583 if (unlikely (!c->check_struct (this))) 584 return_trace (false); 585 586 switch (format) 587 { 588 case 0: return_trace (u.format0.sanitize (c, c->get_num_glyphs ())); 589 case 1: return_trace (u.format1.sanitize (c, c->get_num_glyphs ())); 590 case 2: return_trace (u.format2.sanitize (c, c->get_num_glyphs ())); 591 default:return_trace (false); 592 } 593 } 594 595 HBUINT8 format; 596 union { 597 Charset0 format0; 598 Charset1 format1; 599 Charset2 format2; 600 } u; 601 602 DEFINE_SIZE_MIN (1); 603 }; 604 605 struct CFF1StringIndex : CFF1Index 606 { serializeCFF::CFF1StringIndex607 bool serialize (hb_serialize_context_t *c, const CFF1StringIndex &strings, 608 const hb_inc_bimap_t &sidmap) 609 { 610 TRACE_SERIALIZE (this); 611 if (unlikely ((strings.count == 0) || (sidmap.get_population () == 0))) 612 { 613 if (unlikely (!c->extend_min (this->count))) 614 return_trace (false); 615 count = 0; 616 return_trace (true); 617 } 618 619 byte_str_array_t bytesArray; 620 if (!bytesArray.resize (sidmap.get_population ())) 621 return_trace (false); 622 for (unsigned int i = 0; i < strings.count; i++) 623 { 624 hb_codepoint_t j = sidmap[i]; 625 if (j != HB_MAP_VALUE_INVALID) 626 bytesArray[j] = strings[i]; 627 } 628 629 bool result = CFF1Index::serialize (c, bytesArray); 630 return_trace (result); 631 } 632 }; 633 634 struct cff1_top_dict_interp_env_t : num_interp_env_t 635 { cff1_top_dict_interp_env_tCFF::cff1_top_dict_interp_env_t636 cff1_top_dict_interp_env_t () 637 : num_interp_env_t(), prev_offset(0), last_offset(0) {} cff1_top_dict_interp_env_tCFF::cff1_top_dict_interp_env_t638 cff1_top_dict_interp_env_t (const hb_ubytes_t &bytes) 639 : num_interp_env_t(bytes), prev_offset(0), last_offset(0) {} 640 641 unsigned int prev_offset; 642 unsigned int last_offset; 643 }; 644 645 struct name_dict_values_t 646 { 647 enum name_dict_val_index_t 648 { 649 version, 650 notice, 651 copyright, 652 fullName, 653 familyName, 654 weight, 655 postscript, 656 fontName, 657 baseFontName, 658 registry, 659 ordering, 660 661 ValCount 662 }; 663 initCFF::name_dict_values_t664 void init () 665 { 666 for (unsigned int i = 0; i < ValCount; i++) 667 values[i] = CFF_UNDEF_SID; 668 } 669 operator []CFF::name_dict_values_t670 unsigned int& operator[] (unsigned int i) 671 { assert (i < ValCount); return values[i]; } 672 operator []CFF::name_dict_values_t673 unsigned int operator[] (unsigned int i) const 674 { assert (i < ValCount); return values[i]; } 675 name_op_to_indexCFF::name_dict_values_t676 static enum name_dict_val_index_t name_op_to_index (op_code_t op) 677 { 678 switch (op) { 679 default: // can't happen - just make some compiler happy 680 case OpCode_version: 681 return version; 682 case OpCode_Notice: 683 return notice; 684 case OpCode_Copyright: 685 return copyright; 686 case OpCode_FullName: 687 return fullName; 688 case OpCode_FamilyName: 689 return familyName; 690 case OpCode_Weight: 691 return weight; 692 case OpCode_PostScript: 693 return postscript; 694 case OpCode_FontName: 695 return fontName; 696 case OpCode_BaseFontName: 697 return baseFontName; 698 } 699 } 700 701 unsigned int values[ValCount]; 702 }; 703 704 struct cff1_top_dict_val_t : op_str_t 705 { 706 unsigned int last_arg_offset; 707 }; 708 709 struct cff1_top_dict_values_t : top_dict_values_t<cff1_top_dict_val_t> 710 { initCFF::cff1_top_dict_values_t711 void init () 712 { 713 top_dict_values_t<cff1_top_dict_val_t>::init (); 714 715 nameSIDs.init (); 716 ros_supplement = 0; 717 cidCount = 8720; 718 EncodingOffset = 0; 719 CharsetOffset = 0; 720 FDSelectOffset = 0; 721 privateDictInfo.init (); 722 } finiCFF::cff1_top_dict_values_t723 void fini () { top_dict_values_t<cff1_top_dict_val_t>::fini (); } 724 is_CIDCFF::cff1_top_dict_values_t725 bool is_CID () const 726 { return nameSIDs[name_dict_values_t::registry] != CFF_UNDEF_SID; } 727 728 name_dict_values_t nameSIDs; 729 unsigned int ros_supplement_offset; 730 unsigned int ros_supplement; 731 unsigned int cidCount; 732 733 unsigned int EncodingOffset; 734 unsigned int CharsetOffset; 735 unsigned int FDSelectOffset; 736 table_info_t privateDictInfo; 737 }; 738 739 struct cff1_top_dict_opset_t : top_dict_opset_t<cff1_top_dict_val_t> 740 { process_opCFF::cff1_top_dict_opset_t741 static void process_op (op_code_t op, cff1_top_dict_interp_env_t& env, cff1_top_dict_values_t& dictval) 742 { 743 cff1_top_dict_val_t val; 744 val.last_arg_offset = (env.last_offset-1) - dictval.opStart; /* offset to the last argument */ 745 746 switch (op) { 747 case OpCode_version: 748 case OpCode_Notice: 749 case OpCode_Copyright: 750 case OpCode_FullName: 751 case OpCode_FontName: 752 case OpCode_FamilyName: 753 case OpCode_Weight: 754 case OpCode_PostScript: 755 case OpCode_BaseFontName: 756 dictval.nameSIDs[name_dict_values_t::name_op_to_index (op)] = env.argStack.pop_uint (); 757 env.clear_args (); 758 break; 759 case OpCode_isFixedPitch: 760 case OpCode_ItalicAngle: 761 case OpCode_UnderlinePosition: 762 case OpCode_UnderlineThickness: 763 case OpCode_PaintType: 764 case OpCode_CharstringType: 765 case OpCode_UniqueID: 766 case OpCode_StrokeWidth: 767 case OpCode_SyntheticBase: 768 case OpCode_CIDFontVersion: 769 case OpCode_CIDFontRevision: 770 case OpCode_CIDFontType: 771 case OpCode_UIDBase: 772 case OpCode_FontBBox: 773 case OpCode_XUID: 774 case OpCode_BaseFontBlend: 775 env.clear_args (); 776 break; 777 778 case OpCode_CIDCount: 779 dictval.cidCount = env.argStack.pop_uint (); 780 env.clear_args (); 781 break; 782 783 case OpCode_ROS: 784 dictval.ros_supplement = env.argStack.pop_uint (); 785 dictval.nameSIDs[name_dict_values_t::ordering] = env.argStack.pop_uint (); 786 dictval.nameSIDs[name_dict_values_t::registry] = env.argStack.pop_uint (); 787 env.clear_args (); 788 break; 789 790 case OpCode_Encoding: 791 dictval.EncodingOffset = env.argStack.pop_uint (); 792 env.clear_args (); 793 if (unlikely (dictval.EncodingOffset == 0)) return; 794 break; 795 796 case OpCode_charset: 797 dictval.CharsetOffset = env.argStack.pop_uint (); 798 env.clear_args (); 799 if (unlikely (dictval.CharsetOffset == 0)) return; 800 break; 801 802 case OpCode_FDSelect: 803 dictval.FDSelectOffset = env.argStack.pop_uint (); 804 env.clear_args (); 805 break; 806 807 case OpCode_Private: 808 dictval.privateDictInfo.offset = env.argStack.pop_uint (); 809 dictval.privateDictInfo.size = env.argStack.pop_uint (); 810 env.clear_args (); 811 break; 812 813 default: 814 env.last_offset = env.str_ref.get_offset (); 815 top_dict_opset_t<cff1_top_dict_val_t>::process_op (op, env, dictval); 816 /* Record this operand below if stack is empty, otherwise done */ 817 if (!env.argStack.is_empty ()) return; 818 break; 819 } 820 821 if (unlikely (env.in_error ())) return; 822 823 dictval.add_op (op, env.str_ref, val); 824 } 825 }; 826 827 struct cff1_font_dict_values_t : dict_values_t<op_str_t> 828 { initCFF::cff1_font_dict_values_t829 void init () 830 { 831 dict_values_t<op_str_t>::init (); 832 privateDictInfo.init (); 833 fontName = CFF_UNDEF_SID; 834 } finiCFF::cff1_font_dict_values_t835 void fini () { dict_values_t<op_str_t>::fini (); } 836 837 table_info_t privateDictInfo; 838 unsigned int fontName; 839 }; 840 841 struct cff1_font_dict_opset_t : dict_opset_t 842 { process_opCFF::cff1_font_dict_opset_t843 static void process_op (op_code_t op, num_interp_env_t& env, cff1_font_dict_values_t& dictval) 844 { 845 switch (op) { 846 case OpCode_FontName: 847 dictval.fontName = env.argStack.pop_uint (); 848 env.clear_args (); 849 break; 850 case OpCode_FontMatrix: 851 case OpCode_PaintType: 852 env.clear_args (); 853 break; 854 case OpCode_Private: 855 dictval.privateDictInfo.offset = env.argStack.pop_uint (); 856 dictval.privateDictInfo.size = env.argStack.pop_uint (); 857 env.clear_args (); 858 break; 859 860 default: 861 dict_opset_t::process_op (op, env); 862 if (!env.argStack.is_empty ()) return; 863 break; 864 } 865 866 if (unlikely (env.in_error ())) return; 867 868 dictval.add_op (op, env.str_ref); 869 } 870 }; 871 872 template <typename VAL> 873 struct cff1_private_dict_values_base_t : dict_values_t<VAL> 874 { initCFF::cff1_private_dict_values_base_t875 void init () 876 { 877 dict_values_t<VAL>::init (); 878 subrsOffset = 0; 879 localSubrs = &Null (CFF1Subrs); 880 } finiCFF::cff1_private_dict_values_base_t881 void fini () { dict_values_t<VAL>::fini (); } 882 883 unsigned int subrsOffset; 884 const CFF1Subrs *localSubrs; 885 }; 886 887 typedef cff1_private_dict_values_base_t<op_str_t> cff1_private_dict_values_subset_t; 888 typedef cff1_private_dict_values_base_t<num_dict_val_t> cff1_private_dict_values_t; 889 890 struct cff1_private_dict_opset_t : dict_opset_t 891 { process_opCFF::cff1_private_dict_opset_t892 static void process_op (op_code_t op, num_interp_env_t& env, cff1_private_dict_values_t& dictval) 893 { 894 num_dict_val_t val; 895 val.init (); 896 897 switch (op) { 898 case OpCode_BlueValues: 899 case OpCode_OtherBlues: 900 case OpCode_FamilyBlues: 901 case OpCode_FamilyOtherBlues: 902 case OpCode_StemSnapH: 903 case OpCode_StemSnapV: 904 env.clear_args (); 905 break; 906 case OpCode_StdHW: 907 case OpCode_StdVW: 908 case OpCode_BlueScale: 909 case OpCode_BlueShift: 910 case OpCode_BlueFuzz: 911 case OpCode_ForceBold: 912 case OpCode_LanguageGroup: 913 case OpCode_ExpansionFactor: 914 case OpCode_initialRandomSeed: 915 case OpCode_defaultWidthX: 916 case OpCode_nominalWidthX: 917 val.single_val = env.argStack.pop_num (); 918 env.clear_args (); 919 break; 920 case OpCode_Subrs: 921 dictval.subrsOffset = env.argStack.pop_uint (); 922 env.clear_args (); 923 break; 924 925 default: 926 dict_opset_t::process_op (op, env); 927 if (!env.argStack.is_empty ()) return; 928 break; 929 } 930 931 if (unlikely (env.in_error ())) return; 932 933 dictval.add_op (op, env.str_ref, val); 934 } 935 }; 936 937 struct cff1_private_dict_opset_subset : dict_opset_t 938 { process_opCFF::cff1_private_dict_opset_subset939 static void process_op (op_code_t op, num_interp_env_t& env, cff1_private_dict_values_subset_t& dictval) 940 { 941 switch (op) { 942 case OpCode_BlueValues: 943 case OpCode_OtherBlues: 944 case OpCode_FamilyBlues: 945 case OpCode_FamilyOtherBlues: 946 case OpCode_StemSnapH: 947 case OpCode_StemSnapV: 948 case OpCode_StdHW: 949 case OpCode_StdVW: 950 case OpCode_BlueScale: 951 case OpCode_BlueShift: 952 case OpCode_BlueFuzz: 953 case OpCode_ForceBold: 954 case OpCode_LanguageGroup: 955 case OpCode_ExpansionFactor: 956 case OpCode_initialRandomSeed: 957 case OpCode_defaultWidthX: 958 case OpCode_nominalWidthX: 959 env.clear_args (); 960 break; 961 962 case OpCode_Subrs: 963 dictval.subrsOffset = env.argStack.pop_uint (); 964 env.clear_args (); 965 break; 966 967 default: 968 dict_opset_t::process_op (op, env); 969 if (!env.argStack.is_empty ()) return; 970 break; 971 } 972 973 if (unlikely (env.in_error ())) return; 974 975 dictval.add_op (op, env.str_ref); 976 } 977 }; 978 979 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; 980 typedef dict_interpreter_t<cff1_font_dict_opset_t, cff1_font_dict_values_t> cff1_font_dict_interpreter_t; 981 982 typedef CFF1Index CFF1NameIndex; 983 typedef CFF1IndexOf<TopDict> CFF1TopDictIndex; 984 985 struct cff1_font_dict_values_mod_t 986 { cff1_font_dict_values_mod_tCFF::cff1_font_dict_values_mod_t987 cff1_font_dict_values_mod_t() { init (); } 988 initCFF::cff1_font_dict_values_mod_t989 void init () { init ( &Null (cff1_font_dict_values_t), CFF_UNDEF_SID ); } 990 initCFF::cff1_font_dict_values_mod_t991 void init (const cff1_font_dict_values_t *base_, 992 unsigned int fontName_) 993 { 994 base = base_; 995 fontName = fontName_; 996 privateDictInfo.init (); 997 } 998 get_countCFF::cff1_font_dict_values_mod_t999 unsigned get_count () const { return base->get_count (); } 1000 operator []CFF::cff1_font_dict_values_mod_t1001 const op_str_t &operator [] (unsigned int i) const { return (*base)[i]; } 1002 1003 const cff1_font_dict_values_t *base; 1004 table_info_t privateDictInfo; 1005 unsigned int fontName; 1006 }; 1007 1008 struct CFF1FDArray : FDArray<HBUINT16> 1009 { 1010 /* FDArray::serialize() requires this partial specialization to compile */ 1011 template <typename ITER, typename OP_SERIALIZER> serializeCFF::CFF1FDArray1012 bool serialize (hb_serialize_context_t *c, ITER it, OP_SERIALIZER& opszr) 1013 { return FDArray<HBUINT16>::serialize<cff1_font_dict_values_mod_t, cff1_font_dict_values_mod_t> (c, it, opszr); } 1014 }; 1015 1016 } /* namespace CFF */ 1017 1018 namespace OT { 1019 1020 using namespace CFF; 1021 1022 struct cff1 1023 { 1024 static constexpr hb_tag_t tableTag = HB_OT_TAG_cff1; 1025 sanitizeOT::cff11026 bool sanitize (hb_sanitize_context_t *c) const 1027 { 1028 TRACE_SANITIZE (this); 1029 return_trace (c->check_struct (this) && 1030 likely (version.major == 1)); 1031 } 1032 1033 template <typename PRIVOPSET, typename PRIVDICTVAL> 1034 struct accelerator_templ_t 1035 { initOT::cff1::accelerator_templ_t1036 void init (hb_face_t *face) 1037 { 1038 topDict.init (); 1039 fontDicts.init (); 1040 privateDicts.init (); 1041 1042 this->blob = sc.reference_table<cff1> (face); 1043 1044 /* setup for run-time santization */ 1045 sc.init (this->blob); 1046 sc.start_processing (); 1047 1048 const OT::cff1 *cff = this->blob->template as<OT::cff1> (); 1049 1050 if (cff == &Null (OT::cff1)) 1051 { fini (); return; } 1052 1053 nameIndex = &cff->nameIndex (cff); 1054 if ((nameIndex == &Null (CFF1NameIndex)) || !nameIndex->sanitize (&sc)) 1055 { fini (); return; } 1056 1057 topDictIndex = &StructAtOffset<CFF1TopDictIndex> (nameIndex, nameIndex->get_size ()); 1058 if ((topDictIndex == &Null (CFF1TopDictIndex)) || !topDictIndex->sanitize (&sc) || (topDictIndex->count == 0)) 1059 { fini (); return; } 1060 1061 { /* parse top dict */ 1062 const hb_ubytes_t topDictStr = (*topDictIndex)[0]; 1063 if (unlikely (!topDictStr.sanitize (&sc))) { fini (); return; } 1064 cff1_top_dict_interp_env_t env (topDictStr); 1065 cff1_top_dict_interpreter_t top_interp (env); 1066 if (unlikely (!top_interp.interpret (topDict))) { fini (); return; } 1067 } 1068 1069 if (is_predef_charset ()) 1070 charset = &Null (Charset); 1071 else 1072 { 1073 charset = &StructAtOffsetOrNull<Charset> (cff, topDict.CharsetOffset); 1074 if (unlikely ((charset == &Null (Charset)) || !charset->sanitize (&sc))) { fini (); return; } 1075 } 1076 1077 fdCount = 1; 1078 if (is_CID ()) 1079 { 1080 fdArray = &StructAtOffsetOrNull<CFF1FDArray> (cff, topDict.FDArrayOffset); 1081 fdSelect = &StructAtOffsetOrNull<CFF1FDSelect> (cff, topDict.FDSelectOffset); 1082 if (unlikely ((fdArray == &Null (CFF1FDArray)) || !fdArray->sanitize (&sc) || 1083 (fdSelect == &Null (CFF1FDSelect)) || !fdSelect->sanitize (&sc, fdArray->count))) 1084 { fini (); return; } 1085 1086 fdCount = fdArray->count; 1087 } 1088 else 1089 { 1090 fdArray = &Null (CFF1FDArray); 1091 fdSelect = &Null (CFF1FDSelect); 1092 } 1093 1094 encoding = &Null (Encoding); 1095 if (is_CID ()) 1096 { 1097 if (unlikely (charset == &Null (Charset))) { fini (); return; } 1098 } 1099 else 1100 { 1101 if (!is_predef_encoding ()) 1102 { 1103 encoding = &StructAtOffsetOrNull<Encoding> (cff, topDict.EncodingOffset); 1104 if (unlikely ((encoding == &Null (Encoding)) || !encoding->sanitize (&sc))) { fini (); return; } 1105 } 1106 } 1107 1108 stringIndex = &StructAtOffset<CFF1StringIndex> (topDictIndex, topDictIndex->get_size ()); 1109 if ((stringIndex == &Null (CFF1StringIndex)) || !stringIndex->sanitize (&sc)) 1110 { fini (); return; } 1111 1112 globalSubrs = &StructAtOffset<CFF1Subrs> (stringIndex, stringIndex->get_size ()); 1113 if ((globalSubrs != &Null (CFF1Subrs)) && !globalSubrs->sanitize (&sc)) 1114 { fini (); return; } 1115 1116 charStrings = &StructAtOffsetOrNull<CFF1CharStrings> (cff, topDict.charStringsOffset); 1117 1118 if ((charStrings == &Null (CFF1CharStrings)) || unlikely (!charStrings->sanitize (&sc))) 1119 { fini (); return; } 1120 1121 num_glyphs = charStrings->count; 1122 if (num_glyphs != sc.get_num_glyphs ()) 1123 { fini (); return; } 1124 1125 if (unlikely (!privateDicts.resize (fdCount))) 1126 { fini (); return; } 1127 for (unsigned int i = 0; i < fdCount; i++) 1128 privateDicts[i].init (); 1129 1130 // parse CID font dicts and gather private dicts 1131 if (is_CID ()) 1132 { 1133 for (unsigned int i = 0; i < fdCount; i++) 1134 { 1135 hb_ubytes_t fontDictStr = (*fdArray)[i]; 1136 if (unlikely (!fontDictStr.sanitize (&sc))) { fini (); return; } 1137 cff1_font_dict_values_t *font; 1138 cff1_top_dict_interp_env_t env (fontDictStr); 1139 cff1_font_dict_interpreter_t font_interp (env); 1140 font = fontDicts.push (); 1141 if (unlikely (fontDicts.in_error ())) { fini (); return; } 1142 1143 font->init (); 1144 if (unlikely (!font_interp.interpret (*font))) { fini (); return; } 1145 PRIVDICTVAL *priv = &privateDicts[i]; 1146 const hb_ubytes_t privDictStr = StructAtOffset<UnsizedByteStr> (cff, font->privateDictInfo.offset).as_ubytes (font->privateDictInfo.size); 1147 if (unlikely (!privDictStr.sanitize (&sc))) { fini (); return; } 1148 num_interp_env_t env2 (privDictStr); 1149 dict_interpreter_t<PRIVOPSET, PRIVDICTVAL> priv_interp (env2); 1150 priv->init (); 1151 if (unlikely (!priv_interp.interpret (*priv))) { fini (); return; } 1152 1153 priv->localSubrs = &StructAtOffsetOrNull<CFF1Subrs> (&privDictStr, priv->subrsOffset); 1154 if (priv->localSubrs != &Null (CFF1Subrs) && 1155 unlikely (!priv->localSubrs->sanitize (&sc))) 1156 { fini (); return; } 1157 } 1158 } 1159 else /* non-CID */ 1160 { 1161 cff1_top_dict_values_t *font = &topDict; 1162 PRIVDICTVAL *priv = &privateDicts[0]; 1163 1164 const hb_ubytes_t privDictStr = StructAtOffset<UnsizedByteStr> (cff, font->privateDictInfo.offset).as_ubytes (font->privateDictInfo.size); 1165 if (unlikely (!privDictStr.sanitize (&sc))) { fini (); return; } 1166 num_interp_env_t env (privDictStr); 1167 dict_interpreter_t<PRIVOPSET, PRIVDICTVAL> priv_interp (env); 1168 priv->init (); 1169 if (unlikely (!priv_interp.interpret (*priv))) { fini (); return; } 1170 1171 priv->localSubrs = &StructAtOffsetOrNull<CFF1Subrs> (&privDictStr, priv->subrsOffset); 1172 if (priv->localSubrs != &Null (CFF1Subrs) && 1173 unlikely (!priv->localSubrs->sanitize (&sc))) 1174 { fini (); return; } 1175 } 1176 } 1177 finiOT::cff1::accelerator_templ_t1178 void fini () 1179 { 1180 sc.end_processing (); 1181 topDict.fini (); 1182 fontDicts.fini (); 1183 privateDicts.fini (); 1184 hb_blob_destroy (blob); 1185 blob = nullptr; 1186 } 1187 is_validOT::cff1::accelerator_templ_t1188 bool is_valid () const { return blob; } is_CIDOT::cff1::accelerator_templ_t1189 bool is_CID () const { return topDict.is_CID (); } 1190 is_predef_charsetOT::cff1::accelerator_templ_t1191 bool is_predef_charset () const { return topDict.CharsetOffset <= ExpertSubsetCharset; } 1192 std_code_to_glyphOT::cff1::accelerator_templ_t1193 unsigned int std_code_to_glyph (hb_codepoint_t code) const 1194 { 1195 hb_codepoint_t sid = lookup_standard_encoding_for_sid (code); 1196 if (unlikely (sid == CFF_UNDEF_SID)) 1197 return 0; 1198 1199 if (charset != &Null (Charset)) 1200 return charset->get_glyph (sid, num_glyphs); 1201 else if ((topDict.CharsetOffset == ISOAdobeCharset) 1202 && (code <= 228 /*zcaron*/)) return sid; 1203 return 0; 1204 } 1205 is_predef_encodingOT::cff1::accelerator_templ_t1206 bool is_predef_encoding () const { return topDict.EncodingOffset <= ExpertEncoding; } 1207 glyph_to_codeOT::cff1::accelerator_templ_t1208 hb_codepoint_t glyph_to_code (hb_codepoint_t glyph) const 1209 { 1210 if (encoding != &Null (Encoding)) 1211 return encoding->get_code (glyph); 1212 else 1213 { 1214 hb_codepoint_t sid = glyph_to_sid (glyph); 1215 if (sid == 0) return 0; 1216 hb_codepoint_t code = 0; 1217 switch (topDict.EncodingOffset) 1218 { 1219 case StandardEncoding: 1220 code = lookup_standard_encoding_for_code (sid); 1221 break; 1222 case ExpertEncoding: 1223 code = lookup_expert_encoding_for_code (sid); 1224 break; 1225 default: 1226 break; 1227 } 1228 return code; 1229 } 1230 } 1231 create_glyph_to_sid_mapOT::cff1::accelerator_templ_t1232 hb_map_t *create_glyph_to_sid_map () const 1233 { 1234 if (charset != &Null (Charset)) 1235 { 1236 hb_map_t *mapping = hb_map_create (); 1237 mapping->set (0, 0); 1238 charset->collect_glyph_to_sid_map (mapping, num_glyphs); 1239 return mapping; 1240 } 1241 else 1242 return nullptr; 1243 } 1244 glyph_to_sidOT::cff1::accelerator_templ_t1245 hb_codepoint_t glyph_to_sid (hb_codepoint_t glyph) const 1246 { 1247 if (charset != &Null (Charset)) 1248 return charset->get_sid (glyph, num_glyphs); 1249 else 1250 { 1251 hb_codepoint_t sid = 0; 1252 switch (topDict.CharsetOffset) 1253 { 1254 case ISOAdobeCharset: 1255 if (glyph <= 228 /*zcaron*/) sid = glyph; 1256 break; 1257 case ExpertCharset: 1258 sid = lookup_expert_charset_for_sid (glyph); 1259 break; 1260 case ExpertSubsetCharset: 1261 sid = lookup_expert_subset_charset_for_sid (glyph); 1262 break; 1263 default: 1264 break; 1265 } 1266 return sid; 1267 } 1268 } 1269 sid_to_glyphOT::cff1::accelerator_templ_t1270 hb_codepoint_t sid_to_glyph (hb_codepoint_t sid) const 1271 { 1272 if (charset != &Null (Charset)) 1273 return charset->get_glyph (sid, num_glyphs); 1274 else 1275 { 1276 hb_codepoint_t glyph = 0; 1277 switch (topDict.CharsetOffset) 1278 { 1279 case ISOAdobeCharset: 1280 if (sid <= 228 /*zcaron*/) glyph = sid; 1281 break; 1282 case ExpertCharset: 1283 glyph = lookup_expert_charset_for_glyph (sid); 1284 break; 1285 case ExpertSubsetCharset: 1286 glyph = lookup_expert_subset_charset_for_glyph (sid); 1287 break; 1288 default: 1289 break; 1290 } 1291 return glyph; 1292 } 1293 } 1294 1295 protected: 1296 hb_sanitize_context_t sc; 1297 1298 public: 1299 hb_blob_t *blob = nullptr; 1300 const Encoding *encoding = nullptr; 1301 const Charset *charset = nullptr; 1302 const CFF1NameIndex *nameIndex = nullptr; 1303 const CFF1TopDictIndex *topDictIndex = nullptr; 1304 const CFF1StringIndex *stringIndex = nullptr; 1305 const CFF1Subrs *globalSubrs = nullptr; 1306 const CFF1CharStrings *charStrings = nullptr; 1307 const CFF1FDArray *fdArray = nullptr; 1308 const CFF1FDSelect *fdSelect = nullptr; 1309 unsigned int fdCount = 0; 1310 1311 cff1_top_dict_values_t topDict; 1312 hb_vector_t<cff1_font_dict_values_t> 1313 fontDicts; 1314 hb_vector_t<PRIVDICTVAL> privateDicts; 1315 1316 unsigned int num_glyphs = 0; 1317 }; 1318 1319 struct accelerator_t : accelerator_templ_t<cff1_private_dict_opset_t, cff1_private_dict_values_t> 1320 { accelerator_tOT::cff1::accelerator_t1321 accelerator_t (hb_face_t *face) 1322 { 1323 SUPER::init (face); 1324 1325 glyph_names.set_relaxed (nullptr); 1326 1327 if (!is_valid ()) return; 1328 if (is_CID ()) return; 1329 1330 } ~accelerator_tOT::cff1::accelerator_t1331 ~accelerator_t () 1332 { 1333 hb_sorted_vector_t<gname_t> *names = glyph_names.get_relaxed (); 1334 if (names) 1335 { 1336 names->fini (); 1337 hb_free (names); 1338 } 1339 1340 SUPER::fini (); 1341 } 1342 get_glyph_nameOT::cff1::accelerator_t1343 bool get_glyph_name (hb_codepoint_t glyph, 1344 char *buf, unsigned int buf_len) const 1345 { 1346 if (unlikely (!is_valid ())) return false; 1347 if (is_CID()) return false; 1348 if (unlikely (!buf_len)) return true; 1349 hb_codepoint_t sid = glyph_to_sid (glyph); 1350 const char *str; 1351 size_t str_len; 1352 if (sid < cff1_std_strings_length) 1353 { 1354 hb_bytes_t byte_str = cff1_std_strings (sid); 1355 str = byte_str.arrayZ; 1356 str_len = byte_str.length; 1357 } 1358 else 1359 { 1360 hb_ubytes_t ubyte_str = (*stringIndex)[sid - cff1_std_strings_length]; 1361 str = (const char *)ubyte_str.arrayZ; 1362 str_len = ubyte_str.length; 1363 } 1364 if (!str_len) return false; 1365 unsigned int len = hb_min (buf_len - 1, str_len); 1366 strncpy (buf, (const char*)str, len); 1367 buf[len] = '\0'; 1368 return true; 1369 } 1370 get_glyph_from_nameOT::cff1::accelerator_t1371 bool get_glyph_from_name (const char *name, int len, 1372 hb_codepoint_t *glyph) const 1373 { 1374 if (unlikely (!is_valid ())) return false; 1375 if (is_CID()) return false; 1376 if (len < 0) len = strlen (name); 1377 if (unlikely (!len)) return false; 1378 1379 retry: 1380 hb_sorted_vector_t<gname_t> *names = glyph_names.get_acquire (); 1381 if (unlikely (!names)) 1382 { 1383 names = (hb_sorted_vector_t<gname_t> *) hb_calloc (sizeof (hb_sorted_vector_t<gname_t>), 1); 1384 if (likely (names)) 1385 { 1386 names->init (); 1387 /* TODO */ 1388 1389 /* fill glyph names */ 1390 for (hb_codepoint_t gid = 0; gid < num_glyphs; gid++) 1391 { 1392 hb_codepoint_t sid = glyph_to_sid (gid); 1393 gname_t gname; 1394 gname.sid = sid; 1395 if (sid < cff1_std_strings_length) 1396 gname.name = cff1_std_strings (sid); 1397 else 1398 { 1399 hb_ubytes_t ustr = (*stringIndex)[sid - cff1_std_strings_length]; 1400 gname.name = hb_bytes_t ((const char*) ustr.arrayZ, ustr.length); 1401 } 1402 if (unlikely (!gname.name.arrayZ)) 1403 gname.name = hb_bytes_t ("", 0); /* To avoid nullptr. */ 1404 names->push (gname); 1405 } 1406 names->qsort (); 1407 } 1408 if (unlikely (!glyph_names.cmpexch (nullptr, names))) 1409 { 1410 if (names) 1411 { 1412 names->fini (); 1413 hb_free (names); 1414 } 1415 goto retry; 1416 } 1417 } 1418 1419 gname_t key = { hb_bytes_t (name, len), 0 }; 1420 const gname_t *gname = names ? names->bsearch (key) : nullptr; 1421 if (!gname) return false; 1422 hb_codepoint_t gid = sid_to_glyph (gname->sid); 1423 if (!gid && gname->sid) return false; 1424 *glyph = gid; 1425 return true; 1426 } 1427 1428 HB_INTERNAL bool get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const; 1429 HB_INTERNAL bool get_seac_components (hb_codepoint_t glyph, hb_codepoint_t *base, hb_codepoint_t *accent) const; 1430 HB_INTERNAL bool get_path (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session) const; 1431 1432 private: 1433 struct gname_t 1434 { 1435 hb_bytes_t name; 1436 uint16_t sid; 1437 cmpOT::cff1::accelerator_t::gname_t1438 static int cmp (const void *a_, const void *b_) 1439 { 1440 const gname_t *a = (const gname_t *)a_; 1441 const gname_t *b = (const gname_t *)b_; 1442 unsigned minlen = hb_min (a->name.length, b->name.length); 1443 int ret = strncmp (a->name.arrayZ, b->name.arrayZ, minlen); 1444 if (ret) return ret; 1445 return a->name.length - b->name.length; 1446 } 1447 cmpOT::cff1::accelerator_t::gname_t1448 int cmp (const gname_t &a) const { return cmp (&a, this); } 1449 }; 1450 1451 mutable hb_atomic_ptr_t<hb_sorted_vector_t<gname_t>> glyph_names; 1452 1453 typedef accelerator_templ_t<cff1_private_dict_opset_t, cff1_private_dict_values_t> SUPER; 1454 }; 1455 1456 struct accelerator_subset_t : accelerator_templ_t<cff1_private_dict_opset_subset, cff1_private_dict_values_subset_t> {}; 1457 subsetOT::cff11458 bool subset (hb_subset_context_t *c) const { return hb_subset_cff1 (c); } 1459 1460 protected: 1461 HB_INTERNAL static hb_codepoint_t lookup_standard_encoding_for_code (hb_codepoint_t sid); 1462 HB_INTERNAL static hb_codepoint_t lookup_expert_encoding_for_code (hb_codepoint_t sid); 1463 HB_INTERNAL static hb_codepoint_t lookup_expert_charset_for_sid (hb_codepoint_t glyph); 1464 HB_INTERNAL static hb_codepoint_t lookup_expert_subset_charset_for_sid (hb_codepoint_t glyph); 1465 HB_INTERNAL static hb_codepoint_t lookup_expert_charset_for_glyph (hb_codepoint_t sid); 1466 HB_INTERNAL static hb_codepoint_t lookup_expert_subset_charset_for_glyph (hb_codepoint_t sid); 1467 HB_INTERNAL static hb_codepoint_t lookup_standard_encoding_for_sid (hb_codepoint_t code); 1468 1469 public: 1470 FixedVersion<HBUINT8> version; /* Version of CFF table. set to 0x0100u */ 1471 NNOffsetTo<CFF1NameIndex, HBUINT8> nameIndex; /* headerSize = Offset to Name INDEX. */ 1472 HBUINT8 offSize; /* offset size (unused?) */ 1473 1474 public: 1475 DEFINE_SIZE_STATIC (4); 1476 }; 1477 1478 struct cff1_accelerator_t : cff1::accelerator_t { cff1_accelerator_tOT::cff1_accelerator_t1479 cff1_accelerator_t (hb_face_t *face) : cff1::accelerator_t (face) {} 1480 }; 1481 1482 } /* namespace OT */ 1483 1484 #endif /* HB_OT_CFF1_TABLE_HH */ 1485