[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.
diff --git a/src/graph/graph.hh b/src/graph/graph.hh index 5f23414..0d3dae2 100644 --- a/src/graph/graph.hh +++ b/src/graph/graph.hh
@@ -196,7 +196,8 @@ : 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 @@ ~graph_t () { vertices_.fini (); + for (char* b : buffers) + hb_free (b); } bool in_error () const @@ -255,6 +258,11 @@ 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 @@ bool positions_invalid; bool successful; hb_vector_t<unsigned> num_roots_for_space_; + hb_vector_t<char*> buffers; }; }
diff --git a/src/graph/gsubgpos-context.cc b/src/graph/gsubgpos-context.cc index e0ff6ff..b204442 100644 --- a/src/graph/gsubgpos-context.cc +++ b/src/graph/gsubgpos-context.cc
@@ -33,8 +33,7 @@ : 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 @@ 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 49b2419..9fe9662 100644 --- a/src/graph/gsubgpos-context.hh +++ b/src/graph/gsubgpos-context.hh
@@ -40,22 +40,16 @@ graph_t& graph; unsigned lookup_list_index; hb_hashmap_t<unsigned, graph::Lookup*> lookups; - hb_vector_t<char*> 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 61b1422..48a3fe4 100644 --- a/src/hb-repacker.hh +++ b/src/hb-repacker.hh
@@ -276,35 +276,20 @@ 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<typename T> -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 @@ 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 @@ 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<typename T> +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); }