[repacker] Add additional splitting spaces test.
Fix issues it uncovered.
diff --git a/src/hb-repacker.hh b/src/hb-repacker.hh
index d7b4dd3..1e8f491 100644
--- a/src/hb-repacker.hh
+++ b/src/hb-repacker.hh
@@ -474,7 +474,7 @@
;
remap_obj_indices (index_map, new_subgraph);
- remap_obj_indices (index_map, parents.iter ());
+ remap_obj_indices (index_map, parents.iter (), true);
// Update roots set with new indices as needed.
unsigned next = HB_SET_VALUE_INVALID;
@@ -482,7 +482,6 @@
{
if (index_map.has (next))
{
- printf ("Updated root %u to %u.\n", next, index_map[next]);
roots.del (next);
roots.add (index_map[next]);
}
@@ -752,8 +751,12 @@
unsigned wide_parents (unsigned node_idx, hb_set_t& parents) const
{
unsigned count = 0;
+ hb_set_t visited;
for (unsigned p : vertices_[node_idx].parents)
{
+ if (visited.has (p)) continue;
+ visited.add (p);
+
for (const auto& l : vertices_[p].obj.links)
{
if (l.objidx == node_idx && l.width == 4 && !l.is_signed)
@@ -936,7 +939,8 @@
*/
template<typename Iterator, hb_requires (hb_is_iterator (Iterator))>
void remap_obj_indices (const hb_hashmap_t<unsigned, unsigned>& id_map,
- Iterator subgraph)
+ Iterator subgraph,
+ bool only_wide = false)
{
if (!id_map) return;
for (unsigned i : subgraph)
@@ -945,6 +949,7 @@
{
auto& link = vertices_[i].obj.links[j];
if (!id_map.has (link.objidx)) continue;
+ if (only_wide && !(link.width == 4 && !link.is_signed)) continue;
reassign_link (link, i, id_map[link.objidx]);
}
diff --git a/src/test-repacker.cc b/src/test-repacker.cc
index 785d7e7..26826d4 100644
--- a/src/test-repacker.cc
+++ b/src/test-repacker.cc
@@ -516,6 +516,40 @@
}
static void
+populate_serializer_with_split_spaces_2 (hb_serialize_context_t* c)
+{
+ // Overflow needs to be resolved by splitting the single space
+ std::string large_string(70000, 'a');
+ c->start_serialize<char> ();
+
+ unsigned obj_f = add_object ("f", 1, c);
+
+ start_object (large_string.c_str(), 40000, c);
+ add_offset (obj_f, c);
+ unsigned obj_d = c->pop_pack (false);
+
+ start_object (large_string.c_str(), 40000, c);
+ add_offset (obj_f, c);
+ unsigned obj_e = c->pop_pack (false);
+
+ start_object ("b", 1, c);
+ add_offset (obj_d, c);
+ unsigned obj_b = c->pop_pack (false);
+
+ start_object ("c", 1, c);
+ add_offset (obj_e, c);
+ unsigned obj_c = c->pop_pack (false);
+
+ start_object ("a", 1, c);
+ add_offset (obj_b, c);
+ add_wide_offset (obj_b, c);
+ add_wide_offset (obj_c, c);
+ c->pop_pack (false);
+
+ c->end_serialize();
+}
+
+static void
populate_serializer_with_split_spaces_expected (hb_serialize_context_t* c)
{
// Overflow needs to be resolved by splitting the single space
@@ -552,6 +586,60 @@
}
static void
+populate_serializer_with_split_spaces_expected_2 (hb_serialize_context_t* c)
+{
+ // Overflow needs to be resolved by splitting the single space
+
+ std::string large_string(70000, 'a');
+ c->start_serialize<char> ();
+
+ // Space 2
+
+ unsigned obj_f_double_prime = add_object ("f", 1, c);
+
+ start_object (large_string.c_str(), 40000, c);
+ add_offset (obj_f_double_prime, c);
+ unsigned obj_d_prime = c->pop_pack (false);
+
+ start_object ("b", 1, c);
+ add_offset (obj_d_prime, c);
+ unsigned obj_b_prime = c->pop_pack (false);
+
+ // Space 1
+
+ unsigned obj_f_prime = add_object ("f", 1, c);
+
+ start_object (large_string.c_str(), 40000, c);
+ add_offset (obj_f_prime, c);
+ unsigned obj_e = c->pop_pack (false);
+
+ start_object ("c", 1, c);
+ add_offset (obj_e, c);
+ unsigned obj_c = c->pop_pack (false);
+
+ // Space 0
+
+ unsigned obj_f = add_object ("f", 1, c);
+
+ start_object (large_string.c_str(), 40000, c);
+ add_offset (obj_f, c);
+ unsigned obj_d = c->pop_pack (false);
+
+ start_object ("b", 1, c);
+ add_offset (obj_d, c);
+ unsigned obj_b = c->pop_pack (false);
+
+ // Root
+ start_object ("a", 1, c);
+ add_offset (obj_b, c);
+ add_wide_offset (obj_b_prime, c);
+ add_wide_offset (obj_c, c);
+ c->pop_pack (false);
+
+ c->end_serialize();
+}
+
+static void
populate_serializer_complex_1 (hb_serialize_context_t* c)
{
c->start_serialize<char> ();
@@ -1124,6 +1212,42 @@
}
+static void test_resolve_overflows_via_splitting_spaces_2 ()
+{
+ size_t buffer_size = 160000;
+ void* buffer = malloc (buffer_size);
+ hb_serialize_context_t c (buffer, buffer_size);
+ populate_serializer_with_split_spaces_2 (&c);
+ graph_t graph (c.object_graph ());
+
+ void* out_buffer = malloc (buffer_size);
+ hb_serialize_context_t out (out_buffer, buffer_size);
+
+ assert (c.offset_overflow ());
+ hb_resolve_overflows (c.object_graph (), HB_TAG ('G', 'S', 'U', 'B'), &out, 1);
+ assert (!out.offset_overflow ());
+ hb_bytes_t result = out.copy_bytes ();
+
+ void* expected_buffer = malloc (buffer_size);
+ hb_serialize_context_t e (expected_buffer, buffer_size);
+ assert (!e.offset_overflow ());
+ populate_serializer_with_split_spaces_expected_2 (&e);
+ hb_bytes_t expected_result = e.copy_bytes ();
+
+ assert (result.length == expected_result.length);
+ for (unsigned i = 0; i < expected_result.length; i++)
+ {
+ assert (result[i] == expected_result[i]);
+ }
+
+ result.fini ();
+ expected_result.fini ();
+ free (buffer);
+ free (expected_buffer);
+ free (out_buffer);
+
+}
+
// TODO(garretrieger): update will_overflow tests to check the overflows array.
// TODO(garretrieger): add tests for priority raising.
@@ -1146,6 +1270,7 @@
test_resolve_overflows_via_isolating_16bit_space ();
test_resolve_overflows_via_isolating_16bit_space_2 ();
test_resolve_overflows_via_splitting_spaces ();
+ test_resolve_overflows_via_splitting_spaces_2 ();
test_duplicate_leaf ();
test_duplicate_interior ();
}