Add retain_gids option to subset input. Update glyf and loca handling to respect retain_gids.

This commit is contained in:
Garret Rieger 2019-01-17 18:55:56 -08:00
parent fe53292310
commit b7f971884e
5 changed files with 74 additions and 13 deletions

View File

@ -32,6 +32,7 @@
static bool
_calculate_glyf_and_loca_prime_size (const OT::glyf::accelerator_t &glyf,
hb_vector_t<hb_codepoint_t> &glyph_ids,
const hb_map_t *glyph_map,
hb_bool_t drop_hints,
bool *use_short_loca /* OUT */,
unsigned int *glyf_size /* OUT */,
@ -39,9 +40,12 @@ _calculate_glyf_and_loca_prime_size (const OT::glyf::accelerator_t &glyf,
hb_vector_t<unsigned int> *instruction_ranges /* OUT */)
{
unsigned int total = 0;
hb_codepoint_t max_new_gid = 0;
for (unsigned int i = 0; i < glyph_ids.length; i++)
{
hb_codepoint_t next_glyph = glyph_ids[i];
hb_codepoint_t next_glyph_new_gid = glyph_map->get (next_glyph);
max_new_gid = MAX (max_new_gid, next_glyph_new_gid);
if (!instruction_ranges->resize (instruction_ranges->length + 2))
{
DEBUG_MSG(SUBSET, nullptr, "Failed to resize instruction_ranges.");
@ -79,7 +83,7 @@ _calculate_glyf_and_loca_prime_size (const OT::glyf::accelerator_t &glyf,
*glyf_size = total;
*use_short_loca = (total <= 131070);
*loca_size = (glyph_ids.length + 1)
*loca_size = (max_new_gid + 2)
* (*use_short_loca ? sizeof (OT::HBUINT16) : sizeof (OT::HBUINT32));
DEBUG_MSG(SUBSET, nullptr, "preparing to subset glyf: final size %d, loca size %d, using %s loca",
@ -117,9 +121,9 @@ _write_loca_entry (unsigned int id,
}
static void
_update_components (hb_subset_plan_t * plan,
char * glyph_start,
unsigned int length)
_update_components (const hb_subset_plan_t *plan,
char *glyph_start,
unsigned int length)
{
OT::glyf::CompositeGlyphHeader::Iterator iterator;
if (OT::glyf::CompositeGlyphHeader::get_iterator (glyph_start,
@ -153,22 +157,37 @@ static bool _remove_composite_instruction_flag (char *glyf_prime, unsigned int l
}
static bool
_write_glyf_and_loca_prime (hb_subset_plan_t *plan,
_write_glyf_and_loca_prime (const hb_subset_plan_t *plan,
const OT::glyf::accelerator_t &glyf,
const char *glyf_data,
bool use_short_loca,
hb_vector_t<unsigned int> &instruction_ranges,
hb_vector_t<unsigned int> &instruction_ranges,
unsigned int glyf_prime_size,
char *glyf_prime_data /* OUT */,
unsigned int loca_prime_size,
char *loca_prime_data /* OUT */)
{
hb_vector_t<hb_codepoint_t> &glyph_ids = plan->glyphs;
const hb_vector_t<hb_codepoint_t> &glyph_ids = plan->glyphs;
const hb_map_t *glyph_map = plan->glyph_map;
char *glyf_prime_data_next = glyf_prime_data;
bool success = true;
hb_codepoint_t gid = 0;
for (unsigned int i = 0; i < glyph_ids.length; i++)
{
while (gid < glyph_map->get (glyph_ids[i]))
{
// If we are retaining existing gids then there will potentially be gaps
// in the loca table between glyphs. Fill in this gap with glyphs that have
// no outlines.
success = success && _write_loca_entry (gid,
glyf_prime_data_next - glyf_prime_data,
use_short_loca,
loca_prime_data,
loca_prime_size);
gid++;
}
unsigned int start_offset, end_offset;
if (unlikely (!(glyf.get_offsets (glyph_ids[i], &start_offset, &end_offset) &&
glyf.remove_padding (start_offset, &end_offset))))
@ -204,7 +223,7 @@ _write_glyf_and_loca_prime (hb_subset_plan_t *plan,
memset (glyf_prime_data_next + instruction_start - start_offset - 2, 0, 2);
}
success = success && _write_loca_entry (i,
success = success && _write_loca_entry (gid,
glyf_prime_data_next - glyf_prime_data,
use_short_loca,
loca_prime_data,
@ -213,9 +232,10 @@ _write_glyf_and_loca_prime (hb_subset_plan_t *plan,
// TODO: don't align to two bytes if using long loca.
glyf_prime_data_next += length + (length % 2); // Align to 2 bytes for short loca.
gid++;
}
success = success && _write_loca_entry (glyph_ids.length,
success = success && _write_loca_entry (gid,
glyf_prime_data_next - glyf_prime_data,
use_short_loca,
loca_prime_data,
@ -241,6 +261,7 @@ _hb_subset_glyf_and_loca (const OT::glyf::accelerator_t &glyf,
if (unlikely (!_calculate_glyf_and_loca_prime_size (glyf,
glyphs_to_retain,
plan->glyph_map,
plan->drop_hints,
use_short_loca,
&glyf_prime_size,

View File

@ -44,7 +44,10 @@ hb_subset_input_create_or_fail ()
input->unicodes = hb_set_create ();
input->glyphs = hb_set_create ();
input->drop_hints = false;
input->drop_layout = true;
input->desubroutinize = false;
input->retain_gids = false;
return input;
}
@ -144,3 +147,27 @@ hb_subset_input_get_desubroutinize (hb_subset_input_t *subset_input)
{
return subset_input->desubroutinize;
}
/**
* hb_subset_input_set_retain_gids:
* @subset_input: a subset_input.
* @retain_gids: If true the subsetter will not renumber glyph ids.
* Since: REPLACEME
**/
HB_EXTERN void
hb_subset_input_set_retain_gids (hb_subset_input_t *subset_input,
hb_bool_t retain_gids)
{
subset_input->retain_gids = retain_gids;
}
/**
* hb_subset_input_get_retain_gids:
* Returns: value of retain_gids.
* Since: REPLACEME
**/
HB_EXTERN hb_bool_t
hb_subset_input_get_retain_gids (hb_subset_input_t *subset_input)
{
return subset_input->retain_gids;
}

View File

@ -44,6 +44,7 @@ struct hb_subset_input_t
bool drop_hints : 1;
bool drop_layout : 1;
bool desubroutinize : 1;
bool retain_gids : 1;
/* TODO
*
* features

View File

@ -156,11 +156,15 @@ _populate_gids_to_retain (hb_face_t *face,
}
static void
_create_old_gid_to_new_gid_map (const hb_vector_t<hb_codepoint_t> &glyphs,
hb_map_t *glyph_map)
_create_old_gid_to_new_gid_map (bool retain_gids,
const hb_vector_t<hb_codepoint_t> &glyphs,
hb_map_t *glyph_map)
{
for (unsigned int i = 0; i < glyphs.length; i++) {
glyph_map->set (glyphs[i], i);
if (!retain_gids)
glyph_map->set (glyphs[i], i);
else
glyph_map->set (glyphs[i], glyphs[i]);
}
}
@ -195,7 +199,9 @@ hb_subset_plan_create (hb_face_t *face,
plan->unicodes,
plan->codepoint_to_glyph,
&plan->glyphs);
_create_old_gid_to_new_gid_map (plan->glyphs,
_create_old_gid_to_new_gid_map (input->retain_gids,
plan->glyphs,
plan->glyph_map);
return plan;

View File

@ -72,6 +72,12 @@ hb_subset_input_set_desubroutinize (hb_subset_input_t *subset_input,
HB_EXTERN hb_bool_t
hb_subset_input_get_desubroutinize (hb_subset_input_t *subset_input);
HB_EXTERN void
hb_subset_input_set_retain_gids (hb_subset_input_t *subset_input,
hb_bool_t retain_gids);
HB_EXTERN hb_bool_t
hb_subset_input_get_retain_gids (hb_subset_input_t *subset_input);
/* hb_subset () */
HB_EXTERN hb_face_t *
hb_subset (hb_face_t *source, hb_subset_input_t *input);