From d390ac99f2c2a0f70319df5f6ed3068cc5cbd6fe Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Thu, 1 Jun 2023 07:53:31 +0200 Subject: Upgrade Harfbuzz to 7.3.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes: QTBUG-114098 Pick-to: 6.2 6.5 6.6 Change-Id: I7bc766e6edada6f964c2dc40f18ff710249fb159 Reviewed-by: Tor Arne Vestbø --- src/3rdparty/harfbuzz-ng/CMakeLists.txt | 1 + src/3rdparty/harfbuzz-ng/NEWS | 21 + src/3rdparty/harfbuzz-ng/qt_attribution.json | 4 +- src/3rdparty/harfbuzz-ng/src/OT/Color/COLR/COLR.hh | 8 +- .../harfbuzz-ng/src/OT/Layout/Common/Coverage.hh | 23 +- .../src/OT/Layout/Common/CoverageFormat2.hh | 17 +- .../src/OT/Layout/Common/RangeRecord.hh | 12 + .../harfbuzz-ng/src/OT/Layout/GDEF/GDEF.hh | 24 + .../src/OT/Layout/GPOS/CursivePosFormat1.hh | 4 +- .../harfbuzz-ng/src/OT/Layout/GPOS/GPOS.hh | 2 +- .../src/OT/Layout/GPOS/MarkMarkPosFormat1.hh | 6 +- .../src/OT/Layout/GPOS/PairPosFormat1.hh | 4 +- .../src/OT/Layout/GPOS/PairPosFormat2.hh | 27 +- .../harfbuzz-ng/src/OT/Layout/GPOS/PairSet.hh | 4 +- .../harfbuzz-ng/src/OT/Layout/GSUB/Ligature.hh | 2 +- .../harfbuzz-ng/src/OT/Layout/GSUB/LigatureSet.hh | 62 ++- .../harfbuzz-ng/src/OT/Layout/GSUB/SingleSubst.hh | 2 +- .../harfbuzz-ng/src/OT/glyf/CompositeGlyph.hh | 36 +- src/3rdparty/harfbuzz-ng/src/OT/glyf/Glyph.hh | 93 ++-- .../harfbuzz-ng/src/OT/glyf/SimpleGlyph.hh | 33 +- .../harfbuzz-ng/src/OT/glyf/VarCompositeGlyph.hh | 244 +++++----- .../harfbuzz-ng/src/OT/glyf/path-builder.hh | 8 +- src/3rdparty/harfbuzz-ng/src/graph/graph.hh | 64 +-- .../harfbuzz-ng/src/graph/markbasepos-graph.hh | 5 +- src/3rdparty/harfbuzz-ng/src/graph/serialize.hh | 4 +- src/3rdparty/harfbuzz-ng/src/hb-aat-layout.cc | 8 +- src/3rdparty/harfbuzz-ng/src/hb-algs.hh | 6 +- src/3rdparty/harfbuzz-ng/src/hb-array.hh | 34 +- src/3rdparty/harfbuzz-ng/src/hb-bit-set.hh | 7 +- src/3rdparty/harfbuzz-ng/src/hb-buffer.cc | 2 +- src/3rdparty/harfbuzz-ng/src/hb-buffer.hh | 2 +- src/3rdparty/harfbuzz-ng/src/hb-config.hh | 40 +- src/3rdparty/harfbuzz-ng/src/hb-map.hh | 3 +- src/3rdparty/harfbuzz-ng/src/hb-null.hh | 2 +- src/3rdparty/harfbuzz-ng/src/hb-ot-cff1-table.hh | 4 +- src/3rdparty/harfbuzz-ng/src/hb-ot-cff2-table.hh | 4 +- src/3rdparty/harfbuzz-ng/src/hb-ot-font.cc | 32 +- .../harfbuzz-ng/src/hb-ot-layout-common.hh | 31 +- .../harfbuzz-ng/src/hb-ot-layout-gsubgpos.hh | 48 +- src/3rdparty/harfbuzz-ng/src/hb-ot-layout.cc | 22 +- src/3rdparty/harfbuzz-ng/src/hb-ot-math.cc | 2 +- src/3rdparty/harfbuzz-ng/src/hb-ot-metrics.cc | 2 +- .../harfbuzz-ng/src/hb-ot-shape-normalize.cc | 15 +- .../harfbuzz-ng/src/hb-ot-shaper-indic-machine.hh | 14 +- src/3rdparty/harfbuzz-ng/src/hb-ot-var-common.hh | 3 +- .../harfbuzz-ng/src/hb-ot-var-cvar-table.hh | 1 - .../harfbuzz-ng/src/hb-ot-var-gvar-table.hh | 111 +++-- src/3rdparty/harfbuzz-ng/src/hb-set-digest.hh | 12 +- .../harfbuzz-ng/src/hb-subset-accelerator.hh | 2 + src/3rdparty/harfbuzz-ng/src/hb-subset-input.cc | 31 ++ src/3rdparty/harfbuzz-ng/src/hb-subset-input.hh | 1 + .../harfbuzz-ng/src/hb-subset-plan-member-list.hh | 128 +++++ src/3rdparty/harfbuzz-ng/src/hb-subset-plan.cc | 94 +++- src/3rdparty/harfbuzz-ng/src/hb-subset-plan.hh | 90 +--- src/3rdparty/harfbuzz-ng/src/hb-subset.cc | 8 +- src/3rdparty/harfbuzz-ng/src/hb-subset.h | 3 + src/3rdparty/harfbuzz-ng/src/hb-vector.hh | 4 +- src/3rdparty/harfbuzz-ng/src/hb-version.h | 4 +- src/3rdparty/harfbuzz-ng/src/hb.hh | 4 +- src/3rdparty/harfbuzz-ng/src/main.cc | 532 --------------------- src/3rdparty/harfbuzz-ng/src/test.cc | 95 ---- 61 files changed, 982 insertions(+), 1129 deletions(-) create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-subset-plan-member-list.hh delete mode 100644 src/3rdparty/harfbuzz-ng/src/main.cc delete mode 100644 src/3rdparty/harfbuzz-ng/src/test.cc (limited to 'src') diff --git a/src/3rdparty/harfbuzz-ng/CMakeLists.txt b/src/3rdparty/harfbuzz-ng/CMakeLists.txt index c761bda388..96e21941b2 100644 --- a/src/3rdparty/harfbuzz-ng/CMakeLists.txt +++ b/src/3rdparty/harfbuzz-ng/CMakeLists.txt @@ -58,6 +58,7 @@ qt_internal_add_3rdparty_library(BundledHarfbuzz src/hb-subset-input.cc src/hb-subset-instancer-solver.cc src/hb-subset-plan.cc + src/hb-subset-plan-member-list.hh src/hb-subset-repacker.cc src/hb-subset-repacker.h src/hb-unicode.cc src/hb-unicode.h src/hb-unicode.hh src/hb-utf.hh diff --git a/src/3rdparty/harfbuzz-ng/NEWS b/src/3rdparty/harfbuzz-ng/NEWS index e53a244f1b..ff35843192 100644 --- a/src/3rdparty/harfbuzz-ng/NEWS +++ b/src/3rdparty/harfbuzz-ng/NEWS @@ -1,3 +1,24 @@ +Overview of changes leading to 7.3.0 +Tuesday, May 9, 2023 +==================================== +- Speedup applying glyph variation in VarComposites fonts (over 40% speedup). + (Behdad Esfahbod) +- Speedup instancing some fonts (over 20% speedup in instancing RobotoFlex). + (Behdad Esfahbod) +- Speedup shaping some fonts (over 30% speedup in shaping Roboto). + (Behdad Esfahbod) +- Support subsetting VarComposites and beyond-64k fonts. (Behdad Esfahbod) +- New configuration macro HB_MINIMIZE_MEMORY_USAGE to favor optimizing memory + usage over speed. (Behdad Esfahbod) +- Supporting setting the mapping between old and new glyph indices during + subsetting. (Garret Rieger) +- Various fixes and improvements. + (Behdad Esfahbod, Denis Rochette, Garret Rieger, Han Seung Min, Qunxin Liu) + +- New API: ++hb_subset_input_old_to_new_glyph_mapping() + + Overview of changes leading to 7.2.0 Thursday, April 27, 2023 ==================================== diff --git a/src/3rdparty/harfbuzz-ng/qt_attribution.json b/src/3rdparty/harfbuzz-ng/qt_attribution.json index b1ca7db332..f2b53ef7d6 100644 --- a/src/3rdparty/harfbuzz-ng/qt_attribution.json +++ b/src/3rdparty/harfbuzz-ng/qt_attribution.json @@ -7,8 +7,8 @@ "Description": "HarfBuzz is an OpenType text shaping engine.", "Homepage": "http://harfbuzz.org", - "Version": "7.2.0", - "DownloadLocation": "https://github.com/harfbuzz/harfbuzz/releases/tag/7.2.0", + "Version": "7.3.0", + "DownloadLocation": "https://github.com/harfbuzz/harfbuzz/releases/tag/7.3.0", "License": "MIT License", "LicenseId": "MIT", diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Color/COLR/COLR.hh b/src/3rdparty/harfbuzz-ng/src/OT/Color/COLR/COLR.hh index 191812f48e..2a47984294 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Color/COLR/COLR.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Color/COLR/COLR.hh @@ -1514,10 +1514,10 @@ struct ClipBoxFormat2 : Variable 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)); + clip_box.xMin += roundf (instancer (varIdxBase, 0)); + clip_box.yMin += roundf (instancer (varIdxBase, 1)); + clip_box.xMax += roundf (instancer (varIdxBase, 2)); + clip_box.yMax += roundf (instancer (varIdxBase, 3)); } } }; diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/Coverage.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/Coverage.hh index d35654e245..9ca88f788a 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/Coverage.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/Coverage.hh @@ -113,22 +113,33 @@ struct Coverage TRACE_SERIALIZE (this); if (unlikely (!c->extend_min (this))) return_trace (false); - unsigned count = 0; + unsigned count = hb_len (glyphs); unsigned num_ranges = 0; hb_codepoint_t last = (hb_codepoint_t) -2; + hb_codepoint_t max = 0; + bool unsorted = false; for (auto g: glyphs) { + if (last != (hb_codepoint_t) -2 && g < last) + unsorted = true; if (last + 1 != g) - num_ranges++; + num_ranges++; last = g; - count++; + if (g > max) max = g; } - u.format = count <= num_ranges * 3 ? 1 : 2; + u.format = !unsorted && count <= num_ranges * 3 ? 1 : 2; #ifndef HB_NO_BEYOND_64K - if (count && last > 0xFFFFu) + if (max > 0xFFFFu) u.format += 2; + if (unlikely (max > 0xFFFFFFu)) +#else + if (unlikely (max > 0xFFFFu)) #endif + { + c->check_success (false, HB_SERIALIZE_ERROR_INT_OVERFLOW); + return_trace (false); + } switch (u.format) { @@ -148,8 +159,8 @@ struct Coverage auto it = + iter () | hb_take (c->plan->source->get_num_glyphs ()) - | hb_filter (c->plan->glyph_map_gsub) | hb_map_retains_sorting (c->plan->glyph_map_gsub) + | hb_filter ([] (hb_codepoint_t glyph) { return glyph != HB_MAP_VALUE_INVALID; }) ; // Cache the iterator result as it will be iterated multiple times diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/CoverageFormat2.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/CoverageFormat2.hh index d7fcc35202..fa501d659d 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/CoverageFormat2.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/CoverageFormat2.hh @@ -95,19 +95,26 @@ struct CoverageFormat2_4 unsigned count = 0; unsigned range = (unsigned) -1; last = (hb_codepoint_t) -2; + unsigned unsorted = false; for (auto g: glyphs) { if (last + 1 != g) { + if (unlikely (last != (hb_codepoint_t) -2 && last + 1 > g)) + unsorted = true; + range++; - rangeRecord[range].first = g; - rangeRecord[range].value = count; + rangeRecord.arrayZ[range].first = g; + rangeRecord.arrayZ[range].value = count; } - rangeRecord[range].last = g; + rangeRecord.arrayZ[range].last = g; last = g; count++; } + if (unlikely (unsorted)) + rangeRecord.as_array ().qsort (RangeRecord::cmp_range); + return_trace (true); } @@ -185,8 +192,8 @@ struct CoverageFormat2_4 if (__more__ ()) { unsigned int old = coverage; - j = c->rangeRecord[i].first; - coverage = c->rangeRecord[i].value; + j = c->rangeRecord.arrayZ[i].first; + coverage = c->rangeRecord.arrayZ[i].value; if (unlikely (coverage != old + 1)) { /* Broken table. Skip. Important to avoid DoS. diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/RangeRecord.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/RangeRecord.hh index a62629fad3..85aacace9a 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/RangeRecord.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/RangeRecord.hh @@ -51,6 +51,18 @@ struct RangeRecord int cmp (hb_codepoint_t g) const { return g < first ? -1 : g <= last ? 0 : +1; } + HB_INTERNAL static int cmp_range (const void *pa, const void *pb) { + const RangeRecord *a = (const RangeRecord *) pa; + const RangeRecord *b = (const RangeRecord *) pb; + if (a->first < b->first) return -1; + if (a->first > b->first) return +1; + if (a->last < b->last) return -1; + if (a->last > b->last) return +1; + if (a->value < b->value) return -1; + if (a->value > b->value) return +1; + return 0; + } + unsigned get_population () const { if (unlikely (last < first)) return 0; diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GDEF/GDEF.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GDEF/GDEF.hh index 0551fcf812..c1ff796199 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GDEF/GDEF.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GDEF/GDEF.hh @@ -32,6 +32,7 @@ #include "../../../hb-ot-layout-common.hh" #include "../../../hb-font.hh" +#include "../../../hb-cache.hh" namespace OT { @@ -861,7 +862,30 @@ struct GDEF } ~accelerator_t () { table.destroy (); } + unsigned int get_glyph_props (hb_codepoint_t glyph) const + { + unsigned v; + +#ifndef HB_NO_GDEF_CACHE + if (glyph_props_cache.get (glyph, &v)) + return v; +#endif + + v = table->get_glyph_props (glyph); + +#ifndef HB_NO_GDEF_CACHE + if (likely (table.get_blob ())) // Don't try setting if we are the null instance! + glyph_props_cache.set (glyph, v); +#endif + + return v; + + } + hb_blob_ptr_t table; +#ifndef HB_NO_GDEF_CACHE + mutable hb_cache_t<21, 3, 8> glyph_props_cache; +#endif }; void collect_variation_indices (hb_collect_variation_indices_context_t *c) const diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/CursivePosFormat1.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/CursivePosFormat1.hh index ff255e090a..b8773ba0aa 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/CursivePosFormat1.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/CursivePosFormat1.hh @@ -122,9 +122,9 @@ struct CursivePosFormat1 if (!this_record.entryAnchor) return_trace (false); hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input; - skippy_iter.reset (buffer->idx, 1); + skippy_iter.reset_fast (buffer->idx, 1); unsigned unsafe_from; - if (!skippy_iter.prev (&unsafe_from)) + if (unlikely (!skippy_iter.prev (&unsafe_from))) { buffer->unsafe_to_concat_from_outbuffer (unsafe_from, buffer->idx + 1); return_trace (false); diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/GPOS.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/GPOS.hh index 9493ec987e..f4af98b25f 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/GPOS.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/GPOS.hh @@ -156,7 +156,7 @@ GPOS::position_finish_offsets (hb_font_t *font, hb_buffer_t *buffer) { for (unsigned i = 0; i < len; i++) if (unlikely (pos[i].y_offset)) - pos[i].x_offset += _hb_roundf (font->slant_xy * pos[i].y_offset); + pos[i].x_offset += roundf (font->slant_xy * pos[i].y_offset); } } diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkMarkPosFormat1.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkMarkPosFormat1.hh index fbcebb8044..9dae5ce5da 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkMarkPosFormat1.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkMarkPosFormat1.hh @@ -100,16 +100,16 @@ struct MarkMarkPosFormat1_2 /* now we search backwards for a suitable mark glyph until a non-mark glyph */ hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input; - skippy_iter.reset (buffer->idx, 1); + skippy_iter.reset_fast (buffer->idx, 1); skippy_iter.set_lookup_props (c->lookup_props & ~(uint32_t)LookupFlag::IgnoreFlags); unsigned unsafe_from; - if (!skippy_iter.prev (&unsafe_from)) + if (unlikely (!skippy_iter.prev (&unsafe_from))) { buffer->unsafe_to_concat_from_outbuffer (unsafe_from, buffer->idx + 1); return_trace (false); } - if (!_hb_glyph_info_is_mark (&buffer->info[skippy_iter.idx])) + if (likely (!_hb_glyph_info_is_mark (&buffer->info[skippy_iter.idx]))) { buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1); return_trace (false); diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPosFormat1.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPosFormat1.hh index 4dada1c830..714b4bec72 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPosFormat1.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPosFormat1.hh @@ -110,9 +110,9 @@ struct PairPosFormat1_3 if (likely (index == NOT_COVERED)) return_trace (false); hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input; - skippy_iter.reset (buffer->idx, 1); + skippy_iter.reset_fast (buffer->idx, 1); unsigned unsafe_to; - if (!skippy_iter.next (&unsafe_to)) + if (unlikely (!skippy_iter.next (&unsafe_to))) { buffer->unsafe_to_concat (buffer->idx, unsafe_to); return_trace (false); diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPosFormat2.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPosFormat2.hh index de15a29e3c..31329dfcb5 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPosFormat2.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPosFormat2.hh @@ -50,11 +50,10 @@ struct PairPosFormat2_4 unsigned int len1 = valueFormat1.get_len (); unsigned int len2 = valueFormat2.get_len (); unsigned int stride = HBUINT16::static_size * (len1 + len2); - unsigned int record_size = valueFormat1.get_size () + valueFormat2.get_size (); unsigned int count = (unsigned int) class1Count * (unsigned int) class2Count; return_trace (c->check_range ((const void *) values, count, - record_size) && + stride) && valueFormat1.sanitize_values_stride_unsafe (c, this, &values[0], count, stride) && valueFormat2.sanitize_values_stride_unsafe (c, this, &values[len1], count, stride)); } @@ -131,26 +130,32 @@ struct PairPosFormat2_4 if (likely (index == NOT_COVERED)) return_trace (false); hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input; - skippy_iter.reset (buffer->idx, 1); + skippy_iter.reset_fast (buffer->idx, 1); unsigned unsafe_to; - if (!skippy_iter.next (&unsafe_to)) + if (unlikely (!skippy_iter.next (&unsafe_to))) { buffer->unsafe_to_concat (buffer->idx, unsafe_to); return_trace (false); } - unsigned int len1 = valueFormat1.get_len (); - unsigned int len2 = valueFormat2.get_len (); - unsigned int record_len = len1 + len2; + unsigned int klass2 = (this+classDef2).get_class (buffer->info[skippy_iter.idx].codepoint); + if (!klass2) + { + buffer->unsafe_to_concat (buffer->idx, skippy_iter.idx + 1); + return_trace (false); + } unsigned int klass1 = (this+classDef1).get_class (buffer->cur().codepoint); - unsigned int klass2 = (this+classDef2).get_class (buffer->info[skippy_iter.idx].codepoint); if (unlikely (klass1 >= class1Count || klass2 >= class2Count)) { buffer->unsafe_to_concat (buffer->idx, skippy_iter.idx + 1); return_trace (false); } + unsigned int len1 = valueFormat1.get_len (); + unsigned int len2 = valueFormat2.get_len (); + unsigned int record_len = len1 + len2; + const Value *v = &values[record_len * (klass1 * class2Count + klass2)]; bool applied_first = false, applied_second = false; @@ -164,7 +169,7 @@ struct PairPosFormat2_4 * https://github.com/harfbuzz/harfbuzz/pull/3235#issuecomment-1029814978 */ #ifndef HB_SPLIT_KERN - if (0) + if (false) #endif { if (!len2) @@ -224,8 +229,8 @@ struct PairPosFormat2_4 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]); + applied_first = len1 && valueFormat1.apply_value (c, this, v, buffer->cur_pos()); + applied_second = len2 && 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 ()) diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairSet.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairSet.hh index 147b8e00ea..9faff49909 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairSet.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairSet.hh @@ -120,8 +120,8 @@ struct PairSet 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]); + bool applied_first = len1 && valueFormats[0].apply_value (c, this, &record->values[0], buffer->cur_pos()); + bool applied_second = len2 && 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 ()) diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Ligature.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Ligature.hh index 38057cb60c..8674a52fb5 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Ligature.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Ligature.hh @@ -10,7 +10,7 @@ namespace GSUB_impl { template struct Ligature { - protected: + public: typename Types::HBGlyphID ligGlyph; /* GlyphID of ligature to substitute */ HeadlessArrayOf diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/LigatureSet.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/LigatureSet.hh index 9db25cf567..0ba262e901 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/LigatureSet.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/LigatureSet.hh @@ -72,15 +72,73 @@ struct LigatureSet ; } + static bool match_always (hb_glyph_info_t &info HB_UNUSED, unsigned value HB_UNUSED, const void *data HB_UNUSED) + { + return true; + } + bool apply (hb_ot_apply_context_t *c) const { TRACE_APPLY (this); + unsigned int num_ligs = ligature.len; + +#ifndef HB_NO_OT_LIGATURES_FAST_PATH + if (HB_OPTIMIZE_SIZE_VAL || num_ligs <= 2) +#endif + { + slow: + for (unsigned int i = 0; i < num_ligs; i++) + { + const auto &lig = this+ligature.arrayZ[i]; + if (lig.apply (c)) return_trace (true); + } + return_trace (false); + } + + /* This version is optimized for speed by matching the first component + * of the ligature here, instead of calling into the ligation code. */ + + hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input; + skippy_iter.reset (c->buffer->idx, 1); + skippy_iter.set_match_func (match_always, nullptr); + skippy_iter.set_glyph_data ((HBUINT16 *) nullptr); + unsigned unsafe_to; + hb_codepoint_t first = (unsigned) -1; + bool matched = skippy_iter.next (&unsafe_to); + if (likely (matched)) + { + first = c->buffer->info[skippy_iter.idx].codepoint; + unsafe_to = skippy_iter.idx + 1; + + if (skippy_iter.may_skip (c->buffer->info[skippy_iter.idx])) + { + /* Can't use the fast path if eg. the next char is a default-ignorable + * or other skippable. */ + goto slow; + } + } + + bool unsafe_to_concat = false; + for (unsigned int i = 0; i < num_ligs; i++) { - const auto &lig = this+ligature[i]; - if (lig.apply (c)) return_trace (true); + const auto &lig = this+ligature.arrayZ[i]; + if (unlikely (lig.component.lenP1 <= 1) || + lig.component[1] == first) + { + if (lig.apply (c)) + { + if (unsafe_to_concat) + c->buffer->unsafe_to_concat (c->buffer->idx, unsafe_to); + return_trace (true); + } + } + else if (likely (lig.component.lenP1 > 1)) + unsafe_to_concat = true; } + if (likely (unsafe_to_concat)) + c->buffer->unsafe_to_concat (c->buffer->idx, unsafe_to); return_trace (false); } diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/SingleSubst.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/SingleSubst.hh index 4529927ba6..181c9e52e5 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/SingleSubst.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/SingleSubst.hh @@ -57,7 +57,7 @@ struct SingleSubst #ifndef HB_NO_BEYOND_64K if (+ glyphs - | hb_map_retains_sorting (hb_first) + | hb_map_retains_sorting (hb_second) | hb_filter ([] (hb_codepoint_t gid) { return gid > 0xFFFFu; })) { format += 2; diff --git a/src/3rdparty/harfbuzz-ng/src/OT/glyf/CompositeGlyph.hh b/src/3rdparty/harfbuzz-ng/src/OT/glyf/CompositeGlyph.hh index 94e00d3aea..d81fadf7c8 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/glyf/CompositeGlyph.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/glyf/CompositeGlyph.hh @@ -87,19 +87,42 @@ struct CompositeGlyphRecord } } - void transform_points (contour_point_vector_t &points, + static void transform (const float (&matrix)[4], + hb_array_t points) + { + auto arrayZ = points.arrayZ; + unsigned count = points.length; + + if (matrix[0] != 1.f || matrix[1] != 0.f || + matrix[2] != 0.f || matrix[3] != 1.f) + for (unsigned i = 0; i < count; i++) + arrayZ[i].transform (matrix); + } + + static void translate (const contour_point_t &trans, + hb_array_t points) + { + auto arrayZ = points.arrayZ; + unsigned count = points.length; + + if (trans.x != 0.f || trans.y != 0.f) + for (unsigned i = 0; i < count; i++) + arrayZ[i].translate (trans); + } + + void transform_points (hb_array_t points, const float (&matrix)[4], const contour_point_t &trans) const { if (scaled_offsets ()) { - points.translate (trans); - points.transform (matrix); + translate (trans, points); + transform (matrix, points); } else { - points.transform (matrix); - points.translate (trans); + transform (matrix, points); + translate (trans, points); } } @@ -108,8 +131,9 @@ struct CompositeGlyphRecord float matrix[4]; contour_point_t trans; get_transformation (matrix, trans); + points.alloc (points.length + 4); // For phantom points if (unlikely (!points.resize (points.length + 1))) return false; - points[points.length - 1] = trans; + points.arrayZ[points.length - 1] = trans; return true; } diff --git a/src/3rdparty/harfbuzz-ng/src/OT/glyf/Glyph.hh b/src/3rdparty/harfbuzz-ng/src/OT/glyf/Glyph.hh index 9e15a6e6d0..2bd5fe8206 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/glyf/Glyph.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/glyf/Glyph.hh @@ -155,24 +155,28 @@ struct Glyph { xMin = xMax = all_points[0].x; yMin = yMax = all_points[0].y; - } - for (unsigned i = 1; i < all_points.length - 4; i++) - { - 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); + unsigned count = all_points.length - 4; + for (unsigned i = 1; i < count; i++) + { + 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, roundf (xMin), roundf (xMax), roundf (yMin), roundf (yMax), all_points); - - int rounded_xMin = roundf (xMin); - int rounded_xMax = roundf (xMax); - int rounded_yMin = roundf (yMin); - int rounded_yMax = roundf (yMax); + + // These are destined for storage in a 16 bit field to clamp the values to + // fit into a 16 bit signed integer. + int rounded_xMin = hb_clamp (roundf (xMin), -32768.0f, 32767.0f); + int rounded_xMax = hb_clamp (roundf (xMax), -32768.0f, 32767.0f); + int rounded_yMin = hb_clamp (roundf (yMin), -32768.0f, 32767.0f); + int rounded_yMax = hb_clamp (roundf (yMax), -32768.0f, 32767.0f); + + update_mtx (plan, rounded_xMin, rounded_xMax, rounded_yMin, rounded_yMax, all_points); if (type != EMPTY) { @@ -295,7 +299,7 @@ struct Glyph if (!edge_count) edge_count = &stack_edge_count; if (unlikely (*edge_count > HB_GLYF_MAX_EDGE_COUNT)) return false; (*edge_count)++; - + if (head_maxp_info) { head_maxp_info->maxComponentDepth = hb_max (head_maxp_info->maxComponentDepth, depth); @@ -305,9 +309,8 @@ struct Glyph 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; + contour_point_vector_t &points = type == SIMPLE ? all_points : stack_points; + unsigned old_length = points.length; switch (type) { case SIMPLE: @@ -315,7 +318,7 @@ struct Glyph head_maxp_info->maxContours = hb_max (head_maxp_info->maxContours, (unsigned) header->numberOfContours); if (depth > 0 && composite_contours) *composite_contours += (unsigned) header->numberOfContours; - if (unlikely (!SimpleGlyph (*header, bytes).get_contour_points (points, phantom_only))) + if (unlikely (!SimpleGlyph (*header, bytes).get_contour_points (all_points, phantom_only))) return false; break; case COMPOSITE: @@ -329,6 +332,7 @@ struct Glyph { for (auto &item : get_var_composite_iterator ()) if (unlikely (!item.get_points (points))) return false; + break; } #endif case EMPTY: @@ -367,7 +371,7 @@ struct Glyph #ifndef HB_NO_VAR glyf_accelerator.gvar->apply_deltas_to_points (gid, coords, - points.as_array ()); + points.as_array ().sub_array (old_length)); #endif // mainly used by CompositeGlyph calculating new X/Y offset value so no need to extend it @@ -381,21 +385,20 @@ struct Glyph switch (type) { case SIMPLE: if (depth == 0 && head_maxp_info) - head_maxp_info->maxPoints = hb_max (head_maxp_info->maxPoints, points.length - 4); - if (!inplace) - all_points.extend (points.as_array ()); + head_maxp_info->maxPoints = hb_max (head_maxp_info->maxPoints, all_points.length - old_length - 4); break; case COMPOSITE: { - contour_point_vector_t comp_points; unsigned int comp_index = 0; for (auto &item : get_composite_iterator ()) { - comp_points.reset (); - if (unlikely (!glyf_accelerator.glyph_for_gid (item.get_gid ()) + unsigned old_count = all_points.length; + + if (unlikely ((!phantom_only || (use_my_metrics && item.is_use_my_metrics ())) && + !glyf_accelerator.glyph_for_gid (item.get_gid ()) .get_points (font, glyf_accelerator, - comp_points, + all_points, points_with_deltas, head_maxp_info, composite_contours, @@ -407,6 +410,8 @@ struct Glyph edge_count))) return false; + auto comp_points = all_points.as_array ().sub_array (old_count); + /* 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++) @@ -429,11 +434,11 @@ struct Glyph delta.init (all_points[p1].x - comp_points[p2].x, all_points[p1].y - comp_points[p2].y); - comp_points.translate (delta); + item.translate (delta, comp_points); } } - all_points.extend (comp_points.as_array ().sub_array (0, comp_points.length - PHANTOM_COUNT)); + all_points.resize (all_points.length - PHANTOM_COUNT); if (all_points.length > HB_GLYF_MAX_POINTS) return false; @@ -453,14 +458,12 @@ struct Glyph #ifndef HB_NO_VAR_COMPOSITES case VAR_COMPOSITE: { - contour_point_vector_t comp_points; hb_array_t points_left = points.as_array (); for (auto &item : get_var_composite_iterator ()) { unsigned item_num_points = item.get_num_points (); hb_array_t record_points = points_left.sub_array (0, item_num_points); - - comp_points.reset (); + assert (record_points.length == item_num_points); auto component_coords = coords; if (item.is_reset_unspecified_axes ()) @@ -469,10 +472,13 @@ struct Glyph coord_setter_t coord_setter (component_coords); item.set_variations (coord_setter, record_points); - if (unlikely (!glyf_accelerator.glyph_for_gid (item.get_gid ()) + unsigned old_count = all_points.length; + + if (unlikely ((!phantom_only || (use_my_metrics && item.is_use_my_metrics ())) && + !glyf_accelerator.glyph_for_gid (item.get_gid ()) .get_points (font, glyf_accelerator, - comp_points, + all_points, points_with_deltas, head_maxp_info, nullptr, @@ -484,15 +490,18 @@ struct Glyph edge_count))) return false; + auto comp_points = all_points.as_array ().sub_array (old_count); + /* Apply component transformation */ - item.transform_points (record_points, comp_points); + if (comp_points) // Empty in case of phantom_only + 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)); + all_points.resize (all_points.length - PHANTOM_COUNT); if (all_points.length > HB_GLYF_MAX_POINTS) return false; @@ -512,9 +521,10 @@ struct Glyph /* Undocumented rasterizer behavior: * Shift points horizontally by the updated left side bearing */ - contour_point_t delta; - delta.init (-phantoms[PHANTOM_LEFT].x, 0.f); - if (delta.x) all_points.translate (delta); + int v = -phantoms[PHANTOM_LEFT].x; + if (v) + for (auto &point : all_points) + point.x += v; } return !all_points.in_error (); @@ -545,10 +555,11 @@ struct Glyph int num_contours = header->numberOfContours; if (unlikely (num_contours == 0)) type = EMPTY; else if (num_contours > 0) type = SIMPLE; + else if (num_contours == -1) type = COMPOSITE; #ifndef HB_NO_VAR_COMPOSITES else if (num_contours == -2) type = VAR_COMPOSITE; #endif - else type = COMPOSITE; /* negative numbers */ + else type = EMPTY; // Spec deviation; Spec says COMPOSITE, but not seen in the wild. } protected: diff --git a/src/3rdparty/harfbuzz-ng/src/OT/glyf/SimpleGlyph.hh b/src/3rdparty/harfbuzz-ng/src/OT/glyf/SimpleGlyph.hh index b6679b2dae..555bcee346 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/glyf/SimpleGlyph.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/glyf/SimpleGlyph.hh @@ -124,7 +124,7 @@ struct SimpleGlyph } static bool read_flags (const HBUINT8 *&p /* IN/OUT */, - contour_point_vector_t &points_ /* IN/OUT */, + hb_array_t points_ /* IN/OUT */, const HBUINT8 *end) { unsigned count = points_.length; @@ -146,7 +146,7 @@ struct SimpleGlyph } static bool read_points (const HBUINT8 *&p /* IN/OUT */, - contour_point_vector_t &points_ /* IN/OUT */, + hb_array_t points_ /* IN/OUT */, const HBUINT8 *end, float contour_point_t::*m, const simple_glyph_flag_t short_flag, @@ -157,7 +157,7 @@ struct SimpleGlyph unsigned count = points_.length; for (unsigned i = 0; i < count; i++) { - unsigned flag = points_[i].flag; + unsigned flag = points_.arrayZ[i].flag; if (flag & short_flag) { if (unlikely (p + 1 > end)) return false; @@ -180,18 +180,21 @@ struct SimpleGlyph return true; } - bool get_contour_points (contour_point_vector_t &points_ /* OUT */, + bool get_contour_points (contour_point_vector_t &points /* OUT */, bool phantom_only = false) const { const HBUINT16 *endPtsOfContours = &StructAfter (header); int num_contours = header.numberOfContours; - assert (num_contours); + assert (num_contours > 0); /* One extra item at the end, for the instruction-count below. */ if (unlikely (!bytes.check_range (&endPtsOfContours[num_contours]))) return false; unsigned int num_points = endPtsOfContours[num_contours - 1] + 1; - points_.alloc (num_points + 4, true); // Allocate for phantom points, to avoid a possible copy - if (!points_.resize (num_points)) return false; + unsigned old_length = points.length; + points.alloc (points.length + num_points + 4, true); // Allocate for phantom points, to avoid a possible copy + if (!points.resize (points.length + num_points, false)) return false; + auto points_ = points.as_array ().sub_array (old_length); + hb_memset (points_.arrayZ, 0, sizeof (contour_point_t) * num_points); if (phantom_only) return true; for (int i = 0; i < num_contours; i++) @@ -214,7 +217,7 @@ struct SimpleGlyph } static void encode_coord (int value, - uint8_t &flag, + unsigned &flag, const simple_glyph_flag_t short_flag, const simple_glyph_flag_t same_flag, hb_vector_t &coords /* OUT */) @@ -239,9 +242,9 @@ struct SimpleGlyph } } - static void encode_flag (uint8_t &flag, - uint8_t &repeat, - uint8_t lastflag, + static void encode_flag (unsigned flag, + unsigned &repeat, + unsigned lastflag, hb_vector_t &flags /* OUT */) { if (flag == lastflag && repeat != 255) @@ -262,7 +265,7 @@ struct SimpleGlyph else { repeat = 0; - flags.push (flag); + flags.arrayZ[flags.length++] = flag; } } @@ -282,13 +285,13 @@ struct SimpleGlyph if (unlikely (!x_coords.alloc (2*num_points, true))) return false; if (unlikely (!y_coords.alloc (2*num_points, true))) return false; - uint8_t lastflag = 255, repeat = 0; + unsigned lastflag = 255, repeat = 0; int prev_x = 0, prev_y = 0; for (unsigned i = 0; i < num_points; i++) { - uint8_t flag = all_points.arrayZ[i].flag; - flag &= FLAG_ON_CURVE + FLAG_OVERLAP_SIMPLE; + unsigned flag = all_points.arrayZ[i].flag; + flag &= FLAG_ON_CURVE | FLAG_OVERLAP_SIMPLE | FLAG_CUBIC; int cur_x = roundf (all_points.arrayZ[i].x); int cur_y = roundf (all_points.arrayZ[i].y); diff --git a/src/3rdparty/harfbuzz-ng/src/OT/glyf/VarCompositeGlyph.hh b/src/3rdparty/harfbuzz-ng/src/OT/glyf/VarCompositeGlyph.hh index 309ec473aa..6dc6fd9ded 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/glyf/VarCompositeGlyph.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/glyf/VarCompositeGlyph.hh @@ -36,24 +36,21 @@ struct VarCompositeGlyphRecord unsigned int get_size () const { + unsigned fl = flags; unsigned int size = min_size; - unsigned axis_width = (flags & AXIS_INDICES_ARE_SHORT) ? 4 : 3; + unsigned axis_width = (fl & AXIS_INDICES_ARE_SHORT) ? 4 : 3; size += numAxes * axis_width; - // gid - size += 2; - if (flags & GID_IS_24BIT) size += 1; + if (fl & GID_IS_24BIT) 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; + // 2 bytes each for the following flags + fl = fl & (HAVE_TRANSLATE_X | HAVE_TRANSLATE_Y | + HAVE_ROTATION | + HAVE_SCALE_X | HAVE_SCALE_Y | + HAVE_SKEW_X | HAVE_SKEW_Y | + HAVE_TCENTER_X | HAVE_TCENTER_Y); + size += hb_popcount (fl) * 2; return size; } @@ -66,17 +63,17 @@ struct VarCompositeGlyphRecord hb_codepoint_t get_gid () const { if (flags & GID_IS_24BIT) - return StructAfter (numAxes); + return * (const HBGlyphID24 *) &pad; else - return StructAfter (numAxes); + return * (const HBGlyphID16 *) &pad; } void set_gid (hb_codepoint_t gid) { if (flags & GID_IS_24BIT) - StructAfter (numAxes) = gid; + * (HBGlyphID24 *) &pad = gid; else - StructAfter (numAxes) = gid; + * (HBGlyphID16 *) &pad = gid; } unsigned get_numAxes () const @@ -86,26 +83,44 @@ struct VarCompositeGlyphRecord unsigned get_num_points () const { + unsigned fl = flags; 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++; + if (fl & AXES_HAVE_VARIATION) num += numAxes; + + /* Hopefully faster code, relying on the value of the flags. */ + fl = (((fl & (HAVE_TRANSLATE_Y | HAVE_SCALE_Y | HAVE_SKEW_Y | HAVE_TCENTER_Y)) >> 1) | fl) & + (HAVE_TRANSLATE_X | HAVE_ROTATION | HAVE_SCALE_X | HAVE_SKEW_X | HAVE_TCENTER_X); + num += hb_popcount (fl); + return num; + + /* Slower but more readable code. */ + if (fl & (HAVE_TRANSLATE_X | HAVE_TRANSLATE_Y)) num++; + if (fl & HAVE_ROTATION) num++; + if (fl & (HAVE_SCALE_X | HAVE_SCALE_Y)) num++; + if (fl & (HAVE_SKEW_X | HAVE_SKEW_Y)) num++; + if (fl & (HAVE_TCENTER_X | HAVE_TCENTER_Y)) num++; return num; } - void transform_points (hb_array_t record_points, - contour_point_vector_t &points) const + void transform_points (hb_array_t record_points, + hb_array_t points) const { float matrix[4]; contour_point_t trans; - get_transformation_from_points (record_points, matrix, trans); + get_transformation_from_points (record_points.arrayZ, matrix, trans); + + auto arrayZ = points.arrayZ; + unsigned count = points.length; - points.transform (matrix); - points.translate (trans); + if (matrix[0] != 1.f || matrix[1] != 0.f || + matrix[2] != 0.f || matrix[3] != 1.f) + for (unsigned i = 0; i < count; i++) + arrayZ[i].transform (matrix); + + if (trans.x != 0.f || trans.y != 0.f) + for (unsigned i = 0; i < count; i++) + arrayZ[i].translate (trans); } static inline void transform (float (&matrix)[4], contour_point_t &trans, @@ -136,26 +151,41 @@ struct VarCompositeGlyphRecord 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); + if (!translateX && !translateY) + return; + + trans.x += matrix[0] * translateX + matrix[2] * translateY; + trans.y += matrix[1] * translateX + matrix[3] * translateY; } 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); + if (scaleX == 1.f && scaleY == 1.f) + return; + + matrix[0] *= scaleX; + matrix[1] *= scaleX; + matrix[2] *= scaleY; + matrix[3] *= scaleY; } static void rotate (float (&matrix)[4], contour_point_t &trans, float rotation) { + if (!rotation) + return; + // https://github.com/fonttools/fonttools/blob/f66ee05f71c8b57b5f519ee975e95edcd1466e14/Lib/fontTools/misc/transform.py#L240 rotation = rotation * HB_PI; - float c = cosf (rotation); - float s = sinf (rotation); + float c; + float s; +#ifdef HAVE_SINCOSF + sincosf (rotation, &s, &c); +#else + c = cosf (rotation); + s = sinf (rotation); +#endif float other[6] = {c, s, -s, c, 0.f, 0.f}; transform (matrix, trans, other); } @@ -163,101 +193,100 @@ struct VarCompositeGlyphRecord static void skew (float (&matrix)[4], contour_point_t &trans, float skewX, float skewY) { + if (!skewX && !skewY) + return; + // https://github.com/fonttools/fonttools/blob/f66ee05f71c8b57b5f519ee975e95edcd1466e14/Lib/fontTools/misc/transform.py#L255 skewX = skewX * HB_PI; skewY = skewY * HB_PI; - float other[6] = {1.f, tanf (skewY), tanf (skewX), 1.f, 0.f, 0.f}; + float other[6] = {1.f, + skewY ? tanf (skewY) : 0.f, + skewX ? tanf (skewX) : 0.f, + 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 << 10); - float scaleY = 1.f * (1 << 10); - float skewX = 0.f; - float skewY = 0.f; - float tCenterX = 0.f; - float tCenterY = 0.f; - unsigned num_points = get_num_points (); - if (unlikely (!points.resize (points.length + num_points))) return false; + points.alloc (points.length + num_points + 4); // For phantom points + if (unlikely (!points.resize (points.length + num_points, false))) return false; + contour_point_t *rec_points = points.arrayZ + (points.length - num_points); + memset (rec_points, 0, num_points * sizeof (rec_points[0])); - unsigned axis_width = (flags & AXIS_INDICES_ARE_SHORT) ? 2 : 1; - unsigned axes_size = numAxes * axis_width; + unsigned fl = flags; - const F2DOT14 *q = (const F2DOT14 *) (axes_size + - (flags & GID_IS_24BIT ? 3 : 2) + - &StructAfter (numAxes)); + unsigned num_axes = numAxes; + unsigned axis_width = (fl & AXIS_INDICES_ARE_SHORT) ? 2 : 1; + unsigned axes_size = num_axes * axis_width; - hb_array_t rec_points = points.as_array ().sub_array (points.length - num_points); + const F2DOT14 *q = (const F2DOT14 *) (axes_size + + (fl & GID_IS_24BIT ? 3 : 2) + + (const HBUINT8 *) &pad); - unsigned count = numAxes; - if (flags & AXES_HAVE_VARIATION) + unsigned count = num_axes; + if (fl & AXES_HAVE_VARIATION) { for (unsigned i = 0; i < count; i++) - rec_points[i].x = q++->to_int (); - rec_points += count; + rec_points++->x = q++->to_int (); } 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 F4DOT12 *) p++)->to_int (); - if (flags & HAVE_SCALE_X) scaleX = ((const F6DOT10 *) p++)->to_int (); - if (flags & HAVE_SCALE_Y) scaleY = ((const F6DOT10 *) p++)->to_int (); - if (flags & HAVE_SKEW_X) skewX = ((const F4DOT12 *) p++)->to_int (); - if (flags & HAVE_SKEW_Y) skewY = ((const F4DOT12 *) p++)->to_int (); - 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)) + if (fl & (HAVE_TRANSLATE_X | HAVE_TRANSLATE_Y)) { - rec_points[0].x = translateX; - rec_points[0].y = translateY; + int translateX = (fl & HAVE_TRANSLATE_X) ? * (const FWORD *) p++ : 0; + int translateY = (fl & HAVE_TRANSLATE_Y) ? * (const FWORD *) p++ : 0; + rec_points->x = translateX; + rec_points->y = translateY; rec_points++; } - if (flags & HAVE_ROTATION) + if (fl & HAVE_ROTATION) { - rec_points[0].x = rotation; + int rotation = (fl & HAVE_ROTATION) ? ((const F4DOT12 *) p++)->to_int () : 0; + rec_points->x = rotation; rec_points++; } - if (flags & (HAVE_SCALE_X | HAVE_SCALE_Y)) + if (fl & (HAVE_SCALE_X | HAVE_SCALE_Y)) { - rec_points[0].x = scaleX; - rec_points[0].y = scaleY; + int scaleX = (fl & HAVE_SCALE_X) ? ((const F6DOT10 *) p++)->to_int () : 1 << 10; + int scaleY = (fl & HAVE_SCALE_Y) ? ((const F6DOT10 *) p++)->to_int () : 1 << 10; + if ((fl & UNIFORM_SCALE) && !(fl & HAVE_SCALE_Y)) + scaleY = scaleX; + rec_points->x = scaleX; + rec_points->y = scaleY; rec_points++; } - if (flags & (HAVE_SKEW_X | HAVE_SKEW_Y)) + if (fl & (HAVE_SKEW_X | HAVE_SKEW_Y)) { - rec_points[0].x = skewX; - rec_points[0].y = skewY; + int skewX = (fl & HAVE_SKEW_X) ? ((const F4DOT12 *) p++)->to_int () : 0; + int skewY = (fl & HAVE_SKEW_Y) ? ((const F4DOT12 *) p++)->to_int () : 0; + rec_points->x = skewX; + rec_points->y = skewY; rec_points++; } - if (flags & (HAVE_TCENTER_X | HAVE_TCENTER_Y)) + if (fl & (HAVE_TCENTER_X | HAVE_TCENTER_Y)) { - rec_points[0].x = tCenterX; - rec_points[0].y = tCenterY; + int tCenterX = (fl & HAVE_TCENTER_X) ? * (const FWORD *) p++ : 0; + int tCenterY = (fl & HAVE_TCENTER_Y) ? * (const FWORD *) p++ : 0; + rec_points->x = tCenterX; + rec_points->y = tCenterY; rec_points++; } - assert (!rec_points); return true; } - void get_transformation_from_points (hb_array_t rec_points, + void get_transformation_from_points (const contour_point_t *rec_points, float (&matrix)[4], contour_point_t &trans) const { - if (flags & AXES_HAVE_VARIATION) + unsigned fl = flags; + + if (fl & AXES_HAVE_VARIATION) rec_points += numAxes; matrix[0] = matrix[3] = 1.f; @@ -274,36 +303,35 @@ struct VarCompositeGlyphRecord float tCenterX = 0.f; float tCenterY = 0.f; - if (flags & (HAVE_TRANSLATE_X | HAVE_TRANSLATE_Y)) + if (fl & (HAVE_TRANSLATE_X | HAVE_TRANSLATE_Y)) { - translateX = rec_points[0].x; - translateY = rec_points[0].y; + translateX = rec_points->x; + translateY = rec_points->y; rec_points++; } - if (flags & HAVE_ROTATION) + if (fl & HAVE_ROTATION) { - rotation = rec_points[0].x / (1 << 12); + rotation = rec_points->x / (1 << 12); rec_points++; } - if (flags & (HAVE_SCALE_X | HAVE_SCALE_Y)) + if (fl & (HAVE_SCALE_X | HAVE_SCALE_Y)) { - scaleX = rec_points[0].x / (1 << 10); - scaleY = rec_points[0].y / (1 << 10); + scaleX = rec_points->x / (1 << 10); + scaleY = rec_points->y / (1 << 10); rec_points++; } - if (flags & (HAVE_SKEW_X | HAVE_SKEW_Y)) + if (fl & (HAVE_SKEW_X | HAVE_SKEW_Y)) { - skewX = rec_points[0].x / (1 << 12); - skewY = rec_points[0].y / (1 << 12); + skewX = rec_points->x / (1 << 12); + skewY = rec_points->y / (1 << 12); rec_points++; } - if (flags & (HAVE_TCENTER_X | HAVE_TCENTER_Y)) + if (fl & (HAVE_TCENTER_X | HAVE_TCENTER_Y)) { - tCenterX = rec_points[0].x; - tCenterY = rec_points[0].y; + tCenterX = rec_points->x; + tCenterY = rec_points->y; rec_points++; } - assert (!rec_points); translate (matrix, trans, translateX + tCenterX, translateY + tCenterY); rotate (matrix, trans, rotation); @@ -317,18 +345,19 @@ struct VarCompositeGlyphRecord { bool have_variations = flags & AXES_HAVE_VARIATION; unsigned axis_width = (flags & AXIS_INDICES_ARE_SHORT) ? 2 : 1; + unsigned num_axes = numAxes; const HBUINT8 *p = (const HBUINT8 *) (((HBUINT8 *) &numAxes) + numAxes.static_size + (flags & GID_IS_24BIT ? 3 : 2)); const HBUINT16 *q = (const HBUINT16 *) (((HBUINT8 *) &numAxes) + numAxes.static_size + (flags & GID_IS_24BIT ? 3 : 2)); - const F2DOT14 *a = (const F2DOT14 *) ((HBUINT8 *) (axis_width == 1 ? (p + numAxes) : (HBUINT8 *) (q + numAxes))); + const F2DOT14 *a = (const F2DOT14 *) ((HBUINT8 *) (axis_width == 1 ? (p + num_axes) : (HBUINT8 *) (q + num_axes))); - unsigned count = numAxes; + unsigned count = num_axes; 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++->to_int (); + signed v = have_variations ? rec_points.arrayZ[i].x : a++->to_int (); v = hb_clamp (v, -(1<<14), (1<<14)); setter[axis_index] = v; @@ -338,8 +367,9 @@ struct VarCompositeGlyphRecord protected: HBUINT16 flags; HBUINT8 numAxes; + HBUINT16 pad; public: - DEFINE_SIZE_MIN (3); + DEFINE_SIZE_MIN (5); }; using var_composite_iter_t = composite_iter_tmpl; diff --git a/src/3rdparty/harfbuzz-ng/src/OT/glyf/path-builder.hh b/src/3rdparty/harfbuzz-ng/src/OT/glyf/path-builder.hh index 8916241f76..f7f732d336 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/glyf/path-builder.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/glyf/path-builder.hh @@ -28,12 +28,8 @@ struct path_builder_t { return optional_point_t (x + t * (p.x - x), y + t * (p.y - y)); } } first_oncurve, first_offcurve, first_offcurve2, last_offcurve, last_offcurve2; - path_builder_t (hb_font_t *font_, hb_draw_session_t &draw_session_) - { - font = font_; - draw_session = &draw_session_; - first_oncurve = first_offcurve = first_offcurve2 = last_offcurve = last_offcurve2 = optional_point_t (); - } + path_builder_t (hb_font_t *font_, hb_draw_session_t &draw_session_) : + font (font_), draw_session (&draw_session_) {} /* based on https://github.com/RazrFalcon/ttf-parser/blob/4f32821/src/glyf.rs#L287 See also: diff --git a/src/3rdparty/harfbuzz-ng/src/graph/graph.hh b/src/3rdparty/harfbuzz-ng/src/graph/graph.hh index 38ca5db096..294a999918 100644 --- a/src/3rdparty/harfbuzz-ng/src/graph/graph.hh +++ b/src/3rdparty/harfbuzz-ng/src/graph/graph.hh @@ -173,9 +173,10 @@ struct graph_t void remove_parent (unsigned parent_index) { - for (unsigned i = 0; i < parents.length; i++) + unsigned count = parents.length; + for (unsigned i = 0; i < count; i++) { - if (parents[i] != parent_index) continue; + if (parents.arrayZ[i] != parent_index) continue; parents.remove_unordered (i); break; } @@ -183,7 +184,8 @@ struct graph_t void remove_real_link (unsigned child_index, const void* offset) { - for (unsigned i = 0; i < obj.real_links.length; i++) + unsigned count = obj.real_links.length; + for (unsigned i = 0; i < count; i++) { auto& link = obj.real_links.arrayZ[i]; if (link.objidx != child_index) @@ -199,16 +201,18 @@ struct graph_t void remap_parents (const hb_vector_t& id_map) { - for (unsigned i = 0; i < parents.length; i++) - parents[i] = id_map[parents[i]]; + unsigned count = parents.length; + for (unsigned i = 0; i < count; i++) + parents.arrayZ[i] = id_map[parents.arrayZ[i]]; } void remap_parent (unsigned old_index, unsigned new_index) { - for (unsigned i = 0; i < parents.length; i++) + unsigned count = parents.length; + for (unsigned i = 0; i < count; i++) { - if (parents[i] == old_index) - parents[i] = new_index; + if (parents.arrayZ[i] == old_index) + parents.arrayZ[i] = new_index; } } @@ -328,11 +332,12 @@ struct graph_t bool removed_nil = false; vertices_.alloc (objects.length); vertices_scratch_.alloc (objects.length); - for (unsigned i = 0; i < objects.length; i++) + unsigned count = objects.length; + for (unsigned i = 0; i < count; i++) { // 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]) + if (i == 0 && !objects.arrayZ[i]) { removed_nil = true; continue; @@ -340,9 +345,9 @@ struct graph_t vertex_t* v = vertices_.push (); if (check_success (!vertices_.in_error ())) - v->obj = *objects[i]; + v->obj = *objects.arrayZ[i]; - check_success (v->link_positions_valid (objects.length, removed_nil)); + check_success (v->link_positions_valid (count, removed_nil)); if (!removed_nil) continue; // Fix indices to account for removed nil object. @@ -579,8 +584,8 @@ struct graph_t const auto& node = object (node_idx); if (offset < node.head || offset >= node.tail) return -1; - unsigned length = node.real_links.length; - for (unsigned i = 0; i < length; i++) + unsigned count = node.real_links.length; + for (unsigned i = 0; i < count; i++) { // Use direct access for increased performance, this is a hot method. const auto& link = node.real_links.arrayZ[i]; @@ -1135,8 +1140,9 @@ struct graph_t size_t total_size_in_bytes () const { size_t total_size = 0; - for (unsigned i = 0; i < vertices_.length; i++) { - size_t size = vertices_[i].obj.tail - vertices_[i].obj.head; + unsigned count = vertices_.length; + for (unsigned i = 0; i < count; i++) { + size_t size = vertices_.arrayZ[i].obj.tail - vertices_.arrayZ[i].obj.head; total_size += size; } return total_size; @@ -1183,21 +1189,23 @@ struct graph_t { if (!parents_invalid) return; - for (unsigned i = 0; i < vertices_.length; i++) - vertices_[i].parents.reset (); + unsigned count = vertices_.length; + + for (unsigned i = 0; i < count; i++) + vertices_.arrayZ[i].parents.reset (); - for (unsigned p = 0; p < vertices_.length; p++) + for (unsigned p = 0; p < count; p++) { - for (auto& l : vertices_[p].obj.all_links ()) + for (auto& l : vertices_.arrayZ[p].obj.all_links ()) { vertices_[l.objidx].parents.push (p); } } - for (unsigned i = 0; i < vertices_.length; i++) + for (unsigned i = 0; i < count; 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 ()); + check_success (!vertices_.arrayZ[i].parents.in_error ()); parents_invalid = false; } @@ -1239,12 +1247,13 @@ struct graph_t // According to https://www3.cs.stonybrook.edu/~rezaul/papers/TR-07-54.pdf // for practical performance this is faster then using a more advanced queue // (such as a fibonacci queue) with a fast decrease priority. - for (unsigned i = 0; i < vertices_.length; i++) + unsigned count = vertices_.length; + for (unsigned i = 0; i < count; i++) { if (i == vertices_.length - 1) - vertices_[i].distance = 0; + vertices_.arrayZ[i].distance = 0; else - vertices_[i].distance = hb_int_max (int64_t); + vertices_.arrayZ[i].distance = hb_int_max (int64_t); } hb_priority_queue_t queue; @@ -1332,10 +1341,11 @@ struct graph_t void remap_all_obj_indices (const hb_vector_t& id_map, hb_vector_t* sorted_graph) const { - for (unsigned i = 0; i < sorted_graph->length; i++) + unsigned count = sorted_graph->length; + for (unsigned i = 0; i < count; i++) { (*sorted_graph)[i].remap_parents (id_map); - for (auto& link : (*sorted_graph)[i].obj.all_links_writer ()) + for (auto& link : sorted_graph->arrayZ[i].obj.all_links_writer ()) { link.objidx = id_map[link.objidx]; } diff --git a/src/3rdparty/harfbuzz-ng/src/graph/markbasepos-graph.hh b/src/3rdparty/harfbuzz-ng/src/graph/markbasepos-graph.hh index 84ef5f71b9..5e9d5aea3a 100644 --- a/src/3rdparty/harfbuzz-ng/src/graph/markbasepos-graph.hh +++ b/src/3rdparty/harfbuzz-ng/src/graph/markbasepos-graph.hh @@ -319,7 +319,8 @@ struct MarkBasePosFormat1 : public OT::Layout::GPOS_impl::MarkBasePosFormat1_2 class_to_info; unsigned class_count= classCount; - class_to_info.resize (class_count); + if (!class_to_info.resize (class_count)) + return hb_vector_t(); auto mark_array = c.graph.as_table (this_index, &markArray); if (!mark_array) return hb_vector_t (); @@ -327,6 +328,7 @@ struct MarkBasePosFormat1 : public OT::Layout::GPOS_impl::MarkBasePosFormat1_2= class_count) continue; class_to_info[klass].marks.add (mark); } @@ -335,6 +337,7 @@ struct MarkBasePosFormat1 : public OT::Layout::GPOS_impl::MarkBasePosFormat1_2= class_count) continue; class_to_info[klass].child_indices.push (link.objidx); } diff --git a/src/3rdparty/harfbuzz-ng/src/graph/serialize.hh b/src/3rdparty/harfbuzz-ng/src/graph/serialize.hh index 040fd1de5f..2e0b845baa 100644 --- a/src/3rdparty/harfbuzz-ng/src/graph/serialize.hh +++ b/src/3rdparty/harfbuzz-ng/src/graph/serialize.hh @@ -116,10 +116,10 @@ will_overflow (graph_t& graph, for (int parent_idx = vertices.length - 1; parent_idx >= 0; parent_idx--) { // Don't need to check virtual links for overflow - for (const auto& link : vertices[parent_idx].obj.real_links) + for (const auto& link : vertices.arrayZ[parent_idx].obj.real_links) { int64_t offset = compute_offset (graph, parent_idx, link); - if (is_valid_offset (offset, link)) + if (likely (is_valid_offset (offset, link))) continue; if (!overflows) return true; diff --git a/src/3rdparty/harfbuzz-ng/src/hb-aat-layout.cc b/src/3rdparty/harfbuzz-ng/src/hb-aat-layout.cc index c9147ff73b..5e4cea2224 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-aat-layout.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-aat-layout.cc @@ -55,7 +55,13 @@ AAT::hb_aat_apply_context_t::hb_aat_apply_context_t (const hb_ot_shape_plan_t *p buffer (buffer_), sanitizer (), ankr_table (&Null (AAT::ankr)), - gdef_table (face->table.GDEF->table), + gdef_table ( +#ifndef HB_NO_OT_LAYOUT + face->table.GDEF->table +#else + &Null (GDEF) +#endif + ), lookup_index (0) { sanitizer.init (blob); diff --git a/src/3rdparty/harfbuzz-ng/src/hb-algs.hh b/src/3rdparty/harfbuzz-ng/src/hb-algs.hh index 13587eac01..da383e050a 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-algs.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-algs.hh @@ -626,8 +626,10 @@ hb_popcount (T v) if (sizeof (T) == 8) { - unsigned int shift = 32; - return hb_popcount ((uint32_t) v) + hb_popcount ((uint32_t) (v >> shift)); + uint64_t y = (uint64_t) v; + y -= ((y >> 1) & 0x5555555555555555ull); + y = (y & 0x3333333333333333ull) + (y >> 2 & 0x3333333333333333ull); + return ((y + (y >> 4)) & 0xf0f0f0f0f0f0f0full) * 0x101010101010101ull >> 56; } if (sizeof (T) == 16) diff --git a/src/3rdparty/harfbuzz-ng/src/hb-array.hh b/src/3rdparty/harfbuzz-ng/src/hb-array.hh index e82c081535..1a22e15c0f 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-array.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-array.hh @@ -122,9 +122,13 @@ struct hb_array_t : hb_iter_with_fallback_t, Type&> uint32_t hash () const { - uint32_t current = 0; + // FNV-1a hash function + uint32_t current = /*cbf29ce4*/0x84222325; for (auto &v : *this) - current = current * 31 + hb_hash (v); + { + current = current ^ hb_hash (v); + current = current * 16777619; + } return current; } @@ -452,36 +456,50 @@ inline bool hb_array_t::operator == (const hb_array_t inline uint32_t hb_array_t::hash () const { - uint32_t current = 0; + // FNV-1a hash function + uint32_t current = /*cbf29ce4*/0x84222325; 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); + { + current = current ^ hb_hash ((uint32_t) ((const packed_uint32_t *) &this->arrayZ[i])->v); + current = current * 16777619; + } #endif for (; i < this->length; i++) - current = current * 31 + hb_hash (this->arrayZ[i]); + { + current = current ^ hb_hash (this->arrayZ[i]); + current = current * 16777619; + } return current; } template <> inline uint32_t hb_array_t::hash () const { - uint32_t current = 0; + // FNV-1a hash function + uint32_t current = /*cbf29ce4*/0x84222325; 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); + { + current = current ^ hb_hash ((uint32_t) ((const packed_uint32_t *) &this->arrayZ[i])->v); + current = current * 16777619; + } #endif for (; i < this->length; i++) - current = current * 31 + hb_hash (this->arrayZ[i]); + { + current = current ^ hb_hash (this->arrayZ[i]); + current = current * 16777619; + } return current; } diff --git a/src/3rdparty/harfbuzz-ng/src/hb-bit-set.hh b/src/3rdparty/harfbuzz-ng/src/hb-bit-set.hh index c30b2af7b0..d290f6114c 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-bit-set.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-bit-set.hh @@ -402,7 +402,6 @@ struct hb_bit_set_t uint32_t spm = page_map[spi].major; uint32_t lpm = larger_set.page_map[lpi].major; auto sp = page_at (spi); - auto lp = larger_set.page_at (lpi); if (spm < lpm && !sp.is_empty ()) return false; @@ -410,6 +409,7 @@ struct hb_bit_set_t if (lpm < spm) continue; + auto lp = larger_set.page_at (lpi); if (!sp.is_subset (lp)) return false; @@ -623,6 +623,7 @@ struct hb_bit_set_t *codepoint = INVALID; return false; } + last_page_lookup = i; } const auto* pages_array = pages.arrayZ; @@ -632,7 +633,6 @@ struct hb_bit_set_t if (pages_array[current.index].next (codepoint)) { *codepoint += current.major * page_t::PAGE_BITS; - last_page_lookup = i; return true; } i++; @@ -649,7 +649,6 @@ struct hb_bit_set_t return true; } } - last_page_lookup = 0; *codepoint = INVALID; return false; } @@ -921,7 +920,7 @@ struct hb_bit_set_t memmove (page_map.arrayZ + i + 1, page_map.arrayZ + i, (page_map.length - 1 - i) * page_map.item_size); - page_map[i] = map; + page_map.arrayZ[i] = map; } last_page_lookup = i; diff --git a/src/3rdparty/harfbuzz-ng/src/hb-buffer.cc b/src/3rdparty/harfbuzz-ng/src/hb-buffer.cc index 616cee807f..ace2a104fd 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-buffer.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-buffer.cc @@ -268,7 +268,7 @@ hb_buffer_t::similar (const hb_buffer_t &src) unicode = hb_unicode_funcs_reference (src.unicode); flags = src.flags; cluster_level = src.cluster_level; - replacement = src.invisible; + replacement = src.replacement; invisible = src.invisible; not_found = src.not_found; } diff --git a/src/3rdparty/harfbuzz-ng/src/hb-buffer.hh b/src/3rdparty/harfbuzz-ng/src/hb-buffer.hh index 5a43cabcb7..7a97fc7168 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-buffer.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-buffer.hh @@ -553,7 +553,7 @@ struct hb_buffer_t bool message (hb_font_t *font, const char *fmt, ...) HB_PRINTF_FUNC(3, 4) { #ifdef HB_NO_BUFFER_MESSAGE - return true; + return true; #else if (likely (!messaging ())) return true; diff --git a/src/3rdparty/harfbuzz-ng/src/hb-config.hh b/src/3rdparty/harfbuzz-ng/src/hb-config.hh index 52adaad438..26f7cba83e 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-config.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-config.hh @@ -44,14 +44,14 @@ #ifdef HB_TINY #define HB_LEAN #define HB_MINI +#define HB_OPTIMIZE_SIZE +#define HB_OPTIMIZE_SIZE_MORE +#define HB_MINIMIZE_MEMORY_USAGE #define HB_NO_MT #define HB_NO_UCD_UNASSIGNED #ifndef NDEBUG #define NDEBUG #endif -#ifndef __OPTIMIZE_SIZE__ -#define __OPTIMIZE_SIZE__ -#endif #endif #ifdef HB_LEAN @@ -97,6 +97,12 @@ #define HB_NO_BORING_EXPANSION #endif +#ifdef __OPTIMIZE_SIZE__ +#ifndef HB_OPTIMIZE_SIZE +#define HB_OPTIMIZE_SIZE +#endif +#endif + #if defined(HAVE_CONFIG_OVERRIDE_H) || defined(HB_CONFIG_OVERRIDE_H) #ifndef HB_CONFIG_OVERRIDE_H #define HB_CONFIG_OVERRIDE_H "config-override.h" @@ -107,8 +113,10 @@ /* Closure of options. */ #ifdef HB_NO_BORING_EXPANSION -#define HB_NO_BEYOND_64K #define HB_NO_AVAR2 +#define HB_NO_BEYOND_64K +#define HB_NO_CUBIC_GLYF +#define HB_NO_VAR_COMPOSITES #endif #ifdef HB_DISABLE_DEPRECATED @@ -175,21 +183,27 @@ #define HB_NO_OT_SHAPER_MYANMAR_ZAWGYI #endif -#ifdef NDEBUG -#ifndef HB_NDEBUG -#define HB_NDEBUG -#endif +#ifdef HB_OPTIMIZE_SIZE_MORE +#define HB_NO_OT_LIGATURES_FAST_PATH #endif -#ifdef __OPTIMIZE_SIZE__ -#ifndef HB_OPTIMIZE_SIZE -#define HB_OPTIMIZE_SIZE -#endif +#ifdef HB_MINIMIZE_MEMORY_USAGE +#define HB_NO_GDEF_CACHE +#define HB_NO_OT_LAYOUT_LOOKUP_CACHE +#define HB_NO_OT_FONT_ADVANCE_CACHE +#define HB_NO_OT_FONT_CMAP_CACHE #endif #ifdef HB_OPTIMIZE_SIZE -#define HB_NO_OT_LAYOUT_LOOKUP_CACHE +#define HB_OPTIMIZE_SIZE_VAL 1 +#else +#define HB_OPTIMIZE_SIZE_VAL 0 #endif +#ifdef HB_MINIMIZE_MEMORY_USAGE +#define HB_MINIMIZE_MEMORY_USAGE_VAL 1 +#else +#define HB_MINIMIZE_MEMORY_USAGE_VAL 0 +#endif #endif /* HB_CONFIG_HH */ diff --git a/src/3rdparty/harfbuzz-ng/src/hb-map.hh b/src/3rdparty/harfbuzz-ng/src/hb-map.hh index 041b8829af..c685a9a3e1 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-map.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-map.hh @@ -401,7 +401,8 @@ struct hb_hashmap_t unsigned int tombstone = (unsigned) -1; while (items[i].is_used ()) { - if (items[i].hash == hash && items[i] == key) + if ((hb_is_same (K, hb_codepoint_t) || items[i].hash == hash) && + items[i] == key) return items[i]; if (tombstone == (unsigned) -1 && items[i].is_tombstone ()) tombstone = i; diff --git a/src/3rdparty/harfbuzz-ng/src/hb-null.hh b/src/3rdparty/harfbuzz-ng/src/hb-null.hh index 0d7f4da79e..3da2d75ef5 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-null.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-null.hh @@ -37,7 +37,7 @@ /* Global nul-content Null pool. Enlarge as necessary. */ -#define HB_NULL_POOL_SIZE 448 +#define HB_NULL_POOL_SIZE 520 template struct _hb_has_min_size : hb_false_type {}; diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-cff1-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-cff1-table.hh index f461a23044..4d0a965eee 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-cff1-table.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-cff1-table.hh @@ -44,7 +44,7 @@ namespace CFF { * CFF -- Compact Font Format (CFF) * https://www.adobe.com/content/dam/acom/en/devnet/font/pdfs/5176.CFF.pdf */ -#define HB_OT_TAG_cff1 HB_TAG('C','F','F',' ') +#define HB_OT_TAG_CFF1 HB_TAG('C','F','F',' ') #define CFF_UNDEF_SID CFF_UNDEF_CODE @@ -1019,7 +1019,7 @@ using namespace CFF; struct cff1 { - static constexpr hb_tag_t tableTag = HB_OT_TAG_cff1; + static constexpr hb_tag_t tableTag = HB_OT_TAG_CFF1; bool sanitize (hb_sanitize_context_t *c) const { diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-cff2-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-cff2-table.hh index b9a8819ab8..2134d48660 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-cff2-table.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-cff2-table.hh @@ -38,7 +38,7 @@ namespace CFF { * CFF2 -- Compact Font Format (CFF) Version 2 * https://docs.microsoft.com/en-us/typography/opentype/spec/cff2 */ -#define HB_OT_TAG_cff2 HB_TAG('C','F','F','2') +#define HB_OT_TAG_CFF2 HB_TAG('C','F','F','2') typedef CFFIndex CFF2Index; template struct CFF2IndexOf : CFFIndexOf {}; @@ -379,7 +379,7 @@ using namespace CFF; struct cff2 { - static constexpr hb_tag_t tableTag = HB_OT_TAG_cff2; + static constexpr hb_tag_t tableTag = HB_OT_TAG_CFF2; bool sanitize (hb_sanitize_context_t *c) const { diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-font.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-font.cc index 06f7092a59..c89a1954a9 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-font.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-font.cc @@ -64,13 +64,17 @@ using hb_ot_font_cmap_cache_t = hb_cache_t<21, 16, 8, true>; using hb_ot_font_advance_cache_t = hb_cache_t<24, 16, 8, true>; +#ifndef HB_NO_OT_FONT_CMAP_CACHE static hb_user_data_key_t hb_ot_font_cmap_cache_user_data_key; +#endif struct hb_ot_font_t { const hb_ot_face_t *ot_face; +#ifndef HB_NO_OT_FONT_CMAP_CACHE hb_ot_font_cmap_cache_t *cmap_cache; +#endif /* h_advance caching */ mutable hb_atomic_int_t cached_coords_serial; @@ -86,6 +90,7 @@ _hb_ot_font_create (hb_font_t *font) ot_font->ot_face = &font->face->table; +#ifndef HB_NO_OT_FONT_CMAP_CACHE // retry: auto *cmap_cache = (hb_ot_font_cmap_cache_t *) hb_face_get_user_data (font->face, &hb_ot_font_cmap_cache_user_data_key); @@ -112,6 +117,7 @@ _hb_ot_font_create (hb_font_t *font) } out: ot_font->cmap_cache = cmap_cache; +#endif return ot_font; } @@ -136,7 +142,11 @@ hb_ot_get_nominal_glyph (hb_font_t *font HB_UNUSED, { const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; const hb_ot_face_t *ot_face = ot_font->ot_face; - return ot_face->cmap->get_nominal_glyph (unicode, glyph, ot_font->cmap_cache); + hb_ot_font_cmap_cache_t *cmap_cache = nullptr; +#ifndef HB_NO_OT_FONT_CMAP_CACHE + cmap_cache = ot_font->cmap_cache; +#endif + return ot_face->cmap->get_nominal_glyph (unicode, glyph, cmap_cache); } static unsigned int @@ -151,10 +161,14 @@ hb_ot_get_nominal_glyphs (hb_font_t *font HB_UNUSED, { const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; const hb_ot_face_t *ot_face = ot_font->ot_face; + hb_ot_font_cmap_cache_t *cmap_cache = nullptr; +#ifndef HB_NO_OT_FONT_CMAP_CACHE + cmap_cache = ot_font->cmap_cache; +#endif return ot_face->cmap->get_nominal_glyphs (count, first_unicode, unicode_stride, first_glyph, glyph_stride, - ot_font->cmap_cache); + cmap_cache); } static hb_bool_t @@ -167,9 +181,13 @@ hb_ot_get_variation_glyph (hb_font_t *font HB_UNUSED, { const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; const hb_ot_face_t *ot_face = ot_font->ot_face; + hb_ot_font_cmap_cache_t *cmap_cache = nullptr; +#ifndef HB_NO_OT_FONT_CMAP_CACHE + cmap_cache = ot_font->cmap_cache; +#endif return ot_face->cmap->get_variation_glyph (unicode, variation_selector, glyph, - ot_font->cmap_cache); + cmap_cache); } static void @@ -188,7 +206,7 @@ hb_ot_get_glyph_h_advances (hb_font_t* font, void* font_data, hb_position_t *orig_first_advance = first_advance; -#ifndef HB_NO_VAR +#if !defined(HB_NO_VAR) && !defined(HB_NO_OT_FONT_ADVANCE_CACHE) const OT::HVAR &HVAR = *hmtx.var_table; const OT::VariationStore &varStore = &HVAR + HVAR.varStore; OT::VariationStore::cache_t *varStore_cache = font->num_coords * count >= 128 ? varStore.create_cache () : nullptr; @@ -258,7 +276,7 @@ hb_ot_get_glyph_h_advances (hb_font_t* font, void* font_data, } } -#ifndef HB_NO_VAR +#if !defined(HB_NO_VAR) && !defined(HB_NO_OT_FONT_ADVANCE_CACHE) OT::VariationStore::destroy_cache (varStore_cache); #endif @@ -293,7 +311,7 @@ hb_ot_get_glyph_v_advances (hb_font_t* font, void* font_data, if (vmtx.has_data ()) { -#ifndef HB_NO_VAR +#if !defined(HB_NO_VAR) && !defined(HB_NO_OT_FONT_ADVANCE_CACHE) const OT::VVAR &VVAR = *vmtx.var_table; const OT::VariationStore &varStore = &VVAR + VVAR.varStore; OT::VariationStore::cache_t *varStore_cache = font->num_coords ? varStore.create_cache () : nullptr; @@ -308,7 +326,7 @@ hb_ot_get_glyph_v_advances (hb_font_t* font, void* font_data, first_advance = &StructAtOffsetUnaligned (first_advance, advance_stride); } -#ifndef HB_NO_VAR +#if !defined(HB_NO_VAR) && !defined(HB_NO_OT_FONT_ADVANCE_CACHE) OT::VariationStore::destroy_cache (varStore_cache); #endif } diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-common.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-common.hh index 52b7dc254b..36f123b559 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-common.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-common.hh @@ -189,7 +189,7 @@ struct hb_collect_variation_indices_context_t : hb_set_t *layout_variation_indices; hb_hashmap_t> *varidx_delta_map; - hb_font_t *font; + hb_vector_t *normalized_coords; const VariationStore *var_store; const hb_set_t *glyph_set; const hb_map_t *gpos_lookups; @@ -197,14 +197,14 @@ struct hb_collect_variation_indices_context_t : hb_collect_variation_indices_context_t (hb_set_t *layout_variation_indices_, hb_hashmap_t> *varidx_delta_map_, - hb_font_t *font_, + hb_vector_t *normalized_coords_, const VariationStore *var_store_, const hb_set_t *glyph_set_, const hb_map_t *gpos_lookups_, float *store_cache_) : layout_variation_indices (layout_variation_indices_), varidx_delta_map (varidx_delta_map_), - font (font_), + normalized_coords (normalized_coords_), var_store (var_store_), glyph_set (glyph_set_), gpos_lookups (gpos_lookups_), @@ -1769,6 +1769,7 @@ struct ClassDefFormat2_4 return_trace (true); } + unsigned unsorted = false; unsigned num_ranges = 1; hb_codepoint_t prev_gid = (*it).first; unsigned prev_klass = (*it).second; @@ -1789,6 +1790,10 @@ struct ClassDefFormat2_4 if (cur_gid != prev_gid + 1 || cur_klass != prev_klass) { + + if (unlikely (cur_gid < prev_gid)) + unsorted = true; + if (unlikely (!record)) break; record->last = prev_gid; num_ranges++; @@ -1804,8 +1809,14 @@ struct ClassDefFormat2_4 prev_gid = cur_gid; } + if (unlikely (c->in_error ())) return_trace (false); + if (likely (record)) record->last = prev_gid; rangeRecord.len = num_ranges; + + if (unlikely (unsorted)) + rangeRecord.as_array ().qsort (RangeRecord::cmp_range); + return_trace (true); } @@ -2097,8 +2108,15 @@ struct ClassDef #ifndef HB_NO_BEYOND_64K if (glyph_max > 0xFFFFu) - format += 2; + u.format += 2; + if (unlikely (glyph_max > 0xFFFFFFu)) +#else + if (unlikely (glyph_max > 0xFFFFu)) #endif + { + c->check_success (false, HB_SERIALIZE_ERROR_INT_OVERFLOW); + return_trace (false); + } u.format = format; @@ -3547,8 +3565,9 @@ struct VariationDevice { c->layout_variation_indices->add (varIdx); int delta = 0; - if (c->font && c->var_store) - delta = roundf (get_delta (c->font, *c->var_store, c->store_cache)); + if (c->normalized_coords && c->var_store) + delta = roundf (c->var_store->get_delta (varIdx, c->normalized_coords->arrayZ, + c->normalized_coords->length, c->store_cache)); /* set new varidx to HB_OT_LAYOUT_NO_VARIATIONS_INDEX here, will remap * varidx later*/ diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gsubgpos.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gsubgpos.hh index e1b66a199a..8e5be92d12 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gsubgpos.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gsubgpos.hh @@ -476,6 +476,7 @@ struct hb_ot_apply_context_t : void init (hb_ot_apply_context_t *c_, bool context_match = false) { c = c_; + end = c->buffer->len; match_glyph_data16 = nullptr; #ifndef HB_NO_BEYOND_64K match_glyph_data24 = nullptr; @@ -489,6 +490,7 @@ struct hb_ot_apply_context_t : matcher.set_mask (context_match ? -1 : c->lookup_mask); /* Per syllable matching is only for GSUB. */ matcher.set_per_syllable (c->table_index == 0 && c->per_syllable); + matcher.set_syllable (0); } void set_lookup_props (unsigned int lookup_props) { @@ -523,6 +525,14 @@ struct hb_ot_apply_context_t : matcher.set_syllable (start_index_ == c->buffer->idx ? c->buffer->cur().syllable () : 0); } + void reset_fast (unsigned int start_index_, + unsigned int num_items_) + { + // Doesn't set end or syllable. Used by GPOS which doesn't care / change. + idx = start_index_; + num_items = num_items_; + } + void reject () { num_items++; @@ -695,6 +705,7 @@ struct hb_ot_apply_context_t : hb_buffer_t *buffer; recurse_func_t recurse_func = nullptr; const GDEF &gdef; + const GDEF::accelerator_t &gdef_accel; const VariationStore &var_store; VariationStore::cache_t *var_store_cache; hb_set_digest_t digest; @@ -726,6 +737,13 @@ struct hb_ot_apply_context_t : *face->table.GDEF->table #else Null (GDEF) +#endif + ), + gdef_accel ( +#ifndef HB_NO_OT_LAYOUT + *face->table.GDEF +#else + Null (GDEF::accelerator_t) #endif ), var_store (gdef.get_var_store ()), @@ -754,10 +772,10 @@ struct hb_ot_apply_context_t : iter_context.init (this, true); } - void set_lookup_mask (hb_mask_t mask) { lookup_mask = mask; last_base = -1; last_base_until = 0; init_iters (); } - void set_auto_zwj (bool auto_zwj_) { auto_zwj = auto_zwj_; init_iters (); } - void set_auto_zwnj (bool auto_zwnj_) { auto_zwnj = auto_zwnj_; init_iters (); } - void set_per_syllable (bool per_syllable_) { per_syllable = per_syllable_; init_iters (); } + void set_lookup_mask (hb_mask_t mask, bool init = true) { lookup_mask = mask; last_base = -1; last_base_until = 0; if (init) init_iters (); } + void set_auto_zwj (bool auto_zwj_, bool init = true) { auto_zwj = auto_zwj_; if (init) init_iters (); } + void set_auto_zwnj (bool auto_zwnj_, bool init = true) { auto_zwnj = auto_zwnj_; if (init) init_iters (); } + void set_per_syllable (bool per_syllable_, bool init = true) { per_syllable = per_syllable_; if (init) init_iters (); } void set_random (bool random_) { random = random_; } void set_recurse_func (recurse_func_t func) { recurse_func = func; } void set_lookup_index (unsigned int lookup_index_) { lookup_index = lookup_index_; } @@ -793,7 +811,6 @@ struct hb_ot_apply_context_t : bool check_glyph_property (const hb_glyph_info_t *info, unsigned int match_props) const { - hb_codepoint_t glyph = info->codepoint; unsigned int glyph_props = _hb_glyph_info_get_glyph_props (info); /* Not covered, if, for example, glyph class is ligature and @@ -803,7 +820,7 @@ struct hb_ot_apply_context_t : return false; if (unlikely (glyph_props & HB_OT_LAYOUT_GLYPH_PROPS_MARK)) - return match_properties_mark (glyph, glyph_props, match_props); + return match_properties_mark (info->codepoint, glyph_props, match_props); return true; } @@ -836,7 +853,7 @@ struct hb_ot_apply_context_t : if (likely (has_glyph_classes)) { props &= HB_OT_LAYOUT_GLYPH_PROPS_PRESERVE; - _hb_glyph_info_set_glyph_props (&buffer->cur(), props | gdef.get_glyph_props (glyph_index)); + _hb_glyph_info_set_glyph_props (&buffer->cur(), props | gdef_accel.get_glyph_props (glyph_index)); } else if (class_guess) { @@ -884,7 +901,7 @@ struct hb_accelerate_subtables_context_t : #ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE template - static inline auto apply_cached_ (const T *obj, 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_cached (c) ) template static inline auto apply_cached_ (const T *obj, hb_ot_apply_context_t *c, hb_priority<0>) HB_RETURN (bool, obj->apply (c) ) template @@ -1241,7 +1258,6 @@ static inline bool match_input (hb_ot_apply_context_t *c, */ unsigned int total_component_count = 0; - total_component_count += _hb_glyph_info_get_lig_num_comps (&buffer->cur()); unsigned int first_lig_id = _hb_glyph_info_get_lig_id (&buffer->cur()); unsigned int first_lig_comp = _hb_glyph_info_get_lig_comp (&buffer->cur()); @@ -1252,7 +1268,6 @@ static inline bool match_input (hb_ot_apply_context_t *c, LIGBASE_MAY_SKIP } ligbase = LIGBASE_NOT_CHECKED; - match_positions[0] = buffer->idx; for (unsigned int i = 1; i < count; i++) { unsigned unsafe_to; @@ -1317,7 +1332,12 @@ static inline bool match_input (hb_ot_apply_context_t *c, *end_position = skippy_iter.idx + 1; if (p_total_component_count) + { + total_component_count += _hb_glyph_info_get_lig_num_comps (&buffer->cur()); *p_total_component_count = total_component_count; + } + + match_positions[0] = buffer->idx; return_trace (true); } @@ -2431,7 +2451,9 @@ struct ContextFormat2_5 } } - bool apply (hb_ot_apply_context_t *c, bool cached = false) const + bool apply_cached (hb_ot_apply_context_t *c) const { return _apply (c, true); } + bool apply (hb_ot_apply_context_t *c) const { return _apply (c, false); } + bool _apply (hb_ot_apply_context_t *c, bool cached) const { TRACE_APPLY (this); unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint); @@ -3534,7 +3556,9 @@ struct ChainContextFormat2_5 } } - bool apply (hb_ot_apply_context_t *c, bool cached = false) const + bool apply_cached (hb_ot_apply_context_t *c) const { return _apply (c, true); } + bool apply (hb_ot_apply_context_t *c) const { return _apply (c, false); } + bool _apply (hb_ot_apply_context_t *c, bool cached) const { TRACE_APPLY (this); unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint); diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.cc index 256a055863..c66ee8cfd0 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.cc @@ -64,8 +64,8 @@ using OT::Layout::GPOS; * @include: hb-ot.h * * Functions for querying OpenType Layout features in the font face. - * See the OpenType - * specification for details. + * See the [OpenType specification](http://www.microsoft.com/typography/otspec/) + * for details. **/ @@ -257,12 +257,13 @@ _hb_ot_layout_set_glyph_props (hb_font_t *font, { _hb_buffer_assert_gsubgpos_vars (buffer); - const OT::GDEF &gdef = *font->face->table.GDEF->table; + const auto &gdef = *font->face->table.GDEF; unsigned int count = buffer->len; + hb_glyph_info_t *info = buffer->info; for (unsigned int i = 0; i < count; i++) { - _hb_glyph_info_set_glyph_props (&buffer->info[i], gdef.get_glyph_props (buffer->info[i].codepoint)); - _hb_glyph_info_clear_lig_props (&buffer->info[i]); + _hb_glyph_info_set_glyph_props (&info[i], gdef.get_glyph_props (info[i].codepoint)); + _hb_glyph_info_clear_lig_props (&info[i]); } } @@ -1895,7 +1896,7 @@ apply_backward (OT::hb_ot_apply_context_t *c, 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, subtable_count, false); + ret |= accel.apply (c, subtable_count, false); /* The reverse lookup doesn't "advance" cursor (for good reason). */ buffer->idx--; @@ -1977,11 +1978,12 @@ inline void hb_ot_map_t::apply (const Proxy &proxy, if (accel->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_lookup_mask (lookup.mask, false); + c.set_auto_zwj (lookup.auto_zwj, false); + c.set_auto_zwnj (lookup.auto_zwnj, false); c.set_random (lookup.random); - c.set_per_syllable (lookup.per_syllable); + c.set_per_syllable (lookup.per_syllable, false); + /* apply_string's set_lookup_props initializes the iterators. */ apply_string (&c, proxy.accel.table->get_lookup (lookup_index), diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-math.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-math.cc index c515867bdf..876ad258e3 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-math.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-math.cc @@ -76,7 +76,7 @@ hb_ot_math_has_data (hb_face_t *face) * * However, if the requested constant is #HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN, * #HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN or - * #HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN, then the return value is + * #HB_OT_MATH_CONSTANT_RADICAL_DEGREE_BOTTOM_RAISE_PERCENT, then the return value is * an integer between 0 and 100 representing that percentage. * * Return value: the requested constant or zero diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-metrics.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-metrics.cc index 5b12482b97..e314d946b6 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-metrics.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-metrics.cc @@ -196,7 +196,7 @@ hb_ot_metrics_get_position (hb_font_t *font, *position *= mult; if (font->slant) - *position += _hb_roundf (mult * font->slant_xy * rise); + *position += roundf (mult * font->slant_xy * rise); } return ret; diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-normalize.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-normalize.cc index 897377aa15..69dbec0783 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-normalize.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-normalize.cc @@ -383,14 +383,15 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan, if (!all_simple && buffer->message(font, "start reorder")) { count = buffer->len; + hb_glyph_info_t *info = buffer->info; for (unsigned int i = 0; i < count; i++) { - if (_hb_glyph_info_get_modified_combining_class (&buffer->info[i]) == 0) + if (_hb_glyph_info_get_modified_combining_class (&info[i]) == 0) continue; unsigned int end; for (end = i + 1; end < count; end++) - if (_hb_glyph_info_get_modified_combining_class (&buffer->info[end]) == 0) + if (_hb_glyph_info_get_modified_combining_class (&info[end]) == 0) break; /* We are going to do a O(n^2). Only do this if the sequence is short. */ @@ -414,11 +415,13 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan, * If it did NOT, then make it skippable. * https://github.com/harfbuzz/harfbuzz/issues/554 */ - for (unsigned int i = 1; i + 1 < buffer->len; i++) - if (buffer->info[i].codepoint == 0x034Fu/*CGJ*/ && - (info_cc(buffer->info[i+1]) == 0 || info_cc(buffer->info[i-1]) <= info_cc(buffer->info[i+1]))) + unsigned count = buffer->len; + hb_glyph_info_t *info = buffer->info; + for (unsigned int i = 1; i + 1 < count; i++) + if (info[i].codepoint == 0x034Fu/*CGJ*/ && + (info_cc(info[i+1]) == 0 || info_cc(info[i-1]) <= info_cc(info[i+1]))) { - _hb_glyph_info_unhide (&buffer->info[i]); + _hb_glyph_info_unhide (&info[i]); } } diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-indic-machine.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-indic-machine.hh index 7dd47755af..353e32d32c 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-indic-machine.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-indic-machine.hh @@ -53,7 +53,7 @@ enum indic_syllable_type_t { }; -#line 54 "hb-ot-shaper-indic-machine.hh" +#line 57 "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 @@ -76,7 +76,7 @@ enum indic_syllable_type_t { #define indic_syllable_machine_ex_ZWNJ 5u -#line 75 "hb-ot-shaper-indic-machine.hh" +#line 80 "hb-ot-shaper-indic-machine.hh" static const unsigned char _indic_syllable_machine_trans_keys[] = { 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, @@ -460,7 +460,7 @@ find_syllables_indic (hb_buffer_t *buffer) int cs; hb_glyph_info_t *info = buffer->info; -#line 453 "hb-ot-shaper-indic-machine.hh" +#line 464 "hb-ot-shaper-indic-machine.hh" { cs = indic_syllable_machine_start; ts = 0; @@ -476,7 +476,7 @@ find_syllables_indic (hb_buffer_t *buffer) unsigned int syllable_serial = 1; -#line 465 "hb-ot-shaper-indic-machine.hh" +#line 480 "hb-ot-shaper-indic-machine.hh" { int _slen; int _trans; @@ -490,7 +490,7 @@ _resume: #line 1 "NONE" {ts = p;} break; -#line 477 "hb-ot-shaper-indic-machine.hh" +#line 494 "hb-ot-shaper-indic-machine.hh" } _keys = _indic_syllable_machine_trans_keys + (cs<<1); @@ -593,7 +593,7 @@ _eof_trans: #line 114 "hb-ot-shaper-indic-machine.rl" {act = 6;} break; -#line 559 "hb-ot-shaper-indic-machine.hh" +#line 597 "hb-ot-shaper-indic-machine.hh" } _again: @@ -602,7 +602,7 @@ _again: #line 1 "NONE" {ts = 0;} break; -#line 566 "hb-ot-shaper-indic-machine.hh" +#line 606 "hb-ot-shaper-indic-machine.hh" } if ( ++p != pe ) diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-var-common.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-var-common.hh index 853fe3839b..7d4bf2241c 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-var-common.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-var-common.hh @@ -270,7 +270,8 @@ struct TupleVariationHeader if (shared_tuple_active_idx) { - assert (index < shared_tuple_active_idx->length); + if (unlikely (index >= shared_tuple_active_idx->length)) + return 0.f; int v = (*shared_tuple_active_idx).arrayZ[index]; if (v != -1) { diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-var-cvar-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-var-cvar-table.hh index bdb2b6b23b..7fd0f1d79d 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-var-cvar-table.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-var-cvar-table.hh @@ -126,7 +126,6 @@ struct cvar hb_blob_destroy (cvt_prime_blob); return false; } - hb_memset (cvt_deltas.arrayZ, 0, cvt_deltas.get_size ()); if (!calculate_cvt_deltas (plan->normalized_coords.length, plan->normalized_coords.as_array (), num_cvt_item, tuple_var_data, base, cvt_deltas)) diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-var-gvar-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-var-gvar-table.hh index 4752a08fbe..ece892e1dd 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-var-gvar-table.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-var-gvar-table.hh @@ -44,8 +44,15 @@ struct contour_point_t void init (float x_ = 0.f, float y_ = 0.f, bool is_end_point_ = false) { flag = 0; x = x_; y = y_; is_end_point = is_end_point_; } + void transform (const float (&matrix)[4]) + { + float x_ = x * matrix[0] + y * matrix[2]; + y = x * matrix[1] + y * matrix[3]; + x = x_; + } void translate (const contour_point_t &p) { x += p.x; y += p.y; } + float x = 0.f; float y = 0.f; uint8_t flag = 0; @@ -63,32 +70,6 @@ struct contour_point_vector_t : hb_vector_t unsigned count = a.length; hb_memcpy (arrayZ, a.arrayZ, count * sizeof (arrayZ[0])); } - - void transform (const float (&matrix)[4]) - { - if (matrix[0] == 1.f && matrix[1] == 0.f && - matrix[2] == 0.f && matrix[3] == 1.f) - return; - auto arrayZ = this->arrayZ; - unsigned count = length; - for (unsigned i = 0; i < count; i++) - { - contour_point_t &p = arrayZ[i]; - float x_ = p.x * matrix[0] + p.y * matrix[2]; - p.y = p.x * matrix[1] + p.y * matrix[3]; - p.x = x_; - } - } - - void translate (const contour_point_t& delta) - { - if (delta.x == 0.f && delta.y == 0.f) - return; - auto arrayZ = this->arrayZ; - unsigned count = length; - for (unsigned i = 0; i < count; i++) - arrayZ[i].translate (delta); - } }; struct GlyphVariationData : TupleVariationData @@ -238,7 +219,7 @@ struct gvar int idx = -1; for (unsigned j = 0; j < axis_count; j++) { - F2DOT14 peak = tuple.arrayZ[j]; + const F2DOT14 &peak = tuple.arrayZ[j]; if (peak.to_int () != 0) { if (idx != -1) @@ -249,7 +230,7 @@ struct gvar idx = j; } } - shared_tuple_active_idx[i] = idx; + shared_tuple_active_idx.arrayZ[i] = idx; } } ~accelerator_t () { table.destroy (); } @@ -311,7 +292,7 @@ struct gvar hb_vector_t end_points; // Populated lazily unsigned num_coords = table->axisCount; - hb_array_t shared_tuples = (table+table->sharedTuples).as_array (table->sharedTupleCount * table->axisCount); + hb_array_t shared_tuples = (table+table->sharedTuples).as_array (table->sharedTupleCount * num_coords); hb_vector_t private_indices; hb_vector_t x_deltas; @@ -320,7 +301,7 @@ struct gvar do { float scalar = iterator.current_tuple->calculate_scalar (coords, num_coords, shared_tuples, - shared_tuple_active_idx.in_error () ? nullptr : &shared_tuple_active_idx); + &shared_tuple_active_idx); if (scalar == 0.f) continue; const HBUINT8 *p = iterator.get_serialized_data (); unsigned int length = iterator.current_tuple->get_data_size (); @@ -329,8 +310,9 @@ struct gvar if (!deltas) { - if (unlikely (!deltas_vec.resize (points.length))) return false; + if (unlikely (!deltas_vec.resize (points.length, false))) return false; deltas = deltas_vec.as_array (); + hb_memset (deltas.arrayZ, 0, deltas.get_size ()); // Faster than vector resize } const HBUINT8 *end = p + length; @@ -359,7 +341,8 @@ struct gvar if (flush) { - for (unsigned int i = 0; i < points.length; i++) + unsigned count = points.length; + for (unsigned int i = 0; i < count; i++) points.arrayZ[i].translate (deltas.arrayZ[i]); flush = false; @@ -367,7 +350,8 @@ struct gvar hb_memset (deltas.arrayZ, 0, deltas.get_size ()); } - if (scalar != 1.0f) + if (HB_OPTIMIZE_SIZE_VAL) + { for (unsigned int i = 0; i < num_deltas; i++) { unsigned int pt_index; @@ -383,29 +367,61 @@ struct gvar delta.x += x_deltas.arrayZ[i] * scalar; delta.y += y_deltas.arrayZ[i] * scalar; } + } else - for (unsigned int i = 0; i < num_deltas; i++) + { + /* Ouch. Four cases... for optimization. */ + if (scalar != 1.0f) { - unsigned int pt_index; if (apply_to_all) - pt_index = i; + for (unsigned int i = 0; i < num_deltas; i++) + { + unsigned int pt_index = i; + auto &delta = deltas.arrayZ[pt_index]; + delta.x += x_deltas.arrayZ[i] * scalar; + delta.y += y_deltas.arrayZ[i] * scalar; + } else - { - pt_index = indices[i]; - if (unlikely (pt_index >= deltas.length)) continue; - } - auto &delta = deltas.arrayZ[pt_index]; - delta.flag = 1; /* this point is referenced, i.e., explicit deltas specified */ - delta.x += x_deltas.arrayZ[i]; - delta.y += y_deltas.arrayZ[i]; + for (unsigned int i = 0; i < num_deltas; i++) + { + unsigned int pt_index = indices[i]; + if (unlikely (pt_index >= deltas.length)) continue; + auto &delta = deltas.arrayZ[pt_index]; + 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 + { + if (apply_to_all) + for (unsigned int i = 0; i < num_deltas; i++) + { + unsigned int pt_index = i; + auto &delta = deltas.arrayZ[pt_index]; + delta.x += x_deltas.arrayZ[i]; + delta.y += y_deltas.arrayZ[i]; + } + else + for (unsigned int i = 0; i < num_deltas; i++) + { + unsigned int pt_index = indices[i]; + if (unlikely (pt_index >= deltas.length)) continue; + auto &delta = deltas.arrayZ[pt_index]; + 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 */ if (!apply_to_all) { if (!end_points) { - for (unsigned i = 0; i < points.length; ++i) + unsigned count = points.length; + for (unsigned i = 0; i < count; ++i) if (points.arrayZ[i].is_end_point) end_points.push (i); if (unlikely (end_points.in_error ())) return false; @@ -465,8 +481,11 @@ struct gvar } while (iterator.move_to_next ()); if (flush) - for (unsigned int i = 0; i < points.length; i++) + { + unsigned count = points.length; + for (unsigned int i = 0; i < count; i++) points.arrayZ[i].translate (deltas.arrayZ[i]); + } return true; } diff --git a/src/3rdparty/harfbuzz-ng/src/hb-set-digest.hh b/src/3rdparty/harfbuzz-ng/src/hb-set-digest.hh index e8409111f2..dab713729b 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-set-digest.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-set-digest.hh @@ -45,10 +45,16 @@ * a lookup's or subtable's Coverage table(s), and then when we * want to apply the lookup or subtable to a glyph, before trying * to apply, we ask the filter if the glyph may be covered. If it's - * not, we return early. + * not, we return early. We can also match a digest against another + * digest. * - * We use these filters both at the lookup-level, and then again, - * at the subtable-level. Both have performance win. + * We use these filters at three levels: + * - If the digest for all the glyphs in the buffer as a whole + * does not match the digest for the lookup, skip the lookup. + * - For each glyph, if it doesn't match the lookup digest, + * skip it. + * - For each glyph, if it doesn't match the subtable digest, + * skip it. * * The main filter we use is a combination of three bits-pattern * filters. A bits-pattern filter checks a number of bits (5 or 6) diff --git a/src/3rdparty/harfbuzz-ng/src/hb-subset-accelerator.hh b/src/3rdparty/harfbuzz-ng/src/hb-subset-accelerator.hh index e523c25820..bb7c62d064 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-subset-accelerator.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-subset-accelerator.hh @@ -58,6 +58,8 @@ struct hb_subset_accelerator_t hb_subset_accelerator_t* accel = (hb_subset_accelerator_t*) hb_calloc (1, sizeof(hb_subset_accelerator_t)); + if (unlikely (!accel)) return accel; + new (accel) hb_subset_accelerator_t (unicode_to_gid_, gid_to_unicodes_, unicodes_, diff --git a/src/3rdparty/harfbuzz-ng/src/hb-subset-input.cc b/src/3rdparty/harfbuzz-ng/src/hb-subset-input.cc index 5f001ac251..465af50814 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-subset-input.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-subset-input.cc @@ -520,6 +520,37 @@ hb_subset_preprocess (hb_face_t *source) return new_source; } +/** + * hb_subset_input_old_to_new_glyph_mapping: + * @input: a #hb_subset_input_t object. + * + * Returns a map which can be used to provide an explicit mapping from old to new glyph + * id's in the produced subset. The caller should populate the map as desired. + * If this map is left empty then glyph ids will be automatically mapped to new + * values by the subsetter. If populated, the mapping must be unique. That + * is no two original glyph ids can be mapped to the same new id. + * Additionally, if a mapping is provided then the retain gids option cannot + * be enabled. + * + * Any glyphs that are retained in the subset which are not specified + * in this mapping will be assigned glyph ids after the highest glyph + * id in the mapping. + * + * Note: this will accept and apply non-monotonic mappings, however this + * may result in unsorted Coverage tables. Such fonts may not work for all + * use cases (for example ots will reject unsorted coverage tables). So it's + * recommended, if possible, to supply a monotonic mapping. + * + * Return value: (transfer none): pointer to the #hb_map_t of the custom glyphs ID map. + * + * Since: 7.3.0 + **/ +HB_EXTERN hb_map_t* +hb_subset_input_old_to_new_glyph_mapping (hb_subset_input_t *input) +{ + return &input->glyph_map; +} + #ifdef HB_EXPERIMENTAL_API /** * hb_subset_input_override_name_table: diff --git a/src/3rdparty/harfbuzz-ng/src/hb-subset-input.hh b/src/3rdparty/harfbuzz-ng/src/hb-subset-input.hh index 1550e8b2c3..1970f795b9 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-subset-input.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-subset-input.hh @@ -119,6 +119,7 @@ struct hb_subset_input_t bool force_long_loca = false; hb_hashmap_t axes_location; + hb_map_t glyph_map; #ifdef HB_EXPERIMENTAL_API hb_hashmap_t name_table_overrides; #endif diff --git a/src/3rdparty/harfbuzz-ng/src/hb-subset-plan-member-list.hh b/src/3rdparty/harfbuzz-ng/src/hb-subset-plan-member-list.hh new file mode 100644 index 0000000000..acf508c32d --- /dev/null +++ b/src/3rdparty/harfbuzz-ng/src/hb-subset-plan-member-list.hh @@ -0,0 +1,128 @@ +/* + * Copyright © 2018 Google, Inc. + * Copyright © 2023 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. + * + * Google Author(s): Garret Rieger, Roderick Sheeter + */ + +#ifndef HB_SUBSET_PLAN_MEMBER_LIST_HH +#define HB_SUBSET_PLAN_MEMBER_LIST_HH +#endif /* HB_SUBSET_PLAN_MEMBER_LIST_HH */ /* Dummy header guards */ + +#define E(x, y) x, y + +// For each cp that we'd like to retain maps to the corresponding gid. +HB_SUBSET_PLAN_MEMBER (hb_set_t, unicodes) +HB_SUBSET_PLAN_MEMBER (hb_sorted_vector_t E(>), unicode_to_new_gid_list) + +// name_ids we would like to retain +HB_SUBSET_PLAN_MEMBER (hb_set_t, name_ids) + +// name_languages we would like to retain +HB_SUBSET_PLAN_MEMBER (hb_set_t, name_languages) + +//layout features which will be preserved +HB_SUBSET_PLAN_MEMBER (hb_set_t, layout_features) + +// layout scripts which will be preserved. +HB_SUBSET_PLAN_MEMBER (hb_set_t, layout_scripts) + +//glyph ids requested to retain +HB_SUBSET_PLAN_MEMBER (hb_set_t, glyphs_requested) + +// Tables which should not be processed, just pass them through. +HB_SUBSET_PLAN_MEMBER (hb_set_t, no_subset_tables) + +// Tables which should be dropped. +HB_SUBSET_PLAN_MEMBER (hb_set_t, drop_tables) + +// Old -> New glyph id mapping +HB_SUBSET_PLAN_MEMBER (hb_map_t, glyph_map_gsub) + +HB_SUBSET_PLAN_MEMBER (hb_set_t, _glyphset) +HB_SUBSET_PLAN_MEMBER (hb_set_t, _glyphset_gsub) +HB_SUBSET_PLAN_MEMBER (hb_set_t, _glyphset_mathed) +HB_SUBSET_PLAN_MEMBER (hb_set_t, _glyphset_colred) + +//active lookups we'd like to retain +HB_SUBSET_PLAN_MEMBER (hb_map_t, gsub_lookups) +HB_SUBSET_PLAN_MEMBER (hb_map_t, gpos_lookups) + +//active langsys we'd like to retain +HB_SUBSET_PLAN_MEMBER (hb_hashmap_t E(>), gsub_langsys) +HB_SUBSET_PLAN_MEMBER (hb_hashmap_t E(>), gpos_langsys) + +//active features after removing redundant langsys and prune_features +HB_SUBSET_PLAN_MEMBER (hb_map_t, gsub_features) +HB_SUBSET_PLAN_MEMBER (hb_map_t, gpos_features) + +//active feature variation records/condition index with variations +HB_SUBSET_PLAN_MEMBER (hb_hashmap_t E(>), gsub_feature_record_cond_idx_map) +HB_SUBSET_PLAN_MEMBER (hb_hashmap_t E(>), gpos_feature_record_cond_idx_map) + +//feature index-> address of substituation feature table mapping with +//variations +HB_SUBSET_PLAN_MEMBER (hb_hashmap_t E(), gsub_feature_substitutes_map) +HB_SUBSET_PLAN_MEMBER (hb_hashmap_t E(), gpos_feature_substitutes_map) + +//active layers/palettes we'd like to retain +HB_SUBSET_PLAN_MEMBER (hb_map_t, colrv1_layers) +HB_SUBSET_PLAN_MEMBER (hb_map_t, colr_palettes) + +//Old layout item variation index -> (New varidx, delta) mapping +HB_SUBSET_PLAN_MEMBER (hb_hashmap_t E()>), layout_variation_idx_delta_map) + +//gdef varstore retained varidx mapping +HB_SUBSET_PLAN_MEMBER (hb_vector_t, gdef_varstore_inner_maps) + +HB_SUBSET_PLAN_MEMBER (hb_hashmap_t E(>), sanitized_table_cache) + +//normalized axes location map +HB_SUBSET_PLAN_MEMBER (hb_hashmap_t E(), axes_location) +HB_SUBSET_PLAN_MEMBER (hb_vector_t, normalized_coords) + +//user specified axes location map +HB_SUBSET_PLAN_MEMBER (hb_hashmap_t E(), user_axes_location) + +//retained old axis index -> new axis index mapping in fvar axis array +HB_SUBSET_PLAN_MEMBER (hb_map_t, axes_index_map) + +//axis_index->axis_tag mapping in fvar axis array +HB_SUBSET_PLAN_MEMBER (hb_map_t, axes_old_index_tag_map) + +//hmtx metrics map: new gid->(advance, lsb) +HB_SUBSET_PLAN_MEMBER (mutable hb_hashmap_t E()>), hmtx_map) +//vmtx metrics map: new gid->(advance, lsb) +HB_SUBSET_PLAN_MEMBER (mutable hb_hashmap_t E()>), vmtx_map) +//boundsWidth map: new gid->boundsWidth, boundWidth=xMax - xMin +HB_SUBSET_PLAN_MEMBER (mutable hb_map_t, bounds_width_map) +//boundsHeight map: new gid->boundsHeight, boundsHeight=yMax - yMin +HB_SUBSET_PLAN_MEMBER (mutable hb_map_t, bounds_height_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_SUBSET_PLAN_MEMBER (hb_hashmap_t E(), name_table_overrides) +#endif + +#undef E diff --git a/src/3rdparty/harfbuzz-ng/src/hb-subset-plan.cc b/src/3rdparty/harfbuzz-ng/src/hb-subset-plan.cc index aea886864d..791f92d02d 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-subset-plan.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-subset-plan.cc @@ -381,18 +381,10 @@ _collect_layout_variation_indices (hb_subset_plan_t* plan) const OT::VariationStore *var_store = nullptr; hb_set_t varidx_set; - hb_font_t *font = nullptr; float *store_cache = nullptr; bool collect_delta = plan->pinned_at_default ? false : true; if (collect_delta) { - if (unlikely (!plan->check_success (font = _get_hb_font_with_variations (plan)))) { - hb_font_destroy (font); - gdef.destroy (); - gpos.destroy (); - return; - } - if (gdef->has_var_store ()) { var_store = &(gdef->get_var_store ()); @@ -402,7 +394,8 @@ _collect_layout_variation_indices (hb_subset_plan_t* plan) OT::hb_collect_variation_indices_context_t c (&varidx_set, &plan->layout_variation_idx_delta_map, - font, var_store, + plan->normalized_coords ? &(plan->normalized_coords) : nullptr, + var_store, &plan->_glyphset_gsub, &plan->gpos_lookups, store_cache); @@ -411,7 +404,6 @@ _collect_layout_variation_indices (hb_subset_plan_t* plan) if (hb_ot_layout_has_positioning (plan->source)) gpos->collect_variation_indices (&c); - hb_font_destroy (font); var_store->destroy_cache (store_cache); gdef->remap_layout_variation_indices (&varidx_set, &plan->layout_variation_idx_delta_map); @@ -616,13 +608,14 @@ _glyf_add_gid_and_children (const OT::glyf_accelerator_t &glyf, int operation_count, unsigned depth = 0) { - if (unlikely (depth++ > HB_MAX_NESTING_LEVEL)) return operation_count; - if (unlikely (--operation_count < 0)) return operation_count; /* Check if is already visited */ if (gids_to_retain->has (gid)) return operation_count; gids_to_retain->add (gid); + if (unlikely (depth++ > HB_MAX_NESTING_LEVEL)) return operation_count; + if (unlikely (--operation_count < 0)) return operation_count; + for (auto &item : glyf.glyph_for_gid (gid).get_composite_iterator ()) operation_count = _glyf_add_gid_and_children (glyf, @@ -775,10 +768,11 @@ _create_glyph_map_gsub (const hb_set_t* glyph_set_gsub, ; } -static void +static bool _create_old_gid_to_new_gid_map (const hb_face_t *face, bool retain_gids, const hb_set_t *all_gids_to_retain, + const hb_map_t *requested_glyph_map, hb_map_t *glyph_map, /* OUT */ hb_map_t *reverse_glyph_map, /* OUT */ unsigned int *num_glyphs /* OUT */) @@ -787,7 +781,54 @@ _create_old_gid_to_new_gid_map (const hb_face_t *face, reverse_glyph_map->resize (pop); glyph_map->resize (pop); - if (!retain_gids) + if (*requested_glyph_map) + { + hb_set_t new_gids(requested_glyph_map->values()); + if (new_gids.get_population() != requested_glyph_map->get_population()) + { + DEBUG_MSG (SUBSET, nullptr, "The provided custom glyph mapping is not unique."); + return false; + } + + if (retain_gids) + { + DEBUG_MSG (SUBSET, nullptr, + "HB_SUBSET_FLAGS_RETAIN_GIDS cannot be set if " + "a custom glyph mapping has been provided."); + return false; + } + + hb_codepoint_t max_glyph = 0; + hb_set_t remaining; + for (auto old_gid : all_gids_to_retain->iter ()) + { + if (old_gid == 0) { + reverse_glyph_map->set(0, 0); + continue; + } + + hb_codepoint_t* new_gid; + if (!requested_glyph_map->has (old_gid, &new_gid)) + { + remaining.add(old_gid); + continue; + } + + if (*new_gid > max_glyph) + max_glyph = *new_gid; + reverse_glyph_map->set (*new_gid, old_gid); + } + + // Anything that wasn't mapped by the requested mapping should + // be placed after the requested mapping. + for (auto old_gid : remaining) + { + reverse_glyph_map->set(++max_glyph, old_gid); + } + + *num_glyphs = max_glyph + 1; + } + else if (!retain_gids) { + hb_enumerate (hb_iter (all_gids_to_retain), (hb_codepoint_t) 0) | hb_sink (reverse_glyph_map) @@ -813,6 +854,8 @@ _create_old_gid_to_new_gid_map (const hb_face_t *face, | hb_map (&hb_pair_t::reverse) | hb_sink (glyph_map) ; + + return true; } #ifndef HB_NO_VAR @@ -1002,7 +1045,6 @@ hb_subset_plan_t::hb_subset_plan_t (hb_face_t *face, if (accel) accelerator = (hb_subset_accelerator_t*) accel; - if (unlikely (in_error ())) return; @@ -1016,12 +1058,16 @@ hb_subset_plan_t::hb_subset_plan_t (hb_face_t *face, if (unlikely (in_error ())) return; - _create_old_gid_to_new_gid_map (face, - input->flags & HB_SUBSET_FLAGS_RETAIN_GIDS, - &_glyphset, - glyph_map, - reverse_glyph_map, - &_num_output_glyphs); + if (!check_success(_create_old_gid_to_new_gid_map( + face, + input->flags & HB_SUBSET_FLAGS_RETAIN_GIDS, + &_glyphset, + &input->glyph_map, + glyph_map, + reverse_glyph_map, + &_num_output_glyphs))) { + return; + } _create_glyph_map_gsub ( &_glyphset_gsub, @@ -1060,7 +1106,13 @@ hb_subset_plan_t::hb_subset_plan_t (hb_face_t *face, gid_to_unicodes, unicodes, has_seac); + + check_success (inprogress_accelerator); } + +#define HB_SUBSET_PLAN_MEMBER(Type, Name) check_success (!Name.in_error ()); +#include "hb-subset-plan-member-list.hh" +#undef HB_SUBSET_PLAN_MEMBER } /** diff --git a/src/3rdparty/harfbuzz-ng/src/hb-subset-plan.hh b/src/3rdparty/harfbuzz-ng/src/hb-subset-plan.hh index e34eeb89ae..19470ff83e 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-subset-plan.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-subset-plan.hh @@ -97,112 +97,30 @@ struct hb_subset_plan_t 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_sorted_vector_t> unicode_to_new_gid_list; - - // name_ids we would like to retain - hb_set_t name_ids; - - // name_languages we would like to retain - hb_set_t name_languages; - - //layout features which will be preserved - hb_set_t layout_features; - - // layout scripts which will be preserved. - hb_set_t layout_scripts; - - //glyph ids requested to retain - hb_set_t glyphs_requested; - - // Tables which should not be processed, just pass them through. - hb_set_t no_subset_tables; - - // Tables which should be dropped. - hb_set_t drop_tables; - // The glyph subset hb_map_t *codepoint_to_glyph; // Needs to be heap-allocated // Old -> New glyph id mapping hb_map_t *glyph_map; // Needs to be heap-allocated hb_map_t *reverse_glyph_map; // Needs to be heap-allocated - hb_map_t glyph_map_gsub; // Plan is only good for a specific source/dest so keep them with it hb_face_t *source; hb_face_t *dest; unsigned int _num_output_glyphs; - hb_set_t _glyphset; - hb_set_t _glyphset_gsub; - hb_set_t _glyphset_mathed; - hb_set_t _glyphset_colred; - - //active lookups we'd like to retain - hb_map_t gsub_lookups; - hb_map_t gpos_lookups; - - //active langsys we'd like to retain - hb_hashmap_t> gsub_langsys; - hb_hashmap_t> gpos_langsys; - - //active features after removing redundant langsys and prune_features - hb_map_t gsub_features; - hb_map_t gpos_features; - - //active feature variation records/condition index with variations - hb_hashmap_t> gsub_feature_record_cond_idx_map; - hb_hashmap_t> gpos_feature_record_cond_idx_map; - - //feature index-> address of substituation feature table mapping with - //variations - hb_hashmap_t gsub_feature_substitutes_map; - hb_hashmap_t gpos_feature_substitutes_map; - - //active layers/palettes we'd like to retain - hb_map_t colrv1_layers; - hb_map_t colr_palettes; - - //Old layout item variation index -> (New varidx, delta) mapping - hb_hashmap_t> layout_variation_idx_delta_map; - - //gdef varstore retained varidx mapping - hb_vector_t gdef_varstore_inner_maps; - - hb_hashmap_t> sanitized_table_cache; - //normalized axes location map - hb_hashmap_t axes_location; - hb_vector_t normalized_coords; - //user specified axes location map - hb_hashmap_t 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) - mutable hb_hashmap_t> hmtx_map; - //vmtx metrics map: new gid->(advance, lsb) - mutable hb_hashmap_t> vmtx_map; - //boundsWidth map: new gid->boundsWidth, boundWidth=xMax - xMin - mutable hb_map_t bounds_width_map; - //boundsHeight map: new gid->boundsHeight, boundsHeight=yMax - yMin - mutable hb_map_t bounds_height_map; +#define HB_SUBSET_PLAN_MEMBER(Type, Name) Type Name; +#include "hb-subset-plan-member-list.hh" +#undef HB_SUBSET_PLAN_MEMBER //recalculated head/maxp table info after instancing mutable head_maxp_info_t head_maxp_info; -#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 name_table_overrides; -#endif - const hb_subset_accelerator_t* accelerator; hb_subset_accelerator_t* inprogress_accelerator; diff --git a/src/3rdparty/harfbuzz-ng/src/hb-subset.cc b/src/3rdparty/harfbuzz-ng/src/hb-subset.cc index 5ea422983c..9c066e6d78 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-subset.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-subset.cc @@ -96,8 +96,8 @@ static hb_tag_t known_tables[] { HB_OT_TAG_BASE, HB_OT_TAG_CBDT, HB_OT_TAG_CBLC, - HB_OT_TAG_cff1, - HB_OT_TAG_cff2, + HB_OT_TAG_CFF1, + HB_OT_TAG_CFF2, HB_OT_TAG_cmap, HB_OT_TAG_COLR, HB_OT_TAG_CPAL, @@ -457,8 +457,8 @@ _subset_table (hb_subset_plan_t *plan, case HB_OT_TAG_MATH: return _subset (plan, buf); #ifndef HB_NO_SUBSET_CFF - case HB_OT_TAG_cff1: return _subset (plan, buf); - case HB_OT_TAG_cff2: return _subset (plan, buf); + case HB_OT_TAG_CFF1: return _subset (plan, buf); + case HB_OT_TAG_CFF2: return _subset (plan, buf); case HB_OT_TAG_VORG: return _subset (plan, buf); #endif diff --git a/src/3rdparty/harfbuzz-ng/src/hb-subset.h b/src/3rdparty/harfbuzz-ng/src/hb-subset.h index 41d9587052..6368ff93f0 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-subset.h +++ b/src/3rdparty/harfbuzz-ng/src/hb-subset.h @@ -154,6 +154,9 @@ hb_subset_input_glyph_set (hb_subset_input_t *input); HB_EXTERN hb_set_t * hb_subset_input_set (hb_subset_input_t *input, hb_subset_sets_t set_type); +HB_EXTERN hb_map_t* +hb_subset_input_old_to_new_glyph_mapping (hb_subset_input_t *input); + HB_EXTERN hb_subset_flags_t hb_subset_input_get_flags (hb_subset_input_t *input); diff --git a/src/3rdparty/harfbuzz-ng/src/hb-vector.hh b/src/3rdparty/harfbuzz-ng/src/hb-vector.hh index 58d467a405..d61ce48c01 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-vector.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-vector.hh @@ -290,13 +290,11 @@ struct hb_vector_t copy_vector (const hb_vector_t &other) { length = other.length; -#ifndef HB_OPTIMIZE_SIZE - if (sizeof (T) >= sizeof (long long)) + if (!HB_OPTIMIZE_SIZE_VAL && 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 -#include -#include -#include - -#ifdef HB_NO_OPEN -#define hb_blob_create_from_file_or_fail(x) hb_blob_get_empty () -#endif - -#if !defined(HB_NO_COLOR) && !defined(HB_NO_DRAW) -static void -svg_dump (hb_face_t *face, unsigned face_index) -{ - unsigned glyph_count = hb_face_get_glyph_count (face); - - for (unsigned glyph_id = 0; glyph_id < glyph_count; ++glyph_id) - { - hb_blob_t *blob = hb_ot_color_glyph_reference_svg (face, glyph_id); - - if (hb_blob_get_length (blob) == 0) continue; - - unsigned length; - const char *data = hb_blob_get_data (blob, &length); - - char output_path[255]; - snprintf (output_path, sizeof output_path, - "out/svg-%u-%u.svg%s", - glyph_id, - face_index, - // append "z" if the content is gzipped, https://stackoverflow.com/a/6059405 - (length > 2 && (data[0] == '\x1F') && (data[1] == '\x8B')) ? "z" : ""); - - FILE *f = fopen (output_path, "wb"); - fwrite (data, 1, length, f); - fclose (f); - - hb_blob_destroy (blob); - } -} - -/* _png API is so easy to use unlike the below code, don't get confused */ -static void -png_dump (hb_face_t *face, unsigned face_index) -{ - unsigned glyph_count = hb_face_get_glyph_count (face); - hb_font_t *font = hb_font_create (face); - - /* scans the font for strikes */ - unsigned sample_glyph_id; - /* we don't care about different strikes for different glyphs at this point */ - for (sample_glyph_id = 0; sample_glyph_id < glyph_count; ++sample_glyph_id) - { - hb_blob_t *blob = hb_ot_color_glyph_reference_png (font, sample_glyph_id); - unsigned blob_length = hb_blob_get_length (blob); - hb_blob_destroy (blob); - if (blob_length != 0) - break; - } - - unsigned upem = hb_face_get_upem (face); - unsigned blob_length = 0; - unsigned strike = 0; - for (unsigned ppem = 1; ppem < upem; ++ppem) - { - hb_font_set_ppem (font, ppem, ppem); - hb_blob_t *blob = hb_ot_color_glyph_reference_png (font, sample_glyph_id); - unsigned new_blob_length = hb_blob_get_length (blob); - hb_blob_destroy (blob); - if (new_blob_length != blob_length) - { - for (unsigned glyph_id = 0; glyph_id < glyph_count; ++glyph_id) - { - hb_blob_t *blob = hb_ot_color_glyph_reference_png (font, glyph_id); - - if (hb_blob_get_length (blob) == 0) continue; - - unsigned length; - const char *data = hb_blob_get_data (blob, &length); - - char output_path[255]; - snprintf (output_path, sizeof output_path, "out/png-%u-%u-%u.png", glyph_id, strike, face_index); - - FILE *f = fopen (output_path, "wb"); - fwrite (data, 1, length, f); - fclose (f); - - hb_blob_destroy (blob); - } - - strike++; - blob_length = new_blob_length; - } - } - - hb_font_destroy (font); -} - -struct draw_data_t -{ - FILE *f; - hb_position_t ascender; -}; - -static void -move_to (hb_draw_funcs_t *, draw_data_t *draw_data, - hb_draw_state_t *, - float to_x, float to_y, - void *) -{ - fprintf (draw_data->f, "M%g,%g", to_x, draw_data->ascender - to_y); -} - -static void -line_to (hb_draw_funcs_t *, draw_data_t *draw_data, - hb_draw_state_t *, - float to_x, float to_y, - void *) -{ - fprintf (draw_data->f, "L%g,%g", to_x, draw_data->ascender - to_y); -} - -static void -quadratic_to (hb_draw_funcs_t *, draw_data_t *draw_data, - hb_draw_state_t *, - float control_x, float control_y, - float to_x, float to_y, - void *) -{ - fprintf (draw_data->f, "Q%g,%g %g,%g", control_x, draw_data->ascender - control_y, - to_x, draw_data->ascender - to_y); -} - -static void -cubic_to (hb_draw_funcs_t *, draw_data_t *draw_data, - hb_draw_state_t *, - float control1_x, float control1_y, - float control2_x, float control2_y, - float to_x, float to_y, - void *) -{ - fprintf (draw_data->f, "C%g,%g %g,%g %g,%g", control1_x, draw_data->ascender - control1_y, - control2_x, draw_data->ascender - control2_y, - to_x, draw_data->ascender - to_y); -} - -static void -close_path (hb_draw_funcs_t *, draw_data_t *draw_data, - hb_draw_state_t *, - void *) -{ - fprintf (draw_data->f, "Z"); -} - -static void -layered_glyph_dump (hb_font_t *font, hb_draw_funcs_t *funcs, unsigned face_index) -{ - hb_face_t *face = hb_font_get_face (font); - unsigned palette_count = hb_ot_color_palette_get_count (face); - for (unsigned palette = 0; palette < palette_count; ++palette) - { - unsigned num_colors = hb_ot_color_palette_get_colors (face, palette, 0, nullptr, nullptr); - if (!num_colors) continue; - - hb_color_t *colors = (hb_color_t*) calloc (num_colors, sizeof (hb_color_t)); - hb_ot_color_palette_get_colors (face, palette, 0, &num_colors, colors); - if (!num_colors) - { - free (colors); - continue; - } - - unsigned num_glyphs = hb_face_get_glyph_count (face); - for (hb_codepoint_t gid = 0; gid < num_glyphs; ++gid) - { - unsigned num_layers = hb_ot_color_glyph_get_layers (face, gid, 0, nullptr, nullptr); - if (!num_layers) continue; - - hb_ot_color_layer_t *layers = (hb_ot_color_layer_t*) malloc (num_layers * sizeof (hb_ot_color_layer_t)); - - hb_ot_color_glyph_get_layers (face, gid, 0, &num_layers, layers); - if (num_layers) - { - hb_font_extents_t font_extents; - hb_font_get_extents_for_direction (font, HB_DIRECTION_LTR, &font_extents); - hb_glyph_extents_t extents = {0}; - if (!hb_font_get_glyph_extents (font, gid, &extents)) - { - printf ("Skip gid: %u\n", gid); - continue; - } - - char output_path[255]; - snprintf (output_path, sizeof output_path, "out/colr-%u-%u-%u.svg", gid, palette, face_index); - FILE *f = fopen (output_path, "wb"); - fprintf (f, "\n", - extents.x_bearing, 0, - extents.x_bearing + extents.width, -extents.height); - draw_data_t draw_data; - draw_data.ascender = extents.y_bearing; - draw_data.f = f; - - for (unsigned layer = 0; layer < num_layers; ++layer) - { - hb_color_t color = 0x000000FF; - if (layers[layer].color_index != 0xFFFF) - color = colors[layers[layer].color_index]; - fprintf (f, "\n"); - } - - fprintf (f, ""); - fclose (f); - } - free (layers); - } - - free (colors); - } -} - -static void -dump_glyphs (hb_font_t *font, hb_draw_funcs_t *funcs, unsigned face_index) -{ - unsigned num_glyphs = hb_face_get_glyph_count (hb_font_get_face (font)); - for (unsigned gid = 0; gid < num_glyphs; ++gid) - { - hb_font_extents_t font_extents; - hb_font_get_extents_for_direction (font, HB_DIRECTION_LTR, &font_extents); - hb_glyph_extents_t extents = {0}; - if (!hb_font_get_glyph_extents (font, gid, &extents)) - { - printf ("Skip gid: %u\n", gid); - continue; - } - - char output_path[255]; - snprintf (output_path, sizeof output_path, "out/%u-%u.svg", face_index, gid); - FILE *f = fopen (output_path, "wb"); - fprintf (f, ""); - fclose (f); - } -} - -static void -dump_glyphs (hb_blob_t *blob, const char *font_name) -{ - FILE *font_name_file = fopen ("out/.dumped_font_name", "r"); - if (font_name_file) - { - fprintf (stderr, "Purge or rename ./out folder if you like to run a glyph dump,\n" - "run it like `rm -rf out && mkdir out && src/main font-file.ttf`\n"); - return; - } - - font_name_file = fopen ("out/.dumped_font_name", "w"); - if (!font_name_file) - { - fprintf (stderr, "./out is not accessible as a folder, create it please\n"); - return; - } - fwrite (font_name, 1, strlen (font_name), font_name_file); - fclose (font_name_file); - - hb_draw_funcs_t *funcs = hb_draw_funcs_create (); - hb_draw_funcs_set_move_to_func (funcs, (hb_draw_move_to_func_t) move_to, nullptr, nullptr); - hb_draw_funcs_set_line_to_func (funcs, (hb_draw_line_to_func_t) line_to, nullptr, nullptr); - hb_draw_funcs_set_quadratic_to_func (funcs, (hb_draw_quadratic_to_func_t) quadratic_to, nullptr, nullptr); - hb_draw_funcs_set_cubic_to_func (funcs, (hb_draw_cubic_to_func_t) cubic_to, nullptr, nullptr); - hb_draw_funcs_set_close_path_func (funcs, (hb_draw_close_path_func_t) close_path, nullptr, nullptr); - - unsigned num_faces = hb_face_count (blob); - for (unsigned face_index = 0; face_index < num_faces; ++face_index) - { - hb_face_t *face = hb_face_create (blob, face_index); - hb_font_t *font = hb_font_create (face); - - if (hb_ot_color_has_png (face)) - printf ("Dumping png (CBDT/sbix)...\n"); - png_dump (face, face_index); - - if (hb_ot_color_has_svg (face)) - printf ("Dumping svg (SVG )...\n"); - svg_dump (face, face_index); - - if (hb_ot_color_has_layers (face) && hb_ot_color_has_palettes (face)) - printf ("Dumping layered color glyphs (COLR/CPAL)...\n"); - layered_glyph_dump (font, funcs, face_index); - - dump_glyphs (font, funcs, face_index); - - hb_font_destroy (font); - hb_face_destroy (face); - } - - hb_draw_funcs_destroy (funcs); -} -#endif - -#ifndef MAIN_CC_NO_PRIVATE_API -/* Only this part of this mini app uses private API */ -#include "hb-static.cc" -#include "hb-open-file.hh" -#include "hb-ot-layout-gdef-table.hh" -#include "hb-ot-layout-gsubgpos.hh" - -using namespace OT; - -static void -print_layout_info_using_private_api (hb_blob_t *blob) -{ - const char *font_data = hb_blob_get_data (blob, nullptr); - hb_blob_t *font_blob = hb_sanitize_context_t ().sanitize_blob (blob); - const OpenTypeFontFile* sanitized = font_blob->as (); - if (!font_blob->data) - { - printf ("Sanitization of the file wasn't successful. Exit"); - exit (1); - } - const OpenTypeFontFile& ot = *sanitized; - - switch (ot.get_tag ()) - { - case OpenTypeFontFile::TrueTypeTag: - printf ("OpenType font with TrueType outlines\n"); - break; - case OpenTypeFontFile::CFFTag: - printf ("OpenType font with CFF (Type1) outlines\n"); - break; - case OpenTypeFontFile::TTCTag: - printf ("TrueType Collection of OpenType fonts\n"); - break; - case OpenTypeFontFile::TrueTag: - printf ("Obsolete Apple TrueType font\n"); - break; - case OpenTypeFontFile::Typ1Tag: - printf ("Obsolete Apple Type1 font in SFNT container\n"); - break; - case OpenTypeFontFile::DFontTag: - printf ("DFont Mac Resource Fork\n"); - break; - default: - printf ("Unknown font format\n"); - break; - } - - unsigned num_faces = hb_face_count (blob); - printf ("%u font(s) found in file\n", num_faces); - for (unsigned n_font = 0; n_font < num_faces; ++n_font) - { - const OpenTypeFontFace &font = ot.get_face (n_font); - printf ("Font %u of %u:\n", n_font, num_faces); - - unsigned num_tables = font.get_table_count (); - printf (" %u table(s) found in font\n", num_tables); - for (unsigned n_table = 0; n_table < num_tables; ++n_table) - { - const OpenTypeTable &table = font.get_table (n_table); - printf (" Table %2u of %2u: %.4s (0x%08x+0x%08x)\n", n_table, num_tables, - (const char *) table.tag, - (unsigned) table.offset, - (unsigned) table.length); - - switch (table.tag) - { - - case HB_OT_TAG_GSUB: - case HB_OT_TAG_GPOS: - { - - const GSUBGPOS &g = *reinterpret_cast (font_data + table.offset); - - unsigned num_scripts = g.get_script_count (); - printf (" %u script(s) found in table\n", num_scripts); - for (unsigned n_script = 0; n_script < num_scripts; ++n_script) - { - const Script &script = g.get_script (n_script); - printf (" Script %2u of %2u: %.4s\n", n_script, num_scripts, - (const char *) g.get_script_tag (n_script)); - - if (!script.has_default_lang_sys ()) - printf (" No default language system\n"); - int num_langsys = script.get_lang_sys_count (); - printf (" %d language system(s) found in script\n", num_langsys); - for (int n_langsys = script.has_default_lang_sys () ? -1 : 0; n_langsys < num_langsys; ++n_langsys) - { - const LangSys &langsys = n_langsys == -1 - ? script.get_default_lang_sys () - : script.get_lang_sys (n_langsys); - if (n_langsys == -1) - printf (" Default Language System\n"); - else - printf (" Language System %2d of %2d: %.4s\n", n_langsys, num_langsys, - (const char *) script.get_lang_sys_tag (n_langsys)); - if (!langsys.has_required_feature ()) - printf (" No required feature\n"); - else - printf (" Required feature index: %u\n", - langsys.get_required_feature_index ()); - - unsigned num_features = langsys.get_feature_count (); - printf (" %u feature(s) found in language system\n", num_features); - for (unsigned n_feature = 0; n_feature < num_features; ++n_feature) - { - printf (" Feature index %2u of %2u: %u\n", n_feature, num_features, - langsys.get_feature_index (n_feature)); - } - } - } - - unsigned num_features = g.get_feature_count (); - printf (" %u feature(s) found in table\n", num_features); - for (unsigned n_feature = 0; n_feature < num_features; ++n_feature) - { - const Feature &feature = g.get_feature (n_feature); - unsigned num_lookups = feature.get_lookup_count (); - printf (" Feature %2u of %2u: %c%c%c%c\n", n_feature, num_features, - HB_UNTAG (g.get_feature_tag (n_feature))); - - printf (" %u lookup(s) found in feature\n", num_lookups); - for (unsigned n_lookup = 0; n_lookup < num_lookups; ++n_lookup) { - printf (" Lookup index %2u of %2u: %u\n", n_lookup, num_lookups, - feature.get_lookup_index (n_lookup)); - } - } - - unsigned num_lookups = g.get_lookup_count (); - printf (" %u lookup(s) found in table\n", num_lookups); - for (unsigned n_lookup = 0; n_lookup < num_lookups; ++n_lookup) - { - const Lookup &lookup = g.get_lookup (n_lookup); - printf (" Lookup %2u of %2u: type %u, props 0x%04X\n", n_lookup, num_lookups, - lookup.get_type (), lookup.get_props ()); - } - - } - break; - - case GDEF::tableTag: - { - - const GDEF &gdef = *reinterpret_cast (font_data + table.offset); - - printf (" Has %sglyph classes\n", - gdef.has_glyph_classes () ? "" : "no "); - printf (" Has %smark attachment types\n", - gdef.has_mark_attachment_types () ? "" : "no "); - printf (" Has %sattach list\n", - gdef.has_attach_list () ? "" : "no "); - printf (" Has %slig carets\n", - gdef.has_lig_carets () ? "" : "no "); - printf (" Has %smark glyph sets\n", - gdef.has_mark_glyph_sets () ? "" : "no "); - break; - } - } - } - } -} -/* end of private API use */ -#endif - -int -main (int argc, char **argv) -{ - if (argc != 2) - { - fprintf (stderr, "usage: %s font-file.ttf\n", argv[0]); - exit (1); - } - - hb_blob_t *blob = hb_blob_create_from_file_or_fail (argv[1]); - assert (blob); - printf ("Opened font file %s: %u bytes long\n", argv[1], hb_blob_get_length (blob)); -#ifndef MAIN_CC_NO_PRIVATE_API - print_layout_info_using_private_api (blob); -#endif -#if !defined(HB_NO_COLOR) && !defined(HB_NO_DRAW) - dump_glyphs (blob, argv[1]); -#endif - hb_blob_destroy (blob); - - return 0; -} diff --git a/src/3rdparty/harfbuzz-ng/src/test.cc b/src/3rdparty/harfbuzz-ng/src/test.cc deleted file mode 100644 index f7e4e7ecde..0000000000 --- a/src/3rdparty/harfbuzz-ng/src/test.cc +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright © 2010,2011 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): Behdad Esfahbod - */ - -#include "hb.hh" - -#ifdef HAVE_FREETYPE -#include "hb-ft.h" -#endif - -#ifdef HB_NO_OPEN -#define hb_blob_create_from_file_or_fail(x) hb_blob_get_empty () -#endif - -int -main (int argc, char **argv) -{ - if (argc != 2) { - fprintf (stderr, "usage: %s font-file.ttf\n", argv[0]); - exit (1); - } - - hb_blob_t *blob = hb_blob_create_from_file_or_fail (argv[1]); - assert (blob); - printf ("Opened font file %s: %u bytes long\n", argv[1], hb_blob_get_length (blob)); - - /* Create the face */ - hb_face_t *face = hb_face_create (blob, 0 /* first face */); - hb_blob_destroy (blob); - blob = nullptr; - unsigned int upem = hb_face_get_upem (face); - - hb_font_t *font = hb_font_create (face); - hb_font_set_scale (font, upem, upem); - -#ifdef HAVE_FREETYPE - hb_ft_font_set_funcs (font); -#endif - - hb_buffer_t *buffer = hb_buffer_create (); - - hb_buffer_add_utf8 (buffer, "\xe0\xa4\x95\xe0\xa5\x8d\xe0\xa4\xb0\xe0\xa5\x8d\xe0\xa4\x95", -1, 0, -1); - hb_buffer_guess_segment_properties (buffer); - - hb_shape (font, buffer, nullptr, 0); - - unsigned int count = hb_buffer_get_length (buffer); - hb_glyph_info_t *infos = hb_buffer_get_glyph_infos (buffer, nullptr); - hb_glyph_position_t *positions = hb_buffer_get_glyph_positions (buffer, nullptr); - - for (unsigned int i = 0; i < count; i++) - { - hb_glyph_info_t *info = &infos[i]; - hb_glyph_position_t *pos = &positions[i]; - - printf ("cluster %u glyph 0x%x at (%d,%d)+(%d,%d)\n", - info->cluster, - info->codepoint, - pos->x_offset, - pos->y_offset, - pos->x_advance, - pos->y_advance); - - } - - hb_buffer_destroy (buffer); - hb_font_destroy (font); - hb_face_destroy (face); - - return 0; -} - - -- cgit v1.2.3