From 0a5d1440f829f07454592adde9dd3aa93ad74442 Mon Sep 17 00:00:00 2001 From: Garret Rieger Date: Wed, 7 Feb 2018 13:09:54 -0800 Subject: [PATCH] Add implementation of glyf subsetting. --- src/hb-subset-glyf.cc | 81 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 76 insertions(+), 5 deletions(-) diff --git a/src/hb-subset-glyf.cc b/src/hb-subset-glyf.cc index 5a3dff6d..e0ae5d80 100644 --- a/src/hb-subset-glyf.cc +++ b/src/hb-subset-glyf.cc @@ -24,9 +24,56 @@ * Google Author(s): Garret Rieger */ +#include "hb-open-type-private.hh" #include "hb-ot-glyf-table.hh" +#include "hb-set.h" #include "hb-subset-glyf.hh" +bool +calculate_glyf_prime_size (const OT::glyf::accelerator_t &glyf, + hb_set_t *glyph_ids, + unsigned int *size /* OUT */) +{ + unsigned int total = 0; + hb_codepoint_t next_glyph = -1; + while (hb_set_next(glyph_ids, &next_glyph)) { + unsigned int start_offset, end_offset; + if (!glyf.get_offsets (next_glyph, &start_offset, &end_offset)) { + *size = 0; + return false; + } + + total += end_offset - start_offset; + } + + *size = total; + return true; +} + +bool +write_glyf_prime (const OT::glyf::accelerator_t &glyf, + const char *glyf_data, + hb_set_t *glyph_ids, + int glyf_prime_size, + char *glyf_prime_data /* OUT */) +{ + char *glyf_prime_data_next = glyf_prime_data; + + hb_codepoint_t next_glyph = -1; + while (hb_set_next(glyph_ids, &next_glyph)) { + unsigned int start_offset, end_offset; + if (!glyf.get_offsets (next_glyph, &start_offset, &end_offset)) { + return false; + } + + int length = end_offset - start_offset; + memcpy (glyf_prime_data_next, glyf_data + start_offset, length); + glyf_prime_data_next += length; + } + + return true; +} + /** * hb_subset_glyf: * Subsets the glyph table according to a provided plan. @@ -40,13 +87,37 @@ hb_subset_glyf (hb_subset_plan_t *plan, hb_face_t *face, hb_blob_t **glyf_prime /* OUT */) { - OT::glyf::accelerator_t glyf_accelerator; - glyf_accelerator.init(face); + // TODO(grieger): Sanity check writes to make sure they are in-bounds. + // TODO(grieger): Sanity check allocation size for the new table. + // TODO(grieger): Subset loca simultaneously. + + hb_blob_t *glyf_blob = OT::Sanitizer().sanitize (face->reference_table (HB_OT_TAG_glyf)); + const char *glyf_data = hb_blob_get_data(glyf_blob, nullptr); + + OT::glyf::accelerator_t glyf; + glyf.init(face); - // TODO + unsigned int glyf_prime_size; + if (!calculate_glyf_prime_size (glyf, + plan->glyphs_to_retain, + &glyf_prime_size)) { + glyf.fini(); + return false; + } - glyf_accelerator.fini(); + char *glyf_prime_data = (char *) calloc (glyf_prime_size, 1); + if (!write_glyf_prime (glyf, glyf_data, plan->glyphs_to_retain, glyf_prime_size, + glyf_prime_data)) { + glyf.fini(); + free (glyf_prime_data); + return false; + } - *glyf_prime = hb_blob_get_empty (); + glyf.fini(); + *glyf_prime = hb_blob_create (glyf_prime_data, + glyf_prime_size, + HB_MEMORY_MODE_READONLY, + glyf_prime_data, + free); return true; } -- 2.34.1