|
|
|
@ -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) |
|
|
|
|
{ |
|
|
|
|
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; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
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_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 (); |
|
|
|
|
needed = _try_subset (table, &buf, buf_size, &c); |
|
|
|
|
} |
|
|
|
|
hb_blob_destroy (source_blob); |
|
|
|
|
|
|
|
|
|
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; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
result = !serializer.in_error (); |
|
|
|
|
if (!needed) |
|
|
|
|
{ |
|
|
|
|
DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c::subset table subsetted to empty.", HB_UNTAG (tag)); |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
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)); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
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); |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c::subset sanitize failed on source table.", HB_UNTAG (tag)); |
|
|
|
|
|
|
|
|
|
hb_blob_destroy (source_blob); |
|
|
|
|
DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c::subset %s", HB_UNTAG (tag), result ? "success" : "FAILED!"); |
|
|
|
|
DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c::subset %s", |
|
|
|
|
HB_UNTAG (tag), result ? "success" : "FAILED!"); |
|
|
|
|
return result; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|