summaryrefslogtreecommitdiff
path: root/src/hb-subset.cc
diff options
context:
space:
mode:
authorMichiharu Ariza <ariza@adobe.com>2018-09-06 22:27:44 -0700
committerMichiharu Ariza <ariza@adobe.com>2018-09-06 22:27:44 -0700
commit22b88632d5bd3676642b0a1d93f27e47438c140b (patch)
treed3ddf769185409cc870d439ce09352ae4c33ce3c /src/hb-subset.cc
parent2a74536aae443a8b7f23ed018dec14a013c04dfe (diff)
parent21bf147054f6b5bd1c430c0e02a8c4058ed229a1 (diff)
downloadharfbuzz-22b88632d5bd3676642b0a1d93f27e47438c140b.tar.gz
Merge branch 'master' into cff-subset
Diffstat (limited to 'src/hb-subset.cc')
-rw-r--r--src/hb-subset.cc113
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);