diff options
author | Michiharu Ariza <ariza@adobe.com> | 2018-09-06 22:27:44 -0700 |
---|---|---|
committer | Michiharu Ariza <ariza@adobe.com> | 2018-09-06 22:27:44 -0700 |
commit | 22b88632d5bd3676642b0a1d93f27e47438c140b (patch) | |
tree | d3ddf769185409cc870d439ce09352ae4c33ce3c /src/hb-subset.cc | |
parent | 2a74536aae443a8b7f23ed018dec14a013c04dfe (diff) | |
parent | 21bf147054f6b5bd1c430c0e02a8c4058ed229a1 (diff) | |
download | harfbuzz-22b88632d5bd3676642b0a1d93f27e47438c140b.tar.gz |
Merge branch 'master' into cff-subset
Diffstat (limited to 'src/hb-subset.cc')
-rw-r--r-- | src/hb-subset.cc | 113 |
1 files changed, 76 insertions, 37 deletions
diff --git a/src/hb-subset.cc b/src/hb-subset.cc index d106e0ae..8b09210f 100644 --- a/src/hb-subset.cc +++ b/src/hb-subset.cc @@ -27,9 +27,8 @@ #include "hb.hh" #include "hb-open-type.hh" -#include "hb-subset-glyf.hh" #include "hb-subset.hh" -#include "hb-subset-plan.hh" +#include "hb-subset-glyf.hh" #include "hb-open-file.hh" #include "hb-ot-cmap-table.hh" @@ -43,37 +42,73 @@ #include "hb-ot-post-table.hh" #include "hb-ot-cff1-table.hh" #include "hb-ot-cff2-table.hh" +#include "hb-ot-layout-gsub-table.hh" +#include "hb-ot-layout-gpos-table.hh" -struct hb_subset_profile_t { - hb_object_header_t header; - ASSERT_POD (); -}; - -/** - * hb_subset_profile_create: - * - * Return value: New profile with default settings. - * - * Since: 1.8.0 - **/ -hb_subset_profile_t * -hb_subset_profile_create () +static unsigned int +_plan_estimate_subset_table_size (hb_subset_plan_t *plan, + unsigned int table_len) { - return hb_object_create<hb_subset_profile_t>(); + 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)); } -/** - * hb_subset_profile_destroy: - * - * Since: 1.8.0 - **/ -void -hb_subset_profile_destroy (hb_subset_profile_t *profile) +template<typename TableType> +static bool +_subset2 (hb_subset_plan_t *plan) { - if (!hb_object_destroy (profile)) return; + hb_blob_t *source_blob = hb_sanitize_context_t ().reference_table<TableType> (plan->source); + const TableType *table = source_blob->as<TableType> (); - free (profile); + 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> @@ -86,11 +121,9 @@ _subset (hb_subset_plan_t *plan) hb_tag_t tag = TableType::tableTag; hb_bool_t result = false; if (source_blob->data) - { - result = table->subset(plan); - } else { + result = table->subset (plan); + 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!"); @@ -149,6 +182,14 @@ _subset_table (hb_subset_plan_t *plan, case HB_OT_TAG_cff2: result = _subset<const OT::cff2> (plan); 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: hb_blob_t *source_table = hb_face_reference_table(plan->source, tag); if (likely (source_table)) @@ -177,7 +218,7 @@ _should_drop_table(hb_subset_plan_t *plan, hb_tag_t tag) case HB_TAG ('G', 'D', 'E', 'F'): /* temporary */ case HB_TAG ('G', 'P', 'O', 'S'): /* temporary */ case HB_TAG ('G', 'S', 'U', 'B'): /* temporary */ - return plan->drop_ot_layout; + return plan->drop_layout; // Drop these tables below by default, list pulled // from fontTools: case HB_TAG ('B', 'A', 'S', 'E'): @@ -206,19 +247,17 @@ _should_drop_table(hb_subset_plan_t *plan, hb_tag_t tag) /** * hb_subset: * @source: font face data to be subset. - * @profile: profile to use for the subsetting. * @input: input to use for the subsetting. * - * Subsets a font according to provided profile and input. + * Subsets a font according to provided input. **/ hb_face_t * hb_subset (hb_face_t *source, - hb_subset_profile_t *profile, hb_subset_input_t *input) { - if (unlikely (!profile || !input || !source)) return hb_face_get_empty(); + if (unlikely (!input || !source)) return hb_face_get_empty(); - hb_subset_plan_t *plan = hb_subset_plan_create (source, profile, input); + hb_subset_plan_t *plan = hb_subset_plan_create (source, input); hb_tag_t table_tags[32]; unsigned int offset = 0, count; @@ -237,7 +276,7 @@ hb_subset (hb_face_t *source, success = success && _subset_table (plan, tag); } offset += count; - } while (count == ARRAY_LENGTH (table_tags)); + } while (success && count == ARRAY_LENGTH (table_tags)); hb_face_t *result = success ? hb_face_reference(plan->dest) : hb_face_get_empty(); hb_subset_plan_destroy (plan); |