|
|
@ -196,8 +196,7 @@ struct glyf |
|
|
|
if (!plan->old_gid_for_new_gid (new_gid, &subset_glyph.old_gid)) |
|
|
|
if (!plan->old_gid_for_new_gid (new_gid, &subset_glyph.old_gid)) |
|
|
|
return subset_glyph; |
|
|
|
return subset_glyph; |
|
|
|
|
|
|
|
|
|
|
|
subset_glyph.source_glyph = glyf.bytes_for_glyph (subset_glyph.old_gid, |
|
|
|
subset_glyph.source_glyph = glyf.bytes_for_glyph (subset_glyph.old_gid, true); |
|
|
|
true); |
|
|
|
|
|
|
|
if (plan->drop_hints) subset_glyph.drop_hints (glyf); |
|
|
|
if (plan->drop_hints) subset_glyph.drop_hints (glyf); |
|
|
|
else subset_glyph.dest_start = subset_glyph.source_glyph; |
|
|
|
else subset_glyph.dest_start = subset_glyph.source_glyph; |
|
|
|
|
|
|
|
|
|
|
@ -591,71 +590,68 @@ struct glyf |
|
|
|
const bool phantom_only=false) const |
|
|
|
const bool phantom_only=false) const |
|
|
|
{ |
|
|
|
{ |
|
|
|
unsigned int num_points = 0; |
|
|
|
unsigned int num_points = 0; |
|
|
|
unsigned int start_offset, end_offset; |
|
|
|
hb_bytes_t bytes = bytes_for_glyph (glyph); |
|
|
|
if (unlikely (!get_offsets (glyph, &start_offset, &end_offset))) return false; |
|
|
|
const GlyphHeader &glyph_header = *bytes.as<GlyphHeader> (); |
|
|
|
if (unlikely (end_offset - start_offset < GlyphHeader::static_size)) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
/* empty glyph */ |
|
|
|
|
|
|
|
points_.resize (PHANTOM_COUNT); |
|
|
|
|
|
|
|
for (unsigned int i = 0; i < points_.length; i++) points_[i].init (); |
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const GlyphHeader &glyph_header = StructAtOffset<GlyphHeader> (glyf_table, start_offset); |
|
|
|
|
|
|
|
if (glyph_header.is_composite_glyph ()) |
|
|
|
if (glyph_header.is_composite_glyph ()) |
|
|
|
{ |
|
|
|
{ |
|
|
|
hb_bytes_t bytes ((const char *) this->glyf_table + start_offset, |
|
|
|
/* add one pseudo point for each component in composite glyph */ |
|
|
|
end_offset - start_offset); |
|
|
|
|
|
|
|
/* For a composite glyph, add one pseudo point for each component */ |
|
|
|
|
|
|
|
num_points += hb_len (get_composite_iterator (bytes)); |
|
|
|
num_points += hb_len (get_composite_iterator (bytes)); |
|
|
|
points_.resize (num_points + PHANTOM_COUNT); |
|
|
|
points_.resize (num_points + PHANTOM_COUNT); |
|
|
|
for (unsigned int i = 0; i < points_.length; i++) points_[i].init (); |
|
|
|
for (unsigned int i = 0; i < points_.length; i++) points_[i].init (); |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
else if (glyph_header.is_simple_glyph ()) |
|
|
|
const HBUINT16 *end_pts = &StructAfter<HBUINT16, GlyphHeader> (glyph_header); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
range_checker_t checker (glyf_table, start_offset, end_offset); |
|
|
|
|
|
|
|
num_points = 0; |
|
|
|
|
|
|
|
int num_contours = glyph_header.numberOfContours; |
|
|
|
|
|
|
|
if (glyph_header.is_simple_glyph ()) |
|
|
|
|
|
|
|
{ |
|
|
|
{ |
|
|
|
|
|
|
|
const HBUINT16 *end_pts = &StructAfter<HBUINT16, GlyphHeader> (glyph_header); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
unsigned int start_offset, end_offset; |
|
|
|
|
|
|
|
if (unlikely (!get_offsets (glyph, &start_offset, &end_offset))) return false; |
|
|
|
|
|
|
|
range_checker_t checker (glyf_table, start_offset, end_offset); |
|
|
|
|
|
|
|
num_points = 0; |
|
|
|
|
|
|
|
int num_contours = glyph_header.numberOfContours; |
|
|
|
if (unlikely (!checker.in_range (&end_pts[num_contours + 1]))) return false; |
|
|
|
if (unlikely (!checker.in_range (&end_pts[num_contours + 1]))) return false; |
|
|
|
num_points = end_pts[glyph_header.numberOfContours - 1] + 1; |
|
|
|
num_points = end_pts[glyph_header.numberOfContours - 1] + 1; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
points_.resize (num_points + PHANTOM_COUNT); |
|
|
|
points_.resize (num_points + PHANTOM_COUNT); |
|
|
|
for (unsigned int i = 0; i < points_.length; i++) points_[i].init (); |
|
|
|
for (unsigned int i = 0; i < points_.length; i++) points_[i].init (); |
|
|
|
if (!glyph_header.is_simple_glyph () || phantom_only) return true; |
|
|
|
if (!glyph_header.is_simple_glyph () || phantom_only) return true; |
|
|
|
|
|
|
|
|
|
|
|
/* Read simple glyph points if !phantom_only */ |
|
|
|
/* Read simple glyph points if !phantom_only */ |
|
|
|
end_points_.resize (num_contours); |
|
|
|
end_points_.resize (num_contours); |
|
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < num_contours; i++) |
|
|
|
for (int i = 0; i < num_contours; i++) |
|
|
|
end_points_[i] = end_pts[i]; |
|
|
|
end_points_[i] = end_pts[i]; |
|
|
|
|
|
|
|
|
|
|
|
/* Skip instructions */ |
|
|
|
/* Skip instructions */ |
|
|
|
const HBUINT8 *p = &StructAtOffset<HBUINT8> (&end_pts[num_contours + 1], |
|
|
|
const HBUINT8 *p = &StructAtOffset<HBUINT8> (&end_pts[num_contours + 1], |
|
|
|
end_pts[num_contours]); |
|
|
|
end_pts[num_contours]); |
|
|
|
|
|
|
|
|
|
|
|
/* Read flags */ |
|
|
|
/* Read flags */ |
|
|
|
for (unsigned int i = 0; i < num_points; i++) |
|
|
|
for (unsigned int i = 0; i < num_points; i++) |
|
|
|
{ |
|
|
|
|
|
|
|
if (unlikely (!checker.in_range (p))) return false; |
|
|
|
|
|
|
|
uint8_t flag = *p++; |
|
|
|
|
|
|
|
points_[i].flag = flag; |
|
|
|
|
|
|
|
if ((flag & FLAG_REPEAT) != 0) |
|
|
|
|
|
|
|
{ |
|
|
|
{ |
|
|
|
if (unlikely (!checker.in_range (p))) return false; |
|
|
|
if (unlikely (!checker.in_range (p))) return false; |
|
|
|
unsigned int repeat_count = *p++; |
|
|
|
uint8_t flag = *p++; |
|
|
|
while ((repeat_count-- > 0) && (++i < num_points)) |
|
|
|
points_[i].flag = flag; |
|
|
|
points_[i].flag = flag; |
|
|
|
if ((flag & FLAG_REPEAT) != 0) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (unlikely (!checker.in_range (p))) return false; |
|
|
|
|
|
|
|
unsigned int repeat_count = *p++; |
|
|
|
|
|
|
|
while ((repeat_count-- > 0) && (++i < num_points)) |
|
|
|
|
|
|
|
points_[i].flag = flag; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Read x & y coordinates */ |
|
|
|
/* Read x & y coordinates */ |
|
|
|
return (read_points<x_setter_t> (p, points_, checker) && |
|
|
|
return (read_points<x_setter_t> (p, points_, checker) && |
|
|
|
read_points<y_setter_t> (p, points_, checker)); |
|
|
|
read_points<y_setter_t> (p, points_, checker)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
/* empty glyph */ |
|
|
|
|
|
|
|
points_.resize (PHANTOM_COUNT); |
|
|
|
|
|
|
|
for (unsigned int i = 0; i < points_.length; i++) points_[i].init (); |
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
struct contour_bounds_t |
|
|
|
struct contour_bounds_t |
|
|
@ -700,13 +696,9 @@ struct glyf |
|
|
|
end_offset - start_offset); |
|
|
|
end_offset - start_offset); |
|
|
|
const GlyphHeader &glyph_header = *bytes.as<GlyphHeader> (); |
|
|
|
const GlyphHeader &glyph_header = *bytes.as<GlyphHeader> (); |
|
|
|
if (glyph_header.is_simple_glyph ()) |
|
|
|
if (glyph_header.is_simple_glyph ()) |
|
|
|
{ |
|
|
|
|
|
|
|
/* simple glyph */ |
|
|
|
|
|
|
|
all_points.extend (points.as_array ()); |
|
|
|
all_points.extend (points.as_array ()); |
|
|
|
} |
|
|
|
|
|
|
|
else if (glyph_header.is_composite_glyph ()) |
|
|
|
else if (glyph_header.is_composite_glyph ()) |
|
|
|
{ |
|
|
|
{ |
|
|
|
/* composite glyph */ |
|
|
|
|
|
|
|
for (auto &item : get_composite_iterator (bytes)) |
|
|
|
for (auto &item : get_composite_iterator (bytes)) |
|
|
|
{ |
|
|
|
{ |
|
|
|
contour_point_vector_t comp_points; |
|
|
|
contour_point_vector_t comp_points; |
|
|
@ -892,8 +884,7 @@ struct glyf |
|
|
|
unsigned int *start_offset /* OUT */, |
|
|
|
unsigned int *start_offset /* OUT */, |
|
|
|
unsigned int *end_offset /* OUT */) const |
|
|
|
unsigned int *end_offset /* OUT */) const |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (unlikely (glyph >= num_glyphs)) |
|
|
|
if (unlikely (glyph >= num_glyphs)) return false; |
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (short_offset) |
|
|
|
if (short_offset) |
|
|
|
{ |
|
|
|
{ |
|
|
@ -916,16 +907,9 @@ struct glyf |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
bool get_instruction_length (hb_bytes_t glyph, |
|
|
|
bool get_instruction_length (hb_bytes_t glyph, |
|
|
|
unsigned int * length /* OUT */) const |
|
|
|
unsigned int *length /* OUT */) const |
|
|
|
{ |
|
|
|
{ |
|
|
|
const GlyphHeader &glyph_header = *glyph.as<GlyphHeader> (); |
|
|
|
const GlyphHeader &glyph_header = *glyph.as<GlyphHeader> (); |
|
|
|
/* Empty glyph; no instructions. */ |
|
|
|
|
|
|
|
if (!glyph_header.has_data ()) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
*length = 0; |
|
|
|
|
|
|
|
/* only 0 byte glyphs are healthy when missing GlyphHeader */ |
|
|
|
|
|
|
|
return glyph.length == 0; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (glyph_header.is_composite_glyph ()) |
|
|
|
if (glyph_header.is_composite_glyph ()) |
|
|
|
{ |
|
|
|
{ |
|
|
|
unsigned int start = glyph.length; |
|
|
|
unsigned int start = glyph.length; |
|
|
@ -947,24 +931,22 @@ struct glyf |
|
|
|
} |
|
|
|
} |
|
|
|
*length = end - start; |
|
|
|
*length = end - start; |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
else if (glyph_header.is_simple_glyph ()) |
|
|
|
{ |
|
|
|
{ |
|
|
|
unsigned int instruction_len_offset = glyph_header.simple_instruction_len_offset (); |
|
|
|
unsigned int instruction_len_offset = glyph_header.simple_instruction_len_offset (); |
|
|
|
if (unlikely (instruction_len_offset + 2 > glyph.length)) |
|
|
|
if (unlikely (instruction_len_offset + 2 > glyph.length)) return false; |
|
|
|
{ |
|
|
|
|
|
|
|
DEBUG_MSG (SUBSET, nullptr, "Glyph size is too short, missing field instructionLength."); |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const HBUINT16 &instruction_len = StructAtOffset<HBUINT16> (&glyph, instruction_len_offset); |
|
|
|
const HBUINT16 &instruction_len = StructAtOffset<HBUINT16> (&glyph, instruction_len_offset); |
|
|
|
/* Out of bounds of the current glyph */ |
|
|
|
/* Out of bounds of the current glyph */ |
|
|
|
if (unlikely (glyph_header.simple_length (instruction_len) > glyph.length)) |
|
|
|
if (unlikely (glyph_header.simple_length (instruction_len) > glyph.length)) return false; |
|
|
|
{ |
|
|
|
|
|
|
|
DEBUG_MSG (SUBSET, nullptr, "The instructions array overruns the glyph's boundaries."); |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
*length = (uint16_t) instruction_len; |
|
|
|
*length = (uint16_t) instruction_len; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
else /* Empty glyph */ |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
*length = 0; |
|
|
|
|
|
|
|
/* only 0 byte glyphs are healthy when missing GlyphHeader */ |
|
|
|
|
|
|
|
return glyph.length == 0; |
|
|
|
|
|
|
|
} |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|