From ebb64b50da52b40ff19e5ea6ad39114ca1c684e2 Mon Sep 17 00:00:00 2001 From: Garret Rieger Date: Thu, 21 Jul 2022 18:36:20 +0000 Subject: [PATCH] [repacker] size buffer correctly. --- src/graph/gsubgpos-graph.hh | 74 ++++++++++++++++++++++--------------- src/hb-repacker.hh | 24 ++++++++++-- 2 files changed, 66 insertions(+), 32 deletions(-) diff --git a/src/graph/gsubgpos-graph.hh b/src/graph/gsubgpos-graph.hh index 3a3b4c333..27a1e5cb6 100644 --- a/src/graph/gsubgpos-graph.hh +++ b/src/graph/gsubgpos-graph.hh @@ -33,8 +33,15 @@ namespace graph { +struct Lookup; + struct GSTAR : public OT::GSUBGPOS { + static GSTAR* graph_to_gstar (graph_t& graph) + { + return (GSTAR*) graph.root ().obj.head; + } + const void* get_lookup_list_field_offset () const { switch (u.version.major) { @@ -46,18 +53,38 @@ struct GSTAR : public OT::GSUBGPOS } } + void find_lookups (graph_t& graph, + hb_hashmap_t& lookups /* OUT */) + { + // TODO: template on types, based on gstar version. + unsigned lookup_list_idx = graph.index_for_offset (graph.root_idx (), + get_lookup_list_field_offset()); + + const OT::LookupList* lookupList = + (const OT::LookupList*) graph.object (lookup_list_idx).head; + + for (unsigned i = 0; i < lookupList->len; i++) + { + unsigned lookup_idx = graph.index_for_offset (lookup_list_idx, &(lookupList->arrayZ[i])); + Lookup* lookup = (Lookup*) graph.object (lookup_idx).head; + lookups.set (lookup_idx, lookup); + } +} + + + }; struct Lookup : public OT::Lookup { - unsigned extension_type (hb_tag_t table_tag) + unsigned number_of_subtables () const { - switch (table_tag) - { - case HB_OT_TAG_GPOS: return 9; - case HB_OT_TAG_GSUB: return 7; - default: return 0; - } + return subTable.len; + } + + bool is_extension (hb_tag_t table_tag) const + { + return lookupType == extension_type (table_tag); } bool make_extension (hb_tag_t table_tag, @@ -66,9 +93,9 @@ struct Lookup : public OT::Lookup hb_vector_t& buffer) { // TODO: use a context_t? - unsigned ext_type = extension_type (table_tag); unsigned type = lookupType; - if (!ext_type || type == ext_type) + unsigned ext_type = extension_type (table_tag); + if (!ext_type || is_extension (table_tag)) { // NOOP printf("Already extension (obj %u).\n", this_index); @@ -151,29 +178,18 @@ struct Lookup : public OT::Lookup return true; } -}; -static inline void -find_lookups (graph_t& graph, - hb_hashmap_t& lookups /* OUT */) -{ - // TODO: move this into GSTAR? - // TODO: template on types, based on gstar version. - const GSTAR* gstar = (const GSTAR*) graph.root ().obj.head; - - unsigned lookup_list_idx = graph.index_for_offset (graph.root_idx (), - gstar->get_lookup_list_field_offset()); - - const OT::LookupList* lookupList = - (const OT::LookupList*) graph.object (lookup_list_idx).head; - - for (unsigned i = 0; i < lookupList->len; i++) + private: + unsigned extension_type (hb_tag_t table_tag) const { - unsigned lookup_idx = graph.index_for_offset (lookup_list_idx, &(lookupList->arrayZ[i])); - Lookup* lookup = (Lookup*) graph.object (lookup_idx).head; - lookups.set (lookup_idx, lookup); + switch (table_tag) + { + case HB_OT_TAG_GPOS: return 9; + case HB_OT_TAG_GSUB: return 7; + default: return 0; + } } -} +}; } diff --git a/src/hb-repacker.hh b/src/hb-repacker.hh index 041b5260d..545da7ac2 100644 --- a/src/hb-repacker.hh +++ b/src/hb-repacker.hh @@ -43,12 +43,32 @@ using graph::graph_t; * docs/repacker.md */ +static inline +unsigned _num_non_ext_subtables (hb_tag_t table_tag, + const hb_hashmap_t& lookups) +{ + unsigned count = 0; + for (auto l : lookups.values ()) + { + if (l->is_extension (table_tag)) continue; + count += l->number_of_subtables (); + } + return count; +} + + static inline bool _make_extensions (hb_tag_t table_tag, graph_t& sorted_graph, hb_vector_t& buffer) { // TODO: Move this into graph or gsubgpos graph? + graph::GSTAR* gstar = graph::GSTAR::graph_to_gstar (sorted_graph); hb_hashmap_t lookups; - find_lookups (sorted_graph, lookups); + gstar->find_lookups (sorted_graph, lookups); + + unsigned extension_size = OT::ExtensionFormat1::static_size; + if (!buffer.alloc (_num_non_ext_subtables (table_tag, lookups) * extension_size)) + return false; + for (auto p : lookups.iter ()) { @@ -187,8 +207,6 @@ hb_resolve_overflows (const T& packed, } hb_vector_t extension_buffer; - if (!extension_buffer.alloc(100000)) // TODO: cleanup - return nullptr; if ((table_tag == HB_OT_TAG_GPOS || table_tag == HB_OT_TAG_GSUB) && will_overflow)