diff options
Diffstat (limited to 'thirdparty/harfbuzz')
162 files changed, 7566 insertions, 4428 deletions
diff --git a/thirdparty/harfbuzz/src/OT/Layout/Common/Coverage.hh b/thirdparty/harfbuzz/src/OT/Layout/Common/Coverage.hh index eef89a2879..fbd7c642ab 100644 --- a/thirdparty/harfbuzz/src/OT/Layout/Common/Coverage.hh +++ b/thirdparty/harfbuzz/src/OT/Layout/Common/Coverage.hh @@ -49,7 +49,7 @@ struct Coverage HBUINT16 format; /* Format identifier */ CoverageFormat1_3<SmallTypes> format1; CoverageFormat2_4<SmallTypes> format2; -#ifndef HB_NO_BORING_EXPANSION +#ifndef HB_NO_BEYOND_64K CoverageFormat1_3<MediumTypes>format3; CoverageFormat2_4<MediumTypes>format4; #endif @@ -65,7 +65,7 @@ struct Coverage { case 1: return_trace (u.format1.sanitize (c)); case 2: return_trace (u.format2.sanitize (c)); -#ifndef HB_NO_BORING_EXPANSION +#ifndef HB_NO_BEYOND_64K case 3: return_trace (u.format3.sanitize (c)); case 4: return_trace (u.format4.sanitize (c)); #endif @@ -74,10 +74,8 @@ struct Coverage } /* Has interface. */ - static constexpr unsigned SENTINEL = NOT_COVERED; - typedef unsigned int value_t; - value_t operator [] (hb_codepoint_t k) const { return get (k); } - bool has (hb_codepoint_t k) const { return (*this)[k] != SENTINEL; } + unsigned operator [] (hb_codepoint_t k) const { return get (k); } + bool has (hb_codepoint_t k) const { return (*this)[k] != NOT_COVERED; } /* Predicate. */ bool operator () (hb_codepoint_t k) const { return has (k); } @@ -87,7 +85,7 @@ struct Coverage switch (u.format) { case 1: return u.format1.get_coverage (glyph_id); case 2: return u.format2.get_coverage (glyph_id); -#ifndef HB_NO_BORING_EXPANSION +#ifndef HB_NO_BEYOND_64K case 3: return u.format3.get_coverage (glyph_id); case 4: return u.format4.get_coverage (glyph_id); #endif @@ -100,7 +98,7 @@ struct Coverage switch (u.format) { case 1: return u.format1.get_population (); case 2: return u.format2.get_population (); -#ifndef HB_NO_BORING_EXPANSION +#ifndef HB_NO_BEYOND_64K case 3: return u.format3.get_population (); case 4: return u.format4.get_population (); #endif @@ -127,7 +125,7 @@ struct Coverage } u.format = count <= num_ranges * 3 ? 1 : 2; -#ifndef HB_NO_BORING_EXPANSION +#ifndef HB_NO_BEYOND_64K if (count && last > 0xFFFFu) u.format += 2; #endif @@ -136,7 +134,7 @@ struct Coverage { case 1: return_trace (u.format1.serialize (c, glyphs)); case 2: return_trace (u.format2.serialize (c, glyphs)); -#ifndef HB_NO_BORING_EXPANSION +#ifndef HB_NO_BEYOND_64K case 3: return_trace (u.format3.serialize (c, glyphs)); case 4: return_trace (u.format4.serialize (c, glyphs)); #endif @@ -166,7 +164,7 @@ struct Coverage { case 1: return u.format1.intersects (glyphs); case 2: return u.format2.intersects (glyphs); -#ifndef HB_NO_BORING_EXPANSION +#ifndef HB_NO_BEYOND_64K case 3: return u.format3.intersects (glyphs); case 4: return u.format4.intersects (glyphs); #endif @@ -179,7 +177,7 @@ struct Coverage { case 1: return u.format1.intersects_coverage (glyphs, index); case 2: return u.format2.intersects_coverage (glyphs, index); -#ifndef HB_NO_BORING_EXPANSION +#ifndef HB_NO_BEYOND_64K case 3: return u.format3.intersects_coverage (glyphs, index); case 4: return u.format4.intersects_coverage (glyphs, index); #endif @@ -196,7 +194,7 @@ struct Coverage { case 1: return u.format1.collect_coverage (glyphs); case 2: return u.format2.collect_coverage (glyphs); -#ifndef HB_NO_BORING_EXPANSION +#ifndef HB_NO_BEYOND_64K case 3: return u.format3.collect_coverage (glyphs); case 4: return u.format4.collect_coverage (glyphs); #endif @@ -212,7 +210,7 @@ struct Coverage { case 1: return u.format1.intersect_set (glyphs, intersect_glyphs); case 2: return u.format2.intersect_set (glyphs, intersect_glyphs); -#ifndef HB_NO_BORING_EXPANSION +#ifndef HB_NO_BEYOND_64K case 3: return u.format3.intersect_set (glyphs, intersect_glyphs); case 4: return u.format4.intersect_set (glyphs, intersect_glyphs); #endif @@ -225,13 +223,13 @@ struct Coverage static constexpr bool is_sorted_iterator = true; iter_t (const Coverage &c_ = Null (Coverage)) { - memset (this, 0, sizeof (*this)); + hb_memset (this, 0, sizeof (*this)); format = c_.u.format; switch (format) { case 1: u.format1.init (c_.u.format1); return; case 2: u.format2.init (c_.u.format2); return; -#ifndef HB_NO_BORING_EXPANSION +#ifndef HB_NO_BEYOND_64K case 3: u.format3.init (c_.u.format3); return; case 4: u.format4.init (c_.u.format4); return; #endif @@ -244,7 +242,7 @@ struct Coverage { case 1: return u.format1.__more__ (); case 2: return u.format2.__more__ (); -#ifndef HB_NO_BORING_EXPANSION +#ifndef HB_NO_BEYOND_64K case 3: return u.format3.__more__ (); case 4: return u.format4.__more__ (); #endif @@ -257,7 +255,7 @@ struct Coverage { case 1: u.format1.__next__ (); break; case 2: u.format2.__next__ (); break; -#ifndef HB_NO_BORING_EXPANSION +#ifndef HB_NO_BEYOND_64K case 3: u.format3.__next__ (); break; case 4: u.format4.__next__ (); break; #endif @@ -273,7 +271,7 @@ struct Coverage { case 1: return u.format1.get_glyph (); case 2: return u.format2.get_glyph (); -#ifndef HB_NO_BORING_EXPANSION +#ifndef HB_NO_BEYOND_64K case 3: return u.format3.get_glyph (); case 4: return u.format4.get_glyph (); #endif @@ -287,7 +285,7 @@ struct Coverage { case 1: return u.format1 != o.u.format1; case 2: return u.format2 != o.u.format2; -#ifndef HB_NO_BORING_EXPANSION +#ifndef HB_NO_BEYOND_64K case 3: return u.format3 != o.u.format3; case 4: return u.format4 != o.u.format4; #endif @@ -302,7 +300,7 @@ struct Coverage { case 1: it.u.format1 = u.format1.__end__ (); break; case 2: it.u.format2 = u.format2.__end__ (); break; -#ifndef HB_NO_BORING_EXPANSION +#ifndef HB_NO_BEYOND_64K case 3: it.u.format3 = u.format3.__end__ (); break; case 4: it.u.format4 = u.format4.__end__ (); break; #endif @@ -314,7 +312,7 @@ struct Coverage private: unsigned int format; union { -#ifndef HB_NO_BORING_EXPANSION +#ifndef HB_NO_BEYOND_64K CoverageFormat2_4<MediumTypes>::iter_t format4; /* Put this one first since it's larger; helps shut up compiler. */ CoverageFormat1_3<MediumTypes>::iter_t format3; #endif diff --git a/thirdparty/harfbuzz/src/OT/Layout/Common/CoverageFormat1.hh b/thirdparty/harfbuzz/src/OT/Layout/Common/CoverageFormat1.hh index 82fd48dc50..5d68e3d15e 100644 --- a/thirdparty/harfbuzz/src/OT/Layout/Common/CoverageFormat1.hh +++ b/thirdparty/harfbuzz/src/OT/Layout/Common/CoverageFormat1.hh @@ -77,7 +77,14 @@ struct CoverageFormat1_3 bool intersects (const hb_set_t *glyphs) const { - /* TODO Speed up, using hb_set_next() and bsearch()? */ + if (glyphArray.len > glyphs->get_population () * hb_bit_storage ((unsigned) glyphArray.len) / 2) + { + for (hb_codepoint_t g = HB_SET_VALUE_INVALID; glyphs->next (&g);) + if (get_coverage (g) != NOT_COVERED) + return true; + return false; + } + for (const auto& g : glyphArray.as_array ()) if (glyphs->has (g)) return true; diff --git a/thirdparty/harfbuzz/src/OT/Layout/Common/CoverageFormat2.hh b/thirdparty/harfbuzz/src/OT/Layout/Common/CoverageFormat2.hh index 974d094633..d7fcc35202 100644 --- a/thirdparty/harfbuzz/src/OT/Layout/Common/CoverageFormat2.hh +++ b/thirdparty/harfbuzz/src/OT/Layout/Common/CoverageFormat2.hh @@ -80,8 +80,6 @@ struct CoverageFormat2_4 TRACE_SERIALIZE (this); if (unlikely (!c->extend_min (this))) return_trace (false); - /* TODO(iter) Write more efficiently? */ - unsigned num_ranges = 0; hb_codepoint_t last = (hb_codepoint_t) -2; for (auto g: glyphs) @@ -115,26 +113,22 @@ struct CoverageFormat2_4 bool intersects (const hb_set_t *glyphs) const { + if (rangeRecord.len > glyphs->get_population () * hb_bit_storage ((unsigned) rangeRecord.len) / 2) + { + for (hb_codepoint_t g = HB_SET_VALUE_INVALID; glyphs->next (&g);) + if (get_coverage (g) != NOT_COVERED) + return true; + return false; + } + return hb_any (+ hb_iter (rangeRecord) | hb_map ([glyphs] (const RangeRecord<Types> &range) { return range.intersects (*glyphs); })); } bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const { - auto cmp = [] (const void *pk, const void *pr) -> int - { - unsigned index = * (const unsigned *) pk; - const RangeRecord<Types> &range = * (const RangeRecord<Types> *) pr; - if (index < range.value) return -1; - if (index > (unsigned int) range.value + (range.last - range.first)) return +1; - return 0; - }; - - auto arr = rangeRecord.as_array (); - unsigned idx; - if (hb_bsearch_impl (&idx, index, - arr.arrayZ, arr.length, sizeof (arr[0]), - (int (*)(const void *_key, const void *_item)) cmp)) - return arr.arrayZ[idx].intersects (*glyphs); + auto *range = rangeRecord.as_array ().bsearch (index); + if (range) + return range->intersects (*glyphs); return false; } @@ -142,9 +136,14 @@ struct CoverageFormat2_4 hb_requires (hb_is_sink_of (IterableOut, hb_codepoint_t))> void intersect_set (const hb_set_t &glyphs, IterableOut&& intersect_glyphs) const { + /* Break out of loop for overlapping, broken, tables, + * to avoid fuzzer timouts. */ + hb_codepoint_t last = 0; for (const auto& range : rangeRecord) { - hb_codepoint_t last = range.last; + if (unlikely (range.first < last)) + break; + last = range.last; for (hb_codepoint_t g = range.first - 1; glyphs.next (&g) && g <= last;) intersect_glyphs << g; diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/GPOS.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/GPOS.hh index 72829377a6..9493ec987e 100644 --- a/thirdparty/harfbuzz/src/OT/Layout/GPOS/GPOS.hh +++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/GPOS.hh @@ -39,7 +39,7 @@ struct GPOS : GSUBGPOS bool subset (hb_subset_context_t *c) const { - hb_subset_layout_context_t l (c, tableTag, c->plan->gpos_lookups, c->plan->gpos_langsys, c->plan->gpos_features); + hb_subset_layout_context_t l (c, tableTag); return GSUBGPOS::subset<PosLookup> (&l); } diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkBasePos.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkBasePos.hh index c99b6b2e4b..edf7099c07 100644 --- a/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkBasePos.hh +++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkBasePos.hh @@ -13,7 +13,7 @@ struct MarkBasePos union { HBUINT16 format; /* Format identifier */ MarkBasePosFormat1_2<SmallTypes> format1; -#ifndef HB_NO_BORING_EXPANSION +#ifndef HB_NO_BEYOND_64K MarkBasePosFormat1_2<MediumTypes> format2; #endif } u; @@ -26,7 +26,7 @@ struct MarkBasePos if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); switch (u.format) { case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...)); -#ifndef HB_NO_BORING_EXPANSION +#ifndef HB_NO_BEYOND_64K case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...)); #endif default:return_trace (c->default_return_value ()); diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkLigPos.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkLigPos.hh index 8a4de9ffaa..09152fd876 100644 --- a/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkLigPos.hh +++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkLigPos.hh @@ -13,7 +13,7 @@ struct MarkLigPos union { HBUINT16 format; /* Format identifier */ MarkLigPosFormat1_2<SmallTypes> format1; -#ifndef HB_NO_BORING_EXPANSION +#ifndef HB_NO_BEYOND_64K MarkLigPosFormat1_2<MediumTypes> format2; #endif } u; @@ -26,7 +26,7 @@ struct MarkLigPos if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); switch (u.format) { case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...)); -#ifndef HB_NO_BORING_EXPANSION +#ifndef HB_NO_BEYOND_64K case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...)); #endif default:return_trace (c->default_return_value ()); diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkMarkPos.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkMarkPos.hh index 74b5105c42..4118fc304f 100644 --- a/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkMarkPos.hh +++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkMarkPos.hh @@ -13,7 +13,7 @@ struct MarkMarkPos union { HBUINT16 format; /* Format identifier */ MarkMarkPosFormat1_2<SmallTypes> format1; -#ifndef HB_NO_BORING_EXPANSION +#ifndef HB_NO_BEYOND_64K MarkMarkPosFormat1_2<MediumTypes> format2; #endif } u; @@ -26,7 +26,7 @@ struct MarkMarkPos if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); switch (u.format) { case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...)); -#ifndef HB_NO_BORING_EXPANSION +#ifndef HB_NO_BEYOND_64K case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...)); #endif default:return_trace (c->default_return_value ()); diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairPos.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairPos.hh index 72bfc43dc4..9823768cbc 100644 --- a/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairPos.hh +++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairPos.hh @@ -15,7 +15,7 @@ struct PairPos HBUINT16 format; /* Format identifier */ PairPosFormat1_3<SmallTypes> format1; PairPosFormat2_4<SmallTypes> format2; -#ifndef HB_NO_BORING_EXPANSION +#ifndef HB_NO_BEYOND_64K PairPosFormat1_3<MediumTypes> format3; PairPosFormat2_4<MediumTypes> format4; #endif @@ -30,7 +30,7 @@ struct PairPos switch (u.format) { case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...)); case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...)); -#ifndef HB_NO_BORING_EXPANSION +#ifndef HB_NO_BEYOND_64K case 3: return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...)); case 4: return_trace (c->dispatch (u.format4, std::forward<Ts> (ds)...)); #endif diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairPosFormat1.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairPosFormat1.hh index ddf7313f94..9c9b268889 100644 --- a/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairPosFormat1.hh +++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairPosFormat1.hh @@ -51,8 +51,21 @@ struct PairPosFormat1_3 bool intersects (const hb_set_t *glyphs) const { + auto &cov = this+coverage; + + if (pairSet.len > glyphs->get_population () * hb_bit_storage ((unsigned) pairSet.len) / 4) + { + for (hb_codepoint_t g = HB_SET_VALUE_INVALID; glyphs->next (&g);) + { + unsigned i = cov.get_coverage (g); + if ((this+pairSet[i]).intersects (glyphs, valueFormat)) + return true; + } + return false; + } + return - + hb_zip (this+coverage, pairSet) + + hb_zip (cov, pairSet) | hb_filter (*glyphs, hb_first) | hb_map (hb_second) | hb_map ([glyphs, this] (const typename Types::template OffsetTo<PairSet> &_) @@ -171,12 +184,16 @@ struct PairPosFormat1_3 unsigned format1 = 0; unsigned format2 = 0; for (const auto & _ : - + hb_zip (this+coverage, pairSet) | hb_filter (glyphset, hb_first) | hb_map (hb_second)) + + hb_zip (this+coverage, pairSet) + | hb_filter (glyphset, hb_first) + | hb_map (hb_second) + ) { const PairSet& set = (this + _); const PairValueRecord *record = &set.firstPairValueRecord; - for (unsigned i = 0; i < set.len; i++) + unsigned count = set.len; + for (unsigned i = 0; i < count; i++) { if (record->intersects (glyphset)) { @@ -185,6 +202,9 @@ struct PairPosFormat1_3 } record = &StructAtOffset<const PairValueRecord> (record, record_size); } + + if (format1 == valueFormat[0] && format2 == valueFormat[1]) + break; } return hb_pair (format1, format2); diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairPosFormat2.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairPosFormat2.hh index 83b093b988..9c87ac2b03 100644 --- a/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairPosFormat2.hh +++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairPosFormat2.hh @@ -220,17 +220,25 @@ struct PairPosFormat2_4 if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ()) { c->buffer->message (c->font, - "kerning glyphs at %d,%d", + "try kerning glyphs at %d,%d", c->buffer->idx, skippy_iter.idx); } applied_first = valueFormat1.apply_value (c, this, v, buffer->cur_pos()); applied_second = valueFormat2.apply_value (c, this, v + len1, buffer->pos[skippy_iter.idx]); + if (applied_first || applied_second) + if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ()) + { + c->buffer->message (c->font, + "kerned glyphs at %d,%d", + c->buffer->idx, skippy_iter.idx); + } + if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ()) { c->buffer->message (c->font, - "kerned glyphs at %d,%d", + "tried kerning glyphs at %d,%d", c->buffer->idx, skippy_iter.idx); } @@ -241,10 +249,15 @@ struct PairPosFormat2_4 boring: buffer->unsafe_to_concat (buffer->idx, skippy_iter.idx + 1); + if (len2) + { + skippy_iter.idx++; + // https://github.com/harfbuzz/harfbuzz/issues/3824 + // https://github.com/harfbuzz/harfbuzz/issues/3888#issuecomment-1326781116 + buffer->unsafe_to_break (buffer->idx, skippy_iter.idx + 1); + } buffer->idx = skippy_iter.idx; - if (len2) - buffer->idx++; return_trace (true); } @@ -309,6 +322,7 @@ struct PairPosFormat2_4 { unsigned len1 = valueFormat1.get_len (); unsigned len2 = valueFormat2.get_len (); + unsigned record_size = len1 + len2; unsigned format1 = 0; unsigned format2 = 0; @@ -317,10 +331,13 @@ struct PairPosFormat2_4 { for (unsigned class2_idx : + hb_range ((unsigned) class2Count) | hb_filter (klass2_map)) { - unsigned idx = (class1_idx * (unsigned) class2Count + class2_idx) * (len1 + len2); + unsigned idx = (class1_idx * (unsigned) class2Count + class2_idx) * record_size; format1 = format1 | valueFormat1.get_effective_format (&values[idx]); format2 = format2 | valueFormat2.get_effective_format (&values[idx + len1]); } + + if (format1 == valueFormat1 && format2 == valueFormat2) + break; } return hb_pair (format1, format2); diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairSet.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairSet.hh index aa48d933c3..a318f39913 100644 --- a/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairSet.hh +++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairSet.hh @@ -112,24 +112,38 @@ struct PairSet if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ()) { c->buffer->message (c->font, - "kerning glyphs at %d,%d", + "try kerning glyphs at %d,%d", c->buffer->idx, pos); } bool applied_first = valueFormats[0].apply_value (c, this, &record->values[0], buffer->cur_pos()); bool applied_second = valueFormats[1].apply_value (c, this, &record->values[len1], buffer->pos[pos]); + if (applied_first || applied_second) + if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ()) + { + c->buffer->message (c->font, + "kerned glyphs at %d,%d", + c->buffer->idx, pos); + } + if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ()) { c->buffer->message (c->font, - "kerned glyphs at %d,%d", + "tried kerning glyphs at %d,%d", c->buffer->idx, pos); } if (applied_first || applied_second) buffer->unsafe_to_break (buffer->idx, pos + 1); + if (len2) - pos++; + { + pos++; + // https://github.com/harfbuzz/harfbuzz/issues/3824 + // https://github.com/harfbuzz/harfbuzz/issues/3888#issuecomment-1326781116 + buffer->unsafe_to_break (buffer->idx, pos + 1); + } buffer->idx = pos; return_trace (true); diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/SinglePosFormat1.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/SinglePosFormat1.hh index 5a9dd58a63..b4c9fc3db0 100644 --- a/thirdparty/harfbuzz/src/OT/Layout/GPOS/SinglePosFormat1.hh +++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/SinglePosFormat1.hh @@ -80,6 +80,24 @@ struct SinglePosFormat1 return_trace (true); } + bool + position_single (hb_font_t *font, + hb_direction_t direction, + hb_codepoint_t gid, + hb_glyph_position_t &pos) const + { + unsigned int index = (this+coverage).get_coverage (gid); + if (likely (index == NOT_COVERED)) return false; + + /* This is ugly... */ + hb_buffer_t buffer; + buffer.props.direction = direction; + OT::hb_ot_apply_context_t c (1, font, &buffer); + + valueFormat.apply_value (&c, this, values, pos); + return true; + } + template<typename Iterator, typename SrcLookup, hb_requires (hb_is_iterator (Iterator))> diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/SinglePosFormat2.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/SinglePosFormat2.hh index 8a6e8a42a6..c77951156b 100644 --- a/thirdparty/harfbuzz/src/OT/Layout/GPOS/SinglePosFormat2.hh +++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/SinglePosFormat2.hh @@ -68,7 +68,7 @@ struct SinglePosFormat2 unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint); if (likely (index == NOT_COVERED)) return_trace (false); - if (likely (index >= valueCount)) return_trace (false); + if (unlikely (index >= valueCount)) return_trace (false); if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ()) { @@ -92,6 +92,28 @@ struct SinglePosFormat2 return_trace (true); } + bool + position_single (hb_font_t *font, + hb_direction_t direction, + hb_codepoint_t gid, + hb_glyph_position_t &pos) const + { + unsigned int index = (this+coverage).get_coverage (gid); + if (likely (index == NOT_COVERED)) return false; + if (unlikely (index >= valueCount)) return false; + + /* This is ugly... */ + hb_buffer_t buffer; + buffer.props.direction = direction; + OT::hb_ot_apply_context_t c (1, font, &buffer); + + valueFormat.apply_value (&c, this, + &values[index * valueFormat.get_len ()], + pos); + return true; + } + + template<typename Iterator, typename SrcLookup, hb_requires (hb_is_iterator (Iterator))> diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/AlternateSet.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/AlternateSet.hh index 4a9e9672eb..6c50c9717a 100644 --- a/thirdparty/harfbuzz/src/OT/Layout/GSUB/AlternateSet.hh +++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/AlternateSet.hh @@ -84,7 +84,7 @@ struct AlternateSet { if (alternates.len && alternate_count) { - + alternates.sub_array (start_offset, alternate_count) + + alternates.as_array ().sub_array (start_offset, alternate_count) | hb_sink (hb_array (alternate_glyphs, *alternate_count)) ; } diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/AlternateSubst.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/AlternateSubst.hh index 37406179a2..9d7cd6fddf 100644 --- a/thirdparty/harfbuzz/src/OT/Layout/GSUB/AlternateSubst.hh +++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/AlternateSubst.hh @@ -14,7 +14,7 @@ struct AlternateSubst union { HBUINT16 format; /* Format identifier */ AlternateSubstFormat1_2<SmallTypes> format1; -#ifndef HB_NO_BORING_EXPANSION +#ifndef HB_NO_BEYOND_64K AlternateSubstFormat1_2<MediumTypes> format2; #endif } u; @@ -27,7 +27,7 @@ struct AlternateSubst if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); switch (u.format) { case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...)); -#ifndef HB_NO_BORING_EXPANSION +#ifndef HB_NO_BEYOND_64K case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...)); #endif default:return_trace (c->default_return_value ()); diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/GSUB.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/GSUB.hh index c0ff098f49..900cf603e4 100644 --- a/thirdparty/harfbuzz/src/OT/Layout/GSUB/GSUB.hh +++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/GSUB.hh @@ -27,7 +27,7 @@ struct GSUB : GSUBGPOS bool subset (hb_subset_context_t *c) const { - hb_subset_layout_context_t l (c, tableTag, c->plan->gsub_lookups, c->plan->gsub_langsys, c->plan->gsub_features); + hb_subset_layout_context_t l (c, tableTag); return GSUBGPOS::subset<SubstLookup> (&l); } diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/Ligature.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/Ligature.hh index f373d921b5..cdb35f525b 100644 --- a/thirdparty/harfbuzz/src/OT/Layout/GSUB/Ligature.hh +++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/Ligature.hh @@ -118,7 +118,7 @@ struct Ligature match_positions[i] += delta; if (i) *p++ = ','; - sprintf (p, "%u", match_positions[i]); + snprintf (p, sizeof(buf) - (p - buf), "%u", match_positions[i]); p += strlen(p); } diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/LigatureSubst.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/LigatureSubst.hh index 63707972a8..7ba19e844c 100644 --- a/thirdparty/harfbuzz/src/OT/Layout/GSUB/LigatureSubst.hh +++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/LigatureSubst.hh @@ -14,7 +14,7 @@ struct LigatureSubst union { HBUINT16 format; /* Format identifier */ LigatureSubstFormat1_2<SmallTypes> format1; -#ifndef HB_NO_BORING_EXPANSION +#ifndef HB_NO_BEYOND_64K LigatureSubstFormat1_2<MediumTypes> format2; #endif } u; @@ -27,7 +27,7 @@ struct LigatureSubst if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); switch (u.format) { case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...)); -#ifndef HB_NO_BORING_EXPANSION +#ifndef HB_NO_BEYOND_64K case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...)); #endif default:return_trace (c->default_return_value ()); diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/MultipleSubst.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/MultipleSubst.hh index 852ca3eac5..95710ed2be 100644 --- a/thirdparty/harfbuzz/src/OT/Layout/GSUB/MultipleSubst.hh +++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/MultipleSubst.hh @@ -14,7 +14,7 @@ struct MultipleSubst union { HBUINT16 format; /* Format identifier */ MultipleSubstFormat1_2<SmallTypes> format1; -#ifndef HB_NO_BORING_EXPANSION +#ifndef HB_NO_BEYOND_64K MultipleSubstFormat1_2<MediumTypes> format2; #endif } u; @@ -28,7 +28,7 @@ struct MultipleSubst if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); switch (u.format) { case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...)); -#ifndef HB_NO_BORING_EXPANSION +#ifndef HB_NO_BEYOND_64K case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...)); #endif default:return_trace (c->default_return_value ()); diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/Sequence.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/Sequence.hh index 3d84a5e6ea..e2190078b8 100644 --- a/thirdparty/harfbuzz/src/OT/Layout/GSUB/Sequence.hh +++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/Sequence.hh @@ -117,7 +117,7 @@ struct Sequence { if (buf < p) *p++ = ','; - sprintf (p, "%u", i); + snprintf (p, sizeof(buf) - (p - buf), "%u", i); p += strlen(p); } diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubst.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubst.hh index 6942e6997f..7da8103168 100644 --- a/thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubst.hh +++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubst.hh @@ -16,7 +16,7 @@ struct SingleSubst HBUINT16 format; /* Format identifier */ SingleSubstFormat1_3<SmallTypes> format1; SingleSubstFormat2_4<SmallTypes> format2; -#ifndef HB_NO_BORING_EXPANSION +#ifndef HB_NO_BEYOND_64K SingleSubstFormat1_3<MediumTypes> format3; SingleSubstFormat2_4<MediumTypes> format4; #endif @@ -32,7 +32,7 @@ struct SingleSubst switch (u.format) { case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...)); case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...)); -#ifndef HB_NO_BORING_EXPANSION +#ifndef HB_NO_BEYOND_64K case 3: return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...)); case 4: return_trace (c->dispatch (u.format4, std::forward<Ts> (ds)...)); #endif @@ -55,7 +55,7 @@ struct SingleSubst format = 1; hb_codepoint_t mask = 0xFFFFu; -#ifndef HB_NO_BORING_EXPANSION +#ifndef HB_NO_BEYOND_64K if (+ glyphs | hb_map_retains_sorting (hb_first) | hb_filter ([] (hb_codepoint_t gid) { return gid > 0xFFFFu; })) @@ -78,7 +78,7 @@ struct SingleSubst | hb_map_retains_sorting (hb_first), delta)); case 2: return_trace (u.format2.serialize (c, glyphs)); -#ifndef HB_NO_BORING_EXPANSION +#ifndef HB_NO_BEYOND_64K case 3: return_trace (u.format3.serialize (c, + glyphs | hb_map_retains_sorting (hb_first), diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubstFormat1.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubstFormat1.hh index 13665d7ba1..1be21b98bc 100644 --- a/thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubstFormat1.hh +++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubstFormat1.hh @@ -57,7 +57,7 @@ struct SingleSubstFormat1_3 hb_codepoint_t max_before = intersection.get_max (); hb_codepoint_t min_after = (min_before + d) & mask; hb_codepoint_t max_after = (max_before + d) & mask; - if (pop >= max_before - min_before && + if (intersection.get_population () == max_before - min_before + 1 && ((min_before <= min_after && min_after <= max_before) || (min_before <= max_after && max_after <= max_before))) return; diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubstFormat2.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubstFormat2.hh index 5416299754..01df714525 100644 --- a/thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubstFormat2.hh +++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubstFormat2.hh @@ -36,8 +36,24 @@ struct SingleSubstFormat2_4 void closure (hb_closure_context_t *c) const { - + hb_zip (this+coverage, substitute) - | hb_filter (c->parent_active_glyphs (), hb_first) + auto &cov = this+coverage; + auto &glyph_set = c->parent_active_glyphs (); + + if (substitute.len > glyph_set.get_population () * 4) + { + for (auto g : glyph_set) + { + unsigned i = cov.get_coverage (g); + if (i == NOT_COVERED || i >= substitute.len) + continue; + c->output->add (substitute.arrayZ[i]); + } + + return; + } + + + hb_zip (cov, substitute) + | hb_filter (glyph_set, hb_first) | hb_map (hb_second) | hb_sink (c->output) ; diff --git a/thirdparty/harfbuzz/src/OT/glyf/CompositeGlyph.hh b/thirdparty/harfbuzz/src/OT/glyf/CompositeGlyph.hh index fc8e309bc9..edf8cd8797 100644 --- a/thirdparty/harfbuzz/src/OT/glyf/CompositeGlyph.hh +++ b/thirdparty/harfbuzz/src/OT/glyf/CompositeGlyph.hh @@ -3,6 +3,7 @@ #include "../../hb-open-type.hh" +#include "composite-iter.hh" namespace OT { @@ -121,7 +122,7 @@ struct CompositeGlyphRecord if (flags & ARG_1_AND_2_ARE_WORDS) { // no overflow, copy and update value with deltas - memcpy (out, this, len); + hb_memcpy (out, this, len); const HBINT16 *px = reinterpret_cast<const HBINT16 *> (p); HBINT16 *o = reinterpret_cast<HBINT16 *> (out + len_before_val); @@ -135,7 +136,7 @@ struct CompositeGlyphRecord if (new_x <= 127 && new_x >= -128 && new_y <= 127 && new_y >= -128) { - memcpy (out, this, len); + hb_memcpy (out, this, len); HBINT8 *o = reinterpret_cast<HBINT8 *> (out + len_before_val); o[0] = new_x; o[1] = new_y; @@ -143,7 +144,7 @@ struct CompositeGlyphRecord else { // int8 overflows after deltas applied - memcpy (out, this, len_before_val); + hb_memcpy (out, this, len_before_val); //update flags CompositeGlyphRecord *o = reinterpret_cast<CompositeGlyphRecord *> (out); @@ -152,14 +153,14 @@ struct CompositeGlyphRecord HBINT16 new_value; new_value = new_x; - memcpy (out, &new_value, HBINT16::static_size); + hb_memcpy (out, &new_value, HBINT16::static_size); out += HBINT16::static_size; new_value = new_y; - memcpy (out, &new_value, HBINT16::static_size); + hb_memcpy (out, &new_value, HBINT16::static_size); out += HBINT16::static_size; - memcpy (out, p+2, len - len_before_val - 2); + hb_memcpy (out, p+2, len - len_before_val - 2); len += 2; } } @@ -252,55 +253,7 @@ struct CompositeGlyphRecord DEFINE_SIZE_MIN (4); }; -struct composite_iter_t : hb_iter_with_fallback_t<composite_iter_t, const CompositeGlyphRecord &> -{ - typedef const CompositeGlyphRecord *__item_t__; - composite_iter_t (hb_bytes_t glyph_, __item_t__ current_) : - glyph (glyph_), current (nullptr), current_size (0) - { - set_current (current_); - } - - composite_iter_t () : glyph (hb_bytes_t ()), current (nullptr), current_size (0) {} - - item_t __item__ () const { return *current; } - bool __more__ () const { return current; } - void __next__ () - { - if (!current->has_more ()) { current = nullptr; return; } - - set_current (&StructAtOffset<CompositeGlyphRecord> (current, current_size)); - } - composite_iter_t __end__ () const { return composite_iter_t (); } - bool operator != (const composite_iter_t& o) const - { return current != o.current; } - - - void set_current (__item_t__ current_) - { - if (!glyph.check_range (current_, CompositeGlyphRecord::min_size)) - { - current = nullptr; - current_size = 0; - return; - } - unsigned size = current_->get_size (); - if (!glyph.check_range (current_, size)) - { - current = nullptr; - current_size = 0; - return; - } - - current = current_; - current_size = size; - } - - private: - hb_bytes_t glyph; - __item_t__ current; - unsigned current_size; -}; +using composite_iter_t = composite_iter_tmpl<CompositeGlyphRecord>; struct CompositeGlyph { @@ -382,7 +335,7 @@ struct CompositeGlyph unsigned comp_len = component.get_size (); if (component.is_anchored ()) { - memcpy (p, &component, comp_len); + hb_memcpy (p, &component, comp_len); p += comp_len; } else @@ -398,7 +351,7 @@ struct CompositeGlyph if (source_len > source_comp_len) { unsigned instr_len = source_len - source_comp_len; - memcpy (p, (const char *)c + source_comp_len, instr_len); + hb_memcpy (p, (const char *)c + source_comp_len, instr_len); p += instr_len; } diff --git a/thirdparty/harfbuzz/src/OT/glyf/Glyph.hh b/thirdparty/harfbuzz/src/OT/glyf/Glyph.hh index afcb5dc834..b7215b0170 100644 --- a/thirdparty/harfbuzz/src/OT/glyf/Glyph.hh +++ b/thirdparty/harfbuzz/src/OT/glyf/Glyph.hh @@ -7,6 +7,8 @@ #include "GlyphHeader.hh" #include "SimpleGlyph.hh" #include "CompositeGlyph.hh" +#include "VarCompositeGlyph.hh" +#include "coord-setter.hh" namespace OT { @@ -16,6 +18,11 @@ struct glyf_accelerator_t; namespace glyf_impl { +#ifndef HB_GLYF_MAX_POINTS +#define HB_GLYF_MAX_POINTS 10000 +#endif + + enum phantom_point_index_t { PHANTOM_LEFT = 0, @@ -27,7 +34,7 @@ enum phantom_point_index_t struct Glyph { - enum glyph_type_t { EMPTY, SIMPLE, COMPOSITE }; + enum glyph_type_t { EMPTY, SIMPLE, COMPOSITE, VAR_COMPOSITE }; public: composite_iter_t get_composite_iterator () const @@ -35,6 +42,11 @@ struct Glyph if (type != COMPOSITE) return composite_iter_t (); return CompositeGlyph (*header, bytes).iter (); } + var_composite_iter_t get_var_composite_iterator () const + { + if (type != VAR_COMPOSITE) return var_composite_iter_t (); + return VarCompositeGlyph (*header, bytes).iter (); + } const hb_bytes_t trim_padding () const { @@ -102,40 +114,42 @@ struct Glyph hb_bytes_t &dest_bytes /* OUT */) const { GlyphHeader *glyph_header = nullptr; - if (all_points.length > 4) + if (type != EMPTY && all_points.length > 4) { glyph_header = (GlyphHeader *) hb_calloc (1, GlyphHeader::static_size); if (unlikely (!glyph_header)) return false; } - int xMin, xMax; - xMin = xMax = roundf (all_points[0].x); - - int yMin, yMax; - yMin = yMax = roundf (all_points[0].y); + float xMin = 0, xMax = 0; + float yMin = 0, yMax = 0; + if (all_points.length > 4) + { + xMin = xMax = all_points[0].x; + yMin = yMax = all_points[0].y; + } for (unsigned i = 1; i < all_points.length - 4; i++) { - float rounded_x = roundf (all_points[i].x); - float rounded_y = roundf (all_points[i].y); - xMin = hb_min (xMin, rounded_x); - xMax = hb_max (xMax, rounded_x); - yMin = hb_min (yMin, rounded_y); - yMax = hb_max (yMax, rounded_y); + float x = all_points[i].x; + float y = all_points[i].y; + xMin = hb_min (xMin, x); + xMax = hb_max (xMax, x); + yMin = hb_min (yMin, y); + yMax = hb_max (yMax, y); } - update_mtx (plan, xMin, yMax, all_points); + update_mtx (plan, roundf (xMin), roundf (yMax), all_points); /*for empty glyphs: all_points only include phantom points. *just update metrics and then return */ - if (all_points.length == 4) + if (!glyph_header) return true; glyph_header->numberOfContours = header->numberOfContours; - glyph_header->xMin = xMin; - glyph_header->yMin = yMin; - glyph_header->xMax = xMax; - glyph_header->yMax = yMax; + glyph_header->xMin = roundf (xMin); + glyph_header->yMin = roundf (yMin); + glyph_header->xMax = roundf (xMax); + glyph_header->yMax = roundf (yMax); dest_bytes = hb_bytes_t ((const char *)glyph_header, GlyphHeader::static_size); return true; @@ -145,10 +159,17 @@ struct Glyph hb_font_t *font, const glyf_accelerator_t &glyf, hb_bytes_t &dest_start, /* IN/OUT */ - hb_bytes_t &dest_end /* OUT */) const + hb_bytes_t &dest_end /* OUT */) { contour_point_vector_t all_points, deltas; - get_points (font, glyf, all_points, &deltas, false); + if (!get_points (font, glyf, all_points, &deltas, false, false)) + return false; + + // .notdef, set type to empty so we only update metrics and don't compile bytes for + // it + if (gid == 0 && + !(plan->flags & HB_SUBSET_FLAGS_NOTDEF_OUTLINE)) + type = EMPTY; switch (type) { case COMPOSITE: @@ -171,7 +192,12 @@ struct Glyph break; } - return compile_header_bytes (plan, all_points, dest_start); + if (!compile_header_bytes (plan, all_points, dest_start)) + { + dest_end.fini (); + return false; + } + return true; } @@ -182,17 +208,27 @@ struct Glyph bool get_points (hb_font_t *font, const accelerator_t &glyf_accelerator, contour_point_vector_t &all_points /* OUT */, contour_point_vector_t *deltas = nullptr, /* OUT */ + bool shift_points_hori = true, bool use_my_metrics = true, bool phantom_only = false, + hb_array_t<int> coords = hb_array_t<int> (), unsigned int depth = 0) const { if (unlikely (depth > HB_MAX_NESTING_LEVEL)) return false; + + if (!coords) + coords = hb_array (font->coords, font->num_coords); + contour_point_vector_t stack_points; bool inplace = type == SIMPLE && all_points.length == 0; /* Load into all_points if it's empty, as an optimization. */ contour_point_vector_t &points = inplace ? all_points : stack_points; switch (type) { + case SIMPLE: + if (unlikely (!SimpleGlyph (*header, bytes).get_contour_points (points, phantom_only))) + return false; + break; case COMPOSITE: { /* pseudo component points for each component in composite glyph */ @@ -200,20 +236,25 @@ struct Glyph if (unlikely (!points.resize (num_points))) return false; break; } - case SIMPLE: - if (unlikely (!SimpleGlyph (*header, bytes).get_contour_points (points, phantom_only))) - return false; +#ifndef HB_NO_VAR_COMPOSITES + case VAR_COMPOSITE: + { + for (auto &item : get_var_composite_iterator ()) + if (unlikely (!item.get_points (points))) return false; + } +#endif + default: break; } /* Init phantom points */ if (unlikely (!points.resize (points.length + PHANTOM_COUNT))) return false; - hb_array_t<contour_point_t> phantoms = points.sub_array (points.length - PHANTOM_COUNT, PHANTOM_COUNT); + hb_array_t<contour_point_t> phantoms = points.as_array ().sub_array (points.length - PHANTOM_COUNT, PHANTOM_COUNT); { int lsb = 0; int h_delta = glyf_accelerator.hmtx->get_leading_bearing_without_var_unscaled (gid, &lsb) ? (int) header->xMin - lsb : 0; - int tsb = 0; + HB_UNUSED int tsb = 0; int v_orig = (int) header->yMax + #ifndef HB_NO_VERTICAL ((void) glyf_accelerator.vmtx->get_leading_bearing_without_var_unscaled (gid, &tsb), tsb) @@ -238,12 +279,13 @@ struct Glyph if (deltas != nullptr && depth == 0 && type == COMPOSITE) { if (unlikely (!deltas->resize (points.length))) return false; - for (unsigned i = 0 ; i < points.length; i++) - deltas->arrayZ[i] = points.arrayZ[i]; + deltas->copy_vector (points); } #ifndef HB_NO_VAR - glyf_accelerator.gvar->apply_deltas_to_points (gid, font, points.as_array ()); + glyf_accelerator.gvar->apply_deltas_to_points (gid, + coords, + points.as_array ()); #endif // mainly used by CompositeGlyph calculating new X/Y offset value so no need to extend it @@ -269,9 +311,17 @@ struct Glyph for (auto &item : get_composite_iterator ()) { comp_points.reset (); + if (unlikely (!glyf_accelerator.glyph_for_gid (item.get_gid ()) - .get_points (font, glyf_accelerator, comp_points, - deltas, use_my_metrics, phantom_only, depth + 1))) + .get_points (font, + glyf_accelerator, + comp_points, + deltas, + shift_points_hori, + use_my_metrics, + phantom_only, + coords, + depth + 1))) return false; /* Copy phantom points from component if USE_MY_METRICS flag set */ @@ -299,18 +349,66 @@ struct Glyph } } - all_points.extend (comp_points.sub_array (0, comp_points.length - PHANTOM_COUNT)); + all_points.extend (comp_points.as_array ().sub_array (0, comp_points.length - PHANTOM_COUNT)); + + if (all_points.length > HB_GLYF_MAX_POINTS) + return false; comp_index++; } all_points.extend (phantoms); } break; +#ifndef HB_NO_VAR_COMPOSITES + case VAR_COMPOSITE: + { + contour_point_vector_t comp_points; + hb_array_t<contour_point_t> points_left = points.as_array (); + for (auto &item : get_var_composite_iterator ()) + { + hb_array_t<contour_point_t> record_points = points_left.sub_array (0, item.get_num_points ()); + + comp_points.reset (); + + coord_setter_t coord_setter (coords); + item.set_variations (coord_setter, record_points); + + if (unlikely (!glyf_accelerator.glyph_for_gid (item.get_gid ()) + .get_points (font, + glyf_accelerator, + comp_points, + deltas, + shift_points_hori, + use_my_metrics, + phantom_only, + coord_setter.get_coords (), + depth + 1))) + return false; + + /* Apply component transformation */ + item.transform_points (record_points, comp_points); + + /* Copy phantom points from component if USE_MY_METRICS flag set */ + if (use_my_metrics && item.is_use_my_metrics ()) + for (unsigned int i = 0; i < PHANTOM_COUNT; i++) + phantoms[i] = comp_points[comp_points.length - PHANTOM_COUNT + i]; + + all_points.extend (comp_points.as_array ().sub_array (0, comp_points.length - PHANTOM_COUNT)); + + if (all_points.length > HB_GLYF_MAX_POINTS) + return false; + + points_left += item.get_num_points (); + } + all_points.extend (phantoms); + } break; +#endif default: all_points.extend (phantoms); + break; } - if (depth == 0) /* Apply at top level */ + if (depth == 0 && shift_points_hori) /* Apply at top level */ { /* Undocumented rasterizer behavior: * Shift points horizontally by the updated left side bearing @@ -332,14 +430,21 @@ struct Glyph hb_bytes_t get_bytes () const { return bytes; } - Glyph (hb_bytes_t bytes_ = hb_bytes_t (), - hb_codepoint_t gid_ = (hb_codepoint_t) -1) : bytes (bytes_), - header (bytes.as<GlyphHeader> ()), - gid (gid_) + Glyph () : bytes (), + header (bytes.as<GlyphHeader> ()), + gid (-1), + type(EMPTY) + {} + + Glyph (hb_bytes_t bytes_, + hb_codepoint_t gid_ = (unsigned) -1) : bytes (bytes_), + header (bytes.as<GlyphHeader> ()), + gid (gid_) { int num_contours = header->numberOfContours; if (unlikely (num_contours == 0)) type = EMPTY; else if (num_contours > 0) type = SIMPLE; + else if (num_contours == -2) type = VAR_COMPOSITE; else type = COMPOSITE; /* negative numbers */ } diff --git a/thirdparty/harfbuzz/src/OT/glyf/SimpleGlyph.hh b/thirdparty/harfbuzz/src/OT/glyf/SimpleGlyph.hh index b99665d6a0..2b4aa99d25 100644 --- a/thirdparty/harfbuzz/src/OT/glyf/SimpleGlyph.hh +++ b/thirdparty/harfbuzz/src/OT/glyf/SimpleGlyph.hh @@ -132,8 +132,8 @@ struct SimpleGlyph if (unlikely (p + 1 > end)) return false; unsigned int repeat_count = *p++; unsigned stop = hb_min (i + repeat_count, count); - for (; i < stop;) - points_.arrayZ[i++].flag = flag; + for (; i < stop; i++) + points_.arrayZ[i].flag = flag; } } return true; @@ -223,33 +223,34 @@ struct SimpleGlyph if (value > 0) flag |= same_flag; else value = -value; - coords.push ((uint8_t)value); + coords.arrayZ[coords.length++] = (uint8_t) value; } else { int16_t val = value; - coords.push (val >> 8); - coords.push (val & 0xff); + coords.arrayZ[coords.length++] = val >> 8; + coords.arrayZ[coords.length++] = val & 0xff; } } static void encode_flag (uint8_t &flag, uint8_t &repeat, - uint8_t &lastflag, + uint8_t lastflag, hb_vector_t<uint8_t> &flags /* OUT */) { if (flag == lastflag && repeat != 255) { - repeat = repeat + 1; + repeat++; if (repeat == 1) { - flags.push(flag); + /* We know there's room. */ + flags.arrayZ[flags.length++] = flag; } else { unsigned len = flags.length; - flags[len-2] = flag | FLAG_REPEAT; - flags[len-1] = repeat; + flags.arrayZ[len-2] = flag | FLAG_REPEAT; + flags.arrayZ[len-1] = repeat; } } else @@ -257,7 +258,6 @@ struct SimpleGlyph repeat = 0; flags.push (flag); } - lastflag = flag; } bool compile_bytes_with_deltas (const contour_point_vector_t &all_points, @@ -269,33 +269,30 @@ struct SimpleGlyph dest_bytes = hb_bytes_t (); return true; } - //convert absolute values to relative values unsigned num_points = all_points.length - 4; - hb_vector_t<hb_pair_t<int, int>> deltas; - deltas.resize (num_points); - - for (unsigned i = 0; i < num_points; i++) - { - deltas[i].first = i == 0 ? roundf (all_points[i].x) : roundf (all_points[i].x) - roundf (all_points[i-1].x); - deltas[i].second = i == 0 ? roundf (all_points[i].y) : roundf (all_points[i].y) - roundf (all_points[i-1].y); - } hb_vector_t<uint8_t> flags, x_coords, y_coords; - flags.alloc (num_points); - x_coords.alloc (2*num_points); - y_coords.alloc (2*num_points); + if (unlikely (!flags.alloc (num_points))) return false; + if (unlikely (!x_coords.alloc (2*num_points))) return false; + if (unlikely (!y_coords.alloc (2*num_points))) return false; - uint8_t lastflag = 0, repeat = 0; + uint8_t lastflag = 255, repeat = 0; + int prev_x = 0, prev_y = 0; for (unsigned i = 0; i < num_points; i++) { - uint8_t flag = all_points[i].flag; + uint8_t flag = all_points.arrayZ[i].flag; flag &= FLAG_ON_CURVE + FLAG_OVERLAP_SIMPLE; - encode_coord (deltas[i].first, flag, FLAG_X_SHORT, FLAG_X_SAME, x_coords); - encode_coord (deltas[i].second, flag, FLAG_Y_SHORT, FLAG_Y_SAME, y_coords); - if (i == 0) lastflag = flag + 1; //make lastflag != flag for the first point + int cur_x = roundf (all_points.arrayZ[i].x); + int cur_y = roundf (all_points.arrayZ[i].y); + encode_coord (cur_x - prev_x, flag, FLAG_X_SHORT, FLAG_X_SAME, x_coords); + encode_coord (cur_y - prev_y, flag, FLAG_Y_SHORT, FLAG_Y_SAME, y_coords); encode_flag (flag, repeat, lastflag, flags); + + prev_x = cur_x; + prev_y = cur_y; + lastflag = flag; } unsigned len_before_instrs = 2 * header.numberOfContours + 2; @@ -305,29 +302,29 @@ struct SimpleGlyph if (!no_hinting) total_len += len_instrs; - char *p = (char *) hb_calloc (total_len, sizeof (char)); + char *p = (char *) hb_malloc (total_len); if (unlikely (!p)) return false; const char *src = bytes.arrayZ + GlyphHeader::static_size; char *cur = p; - memcpy (p, src, len_before_instrs); + hb_memcpy (p, src, len_before_instrs); cur += len_before_instrs; src += len_before_instrs; if (!no_hinting) { - memcpy (cur, src, len_instrs); + hb_memcpy (cur, src, len_instrs); cur += len_instrs; } - memcpy (cur, flags.arrayZ, flags.length); + hb_memcpy (cur, flags.arrayZ, flags.length); cur += flags.length; - memcpy (cur, x_coords.arrayZ, x_coords.length); + hb_memcpy (cur, x_coords.arrayZ, x_coords.length); cur += x_coords.length; - memcpy (cur, y_coords.arrayZ, y_coords.length); + hb_memcpy (cur, y_coords.arrayZ, y_coords.length); dest_bytes = hb_bytes_t (p, total_len); return true; diff --git a/thirdparty/harfbuzz/src/OT/glyf/SubsetGlyph.hh b/thirdparty/harfbuzz/src/OT/glyf/SubsetGlyph.hh index 7ddefc5a91..1a0370c757 100644 --- a/thirdparty/harfbuzz/src/OT/glyf/SubsetGlyph.hh +++ b/thirdparty/harfbuzz/src/OT/glyf/SubsetGlyph.hh @@ -14,7 +14,6 @@ namespace glyf_impl { struct SubsetGlyph { - hb_codepoint_t new_gid; hb_codepoint_t old_gid; Glyph source_glyph; hb_bytes_t dest_start; /* region of source_glyph to copy first */ @@ -22,10 +21,18 @@ struct SubsetGlyph bool serialize (hb_serialize_context_t *c, bool use_short_loca, - const hb_subset_plan_t *plan) const + const hb_subset_plan_t *plan, + hb_font_t *font) { TRACE_SERIALIZE (this); + if (font) + { + const OT::glyf_accelerator_t &glyf = *font->face->table.glyf; + if (!this->compile_bytes_with_deltas (plan, font, glyf)) + return_trace (false); + } + 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 = use_short_loca ? padding () : 0; diff --git a/thirdparty/harfbuzz/src/OT/glyf/VarCompositeGlyph.hh b/thirdparty/harfbuzz/src/OT/glyf/VarCompositeGlyph.hh new file mode 100644 index 0000000000..0f4c71c83d --- /dev/null +++ b/thirdparty/harfbuzz/src/OT/glyf/VarCompositeGlyph.hh @@ -0,0 +1,353 @@ +#ifndef OT_GLYF_VARCOMPOSITEGLYPH_HH +#define OT_GLYF_VARCOMPOSITEGLYPH_HH + + +#include "../../hb-open-type.hh" +#include "coord-setter.hh" + + +namespace OT { +namespace glyf_impl { + + +struct VarCompositeGlyphRecord +{ + protected: + enum var_composite_glyph_flag_t + { + USE_MY_METRICS = 0x0001, + AXIS_INDICES_ARE_SHORT = 0x0002, + UNIFORM_SCALE = 0x0004, + HAVE_TRANSLATE_X = 0x0008, + HAVE_TRANSLATE_Y = 0x0010, + HAVE_ROTATION = 0x0020, + HAVE_SCALE_X = 0x0040, + HAVE_SCALE_Y = 0x0080, + HAVE_SKEW_X = 0x0100, + HAVE_SKEW_Y = 0x0200, + HAVE_TCENTER_X = 0x0400, + HAVE_TCENTER_Y = 0x0800, + GID_IS_24 = 0x1000, + AXES_HAVE_VARIATION = 0x2000, + }; + + public: + + unsigned int get_size () const + { + unsigned int size = min_size; + + unsigned axis_width = (flags & AXIS_INDICES_ARE_SHORT) ? 4 : 3; + size += numAxes * axis_width; + + // gid + size += 2; + if (flags & GID_IS_24) size += 1; + + if (flags & HAVE_TRANSLATE_X) size += 2; + if (flags & HAVE_TRANSLATE_Y) size += 2; + if (flags & HAVE_ROTATION) size += 2; + if (flags & HAVE_SCALE_X) size += 2; + if (flags & HAVE_SCALE_Y) size += 2; + if (flags & HAVE_SKEW_X) size += 2; + if (flags & HAVE_SKEW_Y) size += 2; + if (flags & HAVE_TCENTER_X) size += 2; + if (flags & HAVE_TCENTER_Y) size += 2; + + return size; + } + + bool has_more () const { return true; } + + bool is_use_my_metrics () const { return flags & USE_MY_METRICS; } + + hb_codepoint_t get_gid () const + { + if (flags & GID_IS_24) + return StructAfter<const HBGlyphID24> (numAxes); + else + return StructAfter<const HBGlyphID16> (numAxes); + } + + unsigned get_numAxes () const + { + return numAxes; + } + + unsigned get_num_points () const + { + unsigned num = 0; + if (flags & AXES_HAVE_VARIATION) num += numAxes; + if (flags & (HAVE_TRANSLATE_X | HAVE_TRANSLATE_Y)) num++; + if (flags & HAVE_ROTATION) num++; + if (flags & (HAVE_SCALE_X | HAVE_SCALE_Y)) num++; + if (flags & (HAVE_SKEW_X | HAVE_SKEW_Y)) num++; + if (flags & (HAVE_TCENTER_X | HAVE_TCENTER_Y)) num++; + return num; + } + + void transform_points (hb_array_t<contour_point_t> record_points, + contour_point_vector_t &points) const + { + float matrix[4]; + contour_point_t trans; + + get_transformation_from_points (record_points, matrix, trans); + + points.transform (matrix); + points.translate (trans); + } + + static inline void transform (float (&matrix)[4], contour_point_t &trans, + float (other)[6]) + { + // https://github.com/fonttools/fonttools/blob/f66ee05f71c8b57b5f519ee975e95edcd1466e14/Lib/fontTools/misc/transform.py#L268 + float xx1 = other[0]; + float xy1 = other[1]; + float yx1 = other[2]; + float yy1 = other[3]; + float dx1 = other[4]; + float dy1 = other[5]; + float xx2 = matrix[0]; + float xy2 = matrix[1]; + float yx2 = matrix[2]; + float yy2 = matrix[3]; + float dx2 = trans.x; + float dy2 = trans.y; + + matrix[0] = xx1*xx2 + xy1*yx2; + matrix[1] = xx1*xy2 + xy1*yy2; + matrix[2] = yx1*xx2 + yy1*yx2; + matrix[3] = yx1*xy2 + yy1*yy2; + trans.x = xx2*dx1 + yx2*dy1 + dx2; + trans.y = xy2*dx1 + yy2*dy1 + dy2; + } + + static void translate (float (&matrix)[4], contour_point_t &trans, + float translateX, float translateY) + { + // https://github.com/fonttools/fonttools/blob/f66ee05f71c8b57b5f519ee975e95edcd1466e14/Lib/fontTools/misc/transform.py#L213 + float other[6] = {1.f, 0.f, 0.f, 1.f, translateX, translateY}; + transform (matrix, trans, other); + } + + static void scale (float (&matrix)[4], contour_point_t &trans, + float scaleX, float scaleY) + { + // https://github.com/fonttools/fonttools/blob/f66ee05f71c8b57b5f519ee975e95edcd1466e14/Lib/fontTools/misc/transform.py#L224 + float other[6] = {scaleX, 0.f, 0.f, scaleY, 0.f, 0.f}; + transform (matrix, trans, other); + } + + static void rotate (float (&matrix)[4], contour_point_t &trans, + float rotation) + { + // https://github.com/fonttools/fonttools/blob/f66ee05f71c8b57b5f519ee975e95edcd1466e14/Lib/fontTools/misc/transform.py#L240 + rotation = rotation * float (M_PI); + float c = cosf (rotation); + float s = sinf (rotation); + float other[6] = {c, s, -s, c, 0.f, 0.f}; + transform (matrix, trans, other); + } + + static void skew (float (&matrix)[4], contour_point_t &trans, + float skewX, float skewY) + { + // https://github.com/fonttools/fonttools/blob/f66ee05f71c8b57b5f519ee975e95edcd1466e14/Lib/fontTools/misc/transform.py#L255 + skewX = skewX * float (M_PI); + skewY = skewY * float (M_PI); + float other[6] = {1.f, tanf (skewY), tanf (skewX), 1.f, 0.f, 0.f}; + transform (matrix, trans, other); + } + + bool get_points (contour_point_vector_t &points) const + { + float translateX = 0.f; + float translateY = 0.f; + float rotation = 0.f; + float scaleX = 1.f * (1 << 12); + float scaleY = 1.f * (1 << 12); + float skewX = 0.f; + float skewY = 0.f; + float tCenterX = 0.f; + float tCenterY = 0.f; + + if (unlikely (!points.resize (points.length + get_num_points ()))) return false; + + unsigned axis_width = (flags & AXIS_INDICES_ARE_SHORT) ? 2 : 1; + unsigned axes_size = numAxes * axis_width; + + const F2DOT14 *q = (const F2DOT14 *) (axes_size + + (flags & GID_IS_24 ? 3 : 2) + + &StructAfter<const HBUINT8> (numAxes)); + + hb_array_t<contour_point_t> rec_points = points.as_array ().sub_array (points.length - get_num_points ()); + + unsigned count = numAxes; + if (flags & AXES_HAVE_VARIATION) + { + for (unsigned i = 0; i < count; i++) + rec_points[i].x = *q++; + rec_points += count; + } + else + q += count; + + const HBUINT16 *p = (const HBUINT16 *) q; + + if (flags & HAVE_TRANSLATE_X) translateX = * (const FWORD *) p++; + if (flags & HAVE_TRANSLATE_Y) translateY = * (const FWORD *) p++; + if (flags & HAVE_ROTATION) rotation = * (const F2DOT14 *) p++; + if (flags & HAVE_SCALE_X) scaleX = * (const F4DOT12 *) p++; + if (flags & HAVE_SCALE_Y) scaleY = * (const F4DOT12 *) p++; + if (flags & HAVE_SKEW_X) skewX = * (const F2DOT14 *) p++; + if (flags & HAVE_SKEW_Y) skewY = * (const F2DOT14 *) p++; + if (flags & HAVE_TCENTER_X) tCenterX = * (const FWORD *) p++; + if (flags & HAVE_TCENTER_Y) tCenterY = * (const FWORD *) p++; + + if ((flags & UNIFORM_SCALE) && !(flags & HAVE_SCALE_Y)) + scaleY = scaleX; + + if (flags & (HAVE_TRANSLATE_X | HAVE_TRANSLATE_Y)) + { + rec_points[0].x = translateX; + rec_points[0].y = translateY; + rec_points++; + } + if (flags & HAVE_ROTATION) + { + rec_points[0].x = rotation; + rec_points++; + } + if (flags & (HAVE_SCALE_X | HAVE_SCALE_Y)) + { + rec_points[0].x = scaleX; + rec_points[0].y = scaleY; + rec_points++; + } + if (flags & (HAVE_SKEW_X | HAVE_SKEW_Y)) + { + rec_points[0].x = skewX; + rec_points[0].y = skewY; + rec_points++; + } + if (flags & (HAVE_TCENTER_X | HAVE_TCENTER_Y)) + { + rec_points[0].x = tCenterX; + rec_points[0].y = tCenterY; + rec_points++; + } + assert (!rec_points); + + return true; + } + + void get_transformation_from_points (hb_array_t<contour_point_t> rec_points, + float (&matrix)[4], contour_point_t &trans) const + { + if (flags & AXES_HAVE_VARIATION) + rec_points += numAxes; + + matrix[0] = matrix[3] = 1.f; + matrix[1] = matrix[2] = 0.f; + trans.init (0.f, 0.f); + + float translateX = 0.f; + float translateY = 0.f; + float rotation = 0.f; + float scaleX = 1.f; + float scaleY = 1.f; + float skewX = 0.f; + float skewY = 0.f; + float tCenterX = 0.f; + float tCenterY = 0.f; + + if (flags & (HAVE_TRANSLATE_X | HAVE_TRANSLATE_Y)) + { + translateX = rec_points[0].x; + translateY = rec_points[0].y; + rec_points++; + } + if (flags & HAVE_ROTATION) + { + rotation = rec_points[0].x / (1 << 14); + rec_points++; + } + if (flags & (HAVE_SCALE_X | HAVE_SCALE_Y)) + { + scaleX = rec_points[0].x / (1 << 12); + scaleY = rec_points[0].y / (1 << 12); + rec_points++; + } + if (flags & (HAVE_SKEW_X | HAVE_SKEW_Y)) + { + skewX = rec_points[0].x / (1 << 14); + skewY = rec_points[0].y / (1 << 14); + rec_points++; + } + if (flags & (HAVE_TCENTER_X | HAVE_TCENTER_Y)) + { + tCenterX = rec_points[0].x; + tCenterY = rec_points[0].y; + rec_points++; + } + assert (!rec_points); + + translate (matrix, trans, translateX + tCenterX, translateY + tCenterY); + rotate (matrix, trans, rotation); + scale (matrix, trans, scaleX, scaleY); + skew (matrix, trans, -skewX, skewY); + translate (matrix, trans, -tCenterX, -tCenterY); + } + + void set_variations (coord_setter_t &setter, + hb_array_t<contour_point_t> rec_points) const + { + bool have_variations = flags & AXES_HAVE_VARIATION; + unsigned axis_width = (flags & AXIS_INDICES_ARE_SHORT) ? 2 : 1; + + const HBUINT8 *p = (const HBUINT8 *) (((HBUINT8 *) &numAxes) + numAxes.static_size + (flags & GID_IS_24 ? 3 : 2)); + const HBUINT16 *q = (const HBUINT16 *) (((HBUINT8 *) &numAxes) + numAxes.static_size + (flags & GID_IS_24 ? 3 : 2)); + + const F2DOT14 *a = (const F2DOT14 *) ((HBUINT8 *) (axis_width == 1 ? (p + numAxes) : (HBUINT8 *) (q + numAxes))); + + unsigned count = numAxes; + for (unsigned i = 0; i < count; i++) + { + unsigned axis_index = axis_width == 1 ? (unsigned) *p++ : (unsigned) *q++; + + signed v = have_variations ? rec_points[i].x : *a++; + + v += setter[axis_index]; + v = hb_clamp (v, -(1<<14), (1<<14)); + setter[axis_index] = v; + } + } + + protected: + HBUINT16 flags; + HBUINT8 numAxes; + public: + DEFINE_SIZE_MIN (3); +}; + +using var_composite_iter_t = composite_iter_tmpl<VarCompositeGlyphRecord>; + +struct VarCompositeGlyph +{ + const GlyphHeader &header; + hb_bytes_t bytes; + VarCompositeGlyph (const GlyphHeader &header_, hb_bytes_t bytes_) : + header (header_), bytes (bytes_) {} + + var_composite_iter_t iter () const + { return var_composite_iter_t (bytes, &StructAfter<VarCompositeGlyphRecord, GlyphHeader> (header)); } + +}; + + +} /* namespace glyf_impl */ +} /* namespace OT */ + + +#endif /* OT_GLYF_VARCOMPOSITEGLYPH_HH */ diff --git a/thirdparty/harfbuzz/src/OT/glyf/composite-iter.hh b/thirdparty/harfbuzz/src/OT/glyf/composite-iter.hh new file mode 100644 index 0000000000..d05701f3d1 --- /dev/null +++ b/thirdparty/harfbuzz/src/OT/glyf/composite-iter.hh @@ -0,0 +1,68 @@ +#ifndef OT_GLYF_COMPOSITE_ITER_HH +#define OT_GLYF_COMPOSITE_ITER_HH + + +#include "../../hb.hh" + + +namespace OT { +namespace glyf_impl { + + +template <typename CompositeGlyphRecord> +struct composite_iter_tmpl : hb_iter_with_fallback_t<composite_iter_tmpl<CompositeGlyphRecord>, + const CompositeGlyphRecord &> +{ + typedef const CompositeGlyphRecord *__item_t__; + composite_iter_tmpl (hb_bytes_t glyph_, __item_t__ current_) : + glyph (glyph_), current (nullptr), current_size (0) + { + set_current (current_); + } + + composite_iter_tmpl () : glyph (hb_bytes_t ()), current (nullptr), current_size (0) {} + + const CompositeGlyphRecord & __item__ () const { return *current; } + bool __more__ () const { return current; } + void __next__ () + { + if (!current->has_more ()) { current = nullptr; return; } + + set_current (&StructAtOffset<CompositeGlyphRecord> (current, current_size)); + } + composite_iter_tmpl __end__ () const { return composite_iter_tmpl (); } + bool operator != (const composite_iter_tmpl& o) const + { return current != o.current; } + + + void set_current (__item_t__ current_) + { + if (!glyph.check_range (current_, CompositeGlyphRecord::min_size)) + { + current = nullptr; + current_size = 0; + return; + } + unsigned size = current_->get_size (); + if (!glyph.check_range (current_, size)) + { + current = nullptr; + current_size = 0; + return; + } + + current = current_; + current_size = size; + } + + private: + hb_bytes_t glyph; + __item_t__ current; + unsigned current_size; +}; + + +} /* namespace glyf_impl */ +} /* namespace OT */ + +#endif /* OT_GLYF_COMPOSITE_ITER_HH */ diff --git a/thirdparty/harfbuzz/src/OT/glyf/coord-setter.hh b/thirdparty/harfbuzz/src/OT/glyf/coord-setter.hh new file mode 100644 index 0000000000..df64ed5af7 --- /dev/null +++ b/thirdparty/harfbuzz/src/OT/glyf/coord-setter.hh @@ -0,0 +1,34 @@ +#ifndef OT_GLYF_COORD_SETTER_HH +#define OT_GLYF_COORD_SETTER_HH + + +#include "../../hb.hh" + + +namespace OT { +namespace glyf_impl { + + +struct coord_setter_t +{ + coord_setter_t (hb_array_t<int> coords) : + coords (coords) {} + + int& operator [] (unsigned idx) + { + if (coords.length < idx + 1) + coords.resize (idx + 1); + return coords[idx]; + } + + hb_array_t<int> get_coords () + { return coords.as_array (); } + + hb_vector_t<int> coords; +}; + + +} /* namespace glyf_impl */ +} /* namespace OT */ + +#endif /* OT_GLYF_COORD_SETTER_HH */ diff --git a/thirdparty/harfbuzz/src/OT/glyf/glyf.hh b/thirdparty/harfbuzz/src/OT/glyf/glyf.hh index be2cb1d0dc..e6e985c38c 100644 --- a/thirdparty/harfbuzz/src/OT/glyf/glyf.hh +++ b/thirdparty/harfbuzz/src/OT/glyf/glyf.hh @@ -42,11 +42,15 @@ struct glyf bool serialize (hb_serialize_context_t *c, Iterator it, bool use_short_loca, - const hb_subset_plan_t *plan) + const hb_subset_plan_t *plan, + hb_font_t *font) { TRACE_SERIALIZE (this); + unsigned init_len = c->length (); - for (const auto &_ : it) _.serialize (c, use_short_loca, plan); + for (auto &_ : it) + if (unlikely (!_.serialize (c, use_short_loca, plan, font))) + return false; /* As a special case when all glyph in the font are empty, add a zero byte * to the table, so that OTS doesn’t reject it, and to make the table work @@ -72,21 +76,28 @@ struct glyf if (unlikely (!c->serializer->check_success (glyf_prime))) return_trace (false); hb_vector_t<glyf_impl::SubsetGlyph> glyphs; - _populate_subset_glyphs (c->plan, &glyphs); + _populate_subset_glyphs (c->plan, glyphs); + hb_font_t *font = nullptr; if (!c->plan->pinned_at_default) - _compile_subset_glyphs_with_deltas (c->plan, &glyphs); + { + font = _create_font_for_instancing (c->plan); + if (unlikely (!font)) return false; + } auto padded_offsets = + hb_iter (glyphs) | hb_map (&glyf_impl::SubsetGlyph::padded_size) ; - unsigned max_offset = + padded_offsets | hb_reduce (hb_add, 0); - bool use_short_loca = max_offset < 0x1FFFF; - + bool use_short_loca = false; + if (likely (!c->plan->force_long_loca)) + { + unsigned max_offset = + padded_offsets | hb_reduce (hb_add, 0); + use_short_loca = max_offset < 0x1FFFF; + } - glyf_prime->serialize (c->serializer, hb_iter (glyphs), use_short_loca, c->plan); + glyf_prime->serialize (c->serializer, glyphs.writer (), use_short_loca, c->plan, font); if (!use_short_loca) { padded_offsets = + hb_iter (glyphs) @@ -94,9 +105,12 @@ struct glyf ; } - - if (!c->plan->pinned_at_default) + if (font) + { _free_compiled_subset_glyphs (&glyphs); + hb_font_destroy (font); + } + if (unlikely (c->serializer->in_error ())) return_trace (false); return_trace (c->serializer->check_success (glyf_impl::_add_loca_and_head (c->plan, padded_offsets, @@ -105,11 +119,10 @@ struct glyf void _populate_subset_glyphs (const hb_subset_plan_t *plan, - hb_vector_t<glyf_impl::SubsetGlyph> *glyphs /* OUT */) const; - - void - _compile_subset_glyphs_with_deltas (const hb_subset_plan_t *plan, - hb_vector_t<glyf_impl::SubsetGlyph> *glyphs /* OUT */) const; + hb_vector_t<glyf_impl::SubsetGlyph> &glyphs /* OUT */) const; + + hb_font_t * + _create_font_for_instancing (const hb_subset_plan_t *plan) const; void _free_compiled_subset_glyphs (hb_vector_t<glyf_impl::SubsetGlyph> *glyphs) const { @@ -180,7 +193,7 @@ struct glyf_accelerator_t contour_point_vector_t all_points; bool phantom_only = !consumer.is_consuming_contour_points (); - if (unlikely (!glyph_for_gid (gid).get_points (font, *this, all_points, nullptr, true, phantom_only))) + if (unlikely (!glyph_for_gid (gid).get_points (font, *this, all_points, nullptr, true, true, phantom_only))) return false; if (consumer.is_consuming_contour_points ()) @@ -374,44 +387,45 @@ struct glyf_accelerator_t inline void glyf::_populate_subset_glyphs (const hb_subset_plan_t *plan, - hb_vector_t<glyf_impl::SubsetGlyph> *glyphs /* OUT */) const + hb_vector_t<glyf_impl::SubsetGlyph>& glyphs /* OUT */) const { OT::glyf_accelerator_t glyf (plan->source); + unsigned num_glyphs = plan->num_output_glyphs (); + if (!glyphs.resize (num_glyphs)) return; - + hb_range (plan->num_output_glyphs ()) - | hb_map ([&] (hb_codepoint_t new_gid) - { - glyf_impl::SubsetGlyph subset_glyph = {0}; - subset_glyph.new_gid = new_gid; - - /* 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 (new_gid == 0 && - !(plan->flags & HB_SUBSET_FLAGS_NOTDEF_OUTLINE)) - subset_glyph.source_glyph = glyf_impl::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) - ; + for (auto p : plan->glyph_map->iter ()) + { + unsigned new_gid = p.second; + glyf_impl::SubsetGlyph& subset_glyph = glyphs.arrayZ[new_gid]; + subset_glyph.old_gid = p.first; + + if (unlikely (new_gid == 0 && + !(plan->flags & HB_SUBSET_FLAGS_NOTDEF_OUTLINE)) && + plan->pinned_at_default) + subset_glyph.source_glyph = glyf_impl::Glyph (); + else + { + /* If plan has an accelerator, the preprocessing step already trimmed glyphs. + * Don't trim them again! */ + subset_glyph.source_glyph = glyf.glyph_for_gid (subset_glyph.old_gid, !plan->accelerator); + } + + if (plan->flags & HB_SUBSET_FLAGS_NO_HINTING) + subset_glyph.drop_hints_bytes (); + else + subset_glyph.dest_start = subset_glyph.source_glyph.get_bytes (); + } } -inline void -glyf::_compile_subset_glyphs_with_deltas (const hb_subset_plan_t *plan, - hb_vector_t<glyf_impl::SubsetGlyph> *glyphs /* OUT */) const +inline hb_font_t * +glyf::_create_font_for_instancing (const hb_subset_plan_t *plan) const { - OT::glyf_accelerator_t glyf (plan->source); hb_font_t *font = hb_font_create (plan->source); + if (unlikely (font == hb_font_get_empty ())) return nullptr; hb_vector_t<hb_variation_t> vars; - vars.alloc (plan->user_axes_location->get_population ()); + if (unlikely (!vars.alloc (plan->user_axes_location->get_population ()))) + return nullptr; for (auto _ : *plan->user_axes_location) { @@ -421,11 +435,10 @@ glyf::_compile_subset_glyphs_with_deltas (const hb_subset_plan_t *plan, vars.push (var); } +#ifndef HB_NO_VAR hb_font_set_variations (font, vars.arrayZ, plan->user_axes_location->get_population ()); - for (auto& subset_glyph : *glyphs) - const_cast<glyf_impl::SubsetGlyph &> (subset_glyph).compile_bytes_with_deltas (plan, font, glyf); - - hb_font_destroy (font); +#endif + return font; } diff --git a/thirdparty/harfbuzz/src/graph/classdef-graph.hh b/thirdparty/harfbuzz/src/graph/classdef-graph.hh index 0bda76ac2f..c2e24a7067 100644 --- a/thirdparty/harfbuzz/src/graph/classdef-graph.hh +++ b/thirdparty/harfbuzz/src/graph/classdef-graph.hh @@ -112,7 +112,7 @@ struct ClassDef : public OT::ClassDef { case 1: return ((ClassDefFormat1*)this)->sanitize (vertex); case 2: return ((ClassDefFormat2*)this)->sanitize (vertex); -#ifndef HB_NO_BORING_EXPANSION +#ifndef HB_NO_BEYOND_64K // Not currently supported case 3: case 4: diff --git a/thirdparty/harfbuzz/src/graph/coverage-graph.hh b/thirdparty/harfbuzz/src/graph/coverage-graph.hh index 3c1022f090..49d0936315 100644 --- a/thirdparty/harfbuzz/src/graph/coverage-graph.hh +++ b/thirdparty/harfbuzz/src/graph/coverage-graph.hh @@ -136,7 +136,7 @@ struct Coverage : public OT::Layout::Common::Coverage { case 1: return ((CoverageFormat1*)this)->sanitize (vertex); case 2: return ((CoverageFormat2*)this)->sanitize (vertex); -#ifndef HB_NO_BORING_EXPANSION +#ifndef HB_NO_BEYOND_64K // Not currently supported case 3: case 4: diff --git a/thirdparty/harfbuzz/src/graph/graph.hh b/thirdparty/harfbuzz/src/graph/graph.hh index 64878a84a4..dc5b6a36fe 100644 --- a/thirdparty/harfbuzz/src/graph/graph.hh +++ b/thirdparty/harfbuzz/src/graph/graph.hh @@ -49,6 +49,50 @@ struct graph_t unsigned end = 0; unsigned priority = 0; + + bool link_positions_valid (unsigned num_objects, bool removed_nil) + { + hb_set_t assigned_bytes; + for (const auto& l : obj.real_links) + { + if (l.objidx >= num_objects + || (removed_nil && !l.objidx)) + { + DEBUG_MSG (SUBSET_REPACK, nullptr, + "Invalid graph. Invalid object index."); + return false; + } + + unsigned start = l.position; + unsigned end = start + l.width - 1; + + if (unlikely (l.width < 2 || l.width > 4)) + { + DEBUG_MSG (SUBSET_REPACK, nullptr, + "Invalid graph. Invalid link width."); + return false; + } + + if (unlikely (end >= table_size ())) + { + DEBUG_MSG (SUBSET_REPACK, nullptr, + "Invalid graph. Link position is out of bounds."); + return false; + } + + if (unlikely (assigned_bytes.intersects (start, end))) + { + DEBUG_MSG (SUBSET_REPACK, nullptr, + "Invalid graph. Found offsets whose positions overlap."); + return false; + } + + assigned_bytes.add_range (start, end); + } + + return !assigned_bytes.in_error (); + } + void normalize () { obj.real_links.qsort (); @@ -70,8 +114,8 @@ struct graph_t { DEBUG_MSG (SUBSET_REPACK, nullptr, "vertex [%lu] bytes != [%lu] bytes, depth = %u", - table_size (), - other.table_size (), + (unsigned long) table_size (), + (unsigned long) other.table_size (), depth); auto a = as_bytes (); @@ -132,7 +176,7 @@ struct graph_t for (unsigned i = 0; i < parents.length; i++) { if (parents[i] != parent_index) continue; - parents.remove (i); + parents.remove_unordered (i); break; } } @@ -148,7 +192,7 @@ struct graph_t if ((obj.head + link.position) != offset) continue; - obj.real_links.remove (i); + obj.real_links.remove_unordered (i); return; } } @@ -286,8 +330,6 @@ struct graph_t vertices_scratch_.alloc (objects.length); for (unsigned i = 0; i < objects.length; i++) { - // TODO(grieger): check all links point to valid objects. - // If this graph came from a serialization buffer object 0 is the // nil object. We don't need it for our purposes here so drop it. if (i == 0 && !objects[i]) @@ -299,6 +341,9 @@ struct graph_t vertex_t* v = vertices_.push (); if (check_success (!vertices_.in_error ())) v->obj = *objects[i]; + + check_success (v->link_positions_valid (objects.length, removed_nil)); + if (!removed_nil) continue; // Fix indices to account for removed nil object. for (auto& l : v->obj.all_links_writer ()) { @@ -418,6 +463,13 @@ struct graph_t hb_swap (sorted_graph[new_id], vertices_[next_id]); const vertex_t& next = sorted_graph[new_id]; + if (unlikely (!check_success(new_id >= 0))) { + // We are out of ids. Which means we've visited a node more than once. + // This graph contains a cycle which is not allowed. + DEBUG_MSG (SUBSET_REPACK, nullptr, "Invalid graph. Contains cycle."); + return; + } + id_map[next_id] = new_id--; for (const auto& link : next.obj.all_links ()) { @@ -496,6 +548,12 @@ struct graph_t } template <typename T, typename ...Ts> + vertex_and_table_t<T> as_mutable_table (unsigned parent, const void* offset, Ts... ds) + { + return as_table_from_index<T> (mutable_index_for_offset (parent, offset), std::forward<Ts>(ds)...); + } + + template <typename T, typename ...Ts> vertex_and_table_t<T> as_table_from_index (unsigned index, Ts... ds) { if (index >= vertices_.length) @@ -574,7 +632,7 @@ struct graph_t while (roots) { - unsigned next = HB_SET_VALUE_INVALID; + uint32_t next = HB_SET_VALUE_INVALID; if (unlikely (!check_success (!roots.in_error ()))) break; if (!roots.next (&next)) break; @@ -655,8 +713,8 @@ struct graph_t auto new_subgraph = + subgraph.keys () - | hb_map([&] (unsigned node_idx) { - const unsigned *v; + | hb_map([&] (uint32_t node_idx) { + const uint32_t *v; if (index_map.has (node_idx, &v)) return *v; return node_idx; }) @@ -666,10 +724,10 @@ struct graph_t remap_obj_indices (index_map, parents.iter (), true); // Update roots set with new indices as needed. - unsigned next = HB_SET_VALUE_INVALID; + uint32_t next = HB_SET_VALUE_INVALID; while (roots.next (&next)) { - const unsigned *v; + const uint32_t *v; if (index_map.has (next, &v)) { roots.del (next); @@ -684,7 +742,7 @@ struct graph_t { for (const auto& link : vertices_[node_idx].obj.all_links ()) { - const unsigned *v; + const uint32_t *v; if (subgraph.has (link.objidx, &v)) { subgraph.set (link.objidx, *v + 1); @@ -833,7 +891,20 @@ struct graph_t * parent to the clone. The copy is a shallow copy, objects * linked from child are not duplicated. */ - bool duplicate (unsigned parent_idx, unsigned child_idx) + unsigned duplicate_if_shared (unsigned parent_idx, unsigned child_idx) + { + unsigned new_idx = duplicate (parent_idx, child_idx); + if (new_idx == (unsigned) -1) return child_idx; + return new_idx; + } + + + /* + * Creates a copy of child and re-assigns the link from + * parent to the clone. The copy is a shallow copy, objects + * linked from child are not duplicated. + */ + unsigned duplicate (unsigned parent_idx, unsigned child_idx) { update_parents (); @@ -849,7 +920,7 @@ struct graph_t // to child are from parent. DEBUG_MSG (SUBSET_REPACK, nullptr, " Not duplicating %d => %d", parent_idx, child_idx); - return false; + return -1; } DEBUG_MSG (SUBSET_REPACK, nullptr, " Duplicating %d => %d", @@ -869,7 +940,7 @@ struct graph_t reassign_link (l, parent_idx, clone_idx); } - return true; + return clone_idx; } @@ -922,6 +993,72 @@ struct graph_t return made_change; } + bool is_fully_connected () + { + update_parents(); + + if (root().parents) + // Root cannot have parents. + return false; + + for (unsigned i = 0; i < root_idx (); i++) + { + if (!vertices_[i].parents) + return false; + } + return true; + } + +#if 0 + /* + * Saves the current graph to a packed binary format which the repacker fuzzer takes + * as a seed. + */ + void save_fuzzer_seed (hb_tag_t tag) const + { + FILE* f = fopen ("./repacker_fuzzer_seed", "w"); + fwrite ((void*) &tag, sizeof (tag), 1, f); + + uint16_t num_objects = vertices_.length; + fwrite ((void*) &num_objects, sizeof (num_objects), 1, f); + + for (const auto& v : vertices_) + { + uint16_t blob_size = v.table_size (); + fwrite ((void*) &blob_size, sizeof (blob_size), 1, f); + fwrite ((const void*) v.obj.head, blob_size, 1, f); + } + + uint16_t link_count = 0; + for (const auto& v : vertices_) + link_count += v.obj.real_links.length; + + fwrite ((void*) &link_count, sizeof (link_count), 1, f); + + typedef struct + { + uint16_t parent; + uint16_t child; + uint16_t position; + uint8_t width; + } link_t; + + for (unsigned i = 0; i < vertices_.length; i++) + { + for (const auto& l : vertices_[i].obj.real_links) + { + link_t link { + (uint16_t) i, (uint16_t) l.objidx, + (uint16_t) l.position, (uint8_t) l.width + }; + fwrite ((void*) &link, sizeof (link), 1, f); + } + } + + fclose (f); + } +#endif + void print_orphaned_nodes () { if (!DEBUG_ENABLED(SUBSET_REPACK)) return; @@ -930,6 +1067,10 @@ struct graph_t parents_invalid = true; update_parents(); + if (root().parents) { + DEBUG_MSG (SUBSET_REPACK, nullptr, "Root node has incoming edges."); + } + for (unsigned i = 0; i < root_idx (); i++) { const auto& v = vertices_[i]; @@ -1046,6 +1187,11 @@ struct graph_t } } + for (unsigned i = 0; i < vertices_.length; i++) + // parents arrays must be accurate or downstream operations like cycle detection + // and sorting won't work correctly. + check_success (!vertices_[i].parents.in_error ()); + parents_invalid = false; } @@ -1164,7 +1310,7 @@ struct graph_t { for (auto& link : vertices_[i].obj.all_links_writer ()) { - const unsigned *v; + const uint32_t *v; if (!id_map.has (link.objidx, &v)) continue; if (only_wide && !(link.width == 4 && !link.is_signed)) continue; diff --git a/thirdparty/harfbuzz/src/graph/gsubgpos-graph.hh b/thirdparty/harfbuzz/src/graph/gsubgpos-graph.hh index a93e7d1c73..c170638409 100644 --- a/thirdparty/harfbuzz/src/graph/gsubgpos-graph.hh +++ b/thirdparty/harfbuzz/src/graph/gsubgpos-graph.hh @@ -131,8 +131,10 @@ struct Lookup : public OT::Lookup for (unsigned i = 0; i < subTable.len; i++) { unsigned subtable_index = c.graph.index_for_offset (this_index, &subTable[i]); + unsigned parent_index = this_index; if (is_ext) { unsigned ext_subtable_index = subtable_index; + parent_index = ext_subtable_index; ExtensionFormat1<OT::Layout::GSUB_impl::ExtensionSubst>* extension = (ExtensionFormat1<OT::Layout::GSUB_impl::ExtensionSubst>*) c.graph.object (ext_subtable_index).head; @@ -150,9 +152,9 @@ struct Lookup : public OT::Lookup switch (type) { case 2: - new_sub_tables = split_subtable<PairPos> (c, subtable_index); break; + new_sub_tables = split_subtable<PairPos> (c, parent_index, subtable_index); break; case 4: - new_sub_tables = split_subtable<MarkBasePos> (c, subtable_index); break; + new_sub_tables = split_subtable<MarkBasePos> (c, parent_index, subtable_index); break; default: break; } @@ -172,13 +174,14 @@ struct Lookup : public OT::Lookup template<typename T> hb_vector_t<unsigned> split_subtable (gsubgpos_graph_context_t& c, + unsigned parent_idx, unsigned objidx) { T* sub_table = (T*) c.graph.object (objidx).head; if (!sub_table || !sub_table->sanitize (c.graph.vertices_[objidx])) return hb_vector_t<unsigned> (); - return sub_table->split_subtables (c, objidx); + return sub_table->split_subtables (c, parent_idx, objidx); } void add_sub_tables (gsubgpos_graph_context_t& c, @@ -198,7 +201,7 @@ struct Lookup : public OT::Lookup + new_subtable_count * OT::Offset16::static_size; char* buffer = (char*) hb_calloc (1, new_size); c.add_buffer (buffer); - memcpy (buffer, v.obj.head, v.table_size()); + hb_memcpy (buffer, v.obj.head, v.table_size()); v.obj.head = buffer; v.obj.tail = buffer + new_size; @@ -352,7 +355,7 @@ struct GSTAR : public OT::GSUBGPOS { switch (u.version.major) { case 1: return u.version1.get_lookup_list_offset (); -#ifndef HB_NO_BORING_EXPANSION +#ifndef HB_NO_BEYOND_64K case 2: return u.version2.get_lookup_list_offset (); #endif default: return 0; @@ -371,7 +374,7 @@ struct GSTAR : public OT::GSUBGPOS { switch (u.version.major) { case 1: find_lookups<SmallTypes> (graph, lookups); break; -#ifndef HB_NO_BORING_EXPANSION +#ifndef HB_NO_BEYOND_64K case 2: find_lookups<MediumTypes> (graph, lookups); break; #endif } diff --git a/thirdparty/harfbuzz/src/graph/markbasepos-graph.hh b/thirdparty/harfbuzz/src/graph/markbasepos-graph.hh index 56fa812406..84ef5f71b9 100644 --- a/thirdparty/harfbuzz/src/graph/markbasepos-graph.hh +++ b/thirdparty/harfbuzz/src/graph/markbasepos-graph.hh @@ -112,7 +112,7 @@ struct AnchorMatrix : public OT::Layout::GPOS_impl::AnchorMatrix auto& child = c.graph.vertices_[child_idx]; child.remove_parent (this_index); - o.real_links.remove (i); + o.real_links.remove_unordered (i); num_links--; i--; } @@ -209,7 +209,9 @@ struct MarkBasePosFormat1 : public OT::Layout::GPOS_impl::MarkBasePosFormat1_2<S return vertex_len >= MarkBasePosFormat1::static_size; } - hb_vector_t<unsigned> split_subtables (gsubgpos_graph_context_t& c, unsigned this_index) + hb_vector_t<unsigned> split_subtables (gsubgpos_graph_context_t& c, + unsigned parent_index, + unsigned this_index) { hb_set_t visited; @@ -261,7 +263,7 @@ struct MarkBasePosFormat1 : public OT::Layout::GPOS_impl::MarkBasePosFormat1_2<S split_context_t split_context { c, this, - this_index, + c.graph.duplicate_if_shared (parent_index, this_index), std::move (class_to_info), c.graph.vertices_[mark_array_id].position_to_index_map (), }; @@ -365,12 +367,12 @@ struct MarkBasePosFormat1 : public OT::Layout::GPOS_impl::MarkBasePosFormat1_2<S classCount = count; - auto mark_coverage = sc.c.graph.as_table<Coverage> (this_index, - &markCoverage); + auto mark_coverage = sc.c.graph.as_mutable_table<Coverage> (this_index, + &markCoverage); if (!mark_coverage) return false; hb_set_t marks = sc.marks_for (0, count); auto new_coverage = - + hb_zip (hb_range (), mark_coverage.table->iter ()) + + hb_enumerate (mark_coverage.table->iter ()) | hb_filter (marks, hb_first) | hb_map_retains_sorting (hb_second) ; @@ -380,17 +382,17 @@ struct MarkBasePosFormat1 : public OT::Layout::GPOS_impl::MarkBasePosFormat1_2<S return false; - auto base_array = sc.c.graph.as_table<AnchorMatrix> (this_index, - &baseArray, - old_count); + auto base_array = sc.c.graph.as_mutable_table<AnchorMatrix> (this_index, + &baseArray, + old_count); if (!base_array || !base_array.table->shrink (sc.c, base_array.index, old_count, count)) return false; - auto mark_array = sc.c.graph.as_table<MarkArray> (this_index, - &markArray); + auto mark_array = sc.c.graph.as_mutable_table<MarkArray> (this_index, + &markArray); if (!mark_array || !mark_array.table->shrink (sc.c, sc.mark_array_links, mark_array.index, @@ -429,7 +431,7 @@ struct MarkBasePosFormat1 : public OT::Layout::GPOS_impl::MarkBasePosFormat1_2<S if (!mark_coverage) return false; hb_set_t marks = sc.marks_for (start, end); auto new_coverage = - + hb_zip (hb_range (), mark_coverage.table->iter ()) + + hb_enumerate (mark_coverage.table->iter ()) | hb_filter (marks, hb_first) | hb_map_retains_sorting (hb_second) ; @@ -469,12 +471,13 @@ struct MarkBasePosFormat1 : public OT::Layout::GPOS_impl::MarkBasePosFormat1_2<S struct MarkBasePos : public OT::Layout::GPOS_impl::MarkBasePos { hb_vector_t<unsigned> split_subtables (gsubgpos_graph_context_t& c, + unsigned parent_index, unsigned this_index) { switch (u.format) { case 1: - return ((MarkBasePosFormat1*)(&u.format1))->split_subtables (c, this_index); -#ifndef HB_NO_BORING_EXPANSION + return ((MarkBasePosFormat1*)(&u.format1))->split_subtables (c, parent_index, this_index); +#ifndef HB_NO_BEYOND_64K case 2: HB_FALLTHROUGH; // Don't split 24bit PairPos's. #endif @@ -491,7 +494,7 @@ struct MarkBasePos : public OT::Layout::GPOS_impl::MarkBasePos switch (u.format) { case 1: return ((MarkBasePosFormat1*)(&u.format1))->sanitize (vertex); -#ifndef HB_NO_BORING_EXPANSION +#ifndef HB_NO_BEYOND_64K case 2: HB_FALLTHROUGH; #endif default: diff --git a/thirdparty/harfbuzz/src/graph/pairpos-graph.hh b/thirdparty/harfbuzz/src/graph/pairpos-graph.hh index 976b872329..1c13eb24f9 100644 --- a/thirdparty/harfbuzz/src/graph/pairpos-graph.hh +++ b/thirdparty/harfbuzz/src/graph/pairpos-graph.hh @@ -47,7 +47,9 @@ struct PairPosFormat1 : public OT::Layout::GPOS_impl::PairPosFormat1_3<SmallType min_size + pairSet.get_size () - pairSet.len.get_size(); } - hb_vector_t<unsigned> split_subtables (gsubgpos_graph_context_t& c, unsigned this_index) + hb_vector_t<unsigned> split_subtables (gsubgpos_graph_context_t& c, + unsigned parent_index, + unsigned this_index) { hb_set_t visited; @@ -81,7 +83,7 @@ struct PairPosFormat1 : public OT::Layout::GPOS_impl::PairPosFormat1_3<SmallType split_context_t split_context { c, this, - this_index, + c.graph.duplicate_if_shared (parent_index, this_index), }; return actuate_subtable_split<split_context_t> (split_context, split_points); @@ -125,23 +127,19 @@ struct PairPosFormat1 : public OT::Layout::GPOS_impl::PairPosFormat1_3<SmallType pairSet.len = count; c.graph.vertices_[this_index].obj.tail -= (old_count - count) * SmallTypes::size; - unsigned coverage_id = c.graph.mutable_index_for_offset (this_index, &coverage); - unsigned coverage_size = c.graph.vertices_[coverage_id].table_size (); - auto& coverage_v = c.graph.vertices_[coverage_id]; - - Coverage* coverage_table = (Coverage*) coverage_v.obj.head; - if (!coverage_table || !coverage_table->sanitize (coverage_v)) - return false; + auto coverage = c.graph.as_mutable_table<Coverage> (this_index, &this->coverage); + if (!coverage) return false; + unsigned coverage_size = coverage.vertex->table_size (); auto new_coverage = - + hb_zip (coverage_table->iter (), hb_range ()) + + hb_zip (coverage.table->iter (), hb_range ()) | hb_filter ([&] (hb_pair_t<unsigned, unsigned> p) { return p.second < count; }) | hb_map_retains_sorting (hb_first) ; - return Coverage::make_coverage (c, new_coverage, coverage_id, coverage_size); + return Coverage::make_coverage (c, new_coverage, coverage.index, coverage_size); } // Create a new PairPos including PairSet's from start (inclusive) to end (exclusive). @@ -206,7 +204,9 @@ struct PairPosFormat2 : public OT::Layout::GPOS_impl::PairPosFormat2_4<SmallType min_size + class1_count * get_class1_record_size (); } - hb_vector_t<unsigned> split_subtables (gsubgpos_graph_context_t& c, unsigned this_index) + hb_vector_t<unsigned> split_subtables (gsubgpos_graph_context_t& c, + unsigned parent_index, + unsigned this_index) { const unsigned base_size = OT::Layout::GPOS_impl::PairPosFormat2_4<SmallTypes>::min_size; const unsigned class_def_2_size = size_of (c, this_index, &classDef2); @@ -287,7 +287,7 @@ struct PairPosFormat2 : public OT::Layout::GPOS_impl::PairPosFormat2_4<SmallType split_context_t split_context { c, this, - this_index, + c.graph.duplicate_if_shared (parent_index, this_index), class1_record_size, total_value_len, value_1_len, @@ -434,7 +434,7 @@ struct PairPosFormat2 : public OT::Layout::GPOS_impl::PairPosFormat2_4<SmallType char* start_addr = ((char*)&values[0]) + start * split_context.class1_record_size; unsigned num_records = end - start; - memcpy (&pair_pos_prime->values[0], + hb_memcpy (&pair_pos_prime->values[0], start_addr, num_records * split_context.class1_record_size); @@ -508,40 +508,37 @@ struct PairPosFormat2 : public OT::Layout::GPOS_impl::PairPosFormat2_4<SmallType graph.vertices_[split_context.this_index].obj.tail -= (old_count - count) * split_context.class1_record_size; - unsigned coverage_id = - graph.mutable_index_for_offset (split_context.this_index, &coverage); - unsigned class_def_1_id = - graph.mutable_index_for_offset (split_context.this_index, &classDef1); - auto& coverage_v = graph.vertices_[coverage_id]; - auto& class_def_1_v = graph.vertices_[class_def_1_id]; - Coverage* coverage_table = (Coverage*) coverage_v.obj.head; - ClassDef* class_def_1_table = (ClassDef*) class_def_1_v.obj.head; - if (!coverage_table - || !coverage_table->sanitize (coverage_v) - || !class_def_1_table - || !class_def_1_table->sanitize (class_def_1_v)) - return false; + auto coverage = + graph.as_mutable_table<Coverage> (split_context.this_index, &this->coverage); + if (!coverage) return false; + + auto class_def_1 = + graph.as_mutable_table<ClassDef> (split_context.this_index, &classDef1); + if (!class_def_1) return false; auto klass_map = - + coverage_table->iter () + + coverage.table->iter () | hb_map_retains_sorting ([&] (hb_codepoint_t gid) { - return hb_pair_t<hb_codepoint_t, hb_codepoint_t> (gid, class_def_1_table->get_class (gid)); + return hb_pair_t<hb_codepoint_t, hb_codepoint_t> (gid, class_def_1.table->get_class (gid)); }) | hb_filter ([&] (hb_codepoint_t klass) { return klass < count; }, hb_second) ; + auto new_coverage = + klass_map | hb_map_retains_sorting (hb_first); if (!Coverage::make_coverage (split_context.c, - + klass_map | hb_map_retains_sorting (hb_first), - coverage_id, - coverage_v.table_size ())) + + new_coverage, + coverage.index, + // existing ranges my not be kept, worst case size is a format 1 + // coverage table. + 4 + new_coverage.len() * 2)) return false; return ClassDef::make_class_def (split_context.c, + klass_map, - class_def_1_id, - class_def_1_v.table_size ()); + class_def_1.index, + class_def_1.vertex->table_size ()); } hb_hashmap_t<unsigned, unsigned> @@ -605,14 +602,16 @@ struct PairPosFormat2 : public OT::Layout::GPOS_impl::PairPosFormat2_4<SmallType struct PairPos : public OT::Layout::GPOS_impl::PairPos { - hb_vector_t<unsigned> split_subtables (gsubgpos_graph_context_t& c, unsigned this_index) + hb_vector_t<unsigned> split_subtables (gsubgpos_graph_context_t& c, + unsigned parent_index, + unsigned this_index) { switch (u.format) { case 1: - return ((PairPosFormat1*)(&u.format1))->split_subtables (c, this_index); + return ((PairPosFormat1*)(&u.format1))->split_subtables (c, parent_index, this_index); case 2: - return ((PairPosFormat2*)(&u.format2))->split_subtables (c, this_index); -#ifndef HB_NO_BORING_EXPANSION + return ((PairPosFormat2*)(&u.format2))->split_subtables (c, parent_index, this_index); +#ifndef HB_NO_BEYOND_64K case 3: HB_FALLTHROUGH; case 4: HB_FALLTHROUGH; // Don't split 24bit PairPos's. @@ -632,7 +631,7 @@ struct PairPos : public OT::Layout::GPOS_impl::PairPos return ((PairPosFormat1*)(&u.format1))->sanitize (vertex); case 2: return ((PairPosFormat2*)(&u.format2))->sanitize (vertex); -#ifndef HB_NO_BORING_EXPANSION +#ifndef HB_NO_BEYOND_64K case 3: HB_FALLTHROUGH; case 4: HB_FALLTHROUGH; #endif diff --git a/thirdparty/harfbuzz/src/graph/serialize.hh b/thirdparty/harfbuzz/src/graph/serialize.hh index ecc6cc5aea..d03a61bd19 100644 --- a/thirdparty/harfbuzz/src/graph/serialize.hh +++ b/thirdparty/harfbuzz/src/graph/serialize.hh @@ -33,6 +33,23 @@ struct overflow_record_t { unsigned parent; unsigned child; + + bool operator != (const overflow_record_t o) const + { return !(*this == o); } + + inline bool operator == (const overflow_record_t& o) const + { + return parent == o.parent && + child == o.child; + } + + inline uint32_t hash () const + { + uint32_t current = 0; + current = current * 31 + hb_hash (parent); + current = current * 31 + hb_hash (child); + return current; + } }; inline @@ -94,6 +111,7 @@ will_overflow (graph_t& graph, if (overflows) overflows->resize (0); graph.update_positions (); + hb_hashmap_t<overflow_record_t*, bool> record_set; const auto& vertices = graph.vertices_; for (int parent_idx = vertices.length - 1; parent_idx >= 0; parent_idx--) { @@ -109,7 +127,10 @@ will_overflow (graph_t& graph, overflow_record_t r; r.parent = parent_idx; r.child = link.objidx; + if (record_set.has(&r)) continue; // don't keep duplicate overflows. + overflows->push (r); + record_set.set(&r, true); } } @@ -223,7 +244,7 @@ inline hb_blob_t* serialize (const graph_t& graph) return nullptr; } - memcpy (start, vertices[i].obj.head, size); + hb_memcpy (start, vertices[i].obj.head, size); // Only real links needs to be serialized. for (const auto& link : vertices[i].obj.real_links) diff --git a/thirdparty/harfbuzz/src/hb-aat-layout-just-table.hh b/thirdparty/harfbuzz/src/hb-aat-layout-just-table.hh index 57c105967d..8fd3990f88 100644 --- a/thirdparty/harfbuzz/src/hb-aat-layout-just-table.hh +++ b/thirdparty/harfbuzz/src/hb-aat-layout-just-table.hh @@ -70,9 +70,9 @@ struct DecompositionAction ActionSubrecordHeader header; - HBFixed lowerLimit; /* If the distance factor is less than this value, + F16DOT16 lowerLimit; /* If the distance factor is less than this value, * then the ligature is decomposed. */ - HBFixed upperLimit; /* If the distance factor is greater than this value, + F16DOT16 upperLimit; /* If the distance factor is greater than this value, * then the ligature is decomposed. */ HBUINT16 order; /* Numerical order in which this ligature will * be decomposed; you may want infrequent ligatures @@ -118,7 +118,7 @@ struct ConditionalAddGlyphAction protected: ActionSubrecordHeader header; - HBFixed substThreshold; /* Distance growth factor (in ems) at which + F16DOT16 substThreshold; /* Distance growth factor (in ems) at which * this glyph is replaced and the growth factor * recalculated. */ HBGlyphID16 addGlyph; /* Glyph to be added as kashida. If this value is @@ -146,13 +146,13 @@ struct DuctileGlyphAction HBUINT32 variationAxis; /* The 4-byte tag identifying the ductile axis. * This would normally be 0x64756374 ('duct'), * but you may use any axis the font contains. */ - HBFixed minimumLimit; /* The lowest value for the ductility axis that + F16DOT16 minimumLimit; /* The lowest value for the ductility axis that * still yields an acceptable appearance. Normally * this will be 1.0. */ - HBFixed noStretchValue; /* This is the default value that corresponds to + F16DOT16 noStretchValue; /* This is the default value that corresponds to * no change in appearance. Normally, this will * be 1.0. */ - HBFixed maximumLimit; /* The highest value for the ductility axis that + F16DOT16 maximumLimit; /* The highest value for the ductility axis that * still yields an acceptable appearance. */ public: DEFINE_SIZE_STATIC (22); @@ -271,14 +271,14 @@ struct JustWidthDeltaEntry }; protected: - HBFixed beforeGrowLimit;/* The ratio by which the advance width of the + F16DOT16 beforeGrowLimit;/* The ratio by which the advance width of the * glyph is permitted to grow on the left or top side. */ - HBFixed beforeShrinkLimit; + F16DOT16 beforeShrinkLimit; /* The ratio by which the advance width of the * glyph is permitted to shrink on the left or top side. */ - HBFixed afterGrowLimit; /* The ratio by which the advance width of the glyph + F16DOT16 afterGrowLimit; /* The ratio by which the advance width of the glyph * is permitted to shrink on the left or top side. */ - HBFixed afterShrinkLimit; + F16DOT16 afterShrinkLimit; /* The ratio by which the advance width of the glyph * is at most permitted to shrink on the right or * bottom side. */ diff --git a/thirdparty/harfbuzz/src/hb-aat-layout-morx-table.hh b/thirdparty/harfbuzz/src/hb-aat-layout-morx-table.hh index aa4ad4cf3c..8b9190d0be 100644 --- a/thirdparty/harfbuzz/src/hb-aat-layout-morx-table.hh +++ b/thirdparty/harfbuzz/src/hb-aat-layout-morx-table.hh @@ -131,14 +131,14 @@ struct RearrangementSubtable hb_glyph_info_t *info = buffer->info; hb_glyph_info_t buf[4]; - memcpy (buf, info + start, l * sizeof (buf[0])); - memcpy (buf + 2, info + end - r, r * sizeof (buf[0])); + hb_memcpy (buf, info + start, l * sizeof (buf[0])); + hb_memcpy (buf + 2, info + end - r, r * sizeof (buf[0])); if (l != r) memmove (info + start + r, info + start + l, (end - start - l - r) * sizeof (buf[0])); - memcpy (info + start, buf + 2, r * sizeof (buf[0])); - memcpy (info + end - l, buf, l * sizeof (buf[0])); + hb_memcpy (info + start, buf + 2, r * sizeof (buf[0])); + hb_memcpy (info + end - l, buf, l * sizeof (buf[0])); if (reverse_l) { buf[0] = info[end - 1]; diff --git a/thirdparty/harfbuzz/src/hb-aat-layout-trak-table.hh b/thirdparty/harfbuzz/src/hb-aat-layout-trak-table.hh index 68bcb2396f..2ba9355b06 100644 --- a/thirdparty/harfbuzz/src/hb-aat-layout-trak-table.hh +++ b/thirdparty/harfbuzz/src/hb-aat-layout-trak-table.hh @@ -62,7 +62,7 @@ struct TrackTableEntry } protected: - HBFixed track; /* Track value for this record. */ + F16DOT16 track; /* Track value for this record. */ NameID trackNameID; /* The 'name' table index for this track. * (a short word or phrase like "loose" * or "very tight") */ @@ -82,7 +82,7 @@ struct TrackData const void *base) const { unsigned int sizes = nSizes; - hb_array_t<const HBFixed> size_table ((base+sizeTable).arrayZ, sizes); + hb_array_t<const F16DOT16> size_table ((base+sizeTable).arrayZ, sizes); float s0 = size_table[idx].to_float (); float s1 = size_table[idx + 1].to_float (); @@ -120,7 +120,7 @@ struct TrackData if (!sizes) return 0.; if (sizes == 1) return trackTableEntry->get_value (base, 0, sizes); - hb_array_t<const HBFixed> size_table ((base+sizeTable).arrayZ, sizes); + hb_array_t<const F16DOT16> size_table ((base+sizeTable).arrayZ, sizes); unsigned int size_index; for (size_index = 0; size_index < sizes - 1; size_index++) if (size_table[size_index].to_float () >= ptem) @@ -141,7 +141,7 @@ struct TrackData protected: HBUINT16 nTracks; /* Number of separate tracks included in this table. */ HBUINT16 nSizes; /* Number of point sizes included in this table. */ - NNOffset32To<UnsizedArrayOf<HBFixed>> + NNOffset32To<UnsizedArrayOf<F16DOT16>> sizeTable; /* Offset from start of the tracking table to * Array[nSizes] of size values.. */ UnsizedArrayOf<TrackTableEntry> diff --git a/thirdparty/harfbuzz/src/hb-aat-layout.cc b/thirdparty/harfbuzz/src/hb-aat-layout.cc index e06d286ff0..78427b0d5a 100644 --- a/thirdparty/harfbuzz/src/hb-aat-layout.cc +++ b/thirdparty/harfbuzz/src/hb-aat-layout.cc @@ -131,6 +131,7 @@ static const hb_aat_feature_mapping_t feature_mappings[] = {HB_TAG ('p','n','u','m'), HB_AAT_LAYOUT_FEATURE_TYPE_NUMBER_SPACING, HB_AAT_LAYOUT_FEATURE_SELECTOR_PROPORTIONAL_NUMBERS, (hb_aat_layout_feature_selector_t) 4}, {HB_TAG ('p','w','i','d'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING, HB_AAT_LAYOUT_FEATURE_SELECTOR_PROPORTIONAL_TEXT, (hb_aat_layout_feature_selector_t) 7}, {HB_TAG ('q','w','i','d'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING, HB_AAT_LAYOUT_FEATURE_SELECTOR_QUARTER_WIDTH_TEXT, (hb_aat_layout_feature_selector_t) 7}, + {HB_TAG ('r','l','i','g'), HB_AAT_LAYOUT_FEATURE_TYPE_LIGATURES, HB_AAT_LAYOUT_FEATURE_SELECTOR_REQUIRED_LIGATURES_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_REQUIRED_LIGATURES_OFF}, {HB_TAG ('r','u','b','y'), HB_AAT_LAYOUT_FEATURE_TYPE_RUBY_KANA, HB_AAT_LAYOUT_FEATURE_SELECTOR_RUBY_KANA_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_RUBY_KANA_OFF}, {HB_TAG ('s','i','n','f'), HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_POSITION, HB_AAT_LAYOUT_FEATURE_SELECTOR_SCIENTIFIC_INFERIORS, HB_AAT_LAYOUT_FEATURE_SELECTOR_NORMAL_POSITION}, {HB_TAG ('s','m','c','p'), HB_AAT_LAYOUT_FEATURE_TYPE_LOWER_CASE, HB_AAT_LAYOUT_FEATURE_SELECTOR_LOWER_CASE_SMALL_CAPS, HB_AAT_LAYOUT_FEATURE_SELECTOR_DEFAULT_LOWER_CASE}, @@ -288,7 +289,7 @@ is_deleted_glyph (const hb_glyph_info_t *info) void hb_aat_layout_remove_deleted_glyphs (hb_buffer_t *buffer) { - hb_ot_layout_delete_glyphs_inplace (buffer, is_deleted_glyph); + buffer->delete_glyphs_inplace (is_deleted_glyph); } /** diff --git a/thirdparty/harfbuzz/src/hb-aat-map.hh b/thirdparty/harfbuzz/src/hb-aat-map.hh index c914f58d70..d0ee7d672c 100644 --- a/thirdparty/harfbuzz/src/hb-aat-map.hh +++ b/thirdparty/harfbuzz/src/hb-aat-map.hh @@ -38,7 +38,7 @@ struct hb_aat_map_t void init () { - memset (this, 0, sizeof (*this)); + hb_memset (this, 0, sizeof (*this)); chain_flags.init (); } void fini () { chain_flags.fini (); } diff --git a/thirdparty/harfbuzz/src/hb-algs.hh b/thirdparty/harfbuzz/src/hb-algs.hh index cc37c073da..d85a4afe10 100644 --- a/thirdparty/harfbuzz/src/hb-algs.hh +++ b/thirdparty/harfbuzz/src/hb-algs.hh @@ -236,17 +236,6 @@ struct template <typename T> constexpr auto impl (const T& v, hb_priority<1>) const HB_RETURN (uint32_t, hb_deref (v).hash ()) - template <typename T> constexpr uint32_t - impl (const hb::shared_ptr<T>& v, hb_priority<1>) const - { - return v.get () ? v.get ()->hash () : 0; - } - template <typename T> constexpr uint32_t - impl (const hb::unique_ptr<T>& v, hb_priority<1>) const - { - return v.get () ? v.get ()->hash () : 0; - } - template <typename T> constexpr auto impl (const T& v, hb_priority<0>) const HB_RETURN (uint32_t, std::hash<hb_decay<decltype (hb_deref (v))>>{} (hb_deref (v))) @@ -495,6 +484,17 @@ struct } HB_FUNCOBJ (hb_equal); +struct +{ + template <typename T> void + operator () (T& a, T& b) const + { + using std::swap; // allow ADL + swap (a, b); + } +} +HB_FUNCOBJ (hb_swap); + template <typename T1, typename T2> struct hb_pair_t @@ -507,7 +507,7 @@ struct hb_pair_t hb_enable_if (std::is_default_constructible<U1>::value && std::is_default_constructible<U2>::value)> hb_pair_t () : first (), second () {} - hb_pair_t (T1 a, T2 b) : first (a), second (b) {} + hb_pair_t (T1 a, T2 b) : first (std::forward<T1> (a)), second (std::forward<T2> (b)) {} template <typename Q1, typename Q2, hb_enable_if (hb_is_convertible (T1, Q1) && @@ -524,6 +524,25 @@ struct hb_pair_t bool operator > (const pair_t& o) const { return first > o.first || (first == o.first && second > o.second); } bool operator <= (const pair_t& o) const { return !(*this > o); } + static int cmp (const void *pa, const void *pb) + { + pair_t *a = (pair_t *) pa; + pair_t *b = (pair_t *) pb; + + if (a->first < b->first) return -1; + if (a->first > b->first) return +1; + if (a->second < b->second) return -1; + if (a->second > b->second) return +1; + return 0; + } + + friend void swap (hb_pair_t& a, hb_pair_t& b) + { + hb_swap (a.first, b.first); + hb_swap (a.second, b.second); + } + + T1 first; T2 second; }; @@ -570,17 +589,6 @@ struct } HB_FUNCOBJ (hb_clamp); -struct -{ - template <typename T> void - operator () (T& a, T& b) const - { - using std::swap; // allow ADL - swap (a, b); - } -} -HB_FUNCOBJ (hb_swap); - /* * Bithacks. */ @@ -849,19 +857,14 @@ hb_in_range (T u, T lo, T hi) return (T)(u - lo) <= (T)(hi - lo); } template <typename T> static inline bool -hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2) +hb_in_ranges (T u, T lo1, T hi1) { - return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2); + return hb_in_range (u, lo1, hi1); } -template <typename T> static inline bool -hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2, T lo3, T hi3) +template <typename T, typename ...Ts> static inline bool +hb_in_ranges (T u, T lo1, T hi1, Ts... ds) { - return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2) || hb_in_range (u, lo3, hi3); -} -template <typename T> static inline bool -hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2, T lo3, T hi3, T lo4, T hi4) -{ - return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2) || hb_in_range (u, lo3, hi3) || hb_in_range (u, lo4, hi4); + return hb_in_range<T> (u, lo1, hi1) || hb_in_ranges<T> (u, ds...); } @@ -869,10 +872,18 @@ hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2, T lo3, T hi3, T lo4, T hi4) * Overflow checking. */ -/* Consider __builtin_mul_overflow use here also */ static inline bool -hb_unsigned_mul_overflows (unsigned int count, unsigned int size) +hb_unsigned_mul_overflows (unsigned int count, unsigned int size, unsigned *result = nullptr) { +#if (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__) + unsigned stack_result; + if (!result) + result = &stack_result; + return __builtin_mul_overflow (count, size, result); +#endif + + if (result) + *result = count * size; return (size > 0) && (count >= ((unsigned int) -1) / size); } @@ -1164,9 +1175,12 @@ hb_qsort (void *base, size_t nel, size_t width, } -template <typename T, typename T2, typename T3> static inline void -hb_stable_sort (T *array, unsigned int len, int(*compar)(const T2 *, const T2 *), T3 *array2) +template <typename T, typename T2, typename T3 = int> static inline void +hb_stable_sort (T *array, unsigned int len, int(*compar)(const T2 *, const T2 *), T3 *array2 = nullptr) { + static_assert (hb_is_trivially_copy_assignable (T), ""); + static_assert (hb_is_trivially_copy_assignable (T3), ""); + for (unsigned int i = 1; i < len; i++) { unsigned int j = i; @@ -1189,12 +1203,6 @@ hb_stable_sort (T *array, unsigned int len, int(*compar)(const T2 *, const T2 *) } } -template <typename T> static inline void -hb_stable_sort (T *array, unsigned int len, int(*compar)(const T *, const T *)) -{ - hb_stable_sort (array, len, compar, (int *) nullptr); -} - static inline hb_bool_t hb_codepoint_parse (const char *s, unsigned int len, int base, hb_codepoint_t *out) { @@ -1322,47 +1330,4 @@ struct HB_FUNCOBJ (hb_dec); -/* Compiler-assisted vectorization. */ - -/* Type behaving similar to vectorized vars defined using __attribute__((vector_size(...))), - * basically a fixed-size bitset. */ -template <typename elt_t, unsigned int byte_size> -struct hb_vector_size_t -{ - elt_t& operator [] (unsigned int i) { return v[i]; } - const elt_t& operator [] (unsigned int i) const { return v[i]; } - - void clear (unsigned char v = 0) { memset (this, v, sizeof (*this)); } - - template <typename Op> - hb_vector_size_t process (const Op& op) const - { - hb_vector_size_t r; - for (unsigned int i = 0; i < ARRAY_LENGTH (v); i++) - r.v[i] = op (v[i]); - return r; - } - template <typename Op> - hb_vector_size_t process (const Op& op, const hb_vector_size_t &o) const - { - hb_vector_size_t r; - for (unsigned int i = 0; i < ARRAY_LENGTH (v); i++) - r.v[i] = op (v[i], o.v[i]); - return r; - } - hb_vector_size_t operator | (const hb_vector_size_t &o) const - { return process (hb_bitwise_or, o); } - hb_vector_size_t operator & (const hb_vector_size_t &o) const - { return process (hb_bitwise_and, o); } - hb_vector_size_t operator ^ (const hb_vector_size_t &o) const - { return process (hb_bitwise_xor, o); } - hb_vector_size_t operator ~ () const - { return process (hb_bitwise_neg); } - - private: - static_assert (0 == byte_size % sizeof (elt_t), ""); - elt_t v[byte_size / sizeof (elt_t)]; -}; - - #endif /* HB_ALGS_HH */ diff --git a/thirdparty/harfbuzz/src/hb-array.hh b/thirdparty/harfbuzz/src/hb-array.hh index 5884007c19..17562bc336 100644 --- a/thirdparty/harfbuzz/src/hb-array.hh +++ b/thirdparty/harfbuzz/src/hb-array.hh @@ -100,10 +100,18 @@ struct hb_array_t : hb_iter_with_fallback_t<hb_array_t<Type>, Type&> /* Ouch. The operator== compares the contents of the array. For range-based for loops, * it's best if we can just compare arrayZ, though comparing contents is still fast, * but also would require that Type has operator==. As such, we optimize this operator - * for range-based for loop and just compare arrayZ and length. */ + * for range-based for loop and just compare arrayZ and length. + * + * The above comment is outdated now because we implemented separate begin/end to + * objects that were using hb_array_t for range-based loop before. */ bool operator != (const hb_array_t& o) const { return this->arrayZ != o.arrayZ || this->length != o.length; } + /* Faster range-based for loop without bounds-check. */ + Type *begin () const { return arrayZ; } + Type *end () const { return arrayZ + length; } + + /* Extra operators. */ Type * operator & () const { return arrayZ; } @@ -112,11 +120,11 @@ struct hb_array_t : hb_iter_with_fallback_t<hb_array_t<Type>, Type&> HB_INTERNAL bool operator == (const hb_array_t &o) const; - uint32_t hash () const { + uint32_t hash () const + { uint32_t current = 0; - for (unsigned int i = 0; i < this->length; i++) { - current = current * 31 + hb_hash (this->arrayZ[i]); - } + for (auto &v : *this) + current = current * 31 + hb_hash (v); return current; } @@ -184,23 +192,18 @@ struct hb_array_t : hb_iter_with_fallback_t<hb_array_t<Type>, Type&> hb_sorted_array_t<Type> qsort (int (*cmp_)(const void*, const void*)) { + //static_assert (hb_enable_if (hb_is_trivially_copy_assignable(Type)), ""); if (likely (length)) hb_qsort (arrayZ, length, this->get_item_size (), cmp_); return hb_sorted_array_t<Type> (*this); } hb_sorted_array_t<Type> qsort () { + //static_assert (hb_enable_if (hb_is_trivially_copy_assignable(Type)), ""); if (likely (length)) hb_qsort (arrayZ, length, this->get_item_size (), Type::cmp); return hb_sorted_array_t<Type> (*this); } - void qsort (unsigned int start, unsigned int end) - { - end = hb_min (end, length); - assert (start <= end); - if (likely (start < end)) - hb_qsort (arrayZ + start, end - start, this->get_item_size (), Type::cmp); - } /* * Other methods. @@ -262,17 +265,31 @@ struct hb_array_t : hb_iter_with_fallback_t<hb_array_t<Type>, Type&> void fini () { hb_free ((void *) arrayZ); arrayZ = nullptr; length = 0; } - template <typename hb_serialize_context_t> + template <typename hb_serialize_context_t, + typename U = Type, + hb_enable_if (!(sizeof (U) < sizeof (long long) && hb_is_trivially_copy_assignable(hb_decay<Type>)))> hb_array_t copy (hb_serialize_context_t *c) const { TRACE_SERIALIZE (this); auto* out = c->start_embed (arrayZ); - if (unlikely (!c->extend_size (out, get_size ()))) return_trace (hb_array_t ()); + if (unlikely (!c->extend_size (out, get_size (), false))) return_trace (hb_array_t ()); for (unsigned i = 0; i < length; i++) out[i] = arrayZ[i]; /* TODO: add version that calls c->copy() */ return_trace (hb_array_t (out, length)); } + template <typename hb_serialize_context_t, + typename U = Type, + hb_enable_if (sizeof (U) < sizeof (long long) && hb_is_trivially_copy_assignable(hb_decay<Type>))> + hb_array_t copy (hb_serialize_context_t *c) const + { + TRACE_SERIALIZE (this); + auto* out = c->start_embed (arrayZ); + if (unlikely (!c->extend_size (out, get_size (), false))) return_trace (hb_array_t ()); + hb_memcpy (out, arrayZ, get_size ()); + return_trace (hb_array_t (out, length)); + } + template <typename hb_sanitize_context_t> bool sanitize (hb_sanitize_context_t *c) const { return c->check_array (arrayZ, length); } @@ -295,8 +312,8 @@ hb_array (T (&array_)[length_]) template <typename Type> struct hb_sorted_array_t : - hb_iter_t<hb_sorted_array_t<Type>, Type&>, - hb_array_t<Type> + hb_array_t<Type>, + hb_iter_t<hb_sorted_array_t<Type>, Type&> { typedef hb_iter_t<hb_sorted_array_t, Type&> iter_base_t; HB_ITER_USING (iter_base_t); @@ -316,8 +333,8 @@ struct hb_sorted_array_t : template <typename U, hb_enable_if (hb_is_cr_convertible(U, Type))> constexpr hb_sorted_array_t (const hb_array_t<U> &o) : - hb_iter_t<hb_sorted_array_t, Type&> (), - hb_array_t<Type> (o) {} + hb_array_t<Type> (o), + hb_iter_t<hb_sorted_array_t, Type&> () {} template <typename U, hb_enable_if (hb_is_cr_convertible(U, Type))> hb_sorted_array_t& operator = (const hb_array_t<U> &o) @@ -329,6 +346,11 @@ struct hb_sorted_array_t : bool operator != (const hb_sorted_array_t& o) const { return this->arrayZ != o.arrayZ || this->length != o.length; } + /* Faster range-based for loop without bounds-check. */ + Type *begin () const { return this->arrayZ; } + Type *end () const { return this->arrayZ + this->length; } + + hb_sorted_array_t sub_array (unsigned int start_offset, unsigned int *seg_count /* IN/OUT */) const { return hb_sorted_array_t (((const hb_array_t<Type> *) (this))->sub_array (start_offset, seg_count)); } hb_sorted_array_t sub_array (unsigned int start_offset, unsigned int seg_count) const @@ -421,18 +443,42 @@ inline bool hb_array_t<const unsigned char>::operator == (const hb_array_t<const return 0 == hb_memcmp (arrayZ, o.arrayZ, length); } + +/* Specialize hash() for byte arrays. */ + template <> -inline uint32_t hb_array_t<const char>::hash () const { +inline uint32_t hb_array_t<const char>::hash () const +{ uint32_t current = 0; - for (unsigned int i = 0; i < this->length; i++) - current = current * 31 + (uint32_t) (this->arrayZ[i] * 2654435761u); + unsigned i = 0; + +#if defined(__OPTIMIZE__) && !defined(HB_NO_PACKED) && \ + ((defined(__GNUC__) && __GNUC__ >= 5) || defined(__clang__)) + struct __attribute__((packed)) packed_uint32_t { uint32_t v; }; + for (; i + 4 <= this->length; i += 4) + current = current * 31 + hb_hash ((uint32_t) ((packed_uint32_t *) &this->arrayZ[i])->v); +#endif + + for (; i < this->length; i++) + current = current * 31 + hb_hash (this->arrayZ[i]); return current; } + template <> -inline uint32_t hb_array_t<const unsigned char>::hash () const { +inline uint32_t hb_array_t<const unsigned char>::hash () const +{ uint32_t current = 0; - for (unsigned int i = 0; i < this->length; i++) - current = current * 31 + (uint32_t) (this->arrayZ[i] * 2654435761u); + unsigned i = 0; + +#if defined(__OPTIMIZE__) && !defined(HB_NO_PACKED) && \ + ((defined(__GNUC__) && __GNUC__ >= 5) || defined(__clang__)) + struct __attribute__((packed)) packed_uint32_t { uint32_t v; }; + for (; i + 4 <= this->length; i += 4) + current = current * 31 + hb_hash ((uint32_t) ((packed_uint32_t *) &this->arrayZ[i])->v); +#endif + + for (; i < this->length; i++) + current = current * 31 + hb_hash (this->arrayZ[i]); return current; } diff --git a/thirdparty/harfbuzz/src/hb-bit-page.hh b/thirdparty/harfbuzz/src/hb-bit-page.hh index 95ae1b7bf9..11987054f8 100644 --- a/thirdparty/harfbuzz/src/hb-bit-page.hh +++ b/thirdparty/harfbuzz/src/hb-bit-page.hh @@ -30,6 +30,53 @@ #include "hb.hh" + +/* Compiler-assisted vectorization. */ + +/* Type behaving similar to vectorized vars defined using __attribute__((vector_size(...))), + * basically a fixed-size bitset. */ +template <typename elt_t, unsigned int byte_size> +struct hb_vector_size_t +{ + elt_t& operator [] (unsigned int i) { return v[i]; } + const elt_t& operator [] (unsigned int i) const { return v[i]; } + + void clear (unsigned char v = 0) { hb_memset (this, v, sizeof (*this)); } + + template <typename Op> + hb_vector_size_t process (const Op& op) const + { + hb_vector_size_t r; + for (unsigned int i = 0; i < ARRAY_LENGTH (v); i++) + r.v[i] = op (v[i]); + return r; + } + template <typename Op> + hb_vector_size_t process (const Op& op, const hb_vector_size_t &o) const + { + hb_vector_size_t r; + for (unsigned int i = 0; i < ARRAY_LENGTH (v); i++) + r.v[i] = op (v[i], o.v[i]); + return r; + } + hb_vector_size_t operator | (const hb_vector_size_t &o) const + { return process (hb_bitwise_or, o); } + hb_vector_size_t operator & (const hb_vector_size_t &o) const + { return process (hb_bitwise_and, o); } + hb_vector_size_t operator ^ (const hb_vector_size_t &o) const + { return process (hb_bitwise_xor, o); } + hb_vector_size_t operator ~ () const + { return process (hb_bitwise_neg); } + + hb_array_t<const elt_t> iter () const + { return hb_array (v); } + + private: + static_assert (0 == byte_size % sizeof (elt_t), ""); + elt_t v[byte_size / sizeof (elt_t)]; +}; + + struct hb_bit_page_t { void init0 () { v.clear (); } @@ -40,17 +87,17 @@ struct hb_bit_page_t bool is_empty () const { - for (unsigned i = 0; i < len (); i++) - if (v[i]) - return false; - return true; + return + + hb_iter (v) + | hb_none + ; } uint32_t hash () const { - uint32_t h = 0; - for (unsigned i = 0; i < len (); i++) - h = h * 31 + hb_hash (v[i]); - return h; + return + + hb_iter (v) + | hb_reduce ([] (uint32_t h, const elt_t &_) { return h * 31 + hb_hash (_); }, (uint32_t) 0u) + ; } void add (hb_codepoint_t g) { elt (g) |= mask (g); } @@ -69,7 +116,7 @@ struct hb_bit_page_t *la |= ~(mask (a) - 1); la++; - memset (la, 0xff, (char *) lb - (char *) la); + hb_memset (la, 0xff, (char *) lb - (char *) la); *lb |= ((mask (b) << 1) - 1); } @@ -85,7 +132,7 @@ struct hb_bit_page_t *la &= mask (a) - 1; la++; - memset (la, 0, (char *) lb - (char *) la); + hb_memset (la, 0, (char *) lb - (char *) la); *lb &= ~((mask (b) << 1) - 1); } @@ -101,13 +148,13 @@ struct hb_bit_page_t hb_codepoint_t *p, unsigned int size) const { - unsigned int start_v = start_value >> ELT_BITS_LOG_2; + unsigned int start_v = start_value / ELT_BITS; unsigned int start_bit = start_value & ELT_MASK; unsigned int count = 0; for (unsigned i = start_v; i < len () && count < size; i++) { elt_t bits = v[i]; - uint32_t v_base = base | (i << ELT_BITS_LOG_2); + uint32_t v_base = base | (i * ELT_BITS); for (unsigned int j = start_bit; j < ELT_BITS && count < size; j++) { if ((elt_t(1) << j) & bits) { @@ -132,13 +179,13 @@ struct hb_bit_page_t unsigned int size, hb_codepoint_t *next_value) const { - unsigned int start_v = start_value >> ELT_BITS_LOG_2; + unsigned int start_v = start_value / ELT_BITS; unsigned int start_bit = start_value & ELT_MASK; unsigned int count = 0; for (unsigned i = start_v; i < len () && count < size; i++) { elt_t bits = v[i]; - uint32_t v_offset = i << ELT_BITS_LOG_2; + uint32_t v_offset = i * ELT_BITS; for (unsigned int j = start_bit; j < ELT_BITS && count < size; j++) { if ((elt_t(1) << j) & bits) @@ -161,7 +208,10 @@ struct hb_bit_page_t bool is_equal (const hb_bit_page_t &other) const { - return 0 == hb_memcmp (&v, &other.v, sizeof (v)); + for (unsigned i = 0; i < len (); i++) + if (v[i] != other.v[i]) + return false; + return true; } bool is_subset (const hb_bit_page_t &larger_page) const { @@ -173,10 +223,10 @@ struct hb_bit_page_t unsigned int get_population () const { - unsigned int pop = 0; - for (unsigned int i = 0; i < len (); i++) - pop += hb_popcount (v[i]); - return pop; + return + + hb_iter (v) + | hb_reduce ([] (unsigned pop, const elt_t &_) { return pop + hb_popcount (_); }, 0u) + ; } bool next (hb_codepoint_t *codepoint) const @@ -262,8 +312,6 @@ struct hb_bit_page_t typedef hb_vector_size_t<elt_t, PAGE_BITS / 8> vector_t; static constexpr unsigned ELT_BITS = sizeof (elt_t) * 8; - static constexpr unsigned ELT_BITS_LOG_2 = 6; - static_assert (1 << ELT_BITS_LOG_2 == ELT_BITS, ""); static constexpr unsigned ELT_MASK = ELT_BITS - 1; static constexpr unsigned BITS = sizeof (vector_t) * 8; diff --git a/thirdparty/harfbuzz/src/hb-bit-set-invertible.hh b/thirdparty/harfbuzz/src/hb-bit-set-invertible.hh index 27fb0732ea..ff8aecc60c 100644 --- a/thirdparty/harfbuzz/src/hb-bit-set-invertible.hh +++ b/thirdparty/harfbuzz/src/hb-bit-set-invertible.hh @@ -123,10 +123,8 @@ struct hb_bit_set_invertible_t bool get (hb_codepoint_t g) const { return s.get (g) ^ inverted; } /* Has interface. */ - static constexpr bool SENTINEL = false; - typedef bool value_t; - value_t operator [] (hb_codepoint_t k) const { return get (k); } - bool has (hb_codepoint_t k) const { return (*this)[k] != SENTINEL; } + bool operator [] (hb_codepoint_t k) const { return get (k); } + bool has (hb_codepoint_t k) const { return (*this)[k]; } /* Predicate. */ bool operator () (hb_codepoint_t k) const { return has (k); } diff --git a/thirdparty/harfbuzz/src/hb-bit-set.hh b/thirdparty/harfbuzz/src/hb-bit-set.hh index a63887efda..8de6e037fb 100644 --- a/thirdparty/harfbuzz/src/hb-bit-set.hh +++ b/thirdparty/harfbuzz/src/hb-bit-set.hh @@ -85,10 +85,10 @@ struct hb_bit_set_t void err () { if (successful) successful = false; } /* TODO Remove */ bool in_error () const { return !successful; } - bool resize (unsigned int count) + bool resize (unsigned int count, bool clear = true) { if (unlikely (!successful)) return false; - if (unlikely (!pages.resize (count) || !page_map.resize (count))) + if (unlikely (!pages.resize (count, clear) || !page_map.resize (count, clear))) { pages.resize (page_map.length); successful = false; @@ -330,10 +330,8 @@ struct hb_bit_set_t } /* Has interface. */ - static constexpr bool SENTINEL = false; - typedef bool value_t; - value_t operator [] (hb_codepoint_t k) const { return get (k); } - bool has (hb_codepoint_t k) const { return (*this)[k] != SENTINEL; } + bool operator [] (hb_codepoint_t k) const { return get (k); } + bool has (hb_codepoint_t k) const { return (*this)[k]; } /* Predicate. */ bool operator () (hb_codepoint_t k) const { return has (k); } @@ -352,7 +350,7 @@ struct hb_bit_set_t { if (unlikely (!successful)) return; unsigned int count = other.pages.length; - if (unlikely (!resize (count))) + if (unlikely (!resize (count, false))) return; population = other.population; @@ -391,7 +389,7 @@ struct hb_bit_set_t bool is_subset (const hb_bit_set_t &larger_set) const { if (has_population () && larger_set.has_population () && - population != larger_set.population) + population > larger_set.population) return false; uint32_t spi = 0; @@ -540,21 +538,21 @@ struct hb_bit_set_t b = nb; for (; a && b; ) { - if (page_map[a - 1].major == other.page_map[b - 1].major) + if (page_map.arrayZ[a - 1].major == other.page_map.arrayZ[b - 1].major) { a--; b--; count--; - page_map[count] = page_map[a]; + page_map.arrayZ[count] = page_map.arrayZ[a]; page_at (count).v = op (page_at (a).v, other.page_at (b).v); } - else if (page_map[a - 1].major > other.page_map[b - 1].major) + else if (page_map.arrayZ[a - 1].major > other.page_map.arrayZ[b - 1].major) { a--; if (passthru_left) { count--; - page_map[count] = page_map[a]; + page_map.arrayZ[count] = page_map.arrayZ[a]; } } else @@ -563,8 +561,8 @@ struct hb_bit_set_t if (passthru_right) { count--; - page_map[count].major = other.page_map[b].major; - page_map[count].index = next_page++; + page_map.arrayZ[count].major = other.page_map.arrayZ[b].major; + page_map.arrayZ[count].index = next_page++; page_at (count).v = other.page_at (b).v; } } @@ -574,15 +572,15 @@ struct hb_bit_set_t { a--; count--; - page_map[count] = page_map [a]; + page_map.arrayZ[count] = page_map.arrayZ[a]; } if (passthru_right) while (b) { b--; count--; - page_map[count].major = other.page_map[b].major; - page_map[count].index = next_page++; + page_map.arrayZ[count].major = other.page_map.arrayZ[b].major; + page_map.arrayZ[count].index = next_page++; page_at (count).v = other.page_at (b).v; } assert (!count); @@ -605,8 +603,6 @@ struct hb_bit_set_t bool next (hb_codepoint_t *codepoint) const { - // TODO: this should be merged with prev() as both implementations - // are very similar. if (unlikely (*codepoint == INVALID)) { *codepoint = get_min (); return *codepoint != INVALID; @@ -640,7 +636,7 @@ struct hb_bit_set_t for (; i < page_map.length; i++) { - const page_map_t ¤t = page_map.arrayZ[i]; + const page_map_t ¤t = page_map_array[i]; hb_codepoint_t m = pages_array[current.index].get_min (); if (m != INVALID) { @@ -663,21 +659,21 @@ struct hb_bit_set_t page_map_t map = {get_major (*codepoint), 0}; unsigned int i; page_map.bfind (map, &i, HB_NOT_FOUND_STORE_CLOSEST); - if (i < page_map.length && page_map[i].major == map.major) + if (i < page_map.length && page_map.arrayZ[i].major == map.major) { - if (pages[page_map[i].index].previous (codepoint)) + if (pages[page_map.arrayZ[i].index].previous (codepoint)) { - *codepoint += page_map[i].major * page_t::PAGE_BITS; + *codepoint += page_map.arrayZ[i].major * page_t::PAGE_BITS; return true; } } i--; for (; (int) i >= 0; i--) { - hb_codepoint_t m = pages[page_map[i].index].get_max (); + hb_codepoint_t m = pages.arrayZ[page_map.arrayZ[i].index].get_max (); if (m != INVALID) { - *codepoint = page_map[i].major * page_t::PAGE_BITS + m; + *codepoint = page_map.arrayZ[i].major * page_t::PAGE_BITS + m; return true; } } @@ -905,7 +901,7 @@ struct hb_bit_set_t { auto &cached_page = page_map.arrayZ[i]; if (cached_page.major == major) - return &pages[cached_page.index]; + return &pages.arrayZ[cached_page.index]; } page_map_t map = {major, pages.length}; @@ -917,15 +913,15 @@ struct hb_bit_set_t if (unlikely (!resize (pages.length + 1))) return nullptr; - pages[map.index].init0 (); - memmove (page_map + i + 1, - page_map + i, + pages.arrayZ[map.index].init0 (); + memmove (page_map.arrayZ + i + 1, + page_map.arrayZ + i, (page_map.length - 1 - i) * page_map.item_size); page_map[i] = map; } last_page_lookup = i; - return &pages[page_map[i].index]; + return &pages.arrayZ[page_map.arrayZ[i].index]; } const page_t *page_for (hb_codepoint_t g) const { @@ -939,7 +935,7 @@ struct hb_bit_set_t { auto &cached_page = page_map.arrayZ[i]; if (cached_page.major == major) - return &pages[cached_page.index]; + return &pages.arrayZ[cached_page.index]; } page_map_t key = {major}; @@ -947,10 +943,18 @@ struct hb_bit_set_t return nullptr; last_page_lookup = i; - return &pages[page_map[i].index]; + return &pages.arrayZ[page_map[i].index]; + } + page_t &page_at (unsigned int i) + { + assert (i < page_map.length); + return pages.arrayZ[page_map.arrayZ[i].index]; + } + const page_t &page_at (unsigned int i) const + { + assert (i < page_map.length); + return pages.arrayZ[page_map.arrayZ[i].index]; } - page_t &page_at (unsigned int i) { return pages[page_map[i].index]; } - const page_t &page_at (unsigned int i) const { return pages[page_map[i].index]; } unsigned int get_major (hb_codepoint_t g) const { return g >> page_t::PAGE_BITS_LOG_2; } unsigned int page_remainder (hb_codepoint_t g) const { return g & page_t::PAGE_BITMASK; } hb_codepoint_t major_start (unsigned int major) const { return major << page_t::PAGE_BITS_LOG_2; } diff --git a/thirdparty/harfbuzz/src/hb-blob.cc b/thirdparty/harfbuzz/src/hb-blob.cc index 9bc12ea3fa..f0fda1fa4d 100644 --- a/thirdparty/harfbuzz/src/hb-blob.cc +++ b/thirdparty/harfbuzz/src/hb-blob.cc @@ -495,7 +495,7 @@ hb_blob_t::try_make_writable () DEBUG_MSG_FUNC (BLOB, this, "dupped successfully -> %p\n", this->data); - memcpy (new_data, this->data, this->length); + hb_memcpy (new_data, this->data, this->length); this->destroy_user_data (); this->mode = HB_MEMORY_MODE_WRITABLE; this->data = new_data; diff --git a/thirdparty/harfbuzz/src/hb-buffer-deserialize-json.hh b/thirdparty/harfbuzz/src/hb-buffer-deserialize-json.hh index 87095855d6..993bb1f698 100644 --- a/thirdparty/harfbuzz/src/hb-buffer-deserialize-json.hh +++ b/thirdparty/harfbuzz/src/hb-buffer-deserialize-json.hh @@ -32,7 +32,7 @@ #include "hb.hh" -#line 36 "hb-buffer-deserialize-json.hh" +#line 33 "hb-buffer-deserialize-json.hh" static const unsigned char _deserialize_json_trans_keys[] = { 0u, 0u, 9u, 123u, 9u, 34u, 97u, 117u, 120u, 121u, 34u, 34u, 9u, 58u, 9u, 57u, 48u, 57u, 9u, 125u, 9u, 125u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u, 48u, 57u, @@ -557,12 +557,12 @@ _hb_buffer_deserialize_json (hb_buffer_t *buffer, hb_glyph_info_t info = {0}; hb_glyph_position_t pos = {0}; -#line 561 "hb-buffer-deserialize-json.hh" +#line 554 "hb-buffer-deserialize-json.hh" { cs = deserialize_json_start; } -#line 566 "hb-buffer-deserialize-json.hh" +#line 557 "hb-buffer-deserialize-json.hh" { int _slen; int _trans; @@ -590,8 +590,8 @@ _resume: case 1: #line 38 "hb-buffer-deserialize-json.rl" { - memset (&info, 0, sizeof (info)); - memset (&pos , 0, sizeof (pos )); + hb_memset (&info, 0, sizeof (info)); + hb_memset (&pos , 0, sizeof (pos )); } break; case 5: @@ -774,7 +774,7 @@ _resume: *end_ptr = p; } break; -#line 778 "hb-buffer-deserialize-json.hh" +#line 735 "hb-buffer-deserialize-json.hh" } _again: diff --git a/thirdparty/harfbuzz/src/hb-buffer-deserialize-text.hh b/thirdparty/harfbuzz/src/hb-buffer-deserialize-text.hh index 9062610de2..6b9b4282fc 100644 --- a/thirdparty/harfbuzz/src/hb-buffer-deserialize-text.hh +++ b/thirdparty/harfbuzz/src/hb-buffer-deserialize-text.hh @@ -32,32 +32,30 @@ #include "hb.hh" -#line 36 "hb-buffer-deserialize-text.hh" +#line 33 "hb-buffer-deserialize-text.hh" static const unsigned char _deserialize_text_trans_keys[] = { - 0u, 0u, 9u, 91u, 85u, 85u, 43u, 43u, 48u, 102u, 9u, 85u, 48u, 57u, 45u, 57u, - 48u, 57u, 48u, 57u, 48u, 57u, 45u, 57u, 48u, 57u, 44u, 44u, 45u, 57u, 48u, 57u, - 44u, 57u, 43u, 124u, 45u, 57u, 48u, 57u, 9u, 124u, 9u, 124u, 0u, 0u, 9u, 85u, + 0u, 0u, 9u, 91u, 85u, 85u, 43u, 43u, 48u, 102u, 9u, 85u, 48u, 57u, 48u, 57u, + 45u, 57u, 48u, 57u, 45u, 57u, 48u, 57u, 48u, 57u, 45u, 57u, 48u, 57u, 44u, 44u, + 45u, 57u, 48u, 57u, 44u, 57u, 43u, 124u, 9u, 124u, 9u, 124u, 0u, 0u, 9u, 85u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, - 9u, 124u, 9u, 124u, 9u, 124u, 0 + 0 }; static const char _deserialize_text_key_spans[] = { - 0, 83, 1, 1, 55, 77, 10, 13, - 10, 10, 10, 13, 10, 1, 13, 10, - 14, 82, 13, 10, 116, 116, 0, 77, - 116, 116, 116, 116, 116, 116, 116, 116, + 0, 83, 1, 1, 55, 77, 10, 10, + 13, 10, 13, 10, 10, 13, 10, 1, + 13, 10, 14, 82, 116, 116, 0, 77, 116, 116, 116, 116, 116, 116, 116, 116, - 116, 116, 116 + 116, 116, 116, 116, 116, 116, 116, 116 }; static const short _deserialize_text_index_offsets[] = { 0, 0, 84, 86, 88, 144, 222, 233, - 247, 258, 269, 280, 294, 305, 307, 321, - 332, 347, 430, 444, 455, 572, 689, 690, + 244, 258, 269, 283, 294, 305, 319, 330, + 332, 346, 357, 372, 455, 572, 689, 690, 768, 885, 1002, 1119, 1236, 1353, 1470, 1587, - 1704, 1821, 1938, 2055, 2172, 2289, 2406, 2523, - 2640, 2757, 2874 + 1704, 1821, 1938, 2055, 2172, 2289, 2406, 2523 }; static const char _deserialize_text_indicies[] = { @@ -90,34 +88,34 @@ static const char _deserialize_text_indicies[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 1, 8, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 1, 10, 1, 1, 11, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 1, + 9, 1, 10, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 1, 12, 1, 1, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 1, 15, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 1, 17, 18, - 18, 18, 18, 18, 18, 18, 18, 18, - 1, 19, 1, 1, 20, 21, 21, 21, + 16, 16, 16, 16, 16, 1, 17, 1, + 1, 18, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 1, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 1, 22, 23, 23, 23, 23, 23, 23, 23, 23, - 23, 1, 24, 1, 25, 1, 1, 26, - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 1, 28, 29, 29, 29, 29, 29, - 29, 29, 29, 29, 1, 24, 1, 1, - 1, 23, 23, 23, 23, 23, 23, 23, - 23, 23, 23, 1, 30, 30, 1, 1, + 23, 1, 24, 1, 1, 25, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 1, + 27, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 1, 29, 1, 30, 1, 1, + 31, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 1, 33, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 1, 29, 1, + 1, 1, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 1, 35, 35, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 30, 1, - 1, 30, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 35, + 1, 1, 35, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 30, 30, 1, + 1, 1, 1, 1, 1, 1, 35, 35, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 30, 1, 31, - 1, 1, 32, 33, 33, 33, 33, 33, - 33, 33, 33, 33, 1, 34, 35, 35, - 35, 35, 35, 35, 35, 35, 35, 1, + 1, 1, 1, 1, 1, 1, 35, 1, 36, 36, 36, 36, 36, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 36, @@ -201,282 +199,235 @@ static const char _deserialize_text_indicies[] = { 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 56, 48, - 57, 57, 57, 57, 57, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 57, - 30, 30, 58, 30, 30, 30, 30, 30, - 30, 30, 59, 1, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 60, 30, 30, 61, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 62, 63, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 64, 30, 57, 57, 57, - 57, 57, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 57, 30, 30, 58, - 30, 30, 30, 30, 30, 30, 30, 59, - 1, 30, 30, 30, 65, 66, 66, 66, - 66, 66, 66, 66, 66, 66, 30, 30, - 30, 60, 30, 30, 61, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 62, 63, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 64, 30, 67, 67, 67, 67, 67, 1, + 57, 57, 57, 57, 57, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 57, + 35, 35, 58, 35, 35, 35, 35, 35, + 35, 35, 59, 1, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 60, 35, 35, 61, + 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 62, 63, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 64, 35, 65, 65, 65, + 65, 65, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 65, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 67, 1, 1, 68, 1, 1, 1, - 1, 1, 1, 1, 1, 69, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 70, 1, + 1, 66, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 71, 1, 72, - 72, 72, 72, 72, 1, 1, 1, 1, + 67, 1, 68, 68, 68, 68, 68, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 72, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 68, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 42, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 42, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 73, 1, 74, 74, 74, 74, - 74, 48, 48, 48, 48, 48, 48, 48, + 1, 1, 1, 1, 1, 69, 1, 70, + 70, 70, 70, 70, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 74, 48, 48, 50, 48, - 48, 48, 48, 48, 48, 48, 51, 1, + 48, 48, 48, 48, 48, 48, 70, 48, + 48, 50, 48, 48, 48, 48, 48, 48, + 48, 51, 1, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 52, 48, 48, 53, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 52, 48, 48, 53, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 54, - 55, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 54, 55, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 56, - 48, 75, 75, 75, 75, 75, 1, 1, + 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 56, 48, 71, 71, 71, 71, + 71, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 71, 1, 1, 72, 1, + 1, 1, 1, 1, 1, 1, 1, 73, 1, 1, 1, 1, 1, 1, 1, 1, - 75, 1, 1, 76, 1, 1, 1, 1, - 1, 1, 1, 77, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 78, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 45, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 74, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 79, 1, 80, 80, - 80, 80, 80, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 75, + 1, 76, 76, 76, 76, 76, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 80, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 76, 1, 1, 77, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 81, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 78, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 82, 1, 80, 80, 80, 80, 80, + 1, 1, 1, 1, 79, 1, 76, 76, + 76, 76, 76, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 76, 1, 1, + 77, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 80, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 83, 83, 83, 83, 83, 83, - 83, 83, 83, 83, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 78, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 81, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 79, 1, 71, 71, 71, 71, 71, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 82, 1, - 84, 84, 84, 84, 84, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 84, - 1, 1, 85, 1, 1, 1, 1, 1, - 1, 1, 86, 1, 1, 1, 1, 1, + 1, 1, 71, 1, 1, 72, 1, 1, + 1, 1, 1, 1, 1, 1, 73, 1, + 1, 1, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 74, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 87, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 75, 1, + 80, 80, 80, 80, 80, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 88, 1, 84, 84, 84, - 84, 84, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 80, + 1, 1, 81, 1, 1, 1, 1, 1, + 1, 1, 82, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 84, 1, 1, 85, - 1, 1, 1, 1, 1, 1, 1, 86, - 1, 1, 1, 1, 29, 29, 29, 29, - 29, 29, 29, 29, 29, 29, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 83, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 45, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 87, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 84, 1, 85, 85, 85, + 85, 85, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 88, 1, 75, 75, 75, 75, 75, 1, + 1, 1, 1, 1, 85, 1, 1, 86, + 1, 1, 1, 1, 1, 1, 1, 87, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 75, 1, 1, 76, 1, 1, 1, - 1, 1, 1, 1, 77, 1, 1, 1, - 1, 89, 89, 89, 89, 89, 89, 89, - 89, 89, 89, 1, 1, 1, 1, 1, - 1, 78, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 45, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 88, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 79, 1, 90, - 90, 90, 90, 90, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 90, 1, - 1, 91, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 89, 1, 85, 85, 85, 85, 85, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 85, 1, 1, 86, 1, 1, 1, + 1, 1, 1, 1, 87, 1, 1, 1, + 1, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 92, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 88, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 93, 1, 90, 90, 90, 90, - 90, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 90, 1, 1, 91, 1, + 1, 1, 1, 1, 1, 89, 1, 80, + 80, 80, 80, 80, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 35, 35, 35, 35, 35, - 35, 35, 35, 35, 35, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 80, 1, + 1, 81, 1, 1, 1, 1, 1, 1, + 1, 82, 1, 1, 1, 1, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, + 1, 1, 1, 1, 1, 1, 83, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 45, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 92, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 93, - 1, 67, 67, 67, 67, 67, 1, 1, + 1, 1, 84, 1, 65, 65, 65, 65, + 65, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 65, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 67, 1, 1, 68, 1, 1, 1, 1, - 1, 1, 1, 1, 69, 1, 1, 1, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 70, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 66, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 71, 1, 94, 94, - 94, 94, 94, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 94, 30, 30, - 58, 30, 30, 30, 30, 30, 30, 30, - 59, 1, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 60, 30, 30, 61, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 62, 95, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 96, 30, 94, 94, 94, 94, 94, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 94, 30, 30, 58, 30, 30, - 30, 30, 30, 30, 30, 59, 1, 30, - 30, 30, 97, 97, 97, 97, 97, 97, - 97, 97, 97, 97, 30, 30, 30, 60, - 30, 30, 61, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 62, 95, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 96, 30, - 0 + 1, 1, 1, 1, 1, 1, 1, 67, + 1, 0 }; static const char _deserialize_text_trans_targs[] = { 1, 0, 2, 26, 3, 4, 20, 5, - 24, 25, 8, 29, 40, 29, 40, 32, - 37, 33, 34, 12, 13, 16, 13, 16, - 14, 15, 35, 36, 35, 36, 27, 19, - 38, 39, 38, 39, 21, 20, 6, 22, + 24, 25, 28, 39, 9, 31, 34, 31, + 34, 11, 32, 33, 32, 33, 35, 38, + 14, 15, 18, 15, 18, 16, 17, 36, + 37, 36, 37, 27, 21, 20, 6, 22, 23, 21, 22, 23, 21, 22, 23, 25, - 27, 27, 28, 7, 9, 11, 17, 22, - 31, 27, 28, 7, 9, 11, 17, 22, - 31, 41, 42, 30, 10, 18, 22, 31, - 30, 31, 31, 30, 10, 7, 11, 31, - 30, 22, 31, 34, 30, 10, 7, 22, - 31, 37, 30, 10, 22, 31, 27, 22, - 31, 42 + 27, 27, 7, 8, 12, 13, 19, 22, + 30, 27, 7, 8, 12, 13, 19, 22, + 30, 29, 22, 30, 29, 30, 30, 29, + 7, 10, 22, 30, 29, 7, 22, 30, + 29, 7, 8, 13, 30, 29, 7, 8, + 22, 30, 38, 39 }; static const char _deserialize_text_trans_actions[] = { 0, 0, 0, 0, 1, 0, 2, 0, - 2, 2, 3, 4, 4, 5, 5, 4, - 4, 4, 4, 3, 3, 3, 0, 0, - 6, 3, 4, 4, 5, 5, 5, 3, - 4, 4, 5, 5, 7, 8, 9, 7, + 2, 2, 3, 3, 4, 3, 3, 5, + 5, 4, 3, 3, 5, 5, 3, 3, + 4, 4, 4, 0, 0, 6, 4, 3, + 3, 5, 5, 5, 7, 8, 9, 7, 7, 0, 0, 0, 10, 10, 10, 8, - 12, 13, 14, 15, 15, 15, 16, 11, - 11, 18, 19, 20, 20, 20, 0, 17, - 17, 4, 4, 21, 22, 22, 21, 21, - 0, 0, 13, 10, 23, 23, 23, 10, - 24, 24, 24, 5, 25, 26, 26, 25, - 25, 5, 27, 28, 27, 27, 30, 29, - 29, 5 + 12, 13, 14, 14, 14, 14, 15, 11, + 11, 17, 18, 18, 18, 18, 0, 16, + 16, 19, 19, 19, 0, 0, 13, 20, + 21, 21, 20, 20, 22, 23, 22, 22, + 10, 24, 24, 24, 10, 25, 26, 26, + 25, 25, 5, 5 }; static const char _deserialize_text_eof_actions[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, - 10, 10, 11, 17, 17, 21, 0, 11, - 10, 24, 24, 25, 25, 10, 27, 27, - 21, 29, 29 + 10, 10, 11, 16, 19, 0, 11, 20, + 22, 22, 20, 10, 25, 25, 10, 19 }; static const int deserialize_text_start = 1; @@ -509,12 +460,12 @@ _hb_buffer_deserialize_text (hb_buffer_t *buffer, hb_glyph_info_t info = {0}; hb_glyph_position_t pos = {0}; -#line 513 "hb-buffer-deserialize-text.hh" +#line 457 "hb-buffer-deserialize-text.hh" { cs = deserialize_text_start; } -#line 518 "hb-buffer-deserialize-text.hh" +#line 460 "hb-buffer-deserialize-text.hh" { int _slen; int _trans; @@ -542,11 +493,11 @@ _resume: case 1: #line 38 "hb-buffer-deserialize-text.rl" { - memset (&info, 0, sizeof (info)); - memset (&pos , 0, sizeof (pos )); + hb_memset (&info, 0, sizeof (info)); + hb_memset (&pos , 0, sizeof (pos )); } break; - case 3: + case 4: #line 51 "hb-buffer-deserialize-text.rl" { tok = p; @@ -560,7 +511,7 @@ _resume: #line 56 "hb-buffer-deserialize-text.rl" { if (unlikely (!buffer->ensure_unicode ())) return false; } break; - case 20: + case 18: #line 58 "hb-buffer-deserialize-text.rl" { /* TODO Unescape delimiters. */ @@ -574,7 +525,7 @@ _resume: #line 66 "hb-buffer-deserialize-text.rl" {if (!parse_hex (tok, p, &info.codepoint )) return false; } break; - case 23: + case 24: #line 68 "hb-buffer-deserialize-text.rl" { if (!parse_uint (tok, p, &info.cluster )) return false; } break; @@ -586,26 +537,26 @@ _resume: #line 70 "hb-buffer-deserialize-text.rl" { if (!parse_int (tok, p, &pos.y_offset )) return false; } break; - case 22: + case 21: #line 71 "hb-buffer-deserialize-text.rl" { if (!parse_int (tok, p, &pos.x_advance)) return false; } break; - case 28: + case 23: #line 72 "hb-buffer-deserialize-text.rl" { if (!parse_int (tok, p, &pos.y_advance)) return false; } break; - case 16: + case 15: #line 38 "hb-buffer-deserialize-text.rl" { - memset (&info, 0, sizeof (info)); - memset (&pos , 0, sizeof (pos )); + hb_memset (&info, 0, sizeof (info)); + hb_memset (&pos , 0, sizeof (pos )); } #line 51 "hb-buffer-deserialize-text.rl" { tok = p; } break; - case 4: + case 3: #line 51 "hb-buffer-deserialize-text.rl" { tok = p; @@ -621,7 +572,7 @@ _resume: #line 56 "hb-buffer-deserialize-text.rl" { if (unlikely (!buffer->ensure_unicode ())) return false; } break; - case 17: + case 16: #line 58 "hb-buffer-deserialize-text.rl" { /* TODO Unescape delimiters. */ @@ -639,18 +590,6 @@ _resume: *end_ptr = p; } break; - case 19: -#line 58 "hb-buffer-deserialize-text.rl" - { - /* TODO Unescape delimiters. */ - if (!hb_font_glyph_from_string (font, - tok, p - tok, - &info.codepoint)) - return false; -} -#line 55 "hb-buffer-deserialize-text.rl" - { if (unlikely (!buffer->ensure_glyphs ())) return false; } - break; case 7: #line 66 "hb-buffer-deserialize-text.rl" {if (!parse_hex (tok, p, &info.codepoint )) return false; } @@ -687,7 +626,7 @@ _resume: *end_ptr = p; } break; - case 21: + case 20: #line 71 "hb-buffer-deserialize-text.rl" { if (!parse_int (tok, p, &pos.x_advance)) return false; } #line 43 "hb-buffer-deserialize-text.rl" @@ -699,7 +638,7 @@ _resume: *end_ptr = p; } break; - case 27: + case 22: #line 72 "hb-buffer-deserialize-text.rl" { if (!parse_int (tok, p, &pos.y_advance)) return false; } #line 43 "hb-buffer-deserialize-text.rl" @@ -711,7 +650,7 @@ _resume: *end_ptr = p; } break; - case 24: + case 19: #line 73 "hb-buffer-deserialize-text.rl" { if (!parse_uint (tok, p, &info.mask )) return false; } #line 43 "hb-buffer-deserialize-text.rl" @@ -726,8 +665,8 @@ _resume: case 12: #line 38 "hb-buffer-deserialize-text.rl" { - memset (&info, 0, sizeof (info)); - memset (&pos , 0, sizeof (pos )); + hb_memset (&info, 0, sizeof (info)); + hb_memset (&pos , 0, sizeof (pos )); } #line 51 "hb-buffer-deserialize-text.rl" { @@ -736,11 +675,11 @@ _resume: #line 55 "hb-buffer-deserialize-text.rl" { if (unlikely (!buffer->ensure_glyphs ())) return false; } break; - case 15: + case 14: #line 38 "hb-buffer-deserialize-text.rl" { - memset (&info, 0, sizeof (info)); - memset (&pos , 0, sizeof (pos )); + hb_memset (&info, 0, sizeof (info)); + hb_memset (&pos , 0, sizeof (pos )); } #line 51 "hb-buffer-deserialize-text.rl" { @@ -755,7 +694,7 @@ _resume: return false; } break; - case 18: + case 17: #line 58 "hb-buffer-deserialize-text.rl" { /* TODO Unescape delimiters. */ @@ -775,31 +714,11 @@ _resume: *end_ptr = p; } break; - case 29: -#line 58 "hb-buffer-deserialize-text.rl" - { - /* TODO Unescape delimiters. */ - if (!hb_font_glyph_from_string (font, - tok, p - tok, - &info.codepoint)) - return false; -} -#line 73 "hb-buffer-deserialize-text.rl" - { if (!parse_uint (tok, p, &info.mask )) return false; } -#line 43 "hb-buffer-deserialize-text.rl" - { - buffer->add_info (info); - if (unlikely (!buffer->successful)) - return false; - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; -} - break; case 11: #line 38 "hb-buffer-deserialize-text.rl" { - memset (&info, 0, sizeof (info)); - memset (&pos , 0, sizeof (pos )); + hb_memset (&info, 0, sizeof (info)); + hb_memset (&pos , 0, sizeof (pos )); } #line 51 "hb-buffer-deserialize-text.rl" { @@ -822,54 +741,11 @@ _resume: *end_ptr = p; } break; - case 14: -#line 38 "hb-buffer-deserialize-text.rl" - { - memset (&info, 0, sizeof (info)); - memset (&pos , 0, sizeof (pos )); -} -#line 51 "hb-buffer-deserialize-text.rl" - { - tok = p; -} -#line 58 "hb-buffer-deserialize-text.rl" - { - /* TODO Unescape delimiters. */ - if (!hb_font_glyph_from_string (font, - tok, p - tok, - &info.codepoint)) - return false; -} -#line 55 "hb-buffer-deserialize-text.rl" - { if (unlikely (!buffer->ensure_glyphs ())) return false; } - break; - case 30: -#line 58 "hb-buffer-deserialize-text.rl" - { - /* TODO Unescape delimiters. */ - if (!hb_font_glyph_from_string (font, - tok, p - tok, - &info.codepoint)) - return false; -} -#line 73 "hb-buffer-deserialize-text.rl" - { if (!parse_uint (tok, p, &info.mask )) return false; } -#line 55 "hb-buffer-deserialize-text.rl" - { if (unlikely (!buffer->ensure_glyphs ())) return false; } -#line 43 "hb-buffer-deserialize-text.rl" - { - buffer->add_info (info); - if (unlikely (!buffer->successful)) - return false; - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; -} - break; case 13: #line 38 "hb-buffer-deserialize-text.rl" { - memset (&info, 0, sizeof (info)); - memset (&pos , 0, sizeof (pos )); + hb_memset (&info, 0, sizeof (info)); + hb_memset (&pos , 0, sizeof (pos )); } #line 51 "hb-buffer-deserialize-text.rl" { @@ -894,7 +770,7 @@ _resume: *end_ptr = p; } break; -#line 898 "hb-buffer-deserialize-text.hh" +#line 715 "hb-buffer-deserialize-text.hh" } _again: @@ -906,7 +782,7 @@ _again: if ( p == eof ) { switch ( _deserialize_text_eof_actions[cs] ) { - case 17: + case 16: #line 58 "hb-buffer-deserialize-text.rl" { /* TODO Unescape delimiters. */ @@ -960,7 +836,7 @@ _again: *end_ptr = p; } break; - case 21: + case 20: #line 71 "hb-buffer-deserialize-text.rl" { if (!parse_int (tok, p, &pos.x_advance)) return false; } #line 43 "hb-buffer-deserialize-text.rl" @@ -972,7 +848,7 @@ _again: *end_ptr = p; } break; - case 27: + case 22: #line 72 "hb-buffer-deserialize-text.rl" { if (!parse_int (tok, p, &pos.y_advance)) return false; } #line 43 "hb-buffer-deserialize-text.rl" @@ -984,27 +860,7 @@ _again: *end_ptr = p; } break; - case 24: -#line 73 "hb-buffer-deserialize-text.rl" - { if (!parse_uint (tok, p, &info.mask )) return false; } -#line 43 "hb-buffer-deserialize-text.rl" - { - buffer->add_info (info); - if (unlikely (!buffer->successful)) - return false; - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; -} - break; - case 29: -#line 58 "hb-buffer-deserialize-text.rl" - { - /* TODO Unescape delimiters. */ - if (!hb_font_glyph_from_string (font, - tok, p - tok, - &info.codepoint)) - return false; -} + case 19: #line 73 "hb-buffer-deserialize-text.rl" { if (!parse_uint (tok, p, &info.mask )) return false; } #line 43 "hb-buffer-deserialize-text.rl" @@ -1019,8 +875,8 @@ _again: case 11: #line 38 "hb-buffer-deserialize-text.rl" { - memset (&info, 0, sizeof (info)); - memset (&pos , 0, sizeof (pos )); + hb_memset (&info, 0, sizeof (info)); + hb_memset (&pos , 0, sizeof (pos )); } #line 51 "hb-buffer-deserialize-text.rl" { @@ -1043,7 +899,7 @@ _again: *end_ptr = p; } break; -#line 1047 "hb-buffer-deserialize-text.hh" +#line 825 "hb-buffer-deserialize-text.hh" } } diff --git a/thirdparty/harfbuzz/src/hb-buffer-serialize.cc b/thirdparty/harfbuzz/src/hb-buffer-serialize.cc index d1e1775430..a458f2318f 100644 --- a/thirdparty/harfbuzz/src/hb-buffer-serialize.cc +++ b/thirdparty/harfbuzz/src/hb-buffer-serialize.cc @@ -183,7 +183,7 @@ _hb_buffer_serialize_glyphs_json (hb_buffer_t *buffer, unsigned int l = p - b; if (buf_size > l) { - memcpy (buf, b, l); + hb_memcpy (buf, b, l); buf += l; buf_size -= l; *buf_consumed += l; @@ -241,7 +241,7 @@ _hb_buffer_serialize_unicode_json (hb_buffer_t *buffer, unsigned int l = p - b; if (buf_size > l) { - memcpy (buf, b, l); + hb_memcpy (buf, b, l); buf += l; buf_size -= l; *buf_consumed += l; @@ -329,7 +329,7 @@ _hb_buffer_serialize_glyphs_text (hb_buffer_t *buffer, unsigned int l = p - b; if (buf_size > l) { - memcpy (buf, b, l); + hb_memcpy (buf, b, l); buf += l; buf_size -= l; *buf_consumed += l; @@ -381,7 +381,7 @@ _hb_buffer_serialize_unicode_text (hb_buffer_t *buffer, unsigned int l = p - b; if (buf_size > l) { - memcpy (buf, b, l); + hb_memcpy (buf, b, l); buf += l; buf_size -= l; *buf_consumed += l; diff --git a/thirdparty/harfbuzz/src/hb-buffer-verify.cc b/thirdparty/harfbuzz/src/hb-buffer-verify.cc index 5453e1ca94..1cd52b39b1 100644 --- a/thirdparty/harfbuzz/src/hb-buffer-verify.cc +++ b/thirdparty/harfbuzz/src/hb-buffer-verify.cc @@ -186,7 +186,7 @@ buffer_verify_unsafe_to_break (hb_buffer_t *buffer, bool ret = true; hb_buffer_diff_flags_t diff = hb_buffer_diff (reconstruction, buffer, (hb_codepoint_t) -1, 0); - if (diff) + if (diff & ~HB_BUFFER_DIFF_FLAG_GLYPH_FLAGS_MISMATCH) { buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "unsafe-to-break test failed."); ret = false; @@ -313,7 +313,6 @@ buffer_verify_unsafe_to_concat (hb_buffer_t *buffer, bool ret = true; hb_buffer_diff_flags_t diff; - /* * Shape the two fragment streams. */ @@ -382,7 +381,7 @@ buffer_verify_unsafe_to_concat (hb_buffer_t *buffer, * Diff results. */ diff = hb_buffer_diff (reconstruction, buffer, (hb_codepoint_t) -1, 0); - if (diff) + if (diff & ~HB_BUFFER_DIFF_FLAG_GLYPH_FLAGS_MISMATCH) { buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "unsafe-to-concat test failed."); ret = false; diff --git a/thirdparty/harfbuzz/src/hb-buffer.cc b/thirdparty/harfbuzz/src/hb-buffer.cc index 57a5ae03ed..4b6c2d9eaa 100644 --- a/thirdparty/harfbuzz/src/hb-buffer.cc +++ b/thirdparty/harfbuzz/src/hb-buffer.cc @@ -172,12 +172,13 @@ hb_buffer_t::enlarge (unsigned int size) while (size >= new_allocated) new_allocated += (new_allocated >> 1) + 32; - static_assert ((sizeof (info[0]) == sizeof (pos[0])), ""); - if (unlikely (hb_unsigned_mul_overflows (new_allocated, sizeof (info[0])))) + unsigned new_bytes; + if (unlikely (hb_unsigned_mul_overflows (new_allocated, sizeof (info[0]), &new_bytes))) goto done; - new_pos = (hb_glyph_position_t *) hb_realloc (pos, new_allocated * sizeof (pos[0])); - new_info = (hb_glyph_info_t *) hb_realloc (info, new_allocated * sizeof (info[0])); + static_assert (sizeof (info[0]) == sizeof (pos[0]), ""); + new_pos = (hb_glyph_position_t *) hb_realloc (pos, new_bytes); + new_info = (hb_glyph_info_t *) hb_realloc (info, new_bytes); done: if (unlikely (!new_pos || !new_info)) @@ -208,7 +209,7 @@ hb_buffer_t::make_room_for (unsigned int num_in, assert (have_output); out_info = (hb_glyph_info_t *) pos; - memcpy (out_info, info, out_len * sizeof (out_info[0])); + hb_memcpy (out_info, info, out_len * sizeof (out_info[0])); } return true; @@ -229,7 +230,7 @@ hb_buffer_t::shift_forward (unsigned int count) * Ideally, we should at least set Default_Ignorable bits on * these, as well as consistent cluster values. But the former * is layering violation... */ - memset (info + len, 0, (idx + count - len) * sizeof (info[0])); + hb_memset (info + len, 0, (idx + count - len) * sizeof (info[0])); } len += count; idx += count; @@ -298,8 +299,8 @@ hb_buffer_t::clear () out_len = 0; out_info = info; - memset (context, 0, sizeof context); - memset (context_len, 0, sizeof context_len); + hb_memset (context, 0, sizeof context); + hb_memset (context_len, 0, sizeof context_len); deallocate_var_all (); serial = 0; @@ -313,15 +314,14 @@ hb_buffer_t::enter () serial = 0; shaping_failed = false; scratch_flags = HB_BUFFER_SCRATCH_FLAG_DEFAULT; - if (likely (!hb_unsigned_mul_overflows (len, HB_BUFFER_MAX_LEN_FACTOR))) + unsigned mul; + if (likely (!hb_unsigned_mul_overflows (len, HB_BUFFER_MAX_LEN_FACTOR, &mul))) { - max_len = hb_max (len * HB_BUFFER_MAX_LEN_FACTOR, - (unsigned) HB_BUFFER_MAX_LEN_MIN); + max_len = hb_max (mul, (unsigned) HB_BUFFER_MAX_LEN_MIN); } - if (likely (!hb_unsigned_mul_overflows (len, HB_BUFFER_MAX_OPS_FACTOR))) + if (likely (!hb_unsigned_mul_overflows (len, HB_BUFFER_MAX_OPS_FACTOR, &mul))) { - max_ops = hb_max (len * HB_BUFFER_MAX_OPS_FACTOR, - (unsigned) HB_BUFFER_MAX_OPS_MIN); + max_ops = hb_max (mul, (unsigned) HB_BUFFER_MAX_OPS_MIN); } } void @@ -345,7 +345,7 @@ hb_buffer_t::add (hb_codepoint_t codepoint, glyph = &info[len]; - memset (glyph, 0, sizeof (*glyph)); + hb_memset (glyph, 0, sizeof (*glyph)); glyph->codepoint = codepoint; glyph->mask = 0; glyph->cluster = cluster; @@ -606,6 +606,53 @@ done: } void +hb_buffer_t::delete_glyphs_inplace (bool (*filter) (const hb_glyph_info_t *info)) +{ + /* Merge clusters and delete filtered glyphs. + * NOTE! We can't use out-buffer as we have positioning data. */ + unsigned int j = 0; + unsigned int count = len; + for (unsigned int i = 0; i < count; i++) + { + if (filter (&info[i])) + { + /* Merge clusters. + * Same logic as delete_glyph(), but for in-place removal. */ + + unsigned int cluster = info[i].cluster; + if (i + 1 < count && cluster == info[i + 1].cluster) + continue; /* Cluster survives; do nothing. */ + + if (j) + { + /* Merge cluster backward. */ + if (cluster < info[j - 1].cluster) + { + unsigned int mask = info[i].mask; + unsigned int old_cluster = info[j - 1].cluster; + for (unsigned k = j; k && info[k - 1].cluster == old_cluster; k--) + set_cluster (info[k - 1], cluster, mask); + } + continue; + } + + if (i + 1 < count) + merge_clusters (i, i + 2); /* Merge cluster forward. */ + + continue; + } + + if (j != i) + { + info[j] = info[i]; + pos[j] = pos[i]; + } + j++; + } + len = j; +} + +void hb_buffer_t::guess_segment_properties () { assert_unicode (); @@ -933,7 +980,6 @@ hb_buffer_get_unicode_funcs (const hb_buffer_t *buffer) void hb_buffer_set_direction (hb_buffer_t *buffer, hb_direction_t direction) - { if (unlikely (hb_object_is_immutable (buffer))) return; @@ -1385,9 +1431,9 @@ hb_buffer_set_length (hb_buffer_t *buffer, /* Wipe the new space */ if (length > buffer->len) { - memset (buffer->info + buffer->len, 0, sizeof (buffer->info[0]) * (length - buffer->len)); + hb_memset (buffer->info + buffer->len, 0, sizeof (buffer->info[0]) * (length - buffer->len)); if (buffer->have_positions) - memset (buffer->pos + buffer->len, 0, sizeof (buffer->pos[0]) * (length - buffer->len)); + hb_memset (buffer->pos + buffer->len, 0, sizeof (buffer->pos[0]) * (length - buffer->len)); } buffer->len = length; @@ -1795,7 +1841,9 @@ hb_buffer_add_latin1 (hb_buffer_t *buffer, * marks at stat of run. * * This function does not check the validity of @text, it is up to the caller - * to ensure it contains a valid Unicode code points. + * to ensure it contains a valid Unicode scalar values. In contrast, + * hb_buffer_add_utf32() can be used that takes similar input but performs + * sanity-check on the input. * * Since: 0.9.31 **/ @@ -1858,9 +1906,9 @@ hb_buffer_append (hb_buffer_t *buffer, hb_segment_properties_overlay (&buffer->props, &source->props); - memcpy (buffer->info + orig_len, source->info + start, (end - start) * sizeof (buffer->info[0])); + hb_memcpy (buffer->info + orig_len, source->info + start, (end - start) * sizeof (buffer->info[0])); if (buffer->have_positions) - memcpy (buffer->pos + orig_len, source->pos + start, (end - start) * sizeof (buffer->pos[0])); + hb_memcpy (buffer->pos + orig_len, source->pos + start, (end - start) * sizeof (buffer->pos[0])); if (source->content_type == HB_BUFFER_CONTENT_TYPE_UNICODE) { @@ -2048,7 +2096,7 @@ hb_buffer_diff (hb_buffer_t *buffer, result |= HB_BUFFER_DIFF_FLAG_CODEPOINT_MISMATCH; if (buf_info->cluster != ref_info->cluster) result |= HB_BUFFER_DIFF_FLAG_CLUSTER_MISMATCH; - if ((buf_info->mask & ~ref_info->mask & HB_GLYPH_FLAG_DEFINED)) + if ((buf_info->mask ^ ref_info->mask) & HB_GLYPH_FLAG_DEFINED) result |= HB_BUFFER_DIFF_FLAG_GLYPH_FLAGS_MISMATCH; if (contains && ref_info->codepoint == dottedcircle_glyph) result |= HB_BUFFER_DIFF_FLAG_DOTTED_CIRCLE_PRESENT; @@ -2103,6 +2151,13 @@ hb_buffer_set_message_func (hb_buffer_t *buffer, hb_buffer_message_func_t func, void *user_data, hb_destroy_func_t destroy) { + if (unlikely (hb_object_is_immutable (buffer))) + { + if (destroy) + destroy (user_data); + return; + } + if (buffer->message_destroy) buffer->message_destroy (buffer->message_data); diff --git a/thirdparty/harfbuzz/src/hb-buffer.hh b/thirdparty/harfbuzz/src/hb-buffer.hh index 26c3f0fac8..bb1efe9dd3 100644 --- a/thirdparty/harfbuzz/src/hb-buffer.hh +++ b/thirdparty/harfbuzz/src/hb-buffer.hh @@ -32,6 +32,7 @@ #include "hb.hh" #include "hb-unicode.hh" +#include "hb-set-digest.hh" #ifndef HB_BUFFER_MAX_LEN_FACTOR @@ -207,6 +208,14 @@ struct hb_buffer_t hb_glyph_info_t &prev () { return out_info[out_len ? out_len - 1 : 0]; } hb_glyph_info_t prev () const { return out_info[out_len ? out_len - 1 : 0]; } + hb_set_digest_t digest () const + { + hb_set_digest_t d; + d.init (); + d.add_array (&info[0].codepoint, len, sizeof (info[0])); + return d; + } + HB_INTERNAL void similar (const hb_buffer_t &src); HB_INTERNAL void reset (); HB_INTERNAL void clear (); @@ -402,6 +411,8 @@ struct hb_buffer_t HB_INTERNAL void merge_out_clusters (unsigned int start, unsigned int end); /* Merge clusters for deleting current glyph, and skip it. */ HB_INTERNAL void delete_glyph (); + HB_INTERNAL void delete_glyphs_inplace (bool (*filter) (const hb_glyph_info_t *info)); + /* Adds glyph flags in mask to infos with clusters between start and end. diff --git a/thirdparty/harfbuzz/src/hb-cache.hh b/thirdparty/harfbuzz/src/hb-cache.hh index 897f313fbd..f8c8108f1f 100644 --- a/thirdparty/harfbuzz/src/hb-cache.hh +++ b/thirdparty/harfbuzz/src/hb-cache.hh @@ -46,7 +46,7 @@ struct hb_cache_t >::type; static_assert ((key_bits >= cache_bits), ""); - static_assert ((key_bits + value_bits - cache_bits <= 8 * sizeof (item_t)), ""); + static_assert ((key_bits + value_bits <= cache_bits + 8 * sizeof (item_t)), ""); void init () { clear (); } void fini () {} diff --git a/thirdparty/harfbuzz/src/hb-cff-interp-common.hh b/thirdparty/harfbuzz/src/hb-cff-interp-common.hh index 5c2cb060a4..49805a89c5 100644 --- a/thirdparty/harfbuzz/src/hb-cff-interp-common.hh +++ b/thirdparty/harfbuzz/src/hb-cff-interp-common.hh @@ -284,65 +284,56 @@ struct UnsizedByteStr : UnsizedArrayOf <HBUINT8> /* A byte string associated with the current offset and an error condition */ struct byte_str_ref_t { - byte_str_ref_t () { init (); } - - void init () - { - str = hb_ubytes_t (); - offset = 0; - error = false; - } - - void fini () {} + byte_str_ref_t () + : str () {} byte_str_ref_t (const hb_ubytes_t &str_, unsigned int offset_ = 0) - : str (str_), offset (offset_), error (false) {} + : str (str_) { set_offset (offset_); } void reset (const hb_ubytes_t &str_, unsigned int offset_ = 0) { str = str_; - offset = offset_; - error = false; + set_offset (offset_); } const unsigned char& operator [] (int i) { - if (unlikely ((unsigned int) (offset + i) >= str.length)) + if (unlikely ((unsigned int) (get_offset () + i) >= str.length)) { set_error (); return Null (unsigned char); } - return str[offset + i]; + return str.arrayZ[get_offset () + i]; } + unsigned char head_unchecked () const { return str.arrayZ[get_offset ()]; } + /* Conversion to hb_ubytes_t */ - operator hb_ubytes_t () const { return str.sub_array (offset, str.length - offset); } + operator hb_ubytes_t () const { return str.sub_array (get_offset ()); } hb_ubytes_t sub_array (unsigned int offset_, unsigned int len_) const { return str.sub_array (offset_, len_); } bool avail (unsigned int count=1) const - { return (!in_error () && offset + count <= str.length); } + { return get_offset () + count <= str.length; } void inc (unsigned int count=1) { - if (likely (!in_error () && (offset <= str.length) && (offset + count <= str.length))) - { - offset += count; - } - else - { - offset = str.length; - set_error (); - } + /* Automatically puts us in error if count is out-of-range. */ + set_offset (get_offset () + count); } - void set_error () { error = true; } - bool in_error () const { return error; } + /* We (ab)use ubytes backwards_length as a cursor (called offset), + * as well as to store error condition. */ - hb_ubytes_t str; - unsigned int offset; /* beginning of the sub-string within str */ + unsigned get_offset () const { return str.backwards_length; } + void set_offset (unsigned offset) { str.backwards_length = offset; } + + void set_error () { str.backwards_length = str.length + 1; } + bool in_error () const { return str.backwards_length > str.length; } + + unsigned total_size () const { return str.length; } protected: - bool error; + hb_ubytes_t str; }; using byte_str_array_t = hb_vector_t<hb_ubytes_t>; @@ -491,8 +482,15 @@ struct arg_stack_t : cff_stack_t<ARG, 513> /* an operator prefixed by its operands in a byte string */ struct op_str_t { - hb_ubytes_t str; + /* This used to have a hb_ubytes_t. Using a pointer and length + * in a particular order, saves 8 bytes in this struct and more + * in our parsed_cs_op_t subclass. */ + + const unsigned char *ptr = nullptr; + op_code_t op; + + uint8_t length = 0; }; /* base of OP_SERIALIZER */ @@ -503,9 +501,11 @@ struct op_serializer_t { TRACE_SERIALIZE (this); - HBUINT8 *d = c->allocate_size<HBUINT8> (opstr.str.length); + unsigned char *d = c->allocate_size<unsigned char> (opstr.length); if (unlikely (!d)) return_trace (false); - memcpy (d, &opstr.str[0], opstr.str.length); + /* Faster than hb_memcpy for small strings. */ + for (unsigned i = 0; i < opstr.length; i++) + d[i] = opstr.ptr[i]; return_trace (true); } }; @@ -529,16 +529,20 @@ struct parsed_values_t { VAL *val = values.push (); val->op = op; - val->str = str_ref.str.sub_array (opStart, str_ref.offset - opStart); - opStart = str_ref.offset; + auto arr = str_ref.sub_array (opStart, str_ref.get_offset () - opStart); + val->ptr = arr.arrayZ; + val->length = arr.length; + opStart = str_ref.get_offset (); } void add_op (op_code_t op, const byte_str_ref_t& str_ref, const VAL &v) { VAL *val = values.push (v); val->op = op; - val->str = str_ref.sub_array ( opStart, str_ref.offset - opStart); - opStart = str_ref.offset; + auto arr = str_ref.sub_array (opStart, str_ref.get_offset () - opStart); + val->ptr = arr.arrayZ; + val->length = arr.length; + opStart = str_ref.get_offset (); } bool has_op (op_code_t op) const @@ -549,8 +553,7 @@ struct parsed_values_t } unsigned get_count () const { return values.length; } - const VAL &get_value (unsigned int i) const { return values[i]; } - const VAL &operator [] (unsigned int i) const { return get_value (i); } + const VAL &operator [] (unsigned int i) const { return values[i]; } unsigned int opStart; hb_vector_t<VAL> values; @@ -565,23 +568,23 @@ struct interp_env_t str_ref.reset (str_); } bool in_error () const - { return error || str_ref.in_error () || argStack.in_error (); } + { return str_ref.in_error () || argStack.in_error (); } - void set_error () { error = true; } + void set_error () { str_ref.set_error (); } op_code_t fetch_op () { op_code_t op = OpCode_Invalid; if (unlikely (!str_ref.avail ())) return OpCode_Invalid; - op = (op_code_t)(unsigned char)str_ref[0]; + op = (op_code_t) str_ref.head_unchecked (); + str_ref.inc (); if (op == OpCode_escape) { if (unlikely (!str_ref.avail ())) return OpCode_Invalid; - op = Make_OpCode_ESC(str_ref[1]); + op = Make_OpCode_ESC (str_ref.head_unchecked ()); str_ref.inc (); } - str_ref.inc (); return op; } @@ -596,8 +599,6 @@ struct interp_env_t str_ref; arg_stack_t<ARG> argStack; - protected: - bool error = false; }; using num_interp_env_t = interp_env_t<>; diff --git a/thirdparty/harfbuzz/src/hb-cff2-interp-cs.hh b/thirdparty/harfbuzz/src/hb-cff2-interp-cs.hh index d0b9e7b086..00c25800e6 100644 --- a/thirdparty/harfbuzz/src/hb-cff2-interp-cs.hh +++ b/thirdparty/harfbuzz/src/hb-cff2-interp-cs.hh @@ -40,13 +40,15 @@ struct blend_arg_t : number_t void set_real (double v) { reset_blends (); number_t::set_real (v); } void set_blends (unsigned int numValues_, unsigned int valueIndex_, - unsigned int numBlends, hb_array_t<const blend_arg_t> blends_) + hb_array_t<const blend_arg_t> blends_) { numValues = numValues_; valueIndex = valueIndex_; - deltas.resize (numBlends); + unsigned numBlends = blends_.length; + if (unlikely (!deltas.resize (numBlends))) + return; for (unsigned int i = 0; i < numBlends; i++) - deltas[i] = blends_[i]; + deltas.arrayZ[i] = blends_.arrayZ[i]; } bool blending () const { return deltas.length > 0; } @@ -61,7 +63,6 @@ struct blend_arg_t : number_t hb_vector_t<number_t> deltas; }; -typedef interp_env_t<blend_arg_t> BlendInterpEnv; typedef biased_subrs_t<CFF2Subrs> cff2_biased_subrs_t; template <typename ELEM> @@ -154,8 +155,9 @@ struct cff2_cs_interp_env_t : cs_interp_env_t<ELEM, CFF2Subrs> { if (likely (scalars.length == deltas.length)) { - for (unsigned int i = 0; i < scalars.length; i++) - v += (double) scalars[i] * deltas[i].to_real (); + unsigned count = scalars.length; + for (unsigned i = 0; i < count; i++) + v += (double) scalars.arrayZ[i] * deltas.arrayZ[i].to_real (); } } return v; @@ -220,7 +222,7 @@ struct cff2_cs_opset_t : cs_opset_t<ELEM, OPSET, cff2_cs_interp_env_t<ELEM>, PAR const hb_array_t<const ELEM> blends, unsigned n, unsigned i) { - arg.set_blends (n, i, blends.length, blends); + arg.set_blends (n, i, blends); } template <typename T = ELEM, hb_enable_if (!hb_is_same (T, blend_arg_t))> diff --git a/thirdparty/harfbuzz/src/hb-common.cc b/thirdparty/harfbuzz/src/hb-common.cc index bbb6cd552b..e9f9cfeb5f 100644 --- a/thirdparty/harfbuzz/src/hb-common.cc +++ b/thirdparty/harfbuzz/src/hb-common.cc @@ -285,7 +285,7 @@ struct hb_language_item_t { lang = (hb_language_t) hb_malloc(len); if (likely (lang)) { - memcpy((unsigned char *) lang, s, len); + hb_memcpy((unsigned char *) lang, s, len); for (unsigned char *p = (unsigned char *) lang; *p; p++) *p = canon_map[*p]; } @@ -379,7 +379,7 @@ hb_language_from_string (const char *str, int len) /* NUL-terminate it. */ char strbuf[64]; len = hb_min (len, (int) sizeof (strbuf) - 1); - memcpy (strbuf, str, len); + hb_memcpy (strbuf, str, len); strbuf[len] = '\0'; item = lang_find_or_insert (strbuf); } @@ -976,7 +976,7 @@ hb_feature_from_string (const char *str, int len, } if (feature) - memset (feature, 0, sizeof (*feature)); + hb_memset (feature, 0, sizeof (*feature)); return false; } @@ -1025,7 +1025,7 @@ hb_feature_to_string (hb_feature_t *feature, } assert (len < ARRAY_LENGTH (s)); len = hb_min (len, size - 1); - memcpy (buf, s, len); + hb_memcpy (buf, s, len); buf[len] = '\0'; } @@ -1088,7 +1088,7 @@ hb_variation_from_string (const char *str, int len, } if (variation) - memset (variation, 0, sizeof (*variation)); + hb_memset (variation, 0, sizeof (*variation)); return false; } @@ -1136,7 +1136,7 @@ get_C_locale () /** * hb_variation_to_string: * @variation: an #hb_variation_t to convert - * @buf: (array length=size) (out): output string + * @buf: (array length=size) (out caller-allocates): output string * @size: the allocated size of @buf * * Converts an #hb_variation_t into a `NULL`-terminated string in the format @@ -1166,7 +1166,7 @@ hb_variation_to_string (hb_variation_t *variation, assert (len < ARRAY_LENGTH (s)); len = hb_min (len, size - 1); - memcpy (buf, s, len); + hb_memcpy (buf, s, len); buf[len] = '\0'; } diff --git a/thirdparty/harfbuzz/src/hb-config.hh b/thirdparty/harfbuzz/src/hb-config.hh index 5567ddaec3..98b1e9d0cf 100644 --- a/thirdparty/harfbuzz/src/hb-config.hh +++ b/thirdparty/harfbuzz/src/hb-config.hh @@ -35,8 +35,9 @@ #include "config.h" #endif -#ifndef HB_BORING_EXPANSION -#define HB_NO_BORING_EXPANSION +#ifndef HB_EXPERIMENTAL_API +#define HB_NO_BEYOND_64K +#define HB_NO_VAR_COMPOSITES #endif #ifdef HB_TINY @@ -71,6 +72,7 @@ #define HB_NO_LANGUAGE_PRIVATE_SUBTAG #define HB_NO_LAYOUT_FEATURE_PARAMS #define HB_NO_LAYOUT_COLLECT_GLYPHS +#define HB_NO_LAYOUT_RARELY_USED #define HB_NO_LAYOUT_UNUSED #define HB_NO_MATH #define HB_NO_META @@ -83,6 +85,7 @@ #define HB_NO_OT_SHAPE_FRACTIONS #define HB_NO_STYLE #define HB_NO_SUBSET_LAYOUT +#define HB_NO_VERTICAL #define HB_NO_VAR #endif @@ -103,7 +106,7 @@ #ifdef HB_NO_BORING_EXPANSION #define HB_NO_BEYOND_64K -#define HB_NO_VARIATIONS2 +#define HB_NO_AVAR2 #endif #ifdef HB_DISABLE_DEPRECATED @@ -112,6 +115,11 @@ #define HB_IF_NOT_DEPRECATED(x) x #endif +#ifdef HB_NO_SHAPER +#define HB_NO_OT_SHAPE +#define HB_NO_AAT_SHAPE +#endif + #ifdef HB_NO_AAT #define HB_NO_OT_NAME_LANGUAGE_AAT #define HB_NO_AAT_SHAPE @@ -158,6 +166,7 @@ #define HB_NO_OT_SHAPER_HEBREW_FALLBACK #define HB_NO_OT_SHAPER_THAI_FALLBACK #define HB_NO_OT_SHAPER_VOWEL_CONSTRAINTS +#define HB_NO_OT_SHAPER_MYANMAR_ZAWGYI #endif #ifdef NDEBUG diff --git a/thirdparty/harfbuzz/src/hb-coretext.cc b/thirdparty/harfbuzz/src/hb-coretext.cc index 99b33c001e..4267e0e13e 100644 --- a/thirdparty/harfbuzz/src/hb-coretext.cc +++ b/thirdparty/harfbuzz/src/hb-coretext.cc @@ -347,10 +347,13 @@ _hb_coretext_shaper_font_data_create (hb_font_t *font) hb_ot_var_axis_info_t info; unsigned int c = 1; hb_ot_var_get_axis_infos (font->face, i, &c, &info); - CFDictionarySetValue (variations, - CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &info.tag), - CFNumberCreate (kCFAllocatorDefault, kCFNumberFloatType, &font->design_coords[i]) - ); + float v = hb_clamp (font->design_coords[i], info.min_value, info.max_value); + + CFNumberRef tag_number = CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &info.tag); + CFNumberRef value_number = CFNumberCreate (kCFAllocatorDefault, kCFNumberFloatType, &v); + CFDictionarySetValue (variations, tag_number, value_number); + CFRelease (tag_number); + CFRelease (value_number); } CFDictionaryRef attributes = @@ -648,7 +651,7 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan, } else { active_feature_t *feature = active_features.lsearch (event->feature); if (feature) - active_features.remove (feature - active_features.arrayZ); + active_features.remove_ordered (feature - active_features.arrayZ); } } } diff --git a/thirdparty/harfbuzz/src/hb-cplusplus.hh b/thirdparty/harfbuzz/src/hb-cplusplus.hh index c4d9d29e23..a210ab7960 100644 --- a/thirdparty/harfbuzz/src/hb-cplusplus.hh +++ b/thirdparty/harfbuzz/src/hb-cplusplus.hh @@ -69,9 +69,9 @@ struct shared_ptr operator T * () const { return p; } T& operator * () const { return *get (); } T* operator -> () const { return get (); } - operator bool () { return p; } - bool operator == (const shared_ptr &o) { return p == o.p; } - bool operator != (const shared_ptr &o) { return p != o.p; } + operator bool () const { return p; } + bool operator == (const shared_ptr &o) const { return p == o.p; } + bool operator != (const shared_ptr &o) const { return p != o.p; } static T* get_empty() { return v::get_empty (); } T* reference() { return v::reference (p); } diff --git a/thirdparty/harfbuzz/src/hb-draw.cc b/thirdparty/harfbuzz/src/hb-draw.cc index 46797e64e6..72c203f24f 100644 --- a/thirdparty/harfbuzz/src/hb-draw.cc +++ b/thirdparty/harfbuzz/src/hb-draw.cc @@ -80,6 +80,56 @@ hb_draw_close_path_nil (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data HB_UN void *user_data HB_UNUSED) {} +static bool +_hb_draw_funcs_set_preamble (hb_draw_funcs_t *dfuncs, + bool func_is_null, + void **user_data, + hb_destroy_func_t *destroy) +{ + if (hb_object_is_immutable (dfuncs)) + { + if (*destroy) + (*destroy) (*user_data); + return false; + } + + if (func_is_null) + { + if (*destroy) + (*destroy) (*user_data); + *destroy = nullptr; + *user_data = nullptr; + } + + return true; +} + +static bool +_hb_draw_funcs_set_middle (hb_draw_funcs_t *dfuncs, + void *user_data, + hb_destroy_func_t destroy) +{ + if (user_data && !dfuncs->user_data) + { + dfuncs->user_data = (decltype (dfuncs->user_data)) hb_calloc (1, sizeof (*dfuncs->user_data)); + if (unlikely (!dfuncs->user_data)) + goto fail; + } + if (destroy && !dfuncs->destroy) + { + dfuncs->destroy = (decltype (dfuncs->destroy)) hb_calloc (1, sizeof (*dfuncs->destroy)); + if (unlikely (!dfuncs->destroy)) + goto fail; + } + + return true; + +fail: + if (destroy) + (destroy) (user_data); + return false; +} + #define HB_DRAW_FUNC_IMPLEMENT(name) \ \ void \ @@ -88,43 +138,24 @@ hb_draw_funcs_set_##name##_func (hb_draw_funcs_t *dfuncs, \ void *user_data, \ hb_destroy_func_t destroy) \ { \ - if (hb_object_is_immutable (dfuncs)) \ - return; \ + if (!_hb_draw_funcs_set_preamble (dfuncs, !func, &user_data, &destroy))\ + return; \ \ if (dfuncs->destroy && dfuncs->destroy->name) \ dfuncs->destroy->name (!dfuncs->user_data ? nullptr : dfuncs->user_data->name); \ \ - if (user_data && !dfuncs->user_data) \ - { \ - dfuncs->user_data = (decltype (dfuncs->user_data)) hb_calloc (1, sizeof (*dfuncs->user_data)); \ - if (unlikely (!dfuncs->user_data)) \ - goto fail; \ - } \ - if (destroy && !dfuncs->destroy) \ - { \ - dfuncs->destroy = (decltype (dfuncs->destroy)) hb_calloc (1, sizeof (*dfuncs->destroy)); \ - if (unlikely (!dfuncs->destroy)) \ - goto fail; \ - } \ + if (!_hb_draw_funcs_set_middle (dfuncs, user_data, destroy)) \ + return; \ \ - if (func) { \ + if (func) \ dfuncs->func.name = func; \ - if (dfuncs->user_data) \ - dfuncs->user_data->name = user_data; \ - if (dfuncs->destroy) \ - dfuncs->destroy->name = destroy; \ - } else { \ + else \ dfuncs->func.name = hb_draw_##name##_nil; \ - if (dfuncs->user_data) \ - dfuncs->user_data->name = nullptr; \ - if (dfuncs->destroy) \ - dfuncs->destroy->name = nullptr; \ - } \ - return; \ - \ -fail: \ - if (destroy) \ - destroy (user_data); \ + \ + if (dfuncs->user_data) \ + dfuncs->user_data->name = user_data; \ + if (dfuncs->destroy) \ + dfuncs->destroy->name = destroy; \ } HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS diff --git a/thirdparty/harfbuzz/src/hb-face.cc b/thirdparty/harfbuzz/src/hb-face.cc index 2160d6a010..8b4b635c7a 100644 --- a/thirdparty/harfbuzz/src/hb-face.cc +++ b/thirdparty/harfbuzz/src/hb-face.cc @@ -288,6 +288,7 @@ hb_face_destroy (hb_face_t *face) { if (!hb_object_destroy (face)) return; +#ifndef HB_NO_SHAPER for (hb_face_t::plan_node_t *node = face->shape_plans; node; ) { hb_face_t::plan_node_t *next = node->next; @@ -295,6 +296,7 @@ hb_face_destroy (hb_face_t *face) hb_free (node); node = next; } +#endif face->data.fini (); face->table.fini (); @@ -633,20 +635,29 @@ hb_face_collect_variation_unicodes (hb_face_t *face, * face-builder: A face that has add_table(). */ +struct face_table_info_t +{ + hb_blob_t* data; + signed order; +}; + struct hb_face_builder_data_t { - hb_hashmap_t<hb_tag_t, hb_blob_t *> tables; + hb_hashmap_t<hb_tag_t, face_table_info_t> tables; }; static int compare_entries (const void* pa, const void* pb) { - const auto& a = * (const hb_pair_t<hb_tag_t, hb_blob_t*> *) pa; - const auto& b = * (const hb_pair_t<hb_tag_t, hb_blob_t*> *) pb; + const auto& a = * (const hb_pair_t<hb_tag_t, face_table_info_t> *) pa; + const auto& b = * (const hb_pair_t<hb_tag_t, face_table_info_t> *) pb; /* Order by blob size first (smallest to largest) and then table tag */ - if (a.second->length != b.second->length) - return a.second->length < b.second->length ? -1 : +1; + if (a.second.order != b.second.order) + return a.second.order < b.second.order ? -1 : +1; + + if (a.second.data->length != b.second.data->length) + return a.second.data->length < b.second.data->length ? -1 : +1; return a.first < b.first ? -1 : a.first == b.first ? 0 : +1; } @@ -668,8 +679,8 @@ _hb_face_builder_data_destroy (void *user_data) { hb_face_builder_data_t *data = (hb_face_builder_data_t *) user_data; - for (hb_blob_t* b : data->tables.values()) - hb_blob_destroy (b); + for (auto info : data->tables.values()) + hb_blob_destroy (info.data); data->tables.fini (); @@ -683,8 +694,8 @@ _hb_face_builder_data_reference_blob (hb_face_builder_data_t *data) unsigned int table_count = data->tables.get_population (); unsigned int face_length = table_count * 16 + 12; - for (hb_blob_t* b : data->tables.values()) - face_length += hb_ceil_to_4 (hb_blob_get_length (b)); + for (auto info : data->tables.values()) + face_length += hb_ceil_to_4 (hb_blob_get_length (info.data)); char *buf = (char *) hb_malloc (face_length); if (unlikely (!buf)) @@ -699,7 +710,7 @@ _hb_face_builder_data_reference_blob (hb_face_builder_data_t *data) hb_tag_t sfnt_tag = is_cff ? OT::OpenTypeFontFile::CFFTag : OT::OpenTypeFontFile::TrueTypeTag; // Sort the tags so that produced face is deterministic. - hb_vector_t<hb_pair_t <hb_tag_t, hb_blob_t*>> sorted_entries; + hb_vector_t<hb_pair_t <hb_tag_t, face_table_info_t>> sorted_entries; data->tables.iter () | hb_sink (sorted_entries); if (unlikely (sorted_entries.in_error ())) { @@ -708,7 +719,13 @@ _hb_face_builder_data_reference_blob (hb_face_builder_data_t *data) } sorted_entries.qsort (compare_entries); - bool ret = f->serialize_single (&c, sfnt_tag, + sorted_entries.iter()); + + bool ret = f->serialize_single (&c, + sfnt_tag, + + sorted_entries.iter() + | hb_map ([&] (hb_pair_t<hb_tag_t, face_table_info_t> _) { + return hb_pair_t<hb_tag_t, hb_blob_t*> (_.first, _.second.data); + })); c.end_serialize (); @@ -729,7 +746,7 @@ _hb_face_builder_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void if (!tag) return _hb_face_builder_data_reference_blob (data); - return hb_blob_reference (data->tables[tag]); + return hb_blob_reference (data->tables[tag].data); } @@ -769,16 +786,16 @@ hb_face_builder_create () hb_bool_t hb_face_builder_add_table (hb_face_t *face, hb_tag_t tag, hb_blob_t *blob) { - if (tag == HB_MAP_VALUE_INVALID) + if (unlikely (face->destroy != (hb_destroy_func_t) _hb_face_builder_data_destroy)) return false; - if (unlikely (face->destroy != (hb_destroy_func_t) _hb_face_builder_data_destroy)) + if (tag == HB_MAP_VALUE_INVALID) return false; hb_face_builder_data_t *data = (hb_face_builder_data_t *) face->user_data; - hb_blob_t* previous = data->tables.get (tag); - if (!data->tables.set (tag, hb_blob_reference (blob))) + hb_blob_t* previous = data->tables.get (tag).data; + if (!data->tables.set (tag, face_table_info_t {hb_blob_reference (blob), -1})) { hb_blob_destroy (blob); return false; @@ -787,3 +804,39 @@ hb_face_builder_add_table (hb_face_t *face, hb_tag_t tag, hb_blob_t *blob) hb_blob_destroy (previous); return true; } + +/** + * hb_face_builder_sort_tables: + * @face: A face object created with hb_face_builder_create() + * @tags: (array zero-terminated=1): ordered list of table tags terminated by + * %HB_TAG_NONE + * + * Set the ordering of tables for serialization. Any tables not + * specified in the tags list will be ordered after the tables in + * tags, ordered by the default sort ordering. + * + * Since: 5.3.0 + **/ +void +hb_face_builder_sort_tables (hb_face_t *face, + const hb_tag_t *tags) +{ + if (unlikely (face->destroy != (hb_destroy_func_t) _hb_face_builder_data_destroy)) + return; + + hb_face_builder_data_t *data = (hb_face_builder_data_t *) face->user_data; + + // Sort all unspecified tables after any specified tables. + for (auto& info : data->tables.values_ref()) + info.order = (unsigned) -1; + + signed order = 0; + for (const hb_tag_t* tag = tags; + *tag; + tag++) + { + face_table_info_t* info; + if (!data->tables.has (*tag, &info)) continue; + info->order = order++; + } +} diff --git a/thirdparty/harfbuzz/src/hb-face.h b/thirdparty/harfbuzz/src/hb-face.h index 6ef2f8b886..38e7104af6 100644 --- a/thirdparty/harfbuzz/src/hb-face.h +++ b/thirdparty/harfbuzz/src/hb-face.h @@ -171,6 +171,10 @@ hb_face_builder_add_table (hb_face_t *face, hb_tag_t tag, hb_blob_t *blob); +HB_EXTERN void +hb_face_builder_sort_tables (hb_face_t *face, + const hb_tag_t *tags); + HB_END_DECLS diff --git a/thirdparty/harfbuzz/src/hb-face.hh b/thirdparty/harfbuzz/src/hb-face.hh index 12e10d01e0..1bf0606e52 100644 --- a/thirdparty/harfbuzz/src/hb-face.hh +++ b/thirdparty/harfbuzz/src/hb-face.hh @@ -65,7 +65,9 @@ struct hb_face_t hb_shape_plan_t *shape_plan; plan_node_t *next; }; +#ifndef HB_NO_SHAPER hb_atomic_ptr_t<plan_node_t> shape_plans; +#endif hb_blob_t *reference_table (hb_tag_t tag) const { diff --git a/thirdparty/harfbuzz/src/hb-fallback-shape.cc b/thirdparty/harfbuzz/src/hb-fallback-shape.cc index f8524ecc8e..c54ad8764b 100644 --- a/thirdparty/harfbuzz/src/hb-fallback-shape.cc +++ b/thirdparty/harfbuzz/src/hb-fallback-shape.cc @@ -75,16 +75,6 @@ _hb_fallback_shape (hb_shape_plan_t *shape_plan HB_UNUSED, const hb_feature_t *features HB_UNUSED, unsigned int num_features HB_UNUSED) { - /* TODO - * - * - Apply fallback kern. - * - Handle Variation Selectors? - * - Apply normalization? - * - * This will make the fallback shaper into a dumb "TrueType" - * shaper which many people unfortunately still request. - */ - hb_codepoint_t space; bool has_space = (bool) font->get_nominal_glyph (' ', &space); diff --git a/thirdparty/harfbuzz/src/hb-font.cc b/thirdparty/harfbuzz/src/hb-font.cc index 856bbdda32..0ce3e2608a 100644 --- a/thirdparty/harfbuzz/src/hb-font.cc +++ b/thirdparty/harfbuzz/src/hb-font.cc @@ -71,7 +71,7 @@ hb_font_get_font_h_extents_nil (hb_font_t *font HB_UNUSED, hb_font_extents_t *extents, void *user_data HB_UNUSED) { - memset (extents, 0, sizeof (*extents)); + hb_memset (extents, 0, sizeof (*extents)); return false; } @@ -96,7 +96,7 @@ hb_font_get_font_v_extents_nil (hb_font_t *font HB_UNUSED, hb_font_extents_t *extents, void *user_data HB_UNUSED) { - memset (extents, 0, sizeof (*extents)); + hb_memset (extents, 0, sizeof (*extents)); return false; } @@ -409,7 +409,7 @@ hb_font_get_glyph_extents_nil (hb_font_t *font HB_UNUSED, hb_glyph_extents_t *extents, void *user_data HB_UNUSED) { - memset (extents, 0, sizeof (*extents)); + hb_memset (extents, 0, sizeof (*extents)); return false; } @@ -518,6 +518,7 @@ typedef struct hb_font_get_glyph_shape_default_adaptor_t { void *draw_data; float x_scale; float y_scale; + float slant; } hb_font_get_glyph_shape_default_adaptor_t; static void @@ -530,9 +531,10 @@ hb_draw_move_to_default (hb_draw_funcs_t *dfuncs HB_UNUSED, hb_font_get_glyph_shape_default_adaptor_t *adaptor = (hb_font_get_glyph_shape_default_adaptor_t *) draw_data; float x_scale = adaptor->x_scale; float y_scale = adaptor->y_scale; + float slant = adaptor->slant; adaptor->draw_funcs->emit_move_to (adaptor->draw_data, *st, - x_scale * to_x, y_scale * to_y); + x_scale * to_x + slant * to_y, y_scale * to_y); } static void @@ -544,12 +546,13 @@ hb_draw_line_to_default (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data, hb_font_get_glyph_shape_default_adaptor_t *adaptor = (hb_font_get_glyph_shape_default_adaptor_t *) draw_data; float x_scale = adaptor->x_scale; float y_scale = adaptor->y_scale; + float slant = adaptor->slant; - st->current_x *= x_scale; - st->current_y *= y_scale; + st->current_x = st->current_x * x_scale + st->current_y * slant; + st->current_y = st->current_y * y_scale; adaptor->draw_funcs->emit_line_to (adaptor->draw_data, *st, - x_scale * to_x, y_scale * to_y); + x_scale * to_x + slant * to_y, y_scale * to_y); } static void @@ -562,13 +565,14 @@ hb_draw_quadratic_to_default (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data hb_font_get_glyph_shape_default_adaptor_t *adaptor = (hb_font_get_glyph_shape_default_adaptor_t *) draw_data; float x_scale = adaptor->x_scale; float y_scale = adaptor->y_scale; + float slant = adaptor->slant; - st->current_x *= x_scale; - st->current_y *= y_scale; + st->current_x = st->current_x * x_scale + st->current_y * slant; + st->current_y = st->current_y * y_scale; adaptor->draw_funcs->emit_quadratic_to (adaptor->draw_data, *st, - x_scale * control_x, y_scale * control_y, - x_scale * to_x, y_scale * to_y); + x_scale * control_x + slant * control_y, y_scale * control_y, + x_scale * to_x + slant * to_y, y_scale * to_y); } static void @@ -582,14 +586,15 @@ hb_draw_cubic_to_default (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data, hb_font_get_glyph_shape_default_adaptor_t *adaptor = (hb_font_get_glyph_shape_default_adaptor_t *) draw_data; float x_scale = adaptor->x_scale; float y_scale = adaptor->y_scale; + float slant = adaptor->slant; - st->current_x *= x_scale; - st->current_y *= y_scale; + st->current_x = st->current_x * x_scale + st->current_y * slant; + st->current_y = st->current_y * y_scale; adaptor->draw_funcs->emit_cubic_to (adaptor->draw_data, *st, - x_scale * control1_x, y_scale * control1_y, - x_scale * control2_x, y_scale * control2_y, - x_scale * to_x, y_scale * to_y); + x_scale * control1_x + slant * control1_y, y_scale * control1_y, + x_scale * control2_x + slant * control2_y, y_scale * control2_y, + x_scale * to_x + slant * to_y, y_scale * to_y); } static void @@ -623,8 +628,10 @@ hb_font_get_glyph_shape_default (hb_font_t *font, hb_font_get_glyph_shape_default_adaptor_t adaptor = { draw_funcs, draw_data, - (float) font->x_scale / (float) font->parent->x_scale, - (float) font->y_scale / (float) font->parent->y_scale + font->parent->x_scale ? (float) font->x_scale / (float) font->parent->x_scale : 0.f, + font->parent->y_scale ? (float) font->y_scale / (float) font->parent->y_scale : 0.f, + font->parent->y_scale ? (font->slant - font->parent->slant) * + (float) font->x_scale / (float) font->parent->y_scale : 0.f }; font->parent->get_glyph_shape (glyph, @@ -822,6 +829,56 @@ hb_font_funcs_is_immutable (hb_font_funcs_t *ffuncs) } +static bool +_hb_font_funcs_set_preamble (hb_font_funcs_t *ffuncs, + bool func_is_null, + void **user_data, + hb_destroy_func_t *destroy) +{ + if (hb_object_is_immutable (ffuncs)) + { + if (*destroy) + (*destroy) (*user_data); + return false; + } + + if (func_is_null) + { + if (*destroy) + (*destroy) (*user_data); + *destroy = nullptr; + *user_data = nullptr; + } + + return true; +} + +static bool +_hb_font_funcs_set_middle (hb_font_funcs_t *ffuncs, + void *user_data, + hb_destroy_func_t destroy) +{ + if (user_data && !ffuncs->user_data) + { + ffuncs->user_data = (decltype (ffuncs->user_data)) hb_calloc (1, sizeof (*ffuncs->user_data)); + if (unlikely (!ffuncs->user_data)) + goto fail; + } + if (destroy && !ffuncs->destroy) + { + ffuncs->destroy = (decltype (ffuncs->destroy)) hb_calloc (1, sizeof (*ffuncs->destroy)); + if (unlikely (!ffuncs->destroy)) + goto fail; + } + + return true; + +fail: + if (destroy) + (destroy) (user_data); + return false; +} + #define HB_FONT_FUNC_IMPLEMENT(name) \ \ void \ @@ -830,51 +887,24 @@ hb_font_funcs_set_##name##_func (hb_font_funcs_t *ffuncs, \ void *user_data, \ hb_destroy_func_t destroy) \ { \ - if (hb_object_is_immutable (ffuncs)) \ - goto fail; \ - \ - if (!func) \ - { \ - if (destroy) \ - destroy (user_data); \ - destroy = nullptr; \ - user_data = nullptr; \ - } \ + if (!_hb_font_funcs_set_preamble (ffuncs, !func, &user_data, &destroy))\ + return; \ \ if (ffuncs->destroy && ffuncs->destroy->name) \ ffuncs->destroy->name (!ffuncs->user_data ? nullptr : ffuncs->user_data->name); \ \ - if (user_data && !ffuncs->user_data) \ - { \ - ffuncs->user_data = (decltype (ffuncs->user_data)) hb_calloc (1, sizeof (*ffuncs->user_data)); \ - if (unlikely (!ffuncs->user_data)) \ - goto fail; \ - } \ - if (destroy && !ffuncs->destroy) \ - { \ - ffuncs->destroy = (decltype (ffuncs->destroy)) hb_calloc (1, sizeof (*ffuncs->destroy)); \ - if (unlikely (!ffuncs->destroy)) \ - goto fail; \ - } \ + if (!_hb_font_funcs_set_middle (ffuncs, user_data, destroy)) \ + return; \ \ - if (func) { \ + if (func) \ ffuncs->get.f.name = func; \ - if (ffuncs->user_data) \ - ffuncs->user_data->name = user_data; \ - if (ffuncs->destroy) \ - ffuncs->destroy->name = destroy; \ - } else { \ + else \ ffuncs->get.f.name = hb_font_get_##name##_default; \ - if (ffuncs->user_data) \ - ffuncs->user_data->name = nullptr; \ - if (ffuncs->destroy) \ - ffuncs->destroy->name = nullptr; \ - } \ - return; \ - \ -fail: \ - if (destroy) \ - destroy (user_data); \ + \ + if (ffuncs->user_data) \ + ffuncs->user_data->name = user_data; \ + if (ffuncs->destroy) \ + ffuncs->destroy->name = destroy; \ } HB_FONT_FUNCS_IMPLEMENT_CALLBACKS @@ -1323,7 +1353,7 @@ hb_font_get_glyph_from_name (hb_font_t *font, * @draw_data: User data to pass to draw callbacks * * Fetches the glyph shape that corresponds to a glyph in the specified @font. - * The shape is returned by way of calls to the callsbacks of the @dfuncs + * The shape is returned by way of calls to the callbacks of the @dfuncs * objects, with @draw_data passed to them. * * Since: 4.0.0 @@ -1780,8 +1810,8 @@ hb_font_create_sub_font (hb_font_t *parent) float *design_coords = (float *) hb_calloc (num_coords, sizeof (parent->design_coords[0])); if (likely (coords && design_coords)) { - memcpy (coords, parent->coords, num_coords * sizeof (parent->coords[0])); - memcpy (design_coords, parent->design_coords, num_coords * sizeof (parent->design_coords[0])); + hb_memcpy (coords, parent->coords, num_coords * sizeof (parent->coords[0])); + hb_memcpy (design_coords, parent->design_coords, num_coords * sizeof (parent->design_coords[0])); _hb_font_adopt_var_coords (font, coords, design_coords, num_coords); } else @@ -2443,7 +2473,7 @@ hb_font_set_var_coords_design (hb_font_t *font, } if (coords_length) - memcpy (design_coords, coords, coords_length * sizeof (font->design_coords[0])); + hb_memcpy (design_coords, coords, coords_length * sizeof (font->design_coords[0])); hb_ot_var_normalize_coords (font->face, coords_length, coords, normalized); _hb_font_adopt_var_coords (font, normalized, design_coords, coords_length); @@ -2519,8 +2549,8 @@ hb_font_set_var_coords_normalized (hb_font_t *font, if (coords_length) { - memcpy (copy, coords, coords_length * sizeof (coords[0])); - memcpy (unmapped, coords, coords_length * sizeof (coords[0])); + hb_memcpy (copy, coords, coords_length * sizeof (coords[0])); + hb_memcpy (unmapped, coords, coords_length * sizeof (coords[0])); } /* Best effort design coords simulation */ diff --git a/thirdparty/harfbuzz/src/hb-font.hh b/thirdparty/harfbuzz/src/hb-font.hh index bb402e23eb..6942d99c70 100644 --- a/thirdparty/harfbuzz/src/hb-font.hh +++ b/thirdparty/harfbuzz/src/hb-font.hh @@ -206,14 +206,14 @@ struct hb_font_t hb_bool_t get_font_h_extents (hb_font_extents_t *extents) { - memset (extents, 0, sizeof (*extents)); + hb_memset (extents, 0, sizeof (*extents)); return klass->get.f.font_h_extents (this, user_data, extents, !klass->user_data ? nullptr : klass->user_data->font_h_extents); } hb_bool_t get_font_v_extents (hb_font_extents_t *extents) { - memset (extents, 0, sizeof (*extents)); + hb_memset (extents, 0, sizeof (*extents)); return klass->get.f.font_v_extents (this, user_data, extents, !klass->user_data ? nullptr : klass->user_data->font_v_extents); @@ -342,7 +342,7 @@ struct hb_font_t hb_bool_t get_glyph_extents (hb_codepoint_t glyph, hb_glyph_extents_t *extents) { - memset (extents, 0, sizeof (*extents)); + hb_memset (extents, 0, sizeof (*extents)); return klass->get.f.glyph_extents (this, user_data, glyph, extents, diff --git a/thirdparty/harfbuzz/src/hb-ft.cc b/thirdparty/harfbuzz/src/hb-ft.cc index bcc1dd080f..3892dedc13 100644 --- a/thirdparty/harfbuzz/src/hb-ft.cc +++ b/thirdparty/harfbuzz/src/hb-ft.cc @@ -89,7 +89,7 @@ struct hb_ft_font_t bool unref; /* Whether to destroy ft_face when done. */ bool transform; /* Whether to apply FT_Face's transform. */ - mutable hb_mutex_t lock; + mutable hb_mutex_t lock; /* Protects members below. */ FT_Face ft_face; mutable unsigned cached_serial; mutable hb_ft_advance_cache_t advance_cache; @@ -732,16 +732,18 @@ hb_ft_get_font_h_extents (hb_font_t *font HB_UNUSED, static int _hb_ft_move_to (const FT_Vector *to, - hb_draw_session_t *drawing) + void *arg) { + hb_draw_session_t *drawing = (hb_draw_session_t *) arg; drawing->move_to (to->x, to->y); return FT_Err_Ok; } static int _hb_ft_line_to (const FT_Vector *to, - hb_draw_session_t *drawing) + void *arg) { + hb_draw_session_t *drawing = (hb_draw_session_t *) arg; drawing->line_to (to->x, to->y); return FT_Err_Ok; } @@ -749,8 +751,9 @@ _hb_ft_line_to (const FT_Vector *to, static int _hb_ft_conic_to (const FT_Vector *control, const FT_Vector *to, - hb_draw_session_t *drawing) + void *arg) { + hb_draw_session_t *drawing = (hb_draw_session_t *) arg; drawing->quadratic_to (control->x, control->y, to->x, to->y); return FT_Err_Ok; @@ -760,8 +763,9 @@ static int _hb_ft_cubic_to (const FT_Vector *control1, const FT_Vector *control2, const FT_Vector *to, - hb_draw_session_t *drawing) + void *arg) { + hb_draw_session_t *drawing = (hb_draw_session_t *) arg; drawing->cubic_to (control1->x, control1->y, control2->x, control2->y, to->x, to->y); @@ -787,10 +791,10 @@ hb_ft_get_glyph_shape (hb_font_t *font HB_UNUSED, return; const FT_Outline_Funcs outline_funcs = { - (FT_Outline_MoveToFunc) _hb_ft_move_to, - (FT_Outline_LineToFunc) _hb_ft_line_to, - (FT_Outline_ConicToFunc) _hb_ft_conic_to, - (FT_Outline_CubicToFunc) _hb_ft_cubic_to, + _hb_ft_move_to, + _hb_ft_line_to, + _hb_ft_conic_to, + _hb_ft_cubic_to, 0, /* shift */ 0, /* delta */ }; @@ -975,8 +979,9 @@ hb_ft_face_create_referenced (FT_Face ft_face) } static void -hb_ft_face_finalize (FT_Face ft_face) +hb_ft_face_finalize (void *arg) { + FT_Face ft_face = (FT_Face) arg; hb_face_destroy ((hb_face_t *) ft_face->generic.data); } @@ -1008,7 +1013,7 @@ hb_ft_face_create_cached (FT_Face ft_face) ft_face->generic.finalizer (ft_face); ft_face->generic.data = hb_ft_face_create (ft_face, nullptr); - ft_face->generic.finalizer = (FT_Generic_Finalizer) hb_ft_face_finalize; + ft_face->generic.finalizer = hb_ft_face_finalize; } return hb_face_reference ((hb_face_t *) ft_face->generic.data); @@ -1217,8 +1222,9 @@ get_ft_library () } static void -_release_blob (FT_Face ft_face) +_release_blob (void *arg) { + FT_Face ft_face = (FT_Face) arg; hb_blob_destroy ((hb_blob_t *) ft_face->generic.data); } @@ -1271,7 +1277,7 @@ hb_ft_font_set_funcs (hb_font_t *font) ft_face->generic.data = blob; - ft_face->generic.finalizer = (FT_Generic_Finalizer) _release_blob; + ft_face->generic.finalizer = _release_blob; _hb_ft_font_set_funcs (font, ft_face, true); hb_ft_font_set_load_flags (font, FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING); diff --git a/thirdparty/harfbuzz/src/hb-glib.cc b/thirdparty/harfbuzz/src/hb-glib.cc index 8ddc7ebad8..1da81696e7 100644 --- a/thirdparty/harfbuzz/src/hb-glib.cc +++ b/thirdparty/harfbuzz/src/hb-glib.cc @@ -129,32 +129,9 @@ hb_glib_unicode_compose (hb_unicode_funcs_t *ufuncs HB_UNUSED, { #if GLIB_CHECK_VERSION(2,29,12) return g_unichar_compose (a, b, ab); +#else + return false; #endif - - /* We don't ifdef-out the fallback code such that compiler always - * sees it and makes sure it's compilable. */ - - gchar utf8[12]; - gchar *normalized; - int len; - hb_bool_t ret; - - len = g_unichar_to_utf8 (a, utf8); - len += g_unichar_to_utf8 (b, utf8 + len); - normalized = g_utf8_normalize (utf8, len, G_NORMALIZE_NFC); - len = g_utf8_strlen (normalized, -1); - if (unlikely (!len)) - return false; - - if (len == 1) { - *ab = g_utf8_get_char (normalized); - ret = true; - } else { - ret = false; - } - - g_free (normalized); - return ret; } static hb_bool_t @@ -166,55 +143,9 @@ hb_glib_unicode_decompose (hb_unicode_funcs_t *ufuncs HB_UNUSED, { #if GLIB_CHECK_VERSION(2,29,12) return g_unichar_decompose (ab, a, b); +#else + return false; #endif - - /* We don't ifdef-out the fallback code such that compiler always - * sees it and makes sure it's compilable. */ - - gchar utf8[6]; - gchar *normalized; - int len; - hb_bool_t ret; - - len = g_unichar_to_utf8 (ab, utf8); - normalized = g_utf8_normalize (utf8, len, G_NORMALIZE_NFD); - len = g_utf8_strlen (normalized, -1); - if (unlikely (!len)) - return false; - - if (len == 1) { - *a = g_utf8_get_char (normalized); - *b = 0; - ret = *a != ab; - } else if (len == 2) { - *a = g_utf8_get_char (normalized); - *b = g_utf8_get_char (g_utf8_next_char (normalized)); - /* Here's the ugly part: if ab decomposes to a single character and - * that character decomposes again, we have to detect that and undo - * the second part :-(. */ - gchar *recomposed = g_utf8_normalize (normalized, -1, G_NORMALIZE_NFC); - hb_codepoint_t c = g_utf8_get_char (recomposed); - if (c != ab && c != *a) { - *a = c; - *b = 0; - } - g_free (recomposed); - ret = true; - } else { - /* If decomposed to more than two characters, take the last one, - * and recompose the rest to get the first component. */ - gchar *end = g_utf8_offset_to_pointer (normalized, len - 1); - gchar *recomposed; - *b = g_utf8_get_char (end); - recomposed = g_utf8_normalize (normalized, end - normalized, G_NORMALIZE_NFC); - /* We expect that recomposed has exactly one character now. */ - *a = g_utf8_get_char (recomposed); - g_free (recomposed); - ret = true; - } - - g_free (normalized); - return ret; } diff --git a/thirdparty/harfbuzz/src/hb-graphite2.cc b/thirdparty/harfbuzz/src/hb-graphite2.cc index 4d0e687c75..9e068f8d84 100644 --- a/thirdparty/harfbuzz/src/hb-graphite2.cc +++ b/thirdparty/harfbuzz/src/hb-graphite2.cc @@ -318,7 +318,7 @@ _hb_graphite2_shape (hb_shape_plan_t *shape_plan HB_UNUSED, #undef ALLOCATE_ARRAY - memset (clusters, 0, sizeof (clusters[0]) * buffer->len); + hb_memset (clusters, 0, sizeof (clusters[0]) * buffer->len); hb_codepoint_t *pg = gids; clusters[0].cluster = buffer->info[0].cluster; diff --git a/thirdparty/harfbuzz/src/hb-iter.hh b/thirdparty/harfbuzz/src/hb-iter.hh index 1a3ab43de0..b57f37b132 100644 --- a/thirdparty/harfbuzz/src/hb-iter.hh +++ b/thirdparty/harfbuzz/src/hb-iter.hh @@ -73,8 +73,10 @@ struct hb_iter_t /* Operators. */ iter_t iter () const { return *thiz(); } iter_t operator + () const { return *thiz(); } - iter_t begin () const { return *thiz(); } - iter_t end () const { return thiz()->__end__ (); } + iter_t _begin () const { return *thiz(); } + iter_t begin () const { return _begin (); } + iter_t _end () const { return thiz()->__end__ (); } + iter_t end () const { return _end (); } explicit operator bool () const { return thiz()->__more__ (); } unsigned len () const { return thiz()->__len__ (); } /* The following can only be enabled if item_t is reference type. Otherwise @@ -118,7 +120,9 @@ struct hb_iter_t #define HB_ITER_USING(Name) \ using item_t = typename Name::item_t; \ + using Name::_begin; \ using Name::begin; \ + using Name::_end; \ using Name::end; \ using Name::get_item_size; \ using Name::is_iterator; \ @@ -377,7 +381,7 @@ struct hb_map_iter_t : void __forward__ (unsigned n) { it += n; } void __prev__ () { --it; } void __rewind__ (unsigned n) { it -= n; } - hb_map_iter_t __end__ () const { return hb_map_iter_t (it.end (), f); } + hb_map_iter_t __end__ () const { return hb_map_iter_t (it._end (), f); } bool operator != (const hb_map_iter_t& o) const { return it != o.it; } @@ -440,7 +444,7 @@ struct hb_filter_iter_t : bool __more__ () const { return bool (it); } void __next__ () { do ++it; while (it && !hb_has (p.get (), hb_get (f.get (), *it))); } void __prev__ () { do --it; while (it && !hb_has (p.get (), hb_get (f.get (), *it))); } - hb_filter_iter_t __end__ () const { return hb_filter_iter_t (it.end (), p, f); } + hb_filter_iter_t __end__ () const { return hb_filter_iter_t (it._end (), p, f); } bool operator != (const hb_filter_iter_t& o) const { return it != o.it; } @@ -553,7 +557,7 @@ struct hb_zip_iter_t : void __forward__ (unsigned n) { a += n; b += n; } void __prev__ () { --a; --b; } void __rewind__ (unsigned n) { a -= n; b -= n; } - hb_zip_iter_t __end__ () const { return hb_zip_iter_t (a.end (), b.end ()); } + hb_zip_iter_t __end__ () const { return hb_zip_iter_t (a._end (), b._end ()); } /* Note, we should stop if ANY of the iters reaches end. As such two compare * unequal if both items are unequal, NOT if either is unequal. */ bool operator != (const hb_zip_iter_t& o) const @@ -637,7 +641,7 @@ struct hb_concat_iter_t : } } - hb_concat_iter_t __end__ () const { return hb_concat_iter_t (a.end (), b.end ()); } + hb_concat_iter_t __end__ () const { return hb_concat_iter_t (a._end (), b._end ()); } bool operator != (const hb_concat_iter_t& o) const { return a != o.a diff --git a/thirdparty/harfbuzz/src/hb-machinery.hh b/thirdparty/harfbuzz/src/hb-machinery.hh index 2571f22e15..b555739cfb 100644 --- a/thirdparty/harfbuzz/src/hb-machinery.hh +++ b/thirdparty/harfbuzz/src/hb-machinery.hh @@ -136,6 +136,13 @@ static inline Type& StructAfter(TObject &X) /* * Lazy loaders. + * + * The lazy-loaders are thread-safe pointer-like objects that create their + * instead on-demand. They also support access to a "data" object that is + * necessary for creating their instance. The data object, if specified, + * is accessed via pointer math, located at a location before the position + * of the loader itself. This avoids having to store a pointer to data + * for every lazy-loader. Multiple lazy-loaders can access the same data. */ template <typename Data, unsigned int WheresData> @@ -228,7 +235,8 @@ struct hb_lazy_loader_t : hb_data_wrapper_t<Data, WheresData> bool cmpexch (Stored *current, Stored *value) const { - /* This *must* be called when there are no other threads accessing. */ + /* This function can only be safely called directly if no + * other thread is accessing. */ return this->instance.cmpexch (current, value); } @@ -261,7 +269,7 @@ struct hb_lazy_loader_t : hb_data_wrapper_t<Data, WheresData> hb_free (p); } -// private: + private: /* Must only have one pointer. */ hb_atomic_ptr_t<Stored *> instance; }; @@ -283,7 +291,7 @@ struct hb_table_lazy_loader_t : hb_lazy_loader_t<T, { auto c = hb_sanitize_context_t (); if (core) - c.set_num_glyphs (0); // So we don't recurse ad infinitum... + c.set_num_glyphs (0); // So we don't recurse ad infinitum, or doesn't need num_glyphs return c.reference_table<T> (face); } static void destroy (hb_blob_t *p) { hb_blob_destroy (p); } diff --git a/thirdparty/harfbuzz/src/hb-map.hh b/thirdparty/harfbuzz/src/hb-map.hh index 8302e3f8c7..bfb1b3f768 100644 --- a/thirdparty/harfbuzz/src/hb-map.hh +++ b/thirdparty/harfbuzz/src/hb-map.hh @@ -43,9 +43,9 @@ struct hb_hashmap_t hb_hashmap_t () { init (); } ~hb_hashmap_t () { fini (); } - hb_hashmap_t (const hb_hashmap_t& o) : hb_hashmap_t () { resize (population); hb_copy (o, *this); } + hb_hashmap_t (const hb_hashmap_t& o) : hb_hashmap_t () { resize (o.population); hb_copy (o, *this); } hb_hashmap_t (hb_hashmap_t&& o) : hb_hashmap_t () { hb_swap (*this, o); } - hb_hashmap_t& operator= (const hb_hashmap_t& o) { resize (population); hb_copy (o, *this); return *this; } + hb_hashmap_t& operator= (const hb_hashmap_t& o) { reset (); resize (o.population); hb_copy (o, *this); return *this; } hb_hashmap_t& operator= (hb_hashmap_t&& o) { hb_swap (*this, o); return *this; } hb_hashmap_t (std::initializer_list<hb_pair_t<K, V>> lst) : hb_hashmap_t () @@ -71,6 +71,11 @@ struct hb_hashmap_t uint32_t is_tombstone_ : 1; V value; + item_t () : key (), + hash (0), + is_used_ (false), is_tombstone_ (false), + value () {} + bool is_used () const { return is_used_; } void set_used (bool is_used) { is_used_ = is_used; } bool is_tombstone () const { return is_tombstone_; } @@ -88,17 +93,8 @@ struct hb_hashmap_t return minus_1; }; - void clear () - { - new (std::addressof (key)) K (); - new (std::addressof (value)) V (); - hash = 0; - is_used_ = false; - is_tombstone_ = false; - } - - bool operator == (const K &o) { return hb_deref (key) == hb_deref (o); } - bool operator == (const item_t &o) { return *this == o.key; } + bool operator == (const K &o) const { return hb_deref (key) == hb_deref (o); } + bool operator == (const item_t &o) const { return *this == o.key; } hb_pair_t<K, V> get_pair() const { return hb_pair_t<K, V> (key, value); } hb_pair_t<const K &, const V &> get_pair_ref() const { return hb_pair_t<const K &, const V &> (key, value); } @@ -107,8 +103,8 @@ struct hb_hashmap_t }; hb_object_header_t header; - bool successful; /* Allocations successful */ - unsigned int population; /* Not including tombstones. */ + unsigned int successful : 1; /* Allocations successful */ + unsigned int population : 31; /* Not including tombstones. */ unsigned int occupancy; /* Including tombstones. */ unsigned int mask; unsigned int prime; @@ -118,7 +114,10 @@ struct hb_hashmap_t { if (unlikely (!a.successful || !b.successful)) return; - hb_swap (a.population, b.population); + unsigned tmp = a.population; + a.population = b.population; + b.population = tmp; + //hb_swap (a.population, b.population); hb_swap (a.occupancy, b.occupancy); hb_swap (a.mask, b.mask); hb_swap (a.prime, b.prime); @@ -160,7 +159,9 @@ struct hb_hashmap_t { if (unlikely (!successful)) return false; - unsigned int power = hb_bit_storage (hb_max (population, new_population) * 2 + 8); + if (new_population != 0 && (new_population + new_population / 2) < mask) return true; + + unsigned int power = hb_bit_storage (hb_max ((unsigned) population, new_population) * 2 + 8); unsigned int new_size = 1u << power; item_t *new_items = (item_t *) hb_malloc ((size_t) new_size * sizeof (item_t)); if (unlikely (!new_items)) @@ -169,9 +170,9 @@ struct hb_hashmap_t return false; } for (auto &_ : hb_iter (new_items, new_size)) - _.clear (); + new (&_) item_t (); - unsigned int old_size = mask + 1; + unsigned int old_size = size (); item_t *old_items = items; /* Switch to new, empty, array. */ @@ -181,47 +182,82 @@ struct hb_hashmap_t items = new_items; /* Insert back old items. */ - if (old_items) - for (unsigned int i = 0; i < old_size; i++) + for (unsigned int i = 0; i < old_size; i++) + { + if (old_items[i].is_real ()) { - if (old_items[i].is_real ()) - { - set_with_hash (old_items[i].key, - old_items[i].hash, - std::move (old_items[i].value)); - } - old_items[i].~item_t (); + set_with_hash (std::move (old_items[i].key), + old_items[i].hash, + std::move (old_items[i].value)); } + old_items[i].~item_t (); + } hb_free (old_items); return true; } + template <typename KK, typename VV> + bool set_with_hash (KK&& key, uint32_t hash, VV&& value, bool is_delete=false) + { + if (unlikely (!successful)) return false; + if (unlikely ((occupancy + occupancy / 2) >= mask && !resize ())) return false; + item_t &item = item_for_hash (key, hash); + + if (is_delete && !(item == key)) + return true; /* Trying to delete non-existent key. */ + + if (item.is_used ()) + { + occupancy--; + if (!item.is_tombstone ()) + population--; + } + + item.key = std::forward<KK> (key); + item.value = std::forward<VV> (value); + item.hash = hash; + item.set_used (true); + item.set_tombstone (is_delete); + + occupancy++; + if (!is_delete) + population++; + + return true; + } + + template <typename VV> + bool set (const K &key, VV&& value) { return set_with_hash (key, hb_hash (key), std::forward<VV> (value)); } template <typename VV> - bool set (K key, VV&& value) { return set_with_hash (key, hb_hash (key), std::forward<VV> (value)); } + bool set (K &&key, VV&& value) { return set_with_hash (std::move (key), hb_hash (key), std::forward<VV> (value)); } - const V& get (K key) const + const V& get_with_hash (const K &key, uint32_t hash) const + { + if (unlikely (!items)) return item_t::default_value (); + auto &item = item_for_hash (key, hash); + return item.is_real () && item == key ? item.value : item_t::default_value (); + } + const V& get (const K &key) const { if (unlikely (!items)) return item_t::default_value (); - unsigned int i = bucket_for (key); - return items[i].is_real () && items[i] == key ? items[i].value : item_t::default_value (); + return get_with_hash (key, hb_hash (key)); } - void del (K key) { set_with_hash (key, hb_hash (key), item_t::default_value (), true); } + void del (const K &key) { set_with_hash (key, hb_hash (key), item_t::default_value (), true); } /* Has interface. */ - typedef const V& value_t; - value_t operator [] (K k) const { return get (k); } + const V& operator [] (K k) const { return get (k); } template <typename VV=V> bool has (K key, VV **vp = nullptr) const { if (unlikely (!items)) return false; - unsigned int i = bucket_for (key); - if (items[i].is_real () && items[i] == key) + auto &item = item_for_hash (key, hb_hash (key)); + if (item.is_real () && item == key) { - if (vp) *vp = &items[i].value; + if (vp) *vp = std::addressof (item.value); return true; } else @@ -230,13 +266,18 @@ struct hb_hashmap_t /* Projection. */ V operator () (K k) const { return get (k); } + unsigned size () const { return mask ? mask + 1 : 0; } + void clear () { if (unlikely (!successful)) return; - if (items) - for (auto &_ : hb_iter (items, mask + 1)) - _.clear (); + for (auto &_ : hb_iter (items, size ())) + { + /* Reconstruct items. */ + _.~item_t (); + new (&_) item_t (); + } population = occupancy = 0; } @@ -246,11 +287,10 @@ struct hb_hashmap_t uint32_t hash () const { - uint32_t h = 0; - for (const auto &item : + hb_array (items, mask ? mask + 1 : 0) - | hb_filter (&item_t::is_real)) - h ^= item.total_hash (); - return h; + return + + iter_items () + | hb_reduce ([] (uint32_t h, const item_t &_) { return h ^ _.total_hash (); }, (uint32_t) 0u) + ; } bool is_equal (const hb_hashmap_t &other) const @@ -258,7 +298,7 @@ struct hb_hashmap_t if (population != other.population) return false; for (auto pair : iter ()) - if (get (pair.first) != pair.second) + if (other.get (pair.first) != pair.second) return false; return true; @@ -271,87 +311,54 @@ struct hb_hashmap_t /* * Iterator */ - auto iter () const HB_AUTO_RETURN + + auto iter_items () const HB_AUTO_RETURN ( - + hb_array (items, mask ? mask + 1 : 0) + + hb_iter (items, size ()) | hb_filter (&item_t::is_real) - | hb_map (&item_t::get_pair) ) auto iter_ref () const HB_AUTO_RETURN ( - + hb_array (items, mask ? mask + 1 : 0) - | hb_filter (&item_t::is_real) + + iter_items () | hb_map (&item_t::get_pair_ref) ) - auto keys () const HB_AUTO_RETURN + auto iter () const HB_AUTO_RETURN ( - + hb_array (items, mask ? mask + 1 : 0) - | hb_filter (&item_t::is_real) - | hb_map (&item_t::key) - | hb_map (hb_ridentity) + + iter_items () + | hb_map (&item_t::get_pair) ) auto keys_ref () const HB_AUTO_RETURN ( - + hb_array (items, mask ? mask + 1 : 0) - | hb_filter (&item_t::is_real) + + iter_items () | hb_map (&item_t::key) ) - auto values () const HB_AUTO_RETURN + auto keys () const HB_AUTO_RETURN ( - + hb_array (items, mask ? mask + 1 : 0) - | hb_filter (&item_t::is_real) - | hb_map (&item_t::value) + + keys_ref () | hb_map (hb_ridentity) ) auto values_ref () const HB_AUTO_RETURN ( - + hb_array (items, mask ? mask + 1 : 0) - | hb_filter (&item_t::is_real) + + iter_items () | hb_map (&item_t::value) ) + auto values () const HB_AUTO_RETURN + ( + + values_ref () + | hb_map (hb_ridentity) + ) /* Sink interface. */ hb_hashmap_t& operator << (const hb_pair_t<K, V>& v) { set (v.first, v.second); return *this; } - - protected: - - template <typename VV> - bool set_with_hash (K key, uint32_t hash, VV&& value, bool is_delete=false) - { - if (unlikely (!successful)) return false; - if (unlikely ((occupancy + occupancy / 2) >= mask && !resize ())) return false; - unsigned int i = bucket_for_hash (key, hash); - - if (is_delete && items[i].key != key) - return true; /* Trying to delete non-existent key. */ - - if (items[i].is_used ()) - { - occupancy--; - if (!items[i].is_tombstone ()) - population--; - } - - items[i].key = key; - items[i].value = std::forward<VV> (value); - items[i].hash = hash; - items[i].set_used (true); - items[i].set_tombstone (is_delete); - - occupancy++; - if (!is_delete) - population++; - - return true; - } - - unsigned int bucket_for (const K &key) const - { - return bucket_for_hash (key, hb_hash (key)); - } - - unsigned int bucket_for_hash (const K &key, uint32_t hash) const + hb_hashmap_t& operator << (const hb_pair_t<K, V&&>& v) + { set (v.first, std::move (v.second)); return *this; } + hb_hashmap_t& operator << (const hb_pair_t<K&&, V>& v) + { set (std::move (v.first), v.second); return *this; } + hb_hashmap_t& operator << (const hb_pair_t<K&&, V&&>& v) + { set (std::move (v.first), std::move (v.second)); return *this; } + + item_t& item_for_hash (const K &key, uint32_t hash) const { hash &= 0x3FFFFFFF; // We only store lower 30bit of hash unsigned int i = hash % prime; @@ -360,12 +367,12 @@ struct hb_hashmap_t while (items[i].is_used ()) { if (items[i].hash == hash && items[i] == key) - return i; + return items[i]; if (tombstone == (unsigned) -1 && items[i].is_tombstone ()) tombstone = i; i = (i + ++step) & mask; } - return tombstone == (unsigned) -1 ? i : tombstone; + return items[tombstone == (unsigned) -1 ? i : tombstone]; } static unsigned int prime_for (unsigned int shift) diff --git a/thirdparty/harfbuzz/src/hb-meta.hh b/thirdparty/harfbuzz/src/hb-meta.hh index 1921ccbb6d..31aa7fa6f1 100644 --- a/thirdparty/harfbuzz/src/hb-meta.hh +++ b/thirdparty/harfbuzz/src/hb-meta.hh @@ -112,8 +112,7 @@ template <typename T> auto _hb_try_add_pointer (hb_priority<1>) -> hb_type_ident template <typename T> using hb_add_pointer = decltype (_hb_try_add_pointer<T> (hb_prioritize)); -/* TODO Add feature-parity to std::decay. */ -template <typename T> using hb_decay = hb_remove_const<hb_remove_reference<T>>; +template <typename T> using hb_decay = typename std::decay<T>::type; #define hb_is_convertible(From,To) std::is_convertible<From, To>::value @@ -133,6 +132,18 @@ struct template <typename T> constexpr auto operator () (T *v) const HB_AUTO_RETURN (*v) + + template <typename T> constexpr auto + operator () (const hb::shared_ptr<T>& v) const HB_AUTO_RETURN (*v) + + template <typename T> constexpr auto + operator () (hb::shared_ptr<T>& v) const HB_AUTO_RETURN (*v) + + template <typename T> constexpr auto + operator () (const hb::unique_ptr<T>& v) const HB_AUTO_RETURN (*v) + + template <typename T> constexpr auto + operator () (hb::unique_ptr<T>& v) const HB_AUTO_RETURN (*v) } HB_FUNCOBJ (hb_deref); diff --git a/thirdparty/harfbuzz/src/hb-ms-feature-ranges.hh b/thirdparty/harfbuzz/src/hb-ms-feature-ranges.hh index d40fdeaa82..46a20c91ea 100644 --- a/thirdparty/harfbuzz/src/hb-ms-feature-ranges.hh +++ b/thirdparty/harfbuzz/src/hb-ms-feature-ranges.hh @@ -166,7 +166,7 @@ hb_ms_setup_features (const hb_feature_t *features, { auto *feature = active_features.lsearch (event->feature); if (feature) - active_features.remove (feature - active_features.arrayZ); + active_features.remove_ordered (feature - active_features.arrayZ); } } diff --git a/thirdparty/harfbuzz/src/hb-multimap.hh b/thirdparty/harfbuzz/src/hb-multimap.hh new file mode 100644 index 0000000000..f0f95917aa --- /dev/null +++ b/thirdparty/harfbuzz/src/hb-multimap.hh @@ -0,0 +1,92 @@ +/* + * Copyright © 2022 Behdad Esfahbod + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +#ifndef HB_MULTIMAP_HH +#define HB_MULTIMAP_HH + +#include "hb.hh" +#include "hb-map.hh" +#include "hb-vector.hh" + + +/* + * hb_multimap_t + */ + +struct hb_multimap_t +{ + void add (hb_codepoint_t k, hb_codepoint_t v) + { + hb_codepoint_t *i; + if (multiples_indices.has (k, &i)) + { + multiples_values[*i].push (v); + return; + } + + hb_codepoint_t *old_v; + if (singulars.has (k, &old_v)) + { + hb_codepoint_t old = *old_v; + singulars.del (k); + + multiples_indices.set (k, multiples_values.length); + auto *vec = multiples_values.push (); + + vec->push (old); + vec->push (v); + + return; + } + + singulars.set (k, v); + } + + hb_array_t<const hb_codepoint_t> get (hb_codepoint_t k) const + { + hb_codepoint_t *v; + if (singulars.has (k, &v)) + return hb_array (v, 1); + + hb_codepoint_t *i; + if (multiples_indices.has (k, &i)) + return multiples_values[*i].as_array (); + + return hb_array_t<hb_codepoint_t> (); + } + + bool in_error () const + { + return singulars.in_error () || multiples_indices.in_error () || multiples_values.in_error (); + } + + protected: + hb_map_t singulars; + hb_map_t multiples_indices; + hb_vector_t<hb_vector_t<hb_codepoint_t>> multiples_values; +}; + + + +#endif /* HB_MULTIMAP_HH */ diff --git a/thirdparty/harfbuzz/src/hb-mutex.hh b/thirdparty/harfbuzz/src/hb-mutex.hh index 6914b22450..053f9ddcc4 100644 --- a/thirdparty/harfbuzz/src/hb-mutex.hh +++ b/thirdparty/harfbuzz/src/hb-mutex.hh @@ -108,10 +108,11 @@ struct hb_mutex_t struct hb_lock_t { - hb_lock_t (hb_mutex_t &mutex_) : mutex (mutex_) { mutex.lock (); } - ~hb_lock_t () { mutex.unlock (); } + hb_lock_t (hb_mutex_t &mutex_) : mutex (&mutex_) { mutex->lock (); } + hb_lock_t (hb_mutex_t *mutex_) : mutex (mutex_) { if (mutex) mutex->lock (); } + ~hb_lock_t () { if (mutex) mutex->unlock (); } private: - hb_mutex_t &mutex; + hb_mutex_t *mutex; }; diff --git a/thirdparty/harfbuzz/src/hb-number-parser.hh b/thirdparty/harfbuzz/src/hb-number-parser.hh index 1a9dbba6dd..ec68c3a728 100644 --- a/thirdparty/harfbuzz/src/hb-number-parser.hh +++ b/thirdparty/harfbuzz/src/hb-number-parser.hh @@ -31,7 +31,7 @@ #include "hb.hh" -#line 35 "hb-number-parser.hh" +#line 32 "hb-number-parser.hh" static const unsigned char _double_parser_trans_keys[] = { 0u, 0u, 43u, 57u, 46u, 57u, 48u, 57u, 43u, 57u, 48u, 57u, 48u, 101u, 48u, 57u, 46u, 101u, 0 @@ -135,12 +135,12 @@ strtod_rl (const char *p, const char **end_ptr /* IN/OUT */) int cs; -#line 139 "hb-number-parser.hh" +#line 132 "hb-number-parser.hh" { cs = double_parser_start; } -#line 144 "hb-number-parser.hh" +#line 135 "hb-number-parser.hh" { int _slen; int _trans; @@ -198,7 +198,7 @@ _resume: exp_overflow = true; } break; -#line 202 "hb-number-parser.hh" +#line 187 "hb-number-parser.hh" } _again: diff --git a/thirdparty/harfbuzz/src/hb-object.hh b/thirdparty/harfbuzz/src/hb-object.hh index 9876c2923c..a23c25f7ca 100644 --- a/thirdparty/harfbuzz/src/hb-object.hh +++ b/thirdparty/harfbuzz/src/hb-object.hh @@ -80,7 +80,7 @@ struct hb_lockable_set_t if (item) { item_t old = *item; - *item = items[items.length - 1]; + *item = std::move (items.tail ()); items.pop (); l.unlock (); old.fini (); @@ -123,7 +123,7 @@ struct hb_lockable_set_t l.lock (); while (items.length) { - item_t old = items[items.length - 1]; + item_t old = items.tail (); items.pop (); l.unlock (); old.fini (); diff --git a/thirdparty/harfbuzz/src/hb-open-file.hh b/thirdparty/harfbuzz/src/hb-open-file.hh index 6eee5827c1..13570a46e0 100644 --- a/thirdparty/harfbuzz/src/hb-open-file.hh +++ b/thirdparty/harfbuzz/src/hb-open-file.hh @@ -90,7 +90,7 @@ typedef struct OpenTypeOffsetTable { if (table_count) { - + tables.sub_array (start_offset, table_count) + + tables.as_array ().sub_array (start_offset, table_count) | hb_map (&TableRecord::tag) | hb_sink (hb_array (table_tags, *table_count)) ; @@ -158,7 +158,7 @@ typedef struct OpenTypeOffsetTable return_trace (false); if (likely (len)) - memcpy (start, blob->data, len); + hb_memcpy (start, blob->data, len); /* 4-byte alignment. */ c->align (4); diff --git a/thirdparty/harfbuzz/src/hb-open-type.hh b/thirdparty/harfbuzz/src/hb-open-type.hh index d0d01a68c5..290799127a 100644 --- a/thirdparty/harfbuzz/src/hb-open-type.hh +++ b/thirdparty/harfbuzz/src/hb-open-type.hh @@ -141,27 +141,27 @@ typedef HBINT32 FWORD32; /* 16-bit unsigned integer (HBUINT16) that describes a quantity in FUnits. */ typedef HBUINT16 UFWORD; -/* 16-bit signed fixed number with the low 14 bits of fraction (2.14). */ -struct F2DOT14 : HBINT16 +template <typename Type, unsigned fraction_bits> +struct HBFixed : Type { - F2DOT14& operator = (uint16_t i ) { HBINT16::operator= (i); return *this; } - // 16384 means 1<<14 - float to_float () const { return ((int32_t) v) / 16384.f; } - void set_float (float f) { v = roundf (f * 16384.f); } + static constexpr float shift = (float) (1 << fraction_bits); + static_assert (Type::static_size * 8 > fraction_bits, ""); + + HBFixed& operator = (typename Type::type i ) { Type::operator= (i); return *this; } + float to_float (float offset = 0) const { return ((int32_t) Type::v + offset) / shift; } + void set_float (float f) { Type::v = roundf (f * shift); } public: - DEFINE_SIZE_STATIC (2); + DEFINE_SIZE_STATIC (Type::static_size); }; +/* 16-bit signed fixed number with the low 14 bits of fraction (2.14). */ +using F2DOT14 = HBFixed<HBINT16, 14>; + +/* 16-bit signed fixed number with the low 12 bits of fraction (4.12). */ +using F4DOT12 = HBFixed<HBINT16, 12>; + /* 32-bit signed fixed-point number (16.16). */ -struct HBFixed : HBINT32 -{ - HBFixed& operator = (uint32_t i) { HBINT32::operator= (i); return *this; } - // 65536 means 1<<16 - float to_float () const { return ((int32_t) v) / 65536.f; } - void set_float (float f) { v = roundf (f * 65536.f); } - public: - DEFINE_SIZE_STATIC (4); -}; +using F16DOT16 = HBFixed<HBINT32, 16>; /* Date represented in number of seconds since 12:00 midnight, January 1, * 1904. The value is represented as a signed 64-bit integer. */ @@ -212,6 +212,12 @@ typedef Index NameID; struct VarIdx : HBUINT32 { static constexpr unsigned NO_VARIATION = 0xFFFFFFFFu; + static_assert (NO_VARIATION == HB_OT_LAYOUT_NO_VARIATIONS_INDEX, ""); + static uint32_t add (uint32_t i, unsigned short v) + { + if (i == NO_VARIATION) return i; + return i + v; + } VarIdx& operator = (uint32_t i) { HBUINT32::operator= (i); return *this; } }; DECLARE_NULL_NAMESPACE_BYTES (OT, VarIdx); @@ -496,10 +502,10 @@ struct UnsizedArrayOf void qsort (unsigned int len, unsigned int start = 0, unsigned int end = (unsigned int) -1) { as_array (len).qsort (start, end); } - bool serialize (hb_serialize_context_t *c, unsigned int items_len) + bool serialize (hb_serialize_context_t *c, unsigned int items_len, bool clear = true) { TRACE_SERIALIZE (this); - if (unlikely (!c->extend (this, items_len))) return_trace (false); + if (unlikely (!c->extend_size (this, get_size (items_len), clear))) return_trace (false); return_trace (true); } template <typename Iterator, @@ -507,8 +513,8 @@ struct UnsizedArrayOf bool serialize (hb_serialize_context_t *c, Iterator items) { TRACE_SERIALIZE (this); - unsigned count = items.len (); - if (unlikely (!serialize (c, count))) return_trace (false); + unsigned count = hb_len (items); + if (unlikely (!serialize (c, count, false))) return_trace (false); /* TODO Umm. Just exhaust the iterator instead? Being extra * cautious right now.. */ for (unsigned i = 0; i < count; i++, ++items) @@ -649,14 +655,9 @@ struct ArrayOf operator iter_t () const { return iter (); } operator writer_t () { return writer (); } - hb_array_t<const Type> sub_array (unsigned int start_offset, unsigned int count) const - { return as_array ().sub_array (start_offset, count); } - hb_array_t<const Type> sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */) const - { return as_array ().sub_array (start_offset, count); } - hb_array_t<Type> sub_array (unsigned int start_offset, unsigned int count) - { return as_array ().sub_array (start_offset, count); } - hb_array_t<Type> sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */) - { return as_array ().sub_array (start_offset, count); } + /* Faster range-based for loop. */ + const Type *begin () const { return arrayZ; } + const Type *end () const { return arrayZ + len; } template <typename T> Type &lsearch (const T &x, Type ¬_found = Crap (Type)) @@ -670,15 +671,15 @@ struct ArrayOf unsigned int to_store = (unsigned int) -1) const { return as_array ().lfind (x, i, not_found, to_store); } - void qsort (unsigned int start = 0, unsigned int end = (unsigned int) -1) - { as_array ().qsort (start, end); } + void qsort () + { as_array ().qsort (); } - HB_NODISCARD bool serialize (hb_serialize_context_t *c, unsigned items_len) + HB_NODISCARD bool serialize (hb_serialize_context_t *c, unsigned items_len, bool clear = true) { TRACE_SERIALIZE (this); if (unlikely (!c->extend_min (this))) return_trace (false); c->check_assign (len, items_len, HB_SERIALIZE_ERROR_ARRAY_OVERFLOW); - if (unlikely (!c->extend (this))) return_trace (false); + if (unlikely (!c->extend_size (this, get_size (), clear))) return_trace (false); return_trace (true); } template <typename Iterator, @@ -686,8 +687,8 @@ struct ArrayOf HB_NODISCARD bool serialize (hb_serialize_context_t *c, Iterator items) { TRACE_SERIALIZE (this); - unsigned count = items.len (); - if (unlikely (!serialize (c, count))) return_trace (false); + unsigned count = hb_len (items); + if (unlikely (!serialize (c, count, false))) return_trace (false); /* TODO Umm. Just exhaust the iterator instead? Being extra * cautious right now.. */ for (unsigned i = 0; i < count; i++, ++items) @@ -831,21 +832,25 @@ struct HeadlessArrayOf operator iter_t () const { return iter (); } operator writer_t () { return writer (); } - bool serialize (hb_serialize_context_t *c, unsigned int items_len) + /* Faster range-based for loop. */ + const Type *begin () const { return arrayZ; } + const Type *end () const { return arrayZ + get_length (); } + + HB_NODISCARD bool serialize (hb_serialize_context_t *c, unsigned int items_len, bool clear = true) { TRACE_SERIALIZE (this); if (unlikely (!c->extend_min (this))) return_trace (false); c->check_assign (lenP1, items_len + 1, HB_SERIALIZE_ERROR_ARRAY_OVERFLOW); - if (unlikely (!c->extend (this))) return_trace (false); + if (unlikely (!c->extend_size (this, get_size (), clear))) return_trace (false); return_trace (true); } template <typename Iterator, hb_requires (hb_is_source_of (Iterator, Type))> - bool serialize (hb_serialize_context_t *c, Iterator items) + HB_NODISCARD bool serialize (hb_serialize_context_t *c, Iterator items) { TRACE_SERIALIZE (this); - unsigned count = items.len (); - if (unlikely (!serialize (c, count))) return_trace (false); + unsigned count = hb_len (items); + if (unlikely (!serialize (c, count, false))) return_trace (false); /* TODO Umm. Just exhaust the iterator instead? Being extra * cautious right now.. */ for (unsigned i = 0; i < count; i++, ++items) @@ -947,14 +952,9 @@ struct SortedArrayOf : ArrayOf<Type, LenType> operator iter_t () const { return iter (); } operator writer_t () { return writer (); } - hb_sorted_array_t<const Type> sub_array (unsigned int start_offset, unsigned int count) const - { return as_array ().sub_array (start_offset, count); } - hb_sorted_array_t<const Type> sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */) const - { return as_array ().sub_array (start_offset, count); } - hb_sorted_array_t<Type> sub_array (unsigned int start_offset, unsigned int count) - { return as_array ().sub_array (start_offset, count); } - hb_sorted_array_t<Type> sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */) - { return as_array ().sub_array (start_offset, count); } + /* Faster range-based for loop. */ + const Type *begin () const { return this->arrayZ; } + const Type *end () const { return this->arrayZ + this->len; } bool serialize (hb_serialize_context_t *c, unsigned int items_len) { diff --git a/thirdparty/harfbuzz/src/hb-ot-cff-common.hh b/thirdparty/harfbuzz/src/hb-ot-cff-common.hh index ae3b83a256..f22824fc69 100644 --- a/thirdparty/harfbuzz/src/hb-ot-cff-common.hh +++ b/thirdparty/harfbuzz/src/hb-ot-cff-common.hh @@ -66,95 +66,25 @@ struct CFFIndex { TRACE_SERIALIZE (this); unsigned int size = get_size (); - CFFIndex *out = c->allocate_size<CFFIndex> (size); + CFFIndex *out = c->allocate_size<CFFIndex> (size, false); if (likely (out)) - memcpy (out, this, size); + hb_memcpy (out, this, size); return_trace (out); } + template <typename Iterable, + hb_requires (hb_is_iterable (Iterable))> bool serialize (hb_serialize_context_t *c, - unsigned int offSize_, - const byte_str_array_t &byteArray) + const Iterable &iterable) { TRACE_SERIALIZE (this); - - if (byteArray.length == 0) - { - COUNT *dest = c->allocate_min<COUNT> (); - if (unlikely (!dest)) return_trace (false); - *dest = 0; - return_trace (true); - } - - /* serialize CFFIndex header */ - if (unlikely (!c->extend_min (this))) return_trace (false); - this->count = byteArray.length; - this->offSize = offSize_; - if (unlikely (!c->allocate_size<HBUINT8> (offSize_ * (byteArray.length + 1)))) - return_trace (false); - - /* serialize indices */ - unsigned int offset = 1; - unsigned int i = 0; - for (; i < byteArray.length; i++) - { - set_offset_at (i, offset); - offset += byteArray[i].get_size (); - } - set_offset_at (i, offset); - - /* serialize data */ - for (unsigned int i = 0; i < byteArray.length; i++) - { - const hb_ubytes_t &bs = byteArray[i]; - unsigned char *dest = c->allocate_size<unsigned char> (bs.length); - if (unlikely (!dest)) return_trace (false); - memcpy (dest, &bs[0], bs.length); - } - - return_trace (true); - } - - bool serialize (hb_serialize_context_t *c, - unsigned int offSize_, - const str_buff_vec_t &buffArray) - { - byte_str_array_t byteArray; - byteArray.init (); - byteArray.resize (buffArray.length); - for (unsigned int i = 0; i < byteArray.length; i++) - byteArray[i] = hb_ubytes_t (buffArray[i].arrayZ, buffArray[i].length); - bool result = this->serialize (c, offSize_, byteArray); - byteArray.fini (); - return result; - } - - template <typename Iterator, - hb_requires (hb_is_iterator (Iterator))> - bool serialize (hb_serialize_context_t *c, - Iterator it) - { - TRACE_SERIALIZE (this); - serialize_header(c, + it | hb_map ([] (const hb_ubytes_t &_) { return _.length; })); + auto it = hb_iter (iterable); + serialize_header(c, + it | hb_map (hb_iter) | hb_map (hb_len)); for (const auto &_ : +it) - _.copy (c); + hb_iter (_).copy (c); return_trace (true); } - bool serialize (hb_serialize_context_t *c, - const byte_str_array_t &byteArray) - { return serialize (c, + hb_iter (byteArray)); } - - bool serialize (hb_serialize_context_t *c, - const str_buff_vec_t &buffArray) - { - auto it = - + hb_iter (buffArray) - | hb_map ([] (const str_buff_t &_) { return hb_ubytes_t (_.arrayZ, _.length); }) - ; - return serialize (c, it); - } - template <typename Iterator, hb_requires (hb_is_iterator (Iterator))> bool serialize_header (hb_serialize_context_t *c, @@ -171,7 +101,7 @@ struct CFFIndex if (!this->count) return_trace (true); if (unlikely (!c->extend (this->offSize))) return_trace (false); this->offSize = off_size; - if (unlikely (!c->allocate_size<HBUINT8> (off_size * (this->count + 1)))) + if (unlikely (!c->allocate_size<HBUINT8> (off_size * (this->count + 1), false))) return_trace (false); /* serialize indices */ @@ -179,14 +109,27 @@ struct CFFIndex unsigned int i = 0; for (unsigned _ : +it) { - CFFIndex<COUNT>::set_offset_at (i++, offset); + set_offset_at (i++, offset); offset += _; } - CFFIndex<COUNT>::set_offset_at (i, offset); + set_offset_at (i, offset); return_trace (true); } + template <typename Iterable, + hb_requires (hb_is_iterable (Iterable))> + static unsigned total_size (const Iterable &iterable) + { + auto it = + hb_iter (iterable) | hb_map (hb_iter) | hb_map (hb_len); + if (!it) return 0; + + unsigned total = + it | hb_reduce (hb_add, 0); + unsigned off_size = (hb_bit_storage (total + 1) + 7) / 8; + + return min_size + HBUINT8::static_size + (hb_len (it) + 1) * off_size + total; + } + void set_offset_at (unsigned int index, unsigned int offset) { assert (index <= count); @@ -207,10 +150,14 @@ struct CFFIndex unsigned int size = offSize; const HBUINT8 *p = offsets + size * index; - unsigned int offset = 0; - for (; size; size--) - offset = (offset << 8) + *p++; - return offset; + switch (size) + { + case 1: return * (HBUINT8 *) p; + case 2: return * (HBUINT16 *) p; + case 3: return * (HBUINT24 *) p; + case 4: return * (HBUINT32 *) p; + default: return 0; + } } unsigned int length_at (unsigned int index) const @@ -229,6 +176,7 @@ struct CFFIndex hb_ubytes_t operator [] (unsigned int index) const { if (unlikely (index >= count)) return hb_ubytes_t (); + _hb_compiler_memory_r_barrier (); unsigned length = length_at (index); if (unlikely (!length)) return hb_ubytes_t (); return hb_ubytes_t (data_base () + offset_at (index) - 1, length); @@ -280,7 +228,7 @@ struct CFFIndexOf : CFFIndex<COUNT> if (unlikely (!c->extend_min (this))) return_trace (false); this->count = dataArrayLen; this->offSize = offSize_; - if (unlikely (!c->allocate_size<HBUINT8> (offSize_ * (dataArrayLen + 1)))) + if (unlikely (!c->allocate_size<HBUINT8> (offSize_ * (dataArrayLen + 1), false))) return_trace (false); /* serialize indices */ @@ -288,10 +236,10 @@ struct CFFIndexOf : CFFIndex<COUNT> unsigned int i = 0; for (; i < dataArrayLen; i++) { - CFFIndex<COUNT>::set_offset_at (i, offset); + this->set_offset_at (i, offset); offset += dataSizeArray[i]; } - CFFIndex<COUNT>::set_offset_at (i, offset); + this->set_offset_at (i, offset); /* serialize data */ for (unsigned int i = 0; i < dataArrayLen; i++) @@ -324,13 +272,12 @@ struct Dict : UnsizedByteStr template <typename T, typename V> static bool serialize_int_op (hb_serialize_context_t *c, op_code_t op, V value, op_code_t intOp) { - // XXX: not sure why but LLVM fails to compile the following 'unlikely' macro invocation - if (/*unlikely*/ (!serialize_int<T, V> (c, intOp, value))) + if (unlikely ((!serialize_int<T, V> (c, intOp, value)))) return false; TRACE_SERIALIZE (this); /* serialize the opcode */ - HBUINT8 *p = c->allocate_size<HBUINT8> (OpCode_Size (op)); + HBUINT8 *p = c->allocate_size<HBUINT8> (OpCode_Size (op), false); if (unlikely (!p)) return_trace (false); if (Is_OpCode_ESC (op)) { @@ -415,9 +362,8 @@ struct FDSelect0 { TRACE_SANITIZE (this); if (unlikely (!(c->check_struct (this)))) return_trace (false); - for (unsigned int i = 0; i < c->get_num_glyphs (); i++) - if (unlikely (!fds[i].sanitize (c))) - return_trace (false); + if (unlikely (!c->check_array (fds, c->get_num_glyphs ()))) + return_trace (false); return_trace (true); } @@ -471,14 +417,20 @@ struct FDSelect3_4 return_trace (true); } - hb_codepoint_t get_fd (hb_codepoint_t glyph) const + static int _cmp_range (const void *_key, const void *_item) { - unsigned int i; - for (i = 1; i < nRanges (); i++) - if (glyph < ranges[i].first) - break; + hb_codepoint_t glyph = * (hb_codepoint_t *) _key; + FDSelect3_4_Range<GID_TYPE, FD_TYPE> *range = (FDSelect3_4_Range<GID_TYPE, FD_TYPE> *) _item; - return (hb_codepoint_t) ranges[i - 1].fd; + if (glyph < range[0].first) return -1; + if (glyph < range[1].first) return 0; + return +1; + } + + hb_codepoint_t get_fd (hb_codepoint_t glyph) const + { + auto *range = hb_bsearch (glyph, &ranges[0], nRanges () - 1, sizeof (ranges[0]), _cmp_range); + return range ? range->fd : ranges[nRanges () - 1].fd; } GID_TYPE &nRanges () { return ranges.len; } @@ -501,9 +453,9 @@ struct FDSelect { TRACE_SERIALIZE (this); unsigned int size = src.get_size (num_glyphs); - FDSelect *dest = c->allocate_size<FDSelect> (size); + FDSelect *dest = c->allocate_size<FDSelect> (size, false); if (unlikely (!dest)) return_trace (false); - memcpy (dest, &src, size); + hb_memcpy (dest, &src, size); return_trace (true); } diff --git a/thirdparty/harfbuzz/src/hb-ot-cff1-table.hh b/thirdparty/harfbuzz/src/hb-ot-cff1-table.hh index 17b0296616..bb856c9ddb 100644 --- a/thirdparty/harfbuzz/src/hb-ot-cff1-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-cff1-table.hh @@ -175,7 +175,7 @@ struct Encoding unsigned int size = src.get_size (); Encoding *dest = c->allocate_size<Encoding> (size); if (unlikely (!dest)) return_trace (false); - memcpy (dest, &src, size); + hb_memcpy (dest, &src, size); return_trace (true); } @@ -471,7 +471,7 @@ struct Charset unsigned int size = src.get_size (num_glyphs); Charset *dest = c->allocate_size<Charset> (size); if (unlikely (!dest)) return_trace (false); - memcpy (dest, &src, size); + hb_memcpy (dest, &src, size); return_trace (true); } @@ -617,7 +617,6 @@ struct CFF1StringIndex : CFF1Index } byte_str_array_t bytesArray; - bytesArray.init (); if (!bytesArray.resize (sidmap.get_population ())) return_trace (false); for (unsigned int i = 0; i < strings.count; i++) @@ -628,7 +627,6 @@ struct CFF1StringIndex : CFF1Index } bool result = CFF1Index::serialize (c, bytesArray); - bytesArray.fini (); return_trace (result); } }; @@ -813,7 +811,7 @@ struct cff1_top_dict_opset_t : top_dict_opset_t<cff1_top_dict_val_t> break; default: - env.last_offset = env.str_ref.offset; + env.last_offset = env.str_ref.get_offset (); top_dict_opset_t<cff1_top_dict_val_t>::process_op (op, env, dictval); /* Record this operand below if stack is empty, otherwise done */ if (!env.argStack.is_empty ()) return; @@ -1295,10 +1293,10 @@ struct cff1 } protected: - hb_blob_t *blob = nullptr; hb_sanitize_context_t sc; public: + hb_blob_t *blob = nullptr; const Encoding *encoding = nullptr; const Charset *charset = nullptr; const CFF1NameIndex *nameIndex = nullptr; diff --git a/thirdparty/harfbuzz/src/hb-ot-cff2-table.hh b/thirdparty/harfbuzz/src/hb-ot-cff2-table.hh index 746160dc8e..9081930bbe 100644 --- a/thirdparty/harfbuzz/src/hb-ot-cff2-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-cff2-table.hh @@ -56,7 +56,7 @@ struct CFF2FDSelect unsigned int size = src.get_size (num_glyphs); CFF2FDSelect *dest = c->allocate_size<CFF2FDSelect> (size); if (unlikely (!dest)) return_trace (false); - memcpy (dest, &src, size); + hb_memcpy (dest, &src, size); return_trace (true); } @@ -124,7 +124,7 @@ struct CFF2VariationStore unsigned int size_ = varStore->get_size (); CFF2VariationStore *dest = c->allocate_size<CFF2VariationStore> (size_); if (unlikely (!dest)) return_trace (false); - memcpy (dest, varStore, size_); + hb_memcpy (dest, varStore, size_); return_trace (true); } @@ -483,13 +483,18 @@ struct cff2 blob = nullptr; } + hb_map_t *create_glyph_to_sid_map () const + { + return nullptr; + } + bool is_valid () const { return blob; } protected: - hb_blob_t *blob = nullptr; hb_sanitize_context_t sc; public: + hb_blob_t *blob = nullptr; cff2_top_dict_values_t topDict; const CFF2Subrs *globalSubrs = nullptr; const CFF2VariationStore *varStore = nullptr; diff --git a/thirdparty/harfbuzz/src/hb-ot-cmap-table.hh b/thirdparty/harfbuzz/src/hb-ot-cmap-table.hh index 09c9fe93f3..523196fa79 100644 --- a/thirdparty/harfbuzz/src/hb-ot-cmap-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-cmap-table.hh @@ -909,7 +909,7 @@ struct DefaultUVS : SortedArray32Of<UnicodeValueRange> hb_codepoint_t first = arrayZ[i].startUnicodeValue; hb_codepoint_t last = hb_min ((hb_codepoint_t) (first + arrayZ[i].additionalCount), (hb_codepoint_t) HB_UNICODE_MAX); - out->add_range (first, hb_min (last, 0x10FFFFu)); + out->add_range (first, last); } } @@ -925,37 +925,75 @@ struct DefaultUVS : SortedArray32Of<UnicodeValueRange> if (unlikely (!c->copy<HBUINT32> (len))) return nullptr; unsigned init_len = c->length (); - hb_codepoint_t lastCode = HB_MAP_VALUE_INVALID; - int count = -1; - - for (const UnicodeValueRange& _ : as_array ()) + if (this->len > unicodes->get_population () * hb_bit_storage ((unsigned) this->len)) { - for (const unsigned addcnt : hb_range ((unsigned) _.additionalCount + 1)) + hb_codepoint_t start = HB_SET_VALUE_INVALID; + hb_codepoint_t end = HB_SET_VALUE_INVALID; + + for (hb_codepoint_t u = HB_SET_VALUE_INVALID; + unicodes->next (&u);) { - unsigned curEntry = (unsigned) _.startUnicodeValue + addcnt; - if (!unicodes->has (curEntry)) continue; - count += 1; - if (lastCode == HB_MAP_VALUE_INVALID) - lastCode = curEntry; - else if (lastCode + count != curEntry) + if (!as_array ().bsearch (u)) + continue; + if (start == HB_SET_VALUE_INVALID) { + start = u; + end = start - 1; + } + if (end + 1 != u || end - start == 255) + { UnicodeValueRange rec; - rec.startUnicodeValue = lastCode; - rec.additionalCount = count - 1; + rec.startUnicodeValue = start; + rec.additionalCount = end - start; c->copy<UnicodeValueRange> (rec); - - lastCode = curEntry; - count = 0; + start = u; } + end = u; + } + if (start != HB_SET_VALUE_INVALID) + { + UnicodeValueRange rec; + rec.startUnicodeValue = start; + rec.additionalCount = end - start; + c->copy<UnicodeValueRange> (rec); } - } - if (lastCode != HB_MAP_VALUE_INVALID) + } + else { - UnicodeValueRange rec; - rec.startUnicodeValue = lastCode; - rec.additionalCount = count; - c->copy<UnicodeValueRange> (rec); + hb_codepoint_t lastCode = HB_SET_VALUE_INVALID; + int count = -1; + + for (const UnicodeValueRange& _ : *this) + { + hb_codepoint_t curEntry = (hb_codepoint_t) (_.startUnicodeValue - 1); + hb_codepoint_t end = curEntry + _.additionalCount + 2; + + for (; unicodes->next (&curEntry) && curEntry < end;) + { + count += 1; + if (lastCode == HB_SET_VALUE_INVALID) + lastCode = curEntry; + else if (lastCode + count != curEntry) + { + UnicodeValueRange rec; + rec.startUnicodeValue = lastCode; + rec.additionalCount = count - 1; + c->copy<UnicodeValueRange> (rec); + + lastCode = curEntry; + count = 0; + } + } + } + + if (lastCode != HB_MAP_VALUE_INVALID) + { + UnicodeValueRange rec; + rec.startUnicodeValue = lastCode; + rec.additionalCount = count; + c->copy<UnicodeValueRange> (rec); + } } if (c->length () - init_len == 0) @@ -1474,32 +1512,80 @@ struct EncodingRecord DEFINE_SIZE_STATIC (8); }; +struct cmap; + struct SubtableUnicodesCache { private: - const void* base; - hb_hashmap_t<intptr_t, hb::unique_ptr<hb_set_t>> cached_unicodes; + hb_blob_ptr_t<cmap> base_blob; + const char* base; + hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> cached_unicodes; public: + + static SubtableUnicodesCache* create (hb_blob_ptr_t<cmap> source_table) + { + SubtableUnicodesCache* cache = + (SubtableUnicodesCache*) hb_malloc (sizeof(SubtableUnicodesCache)); + new (cache) SubtableUnicodesCache (source_table); + return cache; + } + + static void destroy (void* value) { + if (!value) return; + + SubtableUnicodesCache* cache = (SubtableUnicodesCache*) value; + cache->~SubtableUnicodesCache (); + hb_free (cache); + } + SubtableUnicodesCache(const void* cmap_base) - : base(cmap_base), cached_unicodes() {} + : base_blob(), + base ((const char*) cmap_base), + cached_unicodes () + {} + + SubtableUnicodesCache(hb_blob_ptr_t<cmap> base_blob_) + : base_blob(base_blob_), + base ((const char *) base_blob.get()), + cached_unicodes () + {} + + ~SubtableUnicodesCache() + { + base_blob.destroy (); + } + + bool same_base(const void* other) const + { + return other == (const void*) base; + } - hb_set_t* set_for (const EncodingRecord* record) + const hb_set_t* set_for (const EncodingRecord* record, + SubtableUnicodesCache& mutable_cache) const { - if (!cached_unicodes.has ((intptr_t) record)) + if (cached_unicodes.has ((unsigned) ((const char *) record - base))) + return cached_unicodes.get ((unsigned) ((const char *) record - base)); + + return mutable_cache.set_for (record); + } + + const hb_set_t* set_for (const EncodingRecord* record) + { + if (!cached_unicodes.has ((unsigned) ((const char *) record - base))) { hb_set_t *s = hb_set_create (); if (unlikely (s->in_error ())) return hb_set_get_empty (); - + (base+record->subtable).collect_unicodes (s); - if (unlikely (!cached_unicodes.set ((intptr_t) record, hb::unique_ptr<hb_set_t> {s}))) + if (unlikely (!cached_unicodes.set ((unsigned) ((const char *) record - base), hb::unique_ptr<hb_set_t> {s}))) return hb_set_get_empty (); return s; } - return cached_unicodes.get ((intptr_t) record); + return cached_unicodes.get ((unsigned) ((const char *) record - base)); } }; @@ -1523,13 +1609,30 @@ struct cmap { static constexpr hb_tag_t tableTag = HB_OT_TAG_cmap; + + static SubtableUnicodesCache* create_filled_cache(hb_blob_ptr_t<cmap> source_table) { + const cmap* cmap = source_table.get(); + auto it = + + hb_iter (cmap->encodingRecord) + | hb_filter ([&](const EncodingRecord& _) { + return cmap::filter_encoding_records_for_subset (cmap, _); + }) + ; + + SubtableUnicodesCache* cache = SubtableUnicodesCache::create(source_table); + for (const EncodingRecord& _ : it) + cache->set_for(&_); // populate the cache for this encoding record. + + return cache; + } + template<typename Iterator, typename EncodingRecIter, hb_requires (hb_is_iterator (EncodingRecIter))> bool serialize (hb_serialize_context_t *c, Iterator it, EncodingRecIter encodingrec_iter, const void *base, - const hb_subset_plan_t *plan, + hb_subset_plan_t *plan, bool drop_format_4 = false) { if (unlikely (!c->extend_min ((*this)))) return false; @@ -1538,7 +1641,14 @@ struct cmap unsigned format4objidx = 0, format12objidx = 0, format14objidx = 0; auto snap = c->snapshot (); - SubtableUnicodesCache unicodes_cache (base); + SubtableUnicodesCache local_unicodes_cache (base); + const SubtableUnicodesCache* unicodes_cache = &local_unicodes_cache; + + if (plan->accelerator && + plan->accelerator->cmap_cache && + plan->accelerator->cmap_cache->same_base (base)) + unicodes_cache = plan->accelerator->cmap_cache; + for (const EncodingRecord& _ : encodingrec_iter) { if (c->in_error ()) @@ -1547,7 +1657,7 @@ struct cmap unsigned format = (base+_.subtable).u.format; if (format != 4 && format != 12 && format != 14) continue; - hb_set_t* unicodes_set = unicodes_cache.set_for (&_); + const hb_set_t* unicodes_set = unicodes_cache->set_for (&_, local_unicodes_cache); if (!drop_format_4 && format == 4) { @@ -1566,7 +1676,13 @@ struct cmap else if (format == 12) { - if (_can_drop (_, *unicodes_set, base, unicodes_cache, + it | hb_map (hb_first), encodingrec_iter)) continue; + if (_can_drop (_, + *unicodes_set, + base, + *unicodes_cache, + local_unicodes_cache, + + it | hb_map (hb_first), encodingrec_iter)) + continue; c->copy (_, + it | hb_filter (*unicodes_set, hb_first), 12u, base, plan, &format12objidx); } else if (format == 14) c->copy (_, it, 14u, base, plan, &format14objidx); @@ -1585,7 +1701,8 @@ struct cmap bool _can_drop (const EncodingRecord& cmap12, const hb_set_t& cmap12_unicodes, const void* base, - SubtableUnicodesCache& unicodes_cache, + const SubtableUnicodesCache& unicodes_cache, + SubtableUnicodesCache& local_unicodes_cache, Iterator subset_unicodes, EncodingRecordIterator encoding_records) { @@ -1616,7 +1733,7 @@ struct cmap || (base+_.subtable).get_language() != target_language) continue; - hb_set_t* sibling_unicodes = unicodes_cache.set_for (&_); + const hb_set_t* sibling_unicodes = unicodes_cache.set_for (&_, local_unicodes_cache); auto cmap12 = + subset_unicodes | hb_filter (cmap12_unicodes); auto sibling = + subset_unicodes | hb_filter (*sibling_unicodes); @@ -1653,17 +1770,9 @@ struct cmap auto encodingrec_iter = + hb_iter (encodingRecord) - | hb_filter ([&] (const EncodingRecord& _) - { - if ((_.platformID == 0 && _.encodingID == 3) || - (_.platformID == 0 && _.encodingID == 4) || - (_.platformID == 3 && _.encodingID == 1) || - (_.platformID == 3 && _.encodingID == 10) || - (this + _.subtable).u.format == 14) - return true; - - return false; - }) + | hb_filter ([&](const EncodingRecord& _) { + return cmap::filter_encoding_records_for_subset (this, _); + }) ; if (unlikely (!encodingrec_iter.len ())) return_trace (false); @@ -1692,7 +1801,11 @@ struct cmap { return (_.second != HB_MAP_VALUE_INVALID); }) ; - return_trace (cmap_prime->serialize (c->serializer, it, encodingrec_iter, this, c->plan)); + return_trace (cmap_prime->serialize (c->serializer, + it, + encodingrec_iter, + this, + c->plan)); } const CmapSubtable *find_best_subtable (bool *symbol = nullptr) const @@ -1928,6 +2041,19 @@ struct cmap encodingRecord.sanitize (c, this)); } + private: + + static bool filter_encoding_records_for_subset(const cmap* cmap, + const EncodingRecord& _) + { + return + (_.platformID == 0 && _.encodingID == 3) || + (_.platformID == 0 && _.encodingID == 4) || + (_.platformID == 3 && _.encodingID == 1) || + (_.platformID == 3 && _.encodingID == 10) || + (cmap + _.subtable).u.format == 14; + } + protected: HBUINT16 version; /* Table version number (0). */ SortedArray16Of<EncodingRecord> diff --git a/thirdparty/harfbuzz/src/hb-ot-color-cbdt-table.hh b/thirdparty/harfbuzz/src/hb-ot-color-cbdt-table.hh index 23fa56c4f6..3246894d39 100644 --- a/thirdparty/harfbuzz/src/hb-ot-color-cbdt-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-color-cbdt-table.hh @@ -67,7 +67,7 @@ _copy_data_to_cbdt (hb_vector_t<char> *cbdt_prime, { unsigned int new_len = cbdt_prime->length + length; if (unlikely (!cbdt_prime->alloc (new_len))) return false; - memcpy (cbdt_prime->arrayZ + cbdt_prime->length, data, length); + hb_memcpy (cbdt_prime->arrayZ + cbdt_prime->length, data, length); cbdt_prime->length = new_len; return true; } @@ -468,13 +468,13 @@ struct IndexSubtableRecord if (unlikely (!c->serializer->check_success (records->resize (records->length + 1)))) return_trace (false); - (*records)[records->length - 1].firstGlyphIndex = 1; - (*records)[records->length - 1].lastGlyphIndex = 0; + records->tail ().firstGlyphIndex = 1; + records->tail ().lastGlyphIndex = 0; bitmap_size_context->size += IndexSubtableRecord::min_size; c->serializer->push (); - if (unlikely (!add_new_subtable (c, bitmap_size_context, &((*records)[records->length - 1]), lookup, base, start))) + if (unlikely (!add_new_subtable (c, bitmap_size_context, &(records->tail ()), lookup, base, start))) { c->serializer->pop_discard (); c->serializer->revert (snap); diff --git a/thirdparty/harfbuzz/src/hb-ot-color-colr-table.hh b/thirdparty/harfbuzz/src/hb-ot-color-colr-table.hh index f01d383bdc..1af9d30937 100644 --- a/thirdparty/harfbuzz/src/hb-ot-color-colr-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-color-colr-table.hh @@ -39,11 +39,7 @@ #define HB_OT_TAG_COLR HB_TAG('C','O','L','R') #ifndef HB_COLRV1_MAX_NESTING_LEVEL -#define HB_COLRV1_MAX_NESTING_LEVEL 100 -#endif - -#ifndef COLRV1_ENABLE_SUBSETTING -#define COLRV1_ENABLE_SUBSETTING 1 +#define HB_COLRV1_MAX_NESTING_LEVEL 16 #endif namespace OT { @@ -188,6 +184,7 @@ struct Variable protected: T value; + public: VarIdx varIdxBase; public: DEFINE_SIZE_STATIC (4 + T::static_size); @@ -196,6 +193,8 @@ struct Variable template <typename T> struct NoVariable { + static constexpr uint32_t varIdxBase = VarIdx::NO_VARIATION; + NoVariable<T>* copy (hb_serialize_context_t *c) const { TRACE_SERIALIZE (this); @@ -358,14 +357,14 @@ struct Affine2x3 return_trace (c->check_struct (this)); } - HBFixed xx; - HBFixed yx; - HBFixed xy; - HBFixed yy; - HBFixed dx; - HBFixed dy; + F16DOT16 xx; + F16DOT16 yx; + F16DOT16 xy; + F16DOT16 yy; + F16DOT16 dx; + F16DOT16 dy; public: - DEFINE_SIZE_STATIC (6 * HBFixed::static_size); + DEFINE_SIZE_STATIC (6 * F16DOT16::static_size); }; struct PaintColrLayers @@ -888,6 +887,11 @@ struct PaintComposite DEFINE_SIZE_STATIC (8); }; +struct ClipBoxData +{ + int xMin, yMin, xMax, yMax; +}; + struct ClipBoxFormat1 { bool sanitize (hb_sanitize_context_t *c) const @@ -896,6 +900,14 @@ struct ClipBoxFormat1 return_trace (c->check_struct (this)); } + void get_clip_box (ClipBoxData &clip_box, const VarStoreInstancer &instancer HB_UNUSED) const + { + clip_box.xMin = xMin; + clip_box.yMin = yMin; + clip_box.xMax = xMax; + clip_box.yMax = yMax; + } + public: HBUINT8 format; /* format = 1(noVar) or 2(Var)*/ FWORD xMin; @@ -906,7 +918,20 @@ struct ClipBoxFormat1 DEFINE_SIZE_STATIC (1 + 4 * FWORD::static_size); }; -struct ClipBoxFormat2 : Variable<ClipBoxFormat1> {}; +struct ClipBoxFormat2 : Variable<ClipBoxFormat1> +{ + void get_clip_box (ClipBoxData &clip_box, const VarStoreInstancer &instancer) const + { + value.get_clip_box(clip_box, instancer); + if (instancer) + { + clip_box.xMin += _hb_roundf (instancer (varIdxBase, 0)); + clip_box.yMin += _hb_roundf (instancer (varIdxBase, 1)); + clip_box.xMax += _hb_roundf (instancer (varIdxBase, 2)); + clip_box.yMax += _hb_roundf (instancer (varIdxBase, 3)); + } + } +}; struct ClipBox { @@ -932,6 +957,28 @@ struct ClipBox } } + bool get_extents (hb_glyph_extents_t *extents, + const VarStoreInstancer &instancer) const + { + ClipBoxData clip_box; + switch (u.format) { + case 1: + u.format1.get_clip_box (clip_box, instancer); + break; + case 2: + u.format2.get_clip_box (clip_box, instancer); + break; + default: + return false; + } + + extents->x_bearing = clip_box.xMin; + extents->y_bearing = clip_box.yMax; + extents->width = clip_box.xMax - clip_box.xMin; + extents->height = clip_box.yMin - clip_box.yMax; + return true; + } + protected: union { HBUINT8 format; /* Format identifier */ @@ -942,6 +989,9 @@ struct ClipBox struct ClipRecord { + int cmp (hb_codepoint_t g) const + { return g < startGlyphID ? -1 : g <= endGlyphID ? 0 : +1; } + ClipRecord* copy (hb_serialize_context_t *c, const void *base) const { TRACE_SERIALIZE (this); @@ -957,6 +1007,13 @@ struct ClipRecord return_trace (c->check_struct (this) && clipBox.sanitize (c, base)); } + bool get_extents (hb_glyph_extents_t *extents, + const void *base, + const VarStoreInstancer &instancer) const + { + return (base+clipBox).get_extents (extents, instancer); + } + public: HBUINT16 startGlyphID; // first gid clip applies to HBUINT16 endGlyphID; // last gid clip applies to, inclusive @@ -964,6 +1021,7 @@ struct ClipRecord public: DEFINE_SIZE_STATIC (7); }; +DECLARE_NULL_NAMESPACE_BYTES (OT, ClipRecord); struct ClipList { @@ -1052,11 +1110,26 @@ struct ClipList bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); + // TODO Make a formatted struct! return_trace (c->check_struct (this) && clips.sanitize (c, this)); } + bool + get_extents (hb_codepoint_t gid, + hb_glyph_extents_t *extents, + const VarStoreInstancer &instancer) const + { + auto *rec = clips.as_array ().bsearch (gid); + if (rec) + { + rec->get_extents (extents, this, instancer); + return true; + } + return false; + } + HBUINT8 format; // Set to 1. - Array32Of<ClipRecord> clips; // Clip records, sorted by startGlyphID + SortedArray32Of<ClipRecord> clips; // Clip records, sorted by startGlyphID public: DEFINE_SIZE_ARRAY_SIZED (5, clips); }; @@ -1359,7 +1432,7 @@ struct COLR (this+baseGlyphsZ).sanitize (c, numBaseGlyphs) && (this+layersZ).sanitize (c, numLayers) && (version == 0 || - (COLRV1_ENABLE_SUBSETTING && version == 1 && + (version == 1 && baseGlyphList.sanitize (c, this) && layerList.sanitize (c, this) && clipList.sanitize (c, this) && @@ -1516,6 +1589,30 @@ struct COLR return_trace (true); } + bool + get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const + { + if (version != 1) + return false; + + VarStoreInstancer instancer (this+varStore, + this+varIdxMap, + hb_array (font->coords, font->num_coords)); + + if ((this+clipList).get_extents (glyph, + extents, + instancer)) + { + extents->x_bearing = font->em_scale_x (extents->x_bearing); + extents->y_bearing = font->em_scale_x (extents->y_bearing); + extents->width = font->em_scale_x (extents->width); + extents->height = font->em_scale_x (extents->height); + return true; + } + + return false; + } + protected: HBUINT16 version; /* Table version number (starts at 0). */ HBUINT16 numBaseGlyphs; /* Number of Base Glyph Records. */ diff --git a/thirdparty/harfbuzz/src/hb-ot-color.cc b/thirdparty/harfbuzz/src/hb-ot-color.cc index a9ae013682..696ca3e17f 100644 --- a/thirdparty/harfbuzz/src/hb-ot-color.cc +++ b/thirdparty/harfbuzz/src/hb-ot-color.cc @@ -295,8 +295,8 @@ hb_ot_color_has_png (hb_face_t *face) * @glyph: a glyph index * * Fetches the PNG image for a glyph. This function takes a font object, not a face object, - * as input. To get an optimally sized PNG blob, the UPEM value must be set on the @font - * object. If UPEM is unset, the blob returned will be the largest PNG available. + * as input. To get an optimally sized PNG blob, the PPEM values must be set on the @font + * object. If PPEM is unset, the blob returned will be the largest PNG available. * * If the glyph has no PNG image, the singleton empty blob is returned. * diff --git a/thirdparty/harfbuzz/src/hb-ot-face-table-list.hh b/thirdparty/harfbuzz/src/hb-ot-face-table-list.hh index c05034b3bb..c9da36c1bb 100644 --- a/thirdparty/harfbuzz/src/hb-ot-face-table-list.hh +++ b/thirdparty/harfbuzz/src/hb-ot-face-table-list.hh @@ -56,9 +56,9 @@ HB_OT_CORE_TABLE (OT, maxp) #if !defined(HB_NO_FACE_COLLECT_UNICODES) || !defined(HB_NO_OT_FONT) HB_OT_ACCELERATOR (OT, cmap) #endif -HB_OT_TABLE (OT, hhea) +HB_OT_CORE_TABLE (OT, hhea) HB_OT_ACCELERATOR (OT, hmtx) -HB_OT_TABLE (OT, OS2) +HB_OT_CORE_TABLE (OT, OS2) #if !defined(HB_NO_OT_FONT_GLYPH_NAMES) || !defined(HB_NO_METRICS) || !defined(HB_NO_STYLE) HB_OT_ACCELERATOR (OT, post) #endif @@ -66,7 +66,7 @@ HB_OT_ACCELERATOR (OT, post) HB_OT_ACCELERATOR (OT, name) #endif #ifndef HB_NO_STYLE -HB_OT_TABLE (OT, STAT) +HB_OT_CORE_TABLE (OT, STAT) #endif #ifndef HB_NO_META HB_OT_ACCELERATOR (OT, meta) @@ -74,9 +74,9 @@ HB_OT_ACCELERATOR (OT, meta) /* Vertical layout. */ #ifndef HB_NO_VERTICAL -HB_OT_TABLE (OT, vhea) +HB_OT_CORE_TABLE (OT, vhea) HB_OT_ACCELERATOR (OT, vmtx) -HB_OT_TABLE (OT, VORG) +HB_OT_CORE_TABLE (OT, VORG) #endif /* TrueType outlines. */ @@ -91,15 +91,15 @@ HB_OT_ACCELERATOR (OT, cff2) /* OpenType variations. */ #ifndef HB_NO_VAR -HB_OT_TABLE (OT, fvar) -HB_OT_TABLE (OT, avar) +HB_OT_CORE_TABLE (OT, fvar) +HB_OT_CORE_TABLE (OT, avar) HB_OT_ACCELERATOR (OT, gvar) -HB_OT_TABLE (OT, MVAR) +HB_OT_CORE_TABLE (OT, MVAR) #endif /* Legacy kern. */ #ifndef HB_NO_OT_KERN -HB_OT_TABLE (OT, kern) +HB_OT_CORE_TABLE (OT, kern) #endif /* OpenType shaping. */ @@ -107,12 +107,12 @@ HB_OT_TABLE (OT, kern) HB_OT_ACCELERATOR (OT, GDEF) HB_OT_ACCELERATOR (OT, GSUB) HB_OT_ACCELERATOR (OT, GPOS) -//HB_OT_TABLE (OT, JSTF) +//HB_OT_CORE_TABLE (OT, JSTF) #endif /* OpenType baseline. */ #ifndef HB_NO_BASE -HB_OT_TABLE (OT, BASE) +HB_OT_CORE_TABLE (OT, BASE) #endif /* AAT shaping. */ @@ -129,8 +129,8 @@ HB_OT_TABLE (AAT, feat) /* OpenType color fonts. */ #ifndef HB_NO_COLOR -HB_OT_TABLE (OT, COLR) -HB_OT_TABLE (OT, CPAL) +HB_OT_CORE_TABLE (OT, COLR) +HB_OT_CORE_TABLE (OT, CPAL) HB_OT_ACCELERATOR (OT, CBDT) HB_OT_ACCELERATOR (OT, sbix) HB_OT_ACCELERATOR (OT, SVG) @@ -138,7 +138,7 @@ HB_OT_ACCELERATOR (OT, SVG) /* OpenType math. */ #ifndef HB_NO_MATH -HB_OT_TABLE (OT, MATH) +HB_OT_CORE_TABLE (OT, MATH) #endif diff --git a/thirdparty/harfbuzz/src/hb-ot-font.cc b/thirdparty/harfbuzz/src/hb-ot-font.cc index c90a65665c..8405103423 100644 --- a/thirdparty/harfbuzz/src/hb-ot-font.cc +++ b/thirdparty/harfbuzz/src/hb-ot-font.cc @@ -40,12 +40,12 @@ #include "hb-ot-cff1-table.hh" #include "hb-ot-cff2-table.hh" #include "hb-ot-hmtx-table.hh" -#include "hb-ot-os2-table.hh" #include "hb-ot-post-table.hh" #include "hb-ot-stat-table.hh" // Just so we compile it; unused otherwise. #include "hb-ot-vorg-table.hh" #include "hb-ot-color-cbdt-table.hh" #include "hb-ot-color-sbix-table.hh" +#include "hb-ot-color-colr-table.hh" /** @@ -349,17 +349,17 @@ hb_ot_get_glyph_extents (hb_font_t *font, #if !defined(HB_NO_OT_FONT_BITMAP) && !defined(HB_NO_COLOR) if (ot_face->sbix->get_extents (font, glyph, extents)) return true; + if (ot_face->CBDT->get_extents (font, glyph, extents)) return true; +#endif +#if !defined(HB_NO_COLOR) + if (ot_face->COLR->get_extents (font, glyph, extents)) return true; #endif if (ot_face->glyf->get_extents (font, glyph, extents)) return true; #ifndef HB_NO_OT_FONT_CFF if (ot_face->cff1->get_extents (font, glyph, extents)) return true; if (ot_face->cff2->get_extents (font, glyph, extents)) return true; #endif -#if !defined(HB_NO_OT_FONT_BITMAP) && !defined(HB_NO_COLOR) - if (ot_face->CBDT->get_extents (font, glyph, extents)) return true; -#endif - // TODO Hook up side-bearings variations. return false; } diff --git a/thirdparty/harfbuzz/src/hb-ot-layout-common.hh b/thirdparty/harfbuzz/src/hb-ot-layout-common.hh index 05916a252c..0f424f5aa6 100644 --- a/thirdparty/harfbuzz/src/hb-ot-layout-common.hh +++ b/thirdparty/harfbuzz/src/hb-ot-layout-common.hh @@ -94,6 +94,19 @@ static bool ClassDef_remap_and_serialize ( hb_sorted_vector_t<hb_pair_t<hb_codepoint_t, hb_codepoint_t>> &glyph_and_klass, /* IN/OUT */ hb_map_t *klass_map /*IN/OUT*/); +struct hb_collect_feature_substitutes_with_var_context_t +{ + const hb_map_t *axes_index_tag_map; + const hb_hashmap_t<hb_tag_t, int> *axes_location; + hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *record_cond_idx_map; + hb_hashmap_t<unsigned, const Feature*> *feature_substitutes_map; + + // not stored in subset_plan + hb_set_t *feature_indices; + bool apply; + unsigned cur_record_idx; + hb_hashmap_t<hb::shared_ptr<hb_map_t>, unsigned> *conditionset_map; +}; struct hb_prune_langsys_context_t { @@ -160,24 +173,40 @@ struct hb_subset_layout_context_t : const hb_map_t *lookup_index_map; const hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> *script_langsys_map; const hb_map_t *feature_index_map; + const hb_hashmap_t<unsigned, const Feature*> *feature_substitutes_map; + hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *feature_record_cond_idx_map; + unsigned cur_script_index; + unsigned cur_feature_var_record_idx; hb_subset_layout_context_t (hb_subset_context_t *c_, - hb_tag_t tag_, - hb_map_t *lookup_map_, - hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> *script_langsys_map_, - hb_map_t *feature_index_map_) : + hb_tag_t tag_) : subset_context (c_), table_tag (tag_), - lookup_index_map (lookup_map_), - script_langsys_map (script_langsys_map_), - feature_index_map (feature_index_map_), cur_script_index (0xFFFFu), + cur_feature_var_record_idx (0u), script_count (0), langsys_count (0), feature_index_count (0), lookup_index_count (0) - {} + { + if (tag_ == HB_OT_TAG_GSUB) + { + lookup_index_map = c_->plan->gsub_lookups; + script_langsys_map = c_->plan->gsub_langsys; + feature_index_map = c_->plan->gsub_features; + feature_substitutes_map = c_->plan->gsub_feature_substitutes_map; + feature_record_cond_idx_map = c_->plan->user_axes_location->is_empty () ? nullptr : c_->plan->gsub_feature_record_cond_idx_map; + } + else + { + lookup_index_map = c_->plan->gpos_lookups; + script_langsys_map = c_->plan->gpos_langsys; + feature_index_map = c_->plan->gpos_features; + feature_substitutes_map = c_->plan->gpos_feature_substitutes_map; + feature_record_cond_idx_map = c_->plan->user_axes_location->is_empty () ? nullptr : c_->plan->gpos_feature_record_cond_idx_map; + } + } private: unsigned script_count; @@ -324,6 +353,31 @@ struct subset_record_array_t const void *base; }; +template<typename OutputArray, typename Arg> +struct subset_record_array_arg_t +{ + subset_record_array_arg_t (hb_subset_layout_context_t *c_, OutputArray* out_, + const void *base_, + Arg &&arg_) : subset_layout_context (c_), + out (out_), base (base_), arg (arg_) {} + + template <typename T> + void + operator () (T&& record) + { + auto snap = subset_layout_context->subset_context->serializer->snapshot (); + bool ret = record.subset (subset_layout_context, base, arg); + if (!ret) subset_layout_context->subset_context->serializer->revert (snap); + else out->len++; + } + + private: + hb_subset_layout_context_t *subset_layout_context; + OutputArray *out; + const void *base; + Arg &&arg; +}; + /* * Helper to subset a RecordList/record array. Subsets each Record in the array and * discards the record if the subset operation returns false. @@ -335,6 +389,13 @@ struct operator () (hb_subset_layout_context_t *c, OutputArray* out, const void *base) const { return subset_record_array_t<OutputArray> (c, out, base); } + + /* Variant with one extra argument passed to subset */ + template<typename OutputArray, typename Arg> + subset_record_array_arg_t<OutputArray, Arg> + operator () (hb_subset_layout_context_t *c, OutputArray* out, + const void *base, Arg &&arg) const + { return subset_record_array_arg_t<OutputArray, Arg> (c, out, base, arg); } } HB_FUNCOBJ (subset_record_array); @@ -417,7 +478,7 @@ struct IndexArray : Array16Of<Index> { if (_count) { - + this->sub_array (start_offset, _count) + + this->as_array ().sub_array (start_offset, _count) | hb_sink (hb_array (_indexes, *_count)) ; } @@ -431,94 +492,6 @@ struct IndexArray : Array16Of<Index> }; -struct Record_sanitize_closure_t { - hb_tag_t tag; - const void *list_base; -}; - -template <typename Type> -struct Record -{ - int cmp (hb_tag_t a) const { return tag.cmp (a); } - - bool subset (hb_subset_layout_context_t *c, const void *base) const - { - TRACE_SUBSET (this); - auto *out = c->subset_context->serializer->embed (this); - if (unlikely (!out)) return_trace (false); - bool ret = out->offset.serialize_subset (c->subset_context, offset, base, c, &tag); - return_trace (ret); - } - - bool sanitize (hb_sanitize_context_t *c, const void *base) const - { - TRACE_SANITIZE (this); - const Record_sanitize_closure_t closure = {tag, base}; - return_trace (c->check_struct (this) && offset.sanitize (c, base, &closure)); - } - - Tag tag; /* 4-byte Tag identifier */ - Offset16To<Type> - offset; /* Offset from beginning of object holding - * the Record */ - public: - DEFINE_SIZE_STATIC (6); -}; - -template <typename Type> -struct RecordArrayOf : SortedArray16Of<Record<Type>> -{ - const Offset16To<Type>& get_offset (unsigned int i) const - { return (*this)[i].offset; } - Offset16To<Type>& get_offset (unsigned int i) - { return (*this)[i].offset; } - const Tag& get_tag (unsigned int i) const - { return (*this)[i].tag; } - unsigned int get_tags (unsigned int start_offset, - unsigned int *record_count /* IN/OUT */, - hb_tag_t *record_tags /* OUT */) const - { - if (record_count) - { - + this->sub_array (start_offset, record_count) - | hb_map (&Record<Type>::tag) - | hb_sink (hb_array (record_tags, *record_count)) - ; - } - return this->len; - } - bool find_index (hb_tag_t tag, unsigned int *index) const - { - return this->bfind (tag, index, HB_NOT_FOUND_STORE, Index::NOT_FOUND_INDEX); - } -}; - -template <typename Type> -struct RecordListOf : RecordArrayOf<Type> -{ - const Type& operator [] (unsigned int i) const - { return this+this->get_offset (i); } - - bool subset (hb_subset_context_t *c, - hb_subset_layout_context_t *l) const - { - TRACE_SUBSET (this); - auto *out = c->serializer->start_embed (*this); - if (unlikely (!c->serializer->extend_min (out))) return_trace (false); - - + this->iter () - | hb_apply (subset_record_array (l, out, this)) - ; - return_trace (true); - } - - bool sanitize (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - return_trace (RecordArrayOf<Type>::sanitize (c, this)); - } -}; - /* https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#size */ struct FeatureParamsSize { @@ -685,7 +658,7 @@ struct FeatureParamsCharacterVariants { if (char_count) { - + characters.sub_array (start_offset, char_count) + + characters.as_array ().sub_array (start_offset, char_count) | hb_sink (hb_array (chars, *char_count)) ; } @@ -801,6 +774,10 @@ struct FeatureParams DEFINE_SIZE_MIN (0); }; +struct Record_sanitize_closure_t { + hb_tag_t tag; + const void *list_base; +}; struct Feature { @@ -897,6 +874,103 @@ struct Feature DEFINE_SIZE_ARRAY_SIZED (4, lookupIndex); }; +template <typename Type> +struct Record +{ + int cmp (hb_tag_t a) const { return tag.cmp (a); } + + bool subset (hb_subset_layout_context_t *c, const void *base, const void *f_sub = nullptr) const + { + TRACE_SUBSET (this); + auto *out = c->subset_context->serializer->embed (this); + if (unlikely (!out)) return_trace (false); + + if (!f_sub) + return_trace (out->offset.serialize_subset (c->subset_context, offset, base, c, &tag)); + + const Feature& f = *reinterpret_cast<const Feature *> (f_sub); + auto *s = c->subset_context->serializer; + s->push (); + + out->offset = 0; + bool ret = f.subset (c->subset_context, c, &tag); + if (ret) + s->add_link (out->offset, s->pop_pack ()); + else + s->pop_discard (); + + return_trace (ret); + } + + bool sanitize (hb_sanitize_context_t *c, const void *base) const + { + TRACE_SANITIZE (this); + const Record_sanitize_closure_t closure = {tag, base}; + return_trace (c->check_struct (this) && offset.sanitize (c, base, &closure)); + } + + Tag tag; /* 4-byte Tag identifier */ + Offset16To<Type> + offset; /* Offset from beginning of object holding + * the Record */ + public: + DEFINE_SIZE_STATIC (6); +}; + +template <typename Type> +struct RecordArrayOf : SortedArray16Of<Record<Type>> +{ + const Offset16To<Type>& get_offset (unsigned int i) const + { return (*this)[i].offset; } + Offset16To<Type>& get_offset (unsigned int i) + { return (*this)[i].offset; } + const Tag& get_tag (unsigned int i) const + { return (*this)[i].tag; } + unsigned int get_tags (unsigned int start_offset, + unsigned int *record_count /* IN/OUT */, + hb_tag_t *record_tags /* OUT */) const + { + if (record_count) + { + + this->as_array ().sub_array (start_offset, record_count) + | hb_map (&Record<Type>::tag) + | hb_sink (hb_array (record_tags, *record_count)) + ; + } + return this->len; + } + bool find_index (hb_tag_t tag, unsigned int *index) const + { + return this->bfind (tag, index, HB_NOT_FOUND_STORE, Index::NOT_FOUND_INDEX); + } +}; + +template <typename Type> +struct RecordListOf : RecordArrayOf<Type> +{ + const Type& operator [] (unsigned int i) const + { return this+this->get_offset (i); } + + bool subset (hb_subset_context_t *c, + hb_subset_layout_context_t *l) const + { + TRACE_SUBSET (this); + auto *out = c->serializer->start_embed (*this); + if (unlikely (!c->serializer->extend_min (out))) return_trace (false); + + + this->iter () + | hb_apply (subset_record_array (l, out, this)) + ; + return_trace (true); + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (RecordArrayOf<Type>::sanitize (c, this)); + } +}; + struct RecordListOfFeature : RecordListOf<Feature> { bool subset (hb_subset_context_t *c, @@ -906,12 +980,19 @@ struct RecordListOfFeature : RecordListOf<Feature> auto *out = c->serializer->start_embed (*this); if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false); - unsigned count = this->len; - + hb_zip (*this, hb_range (count)) - | hb_filter (l->feature_index_map, hb_second) - | hb_map (hb_first) - | hb_apply (subset_record_array (l, out, this)) + + hb_enumerate (*this) + | hb_filter (l->feature_index_map, hb_first) + | hb_apply ([l, out, this] (const hb_pair_t<unsigned, const Record<Feature>&>& _) + { + const Feature *f_sub = nullptr; + const Feature **f = nullptr; + if (l->feature_substitutes_map->has (_.first, &f)) + f_sub = *f; + + subset_record_array (l, out, this, f_sub) (_.second); + }) ; + return_trace (true); } }; @@ -996,7 +1077,7 @@ struct LangSys auto *out = c->serializer->start_embed (*this); if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false); - const unsigned *v; + const uint32_t *v; out->reqFeatureIndex = l->feature_index_map->has (reqFeatureIndex, &v) ? *v : 0xFFFFu; if (!l->visitFeatureIndex (featureIndex.len)) @@ -1064,7 +1145,6 @@ struct Script return; } - unsigned langsys_count = get_lang_sys_count (); if (has_default_lang_sys ()) { //only collect features from non-redundant langsys @@ -1073,24 +1153,24 @@ struct Script d.collect_features (c); } - for (auto _ : + hb_zip (langSys, hb_range (langsys_count))) + for (auto _ : + hb_enumerate (langSys)) { - const LangSys& l = this+_.first.offset; + const LangSys& l = this+_.second.offset; if (!c->visitLangsys (l.get_feature_count ())) continue; if (l.compare (d, c->duplicate_feature_map)) continue; l.collect_features (c); - c->script_langsys_map->get (script_index)->add (_.second); + c->script_langsys_map->get (script_index)->add (_.first); } } else { - for (auto _ : + hb_zip (langSys, hb_range (langsys_count))) + for (auto _ : + hb_enumerate (langSys)) { - const LangSys& l = this+_.first.offset; + const LangSys& l = this+_.second.offset; if (!c->visitLangsys (l.get_feature_count ())) continue; l.collect_features (c); - c->script_langsys_map->get (script_index)->add (_.second); + c->script_langsys_map->get (script_index)->add (_.first); } } } @@ -1128,10 +1208,9 @@ struct Script const hb_set_t *active_langsys = l->script_langsys_map->get (l->cur_script_index); if (active_langsys) { - unsigned count = langSys.len; - + hb_zip (langSys, hb_range (count)) - | hb_filter (active_langsys, hb_second) - | hb_map (hb_first) + + hb_enumerate (langSys) + | hb_filter (active_langsys, hb_first) + | hb_map (hb_second) | hb_filter ([=] (const Record<LangSys>& record) {return l->visitLangSys (); }) | hb_apply (subset_record_array (l, &(out->langSys), this)) ; @@ -1167,12 +1246,11 @@ struct RecordListOfScript : RecordListOf<Script> auto *out = c->serializer->start_embed (*this); if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false); - unsigned count = this->len; - for (auto _ : + hb_zip (*this, hb_range (count))) + for (auto _ : + hb_enumerate (*this)) { auto snap = c->serializer->snapshot (); - l->cur_script_index = _.second; - bool ret = _.first.subset (l, this); + l->cur_script_index = _.first; + bool ret = _.second.subset (l, this); if (!ret) c->serializer->revert (snap); else out->len++; } @@ -1305,7 +1383,13 @@ struct Lookup outMarkFilteringSet = markFilteringSet; } - return_trace (out->subTable.len); + // Always keep the lookup even if it's empty. The rest of layout subsetting depends on lookup + // indices being consistent with those computed during planning. So if an empty lookup is + // discarded during the subset phase it will invalidate all subsequent lookup indices. + // Generally we shouldn't end up with an empty lookup as we pre-prune them during the planning + // phase, but it can happen in rare cases such as when during closure subtable is considered + // degenerate (see: https://github.com/harfbuzz/harfbuzz/issues/3853) + return true; } template <typename TSubTable> @@ -1371,10 +1455,9 @@ struct LookupOffsetList : List16OfOffsetTo<TLookup, OffsetType> auto *out = c->serializer->start_embed (this); if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false); - unsigned count = this->len; - + hb_zip (*this, hb_range (count)) - | hb_filter (l->lookup_index_map, hb_second) - | hb_map (hb_first) + + hb_enumerate (*this) + | hb_filter (l->lookup_index_map, hb_first) + | hb_map (hb_second) | hb_apply (subset_offset_array (c, *out, this)) ; return_trace (true); @@ -1408,7 +1491,7 @@ static bool ClassDef_remap_and_serialize (hb_serialize_context_t *c, klass_map->set (0, 0); unsigned idx = klass_map->has (0) ? 1 : 0; - for (const unsigned k: klasses.iter ()) + for (const unsigned k: klasses) { if (klass_map->has (k)) continue; klass_map->set (k, idx); @@ -1441,6 +1524,11 @@ struct ClassDefFormat1_3 return classValue[(unsigned int) (glyph_id - startGlyph)]; } + unsigned get_population () const + { + return classValue.len; + } + template<typename Iterator, hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))> bool serialize (hb_serialize_context_t *c, @@ -1465,7 +1553,7 @@ struct ClassDefFormat1_3 startGlyph = glyph_min; if (unlikely (!classValue.serialize (c, glyph_count))) return_trace (false); - for (const hb_pair_t<hb_codepoint_t, unsigned> gid_klass_pair : + it) + for (const hb_pair_t<hb_codepoint_t, uint32_t> gid_klass_pair : + it) { unsigned idx = gid_klass_pair.first - glyph_min; classValue[idx] = gid_klass_pair.second; @@ -1556,11 +1644,10 @@ struct ClassDefFormat1_3 bool intersects (const hb_set_t *glyphs) const { - /* TODO Speed up, using hb_set_next()? */ hb_codepoint_t start = startGlyph; hb_codepoint_t end = startGlyph + classValue.len; for (hb_codepoint_t iter = startGlyph - 1; - hb_set_next (glyphs, &iter) && iter < end;) + glyphs->next (&iter) && iter < end;) if (classValue[iter - start]) return true; return false; } @@ -1571,10 +1658,10 @@ struct ClassDefFormat1_3 { /* Match if there's any glyph that is not listed! */ hb_codepoint_t g = HB_SET_VALUE_INVALID; - if (!hb_set_next (glyphs, &g)) return false; + if (!glyphs->next (&g)) return false; if (g < startGlyph) return true; g = startGlyph + count - 1; - if (hb_set_next (glyphs, &g)) return true; + if (glyphs->next (&g)) return true; /* Fall through. */ } /* TODO Speed up, using set overlap first? */ @@ -1592,12 +1679,12 @@ struct ClassDefFormat1_3 if (klass == 0) { unsigned start_glyph = startGlyph; - for (unsigned g = HB_SET_VALUE_INVALID; - hb_set_next (glyphs, &g) && g < start_glyph;) + for (uint32_t g = HB_SET_VALUE_INVALID; + glyphs->next (&g) && g < start_glyph;) intersect_glyphs->add (g); - for (unsigned g = startGlyph + count - 1; - hb_set_next (glyphs, &g);) + for (uint32_t g = startGlyph + count - 1; + glyphs-> next (&g);) intersect_glyphs->add (g); return; @@ -1613,7 +1700,7 @@ struct ClassDefFormat1_3 unsigned start_glyph = startGlyph; unsigned end_glyph = start_glyph + count; for (unsigned g = startGlyph - 1; - hb_set_next (glyphs, &g) && g < end_glyph;) + glyphs->next (&g) && g < end_glyph;) if (classValue.arrayZ[g - start_glyph] == klass) intersect_glyphs->add (g); #endif @@ -1656,6 +1743,14 @@ struct ClassDefFormat2_4 return rangeRecord.bsearch (glyph_id).value; } + unsigned get_population () const + { + typename Types::large_int ret = 0; + for (const auto &r : rangeRecord) + ret += r.get_population (); + return ret > UINT_MAX ? UINT_MAX : (unsigned) ret; + } + template<typename Iterator, hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))> bool serialize (hb_serialize_context_t *c, @@ -1719,28 +1814,45 @@ struct ClassDefFormat2_4 { TRACE_SUBSET (this); const hb_map_t &glyph_map = *c->plan->glyph_map_gsub; + const hb_set_t &glyph_set = *c->plan->glyphset_gsub (); hb_sorted_vector_t<hb_pair_t<hb_codepoint_t, hb_codepoint_t>> glyph_and_klass; hb_set_t orig_klasses; - unsigned num_source_glyphs = c->plan->source->get_num_glyphs (); - unsigned count = rangeRecord.len; - for (unsigned i = 0; i < count; i++) + if (glyph_set.get_population () * hb_bit_storage ((unsigned) rangeRecord.len) / 2 + < get_population ()) { - unsigned klass = rangeRecord[i].value; - if (!klass) continue; - hb_codepoint_t start = rangeRecord[i].first; - hb_codepoint_t end = hb_min (rangeRecord[i].last + 1, num_source_glyphs); - for (hb_codepoint_t g = start; g < end; g++) + for (hb_codepoint_t g : glyph_set) { - hb_codepoint_t new_gid = glyph_map[g]; + unsigned klass = get_class (g); + if (!klass) continue; + hb_codepoint_t new_gid = glyph_map[g]; if (new_gid == HB_MAP_VALUE_INVALID) continue; - if (glyph_filter && !glyph_filter->has (g)) continue; - + if (glyph_filter && !glyph_filter->has (g)) continue; glyph_and_klass.push (hb_pair (new_gid, klass)); orig_klasses.add (klass); } } + else + { + unsigned num_source_glyphs = c->plan->source->get_num_glyphs (); + for (auto &range : rangeRecord) + { + unsigned klass = range.value; + if (!klass) continue; + hb_codepoint_t start = range.first; + hb_codepoint_t end = hb_min (range.last + 1, num_source_glyphs); + for (hb_codepoint_t g = start; g < end; g++) + { + hb_codepoint_t new_gid = glyph_map[g]; + if (new_gid == HB_MAP_VALUE_INVALID) continue; + if (glyph_filter && !glyph_filter->has (g)) continue; + + glyph_and_klass.push (hb_pair (new_gid, klass)); + orig_klasses.add (klass); + } + } + } const hb_set_t& glyphset = *c->plan->glyphset_gsub (); unsigned glyph_count = glyph_filter @@ -1767,10 +1879,9 @@ struct ClassDefFormat2_4 template <typename set_t> bool collect_coverage (set_t *glyphs) const { - unsigned int count = rangeRecord.len; - for (unsigned int i = 0; i < count; i++) - if (rangeRecord[i].value) - if (unlikely (!rangeRecord[i].collect_coverage (glyphs))) + for (auto &range : rangeRecord) + if (range.value) + if (unlikely (!range.collect_coverage (glyphs))) return false; return true; } @@ -1778,11 +1889,10 @@ struct ClassDefFormat2_4 template <typename set_t> bool collect_class (set_t *glyphs, unsigned int klass) const { - unsigned int count = rangeRecord.len; - for (unsigned int i = 0; i < count; i++) + for (auto &range : rangeRecord) { - if (rangeRecord[i].value == klass) - if (unlikely (!rangeRecord[i].collect_coverage (glyphs))) + if (range.value == klass) + if (unlikely (!range.collect_coverage (glyphs))) return false; } return true; @@ -1790,32 +1900,32 @@ struct ClassDefFormat2_4 bool intersects (const hb_set_t *glyphs) const { - /* TODO Speed up, using hb_set_next() and bsearch()? */ - unsigned int count = rangeRecord.len; - for (unsigned int i = 0; i < count; i++) + if (rangeRecord.len > glyphs->get_population () * hb_bit_storage ((unsigned) rangeRecord.len) / 2) { - const auto& range = rangeRecord[i]; - if (range.intersects (*glyphs) && range.value) - return true; + for (hb_codepoint_t g = HB_SET_VALUE_INVALID; glyphs->next (&g);) + if (get_class (g)) + return true; + return false; } - return false; + + return hb_any (+ hb_iter (rangeRecord) + | hb_map ([glyphs] (const RangeRecord<Types> &range) { return range.intersects (*glyphs) && range.value; })); } bool intersects_class (const hb_set_t *glyphs, uint16_t klass) const { - unsigned int count = rangeRecord.len; if (klass == 0) { /* Match if there's any glyph that is not listed! */ hb_codepoint_t g = HB_SET_VALUE_INVALID; - for (unsigned int i = 0; i < count; i++) + for (auto &range : rangeRecord) { - if (!hb_set_next (glyphs, &g)) + if (!glyphs->next (&g)) break; - if (g < rangeRecord[i].first) + if (g < range.first) return true; - g = rangeRecord[i].last; + g = range.last; } - if (g != HB_SET_VALUE_INVALID && hb_set_next (glyphs, &g)) + if (g != HB_SET_VALUE_INVALID && glyphs->next (&g)) return true; /* Fall through. */ } @@ -1827,49 +1937,49 @@ struct ClassDefFormat2_4 void intersected_class_glyphs (const hb_set_t *glyphs, unsigned klass, hb_set_t *intersect_glyphs) const { - unsigned count = rangeRecord.len; if (klass == 0) { hb_codepoint_t g = HB_SET_VALUE_INVALID; - for (unsigned int i = 0; i < count; i++) + for (auto &range : rangeRecord) { - if (!hb_set_next (glyphs, &g)) + if (!glyphs->next (&g)) goto done; - while (g < rangeRecord[i].first) + while (g < range.first) { intersect_glyphs->add (g); - if (!hb_set_next (glyphs, &g)) + if (!glyphs->next (&g)) goto done; } - g = rangeRecord[i].last; + g = range.last; } - while (hb_set_next (glyphs, &g)) + while (glyphs->next (&g)) intersect_glyphs->add (g); done: return; } -#if 0 - /* The following implementation is faster asymptotically, but slower - * in practice. */ - if ((count >> 3) > glyphs->get_population ()) + unsigned count = rangeRecord.len; + if (count > glyphs->get_population () * hb_bit_storage (count) * 8) { for (hb_codepoint_t g = HB_SET_VALUE_INVALID; - hb_set_next (glyphs, &g);) - if (rangeRecord.as_array ().bfind (g)) + glyphs->next (&g);) + { + unsigned i; + if (rangeRecord.as_array ().bfind (g, &i) && + rangeRecord.arrayZ[i].value == klass) intersect_glyphs->add (g); + } return; } -#endif - for (unsigned int i = 0; i < count; i++) + for (auto &range : rangeRecord) { - if (rangeRecord[i].value != klass) continue; + if (range.value != klass) continue; - unsigned end = rangeRecord[i].last + 1; - for (hb_codepoint_t g = rangeRecord[i].first - 1; - hb_set_next (glyphs, &g) && g < end;) + unsigned end = range.last + 1; + for (hb_codepoint_t g = range.first - 1; + glyphs->next (&g) && g < end;) intersect_glyphs->add (g); } } @@ -1878,25 +1988,24 @@ struct ClassDefFormat2_4 { if (glyphs->is_empty ()) return; - unsigned count = rangeRecord.len; hb_codepoint_t g = HB_SET_VALUE_INVALID; - for (unsigned int i = 0; i < count; i++) + for (auto &range : rangeRecord) { - if (!hb_set_next (glyphs, &g)) + if (!glyphs->next (&g)) break; - if (g < rangeRecord[i].first) + if (g < range.first) { intersect_classes->add (0); break; } - g = rangeRecord[i].last; + g = range.last; } - if (g != HB_SET_VALUE_INVALID && hb_set_next (glyphs, &g)) + if (g != HB_SET_VALUE_INVALID && glyphs->next (&g)) intersect_classes->add (0); - for (const auto& record : rangeRecord.iter ()) - if (record.intersects (*glyphs)) - intersect_classes->add (record.value); + for (const auto& range : rangeRecord) + if (range.intersects (*glyphs)) + intersect_classes->add (range.value); } protected: @@ -1911,10 +2020,8 @@ struct ClassDefFormat2_4 struct ClassDef { /* Has interface. */ - static constexpr unsigned SENTINEL = 0; - typedef unsigned int value_t; - value_t operator [] (hb_codepoint_t k) const { return get (k); } - bool has (hb_codepoint_t k) const { return (*this)[k] != SENTINEL; } + unsigned operator [] (hb_codepoint_t k) const { return get (k); } + bool has (hb_codepoint_t k) const { return (*this)[k]; } /* Projection. */ hb_codepoint_t operator () (hb_codepoint_t k) const { return get (k); } @@ -1932,6 +2039,19 @@ struct ClassDef } } + unsigned get_population () const + { + switch (u.format) { + case 1: return u.format1.get_population (); + case 2: return u.format2.get_population (); +#ifndef HB_NO_BEYOND_64K + case 3: return u.format3.get_population (); + case 4: return u.format4.get_population (); +#endif + default:return NOT_COVERED; + } + } + template<typename Iterator, hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))> bool serialize (hb_serialize_context_t *c, Iterator it_with_class_zero) @@ -2249,7 +2369,7 @@ struct VarRegionList { unsigned int backward = region_map.backward (r); if (backward >= region_count) return_trace (false); - memcpy (&axesZ[axisCount * r], &src->axesZ[axisCount * backward], VarRegionAxis::static_size * axisCount); + hb_memcpy (&axesZ[axisCount * r], &src->axesZ[axisCount * backward], VarRegionAxis::static_size * axisCount); } return_trace (true); @@ -2359,21 +2479,26 @@ struct VarData unsigned ri_count = src->regionIndices.len; enum delta_size_t { kZero=0, kNonWord, kWord }; hb_vector_t<delta_size_t> delta_sz; - hb_vector_t<unsigned int> ri_map; /* maps old index to new index */ + hb_vector_t<unsigned int> ri_map; /* maps new index to old index */ delta_sz.resize (ri_count); ri_map.resize (ri_count); unsigned int new_word_count = 0; unsigned int r; + const HBUINT8 *src_delta_bytes = src->get_delta_bytes (); + unsigned src_row_size = src->get_row_size (); + unsigned src_word_count = src->wordCount (); + bool src_long_words = src->longWords (); + bool has_long = false; - if (src->longWords ()) + if (src_long_words) { - for (r = 0; r < ri_count; r++) + for (r = 0; r < src_word_count; r++) { for (unsigned int i = 0; i < inner_map.get_next_value (); i++) { unsigned int old = inner_map.backward (i); - int32_t delta = src->get_item_delta (old, r); + int32_t delta = src->get_item_delta_fast (old, r, src_delta_bytes, src_row_size); if (delta < -65536 || 65535 < delta) { has_long = true; @@ -2387,11 +2512,13 @@ struct VarData signed max_threshold = has_long ? +65535 : +127; for (r = 0; r < ri_count; r++) { + bool short_circuit = src_long_words == has_long && src_word_count <= r; + delta_sz[r] = kZero; for (unsigned int i = 0; i < inner_map.get_next_value (); i++) { unsigned int old = inner_map.backward (i); - int32_t delta = src->get_item_delta (old, r); + int32_t delta = src->get_item_delta_fast (old, r, src_delta_bytes, src_row_size); if (delta < min_threshold || max_threshold < delta) { delta_sz[r] = kWord; @@ -2399,7 +2526,11 @@ struct VarData break; } else if (delta != 0) + { delta_sz[r] = kNonWord; + if (short_circuit) + break; + } } } @@ -2409,7 +2540,8 @@ struct VarData for (r = 0; r < ri_count; r++) if (delta_sz[r]) { - ri_map[r] = (delta_sz[r] == kWord)? word_index++ : non_word_index++; + unsigned new_r = (delta_sz[r] == kWord)? word_index++ : non_word_index++; + ri_map[new_r] = r; new_ri_count++; } @@ -2419,14 +2551,20 @@ struct VarData if (unlikely (!c->extend (this))) return_trace (false); - for (r = 0; r < ri_count; r++) - if (delta_sz[r]) regionIndices[ri_map[r]] = region_map[src->regionIndices[r]]; + for (r = 0; r < new_ri_count; r++) + regionIndices[r] = region_map[src->regionIndices[ri_map[r]]]; - for (unsigned int i = 0; i < itemCount; i++) + HBUINT8 *delta_bytes = get_delta_bytes (); + unsigned row_size = get_row_size (); + unsigned count = itemCount; + for (unsigned int i = 0; i < count; i++) { - unsigned int old = inner_map.backward (i); - for (unsigned int r = 0; r < ri_count; r++) - if (delta_sz[r]) set_item_delta (i, ri_map[r], src->get_item_delta (old, r)); + unsigned int old = inner_map.backward (i); + for (unsigned int r = 0; r < new_ri_count; r++) + set_item_delta_fast (i, r, + src->get_item_delta_fast (old, ri_map[r], + src_delta_bytes, src_row_size), + delta_bytes, row_size); } return_trace (true); @@ -2434,12 +2572,15 @@ struct VarData void collect_region_refs (hb_set_t ®ion_indices, const hb_inc_bimap_t &inner_map) const { + const HBUINT8 *delta_bytes = get_delta_bytes (); + unsigned row_size = get_row_size (); + for (unsigned int r = 0; r < regionIndices.len; r++) { - unsigned int region = regionIndices[r]; + unsigned int region = regionIndices.arrayZ[r]; if (region_indices.has (region)) continue; for (unsigned int i = 0; i < inner_map.get_next_value (); i++) - if (get_item_delta (inner_map.backward (i), r) != 0) + if (get_item_delta_fast (inner_map.backward (i), r, delta_bytes, row_size) != 0) { region_indices.add (region); break; @@ -2454,10 +2595,12 @@ struct VarData HBUINT8 *get_delta_bytes () { return &StructAfter<HBUINT8> (regionIndices); } - int32_t get_item_delta (unsigned int item, unsigned int region) const + int32_t get_item_delta_fast (unsigned int item, unsigned int region, + const HBUINT8 *delta_bytes, unsigned row_size) const { - if ( item >= itemCount || unlikely (region >= regionIndices.len)) return 0; - const HBINT8 *p = (const HBINT8 *) get_delta_bytes () + item * get_row_size (); + if (unlikely (item >= itemCount || region >= regionIndices.len)) return 0; + + const HBINT8 *p = (const HBINT8 *) delta_bytes + item * row_size; unsigned word_count = wordCount (); bool is_long = longWords (); if (is_long) @@ -2475,10 +2618,17 @@ struct VarData return (p + HBINT16::static_size * word_count)[region - word_count]; } } + int32_t get_item_delta (unsigned int item, unsigned int region) const + { + return get_item_delta_fast (item, region, + get_delta_bytes (), + get_row_size ()); + } - void set_item_delta (unsigned int item, unsigned int region, int32_t delta) + void set_item_delta_fast (unsigned int item, unsigned int region, int32_t delta, + HBUINT8 *delta_bytes, unsigned row_size) { - HBINT8 *p = (HBINT8 *)get_delta_bytes () + item * get_row_size (); + HBINT8 *p = (HBINT8 *) delta_bytes + item * row_size; unsigned word_count = wordCount (); bool is_long = longWords (); if (is_long) @@ -2496,6 +2646,12 @@ struct VarData (p + HBINT16::static_size * word_count)[region - word_count] = delta; } } + void set_item_delta (unsigned int item, unsigned int region, int32_t delta) + { + set_item_delta_fast (item, region, delta, + get_delta_bytes (), + get_row_size ()); + } bool longWords () const { return wordSizeCount & 0x8000u /* LONG_WORDS */; } unsigned wordCount () const { return wordSizeCount & 0x7FFFu /* WORD_DELTA_COUNT_MASK */; } @@ -2559,6 +2715,14 @@ struct VariationStore unsigned int inner = index & 0xFFFF; return get_delta (outer, inner, coords, coord_count, cache); } + float get_delta (unsigned int index, + hb_array_t<int> coords, + VarRegionList::cache_t *cache = nullptr) const + { + return get_delta (index, + coords.arrayZ, coords.length, + cache); + } bool sanitize (hb_sanitize_context_t *c) const { @@ -2692,6 +2856,13 @@ struct VariationStore /* * Feature Variations */ +enum Cond_with_Var_flag_t +{ + KEEP_COND_WITH_VAR = 0, + DROP_COND_WITH_VAR = 1, + DROP_RECORD_WITH_VAR = 2, + MEM_ERR_WITH_VAR = 3, +}; struct ConditionFormat1 { @@ -2702,10 +2873,52 @@ struct ConditionFormat1 TRACE_SUBSET (this); auto *out = c->serializer->embed (this); if (unlikely (!out)) return_trace (false); - return_trace (true); + + const hb_map_t *index_map = c->plan->axes_index_map; + if (index_map->is_empty ()) return_trace (true); + + if (!index_map->has (axisIndex)) + return_trace (false); + + return_trace (c->serializer->check_assign (out->axisIndex, index_map->get (axisIndex), + HB_SERIALIZE_ERROR_INT_OVERFLOW)); } private: + Cond_with_Var_flag_t keep_with_variations (hb_collect_feature_substitutes_with_var_context_t *c, + hb_map_t *condition_map /* OUT */) const + { + //invalid axis index, drop the entire record + if (!c->axes_index_tag_map->has (axisIndex)) + return DROP_RECORD_WITH_VAR; + + hb_tag_t axis_tag = c->axes_index_tag_map->get (axisIndex); + + //axis not pinned, keep the condition + if (!c->axes_location->has (axis_tag)) + { + // add axisIndex->value into the hashmap so we can check if the record is + // unique with variations + int16_t min_val = filterRangeMinValue; + int16_t max_val = filterRangeMaxValue; + hb_codepoint_t val = (max_val << 16) + min_val; + + condition_map->set (axisIndex, val); + return KEEP_COND_WITH_VAR; + } + + //axis pinned, check if condition is met + //TODO: add check for axis Ranges + int v = c->axes_location->get (axis_tag); + + //condition not met, drop the entire record + if (v < filterRangeMinValue || v > filterRangeMaxValue) + return DROP_RECORD_WITH_VAR; + + //axis pinned and condition met, drop the condition + return DROP_COND_WITH_VAR; + } + bool evaluate (const int *coords, unsigned int coord_len) const { int coord = axisIndex < coord_len ? coords[axisIndex] : 0; @@ -2737,6 +2950,15 @@ struct Condition } } + Cond_with_Var_flag_t keep_with_variations (hb_collect_feature_substitutes_with_var_context_t *c, + hb_map_t *condition_map /* OUT */) const + { + switch (u.format) { + case 1: return u.format1.keep_with_variations (c, condition_map); + default:return KEEP_COND_WITH_VAR; + } + } + template <typename context_t, typename ...Ts> typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const { @@ -2778,15 +3000,65 @@ struct ConditionSet return true; } - bool subset (hb_subset_context_t *c) const + Cond_with_Var_flag_t keep_with_variations (hb_collect_feature_substitutes_with_var_context_t *c) const + { + hb_map_t *condition_map = hb_map_create (); + if (unlikely (!condition_map)) return MEM_ERR_WITH_VAR; + hb::shared_ptr<hb_map_t> p {condition_map}; + + hb_set_t *cond_set = hb_set_create (); + if (unlikely (!cond_set)) return MEM_ERR_WITH_VAR; + hb::shared_ptr<hb_set_t> s {cond_set}; + + unsigned num_kept_cond = 0, cond_idx = 0; + for (const auto& offset : conditions) + { + Cond_with_Var_flag_t ret = (this+offset).keep_with_variations (c, condition_map); + // one condition is not met, drop the entire record + if (ret == DROP_RECORD_WITH_VAR) + return DROP_RECORD_WITH_VAR; + + // axis not pinned, keep this condition + if (ret == KEEP_COND_WITH_VAR) + { + cond_set->add (cond_idx); + num_kept_cond++; + } + cond_idx++; + } + + // all conditions met + if (num_kept_cond == 0) return DROP_COND_WITH_VAR; + + //check if condition_set is unique with variations + if (c->conditionset_map->has (p)) + //duplicate found, drop the entire record + return DROP_RECORD_WITH_VAR; + + c->conditionset_map->set (p, 1); + c->record_cond_idx_map->set (c->cur_record_idx, s); + + return KEEP_COND_WITH_VAR; + } + + bool subset (hb_subset_context_t *c, + hb_subset_layout_context_t *l) const { TRACE_SUBSET (this); auto *out = c->serializer->start_embed (this); if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false); - + conditions.iter () - | hb_apply (subset_offset_array (c, out->conditions, this)) - ; + hb_set_t *retained_cond_set = nullptr; + if (l->feature_record_cond_idx_map != nullptr) + retained_cond_set = l->feature_record_cond_idx_map->get (l->cur_feature_var_record_idx); + + unsigned int count = conditions.len; + for (unsigned int i = 0; i < count; i++) + { + if (retained_cond_set != nullptr && !retained_cond_set->has (i)) + continue; + subset_offset_array (c, out->conditions, this) (conditions[i]); + } return_trace (bool (out->conditions)); } @@ -2820,10 +3092,19 @@ struct FeatureTableSubstitutionRecord feature_indexes->add (featureIndex); } + void collect_feature_substitutes_with_variations (hb_hashmap_t<unsigned, const Feature*> *feature_substitutes_map, + const hb_set_t *feature_indices, + const void *base) const + { + if (feature_indices->has (featureIndex)) + feature_substitutes_map->set (featureIndex, &(base+feature)); + } + bool subset (hb_subset_layout_context_t *c, const void *base) const { TRACE_SUBSET (this); - if (!c->feature_index_map->has (featureIndex)) { + if (!c->feature_index_map->has (featureIndex) || + c->feature_substitutes_map->has (featureIndex)) { // Feature that is being substituted is not being retained, so we don't // need this. return_trace (false); @@ -2865,10 +3146,16 @@ struct FeatureTableSubstitution } void collect_lookups (const hb_set_t *feature_indexes, + const hb_hashmap_t<unsigned, const Feature*> *feature_substitutes_map, hb_set_t *lookup_indexes /* OUT */) const { + hb_iter (substitutions) | hb_filter (feature_indexes, &FeatureTableSubstitutionRecord::featureIndex) + | hb_filter ([feature_substitutes_map] (const FeatureTableSubstitutionRecord& record) + { + if (feature_substitutes_map == nullptr) return true; + return !feature_substitutes_map->has (record.featureIndex); + }) | hb_apply ([this, lookup_indexes] (const FeatureTableSubstitutionRecord& r) { r.collect_lookups (this, lookup_indexes); }) ; @@ -2890,6 +3177,12 @@ struct FeatureTableSubstitution return false; } + void collect_feature_substitutes_with_variations (hb_collect_feature_substitutes_with_var_context_t *c) const + { + for (const FeatureTableSubstitutionRecord& record : substitutions) + record.collect_feature_substitutes_with_variations (c->feature_substitutes_map, c->feature_indices, this); + } + bool subset (hb_subset_context_t *c, hb_subset_layout_context_t *l) const { @@ -2929,9 +3222,10 @@ struct FeatureVariationRecord void collect_lookups (const void *base, const hb_set_t *feature_indexes, + const hb_hashmap_t<unsigned, const Feature*> *feature_substitutes_map, hb_set_t *lookup_indexes /* OUT */) const { - return (base+substitutions).collect_lookups (feature_indexes, lookup_indexes); + return (base+substitutions).collect_lookups (feature_indexes, feature_substitutes_map, lookup_indexes); } void closure_features (const void *base, @@ -2946,13 +3240,25 @@ struct FeatureVariationRecord return (base+substitutions).intersects_features (feature_index_map); } + void collect_feature_substitutes_with_variations (hb_collect_feature_substitutes_with_var_context_t *c, + const void *base) const + { + // ret == 1, all conditions met + if ((base+conditions).keep_with_variations (c) == DROP_COND_WITH_VAR && + c->apply) + { + (base+substitutions).collect_feature_substitutes_with_variations (c); + c->apply = false; // set variations only once + } + } + bool subset (hb_subset_layout_context_t *c, const void *base) const { TRACE_SUBSET (this); auto *out = c->subset_context->serializer->embed (this); if (unlikely (!out)) return_trace (false); - out->conditions.serialize_subset (c->subset_context, conditions, base); + out->conditions.serialize_subset (c->subset_context, conditions, base, c); out->substitutions.serialize_subset (c->subset_context, substitutions, base, c); return_trace (true); @@ -3002,6 +3308,16 @@ struct FeatureVariations return (this+record.substitutions).find_substitute (feature_index); } + void collect_feature_substitutes_with_variations (hb_collect_feature_substitutes_with_var_context_t *c) const + { + unsigned int count = varRecords.len; + for (unsigned int i = 0; i < count; i++) + { + c->cur_record_idx = i; + varRecords[i].collect_feature_substitutes_with_variations (c, this); + } + } + FeatureVariations* copy (hb_serialize_context_t *c) const { TRACE_SERIALIZE (this); @@ -3009,17 +3325,25 @@ struct FeatureVariations } void collect_lookups (const hb_set_t *feature_indexes, + const hb_hashmap_t<unsigned, const Feature*> *feature_substitutes_map, hb_set_t *lookup_indexes /* OUT */) const { for (const FeatureVariationRecord& r : varRecords) - r.collect_lookups (this, feature_indexes, lookup_indexes); + r.collect_lookups (this, feature_indexes, feature_substitutes_map, lookup_indexes); } void closure_features (const hb_map_t *lookup_indexes, + const hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *feature_record_cond_idx_map, hb_set_t *feature_indexes /* OUT */) const { - for (const FeatureVariationRecord& record : varRecords) - record.closure_features (this, lookup_indexes, feature_indexes); + unsigned int count = varRecords.len; + for (unsigned int i = 0; i < count; i++) + { + if (feature_record_cond_idx_map != nullptr && + !feature_record_cond_idx_map->has (i)) + continue; + varRecords[i].closure_features (this, lookup_indexes, feature_indexes); + } } bool subset (hb_subset_context_t *c, @@ -3041,7 +3365,13 @@ struct FeatureVariations } unsigned count = (unsigned) (keep_up_to + 1); - for (unsigned i = 0; i < count; i++) { + for (unsigned i = 0; i < count; i++) + { + if (l->feature_record_cond_idx_map != nullptr && + !l->feature_record_cond_idx_map->has (i)) + continue; + + l->cur_feature_var_record_idx = i; subset_record_array (l, &(out->varRecords), this) (varRecords[i]); } return_trace (bool (out->varRecords)); @@ -3171,17 +3501,16 @@ struct VariationDevice { TRACE_SERIALIZE (this); if (!layout_variation_idx_delta_map) return_trace (nullptr); - auto snap = c->snapshot (); + + hb_pair_t<unsigned, int> *v; + if (!layout_variation_idx_delta_map->has (varIdx, &v)) + return_trace (nullptr); + + c->start_zerocopy (this->static_size); auto *out = c->embed (this); if (unlikely (!out)) return_trace (nullptr); - /* TODO Just get() and bail if NO_VARIATION. Needs to setup the map to return that. */ - if (!layout_variation_idx_delta_map->has (varIdx)) - { - c->revert (snap); - return_trace (nullptr); - } - unsigned new_idx = hb_first (layout_variation_idx_delta_map->get (varIdx)); + unsigned new_idx = hb_first (*v); out->varIdx = new_idx; return_trace (out); } diff --git a/thirdparty/harfbuzz/src/hb-ot-layout-gdef-table.hh b/thirdparty/harfbuzz/src/hb-ot-layout-gdef-table.hh index 22925fdfa9..a84edef162 100644 --- a/thirdparty/harfbuzz/src/hb-ot-layout-gdef-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-layout-gdef-table.hh @@ -73,7 +73,7 @@ struct AttachList if (point_count) { - + points.sub_array (start_offset, point_count) + + points.as_array ().sub_array (start_offset, point_count) | hb_sink (hb_array (point_array, *point_count)) ; } @@ -322,7 +322,7 @@ struct LigGlyph { if (caret_count) { - + carets.sub_array (start_offset, caret_count) + + carets.as_array ().sub_array (start_offset, caret_count) | hb_map (hb_add (this)) | hb_map ([&] (const CaretValue &value) { return value.get_caret_value (font, direction, glyph_id, var_store); }) | hb_sink (hb_array (caret_array, *caret_count)) diff --git a/thirdparty/harfbuzz/src/hb-ot-layout-gsubgpos.hh b/thirdparty/harfbuzz/src/hb-ot-layout-gsubgpos.hh index c15a42b0f1..04ccefd108 100644 --- a/thirdparty/harfbuzz/src/hb-ot-layout-gsubgpos.hh +++ b/thirdparty/harfbuzz/src/hb-ot-layout-gsubgpos.hh @@ -100,8 +100,8 @@ struct hb_closure_context_t : bool is_lookup_done (unsigned int lookup_index) { - if (done_lookups_glyph_count->in_error () || - done_lookups_glyph_set->in_error ()) + if (unlikely (done_lookups_glyph_count->in_error () || + done_lookups_glyph_set->in_error ())) return true; /* Have we visited this lookup with the current set of glyphs? */ @@ -535,7 +535,12 @@ struct hb_ot_apply_context_t : bool next (unsigned *unsafe_to = nullptr) { assert (num_items > 0); - while (idx + num_items < end) + /* The alternate condition below is faster at string boundaries, + * but produces subpar "unsafe-to-concat" values. */ + signed stop = (signed) end - (signed) num_items; + if (c->buffer->flags & HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT) + stop = (signed) end - 1; + while ((signed) idx < stop) { idx++; hb_glyph_info_t &info = c->buffer->info[idx]; @@ -568,7 +573,12 @@ struct hb_ot_apply_context_t : bool prev (unsigned *unsafe_from = nullptr) { assert (num_items > 0); - while (idx > num_items - 1) + /* The alternate condition below is faster at string boundaries, + * but produces subpar "unsafe-to-concat" values. */ + unsigned stop = num_items - 1; + if (c->buffer->flags & HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT) + stop = 1 - 1; + while (idx > stop) { idx--; hb_glyph_info_t &info = c->buffer->out_info[idx]; @@ -672,6 +682,7 @@ struct hb_ot_apply_context_t : const GDEF &gdef; const VariationStore &var_store; VariationStore::cache_t *var_store_cache; + hb_set_digest_t digest; hb_direction_t direction; hb_mask_t lookup_mask = 1; @@ -707,6 +718,7 @@ struct hb_ot_apply_context_t : nullptr #endif ), + digest (buffer_->digest ()), direction (buffer_->props.direction), has_glyph_classes (gdef.has_glyph_classes ()) { init_iters (); } @@ -781,8 +793,10 @@ struct hb_ot_apply_context_t : void _set_glyph_class (hb_codepoint_t glyph_index, unsigned int class_guess = 0, bool ligature = false, - bool component = false) const + bool component = false) { + digest.add (glyph_index); + if (new_syllables != (unsigned) -1) buffer->cur().syllable() = new_syllables; @@ -815,24 +829,24 @@ struct hb_ot_apply_context_t : _hb_glyph_info_set_glyph_props (&buffer->cur(), props); } - void replace_glyph (hb_codepoint_t glyph_index) const + void replace_glyph (hb_codepoint_t glyph_index) { _set_glyph_class (glyph_index); (void) buffer->replace_glyph (glyph_index); } - void replace_glyph_inplace (hb_codepoint_t glyph_index) const + void replace_glyph_inplace (hb_codepoint_t glyph_index) { _set_glyph_class (glyph_index); buffer->cur().codepoint = glyph_index; } void replace_glyph_with_ligature (hb_codepoint_t glyph_index, - unsigned int class_guess) const + unsigned int class_guess) { _set_glyph_class (glyph_index, class_guess, true); (void) buffer->replace_glyph (glyph_index); } void output_glyph_for_component (hb_codepoint_t glyph_index, - unsigned int class_guess) const + unsigned int class_guess) { _set_glyph_class (glyph_index, class_guess, false, true); (void) buffer->output_glyph (glyph_index); @@ -844,7 +858,7 @@ struct hb_accelerate_subtables_context_t : hb_dispatch_context_t<hb_accelerate_subtables_context_t> { template <typename Type> - static inline bool apply_to (const void *obj, OT::hb_ot_apply_context_t *c) + static inline bool apply_to (const void *obj, hb_ot_apply_context_t *c) { const Type *typed_obj = (const Type *) obj; return typed_obj->apply (c); @@ -852,30 +866,30 @@ struct hb_accelerate_subtables_context_t : #ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE template <typename T> - static inline auto apply_cached_ (const T *obj, OT::hb_ot_apply_context_t *c, hb_priority<1>) HB_RETURN (bool, obj->apply (c, true) ) + static inline auto apply_cached_ (const T *obj, hb_ot_apply_context_t *c, hb_priority<1>) HB_RETURN (bool, obj->apply (c, true) ) template <typename T> - static inline auto apply_cached_ (const T *obj, OT::hb_ot_apply_context_t *c, hb_priority<0>) HB_RETURN (bool, obj->apply (c) ) + static inline auto apply_cached_ (const T *obj, hb_ot_apply_context_t *c, hb_priority<0>) HB_RETURN (bool, obj->apply (c) ) template <typename Type> - static inline bool apply_cached_to (const void *obj, OT::hb_ot_apply_context_t *c) + static inline bool apply_cached_to (const void *obj, hb_ot_apply_context_t *c) { const Type *typed_obj = (const Type *) obj; return apply_cached_ (typed_obj, c, hb_prioritize); } template <typename T> - static inline auto cache_func_ (const T *obj, OT::hb_ot_apply_context_t *c, bool enter, hb_priority<1>) HB_RETURN (bool, obj->cache_func (c, enter) ) + static inline auto cache_func_ (const T *obj, hb_ot_apply_context_t *c, bool enter, hb_priority<1>) HB_RETURN (bool, obj->cache_func (c, enter) ) template <typename T> - static inline bool cache_func_ (const T *obj, OT::hb_ot_apply_context_t *c, bool enter, hb_priority<0>) { return false; } + static inline bool cache_func_ (const T *obj, hb_ot_apply_context_t *c, bool enter, hb_priority<0>) { return false; } template <typename Type> - static inline bool cache_func_to (const void *obj, OT::hb_ot_apply_context_t *c, bool enter) + static inline bool cache_func_to (const void *obj, hb_ot_apply_context_t *c, bool enter) { const Type *typed_obj = (const Type *) obj; return cache_func_ (typed_obj, c, enter, hb_prioritize); } #endif - typedef bool (*hb_apply_func_t) (const void *obj, OT::hb_ot_apply_context_t *c); - typedef bool (*hb_cache_func_t) (const void *obj, OT::hb_ot_apply_context_t *c, bool enter); + typedef bool (*hb_apply_func_t) (const void *obj, hb_ot_apply_context_t *c); + typedef bool (*hb_cache_func_t) (const void *obj, hb_ot_apply_context_t *c, bool enter); struct hb_applicable_t { @@ -901,20 +915,20 @@ struct hb_accelerate_subtables_context_t : obj_.get_coverage ().collect_coverage (&digest); } - bool apply (OT::hb_ot_apply_context_t *c) const + bool apply (hb_ot_apply_context_t *c) const { return digest.may_have (c->buffer->cur().codepoint) && apply_func (obj, c); } #ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE - bool apply_cached (OT::hb_ot_apply_context_t *c) const + bool apply_cached (hb_ot_apply_context_t *c) const { return digest.may_have (c->buffer->cur().codepoint) && apply_cached_func (obj, c); } - bool cache_enter (OT::hb_ot_apply_context_t *c) const + bool cache_enter (hb_ot_apply_context_t *c) const { return cache_func (obj, c, true); } - void cache_leave (OT::hb_ot_apply_context_t *c) const + void cache_leave (hb_ot_apply_context_t *c) const { cache_func (obj, c, false); } @@ -988,8 +1002,8 @@ struct hb_accelerate_subtables_context_t : }; -typedef bool (*intersects_func_t) (const hb_set_t *glyphs, unsigned value, const void *data); -typedef void (*intersected_glyphs_func_t) (const hb_set_t *glyphs, const void *data, unsigned value, hb_set_t *intersected_glyphs); +typedef bool (*intersects_func_t) (const hb_set_t *glyphs, unsigned value, const void *data, void *cache); +typedef void (*intersected_glyphs_func_t) (const hb_set_t *glyphs, const void *data, unsigned value, hb_set_t *intersected_glyphs, void *cache); typedef void (*collect_glyphs_func_t) (hb_set_t *glyphs, unsigned value, const void *data); typedef bool (*match_func_t) (hb_glyph_info_t &info, unsigned value, const void *data); @@ -1012,16 +1026,25 @@ struct ChainContextApplyFuncs }; -static inline bool intersects_glyph (const hb_set_t *glyphs, unsigned value, const void *data HB_UNUSED) +static inline bool intersects_glyph (const hb_set_t *glyphs, unsigned value, const void *data HB_UNUSED, void *cache HB_UNUSED) { return glyphs->has (value); } -static inline bool intersects_class (const hb_set_t *glyphs, unsigned value, const void *data) +static inline bool intersects_class (const hb_set_t *glyphs, unsigned value, const void *data, void *cache) { const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data); - return class_def.intersects_class (glyphs, value); + hb_map_t *map = (hb_map_t *) cache; + + hb_codepoint_t *cached_v; + if (map->has (value, &cached_v)) + return *cached_v; + + bool v = class_def.intersects_class (glyphs, value); + map->set (value, v); + + return v; } -static inline bool intersects_coverage (const hb_set_t *glyphs, unsigned value, const void *data) +static inline bool intersects_coverage (const hb_set_t *glyphs, unsigned value, const void *data, void *cache HB_UNUSED) { Offset16To<Coverage> coverage; coverage = value; @@ -1029,17 +1052,36 @@ static inline bool intersects_coverage (const hb_set_t *glyphs, unsigned value, } -static inline void intersected_glyph (const hb_set_t *glyphs HB_UNUSED, const void *data, unsigned value, hb_set_t *intersected_glyphs) +static inline void intersected_glyph (const hb_set_t *glyphs HB_UNUSED, const void *data, unsigned value, hb_set_t *intersected_glyphs, HB_UNUSED void *cache) { unsigned g = reinterpret_cast<const HBUINT16 *>(data)[value]; intersected_glyphs->add (g); } -static inline void intersected_class_glyphs (const hb_set_t *glyphs, const void *data, unsigned value, hb_set_t *intersected_glyphs) + +using intersected_class_cache_t = hb_hashmap_t<unsigned, hb_set_t>; + +static inline void intersected_class_glyphs (const hb_set_t *glyphs, const void *data, unsigned value, hb_set_t *intersected_glyphs, void *cache) { const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data); - class_def.intersected_class_glyphs (glyphs, value, intersected_glyphs); + + intersected_class_cache_t *map = (intersected_class_cache_t *) cache; + + hb_set_t *cached_v; + if (map->has (value, &cached_v)) + { + intersected_glyphs->union_ (*cached_v); + return; + } + + hb_set_t v; + class_def.intersected_class_glyphs (glyphs, value, &v); + + intersected_glyphs->union_ (v); + + map->set (value, std::move (v)); } -static inline void intersected_coverage_glyphs (const hb_set_t *glyphs, const void *data, unsigned value, hb_set_t *intersected_glyphs) + +static inline void intersected_coverage_glyphs (const hb_set_t *glyphs, const void *data, unsigned value, hb_set_t *intersected_glyphs, HB_UNUSED void *cache) { Offset16To<Coverage> coverage; coverage = value; @@ -1052,10 +1094,11 @@ static inline bool array_is_subset_of (const hb_set_t *glyphs, unsigned int count, const HBUINT values[], intersects_func_t intersects_func, - const void *intersects_data) + const void *intersects_data, + void *cache) { for (const auto &_ : + hb_iter (values, count)) - if (!intersects_func (glyphs, _, intersects_data)) return false; + if (!intersects_func (glyphs, _, intersects_data, cache)) return false; return true; } @@ -1492,7 +1535,8 @@ static void context_closure_recurse_lookups (hb_closure_context_t *c, unsigned value, ContextFormat context_format, const void *data, - intersected_glyphs_func_t intersected_glyphs_func) + intersected_glyphs_func_t intersected_glyphs_func, + void *cache) { hb_set_t *covered_seq_indicies = hb_set_create (); for (unsigned int i = 0; i < lookupCount; i++) @@ -1513,7 +1557,7 @@ static void context_closure_recurse_lookups (hb_closure_context_t *c, pos_glyphs.add (value); break; case ContextFormat::ClassBasedContext: - intersected_glyphs_func (&c->parent_active_glyphs (), data, value, &pos_glyphs); + intersected_glyphs_func (&c->parent_active_glyphs (), data, value, &pos_glyphs, cache); break; case ContextFormat::CoverageBasedContext: pos_glyphs.set (c->parent_active_glyphs ()); @@ -1530,7 +1574,7 @@ static void context_closure_recurse_lookups (hb_closure_context_t *c, input_value = input[seqIndex - 1]; } - intersected_glyphs_func (c->glyphs, input_data, input_value, &pos_glyphs); + intersected_glyphs_func (c->glyphs, input_data, input_value, &pos_glyphs, cache); } } @@ -1710,6 +1754,8 @@ struct ContextClosureLookupContext ContextClosureFuncs funcs; ContextFormat context_format; const void *intersects_data; + void *intersects_cache; + void *intersected_glyphs_cache; }; struct ContextCollectGlyphsLookupContext @@ -1732,7 +1778,9 @@ static inline bool context_intersects (const hb_set_t *glyphs, { return array_is_subset_of (glyphs, inputCount ? inputCount - 1 : 0, input, - lookup_context.funcs.intersects, lookup_context.intersects_data); + lookup_context.funcs.intersects, + lookup_context.intersects_data, + lookup_context.intersects_cache); } template <typename HBUINT> @@ -1753,7 +1801,8 @@ static inline void context_closure_lookup (hb_closure_context_t *c, value, lookup_context.context_format, lookup_context.intersects_data, - lookup_context.funcs.intersected_glyphs); + lookup_context.funcs.intersected_glyphs, + lookup_context.intersected_glyphs_cache); } template <typename HBUINT> @@ -1777,7 +1826,7 @@ static inline bool context_would_apply_lookup (hb_would_apply_context_t *c, const HBUINT input[], /* Array of input values--start with second glyph */ unsigned int lookupCount HB_UNUSED, const LookupRecord lookupRecord[] HB_UNUSED, - ContextApplyLookupContext &lookup_context) + const ContextApplyLookupContext &lookup_context) { return would_match_input (c, inputCount, input, @@ -1790,7 +1839,7 @@ static inline bool context_apply_lookup (hb_ot_apply_context_t *c, const HBUINT input[], /* Array of input values--start with second glyph */ unsigned int lookupCount, const LookupRecord lookupRecord[], - ContextApplyLookupContext &lookup_context) + const ContextApplyLookupContext &lookup_context) { unsigned match_end = 0; unsigned match_positions[HB_MAX_CONTEXT_LENGTH]; @@ -1858,7 +1907,7 @@ struct Rule } bool would_apply (hb_would_apply_context_t *c, - ContextApplyLookupContext &lookup_context) const + const ContextApplyLookupContext &lookup_context) const { const auto &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>> (inputZ.as_array (inputCount ? inputCount - 1 : 0)); @@ -1869,7 +1918,7 @@ struct Rule } bool apply (hb_ot_apply_context_t *c, - ContextApplyLookupContext &lookup_context) const + const ContextApplyLookupContext &lookup_context) const { TRACE_APPLY (this); const auto &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>> @@ -1989,7 +2038,7 @@ struct RuleSet } bool would_apply (hb_would_apply_context_t *c, - ContextApplyLookupContext &lookup_context) const + const ContextApplyLookupContext &lookup_context) const { return + hb_iter (rule) @@ -2000,7 +2049,7 @@ struct RuleSet } bool apply (hb_ot_apply_context_t *c, - ContextApplyLookupContext &lookup_context) const + const ContextApplyLookupContext &lookup_context) const { TRACE_APPLY (this); return_trace ( @@ -2108,7 +2157,7 @@ struct ContextFormat1_4 void closure_lookups (hb_closure_lookups_context_t *c) const { struct ContextClosureLookupContext lookup_context = { - {intersects_glyph, intersected_glyph}, + {intersects_glyph, nullptr}, ContextFormat::SimpleContext, nullptr }; @@ -2220,10 +2269,12 @@ struct ContextFormat2_5 const ClassDef &class_def = this+classDef; + hb_map_t cache; struct ContextClosureLookupContext lookup_context = { - {intersects_class, intersected_class_glyphs}, + {intersects_class, nullptr}, ContextFormat::ClassBasedContext, - &class_def + &class_def, + &cache }; hb_set_t retained_coverage_glyphs; @@ -2259,10 +2310,14 @@ struct ContextFormat2_5 const ClassDef &class_def = this+classDef; + hb_map_t cache; + intersected_class_cache_t intersected_cache; struct ContextClosureLookupContext lookup_context = { {intersects_class, intersected_class_glyphs}, ContextFormat::ClassBasedContext, - &class_def + &class_def, + &cache, + &intersected_cache }; + hb_enumerate (ruleSet) @@ -2286,10 +2341,12 @@ struct ContextFormat2_5 const ClassDef &class_def = this+classDef; + hb_map_t cache; struct ContextClosureLookupContext lookup_context = { - {intersects_class, intersected_class_glyphs}, + {intersects_class, nullptr}, ContextFormat::ClassBasedContext, - &class_def + &class_def, + &cache }; + hb_iter (ruleSet) @@ -2407,6 +2464,7 @@ struct ContextFormat2_5 const hb_map_t *lookup_map = c->table_tag == HB_OT_TAG_GSUB ? c->plan->gsub_lookups : c->plan->gpos_lookups; bool ret = true; int non_zero_index = -1, index = 0; + auto snapshot = c->serializer->snapshot(); for (const auto& _ : + hb_enumerate (ruleSet) | hb_filter (klass_map, hb_first)) { @@ -2418,8 +2476,10 @@ struct ContextFormat2_5 } if (coverage_glyph_classes.has (_.first) && - o->serialize_subset (c, _.second, this, lookup_map, &klass_map)) + o->serialize_subset (c, _.second, this, lookup_map, &klass_map)) { non_zero_index = index; + snapshot = c->serializer->snapshot(); + } index++; } @@ -2433,6 +2493,7 @@ struct ContextFormat2_5 out->ruleSet.pop (); index--; } + c->serializer->revert (snapshot); return_trace (bool (out->ruleSet)); } @@ -2469,7 +2530,7 @@ struct ContextFormat3 return false; struct ContextClosureLookupContext lookup_context = { - {intersects_coverage, intersected_coverage_glyphs}, + {intersects_coverage, nullptr}, ContextFormat::CoverageBasedContext, this }; @@ -2655,6 +2716,8 @@ struct ChainContextClosureLookupContext ContextClosureFuncs funcs; ContextFormat context_format; const void *intersects_data[3]; + void *intersects_cache[3]; + void *intersected_glyphs_cache; }; struct ChainContextCollectGlyphsLookupContext @@ -2681,13 +2744,19 @@ static inline bool chain_context_intersects (const hb_set_t *glyphs, { return array_is_subset_of (glyphs, backtrackCount, backtrack, - lookup_context.funcs.intersects, lookup_context.intersects_data[0]) + lookup_context.funcs.intersects, + lookup_context.intersects_data[0], + lookup_context.intersects_cache[0]) && array_is_subset_of (glyphs, inputCount ? inputCount - 1 : 0, input, - lookup_context.funcs.intersects, lookup_context.intersects_data[1]) + lookup_context.funcs.intersects, + lookup_context.intersects_data[1], + lookup_context.intersects_cache[1]) && array_is_subset_of (glyphs, lookaheadCount, lookahead, - lookup_context.funcs.intersects, lookup_context.intersects_data[2]); + lookup_context.funcs.intersects, + lookup_context.intersects_data[2], + lookup_context.intersects_cache[2]); } template <typename HBUINT> @@ -2714,7 +2783,8 @@ static inline void chain_context_closure_lookup (hb_closure_context_t *c, value, lookup_context.context_format, lookup_context.intersects_data[1], - lookup_context.funcs.intersected_glyphs); + lookup_context.funcs.intersected_glyphs, + lookup_context.intersected_glyphs_cache); } template <typename HBUINT> @@ -2752,7 +2822,7 @@ static inline bool chain_context_would_apply_lookup (hb_would_apply_context_t *c const HBUINT lookahead[] HB_UNUSED, unsigned int lookupCount HB_UNUSED, const LookupRecord lookupRecord[] HB_UNUSED, - ChainContextApplyLookupContext &lookup_context) + const ChainContextApplyLookupContext &lookup_context) { return (c->zero_context ? !backtrackCount && !lookaheadCount : true) && would_match_input (c, @@ -2770,7 +2840,7 @@ static inline bool chain_context_apply_lookup (hb_ot_apply_context_t *c, const HBUINT lookahead[], unsigned int lookupCount, const LookupRecord lookupRecord[], - ChainContextApplyLookupContext &lookup_context) + const ChainContextApplyLookupContext &lookup_context) { unsigned end_index = c->buffer->idx; unsigned match_end = 0; @@ -2864,7 +2934,7 @@ struct ChainRule } bool would_apply (hb_would_apply_context_t *c, - ChainContextApplyLookupContext &lookup_context) const + const ChainContextApplyLookupContext &lookup_context) const { const auto &input = StructAfter<decltype (inputX)> (backtrack); const auto &lookahead = StructAfter<decltype (lookaheadX)> (input); @@ -2876,7 +2946,8 @@ struct ChainRule lookup.arrayZ, lookup_context); } - bool apply (hb_ot_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const + bool apply (hb_ot_apply_context_t *c, + const ChainContextApplyLookupContext &lookup_context) const { TRACE_APPLY (this); const auto &input = StructAfter<decltype (inputX)> (backtrack); @@ -3042,7 +3113,8 @@ struct ChainRuleSet ; } - bool would_apply (hb_would_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const + bool would_apply (hb_would_apply_context_t *c, + const ChainContextApplyLookupContext &lookup_context) const { return + hb_iter (rule) @@ -3052,7 +3124,8 @@ struct ChainRuleSet ; } - bool apply (hb_ot_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const + bool apply (hb_ot_apply_context_t *c, + const ChainContextApplyLookupContext &lookup_context) const { TRACE_APPLY (this); return_trace ( @@ -3166,7 +3239,7 @@ struct ChainContextFormat1_4 void closure_lookups (hb_closure_lookups_context_t *c) const { struct ChainContextClosureLookupContext lookup_context = { - {intersects_glyph, intersected_glyph}, + {intersects_glyph, nullptr}, ContextFormat::SimpleContext, {nullptr, nullptr, nullptr} }; @@ -3278,12 +3351,14 @@ struct ChainContextFormat2_5 const ClassDef &input_class_def = this+inputClassDef; const ClassDef &lookahead_class_def = this+lookaheadClassDef; + hb_map_t caches[3] = {}; struct ChainContextClosureLookupContext lookup_context = { - {intersects_class, intersected_class_glyphs}, + {intersects_class, nullptr}, ContextFormat::ClassBasedContext, {&backtrack_class_def, &input_class_def, - &lookahead_class_def} + &lookahead_class_def}, + {&caches[0], &caches[1], &caches[2]} }; hb_set_t retained_coverage_glyphs; @@ -3321,12 +3396,16 @@ struct ChainContextFormat2_5 const ClassDef &input_class_def = this+inputClassDef; const ClassDef &lookahead_class_def = this+lookaheadClassDef; + hb_map_t caches[3] = {}; + intersected_class_cache_t intersected_cache; struct ChainContextClosureLookupContext lookup_context = { {intersects_class, intersected_class_glyphs}, ContextFormat::ClassBasedContext, {&backtrack_class_def, &input_class_def, - &lookahead_class_def} + &lookahead_class_def}, + {&caches[0], &caches[1], &caches[2]}, + &intersected_cache }; + hb_enumerate (ruleSet) @@ -3352,12 +3431,14 @@ struct ChainContextFormat2_5 const ClassDef &input_class_def = this+inputClassDef; const ClassDef &lookahead_class_def = this+lookaheadClassDef; + hb_map_t caches[3] = {}; struct ChainContextClosureLookupContext lookup_context = { - {intersects_class, intersected_class_glyphs}, + {intersects_class, nullptr}, ContextFormat::ClassBasedContext, {&backtrack_class_def, &input_class_def, - &lookahead_class_def} + &lookahead_class_def}, + {&caches[0], &caches[1], &caches[2]} }; + hb_iter (ruleSet) @@ -3587,7 +3668,7 @@ struct ChainContextFormat3 const auto &lookahead = StructAfter<decltype (lookaheadX)> (input); struct ChainContextClosureLookupContext lookup_context = { - {intersects_coverage, intersected_coverage_glyphs}, + {intersects_coverage, nullptr}, ContextFormat::CoverageBasedContext, {this, this, this} }; @@ -3938,13 +4019,14 @@ struct hb_ot_layout_lookup_accelerator_t template <typename TLookup> void init (const TLookup &lookup) { - digest.init (); - lookup.collect_coverage (&digest); - subtables.init (); - OT::hb_accelerate_subtables_context_t c_accelerate_subtables (subtables); + hb_accelerate_subtables_context_t c_accelerate_subtables (subtables); lookup.dispatch (&c_accelerate_subtables); + digest.init (); + for (auto& subtable : hb_iter (subtables)) + digest.add (subtable.digest); + #ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE cache_user_idx = c_accelerate_subtables.cache_user_idx; for (unsigned i = 0; i < subtables.length; i++) @@ -3962,21 +4044,25 @@ struct hb_ot_layout_lookup_accelerator_t #ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE if (use_cache) { - for (unsigned int i = 0; i < subtables.length; i++) - if (subtables[i].apply_cached (c)) - return true; + return + + hb_iter (subtables) + | hb_map ([&c] (const hb_accelerate_subtables_context_t::hb_applicable_t &_) { return _.apply_cached (c); }) + | hb_any + ; } else #endif { - for (unsigned int i = 0; i < subtables.length; i++) - if (subtables[i].apply (c)) - return true; + return + + hb_iter (subtables) + | hb_map ([&c] (const hb_accelerate_subtables_context_t::hb_applicable_t &_) { return _.apply (c); }) + | hb_any + ; } return false; } - bool cache_enter (OT::hb_ot_apply_context_t *c) const + bool cache_enter (hb_ot_apply_context_t *c) const { #ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE return cache_user_idx != (unsigned) -1 && @@ -3985,7 +4071,7 @@ struct hb_ot_layout_lookup_accelerator_t return false; #endif } - void cache_leave (OT::hb_ot_apply_context_t *c) const + void cache_leave (hb_ot_apply_context_t *c) const { #ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE subtables[cache_user_idx].cache_leave (c); @@ -3993,8 +4079,8 @@ struct hb_ot_layout_lookup_accelerator_t } - private: hb_set_digest_t digest; + private: hb_accelerate_subtables_context_t::array_t subtables; #ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE unsigned cache_user_idx = (unsigned) -1; @@ -4236,24 +4322,30 @@ struct GSUBGPOS } void feature_variation_collect_lookups (const hb_set_t *feature_indexes, + const hb_hashmap_t<unsigned, const Feature*> *feature_substitutes_map, hb_set_t *lookup_indexes /* OUT */) const { #ifndef HB_NO_VAR - get_feature_variations ().collect_lookups (feature_indexes, lookup_indexes); + get_feature_variations ().collect_lookups (feature_indexes, feature_substitutes_map, lookup_indexes); #endif } +#ifndef HB_NO_VAR + void collect_feature_substitutes_with_variations (hb_collect_feature_substitutes_with_var_context_t *c) const + { get_feature_variations ().collect_feature_substitutes_with_variations (c); } +#endif + template <typename TLookup> void closure_lookups (hb_face_t *face, const hb_set_t *glyphs, hb_set_t *lookup_indexes /* IN/OUT */) const { hb_set_t visited_lookups, inactive_lookups; - OT::hb_closure_lookups_context_t c (face, glyphs, &visited_lookups, &inactive_lookups); + hb_closure_lookups_context_t c (face, glyphs, &visited_lookups, &inactive_lookups); c.set_recurse_func (TLookup::template dispatch_recurse_func<hb_closure_lookups_context_t>); - for (unsigned lookup_index : + hb_iter (lookup_indexes)) + for (unsigned lookup_index : *lookup_indexes) reinterpret_cast<const TLookup &> (get_lookup (lookup_index)).closure_lookups (&c, lookup_index); hb_set_union (lookup_indexes, &visited_lookups); @@ -4278,6 +4370,8 @@ struct GSUBGPOS } void prune_features (const hb_map_t *lookup_indices, /* IN */ + const hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *feature_record_cond_idx_map, /* IN */ + const hb_hashmap_t<unsigned, const Feature*> *feature_substitutes_map, /* IN */ hb_set_t *feature_indices /* IN/OUT */) const { #ifndef HB_NO_VAR @@ -4285,7 +4379,7 @@ struct GSUBGPOS // if the FeatureVariation's table and the alternate version(s) intersect the // set of lookup indices. hb_set_t alternate_feature_indices; - get_feature_variations ().closure_features (lookup_indices, &alternate_feature_indices); + get_feature_variations ().closure_features (lookup_indices, feature_record_cond_idx_map, &alternate_feature_indices); if (unlikely (alternate_feature_indices.in_error())) { feature_indices->err (); @@ -4293,9 +4387,8 @@ struct GSUBGPOS } #endif - for (unsigned i : feature_indices->iter()) + for (unsigned i : hb_iter (feature_indices)) { - const Feature& f = get_feature (i); hb_tag_t tag = get_feature_tag (i); if (tag == HB_TAG ('p', 'r', 'e', 'f')) // Note: Never ever drop feature 'pref', even if it's empty. @@ -4305,11 +4398,16 @@ struct GSUBGPOS continue; - if (!f.featureParams.is_null () && + const Feature *f = &(get_feature (i)); + const Feature** p = nullptr; + if (feature_substitutes_map->has (i, &p)) + f = *p; + + if (!f->featureParams.is_null () && tag == HB_TAG ('s', 'i', 'z', 'e')) continue; - if (!f.intersects_lookup_indexes (lookup_indices) + if (!f->intersects_lookup_indexes (lookup_indices) #ifndef HB_NO_VAR && !alternate_feature_indices.has (i) #endif diff --git a/thirdparty/harfbuzz/src/hb-ot-layout.cc b/thirdparty/harfbuzz/src/hb-ot-layout.cc index 44e57987b7..e8091ec3e0 100644 --- a/thirdparty/harfbuzz/src/hb-ot-layout.cc +++ b/thirdparty/harfbuzz/src/hb-ot-layout.cc @@ -1271,7 +1271,7 @@ hb_ot_layout_collect_lookups (hb_face_t *face, hb_set_next (&feature_indexes, &feature_index);) g.get_feature (feature_index).add_lookup_indexes_to (lookup_indexes); - g.feature_variation_collect_lookups (&feature_indexes, lookup_indexes); + g.feature_variation_collect_lookups (&feature_indexes, nullptr, lookup_indexes); } @@ -1465,56 +1465,6 @@ hb_ot_layout_substitute_start (hb_font_t *font, _hb_ot_layout_set_glyph_props (font, buffer); } -void -hb_ot_layout_delete_glyphs_inplace (hb_buffer_t *buffer, - bool (*filter) (const hb_glyph_info_t *info)) -{ - /* Merge clusters and delete filtered glyphs. - * NOTE! We can't use out-buffer as we have positioning data. */ - unsigned int j = 0; - unsigned int count = buffer->len; - hb_glyph_info_t *info = buffer->info; - hb_glyph_position_t *pos = buffer->pos; - for (unsigned int i = 0; i < count; i++) - { - if (filter (&info[i])) - { - /* Merge clusters. - * Same logic as buffer->delete_glyph(), but for in-place removal. */ - - unsigned int cluster = info[i].cluster; - if (i + 1 < count && cluster == info[i + 1].cluster) - continue; /* Cluster survives; do nothing. */ - - if (j) - { - /* Merge cluster backward. */ - if (cluster < info[j - 1].cluster) - { - unsigned int mask = info[i].mask; - unsigned int old_cluster = info[j - 1].cluster; - for (unsigned k = j; k && info[k - 1].cluster == old_cluster; k--) - buffer->set_cluster (info[k - 1], cluster, mask); - } - continue; - } - - if (i + 1 < count) - buffer->merge_clusters (i, i + 2); /* Merge cluster forward. */ - - continue; - } - - if (j != i) - { - info[j] = info[i]; - pos[j] = pos[i]; - } - j++; - } - buffer->len = j; -} - /** * hb_ot_layout_lookup_substitute_closure: * @face: #hb_face_t to work upon @@ -1709,6 +1659,8 @@ hb_ot_layout_get_size_params (hb_face_t *face, return false; } + + /** * hb_ot_layout_feature_get_name_ids: * @face: #hb_face_t to work upon @@ -1865,7 +1817,7 @@ apply_forward (OT::hb_ot_apply_context_t *c, while (buffer->idx < buffer->len && buffer->successful) { bool applied = false; - if (accel.may_have (buffer->cur().codepoint) && + if (accel.digest.may_have (buffer->cur().codepoint) && (buffer->cur().mask & c->lookup_mask) && c->check_glyph_property (&buffer->cur(), c->lookup_props)) { @@ -1892,7 +1844,7 @@ apply_backward (OT::hb_ot_apply_context_t *c, hb_buffer_t *buffer = c->buffer; do { - if (accel.may_have (buffer->cur().codepoint) && + if (accel.digest.may_have (buffer->cur().codepoint) && (buffer->cur().mask & c->lookup_mask) && c->check_glyph_property (&buffer->cur(), c->lookup_props)) ret |= accel.apply (c, false); @@ -1906,15 +1858,16 @@ apply_backward (OT::hb_ot_apply_context_t *c, } template <typename Proxy> -static inline void +static inline bool apply_string (OT::hb_ot_apply_context_t *c, const typename Proxy::Lookup &lookup, const OT::hb_ot_layout_lookup_accelerator_t &accel) { + bool ret = false; hb_buffer_t *buffer = c->buffer; if (unlikely (!buffer->len || !c->lookup_mask)) - return; + return ret; c->set_lookup_props (lookup.get_props ()); @@ -1925,7 +1878,7 @@ apply_string (OT::hb_ot_apply_context_t *c, buffer->clear_output (); buffer->idx = 0; - apply_forward (c, accel); + ret = apply_forward (c, accel); if (!Proxy::always_inplace) buffer->sync (); @@ -1935,8 +1888,10 @@ apply_string (OT::hb_ot_apply_context_t *c, /* in-place backward substitution/positioning */ assert (!buffer->have_output); buffer->idx = buffer->len - 1; - apply_backward (c, accel); + ret = apply_backward (c, accel); } + + return ret; } template <typename Proxy> @@ -1955,23 +1910,42 @@ inline void hb_ot_map_t::apply (const Proxy &proxy, const stage_map_t *stage = &stages[table_index][stage_index]; for (; i < stage->last_lookup; i++) { - unsigned int lookup_index = lookups[table_index][i].index; - if (!buffer->message (font, "start lookup %d", lookup_index)) continue; - c.set_lookup_index (lookup_index); - c.set_lookup_mask (lookups[table_index][i].mask); - c.set_auto_zwj (lookups[table_index][i].auto_zwj); - c.set_auto_zwnj (lookups[table_index][i].auto_zwnj); - c.set_random (lookups[table_index][i].random); - c.set_per_syllable (lookups[table_index][i].per_syllable); - - apply_string<Proxy> (&c, - proxy.table.get_lookup (lookup_index), - proxy.accels[lookup_index]); - (void) buffer->message (font, "end lookup %d", lookup_index); + auto &lookup = lookups[table_index][i]; + + unsigned int lookup_index = lookup.index; + if (!buffer->message (font, "start lookup %d feature '%c%c%c%c'", lookup_index, HB_UNTAG (lookup.feature_tag))) continue; + + /* c.digest is a digest of all the current glyphs in the buffer + * (plus some past glyphs). + * + * Only try applying the lookup if there is any overlap. */ + if (proxy.accels[lookup_index].digest.may_have (c.digest)) + { + c.set_lookup_index (lookup_index); + c.set_lookup_mask (lookup.mask); + c.set_auto_zwj (lookup.auto_zwj); + c.set_auto_zwnj (lookup.auto_zwnj); + c.set_random (lookup.random); + c.set_per_syllable (lookup.per_syllable); + + apply_string<Proxy> (&c, + proxy.table.get_lookup (lookup_index), + proxy.accels[lookup_index]); + } + else + (void) buffer->message (font, "skipped lookup %d feature '%c%c%c%c' because no glyph matches", lookup_index, HB_UNTAG (lookup.feature_tag)); + + (void) buffer->message (font, "end lookup %d feature '%c%c%c%c'", lookup_index, HB_UNTAG (lookup.feature_tag)); } if (stage->pause_func) - stage->pause_func (plan, font, buffer); + { + if (stage->pause_func (plan, font, buffer)) + { + /* Refresh working buffer digest since buffer changed. */ + c.digest = buffer->digest (); + } + } } } @@ -2341,6 +2315,7 @@ struct hb_get_glyph_alternates_dispatch_t : ( _dispatch (obj, hb_prioritize, std::forward<Ts> (ds)...) ) }; +#ifndef HB_NO_LAYOUT_RARELY_USED /** * hb_ot_layout_lookup_get_glyph_alternates: * @face: a face. @@ -2373,4 +2348,72 @@ hb_ot_layout_lookup_get_glyph_alternates (hb_face_t *face, return ret; } + +struct hb_position_single_dispatch_t : + hb_dispatch_context_t<hb_position_single_dispatch_t, bool> +{ + static return_t default_return_value () { return false; } + bool stop_sublookup_iteration (return_t r) const { return r; } + + private: + template <typename T, typename ...Ts> auto + _dispatch (const T &obj, hb_priority<1>, Ts&&... ds) HB_AUTO_RETURN + ( obj.position_single (std::forward<Ts> (ds)...) ) + template <typename T, typename ...Ts> auto + _dispatch (const T &obj, hb_priority<0>, Ts&&... ds) HB_AUTO_RETURN + ( default_return_value () ) + public: + template <typename T, typename ...Ts> auto + dispatch (const T &obj, Ts&&... ds) HB_AUTO_RETURN + ( _dispatch (obj, hb_prioritize, std::forward<Ts> (ds)...) ) +}; + +/** + * hb_ot_layout_lookup_get_optical_bound: + * @font: a font. + * @lookup_index: index of the feature lookup to query. + * @direction: edge of the glyph to query. + * @glyph: a glyph id. + * + * Fetches the optical bound of a glyph positioned at the margin of text. + * The direction identifies which edge of the glyph to query. + * + * Return value: Adjustment value. Negative values mean the glyph will stick out of the margin. + * + * Since: 5.3.0 + **/ +hb_position_t +hb_ot_layout_lookup_get_optical_bound (hb_font_t *font, + unsigned lookup_index, + hb_direction_t direction, + hb_codepoint_t glyph) +{ + const OT::PosLookup &lookup = font->face->table.GPOS->table->get_lookup (lookup_index); + hb_glyph_position_t pos = {0}; + hb_position_single_dispatch_t c; + lookup.dispatch (&c, font, direction, glyph, pos); + hb_position_t ret = 0; + switch (direction) + { + case HB_DIRECTION_LTR: + ret = pos.x_offset; + break; + case HB_DIRECTION_RTL: + ret = pos.x_advance - pos.x_offset; + break; + case HB_DIRECTION_TTB: + ret = pos.y_offset; + break; + case HB_DIRECTION_BTT: + ret = pos.y_advance - pos.y_offset; + break; + case HB_DIRECTION_INVALID: + default: + break; + } + return ret; +} +#endif + + #endif diff --git a/thirdparty/harfbuzz/src/hb-ot-layout.h b/thirdparty/harfbuzz/src/hb-ot-layout.h index 4edddd9e0d..f7b488f870 100644 --- a/thirdparty/harfbuzz/src/hb-ot-layout.h +++ b/thirdparty/harfbuzz/src/hb-ot-layout.h @@ -403,6 +403,16 @@ hb_ot_layout_get_size_params (hb_face_t *face, unsigned int *range_start, /* OUT. May be NULL */ unsigned int *range_end /* OUT. May be NULL */); +HB_EXTERN hb_position_t +hb_ot_layout_lookup_get_optical_bound (hb_font_t *font, + unsigned lookup_index, + hb_direction_t direction, + hb_codepoint_t glyph); + + +/* + * GSUB/GPOS + */ HB_EXTERN hb_bool_t hb_ot_layout_feature_get_name_ids (hb_face_t *face, @@ -423,6 +433,7 @@ hb_ot_layout_feature_get_characters (hb_face_t *face, unsigned int *char_count /* IN/OUT. May be NULL */, hb_codepoint_t *characters /* OUT. May be NULL */); + /* * BASE */ diff --git a/thirdparty/harfbuzz/src/hb-ot-layout.hh b/thirdparty/harfbuzz/src/hb-ot-layout.hh index de06610cb5..9505d5f147 100644 --- a/thirdparty/harfbuzz/src/hb-ot-layout.hh +++ b/thirdparty/harfbuzz/src/hb-ot-layout.hh @@ -102,10 +102,6 @@ HB_INTERNAL void hb_ot_layout_substitute_start (hb_font_t *font, hb_buffer_t *buffer); -HB_INTERNAL void -hb_ot_layout_delete_glyphs_inplace (hb_buffer_t *buffer, - bool (*filter) (const hb_glyph_info_t *info)); - namespace OT { struct hb_ot_apply_context_t; struct hb_ot_layout_lookup_accelerator_t; @@ -552,7 +548,7 @@ _hb_glyph_info_clear_substituted (hb_glyph_info_t *info) info->glyph_props() &= ~(HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED); } -static inline void +static inline bool _hb_clear_substitution_flags (const hb_ot_shape_plan_t *plan HB_UNUSED, hb_font_t *font HB_UNUSED, hb_buffer_t *buffer) @@ -561,6 +557,7 @@ _hb_clear_substitution_flags (const hb_ot_shape_plan_t *plan HB_UNUSED, unsigned int count = buffer->len; for (unsigned int i = 0; i < count; i++) _hb_glyph_info_clear_substituted (&info[i]); + return false; } diff --git a/thirdparty/harfbuzz/src/hb-ot-map.cc b/thirdparty/harfbuzz/src/hb-ot-map.cc index 39215b335f..8882dbaccb 100644 --- a/thirdparty/harfbuzz/src/hb-ot-map.cc +++ b/thirdparty/harfbuzz/src/hb-ot-map.cc @@ -45,7 +45,7 @@ void hb_ot_map_t::collect_lookups (unsigned int table_index, hb_set_t *lookups_o hb_ot_map_builder_t::hb_ot_map_builder_t (hb_face_t *face_, const hb_segment_properties_t &props_) { - memset (this, 0, sizeof (*this)); + hb_memset (this, 0, sizeof (*this)); feature_infos.init (); for (unsigned int table_index = 0; table_index < 2; table_index++) @@ -133,7 +133,8 @@ hb_ot_map_builder_t::add_lookups (hb_ot_map_t &m, bool auto_zwnj, bool auto_zwj, bool random, - bool per_syllable) + bool per_syllable, + hb_tag_t feature_tag) { unsigned int lookup_indices[32]; unsigned int offset, len; @@ -162,6 +163,7 @@ hb_ot_map_builder_t::add_lookups (hb_ot_map_t &m, lookup->auto_zwj = auto_zwj; lookup->random = random; lookup->per_syllable = per_syllable; + lookup->feature_tag = feature_tag; } offset += len; @@ -212,24 +214,26 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m, if (feature_infos.length) { feature_infos.qsort (); + auto *f = feature_infos.arrayZ; unsigned int j = 0; - for (unsigned int i = 1; i < feature_infos.length; i++) - if (feature_infos[i].tag != feature_infos[j].tag) - feature_infos[++j] = feature_infos[i]; + unsigned count = feature_infos.length; + for (unsigned int i = 1; i < count; i++) + if (f[i].tag != f[j].tag) + f[++j] = f[i]; else { - if (feature_infos[i].flags & F_GLOBAL) { - feature_infos[j].flags |= F_GLOBAL; - feature_infos[j].max_value = feature_infos[i].max_value; - feature_infos[j].default_value = feature_infos[i].default_value; + if (f[i].flags & F_GLOBAL) { + f[j].flags |= F_GLOBAL; + f[j].max_value = f[i].max_value; + f[j].default_value = f[i].default_value; } else { - if (feature_infos[j].flags & F_GLOBAL) - feature_infos[j].flags ^= F_GLOBAL; - feature_infos[j].max_value = hb_max (feature_infos[j].max_value, feature_infos[i].max_value); + if (f[j].flags & F_GLOBAL) + f[j].flags ^= F_GLOBAL; + f[j].max_value = hb_max (f[j].max_value, f[i].max_value); /* Inherit default_value from j */ } - feature_infos[j].flags |= (feature_infos[i].flags & F_HAS_FALLBACK); - feature_infos[j].stage[0] = hb_min (feature_infos[j].stage[0], feature_infos[i].stage[0]); - feature_infos[j].stage[1] = hb_min (feature_infos[j].stage[1], feature_infos[i].stage[1]); + f[j].flags |= (f[i].flags & F_HAS_FALLBACK); + f[j].stage[0] = hb_min (f[j].stage[0], f[i].stage[0]); + f[j].stage[1] = hb_min (f[j].stage[1], f[i].stage[1]); } feature_infos.shrink (j + 1); } @@ -239,7 +243,8 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m, static_assert ((!(HB_GLYPH_FLAG_DEFINED & (HB_GLYPH_FLAG_DEFINED + 1))), ""); unsigned int next_bit = hb_popcount (HB_GLYPH_FLAG_DEFINED) + 1; - for (unsigned int i = 0; i < feature_infos.length; i++) + unsigned count = feature_infos.length; + for (unsigned int i = 0; i < count; i++) { const feature_info_t *info = &feature_infos[i]; @@ -308,7 +313,7 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m, map->_1_mask = (1u << map->shift) & map->mask; map->needs_fallback = !found; } - feature_infos.shrink (0); /* Done with these */ + //feature_infos.shrink (0); /* Done with these */ add_gsub_pause (nullptr); @@ -317,6 +322,7 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m, for (unsigned int table_index = 0; table_index < 2; table_index++) { /* Collect lookup indices for features */ + auto &lookups = m.lookups[table_index]; unsigned int stage_index = 0; unsigned int last_num_lookups = 0; @@ -329,36 +335,39 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m, key.variations_index[table_index], global_bit_mask); - for (unsigned i = 0; i < m.features.length; i++) - if (m.features[i].stage[table_index] == stage) + for (auto &feature : m.features) + { + if (feature.stage[table_index] == stage) add_lookups (m, table_index, - m.features[i].index[table_index], + feature.index[table_index], key.variations_index[table_index], - m.features[i].mask, - m.features[i].auto_zwnj, - m.features[i].auto_zwj, - m.features[i].random, - m.features[i].per_syllable); + feature.mask, + feature.auto_zwnj, + feature.auto_zwj, + feature.random, + feature.per_syllable, + feature.tag); + } /* Sort lookups and merge duplicates */ - if (last_num_lookups < m.lookups[table_index].length) + if (last_num_lookups < lookups.length) { - m.lookups[table_index].qsort (last_num_lookups, m.lookups[table_index].length); + lookups.as_array ().sub_array (last_num_lookups, lookups.length - last_num_lookups).qsort (); unsigned int j = last_num_lookups; - for (unsigned int i = j + 1; i < m.lookups[table_index].length; i++) - if (m.lookups[table_index][i].index != m.lookups[table_index][j].index) - m.lookups[table_index][++j] = m.lookups[table_index][i]; + for (unsigned int i = j + 1; i < lookups.length; i++) + if (lookups.arrayZ[i].index != lookups.arrayZ[j].index) + lookups.arrayZ[++j] = lookups.arrayZ[i]; else { - m.lookups[table_index][j].mask |= m.lookups[table_index][i].mask; - m.lookups[table_index][j].auto_zwnj &= m.lookups[table_index][i].auto_zwnj; - m.lookups[table_index][j].auto_zwj &= m.lookups[table_index][i].auto_zwj; + lookups.arrayZ[j].mask |= lookups.arrayZ[i].mask; + lookups.arrayZ[j].auto_zwnj &= lookups.arrayZ[i].auto_zwnj; + lookups.arrayZ[j].auto_zwj &= lookups.arrayZ[i].auto_zwj; } - m.lookups[table_index].shrink (j + 1); + lookups.shrink (j + 1); } - last_num_lookups = m.lookups[table_index].length; + last_num_lookups = lookups.length; if (stage_index < stages[table_index].length && stages[table_index][stage_index].index == stage) { hb_ot_map_t::stage_map_t *stage_map = m.stages[table_index].push (); diff --git a/thirdparty/harfbuzz/src/hb-ot-map.hh b/thirdparty/harfbuzz/src/hb-ot-map.hh index a7b5eec30d..efc8cae96a 100644 --- a/thirdparty/harfbuzz/src/hb-ot-map.hh +++ b/thirdparty/harfbuzz/src/hb-ot-map.hh @@ -69,6 +69,7 @@ struct hb_ot_map_t unsigned short random : 1; unsigned short per_syllable : 1; hb_mask_t mask; + hb_tag_t feature_tag; HB_INTERNAL static int cmp (const void *pa, const void *pb) { @@ -78,7 +79,9 @@ struct hb_ot_map_t } }; - typedef void (*pause_func_t) (const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer); + /* Pause functions return true if new glyph indices might have been + * added to the buffer. This is used to update buffer digest. */ + typedef bool (*pause_func_t) (const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer); struct stage_map_t { unsigned int last_lookup; /* Cumulative */ @@ -87,13 +90,13 @@ struct hb_ot_map_t void init () { - memset (this, 0, sizeof (*this)); + hb_memset (this, 0, sizeof (*this)); - features.init (); + features.init0 (); for (unsigned int table_index = 0; table_index < 2; table_index++) { - lookups[table_index].init (); - stages[table_index].init (); + lookups[table_index].init0 (); + stages[table_index].init0 (); } } void fini () @@ -239,7 +242,8 @@ struct hb_ot_map_builder_t bool auto_zwnj = true, bool auto_zwj = true, bool random = false, - bool per_syllable = false); + bool per_syllable = false, + hb_tag_t feature_tag = HB_TAG(' ',' ',' ',' ')); struct feature_info_t { hb_tag_t tag; diff --git a/thirdparty/harfbuzz/src/hb-ot-math-table.hh b/thirdparty/harfbuzz/src/hb-ot-math-table.hh index d834d94371..93953370e2 100644 --- a/thirdparty/harfbuzz/src/hb-ot-math-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-math-table.hh @@ -77,11 +77,11 @@ struct MathConstants HBINT16 *p = c->allocate_size<HBINT16> (HBINT16::static_size * 2); if (unlikely (!p)) return_trace (nullptr); - memcpy (p, percentScaleDown, HBINT16::static_size * 2); + hb_memcpy (p, percentScaleDown, HBINT16::static_size * 2); HBUINT16 *m = c->allocate_size<HBUINT16> (HBUINT16::static_size * 2); if (unlikely (!m)) return_trace (nullptr); - memcpy (m, minHeight, HBUINT16::static_size * 2); + hb_memcpy (m, minHeight, HBUINT16::static_size * 2); unsigned count = ARRAY_LENGTH (mathValueRecords); for (unsigned i = 0; i < count; i++) @@ -786,7 +786,7 @@ struct MathGlyphAssembly if (parts_count) { int64_t mult = font->dir_mult (direction); - for (auto _ : hb_zip (partRecords.sub_array (start_offset, parts_count), + for (auto _ : hb_zip (partRecords.as_array ().sub_array (start_offset, parts_count), hb_array (parts, *parts_count))) _.first.extract (_.second, mult, font); } @@ -855,7 +855,7 @@ struct MathGlyphConstruction if (variants_count) { int64_t mult = font->dir_mult (direction); - for (auto _ : hb_zip (mathGlyphVariantRecord.sub_array (start_offset, variants_count), + for (auto _ : hb_zip (mathGlyphVariantRecord.as_array ().sub_array (start_offset, variants_count), hb_array (variants, *variants_count))) _.second = {_.first.variantGlyph, font->em_mult (_.first.advanceMeasurement, mult)}; } diff --git a/thirdparty/harfbuzz/src/hb-ot-meta-table.hh b/thirdparty/harfbuzz/src/hb-ot-meta-table.hh index 93e64c5327..e1b68bcf91 100644 --- a/thirdparty/harfbuzz/src/hb-ot-meta-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-meta-table.hh @@ -84,7 +84,7 @@ struct meta { if (count) { - + table->dataMaps.sub_array (start_offset, count) + + table->dataMaps.as_array ().sub_array (start_offset, count) | hb_map (&DataMap::get_tag) | hb_map ([](hb_tag_t tag) { return (hb_ot_meta_tag_t) tag; }) | hb_sink (hb_array (entries, *count)) diff --git a/thirdparty/harfbuzz/src/hb-ot-name-table.hh b/thirdparty/harfbuzz/src/hb-ot-name-table.hh index 1f2131ffcc..6f4461cc15 100644 --- a/thirdparty/harfbuzz/src/hb-ot-name-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-name-table.hh @@ -30,10 +30,55 @@ #include "hb-open-type.hh" #include "hb-ot-name-language.hh" #include "hb-aat-layout.hh" +#include "hb-utf.hh" namespace OT { +template <typename in_utf_t, typename out_utf_t> +inline unsigned int +hb_ot_name_convert_utf (hb_bytes_t bytes, + unsigned int *text_size /* IN/OUT */, + typename out_utf_t::codepoint_t *text /* OUT */) +{ + unsigned int src_len = bytes.length / sizeof (typename in_utf_t::codepoint_t); + const typename in_utf_t::codepoint_t *src = (const typename in_utf_t::codepoint_t *) bytes.arrayZ; + const typename in_utf_t::codepoint_t *src_end = src + src_len; + + typename out_utf_t::codepoint_t *dst = text; + + hb_codepoint_t unicode; + const hb_codepoint_t replacement = HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT; + + if (text_size && *text_size) + { + (*text_size)--; /* Save room for NUL-termination. */ + const typename out_utf_t::codepoint_t *dst_end = text + *text_size; + + while (src < src_end && dst < dst_end) + { + const typename in_utf_t::codepoint_t *src_next = in_utf_t::next (src, src_end, &unicode, replacement); + typename out_utf_t::codepoint_t *dst_next = out_utf_t::encode (dst, dst_end, unicode); + if (dst_next == dst) + break; /* Out-of-room. */ + + dst = dst_next; + src = src_next; + } + + *text_size = dst - text; + *dst = 0; /* NUL-terminate. */ + } + + /* Accumulate length of rest. */ + unsigned int dst_len = dst - text; + while (src < src_end) + { + src = in_utf_t::next (src, src_end, &unicode, replacement); + dst_len += out_utf_t::encode_len (unicode); + } + return dst_len; +} #define entry_score var.u16[0] #define entry_index var.u16[1] @@ -97,12 +142,68 @@ struct NameRecord return UNSUPPORTED; } - NameRecord* copy (hb_serialize_context_t *c, const void *base) const + NameRecord* copy (hb_serialize_context_t *c, const void *base +#ifdef HB_EXPERIMENTAL_API + , const hb_hashmap_t<hb_ot_name_record_ids_t, hb_bytes_t> *name_table_overrides +#endif + ) const { TRACE_SERIALIZE (this); + HB_UNUSED auto snap = c->snapshot (); auto *out = c->embed (this); if (unlikely (!out)) return_trace (nullptr); - out->offset.serialize_copy (c, offset, base, 0, hb_serialize_context_t::Tail, length); +#ifdef HB_EXPERIMENTAL_API + hb_ot_name_record_ids_t record_ids (platformID, encodingID, languageID, nameID); + hb_bytes_t* name_bytes; + + if (name_table_overrides->has (record_ids, &name_bytes)) { + hb_bytes_t encoded_bytes = *name_bytes; + char *name_str_utf16_be = nullptr; + + if (platformID != 1) + { + unsigned text_size = hb_ot_name_convert_utf<hb_utf8_t, hb_utf16_be_t> (*name_bytes, nullptr, nullptr); + + text_size++; // needs to consider NULL terminator for use in hb_ot_name_convert_utf() + unsigned byte_len = text_size * hb_utf16_be_t::codepoint_t::static_size; + name_str_utf16_be = (char *) hb_calloc (byte_len, 1); + if (!name_str_utf16_be) + { + c->revert (snap); + return_trace (nullptr); + } + hb_ot_name_convert_utf<hb_utf8_t, hb_utf16_be_t> (*name_bytes, &text_size, + (hb_utf16_be_t::codepoint_t *) name_str_utf16_be); + + unsigned encoded_byte_len = text_size * hb_utf16_be_t::codepoint_t::static_size; + if (!encoded_byte_len || !c->check_assign (out->length, encoded_byte_len, HB_SERIALIZE_ERROR_INT_OVERFLOW)) { + c->revert (snap); + hb_free (name_str_utf16_be); + return_trace (nullptr); + } + + encoded_bytes = hb_bytes_t (name_str_utf16_be, encoded_byte_len); + } + else + { + // mac platform, copy the UTF-8 string(all ascii characters) as is + if (!c->check_assign (out->length, encoded_bytes.length, HB_SERIALIZE_ERROR_INT_OVERFLOW)) { + c->revert (snap); + return_trace (nullptr); + } + } + + out->offset = 0; + c->push (); + encoded_bytes.copy (c); + c->add_link (out->offset, c->pop_pack (), hb_serialize_context_t::Tail, 0); + hb_free (name_str_utf16_be); + } + else +#endif + { + out->offset.serialize_copy (c, offset, base, 0, hb_serialize_context_t::Tail, length); + } return_trace (out); } @@ -216,29 +317,61 @@ struct name hb_requires (hb_is_source_of (Iterator, const NameRecord &))> bool serialize (hb_serialize_context_t *c, Iterator it, - const void *src_string_pool) + const void *src_string_pool +#ifdef HB_EXPERIMENTAL_API + , const hb_vector_t<hb_ot_name_record_ids_t>& insert_name_records + , const hb_hashmap_t<hb_ot_name_record_ids_t, hb_bytes_t> *name_table_overrides +#endif + ) { TRACE_SERIALIZE (this); if (unlikely (!c->extend_min ((*this)))) return_trace (false); + unsigned total_count = it.len () +#ifdef HB_EXPERIMENTAL_API + + insert_name_records.length +#endif + ; this->format = 0; - this->count = it.len (); + if (!c->check_assign (this->count, total_count, HB_SERIALIZE_ERROR_INT_OVERFLOW)) + return false; - NameRecord *name_records = (NameRecord *) hb_calloc (it.len (), NameRecord::static_size); + NameRecord *name_records = (NameRecord *) hb_calloc (total_count, NameRecord::static_size); if (unlikely (!name_records)) return_trace (false); - hb_array_t<NameRecord> records (name_records, it.len ()); + hb_array_t<NameRecord> records (name_records, total_count); for (const NameRecord& record : it) { + hb_memcpy (name_records, &record, NameRecord::static_size); + name_records++; + } + +#ifdef HB_EXPERIMENTAL_API + for (unsigned i = 0; i < insert_name_records.length; i++) + { + const hb_ot_name_record_ids_t& ids = insert_name_records[i]; + NameRecord record; + record.platformID = ids.platform_id; + record.encodingID = ids.encoding_id; + record.languageID = ids.language_id; + record.nameID = ids.name_id; + record.length = 0; // handled in NameRecord copy() + record.offset = 0; memcpy (name_records, &record, NameRecord::static_size); name_records++; } +#endif records.qsort (); - c->copy_all (records, src_string_pool); + c->copy_all (records, + src_string_pool +#ifdef HB_EXPERIMENTAL_API + , name_table_overrides +#endif + ); hb_free (records.arrayZ); @@ -256,6 +389,11 @@ struct name name *name_prime = c->serializer->start_embed<name> (); if (unlikely (!name_prime)) return_trace (false); +#ifdef HB_EXPERIMENTAL_API + const hb_hashmap_t<hb_ot_name_record_ids_t, hb_bytes_t> *name_table_overrides = + c->plan->name_table_overrides; +#endif + auto it = + nameRecordZ.as_array (count) | hb_filter (c->plan->name_ids, &NameRecord::nameID) @@ -265,10 +403,48 @@ struct name (c->plan->flags & HB_SUBSET_FLAGS_NAME_LEGACY) || namerecord.isUnicode (); }) +#ifdef HB_EXPERIMENTAL_API + | hb_filter ([&] (const NameRecord& namerecord) { + if (name_table_overrides->is_empty ()) + return true; + hb_ot_name_record_ids_t rec_ids (namerecord.platformID, + namerecord.encodingID, + namerecord.languageID, + namerecord.nameID); + + hb_bytes_t *p; + if (name_table_overrides->has (rec_ids, &p) && + (*p).length == 0) + return false; + return true; + }) +#endif ; - name_prime->serialize (c->serializer, it, std::addressof (this + stringOffset)); - return_trace (name_prime->count); +#ifdef HB_EXPERIMENTAL_API + hb_vector_t<hb_ot_name_record_ids_t> insert_name_records; + if (!name_table_overrides->is_empty ()) + { + if (unlikely (!insert_name_records.alloc (name_table_overrides->get_population ()))) + return_trace (false); + for (const auto& record_ids : name_table_overrides->keys ()) + { + if (name_table_overrides->get (record_ids).length == 0) + continue; + if (has_name_record_with_ids (record_ids)) + continue; + insert_name_records.push (record_ids); + } + } +#endif + + return (name_prime->serialize (c->serializer, it, + std::addressof (this + stringOffset) +#ifdef HB_EXPERIMENTAL_API + , insert_name_records + , name_table_overrides +#endif + )); } bool sanitize_records (hb_sanitize_context_t *c) const @@ -378,6 +554,23 @@ struct name hb_vector_t<hb_ot_name_entry_t> names; }; + private: + // sometimes NameRecords are not sorted in the font file, so use linear search + // here + bool has_name_record_with_ids (const hb_ot_name_record_ids_t& record_ids) const + { + for (const auto& record : nameRecordZ.as_array (count)) + { + if (record.platformID == record_ids.platform_id && + record.encodingID == record_ids.encoding_id && + record.languageID == record_ids.language_id && + record.nameID == record_ids.name_id) + return true; + } + return false; + } + + public: /* We only implement format 0 for now. */ HBUINT16 format; /* Format selector (=0/1). */ HBUINT16 count; /* Number of name records. */ diff --git a/thirdparty/harfbuzz/src/hb-ot-name.cc b/thirdparty/harfbuzz/src/hb-ot-name.cc index c35ac5b3dc..6adf1e8fbe 100644 --- a/thirdparty/harfbuzz/src/hb-ot-name.cc +++ b/thirdparty/harfbuzz/src/hb-ot-name.cc @@ -64,52 +64,6 @@ hb_ot_name_list_names (hb_face_t *face, return (const hb_ot_name_entry_t *) name.names; } - -template <typename in_utf_t, typename out_utf_t> -static inline unsigned int -hb_ot_name_convert_utf (hb_bytes_t bytes, - unsigned int *text_size /* IN/OUT */, - typename out_utf_t::codepoint_t *text /* OUT */) -{ - unsigned int src_len = bytes.length / sizeof (typename in_utf_t::codepoint_t); - const typename in_utf_t::codepoint_t *src = (const typename in_utf_t::codepoint_t *) bytes.arrayZ; - const typename in_utf_t::codepoint_t *src_end = src + src_len; - - typename out_utf_t::codepoint_t *dst = text; - - hb_codepoint_t unicode; - const hb_codepoint_t replacement = HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT; - - if (text_size && *text_size) - { - (*text_size)--; /* Same room for NUL-termination. */ - const typename out_utf_t::codepoint_t *dst_end = text + *text_size; - - while (src < src_end && dst < dst_end) - { - const typename in_utf_t::codepoint_t *src_next = in_utf_t::next (src, src_end, &unicode, replacement); - typename out_utf_t::codepoint_t *dst_next = out_utf_t::encode (dst, dst_end, unicode); - if (dst_next == dst) - break; /* Out-of-room. */ - - dst = dst_next; - src = src_next; - } - - *text_size = dst - text; - *dst = 0; /* NUL-terminate. */ - } - - /* Accumulate length of rest. */ - unsigned int dst_len = dst - text; - while (src < src_end) - { - src = in_utf_t::next (src, src_end, &unicode, replacement); - dst_len += out_utf_t::encode_len (unicode); - } - return dst_len; -} - template <typename utf_t> static inline unsigned int hb_ot_name_get_utf (hb_face_t *face, @@ -130,10 +84,10 @@ hb_ot_name_get_utf (hb_face_t *face, hb_bytes_t bytes = name.get_name (idx); if (width == 2) /* UTF16-BE */ - return hb_ot_name_convert_utf<hb_utf16_be_t, utf_t> (bytes, text_size, text); + return OT::hb_ot_name_convert_utf<hb_utf16_be_t, utf_t> (bytes, text_size, text); if (width == 1) /* ASCII */ - return hb_ot_name_convert_utf<hb_ascii_t, utf_t> (bytes, text_size, text); + return OT::hb_ot_name_convert_utf<hb_ascii_t, utf_t> (bytes, text_size, text); } if (text_size) @@ -227,5 +181,4 @@ hb_ot_name_get_utf32 (hb_face_t *face, return hb_ot_name_get_utf<hb_utf32_t> (face, name_id, language, text_size, text); } - #endif diff --git a/thirdparty/harfbuzz/src/hb-ot-os2-table.hh b/thirdparty/harfbuzz/src/hb-ot-os2-table.hh index c6e8fad6fc..5b017d56a6 100644 --- a/thirdparty/harfbuzz/src/hb-ot-os2-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-os2-table.hh @@ -212,17 +212,6 @@ struct OS2 TRACE_SUBSET (this); OS2 *os2_prime = c->serializer->embed (this); if (unlikely (!os2_prime)) return_trace (false); - if (c->plan->flags & HB_SUBSET_FLAGS_NO_PRUNE_UNICODE_RANGES) - return_trace (true); - - /* when --gids option is not used, no need to do collect_mapping that is - * iterating all codepoints in each subtable, which is not efficient */ - uint16_t min_cp, max_cp; - find_min_and_max_codepoint (c->plan->unicodes, &min_cp, &max_cp); - os2_prime->usFirstCharIndex = min_cp; - os2_prime->usLastCharIndex = max_cp; - - _update_unicode_ranges (c->plan->unicodes, os2_prime->ulUnicodeRange); if (c->plan->user_axes_location->has (HB_TAG ('w','g','h','t')) && !c->plan->pinned_at_default) @@ -244,6 +233,18 @@ struct OS2 return_trace (false); } + if (c->plan->flags & HB_SUBSET_FLAGS_NO_PRUNE_UNICODE_RANGES) + return_trace (true); + + /* when --gids option is not used, no need to do collect_mapping that is + * iterating all codepoints in each subtable, which is not efficient */ + uint16_t min_cp, max_cp; + find_min_and_max_codepoint (c->plan->unicodes, &min_cp, &max_cp); + os2_prime->usFirstCharIndex = min_cp; + os2_prime->usLastCharIndex = max_cp; + + _update_unicode_ranges (c->plan->unicodes, os2_prime->ulUnicodeRange); + return_trace (true); } diff --git a/thirdparty/harfbuzz/src/hb-ot-post-table-v2subset.hh b/thirdparty/harfbuzz/src/hb-ot-post-table-v2subset.hh index 4d427e5431..951e6395d6 100644 --- a/thirdparty/harfbuzz/src/hb-ot-post-table-v2subset.hh +++ b/thirdparty/harfbuzz/src/hb-ot-post-table-v2subset.hh @@ -78,14 +78,14 @@ HB_INTERNAL bool postV2Tail::subset (hb_subset_context_t *c) const post::accelerator_t _post (c->plan->source); - hb_hashmap_t<hb_bytes_t, unsigned, true> glyph_name_to_new_index; + hb_hashmap_t<hb_bytes_t, uint32_t, true> glyph_name_to_new_index; for (hb_codepoint_t new_gid = 0; new_gid < num_glyphs; new_gid++) { hb_codepoint_t old_gid = reverse_glyph_map.get (new_gid); unsigned old_index = glyphNameIndex[old_gid]; unsigned new_index; - const unsigned *new_index2; + const uint32_t *new_index2; if (old_index <= 257) new_index = old_index; else if (old_new_index_map.has (old_index, &new_index2)) { diff --git a/thirdparty/harfbuzz/src/hb-ot-post-table.hh b/thirdparty/harfbuzz/src/hb-ot-post-table.hh index 80d02ffba7..a04b80357b 100644 --- a/thirdparty/harfbuzz/src/hb-ot-post-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-post-table.hh @@ -84,7 +84,7 @@ struct post post *post_prime = c->allocate_min<post> (); if (unlikely (!post_prime)) return_trace (false); - memcpy (post_prime, this, post::min_size); + hb_memcpy (post_prime, this, post::min_size); if (!glyph_names) return_trace (c->check_assign (post_prime->version.major, 3, HB_SERIALIZE_ERROR_INT_OVERFLOW)); // Version 3 does not have any glyph names. @@ -282,7 +282,7 @@ struct post * 0x00020000 for version 2.0 * 0x00025000 for version 2.5 (deprecated) * 0x00030000 for version 3.0 */ - HBFixed italicAngle; /* Italic angle in counter-clockwise degrees + F16DOT16 italicAngle; /* Italic angle in counter-clockwise degrees * from the vertical. Zero for upright text, * negative for text that leans to the right * (forward). */ diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-normalize.cc b/thirdparty/harfbuzz/src/hb-ot-shape-normalize.cc index 7db0b25b73..897377aa15 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shape-normalize.cc +++ b/thirdparty/harfbuzz/src/hb-ot-shape-normalize.cc @@ -341,7 +341,7 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan, { unsigned int end; for (end = buffer->idx + 1; end < count; end++) - if (unlikely (_hb_glyph_info_is_unicode_mark (&buffer->info[end]))) + if (_hb_glyph_info_is_unicode_mark (&buffer->info[end])) break; if (end < count) diff --git a/thirdparty/harfbuzz/src/hb-ot-shape.cc b/thirdparty/harfbuzz/src/hb-ot-shape.cc index 7f679cfd39..bbdfc214a1 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shape.cc +++ b/thirdparty/harfbuzz/src/hb-ot-shape.cc @@ -91,9 +91,11 @@ hb_ot_shape_planner_t::hb_ot_shape_planner_t (hb_face_t *fac script_zero_marks = shaper->zero_width_marks != HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE; script_fallback_mark_positioning = shaper->fallback_position; +#ifndef HB_NO_AAT_SHAPE /* https://github.com/harfbuzz/harfbuzz/issues/1528 */ if (apply_morx && shaper != &_hb_ot_shaper_default) shaper = &_hb_ot_shaper_dumber; +#endif } void @@ -527,18 +529,20 @@ hb_set_unicode_props (hb_buffer_t *buffer) } #endif /* Or part of the Other_Grapheme_Extend that is not marks. - * As of Unicode 11 that is just: + * As of Unicode 15 that is just: * * 200C ; Other_Grapheme_Extend # Cf ZERO WIDTH NON-JOINER * FF9E..FF9F ; Other_Grapheme_Extend # Lm [2] HALFWIDTH KATAKANA VOICED SOUND MARK..HALFWIDTH KATAKANA SEMI-VOICED SOUND MARK * E0020..E007F ; Other_Grapheme_Extend # Cf [96] TAG SPACE..CANCEL TAG * * ZWNJ is special, we don't want to merge it as there's no need, and keeping - * it separate results in more granular clusters. Ignore Katakana for now. + * it separate results in more granular clusters. * Tags are used for Emoji sub-region flag sequences: * https://github.com/harfbuzz/harfbuzz/issues/1556 + * Katakana ones were requested: + * https://github.com/harfbuzz/harfbuzz/issues/3844 */ - else if (unlikely (hb_in_range<hb_codepoint_t> (info[i].codepoint, 0xE0020u, 0xE007Fu))) + else if (unlikely (hb_in_ranges<hb_codepoint_t> (info[i].codepoint, 0xFF9Eu, 0xFF9Fu, 0xE0020u, 0xE007Fu))) _hb_glyph_info_set_continuation (&info[i]); } } @@ -862,7 +866,7 @@ hb_ot_hide_default_ignorables (hb_buffer_t *buffer, } } else - hb_ot_layout_delete_glyphs_inplace (buffer, _hb_glyph_info_is_default_ignorable); + buffer->delete_glyphs_inplace (_hb_glyph_info_is_default_ignorable); } diff --git a/thirdparty/harfbuzz/src/hb-ot-shape.hh b/thirdparty/harfbuzz/src/hb-ot-shape.hh index cd6f15cbe2..ace28602f6 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shape.hh +++ b/thirdparty/harfbuzz/src/hb-ot-shape.hh @@ -51,7 +51,7 @@ struct hb_ot_shape_plan_key_t bool equal (const hb_ot_shape_plan_key_t *other) { - return 0 == memcmp (this, other, sizeof (*this)); + return 0 == hb_memcmp (this, other, sizeof (*this)); } }; diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-arabic.cc b/thirdparty/harfbuzz/src/hb-ot-shaper-arabic.cc index ed2748b828..2332ae3697 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shaper-arabic.cc +++ b/thirdparty/harfbuzz/src/hb-ot-shaper-arabic.cc @@ -161,22 +161,23 @@ static const struct arabic_state_table_entry { }; -static void +static bool arabic_fallback_shape (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer); -static void +static bool record_stch (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer); -static void +static bool deallocate_buffer_var (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) { HB_BUFFER_DEALLOCATE_VAR (buffer, arabic_shaping_action); + return false; } static void @@ -412,19 +413,19 @@ setup_masks_arabic (const hb_ot_shape_plan_t *plan, setup_masks_arabic_plan (arabic_plan, buffer, plan->props.script); } -static void +static bool arabic_fallback_shape (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) { #ifdef HB_NO_OT_SHAPER_ARABIC_FALLBACK - return; + return false; #endif const arabic_shape_plan_t *arabic_plan = (const arabic_shape_plan_t *) plan->data; if (!arabic_plan->do_fallback) - return; + return false; retry: arabic_fallback_plan_t *fallback_plan = arabic_plan->fallback_plan; @@ -440,6 +441,7 @@ retry: } arabic_fallback_plan_shape (fallback_plan, font, buffer); + return true; } /* @@ -450,14 +452,14 @@ retry: * marks can use it as well. */ -static void +static bool record_stch (const hb_ot_shape_plan_t *plan, hb_font_t *font HB_UNUSED, hb_buffer_t *buffer) { const arabic_shape_plan_t *arabic_plan = (const arabic_shape_plan_t *) plan->data; if (!arabic_plan->has_stch) - return; + return false; /* 'stch' feature was just applied. Look for anything that multiplied, * and record it for stch treatment later. Note that rtlm, frac, etc @@ -473,6 +475,7 @@ record_stch (const hb_ot_shape_plan_t *plan, info[i].arabic_shaping_action() = comp % 2 ? STCH_REPEATING : STCH_FIXED; buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_ARABIC_HAS_STCH; } + return false; } static void diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-default.cc b/thirdparty/harfbuzz/src/hb-ot-shaper-default.cc index 2f6f499eec..f0404a4d2c 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shaper-default.cc +++ b/thirdparty/harfbuzz/src/hb-ot-shaper-default.cc @@ -49,6 +49,7 @@ const hb_ot_shaper_t _hb_ot_shaper_default = true, /* fallback_position */ }; +#ifndef HB_NO_AAT_SHAPE /* Same as default but no mark advance zeroing / fallback positioning. * Dumbest shaper ever, basically. */ const hb_ot_shaper_t _hb_ot_shaper_dumber = @@ -68,6 +69,7 @@ const hb_ot_shaper_t _hb_ot_shaper_dumber = HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE, false, /* fallback_position */ }; +#endif #endif diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-indic-machine.hh b/thirdparty/harfbuzz/src/hb-ot-shaper-indic-machine.hh index d52b13f616..d6c67b81bd 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shaper-indic-machine.hh +++ b/thirdparty/harfbuzz/src/hb-ot-shaper-indic-machine.hh @@ -53,7 +53,7 @@ enum indic_syllable_type_t { }; -#line 57 "hb-ot-shaper-indic-machine.hh" +#line 54 "hb-ot-shaper-indic-machine.hh" #define indic_syllable_machine_ex_A 9u #define indic_syllable_machine_ex_C 1u #define indic_syllable_machine_ex_CM 16u @@ -61,6 +61,7 @@ enum indic_syllable_type_t { #define indic_syllable_machine_ex_DOTTEDCIRCLE 11u #define indic_syllable_machine_ex_H 4u #define indic_syllable_machine_ex_M 7u +#define indic_syllable_machine_ex_MPst 13u #define indic_syllable_machine_ex_N 3u #define indic_syllable_machine_ex_PLACEHOLDER 10u #define indic_syllable_machine_ex_RS 12u @@ -75,268 +76,302 @@ enum indic_syllable_type_t { #define indic_syllable_machine_ex_ZWNJ 5u -#line 79 "hb-ot-shaper-indic-machine.hh" +#line 75 "hb-ot-shaper-indic-machine.hh" static const unsigned char _indic_syllable_machine_trans_keys[] = { - 8u, 8u, 4u, 8u, 5u, 7u, 5u, 8u, 4u, 8u, 4u, 12u, 4u, 8u, 8u, 8u, - 5u, 7u, 5u, 8u, 4u, 8u, 4u, 12u, 4u, 12u, 4u, 12u, 8u, 8u, 5u, 7u, - 5u, 8u, 4u, 8u, 4u, 8u, 4u, 12u, 8u, 8u, 5u, 7u, 5u, 8u, 4u, 8u, - 4u, 8u, 5u, 8u, 8u, 8u, 1u, 18u, 3u, 16u, 3u, 16u, 4u, 16u, 1u, 15u, - 5u, 9u, 5u, 9u, 9u, 9u, 5u, 9u, 1u, 15u, 1u, 15u, 1u, 15u, 3u, 9u, - 4u, 9u, 5u, 9u, 4u, 9u, 5u, 9u, 3u, 9u, 5u, 9u, 3u, 16u, 3u, 16u, - 3u, 16u, 3u, 16u, 4u, 16u, 1u, 15u, 3u, 16u, 3u, 16u, 4u, 16u, 1u, 15u, - 5u, 9u, 9u, 9u, 5u, 9u, 1u, 15u, 1u, 15u, 3u, 9u, 4u, 9u, 5u, 9u, - 4u, 9u, 5u, 9u, 5u, 9u, 3u, 9u, 5u, 9u, 3u, 16u, 3u, 16u, 4u, 8u, - 3u, 16u, 3u, 16u, 4u, 16u, 1u, 15u, 3u, 16u, 1u, 15u, 5u, 9u, 9u, 9u, - 5u, 9u, 1u, 15u, 1u, 15u, 3u, 9u, 4u, 9u, 5u, 9u, 3u, 16u, 4u, 9u, - 5u, 9u, 5u, 9u, 3u, 9u, 5u, 9u, 3u, 16u, 4u, 12u, 4u, 8u, 3u, 16u, - 3u, 16u, 4u, 16u, 1u, 15u, 3u, 16u, 1u, 15u, 5u, 9u, 9u, 9u, 5u, 9u, - 1u, 15u, 1u, 15u, 3u, 9u, 4u, 9u, 5u, 9u, 3u, 16u, 4u, 9u, 5u, 9u, - 5u, 9u, 3u, 9u, 5u, 9u, 1u, 16u, 3u, 16u, 1u, 16u, 4u, 12u, 5u, 9u, - 9u, 9u, 5u, 9u, 1u, 15u, 3u, 9u, 5u, 9u, 5u, 9u, 9u, 9u, 5u, 9u, - 1u, 15u, 0 + 8u, 8u, 4u, 13u, 5u, 13u, 5u, 13u, 13u, 13u, 4u, 13u, 4u, 13u, 4u, 13u, + 8u, 8u, 5u, 13u, 5u, 13u, 13u, 13u, 4u, 13u, 4u, 13u, 4u, 13u, 4u, 13u, + 8u, 8u, 5u, 13u, 5u, 13u, 13u, 13u, 4u, 13u, 4u, 13u, 4u, 13u, 8u, 8u, + 5u, 13u, 5u, 13u, 13u, 13u, 4u, 13u, 4u, 13u, 5u, 13u, 8u, 8u, 1u, 18u, + 3u, 16u, 3u, 16u, 4u, 16u, 1u, 15u, 5u, 9u, 5u, 9u, 9u, 9u, 5u, 9u, + 1u, 15u, 1u, 15u, 1u, 15u, 3u, 13u, 4u, 13u, 5u, 13u, 5u, 13u, 4u, 13u, + 5u, 9u, 3u, 9u, 5u, 9u, 3u, 16u, 3u, 16u, 3u, 16u, 3u, 16u, 4u, 16u, + 1u, 15u, 3u, 16u, 3u, 16u, 4u, 16u, 1u, 15u, 5u, 9u, 9u, 9u, 5u, 9u, + 1u, 15u, 1u, 15u, 3u, 13u, 4u, 13u, 5u, 13u, 5u, 13u, 4u, 13u, 5u, 9u, + 5u, 9u, 3u, 9u, 5u, 9u, 3u, 16u, 3u, 16u, 4u, 13u, 3u, 16u, 3u, 16u, + 4u, 16u, 1u, 15u, 3u, 16u, 1u, 15u, 5u, 9u, 9u, 9u, 5u, 9u, 1u, 15u, + 1u, 15u, 3u, 13u, 4u, 13u, 5u, 13u, 5u, 13u, 3u, 16u, 4u, 13u, 5u, 9u, + 5u, 9u, 3u, 9u, 5u, 9u, 3u, 16u, 4u, 13u, 4u, 13u, 3u, 16u, 3u, 16u, + 4u, 16u, 1u, 15u, 3u, 16u, 1u, 15u, 5u, 9u, 9u, 9u, 5u, 9u, 1u, 15u, + 1u, 15u, 3u, 13u, 4u, 13u, 5u, 13u, 5u, 13u, 3u, 16u, 4u, 13u, 5u, 9u, + 5u, 9u, 3u, 9u, 5u, 9u, 1u, 16u, 3u, 16u, 1u, 16u, 4u, 13u, 5u, 13u, + 5u, 13u, 9u, 9u, 5u, 9u, 1u, 15u, 3u, 9u, 5u, 9u, 5u, 9u, 9u, 9u, + 5u, 9u, 1u, 15u, 0 }; static const char _indic_syllable_machine_key_spans[] = { - 1, 5, 3, 4, 5, 9, 5, 1, - 3, 4, 5, 9, 9, 9, 1, 3, - 4, 5, 5, 9, 1, 3, 4, 5, - 5, 4, 1, 18, 14, 14, 13, 15, - 5, 5, 1, 5, 15, 15, 15, 7, - 6, 5, 6, 5, 7, 5, 14, 14, - 14, 14, 13, 15, 14, 14, 13, 15, - 5, 1, 5, 15, 15, 7, 6, 5, - 6, 5, 5, 7, 5, 14, 14, 5, - 14, 14, 13, 15, 14, 15, 5, 1, - 5, 15, 15, 7, 6, 5, 14, 6, - 5, 5, 7, 5, 14, 9, 5, 14, - 14, 13, 15, 14, 15, 5, 1, 5, - 15, 15, 7, 6, 5, 14, 6, 5, - 5, 7, 5, 16, 14, 16, 9, 5, - 1, 5, 15, 7, 5, 5, 1, 5, - 15 + 1, 10, 9, 9, 1, 10, 10, 10, + 1, 9, 9, 1, 10, 10, 10, 10, + 1, 9, 9, 1, 10, 10, 10, 1, + 9, 9, 1, 10, 10, 9, 1, 18, + 14, 14, 13, 15, 5, 5, 1, 5, + 15, 15, 15, 11, 10, 9, 9, 10, + 5, 7, 5, 14, 14, 14, 14, 13, + 15, 14, 14, 13, 15, 5, 1, 5, + 15, 15, 11, 10, 9, 9, 10, 5, + 5, 7, 5, 14, 14, 10, 14, 14, + 13, 15, 14, 15, 5, 1, 5, 15, + 15, 11, 10, 9, 9, 14, 10, 5, + 5, 7, 5, 14, 10, 10, 14, 14, + 13, 15, 14, 15, 5, 1, 5, 15, + 15, 11, 10, 9, 9, 14, 10, 5, + 5, 7, 5, 16, 14, 16, 10, 9, + 9, 1, 5, 15, 7, 5, 5, 1, + 5, 15 }; static const short _indic_syllable_machine_index_offsets[] = { - 0, 2, 8, 12, 17, 23, 33, 39, - 41, 45, 50, 56, 66, 76, 86, 88, - 92, 97, 103, 109, 119, 121, 125, 130, - 136, 142, 147, 149, 168, 183, 198, 212, - 228, 234, 240, 242, 248, 264, 280, 296, - 304, 311, 317, 324, 330, 338, 344, 359, - 374, 389, 404, 418, 434, 449, 464, 478, - 494, 500, 502, 508, 524, 540, 548, 555, - 561, 568, 574, 580, 588, 594, 609, 624, - 630, 645, 660, 674, 690, 705, 721, 727, - 729, 735, 751, 767, 775, 782, 788, 803, - 810, 816, 822, 830, 836, 851, 861, 867, - 882, 897, 911, 927, 942, 958, 964, 966, - 972, 988, 1004, 1012, 1019, 1025, 1040, 1047, - 1053, 1059, 1067, 1073, 1090, 1105, 1122, 1132, - 1138, 1140, 1146, 1162, 1170, 1176, 1182, 1184, - 1190 + 0, 2, 13, 23, 33, 35, 46, 57, + 68, 70, 80, 90, 92, 103, 114, 125, + 136, 138, 148, 158, 160, 171, 182, 193, + 195, 205, 215, 217, 228, 239, 249, 251, + 270, 285, 300, 314, 330, 336, 342, 344, + 350, 366, 382, 398, 410, 421, 431, 441, + 452, 458, 466, 472, 487, 502, 517, 532, + 546, 562, 577, 592, 606, 622, 628, 630, + 636, 652, 668, 680, 691, 701, 711, 722, + 728, 734, 742, 748, 763, 778, 789, 804, + 819, 833, 849, 864, 880, 886, 888, 894, + 910, 926, 938, 949, 959, 969, 984, 995, + 1001, 1007, 1015, 1021, 1036, 1047, 1058, 1073, + 1088, 1102, 1118, 1133, 1149, 1155, 1157, 1163, + 1179, 1195, 1207, 1218, 1228, 1238, 1253, 1264, + 1270, 1276, 1284, 1290, 1307, 1322, 1339, 1350, + 1360, 1370, 1372, 1378, 1394, 1402, 1408, 1414, + 1416, 1422 }; static const unsigned char _indic_syllable_machine_indicies[] = { - 1, 0, 2, 3, 3, 4, 1, 0, - 3, 3, 4, 0, 3, 3, 4, 1, - 0, 5, 3, 3, 4, 1, 0, 2, - 3, 3, 4, 1, 0, 0, 0, 6, - 0, 8, 9, 9, 10, 11, 7, 11, - 7, 9, 9, 10, 7, 9, 9, 10, - 11, 7, 12, 9, 9, 10, 11, 7, - 8, 9, 9, 10, 11, 7, 7, 7, - 13, 7, 8, 9, 9, 10, 11, 7, - 7, 7, 14, 7, 16, 17, 17, 18, - 19, 15, 15, 15, 20, 15, 19, 15, - 17, 17, 18, 21, 17, 17, 18, 19, - 15, 16, 17, 17, 18, 19, 15, 22, - 17, 17, 18, 19, 15, 24, 25, 25, - 26, 27, 23, 23, 23, 28, 23, 27, - 23, 25, 25, 26, 23, 25, 25, 26, - 27, 23, 24, 25, 25, 26, 27, 23, - 29, 25, 25, 26, 27, 23, 17, 17, - 18, 1, 0, 31, 30, 33, 34, 35, - 36, 37, 38, 18, 19, 39, 40, 40, - 20, 32, 41, 42, 43, 44, 45, 32, - 47, 48, 49, 50, 4, 1, 51, 46, - 46, 6, 46, 46, 46, 52, 46, 53, - 48, 54, 54, 4, 1, 51, 46, 46, - 46, 46, 46, 46, 52, 46, 48, 54, - 54, 4, 1, 51, 46, 46, 46, 46, - 46, 46, 52, 46, 33, 46, 46, 46, - 55, 56, 46, 1, 51, 46, 46, 46, - 46, 46, 33, 46, 57, 57, 46, 1, - 51, 46, 51, 46, 46, 58, 51, 46, - 51, 46, 51, 46, 46, 46, 51, 46, - 33, 46, 59, 46, 57, 57, 46, 1, - 51, 46, 46, 46, 46, 46, 33, 46, - 33, 46, 46, 46, 57, 57, 46, 1, - 51, 46, 46, 46, 46, 46, 33, 46, - 33, 46, 46, 46, 57, 56, 46, 1, - 51, 46, 46, 46, 46, 46, 33, 46, - 60, 61, 62, 62, 4, 1, 51, 46, - 61, 62, 62, 4, 1, 51, 46, 62, - 62, 4, 1, 51, 46, 63, 64, 64, - 4, 1, 51, 46, 55, 65, 46, 1, - 51, 46, 55, 46, 57, 57, 46, 1, - 51, 46, 57, 65, 46, 1, 51, 46, - 47, 48, 54, 54, 4, 1, 51, 46, - 46, 46, 46, 46, 46, 52, 46, 47, - 48, 49, 54, 4, 1, 51, 46, 46, - 6, 46, 46, 46, 52, 46, 67, 68, - 69, 70, 10, 11, 71, 66, 66, 14, - 66, 66, 66, 72, 66, 73, 68, 74, - 70, 10, 11, 71, 66, 66, 66, 66, - 66, 66, 72, 66, 68, 74, 70, 10, - 11, 71, 66, 66, 66, 66, 66, 66, - 72, 66, 75, 66, 66, 66, 76, 77, - 66, 11, 71, 66, 66, 66, 66, 66, - 75, 66, 78, 68, 79, 80, 10, 11, - 71, 66, 66, 13, 66, 66, 66, 72, - 66, 81, 68, 74, 74, 10, 11, 71, - 66, 66, 66, 66, 66, 66, 72, 66, - 68, 74, 74, 10, 11, 71, 66, 66, - 66, 66, 66, 66, 72, 66, 75, 66, - 66, 66, 82, 77, 66, 11, 71, 66, - 66, 66, 66, 66, 75, 66, 71, 66, - 66, 83, 71, 66, 71, 66, 71, 66, - 66, 66, 71, 66, 75, 66, 84, 66, - 82, 82, 66, 11, 71, 66, 66, 66, - 66, 66, 75, 66, 75, 66, 66, 66, - 82, 82, 66, 11, 71, 66, 66, 66, - 66, 66, 75, 66, 85, 86, 87, 87, - 10, 11, 71, 66, 86, 87, 87, 10, - 11, 71, 66, 87, 87, 10, 11, 71, - 66, 88, 89, 89, 10, 11, 71, 66, - 76, 90, 66, 11, 71, 66, 82, 82, - 66, 11, 71, 66, 76, 66, 82, 82, - 66, 11, 71, 66, 82, 90, 66, 11, - 71, 66, 78, 68, 74, 74, 10, 11, - 71, 66, 66, 66, 66, 66, 66, 72, - 66, 78, 68, 79, 74, 10, 11, 71, - 66, 66, 13, 66, 66, 66, 72, 66, - 8, 9, 9, 10, 11, 66, 67, 68, - 74, 70, 10, 11, 71, 66, 66, 66, - 66, 66, 66, 72, 66, 92, 36, 93, - 93, 18, 19, 39, 91, 91, 91, 91, - 91, 91, 43, 91, 36, 93, 93, 18, - 19, 39, 91, 91, 91, 91, 91, 91, - 43, 91, 94, 91, 91, 91, 95, 96, - 91, 19, 39, 91, 91, 91, 91, 91, - 94, 91, 35, 36, 97, 98, 18, 19, - 39, 91, 91, 20, 91, 91, 91, 43, - 91, 94, 91, 91, 91, 99, 96, 91, - 19, 39, 91, 91, 91, 91, 91, 94, - 91, 39, 91, 91, 100, 39, 91, 39, - 91, 39, 91, 91, 91, 39, 91, 94, - 91, 101, 91, 99, 99, 91, 19, 39, - 91, 91, 91, 91, 91, 94, 91, 94, - 91, 91, 91, 99, 99, 91, 19, 39, - 91, 91, 91, 91, 91, 94, 91, 102, - 103, 104, 104, 18, 19, 39, 91, 103, - 104, 104, 18, 19, 39, 91, 104, 104, - 18, 19, 39, 91, 35, 36, 93, 93, - 18, 19, 39, 91, 91, 91, 91, 91, - 91, 43, 91, 105, 106, 106, 18, 19, - 39, 91, 95, 107, 91, 19, 39, 91, - 99, 99, 91, 19, 39, 91, 95, 91, - 99, 99, 91, 19, 39, 91, 99, 107, - 91, 19, 39, 91, 35, 36, 97, 93, - 18, 19, 39, 91, 91, 20, 91, 91, - 91, 43, 91, 16, 17, 17, 18, 19, - 108, 108, 108, 20, 108, 16, 17, 17, - 18, 19, 108, 110, 111, 112, 113, 26, - 27, 114, 109, 109, 28, 109, 109, 109, - 115, 109, 116, 111, 113, 113, 26, 27, - 114, 109, 109, 109, 109, 109, 109, 115, - 109, 111, 113, 113, 26, 27, 114, 109, - 109, 109, 109, 109, 109, 115, 109, 117, - 109, 109, 109, 118, 119, 109, 27, 114, - 109, 109, 109, 109, 109, 117, 109, 110, - 111, 112, 40, 26, 27, 114, 109, 109, - 28, 109, 109, 109, 115, 109, 117, 109, - 109, 109, 120, 119, 109, 27, 114, 109, - 109, 109, 109, 109, 117, 109, 114, 109, - 109, 121, 114, 109, 114, 109, 114, 109, - 109, 109, 114, 109, 117, 109, 122, 109, - 120, 120, 109, 27, 114, 109, 109, 109, - 109, 109, 117, 109, 117, 109, 109, 109, - 120, 120, 109, 27, 114, 109, 109, 109, - 109, 109, 117, 109, 123, 124, 125, 125, - 26, 27, 114, 109, 124, 125, 125, 26, - 27, 114, 109, 125, 125, 26, 27, 114, - 109, 110, 111, 113, 113, 26, 27, 114, - 109, 109, 109, 109, 109, 109, 115, 109, - 126, 127, 127, 26, 27, 114, 109, 118, - 128, 109, 27, 114, 109, 120, 120, 109, - 27, 114, 109, 118, 109, 120, 120, 109, - 27, 114, 109, 120, 128, 109, 27, 114, - 109, 33, 34, 35, 36, 97, 93, 18, - 19, 39, 40, 40, 20, 91, 91, 33, - 43, 91, 47, 129, 49, 50, 4, 1, - 51, 46, 46, 6, 46, 46, 46, 52, - 46, 33, 34, 35, 36, 130, 131, 18, - 132, 133, 46, 40, 20, 46, 46, 33, - 43, 46, 16, 134, 134, 18, 132, 51, - 46, 46, 20, 46, 133, 46, 46, 135, - 133, 46, 133, 46, 133, 46, 46, 46, - 133, 46, 33, 46, 59, 16, 134, 134, - 18, 132, 51, 46, 46, 46, 46, 46, - 33, 46, 137, 136, 138, 138, 136, 31, - 139, 136, 138, 138, 136, 31, 139, 136, - 139, 136, 136, 140, 139, 136, 139, 136, - 139, 136, 136, 136, 139, 136, 33, 108, - 108, 108, 108, 108, 108, 108, 108, 40, - 108, 108, 108, 108, 33, 108, 0 + 1, 0, 2, 3, 3, 4, 5, 0, + 0, 0, 0, 4, 0, 3, 3, 4, + 6, 0, 0, 0, 0, 4, 0, 3, + 3, 4, 5, 0, 0, 0, 0, 4, + 0, 4, 0, 7, 3, 3, 4, 5, + 0, 0, 0, 0, 4, 0, 2, 3, + 3, 4, 5, 0, 0, 0, 8, 4, + 0, 10, 11, 11, 12, 13, 9, 9, + 9, 9, 12, 9, 14, 9, 11, 11, + 12, 15, 9, 9, 9, 9, 12, 9, + 11, 11, 12, 13, 9, 9, 9, 9, + 12, 9, 12, 9, 16, 11, 11, 12, + 13, 9, 9, 9, 9, 12, 9, 10, + 11, 11, 12, 13, 9, 9, 9, 17, + 12, 9, 10, 11, 11, 12, 13, 9, + 9, 9, 18, 12, 9, 20, 21, 21, + 22, 23, 19, 19, 19, 24, 22, 19, + 25, 19, 21, 21, 22, 27, 26, 26, + 26, 26, 22, 26, 21, 21, 22, 23, + 19, 19, 19, 19, 22, 19, 22, 26, + 20, 21, 21, 22, 23, 19, 19, 19, + 19, 22, 19, 28, 21, 21, 22, 23, + 19, 19, 19, 19, 22, 19, 30, 31, + 31, 32, 33, 29, 29, 29, 34, 32, + 29, 35, 29, 31, 31, 32, 36, 29, + 29, 29, 29, 32, 29, 31, 31, 32, + 33, 29, 29, 29, 29, 32, 29, 32, + 29, 30, 31, 31, 32, 33, 29, 29, + 29, 29, 32, 29, 37, 31, 31, 32, + 33, 29, 29, 29, 29, 32, 29, 21, + 21, 22, 38, 0, 0, 0, 0, 22, + 0, 40, 39, 42, 43, 44, 45, 46, + 47, 22, 23, 48, 49, 49, 24, 22, + 50, 51, 52, 53, 54, 41, 56, 57, + 58, 59, 4, 5, 60, 55, 55, 8, + 4, 55, 55, 61, 55, 62, 57, 63, + 63, 4, 5, 60, 55, 55, 55, 4, + 55, 55, 61, 55, 57, 63, 63, 4, + 5, 60, 55, 55, 55, 4, 55, 55, + 61, 55, 42, 55, 55, 55, 64, 65, + 55, 1, 60, 55, 55, 55, 55, 55, + 42, 55, 66, 66, 55, 1, 60, 55, + 60, 55, 55, 67, 60, 55, 60, 55, + 60, 55, 55, 55, 60, 55, 42, 55, + 68, 55, 66, 66, 55, 1, 60, 55, + 55, 55, 55, 55, 42, 55, 42, 55, + 55, 55, 66, 66, 55, 1, 60, 55, + 55, 55, 55, 55, 42, 55, 42, 55, + 55, 55, 66, 65, 55, 1, 60, 55, + 55, 55, 55, 55, 42, 55, 69, 70, + 71, 71, 4, 5, 60, 55, 55, 55, + 4, 55, 70, 71, 71, 4, 5, 60, + 55, 55, 55, 4, 55, 71, 71, 4, + 5, 60, 55, 55, 55, 4, 55, 60, + 55, 55, 67, 60, 55, 55, 55, 4, + 55, 72, 73, 73, 4, 5, 60, 55, + 55, 55, 4, 55, 64, 74, 55, 1, + 60, 55, 64, 55, 66, 66, 55, 1, + 60, 55, 66, 74, 55, 1, 60, 55, + 56, 57, 63, 63, 4, 5, 60, 55, + 55, 55, 4, 55, 55, 61, 55, 56, + 57, 58, 63, 4, 5, 60, 55, 55, + 8, 4, 55, 55, 61, 55, 76, 77, + 78, 79, 12, 13, 80, 75, 75, 18, + 12, 75, 75, 81, 75, 82, 77, 83, + 79, 12, 13, 80, 75, 75, 75, 12, + 75, 75, 81, 75, 77, 83, 79, 12, + 13, 80, 75, 75, 75, 12, 75, 75, + 81, 75, 84, 75, 75, 75, 85, 86, + 75, 14, 80, 75, 75, 75, 75, 75, + 84, 75, 87, 77, 88, 89, 12, 13, + 80, 75, 75, 17, 12, 75, 75, 81, + 75, 90, 77, 83, 83, 12, 13, 80, + 75, 75, 75, 12, 75, 75, 81, 75, + 77, 83, 83, 12, 13, 80, 75, 75, + 75, 12, 75, 75, 81, 75, 84, 75, + 75, 75, 91, 86, 75, 14, 80, 75, + 75, 75, 75, 75, 84, 75, 80, 75, + 75, 92, 80, 75, 80, 75, 80, 75, + 75, 75, 80, 75, 84, 75, 93, 75, + 91, 91, 75, 14, 80, 75, 75, 75, + 75, 75, 84, 75, 84, 75, 75, 75, + 91, 91, 75, 14, 80, 75, 75, 75, + 75, 75, 84, 75, 94, 95, 96, 96, + 12, 13, 80, 75, 75, 75, 12, 75, + 95, 96, 96, 12, 13, 80, 75, 75, + 75, 12, 75, 96, 96, 12, 13, 80, + 75, 75, 75, 12, 75, 80, 75, 75, + 92, 80, 75, 75, 75, 12, 75, 97, + 98, 98, 12, 13, 80, 75, 75, 75, + 12, 75, 85, 99, 75, 14, 80, 75, + 91, 91, 75, 14, 80, 75, 85, 75, + 91, 91, 75, 14, 80, 75, 91, 99, + 75, 14, 80, 75, 87, 77, 83, 83, + 12, 13, 80, 75, 75, 75, 12, 75, + 75, 81, 75, 87, 77, 88, 83, 12, + 13, 80, 75, 75, 17, 12, 75, 75, + 81, 75, 10, 11, 11, 12, 13, 75, + 75, 75, 75, 12, 75, 76, 77, 83, + 79, 12, 13, 80, 75, 75, 75, 12, + 75, 75, 81, 75, 101, 45, 102, 102, + 22, 23, 48, 100, 100, 100, 22, 100, + 100, 52, 100, 45, 102, 102, 22, 23, + 48, 100, 100, 100, 22, 100, 100, 52, + 100, 103, 100, 100, 100, 104, 105, 100, + 25, 48, 100, 100, 100, 100, 100, 103, + 100, 44, 45, 106, 107, 22, 23, 48, + 100, 100, 24, 22, 100, 100, 52, 100, + 103, 100, 100, 100, 108, 105, 100, 25, + 48, 100, 100, 100, 100, 100, 103, 100, + 48, 100, 100, 109, 48, 100, 48, 100, + 48, 100, 100, 100, 48, 100, 103, 100, + 110, 100, 108, 108, 100, 25, 48, 100, + 100, 100, 100, 100, 103, 100, 103, 100, + 100, 100, 108, 108, 100, 25, 48, 100, + 100, 100, 100, 100, 103, 100, 111, 112, + 113, 113, 22, 23, 48, 100, 100, 100, + 22, 100, 112, 113, 113, 22, 23, 48, + 100, 100, 100, 22, 100, 113, 113, 22, + 23, 48, 100, 100, 100, 22, 100, 48, + 100, 100, 109, 48, 100, 100, 100, 22, + 100, 44, 45, 102, 102, 22, 23, 48, + 100, 100, 100, 22, 100, 100, 52, 100, + 114, 115, 115, 22, 23, 48, 100, 100, + 100, 22, 100, 104, 116, 100, 25, 48, + 100, 108, 108, 100, 25, 48, 100, 104, + 100, 108, 108, 100, 25, 48, 100, 108, + 116, 100, 25, 48, 100, 44, 45, 106, + 102, 22, 23, 48, 100, 100, 24, 22, + 100, 100, 52, 100, 20, 21, 21, 22, + 23, 117, 117, 117, 24, 22, 117, 20, + 21, 21, 22, 23, 117, 117, 117, 117, + 22, 117, 119, 120, 121, 122, 32, 33, + 123, 118, 118, 34, 32, 118, 118, 124, + 118, 125, 120, 122, 122, 32, 33, 123, + 118, 118, 118, 32, 118, 118, 124, 118, + 120, 122, 122, 32, 33, 123, 118, 118, + 118, 32, 118, 118, 124, 118, 126, 118, + 118, 118, 127, 128, 118, 35, 123, 118, + 118, 118, 118, 118, 126, 118, 119, 120, + 121, 49, 32, 33, 123, 118, 118, 34, + 32, 118, 118, 124, 118, 126, 118, 118, + 118, 129, 128, 118, 35, 123, 118, 118, + 118, 118, 118, 126, 118, 123, 118, 118, + 130, 123, 118, 123, 118, 123, 118, 118, + 118, 123, 118, 126, 118, 131, 118, 129, + 129, 118, 35, 123, 118, 118, 118, 118, + 118, 126, 118, 126, 118, 118, 118, 129, + 129, 118, 35, 123, 118, 118, 118, 118, + 118, 126, 118, 132, 133, 134, 134, 32, + 33, 123, 118, 118, 118, 32, 118, 133, + 134, 134, 32, 33, 123, 118, 118, 118, + 32, 118, 134, 134, 32, 33, 123, 118, + 118, 118, 32, 118, 123, 118, 118, 130, + 123, 118, 118, 118, 32, 118, 119, 120, + 122, 122, 32, 33, 123, 118, 118, 118, + 32, 118, 118, 124, 118, 135, 136, 136, + 32, 33, 123, 118, 118, 118, 32, 118, + 127, 137, 118, 35, 123, 118, 129, 129, + 118, 35, 123, 118, 127, 118, 129, 129, + 118, 35, 123, 118, 129, 137, 118, 35, + 123, 118, 42, 43, 44, 45, 106, 102, + 22, 23, 48, 49, 49, 24, 22, 100, + 42, 52, 100, 56, 138, 58, 59, 4, + 5, 60, 55, 55, 8, 4, 55, 55, + 61, 55, 42, 43, 44, 45, 139, 140, + 22, 141, 142, 55, 49, 24, 22, 55, + 42, 52, 55, 20, 143, 143, 22, 141, + 60, 55, 55, 24, 22, 55, 60, 55, + 55, 67, 60, 55, 55, 55, 22, 55, + 142, 55, 55, 144, 142, 55, 55, 55, + 22, 55, 142, 55, 142, 55, 55, 55, + 142, 55, 42, 55, 68, 20, 143, 143, + 22, 141, 60, 55, 55, 55, 22, 55, + 42, 55, 146, 145, 147, 147, 145, 40, + 148, 145, 147, 147, 145, 40, 148, 145, + 148, 145, 145, 149, 148, 145, 148, 145, + 148, 145, 145, 145, 148, 145, 42, 117, + 117, 117, 117, 117, 117, 117, 117, 49, + 117, 117, 117, 117, 42, 117, 0 }; static const unsigned char _indic_syllable_machine_trans_targs[] = { - 27, 33, 38, 2, 39, 45, 46, 27, - 55, 8, 61, 56, 68, 69, 72, 27, - 77, 15, 83, 78, 86, 27, 91, 27, - 100, 21, 106, 101, 109, 114, 27, 125, - 27, 28, 48, 73, 75, 93, 94, 79, - 95, 115, 116, 87, 123, 128, 27, 29, - 31, 5, 47, 34, 42, 30, 1, 32, - 36, 0, 35, 37, 40, 41, 3, 43, - 4, 44, 27, 49, 51, 12, 71, 57, - 64, 50, 6, 52, 66, 59, 53, 11, - 70, 54, 7, 58, 60, 62, 63, 9, - 65, 10, 67, 27, 74, 17, 76, 89, - 81, 13, 92, 14, 80, 82, 84, 85, - 16, 88, 18, 90, 27, 27, 96, 98, - 19, 23, 102, 110, 97, 99, 112, 104, - 20, 103, 105, 107, 108, 22, 111, 24, - 113, 117, 118, 122, 119, 120, 25, 121, - 27, 124, 26, 126, 127 + 31, 37, 42, 2, 43, 46, 4, 50, + 51, 31, 60, 9, 66, 69, 61, 11, + 74, 75, 78, 31, 83, 17, 89, 92, + 93, 84, 31, 19, 98, 31, 107, 24, + 113, 116, 117, 108, 26, 122, 127, 31, + 134, 31, 32, 53, 79, 81, 100, 101, + 85, 102, 123, 124, 94, 132, 137, 31, + 33, 35, 6, 52, 38, 47, 34, 1, + 36, 40, 0, 39, 41, 44, 45, 3, + 48, 5, 49, 31, 54, 56, 14, 77, + 62, 70, 55, 7, 57, 72, 64, 58, + 13, 76, 59, 8, 63, 65, 67, 68, + 10, 71, 12, 73, 31, 80, 20, 82, + 96, 87, 15, 99, 16, 86, 88, 90, + 91, 18, 95, 21, 97, 31, 31, 103, + 105, 22, 27, 109, 118, 104, 106, 120, + 111, 23, 110, 112, 114, 115, 25, 119, + 28, 121, 125, 126, 131, 128, 129, 29, + 130, 31, 133, 30, 135, 136 }; static const char _indic_syllable_machine_trans_actions[] = { - 1, 0, 2, 0, 2, 2, 2, 3, - 2, 0, 2, 0, 2, 2, 2, 4, - 2, 0, 5, 0, 5, 6, 2, 7, - 2, 0, 2, 0, 2, 2, 8, 0, - 11, 2, 2, 5, 0, 12, 12, 0, - 2, 5, 2, 5, 2, 0, 13, 2, - 0, 0, 2, 0, 2, 2, 0, 2, - 2, 0, 0, 2, 2, 2, 0, 0, - 0, 2, 14, 2, 0, 0, 2, 0, - 2, 2, 0, 2, 2, 2, 2, 0, + 1, 0, 2, 0, 2, 0, 0, 2, + 2, 3, 2, 0, 2, 0, 0, 0, + 2, 2, 2, 4, 2, 0, 5, 0, + 5, 0, 6, 0, 2, 7, 2, 0, + 2, 0, 2, 0, 0, 2, 0, 8, + 0, 11, 2, 2, 5, 0, 12, 12, + 0, 2, 5, 2, 5, 2, 0, 13, + 2, 0, 0, 2, 0, 2, 2, 0, 2, 2, 0, 0, 2, 2, 2, 0, - 0, 0, 2, 15, 5, 0, 5, 2, - 2, 0, 5, 0, 0, 2, 5, 5, - 0, 0, 0, 2, 16, 17, 2, 0, - 0, 0, 0, 2, 2, 2, 2, 2, - 0, 0, 2, 2, 2, 0, 0, 0, - 2, 0, 18, 18, 0, 0, 0, 0, - 19, 2, 0, 0, 0 + 0, 0, 2, 14, 2, 0, 0, 2, + 0, 2, 2, 0, 2, 2, 2, 2, + 0, 2, 2, 0, 0, 2, 2, 2, + 0, 0, 0, 2, 15, 5, 0, 5, + 2, 2, 0, 5, 0, 0, 2, 5, + 5, 0, 0, 0, 2, 16, 17, 2, + 0, 0, 0, 0, 2, 2, 2, 2, + 2, 0, 0, 2, 2, 2, 0, 0, + 0, 2, 0, 18, 18, 0, 0, 0, + 0, 19, 2, 0, 0, 0 }; static const char _indic_syllable_machine_to_state_actions[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 9, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -349,14 +384,16 @@ static const char _indic_syllable_machine_to_state_actions[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0 + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0 }; static const char _indic_syllable_machine_from_state_actions[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 10, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 10, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -369,41 +406,42 @@ static const char _indic_syllable_machine_from_state_actions[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0 + 0, 0 }; static const short _indic_syllable_machine_eof_trans[] = { - 1, 1, 1, 1, 1, 1, 8, 8, - 8, 8, 8, 8, 8, 16, 16, 22, - 16, 16, 16, 24, 24, 24, 24, 24, - 24, 1, 31, 0, 47, 47, 47, 47, - 47, 47, 47, 47, 47, 47, 47, 47, - 47, 47, 47, 47, 47, 47, 47, 47, - 67, 67, 67, 67, 67, 67, 67, 67, - 67, 67, 67, 67, 67, 67, 67, 67, - 67, 67, 67, 67, 67, 67, 67, 67, - 67, 92, 92, 92, 92, 92, 92, 92, - 92, 92, 92, 92, 92, 92, 92, 92, - 92, 92, 92, 92, 92, 109, 109, 110, - 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 92, 47, 47, 47, 47, - 47, 47, 47, 137, 137, 137, 137, 137, - 109 + 1, 1, 1, 1, 1, 1, 1, 10, + 10, 10, 10, 10, 10, 10, 10, 20, + 20, 27, 20, 27, 20, 20, 30, 30, + 30, 30, 30, 30, 30, 1, 40, 0, + 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 101, + 101, 101, 101, 101, 101, 101, 101, 101, + 101, 101, 101, 101, 101, 101, 101, 101, + 101, 101, 101, 101, 118, 118, 119, 119, + 119, 119, 119, 119, 119, 119, 119, 119, + 119, 119, 119, 119, 119, 119, 119, 119, + 119, 119, 119, 101, 56, 56, 56, 56, + 56, 56, 56, 56, 146, 146, 146, 146, + 146, 118 }; -static const int indic_syllable_machine_start = 27; -static const int indic_syllable_machine_first_final = 27; +static const int indic_syllable_machine_start = 31; +static const int indic_syllable_machine_first_final = 31; static const int indic_syllable_machine_error = -1; -static const int indic_syllable_machine_en_main = 27; +static const int indic_syllable_machine_en_main = 31; #line 58 "hb-ot-shaper-indic-machine.rl" -#line 117 "hb-ot-shaper-indic-machine.rl" +#line 118 "hb-ot-shaper-indic-machine.rl" #define found_syllable(syllable_type) \ @@ -412,7 +450,7 @@ static const int indic_syllable_machine_en_main = 27; for (unsigned int i = ts; i < te; i++) \ info[i].syllable() = (syllable_serial << 4) | syllable_type; \ syllable_serial++; \ - if (unlikely (syllable_serial == 16)) syllable_serial = 1; \ + if (syllable_serial == 16) syllable_serial = 1; \ } HB_STMT_END inline void @@ -422,7 +460,7 @@ find_syllables_indic (hb_buffer_t *buffer) int cs; hb_glyph_info_t *info = buffer->info; -#line 426 "hb-ot-shaper-indic-machine.hh" +#line 453 "hb-ot-shaper-indic-machine.hh" { cs = indic_syllable_machine_start; ts = 0; @@ -430,7 +468,7 @@ find_syllables_indic (hb_buffer_t *buffer) act = 0; } -#line 137 "hb-ot-shaper-indic-machine.rl" +#line 138 "hb-ot-shaper-indic-machine.rl" p = 0; @@ -438,7 +476,7 @@ find_syllables_indic (hb_buffer_t *buffer) unsigned int syllable_serial = 1; -#line 442 "hb-ot-shaper-indic-machine.hh" +#line 465 "hb-ot-shaper-indic-machine.hh" { int _slen; int _trans; @@ -452,7 +490,7 @@ _resume: #line 1 "NONE" {ts = p;} break; -#line 456 "hb-ot-shaper-indic-machine.hh" +#line 477 "hb-ot-shaper-indic-machine.hh" } _keys = _indic_syllable_machine_trans_keys + (cs<<1); @@ -475,51 +513,51 @@ _eof_trans: {te = p+1;} break; case 11: -#line 113 "hb-ot-shaper-indic-machine.rl" +#line 114 "hb-ot-shaper-indic-machine.rl" {te = p+1;{ found_syllable (indic_non_indic_cluster); }} break; case 13: -#line 108 "hb-ot-shaper-indic-machine.rl" +#line 109 "hb-ot-shaper-indic-machine.rl" {te = p;p--;{ found_syllable (indic_consonant_syllable); }} break; case 14: -#line 109 "hb-ot-shaper-indic-machine.rl" +#line 110 "hb-ot-shaper-indic-machine.rl" {te = p;p--;{ found_syllable (indic_vowel_syllable); }} break; case 17: -#line 110 "hb-ot-shaper-indic-machine.rl" +#line 111 "hb-ot-shaper-indic-machine.rl" {te = p;p--;{ found_syllable (indic_standalone_cluster); }} break; case 19: -#line 111 "hb-ot-shaper-indic-machine.rl" +#line 112 "hb-ot-shaper-indic-machine.rl" {te = p;p--;{ found_syllable (indic_symbol_cluster); }} break; case 15: -#line 112 "hb-ot-shaper-indic-machine.rl" +#line 113 "hb-ot-shaper-indic-machine.rl" {te = p;p--;{ found_syllable (indic_broken_cluster); buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE; }} break; case 16: -#line 113 "hb-ot-shaper-indic-machine.rl" +#line 114 "hb-ot-shaper-indic-machine.rl" {te = p;p--;{ found_syllable (indic_non_indic_cluster); }} break; case 1: -#line 108 "hb-ot-shaper-indic-machine.rl" +#line 109 "hb-ot-shaper-indic-machine.rl" {{p = ((te))-1;}{ found_syllable (indic_consonant_syllable); }} break; case 3: -#line 109 "hb-ot-shaper-indic-machine.rl" +#line 110 "hb-ot-shaper-indic-machine.rl" {{p = ((te))-1;}{ found_syllable (indic_vowel_syllable); }} break; case 7: -#line 110 "hb-ot-shaper-indic-machine.rl" +#line 111 "hb-ot-shaper-indic-machine.rl" {{p = ((te))-1;}{ found_syllable (indic_standalone_cluster); }} break; case 8: -#line 111 "hb-ot-shaper-indic-machine.rl" +#line 112 "hb-ot-shaper-indic-machine.rl" {{p = ((te))-1;}{ found_syllable (indic_symbol_cluster); }} break; case 4: -#line 112 "hb-ot-shaper-indic-machine.rl" +#line 113 "hb-ot-shaper-indic-machine.rl" {{p = ((te))-1;}{ found_syllable (indic_broken_cluster); buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE; }} break; case 6: @@ -540,19 +578,19 @@ _eof_trans: case 18: #line 1 "NONE" {te = p+1;} -#line 108 "hb-ot-shaper-indic-machine.rl" +#line 109 "hb-ot-shaper-indic-machine.rl" {act = 1;} break; case 5: #line 1 "NONE" {te = p+1;} -#line 112 "hb-ot-shaper-indic-machine.rl" +#line 113 "hb-ot-shaper-indic-machine.rl" {act = 5;} break; case 12: #line 1 "NONE" {te = p+1;} -#line 113 "hb-ot-shaper-indic-machine.rl" +#line 114 "hb-ot-shaper-indic-machine.rl" {act = 6;} break; #line 559 "hb-ot-shaper-indic-machine.hh" @@ -564,7 +602,7 @@ _again: #line 1 "NONE" {ts = 0;} break; -#line 568 "hb-ot-shaper-indic-machine.hh" +#line 566 "hb-ot-shaper-indic-machine.hh" } if ( ++p != pe ) @@ -580,7 +618,7 @@ _again: } -#line 145 "hb-ot-shaper-indic-machine.rl" +#line 146 "hb-ot-shaper-indic-machine.rl" } diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-indic-table.cc b/thirdparty/harfbuzz/src/hb-ot-shaper-indic-table.cc index bf6a2757bb..d9fb0510e4 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shaper-indic-table.cc +++ b/thirdparty/harfbuzz/src/hb-ot-shaper-indic-table.cc @@ -42,6 +42,7 @@ #define OT_PLACEHOLDER I_Cat(PLACEHOLDER) #define OT_DOTTEDCIRCLE I_Cat(DOTTEDCIRCLE) #define OT_RS I_Cat(RS) +#define OT_MPst I_Cat(MPst) #define OT_Repha I_Cat(Repha) #define OT_Ra I_Cat(Ra) #define OT_CM I_Cat(CM) @@ -80,9 +81,10 @@ static_assert (OT_VPst == M_Cat(VPst), ""); #define _OT_CS OT_CS /* 2 chars; CS */ #define _OT_DC OT_DOTTEDCIRCLE /* 1 chars; DOTTEDCIRCLE */ #define _OT_H OT_H /* 11 chars; H */ -#define _OT_M OT_M /* 143 chars; M */ +#define _OT_M OT_M /* 142 chars; M */ #define _OT_MH OT_MH /* 1 chars; MH */ #define _OT_ML OT_ML /* 1 chars; ML */ +#define _OT_MP OT_MPst /* 1 chars; MPst */ #define _OT_MR OT_MR /* 1 chars; MR */ #define _OT_MW OT_MW /* 2 chars; MW */ #define _OT_MY OT_MY /* 3 chars; MY */ @@ -200,7 +202,7 @@ static const uint16_t indic_table[] = { /* 0A28 */ _(C,C), _(X,X), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), /* 0A30 */ _(R,C), _(X,X), _(C,C), _(C,C), _(X,X), _(C,C), _(C,C), _(X,X), /* 0A38 */ _(C,C), _(C,C), _(X,X), _(X,X), _(N,X), _(X,X), _(M,AP), _(M,LM), - /* 0A40 */ _(M,AP), _(M,AP), _(M,AP), _(X,X), _(X,X), _(X,X), _(X,X), _(M,AP), + /* 0A40 */_(MP,AP), _(M,AP), _(M,AP), _(X,X), _(X,X), _(X,X), _(X,X), _(M,AP), /* 0A48 */ _(M,AP), _(X,X), _(X,X), _(M,AP), _(M,AP), _(H,B), _(X,X), _(X,X), /* 0A50 */ _(X,X), _(M,B), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), /* 0A58 */ _(X,X), _(C,C), _(C,C), _(C,C), _(C,C), _(X,X), _(C,C), _(X,X), @@ -451,15 +453,12 @@ static const uint16_t indic_table[] = { /* Grantha */ /* 11300 */ _(X,X),_(SM,SM),_(SM,SM),_(SM,SM), _(X,X), _(X,X), _(X,X), _(X,X), - /* 11308 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), - /* 11310 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), - /* 11318 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), - /* 11320 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), - /* 11328 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), - /* 11330 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), + +#define indic_offset_0x11338u 1720 + /* 11338 */ _(X,X), _(X,X), _(X,X), _(N,X), _(N,X), _(X,X), _(X,X), _(X,X), -}; /* Table items: 1776; occupancy: 69% */ +}; /* Table items: 1728; occupancy: 71% */ uint16_t hb_indic_get_categories (hb_codepoint_t u) @@ -497,7 +496,8 @@ hb_indic_get_categories (hb_codepoint_t u) break; case 0x11u: - if (hb_in_range<hb_codepoint_t> (u, 0x11300u, 0x1133Fu)) return indic_table[u - 0x11300u + indic_offset_0x11300u]; + if (hb_in_range<hb_codepoint_t> (u, 0x11300u, 0x11307u)) return indic_table[u - 0x11300u + indic_offset_0x11300u]; + if (hb_in_range<hb_codepoint_t> (u, 0x11338u, 0x1133Fu)) return indic_table[u - 0x11338u + indic_offset_0x11338u]; break; default: @@ -519,6 +519,7 @@ hb_indic_get_categories (hb_codepoint_t u) #undef _OT_M #undef _OT_MH #undef _OT_ML +#undef _OT_MP #undef _OT_MR #undef _OT_MW #undef _OT_MY diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-indic.cc b/thirdparty/harfbuzz/src/hb-ot-shaper-indic.cc index 55509c1101..7652210d9d 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shaper-indic.cc +++ b/thirdparty/harfbuzz/src/hb-ot-shaper-indic.cc @@ -223,15 +223,15 @@ enum { INDIC_BASIC_FEATURES = INDIC_INIT, /* Don't forget to update this! */ }; -static void +static bool setup_syllables_indic (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer); -static void +static bool initial_reordering_indic (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer); -static void +static bool final_reordering_indic (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer); @@ -413,7 +413,7 @@ setup_masks_indic (const hb_ot_shape_plan_t *plan HB_UNUSED, set_indic_properties (info[i]); } -static void +static bool setup_syllables_indic (const hb_ot_shape_plan_t *plan HB_UNUSED, hb_font_t *font HB_UNUSED, hb_buffer_t *buffer) @@ -422,6 +422,7 @@ setup_syllables_indic (const hb_ot_shape_plan_t *plan HB_UNUSED, find_syllables_indic (buffer); foreach_syllable (buffer, start, end) buffer->unsafe_to_break (start, end); + return false; } static int @@ -714,6 +715,9 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan, } } } else if (info[i].indic_position() != POS_SMVD) { + if (info[i].indic_category() == I_Cat(MPst) && + i > start && info[i - 1].indic_category() == I_Cat(SM)) + info[i - 1].indic_position() = info[i].indic_position(); last_pos = (indic_position_t) info[i].indic_position(); } } @@ -729,7 +733,7 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan, if (info[j].indic_position() < POS_SMVD) info[j].indic_position() = info[i].indic_position(); last = i; - } else if (info[i].indic_category() == I_Cat(M)) + } else if (FLAG_UNSAFE (info[i].indic_category()) & (FLAG (I_Cat(M)) | FLAG (I_Cat(MPst)))) last = i; } @@ -742,14 +746,40 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan, /* Sit tight, rock 'n roll! */ hb_stable_sort (info + start, end - start, compare_indic_order); - /* Find base again */ + + /* Find base again; also flip left-matra sequence. */ + unsigned first_left_matra = end; + unsigned last_left_matra = end; base = end; for (unsigned int i = start; i < end; i++) + { if (info[i].indic_position() == POS_BASE_C) { base = i; break; } + else if (info[i].indic_position() == POS_PRE_M) + { + if (first_left_matra == end) + first_left_matra = i; + last_left_matra = i; + } + } + /* https://github.com/harfbuzz/harfbuzz/issues/3863 */ + if (first_left_matra < last_left_matra) + { + /* No need to merge clusters, handled later. */ + buffer->reverse_range (first_left_matra, last_left_matra + 1); + /* Reverse back nuktas, etc. */ + unsigned i = first_left_matra; + for (unsigned j = i; j <= last_left_matra; j++) + if (FLAG_UNSAFE (info[j].indic_category()) & (FLAG (I_Cat(M)) | FLAG (I_Cat(MPst)))) + { + buffer->reverse_range (i, j + 1); + i = j + 1; + } + } + /* Things are out-of-control for post base positions, they may shuffle * around like crazy. In old-spec mode, we move halants around, so in * that case merge all clusters after base. Otherwise, check the sort @@ -955,25 +985,29 @@ initial_reordering_syllable_indic (const hb_ot_shape_plan_t *plan, } } -static void +static bool initial_reordering_indic (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) { + bool ret = false; if (!buffer->message (font, "start reordering indic initial")) - return; + return ret; update_consonant_positions_indic (plan, font, buffer); - hb_syllabic_insert_dotted_circles (font, buffer, - indic_broken_cluster, - I_Cat(DOTTEDCIRCLE), - I_Cat(Repha), - POS_END); + if (hb_syllabic_insert_dotted_circles (font, buffer, + indic_broken_cluster, + I_Cat(DOTTEDCIRCLE), + I_Cat(Repha), + POS_END)) + ret = true; foreach_syllable (buffer, start, end) initial_reordering_syllable_indic (plan, font->face, buffer, start, end); (void) buffer->message (font, "end reordering indic initial"); + + return ret; } static void @@ -1116,7 +1150,7 @@ final_reordering_syllable_indic (const hb_ot_shape_plan_t *plan, { search: while (new_pos > start && - !(is_one_of (info[new_pos], (FLAG (I_Cat(M)) | FLAG (I_Cat(H)))))) + !(is_one_of (info[new_pos], (FLAG (I_Cat(M)) | FLAG (I_Cat(MPst)) | FLAG (I_Cat(H)))))) new_pos--; /* If we found no Halant we are done. @@ -1316,7 +1350,8 @@ final_reordering_syllable_indic (const hb_ot_shape_plan_t *plan, unlikely (is_halant (info[new_reph_pos]))) { for (unsigned int i = base + 1; i < new_reph_pos; i++) - if (info[i].indic_category() == I_Cat(M)) { + if (FLAG_UNSAFE (info[i].indic_category()) & (FLAG (I_Cat(M)) | FLAG (I_Cat(MPst)))) + { /* Ok, got it. */ new_reph_pos--; } @@ -1376,7 +1411,7 @@ final_reordering_syllable_indic (const hb_ot_shape_plan_t *plan, if (buffer->props.script != HB_SCRIPT_MALAYALAM && buffer->props.script != HB_SCRIPT_TAMIL) { while (new_pos > start && - !(is_one_of (info[new_pos - 1], FLAG(I_Cat(M)) | FLAG (I_Cat(H))))) + !(is_one_of (info[new_pos - 1], FLAG (I_Cat(M)) | FLAG (I_Cat(MPst)) | FLAG (I_Cat(H))))) new_pos--; } @@ -1439,13 +1474,13 @@ final_reordering_syllable_indic (const hb_ot_shape_plan_t *plan, } -static void +static bool final_reordering_indic (const hb_ot_shape_plan_t *plan, hb_font_t *font HB_UNUSED, hb_buffer_t *buffer) { unsigned int count = buffer->len; - if (unlikely (!count)) return; + if (unlikely (!count)) return false; if (buffer->message (font, "start reordering indic final")) { foreach_syllable (buffer, start, end) @@ -1455,6 +1490,8 @@ final_reordering_indic (const hb_ot_shape_plan_t *plan, HB_BUFFER_DEALLOCATE_VAR (buffer, indic_category); HB_BUFFER_DEALLOCATE_VAR (buffer, indic_position); + + return false; } diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-khmer-machine.hh b/thirdparty/harfbuzz/src/hb-ot-shaper-khmer-machine.hh index e18bd75ef1..fd91ee0caf 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shaper-khmer-machine.hh +++ b/thirdparty/harfbuzz/src/hb-ot-shaper-khmer-machine.hh @@ -48,7 +48,7 @@ enum khmer_syllable_type_t { }; -#line 52 "hb-ot-shaper-khmer-machine.hh" +#line 49 "hb-ot-shaper-khmer-machine.hh" #define khmer_syllable_machine_ex_C 1u #define khmer_syllable_machine_ex_DOTTEDCIRCLE 11u #define khmer_syllable_machine_ex_H 4u @@ -66,7 +66,7 @@ enum khmer_syllable_type_t { #define khmer_syllable_machine_ex_ZWNJ 5u -#line 70 "hb-ot-shaper-khmer-machine.hh" +#line 65 "hb-ot-shaper-khmer-machine.hh" static const unsigned char _khmer_syllable_machine_trans_keys[] = { 5u, 26u, 5u, 26u, 1u, 15u, 5u, 26u, 5u, 26u, 5u, 26u, 5u, 26u, 5u, 26u, 5u, 26u, 5u, 26u, 5u, 26u, 5u, 26u, 5u, 26u, 1u, 15u, 5u, 26u, 5u, 26u, @@ -284,7 +284,7 @@ static const int khmer_syllable_machine_en_main = 21; for (unsigned int i = ts; i < te; i++) \ info[i].syllable() = (syllable_serial << 4) | syllable_type; \ syllable_serial++; \ - if (unlikely (syllable_serial == 16)) syllable_serial = 1; \ + if (syllable_serial == 16) syllable_serial = 1; \ } HB_STMT_END inline void @@ -294,7 +294,7 @@ find_syllables_khmer (hb_buffer_t *buffer) int cs; hb_glyph_info_t *info = buffer->info; -#line 298 "hb-ot-shaper-khmer-machine.hh" +#line 287 "hb-ot-shaper-khmer-machine.hh" { cs = khmer_syllable_machine_start; ts = 0; @@ -310,7 +310,7 @@ find_syllables_khmer (hb_buffer_t *buffer) unsigned int syllable_serial = 1; -#line 314 "hb-ot-shaper-khmer-machine.hh" +#line 299 "hb-ot-shaper-khmer-machine.hh" { int _slen; int _trans; @@ -324,7 +324,7 @@ _resume: #line 1 "NONE" {ts = p;} break; -#line 328 "hb-ot-shaper-khmer-machine.hh" +#line 311 "hb-ot-shaper-khmer-machine.hh" } _keys = _khmer_syllable_machine_trans_keys + (cs<<1); @@ -394,7 +394,7 @@ _eof_trans: #line 98 "hb-ot-shaper-khmer-machine.rl" {act = 3;} break; -#line 398 "hb-ot-shaper-khmer-machine.hh" +#line 368 "hb-ot-shaper-khmer-machine.hh" } _again: @@ -403,7 +403,7 @@ _again: #line 1 "NONE" {ts = 0;} break; -#line 407 "hb-ot-shaper-khmer-machine.hh" +#line 375 "hb-ot-shaper-khmer-machine.hh" } if ( ++p != pe ) diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-khmer.cc b/thirdparty/harfbuzz/src/hb-ot-shaper-khmer.cc index d9795589fa..019a285102 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shaper-khmer.cc +++ b/thirdparty/harfbuzz/src/hb-ot-shaper-khmer.cc @@ -89,11 +89,11 @@ set_khmer_properties (hb_glyph_info_t &info) info.khmer_category() = (khmer_category_t) (type & 0xFFu); } -static void +static bool setup_syllables_khmer (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer); -static void +static bool reorder_khmer (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer); @@ -192,7 +192,7 @@ setup_masks_khmer (const hb_ot_shape_plan_t *plan HB_UNUSED, set_khmer_properties (info[i]); } -static void +static bool setup_syllables_khmer (const hb_ot_shape_plan_t *plan HB_UNUSED, hb_font_t *font HB_UNUSED, hb_buffer_t *buffer) @@ -201,6 +201,7 @@ setup_syllables_khmer (const hb_ot_shape_plan_t *plan HB_UNUSED, find_syllables_khmer (buffer); foreach_syllable (buffer, start, end) buffer->unsafe_to_break (start, end); + return false; } @@ -303,23 +304,27 @@ reorder_syllable_khmer (const hb_ot_shape_plan_t *plan, } } -static void +static bool reorder_khmer (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) { + bool ret = false; if (buffer->message (font, "start reordering khmer")) { - hb_syllabic_insert_dotted_circles (font, buffer, - khmer_broken_cluster, - K_Cat(DOTTEDCIRCLE), - (unsigned) -1); + if (hb_syllabic_insert_dotted_circles (font, buffer, + khmer_broken_cluster, + K_Cat(DOTTEDCIRCLE), + (unsigned) -1)) + ret = true; foreach_syllable (buffer, start, end) reorder_syllable_khmer (plan, font->face, buffer, start, end); (void) buffer->message (font, "end reordering khmer"); } HB_BUFFER_DEALLOCATE_VAR (buffer, khmer_category); + + return ret; } diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-myanmar-machine.hh b/thirdparty/harfbuzz/src/hb-ot-shaper-myanmar-machine.hh index b109708937..87cded4ed8 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shaper-myanmar-machine.hh +++ b/thirdparty/harfbuzz/src/hb-ot-shaper-myanmar-machine.hh @@ -50,7 +50,7 @@ enum myanmar_syllable_type_t { }; -#line 54 "hb-ot-shaper-myanmar-machine.hh" +#line 51 "hb-ot-shaper-myanmar-machine.hh" #define myanmar_syllable_machine_ex_A 9u #define myanmar_syllable_machine_ex_As 32u #define myanmar_syllable_machine_ex_C 1u @@ -77,7 +77,7 @@ enum myanmar_syllable_type_t { #define myanmar_syllable_machine_ex_ZWNJ 5u -#line 81 "hb-ot-shaper-myanmar-machine.hh" +#line 76 "hb-ot-shaper-myanmar-machine.hh" static const unsigned char _myanmar_syllable_machine_trans_keys[] = { 1u, 41u, 3u, 41u, 5u, 39u, 5u, 8u, 3u, 41u, 3u, 39u, 3u, 39u, 5u, 39u, 5u, 39u, 3u, 39u, 3u, 39u, 3u, 41u, 5u, 39u, 1u, 15u, 3u, 39u, 3u, 39u, @@ -433,7 +433,7 @@ static const int myanmar_syllable_machine_en_main = 0; for (unsigned int i = ts; i < te; i++) \ info[i].syllable() = (syllable_serial << 4) | syllable_type; \ syllable_serial++; \ - if (unlikely (syllable_serial == 16)) syllable_serial = 1; \ + if (syllable_serial == 16) syllable_serial = 1; \ } HB_STMT_END inline void @@ -443,7 +443,7 @@ find_syllables_myanmar (hb_buffer_t *buffer) int cs; hb_glyph_info_t *info = buffer->info; -#line 447 "hb-ot-shaper-myanmar-machine.hh" +#line 436 "hb-ot-shaper-myanmar-machine.hh" { cs = myanmar_syllable_machine_start; ts = 0; @@ -459,7 +459,7 @@ find_syllables_myanmar (hb_buffer_t *buffer) unsigned int syllable_serial = 1; -#line 463 "hb-ot-shaper-myanmar-machine.hh" +#line 448 "hb-ot-shaper-myanmar-machine.hh" { int _slen; int _trans; @@ -473,7 +473,7 @@ _resume: #line 1 "NONE" {ts = p;} break; -#line 477 "hb-ot-shaper-myanmar-machine.hh" +#line 460 "hb-ot-shaper-myanmar-machine.hh" } _keys = _myanmar_syllable_machine_trans_keys + (cs<<1); @@ -519,7 +519,7 @@ _eof_trans: #line 113 "hb-ot-shaper-myanmar-machine.rl" {te = p;p--;{ found_syllable (myanmar_non_myanmar_cluster); }} break; -#line 523 "hb-ot-shaper-myanmar-machine.hh" +#line 498 "hb-ot-shaper-myanmar-machine.hh" } _again: @@ -528,7 +528,7 @@ _again: #line 1 "NONE" {ts = 0;} break; -#line 532 "hb-ot-shaper-myanmar-machine.hh" +#line 505 "hb-ot-shaper-myanmar-machine.hh" } if ( ++p != pe ) diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-myanmar.cc b/thirdparty/harfbuzz/src/hb-ot-shaper-myanmar.cc index 78bd8de524..1b2a085a8d 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shaper-myanmar.cc +++ b/thirdparty/harfbuzz/src/hb-ot-shaper-myanmar.cc @@ -98,11 +98,11 @@ is_consonant_myanmar (const hb_glyph_info_t &info) } -static void +static bool setup_syllables_myanmar (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer); -static void +static bool reorder_myanmar (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer); @@ -150,7 +150,7 @@ setup_masks_myanmar (const hb_ot_shape_plan_t *plan HB_UNUSED, set_myanmar_properties (info[i]); } -static void +static bool setup_syllables_myanmar (const hb_ot_shape_plan_t *plan HB_UNUSED, hb_font_t *font HB_UNUSED, hb_buffer_t *buffer) @@ -159,6 +159,7 @@ setup_syllables_myanmar (const hb_ot_shape_plan_t *plan HB_UNUSED, find_syllables_myanmar (buffer); foreach_syllable (buffer, start, end) buffer->unsafe_to_break (start, end); + return false; } static int @@ -270,6 +271,33 @@ initial_reordering_consonant_syllable (hb_buffer_t *buffer, /* Sit tight, rock 'n roll! */ buffer->sort (start, end, compare_myanmar_order); + + /* Flip left-matra sequence. */ + unsigned first_left_matra = end; + unsigned last_left_matra = end; + for (unsigned int i = start; i < end; i++) + { + if (info[i].myanmar_position() == POS_PRE_M) + { + if (first_left_matra == end) + first_left_matra = i; + last_left_matra = i; + } + } + /* https://github.com/harfbuzz/harfbuzz/issues/3863 */ + if (first_left_matra < last_left_matra) + { + /* No need to merge clusters, done already? */ + buffer->reverse_range (first_left_matra, last_left_matra + 1); + /* Reverse back VS, etc. */ + unsigned i = first_left_matra; + for (unsigned j = i; j <= last_left_matra; j++) + if (info[j].myanmar_category() == M_Cat(VPre)) + { + buffer->reverse_range (i, j + 1); + i = j + 1; + } + } } static void @@ -291,16 +319,18 @@ reorder_syllable_myanmar (const hb_ot_shape_plan_t *plan HB_UNUSED, } } -static void +static bool reorder_myanmar (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) { + bool ret = false; if (buffer->message (font, "start reordering myanmar")) { - hb_syllabic_insert_dotted_circles (font, buffer, - myanmar_broken_cluster, - M_Cat(DOTTEDCIRCLE)); + if (hb_syllabic_insert_dotted_circles (font, buffer, + myanmar_broken_cluster, + M_Cat(DOTTEDCIRCLE))) + ret = true; foreach_syllable (buffer, start, end) reorder_syllable_myanmar (plan, font->face, buffer, start, end); @@ -309,6 +339,8 @@ reorder_myanmar (const hb_ot_shape_plan_t *plan, HB_BUFFER_DEALLOCATE_VAR (buffer, myanmar_category); HB_BUFFER_DEALLOCATE_VAR (buffer, myanmar_position); + + return ret; } @@ -331,6 +363,7 @@ const hb_ot_shaper_t _hb_ot_shaper_myanmar = }; +#ifndef HB_NO_OT_SHAPER_MYANMAR_ZAWGYI /* Ugly Zawgyi encoding. * Disable all auto processing. * https://github.com/harfbuzz/harfbuzz/issues/1162 */ @@ -351,6 +384,7 @@ const hb_ot_shaper_t _hb_ot_shaper_myanmar_zawgyi = HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE, false, /* fallback_position */ }; +#endif #endif diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-syllabic.cc b/thirdparty/harfbuzz/src/hb-ot-shaper-syllabic.cc index a8e0d8e8c1..89226ae4a1 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shaper-syllabic.cc +++ b/thirdparty/harfbuzz/src/hb-ot-shaper-syllabic.cc @@ -29,7 +29,7 @@ #include "hb-ot-shaper-syllabic.hh" -void +bool hb_syllabic_insert_dotted_circles (hb_font_t *font, hb_buffer_t *buffer, unsigned int broken_syllable_type, @@ -38,13 +38,13 @@ hb_syllabic_insert_dotted_circles (hb_font_t *font, int dottedcircle_position) { if (unlikely (buffer->flags & HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE)) - return; + return false; if (likely (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE))) - return; + return false; hb_codepoint_t dottedcircle_glyph; if (!font->get_nominal_glyph (0x25CCu, &dottedcircle_glyph)) - return; + return false; hb_glyph_info_t dottedcircle = {0}; dottedcircle.codepoint = 0x25CCu; @@ -84,14 +84,16 @@ hb_syllabic_insert_dotted_circles (hb_font_t *font, (void) buffer->next_glyph (); } buffer->sync (); + return true; } -HB_INTERNAL void +HB_INTERNAL bool hb_syllabic_clear_var (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) { HB_BUFFER_DEALLOCATE_VAR (buffer, syllable); + return false; } diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-syllabic.hh b/thirdparty/harfbuzz/src/hb-ot-shaper-syllabic.hh index e8a15bb48a..f240ad1c26 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shaper-syllabic.hh +++ b/thirdparty/harfbuzz/src/hb-ot-shaper-syllabic.hh @@ -30,7 +30,7 @@ #include "hb-ot-shaper.hh" -HB_INTERNAL void +HB_INTERNAL bool hb_syllabic_insert_dotted_circles (hb_font_t *font, hb_buffer_t *buffer, unsigned int broken_syllable_type, @@ -38,7 +38,7 @@ hb_syllabic_insert_dotted_circles (hb_font_t *font, int repha_category = -1, int dottedcircle_position = -1); -HB_INTERNAL void +HB_INTERNAL bool hb_syllabic_clear_var (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer); diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-thai.cc b/thirdparty/harfbuzz/src/hb-ot-shaper-thai.cc index 15349b1e64..6cd67cde35 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shaper-thai.cc +++ b/thirdparty/harfbuzz/src/hb-ot-shaper-thai.cc @@ -98,9 +98,9 @@ static hb_codepoint_t thai_pua_shape (hb_codepoint_t u, thai_action_t action, hb_font_t *font) { struct thai_pua_mapping_t { - hb_codepoint_t u; - hb_codepoint_t win_pua; - hb_codepoint_t mac_pua; + uint16_t u; + uint16_t win_pua; + uint16_t mac_pua; } const *pua_mappings = nullptr; static const thai_pua_mapping_t SD_mappings[] = { {0x0E48u, 0xF70Au, 0xF88Bu}, /* MAI EK */ diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-use-machine.hh b/thirdparty/harfbuzz/src/hb-ot-shaper-use-machine.hh index 41e8a34f3b..f2fbdb725b 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shaper-use-machine.hh +++ b/thirdparty/harfbuzz/src/hb-ot-shaper-use-machine.hh @@ -53,7 +53,7 @@ enum use_syllable_type_t { }; -#line 57 "hb-ot-shaper-use-machine.hh" +#line 54 "hb-ot-shaper-use-machine.hh" #define use_syllable_machine_ex_B 1u #define use_syllable_machine_ex_CGJ 6u #define use_syllable_machine_ex_CMAbv 31u @@ -97,7 +97,7 @@ enum use_syllable_type_t { #define use_syllable_machine_ex_ZWNJ 14u -#line 101 "hb-ot-shaper-use-machine.hh" +#line 96 "hb-ot-shaper-use-machine.hh" static const unsigned char _use_syllable_machine_trans_keys[] = { 0u, 53u, 11u, 53u, 11u, 53u, 1u, 53u, 14u, 48u, 14u, 47u, 14u, 47u, 14u, 47u, 14u, 46u, 14u, 46u, 14u, 14u, 14u, 48u, 14u, 48u, 14u, 48u, 1u, 14u, 14u, 48u, @@ -839,7 +839,7 @@ static const int use_syllable_machine_en_main = 0; for (unsigned i = (*ts).second.first; i < (*te).second.first; ++i) \ info[i].syllable() = (syllable_serial << 4) | syllable_type; \ syllable_serial++; \ - if (unlikely (syllable_serial == 16)) syllable_serial = 1; \ + if (syllable_serial == 16) syllable_serial = 1; \ } HB_STMT_END @@ -929,7 +929,7 @@ find_syllables_use (hb_buffer_t *buffer) unsigned int act HB_UNUSED; int cs; -#line 933 "hb-ot-shaper-use-machine.hh" +#line 922 "hb-ot-shaper-use-machine.hh" { cs = use_syllable_machine_start; ts = 0; @@ -942,7 +942,7 @@ find_syllables_use (hb_buffer_t *buffer) unsigned int syllable_serial = 1; -#line 946 "hb-ot-shaper-use-machine.hh" +#line 931 "hb-ot-shaper-use-machine.hh" { int _slen; int _trans; @@ -956,7 +956,7 @@ _resume: #line 1 "NONE" {ts = p;} break; -#line 960 "hb-ot-shaper-use-machine.hh" +#line 943 "hb-ot-shaper-use-machine.hh" } _keys = _use_syllable_machine_trans_keys + (cs<<1); @@ -1046,7 +1046,7 @@ _eof_trans: #line 178 "hb-ot-shaper-use-machine.rl" {te = p;p--;{ found_syllable (use_non_cluster); }} break; -#line 1050 "hb-ot-shaper-use-machine.hh" +#line 1014 "hb-ot-shaper-use-machine.hh" } _again: @@ -1055,7 +1055,7 @@ _again: #line 1 "NONE" {ts = 0;} break; -#line 1059 "hb-ot-shaper-use-machine.hh" +#line 1021 "hb-ot-shaper-use-machine.hh" } if ( ++p != pe ) diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-use-table.hh b/thirdparty/harfbuzz/src/hb-ot-shaper-use-table.hh index 6395d689ae..6b6b552ee5 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shaper-use-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-shaper-use-table.hh @@ -25,6 +25,7 @@ * # Updated for Unicode 12.1 by Andrew Glass 2019-05-24 * # Updated for Unicode 13.0 by Andrew Glass 2020-07-28 * # Updated for Unicode 14.0 by Andrew Glass 2021-09-25 + * # Updated for Unicode 15.0 by Andrew Glass 2022-09-16 * # Override values For Indic_Positional_Category * # Not derivable * # Initial version based on Unicode 7.0 by Andrew Glass 2014-03-17 @@ -34,6 +35,7 @@ * # Updated for Unicode 12.1 by Andrew Glass 2019-05-30 * # Updated for Unicode 13.0 by Andrew Glass 2020-07-28 * # Updated for Unicode 14.0 by Andrew Glass 2021-09-28 + * # Updated for Unicode 15.0 by Andrew Glass 2022-09-16 * UnicodeData.txt does not have a header. */ @@ -89,8 +91,11 @@ #define VMPre USE(VMPre) #pragma GCC diagnostic pop + +#ifndef HB_OPTIMIZE_SIZE + static const uint8_t -hb_use_u8[3115] = +hb_use_u8[3141] = { 16, 50, 51, 51, 51, 52, 51, 83, 118, 131, 51, 57, 58, 179, 195, 61, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, @@ -125,11 +130,11 @@ hb_use_u8[3115] = 2, 2, 2, 2, 2, 2, 2, 2, 2, 88, 89, 2, 2, 2, 2, 2, 2, 2, 2, 90, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 91, 2, 2, 92, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 93, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 94, 94, 95, 96, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, - 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, - 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 2, 2, 2, 91, 2, 2, 92, 2, 2, 2, 93, 2, 2, 2, 2, 2, + 2, 2, 2, 94, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 95, 95, 96, 97, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, + 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, + 95, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 2, 2, 2, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 4, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7, 0, 0, 0, 0, 0, 0, @@ -226,70 +231,72 @@ hb_use_u8[3115] = 0, 9, 47, 2, 2, 2, 2, 2, 2, 2, 2, 2, 125, 18, 20, 151, 20, 19, 152, 153, 2, 2, 2, 2, 2, 0, 0, 63, 154, 0, 0, 0, 0, 2, 11, 0, 0, 0, 0, 0, 0, 2, 63, 23, 18, 18, 18, 20, - 20, 106, 155, 0, 0, 156, 157, 29, 158, 28, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 21, 17, 20, 20, 159, 42, 0, 0, 0, + 20, 106, 155, 0, 0, 54, 156, 29, 157, 28, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 21, 17, 20, 20, 158, 42, 0, 0, 0, 47, 125, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 7, 7, 2, 2, 28, 2, 2, 2, 2, 2, 2, 2, 28, 2, 2, 2, 2, 2, 2, 2, - 8, 16, 17, 19, 20, 160, 29, 0, 0, 9, 9, 28, 2, 2, 2, 7, + 8, 16, 17, 19, 20, 159, 29, 0, 0, 9, 9, 28, 2, 2, 2, 7, 28, 7, 2, 28, 2, 2, 56, 15, 21, 14, 21, 45, 30, 31, 30, 32, 0, 0, 0, 0, 33, 0, 0, 0, 2, 2, 21, 0, 9, 9, 9, 44, 0, 9, 9, 44, 0, 0, 0, 0, 0, 2, 2, 63, 23, 18, 18, 18, 20, 21, 123, 13, 15, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 0, - 161, 162, 0, 0, 0, 0, 0, 0, 0, 16, 17, 18, 18, 64, 97, 23, - 158, 9, 163, 7, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, - 63, 23, 18, 18, 0, 46, 46, 9, 164, 35, 0, 0, 0, 0, 0, 0, + 160, 161, 0, 0, 0, 0, 0, 0, 0, 16, 17, 18, 18, 64, 97, 23, + 157, 9, 162, 7, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, + 63, 23, 18, 18, 0, 46, 46, 9, 163, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 18, 0, 21, 17, 18, 18, 19, 14, 80, - 164, 36, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 8, 165, - 23, 18, 20, 20, 163, 7, 0, 0, 0, 2, 2, 2, 2, 2, 7, 41, + 163, 36, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 8, 164, + 23, 18, 20, 20, 162, 7, 0, 0, 0, 2, 2, 2, 2, 2, 7, 41, 133, 21, 20, 18, 74, 19, 20, 0, 0, 2, 2, 2, 7, 0, 0, 0, - 0, 2, 2, 2, 2, 2, 2, 16, 17, 18, 19, 20, 103, 164, 35, 0, + 0, 2, 2, 2, 2, 2, 2, 16, 17, 18, 19, 20, 103, 163, 35, 0, 0, 2, 2, 2, 7, 28, 0, 2, 2, 2, 2, 28, 7, 2, 2, 2, - 2, 21, 21, 16, 30, 31, 10, 166, 167, 168, 169, 0, 0, 0, 0, 0, + 2, 21, 21, 16, 30, 31, 10, 165, 166, 167, 168, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 2, 2, 2, 63, 23, 18, 18, 0, 20, 21, 27, 106, 0, 31, 0, 0, 0, 0, 0, 50, 18, 20, 20, 20, 137, 2, - 2, 2, 170, 171, 9, 13, 172, 70, 173, 0, 0, 1, 144, 0, 0, 0, - 0, 50, 18, 20, 14, 17, 18, 2, 2, 2, 2, 155, 155, 155, 174, 174, - 174, 174, 174, 174, 13, 175, 0, 28, 0, 20, 18, 18, 29, 20, 20, 9, - 164, 0, 59, 59, 59, 59, 59, 59, 59, 64, 19, 80, 44, 0, 0, 0, + 2, 2, 169, 170, 9, 13, 171, 70, 172, 0, 0, 1, 144, 0, 0, 0, + 0, 50, 18, 20, 14, 17, 18, 2, 2, 2, 2, 155, 155, 155, 173, 173, + 173, 173, 173, 173, 13, 174, 0, 28, 0, 20, 18, 18, 29, 20, 20, 9, + 163, 0, 59, 59, 59, 59, 59, 59, 59, 64, 19, 80, 44, 0, 0, 0, 0, 2, 2, 2, 7, 2, 28, 2, 2, 50, 20, 20, 29, 0, 36, 20, - 25, 9, 157, 176, 172, 0, 0, 0, 0, 2, 2, 2, 28, 7, 2, 2, + 25, 9, 156, 175, 171, 0, 0, 0, 0, 2, 2, 2, 28, 7, 2, 2, 2, 2, 2, 2, 2, 2, 21, 21, 45, 20, 33, 80, 66, 0, 0, 0, - 0, 2, 177, 64, 45, 0, 0, 0, 0, 9, 178, 2, 2, 2, 2, 2, + 0, 2, 176, 64, 45, 0, 0, 0, 0, 9, 177, 2, 2, 2, 2, 2, 2, 2, 2, 21, 20, 18, 29, 0, 46, 14, 140, 0, 0, 0, 0, 0, - 0, 179, 179, 179, 106, 7, 0, 0, 0, 9, 9, 9, 44, 0, 0, 0, - 0, 2, 2, 2, 2, 2, 7, 0, 56, 180, 18, 18, 18, 18, 18, 18, + 0, 178, 178, 178, 106, 179, 178, 0, 0, 145, 2, 2, 180, 114, 114, 114, + 114, 114, 114, 114, 0, 0, 0, 0, 0, 9, 9, 9, 44, 0, 0, 0, + 0, 2, 2, 2, 2, 2, 7, 0, 56, 181, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 38, 114, 24, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 2, 2, 2, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 56, 35, 0, 4, 118, 118, 118, 119, 0, 0, 9, 9, 9, 47, 2, 2, 2, 0, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, - 44, 2, 2, 2, 2, 2, 2, 9, 9, 2, 2, 42, 42, 42, 90, 0, - 0, O, O, O, GB, B, B, GB, O, O, WJ,FMPst,FMPst, O, CGJ, B, - O, B,VMAbv,VMAbv,VMAbv, O,VMAbv, B,CMBlw,CMBlw,CMBlw,VMAbv,VMPst, VAbv, VPst,CMBlw, - B, VPst, VPre, VPst, VBlw, VBlw, VBlw, VBlw, VAbv, VAbv, VAbv, VPst, VPst, VPst, H, VPre, - VPst,VMBlw, O, O, VAbv, GB,VMAbv,VMPst,VMPst, O, B, VBlw, O, O, VPre, VPre, - O, VPre, H, O, VPst,FMAbv, O,CMBlw, O, VAbv, O, VAbv, H, O,VMBlw,VMAbv, - CMAbv, GB, GB, O, MBlw,CMAbv,CMAbv, VPst, VAbv,VMAbv, O, VPst, O, VPre, VPre,VMAbv, - B, O, CS, CS,VMPst, B, VAbv, VAbv, B, R, O, HVM, O, O, FBlw, O, - CMAbv, O,CMBlw, VAbv, VBlw, B, SUB, SUB, SUB, O, SUB, SUB, O, FBlw, O, B, - VPst, VBlw, VPre,VMAbv,VMBlw,VMPst, IS, VAbv, MPst, MPre, MBlw, MBlw, B, MBlw, MBlw, VPst, - VMPst,VMPst, B, MBlw, VPst, VPre, VAbv, VAbv,VMPst,VMPst,VMBlw, B,VMPst, VBlw, VPst, CGJ, - CGJ, VPst,VMAbv,VMAbv,FMAbv, FAbv,CMAbv,FMAbv,VMAbv,FMAbv, VAbv, IS,FMAbv, B,FMAbv, B, - CGJ, WJ, CGJ, GB,CMAbv,CMAbv, B, GB, B, VAbv, SUB, FPst, FPst,VMBlw, FPst, FPst, - FBlw,VMAbv,FMBlw, VAbv, VPre, B, MPre, MBlw, SUB, FAbv, FAbv, MAbv, SUB, Sk, VPst, VAbv, - VMAbv,VMAbv, FAbv,CMAbv, VPst, H, B, O,SMAbv,SMBlw,SMAbv,SMAbv,SMAbv, VPst, IS, VBlw, - FAbv,VMPre,VMPre,FMAbv,CMBlw,VMBlw,VMBlw,VMAbv, CS, O,FMAbv, ZWNJ, CGJ, WJ, WJ, WJ, - O,FMPst, O, O, H, MPst, VPst, H,VMAbv, VAbv,VMBlw, B, VBlw, FPst, VPst, FAbv, - VMPst, B,CMAbv, VAbv, MBlw, MPst, MBlw, H, O, VBlw, MPst, MPre, MAbv, MBlw, O, B, - FAbv, FAbv, FPst, VBlw, B, B, VPre, O,VMPst, IS, O,VMPst, VBlw, VPst,VMBlw,VMBlw, - VMAbv, O, IS,VMBlw, B,VMPst,VMAbv,VMPst, CS, CS, B, N, N, O, HN, VPre, - VBlw, VAbv, IS,CMAbv, O, VPst, B, R, R, O,FMBlw,CMBlw, VAbv, VPre,VMAbv,VMAbv, - H, VAbv,CMBlw,FMAbv, B, CS, CS, H,CMBlw,VMPst, H,VMPst, VAbv,VMAbv, VPst, IS, - R, MPst, R, MPst,CMBlw, B,FMBlw, VBlw,VMAbv, R, MBlw, MBlw, GB, FBlw, FBlw,CMAbv, - IS, VBlw, IS, GB, VAbv, R,VMPst, H, H, O, VBlw, + 44, 2, 2, 2, 2, 2, 2, 9, 9, 2, 2, 2, 2, 2, 2, 20, + 20, 2, 2, 42, 42, 42, 90, 0, 0, O, O, O, GB, B, B, GB, + O, O, WJ,FMPst,FMPst, O, CGJ, B, O, B,VMAbv,VMAbv,VMAbv, O,VMAbv, B, + CMBlw,CMBlw,CMBlw,VMAbv,VMPst, VAbv, VPst,CMBlw, B, VPst, VPre, VPst, VBlw, VBlw, VBlw, VBlw, + VAbv, VAbv, VAbv, VPst, VPst, VPst, H, VPre, VPst,VMBlw, O, O, VAbv, GB,VMAbv,VMPst, + VMPst, O, B, VBlw, O, O, VPre, VPre, O, VPre, H, O, VPst,FMAbv, O,CMBlw, + O, VAbv, O, VAbv, H, O,VMBlw,VMAbv,CMAbv, GB, GB, O, MBlw,CMAbv,CMAbv, VPst, + VAbv,VMAbv, O, VPst, O, VPre, VPre,VMAbv, B, O, CS, CS,VMPst, B, VAbv, VAbv, + B, R, O, HVM, O, O,FMBlw, O,CMAbv, O,CMBlw, VAbv, VBlw, B, SUB, SUB, + SUB, O, SUB, SUB, O,FMBlw, O, B, VPst, VBlw, VPre,VMAbv,VMBlw,VMPst, IS, VAbv, + MPst, MPre, MBlw, MBlw, B, MBlw, MBlw, VPst,VMPst,VMPst, B, MBlw, VPst, VPre, VAbv, VAbv, + VMPst,VMPst,VMBlw, B,VMPst, VBlw, VPst, CGJ, CGJ, VPst,VMAbv,VMAbv,FMAbv, FAbv,CMAbv,FMAbv, + VMAbv,FMAbv, VAbv, IS,FMAbv, B,FMAbv, B, CGJ, WJ, CGJ, GB,CMAbv,CMAbv, B, GB, + B, VAbv, SUB, FPst, FPst,VMBlw, FPst, FPst, FBlw,VMAbv,FMBlw, VAbv, VPre, B, MPre, MBlw, + SUB, FAbv, FAbv, MAbv, SUB, Sk, VPst, VAbv,VMAbv,VMAbv, FAbv,CMAbv, VPst, H, B, O, + SMAbv,SMBlw,SMAbv,SMAbv,SMAbv, VPst, IS, VBlw, FAbv,VMPre,VMPre,FMAbv,CMBlw,VMBlw,VMBlw,VMAbv, + CS, O,FMAbv, ZWNJ, CGJ, WJ, WJ, WJ, O,FMPst, O, O, H, MPst, VPst, H, + VMAbv, VAbv,VMBlw, B, VBlw, FPst, VPst, FAbv,VMPst, B,CMAbv, VAbv, MBlw, MPst, MBlw, H, + O, VBlw, MPst, MPre, MAbv, MBlw, O, B, FAbv, FAbv, FPst, VBlw, B, B, VPre, O, + VMPst, IS, O,VMPst, VBlw, VPst,VMBlw,VMBlw,VMAbv, O, IS,VMBlw, B,VMPst,VMAbv,VMPst, + CS, CS, B, N, N, O, HN, VPre, VBlw, VAbv, IS,CMAbv, O, VPst, B, R, + R,CMBlw, VAbv, VPre,VMAbv,VMAbv, H, VAbv,CMBlw,FMAbv, B, CS, CS, H,CMBlw,VMPst, + H,VMPst, VAbv,VMAbv, VPst, IS, R, MPst, R, MPst,CMBlw, B,FMBlw, VBlw,VMAbv, R, + MBlw, MBlw, GB, FBlw, FBlw,CMAbv, IS, VBlw, IS, GB, VAbv, R,VMPst, H, H, B, + H, B,VMBlw, O, VBlw, }; static const uint16_t -hb_use_u16[776] = +hb_use_u16[784] = { 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 3, 4, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, @@ -332,14 +339,279 @@ hb_use_u16[776] = 9,242, 73,243, 0, 0, 0, 0,244, 9, 9,245,246, 2,247, 9, 248,249, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9,250, 251, 48, 9,252,253, 2, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 98,254, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, - 9, 9, 9,255, 0, 0, 0, 0, 9, 9, 9, 9,256,257,258,258, - 259,260, 0, 0, 0, 0,261, 0, 9, 9, 9, 9, 9,262, 0, 0, - 9, 9, 9, 9, 9, 9,105, 70, 94,263, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0,264, 9, 9, 70,265,266, 0, 0, 0, - 0, 9,267, 0, 9, 9,268, 2, 9, 9, 9, 9,269, 2, 0, 0, - 129,129,129,129,129,129,129,129,160,160,160,160,160,160,160,160, - 160,160,160,160,160,160,160,129, + 9, 9, 9,254,255,256, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, + 9, 9, 9,257, 0, 0, 0, 0, 9, 9, 9, 9,258,259,260,260, + 261,262, 0, 0, 0, 0,263, 0, 9, 9, 9, 9, 9,264, 0, 0, + 9, 9, 9, 9, 9, 9,105, 70, 94,265, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0,266, 9, 9, 70,267,268, 0, 0, 0, + 0, 9,269, 0, 9, 9,270, 2, 0, 0, 0, 0, 0, 9,271, 2, + 9, 9, 9, 9,272, 2, 0, 0,129,129,129,129,129,129,129,129, + 160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,129, +}; + +static inline unsigned +hb_use_b4 (const uint8_t* a, unsigned i) +{ + return (a[i>>1]>>((i&1u)<<2))&15u; +} +static inline uint_fast8_t +hb_use_get_category (unsigned u) +{ + return u<921600u?hb_use_u8[2777+(((hb_use_u8[593+(((hb_use_u16[((hb_use_u8[113+(((hb_use_b4(hb_use_u8,u>>1>>3>>3>>5))<<5)+((u>>1>>3>>3)&31u))])<<3)+((u>>1>>3)&7u)])<<3)+((u>>1)&7u))])<<1)+((u)&1u))]:O; +} + + +#else + +static const uint8_t +hb_use_u8[3413] = +{ + 16, 50, 51, 51, 51, 52, 51, 83, 118, 131, 51, 57, 58, 179, 195, 61, + 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, + 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, + 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, + 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, + 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, + 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, + 14, 0, 1, 1, 2, 1, 1, 3, 4, 5, 6, 7, 8, 9, 10, 1, + 11, 12, 1, 1, 1, 1, 1, 1, 13, 14, 15, 16, 17, 18, 19, 1, + 1, 20, 1, 1, 1, 1, 21, 1, 1, 1, 1, 1, 1, 1, 22, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 24, 25, 26, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, + 28, 1, 1, 1, 1, 1, 29, 1, 1, 1, 1, 30, 31, 1, 32, 33, + 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 1, 46, 47, 48, + 49, 50, 50, 50, 50, 51, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 52, 53, 1, 1, 1, + 54, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 50, 55, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 56, 1, 1, + 1, 1, 57, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 58, 59, 1, 60, 1, 1, 1, 1, 61, 1, 1, 1, 1, 1, + 1, 62, 63, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, + 62, 0, 1, 0, 0, 0, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 6, 7, 0, 0, 8, 0, 0, 0, 0, + 0, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 36, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, + 0, 55, 56, 57, 58, 59, 0, 0, 0, 60, 61, 62, 63, 55, 64, 65, + 66, 67, 55, 55, 68, 69, 70, 0, 0, 71, 72, 73, 74, 55, 75, 76, + 0, 77, 55, 78, 79, 80, 0, 0, 0, 81, 82, 83, 84, 85, 86, 55, + 87, 55, 88, 89, 0, 0, 0, 90, 91, 0, 0, 0, 0, 0, 0, 0, + 92, 93, 94, 0, 95, 96, 0, 0, 97, 0, 0, 0, 0, 0, 0, 98, + 0, 0, 99, 55, 100, 0, 0, 0, 0, 101, 102, 55, 103, 104, 105, 106, + 107, 55, 108, 109, 0, 110, 111, 112, 113, 55, 114, 115, 116, 55, 117, 118, + 119, 0, 0, 0, 0, 0, 0, 55, 120, 121, 0, 0, 0, 0, 0, 0, + 122, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 124, 125, 126, 0, + 0, 127, 128, 129, 0, 0, 0, 50, 130, 0, 0, 0, 0, 131, 132, 0, + 0, 55, 133, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 134, 0, + 0, 0, 99, 135, 99, 136, 137, 138, 0, 139, 140, 141, 142, 143, 144, 145, + 0, 146, 147, 148, 149, 143, 150, 151, 152, 153, 154, 155, 0, 156, 157, 158, + 159, 160, 161, 162, 163, 0, 0, 0, 0, 55, 164, 165, 166, 167, 168, 169, + 0, 0, 0, 0, 0, 55, 170, 171, 0, 55, 172, 173, 0, 55, 174, 66, + 0, 175, 176, 177, 0, 0, 0, 0, 0, 55, 178, 0, 0, 0, 0, 0, + 0, 179, 180, 181, 0, 0, 182, 183, 184, 185, 186, 187, 55, 188, 0, 0, + 0, 189, 190, 191, 192, 193, 194, 0, 0, 195, 196, 197, 198, 199, 66, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 200, 201, 202, 203, 0, 0, 0, 0, + 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 204, 205, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 66, 0, 55, 206, 0, 0, 0, 0, 0, + 0, 55, 55, 207, 208, 209, 0, 0, 210, 55, 55, 55, 55, 55, 55, 211, + 0, 55, 55, 55, 212, 213, 0, 0, 0, 0, 0, 0, 214, 0, 0, 0, + 0, 55, 215, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 217, 55, + 218, 0, 0, 0, 0, 0, 0, 99, 219, 55, 55, 220, 0, 0, 0, 0, + 0, 221, 221, 221, 221, 221, 221, 221, 221, 222, 222, 222, 222, 222, 222, 222, + 223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 0, 2, 2, 2, 2, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 4, + 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 6, 7, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 8, 9, 9, 9, 9, 0, 0, 0, 7, 10, + 0, 2, 2, 2, 2, 11, 12, 0, 0, 9, 13, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 14, 15, 16, 17, 18, 19, 20, 14, 21, 22, + 23, 10, 24, 25, 18, 2, 2, 2, 2, 2, 18, 0, 2, 2, 2, 2, + 2, 0, 2, 2, 2, 2, 2, 2, 2, 26, 27, 28, 2, 2, 2, 7, + 28, 7, 28, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 7, 2, 2, + 2, 7, 7, 0, 2, 2, 0, 15, 16, 17, 18, 29, 30, 31, 30, 32, + 0, 0, 0, 0, 33, 0, 0, 2, 28, 2, 0, 0, 0, 0, 0, 7, + 34, 10, 13, 28, 2, 2, 7, 0, 28, 7, 2, 28, 7, 2, 0, 35, + 16, 17, 29, 0, 25, 36, 25, 37, 0, 38, 0, 0, 0, 28, 2, 7, + 7, 0, 0, 0, 2, 2, 2, 2, 2, 39, 40, 41, 0, 0, 0, 0, + 0, 10, 13, 28, 2, 2, 2, 2, 28, 2, 28, 2, 2, 2, 2, 2, + 2, 7, 2, 28, 2, 2, 0, 15, 16, 17, 18, 19, 25, 20, 33, 22, + 0, 0, 0, 0, 0, 28, 39, 39, 42, 10, 27, 28, 2, 2, 2, 7, + 28, 7, 2, 28, 2, 2, 0, 15, 43, 0, 0, 25, 20, 0, 0, 2, + 28, 28, 0, 0, 0, 0, 0, 0, 0, 0, 44, 28, 2, 2, 7, 0, + 2, 7, 2, 2, 0, 28, 7, 7, 2, 0, 28, 7, 0, 2, 7, 0, + 2, 2, 2, 2, 2, 2, 0, 0, 21, 14, 45, 0, 46, 31, 46, 32, + 0, 0, 0, 0, 33, 0, 0, 0, 0, 13, 27, 47, 2, 2, 2, 7, + 2, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 15, + 20, 14, 21, 45, 20, 36, 20, 37, 0, 0, 0, 25, 29, 2, 7, 0, + 0, 8, 27, 28, 2, 2, 2, 7, 2, 2, 2, 28, 2, 2, 0, 15, + 43, 0, 0, 33, 45, 0, 0, 0, 7, 48, 49, 0, 0, 0, 0, 0, + 0, 9, 27, 2, 2, 2, 2, 7, 2, 2, 2, 2, 2, 2, 50, 51, + 21, 21, 17, 29, 46, 31, 46, 32, 52, 0, 0, 0, 33, 0, 0, 0, + 28, 10, 27, 28, 2, 2, 2, 2, 2, 2, 2, 2, 7, 0, 2, 2, + 2, 2, 28, 2, 2, 2, 2, 28, 0, 2, 2, 2, 7, 0, 53, 0, + 33, 21, 20, 29, 29, 16, 46, 46, 23, 0, 21, 0, 0, 0, 0, 0, + 0, 2, 0, 2, 7, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, + 0, 2, 2, 54, 54, 55, 0, 0, 16, 2, 2, 2, 2, 28, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 7, 0, 56, 19, 57, 20, 20, 18, 18, + 44, 19, 9, 29, 9, 2, 2, 58, 59, 59, 59, 59, 59, 60, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 61, + 0, 0, 0, 0, 62, 0, 0, 0, 0, 2, 2, 2, 2, 2, 63, 43, + 57, 64, 20, 20, 65, 66, 67, 68, 69, 2, 2, 2, 2, 2, 1, 0, + 3, 2, 2, 2, 21, 18, 2, 2, 70, 69, 71, 72, 63, 71, 27, 27, + 2, 50, 20, 51, 2, 2, 2, 2, 2, 2, 73, 74, 75, 27, 27, 76, + 77, 2, 2, 2, 2, 2, 27, 43, 0, 2, 57, 78, 0, 0, 0, 0, + 28, 2, 57, 45, 0, 0, 0, 0, 0, 2, 57, 0, 0, 0, 0, 0, + 0, 2, 2, 2, 2, 2, 2, 7, 2, 7, 57, 0, 0, 0, 0, 0, + 0, 2, 2, 79, 43, 20, 57, 18, 46, 46, 46, 46, 13, 80, 81, 82, + 83, 84, 85, 0, 0, 0, 0, 86, 0, 7, 0, 0, 28, 0, 87, 79, + 88, 2, 2, 2, 2, 7, 0, 0, 0, 40, 40, 89, 90, 2, 2, 2, + 2, 2, 2, 2, 2, 11, 7, 0, 0, 91, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 7, 20, 78, 43, 20, 92, 59, 0, + 0, 93, 94, 93, 93, 95, 96, 0, 0, 2, 2, 2, 2, 2, 2, 2, + 0, 2, 2, 7, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 0, + 0, 2, 2, 2, 2, 27, 0, 0, 0, 2, 2, 2, 2, 2, 7, 0, + 0, 2, 2, 2, 50, 97, 43, 0, 0, 2, 2, 98, 99, 100, 101, 59, + 61, 102, 14, 43, 20, 57, 19, 78, 46, 46, 74, 9, 9, 9, 103, 44, + 38, 9, 104, 72, 2, 2, 2, 2, 2, 2, 2, 105, 20, 18, 18, 20, + 46, 46, 20, 106, 2, 2, 2, 7, 0, 0, 0, 0, 0, 0, 107, 108, + 109, 109, 109, 0, 0, 0, 0, 0, 0, 104, 72, 2, 2, 2, 2, 2, + 2, 58, 59, 57, 23, 20, 110, 59, 2, 2, 2, 2, 105, 20, 21, 43, + 43, 100, 12, 0, 0, 0, 0, 0, 0, 2, 2, 59, 16, 46, 21, 111, + 100, 100, 100, 112, 113, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 28, + 2, 9, 44, 114, 114, 114, 9, 114, 114, 13, 114, 114, 114, 24, 0, 38, + 0, 0, 0, 115, 49, 9, 3, 0, 0, 0, 0, 0, 0, 0, 116, 0, + 0, 0, 0, 0, 0, 0, 4, 117, 118, 40, 40, 3, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 118, 118, 119, 118, 118, 118, 118, 118, 118, 118, + 118, 0, 0, 120, 0, 0, 0, 0, 0, 0, 5, 120, 0, 0, 0, 0, + 0, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, + 0, 2, 2, 2, 2, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 0, + 121, 2, 51, 2, 106, 2, 8, 2, 2, 2, 63, 17, 14, 0, 0, 29, + 0, 2, 2, 0, 0, 0, 0, 0, 0, 27, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 122, 21, 21, 21, 21, 21, 21, 21, 123, 0, 0, 0, 0, + 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 2, 0, 0, 0, 0, 0, + 50, 2, 2, 2, 20, 20, 124, 114, 0, 2, 2, 2, 125, 18, 57, 18, + 111, 100, 126, 0, 0, 0, 0, 0, 0, 9, 127, 2, 2, 2, 2, 2, + 2, 2, 128, 21, 20, 18, 46, 129, 130, 131, 0, 0, 0, 0, 0, 0, + 0, 2, 2, 50, 28, 2, 2, 2, 2, 2, 2, 2, 2, 8, 20, 57, + 97, 74, 132, 133, 134, 0, 0, 0, 0, 2, 135, 2, 2, 2, 2, 136, + 0, 28, 2, 40, 3, 0, 77, 13, 2, 51, 20, 137, 50, 51, 2, 2, + 103, 8, 7, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 138, 19, + 23, 0, 0, 139, 140, 0, 0, 0, 0, 2, 63, 43, 21, 78, 45, 141, + 0, 79, 79, 79, 79, 79, 79, 79, 79, 0, 0, 0, 0, 0, 0, 0, + 4, 118, 118, 118, 118, 119, 0, 0, 0, 2, 2, 2, 2, 2, 7, 2, + 2, 2, 7, 2, 28, 2, 2, 2, 2, 2, 28, 2, 2, 2, 28, 7, + 0, 125, 18, 25, 29, 0, 0, 142, 143, 2, 2, 28, 2, 28, 2, 2, + 2, 2, 2, 2, 0, 12, 35, 0, 144, 2, 2, 11, 35, 0, 28, 2, + 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 2, 2, + 7, 2, 2, 9, 39, 0, 0, 0, 0, 2, 2, 2, 2, 2, 25, 36, + 0, 2, 2, 2, 114, 114, 114, 114, 114, 145, 2, 7, 0, 0, 0, 0, + 0, 2, 12, 12, 0, 0, 0, 0, 0, 7, 2, 2, 7, 2, 2, 2, + 2, 28, 2, 7, 0, 28, 2, 0, 0, 146, 147, 148, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 20, 20, 18, 18, 18, 20, 20, 131, 0, 0, 0, + 0, 0, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 2, 2, 2, 2, + 2, 51, 50, 51, 0, 0, 0, 0, 150, 9, 72, 2, 2, 2, 2, 2, + 2, 16, 17, 19, 14, 22, 35, 0, 0, 0, 29, 0, 0, 0, 0, 0, + 0, 9, 47, 2, 2, 2, 2, 2, 2, 2, 2, 2, 125, 18, 20, 151, + 20, 19, 152, 153, 2, 2, 2, 2, 2, 0, 0, 63, 154, 0, 0, 0, + 0, 2, 11, 0, 0, 0, 0, 0, 0, 2, 63, 23, 18, 18, 18, 20, + 20, 106, 155, 0, 0, 54, 156, 29, 157, 28, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 21, 17, 20, 20, 158, 42, 0, 0, 0, + 47, 125, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 7, 7, 2, 2, + 28, 2, 2, 2, 2, 2, 2, 2, 28, 2, 2, 2, 2, 2, 2, 2, + 8, 16, 17, 19, 20, 159, 29, 0, 0, 9, 9, 28, 2, 2, 2, 7, + 28, 7, 2, 28, 2, 2, 56, 15, 21, 14, 21, 45, 30, 31, 30, 32, + 0, 0, 0, 0, 33, 0, 0, 0, 2, 2, 21, 0, 9, 9, 9, 44, + 0, 9, 9, 44, 0, 0, 0, 0, 0, 2, 2, 63, 23, 18, 18, 18, + 20, 21, 123, 13, 15, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 0, + 160, 161, 0, 0, 0, 0, 0, 0, 0, 16, 17, 18, 18, 64, 97, 23, + 157, 9, 162, 7, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, + 63, 23, 18, 18, 0, 46, 46, 9, 163, 35, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 2, 2, 18, 0, 21, 17, 18, 18, 19, 14, 80, + 163, 36, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 8, 164, + 23, 18, 20, 20, 162, 7, 0, 0, 0, 2, 2, 2, 2, 2, 7, 41, + 133, 21, 20, 18, 74, 19, 20, 0, 0, 2, 2, 2, 7, 0, 0, 0, + 0, 2, 2, 2, 2, 2, 2, 16, 17, 18, 19, 20, 103, 163, 35, 0, + 0, 2, 2, 2, 7, 28, 0, 2, 2, 2, 2, 28, 7, 2, 2, 2, + 2, 21, 21, 16, 30, 31, 10, 165, 166, 167, 168, 0, 0, 0, 0, 0, + 0, 2, 2, 2, 2, 0, 2, 2, 2, 63, 23, 18, 18, 0, 20, 21, + 27, 106, 0, 31, 0, 0, 0, 0, 0, 50, 18, 20, 20, 20, 137, 2, + 2, 2, 169, 170, 9, 13, 171, 70, 172, 0, 0, 1, 144, 0, 0, 0, + 0, 50, 18, 20, 14, 17, 18, 2, 2, 2, 2, 155, 155, 155, 173, 173, + 173, 173, 173, 173, 13, 174, 0, 28, 0, 20, 18, 18, 29, 20, 20, 9, + 163, 0, 59, 59, 59, 59, 59, 59, 59, 64, 19, 80, 44, 0, 0, 0, + 0, 2, 2, 2, 7, 2, 28, 2, 2, 50, 20, 20, 29, 0, 36, 20, + 25, 9, 156, 175, 171, 0, 0, 0, 0, 2, 2, 2, 28, 7, 2, 2, + 2, 2, 2, 2, 2, 2, 21, 21, 45, 20, 33, 80, 66, 0, 0, 0, + 0, 2, 176, 64, 45, 0, 0, 0, 0, 9, 177, 2, 2, 2, 2, 2, + 2, 2, 2, 21, 20, 18, 29, 0, 46, 14, 140, 0, 0, 0, 0, 0, + 0, 178, 178, 178, 106, 179, 178, 0, 0, 145, 2, 2, 180, 114, 114, 114, + 114, 114, 114, 114, 0, 0, 0, 0, 0, 9, 9, 9, 44, 0, 0, 0, + 0, 2, 2, 2, 2, 2, 7, 0, 56, 181, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, + 38, 114, 24, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, + 0, 2, 2, 2, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 56, + 35, 0, 4, 118, 118, 118, 119, 0, 0, 9, 9, 9, 47, 2, 2, 2, + 0, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, + 44, 2, 2, 2, 2, 2, 2, 9, 9, 2, 2, 2, 2, 2, 2, 20, + 20, 2, 2, 42, 42, 42, 90, 0, 0, O, O, O, GB, B, B, GB, + O, O, WJ,FMPst,FMPst, O, CGJ, B, O, B,VMAbv,VMAbv,VMAbv, O,VMAbv, B, + CMBlw,CMBlw,CMBlw,VMAbv,VMPst, VAbv, VPst,CMBlw, B, VPst, VPre, VPst, VBlw, VBlw, VBlw, VBlw, + VAbv, VAbv, VAbv, VPst, VPst, VPst, H, VPre, VPst,VMBlw, O, O, VAbv, GB,VMAbv,VMPst, + VMPst, O, B, VBlw, O, O, VPre, VPre, O, VPre, H, O, VPst,FMAbv, O,CMBlw, + O, VAbv, O, VAbv, H, O,VMBlw,VMAbv,CMAbv, GB, GB, O, MBlw,CMAbv,CMAbv, VPst, + VAbv,VMAbv, O, VPst, O, VPre, VPre,VMAbv, B, O, CS, CS,VMPst, B, VAbv, VAbv, + B, R, O, HVM, O, O,FMBlw, O,CMAbv, O,CMBlw, VAbv, VBlw, B, SUB, SUB, + SUB, O, SUB, SUB, O,FMBlw, O, B, VPst, VBlw, VPre,VMAbv,VMBlw,VMPst, IS, VAbv, + MPst, MPre, MBlw, MBlw, B, MBlw, MBlw, VPst,VMPst,VMPst, B, MBlw, VPst, VPre, VAbv, VAbv, + VMPst,VMPst,VMBlw, B,VMPst, VBlw, VPst, CGJ, CGJ, VPst,VMAbv,VMAbv,FMAbv, FAbv,CMAbv,FMAbv, + VMAbv,FMAbv, VAbv, IS,FMAbv, B,FMAbv, B, CGJ, WJ, CGJ, GB,CMAbv,CMAbv, B, GB, + B, VAbv, SUB, FPst, FPst,VMBlw, FPst, FPst, FBlw,VMAbv,FMBlw, VAbv, VPre, B, MPre, MBlw, + SUB, FAbv, FAbv, MAbv, SUB, Sk, VPst, VAbv,VMAbv,VMAbv, FAbv,CMAbv, VPst, H, B, O, + SMAbv,SMBlw,SMAbv,SMAbv,SMAbv, VPst, IS, VBlw, FAbv,VMPre,VMPre,FMAbv,CMBlw,VMBlw,VMBlw,VMAbv, + CS, O,FMAbv, ZWNJ, CGJ, WJ, WJ, WJ, O,FMPst, O, O, H, MPst, VPst, H, + VMAbv, VAbv,VMBlw, B, VBlw, FPst, VPst, FAbv,VMPst, B,CMAbv, VAbv, MBlw, MPst, MBlw, H, + O, VBlw, MPst, MPre, MAbv, MBlw, O, B, FAbv, FAbv, FPst, VBlw, B, B, VPre, O, + VMPst, IS, O,VMPst, VBlw, VPst,VMBlw,VMBlw,VMAbv, O, IS,VMBlw, B,VMPst,VMAbv,VMPst, + CS, CS, B, N, N, O, HN, VPre, VBlw, VAbv, IS,CMAbv, O, VPst, B, R, + R,CMBlw, VAbv, VPre,VMAbv,VMAbv, H, VAbv,CMBlw,FMAbv, B, CS, CS, H,CMBlw,VMPst, + H,VMPst, VAbv,VMAbv, VPst, IS, R, MPst, R, MPst,CMBlw, B,FMBlw, VBlw,VMAbv, R, + MBlw, MBlw, GB, FBlw, FBlw,CMAbv, IS, VBlw, IS, GB, VAbv, R,VMPst, H, H, B, + H, B,VMBlw, O, VBlw, +}; +static const uint16_t +hb_use_u16[448] = +{ + 0, 0, 1, 2, 3, 4, 0, 5, 6, 0, 7, 0, 8, 9, 10, 11, + 9, 12, 13, 9, 9, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 17, 25, 26, 20, 21, 27, 28, 29, 30, 31, 32, 33, 21, 34, 35, 0, + 17, 36, 37, 20, 21, 38, 23, 39, 17, 40, 41, 42, 43, 44, 45, 46, + 30, 0, 47, 48, 21, 49, 50, 51, 17, 0, 52, 48, 21, 53, 50, 54, + 17, 55, 56, 48, 9, 57, 58, 59, 60, 61, 9, 62, 63, 64, 30, 65, + 66, 67, 9, 68, 69, 9, 70, 71, 72, 73, 74, 75, 76, 0, 9, 9, + 77, 78, 79, 80, 81, 82, 83, 84, 9, 85, 9, 86, 9, 87, 88, 89, + 9, 90, 91, 92, 2, 0, 93, 0, 9, 94, 95, 9, 96, 0, 97, 98, + 99,100, 30, 9,101,102,103, 9,104,105, 9,106, 9,107,108,109, + 2, 2,110, 9, 9,111,112, 2,113,114,115, 9,116, 9,117,118, + 119,120,121, 0, 0,122,123,124, 0,125,126,127,128, 0,129,130, + 131, 0, 0,132,133, 0, 0, 9,134,135,136, 9,137, 0, 9,138, + 139, 9, 9,140,141, 2,142,143,144, 9,145,146,147, 9, 9,148, + 149, 2,150, 98,151,152,153, 2, 9,154, 9,155,156, 0,157,158, + 159, 2,160, 0, 0,161, 0,162, 0,163,163,164, 33,165,166,167, + 9,168, 94, 0,169, 0, 9,170,171, 0,172, 2,173,170,174,175, + 176, 0, 0,177,178, 0,179, 9, 9,180,181,182,183,184,185, 9, + 9,186,187, 0,188, 9,189,190,191, 9, 9,192, 9,193,194,105, + 195,102, 9, 33,196,197,198, 0,199,200, 94, 9, 9,201,202, 2, + 203, 20, 21,204,205,206,207,208, 9,209,210,211,212, 0,195, 9, + 9,213,214, 2,215,216,217,218, 9,219,220, 2,221,222, 9,223, + 224,103,225, 0,226,227,228,229, 9,230,231, 2,232, 9, 9,233, + 234, 0,235, 9, 9,236,237,238,239,240, 21, 9,215,241, 7, 9, + 70, 18, 9,242, 73,243,244, 9, 9,245,246, 2,247, 9,248,249, + 9,250,251, 48, 9,252,253, 2, 9,254,255,256, 9,257,258,259, + 260,260,261,262,263, 0, 9,264,105, 70, 94,265, 0,266, 70,267, + 268, 0,269, 0,270, 2,271, 2,272, 2,129,129,160,160,160,129, }; static inline unsigned @@ -350,9 +622,11 @@ hb_use_b4 (const uint8_t* a, unsigned i) static inline uint_fast8_t hb_use_get_category (unsigned u) { - return u<921600u?hb_use_u8[2753+(((hb_use_u8[593+(((hb_use_u16[((hb_use_u8[113+(((hb_use_b4(hb_use_u8,u>>1>>3>>3>>5))<<5)+((u>>1>>3>>3)&31u))])<<3)+((u>>1>>3)&7u)])<<3)+((u>>1)&7u))])<<1)+((u)&1u))]:O; + return u<921600u?hb_use_u8[3049+(((hb_use_u8[865+(((hb_use_u16[((hb_use_u8[353+(((hb_use_u8[113+(((hb_use_b4(hb_use_u8,u>>1>>3>>1>>3>>4))<<4)+((u>>1>>3>>1>>3)&15u))])<<3)+((u>>1>>3>>1)&7u))])<<1)+((u>>1>>3)&1u)])<<3)+((u>>1)&7u))])<<1)+((u)&1u))]:O; } +#endif + #undef B #undef CGJ #undef CS diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-use.cc b/thirdparty/harfbuzz/src/hb-ot-shaper-use.cc index c40ec52f9c..342aba1235 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shaper-use.cc +++ b/thirdparty/harfbuzz/src/hb-ot-shaper-use.cc @@ -89,19 +89,19 @@ use_other_features[] = HB_TAG('p','s','t','s'), }; -static void +static bool setup_syllables_use (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer); -static void +static bool record_rphf_use (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer); -static void +static bool record_pref_use (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer); -static void +static bool reorder_use (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer); @@ -293,7 +293,7 @@ setup_topographical_masks (const hb_ot_shape_plan_t *plan, } } -static void +static bool setup_syllables_use (const hb_ot_shape_plan_t *plan, hb_font_t *font HB_UNUSED, hb_buffer_t *buffer) @@ -304,9 +304,10 @@ setup_syllables_use (const hb_ot_shape_plan_t *plan, buffer->unsafe_to_break (start, end); setup_rphf_mask (plan, buffer); setup_topographical_masks (plan, buffer); + return false; } -static void +static bool record_rphf_use (const hb_ot_shape_plan_t *plan, hb_font_t *font HB_UNUSED, hb_buffer_t *buffer) @@ -314,7 +315,7 @@ record_rphf_use (const hb_ot_shape_plan_t *plan, const use_shape_plan_t *use_plan = (const use_shape_plan_t *) plan->data; hb_mask_t mask = use_plan->rphf_mask; - if (!mask) return; + if (!mask) return false; hb_glyph_info_t *info = buffer->info; foreach_syllable (buffer, start, end) @@ -327,9 +328,10 @@ record_rphf_use (const hb_ot_shape_plan_t *plan, break; } } + return false; } -static void +static bool record_pref_use (const hb_ot_shape_plan_t *plan HB_UNUSED, hb_font_t *font HB_UNUSED, hb_buffer_t *buffer) @@ -346,6 +348,7 @@ record_pref_use (const hb_ot_shape_plan_t *plan HB_UNUSED, break; } } + return false; } static inline bool @@ -438,17 +441,19 @@ reorder_syllable_use (hb_buffer_t *buffer, unsigned int start, unsigned int end) } } -static void +static bool reorder_use (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) { + bool ret = false; if (buffer->message (font, "start reordering USE")) { - hb_syllabic_insert_dotted_circles (font, buffer, - use_broken_cluster, - USE(B), - USE(R)); + if (hb_syllabic_insert_dotted_circles (font, buffer, + use_broken_cluster, + USE(B), + USE(R))) + ret = true; foreach_syllable (buffer, start, end) reorder_syllable_use (buffer, start, end); @@ -457,6 +462,8 @@ reorder_use (const hb_ot_shape_plan_t *plan, } HB_BUFFER_DEALLOCATE_VAR (buffer, use_category); + + return ret; } diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-vowel-constraints.cc b/thirdparty/harfbuzz/src/hb-ot-shaper-vowel-constraints.cc index cb4db4a8b2..e76b554b00 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shaper-vowel-constraints.cc +++ b/thirdparty/harfbuzz/src/hb-ot-shaper-vowel-constraints.cc @@ -342,6 +342,40 @@ _hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB_UNUSED, } break; + case HB_SCRIPT_KHOJKI: + for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) + { + bool matched = false; + switch (buffer->cur ().codepoint) + { + case 0x11200u: + switch (buffer->cur (1).codepoint) + { + case 0x1122Cu: case 0x11231u: case 0x11233u: + matched = true; + break; + } + break; + case 0x11206u: + matched = 0x1122Cu == buffer->cur (1).codepoint; + break; + case 0x1122Cu: + switch (buffer->cur (1).codepoint) + { + case 0x11230u: case 0x11231u: + matched = true; + break; + } + break; + case 0x11240u: + matched = 0x1122Eu == buffer->cur (1).codepoint; + break; + } + (void) buffer->next_glyph (); + if (matched) _output_with_dotted_circle (buffer); + } + break; + case HB_SCRIPT_KHUDAWADI: for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) { diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper.hh b/thirdparty/harfbuzz/src/hb-ot-shaper.hh index b2d1acb39b..0207b2bbe3 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shaper.hh +++ b/thirdparty/harfbuzz/src/hb-ot-shaper.hh @@ -262,11 +262,13 @@ hb_ot_shaper_categorize (const hb_ot_shape_planner_t *planner) return &_hb_ot_shaper_myanmar; +#ifndef HB_NO_OT_SHAPER_MYANMAR_ZAWGYI #define HB_SCRIPT_MYANMAR_ZAWGYI ((hb_script_t) HB_TAG ('Q','a','a','g')) case HB_SCRIPT_MYANMAR_ZAWGYI: /* https://github.com/harfbuzz/harfbuzz/issues/1162 */ return &_hb_ot_shaper_myanmar_zawgyi; +#endif /* Unicode-2.0 additions */ diff --git a/thirdparty/harfbuzz/src/hb-ot-stat-table.hh b/thirdparty/harfbuzz/src/hb-ot-stat-table.hh index d83bf14219..59bb2daccd 100644 --- a/thirdparty/harfbuzz/src/hb-ot-stat-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-stat-table.hh @@ -136,7 +136,7 @@ struct AxisValueFormat1 NameID valueNameID; /* The name ID for entries in the 'name' table * that provide a display string for this * attribute value. */ - HBFixed value; /* A numeric value for this attribute value. */ + F16DOT16 value; /* A numeric value for this attribute value. */ public: DEFINE_SIZE_STATIC (12); }; @@ -195,10 +195,10 @@ struct AxisValueFormat2 NameID valueNameID; /* The name ID for entries in the 'name' table * that provide a display string for this * attribute value. */ - HBFixed nominalValue; /* A numeric value for this attribute value. */ - HBFixed rangeMinValue; /* The minimum value for a range associated + F16DOT16 nominalValue; /* A numeric value for this attribute value. */ + F16DOT16 rangeMinValue; /* The minimum value for a range associated * with the specified name ID. */ - HBFixed rangeMaxValue; /* The maximum value for a range associated + F16DOT16 rangeMaxValue; /* The maximum value for a range associated * with the specified name ID. */ public: DEFINE_SIZE_STATIC (20); @@ -258,8 +258,8 @@ struct AxisValueFormat3 NameID valueNameID; /* The name ID for entries in the 'name' table * that provide a display string for this * attribute value. */ - HBFixed value; /* A numeric value for this attribute value. */ - HBFixed linkedValue; /* The numeric value for a style-linked mapping + F16DOT16 value; /* A numeric value for this attribute value. */ + F16DOT16 linkedValue; /* The numeric value for a style-linked mapping * from this value. */ public: DEFINE_SIZE_STATIC (16); @@ -280,7 +280,7 @@ struct AxisValueRecord HBUINT16 axisIndex; /* Zero-base index into the axis record array * identifying the axis to which this value * applies. Must be less than designAxisCount. */ - HBFixed value; /* A numeric value for this attribute value. */ + F16DOT16 value; /* A numeric value for this attribute value. */ public: DEFINE_SIZE_STATIC (6); }; @@ -320,7 +320,7 @@ struct AxisValueFormat4 unsigned total_size = min_size + axisCount * AxisValueRecord::static_size; auto *out = c->serializer->allocate_size<AxisValueFormat4> (total_size); if (unlikely (!out)) return_trace (false); - memcpy (out, this, total_size); + hb_memcpy (out, this, total_size); return_trace (true); } diff --git a/thirdparty/harfbuzz/src/hb-ot-tag.cc b/thirdparty/harfbuzz/src/hb-ot-tag.cc index 1b18270cca..f6ba3b0d47 100644 --- a/thirdparty/harfbuzz/src/hb-ot-tag.cc +++ b/thirdparty/harfbuzz/src/hb-ot-tag.cc @@ -577,7 +577,7 @@ hb_ot_tags_to_script_and_language (hb_tag_t script_tag, else { int shift; - memcpy (buf, lang_str, len); + hb_memcpy (buf, lang_str, len); if (lang_str[0] != 'x' || lang_str[1] != '-') { buf[len++] = '-'; buf[len++] = 'x'; diff --git a/thirdparty/harfbuzz/src/hb-ot-var-avar-table.hh b/thirdparty/harfbuzz/src/hb-ot-var-avar-table.hh index f60bc4a3ce..cc5c5c0068 100644 --- a/thirdparty/harfbuzz/src/hb-ot-var-avar-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-var-avar-table.hh @@ -143,7 +143,7 @@ struct avar TRACE_SANITIZE (this); if (!(version.sanitize (c) && (version.major == 1 -#ifndef HB_NO_VARIATIONS2 +#ifndef HB_NO_AVAR2 || version.major == 2 #endif ) && @@ -159,7 +159,7 @@ struct avar map = &StructAfter<SegmentMaps> (*map); } -#ifndef HB_NO_VARIATIONS2 +#ifndef HB_NO_AVAR2 if (version.major < 2) return_trace (true); @@ -182,7 +182,7 @@ struct avar map = &StructAfter<SegmentMaps> (*map); } -#ifndef HB_NO_VARIATIONS2 +#ifndef HB_NO_AVAR2 if (version.major < 2) return; diff --git a/thirdparty/harfbuzz/src/hb-ot-var-common.hh b/thirdparty/harfbuzz/src/hb-ot-var-common.hh index 1d29e3e4f9..4997c2e2e8 100644 --- a/thirdparty/harfbuzz/src/hb-ot-var-common.hh +++ b/thirdparty/harfbuzz/src/hb-ot-var-common.hh @@ -47,7 +47,7 @@ struct DeltaSetIndexMapFormat01 HBUINT8 *p = c->allocate_size<HBUINT8> (total_size); if (unlikely (!p)) return_trace (nullptr); - memcpy (p, this, HBUINT8::static_size * total_size); + hb_memcpy (p, this, HBUINT8::static_size * total_size); return_trace (out); } @@ -219,6 +219,25 @@ struct DeltaSetIndexMap DEFINE_SIZE_UNION (1, format); }; + +struct VarStoreInstancer +{ + VarStoreInstancer (const VariationStore &varStore, + const DeltaSetIndexMap &varIdxMap, + hb_array_t<int> coords) : + varStore (varStore), varIdxMap (varIdxMap), coords (coords) {} + + operator bool () const { return bool (coords); } + + float operator() (uint32_t varIdx, unsigned short offset = 0) const + { return varStore.get_delta (varIdxMap.map (VarIdx::add (varIdx, offset)), coords); } + + const VariationStore &varStore; + const DeltaSetIndexMap &varIdxMap; + hb_array_t<int> coords; +}; + + } /* namespace OT */ diff --git a/thirdparty/harfbuzz/src/hb-ot-var-fvar-table.hh b/thirdparty/harfbuzz/src/hb-ot-var-fvar-table.hh index b9b49f2287..c1d57a002a 100644 --- a/thirdparty/harfbuzz/src/hb-ot-var-fvar-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-var-fvar-table.hh @@ -44,9 +44,47 @@ struct InstanceRecord { friend struct fvar; - hb_array_t<const HBFixed> get_coordinates (unsigned int axis_count) const + hb_array_t<const F16DOT16> get_coordinates (unsigned int axis_count) const { return coordinatesZ.as_array (axis_count); } + bool subset (hb_subset_context_t *c, + unsigned axis_count, + bool has_postscript_nameid) const + { + TRACE_SUBSET (this); + if (unlikely (!c->serializer->embed (subfamilyNameID))) return_trace (false); + if (unlikely (!c->serializer->embed (flags))) return_trace (false); + + const hb_array_t<const F16DOT16> coords = get_coordinates (axis_count); + const hb_hashmap_t<hb_tag_t, float> *axes_location = c->plan->user_axes_location; + for (unsigned i = 0 ; i < axis_count; i++) + { + uint32_t *axis_tag; + // only keep instances whose coordinates == pinned axis location + if (!c->plan->axes_old_index_tag_map->has (i, &axis_tag)) continue; + + if (axes_location->has (*axis_tag) && + fabsf (axes_location->get (*axis_tag) - coords[i].to_float ()) > 0.001f) + return_trace (false); + + if (!c->plan->axes_index_map->has (i)) + continue; + + if (!c->serializer->embed (coords[i])) + return_trace (false); + } + + if (has_postscript_nameid) + { + NameID name_id; + name_id = StructAfter<NameID> (coords); + if (!c->serializer->embed (name_id)) + return_trace (false); + } + + return_trace (true); + } + bool sanitize (hb_sanitize_context_t *c, unsigned int axis_count) const { TRACE_SANITIZE (this); @@ -58,7 +96,7 @@ struct InstanceRecord NameID subfamilyNameID;/* The name ID for entries in the 'name' table * that provide subfamily names for this instance. */ HBUINT16 flags; /* Reserved for future use — set to 0. */ - UnsizedArrayOf<HBFixed> + UnsizedArrayOf<F16DOT16> coordinatesZ; /* The coordinates array for this instance. */ //NameID postScriptNameIDX;/*Optional. The name ID for entries in the 'name' // * table that provide PostScript names for this @@ -151,9 +189,9 @@ struct AxisRecord public: Tag axisTag; /* Tag identifying the design variation for the axis. */ protected: - HBFixed minValue; /* The minimum coordinate value for the axis. */ - HBFixed defaultValue; /* The default coordinate value for the axis. */ - HBFixed maxValue; /* The maximum coordinate value for the axis. */ + F16DOT16 minValue; /* The minimum coordinate value for the axis. */ + F16DOT16 defaultValue; /* The default coordinate value for the axis. */ + F16DOT16 maxValue; /* The maximum coordinate value for the axis. */ public: HBUINT16 flags; /* Axis flags. */ NameID axisNameID; /* The name ID for entries in the 'name' table that @@ -268,7 +306,7 @@ struct fvar if (coords_length && *coords_length) { - hb_array_t<const HBFixed> instanceCoords = instance->get_coordinates (axisCount) + hb_array_t<const F16DOT16> instanceCoords = instance->get_coordinates (axisCount) .sub_array (0, coords_length); for (unsigned int i = 0; i < instanceCoords.length; i++) coords[i] = instanceCoords.arrayZ[i].to_float (); @@ -299,13 +337,13 @@ struct fvar { const InstanceRecord *instance = get_instance (i); - if (hb_any (+ hb_zip (instance->get_coordinates (axisCount), hb_range ((unsigned)axisCount)) - | hb_filter (pinned_axes, hb_second) - | hb_map ([&] (const hb_pair_t<const HBFixed&, unsigned>& _) + if (hb_any (+ hb_enumerate (instance->get_coordinates (axisCount)) + | hb_filter (pinned_axes, hb_first) + | hb_map ([&] (const hb_pair_t<unsigned, const F16DOT16&>& _) { - hb_tag_t axis_tag = pinned_axes.get (_.second); + hb_tag_t axis_tag = pinned_axes.get (_.first); float location = user_axes_location->get (axis_tag); - if (fabs ((double)location - (double)_.first.to_float ()) > 0.001) return true; + if (fabs ((double)location - (double)_.second.to_float ()) > 0.001) return true; return false; }) )) @@ -321,6 +359,48 @@ struct fvar } } + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + unsigned retained_axis_count = c->plan->axes_index_map->get_population (); + if (!retained_axis_count) //all axes are pinned + return_trace (false); + + fvar *out = c->serializer->embed (this); + if (unlikely (!out)) return_trace (false); + + if (!c->serializer->check_assign (out->axisCount, retained_axis_count, HB_SERIALIZE_ERROR_INT_OVERFLOW)) + return_trace (false); + + bool has_postscript_nameid = false; + if (instanceSize >= axisCount * 4 + 6) + has_postscript_nameid = true; + + if (!c->serializer->check_assign (out->instanceSize, retained_axis_count * 4 + (has_postscript_nameid ? 6 : 4), + HB_SERIALIZE_ERROR_INT_OVERFLOW)) + return_trace (false); + + auto axes_records = get_axes (); + for (unsigned i = 0 ; i < (unsigned)axisCount; i++) + { + if (!c->plan->axes_index_map->has (i)) continue; + if (unlikely (!c->serializer->embed (axes_records[i]))) + return_trace (false); + } + + if (!c->serializer->check_assign (out->firstAxis, get_size (), HB_SERIALIZE_ERROR_INT_OVERFLOW)) + return_trace (false); + + for (unsigned i = 0 ; i < (unsigned)instanceCount; i++) + { + const InstanceRecord *instance = get_instance (i); + auto snap = c->serializer->snapshot (); + if (!instance->subset (c, axisCount, has_postscript_nameid)) + c->serializer->revert (snap); + } + return_trace (true); + } + public: hb_array_t<const AxisRecord> get_axes () const { return hb_array (&(this+firstAxis), axisCount); } @@ -346,8 +426,8 @@ struct fvar HBUINT16 instanceCount; /* The number of named instances defined in the font * (the number of records in the instances array). */ HBUINT16 instanceSize; /* The size in bytes of each InstanceRecord — set - * to either axisCount * sizeof(HBFixed) + 4, or to - * axisCount * sizeof(HBFixed) + 6. */ + * to either axisCount * sizeof(F16DOT16) + 4, or to + * axisCount * sizeof(F16DOT16) + 6. */ public: DEFINE_SIZE_STATIC (16); diff --git a/thirdparty/harfbuzz/src/hb-ot-var-gvar-table.hh b/thirdparty/harfbuzz/src/hb-ot-var-gvar-table.hh index bf1039d1d6..e02063ca43 100644 --- a/thirdparty/harfbuzz/src/hb-ot-var-gvar-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-var-gvar-table.hh @@ -56,12 +56,11 @@ struct contour_point_vector_t : hb_vector_t<contour_point_t> void extend (const hb_array_t<contour_point_t> &a) { unsigned int old_len = length; - if (unlikely (!resize (old_len + a.length))) + if (unlikely (!resize (old_len + a.length, false))) return; auto arrayZ = this->arrayZ + old_len; unsigned count = a.length; - for (unsigned int i = 0; i < count; i++) - arrayZ[i] = a.arrayZ[i]; + hb_memcpy (arrayZ, a.arrayZ, count * sizeof (arrayZ[0])); } void transform (const float (&matrix)[4]) @@ -231,8 +230,8 @@ struct GlyphVariationData { return (index < var_data->tupleVarCount.get_count ()) && var_data_bytes.check_range (current_tuple, TupleVariationHeader::min_size) && - var_data_bytes.check_range (current_tuple, hb_max (current_tuple->get_data_size (), current_tuple->get_size (axis_count))) && - current_tuple->get_size (axis_count); + var_data_bytes.check_range (current_tuple, hb_max (current_tuple->get_data_size (), + current_tuple->get_size (axis_count))); } bool move_to_next () @@ -281,42 +280,42 @@ struct GlyphVariationData if (unlikely (p + 1 > end)) return false; - uint16_t count = *p++; + unsigned count = *p++; if (count & POINTS_ARE_WORDS) { if (unlikely (p + 1 > end)) return false; count = ((count & POINT_RUN_COUNT_MASK) << 8) | *p++; } - if (unlikely (!points.resize (count))) return false; + if (unlikely (!points.resize (count, false))) return false; - unsigned int n = 0; - uint16_t i = 0; + unsigned n = 0; + unsigned i = 0; while (i < count) { if (unlikely (p + 1 > end)) return false; - uint16_t j; - uint8_t control = *p++; - uint16_t run_count = (control & POINT_RUN_COUNT_MASK) + 1; + unsigned control = *p++; + unsigned run_count = (control & POINT_RUN_COUNT_MASK) + 1; + if (unlikely (i + run_count > count)) return false; + unsigned j; if (control & POINTS_ARE_WORDS) { - for (j = 0; j < run_count && i < count; j++, i++) + if (unlikely (p + run_count * HBUINT16::static_size > end)) return false; + for (j = 0; j < run_count; j++, i++) { - if (unlikely (p + HBUINT16::static_size > end)) return false; n += *(const HBUINT16 *)p; - points[i] = n; + points.arrayZ[i] = n; p += HBUINT16::static_size; } } else { - for (j = 0; j < run_count && i < count; j++, i++) + if (unlikely (p + run_count > end)) return false; + for (j = 0; j < run_count; j++, i++) { - if (unlikely (p + 1 > end)) return false; n += *p++; - points[i] = n; + points.arrayZ[i] = n; } } - if (j < run_count) return false; } return true; } @@ -332,32 +331,37 @@ struct GlyphVariationData DELTA_RUN_COUNT_MASK = 0x3F }; - unsigned int i = 0; - unsigned int count = deltas.length; + unsigned i = 0; + unsigned count = deltas.length; while (i < count) { if (unlikely (p + 1 > end)) return false; - uint8_t control = *p++; - unsigned int run_count = (control & DELTA_RUN_COUNT_MASK) + 1; - unsigned int j; + unsigned control = *p++; + unsigned run_count = (control & DELTA_RUN_COUNT_MASK) + 1; + if (unlikely (i + run_count > count)) return false; + unsigned j; if (control & DELTAS_ARE_ZERO) - for (j = 0; j < run_count && i < count; j++, i++) - deltas[i] = 0; + { + for (j = 0; j < run_count; j++, i++) + deltas.arrayZ[i] = 0; + } else if (control & DELTAS_ARE_WORDS) - for (j = 0; j < run_count && i < count; j++, i++) + { + if (unlikely (p + run_count * HBUINT16::static_size > end)) return false; + for (j = 0; j < run_count; j++, i++) { - if (unlikely (p + HBUINT16::static_size > end)) return false; - deltas[i] = *(const HBINT16 *) p; + deltas.arrayZ[i] = * (const HBINT16 *) p; p += HBUINT16::static_size; } + } else - for (j = 0; j < run_count && i < count; j++, i++) + { + if (unlikely (p + run_count > end)) return false; + for (j = 0; j < run_count; j++, i++) { - if (unlikely (p + 1 > end)) return false; - deltas[i] = *(const HBINT8 *) p++; + deltas.arrayZ[i] = * (const HBINT8 *) p++; } - if (j < run_count) - return false; + } } return true; } @@ -450,7 +454,7 @@ struct gvar F2DOT14 *tuples = c->serializer->allocate_size<F2DOT14> (shared_tuple_size); if (!tuples) return_trace (false); out->sharedTuples = (char *) tuples - (char *) out; - memcpy (tuples, this+sharedTuples, shared_tuple_size); + hb_memcpy (tuples, this+sharedTuples, shared_tuple_size); } char *subset_data = c->serializer->allocate_size<char> (subset_data_size); @@ -473,7 +477,7 @@ struct gvar ((HBUINT16 *) subset_offsets)[gid] = glyph_offset / 2; if (var_data_bytes.length > 0) - memcpy (subset_data, var_data_bytes.arrayZ, var_data_bytes.length); + hb_memcpy (subset_data, var_data_bytes.arrayZ, var_data_bytes.length); subset_data += var_data_bytes.length; glyph_offset += var_data_bytes.length; } @@ -501,6 +505,7 @@ struct gvar unsigned get_offset (unsigned i) const { if (unlikely (i > glyphCount)) return 0; + _hb_compiler_memory_r_barrier (); return is_long_offset () ? get_long_offset_array ()[i] : get_short_offset_array ()[i] * 2; } @@ -521,11 +526,11 @@ struct gvar unsigned int target, unsigned int prev, unsigned int next, float contour_point_t::*m) { - float target_val = points[target].*m; - float prev_val = points[prev].*m; - float next_val = points[next].*m; - float prev_delta = deltas[prev].*m; - float next_delta = deltas[next].*m; + float target_val = points.arrayZ[target].*m; + float prev_val = points.arrayZ[prev].*m; + float next_val = points.arrayZ[next].*m; + float prev_delta = deltas.arrayZ[prev].*m; + float next_delta = deltas.arrayZ[next].*m; if (prev_val == next_val) return (prev_delta == next_delta) ? prev_delta : 0.f; @@ -543,10 +548,11 @@ struct gvar { return (i >= end) ? start : (i + 1); } public: - bool apply_deltas_to_points (hb_codepoint_t glyph, hb_font_t *font, + bool apply_deltas_to_points (hb_codepoint_t glyph, + hb_array_t<int> coords, const hb_array_t<contour_point_t> points) const { - if (!font->num_coords) return true; + if (!coords) return true; if (unlikely (glyph >= table->glyphCount)) return true; @@ -559,20 +565,20 @@ struct gvar return true; /* so isn't applied at all */ /* Save original points for inferred delta calculation */ - contour_point_vector_t orig_points; - if (unlikely (!orig_points.resize (points.length))) return false; - for (unsigned int i = 0; i < orig_points.length; i++) - orig_points.arrayZ[i] = points.arrayZ[i]; + contour_point_vector_t orig_points_vec; + orig_points_vec.extend (points); + if (unlikely (orig_points_vec.in_error ())) return false; + auto orig_points = orig_points_vec.as_array (); - contour_point_vector_t deltas; /* flag is used to indicate referenced point */ - if (unlikely (!deltas.resize (points.length))) return false; + contour_point_vector_t deltas_vec; /* flag is used to indicate referenced point */ + if (unlikely (!deltas_vec.resize (points.length, false))) return false; + auto deltas = deltas_vec.as_array (); hb_vector_t<unsigned> end_points; for (unsigned i = 0; i < points.length; ++i) - if (points[i].is_end_point) + if (points.arrayZ[i].is_end_point) end_points.push (i); - auto coords = hb_array (font->coords, font->num_coords); unsigned num_coords = table->axisCount; hb_array_t<const F2DOT14> shared_tuples = (table+table->sharedTuples).as_array (table->sharedTupleCount * table->axisCount); @@ -598,70 +604,89 @@ struct gvar bool apply_to_all = (indices.length == 0); unsigned int num_deltas = apply_to_all ? points.length : indices.length; - if (unlikely (!x_deltas.resize (num_deltas))) return false; + if (unlikely (!x_deltas.resize (num_deltas, false))) return false; if (unlikely (!GlyphVariationData::unpack_deltas (p, x_deltas, end))) return false; - if (unlikely (!y_deltas.resize (num_deltas))) return false; + if (unlikely (!y_deltas.resize (num_deltas, false))) return false; if (unlikely (!GlyphVariationData::unpack_deltas (p, y_deltas, end))) return false; - for (unsigned int i = 0; i < deltas.length; i++) - deltas[i].init (); - for (unsigned int i = 0; i < num_deltas; i++) - { - unsigned int pt_index = apply_to_all ? i : indices[i]; - if (unlikely (pt_index >= deltas.length)) continue; - deltas.arrayZ[pt_index].flag = 1; /* this point is referenced, i.e., explicit deltas specified */ - deltas.arrayZ[pt_index].x += x_deltas.arrayZ[i] * scalar; - deltas.arrayZ[pt_index].y += y_deltas.arrayZ[i] * scalar; - } + hb_memset (deltas.arrayZ, 0, deltas.get_size ()); + + unsigned ref_points = 0; + if (scalar != 1.0f) + for (unsigned int i = 0; i < num_deltas; i++) + { + unsigned int pt_index = apply_to_all ? i : indices[i]; + if (unlikely (pt_index >= deltas.length)) continue; + auto &delta = deltas.arrayZ[pt_index]; + ref_points += !delta.flag; + delta.flag = 1; /* this point is referenced, i.e., explicit deltas specified */ + delta.x += x_deltas.arrayZ[i] * scalar; + delta.y += y_deltas.arrayZ[i] * scalar; + } + else + for (unsigned int i = 0; i < num_deltas; i++) + { + unsigned int pt_index = apply_to_all ? i : indices[i]; + if (unlikely (pt_index >= deltas.length)) continue; + auto &delta = deltas.arrayZ[pt_index]; + ref_points += !delta.flag; + delta.flag = 1; /* this point is referenced, i.e., explicit deltas specified */ + delta.x += x_deltas.arrayZ[i]; + delta.y += y_deltas.arrayZ[i]; + } /* infer deltas for unreferenced points */ - unsigned start_point = 0; - for (unsigned c = 0; c < end_points.length; c++) + if (ref_points && ref_points < orig_points.length) { - unsigned end_point = end_points[c]; + unsigned start_point = 0; + for (unsigned c = 0; c < end_points.length; c++) + { + unsigned end_point = end_points.arrayZ[c]; - /* Check the number of unreferenced points in a contour. If no unref points or no ref points, nothing to do. */ - unsigned unref_count = 0; - for (unsigned i = start_point; i <= end_point; i++) - if (!deltas[i].flag) unref_count++; + /* Check the number of unreferenced points in a contour. If no unref points or no ref points, nothing to do. */ + unsigned unref_count = 0; + for (unsigned i = start_point; i < end_point + 1; i++) + unref_count += deltas.arrayZ[i].flag; + unref_count = (end_point - start_point + 1) - unref_count; - unsigned j = start_point; - if (unref_count == 0 || unref_count > end_point - start_point) - goto no_more_gaps; + unsigned j = start_point; + if (unref_count == 0 || unref_count > end_point - start_point) + goto no_more_gaps; - for (;;) - { - /* Locate the next gap of unreferenced points between two referenced points prev and next. - * Note that a gap may wrap around at left (start_point) and/or at right (end_point). - */ - unsigned int prev, next, i; - for (;;) - { - i = j; - j = next_index (i, start_point, end_point); - if (deltas[i].flag && !deltas[j].flag) break; - } - prev = j = i; - for (;;) - { - i = j; - j = next_index (i, start_point, end_point); - if (!deltas[i].flag && deltas[j].flag) break; - } - next = j; - /* Infer deltas for all unref points in the gap between prev and next */ - i = prev; for (;;) { - i = next_index (i, start_point, end_point); - if (i == next) break; - deltas[i].x = infer_delta (orig_points.as_array (), deltas.as_array (), i, prev, next, &contour_point_t::x); - deltas[i].y = infer_delta (orig_points.as_array (), deltas.as_array (), i, prev, next, &contour_point_t::y); - if (--unref_count == 0) goto no_more_gaps; + /* Locate the next gap of unreferenced points between two referenced points prev and next. + * Note that a gap may wrap around at left (start_point) and/or at right (end_point). + */ + unsigned int prev, next, i; + for (;;) + { + i = j; + j = next_index (i, start_point, end_point); + if (deltas.arrayZ[i].flag && !deltas.arrayZ[j].flag) break; + } + prev = j = i; + for (;;) + { + i = j; + j = next_index (i, start_point, end_point); + if (!deltas.arrayZ[i].flag && deltas.arrayZ[j].flag) break; + } + next = j; + /* Infer deltas for all unref points in the gap between prev and next */ + i = prev; + for (;;) + { + i = next_index (i, start_point, end_point); + if (i == next) break; + deltas.arrayZ[i].x = infer_delta (orig_points, deltas, i, prev, next, &contour_point_t::x); + deltas.arrayZ[i].y = infer_delta (orig_points, deltas, i, prev, next, &contour_point_t::y); + if (--unref_count == 0) goto no_more_gaps; + } } + no_more_gaps: + start_point = end_point + 1; } - no_more_gaps: - start_point = end_point + 1; } /* apply specified / inferred deltas to points */ diff --git a/thirdparty/harfbuzz/src/hb-pool.hh b/thirdparty/harfbuzz/src/hb-pool.hh index dcf8f6627d..e4bb64f627 100644 --- a/thirdparty/harfbuzz/src/hb-pool.hh +++ b/thirdparty/harfbuzz/src/hb-pool.hh @@ -35,15 +35,13 @@ template <typename T, unsigned ChunkLen = 16> struct hb_pool_t { hb_pool_t () : next (nullptr) {} - ~hb_pool_t () { fini (); } - - void fini () + ~hb_pool_t () { next = nullptr; - for (chunk_t *_ : chunks) hb_free (_); - - chunks.fini (); + + hb_iter (chunks) + | hb_apply (hb_free) + ; } T* alloc () @@ -60,7 +58,7 @@ struct hb_pool_t T* obj = next; next = * ((T**) next); - memset (obj, 0, sizeof (T)); + hb_memset (obj, 0, sizeof (T)); return obj; } diff --git a/thirdparty/harfbuzz/src/hb-priority-queue.hh b/thirdparty/harfbuzz/src/hb-priority-queue.hh index ffb86e30ae..ac76b7d955 100644 --- a/thirdparty/harfbuzz/src/hb-priority-queue.hh +++ b/thirdparty/harfbuzz/src/hb-priority-queue.hh @@ -63,7 +63,9 @@ struct hb_priority_queue_t heap.arrayZ[0] = heap.arrayZ[heap.length - 1]; heap.shrink (heap.length - 1); - bubble_down (0); + + if (!is_empty ()) + bubble_down (0); return result; } @@ -100,7 +102,7 @@ struct hb_priority_queue_t void bubble_down (unsigned index) { - assert (index <= heap.length); + assert (index < heap.length); unsigned left = left_child (index); unsigned right = right_child (index); @@ -112,7 +114,7 @@ struct hb_priority_queue_t bool has_right = right < heap.length; if (heap.arrayZ[index].first <= heap.arrayZ[left].first - && (!has_right || heap[index].first <= heap.arrayZ[right].first)) + && (!has_right || heap.arrayZ[index].first <= heap.arrayZ[right].first)) return; if (!has_right || heap.arrayZ[left].first < heap.arrayZ[right].first) @@ -128,7 +130,7 @@ struct hb_priority_queue_t void bubble_up (unsigned index) { - assert (index <= heap.length); + assert (index < heap.length); if (index == 0) return; @@ -142,8 +144,8 @@ struct hb_priority_queue_t void swap (unsigned a, unsigned b) { - assert (a <= heap.length); - assert (b <= heap.length); + assert (a < heap.length); + assert (b < heap.length); hb_swap (heap.arrayZ[a], heap.arrayZ[b]); } }; diff --git a/thirdparty/harfbuzz/src/hb-repacker.hh b/thirdparty/harfbuzz/src/hb-repacker.hh index 40a5326118..7a3143cec3 100644 --- a/thirdparty/harfbuzz/src/hb-repacker.hh +++ b/thirdparty/harfbuzz/src/hb-repacker.hh @@ -209,7 +209,7 @@ bool _try_isolating_subgraphs (const hb_vector_t<graph::overflow_record_t>& over // Only move at most half of the roots in a space at a time. unsigned extra = roots_to_isolate.get_population () - maximum_to_move; while (extra--) { - unsigned root = HB_SET_VALUE_INVALID; + uint32_t root = HB_SET_VALUE_INVALID; roots_to_isolate.previous (&root); roots_to_isolate.del (root); } @@ -244,7 +244,7 @@ bool _process_overflows (const hb_vector_t<graph::overflow_record_t>& overflows, { // The child object is shared, we may be able to eliminate the overflow // by duplicating it. - if (!sorted_graph.duplicate (r.parent, r.child)) continue; + if (sorted_graph.duplicate (r.parent, r.child) == (unsigned) -1) continue; return true; } @@ -283,6 +283,11 @@ hb_resolve_graph_overflows (hb_tag_t table_tag, graph_t& sorted_graph /* IN/OUT */) { sorted_graph.sort_shortest_distance (); + if (sorted_graph.in_error ()) + { + DEBUG_MSG (SUBSET_REPACK, nullptr, "Sorted graph in error state after initial sort."); + return false; + } bool will_overflow = graph::will_overflow (sorted_graph); if (!will_overflow) @@ -376,6 +381,26 @@ hb_resolve_overflows (const T& packed, unsigned max_rounds = 20, bool recalculate_extensions = false) { graph_t sorted_graph (packed); + if (sorted_graph.in_error ()) + { + // Invalid graph definition. + return nullptr; + } + + if (!sorted_graph.is_fully_connected ()) + { + sorted_graph.print_orphaned_nodes (); + return nullptr; + } + + if (sorted_graph.in_error ()) + { + // Allocations failed somewhere + DEBUG_MSG (SUBSET_REPACK, nullptr, + "Graph is in error, likely due to a memory allocation error."); + return nullptr; + } + if (!hb_resolve_graph_overflows (table_tag, max_rounds, recalculate_extensions, sorted_graph)) return nullptr; diff --git a/thirdparty/harfbuzz/src/hb-sanitize.hh b/thirdparty/harfbuzz/src/hb-sanitize.hh index 65c2772201..bd3250e580 100644 --- a/thirdparty/harfbuzz/src/hb-sanitize.hh +++ b/thirdparty/harfbuzz/src/hb-sanitize.hh @@ -198,10 +198,11 @@ struct hb_sanitize_context_t : void start_processing () { reset_object (); - if (unlikely (hb_unsigned_mul_overflows (this->end - this->start, HB_SANITIZE_MAX_OPS_FACTOR))) + unsigned m; + if (unlikely (hb_unsigned_mul_overflows (this->end - this->start, HB_SANITIZE_MAX_OPS_FACTOR, &m))) this->max_ops = HB_SANITIZE_MAX_OPS_MAX; else - this->max_ops = hb_clamp ((unsigned) (this->end - this->start) * HB_SANITIZE_MAX_OPS_FACTOR, + this->max_ops = hb_clamp (m, (unsigned) HB_SANITIZE_MAX_OPS_MIN, (unsigned) HB_SANITIZE_MAX_OPS_MAX); this->edit_count = 0; @@ -252,8 +253,9 @@ struct hb_sanitize_context_t : unsigned int a, unsigned int b) const { - return !hb_unsigned_mul_overflows (a, b) && - this->check_range (base, a * b); + unsigned m; + return !hb_unsigned_mul_overflows (a, b, &m) && + this->check_range (base, m); } template <typename T> @@ -262,8 +264,9 @@ struct hb_sanitize_context_t : unsigned int b, unsigned int c) const { - return !hb_unsigned_mul_overflows (a, b) && - this->check_range (base, a * b, c); + unsigned m; + return !hb_unsigned_mul_overflows (a, b, &m) && + this->check_range (base, m, c); } template <typename T> diff --git a/thirdparty/harfbuzz/src/hb-serialize.hh b/thirdparty/harfbuzz/src/hb-serialize.hh index f47cde5eb5..d5573281f1 100644 --- a/thirdparty/harfbuzz/src/hb-serialize.hh +++ b/thirdparty/harfbuzz/src/hb-serialize.hh @@ -194,7 +194,6 @@ struct hb_serialize_context_t current = current->next; _->fini (); } - object_pool.fini (); } bool in_error () const { return bool (errors); } @@ -224,6 +223,7 @@ struct hb_serialize_context_t this->errors = HB_SERIALIZE_ERROR_NONE; this->head = this->start; this->tail = this->end; + this->zerocopy = nullptr; this->debug_depth = 0; fini (); @@ -326,7 +326,8 @@ struct hb_serialize_context_t if (unlikely (in_error() && !only_overflow ())) return; current = current->next; - revert (obj->head, obj->tail); + revert (zerocopy ? zerocopy : obj->head, obj->tail); + zerocopy = nullptr; obj->fini (); object_pool.release (obj); } @@ -344,8 +345,11 @@ struct hb_serialize_context_t current = current->next; obj->tail = head; obj->next = nullptr; + assert (obj->head <= obj->tail); unsigned len = obj->tail - obj->head; - head = obj->head; /* Rewind head. */ + head = zerocopy ? zerocopy : obj->head; /* Rewind head. */ + bool was_zerocopy = zerocopy; + zerocopy = nullptr; if (!len) { @@ -355,9 +359,11 @@ struct hb_serialize_context_t } objidx_t objidx; + uint32_t hash = 0; if (share) { - objidx = packed_map.get (obj); + hash = hb_hash (obj); + objidx = packed_map.get_with_hash (obj, hash); if (objidx) { merge_virtual_links (obj, objidx); @@ -367,7 +373,10 @@ struct hb_serialize_context_t } tail -= len; - memmove (tail, obj->head, len); + if (was_zerocopy) + assert (tail == obj->head); + else + memmove (tail, obj->head, len); obj->head = tail; obj->tail = tail + len; @@ -385,7 +394,7 @@ struct hb_serialize_context_t objidx = packed.length - 1; - if (share) packed_map.set (obj, objidx); + if (share) packed_map.set_with_hash (obj, hash, objidx); propagate_error (packed_map); return objidx; @@ -569,8 +578,26 @@ struct hb_serialize_context_t return !bool ((errors = (errors | err_type))); } + bool start_zerocopy (size_t size) + { + if (unlikely (in_error ())) return false; + + if (unlikely (size > INT_MAX || this->tail - this->head < ptrdiff_t (size))) + { + err (HB_SERIALIZE_ERROR_OUT_OF_ROOM); + return false; + } + + assert (!this->zerocopy); + this->zerocopy = this->head; + + assert (this->current->head == this->head); + this->current->head = this->current->tail = this->head = this->tail - size; + return true; + } + template <typename Type> - Type *allocate_size (size_t size) + Type *allocate_size (size_t size, bool clear = true) { if (unlikely (in_error ())) return nullptr; @@ -579,7 +606,8 @@ struct hb_serialize_context_t err (HB_SERIALIZE_ERROR_OUT_OF_ROOM); return nullptr; } - hb_memset (this->head, 0, size); + if (clear) + hb_memset (this->head, 0, size); char *ret = this->head; this->head += size; return reinterpret_cast<Type *> (ret); @@ -593,9 +621,9 @@ struct hb_serialize_context_t Type *embed (const Type *obj) { unsigned int size = obj->get_size (); - Type *ret = this->allocate_size<Type> (size); + Type *ret = this->allocate_size<Type> (size, false); if (unlikely (!ret)) return nullptr; - memcpy (ret, obj, size); + hb_memcpy (ret, obj, size); return ret; } template <typename Type> @@ -616,7 +644,7 @@ struct hb_serialize_context_t } /* Like embed, but active: calls obj.operator=() or obj.copy() to transfer data - * instead of memcpy(). */ + * instead of hb_memcpy(). */ template <typename Type, typename ...Ts> Type *copy (const Type &src, Ts&&... ds) { return _copy (src, hb_prioritize, std::forward<Ts> (ds)...); } @@ -634,7 +662,7 @@ struct hb_serialize_context_t hb_serialize_context_t& operator << (const Type &obj) & { embed (obj); return *this; } template <typename Type> - Type *extend_size (Type *obj, size_t size) + Type *extend_size (Type *obj, size_t size, bool clear = true) { if (unlikely (in_error ())) return nullptr; @@ -642,12 +670,12 @@ struct hb_serialize_context_t assert ((char *) obj <= this->head); assert ((size_t) (this->head - (char *) obj) <= size); if (unlikely (((char *) obj + size < (char *) obj) || - !this->allocate_size<Type> (((char *) obj) + size - this->head))) return nullptr; + !this->allocate_size<Type> (((char *) obj) + size - this->head, clear))) return nullptr; return reinterpret_cast<Type *> (obj); } template <typename Type> - Type *extend_size (Type &obj, size_t size) - { return extend_size (std::addressof (obj), size); } + Type *extend_size (Type &obj, size_t size, bool clear = true) + { return extend_size (std::addressof (obj), size, clear); } template <typename Type> Type *extend_min (Type *obj) { return extend_size (obj, obj->min_size); } @@ -676,8 +704,8 @@ struct hb_serialize_context_t char *p = (char *) hb_malloc (len); if (unlikely (!p)) return hb_bytes_t (); - memcpy (p, this->start, this->head - this->start); - memcpy (p + (this->head - this->start), this->tail, this->end - this->tail); + hb_memcpy (p, this->start, this->head - this->start); + hb_memcpy (p + (this->head - this->start), this->tail, this->end - this->tail); return hb_bytes_t (p, len); } template <typename Type> @@ -704,7 +732,7 @@ struct hb_serialize_context_t } public: - char *start, *head, *tail, *end; + char *start, *head, *tail, *end, *zerocopy; unsigned int debug_depth; hb_serialize_error_t errors; diff --git a/thirdparty/harfbuzz/src/hb-set-digest.hh b/thirdparty/harfbuzz/src/hb-set-digest.hh index fab36216e4..e8409111f2 100644 --- a/thirdparty/harfbuzz/src/hb-set-digest.hh +++ b/thirdparty/harfbuzz/src/hb-set-digest.hh @@ -28,6 +28,7 @@ #define HB_SET_DIGEST_HH #include "hb.hh" +#include "hb-machinery.hh" /* * The set-digests here implement various "filters" that support @@ -75,6 +76,8 @@ struct hb_set_digest_bits_pattern_t void init () { mask = 0; } + void add (const hb_set_digest_bits_pattern_t &o) { mask |= o.mask; } + void add (hb_codepoint_t g) { mask |= mask_for (g); } bool add_range (hb_codepoint_t a, hb_codepoint_t b) @@ -95,7 +98,7 @@ struct hb_set_digest_bits_pattern_t for (unsigned int i = 0; i < count; i++) { add (*array); - array = (const T *) (stride + (const char *) array); + array = &StructAtOffsetUnaligned<T> ((const void *) array, stride); } } template <typename T> @@ -103,16 +106,15 @@ struct hb_set_digest_bits_pattern_t template <typename T> bool add_sorted_array (const T *array, unsigned int count, unsigned int stride=sizeof(T)) { - for (unsigned int i = 0; i < count; i++) - { - add (*array); - array = (const T *) (stride + (const char *) array); - } + add_array (array, count, stride); return true; } template <typename T> bool add_sorted_array (const hb_sorted_array_t<const T>& arr) { return add_sorted_array (&arr, arr.len ()); } + bool may_have (const hb_set_digest_bits_pattern_t &o) const + { return mask & o.mask; } + bool may_have (hb_codepoint_t g) const { return mask & mask_for (g); } @@ -132,6 +134,12 @@ struct hb_set_digest_combiner_t tail.init (); } + void add (const hb_set_digest_combiner_t &o) + { + head.add (o.head); + tail.add (o.tail); + } + void add (hb_codepoint_t g) { head.add (g); @@ -140,9 +148,8 @@ struct hb_set_digest_combiner_t bool add_range (hb_codepoint_t a, hb_codepoint_t b) { - head.add_range (a, b); - tail.add_range (a, b); - return true; + return head.add_range (a, b) && + tail.add_range (a, b); } template <typename T> void add_array (const T *array, unsigned int count, unsigned int stride=sizeof(T)) @@ -155,13 +162,17 @@ struct hb_set_digest_combiner_t template <typename T> bool add_sorted_array (const T *array, unsigned int count, unsigned int stride=sizeof(T)) { - head.add_sorted_array (array, count, stride); - tail.add_sorted_array (array, count, stride); - return true; + return head.add_sorted_array (array, count, stride) && + tail.add_sorted_array (array, count, stride); } template <typename T> bool add_sorted_array (const hb_sorted_array_t<const T>& arr) { return add_sorted_array (&arr, arr.len ()); } + bool may_have (const hb_set_digest_combiner_t &o) const + { + return head.may_have (o.head) && tail.may_have (o.tail); + } + bool may_have (hb_codepoint_t g) const { return head.may_have (g) && tail.may_have (g); diff --git a/thirdparty/harfbuzz/src/hb-set.hh b/thirdparty/harfbuzz/src/hb-set.hh index 5d5576cb9e..f958a081fb 100644 --- a/thirdparty/harfbuzz/src/hb-set.hh +++ b/thirdparty/harfbuzz/src/hb-set.hh @@ -105,10 +105,8 @@ struct hb_sparseset_t bool get (hb_codepoint_t g) const { return s.get (g); } /* Has interface. */ - static constexpr bool SENTINEL = false; - typedef bool value_t; - value_t operator [] (hb_codepoint_t k) const { return get (k); } - bool has (hb_codepoint_t k) const { return (*this)[k] != SENTINEL; } + bool operator [] (hb_codepoint_t k) const { return get (k); } + bool has (hb_codepoint_t k) const { return (*this)[k]; } /* Predicate. */ bool operator () (hb_codepoint_t k) const { return has (k); } diff --git a/thirdparty/harfbuzz/src/hb-shape-plan.cc b/thirdparty/harfbuzz/src/hb-shape-plan.cc index 9e513c0458..cabcbd4e72 100644 --- a/thirdparty/harfbuzz/src/hb-shape-plan.cc +++ b/thirdparty/harfbuzz/src/hb-shape-plan.cc @@ -31,6 +31,8 @@ #include "hb-buffer.hh" +#ifndef HB_NO_SHAPER + /** * SECTION:hb-shape-plan * @title: hb-shape-plan @@ -74,7 +76,7 @@ hb_shape_plan_key_t::init (bool copy, this->user_features = copy ? features : user_features; if (copy && num_user_features) { - memcpy (features, user_features, num_user_features * sizeof (hb_feature_t)); + hb_memcpy (features, user_features, num_user_features * sizeof (hb_feature_t)); /* Make start/end uniform to easier catch bugs. */ for (unsigned int i = 0; i < num_user_features; i++) { @@ -574,3 +576,6 @@ retry: return hb_shape_plan_reference (shape_plan); } + + +#endif diff --git a/thirdparty/harfbuzz/src/hb-shape.cc b/thirdparty/harfbuzz/src/hb-shape.cc index 547d0afc47..7b5bf2c5ef 100644 --- a/thirdparty/harfbuzz/src/hb-shape.cc +++ b/thirdparty/harfbuzz/src/hb-shape.cc @@ -35,6 +35,8 @@ #include "hb-machinery.hh" +#ifndef HB_NO_SHAPER + /** * SECTION:hb-shape * @title: hb-shape @@ -192,3 +194,6 @@ hb_shape (hb_font_t *font, { hb_shape_full (font, buffer, features, num_features, nullptr); } + + +#endif diff --git a/thirdparty/harfbuzz/src/hb-shaper.cc b/thirdparty/harfbuzz/src/hb-shaper.cc index a900ac6991..c4885cda94 100644 --- a/thirdparty/harfbuzz/src/hb-shaper.cc +++ b/thirdparty/harfbuzz/src/hb-shaper.cc @@ -53,7 +53,7 @@ static struct hb_shapers_lazy_loader_t : hb_lazy_loader_t<hb_shaper_entry_t, if (unlikely (!shapers)) return nullptr; - memcpy (shapers, _hb_all_shapers, sizeof (_hb_all_shapers)); + hb_memcpy (shapers, _hb_all_shapers, sizeof (_hb_all_shapers)); /* Reorder shaper list to prefer requested shapers. */ unsigned int i = 0; diff --git a/thirdparty/harfbuzz/src/hb-static.cc b/thirdparty/harfbuzz/src/hb-static.cc index 5d4c7cda1b..eac50754c2 100644 --- a/thirdparty/harfbuzz/src/hb-static.cc +++ b/thirdparty/harfbuzz/src/hb-static.cc @@ -33,6 +33,7 @@ #include "hb-aat-layout-feat-table.hh" #include "hb-ot-layout-common.hh" #include "hb-ot-cmap-table.hh" +#include "hb-ot-color-colr-table.hh" #include "hb-ot-glyf-table.hh" #include "hb-ot-head-table.hh" #include "hb-ot-maxp-table.hh" @@ -47,6 +48,7 @@ DEFINE_NULL_NAMESPACE_BYTES (OT, Index) = {0xFF,0xFF}; DEFINE_NULL_NAMESPACE_BYTES (OT, VarIdx) = {0xFF,0xFF,0xFF,0xFF}; DEFINE_NULL_NAMESPACE_BYTES (OT, LangSys) = {0x00,0x00, 0xFF,0xFF, 0x00,0x00}; DEFINE_NULL_NAMESPACE_BYTES (OT, RangeRecord) = {0x01}; +DEFINE_NULL_NAMESPACE_BYTES (OT, ClipRecord) = {0x01}; DEFINE_NULL_NAMESPACE_BYTES (OT, CmapSubtableLongGroup) = {0x00,0x00,0x00,0x01, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00}; DEFINE_NULL_NAMESPACE_BYTES (AAT, SettingName) = {0xFF,0xFF, 0xFF,0xFF}; DEFINE_NULL_NAMESPACE_BYTES (AAT, Lookup) = {0xFF,0xFF}; diff --git a/thirdparty/harfbuzz/src/hb-subset-accelerator.hh b/thirdparty/harfbuzz/src/hb-subset-accelerator.hh new file mode 100644 index 0000000000..63ae6d77e2 --- /dev/null +++ b/thirdparty/harfbuzz/src/hb-subset-accelerator.hh @@ -0,0 +1,121 @@ +/* + * Copyright © 2022 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Garret Rieger + */ + +#ifndef HB_SUBSET_ACCELERATOR_HH +#define HB_SUBSET_ACCELERATOR_HH + + +#include "hb.hh" + +#include "hb-map.hh" +#include "hb-multimap.hh" +#include "hb-set.hh" + +extern HB_INTERNAL hb_user_data_key_t _hb_subset_accelerator_user_data_key; + +namespace CFF { +struct cff_subset_accelerator_t; +} + +namespace OT { +struct SubtableUnicodesCache; +}; + +struct hb_subset_accelerator_t +{ + static hb_user_data_key_t* user_data_key() + { + return &_hb_subset_accelerator_user_data_key; + } + + static hb_subset_accelerator_t* create(const hb_map_t& unicode_to_gid_, + const hb_multimap_t gid_to_unicodes_, + const hb_set_t& unicodes_, + bool has_seac_) { + hb_subset_accelerator_t* accel = + (hb_subset_accelerator_t*) hb_malloc (sizeof(hb_subset_accelerator_t)); + new (accel) hb_subset_accelerator_t (unicode_to_gid_, gid_to_unicodes_, unicodes_); + accel->has_seac = has_seac_; + return accel; + } + + static void destroy(void* value) { + if (!value) return; + + hb_subset_accelerator_t* accel = (hb_subset_accelerator_t*) value; + + if (accel->cff_accelerator && accel->destroy_cff_accelerator) + accel->destroy_cff_accelerator ((void*) accel->cff_accelerator); + + if (accel->cmap_cache && accel->destroy_cmap_cache) + accel->destroy_cmap_cache ((void*) accel->cmap_cache); + + accel->~hb_subset_accelerator_t (); + hb_free (accel); + } + + hb_subset_accelerator_t (const hb_map_t& unicode_to_gid_, + const hb_multimap_t& gid_to_unicodes_, + const hb_set_t& unicodes_) + : unicode_to_gid(unicode_to_gid_), gid_to_unicodes (gid_to_unicodes_), unicodes(unicodes_), + cmap_cache(nullptr), destroy_cmap_cache(nullptr), + has_seac(false), cff_accelerator(nullptr), destroy_cff_accelerator(nullptr) + { sanitized_table_cache_lock.init (); } + + ~hb_subset_accelerator_t () + { sanitized_table_cache_lock.fini (); } + + // Generic + + mutable hb_mutex_t sanitized_table_cache_lock; + mutable hb_hashmap_t<hb_tag_t, hb::unique_ptr<hb_blob_t>> sanitized_table_cache; + + const hb_map_t unicode_to_gid; + const hb_multimap_t gid_to_unicodes; + const hb_set_t unicodes; + + // cmap + const OT::SubtableUnicodesCache* cmap_cache; + hb_destroy_func_t destroy_cmap_cache; + + // CFF + bool has_seac; + const CFF::cff_subset_accelerator_t* cff_accelerator; + hb_destroy_func_t destroy_cff_accelerator; + + // TODO(garretrieger): cumulative glyf checksum map + + bool in_error () const + { + return unicode_to_gid.in_error () || + gid_to_unicodes.in_error () || + unicodes.in_error () || + sanitized_table_cache.in_error (); + } +}; + + +#endif /* HB_SUBSET_ACCELERATOR_HH */ diff --git a/thirdparty/harfbuzz/src/hb-subset-cff-common.cc b/thirdparty/harfbuzz/src/hb-subset-cff-common.cc index 711b2236d6..6e1b6f713d 100644 --- a/thirdparty/harfbuzz/src/hb-subset-cff-common.cc +++ b/thirdparty/harfbuzz/src/hb-subset-cff-common.cc @@ -66,8 +66,7 @@ hb_plan_subset_cff_fdselect (const hb_subset_plan_t *plan, { /* use hb_set to determine the subset of font dicts */ - hb_set_t *set = hb_set_create (); - if (unlikely (set == &Null (hb_set_t))) return false; + hb_set_t set; hb_codepoint_t prev_fd = CFF_UNDEF_CODE; for (hb_codepoint_t i = 0; i < subset_num_glyphs; i++) { @@ -79,7 +78,7 @@ hb_plan_subset_cff_fdselect (const hb_subset_plan_t *plan, glyph = i; } fd = src.get_fd (glyph); - set->add (fd); + set.add (fd); if (fd != prev_fd) { @@ -90,12 +89,11 @@ hb_plan_subset_cff_fdselect (const hb_subset_plan_t *plan, } } - subset_fd_count = set->get_population (); + subset_fd_count = set.get_population (); if (subset_fd_count == fdCount) { /* all font dicts belong to the subset. no need to subset FDSelect & FDArray */ fdmap.identity (fdCount); - hb_set_destroy (set); } else { @@ -103,9 +101,8 @@ hb_plan_subset_cff_fdselect (const hb_subset_plan_t *plan, fdmap.reset (); hb_codepoint_t fd = CFF_UNDEF_CODE; - while (set->next (&fd)) + while (set.next (&fd)) fdmap.add (fd); - hb_set_destroy (set); if (unlikely (fdmap.get_population () != subset_fd_count)) return false; } diff --git a/thirdparty/harfbuzz/src/hb-subset-cff-common.hh b/thirdparty/harfbuzz/src/hb-subset-cff-common.hh index bb9f27eec1..8bbc017656 100644 --- a/thirdparty/harfbuzz/src/hb-subset-cff-common.hh +++ b/thirdparty/harfbuzz/src/hb-subset-cff-common.hh @@ -38,15 +38,16 @@ namespace CFF { struct str_encoder_t { str_encoder_t (str_buff_t &buff_) - : buff (buff_), error (false) {} + : buff (buff_) {} void reset () { buff.reset (); } void encode_byte (unsigned char b) { - buff.push (b); - if (unlikely (buff.in_error ())) - set_error (); + if (likely ((signed) buff.length < buff.allocated)) + buff.arrayZ[buff.length++] = b; + else + buff.push (b); } void encode_int (int v) @@ -108,27 +109,18 @@ struct str_encoder_t encode_byte (op); } - void copy_str (const hb_ubytes_t &str) + void copy_str (const unsigned char *str, unsigned length) { - unsigned int offset = buff.length; - /* Manually resize buffer since faster. */ - if ((signed) (buff.length + str.length) <= buff.allocated) - buff.length += str.length; - else if (unlikely (!buff.resize (offset + str.length))) - { - set_error (); - return; - } - memcpy (buff.arrayZ + offset, &str[0], str.length); + assert ((signed) (buff.length + length) <= buff.allocated); + hb_memcpy (buff.arrayZ + buff.length, str, length); + buff.length += length; } - bool is_error () const { return error; } + bool in_error () const { return buff.in_error (); } protected: - void set_error () { error = true; } str_buff_t &buff; - bool error; }; struct cff_sub_table_info_t { @@ -187,9 +179,12 @@ struct cff_font_dict_op_serializer_t : op_serializer_t } else { - HBUINT8 *d = c->allocate_size<HBUINT8> (opstr.str.length); + unsigned char *d = c->allocate_size<unsigned char> (opstr.length); if (unlikely (!d)) return_trace (false); - memcpy (d, &opstr.str[0], opstr.str.length); + /* Faster than hb_memcpy for small strings. */ + for (unsigned i = 0; i < opstr.length; i++) + d[i] = opstr.ptr[i]; + //hb_memcpy (d, opstr.ptr, opstr.length); } return_trace (true); } @@ -239,11 +234,10 @@ struct subr_flattener_t bool flatten (str_buff_vec_t &flat_charstrings) { - if (!flat_charstrings.resize (plan->num_output_glyphs ())) + unsigned count = plan->num_output_glyphs (); + if (!flat_charstrings.resize (count)) return false; - for (unsigned int i = 0; i < plan->num_output_glyphs (); i++) - flat_charstrings[i].init (); - for (unsigned int i = 0; i < plan->num_output_glyphs (); i++) + for (unsigned int i = 0; i < count; i++) { hb_codepoint_t glyph; if (!plan->old_gid_for_new_gid (i, &glyph)) @@ -259,7 +253,7 @@ struct subr_flattener_t ENV env (str, acc, fd); cs_interpreter_t<ENV, OPSET, flatten_param_t> interp (env); flatten_param_t param = { - flat_charstrings[i], + flat_charstrings.arrayZ[i], (bool) (plan->flags & HB_SUBSET_FLAGS_NO_HINTING) }; if (unlikely (!interp.interpret (param))) @@ -274,11 +268,9 @@ struct subr_flattener_t struct subr_closures_t { - subr_closures_t (unsigned int fd_count) : valid (false), global_closure (), local_closures () + subr_closures_t (unsigned int fd_count) : global_closure (), local_closures () { - valid = true; - if (!local_closures.resize (fd_count)) - valid = false; + local_closures.resize (fd_count); } void reset () @@ -288,47 +280,38 @@ struct subr_closures_t local_closures[i].clear(); } - bool is_valid () const { return valid; } - bool valid; + bool in_error () const { return local_closures.in_error (); } hb_set_t global_closure; hb_vector_t<hb_set_t> local_closures; }; struct parsed_cs_op_t : op_str_t { - void init (unsigned int subr_num_ = 0) - { - subr_num = subr_num_; - drop_flag = false; - keep_flag = false; - skip_flag = false; - } - - bool for_drop () const { return drop_flag; } - void set_drop () { if (!for_keep ()) drop_flag = true; } + parsed_cs_op_t (unsigned int subr_num_ = 0) : + subr_num (subr_num_) {} - bool for_keep () const { return keep_flag; } - void set_keep () { keep_flag = true; } + bool is_hinting () const { return hinting_flag; } + void set_hinting () { hinting_flag = true; } - bool for_skip () const { return skip_flag; } - void set_skip () { skip_flag = true; } - - unsigned int subr_num; + /* The layout of this struct is designed to fit within the + * padding of op_str_t! */ protected: - bool drop_flag; - bool keep_flag; - bool skip_flag; + bool hinting_flag = false; + + public: + uint16_t subr_num; }; struct parsed_cs_str_t : parsed_values_t<parsed_cs_op_t> { - void init () + parsed_cs_str_t () : + parsed (false), + hint_dropped (false), + has_prefix_ (false), + has_calls_ (false) { SUPER::init (); - parsed = false; - hint_dropped = false; - has_prefix_ = false; } void add_op (op_code_t op, const byte_str_ref_t& str_ref) @@ -341,13 +324,12 @@ struct parsed_cs_str_t : parsed_values_t<parsed_cs_op_t> { if (!is_parsed ()) { - unsigned int parsed_len = get_count (); - if (likely (parsed_len > 0)) - values[parsed_len-1].set_skip (); + has_calls_ = true; - parsed_cs_op_t val; - val.init (subr_num); - SUPER::add_op (op, str_ref, val); + /* Pop the subroutine number. */ + values.pop (); + + SUPER::add_op (op, str_ref, {subr_num}); } } @@ -377,11 +359,14 @@ struct parsed_cs_str_t : parsed_values_t<parsed_cs_op_t> op_code_t prefix_op () const { return prefix_op_; } const number_t &prefix_num () const { return prefix_num_; } + bool has_calls () const { return has_calls_; } + protected: - bool parsed; - bool hint_dropped; - bool vsindex_dropped; - bool has_prefix_; + bool parsed : 1; + bool hint_dropped : 1; + bool vsindex_dropped : 1; + bool has_prefix_ : 1; + bool has_calls_ : 1; op_code_t prefix_op_; number_t prefix_num_; @@ -395,6 +380,59 @@ struct parsed_cs_str_vec_t : hb_vector_t<parsed_cs_str_t> typedef hb_vector_t<parsed_cs_str_t> SUPER; }; +struct cff_subset_accelerator_t +{ + static cff_subset_accelerator_t* create ( + hb_blob_t* original_blob, + const parsed_cs_str_vec_t& parsed_charstrings, + const parsed_cs_str_vec_t& parsed_global_subrs, + const hb_vector_t<parsed_cs_str_vec_t>& parsed_local_subrs) { + cff_subset_accelerator_t* accel = + (cff_subset_accelerator_t*) hb_malloc (sizeof(cff_subset_accelerator_t)); + new (accel) cff_subset_accelerator_t (original_blob, + parsed_charstrings, + parsed_global_subrs, + parsed_local_subrs); + return accel; + } + + static void destroy (void* value) { + if (!value) return; + + cff_subset_accelerator_t* accel = (cff_subset_accelerator_t*) value; + accel->~cff_subset_accelerator_t (); + hb_free (accel); + } + + cff_subset_accelerator_t( + hb_blob_t* original_blob_, + const parsed_cs_str_vec_t& parsed_charstrings_, + const parsed_cs_str_vec_t& parsed_global_subrs_, + const hb_vector_t<parsed_cs_str_vec_t>& parsed_local_subrs_) + { + parsed_charstrings = parsed_charstrings_; + parsed_global_subrs = parsed_global_subrs_; + parsed_local_subrs = parsed_local_subrs_; + + // the parsed charstrings point to memory in the original CFF table so we must hold a reference + // to it to keep the memory valid. + original_blob = hb_blob_reference (original_blob_); + } + + ~cff_subset_accelerator_t() { + hb_blob_destroy (original_blob); + hb_map_destroy (glyph_to_sid_map.get_relaxed ()); + } + + parsed_cs_str_vec_t parsed_charstrings; + parsed_cs_str_vec_t parsed_global_subrs; + hb_vector_t<parsed_cs_str_vec_t> parsed_local_subrs; + mutable hb_atomic_ptr_t<hb_map_t> glyph_to_sid_map = nullptr; + + private: + hb_blob_t* original_blob; +}; + struct subr_subset_param_t { subr_subset_param_t (parsed_cs_str_t *parsed_charstring_, @@ -446,7 +484,11 @@ struct subr_subset_param_t if (unlikely (calling && !parsed_str->is_parsed () && (parsed_str->values.length > 0))) env.set_error (); else + { + if (!parsed_str->is_parsed ()) + parsed_str->alloc (env.str_ref.total_size () / 2); current_parsed_str = parsed_str; + } } parsed_cs_str_t *current_parsed_str; @@ -506,7 +548,7 @@ struct subr_remaps_t { global_remap.create (&closures.global_closure); for (unsigned int i = 0; i < local_remaps.length; i++) - local_remaps[i].create (&closures.local_closures[i]); + local_remaps.arrayZ[i].create (&closures.local_closures[i]); } subr_remap_t global_remap; @@ -517,7 +559,8 @@ template <typename SUBSETTER, typename SUBRS, typename ACC, typename ENV, typena struct subr_subsetter_t { subr_subsetter_t (ACC &acc_, const hb_subset_plan_t *plan_) - : acc (acc_), plan (plan_), closures(acc_.fdCount), remaps(acc_.fdCount) + : acc (acc_), plan (plan_), closures(acc_.fdCount), + remaps(acc_.fdCount) {} /* Subroutine subsetting with --no-desubroutinize runs in phases: @@ -536,55 +579,96 @@ struct subr_subsetter_t */ bool subset (void) { - parsed_charstrings.resize (plan->num_output_glyphs ()); - parsed_global_subrs.resize (acc.globalSubrs->count); - - if (unlikely (remaps.in_error() - || parsed_charstrings.in_error () - || parsed_global_subrs.in_error ())) { - return false; + unsigned fd_count = acc.fdCount; + const cff_subset_accelerator_t* cff_accelerator = nullptr; + if (plan->accelerator && plan->accelerator->cff_accelerator) { + cff_accelerator = plan->accelerator->cff_accelerator; + fd_count = cff_accelerator->parsed_local_subrs.length; } - if (unlikely (!parsed_local_subrs.resize (acc.fdCount))) return false; + if (cff_accelerator) { + // If we are not dropping hinting then charstrings are not modified so we can + // just use a reference to the cached copies. + cached_charstrings.resize (plan->num_output_glyphs ()); + parsed_global_subrs = &cff_accelerator->parsed_global_subrs; + parsed_local_subrs = &cff_accelerator->parsed_local_subrs; + } else { + parsed_charstrings.resize (plan->num_output_glyphs ()); + parsed_global_subrs_storage.resize (acc.globalSubrs->count); - for (unsigned int i = 0; i < acc.fdCount; i++) - { - parsed_local_subrs[i].resize (acc.privateDicts[i].localSubrs->count); - if (unlikely (parsed_local_subrs[i].in_error ())) return false; + if (unlikely (!parsed_local_subrs_storage.resize (fd_count))) return false; + + for (unsigned int i = 0; i < acc.fdCount; i++) + { + unsigned count = acc.privateDicts[i].localSubrs->count; + parsed_local_subrs_storage[i].resize (count); + if (unlikely (parsed_local_subrs_storage[i].in_error ())) return false; + } + + parsed_global_subrs = &parsed_global_subrs_storage; + parsed_local_subrs = &parsed_local_subrs_storage; } - if (unlikely (!closures.valid)) + + if (unlikely (remaps.in_error() + || cached_charstrings.in_error () + || parsed_charstrings.in_error () + || parsed_global_subrs->in_error () + || closures.in_error ())) { return false; + } /* phase 1 & 2 */ for (unsigned int i = 0; i < plan->num_output_glyphs (); i++) { hb_codepoint_t glyph; if (!plan->old_gid_for_new_gid (i, &glyph)) - continue; + continue; + const hb_ubytes_t str = (*acc.charStrings)[glyph]; unsigned int fd = acc.fdSelect->get_fd (glyph); if (unlikely (fd >= acc.fdCount)) - return false; + return false; + + if (cff_accelerator) + { + // parsed string already exists in accelerator, copy it and move + // on. + if (cached_charstrings) + cached_charstrings[i] = &cff_accelerator->parsed_charstrings[glyph]; + else + parsed_charstrings[i] = cff_accelerator->parsed_charstrings[glyph]; + + continue; + } ENV env (str, acc, fd); cs_interpreter_t<ENV, OPSET, subr_subset_param_t> interp (env); - parsed_charstrings[i].alloc (str.length); + parsed_charstrings[i].alloc (str.length / 2); subr_subset_param_t param (&parsed_charstrings[i], - &parsed_global_subrs, - &parsed_local_subrs[fd], - &closures.global_closure, - &closures.local_closures[fd], - plan->flags & HB_SUBSET_FLAGS_NO_HINTING); + &parsed_global_subrs_storage, + &parsed_local_subrs_storage[fd], + &closures.global_closure, + &closures.local_closures[fd], + plan->flags & HB_SUBSET_FLAGS_NO_HINTING); if (unlikely (!interp.interpret (param))) - return false; + return false; /* complete parsed string esp. copy CFF1 width or CFF2 vsindex to the parsed charstring for encoding */ SUBSETTER::complete_parsed_str (interp.env, param, parsed_charstrings[i]); } - if (plan->flags & HB_SUBSET_FLAGS_NO_HINTING) + // Since parsed strings were loaded from accelerator, we still need + // to compute the subroutine closures which would have normally happened during + // parsing. + if (cff_accelerator && + !closure_subroutines(*parsed_global_subrs, + *parsed_local_subrs)) + return false; + + if ((plan->flags & HB_SUBSET_FLAGS_NO_HINTING && !cff_accelerator) || + plan->inprogress_accelerator) { /* mark hint ops and arguments for drop */ for (unsigned int i = 0; i < plan->num_output_glyphs (); i++) @@ -596,8 +680,8 @@ struct subr_subsetter_t if (unlikely (fd >= acc.fdCount)) return false; subr_subset_param_t param (&parsed_charstrings[i], - &parsed_global_subrs, - &parsed_local_subrs[fd], + &parsed_global_subrs_storage, + &parsed_local_subrs_storage[fd], &closures.global_closure, &closures.local_closures[fd], plan->flags & HB_SUBSET_FLAGS_NO_HINTING); @@ -612,27 +696,14 @@ struct subr_subsetter_t } /* after dropping hints recreate closures of actually used subrs */ - closures.reset (); - for (unsigned int i = 0; i < plan->num_output_glyphs (); i++) - { - hb_codepoint_t glyph; - if (!plan->old_gid_for_new_gid (i, &glyph)) - continue; - unsigned int fd = acc.fdSelect->get_fd (glyph); - if (unlikely (fd >= acc.fdCount)) - return false; - subr_subset_param_t param (&parsed_charstrings[i], - &parsed_global_subrs, - &parsed_local_subrs[fd], - &closures.global_closure, - &closures.local_closures[fd], - plan->flags & HB_SUBSET_FLAGS_NO_HINTING); - collect_subr_refs_in_str (parsed_charstrings[i], param); - } + if (plan->flags & HB_SUBSET_FLAGS_NO_HINTING && + !cff_accelerator && + !closure_subroutines(*parsed_global_subrs, *parsed_local_subrs)) return false; } remaps.create (closures); + populate_subset_accelerator (); return true; } @@ -646,13 +717,13 @@ struct subr_subsetter_t if (!plan->old_gid_for_new_gid (i, &glyph)) { /* add an endchar only charstring for a missing glyph if CFF1 */ - if (endchar_op != OpCode_Invalid) buffArray[i].push (endchar_op); + if (endchar_op != OpCode_Invalid) buffArray.arrayZ[i].push (endchar_op); continue; } unsigned int fd = acc.fdSelect->get_fd (glyph); if (unlikely (fd >= acc.fdCount)) return false; - if (unlikely (!encode_str (parsed_charstrings[i], fd, buffArray[i]))) + if (unlikely (!encode_str (get_parsed_charstring (i), fd, buffArray.arrayZ[i]))) return false; } return true; @@ -664,26 +735,25 @@ struct subr_subsetter_t if (unlikely (!buffArray.resize (count))) return false; - for (unsigned int old_num = 0; old_num < subrs.length; old_num++) + for (unsigned int new_num = 0; new_num < count; new_num++) { - hb_codepoint_t new_num = remap[old_num]; - if (new_num != CFF_UNDEF_CODE) - { - if (unlikely (!encode_str (subrs[old_num], fd, buffArray[new_num]))) - return false; - } + hb_codepoint_t old_num = remap.backward (new_num); + assert (old_num != CFF_UNDEF_CODE); + + if (unlikely (!encode_str (subrs[old_num], fd, buffArray[new_num]))) + return false; } return true; } bool encode_globalsubrs (str_buff_vec_t &buffArray) { - return encode_subrs (parsed_global_subrs, remaps.global_remap, 0, buffArray); + return encode_subrs (*parsed_global_subrs, remaps.global_remap, 0, buffArray); } bool encode_localsubrs (unsigned int fd, str_buff_vec_t &buffArray) const { - return encode_subrs (parsed_local_subrs[fd], remaps.local_remaps[fd], fd, buffArray); + return encode_subrs ((*parsed_local_subrs)[fd], remaps.local_remaps[fd], fd, buffArray); } protected: @@ -712,7 +782,7 @@ struct subr_subsetter_t * then this entire subroutine must be a hint. drop its call. */ if (drop.ends_in_hint) { - str.values[pos].set_drop (); + str.values[pos].set_hinting (); /* if this subr call is at the end of the parent subr, propagate the flag * otherwise reset the flag */ if (!str.at_end (pos)) @@ -720,7 +790,7 @@ struct subr_subsetter_t } else if (drop.all_dropped) { - str.values[pos].set_drop (); + str.values[pos].set_hinting (); } return has_hint; @@ -731,20 +801,22 @@ struct subr_subsetter_t { bool seen_hint = false; - for (unsigned int pos = 0; pos < str.values.length; pos++) + unsigned count = str.values.length; + auto *values = str.values.arrayZ; + for (unsigned int pos = 0; pos < count; pos++) { bool has_hint = false; - switch (str.values[pos].op) + switch (values[pos].op) { case OpCode_callsubr: has_hint = drop_hints_in_subr (str, pos, - *param.parsed_local_subrs, str.values[pos].subr_num, + *param.parsed_local_subrs, values[pos].subr_num, param, drop); break; case OpCode_callgsubr: has_hint = drop_hints_in_subr (str, pos, - *param.parsed_global_subrs, str.values[pos].subr_num, + *param.parsed_global_subrs, values[pos].subr_num, param, drop); break; @@ -758,7 +830,7 @@ struct subr_subsetter_t case OpCode_cntrmask: if (drop.seen_moveto) { - str.values[pos].set_drop (); + values[pos].set_hinting (); break; } HB_FALLTHROUGH; @@ -768,13 +840,13 @@ struct subr_subsetter_t case OpCode_hstem: case OpCode_vstem: has_hint = true; - str.values[pos].set_drop (); + values[pos].set_hinting (); if (str.at_end (pos)) drop.ends_in_hint = true; break; case OpCode_dotsection: - str.values[pos].set_drop (); + values[pos].set_hinting (); break; default: @@ -785,10 +857,10 @@ struct subr_subsetter_t { for (int i = pos - 1; i >= 0; i--) { - parsed_cs_op_t &csop = str.values[(unsigned)i]; - if (csop.for_drop ()) + parsed_cs_op_t &csop = values[(unsigned)i]; + if (csop.is_hinting ()) break; - csop.set_drop (); + csop.set_hinting (); if (csop.op == OpCode_vsindexcs) drop.vsindex_dropped = true; } @@ -801,12 +873,12 @@ struct subr_subsetter_t * only (usually one) hintmask operator, then calls to this subr can be dropped. */ drop.all_dropped = true; - for (unsigned int pos = 0; pos < str.values.length; pos++) + for (unsigned int pos = 0; pos < count; pos++) { - parsed_cs_op_t &csop = str.values[pos]; + parsed_cs_op_t &csop = values[pos]; if (csop.op == OpCode_return) break; - if (!csop.for_drop ()) + if (!csop.is_hinting ()) { drop.all_dropped = false; break; @@ -816,32 +888,62 @@ struct subr_subsetter_t return seen_hint; } - void collect_subr_refs_in_subr (parsed_cs_str_t &str, unsigned int pos, - unsigned int subr_num, parsed_cs_str_vec_t &subrs, + bool closure_subroutines (const parsed_cs_str_vec_t& global_subrs, + const hb_vector_t<parsed_cs_str_vec_t>& local_subrs) + { + closures.reset (); + for (unsigned int i = 0; i < plan->num_output_glyphs (); i++) + { + hb_codepoint_t glyph; + if (!plan->old_gid_for_new_gid (i, &glyph)) + continue; + unsigned int fd = acc.fdSelect->get_fd (glyph); + if (unlikely (fd >= acc.fdCount)) + return false; + + // Note: const cast is safe here because the collect_subr_refs_in_str only performs a + // closure and does not modify any of the charstrings. + subr_subset_param_t param (const_cast<parsed_cs_str_t*> (&get_parsed_charstring (i)), + const_cast<parsed_cs_str_vec_t*> (&global_subrs), + const_cast<parsed_cs_str_vec_t*> (&local_subrs[fd]), + &closures.global_closure, + &closures.local_closures[fd], + plan->flags & HB_SUBSET_FLAGS_NO_HINTING); + collect_subr_refs_in_str (get_parsed_charstring (i), param); + } + + return true; + } + + void collect_subr_refs_in_subr (unsigned int subr_num, parsed_cs_str_vec_t &subrs, hb_set_t *closure, const subr_subset_param_t ¶m) { + if (closure->has (subr_num)) + return; closure->add (subr_num); collect_subr_refs_in_str (subrs[subr_num], param); } - void collect_subr_refs_in_str (parsed_cs_str_t &str, const subr_subset_param_t ¶m) + void collect_subr_refs_in_str (const parsed_cs_str_t &str, + const subr_subset_param_t ¶m) { - for (unsigned int pos = 0; pos < str.values.length; pos++) + if (!str.has_calls ()) + return; + + for (auto &opstr : str.values) { - if (!str.values[pos].for_drop ()) + if (!param.drop_hints || !opstr.is_hinting ()) { - switch (str.values[pos].op) + switch (opstr.op) { case OpCode_callsubr: - collect_subr_refs_in_subr (str, pos, - str.values[pos].subr_num, *param.parsed_local_subrs, + collect_subr_refs_in_subr (opstr.subr_num, *param.parsed_local_subrs, param.local_closure, param); break; case OpCode_callgsubr: - collect_subr_refs_in_subr (str, pos, - str.values[pos].subr_num, *param.parsed_global_subrs, + collect_subr_refs_in_subr (opstr.subr_num, *param.parsed_global_subrs, param.global_closure, param); break; @@ -853,42 +955,113 @@ struct subr_subsetter_t bool encode_str (const parsed_cs_str_t &str, const unsigned int fd, str_buff_t &buff) const { - unsigned count = str.get_count (); str_encoder_t encoder (buff); encoder.reset (); - buff.alloc (count * 3); + bool hinting = !(plan->flags & HB_SUBSET_FLAGS_NO_HINTING); /* if a prefix (CFF1 width or CFF2 vsindex) has been removed along with hints, * re-insert it at the beginning of charstreing */ - if (str.has_prefix () && str.is_hint_dropped ()) + if (str.has_prefix () && !hinting && str.is_hint_dropped ()) { encoder.encode_num (str.prefix_num ()); if (str.prefix_op () != OpCode_Invalid) encoder.encode_op (str.prefix_op ()); } - for (unsigned int i = 0; i < count; i++) + + unsigned size = 0; + for (auto &opstr : str.values) { - const parsed_cs_op_t &opstr = str.values[i]; - if (!opstr.for_drop () && !opstr.for_skip ()) + size += opstr.length; + if (opstr.op == OpCode_callsubr || opstr.op == OpCode_callgsubr) + size += 3; + } + if (!buff.alloc (buff.length + size)) + return false; + + for (auto &opstr : str.values) + { + if (hinting || !opstr.is_hinting ()) { switch (opstr.op) { case OpCode_callsubr: encoder.encode_int (remaps.local_remaps[fd].biased_num (opstr.subr_num)); - encoder.encode_op (OpCode_callsubr); + encoder.copy_str (opstr.ptr, opstr.length); break; case OpCode_callgsubr: encoder.encode_int (remaps.global_remap.biased_num (opstr.subr_num)); - encoder.encode_op (OpCode_callgsubr); + encoder.copy_str (opstr.ptr, opstr.length); break; default: - encoder.copy_str (opstr.str); + encoder.copy_str (opstr.ptr, opstr.length); break; } } } - return !encoder.is_error (); + return !encoder.in_error (); + } + + void compact_parsed_strings () const + { + for (auto &cs : parsed_charstrings) + compact_string (cs); + for (auto &cs : parsed_global_subrs_storage) + compact_string (cs); + for (auto &vec : parsed_local_subrs_storage) + for (auto &cs : vec) + compact_string (cs); + } + + static void compact_string (parsed_cs_str_t &str) + { + unsigned count = str.values.length; + if (unlikely (!count)) return; + auto &opstr = str.values.arrayZ; + unsigned j = 0; + for (unsigned i = 1; i < count; i++) + { + /* See if we can combine op j and op i. */ + bool combine = + (opstr[j].op != OpCode_callsubr && opstr[j].op != OpCode_callgsubr) && + (opstr[i].op != OpCode_callsubr && opstr[i].op != OpCode_callgsubr) && + (opstr[j].is_hinting () == opstr[i].is_hinting ()) && + (opstr[j].ptr + opstr[j].length == opstr[i].ptr) && + (opstr[j].length + opstr[i].length <= 255); + + if (combine) + { + opstr[j].length += opstr[i].length; + opstr[j].op = OpCode_Invalid; + } + else + { + opstr[++j] = opstr[i]; + } + } + str.values.shrink (j + 1); + } + + void populate_subset_accelerator () const + { + if (!plan->inprogress_accelerator) return; + + compact_parsed_strings (); + + plan->inprogress_accelerator->cff_accelerator = + cff_subset_accelerator_t::create(acc.blob, + parsed_charstrings, + parsed_global_subrs_storage, + parsed_local_subrs_storage); + plan->inprogress_accelerator->destroy_cff_accelerator = + cff_subset_accelerator_t::destroy; + + } + + const parsed_cs_str_t& get_parsed_charstring (unsigned i) const + { + if (cached_charstrings) return *(cached_charstrings[i]); + return parsed_charstrings[i]; } protected: @@ -897,13 +1070,17 @@ struct subr_subsetter_t subr_closures_t closures; - parsed_cs_str_vec_t parsed_charstrings; - parsed_cs_str_vec_t parsed_global_subrs; - hb_vector_t<parsed_cs_str_vec_t> parsed_local_subrs; + hb_vector_t<const parsed_cs_str_t*> cached_charstrings; + const parsed_cs_str_vec_t* parsed_global_subrs; + const hb_vector_t<parsed_cs_str_vec_t>* parsed_local_subrs; subr_remaps_t remaps; private: + + parsed_cs_str_vec_t parsed_charstrings; + parsed_cs_str_vec_t parsed_global_subrs_storage; + hb_vector_t<parsed_cs_str_vec_t> parsed_local_subrs_storage; typedef typename SUBRS::count_type subr_count_type; }; diff --git a/thirdparty/harfbuzz/src/hb-subset-cff1.cc b/thirdparty/harfbuzz/src/hb-subset-cff1.cc index 52bb13d320..538f28f5aa 100644 --- a/thirdparty/harfbuzz/src/hb-subset-cff1.cc +++ b/thirdparty/harfbuzz/src/hb-subset-cff1.cc @@ -167,9 +167,10 @@ struct cff1_top_dict_op_serializer_t : cff_top_dict_op_serializer_t<cff1_top_dic * for supplement, the original byte string is copied along with the op code */ op_str_t supp_op; supp_op.op = op; - if ( unlikely (!(opstr.str.length >= opstr.last_arg_offset + 3))) + if ( unlikely (!(opstr.length >= opstr.last_arg_offset + 3))) return_trace (false); - supp_op.str = hb_ubytes_t (&opstr.str + opstr.last_arg_offset, opstr.str.length - opstr.last_arg_offset); + supp_op.ptr = opstr.ptr + opstr.last_arg_offset; + supp_op.length = opstr.length - opstr.last_arg_offset; return_trace (UnsizedByteStr::serialize_int2 (c, mod.nameSIDs[name_dict_values_t::registry]) && UnsizedByteStr::serialize_int2 (c, mod.nameSIDs[name_dict_values_t::ordering]) && copy_opstr (c, supp_op)); @@ -442,8 +443,17 @@ struct cff_subset_plan { return; } - bool use_glyph_to_sid_map = plan->num_output_glyphs () > plan->source->get_num_glyphs () / 8.; - hb_map_t *glyph_to_sid_map = use_glyph_to_sid_map ? acc.create_glyph_to_sid_map () : nullptr; + hb_map_t *glyph_to_sid_map = (plan->accelerator && plan->accelerator->cff_accelerator) ? + plan->accelerator->cff_accelerator->glyph_to_sid_map : + nullptr; + bool created_map = false; + if (!glyph_to_sid_map && + ((plan->accelerator && plan->accelerator->cff_accelerator) || + plan->num_output_glyphs () > plan->source->get_num_glyphs () / 8.)) + { + created_map = true; + glyph_to_sid_map = acc.create_glyph_to_sid_map (); + } unsigned int glyph; for (glyph = 1; glyph < plan->num_output_glyphs (); glyph++) @@ -467,8 +477,12 @@ struct cff_subset_plan { last_sid = sid; } - if (glyph_to_sid_map) - hb_map_destroy (glyph_to_sid_map); + if (created_map) + { + if (!(plan->accelerator && plan->accelerator->cff_accelerator) || + !plan->accelerator->cff_accelerator->glyph_to_sid_map.cmpexch (nullptr, glyph_to_sid_map)) + hb_map_destroy (glyph_to_sid_map); + } bool two_byte = subset_charset_ranges.complete (glyph); @@ -728,11 +742,17 @@ static bool _serialize_cff1 (hb_serialize_context_t *c, /* CharStrings */ { + c->push<CFF1CharStrings> (); + + unsigned total_size = CFF1CharStrings::total_size (plan.subset_charstrings); + if (unlikely (!c->start_zerocopy (total_size))) + return false; + CFF1CharStrings *cs = c->start_embed<CFF1CharStrings> (); if (unlikely (!cs)) return false; - c->push (); + if (likely (cs->serialize (c, plan.subset_charstrings))) - plan.info.char_strings_link = c->pop_pack (); + plan.info.char_strings_link = c->pop_pack (false); else { c->pop_discard (); @@ -815,7 +835,7 @@ static bool _serialize_cff1 (hb_serialize_context_t *c, CFF1Subrs *dest = c->start_embed <CFF1Subrs> (); if (unlikely (!dest)) return false; if (likely (dest->serialize (c, plan.subset_globalsubrs))) - c->pop_pack (); + c->pop_pack (false); else { c->pop_discard (); diff --git a/thirdparty/harfbuzz/src/hb-subset-cff2.cc b/thirdparty/harfbuzz/src/hb-subset-cff2.cc index 08e820efcf..60946b0281 100644 --- a/thirdparty/harfbuzz/src/hb-subset-cff2.cc +++ b/thirdparty/harfbuzz/src/hb-subset-cff2.cc @@ -334,7 +334,7 @@ static bool _serialize_cff2 (hb_serialize_context_t *c, if (unlikely (!dest)) return false; c->push (); if (likely (dest->serialize (c, plan.subset_localsubrs[i]))) - subrs_link = c->pop_pack (); + subrs_link = c->pop_pack (false); else { c->pop_discard (); @@ -361,11 +361,17 @@ static bool _serialize_cff2 (hb_serialize_context_t *c, /* CharStrings */ { + c->push (); + + unsigned total_size = CFF2CharStrings::total_size (plan.subset_charstrings); + if (unlikely (!c->start_zerocopy (total_size))) + return false; + CFF2CharStrings *cs = c->start_embed<CFF2CharStrings> (); if (unlikely (!cs)) return false; - c->push (); + if (likely (cs->serialize (c, plan.subset_charstrings))) - plan.info.char_strings_link = c->pop_pack (); + plan.info.char_strings_link = c->pop_pack (false); else { c->pop_discard (); @@ -377,9 +383,10 @@ static bool _serialize_cff2 (hb_serialize_context_t *c, if (acc.fdSelect != &Null (CFF2FDSelect)) { c->push (); - if (likely (hb_serialize_cff_fdselect (c, num_glyphs, *(const FDSelect *)acc.fdSelect, plan.orig_fdcount, - plan.subset_fdselect_format, plan.subset_fdselect_size, - plan.subset_fdselect_ranges))) + if (likely (hb_serialize_cff_fdselect (c, num_glyphs, *(const FDSelect *)acc.fdSelect, + plan.orig_fdcount, + plan.subset_fdselect_format, plan.subset_fdselect_size, + plan.subset_fdselect_ranges))) plan.info.fd_select.link = c->pop_pack (); else { @@ -401,7 +408,7 @@ static bool _serialize_cff2 (hb_serialize_context_t *c, hb_iter (private_dict_infos)) ; if (unlikely (!fda->serialize (c, it, fontSzr))) return false; - plan.info.fd_array_link = c->pop_pack (); + plan.info.fd_array_link = c->pop_pack (false); } /* variation store */ @@ -410,7 +417,7 @@ static bool _serialize_cff2 (hb_serialize_context_t *c, c->push (); CFF2VariationStore *dest = c->start_embed<CFF2VariationStore> (); if (unlikely (!dest || !dest->serialize (c, acc.varStore))) return false; - plan.info.var_store_link = c->pop_pack (); + plan.info.var_store_link = c->pop_pack (false); } OT::cff2 *cff2 = c->allocate_min<OT::cff2> (); diff --git a/thirdparty/harfbuzz/src/hb-subset-input.cc b/thirdparty/harfbuzz/src/hb-subset-input.cc index 14ae210d49..42434ae0ef 100644 --- a/thirdparty/harfbuzz/src/hb-subset-input.cc +++ b/thirdparty/harfbuzz/src/hb-subset-input.cc @@ -26,7 +26,7 @@ #include "hb-subset.hh" #include "hb-set.hh" - +#include "hb-utf.hh" /** * hb_subset_input_create_or_fail: * @@ -49,8 +49,15 @@ hb_subset_input_create_or_fail (void) set = hb_set_create (); input->axes_location = hb_hashmap_create<hb_tag_t, float> (); - - if (!input->axes_location || input->in_error ()) +#ifdef HB_EXPERIMENTAL_API + input->name_table_overrides = hb_hashmap_create<hb_ot_name_record_ids_t, hb_bytes_t> (); +#endif + + if (!input->axes_location || +#ifdef HB_EXPERIMENTAL_API + !input->name_table_overrides || +#endif + input->in_error ()) { hb_subset_input_destroy (input); return nullptr; @@ -89,7 +96,6 @@ hb_subset_input_create_or_fail (void) hb_tag_t default_no_subset_tables[] = { HB_TAG ('a', 'v', 'a', 'r'), - HB_TAG ('f', 'v', 'a', 'r'), HB_TAG ('g', 'a', 's', 'p'), HB_TAG ('c', 'v', 't', ' '), HB_TAG ('f', 'p', 'g', 'm'), @@ -249,6 +255,15 @@ hb_subset_input_destroy (hb_subset_input_t *input) hb_hashmap_destroy (input->axes_location); +#ifdef HB_EXPERIMENTAL_API + if (input->name_table_overrides) + { + for (auto _ : *input->name_table_overrides) + _.second.fini (); + } + hb_hashmap_destroy (input->name_table_overrides); +#endif + hb_free (input); } @@ -380,7 +395,6 @@ hb_subset_input_get_user_data (const hb_subset_input_t *input, return hb_object_get_user_data (input, key); } -#ifdef HB_EXPERIMENTAL_API #ifndef HB_NO_VAR /** * hb_subset_input_pin_axis_to_default: (skip) @@ -389,11 +403,14 @@ hb_subset_input_get_user_data (const hb_subset_input_t *input, * * Pin an axis to its default location in the given subset input object. * + * Currently only works for fonts with 'glyf' tables. CFF and CFF2 is not + * yet supported. Additionally all axes in a font must be pinned. + * * Return value: `true` if success, `false` otherwise * - * Since: EXPERIMENTAL + * Since: 6.0.0 **/ -hb_bool_t +HB_EXTERN hb_bool_t hb_subset_input_pin_axis_to_default (hb_subset_input_t *input, hb_face_t *face, hb_tag_t axis_tag) @@ -413,11 +430,14 @@ hb_subset_input_pin_axis_to_default (hb_subset_input_t *input, * * Pin an axis to a fixed location in the given subset input object. * + * Currently only works for fonts with 'glyf' tables. CFF and CFF2 is not + * yet supported. Additionally all axes in a font must be pinned. + * * Return value: `true` if success, `false` otherwise * - * Since: EXPERIMENTAL + * Since: 6.0.0 **/ -hb_bool_t +HB_EXTERN hb_bool_t hb_subset_input_pin_axis_location (hb_subset_input_t *input, hb_face_t *face, hb_tag_t axis_tag, @@ -431,4 +451,150 @@ hb_subset_input_pin_axis_location (hb_subset_input_t *input, return input->axes_location->set (axis_tag, val); } #endif + +/** + * hb_subset_preprocess: + * @source: a #hb_face_t object. + * + * Preprocesses the face and attaches data that will be needed by the + * subsetter. Future subsetting operations can then use the precomputed data + * to speed up the subsetting operation. + * + * See [subset-preprocessing](https://github.com/harfbuzz/harfbuzz/blob/main/docs/subset-preprocessing.md) + * for more information. + * + * Note: the preprocessed face may contain sub-blobs that reference the memory + * backing the source #hb_face_t. Therefore in the case that this memory is not + * owned by the source face you will need to ensure that memory lives + * as long as the returned #hb_face_t. + * + * Returns: a new #hb_face_t. + * + * Since: 6.0.0 + **/ + +HB_EXTERN hb_face_t * +hb_subset_preprocess (hb_face_t *source) +{ + hb_subset_input_t* input = hb_subset_input_create_or_fail (); + if (!input) + return source; + + hb_set_clear (hb_subset_input_set(input, HB_SUBSET_SETS_UNICODE)); + hb_set_invert (hb_subset_input_set(input, HB_SUBSET_SETS_UNICODE)); + + hb_set_clear (hb_subset_input_set(input, HB_SUBSET_SETS_GLYPH_INDEX)); + hb_set_invert (hb_subset_input_set(input, HB_SUBSET_SETS_GLYPH_INDEX)); + + hb_set_clear (hb_subset_input_set(input, + HB_SUBSET_SETS_LAYOUT_FEATURE_TAG)); + hb_set_invert (hb_subset_input_set(input, + HB_SUBSET_SETS_LAYOUT_FEATURE_TAG)); + + hb_set_clear (hb_subset_input_set(input, + HB_SUBSET_SETS_LAYOUT_SCRIPT_TAG)); + hb_set_invert (hb_subset_input_set(input, + HB_SUBSET_SETS_LAYOUT_SCRIPT_TAG)); + + hb_set_clear (hb_subset_input_set(input, + HB_SUBSET_SETS_NAME_ID)); + hb_set_invert (hb_subset_input_set(input, + HB_SUBSET_SETS_NAME_ID)); + + hb_set_clear (hb_subset_input_set(input, + HB_SUBSET_SETS_NAME_LANG_ID)); + hb_set_invert (hb_subset_input_set(input, + HB_SUBSET_SETS_NAME_LANG_ID)); + + hb_subset_input_set_flags(input, + HB_SUBSET_FLAGS_NOTDEF_OUTLINE | + HB_SUBSET_FLAGS_GLYPH_NAMES | + HB_SUBSET_FLAGS_RETAIN_GIDS | + HB_SUBSET_FLAGS_NO_PRUNE_UNICODE_RANGES); + input->attach_accelerator_data = true; + + // Always use long loca in the preprocessed version. This allows + // us to store the glyph bytes unpadded which allows the future subset + // operation to run faster by skipping the trim padding step. + input->force_long_loca = true; + + hb_face_t* new_source = hb_subset_or_fail (source, input); + hb_subset_input_destroy (input); + + if (!new_source) { + DEBUG_MSG (SUBSET, nullptr, "Preprocessing failed due to subset failure."); + return source; + } + + return new_source; +} + +#ifdef HB_EXPERIMENTAL_API +/** + * hb_subset_input_override_name_table: + * @input: a #hb_subset_input_t object. + * @name_id: name_id of a nameRecord + * @platform_id: platform ID of a nameRecord + * @encoding_id: encoding ID of a nameRecord + * @language_id: language ID of a nameRecord + * @name_str: pointer to name string new value or null to indicate should remove + * @str_len: the size of @name_str, or -1 if it is `NULL`-terminated + * + * Override the name string of the NameRecord identified by name_id, + * platform_id, encoding_id and language_id. If a record with that name_id + * doesn't exist, create it and insert to the name table. + * + * Note: for mac platform, we only support name_str with all ascii characters, + * name_str with non-ascii characters will be ignored. + * + * Since: EXPERIMENTAL + **/ +HB_EXTERN hb_bool_t +hb_subset_input_override_name_table (hb_subset_input_t *input, + hb_ot_name_id_t name_id, + unsigned platform_id, + unsigned encoding_id, + unsigned language_id, + const char *name_str, + int str_len /* -1 means nul-terminated */) +{ + if (!name_str) + { + str_len = 0; + } + else if (str_len == -1) + { + str_len = strlen (name_str); + } + + hb_bytes_t name_bytes (nullptr, 0); + if (str_len) + { + if (platform_id == 1) + { + const uint8_t *src = reinterpret_cast<const uint8_t*> (name_str); + const uint8_t *src_end = src + str_len; + + hb_codepoint_t unicode; + const hb_codepoint_t replacement = HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT; + while (src < src_end) + { + src = hb_utf8_t::next (src, src_end, &unicode, replacement); + if (unicode >= 0x0080u) + { + printf ("Non-ascii character detected, ignored...This API supports acsii characters only for mac platform\n"); + return false; + } + } + } + char *override_name = (char *) hb_malloc (str_len); + if (unlikely (!override_name)) return false; + + hb_memcpy (override_name, name_str, str_len); + name_bytes = hb_bytes_t (override_name, str_len); + } + input->name_table_overrides->set (hb_ot_name_record_ids_t (platform_id, encoding_id, language_id, name_id), name_bytes); + return true; +} + #endif diff --git a/thirdparty/harfbuzz/src/hb-subset-input.hh b/thirdparty/harfbuzz/src/hb-subset-input.hh index 2335f0634f..ecd47b7abf 100644 --- a/thirdparty/harfbuzz/src/hb-subset-input.hh +++ b/thirdparty/harfbuzz/src/hb-subset-input.hh @@ -36,6 +36,48 @@ #include "hb-font.hh" +struct hb_ot_name_record_ids_t +{ + hb_ot_name_record_ids_t () = default; + hb_ot_name_record_ids_t (unsigned platform_id_, + unsigned encoding_id_, + unsigned language_id_, + unsigned name_id_) + :platform_id (platform_id_), + encoding_id (encoding_id_), + language_id (language_id_), + name_id (name_id_) {} + + bool operator != (const hb_ot_name_record_ids_t o) const + { return !(*this == o); } + + inline bool operator == (const hb_ot_name_record_ids_t& o) const + { + return platform_id == o.platform_id && + encoding_id == o.encoding_id && + language_id == o.language_id && + name_id == o.name_id; + } + + inline uint32_t hash () const + { + uint32_t current = 0; + current = current * 31 + hb_hash (platform_id); + current = current * 31 + hb_hash (encoding_id); + current = current * 31 + hb_hash (language_id); + current = current * 31 + hb_hash (name_id); + return current; + } + + unsigned platform_id; + unsigned encoding_id; + unsigned language_id; + unsigned name_id; +}; + +typedef struct hb_ot_name_record_ids_t hb_ot_name_record_ids_t; + + HB_MARK_AS_FLAG_T (hb_subset_flags_t); struct hb_subset_input_t @@ -59,7 +101,15 @@ struct hb_subset_input_t }; unsigned flags; + bool attach_accelerator_data = false; + + // If set loca format will always be the long version. + bool force_long_loca = false; + hb_hashmap_t<hb_tag_t, float> *axes_location; +#ifdef HB_EXPERIMENTAL_API + hb_hashmap_t<hb_ot_name_record_ids_t, hb_bytes_t> *name_table_overrides; +#endif inline unsigned num_sets () const { @@ -79,7 +129,11 @@ struct hb_subset_input_t return true; } - return axes_location->in_error (); + return axes_location->in_error () +#ifdef HB_EXPERIMENTAL_API + || name_table_overrides->in_error () +#endif + ; } }; diff --git a/thirdparty/harfbuzz/src/hb-subset-plan.cc b/thirdparty/harfbuzz/src/hb-subset-plan.cc index 079ab8bf99..71bc908ffb 100644 --- a/thirdparty/harfbuzz/src/hb-subset-plan.cc +++ b/thirdparty/harfbuzz/src/hb-subset-plan.cc @@ -25,7 +25,9 @@ */ #include "hb-subset-plan.hh" +#include "hb-subset-accelerator.hh" #include "hb-map.hh" +#include "hb-multimap.hh" #include "hb-set.hh" #include "hb-ot-cmap-table.hh" @@ -46,7 +48,7 @@ using OT::Layout::GPOS; typedef hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> script_langsys_map; #ifndef HB_NO_SUBSET_CFF -static inline void +static inline bool _add_cff_seac_components (const OT::cff1::accelerator_t &cff, hb_codepoint_t gid, hb_set_t *gids_to_retain) @@ -56,7 +58,9 @@ _add_cff_seac_components (const OT::cff1::accelerator_t &cff, { gids_to_retain->add (base_gid); gids_to_retain->add (accent_gid); + return true; } + return false; } #endif @@ -81,10 +85,8 @@ static void _remap_indexes (const hb_set_t *indexes, hb_map_t *mapping /* OUT */) { - unsigned count = indexes->get_population (); - - for (auto _ : + hb_zip (indexes->iter (), hb_range (count))) - mapping->set (_.first, _.second); + for (auto _ : + hb_enumerate (indexes->iter ())) + mapping->set (_.second, _.first); } @@ -129,7 +131,9 @@ template <typename T> static void _collect_layout_indices (hb_subset_plan_t *plan, const T& table, hb_set_t *lookup_indices, /* OUT */ - hb_set_t *feature_indices /* OUT */) + hb_set_t *feature_indices, /* OUT */ + hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *feature_record_cond_idx_map, /* OUT */ + hb_hashmap_t<unsigned, const OT::Feature*> *feature_substitutes_map /* OUT */) { unsigned num_features = table.get_feature_count (); hb_vector_t<hb_tag_t> features; @@ -154,16 +158,37 @@ static void _collect_layout_indices (hb_subset_plan_t *plan, retain_all_features ? nullptr : features.arrayZ, feature_indices); +#ifndef HB_NO_VAR + // collect feature substitutes with variations + if (!plan->user_axes_location->is_empty ()) + { + hb_hashmap_t<hb::shared_ptr<hb_map_t>, unsigned> conditionset_map; + OT::hb_collect_feature_substitutes_with_var_context_t c = + { + plan->axes_old_index_tag_map, + plan->axes_location, + feature_record_cond_idx_map, + feature_substitutes_map, + feature_indices, + true, + 0, + &conditionset_map + }; + table.collect_feature_substitutes_with_variations (&c); + } +#endif + for (unsigned feature_index : *feature_indices) { - //TODO: replace HB_OT_LAYOUT_NO_VARIATIONS_INDEX with variation_index for - //instancing - const OT::Feature &f = table.get_feature_variation (feature_index, HB_OT_LAYOUT_NO_VARIATIONS_INDEX); - f.add_lookup_indexes_to (lookup_indices); + const OT::Feature* f = &(table.get_feature (feature_index)); + const OT::Feature **p = nullptr; + if (feature_substitutes_map->has (feature_index, &p)) + f = *p; + + f->add_lookup_indexes_to (lookup_indices); } - //TODO: update for instancing: only collect lookups from feature_indexes that have no variations - table.feature_variation_collect_lookups (feature_indices, lookup_indices); + table.feature_variation_collect_lookups (feature_indices, feature_substitutes_map, lookup_indices); } @@ -171,6 +196,7 @@ static inline void _GSUBGPOS_find_duplicate_features (const OT::GSUBGPOS &g, const hb_map_t *lookup_indices, const hb_set_t *feature_indices, + const hb_hashmap_t<unsigned, const OT::Feature*> *feature_substitutes_map, hb_map_t *duplicate_feature_map /* OUT */) { if (feature_indices->is_empty ()) return; @@ -195,16 +221,22 @@ _GSUBGPOS_find_duplicate_features (const OT::GSUBGPOS &g, hb_set_t* same_tag_features = unique_features.get (t); for (unsigned other_f_index : same_tag_features->iter ()) { - const OT::Feature& f = g.get_feature (i); - const OT::Feature& other_f = g.get_feature (other_f_index); + const OT::Feature* f = &(g.get_feature (i)); + const OT::Feature **p = nullptr; + if (feature_substitutes_map->has (i, &p)) + f = *p; + + const OT::Feature* other_f = &(g.get_feature (other_f_index)); + if (feature_substitutes_map->has (other_f_index, &p)) + f = *p; auto f_iter = - + hb_iter (f.lookupIndex) + + hb_iter (f->lookupIndex) | hb_filter (lookup_indices) ; auto other_f_iter = - + hb_iter (other_f.lookupIndex) + + hb_iter (other_f->lookupIndex) | hb_filter (lookup_indices) ; @@ -237,7 +269,9 @@ _closure_glyphs_lookups_features (hb_subset_plan_t *plan, hb_set_t *gids_to_retain, hb_map_t *lookups, hb_map_t *features, - script_langsys_map *langsys_map) + script_langsys_map *langsys_map, + hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *feature_record_cond_idx_map, + hb_hashmap_t<unsigned, const OT::Feature*> *feature_substitutes_map) { hb_blob_ptr_t<T> table = plan->source_table<T> (); hb_tag_t table_tag = table->tableTag; @@ -245,7 +279,9 @@ _closure_glyphs_lookups_features (hb_subset_plan_t *plan, _collect_layout_indices<T> (plan, *table, &lookup_indices, - &feature_indices); + &feature_indices, + feature_record_cond_idx_map, + feature_substitutes_map); if (table_tag == HB_OT_TAG_GSUB) hb_ot_layout_lookups_substitute_closure (plan->source, @@ -257,9 +293,12 @@ _closure_glyphs_lookups_features (hb_subset_plan_t *plan, _remap_indexes (&lookup_indices, lookups); // prune features - table->prune_features (lookups, &feature_indices); + table->prune_features (lookups, + plan->user_axes_location->is_empty () ? nullptr : feature_record_cond_idx_map, + feature_substitutes_map, + &feature_indices); hb_map_t duplicate_feature_map; - _GSUBGPOS_find_duplicate_features (*table, lookups, &feature_indices, &duplicate_feature_map); + _GSUBGPOS_find_duplicate_features (*table, lookups, &feature_indices, feature_substitutes_map, &duplicate_feature_map); feature_indices.clear (); table->prune_langsys (&duplicate_feature_map, plan->layout_scripts, langsys_map, &feature_indices); @@ -306,7 +345,9 @@ _get_hb_font_with_variations (const hb_subset_plan_t *plan) vars.push (var); } +#ifndef HB_NO_VAR hb_font_set_variations (font, vars.arrayZ, plan->user_axes_location->get_population ()); +#endif return font; } @@ -419,46 +460,108 @@ _populate_unicodes_to_retain (const hb_set_t *unicodes, hb_subset_plan_t *plan) { OT::cmap::accelerator_t cmap (plan->source); - unsigned size_threshold = plan->source->get_num_glyphs (); if (glyphs->is_empty () && unicodes->get_population () < size_threshold) { + + const hb_map_t* unicode_to_gid = nullptr; + if (plan->accelerator) + unicode_to_gid = &plan->accelerator->unicode_to_gid; + // This is approach to collection is faster, but can only be used if glyphs // are not being explicitly added to the subset and the input unicodes set is // not excessively large (eg. an inverted set). plan->unicode_to_new_gid_list.alloc (unicodes->get_population ()); - for (hb_codepoint_t cp : *unicodes) - { - hb_codepoint_t gid; - if (!cmap.get_nominal_glyph (cp, &gid)) + if (!unicode_to_gid) { + for (hb_codepoint_t cp : *unicodes) { - DEBUG_MSG(SUBSET, nullptr, "Drop U+%04X; no gid", cp); - continue; + hb_codepoint_t gid; + if (!cmap.get_nominal_glyph (cp, &gid)) + { + DEBUG_MSG(SUBSET, nullptr, "Drop U+%04X; no gid", cp); + continue; + } + + plan->codepoint_to_glyph->set (cp, gid); + plan->unicode_to_new_gid_list.push (hb_pair (cp, gid)); + } + } else { + // Use in memory unicode to gid map it's faster then looking up from + // the map. This code is mostly duplicated from above to avoid doing + // conditionals on the presence of the unicode_to_gid map each + // iteration. + for (hb_codepoint_t cp : *unicodes) + { + hb_codepoint_t gid = unicode_to_gid->get (cp); + if (gid == HB_MAP_VALUE_INVALID) + { + DEBUG_MSG(SUBSET, nullptr, "Drop U+%04X; no gid", cp); + continue; + } + + plan->codepoint_to_glyph->set (cp, gid); + plan->unicode_to_new_gid_list.push (hb_pair (cp, gid)); } - - plan->codepoint_to_glyph->set (cp, gid); - plan->unicode_to_new_gid_list.push (hb_pair (cp, gid)); } } else { // This approach is slower, but can handle adding in glyphs to the subset and will match // them with cmap entries. - hb_map_t unicode_glyphid_map; - hb_set_t cmap_unicodes; - cmap.collect_mapping (&cmap_unicodes, &unicode_glyphid_map); - plan->unicode_to_new_gid_list.alloc (hb_min(unicodes->get_population () - + glyphs->get_population (), - cmap_unicodes.get_population ())); - - for (hb_codepoint_t cp : cmap_unicodes) + + hb_map_t unicode_glyphid_map_storage; + hb_set_t cmap_unicodes_storage; + const hb_map_t* unicode_glyphid_map = &unicode_glyphid_map_storage; + const hb_set_t* cmap_unicodes = &cmap_unicodes_storage; + + if (!plan->accelerator) { + cmap.collect_mapping (&cmap_unicodes_storage, &unicode_glyphid_map_storage); + plan->unicode_to_new_gid_list.alloc (hb_min(unicodes->get_population () + + glyphs->get_population (), + cmap_unicodes->get_population ())); + } else { + unicode_glyphid_map = &plan->accelerator->unicode_to_gid; + cmap_unicodes = &plan->accelerator->unicodes; + } + + if (plan->accelerator && + unicodes->get_population () < cmap_unicodes->get_population () && + glyphs->get_population () < cmap_unicodes->get_population ()) + { + auto &gid_to_unicodes = plan->accelerator->gid_to_unicodes; + for (hb_codepoint_t gid : *glyphs) + { + auto unicodes = gid_to_unicodes.get (gid); + + for (hb_codepoint_t cp : unicodes) + { + plan->codepoint_to_glyph->set (cp, gid); + plan->unicode_to_new_gid_list.push (hb_pair (cp, gid)); + } + } + for (hb_codepoint_t cp : *unicodes) + { + /* Don't double-add entry. */ + if (plan->codepoint_to_glyph->has (cp)) + continue; + + hb_codepoint_t gid = (*unicode_glyphid_map)[cp]; + plan->codepoint_to_glyph->set (cp, gid); + plan->unicode_to_new_gid_list.push (hb_pair (cp, gid)); + } + plan->unicode_to_new_gid_list.qsort (); + } + else { - hb_codepoint_t gid = unicode_glyphid_map[cp]; - if (!unicodes->has (cp) && !glyphs->has (gid)) - continue; + for (hb_codepoint_t cp : *cmap_unicodes) + { + hb_codepoint_t gid = (*unicode_glyphid_map)[cp]; + if (!unicodes->has (cp) && !glyphs->has (gid)) + continue; - plan->codepoint_to_glyph->set (cp, gid); - plan->unicode_to_new_gid_list.push (hb_pair (cp, gid)); + plan->codepoint_to_glyph->set (cp, gid); + plan->unicode_to_new_gid_list.push (hb_pair (cp, gid)); + } } /* Add gids which where requested, but not mapped in cmap */ @@ -509,9 +612,7 @@ _glyf_add_gid_and_children (const OT::glyf_accelerator_t &glyf, static void _populate_gids_to_retain (hb_subset_plan_t* plan, - bool close_over_gsub, - bool close_over_gpos, - bool close_over_gdef) + hb_set_t* drop_tables) { OT::glyf_accelerator_t glyf (plan->source); #ifndef HB_NO_SUBSET_CFF @@ -523,32 +624,42 @@ _populate_gids_to_retain (hb_subset_plan_t* plan, _cmap_closure (plan->source, plan->unicodes, plan->_glyphset_gsub); #ifndef HB_NO_SUBSET_LAYOUT - if (close_over_gsub) + if (!drop_tables->has (HB_OT_TAG_GSUB)) // closure all glyphs/lookups/features needed for GSUB substitutions. _closure_glyphs_lookups_features<GSUB> ( plan, plan->_glyphset_gsub, plan->gsub_lookups, plan->gsub_features, - plan->gsub_langsys); + plan->gsub_langsys, + plan->gsub_feature_record_cond_idx_map, + plan->gsub_feature_substitutes_map); - if (close_over_gpos) + if (!drop_tables->has (HB_OT_TAG_GPOS)) _closure_glyphs_lookups_features<GPOS> ( plan, plan->_glyphset_gsub, plan->gpos_lookups, plan->gpos_features, - plan->gpos_langsys); + plan->gpos_langsys, + plan->gpos_feature_record_cond_idx_map, + plan->gpos_feature_substitutes_map); #endif _remove_invalid_gids (plan->_glyphset_gsub, plan->source->get_num_glyphs ()); hb_set_set (plan->_glyphset_mathed, plan->_glyphset_gsub); - _math_closure (plan, plan->_glyphset_mathed); - _remove_invalid_gids (plan->_glyphset_mathed, plan->source->get_num_glyphs ()); + if (!drop_tables->has (HB_OT_TAG_MATH)) + { + _math_closure (plan, plan->_glyphset_mathed); + _remove_invalid_gids (plan->_glyphset_mathed, plan->source->get_num_glyphs ()); + } hb_set_t cur_glyphset = *plan->_glyphset_mathed; - _colr_closure (plan->source, plan->colrv1_layers, plan->colr_palettes, &cur_glyphset); - _remove_invalid_gids (&cur_glyphset, plan->source->get_num_glyphs ()); + if (!drop_tables->has (HB_OT_TAG_COLR)) + { + _colr_closure (plan->source, plan->colrv1_layers, plan->colr_palettes, &cur_glyphset); + _remove_invalid_gids (&cur_glyphset, plan->source->get_num_glyphs ()); + } hb_set_set (plan->_glyphset_colred, &cur_glyphset); @@ -561,16 +672,22 @@ _populate_gids_to_retain (hb_subset_plan_t* plan, else plan->_glyphset->union_ (cur_glyphset); #ifndef HB_NO_SUBSET_CFF - if (cff.is_valid ()) - for (hb_codepoint_t gid : cur_glyphset) - _add_cff_seac_components (cff, gid, plan->_glyphset); + if (!plan->accelerator || plan->accelerator->has_seac) + { + bool has_seac = false; + if (cff.is_valid ()) + for (hb_codepoint_t gid : cur_glyphset) + if (_add_cff_seac_components (cff, gid, plan->_glyphset)) + has_seac = true; + plan->has_seac = has_seac; + } #endif _remove_invalid_gids (plan->_glyphset, plan->source->get_num_glyphs ()); #ifndef HB_NO_VAR - if (close_over_gdef) + if (!drop_tables->has (HB_OT_TAG_GDEF)) _collect_layout_variation_indices (plan); #endif } @@ -659,18 +776,22 @@ _normalize_axes_location (hb_face_t *face, hb_subset_plan_t *plan) seg_maps = face->table.avar->get_segment_maps (); bool axis_not_pinned = false; - unsigned axis_count = 0; + unsigned old_axis_idx = 0, new_axis_idx = 0; for (const auto& axis : axes) { hb_tag_t axis_tag = axis.get_axis_tag (); + plan->axes_old_index_tag_map->set (old_axis_idx, axis_tag); + if (!plan->user_axes_location->has (axis_tag)) { axis_not_pinned = true; + plan->axes_index_map->set (old_axis_idx, new_axis_idx); + new_axis_idx++; } else { int normalized_v = axis.normalize_axis_value (plan->user_axes_location->get (axis_tag)); - if (has_avar && axis_count < face->table.avar->get_axis_count ()) + if (has_avar && old_axis_idx < face->table.avar->get_axis_count ()) { normalized_v = seg_maps->map (normalized_v); } @@ -681,7 +802,7 @@ _normalize_axes_location (hb_face_t *face, hb_subset_plan_t *plan) if (has_avar) seg_maps = &StructAfter<OT::SegmentMaps> (*seg_maps); - axis_count++; + old_axis_idx++; } plan->all_axes_pinned = !axis_not_pinned; } @@ -741,6 +862,13 @@ hb_subset_plan_create_or_fail (hb_face_t *face, plan->gsub_features = hb_map_create (); plan->gpos_features = hb_map_create (); + + plan->check_success (plan->gsub_feature_record_cond_idx_map = hb_hashmap_create<unsigned, hb::shared_ptr<hb_set_t>> ()); + plan->check_success (plan->gpos_feature_record_cond_idx_map = hb_hashmap_create<unsigned, hb::shared_ptr<hb_set_t>> ()); + + plan->check_success (plan->gsub_feature_substitutes_map = hb_hashmap_create<unsigned, const OT::Feature*> ()); + plan->check_success (plan->gpos_feature_substitutes_map = hb_hashmap_create<unsigned, const OT::Feature*> ()); + plan->colrv1_layers = hb_map_create (); plan->colr_palettes = hb_map_create (); plan->check_success (plan->layout_variation_idx_delta_map = hb_hashmap_create<unsigned, hb_pair_t<unsigned, int>> ()); @@ -751,12 +879,40 @@ hb_subset_plan_create_or_fail (hb_face_t *face, plan->check_success (plan->user_axes_location = hb_hashmap_create<hb_tag_t, float> ()); if (plan->user_axes_location && input->axes_location) *plan->user_axes_location = *input->axes_location; + plan->check_success (plan->axes_index_map = hb_map_create ()); + plan->check_success (plan->axes_old_index_tag_map = hb_map_create ()); plan->all_axes_pinned = false; plan->pinned_at_default = true; plan->check_success (plan->vmtx_map = hb_hashmap_create<unsigned, hb_pair_t<unsigned, int>> ()); plan->check_success (plan->hmtx_map = hb_hashmap_create<unsigned, hb_pair_t<unsigned, int>> ()); +#ifdef HB_EXPERIMENTAL_API + plan->check_success (plan->name_table_overrides = hb_hashmap_create<hb_ot_name_record_ids_t, hb_bytes_t> ()); + if (plan->name_table_overrides && input->name_table_overrides) + { + for (auto _ : *input->name_table_overrides) + { + hb_bytes_t name_bytes = _.second; + unsigned len = name_bytes.length; + char *name_str = (char *) hb_malloc (len); + if (unlikely (!plan->check_success (name_str))) + break; + + hb_memcpy (name_str, name_bytes.arrayZ, len); + plan->name_table_overrides->set (_.first, hb_bytes_t (name_str, len)); + } + } +#endif + + void* accel = hb_face_get_user_data(face, hb_subset_accelerator_t::user_data_key()); + + plan->attach_accelerator_data = input->attach_accelerator_data; + plan->force_long_loca = input->force_long_loca; + if (accel) + plan->accelerator = (hb_subset_accelerator_t*) accel; + + if (unlikely (plan->in_error ())) { hb_subset_plan_destroy (plan); return nullptr; @@ -768,10 +924,7 @@ hb_subset_plan_create_or_fail (hb_face_t *face, _populate_unicodes_to_retain (input->sets.unicodes, input->sets.glyphs, plan); - _populate_gids_to_retain (plan, - !input->sets.drop_tables->has (HB_OT_TAG_GSUB), - !input->sets.drop_tables->has (HB_OT_TAG_GPOS), - !input->sets.drop_tables->has (HB_OT_TAG_GDEF)); + _populate_gids_to_retain (plan, input->sets.drop_tables); _create_old_gid_to_new_gid_map (face, input->flags & HB_SUBSET_FLAGS_RETAIN_GIDS, @@ -798,6 +951,28 @@ hb_subset_plan_create_or_fail (hb_face_t *face, hb_subset_plan_destroy (plan); return nullptr; } + + + if (plan->attach_accelerator_data) + { + hb_multimap_t gid_to_unicodes; + + hb_map_t &unicode_to_gid = *plan->codepoint_to_glyph; + + for (auto unicode : *plan->unicodes) + { + auto gid = unicode_to_gid[unicode]; + gid_to_unicodes.add (gid, unicode); + } + + plan->inprogress_accelerator = + hb_subset_accelerator_t::create (*plan->codepoint_to_glyph, + gid_to_unicodes, + *plan->unicodes, + plan->has_seac); + } + + return plan; } diff --git a/thirdparty/harfbuzz/src/hb-subset-plan.hh b/thirdparty/harfbuzz/src/hb-subset-plan.hh index 98a45e5f6d..1b2aee7825 100644 --- a/thirdparty/harfbuzz/src/hb-subset-plan.hh +++ b/thirdparty/harfbuzz/src/hb-subset-plan.hh @@ -31,11 +31,16 @@ #include "hb-subset.h" #include "hb-subset-input.hh" +#include "hb-subset-accelerator.hh" #include "hb-map.hh" #include "hb-bimap.hh" #include "hb-set.hh" +namespace OT { +struct Feature; +} + struct hb_subset_plan_t { hb_subset_plan_t () @@ -67,15 +72,33 @@ struct hb_subset_plan_t hb_map_destroy (gpos_features); hb_map_destroy (colrv1_layers); hb_map_destroy (colr_palettes); + hb_map_destroy (axes_index_map); + hb_map_destroy (axes_old_index_tag_map); hb_hashmap_destroy (gsub_langsys); hb_hashmap_destroy (gpos_langsys); + hb_hashmap_destroy (gsub_feature_record_cond_idx_map); + hb_hashmap_destroy (gpos_feature_record_cond_idx_map); + hb_hashmap_destroy (gsub_feature_substitutes_map); + hb_hashmap_destroy (gpos_feature_substitutes_map); hb_hashmap_destroy (axes_location); hb_hashmap_destroy (sanitized_table_cache); hb_hashmap_destroy (hmtx_map); hb_hashmap_destroy (vmtx_map); hb_hashmap_destroy (layout_variation_idx_delta_map); +#ifdef HB_EXPERIMENTAL_API + if (name_table_overrides) + { + for (auto _ : *name_table_overrides) + _.second.fini (); + } + hb_hashmap_destroy (name_table_overrides); +#endif + + if (inprogress_accelerator) + hb_subset_accelerator_t::destroy ((void*) inprogress_accelerator); + if (user_axes_location) { hb_object_destroy (user_axes_location); @@ -87,10 +110,12 @@ struct hb_subset_plan_t bool successful; unsigned flags; + bool attach_accelerator_data = false; + bool force_long_loca = false; // For each cp that we'd like to retain maps to the corresponding gid. hb_set_t *unicodes; - hb_vector_t<hb_pair_t<hb_codepoint_t, hb_codepoint_t>> unicode_to_new_gid_list; + hb_sorted_vector_t<hb_pair_t<hb_codepoint_t, hb_codepoint_t>> unicode_to_new_gid_list; // name_ids we would like to retain hb_set_t *name_ids; @@ -143,6 +168,15 @@ struct hb_subset_plan_t hb_map_t *gsub_features; hb_map_t *gpos_features; + //active feature variation records/condition index with variations + hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *gsub_feature_record_cond_idx_map; + hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *gpos_feature_record_cond_idx_map; + + //feature index-> address of substituation feature table mapping with + //variations + hb_hashmap_t<unsigned, const OT::Feature*> *gsub_feature_substitutes_map; + hb_hashmap_t<unsigned, const OT::Feature*> *gpos_feature_substitutes_map; + //active layers/palettes we'd like to retain hb_map_t *colrv1_layers; hb_map_t *colr_palettes; @@ -158,31 +192,47 @@ struct hb_subset_plan_t hb_hashmap_t<hb_tag_t, int> *axes_location; //user specified axes location map hb_hashmap_t<hb_tag_t, float> *user_axes_location; + //retained old axis index -> new axis index mapping in fvar axis array + hb_map_t *axes_index_map; + //axis_index->axis_tag mapping in fvar axis array + hb_map_t *axes_old_index_tag_map; bool all_axes_pinned; bool pinned_at_default; + bool has_seac; //hmtx metrics map: new gid->(advance, lsb) hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *hmtx_map; //vmtx metrics map: new gid->(advance, lsb) hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *vmtx_map; +#ifdef HB_EXPERIMENTAL_API + // name table overrides map: hb_ot_name_record_ids_t-> name string new value or + // None to indicate should remove + hb_hashmap_t<hb_ot_name_record_ids_t, hb_bytes_t> *name_table_overrides; +#endif + + const hb_subset_accelerator_t* accelerator; + hb_subset_accelerator_t* inprogress_accelerator; + public: template<typename T> hb_blob_ptr_t<T> source_table() { - if (sanitized_table_cache - && !sanitized_table_cache->in_error () - && sanitized_table_cache->has (T::tableTag)) { - return hb_blob_reference (sanitized_table_cache->get (T::tableTag).get ()); + hb_lock_t (accelerator ? &accelerator->sanitized_table_cache_lock : nullptr); + + auto *cache = accelerator ? &accelerator->sanitized_table_cache : sanitized_table_cache; + if (cache + && !cache->in_error () + && cache->has (+T::tableTag)) { + return hb_blob_reference (cache->get (+T::tableTag).get ()); } hb::unique_ptr<hb_blob_t> table_blob {hb_sanitize_context_t ().reference_table<T> (source)}; hb_blob_t* ret = hb_blob_reference (table_blob.get ()); - if (likely (sanitized_table_cache)) - sanitized_table_cache->set (T::tableTag, - std::move (table_blob)); + if (likely (cache)) + cache->set (+T::tableTag, std::move (table_blob)); return ret; } diff --git a/thirdparty/harfbuzz/src/hb-subset.cc b/thirdparty/harfbuzz/src/hb-subset.cc index 1a0bcbd1fe..186b12dbb8 100644 --- a/thirdparty/harfbuzz/src/hb-subset.cc +++ b/thirdparty/harfbuzz/src/hb-subset.cc @@ -50,11 +50,13 @@ #include "hb-ot-color-cbdt-table.hh" #include "hb-ot-layout-gsub-table.hh" #include "hb-ot-layout-gpos-table.hh" +#include "hb-ot-var-fvar-table.hh" #include "hb-ot-var-gvar-table.hh" #include "hb-ot-var-hvar-table.hh" #include "hb-ot-math-table.hh" #include "hb-ot-stat-table.hh" #include "hb-repacker.hh" +#include "hb-subset-accelerator.hh" using OT::Layout::GSUB; using OT::Layout::GPOS; @@ -80,6 +82,10 @@ using OT::Layout::GPOS; * retain glyph ids option and configure the subset to pass through the layout tables untouched. */ + +hb_user_data_key_t _hb_subset_accelerator_user_data_key = {}; + + /* * The list of tables in the open type spec. Used to check for tables that may need handling * if we are unable to list the tables in a face. @@ -407,20 +413,14 @@ _passthrough (hb_subset_plan_t *plan, hb_tag_t tag) static bool _dependencies_satisfied (hb_subset_plan_t *plan, hb_tag_t tag, - hb_set_t &visited_set, hb_set_t &revisit_set) + const hb_set_t &subsetted_tags, + const hb_set_t &pending_subset_tags) { switch (tag) { case HB_OT_TAG_hmtx: case HB_OT_TAG_vmtx: - if (!plan->pinned_at_default && - !visited_set.has (HB_OT_TAG_glyf)) - { - revisit_set.add (tag); - return false; - } - return true; - + return plan->pinned_at_default || !pending_subset_tags.has (HB_OT_TAG_glyf); default: return true; } @@ -475,6 +475,9 @@ _subset_table (hb_subset_plan_t *plan, case HB_OT_TAG_HVAR: return _subset<const OT::HVAR> (plan, buf); case HB_OT_TAG_VVAR: return _subset<const OT::VVAR> (plan, buf); #endif + case HB_OT_TAG_fvar: + if (plan->user_axes_location->is_empty ()) return _passthrough (plan, tag); + return _subset<const OT::fvar> (plan, buf); case HB_OT_TAG_STAT: /*TODO(qxliu): change the condition as we support more complex * instancing operation*/ @@ -490,6 +493,34 @@ _subset_table (hb_subset_plan_t *plan, } } +static void _attach_accelerator_data (hb_subset_plan_t* plan, + hb_face_t* face /* IN/OUT */) +{ + if (!plan->inprogress_accelerator) return; + + // Transfer the accelerator from the plan to us. + hb_subset_accelerator_t* accel = plan->inprogress_accelerator; + plan->inprogress_accelerator = nullptr; + + if (accel->in_error ()) + { + hb_subset_accelerator_t::destroy (accel); + return; + } + + // Populate caches that need access to the final tables. + hb_blob_ptr_t<OT::cmap> cmap_ptr (hb_sanitize_context_t ().reference_table<OT::cmap> (face)); + accel->cmap_cache = OT::cmap::create_filled_cache (cmap_ptr); + accel->destroy_cmap_cache = OT::SubtableUnicodesCache::destroy; + + if (!hb_face_set_user_data(face, + hb_subset_accelerator_t::user_data_key(), + accel, + hb_subset_accelerator_t::destroy, + true)) + hb_subset_accelerator_t::destroy (accel); +} + /** * hb_subset_or_fail: * @source: font face data to be subset. @@ -535,41 +566,67 @@ hb_subset_plan_execute_or_fail (hb_subset_plan_t *plan) return nullptr; } - hb_set_t tags_set, revisit_set; - bool success = true; hb_tag_t table_tags[32]; unsigned offset = 0, num_tables = ARRAY_LENGTH (table_tags); - hb_vector_t<char> buf; - buf.alloc (4096 - 16); + hb_set_t subsetted_tags, pending_subset_tags; while (((void) _get_table_tags (plan, offset, &num_tables, table_tags), num_tables)) { for (unsigned i = 0; i < num_tables; ++i) { hb_tag_t tag = table_tags[i]; - if (_should_drop_table (plan, tag) && !tags_set.has (tag)) continue; - if (!_dependencies_satisfied (plan, tag, tags_set, revisit_set)) continue; - tags_set.add (tag); - success = _subset_table (plan, buf, tag); - if (unlikely (!success)) goto end; + if (_should_drop_table (plan, tag)) continue; + pending_subset_tags.add (tag); + } + + offset += num_tables; + } + + hb_vector_t<char> buf; + buf.alloc (4096 - 16); + + + bool success = true; + + while (!pending_subset_tags.is_empty ()) + { + if (subsetted_tags.in_error () + || pending_subset_tags.in_error ()) { + success = false; + goto end; } - /*delayed subsetting for some tables since they might have dependency on other tables in some cases: - e.g: during instantiating glyf tables, hmetrics/vmetrics are updated and saved in subset plan, - hmtx/vmtx subsetting need to use these updated metrics values*/ - while (!revisit_set.is_empty ()) + bool made_changes = false; + for (hb_tag_t tag : pending_subset_tags) { - hb_set_t revisit_temp; - for (hb_tag_t tag : revisit_set) + if (!_dependencies_satisfied (plan, tag, + subsetted_tags, + pending_subset_tags)) { - if (!_dependencies_satisfied (plan, tag, tags_set, revisit_temp)) continue; - tags_set.add (tag); - success = _subset_table (plan, buf, tag); - if (unlikely (!success)) goto end; + // delayed subsetting for some tables since they might have dependency on other tables + // in some cases: e.g: during instantiating glyf tables, hmetrics/vmetrics are updated + // and saved in subset plan, hmtx/vmtx subsetting need to use these updated metrics values + continue; } - revisit_set = revisit_temp; + + pending_subset_tags.del (tag); + subsetted_tags.add (tag); + made_changes = true; + + success = _subset_table (plan, buf, tag); + if (unlikely (!success)) goto end; } - offset += num_tables; + + if (!made_changes) + { + DEBUG_MSG (SUBSET, nullptr, "Table dependencies unable to be satisfied. Subset failed."); + success = false; + goto end; + } + } + + if (success && plan->attach_accelerator_data) { + _attach_accelerator_data (plan, plan->dest); } end: diff --git a/thirdparty/harfbuzz/src/hb-subset.h b/thirdparty/harfbuzz/src/hb-subset.h index 08e52dbd2d..b83264ea5e 100644 --- a/thirdparty/harfbuzz/src/hb-subset.h +++ b/thirdparty/harfbuzz/src/hb-subset.h @@ -28,6 +28,7 @@ #define HB_SUBSET_H #include "hb.h" +#include "hb-ot.h" HB_BEGIN_DECLS @@ -70,6 +71,14 @@ typedef struct hb_subset_plan_t hb_subset_plan_t; * in the final subset. * @HB_SUBSET_FLAGS_NO_PRUNE_UNICODE_RANGES: If set then the unicode ranges in * OS/2 will not be recalculated. + * @HB_SUBSET_FLAGS_PATCH_MODE: If set the subsetter behaviour will be modified + * to produce a subset that is better suited to patching. For example cmap + * subtable format will be kept stable. + * @HB_SUBSET_FLAGS_OMIT_GLYF: If set the subsetter won't actually produce the final + * glyf table bytes. The table directory will include and entry as if the table was + * there but the actual final font blob will be truncated prior to the glyf data. This + * is a useful performance optimization when a font aware binary patching algorithm + * is being used to diff two subsets. * * List of boolean properties that can be configured on the subset input. * @@ -86,6 +95,8 @@ typedef enum { /*< flags >*/ HB_SUBSET_FLAGS_NOTDEF_OUTLINE = 0x00000040u, HB_SUBSET_FLAGS_GLYPH_NAMES = 0x00000080u, HB_SUBSET_FLAGS_NO_PRUNE_UNICODE_RANGES = 0x00000100u, + // Not supported yet: HB_SUBSET_FLAGS_PATCH_MODE = 0x00000200u, + // Not supported yet: HB_SUBSET_FLAGS_OMIT_GLYF = 0x00000400u, } hb_subset_flags_t; /** @@ -154,8 +165,6 @@ HB_EXTERN void hb_subset_input_set_flags (hb_subset_input_t *input, unsigned value); -#ifdef HB_EXPERIMENTAL_API -#ifndef HB_NO_VAR HB_EXTERN hb_bool_t hb_subset_input_pin_axis_to_default (hb_subset_input_t *input, hb_face_t *face, @@ -166,8 +175,21 @@ hb_subset_input_pin_axis_location (hb_subset_input_t *input, hb_face_t *face, hb_tag_t axis_tag, float axis_value); + +#ifdef HB_EXPERIMENTAL_API +HB_EXTERN hb_bool_t +hb_subset_input_override_name_table (hb_subset_input_t *input, + hb_ot_name_id_t name_id, + unsigned platform_id, + unsigned encoding_id, + unsigned language_id, + const char *name_str, + int str_len); + #endif -#endif + +HB_EXTERN hb_face_t * +hb_subset_preprocess (hb_face_t *source); HB_EXTERN hb_face_t * hb_subset_or_fail (hb_face_t *source, const hb_subset_input_t *input); diff --git a/thirdparty/harfbuzz/src/hb-ucd-table.hh b/thirdparty/harfbuzz/src/hb-ucd-table.hh index a372a4afce..f7d76eee18 100644 --- a/thirdparty/harfbuzz/src/hb-ucd-table.hh +++ b/thirdparty/harfbuzz/src/hb-ucd-table.hh @@ -1069,7 +1069,7 @@ _hb_ucd_dm2_u64_map[388] = #ifndef HB_OPTIMIZE_SIZE static const uint8_t -_hb_ucd_u8[18260] = +_hb_ucd_u8[17868] = { 0, 1, 2, 3, 4, 5, 6, 7, 7, 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 9, 10, 7, 7, 7, 7, 11, 12, 13, 13, 13, 14, @@ -1535,191 +1535,166 @@ _hb_ucd_u8[18260] = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38, 39, 0, 0, 0, 0, 0, 0, 40, 41, 42, 0, 43, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 0, 0, 0, 0, - 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 6, 7, 8, 0, - 9, 0, 10, 11, 0, 0, 12, 13, 14, 15, 16, 0, 0, 0, 0, 17, - 18, 19, 20, 0, 21, 0, 22, 23, 0, 24, 25, 0, 0, 24, 26, 27, - 0, 24, 26, 0, 0, 24, 26, 0, 0, 24, 26, 0, 0, 0, 26, 0, - 0, 24, 28, 0, 0, 24, 26, 0, 0, 29, 26, 0, 0, 0, 30, 0, - 0, 31, 32, 0, 0, 33, 34, 0, 35, 36, 0, 37, 38, 0, 39, 0, - 0, 40, 0, 0, 41, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 43, 44, 0, 0, 0, 0, 45, 0, - 0, 0, 0, 0, 0, 46, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, - 48, 0, 0, 49, 0, 50, 51, 0, 0, 52, 53, 54, 0, 55, 0, 56, - 0, 57, 0, 0, 0, 0, 58, 59, 0, 0, 0, 0, 0, 0, 60, 61, - 0, 0, 0, 0, 0, 0, 62, 63, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 65, 0, 0, 0, 66, - 0, 67, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 69, 70, 0, 0, 71, 0, 0, 0, 0, 0, 0, 0, 0, - 72, 73, 0, 0, 0, 0, 53, 74, 0, 75, 76, 0, 0, 77, 78, 0, - 0, 0, 0, 0, 0, 79, 80, 81, 0, 0, 0, 0, 0, 0, 0, 26, - 0, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, - 0, 83, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, - 0, 0, 0, 0, 0, 0, 0, 85, 0, 0, 0, 86, 0, 0, 0, 0, - 87, 88, 0, 0, 0, 0, 0, 89, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 91, 0, 92, 0, 0, 93, 0, 94, 0, 0, 0, - 0, 0, 72, 95, 0, 96, 0, 0, 97, 98, 0, 77, 0, 0, 99, 0, - 0,100, 0, 0, 0, 0, 0,101, 0,102, 26,103, 0, 0, 0, 0, - 0, 0,104, 0, 0, 0,105, 0, 0, 0, 0, 0, 0, 65,106, 0, - 0, 65, 0, 0, 0,107, 0, 0, 0,108, 0, 0, 0, 0, 0, 0, - 0, 96, 0, 0, 0, 0, 0, 0, 0,109,110, 0, 0, 0, 0, 78, - 0, 44,111, 0,112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 65, 0, 0, 0, 0, 0, 0, 0, 0,113, 0,114, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,115, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0,116, 0,117, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,118, - 0, 0, 0, 0,119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,120,121,122, 0, 0, - 0, 0,123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 124,125, 0, 0,126, 0, 0, 0, 0,117, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0,127, 0,128, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0,129, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,130, 0, 0, 0,131, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 3, 4, - 5, 6, 7, 4, 4, 8, 9, 10, 1, 11, 12, 13, 14, 15, 16, 17, - 18, 1, 1, 1, 0, 0, 0, 0, 19, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 20, 21, 22, 1, 23, 4, 21, 24, 25, 26, 27, 28, - 29, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 31, 0, - 0, 0, 32, 33, 34, 35, 1, 36, 0, 0, 0, 0, 37, 0, 0, 0, - 0, 0, 0, 0, 0, 38, 1, 39, 14, 39, 40, 41, 0, 0, 0, 0, - 0, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 43, 36, 44, 45, - 21, 45, 46, 0, 0, 0, 0, 0, 0, 0, 19, 1, 21, 0, 0, 47, - 0, 0, 0, 0, 0, 38, 48, 1, 1, 49, 49, 50, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 51, 0, 0, 0, 0, 0, 0, 0, 52, 1, - 0, 0, 38, 14, 4, 1, 1, 1, 53, 21, 43, 52, 54, 21, 35, 1, - 0, 0, 0, 0, 0, 0, 0, 55, 0, 0, 0, 56, 57, 58, 0, 0, - 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59, - 0, 0, 0, 56, 0, 60, 0, 0, 0, 0, 0, 0, 0, 0, 61, 62, - 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, - 0, 0, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 0, - 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 0, - 0, 0, 0, 0, 0, 69, 70, 0, 0, 0, 0, 0, 71, 72, 73, 74, - 75, 76, 0, 0, 0, 0, 0, 0, 0, 77, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 78, 79, 0, 0, 0, 0, 47, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 49, 0, 0, 0, 0, 0, 80, 0, 0, - 0, 0, 0, 0, 0, 62, 0, 0, 0, 0, 0, 0, 63, 0, 0, 81, - 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 0, - 0, 0, 0, 0, 0, 19, 84, 0, 62, 0, 0, 0, 0, 49, 1, 85, - 0, 0, 0, 0, 1, 52, 15, 86, 36, 10, 21, 87, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 55, 0, 0, 0, 62, 0, 0, 0, 0, 0, 0, - 0, 0, 19, 10, 1, 0, 0, 0, 0, 0, 88, 0, 0, 0, 0, 0, - 0, 89, 0, 0, 88, 0, 0, 0, 0, 0, 0, 0, 0, 78, 0, 0, - 0, 0, 0, 0, 87, 9, 12, 4, 90, 8, 91, 47, 0, 58, 50, 0, - 21, 1, 21, 92, 93, 1, 1, 1, 1, 1, 1, 1, 1, 94, 95, 96, - 0, 0, 0, 0, 97, 1, 98, 58, 81, 99,100, 4, 58, 0, 0, 0, - 0, 0, 0, 19, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61, - 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,101,102, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,103, 0, 0, 0, 0, 19, 0, 1, 1, 50, - 0, 0, 0, 0, 0, 0, 0, 38, 0, 0, 0, 0, 50, 0, 0, 0, - 0, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0, 0, - 1, 1, 1, 1, 50, 0, 0, 0, 0, 0,104, 68, 0, 0, 0, 0, - 0, 0, 0, 0, 61, 0, 0, 0, 0, 0, 0, 0, 78, 0, 0, 0, - 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,105,106, 58, 38, - 81, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, - 0, 0, 0, 0, 0, 0, 0,107, 1, 14, 4, 12, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 47, 84, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 38, 87, 0, 0, 0, 0,108, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,109, 61, 0,110, 0, 0, 0, 0, 0, 0, - 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 19, 58, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 51, 0,111, 14, 52, 84, 0, 0, 0, - 112, 41, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 61, - 0, 0, 0, 0, 0, 0,113, 0, 87, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 61, 62, 0, 0, 62, 0, 89, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0,113, 0, 0, 0, 0,114, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 78, 55, 0, 38, 1, 58, 1, 58, 0, 0, - 63, 89, 0, 0, 0, 0, 0, 59,115, 0, 0, 0, 0, 0, 0, 0, - 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,115, 0, 0, - 0, 0, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, - 78, 0, 0, 0, 0, 0, 0, 0, 0, 61, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 56, 0, 89, 80, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 61, 0, 0, 79, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 8, 91, 0, 0, 0, 0, 0, 0, 1, 87, 0, 0, - 0, 0, 0, 0,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,117, - 0,118,119,120,121, 0,104, 4,122, 49, 23, 0, 0, 0, 0, 0, - 0, 0, 38, 50, 0, 0, 0, 0, 38, 58, 0, 0, 0, 0, 0, 0, - 1, 87, 1, 1, 1, 1, 39, 1, 48,105, 87, 0, 0, 0, 0, 0, - 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 59, 0, 0, 0, 0, - 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,123, 0, 0, 0, 0, - 0, 0, 0, 0, 4,122, 0, 0, 0, 1,124, 0, 0, 0, 0, 0, - 0, 0, 0, 0,230,230,230,230,230,232,220,220,220,220,232,216, - 220,220,220,220,220,202,202,220,220,220,220,202,202,220,220,220, - 1, 1, 1, 1, 1,220,220,220,220,230,230,230,230,240,230,220, - 220,220,230,230,230,220,220, 0,230,230,230,220,220,220,220,230, - 232,220,220,230,233,234,234,233,234,234,233,230, 0, 0, 0,230, - 0,220,230,230,230,230,220,230,230,230,222,220,230,230,220,220, - 230,222,228,230, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, - 21, 22, 0, 23, 0, 24, 25, 0,230,220, 0, 18, 30, 31, 32, 0, - 0, 0, 0, 27, 28, 29, 30, 31, 32, 33, 34,230,230,220,220,230, - 220,230,230,220, 35, 0, 0, 0, 0, 0,230,230,230, 0, 0,230, - 230, 0,220,230,230,220, 0, 0, 0, 36, 0, 0,230,220,230,230, - 220,220,230,220,220,230,220,230,220,230,230, 0, 0,220, 0, 0, - 230,230, 0,230, 0,230,230,230,230,230, 0, 0, 0,220,220,220, - 230,220,220,220,230,230, 0,220, 27, 28, 29,230, 7, 0, 0, 0, - 0, 9, 0, 0, 0,230,220,230,230, 0, 0, 0, 0, 0,230, 0, - 0, 84, 91, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 9, 0, - 103,103, 9, 0,107,107,107,107,118,118, 9, 0,122,122,122,122, - 220,220, 0, 0, 0,220, 0,220, 0,216, 0, 0, 0,129,130, 0, - 132, 0, 0, 0, 0, 0,130,130,130,130, 0, 0,130, 0,230,230, - 9, 0,230,230, 0, 0,220, 0, 0, 0, 0, 7, 0, 9, 9, 0, - 9, 9, 0, 0, 0,230, 0, 0, 0,228, 0, 0, 0,222,230,220, - 220, 0, 0, 0,230, 0, 0,220,230,220, 0,220,230,230,230, 0, - 0, 0, 9, 9, 0, 0, 7, 0,230, 0, 1, 1, 1, 0, 0, 0, - 230,234,214,220,202,230,230,230,230,230,232,228,228,220,218,230, - 233,220,230,220,230,230, 1, 1, 1, 1, 1,230, 0, 1, 1,230, - 220,230, 1, 1, 0, 0,218,228,232,222,224,224, 0, 8, 8, 0, - 0, 0, 0,220,230, 0,230,230,220, 0, 0,230, 0, 0, 26, 0, - 0,220, 0,230,230, 1,220, 0, 0,230,220, 0, 0, 0,220,220, - 0, 0,230,220, 0, 9, 7, 0, 0, 7, 9, 0, 0, 0, 9, 7, - 6, 6, 0, 0, 0, 0, 1, 0, 0,216,216, 1, 1, 1, 0, 0, - 0,226,216,216,216,216,216, 0,220,220,220, 0,232,232,220,230, - 230,230, 7, 0, 16, 17, 17, 17, 17, 17, 17, 33, 17, 17, 17, 19, - 17, 17, 17, 17, 20,101, 17,113,129,169, 17, 27, 28, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, + 0, 0, 3, 0, 0, 0, 4, 5, 6, 7, 0, 8, 9, 10, 0, 11, + 12, 13, 14, 15, 16, 17, 16, 18, 16, 19, 16, 19, 16, 19, 0, 19, + 16, 20, 16, 19, 21, 19, 0, 22, 23, 24, 25, 26, 27, 28, 29, 30, + 31, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, + 0, 0, 0, 0, 34, 0, 0, 35, 0, 0, 36, 0, 37, 0, 0, 0, + 38, 39, 40, 41, 42, 43, 44, 45, 46, 0, 0, 47, 0, 0, 0, 48, + 0, 0, 0, 49, 0, 0, 0, 0, 0, 0, 0, 50, 0, 51, 0, 52, + 53, 0, 54, 0, 0, 0, 0, 0, 0, 55, 56, 57, 0, 0, 0, 0, + 58, 0, 0, 59, 60, 61, 62, 63, 0, 0, 64, 65, 0, 0, 0, 66, + 0, 0, 0, 0, 67, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 69, 0, 0, 0, 70, 0, 71, 0, 0, + 72, 0, 0, 73, 0, 0, 0, 0, 0, 0, 0, 0, 74, 0, 0, 0, + 0, 0, 75, 76, 0, 77, 78, 0, 0, 79, 80, 0, 81, 62, 0, 82, + 83, 0, 0, 84, 85, 86, 0, 0, 0, 87, 0, 88, 0, 0, 51, 89, + 51, 0, 90, 0, 91, 0, 0, 0, 80, 0, 0, 0, 92, 93, 0, 94, + 95, 96, 97, 0, 0, 0, 0, 0, 51, 0, 0, 0, 0, 98, 99, 0, + 0, 0, 0, 0, 0,100, 0, 0, 0, 0, 0,101,102, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0,103, 0, 0,104, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0,105,106, 0, 0,107, 0, 0, 0, 0, 0, 0, + 108, 0,109, 0,102, 0, 0, 0, 0, 0,110,111, 0, 0, 0, 0, + 0, 0, 0,112, 0, 0, 0, 0, 0, 0, 0,113, 0,114, 0, 0, + 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 0, 8, 0, 0, 0, + 0, 9, 10, 11, 12, 0, 0, 0, 0, 13, 0, 0, 14, 15, 0, 16, + 0, 17, 18, 0, 0, 19, 0, 20, 21, 0, 0, 0, 0, 0, 22, 23, + 0, 24, 25, 0, 0, 26, 0, 0, 0, 27, 0, 0, 28, 29, 30, 31, + 0, 0, 0, 32, 33, 34, 0, 0, 33, 0, 0, 35, 33, 0, 0, 0, + 33, 36, 0, 0, 0, 0, 0, 37, 38, 0, 0, 0, 0, 0, 0, 39, + 40, 0, 0, 0, 0, 0, 0, 41, 42, 0, 0, 0, 0, 43, 0, 44, + 0, 0, 0, 45, 46, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 48, + 49, 0, 0, 0, 0, 50, 0, 0, 0, 51, 0, 52, 0, 53, 0, 0, + 0, 0, 54, 0, 0, 0, 0, 55, 0, 56, 0, 0, 0, 0, 57, 58, + 0, 0, 0, 59, 60, 0, 0, 0, 0, 0, 0, 61, 52, 0, 62, 63, + 0, 0, 64, 0, 0, 0, 65, 66, 0, 0, 0, 67, 0, 68, 69, 70, + 71, 72, 1, 73, 0, 74, 75, 76, 0, 0, 77, 78, 0, 0, 0, 79, + 0, 0, 1, 1, 0, 0, 80, 0, 0, 81, 0, 0, 0, 0, 77, 82, + 0, 83, 0, 0, 0, 0, 0, 78, 84, 0, 85, 0, 52, 0, 1, 78, + 0, 0, 86, 0, 0, 87, 0, 0, 0, 0, 0, 88, 57, 0, 0, 0, + 0, 0, 0, 89, 90, 0, 0, 84, 0, 0, 33, 0, 0, 91, 0, 0, + 0, 0, 92, 0, 0, 0, 0, 49, 0, 0, 93, 0, 0, 0, 0, 94, + 95, 0, 0, 96, 0, 0, 97, 0, 0, 0, 98, 0, 0, 0, 99, 0, + 0, 0, 0,100,101, 93, 0, 0,102, 0, 0, 0, 84, 0, 0,103, + 0, 0, 0,104,105, 0, 0,106,107, 0, 0, 0, 0, 0, 0,108, + 0, 0,109, 0, 0, 0, 0,110, 33, 0,111,112,113, 35, 0, 0, + 114, 0, 0, 0,115, 0, 0, 0, 0, 0, 0,116, 0, 0,117, 0, + 0, 0, 0,118, 88, 0, 0, 0, 0, 0, 57, 0, 0, 0, 0, 52, + 119, 0, 0, 0, 0,120, 0, 0,121, 0, 0, 0, 0,119, 0, 0, + 122, 0, 0, 0, 0, 0, 0,123, 0, 0, 0,124, 0, 0, 0,125, + 0,126, 0, 0, 0, 0,127,128,129, 0,130, 0,131, 0, 0, 0, + 132,133,134, 0, 77, 0, 0, 0, 0, 0, 35, 0, 0, 0,135, 0, + 0, 0,136, 0, 0,137, 0, 0,138, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 2, 3, 4, 5, 6, 7, 4, 4, 8, 9, 10, + 1, 11, 12, 13, 14, 15, 16, 17, 18, 1, 1, 1, 19, 1, 0, 0, + 20, 21, 22, 1, 23, 4, 21, 24, 25, 26, 27, 28, 29, 30, 0, 0, + 1, 1, 31, 0, 0, 0, 32, 33, 34, 35, 1, 36, 37, 0, 0, 0, + 0, 38, 1, 39, 14, 39, 40, 41, 42, 0, 0, 0, 43, 36, 44, 45, + 21, 45, 46, 0, 0, 0, 19, 1, 21, 0, 0, 47, 0, 38, 48, 1, + 1, 49, 49, 50, 0, 0, 51, 0, 0, 0, 52, 1, 0, 0, 38, 14, + 4, 1, 1, 1, 53, 21, 43, 52, 54, 21, 35, 1, 0, 0, 0, 55, + 0, 0, 0, 56, 57, 58, 0, 0, 0, 0, 0, 59, 0, 60, 0, 0, + 0, 0, 61, 62, 0, 0, 63, 0, 0, 0, 64, 0, 0, 0, 65, 0, + 0, 0, 66, 0, 0, 0, 67, 0, 0, 0, 68, 0, 0, 69, 70, 0, + 71, 72, 73, 74, 75, 76, 0, 0, 0, 77, 0, 0, 0, 78, 79, 0, + 0, 0, 0, 47, 0, 0, 0, 49, 0, 80, 0, 0, 0, 62, 0, 0, + 63, 0, 0, 81, 0, 0, 82, 0, 0, 0, 83, 0, 0, 19, 84, 0, + 62, 0, 0, 0, 0, 49, 1, 85, 1, 52, 15, 86, 36, 10, 21, 87, + 0, 55, 0, 0, 0, 0, 19, 10, 1, 0, 0, 0, 0, 0, 88, 0, + 0, 89, 0, 0, 88, 0, 0, 0, 0, 78, 0, 0, 87, 9, 12, 4, + 90, 8, 91, 47, 0, 58, 50, 0, 21, 1, 21, 92, 93, 1, 1, 1, + 1, 94, 95, 96, 97, 1, 98, 58, 81, 99,100, 4, 58, 0, 0, 0, + 0, 0, 0, 19, 50, 0, 0, 0, 0, 0, 0, 61, 0, 0,101,102, + 0, 0,103, 0, 0, 1, 1, 50, 0, 0, 0, 38, 0, 63, 0, 0, + 0, 0, 0, 62, 0, 0,104, 68, 61, 0, 0, 0, 78, 0, 0, 0, + 105,106, 58, 38, 81, 0, 0, 0, 0, 0, 0,107, 1, 14, 4, 12, + 84, 0, 0, 0, 0, 38, 87, 0, 0, 0, 0,108, 0, 0,109, 61, + 0,110, 0, 0, 0, 1, 0, 0, 0, 0, 19, 58, 0, 0, 0, 51, + 0,111, 14, 52,112, 41, 0, 0, 62, 0, 0, 61, 0, 0,113, 0, + 87, 0, 0, 0, 61, 62, 0, 0, 62, 0, 89, 0, 0,113, 0, 0, + 0, 0,114, 0, 0, 0, 78, 55, 0, 38, 1, 58, 1, 58, 0, 0, + 63, 89, 0, 0,115, 0, 0, 0, 55, 0, 0, 0, 0,115, 0, 0, + 0, 0, 61, 0, 0, 0, 0, 79, 0, 61, 0, 0, 0, 0, 56, 0, + 89, 80, 0, 0, 79, 0, 0, 0, 8, 91, 0, 0, 1, 87, 0, 0, + 116, 0, 0, 0, 0, 0, 0,117, 0,118,119,120,121, 0,104, 4, + 122, 49, 23, 0, 0, 0, 38, 50, 38, 58, 0, 0, 1, 87, 1, 1, + 1, 1, 39, 1, 48,105, 87, 0, 0, 0, 0, 1, 0, 0, 0,123, + 4,122, 0, 0, 0, 1,124, 0, 0, 0, 0, 0,230,230,230,230, + 230,232,220,220,220,220,232,216,220,220,220,220,220,202,202,220, + 220,220,220,202,202,220,220,220, 1, 1, 1, 1, 1,220,220,220, + 220,230,230,230,230,240,230,220,220,220,230,230,230,220,220, 0, + 230,230,230,220,220,220,220,230,232,220,220,230,233,234,234,233, + 234,234,233,230, 0, 0, 0,230, 0,220,230,230,230,230,220,230, + 230,230,222,220,230,230,220,220,230,222,228,230, 10, 11, 12, 13, + 14, 15, 16, 17, 18, 19, 19, 20, 21, 22, 0, 23, 0, 24, 25, 0, + 230,220, 0, 18, 30, 31, 32, 0, 0, 0, 0, 27, 28, 29, 30, 31, + 32, 33, 34,230,230,220,220,230,220,230,230,220, 35, 0, 0, 0, + 0, 0,230,230,230, 0, 0,230,230, 0,220,230,230,220, 0, 0, + 0, 36, 0, 0,230,220,230,230,220,220,230,220,220,230,220,230, + 220,230,230, 0, 0,220, 0, 0,230,230, 0,230, 0,230,230,230, + 230,230, 0, 0, 0,220,220,220,230,220,220,220,230,230, 0,220, + 27, 28, 29,230, 7, 0, 0, 0, 0, 9, 0, 0, 0,230,220,230, + 230, 0, 0, 0, 0, 0,230, 0, 0, 84, 91, 0, 0, 0, 0, 9, + 9, 0, 0, 0, 0, 0, 9, 0,103,103, 9, 0,107,107,107,107, + 118,118, 9, 0,122,122,122,122,220,220, 0, 0, 0,220, 0,220, + 0,216, 0, 0, 0,129,130, 0,132, 0, 0, 0, 0, 0,130,130, + 130,130, 0, 0,130, 0,230,230, 9, 0,230,230, 0, 0,220, 0, + 0, 0, 0, 7, 0, 9, 9, 0, 9, 9, 0, 0, 0,230, 0, 0, + 0,228, 0, 0, 0,222,230,220,220, 0, 0, 0,230, 0, 0,220, + 230,220, 0,220,230,230,230, 0, 0, 0, 9, 9, 0, 0, 7, 0, + 230, 0, 1, 1, 1, 0, 0, 0,230,234,214,220,202,230,230,230, + 230,230,232,228,228,220,218,230,233,220,230,220,230,230, 1, 1, + 1, 1, 1,230, 0, 1, 1,230,220,230, 1, 1, 0, 0,218,228, + 232,222,224,224, 0, 8, 8, 0, 0, 0, 0,220,230, 0,230,230, + 220, 0, 0,230, 0, 0, 26, 0, 0,220, 0,230,230, 1,220, 0, + 0,230,220, 0, 0, 0,220,220, 0, 0,230,220, 0, 9, 7, 0, + 0, 7, 9, 0, 0, 0, 9, 7, 6, 6, 0, 0, 0, 0, 1, 0, + 0,216,216, 1, 1, 1, 0, 0, 0,226,216,216,216,216,216, 0, + 220,220,220, 0,232,232,220,230,230,230, 7, 0, 16, 17, 17, 17, + 17, 17, 17, 33, 17, 17, 17, 19, 17, 17, 17, 17, 20,101, 17,113, + 129,169, 17, 27, 28, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17,237, 0, 1, 2, 2, 0, 3, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 5, 0, 0, 0, 0, 6, 7, 8, 9, 0, 0, 0, 10, 11, 12, 13, - 14, 15, 16, 17, 18, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, - 0, 0, 21, 22, 0, 0, 0, 0, 23, 24, 25, 26, 0, 27, 0, 28, - 29, 30, 31, 32, 0, 0, 0, 0, 0, 0, 0, 33, 34, 35, 36, 0, - 0, 0, 0, 0, 37, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38, 39, - 0, 0, 0, 0, 1, 2, 40, 41, 0, 1, 2, 2, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0, - 0, 0, 3, 4, 0, 0, 5, 0, 0, 0, 6, 0, 0, 0, 0, 0, - 0, 0, 7, 1, 0, 0, 0, 0, 0, 0, 8, 9, 0, 0, 0, 0, - 0, 0, 10, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 11, 12, - 0, 13, 0, 14, 15, 16, 0, 0, 0, 0, 0, 1, 17, 18, 0, 19, - 7, 1, 0, 0, 0, 20, 20, 7, 20, 20, 20, 20, 20, 20, 20, 8, - 21, 0, 22, 0, 7, 23, 24, 0, 20, 20, 25, 0, 0, 0, 26, 27, - 1, 7, 20, 20, 20, 20, 20, 1, 28, 29, 30, 31, 0, 0, 20, 0, - 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 20, 20, - 20, 1, 0, 0, 8, 21, 32, 4, 0, 10, 0, 33, 7, 20, 20, 20, - 0, 0, 0, 0, 8, 34, 34, 35, 36, 34, 37, 0, 38, 1, 20, 20, - 0, 0, 39, 0, 1, 1, 0, 8, 21, 1, 20, 0, 0, 0, 1, 0, - 0, 40, 1, 1, 0, 0, 8, 21, 0, 1, 0, 1, 0, 1, 0, 0, - 0, 0, 26, 34, 34, 34, 34, 34, 34, 34, 34, 34, 21, 7, 20, 41, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 21, 0, 42, 43, 44, 0, 45, - 0, 8, 21, 0, 0, 0, 0, 0, 0, 0, 0, 46, 7, 1, 10, 1, - 0, 0, 0, 1, 20, 20, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 26, 34, 9, 0, 0, 20, 20, 1, 20, 20, 0, 0, 0, 0, 0, - 0, 0, 26, 21, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 3, 47, 48, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, - 4, 5, 6, 7, 7, 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 9, 10, 11, 11, 11, 11, 12, 13, 13, 13, 13, 14, 15, 16, 17, 18, - 19, 20, 21, 13, 22, 13, 13, 13, 13, 23, 24, 24, 25, 26, 13, 13, - 13, 27, 28, 29, 13, 30, 31, 32, 33, 34, 35, 36, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 37, 7, 38, 39, 7, 40, 7, 7, 7, 41, 13, 42, 7, 7, 43, 7, - 44, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,237, 0, 1, 2, 2, + 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 6, 7, 8, + 9, 0, 0, 0, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 21, 22, 0, 0, 0, 0, + 23, 24, 25, 26, 0, 27, 0, 28, 29, 30, 31, 32, 0, 0, 0, 0, + 0, 0, 0, 33, 34, 35, 36, 0, 0, 0, 0, 0, 37, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 38, 39, 0, 0, 0, 0, 1, 2, 40, 41, + 0, 1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 3, 4, 0, 0, 5, 0, + 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 7, 1, 0, 0, 0, 0, + 0, 0, 8, 9, 0, 0, 0, 0, 0, 0, 10, 0, 0, 10, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 10, + 0, 0, 0, 0, 0, 0, 11, 12, 0, 13, 0, 14, 15, 16, 0, 0, + 0, 0, 0, 1, 17, 18, 0, 19, 7, 1, 0, 0, 0, 20, 20, 7, + 20, 20, 20, 20, 20, 20, 20, 8, 21, 0, 22, 0, 7, 23, 24, 0, + 20, 20, 25, 0, 0, 0, 26, 27, 1, 7, 20, 20, 20, 20, 20, 1, + 28, 29, 30, 31, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 10, 0, + 0, 0, 0, 0, 0, 0, 20, 20, 20, 1, 0, 0, 8, 21, 32, 4, + 0, 10, 0, 33, 7, 20, 20, 20, 0, 0, 0, 0, 8, 34, 34, 35, + 36, 34, 37, 0, 38, 1, 20, 20, 0, 0, 39, 0, 1, 1, 0, 8, + 21, 1, 20, 0, 0, 0, 1, 0, 0, 40, 1, 1, 0, 0, 8, 21, + 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 26, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 21, 7, 20, 41, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 21, 0, 42, 43, 44, 0, 45, 0, 8, 21, 0, 0, 0, 0, 0, + 0, 0, 0, 46, 7, 1, 10, 1, 0, 0, 0, 1, 20, 20, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 34, 9, 0, 0, 20, 20, + 1, 20, 20, 0, 0, 0, 0, 0, 0, 0, 26, 21, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 47, 48, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 7, 8, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 9, 10, 11, 11, 11, 11, 12, 13, + 13, 13, 13, 14, 15, 16, 17, 18, 19, 20, 21, 13, 22, 13, 13, 13, + 13, 23, 24, 24, 25, 26, 13, 13, 13, 27, 28, 29, 13, 30, 31, 32, + 33, 34, 35, 36, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 37, 7, 38, 39, 7, 40, 7, 7, + 7, 41, 13, 42, 7, 7, 43, 7, 44, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, @@ -1740,420 +1715,420 @@ _hb_ucd_u8[18260] = 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 45, 0, 0, 1, - 2, 2, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 32, 33, 34, 35, 36, 37, 37, 37, 37, 37, 38, 39, 40, 41, 42, - 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 2, 2, 53, 54, 55, 56, - 57, 58, 59, 59, 59, 59, 60, 59, 59, 59, 59, 59, 59, 59, 61, 61, - 59, 59, 59, 59, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, - 74, 75, 76, 77, 78, 59, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 45, 0, 0, 1, 2, 2, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, 32, 32, 33, 34, 35, 36, 37, 37, + 37, 37, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 2, 2, 53, 54, 55, 56, 57, 58, 59, 59, 59, 59, 60, 59, + 59, 59, 59, 59, 59, 59, 61, 61, 59, 59, 59, 59, 62, 63, 64, 65, + 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 59, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, - 70, 70, 70, 70, 70, 70, 70, 70, 70, 79, 70, 70, 70, 70, 80, 80, - 80, 80, 80, 80, 80, 80, 80, 81, 82, 82, 83, 84, 85, 86, 87, 88, - 89, 90, 91, 92, 93, 94, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 79, 70, 70, 70, 70, 80, 80, 80, 80, 80, 80, 80, 80, 80, 81, + 82, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 95, 96, 96, - 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, - 70, 70, 97, 98, 99,100,101,101,102,103,104,105,106,107,108,109, - 110,111, 96,112,113,114,115,116,117,118,119,119,120,121,122,123, - 124,125,126,127,128,129,130,131,132, 96,133,134,135,136,137,138, - 139,140,141,142,143, 96,144,145, 96,146,147,148,149, 96,150,151, - 152,153,154,155,156, 96,157,158,159,160, 96,161,162,163,164,164, - 164,164,164,164,164,165,166,164,167, 96, 96, 96, 96, 96, 96, 96, - 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,168,169,169, - 169,169,169,169,169,169,170, 96, 96, 96, 96, 96, 96, 96, 96, 96, - 96, 96, 96, 96, 96, 96,171,171,171,171,172, 96, 96, 96,173,173, - 173,173,174,175,176,177, 96, 96, 96, 96,178,179,180,181,182,182, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 95, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, + 96, 96, 96, 96, 96, 96, 96, 96, 70, 70, 97, 98, 99,100,101,101, + 102,103,104,105,106,107,108,109,110,111, 96,112,113,114,115,116, + 117,118,119,119,120,121,122,123,124,125,126,127,128,129,130,131, + 132, 96,133,134,135,136,137,138,139,140,141,142,143, 96,144,145, + 96,146,147,148,149, 96,150,151,152,153,154,155,156, 96,157,158, + 159,160, 96,161,162,163,164,164,164,164,164,164,164,165,166,164, + 167, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, + 96, 96, 96, 96, 96,168,169,169,169,169,169,169,169,169,170, 96, + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,171,171, + 171,171,172, 96, 96, 96,173,173,173,173,174,175,176,177, 96, 96, + 96, 96,178,179,180,181,182,182,182,182,182,182,182,182,182,182, 182,182,182,182,182,182,182,182,182,182,182,182,182,182,182,182, - 182,182,182,182,182,182,182,182,182,182,182,182,182,183,182,182, - 182,182,182,182,184,184,184,185,186, 96, 96, 96, 96, 96, 96, 96, - 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,187,188,189, - 190,191,191,192, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, - 96, 96, 96, 96, 96, 96,193,194, 96, 96, 96, 96, 96, 96, 96, 96, - 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,195,196, 59,197, - 198,199,200,201,202, 96,203,204,205, 59, 59,206, 59,207,208,208, - 208,208,208,209, 96, 96, 96, 96, 96, 96, 96, 96,210, 96,211,212, - 213, 96, 96,214, 96, 96, 96,215, 96, 96, 96, 96, 96,216,217,218, - 219, 96, 96, 96, 96, 96,220,221,222, 96,223,224, 96, 96,225,226, - 59,227,228, 96, 59, 59, 59, 59, 59, 59, 59,229,230,231,232,233, - 59, 59,234,235, 59,236, 96, 96, 96, 96, 96, 96, 96, 96, 70, 70, - 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,237, 70, 70, 70, 70, - 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,238, 70,239, 70, + 182,182,182,182,182,183,182,182,182,182,182,182,184,184,184,185, + 186, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, + 96, 96, 96, 96, 96,187,188,189,190,191,191,192, 96, 96, 96, 96, + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,193,194, + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, + 96, 96, 96, 96,195,196, 59,197,198,199,200,201,202, 96,203,204, + 205, 59, 59,206, 59,207,208,208,208,208,208,209, 96, 96, 96, 96, + 96, 96, 96, 96,210, 96,211,212,213, 96, 96,214, 96, 96, 96,215, + 96, 96, 96, 96, 96,216,217,218,219, 96, 96, 96, 96, 96,220,221, + 222, 96,223,224, 96, 96,225,226, 59,227,228, 96, 59, 59, 59, 59, + 59, 59, 59,229,230,231,232,233, 59, 59,234,235, 59,236, 96, 96, + 96, 96, 96, 96, 96, 96, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70,237, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70,238, 70,239, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, - 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,240, 70, 70, 70, 70, - 70, 70, 70, 70, 70,241, 96, 96, 96, 96, 96, 96, 96, 96, 70, 70, - 70, 70,242, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 70, 70, - 70, 70, 70, 70,243, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, - 70, 70, 70, 70, 70,244, 96, 96, 96, 96, 96, 96, 96, 96,245, 96, - 246,247, 0, 1, 2, 2, 0, 1, 2, 2, 2, 3, 4, 5, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 0, 0, 0, 0, 0, 0, 0, - 19, 0, 0, 0, 0, 0, 19, 19, 19, 19, 19, 19, 19, 0, 19, 0, - 0, 0, 0, 0, 0, 0, 19, 19, 19, 19, 19, 0, 0, 0, 0, 0, - 26, 26, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, - 9, 9, 0, 9, 9, 9, 2, 2, 9, 9, 9, 9, 0, 9, 2, 2, - 2, 2, 9, 0, 9, 0, 9, 9, 9, 2, 9, 2, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 2, 9, 9, 9, 9, 9, 9, 9, - 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 1, 1, 6, 2, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 2, 4, 4, 4, 2, 2, 4, 4, 4, 2, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 2, 2, - 2, 2, 2, 2, 2, 2, 14, 14, 14, 2, 2, 2, 2, 14, 14, 14, - 14, 14, 14, 2, 2, 2, 3, 3, 3, 3, 3, 0, 3, 3, 3, 3, - 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 0, 3, 3, 3, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 1, 3, - 3, 3, 3, 3, 3, 3, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, - 37, 37, 37, 37, 2, 37, 37, 37, 37, 2, 2, 37, 37, 37, 38, 38, - 38, 38, 38, 38, 38, 38, 38, 38, 2, 2, 2, 2, 2, 2, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, 64, 2, 2, 64, 64, 64, 90, 90, - 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 2, 2, 90, 90, - 90, 90, 90, 90, 90, 2, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, - 95, 95, 2, 2, 95, 2, 37, 37, 37, 2, 2, 2, 2, 2, 3, 3, - 3, 3, 3, 3, 3, 2, 3, 3, 2, 2, 2, 2, 2, 2, 3, 3, - 0, 3, 3, 3, 3, 3, 7, 7, 7, 7, 7, 7, 7, 7, 7, 1, - 1, 1, 1, 7, 7, 7, 7, 7, 7, 7, 0, 0, 7, 7, 5, 5, - 5, 5, 2, 5, 5, 5, 5, 5, 5, 5, 5, 2, 2, 5, 5, 2, - 2, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2, - 5, 5, 5, 5, 5, 5, 5, 2, 5, 2, 2, 2, 5, 5, 5, 5, - 2, 2, 5, 5, 5, 5, 5, 2, 2, 5, 5, 5, 5, 2, 2, 2, - 2, 2, 2, 2, 2, 5, 2, 2, 2, 2, 5, 5, 2, 5, 5, 5, - 5, 5, 2, 2, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2, 2, 11, - 11, 11, 2, 11, 11, 11, 11, 11, 11, 2, 2, 2, 2, 11, 11, 2, - 2, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 2, - 11, 11, 11, 11, 11, 11, 11, 2, 11, 11, 2, 11, 11, 2, 11, 11, - 2, 2, 11, 2, 11, 11, 11, 2, 2, 11, 11, 11, 2, 2, 2, 11, - 2, 2, 2, 2, 2, 2, 2, 11, 11, 11, 11, 2, 11, 2, 2, 2, - 2, 2, 2, 2, 11, 11, 11, 11, 11, 11, 11, 11, 11, 2, 2, 10, - 10, 10, 2, 10, 10, 10, 10, 10, 10, 10, 10, 10, 2, 10, 10, 10, - 2, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 2, - 10, 10, 10, 10, 10, 10, 10, 2, 10, 10, 2, 10, 10, 10, 10, 10, - 2, 2, 10, 10, 10, 10, 10, 10, 2, 10, 10, 10, 2, 2, 10, 2, - 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 2, 2, 10, 10, 10, 10, - 2, 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 10, 10, 10, 2, 21, - 21, 21, 2, 21, 21, 21, 21, 21, 21, 21, 21, 2, 2, 21, 21, 2, - 2, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 2, - 21, 21, 21, 21, 21, 21, 21, 2, 21, 21, 2, 21, 21, 21, 21, 21, - 2, 2, 21, 21, 21, 21, 21, 2, 2, 21, 21, 21, 2, 2, 2, 2, - 2, 2, 2, 21, 21, 21, 2, 2, 2, 2, 21, 21, 2, 21, 21, 21, - 21, 21, 2, 2, 21, 21, 2, 2, 22, 22, 2, 22, 22, 22, 22, 22, - 22, 2, 2, 2, 22, 22, 22, 2, 22, 22, 22, 22, 2, 2, 2, 22, - 22, 2, 22, 2, 22, 22, 2, 2, 2, 22, 22, 2, 2, 2, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, 2, 2, 2, 2, 22, 22, 22, 2, - 2, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 22, 22, 22, 22, - 22, 2, 2, 2, 2, 2, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, - 23, 23, 23, 2, 23, 23, 23, 2, 23, 23, 23, 23, 23, 23, 23, 23, - 2, 2, 23, 23, 23, 23, 23, 2, 23, 23, 23, 23, 2, 2, 2, 2, - 2, 2, 2, 23, 23, 2, 23, 23, 23, 2, 2, 23, 2, 2, 23, 23, - 23, 23, 2, 2, 23, 23, 2, 2, 2, 2, 2, 2, 2, 23, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 2, 16, 16, 16, 2, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 2, 16, 16, 16, 16, 16, - 2, 2, 16, 16, 16, 16, 16, 2, 16, 16, 16, 16, 2, 2, 2, 2, - 2, 2, 2, 16, 16, 2, 16, 16, 16, 16, 2, 2, 16, 16, 2, 16, - 16, 16, 2, 2, 2, 2, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, - 20, 20, 20, 2, 20, 20, 20, 2, 20, 20, 20, 20, 20, 20, 2, 2, - 2, 2, 20, 20, 20, 20, 20, 20, 20, 20, 2, 2, 20, 20, 2, 36, - 36, 36, 2, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, - 36, 36, 36, 36, 36, 2, 2, 2, 36, 36, 36, 36, 36, 36, 36, 36, - 2, 36, 36, 36, 36, 36, 36, 36, 36, 36, 2, 36, 2, 2, 2, 2, - 36, 2, 2, 2, 2, 36, 36, 36, 36, 36, 36, 2, 36, 2, 2, 2, - 2, 2, 2, 2, 36, 36, 2, 2, 36, 36, 36, 2, 2, 2, 2, 24, - 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, - 24, 2, 2, 2, 2, 0, 24, 24, 24, 24, 2, 2, 2, 2, 2, 18, - 18, 2, 18, 2, 18, 18, 18, 18, 18, 2, 18, 18, 18, 18, 18, 18, - 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 2, 18, 2, 18, 18, 18, - 18, 18, 18, 18, 2, 2, 18, 18, 18, 18, 18, 2, 18, 2, 18, 18, - 18, 18, 18, 18, 18, 2, 18, 18, 2, 2, 18, 18, 18, 18, 25, 25, - 25, 25, 25, 25, 25, 25, 2, 25, 25, 25, 25, 25, 25, 25, 25, 25, - 25, 25, 25, 2, 2, 2, 25, 25, 25, 25, 25, 2, 25, 25, 25, 25, - 25, 25, 25, 0, 0, 0, 0, 25, 25, 2, 2, 2, 2, 2, 33, 33, - 33, 33, 33, 33, 33, 33, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 2, 8, 2, 2, 2, 2, 2, 8, 2, 2, 8, 8, - 8, 0, 8, 8, 8, 8, 12, 12, 12, 12, 12, 12, 12, 12, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 2, 30, 30, 30, 30, 2, 2, 30, 30, - 30, 30, 30, 30, 30, 2, 30, 30, 30, 2, 2, 30, 30, 30, 30, 30, - 30, 30, 30, 2, 2, 2, 30, 30, 2, 2, 2, 2, 2, 2, 29, 29, - 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 2, 2, 28, 28, - 28, 28, 28, 28, 28, 28, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 2, 2, 2, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, - 35, 0, 0, 0, 35, 35, 35, 2, 2, 2, 2, 2, 2, 2, 45, 45, - 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 45, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, - 44, 44, 44, 0, 0, 2, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, - 43, 43, 2, 2, 2, 2, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, - 46, 46, 46, 2, 46, 46, 46, 2, 46, 46, 2, 2, 2, 2, 31, 31, - 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 2, 2, 31, 31, - 2, 2, 2, 2, 2, 2, 32, 32, 0, 0, 32, 0, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 2, 2, 2, 2, 2, 2, 32, 2, - 2, 2, 2, 2, 2, 2, 32, 32, 32, 2, 2, 2, 2, 2, 28, 28, - 28, 28, 28, 28, 2, 2, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 2, 48, 48, 48, 48, 2, 2, 2, 2, 48, 2, - 2, 2, 48, 48, 48, 48, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, - 52, 52, 52, 52, 2, 2, 52, 52, 52, 52, 52, 2, 2, 2, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 2, 2, 2, 2, 58, 58, - 2, 2, 2, 2, 2, 2, 58, 58, 58, 2, 2, 2, 58, 58, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 2, 2, 54, 54, 91, 91, - 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 2, 91, 91, - 91, 91, 91, 2, 2, 91, 91, 91, 2, 2, 2, 2, 2, 2, 91, 91, - 91, 91, 91, 91, 2, 2, 1, 1, 1, 1, 1, 1, 1, 2, 62, 62, - 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 2, 2, 2, 62, 62, - 62, 62, 62, 62, 62, 2, 76, 76, 76, 76, 76, 76, 76, 76, 93, 93, - 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 2, 2, 2, 2, 2, 2, - 2, 2, 93, 93, 93, 93, 70, 70, 70, 70, 70, 70, 70, 70, 2, 2, - 2, 70, 70, 70, 70, 70, 70, 70, 2, 2, 2, 70, 70, 70, 73, 73, - 73, 73, 73, 73, 73, 73, 6, 2, 2, 2, 2, 2, 2, 2, 8, 8, - 8, 2, 2, 8, 8, 8, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, - 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, - 0, 0, 1, 0, 0, 0, 1, 1, 0, 2, 2, 2, 2, 2, 19, 19, - 19, 19, 19, 19, 9, 9, 9, 9, 9, 6, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 9, 9, 9, 9, 9, 19, 19, 19, 19, 9, 9, 9, 9, - 9, 19, 19, 19, 19, 19, 6, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 9, 9, 9, 9, 9, 9, 9, 2, 2, 2, 9, - 2, 9, 2, 9, 2, 9, 9, 9, 9, 9, 9, 2, 9, 9, 9, 9, - 9, 9, 2, 2, 9, 9, 9, 9, 9, 9, 2, 9, 9, 9, 2, 2, - 9, 9, 9, 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 2, 0, 0, - 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 19, - 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, - 0, 0, 0, 0, 0, 2, 19, 19, 19, 19, 19, 2, 2, 2, 0, 2, - 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 0, 0, - 0, 0, 0, 0, 9, 0, 0, 0, 19, 19, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 19, 0, 19, 0, 0, 0, 2, 2, 2, 2, 0, 0, - 0, 2, 2, 2, 2, 2, 27, 27, 27, 27, 27, 27, 27, 27, 0, 0, - 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 56, 56, - 56, 56, 56, 56, 56, 56, 55, 55, 55, 55, 2, 2, 2, 2, 2, 55, - 55, 55, 55, 55, 55, 55, 61, 61, 61, 61, 61, 61, 61, 61, 2, 2, - 2, 2, 2, 2, 2, 61, 61, 2, 2, 2, 2, 2, 2, 2, 0, 0, - 0, 0, 0, 0, 2, 2, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 2, 13, 13, 13, 13, 13, 13, 13, 13, 13, 2, 2, 2, 2, 13, 13, - 13, 13, 13, 13, 2, 2, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, - 0, 0, 0, 13, 0, 13, 0, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 1, 1, 1, 1, 12, 12, 13, 13, 13, 13, 0, 0, 0, 0, 2, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 2, 2, 1, 1, 0, 0, 15, 15, 15, 0, 17, - 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, - 17, 0, 0, 17, 17, 17, 2, 2, 2, 2, 2, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 2, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 2, 12, 12, 12, 12, 12, 12, 12, 0, 17, 17, - 17, 17, 17, 17, 17, 0, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, - 39, 39, 39, 2, 2, 2, 39, 39, 39, 39, 39, 39, 39, 2, 86, 86, - 86, 86, 86, 86, 86, 86, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 2, 2, 2, 2, 79, 79, 79, 79, 79, 79, 79, 79, 0, 0, - 19, 19, 19, 19, 19, 19, 0, 0, 0, 19, 19, 19, 19, 19, 19, 19, - 19, 2, 2, 2, 2, 2, 19, 19, 2, 19, 2, 19, 19, 19, 19, 19, - 2, 2, 2, 2, 2, 2, 2, 2, 19, 19, 19, 19, 19, 19, 60, 60, - 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 2, 2, 2, 0, 0, - 2, 2, 2, 2, 2, 2, 65, 65, 65, 65, 65, 65, 65, 65, 75, 75, - 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 2, 2, 2, 2, - 2, 2, 2, 2, 75, 75, 75, 75, 2, 2, 2, 2, 2, 2, 69, 69, - 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 0, 69, 74, 74, - 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 74, 12, 12, 12, 12, 12, 2, 2, 2, 84, 84, - 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 2, 0, 84, 84, - 2, 2, 2, 2, 84, 84, 33, 33, 33, 33, 33, 33, 33, 2, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 2, 68, 68, - 68, 68, 68, 68, 2, 2, 68, 68, 2, 2, 68, 68, 68, 68, 92, 92, - 92, 92, 92, 92, 92, 92, 92, 92, 92, 2, 2, 2, 2, 2, 2, 2, - 2, 92, 92, 92, 92, 92, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 2, 2, 30, 30, 30, 30, 30, 30, 2, 19, 19, - 19, 0, 19, 19, 19, 19, 19, 19, 19, 19, 19, 9, 19, 19, 19, 19, - 0, 0, 2, 2, 2, 2, 87, 87, 87, 87, 87, 87, 2, 2, 87, 87, - 2, 2, 2, 2, 2, 2, 12, 12, 12, 12, 2, 2, 2, 2, 2, 2, - 2, 12, 12, 12, 12, 12, 13, 13, 2, 2, 2, 2, 2, 2, 19, 19, - 19, 19, 19, 19, 19, 2, 2, 2, 2, 4, 4, 4, 4, 4, 2, 2, - 2, 2, 2, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 2, 14, 14, - 14, 14, 14, 2, 14, 2, 14, 14, 2, 14, 14, 2, 14, 14, 3, 3, - 3, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 0, 0, 2, 2, 3, 3, 3, 3, 3, 3, 2, 2, - 2, 2, 2, 2, 2, 3, 1, 1, 1, 1, 1, 1, 6, 6, 0, 0, - 0, 2, 0, 0, 0, 0, 3, 3, 3, 3, 3, 2, 3, 3, 3, 3, - 3, 3, 3, 2, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 2, 2, - 12, 12, 12, 12, 12, 12, 2, 2, 12, 12, 12, 2, 2, 2, 2, 0, - 0, 0, 0, 0, 2, 2, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 2, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 2, 49, 49, - 49, 2, 49, 49, 2, 49, 49, 49, 49, 49, 49, 49, 2, 2, 49, 49, - 49, 2, 2, 2, 2, 2, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, - 0, 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 2, 2, 2, 9, 2, - 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 1, 2, 2, 71, 71, - 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 2, 2, 2, 67, 67, - 67, 67, 67, 67, 67, 67, 67, 2, 2, 2, 2, 2, 2, 2, 1, 0, - 0, 0, 0, 0, 0, 0, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, - 42, 42, 2, 2, 2, 2, 2, 2, 2, 2, 2, 42, 42, 42, 41, 41, - 41, 41, 41, 41, 41, 41, 41, 41, 41, 2, 2, 2, 2, 2,118,118, - 118,118,118,118,118,118,118,118,118, 2, 2, 2, 2, 2, 53, 53, - 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 2, 53, 59, 59, - 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 2, 2, 2, 2, 59, 59, - 59, 59, 59, 59, 2, 2, 40, 40, 40, 40, 40, 40, 40, 40, 51, 51, - 51, 51, 51, 51, 51, 51, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 2, 2, 50, 50, 2, 2, 2, 2, 2, 2,135,135, - 135,135,135,135,135,135,135,135,135,135, 2, 2, 2, 2,106,106, - 106,106,106,106,106,106,104,104,104,104,104,104,104,104,104,104, - 104,104, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,104,161,161, - 161,161,161,161,161,161,161,161,161, 2,161,161,161,161,161,161, - 161, 2,161,161, 2,161,161,161, 2,161,161,161,161,161,161,161, - 2,161,161, 2, 2, 2,110,110,110,110,110,110,110,110,110,110, - 110,110,110,110,110, 2,110,110,110,110,110,110, 2, 2, 19, 19, - 19, 19, 19, 19, 2, 19, 19, 2, 19, 19, 19, 19, 19, 19, 47, 47, - 47, 47, 47, 47, 2, 2, 47, 2, 47, 47, 47, 47, 47, 47, 47, 47, - 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 2, 47, 47, 2, - 2, 2, 47, 2, 2, 47, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, - 81, 81, 81, 81, 2, 81,120,120,120,120,120,120,120,120,116,116, - 116,116,116,116,116,116,116,116,116,116,116,116,116, 2, 2, 2, - 2, 2, 2, 2, 2,116,128,128,128,128,128,128,128,128,128,128, - 128, 2,128,128, 2, 2, 2, 2, 2,128,128,128,128,128, 66, 66, - 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 2, 2, 2, 66, 72, 72, - 72, 72, 72, 72, 72, 72, 72, 72, 2, 2, 2, 2, 2, 72, 98, 98, - 98, 98, 98, 98, 98, 98, 97, 97, 97, 97, 97, 97, 97, 97, 2, 2, - 2, 2, 97, 97, 97, 97, 2, 2, 97, 97, 97, 97, 97, 97, 57, 57, - 57, 57, 2, 57, 57, 2, 2, 2, 2, 2, 57, 57, 57, 57, 57, 57, - 57, 57, 2, 57, 57, 57, 2, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 2, 2, 57, 57, - 57, 2, 2, 2, 2, 57, 57, 2, 2, 2, 2, 2, 2, 2, 88, 88, - 88, 88, 88, 88, 88, 88,117,117,117,117,117,117,117,117,112,112, - 112,112,112,112,112,112,112,112,112,112,112,112,112, 2, 2, 2, - 2,112,112,112,112,112, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, - 78, 78, 78, 78, 2, 2, 2, 78, 78, 78, 78, 78, 78, 78, 83, 83, - 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 2, 2, 82, 82, - 82, 82, 82, 82, 82, 82, 82, 82, 82, 2, 2, 2, 2, 2,122,122, - 122,122,122,122,122,122,122,122, 2, 2, 2, 2, 2, 2, 2,122, - 122,122,122, 2, 2, 2, 2,122,122,122,122,122,122,122, 89, 89, - 89, 89, 89, 89, 89, 89, 89, 2, 2, 2, 2, 2, 2, 2,130,130, - 130,130,130,130,130,130,130,130,130, 2, 2, 2, 2, 2, 2, 2, - 130,130,130,130,130,130,144,144,144,144,144,144,144,144,144,144, - 2, 2, 2, 2, 2, 2,156,156,156,156,156,156,156,156,156,156, - 2,156,156,156, 2, 2,156,156, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 3, 3, 3,147,147,147,147,147,147,147,147,148,148, - 148,148,148,148,148,148,148,148, 2, 2, 2, 2, 2, 2,158,158, - 158,158,158,158,158,158,158,158, 2, 2, 2, 2, 2, 2,153,153, - 153,153,153,153,153,153,153,153,153,153, 2, 2, 2, 2,149,149, - 149,149,149,149,149,149,149,149,149,149,149,149,149, 2, 94, 94, - 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 2, 2, 2, 2, - 94, 94, 94, 94, 94, 94, 2, 2, 2, 2, 2, 2, 2, 94, 85, 85, - 85, 85, 85, 85, 85, 85, 85, 85, 85, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 85, 2, 2,101,101,101,101,101,101,101,101,101, 2, - 2, 2, 2, 2, 2, 2,101,101, 2, 2, 2, 2, 2, 2, 96, 96, - 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 2, 96, 96,111,111, - 111,111,111,111,111,111,111,111,111,111,111,111,111, 2,100,100, - 100,100,100,100,100,100, 2, 36, 36, 36, 36, 36, 36, 36, 36, 36, - 36, 36, 36, 2, 2, 2,108,108,108,108,108,108,108,108,108,108, - 2,108,108,108,108,108,108,108, 2, 2, 2, 2, 2, 2,129,129, - 129,129,129,129,129, 2,129, 2,129,129,129,129, 2,129,129,129, - 129,129,129,129,129,129,129,129,129,129,129,129, 2,129,129,129, - 2, 2, 2, 2, 2, 2,109,109,109,109,109,109,109,109,109,109, - 109, 2, 2, 2, 2, 2,109,109, 2, 2, 2, 2, 2, 2,107,107, - 107,107, 2,107,107,107,107,107,107,107,107, 2, 2,107,107, 2, - 2,107,107,107,107,107,107,107,107,107,107,107,107,107,107, 2, - 107,107,107,107,107,107,107, 2,107,107, 2,107,107,107,107,107, - 2, 1,107,107,107,107,107, 2, 2,107,107,107, 2, 2,107, 2, - 2, 2, 2, 2, 2,107, 2, 2, 2, 2, 2,107,107,107,107,107, - 107,107, 2, 2,107,107,107,107,107,107,107, 2, 2, 2,137,137, - 137,137,137,137,137,137,137,137,137,137, 2,137,137,137,137,137, - 2, 2, 2, 2, 2, 2,124,124,124,124,124,124,124,124,124,124, - 2, 2, 2, 2, 2, 2,123,123,123,123,123,123,123,123,123,123, - 123,123,123,123, 2, 2,114,114,114,114,114,114,114,114,114,114, - 114,114,114, 2, 2, 2,114,114, 2, 2, 2, 2, 2, 2, 32, 32, - 32, 32, 32, 2, 2, 2,102,102,102,102,102,102,102,102,102,102, - 2, 2, 2, 2, 2, 2,126,126,126,126,126,126,126,126,126,126, - 126, 2, 2,126,126,126,126,126,126,126, 2, 2, 2, 2,126,126, - 126,126,126,126,126, 2,142,142,142,142,142,142,142,142,142,142, - 142,142, 2, 2, 2, 2,125,125,125,125,125,125,125,125,125,125, - 125, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,125,154,154, - 154,154,154,154,154, 2, 2,154, 2, 2,154,154,154,154,154,154, - 154,154, 2,154,154, 2,154,154,154,154,154,154,154,154,154,154, - 154,154,154,154, 2,154,154, 2, 2,154,154,154,154,154,154,154, - 2, 2, 2, 2, 2, 2,150,150,150,150,150,150,150,150, 2, 2, - 150,150,150,150,150,150,150,150,150,150,150, 2, 2, 2,141,141, - 141,141,141,141,141,141,140,140,140,140,140,140,140,140,140,140, - 140, 2, 2, 2, 2, 2,121,121,121,121,121,121,121,121,121, 2, - 2, 2, 2, 2, 2, 2, 7, 7, 2, 2, 2, 2, 2, 2,133,133, - 133,133,133,133,133,133,133, 2,133,133,133,133,133,133,133,133, - 133,133,133,133,133, 2,133,133,133,133,133,133, 2, 2,133,133, - 133,133,133, 2, 2, 2,134,134,134,134,134,134,134,134, 2, 2, - 134,134,134,134,134,134, 2,134,134,134,134,134,134,134,134,134, - 134,134,134,134,134, 2,138,138,138,138,138,138,138, 2,138,138, - 2,138,138,138,138,138,138,138,138,138,138,138,138,138, 2, 2, - 138, 2,138,138, 2,138,138,138, 2, 2, 2, 2, 2, 2,143,143, - 143,143,143,143, 2,143,143, 2,143,143,143,143,143,143,143,143, - 143,143,143,143,143,143,143,143,143,143,143,143,143, 2,143,143, - 2,143,143,143,143,143,143, 2, 2, 2, 2, 2, 2, 2,143,143, - 2, 2, 2, 2, 2, 2,145,145,145,145,145,145,145,145,145, 2, - 2, 2, 2, 2, 2, 2,163,163,163,163,163,163,163,163,163, 2, - 163,163,163,163,163,163,163,163,163, 2, 2, 2,163,163,163,163, - 2, 2, 2, 2, 2, 2, 86, 2, 2, 2, 2, 2, 2, 2, 22, 22, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 22, 63, 63, - 63, 63, 63, 63, 63, 63, 63, 63, 2, 2, 2, 2, 2, 2, 63, 63, - 63, 63, 63, 63, 63, 2, 63, 63, 63, 63, 63, 2, 2, 2, 63, 63, - 63, 63, 2, 2, 2, 2,157,157,157,157,157,157,157,157,157,157, - 157, 2, 2, 2, 2, 2, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, - 80, 80, 80, 80, 2, 2,127,127,127,127,127,127,127,127,127,127, - 127,127,127,127,127, 2, 79, 2, 2, 2, 2, 2, 2, 2,115,115, - 115,115,115,115,115,115,115,115,115,115,115,115,115, 2,115,115, - 2, 2, 2, 2,115,115,159,159,159,159,159,159,159,159,159,159, - 159,159,159,159,159, 2,159,159, 2, 2, 2, 2, 2, 2,103,103, - 103,103,103,103,103,103,103,103,103,103,103,103, 2, 2,119,119, - 119,119,119,119,119,119,119,119,119,119,119,119, 2, 2,119,119, - 2,119,119,119,119,119, 2, 2, 2, 2, 2,119,119,119,146,146, - 146,146,146,146,146,146,146,146,146, 2, 2, 2, 2, 2, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99, 99, 2, 2, 2, 2, 99, 2, 2, - 2, 2, 2, 2, 2, 99,136,139, 13, 13,155, 2, 2, 2,136,136, - 136,136,136,136,136,136,155,155,155,155,155,155,155,155,155,155, - 155,155,155,155, 2, 2,136, 2, 2, 2, 2, 2, 2, 2, 17, 17, - 17, 17, 2, 17, 17, 17, 17, 17, 17, 17, 2, 17, 17, 2, 17, 15, - 15, 15, 15, 15, 15, 15, 17, 17, 17, 2, 2, 2, 2, 2, 2, 2, - 15, 2, 2, 2, 2, 2, 15, 15, 15, 2, 2, 17, 2, 2, 2, 2, - 2, 2, 17, 17, 17, 17,139,139,139,139,139,139,139,139,139,139, - 139,139, 2, 2, 2, 2,105,105,105,105,105,105,105,105,105,105, - 105, 2, 2, 2, 2, 2,105,105,105,105,105, 2, 2, 2,105, 2, - 2, 2, 2, 2, 2, 2,105,105, 2, 2,105,105,105,105, 1, 1, - 1, 1, 1, 1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, - 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, - 1, 1, 1, 1, 0, 0, 2, 2, 0, 2, 2, 0, 0, 2, 2, 0, - 0, 0, 0, 2, 0, 0, 0, 0, 2, 0, 2, 0, 0, 0, 0, 0, - 0, 0, 2, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, - 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 2, 0, 2, 2, 2, - 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0,131,131, - 131,131,131,131,131,131,131,131,131,131, 2, 2, 2, 2, 2, 2, - 2,131,131,131,131,131, 2,131,131,131,131,131,131,131, 2, 2, - 2, 2, 2, 19, 19, 19, 56, 56, 56, 56, 56, 56, 56, 2, 56, 2, - 2, 56, 56, 56, 56, 56, 56, 56, 2, 56, 56, 2, 56, 56, 56, 56, - 56, 2, 2, 2, 2, 2, 6, 6, 6, 6, 6, 6, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 6,151,151,151,151,151,151,151,151,151,151, - 151,151,151, 2, 2, 2,151,151,151,151,151,151, 2, 2,151,151, - 2, 2, 2, 2,151,151,160,160,160,160,160,160,160,160,160,160, - 160,160,160,160,160, 2,152,152,152,152,152,152,152,152,152,152, - 2, 2, 2, 2, 2,152,164,164,164,164,164,164,164,164,164,164, - 2, 2, 2, 2, 2, 2, 30, 30, 30, 30, 2, 30, 30, 2,113,113, - 113,113,113,113,113,113,113,113,113,113,113, 2, 2,113,113,113, - 113,113,113,113,113, 2,132,132,132,132,132,132,132,132,132,132, - 132,132, 2, 2, 2, 2,132,132, 2, 2, 2, 2,132,132, 3, 3, - 3, 3, 2, 3, 3, 3, 2, 3, 3, 2, 3, 2, 2, 3, 2, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 3, 3, 3, 3, 2, 3, - 2, 3, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 3, 2, 3, - 2, 3, 2, 3, 3, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, - 3, 3, 3, 2, 3, 2, 3, 3, 2, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 2, 2, 2, 2, 2, 3, 3, 3, 2, 3, 3, 3, 2, 2, - 2, 2, 2, 2, 0, 0, 15, 0, 0, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 0, 0, 0, 0, 2, 2, 2, 0, 0, 0, 0, 0, 13, 2, - 2, 2, 2, 2, 2, 2, 13, 13, 13, 2, 2, 2, 2, 2, 2, 0, - 2, 2, 2, 2, 2, 2, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, - 9, 9, 9, 10, 9, 11, 12, 13, 9, 9, 9, 14, 9, 9, 15, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 70, 70, 70,240, 70, 70, 70, 70, 70, 70, 70, 70, 70,241, 96, 96, + 96, 96, 96, 96, 96, 96, 70, 70, 70, 70,242, 96, 96, 96, 96, 96, + 96, 96, 96, 96, 96, 96, 70, 70, 70, 70, 70, 70,243, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,244, 96, 96, + 96, 96, 96, 96, 96, 96,245, 96,246,247, 0, 1, 2, 2, 0, 1, + 2, 2, 2, 3, 4, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 19, 19, + 19, 19, 19, 19, 19, 0, 19, 0, 0, 0, 0, 0, 0, 0, 19, 19, + 19, 19, 19, 0, 0, 0, 0, 0, 26, 26, 0, 0, 0, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 0, 9, 9, 9, 2, 2, + 9, 9, 9, 9, 0, 9, 2, 2, 2, 2, 9, 0, 9, 0, 9, 9, + 9, 2, 9, 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 2, 9, 9, 9, 9, 9, 9, 9, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 1, 1, 6, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 4, 4, + 4, 2, 2, 4, 4, 4, 2, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 2, 2, 2, 2, 2, 2, 2, 2, 14, 14, + 14, 2, 2, 2, 2, 14, 14, 14, 14, 14, 14, 2, 2, 2, 3, 3, + 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 0, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 3, 3, 3, 0, 0, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 3, 3, 1, 3, 3, 3, 3, 3, 3, 3, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 2, 37, 37, 37, + 37, 2, 2, 37, 37, 37, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, + 2, 2, 2, 2, 2, 2, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 2, 2, 64, 64, 64, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 2, 2, 90, 90, 90, 90, 90, 90, 90, 2, 95, 95, + 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 2, 2, 95, 2, 37, 37, + 37, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 2, 3, 3, + 2, 2, 2, 2, 2, 2, 3, 3, 0, 3, 3, 3, 3, 3, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 1, 1, 1, 1, 7, 7, 7, 7, 7, + 7, 7, 0, 0, 7, 7, 5, 5, 5, 5, 2, 5, 5, 5, 5, 5, + 5, 5, 5, 2, 2, 5, 5, 2, 2, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 2, 5, 5, 5, 5, 5, 5, 5, 2, + 5, 2, 2, 2, 5, 5, 5, 5, 2, 2, 5, 5, 5, 5, 5, 2, + 2, 5, 5, 5, 5, 2, 2, 2, 2, 2, 2, 2, 2, 5, 2, 2, + 2, 2, 5, 5, 2, 5, 5, 5, 5, 5, 2, 2, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 2, 2, 11, 11, 11, 2, 11, 11, 11, 11, 11, + 11, 2, 2, 2, 2, 11, 11, 2, 2, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 2, 11, 11, 11, 11, 11, 11, 11, 2, + 11, 11, 2, 11, 11, 2, 11, 11, 2, 2, 11, 2, 11, 11, 11, 2, + 2, 11, 11, 11, 2, 2, 2, 11, 2, 2, 2, 2, 2, 2, 2, 11, + 11, 11, 11, 2, 11, 2, 2, 2, 2, 2, 2, 2, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 2, 2, 10, 10, 10, 2, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 2, 10, 10, 10, 2, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 2, 10, 10, 10, 10, 10, 10, 10, 2, + 10, 10, 2, 10, 10, 10, 10, 10, 2, 2, 10, 10, 10, 10, 10, 10, + 2, 10, 10, 10, 2, 2, 10, 2, 2, 2, 2, 2, 2, 2, 10, 10, + 10, 10, 2, 2, 10, 10, 10, 10, 2, 2, 2, 2, 2, 2, 2, 10, + 10, 10, 10, 10, 10, 10, 2, 21, 21, 21, 2, 21, 21, 21, 21, 21, + 21, 21, 21, 2, 2, 21, 21, 2, 2, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 2, 21, 21, 21, 21, 21, 21, 21, 2, + 21, 21, 2, 21, 21, 21, 21, 21, 2, 2, 21, 21, 21, 21, 21, 2, + 2, 21, 21, 21, 2, 2, 2, 2, 2, 2, 2, 21, 21, 21, 2, 2, + 2, 2, 21, 21, 2, 21, 21, 21, 21, 21, 2, 2, 21, 21, 2, 2, + 22, 22, 2, 22, 22, 22, 22, 22, 22, 2, 2, 2, 22, 22, 22, 2, + 22, 22, 22, 22, 2, 2, 2, 22, 22, 2, 22, 2, 22, 22, 2, 2, + 2, 22, 22, 2, 2, 2, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 2, 2, 2, 2, 22, 22, 22, 2, 2, 2, 2, 2, 2, 22, 2, 2, + 2, 2, 2, 2, 22, 22, 22, 22, 22, 2, 2, 2, 2, 2, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 2, 23, 23, 23, 2, + 23, 23, 23, 23, 23, 23, 23, 23, 2, 2, 23, 23, 23, 23, 23, 2, + 23, 23, 23, 23, 2, 2, 2, 2, 2, 2, 2, 23, 23, 2, 23, 23, + 23, 2, 2, 23, 2, 2, 23, 23, 23, 23, 2, 2, 23, 23, 2, 2, + 2, 2, 2, 2, 2, 23, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 2, 16, 16, 16, 2, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 2, 16, 16, 16, 16, 16, 2, 2, 16, 16, 16, 16, 16, 2, + 16, 16, 16, 16, 2, 2, 2, 2, 2, 2, 2, 16, 16, 2, 16, 16, + 16, 16, 2, 2, 16, 16, 2, 16, 16, 16, 2, 2, 2, 2, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 2, 20, 20, 20, 2, + 20, 20, 20, 20, 20, 20, 2, 2, 2, 2, 20, 20, 20, 20, 20, 20, + 20, 20, 2, 2, 20, 20, 2, 36, 36, 36, 2, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 2, 2, 2, + 36, 36, 36, 36, 36, 36, 36, 36, 2, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 2, 36, 2, 2, 2, 2, 36, 2, 2, 2, 2, 36, 36, 36, + 36, 36, 36, 2, 36, 2, 2, 2, 2, 2, 2, 2, 36, 36, 2, 2, + 36, 36, 36, 2, 2, 2, 2, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 2, 2, 2, 2, 0, 24, 24, + 24, 24, 2, 2, 2, 2, 2, 18, 18, 2, 18, 2, 18, 18, 18, 18, + 18, 2, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 2, 18, 2, 18, 18, 18, 18, 18, 18, 18, 2, 2, 18, 18, + 18, 18, 18, 2, 18, 2, 18, 18, 18, 18, 18, 18, 18, 2, 18, 18, + 2, 2, 18, 18, 18, 18, 25, 25, 25, 25, 25, 25, 25, 25, 2, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 2, 2, 2, 25, 25, + 25, 25, 25, 2, 25, 25, 25, 25, 25, 25, 25, 0, 0, 0, 0, 25, + 25, 2, 2, 2, 2, 2, 33, 33, 33, 33, 33, 33, 33, 33, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 2, 8, 2, 2, + 2, 2, 2, 8, 2, 2, 8, 8, 8, 0, 8, 8, 8, 8, 12, 12, + 12, 12, 12, 12, 12, 12, 30, 30, 30, 30, 30, 30, 30, 30, 30, 2, + 30, 30, 30, 30, 2, 2, 30, 30, 30, 30, 30, 30, 30, 2, 30, 30, + 30, 2, 2, 30, 30, 30, 30, 30, 30, 30, 30, 2, 2, 2, 30, 30, + 2, 2, 2, 2, 2, 2, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 2, 2, 28, 28, 28, 28, 28, 28, 28, 28, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 2, 2, 2, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 0, 0, 0, 35, 35, 35, 2, + 2, 2, 2, 2, 2, 2, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 2, 2, 2, 2, 2, 2, 2, 2, 2, 45, 44, 44, + 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 0, 0, 2, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 2, 2, 2, 2, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 2, 46, 46, 46, 2, + 46, 46, 2, 2, 2, 2, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, + 31, 31, 31, 31, 2, 2, 31, 31, 2, 2, 2, 2, 2, 2, 32, 32, + 0, 0, 32, 0, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 2, 2, 2, 2, 2, 2, 32, 2, 2, 2, 2, 2, 2, 2, 32, 32, + 32, 2, 2, 2, 2, 2, 28, 28, 28, 28, 28, 28, 2, 2, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 2, 48, 48, + 48, 48, 2, 2, 2, 2, 48, 2, 2, 2, 48, 48, 48, 48, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 2, 2, 52, 52, + 52, 52, 52, 2, 2, 2, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 2, 2, 2, 2, 58, 58, 2, 2, 2, 2, 2, 2, 58, 58, + 58, 2, 2, 2, 58, 58, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 2, 2, 54, 54, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 2, 91, 91, 91, 91, 91, 2, 2, 91, 91, 91, + 2, 2, 2, 2, 2, 2, 91, 91, 91, 91, 91, 91, 2, 2, 1, 1, + 1, 1, 1, 1, 1, 2, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, + 62, 62, 62, 2, 2, 2, 62, 62, 62, 62, 62, 62, 62, 2, 76, 76, + 76, 76, 76, 76, 76, 76, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, + 93, 93, 2, 2, 2, 2, 2, 2, 2, 2, 93, 93, 93, 93, 70, 70, + 70, 70, 70, 70, 70, 70, 2, 2, 2, 70, 70, 70, 70, 70, 70, 70, + 2, 2, 2, 70, 70, 70, 73, 73, 73, 73, 73, 73, 73, 73, 6, 2, + 2, 2, 2, 2, 2, 2, 8, 8, 8, 2, 2, 8, 8, 8, 1, 1, + 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, + 0, 2, 2, 2, 2, 2, 19, 19, 19, 19, 19, 19, 9, 9, 9, 9, + 9, 6, 19, 19, 19, 19, 19, 19, 19, 19, 19, 9, 9, 9, 9, 9, + 19, 19, 19, 19, 9, 9, 9, 9, 9, 19, 19, 19, 19, 19, 6, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 9, 9, 9, + 9, 9, 9, 9, 2, 2, 2, 9, 2, 9, 2, 9, 2, 9, 9, 9, + 9, 9, 9, 2, 9, 9, 9, 9, 9, 9, 2, 2, 9, 9, 9, 9, + 9, 9, 2, 9, 9, 9, 2, 2, 9, 9, 9, 2, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 2, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 2, 0, 0, 0, 19, 2, 2, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 2, 19, 19, + 19, 19, 19, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, + 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, + 19, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 19, 0, + 0, 0, 2, 2, 2, 2, 0, 0, 0, 2, 2, 2, 2, 2, 27, 27, + 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 0, 56, 56, 56, 56, 56, 56, 56, 56, 55, 55, + 55, 55, 2, 2, 2, 2, 2, 55, 55, 55, 55, 55, 55, 55, 61, 61, + 61, 61, 61, 61, 61, 61, 2, 2, 2, 2, 2, 2, 2, 61, 61, 2, + 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 2, 2, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 2, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 2, 2, 2, 2, 13, 13, 13, 13, 13, 13, 2, 2, 0, 0, + 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 0, 13, 0, 13, 0, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 1, 1, 1, 1, 12, 12, 13, 13, + 13, 13, 0, 0, 0, 0, 2, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 2, 2, 1, + 1, 0, 0, 15, 15, 15, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 17, 17, 17, 2, 2, + 2, 2, 2, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 2, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 2, 12, 12, + 12, 12, 12, 12, 12, 0, 17, 17, 17, 17, 17, 17, 17, 0, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 2, 2, 2, 39, 39, + 39, 39, 39, 39, 39, 2, 86, 86, 86, 86, 86, 86, 86, 86, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 2, 2, 2, 2, 79, 79, + 79, 79, 79, 79, 79, 79, 0, 0, 19, 19, 19, 19, 19, 19, 0, 0, + 0, 19, 19, 19, 19, 19, 19, 19, 19, 2, 2, 2, 2, 2, 19, 19, + 2, 19, 2, 19, 19, 19, 19, 19, 2, 2, 2, 2, 2, 2, 2, 2, + 19, 19, 19, 19, 19, 19, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, + 60, 60, 60, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 65, 65, + 65, 65, 65, 65, 65, 65, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, + 75, 75, 75, 75, 2, 2, 2, 2, 2, 2, 2, 2, 75, 75, 75, 75, + 2, 2, 2, 2, 2, 2, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, + 69, 69, 69, 69, 0, 69, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 74, 12, 12, + 12, 12, 12, 2, 2, 2, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, + 84, 84, 84, 84, 2, 0, 84, 84, 2, 2, 2, 2, 84, 84, 33, 33, + 33, 33, 33, 33, 33, 2, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, + 68, 68, 68, 68, 68, 2, 68, 68, 68, 68, 68, 68, 2, 2, 68, 68, + 2, 2, 68, 68, 68, 68, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, + 92, 2, 2, 2, 2, 2, 2, 2, 2, 92, 92, 92, 92, 92, 87, 87, + 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 2, 2, 30, + 30, 30, 30, 30, 30, 2, 19, 19, 19, 0, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 9, 19, 19, 19, 19, 0, 0, 2, 2, 2, 2, 87, 87, + 87, 87, 87, 87, 2, 2, 87, 87, 2, 2, 2, 2, 2, 2, 12, 12, + 12, 12, 2, 2, 2, 2, 2, 2, 2, 12, 12, 12, 12, 12, 13, 13, + 2, 2, 2, 2, 2, 2, 19, 19, 19, 19, 19, 19, 19, 2, 2, 2, + 2, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 2, 14, 14, 14, 14, 14, 2, 14, 2, 14, 14, + 2, 14, 14, 2, 14, 14, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, + 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 2, 2, + 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 3, 1, 1, + 1, 1, 1, 1, 6, 6, 0, 0, 0, 2, 0, 0, 0, 0, 3, 3, + 3, 3, 3, 2, 3, 3, 3, 3, 3, 3, 3, 2, 2, 0, 2, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 17, 17, + 17, 17, 17, 17, 0, 0, 2, 2, 12, 12, 12, 12, 12, 12, 2, 2, + 12, 12, 12, 2, 2, 2, 2, 0, 0, 0, 0, 0, 2, 2, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 2, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 2, 49, 49, 49, 2, 49, 49, 2, 49, 49, 49, + 49, 49, 49, 49, 2, 2, 49, 49, 49, 2, 2, 2, 2, 2, 0, 0, + 0, 2, 2, 2, 2, 0, 0, 0, 0, 0, 2, 2, 2, 0, 0, 0, + 0, 0, 0, 2, 2, 2, 9, 2, 2, 2, 2, 2, 2, 2, 0, 0, + 0, 0, 0, 1, 2, 2, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, + 71, 71, 71, 2, 2, 2, 67, 67, 67, 67, 67, 67, 67, 67, 67, 2, + 2, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 42, 42, 42, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 2, 2, 2, 2, 2,118,118,118,118,118,118,118,118,118,118, + 118, 2, 2, 2, 2, 2, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, + 53, 53, 53, 53, 2, 53, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 2, 2, 2, 2, 59, 59, 59, 59, 59, 59, 2, 2, 40, 40, + 40, 40, 40, 40, 40, 40, 51, 51, 51, 51, 51, 51, 51, 51, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 2, 2, 50, 50, + 2, 2, 2, 2, 2, 2,135,135,135,135,135,135,135,135,135,135, + 135,135, 2, 2, 2, 2,106,106,106,106,106,106,106,106,104,104, + 104,104,104,104,104,104,104,104,104,104, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2,104,161,161,161,161,161,161,161,161,161,161, + 161, 2,161,161,161,161,161,161,161, 2,161,161, 2,161,161,161, + 2,161,161,161,161,161,161,161, 2,161,161, 2, 2, 2,110,110, + 110,110,110,110,110,110,110,110,110,110,110,110,110, 2,110,110, + 110,110,110,110, 2, 2, 19, 19, 19, 19, 19, 19, 2, 19, 19, 2, + 19, 19, 19, 19, 19, 19, 47, 47, 47, 47, 47, 47, 2, 2, 47, 2, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 2, 47, 47, 2, 2, 2, 47, 2, 2, 47, 81, 81, + 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 2, 81,120,120, + 120,120,120,120,120,120,116,116,116,116,116,116,116,116,116,116, + 116,116,116,116,116, 2, 2, 2, 2, 2, 2, 2, 2,116,128,128, + 128,128,128,128,128,128,128,128,128, 2,128,128, 2, 2, 2, 2, + 2,128,128,128,128,128, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, + 66, 66, 2, 2, 2, 66, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, + 2, 2, 2, 2, 2, 72, 98, 98, 98, 98, 98, 98, 98, 98, 97, 97, + 97, 97, 97, 97, 97, 97, 2, 2, 2, 2, 97, 97, 97, 97, 2, 2, + 97, 97, 97, 97, 97, 97, 57, 57, 57, 57, 2, 57, 57, 2, 2, 2, + 2, 2, 57, 57, 57, 57, 57, 57, 57, 57, 2, 57, 57, 57, 2, 57, + 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, + 57, 57, 57, 57, 2, 2, 57, 57, 57, 2, 2, 2, 2, 57, 57, 2, + 2, 2, 2, 2, 2, 2, 88, 88, 88, 88, 88, 88, 88, 88,117,117, + 117,117,117,117,117,117,112,112,112,112,112,112,112,112,112,112, + 112,112,112,112,112, 2, 2, 2, 2,112,112,112,112,112, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 2, 2, 2, 78, + 78, 78, 78, 78, 78, 78, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 2, 2, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, + 82, 2, 2, 2, 2, 2,122,122,122,122,122,122,122,122,122,122, + 2, 2, 2, 2, 2, 2, 2,122,122,122,122, 2, 2, 2, 2,122, + 122,122,122,122,122,122, 89, 89, 89, 89, 89, 89, 89, 89, 89, 2, + 2, 2, 2, 2, 2, 2,130,130,130,130,130,130,130,130,130,130, + 130, 2, 2, 2, 2, 2, 2, 2,130,130,130,130,130,130,144,144, + 144,144,144,144,144,144,144,144, 2, 2, 2, 2, 2, 2,156,156, + 156,156,156,156,156,156,156,156, 2,156,156,156, 2, 2,156,156, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3,147,147, + 147,147,147,147,147,147,148,148,148,148,148,148,148,148,148,148, + 2, 2, 2, 2, 2, 2,158,158,158,158,158,158,158,158,158,158, + 2, 2, 2, 2, 2, 2,153,153,153,153,153,153,153,153,153,153, + 153,153, 2, 2, 2, 2,149,149,149,149,149,149,149,149,149,149, + 149,149,149,149,149, 2, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 2, 2, 2, 2, 94, 94, 94, 94, 94, 94, 2, 2, + 2, 2, 2, 2, 2, 94, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 85, 2, 2,101,101, + 101,101,101,101,101,101,101, 2, 2, 2, 2, 2, 2, 2,101,101, + 2, 2, 2, 2, 2, 2, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, + 96, 96, 96, 2, 96, 96,111,111,111,111,111,111,111,111,111,111, + 111,111,111,111,111, 2,100,100,100,100,100,100,100,100, 2, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 2, 2, 2,108,108, + 108,108,108,108,108,108,108,108, 2,108,108,108,108,108,108,108, + 2, 2, 2, 2, 2, 2,129,129,129,129,129,129,129, 2,129, 2, + 129,129,129,129, 2,129,129,129,129,129,129,129,129,129,129,129, + 129,129,129,129, 2,129,129,129, 2, 2, 2, 2, 2, 2,109,109, + 109,109,109,109,109,109,109,109,109, 2, 2, 2, 2, 2,109,109, + 2, 2, 2, 2, 2, 2,107,107,107,107, 2,107,107,107,107,107, + 107,107,107, 2, 2,107,107, 2, 2,107,107,107,107,107,107,107, + 107,107,107,107,107,107,107, 2,107,107,107,107,107,107,107, 2, + 107,107, 2,107,107,107,107,107, 2, 1,107,107,107,107,107, 2, + 2,107,107,107, 2, 2,107, 2, 2, 2, 2, 2, 2,107, 2, 2, + 2, 2, 2,107,107,107,107,107,107,107, 2, 2,107,107,107,107, + 107,107,107, 2, 2, 2,137,137,137,137,137,137,137,137,137,137, + 137,137, 2,137,137,137,137,137, 2, 2, 2, 2, 2, 2,124,124, + 124,124,124,124,124,124,124,124, 2, 2, 2, 2, 2, 2,123,123, + 123,123,123,123,123,123,123,123,123,123,123,123, 2, 2,114,114, + 114,114,114,114,114,114,114,114,114,114,114, 2, 2, 2,114,114, + 2, 2, 2, 2, 2, 2, 32, 32, 32, 32, 32, 2, 2, 2,102,102, + 102,102,102,102,102,102,102,102, 2, 2, 2, 2, 2, 2,126,126, + 126,126,126,126,126,126,126,126,126, 2, 2,126,126,126,126,126, + 126,126, 2, 2, 2, 2,126,126,126,126,126,126,126, 2,142,142, + 142,142,142,142,142,142,142,142,142,142, 2, 2, 2, 2,125,125, + 125,125,125,125,125,125,125,125,125, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2,125,154,154,154,154,154,154,154, 2, 2,154, + 2, 2,154,154,154,154,154,154,154,154, 2,154,154, 2,154,154, + 154,154,154,154,154,154,154,154,154,154,154,154, 2,154,154, 2, + 2,154,154,154,154,154,154,154, 2, 2, 2, 2, 2, 2,150,150, + 150,150,150,150,150,150, 2, 2,150,150,150,150,150,150,150,150, + 150,150,150, 2, 2, 2,141,141,141,141,141,141,141,141,140,140, + 140,140,140,140,140,140,140,140,140, 2, 2, 2, 2, 2,121,121, + 121,121,121,121,121,121,121, 2, 2, 2, 2, 2, 2, 2, 7, 7, + 2, 2, 2, 2, 2, 2,133,133,133,133,133,133,133,133,133, 2, + 133,133,133,133,133,133,133,133,133,133,133,133,133, 2,133,133, + 133,133,133,133, 2, 2,133,133,133,133,133, 2, 2, 2,134,134, + 134,134,134,134,134,134, 2, 2,134,134,134,134,134,134, 2,134, + 134,134,134,134,134,134,134,134,134,134,134,134,134, 2,138,138, + 138,138,138,138,138, 2,138,138, 2,138,138,138,138,138,138,138, + 138,138,138,138,138,138, 2, 2,138, 2,138,138, 2,138,138,138, + 2, 2, 2, 2, 2, 2,143,143,143,143,143,143, 2,143,143, 2, + 143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143, + 143,143,143,143,143, 2,143,143, 2,143,143,143,143,143,143, 2, + 2, 2, 2, 2, 2, 2,143,143, 2, 2, 2, 2, 2, 2,145,145, + 145,145,145,145,145,145,145, 2, 2, 2, 2, 2, 2, 2,163,163, + 163,163,163,163,163,163,163, 2,163,163,163,163,163,163,163,163, + 163, 2, 2, 2,163,163,163,163, 2, 2, 2, 2, 2, 2, 86, 2, + 2, 2, 2, 2, 2, 2, 22, 22, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 22, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, + 2, 2, 2, 2, 2, 2, 63, 63, 63, 63, 63, 63, 63, 2, 63, 63, + 63, 63, 63, 2, 2, 2, 63, 63, 63, 63, 2, 2, 2, 2,157,157, + 157,157,157,157,157,157,157,157,157, 2, 2, 2, 2, 2, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 2, 2,127,127, + 127,127,127,127,127,127,127,127,127,127,127,127,127, 2, 79, 2, + 2, 2, 2, 2, 2, 2,115,115,115,115,115,115,115,115,115,115, + 115,115,115,115,115, 2,115,115, 2, 2, 2, 2,115,115,159,159, + 159,159,159,159,159,159,159,159,159,159,159,159,159, 2,159,159, + 2, 2, 2, 2, 2, 2,103,103,103,103,103,103,103,103,103,103, + 103,103,103,103, 2, 2,119,119,119,119,119,119,119,119,119,119, + 119,119,119,119, 2, 2,119,119, 2,119,119,119,119,119, 2, 2, + 2, 2, 2,119,119,119,146,146,146,146,146,146,146,146,146,146, + 146, 2, 2, 2, 2, 2, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, + 99, 2, 2, 2, 2, 99, 2, 2, 2, 2, 2, 2, 2, 99,136,139, + 13, 13,155, 2, 2, 2,136,136,136,136,136,136,136,136,155,155, + 155,155,155,155,155,155,155,155,155,155,155,155, 2, 2,136, 2, + 2, 2, 2, 2, 2, 2, 17, 17, 17, 17, 2, 17, 17, 17, 17, 17, + 17, 17, 2, 17, 17, 2, 17, 15, 15, 15, 15, 15, 15, 15, 17, 17, + 17, 2, 2, 2, 2, 2, 2, 2, 15, 2, 2, 2, 2, 2, 15, 15, + 15, 2, 2, 17, 2, 2, 2, 2, 2, 2, 17, 17, 17, 17,139,139, + 139,139,139,139,139,139,139,139,139,139, 2, 2, 2, 2,105,105, + 105,105,105,105,105,105,105,105,105, 2, 2, 2, 2, 2,105,105, + 105,105,105, 2, 2, 2,105, 2, 2, 2, 2, 2, 2, 2,105,105, + 2, 2,105,105,105,105, 1, 1, 1, 1, 1, 1, 2, 2, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, + 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 2, 2, + 0, 2, 2, 0, 0, 2, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, + 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, + 0, 2, 2, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 2, 0, 0, + 0, 0, 0, 2, 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 2, + 0, 0, 0, 0, 0, 0,131,131,131,131,131,131,131,131,131,131, + 131,131, 2, 2, 2, 2, 2, 2, 2,131,131,131,131,131, 2,131, + 131,131,131,131,131,131, 2, 2, 2, 2, 2, 19, 19, 19, 56, 56, + 56, 56, 56, 56, 56, 2, 56, 2, 2, 56, 56, 56, 56, 56, 56, 56, + 2, 56, 56, 2, 56, 56, 56, 56, 56, 2, 2, 2, 2, 2, 6, 6, + 6, 6, 6, 6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6,151,151, + 151,151,151,151,151,151,151,151,151,151,151, 2, 2, 2,151,151, + 151,151,151,151, 2, 2,151,151, 2, 2, 2, 2,151,151,160,160, + 160,160,160,160,160,160,160,160,160,160,160,160,160, 2,152,152, + 152,152,152,152,152,152,152,152, 2, 2, 2, 2, 2,152,164,164, + 164,164,164,164,164,164,164,164, 2, 2, 2, 2, 2, 2, 30, 30, + 30, 30, 2, 30, 30, 2,113,113,113,113,113,113,113,113,113,113, + 113,113,113, 2, 2,113,113,113,113,113,113,113,113, 2,132,132, + 132,132,132,132,132,132,132,132,132,132, 2, 2, 2, 2,132,132, + 2, 2, 2, 2,132,132, 3, 3, 3, 3, 2, 3, 3, 3, 2, 3, + 3, 2, 3, 2, 2, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 2, 3, 3, 3, 3, 2, 3, 2, 3, 2, 2, 2, 2, 2, 2, + 3, 2, 2, 2, 2, 3, 2, 3, 2, 3, 2, 3, 3, 3, 2, 3, + 2, 3, 2, 3, 2, 3, 2, 3, 3, 3, 3, 2, 3, 2, 3, 3, + 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 3, + 3, 3, 2, 3, 3, 3, 2, 2, 2, 2, 2, 2, 0, 0, 15, 0, + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 2, 2, + 2, 0, 0, 0, 0, 0, 13, 2, 2, 2, 2, 2, 2, 2, 13, 13, + 13, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 0, 1, + 2, 3, 4, 5, 6, 7, 8, 9, 9, 9, 9, 10, 9, 11, 12, 13, + 9, 9, 9, 14, 9, 9, 15, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 16, 17, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 18, 19, - 20, 9, 21, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 16, 17, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 18, 19, 20, 9, 21, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 22, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 22, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, @@ -2162,57 +2137,57 @@ _hb_ucd_u8[18260] = 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 23, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0, 0, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 23, 0, 0, 24, 25, 26, 27, 28, - 29, 30, 0, 0, 31, 32, 0, 33, 0, 34, 0, 35, 0, 0, 0, 0, - 36, 37, 38, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 41, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 23, 24, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, + 9, 10, 11, 12, 0, 0, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 23, 0, 0, 24, 25, 26, 27, 28, 29, 30, 0, 0, 31, 32, 0, 33, + 0, 34, 0, 35, 0, 0, 0, 0, 36, 37, 38, 39, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 41, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 43, 44, 0, 45, 0, 0, 0, 0, 0, 0, - 46, 47, 0, 0, 0, 0, 0, 48, 0, 49, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 50, 51, 0, 0, 0, 52, 0, 0, - 53, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 0, 0, 0, 0, 0, - 55, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, - 0, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 58, 59, 60, 61, 62, 63, 64, 65, - 0, 0, 0, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 44, + 0, 45, 0, 0, 0, 0, 0, 0, 46, 47, 0, 0, 0, 0, 0, 48, + 0, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 50, 51, 0, 0, 0, 52, 0, 0, 53, 0, 0, 0, 0, 0, 0, 0, + 54, 0, 0, 0, 0, 0, 0, 0, 55, 0, 0, 0, 0, 0, 0, 0, + 56, 0, 0, 0, 0, 0, 0, 0, 0, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 58, 59, 60, 61, 62, 63, 64, 65, 0, 0, 0, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 67, 68, 0, 69, 70, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, - 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, - 99,100,101,102,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,104, 0, 0, 0, 0, 0, 0,105,106, 0, - 107, 0, 0, 0,108, 0,109, 0,110, 0,111,112,113, 0,114, 0, - 0, 0,115, 0, 0, 0,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0,117, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,118,119,120,121, 0,122,123,124, - 125,126, 0,127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 68, 0, 69, + 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71, 72, 73, 74, + 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, + 91, 92, 93, 94, 95, 96, 97, 98, 99,100,101,102,103, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,104, 0, + 0, 0, 0, 0, 0,105,106, 0,107, 0, 0, 0,108, 0,109, 0, + 110, 0,111,112,113, 0,114, 0, 0, 0,115, 0, 0, 0,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0,128,129,130,131,132,133,134,135,136,137,138,139, - 140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155, - 156,157, 0, 0, 0,158,159,160,161, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,162,163, 0, - 0, 0, 0, 0, 0, 0,164, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0,117, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,165, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,166, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,167, + 118,119,120,121, 0,122,123,124,125,126, 0,127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0,168, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128,129,130,131, + 132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147, + 148,149,150,151,152,153,154,155,156,157, 0, 0, 0,158,159,160, + 161, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0,162,163, 0, 0, 0, 0, 0, 0, 0,164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0,169,170, 0, 0, 0, 0,171, - 172, 0, 0, 0,173,174,175,176,177,178,179,180,181,182,183,184, - 185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200, - 201,202,203,204,205,206, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 2, 3, 4, + 165, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0,166, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0,167, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,168, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0,169,170, 0, 0, 0, 0,171,172, 0, 0, 0,173,174,175,176, + 177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192, + 193,194,195,196,197,198,199,200,201,202,203,204,205,206, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, }; static const uint16_t _hb_ucd_u16[9320] = @@ -2827,7 +2802,7 @@ _hb_ucd_gc (unsigned u) static inline uint_fast8_t _hb_ucd_ccc (unsigned u) { - return u<125259u?_hb_ucd_u8[9184+(((_hb_ucd_u8[8128+(((_hb_ucd_u8[7424+(((_hb_ucd_u8[7178+(u>>2>>3>>4)])<<4)+((u>>2>>3)&15u))])<<3)+((u>>2)&7u))])<<2)+((u)&3u))]:0; + return u<125259u?_hb_ucd_u8[8792+(((_hb_ucd_u8[8236+(((_hb_ucd_u8[7776+(((_hb_ucd_u8[7424+(((_hb_ucd_u8[7178+(u>>2>>2>>2>>3)])<<3)+((u>>2>>2>>2)&7u))])<<2)+((u>>2>>2)&3u))])<<2)+((u>>2)&3u))])<<2)+((u)&3u))]:0; } static inline unsigned _hb_ucd_b4 (const uint8_t* a, unsigned i) @@ -2837,24 +2812,24 @@ _hb_ucd_b4 (const uint8_t* a, unsigned i) static inline int_fast16_t _hb_ucd_bmg (unsigned u) { - return u<65380u?_hb_ucd_i16[((_hb_ucd_u8[9932+(((_hb_ucd_u8[9812+(((_hb_ucd_b4(9684+_hb_ucd_u8,u>>2>>3>>3))<<3)+((u>>2>>3)&7u))])<<3)+((u>>2)&7u))])<<2)+((u)&3u)]:0; + return u<65380u?_hb_ucd_i16[((_hb_ucd_u8[9540+(((_hb_ucd_u8[9420+(((_hb_ucd_b4(9292+_hb_ucd_u8,u>>2>>3>>3))<<3)+((u>>2>>3)&7u))])<<3)+((u>>2)&7u))])<<2)+((u)&3u)]:0; } static inline uint_fast8_t _hb_ucd_sc (unsigned u) { - return u<918000u?_hb_ucd_u8[11454+(((_hb_ucd_u16[2040+(((_hb_ucd_u8[10718+(((_hb_ucd_u8[10268+(u>>3>>4>>4)])<<4)+((u>>3>>4)&15u))])<<4)+((u>>3)&15u))])<<3)+((u)&7u))]:2; + return u<918000u?_hb_ucd_u8[11062+(((_hb_ucd_u16[2040+(((_hb_ucd_u8[10326+(((_hb_ucd_u8[9876+(u>>3>>4>>4)])<<4)+((u>>3>>4)&15u))])<<4)+((u>>3)&15u))])<<3)+((u)&7u))]:2; } static inline uint_fast16_t _hb_ucd_dm (unsigned u) { - return u<195102u?_hb_ucd_u16[6008+(((_hb_ucd_u8[17460+(((_hb_ucd_u8[17078+(u>>4>>5)])<<5)+((u>>4)&31u))])<<4)+((u)&15u))]:0; + return u<195102u?_hb_ucd_u16[6008+(((_hb_ucd_u8[17068+(((_hb_ucd_u8[16686+(u>>4>>5)])<<5)+((u>>4)&31u))])<<4)+((u)&15u))]:0; } #elif !defined(HB_NO_UCD_UNASSIGNED) static const uint8_t -_hb_ucd_u8[17868] = +_hb_ucd_u8[14744] = { 0, 1, 2, 3, 4, 5, 6, 7, 7, 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 9, 10, 7, 7, 7, 7, 11, 12, 13, 13, 13, 14, @@ -3436,51 +3411,54 @@ _hb_ucd_u8[17868] = 0,230,220, 0, 0, 0,220,220, 0, 0,230,220, 0, 9, 7, 0, 0, 7, 9, 0, 0, 0, 9, 7, 6, 6, 0, 0, 0, 0, 1, 0, 0,216,216, 1, 1, 1, 0, 0, 0,226,216,216,216,216,216, 0, - 220,220,220, 0,232,232,220,230,230,230, 7, 0, 16, 17, 17, 17, - 17, 17, 17, 33, 17, 17, 17, 19, 17, 17, 17, 17, 20,101, 17,113, - 129,169, 17, 27, 28, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 220,220,220, 0,232,232,220,230,230,230, 7, 0, 16, 17, 17, 33, + 17, 49, 17, 17, 84, 97,135,145, 26, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,237, 0, 1, 2, 2, - 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 6, 7, 8, - 9, 0, 0, 0, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 21, 22, 0, 0, 0, 0, - 23, 24, 25, 26, 0, 27, 0, 28, 29, 30, 31, 32, 0, 0, 0, 0, - 0, 0, 0, 33, 34, 35, 36, 0, 0, 0, 0, 0, 37, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 38, 39, 0, 0, 0, 0, 1, 2, 40, 41, - 0, 1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, - 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 3, 4, 0, 0, 5, 0, - 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 7, 1, 0, 0, 0, 0, - 0, 0, 8, 9, 0, 0, 0, 0, 0, 0, 10, 0, 0, 10, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 10, - 0, 0, 0, 0, 0, 0, 11, 12, 0, 13, 0, 14, 15, 16, 0, 0, - 0, 0, 0, 1, 17, 18, 0, 19, 7, 1, 0, 0, 0, 20, 20, 7, - 20, 20, 20, 20, 20, 20, 20, 8, 21, 0, 22, 0, 7, 23, 24, 0, - 20, 20, 25, 0, 0, 0, 26, 27, 1, 7, 20, 20, 20, 20, 20, 1, - 28, 29, 30, 31, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 10, 0, - 0, 0, 0, 0, 0, 0, 20, 20, 20, 1, 0, 0, 8, 21, 32, 4, - 0, 10, 0, 33, 7, 20, 20, 20, 0, 0, 0, 0, 8, 34, 34, 35, - 36, 34, 37, 0, 38, 1, 20, 20, 0, 0, 39, 0, 1, 1, 0, 8, - 21, 1, 20, 0, 0, 0, 1, 0, 0, 40, 1, 1, 0, 0, 8, 21, - 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 26, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 21, 7, 20, 41, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 21, 0, 42, 43, 44, 0, 45, 0, 8, 21, 0, 0, 0, 0, 0, - 0, 0, 0, 46, 7, 1, 10, 1, 0, 0, 0, 1, 20, 20, 1, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 34, 9, 0, 0, 20, 20, - 1, 20, 20, 0, 0, 0, 0, 0, 0, 0, 26, 21, 0, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 47, 48, 0, 0, 0, - 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 7, 8, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 9, 10, 11, 11, 11, 11, 12, 13, - 13, 13, 13, 14, 15, 16, 17, 18, 19, 20, 21, 13, 22, 13, 13, 13, - 13, 23, 24, 24, 25, 26, 13, 13, 13, 27, 28, 29, 13, 30, 31, 32, - 33, 34, 35, 36, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 37, 7, 38, 39, 7, 40, 7, 7, - 7, 41, 13, 42, 7, 7, 43, 7, 44, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,177, 0, 1, 2, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 4, 3, 3, 3, 3, 3, 5, 3, 3, 3, 3, 3, 6, 7, 8, 3, + 3, 3, 3, 3, 9, 10, 11, 12, 13, 3, 3, 3, 3, 3, 3, 3, + 3, 14, 3, 15, 3, 3, 3, 3, 3, 3, 16, 17, 18, 19, 20, 21, + 3, 3, 3, 22, 23, 24, 3, 3, 3, 3, 3, 3, 25, 3, 3, 3, + 3, 3, 3, 3, 3, 26, 3, 3, 27, 28, 0, 1, 0, 0, 0, 0, + 0, 1, 0, 2, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 0, + 0, 4, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 6, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 8, 9, 0, 0, 0, 0, 0, 0, 9, 0, 9, 0, 0, + 0, 0, 0, 0, 0, 10, 11, 12, 13, 0, 0, 14, 15, 16, 6, 0, + 17, 18, 19, 19, 19, 20, 21, 22, 23, 24, 19, 25, 0, 26, 27, 19, + 19, 28, 29, 30, 0, 31, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, + 0, 19, 28, 0, 32, 33, 9, 34, 35, 19, 0, 0, 36, 37, 38, 39, + 40, 19, 0, 41, 42, 43, 44, 31, 0, 1, 45, 42, 0, 0, 0, 0, + 0, 32, 14, 14, 0, 0, 0, 0, 14, 0, 0, 46, 47, 47, 47, 47, + 48, 49, 47, 47, 47, 47, 50, 51, 52, 53, 43, 21, 0, 0, 0, 0, + 0, 0, 0, 54, 6, 55, 0, 14, 19, 1, 0, 0, 0, 0, 56, 57, + 0, 0, 0, 0, 0, 19, 58, 31, 0, 0, 0, 0, 0, 0, 0, 59, + 14, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 3, 0, 0, 0, 60, + 61, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 2, 3, + 0, 4, 5, 0, 0, 6, 0, 0, 0, 7, 0, 0, 0, 1, 1, 0, + 0, 8, 9, 0, 8, 9, 0, 0, 0, 0, 8, 9, 10, 11, 12, 0, + 0, 0, 13, 0, 0, 0, 0, 14, 15, 16, 17, 0, 0, 0, 1, 0, + 0, 18, 19, 0, 0, 0, 20, 0, 0, 0, 1, 1, 1, 1, 0, 1, + 1, 1, 1, 1, 1, 1, 0, 8, 21, 9, 0, 0, 22, 0, 0, 0, + 0, 1, 0, 23, 24, 25, 0, 0, 26, 0, 0, 0, 8, 21, 27, 0, + 1, 0, 0, 1, 1, 1, 1, 0, 1, 28, 29, 30, 0, 31, 32, 20, + 1, 1, 0, 0, 0, 8, 21, 9, 1, 4, 5, 0, 0, 0, 33, 9, + 0, 1, 1, 1, 0, 8, 21, 21, 21, 21, 34, 1, 35, 21, 21, 21, + 9, 36, 0, 0, 37, 38, 1, 0, 39, 0, 0, 0, 1, 0, 1, 0, + 0, 0, 0, 8, 21, 9, 1, 0, 0, 0, 40, 0, 8, 21, 21, 21, + 21, 21, 21, 21, 21, 9, 0, 1, 1, 1, 1, 8, 21, 21, 21, 9, + 0, 0, 0, 41, 0, 42, 43, 0, 0, 0, 1, 44, 0, 0, 0, 45, + 8, 9, 1, 0, 0, 0, 8, 21, 21, 21, 9, 0, 1, 0, 1, 1, + 8, 21, 21, 9, 0, 4, 5, 8, 9, 1, 0, 0, 0, 1, 2, 3, + 4, 5, 6, 7, 7, 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 9, 10, 11, 11, 11, 11, 12, 13, 13, 13, 13, 14, 15, 16, 17, 18, + 19, 20, 21, 13, 22, 13, 13, 13, 13, 23, 24, 24, 25, 26, 13, 13, + 13, 27, 28, 29, 13, 30, 31, 32, 33, 34, 35, 36, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 37, 7, 38, 39, 7, 40, 7, 7, 7, 41, 13, 42, 7, 7, 43, 7, + 44, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, @@ -3501,419 +3479,221 @@ _hb_ucd_u8[17868] = 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 45, 0, 0, 1, 2, 2, 2, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, - 24, 25, 26, 27, 28, 29, 30, 31, 32, 32, 33, 34, 35, 36, 37, 37, - 37, 37, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, - 51, 52, 2, 2, 53, 54, 55, 56, 57, 58, 59, 59, 59, 59, 60, 59, - 59, 59, 59, 59, 59, 59, 61, 61, 59, 59, 59, 59, 62, 63, 64, 65, - 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 59, 70, 70, - 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 45, 0, 0, 1, + 2, 2, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 32, 33, 34, 35, 36, 37, 37, 37, 37, 37, 38, 39, 40, 41, 42, + 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 2, 2, 53, 54, 55, 56, + 57, 58, 59, 59, 59, 59, 60, 59, 59, 59, 59, 59, 59, 59, 61, 61, + 59, 59, 59, 59, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, + 74, 75, 76, 77, 78, 59, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, - 70, 79, 70, 70, 70, 70, 80, 80, 80, 80, 80, 80, 80, 80, 80, 81, - 82, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 79, 70, 70, 70, 70, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 81, 82, 82, 83, 84, 85, 86, 87, 88, + 89, 90, 91, 92, 93, 94, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 95, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, - 96, 96, 96, 96, 96, 96, 96, 96, 70, 70, 97, 98, 99,100,101,101, - 102,103,104,105,106,107,108,109,110,111, 96,112,113,114,115,116, - 117,118,119,119,120,121,122,123,124,125,126,127,128,129,130,131, - 132, 96,133,134,135,136,137,138,139,140,141,142,143, 96,144,145, - 96,146,147,148,149, 96,150,151,152,153,154,155,156, 96,157,158, - 159,160, 96,161,162,163,164,164,164,164,164,164,164,165,166,164, - 167, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, - 96, 96, 96, 96, 96,168,169,169,169,169,169,169,169,169,170, 96, - 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,171,171, - 171,171,172, 96, 96, 96,173,173,173,173,174,175,176,177, 96, 96, - 96, 96,178,179,180,181,182,182,182,182,182,182,182,182,182,182, - 182,182,182,182,182,182,182,182,182,182,182,182,182,182,182,182, - 182,182,182,182,182,183,182,182,182,182,182,182,184,184,184,185, - 186, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, - 96, 96, 96, 96, 96,187,188,189,190,191,191,192, 96, 96, 96, 96, - 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,193,194, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 95, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, - 96, 96, 96, 96,195,196, 59,197,198,199,200,201,202, 96,203,204, - 205, 59, 59,206, 59,207,208,208,208,208,208,209, 96, 96, 96, 96, - 96, 96, 96, 96,210, 96,211,212,213, 96, 96,214, 96, 96, 96,215, - 96, 96, 96, 96, 96,216,217,218,219, 96, 96, 96, 96, 96,220,221, - 222, 96,223,224, 96, 96,225,226, 59,227,228, 96, 59, 59, 59, 59, - 59, 59, 59,229,230,231,232,233, 59, 59,234,235, 59,236, 96, 96, - 96, 96, 96, 96, 96, 96, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, - 70, 70, 70,237, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, - 70, 70, 70, 70,238, 70,239, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 97, 98, 99,100,101,101,102,103,104,105,106,107,108,109, + 110,111, 96,112,113,114,115,116,117,118,119,119,120,121,122,123, + 124,125,126,127,128,129,130,131,132, 96,133,134,135,136,137,138, + 139,140,141,142,143, 96,144,145, 96,146,147,148,149, 96,150,151, + 152,153,154,155,156, 96,157,158,159,160, 96,161,162,163,164,164, + 164,164,164,164,164,165,166,164,167, 96, 96, 96, 96, 96, 96, 96, + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,168,169,169, + 169,169,169,169,169,169,170, 96, 96, 96, 96, 96, 96, 96, 96, 96, + 96, 96, 96, 96, 96, 96,171,171,171,171,172, 96, 96, 96,173,173, + 173,173,174,175,176,177, 96, 96, 96, 96,178,179,180,181,182,182, + 182,182,182,182,182,182,182,182,182,182,182,182,182,182,182,182, + 182,182,182,182,182,182,182,182,182,182,182,182,182,183,182,182, + 182,182,182,182,184,184,184,185,186, 96, 96, 96, 96, 96, 96, 96, + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,187,188,189, + 190,191,191,192, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, + 96, 96, 96, 96, 96, 96,193,194, 96, 96, 96, 96, 96, 96, 96, 96, + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,195,196, 59,197, + 198,199,200,201,202, 96,203,204,205, 59, 59,206, 59,207,208,208, + 208,208,208,209, 96, 96, 96, 96, 96, 96, 96, 96,210, 96,211,212, + 213, 96, 96,214, 96, 96, 96,215, 96, 96, 96, 96, 96,216,217,218, + 219, 96, 96, 96, 96, 96,220,221,222, 96,223,224, 96, 96,225,226, + 59,227,228, 96, 59, 59, 59, 59, 59, 59, 59,229,230,231,232,233, + 59, 59,234,235, 59,236, 96, 96, 96, 96, 96, 96, 96, 96, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,237, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,238, 70,239, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, - 70, 70, 70,240, 70, 70, 70, 70, 70, 70, 70, 70, 70,241, 96, 96, - 96, 96, 96, 96, 96, 96, 70, 70, 70, 70,242, 96, 96, 96, 96, 96, - 96, 96, 96, 96, 96, 96, 70, 70, 70, 70, 70, 70,243, 70, 70, 70, - 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,244, 96, 96, - 96, 96, 96, 96, 96, 96,245, 96,246,247, 0, 1, 2, 2, 0, 1, - 2, 2, 2, 3, 4, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 19, 19, - 19, 19, 19, 19, 19, 0, 19, 0, 0, 0, 0, 0, 0, 0, 19, 19, - 19, 19, 19, 0, 0, 0, 0, 0, 26, 26, 0, 0, 0, 0, 1, 1, - 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 0, 9, 9, 9, 2, 2, - 9, 9, 9, 9, 0, 9, 2, 2, 2, 2, 9, 0, 9, 0, 9, 9, - 9, 2, 9, 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 2, 9, 9, 9, 9, 9, 9, 9, 55, 55, 55, 55, 55, 55, 55, 55, - 55, 55, 55, 55, 55, 55, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 1, 1, 6, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 4, 4, - 4, 2, 2, 4, 4, 4, 2, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 2, 2, 2, 2, 2, 2, 2, 2, 14, 14, - 14, 2, 2, 2, 2, 14, 14, 14, 14, 14, 14, 2, 2, 2, 3, 3, - 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 0, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 3, 3, 3, 0, 0, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 3, 3, 1, 3, 3, 3, 3, 3, 3, 3, 37, 37, - 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 2, 37, 37, 37, - 37, 2, 2, 37, 37, 37, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, - 2, 2, 2, 2, 2, 2, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, - 64, 2, 2, 64, 64, 64, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, - 90, 90, 90, 90, 2, 2, 90, 90, 90, 90, 90, 90, 90, 2, 95, 95, - 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 2, 2, 95, 2, 37, 37, - 37, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 2, 3, 3, - 2, 2, 2, 2, 2, 2, 3, 3, 0, 3, 3, 3, 3, 3, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 1, 1, 1, 1, 7, 7, 7, 7, 7, - 7, 7, 0, 0, 7, 7, 5, 5, 5, 5, 2, 5, 5, 5, 5, 5, - 5, 5, 5, 2, 2, 5, 5, 2, 2, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 2, 5, 5, 5, 5, 5, 5, 5, 2, - 5, 2, 2, 2, 5, 5, 5, 5, 2, 2, 5, 5, 5, 5, 5, 2, - 2, 5, 5, 5, 5, 2, 2, 2, 2, 2, 2, 2, 2, 5, 2, 2, - 2, 2, 5, 5, 2, 5, 5, 5, 5, 5, 2, 2, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 2, 2, 11, 11, 11, 2, 11, 11, 11, 11, 11, - 11, 2, 2, 2, 2, 11, 11, 2, 2, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 2, 11, 11, 11, 11, 11, 11, 11, 2, - 11, 11, 2, 11, 11, 2, 11, 11, 2, 2, 11, 2, 11, 11, 11, 2, - 2, 11, 11, 11, 2, 2, 2, 11, 2, 2, 2, 2, 2, 2, 2, 11, - 11, 11, 11, 2, 11, 2, 2, 2, 2, 2, 2, 2, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 2, 2, 10, 10, 10, 2, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 2, 10, 10, 10, 2, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 2, 10, 10, 10, 10, 10, 10, 10, 2, - 10, 10, 2, 10, 10, 10, 10, 10, 2, 2, 10, 10, 10, 10, 10, 10, - 2, 10, 10, 10, 2, 2, 10, 2, 2, 2, 2, 2, 2, 2, 10, 10, - 10, 10, 2, 2, 10, 10, 10, 10, 2, 2, 2, 2, 2, 2, 2, 10, - 10, 10, 10, 10, 10, 10, 2, 21, 21, 21, 2, 21, 21, 21, 21, 21, - 21, 21, 21, 2, 2, 21, 21, 2, 2, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 2, 21, 21, 21, 21, 21, 21, 21, 2, - 21, 21, 2, 21, 21, 21, 21, 21, 2, 2, 21, 21, 21, 21, 21, 2, - 2, 21, 21, 21, 2, 2, 2, 2, 2, 2, 2, 21, 21, 21, 2, 2, - 2, 2, 21, 21, 2, 21, 21, 21, 21, 21, 2, 2, 21, 21, 2, 2, - 22, 22, 2, 22, 22, 22, 22, 22, 22, 2, 2, 2, 22, 22, 22, 2, - 22, 22, 22, 22, 2, 2, 2, 22, 22, 2, 22, 2, 22, 22, 2, 2, - 2, 22, 22, 2, 2, 2, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, - 2, 2, 2, 2, 22, 22, 22, 2, 2, 2, 2, 2, 2, 22, 2, 2, - 2, 2, 2, 2, 22, 22, 22, 22, 22, 2, 2, 2, 2, 2, 23, 23, - 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 2, 23, 23, 23, 2, - 23, 23, 23, 23, 23, 23, 23, 23, 2, 2, 23, 23, 23, 23, 23, 2, - 23, 23, 23, 23, 2, 2, 2, 2, 2, 2, 2, 23, 23, 2, 23, 23, - 23, 2, 2, 23, 2, 2, 23, 23, 23, 23, 2, 2, 23, 23, 2, 2, - 2, 2, 2, 2, 2, 23, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 2, 16, 16, 16, 2, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 2, 16, 16, 16, 16, 16, 2, 2, 16, 16, 16, 16, 16, 2, - 16, 16, 16, 16, 2, 2, 2, 2, 2, 2, 2, 16, 16, 2, 16, 16, - 16, 16, 2, 2, 16, 16, 2, 16, 16, 16, 2, 2, 2, 2, 20, 20, - 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 2, 20, 20, 20, 2, - 20, 20, 20, 20, 20, 20, 2, 2, 2, 2, 20, 20, 20, 20, 20, 20, - 20, 20, 2, 2, 20, 20, 2, 36, 36, 36, 2, 36, 36, 36, 36, 36, - 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 2, 2, 2, - 36, 36, 36, 36, 36, 36, 36, 36, 2, 36, 36, 36, 36, 36, 36, 36, - 36, 36, 2, 36, 2, 2, 2, 2, 36, 2, 2, 2, 2, 36, 36, 36, - 36, 36, 36, 2, 36, 2, 2, 2, 2, 2, 2, 2, 36, 36, 2, 2, - 36, 36, 36, 2, 2, 2, 2, 24, 24, 24, 24, 24, 24, 24, 24, 24, - 24, 24, 24, 24, 24, 24, 24, 24, 24, 2, 2, 2, 2, 0, 24, 24, - 24, 24, 2, 2, 2, 2, 2, 18, 18, 2, 18, 2, 18, 18, 18, 18, - 18, 2, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, - 18, 18, 2, 18, 2, 18, 18, 18, 18, 18, 18, 18, 2, 2, 18, 18, - 18, 18, 18, 2, 18, 2, 18, 18, 18, 18, 18, 18, 18, 2, 18, 18, - 2, 2, 18, 18, 18, 18, 25, 25, 25, 25, 25, 25, 25, 25, 2, 25, - 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 2, 2, 2, 25, 25, - 25, 25, 25, 2, 25, 25, 25, 25, 25, 25, 25, 0, 0, 0, 0, 25, - 25, 2, 2, 2, 2, 2, 33, 33, 33, 33, 33, 33, 33, 33, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 2, 8, 2, 2, - 2, 2, 2, 8, 2, 2, 8, 8, 8, 0, 8, 8, 8, 8, 12, 12, - 12, 12, 12, 12, 12, 12, 30, 30, 30, 30, 30, 30, 30, 30, 30, 2, - 30, 30, 30, 30, 2, 2, 30, 30, 30, 30, 30, 30, 30, 2, 30, 30, - 30, 2, 2, 30, 30, 30, 30, 30, 30, 30, 30, 2, 2, 2, 30, 30, - 2, 2, 2, 2, 2, 2, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, - 29, 29, 29, 29, 2, 2, 28, 28, 28, 28, 28, 28, 28, 28, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 2, 2, 2, 35, 35, - 35, 35, 35, 35, 35, 35, 35, 35, 35, 0, 0, 0, 35, 35, 35, 2, - 2, 2, 2, 2, 2, 2, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, - 45, 45, 45, 45, 2, 2, 2, 2, 2, 2, 2, 2, 2, 45, 44, 44, - 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 0, 0, 2, 43, 43, - 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 2, 2, 2, 2, 46, 46, - 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 2, 46, 46, 46, 2, - 46, 46, 2, 2, 2, 2, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, - 31, 31, 31, 31, 2, 2, 31, 31, 2, 2, 2, 2, 2, 2, 32, 32, - 0, 0, 32, 0, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 2, 2, 2, 2, 2, 2, 32, 2, 2, 2, 2, 2, 2, 2, 32, 32, - 32, 2, 2, 2, 2, 2, 28, 28, 28, 28, 28, 28, 2, 2, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 2, 48, 48, - 48, 48, 2, 2, 2, 2, 48, 2, 2, 2, 48, 48, 48, 48, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 2, 2, 52, 52, - 52, 52, 52, 2, 2, 2, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 2, 2, 2, 2, 58, 58, 2, 2, 2, 2, 2, 2, 58, 58, - 58, 2, 2, 2, 58, 58, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 2, 2, 54, 54, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, - 91, 91, 91, 91, 91, 2, 91, 91, 91, 91, 91, 2, 2, 91, 91, 91, - 2, 2, 2, 2, 2, 2, 91, 91, 91, 91, 91, 91, 2, 2, 1, 1, - 1, 1, 1, 1, 1, 2, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, - 62, 62, 62, 2, 2, 2, 62, 62, 62, 62, 62, 62, 62, 2, 76, 76, - 76, 76, 76, 76, 76, 76, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, - 93, 93, 2, 2, 2, 2, 2, 2, 2, 2, 93, 93, 93, 93, 70, 70, - 70, 70, 70, 70, 70, 70, 2, 2, 2, 70, 70, 70, 70, 70, 70, 70, - 2, 2, 2, 70, 70, 70, 73, 73, 73, 73, 73, 73, 73, 73, 6, 2, - 2, 2, 2, 2, 2, 2, 8, 8, 8, 2, 2, 8, 8, 8, 1, 1, - 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, - 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, - 0, 2, 2, 2, 2, 2, 19, 19, 19, 19, 19, 19, 9, 9, 9, 9, - 9, 6, 19, 19, 19, 19, 19, 19, 19, 19, 19, 9, 9, 9, 9, 9, - 19, 19, 19, 19, 9, 9, 9, 9, 9, 19, 19, 19, 19, 19, 6, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 9, 9, 9, - 9, 9, 9, 9, 2, 2, 2, 9, 2, 9, 2, 9, 2, 9, 9, 9, - 9, 9, 9, 2, 9, 9, 9, 9, 9, 9, 2, 2, 9, 9, 9, 9, - 9, 9, 2, 9, 9, 9, 2, 2, 9, 9, 9, 2, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 2, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, - 0, 0, 0, 2, 0, 0, 0, 19, 2, 2, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 2, 19, 19, - 19, 19, 19, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, - 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, - 19, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 19, 0, - 0, 0, 2, 2, 2, 2, 0, 0, 0, 2, 2, 2, 2, 2, 27, 27, - 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, - 0, 0, 0, 0, 2, 0, 56, 56, 56, 56, 56, 56, 56, 56, 55, 55, - 55, 55, 2, 2, 2, 2, 2, 55, 55, 55, 55, 55, 55, 55, 61, 61, - 61, 61, 61, 61, 61, 61, 2, 2, 2, 2, 2, 2, 2, 61, 61, 2, - 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 2, 2, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 2, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 2, 2, 2, 2, 13, 13, 13, 13, 13, 13, 2, 2, 0, 0, - 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 0, 13, 0, 13, 0, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 1, 1, 1, 1, 12, 12, 13, 13, - 13, 13, 0, 0, 0, 0, 2, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 2, 2, 1, - 1, 0, 0, 15, 15, 15, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 17, 17, 17, 2, 2, - 2, 2, 2, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 2, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 2, 12, 12, - 12, 12, 12, 12, 12, 0, 17, 17, 17, 17, 17, 17, 17, 0, 39, 39, - 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 2, 2, 2, 39, 39, - 39, 39, 39, 39, 39, 2, 86, 86, 86, 86, 86, 86, 86, 86, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 2, 2, 2, 2, 79, 79, - 79, 79, 79, 79, 79, 79, 0, 0, 19, 19, 19, 19, 19, 19, 0, 0, - 0, 19, 19, 19, 19, 19, 19, 19, 19, 2, 2, 2, 2, 2, 19, 19, - 2, 19, 2, 19, 19, 19, 19, 19, 2, 2, 2, 2, 2, 2, 2, 2, - 19, 19, 19, 19, 19, 19, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, - 60, 60, 60, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 65, 65, - 65, 65, 65, 65, 65, 65, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, - 75, 75, 75, 75, 2, 2, 2, 2, 2, 2, 2, 2, 75, 75, 75, 75, - 2, 2, 2, 2, 2, 2, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, - 69, 69, 69, 69, 0, 69, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, - 74, 74, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 74, 12, 12, - 12, 12, 12, 2, 2, 2, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, - 84, 84, 84, 84, 2, 0, 84, 84, 2, 2, 2, 2, 84, 84, 33, 33, - 33, 33, 33, 33, 33, 2, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 2, 68, 68, 68, 68, 68, 68, 2, 2, 68, 68, - 2, 2, 68, 68, 68, 68, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, - 92, 2, 2, 2, 2, 2, 2, 2, 2, 92, 92, 92, 92, 92, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 2, 2, 30, - 30, 30, 30, 30, 30, 2, 19, 19, 19, 0, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 9, 19, 19, 19, 19, 0, 0, 2, 2, 2, 2, 87, 87, - 87, 87, 87, 87, 2, 2, 87, 87, 2, 2, 2, 2, 2, 2, 12, 12, - 12, 12, 2, 2, 2, 2, 2, 2, 2, 12, 12, 12, 12, 12, 13, 13, - 2, 2, 2, 2, 2, 2, 19, 19, 19, 19, 19, 19, 19, 2, 2, 2, - 2, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 2, 14, 14, 14, 14, 14, 2, 14, 2, 14, 14, - 2, 14, 14, 2, 14, 14, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, - 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 2, 2, - 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 3, 1, 1, - 1, 1, 1, 1, 6, 6, 0, 0, 0, 2, 0, 0, 0, 0, 3, 3, - 3, 3, 3, 2, 3, 3, 3, 3, 3, 3, 3, 2, 2, 0, 2, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 17, 17, - 17, 17, 17, 17, 0, 0, 2, 2, 12, 12, 12, 12, 12, 12, 2, 2, - 12, 12, 12, 2, 2, 2, 2, 0, 0, 0, 0, 0, 2, 2, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 2, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 2, 49, 49, 49, 2, 49, 49, 2, 49, 49, 49, - 49, 49, 49, 49, 2, 2, 49, 49, 49, 2, 2, 2, 2, 2, 0, 0, - 0, 2, 2, 2, 2, 0, 0, 0, 0, 0, 2, 2, 2, 0, 0, 0, - 0, 0, 0, 2, 2, 2, 9, 2, 2, 2, 2, 2, 2, 2, 0, 0, - 0, 0, 0, 1, 2, 2, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, - 71, 71, 71, 2, 2, 2, 67, 67, 67, 67, 67, 67, 67, 67, 67, 2, - 2, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 42, 42, - 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 42, 42, 42, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, - 41, 2, 2, 2, 2, 2,118,118,118,118,118,118,118,118,118,118, - 118, 2, 2, 2, 2, 2, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, - 53, 53, 53, 53, 2, 53, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, - 59, 59, 2, 2, 2, 2, 59, 59, 59, 59, 59, 59, 2, 2, 40, 40, - 40, 40, 40, 40, 40, 40, 51, 51, 51, 51, 51, 51, 51, 51, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 2, 2, 50, 50, - 2, 2, 2, 2, 2, 2,135,135,135,135,135,135,135,135,135,135, - 135,135, 2, 2, 2, 2,106,106,106,106,106,106,106,106,104,104, - 104,104,104,104,104,104,104,104,104,104, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2,104,161,161,161,161,161,161,161,161,161,161, - 161, 2,161,161,161,161,161,161,161, 2,161,161, 2,161,161,161, - 2,161,161,161,161,161,161,161, 2,161,161, 2, 2, 2,110,110, - 110,110,110,110,110,110,110,110,110,110,110,110,110, 2,110,110, - 110,110,110,110, 2, 2, 19, 19, 19, 19, 19, 19, 2, 19, 19, 2, - 19, 19, 19, 19, 19, 19, 47, 47, 47, 47, 47, 47, 2, 2, 47, 2, - 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, - 47, 47, 47, 47, 2, 47, 47, 2, 2, 2, 47, 2, 2, 47, 81, 81, - 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 2, 81,120,120, - 120,120,120,120,120,120,116,116,116,116,116,116,116,116,116,116, - 116,116,116,116,116, 2, 2, 2, 2, 2, 2, 2, 2,116,128,128, - 128,128,128,128,128,128,128,128,128, 2,128,128, 2, 2, 2, 2, - 2,128,128,128,128,128, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, - 66, 66, 2, 2, 2, 66, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, - 2, 2, 2, 2, 2, 72, 98, 98, 98, 98, 98, 98, 98, 98, 97, 97, - 97, 97, 97, 97, 97, 97, 2, 2, 2, 2, 97, 97, 97, 97, 2, 2, - 97, 97, 97, 97, 97, 97, 57, 57, 57, 57, 2, 57, 57, 2, 2, 2, - 2, 2, 57, 57, 57, 57, 57, 57, 57, 57, 2, 57, 57, 57, 2, 57, - 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 57, 57, 2, 2, 57, 57, 57, 2, 2, 2, 2, 57, 57, 2, - 2, 2, 2, 2, 2, 2, 88, 88, 88, 88, 88, 88, 88, 88,117,117, - 117,117,117,117,117,117,112,112,112,112,112,112,112,112,112,112, - 112,112,112,112,112, 2, 2, 2, 2,112,112,112,112,112, 78, 78, - 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 2, 2, 2, 78, - 78, 78, 78, 78, 78, 78, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, - 83, 83, 83, 83, 2, 2, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, - 82, 2, 2, 2, 2, 2,122,122,122,122,122,122,122,122,122,122, - 2, 2, 2, 2, 2, 2, 2,122,122,122,122, 2, 2, 2, 2,122, - 122,122,122,122,122,122, 89, 89, 89, 89, 89, 89, 89, 89, 89, 2, - 2, 2, 2, 2, 2, 2,130,130,130,130,130,130,130,130,130,130, - 130, 2, 2, 2, 2, 2, 2, 2,130,130,130,130,130,130,144,144, - 144,144,144,144,144,144,144,144, 2, 2, 2, 2, 2, 2,156,156, - 156,156,156,156,156,156,156,156, 2,156,156,156, 2, 2,156,156, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3,147,147, - 147,147,147,147,147,147,148,148,148,148,148,148,148,148,148,148, - 2, 2, 2, 2, 2, 2,158,158,158,158,158,158,158,158,158,158, - 2, 2, 2, 2, 2, 2,153,153,153,153,153,153,153,153,153,153, - 153,153, 2, 2, 2, 2,149,149,149,149,149,149,149,149,149,149, - 149,149,149,149,149, 2, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, - 94, 94, 94, 94, 2, 2, 2, 2, 94, 94, 94, 94, 94, 94, 2, 2, - 2, 2, 2, 2, 2, 94, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, - 85, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 85, 2, 2,101,101, - 101,101,101,101,101,101,101, 2, 2, 2, 2, 2, 2, 2,101,101, - 2, 2, 2, 2, 2, 2, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, - 96, 96, 96, 2, 96, 96,111,111,111,111,111,111,111,111,111,111, - 111,111,111,111,111, 2,100,100,100,100,100,100,100,100, 2, 36, - 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 2, 2, 2,108,108, - 108,108,108,108,108,108,108,108, 2,108,108,108,108,108,108,108, - 2, 2, 2, 2, 2, 2,129,129,129,129,129,129,129, 2,129, 2, - 129,129,129,129, 2,129,129,129,129,129,129,129,129,129,129,129, - 129,129,129,129, 2,129,129,129, 2, 2, 2, 2, 2, 2,109,109, - 109,109,109,109,109,109,109,109,109, 2, 2, 2, 2, 2,109,109, - 2, 2, 2, 2, 2, 2,107,107,107,107, 2,107,107,107,107,107, - 107,107,107, 2, 2,107,107, 2, 2,107,107,107,107,107,107,107, - 107,107,107,107,107,107,107, 2,107,107,107,107,107,107,107, 2, - 107,107, 2,107,107,107,107,107, 2, 1,107,107,107,107,107, 2, - 2,107,107,107, 2, 2,107, 2, 2, 2, 2, 2, 2,107, 2, 2, - 2, 2, 2,107,107,107,107,107,107,107, 2, 2,107,107,107,107, - 107,107,107, 2, 2, 2,137,137,137,137,137,137,137,137,137,137, - 137,137, 2,137,137,137,137,137, 2, 2, 2, 2, 2, 2,124,124, - 124,124,124,124,124,124,124,124, 2, 2, 2, 2, 2, 2,123,123, - 123,123,123,123,123,123,123,123,123,123,123,123, 2, 2,114,114, - 114,114,114,114,114,114,114,114,114,114,114, 2, 2, 2,114,114, - 2, 2, 2, 2, 2, 2, 32, 32, 32, 32, 32, 2, 2, 2,102,102, - 102,102,102,102,102,102,102,102, 2, 2, 2, 2, 2, 2,126,126, - 126,126,126,126,126,126,126,126,126, 2, 2,126,126,126,126,126, - 126,126, 2, 2, 2, 2,126,126,126,126,126,126,126, 2,142,142, - 142,142,142,142,142,142,142,142,142,142, 2, 2, 2, 2,125,125, - 125,125,125,125,125,125,125,125,125, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2,125,154,154,154,154,154,154,154, 2, 2,154, - 2, 2,154,154,154,154,154,154,154,154, 2,154,154, 2,154,154, - 154,154,154,154,154,154,154,154,154,154,154,154, 2,154,154, 2, - 2,154,154,154,154,154,154,154, 2, 2, 2, 2, 2, 2,150,150, - 150,150,150,150,150,150, 2, 2,150,150,150,150,150,150,150,150, - 150,150,150, 2, 2, 2,141,141,141,141,141,141,141,141,140,140, - 140,140,140,140,140,140,140,140,140, 2, 2, 2, 2, 2,121,121, - 121,121,121,121,121,121,121, 2, 2, 2, 2, 2, 2, 2, 7, 7, - 2, 2, 2, 2, 2, 2,133,133,133,133,133,133,133,133,133, 2, - 133,133,133,133,133,133,133,133,133,133,133,133,133, 2,133,133, - 133,133,133,133, 2, 2,133,133,133,133,133, 2, 2, 2,134,134, - 134,134,134,134,134,134, 2, 2,134,134,134,134,134,134, 2,134, - 134,134,134,134,134,134,134,134,134,134,134,134,134, 2,138,138, - 138,138,138,138,138, 2,138,138, 2,138,138,138,138,138,138,138, - 138,138,138,138,138,138, 2, 2,138, 2,138,138, 2,138,138,138, - 2, 2, 2, 2, 2, 2,143,143,143,143,143,143, 2,143,143, 2, - 143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143, - 143,143,143,143,143, 2,143,143, 2,143,143,143,143,143,143, 2, - 2, 2, 2, 2, 2, 2,143,143, 2, 2, 2, 2, 2, 2,145,145, - 145,145,145,145,145,145,145, 2, 2, 2, 2, 2, 2, 2,163,163, - 163,163,163,163,163,163,163, 2,163,163,163,163,163,163,163,163, - 163, 2, 2, 2,163,163,163,163, 2, 2, 2, 2, 2, 2, 86, 2, - 2, 2, 2, 2, 2, 2, 22, 22, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 22, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, - 2, 2, 2, 2, 2, 2, 63, 63, 63, 63, 63, 63, 63, 2, 63, 63, - 63, 63, 63, 2, 2, 2, 63, 63, 63, 63, 2, 2, 2, 2,157,157, - 157,157,157,157,157,157,157,157,157, 2, 2, 2, 2, 2, 80, 80, - 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 2, 2,127,127, - 127,127,127,127,127,127,127,127,127,127,127,127,127, 2, 79, 2, - 2, 2, 2, 2, 2, 2,115,115,115,115,115,115,115,115,115,115, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,240, 70, 70, 70, 70, + 70, 70, 70, 70, 70,241, 96, 96, 96, 96, 96, 96, 96, 96, 70, 70, + 70, 70,242, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 70, 70, + 70, 70, 70, 70,243, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70,244, 96, 96, 96, 96, 96, 96, 96, 96,245, 96, + 246,247, 0, 1, 2, 2, 0, 1, 2, 2, 2, 3, 4, 5, 0, 0, + 0, 0, 0, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 0, 0, 0, + 19, 0, 19, 0, 0, 0, 0, 0, 26, 26, 1, 1, 1, 1, 9, 9, + 9, 9, 0, 9, 9, 9, 2, 2, 9, 9, 9, 9, 0, 9, 2, 2, + 2, 2, 9, 0, 9, 0, 9, 9, 9, 2, 9, 2, 9, 9, 9, 9, + 2, 9, 9, 9, 55, 55, 55, 55, 55, 55, 6, 6, 6, 6, 6, 1, + 1, 6, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 2, 2, 2, 2, 14, 14, 2, + 2, 2, 3, 3, 3, 3, 3, 0, 3, 3, 0, 3, 3, 3, 3, 3, + 3, 0, 3, 3, 3, 1, 1, 1, 3, 3, 1, 3, 3, 3, 37, 37, + 37, 37, 37, 37, 2, 37, 37, 37, 37, 2, 2, 37, 37, 37, 38, 38, + 38, 38, 38, 38, 2, 2, 64, 64, 64, 64, 64, 64, 64, 2, 2, 64, + 64, 64, 90, 90, 90, 90, 90, 90, 2, 2, 90, 90, 90, 2, 95, 95, + 95, 95, 2, 2, 95, 2, 3, 3, 3, 2, 3, 3, 2, 2, 3, 3, + 0, 3, 7, 7, 7, 7, 7, 1, 1, 1, 1, 7, 7, 7, 0, 0, + 7, 7, 5, 5, 5, 5, 2, 5, 5, 5, 5, 2, 2, 5, 5, 2, + 5, 5, 5, 2, 5, 2, 2, 2, 5, 5, 5, 5, 2, 2, 5, 5, + 5, 2, 2, 2, 2, 5, 5, 5, 2, 5, 2, 11, 11, 11, 11, 11, + 11, 2, 2, 2, 2, 11, 11, 2, 2, 11, 11, 11, 11, 11, 11, 2, + 11, 11, 2, 11, 11, 2, 11, 11, 2, 2, 2, 11, 2, 2, 11, 2, + 11, 2, 2, 2, 11, 11, 2, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 2, 10, 10, 2, 10, 10, 10, 10, 2, 2, 10, 2, 2, 2, 2, 2, + 10, 10, 2, 21, 21, 21, 21, 21, 21, 21, 21, 2, 2, 21, 21, 2, + 21, 21, 21, 21, 2, 2, 21, 21, 2, 21, 2, 2, 21, 21, 2, 2, + 22, 22, 2, 22, 22, 22, 22, 22, 22, 2, 22, 2, 22, 22, 22, 22, + 2, 2, 2, 22, 22, 2, 2, 2, 2, 22, 22, 2, 2, 2, 22, 22, + 22, 22, 23, 23, 23, 23, 23, 2, 23, 23, 23, 23, 2, 2, 2, 23, + 23, 2, 23, 23, 23, 2, 2, 23, 2, 2, 2, 2, 23, 23, 2, 2, + 2, 23, 16, 16, 16, 16, 16, 2, 16, 16, 2, 16, 16, 16, 16, 16, + 2, 2, 2, 16, 16, 2, 2, 2, 16, 16, 20, 20, 20, 20, 20, 2, + 20, 20, 2, 2, 20, 20, 2, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 2, 2, 2, 36, 36, 36, 36, 2, 36, 2, 36, 2, 2, 2, 2, + 36, 2, 2, 2, 2, 36, 36, 2, 36, 2, 36, 2, 2, 2, 2, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 2, 2, 2, 2, 0, 2, 18, + 18, 2, 18, 2, 18, 18, 18, 18, 18, 2, 18, 18, 18, 18, 2, 18, + 2, 18, 18, 18, 2, 2, 18, 2, 18, 2, 25, 25, 25, 25, 2, 25, + 25, 25, 25, 2, 2, 2, 25, 2, 25, 25, 25, 0, 0, 0, 0, 25, + 25, 2, 33, 33, 33, 33, 8, 8, 8, 8, 8, 8, 2, 8, 2, 8, + 2, 2, 8, 8, 8, 0, 12, 12, 12, 12, 30, 30, 30, 30, 30, 2, + 30, 30, 30, 30, 2, 2, 30, 30, 30, 2, 2, 30, 30, 30, 30, 2, + 2, 2, 29, 29, 29, 29, 29, 29, 2, 2, 28, 28, 28, 28, 34, 34, + 34, 34, 34, 2, 2, 2, 35, 35, 35, 35, 35, 35, 35, 0, 0, 0, + 35, 35, 35, 2, 2, 2, 45, 45, 45, 45, 45, 45, 2, 2, 2, 2, + 2, 45, 44, 44, 44, 44, 44, 0, 0, 2, 43, 43, 43, 43, 46, 46, + 46, 46, 46, 2, 46, 46, 31, 31, 31, 31, 31, 31, 2, 2, 32, 32, + 0, 0, 32, 0, 32, 32, 32, 32, 32, 32, 32, 32, 2, 2, 32, 2, + 2, 2, 32, 32, 32, 2, 28, 28, 2, 2, 48, 48, 48, 48, 48, 48, + 48, 2, 48, 2, 2, 2, 52, 52, 52, 52, 52, 52, 2, 2, 52, 2, + 2, 2, 58, 58, 58, 58, 58, 58, 2, 2, 58, 58, 58, 2, 2, 2, + 58, 58, 54, 54, 54, 54, 2, 2, 54, 54, 91, 91, 91, 91, 91, 91, + 91, 2, 91, 2, 2, 91, 91, 91, 2, 2, 1, 1, 1, 2, 62, 62, + 62, 62, 62, 2, 2, 2, 62, 62, 62, 2, 76, 76, 76, 76, 93, 93, + 93, 93, 70, 70, 70, 70, 2, 2, 2, 70, 70, 70, 2, 2, 2, 70, + 70, 70, 73, 73, 73, 73, 6, 2, 2, 2, 8, 8, 8, 2, 2, 8, + 8, 8, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, + 0, 0, 1, 1, 0, 2, 19, 19, 9, 9, 9, 9, 9, 6, 19, 9, + 9, 9, 9, 9, 19, 19, 9, 9, 9, 19, 6, 19, 19, 19, 19, 19, + 19, 9, 9, 9, 2, 2, 2, 9, 2, 9, 2, 9, 9, 9, 1, 1, + 0, 0, 0, 2, 0, 0, 0, 19, 2, 2, 0, 0, 0, 19, 0, 0, + 0, 2, 19, 2, 2, 2, 0, 2, 2, 2, 1, 2, 2, 2, 0, 0, + 9, 0, 0, 0, 19, 19, 27, 27, 27, 27, 2, 2, 0, 0, 0, 0, + 2, 0, 56, 56, 56, 56, 2, 55, 55, 55, 61, 61, 61, 61, 2, 2, + 2, 61, 61, 2, 2, 2, 0, 0, 2, 2, 13, 13, 13, 13, 13, 13, + 2, 13, 13, 13, 2, 2, 0, 13, 0, 13, 0, 13, 13, 13, 13, 13, + 1, 1, 1, 1, 12, 12, 2, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 2, 2, 1, 1, 0, 0, 15, 15, 15, 0, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 0, 2, 26, 26, 26, 26, 26, 26, 26, 2, 12, + 12, 12, 12, 12, 12, 2, 12, 12, 12, 0, 39, 39, 39, 39, 39, 2, + 2, 2, 39, 39, 39, 2, 86, 86, 86, 86, 77, 77, 77, 77, 79, 79, + 79, 79, 19, 19, 19, 2, 19, 19, 2, 19, 2, 19, 19, 19, 19, 19, + 2, 2, 2, 2, 19, 19, 60, 60, 60, 60, 60, 2, 2, 2, 65, 65, + 65, 65, 75, 75, 75, 75, 75, 75, 2, 2, 2, 2, 75, 75, 69, 69, + 69, 69, 69, 69, 0, 69, 74, 74, 74, 74, 2, 2, 2, 74, 12, 2, + 2, 2, 84, 84, 84, 84, 84, 84, 2, 0, 84, 84, 2, 2, 2, 2, + 84, 84, 33, 33, 33, 2, 68, 68, 68, 68, 68, 68, 68, 2, 68, 68, + 2, 2, 92, 92, 92, 92, 92, 92, 92, 2, 2, 2, 2, 92, 87, 87, + 87, 87, 87, 87, 87, 2, 19, 9, 19, 19, 19, 19, 0, 0, 87, 87, + 2, 2, 2, 2, 2, 12, 2, 2, 2, 4, 14, 2, 14, 2, 14, 14, + 2, 14, 14, 2, 14, 14, 2, 2, 2, 3, 3, 3, 0, 0, 2, 2, + 3, 3, 1, 1, 6, 6, 3, 2, 3, 3, 3, 2, 2, 0, 2, 0, + 0, 0, 0, 0, 17, 17, 17, 17, 0, 0, 2, 2, 12, 12, 49, 49, + 49, 49, 2, 49, 49, 49, 49, 49, 49, 2, 49, 49, 2, 49, 49, 49, + 2, 2, 9, 2, 2, 2, 0, 1, 2, 2, 71, 71, 71, 71, 71, 2, + 2, 2, 67, 67, 67, 67, 67, 2, 2, 2, 42, 42, 42, 42, 2, 42, + 42, 42, 41, 41, 41, 41, 41, 41, 41, 2,118,118,118,118,118,118, + 118, 2, 53, 53, 53, 53, 53, 53, 2, 53, 59, 59, 59, 59, 59, 59, + 2, 2, 40, 40, 40, 40, 51, 51, 51, 51, 50, 50, 50, 50, 50, 50, + 2, 2,135,135,135,135,106,106,106,106,104,104,104,104, 2, 2, + 2,104,161,161,161,161,161,161,161, 2,161,161, 2,161,161, 2, + 2, 2,110,110,110,110,110,110,110, 2,110,110, 2, 2, 19, 2, + 19, 19, 47, 47, 47, 47, 47, 47, 2, 2, 47, 2, 47, 47, 47, 47, + 2, 47, 47, 2, 2, 2, 47, 2, 2, 47, 81, 81, 81, 81, 81, 81, + 2, 81,120,120,120,120,116,116,116,116,116,116,116, 2, 2, 2, + 2,116,128,128,128,128,128,128,128, 2,128,128, 2, 2, 2, 2, + 2,128, 66, 66, 66, 66, 2, 2, 2, 66, 72, 72, 72, 72, 72, 72, + 2, 2, 2, 2, 2, 72, 98, 98, 98, 98, 97, 97, 97, 97, 2, 2, + 97, 97, 57, 57, 57, 57, 2, 57, 57, 2, 2, 57, 57, 57, 57, 57, + 2, 2, 57, 57, 57, 2, 2, 2, 2, 57, 57, 2, 2, 2, 88, 88, + 88, 88,117,117,117,117,112,112,112,112,112,112,112, 2, 2, 2, + 2,112, 78, 78, 78, 78, 78, 78, 2, 2, 2, 78, 78, 78, 83, 83, + 83, 83, 83, 83, 2, 2, 82, 82, 82, 82, 82, 82, 82, 2,122,122, + 122,122,122,122, 2, 2, 2,122,122,122,122, 2, 2, 2, 89, 89, + 89, 89, 89, 2, 2, 2,130,130,130,130,130,130,130, 2, 2, 2, + 130,130,144,144,144,144,144,144, 2, 2,156,156,156,156,156,156, + 2,156,156,156, 2, 2, 2, 3, 3, 3,147,147,147,147,148,148, + 148,148,148,148, 2, 2,158,158,158,158,158,158, 2, 2,153,153, + 153,153,149,149,149,149,149,149,149, 2, 94, 94, 94, 94, 94, 94, + 2, 2, 2, 2, 94, 94, 2, 2, 2, 94, 85, 85, 85, 85, 85, 85, + 85, 2, 2, 85, 2, 2,101,101,101,101,101, 2, 2, 2,101,101, + 2, 2, 96, 96, 96, 96, 96, 2, 96, 96,111,111,111,111,111,111, + 111, 2,100,100,100,100,108,108,108,108,108,108, 2,108,108,108, + 2, 2,129,129,129,129,129,129,129, 2,129, 2,129,129,129,129, + 2,129,129,129, 2, 2,109,109,109,109,109,109,109, 2,109,109, + 2, 2,107,107,107,107, 2,107,107,107,107, 2, 2,107,107, 2, + 107,107,107,107, 2, 1,107,107, 2, 2,107, 2, 2, 2, 2, 2, + 2,107, 2, 2,107,107,137,137,137,137, 2,137,137,137,137,137, + 2, 2,124,124,124,124,124,124, 2, 2,123,123,123,123,123,123, + 2, 2,114,114,114,114,114, 2, 2, 2,114,114, 2, 2,102,102, + 102,102,102,102, 2, 2,126,126,126,126,126,126,126, 2, 2,126, + 126,126,142,142,142,142,125,125,125,125,125,125,125, 2, 2, 2, + 2,125,154,154,154,154,154,154,154, 2, 2,154, 2, 2, 2,154, + 154, 2,154,154, 2,154,154, 2, 2,154,154,154, 2, 2,150,150, + 150,150, 2, 2,150,150,150, 2, 2, 2,141,141,141,141,140,140, + 140,140,140,140,140, 2,121,121,121,121,121, 2, 2, 2, 7, 7, + 2, 2,133,133,133,133,133, 2,133,133,133,133,133, 2,133,133, + 2, 2,133, 2, 2, 2,134,134,134,134, 2, 2,134,134, 2,134, + 134,134,134,134,134, 2,138,138,138,138,138,138,138, 2,138,138, + 2,138, 2, 2,138, 2,138,138, 2, 2,143,143,143,143,143,143, + 2,143,143, 2,143,143,143,143,143, 2,143, 2, 2, 2,143,143, + 2, 2,145,145,145,145,145, 2, 2, 2,163,163,163,163,163, 2, + 163,163,163,163,163, 2, 2, 2,163,163,163,163, 2, 2, 86, 2, + 2, 2, 63, 63, 63, 63, 63, 63, 2, 2, 63, 63, 63, 2, 63, 2, + 2, 2,157,157,157,157,157,157,157, 2, 80, 80, 80, 80, 80, 80, + 2, 2,127,127,127,127,127,127,127, 2, 79, 2, 2, 2,115,115, 115,115,115,115,115, 2,115,115, 2, 2, 2, 2,115,115,159,159, - 159,159,159,159,159,159,159,159,159,159,159,159,159, 2,159,159, - 2, 2, 2, 2, 2, 2,103,103,103,103,103,103,103,103,103,103, - 103,103,103,103, 2, 2,119,119,119,119,119,119,119,119,119,119, - 119,119,119,119, 2, 2,119,119, 2,119,119,119,119,119, 2, 2, - 2, 2, 2,119,119,119,146,146,146,146,146,146,146,146,146,146, - 146, 2, 2, 2, 2, 2, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, - 99, 2, 2, 2, 2, 99, 2, 2, 2, 2, 2, 2, 2, 99,136,139, - 13, 13,155, 2, 2, 2,136,136,136,136,136,136,136,136,155,155, - 155,155,155,155,155,155,155,155,155,155,155,155, 2, 2,136, 2, - 2, 2, 2, 2, 2, 2, 17, 17, 17, 17, 2, 17, 17, 17, 17, 17, - 17, 17, 2, 17, 17, 2, 17, 15, 15, 15, 15, 15, 15, 15, 17, 17, - 17, 2, 2, 2, 2, 2, 2, 2, 15, 2, 2, 2, 2, 2, 15, 15, - 15, 2, 2, 17, 2, 2, 2, 2, 2, 2, 17, 17, 17, 17,139,139, - 139,139,139,139,139,139,139,139,139,139, 2, 2, 2, 2,105,105, - 105,105,105,105,105,105,105,105,105, 2, 2, 2, 2, 2,105,105, - 105,105,105, 2, 2, 2,105, 2, 2, 2, 2, 2, 2, 2,105,105, - 2, 2,105,105,105,105, 1, 1, 1, 1, 1, 1, 2, 2, 0, 0, - 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, - 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 2, 2, - 0, 2, 2, 0, 0, 2, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, - 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, - 0, 2, 2, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 2, 0, 0, - 0, 0, 0, 2, 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 2, - 0, 0, 0, 0, 0, 0,131,131,131,131,131,131,131,131,131,131, - 131,131, 2, 2, 2, 2, 2, 2, 2,131,131,131,131,131, 2,131, - 131,131,131,131,131,131, 2, 2, 2, 2, 2, 19, 19, 19, 56, 56, - 56, 56, 56, 56, 56, 2, 56, 2, 2, 56, 56, 56, 56, 56, 56, 56, - 2, 56, 56, 2, 56, 56, 56, 56, 56, 2, 2, 2, 2, 2, 6, 6, - 6, 6, 6, 6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6,151,151, - 151,151,151,151,151,151,151,151,151,151,151, 2, 2, 2,151,151, - 151,151,151,151, 2, 2,151,151, 2, 2, 2, 2,151,151,160,160, - 160,160,160,160,160,160,160,160,160,160,160,160,160, 2,152,152, - 152,152,152,152,152,152,152,152, 2, 2, 2, 2, 2,152,164,164, - 164,164,164,164,164,164,164,164, 2, 2, 2, 2, 2, 2, 30, 30, - 30, 30, 2, 30, 30, 2,113,113,113,113,113,113,113,113,113,113, - 113,113,113, 2, 2,113,113,113,113,113,113,113,113, 2,132,132, - 132,132,132,132,132,132,132,132,132,132, 2, 2, 2, 2,132,132, - 2, 2, 2, 2,132,132, 3, 3, 3, 3, 2, 3, 3, 3, 2, 3, - 3, 2, 3, 2, 2, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 2, 3, 3, 3, 3, 2, 3, 2, 3, 2, 2, 2, 2, 2, 2, - 3, 2, 2, 2, 2, 3, 2, 3, 2, 3, 2, 3, 3, 3, 2, 3, - 2, 3, 2, 3, 2, 3, 2, 3, 3, 3, 3, 2, 3, 2, 3, 3, - 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 3, - 3, 3, 2, 3, 3, 3, 2, 2, 2, 2, 2, 2, 0, 0, 15, 0, - 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 2, 2, - 2, 0, 0, 0, 0, 0, 13, 2, 2, 2, 2, 2, 2, 2, 13, 13, - 13, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 0, 1, - 2, 3, 4, 5, 6, 7, 8, 9, 9, 9, 9, 10, 9, 11, 12, 13, - 9, 9, 9, 14, 9, 9, 15, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 159,159,159,159,159, 2,159,159, 2, 2,103,103,103,103,103,103, + 2, 2,119,119,119,119,119,119, 2, 2,119,119, 2,119, 2,119, + 119,119,146,146,146,146,146,146,146, 2, 99, 99, 99, 99, 99, 99, + 99, 2, 2, 2, 2, 99,136,139, 13, 13,155, 2, 2, 2,136,136, + 136,136,155,155,155,155,155,155, 2, 2,136, 2, 2, 2, 2, 17, + 17, 17, 2, 17, 17, 2, 17, 15, 15, 15, 17, 17, 17, 2, 2, 2, + 15, 2, 2, 17, 2, 2,139,139,139,139,105,105,105,105,105,105, + 105, 2,105, 2, 2, 2,105,105, 2, 2, 1, 1, 2, 2, 0, 0, + 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 2, 2, 0, 2, 2, 0, + 0, 2, 0, 2, 0, 2,131,131,131,131, 2, 2, 2,131, 2,131, + 131,131, 56, 56, 56, 2, 56, 2, 2, 56, 56, 56, 2, 56, 56, 2, + 56, 56, 6, 6, 2, 2, 2, 2, 2, 6,151,151,151,151,151, 2, + 2, 2,151,151, 2, 2, 2, 2,151,151,160,160,160,160,160,160, + 160, 2,152,152,152,152,152,152, 2, 2, 2, 2, 2,152,164,164, + 164,164,164,164, 2, 2, 2, 30, 30, 2,113,113,113,113,113, 2, + 2,113,113,113,113, 2,132,132,132,132,132,132, 2, 2, 2, 2, + 132,132, 2, 3, 3, 2, 3, 2, 2, 3, 2, 3, 2, 3, 2, 2, + 3, 2, 3, 2, 3, 2, 3, 3, 2, 3, 15, 0, 0, 2, 13, 2, + 2, 2, 13, 13, 13, 2, 2, 0, 2, 2, 0, 1, 2, 3, 4, 5, + 6, 7, 8, 9, 9, 9, 9, 10, 9, 11, 12, 13, 9, 9, 9, 14, + 9, 9, 15, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 16, 17, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 18, 19, 20, 9, 21, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 16, 17, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 18, 19, 20, 9, 21, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 22, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 22, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, @@ -3922,60 +3702,60 @@ _hb_ucd_u8[17868] = 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 23, 24, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, - 9, 10, 11, 12, 0, 0, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 23, 0, 0, 24, 25, 26, 27, 28, 29, 30, 0, 0, 31, 32, 0, 33, - 0, 34, 0, 35, 0, 0, 0, 0, 36, 37, 38, 39, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 41, 42, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 44, - 0, 45, 0, 0, 0, 0, 0, 0, 46, 47, 0, 0, 0, 0, 0, 48, - 0, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 50, 51, 0, 0, 0, 52, 0, 0, 53, 0, 0, 0, 0, 0, 0, 0, - 54, 0, 0, 0, 0, 0, 0, 0, 55, 0, 0, 0, 0, 0, 0, 0, - 56, 0, 0, 0, 0, 0, 0, 0, 0, 57, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 58, 59, 60, 61, 62, 63, 64, 65, 0, 0, 0, 0, 0, 0, 66, 0, + 9, 9, 9, 9, 9, 9, 23, 24, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, + 0, 0, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 0, 0, 24, + 25, 26, 27, 28, 29, 30, 0, 0, 31, 32, 0, 33, 0, 34, 0, 35, + 0, 0, 0, 0, 36, 37, 38, 39, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 41, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 44, 0, 45, 0, 0, + 0, 0, 0, 0, 46, 47, 0, 0, 0, 0, 0, 48, 0, 49, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 51, 0, 0, + 0, 52, 0, 0, 53, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 0, + 0, 0, 0, 0, 55, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, + 0, 0, 0, 0, 0, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 58, 59, 60, 61, + 62, 63, 64, 65, 0, 0, 0, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 68, 0, 69, - 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71, 72, 73, 74, - 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, - 91, 92, 93, 94, 95, 96, 97, 98, 99,100,101,102,103, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,104, 0, - 0, 0, 0, 0, 0,105,106, 0,107, 0, 0, 0,108, 0,109, 0, - 110, 0,111,112,113, 0,114, 0, 0, 0,115, 0, 0, 0,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0,117, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 67, 68, 0, 69, 70, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 71, 72, 73, 74, 75, 76, 77, 78, + 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, + 95, 96, 97, 98, 99,100,101,102,103, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,104, 0, 0, 0, 0, 0, + 0,105,106, 0,107, 0, 0, 0,108, 0,109, 0,110, 0,111,112, + 113, 0,114, 0, 0, 0,115, 0, 0, 0,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 118,119,120,121, 0,122,123,124,125,126, 0,127, 0, 0, 0, 0, + 0, 0, 0, 0, 0,117, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,118,119,120,121, + 0,122,123,124,125,126, 0,127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128,129,130,131, - 132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147, - 148,149,150,151,152,153,154,155,156,157, 0, 0, 0,158,159,160, - 161, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0,162,163, 0, 0, 0, 0, 0, 0, 0,164, 0, + 0, 0, 0, 0, 0, 0, 0, 0,128,129,130,131,132,133,134,135, + 136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151, + 152,153,154,155,156,157, 0, 0, 0,158,159,160,161, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0,162,163, 0, 0, 0, 0, 0, 0, 0,164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 165, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0,166, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0,167, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,168, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,165, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0,166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0,167, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0,169,170, 0, 0, 0, 0,171,172, 0, 0, 0,173,174,175,176, - 177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192, - 193,194,195,196,197,198,199,200,201,202,203,204,205,206, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,169,170, 0, + 0, 0, 0,171,172, 0, 0, 0,173,174,175,176,177,178,179,180, + 181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196, + 197,198,199,200,201,202,203,204,205,206, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, + 0, 0, 0, 0, 1, 2, 3, 4, }; static const uint16_t -_hb_ucd_u16[9320] = +_hb_ucd_u16[10040] = { 0, 0, 1, 2, 3, 4, 5, 6, 0, 0, 7, 8, 9, 10, 11, 12, 13, 13, 13, 14, 15, 13, 13, 16, 17, 18, 19, 20, 21, 22, 13, 23, @@ -4104,255 +3884,300 @@ _hb_ucd_u16[9320] = 48, 48, 48, 48, 71, 48, 48, 48, 48, 48, 48, 140, 140, 140, 140, 140, 683, 140, 570, 570, 570, 570, 570, 570, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 140, 391, 391, 391, 391, 391, 391, 391, 684, - 391, 391, 391, 391, 391, 391, 391, 685, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 2, 2, 3, 1, 2, 2, 3, 0, 0, 0, 0, 0, 4, 0, 4, - 2, 2, 5, 2, 2, 2, 5, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, - 0, 0, 0, 0, 7, 8, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 10, 11, 12, 13, 14, 14, 15, 14, 14, 14, - 14, 14, 14, 14, 16, 17, 14, 14, 18, 18, 18, 18, 18, 18, 18, 18, - 18, 18, 18, 18, 18, 18, 18, 18, 19, 18, 18, 18, 18, 18, 18, 18, - 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 20, 21, - 21, 21, 22, 20, 21, 21, 21, 21, 21, 23, 24, 25, 25, 25, 25, 25, - 25, 26, 25, 25, 25, 27, 28, 26, 29, 30, 31, 32, 31, 31, 31, 31, - 33, 34, 35, 31, 31, 31, 36, 31, 31, 31, 31, 31, 31, 31, 31, 31, - 31, 31, 31, 29, 31, 31, 31, 31, 37, 38, 37, 37, 37, 37, 37, 37, - 37, 39, 31, 31, 31, 31, 31, 31, 40, 40, 40, 40, 40, 40, 41, 26, - 42, 42, 42, 42, 42, 42, 42, 43, 44, 44, 44, 44, 44, 45, 44, 46, - 47, 47, 47, 48, 37, 49, 31, 31, 31, 50, 51, 31, 31, 31, 31, 31, - 31, 31, 31, 31, 52, 31, 31, 31, 53, 53, 53, 53, 53, 53, 53, 53, - 53, 53, 54, 53, 55, 53, 53, 53, 56, 57, 58, 59, 59, 60, 61, 62, - 57, 63, 64, 65, 66, 59, 59, 67, 68, 69, 70, 71, 71, 72, 73, 74, - 69, 75, 76, 77, 78, 71, 79, 26, 80, 81, 82, 83, 83, 84, 85, 86, - 81, 87, 88, 26, 89, 83, 90, 91, 92, 93, 94, 95, 95, 96, 97, 98, - 93, 99, 100, 101, 102, 95, 95, 26, 103, 104, 105, 106, 107, 104, 108, 109, - 104, 105, 110, 26, 111, 108, 108, 112, 113, 114, 115, 113, 113, 115, 113, 116, - 114, 117, 118, 119, 120, 113, 121, 113, 122, 123, 124, 122, 122, 124, 125, 126, - 123, 127, 128, 128, 129, 122, 130, 26, 131, 132, 133, 131, 131, 131, 131, 131, - 132, 133, 134, 131, 135, 131, 131, 131, 136, 137, 138, 139, 137, 137, 140, 141, - 138, 142, 143, 137, 144, 137, 145, 26, 146, 147, 147, 147, 147, 147, 147, 148, - 147, 147, 147, 149, 26, 26, 26, 26, 150, 151, 152, 152, 153, 152, 152, 154, - 155, 156, 152, 157, 26, 26, 26, 26, 158, 158, 158, 158, 158, 158, 158, 158, - 158, 159, 158, 158, 158, 160, 159, 158, 158, 158, 158, 159, 158, 158, 158, 161, - 158, 161, 162, 163, 26, 26, 26, 26, 164, 164, 164, 164, 164, 164, 164, 164, - 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 165, 165, 165, 165, - 166, 167, 165, 165, 165, 165, 165, 168, 169, 169, 169, 169, 169, 169, 169, 169, - 169, 169, 169, 169, 169, 169, 169, 169, 170, 170, 170, 170, 170, 170, 170, 170, - 170, 171, 172, 171, 170, 170, 170, 170, 170, 171, 170, 170, 170, 170, 171, 172, - 171, 170, 172, 170, 170, 170, 170, 170, 170, 170, 171, 170, 170, 170, 170, 170, - 170, 170, 170, 173, 170, 170, 170, 174, 170, 170, 170, 175, 176, 176, 176, 176, - 176, 176, 176, 176, 176, 176, 177, 177, 178, 178, 178, 178, 178, 178, 178, 178, - 178, 178, 178, 178, 178, 178, 178, 178, 179, 179, 179, 180, 181, 181, 181, 181, - 181, 181, 181, 181, 181, 182, 181, 183, 184, 184, 185, 186, 187, 187, 188, 26, - 189, 189, 190, 26, 191, 192, 193, 26, 194, 194, 194, 194, 194, 194, 194, 194, - 194, 194, 194, 195, 194, 196, 194, 196, 197, 198, 198, 199, 198, 198, 198, 198, - 198, 198, 198, 198, 198, 198, 198, 200, 198, 198, 198, 198, 198, 201, 178, 178, - 178, 178, 178, 178, 178, 178, 202, 26, 203, 203, 203, 204, 203, 205, 203, 205, - 206, 203, 207, 207, 207, 208, 209, 26, 210, 210, 210, 210, 210, 211, 210, 210, - 210, 212, 210, 213, 194, 194, 194, 194, 214, 214, 214, 215, 216, 216, 216, 216, - 216, 216, 216, 217, 216, 216, 216, 218, 216, 219, 216, 219, 216, 220, 9, 9, - 9, 221, 26, 26, 26, 26, 26, 26, 222, 222, 222, 222, 222, 222, 222, 222, - 222, 223, 222, 222, 222, 222, 222, 224, 225, 225, 225, 225, 225, 225, 225, 225, - 226, 226, 226, 226, 226, 226, 227, 228, 229, 229, 229, 229, 229, 229, 229, 230, - 229, 231, 232, 232, 232, 232, 232, 232, 18, 233, 165, 165, 165, 165, 165, 234, - 225, 26, 235, 9, 236, 237, 238, 239, 2, 2, 2, 2, 240, 241, 2, 2, - 2, 2, 2, 242, 243, 244, 2, 245, 2, 2, 2, 2, 2, 2, 2, 246, - 9, 9, 9, 9, 9, 9, 9, 9, 14, 14, 247, 247, 14, 14, 14, 14, - 247, 247, 14, 248, 14, 14, 14, 247, 14, 14, 14, 14, 14, 14, 249, 14, - 249, 14, 250, 251, 14, 14, 252, 253, 0, 254, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 255, 0, 256, 257, 0, 258, 2, 259, 0, 0, 0, 0, - 260, 26, 9, 9, 9, 9, 261, 26, 0, 0, 0, 0, 262, 263, 4, 0, - 0, 264, 0, 0, 2, 2, 2, 2, 2, 265, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 258, 26, 26, 26, - 0, 266, 26, 26, 0, 0, 0, 0, 267, 267, 267, 267, 267, 267, 267, 267, - 267, 267, 267, 267, 267, 267, 267, 267, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 268, 0, 0, 0, 269, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 270, 270, 270, 270, 270, 270, 270, 270, - 270, 270, 270, 270, 2, 2, 2, 2, 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 271, 272, 165, 165, 165, 165, 166, 167, 273, 273, - 273, 273, 273, 273, 273, 274, 275, 274, 170, 170, 172, 26, 172, 172, 172, 172, - 172, 172, 172, 172, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 276, 26, 26, 26, 26, 277, 277, 277, 278, 277, 277, 277, 277, - 277, 277, 277, 277, 277, 277, 279, 26, 277, 277, 277, 277, 277, 277, 277, 277, - 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, - 277, 277, 280, 26, 26, 26, 0, 281, 282, 0, 0, 0, 283, 284, 0, 285, - 286, 287, 287, 287, 287, 287, 287, 287, 287, 287, 288, 289, 290, 291, 291, 291, - 291, 291, 291, 291, 291, 291, 291, 292, 293, 294, 294, 294, 294, 294, 295, 169, - 169, 169, 169, 169, 169, 169, 169, 169, 169, 296, 0, 0, 294, 294, 294, 294, - 0, 0, 0, 0, 281, 26, 291, 291, 169, 169, 169, 296, 0, 0, 0, 0, - 0, 0, 0, 0, 169, 169, 169, 297, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 291, 291, 291, 291, 291, 298, 291, 291, 291, 291, 291, 291, 291, 291, - 291, 291, 291, 0, 0, 0, 0, 0, 277, 277, 277, 277, 277, 277, 277, 277, - 0, 0, 0, 0, 0, 0, 0, 0, 299, 299, 299, 299, 299, 299, 299, 299, - 299, 299, 299, 299, 299, 299, 299, 299, 299, 300, 299, 299, 299, 299, 299, 299, - 301, 26, 302, 302, 302, 302, 302, 302, 303, 303, 303, 303, 303, 303, 303, 303, - 303, 303, 303, 303, 303, 303, 303, 303, 303, 303, 303, 303, 303, 304, 26, 26, - 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 305, 305, 305, 305, - 305, 305, 305, 305, 305, 305, 305, 26, 0, 0, 0, 0, 306, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 307, 2, 2, 2, 2, 2, 2, - 2, 308, 309, 310, 26, 26, 311, 2, 312, 312, 312, 312, 312, 313, 0, 314, - 315, 315, 315, 315, 315, 315, 315, 26, 316, 316, 316, 316, 316, 316, 316, 316, - 317, 318, 316, 319, 53, 53, 53, 53, 320, 320, 320, 320, 320, 321, 322, 322, - 322, 322, 323, 324, 169, 169, 169, 325, 326, 326, 326, 326, 326, 326, 326, 326, - 326, 327, 326, 328, 164, 164, 164, 329, 330, 330, 330, 330, 330, 330, 331, 26, - 330, 332, 330, 333, 164, 164, 164, 164, 334, 334, 334, 334, 334, 334, 334, 334, - 335, 26, 26, 336, 337, 337, 338, 26, 339, 339, 339, 26, 172, 172, 2, 2, - 2, 2, 2, 340, 341, 342, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, - 337, 337, 337, 337, 337, 343, 337, 344, 169, 169, 169, 169, 345, 26, 169, 169, - 296, 346, 169, 169, 169, 169, 169, 345, 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, 277, 277, 277, 277, 277, 277, 277, 277, - 277, 277, 277, 277, 277, 280, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, - 277, 277, 277, 347, 26, 26, 26, 26, 348, 26, 349, 350, 25, 25, 351, 352, - 353, 25, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, - 354, 26, 355, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, - 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 356, - 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 357, 31, 31, 31, 31, 31, - 31, 358, 26, 26, 26, 26, 31, 31, 9, 9, 0, 314, 9, 359, 0, 0, - 0, 0, 360, 0, 258, 281, 361, 31, 31, 31, 31, 31, 31, 31, 31, 31, - 31, 31, 31, 31, 31, 31, 31, 362, 363, 0, 0, 0, 1, 2, 2, 3, - 1, 2, 2, 3, 364, 291, 290, 291, 291, 291, 291, 365, 169, 169, 169, 296, - 366, 366, 366, 367, 258, 258, 26, 368, 369, 370, 369, 369, 371, 369, 369, 372, - 369, 373, 369, 373, 26, 26, 26, 26, 369, 369, 369, 369, 369, 369, 369, 369, - 369, 369, 369, 369, 369, 369, 369, 374, 375, 0, 0, 0, 0, 0, 376, 0, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 253, 0, 377, 378, 26, 26, 26, - 26, 26, 0, 0, 0, 0, 0, 379, 380, 380, 380, 381, 382, 382, 382, 382, - 382, 382, 383, 26, 384, 0, 0, 281, 385, 385, 385, 385, 386, 387, 388, 388, - 388, 389, 390, 390, 390, 390, 390, 391, 392, 392, 392, 393, 394, 394, 394, 394, - 395, 394, 396, 26, 26, 26, 26, 26, 397, 397, 397, 397, 397, 397, 397, 397, - 397, 397, 398, 398, 398, 398, 398, 398, 399, 399, 399, 400, 399, 401, 402, 402, - 402, 402, 403, 402, 402, 402, 402, 403, 404, 404, 404, 404, 404, 26, 405, 405, - 405, 405, 405, 405, 406, 407, 408, 409, 408, 409, 410, 408, 411, 408, 411, 412, - 26, 26, 26, 26, 26, 26, 26, 26, 413, 413, 413, 413, 413, 413, 413, 413, - 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 414, 26, - 413, 413, 415, 26, 413, 26, 26, 26, 416, 2, 2, 2, 2, 2, 417, 308, - 26, 26, 26, 26, 26, 26, 26, 26, 418, 419, 420, 420, 420, 420, 421, 422, - 423, 423, 424, 423, 425, 425, 425, 425, 426, 426, 426, 427, 428, 426, 26, 26, - 26, 26, 26, 26, 429, 429, 430, 431, 432, 432, 432, 433, 434, 434, 434, 435, - 26, 26, 26, 26, 26, 26, 26, 26, 436, 436, 436, 436, 437, 437, 437, 438, - 437, 437, 439, 437, 437, 437, 437, 437, 440, 441, 442, 443, 444, 444, 445, 446, - 444, 447, 444, 447, 448, 448, 448, 448, 449, 449, 449, 449, 26, 26, 26, 26, - 450, 450, 450, 450, 451, 452, 451, 26, 453, 453, 453, 453, 453, 453, 454, 455, - 456, 456, 457, 456, 458, 458, 459, 458, 460, 460, 461, 462, 26, 463, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, 464, 464, 464, 464, 464, 464, 464, 464, - 464, 465, 26, 26, 26, 26, 26, 26, 466, 466, 466, 466, 466, 466, 467, 26, - 466, 466, 466, 466, 466, 466, 467, 468, 469, 469, 469, 469, 469, 26, 469, 470, - 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 31, 31, 31, 50, 471, 471, 471, 471, 471, 472, 473, 26, - 26, 26, 26, 26, 26, 26, 26, 474, 475, 475, 475, 475, 475, 26, 476, 476, - 476, 476, 476, 477, 26, 26, 478, 478, 478, 479, 26, 26, 26, 26, 480, 480, - 480, 481, 26, 26, 482, 482, 483, 26, 484, 484, 484, 484, 484, 484, 484, 484, - 484, 485, 486, 484, 484, 484, 485, 487, 488, 488, 488, 488, 488, 488, 488, 488, - 489, 490, 491, 491, 491, 492, 491, 493, 494, 494, 494, 494, 494, 494, 495, 494, - 494, 26, 496, 496, 496, 496, 497, 26, 498, 498, 498, 498, 498, 498, 498, 498, - 498, 498, 498, 498, 499, 137, 500, 26, 501, 501, 502, 501, 501, 501, 501, 501, - 503, 26, 26, 26, 26, 26, 26, 26, 504, 505, 506, 507, 506, 508, 509, 509, - 509, 509, 509, 509, 509, 510, 509, 511, 512, 513, 514, 515, 515, 516, 517, 518, - 513, 519, 520, 521, 522, 523, 523, 26, 524, 524, 524, 524, 524, 524, 524, 524, - 524, 524, 524, 525, 526, 26, 26, 26, 527, 527, 527, 527, 527, 527, 527, 527, - 527, 26, 527, 528, 26, 26, 26, 26, 529, 529, 529, 529, 529, 529, 530, 529, - 529, 529, 529, 530, 26, 26, 26, 26, 531, 531, 531, 531, 531, 531, 531, 531, - 532, 26, 531, 533, 198, 534, 26, 26, 535, 535, 535, 535, 535, 535, 535, 536, - 535, 536, 26, 26, 26, 26, 26, 26, 537, 537, 537, 538, 537, 539, 537, 537, - 540, 26, 26, 26, 26, 26, 26, 26, 541, 541, 541, 541, 541, 541, 541, 542, - 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 543, 543, 543, 543, - 543, 543, 543, 543, 543, 543, 544, 545, 546, 547, 548, 549, 549, 549, 550, 551, - 546, 26, 549, 552, 26, 26, 26, 26, 26, 26, 26, 26, 553, 554, 553, 553, - 553, 553, 553, 554, 555, 26, 26, 26, 556, 556, 556, 556, 556, 556, 556, 556, - 556, 26, 557, 557, 557, 557, 557, 557, 557, 557, 557, 557, 558, 26, 178, 178, - 559, 559, 559, 559, 559, 559, 559, 560, 53, 561, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, 562, 563, 562, 562, 562, 562, 564, 562, - 565, 26, 562, 562, 562, 566, 567, 567, 567, 567, 568, 567, 567, 569, 570, 26, - 26, 26, 26, 26, 26, 26, 26, 26, 571, 572, 573, 573, 573, 573, 571, 574, - 573, 26, 573, 575, 576, 577, 578, 578, 578, 579, 580, 581, 578, 582, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 583, 583, 583, 584, 585, 585, 586, 585, 585, 585, 585, 587, - 585, 585, 585, 588, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 589, 26, - 108, 108, 108, 108, 108, 108, 590, 591, 592, 592, 592, 592, 592, 592, 592, 592, - 592, 592, 592, 592, 592, 592, 592, 592, 592, 592, 592, 593, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, 592, 592, 592, 592, 592, 592, 592, 592, - 592, 592, 592, 592, 592, 594, 595, 26, 592, 592, 592, 592, 592, 592, 592, 592, - 596, 26, 26, 26, 26, 26, 26, 26, 26, 26, 597, 597, 597, 597, 597, 597, - 597, 597, 597, 597, 597, 597, 598, 26, 599, 599, 599, 599, 599, 599, 599, 599, - 599, 599, 599, 599, 599, 599, 599, 599, 599, 599, 599, 599, 599, 599, 599, 599, - 599, 599, 600, 26, 26, 26, 26, 26, 601, 601, 601, 601, 601, 601, 601, 601, - 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, - 602, 26, 26, 26, 26, 26, 26, 26, 305, 305, 305, 305, 305, 305, 305, 305, - 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 603, - 604, 604, 604, 605, 604, 606, 607, 607, 607, 607, 607, 607, 607, 607, 607, 608, - 607, 609, 610, 610, 610, 611, 611, 26, 612, 612, 612, 612, 612, 612, 612, 612, - 613, 26, 612, 614, 614, 612, 612, 615, 612, 612, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 617, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, 618, 618, 618, 618, 618, 618, 618, 618, - 618, 619, 618, 618, 618, 618, 618, 618, 618, 620, 618, 618, 26, 26, 26, 26, - 26, 26, 26, 26, 621, 26, 347, 26, 622, 622, 622, 622, 622, 622, 622, 622, - 622, 622, 622, 622, 622, 622, 622, 622, 622, 622, 622, 622, 622, 622, 622, 622, - 622, 622, 622, 622, 622, 622, 622, 26, 623, 623, 623, 623, 623, 623, 623, 623, - 623, 623, 623, 623, 623, 623, 623, 623, 623, 623, 623, 623, 623, 623, 623, 623, - 623, 623, 624, 26, 26, 26, 26, 26, 622, 625, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 626, 627, 628, 287, 287, 287, 287, 287, 287, 287, - 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, - 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, 629, 26, 630, 26, - 26, 26, 631, 26, 632, 26, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, - 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, - 633, 633, 633, 633, 633, 633, 633, 634, 635, 635, 635, 635, 635, 635, 635, 635, - 635, 635, 635, 635, 635, 636, 635, 637, 635, 638, 635, 639, 281, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, 9, 9, 9, 9, 9, 640, 9, 9, - 221, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 281, 26, 26, 26, 26, 26, 26, 26, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 276, 26, 0, 0, 0, 0, 258, 363, 0, 0, - 0, 0, 0, 0, 641, 642, 0, 643, 644, 645, 0, 0, 0, 646, 0, 0, - 0, 0, 0, 0, 0, 266, 26, 26, 14, 14, 14, 14, 14, 14, 14, 14, - 247, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 0, 0, 281, 26, 0, 0, 281, 26, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 258, 26, 0, 0, 0, 260, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 255, 647, 648, 0, 649, - 650, 0, 0, 0, 0, 0, 0, 0, 269, 651, 255, 255, 0, 0, 0, 652, - 653, 654, 655, 0, 0, 0, 0, 0, 0, 0, 0, 0, 276, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 268, 0, 0, 0, 0, 0, 0, 656, 656, 656, 656, 656, 656, 656, 656, - 656, 656, 656, 656, 656, 656, 656, 656, 656, 657, 26, 658, 659, 656, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, 2, 2, 2, 348, 660, 308, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, 661, 270, 270, 662, 663, 664, 18, 18, - 18, 18, 18, 18, 18, 665, 26, 26, 26, 666, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, 667, 667, 667, 667, 667, 668, 667, 669, - 667, 670, 26, 26, 26, 26, 26, 26, 26, 26, 671, 671, 671, 672, 26, 26, - 673, 673, 673, 673, 673, 673, 673, 674, 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 675, 675, 675, 675, 675, 676, 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 172, 677, 170, 172, 678, 678, 678, 678, 678, 678, 678, 678, - 678, 678, 678, 678, 678, 678, 678, 678, 678, 678, 678, 678, 678, 678, 678, 678, - 679, 678, 680, 26, 26, 26, 26, 26, 681, 681, 681, 681, 681, 681, 681, 681, - 681, 682, 681, 683, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 363, 0, 0, 0, 0, 0, 0, 0, 377, 26, - 26, 26, 26, 26, 26, 26, 26, 26, 363, 0, 0, 0, 0, 0, 0, 276, - 26, 26, 26, 26, 26, 26, 26, 26, 684, 31, 31, 31, 685, 686, 687, 688, - 689, 690, 685, 691, 685, 687, 687, 692, 31, 693, 31, 694, 695, 693, 31, 694, - 26, 26, 26, 26, 26, 26, 51, 26, 0, 0, 0, 0, 0, 281, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 281, 26, 0, 258, 363, 0, - 363, 0, 363, 0, 0, 0, 276, 26, 0, 0, 0, 0, 0, 276, 26, 26, - 26, 26, 26, 26, 696, 0, 0, 0, 697, 26, 0, 0, 0, 0, 0, 281, - 0, 260, 314, 26, 276, 26, 26, 26, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 698, 0, 377, 0, 377, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 258, 699, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 314, 0, 281, 260, 26, 0, 281, 0, 0, 0, 0, 0, 0, - 0, 26, 0, 314, 0, 0, 0, 0, 0, 26, 0, 0, 0, 276, 314, 26, - 26, 26, 26, 26, 26, 26, 26, 26, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 281, 26, 0, 276, 0, 377, 0, 260, 0, 0, 0, 0, 0, 269, - 276, 696, 0, 281, 0, 260, 0, 260, 0, 0, 360, 0, 0, 0, 0, 0, - 0, 266, 26, 26, 26, 26, 0, 314, 277, 277, 277, 277, 277, 277, 277, 277, - 277, 277, 277, 277, 26, 26, 26, 26, 277, 277, 277, 277, 277, 277, 277, 347, - 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 280, 277, 277, 277, 277, - 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 347, 26, 277, 277, - 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, - 277, 277, 277, 277, 700, 26, 26, 26, 277, 277, 277, 280, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, 277, 277, 277, 277, 277, 277, 277, 277, - 277, 701, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, 702, 26, 26, 26, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 391, 391, 391, 391, 391, 391, 391, 685, 0, 0, 0, 0, 1, 2, 1, 2, + 0, 0, 3, 3, 4, 5, 4, 5, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 6, 0, 0, 7, 0, 8, 8, 8, 8, 8, 8, 8, 9, + 10, 11, 12, 11, 11, 11, 13, 11, 14, 14, 14, 14, 14, 14, 14, 14, + 15, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 16, 17, 18, 17, 17, + 19, 20, 21, 21, 22, 21, 23, 24, 25, 26, 27, 27, 28, 29, 27, 30, + 27, 27, 27, 27, 27, 31, 27, 27, 32, 33, 33, 33, 34, 27, 27, 27, + 35, 35, 35, 36, 37, 37, 37, 38, 39, 39, 40, 41, 42, 43, 44, 27, + 45, 46, 27, 27, 27, 27, 47, 27, 48, 48, 48, 48, 48, 49, 50, 48, + 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, + 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, + 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, + 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 109, 110, 111, 112, 109, + 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 122, 123, 122, 124, 125, 125, + 126, 127, 128, 129, 130, 131, 125, 125, 132, 132, 132, 132, 133, 132, 134, 135, + 132, 133, 132, 136, 136, 137, 125, 125, 138, 138, 138, 138, 138, 138, 138, 138, + 138, 138, 139, 139, 140, 139, 139, 141, 142, 142, 142, 142, 142, 142, 142, 142, + 143, 143, 143, 143, 144, 145, 143, 143, 144, 143, 143, 146, 147, 148, 143, 143, + 143, 147, 143, 143, 143, 149, 143, 150, 143, 151, 152, 152, 152, 152, 152, 153, + 154, 154, 154, 154, 154, 154, 154, 154, 155, 156, 157, 157, 157, 157, 158, 159, + 160, 161, 162, 163, 164, 165, 166, 167, 168, 168, 168, 168, 168, 169, 170, 170, + 171, 172, 173, 173, 173, 173, 173, 174, 173, 173, 175, 154, 154, 154, 154, 176, + 177, 178, 179, 179, 180, 181, 182, 183, 184, 184, 185, 184, 186, 187, 168, 168, + 188, 189, 190, 190, 190, 191, 190, 192, 193, 193, 194, 8, 195, 125, 125, 125, + 196, 196, 196, 196, 197, 196, 196, 198, 199, 199, 199, 199, 200, 200, 200, 201, + 202, 202, 202, 203, 204, 205, 205, 205, 206, 139, 139, 207, 208, 209, 210, 211, + 4, 4, 212, 4, 4, 213, 214, 215, 4, 4, 4, 216, 8, 8, 8, 8, + 11, 217, 11, 11, 217, 218, 11, 219, 11, 11, 11, 220, 220, 221, 11, 222, + 223, 0, 0, 0, 0, 0, 224, 225, 226, 227, 0, 0, 228, 8, 8, 229, + 0, 0, 230, 231, 232, 0, 4, 4, 233, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 234, 125, 235, 125, 0, 0, + 236, 236, 236, 236, 236, 236, 236, 236, 0, 0, 0, 0, 0, 0, 0, 237, + 0, 238, 0, 0, 0, 0, 0, 0, 239, 239, 239, 239, 239, 239, 4, 4, + 240, 240, 240, 240, 240, 240, 240, 241, 139, 139, 140, 242, 242, 242, 243, 244, + 143, 245, 246, 246, 246, 246, 14, 14, 0, 0, 0, 0, 0, 247, 125, 125, + 248, 249, 248, 248, 248, 248, 248, 250, 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 251, 125, 252, 253, 0, 254, 255, 256, 257, 257, 257, + 257, 258, 259, 260, 260, 260, 260, 261, 262, 263, 263, 264, 142, 142, 142, 142, + 265, 0, 263, 263, 0, 0, 266, 260, 142, 265, 0, 0, 0, 0, 142, 267, + 0, 0, 0, 0, 0, 260, 260, 268, 260, 260, 260, 260, 260, 269, 0, 0, + 248, 248, 248, 248, 0, 0, 0, 0, 270, 270, 270, 270, 270, 270, 270, 270, + 271, 270, 270, 270, 272, 273, 273, 273, 274, 274, 274, 274, 274, 274, 274, 274, + 274, 274, 275, 125, 14, 14, 14, 14, 14, 14, 276, 276, 276, 276, 276, 277, + 0, 0, 278, 4, 4, 4, 4, 4, 279, 4, 4, 4, 280, 281, 125, 282, + 283, 283, 284, 285, 286, 286, 286, 287, 288, 288, 288, 288, 289, 290, 48, 48, + 291, 291, 292, 293, 293, 294, 142, 295, 296, 296, 296, 296, 297, 298, 138, 299, + 300, 300, 300, 301, 302, 303, 138, 138, 304, 304, 304, 304, 305, 306, 307, 308, + 309, 310, 246, 4, 4, 311, 312, 152, 152, 152, 152, 152, 307, 307, 313, 314, + 142, 142, 315, 142, 316, 142, 142, 317, 125, 125, 125, 125, 125, 125, 125, 125, + 248, 248, 248, 248, 248, 248, 318, 248, 248, 248, 248, 248, 248, 319, 125, 125, + 320, 321, 21, 322, 323, 27, 27, 27, 27, 27, 27, 27, 324, 325, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 326, 27, 27, 27, 27, + 27, 327, 27, 27, 328, 125, 125, 27, 8, 285, 329, 0, 0, 330, 331, 332, + 27, 27, 27, 27, 27, 27, 27, 333, 334, 0, 1, 2, 1, 2, 335, 259, + 260, 336, 142, 265, 337, 338, 339, 340, 341, 342, 343, 344, 345, 345, 125, 125, + 342, 342, 342, 342, 342, 342, 342, 346, 347, 0, 0, 348, 11, 11, 11, 11, + 349, 350, 351, 125, 125, 0, 0, 352, 353, 354, 355, 355, 355, 356, 357, 252, + 358, 358, 359, 360, 361, 362, 362, 363, 364, 365, 366, 366, 367, 368, 125, 125, + 369, 369, 369, 369, 369, 370, 370, 370, 371, 372, 373, 374, 374, 375, 374, 376, + 377, 377, 378, 379, 379, 379, 380, 381, 381, 382, 383, 384, 125, 125, 125, 125, + 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 386, 385, 387, 388, 125, + 389, 4, 4, 390, 125, 125, 125, 125, 391, 392, 392, 393, 394, 395, 396, 396, + 397, 398, 399, 125, 125, 125, 400, 401, 402, 403, 404, 405, 125, 125, 125, 125, + 406, 406, 407, 408, 407, 409, 407, 407, 410, 411, 412, 413, 414, 414, 415, 415, + 416, 416, 125, 125, 417, 417, 418, 419, 420, 420, 420, 421, 422, 423, 424, 425, + 426, 427, 428, 125, 125, 125, 125, 125, 429, 429, 429, 429, 430, 125, 125, 125, + 431, 431, 431, 432, 431, 431, 431, 433, 434, 434, 435, 436, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 27, 45, 437, 437, 438, 439, 125, 125, 125, 440, + 441, 441, 442, 443, 443, 444, 125, 445, 446, 125, 125, 447, 448, 125, 449, 450, + 451, 451, 451, 451, 452, 453, 451, 454, 455, 455, 455, 455, 456, 457, 458, 459, + 460, 460, 460, 461, 462, 463, 463, 464, 465, 465, 465, 465, 465, 465, 466, 467, + 468, 469, 468, 468, 470, 125, 125, 125, 471, 472, 473, 474, 474, 474, 475, 476, + 477, 478, 479, 480, 481, 482, 483, 484, 485, 485, 485, 485, 485, 486, 487, 125, + 488, 488, 488, 488, 489, 490, 125, 125, 491, 491, 491, 492, 491, 493, 125, 125, + 494, 494, 494, 494, 495, 496, 497, 125, 498, 498, 498, 499, 499, 125, 125, 125, + 500, 501, 502, 500, 503, 125, 125, 125, 504, 504, 504, 505, 125, 125, 125, 125, + 125, 125, 506, 506, 506, 506, 506, 507, 508, 509, 510, 511, 512, 513, 125, 125, + 125, 125, 514, 515, 515, 514, 516, 125, 517, 517, 517, 517, 518, 519, 519, 519, + 519, 519, 520, 154, 521, 521, 521, 522, 523, 125, 125, 125, 125, 125, 125, 125, + 524, 525, 525, 526, 527, 525, 528, 529, 529, 530, 531, 532, 125, 125, 125, 125, + 533, 534, 534, 535, 536, 537, 538, 539, 540, 541, 542, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 543, 544, 545, 546, 545, 547, 545, 548, 125, 125, + 125, 125, 125, 549, 550, 550, 550, 551, 552, 552, 552, 552, 552, 552, 552, 552, + 552, 553, 125, 125, 125, 125, 125, 125, 552, 552, 552, 552, 552, 552, 554, 555, + 552, 552, 552, 552, 556, 125, 125, 125, 125, 557, 557, 557, 557, 557, 557, 558, + 559, 559, 559, 559, 559, 559, 559, 559, 559, 559, 559, 559, 559, 560, 125, 125, + 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 562, 125, 125, 125, + 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 563, 564, 565, 566, 567, + 567, 567, 567, 568, 569, 570, 571, 572, 573, 573, 573, 573, 574, 575, 576, 577, + 573, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 578, 578, 578, 578, + 578, 579, 125, 125, 125, 125, 125, 125, 580, 580, 580, 580, 581, 580, 580, 580, + 582, 580, 125, 125, 125, 125, 583, 584, 585, 585, 585, 585, 585, 585, 585, 585, + 585, 585, 585, 585, 585, 585, 585, 586, 587, 587, 587, 587, 587, 587, 587, 587, + 587, 587, 587, 587, 587, 588, 125, 125, 589, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 590, 591, 257, 257, 257, 257, 257, 257, 257, + 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 592, 593, 125, 594, 595, 596, + 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 597, + 598, 598, 598, 598, 598, 598, 599, 600, 601, 602, 266, 125, 125, 125, 125, 125, + 8, 8, 603, 8, 604, 0, 0, 0, 0, 0, 0, 0, 266, 125, 125, 125, + 0, 0, 0, 0, 0, 0, 0, 605, 0, 0, 606, 0, 0, 0, 607, 608, + 609, 0, 610, 0, 0, 0, 235, 125, 11, 11, 11, 11, 611, 125, 125, 125, + 125, 125, 125, 125, 0, 266, 0, 266, 0, 0, 0, 0, 0, 234, 0, 612, + 0, 0, 0, 0, 0, 224, 0, 0, 0, 613, 614, 615, 616, 0, 0, 0, + 617, 618, 0, 619, 620, 621, 0, 0, 0, 0, 622, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 623, 0, 0, 0, 624, 624, 624, 624, 624, 624, 624, 624, + 625, 626, 627, 125, 125, 125, 125, 125, 4, 628, 629, 125, 125, 125, 125, 125, + 630, 631, 632, 14, 14, 14, 633, 125, 634, 125, 125, 125, 125, 125, 125, 125, + 635, 635, 636, 637, 638, 125, 125, 125, 125, 639, 640, 125, 641, 641, 641, 642, + 125, 125, 125, 125, 125, 643, 643, 644, 125, 125, 125, 125, 125, 125, 645, 646, + 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 648, 649, 125, 125, + 650, 650, 650, 650, 651, 652, 125, 125, 125, 125, 125, 125, 125, 125, 125, 334, + 0, 0, 0, 653, 125, 125, 125, 125, 334, 0, 0, 247, 125, 125, 125, 125, + 654, 27, 655, 656, 657, 658, 659, 660, 661, 662, 663, 662, 125, 125, 125, 664, + 0, 0, 252, 0, 0, 0, 0, 0, 0, 266, 226, 334, 334, 334, 0, 605, + 0, 0, 247, 125, 125, 125, 665, 0, 666, 0, 0, 252, 612, 667, 605, 125, + 0, 0, 0, 0, 0, 668, 350, 350, 0, 0, 0, 0, 0, 0, 0, 669, + 0, 0, 0, 0, 0, 285, 252, 228, 252, 0, 0, 0, 670, 285, 0, 0, + 670, 0, 247, 667, 125, 125, 125, 125, 0, 0, 0, 0, 0, 266, 247, 350, + 612, 0, 0, 671, 672, 252, 612, 612, 0, 330, 0, 0, 235, 125, 125, 285, + 248, 248, 248, 248, 248, 248, 125, 125, 248, 248, 248, 319, 248, 248, 248, 248, + 248, 318, 248, 248, 248, 248, 248, 248, 248, 248, 584, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 673, 125, 248, 318, 125, 125, 125, 125, 125, 125, + 248, 248, 248, 248, 674, 248, 248, 248, 248, 248, 248, 125, 125, 125, 125, 125, + 675, 125, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 1, 2, 2, 2, + 2, 2, 3, 0, 0, 0, 4, 0, 2, 2, 2, 2, 2, 3, 2, 2, + 2, 2, 5, 0, 2, 5, 6, 0, 7, 7, 7, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 8, 8, 8, 8, 16, 8, 8, 8, 17, 18, 18, 18, + 19, 19, 19, 19, 19, 20, 19, 19, 21, 22, 22, 22, 22, 22, 22, 22, + 22, 23, 21, 22, 22, 22, 23, 21, 24, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 12, 12, 25, 25, 26, 27, 25, 28, 12, 12, 29, 30, 29, 31, + 29, 29, 32, 32, 29, 29, 29, 29, 31, 29, 33, 7, 7, 34, 29, 29, + 35, 29, 29, 29, 29, 29, 29, 30, 36, 36, 36, 37, 36, 36, 36, 36, + 36, 36, 38, 39, 40, 40, 40, 40, 41, 12, 12, 12, 42, 42, 42, 42, + 42, 42, 43, 44, 45, 45, 45, 45, 45, 45, 45, 46, 45, 45, 45, 47, + 48, 48, 48, 48, 48, 48, 48, 49, 36, 36, 38, 12, 29, 29, 29, 50, + 51, 12, 29, 29, 52, 29, 29, 29, 53, 53, 53, 53, 54, 55, 53, 53, + 53, 56, 53, 53, 57, 58, 57, 59, 59, 57, 57, 57, 57, 57, 60, 57, + 61, 62, 63, 57, 57, 59, 59, 64, 12, 65, 12, 66, 57, 62, 57, 57, + 57, 57, 57, 64, 67, 67, 68, 69, 70, 71, 71, 71, 71, 71, 72, 71, + 72, 73, 74, 72, 68, 69, 70, 74, 75, 12, 67, 76, 12, 77, 71, 71, + 71, 68, 12, 12, 78, 78, 79, 80, 80, 79, 79, 79, 79, 79, 81, 79, + 81, 78, 82, 79, 79, 80, 80, 82, 83, 12, 12, 12, 79, 84, 79, 79, + 82, 12, 78, 79, 85, 85, 86, 87, 87, 86, 86, 86, 86, 86, 88, 86, + 88, 85, 89, 86, 86, 87, 87, 89, 12, 85, 12, 90, 86, 91, 86, 86, + 86, 86, 12, 12, 92, 93, 94, 92, 95, 96, 97, 95, 98, 99, 94, 92, + 100, 100, 96, 92, 94, 92, 95, 96, 99, 98, 12, 12, 12, 92, 100, 100, + 100, 100, 94, 12, 101, 101, 101, 102, 102, 101, 101, 101, 101, 101, 102, 101, + 101, 101, 103, 101, 101, 102, 102, 103, 12, 104, 105, 106, 101, 107, 101, 101, + 12, 108, 101, 101, 109, 109, 109, 110, 110, 109, 109, 109, 109, 109, 110, 109, + 109, 111, 112, 109, 109, 110, 110, 112, 12, 113, 12, 113, 109, 114, 109, 109, + 111, 12, 12, 12, 115, 115, 115, 116, 116, 115, 115, 115, 115, 115, 115, 115, + 115, 116, 116, 115, 12, 115, 115, 115, 115, 117, 115, 115, 118, 118, 119, 119, + 119, 120, 121, 119, 119, 119, 119, 119, 122, 119, 119, 123, 119, 120, 124, 125, + 119, 126, 119, 119, 12, 121, 119, 119, 121, 127, 12, 12, 128, 129, 129, 129, + 129, 129, 129, 129, 129, 129, 130, 131, 129, 129, 129, 12, 12, 12, 12, 12, + 132, 133, 134, 135, 135, 135, 135, 135, 135, 136, 135, 135, 135, 135, 135, 137, + 135, 138, 135, 134, 135, 135, 137, 135, 139, 139, 139, 139, 139, 139, 140, 139, + 139, 139, 139, 141, 140, 139, 139, 139, 139, 139, 139, 142, 139, 143, 144, 12, + 145, 145, 145, 145, 146, 146, 146, 146, 146, 147, 12, 148, 146, 146, 149, 146, + 150, 150, 150, 150, 151, 151, 151, 151, 151, 151, 152, 153, 151, 154, 152, 153, + 152, 153, 151, 154, 152, 153, 151, 151, 151, 154, 151, 151, 151, 151, 154, 155, + 151, 151, 151, 156, 151, 151, 153, 12, 157, 157, 157, 157, 157, 158, 157, 158, + 159, 159, 159, 159, 160, 160, 160, 160, 160, 160, 160, 161, 162, 162, 162, 162, + 162, 162, 163, 164, 162, 162, 165, 12, 166, 166, 166, 166, 166, 167, 12, 168, + 169, 169, 169, 169, 169, 170, 12, 12, 171, 171, 171, 171, 171, 12, 12, 12, + 172, 172, 172, 173, 173, 12, 12, 12, 174, 174, 174, 174, 174, 174, 174, 175, + 174, 174, 175, 12, 176, 177, 178, 178, 178, 178, 179, 12, 178, 178, 178, 178, + 178, 178, 180, 12, 178, 178, 181, 12, 159, 182, 12, 12, 183, 183, 183, 183, + 183, 183, 183, 184, 183, 183, 183, 12, 185, 183, 183, 183, 186, 186, 186, 186, + 186, 186, 186, 187, 186, 188, 12, 12, 189, 189, 189, 189, 189, 189, 189, 12, + 189, 189, 190, 12, 189, 189, 191, 192, 193, 193, 193, 193, 193, 193, 193, 194, + 195, 195, 195, 195, 195, 195, 195, 196, 195, 195, 195, 197, 195, 195, 198, 12, + 195, 195, 195, 198, 7, 7, 7, 199, 200, 200, 200, 200, 200, 200, 200, 201, + 200, 200, 200, 202, 203, 203, 203, 203, 204, 204, 204, 204, 204, 12, 12, 204, + 205, 205, 205, 205, 205, 205, 206, 205, 205, 205, 207, 208, 209, 209, 209, 209, + 19, 19, 210, 12, 146, 146, 211, 212, 203, 203, 12, 12, 213, 7, 7, 7, + 214, 7, 215, 216, 0, 215, 217, 12, 2, 218, 219, 2, 2, 2, 2, 220, + 221, 218, 222, 2, 2, 2, 223, 2, 2, 2, 2, 224, 8, 225, 8, 225, + 8, 8, 226, 226, 8, 8, 8, 225, 8, 15, 8, 8, 8, 10, 8, 227, + 10, 15, 8, 14, 0, 0, 0, 228, 0, 229, 0, 0, 230, 0, 0, 231, + 0, 0, 0, 232, 2, 2, 2, 233, 234, 12, 12, 12, 235, 12, 12, 12, + 0, 236, 237, 0, 4, 0, 0, 0, 0, 0, 0, 4, 2, 2, 5, 12, + 0, 232, 12, 12, 0, 0, 232, 12, 238, 238, 238, 238, 0, 239, 0, 0, + 0, 240, 0, 0, 241, 241, 241, 241, 18, 18, 18, 18, 18, 12, 242, 18, + 243, 243, 243, 243, 243, 243, 12, 244, 245, 12, 12, 244, 151, 154, 12, 12, + 151, 154, 151, 154, 0, 0, 0, 246, 247, 247, 247, 247, 247, 247, 248, 247, + 247, 12, 12, 12, 247, 249, 12, 12, 0, 0, 0, 12, 0, 250, 0, 0, + 251, 247, 252, 253, 0, 0, 247, 0, 254, 255, 255, 255, 255, 255, 255, 255, + 255, 256, 257, 258, 259, 260, 260, 260, 260, 260, 260, 260, 260, 260, 261, 259, + 12, 262, 263, 263, 263, 263, 263, 263, 264, 150, 150, 150, 150, 150, 150, 265, + 0, 12, 12, 12, 150, 150, 150, 266, 260, 260, 260, 261, 260, 260, 0, 0, + 267, 267, 267, 267, 267, 267, 267, 268, 267, 269, 12, 12, 270, 270, 270, 270, + 271, 271, 271, 271, 271, 271, 271, 12, 272, 272, 272, 272, 272, 272, 12, 12, + 237, 2, 2, 2, 2, 2, 231, 2, 2, 2, 273, 12, 274, 275, 276, 12, + 277, 2, 2, 2, 278, 278, 278, 278, 278, 278, 278, 279, 0, 0, 246, 12, + 280, 280, 280, 280, 280, 280, 12, 12, 281, 281, 281, 281, 281, 282, 12, 283, + 281, 281, 282, 12, 284, 284, 284, 284, 284, 284, 284, 285, 286, 286, 286, 286, + 286, 12, 12, 287, 150, 150, 150, 288, 289, 289, 289, 289, 289, 289, 289, 290, + 289, 289, 291, 292, 145, 145, 145, 293, 294, 294, 294, 294, 294, 295, 12, 12, + 294, 294, 294, 296, 294, 294, 296, 294, 297, 297, 297, 297, 298, 12, 12, 12, + 12, 12, 299, 297, 300, 300, 300, 300, 300, 301, 12, 12, 155, 154, 155, 154, + 155, 154, 12, 12, 2, 2, 3, 2, 2, 302, 303, 12, 300, 300, 300, 304, + 300, 300, 304, 12, 150, 12, 12, 12, 150, 265, 305, 150, 150, 150, 150, 12, + 247, 247, 247, 249, 247, 247, 249, 12, 2, 273, 12, 12, 306, 22, 12, 24, + 25, 26, 25, 307, 308, 309, 25, 25, 50, 12, 12, 12, 310, 29, 29, 29, + 29, 29, 29, 311, 312, 29, 29, 29, 29, 29, 12, 310, 7, 7, 7, 313, + 232, 0, 0, 0, 0, 232, 0, 12, 29, 314, 29, 29, 29, 29, 29, 315, + 316, 0, 0, 0, 0, 317, 260, 260, 260, 260, 260, 318, 319, 150, 319, 150, + 319, 150, 319, 288, 0, 232, 0, 232, 12, 12, 316, 246, 320, 320, 320, 321, + 320, 320, 320, 320, 320, 322, 320, 320, 320, 320, 322, 323, 320, 320, 320, 324, + 320, 320, 322, 12, 232, 131, 0, 0, 0, 131, 0, 0, 8, 8, 8, 14, + 0, 0, 0, 234, 325, 12, 12, 12, 0, 0, 0, 326, 327, 327, 327, 327, + 327, 327, 327, 328, 329, 329, 329, 329, 330, 12, 12, 12, 215, 0, 0, 0, + 331, 331, 331, 331, 331, 12, 12, 332, 333, 333, 333, 333, 333, 333, 334, 12, + 335, 335, 335, 335, 335, 335, 336, 12, 337, 337, 337, 337, 337, 337, 337, 338, + 339, 339, 339, 339, 339, 12, 339, 339, 339, 340, 12, 12, 341, 341, 341, 341, + 342, 342, 342, 342, 343, 343, 343, 343, 343, 343, 343, 344, 343, 343, 344, 12, + 345, 345, 345, 345, 345, 12, 345, 345, 345, 345, 345, 12, 346, 346, 346, 346, + 346, 346, 12, 12, 347, 347, 347, 347, 347, 12, 12, 348, 349, 349, 350, 349, + 350, 351, 349, 349, 351, 349, 349, 349, 351, 349, 351, 352, 353, 353, 353, 353, + 353, 354, 12, 12, 353, 355, 12, 12, 353, 353, 12, 12, 2, 274, 2, 2, + 356, 2, 273, 12, 357, 358, 359, 357, 357, 357, 357, 357, 357, 360, 361, 362, + 363, 363, 363, 363, 363, 364, 363, 363, 365, 365, 365, 365, 366, 366, 366, 366, + 366, 366, 366, 367, 12, 368, 366, 366, 369, 369, 369, 369, 370, 371, 372, 369, + 373, 373, 373, 373, 373, 373, 373, 374, 375, 375, 375, 375, 375, 375, 376, 377, + 378, 378, 378, 378, 379, 379, 379, 379, 379, 379, 12, 379, 380, 379, 379, 379, + 381, 382, 12, 381, 381, 383, 383, 381, 381, 381, 381, 381, 381, 384, 385, 386, + 381, 381, 387, 12, 388, 388, 388, 388, 389, 389, 389, 389, 390, 390, 390, 390, + 390, 391, 392, 390, 390, 391, 12, 12, 393, 393, 393, 393, 393, 394, 395, 393, + 396, 396, 396, 396, 396, 397, 396, 396, 398, 398, 398, 398, 399, 12, 398, 398, + 400, 400, 400, 400, 401, 12, 402, 403, 12, 12, 402, 400, 404, 404, 404, 404, + 404, 404, 405, 12, 406, 406, 406, 406, 407, 12, 12, 12, 407, 12, 408, 406, + 409, 409, 409, 409, 409, 409, 12, 12, 409, 409, 410, 12, 411, 411, 411, 411, + 411, 411, 412, 413, 413, 12, 12, 12, 12, 12, 12, 414, 415, 415, 415, 415, + 415, 415, 12, 12, 416, 416, 416, 416, 416, 416, 417, 12, 418, 418, 418, 418, + 418, 418, 419, 12, 420, 420, 420, 420, 420, 420, 420, 12, 421, 421, 421, 421, + 421, 422, 12, 12, 423, 423, 423, 423, 423, 423, 423, 424, 425, 423, 423, 423, + 423, 424, 12, 426, 427, 427, 427, 427, 428, 12, 12, 429, 430, 430, 430, 430, + 430, 430, 431, 12, 430, 430, 432, 12, 433, 433, 433, 433, 433, 434, 433, 433, + 433, 433, 12, 12, 435, 435, 435, 435, 435, 436, 12, 12, 437, 437, 437, 437, + 118, 119, 119, 119, 119, 127, 12, 12, 438, 438, 438, 438, 439, 438, 438, 438, + 440, 12, 12, 12, 441, 442, 443, 444, 441, 441, 441, 444, 441, 441, 445, 12, + 446, 446, 446, 446, 446, 446, 447, 12, 446, 446, 448, 12, 449, 450, 449, 451, + 451, 449, 449, 449, 449, 449, 452, 449, 452, 450, 453, 449, 449, 451, 451, 454, + 455, 456, 12, 450, 449, 457, 449, 455, 449, 455, 12, 12, 458, 458, 458, 458, + 458, 458, 458, 459, 460, 12, 12, 12, 461, 461, 461, 461, 461, 461, 12, 12, + 461, 461, 462, 12, 463, 463, 463, 463, 463, 464, 463, 463, 463, 463, 463, 464, + 465, 465, 465, 465, 465, 466, 12, 12, 465, 465, 467, 12, 178, 178, 178, 180, + 468, 468, 468, 468, 468, 468, 469, 12, 470, 470, 470, 470, 470, 470, 471, 472, + 470, 470, 470, 12, 470, 471, 12, 12, 473, 473, 473, 473, 473, 473, 473, 12, + 474, 474, 474, 474, 475, 12, 12, 476, 477, 478, 479, 477, 477, 480, 477, 477, + 477, 477, 477, 477, 477, 481, 482, 477, 477, 478, 12, 12, 477, 477, 483, 12, + 484, 484, 485, 484, 484, 484, 484, 484, 484, 486, 12, 12, 487, 487, 487, 487, + 487, 487, 12, 12, 488, 488, 488, 488, 489, 12, 12, 12, 490, 490, 490, 490, + 490, 490, 491, 12, 53, 53, 492, 12, 493, 493, 494, 493, 493, 493, 493, 493, + 493, 495, 493, 493, 493, 496, 12, 12, 493, 493, 493, 497, 498, 498, 498, 498, + 499, 498, 498, 498, 498, 498, 500, 498, 498, 501, 12, 12, 502, 503, 504, 502, + 502, 502, 502, 502, 502, 503, 505, 504, 502, 502, 12, 12, 502, 502, 506, 12, + 507, 508, 509, 507, 507, 507, 507, 507, 507, 507, 507, 510, 508, 507, 511, 12, + 507, 507, 512, 12, 513, 513, 513, 513, 513, 513, 514, 12, 515, 515, 515, 515, + 516, 515, 515, 515, 515, 515, 517, 518, 515, 515, 519, 12, 520, 12, 12, 12, + 100, 100, 100, 100, 96, 12, 12, 98, 521, 521, 521, 521, 521, 521, 522, 12, + 521, 521, 521, 523, 521, 524, 12, 12, 521, 12, 12, 12, 525, 525, 525, 525, + 526, 12, 12, 12, 527, 527, 527, 527, 527, 528, 12, 12, 529, 529, 529, 529, + 529, 530, 12, 12, 272, 272, 531, 12, 532, 532, 532, 532, 532, 532, 532, 533, + 532, 532, 534, 535, 536, 536, 536, 536, 536, 536, 536, 537, 536, 536, 538, 12, + 539, 539, 539, 539, 539, 539, 539, 540, 539, 540, 12, 12, 541, 541, 541, 541, + 541, 542, 12, 12, 541, 541, 543, 541, 543, 541, 541, 541, 541, 541, 12, 544, + 545, 545, 545, 545, 545, 545, 546, 12, 547, 547, 547, 547, 547, 547, 548, 549, + 547, 547, 12, 549, 550, 551, 12, 12, 249, 12, 12, 12, 552, 552, 552, 552, + 552, 552, 12, 12, 553, 553, 553, 553, 553, 554, 12, 12, 552, 552, 555, 12, + 260, 556, 260, 557, 558, 255, 255, 255, 559, 12, 12, 12, 560, 12, 12, 12, + 256, 561, 12, 12, 12, 260, 12, 12, 562, 562, 562, 562, 562, 562, 562, 12, + 563, 563, 563, 563, 563, 563, 564, 12, 563, 563, 563, 565, 563, 563, 565, 12, + 563, 563, 566, 563, 7, 7, 7, 567, 7, 199, 12, 12, 0, 246, 12, 12, + 0, 232, 316, 0, 0, 568, 228, 0, 0, 0, 568, 7, 213, 569, 7, 0, + 0, 0, 570, 228, 8, 225, 12, 12, 0, 0, 234, 12, 0, 0, 0, 229, + 571, 572, 316, 229, 0, 0, 240, 316, 0, 316, 0, 0, 0, 240, 232, 316, + 0, 229, 0, 229, 0, 0, 240, 232, 0, 573, 239, 0, 229, 0, 0, 0, + 0, 246, 0, 0, 0, 0, 0, 239, 574, 574, 574, 574, 574, 574, 574, 12, + 12, 12, 575, 574, 576, 574, 574, 574, 2, 2, 2, 273, 12, 275, 273, 12, + 241, 577, 241, 241, 241, 241, 578, 241, 579, 580, 577, 12, 19, 19, 19, 581, + 12, 12, 12, 582, 583, 583, 583, 583, 583, 583, 583, 584, 583, 583, 583, 585, + 583, 583, 585, 586, 587, 587, 587, 587, 587, 587, 587, 588, 589, 589, 589, 589, + 589, 589, 590, 591, 592, 592, 592, 592, 592, 592, 593, 12, 151, 154, 151, 594, + 151, 151, 151, 154, 595, 595, 595, 595, 595, 596, 595, 595, 595, 597, 12, 12, + 598, 598, 598, 598, 598, 598, 598, 12, 598, 598, 599, 600, 0, 234, 12, 12, + 29, 414, 29, 29, 601, 602, 414, 29, 50, 29, 603, 12, 604, 310, 603, 414, + 601, 602, 603, 603, 601, 602, 50, 29, 50, 29, 414, 605, 29, 29, 606, 29, + 29, 29, 29, 12, 414, 414, 606, 29, 51, 12, 12, 12, 12, 239, 0, 0, + 607, 12, 12, 12, 246, 12, 12, 12, 0, 0, 12, 0, 0, 232, 131, 0, + 0, 0, 12, 12, 0, 0, 0, 240, 0, 246, 12, 239, 608, 12, 12, 12, + 247, 247, 609, 12, 610, 12, 12, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 939, 940, 941, 942, 946, 948, 0, 962, 969, 970, 971, 976,1001,1002,1003,1008, 0,1033,1040,1041,1042,1043,1047, 0, 0,1080,1081,1082,1086,1110, 0, 0,1124,1125,1126,1127,1131,1133, 0,1147, @@ -4562,21 +4387,14 @@ _hb_ucd_u16[9320] = 817, 818, 819, 820, 821, 935, 0, 0, }; static const int16_t -_hb_ucd_i16[196] = +_hb_ucd_i16[92] = { - 0, 0, 0, 0, 1, -1, 0, 0, 2, 0, -2, 0, 0, 0, 0, 2, - 0, -2, 0, 0, 0, 0, 0, 16, 0, 0, 0, -16, 0, 0, 1, -1, - 0, 0, 0, 1, -1, 0, 0, 0, 0, 1, -1, 0, 3, 3, 3, -3, - -3, -3, 0, 0, 0, 2016, 0, 0, 0, 0, 0, 2527, 1923, 1914, 1918, 0, - 2250, 0, 0, 0, 0, 0, 0, 138, 0, 7, 0, 0, -7, 0, 0, 0, - 1, -1, 1, -1, -1, 1, -1, 0, 1824, 0, 0, 0, 0, 0, 2104, 0, - 2108, 2106, 0, 2106, 1316, 0, 0, 0, 0, 1, -1, 1, -1, -138, 0, 0, - 1, -1, 8, 8, 8, 0, 7, 7, 0, 0, -8, -8, -8, -7, -7, 0, - 1, -1, 0, 2,-1316, 1, -1, 0, -1, 1, -1, 1, -1, 3, 1, -1, - -3, 1, -1, 1, -1, 0, 0,-1914,-1918, 0, 0,-1923,-1824, 0, 0, 0, - 0,-2016, 0, 0, 1, -1, 0, 1, 0, 0,-2104, 0, 0, 0, 0,-2106, - -2108,-2106, 0, 0, 1, -1,-2250, 0, 0, 0,-2527, 0, 0, -2, 0, 1, - -1, 0, 1, -1, + 0, 0, 1, -1, 2, 0, -2, 0, 0, 2, 0, -2, 0, 16, 0, -16, + 0, 1, -1, 0, 3, 3, 3, -3, -3, -3, 0, 2016, 0, 2527, 1923, 1914, + 1918, 0, 2250, 0, 0, 138, 0, 7, -7, 0, -1, 1, 1824, 0, 2104, 0, + 2108, 2106, 0, 2106, 1316, 0, -1, -138, 8, 8, 8, 0, 7, 7, -8, -8, + -8, -7,-1316, 1, -1, 3, -3, 1, 0,-1914,-1918, 0, 0,-1923,-1824, 0, + 0,-2016,-2104, 0, 0,-2106,-2108,-2106,-2250, 0,-2527, 0, }; static inline uint_fast8_t @@ -4597,17 +4415,17 @@ _hb_ucd_b4 (const uint8_t* a, unsigned i) static inline int_fast16_t _hb_ucd_bmg (unsigned u) { - return u<65380u?_hb_ucd_i16[((_hb_ucd_u8[9540+(((_hb_ucd_u8[9420+(((_hb_ucd_b4(9292+_hb_ucd_u8,u>>2>>3>>3))<<3)+((u>>2>>3)&7u))])<<3)+((u>>2)&7u))])<<2)+((u)&3u)]:0; + return u<65380u?_hb_ucd_i16[((_hb_ucd_u8[9684+(((_hb_ucd_u8[9452+(((_hb_ucd_u8[9356+(((_hb_ucd_b4(9292+_hb_ucd_u8,u>>1>>2>>3>>3))<<3)+((u>>1>>2>>3)&7u))])<<3)+((u>>1>>2)&7u))])<<2)+((u>>1)&3u))])<<1)+((u)&1u)]:0; } static inline uint_fast8_t _hb_ucd_sc (unsigned u) { - return u<918000u?_hb_ucd_u8[11062+(((_hb_ucd_u16[2040+(((_hb_ucd_u8[10326+(((_hb_ucd_u8[9876+(u>>3>>4>>4)])<<4)+((u>>3>>4)&15u))])<<4)+((u>>3)&15u))])<<3)+((u)&7u))]:2; + return u<918000u?_hb_ucd_u8[11118+(((_hb_ucd_u16[4024+(((_hb_ucd_u16[2040+(((_hb_ucd_u8[10382+(((_hb_ucd_u8[9932+(u>>2>>2>>3>>4)])<<4)+((u>>2>>2>>3)&15u))])<<3)+((u>>2>>2)&7u))])<<2)+((u>>2)&3u))])<<2)+((u)&3u))]:2; } static inline uint_fast16_t _hb_ucd_dm (unsigned u) { - return u<195102u?_hb_ucd_u16[6008+(((_hb_ucd_u8[17068+(((_hb_ucd_u8[16686+(u>>4>>5)])<<5)+((u>>4)&31u))])<<4)+((u)&15u))]:0; + return u<195102u?_hb_ucd_u16[6728+(((_hb_ucd_u8[13944+(((_hb_ucd_u8[13562+(u>>4>>5)])<<5)+((u>>4)&31u))])<<4)+((u)&15u))]:0; } diff --git a/thirdparty/harfbuzz/src/hb-ucd.cc b/thirdparty/harfbuzz/src/hb-ucd.cc index baea224a25..4c8b1ee5e6 100644 --- a/thirdparty/harfbuzz/src/hb-ucd.cc +++ b/thirdparty/harfbuzz/src/hb-ucd.cc @@ -129,12 +129,16 @@ hb_ucd_compose (hb_unicode_funcs_t *ufuncs HB_UNUSED, hb_codepoint_t a, hb_codepoint_t b, hb_codepoint_t *ab, void *user_data HB_UNUSED) { + // Hangul is handled algorithmically. if (_hb_ucd_compose_hangul (a, b, ab)) return true; hb_codepoint_t u = 0; if ((a & 0xFFFFF800u) == 0x0000u && (b & 0xFFFFFF80) == 0x0300u) { + /* If "a" is small enough and "b" is in the U+0300 range, + * the composition data is encoded in a 32bit array sorted + * by "a,b" pair. */ uint32_t k = HB_CODEPOINT_ENCODE3_11_7_14 (a, b, 0); const uint32_t *v = hb_bsearch (k, _hb_ucd_dm2_u32_map, @@ -146,6 +150,8 @@ hb_ucd_compose (hb_unicode_funcs_t *ufuncs HB_UNUSED, } else { + /* Otherwise it is stored in a 64bit array sorted by + * "a,b" pair. */ uint64_t k = HB_CODEPOINT_ENCODE3 (a, b, 0); const uint64_t *v = hb_bsearch (k, _hb_ucd_dm2_u64_map, @@ -170,15 +176,22 @@ hb_ucd_decompose (hb_unicode_funcs_t *ufuncs HB_UNUSED, unsigned i = _hb_ucd_dm (ab); + /* If no data, there's no decomposition. */ if (likely (!i)) return false; i--; + /* Check if it's a single-character decomposition. */ if (i < ARRAY_LENGTH (_hb_ucd_dm1_p0_map) + ARRAY_LENGTH (_hb_ucd_dm1_p2_map)) { + /* Single-character decompositions currently are only in plane 0 or plane 2. */ if (i < ARRAY_LENGTH (_hb_ucd_dm1_p0_map)) + { + /* Plane 0. */ *a = _hb_ucd_dm1_p0_map[i]; + } else { + /* Plane 2. */ i -= ARRAY_LENGTH (_hb_ucd_dm1_p0_map); *a = 0x20000 | _hb_ucd_dm1_p2_map[i]; } @@ -187,8 +200,10 @@ hb_ucd_decompose (hb_unicode_funcs_t *ufuncs HB_UNUSED, } i -= ARRAY_LENGTH (_hb_ucd_dm1_p0_map) + ARRAY_LENGTH (_hb_ucd_dm1_p2_map); + /* Otherwise they are encoded either in a 32bit array or a 64bit array. */ if (i < ARRAY_LENGTH (_hb_ucd_dm2_u32_map)) { + /* 32bit array. */ uint32_t v = _hb_ucd_dm2_u32_map[i]; *a = HB_CODEPOINT_DECODE3_11_7_14_1 (v); *b = HB_CODEPOINT_DECODE3_11_7_14_2 (v); @@ -196,6 +211,7 @@ hb_ucd_decompose (hb_unicode_funcs_t *ufuncs HB_UNUSED, } i -= ARRAY_LENGTH (_hb_ucd_dm2_u32_map); + /* 64bit array. */ uint64_t v = _hb_ucd_dm2_u64_map[i]; *a = HB_CODEPOINT_DECODE3_1 (v); *b = HB_CODEPOINT_DECODE3_2 (v); diff --git a/thirdparty/harfbuzz/src/hb-unicode.cc b/thirdparty/harfbuzz/src/hb-unicode.cc index c1795dc7f2..9a6471e52c 100644 --- a/thirdparty/harfbuzz/src/hb-unicode.cc +++ b/thirdparty/harfbuzz/src/hb-unicode.cc @@ -377,20 +377,30 @@ hb_unicode_funcs_set_##name##_func (hb_unicode_funcs_t *ufuncs, \ hb_destroy_func_t destroy) \ { \ if (hb_object_is_immutable (ufuncs)) \ - return; \ + goto fail; \ + \ + if (!func) \ + { \ + if (destroy) \ + destroy (user_data); \ + destroy = nullptr; \ + user_data = ufuncs->parent->user_data.name; \ + } \ \ if (ufuncs->destroy.name) \ ufuncs->destroy.name (ufuncs->user_data.name); \ \ - if (func) { \ + if (func) \ ufuncs->func.name = func; \ - ufuncs->user_data.name = user_data; \ - ufuncs->destroy.name = destroy; \ - } else { \ + else \ ufuncs->func.name = ufuncs->parent->func.name; \ - ufuncs->user_data.name = ufuncs->parent->user_data.name; \ - ufuncs->destroy.name = nullptr; \ - } \ + ufuncs->user_data.name = user_data; \ + ufuncs->destroy.name = destroy; \ + return; \ + \ +fail: \ + if (destroy) \ + destroy (user_data); \ } HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS diff --git a/thirdparty/harfbuzz/src/hb-uniscribe.cc b/thirdparty/harfbuzz/src/hb-uniscribe.cc index 50f71ce9ce..9648e02663 100644 --- a/thirdparty/harfbuzz/src/hb-uniscribe.cc +++ b/thirdparty/harfbuzz/src/hb-uniscribe.cc @@ -355,7 +355,7 @@ _hb_rename_font (hb_blob_t *blob, wchar_t *new_name) return nullptr; } - memcpy(new_sfnt_data, orig_sfnt_data, length); + hb_memcpy(new_sfnt_data, orig_sfnt_data, length); OT::name &name = StructAtOffset<OT::name> (new_sfnt_data, name_table_offset); name.format = 0; @@ -478,11 +478,11 @@ populate_log_font (LOGFONTW *lf, hb_font_t *font, unsigned int font_size) { - memset (lf, 0, sizeof (*lf)); + hb_memset (lf, 0, sizeof (*lf)); lf->lfHeight = - (int) font_size; lf->lfCharSet = DEFAULT_CHARSET; - memcpy (lf->lfFaceName, font->face->data.uniscribe->face_name, sizeof (lf->lfFaceName)); + hb_memcpy (lf->lfFaceName, font->face->data.uniscribe->face_name, sizeof (lf->lfFaceName)); return true; } diff --git a/thirdparty/harfbuzz/src/hb-vector.hh b/thirdparty/harfbuzz/src/hb-vector.hh index a6d9f6b3fb..9b52f5ca95 100644 --- a/thirdparty/harfbuzz/src/hb-vector.hh +++ b/thirdparty/harfbuzz/src/hb-vector.hh @@ -35,7 +35,7 @@ template <typename Type, bool sorted=false> -struct hb_vector_t : std::conditional<sorted, hb_vector_t<Type, false>, hb_empty_t>::type +struct hb_vector_t { typedef Type item_t; static constexpr unsigned item_size = hb_static_size (Type); @@ -53,9 +53,10 @@ struct hb_vector_t : std::conditional<sorted, hb_vector_t<Type, false>, hb_empty hb_requires (hb_is_iterable (Iterable))> hb_vector_t (const Iterable &o) : hb_vector_t () { - if (hb_iter (o).is_random_access_iterator) - alloc (hb_len (hb_iter (o))); - hb_copy (o, *this); + auto iter = hb_iter (o); + if (iter.is_random_access_iterator) + alloc (hb_len (iter)); + hb_copy (iter, *this); } hb_vector_t (const hb_vector_t &o) : hb_vector_t () { @@ -83,6 +84,9 @@ struct hb_vector_t : std::conditional<sorted, hb_vector_t<Type, false>, hb_empty allocated = length = 0; arrayZ = nullptr; } + void init0 () + { + } void fini () { @@ -94,7 +98,11 @@ struct hb_vector_t : std::conditional<sorted, hb_vector_t<Type, false>, hb_empty void reset () { if (unlikely (in_error ())) - allocated = length; // Big hack! + /* Big Hack! We don't know the true allocated size before + * an allocation failure happened. But we know it was at + * least as big as length. Restore it to that and continue + * as if error did not happen. */ + allocated = length; resize (0); } @@ -122,7 +130,7 @@ struct hb_vector_t : std::conditional<sorted, hb_vector_t<Type, false>, hb_empty } hb_bytes_t as_bytes () const - { return hb_bytes_t ((const char *) arrayZ, length * item_size); } + { return hb_bytes_t ((const char *) arrayZ, get_size ()); } bool operator == (const hb_vector_t &o) const { return as_array () == o.as_array (); } bool operator != (const hb_vector_t &o) const { return !(*this == o); } @@ -164,14 +172,10 @@ struct hb_vector_t : std::conditional<sorted, hb_vector_t<Type, false>, hb_empty operator iter_t () const { return iter (); } operator writer_t () { return writer (); } - c_array_t sub_array (unsigned int start_offset, unsigned int count) const - { return as_array ().sub_array (start_offset, count); } - c_array_t sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */) const - { return as_array ().sub_array (start_offset, count); } - array_t sub_array (unsigned int start_offset, unsigned int count) - { return as_array ().sub_array (start_offset, count); } - array_t sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */) - { return as_array ().sub_array (start_offset, count); } + /* Faster range-based for loop. */ + Type *begin () const { return arrayZ; } + Type *end () const { return arrayZ + length; } + hb_sorted_array_t<Type> as_sorted_array () { return hb_sorted_array (arrayZ, length); } @@ -240,12 +244,11 @@ struct hb_vector_t : std::conditional<sorted, hb_vector_t<Type, false>, hb_empty if (likely (new_array)) { for (unsigned i = 0; i < length; i++) + { new (std::addressof (new_array[i])) Type (); - for (unsigned i = 0; i < (unsigned) length; i++) new_array[i] = std::move (arrayZ[i]); - unsigned old_length = length; - shrink_vector (0); - length = old_length; + arrayZ[i].~Type (); + } hb_free (arrayZ); } return new_array; @@ -277,7 +280,14 @@ struct hb_vector_t : std::conditional<sorted, hb_vector_t<Type, false>, hb_empty copy_vector (const hb_vector_t &other) { length = other.length; - hb_memcpy ((void *) arrayZ, (const void *) other.arrayZ, length * item_size); +#ifndef HB_OPTIMIZE_SIZE + if (sizeof (T) >= sizeof (long long)) + /* This runs faster because of alignment. */ + for (unsigned i = 0; i < length; i++) + arrayZ[i] = other.arrayZ[i]; + else +#endif + hb_memcpy ((void *) arrayZ, (const void *) other.arrayZ, length * item_size); } template <typename T = Type, hb_enable_if (!hb_is_trivially_copyable (T) && @@ -309,15 +319,6 @@ struct hb_vector_t : std::conditional<sorted, hb_vector_t<Type, false>, hb_empty } } - template <typename T = Type, - hb_enable_if (hb_is_trivially_destructible(T))> - void - shrink_vector (unsigned size) - { - length = size; - } - template <typename T = Type, - hb_enable_if (!hb_is_trivially_destructible(T))> void shrink_vector (unsigned size) { @@ -328,17 +329,6 @@ struct hb_vector_t : std::conditional<sorted, hb_vector_t<Type, false>, hb_empty } } - template <typename T = Type, - hb_enable_if (hb_is_trivially_copy_assignable(T))> - void - shift_down_vector (unsigned i) - { - memmove (static_cast<void *> (&arrayZ[i - 1]), - static_cast<void *> (&arrayZ[i]), - (length - i) * sizeof (Type)); - } - template <typename T = Type, - hb_enable_if (!hb_is_trivially_copy_assignable(T))> void shift_down_vector (unsigned i) { @@ -381,16 +371,22 @@ struct hb_vector_t : std::conditional<sorted, hb_vector_t<Type, false>, hb_empty return true; } - bool resize (int size_) + bool resize (int size_, bool initialize = true) { unsigned int size = size_ < 0 ? 0u : (unsigned int) size_; if (!alloc (size)) return false; if (size > length) - grow_vector (size); + { + if (initialize) + grow_vector (size); + } else if (size < length) - shrink_vector (size); + { + if (initialize) + shrink_vector (size); + } length = size; return true; @@ -399,13 +395,13 @@ struct hb_vector_t : std::conditional<sorted, hb_vector_t<Type, false>, hb_empty Type pop () { if (!length) return Null (Type); - Type v = arrayZ[length - 1]; + Type v {std::move (arrayZ[length - 1])}; arrayZ[length - 1].~Type (); length--; return v; } - void remove (unsigned int i) + void remove_ordered (unsigned int i) { if (unlikely (i >= length)) return; @@ -414,6 +410,18 @@ struct hb_vector_t : std::conditional<sorted, hb_vector_t<Type, false>, hb_empty length--; } + template <bool Sorted = sorted, + hb_enable_if (!Sorted)> + void remove_unordered (unsigned int i) + { + if (unlikely (i >= length)) + return; + if (i != length - 1) + arrayZ[i] = std::move (arrayZ[length - 1]); + arrayZ[length - 1].~Type (); + length--; + } + void shrink (int size_) { unsigned int size = size_ < 0 ? 0u : (unsigned int) size_; @@ -425,10 +433,8 @@ struct hb_vector_t : std::conditional<sorted, hb_vector_t<Type, false>, hb_empty /* Sorting API. */ - void qsort (int (*cmp)(const void*, const void*)) + void qsort (int (*cmp)(const void*, const void*) = Type::cmp) { as_array ().qsort (cmp); } - void qsort (unsigned int start = 0, unsigned int end = (unsigned int) -1) - { as_array ().qsort (start, end); } /* Unsorted search API. */ template <typename T> diff --git a/thirdparty/harfbuzz/src/hb-version.h b/thirdparty/harfbuzz/src/hb-version.h index fa7403cae7..1070262a3b 100644 --- a/thirdparty/harfbuzz/src/hb-version.h +++ b/thirdparty/harfbuzz/src/hb-version.h @@ -41,13 +41,13 @@ HB_BEGIN_DECLS * * The major component of the library version available at compile-time. */ -#define HB_VERSION_MAJOR 5 +#define HB_VERSION_MAJOR 6 /** * HB_VERSION_MINOR: * * The minor component of the library version available at compile-time. */ -#define HB_VERSION_MINOR 2 +#define HB_VERSION_MINOR 0 /** * HB_VERSION_MICRO: * @@ -60,7 +60,7 @@ HB_BEGIN_DECLS * * A string literal containing the library version available at compile-time. */ -#define HB_VERSION_STRING "5.2.0" +#define HB_VERSION_STRING "6.0.0" /** * HB_VERSION_ATLEAST: diff --git a/thirdparty/harfbuzz/src/hb.hh b/thirdparty/harfbuzz/src/hb.hh index 8ec638a2b4..410d090d36 100644 --- a/thirdparty/harfbuzz/src/hb.hh +++ b/thirdparty/harfbuzz/src/hb.hh @@ -126,6 +126,7 @@ /* Ignored intentionally. */ #ifndef HB_NO_PRAGMA_GCC_DIAGNOSTIC_IGNORED #pragma GCC diagnostic ignored "-Wclass-memaccess" +#pragma GCC diagnostic ignored "-Wcast-function-type-strict" // https://github.com/harfbuzz/harfbuzz/pull/3859#issuecomment-1295409126 #pragma GCC diagnostic ignored "-Wformat-nonliteral" #pragma GCC diagnostic ignored "-Wformat-zero-length" #pragma GCC diagnostic ignored "-Wmissing-field-initializers" |