[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
#include "hb-open-type-private.hh"
#include "hb-set-private.hh"
#include "hb-subset-plan.hh"
/*
@ -111,7 +112,7 @@ struct CmapSubtableFormat4
{
hb_codepoint_t cp = segments[i].start_code;
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);
id_delta[i].set (start_gid - segments[i].start_code);
} else {
@ -139,7 +140,7 @@ struct CmapSubtableFormat4
{
hb_codepoint_t cp = segments[i].start_code + j;
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);
glyph_id_array[j].set (new_gid);
}
@ -176,10 +177,11 @@ struct CmapSubtableFormat4
{
segment_plan *segment = nullptr;
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;
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);
return false;
@ -494,11 +496,11 @@ struct CmapSubtableFormat12 : CmapSubtableLongSegmented<CmapSubtableFormat12>
hb_vector_t<CmapSubtableLongGroup> *groups)
{
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;
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);
return false;
@ -882,7 +884,7 @@ struct cmap
HB_MEMORY_MODE_READONLY,
dest,
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);
return result;
}

View File

@ -88,9 +88,9 @@ struct glyf
bool success = true;
bool use_short_loca = false;
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 && hb_subset_plan_add_table (plan, HB_OT_TAG_loca, loca_prime);
success = success && _add_head_and_set_loca_version (plan->source, use_short_loca, plan->dest);
success = success && plan->add_table (HB_OT_TAG_glyf, glyf_prime);
success = success && plan->add_table (HB_OT_TAG_loca, loca_prime);
success = success && _add_head_and_set_loca_version (plan, use_short_loca);
} else {
success = false;
}
@ -101,9 +101,9 @@ struct glyf
}
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_destroy (head_blob);
@ -112,7 +112,7 @@ struct glyf
OT::head *head_prime = (OT::head *) hb_blob_get_data_writable (head_prime_blob, nullptr);
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);
return success;

View File

@ -59,13 +59,13 @@ struct DeviceRecord
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
{
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]);
@ -147,7 +147,7 @@ struct hdmx
this->version.set (source_hdmx->version);
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++)
{
@ -163,7 +163,7 @@ struct hdmx
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
@ -189,7 +189,7 @@ struct hdmx
HB_MEMORY_MODE_READONLY,
dest,
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);
return result;

View File

@ -81,7 +81,7 @@ struct hmtxvmtx
H *table = (H *) hb_blob_get_data (dest_blob, &length);
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);
return result;
@ -94,7 +94,7 @@ struct hmtxvmtx
/* All the trailing glyphs with the same advance can use one LongMetric
* 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 last_advance = _mtx.get_advance (gids[num_advances - 1]);
while (num_advances > 1
@ -178,7 +178,7 @@ struct hmtxvmtx
HB_MEMORY_MODE_READONLY,
dest,
free);
bool success = hb_subset_plan_add_table (plan, T::tableTag, result);
bool success = plan->add_table (T::tableTag, result);
hb_blob_destroy (result);
return success;
}

View File

@ -109,11 +109,11 @@ struct maxp
}
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)
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);
return result;
}

View File

@ -63,26 +63,25 @@ struct os2
}
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->usLastCharIndex.set (max_cp);
_update_unicode_ranges (plan->codepoints, os2_prime->ulUnicodeRange);
bool result = hb_subset_plan_add_table(plan, HB_OT_TAG_os2, os2_prime_blob);
_update_unicode_ranges (plan->unicodes, os2_prime->ulUnicodeRange);
bool result = plan->add_table (HB_OT_TAG_os2, os2_prime_blob);
hb_blob_destroy (os2_prime_blob);
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
{
for (unsigned int i = 0; i < 4; i++)
ulUnicodeRange[i].set (0);
for (unsigned int i = 0; i < codepoints.len; i++)
{
hb_codepoint_t cp = codepoints[i];
hb_codepoint_t cp = HB_SET_VALUE_INVALID;
while (codepoints->next (&cp)) {
unsigned int bit = hb_get_unicode_range_bit (cp);
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 *max_cp /* OUT */)
{
hb_codepoint_t min = -1, max = 0;
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;
*min_cp = codepoints->get_min ();
*max_cp = codepoints->get_max ();
}
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.
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);
return result;

View File

