|
|
@ -40,8 +40,75 @@ |
|
|
|
#include "hb-ot-maxp-table.hh" |
|
|
|
#include "hb-ot-maxp-table.hh" |
|
|
|
#include "hb-ot-os2-table.hh" |
|
|
|
#include "hb-ot-os2-table.hh" |
|
|
|
#include "hb-ot-post-table.hh" |
|
|
|
#include "hb-ot-post-table.hh" |
|
|
|
|
|
|
|
#include "hb-ot-layout-gsub-table.hh" |
|
|
|
|
|
|
|
#include "hb-ot-layout-gpos-table.hh" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static unsigned int |
|
|
|
|
|
|
|
_plan_estimate_subset_table_size (hb_subset_plan_t *plan, |
|
|
|
|
|
|
|
unsigned int table_len) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
unsigned int src_glyphs = plan->source->get_num_glyphs (); |
|
|
|
|
|
|
|
unsigned int dst_glyphs = plan->glyphset->get_population (); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return 512 + (unsigned int) (table_len * sqrt ((double) dst_glyphs / src_glyphs)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template<typename TableType> |
|
|
|
|
|
|
|
static bool |
|
|
|
|
|
|
|
_subset2 (hb_subset_plan_t *plan) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
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; |
|
|
|
|
|
|
|
hb_bool_t result = false; |
|
|
|
|
|
|
|
if (source_blob->data) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
hb_auto_t<hb_vector_t<char>> buf; |
|
|
|
|
|
|
|
unsigned int 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); |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
retry: |
|
|
|
|
|
|
|
hb_serialize_context_t serializer (buf.arrayZ, buf_size); |
|
|
|
|
|
|
|
hb_subset_context_t c (plan, &serializer); |
|
|
|
|
|
|
|
result = 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); |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
goto retry; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (result) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
hb_blob_t *dest_blob = serializer.copy_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 |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c::subset table subsetted to empty.", HB_UNTAG(tag)); |
|
|
|
|
|
|
|
result = true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
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!"); |
|
|
|
|
|
|
|
return result; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
template<typename TableType> |
|
|
|
template<typename TableType> |
|
|
|
static bool |
|
|
|
static bool |
|
|
|
_subset (hb_subset_plan_t *plan) |
|
|
|
_subset (hb_subset_plan_t *plan) |
|
|
@ -107,6 +174,14 @@ _subset_table (hb_subset_plan_t *plan, |
|
|
|
case HB_OT_TAG_post: |
|
|
|
case HB_OT_TAG_post: |
|
|
|
result = _subset<const OT::post> (plan); |
|
|
|
result = _subset<const OT::post> (plan); |
|
|
|
break; |
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case HB_OT_TAG_GSUB: |
|
|
|
|
|
|
|
result = _subset2<const OT::GSUB> (plan); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case HB_OT_TAG_GPOS: |
|
|
|
|
|
|
|
result = _subset2<const OT::GPOS> (plan); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
default: |
|
|
|
default: |
|
|
|
hb_blob_t *source_table = hb_face_reference_table(plan->source, tag); |
|
|
|
hb_blob_t *source_table = hb_face_reference_table(plan->source, tag); |
|
|
|
if (likely (source_table)) |
|
|
|
if (likely (source_table)) |
|
|
|