[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.
This commit is contained in:
Garret Rieger 2022-08-15 22:49:24 +00:00
parent c414ef292b
commit 5cf2a25a60
4 changed files with 53 additions and 40 deletions

View File

@ -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<unsigned> num_roots_for_space_;
hb_vector_t<char*> buffers;
};
}

View File

@ -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);
}

View File

@ -40,22 +40,16 @@ struct gsubgpos_graph_context_t
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:

View File

@ -276,35 +276,20 @@ bool _process_overflows (const hb_vector_t<graph::overflow_record_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<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 @@ 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<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);
}