153 lines
4.1 KiB
C++
153 lines
4.1 KiB
C++
#ifndef OT_GLYF_SUBSETGLYPH_HH
|
|
#define OT_GLYF_SUBSETGLYPH_HH
|
|
|
|
|
|
#include "../../hb-open-type.hh"
|
|
|
|
|
|
namespace OT {
|
|
|
|
struct glyf_accelerator_t;
|
|
|
|
namespace glyf_impl {
|
|
|
|
|
|
struct SubsetGlyph
|
|
{
|
|
hb_codepoint_t old_gid;
|
|
Glyph source_glyph;
|
|
hb_bytes_t dest_start; /* region of source_glyph to copy first */
|
|
hb_bytes_t dest_end; /* region of source_glyph to copy second */
|
|
bool allocated;
|
|
|
|
bool serialize (hb_serialize_context_t *c,
|
|
bool use_short_loca,
|
|
const hb_subset_plan_t *plan)
|
|
{
|
|
TRACE_SERIALIZE (this);
|
|
|
|
hb_bytes_t dest_glyph = dest_start.copy (c);
|
|
hb_bytes_t end_copy = dest_end.copy (c);
|
|
if (!end_copy.arrayZ || !dest_glyph.arrayZ) {
|
|
return false;
|
|
}
|
|
|
|
dest_glyph = hb_bytes_t (&dest_glyph, dest_glyph.length + end_copy.length);
|
|
unsigned int pad_length = use_short_loca ? padding () : 0;
|
|
DEBUG_MSG (SUBSET, nullptr, "serialize %u byte glyph, width %u pad %u", dest_glyph.length, dest_glyph.length + pad_length, pad_length);
|
|
|
|
HBUINT8 pad;
|
|
pad = 0;
|
|
while (pad_length > 0)
|
|
{
|
|
c->embed (pad);
|
|
pad_length--;
|
|
}
|
|
|
|
if (unlikely (!dest_glyph.length)) return_trace (true);
|
|
|
|
/* update components gids. */
|
|
for (auto &_ : Glyph (dest_glyph).get_composite_iterator ())
|
|
{
|
|
hb_codepoint_t new_gid;
|
|
if (plan->new_gid_for_old_gid (_.get_gid(), &new_gid))
|
|
const_cast<CompositeGlyphRecord &> (_).set_gid (new_gid);
|
|
}
|
|
#ifndef HB_NO_VAR_COMPOSITES
|
|
for (auto &_ : Glyph (dest_glyph).get_var_composite_iterator ())
|
|
{
|
|
hb_codepoint_t new_gid;
|
|
if (plan->new_gid_for_old_gid (_.get_gid(), &new_gid))
|
|
const_cast<VarCompositeGlyphRecord &> (_).set_gid (new_gid);
|
|
}
|
|
#endif
|
|
|
|
#ifndef HB_NO_BEYOND_64K
|
|
auto it = Glyph (dest_glyph).get_composite_iterator ();
|
|
if (it)
|
|
{
|
|
/* lower GID24 to GID16 in components if possible.
|
|
*
|
|
* TODO: VarComposite. Not as critical, since VarComposite supports
|
|
* gid24 from the first version. */
|
|
char *p = it ? (char *) &*it : nullptr;
|
|
char *q = p;
|
|
const char *end = dest_glyph.arrayZ + dest_glyph.length;
|
|
while (it)
|
|
{
|
|
auto &rec = const_cast<CompositeGlyphRecord &> (*it);
|
|
++it;
|
|
|
|
q += rec.get_size ();
|
|
|
|
rec.lower_gid_24_to_16 ();
|
|
|
|
unsigned size = rec.get_size ();
|
|
|
|
memmove (p, &rec, size);
|
|
|
|
p += size;
|
|
}
|
|
memmove (p, q, end - q);
|
|
p += end - q;
|
|
|
|
/* We want to shorten the glyph, but we can't do that without
|
|
* updating the length in the loca table, which is already
|
|
* written out :-(. So we just fill the rest of the glyph with
|
|
* harmless instructions, since that's what they will be
|
|
* interpreted as.
|
|
*
|
|
* Should move the lowering to _populate_subset_glyphs() to
|
|
* fix this issue. */
|
|
|
|
hb_memset (p, 0x7A /* TrueType instruction ROFF; harmless */, end - p);
|
|
p += end - p;
|
|
dest_glyph = hb_bytes_t (dest_glyph.arrayZ, p - (char *) dest_glyph.arrayZ);
|
|
|
|
// TODO: Padding; & trim serialized bytes.
|
|
// TODO: Update length in loca. Ugh.
|
|
}
|
|
#endif
|
|
|
|
if (plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
|
|
Glyph (dest_glyph).drop_hints ();
|
|
|
|
if (plan->flags & HB_SUBSET_FLAGS_SET_OVERLAPS_FLAG)
|
|
Glyph (dest_glyph).set_overlaps_flag ();
|
|
|
|
return_trace (true);
|
|
}
|
|
|
|
bool compile_bytes_with_deltas (const hb_subset_plan_t *plan,
|
|
hb_font_t *font,
|
|
const glyf_accelerator_t &glyf)
|
|
{
|
|
allocated = source_glyph.compile_bytes_with_deltas (plan, font, glyf, dest_start, dest_end);
|
|
return allocated;
|
|
}
|
|
|
|
void free_compiled_bytes ()
|
|
{
|
|
if (likely (allocated)) {
|
|
allocated = false;
|
|
dest_start.fini ();
|
|
dest_end.fini ();
|
|
}
|
|
}
|
|
|
|
void drop_hints_bytes ()
|
|
{ source_glyph.drop_hints_bytes (dest_start, dest_end); }
|
|
|
|
unsigned int length () const { return dest_start.length + dest_end.length; }
|
|
/* pad to 2 to ensure 2-byte loca will be ok */
|
|
unsigned int padding () const { return length () % 2; }
|
|
unsigned int padded_size () const { return length () + padding (); }
|
|
};
|
|
|
|
|
|
} /* namespace glyf_impl */
|
|
} /* namespace OT */
|
|
|
|
|
|
#endif /* OT_GLYF_SUBSETGLYPH_HH */
|