[repacker] add ext promotion test.
This commit is contained in:
parent
7ebc92f2e0
commit
ffb0f7936f
|
@ -86,7 +86,7 @@ struct Lookup : public OT::Lookup
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG_MSG (SUBSET_REPACK, nullptr,
|
DEBUG_MSG (SUBSET_REPACK, nullptr,
|
||||||
"Promoting lookup type %u (obj %u) to extension.\n",
|
"Promoting lookup type %u (obj %u) to extension.",
|
||||||
type,
|
type,
|
||||||
this_index);
|
this_index);
|
||||||
|
|
||||||
|
|
|
@ -45,6 +45,9 @@ inline int compare_sizes (const void* a, const void* b)
|
||||||
{
|
{
|
||||||
hb_pair_t<unsigned, size_t>* size_a = (hb_pair_t<unsigned, size_t>*) a;
|
hb_pair_t<unsigned, size_t>* size_a = (hb_pair_t<unsigned, size_t>*) a;
|
||||||
hb_pair_t<unsigned, size_t>* size_b = (hb_pair_t<unsigned, size_t>*) b;
|
hb_pair_t<unsigned, size_t>* size_b = (hb_pair_t<unsigned, size_t>*) b;
|
||||||
|
if (size_a->second == size_b->second) {
|
||||||
|
return size_b->first - size_a->first;
|
||||||
|
}
|
||||||
return size_a->second - size_b->second;
|
return size_a->second - size_b->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,16 +30,22 @@
|
||||||
#include "hb-open-type.hh"
|
#include "hb-open-type.hh"
|
||||||
#include "graph/serialize.hh"
|
#include "graph/serialize.hh"
|
||||||
|
|
||||||
|
static void extend (const char* value,
|
||||||
|
unsigned len,
|
||||||
|
hb_serialize_context_t* c)
|
||||||
|
{
|
||||||
|
char* obj = c->allocate_size<char> (len);
|
||||||
|
memcpy (obj, value, len);
|
||||||
|
}
|
||||||
|
|
||||||
static void start_object(const char* tag,
|
static void start_object(const char* tag,
|
||||||
unsigned len,
|
unsigned len,
|
||||||
hb_serialize_context_t* c)
|
hb_serialize_context_t* c)
|
||||||
{
|
{
|
||||||
c->push ();
|
c->push ();
|
||||||
char* obj = c->allocate_size<char> (len);
|
extend (tag, len, c);
|
||||||
strncpy (obj, tag, len);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static unsigned add_object(const char* tag,
|
static unsigned add_object(const char* tag,
|
||||||
unsigned len,
|
unsigned len,
|
||||||
hb_serialize_context_t* c)
|
hb_serialize_context_t* c)
|
||||||
|
@ -76,7 +82,8 @@ static void add_wide_offset (unsigned id,
|
||||||
static void run_resolve_overflow_test (const char* name,
|
static void run_resolve_overflow_test (const char* name,
|
||||||
hb_serialize_context_t& overflowing,
|
hb_serialize_context_t& overflowing,
|
||||||
hb_serialize_context_t& expected,
|
hb_serialize_context_t& expected,
|
||||||
unsigned num_iterations = 0)
|
unsigned num_iterations = 0,
|
||||||
|
bool recalculate_extensions = false)
|
||||||
{
|
{
|
||||||
printf (">>> Testing overflowing resolution for %s\n",
|
printf (">>> Testing overflowing resolution for %s\n",
|
||||||
name);
|
name);
|
||||||
|
@ -86,7 +93,9 @@ static void run_resolve_overflow_test (const char* name,
|
||||||
|
|
||||||
assert (overflowing.offset_overflow ());
|
assert (overflowing.offset_overflow ());
|
||||||
hb_blob_t* out = hb_resolve_overflows (overflowing.object_graph (),
|
hb_blob_t* out = hb_resolve_overflows (overflowing.object_graph (),
|
||||||
HB_TAG ('G', 'S', 'U', 'B'), num_iterations);
|
HB_TAG ('G', 'S', 'U', 'B'),
|
||||||
|
num_iterations,
|
||||||
|
recalculate_extensions);
|
||||||
assert (out);
|
assert (out);
|
||||||
|
|
||||||
hb_bytes_t result = out->as_bytes ();
|
hb_bytes_t result = out->as_bytes ();
|
||||||
|
@ -95,10 +104,20 @@ static void run_resolve_overflow_test (const char* name,
|
||||||
hb_bytes_t expected_result = expected.copy_bytes ();
|
hb_bytes_t expected_result = expected.copy_bytes ();
|
||||||
|
|
||||||
assert (result.length == expected_result.length);
|
assert (result.length == expected_result.length);
|
||||||
|
|
||||||
|
bool equal = true;
|
||||||
for (unsigned i = 0; i < expected_result.length; i++)
|
for (unsigned i = 0; i < expected_result.length; i++)
|
||||||
{
|
{
|
||||||
assert (result[i] == expected_result[i]);
|
if (result[i] != expected_result[i])
|
||||||
|
{
|
||||||
|
equal = false;
|
||||||
|
uint8_t a = result[i];
|
||||||
|
uint8_t b = expected_result[i];
|
||||||
|
printf("%08u: %x != %x\n", i, a, b);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert (equal);
|
||||||
|
|
||||||
expected_result.fini ();
|
expected_result.fini ();
|
||||||
hb_blob_destroy (out);
|
hb_blob_destroy (out);
|
||||||
|
@ -865,6 +884,89 @@ populate_serializer_with_24_and_32_bit_offsets (hb_serialize_context_t* c)
|
||||||
c->end_serialize();
|
c->end_serialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
populate_serializer_with_extension_promotion (hb_serialize_context_t* c,
|
||||||
|
int num_extensions = 0)
|
||||||
|
{
|
||||||
|
constexpr int num_lookups = 5;
|
||||||
|
constexpr int num_subtables = num_lookups * 2;
|
||||||
|
unsigned int lookups[num_lookups];
|
||||||
|
unsigned int subtables[num_subtables];
|
||||||
|
unsigned int extensions[num_subtables];
|
||||||
|
|
||||||
|
std::string large_string(60000, 'a');
|
||||||
|
c->start_serialize<char> ();
|
||||||
|
|
||||||
|
|
||||||
|
for (int i = num_subtables - 1; i >= 0; i--)
|
||||||
|
subtables[i] = add_object(large_string.c_str (), 15000, c);
|
||||||
|
|
||||||
|
for (int i = num_subtables - 1;
|
||||||
|
i >= (num_lookups - num_extensions) * 2;
|
||||||
|
i--)
|
||||||
|
{
|
||||||
|
char ext[] = {
|
||||||
|
0, 1,
|
||||||
|
0, 5
|
||||||
|
};
|
||||||
|
|
||||||
|
unsigned ext_index = i - (num_lookups - num_extensions) * 2; // 5
|
||||||
|
unsigned subtable_index = num_subtables - ext_index - 1; // 10 - 5 - 1 = 4
|
||||||
|
|
||||||
|
start_object (ext, 4, c);
|
||||||
|
add_wide_offset (subtables[subtable_index], c);
|
||||||
|
|
||||||
|
extensions[i] = c->pop_pack (false);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = num_lookups - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
bool is_ext = (i >= (num_lookups - num_extensions));
|
||||||
|
|
||||||
|
char lookup[] = {
|
||||||
|
0, is_ext ? (char) 7 : (char) 5, // type
|
||||||
|
0, 0, // flag
|
||||||
|
0, 2, // num subtables
|
||||||
|
};
|
||||||
|
|
||||||
|
start_object (lookup, 6, c);
|
||||||
|
if (is_ext) {
|
||||||
|
add_offset (extensions[i * 2], c);
|
||||||
|
add_offset (extensions[i * 2 + 1], c);
|
||||||
|
} else {
|
||||||
|
add_offset (subtables[i * 2], c);
|
||||||
|
add_offset (subtables[i * 2 + 1], c);
|
||||||
|
}
|
||||||
|
|
||||||
|
char filter[] = {0, 0};
|
||||||
|
extend (filter, 2, c);
|
||||||
|
|
||||||
|
lookups[i] = c->pop_pack (false);
|
||||||
|
}
|
||||||
|
|
||||||
|
char lookup_count[] = {0, num_lookups};
|
||||||
|
start_object ((char *) &lookup_count, 2, c);
|
||||||
|
|
||||||
|
for (int i = 0; i < num_lookups; i++)
|
||||||
|
add_offset (lookups[i], c);
|
||||||
|
|
||||||
|
unsigned lookup_list = c->pop_pack (false);
|
||||||
|
|
||||||
|
char gsub_header[] = {
|
||||||
|
0, 1, // major
|
||||||
|
0, 0, // minor
|
||||||
|
0, 0, // script list
|
||||||
|
0, 0, // feature list
|
||||||
|
};
|
||||||
|
|
||||||
|
start_object (gsub_header, 8, c);
|
||||||
|
add_offset (lookup_list, c);
|
||||||
|
c->pop_pack (false);
|
||||||
|
|
||||||
|
c->end_serialize();
|
||||||
|
}
|
||||||
|
|
||||||
static void test_sort_shortest ()
|
static void test_sort_shortest ()
|
||||||
{
|
{
|
||||||
size_t buffer_size = 100;
|
size_t buffer_size = 100;
|
||||||
|
@ -1212,6 +1314,28 @@ static void test_resolve_mixed_overflows_via_isolation_spaces ()
|
||||||
hb_blob_destroy (out);
|
hb_blob_destroy (out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_resolve_with_extension_promotion ()
|
||||||
|
{
|
||||||
|
size_t buffer_size = 200000;
|
||||||
|
void* buffer = malloc (buffer_size);
|
||||||
|
assert (buffer);
|
||||||
|
hb_serialize_context_t c (buffer, buffer_size);
|
||||||
|
populate_serializer_with_extension_promotion (&c);
|
||||||
|
|
||||||
|
void* expected_buffer = malloc (buffer_size);
|
||||||
|
assert (expected_buffer);
|
||||||
|
hb_serialize_context_t e (expected_buffer, buffer_size);
|
||||||
|
populate_serializer_with_extension_promotion (&e, 3);
|
||||||
|
|
||||||
|
run_resolve_overflow_test ("test_resolve_with_extension_promotion",
|
||||||
|
c,
|
||||||
|
e,
|
||||||
|
20,
|
||||||
|
true);
|
||||||
|
free (buffer);
|
||||||
|
free (expected_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
static void test_resolve_overflows_via_splitting_spaces ()
|
static void test_resolve_overflows_via_splitting_spaces ()
|
||||||
{
|
{
|
||||||
size_t buffer_size = 160000;
|
size_t buffer_size = 160000;
|
||||||
|
@ -1358,4 +1482,5 @@ main (int argc, char **argv)
|
||||||
test_duplicate_interior ();
|
test_duplicate_interior ();
|
||||||
test_virtual_link ();
|
test_virtual_link ();
|
||||||
test_shared_node_with_virtual_links ();
|
test_shared_node_with_virtual_links ();
|
||||||
|
test_resolve_with_extension_promotion ();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue