Bug 1883518 - Remove a bunch of unused ServoBindings.toml entries. r=firefox-style...
[gecko.git] / gfx / harfbuzz / src / hb-ot-cff1-table.hh
blobc869e90554bf393feab5b29c18af22d48b250d1f
1 /*
2 * Copyright © 2018 Adobe Inc.
4 * This is part of HarfBuzz, a text shaping library.
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.
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.
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.
24 * Adobe Author(s): Michiharu Ariza
27 #ifndef HB_OT_CFF1_TABLE_HH
28 #define HB_OT_CFF1_TABLE_HH
30 #include "hb-ot-cff-common.hh"
31 #include "hb-subset-cff-common.hh"
32 #include "hb-draw.hh"
33 #include "hb-paint.hh"
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
41 namespace CFF {
44 * CFF -- Compact Font Format (CFF)
45 * https://www.adobe.com/content/dam/acom/en/devnet/font/pdfs/5176.CFF.pdf
47 #define HB_OT_TAG_CFF1 HB_TAG('C','F','F',' ')
49 #define CFF_UNDEF_SID CFF_UNDEF_CODE
51 enum EncodingID { StandardEncoding = 0, ExpertEncoding = 1 };
52 enum CharsetID { ISOAdobeCharset = 0, ExpertCharset = 1, ExpertSubsetCharset = 2 };
54 typedef CFFIndex<HBUINT16> CFF1Index;
56 typedef CFFIndex<HBUINT16> CFF1Index;
57 typedef CFF1Index CFF1CharStrings;
58 typedef Subrs<HBUINT16> CFF1Subrs;
60 struct CFF1FDSelect : FDSelect {};
62 /* Encoding */
63 struct Encoding0 {
64 bool sanitize (hb_sanitize_context_t *c) const
66 TRACE_SANITIZE (this);
67 return_trace (codes.sanitize (c));
70 hb_codepoint_t get_code (hb_codepoint_t glyph) const
72 assert (glyph > 0);
73 glyph--;
74 if (glyph < nCodes ())
76 return (hb_codepoint_t)codes[glyph];
78 else
79 return CFF_UNDEF_CODE;
82 HBUINT8 &nCodes () { return codes.len; }
83 HBUINT8 nCodes () const { return codes.len; }
85 ArrayOf<HBUINT8, HBUINT8> codes;
87 DEFINE_SIZE_ARRAY_SIZED (1, codes);
90 struct Encoding1_Range {
91 bool sanitize (hb_sanitize_context_t *c) const
93 TRACE_SANITIZE (this);
94 return_trace (c->check_struct (this));
97 HBUINT8 first;
98 HBUINT8 nLeft;
100 DEFINE_SIZE_STATIC (2);
103 struct Encoding1 {
104 bool sanitize (hb_sanitize_context_t *c) const
106 TRACE_SANITIZE (this);
107 return_trace (ranges.sanitize (c));
110 hb_codepoint_t get_code (hb_codepoint_t glyph) const
112 /* TODO: Add cache like get_sid. */
113 assert (glyph > 0);
114 glyph--;
115 for (unsigned int i = 0; i < nRanges (); i++)
117 if (glyph <= ranges[i].nLeft)
119 hb_codepoint_t code = (hb_codepoint_t) ranges[i].first + glyph;
120 return (likely (code < 0x100) ? code: CFF_UNDEF_CODE);
122 glyph -= (ranges[i].nLeft + 1);
124 return CFF_UNDEF_CODE;
127 HBUINT8 &nRanges () { return ranges.len; }
128 HBUINT8 nRanges () const { return ranges.len; }
130 ArrayOf<Encoding1_Range, HBUINT8> ranges;
132 DEFINE_SIZE_ARRAY_SIZED (1, ranges);
135 struct SuppEncoding {
136 bool sanitize (hb_sanitize_context_t *c) const
138 TRACE_SANITIZE (this);
139 return_trace (c->check_struct (this));
142 HBUINT8 code;
143 HBUINT16 glyph;
145 DEFINE_SIZE_STATIC (3);
148 struct CFF1SuppEncData {
149 bool sanitize (hb_sanitize_context_t *c) const
151 TRACE_SANITIZE (this);
152 return_trace (supps.sanitize (c));
155 void get_codes (hb_codepoint_t sid, hb_vector_t<hb_codepoint_t> &codes) const
157 for (unsigned int i = 0; i < nSups (); i++)
158 if (sid == supps[i].glyph)
159 codes.push (supps[i].code);
162 HBUINT8 &nSups () { return supps.len; }
163 HBUINT8 nSups () const { return supps.len; }
165 ArrayOf<SuppEncoding, HBUINT8> supps;
167 DEFINE_SIZE_ARRAY_SIZED (1, supps);
170 struct Encoding
172 /* serialize a fullset Encoding */
173 bool serialize (hb_serialize_context_t *c, const Encoding &src)
175 TRACE_SERIALIZE (this);
176 return_trace (c->embed (src));
179 /* serialize a subset Encoding */
180 bool serialize (hb_serialize_context_t *c,
181 uint8_t format,
182 unsigned int enc_count,
183 const hb_vector_t<code_pair_t>& code_ranges,
184 const hb_vector_t<code_pair_t>& supp_codes)
186 TRACE_SERIALIZE (this);
187 Encoding *dest = c->extend_min (this);
188 if (unlikely (!dest)) return_trace (false);
189 dest->format = format | ((supp_codes.length > 0) ? 0x80 : 0);
190 switch (format) {
191 case 0:
193 Encoding0 *fmt0 = c->allocate_size<Encoding0> (Encoding0::min_size + HBUINT8::static_size * enc_count);
194 if (unlikely (!fmt0)) return_trace (false);
195 fmt0->nCodes () = enc_count;
196 unsigned int glyph = 0;
197 for (unsigned int i = 0; i < code_ranges.length; i++)
199 hb_codepoint_t code = code_ranges[i].code;
200 for (int left = (int)code_ranges[i].glyph; left >= 0; left--)
201 fmt0->codes[glyph++] = code++;
202 if (unlikely (!((glyph <= 0x100) && (code <= 0x100))))
203 return_trace (false);
206 break;
208 case 1:
210 Encoding1 *fmt1 = c->allocate_size<Encoding1> (Encoding1::min_size + Encoding1_Range::static_size * code_ranges.length);
211 if (unlikely (!fmt1)) return_trace (false);
212 fmt1->nRanges () = code_ranges.length;
213 for (unsigned int i = 0; i < code_ranges.length; i++)
215 if (unlikely (!((code_ranges[i].code <= 0xFF) && (code_ranges[i].glyph <= 0xFF))))
216 return_trace (false);
217 fmt1->ranges[i].first = code_ranges[i].code;
218 fmt1->ranges[i].nLeft = code_ranges[i].glyph;
221 break;
225 if (supp_codes.length)
227 CFF1SuppEncData *suppData = c->allocate_size<CFF1SuppEncData> (CFF1SuppEncData::min_size + SuppEncoding::static_size * supp_codes.length);
228 if (unlikely (!suppData)) return_trace (false);
229 suppData->nSups () = supp_codes.length;
230 for (unsigned int i = 0; i < supp_codes.length; i++)
232 suppData->supps[i].code = supp_codes[i].code;
233 suppData->supps[i].glyph = supp_codes[i].glyph; /* actually SID */
237 return_trace (true);
240 unsigned int get_size () const
242 unsigned int size = min_size;
243 switch (table_format ())
245 case 0: size += u.format0.get_size (); break;
246 case 1: size += u.format1.get_size (); break;
248 if (has_supplement ())
249 size += suppEncData ().get_size ();
250 return size;
253 hb_codepoint_t get_code (hb_codepoint_t glyph) const
255 switch (table_format ())
257 case 0: return u.format0.get_code (glyph);
258 case 1: return u.format1.get_code (glyph);
259 default:return 0;
263 uint8_t table_format () const { return format & 0x7F; }
264 bool has_supplement () const { return format & 0x80; }
266 void get_supplement_codes (hb_codepoint_t sid, hb_vector_t<hb_codepoint_t> &codes) const
268 codes.resize (0);
269 if (has_supplement ())
270 suppEncData().get_codes (sid, codes);
273 bool sanitize (hb_sanitize_context_t *c) const
275 TRACE_SANITIZE (this);
276 if (unlikely (!c->check_struct (this)))
277 return_trace (false);
278 hb_barrier ();
280 switch (table_format ())
282 case 0: if (unlikely (!u.format0.sanitize (c))) { return_trace (false); } break;
283 case 1: if (unlikely (!u.format1.sanitize (c))) { return_trace (false); } break;
284 default:return_trace (false);
286 return_trace (likely (!has_supplement () || suppEncData ().sanitize (c)));
289 protected:
290 const CFF1SuppEncData &suppEncData () const
292 switch (table_format ())
294 case 0: return StructAfter<CFF1SuppEncData> (u.format0.codes[u.format0.nCodes ()-1]);
295 case 1: return StructAfter<CFF1SuppEncData> (u.format1.ranges[u.format1.nRanges ()-1]);
296 default:return Null (CFF1SuppEncData);
300 public:
301 HBUINT8 format;
302 union {
303 Encoding0 format0;
304 Encoding1 format1;
305 } u;
306 /* CFF1SuppEncData suppEncData; */
308 DEFINE_SIZE_MIN (1);
311 /* Charset */
312 struct Charset0
314 bool sanitize (hb_sanitize_context_t *c, unsigned int num_glyphs, unsigned *num_charset_entries) const
316 TRACE_SANITIZE (this);
317 if (num_charset_entries) *num_charset_entries = num_glyphs;
318 return_trace (sids.sanitize (c, num_glyphs - 1));
321 hb_codepoint_t get_sid (hb_codepoint_t glyph, unsigned num_glyphs) const
323 if (unlikely (glyph >= num_glyphs)) return 0;
324 if (unlikely (glyph == 0))
325 return 0;
326 else
327 return sids[glyph - 1];
330 void collect_glyph_to_sid_map (glyph_to_sid_map_t *mapping, unsigned int num_glyphs) const
332 mapping->resize (num_glyphs, false);
333 for (hb_codepoint_t gid = 1; gid < num_glyphs; gid++)
334 mapping->arrayZ[gid] = {sids[gid - 1], gid};
337 hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const
339 if (sid == 0)
340 return 0;
342 for (unsigned int glyph = 1; glyph < num_glyphs; glyph++)
344 if (sids[glyph-1] == sid)
345 return glyph;
347 return 0;
350 static unsigned int get_size (unsigned int num_glyphs)
352 assert (num_glyphs > 0);
353 return UnsizedArrayOf<HBUINT16>::get_size (num_glyphs - 1);
356 UnsizedArrayOf<HBUINT16> sids;
358 DEFINE_SIZE_ARRAY(0, sids);
361 template <typename TYPE>
362 struct Charset_Range {
363 bool sanitize (hb_sanitize_context_t *c) const
365 TRACE_SANITIZE (this);
366 return_trace (c->check_struct (this));
369 HBUINT16 first;
370 TYPE nLeft;
372 DEFINE_SIZE_STATIC (HBUINT16::static_size + TYPE::static_size);
375 template <typename TYPE>
376 struct Charset1_2 {
377 bool sanitize (hb_sanitize_context_t *c, unsigned int num_glyphs, unsigned *num_charset_entries) const
379 TRACE_SANITIZE (this);
380 num_glyphs--;
381 unsigned i;
382 for (i = 0; num_glyphs > 0; i++)
384 if (unlikely (!(ranges[i].sanitize (c) &&
385 hb_barrier () &&
386 (num_glyphs >= ranges[i].nLeft + 1))))
387 return_trace (false);
388 num_glyphs -= (ranges[i].nLeft + 1);
390 if (num_charset_entries)
391 *num_charset_entries = i;
392 return_trace (true);
395 hb_codepoint_t get_sid (hb_codepoint_t glyph, unsigned num_glyphs,
396 code_pair_t *cache = nullptr) const
398 if (unlikely (glyph >= num_glyphs)) return 0;
399 unsigned i;
400 hb_codepoint_t start_glyph;
401 if (cache && likely (cache->glyph <= glyph))
403 i = cache->code;
404 start_glyph = cache->glyph;
406 else
408 if (unlikely (glyph == 0)) return 0;
409 i = 0;
410 start_glyph = 1;
412 glyph -= start_glyph;
413 for (;; i++)
415 unsigned count = ranges[i].nLeft;
416 if (glyph <= count)
418 if (cache)
419 *cache = {i, start_glyph};
420 return ranges[i].first + glyph;
422 count++;
423 start_glyph += count;
424 glyph -= count;
427 return 0;
430 void collect_glyph_to_sid_map (glyph_to_sid_map_t *mapping, unsigned int num_glyphs) const
432 mapping->resize (num_glyphs, false);
433 hb_codepoint_t gid = 1;
434 if (gid >= num_glyphs)
435 return;
436 for (unsigned i = 0;; i++)
438 hb_codepoint_t sid = ranges[i].first;
439 unsigned count = ranges[i].nLeft + 1;
440 unsigned last = gid + count;
441 for (unsigned j = 0; j < count; j++)
442 mapping->arrayZ[gid++] = {sid++, last - 1};
444 if (gid >= num_glyphs)
445 break;
449 hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const
451 if (sid == 0) return 0;
452 hb_codepoint_t glyph = 1;
453 for (unsigned int i = 0;; i++)
455 if (glyph >= num_glyphs)
456 return 0;
457 if ((ranges[i].first <= sid) && (sid <= ranges[i].first + ranges[i].nLeft))
458 return glyph + (sid - ranges[i].first);
459 glyph += (ranges[i].nLeft + 1);
462 return 0;
465 unsigned int get_size (unsigned int num_glyphs) const
467 int glyph = (int) num_glyphs;
468 unsigned num_ranges = 0;
470 assert (glyph > 0);
471 glyph--;
472 for (unsigned int i = 0; glyph > 0; i++)
474 glyph -= (ranges[i].nLeft + 1);
475 num_ranges++;
478 return get_size_for_ranges (num_ranges);
481 static unsigned int get_size_for_ranges (unsigned int num_ranges)
483 return UnsizedArrayOf<Charset_Range<TYPE> >::get_size (num_ranges);
486 UnsizedArrayOf<Charset_Range<TYPE>> ranges;
488 DEFINE_SIZE_ARRAY (0, ranges);
491 typedef Charset1_2<HBUINT8> Charset1;
492 typedef Charset1_2<HBUINT16> Charset2;
493 typedef Charset_Range<HBUINT8> Charset1_Range;
494 typedef Charset_Range<HBUINT16> Charset2_Range;
496 struct Charset
498 /* serialize a fullset Charset */
499 bool serialize (hb_serialize_context_t *c, const Charset &src, unsigned int num_glyphs)
501 TRACE_SERIALIZE (this);
502 return_trace (c->embed ((const char *) &src, src.get_size (num_glyphs)));
505 /* serialize a subset Charset */
506 bool serialize (hb_serialize_context_t *c,
507 uint8_t format,
508 unsigned int num_glyphs,
509 const hb_vector_t<code_pair_t>& sid_ranges)
511 TRACE_SERIALIZE (this);
512 Charset *dest = c->extend_min (this);
513 if (unlikely (!dest)) return_trace (false);
514 dest->format = format;
515 switch (format)
517 case 0:
519 Charset0 *fmt0 = c->allocate_size<Charset0> (Charset0::get_size (num_glyphs), false);
520 if (unlikely (!fmt0)) return_trace (false);
521 unsigned int glyph = 0;
522 for (unsigned int i = 0; i < sid_ranges.length; i++)
524 hb_codepoint_t sid = sid_ranges.arrayZ[i].code;
525 for (int left = (int)sid_ranges.arrayZ[i].glyph; left >= 0; left--)
526 fmt0->sids[glyph++] = sid++;
529 break;
531 case 1:
533 Charset1 *fmt1 = c->allocate_size<Charset1> (Charset1::get_size_for_ranges (sid_ranges.length), false);
534 if (unlikely (!fmt1)) return_trace (false);
535 hb_codepoint_t all_glyphs = 0;
536 for (unsigned int i = 0; i < sid_ranges.length; i++)
538 auto &_ = sid_ranges.arrayZ[i];
539 all_glyphs |= _.glyph;
540 fmt1->ranges[i].first = _.code;
541 fmt1->ranges[i].nLeft = _.glyph;
543 if (unlikely (!(all_glyphs <= 0xFF)))
544 return_trace (false);
546 break;
548 case 2:
550 Charset2 *fmt2 = c->allocate_size<Charset2> (Charset2::get_size_for_ranges (sid_ranges.length), false);
551 if (unlikely (!fmt2)) return_trace (false);
552 hb_codepoint_t all_glyphs = 0;
553 for (unsigned int i = 0; i < sid_ranges.length; i++)
555 auto &_ = sid_ranges.arrayZ[i];
556 all_glyphs |= _.glyph;
557 fmt2->ranges[i].first = _.code;
558 fmt2->ranges[i].nLeft = _.glyph;
560 if (unlikely (!(all_glyphs <= 0xFFFF)))
561 return_trace (false);
563 break;
566 return_trace (true);
569 unsigned int get_size (unsigned int num_glyphs) const
571 switch (format)
573 case 0: return min_size + u.format0.get_size (num_glyphs);
574 case 1: return min_size + u.format1.get_size (num_glyphs);
575 case 2: return min_size + u.format2.get_size (num_glyphs);
576 default:return 0;
580 hb_codepoint_t get_sid (hb_codepoint_t glyph, unsigned int num_glyphs,
581 code_pair_t *cache = nullptr) const
583 switch (format)
585 case 0: return u.format0.get_sid (glyph, num_glyphs);
586 case 1: return u.format1.get_sid (glyph, num_glyphs, cache);
587 case 2: return u.format2.get_sid (glyph, num_glyphs, cache);
588 default:return 0;
592 void collect_glyph_to_sid_map (glyph_to_sid_map_t *mapping, unsigned int num_glyphs) const
594 switch (format)
596 case 0: u.format0.collect_glyph_to_sid_map (mapping, num_glyphs); return;
597 case 1: u.format1.collect_glyph_to_sid_map (mapping, num_glyphs); return;
598 case 2: u.format2.collect_glyph_to_sid_map (mapping, num_glyphs); return;
599 default:return;
603 hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const
605 switch (format)
607 case 0: return u.format0.get_glyph (sid, num_glyphs);
608 case 1: return u.format1.get_glyph (sid, num_glyphs);
609 case 2: return u.format2.get_glyph (sid, num_glyphs);
610 default:return 0;
614 bool sanitize (hb_sanitize_context_t *c, unsigned *num_charset_entries) const
616 TRACE_SANITIZE (this);
617 if (unlikely (!c->check_struct (this)))
618 return_trace (false);
619 hb_barrier ();
621 switch (format)
623 case 0: return_trace (u.format0.sanitize (c, c->get_num_glyphs (), num_charset_entries));
624 case 1: return_trace (u.format1.sanitize (c, c->get_num_glyphs (), num_charset_entries));
625 case 2: return_trace (u.format2.sanitize (c, c->get_num_glyphs (), num_charset_entries));
626 default:return_trace (false);
630 HBUINT8 format;
631 union {
632 Charset0 format0;
633 Charset1 format1;
634 Charset2 format2;
635 } u;
637 DEFINE_SIZE_MIN (1);
640 struct CFF1StringIndex : CFF1Index
642 bool serialize (hb_serialize_context_t *c, const CFF1StringIndex &strings,
643 const hb_vector_t<unsigned> &sidmap)
645 TRACE_SERIALIZE (this);
646 if (unlikely ((strings.count == 0) || (sidmap.length == 0)))
648 if (unlikely (!c->extend_min (this->count)))
649 return_trace (false);
650 count = 0;
651 return_trace (true);
654 if (unlikely (sidmap.in_error ())) return_trace (false);
656 // Save this in a vector since serialize() iterates it twice.
657 hb_vector_t<hb_ubytes_t> bytesArray (+ hb_iter (sidmap)
658 | hb_map (strings));
660 if (unlikely (bytesArray.in_error ())) return_trace (false);
662 bool result = CFF1Index::serialize (c, bytesArray);
663 return_trace (result);
667 struct cff1_top_dict_interp_env_t : num_interp_env_t
669 cff1_top_dict_interp_env_t ()
670 : num_interp_env_t(), prev_offset(0), last_offset(0) {}
671 cff1_top_dict_interp_env_t (const hb_ubytes_t &bytes)
672 : num_interp_env_t(bytes), prev_offset(0), last_offset(0) {}
674 unsigned int prev_offset;
675 unsigned int last_offset;
678 struct name_dict_values_t
680 enum name_dict_val_index_t
682 version,
683 notice,
684 copyright,
685 fullName,
686 familyName,
687 weight,
688 postscript,
689 fontName,
690 baseFontName,
691 registry,
692 ordering,
694 ValCount
697 void init ()
699 for (unsigned int i = 0; i < ValCount; i++)
700 values[i] = CFF_UNDEF_SID;
703 unsigned int& operator[] (unsigned int i)
704 { assert (i < ValCount); return values[i]; }
706 unsigned int operator[] (unsigned int i) const
707 { assert (i < ValCount); return values[i]; }
709 static enum name_dict_val_index_t name_op_to_index (op_code_t op)
711 switch (op) {
712 default: // can't happen - just make some compiler happy
713 case OpCode_version:
714 return version;
715 case OpCode_Notice:
716 return notice;
717 case OpCode_Copyright:
718 return copyright;
719 case OpCode_FullName:
720 return fullName;
721 case OpCode_FamilyName:
722 return familyName;
723 case OpCode_Weight:
724 return weight;
725 case OpCode_PostScript:
726 return postscript;
727 case OpCode_FontName:
728 return fontName;
729 case OpCode_BaseFontName:
730 return baseFontName;
734 unsigned int values[ValCount];
737 struct cff1_top_dict_val_t : op_str_t
739 unsigned int last_arg_offset;
742 struct cff1_top_dict_values_t : top_dict_values_t<cff1_top_dict_val_t>
744 void init ()
746 top_dict_values_t<cff1_top_dict_val_t>::init ();
748 nameSIDs.init ();
749 ros_supplement = 0;
750 cidCount = 8720;
751 EncodingOffset = 0;
752 CharsetOffset = 0;
753 FDSelectOffset = 0;
754 privateDictInfo.init ();
756 void fini () { top_dict_values_t<cff1_top_dict_val_t>::fini (); }
758 bool is_CID () const
759 { return nameSIDs[name_dict_values_t::registry] != CFF_UNDEF_SID; }
761 name_dict_values_t nameSIDs;
762 unsigned int ros_supplement_offset;
763 unsigned int ros_supplement;
764 unsigned int cidCount;
766 unsigned int EncodingOffset;
767 unsigned int CharsetOffset;
768 unsigned int FDSelectOffset;
769 table_info_t privateDictInfo;
772 struct cff1_top_dict_opset_t : top_dict_opset_t<cff1_top_dict_val_t>
774 static void process_op (op_code_t op, cff1_top_dict_interp_env_t& env, cff1_top_dict_values_t& dictval)
776 cff1_top_dict_val_t val;
777 val.last_arg_offset = (env.last_offset-1) - dictval.opStart; /* offset to the last argument */
779 switch (op) {
780 case OpCode_version:
781 case OpCode_Notice:
782 case OpCode_Copyright:
783 case OpCode_FullName:
784 case OpCode_FontName:
785 case OpCode_FamilyName:
786 case OpCode_Weight:
787 case OpCode_PostScript:
788 case OpCode_BaseFontName:
789 dictval.nameSIDs[name_dict_values_t::name_op_to_index (op)] = env.argStack.pop_uint ();
790 env.clear_args ();
791 break;
792 case OpCode_isFixedPitch:
793 case OpCode_ItalicAngle:
794 case OpCode_UnderlinePosition:
795 case OpCode_UnderlineThickness:
796 case OpCode_PaintType:
797 case OpCode_CharstringType:
798 case OpCode_UniqueID:
799 case OpCode_StrokeWidth:
800 case OpCode_SyntheticBase:
801 case OpCode_CIDFontVersion:
802 case OpCode_CIDFontRevision:
803 case OpCode_CIDFontType:
804 case OpCode_UIDBase:
805 case OpCode_FontBBox:
806 case OpCode_XUID:
807 case OpCode_BaseFontBlend:
808 env.clear_args ();
809 break;
811 case OpCode_CIDCount:
812 dictval.cidCount = env.argStack.pop_uint ();
813 env.clear_args ();
814 break;
816 case OpCode_ROS:
817 dictval.ros_supplement = env.argStack.pop_uint ();
818 dictval.nameSIDs[name_dict_values_t::ordering] = env.argStack.pop_uint ();
819 dictval.nameSIDs[name_dict_values_t::registry] = env.argStack.pop_uint ();
820 env.clear_args ();
821 break;
823 case OpCode_Encoding:
824 dictval.EncodingOffset = env.argStack.pop_uint ();
825 env.clear_args ();
826 if (unlikely (dictval.EncodingOffset == 0)) return;
827 break;
829 case OpCode_charset:
830 dictval.CharsetOffset = env.argStack.pop_uint ();
831 env.clear_args ();
832 if (unlikely (dictval.CharsetOffset == 0)) return;
833 break;
835 case OpCode_FDSelect:
836 dictval.FDSelectOffset = env.argStack.pop_uint ();
837 env.clear_args ();
838 break;
840 case OpCode_Private:
841 dictval.privateDictInfo.offset = env.argStack.pop_uint ();
842 dictval.privateDictInfo.size = env.argStack.pop_uint ();
843 env.clear_args ();
844 break;
846 default:
847 env.last_offset = env.str_ref.get_offset ();
848 top_dict_opset_t<cff1_top_dict_val_t>::process_op (op, env, dictval);
849 /* Record this operand below if stack is empty, otherwise done */
850 if (!env.argStack.is_empty ()) return;
851 break;
854 if (unlikely (env.in_error ())) return;
856 dictval.add_op (op, env.str_ref, val);
860 struct cff1_font_dict_values_t : dict_values_t<op_str_t>
862 void init ()
864 dict_values_t<op_str_t>::init ();
865 privateDictInfo.init ();
866 fontName = CFF_UNDEF_SID;
868 void fini () { dict_values_t<op_str_t>::fini (); }
870 table_info_t privateDictInfo;
871 unsigned int fontName;
874 struct cff1_font_dict_opset_t : dict_opset_t
876 static void process_op (op_code_t op, num_interp_env_t& env, cff1_font_dict_values_t& dictval)
878 switch (op) {
879 case OpCode_FontName:
880 dictval.fontName = env.argStack.pop_uint ();
881 env.clear_args ();
882 break;
883 case OpCode_FontMatrix:
884 case OpCode_PaintType:
885 env.clear_args ();
886 break;
887 case OpCode_Private:
888 dictval.privateDictInfo.offset = env.argStack.pop_uint ();
889 dictval.privateDictInfo.size = env.argStack.pop_uint ();
890 env.clear_args ();
891 break;
893 default:
894 dict_opset_t::process_op (op, env);
895 if (!env.argStack.is_empty ()) return;
896 break;
899 if (unlikely (env.in_error ())) return;
901 dictval.add_op (op, env.str_ref);
905 template <typename VAL>
906 struct cff1_private_dict_values_base_t : dict_values_t<VAL>
908 void init ()
910 dict_values_t<VAL>::init ();
911 subrsOffset = 0;
912 localSubrs = &Null (CFF1Subrs);
914 void fini () { dict_values_t<VAL>::fini (); }
916 unsigned int subrsOffset;
917 const CFF1Subrs *localSubrs;
920 typedef cff1_private_dict_values_base_t<op_str_t> cff1_private_dict_values_subset_t;
921 typedef cff1_private_dict_values_base_t<num_dict_val_t> cff1_private_dict_values_t;
923 struct cff1_private_dict_opset_t : dict_opset_t
925 static void process_op (op_code_t op, num_interp_env_t& env, cff1_private_dict_values_t& dictval)
927 num_dict_val_t val;
928 val.init ();
930 switch (op) {
931 case OpCode_BlueValues:
932 case OpCode_OtherBlues:
933 case OpCode_FamilyBlues:
934 case OpCode_FamilyOtherBlues:
935 case OpCode_StemSnapH:
936 case OpCode_StemSnapV:
937 case OpCode_StdHW:
938 case OpCode_StdVW:
939 case OpCode_BlueScale:
940 case OpCode_BlueShift:
941 case OpCode_BlueFuzz:
942 case OpCode_ForceBold:
943 case OpCode_LanguageGroup:
944 case OpCode_ExpansionFactor:
945 case OpCode_initialRandomSeed:
946 case OpCode_defaultWidthX:
947 case OpCode_nominalWidthX:
948 env.clear_args ();
949 break;
950 case OpCode_Subrs:
951 dictval.subrsOffset = env.argStack.pop_uint ();
952 env.clear_args ();
953 break;
955 default:
956 dict_opset_t::process_op (op, env);
957 if (!env.argStack.is_empty ()) return;
958 break;
961 if (unlikely (env.in_error ())) return;
963 dictval.add_op (op, env.str_ref, val);
967 struct cff1_private_dict_opset_subset_t : dict_opset_t
969 static void process_op (op_code_t op, num_interp_env_t& env, cff1_private_dict_values_subset_t& dictval)
971 switch (op) {
972 case OpCode_BlueValues:
973 case OpCode_OtherBlues:
974 case OpCode_FamilyBlues:
975 case OpCode_FamilyOtherBlues:
976 case OpCode_StemSnapH:
977 case OpCode_StemSnapV:
978 case OpCode_StdHW:
979 case OpCode_StdVW:
980 case OpCode_BlueScale:
981 case OpCode_BlueShift:
982 case OpCode_BlueFuzz:
983 case OpCode_ForceBold:
984 case OpCode_LanguageGroup:
985 case OpCode_ExpansionFactor:
986 case OpCode_initialRandomSeed:
987 case OpCode_defaultWidthX:
988 case OpCode_nominalWidthX:
989 env.clear_args ();
990 break;
992 case OpCode_Subrs:
993 dictval.subrsOffset = env.argStack.pop_uint ();
994 env.clear_args ();
995 break;
997 default:
998 dict_opset_t::process_op (op, env);
999 if (!env.argStack.is_empty ()) return;
1000 break;
1003 if (unlikely (env.in_error ())) return;
1005 dictval.add_op (op, env.str_ref);
1009 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;
1010 typedef dict_interpreter_t<cff1_font_dict_opset_t, cff1_font_dict_values_t> cff1_font_dict_interpreter_t;
1012 typedef CFF1Index CFF1NameIndex;
1013 typedef CFF1Index CFF1TopDictIndex;
1015 struct cff1_font_dict_values_mod_t
1017 cff1_font_dict_values_mod_t() { init (); }
1019 void init () { init ( &Null (cff1_font_dict_values_t), CFF_UNDEF_SID ); }
1021 void init (const cff1_font_dict_values_t *base_,
1022 unsigned int fontName_)
1024 base = base_;
1025 fontName = fontName_;
1026 privateDictInfo.init ();
1029 unsigned get_count () const { return base->get_count (); }
1031 const op_str_t &operator [] (unsigned int i) const { return (*base)[i]; }
1033 const cff1_font_dict_values_t *base;
1034 table_info_t privateDictInfo;
1035 unsigned int fontName;
1038 struct CFF1FDArray : FDArray<HBUINT16>
1040 /* FDArray::serialize() requires this partial specialization to compile */
1041 template <typename ITER, typename OP_SERIALIZER>
1042 bool serialize (hb_serialize_context_t *c, ITER it, OP_SERIALIZER& opszr)
1043 { return FDArray<HBUINT16>::serialize<cff1_font_dict_values_mod_t, cff1_font_dict_values_mod_t> (c, it, opszr); }
1046 } /* namespace CFF */
1048 namespace OT {
1050 using namespace CFF;
1052 struct cff1
1054 static constexpr hb_tag_t tableTag = HB_OT_TAG_CFF1;
1056 bool sanitize (hb_sanitize_context_t *c) const
1058 TRACE_SANITIZE (this);
1059 return_trace (c->check_struct (this) &&
1060 hb_barrier () &&
1061 likely (version.major == 1));
1064 template <typename PRIVOPSET, typename PRIVDICTVAL>
1065 struct accelerator_templ_t
1067 static constexpr hb_tag_t tableTag = cff1::tableTag;
1069 accelerator_templ_t (hb_face_t *face)
1071 if (!face) return;
1073 topDict.init ();
1074 fontDicts.init ();
1075 privateDicts.init ();
1077 this->blob = sc.reference_table<cff1> (face);
1079 /* setup for run-time santization */
1080 sc.init (this->blob);
1081 sc.start_processing ();
1083 const OT::cff1 *cff = this->blob->template as<OT::cff1> ();
1085 if (cff == &Null (OT::cff1))
1086 goto fail;
1088 nameIndex = &cff->nameIndex (cff);
1089 if ((nameIndex == &Null (CFF1NameIndex)) || !nameIndex->sanitize (&sc))
1090 goto fail;
1091 hb_barrier ();
1093 topDictIndex = &StructAtOffset<CFF1TopDictIndex> (nameIndex, nameIndex->get_size ());
1094 if ((topDictIndex == &Null (CFF1TopDictIndex)) || !topDictIndex->sanitize (&sc) || (topDictIndex->count == 0))
1095 goto fail;
1096 hb_barrier ();
1098 { /* parse top dict */
1099 const hb_ubytes_t topDictStr = (*topDictIndex)[0];
1100 if (unlikely (!topDictStr.sanitize (&sc))) goto fail;
1101 hb_barrier ();
1102 cff1_top_dict_interp_env_t env (topDictStr);
1103 cff1_top_dict_interpreter_t top_interp (env);
1104 if (unlikely (!top_interp.interpret (topDict))) goto fail;
1107 if (is_predef_charset ())
1108 charset = &Null (Charset);
1109 else
1111 charset = &StructAtOffsetOrNull<Charset> (cff, topDict.CharsetOffset);
1112 if (unlikely ((charset == &Null (Charset)) || !charset->sanitize (&sc, &num_charset_entries))) goto fail;
1113 hb_barrier ();
1116 fdCount = 1;
1117 if (is_CID ())
1119 fdArray = &StructAtOffsetOrNull<CFF1FDArray> (cff, topDict.FDArrayOffset);
1120 fdSelect = &StructAtOffsetOrNull<CFF1FDSelect> (cff, topDict.FDSelectOffset);
1121 if (unlikely ((fdArray == &Null (CFF1FDArray)) || !fdArray->sanitize (&sc) ||
1122 (fdSelect == &Null (CFF1FDSelect)) || !fdSelect->sanitize (&sc, fdArray->count)))
1123 goto fail;
1124 hb_barrier ();
1126 fdCount = fdArray->count;
1128 else
1130 fdArray = &Null (CFF1FDArray);
1131 fdSelect = &Null (CFF1FDSelect);
1134 encoding = &Null (Encoding);
1135 if (is_CID ())
1137 if (unlikely (charset == &Null (Charset))) goto fail;
1139 else
1141 if (!is_predef_encoding ())
1143 encoding = &StructAtOffsetOrNull<Encoding> (cff, topDict.EncodingOffset);
1144 if (unlikely ((encoding == &Null (Encoding)) || !encoding->sanitize (&sc))) goto fail;
1145 hb_barrier ();
1149 stringIndex = &StructAtOffset<CFF1StringIndex> (topDictIndex, topDictIndex->get_size ());
1150 if ((stringIndex == &Null (CFF1StringIndex)) || !stringIndex->sanitize (&sc))
1151 goto fail;
1152 hb_barrier ();
1154 globalSubrs = &StructAtOffset<CFF1Subrs> (stringIndex, stringIndex->get_size ());
1155 if ((globalSubrs != &Null (CFF1Subrs)) && !globalSubrs->sanitize (&sc))
1156 goto fail;
1157 hb_barrier ();
1159 charStrings = &StructAtOffsetOrNull<CFF1CharStrings> (cff, topDict.charStringsOffset);
1161 if ((charStrings == &Null (CFF1CharStrings)) || unlikely (!charStrings->sanitize (&sc)))
1162 goto fail;
1163 hb_barrier ();
1165 num_glyphs = charStrings->count;
1166 if (num_glyphs != sc.get_num_glyphs ())
1167 goto fail;
1169 if (unlikely (!privateDicts.resize (fdCount)))
1170 goto fail;
1171 for (unsigned int i = 0; i < fdCount; i++)
1172 privateDicts[i].init ();
1174 // parse CID font dicts and gather private dicts
1175 if (is_CID ())
1177 for (unsigned int i = 0; i < fdCount; i++)
1179 hb_ubytes_t fontDictStr = (*fdArray)[i];
1180 if (unlikely (!fontDictStr.sanitize (&sc))) goto fail;
1181 hb_barrier ();
1182 cff1_font_dict_values_t *font;
1183 cff1_top_dict_interp_env_t env (fontDictStr);
1184 cff1_font_dict_interpreter_t font_interp (env);
1185 font = fontDicts.push ();
1186 if (unlikely (fontDicts.in_error ())) goto fail;
1188 font->init ();
1189 if (unlikely (!font_interp.interpret (*font))) goto fail;
1190 PRIVDICTVAL *priv = &privateDicts[i];
1191 const hb_ubytes_t privDictStr = StructAtOffset<UnsizedByteStr> (cff, font->privateDictInfo.offset).as_ubytes (font->privateDictInfo.size);
1192 if (unlikely (!privDictStr.sanitize (&sc))) goto fail;
1193 hb_barrier ();
1194 num_interp_env_t env2 (privDictStr);
1195 dict_interpreter_t<PRIVOPSET, PRIVDICTVAL> priv_interp (env2);
1196 priv->init ();
1197 if (unlikely (!priv_interp.interpret (*priv))) goto fail;
1199 priv->localSubrs = &StructAtOffsetOrNull<CFF1Subrs> (&privDictStr, priv->subrsOffset);
1200 if (priv->localSubrs != &Null (CFF1Subrs) &&
1201 unlikely (!priv->localSubrs->sanitize (&sc)))
1202 goto fail;
1203 hb_barrier ();
1206 else /* non-CID */
1208 cff1_top_dict_values_t *font = &topDict;
1209 PRIVDICTVAL *priv = &privateDicts[0];
1211 const hb_ubytes_t privDictStr = StructAtOffset<UnsizedByteStr> (cff, font->privateDictInfo.offset).as_ubytes (font->privateDictInfo.size);
1212 if (unlikely (!privDictStr.sanitize (&sc))) goto fail;
1213 hb_barrier ();
1214 num_interp_env_t env (privDictStr);
1215 dict_interpreter_t<PRIVOPSET, PRIVDICTVAL> priv_interp (env);
1216 priv->init ();
1217 if (unlikely (!priv_interp.interpret (*priv))) goto fail;
1219 priv->localSubrs = &StructAtOffsetOrNull<CFF1Subrs> (&privDictStr, priv->subrsOffset);
1220 if (priv->localSubrs != &Null (CFF1Subrs) &&
1221 unlikely (!priv->localSubrs->sanitize (&sc)))
1222 goto fail;
1223 hb_barrier ();
1226 return;
1228 fail:
1229 _fini ();
1231 ~accelerator_templ_t () { _fini (); }
1232 void _fini ()
1234 sc.end_processing ();
1235 topDict.fini ();
1236 fontDicts.fini ();
1237 privateDicts.fini ();
1238 hb_blob_destroy (blob);
1239 blob = nullptr;
1242 hb_blob_t *get_blob () const { return blob; }
1244 bool is_valid () const { return blob; }
1245 bool is_CID () const { return topDict.is_CID (); }
1247 bool is_predef_charset () const { return topDict.CharsetOffset <= ExpertSubsetCharset; }
1249 unsigned int std_code_to_glyph (hb_codepoint_t code) const
1251 hb_codepoint_t sid = lookup_standard_encoding_for_sid (code);
1252 if (unlikely (sid == CFF_UNDEF_SID))
1253 return 0;
1255 if (charset != &Null (Charset))
1256 return charset->get_glyph (sid, num_glyphs);
1257 else if ((topDict.CharsetOffset == ISOAdobeCharset)
1258 && (code <= 228 /*zcaron*/)) return sid;
1259 return 0;
1262 bool is_predef_encoding () const { return topDict.EncodingOffset <= ExpertEncoding; }
1264 hb_codepoint_t glyph_to_code (hb_codepoint_t glyph,
1265 code_pair_t *glyph_to_sid_cache = nullptr) const
1267 if (encoding != &Null (Encoding))
1268 return encoding->get_code (glyph);
1269 else
1271 hb_codepoint_t sid = glyph_to_sid (glyph, glyph_to_sid_cache);
1272 if (sid == 0) return 0;
1273 hb_codepoint_t code = 0;
1274 switch (topDict.EncodingOffset)
1276 case StandardEncoding:
1277 code = lookup_standard_encoding_for_code (sid);
1278 break;
1279 case ExpertEncoding:
1280 code = lookup_expert_encoding_for_code (sid);
1281 break;
1282 default:
1283 break;
1285 return code;
1289 glyph_to_sid_map_t *create_glyph_to_sid_map () const
1291 if (charset != &Null (Charset))
1293 auto *mapping = (glyph_to_sid_map_t *) hb_malloc (sizeof (glyph_to_sid_map_t));
1294 if (unlikely (!mapping)) return nullptr;
1295 mapping = new (mapping) glyph_to_sid_map_t ();
1296 mapping->push (code_pair_t {0, 1});
1297 charset->collect_glyph_to_sid_map (mapping, num_glyphs);
1298 return mapping;
1300 else
1301 return nullptr;
1304 hb_codepoint_t glyph_to_sid (hb_codepoint_t glyph,
1305 code_pair_t *cache = nullptr) const
1307 if (charset != &Null (Charset))
1308 return charset->get_sid (glyph, num_glyphs, cache);
1309 else
1311 hb_codepoint_t sid = 0;
1312 switch (topDict.CharsetOffset)
1314 case ISOAdobeCharset:
1315 if (glyph <= 228 /*zcaron*/) sid = glyph;
1316 break;
1317 case ExpertCharset:
1318 sid = lookup_expert_charset_for_sid (glyph);
1319 break;
1320 case ExpertSubsetCharset:
1321 sid = lookup_expert_subset_charset_for_sid (glyph);
1322 break;
1323 default:
1324 break;
1326 return sid;
1330 hb_codepoint_t sid_to_glyph (hb_codepoint_t sid) const
1332 if (charset != &Null (Charset))
1333 return charset->get_glyph (sid, num_glyphs);
1334 else
1336 hb_codepoint_t glyph = 0;
1337 switch (topDict.CharsetOffset)
1339 case ISOAdobeCharset:
1340 if (sid <= 228 /*zcaron*/) glyph = sid;
1341 break;
1342 case ExpertCharset:
1343 glyph = lookup_expert_charset_for_glyph (sid);
1344 break;
1345 case ExpertSubsetCharset:
1346 glyph = lookup_expert_subset_charset_for_glyph (sid);
1347 break;
1348 default:
1349 break;
1351 return glyph;
1355 protected:
1356 hb_sanitize_context_t sc;
1358 public:
1359 hb_blob_t *blob = nullptr;
1360 const Encoding *encoding = nullptr;
1361 const Charset *charset = nullptr;
1362 const CFF1NameIndex *nameIndex = nullptr;
1363 const CFF1TopDictIndex *topDictIndex = nullptr;
1364 const CFF1StringIndex *stringIndex = nullptr;
1365 const CFF1Subrs *globalSubrs = nullptr;
1366 const CFF1CharStrings *charStrings = nullptr;
1367 const CFF1FDArray *fdArray = nullptr;
1368 const CFF1FDSelect *fdSelect = nullptr;
1369 unsigned int fdCount = 0;
1371 cff1_top_dict_values_t topDict;
1372 hb_vector_t<cff1_font_dict_values_t>
1373 fontDicts;
1374 hb_vector_t<PRIVDICTVAL> privateDicts;
1376 unsigned int num_glyphs = 0;
1377 unsigned int num_charset_entries = 0;
1380 struct accelerator_t : accelerator_templ_t<cff1_private_dict_opset_t, cff1_private_dict_values_t>
1382 accelerator_t (hb_face_t *face) : SUPER (face)
1384 glyph_names.set_relaxed (nullptr);
1386 if (!is_valid ()) return;
1387 if (is_CID ()) return;
1389 ~accelerator_t ()
1391 hb_sorted_vector_t<gname_t> *names = glyph_names.get_relaxed ();
1392 if (names)
1394 names->fini ();
1395 hb_free (names);
1399 bool get_glyph_name (hb_codepoint_t glyph,
1400 char *buf, unsigned int buf_len) const
1402 if (unlikely (glyph >= num_glyphs)) return false;
1403 if (unlikely (!is_valid ())) return false;
1404 if (is_CID()) return false;
1405 if (unlikely (!buf_len)) return true;
1406 hb_codepoint_t sid = glyph_to_sid (glyph);
1407 const char *str;
1408 size_t str_len;
1409 if (sid < cff1_std_strings_length)
1411 hb_bytes_t byte_str = cff1_std_strings (sid);
1412 str = byte_str.arrayZ;
1413 str_len = byte_str.length;
1415 else
1417 hb_ubytes_t ubyte_str = (*stringIndex)[sid - cff1_std_strings_length];
1418 str = (const char *)ubyte_str.arrayZ;
1419 str_len = ubyte_str.length;
1421 if (!str_len) return false;
1422 unsigned int len = hb_min (buf_len - 1, str_len);
1423 strncpy (buf, (const char*)str, len);
1424 buf[len] = '\0';
1425 return true;
1428 bool get_glyph_from_name (const char *name, int len,
1429 hb_codepoint_t *glyph) const
1431 if (unlikely (!is_valid ())) return false;
1432 if (is_CID()) return false;
1433 if (len < 0) len = strlen (name);
1434 if (unlikely (!len)) return false;
1436 retry:
1437 hb_sorted_vector_t<gname_t> *names = glyph_names.get_acquire ();
1438 if (unlikely (!names))
1440 names = (hb_sorted_vector_t<gname_t> *) hb_calloc (sizeof (hb_sorted_vector_t<gname_t>), 1);
1441 if (likely (names))
1443 names->init ();
1444 /* TODO */
1446 /* fill glyph names */
1447 code_pair_t glyph_to_sid_cache {0, HB_CODEPOINT_INVALID};
1448 for (hb_codepoint_t gid = 0; gid < num_glyphs; gid++)
1450 hb_codepoint_t sid = glyph_to_sid (gid, &glyph_to_sid_cache);
1451 gname_t gname;
1452 gname.sid = sid;
1453 if (sid < cff1_std_strings_length)
1454 gname.name = cff1_std_strings (sid);
1455 else
1457 hb_ubytes_t ustr = (*stringIndex)[sid - cff1_std_strings_length];
1458 gname.name = hb_bytes_t ((const char*) ustr.arrayZ, ustr.length);
1460 if (unlikely (!gname.name.arrayZ))
1461 gname.name = hb_bytes_t ("", 0); /* To avoid nullptr. */
1462 names->push (gname);
1464 names->qsort ();
1466 if (unlikely (!glyph_names.cmpexch (nullptr, names)))
1468 if (names)
1470 names->fini ();
1471 hb_free (names);
1473 goto retry;
1477 gname_t key = { hb_bytes_t (name, len), 0 };
1478 const gname_t *gname = names ? names->bsearch (key) : nullptr;
1479 if (!gname) return false;
1480 hb_codepoint_t gid = sid_to_glyph (gname->sid);
1481 if (!gid && gname->sid) return false;
1482 *glyph = gid;
1483 return true;
1486 HB_INTERNAL bool get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const;
1487 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;
1488 HB_INTERNAL bool get_path (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session) const;
1490 private:
1491 struct gname_t
1493 hb_bytes_t name;
1494 uint16_t sid;
1496 static int cmp (const void *a_, const void *b_)
1498 const gname_t *a = (const gname_t *)a_;
1499 const gname_t *b = (const gname_t *)b_;
1500 unsigned minlen = hb_min (a->name.length, b->name.length);
1501 int ret = strncmp (a->name.arrayZ, b->name.arrayZ, minlen);
1502 if (ret) return ret;
1503 return a->name.length - b->name.length;
1506 int cmp (const gname_t &a) const { return cmp (&a, this); }
1509 mutable hb_atomic_ptr_t<hb_sorted_vector_t<gname_t>> glyph_names;
1511 typedef accelerator_templ_t<cff1_private_dict_opset_t, cff1_private_dict_values_t> SUPER;
1514 struct accelerator_subset_t : accelerator_templ_t<cff1_private_dict_opset_subset_t, cff1_private_dict_values_subset_t>
1516 accelerator_subset_t (hb_face_t *face) : SUPER (face) {}
1517 ~accelerator_subset_t ()
1519 if (cff_accelerator)
1520 cff_subset_accelerator_t::destroy (cff_accelerator);
1523 HB_INTERNAL bool subset (hb_subset_context_t *c) const;
1524 HB_INTERNAL bool serialize (hb_serialize_context_t *c,
1525 struct cff1_subset_plan &plan) const;
1526 HB_INTERNAL bool get_seac_components (hb_codepoint_t glyph, hb_codepoint_t *base, hb_codepoint_t *accent) const;
1528 mutable CFF::cff_subset_accelerator_t* cff_accelerator = nullptr;
1530 typedef accelerator_templ_t<cff1_private_dict_opset_subset_t, cff1_private_dict_values_subset_t> SUPER;
1533 protected:
1534 HB_INTERNAL static hb_codepoint_t lookup_standard_encoding_for_code (hb_codepoint_t sid);
1535 HB_INTERNAL static hb_codepoint_t lookup_expert_encoding_for_code (hb_codepoint_t sid);
1536 HB_INTERNAL static hb_codepoint_t lookup_expert_charset_for_sid (hb_codepoint_t glyph);
1537 HB_INTERNAL static hb_codepoint_t lookup_expert_subset_charset_for_sid (hb_codepoint_t glyph);
1538 HB_INTERNAL static hb_codepoint_t lookup_expert_charset_for_glyph (hb_codepoint_t sid);
1539 HB_INTERNAL static hb_codepoint_t lookup_expert_subset_charset_for_glyph (hb_codepoint_t sid);
1540 HB_INTERNAL static hb_codepoint_t lookup_standard_encoding_for_sid (hb_codepoint_t code);
1542 public:
1543 FixedVersion<HBUINT8> version; /* Version of CFF table. set to 0x0100u */
1544 NNOffsetTo<CFF1NameIndex, HBUINT8> nameIndex; /* headerSize = Offset to Name INDEX. */
1545 HBUINT8 offSize; /* offset size (unused?) */
1547 public:
1548 DEFINE_SIZE_STATIC (4);
1551 struct cff1_accelerator_t : cff1::accelerator_t {
1552 cff1_accelerator_t (hb_face_t *face) : cff1::accelerator_t (face) {}
1555 struct cff1_subset_accelerator_t : cff1::accelerator_subset_t {
1556 cff1_subset_accelerator_t (hb_face_t *face) : cff1::accelerator_subset_t (face) {}
1559 } /* namespace OT */
1561 #endif /* HB_OT_CFF1_TABLE_HH */