[subset] Refactor _subset () to reduce nesting and eliminate the use of 'goto'.
This commit is contained in:
parent
bb5c80a7c2
commit
832f2b599b
@ -119,6 +119,14 @@ struct hb_serialize_context_t
|
||||
|
||||
bool in_error () const { return !this->successful; }
|
||||
|
||||
void reset (void *start_, unsigned int size)
|
||||
{
|
||||
start = (char*) start_;
|
||||
end = start + size;
|
||||
reset ();
|
||||
current = nullptr;
|
||||
}
|
||||
|
||||
void reset ()
|
||||
{
|
||||
this->successful = true;
|
||||
@ -129,6 +137,7 @@ struct hb_serialize_context_t
|
||||
|
||||
fini ();
|
||||
this->packed.push (nullptr);
|
||||
this->packed_map.init ();
|
||||
}
|
||||
|
||||
bool check_success (bool success)
|
||||
|
138
src/hb-subset.cc
138
src/hb-subset.cc
@ -94,74 +94,100 @@ _repack (hb_tag_t tag, const hb_serialize_context_t& c)
|
||||
return repacked.copy_blob ();
|
||||
}
|
||||
|
||||
template<typename TableType>
|
||||
static
|
||||
bool
|
||||
_try_subset (const TableType *table,
|
||||
hb_vector_t<char>* buf,
|
||||
unsigned buf_size,
|
||||
hb_subset_context_t* c /* OUT */)
|
||||
{
|
||||
c->serializer->start_serialize<TableType> ();
|
||||
|
||||
bool needed = table->subset (c);
|
||||
if (!c->serializer->ran_out_of_room)
|
||||
{
|
||||
c->serializer->end_serialize ();
|
||||
return needed;
|
||||
}
|
||||
|
||||
buf_size += (buf_size >> 1) + 32;
|
||||
DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c ran out of room; reallocating to %u bytes.",
|
||||
HB_UNTAG (c->table_tag), buf_size);
|
||||
|
||||
if (unlikely (!buf->alloc (buf_size)))
|
||||
{
|
||||
DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c failed to reallocate %u bytes.",
|
||||
HB_UNTAG (c->table_tag), buf_size);
|
||||
return needed;
|
||||
}
|
||||
|
||||
c->serializer->reset (buf->arrayZ, buf_size);
|
||||
return _try_subset (table, buf, buf_size, c);
|
||||
}
|
||||
|
||||
template<typename TableType>
|
||||
static bool
|
||||
_subset (hb_subset_plan_t *plan)
|
||||
{
|
||||
bool result = false;
|
||||
hb_blob_t *source_blob = hb_sanitize_context_t ().reference_table<TableType> (plan->source);
|
||||
const TableType *table = source_blob->as<TableType> ();
|
||||
|
||||
hb_tag_t tag = TableType::tableTag;
|
||||
if (source_blob->data)
|
||||
if (!source_blob->data)
|
||||
{
|
||||
hb_vector_t<char> buf;
|
||||
/* TODO Not all tables are glyph-related. 'name' table size for example should not be
|
||||
* affected by number of glyphs. Accommodate that. */
|
||||
unsigned buf_size = _plan_estimate_subset_table_size (plan, source_blob->length);
|
||||
DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c initial estimated table size: %u bytes.", HB_UNTAG (tag), buf_size);
|
||||
if (unlikely (!buf.alloc (buf_size)))
|
||||
{
|
||||
DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c failed to allocate %u bytes.", HB_UNTAG (tag), buf_size);
|
||||
hb_blob_destroy (source_blob);
|
||||
return false;
|
||||
}
|
||||
retry:
|
||||
hb_serialize_context_t serializer ((void *) buf, buf_size);
|
||||
serializer.start_serialize<TableType> ();
|
||||
hb_subset_context_t c (source_blob, plan, &serializer, tag);
|
||||
bool needed = table->subset (&c);
|
||||
if (serializer.ran_out_of_room)
|
||||
{
|
||||
buf_size += (buf_size >> 1) + 32;
|
||||
DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c ran out of room; reallocating to %u bytes.", HB_UNTAG (tag), buf_size);
|
||||
if (unlikely (!buf.alloc (buf_size)))
|
||||
{
|
||||
DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c failed to reallocate %u bytes.", HB_UNTAG (tag), buf_size);
|
||||
hb_blob_destroy (source_blob);
|
||||
return false;
|
||||
}
|
||||
goto retry;
|
||||
}
|
||||
serializer.end_serialize ();
|
||||
|
||||
result = !serializer.in_error ();
|
||||
|
||||
if (result)
|
||||
{
|
||||
if (needed)
|
||||
{
|
||||
hb_blob_t *dest_blob = _repack (tag, serializer);
|
||||
if (dest_blob)
|
||||
{
|
||||
DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c final subset table size: %u bytes.", HB_UNTAG (tag), dest_blob->length);
|
||||
result = c.plan->add_table (tag, dest_blob);
|
||||
hb_blob_destroy (dest_blob);
|
||||
} else {
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c::subset table subsetted to empty.", HB_UNTAG (tag));
|
||||
}
|
||||
}
|
||||
DEBUG_MSG (SUBSET, nullptr,
|
||||
"OT::%c%c%c%c::subset sanitize failed on source table.", HB_UNTAG (tag));
|
||||
hb_blob_destroy (source_blob);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c::subset sanitize failed on source table.", HB_UNTAG (tag));
|
||||
|
||||
hb_vector_t<char> buf;
|
||||
/* TODO Not all tables are glyph-related. 'name' table size for example should not be
|
||||
* affected by number of glyphs. Accommodate that. */
|
||||
unsigned buf_size = _plan_estimate_subset_table_size (plan, source_blob->length);
|
||||
DEBUG_MSG (SUBSET, nullptr,
|
||||
"OT::%c%c%c%c initial estimated table size: %u bytes.", HB_UNTAG (tag), buf_size);
|
||||
if (unlikely (!buf.alloc (buf_size)))
|
||||
{
|
||||
DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c failed to allocate %u bytes.", HB_UNTAG (tag), buf_size);
|
||||
hb_blob_destroy (source_blob);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool needed = false;
|
||||
hb_serialize_context_t serializer (buf.arrayZ, buf_size);
|
||||
{
|
||||
hb_subset_context_t c (source_blob, plan, &serializer, tag);
|
||||
needed = _try_subset (table, &buf, buf_size, &c);
|
||||
}
|
||||
hb_blob_destroy (source_blob);
|
||||
DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c::subset %s", HB_UNTAG (tag), result ? "success" : "FAILED!");
|
||||
|
||||
if (serializer.ran_out_of_room || serializer.in_error ())
|
||||
{
|
||||
DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c::subset FAILED!", HB_UNTAG (tag));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!needed)
|
||||
{
|
||||
DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c::subset table subsetted to empty.", HB_UNTAG (tag));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool result = false;
|
||||
hb_blob_t *dest_blob = _repack (tag, serializer);
|
||||
if (dest_blob)
|
||||
{
|
||||
DEBUG_MSG (SUBSET, nullptr,
|
||||
"OT::%c%c%c%c final subset table size: %u bytes.",
|
||||
HB_UNTAG (tag), dest_blob->length);
|
||||
result = plan->add_table (tag, dest_blob);
|
||||
hb_blob_destroy (dest_blob);
|
||||
}
|
||||
|
||||
DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c::subset %s",
|
||||
HB_UNTAG (tag), result ? "success" : "FAILED!");
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -478,6 +478,7 @@ if get_option('tests').enabled()
|
||||
'test-algs': ['test-algs.cc', 'hb-static.cc'],
|
||||
'test-array': ['test-array.cc'],
|
||||
'test-repacker': ['test-repacker.cc', 'hb-static.cc'],
|
||||
'test-priority-queue': ['test-priority-queue.cc', 'hb-static.cc'],
|
||||
'test-iter': ['test-iter.cc', 'hb-static.cc'],
|
||||
'test-meta': ['test-meta.cc', 'hb-static.cc'],
|
||||
'test-number': ['test-number.cc', 'hb-number.cc'],
|
||||
|
Loading…
Reference in New Issue
Block a user