[subset] Dinner time, checkpoint
This commit is contained in:
parent
723d054dcb
commit
8f174870e9
|
@ -86,9 +86,13 @@ struct glyf
|
||||||
{
|
{
|
||||||
TRACE_SERIALIZE (this);
|
TRACE_SERIALIZE (this);
|
||||||
|
|
||||||
// TODO actually copy glyph
|
// pad glyphs to 2-byte boundaries to permit short loca
|
||||||
// TODO worry about instructions
|
HBUINT8 pad;
|
||||||
// TODO capture dest locations for loca
|
+ it
|
||||||
|
| hb_apply ( [&] (hb_bytes_t glyph) {
|
||||||
|
glyph.copy(c);
|
||||||
|
if (glyph.length % 2) c->extend(pad);
|
||||||
|
});
|
||||||
|
|
||||||
return_trace (true);
|
return_trace (true);
|
||||||
}
|
}
|
||||||
|
@ -103,32 +107,54 @@ 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 => pair of start/end offsets
|
// stream new-gids => glyph to keep
|
||||||
// can now copy glyph from <prev>=>end
|
// if dropping hints the glyph to keep doesn't have them anymore
|
||||||
// TODO(instructions)
|
|
||||||
auto it =
|
auto it =
|
||||||
+ hb_iota (c->plan->num_output_glyphs ())
|
+ hb_iota (c->plan->num_output_glyphs ())
|
||||||
| hb_map ([&] (hb_codepoint_t new_gid) {
|
| hb_map ([&] (hb_codepoint_t new_gid) {
|
||||||
unsigned int start_offset = 0, end_offset = 0;
|
|
||||||
|
|
||||||
hb_codepoint_t old_gid;
|
hb_codepoint_t old_gid;
|
||||||
// should never happen, ALL old gids should be mapped
|
// should never happen fail, ALL old gids should be mapped
|
||||||
if (!c->plan->old_gid_for_new_gid (new_gid, &old_gid)) return hb_pair (start_offset, end_offset);
|
if (!c->plan->old_gid_for_new_gid (new_gid, &old_gid)) return hb_bytes_t ();
|
||||||
|
|
||||||
// being empty is perfectly normal
|
|
||||||
if (c->plan->is_empty_glyph (old_gid)) return hb_pair (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 irreversible error
|
||||||
return hb_pair (start_offset, end_offset);
|
return hb_bytes_t ();
|
||||||
}
|
}
|
||||||
return hb_pair (start_offset, end_offset);
|
hb_bytes_t glyph ((const char *) this, end_offset - start_offset);
|
||||||
|
|
||||||
|
// if dropping hints, find hints region and subtract it
|
||||||
|
if (c->plan->drop_hints) {
|
||||||
|
unsigned int instruction_length;
|
||||||
|
if (!glyf.get_instruction_length (glyph, &instruction_length))
|
||||||
|
{
|
||||||
|
// TODO signal irreversible failure
|
||||||
|
return hb_bytes_t ();
|
||||||
|
}
|
||||||
|
glyph = hb_bytes_t (&glyph, glyph.length - instruction_length);
|
||||||
|
}
|
||||||
|
|
||||||
|
return glyph;
|
||||||
});
|
});
|
||||||
|
|
||||||
glyf_prime->serialize (c->serializer, it);
|
glyf_prime->serialize (c->serializer, it);
|
||||||
|
|
||||||
|
// we know enough to write loca
|
||||||
|
// TODO calculate size, do we need two or four byte loca entries
|
||||||
|
unsigned int offset = 0;
|
||||||
|
HBUINT16 loca_entry;
|
||||||
|
loca *loca_prime = c->serializer->start_embed <loca> ();
|
||||||
|
+ hb_enumerate (it)
|
||||||
|
| hb_apply ([&] (hb_pair_t<unsigned, hb_bytes_t> p) {
|
||||||
|
offset += p.second.length;
|
||||||
|
loca_entry = offset / 2;
|
||||||
|
c->serializer->embed(loca_entry);
|
||||||
|
});
|
||||||
|
// one for the road
|
||||||
|
c->serializer->embed(loca_entry);
|
||||||
|
|
||||||
return_trace (true);
|
return_trace (true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -412,45 +438,40 @@ struct glyf
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool get_instruction_offsets (unsigned int start_offset,
|
bool get_instruction_length (hb_bytes_t glyph,
|
||||||
unsigned int end_offset,
|
unsigned int * length /* OUT */) const
|
||||||
unsigned int *instruction_start /* OUT */,
|
|
||||||
unsigned int *instruction_end /* OUT */) const
|
|
||||||
{
|
{
|
||||||
if (end_offset - start_offset < GlyphHeader::static_size)
|
/* Empty glyph; no instructions. */
|
||||||
|
if (glyph.get_size() < GlyphHeader::static_size)
|
||||||
{
|
{
|
||||||
*instruction_start = 0;
|
*length = 0;
|
||||||
*instruction_end = 0;
|
return true;
|
||||||
return true; /* Empty glyph; no instructions. */
|
|
||||||
}
|
}
|
||||||
const GlyphHeader &glyph_header = StructAtOffset<GlyphHeader> (glyf_table, start_offset);
|
unsigned int start = glyph.length;
|
||||||
|
unsigned int end = glyph.length;
|
||||||
|
const GlyphHeader &glyph_header = StructAtOffset<GlyphHeader> (&glyph, 0);
|
||||||
int16_t num_contours = (int16_t) glyph_header.numberOfContours;
|
int16_t num_contours = (int16_t) glyph_header.numberOfContours;
|
||||||
if (num_contours < 0)
|
if (num_contours < 0)
|
||||||
{
|
{
|
||||||
CompositeGlyphHeader::Iterator composite_it;
|
CompositeGlyphHeader::Iterator composite_it;
|
||||||
if (unlikely (!CompositeGlyphHeader::get_iterator (
|
if (unlikely (!CompositeGlyphHeader::get_iterator (&glyph, glyph.length, &composite_it))) return false;
|
||||||
(const char*) this->glyf_table + start_offset,
|
|
||||||
end_offset - start_offset, &composite_it))) return false;
|
|
||||||
const CompositeGlyphHeader *last;
|
const CompositeGlyphHeader *last;
|
||||||
do {
|
do {
|
||||||
last = composite_it.current;
|
last = composite_it.current;
|
||||||
} while (composite_it.move_to_next ());
|
} while (composite_it.move_to_next ());
|
||||||
|
|
||||||
if ((uint16_t) last->flags & CompositeGlyphHeader::WE_HAVE_INSTRUCTIONS)
|
if ((uint16_t) last->flags & CompositeGlyphHeader::WE_HAVE_INSTRUCTIONS)
|
||||||
*instruction_start = ((char *) last - (char *) glyf_table->dataZ.arrayZ) + last->get_size ();
|
start = ((char *) last - (char *) glyf_table->dataZ.arrayZ) + last->get_size ();
|
||||||
else
|
if (unlikely (start > end))
|
||||||
*instruction_start = end_offset;
|
|
||||||
*instruction_end = end_offset;
|
|
||||||
if (unlikely (*instruction_start > *instruction_end))
|
|
||||||
{
|
{
|
||||||
DEBUG_MSG(SUBSET, nullptr, "Invalid instruction offset, %d is outside [%d, %d]", *instruction_start, start_offset, end_offset);
|
DEBUG_MSG(SUBSET, nullptr, "Invalid instruction offset, %d is outside %d byte buffer", start, glyph.length);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
unsigned int instruction_length_offset = start_offset + GlyphHeader::static_size + 2 * num_contours;
|
unsigned int instruction_length_offset = GlyphHeader::static_size + 2 * num_contours;
|
||||||
if (unlikely (instruction_length_offset + 2 > end_offset))
|
if (unlikely (instruction_length_offset + 2 > glyph.length))
|
||||||
{
|
{
|
||||||
DEBUG_MSG(SUBSET, nullptr, "Glyph size is too short, missing field instructionLength.");
|
DEBUG_MSG(SUBSET, nullptr, "Glyph size is too short, missing field instructionLength.");
|
||||||
return false;
|
return false;
|
||||||
|
@ -459,15 +480,13 @@ struct glyf
|
||||||
const HBUINT16 &instruction_length = StructAtOffset<HBUINT16> (glyf_table, instruction_length_offset);
|
const HBUINT16 &instruction_length = StructAtOffset<HBUINT16> (glyf_table, instruction_length_offset);
|
||||||
unsigned int start = instruction_length_offset + 2;
|
unsigned int start = instruction_length_offset + 2;
|
||||||
unsigned int end = start + (uint16_t) instruction_length;
|
unsigned int end = start + (uint16_t) instruction_length;
|
||||||
if (unlikely (end > end_offset)) // Out of bounds of the current glyph
|
if (unlikely (end > glyph.length)) // Out of bounds of the current glyph
|
||||||
{
|
{
|
||||||
DEBUG_MSG(SUBSET, nullptr, "The instructions array overruns the glyph's boundaries.");
|
DEBUG_MSG(SUBSET, nullptr, "The instructions array overruns the glyph's boundaries.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
*instruction_start = start;
|
|
||||||
*instruction_end = end;
|
|
||||||
}
|
}
|
||||||
|
*length = end - start;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue