[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:
parent
c414ef292b
commit
5cf2a25a60
|
@ -196,7 +196,8 @@ struct graph_t
|
||||||
: parents_invalid (true),
|
: parents_invalid (true),
|
||||||
distance_invalid (true),
|
distance_invalid (true),
|
||||||
positions_invalid (true),
|
positions_invalid (true),
|
||||||
successful (true)
|
successful (true),
|
||||||
|
buffers ()
|
||||||
{
|
{
|
||||||
num_roots_for_space_.push (1);
|
num_roots_for_space_.push (1);
|
||||||
bool removed_nil = false;
|
bool removed_nil = false;
|
||||||
|
@ -228,6 +229,8 @@ struct graph_t
|
||||||
~graph_t ()
|
~graph_t ()
|
||||||
{
|
{
|
||||||
vertices_.fini ();
|
vertices_.fini ();
|
||||||
|
for (char* b : buffers)
|
||||||
|
hb_free (b);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool in_error () const
|
bool in_error () const
|
||||||
|
@ -255,6 +258,11 @@ struct graph_t
|
||||||
return vertices_[i].obj;
|
return vertices_[i].obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void add_buffer (char* buffer)
|
||||||
|
{
|
||||||
|
buffers.push (buffer);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Adds a 16 bit link from parent_id to child_id
|
* Adds a 16 bit link from parent_id to child_id
|
||||||
*/
|
*/
|
||||||
|
@ -1127,6 +1135,7 @@ struct graph_t
|
||||||
bool positions_invalid;
|
bool positions_invalid;
|
||||||
bool successful;
|
bool successful;
|
||||||
hb_vector_t<unsigned> num_roots_for_space_;
|
hb_vector_t<unsigned> num_roots_for_space_;
|
||||||
|
hb_vector_t<char*> buffers;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,8 +33,7 @@ gsubgpos_graph_context_t::gsubgpos_graph_context_t (hb_tag_t table_tag_,
|
||||||
: table_tag (table_tag_),
|
: table_tag (table_tag_),
|
||||||
graph (graph_),
|
graph (graph_),
|
||||||
lookup_list_index (0),
|
lookup_list_index (0),
|
||||||
lookups (),
|
lookups ()
|
||||||
buffers ()
|
|
||||||
{
|
{
|
||||||
if (table_tag_ != HB_OT_TAG_GPOS
|
if (table_tag_ != HB_OT_TAG_GPOS
|
||||||
&& table_tag_ != HB_OT_TAG_GSUB)
|
&& table_tag_ != HB_OT_TAG_GSUB)
|
||||||
|
@ -53,7 +52,7 @@ unsigned gsubgpos_graph_context_t::create_node (unsigned size)
|
||||||
if (!buffer)
|
if (!buffer)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
buffers.push (buffer);
|
add_buffer (buffer);
|
||||||
|
|
||||||
return graph.new_node (buffer, buffer + size);
|
return graph.new_node (buffer, buffer + size);
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,22 +40,16 @@ struct gsubgpos_graph_context_t
|
||||||
graph_t& graph;
|
graph_t& graph;
|
||||||
unsigned lookup_list_index;
|
unsigned lookup_list_index;
|
||||||
hb_hashmap_t<unsigned, graph::Lookup*> lookups;
|
hb_hashmap_t<unsigned, graph::Lookup*> lookups;
|
||||||
hb_vector_t<char*> buffers;
|
|
||||||
|
|
||||||
HB_INTERNAL gsubgpos_graph_context_t (hb_tag_t table_tag_,
|
HB_INTERNAL gsubgpos_graph_context_t (hb_tag_t table_tag_,
|
||||||
graph_t& graph_);
|
graph_t& graph_);
|
||||||
|
|
||||||
~gsubgpos_graph_context_t ()
|
|
||||||
{
|
|
||||||
for (char* b : buffers)
|
|
||||||
hb_free (b);
|
|
||||||
}
|
|
||||||
|
|
||||||
HB_INTERNAL unsigned create_node (unsigned size);
|
HB_INTERNAL unsigned create_node (unsigned size);
|
||||||
|
|
||||||
void add_buffer (char* buffer)
|
void add_buffer (char* buffer)
|
||||||
{
|
{
|
||||||
buffers.push (buffer);
|
graph.add_buffer (buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -276,35 +276,20 @@ bool _process_overflows (const hb_vector_t<graph::overflow_record_t>& overflows,
|
||||||
return resolution_attempted;
|
return resolution_attempted;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
inline bool
|
||||||
* Attempts to modify the topological sorting of the provided object graph to
|
hb_resolve_graph_overflows (hb_tag_t table_tag,
|
||||||
* eliminate offset overflows in the links between objects of the graph. If a
|
unsigned max_rounds ,
|
||||||
* non-overflowing ordering is found the updated graph is serialized it into the
|
bool recalculate_extensions,
|
||||||
* provided serialization context.
|
graph_t& sorted_graph /* IN/OUT */)
|
||||||
*
|
{
|
||||||
* 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);
|
|
||||||
sorted_graph.sort_shortest_distance ();
|
sorted_graph.sort_shortest_distance ();
|
||||||
|
|
||||||
bool will_overflow = graph::will_overflow (sorted_graph);
|
bool will_overflow = graph::will_overflow (sorted_graph);
|
||||||
if (!will_overflow)
|
if (!will_overflow)
|
||||||
{
|
return true;
|
||||||
return graph::serialize (sorted_graph);
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
if ((table_tag == HB_OT_TAG_GPOS
|
||||||
|| table_tag == HB_OT_TAG_GSUB)
|
|| table_tag == HB_OT_TAG_GSUB)
|
||||||
&& will_overflow)
|
&& will_overflow)
|
||||||
|
@ -314,13 +299,13 @@ hb_resolve_overflows (const T& packed,
|
||||||
DEBUG_MSG (SUBSET_REPACK, nullptr, "Splitting subtables if needed.");
|
DEBUG_MSG (SUBSET_REPACK, nullptr, "Splitting subtables if needed.");
|
||||||
if (!_presplit_subtables_if_needed (ext_context)) {
|
if (!_presplit_subtables_if_needed (ext_context)) {
|
||||||
DEBUG_MSG (SUBSET_REPACK, nullptr, "Subtable splitting failed.");
|
DEBUG_MSG (SUBSET_REPACK, nullptr, "Subtable splitting failed.");
|
||||||
return nullptr;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG_MSG (SUBSET_REPACK, nullptr, "Promoting lookups to extensions if needed.");
|
DEBUG_MSG (SUBSET_REPACK, nullptr, "Promoting lookups to extensions if needed.");
|
||||||
if (!_promote_extensions_if_needed (ext_context)) {
|
if (!_promote_extensions_if_needed (ext_context)) {
|
||||||
DEBUG_MSG (SUBSET_REPACK, nullptr, "Extensions promotion failed.");
|
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 ())
|
if (sorted_graph.in_error ())
|
||||||
{
|
{
|
||||||
DEBUG_MSG (SUBSET_REPACK, nullptr, "Sorted graph in error state.");
|
DEBUG_MSG (SUBSET_REPACK, nullptr, "Sorted graph in error state.");
|
||||||
return nullptr;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (graph::will_overflow (sorted_graph))
|
if (graph::will_overflow (sorted_graph))
|
||||||
{
|
{
|
||||||
DEBUG_MSG (SUBSET_REPACK, nullptr, "Offset overflow resolution failed.");
|
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);
|
return graph::serialize (sorted_graph);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue