[subset] Switch to using hb_map_t inside of hb_subset_plan_t.

This commit is contained in:
Garret Rieger 2018-05-30 12:23:51 -07:00
parent b3d45de6cf
commit 251cc977e9
11 changed files with 139 additions and 188 deletions

View File

@ -28,6 +28,7 @@
#define HB_OT_CMAP_TABLE_HH #define HB_OT_CMAP_TABLE_HH
#include "hb-open-type-private.hh" #include "hb-open-type-private.hh"
#include "hb-set-private.hh"
#include "hb-subset-plan.hh" #include "hb-subset-plan.hh"
/* /*
@ -111,7 +112,7 @@ struct CmapSubtableFormat4
{ {
hb_codepoint_t cp = segments[i].start_code; hb_codepoint_t cp = segments[i].start_code;
hb_codepoint_t start_gid = 0; hb_codepoint_t start_gid = 0;
if (unlikely (!hb_subset_plan_new_gid_for_codepoint (plan, cp, &start_gid) && cp != 0xFFFF)) if (unlikely (!plan->new_gid_for_codepoint (cp, &start_gid) && cp != 0xFFFF))
return_trace (false); return_trace (false);
id_delta[i].set (start_gid - segments[i].start_code); id_delta[i].set (start_gid - segments[i].start_code);
} else { } else {
@ -139,7 +140,7 @@ struct CmapSubtableFormat4
{ {
hb_codepoint_t cp = segments[i].start_code + j; hb_codepoint_t cp = segments[i].start_code + j;
hb_codepoint_t new_gid; hb_codepoint_t new_gid;
if (unlikely (!hb_subset_plan_new_gid_for_codepoint (plan, cp, &new_gid))) if (unlikely (!plan->new_gid_for_codepoint (cp, &new_gid)))
return_trace (false); return_trace (false);
glyph_id_array[j].set (new_gid); glyph_id_array[j].set (new_gid);
} }
@ -176,10 +177,11 @@ struct CmapSubtableFormat4
{ {
segment_plan *segment = nullptr; segment_plan *segment = nullptr;
hb_codepoint_t last_gid = 0; hb_codepoint_t last_gid = 0;
for (unsigned int i = 0; i < plan->codepoints.len; i++) {
hb_codepoint_t cp = plan->codepoints[i]; hb_codepoint_t cp = HB_SET_VALUE_INVALID;
while (plan->unicodes->next (&cp)) {
hb_codepoint_t new_gid; hb_codepoint_t new_gid;
if (unlikely (!hb_subset_plan_new_gid_for_codepoint (plan, cp, &new_gid))) if (unlikely (!plan->new_gid_for_codepoint (cp, &new_gid)))
{ {
DEBUG_MSG(SUBSET, nullptr, "Unable to find new gid for %04x", cp); DEBUG_MSG(SUBSET, nullptr, "Unable to find new gid for %04x", cp);
return false; return false;
@ -494,11 +496,11 @@ struct CmapSubtableFormat12 : CmapSubtableLongSegmented<CmapSubtableFormat12>
hb_vector_t<CmapSubtableLongGroup> *groups) hb_vector_t<CmapSubtableLongGroup> *groups)
{ {
CmapSubtableLongGroup *group = nullptr; CmapSubtableLongGroup *group = nullptr;
for (unsigned int i = 0; i < plan->codepoints.len; i++) {
hb_codepoint_t cp = plan->codepoints[i]; hb_codepoint_t cp = HB_SET_VALUE_INVALID;
while (plan->unicodes->next (&cp)) {
hb_codepoint_t new_gid; hb_codepoint_t new_gid;
if (unlikely (!hb_subset_plan_new_gid_for_codepoint (plan, cp, &new_gid))) if (unlikely (!plan->new_gid_for_codepoint (cp, &new_gid)))
{ {
DEBUG_MSG(SUBSET, nullptr, "Unable to find new gid for %04x", cp); DEBUG_MSG(SUBSET, nullptr, "Unable to find new gid for %04x", cp);
return false; return false;
@ -882,7 +884,7 @@ struct cmap
HB_MEMORY_MODE_READONLY, HB_MEMORY_MODE_READONLY,
dest, dest,
free); free);
bool result = hb_subset_plan_add_table (plan, HB_OT_TAG_cmap, cmap_prime); bool result = plan->add_table (HB_OT_TAG_cmap, cmap_prime);
hb_blob_destroy (cmap_prime); hb_blob_destroy (cmap_prime);
return result; return result;
} }

View File

@ -88,9 +88,9 @@ struct glyf
bool success = true; bool success = true;
bool use_short_loca = false; bool use_short_loca = false;
if (hb_subset_glyf_and_loca (plan, &use_short_loca, &glyf_prime, &loca_prime)) { if (hb_subset_glyf_and_loca (plan, &use_short_loca, &glyf_prime, &loca_prime)) {
success = success && hb_subset_plan_add_table (plan, HB_OT_TAG_glyf, glyf_prime); success = success && plan->add_table (HB_OT_TAG_glyf, glyf_prime);
success = success && hb_subset_plan_add_table (plan, HB_OT_TAG_loca, loca_prime); success = success && plan->add_table (HB_OT_TAG_loca, loca_prime);
success = success && _add_head_and_set_loca_version (plan->source, use_short_loca, plan->dest); success = success && _add_head_and_set_loca_version (plan, use_short_loca);
} else { } else {
success = false; success = false;
} }
@ -101,9 +101,9 @@ struct glyf
} }
static bool static bool
_add_head_and_set_loca_version (hb_face_t *source, bool use_short_loca, hb_face_t *dest) _add_head_and_set_loca_version (hb_subset_plan_t *plan, bool use_short_loca)
{ {
hb_blob_t *head_blob = OT::Sanitizer<OT::head>().sanitize (hb_face_reference_table (source, HB_OT_TAG_head)); hb_blob_t *head_blob = OT::Sanitizer<OT::head>().sanitize (hb_face_reference_table (plan->source, HB_OT_TAG_head));
hb_blob_t *head_prime_blob = hb_blob_copy_writable_or_fail (head_blob); hb_blob_t *head_prime_blob = hb_blob_copy_writable_or_fail (head_blob);
hb_blob_destroy (head_blob); hb_blob_destroy (head_blob);
@ -112,7 +112,7 @@ struct glyf
OT::head *head_prime = (OT::head *) hb_blob_get_data_writable (head_prime_blob, nullptr); OT::head *head_prime = (OT::head *) hb_blob_get_data_writable (head_prime_blob, nullptr);
head_prime->indexToLocFormat.set (use_short_loca ? 0 : 1); head_prime->indexToLocFormat.set (use_short_loca ? 0 : 1);
bool success = hb_subset_face_add_table (dest, HB_OT_TAG_head, head_prime_blob); bool success = plan->add_table (HB_OT_TAG_head, head_prime_blob);
hb_blob_destroy (head_prime_blob); hb_blob_destroy (head_prime_blob);
return success; return success;

View File

@ -59,13 +59,13 @@ struct DeviceRecord
inline unsigned int len () const inline unsigned int len () const
{ {
return this->subset_plan->gids_to_retain_sorted.len; return this->subset_plan->glyphs.len;
} }
inline const HBUINT8* operator [] (unsigned int i) const inline const HBUINT8* operator [] (unsigned int i) const
{ {
if (unlikely (i >= len())) return nullptr; if (unlikely (i >= len())) return nullptr;
hb_codepoint_t gid = this->subset_plan->gids_to_retain_sorted [i]; hb_codepoint_t gid = this->subset_plan->glyphs [i];
const HBUINT8* width = &(this->source_device_record->widths[gid]); const HBUINT8* width = &(this->source_device_record->widths[gid]);
@ -147,7 +147,7 @@ struct hdmx
this->version.set (source_hdmx->version); this->version.set (source_hdmx->version);
this->num_records.set (source_hdmx->num_records); this->num_records.set (source_hdmx->num_records);
this->size_device_record.set (DeviceRecord::get_size (plan->gids_to_retain_sorted.len)); this->size_device_record.set (DeviceRecord::get_size (plan->glyphs.len));
for (unsigned int i = 0; i < source_hdmx->num_records; i++) for (unsigned int i = 0; i < source_hdmx->num_records; i++)
{ {
@ -163,7 +163,7 @@ struct hdmx
static inline size_t get_subsetted_size (hb_subset_plan_t *plan) static inline size_t get_subsetted_size (hb_subset_plan_t *plan)
{ {
return min_size + DeviceRecord::get_size (plan->gids_to_retain_sorted.len); return min_size + DeviceRecord::get_size (plan->glyphs.len);
} }
inline bool subset (hb_subset_plan_t *plan) const inline bool subset (hb_subset_plan_t *plan) const
@ -189,7 +189,7 @@ struct hdmx
HB_MEMORY_MODE_READONLY, HB_MEMORY_MODE_READONLY,
dest, dest,
free); free);
bool result = hb_subset_plan_add_table (plan, HB_OT_TAG_hdmx, hdmx_prime_blob); bool result = plan->add_table (HB_OT_TAG_hdmx, hdmx_prime_blob);
hb_blob_destroy (hdmx_prime_blob); hb_blob_destroy (hdmx_prime_blob);
return result; return result;

View File

@ -81,7 +81,7 @@ struct hmtxvmtx
H *table = (H *) hb_blob_get_data (dest_blob, &length); H *table = (H *) hb_blob_get_data (dest_blob, &length);
table->numberOfLongMetrics.set (num_hmetrics); table->numberOfLongMetrics.set (num_hmetrics);
bool result = hb_subset_plan_add_table (plan, H::tableTag, dest_blob); bool result = plan->add_table (H::tableTag, dest_blob);
hb_blob_destroy (dest_blob); hb_blob_destroy (dest_blob);
return result; return result;
@ -94,7 +94,7 @@ struct hmtxvmtx
/* All the trailing glyphs with the same advance can use one LongMetric /* All the trailing glyphs with the same advance can use one LongMetric
* and just keep LSB */ * and just keep LSB */
hb_vector_t<hb_codepoint_t> &gids = plan->gids_to_retain_sorted; hb_vector_t<hb_codepoint_t> &gids = plan->glyphs;
unsigned int num_advances = gids.len; unsigned int num_advances = gids.len;
unsigned int last_advance = _mtx.get_advance (gids[num_advances - 1]); unsigned int last_advance = _mtx.get_advance (gids[num_advances - 1]);
while (num_advances > 1 while (num_advances > 1
@ -178,7 +178,7 @@ struct hmtxvmtx
HB_MEMORY_MODE_READONLY, HB_MEMORY_MODE_READONLY,
dest, dest,
free); free);
bool success = hb_subset_plan_add_table (plan, T::tableTag, result); bool success = plan->add_table (T::tableTag, result);
hb_blob_destroy (result); hb_blob_destroy (result);
return success; return success;
} }

