[repacker] during table splits don't mutate shared coverage/classdef in place.

If other subtables are sharing coverage with a subtable being split we have to duplicate the coverage/classdef tables before they are modified during the shrink operation.
This commit is contained in:
Garret Rieger 2022-08-05 01:37:14 +00:00
parent e1ab355056
commit 5d824c09c0
2 changed files with 25 additions and 4 deletions

View File

@ -345,7 +345,9 @@ struct graph_t
}
}
unsigned index_for_offset(unsigned node_idx, const void* offset) const
// Finds the object id of the object pointed to by the offset at 'offset'
// within object[node_idx].
unsigned index_for_offset (unsigned node_idx, const void* offset) const
{
const auto& node = object (node_idx);
if (offset < node.head || offset >= node.tail) return -1;
@ -360,6 +362,24 @@ struct graph_t
return -1;
}
// Finds the object id of the object pointed to by the offset at 'offset'
// within object[node_idx]. Ensures that the returned object is safe to mutate.
// That is, if the original child object is shared by parents other than node_idx
// it will be duplicated and the duplicate will be returned instead.
unsigned mutable_index_for_offset (unsigned node_idx, const void* offset)
{
unsigned child_idx = index_for_offset (node_idx, offset);
auto& child = vertices_[child_idx];
for (unsigned p : child.parents)
{
if (p != node_idx) {
return duplicate (node_idx, child_idx);
}
}
return child_idx;
}
/*
* Assign unique space numbers to each connected subgraph of 24 bit and/or 32 bit offset(s).

View File

@ -123,9 +123,10 @@ struct PairPosFormat1 : public OT::Layout::GPOS_impl::PairPosFormat1_3<SmallType
pairSet.len = count;
c.graph.vertices_[this_index].obj.tail -= (old_count - count) * SmallTypes::size;
unsigned coverage_id = c.graph.index_for_offset (this_index, &coverage);
unsigned coverage_id = c.graph.mutable_index_for_offset (this_index, &coverage);
unsigned coverage_size = c.graph.vertices_[coverage_id].table_size ();
auto& coverage_v = c.graph.vertices_[coverage_id];
Coverage* coverage_table = (Coverage*) coverage_v.obj.head;
if (!coverage_table->sanitize (coverage_v))
return false;
@ -478,9 +479,9 @@ struct PairPosFormat2 : public OT::Layout::GPOS_impl::PairPosFormat2_4<SmallType
(old_count - count) * split_context.class1_record_size;
unsigned coverage_id =
graph.index_for_offset (split_context.this_index, &coverage);
graph.mutable_index_for_offset (split_context.this_index, &coverage);
unsigned class_def_1_id =
graph.index_for_offset (split_context.this_index, &classDef1);
graph.mutable_index_for_offset (split_context.this_index, &classDef1);
auto& coverage_v = graph.vertices_[coverage_id];
auto& class_def_1_v = graph.vertices_[class_def_1_id];
Coverage* coverage_table = (Coverage*) coverage_v.obj.head;