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
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"
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
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
{};
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
74 if (glyph
< nCodes ())
76 return (hb_codepoint_t
)codes
[glyph
];
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));
100 DEFINE_SIZE_STATIC (2);
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. */
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));
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
);
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
,
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);
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);
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
;
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 */
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 ();
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
);
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
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);
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
)));
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
);
306 /* CFF1SuppEncData suppEncData; */
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))
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
342 for (unsigned int glyph
= 1; glyph
< num_glyphs
; glyph
++)
344 if (sids
[glyph
-1] == sid
)
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));
372 DEFINE_SIZE_STATIC (HBUINT16::static_size
+ TYPE::static_size
);
375 template <typename TYPE
>
377 bool sanitize (hb_sanitize_context_t
*c
, unsigned int num_glyphs
, unsigned *num_charset_entries
) const
379 TRACE_SANITIZE (this);
382 for (i
= 0; num_glyphs
> 0; i
++)
384 if (unlikely (!(ranges
[i
].sanitize (c
) &&
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
;
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;
400 hb_codepoint_t start_glyph
;
401 if (cache
&& likely (cache
->glyph
<= glyph
))
404 start_glyph
= cache
->glyph
;
408 if (unlikely (glyph
== 0)) return 0;
412 glyph
-= start_glyph
;
415 unsigned count
= ranges
[i
].nLeft
;
419 *cache
= {i
, start_glyph
};
420 return ranges
[i
].first
+ glyph
;
423 start_glyph
+= count
;
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
)
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
)
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
)
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);
465 unsigned int get_size (unsigned int num_glyphs
) const
467 int glyph
= (int) num_glyphs
;
468 unsigned num_ranges
= 0;
472 for (unsigned int i
= 0; glyph
> 0; i
++)
474 glyph
-= (ranges
[i
].nLeft
+ 1);
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
;
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
,
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
;
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
++;
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);
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);
569 unsigned int get_size (unsigned int num_glyphs
) const
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
);
580 hb_codepoint_t
get_sid (hb_codepoint_t glyph
, unsigned int num_glyphs
,
581 code_pair_t
*cache
= nullptr) const
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
);
592 void collect_glyph_to_sid_map (glyph_to_sid_map_t
*mapping
, unsigned int num_glyphs
) const
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;
603 hb_codepoint_t
get_glyph (hb_codepoint_t sid
, unsigned int num_glyphs
) const
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
);
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);
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);
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);
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
)
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
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
)
712 default: // can't happen - just make some compiler happy
717 case OpCode_Copyright
:
719 case OpCode_FullName
:
721 case OpCode_FamilyName
:
725 case OpCode_PostScript
:
727 case OpCode_FontName
:
729 case OpCode_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
>
746 top_dict_values_t
<cff1_top_dict_val_t
>::init ();
754 privateDictInfo
.init ();
756 void fini () { top_dict_values_t
<cff1_top_dict_val_t
>::fini (); }
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 */
782 case OpCode_Copyright
:
783 case OpCode_FullName
:
784 case OpCode_FontName
:
785 case OpCode_FamilyName
:
787 case OpCode_PostScript
:
788 case OpCode_BaseFontName
:
789 dictval
.nameSIDs
[name_dict_values_t::name_op_to_index (op
)] = env
.argStack
.pop_uint ();
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
:
805 case OpCode_FontBBox
:
807 case OpCode_BaseFontBlend
:
811 case OpCode_CIDCount
:
812 dictval
.cidCount
= env
.argStack
.pop_uint ();
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 ();
823 case OpCode_Encoding
:
824 dictval
.EncodingOffset
= env
.argStack
.pop_uint ();
826 if (unlikely (dictval
.EncodingOffset
== 0)) return;
830 dictval
.CharsetOffset
= env
.argStack
.pop_uint ();
832 if (unlikely (dictval
.CharsetOffset
== 0)) return;
835 case OpCode_FDSelect
:
836 dictval
.FDSelectOffset
= env
.argStack
.pop_uint ();
841 dictval
.privateDictInfo
.offset
= env
.argStack
.pop_uint ();
842 dictval
.privateDictInfo
.size
= env
.argStack
.pop_uint ();
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;
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
>
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
)
879 case OpCode_FontName
:
880 dictval
.fontName
= env
.argStack
.pop_uint ();
883 case OpCode_FontMatrix
:
884 case OpCode_PaintType
:
888 dictval
.privateDictInfo
.offset
= env
.argStack
.pop_uint ();
889 dictval
.privateDictInfo
.size
= env
.argStack
.pop_uint ();
894 dict_opset_t::process_op (op
, env
);
895 if (!env
.argStack
.is_empty ()) return;
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
>
910 dict_values_t
<VAL
>::init ();
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
)
931 case OpCode_BlueValues
:
932 case OpCode_OtherBlues
:
933 case OpCode_FamilyBlues
:
934 case OpCode_FamilyOtherBlues
:
935 case OpCode_StemSnapH
:
936 case OpCode_StemSnapV
:
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
:
951 dictval
.subrsOffset
= env
.argStack
.pop_uint ();
956 dict_opset_t::process_op (op
, env
);
957 if (!env
.argStack
.is_empty ()) return;
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
)
972 case OpCode_BlueValues
:
973 case OpCode_OtherBlues
:
974 case OpCode_FamilyBlues
:
975 case OpCode_FamilyOtherBlues
:
976 case OpCode_StemSnapH
:
977 case OpCode_StemSnapV
:
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
:
993 dictval
.subrsOffset
= env
.argStack
.pop_uint ();
998 dict_opset_t::process_op (op
, env
);
999 if (!env
.argStack
.is_empty ()) return;
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_
)
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 */
1050 using namespace CFF
;
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) &&
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
)
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
))
1088 nameIndex
= &cff
->nameIndex (cff
);
1089 if ((nameIndex
== &Null (CFF1NameIndex
)) || !nameIndex
->sanitize (&sc
))
1093 topDictIndex
= &StructAtOffset
<CFF1TopDictIndex
> (nameIndex
, nameIndex
->get_size ());
1094 if ((topDictIndex
== &Null (CFF1TopDictIndex
)) || !topDictIndex
->sanitize (&sc
) || (topDictIndex
->count
== 0))
1098 { /* parse top dict */
1099 const hb_ubytes_t topDictStr
= (*topDictIndex
)[0];
1100 if (unlikely (!topDictStr
.sanitize (&sc
))) goto fail
;
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
);
1111 charset
= &StructAtOffsetOrNull
<Charset
> (cff
, topDict
.CharsetOffset
);
1112 if (unlikely ((charset
== &Null (Charset
)) || !charset
->sanitize (&sc
, &num_charset_entries
))) goto fail
;
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
)))
1126 fdCount
= fdArray
->count
;
1130 fdArray
= &Null (CFF1FDArray
);
1131 fdSelect
= &Null (CFF1FDSelect
);
1134 encoding
= &Null (Encoding
);
1137 if (unlikely (charset
== &Null (Charset
))) goto fail
;
1141 if (!is_predef_encoding ())
1143 encoding
= &StructAtOffsetOrNull
<Encoding
> (cff
, topDict
.EncodingOffset
);
1144 if (unlikely ((encoding
== &Null (Encoding
)) || !encoding
->sanitize (&sc
))) goto fail
;
1149 stringIndex
= &StructAtOffset
<CFF1StringIndex
> (topDictIndex
, topDictIndex
->get_size ());
1150 if ((stringIndex
== &Null (CFF1StringIndex
)) || !stringIndex
->sanitize (&sc
))
1154 globalSubrs
= &StructAtOffset
<CFF1Subrs
> (stringIndex
, stringIndex
->get_size ());
1155 if ((globalSubrs
!= &Null (CFF1Subrs
)) && !globalSubrs
->sanitize (&sc
))
1159 charStrings
= &StructAtOffsetOrNull
<CFF1CharStrings
> (cff
, topDict
.charStringsOffset
);
1161 if ((charStrings
== &Null (CFF1CharStrings
)) || unlikely (!charStrings
->sanitize (&sc
)))
1165 num_glyphs
= charStrings
->count
;
1166 if (num_glyphs
!= sc
.get_num_glyphs ())
1169 if (unlikely (!privateDicts
.resize (fdCount
)))
1171 for (unsigned int i
= 0; i
< fdCount
; i
++)
1172 privateDicts
[i
].init ();
1174 // parse CID font dicts and gather private dicts
1177 for (unsigned int i
= 0; i
< fdCount
; i
++)
1179 hb_ubytes_t fontDictStr
= (*fdArray
)[i
];
1180 if (unlikely (!fontDictStr
.sanitize (&sc
))) goto fail
;
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
;
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
;
1194 num_interp_env_t
env2 (privDictStr
);
1195 dict_interpreter_t
<PRIVOPSET
, PRIVDICTVAL
> priv_interp (env2
);
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
)))
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
;
1214 num_interp_env_t
env (privDictStr
);
1215 dict_interpreter_t
<PRIVOPSET
, PRIVDICTVAL
> priv_interp (env
);
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
)))
1231 ~accelerator_templ_t () { _fini (); }
1234 sc
.end_processing ();
1237 privateDicts
.fini ();
1238 hb_blob_destroy (blob
);
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
))
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
;
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
);
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
);
1279 case ExpertEncoding
:
1280 code
= lookup_expert_encoding_for_code (sid
);
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
);
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
);
1311 hb_codepoint_t sid
= 0;
1312 switch (topDict
.CharsetOffset
)
1314 case ISOAdobeCharset
:
1315 if (glyph
<= 228 /*zcaron*/) sid
= glyph
;
1318 sid
= lookup_expert_charset_for_sid (glyph
);
1320 case ExpertSubsetCharset
:
1321 sid
= lookup_expert_subset_charset_for_sid (glyph
);
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
);
1336 hb_codepoint_t glyph
= 0;
1337 switch (topDict
.CharsetOffset
)
1339 case ISOAdobeCharset
:
1340 if (sid
<= 228 /*zcaron*/) glyph
= sid
;
1343 glyph
= lookup_expert_charset_for_glyph (sid
);
1345 case ExpertSubsetCharset
:
1346 glyph
= lookup_expert_subset_charset_for_glyph (sid
);
1356 hb_sanitize_context_t sc
;
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
>
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;
1391 hb_sorted_vector_t
<gname_t
> *names
= glyph_names
.get_relaxed ();
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
);
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
;
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
);
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;
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);
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
);
1453 if (sid
< cff1_std_strings_length
)
1454 gname
.name
= cff1_std_strings (sid
);
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
);
1466 if (unlikely (!glyph_names
.cmpexch (nullptr, names
)))
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;
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;
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
;
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
);
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?) */
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 */