[subset] Prepare the repacker for handling 24bit offsets in GSUB/GPOS.

The boring expansion (https://github.com/be-fonts/boring-expansion-spec) plans to introduce 24bit offsets into GSUB/GPOS. This changes the repacker to treat 24 bit offsets similar to 32 bit offsets and assign the top level 24 bit offsets into spaces to improve packing.
pull/3710/head
Garret Rieger 2 years ago
parent 3a722c5354
commit 401066bf3d
  1. 73
      src/graph/graph.hh
  2. 2
      src/hb-repacker.hh

@ -264,29 +264,58 @@ struct graph_t
hb_swap (vertices_, sorted_graph);
}
/*
* Assign unique space numbers to each connected subgraph of 32 bit offset(s).
*/
bool assign_32bit_spaces ()
void find_space_roots (hb_set_t& visited, hb_set_t& roots)
{
unsigned root_index = root_idx ();
hb_set_t visited;
hb_set_t roots;
for (unsigned i = 0; i <= root_index; i++)
int root_index = (int) root_idx ();
for (int i = root_index; i >= 0; i--)
{
if (visited.has (i)) continue;
// Only real links can form 32 bit spaces
for (auto& l : vertices_[i].obj.real_links)
{
if (l.width == 4 && !l.is_signed)
if (l.is_signed || l.width < 3)
continue;
if (i == root_index && l.width == 3)
// Ignore 24bit links from the root node, this skips past the single 24bit
// pointer to the lookup list.
continue;
if (l.width == 3)
{
roots.add (l.objidx);
find_subgraph (l.objidx, visited);
// A 24bit offset forms a root, unless there is 32bit offsets somewhere
// in it's subgraph, then those become the roots instead.
hb_set_t sub_roots;
find_32bit_roots (l.objidx, sub_roots);
if (sub_roots) {
for (unsigned sub_root_idx : sub_roots) {
roots.add (sub_root_idx);
find_subgraph (sub_root_idx, visited);
}
continue;
}
}
roots.add (l.objidx);
find_subgraph (l.objidx, visited);
}
}
}
// Mark everything not in the subgraphs of 32 bit roots as visited.
// This prevents 32 bit subgraphs from being connected via nodes not in the 32 bit subgraphs.
/*
* Assign unique space numbers to each connected subgraph of 24 bit and/or 32 bit offset(s).
* Currently, this is implemented specifically tailored to the structure of a GPOS/GSUB
* (including with 24bit offsets) table.
*/
bool assign_spaces ()
{
hb_set_t visited;
hb_set_t roots;
find_space_roots (visited, roots);
// Mark everything not in the subgraphs of the roots as visited. This prevents
// subgraphs from being connected via nodes not in those subgraphs.
visited.invert ();
if (!roots) return false;
@ -422,6 +451,18 @@ struct graph_t
find_subgraph (link.objidx, subgraph);
}
void find_32bit_roots (unsigned node_idx, hb_set_t& found)
{
for (const auto& link : vertices_[node_idx].obj.all_links ())
{
if (!link.is_signed && link.width == 4) {
found.add (link.objidx);
continue;
}
find_32bit_roots (link.objidx, found);
}
}
/*
* duplicates all nodes in the subgraph reachable from node_idx. Does not re-assign
* links. index_map is updated with mappings from old id to new id. If a duplication has already
@ -622,7 +663,7 @@ struct graph_t
private:
/*
* Returns the numbers of incoming edges that are 32bits wide.
* Returns the numbers of incoming edges that are 24 or 32 bits wide.
*/
unsigned wide_parents (unsigned node_idx, hb_set_t& parents) const
{
@ -636,7 +677,9 @@ struct graph_t
// Only real links can be wide
for (const auto& l : vertices_[p].obj.real_links)
{
if (l.objidx == node_idx && l.width == 4 && !l.is_signed)
if (l.objidx == node_idx
&& (l.width == 3 || l.width == 4)
&& !l.is_signed)
{
count++;
parents.add (p);

@ -172,7 +172,7 @@ hb_resolve_overflows (const T& packed,
&& will_overflow)
{
DEBUG_MSG (SUBSET_REPACK, nullptr, "Assigning spaces to 32 bit subgraphs.");
if (sorted_graph.assign_32bit_spaces ())
if (sorted_graph.assign_spaces ())
sorted_graph.sort_shortest_distance ();
}

Loading…
Cancel
Save