diff options
Diffstat (limited to 'src/3rdparty/harfbuzz-ng/src/hb-subset-cff1.cc')
-rw-r--r-- | src/3rdparty/harfbuzz-ng/src/hb-subset-cff1.cc | 389 |
1 files changed, 245 insertions, 144 deletions
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-subset-cff1.cc b/src/3rdparty/harfbuzz-ng/src/hb-subset-cff1.cc index 35fecd67bc..e9dd5d6427 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-subset-cff1.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-subset-cff1.cc @@ -32,36 +32,59 @@ #include "hb-ot-cff1-table.hh" #include "hb-set.h" #include "hb-bimap.hh" -#include "hb-subset-cff1.hh" #include "hb-subset-plan.hh" #include "hb-subset-cff-common.hh" #include "hb-cff1-interp-cs.hh" using namespace CFF; -struct remap_sid_t : hb_inc_bimap_t +struct remap_sid_t { + unsigned get_population () const { return vector.length; } + + void alloc (unsigned size) + { + map.alloc (size); + vector.alloc (size, true); + } + + bool in_error () const + { return map.in_error () || vector.in_error (); } + unsigned int add (unsigned int sid) { - if ((sid != CFF_UNDEF_SID) && !is_std_std (sid)) - return offset_sid (hb_inc_bimap_t::add (unoffset_sid (sid))); - else + if (is_std_str (sid) || (sid == CFF_UNDEF_SID)) return sid; + + sid = unoffset_sid (sid); + unsigned v = next; + if (map.set (sid, v, false)) + { + vector.push (sid); + next++; + } + else + v = map.get (sid); // already exists + return offset_sid (v); } unsigned int operator[] (unsigned int sid) const { - if (is_std_std (sid) || (sid == CFF_UNDEF_SID)) + if (is_std_str (sid) || (sid == CFF_UNDEF_SID)) return sid; - else - return offset_sid (get (unoffset_sid (sid))); + + return offset_sid (map.get (unoffset_sid (sid))); } static const unsigned int num_std_strings = 391; - static bool is_std_std (unsigned int sid) { return sid < num_std_strings; } + static bool is_std_str (unsigned int sid) { return sid < num_std_strings; } static unsigned int offset_sid (unsigned int sid) { return sid + num_std_strings; } static unsigned int unoffset_sid (unsigned int sid) { return sid - num_std_strings; } + unsigned next = 0; + + hb_map_t map; + hb_vector_t<unsigned> vector; }; struct cff1_sub_table_info_t : cff_sub_table_info_t @@ -167,9 +190,10 @@ struct cff1_top_dict_op_serializer_t : cff_top_dict_op_serializer_t<cff1_top_dic * for supplement, the original byte string is copied along with the op code */ op_str_t supp_op; supp_op.op = op; - if ( unlikely (!(opstr.str.length >= opstr.last_arg_offset + 3))) + if ( unlikely (!(opstr.length >= opstr.last_arg_offset + 3))) return_trace (false); - supp_op.str = byte_str_t (&opstr.str + opstr.last_arg_offset, opstr.str.length - opstr.last_arg_offset); + supp_op.ptr = opstr.ptr + opstr.last_arg_offset; + supp_op.length = opstr.length - opstr.last_arg_offset; return_trace (UnsizedByteStr::serialize_int2 (c, mod.nameSIDs[name_dict_values_t::registry]) && UnsizedByteStr::serialize_int2 (c, mod.nameSIDs[name_dict_values_t::ordering]) && copy_opstr (c, supp_op)); @@ -233,7 +257,7 @@ struct cff1_cs_opset_flatten_t : cff1_cs_opset_t<cff1_cs_opset_flatten_t, flatte { str_encoder_t encoder (param.flatStr); for (unsigned int i = env.arg_start; i < env.argStack.get_count (); i++) - encoder.encode_num (env.eval_arg (i)); + encoder.encode_num_cs (env.eval_arg (i)); SUPER::flush_args (env, param); } @@ -247,7 +271,7 @@ struct cff1_cs_opset_flatten_t : cff1_cs_opset_t<cff1_cs_opset_flatten_t, flatte { assert (env.has_width); str_encoder_t encoder (param.flatStr); - encoder.encode_num (env.width); + encoder.encode_num_cs (env.width); } static void flush_hintmask (op_code_t op, cff1_cs_interp_env_t &env, flatten_param_t& param) @@ -270,16 +294,17 @@ struct range_list_t : hb_vector_t<code_pair_t> /* replace the first glyph ID in the "glyph" field each range with a nLeft value */ bool complete (unsigned int last_glyph) { - bool two_byte = false; - for (unsigned int i = (*this).length; i > 0; i--) + hb_codepoint_t all_glyphs = 0; + unsigned count = this->length; + for (unsigned int i = count; i; i--) { - code_pair_t &pair = (*this)[i - 1]; - unsigned int nLeft = last_glyph - pair.glyph - 1; - if (nLeft >= 0x100) - two_byte = true; + code_pair_t &pair = arrayZ[i - 1]; + unsigned int nLeft = last_glyph - pair.glyph - 1; + all_glyphs |= nLeft; last_glyph = pair.glyph; pair.glyph = nLeft; } + bool two_byte = all_glyphs >= 0x100; return two_byte; } }; @@ -334,6 +359,36 @@ struct cff1_cs_opset_subr_subset_t : cff1_cs_opset_t<cff1_cs_opset_subr_subset_t typedef cff1_cs_opset_t<cff1_cs_opset_subr_subset_t, subr_subset_param_t> SUPER; }; +struct cff1_private_dict_op_serializer_t : op_serializer_t +{ + cff1_private_dict_op_serializer_t (bool desubroutinize_, bool drop_hints_) + : desubroutinize (desubroutinize_), drop_hints (drop_hints_) {} + + bool serialize (hb_serialize_context_t *c, + const op_str_t &opstr, + objidx_t subrs_link) const + { + TRACE_SERIALIZE (this); + + if (drop_hints && dict_opset_t::is_hint_op (opstr.op)) + return_trace (true); + + if (opstr.op == OpCode_Subrs) + { + if (desubroutinize || !subrs_link) + return_trace (true); + else + return_trace (FontDict::serialize_link2_op (c, opstr.op, subrs_link)); + } + + return_trace (copy_opstr (c, opstr)); + } + + protected: + const bool desubroutinize; + const bool drop_hints; +}; + struct cff1_subr_subsetter_t : subr_subsetter_t<cff1_subr_subsetter_t, CFF1Subrs, const OT::cff1::accelerator_subset_t, cff1_cs_interp_env_t, cff1_cs_opset_subr_subset_t, OpCode_endchar> { cff1_subr_subsetter_t (const OT::cff1::accelerator_subset_t &acc_, const hb_subset_plan_t *plan_) @@ -360,8 +415,10 @@ struct cff1_subr_subsetter_t : subr_subsetter_t<cff1_subr_subsetter_t, CFF1Subrs } }; -struct cff_subset_plan { - cff_subset_plan () +namespace OT { +struct cff1_subset_plan +{ + cff1_subset_plan () { for (unsigned int i = 0; i < name_dict_values_t::ValCount; i++) topDictModSIDs[i] = CFF_UNDEF_SID; @@ -371,7 +428,7 @@ struct cff_subset_plan { { const Encoding *encoding = acc.encoding; unsigned int size0, size1; - hb_codepoint_t code, last_code = CFF_UNDEF_CODE; + unsigned code, last_code = CFF_UNDEF_CODE - 1; hb_vector_t<hb_codepoint_t> supp_codes; if (unlikely (!subset_enc_code_ranges.resize (0))) @@ -382,39 +439,42 @@ struct cff_subset_plan { supp_codes.init (); + code_pair_t glyph_to_sid_cache {0, HB_CODEPOINT_INVALID}; subset_enc_num_codes = plan->num_output_glyphs () - 1; unsigned int glyph; - for (glyph = 1; glyph < plan->num_output_glyphs (); glyph++) + auto it = hb_iter (plan->new_to_old_gid_list); + if (it->first == 0) it++; + auto _ = *it; + for (glyph = 1; glyph < num_glyphs; glyph++) { - hb_codepoint_t old_glyph; - if (!plan->old_gid_for_new_gid (glyph, &old_glyph)) + hb_codepoint_t old_glyph; + if (glyph == _.first) + { + old_glyph = _.second; + _ = *++it; + } + else { - /* Retain the code for the old missing glyph ID */ + /* Retain the SID for the old missing glyph ID */ old_glyph = glyph; } - code = acc.glyph_to_code (old_glyph); + code = acc.glyph_to_code (old_glyph, &glyph_to_sid_cache); if (code == CFF_UNDEF_CODE) { subset_enc_num_codes = glyph - 1; break; } - if ((last_code == CFF_UNDEF_CODE) || (code != last_code + 1)) - { - code_pair_t pair = { code, glyph }; - subset_enc_code_ranges.push (pair); - } + if (code != last_code + 1) + subset_enc_code_ranges.push (code_pair_t {code, glyph}); last_code = code; if (encoding != &Null (Encoding)) { - hb_codepoint_t sid = acc.glyph_to_sid (old_glyph); + hb_codepoint_t sid = acc.glyph_to_sid (old_glyph, &glyph_to_sid_cache); encoding->get_supplement_codes (sid, supp_codes); for (unsigned int i = 0; i < supp_codes.length; i++) - { - code_pair_t pair = { supp_codes[i], sid }; - subset_enc_supp_codes.push (pair); - } + subset_enc_supp_codes.push (code_pair_t {supp_codes[i], sid}); } } supp_codes.fini (); @@ -431,46 +491,93 @@ struct cff_subset_plan { subset_enc_format = 1; } - void plan_subset_charset (const OT::cff1::accelerator_subset_t &acc, hb_subset_plan_t *plan) + bool plan_subset_charset (const OT::cff1::accelerator_subset_t &acc, hb_subset_plan_t *plan) { unsigned int size0, size_ranges; - hb_codepoint_t sid, last_sid = CFF_UNDEF_CODE; + unsigned last_sid = CFF_UNDEF_CODE - 1; if (unlikely (!subset_charset_ranges.resize (0))) { plan->check_success (false); - return; + return false; } - unsigned int glyph; - for (glyph = 1; glyph < plan->num_output_glyphs (); glyph++) + code_pair_t glyph_to_sid_cache {0, HB_CODEPOINT_INVALID}; + + unsigned num_glyphs = plan->num_output_glyphs (); + + if (unlikely (!subset_charset_ranges.alloc (hb_min (num_glyphs, + acc.num_charset_entries)))) { - hb_codepoint_t old_glyph; - if (!plan->old_gid_for_new_gid (glyph, &old_glyph)) + plan->check_success (false); + return false; + } + + glyph_to_sid_map_t *glyph_to_sid_map = acc.cff_accelerator ? + acc.cff_accelerator->glyph_to_sid_map.get_acquire () : + nullptr; + bool created_map = false; + if (!glyph_to_sid_map && acc.cff_accelerator) + { + created_map = true; + glyph_to_sid_map = acc.create_glyph_to_sid_map (); + } + + auto it = hb_iter (plan->new_to_old_gid_list); + if (it->first == 0) it++; + auto _ = *it; + bool not_is_cid = !acc.is_CID (); + bool skip = !not_is_cid && glyph_to_sid_map; + if (not_is_cid) + sidmap.alloc (num_glyphs); + for (hb_codepoint_t glyph = 1; glyph < num_glyphs; glyph++) + { + hb_codepoint_t old_glyph; + if (glyph == _.first) + { + old_glyph = _.second; + _ = *++it; + } + else { /* Retain the SID for the old missing glyph ID */ old_glyph = glyph; } - sid = acc.glyph_to_sid (old_glyph); + unsigned sid = glyph_to_sid_map ? + glyph_to_sid_map->arrayZ[old_glyph].code : + acc.glyph_to_sid (old_glyph, &glyph_to_sid_cache); - if (!acc.is_CID ()) + if (not_is_cid) sid = sidmap.add (sid); - if ((last_sid == CFF_UNDEF_CODE) || (sid != last_sid + 1)) + if (sid != last_sid + 1) + subset_charset_ranges.push (code_pair_t {sid, glyph}); + + if (glyph == old_glyph && skip) { - code_pair_t pair = { sid, glyph }; - subset_charset_ranges.push (pair); + glyph = hb_min (_.first - 1, glyph_to_sid_map->arrayZ[old_glyph].glyph); + sid += glyph - old_glyph; } last_sid = sid; } - bool two_byte = subset_charset_ranges.complete (glyph); + if (created_map) + { + if ((!plan->accelerator && acc.cff_accelerator) || + !acc.cff_accelerator->glyph_to_sid_map.cmpexch (nullptr, glyph_to_sid_map)) + { + glyph_to_sid_map->~glyph_to_sid_map_t (); + hb_free (glyph_to_sid_map); + } + } + + bool two_byte = subset_charset_ranges.complete (num_glyphs); - size0 = Charset0::min_size + HBUINT16::static_size * (plan->num_output_glyphs () - 1); + size0 = Charset0::get_size (plan->num_output_glyphs ()); if (!two_byte) - size_ranges = Charset1::min_size + Charset1_Range::static_size * subset_charset_ranges.length; + size_ranges = Charset1::get_size_for_ranges (subset_charset_ranges.length); else - size_ranges = Charset2::min_size + Charset2_Range::static_size * subset_charset_ranges.length; + size_ranges = Charset2::get_size_for_ranges (subset_charset_ranges.length); if (size0 < size_ranges) subset_charset_format = 0; @@ -478,19 +585,18 @@ struct cff_subset_plan { subset_charset_format = 1; else subset_charset_format = 2; + + return true; } bool collect_sids_in_dicts (const OT::cff1::accelerator_subset_t &acc) { - sidmap.reset (); - for (unsigned int i = 0; i < name_dict_values_t::ValCount; i++) { unsigned int sid = acc.topDict.nameSIDs[i]; if (sid != CFF_UNDEF_SID) { - (void)sidmap.add (sid); - topDictModSIDs[i] = sidmap[sid]; + topDictModSIDs[i] = sidmap.add (sid); } } @@ -514,19 +620,24 @@ struct cff_subset_plan { drop_hints = plan->flags & HB_SUBSET_FLAGS_NO_HINTING; desubroutinize = plan->flags & HB_SUBSET_FLAGS_DESUBROUTINIZE; - /* check whether the subset renumbers any glyph IDs */ - gid_renum = false; - for (hb_codepoint_t new_glyph = 0; new_glyph < plan->num_output_glyphs (); new_glyph++) - { - if (!plan->old_gid_for_new_gid(new_glyph, &old_glyph)) - continue; - if (new_glyph != old_glyph) { - gid_renum = true; - break; + #ifdef HB_EXPERIMENTAL_API + min_charstrings_off_size = (plan->flags & HB_SUBSET_FLAGS_IFTB_REQUIREMENTS) ? 4 : 0; + #else + min_charstrings_off_size = 0; + #endif + + subset_charset = !acc.is_predef_charset (); + if (!subset_charset) + /* check whether the subset renumbers any glyph IDs */ + for (const auto &_ : plan->new_to_old_gid_list) + { + if (_.first != _.second) + { + subset_charset = true; + break; + } } - } - subset_charset = gid_renum || !acc.is_predef_charset (); subset_encoding = !acc.is_CID() && !acc.is_predef_encoding (); /* top dict INDEX */ @@ -568,7 +679,8 @@ struct cff_subset_plan { if (unlikely (sidmap.get_population () > 0x8000)) /* assumption: a dict won't reference that many strings */ return false; - if (subset_charset) plan_subset_charset (acc, plan); + if (subset_charset && !plan_subset_charset (acc, plan)) + return false; topdict_mod.reassignSIDs (sidmap); } @@ -632,8 +744,9 @@ struct cff_subset_plan { ; } - return ((subset_charstrings.length == plan->num_output_glyphs ()) - && (fontdicts_mod.length == subset_fdcount)); + return !plan->in_error () && + (subset_charstrings.length == plan->num_output_glyphs ()) && + (fontdicts_mod.length == subset_fdcount); } cff1_top_dict_values_mod_t topdict_mod; @@ -671,25 +784,53 @@ struct cff_subset_plan { unsigned int topDictModSIDs[name_dict_values_t::ValCount]; bool desubroutinize = false; + + unsigned min_charstrings_off_size = 0; }; +} // namespace OT -static bool _serialize_cff1 (hb_serialize_context_t *c, - cff_subset_plan &plan, - const OT::cff1::accelerator_subset_t &acc, - unsigned int num_glyphs) +static bool _serialize_cff1_charstrings (hb_serialize_context_t *c, + struct OT::cff1_subset_plan &plan, + const OT::cff1::accelerator_subset_t &acc) { + c->push<CFF1CharStrings> (); + + unsigned data_size = 0; + unsigned total_size = CFF1CharStrings::total_size (plan.subset_charstrings, &data_size, plan.min_charstrings_off_size); + if (unlikely (!c->start_zerocopy (total_size))) + return false; + + auto *cs = c->start_embed<CFF1CharStrings> (); + if (unlikely (!cs->serialize (c, plan.subset_charstrings, &data_size, plan.min_charstrings_off_size))) { + c->pop_discard (); + return false; + } + + plan.info.char_strings_link = c->pop_pack (false); + return true; +} + +bool +OT::cff1::accelerator_subset_t::serialize (hb_serialize_context_t *c, + struct OT::cff1_subset_plan &plan) const +{ + /* push charstrings onto the object stack first which will ensure it packs as the last + object in the table. Keeping the chastrings last satisfies the requirements for patching + via IFTB. If this ordering needs to be changed in the future, charstrings should be left + at the end whenever HB_SUBSET_FLAGS_ITFB_REQUIREMENTS is enabled. */ + if (!_serialize_cff1_charstrings(c, plan, *this)) + return false; + /* private dicts & local subrs */ - for (int i = (int)acc.privateDicts.length; --i >= 0 ;) + for (int i = (int) privateDicts.length; --i >= 0 ;) { if (plan.fdmap.has (i)) { objidx_t subrs_link = 0; if (plan.subset_localsubrs[i].length > 0) { - CFF1Subrs *dest = c->start_embed <CFF1Subrs> (); - if (unlikely (!dest)) return false; - c->push (); - if (likely (dest && dest->serialize (c, plan.subset_localsubrs[i]))) + auto *dest = c->push <CFF1Subrs> (); + if (likely (dest->serialize (c, plan.subset_localsubrs[i]))) subrs_link = c->pop_pack (); else { @@ -698,12 +839,10 @@ static bool _serialize_cff1 (hb_serialize_context_t *c, } } - PrivateDict *pd = c->start_embed<PrivateDict> (); - if (unlikely (!pd)) return false; - c->push (); - cff_private_dict_op_serializer_t privSzr (plan.desubroutinize, plan.drop_hints); + auto *pd = c->push<PrivateDict> (); + cff1_private_dict_op_serializer_t privSzr (plan.desubroutinize, plan.drop_hints); /* N.B. local subrs immediately follows its corresponding private dict. i.e., subr offset == private dict size */ - if (likely (pd->serialize (c, acc.privateDicts[i], privSzr, subrs_link))) + if (likely (pd->serialize (c, privateDicts[i], privSzr, subrs_link))) { unsigned fd = plan.fdmap[i]; plan.fontdicts_mod[fd].privateDictInfo.size = c->length (); @@ -717,29 +856,13 @@ static bool _serialize_cff1 (hb_serialize_context_t *c, } } - if (!acc.is_CID ()) + if (!is_CID ()) plan.info.privateDictInfo = plan.fontdicts_mod[0].privateDictInfo; - /* CharStrings */ - { - CFF1CharStrings *cs = c->start_embed<CFF1CharStrings> (); - if (unlikely (!cs)) return false; - c->push (); - if (likely (cs->serialize (c, plan.subset_charstrings))) - plan.info.char_strings_link = c->pop_pack (); - else - { - c->pop_discard (); - return false; - } - } - /* FDArray (FD Index) */ - if (acc.fdArray != &Null (CFF1FDArray)) + if (fdArray != &Null (CFF1FDArray)) { - CFF1FDArray *fda = c->start_embed<CFF1FDArray> (); - if (unlikely (!fda)) return false; - c->push (); + auto *fda = c->push<CFF1FDArray> (); cff1_font_dict_op_serializer_t fontSzr; auto it = + hb_zip (+ hb_iter (plan.fontdicts_mod), + hb_iter (plan.fontdicts_mod)); if (likely (fda->serialize (c, it, fontSzr))) @@ -752,10 +875,10 @@ static bool _serialize_cff1 (hb_serialize_context_t *c, } /* FDSelect */ - if (acc.fdSelect != &Null (CFF1FDSelect)) + if (fdSelect != &Null (CFF1FDSelect)) { c->push (); - if (likely (hb_serialize_cff_fdselect (c, num_glyphs, *acc.fdSelect, acc.fdCount, + if (likely (hb_serialize_cff_fdselect (c, plan.num_glyphs, *fdSelect, fdCount, plan.subset_fdselect_format, plan.info.fd_select.size, plan.subset_fdselect_ranges))) plan.info.fd_select.link = c->pop_pack (); @@ -769,9 +892,7 @@ static bool _serialize_cff1 (hb_serialize_context_t *c, /* Charset */ if (plan.subset_charset) { - Charset *dest = c->start_embed<Charset> (); - if (unlikely (!dest)) return false; - c->push (); + auto *dest = c->push<Charset> (); if (likely (dest->serialize (c, plan.subset_charset_format, plan.num_glyphs, @@ -787,9 +908,7 @@ static bool _serialize_cff1 (hb_serialize_context_t *c, /* Encoding */ if (plan.subset_encoding) { - Encoding *dest = c->start_embed<Encoding> (); - if (unlikely (!dest)) return false; - c->push (); + auto *dest = c->push<Encoding> (); if (likely (dest->serialize (c, plan.subset_enc_format, plan.subset_enc_num_codes, @@ -805,11 +924,9 @@ static bool _serialize_cff1 (hb_serialize_context_t *c, /* global subrs */ { - c->push (); - CFF1Subrs *dest = c->start_embed <CFF1Subrs> (); - if (unlikely (!dest)) return false; + auto *dest = c->push <CFF1Subrs> (); if (likely (dest->serialize (c, plan.subset_globalsubrs))) - c->pop_pack (); + c->pop_pack (false); else { c->pop_discard (); @@ -819,10 +936,9 @@ static bool _serialize_cff1 (hb_serialize_context_t *c, /* String INDEX */ { - CFF1StringIndex *dest = c->start_embed<CFF1StringIndex> (); - if (unlikely (!dest)) return false; - c->push (); - if (likely (dest->serialize (c, *acc.stringIndex, plan.sidmap))) + auto *dest = c->push<CFF1StringIndex> (); + if (likely (!plan.sidmap.in_error () && + dest->serialize (c, *stringIndex, plan.sidmap.vector))) c->pop_pack (); else { @@ -842,14 +958,12 @@ static bool _serialize_cff1 (hb_serialize_context_t *c, cff->offSize = 4; /* unused? */ /* name INDEX */ - if (unlikely (!(*acc.nameIndex).copy (c))) return false; + if (unlikely (!c->embed (*nameIndex))) return false; /* top dict INDEX */ { /* serialize singleton TopDict */ - TopDict *top = c->start_embed<TopDict> (); - if (!top) return false; - c->push (); + auto *top = c->push<TopDict> (); cff1_top_dict_op_serializer_t topSzr; unsigned top_size = 0; top_dict_modifiers_t modifier (plan.info, plan.topDictModSIDs); @@ -864,36 +978,23 @@ static bool _serialize_cff1 (hb_serialize_context_t *c, return false; } /* serialize INDEX header for above */ - CFF1Index *dest = c->start_embed<CFF1Index> (); - if (!dest) return false; - return dest->serialize_header (c, hb_iter (hb_array_t<unsigned> (&top_size, 1))); + auto *dest = c->start_embed<CFF1Index> (); + return dest->serialize_header (c, hb_iter (&top_size, 1), top_size); } } -static bool -_hb_subset_cff1 (const OT::cff1::accelerator_subset_t &acc, - hb_subset_context_t *c) +bool +OT::cff1::accelerator_subset_t::subset (hb_subset_context_t *c) const { - cff_subset_plan cff_plan; + cff1_subset_plan cff_plan; - if (unlikely (!cff_plan.create (acc, c->plan))) + if (unlikely (!cff_plan.create (*this, c->plan))) { DEBUG_MSG(SUBSET, nullptr, "Failed to generate a cff subsetting plan."); return false; } - return _serialize_cff1 (c->serializer, cff_plan, acc, c->plan->num_output_glyphs ()); -} - -bool -hb_subset_cff1 (hb_subset_context_t *c) -{ - OT::cff1::accelerator_subset_t acc; - acc.init (c->plan->source); - bool result = likely (acc.is_valid ()) && _hb_subset_cff1 (acc, c); - acc.fini (); - - return result; + return serialize (c->serializer, cff_plan); } |