[glyf] format source
This commit is contained in:
parent
2aef3013f3
commit
d57819cbdb
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright © 2015 Google, Inc.
|
* Copyright © 2015 Google, Inc.
|
||||||
|
* Copyright © 2019 Ebrahim Byagowi
|
||||||
*
|
*
|
||||||
* This is part of HarfBuzz, a text shaping library.
|
* This is part of HarfBuzz, a text shaping library.
|
||||||
*
|
*
|
||||||
|
@ -53,11 +54,12 @@ struct loca
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
UnsizedArrayOf<HBUINT8> dataZ; /* Location data. */
|
UnsizedArrayOf<HBUINT8>
|
||||||
|
dataZ; /* Location data. */
|
||||||
public:
|
public:
|
||||||
DEFINE_SIZE_MIN (0); /* In reality, this is UNBOUNDED() type; but since we always
|
DEFINE_SIZE_MIN (0); /* In reality, this is UNBOUNDED() type; but since we always
|
||||||
* check the size externally, allow Null() object of it by
|
* check the size externally, allow Null() object of it by
|
||||||
* defining it _MIN instead. */
|
* defining it _MIN instead. */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -93,7 +95,9 @@ struct glyf
|
||||||
|
|
||||||
if (unlikely (!loca_prime_data)) return false;
|
if (unlikely (!loca_prime_data)) return false;
|
||||||
|
|
||||||
DEBUG_MSG(SUBSET, nullptr, "loca entry_size %d num_offsets %d max_offset %d size %d", entry_size, num_offsets, max_offset, entry_size * num_offsets);
|
DEBUG_MSG (SUBSET, nullptr, "loca entry_size %d num_offsets %d "
|
||||||
|
"max_offset %d size %d",
|
||||||
|
entry_size, num_offsets, max_offset, entry_size * num_offsets);
|
||||||
|
|
||||||
if (use_short_loca)
|
if (use_short_loca)
|
||||||
_write_loca (padded_offsets, 1, hb_array ((HBUINT16*) loca_prime_data, num_offsets));
|
_write_loca (padded_offsets, 1, hb_array ((HBUINT16*) loca_prime_data, num_offsets));
|
||||||
|
@ -122,20 +126,21 @@ struct glyf
|
||||||
unsigned int offset = 0;
|
unsigned int offset = 0;
|
||||||
dest << 0;
|
dest << 0;
|
||||||
+ it
|
+ it
|
||||||
| hb_map ([=, &offset] (unsigned int padded_size) {
|
| hb_map ([=, &offset] (unsigned int padded_size)
|
||||||
offset += padded_size;
|
{
|
||||||
DEBUG_MSG(SUBSET, nullptr, "loca entry offset %d", offset);
|
offset += padded_size;
|
||||||
return offset >> right_shift;
|
DEBUG_MSG (SUBSET, nullptr, "loca entry offset %d", offset);
|
||||||
})
|
return offset >> right_shift;
|
||||||
|
})
|
||||||
| hb_sink (dest)
|
| hb_sink (dest)
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
// requires source of SubsetGlyph complains the identifier isn't declared
|
// requires source of SubsetGlyph complains the identifier isn't declared
|
||||||
template <typename Iterator>
|
template <typename Iterator>
|
||||||
bool serialize(hb_serialize_context_t *c,
|
bool serialize (hb_serialize_context_t *c,
|
||||||
Iterator it,
|
Iterator it,
|
||||||
const hb_subset_plan_t *plan)
|
const hb_subset_plan_t *plan)
|
||||||
{
|
{
|
||||||
TRACE_SERIALIZE (this);
|
TRACE_SERIALIZE (this);
|
||||||
|
|
||||||
|
@ -167,7 +172,8 @@ struct glyf
|
||||||
;
|
;
|
||||||
|
|
||||||
if (c->serializer->in_error ()) return_trace (false);
|
if (c->serializer->in_error ()) return_trace (false);
|
||||||
return_trace (c->serializer->check_success (_add_loca_and_head (c->plan, padded_offsets)));
|
return_trace (c->serializer->check_success (_add_loca_and_head (c->plan,
|
||||||
|
padded_offsets)));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename SubsetGlyph>
|
template <typename SubsetGlyph>
|
||||||
|
@ -179,23 +185,26 @@ struct glyf
|
||||||
glyf.init (plan->source);
|
glyf.init (plan->source);
|
||||||
|
|
||||||
+ hb_range (plan->num_output_glyphs ())
|
+ hb_range (plan->num_output_glyphs ())
|
||||||
| hb_map ([&] (hb_codepoint_t new_gid) {
|
| hb_map ([&] (hb_codepoint_t new_gid)
|
||||||
SubsetGlyph subset_glyph = {0};
|
{
|
||||||
subset_glyph.new_gid = new_gid;
|
SubsetGlyph subset_glyph = {0};
|
||||||
|
subset_glyph.new_gid = new_gid;
|
||||||
|
|
||||||
// should never fail: all old gids should be mapped
|
// should never fail: all old gids should be mapped
|
||||||
if (!plan->old_gid_for_new_gid (new_gid, &subset_glyph.old_gid)) return subset_glyph;
|
if (!plan->old_gid_for_new_gid (new_gid, &subset_glyph.old_gid))
|
||||||
|
return subset_glyph;
|
||||||
|
|
||||||
subset_glyph.source_glyph = glyf.bytes_for_glyph ((const char *) this, subset_glyph.old_gid);
|
subset_glyph.source_glyph = glyf.bytes_for_glyph ((const char *) this,
|
||||||
if (plan->drop_hints) subset_glyph.drop_hints (glyf);
|
subset_glyph.old_gid);
|
||||||
else subset_glyph.dest_start = subset_glyph.source_glyph;
|
if (plan->drop_hints) subset_glyph.drop_hints (glyf);
|
||||||
|
else subset_glyph.dest_start = subset_glyph.source_glyph;
|
||||||
|
|
||||||
return subset_glyph;
|
return subset_glyph;
|
||||||
})
|
})
|
||||||
| hb_sink (glyphs)
|
| hb_sink (glyphs)
|
||||||
;
|
;
|
||||||
|
|
||||||
glyf.fini();
|
glyf.fini ();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -225,7 +234,9 @@ struct glyf
|
||||||
int16_t num_contours = (int16_t) glyph_header.numberOfContours;
|
int16_t num_contours = (int16_t) glyph_header.numberOfContours;
|
||||||
if (num_contours <= 0) return; // only for simple glyphs
|
if (num_contours <= 0) return; // only for simple glyphs
|
||||||
|
|
||||||
const HBUINT16 &instruction_length = StructAtOffset<HBUINT16> (&glyph, GlyphHeader::static_size + 2 * num_contours);
|
unsigned int contours_length = GlyphHeader::static_size + 2 * num_contours;
|
||||||
|
const HBUINT16 &instruction_length = StructAtOffset<HBUINT16> (&glyph,
|
||||||
|
contours_length);
|
||||||
(HBUINT16 &) instruction_length = 0;
|
(HBUINT16 &) instruction_length = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -236,15 +247,18 @@ struct glyf
|
||||||
|
|
||||||
/* remove WE_HAVE_INSTRUCTIONS from flags in dest */
|
/* remove WE_HAVE_INSTRUCTIONS from flags in dest */
|
||||||
OT::glyf::CompositeGlyphHeader::Iterator composite_it;
|
OT::glyf::CompositeGlyphHeader::Iterator composite_it;
|
||||||
if (unlikely (!OT::glyf::CompositeGlyphHeader::get_iterator (&glyph, glyph.length, &composite_it))) return false;
|
if (unlikely (!OT::glyf::CompositeGlyphHeader::get_iterator (&glyph, glyph.length,
|
||||||
|
&composite_it)))
|
||||||
|
return false;
|
||||||
const OT::glyf::CompositeGlyphHeader *composite_header;
|
const OT::glyf::CompositeGlyphHeader *composite_header;
|
||||||
do {
|
do
|
||||||
|
{
|
||||||
composite_header = composite_it.current;
|
composite_header = composite_it.current;
|
||||||
OT::HBUINT16 *flags = const_cast<OT::HBUINT16 *> (&composite_header->flags);
|
OT::HBUINT16 *flags = const_cast<OT::HBUINT16 *> (&composite_header->flags);
|
||||||
*flags = (uint16_t) *flags & ~OT::glyf::CompositeGlyphHeader::WE_HAVE_INSTRUCTIONS;
|
*flags = (uint16_t) *flags & ~OT::glyf::CompositeGlyphHeader::WE_HAVE_INSTRUCTIONS;
|
||||||
} while (composite_it.move_to_next ());
|
} while (composite_it.move_to_next ());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
_add_head_and_set_loca_version (hb_subset_plan_t *plan, bool use_short_loca)
|
_add_head_and_set_loca_version (hb_subset_plan_t *plan, bool use_short_loca)
|
||||||
|
@ -257,7 +271,7 @@ struct glyf
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
head *head_prime = (head *) hb_blob_get_data_writable (head_prime_blob, nullptr);
|
head *head_prime = (head *) hb_blob_get_data_writable (head_prime_blob, nullptr);
|
||||||
head_prime->indexToLocFormat = use_short_loca ? 0 : 1;
|
head_prime->indexToLocFormat = !use_short_loca;
|
||||||
bool success = plan->add_table (HB_OT_TAG_head, head_prime_blob);
|
bool success = plan->add_table (HB_OT_TAG_head, head_prime_blob);
|
||||||
|
|
||||||
hb_blob_destroy (head_prime_blob);
|
hb_blob_destroy (head_prime_blob);
|
||||||
|
@ -280,7 +294,8 @@ struct glyf
|
||||||
|
|
||||||
struct CompositeGlyphHeader
|
struct CompositeGlyphHeader
|
||||||
{
|
{
|
||||||
enum composite_glyph_flag_t {
|
enum composite_glyph_flag_t
|
||||||
|
{
|
||||||
ARG_1_AND_2_ARE_WORDS = 0x0001,
|
ARG_1_AND_2_ARE_WORDS = 0x0001,
|
||||||
ARGS_ARE_XY_VALUES = 0x0002,
|
ARGS_ARE_XY_VALUES = 0x0002,
|
||||||
ROUND_XY_TO_GRID = 0x0004,
|
ROUND_XY_TO_GRID = 0x0004,
|
||||||
|
@ -340,8 +355,8 @@ struct glyf
|
||||||
bool in_range (const CompositeGlyphHeader *composite) const
|
bool in_range (const CompositeGlyphHeader *composite) const
|
||||||
{
|
{
|
||||||
return (const char *) composite >= glyph_start
|
return (const char *) composite >= glyph_start
|
||||||
&& ((const char *) composite + CompositeGlyphHeader::min_size) <= glyph_end
|
&& ((const char *) composite + CompositeGlyphHeader::min_size) <= glyph_end
|
||||||
&& ((const char *) composite + composite->get_size ()) <= glyph_end;
|
&& ((const char *) composite + composite->get_size ()) <= glyph_end;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -416,7 +431,8 @@ struct glyf
|
||||||
composite);
|
composite);
|
||||||
}
|
}
|
||||||
|
|
||||||
enum simple_glyph_flag_t {
|
enum simple_glyph_flag_t
|
||||||
|
{
|
||||||
FLAG_ON_CURVE = 0x01,
|
FLAG_ON_CURVE = 0x01,
|
||||||
FLAG_X_SHORT = 0x02,
|
FLAG_X_SHORT = 0x02,
|
||||||
FLAG_Y_SHORT = 0x04,
|
FLAG_Y_SHORT = 0x04,
|
||||||
|
@ -466,7 +482,7 @@ struct glyf
|
||||||
{
|
{
|
||||||
if (glyph >= glyph_end)
|
if (glyph >= glyph_end)
|
||||||
{
|
{
|
||||||
DEBUG_MSG(SUBSET, nullptr, "Bad flag");
|
DEBUG_MSG (SUBSET, nullptr, "Bad flag");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
repeat = ((uint8_t) *glyph) + 1;
|
repeat = ((uint8_t) *glyph) + 1;
|
||||||
|
@ -489,7 +505,8 @@ struct glyf
|
||||||
|
|
||||||
if (coordsWithFlags != nCoordinates)
|
if (coordsWithFlags != nCoordinates)
|
||||||
{
|
{
|
||||||
DEBUG_MSG(SUBSET, nullptr, "Expect %d coords to have flags, got flags for %d", nCoordinates, coordsWithFlags);
|
DEBUG_MSG (SUBSET, nullptr, "Expect %d coords to have flags, got flags for %d",
|
||||||
|
nCoordinates, coordsWithFlags);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
glyph += coordBytes;
|
glyph += coordBytes;
|
||||||
|
@ -546,38 +563,47 @@ struct glyf
|
||||||
unsigned int end = glyph.length;
|
unsigned int end = glyph.length;
|
||||||
unsigned int glyph_offset = &glyph - glyf_table;
|
unsigned int glyph_offset = &glyph - glyf_table;
|
||||||
CompositeGlyphHeader::Iterator composite_it;
|
CompositeGlyphHeader::Iterator composite_it;
|
||||||
if (unlikely (!CompositeGlyphHeader::get_iterator (&glyph, glyph.length, &composite_it))) return false;
|
if (unlikely (!CompositeGlyphHeader::get_iterator (&glyph, glyph.length,
|
||||||
|
&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)
|
||||||
start = ((char *) last - (char *) glyf_table->dataZ.arrayZ) + last->get_size () - glyph_offset;
|
start = ((char *) last - (char *) glyf_table->dataZ.arrayZ)
|
||||||
|
+ last->get_size () - glyph_offset;
|
||||||
if (unlikely (start > end))
|
if (unlikely (start > end))
|
||||||
{
|
{
|
||||||
DEBUG_MSG(SUBSET, nullptr, "Invalid instruction offset, %d is outside %d byte buffer", start, glyph.length);
|
DEBUG_MSG (SUBSET, nullptr, "Invalid instruction offset, %d is outside "
|
||||||
|
"%d byte buffer", start, glyph.length);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
*length = end - start;
|
*length = end - start;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// simple glyph
|
/* simple glyph */
|
||||||
unsigned int instruction_length_offset = GlyphHeader::static_size + 2 * num_contours;
|
unsigned int instruction_len_offset = GlyphHeader::static_size + 2 * num_contours;
|
||||||
if (unlikely (instruction_length_offset + 2 > glyph.length))
|
if (unlikely (instruction_len_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;
|
||||||
}
|
}
|
||||||
|
|
||||||
const HBUINT16 &instruction_length = StructAtOffset<HBUINT16> (&glyph, instruction_length_offset);
|
const HBUINT16 &instruction_len = StructAtOffset<HBUINT16> (&glyph,
|
||||||
if (unlikely (instruction_length_offset + 2 + instruction_length > glyph.length)) // Out of bounds of the current glyph
|
instruction_len_offset);
|
||||||
|
/* Out of bounds of the current glyph */
|
||||||
|
if (unlikely (instruction_len_offset + 2 + instruction_len > glyph.length))
|
||||||
{
|
{
|
||||||
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;
|
||||||
}
|
}
|
||||||
*length = (uint16_t) instruction_length;
|
*length = (uint16_t) instruction_len;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -591,34 +617,37 @@ struct glyf
|
||||||
if (end_offset - start_offset < GlyphHeader::static_size)
|
if (end_offset - start_offset < GlyphHeader::static_size)
|
||||||
return true; /* Empty glyph; zero extents. */
|
return true; /* Empty glyph; zero extents. */
|
||||||
|
|
||||||
const GlyphHeader &glyph_header = StructAtOffset<GlyphHeader> (glyf_table, start_offset);
|
const GlyphHeader &glyph_header = StructAtOffset<GlyphHeader> (glyf_table,
|
||||||
|
start_offset);
|
||||||
|
|
||||||
extents->x_bearing = hb_min (glyph_header.xMin, glyph_header.xMax);
|
extents->x_bearing = hb_min (glyph_header.xMin, glyph_header.xMax);
|
||||||
extents->y_bearing = hb_max (glyph_header.yMin, glyph_header.yMax);
|
extents->y_bearing = hb_max (glyph_header.yMin, glyph_header.yMax);
|
||||||
extents->width = hb_max (glyph_header.xMin, glyph_header.xMax) - extents->x_bearing;
|
extents->width = hb_max (glyph_header.xMin, glyph_header.xMax)
|
||||||
extents->height = hb_min (glyph_header.yMin, glyph_header.yMax) - extents->y_bearing;
|
- extents->x_bearing;
|
||||||
|
extents->height = hb_min (glyph_header.yMin, glyph_header.yMax)
|
||||||
|
- extents->y_bearing;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
hb_bytes_t bytes_for_glyph (const char * glyf, hb_codepoint_t gid)
|
hb_bytes_t bytes_for_glyph (const char * glyf, hb_codepoint_t gid)
|
||||||
{
|
|
||||||
unsigned int start_offset, end_offset;
|
|
||||||
if (unlikely (!(get_offsets (gid, &start_offset, &end_offset) &&
|
|
||||||
remove_padding (start_offset, &end_offset))))
|
|
||||||
{
|
{
|
||||||
DEBUG_MSG(SUBSET, nullptr, "Unable to get offset or remove padding for %d", gid);
|
unsigned int start_offset, end_offset;
|
||||||
return hb_bytes_t ();
|
if (unlikely (!(get_offsets (gid, &start_offset, &end_offset) &&
|
||||||
|
remove_padding (start_offset, &end_offset))))
|
||||||
|
{
|
||||||
|
DEBUG_MSG (SUBSET, nullptr, "Unable to get offset or remove padding for %d", gid);
|
||||||
|
return hb_bytes_t ();
|
||||||
|
}
|
||||||
|
hb_bytes_t glyph = hb_bytes_t (glyf + start_offset, end_offset - start_offset);
|
||||||
|
if (glyph.length == 0) return glyph;
|
||||||
|
if (unlikely (glyph.length < GlyphHeader::static_size))
|
||||||
|
{
|
||||||
|
DEBUG_MSG (SUBSET, nullptr, "Glyph size smaller than minimum header %d", gid);
|
||||||
|
return hb_bytes_t ();
|
||||||
|
}
|
||||||
|
return glyph;
|
||||||
}
|
}
|
||||||
hb_bytes_t glyph = hb_bytes_t (glyf + start_offset, end_offset - start_offset);
|
|
||||||
if (glyph.length == 0) return glyph;
|
|
||||||
if (unlikely (glyph.length < GlyphHeader::static_size))
|
|
||||||
{
|
|
||||||
DEBUG_MSG(SUBSET, nullptr, "Glyph size smaller than minimum header %d", gid);
|
|
||||||
return hb_bytes_t ();
|
|
||||||
}
|
|
||||||
return glyph;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool short_offset;
|
bool short_offset;
|
||||||
|
@ -627,99 +656,96 @@ struct glyf
|
||||||
hb_blob_ptr_t<glyf> glyf_table;
|
hb_blob_ptr_t<glyf> glyf_table;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct SubsetGlyph
|
struct SubsetGlyph
|
||||||
{
|
{
|
||||||
hb_codepoint_t new_gid;
|
hb_codepoint_t new_gid;
|
||||||
hb_codepoint_t old_gid;
|
hb_codepoint_t old_gid;
|
||||||
hb_bytes_t source_glyph;
|
hb_bytes_t source_glyph;
|
||||||
hb_bytes_t dest_start; // region of source_glyph to copy first
|
hb_bytes_t dest_start; /* region of source_glyph to copy first */
|
||||||
hb_bytes_t dest_end; // region of source_glyph to copy second
|
hb_bytes_t dest_end; /* region of source_glyph to copy second */
|
||||||
|
|
||||||
|
bool serialize (hb_serialize_context_t *c,
|
||||||
bool serialize (hb_serialize_context_t *c,
|
const hb_subset_plan_t *plan) const
|
||||||
const hb_subset_plan_t *plan) const
|
|
||||||
{
|
|
||||||
TRACE_SERIALIZE (this);
|
|
||||||
|
|
||||||
hb_bytes_t dest_glyph = dest_start.copy(c);
|
|
||||||
dest_glyph = hb_bytes_t (&dest_glyph, dest_glyph.length + dest_end.copy(c).length);
|
|
||||||
unsigned int pad_length = padding ();
|
|
||||||
DEBUG_MSG(SUBSET, nullptr, "serialize %d byte glyph, width %d pad %d", dest_glyph.length, dest_glyph.length + pad_length, pad_length);
|
|
||||||
|
|
||||||
HBUINT8 pad;
|
|
||||||
pad = 0;
|
|
||||||
while (pad_length > 0)
|
|
||||||
{
|
{
|
||||||
c->embed(pad);
|
TRACE_SERIALIZE (this);
|
||||||
pad_length--;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dest_glyph.length)
|
hb_bytes_t dest_glyph = dest_start.copy (c);
|
||||||
{
|
dest_glyph = hb_bytes_t (&dest_glyph, dest_glyph.length + dest_end.copy (c).length);
|
||||||
_fix_component_gids (plan, dest_glyph);
|
unsigned int pad_length = padding ();
|
||||||
if (plan->drop_hints)
|
DEBUG_MSG (SUBSET, nullptr, "serialize %d byte glyph, width %d pad %d",
|
||||||
|
dest_glyph.length, dest_glyph.length + pad_length, pad_length);
|
||||||
|
|
||||||
|
HBUINT8 pad;
|
||||||
|
pad = 0;
|
||||||
|
while (pad_length > 0)
|
||||||
{
|
{
|
||||||
_zero_instruction_length (dest_glyph);
|
c->embed (pad);
|
||||||
c->check_success (_remove_composite_instruction_flag (dest_glyph));
|
pad_length--;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return_trace (true);
|
if (dest_glyph.length)
|
||||||
}
|
{
|
||||||
|
_fix_component_gids (plan, dest_glyph);
|
||||||
|
if (plan->drop_hints)
|
||||||
|
{
|
||||||
|
_zero_instruction_length (dest_glyph);
|
||||||
|
c->check_success (_remove_composite_instruction_flag (dest_glyph));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return_trace (true);
|
||||||
|
}
|
||||||
|
|
||||||
void drop_hints (const OT::glyf::accelerator_t& glyf)
|
void drop_hints (const OT::glyf::accelerator_t& glyf)
|
||||||
{
|
{
|
||||||
if (source_glyph.length == 0) return;
|
if (source_glyph.length == 0) return;
|
||||||
|
|
||||||
unsigned int instruction_length = 0;
|
unsigned int instruction_len = 0;
|
||||||
if (!glyf.get_instruction_length (source_glyph, &instruction_length))
|
if (!glyf.get_instruction_length (source_glyph, &instruction_len))
|
||||||
{
|
{
|
||||||
DEBUG_MSG(SUBSET, nullptr, "Unable to read instruction length for new_gid %d", new_gid);
|
DEBUG_MSG (SUBSET, nullptr, "Unable to read instruction length for new_gid %d",
|
||||||
|
new_gid);
|
||||||
return ;
|
return ;
|
||||||
}
|
}
|
||||||
|
|
||||||
const GlyphHeader& header = StructAtOffset<GlyphHeader> (&source_glyph, 0);
|
const GlyphHeader& header = StructAtOffset<GlyphHeader> (&source_glyph, 0);
|
||||||
int16_t num_contours = (int16_t) header.numberOfContours;
|
int16_t num_contours = (int16_t) header.numberOfContours;
|
||||||
DEBUG_MSG(SUBSET, nullptr, "new_gid %d (%d contours) drop %d instruction bytes from %d byte source glyph", new_gid, num_contours, instruction_length, source_glyph.length);
|
DEBUG_MSG (SUBSET, nullptr, "new_gid %d (%d contours) drop %d instruction bytes "
|
||||||
|
"from %d byte source glyph",
|
||||||
|
new_gid, num_contours, instruction_len, source_glyph.length);
|
||||||
if (num_contours < 0)
|
if (num_contours < 0)
|
||||||
{
|
{
|
||||||
// composite, just chop instructions off the end
|
/* composite, just chop instructions off the end */
|
||||||
dest_start = hb_bytes_t (&source_glyph, source_glyph.length - instruction_length);
|
dest_start = hb_bytes_t (&source_glyph, source_glyph.length - instruction_len);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// simple glyph
|
/* simple glyph */
|
||||||
dest_start = hb_bytes_t (&source_glyph, GlyphHeader::static_size + 2 * header.numberOfContours + 2);
|
unsigned int glyph_length = GlyphHeader::static_size + 2 * header.numberOfContours
|
||||||
dest_end = hb_bytes_t (&source_glyph + dest_start.length + instruction_length,
|
+ 2 + instruction_len;
|
||||||
source_glyph.length - dest_start.length - instruction_length);
|
dest_start = hb_bytes_t (&source_glyph, glyph_length - instruction_len);
|
||||||
DEBUG_MSG(SUBSET, nullptr, "source_len %d start len %d instruction_len %d end len %d", source_glyph.length, dest_start.length, instruction_length, dest_end.length);
|
dest_end = hb_bytes_t (&source_glyph + glyph_length,
|
||||||
|
source_glyph.length - glyph_length);
|
||||||
|
DEBUG_MSG (SUBSET, nullptr, "source_len %d start len %d glyph_len %d "
|
||||||
|
"instruction_len %d end len %d",
|
||||||
|
source_glyph.length, dest_start.length, glyph_length,
|
||||||
|
instruction_len, dest_end.length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int length () const
|
unsigned int length () const { return dest_start.length + dest_end.length; }
|
||||||
{
|
/* pad to 2 to ensure 2-byte loca will be ok */
|
||||||
return dest_start.length + dest_end.length;
|
unsigned int padding () const { return length () % 2; }
|
||||||
}
|
unsigned int padded_size () const { return length () + padding (); }
|
||||||
|
|
||||||
// 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 ();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
UnsizedArrayOf<HBUINT8> dataZ; /* Glyphs data. */
|
UnsizedArrayOf<HBUINT8>
|
||||||
|
dataZ; /* Glyphs data. */
|
||||||
public:
|
public:
|
||||||
DEFINE_SIZE_MIN (0); /* In reality, this is UNBOUNDED() type; but since we always
|
DEFINE_SIZE_MIN (0); /* In reality, this is UNBOUNDED() type; but since we always
|
||||||
* check the size externally, allow Null() object of it by
|
* check the size externally, allow Null() object of it by
|
||||||
* defining it _MIN instead. */
|
* defining it _MIN instead. */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct glyf_accelerator_t : glyf::accelerator_t {};
|
struct glyf_accelerator_t : glyf::accelerator_t {};
|
||||||
|
|
Loading…
Reference in New Issue