From 48b68370743264f900457e4b463e9ced5325ceae Mon Sep 17 00:00:00 2001 From: Garret Rieger Date: Wed, 23 Nov 2022 20:51:51 +0000 Subject: [PATCH 1/7] [subset] add a CFF specific accelerator object. This allows CFF specific accelerator structures to be isolated to the CFF code. --- src/hb-subset-accelerator.hh | 12 +++++++++++- src/hb-subset-cff-common.hh | 22 ++++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/hb-subset-accelerator.hh b/src/hb-subset-accelerator.hh index ecf751748..1caf93c7f 100644 --- a/src/hb-subset-accelerator.hh +++ b/src/hb-subset-accelerator.hh @@ -35,6 +35,10 @@ extern HB_INTERNAL hb_user_data_key_t _hb_subset_accelerator_user_data_key; +namespace CFF { +struct cff_subset_accelerator_t; +} + struct hb_subset_accelerator_t { static hb_user_data_key_t* user_data_key() @@ -62,11 +66,17 @@ struct hb_subset_accelerator_t hb_subset_accelerator_t(const hb_map_t& unicode_to_gid_, const hb_set_t& unicodes_) - : unicode_to_gid(unicode_to_gid_), unicodes(unicodes_) {} + : unicode_to_gid(unicode_to_gid_), unicodes(unicodes_), + has_seac(false), cff_accelerator(nullptr) {} + // Generic const hb_map_t unicode_to_gid; const hb_set_t unicodes; + + // CFF bool has_seac; + CFF::cff_subset_accelerator_t* cff_accelerator; + // TODO(garretrieger): cumulative glyf checksum map // TODO(garretrieger): sanitized table cache. diff --git a/src/hb-subset-cff-common.hh b/src/hb-subset-cff-common.hh index 21fd6f899..78b75d17f 100644 --- a/src/hb-subset-cff-common.hh +++ b/src/hb-subset-cff-common.hh @@ -402,6 +402,28 @@ struct parsed_cs_str_vec_t : hb_vector_t typedef hb_vector_t SUPER; }; +struct cff_subset_accelerator_t +{ + static cff_subset_accelerator_t* create() { + cff_subset_accelerator_t* accel = + (cff_subset_accelerator_t*) hb_malloc (sizeof(cff_subset_accelerator_t)); + new (accel) cff_subset_accelerator_t (); + return accel; + } + + static void destroy(void* value) { + if (!value) return; + + cff_subset_accelerator_t* accel = (cff_subset_accelerator_t*) value; + accel->~cff_subset_accelerator_t (); + hb_free (accel); + } + + parsed_cs_str_t parsed_charstring; + parsed_cs_str_vec_t parsed_global_subrs; + parsed_cs_str_vec_t parsed_local_subrs; +}; + struct subr_subset_param_t { subr_subset_param_t (parsed_cs_str_t *parsed_charstring_, From 47c125845caf1c24f538679ffdc32c04b2f0920b Mon Sep 17 00:00:00 2001 From: Garret Rieger Date: Wed, 23 Nov 2022 21:02:39 +0000 Subject: [PATCH 2/7] [subset] Cache parsed charstrings in the cff accelerator. --- src/hb-subset-cff-common.hh | 36 ++++++++++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/src/hb-subset-cff-common.hh b/src/hb-subset-cff-common.hh index 78b75d17f..f77010b27 100644 --- a/src/hb-subset-cff-common.hh +++ b/src/hb-subset-cff-common.hh @@ -404,10 +404,15 @@ struct parsed_cs_str_vec_t : hb_vector_t struct cff_subset_accelerator_t { - static cff_subset_accelerator_t* create() { + static cff_subset_accelerator_t* create( + const parsed_cs_str_vec_t& parsed_charstrings, + const parsed_cs_str_vec_t& parsed_global_subrs, + const hb_vector_t& parsed_local_subrs) { cff_subset_accelerator_t* accel = (cff_subset_accelerator_t*) hb_malloc (sizeof(cff_subset_accelerator_t)); - new (accel) cff_subset_accelerator_t (); + new (accel) cff_subset_accelerator_t (parsed_charstrings, + parsed_global_subrs, + parsed_local_subrs); return accel; } @@ -419,9 +424,20 @@ struct cff_subset_accelerator_t hb_free (accel); } - parsed_cs_str_t parsed_charstring; + cff_subset_accelerator_t( + const parsed_cs_str_vec_t& parsed_charstrings_, + const parsed_cs_str_vec_t& parsed_global_subrs_, + const hb_vector_t& parsed_local_subrs_) + { + parsed_charstrings = parsed_charstrings_; + parsed_global_subrs = parsed_global_subrs_; + parsed_local_subrs = parsed_local_subrs_; + } + + parsed_cs_str_vec_t parsed_charstrings; parsed_cs_str_vec_t parsed_global_subrs; - parsed_cs_str_vec_t parsed_local_subrs; + hb_vector_t parsed_local_subrs; + }; struct subr_subset_param_t @@ -666,6 +682,7 @@ struct subr_subsetter_t remaps.create (closures); + populate_subset_accelerator(); return true; } @@ -926,6 +943,17 @@ struct subr_subsetter_t return !encoder.is_error (); } + void populate_subset_accelerator() const + { + if (!plan->inprogress_accelerator) return; + + plan->inprogress_accelerator->cff_accelerator = + cff_subset_accelerator_t::create(parsed_charstrings, + parsed_global_subrs, + parsed_local_subrs); + + } + protected: const ACC &acc; const hb_subset_plan_t *plan; From a3afa61ce8d01784d88de4af3647ebd5b3e71fe6 Mon Sep 17 00:00:00 2001 From: Garret Rieger Date: Wed, 23 Nov 2022 22:24:39 +0000 Subject: [PATCH 3/7] [subset] use cached parsed char strings if available. --- src/hb-subset-cff-common.hh | 67 ++++++++++++++++++++++++++++--------- 1 file changed, 51 insertions(+), 16 deletions(-) diff --git a/src/hb-subset-cff-common.hh b/src/hb-subset-cff-common.hh index f77010b27..cd16348e4 100644 --- a/src/hb-subset-cff-common.hh +++ b/src/hb-subset-cff-common.hh @@ -604,17 +604,38 @@ struct subr_subsetter_t if (unlikely (!closures.valid)) return false; + if (plan->accelerator && plan->accelerator->cff_accelerator) { + // Parsed subroutine char stsrings already exist in the accelerator. Copy + // them in. + // TODO(grieger): use reference instead of copy. + parsed_global_subrs = + plan->accelerator->cff_accelerator->parsed_global_subrs; + parsed_local_subrs = + plan->accelerator->cff_accelerator->parsed_local_subrs; + } + /* phase 1 & 2 */ for (unsigned int i = 0; i < plan->num_output_glyphs (); i++) { hb_codepoint_t glyph; if (!plan->old_gid_for_new_gid (i, &glyph)) continue; + const hb_ubytes_t str = (*acc.charStrings)[glyph]; unsigned int fd = acc.fdSelect->get_fd (glyph); if (unlikely (fd >= acc.fdCount)) return false; + if (plan->accelerator && plan->accelerator->cff_accelerator) + { + // parsed string already exists in accelerator, copy it and move + // on. + // TODO(grieger): use reference instead of copy. + parsed_charstrings[i] = + plan->accelerator->cff_accelerator->parsed_charstrings[glyph]; + continue; + } + ENV env (str, acc, fd); cs_interpreter_t interp (env); @@ -662,22 +683,13 @@ struct subr_subsetter_t /* after dropping hints recreate closures of actually used subrs */ closures.reset (); - for (unsigned int i = 0; i < plan->num_output_glyphs (); i++) - { - hb_codepoint_t glyph; - if (!plan->old_gid_for_new_gid (i, &glyph)) - continue; - unsigned int fd = acc.fdSelect->get_fd (glyph); - if (unlikely (fd >= acc.fdCount)) - return false; - subr_subset_param_t param (&parsed_charstrings[i], - &parsed_global_subrs, - &parsed_local_subrs[fd], - &closures.global_closure, - &closures.local_closures[fd], - plan->flags & HB_SUBSET_FLAGS_NO_HINTING); - collect_subr_refs_in_str (parsed_charstrings[i], param); - } + if (!closure_subroutines()) return false; + } else if (plan->accelerator && plan->accelerator->cff_accelerator) { + // Since parsed strings were loaded from accelerator, we still need + // to compute the subroutine closures which would have normally happened during + // parsing. + closures.reset (); + if (!closure_subroutines()) return false; } remaps.create (closures); @@ -866,6 +878,29 @@ struct subr_subsetter_t return seen_hint; } + bool closure_subroutines () + { + closures.reset (); + for (unsigned int i = 0; i < plan->num_output_glyphs (); i++) + { + hb_codepoint_t glyph; + if (!plan->old_gid_for_new_gid (i, &glyph)) + continue; + unsigned int fd = acc.fdSelect->get_fd (glyph); + if (unlikely (fd >= acc.fdCount)) + return false; + subr_subset_param_t param (&parsed_charstrings[i], + &parsed_global_subrs, + &parsed_local_subrs[fd], + &closures.global_closure, + &closures.local_closures[fd], + plan->flags & HB_SUBSET_FLAGS_NO_HINTING); + collect_subr_refs_in_str (parsed_charstrings[i], param); + } + + return true; + } + void collect_subr_refs_in_subr (parsed_cs_str_t &str, unsigned int pos, unsigned int subr_num, parsed_cs_str_vec_t &subrs, hb_set_t *closure, From 4ff09274a86102a69c6e7abebc59d694bc90bbcd Mon Sep 17 00:00:00 2001 From: Garret Rieger Date: Thu, 24 Nov 2022 22:47:29 +0000 Subject: [PATCH 4/7] [subset] In CFF accelerator keep a reference to original face. The charstring objects reference memory from the original face so we need to maintain a reference to prevent it from being destroyed. --- src/hb-subset-cff-common.hh | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/hb-subset-cff-common.hh b/src/hb-subset-cff-common.hh index cd16348e4..44e4ee4c9 100644 --- a/src/hb-subset-cff-common.hh +++ b/src/hb-subset-cff-common.hh @@ -405,12 +405,14 @@ struct parsed_cs_str_vec_t : hb_vector_t struct cff_subset_accelerator_t { static cff_subset_accelerator_t* create( + hb_face_t* original_face, const parsed_cs_str_vec_t& parsed_charstrings, const parsed_cs_str_vec_t& parsed_global_subrs, const hb_vector_t& parsed_local_subrs) { cff_subset_accelerator_t* accel = (cff_subset_accelerator_t*) hb_malloc (sizeof(cff_subset_accelerator_t)); - new (accel) cff_subset_accelerator_t (parsed_charstrings, + new (accel) cff_subset_accelerator_t (original_face, + parsed_charstrings, parsed_global_subrs, parsed_local_subrs); return accel; @@ -425,19 +427,29 @@ struct cff_subset_accelerator_t } cff_subset_accelerator_t( + hb_face_t* original_face_, const parsed_cs_str_vec_t& parsed_charstrings_, const parsed_cs_str_vec_t& parsed_global_subrs_, const hb_vector_t& parsed_local_subrs_) { + // the parsed charstrings point to memory in the original face so we must hold a reference + // to it to keep the memory valid. + original_face = hb_face_reference (original_face_); parsed_charstrings = parsed_charstrings_; parsed_global_subrs = parsed_global_subrs_; parsed_local_subrs = parsed_local_subrs_; } + ~cff_subset_accelerator_t() { + hb_face_destroy (original_face); + } + parsed_cs_str_vec_t parsed_charstrings; parsed_cs_str_vec_t parsed_global_subrs; hb_vector_t parsed_local_subrs; + private: + hb_face_t* original_face; }; struct subr_subset_param_t @@ -983,7 +995,8 @@ struct subr_subsetter_t if (!plan->inprogress_accelerator) return; plan->inprogress_accelerator->cff_accelerator = - cff_subset_accelerator_t::create(parsed_charstrings, + cff_subset_accelerator_t::create(plan->source, + parsed_charstrings, parsed_global_subrs, parsed_local_subrs); From 71c23c1c079cbd992ee3c9e92435ee2b1374c227 Mon Sep 17 00:00:00 2001 From: Garret Rieger Date: Fri, 25 Nov 2022 18:04:44 +0000 Subject: [PATCH 5/7] [subset] don't copy the entire global/loca subr lists from the accelerator. Instead run a closure on the retained charstrings and copy only the referenced subrs. This significantly speeds up cases with small character sets. --- src/hb-subset-cff-common.hh | 80 ++++++++++++++++++++++++------------- 1 file changed, 53 insertions(+), 27 deletions(-) diff --git a/src/hb-subset-cff-common.hh b/src/hb-subset-cff-common.hh index 44e4ee4c9..8b14c88b8 100644 --- a/src/hb-subset-cff-common.hh +++ b/src/hb-subset-cff-common.hh @@ -606,25 +606,27 @@ struct subr_subsetter_t return false; } - if (unlikely (!parsed_local_subrs.resize (acc.fdCount))) return false; + unsigned fd_count = acc.fdCount; + cff_subset_accelerator_t* cff_accelerator = nullptr; + if (plan->accelerator && plan->accelerator->cff_accelerator) { + cff_accelerator = plan->accelerator->cff_accelerator; + fd_count = cff_accelerator->parsed_local_subrs.length; + } + + + if (unlikely (!parsed_local_subrs.resize (fd_count))) return false; for (unsigned int i = 0; i < acc.fdCount; i++) { - parsed_local_subrs[i].resize (acc.privateDicts[i].localSubrs->count); + unsigned count = cff_accelerator + ? cff_accelerator->parsed_local_subrs[i].length + : acc.privateDicts[i].localSubrs->count; + parsed_local_subrs[i].resize (count); if (unlikely (parsed_local_subrs[i].in_error ())) return false; } if (unlikely (!closures.valid)) return false; - if (plan->accelerator && plan->accelerator->cff_accelerator) { - // Parsed subroutine char stsrings already exist in the accelerator. Copy - // them in. - // TODO(grieger): use reference instead of copy. - parsed_global_subrs = - plan->accelerator->cff_accelerator->parsed_global_subrs; - parsed_local_subrs = - plan->accelerator->cff_accelerator->parsed_local_subrs; - } /* phase 1 & 2 */ for (unsigned int i = 0; i < plan->num_output_glyphs (); i++) @@ -638,13 +640,12 @@ struct subr_subsetter_t if (unlikely (fd >= acc.fdCount)) return false; - if (plan->accelerator && plan->accelerator->cff_accelerator) + if (cff_accelerator) { // parsed string already exists in accelerator, copy it and move // on. - // TODO(grieger): use reference instead of copy. parsed_charstrings[i] = - plan->accelerator->cff_accelerator->parsed_charstrings[glyph]; + cff_accelerator->parsed_charstrings[glyph]; continue; } @@ -666,6 +667,14 @@ struct subr_subsetter_t SUBSETTER::complete_parsed_str (interp.env, param, parsed_charstrings[i]); } + // Since parsed strings were loaded from accelerator, we still need + // to compute the subroutine closures which would have normally happened during + // parsing. + if (cff_accelerator && + !closure_and_copy_subroutines(cff_accelerator->parsed_global_subrs, + cff_accelerator->parsed_local_subrs)) + return false; + if (plan->flags & HB_SUBSET_FLAGS_NO_HINTING) { /* mark hint ops and arguments for drop */ @@ -694,14 +703,7 @@ struct subr_subsetter_t } /* after dropping hints recreate closures of actually used subrs */ - closures.reset (); - if (!closure_subroutines()) return false; - } else if (plan->accelerator && plan->accelerator->cff_accelerator) { - // Since parsed strings were loaded from accelerator, we still need - // to compute the subroutine closures which would have normally happened during - // parsing. - closures.reset (); - if (!closure_subroutines()) return false; + if (!closure_subroutines(parsed_global_subrs, parsed_local_subrs)) return false; } remaps.create (closures); @@ -890,7 +892,31 @@ struct subr_subsetter_t return seen_hint; } - bool closure_subroutines () + bool closure_and_copy_subroutines (parsed_cs_str_vec_t& global_subrs, + hb_vector_t& local_subrs) + { + if (!closure_subroutines(global_subrs, + local_subrs)) return false; + + + for (unsigned s : closures.global_closure) { + parsed_global_subrs[s] = global_subrs[s]; + } + + unsigned fd = 0; + for (const hb_set_t& c : closures.local_closures) { + for (unsigned s : c) { + parsed_local_subrs[fd][s] = local_subrs[fd][s]; + } + fd++; + } + + return true; + } + + + bool closure_subroutines (parsed_cs_str_vec_t& global_subrs, + hb_vector_t& local_subrs) { closures.reset (); for (unsigned int i = 0; i < plan->num_output_glyphs (); i++) @@ -902,8 +928,8 @@ struct subr_subsetter_t if (unlikely (fd >= acc.fdCount)) return false; subr_subset_param_t param (&parsed_charstrings[i], - &parsed_global_subrs, - &parsed_local_subrs[fd], + &global_subrs, + &local_subrs[fd], &closures.global_closure, &closures.local_closures[fd], plan->flags & HB_SUBSET_FLAGS_NO_HINTING); @@ -913,7 +939,7 @@ struct subr_subsetter_t return true; } - void collect_subr_refs_in_subr (parsed_cs_str_t &str, unsigned int pos, + void collect_subr_refs_in_subr (const parsed_cs_str_t &str, unsigned int pos, unsigned int subr_num, parsed_cs_str_vec_t &subrs, hb_set_t *closure, const subr_subset_param_t ¶m) @@ -924,7 +950,7 @@ struct subr_subsetter_t collect_subr_refs_in_str (subrs[subr_num], param); } - void collect_subr_refs_in_str (parsed_cs_str_t &str, const subr_subset_param_t ¶m) + void collect_subr_refs_in_str (const parsed_cs_str_t &str, const subr_subset_param_t ¶m) { for (unsigned int pos = 0; pos < str.values.length; pos++) { From 75a99f28abbb6d82e51f49dcda95c0d61b225e98 Mon Sep 17 00:00:00 2001 From: Garret Rieger Date: Fri, 25 Nov 2022 18:38:13 +0000 Subject: [PATCH 6/7] [subset] destruct cff accelerator if present. --- src/hb-subset-accelerator.hh | 7 ++++++- src/hb-subset-cff-common.hh | 6 ++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/hb-subset-accelerator.hh b/src/hb-subset-accelerator.hh index 1caf93c7f..53fea0e77 100644 --- a/src/hb-subset-accelerator.hh +++ b/src/hb-subset-accelerator.hh @@ -60,6 +60,10 @@ struct hb_subset_accelerator_t if (!value) return; hb_subset_accelerator_t* accel = (hb_subset_accelerator_t*) value; + + if (accel->cff_accelerator && accel->destroy_cff_accelerator) + accel->destroy_cff_accelerator ((void*) accel->cff_accelerator); + accel->~hb_subset_accelerator_t (); hb_free (accel); } @@ -67,7 +71,7 @@ struct hb_subset_accelerator_t hb_subset_accelerator_t(const hb_map_t& unicode_to_gid_, const hb_set_t& unicodes_) : unicode_to_gid(unicode_to_gid_), unicodes(unicodes_), - has_seac(false), cff_accelerator(nullptr) {} + has_seac(false), cff_accelerator(nullptr), destroy_cff_accelerator(nullptr) {} // Generic const hb_map_t unicode_to_gid; @@ -76,6 +80,7 @@ struct hb_subset_accelerator_t // CFF bool has_seac; CFF::cff_subset_accelerator_t* cff_accelerator; + hb_destroy_func_t destroy_cff_accelerator; // TODO(garretrieger): cumulative glyf checksum map // TODO(garretrieger): sanitized table cache. diff --git a/src/hb-subset-cff-common.hh b/src/hb-subset-cff-common.hh index 8b14c88b8..0286c7ff4 100644 --- a/src/hb-subset-cff-common.hh +++ b/src/hb-subset-cff-common.hh @@ -404,7 +404,7 @@ struct parsed_cs_str_vec_t : hb_vector_t struct cff_subset_accelerator_t { - static cff_subset_accelerator_t* create( + static cff_subset_accelerator_t* create ( hb_face_t* original_face, const parsed_cs_str_vec_t& parsed_charstrings, const parsed_cs_str_vec_t& parsed_global_subrs, @@ -418,7 +418,7 @@ struct cff_subset_accelerator_t return accel; } - static void destroy(void* value) { + static void destroy (void* value) { if (!value) return; cff_subset_accelerator_t* accel = (cff_subset_accelerator_t*) value; @@ -1025,6 +1025,8 @@ struct subr_subsetter_t parsed_charstrings, parsed_global_subrs, parsed_local_subrs); + plan->inprogress_accelerator->destroy_cff_accelerator = + cff_subset_accelerator_t::destroy; } From 8d5c899b0ff43b4b8aeb767623627cf55168c8fb Mon Sep 17 00:00:00 2001 From: Garret Rieger Date: Fri, 25 Nov 2022 20:33:39 +0000 Subject: [PATCH 7/7] [subset] In cff accelerator hold reference to CFF table instead of the whole font. --- src/hb-ot-cff1-table.hh | 2 +- src/hb-ot-cff2-table.hh | 2 +- src/hb-subset-cff-common.hh | 19 ++++++++++--------- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/hb-ot-cff1-table.hh b/src/hb-ot-cff1-table.hh index 1d39ffe55..54ef270bc 100644 --- a/src/hb-ot-cff1-table.hh +++ b/src/hb-ot-cff1-table.hh @@ -1295,10 +1295,10 @@ struct cff1 } protected: - hb_blob_t *blob = nullptr; hb_sanitize_context_t sc; public: + hb_blob_t *blob = nullptr; const Encoding *encoding = nullptr; const Charset *charset = nullptr; const CFF1NameIndex *nameIndex = nullptr; diff --git a/src/hb-ot-cff2-table.hh b/src/hb-ot-cff2-table.hh index 474ebb0fb..e84709fa7 100644 --- a/src/hb-ot-cff2-table.hh +++ b/src/hb-ot-cff2-table.hh @@ -486,10 +486,10 @@ struct cff2 bool is_valid () const { return blob; } protected: - hb_blob_t *blob = nullptr; hb_sanitize_context_t sc; public: + hb_blob_t *blob = nullptr; cff2_top_dict_values_t topDict; const CFF2Subrs *globalSubrs = nullptr; const CFF2VariationStore *varStore = nullptr; diff --git a/src/hb-subset-cff-common.hh b/src/hb-subset-cff-common.hh index 0286c7ff4..f41e6589d 100644 --- a/src/hb-subset-cff-common.hh +++ b/src/hb-subset-cff-common.hh @@ -405,13 +405,13 @@ struct parsed_cs_str_vec_t : hb_vector_t struct cff_subset_accelerator_t { static cff_subset_accelerator_t* create ( - hb_face_t* original_face, + hb_blob_t* original_blob, const parsed_cs_str_vec_t& parsed_charstrings, const parsed_cs_str_vec_t& parsed_global_subrs, const hb_vector_t& parsed_local_subrs) { cff_subset_accelerator_t* accel = (cff_subset_accelerator_t*) hb_malloc (sizeof(cff_subset_accelerator_t)); - new (accel) cff_subset_accelerator_t (original_face, + new (accel) cff_subset_accelerator_t (original_blob, parsed_charstrings, parsed_global_subrs, parsed_local_subrs); @@ -427,21 +427,22 @@ struct cff_subset_accelerator_t } cff_subset_accelerator_t( - hb_face_t* original_face_, + hb_blob_t* original_blob_, const parsed_cs_str_vec_t& parsed_charstrings_, const parsed_cs_str_vec_t& parsed_global_subrs_, const hb_vector_t& parsed_local_subrs_) { - // the parsed charstrings point to memory in the original face so we must hold a reference - // to it to keep the memory valid. - original_face = hb_face_reference (original_face_); parsed_charstrings = parsed_charstrings_; parsed_global_subrs = parsed_global_subrs_; parsed_local_subrs = parsed_local_subrs_; + + // the parsed charstrings point to memory in the original CFF table so we must hold a reference + // to it to keep the memory valid. + original_blob = hb_blob_reference (original_blob_); } ~cff_subset_accelerator_t() { - hb_face_destroy (original_face); + hb_blob_destroy (original_blob); } parsed_cs_str_vec_t parsed_charstrings; @@ -449,7 +450,7 @@ struct cff_subset_accelerator_t hb_vector_t parsed_local_subrs; private: - hb_face_t* original_face; + hb_blob_t* original_blob; }; struct subr_subset_param_t @@ -1021,7 +1022,7 @@ struct subr_subsetter_t if (!plan->inprogress_accelerator) return; plan->inprogress_accelerator->cff_accelerator = - cff_subset_accelerator_t::create(plan->source, + cff_subset_accelerator_t::create(acc.blob, parsed_charstrings, parsed_global_subrs, parsed_local_subrs);