From 5cf2a25a609a7401b0799b52a972dd10af245aad Mon Sep 17 00:00:00 2001 From: Garret Rieger Date: Mon, 15 Aug 2022 22:49:24 +0000 Subject: [PATCH] [repacker] Expose on internal method in the repacker that allows the caller to pass in/out a graph. Will be used in testing so we can compare graphs instead of packed result. --- src/graph/graph.hh | 11 +++++- src/graph/gsubgpos-context.cc | 5 ++- src/graph/gsubgpos-context.hh | 10 ++---- src/hb-repacker.hh | 67 ++++++++++++++++++++--------------- 4 files changed, 53 insertions(+), 40 deletions(-) diff --git a/src/graph/graph.hh b/src/graph/graph.hh index 5f2341420..0d3dae2c0 100644 --- a/src/graph/graph.hh +++ b/src/graph/graph.hh @@ -196,7 +196,8 @@ struct graph_t : parents_invalid (true), distance_invalid (true), positions_invalid (true), - successful (true) + successful (true), + buffers () { num_roots_for_space_.push (1); bool removed_nil = false; @@ -228,6 +229,8 @@ struct graph_t ~graph_t () { vertices_.fini (); + for (char* b : buffers) + hb_free (b); } bool in_error () const @@ -255,6 +258,11 @@ struct graph_t return vertices_[i].obj; } + void add_buffer (char* buffer) + { + buffers.push (buffer); + } + /* * Adds a 16 bit link from parent_id to child_id */ @@ -1127,6 +1135,7 @@ struct graph_t bool positions_invalid; bool successful; hb_vector_t num_roots_for_space_; + hb_vector_t buffers; }; } diff --git a/src/graph/gsubgpos-context.cc b/src/graph/gsubgpos-context.cc index e0ff6ff85..b2044426d 100644 --- a/src/graph/gsubgpos-context.cc +++ b/src/graph/gsubgpos-context.cc @@ -33,8 +33,7 @@ gsubgpos_graph_context_t::gsubgpos_graph_context_t (hb_tag_t table_tag_, : table_tag (table_tag_), graph (graph_), lookup_list_index (0), - lookups (), - buffers () + lookups () { if (table_tag_ != HB_OT_TAG_GPOS && table_tag_ != HB_OT_TAG_GSUB) @@ -53,7 +52,7 @@ unsigned gsubgpos_graph_context_t::create_node (unsigned size) if (!buffer) return -1; - buffers.push (buffer); + add_buffer (buffer); return graph.new_node (buffer, buffer + size); } diff --git a/src/graph/gsubgpos-context.hh b/src/graph/gsubgpos-context.hh index 49b24198f..9fe9662e6 100644 --- a/src/graph/gsubgpos-context.hh +++ b/src/graph/gsubgpos-context.hh @@ -40,22 +40,16 @@ struct gsubgpos_graph_context_t graph_t& graph; unsigned lookup_list_index; hb_hashmap_t lookups; - hb_vector_t buffers; + HB_INTERNAL gsubgpos_graph_context_t (hb_tag_t table_tag_, graph_t& graph_); - ~gsubgpos_graph_context_t () - { - for (char* b : buffers) - hb_free (b); - } - HB_INTERNAL unsigned create_node (unsigned size); void add_buffer (char* buffer) { - buffers.push (buffer); + graph.add_buffer (buffer); } private: diff --git a/src/hb-repacker.hh b/src/hb-repacker.hh index 61b142238..48a3fe456 100644 --- a/src/hb-repacker.hh +++ b/src/hb-repacker.hh @@ -276,35 +276,20 @@ bool _process_overflows (const hb_vector_t& overflows, return resolution_attempted; } -/* - * Attempts to modify the topological sorting of the provided object graph to - * eliminate offset overflows in the links between objects of the graph. If a - * non-overflowing ordering is found the updated graph is serialized it into the - * provided serialization context. - * - * If necessary the structure of the graph may be modified in ways that do not - * affect the functionality of the graph. For example shared objects may be - * duplicated. - * - * For a detailed writeup describing how the algorithm operates see: - * docs/repacker.md - */ -template -inline hb_blob_t* -hb_resolve_overflows (const T& packed, - hb_tag_t table_tag, - unsigned max_rounds = 20, - bool recalculate_extensions = false) { - graph_t sorted_graph (packed); +inline bool +hb_resolve_graph_overflows (hb_tag_t table_tag, + unsigned max_rounds , + bool recalculate_extensions, + graph_t& sorted_graph /* IN/OUT */) +{ sorted_graph.sort_shortest_distance (); bool will_overflow = graph::will_overflow (sorted_graph); if (!will_overflow) - { - return graph::serialize (sorted_graph); - } + return true; - graph::gsubgpos_graph_context_t ext_context (table_tag, sorted_graph); + // TODO attach to graph? or just move buffers to the graph? + graph::gsubgpos_graph_context_t ext_context (table_tag, sorted_graph); // TODO lifetime if ((table_tag == HB_OT_TAG_GPOS || table_tag == HB_OT_TAG_GSUB) && will_overflow) @@ -314,13 +299,13 @@ hb_resolve_overflows (const T& packed, DEBUG_MSG (SUBSET_REPACK, nullptr, "Splitting subtables if needed."); if (!_presplit_subtables_if_needed (ext_context)) { DEBUG_MSG (SUBSET_REPACK, nullptr, "Subtable splitting failed."); - return nullptr; + return false; } DEBUG_MSG (SUBSET_REPACK, nullptr, "Promoting lookups to extensions if needed."); if (!_promote_extensions_if_needed (ext_context)) { DEBUG_MSG (SUBSET_REPACK, nullptr, "Extensions promotion failed."); - return nullptr; + return false; } } @@ -360,15 +345,41 @@ hb_resolve_overflows (const T& packed, if (sorted_graph.in_error ()) { DEBUG_MSG (SUBSET_REPACK, nullptr, "Sorted graph in error state."); - return nullptr; + return false; } if (graph::will_overflow (sorted_graph)) { DEBUG_MSG (SUBSET_REPACK, nullptr, "Offset overflow resolution failed."); - return nullptr; + return false; } + return true; +} + +/* + * Attempts to modify the topological sorting of the provided object graph to + * eliminate offset overflows in the links between objects of the graph. If a + * non-overflowing ordering is found the updated graph is serialized it into the + * provided serialization context. + * + * If necessary the structure of the graph may be modified in ways that do not + * affect the functionality of the graph. For example shared objects may be + * duplicated. + * + * For a detailed writeup describing how the algorithm operates see: + * docs/repacker.md + */ +template +inline hb_blob_t* +hb_resolve_overflows (const T& packed, + hb_tag_t table_tag, + unsigned max_rounds = 20, + bool recalculate_extensions = false) { + graph_t sorted_graph (packed); + if (!hb_resolve_graph_overflows (table_tag, max_rounds, recalculate_extensions, sorted_graph)) + return nullptr; + return graph::serialize (sorted_graph); }