@ -130,9 +130,8 @@ _update_components (hb_subset_plan_t * plan,
do
{
hb_codepoint_t new_gid;
if (!hb_subset_plan_new_gid_for_old_id (plan,
iterator.current->glyphIndex,
&new_gid))
if (!plan->new_gid_for_old_gid (iterator.current->glyphIndex,
&new_gid))
continue;
((OT::glyf::CompositeGlyphHeader *) iterator.current)->glyphIndex.set (new_gid);
@ -165,7 +164,7 @@ _write_glyf_and_loca_prime (hb_subset_plan_t *plan,
unsigned int loca_prime_size,
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;
bool success = true;
@ -234,7 +233,7 @@ _hb_subset_glyf_and_loca (const OT::glyf::accelerator_t &glyf,
hb_blob_t **loca_prime /* OUT */)
{
// 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 loca_prime_size;

View File

@ -24,78 +24,14 @@
* Google Author(s): Garret Rieger, Roderick Sheeter
*/
#include "hb-map-private.hh"
#include "hb-subset-private.hh"
#include "hb-set-private.hh"
#include "hb-subset-plan.hh"
#include "hb-ot-cmap-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
_add_gid_and_children (const OT::glyf::accelerator_t &glyf,
hb_codepoint_t gid,
@ -119,58 +55,66 @@ _add_gid_and_children (const OT::glyf::accelerator_t &glyf,
static void
_populate_gids_to_retain (hb_face_t *face,
hb_vector_t<hb_codepoint_t>& codepoints,
hb_vector_t<hb_codepoint_t>& old_gids,
hb_vector_t<hb_codepoint_t>& old_gids_sorted)
const hb_set_t *unicodes,
hb_set_t *unicodes_to_retain,
hb_map_t *codepoint_to_glyph,
hb_vector_t<hb_codepoint_t> *glyphs)
{
OT::cmap::accelerator_t cmap;
OT::glyf::accelerator_t glyf;
cmap.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);
for (unsigned int i = 0; i < codepoints.len; i++)
hb_codepoint_t cp = HB_SET_VALUE_INVALID;
while (unicodes->next (&cp))
{
hb_codepoint_t gid;
if (!cmap.get_nominal_glyph (codepoints[i], &gid))
if (!cmap.get_nominal_glyph (cp, &gid))
{
gid = -1;
bad_indices.push (i);
DEBUG_MSG(SUBSET, nullptr, "Drop U+%04X; no gid", cp);
continue;
}
old_gids.push (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);
unicodes_to_retain->add (cp);
codepoint_to_glyph->set (cp, gid);
initial_gids_to_retain->add (gid);
}
// Populate a full set of glyphs to retain by adding all referenced
// composite glyphs.
// 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;
while (hb_set_next (all_gids_to_retain, &gid))
old_gids_sorted.push (gid);
hb_set_t *all_gids_to_retain = hb_set_create ();
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);
glyf.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:
* 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> ();
plan->codepoints.init();
plan->gids_to_retain.init();
plan->gids_to_retain_sorted.init();
plan->drop_hints = input->drop_hints;
plan->unicodes = hb_set_create();
plan->glyphs.init();
plan->source = hb_face_reference (face);
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,
plan->codepoints,
plan->gids_to_retain,
plan->gids_to_retain_sorted);
input->unicodes,
plan->unicodes,
plan->codepoint_to_glyph,
&plan->glyphs);
_create_old_gid_to_new_gid_map (plan->glyphs,
plan->glyph_map);
return plan;
}
@ -214,12 +161,12 @@ hb_subset_plan_destroy (hb_subset_plan_t *plan)
{
if (!hb_object_destroy (plan)) return;
plan->codepoints.fini ();
plan->gids_to_retain.fini ();
plan->gids_to_retain_sorted.fini ();
hb_set_destroy (plan->unicodes);
plan->glyphs.fini();
hb_face_destroy (plan->source);
hb_face_destroy (plan->dest);
hb_map_destroy (plan->codepoint_to_glyph);
hb_map_destroy (plan->glyph_map);
free (plan);
}

View File

@ -30,8 +30,10 @@
#include "hb-private.hh"
#include "hb-subset.h"
#include "hb-subset-private.hh"
#include "hb-object-private.hh"
#include "hb-map-private.hh"
struct hb_subset_plan_t {
hb_object_header_t header;
@ -39,22 +41,55 @@ struct hb_subset_plan_t {
hb_bool_t drop_hints;
// TODO(Q1) actual map, drop this crap
// Look at me ma, I'm a poor mans map codepoint : new gid
// 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;
// For each cp that we'd like to retain maps to the corresponding gid.
hb_set_t *unicodes;
// This list contains the complete set of glyphs to retain and may contain
// 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
hb_face_t *source;
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;
@ -64,21 +99,6 @@ hb_subset_plan_create (hb_face_t *face,
hb_subset_profile_t *profile,
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_subset_plan_destroy (hb_subset_plan_t *plan);

View File

@ -281,7 +281,7 @@ _subset_table (hb_subset_plan_t *plan,
default:
hb_blob_t *source_table = hb_face_reference_table(plan->source, tag);
if (likely (source_table))
result = hb_subset_plan_add_table(plan, tag, source_table);
result = plan->add_table(tag, source_table);
else
result = false;
hb_blob_destroy (source_table);