[subset] Glyf by iter now runs but fails tests

This commit is contained in:
Rod Sheeter 2019-05-09 22:12:20 -07:00
parent f8de063b48
commit ab3fe5de2b
1 changed files with 59 additions and 29 deletions

View File

@ -80,20 +80,35 @@ struct glyf
return_trace (true); return_trace (true);
} }
template<typename Iterator, typename EntryType>
static void
_write_loca (Iterator it, unsigned size_denom, char * loca_data)
{
unsigned int offset = 0;
+ it
| hb_apply ([&] (hb_bytes_t _) {
offset += _.length / size_denom;
EntryType *entry = (EntryType *) loca_data;
*entry = offset;
loca_data += entry->get_size();
});
EntryType *entry = (EntryType *) loca_data;
*entry = offset;
}
template <typename Iterator> template <typename Iterator>
bool serialize(hb_serialize_context_t *c, bool serialize(hb_serialize_context_t *c,
Iterator it) Iterator it)
{ {
TRACE_SERIALIZE (this); TRACE_SERIALIZE (this);
// pad glyphs to 2-byte boundaries to permit short loca // pad glyphs to 2-byte boundaries to permit short loca
HBUINT8 pad; HBUINT8 pad;
+ it + it
| hb_apply ( [&] (hb_bytes_t glyph) { | hb_apply ( [&] (hb_bytes_t glyph) {
glyph.copy(c); glyph.copy(c);
if (glyph.length % 2) c->extend(pad); if (glyph.length % 2) c->embed(pad);
}); });
return_trace (true); return_trace (true);
} }
@ -107,20 +122,22 @@ struct glyf
OT::glyf::accelerator_t glyf; OT::glyf::accelerator_t glyf;
glyf.init (c->plan->source); glyf.init (c->plan->source);
// stream new-gids => glyph to keep // make an iterator of per-glyph hb_bytes_t.
// if dropping hints the glyph to keep doesn't have them anymore // unpadded, hints removed if that was requested.
unsigned int glyf_padded_size = 0; //
auto it = auto it =
+ hb_iota (c->plan->num_output_glyphs ()) + hb_range (c->plan->num_output_glyphs ())
| hb_map ([&] (hb_codepoint_t new_gid) { | hb_map ([&] (hb_codepoint_t new_gid) {
hb_codepoint_t old_gid; hb_codepoint_t old_gid;
// should never happen fail, ALL old gids should be mapped
// should never fail, ALL old gids should be mapped
if (!c->plan->old_gid_for_new_gid (new_gid, &old_gid)) return hb_bytes_t (); if (!c->plan->old_gid_for_new_gid (new_gid, &old_gid)) return hb_bytes_t ();
unsigned int start_offset, end_offset; unsigned int start_offset, end_offset;
if (unlikely (!(glyf.get_offsets (old_gid, &start_offset, &end_offset) && if (unlikely (!(glyf.get_offsets (old_gid, &start_offset, &end_offset) &&
glyf.remove_padding (start_offset, &end_offset)))) glyf.remove_padding (start_offset, &end_offset))))
{ {
// TODO signal irreversible error // TODO signal fatal error
return hb_bytes_t (); return hb_bytes_t ();
} }
hb_bytes_t glyph ((const char *) this, end_offset - start_offset); hb_bytes_t glyph ((const char *) this, end_offset - start_offset);
@ -130,30 +147,43 @@ struct glyf
unsigned int instruction_length; unsigned int instruction_length;
if (!glyf.get_instruction_length (glyph, &instruction_length)) if (!glyf.get_instruction_length (glyph, &instruction_length))
{ {
// TODO signal irreversible failure // TODO signal fatal error
return hb_bytes_t (); return hb_bytes_t ();
} }
glyph = hb_bytes_t (&glyph, glyph.length - instruction_length); glyph = hb_bytes_t (&glyph, glyph.length - instruction_length);
} }
glyf_padded_size += glyph.length + glyph.length % 2;
return glyph; return glyph;
}); });
glyf_prime->serialize (c->serializer, it); glyf_prime->serialize (c->serializer, it);
// we know enough to write loca // TODO whats the right way to serialize loca?
// TODO calculate size, do we need two or four byte loca entries // _subset2 will think these bytes are part of glyf if we write to serializer
unsigned int offset = 0; bool use_short_loca = glyf_padded_size > 131070;
HBUINT16 loca_entry; unsigned int loca_prime_size = (c->plan->num_output_glyphs () + 1) * (use_short_loca ? 2 : 4);
loca *loca_prime = c->serializer->start_embed <loca> (); char *loca_prime_data = (char *) calloc(1, loca_prime_size);
+ hb_enumerate (it)
| hb_apply ([&] (hb_pair_t<unsigned, hb_bytes_t> p) { if (use_short_loca)
offset += p.second.length; {
loca_entry = offset / 2; _write_loca <decltype (it), HBUINT16> (it, 2, loca_prime_data);
c->serializer->embed(loca_entry); }
}); else
// one for the road {
c->serializer->embed(loca_entry); _write_loca <decltype (it), HBUINT32> (it, 1, loca_prime_data);
}
hb_blob_t * loca_blob = hb_blob_create (loca_prime_data,
loca_prime_size,
HB_MEMORY_MODE_READONLY,
loca_prime_data,
free);
if (unlikely (! (c->plan->add_table (HB_OT_TAG_loca, loca_blob)
&& _add_head_and_set_loca_version(c->plan, use_short_loca))))
{
// TODO signal fatal error
return false;
}
return_trace (true); return_trace (true);
} }