View File

@ -109,11 +109,11 @@ struct maxp
} }
OT::maxp *maxp_prime = (OT::maxp *) hb_blob_get_data (maxp_prime_blob, nullptr); OT::maxp *maxp_prime = (OT::maxp *) hb_blob_get_data (maxp_prime_blob, nullptr);
maxp_prime->set_num_glyphs (plan->gids_to_retain_sorted.len); maxp_prime->set_num_glyphs (plan->glyphs.len);
if (plan->drop_hints) if (plan->drop_hints)
drop_hint_fields (plan, maxp_prime); drop_hint_fields (plan, maxp_prime);
bool result = hb_subset_plan_add_table(plan, HB_OT_TAG_maxp, maxp_prime_blob); bool result = plan->add_table (HB_OT_TAG_maxp, maxp_prime_blob);
hb_blob_destroy (maxp_prime_blob); hb_blob_destroy (maxp_prime_blob);
return result; return result;
} }

View File

@ -63,26 +63,25 @@ struct os2
} }
uint16_t min_cp, max_cp; uint16_t min_cp, max_cp;
find_min_and_max_codepoint (plan->codepoints, &min_cp, &max_cp); find_min_and_max_codepoint (plan->unicodes, &min_cp, &max_cp);
os2_prime->usFirstCharIndex.set (min_cp); os2_prime->usFirstCharIndex.set (min_cp);
os2_prime->usLastCharIndex.set (max_cp); os2_prime->usLastCharIndex.set (max_cp);
_update_unicode_ranges (plan->codepoints, os2_prime->ulUnicodeRange); _update_unicode_ranges (plan->unicodes, os2_prime->ulUnicodeRange);
bool result = hb_subset_plan_add_table(plan, HB_OT_TAG_os2, os2_prime_blob); bool result = plan->add_table (HB_OT_TAG_os2, os2_prime_blob);
hb_blob_destroy (os2_prime_blob); hb_blob_destroy (os2_prime_blob);
return result; return result;
} }
inline void _update_unicode_ranges (const hb_vector_t<hb_codepoint_t> &codepoints, inline void _update_unicode_ranges (const hb_set_t *codepoints,
HBUINT32 ulUnicodeRange[4]) const HBUINT32 ulUnicodeRange[4]) const
{ {
for (unsigned int i = 0; i < 4; i++) for (unsigned int i = 0; i < 4; i++)
ulUnicodeRange[i].set (0); ulUnicodeRange[i].set (0);
for (unsigned int i = 0; i < codepoints.len; i++) hb_codepoint_t cp = HB_SET_VALUE_INVALID;
{ while (codepoints->next (&cp)) {
hb_codepoint_t cp = codepoints[i];
unsigned int bit = hb_get_unicode_range_bit (cp); unsigned int bit = hb_get_unicode_range_bit (cp);
if (bit < 128) if (bit < 128)
{ {
@ -101,28 +100,12 @@ struct os2
} }
} }
static inline void find_min_and_max_codepoint (const hb_vector_t<hb_codepoint_t> &codepoints, static inline void find_min_and_max_codepoint (const hb_set_t *codepoints,
uint16_t *min_cp, /* OUT */ uint16_t *min_cp, /* OUT */
uint16_t *max_cp /* OUT */) uint16_t *max_cp /* OUT */)
{ {
hb_codepoint_t min = -1, max = 0; *min_cp = codepoints->get_min ();
*max_cp = codepoints->get_max ();
for (unsigned int i = 0; i < codepoints.len; i++)
{
hb_codepoint_t cp = codepoints[i];
if (cp < min)
min = cp;
if (cp > max)
max = cp;
}
if (min > 0xFFFF)
min = 0xFFFF;
if (max > 0xFFFF)
max = 0xFFFF;
*min_cp = min;
*max_cp = max;
} }
enum font_page_t { enum font_page_t {

View File

@ -99,7 +99,7 @@ struct post
} }
post_prime->version.major.set (3); // Version 3 does not have any glyph names. post_prime->version.major.set (3); // Version 3 does not have any glyph names.
bool result = hb_subset_plan_add_table (plan, HB_OT_TAG_post, post_prime_blob); bool result = plan->add_table (HB_OT_TAG_post, post_prime_blob);
hb_blob_destroy (post_prime_blob); hb_blob_destroy (post_prime_blob);
return result; return result;

View File

@ -130,8 +130,7 @@ _update_components (hb_subset_plan_t * plan,
do do
{ {
hb_codepoint_t new_gid; hb_codepoint_t new_gid;
if (!hb_subset_plan_new_gid_for_old_id (plan, if (!plan->new_gid_for_old_gid (iterator.current->glyphIndex,
iterator.current->glyphIndex,
&new_gid)) &new_gid))
continue; continue;
@ -165,7 +164,7 @@ _write_glyf_and_loca_prime (hb_subset_plan_t *plan,
unsigned int loca_prime_size, unsigned int loca_prime_size,
char *loca_prime_data /* OUT */) char *loca_prime_data /* OUT */)
{ {
hb_vector_t<hb_codepoint_t> &glyph_ids = plan->gids_to_retain_sorted; hb_vector_t<hb_codepoint_t> &glyph_ids = plan->glyphs;
char *glyf_prime_data_next = glyf_prime_data; char *glyf_prime_data_next = glyf_prime_data;
bool success = true; bool success = true;
@ -234,7 +233,7 @@ _hb_subset_glyf_and_loca (const OT::glyf::accelerator_t &glyf,
hb_blob_t **loca_prime /* OUT */) hb_blob_t **loca_prime /* OUT */)
{ {
// TODO(grieger): Sanity check allocation size for the new table. // TODO(grieger): Sanity check allocation size for the new table.
hb_vector_t<hb_codepoint_t> &glyphs_to_retain = plan->gids_to_retain_sorted; hb_vector_t<hb_codepoint_t> &glyphs_to_retain = plan->glyphs;
unsigned int glyf_prime_size; unsigned int glyf_prime_size;
unsigned int loca_prime_size; unsigned int loca_prime_size;

View File

@ -24,78 +24,14 @@
* Google Author(s): Garret Rieger, Roderick Sheeter * Google Author(s): Garret Rieger, Roderick Sheeter
*/ */
#include "hb-map-private.hh"
#include "hb-subset-private.hh" #include "hb-subset-private.hh"
#include "hb-set-private.hh"
#include "hb-subset-plan.hh" #include "hb-subset-plan.hh"
#include "hb-ot-cmap-table.hh" #include "hb-ot-cmap-table.hh"
#include "hb-ot-glyf-table.hh" #include "hb-ot-glyf-table.hh"
static int
_hb_codepoint_t_cmp (const void *pa, const void *pb)
{
hb_codepoint_t a = * (hb_codepoint_t *) pa;
hb_codepoint_t b = * (hb_codepoint_t *) pb;
return a < b ? -1 : a > b ? +1 : 0;
}
hb_bool_t
hb_subset_plan_new_gid_for_codepoint (const hb_subset_plan_t *plan,
hb_codepoint_t codepoint,
hb_codepoint_t *new_gid)
{
// TODO actual map, delete this garbage.
for (unsigned int i = 0; i < plan->codepoints.len; i++)
{
if (plan->codepoints[i] != codepoint) continue;
if (!hb_subset_plan_new_gid_for_old_id(plan, plan->gids_to_retain[i], new_gid))
{
return false;
}
return true;
}
return false;
}
hb_bool_t
hb_subset_plan_new_gid_for_old_id (const hb_subset_plan_t *plan,
hb_codepoint_t old_gid,
hb_codepoint_t *new_gid)
{
// the index in old_gids is the new gid; only up to codepoints.len are valid
for (unsigned int i = 0; i < plan->gids_to_retain_sorted.len; i++)
{
if (plan->gids_to_retain_sorted[i] == old_gid)
{
*new_gid = i;
return true;
}
}
return false;
}
hb_bool_t
hb_subset_plan_add_table (hb_subset_plan_t *plan,
hb_tag_t tag,
hb_blob_t *contents)
{
hb_blob_t *source_blob = plan->source->reference_table (tag);
DEBUG_MSG(SUBSET, nullptr, "add table %c%c%c%c, dest %d bytes, source %d bytes", HB_UNTAG(tag), hb_blob_get_length (contents), hb_blob_get_length (source_blob));
hb_blob_destroy (source_blob);
return hb_subset_face_add_table(plan->dest, tag, contents);
}
static void
_populate_codepoints (hb_set_t *input_codepoints,
hb_vector_t<hb_codepoint_t>& plan_codepoints)
{
plan_codepoints.alloc (hb_set_get_population (input_codepoints));
hb_codepoint_t cp = -1;
while (hb_set_next (input_codepoints, &cp))
plan_codepoints.push(cp);
plan_codepoints.qsort (_hb_codepoint_t_cmp);
}
static void static void
_add_gid_and_children (const OT::glyf::accelerator_t &glyf, _add_gid_and_children (const OT::glyf::accelerator_t &glyf,
hb_codepoint_t gid, hb_codepoint_t gid,
@ -119,58 +55,66 @@ _add_gid_and_children (const OT::glyf::accelerator_t &glyf,
static void static void
_populate_gids_to_retain (hb_face_t *face, _populate_gids_to_retain (hb_face_t *face,
hb_vector_t<hb_codepoint_t>& codepoints, const hb_set_t *unicodes,
hb_vector_t<hb_codepoint_t>& old_gids, hb_set_t *unicodes_to_retain,
hb_vector_t<hb_codepoint_t>& old_gids_sorted) hb_map_t *codepoint_to_glyph,
hb_vector_t<hb_codepoint_t> *glyphs)
{ {
OT::cmap::accelerator_t cmap; OT::cmap::accelerator_t cmap;
OT::glyf::accelerator_t glyf; OT::glyf::accelerator_t glyf;
cmap.init (face); cmap.init (face);
glyf.init (face); glyf.init (face);
hb_auto_t<hb_vector_t<unsigned int> > bad_indices; hb_set_t *initial_gids_to_retain = hb_set_create ();
initial_gids_to_retain->add (0); // Not-def
old_gids.alloc (codepoints.len); hb_codepoint_t cp = HB_SET_VALUE_INVALID;
for (unsigned int i = 0; i < codepoints.len; i++) while (unicodes->next (&cp))
{ {
hb_codepoint_t gid; hb_codepoint_t gid;
if (!cmap.get_nominal_glyph (codepoints[i], &gid)) if (!cmap.get_nominal_glyph (cp, &gid))
{ {
gid = -1; DEBUG_MSG(SUBSET, nullptr, "Drop U+%04X; no gid", cp);
bad_indices.push (i); continue;
} }
old_gids.push (gid); unicodes_to_retain->add (cp);
} codepoint_to_glyph->set (cp, gid);
initial_gids_to_retain->add (gid);
/* Generally there shouldn't be any */
while (bad_indices.len > 0)
{
unsigned int i = bad_indices[bad_indices.len - 1];
bad_indices.pop ();
DEBUG_MSG(SUBSET, nullptr, "Drop U+%04X; no gid", codepoints[i]);
codepoints.remove (i);
old_gids.remove (i);
} }
// Populate a full set of glyphs to retain by adding all referenced // Populate a full set of glyphs to retain by adding all referenced
// composite glyphs. // composite glyphs.
// TODO expand with glyphs reached by G* // TODO expand with glyphs reached by G*
hb_set_t * all_gids_to_retain = hb_set_create ();
_add_gid_and_children (glyf, 0, all_gids_to_retain);
for (unsigned int i = 0; i < old_gids.len; i++)
_add_gid_and_children (glyf, old_gids[i], all_gids_to_retain);
// Transfer to a sorted list.
old_gids_sorted.alloc (hb_set_get_population (all_gids_to_retain));
hb_codepoint_t gid = HB_SET_VALUE_INVALID; hb_codepoint_t gid = HB_SET_VALUE_INVALID;
while (hb_set_next (all_gids_to_retain, &gid)) hb_set_t *all_gids_to_retain = hb_set_create ();
old_gids_sorted.push (gid); while (initial_gids_to_retain->next (&gid))
{
_add_gid_and_children (glyf, gid, all_gids_to_retain);
}
hb_set_destroy (initial_gids_to_retain);
glyphs->alloc (all_gids_to_retain->get_population ());
gid = HB_SET_VALUE_INVALID;
while (all_gids_to_retain->next (&gid))
{
glyphs->push (gid);
}
hb_set_destroy (all_gids_to_retain); hb_set_destroy (all_gids_to_retain);
glyf.fini (); glyf.fini ();
cmap.fini (); cmap.fini ();
} }
static void
_create_old_gid_to_new_gid_map (const hb_vector_t<hb_codepoint_t> &glyphs,
hb_map_t *glyph_map)
{
for (unsigned int i = 0; i < glyphs.len; i++) {
glyph_map->set (glyphs[i], i);
}
}
/** /**
* hb_subset_plan_create: * hb_subset_plan_create:
* Computes a plan for subsetting the supplied face according * Computes a plan for subsetting the supplied face according
@ -188,18 +132,21 @@ hb_subset_plan_create (hb_face_t *face,
{ {
hb_subset_plan_t *plan = hb_object_create<hb_subset_plan_t> (); hb_subset_plan_t *plan = hb_object_create<hb_subset_plan_t> ();
plan->codepoints.init(); plan->drop_hints = input->drop_hints;
plan->gids_to_retain.init(); plan->unicodes = hb_set_create();
plan->gids_to_retain_sorted.init(); plan->glyphs.init();
plan->source = hb_face_reference (face); plan->source = hb_face_reference (face);
plan->dest = hb_subset_face_create (); plan->dest = hb_subset_face_create ();
plan->drop_hints = input->drop_hints; plan->codepoint_to_glyph = hb_map_create();
plan->glyph_map = hb_map_create();
_populate_codepoints (input->unicodes, plan->codepoints);
_populate_gids_to_retain (face, _populate_gids_to_retain (face,
plan->codepoints, input->unicodes,
plan->gids_to_retain, plan->unicodes,
plan->gids_to_retain_sorted); plan->codepoint_to_glyph,
&plan->glyphs);
_create_old_gid_to_new_gid_map (plan->glyphs,
plan->glyph_map);
return plan; return plan;
} }
@ -214,12 +161,12 @@ hb_subset_plan_destroy (hb_subset_plan_t *plan)
{ {
if (!hb_object_destroy (plan)) return; if (!hb_object_destroy (plan)) return;
plan->codepoints.fini (); hb_set_destroy (plan->unicodes);
plan->gids_to_retain.fini (); plan->glyphs.fini();
plan->gids_to_retain_sorted.fini ();
hb_face_destroy (plan->source); hb_face_destroy (plan->source);
hb_face_destroy (plan->dest); hb_face_destroy (plan->dest);
hb_map_destroy (plan->codepoint_to_glyph);
hb_map_destroy (plan->glyph_map);
free (plan); free (plan);
} }

View File

@ -30,8 +30,10 @@
#include "hb-private.hh" #include "hb-private.hh"
#include "hb-subset.h" #include "hb-subset.h"
#include "hb-subset-private.hh"
#include "hb-object-private.hh" #include "hb-object-private.hh"
#include "hb-map-private.hh"
struct hb_subset_plan_t { struct hb_subset_plan_t {
hb_object_header_t header; hb_object_header_t header;
@ -39,22 +41,55 @@ struct hb_subset_plan_t {
hb_bool_t drop_hints; hb_bool_t drop_hints;
// TODO(Q1) actual map, drop this crap // For each cp that we'd like to retain maps to the corresponding gid.
// Look at me ma, I'm a poor mans map codepoint : new gid hb_set_t *unicodes;
// codepoints is sorted and aligned with gids_to_retain.
// These first two lists provide a mapping from cp -> gid
// As a result it does not list the full set of glyphs to retain.
hb_vector_t<hb_codepoint_t> codepoints;
hb_vector_t<hb_codepoint_t> gids_to_retain;
// This list contains the complete set of glyphs to retain and may contain // This list contains the complete set of glyphs to retain and may contain
// more glyphs then the lists above. // more glyphs then the lists above.
hb_vector_t<hb_codepoint_t> gids_to_retain_sorted; hb_vector_t<hb_codepoint_t> glyphs;
hb_map_t *codepoint_to_glyph;
hb_map_t *glyph_map;
// Plan is only good for a specific source/dest so keep them with it // Plan is only good for a specific source/dest so keep them with it
hb_face_t *source; hb_face_t *source;
hb_face_t *dest; hb_face_t *dest;
inline hb_bool_t
new_gid_for_codepoint (hb_codepoint_t codepoint,
hb_codepoint_t *new_gid) const
{
hb_codepoint_t old_gid = codepoint_to_glyph->get (codepoint);
if (old_gid == HB_MAP_VALUE_INVALID)
return false;
return new_gid_for_old_gid (old_gid, new_gid);
}
inline hb_bool_t
new_gid_for_old_gid (hb_codepoint_t old_gid,
hb_codepoint_t *new_gid) const
{
hb_codepoint_t gid = glyph_map->get (old_gid);
if (gid == HB_MAP_VALUE_INVALID)
return false;
*new_gid = gid;
return true;
}
inline hb_bool_t
add_table (hb_tag_t tag,
hb_blob_t *contents)
{
hb_blob_t *source_blob = source->reference_table (tag);
DEBUG_MSG(SUBSET, nullptr, "add table %c%c%c%c, dest %d bytes, source %d bytes",
HB_UNTAG(tag),
hb_blob_get_length (contents),
hb_blob_get_length (source_blob));
hb_blob_destroy (source_blob);
return hb_subset_face_add_table(dest, tag, contents);
}
}; };
typedef struct hb_subset_plan_t hb_subset_plan_t; typedef struct hb_subset_plan_t hb_subset_plan_t;
@ -64,21 +99,6 @@ hb_subset_plan_create (hb_face_t *face,
hb_subset_profile_t *profile, hb_subset_profile_t *profile,
hb_subset_input_t *input); hb_subset_input_t *input);
HB_INTERNAL hb_bool_t
hb_subset_plan_new_gid_for_old_id (const hb_subset_plan_t *plan,
hb_codepoint_t old_gid,
hb_codepoint_t *new_gid /* OUT */);
HB_INTERNAL hb_bool_t
hb_subset_plan_new_gid_for_codepoint (const hb_subset_plan_t *plan,
hb_codepoint_t codepont,
hb_codepoint_t *new_gid /* OUT */);
HB_INTERNAL hb_bool_t
hb_subset_plan_add_table (hb_subset_plan_t *plan,
hb_tag_t tag,
hb_blob_t *contents);
HB_INTERNAL void HB_INTERNAL void
hb_subset_plan_destroy (hb_subset_plan_t *plan); hb_subset_plan_destroy (hb_subset_plan_t *plan);

View File

@ -281,7 +281,7 @@ _subset_table (hb_subset_plan_t *plan,
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))
result = hb_subset_plan_add_table(plan, tag, source_table); result = plan->add_table(tag, source_table);
else else
result = false; result = false;
hb_blob_destroy (source_table); hb_blob_destroy (source_table);