summaryrefslogtreecommitdiff
path: root/thirdparty/harfbuzz/src/graph/graph.hh
diff options
context:
space:
mode:
Diffstat (limited to 'thirdparty/harfbuzz/src/graph/graph.hh')
-rw-r--r--thirdparty/harfbuzz/src/graph/graph.hh80
1 files changed, 67 insertions, 13 deletions
diff --git a/thirdparty/harfbuzz/src/graph/graph.hh b/thirdparty/harfbuzz/src/graph/graph.hh
index 52ca9dd142..49638f34a7 100644
--- a/thirdparty/harfbuzz/src/graph/graph.hh
+++ b/thirdparty/harfbuzz/src/graph/graph.hh
@@ -265,28 +265,64 @@ struct graph_t
}
/*
- * Assign unique space numbers to each connected subgraph of 32 bit offset(s).
+ * Finds the set of nodes (placed into roots) that should be assigned unique spaces.
+ * More specifically this looks for the top most 24 bit or 32 bit links in the graph.
+ * Some special casing is done that is specific to the layout of GSUB/GPOS tables.
*/
- 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. This is to make sure
+ // that extension subtables beneath a 24bit lookup become the spaces instead
+ // of the offset to the lookup.
+ 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;
@@ -423,6 +459,22 @@ struct graph_t
}
/*
+ * Finds the topmost children of 32bit offsets in the subgraph starting
+ * at node_idx. Found indices are placed into 'found'.
+ */
+ 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
* been performed for a given index, then it will be skipped.
@@ -622,7 +674,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 +688,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);