diff options
Diffstat (limited to 'thirdparty/harfbuzz/src/hb-ot-glyf-table.hh')
-rw-r--r-- | thirdparty/harfbuzz/src/hb-ot-glyf-table.hh | 140 |
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); } |