summaryrefslogtreecommitdiff
path: root/thirdparty/harfbuzz/src/hb-ot-glyf-table.hh
diff options
context:
space:
mode:
Diffstat (limited to 'thirdparty/harfbuzz/src/hb-ot-glyf-table.hh')
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-glyf-table.hh140
1 files changed, 105 insertions, 35 deletions
diff --git a/thirdparty/harfbuzz/src/hb-ot-glyf-table.hh b/thirdparty/harfbuzz/src/hb-ot-glyf-table.hh
index 5352156f02..ff7b9b2d25 100644
--- a/thirdparty/harfbuzz/src/hb-ot-glyf-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-glyf-table.hh
@@ -45,6 +45,10 @@ namespace OT {
*/
#define HB_OT_TAG_loca HB_TAG('l','o','c','a')
+#ifndef HB_MAX_COMPOSITE_OPERATIONS
+#define HB_MAX_COMPOSITE_OPERATIONS 100000
+#endif
+
struct loca
{
@@ -98,7 +102,7 @@ struct glyf
unsigned num_offsets = padded_offsets.len () + 1;
bool use_short_loca = max_offset < 0x1FFFF;
unsigned entry_size = use_short_loca ? 2 : 4;
- char *loca_prime_data = (char *) calloc (entry_size, num_offsets);
+ char *loca_prime_data = (char *) hb_calloc (entry_size, num_offsets);
if (unlikely (!loca_prime_data)) return false;
@@ -115,7 +119,7 @@ struct glyf
entry_size * num_offsets,
HB_MEMORY_MODE_WRITABLE,
loca_prime_data,
- free);
+ hb_free);
bool result = plan->add_table (HB_OT_TAG_loca, loca_blob)
&& _add_head_and_set_loca_version (plan, use_short_loca);
@@ -209,10 +213,15 @@ struct glyf
if (!plan->old_gid_for_new_gid (new_gid, &subset_glyph.old_gid))
return subset_glyph;
- subset_glyph.source_glyph = glyf.glyph_for_gid (subset_glyph.old_gid, true);
- if (plan->drop_hints) subset_glyph.drop_hints_bytes ();
- else subset_glyph.dest_start = subset_glyph.source_glyph.get_bytes ();
-
+ if (new_gid == 0 &&
+ !(plan->flags & HB_SUBSET_FLAGS_NOTDEF_OUTLINE))
+ subset_glyph.source_glyph = Glyph ();
+ else
+ subset_glyph.source_glyph = glyf.glyph_for_gid (subset_glyph.old_gid, true);
+ if (plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
+ subset_glyph.drop_hints_bytes ();
+ else
+ subset_glyph.dest_start = subset_glyph.source_glyph.get_bytes ();
return subset_glyph;
})
| hb_sink (glyphs)
@@ -281,6 +290,11 @@ struct glyf
hb_codepoint_t get_glyph_index () const { return glyphIndex; }
void drop_instructions_flag () { flags = (uint16_t) flags & ~WE_HAVE_INSTRUCTIONS; }
+ void set_overlaps_flag ()
+ {
+ flags = (uint16_t) flags | OVERLAP_COMPOUND;
+ }
+
bool has_instructions () const { return flags & WE_HAVE_INSTRUCTIONS; }
bool has_more () const { return flags & MORE_COMPONENTS; }
@@ -383,9 +397,12 @@ struct glyf
{
typedef const CompositeGlyphChain *__item_t__;
composite_iter_t (hb_bytes_t glyph_, __item_t__ current_) :
- glyph (glyph_), current (current_)
- { if (!check_range (current)) current = nullptr; }
- composite_iter_t () : glyph (hb_bytes_t ()), current (nullptr) {}
+ glyph (glyph_), current (nullptr), current_size (0)
+ {
+ set_next (current_);
+ }
+
+ composite_iter_t () : glyph (hb_bytes_t ()), current (nullptr), current_size (0) {}
const CompositeGlyphChain &__item__ () const { return *current; }
bool __more__ () const { return current; }
@@ -393,23 +410,36 @@ struct glyf
{
if (!current->has_more ()) { current = nullptr; return; }
- const CompositeGlyphChain *possible = &StructAfter<CompositeGlyphChain,
- CompositeGlyphChain> (*current);
- if (!check_range (possible)) { current = nullptr; return; }
- current = possible;
+ set_next (&StructAtOffset<CompositeGlyphChain> (current, current_size));
}
bool operator != (const composite_iter_t& o) const
{ return glyph != o.glyph || current != o.current; }
- bool check_range (const CompositeGlyphChain *composite) const
+
+ void set_next (const CompositeGlyphChain *composite)
{
- return glyph.check_range (composite, CompositeGlyphChain::min_size)
- && glyph.check_range (composite, composite->get_size ());
+ if (!glyph.check_range (composite, CompositeGlyphChain::min_size))
+ {
+ current = nullptr;
+ current_size = 0;
+ return;
+ }
+ unsigned size = composite->get_size ();
+ if (!glyph.check_range (composite, size))
+ {
+ current = nullptr;
+ current_size = 0;
+ return;
+ }
+
+ current = composite;
+ current_size = size;
}
private:
hb_bytes_t glyph;
__item_t__ current;
+ unsigned current_size;
};
enum phantom_point_index_t
@@ -427,14 +457,14 @@ struct glyf
{
enum simple_glyph_flag_t
{
- FLAG_ON_CURVE = 0x01,
- FLAG_X_SHORT = 0x02,
- FLAG_Y_SHORT = 0x04,
- FLAG_REPEAT = 0x08,
- FLAG_X_SAME = 0x10,
- FLAG_Y_SAME = 0x20,
- FLAG_RESERVED1 = 0x40,
- FLAG_RESERVED2 = 0x80
+ FLAG_ON_CURVE = 0x01,
+ FLAG_X_SHORT = 0x02,
+ FLAG_Y_SHORT = 0x04,
+ FLAG_REPEAT = 0x08,
+ FLAG_X_SAME = 0x10,
+ FLAG_Y_SAME = 0x20,
+ FLAG_OVERLAP_SIMPLE = 0x40,
+ FLAG_RESERVED2 = 0x80
};
private:
@@ -495,8 +525,8 @@ struct glyf
const Glyph trim_padding () const
{
/* based on FontTools _g_l_y_f.py::trim */
- const char *glyph = bytes.arrayZ;
- const char *glyph_end = glyph + bytes.length;
+ const uint8_t *glyph = (uint8_t*) bytes.arrayZ;
+ const uint8_t *glyph_end = glyph + bytes.length;
/* simple glyph w/contours, possibly trimmable */
glyph += instruction_len_offset ();
@@ -553,6 +583,17 @@ struct glyf
dest_end = bytes.sub_array (glyph_length, bytes.length - glyph_length);
}
+ void set_overlaps_flag ()
+ {
+ if (unlikely (!header.numberOfContours)) return;
+
+ unsigned flags_offset = length (instructions_length ());
+ if (unlikely (length (flags_offset + 1) > bytes.length)) return;
+
+ HBUINT8 &first_flag = (HBUINT8 &) StructAtOffset<HBUINT16> (&bytes, flags_offset);
+ first_flag = (uint8_t) first_flag | FLAG_OVERLAP_SIMPLE;
+ }
+
static bool read_points (const HBUINT8 *&p /* IN/OUT */,
contour_point_vector_t &points_ /* IN/OUT */,
const hb_bytes_t &bytes,
@@ -666,6 +707,12 @@ struct glyf
/* Chop instructions off the end */
void drop_hints_bytes (hb_bytes_t &dest_start) const
{ dest_start = bytes.sub_array (0, bytes.length - instructions_length (bytes)); }
+
+ void set_overlaps_flag ()
+ {
+ const_cast<CompositeGlyphChain &> (StructAfter<CompositeGlyphChain, GlyphHeader> (header))
+ .set_overlaps_flag ();
+ }
};
enum glyph_type_t { EMPTY, SIMPLE, COMPOSITE };
@@ -695,6 +742,15 @@ struct glyf
}
}
+ void set_overlaps_flag ()
+ {
+ switch (type) {
+ case COMPOSITE: CompositeGlyph (*header, bytes).set_overlaps_flag (); return;
+ case SIMPLE: SimpleGlyph (*header, bytes).set_overlaps_flag (); return;
+ default: return;
+ }
+ }
+
void drop_hints_bytes (hb_bytes_t &dest_start, hb_bytes_t &dest_end) const
{
switch (type) {
@@ -886,7 +942,7 @@ struct glyf
{
if (gid >= num_glyphs) return false;
- /* Making this alloc free is not that easy
+ /* Making this allocfree is not that easy
https://github.com/harfbuzz/harfbuzz/issues/2095
mostly because of gvar handling in VF fonts,
perhaps a separate path for non-VF fonts can be considered */
@@ -1045,18 +1101,28 @@ struct glyf
return needs_padding_removal ? glyph.trim_padding () : glyph;
}
- void
- add_gid_and_children (hb_codepoint_t gid, hb_set_t *gids_to_retain,
- unsigned int depth = 0) const
+ unsigned
+ add_gid_and_children (hb_codepoint_t gid,
+ hb_set_t *gids_to_retain,
+ unsigned depth = 0,
+ unsigned operation_count = 0) const
{
- if (unlikely (depth++ > HB_MAX_NESTING_LEVEL)) return;
+ if (unlikely (depth++ > HB_MAX_NESTING_LEVEL)) return operation_count;
+ if (unlikely (operation_count++ > HB_MAX_COMPOSITE_OPERATIONS)) return operation_count;
/* Check if is already visited */
- if (gids_to_retain->has (gid)) return;
+ if (gids_to_retain->has (gid)) return operation_count;
gids_to_retain->add (gid);
- for (auto &item : glyph_for_gid (gid).get_composite_iterator ())
- add_gid_and_children (item.get_glyph_index (), gids_to_retain, depth);
+ auto it = glyph_for_gid (gid).get_composite_iterator ();
+ while (it)
+ {
+ auto item = *(it++);
+ operation_count +=
+ add_gid_and_children (item.get_glyph_index (), gids_to_retain, depth, operation_count);
+ }
+
+ return operation_count;
}
#ifdef HB_EXPERIMENTAL_API
@@ -1230,7 +1296,11 @@ struct glyf
const_cast<CompositeGlyphChain &> (_).set_glyph_index (new_gid);
}
- if (plan->drop_hints) Glyph (dest_glyph).drop_hints ();
+ 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);
}