Add retain_gids option to subset input. Update glyf and loca handling to respect retain_gids.
This commit is contained in:
parent
fe53292310
commit
b7f971884e
|
@ -32,6 +32,7 @@
|
||||||
static bool
|
static bool
|
||||||
_calculate_glyf_and_loca_prime_size (const OT::glyf::accelerator_t &glyf,
|
_calculate_glyf_and_loca_prime_size (const OT::glyf::accelerator_t &glyf,
|
||||||
hb_vector_t<hb_codepoint_t> &glyph_ids,
|
hb_vector_t<hb_codepoint_t> &glyph_ids,
|
||||||
|
const hb_map_t *glyph_map,
|
||||||
hb_bool_t drop_hints,
|
hb_bool_t drop_hints,
|
||||||
bool *use_short_loca /* OUT */,
|
bool *use_short_loca /* OUT */,
|
||||||
unsigned int *glyf_size /* 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 */)
|
hb_vector_t<unsigned int> *instruction_ranges /* OUT */)
|
||||||
{
|
{
|
||||||
unsigned int total = 0;
|
unsigned int total = 0;
|
||||||
|
hb_codepoint_t max_new_gid = 0;
|
||||||
for (unsigned int i = 0; i < glyph_ids.length; i++)
|
for (unsigned int i = 0; i < glyph_ids.length; i++)
|
||||||
{
|
{
|
||||||
hb_codepoint_t next_glyph = glyph_ids[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))
|
if (!instruction_ranges->resize (instruction_ranges->length + 2))
|
||||||
{
|
{
|
||||||
DEBUG_MSG(SUBSET, nullptr, "Failed to resize instruction_ranges.");
|
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;
|
*glyf_size = total;
|
||||||
*use_short_loca = (total <= 131070);
|
*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));
|
* (*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",
|
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
|
static void
|
||||||
_update_components (hb_subset_plan_t * plan,
|
_update_components (const hb_subset_plan_t *plan,
|
||||||
char * glyph_start,
|
char *glyph_start,
|
||||||
unsigned int length)
|
unsigned int length)
|
||||||
{
|
{
|
||||||
OT::glyf::CompositeGlyphHeader::Iterator iterator;
|
OT::glyf::CompositeGlyphHeader::Iterator iterator;
|
||||||
if (OT::glyf::CompositeGlyphHeader::get_iterator (glyph_start,
|
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
|
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 OT::glyf::accelerator_t &glyf,
|
||||||
const char *glyf_data,
|
const char *glyf_data,
|
||||||
bool use_short_loca,
|
bool use_short_loca,
|
||||||
hb_vector_t<unsigned int> &instruction_ranges,
|
hb_vector_t<unsigned int> &instruction_ranges,
|
||||||
unsigned int glyf_prime_size,
|
unsigned int glyf_prime_size,
|
||||||
char *glyf_prime_data /* OUT */,
|
char *glyf_prime_data /* OUT */,
|
||||||
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->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;
|
char *glyf_prime_data_next = glyf_prime_data;
|
||||||
|
|
||||||
bool success = true;
|
bool success = true;
|
||||||
|
hb_codepoint_t gid = 0;
|
||||||
for (unsigned int i = 0; i < glyph_ids.length; i++)
|
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;
|
unsigned int start_offset, end_offset;
|
||||||
if (unlikely (!(glyf.get_offsets (glyph_ids[i], &start_offset, &end_offset) &&
|
if (unlikely (!(glyf.get_offsets (glyph_ids[i], &start_offset, &end_offset) &&
|
||||||
glyf.remove_padding (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);
|
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,
|
glyf_prime_data_next - glyf_prime_data,
|
||||||
use_short_loca,
|
use_short_loca,
|
||||||
loca_prime_data,
|
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.
|
// 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.
|
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,
|
glyf_prime_data_next - glyf_prime_data,
|
||||||
use_short_loca,
|
use_short_loca,
|
||||||
loca_prime_data,
|
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,
|
if (unlikely (!_calculate_glyf_and_loca_prime_size (glyf,
|
||||||
glyphs_to_retain,
|
glyphs_to_retain,
|
||||||
|
plan->glyph_map,
|
||||||
plan->drop_hints,
|
plan->drop_hints,
|
||||||
use_short_loca,
|
use_short_loca,
|
||||||
&glyf_prime_size,
|
&glyf_prime_size,
|
||||||
|
|
|
@ -44,7 +44,10 @@ hb_subset_input_create_or_fail ()
|
||||||
|
|
||||||
input->unicodes = hb_set_create ();
|
input->unicodes = hb_set_create ();
|
||||||
input->glyphs = hb_set_create ();
|
input->glyphs = hb_set_create ();
|
||||||
|
input->drop_hints = false;
|
||||||
input->drop_layout = true;
|
input->drop_layout = true;
|
||||||
|
input->desubroutinize = false;
|
||||||
|
input->retain_gids = false;
|
||||||
|
|
||||||
return input;
|
return input;
|
||||||
}
|
}
|
||||||
|
@ -144,3 +147,27 @@ hb_subset_input_get_desubroutinize (hb_subset_input_t *subset_input)
|
||||||
{
|
{
|
||||||
return subset_input->desubroutinize;
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -44,6 +44,7 @@ struct hb_subset_input_t
|
||||||
bool drop_hints : 1;
|
bool drop_hints : 1;
|
||||||
bool drop_layout : 1;
|
bool drop_layout : 1;
|
||||||
bool desubroutinize : 1;
|
bool desubroutinize : 1;
|
||||||
|
bool retain_gids : 1;
|
||||||
/* TODO
|
/* TODO
|
||||||
*
|
*
|
||||||
* features
|
* features
|
||||||
|
|
|
@ -156,11 +156,15 @@ _populate_gids_to_retain (hb_face_t *face,
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_create_old_gid_to_new_gid_map (const hb_vector_t<hb_codepoint_t> &glyphs,
|
_create_old_gid_to_new_gid_map (bool retain_gids,
|
||||||
hb_map_t *glyph_map)
|
const hb_vector_t<hb_codepoint_t> &glyphs,
|
||||||
|
hb_map_t *glyph_map)
|
||||||
{
|
{
|
||||||
for (unsigned int i = 0; i < glyphs.length; i++) {
|
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->unicodes,
|
||||||
plan->codepoint_to_glyph,
|
plan->codepoint_to_glyph,
|
||||||
&plan->glyphs);
|
&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);
|
plan->glyph_map);
|
||||||
|
|
||||||
return plan;
|
return plan;
|
||||||
|
|
|
@ -72,6 +72,12 @@ hb_subset_input_set_desubroutinize (hb_subset_input_t *subset_input,
|
||||||
HB_EXTERN hb_bool_t
|
HB_EXTERN hb_bool_t
|
||||||
hb_subset_input_get_desubroutinize (hb_subset_input_t *subset_input);
|
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_subset () */
|
||||||
HB_EXTERN hb_face_t *
|
HB_EXTERN hb_face_t *
|
||||||
hb_subset (hb_face_t *source, hb_subset_input_t *input);
|
hb_subset (hb_face_t *source, hb_subset_input_t *input);
|
||||||
|
|
Loading…
Reference in New Issue